diff options
author | Eelco Dolstra <e.dolstra@tudelft.nl> | 2007-04-27T23·28+0000 |
---|---|---|
committer | Eelco Dolstra <e.dolstra@tudelft.nl> | 2007-04-27T23·28+0000 |
commit | a46db5d013a5c3ab5b041824bfb935e5c042886c (patch) | |
tree | 5e56daa787c6958582e5e77877d1336e720ca9c8 | |
parent | 3d05166086682b39e013001bdaedb3e8b68a769f (diff) |
* Package conflict resolution through priority levels. If there is a
user environment collission between two packages due to overlapping file names, then a package with a higher priority will overwrite the symlinks of a package with a lower priority. E.g., $ nix-env --set-flag priority 5 gcc $ nix-env --set-flag priority 10 binutils gives gcc a higher priority than binutils (higher number = lower priority).
-rwxr-xr-x | corepkgs/buildenv/builder.pl.in | 60 | ||||
-rw-r--r-- | corepkgs/buildenv/default.nix | 4 | ||||
-rw-r--r-- | doc/manual/release-notes.xml | 4 |
3 files changed, 48 insertions, 20 deletions
diff --git a/corepkgs/buildenv/builder.pl.in b/corepkgs/buildenv/builder.pl.in index faebe27cc2a1..04c895554a68 100755 --- a/corepkgs/buildenv/builder.pl.in +++ b/corepkgs/buildenv/builder.pl.in @@ -12,13 +12,15 @@ mkdir "$out", 0755 || die "error creating $out"; my $symlinks = 0; +my %priorities; + # For each activated package, create symlinks. sub createLinks { my $srcDir = shift; my $dstDir = shift; - my $ignoreCollisions = shift; + my $priority = shift; my @srcFiles = glob("$srcDir/*"); @@ -42,7 +44,7 @@ sub createLinks { lstat $dstFile; if (-d _) { - createLinks($srcFile, $dstFile, $ignoreCollisions); + createLinks($srcFile, $dstFile, $priority); } elsif (-l _) { @@ -53,27 +55,35 @@ sub createLinks { unlink $dstFile or die "error unlinking `$dstFile': $!"; mkdir $dstFile, 0755 || die "error creating directory `$dstFile': $!"; - createLinks($target, $dstFile, $ignoreCollisions); - createLinks($srcFile, $dstFile, $ignoreCollisions); + createLinks($target, $dstFile, $priority); # !!! <- priority isn't right + createLinks($srcFile, $dstFile, $priority); } else { symlink($srcFile, $dstFile) || die "error creating link `$dstFile': $!"; + $priorities{$dstFile} = $priority; $symlinks++; } } - elsif (-l $dstFile) { - if (!$ignoreCollisions) { + else { + + if (-l $dstFile) { my $target = readlink $dstFile; - die "collission between `$srcFile' and `$target'"; + my $prevPriority = $priorities{$dstFile}; + die ( "Collission between `$srcFile' and `$target'. " + . "Suggested solution: use `nix-env --set-flag " + . "priority NUMBER PKGNAME' to change the priority of " + . "one of the conflicting packages.\n" ) + if $prevPriority == $priority; + next if $prevPriority < $priority; + unlink $dstFile or die; } - } - - else { + symlink($srcFile, $dstFile) || die "error creating link `$dstFile': $!"; + $priorities{$dstFile} = $priority; $symlinks++; } } @@ -86,13 +96,13 @@ my %postponed; sub addPkg; sub addPkg { my $pkgDir = shift; - my $ignoreCollisions = shift; + my $priority = shift; return if (defined $done{$pkgDir}); $done{$pkgDir} = 1; # print "symlinking $pkgDir\n"; - createLinks("$pkgDir", "$out", $ignoreCollisions); + createLinks("$pkgDir", "$out", $priority); my $propagatedFN = "$pkgDir/nix-support/propagated-user-env-packages"; if (-e $propagatedFN) { @@ -107,16 +117,29 @@ sub addPkg { } -# Symlink to the packages that have been installed explicitly by the user. -my @paths = split ' ', $ENV{"derivations"}; +# 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++) { - my $pkgDir = $paths[$n]; - my $isActive = $active[$n]; - addPkg($pkgDir, 0) if $isActive ne "false"; + $pkgs{$paths[$n]} = + { active => $active[$n] + , priority => $priority[$n] }; +} + + +# Symlink to the packages that have been installed explicitly by the +# user. +foreach my $pkg (sort (keys %pkgs)) { + #print $pkg, " ", $pkgs{$pkg}->{priority}, "\n"; + addPkg($pkg, $pkgs{$pkg}->{priority}) if $pkgs{$pkg}->{active} ne "false"; } @@ -124,11 +147,12 @@ for (my $n = 0; $n < scalar @paths; $n++) { # installed by the user (i.e., package X declares that it want Y # installed as well). We do these later because they have a lower # priority in case of collisions. +my $priorityCounter = 1000; # don't care about collisions while (scalar(keys %postponed) > 0) { my @pkgDirs = keys %postponed; %postponed = (); foreach my $pkgDir (sort @pkgDirs) { - addPkg($pkgDir, 1); + addPkg($pkgDir, $priorityCounter++); } } diff --git a/corepkgs/buildenv/default.nix b/corepkgs/buildenv/default.nix index a5452db5ea89..36dd9d0c6a0a 100644 --- a/corepkgs/buildenv/default.nix +++ b/corepkgs/buildenv/default.nix @@ -4,9 +4,11 @@ derivation { name = "user-environment"; system = system; builder = ./builder.pl; - derivations = derivations; + 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; } diff --git a/doc/manual/release-notes.xml b/doc/manual/release-notes.xml index e5d0adf74bef..161643e52d4e 100644 --- a/doc/manual/release-notes.xml +++ b/doc/manual/release-notes.xml @@ -71,7 +71,9 @@ environments.</para></listitem> <listitem><para>TODO: <command>nix-env</command> - <option>--set-flag</option>.</para></listitem> + <option>--set-flag</option>. Specific flags: + <literal>active</literal>, + <literal>priority</literal>.</para></listitem> <listitem><para><command>nix-env -q</command> now has a flag |