nodePackages: refactor, add support for overrides

This commit is contained in:
Jaka Hudoklin 2015-01-24 22:54:03 +01:00
parent a00131bb32
commit 628c84c831
3 changed files with 121 additions and 64 deletions

View File

@ -1,6 +1,32 @@
{ stdenv, runCommand, nodejs, neededNatives}: { stdenv, runCommand, nodejs, neededNatives}:
args @ { name, src, deps ? {}, peerDependencies ? [], flags ? [], preShellHook ? "", postShellHook ? "", resolvedDeps ? {}, bin ? null, ... }: {
name, src,
# List or attribute set of dependencies
deps ? {},
# List or attribute set of peer depencies
peerDependencies ? [],
# Whether package is binary or library
bin ? null,
# Flags passed to npm install
flags ? [],
# Command to be run before shell hook
preShellHook ? "",
# Command to be run after shell hook
postShellHook ? "",
# Attribute set of already resolved deps (internal),
# for avoiding infinite recursion
resolvedDeps ? {},
...
} @ args:
with stdenv.lib; with stdenv.lib;
@ -12,6 +38,9 @@ let
mv *node* $out mv *node* $out
''; '';
# Package name without version
pkgName = (builtins.parseDrvName name).name;
# Convert deps to attribute set # Convert deps to attribute set
attrDeps = if isAttrs deps then deps else attrDeps = if isAttrs deps then deps else
(listToAttrs (map (dep: nameValuePair dep.name dep) deps)); (listToAttrs (map (dep: nameValuePair dep.name dep) deps));
@ -22,10 +51,7 @@ let
# Recursive dependencies that we want to avoid with shim creation # Recursive dependencies that we want to avoid with shim creation
recursiveDeps = removeAttrs attrDeps (attrNames requiredDeps); recursiveDeps = removeAttrs attrDeps (attrNames requiredDeps);
peerDeps = listToAttrs (concatMap (dep: map (name: { peerDeps = filter (dep: dep.pkgName != pkgName) peerDependencies;
inherit name;
value = dep;
}) (filter (nm: !(elem nm (args.passthru.names or []))) dep.names)) (peerDependencies));
self = let self = let
# Pass resolved dependencies to dependencies of this package # Pass resolved dependencies to dependencies of this package
@ -121,29 +147,29 @@ let
# Symlink or copy dependencies for node modules # Symlink or copy dependencies for node modules
# copy is needed if dependency has recursive dependencies, # copy is needed if dependency has recursive dependencies,
# because node can't follow symlinks while resolving recursive deps. # because node can't follow symlinks while resolving recursive deps.
${concatStrings (concatMap (dep: map (name: ${concatMapStrings (dep:
if dep.recursiveDeps == [] then '' if dep.recursiveDeps == [] then ''
ln -sv ${dep}/lib/node_modules/${name} node_modules/ ln -sv ${dep}/lib/node_modules/${dep.pkgName} node_modules/
'' else '' '' else ''
cp -R ${dep}/lib/node_modules/${name} node_modules/ cp -R ${dep}/lib/node_modules/${dep.pkgName} node_modules/
'' ''
) dep.names) deps)} ) deps}
# Symlink peer dependencies # Symlink peer dependencies
${concatStrings (mapAttrsToList (name: dep: '' ${concatMapStrings (dep: ''
ln -sv ${dep}/lib/node_modules/${name} node_modules/ ln -sv ${dep}/lib/node_modules/${dep.pkgName} node_modules/
'') peerDeps)} '') peerDeps}
# Create shims for recursive dependenceies # Create shims for recursive dependenceies
${concatStrings (concatMap (dep: map (name: '' ${concatMapStrings (dep: ''
mkdir -p node_modules/${name} mkdir -p node_modules/${dep.pkgName}
cat > node_modules/${name}/package.json <<EOF cat > node_modules/${dep.pkgName}/package.json <<EOF
{ {
"name": "${name}", "name": "${dep.pkgName}",
"version": "${(builtins.parseDrvName dep.name).version}" "version": "${getVersion dep}"
} }
EOF EOF
'') dep.names) (attrValues recursiveDeps))} '') (attrValues recursiveDeps)}
) )
export HOME=$PWD/build-dir export HOME=$PWD/build-dir
@ -174,34 +200,32 @@ let
cd $HOME cd $HOME
# Remove shims # Remove shims
${concatStrings (concatMap (dep: map (name: '' ${concatMapStrings (dep: ''
rm node_modules/${name}/package.json rm node_modules/${dep.pkgName}/package.json
rmdir node_modules/${name} rmdir node_modules/${dep.pkgName}
'') dep.names) (attrValues recursiveDeps))} '') (attrValues recursiveDeps)}
mkdir -p $out/lib/node_modules mkdir -p $out/lib/node_modules
# Install manual # Install manual
${concatStrings (map (name: '' mv node_modules/${pkgName} $out/lib/node_modules
mv node_modules/${name} $out/lib/node_modules rm -fR $out/lib/node_modules/${pkgName}/node_modules
rm -fR $out/lib/node_modules/${name}/node_modules cp -r node_modules $out/lib/node_modules/${pkgName}/node_modules
cp -r node_modules $out/lib/node_modules/${name}/node_modules
if [ -e "$out/lib/node_modules/${name}/man" ]; then if [ -e "$out/lib/node_modules/${pkgName}/man" ]; then
mkdir -p $out/share mkdir -p $out/share
for dir in "$out/lib/node_modules/${name}/man/"*; do for dir in "$out/lib/node_modules/${pkgName}/man/"*; do
mkdir -p $out/share/man/$(basename "$dir") mkdir -p $out/share/man/$(basename "$dir")
for page in "$dir"/*; do for page in "$dir"/*; do
ln -sv $page $out/share/man/$(basename "$dir") ln -sv $page $out/share/man/$(basename "$dir")
done done
done done
fi fi
'') args.passthru.names)}
# Symlink dependencies # Symlink dependencies
${concatStrings (mapAttrsToList (name: dep: '' ${concatMapStrings (dep: ''
mv node_modules/${name} $out/lib/node_modules mv node_modules/${dep.pkgName} $out/lib/node_modules
'') peerDeps)} '') peerDeps}
# Install binaries and patch shebangs # Install binaries and patch shebangs
mv node_modules/.bin $out/lib/node_modules 2>/dev/null || true mv node_modules/.bin $out/lib/node_modules 2>/dev/null || true
@ -214,19 +238,21 @@ let
runHook postInstall runHook postInstall
''; '';
preFixup = concatStringsSep "\n" (map (src: '' preFixup = ''
find $out -type f -print0 | xargs -0 sed -i 's|${src}|${src.name}|g' find $out -type f -print0 | xargs -0 sed -i 's|${src}|${src.name}|g'
'') src); '';
shellHook = '' shellHook = ''
${preShellHook} ${preShellHook}
export PATH=${nodejs}/bin:$(pwd)/node_modules/.bin:$PATH export PATH=${nodejs}/bin:$(pwd)/node_modules/.bin:$PATH
mkdir -p node_modules mkdir -p node_modules
${concatStrings (concatMap (dep: map (name: '' ${concatMapStrings (dep: ''
ln -sfv ${dep}/lib/node_modules/${name} node_modules/ ln -sfv ${dep}/lib/node_modules/${dep.pkgName} node_modules/
'') dep.names) deps)} '') deps}
${postShellHook} ${postShellHook}
''; '';
passthru.pkgName = pkgName;
} // (filterAttrs (n: v: n != "deps" && n != "resolvedDeps") args) // { } // (filterAttrs (n: v: n != "deps" && n != "resolvedDeps") args) // {
name = "${ name = "${
if bin == true then "bin-" else if bin == false then "node-" else "" if bin == true then "bin-" else if bin == false then "node-" else ""

View File

@ -1664,11 +1664,9 @@ let
nodejs = callPackage ../development/web/nodejs { }; nodejs = callPackage ../development/web/nodejs { };
nodejs-unstable = callPackage ../development/web/nodejs { unstableVersion = true; }; nodejs-unstable = callPackage ../development/web/nodejs { unstableVersion = true; };
nodePackages = recurseIntoAttrs (callPackage ./node-packages.nix { nodePackages = recurseIntoAttrs (
inherit pkgs stdenv nodejs fetchurl fetchgit; callPackage ./node-packages.nix { self = nodePackages; }
neededNatives = [python] ++ lib.optional (lib.elem system lib.platforms.linux) utillinux; );
self = pkgs.nodePackages;
});
ldapvi = callPackage ../tools/misc/ldapvi { }; ldapvi = callPackage ../tools/misc/ldapvi { };

View File

@ -1,23 +1,56 @@
{ pkgs, stdenv, nodejs, fetchurl, fetchgit, neededNatives, self, generated ? ./node-packages-generated.nix }: {
stdenv, pkgs, nodejs
# Self-reference
, self
# Needed natives for installation
, neededNatives ? [pkgs.python] ++ stdenv.lib.optionals stdenv.isLinux [ pkgs.utillinux ]
# Attribute set of generated packages
, generated ? pkgs.callPackage ./node-packages-generated.nix { inherit self; }
# Attribute set of overrides
, overrides ? {}
, ...
} @ args:
with stdenv.lib;
rec { rec {
nativeDeps = { overrides = {
"node-expat" = [ pkgs.expat ]; phantomjs.buildInputs = [ pkgs.phantomjs ];
"node-stringprep" = [ pkgs.icu pkgs.which ]; "node-expat".buildInputs = [ pkgs.expat ];
"rbytes" = [ pkgs.openssl ]; "node-stringprep".buildInputs = [ pkgs.icu pkgs.which ];
"phantomjs" = [ pkgs.phantomjs ]; "node-protobuf".buildInputs = [ pkgs.protobuf ];
"node-protobuf" = [ pkgs.protobuf ]; "rbytes".buildInputs = [ pkgs.openssl ];
}; } // args.overrides or {};
buildNodePackage = import ../development/web/nodejs/build-node-package.nix { # Apply overrides and back compatiblity transformations
inherit stdenv nodejs neededNatives; buildNodePackage = {...} @ args:
inherit (pkgs) runCommand; let
}; pkg = makeOverridable (
pkgs.callPackage ../development/web/nodejs/build-node-package.nix {
inherit nodejs neededNatives;
}
) (args // {
# Backwards compatibility
src = if isList args.src then head args.src else args.src;
pkgName = (builtins.parseDrvName args.name).name;
});
override = overrides.${args.name} or overrides.${pkg.pkgName} or {};
in pkg.override override;
# Backwards compatibility
patchSource = fn: srcAttrs: fn srcAttrs; patchSource = fn: srcAttrs: fn srcAttrs;
patchLatest = patchSource pkgs.fetchurl;
# Backwards compat
patchLatest = patchSource fetchurl;
/* Put manual packages below here (ideally eventually managed by npm2nix */ /* Put manual packages below here (ideally eventually managed by npm2nix */
} // import generated { inherit self fetchurl fetchgit; inherit (pkgs) lib; } } // (
if isAttrs generated then generated
# Backwards compatiblity
else pkgs.callPackage generated { inherit self; }
)