about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2003-07-29T14·28+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2003-07-29T14·28+0000
commit884646593488bfacd851bec72b7ac1a4841bf458 (patch)
tree0417e939be5e5d12645966da3fe6f41fefde0ea2
parentdc14a3de46ee08a28158a886b6abba2c4144f6cd (diff)
* Get garbage collection and cache population to work *properly*.
  Renamed `fstateRefs' to `fstateRequisites'.  The semantics of this
  function is that it returns a list of all paths necessary to realise
  a 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.  Also included are the paths of the
  expressions themselves.  Optionally, one can also include the
  requisites of successor expressions (to recycle intermediate
  results).

* `nix-switch' now distinguishes between an expression and its normal
  form.  Usually, only the normal form is registered as a root of the
  garbage collector.  With the `--source-root' flag, it will also
  register the original expression as a root.

* `nix-collect-garbage' now has a flag `--keep-successors' which
  causes successors not to be included in the list of garbage paths.

* `nix-collect-garbage' now has a flag `--invert' which will print all
  paths that should *not* be garbage collected.

-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'. */