From 3d22bd50b302d80c08a973cf1d274a033a8a5618 Mon Sep 17 00:00:00 2001 From: Wouter den Breejen Date: Wed, 27 Jun 2007 15:43:16 +0000 Subject: [PATCH] nix-state now works, state is recursively commited (when necessary) --- scripts/nix-statecommit.sh.in | 15 +- src/libstore/build.cc | 22 +- src/libstore/local-store.cc | 121 ++++++++-- src/libstore/local-store.hh | 6 + src/libstore/misc.cc | 57 +++-- src/libstore/misc.hh | 5 +- src/libstore/remote-store.cc | 14 ++ src/libstore/remote-store.hh | 3 + src/libstore/store-api.cc | 28 ++- src/libstore/store-api.hh | 15 +- src/libstore/store-state.cc | 15 +- src/libstore/worker-protocol.hh | 1 + src/libutil/util.cc | 24 +- src/nix-state/nix-state.cc | 381 ++++++++++++++++---------------- src/nix-store/help.txt | 5 +- src/nix-store/nix-store.cc | 11 +- src/nix-worker/nix-worker.cc | 11 +- 17 files changed, 457 insertions(+), 277 deletions(-) diff --git a/scripts/nix-statecommit.sh.in b/scripts/nix-statecommit.sh.in index 528169e96..7f8b73662 100755 --- a/scripts/nix-statecommit.sh.in +++ b/scripts/nix-statecommit.sh.in @@ -22,12 +22,15 @@ nonversionedpaths=( $4 ) checkouts=( $5 ) deletesvn=$6 #this flag can be set to 1 to DELETE all .svn folders and NOT commit -echo svnbin: $svnbin -echo subversionedpaths: ${subversionedpaths[@]} -echo subversionedpathsCommitBools: ${subversionedpathsCommitBools[@]} -echo nonversionedpaths: ${nonversionedpaths[@]} -echo checkouts: ${checkouts[@]} -echo deletesvn: $deletesvn + +if [ "$debug" != "" ] ; then + echo svnbin: $svnbin + echo subversionedpaths: ${subversionedpaths[@]} + echo subversionedpathsCommitBools: ${subversionedpathsCommitBools[@]} + echo nonversionedpaths: ${nonversionedpaths[@]} + echo checkouts: ${checkouts[@]} + echo deletesvn: $deletesvn +fi # # diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 016e850d4..573e81bf4 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -1629,6 +1629,7 @@ void DerivationGoal::computeClosure() if(!drv.stateOutputs.find("state")->second.getCreateDirsBeforeInstall()) createStateDirs(drv.stateOutputDirs, drv.stateOutputs, drv.env); + /* Check whether the output paths were created, and grep each output path to determine what other paths it references. Also make all output paths read-only. */ @@ -1681,7 +1682,7 @@ void DerivationGoal::computeClosure() format("output path `%1%' should have %2% hash `%3%', instead has `%4%'") % path % algo % printHash(h) % printHash(h2)); } - + /* Get rid of all weird permissions. */ canonicalisePathMetaData(path); @@ -1719,7 +1720,7 @@ void DerivationGoal::computeClosure() if we could combine this with filterReferences(). */ contentHashes[path] = hashPath(htSHA256, path); } - + /* Register each output path as valid, and register the sets of paths referenced by each of them. This is wrapped in one database transaction to ensure that if we crash, either @@ -1737,6 +1738,8 @@ void DerivationGoal::computeClosure() for (DerivationOutputs::iterator i = drv.outputs.begin(); i != drv.outputs.end(); ++i) { + //printMsg(lvlError, format("SetValidPath: %1%") % i->second.path); + registerValidPath(txn, i->second.path, "", //dummy statePath contentHashes[i->second.path], @@ -1744,19 +1747,22 @@ void DerivationGoal::computeClosure() PathSet(), //dummy stateReferences drvPath); } - + /* * We first register alls paths as valid, and only scan for component references. * Now that those paths are registered as valid, we're able to call queryDeriversStatePath * - * We already scanned for Component references in Component paths - * Now we scan in Component paths for state references + * We already scanned for [Component references in Component paths] //1 + * Now we scan in [Component paths for state references] //2 * * If state is enabled for the path we: - * scan for and state references and component references in the state path + * [scan for and state references and component references in the state path] //3,4 */ //TODO we scan for each output, be then we do multiple scans inside for the state path ..... + + //TODO !!!!!!!!! we don not ONLY need to scan all outputs, but also (recursively) the component references in the state folders + for (DerivationOutputs::iterator i = drv.outputs.begin(); i != drv.outputs.end(); ++i) { Path path = i->second.path; @@ -1770,7 +1776,7 @@ void DerivationGoal::computeClosure() Path componentPath = *i; if(isStateComponentTxn(txn, componentPath)){ - //printMsg(lvlError, format("Scanning for state path: %1%") % (*i)); + //printMsg(lvlError, format("Scanning for state path: %1%") % componentPath); PathSet stateRefs = queryDeriversStatePath(txn, componentPath ,"*",getCallingUserName()); allStatePaths = mergePathSets(stateRefs, allStatePaths); } @@ -1783,7 +1789,7 @@ void DerivationGoal::computeClosure() if(isStateDrvTxn(txn, drv)){ Path statePath = drv.stateOutputs.find("state")->second.statepath; printMsg(lvlTalkative, format("scanning for component and state references inside `%1%'") % statePath); - + PathSet state_references = scanForReferences(statePath, allPaths); PathSet state_stateReferences = scanForStateReferences(statePath, allStatePaths); all_state_references = mergePathSets(all_state_references, mergePathSets(state_references, state_stateReferences)); diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 907c82e1f..0077e838f 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -507,16 +507,24 @@ void LocalStore::queryStateReferrers(const Path & storePath, PathSet & stateRefe void setDeriver(const Transaction & txn, const Path & storePath, const Path & deriver) { + printMsg(lvlError, format("xxxxxxxxxxxxxxxxxxxxxxx")); + assertStorePath(storePath); + printMsg(lvlError, format("Ttttttttttttttttttttttttt")); if (deriver == "") return; + printMsg(lvlError, format("uuuuuuuuuuuuuuuuuuuuuuuuuuuuu")); assertStorePath(deriver); + printMsg(lvlError, format("yyyyyyyyyyyyyyyyyyyyyyyyy")); + if (!isRealisablePath(txn, storePath)) throw Error(format("path `%1%' is not valid") % storePath); if (isStateDrvPathTxn(txn, deriver)){ //Redirect if its a state component + printMsg(lvlError, format("bbbbbbbbbbbbbbb")); addStateDeriver(txn, storePath, deriver); } else{ + printMsg(lvlError, format("ccccccccccccccccccc")); nixDB.setString(txn, dbDerivers, storePath, deriver); } } @@ -530,13 +538,19 @@ void addStateDeriver(const Transaction & txn, const Path & storePath, const Path if (!isRealisablePath(txn, storePath)) throw Error(format("path `%1%' is not valid") % storePath); + printMsg(lvlError, format("dddddddddddddd")); + Derivation drv = derivationFromPath(deriver); string identifier = drv.stateOutputs.find("state")->second.stateIdentifier; string user = drv.stateOutputs.find("state")->second.username; + + printMsg(lvlError, format("eeeeeeeeeeeeeeeeee")); PathSet currentDerivers = queryDerivers(txn, storePath, identifier, user); PathSet updatedDerivers = mergeNewDerivationIntoList(storePath, deriver, currentDerivers, true); + printMsg(lvlError, format("ffffffffffffffffffff")); + Strings data; for (PathSet::iterator i = updatedDerivers.begin(); i != updatedDerivers.end(); ++i) //Convert Paths to Strings data.push_back(*i); @@ -597,7 +611,7 @@ Path queryDeriver(const Transaction & txn, const Path & storePath) bool b = nixDB.queryString(txn, dbDerivers, storePath, deriver); Derivation drv = derivationFromPath(deriver); - if (drv.outputs.size() != 0) + if (isStateDrvTxn(txn, drv)) throw Error(format("This deriver `%1%' is a state deriver, u should use queryDerivers instead of queryDeriver") % deriver); if (b) @@ -769,18 +783,14 @@ void clearSubstitutes() static void setHash(const Transaction & txn, const Path & storePath, const Hash & hash, bool stateHash = false) { - if(stateHash){ - nixDB.setString(txn, dbValidStatePaths, storePath, ""); - } - else{ - nixDB.setString(txn, dbValidPaths, storePath, "sha256:" + printHash(hash)); - assert(hash.type == htSHA256); - } + nixDB.setString(txn, dbValidPaths, storePath, "sha256:" + printHash(hash)); + assert(hash.type == htSHA256); } -static void setStateHash(const Transaction & txn, const Path & storePath, const Hash & hash) +static void setStateValid(const Transaction & txn, const Path & statePath, const Path & drvPath) { - setHash(txn, storePath, hash, true); + printMsg(lvlError, format("setStateValid: '%1%' '%2%'") % statePath % drvPath); + nixDB.setString(txn, dbValidStatePaths, statePath, drvPath); } static Hash queryHash(const Transaction & txn, const Path & storePath) @@ -806,6 +816,20 @@ Hash LocalStore::queryPathHash(const Path & path) return queryHash(noTxn, path); } +static Path queryStatePathDrv(const Transaction & txn, const Path & statePath) +{ + string s; + nixDB.queryString(txn, dbValidStatePaths, statePath, s); + return s; +} + +Path LocalStore::queryStatePathDrv(const Path & statePath) +{ + if (!isValidStatePath(statePath)) + throw Error(format("statepath `%1%' is not valid") % statePath); + return nix::queryStatePathDrv(noTxn, statePath); +} + void registerValidPath(const Transaction & txn, const Path & path, const Path & statePath, const Hash & hash, @@ -839,19 +863,18 @@ void registerValidPaths(const Transaction & txn, const ValidPathInfos & infos) setHash(txn, i->path, i->hash); if (i->statePath != "") - setStateHash(txn, i->statePath, Hash()); //the hash value in the db now becomes empty, but if the key exists, we know that the state path is valid + setStateValid(txn, i->statePath, i->deriver); //if the key exists, we know that the state path is valid, we set the value to the drvPath setReferences(txn, i->path, i->references, i->stateReferences); - + /* Check that all referenced paths are also valid (or about to) become valid). */ + //TODO Maybe also check this for stateReferences???? 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); - - //TODO Also do this for stateReferences???? - + setDeriver(txn, i->path, i->deriver); } } @@ -1489,11 +1512,79 @@ void storePathRequisites(const Path & storePath, const bool includeOutputs, Path } } +/* + * Same as storePathRequisites with withState=true, but now only returns the state paths + */ +void storePathStateRequisitesOnlyTxn(const Transaction & txn, const Path & storePath, const bool includeOutputs, PathSet & statePaths) +{ + PathSet paths; + storePathRequisites(storePath, includeOutputs, paths, true); + + //filter out all non-state paths + for (PathSet::iterator i = paths.begin(); i != paths.end(); ++i){ + if (isValidStatePathTxn(txn, *i)) + statePaths.insert(*i); + } +} + +void LocalStore::storePathStateRequisitesOnly(const Path & storePath, const bool includeOutputs, PathSet & statePaths) +{ + nix::storePathStateRequisitesOnlyTxn(noTxn, storePath, includeOutputs, statePaths); +} void LocalStore::storePathRequisites(const Path & storePath, const bool includeOutputs, PathSet & paths, const bool & withState) { return nix::storePathRequisites(storePath, includeOutputs, paths, withState); } +void convertStatePathsToDerivations(const Transaction & txn, const Path & storePath) +{ + //TODO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +} + +void getDependenciesAtBuildTime(const Transaction & txn, const Path & drvPath) +{ + Derivation drv = derivationFromPath(drvPath); + PathSet allPaths; + PathSet inputPaths; + + //TODO THIS IS A DIRECT COPY FROM BUILD.CC WE SHOULD MERGE !!!!!!!!!!!!1!!!!!!!!!!!!! + + /* The outputs are referenceable paths. */ + for (DerivationOutputs::iterator i = drv.outputs.begin(); + i != drv.outputs.end(); ++i) + { + debug(format("building path `%1%'") % i->second.path); + allPaths.insert(i->second.path); + } + + /* First, the input derivations. */ + for (DerivationInputs::iterator i = drv.inputDrvs.begin(); + i != drv.inputDrvs.end(); ++i) + { + /* Add the relevant output closures of the input derivation + `*i' as input paths. Only add the closures of output paths + that are specified as inputs. */ + assert(store->isValidPath(i->first)); + Derivation inDrv = derivationFromPath(i->first); + for (StringSet::iterator j = i->second.begin(); j != i->second.end(); ++j) + if (inDrv.outputs.find(*j) != inDrv.outputs.end()) + computeFSClosure(inDrv.outputs[*j].path, inputPaths, false); //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!! WE (MAY) ALSO NEED TO COPY STATE + else + throw Error(format("derivation `%1%' requires non-existent output `%2%' from input derivation `%3%'") % drvPath % *j % i->first); + } + + /* Second, the input sources. */ + for (PathSet::iterator i = drv.inputSrcs.begin(); i != drv.inputSrcs.end(); ++i) + computeFSClosure(*i, inputPaths, false); //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!! WE (MAY) ALSO NEED TO COPY STATE + + //debug(format("added input paths %1%") % showPaths(inputPaths)); //TODO + allPaths.insert(inputPaths.begin(), inputPaths.end()); + + for (PathSet::iterator i = allPaths.begin(); i != allPaths.end(); ++i) + printMsg(lvlError, format("ALLPATHS2: %1%") % *i); +} + /* Upgrade from schema 1 (Nix <= 0.7) to schema 2 (Nix >= 0.8). */ static void upgradeStore07() { diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index 0a8925744..b1087960e 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -48,6 +48,8 @@ public: Substitutes querySubstitutes(const Path & srcPath); Hash queryPathHash(const Path & path); + + Path queryStatePathDrv(const Path & statePath); void queryReferences(const Path & path, PathSet & references); @@ -96,6 +98,8 @@ public: void storePathRequisites(const Path & storePath, const bool includeOutputs, PathSet & paths, const bool & withState); + void storePathStateRequisitesOnly(const Path & storePath, const bool includeOutputs, PathSet & statePaths); + }; @@ -205,6 +209,8 @@ bool isStateComponentTxn(const Transaction & txn, const Path & path); bool isStateDrvPathTxn(const Transaction & txn, const Path & drvPath); bool isStateDrvTxn(const Transaction & txn, const Derivation & drv); + +void convertStatePathsToDerivations(const Transaction & txn, const Path & storePath); } diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc index f784d245b..905db7ac1 100644 --- a/src/libstore/misc.cc +++ b/src/libstore/misc.cc @@ -17,28 +17,32 @@ Derivation derivationFromPath(const Path & drvPath) return parseDerivation(t); } - -/* -void computeFSClosure(const Path & storePath, - PathSet & paths, bool flipDirection) -{ - if (paths.find(storePath) != paths.end()) return; - paths.insert(storePath); - - PathSet references; - if (flipDirection) - store->queryReferrers(storePath, references); - else - store->queryReferences(storePath, references); - - for (PathSet::iterator i = references.begin(); i != references.end(); ++i) - computeFSClosure(*i, paths, flipDirection); -} -*/ - void computeFSClosure(const Path & path, PathSet & paths, const bool & withState, bool flipDirection) { - if (paths.find(path) != paths.end()) return; + PathSet allPaths; + computeFSClosureRec(path, allPaths, flipDirection); + + //if withState is false, we filter out all state paths + if(withState == false){ + for (PathSet::iterator i = allPaths.begin(); i != allPaths.end(); ++i){ + if ( ! store->isValidStatePath(*i) ){ + paths.insert(*i); + + //TODO (OBSOLETE) CHECK TO SEE IF THERE WERE NO /NIX/STATE PATHS THAT ARENT VALID AT THIS POINT, REMOVE THIS IN THE FUTURE + string test = "/nix/state"; + if((*i).substr(0, test.size()) == test) + throw Error(format("THIS CANNOT HAPPEN ! computeFSClosure is called before the state path was valid....")); + } + } + } + else{ + paths = allPaths; + } +} + +void computeFSClosureRec(const Path & path, PathSet & paths, const bool & flipDirection) +{ + if (paths.find(path) != paths.end()) return; //takes care of double entries paths.insert(path); @@ -47,23 +51,18 @@ void computeFSClosure(const Path & path, PathSet & paths, const bool & withState if (flipDirection){ store->queryReferrers(path, references); - if(withState) - store->queryStateReferrers(path, stateReferences); + store->queryStateReferrers(path, stateReferences); } else{ store->queryReferences(path, references); - if(withState) - store->queryStateReferences(path, stateReferences); + store->queryStateReferences(path, stateReferences); } PathSet allReferences; - if(withState) - allReferences = mergePathSets(references, stateReferences); - else - allReferences = references; + allReferences = mergePathSets(references, stateReferences); for (PathSet::iterator i = allReferences.begin(); i != allReferences.end(); ++i) - computeFSClosure(*i, paths, withState, flipDirection); + computeFSClosureRec(*i, paths, flipDirection); } diff --git a/src/libstore/misc.hh b/src/libstore/misc.hh index 5ae3c984f..1af328e36 100644 --- a/src/libstore/misc.hh +++ b/src/libstore/misc.hh @@ -18,8 +18,9 @@ Derivation derivationFromPath(const Path & drvPath); `storePath' is returned; that is, the closures under the `referrers' relation instead of the `references' relation is returned. */ -void computeFSClosure(const Path & storePath, - PathSet & paths, const bool & withState, bool flipDirection = false); +void computeFSClosure(const Path & storePath, PathSet & paths, const bool & withState, bool flipDirection = false); + +void computeFSClosureRec(const Path & path, PathSet & paths, const bool & flipDirection); //private /* Return the path corresponding to the output identifier `id' in the given derivation. */ diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index c299da2c2..7e2472776 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -206,6 +206,14 @@ Hash RemoteStore::queryPathHash(const Path & path) return parseHash(htSHA256, hash); } +Path RemoteStore::queryStatePathDrv(const Path & statePath) +{ + writeInt(wopQueryStatePathDrv, to); + writeString(statePath, to); + processStderr(); + Path p = readString(from); //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!! check wheter from is the state path ???? + return p; +} void RemoteStore::queryReferences(const Path & path, PathSet & references) @@ -449,4 +457,10 @@ void RemoteStore::storePathRequisites(const Path & storePath, const bool include } +//TODO +void RemoteStore::storePathStateRequisitesOnly(const Path & storePath, const bool includeOutputs, PathSet & statePaths) +{ + +} + } diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh index c5d7ca755..9d1a22f27 100644 --- a/src/libstore/remote-store.hh +++ b/src/libstore/remote-store.hh @@ -36,6 +36,8 @@ public: bool hasSubstitutes(const Path & path); Hash queryPathHash(const Path & path); + + Path queryStatePathDrv(const Path & statePath); void queryReferences(const Path & path, PathSet & references); @@ -84,6 +86,7 @@ public: void storePathRequisites(const Path & storePath, const bool includeOutputs, PathSet & paths, const bool & withState); + void storePathStateRequisitesOnly(const Path & storePath, const bool includeOutputs, PathSet & statePaths); private: AutoCloseFD fdSocket; diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 2a5114738..a9ba851d1 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -115,9 +115,7 @@ void checkStatePath(const Derivation & drv) Error(format("The statepath from the Derivation does not match the recalculated statepath, are u trying to spoof the statepath?")); } - - -Path makeStateReposPath(const string & type, const Path statePath, const string subfolder, const string & suffix, const string & stateIdentifier) +void calculateStateReposPath(const string & type, const Path statePath, const string subfolder, const string & suffix, const string & stateIdentifier, Path & rootPath, Path & fullPath) { //This is a little trick: we could use the same hash as the statepath, but we change it so the repository also gets a unique scannable hash Hash hash = hashString(htSHA256, statePath); @@ -127,7 +125,7 @@ Path makeStateReposPath(const string & type, const Path statePath, const string throw Error(format("Cannot create a repository for a subfolder without a name")); string hash_subfolder = type + ":sha256:" + printHash(hash) + ":" + subfolder; - string subfolder_ = printHash32(compressHash(hashString(htSHA256, hash_subfolder), 20)) + "-" + subfolder; + string subfolder2 = printHash32(compressHash(hashString(htSHA256, hash_subfolder), 20)) + "-" + subfolder; string suffix_stateIdentifier = stateIdentifier; if(suffix_stateIdentifier != "") @@ -140,9 +138,27 @@ Path makeStateReposPath(const string & type, const Path statePath, const string checkStoreName(suffix); checkStoreName(stateIdentifier); - return nixStoreStateRepos + "/" + rootPath = nixStoreStateRepos + "/" + printHash32(compressHash(hashString(htSHA256, s), 20)) - + "-" + suffix + suffix_stateIdentifier + "/" + subfolder_; + + "-" + suffix + suffix_stateIdentifier; + + fullPath = rootPath + "/" + subfolder2; +} + +Path getStateReposPath(const string & type, const Path statePath, const string subfolder, const string & suffix, const string & stateIdentifier) +{ + Path fullPath; + Path rootPath; + calculateStateReposPath(type, statePath, subfolder, suffix, stateIdentifier, rootPath, fullPath); + return fullPath; +} + +Path getStateReposRootPath(const string & type, const Path statePath, const string & suffix, const string & stateIdentifier) +{ + Path fullPath; + Path rootPath; + calculateStateReposPath(type, statePath, "/", suffix, stateIdentifier, rootPath, fullPath); + return rootPath; } Path makeFixedOutputPath(bool recursive, diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index a1de65b56..4f4131540 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -75,6 +75,9 @@ public: /* Queries the hash of a valid path. */ virtual Hash queryPathHash(const Path & path) = 0; + /* Queries the derivation Path of a valid state path. */ + virtual Path queryStatePathDrv(const Path & statePath) = 0; + /* Queries the set of outgoing FS references for a store path. The result is not cleared. */ virtual void queryReferences(const Path & path, @@ -212,7 +215,8 @@ public: virtual bool isStateDrv(const Derivation & drv) = 0; virtual void storePathRequisites(const Path & storePath, const bool includeOutputs, PathSet & paths, const bool & withState) = 0; - + + virtual void storePathStateRequisitesOnly(const Path & storePath, const bool includeOutputs, PathSet & statePaths) = 0; }; @@ -245,9 +249,14 @@ Path makeStatePath(const string & componentHash, const string & suffix, const st /* TODO ... */ void checkStatePath(const Derivation & drv); -/* Constructs a unique store state repos path name. */ -Path makeStateReposPath(const string & type, const Path statePath, const string subfolder, const string & suffix, const string & stateIdentifier); +/* Calculates a unique store state repos path and also the root path */ +void calculateStateReposPath(const string & type, const Path statePath, const string subfolder, const string & suffix, const string & stateIdentifier, Path & rootPath, Path & fullPath); +/* Returns the full repository path */ +Path getStateReposPath(const string & type, const Path statePath, const string subfolder, const string & suffix, const string & stateIdentifier); + +/* Returns the root path containing the repository's */ +Path getStateReposRootPath(const string & type, const Path statePath, const string & suffix, const string & stateIdentifier); /* This is the preparatory part of addToStore() and addToStoreFixed(); it computes the store path to which srcPath is to be copied. diff --git a/src/libstore/store-state.cc b/src/libstore/store-state.cc index 46f76c34d..91783e61e 100644 --- a/src/libstore/store-state.cc +++ b/src/libstore/store-state.cc @@ -39,6 +39,10 @@ void createStateDirs(const DerivationStateOutputDirs & stateOutputDirs, const De string svnadminbin = nixSVNPath + "/svnadmin"; PathSet intervalPaths; + + //Make sure the 'root' path which holds the repositorys exists, so svn doenst complain. + string repos_root_path = getStateReposRootPath("stateOutput:staterepospath", stateDir, drvName, stateIdentifier); + executeAndPrintShellCommand("mkdir -p " + repos_root_path, "mkdir"); //TODO check if we can create state and staterepos dirs @@ -56,13 +60,13 @@ void createStateDirs(const DerivationStateOutputDirs & stateOutputDirs, const De } //Create a repository for this state location - string repos = makeStateReposPath("stateOutput:staterepospath", stateDir, thisdir, drvName, stateIdentifier); - executeAndPrintShellCommand("mkdir -p " + repos, "mkdir"); + string repos = getStateReposPath("stateOutput:staterepospath", stateDir, thisdir, drvName, stateIdentifier); + if(IsDirectory(repos)) printMsg(lvlTalkative, format("Repos %1% already exists, so we use that repository") % repos); else - executeAndPrintShellCommand(svnadminbin + " create " + repos, "svnadmin"); //TODO create as nixbld.nixbld chmod 700... can you still commit than ?? + executeAndPrintShellCommand(svnadminbin + " create " + repos, "svnadmin"); //TODO create as nixbld.nixbld chmod 700... can you still commit then ?? if(d.type == "interval"){ intervalPaths.insert(statePath); @@ -70,12 +74,13 @@ void createStateDirs(const DerivationStateOutputDirs & stateOutputDirs, const De printMsg(lvlTalkative, format("Adding state subdir: %1% to %2% from repository %3%") % thisdir % fullstatedir % repos); - if(IsDirectory(fullstatedir + "/.svn/")){ + string fullstatedir_svn = fullstatedir + "/.svn/"; + if( ! IsDirectory(fullstatedir_svn) ){ string checkoutcommand = svnbin + " checkout file://" + repos + " " + fullstatedir; executeAndPrintShellCommand(checkoutcommand, "svn"); //TODO checkout as user } else - printMsg(lvlTalkative, format("Statedir %1% already exists, so dont check out its repository again") % fullstatedir); + printMsg(lvlTalkative, format("Statedir %1% already exists, so dont check out its repository again") % fullstatedir_svn); } //Initialize the counters for the statePaths that have an interval to 0 diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh index 343664c80..57f39ac36 100644 --- a/src/libstore/worker-protocol.hh +++ b/src/libstore/worker-protocol.hh @@ -17,6 +17,7 @@ typedef enum { wopQuerySubstitutes, wopHasSubstitutes, wopQueryPathHash, + wopQueryStatePathDrv, wopQueryReferences, wopQueryStateReferences, wopQueryReferrers, diff --git a/src/libutil/util.cc b/src/libutil/util.cc index b50f2e265..d0d7aeed6 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -1015,6 +1015,19 @@ string trim(const string & s) { //TODO , check if we can replace!!! with runProgram like this: string a = runProgram("whoami", true, s); +/* + + Strings args; + args.push_back("rsautl"); + args.push_back("-sign"); + args.push_back("-inkey"); + args.push_back(secretKey); + args.push_back("-in"); + args.push_back(hashFile); + string signature = runProgram(OPENSSL_PATH, true, args); + + */ + void executeAndPrintShellCommand(const string & command, const string & commandName) { string tempoutput = "/tmp/svnoutput.txt"; @@ -1073,20 +1086,18 @@ string time_t2string(const time_t & t) return s; } +//TODO Does this work on windows? bool FileExist(const string FileName) { const char* FileName_C = FileName.c_str(); - //strcpy(FileName_C, FileName.c_str()); - struct stat my_stat; return (stat(FileName_C, &my_stat) == 0); } +//TODO Does this work on windows? bool IsDirectory(const string FileName) { const char* FileName_C = FileName.c_str(); - //strcpy(FileName_C, FileName.c_str()); - struct stat my_stat; if (stat(FileName_C, &my_stat) != 0) return false; return ((my_stat.st_mode & S_IFDIR) != 0); @@ -1095,7 +1106,7 @@ bool IsDirectory(const string FileName) string getCallingUserName() { - //TODO Make this work on WINDOWS + //TODO Make this work on WINDOWS: Untested! /* #include char acUserName[100]; @@ -1109,12 +1120,11 @@ string getCallingUserName() //Linux Strings empty; string username = runProgram("whoami", true, empty); //the username of the user that is trying to build the component - //TODO Can and Should NOT be faked, so this is clearly unsafe ... :( + //TODO Can be faked, so this is clearly unsafe ... :( //Remove the \n int pos = username.find("\n",0); username.erase(pos,1); - //return "root6"; return username; } diff --git a/src/nix-state/nix-state.cc b/src/nix-state/nix-state.cc index 602cf688c..9a12956fa 100644 --- a/src/nix-state/nix-state.cc +++ b/src/nix-state/nix-state.cc @@ -18,6 +18,10 @@ using std::cout; typedef void (* Operation) (Strings opFlags, Strings opArgs); +//two global variables +string stateIdentifier; +string username; + /************************* Build time Functions ******************************/ @@ -36,12 +40,13 @@ void printHelp() // -Derivation getDerivation_andCheckArgs_(Strings opFlags, Strings opArgs, Path & componentPath, Path & statePath, string & stateIdentifier, string & binary, string & derivationPath, bool isStatePath, - bool getDerivers, PathSet & derivers, string & username) //optional +Derivation getDerivation_andCheckArgs_(Strings opFlags, Strings opArgs, Path & componentPath, Path & statePath, + string & binary, string & derivationPath, bool isStatePath, Strings & program_args, + bool getDerivers, PathSet & derivers) //optional { if (!opFlags.empty()) throw UsageError("unknown flag"); - if ( (opArgs.size() != 1 && opArgs.size() != 2) && (getDerivers && opArgs.size() != 3) ) - throw UsageError("only one or two arguments allowed component path / identiefier (or a third when you need to see the derivations: [username]) )"); + if ( opArgs.size() != 1 && opArgs.size() != 2 ) + throw UsageError("only one or two arguments allowed component path and program arguments (counts as one) "); //Parse the full path like /nix/store/...../bin/hello string fullPath = opArgs.front(); @@ -56,63 +61,67 @@ Derivation getDerivation_andCheckArgs_(Strings opFlags, Strings opArgs, Path & c //Check if path is statepath isStatePath = store->isStateComponent(componentPath); - + + //Extract the program arguments + string allargs; if(opArgs.size() > 1){ opArgs.pop_front(); - stateIdentifier = opArgs.front(); - } - - if(username == "") - username = getCallingUserName(); + allargs = opArgs.front(); + + Strings progam_args; + //TODO !!!!!!!!!!!!!!!!!!!!!! + } - //printMsg(lvlError, format("%1% - %2% - %3% - %4%") % componentPath % stateIdentifier % binary % username); + printMsg(lvlError, format("'%1%' - '%2%' - '%3%' - '%4%' - '%5%'") % componentPath % stateIdentifier % binary % username % allargs); - derivers = queryDerivers(noTxn, componentPath, stateIdentifier, username); + if(isStatePath) + derivers = queryDerivers(noTxn, componentPath, stateIdentifier, username); + else + derivers.insert(queryDeriver(noTxn, componentPath)); if(getDerivers == true) return Derivation(); - else if(derivers.size() == 0) - throw UsageError(format("There are no derivers with this combination of identifier '%1%' and username '%2%'") % stateIdentifier % username); - else if(derivers.size() != 1) - throw UsageError(format("There is more than one deriver with identifier '%1%' and username '%2%'") % stateIdentifier % username); + + if(isStatePath){ + if(derivers.size() == 0) + throw UsageError(format("There are no derivers with this combination of identifier '%1%' and username '%2%'") % stateIdentifier % username); + if(derivers.size() != 1) + throw UsageError(format("There is more than one deriver with stateIdentifier '%1%' and username '%2%'") % stateIdentifier % username); + } Derivation drv; for (PathSet::iterator i = derivers.begin(); i != derivers.end(); ++i){ //ugly workaround for drvs[0]. derivationPath = *i; drv = derivationFromPath(derivationPath); } - - DerivationStateOutputs stateOutputs = drv.stateOutputs; - statePath = stateOutputs.find("state")->second.statepath; + + if(isStatePath){ + DerivationStateOutputs stateOutputs = drv.stateOutputs; + statePath = stateOutputs.find("state")->second.statepath; + } + return drv; } //Wrapper -Derivation getDerivation_andCheckArgs(Strings opFlags, Strings opArgs, Path & componentPath, Path & statePath, string & stateIdentifier, string & binary, string & derivationPath, bool & isStatePath) +Derivation getDerivation_andCheckArgs(Strings opFlags, Strings opArgs, Path & componentPath, Path & statePath, + string & binary, string & derivationPath, bool & isStatePath, Strings & program_args) { PathSet empty; - string empty2; - return getDerivation_andCheckArgs_(opFlags, opArgs, componentPath, statePath, stateIdentifier, binary, derivationPath, isStatePath, false, empty, empty2); + return getDerivation_andCheckArgs_(opFlags, opArgs, componentPath, statePath, binary, derivationPath, isStatePath, program_args, false, empty); } // static void opShowDerivations(Strings opFlags, Strings opArgs) { - string username; - - if(opArgs.size() == 3) - username = opArgs.back(); - else if(opArgs.size() == 2) - username = getCallingUserName(); - - string stateIdentifier; Path componentPath; Path statePath; string binary; PathSet derivers; string derivationPath; bool isStatePath; - Derivation drv = getDerivation_andCheckArgs_(opFlags, opArgs, componentPath, statePath, stateIdentifier, binary, derivationPath, true, isStatePath, derivers, username); + Strings program_args; + Derivation drv = getDerivation_andCheckArgs_(opFlags, opArgs, componentPath, statePath, binary, derivationPath, isStatePath, program_args, true, derivers); if(!isStatePath) throw UsageError(format("This path '%1%' is not a state path") % componentPath); @@ -127,11 +136,11 @@ static void opShowStatePath(Strings opFlags, Strings opArgs) { Path componentPath; Path statePath; - string stateIdentifier; string binary; string derivationPath; bool isStatePath; - Derivation drv = getDerivation_andCheckArgs(opFlags, opArgs, componentPath, statePath, stateIdentifier, binary, derivationPath, isStatePath); + Strings program_args; + Derivation drv = getDerivation_andCheckArgs(opFlags, opArgs, componentPath, statePath, binary, derivationPath, isStatePath, program_args); if(!isStatePath) throw UsageError(format("This path '%1%' is not a state path") % componentPath); @@ -144,191 +153,175 @@ static void opShowStateReposRootPath(Strings opFlags, Strings opArgs) { Path componentPath; Path statePath; - string stateIdentifier; string binary; string derivationPath; bool isStatePath; - Derivation drv = getDerivation_andCheckArgs(opFlags, opArgs, componentPath, statePath, stateIdentifier, binary, derivationPath, isStatePath); + Strings program_args; + Derivation drv = getDerivation_andCheckArgs(opFlags, opArgs, componentPath, statePath, binary, derivationPath, isStatePath, program_args); if(!isStatePath) throw UsageError(format("This path '%1%' is not a state path") % componentPath); //Get the a repository for this state location string drvName = drv.env.find("name")->second; - string repos = makeStateReposPath("stateOutput:staterepospath", statePath, "/", drvName, stateIdentifier); //this is a copy from store-state.cc + string repos = getStateReposPath("stateOutput:staterepospath", statePath, "/", drvName, stateIdentifier); //this is a copy from store-state.cc printMsg(lvlError, format("%1%") % repos); } - -PathSet getReferencesClosureWithState(const Path & storepath) +//Comment TODO +PathSet getAllStateDerivationsRecursively(const Path & storePath) { - PathSet paths; - store->storePathRequisites(storepath, false, paths, true); + //Get recursively all state paths + PathSet statePaths; + store->storePathStateRequisitesOnly(storePath, false, statePaths); - for (PathSet::iterator i = paths.begin(); i != paths.end(); ++i) - { - printMsg(lvlError, format("REFCLOSURE %1%") % *i); - } - - //return drvs ! (combo of component + state | component path) - //return single state paths + //Find the matching drv with the statePath + PathSet derivations; + for (PathSet::iterator i = statePaths.begin(); i != statePaths.end(); ++i) + derivations.insert(store->queryStatePathDrv(*i)); + + return derivations; } -//TODO -static void recheckrefsinstaterecursive() -{ - - //PathSet state_references = scanForReferences(statePath, allPaths); - //PathSet state_stateReferences = scanForStateReferences(statePath, allStatePaths); - -} - - - static void opRunComponent(Strings opFlags, Strings opArgs) { - //get the derivation of the current component - + //get the all the info of the component that is being called (we dont really use it yet) Path componentPath; Path statePath; - string stateIdentifier; string binary; string derivationPath; bool isStatePath; - Derivation drv = getDerivation_andCheckArgs(opFlags, opArgs, componentPath, statePath, stateIdentifier, binary, derivationPath, isStatePath); - DerivationStateOutputDirs stateOutputDirs = drv.stateOutputDirs; - DerivationStateOutputs stateOutputs = drv.stateOutputs; - DerivationOutputs outputs = drv.outputs; - string drvName = drv.env.find("name")->second; + Strings program_args; + Derivation drv = getDerivation_andCheckArgs(opFlags, opArgs, componentPath, statePath, binary, derivationPath, isStatePath, program_args); + + //Specifiy the SVN binarys + string svnbin = nixSVNPath + "/svn"; + string svnadminbin = nixSVNPath + "/svnadmin"; - //Check if component is a state component !!! - - //Check for locks ... + + //Check for locks ... ? //add locks ... ? //svn lock ... ? - - //******************* Run the component - //TODO - - - //******************* Afterwards, call the commit script (recursively) //get dependecies (if neccecary | recusively) of all state components that need to be updated - // - //TODO nix-store -qR $(nix-store -qd /nix/store/6x6glnb9idn53yxfqrz6wq53459vv3qd-firefox-2.0.0.3/) - + //TODO maybe also scan the parameters for state or component hashes? + PathSet drvs = getAllStateDerivationsRecursively(componentPath); + //???? //Transaction txn; //createStoreTransaction(txn); //txn.commit(); - - //or noTxn + //******************* With everything in place, we call the commit script on all statePaths ********************** - //for(...){ - // - //} - - string svnbin = nixSVNPath + "/svn"; - string svnadminbin = nixSVNPath + "/svnadmin"; - - //Vector includeing all commit scripts: - vector subversionedpaths; - vector subversionedpathsCommitBoolean; - vector nonversionedpaths; //of type none, no versioning needed - vector checkoutcommands; + for (PathSet::iterator d = drvs.begin(); d != drvs.end(); ++d) + { + //Extract the neccecary info from each Drv + Path drvPath = *d; + Derivation drv = derivationFromPath(drvPath); + DerivationStateOutputs stateOutputs = drv.stateOutputs; + Path statePath = stateOutputs.find("state")->second.statepath; + DerivationStateOutputDirs stateOutputDirs = drv.stateOutputDirs; + string drvName = drv.env.find("name")->second; - //Get all the inverals from the database at once - PathSet intervalPaths; - for (DerivationStateOutputDirs::const_reverse_iterator i = stateOutputDirs.rbegin(); i != stateOutputDirs.rend(); ++i){ - DerivationStateOutputDir d = i->second; - - string thisdir = d.path; - string fullstatedir = statePath + "/" + thisdir; + //Print + printMsg(lvlError, format("Committing statePath: %1%") % statePath); + + //Vector includeing all commit scripts: + vector subversionedpaths; + vector subversionedpathsCommitBoolean; + vector nonversionedpaths; //of type none, no versioning needed + vector checkoutcommands; - if(d.type == "interval"){ - intervalPaths.insert(fullstatedir); + //Get all the inverals from the database at once + PathSet intervalPaths; + for (DerivationStateOutputDirs::const_reverse_iterator i = stateOutputDirs.rbegin(); i != stateOutputDirs.rend(); ++i){ + DerivationStateOutputDir d = i->second; + + string thisdir = d.path; + string fullstatedir = statePath + "/" + thisdir; + + if(d.type == "interval"){ + intervalPaths.insert(fullstatedir); + } } + vector intervals = store->getStatePathsInterval(intervalPaths); + + 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 fullstatedir = statePath + "/" + thisdir; + if(thisdir == "/") //exception for the root dir + fullstatedir = statePath + "/"; + + if(d.type == "none"){ + nonversionedpaths.push_back(fullstatedir); + continue; + } + + //Get the a repository for this state location + string repos = getStateReposPath("stateOutput:staterepospath", statePath, thisdir, drvName, stateIdentifier); //this is a copy from store-state.cc + + //Add the checkout command in case its needed + checkoutcommands.push_back(svnbin + " --ignore-externals checkout file://" + repos + " " + fullstatedir); + subversionedpaths.push_back(fullstatedir); + + if(d.type == "interval"){ + //Get the interval-counter from the database + int interval_counter = intervals[intervalAt]; + int interval = d.getInterval(); + subversionedpathsCommitBoolean.push_back(interval_counter % interval == 0); + + //update the interval + intervals[intervalAt] = interval_counter + 1; + intervalAt++; + } + else if(d.type == "full") + subversionedpathsCommitBoolean.push_back(true); + else if(d.type == "manual") //TODO !!!!! + subversionedpathsCommitBoolean.push_back(false); + else + throw Error(format("interval '%1%' is not handled in nix-state") % d.type); + } + + //Update the intervals again + //store->setStatePathsInterval(intervalPaths, intervals); //TODO UNCOMMENT + + //Call the commit script with the appropiate paramenters + string subversionedstatepathsarray; + for (vector::iterator i = subversionedpaths.begin(); i != subversionedpaths.end(); ++i) + { + subversionedstatepathsarray += *(i) + " "; + } + string subversionedpathsCommitBooleansarray; + for (vector::iterator i = subversionedpathsCommitBoolean.begin(); i != subversionedpathsCommitBoolean.end(); ++i) + { + subversionedpathsCommitBooleansarray += bool2string(*i) + " "; + } + string nonversionedstatepathsarray; + for (vector::iterator i = nonversionedpaths.begin(); i != nonversionedpaths.end(); ++i) + { + nonversionedstatepathsarray += *(i) + " "; + } + string commandsarray; + for (vector::iterator i = checkoutcommands.begin(); i != checkoutcommands.end(); ++i) + { + //#HACK: I cant seem to find a way for bash to parse a 2 dimensional string array as argument, so we use a 1-d array with '|' as seperator + commandsarray += "" + *(i) + " | "; + } + + //make the call + executeAndPrintShellCommand(nixLibexecDir + "/nix/nix-statecommit.sh " + svnbin + + " \"" + subversionedstatepathsarray + "\" " + + " \"" + subversionedpathsCommitBooleansarray + "\" " + + " \"" + nonversionedstatepathsarray + "\" " + + " \"" + commandsarray + "\" ", + "commit-script"); } - vector intervals = store->getStatePathsInterval(intervalPaths); - - 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 fullstatedir = statePath + "/" + thisdir; - if(thisdir == "/") //exception for the root dir - fullstatedir = statePath + "/"; - - - //Path fullStatePath = fullstatedir; //TODO call coerce function //TODO REMOVE? - - if(d.type == "none"){ - nonversionedpaths.push_back(fullstatedir); - continue; - } - - //Get the a repository for this state location - string repos = makeStateReposPath("stateOutput:staterepospath", statePath, thisdir, drvName, stateIdentifier); //this is a copy from store-state.cc - - // - checkoutcommands.push_back(svnbin + " --ignore-externals checkout file://" + repos + " " + fullstatedir); - subversionedpaths.push_back(fullstatedir); - - if(d.type == "interval"){ - //Get the interval-counter from the database - int interval_counter = intervals[intervalAt]; - int interval = d.getInterval(); - subversionedpathsCommitBoolean.push_back(interval_counter % interval == 0); - - //update the interval - intervals[intervalAt] = interval_counter + 1; - intervalAt++; - } - else if(d.type == "full") - subversionedpathsCommitBoolean.push_back(true); - else if(d.type == "manual") //TODO !!!!! - subversionedpathsCommitBoolean.push_back(false); - else - throw Error(format("interval '%1%' is not handled in nix-state") % d.type); - } - - //Update the intervals again - //store->setStatePathsInterval(intervalPaths, intervals); - - //Call the commit script with the appropiate paramenters - string subversionedstatepathsarray; - for (vector::iterator i = subversionedpaths.begin(); i != subversionedpaths.end(); ++i) - { - subversionedstatepathsarray += *(i) + " "; - } - string subversionedpathsCommitBooleansarray; - for (vector::iterator i = subversionedpathsCommitBoolean.begin(); i != subversionedpathsCommitBoolean.end(); ++i) - { - subversionedpathsCommitBooleansarray += bool2string(*i) + " "; - } - string nonversionedstatepathsarray; - for (vector::iterator i = nonversionedpaths.begin(); i != nonversionedpaths.end(); ++i) - { - nonversionedstatepathsarray += *(i) + " "; - } - string commandsarray; - for (vector::iterator i = checkoutcommands.begin(); i != checkoutcommands.end(); ++i) - { - //#HACK: I cant seem to find a way for bash to parse a 2 dimensional string array as argument, so we use a 1-d array with '|' as seperator - commandsarray += "" + *(i) + " | "; - } - - //make the call - executeAndPrintShellCommand(nixLibexecDir + "/nix/nix-statecommit.sh " + svnbin + - " \"" + subversionedstatepathsarray + "\" " + - " \"" + subversionedpathsCommitBooleansarray + "\" " + - " \"" + nonversionedstatepathsarray + "\" " + - " \"" + commandsarray + "\" ", - "commit-script"); } @@ -337,6 +330,7 @@ void run(Strings args) { Strings opFlags, opArgs; Operation op = 0; + /* test * store = openStore(); @@ -363,10 +357,18 @@ void run(Strings args) printMsg(lvlError, format("1: %1%") % bool2string( store->isStateComponent("/nix/store/7xkw5fkz5yw7dpx0pc6l12bh9a56135c-hellostateworld-1.0") ) ); printMsg(lvlError, format("2: %1%") % bool2string( store->isStateComponent("/nix/store/05441jm8xmsidqm43ivk0micckf0mr2m-nvidiaDrivers") ) ); printMsg(lvlError, format("3: %1%") % bool2string( store->isStateDrvPath("/nix/store/2hpx60ibdfv2pslg4rjvp177frijamvi-hellostateworld-1.0.drv") ) ); + + store = openStore(); + convertStatePathsToDerivations(noTxn, ""); return; + store = openStore(); + Path p = store->queryStatePathDrv("/nix/state/6g6kfgimz8szznlshf13s29fn01zp99d-hellohardcodedstateworld-1.0-test2"); + printMsg(lvlError, format("Result: %1%") % p); + return; + */ - + /* test */ for (Strings::iterator i = args.begin(); i != args.end(); ) { @@ -374,7 +376,7 @@ void run(Strings args) Operation oldOp = op; - if (arg == "--run" || arg == "-r") + if (arg == "--commit" || arg == "-c") op = opRunComponent; else if (arg == "--showstatepath") op = opShowStatePath; @@ -400,22 +402,23 @@ void run(Strings args) --delete state? - --user=... - - --show-state-references- -rev = ... - --show-state-references-current //in nix-store - --show-state-referrers- -rev = ... - --show-state-referrers-current //in nix-store - */ - + + else if (arg.substr(0,13) == "--identifier=") + stateIdentifier = arg.substr(13,arg.length()); + else if (arg.substr(0,7) == "--user=") + username = arg.substr(7,arg.length()); else opArgs.push_back(arg); if (oldOp && oldOp != op) throw UsageError("only one operation may be specified"); } + + if(username == "") + username = getCallingUserName(); + printMsg(lvlError, format("%1% - %2%") % stateIdentifier % username); if (!op) throw UsageError("no operation specified"); diff --git a/src/nix-store/help.txt b/src/nix-store/help.txt index 991f1ebd9..4f7039c12 100644 --- a/src/nix-store/help.txt +++ b/src/nix-store/help.txt @@ -30,8 +30,9 @@ Operations: Query flags: --outputs: query the output paths of a Nix derivation (default) - --requisites / -R: print all paths necessary to realise a path - --requisites-withstate: same as --requisites but now also including state paths + --requisites / -R: print all component paths necessary to realise a path + --requisites-state: same as --requisites but now only printing state paths + --requisites-full: same as --requisites but now also including state paths --references: print all paths referenced by the given path --references-state: print all state paths referenced by the given path --referrers: print all paths directly refering to the given path diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index 19fb61f44..c6db9e3a5 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -222,7 +222,7 @@ static void printTree(const Path & path, /* Perform various sorts of queries. */ static void opQuery(Strings opFlags, Strings opArgs) { - enum { qOutputs, qRequisites, qRequisitesWithState, qReferences, qStateReferences, qReferrers, qStateReferrers + enum { qOutputs, qRequisites, qRequisitesState, qRequisitesFull, qReferences, qStateReferences, qReferrers, qStateReferrers , qReferrersClosure, qReferrersClosureWithState, qDeriver, qBinding, qHash , qTree, qGraph, qResolve } query = qOutputs; bool useOutput = false; @@ -234,7 +234,8 @@ static void opQuery(Strings opFlags, Strings opArgs) i != opFlags.end(); ++i) if (*i == "--outputs") query = qOutputs; else if (*i == "--requisites" || *i == "-R") query = qRequisites; - else if (*i == "--requisites-withstate") query = qRequisitesWithState; + else if (*i == "--requisites-state") query = qRequisitesState; + else if (*i == "--requisites-full") query = qRequisitesFull; else if (*i == "--references") query = qReferences; else if (*i == "--references-state") query = qStateReferences; else if (*i == "--referrers" || *i == "--referers") query = qReferrers; @@ -273,7 +274,8 @@ static void opQuery(Strings opFlags, Strings opArgs) } case qRequisites: - case qRequisitesWithState: + case qRequisitesState: + case qRequisitesFull: case qReferences: case qStateReferences: case qReferrers: @@ -286,7 +288,8 @@ static void opQuery(Strings opFlags, Strings opArgs) { Path path = maybeUseOutput(fixPath(*i), useOutput, forceRealise); if (query == qRequisites) store->storePathRequisites(path, includeOutputs, paths, false); - else if (query == qRequisitesWithState) store->storePathRequisites(path, includeOutputs, paths, true); + else if (query == qRequisitesState) store->storePathStateRequisitesOnly(path, includeOutputs, paths); + else if (query == qRequisitesFull) store->storePathRequisites(path, includeOutputs, paths, 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); diff --git a/src/nix-worker/nix-worker.cc b/src/nix-worker/nix-worker.cc index ec34eb727..0b454d3f6 100644 --- a/src/nix-worker/nix-worker.cc +++ b/src/nix-worker/nix-worker.cc @@ -280,6 +280,15 @@ static void performOp(Source & from, Sink & to, unsigned int op) writeString(printHash(hash), to); break; } + + case wopQueryStatePathDrv: { + Path path = readStorePath(from); //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! needs to be the state path + startWork(); + Path p = store->queryStatePathDrv(path); + stopWork(); + writeString(p, to); + break; + } case wopQueryReferences: case wopQueryReferrers: { @@ -303,7 +312,7 @@ static void performOp(Source & from, Sink & to, unsigned int op) if (op == wopQueryStateReferences) store->queryStateReferences(path, paths); else - store->queryStateReferrers(path, paths); //TODO Does this work??? + store->queryStateReferrers(path, paths); //TODO Does this work???, how about the state path????????? stopWork(); writeStringSet(paths, to); break;