1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-26 04:00:59 +01:00

nix-state now works, state is recursively commited (when necessary)

This commit is contained in:
Wouter den Breejen 2007-06-27 15:43:16 +00:00
parent c0dcfed3c3
commit 3d22bd50b3
17 changed files with 457 additions and 277 deletions

View file

@ -22,12 +22,15 @@ nonversionedpaths=( $4 )
checkouts=( $5 ) checkouts=( $5 )
deletesvn=$6 #this flag can be set to 1 to DELETE all .svn folders and NOT commit deletesvn=$6 #this flag can be set to 1 to DELETE all .svn folders and NOT commit
echo svnbin: $svnbin
echo subversionedpaths: ${subversionedpaths[@]} if [ "$debug" != "" ] ; then
echo subversionedpathsCommitBools: ${subversionedpathsCommitBools[@]} echo svnbin: $svnbin
echo nonversionedpaths: ${nonversionedpaths[@]} echo subversionedpaths: ${subversionedpaths[@]}
echo checkouts: ${checkouts[@]} echo subversionedpathsCommitBools: ${subversionedpathsCommitBools[@]}
echo deletesvn: $deletesvn echo nonversionedpaths: ${nonversionedpaths[@]}
echo checkouts: ${checkouts[@]}
echo deletesvn: $deletesvn
fi
# #
# #

View file

