* Maintain a database table (`derivers') that maps output paths to the

derivation that produced them.
* `nix-store -qd PATH' prints out the derivation that produced a path.
This commit is contained in:
Eelco Dolstra 2005-02-07 13:40:40 +00:00
parent a37338815d
commit 450c358e20
4 changed files with 74 additions and 13 deletions

View file

@ -1140,7 +1140,8 @@ void DerivationGoal::computeClosure()
{ {
registerValidPath(txn, i->second.path, registerValidPath(txn, i->second.path,
contentHashes[i->second.path], contentHashes[i->second.path],
allReferences[i->second.path]); allReferences[i->second.path],
drvPath);
} }
txn.commit(); txn.commit();
@ -1501,7 +1502,7 @@ void SubstitutionGoal::finished()
Transaction txn; Transaction txn;
createStoreTransaction(txn); createStoreTransaction(txn);
registerValidPath(txn, storePath, contentHash, references); registerValidPath(txn, storePath, contentHash, references, "");
txn.commit(); txn.commit();
outputLock->setDeletion(true); outputLock->setDeletion(true);

View file

@ -56,6 +56,13 @@ static TableId dbReferers = 0;
*/ */
static TableId dbSubstitutes = 0; static TableId dbSubstitutes = 0;
/* dbDerivers :: Path -> [Path]
This table lists the derivation used to build a path. There can
only be multiple such paths for fixed-output derivations (i.e.,
derivations specifying an expected hash). */
static TableId dbDerivers = 0;
bool Substitute::operator == (const Substitute & sub) bool Substitute::operator == (const Substitute & sub)
{ {
@ -78,6 +85,7 @@ void openDB()
dbReferences = nixDB.openTable("references"); dbReferences = nixDB.openTable("references");
dbReferers = nixDB.openTable("referers"); dbReferers = nixDB.openTable("referers");
dbSubstitutes = nixDB.openTable("substitutes"); dbSubstitutes = nixDB.openTable("substitutes");
dbDerivers = nixDB.openTable("derivers");
} }
@ -318,6 +326,30 @@ void queryReferers(const Path & storePath, PathSet & referers)
} }
void setDeriver(const Transaction & txn, const Path & storePath,
const Path & deriver)
{
assertStorePath(storePath);
if (deriver == "") return;
assertStorePath(deriver);
if (!isRealisablePath(txn, storePath))
throw Error(format("path `%1%' is not valid") % storePath);
nixDB.setString(txn, dbDerivers, storePath, deriver);
}
Path queryDeriver(const Transaction & txn, const Path & storePath)
{
if (!isRealisablePath(noTxn, storePath))
throw Error(format("path `%1%' is not valid") % storePath);
Path deriver;
if (nixDB.queryString(txn, dbDerivers, storePath, deriver))
return deriver;
else
return "";
}
static Substitutes readSubstitutes(const Transaction & txn, static Substitutes readSubstitutes(const Transaction & txn,
const Path & srcPath) const Path & srcPath)
{ {
@ -406,7 +438,8 @@ void clearSubstitutes()
void registerValidPath(const Transaction & txn, void registerValidPath(const Transaction & txn,
const Path & _path, const Hash & hash, const PathSet & references) const Path & _path, const Hash & hash, const PathSet & references,
const Path & deriver)
{ {
Path path(canonPath(_path)); Path path(canonPath(_path));
assertStorePath(path); assertStorePath(path);
@ -423,6 +456,8 @@ void registerValidPath(const Transaction & txn,
if (!isValidPathTxn(txn, *i)) if (!isValidPathTxn(txn, *i))
throw Error(format("cannot register path `%1%' as valid, since its reference `%2%' is invalid") throw Error(format("cannot register path `%1%' as valid, since its reference `%2%' is invalid")
% path % *i); % path % *i);
setDeriver(txn, path, deriver);
} }
@ -433,11 +468,13 @@ static void invalidatePath(const Path & path, Transaction & txn)
debug(format("unregistering path `%1%'") % path); debug(format("unregistering path `%1%'") % path);
/* Clear the `references' entry for this path, as well as the /* Clear the `references' entry for this path, as well as the
inverse `referers' entries; but only if there are no inverse `referers' entries, and the `derivers' entry; but only
substitutes for this path. This maintains the cleanup if there are no substitutes for this path. This maintains the
invariant. */ cleanup invariant. */
if (querySubstitutes(txn, path).size() == 0) if (querySubstitutes(txn, path).size() == 0) {
setReferences(txn, path, PathSet()); setReferences(txn, path, PathSet());
nixDB.delPair(txn, dbDerivers, path);
}
nixDB.delPair(txn, dbValidPaths, path); nixDB.delPair(txn, dbValidPaths, path);
} }
@ -498,7 +535,7 @@ Path addToStore(const Path & _srcPath)
canonicalisePathMetaData(dstPath); canonicalisePathMetaData(dstPath);
Transaction txn(nixDB); Transaction txn(nixDB);
registerValidPath(txn, dstPath, h, PathSet()); registerValidPath(txn, dstPath, h, PathSet(), "");
txn.commit(); txn.commit();
} }
@ -534,7 +571,7 @@ Path addTextToStore(const string & suffix, const string & s,
Transaction txn(nixDB); Transaction txn(nixDB);
registerValidPath(txn, dstPath, registerValidPath(txn, dstPath,
hashPath(htSHA256, dstPath), references); hashPath(htSHA256, dstPath), references, "");
txn.commit(); txn.commit();
} }

