From 5ad89398d12bf8bc83426036dedc2c601ff8f795 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 4 Dec 2012 14:20:36 +0100 Subject: [PATCH] nix-env: Install all outputs of a derivation If you explicitly install a package, presumably you want all of it. So symlink all outputs in the user environment. --- corepkgs/buildenv.nix | 14 +++++++++----- corepkgs/buildenv.pl | 33 ++++++++++++++++----------------- src/nix-env/user-env.cc | 35 +++++++++++++++++++++++++---------- 3 files changed, 50 insertions(+), 32 deletions(-) diff --git a/corepkgs/buildenv.nix b/corepkgs/buildenv.nix index 50c9923af7..9237783792 100644 --- a/corepkgs/buildenv.nix +++ b/corepkgs/buildenv.nix @@ -2,18 +2,22 @@ with import ; { derivations, manifest }: -derivation { +derivation { name = "user-environment"; system = builtins.currentSystem; builder = perl; args = [ "-w" ./buildenv.pl ]; - + manifest = manifest; # !!! grmbl, need structured data for passing this in a clean way. - paths = derivations; - active = map (x: if x ? meta && x.meta ? active then x.meta.active else "true") derivations; - priority = map (x: if x ? meta && x.meta ? priority then x.meta.priority else "5") derivations; + derivations = + map (d: + [ (if d.meta.active or true then "1" else "0") + (d.meta.priority or 5) + (builtins.length d.outputs) + ] ++ map (output: builtins.getAttr output d) d.outputs) + derivations; # Building user environments remotely just causes huge amounts of # network traffic, so don't do that. diff --git a/corepkgs/buildenv.pl b/corepkgs/buildenv.pl index 52a703c066..3d79e50316 100644 --- a/corepkgs/buildenv.pl +++ b/corepkgs/buildenv.pl @@ -43,12 +43,12 @@ sub createLinks { $srcFile =~ /\/log$/) { # Do nothing. - } + } elsif (-d $srcFile) { lstat $dstFile; - + if (-d _) { createLinks($srcFile, $dstFile, $priority); } @@ -59,7 +59,7 @@ sub createLinks { die "collission between directory `$srcFile' and non-directory `$target'"; } unlink $dstFile or die "error unlinking `$dstFile': $!"; - mkdir $dstFile, 0755 || + mkdir $dstFile, 0755 || die "error creating directory `$dstFile': $!"; createLinks($target, $dstFile, $priorities{$dstFile}); createLinks($srcFile, $dstFile, $priority); @@ -86,7 +86,7 @@ sub createLinks { next if $prevPriority < $priority; unlink $dstFile or die; } - + symlink($srcFile, $dstFile) || die "error creating link `$dstFile': $!"; $priorities{$dstFile} = $priority; @@ -125,19 +125,18 @@ sub addPkg { # Convert the stuff we get from the environment back into a coherent # data type. -my @paths = split ' ', $ENV{"paths"}; -my @active = split ' ', $ENV{"active"}; -my @priority = split ' ', $ENV{"priority"}; - -die if scalar @paths != scalar @active; -die if scalar @paths != scalar @priority; - my %pkgs; - -for (my $n = 0; $n < scalar @paths; $n++) { - $pkgs{$paths[$n]} = - { active => $active[$n] - , priority => $priority[$n] }; +my @derivations = split ' ', $ENV{"derivations"}; +while (scalar @derivations) { + my $active = shift @derivations; + my $priority = shift @derivations; + my $outputs = shift @derivations; + for (my $n = 0; $n < $outputs; $n++) { + my $path = shift @derivations; + $pkgs{$path} = + { active => int($active) + , priority => int($priority) }; + } } @@ -145,7 +144,7 @@ for (my $n = 0; $n < scalar @paths; $n++) { # user. foreach my $pkg (sort (keys %pkgs)) { #print $pkg, " ", $pkgs{$pkg}->{priority}, "\n"; - addPkg($pkg, $pkgs{$pkg}->{priority}) if $pkgs{$pkg}->{active} ne "false"; + addPkg($pkg, $pkgs{$pkg}->{priority}) if $pkgs{$pkg}->{active}; } diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc index 0a50493fd1..727c4bd44d 100644 --- a/src/nix-env/user-env.cc +++ b/src/nix-env/user-env.cc @@ -54,21 +54,42 @@ bool createUserEnv(EvalState & state, DrvInfos & elems, unsigned int n = 0; foreach (DrvInfos::iterator, i, elems) { /* Create a pseudo-derivation containing the name, system, - output path, and optionally the derivation path, as well as - the meta attributes. */ + output paths, and optionally the derivation path, as well + as the meta attributes. */ Path drvPath = keepDerivations ? i->queryDrvPath(state) : ""; Value & v(*state.allocValue()); manifest.list.elems[n++] = &v; - state.mkAttrs(v, 8); + state.mkAttrs(v, 16); mkString(*state.allocAttr(v, state.sType), "derivation"); mkString(*state.allocAttr(v, state.sName), i->name); - mkString(*state.allocAttr(v, state.sSystem), i->system); + if (!i->system.empty()) + mkString(*state.allocAttr(v, state.sSystem), i->system); mkString(*state.allocAttr(v, state.sOutPath), i->queryOutPath(state)); if (drvPath != "") mkString(*state.allocAttr(v, state.sDrvPath), i->queryDrvPath(state)); + // Copy each output. + DrvInfo::Outputs outputs = i->queryOutputs(state); + Value & vOutputs = *state.allocAttr(v, state.sOutputs); + state.mkList(vOutputs, outputs.size()); + unsigned int m = 0; + foreach (DrvInfo::Outputs::iterator, j, outputs) { + mkString(*(vOutputs.list.elems[m++] = state.allocValue()), j->first); + Value & vOutputs = *state.allocAttr(v, state.symbols.create(j->first)); + state.mkAttrs(vOutputs, 2); + mkString(*state.allocAttr(vOutputs, state.sOutPath), j->second); + + /* This is only necessary when installing store paths, e.g., + `nix-env -i /nix/store/abcd...-foo'. */ + store->addTempRoot(j->second); + store->ensurePath(j->second); + + references.insert(j->second); + } + + // Copy the meta attributes. Value & vMeta = *state.allocAttr(v, state.sMeta); state.mkAttrs(vMeta, 16); @@ -95,12 +116,6 @@ bool createUserEnv(EvalState & state, DrvInfos & elems, vMeta.attrs->sort(); v.attrs->sort(); - /* This is only necessary when installing store paths, e.g., - `nix-env -i /nix/store/abcd...-foo'. */ - store->addTempRoot(i->queryOutPath(state)); - store->ensurePath(i->queryOutPath(state)); - - references.insert(i->queryOutPath(state)); if (drvPath != "") references.insert(drvPath); }