From c9e78a973a97b256676c9f81d2276a7f48712ee4 Mon Sep 17 00:00:00 2001 From: Wouter den Breejen Date: Thu, 24 May 2007 15:08:12 +0000 Subject: [PATCH] Created commit shell script; next adding nix-state --- src/Makefile.am | 2 +- src/libexpr/primops.cc | 13 ++- src/libstore/derivations.hh | 4 + src/libstore/store-state.cc | 165 ++++++++++++++++++++++++++++++++++++ src/libstore/store-state.hh | 16 ++++ 5 files changed, 195 insertions(+), 5 deletions(-) create mode 100644 src/libstore/store-state.cc create mode 100644 src/libstore/store-state.hh diff --git a/src/Makefile.am b/src/Makefile.am index 971f7d9d1..b344fca8d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,5 @@ SUBDIRS = bin2c boost libutil libstore libmain nix-store nix-hash \ libexpr nix-instantiate nix-env nix-worker nix-setuid-helper \ - nix-log2xml bsdiff-4.3 + nix-log2xml bsdiff-4.3 nix-state EXTRA_DIST = aterm-helper.pl diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 53ee8fe74..d67eee07d 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -439,13 +439,18 @@ static Expr prim_derivationStrict(EvalState & state, const ATermVector & args) if (!matchAttrRHS(staterhs, statevalue, statepos)) abort(); startNest(nest, lvlVomit, format("processing statedir attribute `%1%'") % statekey); try { - string s = coerceToString(state, statevalue, context, true); + string s = trim(coerceToString(state, statevalue, context, true)); if (statekey == "dir") { + //Add a / to the end if it's not there if(s[s.length() - 1] != '/') - dir.path = s + "/"; - else - dir.path = s; + s = s + "/"; + + //Remove the / at the beginning if it's there + if(s[0] == '/') + s = s.substr(1, s.length()); + + dir.path = s; } else if (statekey == "type") { dir.type = s; } else if (statekey == "interval") { dir.interval = s; } diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh index da50c8a9b..6a2a587bd 100644 --- a/src/libstore/derivations.hh +++ b/src/libstore/derivations.hh @@ -81,6 +81,10 @@ struct DerivationStateOutputDir this->interval = interval; } + int getInterval(){ + return 0; //TODO + } + //sort function bool operator<(const DerivationStateOutputDir& a) const { return path < a.path; } }; diff --git a/src/libstore/store-state.cc b/src/libstore/store-state.cc new file mode 100644 index 000000000..cfb31d756 --- /dev/null +++ b/src/libstore/store-state.cc @@ -0,0 +1,165 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "store-state.hh" +#include "globals.hh" +#include "util.hh" +#include "derivations.hh" +#include "store-api.hh" + +namespace nix { + +void createStateDirs(const DerivationStateOutputDirs & stateOutputDirs, const DerivationStateOutputs & stateOutputs, const StringPairs & env) +{ + string stateDir = stateOutputs.find("state")->second.statepath; + string drvName = env.find("name")->second; + + //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; + + for (vector::iterator i = stateDirsVector.begin(); i != stateDirsVector.end(); ++i) + { + DerivationStateOutputDir d = *(i); + + string thisdir = d.path; + string fullstatedir = stateDir + "/" + thisdir; + + //calc create repos for this state location + Hash hash = hashString(htSHA256, stateDir + thisdir); + string repos = makeStateReposPath("stateOutput:staterepospath", hash, drvName); + + //Were going to execute svn shell commands + executeAndPrintShellCommand(svnadminbin + " create " + repos, "svnadmin"); //TODO create as nixbld.nixbld chmod 700 + + //TODO REPLACE TRUE INTO VAR + + //Check if and how this dir needs to be versioned + if(d.type == "none"){ + if(true){ + executeAndPrintShellCommand("mkdir -p " + fullstatedir, "mkdir"); + } + nonversionedpaths.push_back(fullstatedir); + continue; + } + + string checkoutcommand = svnbin + " checkout file://" + repos + " " + fullstatedir; + checkoutcommands.push_back(checkoutcommand); + subversionedpaths.push_back(fullstatedir); + + if(d.type == "interval") + subversionedpathsInterval.push_back(d.getInterval()); + else + subversionedpathsInterval.push_back(0); + + if(true){ + printMsg(lvlError, format("Adding state subdir: %1% to %2% from repository %3%") % thisdir % fullstatedir % repos); + executeAndPrintShellCommand(checkoutcommand, "svn"); //TODO checkout as user + } + } + + //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); + } +} + +void executeAndPrintShellCommand(const string & command, const string & commandName) +{ + string tempoutput = "svnoutput.txt"; + string newcommand = command + " > " + tempoutput; + + int kidstatus, deadpid; + pid_t kidpid = fork(); + switch (kidpid) { + case -1: + throw SysError("unable to fork"); + case 0: + try { // child + int rv = system(newcommand.c_str()); + //int rv = execlp(svnbin.c_str(), svnbin.c_str(), ">", tempoutput.c_str(), NULL); //TODO make this work ... ? + + string line; + std::ifstream myfile (tempoutput.c_str()); + if (myfile.is_open()){ + while (! myfile.eof() ) + { + getline (myfile,line); + if(trim(line) != "") + printMsg(lvlError, format("[%2%]: %1%") % line % commandName); + } + myfile.close(); + } + else{ + throw SysError("svn state error"); + quickExit(1); + } + + if (rv == -1) { + throw SysError("svn state error"); + quickExit(99); + } + quickExit(0); + + } catch (std::exception & e) { + std::cerr << format("state child error: %1%\n") % e.what(); + quickExit(1); + } + } + deadpid = waitpid(kidpid, &kidstatus, 0); + if (deadpid == -1) { + std::cerr << format("state child waitpid error\n"); + quickExit(1); + } + + remove(tempoutput.c_str()); //Remove the tempoutput file +} + +} diff --git a/src/libstore/store-state.hh b/src/libstore/store-state.hh new file mode 100644 index 000000000..a2d7b6810 --- /dev/null +++ b/src/libstore/store-state.hh @@ -0,0 +1,16 @@ +#ifndef __STORESTATE_H +#define __STORESTATE_H + +#include "derivations.hh" + +namespace nix { + +/* Create a state directory. */ +void createStateDirs(const DerivationStateOutputDirs & stateOutputDirs, const DerivationStateOutputs & stateOutputs, const StringPairs & env); + +/* Create and prints the output prefixed with '[commandName]:' via print(lvlError,... of a shell command. */ +void executeAndPrintShellCommand(const string & command, const string & commandName); + +} + +#endif /* !__STORESTATE_H */