* `nix-env (-i|-u) --dry-run' now shows exactly which missing paths
will be built or substituted.
This commit is contained in:
parent
7ba1fd2029
commit
c8bfb11b34
9 changed files with 120 additions and 22 deletions
|
@ -1,6 +1,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "build.hh"
|
#include "build.hh"
|
||||||
|
#include "misc.hh"
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "nixexpr-ast.hh"
|
#include "nixexpr-ast.hh"
|
||||||
|
|
|
@ -2,7 +2,8 @@ lib_LTLIBRARIES = libstore.la
|
||||||
|
|
||||||
libstore_la_SOURCES = \
|
libstore_la_SOURCES = \
|
||||||
store.cc store.hh derivations.cc derivations.hh \
|
store.cc store.hh derivations.cc derivations.hh \
|
||||||
build.cc misc.cc build.hh \
|
build.cc build.hh \
|
||||||
|
misc.cc misc.hh \
|
||||||
globals.cc globals.hh db.cc db.hh \
|
globals.cc globals.hh db.cc db.hh \
|
||||||
references.cc references.hh pathlocks.cc pathlocks.hh \
|
references.cc references.hh pathlocks.cc pathlocks.hh \
|
||||||
gc.cc gc.hh derivations-ast.hh
|
gc.cc gc.hh derivations-ast.hh
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "build.hh"
|
#include "build.hh"
|
||||||
#include "references.hh"
|
#include "references.hh"
|
||||||
#include "pathlocks.hh"
|
#include "pathlocks.hh"
|
||||||
|
#include "misc.hh"
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "gc.hh"
|
#include "gc.hh"
|
||||||
|
|
||||||
|
|
|
@ -15,23 +15,6 @@ void buildDerivations(const PathSet & drvPaths);
|
||||||
be made valid by running a substitute (if defined for the path). */
|
be made valid by running a substitute (if defined for the path). */
|
||||||
void ensurePath(const Path & storePath);
|
void ensurePath(const Path & storePath);
|
||||||
|
|
||||||
/* Read a derivation, after ensuring its existence through
|
|
||||||
ensurePath(). */
|
|
||||||
Derivation derivationFromPath(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
|
|
||||||
indirectly reached from it. `paths' is not cleared. If
|
|
||||||
`flipDirection' is true, the set of paths that can reach
|
|
||||||
`storePath' is returned; that is, the closures under the
|
|
||||||
`referrers' relation instead of the `references' relation is
|
|
||||||
returned. */
|
|
||||||
void computeFSClosure(const Path & storePath,
|
|
||||||
PathSet & paths, bool flipDirection = false);
|
|
||||||
|
|
||||||
/* Return the path corresponding to the output identifier `id' in the
|
|
||||||
given derivation. */
|
|
||||||
Path findOutput(const Derivation & drv, string id);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* !__BUILD_H */
|
#endif /* !__BUILD_H */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "gc.hh"
|
#include "gc.hh"
|
||||||
#include "build.hh"
|
#include "misc.hh"
|
||||||
#include "pathlocks.hh"
|
#include "pathlocks.hh"
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
|
@ -29,10 +29,55 @@ void computeFSClosure(const Path & storePath,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Path findOutput(const Derivation & drv, string id)
|
Path findOutput(const Derivation & drv, string id)
|
||||||
{
|
{
|
||||||
for (DerivationOutputs::const_iterator i = drv.outputs.begin();
|
for (DerivationOutputs::const_iterator i = drv.outputs.begin();
|
||||||
i != drv.outputs.end(); ++i)
|
i != drv.outputs.end(); ++i)
|
||||||
if (i->first == id) return i->second.path;
|
if (i->first == id) return i->second.path;
|
||||||
throw Error(format("derivation has no output `%1%'") % id);
|
throw Error(format("derivation has no output `%1%'") % id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void queryMissing(const PathSet & targets,
|
||||||
|
PathSet & willBuild, PathSet & willSubstitute)
|
||||||
|
{
|
||||||
|
PathSet todo(targets.begin(), targets.end()), done;
|
||||||
|
|
||||||
|
while (!todo.empty()) {
|
||||||
|
Path p = *(todo.begin());
|
||||||
|
todo.erase(p);
|
||||||
|
if (done.find(p) != done.end()) continue;
|
||||||
|
done.insert(p);
|
||||||
|
|
||||||
|
if (isDerivation(p)) {
|
||||||
|
if (!isValidPath(p)) continue;
|
||||||
|
Derivation drv = derivationFromPath(p);
|
||||||
|
|
||||||
|
bool mustBuild = false;
|
||||||
|
for (DerivationOutputs::iterator i = drv.outputs.begin();
|
||||||
|
i != drv.outputs.end(); ++i)
|
||||||
|
if (!isValidPath(i->second.path) &&
|
||||||
|
querySubstitutes(noTxn, i->second.path).size() == 0)
|
||||||
|
mustBuild = true;
|
||||||
|
|
||||||
|
if (mustBuild) {
|
||||||
|
willBuild.insert(p);
|
||||||
|
todo.insert(drv.inputSrcs.begin(), drv.inputSrcs.end());
|
||||||
|
for (DerivationInputs::iterator i = drv.inputDrvs.begin();
|
||||||
|
i != drv.inputDrvs.end(); ++i)
|
||||||
|
todo.insert(i->first);
|
||||||
|
} else
|
||||||
|
for (DerivationOutputs::iterator i = drv.outputs.begin();
|
||||||
|
i != drv.outputs.end(); ++i)
|
||||||
|
todo.insert(i->second.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
if (isValidPath(p)) continue;
|
||||||
|
if (querySubstitutes(noTxn, p).size() > 0)
|
||||||
|
willSubstitute.insert(p);
|
||||||
|
PathSet refs;
|
||||||
|
queryReferences(noTxn, p, todo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
32
src/libstore/misc.hh
Normal file
32
src/libstore/misc.hh
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef __MISC_H
|
||||||
|
#define __MISC_H
|
||||||
|
|
||||||
|
#include "derivations.hh"
|
||||||
|
|
||||||
|
|
||||||
|
/* Read a derivation, after ensuring its existence through
|
||||||
|
ensurePath(). */
|
||||||
|
Derivation derivationFromPath(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
|
||||||
|
indirectly reached from it. `paths' is not cleared. If
|
||||||
|
`flipDirection' is true, the set of paths that can reach
|
||||||
|
`storePath' is returned; that is, the closures under the
|
||||||
|
`referrers' relation instead of the `references' relation is
|
||||||
|
returned. */
|
||||||
|
void computeFSClosure(const Path & storePath,
|
||||||
|
PathSet & paths, bool flipDirection = false);
|
||||||
|
|
||||||
|
/* Return the path corresponding to the output identifier `id' in the
|
||||||
|
given derivation. */
|
||||||
|
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,
|
||||||
|
PathSet & willBuild, PathSet & willSubstitute);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* !__MISC_H */
|
|
@ -2,6 +2,7 @@
|
||||||
#include "names.hh"
|
#include "names.hh"
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "build.hh"
|
#include "build.hh"
|
||||||
|
#include "misc.hh"
|
||||||
#include "gc.hh"
|
#include "gc.hh"
|
||||||
#include "shared.hh"
|
#include "shared.hh"
|
||||||
#include "parser.hh"
|
#include "parser.hh"
|
||||||
|
@ -383,6 +384,33 @@ static void queryInstSources(EvalState & state,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void printMissing(EvalState & state, const DrvInfos & elems)
|
||||||
|
{
|
||||||
|
PathSet targets, willBuild, willSubstitute;
|
||||||
|
for (DrvInfos::const_iterator i = elems.begin(); i != elems.end(); ++i) {
|
||||||
|
Path drvPath = i->queryDrvPath(state);
|
||||||
|
if (drvPath != "")
|
||||||
|
targets.insert(drvPath);
|
||||||
|
else
|
||||||
|
targets.insert(i->queryOutPath(state));
|
||||||
|
}
|
||||||
|
|
||||||
|
queryMissing(targets, willBuild, willSubstitute);
|
||||||
|
|
||||||
|
if (!willBuild.empty()) {
|
||||||
|
printMsg(lvlInfo, format("the following derivations will be built:"));
|
||||||
|
for (PathSet::iterator i = willBuild.begin(); i != willBuild.end(); ++i)
|
||||||
|
printMsg(lvlInfo, format(" %1%") % *i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!willSubstitute.empty()) {
|
||||||
|
printMsg(lvlInfo, format("the following paths will be substituted:"));
|
||||||
|
for (PathSet::iterator i = willSubstitute.begin(); i != willSubstitute.end(); ++i)
|
||||||
|
printMsg(lvlInfo, format(" %1%") % *i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void installDerivations(Globals & globals,
|
static void installDerivations(Globals & globals,
|
||||||
const Strings & args, const Path & profile)
|
const Strings & args, const Path & profile)
|
||||||
{
|
{
|
||||||
|
@ -417,7 +445,10 @@ static void installDerivations(Globals & globals,
|
||||||
printMsg(lvlInfo,
|
printMsg(lvlInfo,
|
||||||
format("installing `%1%'") % i->name);
|
format("installing `%1%'") % i->name);
|
||||||
|
|
||||||
if (globals.dryRun) return;
|
if (globals.dryRun) {
|
||||||
|
printMissing(globals.state, newElems);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
createUserEnv(globals.state, allElems,
|
createUserEnv(globals.state, allElems,
|
||||||
profile, globals.keepDerivations);
|
profile, globals.keepDerivations);
|
||||||
|
@ -500,7 +531,10 @@ static void upgradeDerivations(Globals & globals,
|
||||||
} else newElems.push_back(*i);
|
} else newElems.push_back(*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (globals.dryRun) return;
|
if (globals.dryRun) {
|
||||||
|
printMissing(globals.state, newElems);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
createUserEnv(globals.state, newElems,
|
createUserEnv(globals.state, newElems,
|
||||||
profile, globals.keepDerivations);
|
profile, globals.keepDerivations);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "build.hh"
|
#include "build.hh"
|
||||||
|
#include "misc.hh"
|
||||||
#include "gc.hh"
|
#include "gc.hh"
|
||||||
#include "archive.hh"
|
#include "archive.hh"
|
||||||
#include "shared.hh"
|
#include "shared.hh"
|
||||||
|
|
Loading…
Reference in a new issue