diff --git a/src/translators/nodejs/pure/yarn-lock/default.nix b/src/translators/nodejs/pure/yarn-lock/default.nix index e6006fc0..ecaaa7c1 100644 --- a/src/translators/nodejs/pure/yarn-lock/default.nix +++ b/src/translators/nodejs/pure/yarn-lock/default.nix @@ -19,7 +19,16 @@ yarnLock = "${lib.elemAt inputDirectories 0}/yarn.lock"; packageJSON = b.fromJSON (b.readFile "${lib.elemAt inputDirectories 0}/package.json"); parser = import ./parser.nix { inherit lib; inherit (externals) nix-parsec;}; - parsedLock = lib.foldAttrs (n: a: n // a) {} (parser.parseLock yarnLock).value; + tryParse = parser.parseLock yarnLock; + + parsedLock = + if tryParse.type == "success" then + lib.foldAttrs (n: a: n // a) {} tryParse.value + else + let + failureOffset = tryParse.value.offset; + in + throw "parser failed at: \n${lib.substring failureOffset (failureOffset + 50) tryParse.value.str}"; nameFromLockName = lockName: let version = lib.last (lib.splitString "@" lockName); @@ -37,6 +46,12 @@ url = lib.head (lib.splitString "#" dependencyAttrs.resolved); type = "fetchurl"; } + else if lib.hasInfix "@link:" dependencyName then + { + version = dependencyAttrs.version; + path = lib.last (lib.splitString "@link:" dependencyName); + type = "path"; + } else let gitUrlInfos = lib.splitString "/" dependencyAttrs.resolved; diff --git a/src/translators/nodejs/pure/yarn-lock/parser.nix b/src/translators/nodejs/pure/yarn-lock/parser.nix index f1401e0f..7d12b03a 100644 --- a/src/translators/nodejs/pure/yarn-lock/parser.nix +++ b/src/translators/nodejs/pure/yarn-lock/parser.nix @@ -2,7 +2,7 @@ # # Load in nix repl and test, e.g.: # -# nix-repl> parseConfigFile ./yarn.lock +# nix-repl> parseLock ./yarn.lock # { type = "success"; value = ...; } { lib, nix-parsec }: @@ -13,22 +13,20 @@ rec { inherit (nix-parsec) parsec; # Skip spaces and line comments and newlines - spaceComments = nix-parsec.lexer.space - (skipWhile1 (c: c == " " || c == "\t" || c == "\n")) - (nix-parsec.lexer.skipLineComment "#") - fail; + skipEmptyLinesAndComments = + skipMany (alt + (skipWhile1 (c: c == " " || c == "\t" || c == "\n")) + (skipThen (string "#") (skipWhile (x: x != "\n"))) + ); charInsideQuotes = c: c != "\""; charOutsideQuotes = c: c != "\"" && c != "\n" && c != " " && c != "," && c != ":"; unquotedString = takeWhile1 charOutsideQuotes; newLine = string "\n"; - # use the nix-parsec quotedString quotedString = between (string "\"") (string "\"") (takeWhile1 charInsideQuotes); - # TODO add the relevant fmap to add the attributes version = skipThen (string " version ") (thenSkip quotedString newLine); - # TODO instead of nextLine use an exact count of space and newline ?:w resolved = skipThen (string " resolved ") (thenSkip quotedString newLine); integrity = skipThen (string " integrity ") (thenSkip unquotedString newLine); @@ -47,12 +45,14 @@ rec { dependencyNames = thenSkip (sepBy (alt quotedString unquotedString) (string ", ")) (string ":\n"); dependencyAttrs = bind version (parsedVersion: - bind resolved (parsedResolved: + bind (optional resolved) (parsedResolved: bind (optional integrity) (parsedIntegrity: bind (optional dependencies) (parsedDependencies: bind (optional optionalDependencies) (parsedOptionalDependencies: pure ( - { version = parsedVersion; resolved = parsedResolved; } + { version = parsedVersion; } + // + (if parsedResolved == [ ] then { } else { resolved = builtins.head parsedResolved; }) // (if parsedIntegrity == [ ] then { } else { integrity = builtins.head parsedIntegrity; }) // @@ -61,6 +61,7 @@ rec { (if parsedOptionalDependencies == [ ] then { } else { optionalDependencies = builtins.head parsedOptionalDependencies; }) ) ))))); + namesToAttrsList = namesList: dependencyAttrs: map (dependencyName: lib.nameValuePair dependencyName dependencyAttrs) namesList; group = @@ -69,7 +70,7 @@ rec { dependencyAttrs); configFile = - (skipThen spaceComments + (skipThen skipEmptyLinesAndComments (thenSkip (sepBy group newLine) eof)); parseLock = path: nix-parsec.parsec.runParser configFile (builtins.readFile path);