diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 586255f3d..6937a8d1c 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -4,7 +4,7 @@ bin_SCRIPTS = nix-collect-garbage \ nix-pack-closure nix-unpack-closure \ nix-copy-closure -noinst_SCRIPTS = nix-profile.sh generate-patches.pl find-runtime-roots.pl nix-statecommit.sh +noinst_SCRIPTS = nix-profile.sh generate-patches.pl find-runtime-roots.pl nix-statecommit.sh nix-readrevisions.sh nix-pull nix-push: readmanifest.pm readconfig.pm download-using-manifests.pl @@ -18,6 +18,7 @@ install-exec-local: readmanifest.pm download-using-manifests.pl find-runtime-roo $(INSTALL_PROGRAM) find-runtime-roots.pl $(DESTDIR)$(libexecdir)/nix $(INSTALL_PROGRAM) generate-patches.pl $(DESTDIR)$(libexecdir)/nix $(INSTALL_PROGRAM) nix-statecommit.sh $(DESTDIR)$(libexecdir)/nix + $(INSTALL_PROGRAM) nix-readrevisions.sh $(DESTDIR)$(libexecdir)/nix $(INSTALL) -d $(DESTDIR)$(sysconfdir)/nix include ../substitute.mk @@ -34,4 +35,6 @@ EXTRA_DIST = nix-collect-garbage.in \ nix-pack-closure.in nix-unpack-closure.in \ nix-copy-closure.in \ find-runtime-roots.pl.in \ - nix-statecommit.sh.in + nix-statecommit.sh.in \ + nix-readrevisions.sh + diff --git a/src/libstore/db.cc b/src/libstore/db.cc index facf44d37..82942882c 100644 --- a/src/libstore/db.cc +++ b/src/libstore/db.cc @@ -498,6 +498,8 @@ bool Database::queryStateReferences(const Transaction & txn, TableId table, Strings keys; enumTable(txn, table, keys); //get all revisions + ///////////////?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! create function + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TODO string key = ""; //final key that matches revision + statePath int highestRev = -1; @@ -520,7 +522,8 @@ bool Database::queryStateReferences(const Transaction & txn, TableId table, } } } - + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + if(key == "" && highestRev == -1) //no records found (TODO throw error?) return false; @@ -548,22 +551,94 @@ bool Database::queryStateReferrers(const Transaction & txn, TableId table, void Database::setStateRevisions(const Transaction & txn, TableId table, - const Path & statePath, const int revision, const RevisionNumbers & revisions) + const Path & statePath, const int revision, const RevisionNumbersClosure & revisions) { - //TODO + //Pack the data into Strings + const string seperator = "|"; + Strings data; + for (RevisionNumbersClosure::const_iterator i = revisions.begin(); i != revisions.end(); ++i) { + RevisionNumbers revisionNumbers = *i; + string packedNumbers = ""; + for (RevisionNumbers::iterator j = revisionNumbers.begin(); j != revisionNumbers.end(); ++j) + packedNumbers += int2String(*j) + seperator; + packedNumbers = packedNumbers.substr(0, packedNumbers.length()-1); //remove the last | + data.push_back(packedNumbers); + } + + //Create the key + string key = makeStatePathRevision(statePath, revision); + + //Insert + setStrings(txn, table, key, data); } bool Database::queryStateRevisions(const Transaction & txn, TableId table, - const Path & statePath, RevisionNumbers & revisions, int revision) + const Path & statePath, RevisionNumbersClosure & revisions, int revision) { - //TODO - return false; + const string seperator = "|"; + + Strings keys; + enumTable(txn, table, keys); //get all revisions + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + string key = ""; //final key that matches revision + statePath + int highestRev = -1; + + //Lookup which key we need + for (Strings::iterator i = keys.begin(); i != keys.end(); ++i) { + Path getStatePath_org = *i; + Path getStatePath; + int getRevision; + splitStatePathRevision(*i, getStatePath, getRevision); + + if(getStatePath == statePath){ + + if(revision == -1){ //the user wants the last revision + if(getRevision > highestRev) + highestRev = getRevision; + } + else if(revision == getRevision){ + key = getStatePath_org; + break; + } + } + } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + if(key == "" && highestRev == -1) //no records found (TODO throw error?) + return false; + + if(revision == -1) + key = makeStatePathRevision(statePath, highestRev); + + Strings data; + bool succeed = queryStrings(txn, table, key, data); //now that we have the key, we can query the references + + //Unpack Strings into RevisionNumbersClosure + for (Strings::iterator i = data.begin(); i != data.end(); ++i){ + RevisionNumbers revisionsGroup; + string packedNumbers = *i; + Strings tokens = tokenizeString(packedNumbers, seperator); + for (Strings::iterator j = tokens.begin(); j != tokens.end(); ++j){ + int getRevision; + bool succeed = string2Int(*j, getRevision); + if(!succeed) + throw Error(format("Cannot read revision number from db of path '%1%'") % statePath); + revisionsGroup.push_back(getRevision); + } + revisions.push_back(revisionsGroup); + } + + return succeed; } bool Database::queryAllStateRevisions(const Transaction & txn, TableId table, const Path & statePath, RevisionNumbers & revisions) { //TODO + + //LIST OF x ..... y which revisions are available for a rollback + return false; } diff --git a/src/libstore/db.hh b/src/libstore/db.hh index 150307551..98096a2f9 100644 --- a/src/libstore/db.hh +++ b/src/libstore/db.hh @@ -110,11 +110,11 @@ public: /* Set the revision number of the statePath and the revision numbers of all state paths in the references closure */ void setStateRevisions(const Transaction & txn, TableId table, - const Path & statePath, const int revision, const RevisionNumbers & revisions); + const Path & statePath, const int revision, const RevisionNumbersClosure & revisions); /* Returns all the revision numbers of the state references closure of the given state path */ bool queryStateRevisions(const Transaction & txn, TableId table, - const Path & statePath, RevisionNumbers & revisions, int revision = -1); + const Path & statePath, RevisionNumbersClosure & revisions, int revision = -1); /* Returns all available revision numbers of the given state path */ bool queryAllStateRevisions(const Transaction & txn, TableId table, diff --git a/src/libstore/store-state.cc b/src/libstore/store-state.cc index 0e29a29de..65a7847f7 100644 --- a/src/libstore/store-state.cc +++ b/src/libstore/store-state.cc @@ -98,6 +98,9 @@ void createStateDirs(const DerivationStateOutputDirs & stateOutputDirs, const De //Initialize the counters for the statePaths that have an interval to 0 vector empty; store->setStatePathsInterval(intervalPaths, empty, true); + + //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1 + //Initialize the revisions recursively } diff --git a/src/libutil/types.hh b/src/libutil/types.hh index ff313f88d..d162af2bb 100644 --- a/src/libutil/types.hh +++ b/src/libutil/types.hh @@ -59,8 +59,8 @@ typedef list Paths; typedef set PathSet; //state types -struct RevisionNumbersKey { Path statePath; int revision; } ; typedef list RevisionNumbers; //the Strings (list) of StateReferences and this list are connected by position +typedef list RevisionNumbersClosure; typedef map StateReferences; //typedef std::map StateReferencesKey; diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 917f57c48..b48861daf 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -769,12 +769,8 @@ void killUser(uid_t uid) ////////////////////////////////////////////////////////////////////// - string runProgram(Path program, bool searchPath, const Strings & args) { - /* Split args based on | for pipe-ing */ - StringsList l; - /* Create a pipe. */ Pipe pipe; pipe.create(); @@ -809,78 +805,21 @@ string runProgram(Path program, bool searchPath, const Strings & args) } catch (std::exception & e) { std::cerr << "error: " << e.what() << std::endl; } - quickExit(1); } /* Parent. */ pipe.writeSide.close(); - + + string result = drainFD(pipe.readSide); + /* Wait for the child to finish. */ int status = pid.wait(true); if (!statusOk(status)) throw Error(format("program `%1%' %2%") % program % statusToString(status)); - - - // Create a pipe. - Pipe pipe2; - pipe2.create(); - // Fork. - Pid pid2; - pid2 = fork(); - switch (pid2) { - - case -1: - throw SysError("unable to fork"); - - case 0: // child - try { - - pipe2.readSide.close(); - - if (dup2(pipe2.writeSide, STDOUT_FILENO) == -1) - throw SysError("dupping from-hook write side"); - - dup2(pipe.readSide, STDIN_FILENO); - - Path s = "grep"; - Strings args2; - args2.push_back("Revision"); - - std::vector cargs; // careful with c_str()! - cargs.push_back(s.c_str()); - for (Strings::const_iterator i = args2.begin(); i != args2.end(); ++i) - cargs.push_back(i->c_str()); - cargs.push_back(0); - - if (searchPath) - execvp(s.c_str(), (char * *) &cargs[0]); - else - execv(s.c_str(), (char * *) &cargs[0]); - throw SysError(format("executing `%1%'") % s); - - } catch (std::exception & e) { - std::cerr << "error: " << e.what() << std::endl; - } - - quickExit(1); - } - - /* Parent. */ - - pipe2.writeSide.close(); - - /* wait for second ........... */ - int status2 = pid2.wait(true); - if (!statusOk(status2)) - throw Error(format("program `%1%' %2%") - % program % statusToString(status)); - - - string result = drainFD(pipe2.readSide); return result; } @@ -1216,7 +1155,7 @@ PathSet pathSets_union(const PathSet & paths1, const PathSet & paths2) set_union(vector1.begin(), vector1.end(),vector2.begin(), vector2.end(), back_inserter(setResult)); //Also available: set_symmetric_difference and set_intersection PathSet diff; - for(int i=0; isecond.statepath; + //RevisionNumbers = readRevisionNumbers(drv); + + + + //setStateRevisions(notxn, TableId table, const Path & statePath, const int revision, const RevisionNumbersClosure & revisions); + /* + bool queryStateRevisions(const Transaction & txn, TableId table, + const Path & statePath, RevisionNumbersClosure & revisions, int revision = -1); + */ +} + //Comment TODO PathSet getAllStateDerivationsRecursively(const Path & storePath) { @@ -374,14 +384,16 @@ static void opRunComponent(Strings opFlags, Strings opArgs) p_args.push_back(nonversionedstatepathsarray); p_args.push_back(commandsarray); runProgram_AndPrintOutput(nixLibexecDir + "/nix/nix-statecommit.sh", true, p_args, "svn"); - + //TODO //Scan if needed //scanAndUpdateAllReferencesRecusively ... - //TODO - //Update all revision numbers in the database } + + //Update all revision numbers in the database + setAllRevisionNumbers(drvs); + } @@ -472,12 +484,25 @@ void run(Strings args) nixDB.splitStatePathRevision(gets, statePath2, revision2); printMsg(lvlError, format("'%1%' '%2%'") % statePath2 % int2String(revision2)); - */ - store = openStore(); Derivation drv = derivationFromPath("/nix/store/r2lvhrd8zhb877n07cqvcyp11j9ws5p0-hellohardcodedstateworld-dep1-1.0.drv"); readRevisionNumbers(drv); - return; + + + Strings strings; + strings.push_back("1"); + strings.push_back("3"); + strings.push_back("2"); + string packed = packStrings(strings); + printMsg(lvlError, format("PA '%1%'") % packed); + Strings strings2 = unpackStrings(packed); + for (Strings::iterator i = strings2.begin(); i != strings2.end(); ++i) + printMsg(lvlError, format("UN '%1%'") % *i); + + */ + + //updateRevisionNumbers("/nix/state/xf582zrz6xl677llr07rvskgsi3dli1d-hellohardcodedstateworld-dep1-1.0-test"); + //return; /* test */