Merge pull request #32 from DavHau/dev

conditional overrides + nodejs builder improvements
This commit is contained in:
DavHau 2021-10-22 23:15:50 +07:00 committed by GitHub
commit 2db704be87
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 237 additions and 159 deletions

View File

@ -75,6 +75,7 @@
export NIX_PATH=nixpkgs=${nixpkgs}
export d2nExternalSources=${externalSourcesFor."${system}"}
export dream2nixWithExternals=${dream2nixFor."${system}".dream2nixWithExternals}
export d2nExternalSources=$dream2nixWithExternals/external
'';
});
};

View File

@ -3,6 +3,7 @@
pkgs,
runCommand,
stdenv,
writeText,
# dream2nix inputs
builders,
@ -25,10 +26,10 @@ let
b = builtins;
applyOverrides = utils.applyOverridesToPackageArgs packageOverrides;
dreamLock = utils.readDreamLock { inherit (args) dreamLock; };
inherit (dreamLock.generic) mainPackageName mainPackageVersion;
dependencyGraph = dreamLock.generic.dependencyGraph;
standAlonePackages =
@ -51,7 +52,7 @@ let
lib.recursiveUpdate dreamLock
{
generic.mainPackagenName = name;
generic.mainPackagenVersion = Version;
generic.mainPackagenVersion = version;
# re-introduce removed dependencies
generic.dependencyGraph."${key}" =
@ -63,7 +64,7 @@ let
);
mainPackageKey =
"${dreamLock.generic.mainPackageName}#${dreamLock.generic.mainPackageVersion}";
"${mainPackageName}#${mainPackageVersion}";
nodejsVersion = dreamLock.buildSystem.nodejsVersion;
@ -76,134 +77,170 @@ let
mv node-* $out
'';
allPackages = lib.genAttrs (lib.attrNames fetchedSources) makePackage;
allPackages =
lib.genAttrs
(lib.attrNames fetchedSources)
(key:
let
split = lib.splitString "#" key;
name = b.elemAt split 0;
version = b.elemAt split 1;
in
makePackage name version);
makePackage = name: version:
let
pkgKey = "${name}#${version}";
pkg =
(stdenv.mkDerivation rec {
packageName = name;
pname = utils.sanitizeDerivationName name;
inherit version;
src = fetchedSources."${pkgKey}";
buildInputs = [ nodejs nodejs.python ];
ignoreScripts = false;
inherit nodeSources;
dependencies_json = writeText "dependencies.json"
(b.toJSON
(lib.listToAttrs
(b.map
(pKey:
let
split = lib.splitString "#" pKey;
pname = b.elemAt split 0;
version = b.elemAt split 1;
in
lib.nameValuePair pname version)
dreamLock.generic.dependencyGraph."${pkgKey}" or [])));
nodeDeps =
lib.forEach
(dependencyGraph."${pkgKey}" or [])
(depKey:
allPackages."${depKey}"
)
++
lib.forEach (dreamLock.generic.dependenciesRemoved."${pkgKey}" or [])
(removedDep: standAlonePackages."${pkgKey}");
dontUnpack = true;
installPhase = ''
runHook preInstall
nodeModules=$out/lib/node_modules
mkdir -p $nodeModules
cd $TMPDIR
unpackFile ${src}
# Make the base dir in which the target dependency resides first
mkdir -p "$(dirname "$nodeModules/${packageName}")"
# install source
if [ -f "${src}" ]
then
# Figure out what directory has been unpacked
packageDir="$(find . -maxdepth 1 -type d | tail -1)"
# Restore write permissions
find "$packageDir" -type d -exec chmod u+x {} \;
chmod -R u+w "$packageDir"
# Move the extracted tarball into the output folder
mv "$packageDir" "$nodeModules/${packageName}"
elif [ -d "${src}" ]
then
strippedName="$(stripHash ${src})"
# Restore write permissions
chmod -R u+w "$strippedName"
# Move the extracted directory into the output folder
mv "$strippedName" "$nodeModules/${packageName}"
fi
# repair 'link:' -> 'file:'
mv $nodeModules/${packageName}/package.json $nodeModules/${packageName}/package.json.old
cat $nodeModules/${packageName}/package.json.old | sed 's!link:!file\:!g' > $nodeModules/${packageName}/package.json
rm $nodeModules/${packageName}/package.json.old
# symlink dependency packages into node_modules
for dep in $nodeDeps; do
if [ -e $dep/lib/node_modules ]; then
for module in $(ls $dep/lib/node_modules); do
if [[ $module == @* ]]; then
for submodule in $(ls $dep/lib/node_modules/$module); do
mkdir -p $nodeModules/${packageName}/node_modules/$module
echo "ln -s $dep/lib/node_modules/$module/$submodule $nodeModules/${packageName}/node_modules/$module/$submodule"
ln -s $dep/lib/node_modules/$module/$submodule $nodeModules/${packageName}/node_modules/$module/$submodule
done
else
mkdir -p $nodeModules/${packageName}/node_modules/
echo "ln -s $dep/lib/node_modules/$module $nodeModules/${packageName}/node_modules/$module"
ln -s $dep/lib/node_modules/$module $nodeModules/${packageName}/node_modules/$module
fi
done
fi
done
cd "$nodeModules/${packageName}"
# fix package.json malformed dependency versions
python ${./fix-package-lock.py} $dependencies_json package.json
export HOME=$TMPDIR
flags=("--offline" "--production" "--nodedir=$nodeSources")
if [ -n "$ignoreScripts" ]; then
flags+=("--ignore-scripts")
fi
npm "''${flags[@]}" install
# Create symlink to the deployed executable folder, if applicable
if [ -d "$nodeModules/.bin" ]
then
ln -s $nodeModules/.bin $out/bin
fi
# Create symlinks to the deployed manual page folders, if applicable
if [ -d "$nodeModules/${packageName}/man" ]
then
mkdir -p $out/share
for dir in "$nodeModules/${packageName}/man/"*
do
mkdir -p $out/share/man/$(basename "$dir")
for page in "$dir"/*
do
ln -s $page $out/share/man/$(basename "$dir")
done
done
fi
runHook postInstall
'';
});
in
standAlonePackages."${name}#${version}"
or
(stdenv.mkDerivation (applyOverrides rec {
(utils.applyOverridesToPackage packageOverrides pkg name);
packageName = name;
pname = lib.straings.sanitizeDerivationName name;
inherit version;
src = fetchedSources."${pkgKey}";
buildInputs = [ nodejs ];
nodeDeps =
lib.forEach
(dependencyGraph."${pkgKey}" or [])
(depKey:
allPackages."${depKey}"
)
++
lib.forEach (dreamLock.generic.dependenciesRemoved."${pkgKey}" or [])
(removedDep: standAlonePackages."${pkgKey}");
dontUnpack = true;
installPhase = ''
runHook preInstall
nodeModules=$out/lib/node_modules
mkdir -p $nodeModules
cd $TMPDIR
unpackFile ${src}
# Make the base dir in which the target dependency resides first
mkdir -p "$(dirname "$nodeModules/${packageName}")"
# install source
if [ -f "${src}" ]
then
# Figure out what directory has been unpacked
packageDir="$(find . -maxdepth 1 -type d | tail -1)"
# Restore write permissions
find "$packageDir" -type d -exec chmod u+x {} \;
chmod -R u+w "$packageDir"
# Move the extracted tarball into the output folder
mv "$packageDir" "$nodeModules/${packageName}"
elif [ -d "${src}" ]
then
strippedName="$(stripHash ${src})"
# Restore write permissions
chmod -R u+w "$strippedName"
# Move the extracted directory into the output folder
mv "$strippedName" "$nodeModules/${packageName}"
fi
# repair 'link:' -> 'file:'
mv $nodeModules/${packageName}/package.json $nodeModules/${packageName}/package.json.old
cat $nodeModules/${packageName}/package.json.old | sed 's!link:!file\:!g' > $nodeModules/${packageName}/package.json
rm $nodeModules/${packageName}/package.json.old
# symlink dependency packages into node_modules
for dep in $nodeDeps; do
if [ -e $dep/lib/node_modules ]; then
for module in $(ls $dep/lib/node_modules); do
if [[ $module == @* ]]; then
for submodule in $(ls $dep/lib/node_modules/$module); do
mkdir -p $nodeModules/${packageName}/node_modules/$module
echo "ln -s $dep/lib/node_modules/$module/$submodule $nodeModules/${packageName}/node_modules/$module/$submodule"
ln -s $dep/lib/node_modules/$module/$submodule $nodeModules/${packageName}/node_modules/$module/$submodule
done
else
mkdir -p $nodeModules/${packageName}/node_modules/
echo "ln -s $dep/lib/node_modules/$module $nodeModules/${packageName}/node_modules/$module"
ln -s $dep/lib/node_modules/$module $nodeModules/${packageName}/node_modules/$module
fi
done
fi
done
cd "$nodeModules/${packageName}"
export HOME=$TMPDIR
npm --offline --production --nodedir=${nodeSources} install
# Create symlink to the deployed executable folder, if applicable
if [ -d "$nodeModules/.bin" ]
then
ln -s $nodeModules/.bin $out/bin
fi
# Create symlinks to the deployed manual page folders, if applicable
if [ -d "$nodeModules/${packageName}/man" ]
then
mkdir -p $out/share
for dir in "$nodeModules/${packageName}/man/"*
do
mkdir -p $out/share/man/$(basename "$dir")
for page in "$dir"/*
do
ln -s $page $out/share/man/$(basename "$dir")
done
done
fi
runHook postInstall
'';
}));
package = makePackage mainPackageKey;
package = makePackage mainPackageName mainPackageVersion;
in
{
inherit package;
inherit package allPackages;
}

View File

@ -0,0 +1,24 @@
import json
import sys
with open(sys.argv[1]) as f:
actual_deps = json.load(f)
with open(sys.argv[2]) as f:
package_json = json.load(f)
changed = False
if 'dependencies' in package_json:
for pname, version in package_json['dependencies'].items():
if actual_deps[pname] != package_json['dependencies'][pname]:
package_json['dependencies'][pname] = actual_deps[pname]
changed = True
print(
f"WARNING: replacing malformed version '{version}' for dependency '{pname}' in package.json",
file=sys.stderr
)
if changed:
with open(sys.argv[2], 'w') as f:
json.dump(package_json, f, indent=2)

View File

@ -43,7 +43,7 @@ let
in
{
inherit packageName version;
name = lib.strings.sanitizeDerivationName packageName;
name = utils.sanitizeDerivationName packageName;
src = fetchedSources."${name}";
dependencies =
lib.forEach
@ -61,7 +61,7 @@ let
callNode2Nix = funcName: args:
node2nixEnv."${funcName}" rec {
name = lib.strings.sanitizeDerivationName packageName;
name = utils.sanitizeDerivationName packageName;
packageName = mainPackageName;
version = mainPackageVersion;
dependencies = node2nixDependencies;

View File

@ -28,16 +28,13 @@
else
lib.elemAt inputFiles 0;
parsed = externals.npmlock2nix.readLockfile packageLock;
parsed = b.fromJSON (b.readFile packageLock);
identifyGitSource = dependencyObject:
# TODO: when integrity is there, and git url is github then use tarball instead
# ! (dependencyObject ? integrity) &&
utils.identifyGitUrl dependencyObject.version;
# parseGithubDependency = dependency:
# externals.npmlock2nix.parseGitHubRef dependency.version;
getVersion = dependencyObject:
if identifyGitSource dependencyObject then
builtins.substring 0 8 (utils.parseGitUrl dependencyObject.version).rev

View File

@ -106,5 +106,8 @@ rec {
+ old.postFetch;
});
sanitizeDerivationName = name:
lib.replaceStrings [ "@" "/" ] [ "__at__" "__slash__" ] name;
}

View File

@ -8,45 +8,61 @@ let
exampleOverrides = {
hello = {
condition = old: if old.version > 3.0.0 then true else false;
override = old: {
patches = [];
};
};
hello = [
{
description = "patch hello";
condition = pkg: if pkg.version > 3.0.0 then true else false;
overrideAttrs = old: {
patches = [];
};
override = old: {
withPython = false;
};
}
];
};
applyOverridesToPackageArgs = conditionalOverrides: oldArgs:
let
applyOverridesToPackage = conditionalOverrides: pkg: pname:
if ! conditionalOverrides ? "${pname}" then
pkg
else
let
# if condition is unset, it will be assumed true
evalCondition = condAndOverride: oldArgs:
if condAndOverride ? condition then
condAndOverride.condition oldArgs
else
true;
# if condition is unset, it will be assumed true
evalCondition = condOverride: pkg:
if condOverride ? condition then
condOverride.condition pkg
else
true;
# filter the overrides by the package name and applying conditions
overridesToApply =
(lib.filterAttrs
(name: condAndOverride:
name == oldArgs.pname && condAndOverride.condition oldArgs)
conditionalOverrides);
in
# filter the overrides by the package name and conditions
overridesToApply =
(lib.filter
(condOverride: evalCondition condOverride pkg)
conditionalOverrides."${pname}");
# apply the overrides to the given args and return teh overridden args
lib.recursiveUpdate
# helper to apply one conditional override
# the condition is not evaluated anymore here
applyOneOverride = pkg: condOverride:
let
overrideFuncs =
lib.mapAttrsToList
(funcName: func: { inherit funcName func; })
(lib.filterAttrs (n: v: lib.hasPrefix "override" n) condOverride);
in
b.foldl'
(pkg: overrideFunc: pkg."${overrideFunc.funcName}" overrideFunc.func)
pkg
overrideFuncs;
in
# apply the overrides to the given pkg
(lib.foldl
(old: condAndOverride: old // (condAndOverride.override old))
oldArgs
(lib.attrValues overridesToApply))
{
passthru.appliedConditionalOverrides = lib.attrNames overridesToApply;
};
(pkg: condOverride: applyOneOverride pkg condOverride)
pkg
overridesToApply);
in
{
inherit applyOverridesToPackageArgs;
inherit applyOverridesToPackage;
}