@ -1629,6 +1629,7 @@ void DerivationGoal::computeClosure()
if(!drv.stateOutputs.find("state")->second.getCreateDirsBeforeInstall()) if(!drv.stateOutputs.find("state")->second.getCreateDirsBeforeInstall())
createStateDirs(drv.stateOutputDirs, drv.stateOutputs, drv.env); createStateDirs(drv.stateOutputDirs, drv.stateOutputs, drv.env);
/* Check whether the output paths were created, and grep each /* Check whether the output paths were created, and grep each
output path to determine what other paths it references. Also make all output path to determine what other paths it references. Also make all
output paths read-only. */ output paths read-only. */
@ -1737,6 +1738,8 @@ void DerivationGoal::computeClosure()
for (DerivationOutputs::iterator i = drv.outputs.begin(); for (DerivationOutputs::iterator i = drv.outputs.begin();
i != drv.outputs.end(); ++i) i != drv.outputs.end(); ++i)
{ {
//printMsg(lvlError, format("SetValidPath: %1%") % i->second.path);
registerValidPath(txn, i->second.path, registerValidPath(txn, i->second.path,
"", //dummy statePath "", //dummy statePath
contentHashes[i->second.path], contentHashes[i->second.path],
@ -1749,14 +1752,17 @@ void DerivationGoal::computeClosure()
* We first register alls paths as valid, and only scan for component references. * 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 * Now that those paths are registered as valid, we're able to call queryDeriversStatePath
* *
* We already scanned for Component references in Component paths * We already scanned for [Component references in Component paths] //1
* Now we scan in Component paths for state references * Now we scan in [Component paths for state references] //2
* *
* If state is enabled for the path we: * 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 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) for (DerivationOutputs::iterator i = drv.outputs.begin(); i != drv.outputs.end(); ++i)
{ {
Path path = i->second.path; Path path = i->second.path;
@ -1770,7 +1776,7 @@ void DerivationGoal::computeClosure()
Path componentPath = *i; Path componentPath = *i;
if(isStateComponentTxn(txn, componentPath)){ 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()); PathSet stateRefs = queryDeriversStatePath(txn, componentPath ,"*",getCallingUserName());
allStatePaths = mergePathSets(stateRefs, allStatePaths); allStatePaths = mergePathSets(stateRefs, allStatePaths);
} }

View file

@ -507,16 +507,24 @@ void LocalStore::queryStateReferrers(const Path & storePath, PathSet & stateRefe
void setDeriver(const Transaction & txn, const Path & storePath, const Path & deriver) void setDeriver(const Transaction & txn, const Path & storePath, const Path & deriver)
{ {
printMsg(lvlError, format("xxxxxxxxxxxxxxxxxxxxxxx"));
assertStorePath(storePath); assertStorePath(storePath);
printMsg(lvlError, format("Ttttttttttttttttttttttttt"));
if (deriver == "") return; if (deriver == "") return;
printMsg(lvlError, format("uuuuuuuuuuuuuuuuuuuuuuuuuuuuu"));
assertStorePath(deriver); assertStorePath(deriver);
printMsg(lvlError, format("yyyyyyyyyyyyyyyyyyyyyyyyy"));
if (!isRealisablePath(txn, storePath)) if (!isRealisablePath(txn, storePath))
throw Error(format("path `%1%' is not valid") % storePath); throw Error(format("path `%1%' is not valid") % storePath);
if (isStateDrvPathTxn(txn, deriver)){ //Redirect if its a state component if (isStateDrvPathTxn(txn, deriver)){ //Redirect if its a state component
printMsg(lvlError, format("bbbbbbbbbbbbbbb"));
addStateDeriver(txn, storePath, deriver); addStateDeriver(txn, storePath, deriver);
} }
else{ else{
printMsg(lvlError, format("ccccccccccccccccccc"));
nixDB.setString(txn, dbDerivers, storePath, deriver); nixDB.setString(txn, dbDerivers, storePath, deriver);
} }
} }
@ -530,13 +538,19 @@ void addStateDeriver(const Transaction & txn, const Path & storePath, const Path
if (!isRealisablePath(txn, storePath)) if (!isRealisablePath(txn, storePath))
throw Error(format("path `%1%' is not valid") % storePath); throw Error(format("path `%1%' is not valid") % storePath);
printMsg(lvlError, format("dddddddddddddd"));
Derivation drv = derivationFromPath(deriver); Derivation drv = derivationFromPath(deriver);
string identifier = drv.stateOutputs.find("state")->second.stateIdentifier; string identifier = drv.stateOutputs.find("state")->second.stateIdentifier;
string user = drv.stateOutputs.find("state")->second.username; string user = drv.stateOutputs.find("state")->second.username;
printMsg(lvlError, format("eeeeeeeeeeeeeeeeee"));
PathSet currentDerivers = queryDerivers(txn, storePath, identifier, user); PathSet currentDerivers = queryDerivers(txn, storePath, identifier, user);
PathSet updatedDerivers = mergeNewDerivationIntoList(storePath, deriver, currentDerivers, true); PathSet updatedDerivers = mergeNewDerivationIntoList(storePath, deriver, currentDerivers, true);
printMsg(lvlError, format("ffffffffffffffffffff"));
Strings data; Strings data;
for (PathSet::iterator i = updatedDerivers.begin(); i != updatedDerivers.end(); ++i) //Convert Paths to Strings for (PathSet::iterator i = updatedDerivers.begin(); i != updatedDerivers.end(); ++i) //Convert Paths to Strings
data.push_back(*i); data.push_back(*i);
@ -597,7 +611,7 @@ Path queryDeriver(const Transaction & txn, const Path & storePath)
bool b = nixDB.queryString(txn, dbDerivers, storePath, deriver); bool b = nixDB.queryString(txn, dbDerivers, storePath, deriver);
Derivation drv = derivationFromPath(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); throw Error(format("This deriver `%1%' is a state deriver, u should use queryDerivers instead of queryDeriver") % deriver);
if (b) if (b)
@ -769,18 +783,14 @@ void clearSubstitutes()
static void setHash(const Transaction & txn, const Path & storePath, const Hash & hash, bool stateHash = false) static void setHash(const Transaction & txn, const Path & storePath, const Hash & hash, bool stateHash = false)
{ {
if(stateHash){ nixDB.setString(txn, dbValidPaths, storePath, "sha256:" + printHash(hash));
nixDB.setString(txn, dbValidStatePaths, storePath, ""); assert(hash.type == htSHA256);
}
else{
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) static Hash queryHash(const Transaction & txn, const Path & storePath)
@ -806,6 +816,20 @@ Hash LocalStore::queryPathHash(const Path & path)
return queryHash(noTxn, 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, void registerValidPath(const Transaction & txn,
const Path & path, const Path & statePath, const Hash & hash, 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); setHash(txn, i->path, i->hash);
if (i->statePath != "") 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); setReferences(txn, i->path, i->references, i->stateReferences);
/* Check that all referenced paths are also valid (or about to) become valid). */ /* 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(); for (PathSet::iterator j = i->references.begin();
j != i->references.end(); ++j) j != i->references.end(); ++j)
if (!isValidPathTxn(txn, *j) && newPaths.find(*j) == newPaths.end()) if (!isValidPathTxn(txn, *j) && newPaths.find(*j) == newPaths.end())
throw Error(format("cannot register path `%1%' as valid, since its reference `%2%' is invalid") throw Error(format("cannot register path `%1%' as valid, since its reference `%2%' is invalid")
% i->path % *j); % i->path % *j);
//TODO Also do this for stateReferences????
setDeriver(txn, i->path, i->deriver); 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) void LocalStore::storePathRequisites(const Path & storePath, const bool includeOutputs, PathSet & paths, const bool & withState)
{ {
return nix::storePathRequisites(storePath, includeOutputs, paths, 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). */ /* Upgrade from schema 1 (Nix <= 0.7) to schema 2 (Nix >= 0.8). */
static void upgradeStore07() static void upgradeStore07()
{ {

View file

@ -49,6 +49,8 @@ public:
Hash queryPathHash(const Path & path); Hash queryPathHash(const Path & path);
Path queryStatePathDrv(const Path & statePath);
void queryReferences(const Path & path, PathSet & references); void queryReferences(const Path & path, PathSet & references);
void queryStateReferences(const Path & storePath, PathSet & stateReferences); void queryStateReferences(const Path & storePath, PathSet & stateReferences);
@ -96,6 +98,8 @@ public:
void storePathRequisites(const Path & storePath, const bool includeOutputs, PathSet & paths, const bool & withState); void storePathRequisites(const Path & storePath, const bool includeOutputs, PathSet & paths, const bool & withState);
void storePathStateRequisitesOnly(const Path & storePath, const bool includeOutputs, PathSet & statePaths);
}; };
@ -206,6 +210,8 @@ bool isStateDrvPathTxn(const Transaction & txn, const Path & drvPath);
bool isStateDrvTxn(const Transaction & txn, const Derivation & drv); bool isStateDrvTxn(const Transaction & txn, const Derivation & drv);
void convertStatePathsToDerivations(const Transaction & txn, const Path & storePath);
} }

View file

@ -17,28 +17,32 @@ Derivation derivationFromPath(const Path & drvPath)
return parseDerivation(t); 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) 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); paths.insert(path);
@ -47,23 +51,18 @@ void computeFSClosure(const Path & path, PathSet & paths, const bool & withState
if (flipDirection){ if (flipDirection){
store->queryReferrers(path, references); store->queryReferrers(path, references);
if(withState) store->queryStateReferrers(path, stateReferences);
store->queryStateReferrers(path, stateReferences);
} }
else{ else{
store->queryReferences(path, references); store->queryReferences(path, references);
if(withState) store->queryStateReferences(path, stateReferences);
store->queryStateReferences(path, stateReferences);
} }
PathSet allReferences; PathSet allReferences;
if(withState) allReferences = mergePathSets(references, stateReferences);
allReferences = mergePathSets(references, stateReferences);
else
allReferences = references;
for (PathSet::iterator i = allReferences.begin(); i != allReferences.end(); ++i) for (PathSet::iterator i = allReferences.begin(); i != allReferences.end(); ++i)
computeFSClosure(*i, paths, withState, flipDirection); computeFSClosureRec(*i, paths, flipDirection);
} }

View file

@ -18,8 +18,9 @@ Derivation derivationFromPath(const Path & drvPath);
`storePath' is returned; that is, the closures under the `storePath' is returned; that is, the closures under the
`referrers' relation instead of the `references' relation is `referrers' relation instead of the `references' relation is
returned. */ returned. */
void computeFSClosure(const Path & storePath, void computeFSClosure(const Path & storePath, PathSet & paths, const bool & withState, bool flipDirection = false);
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 /* Return the path corresponding to the output identifier `id' in the
given derivation. */ given derivation. */

View file

@ -206,6 +206,14 @@ Hash RemoteStore::queryPathHash(const Path & path)
return parseHash(htSHA256, hash); 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, void RemoteStore::queryReferences(const Path & path,
PathSet & references) 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)
{
}
} }

