diff --git a/src/libstore/store.cc b/src/libstore/store.cc index e9d6540440..5742bbb738 100644 --- a/src/libstore/store.cc +++ b/src/libstore/store.cc @@ -508,24 +508,48 @@ Hash queryPathHash(const Path & path) 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)); - assertStorePath(path); + ValidPathInfo info; + info.path = path; + info.hash = hash; + info.references = references; + info.deriver = deriver; + ValidPathInfos infos; + infos.push_back(info); + registerValidPaths(txn, infos); +} - debug(format("registering path `%1%'") % path); - setHash(txn, path, hash); - setReferences(txn, path, references); +void registerValidPaths(const Transaction & txn, + const ValidPathInfos & infos) +{ + PathSet newPaths; + for (ValidPathInfos::const_iterator i = infos.begin(); + i != infos.end(); ++i) + newPaths.insert(i->path); + + for (ValidPathInfos::const_iterator i = infos.begin(); + i != infos.end(); ++i) + { + assertStorePath(i->path); + + debug(format("registering path `%1%'") % i->path); + setHash(txn, i->path, i->hash); + + setReferences(txn, i->path, i->references); - /* Check that all referenced paths are also valid. */ - for (PathSet::iterator i = references.begin(); i != references.end(); ++i) - if (!isValidPathTxn(txn, *i)) - throw Error(format("cannot register path `%1%' as valid, since its reference `%2%' is invalid") - % path % *i); + /* Check that all referenced paths are also valid (or about to + become valid). */ + for (PathSet::iterator j = i->references.begin(); + j != i->references.end(); ++j) + if (!isValidPathTxn(txn, *j) && newPaths.find(*j) == newPaths.end()) + throw Error(format("cannot register path `%1%' as valid, since its reference `%2%' is invalid") + % i->path % *j); - setDeriver(txn, path, deriver); + setDeriver(txn, i->path, i->deriver); + } } diff --git a/src/libstore/store.hh b/src/libstore/store.hh index 4a37a66322..01a971404c 100644 --- a/src/libstore/store.hh +++ b/src/libstore/store.hh @@ -66,6 +66,19 @@ void registerValidPath(const Transaction & txn, const Path & path, const Hash & hash, const PathSet & references, const Path & deriver); +struct ValidPathInfo +{ + Path path; + Path deriver; + Hash hash; + PathSet references; +}; + +typedef list ValidPathInfos; + +void registerValidPaths(const Transaction & txn, + const ValidPathInfos & infos); + /* Throw an exception if `path' is not directly in the Nix store. */ void assertStorePath(const Path & path); diff --git a/src/nix-store/main.cc b/src/nix-store/main.cc index 956cbb4fbb..42783e108a 100644 --- a/src/nix-store/main.cc +++ b/src/nix-store/main.cc @@ -405,31 +405,32 @@ static void opRegisterValidity(Strings opFlags, Strings opArgs) if (!opFlags.empty()) throw UsageError("unknown flag"); if (!opArgs.empty()) throw UsageError("no arguments expected"); - Transaction txn; - createStoreTransaction(txn); - + ValidPathInfos infos; + while (1) { - Path path; - Path deriver; - PathSet references; - getline(cin, path); + ValidPathInfo info; + getline(cin, info.path); if (cin.eof()) break; - getline(cin, deriver); + getline(cin, info.deriver); string s; int n; getline(cin, s); if (!string2Int(s, n)) throw Error("number expected"); while (n--) { getline(cin, s); - references.insert(s); + info.references.insert(s); } if (!cin || cin.eof()) throw Error("missing input"); - if (!isValidPathTxn(txn, path)) { + if (!isValidPath(info.path)) { /* !!! races */ - canonicalisePathMetaData(path); - registerValidPath(txn, path, hashPath(htSHA256, path), references, deriver); + canonicalisePathMetaData(info.path); + info.hash = hashPath(htSHA256, info.path); + infos.push_back(info); } } + Transaction txn; + createStoreTransaction(txn); + registerValidPaths(txn, infos); txn.commit(); }