* 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.
This commit is contained in:
parent
dc14a3de46
commit
8846465934
7 changed files with 85 additions and 29 deletions
|
@ -5,13 +5,27 @@ my $storedir = "@prefix@/store";
|
||||||
|
|
||||||
my %alive;
|
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>) {
|
while (<HASHES>) {
|
||||||
chomp;
|
chomp;
|
||||||
$alive{$_} = 1;
|
$alive{$_} = 1;
|
||||||
|
if ($invert) { print "$_\n"; };
|
||||||
}
|
}
|
||||||
close HASHES;
|
close HASHES;
|
||||||
|
|
||||||
|
exit 0 if ($invert);
|
||||||
|
|
||||||
opendir(DIR, $storedir) or die "cannot opendir $storedir: $!";
|
opendir(DIR, $storedir) or die "cannot opendir $storedir: $!";
|
||||||
my @names = readdir(DIR);
|
my @names = readdir(DIR);
|
||||||
closedir DIR;
|
closedir DIR;
|
||||||
|
|
|
@ -3,39 +3,56 @@
|
||||||
use strict;
|
use strict;
|
||||||
|
|
||||||
my $keep = 0;
|
my $keep = 0;
|
||||||
|
my $sourceroot = 0;
|
||||||
|
my $srcid;
|
||||||
|
|
||||||
if (scalar @ARGV > 0 && $ARGV[0] eq "--keep") {
|
foreach my $arg (@ARGV) {
|
||||||
shift @ARGV;
|
if ($arg eq "--keep") { $keep = 1; }
|
||||||
$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";
|
my $linkdir = "@localstatedir@/nix/links";
|
||||||
|
|
||||||
# Build the specified package, and all its dependencies.
|
# Build the specified package, and all its dependencies.
|
||||||
system "nix --install $hash";
|
my $nfid = `nix --install $srcid`;
|
||||||
if ($?) { die "`nix --install' failed"; }
|
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"; }
|
if ($?) { die "`nix --query --list' failed"; }
|
||||||
chomp $pkgdir;
|
chomp $pkgdir;
|
||||||
|
|
||||||
# Figure out a generation number.
|
# Figure out a generation number.
|
||||||
|
opendir(DIR, $linkdir);
|
||||||
my $nr = 0;
|
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";
|
my $link = "$linkdir/$nr";
|
||||||
|
|
||||||
# Create a symlink from $link to $pkgdir.
|
# Create a symlink from $link to $pkgdir.
|
||||||
symlink($pkgdir, $link) or die "cannot create $link: $!";
|
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.
|
# collection and the like.
|
||||||
my $hashfile = "$linkdir/$nr.hash";
|
my $idfile = "$linkdir/$nr.id";
|
||||||
open HASH, "> $hashfile" or die "cannot create $hashfile";
|
open ID, "> $idfile" or die "cannot create $idfile";
|
||||||
print HASH "$hash\n";
|
print ID "$nfid\n";
|
||||||
close HASH;
|
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";
|
my $current = "$linkdir/current";
|
||||||
|
|
||||||
|
@ -59,6 +76,7 @@ rename($tmplink, $current) or die "cannot rename $tmplink";
|
||||||
|
|
||||||
if (!$keep && defined $oldlink) {
|
if (!$keep && defined $oldlink) {
|
||||||
print "deleting old $oldlink\n";
|
print "deleting old $oldlink\n";
|
||||||
unlink($oldlink) == 1 || print "cannot delete $oldlink\n";
|
unlink($oldlink) == 1 or print "cannot delete $oldlink\n";
|
||||||
unlink("$oldlink.hash") == 1 || print "cannot delete $oldlink.hash\n";
|
unlink("$oldlink.id") == 1 or print "cannot delete $oldlink.id\n";
|
||||||
|
unlink("$oldlink-src.id");
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ nix.o: nix-help.txt.hh
|
||||||
install-data-local:
|
install-data-local:
|
||||||
$(INSTALL) -d $(localstatedir)/nix
|
$(INSTALL) -d $(localstatedir)/nix
|
||||||
$(INSTALL) -d $(localstatedir)/nix/links
|
$(INSTALL) -d $(localstatedir)/nix/links
|
||||||
|
ln -sf $(localstatedir)/nix/links/current $(prefix)/current
|
||||||
$(INSTALL) -d $(localstatedir)/log/nix
|
$(INSTALL) -d $(localstatedir)/log/nix
|
||||||
$(INSTALL) -d $(prefix)/store
|
$(INSTALL) -d $(prefix)/store
|
||||||
$(bindir)/nix --init
|
$(bindir)/nix --init
|
||||||
|
|
|
@ -26,7 +26,7 @@ Source selection for --install, --dump:
|
||||||
Query flags:
|
Query flags:
|
||||||
|
|
||||||
--list / -l: query the output paths (roots) of an fstate (default)
|
--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
|
--generators / -g: find expressions producing a subset of given ids
|
||||||
--expansion / -e: print a path containing id
|
--expansion / -e: print a path containing id
|
||||||
--graph: print a dot graph rooted at given ids
|
--graph: print a dot graph rooted at given ids
|
||||||
|
|
15
src/nix.cc
15
src/nix.cc
|
@ -95,18 +95,22 @@ FSId maybeNormalise(const FSId & id, bool normalise)
|
||||||
/* Perform various sorts of queries. */
|
/* Perform various sorts of queries. */
|
||||||
static void opQuery(Strings opFlags, Strings opArgs)
|
static void opQuery(Strings opFlags, Strings opArgs)
|
||||||
{
|
{
|
||||||
enum { qList, qRefs, qGenerators, qExpansion, qGraph
|
enum { qList, qRequisites, qGenerators, qExpansion, qGraph
|
||||||
} query = qList;
|
} query = qList;
|
||||||
bool normalise = false;
|
bool normalise = false;
|
||||||
|
bool includeExprs = true;
|
||||||
|
bool includeSuccessors = false;
|
||||||
|
|
||||||
for (Strings::iterator i = opFlags.begin();
|
for (Strings::iterator i = opFlags.begin();
|
||||||
i != opFlags.end(); i++)
|
i != opFlags.end(); i++)
|
||||||
if (*i == "--list" || *i == "-l") query = qList;
|
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 == "--generators" || *i == "-g") query = qGenerators;
|
||||||
else if (*i == "--expansion" || *i == "-e") query = qExpansion;
|
else if (*i == "--expansion" || *i == "-e") query = qExpansion;
|
||||||
else if (*i == "--graph") query = qGraph;
|
else if (*i == "--graph") query = qGraph;
|
||||||
else if (*i == "--normalise" || *i == "-n") normalise = true;
|
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);
|
else throw UsageError(format("unknown flag `%1%'") % *i);
|
||||||
|
|
||||||
switch (query) {
|
switch (query) {
|
||||||
|
@ -126,13 +130,14 @@ static void opQuery(Strings opFlags, Strings opArgs)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case qRefs: {
|
case qRequisites: {
|
||||||
StringSet paths;
|
StringSet paths;
|
||||||
for (Strings::iterator i = opArgs.begin();
|
for (Strings::iterator i = opArgs.begin();
|
||||||
i != opArgs.end(); i++)
|
i != opArgs.end(); i++)
|
||||||
{
|
{
|
||||||
Strings paths2 = fstateRefs(
|
Strings paths2 = fstateRequisites(
|
||||||
maybeNormalise(argToId(*i), normalise));
|
maybeNormalise(argToId(*i), normalise),
|
||||||
|
includeExprs, includeSuccessors);
|
||||||
paths.insert(paths2.begin(), paths2.end());
|
paths.insert(paths2.begin(), paths2.end());
|
||||||
}
|
}
|
||||||
for (StringSet::iterator i = paths.begin();
|
for (StringSet::iterator i = paths.begin();
|
||||||
|
|
|
@ -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));
|
FState fs = parseFState(termFromId(id));
|
||||||
|
|
||||||
|
@ -257,17 +258,28 @@ static void fstateRefsSet(const FSId & id, StringSet & paths)
|
||||||
else if (fs.type == FState::fsDerive) {
|
else if (fs.type == FState::fsDerive) {
|
||||||
for (FSIds::iterator i = fs.derive.inputs.begin();
|
for (FSIds::iterator i = fs.derive.inputs.begin();
|
||||||
i != fs.derive.inputs.end(); i++)
|
i != fs.derive.inputs.end(); i++)
|
||||||
fstateRefsSet(*i, paths);
|
fstateRequisitesSet(*i,
|
||||||
|
includeExprs, includeSuccessors, paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
else abort();
|
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;
|
StringSet paths;
|
||||||
fstateRefsSet(id, paths);
|
fstateRequisitesSet(id, includeExprs, includeSuccessors, paths);
|
||||||
return Strings(paths.begin(), paths.end());
|
return Strings(paths.begin(), paths.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,14 @@ void realiseSlice(const FSId & id, FSIdSet pending = FSIdSet());
|
||||||
fstate-expression. */
|
fstate-expression. */
|
||||||
Strings fstatePaths(const FSId & id);
|
Strings fstatePaths(const FSId & id);
|
||||||
|
|
||||||
/* Get the list of paths referenced by the given fstate-expression. */
|
/* Get the list of paths that are required to realise the given
|
||||||
Strings fstateRefs(const FSId & id);
|
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
|
/* Return the list of the ids of all known fstate-expressions whose
|
||||||
output ids are completely contained in `ids'. */
|
output ids are completely contained in `ids'. */
|
||||||
|
|
Loading…
Reference in a new issue