From c8bfb11b34e4b8d3cfd714c54e7436c80e4d72ef Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 6 Mar 2006 11:21:15 +0000 Subject: [PATCH] * `nix-env (-i|-u) --dry-run' now shows exactly which missing paths will be built or substituted. --- src/libexpr/primops.cc | 1 + src/libstore/Makefile.am | 3 ++- src/libstore/build.cc | 1 + src/libstore/build.hh | 17 --------------- src/libstore/gc.cc | 2 +- src/libstore/misc.cc | 47 +++++++++++++++++++++++++++++++++++++++- src/libstore/misc.hh | 32 +++++++++++++++++++++++++++ src/nix-env/main.cc | 38 ++++++++++++++++++++++++++++++-- src/nix-store/main.cc | 1 + 9 files changed, 120 insertions(+), 22 deletions(-) create mode 100644 src/libstore/misc.hh diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 4b1aef935..310bca5ae 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -1,6 +1,7 @@ #include #include "build.hh" +#include "misc.hh" #include "eval.hh" #include "globals.hh" #include "nixexpr-ast.hh" diff --git a/src/libstore/Makefile.am b/src/libstore/Makefile.am index 3fa941b3b..384f99b9f 100644 --- a/src/libstore/Makefile.am +++ b/src/libstore/Makefile.am @@ -2,7 +2,8 @@ lib_LTLIBRARIES = libstore.la libstore_la_SOURCES = \ 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 \ references.cc references.hh pathlocks.cc pathlocks.hh \ gc.cc gc.hh derivations-ast.hh diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 2f6d69d3e..9dd12a46d 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -17,6 +17,7 @@ #include "build.hh" #include "references.hh" #include "pathlocks.hh" +#include "misc.hh" #include "globals.hh" #include "gc.hh" diff --git a/src/libstore/build.hh b/src/libstore/build.hh index 9e3d365e9..489a6cabc 100644 --- a/src/libstore/build.hh +++ b/src/libstore/build.hh @@ -15,23 +15,6 @@ void buildDerivations(const PathSet & drvPaths); be made valid by running a substitute (if defined for the path). */ 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 */ diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 5f4f5b27f..c2bc5bdb1 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -1,6 +1,6 @@ #include "globals.hh" #include "gc.hh" -#include "build.hh" +#include "misc.hh" #include "pathlocks.hh" #include diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc index 33efe8beb..91cf25f27 100644 --- a/src/libstore/misc.cc +++ b/src/libstore/misc.cc @@ -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(); i != drv.outputs.end(); ++i) if (i->first == id) return i->second.path; 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); + } + } +} diff --git a/src/libstore/misc.hh b/src/libstore/misc.hh new file mode 100644 index 000000000..f758f5bfd --- /dev/null +++ b/src/libstore/misc.hh @@ -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 */ diff --git a/src/nix-env/main.cc b/src/nix-env/main.cc index 84c89a157..8648e4f0f 100644 --- a/src/nix-env/main.cc +++ b/src/nix-env/main.cc @@ -2,6 +2,7 @@ #include "names.hh" #include "globals.hh" #include "build.hh" +#include "misc.hh" #include "gc.hh" #include "shared.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, const Strings & args, const Path & profile) { @@ -417,7 +445,10 @@ static void installDerivations(Globals & globals, printMsg(lvlInfo, format("installing `%1%'") % i->name); - if (globals.dryRun) return; + if (globals.dryRun) { + printMissing(globals.state, newElems); + return; + } createUserEnv(globals.state, allElems, profile, globals.keepDerivations); @@ -500,7 +531,10 @@ static void upgradeDerivations(Globals & globals, } else newElems.push_back(*i); } - if (globals.dryRun) return; + if (globals.dryRun) { + printMissing(globals.state, newElems); + return; + } createUserEnv(globals.state, newElems, profile, globals.keepDerivations); diff --git a/src/nix-store/main.cc b/src/nix-store/main.cc index ae386a022..132516cd9 100644 --- a/src/nix-store/main.cc +++ b/src/nix-store/main.cc @@ -3,6 +3,7 @@ #include "globals.hh" #include "build.hh" +#include "misc.hh" #include "gc.hh" #include "archive.hh" #include "shared.hh"