From fbc434ee4c39e7516f3634371442899864786584 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 7 Feb 2005 14:32:44 +0000 Subject: [PATCH] * `nix-store -qb' to query derivation environment bindings. Useful for finding build-time dependencies (possibly after a build). E.g., $ nix-store -qb aterm $(nix-store -qd $(which strc)) /nix/store/jw7c7s65n1gwhxpn35j9rgcci6ilzxym-aterm-2.3.1 * Arguments to nix-store can be files within store objects, e.g., /nix/store/jw7c...-aterm-2.3.1/bin/baffle. * Idem for garbage collector roots. --- src/libstore/gc.cc | 6 +++--- src/libstore/store.cc | 22 ++++++++++++++++++++-- src/libstore/store.hh | 5 +++++ src/nix-store/main.cc | 43 ++++++++++++++++++++++++++++++++----------- 4 files changed, 60 insertions(+), 16 deletions(-) diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 6f09e9cb78..020712368f 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -60,7 +60,7 @@ void createSymlink(const Path & link, const Path & target, bool careful) /* Remove the old symlink. */ if (pathExists(link)) { - if (careful && (!isLink(link) || !isStorePath(readLink(link)))) + if (careful && (!isLink(link) || !isInStore(readLink(link)))) throw Error(format("cannot create symlink `%1%'; already exists") % link); unlink(link.c_str()); } @@ -250,10 +250,10 @@ static void findRoots(const Path & path, bool recurseSymlinks, string target = readLink(path); Path target2 = absPath(target, dirOf(path)); - if (isStorePath(target2)) { + if (isInStore(target2)) { debug(format("found root `%1%' in `%2%'") % target2 % path); - roots.insert(target2); + roots.insert(toStorePath(target2)); } else if (recurseSymlinks) { diff --git a/src/libstore/store.cc b/src/libstore/store.cc index a3e98f6969..693a388b3e 100644 --- a/src/libstore/store.cc +++ b/src/libstore/store.cc @@ -176,12 +176,18 @@ void copyPath(const Path & src, const Path & dst) } -bool isStorePath(const Path & path) +bool isInStore(const Path & path) { return path[0] == '/' && path.compare(0, nixStore.size(), nixStore) == 0 && path.size() >= nixStore.size() + 2 - && path[nixStore.size()] == '/' + && path[nixStore.size()] == '/'; +} + + +bool isStorePath(const Path & path) +{ + return isInStore(path) && path.find('/', nixStore.size() + 1) == Path::npos; } @@ -193,6 +199,18 @@ void assertStorePath(const Path & path) } +Path toStorePath(const Path & path) +{ + if (!isInStore(path)) + throw Error(format("path `%1%' is not in the Nix store") % path); + unsigned int slash = path.find('/', nixStore.size() + 1); + if (slash == Path::npos) + return path; + else + return Path(path, 0, slash); +} + + void canonicalisePathMetaData(const Path & path) { checkInterrupt(); diff --git a/src/libstore/store.hh b/src/libstore/store.hh index 95c738ed1b..1f2b630e10 100644 --- a/src/libstore/store.hh +++ b/src/libstore/store.hh @@ -63,8 +63,13 @@ void registerValidPath(const Transaction & txn, /* Throw an exception if `path' is not directly in the Nix store. */ void assertStorePath(const Path & path); +bool isInStore(const Path & path); bool isStorePath(const Path & path); +/* Chop off the parts after the top-level store name, e.g., + /nix/store/abcd-foo/bar => /nix/store/abcd-foo. */ +Path toStorePath(const Path & path); + /* "Fix", or canonicalise, the meta-data of the files in a store path after it has been built. In particular: - the last modification date on each file is set to 0 (i.e., diff --git a/src/nix-store/main.cc b/src/nix-store/main.cc index 4b8d2cf3f7..f9bd3323f4 100644 --- a/src/nix-store/main.cc +++ b/src/nix-store/main.cc @@ -32,15 +32,15 @@ static Path findOutput(const Derivation & drv, string id) } -static Path followSymlinks(Path & path) +static Path fixPath(Path path) { path = absPath(path); - while (!isStorePath(path)) { - if (!isLink(path)) return path; + while (!isInStore(path)) { + if (!isLink(path)) break; string target = readLink(path); path = absPath(target, dirOf(path)); } - return path; + return toStorePath(path); } @@ -76,7 +76,7 @@ static void opRealise(Strings opFlags, Strings opArgs) for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); i++) - *i = followSymlinks(*i); + *i = fixPath(*i); if (opArgs.size() > 1) { PathSet drvPaths; @@ -162,19 +162,27 @@ static void printPathSet(const PathSet & paths) static void opQuery(Strings opFlags, Strings opArgs) { enum { qOutputs, qRequisites, qReferences, qReferers, - qReferersClosure, qDeriver, qGraph } query = qOutputs; + qReferersClosure, qDeriver, qBinding, qGraph } query = qOutputs; bool useOutput = false; bool includeOutputs = false; bool forceRealise = false; + string bindingName; for (Strings::iterator i = opFlags.begin(); - i != opFlags.end(); i++) + i != opFlags.end(); ++i) if (*i == "--outputs") query = qOutputs; else if (*i == "--requisites" || *i == "-R") query = qRequisites; else if (*i == "--references") query = qReferences; else if (*i == "--referers") query = qReferers; else if (*i == "--referers-closure") query = qReferersClosure; else if (*i == "--deriver" || *i == "-d") query = qDeriver; + else if (*i == "--binding" || *i == "-b") { + if (opArgs.size() == 0) + throw UsageError("expected binding name"); + bindingName = opArgs.front(); + opArgs.pop_front(); + query = qBinding; + } else if (*i == "--graph") query = qGraph; else if (*i == "--use-output" || *i == "-u") useOutput = true; else if (*i == "--force-realise" || *i == "-f") forceRealise = true; @@ -187,7 +195,7 @@ static void opQuery(Strings opFlags, Strings opArgs) for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); i++) { - *i = followSymlinks(*i); + *i = fixPath(*i); if (forceRealise) realisePath(*i); Derivation drv = derivationFromPath(*i); cout << format("%1%\n") % findOutput(drv, "out"); @@ -203,7 +211,7 @@ static void opQuery(Strings opFlags, Strings opArgs) for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); i++) { - *i = followSymlinks(*i); + *i = fixPath(*i); Path path = maybeUseOutput(*i, useOutput, forceRealise); if (query == qRequisites) storePathRequisites(path, includeOutputs, paths); @@ -219,13 +227,26 @@ static void opQuery(Strings opFlags, Strings opArgs) for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); i++) { - *i = followSymlinks(*i); + *i = fixPath(*i); Path deriver = queryDeriver(noTxn, *i); cout << format("%1%\n") % (deriver == "" ? "unknown-deriver" : deriver); } break; - + + case qBinding: + for (Strings::iterator i = opArgs.begin(); + i != opArgs.end(); i++) + { + *i = fixPath(*i); + Derivation drv = derivationFromPath(*i); + StringPairs::iterator j = drv.env.find(bindingName); + if (j == drv.env.end()) + throw Error(format("derivation `%1%' has no environment binding named `%2%'") + % *i % bindingName); + cout << format("%1%\n") % j->second; + } + break; #if 0 case qGraph: {