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.
This commit is contained in:
Eelco Dolstra 2012-12-04 14:20:36 +01:00
parent 21c2d8d102
commit 5ad89398d1
3 changed files with 50 additions and 32 deletions

View file

@ -2,18 +2,22 @@ with import <nix/config.nix>;
{ derivations, manifest }: { derivations, manifest }:
derivation { derivation {
name = "user-environment"; name = "user-environment";
system = builtins.currentSystem; system = builtins.currentSystem;
builder = perl; builder = perl;
args = [ "-w" ./buildenv.pl ]; args = [ "-w" ./buildenv.pl ];
manifest = manifest; manifest = manifest;
# !!! grmbl, need structured data for passing this in a clean way. # !!! grmbl, need structured data for passing this in a clean way.
paths = derivations; derivations =
active = map (x: if x ? meta && x.meta ? active then x.meta.active else "true") derivations; map (d:
priority = map (x: if x ? meta && x.meta ? priority then x.meta.priority else "5") derivations; [ (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 # Building user environments remotely just causes huge amounts of
# network traffic, so don't do that. # network traffic, so don't do that.

View file

@ -43,12 +43,12 @@ sub createLinks {
$srcFile =~ /\/log$/) $srcFile =~ /\/log$/)
{ {
# Do nothing. # Do nothing.
} }
elsif (-d $srcFile) { elsif (-d $srcFile) {
lstat $dstFile; lstat $dstFile;
if (-d _) { if (-d _) {
createLinks($srcFile, $dstFile, $priority); createLinks($srcFile, $dstFile, $priority);
} }
@ -59,7 +59,7 @@ sub createLinks {
die "collission between directory `$srcFile' and non-directory `$target'"; die "collission between directory `$srcFile' and non-directory `$target'";
} }
unlink $dstFile or die "error unlinking `$dstFile': $!"; unlink $dstFile or die "error unlinking `$dstFile': $!";
mkdir $dstFile, 0755 || mkdir $dstFile, 0755 ||
die "error creating directory `$dstFile': $!"; die "error creating directory `$dstFile': $!";
createLinks($target, $dstFile, $priorities{$dstFile}); createLinks($target, $dstFile, $priorities{$dstFile});
createLinks($srcFile, $dstFile, $priority); createLinks($srcFile, $dstFile, $priority);
@ -86,7 +86,7 @@ sub createLinks {
next if $prevPriority < $priority; next if $prevPriority < $priority;
unlink $dstFile or die; unlink $dstFile or die;
} }
symlink($srcFile, $dstFile) || symlink($srcFile, $dstFile) ||
die "error creating link `$dstFile': $!"; die "error creating link `$dstFile': $!";
$priorities{$dstFile} = $priority; $priorities{$dstFile} = $priority;
@ -125,19 +125,18 @@ sub addPkg {
# Convert the stuff we get from the environment back into a coherent # Convert the stuff we get from the environment back into a coherent
# data type. # 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; my %pkgs;
my @derivations = split ' ', $ENV{"derivations"};
for (my $n = 0; $n < scalar @paths; $n++) { while (scalar @derivations) {
$pkgs{$paths[$n]} = my $active = shift @derivations;
{ active => $active[$n] my $priority = shift @derivations;
, priority => $priority[$n] }; 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. # user.
foreach my $pkg (sort (keys %pkgs)) { foreach my $pkg (sort (keys %pkgs)) {
#print $pkg, " ", $pkgs{$pkg}->{priority}, "\n"; #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};
} }

View file

@ -54,21 +54,42 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
unsigned int n = 0; unsigned int n = 0;
foreach (DrvInfos::iterator, i, elems) { foreach (DrvInfos::iterator, i, elems) {
/* Create a pseudo-derivation containing the name, system, /* Create a pseudo-derivation containing the name, system,
output path, and optionally the derivation path, as well as output paths, and optionally the derivation path, as well
the meta attributes. */ as the meta attributes. */
Path drvPath = keepDerivations ? i->queryDrvPath(state) : ""; Path drvPath = keepDerivations ? i->queryDrvPath(state) : "";
Value & v(*state.allocValue()); Value & v(*state.allocValue());
manifest.list.elems[n++] = &v; 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.sType), "derivation");
mkString(*state.allocAttr(v, state.sName), i->name); 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)); mkString(*state.allocAttr(v, state.sOutPath), i->queryOutPath(state));
if (drvPath != "") if (drvPath != "")
mkString(*state.allocAttr(v, state.sDrvPath), i->queryDrvPath(state)); 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); Value & vMeta = *state.allocAttr(v, state.sMeta);
state.mkAttrs(vMeta, 16); state.mkAttrs(vMeta, 16);
@ -95,12 +116,6 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
vMeta.attrs->sort(); vMeta.attrs->sort();
v.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); if (drvPath != "") references.insert(drvPath);
} }