packages feed

yarn-lock 0.3.1 → 0.3.2

raw patch · 5 files changed

+75/−30 lines, 5 files

Files

CHANGELOG.md view
@@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.3.2] - 2017-10-02++### Fixed+- Support parsing packages with `@` in the package name + ## [0.3.1] - 2017-08-16  ### Added
src/Data/MultiKeyedMap.hs view
@@ -23,6 +23,7 @@ , mkMKMap, fromList, toList , insert , flattenKeys, keys, values+, mapKeys ) where  import qualified Data.Map.Strict as M@@ -149,7 +150,15 @@     ins = newVal [k] v m     upd ik = MKMap { keyMap, highestIk, valMap = M.insert ik v valMap } +-- | Map function over all keys. See 'M.mapKeys'.+--+-- TODO: Might leak space if a k is mapped to an+-- already existing k', because k’s value might not be+-- referenced anymore.+mapKeys :: (Ord k') => (k -> k') -> MKMap k v -> MKMap k' v+mapKeys f MKMap{..} = MKMap { keyMap = M.mapKeys f keyMap, .. } + -- | Helper, assumes there is no such value already. -- Will leak space otherwise! --@@ -163,3 +172,4 @@         , highestIk = next         , valMap = M.insert next v valMap }   where next = succ highestIk+
src/Yarn/Lock/Parse.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE NoImplicitPrelude, GeneralizedNewtypeDeriving #-}+{-# LANGUAGE NoImplicitPrelude, GeneralizedNewtypeDeriving, OverloadedStrings #-} {-| Module : Yarn.Lock.Parse Description : Parser for yarn.lock files@@ -15,14 +15,17 @@ -- ** Parsers , packageList , packageEntry--- = internal parsers-, field, packageKeys, packageKey+-- * Internal Parsers+, field, nestedField, simpleField+, packageKeys, packageKey ) where  import Protolude hiding (try) import qualified Data.Char as Ch-import qualified Data.Text as Text+import qualified Data.Text as T import qualified Data.Map.Strict as M+import Control.Monad (fail)+ import Text.Megaparsec as MP hiding (space) import Text.Megaparsec.Text import qualified Text.Megaparsec.Lexer as MPL@@ -30,7 +33,7 @@ -- import qualified Data.MultiKeyedMap as MKM -- import Data.Proxy (Proxy(..)) -import qualified Yarn.Lock.Types as T+import qualified Yarn.Lock.Types as YLT   -- | The @yarn.lock@ format doesn’t specifically include a fixed scheme,@@ -44,7 +47,7 @@  -- | A parsed 'Package' AST has one or more keys, a position in the original files -- and a collection of fields.-type Package = T.Keyed (SourcePos, PackageFields)+type Package = YLT.Keyed (SourcePos, PackageFields)   -- | Parse a complete yarn.lock into an abstract syntax tree,@@ -67,8 +70,9 @@ --     source-map "^0.4.4" --   optionalDependencies: --     uglify-js "^2.6"+--     " -- @-packageEntry :: Parser (T.Keyed (SourcePos, PackageFields))+packageEntry :: Parser (YLT.Keyed (SourcePos, PackageFields)) packageEntry = label "package entry" $ do   pos <- getPosition   -- A package entry is a non-indented@@ -76,14 +80,14 @@             -- block that has a header of package keys             -- and an indented part that contains fields             $ indentedFieldsWithHeader packageKeys-  pure $ T.Keyed keys (pos, pkgs)+  pure $ YLT.Keyed keys (pos, pkgs)  -- | The list of PackageKeys that index the same Package -- -- @ -- align-text@^0.1.1, align-text@^0.1.3:\\n -- @-packageKeys :: Parser [T.PackageKey]+packageKeys :: Parser [YLT.PackageKey] packageKeys = label "package keys" $ do   firstEls <- many (try $ lexeme $ packageKey ":," <* char ',')   lastEl   <-                      packageKey ":"  <* char ':'@@ -92,21 +96,26 @@ -- | A packageKey is @\<package-name\>\@\<semver\>@; -- -- If the semver contains spaces, it is also quoted with @"@.-packageKey :: [Char] -> Parser T.PackageKey+packageKey :: [Char] -> Parser YLT.PackageKey packageKey separators = inString (pkgKey "\"")          -- if no string delimiters is used we need to check for the separators          -- this file format is shit :<          <|> pkgKey separators          <?> "package key"   where-    pkgKey valueChars = do-      pkgName <- someTextOf (noneOf "@") <?> "package name part of package key"-      _ <- char '@'-      semver <- (someTextOf (noneOf valueChars))-                <|> (pure Text.empty <?> "an empty semver")-                <?> "semver part of package key"-      pure $ T.PackageKey pkgName semver-+    pkgKey :: [Char] -> Parser YLT.PackageKey+    pkgKey valueChars = label "package key" $ do+      key <- someTextOf (noneOf valueChars)+      -- okay, here’s the rub:+      -- `@` is used for separation, but package names containing `@`+      -- are totally a thing. As first character, as well.+      -- As are package keys without any semver whatsoever, thus ending+      -- with `@`.+      -- Did I mention this file format is big chunks of elephant shit?+      case (\(n, v) -> (T.dropEnd 1 n, v)) $ T.breakOnEnd "@" key of+        ("", _) -> fail "packageKey: package name can not be empty"+        (n, "") -> pure $ YLT.PackageKey n ""+        (n,  v) -> pure $ YLT.PackageKey n v  -- | Either a simple or a nested field. field :: Parser (Text, Either Text PackageFields)@@ -115,20 +124,22 @@     simple = fmap Left <$> simpleField     nested = fmap Right <$> nestedField --- | A key-value pair, separated by space. The value is enclosed in "".+-- | A key-value pair, separated by space.+-- Key any value may be enclosed in "". -- Returns key and value. simpleField :: Parser (Text, Text)-simpleField = (,) <$> lexeme symbolChars+simpleField = (,) <$> lexeme (strSymbolChars <|> symbolChars)                   -- valueChars may be in Strings or maybe not >:                   -- this file format is absolute garbage                   <*> (strValueChars <|> valueChars)                   <?> "simple field"   where     valueChars, strValueChars :: Parser Text-    valueChars = someTextOf (noneOf "\n\r\"")+    valueChars = someTextOf (noneOf ("\n\r\"" :: [Char]))+    strSymbolChars = inString $ symbolChars     strValueChars = inString $ valueChars       -- as with packageKey semvers, this can be empty-      <|> (pure Text.empty <?> "an empty value field")+      <|> (pure T.empty <?> "an empty value field")  -- | Similar to a @simpleField@, but instead of a string -- we get another block with deeper indentation.@@ -162,13 +173,14 @@ symbolChars :: Parser Text symbolChars = label "key symbol" $ someTextOf $ satisfy   (\c -> Ch.isAscii c &&-     (Ch.isLower c || Ch.isUpper c || Ch.isNumber c || c `elem` "-_."))+     (Ch.isLower c || Ch.isUpper c || Ch.isNumber c || c `elem` special))+  where special = "-_.@/" :: [Char]   -- text versions of parsers & helpers  someTextOf :: Parser Char -> Parser Text-someTextOf c = Text.pack <$> some c+someTextOf c = T.pack <$> some c  -- | parse everything as inside a string inString :: Parser a -> Parser a
tests/TestParse.hs view
@@ -46,10 +46,23 @@     dependencies:       core-util-is "~1.0.0"       is.array ""-      string_decoder "~0.10.x"+      "@types/string_decoder" "~0.10.x"       johnny-dep 2.3.4   |] +nestedFieldExample :: Text+nestedFieldExample = [text|+  dependencies:+    core-util-is "~1.0.0"+    is.array ""+    "@types/string_decoder" "~0.10.x"+    johnny-dep 2.3.4+  |]++case_nestedField :: Assertion+case_nestedField = do+  void $ parseSuccess nestedField nestedFieldExample+ case_NestedPackage :: Assertion case_NestedPackage = do   assertBool "there is unicode" (all Ch.isAscii (toS nestedPackage :: [Char]))@@ -62,7 +75,9 @@         (Just (Right (PackageFields nested))) -> do           assertEqual "nested keys" 4 $ length nested           assertEqual "dep exists" (Just (Left "2.3.4"))-            $ Map.lookup "johnny-dep" nested +            $ Map.lookup "johnny-dep" nested+          assertEqual "there can be @" (Just (Left "~0.10.x"))+            $ Map.lookup "@types/string_decoder" nested  case_PackageField :: IO () case_PackageField = do@@ -81,13 +96,16 @@  case_PackageKey :: Assertion case_PackageKey = do-  let key = "foo@^1.3.4, bar@blafoo234, xnu@:\n"+  let key = "foo@^1.3.4, bar@blafoo234, xnu@, @types/foo@@:\n"   parseSuccess packageKeys key     >>= \keys -> do-      keys @=? [ PackageKey "foo" "^1.3.4"+      keys @?= [ PackageKey "foo" "^1.3.4"                , PackageKey "bar" "blafoo234"                -- yes, the version can be empty …-               , PackageKey "xnu" ""]+               , PackageKey "xnu" ""+               -- and yes, package names can contain `@`+               , PackageKey "@types/foo@" ""+               ]  parseSuccess :: Parser a -> Text -> IO a parseSuccess parser string = do
yarn-lock.cabal view
@@ -3,7 +3,7 @@ -- see: https://github.com/sol/hpack  name:           yarn-lock-version:        0.3.1+version:        0.3.2 synopsis:       Represent and parse yarn.lock files description:    Types and parser for the lock file format of the npm successor yarn. All modules should be imported qualified. category:       Data