* `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.
This commit is contained in:
parent
450c358e20
commit
fbc434ee4c
4 changed files with 60 additions and 16 deletions
|
@ -60,7 +60,7 @@ void createSymlink(const Path & link, const Path & target, bool careful)
|
||||||
|
|
||||||
/* Remove the old symlink. */
|
/* Remove the old symlink. */
|
||||||
if (pathExists(link)) {
|
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);
|
throw Error(format("cannot create symlink `%1%'; already exists") % link);
|
||||||
unlink(link.c_str());
|
unlink(link.c_str());
|
||||||
}
|
}
|
||||||
|
@ -250,10 +250,10 @@ static void findRoots(const Path & path, bool recurseSymlinks,
|
||||||
string target = readLink(path);
|
string target = readLink(path);
|
||||||
Path target2 = absPath(target, dirOf(path));
|
Path target2 = absPath(target, dirOf(path));
|
||||||
|
|
||||||
if (isStorePath(target2)) {
|
if (isInStore(target2)) {
|
||||||
debug(format("found root `%1%' in `%2%'")
|
debug(format("found root `%1%' in `%2%'")
|
||||||
% target2 % path);
|
% target2 % path);
|
||||||
roots.insert(target2);
|
roots.insert(toStorePath(target2));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (recurseSymlinks) {
|
else if (recurseSymlinks) {
|
||||||
|
|
|
@ -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] == '/'
|
return path[0] == '/'
|
||||||
&& path.compare(0, nixStore.size(), nixStore) == 0
|
&& path.compare(0, nixStore.size(), nixStore) == 0
|
||||||
&& path.size() >= nixStore.size() + 2
|
&& 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;
|
&& 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)
|
void canonicalisePathMetaData(const Path & path)
|
||||||
{
|
{
|
||||||
checkInterrupt();
|
checkInterrupt();
|
||||||
|
|
|
@ -63,8 +63,13 @@ void registerValidPath(const Transaction & txn,
|
||||||
/* Throw an exception if `path' is not directly in the Nix store. */
|
/* Throw an exception if `path' is not directly in the Nix store. */
|
||||||
void assertStorePath(const Path & path);
|
void assertStorePath(const Path & path);
|
||||||
|
|
||||||
|
bool isInStore(const Path & path);
|
||||||
bool isStorePath(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
|
/* "Fix", or canonicalise, the meta-data of the files in a store path
|
||||||
after it has been built. In particular:
|
after it has been built. In particular:
|
||||||
- the last modification date on each file is set to 0 (i.e.,
|
- the last modification date on each file is set to 0 (i.e.,
|
||||||
|
|
|
@ -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);
|
path = absPath(path);
|
||||||
while (!isStorePath(path)) {
|
while (!isInStore(path)) {
|
||||||
if (!isLink(path)) return path;
|
if (!isLink(path)) break;
|
||||||
string target = readLink(path);
|
string target = readLink(path);
|
||||||
path = absPath(target, dirOf(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();
|
for (Strings::iterator i = opArgs.begin();
|
||||||
i != opArgs.end(); i++)
|
i != opArgs.end(); i++)
|
||||||
*i = followSymlinks(*i);
|
*i = fixPath(*i);
|
||||||
|
|
||||||
if (opArgs.size() > 1) {
|
if (opArgs.size() > 1) {
|
||||||
PathSet drvPaths;
|
PathSet drvPaths;
|
||||||
|
@ -162,19 +162,27 @@ static void printPathSet(const PathSet & paths)
|
||||||
static void opQuery(Strings opFlags, Strings opArgs)
|
static void opQuery(Strings opFlags, Strings opArgs)
|
||||||
{
|
{
|
||||||
enum { qOutputs, qRequisites, qReferences, qReferers,
|
enum { qOutputs, qRequisites, qReferences, qReferers,
|
||||||
qReferersClosure, qDeriver, qGraph } query = qOutputs;
|
qReferersClosure, qDeriver, qBinding, qGraph } query = qOutputs;
|
||||||
bool useOutput = false;
|
bool useOutput = false;
|
||||||
bool includeOutputs = false;
|
bool includeOutputs = false;
|
||||||
bool forceRealise = false;
|
bool forceRealise = false;
|
||||||
|
string bindingName;
|
||||||
|
|
||||||
for (Strings::iterator i = opFlags.begin();
|
for (Strings::iterator i = opFlags.begin();
|
||||||
i != opFlags.end(); i++)
|
i != opFlags.end(); ++i)
|
||||||
if (*i == "--outputs") query = qOutputs;
|
if (*i == "--outputs") query = qOutputs;
|
||||||
else if (*i == "--requisites" || *i == "-R") query = qRequisites;
|
else if (*i == "--requisites" || *i == "-R") query = qRequisites;
|
||||||
else if (*i == "--references") query = qReferences;
|
else if (*i == "--references") query = qReferences;
|
||||||
else if (*i == "--referers") query = qReferers;
|
else if (*i == "--referers") query = qReferers;
|
||||||
else if (*i == "--referers-closure") query = qReferersClosure;
|
else if (*i == "--referers-closure") query = qReferersClosure;
|
||||||
else if (*i == "--deriver" || *i == "-d") query = qDeriver;
|
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 == "--graph") query = qGraph;
|
||||||
else if (*i == "--use-output" || *i == "-u") useOutput = true;
|
else if (*i == "--use-output" || *i == "-u") useOutput = true;
|
||||||
else if (*i == "--force-realise" || *i == "-f") forceRealise = 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();
|
for (Strings::iterator i = opArgs.begin();
|
||||||
i != opArgs.end(); i++)
|
i != opArgs.end(); i++)
|
||||||
{
|
{
|
||||||
*i = followSymlinks(*i);
|
*i = fixPath(*i);
|
||||||
if (forceRealise) realisePath(*i);
|
if (forceRealise) realisePath(*i);
|
||||||
Derivation drv = derivationFromPath(*i);
|
Derivation drv = derivationFromPath(*i);
|
||||||
cout << format("%1%\n") % findOutput(drv, "out");
|
cout << format("%1%\n") % findOutput(drv, "out");
|
||||||
|
@ -203,7 +211,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
|
||||||
for (Strings::iterator i = opArgs.begin();
|
for (Strings::iterator i = opArgs.begin();
|
||||||
i != opArgs.end(); i++)
|
i != opArgs.end(); i++)
|
||||||
{
|
{
|
||||||
*i = followSymlinks(*i);
|
*i = fixPath(*i);
|
||||||
Path path = maybeUseOutput(*i, useOutput, forceRealise);
|
Path path = maybeUseOutput(*i, useOutput, forceRealise);
|
||||||
if (query == qRequisites)
|
if (query == qRequisites)
|
||||||
storePathRequisites(path, includeOutputs, paths);
|
storePathRequisites(path, includeOutputs, paths);
|
||||||
|
@ -219,13 +227,26 @@ static void opQuery(Strings opFlags, Strings opArgs)
|
||||||
for (Strings::iterator i = opArgs.begin();
|
for (Strings::iterator i = opArgs.begin();
|
||||||
i != opArgs.end(); i++)
|
i != opArgs.end(); i++)
|
||||||
{
|
{
|
||||||
*i = followSymlinks(*i);
|
*i = fixPath(*i);
|
||||||
Path deriver = queryDeriver(noTxn, *i);
|
Path deriver = queryDeriver(noTxn, *i);
|
||||||
cout << format("%1%\n") %
|
cout << format("%1%\n") %
|
||||||
(deriver == "" ? "unknown-deriver" : deriver);
|
(deriver == "" ? "unknown-deriver" : deriver);
|
||||||
}
|
}
|
||||||
break;
|
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
|
#if 0
|
||||||
case qGraph: {
|
case qGraph: {
|
||||||
|
|
Loading…
Reference in a new issue