* Support multiple outputs in nix-store (specifically the ‘--query’

and ‘--realise’ actions).
This commit is contained in:
Eelco Dolstra 2011-12-30 17:25:19 +00:00
parent a71d02440b
commit 93b56acb2d

View file

@ -50,26 +50,30 @@ static Path useDeriver(Path path)
} }
/* Realisation the given path. For a derivation that means build it; /* Realise the given path. For a derivation that means build it; for
for other paths it means ensure their validity. */ other paths it means ensure their validity. */
static Path realisePath(const Path & path) static PathSet realisePath(const Path & path)
{ {
if (isDerivation(path)) { if (isDerivation(path)) {
PathSet paths; store->buildDerivations(singleton<PathSet>(path));
paths.insert(path); Derivation drv = derivationFromPath(*store, path);
store->buildDerivations(paths);
Path outPath = findOutput(derivationFromPath(*store, path), "out");
if (gcRoot == "") PathSet outputs;
printGCWarning(); foreach (DerivationOutputs::iterator, i, drv.outputs) {
else Path outPath = i->second.path;
outPath = addPermRoot(*store, outPath, if (gcRoot == "")
makeRootName(gcRoot, rootNr), indirectRoot); printGCWarning();
else
outPath = addPermRoot(*store, outPath,
makeRootName(gcRoot, rootNr), indirectRoot);
outputs.insert(outPath);
}
return outputs;
}
return outPath; else {
} else {
store->ensurePath(path); store->ensurePath(path);
return path; return singleton<PathSet>(path);
} }
} }
@ -96,8 +100,11 @@ static void opRealise(Strings opFlags, Strings opArgs)
if (isDerivation(*i)) drvPaths.insert(*i); if (isDerivation(*i)) drvPaths.insert(*i);
store->buildDerivations(drvPaths); store->buildDerivations(drvPaths);
foreach (Strings::iterator, i, opArgs) foreach (Strings::iterator, i, opArgs) {
cout << format("%1%\n") % realisePath(*i); PathSet paths = realisePath(*i);
foreach (PathSet::iterator, j, paths)
cout << format("%1%\n") % *j;
}
} }
@ -157,14 +164,17 @@ static void opPrintFixedPath(Strings opFlags, Strings opArgs)
} }
static Path maybeUseOutput(const Path & storePath, bool useOutput, bool forceRealise) static PathSet maybeUseOutputs(const Path & storePath, bool useOutput, bool forceRealise)
{ {
if (forceRealise) realisePath(storePath); if (forceRealise) realisePath(storePath);
if (useOutput && isDerivation(storePath)) { if (useOutput && isDerivation(storePath)) {
Derivation drv = derivationFromPath(*store, storePath); Derivation drv = derivationFromPath(*store, storePath);
return findOutput(drv, "out"); PathSet outputs;
foreach (DerivationOutputs::iterator, i, drv.outputs)
outputs.insert(i->second.path);
return outputs;
} }
else return storePath; else return singleton<PathSet>(storePath);
} }
@ -257,7 +267,8 @@ static void opQuery(Strings opFlags, Strings opArgs)
*i = followLinksToStorePath(*i); *i = followLinksToStorePath(*i);
if (forceRealise) realisePath(*i); if (forceRealise) realisePath(*i);
Derivation drv = derivationFromPath(*store, *i); Derivation drv = derivationFromPath(*store, *i);
cout << format("%1%\n") % findOutput(drv, "out"); foreach (DerivationOutputs::iterator, j, drv.outputs)
cout << format("%1%\n") % j->second.path;
} }
break; break;
} }
@ -268,11 +279,13 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qReferrersClosure: { case qReferrersClosure: {
PathSet paths; PathSet paths;
foreach (Strings::iterator, i, opArgs) { foreach (Strings::iterator, i, opArgs) {
Path path = maybeUseOutput(followLinksToStorePath(*i), useOutput, forceRealise); PathSet ps = maybeUseOutputs(followLinksToStorePath(*i), useOutput, forceRealise);
if (query == qRequisites) computeFSClosure(*store, path, paths, false, includeOutputs); foreach (PathSet::iterator, j, ps) {
else if (query == qReferences) store->queryReferences(path, paths); if (query == qRequisites) computeFSClosure(*store, *j, paths, false, includeOutputs);
else if (query == qReferrers) store->queryReferrers(path, paths); else if (query == qReferences) store->queryReferences(*j, paths);
else if (query == qReferrersClosure) computeFSClosure(*store, path, paths, true); else if (query == qReferrers) store->queryReferrers(*j, paths);
else if (query == qReferrersClosure) computeFSClosure(*store, *j, paths, true);
}
} }
Paths sorted = topoSortPaths(*store, paths); Paths sorted = topoSortPaths(*store, paths);
for (Paths::reverse_iterator i = sorted.rbegin(); for (Paths::reverse_iterator i = sorted.rbegin();
@ -304,13 +317,15 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qHash: case qHash:
case qSize: case qSize:
foreach (Strings::iterator, i, opArgs) { foreach (Strings::iterator, i, opArgs) {
Path path = maybeUseOutput(followLinksToStorePath(*i), useOutput, forceRealise); PathSet paths = maybeUseOutputs(followLinksToStorePath(*i), useOutput, forceRealise);
ValidPathInfo info = store->queryPathInfo(path); foreach (PathSet::iterator, j, paths) {
if (query == qHash) { ValidPathInfo info = store->queryPathInfo(*j);
assert(info.hash.type == htSHA256); if (query == qHash) {
cout << format("sha256:%1%\n") % printHash32(info.hash); assert(info.hash.type == htSHA256);
} else if (query == qSize) cout << format("sha256:%1%\n") % printHash32(info.hash);
cout << format("%1%\n") % info.narSize; } else if (query == qSize)
cout << format("%1%\n") % info.narSize;
}
} }
break; break;
@ -323,16 +338,20 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qGraph: { case qGraph: {
PathSet roots; PathSet roots;
foreach (Strings::iterator, i, opArgs) foreach (Strings::iterator, i, opArgs) {
roots.insert(maybeUseOutput(followLinksToStorePath(*i), useOutput, forceRealise)); PathSet paths = maybeUseOutputs(followLinksToStorePath(*i), useOutput, forceRealise);
roots.insert(paths.begin(), paths.end());
}
printDotGraph(roots); printDotGraph(roots);
break; break;
} }
case qXml: { case qXml: {
PathSet roots; PathSet roots;
foreach (Strings::iterator, i, opArgs) foreach (Strings::iterator, i, opArgs) {
roots.insert(maybeUseOutput(followLinksToStorePath(*i), useOutput, forceRealise)); PathSet paths = maybeUseOutputs(followLinksToStorePath(*i), useOutput, forceRealise);
roots.insert(paths.begin(), paths.end());
}
printXmlGraph(roots); printXmlGraph(roots);
break; break;
} }
@ -345,10 +364,11 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qRoots: { case qRoots: {
PathSet referrers; PathSet referrers;
foreach (Strings::iterator, i, opArgs) foreach (Strings::iterator, i, opArgs) {
computeFSClosure(*store, PathSet paths = maybeUseOutputs(followLinksToStorePath(*i), useOutput, forceRealise);
maybeUseOutput(followLinksToStorePath(*i), useOutput, forceRealise), foreach (PathSet::iterator, j, paths)
referrers, true); computeFSClosure(*store, *j, referrers, true);
}
Roots roots = store->findRoots(); Roots roots = store->findRoots();
foreach (Roots::iterator, i, roots) foreach (Roots::iterator, i, roots)
if (referrers.find(i->second) != referrers.end()) if (referrers.find(i->second) != referrers.end())