* Eliminate all uses of the global variable ‘store’ from libstore.

This should also fix:

    nix-instantiate: ./../boost/shared_ptr.hpp:254: T* boost::shared_ptr<T>::operator->() const [with T = nix::StoreAPI]: Assertion `px != 0' failed.

  which was caused by hashDerivationModulo() calling the ‘store’
  object (during store upgrades) before openStore() assigned it.
This commit is contained in:
Eelco Dolstra 2011-08-31 21:11:50 +00:00
parent 5bcdc7e351
commit 93227ff65c
15 changed files with 95 additions and 89 deletions

View file

@ -357,7 +357,7 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v)
runs. */
if (path.at(0) == '=') {
path = string(path, 1);
PathSet refs; computeFSClosure(path, refs);
PathSet refs; computeFSClosure(*store, path, refs);
foreach (PathSet::iterator, j, refs) {
drv.inputSrcs.insert(*j);
if (isDerivation(*j))
@ -433,7 +433,7 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v)
/* Use the masked derivation expression to compute the output
path. */
Hash h = hashDerivationModulo(drv);
Hash h = hashDerivationModulo(*store, drv);
foreach (DerivationOutputs::iterator, i, drv.outputs)
if (i->second.path == "") {
@ -444,7 +444,7 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v)
}
/* Write the resulting term into the Nix store directory. */
Path drvPath = writeDerivation(drv, drvName);
Path drvPath = writeDerivation(*store, drv, drvName);
printMsg(lvlChatty, format("instantiated `%1%' -> `%2%'")
% drvName % drvPath);
@ -452,7 +452,7 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v)
/* Optimisation, but required in read-only mode! because in that
case we don't actually write store derivations, so we can't
read them later. */
drvHashes[drvPath] = hashDerivationModulo(drv);
drvHashes[drvPath] = hashDerivationModulo(*store, drv);
state.mkAttrs(v, 1 + drv.outputs.size());
mkString(*state.allocAttr(v, state.sDrvPath), drvPath, singleton<PathSet>("=" + drvPath));

View file

