* Added a script nix-activate which builds a list of "activated"

packages (i.e., the packages that should appear in the user's $PATH,
  and so on).  Based on this list, the script nix-populate creates a
  hierarchy of symlinks to the relevant files in those packages (e.g.,
  for pkg/bin and pkg/lib).  

  A nice property of nix-populate is that on each run it creates a
  *new* tree, rather than updating the old one.  It then atomically
  switches over to the new tree.  This allows atomic upgrades or
  rollbacks on the set of activated packages.
This commit is contained in:
Eelco Dolstra 2003-03-25 16:36:25 +00:00
parent 3f1a1457e9
commit 0f40a560ca
3 changed files with 108 additions and 18 deletions

22
src/nix-activate Executable file
View file

@ -0,0 +1,22 @@
#! /usr/bin/perl -w
use strict;
my $pkglist = "/home/eelco/.nixactivations";
if (!-f $pkglist) {
system "touch $pkglist";
}
my $hash;
foreach $hash (@ARGV) {
system "grep -q $hash $pkglist";
if ($?) {
print STDERR "activating $hash\n";
system "nix getpkg $hash > /dev/null";
if ($?) { die "`nix getpkg' failed"; }
system "echo $hash >> $pkglist";
}
}
system "nix-populate";

View file

@ -1,18 +0,0 @@
#! /bin/sh
ROOTLIST=~/.nixroots
if ! test -f $ROOTLIST; then
touch $ROOTLIST
fi
for i in $*; do
if nix ensure $i > /dev/null; then
if grep -q $i $ROOTLIST; then
echo $i already is a root
else
echo adding root $i
echo $i >> $ROOTLIST
fi
fi
done

86
src/nix-populate Executable file
View file

@ -0,0 +1,86 @@
#! /usr/bin/perl -w
use strict;
my $pkglist = $ENV{"NIX_ACTIVATIONS"};
$pkglist or die "NIX_ACTIVATIONS not set";
my $linkdir = $ENV{"NIX_LINKS"};
$linkdir or die "NIX_LINKS not set";
my @dirs = ("bin", "sbin", "lib");
# Figure out a generation number.
my $nr = 1;
while (-e "$linkdir/$nr") { $nr++; }
my $gendir = "$linkdir/$nr";
print "populating $gendir\n";
# Create the subdirectories.
mkdir $gendir;
foreach my $dir (@dirs) {
mkdir "$gendir/$dir";
}
# For each activated package, create symlinks.
sub createLinks {
my $srcdir = shift;
my $dstdir = shift;
my @srcfiles = glob("$srcdir/*");
foreach my $srcfile (@srcfiles) {
my $basename = $srcfile;
$basename =~ s/^.*\///g; # strip directory
my $dstfile = "$dstdir/$basename";
if (-d $srcfile) {
# !!! hack for resolving name clashes
if (!-e $dstfile) {
mkdir($dstfile) or
die "error creating directory $dstfile";
}
-d $dstfile or die "$dstfile is not a directory";
createLinks($srcfile, $dstfile);
} else {
print "linking $dstfile to $srcfile\n";
symlink($srcfile, $dstfile) or
die "error creating link $dstfile";
}
}
}
open PKGS, "< $pkglist";
while (<PKGS>) {
chomp;
my $hash = $_;
my $pkgdir = `nix getpkg $hash`;
if ($?) { die "`nix getpkg' failed"; }
chomp $pkgdir;
print "merging $pkgdir\n";
foreach my $dir (@dirs) {
createLinks("$pkgdir/$dir", "$gendir/$dir");
}
}
close PKGS;
# Make $gendir the current generation by pointing $linkdir/current to
# it. The rename() system call is supposed to be essentially atomic
# on Unix. That is, if we have links `current -> X' and `new_current
# -> Y', and we rename new_current to current, a process accessing
# current will see X or Y, but never a file-not-found or other error
# condition. This is sufficient to atomically switch the current link
# tree.
my $current = "$linkdir/current";
print "switching $current to $gendir\n";
my $tmplink = "$linkdir/new_current";
symlink($gendir, $tmplink) or die "cannot create $tmplink";
rename($tmplink, $current) or die "cannot rename $tmplink";