Merge pull request #19 from DavHau/dev

yarn-lock improvements
This commit is contained in:
DavHau 2021-10-08 12:46:33 +07:00 committed by GitHub
commit 1dc003e2e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 150 additions and 49 deletions

View File

@ -69,6 +69,7 @@
shellHook = ''
export NIX_PATH=nixpkgs=${nixpkgs}
export d2nExternalSources=${externalSourcesFor."${system}"}
'';
});
};

View File

@ -154,6 +154,23 @@ class PackageCommand(Command):
)
exit(1)
# transform flags to bool
for argName, argVal in specified_extra_args.copy().items():
if translator['specialArgs'][argName]['type'] == 'flag':
if argVal.lower() in ('yes', 'y', 'true'):
specified_extra_args[argName] = True
elif argVal.lower() in ('no', 'n', 'false'):
specified_extra_args[argName] = False
else:
print(
f"Invalid value {argVal} for argument {argName}",
file=sys.stderr
)
specified_extra_args =\
{k: (bool(v) if translator['specialArgs'][k]['type'] == 'flag' else v ) \
for k, v in specified_extra_args.items()}
# on non-interactive session, assume defaults for unspecified extra args
if not self.io.is_interactive():
specified_extra_args.update(
@ -201,6 +218,7 @@ class PackageCommand(Command):
)
# dump translator arguments to json file and execute translator
print("Translating upstream metadata")
with tempfile.NamedTemporaryFile("w") as input_json_file:
json.dump(translator_input, input_json_file, indent=2)
input_json_file.seek(0) # flushes write cache

View File

