about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2003-03-25T16·36+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2003-03-25T16·36+0000
commit0f40a560cab23f70881e5af405ea112a869dc39a (patch)
tree2bb622fd0230a5f53c330b946cbbe90714139ad5
parent3f1a1457e9ad91f93151200fe43c7c33ea95417b (diff)
* 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.

-rwxr-xr-xsrc/nix-activate22
-rwxr-xr-xsrc/nix-addroot18
-rwxr-xr-xsrc/nix-populate86
3 files changed, 108 insertions, 18 deletions
diff --git a/src/nix-activate b/src/nix-activate
new file mode 100755
index 000000000000..9fe6466866df
--- /dev/null
+++ b/src/nix-activate
@@ -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";
diff --git a/src/nix-addroot b/src/nix-addroot
deleted file mode 100755
index 3ab9e8a252f8..000000000000
--- a/src/nix-addroot
+++ /dev/null
@@ -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
diff --git a/src/nix-populate b/src/nix-populate
new file mode 100755
index 000000000000..294ded893ce0
--- /dev/null
+++ b/src/nix-populate
@@ -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";
+