diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index c29956902..8ce6792b2 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -451,11 +451,21 @@ static Expr prim_derivationStrict(EvalState & state, const ATermVector & args) if(s[0] == '/') s = s.substr(1, s.length()); + if(s == stateRootRepos) + throw EvalError(format("The statedir `%1%' is a keyword and cannot be used, choose another name") % stateRootRepos); + dir.path = s; } else if (statekey == "type") { dir.type = s; } - else if (statekey == "interval") { dir.interval = s; } - else throw EvalError(format("invalid subattirbute `%1%' for attribute dirs") % statekey); + else if (statekey == "interval") { + if(s == "") + continue; + int n; + if (!string2Int(s, n)) throw Error("interval is not a number"); + if(n == 0) throw Error("Interval cannot be 0"); + dir.interval = s; + } + else throw EvalError(format("invalid sub-attirbute `%1%' for attribute dirs") % statekey); } catch (Error & e) { e.addPrefix(format("while evaluating the state derivation attribute `%1%' at %2%:\n") % key % showPos(statepos)); diff --git a/src/libstore/build.cc b/src/libstore/build.cc index f9891e5f2..18f90a3fe 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -1612,6 +1612,7 @@ void DerivationGoal::computeClosure() map allReferences; map contentHashes; + //TODO MOVE THIS TO A PLACE THAT ALSO GETS CALLED WHEN WE DONT NEED TO BUILD ANYTHING //We create state dirs only when state is enabled and when the dirs need to be created after the installation if(drv.stateOutputs.size() != 0) if(!drv.stateOutputs.find("state")->second.getCreateDirsBeforeInstall()) diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh index 2be00bf53..a55f3bd34 100644 --- a/src/libstore/derivations.hh +++ b/src/libstore/derivations.hh @@ -90,7 +90,13 @@ struct DerivationStateOutputDir } int getInterval(){ - return 0; //TODO + if(interval == "") + return 0; + else{ + int i; + if (!string2Int(interval, i)) throw Error("interval is not a number"); + return i; + } } //sort function diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index 2e65df36d..20deae73e 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -19,6 +19,7 @@ string nixSVNPath = "/UNINIT"; string nixConfDir = "/UNINIT"; string nixLibexecDir = "/UNINIT"; string nixBinDir = "/UNINIT"; +string stateRootRepos = "root_repos/"; bool keepFailed = false; bool keepGoing = false; diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index 75cfe83ce..16ee5eb35 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -75,6 +75,9 @@ extern string thisSystem; infinity. */ extern unsigned int maxSilentTime; +//TODO +extern string stateRootRepos; + Strings querySetting(const string & name, const Strings & def); string querySetting(const string & name, const string & def); diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 4b2400b61..603b586fa 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -1162,7 +1162,7 @@ Derivation getStateDerivation(const Path & path) //Get derivations of references nixDB.queryString(txn, dbDerivers, path, data); - printMsg(lvlError, format("DERIVERS %1%") % data); + //printMsg(lvlError, format("DERIVERS %1%") % data); txn.commit(); diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 900e273d7..e1cc7e4c1 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -97,8 +97,16 @@ Path makeStatePath(const string & type, const Hash & hash, const string & suffix + "-" + suffix + suffix_stateIdentifier; } -Path makeStateReposPath(const string & type, const Hash & hash, const string & suffix, const string & stateIdentifier) +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 + Hash hash = hashString(htSHA256, statePath); + + //A little tick again, we dont want to add other repositorys in the root repository, so we rename it. + string subfolder_ = subfolder; + if(subfolder == "") + subfolder_ = stateRootRepos; + string suffix_stateIdentifier = stateIdentifier; if(suffix_stateIdentifier != "") suffix_stateIdentifier = "-" + suffix_stateIdentifier; @@ -112,7 +120,7 @@ Path makeStateReposPath(const string & type, const Hash & hash, const string & s return nixStoreStateRepos + "/" + printHash32(compressHash(hashString(htSHA256, s), 20)) - + "-" + suffix + suffix_stateIdentifier; + + "-" + suffix + suffix_stateIdentifier + "/" + subfolder_; } Path makeFixedOutputPath(bool recursive, diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index 4a683e2ce..a5475956f 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -222,7 +222,7 @@ Path makeFixedOutputPath(bool recursive, Path makeStatePath(const string & type, const Hash & hash, const string & suffix, const string & stateIdentifier); /* Constructs a unique store state repos path name. */ -Path makeStateReposPath(const string & type, const Hash & hash, const string & suffix, const string & stateIdentifier); +Path makeStateReposPath(const string & type, const Path statePath, const string subfolder, const string & suffix, const string & stateIdentifier); /* This is the preparatory part of addToStore() and addToStoreFixed(); diff --git a/src/libstore/store-state.cc b/src/libstore/store-state.cc index 6dc674af7..141c23b16 100644 --- a/src/libstore/store-state.cc +++ b/src/libstore/store-state.cc @@ -22,29 +22,15 @@ void createStateDirs(const DerivationStateOutputDirs & stateOutputDirs, const De string drvName = env.find("name")->second; string stateIdentifier = stateOutputs.find("state")->second.stateIdentifier; - //Convert the map into a sortable vector - vector stateDirsVector; - for (DerivationStateOutputDirs::const_reverse_iterator i = stateOutputDirs.rbegin(); i != stateOutputDirs.rend(); ++i){ - stateDirsVector.push_back(i->second); - } - sort(stateDirsVector.begin(), stateDirsVector.end()); - - printMsg(lvlError, format("stateDir `%1%'") % stateDir); - string svnbin = nixSVNPath + "/svn"; string svnadminbin = nixSVNPath + "/svnadmin"; - - //Vector includeing all commit scripts: - vector commitscript; - vector subversionedpaths; - vector subversionedpathsInterval; - vector nonversionedpaths; //of type none, no versioning needed - vector checkoutcommands; - PathSet statePaths; - for (vector::iterator i = stateDirsVector.begin(); i != stateDirsVector.end(); ++i) - { - DerivationStateOutputDir d = *(i); + PathSet intervalPaths; + + //TODO check if we can create stata and staterepos dirs + + for (DerivationStateOutputDirs::const_reverse_iterator i = stateOutputDirs.rbegin(); i != stateOutputDirs.rend(); ++i){ + DerivationStateOutputDir d = i->second; string thisdir = d.path; string fullstatedir = stateDir + "/" + thisdir; @@ -56,69 +42,29 @@ void createStateDirs(const DerivationStateOutputDirs & stateOutputDirs, const De if(true){ executeAndPrintShellCommand("mkdir -p " + fullstatedir, "mkdir"); } - nonversionedpaths.push_back(fullstatedir); continue; } //Create a repository for this state location - Hash hash = hashString(htSHA256, stateDir + thisdir); - string repos = makeStateReposPath("stateOutput:staterepospath", hash, drvName, stateIdentifier); - executeAndPrintShellCommand(svnadminbin + " create " + repos, "svnadmin"); //TODO create as nixbld.nixbld chmod 700 + string repos = makeStateReposPath("stateOutput:staterepospath", stateDir, thisdir, drvName, stateIdentifier); + executeAndPrintShellCommand("mkdir -p " + repos, "mkdir"); + executeAndPrintShellCommand(svnadminbin + " create " + repos, "svnadmin"); //TODO create as nixbld.nixbld chmod 700... can you still commit than ?? - // - string checkoutcommand = svnbin + " checkout file://" + repos + " " + fullstatedir; - checkoutcommands.push_back(checkoutcommand); - subversionedpaths.push_back(fullstatedir); - if(d.type == "interval"){ - statePaths.insert(statePath); - subversionedpathsInterval.push_back(d.getInterval()); + intervalPaths.insert(statePath); } - else - subversionedpathsInterval.push_back(0); //TODO REPLACE TRUE INTO VAR OF CREATEING DIRS BEFORE OR AFTER INSTALL if(true){ printMsg(lvlError, format("Adding state subdir: %1% to %2% from repository %3%") % thisdir % fullstatedir % repos); + string checkoutcommand = svnbin + " checkout file://" + repos + " " + fullstatedir; executeAndPrintShellCommand(checkoutcommand, "svn"); //TODO checkout as user } } - //Add the statePaths that have an interval + //Initialize the counters for the statePaths that have an interval to 0 vector empty; - store->setStatePathsInterval(statePaths, empty, true); - - //create super commit script - printMsg(lvlError, format("svnbin=%1%") % svnbin); - string subversionedstatepathsarray = "subversionedpaths=( "; - for (vector::iterator i = subversionedpaths.begin(); i != subversionedpaths.end(); ++i) - { - subversionedstatepathsarray += *(i) + " "; - } - printMsg(lvlError, format("%1%)") % subversionedstatepathsarray); - string subversionedpathsIntervalsarray = "subversionedpathsInterval=( "; - for (vector::iterator i = subversionedpathsInterval.begin(); i != subversionedpathsInterval.end(); ++i) - { - subversionedpathsIntervalsarray += int2String(*i) + " "; - } - printMsg(lvlError, format("%1%)") % subversionedpathsIntervalsarray); - string nonversionedstatepathsarray = "nonversionedpaths=( "; - for (vector::iterator i = nonversionedpaths.begin(); i != nonversionedpaths.end(); ++i) - { - nonversionedstatepathsarray += *(i) + " "; - } - printMsg(lvlError, format("%1%)") % nonversionedstatepathsarray); - string commandsarray = "checkouts=( "; - for (vector::iterator i = checkoutcommands.begin(); i != checkoutcommands.end(); ++i) - { - commandsarray += "\"" + *(i) + "\" "; - } - printMsg(lvlError, format("%1%)") % commandsarray); - for (vector::iterator i = commitscript.begin(); i != commitscript.end(); ++i) - { - string s = *(i); - printMsg(lvlError, format("%1%") % s); - } + store->setStatePathsInterval(intervalPaths, empty, true); } //executes a shell command and captures and prints the output. diff --git a/src/nix-state/nix-state.cc b/src/nix-state/nix-state.cc index d63a09c8a..c970adcf7 100644 --- a/src/nix-state/nix-state.cc +++ b/src/nix-state/nix-state.cc @@ -41,7 +41,7 @@ static void opCommitReferencesClosure(Strings opFlags, Strings opArgs) }*/ //Data from user / profile - string component = "/nix/store/1hyp7iiiig3rdf99y74yqhi2jkfpa8pf-hellohardcodedstateworld-1.0"; + string component = "/nix/store/s0g22b5lw693cjpclypkzan27d11v5pg-hellohardcodedstateworld-1.0"; Path componentPath = component; //TODO call coerce function string identifier = "test"; string binary = "hello"; @@ -53,11 +53,14 @@ static void opCommitReferencesClosure(Strings opFlags, Strings opArgs) //********************* Commit state ********************* - //get the derivation + //get the derivation of the current component Derivation drv = store->getStateDerivation(componentPath); + DerivationStateOutputDirs stateOutputDirs = drv.stateOutputDirs; + DerivationStateOutputs stateOutputs = drv.stateOutputs; + DerivationOutputs outputs = drv.outputs; + string drvName = drv.env.find("name")->second; + string stateIdentifier = stateOutputs.find("state")->second.stateIdentifier; - DerivationStateOutputDirs stateOutputDirs; - DerivationStateOutputs stateOutputs; //get dependecies (if neccecary) of all state components that need to be updated PathSet paths = store->getStateReferencesClosure(componentPath); @@ -74,6 +77,76 @@ static void opCommitReferencesClosure(Strings opFlags, Strings opArgs) string svnbin = nixSVNPath + "/svn"; string svnadminbin = nixSVNPath + "/svnadmin"; + Path statePath = stateOutputs.find("state")->second.statepath; + string stateDir = statePath; + + //Vector includeing all commit scripts: + vector commitscript; + vector subversionedpaths; + vector subversionedpathsInterval; + vector nonversionedpaths; //of type none, no versioning needed + vector checkoutcommands; + + for (DerivationStateOutputDirs::const_reverse_iterator i = stateOutputDirs.rbegin(); i != stateOutputDirs.rend(); ++i){ + DerivationStateOutputDir d = i->second; + + string thisdir = d.path; + string fullstatedir = stateDir + "/" + thisdir; + Path statePath = fullstatedir; //TODO call coerce function + + if(d.type == "none"){ + nonversionedpaths.push_back(fullstatedir); + continue; + } + + //Get the a repository for this state location + string repos = makeStateReposPath("stateOutput:staterepospath", stateDir, thisdir, drvName, stateIdentifier); //this is a copy from store-state.cc + + // + checkoutcommands.push_back(svnbin + " checkout file://" + repos + " " + fullstatedir); + subversionedpaths.push_back(fullstatedir); + + if(d.type == "interval"){ + subversionedpathsInterval.push_back(d.getInterval()); + } + else + subversionedpathsInterval.push_back(0); + } + + //create super commit script + printMsg(lvlError, format("svnbin=%1%") % svnbin); + string subversionedstatepathsarray = "subversionedpaths=( "; + for (vector::iterator i = subversionedpaths.begin(); i != subversionedpaths.end(); ++i) + { + subversionedstatepathsarray += *(i) + " "; + } + printMsg(lvlError, format("%1%)") % subversionedstatepathsarray); + string subversionedpathsIntervalsarray = "subversionedpathsInterval=( "; + for (vector::iterator i = subversionedpathsInterval.begin(); i != subversionedpathsInterval.end(); ++i) + { + subversionedpathsIntervalsarray += int2String(*i) + " "; + } + printMsg(lvlError, format("%1%)") % subversionedpathsIntervalsarray); + string nonversionedstatepathsarray = "nonversionedpaths=( "; + for (vector::iterator i = nonversionedpaths.begin(); i != nonversionedpaths.end(); ++i) + { + nonversionedstatepathsarray += *(i) + " "; + } + printMsg(lvlError, format("%1%)") % nonversionedstatepathsarray); + string commandsarray = "checkouts=( "; + for (vector::iterator i = checkoutcommands.begin(); i != checkoutcommands.end(); ++i) + { + commandsarray += "\"" + *(i) + "\" "; + } + printMsg(lvlError, format("%1%)") % commandsarray); + for (vector::iterator i = commitscript.begin(); i != commitscript.end(); ++i) + { + string s = *(i); + printMsg(lvlError, format("%1%") % s); + } + + + //svnbin=/nix/var/nix/profiles/per-user/root/profile/bin/svn //subversionedpaths=( /nix/state/v6rr3yi5ilgn3k0kwxkk633ap4z0m1zi-hellohardcodedstateworld-1.0/ /nix/state/v6rr3yi5ilgn3k0kwxkk633ap4z0m1zi-hellohardcodedstateworld-1.0/log/ ) //subversionedpathsInterval=( 0 0 ) @@ -88,17 +161,6 @@ static void opCommitReferencesClosure(Strings opFlags, Strings opArgs) } - -//Call the appropiate commit scripts with variables like interval - - - - - -/* Scan the arguments; find the operation, set global flags, put all - other flags in a list, and put all other arguments in another - list. */ - void run(Strings args) { Strings opFlags, opArgs; @@ -109,9 +171,21 @@ void run(Strings args) Operation oldOp = op; - if (arg == "--start" || arg == "-r") + if (arg == "--run" || arg == "-r") op = opCommitReferencesClosure; + /* + + --commit + + --run-without-commit + + --backup + + --showlocation + + + else if (arg == "--add" || arg == "-A") op = opAdd; else if (arg == "--add-fixed") @@ -121,6 +195,7 @@ void run(Strings args) else if (arg[0] == '-') opFlags.push_back(arg); */ + else opArgs.push_back(arg); @@ -128,7 +203,6 @@ void run(Strings args) throw UsageError("only one operation may be specified"); } - //opCommitReferencesClosure(); if (!op) throw UsageError("no operation specified");