* `nix-store -qR' and friends: print the paths sorted topologically
under the references relation. This is useful for commands that want to copy paths to another Nix store in the right order.
This commit is contained in:
parent
881feb9698
commit
9da367b7d5
3 changed files with 12 additions and 40 deletions
|
@ -417,7 +417,7 @@ static void dfsVisit(const PathSet & paths, const Path & path,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static Paths topoSort(const PathSet & paths)
|
Paths topoSortPaths(const PathSet & paths)
|
||||||
{
|
{
|
||||||
Paths sorted;
|
Paths sorted;
|
||||||
PathSet visited;
|
PathSet visited;
|
||||||
|
@ -550,7 +550,7 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete,
|
||||||
which things can be deleted safely. */
|
which things can be deleted safely. */
|
||||||
/* !!! when we have multiple output paths per derivation, this
|
/* !!! when we have multiple output paths per derivation, this
|
||||||
will not work anymore because we get cycles. */
|
will not work anymore because we get cycles. */
|
||||||
Paths storePaths = topoSort(storePathSet);
|
Paths storePaths = topoSortPaths(storePathSet);
|
||||||
|
|
||||||
/* Try to delete store paths in the topologically sorted order. */
|
/* Try to delete store paths in the topologically sorted order. */
|
||||||
for (Paths::iterator i = storePaths.begin(); i != storePaths.end(); ++i) {
|
for (Paths::iterator i = storePaths.begin(); i != storePaths.end(); ++i) {
|
||||||
|
|
|
@ -242,6 +242,11 @@ Path addPermRoot(const Path & storePath, const Path & gcRoot,
|
||||||
bool indirect, bool allowOutsideRootsDir = false);
|
bool indirect, bool allowOutsideRootsDir = false);
|
||||||
|
|
||||||
|
|
||||||
|
/* Sort a set of paths topologically under the references relation.
|
||||||
|
If p refers to q, then p follows q in this list. */
|
||||||
|
Paths topoSortPaths(const PathSet & paths);
|
||||||
|
|
||||||
|
|
||||||
/* For now, there is a single global store API object, but we'll
|
/* For now, there is a single global store API object, but we'll
|
||||||
purify that in the future. */
|
purify that in the future. */
|
||||||
extern boost::shared_ptr<StoreAPI> store;
|
extern boost::shared_ptr<StoreAPI> store;
|
||||||
|
|
|
@ -210,14 +210,6 @@ static Path maybeUseOutput(const Path & storePath, bool useOutput, bool forceRea
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void printPathSet(const PathSet & paths)
|
|
||||||
{
|
|
||||||
for (PathSet::iterator i = paths.begin();
|
|
||||||
i != paths.end(); ++i)
|
|
||||||
cout << format("%s\n") % *i;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Some code to print a tree representation of a derivation dependency
|
/* Some code to print a tree representation of a derivation dependency
|
||||||
graph. Topological sorting is used to keep the tree relatively
|
graph. Topological sorting is used to keep the tree relatively
|
||||||
flat. */
|
flat. */
|
||||||
|
@ -227,34 +219,6 @@ const string treeLine = "| ";
|
||||||
const string treeNull = " ";
|
const string treeNull = " ";
|
||||||
|
|
||||||
|
|
||||||
static void dfsVisit(const PathSet & paths, const Path & path,
|
|
||||||
PathSet & visited, Paths & sorted)
|
|
||||||
{
|
|
||||||
if (visited.find(path) != visited.end()) return;
|
|
||||||
visited.insert(path);
|
|
||||||
|
|
||||||
PathSet closure;
|
|
||||||
computeFSClosure(path, closure);
|
|
||||||
|
|
||||||
for (PathSet::iterator i = closure.begin();
|
|
||||||
i != closure.end(); ++i)
|
|
||||||
if (*i != path && paths.find(*i) != paths.end())
|
|
||||||
dfsVisit(paths, *i, visited, sorted);
|
|
||||||
|
|
||||||
sorted.push_front(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Paths topoSort(const PathSet & paths)
|
|
||||||
{
|
|
||||||
Paths sorted;
|
|
||||||
PathSet visited;
|
|
||||||
for (PathSet::const_iterator i = paths.begin(); i != paths.end(); ++i)
|
|
||||||
dfsVisit(paths, *i, visited, sorted);
|
|
||||||
return sorted;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void printTree(const Path & path,
|
static void printTree(const Path & path,
|
||||||
const string & firstPad, const string & tailPad, PathSet & done)
|
const string & firstPad, const string & tailPad, PathSet & done)
|
||||||
{
|
{
|
||||||
|
@ -279,7 +243,7 @@ static void printTree(const Path & path,
|
||||||
closure(B). That is, if derivation A is an (possibly indirect)
|
closure(B). That is, if derivation A is an (possibly indirect)
|
||||||
input of B, then A is printed first. This has the effect of
|
input of B, then A is printed first. This has the effect of
|
||||||
flattening the tree, preventing deeply nested structures. */
|
flattening the tree, preventing deeply nested structures. */
|
||||||
Paths sorted = topoSort(references);
|
Paths sorted = topoSortPaths(references);
|
||||||
reverse(sorted.begin(), sorted.end());
|
reverse(sorted.begin(), sorted.end());
|
||||||
|
|
||||||
for (Paths::iterator i = sorted.begin(); i != sorted.end(); ++i) {
|
for (Paths::iterator i = sorted.begin(); i != sorted.end(); ++i) {
|
||||||
|
@ -355,7 +319,10 @@ static void opQuery(Strings opFlags, Strings opArgs)
|
||||||
else if (query == qReferrers) store->queryReferrers(path, paths);
|
else if (query == qReferrers) store->queryReferrers(path, paths);
|
||||||
else if (query == qReferrersClosure) computeFSClosure(path, paths, true);
|
else if (query == qReferrersClosure) computeFSClosure(path, paths, true);
|
||||||
}
|
}
|
||||||
printPathSet(paths);
|
Paths sorted = topoSortPaths(paths);
|
||||||
|
for (Paths::reverse_iterator i = sorted.rbegin();
|
||||||
|
i != sorted.rend(); ++i)
|
||||||
|
cout << format("%s\n") % *i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue