about summary refs log tree commit diff
diff options
context:
space:
mode:
-rwxr-xr-xscripts/nix-collect-garbage.in16
-rwxr-xr-xscripts/nix-switch.in52
-rw-r--r--src/Makefile.am1
-rw-r--r--src/nix-help.txt2
-rw-r--r--src/nix.cc15
-rw-r--r--src/normalise.cc20
-rw-r--r--src/normalise.hh10
7 files changed, 86 insertions, 30 deletions
diff --git a/scripts/nix-collect-garbage.in b/scripts/nix-collect-garbage.in
index 8f54ba20f3e4..eaa706578117 100755
--- a/scripts/nix-collect-garbage.in
+++ b/scripts/nix-collect-garbage.in
@@ -5,13 +5,27 @@ my $storedir = "@prefix@/store";
 
 my %alive;
 
-open HASHES, "nix --query --refs \$(cat $linkdir/*.hash) |" or die "in `nix -qrh'";
+my $keepsuccessors = 0;
+my $invert = 0;
+
+foreach my $arg (@ARGV) {
+    if ($arg eq "--keep-successors") { $keepsuccessors = 1; }
+    if ($arg eq "--invert") { $invert = 1; }
+    else { die "unknown argument `$arg'" };
+}
+
+my $extraarg = "";
+if ($keepsuccessors) { $extraarg = "--include-successors"; };
+open HASHES, "nix --query --requisites $extraarg \$(cat $linkdir/*.id) |" or die "in `nix -qrh'";
 while (<HASHES>) {
 	chomp;
 	$alive{$_} = 1;
+	if ($invert) { print "$_\n"; };
 }
 close HASHES;
 
+exit 0 if ($invert);
+
 opendir(DIR, $storedir) or die "cannot opendir $storedir: $!";
 my @names = readdir(DIR);
 closedir DIR;
diff --git a/scripts/nix-switch.in b/scripts/nix-switch.in
index ddaca4e227ad..db0e96f3e7e8 100755
--- a/scripts/nix-switch.in
+++ b/scripts/nix-switch.in
@@ -3,39 +3,56 @@
 use strict;
 
 my $keep = 0;