View file

@ -37,6 +37,8 @@ public:
Hash queryPathHash(const Path & path); Hash queryPathHash(const Path & path);
Path queryStatePathDrv(const Path & statePath);
void queryReferences(const Path & path, PathSet & references); void queryReferences(const Path & path, PathSet & references);
void queryStateReferences(const Path & storePath, PathSet & stateReferences); void queryStateReferences(const Path & storePath, PathSet & stateReferences);
@ -84,6 +86,7 @@ public:
void storePathRequisites(const Path & storePath, const bool includeOutputs, PathSet & paths, const bool & withState); void storePathRequisites(const Path & storePath, const bool includeOutputs, PathSet & paths, const bool & withState);
void storePathStateRequisitesOnly(const Path & storePath, const bool includeOutputs, PathSet & statePaths);
private: private:
AutoCloseFD fdSocket; AutoCloseFD fdSocket;

View file

@ -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?")); Error(format("The statepath from the Derivation does not match the recalculated statepath, are u trying to spoof the statepath?"));
} }
void calculateStateReposPath(const string & type, const Path statePath, const string subfolder, const string & suffix, const string & stateIdentifier, Path & rootPath, Path & fullPath)
Path makeStateReposPath(const string & type, const Path statePath, const string subfolder, const string & suffix, const string & stateIdentifier)
{ {
//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 //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); 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")); throw Error(format("Cannot create a repository for a subfolder without a name"));
string hash_subfolder = type + ":sha256:" + printHash(hash) + ":" + subfolder; 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; string suffix_stateIdentifier = stateIdentifier;
if(suffix_stateIdentifier != "") if(suffix_stateIdentifier != "")
@ -140,9 +138,27 @@ Path makeStateReposPath(const string & type, const Path statePath, const string
checkStoreName(suffix); checkStoreName(suffix);
checkStoreName(stateIdentifier); checkStoreName(stateIdentifier);
return nixStoreStateRepos + "/" rootPath = nixStoreStateRepos + "/"
+ printHash32(compressHash(hashString(htSHA256, s), 20)) + 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, Path makeFixedOutputPath(bool recursive,

View file

@ -75,6 +75,9 @@ public:
/* Queries the hash of a valid path. */ /* Queries the hash of a valid path. */
virtual Hash queryPathHash(const Path & path) = 0; 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. /* Queries the set of outgoing FS references for a store path.
The result is not cleared. */ The result is not cleared. */
virtual void queryReferences(const Path & path, virtual void queryReferences(const Path & path,
@ -213,6 +216,7 @@ public:
virtual void storePathRequisites(const Path & storePath, const bool includeOutputs, PathSet & paths, const bool & withState) = 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 ... */ /* TODO ... */
void checkStatePath(const Derivation & drv); void checkStatePath(const Derivation & drv);
/* Constructs a unique store state repos path name. */ /* Calculates a unique store state repos path and also the root path */
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);
/* 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(); /* This is the preparatory part of addToStore() and addToStoreFixed();
it computes the store path to which srcPath is to be copied. it computes the store path to which srcPath is to be copied.

View file

@ -40,6 +40,10 @@ void createStateDirs(const DerivationStateOutputDirs & stateOutputDirs, const De
PathSet intervalPaths; 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 //TODO check if we can create state and staterepos dirs
for (DerivationStateOutputDirs::const_reverse_iterator i = stateOutputDirs.rbegin(); i != stateOutputDirs.rend(); ++i){ for (DerivationStateOutputDirs::const_reverse_iterator i = stateOutputDirs.rbegin(); i != stateOutputDirs.rend(); ++i){
@ -56,13 +60,13 @@ void createStateDirs(const DerivationStateOutputDirs & stateOutputDirs, const De
} }
//Create a repository for this state location //Create a repository for this state location
string repos = makeStateReposPath("stateOutput:staterepospath", stateDir, thisdir, drvName, stateIdentifier); string repos = getStateReposPath("stateOutput:staterepospath", stateDir, thisdir, drvName, stateIdentifier);
executeAndPrintShellCommand("mkdir -p " + repos, "mkdir");
if(IsDirectory(repos)) if(IsDirectory(repos))
printMsg(lvlTalkative, format("Repos %1% already exists, so we use that repository") % repos); printMsg(lvlTalkative, format("Repos %1% already exists, so we use that repository") % repos);
else 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"){ if(d.type == "interval"){
intervalPaths.insert(statePath); 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); 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; string checkoutcommand = svnbin + " checkout file://" + repos + " " + fullstatedir;
executeAndPrintShellCommand(checkoutcommand, "svn"); //TODO checkout as user executeAndPrintShellCommand(checkoutcommand, "svn"); //TODO checkout as user
} }
else 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 //Initialize the counters for the statePaths that have an interval to 0

View file

@ -17,6 +17,7 @@ typedef enum {
wopQuerySubstitutes, wopQuerySubstitutes,
wopHasSubstitutes, wopHasSubstitutes,
wopQueryPathHash, wopQueryPathHash,
wopQueryStatePathDrv,
wopQueryReferences, wopQueryReferences,
wopQueryStateReferences, wopQueryStateReferences,
wopQueryReferrers, wopQueryReferrers,

View file

@ -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); //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) void executeAndPrintShellCommand(const string & command, const string & commandName)
{ {
string tempoutput = "/tmp/svnoutput.txt"; string tempoutput = "/tmp/svnoutput.txt";
@ -1073,20 +1086,18 @@ string time_t2string(const time_t & t)
return s; return s;
} }
//TODO Does this work on windows?
bool FileExist(const string FileName) bool FileExist(const string FileName)
{ {
const char* FileName_C = FileName.c_str(); const char* FileName_C = FileName.c_str();
//strcpy(FileName_C, FileName.c_str());
struct stat my_stat; struct stat my_stat;
return (stat(FileName_C, &my_stat) == 0); return (stat(FileName_C, &my_stat) == 0);
} }
//TODO Does this work on windows?
bool IsDirectory(const string FileName) bool IsDirectory(const string FileName)
{ {
const char* FileName_C = FileName.c_str(); const char* FileName_C = FileName.c_str();
//strcpy(FileName_C, FileName.c_str());
struct stat my_stat; struct stat my_stat;
if (stat(FileName_C, &my_stat) != 0) return false; if (stat(FileName_C, &my_stat) != 0) return false;
return ((my_stat.st_mode & S_IFDIR) != 0); return ((my_stat.st_mode & S_IFDIR) != 0);
@ -1095,7 +1106,7 @@ bool IsDirectory(const string FileName)
string getCallingUserName() string getCallingUserName()
{ {
//TODO Make this work on WINDOWS //TODO Make this work on WINDOWS: Untested!
/* /*
#include <windows.h> #include <windows.h>
char acUserName[100]; char acUserName[100];
@ -1109,12 +1120,11 @@ string getCallingUserName()
//Linux //Linux
Strings empty; Strings empty;
string username = runProgram("whoami", true, empty); //the username of the user that is trying to build the component 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 //Remove the \n
int pos = username.find("\n",0); int pos = username.find("\n",0);
username.erase(pos,1); username.erase(pos,1);
//return "root6";
return username; return username;
} }

View file

@ -18,6 +18,10 @@ using std::cout;
typedef void (* Operation) (Strings opFlags, Strings opArgs); typedef void (* Operation) (Strings opFlags, Strings opArgs);
//two global variables
string stateIdentifier;
string username;
/************************* Build time Functions ******************************/ /************************* 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, Derivation getDerivation_andCheckArgs_(Strings opFlags, Strings opArgs, Path & componentPath, Path & statePath,
bool getDerivers, PathSet & derivers, string & username) //optional string & binary, string & derivationPath, bool isStatePath, Strings & program_args,
bool getDerivers, PathSet & derivers) //optional
{ {
if (!opFlags.empty()) throw UsageError("unknown flag"); if (!opFlags.empty()) throw UsageError("unknown flag");
if ( (opArgs.size() != 1 && opArgs.size() != 2) && (getDerivers && opArgs.size() != 3) ) if ( opArgs.size() != 1 && opArgs.size() != 2 )
throw UsageError("only one or two arguments allowed component path / identiefier (or a third when you need to see the derivations: [username]) )"); 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 //Parse the full path like /nix/store/...../bin/hello
string fullPath = opArgs.front(); string fullPath = opArgs.front();
@ -57,24 +62,32 @@ Derivation getDerivation_andCheckArgs_(Strings opFlags, Strings opArgs, Path & c
//Check if path is statepath //Check if path is statepath
isStatePath = store->isStateComponent(componentPath); isStatePath = store->isStateComponent(componentPath);
//Extract the program arguments
string allargs;
if(opArgs.size() > 1){ if(opArgs.size() > 1){
opArgs.pop_front(); opArgs.pop_front();
stateIdentifier = opArgs.front(); allargs = opArgs.front();
Strings progam_args;
//TODO !!!!!!!!!!!!!!!!!!!!!!
} }
if(username == "") printMsg(lvlError, format("'%1%' - '%2%' - '%3%' - '%4%' - '%5%'") % componentPath % stateIdentifier % binary % username % allargs);
username = getCallingUserName();
//printMsg(lvlError, format("%1% - %2% - %3% - %4%") % componentPath % stateIdentifier % binary % username); if(isStatePath)
derivers = queryDerivers(noTxn, componentPath, stateIdentifier, username);
derivers = queryDerivers(noTxn, componentPath, stateIdentifier, username); else
derivers.insert(queryDeriver(noTxn, componentPath));
if(getDerivers == true) if(getDerivers == true)
return Derivation(); 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); if(isStatePath){
else if(derivers.size() != 1) if(derivers.size() == 0)
throw UsageError(format("There is more than one deriver with identifier '%1%' and username '%2%'") % stateIdentifier % username); 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; Derivation drv;
for (PathSet::iterator i = derivers.begin(); i != derivers.end(); ++i){ //ugly workaround for drvs[0]. for (PathSet::iterator i = derivers.begin(); i != derivers.end(); ++i){ //ugly workaround for drvs[0].
@ -82,37 +95,33 @@ Derivation getDerivation_andCheckArgs_(Strings opFlags, Strings opArgs, Path & c
drv = derivationFromPath(derivationPath); drv = derivationFromPath(derivationPath);
} }
DerivationStateOutputs stateOutputs = drv.stateOutputs; if(isStatePath){
statePath = stateOutputs.find("state")->second.statepath; DerivationStateOutputs stateOutputs = drv.stateOutputs;
statePath = stateOutputs.find("state")->second.statepath;
}
return drv; return drv;
} }
//Wrapper //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; PathSet empty;
string empty2; return getDerivation_andCheckArgs_(opFlags, opArgs, componentPath, statePath, binary, derivationPath, isStatePath, program_args, false, empty);
return getDerivation_andCheckArgs_(opFlags, opArgs, componentPath, statePath, stateIdentifier, binary, derivationPath, isStatePath, false, empty, empty2);
} }
// //
static void opShowDerivations(Strings opFlags, Strings opArgs) 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 componentPath;
Path statePath; Path statePath;
string binary; string binary;
PathSet derivers; PathSet derivers;
string derivationPath; string derivationPath;
bool isStatePath; 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) if(!isStatePath)
throw UsageError(format("This path '%1%' is not a state path") % componentPath); 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 componentPath;
Path statePath; Path statePath;
string stateIdentifier;
string binary; string binary;
string derivationPath; string derivationPath;
bool isStatePath; 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) if(!isStatePath)
throw UsageError(format("This path '%1%' is not a state path") % componentPath); 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 componentPath;
Path statePath; Path statePath;
string stateIdentifier;
string binary; string binary;
string derivationPath; string derivationPath;
bool isStatePath; 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) if(!isStatePath)
throw UsageError(format("This path '%1%' is not a state path") % componentPath); throw UsageError(format("This path '%1%' is not a state path") % componentPath);
//Get the a repository for this state location //Get the a repository for this state location
string drvName = drv.env.find("name")->second; 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); printMsg(lvlError, format("%1%") % repos);
} }
//Comment TODO
PathSet getReferencesClosureWithState(const Path & storepath) PathSet getAllStateDerivationsRecursively(const Path & storePath)
{ {
PathSet paths; //Get recursively all state paths
store->storePathRequisites(storepath, false, paths, true); PathSet statePaths;
store->storePathStateRequisitesOnly(storePath, false, statePaths);
for (PathSet::iterator i = paths.begin(); i != paths.end(); ++i) //Find the matching drv with the statePath
{ PathSet derivations;
printMsg(lvlError, format("REFCLOSURE %1%") % *i); for (PathSet::iterator i = statePaths.begin(); i != statePaths.end(); ++i)
} derivations.insert(store->queryStatePathDrv(*i));
//return drvs ! (combo of component + state | component path) return derivations;
//return single state paths
} }
//TODO
static void recheckrefsinstaterecursive()
{
//PathSet state_references = scanForReferences(statePath, allPaths);
//PathSet state_stateReferences = scanForStateReferences(statePath, allStatePaths);
}
static void opRunComponent(Strings opFlags, Strings opArgs) 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 componentPath;
Path statePath; Path statePath;
string stateIdentifier;
string binary; string binary;
string derivationPath; string derivationPath;
bool isStatePath; bool isStatePath;
Derivation drv = getDerivation_andCheckArgs(opFlags, opArgs, componentPath, statePath, stateIdentifier, binary, derivationPath, isStatePath); Strings program_args;
DerivationStateOutputDirs stateOutputDirs = drv.stateOutputDirs; Derivation drv = getDerivation_andCheckArgs(opFlags, opArgs, componentPath, statePath, binary, derivationPath, isStatePath, program_args);
DerivationStateOutputs stateOutputs = drv.stateOutputs;
DerivationOutputs outputs = drv.outputs;
string drvName = drv.env.find("name")->second;
//Check if component is a state component !!! //Specifiy the SVN binarys
string svnbin = nixSVNPath + "/svn";
string svnadminbin = nixSVNPath + "/svnadmin";
//Check for locks ...
//Check for locks ... ?
//add locks ... ? //add locks ... ?
//svn lock ... ? //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 //get dependecies (if neccecary | recusively) of all state components that need to be updated
// //TODO maybe also scan the parameters for state or component hashes?
//TODO nix-store -qR $(nix-store -qd /nix/store/6x6glnb9idn53yxfqrz6wq53459vv3qd-firefox-2.0.0.3/) PathSet drvs = getAllStateDerivationsRecursively(componentPath);
//????
//Transaction txn; //Transaction txn;
//createStoreTransaction(txn); //createStoreTransaction(txn);
//txn.commit(); //txn.commit();
//or noTxn //******************* With everything in place, we call the commit script on all statePaths **********************
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;
//for(...){ //Print
// printMsg(lvlError, format("Committing statePath: %1%") % statePath);
//}
string svnbin = nixSVNPath + "/svn"; //Vector includeing all commit scripts:
string svnadminbin = nixSVNPath + "/svnadmin"; vector<string> subversionedpaths;
vector<bool> subversionedpathsCommitBoolean;
vector<string> nonversionedpaths; //of type none, no versioning needed
vector<string> checkoutcommands;
//Vector includeing all commit scripts: //Get all the inverals from the database at once
vector<string> subversionedpaths; PathSet intervalPaths;
vector<bool> subversionedpathsCommitBoolean; for (DerivationStateOutputDirs::const_reverse_iterator i = stateOutputDirs.rbegin(); i != stateOutputDirs.rend(); ++i){
vector<string> nonversionedpaths; //of type none, no versioning needed DerivationStateOutputDir d = i->second;
vector<string> checkoutcommands;
//Get all the inverals from the database at once string thisdir = d.path;
PathSet intervalPaths; string fullstatedir = statePath + "/" + thisdir;
for (DerivationStateOutputDirs::const_reverse_iterator i = stateOutputDirs.rbegin(); i != stateOutputDirs.rend(); ++i){
DerivationStateOutputDir d = i->second;
string thisdir = d.path; if(d.type == "interval"){
string fullstatedir = statePath + "/" + thisdir; intervalPaths.insert(fullstatedir);
}
if(d.type == "interval"){
intervalPaths.insert(fullstatedir);
} }
vector<int> 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<string>::iterator i = subversionedpaths.begin(); i != subversionedpaths.end(); ++i)
{
subversionedstatepathsarray += *(i) + " ";
}
string subversionedpathsCommitBooleansarray;
for (vector<bool>::iterator i = subversionedpathsCommitBoolean.begin(); i != subversionedpathsCommitBoolean.end(); ++i)
{
subversionedpathsCommitBooleansarray += bool2string(*i) + " ";
}
string nonversionedstatepathsarray;
for (vector<string>::iterator i = nonversionedpaths.begin(); i != nonversionedpaths.end(); ++i)
{
nonversionedstatepathsarray += *(i) + " ";
}
string commandsarray;
for (vector<string>::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<int> 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<string>::iterator i = subversionedpaths.begin(); i != subversionedpaths.end(); ++i)
{
subversionedstatepathsarray += *(i) + " ";
}
string subversionedpathsCommitBooleansarray;
for (vector<bool>::iterator i = subversionedpathsCommitBoolean.begin(); i != subversionedpathsCommitBoolean.end(); ++i)
{
subversionedpathsCommitBooleansarray += bool2string(*i) + " ";
}
string nonversionedstatepathsarray;
for (vector<string>::iterator i = nonversionedpaths.begin(); i != nonversionedpaths.end(); ++i)
{
nonversionedstatepathsarray += *(i) + " ";
}
string commandsarray;
for (vector<string>::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");
} }
@ -338,6 +331,7 @@ void run(Strings args)
Strings opFlags, opArgs; Strings opFlags, opArgs;
Operation op = 0; Operation op = 0;
/* test * /* test *
store = openStore(); store = openStore();
Path p = "/nix/store/l569q3a2cfx834mcf3vhwczjgbaljnp7-hellohardcodedstateworld-1.0"; // Path p = "/nix/store/l569q3a2cfx834mcf3vhwczjgbaljnp7-hellohardcodedstateworld-1.0"; //
@ -363,6 +357,14 @@ void run(Strings args)
printMsg(lvlError, format("1: %1%") % bool2string( store->isStateComponent("/nix/store/7xkw5fkz5yw7dpx0pc6l12bh9a56135c-hellostateworld-1.0") ) ); 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("2: %1%") % bool2string( store->isStateComponent("/nix/store/05441jm8xmsidqm43ivk0micckf0mr2m-nvidiaDrivers") ) );
printMsg(lvlError, format("3: %1%") % bool2string( store->isStateDrvPath("/nix/store/2hpx60ibdfv2pslg4rjvp177frijamvi-hellostateworld-1.0.drv") ) ); 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; return;
*/ */
@ -374,7 +376,7 @@ void run(Strings args)
Operation oldOp = op; Operation oldOp = op;
if (arg == "--run" || arg == "-r") if (arg == "--commit" || arg == "-c")
op = opRunComponent; op = opRunComponent;
else if (arg == "--showstatepath") else if (arg == "--showstatepath")
op = opShowStatePath; op = opShowStatePath;
@ -400,15 +402,12 @@ void run(Strings args)
--delete state? --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 else
opArgs.push_back(arg); opArgs.push_back(arg);
@ -416,6 +415,10 @@ void run(Strings args)
throw UsageError("only one operation may be specified"); 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"); if (!op) throw UsageError("no operation specified");

View file

@ -30,8 +30,9 @@ Operations:
Query flags: Query flags:
--outputs: query the output paths of a Nix derivation (default) --outputs: query the output paths of a Nix derivation (default)
--requisites / -R: print all paths necessary to realise a path --requisites / -R: print all component paths necessary to realise a path
--requisites-withstate: same as --requisites but now also including state paths --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: print all paths referenced by the given path
--references-state: print all state 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 --referrers: print all paths directly refering to the given path

View file

@ -222,7 +222,7 @@ static void printTree(const Path & path,
/* Perform various sorts of queries. */ /* Perform various sorts of queries. */
static void opQuery(Strings opFlags, Strings opArgs) 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 , qReferrersClosure, qReferrersClosureWithState, qDeriver, qBinding, qHash
, qTree, qGraph, qResolve } query = qOutputs; , qTree, qGraph, qResolve } query = qOutputs;
bool useOutput = false; bool useOutput = false;
@ -234,7 +234,8 @@ static void opQuery(Strings opFlags, Strings opArgs)
i != opFlags.end(); ++i) i != opFlags.end(); ++i)
if (*i == "--outputs") query = qOutputs; if (*i == "--outputs") query = qOutputs;
else if (*i == "--requisites" || *i == "-R") query = qRequisites; else if (*i == "--requisites" || *i == "-R") query = qRequisites;
else if (*i == "--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") query = qReferences;
else if (*i == "--references-state") query = qStateReferences; else if (*i == "--references-state") query = qStateReferences;
else if (*i == "--referrers" || *i == "--referers") query = qReferrers; else if (*i == "--referrers" || *i == "--referers") query = qReferrers;
@ -273,7 +274,8 @@ static void opQuery(Strings opFlags, Strings opArgs)
} }
case qRequisites: case qRequisites:
case qRequisitesWithState: case qRequisitesState:
case qRequisitesFull:
case qReferences: case qReferences:
case qStateReferences: case qStateReferences:
case qReferrers: case qReferrers:
@ -286,7 +288,8 @@ static void opQuery(Strings opFlags, Strings opArgs)
{ {
Path path = maybeUseOutput(fixPath(*i), useOutput, forceRealise); Path path = maybeUseOutput(fixPath(*i), useOutput, forceRealise);
if (query == qRequisites) store->storePathRequisites(path, includeOutputs, paths, false); 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 == qReferences) store->queryReferences(path, paths);
else if (query == qStateReferences) store->queryStateReferences(path, paths); else if (query == qStateReferences) store->queryStateReferences(path, paths);
else if (query == qReferrers) store->queryReferrers(path, paths); else if (query == qReferrers) store->queryReferrers(path, paths);

View file

@ -281,6 +281,15 @@ static void performOp(Source & from, Sink & to, unsigned int op)
break; 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 wopQueryReferences:
case wopQueryReferrers: { case wopQueryReferrers: {
Path path = readStorePath(from); Path path = readStorePath(from);
@ -303,7 +312,7 @@ static void performOp(Source & from, Sink & to, unsigned int op)
if (op == wopQueryStateReferences) if (op == wopQueryStateReferences)
store->queryStateReferences(path, paths); store->queryStateReferences(path, paths);
else else
store->queryStateReferrers(path, paths); //TODO Does this work??? store->queryStateReferrers(path, paths); //TODO Does this work???, how about the state path?????????
stopWork(); stopWork();
writeStringSet(paths, to); writeStringSet(paths, to);
break; break;