@ -52,11 +52,11 @@ void printGCWarning()
}
void printMissing(const PathSet & paths)
void printMissing(StoreAPI & store, const PathSet & paths)
{
unsigned long long downloadSize, narSize;
PathSet willBuild, willSubstitute, unknown;
queryMissing(paths, willBuild, willSubstitute, unknown, downloadSize, narSize);
queryMissing(store, paths, willBuild, willSubstitute, unknown, downloadSize, narSize);
if (!willBuild.empty()) {
printMsg(lvlInfo, format("these derivations will be built:"));

View file

@ -24,11 +24,13 @@ namespace nix {
MakeError(UsageError, nix::Error);
class StoreAPI;
/* Ugh. No better place to put this. */
Path makeRootName(const Path & gcRoot, int & counter);
void printGCWarning();
void printMissing(const PathSet & paths);
void printMissing(StoreAPI & store, const PathSet & paths);
template<class N> N getIntArg(const string & opt,
Strings::iterator & i, const Strings::iterator & end)

View file

@ -934,7 +934,7 @@ void DerivationGoal::haveDerivation()
assert(worker.store.isValidPath(drvPath));
/* Get the derivation. */
drv = derivationFromPath(drvPath);
drv = derivationFromPath(worker.store, drvPath);
foreach (DerivationOutputs::iterator, i, drv.outputs)
worker.store.addTempRoot(i->second.path);
@ -1030,10 +1030,10 @@ void DerivationGoal::inputsRealised()
`*i' as input paths. Only add the closures of output paths
that are specified as inputs. */
assert(worker.store.isValidPath(i->first));
Derivation inDrv = derivationFromPath(i->first);
Derivation inDrv = derivationFromPath(worker.store, i->first);
foreach (StringSet::iterator, j, i->second)
if (inDrv.outputs.find(*j) != inDrv.outputs.end())
computeFSClosure(inDrv.outputs[*j].path, inputPaths);
computeFSClosure(worker.store, inDrv.outputs[*j].path, inputPaths);
else
throw Error(
format("derivation `%1%' requires non-existent output `%2%' from input derivation `%3%'")
@ -1042,7 +1042,7 @@ void DerivationGoal::inputsRealised()
/* Second, the input sources. */
foreach (PathSet::iterator, i, drv.inputSrcs)
computeFSClosure(*i, inputPaths);
computeFSClosure(worker.store, *i, inputPaths);
debug(format("added input paths %1%") % showPaths(inputPaths));
@ -1399,7 +1399,7 @@ HookReply DerivationGoal::tryBuildHook()
list it since the remote system *probably* already has it.) */
PathSet allInputs;
allInputs.insert(inputPaths.begin(), inputPaths.end());
computeFSClosure(drvPath, allInputs);
computeFSClosure(worker.store, drvPath, allInputs);
string s;
foreach (PathSet::iterator, i, allInputs) s += *i + " ";
@ -1545,14 +1545,14 @@ void DerivationGoal::startBuilder()
like passing all build-time dependencies of some path to a
derivation that builds a NixOS DVD image. */
PathSet paths, paths2;
computeFSClosure(storePath, paths);
computeFSClosure(worker.store, storePath, paths);
paths2 = paths;
foreach (PathSet::iterator, j, paths2) {
if (isDerivation(*j)) {
Derivation drv = derivationFromPath(*j);
Derivation drv = derivationFromPath(worker.store, *j);
foreach (DerivationOutputs::iterator, k, drv.outputs)
computeFSClosure(k->second.path, paths);
computeFSClosure(worker.store, k->second.path, paths);
}
}

View file

@ -26,7 +26,8 @@ void DerivationOutput::parseHashInfo(bool & recursive, HashType & hashType, Hash
}
Path writeDerivation(const Derivation & drv, const string & name)
Path writeDerivation(StoreAPI & store,
const Derivation & drv, const string & name)
{
PathSet references;
references.insert(drv.inputSrcs.begin(), drv.inputSrcs.end());
@ -39,7 +40,7 @@ Path writeDerivation(const Derivation & drv, const string & name)
string contents = unparseDerivation(drv);
return readOnlyMode
? computeStorePathForText(suffix, contents, references)
: store->addTextToStore(suffix, contents, references);
: store.addTextToStore(suffix, contents, references);
}
@ -221,7 +222,7 @@ DrvHashes drvHashes;
paths have been replaced by the result of a recursive call to this
function, and that for fixed-output derivations we return a hash of
its output path. */
Hash hashDerivationModulo(Derivation drv)
Hash hashDerivationModulo(StoreAPI & store, Derivation drv)
{
/* Return a fixed hash for fixed-output derivations. */
if (isFixedOutputDrv(drv)) {
@ -238,8 +239,8 @@ Hash hashDerivationModulo(Derivation drv)
foreach (DerivationInputs::const_iterator, i, drv.inputDrvs) {
Hash h = drvHashes[i->first];
if (h.type == htUnknown) {
Derivation drv2 = derivationFromPath(i->first);
h = hashDerivationModulo(drv2);
Derivation drv2 = derivationFromPath(store, i->first);
h = hashDerivationModulo(store, drv2);
drvHashes[i->first] = h;
}
inputs2[printHash(h)] = i->second;

View file

@ -53,8 +53,12 @@ struct Derivation
};
class StoreAPI;
/* Write a derivation to the Nix store, and return its path. */
Path writeDerivation(const Derivation & drv, const string & name);
Path writeDerivation(StoreAPI & store,
const Derivation & drv, const string & name);
/* Parse a derivation. */
Derivation parseDerivation(const string & s);
@ -69,7 +73,7 @@ bool isDerivation(const string & fileName);
/* Return true iff this is a fixed-output derivation. */
bool isFixedOutputDrv(const Derivation & drv);
Hash hashDerivationModulo(Derivation drv);
Hash hashDerivationModulo(StoreAPI & store, Derivation drv);
/* Memoisation of hashDerivationModulo(). */
typedef std::map<Path, Hash> DrvHashes;

View file

@ -90,8 +90,8 @@ void LocalStore::addIndirectRoot(const Path & path)
}
Path addPermRoot(const Path & _storePath, const Path & _gcRoot,
bool indirect, bool allowOutsideRootsDir)
Path addPermRoot(StoreAPI & store, const Path & _storePath,
const Path & _gcRoot, bool indirect, bool allowOutsideRootsDir)
{
Path storePath(canonPath(_storePath));
Path gcRoot(canonPath(_gcRoot));
@ -104,7 +104,7 @@ Path addPermRoot(const Path & _storePath, const Path & _gcRoot,
if (indirect) {
createSymlink(gcRoot, storePath, true);
store->addIndirectRoot(gcRoot);
store.addIndirectRoot(gcRoot);
}
else {
@ -127,7 +127,7 @@ Path addPermRoot(const Path & _storePath, const Path & _gcRoot,
check if the root is in a directory in or linked from the
gcroots directory. */
if (queryBoolSetting("gc-check-reachability", false)) {
Roots roots = store->findRoots();
Roots roots = store.findRoots();
if (roots.find(gcRoot) == roots.end())
printMsg(lvlError,
format(
@ -139,7 +139,7 @@ Path addPermRoot(const Path & _storePath, const Path & _gcRoot,
/* Grab the global GC root, causing us to block while a GC is in
progress. This prevents the set of permanent roots from
increasing while a GC is in progress. */
store->syncWithGC();
store.syncWithGC();
return gcRoot;
}
@ -275,8 +275,8 @@ static void readTempRoots(PathSet & tempRoots, FDs & fds)
}
static void findRoots(const Path & path, bool recurseSymlinks,
bool deleteStale, Roots & roots)
static void findRoots(StoreAPI & store, const Path & path,
bool recurseSymlinks, bool deleteStale, Roots & roots)
{
try {
@ -289,7 +289,7 @@ static void findRoots(const Path & path, bool recurseSymlinks,
if (S_ISDIR(st.st_mode)) {
Strings names = readDirectory(path);
foreach (Strings::iterator, i, names)
findRoots(path + "/" + *i, recurseSymlinks, deleteStale, roots);
findRoots(store, path + "/" + *i, recurseSymlinks, deleteStale, roots);
}
else if (S_ISLNK(st.st_mode)) {
@ -299,7 +299,7 @@ static void findRoots(const Path & path, bool recurseSymlinks,
debug(format("found root `%1%' in `%2%'")
% target % path);
Path storePath = toStorePath(target);
if (store->isValidPath(storePath))
if (store.isValidPath(storePath))
roots[path] = storePath;
else
printMsg(lvlInfo, format("skipping invalid root from `%1%' to `%2%'")
@ -308,7 +308,7 @@ static void findRoots(const Path & path, bool recurseSymlinks,
else if (recurseSymlinks) {
if (pathExists(target))
findRoots(target, false, deleteStale, roots);
findRoots(store, target, false, deleteStale, roots);
else if (deleteStale) {
printMsg(lvlInfo, format("removing stale link from `%1%' to `%2%'") % path % target);
/* Note that we only delete when recursing, i.e.,
@ -331,22 +331,22 @@ static void findRoots(const Path & path, bool recurseSymlinks,
}
static Roots findRoots(bool deleteStale)
static Roots findRoots(StoreAPI & store, bool deleteStale)
{
Roots roots;
Path rootsDir = canonPath((format("%1%/%2%") % nixStateDir % gcRootsDir).str());
findRoots(rootsDir, true, deleteStale, roots);
findRoots(store, rootsDir, true, deleteStale, roots);
return roots;
}
Roots LocalStore::findRoots()
{
return nix::findRoots(false);
return nix::findRoots(*this, false);
}
static void addAdditionalRoots(PathSet & roots)
static void addAdditionalRoots(StoreAPI & store, PathSet & roots)
{
Path rootFinder = getEnv("NIX_ROOT_FINDER",
nixLibexecDir + "/nix/find-runtime-roots.pl");
@ -362,7 +362,7 @@ static void addAdditionalRoots(PathSet & roots)
foreach (Strings::iterator, i, paths) {
if (isInStore(*i)) {
Path path = toStorePath(*i);
if (roots.find(path) == roots.end() && store->isValidPath(path)) {
if (roots.find(path) == roots.end() && store.isValidPath(path)) {
debug(format("got additional root `%1%'") % path);
roots.insert(path);
}
@ -371,32 +371,32 @@ static void addAdditionalRoots(PathSet & roots)
}
static void dfsVisit(const PathSet & paths, const Path & path,
PathSet & visited, Paths & sorted)
static void dfsVisit(StoreAPI & store, const PathSet & paths,
const Path & path, PathSet & visited, Paths & sorted)
{
if (visited.find(path) != visited.end()) return;
visited.insert(path);
PathSet references;
if (store->isValidPath(path))
store->queryReferences(path, references);
if (store.isValidPath(path))
store.queryReferences(path, references);
foreach (PathSet::iterator, i, references)
/* Don't traverse into paths that don't exist. That can
happen due to substitutes for non-existent paths. */
if (*i != path && paths.find(*i) != paths.end())
dfsVisit(paths, *i, visited, sorted);
dfsVisit(store, paths, *i, visited, sorted);
sorted.push_front(path);
}
Paths topoSortPaths(const PathSet & paths)
Paths topoSortPaths(StoreAPI & store, const PathSet & paths)
{
Paths sorted;
PathSet visited;
foreach (PathSet::const_iterator, i, paths)
dfsVisit(paths, *i, visited, sorted);
dfsVisit(store, paths, *i, visited, sorted);
return sorted;
}
@ -582,7 +582,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
/* Find the roots. Since we've grabbed the GC lock, the set of
permanent roots cannot increase now. */
printMsg(lvlError, format("finding garbage collector roots..."));
Roots rootMap = options.ignoreLiveness ? Roots() : nix::findRoots(true);
Roots rootMap = options.ignoreLiveness ? Roots() : nix::findRoots(*this, true);
foreach (Roots::iterator, i, rootMap) state.roots.insert(i->second);
@ -591,7 +591,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
to add running programs to the set of roots (to prevent them
from being garbage collected). */
if (!options.ignoreLiveness)
addAdditionalRoots(state.roots);
addAdditionalRoots(*this, state.roots);
/* Read the temporary roots. This acquires read locks on all
per-process temporary root files. So after this point no paths

View file

@ -497,7 +497,7 @@ void LocalStore::checkDerivationOutputs(const Path & drvPath, const Derivation &
drvCopy.env[i->first] = "";
}
Hash h = hashDerivationModulo(drvCopy);
Hash h = hashDerivationModulo(*this, drvCopy);
foreach (DerivationOutputs::const_iterator, i, drv.outputs) {
Path outPath = makeOutputPath(i->first, h, drvName);

View file

@ -6,15 +6,15 @@
namespace nix {
Derivation derivationFromPath(const Path & drvPath)
Derivation derivationFromPath(StoreAPI & store, const Path & drvPath)
{
assertStorePath(drvPath);
store->ensurePath(drvPath);
store.ensurePath(drvPath);
return parseDerivation(readFile(drvPath));
}
void computeFSClosure(const Path & storePath,
void computeFSClosure(StoreAPI & store, const Path & storePath,
PathSet & paths, bool flipDirection, bool includeOutputs)
{
if (paths.find(storePath) != paths.end()) return;
@ -22,19 +22,19 @@ void computeFSClosure(const Path & storePath,
PathSet references;
if (flipDirection)
store->queryReferrers(storePath, references);
store.queryReferrers(storePath, references);
else
store->queryReferences(storePath, references);
store.queryReferences(storePath, references);
if (includeOutputs && isDerivation(storePath)) {
PathSet outputs = store->queryDerivationOutputs(storePath);
PathSet outputs = store.queryDerivationOutputs(storePath);
foreach (PathSet::iterator, i, outputs)
if (store->isValidPath(*i))
computeFSClosure(*i, paths, flipDirection, true);
if (store.isValidPath(*i))
computeFSClosure(store, *i, paths, flipDirection, true);
}
foreach (PathSet::iterator, i, references)
computeFSClosure(*i, paths, flipDirection, includeOutputs);
computeFSClosure(store, *i, paths, flipDirection, includeOutputs);
}
@ -46,7 +46,7 @@ Path findOutput(const Derivation & drv, string id)
}
void queryMissing(const PathSet & targets,
void queryMissing(StoreAPI & store, const PathSet & targets,
PathSet & willBuild, PathSet & willSubstitute, PathSet & unknown,
unsigned long long & downloadSize, unsigned long long & narSize)
{
@ -61,15 +61,15 @@ void queryMissing(const PathSet & targets,
done.insert(p);
if (isDerivation(p)) {
if (!store->isValidPath(p)) {
if (!store.isValidPath(p)) {
unknown.insert(p);
continue;
}
Derivation drv = derivationFromPath(p);
Derivation drv = derivationFromPath(store, p);
bool mustBuild = false;
foreach (DerivationOutputs::iterator, i, drv.outputs)
if (!store->isValidPath(i->second.path) && !store->hasSubstitutes(i->second.path))
if (!store.isValidPath(i->second.path) && !store.hasSubstitutes(i->second.path))
mustBuild = true;
if (mustBuild) {
@ -83,9 +83,9 @@ void queryMissing(const PathSet & targets,
}
else {
if (store->isValidPath(p)) continue;
if (store.isValidPath(p)) continue;
SubstitutablePathInfo info;
if (store->querySubstitutablePathInfo(p, info)) {
if (store.querySubstitutablePathInfo(p, info)) {
willSubstitute.insert(p);
downloadSize += info.downloadSize;
narSize += info.narSize;

View file

@ -9,7 +9,7 @@ namespace nix {
/* Read a derivation, after ensuring its existence through
ensurePath(). */
Derivation derivationFromPath(const Path & drvPath);
Derivation derivationFromPath(StoreAPI & store, const Path & drvPath);
/* Place in `paths' the set of all store paths in the file system
closure of `storePath'; that is, all paths than can be directly or
@ -18,7 +18,7 @@ Derivation derivationFromPath(const Path & drvPath);
`storePath' is returned; that is, the closures under the
`referrers' relation instead of the `references' relation is
returned. */
void computeFSClosure(const Path & storePath,
void computeFSClosure(StoreAPI & store, const Path & storePath,
PathSet & paths, bool flipDirection = false,
bool includeOutputs = false);
@ -29,7 +29,7 @@ Path findOutput(const Derivation & drv, string id);
/* Given a set of paths that are to be built, return the set of
derivations that will be built, and the set of output paths that
will be substituted. */
void queryMissing(const PathSet & targets,
void queryMissing(StoreAPI & store, const PathSet & targets,
PathSet & willBuild, PathSet & willSubstitute, PathSet & unknown,
unsigned long long & downloadSize, unsigned long long & narSize);

View file

@ -314,13 +314,13 @@ void removeTempRoots();
/* Register a permanent GC root. */
Path addPermRoot(const Path & storePath, const Path & gcRoot,
bool indirect, bool allowOutsideRootsDir = false);
Path addPermRoot(StoreAPI & store, const Path & storePath,
const Path & gcRoot, 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);
Paths topoSortPaths(StoreAPI & store, const PathSet & paths);
/* For now, there is a single global store API object, but we'll

View file

@ -381,7 +381,7 @@ static void queryInstSources(EvalState & state,
if (isDerivation(path)) {
elem.setDrvPath(path);
elem.setOutPath(findOutput(derivationFromPath(path), "out"));
elem.setOutPath(findOutput(derivationFromPath(*store, path), "out"));
if (name.size() >= drvExtension.size() &&
string(name, name.size() - drvExtension.size()) == drvExtension)
name = string(name, 0, name.size() - drvExtension.size());
@ -430,7 +430,7 @@ static void printMissing(EvalState & state, const DrvInfos & elems)
targets.insert(i->queryOutPath(state));
}
printMissing(targets);
printMissing(*store, targets);
}
@ -693,12 +693,12 @@ static void opSet(Globals & globals,
if (drv.queryDrvPath(globals.state) != "") {
PathSet paths = singleton<PathSet>(drv.queryDrvPath(globals.state));
printMissing(paths);
printMissing(*store, paths);
if (globals.dryRun) return;
store->buildDerivations(paths);
}
else {
printMissing(singleton<PathSet>(drv.queryOutPath(globals.state)));
printMissing(*store, singleton<PathSet>(drv.queryOutPath(globals.state)));
if (globals.dryRun) return;
store->ensurePath(drv.queryOutPath(globals.state));
}

View file

@ -91,7 +91,7 @@ Path createGeneration(Path profile, Path outPath)
user environment etc. we've just built. */
Path generation;
makeName(profile, num + 1, generation);
addPermRoot(outPath, generation, false, true);
addPermRoot(*store, outPath, generation, false, true);
return generation;
}

View file

@ -64,9 +64,8 @@ void processExpr(EvalState & state, const Strings & attrPaths,
if (gcRoot == "")
printGCWarning();
else
drvPath = addPermRoot(drvPath,
makeRootName(gcRoot, rootNr),
indirectRoot);
drvPath = addPermRoot(*store, drvPath,
makeRootName(gcRoot, rootNr), indirectRoot);
std::cout << format("%1%\n") % drvPath;
}
}

View file

@ -58,14 +58,13 @@ static Path realisePath(const Path & path)
PathSet paths;
paths.insert(path);
store->buildDerivations(paths);
Path outPath = findOutput(derivationFromPath(path), "out");
Path outPath = findOutput(derivationFromPath(*store, path), "out");
if (gcRoot == "")
printGCWarning();
else
outPath = addPermRoot(outPath,
makeRootName(gcRoot, rootNr),
indirectRoot);
outPath = addPermRoot(*store, outPath,
makeRootName(gcRoot, rootNr), indirectRoot);
return outPath;
} else {
@ -87,7 +86,7 @@ static void opRealise(Strings opFlags, Strings opArgs)
foreach (Strings::iterator, i, opArgs)
*i = followLinksToStorePath(*i);
printMissing(PathSet(opArgs.begin(), opArgs.end()));
printMissing(*store, PathSet(opArgs.begin(), opArgs.end()));
if (dryRun) return;
@ -170,7 +169,7 @@ static Path maybeUseOutput(const Path & storePath, bool useOutput, bool forceRea
{
if (forceRealise) realisePath(storePath);
if (useOutput && isDerivation(storePath)) {
Derivation drv = derivationFromPath(storePath);
Derivation drv = derivationFromPath(*store, storePath);
return findOutput(drv, "out");
}
else return storePath;
@ -210,7 +209,7 @@ static void printTree(const Path & path,
closure(B). That is, if derivation A is an (possibly indirect)
input of B, then A is printed first. This has the effect of
flattening the tree, preventing deeply nested structures. */
Paths sorted = topoSortPaths(references);
Paths sorted = topoSortPaths(*store, references);
reverse(sorted.begin(), sorted.end());
for (Paths::iterator i = sorted.begin(); i != sorted.end(); ++i) {
@ -265,7 +264,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
foreach (Strings::iterator, i, opArgs) {
*i = followLinksToStorePath(*i);
if (forceRealise) realisePath(*i);
Derivation drv = derivationFromPath(*i);
Derivation drv = derivationFromPath(*store, *i);
cout << format("%1%\n") % findOutput(drv, "out");
}
break;
@ -278,12 +277,12 @@ static void opQuery(Strings opFlags, Strings opArgs)
PathSet paths;
foreach (Strings::iterator, i, opArgs) {
Path path = maybeUseOutput(followLinksToStorePath(*i), useOutput, forceRealise);
if (query == qRequisites) computeFSClosure(path, paths, false, includeOutputs);
if (query == qRequisites) computeFSClosure(*store, path, paths, false, includeOutputs);
else if (query == qReferences) store->queryReferences(path, paths);
else if (query == qReferrers) store->queryReferrers(path, paths);
else if (query == qReferrersClosure) computeFSClosure(path, paths, true);
else if (query == qReferrersClosure) computeFSClosure(*store, path, paths, true);
}
Paths sorted = topoSortPaths(paths);
Paths sorted = topoSortPaths(*store, paths);
for (Paths::reverse_iterator i = sorted.rbegin();
i != sorted.rend(); ++i)
cout << format("%s\n") % *i;
@ -301,7 +300,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qBinding:
foreach (Strings::iterator, i, opArgs) {
Path path = useDeriver(followLinksToStorePath(*i));
Derivation drv = derivationFromPath(path);
Derivation drv = derivationFromPath(*store, path);
StringPairs::iterator j = drv.env.find(bindingName);
if (j == drv.env.end())
throw Error(format("derivation `%1%' has no environment binding named `%2%'")
@ -355,7 +354,8 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qRoots: {
PathSet referrers;
foreach (Strings::iterator, i, opArgs)
computeFSClosure(maybeUseOutput(followLinksToStorePath(*i), useOutput, forceRealise),
computeFSClosure(*store,
maybeUseOutput(followLinksToStorePath(*i), useOutput, forceRealise),
referrers, true);
Roots roots = store->findRoots();
foreach (Roots::iterator, i, roots)