View file

@ -57,7 +57,8 @@ void clearSubstitutes();
of the file system contents of the path. The hash must be a of the file system contents of the path. The hash must be a
SHA-256 hash. */ SHA-256 hash. */
void registerValidPath(const Transaction & txn, void registerValidPath(const Transaction & txn,
const Path & path, const Hash & hash, const PathSet & references); const Path & path, const Hash & hash, const PathSet & references,
const Path & deriver);
/* 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);
@ -77,7 +78,8 @@ void canonicalisePathMetaData(const Path & path);
/* Checks whether a path is valid. */ /* Checks whether a path is valid. */
bool isValidPath(const Path & path); bool isValidPath(const Path & path);
/* Sets the set of outgoing FS references for a store path. */ /* Sets the set of outgoing FS references for a store path. Use with
care! */
void setReferences(const Transaction & txn, const Path & storePath, void setReferences(const Transaction & txn, const Path & storePath,
const PathSet & references); const PathSet & references);
@ -89,6 +91,14 @@ void queryReferences(const Path & storePath, PathSet & references);
result is not cleared. */ result is not cleared. */
void queryReferers(const Path & storePath, PathSet & referers); void queryReferers(const Path & storePath, PathSet & referers);
/* Sets the deriver of a store path. Use with care! */
void setDeriver(const Transaction & txn, const Path & storePath,
const Path & deriver);
/* Query the deriver of a store path. Return the empty string if no
deriver has been set. */
Path queryDeriver(const Transaction & txn, const Path & storePath);
/* Constructs a unique store path name. */ /* Constructs a unique store path name. */
Path makeStorePath(const string & type, Path makeStorePath(const string & type,
const Hash & hash, const string & suffix); const Hash & hash, const string & suffix);

View file

@ -162,7 +162,7 @@ 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, qGraph } query = qOutputs; qReferersClosure, qDeriver, qGraph } query = qOutputs;
bool useOutput = false; bool useOutput = false;
bool includeOutputs = false; bool includeOutputs = false;
bool forceRealise = false; bool forceRealise = false;
@ -174,6 +174,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
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 == "--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;
@ -214,6 +215,18 @@ static void opQuery(Strings opFlags, Strings opArgs)
break; break;
} }
case qDeriver:
for (Strings::iterator i = opArgs.begin();
i != opArgs.end(); i++)
{
*i = followSymlinks(*i);
Path deriver = queryDeriver(noTxn, *i);
cout << format("%1%\n") %
(deriver == "" ? "unknown-deriver" : deriver);
}
break;
#if 0 #if 0
case qGraph: { case qGraph: {
PathSet roots; PathSet roots;
@ -288,7 +301,7 @@ static void opValidPath(Strings opFlags, Strings opArgs)
createStoreTransaction(txn); createStoreTransaction(txn);
for (Strings::iterator i = opArgs.begin(); for (Strings::iterator i = opArgs.begin();
i != opArgs.end(); ++i) i != opArgs.end(); ++i)
registerValidPath(txn, *i, hashPath(htSHA256, *i), PathSet()); registerValidPath(txn, *i, hashPath(htSHA256, *i), PathSet(), "");
txn.commit(); txn.commit();
} }