From 4f483aad0f2177a3940cab3dde32b8d397378ffc Mon Sep 17 00:00:00 2001 From: Wouter den Breejen Date: Fri, 6 Jul 2007 15:12:20 +0000 Subject: [PATCH] runProgram backup --- src/libstore/build.cc | 4 +- src/libstore/db.cc | 86 ++++++++++++++---- src/libstore/db.hh | 10 +++ src/libstore/gc.cc | 2 +- src/libstore/local-store.cc | 167 ++++++++++++++++++----------------- src/libstore/local-store.hh | 8 +- src/libstore/misc.cc | 12 +-- src/libstore/misc.hh | 6 +- src/libstore/remote-store.cc | 13 ++- src/libstore/remote-store.hh | 8 +- src/libstore/store-api.hh | 8 +- src/libutil/util.cc | 92 ++++++++++++------- src/nix-state/nix-state.cc | 76 ++++++++++++++-- src/nix-store/dotgraph.cc | 2 +- src/nix-store/nix-store.cc | 10 +-- src/nix-worker/nix-worker.cc | 8 +- 16 files changed, 338 insertions(+), 174 deletions(-) diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 559416795..03750dcd0 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -1083,7 +1083,7 @@ static string makeValidityRegistration(const PathSet & paths, s += deriver + "\n"; PathSet references; - store->queryReferences(*i, references); + store->queryReferences(*i, references, -1); //TODO check if this is ok s += (format("%1%\n") % references.size()).str(); @@ -2018,7 +2018,7 @@ void SubstitutionGoal::init() /* To maintain the closure invariant, we first have to realise the paths referenced by this one. */ - store->queryReferences(storePath, references); + store->queryReferences(storePath, references, -1); for (PathSet::iterator i = references.begin(); i != references.end(); ++i) diff --git a/src/libstore/db.cc b/src/libstore/db.cc index 03737d0a8..facf44d37 100644 --- a/src/libstore/db.cc +++ b/src/libstore/db.cc @@ -444,11 +444,47 @@ void Database::enumTable(const Transaction & txn, TableId table, } catch (DbException e) { rethrow(e); } } +/* State specific db functions */ + +Path Database::makeStatePathRevision(const Path & statePath, const int revision) +{ + string prefix = "-REV-"; + + return statePath + prefix + int2String(revision); +} +void Database::splitStatePathRevision(const Path & revisionedStatePath, Path & statePath, int & revision) +{ + string prefix = "-REV-"; + + int pos = revisionedStatePath.find_last_not_of(prefix); + statePath = revisionedStatePath.substr(0, pos - prefix.length()); + //printMsg(lvlError, format("'%1%' '%2%'") % statePath % revisionedStatePath.substr(pos, revisionedStatePath.size())); + bool succeed = string2Int(revisionedStatePath.substr(pos, revisionedStatePath.size()), revision); + if(!succeed) + throw Error(format("Malformed revision value of path '%1%'") % revisionedStatePath); +} + + void Database::setStateReferences(const Transaction & txn, TableId table, const Path & statePath, const int revision, const Strings & references) { + //printMsg(lvlError, format("setStateReferences/Referrers %1%") % table); + + if(revision == -1) + throw Error("-1 is not a valid revision value for SET-references/referrers"); + + /* + for (Strings::const_iterator i = references.begin(); i != references.end(); ++i) + printMsg(lvlError, format("setStateReferences::: '%1%'") % *i); + */ + + //Warning if it already exists + Strings empty; + if( queryStateReferences(txn, table, statePath, empty, revision) ) + printMsg(lvlError, format("Warning: The revision '%1%' already exists for set-references/referrers of path '%2%' with db '%3%'") % revision % statePath % table); + //Create the key - string key = statePath + "-" + int2String(revision); + string key = makeStatePathRevision(statePath, revision); //Insert setStrings(txn, table, key, references); @@ -457,43 +493,59 @@ void Database::setStateReferences(const Transaction & txn, TableId table, bool Database::queryStateReferences(const Transaction & txn, TableId table, const Path & statePath, Strings & references, int revision) { + //printMsg(lvlError, format("queryStateReferences/Referrers %1%") % table); + Strings keys; enumTable(txn, table, keys); //get all revisions - string key = ""; //final key that matches revision + statePath + string key = ""; //final key that matches revision + statePath int highestRev = -1; //Lookup which key we need for (Strings::iterator i = keys.begin(); i != keys.end(); ++i) { - string getStatePath = *i; + Path getStatePath_org = *i; + Path getStatePath; + int getRevision; + splitStatePathRevision(*i, getStatePath, getRevision); - if(getStatePath.substr(0, statePath.size()) == statePath){ - int getRev; - bool succeed = string2Int(getStatePath.substr(statePath.size() + 1, getStatePath.size()), getRev); - if(!succeed) - throw Error("Malformed revision value after statePath in stateRefereneces"); - - printMsg(lvlError, format("KEY: %1% of %2%") % getStatePath % getRev); + if(getStatePath == statePath){ if(revision == -1){ //the user wants the last revision - if(getRev > highestRev) - highestRev = getRev; + if(getRevision > highestRev) + highestRev = getRevision; } - else if(revision == getRev){ - key = getStatePath; + else if(revision == getRevision){ + key = getStatePath_org; break; } } } - if(key == "" && highestRev == -1) //no records found + if(key == "" && highestRev == -1) //no records found (TODO throw error?) return false; if(revision == -1) - key = statePath + "-" + int2String(highestRev); + key = makeStatePathRevision(statePath, highestRev); return queryStrings(txn, table, key, references); //now that we have the key, we can query the references -} +} + +bool Database::queryStateReferrers(const Transaction & txn, TableId table, + const Path & statePath, Strings & referrers, int revision) +{ + //PathSet referrers; + Strings keys; + Path revisionedStatePath = makeStatePathRevision(statePath, revision); + + enumTable(txn, table, keys, revisionedStatePath + string(1, (char) 0)); + + for (Strings::iterator i = keys.begin(); i != keys.end(); ++i) + printMsg(lvlError, format("queryStateReferrers %1%") % *i); + //referrers.insert(stripPrefix(storePath, *i)); + + return false; +} + void Database::setStateRevisions(const Transaction & txn, TableId table, const Path & statePath, const int revision, const RevisionNumbers & revisions) diff --git a/src/libstore/db.hh b/src/libstore/db.hh index 50951b199..150307551 100644 --- a/src/libstore/db.hh +++ b/src/libstore/db.hh @@ -90,6 +90,12 @@ public: void enumTable(const Transaction & txn, TableId table, Strings & keys, const string & keyPrefix = ""); + /* TODO */ + Path makeStatePathRevision(const Path & statePath, const int revision); + + /* TODO */ + void splitStatePathRevision(const Path & revisionedStatePath, Path & statePath, int & revision); + /* Set the stateReferences for a specific revision (and older until the next higher revision number in the table) */ void setStateReferences(const Transaction & txn, TableId table, const Path & statePath, const int revision, const Strings & references); @@ -98,6 +104,10 @@ public: bool queryStateReferences(const Transaction & txn, TableId table, const Path & statePath, Strings & references, int revision = -1); + /* Returns the referrers for a specific revision (and older until the next higher revision number in the table) */ + bool queryStateReferrers(const Transaction & txn, TableId table, + const Path & statePath, Strings & referrers, int revision = -1); + /* Set the revision number of the statePath and the revision numbers of all state paths in the references closure */ void setStateRevisions(const Transaction & txn, TableId table, const Path & statePath, const int revision, const RevisionNumbers & revisions); diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index f43c138fc..395c27e52 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -406,7 +406,7 @@ static void dfsVisit(const PathSet & paths, const Path & path, PathSet references; if (store->isValidPath(path)) - store->queryReferences(path, references); + store->queryReferences(path, references, -1); //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!! for (PathSet::iterator i = references.begin(); i != references.end(); ++i) diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 296fc785e..689ef6497 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -387,40 +387,51 @@ static string stripPrefix(const string & prefix, const string & s) } -static PathSet getReferrers(const Transaction & txn, const Path & storePath) +//TODO move the code of get(State)Referrers into query variant ..... !!!!!!!!!!!!!!!!!!!!!!!!!!!!??? + + +static PathSet getReferrers(const Transaction & txn, const Path & store_or_statePath, const int revision) { - PathSet referrers; - Strings keys; - - if(isValidPathTxn(txn, storePath)) - nixDB.enumTable(txn, dbComponentComponentReferrers, keys, storePath + string(1, (char) 0)); - else if(isValidStatePathTxn(txn, storePath)) - nixDB.enumTable(txn, dbStateComponentReferrers, keys, storePath + string(1, (char) 0)); + if(isValidPathTxn(txn, store_or_statePath)){ + PathSet referrers; + Strings keys; + nixDB.enumTable(txn, dbComponentComponentReferrers, keys, store_or_statePath + string(1, (char) 0)); + for (Strings::iterator i = keys.begin(); i != keys.end(); ++i) + referrers.insert(stripPrefix(store_or_statePath, *i)); + return referrers; + } + else if(isValidStatePathTxn(txn, store_or_statePath)){ + Paths referrers; + nixDB.queryStateReferrers(txn, dbStateComponentReferrers, store_or_statePath, referrers, revision); + PathSet p(referrers.begin(), referrers.end()); + return p; + } else - throw Error(format("Path '%1%' is not a valid component or state path") % storePath); - - for (Strings::iterator i = keys.begin(); i != keys.end(); ++i) - referrers.insert(stripPrefix(storePath, *i)); - return referrers; + throw Error(format("Path '%1%' is not a valid component or state path") % store_or_statePath); + } -static PathSet getStateReferrers(const Transaction & txn, const Path & storePath) //TODO this is just a copy of getReferrers with a change to dbStateReferrers, maybe make the function more generic? +static PathSet getStateReferrers(const Transaction & txn, const Path & store_or_statePath, const int revision) //TODO this is just a copy of getReferrers with a change to dbStateReferrers, maybe make the function more generic? { - PathSet referrers; - Strings keys; - - if(isValidPathTxn(txn, storePath)) - nixDB.enumTable(txn, dbComponentComponentReferrers, keys, storePath + string(1, (char) 0)); - else if(isValidStatePathTxn(txn, storePath)) - nixDB.enumTable(txn, dbStateComponentReferrers, keys, storePath + string(1, (char) 0)); + if(isValidPathTxn(txn, store_or_statePath)){ + PathSet referrers; + Strings keys; + nixDB.enumTable(txn, dbComponentStateReferrers, keys, store_or_statePath + string(1, (char) 0)); + for (Strings::iterator i = keys.begin(); i != keys.end(); ++i) + referrers.insert(stripPrefix(store_or_statePath, *i)); + return referrers; + } + else if(isValidStatePathTxn(txn, store_or_statePath)){ + Paths referrers; + nixDB.queryStateReferrers(txn, dbStateStateReferrers, store_or_statePath, referrers, revision); + PathSet p(referrers.begin(), referrers.end()); + return p; + } else - throw Error(format("Path '%1%' is not a valid component or state path") % storePath); - - for (Strings::iterator i = keys.begin(); i != keys.end(); ++i) - referrers.insert(stripPrefix(storePath, *i)); - return referrers; + throw Error(format("Path '%1%' is not a valid component or state path") % store_or_statePath); } + void setReferences(const Transaction & txn, const Path & store_or_statePath, const PathSet & references, const PathSet & stateReferences, const int revision) { @@ -440,7 +451,7 @@ void setReferences(const Transaction & txn, const Path & store_or_statePath, PathSet oldStateReferences2; Paths oldReferences_X_c; Paths oldReferences_X_s; - + if(isRealisablePath(txn, store_or_statePath)) { Paths oldReferences_c_c; @@ -467,16 +478,15 @@ void setReferences(const Transaction & txn, const Path & store_or_statePath, Paths oldStateReferences_s_c; Paths oldStateReferences_s_s; - nixDB.queryStrings(txn, dbStateComponentReferences, store_or_statePath, oldStateReferences_s_c); - nixDB.queryStrings(txn, dbStateStateReferences, store_or_statePath, oldStateReferences_s_s); - + nixDB.queryStateReferences(txn, dbStateComponentReferences, store_or_statePath, oldStateReferences_s_c, revision); + nixDB.queryStateReferences(txn, dbStateStateReferences, store_or_statePath, oldStateReferences_s_s, revision); + oldReferences2 = PathSet(oldStateReferences_s_c.begin(), oldStateReferences_s_c.end()); oldStateReferences2 = PathSet(oldStateReferences_s_s.begin(), oldStateReferences_s_s.end()); - if (oldReferences2 == references && oldStateReferences2 == stateReferences) return; - - nixDB.setStrings(txn, dbStateComponentReferences, store_or_statePath, Paths(references.begin(), references.end())); - nixDB.setStateReferences(txn, dbStateStateReferences, store_or_statePath, revision, Paths(stateReferences.begin(), stateReferences.end())); + nixDB.setStateReferences(txn, dbStateComponentReferences, store_or_statePath, revision, Paths(references.begin(), references.end())); + nixDB.setStateReferences(txn, dbStateStateReferences, store_or_statePath, revision, Paths(stateReferences.begin(), stateReferences.end())); + //set vars for the referrers update code below dbXComponentReferrers = dbStateComponentReferrers; dbXStateReferrers = dbStateStateReferrers; @@ -486,102 +496,104 @@ void setReferences(const Transaction & txn, const Path & store_or_statePath, else throw Error(format("Path '%1%' is not a valid component or state path") % store_or_statePath); - //The follow 4 for-loops haved been made generic with variables, they work in the case of statePaths and storePaths - + //store_or_statePath must be postfixed in case it is a statePath + Path store_or_statePath2 = store_or_statePath; + if(isRealisableStatePath(txn, store_or_statePath)) + store_or_statePath2 = nixDB.makeStatePathRevision(store_or_statePath, revision); + + //The follow 4 for-loops haved been made generic with variables, they work in the case of statePaths and storePaths + /* Update the referrers mappings of all new referenced paths. */ for (PathSet::const_iterator i = references.begin(); i != references.end(); ++i) if (oldReferences2.find(*i) == oldReferences2.end()) - nixDB.setString(txn, dbXComponentReferrers, addPrefix(*i, store_or_statePath), ""); + nixDB.setString(txn, dbXComponentReferrers, addPrefix(*i, store_or_statePath2), ""); /* Remove referrer mappings from paths that are no longer references. */ for (Paths::iterator i = oldReferences_X_c.begin(); i != oldReferences_X_c.end(); ++i) if (references.find(*i) == references.end()) - nixDB.delPair(txn, dbXComponentReferrers, addPrefix(*i, store_or_statePath)); + nixDB.delPair(txn, dbXComponentReferrers, addPrefix(*i, store_or_statePath2)); /* Update the state referrers mappings of all new referenced paths. */ for (PathSet::const_iterator i = stateReferences.begin(); i != stateReferences.end(); ++i) if (oldStateReferences2.find(*i) == oldStateReferences2.end()) - nixDB.setString(txn, dbXStateReferrers, addPrefix(*i, store_or_statePath), ""); + nixDB.setString(txn, dbXStateReferrers, addPrefix(*i, store_or_statePath2), ""); /* Remove referrer mappings from paths that are no longer state references. */ for (Paths::iterator i = oldReferences_X_s.begin(); i != oldReferences_X_s.end(); ++i) if (stateReferences.find(*i) == stateReferences.end()) - nixDB.delPair(txn, dbXStateReferrers, addPrefix(*i, store_or_statePath)); - + nixDB.delPair(txn, dbXStateReferrers, addPrefix(*i, store_or_statePath2)); } void queryReferences(const Transaction & txn, - const Path & storePath, PathSet & references) + const Path & store_or_statePath, PathSet & references, const int revision) { Paths references2; - if(isRealisablePath(txn, storePath)) - nixDB.queryStrings(txn, dbComponentComponentReferences, storePath, references2); - else if(isRealisableStatePath(txn, storePath)) - nixDB.queryStrings(txn, dbStateComponentReferences, storePath, references2); + if(isRealisablePath(txn, store_or_statePath)) + nixDB.queryStrings(txn, dbComponentComponentReferences, store_or_statePath, references2); + else if(isRealisableStatePath(txn, store_or_statePath)) + nixDB.queryStateReferences(txn, dbStateComponentReferences, store_or_statePath, references2, revision); else - throw Error(format("Path '%1%' is not a valid component or state path") % storePath); + throw Error(format("Path '%1%' is not a valid component or state path") % store_or_statePath); references.insert(references2.begin(), references2.end()); } void LocalStore::queryReferences(const Path & storePath, - PathSet & references) + PathSet & references, const int revision) { - nix::queryReferences(noTxn, storePath, references); + nix::queryReferences(noTxn, storePath, references, revision); } void queryStateReferences(const Transaction & txn, - const Path & componentOrstatePath, PathSet & stateReferences) + const Path & store_or_statePath, PathSet & stateReferences, const int revision) { Paths stateReferences2; - if(isRealisablePath(txn, componentOrstatePath)) - nixDB.queryStrings(txn, dbComponentStateReferences, componentOrstatePath, stateReferences2); - else if(isRealisableStatePath(txn, componentOrstatePath)) - nixDB.queryStrings(txn, dbStateStateReferences, componentOrstatePath, stateReferences2); //TODO !!!!!!!!!!!!!!!! state-state references are not strings anymore !!!! + if(isRealisablePath(txn, store_or_statePath)) + nixDB.queryStrings(txn, dbComponentStateReferences, store_or_statePath, stateReferences2); + else if(isRealisableStatePath(txn, store_or_statePath)) + nixDB.queryStateReferences(txn, dbStateStateReferences, store_or_statePath, stateReferences2, revision); else - throw Error(format("Path '%1%' is not a valid component or state path") % componentOrstatePath); + throw Error(format("Path '%1%' is not a valid component or state path") % store_or_statePath); stateReferences.insert(stateReferences2.begin(), stateReferences2.end()); } -void LocalStore::queryStateReferences(const Path & componentOrstatePath, PathSet & stateReferences) +void LocalStore::queryStateReferences(const Path & componentOrstatePath, PathSet & stateReferences, const int revision) { - nix::queryStateReferences(noTxn, componentOrstatePath, stateReferences); + nix::queryStateReferences(noTxn, componentOrstatePath, stateReferences, revision); } void queryReferrers(const Transaction & txn, - const Path & storePath, PathSet & referrers) + const Path & storePath, PathSet & referrers, const int revision) { if (!isRealisableComponentOrStatePath(txn, storePath)) throw Error(format("path `%1%' is not valid") % storePath); - PathSet referrers2 = getReferrers(txn, storePath); + PathSet referrers2 = getReferrers(txn, storePath, revision); referrers.insert(referrers2.begin(), referrers2.end()); } - void LocalStore::queryReferrers(const Path & storePath, - PathSet & referrers) + PathSet & referrers, const int revision) { - nix::queryReferrers(noTxn, storePath, referrers); + nix::queryReferrers(noTxn, storePath, referrers, revision); } -void queryStateReferrers(const Transaction & txn, const Path & storePath, PathSet & stateReferrers) +void queryStateReferrers(const Transaction & txn, const Path & storePath, PathSet & stateReferrers, const int revision) { if (!isRealisableComponentOrStatePath(txn, storePath)) throw Error(format("path `%1%' is not valid") % storePath); - PathSet stateReferrers2 = getStateReferrers(txn, storePath); + PathSet stateReferrers2 = getStateReferrers(txn, storePath, revision); stateReferrers.insert(stateReferrers2.begin(), stateReferrers2.end()); } - -void LocalStore::queryStateReferrers(const Path & storePath, PathSet & stateReferrers) +void LocalStore::queryStateReferrers(const Path & storePath, PathSet & stateReferrers, const int revision) { - nix::queryStateReferrers(noTxn, storePath, stateReferrers); + nix::queryStateReferrers(noTxn, storePath, stateReferrers, revision); } @@ -630,11 +642,9 @@ void addStateDeriver(const Transaction & txn, const Path & storePath, const Path } -//TODO Add and .. bool isStateComponentTxn(const Transaction & txn, const Path & storePath) { isValidPathTxn(txn, storePath); - string data; return nixDB.queryString(txn, dbStateInfo, storePath, data); } @@ -645,12 +655,10 @@ bool LocalStore::isStateComponent(const Path & storePath) } -//TODO Add and .. bool isStateDrvPathTxn(const Transaction & txn, const Path & drvPath) { printMsg(lvlError, format("Sssssssssssssssssss %1%") % drvPath); Derivation drv = derivationFromPath(drvPath); - printMsg(lvlError, format("uuuuuuuuuuuuuuuuuu %1%") % drvPath); return isStateDrvTxn(txn, drv); } @@ -659,7 +667,6 @@ bool LocalStore::isStateDrvPath(const Path & isStateDrv) return nix::isStateDrvPathTxn(noTxn, isStateDrv); } -//TODO Add and .. bool isStateDrvTxn(const Transaction & txn, const Derivation & drv) { if (drv.stateOutputs.size() != 0) @@ -1114,7 +1121,7 @@ void LocalStore::exportPath(const Path & path, bool sign, writeString(path, hashAndWriteSink); PathSet references; - nix::queryReferences(txn, path, references); + nix::queryReferences(txn, path, references, -1); //TODO we can only now export the final revision writeStringSet(references, hashAndWriteSink); Path deriver = queryDeriver(txn, path); @@ -1277,7 +1284,7 @@ void deleteFromStore(const Path & _path, unsigned long long & bytesFreed) Transaction txn(nixDB); if (isValidPathTxn(txn, path)) { - PathSet referrers = getReferrers(txn, path); + PathSet referrers = getReferrers(txn, path, -1); //delete latest referrers (TODO?) for (PathSet::iterator i = referrers.begin(); i != referrers.end(); ++i) if (*i != path && isValidPathTxn(txn, *i)) @@ -1396,7 +1403,7 @@ void verifyStore(bool checkContents) else { bool isValid = validPaths.find(*i) != validPaths.end(); PathSet references; - queryReferences(txn, *i, references); + queryReferences(txn, *i, references, -1); //TODO for (PathSet::iterator j = references.begin(); j != references.end(); ++j) { @@ -1445,10 +1452,10 @@ void verifyStore(bool checkContents) else { PathSet references; - queryReferences(txn, from, references); + queryReferences(txn, from, references, -1); //TODO PathSet stateReferences; //already a stateReferrers here! - queryStateReferences(txn, from, stateReferences); + queryStateReferences(txn, from, stateReferences, -1); //TODO CHECK FOR ALL REVISIONS ! if (find(references.begin(), references.end(), to) == references.end()) { printMsg(lvlError, format("adding missing referrer mapping from `%1%' to `%2%'") % from % to); @@ -1702,8 +1709,8 @@ void scanAndUpdateAllReferencesTxn(const Transaction & txn, const Path & statePa //Retrieve old references PathSet old_references; PathSet old_state_references; - queryReferences(txn, statePath, old_references); - queryStateReferences(txn, statePath, old_state_references); + queryReferences(txn, statePath, old_references, -1); //get the latsest references + queryStateReferences(txn, statePath, old_state_references, -1); //Check for added and removed paths PathSet diff_references_removed; @@ -1872,7 +1879,7 @@ static void upgradeStore07() } PathSet prevReferences; - queryReferences(txn, path, prevReferences); + queryReferences(txn, path, prevReferences, -1); if (prevReferences.size() > 0 && references != prevReferences) printMsg(lvlError, format("warning: conflicting references for `%1%'") % path); diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index baa91eec5..fe077a124 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -51,13 +51,13 @@ public: Path queryStatePathDrv(const Path & statePath); - void queryReferences(const Path & path, PathSet & references); + void queryReferences(const Path & path, PathSet & references, const int revision); - void queryStateReferences(const Path & storePath, PathSet & stateReferences); + void queryStateReferences(const Path & storePath, PathSet & stateReferences, const int revision); - void queryReferrers(const Path & path, PathSet & referrers); + void queryReferrers(const Path & path, PathSet & referrers, const int revision); - void queryStateReferrers(const Path & path, PathSet & stateReferrers); + void queryStateReferrers(const Path & path, PathSet & stateReferrers, const int revision); Path addToStore(const Path & srcPath, bool fixed = false, bool recursive = false, string hashAlgo = "", diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc index adf0bbd15..ad23768a5 100644 --- a/src/libstore/misc.cc +++ b/src/libstore/misc.cc @@ -11,7 +11,9 @@ namespace nix { Derivation derivationFromPath(const Path & drvPath) { assertStorePath(drvPath); + printMsg(lvlError, format("tttttttttttttttttt")); store->ensurePath(drvPath); + printMsg(lvlError, format("uuuuuuuuuuuuuuuuuu")); ATerm t = ATreadFromNamedFile(drvPath.c_str()); if (!t) throw Error(format("cannot read aterm from `%1%'") % drvPath); return parseDerivation(t); @@ -58,12 +60,12 @@ void computeFSClosureRec(const Path & path, PathSet & paths, const bool & flipDi PathSet stateReferences; if (flipDirection){ - store->queryReferrers(path, references); - store->queryStateReferrers(path, stateReferences); + store->queryReferrers(path, references, -1); + store->queryStateReferrers(path, stateReferences, -1); } else{ - store->queryReferences(path, references); - store->queryStateReferences(path, stateReferences); + store->queryReferences(path, references, -1); + store->queryStateReferences(path, stateReferences, -1); } PathSet allReferences; @@ -122,7 +124,7 @@ void queryMissing(const PathSet & targets, if (store->hasSubstitutes(p)) willSubstitute.insert(p); PathSet refs; - store->queryReferences(p, todo); + store->queryReferences(p, todo, -1); //TODO? } } } diff --git a/src/libstore/misc.hh b/src/libstore/misc.hh index 1cc713fc6..67e631a57 100644 --- a/src/libstore/misc.hh +++ b/src/libstore/misc.hh @@ -18,8 +18,10 @@ Derivation derivationFromPath(const Path & drvPath); `storePath' is returned; that is, the closures under the `referrers' relation instead of the `references' relation is - withState = TODO comment - withComponents = TODO + withState = include the state paths into the closure + withComponents = include the component paths into the closure + + We can currentky only compute the closure of the latsest revision! returned. */ void computeFSClosure(const Path & storePath, PathSet & paths, const bool & withComponents, const bool & withState, bool flipDirection = false); diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index a657eba41..10e55b4c2 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -216,44 +216,49 @@ Path RemoteStore::queryStatePathDrv(const Path & statePath) } void RemoteStore::queryReferences(const Path & path, - PathSet & references) + PathSet & references, const int revision) { writeInt(wopQueryReferences, to); writeString(path, to); processStderr(); PathSet references2 = readStorePaths(from); references.insert(references2.begin(), references2.end()); + //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! include revision? } void RemoteStore::queryStateReferences(const Path & path, - PathSet & stateReferences) + PathSet & stateReferences, const int revision) { writeInt(wopQueryStateReferences, to); writeString(path, to); processStderr(); PathSet stateReferences2 = readStorePaths(from); stateReferences.insert(stateReferences2.begin(), stateReferences2.end()); + //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! include revision? } void RemoteStore::queryReferrers(const Path & path, - PathSet & referrers) + PathSet & referrers, const int revision) { writeInt(wopQueryReferrers, to); writeString(path, to); processStderr(); PathSet referrers2 = readStorePaths(from); referrers.insert(referrers2.begin(), referrers2.end()); + //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! include revision? } -void RemoteStore::queryStateReferrers(const Path & path, PathSet & stateReferrers) +void RemoteStore::queryStateReferrers(const Path & path, + PathSet & stateReferrers, const int revision) { writeInt(wopQueryStateReferrers, to); writeString(path, to); processStderr(); PathSet stateReferrers2 = readStorePaths(from); stateReferrers.insert(stateReferrers2.begin(), stateReferrers2.end()); + //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! include revision? } diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh index 5cdd9f1d0..43fe6c80a 100644 --- a/src/libstore/remote-store.hh +++ b/src/libstore/remote-store.hh @@ -39,13 +39,13 @@ public: Path queryStatePathDrv(const Path & statePath); - void queryReferences(const Path & path, PathSet & references); + void queryReferences(const Path & path, PathSet & references, const int revision); - void queryStateReferences(const Path & storePath, PathSet & stateReferences); + void queryStateReferences(const Path & storePath, PathSet & stateReferences, const int revision); - void queryReferrers(const Path & path, PathSet & referrers); + void queryReferrers(const Path & path, PathSet & referrers, const int revision); - void queryStateReferrers(const Path & path, PathSet & stateReferrers); + void queryStateReferrers(const Path & path, PathSet & stateReferrers, const int revision); Path addToStore(const Path & srcPath, bool fixed = false, bool recursive = false, string hashAlgo = "", diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index e0b3f5b1b..da0c00fc2 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -81,20 +81,20 @@ public: /* Queries the set of outgoing FS references for a store path. The result is not cleared. */ virtual void queryReferences(const Path & path, - PathSet & references) = 0; + PathSet & references, const int revision) = 0; /* Queries the set of outgoing FS state-references for a store path. The result is not cleared. */ - virtual void queryStateReferences(const Path & storePath, PathSet & stateReferences) = 0; + virtual void queryStateReferences(const Path & storePath, PathSet & stateReferences, const int revision) = 0; /* Queries the set of incoming FS references for a store path. The result is not cleared. */ virtual void queryReferrers(const Path & path, - PathSet & referrers) = 0; + PathSet & referrers, const int revision) = 0; /* Queries the set of incoming FS state-references for a store path. The result is not cleared. */ - virtual void queryStateReferrers(const Path & path, PathSet & stateReferrers) = 0; + virtual void queryStateReferrers(const Path & path, PathSet & stateReferrers, const int revision) = 0; /* Copy the contents of a path to the store and register the validity the resulting path. The resulting path is returned. diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 4387c91f0..d85ac6349 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -806,20 +806,78 @@ string runProgram(Path program, bool searchPath, const Strings & args) } catch (std::exception & e) { std::cerr << "error: " << e.what() << std::endl; } + quickExit(1); } /* Parent. */ pipe.writeSide.close(); + + + // Create a pipe. + Pipe pipe2; + pipe2.create(); - string result = drainFD(pipe.readSide); + // Fork. + Pid pid2; + pid2 = fork(); + switch (pid2) { + + case -1: + throw SysError("unable to fork"); + + case 0: // child + try { + + pipe2.readSide.close(); + + if (dup2(pipe2.writeSide, STDOUT_FILENO) == -1) + throw SysError("dupping from-hook write side"); + + dup2(pipe.readSide, STDIN_FILENO); + + Path s = "grep"; + Strings args2; + args2.push_back("Revision"); + + std::vector cargs; // careful with c_str()! + cargs.push_back(s.c_str()); + for (Strings::const_iterator i = args2.begin(); i != args2.end(); ++i) + cargs.push_back(i->c_str()); + cargs.push_back(0); + + if (searchPath) + execvp(s.c_str(), (char * *) &cargs[0]); + else + execv(s.c_str(), (char * *) &cargs[0]); + throw SysError(format("executing `%1%'") % s); + + } catch (std::exception & e) { + std::cerr << "error: " << e.what() << std::endl; + } + + quickExit(1); + } + + /* Parent. */ + + pipe2.writeSide.close(); + + + string result = drainFD(pipe2.readSide); /* Wait for the child to finish. */ int status = pid.wait(true); if (!statusOk(status)) throw Error(format("program `%1%' %2%") % program % statusToString(status)); + + /* wait for second ........... */ + int status2 = pid2.wait(true); + if (!statusOk(status2)) + throw Error(format("program `%1%' %2%") + % program % statusToString(status)); return result; } @@ -1149,44 +1207,21 @@ string getCallingUserName() //merges two PathSets into one, removing doubles (union) PathSet pathSets_union(const PathSet & paths1, const PathSet & paths2) { - /* - for (PathSet::iterator i = paths1.begin(); i != paths1.end(); ++i) - printMsg(lvlError, format("paths1: '%1%'") % (*i)); - for (PathSet::iterator i = paths2.begin(); i != paths2.end(); ++i) - printMsg(lvlError, format("paths2: '%1%'") % (*i)); - */ - vector vector1(paths1.begin(), paths1.end()); vector vector2(paths2.begin(), paths2.end()); vector setResult; - set_union(vector1.begin(), vector1.end(),vector2.begin(), vector2.end(), back_inserter(setResult)); - - //Also available: - //set_symmetric_difference - //set_intersection + set_union(vector1.begin(), vector1.end(),vector2.begin(), vector2.end(), back_inserter(setResult)); //Also available: set_symmetric_difference and set_intersection PathSet diff; for(int i=0; isecond; + DerivationStateOutputs stateOutputs = drv.stateOutputs; + Path statePath = stateOutputs.find("state")->second.statepath; + string getStateIdentifier = stateOutputs.find("state")->second.stateIdentifier; + + for (DerivationStateOutputDirs::const_reverse_iterator i = stateOutputDirs.rbegin(); i != stateOutputDirs.rend(); ++i){ + DerivationStateOutputDir d = i->second; + string thisdir = d.path; + + //Get the a repository for this state location + string repos = getStateReposPath("stateOutput:staterepospath", statePath, thisdir, drvName, getStateIdentifier); //this is a copy from store-state.cc + + if(IsDirectory(repos)){ + printMsg(lvlError, format("'%1%'") % repos); + Strings p_args; + p_args.push_back("info"); + p_args.push_back("file://" + repos); + + string output = runProgram(svnbin, true, p_args); + + /* + p_args.clear(); + p_args.push_back("-n"); + p_args.push_back("/^Revision: /p"); + p_args.push_back(output); + output = runProgram("sed", true, p_args); + */ + + printMsg(lvlError, format("%2%") % repos % output); + } + + } + + //svn info $repos | sed -n '/^Revision: /p' | sed 's/Revision: //' | tr -d "\12" + + return revisions; +} + //Comment TODO PathSet getAllStateDerivationsRecursively(const Path & storePath) { @@ -260,8 +304,7 @@ static void opRunComponent(Strings opFlags, Strings opArgs) int intervalAt=0; for (DerivationStateOutputDirs::const_reverse_iterator i = stateOutputDirs.rbegin(); i != stateOutputDirs.rend(); ++i){ DerivationStateOutputDir d = i->second; - - string thisdir = d.path; //TODO CONVERT + string thisdir = d.path; string fullstatedir = statePath + "/" + thisdir; if(thisdir == "/") //exception for the root dir @@ -298,7 +341,7 @@ static void opRunComponent(Strings opFlags, Strings opArgs) } //Update the intervals again - //store->setStatePathsInterval(intervalPaths, intervals); //TODO UNCOMMENT + store->setStatePathsInterval(intervalPaths, intervals); //Call the commit script with the appropiate paramenters string subversionedstatepathsarray; @@ -323,7 +366,7 @@ static void opRunComponent(Strings opFlags, Strings opArgs) commandsarray += "" + *(i) + " | "; } - //make the call + //make the call to the commit script Strings p_args; p_args.push_back(svnbin); p_args.push_back(subversionedstatepathsarray); @@ -333,8 +376,11 @@ static void opRunComponent(Strings opFlags, Strings opArgs) runProgram_AndPrintOutput(nixLibexecDir + "/nix/nix-statecommit.sh", true, p_args, "svn"); //TODO - //Scan again?? + //Scan if needed //scanAndUpdateAllReferencesRecusively ... + + //TODO + //Update all revision numbers in the database } } @@ -403,10 +449,7 @@ void run(Strings args) store = openStore(); //setReferences_statePath("/nix/state/afsdsdafsdaf-sdaf", 7); - return; - - */ - + Paths p1; p1.push_back("a"); p1.push_back("b"); @@ -419,6 +462,21 @@ void run(Strings args) for (PathSet::iterator i = px.begin(); i != px.end(); ++i) printMsg(lvlError, format("MERGED: %1%") % *i); + + Database nixDB; + Path statePath = "afsdsdafsadf-sda-fsda-f-sdaf-sdaf"; + int revision = 5; + Path statePath2; + Path gets = nixDB.makeStatePathRevision(statePath, revision); + int revision2; + nixDB.splitStatePathRevision(gets, statePath2, revision2); + printMsg(lvlError, format("'%1%' '%2%'") % statePath2 % int2String(revision2)); + + */ + + store = openStore(); + Derivation drv = derivationFromPath("/nix/store/r2lvhrd8zhb877n07cqvcyp11j9ws5p0-hellohardcodedstateworld-dep1-1.0.drv"); + readRevisionNumbers(drv); return; /* test */ diff --git a/src/nix-store/dotgraph.cc b/src/nix-store/dotgraph.cc index 989945600..674c174f5 100644 --- a/src/nix-store/dotgraph.cc +++ b/src/nix-store/dotgraph.cc @@ -112,7 +112,7 @@ void printDotGraph(const PathSet & roots) cout << makeNode(path, symbolicName(path), "#ff0000"); PathSet references; - store->queryReferences(path, references); + store->queryReferences(path, references, -1); //TODO maybe also include state paths? for (PathSet::iterator i = references.begin(); i != references.end(); ++i) diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index e9d8784e6..55a0235a8 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -212,7 +212,7 @@ static void printTree(const Path & path, cout << format("%1%%2%\n") % firstPad % path; PathSet references; - store->queryReferences(path, references); + store->queryReferences(path, references, -1); //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Adjust printTree, include state paths! #if 0 for (PathSet::iterator i = drv.inputSrcs.begin(); @@ -307,10 +307,10 @@ static void opQuery(Strings opFlags, Strings opArgs) if (query == qRequisites) store->storePathRequisites(path, includeOutputs, paths, true, false); else if (query == qRequisitesState) store->storePathRequisites(path, includeOutputs, paths, false, true); else if (query == qRequisitesFull) store->storePathRequisites(path, includeOutputs, paths, true, true); - else if (query == qReferences) store->queryReferences(path, paths); - else if (query == qStateReferences) store->queryStateReferences(path, paths); - else if (query == qReferrers) store->queryReferrers(path, paths); - else if (query == qStateReferrers) store->queryStateReferrers(path, paths); + else if (query == qReferences) store->queryReferences(path, paths, -1); + else if (query == qStateReferences) store->queryStateReferences(path, paths, -1); //latest revision + else if (query == qReferrers) store->queryReferrers(path, paths, -1); + else if (query == qStateReferrers) store->queryStateReferrers(path, paths, -1); //latest revision else if (query == qReferrersClosure) computeFSClosure(path, paths, true, false, true); else if (query == qReferrersClosureWithState) computeFSClosure(path, paths, true, true, true); } diff --git a/src/nix-worker/nix-worker.cc b/src/nix-worker/nix-worker.cc index 0b454d3f6..03c523d04 100644 --- a/src/nix-worker/nix-worker.cc +++ b/src/nix-worker/nix-worker.cc @@ -296,9 +296,9 @@ static void performOp(Source & from, Sink & to, unsigned int op) startWork(); PathSet paths; if (op == wopQueryReferences) - store->queryReferences(path, paths); + store->queryReferences(path, paths, -1); else - store->queryReferrers(path, paths); + store->queryReferrers(path, paths, -1); stopWork(); writeStringSet(paths, to); break; @@ -310,9 +310,9 @@ static void performOp(Source & from, Sink & to, unsigned int op) startWork(); PathSet paths; if (op == wopQueryStateReferences) - store->queryStateReferences(path, paths); + store->queryStateReferences(path, paths, -1); else - store->queryStateReferrers(path, paths); //TODO Does this work???, how about the state path????????? + store->queryStateReferrers(path, paths, -1); //TODO Does this work???, how about the state path????????? stopWork(); writeStringSet(paths, to); break;