@ -1,8 +1,9 @@
{
coreutils,
lib,
callPackageDream,
pkgs,
callPackageDream,
externalSources,
externals,
dream2nixWithExternals,
@ -48,7 +49,7 @@ let
bin = pkgs.writeScriptBin "translate" ''
#!${pkgs.bash}/bin/bash
jsonInputFile=$(realpath $1)
jsonInputFile=$(${coreutils}/bin/realpath $1)
outputFile=$(${pkgs.jq}/bin/jq '.outputFile' -c -r $jsonInputFile)
nix eval --show-trace --impure --raw --expr "

View File

@ -77,7 +77,7 @@
depsExact = pdata.depsExact;
}]
# handle http(s) dependency
else
else
[rec {
name = "${pname}#${version}";
version = pdata.version;
@ -125,6 +125,15 @@
producedBy = translatorName;
mainPackage = parsed.name;
dependencyGraph =
{
"${parsed.name}" =
lib.mapAttrsToList
(pname: pdata: "${pname}#${getVersion pdata}")
(lib.filterAttrs
(pname: pdata: ! (pdata.dev or false) || dev)
parsed.dependencies);
}
//
lib.listToAttrs
(map
(dep: lib.nameValuePair dep.name dep.depsExact)

View File

@ -12,14 +12,31 @@
{
inputDirectories,
inputFiles,
# extraArgs
dev,
optional,
peer,
...
}:
let
b = builtins;
yarnLock = "${lib.elemAt inputDirectories 0}/yarn.lock";
yarnLock = utils.readTextFile "${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;
mainPackageName = packageJSON.name;
mainPackageKey = "${mainPackageName}#${packageJSON.version}";
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 50 tryParse.value.str}";
nameFromLockName = lockName:
let
version = lib.last (lib.splitString "@" lockName);
@ -30,14 +47,8 @@
name = nameFromLockName dependencyName;
in
lib.nameValuePair ("${name}#${dependencyAttrs.version}") (
if ! lib.hasInfix "@github:" dependencyName then
{
version = dependencyAttrs.version;
hash = dependencyAttrs.integrity;
url = lib.head (lib.splitString "#" dependencyAttrs.resolved);
type = "fetchurl";
}
else
if lib.hasInfix "@github:" dependencyName
|| lib.hasInfix "codeload.github.com/" dependencyAttrs.resolved then
let
gitUrlInfos = lib.splitString "/" dependencyAttrs.resolved;
in
@ -47,24 +58,75 @@
owner = lib.elemAt gitUrlInfos 3;
repo = lib.elemAt gitUrlInfos 4;
}
else if lib.hasInfix "@link:" dependencyName then
{
version = dependencyAttrs.version;
path = lib.last (lib.splitString "@link:" dependencyName);
type = "path";
}
else
{
version = dependencyAttrs.version;
hash =
if dependencyAttrs ? integrity then
dependencyAttrs.integrity
else
throw "Missing integrity for ${dependencyName}";
url = lib.head (lib.splitString "#" dependencyAttrs.resolved);
type = "fetchurl";
}
)) parsedLock;
dependencyGraph = lib.mapAttrs' (dependencyName: dependencyAttrs:
let
name = nameFromLockName dependencyName;
dependencies = dependencyAttrs.dependencies or [] ++ dependencyAttrs.optionalDependencies or [];
graph = lib.forEach dependencies (dependency:
builtins.head (
lib.mapAttrsToList (name: value:
dependencyGraph =
(lib.mapAttrs'
(dependencyName: dependencyAttrs:
let
yarnName = "${name}@${value}";
version = parsedLock."${yarnName}".version;
name = nameFromLockName dependencyName;
dependencies =
dependencyAttrs.dependencies or []
++ (lib.optionals optional (dependencyAttrs.optionalDependencies or []));
graph = lib.forEach dependencies (dependency:
builtins.head (
lib.mapAttrsToList
(name: value:
let
yarnName = "${name}@${value}";
version = parsedLock."${yarnName}".version;
in
"${name}#${version}"
)
dependency
)
);
in
"${name}#${version}"
) dependency
lib.nameValuePair ("${name}#${dependencyAttrs.version}") graph
)
);
in
lib.nameValuePair ("${name}#${dependencyAttrs.version}") graph) parsedLock;
parsedLock
)
//
{
"${mainPackageName}" =
lib.mapAttrsToList
(depName: depSemVer:
let
depYarnKey = "${depName}@${depSemVer}";
dependencyAttrs =
if ! parsedLock ? "${depYarnKey}" then
throw "Cannot find entry for top level dependency: '${depYarnKey}'"
else
parsedLock."${depYarnKey}";
in
"${depName}#${dependencyAttrs.version}"
)
(
packageJSON.dependencies or {}
//
(lib.optionalAttrs dev (packageJSON.devDependencies or {}))
//
(lib.optionalAttrs peer (packageJSON.peerDependencies or {}))
);
};
in
# TODO: produce dream lock like in /specifications/dream-lock-example.json
@ -74,7 +136,7 @@
generic = {
buildSystem = "nodejs";
producedBy = translatorName;
mainPackage = packageJSON.name;
mainPackage = mainPackageName;
inherit dependencyGraph;
sourcesCombinedHash = null;
};
@ -112,10 +174,20 @@
# String arguments contain a default value and examples. Flags do not.
specialArgs = {
# optionalDependencies = {
# description = "Whether to include optional dependencies";
# type = "flag";
# };
dev = {
description = "Whether to include development dependencies";
type = "flag";
};
optional = {
description = "Whether to include optional dependencies";
type = "flag";
};
peer = {
description = "Whether to include peer dependencies";
type = "flag";
};
};
}

View File

@ -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,8 +70,8 @@ rec {
dependencyAttrs);
configFile =
(skipThen spaceComments
(skipThen skipEmptyLinesAndComments
(thenSkip (sepBy group newLine) eof));
parseLock = path: nix-parsec.parsec.runParser configFile (builtins.readFile path);
parseLock = text: nix-parsec.parsec.runParser configFile text;
}

View File

@ -17,6 +17,8 @@ rec {
readDreamLock = callPackageDream ./readDreamLock.nix {};
readTextFile = file: lib.replaceStrings [ "\r\n" ] [ "\n" ] (b.readFile file);
isFile = path: (builtins.readDir (b.dirOf path))."${b.baseNameOf path}" == "regular";
isDir = path: (builtins.readDir (b.dirOf path))."${b.baseNameOf path}" == "directory";

View File

@ -21,8 +21,5 @@ let
dependencyGraph = lock.generic.dependencyGraph;
in
lib.recursiveUpdate
lock
{
generic.dependencyGraph."${mainPackage}" = dependencyGraph."${mainPackage}" or lib.attrNames dependencyGraph;
}
lock