-
-if (scalar @ARGV > 0 && $ARGV[0] eq "--keep") {
-    shift @ARGV;
-    $keep = 1;
+my $sourceroot = 0;
+my $srcid;
+
+foreach my $arg (@ARGV) {
+    if ($arg eq "--keep") { $keep = 1; }
+    elsif ($arg eq "--source-root") { $sourceroot = 1; }
+    elsif ($arg =~ /^([0-9a-z]{32})$/) { $srcid = $arg; }
+    else { die "unknown argument `$arg'" };
 }
 
-my $hash = $ARGV[0];
-$hash || die "no package hash specified";
-
 my $linkdir = "@localstatedir@/nix/links";
 
 # Build the specified package, and all its dependencies.
-system "nix --install $hash";
+my $nfid = `nix --install $srcid`;
 if ($?) { die "`nix --install' failed"; }
+chomp $nfid;
+die unless $nfid =~ /^([0-9a-z]{32})$/;
 
-my $pkgdir = `nix --query --list $hash`;
+my $pkgdir = `nix --query --list $nfid`;
 if ($?) { die "`nix --query --list' failed"; }
 chomp $pkgdir;
 
 # Figure out a generation number.
+opendir(DIR, $linkdir);
 my $nr = 0;
-while (-e "$linkdir/$nr") { $nr++; }
+foreach my $n (sort(readdir(DIR))) {
+    next if (!($n =~ /^\d+$/));
+    $nr = $n + 1 if ($n >= $nr);
+}
+closedir(DIR);
+
 my $link = "$linkdir/$nr";
 
 # Create a symlink from $link to $pkgdir.
 symlink($pkgdir, $link) or die "cannot create $link: $!";
 
-# Also store the hash of $pkgdir.  This is useful for garbage
+# Store the id of the normal form.  This is useful for garbage
 # collection and the like.
-my $hashfile = "$linkdir/$nr.hash";
-open HASH, "> $hashfile" or die "cannot create $hashfile";
-print HASH "$hash\n";
-close HASH;
+my $idfile = "$linkdir/$nr.id";
+open ID, "> $idfile" or die "cannot create $idfile";
+print ID "$nfid\n";
+close ID;
+
+# Optionally store the source id.
+if ($sourceroot) {
+    $idfile = "$linkdir/$nr-src.id";
+    open ID, "> $idfile" or die "cannot create $idfile";
+    print ID "$srcid\n";
+    close ID;
+}
 
 my $current = "$linkdir/current";
 
@@ -59,6 +76,7 @@ rename($tmplink, $current) or die "cannot rename $tmplink";
 
 if (!$keep && defined $oldlink) {
     print "deleting old $oldlink\n";
-    unlink($oldlink) == 1 || print "cannot delete $oldlink\n";
-    unlink("$oldlink.hash") == 1 || print "cannot delete $oldlink.hash\n";
+    unlink($oldlink) == 1 or print "cannot delete $oldlink\n";
+    unlink("$oldlink.id") == 1 or print "cannot delete $oldlink.id\n";
+    unlink("$oldlink-src.id");
 }
diff --git a/src/Makefile.am b/src/Makefile.am
index 23e2429191ac..cc51eff36577 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -43,6 +43,7 @@ nix.o: nix-help.txt.hh
 install-data-local:
 	$(INSTALL) -d $(localstatedir)/nix
 	$(INSTALL) -d $(localstatedir)/nix/links
+	ln -sf $(localstatedir)/nix/links/current $(prefix)/current
 	$(INSTALL) -d $(localstatedir)/log/nix
 	$(INSTALL) -d $(prefix)/store
 	$(bindir)/nix --init
diff --git a/src/nix-help.txt b/src/nix-help.txt
index ecf9b5c16d25..0e54d162de05 100644
--- a/src/nix-help.txt
+++ b/src/nix-help.txt
@@ -26,7 +26,7 @@ Source selection for --install, --dump:
 Query flags:
 
   --list / -l: query the output paths (roots) of an fstate (default)
-  --refs / -r: query paths referenced by an fstate
+  --requisites / -r: print all paths necessary to realise expression
   --generators / -g: find expressions producing a subset of given ids
   --expansion / -e: print a path containing id
   --graph: print a dot graph rooted at given ids
diff --git a/src/nix.cc b/src/nix.cc
index a7bcf7268413..68d01f2f87a3 100644
--- a/src/nix.cc
+++ b/src/nix.cc
@@ -95,18 +95,22 @@ FSId maybeNormalise(const FSId & id, bool normalise)
 /* Perform various sorts of queries. */
 static void opQuery(Strings opFlags, Strings opArgs)
 {
-    enum { qList, qRefs, qGenerators, qExpansion, qGraph 
+    enum { qList, qRequisites, qGenerators, qExpansion, qGraph 
     } query = qList;
     bool normalise = false;
+    bool includeExprs = true;
+    bool includeSuccessors = false;
 
     for (Strings::iterator i = opFlags.begin();
          i != opFlags.end(); i++)
         if (*i == "--list" || *i == "-l") query = qList;
-        else if (*i == "--refs" || *i == "-r") query = qRefs;
+        else if (*i == "--requisites" || *i == "-r") query = qRequisites;
         else if (*i == "--generators" || *i == "-g") query = qGenerators;
         else if (*i == "--expansion" || *i == "-e") query = qExpansion;
         else if (*i == "--graph") query = qGraph;
         else if (*i == "--normalise" || *i == "-n") normalise = true;
+        else if (*i == "--exclude-exprs") includeExprs = false;
+        else if (*i == "--include-successors") includeSuccessors = true;
         else throw UsageError(format("unknown flag `%1%'") % *i);
 
     switch (query) {
@@ -126,13 +130,14 @@ static void opQuery(Strings opFlags, Strings opArgs)
             break;
         }
 
-        case qRefs: {
+        case qRequisites: {
             StringSet paths;
             for (Strings::iterator i = opArgs.begin();
                  i != opArgs.end(); i++)
             {
-                Strings paths2 = fstateRefs(
-                    maybeNormalise(argToId(*i), normalise));
+                Strings paths2 = fstateRequisites(
+                    maybeNormalise(argToId(*i), normalise),
+                    includeExprs, includeSuccessors);
                 paths.insert(paths2.begin(), paths2.end());
             }
             for (StringSet::iterator i = paths.begin(); 
diff --git a/src/normalise.cc b/src/normalise.cc
index eefb790b6f98..5ef4d82ac139 100644
--- a/src/normalise.cc
+++ b/src/normalise.cc
@@ -244,7 +244,8 @@ Strings fstatePaths(const FSId & id)
 }
 
 
-static void fstateRefsSet(const FSId & id, StringSet & paths)
+static void fstateRequisitesSet(const FSId & id, 
+    bool includeExprs, bool includeSuccessors, StringSet & paths)
 {
     FState fs = parseFState(termFromId(id));
 
@@ -257,17 +258,28 @@ static void fstateRefsSet(const FSId & id, StringSet & paths)
     else if (fs.type == FState::fsDerive) {
         for (FSIds::iterator i = fs.derive.inputs.begin();
              i != fs.derive.inputs.end(); i++)
-            fstateRefsSet(*i, paths);
+            fstateRequisitesSet(*i,
+                includeExprs, includeSuccessors, paths);
     }
 
     else abort();
+
+    if (includeExprs) 
+        paths.insert(expandId(id));
+
+    string idSucc;
+    if (includeSuccessors &&
+        queryDB(nixDB, dbSuccessors, id, idSucc))
+        fstateRequisitesSet(parseHash(idSucc), 
+            includeExprs, includeSuccessors, paths);
 }
 
 
-Strings fstateRefs(const FSId & id)
+Strings fstateRequisites(const FSId & id,
+    bool includeExprs, bool includeSuccessors)
 {
     StringSet paths;
-    fstateRefsSet(id, paths);
+    fstateRequisitesSet(id, includeExprs, includeSuccessors, paths);
     return Strings(paths.begin(), paths.end());
 }
 
diff --git a/src/normalise.hh b/src/normalise.hh
index a5b45c861926..98f58783e5b8 100644
--- a/src/normalise.hh
+++ b/src/normalise.hh
@@ -15,8 +15,14 @@ void realiseSlice(const FSId & id, FSIdSet pending = FSIdSet());
    fstate-expression. */
 Strings fstatePaths(const FSId & id);
 
-/* Get the list of paths referenced by the given fstate-expression. */
-Strings fstateRefs(const FSId & id);
+/* Get the list of paths that are required to realise the given
+   expression.  For a derive expression, this is the union of
+   requisites of the inputs; for a slice expression, it is the path of
+   each element in the slice.  If `includeExprs' is true, include the
+   paths of the Nix expressions themselves.  If `includeSuccessors' is
+   true, include the requisites of successors. */
+Strings fstateRequisites(const FSId & id,
+    bool includeExprs, bool includeSuccessors);
 
 /* Return the list of the ids of all known fstate-expressions whose
    output ids are completely contained in `ids'. */