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

major update

This commit is contained in:
Wouter den Breejen 2007-07-08 19:02:08 +00:00
parent cc7d4c8bd7
commit ca5fc7c582
15 changed files with 562 additions and 68 deletions

View file

@ -456,22 +456,45 @@ void Database::splitStatePathRevision(const Path & revisionedStatePath, Path & s
{
string prefix = "-REV-";
int pos = revisionedStatePath.find_last_not_of(prefix);
statePath = revisionedStatePath.substr(0, pos - prefix.length());
//printMsg(lvlError, format("'%1%' '%2%'") % statePath % revisionedStatePath.substr(pos, revisionedStatePath.size()));
bool succeed = string2Int(revisionedStatePath.substr(pos, revisionedStatePath.size()), revision);
int pos = revisionedStatePath.find_last_of(prefix);
statePath = revisionedStatePath.substr(0, pos - prefix.length() + 1);
//printMsg(lvlError, format("'%2%' - '%1%'") % revisionedStatePath.substr(pos+1, revisionedStatePath.length()) % int2String(pos));
bool succeed = string2Int(revisionedStatePath.substr(pos+1, revisionedStatePath.length()), revision);
if(!succeed)
throw Error(format("Malformed revision value of path '%1%'") % revisionedStatePath);
}
int Database::getNewRevisionNumber(const Transaction & txn, TableId table,
const Path & statePath)
{
//query
string data;
bool notEmpty = queryString(txn, table, statePath, data);
if(!notEmpty){
setString(txn, table, statePath, int2String(1));
return 1;
}
int revision;
bool succeed = string2Int(data, revision);
if(!succeed)
throw Error(format("Malformed revision counter value of path '%1%'") % statePath);
revision++;
setString(txn, table, statePath, int2String(revision));
return revision;
}
void Database::setStateReferences(const Transaction & txn, TableId table,
const Path & statePath, const int revision, const Strings & references)
const Path & statePath, const Strings & references, int revision)
{
//printMsg(lvlError, format("setStateReferences/Referrers %1%") % table);
if(revision == -1)
throw Error("-1 is not a valid revision value for SET-references/referrers");
revision = getNewRevisionNumber(txn, table, statePath);
/*
for (Strings::const_iterator i = references.begin(); i != references.end(); ++i)
@ -490,6 +513,31 @@ void Database::setStateReferences(const Transaction & txn, TableId table,
setStrings(txn, table, key, references);
}
bool Database::lookupHighestRevivison(const Strings & keys, const Path & statePath, string & key)
{
int highestRev = -1;
//Lookup which key we need
for (Strings::const_iterator i = keys.begin(); i != keys.end(); ++i) {
if((*i).substr(0, statePath.length()) != statePath || (*i).length() == statePath.length()) //dont check the new-revision key or other keys
continue;
//printMsg(lvlError, format("'%1%' - '%2%'") % *i % statePath);
Path getStatePath;
int getRevision;
splitStatePathRevision(*i, getStatePath, getRevision);
if(getRevision > highestRev)
highestRev = getRevision;
}
if(highestRev == -1) //no records found (TODO throw error?)
return false;
key = makeStatePathRevision(statePath, highestRev); //final key that matches revision + statePath
return true;
}
bool Database::queryStateReferences(const Transaction & txn, TableId table,
const Path & statePath, Strings & references, int revision)
{
@ -498,6 +546,16 @@ bool Database::queryStateReferences(const Transaction & txn, TableId table,
Strings keys;
enumTable(txn, table, keys); //get all revisions
string key;
if(revision == -1){
bool foundsomething = lookupHighestRevivison(keys, statePath, key);
if(!foundsomething)
return false;
}
else
key = makeStatePathRevision(statePath, revision);
/*
///////////////?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! create function
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TODO
string key = ""; //final key that matches revision + statePath
@ -529,6 +587,7 @@ bool Database::queryStateReferences(const Transaction & txn, TableId table,
if(revision == -1)
key = makeStatePathRevision(statePath, highestRev);
*/
return queryStrings(txn, table, key, references); //now that we have the key, we can query the references
}
@ -551,12 +610,32 @@ bool Database::queryStateReferrers(const Transaction & txn, TableId table,
void Database::setStateRevisions(const Transaction & txn, TableId table,
const Path & statePath, const int revision, const RevisionNumbersClosure & revisions)
const Path & statePath, const RevisionNumbersSetClosure & revisions, int revision)
{
if(revision == -1)
revision = getNewRevisionNumber(txn, table, statePath);
//Sort based on statePath to RevisionNumbersClosure
RevisionNumbersClosure sorted_revisions;
vector<Path> sortedStatePaths;
for (RevisionNumbersSetClosure::const_iterator i = revisions.begin(); i != revisions.end(); ++i)
sortedStatePaths.push_back((*i).first);
sort(sortedStatePaths.begin(), sortedStatePaths.end());
for (vector<Path>::const_iterator i = sortedStatePaths.begin(); i != sortedStatePaths.end(); ++i)
sorted_revisions.push_back(revisions.at(*i));
//////////////////
for (vector<Path>::const_iterator i = sortedStatePaths.begin(); i != sortedStatePaths.end(); ++i){
printMsg(lvlError, format("Insert: %1%") % *i);
for (RevisionNumbers::const_iterator e = (revisions.at(*i)).begin(); e != (revisions.at(*i)).end(); ++e)
printMsg(lvlError, format("Rev: %1%") % *e);
}
//////////////////
//Pack the data into Strings
const string seperator = "|";
Strings data;
for (RevisionNumbersClosure::const_iterator i = revisions.begin(); i != revisions.end(); ++i) {
for (RevisionNumbersClosure::const_iterator i = sorted_revisions.begin(); i != sorted_revisions.end(); ++i) {
RevisionNumbers revisionNumbers = *i;
string packedNumbers = "";
for (RevisionNumbers::iterator j = revisionNumbers.begin(); j != revisionNumbers.end(); ++j)
@ -580,6 +659,16 @@ bool Database::queryStateRevisions(const Transaction & txn, TableId table,
Strings keys;
enumTable(txn, table, keys); //get all revisions
string key;
if(revision == -1){
bool foundsomething = lookupHighestRevivison(keys, statePath, key);
if(!foundsomething)
return false;
}
else
key = makeStatePathRevision(statePath, revision);
/*
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
string key = ""; //final key that matches revision + statePath
int highestRev = -1;
@ -610,7 +699,8 @@ bool Database::queryStateRevisions(const Transaction & txn, TableId table,
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
@ -632,14 +722,28 @@ bool Database::queryStateRevisions(const Transaction & txn, TableId table,
return succeed;
}
bool Database::queryAllStateRevisions(const Transaction & txn, TableId table,
//TODO include comments into revisions?
bool Database::queryAvailableStateRevisions(const Transaction & txn, TableId table,
const Path & statePath, RevisionNumbers & revisions)
{
//TODO
Strings keys;
enumTable(txn, table, keys); //get all revisions
//LIST OF x ..... y which revisions are available for a rollback
for (Strings::const_iterator i = keys.begin(); i != keys.end(); ++i) {
return false;
if((*i).substr(0, statePath.length()) != statePath || (*i).length() == statePath.length()) //dont check the new-revision key or other keys
continue;
Path getStatePath;
int getRevision;
splitStatePathRevision(*i, getStatePath, getRevision);
revisions.push_back(getRevision);
}
if(revisions.empty())
return false;
else
return true;
}
}

View file

@ -60,6 +60,13 @@ private:
void open2(const string & path, bool removeOldEnv);
/* TODO */
bool lookupHighestRevivison(const Strings & keys, const Path & statePath, string & key);
/* TODO */
int getNewRevisionNumber(const Transaction & txn, TableId table, const Path & statePath);
public:
Database();
~Database();
@ -98,7 +105,7 @@ public:
/* Set the stateReferences for a specific revision (and older until the next higher revision number in the table) */
void setStateReferences(const Transaction & txn, TableId table,
const Path & statePath, const int revision, const Strings & references);
const Path & statePath, const Strings & references, int revision = -1);
/* Returns the references for a specific revision (and older until the next higher revision number in the table) */
bool queryStateReferences(const Transaction & txn, TableId table,
@ -110,14 +117,14 @@ 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 RevisionNumbersClosure & revisions);
const Path & statePath, const RevisionNumbersSetClosure & revisions, int revision = -1);
/* 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, RevisionNumbersClosure & revisions, int revision = -1);
/* Returns all available revision numbers of the given state path */
bool queryAllStateRevisions(const Transaction & txn, TableId table,
bool queryAvailableStateRevisions(const Transaction & txn, TableId table,
const Path & statePath, RevisionNumbers & revisions);
};

View file

@ -116,6 +116,13 @@ static TableId dbStateCounters = 0;
*/
static TableId dbStateInfo = 0;
/* dbStateRevisions :: StatePath -> RevisionNumbersClosure
This table lists the statepaths + recursive (indirect) references and the revision numbers of their repositorys
*/
static TableId dbStateRevisions = 0;
bool Substitute::operator == (const Substitute & sub) const
{
return program == sub.program
@ -189,7 +196,8 @@ LocalStore::LocalStore(bool reserveSpace)
dbComponentStateReferrers = nixDB.openTable("referrers_c_s", true);
dbStateComponentReferrers = nixDB.openTable("referrers_s_c", true);
dbStateStateReferrers = nixDB.openTable("referrers_s_s", true);
dbStateRevisions = nixDB.openTable("staterevisions", true);
int curSchema = 0;
Path schemaFN = nixDBPath + "/schema";
@ -484,8 +492,8 @@ void setReferences(const Transaction & txn, const Path & store_or_statePath,
oldReferences2 = PathSet(oldStateReferences_s_c.begin(), oldStateReferences_s_c.end());
oldStateReferences2 = PathSet(oldStateReferences_s_s.begin(), oldStateReferences_s_s.end());
nixDB.setStateReferences(txn, dbStateComponentReferences, store_or_statePath, revision, Paths(references.begin(), references.end()));
nixDB.setStateReferences(txn, dbStateStateReferences, store_or_statePath, revision, Paths(stateReferences.begin(), stateReferences.end()));
nixDB.setStateReferences(txn, dbStateComponentReferences, store_or_statePath, Paths(references.begin(), references.end()), revision);
nixDB.setStateReferences(txn, dbStateStateReferences, store_or_statePath, Paths(stateReferences.begin(), stateReferences.end()), revision);
//set vars for the referrers update code below
dbXComponentReferrers = dbStateComponentReferrers;
@ -1702,6 +1710,8 @@ void scanAndUpdateAllReferencesTxn(const Transaction & txn, const Path & statePa
allReferencesKeys2.push_back(path);
}
//TODO maybe only scan in the changeset (patch) for new references? (this will be difficult and depending on the underlying versioning system)
//Scan in for component and state references
PathSet state_references = scanForReferences(statePath, PathSet(allReferencesKeys2.begin(), allReferencesKeys2.end()));
PathSet state_stateReferences = scanForReferences(statePath, PathSet(allStateReferencesKeys.begin(), allStateReferencesKeys.end()));
@ -1738,6 +1748,7 @@ void scanAndUpdateAllReferencesTxn(const Transaction & txn, const Path & statePa
printMsg(lvlError, format("Added state reference found!: '%1%' in state path '%2%'") % (*i) % statePath);
//TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
/*
Register Valid again if neccesary
update the extra references in a new table??? why???
@ -1792,7 +1803,7 @@ void scanAndUpdateAllReferencesRecusively(const Transaction & txn, const Path &
//call scanForAllReferences again on all newly found statePaths
for (PathSet::iterator i = statePaths.begin(); i != statePaths.end(); ++i)
{
//... and merge
//Scan, update, call recursively
PathSet newFoundComponentReferences;
PathSet newFoundStateReferences;
scanAndUpdateAllReferencesTxn(txn, *i, newFoundComponentReferences, newFoundStateReferences);
@ -1809,6 +1820,37 @@ void LocalStore::scanAndUpdateAllReferencesRecusively(const Path & storeOrStateP
return nix::scanAndUpdateAllReferencesRecusively(noTxn, storeOrStatePath);
}
void setStateRevisions(const Transaction & txn, const Path & statePath, const RevisionNumbersSetClosure & revisions, const int revision)
{
nixDB.setStateRevisions(txn, dbStateRevisions, statePath, revisions, revision);
}
void LocalStore::setStateRevisions(const Path & statePath, const RevisionNumbersSetClosure & revisions, const int revision)
{
nix::setStateRevisions(noTxn, statePath, revisions, revision);
}
bool queryStateRevisions(const Transaction & txn, const Path & statePath, RevisionNumbersClosure & revisions, const int revision)
{
return nixDB.queryStateRevisions(txn, dbStateRevisions, statePath, revisions, revision);
}
bool LocalStore::queryStateRevisions(const Path & statePath, RevisionNumbersClosure & revisions, const int revision)
{
return nix::queryStateRevisions(noTxn, statePath, revisions, revision);
}
bool queryAvailableStateRevisions(const Transaction & txn, const Path & statePath, RevisionNumbers & revisions)
{
return nixDB.queryAvailableStateRevisions(txn, dbStateRevisions, statePath, revisions);
}
bool LocalStore::queryAvailableStateRevisions(const Path & statePath, RevisionNumbers & revisions)
{
return nix::queryAvailableStateRevisions(noTxn, statePath, revisions);
}
/* Upgrade from schema 1 (Nix <= 0.7) to schema 2 (Nix >= 0.8). */
static void upgradeStore07()

View file

@ -102,6 +102,12 @@ public:
void scanAndUpdateAllReferencesRecusively(const Path & storeOrstatePath);
void setStateRevisions(const Path & statePath, const RevisionNumbersSetClosure & revisions, const int revision);
bool queryStateRevisions(const Path & statePath, RevisionNumbersClosure & revisions, const int revision);
bool queryAvailableStateRevisions(const Path & statePath, RevisionNumbers & revisions);
};

View file

@ -474,6 +474,22 @@ void RemoteStore::scanAndUpdateAllReferencesRecusively(const Path & storeOrstate
}
//TODO
void RemoteStore::setStateRevisions(const Path & statePath, const RevisionNumbersSetClosure & revisions, const int revision)
{
}
//TODO
bool RemoteStore::queryStateRevisions(const Path & statePath, RevisionNumbersClosure & revisions, const int revision)
{
return false;
}
//TODO
bool RemoteStore::queryAvailableStateRevisions(const Path & statePath, RevisionNumbers & revisions)
{
return false;
}
}

View file

@ -89,6 +89,12 @@ public:
void scanAndUpdateAllReferences(const Path & statePath);
void scanAndUpdateAllReferencesRecusively(const Path & storeOrstatePath);
void setStateRevisions(const Path & statePath, const RevisionNumbersSetClosure & revisions, const int revision);
bool queryStateRevisions(const Path & statePath, RevisionNumbersClosure & revisions, const int revision);
bool queryAvailableStateRevisions(const Path & statePath, RevisionNumbers & revisions);
private:
AutoCloseFD fdSocket;

View file

@ -222,6 +222,15 @@ public:
/* TODO */
virtual void scanAndUpdateAllReferencesRecusively(const Path & storeOrstatePath) = 0;
/* TODO */
virtual void setStateRevisions(const Path & statePath, const RevisionNumbersSetClosure & revisions, const int revision) = 0;
/* TODO */
virtual bool queryStateRevisions(const Path & statePath, RevisionNumbersClosure & revisions, const int revision) = 0;
/* TODO */
virtual bool queryAvailableStateRevisions(const Path & statePath, RevisionNumbers & revisions) = 0;
};

View file

@ -60,6 +60,7 @@ typedef set<Path> PathSet;
//state types
typedef list<int> RevisionNumbers; //the Strings (list) of StateReferences and this list are connected by position
typedef map<Path, RevisionNumbers> RevisionNumbersSetClosure; //We include to the paths to sort on
typedef list<RevisionNumbers> RevisionNumbersClosure;
typedef map<int, Strings> StateReferences;

View file

@ -22,6 +22,7 @@ typedef void (* Operation) (Strings opFlags, Strings opArgs);
//two global variables
string stateIdentifier;
string username;
int revision_arg;
/************************* Build time Functions ******************************/
@ -181,50 +182,48 @@ RevisionNumbers readRevisionNumbers(const Derivation & drv)
Path statePath = stateOutputs.find("state")->second.statepath;
string getStateIdentifier = stateOutputs.find("state")->second.stateIdentifier;
//TODO sort based on the repository
vector<Path> sorted_repositorys;
for (DerivationStateOutputDirs::const_reverse_iterator i = stateOutputDirs.rbegin(); i != stateOutputDirs.rend(); ++i){
DerivationStateOutputDir d = i->second;
string thisdir = d.path;
//Get the a repository for this state location
string repos = getStateReposPath("stateOutput:staterepospath", statePath, thisdir, drvName, getStateIdentifier); //this is a copy from store-state.cc
sorted_repositorys.push_back(repos);
}
sort(sorted_repositorys.begin(), sorted_repositorys.end());
//After the sort read the paths
for (vector<Path>::const_iterator i = sorted_repositorys.begin(); i != sorted_repositorys.end(); ++i){
string repos = *i;
printMsg(lvlError, format("%1%") % repos);
if(IsDirectory(repos)){
Strings p_args;
p_args.push_back(svnbin);
p_args.push_back("file://" + repos);
string output = runProgram(nixLibexecDir + "/nix/nix-readrevisions.sh", true, p_args);
int pos = output.find("\n",0);
string output = runProgram(nixLibexecDir + "/nix/nix-readrevisions.sh", true, p_args); //run
int pos = output.find("\n",0); //remove trailing \n
output.erase(pos,1);
int revision;
bool succeed = string2Int(output, revision);
if(!succeed)
throw Error(format("Cannot read revision number of path '%1%'") % repos);
revisions.push_back(revision);
}
revisions.push_back(revision); //insert into array
}
else
revisions.push_back(-1);
}
return revisions;
}
void setAllRevisionNumbers(const PathSet & drvs)
{
//for.....
//DerivationStateOutputs stateOutputs = drv.stateOutputs;
//Path statePath = stateOutputs.find("state")->second.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
/*
* Input: store (or statePath?)
* Returns all the drv's of the statePaths (in)directly referenced.
*/
PathSet getAllStateDerivationsRecursively(const Path & storePath)
{
//Get recursively all state paths
@ -239,16 +238,61 @@ PathSet getAllStateDerivationsRecursively(const Path & storePath)
return derivations;
}
//TODO also allow statePaths as input?
static void queryAvailableStateRevisions(Strings opFlags, Strings opArgs)
{
Path componentPath;
Path statePath;
string binary;
string derivationPath;
bool isStatePath;
string program_args;
Derivation drv = getDerivation_andCheckArgs(opFlags, opArgs, componentPath, statePath, binary, derivationPath, isStatePath, program_args);
RevisionNumbers revisions;
bool notEmpty = store->queryAvailableStateRevisions(statePath, revisions);
if(!notEmpty){ //can this happen?
printMsg(lvlError, format("No revisions yet for: %1%") % statePath);
return;
}
for (RevisionNumbers::iterator i = revisions.begin(); i != revisions.end(); ++i)
{
printMsg(lvlError, format("Available Revision: %1%") % int2String(*i));
}
}
static void revertToRevision(Strings opFlags, Strings opArgs)
{
Path componentPath;
Path statePath;
string binary;
string derivationPath;
bool isStatePath;
string program_args;
Derivation drv = getDerivation_andCheckArgs(opFlags, opArgs, componentPath, statePath, binary, derivationPath, isStatePath, program_args);
bool recursive = true; //TODO !!!!!!!!!
//get dependecies (if neccecary | recusively) of all state components that need to be updated
PathSet root_drvs = getAllStateDerivationsRecursively(componentPath);
//revision_arg
//TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
static void opRunComponent(Strings opFlags, Strings opArgs)
{
//get the all the info of the component that is being called (we dont really use it yet)
Path componentPath;
Path statePath;
string binary;
string derivationPath;
bool isStatePath;
string program_args;
Derivation drv = getDerivation_andCheckArgs(opFlags, opArgs, componentPath, statePath, binary, derivationPath, isStatePath, program_args);
Path root_componentPath;
Path root_statePath;
string root_binary;
string root_derivationPath;
bool root_isStatePath;
string root_program_args;
Derivation root_drv = getDerivation_andCheckArgs(opFlags, opArgs, root_componentPath, root_statePath, root_binary, root_derivationPath, root_isStatePath, root_program_args);
//Specifiy the SVN binarys
string svnbin = nixSVNPath + "/svn";
@ -261,8 +305,7 @@ static void opRunComponent(Strings opFlags, Strings opArgs)
//svn lock ... ?
//get dependecies (if neccecary | recusively) of all state components that need to be updated
PathSet drvs = getAllStateDerivationsRecursively(componentPath);
PathSet root_drvs = getAllStateDerivationsRecursively(root_componentPath);
//TODO maybe also scan the parameters for state or component hashes?
//program_args
@ -274,11 +317,13 @@ static void opRunComponent(Strings opFlags, Strings opArgs)
//******************* Run ****************************
executeShellCommand(componentPath + binary + " " + program_args); //more efficient way needed ???
executeShellCommand(root_componentPath + root_binary + " " + root_program_args); //more efficient way needed ???
//******************* With everything in place, we call the commit script on all statePaths **********************
for (PathSet::iterator d = drvs.begin(); d != drvs.end(); ++d)
map<Path, RevisionNumbers> rivisionsClosureMapping;
for (PathSet::iterator d = root_drvs.begin(); d != root_drvs.end(); ++d)
{
//Extract the neccecary info from each Drv
Path drvPath = *d;
@ -384,20 +429,30 @@ 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 ...
if(false)
store->scanAndUpdateAllReferencesRecusively(statePath);
rivisionsClosureMapping[statePath] = readRevisionNumbers(drv); //Get current numbers
}
//Update all revision numbers in the database
setAllRevisionNumbers(drvs);
//Store the revision numbers in the database for this statePath to a new revision
store->setStateRevisions(root_statePath, rivisionsClosureMapping, -1);
RevisionNumbersClosure getRivisionsClosure;
bool b = store->queryStateRevisions(root_statePath, getRivisionsClosure, -1);
for (RevisionNumbersClosure::iterator d = getRivisionsClosure.begin(); d != getRivisionsClosure.end(); ++d){
printMsg(lvlError, format("REVVV"));
for (RevisionNumbers::iterator e = (*d).begin(); e != (*d).end(); ++e)
printMsg(lvlError, format("REV %1%") % *e);
}
}
void run(Strings args)
{
Strings opFlags, opArgs;
@ -519,6 +574,11 @@ void run(Strings args)
op = opShowStateReposRootPath;
else if (arg == "--showderivations")
op = opShowDerivations;
else if (arg == "--showrevisions")
op = queryAvailableStateRevisions;
else if (arg.substr(0,21) == "--revert-to-revision=")
op = revertToRevision;
/*
@ -526,24 +586,40 @@ void run(Strings args)
--run-without-commit
--showrevisions
--revert-to-revision=
--share-from
--unshare
OPTIONAL
--scanreferences
/////////////////////
--backup ?
--exclude-commit-paths
TODO update getDerivation in nix-store to handle state indentifiers
--revert-to-state (recursive revert...)
--delete-state
--share-from
--delete-revision
*/
else if (arg.substr(0,21) == "--revert-to-revision="){
bool succeed = string2Int(arg.substr(21,arg.length()), revision_arg);
if(!succeed)
throw UsageError("The given revision is not a valid number");
}
else if (arg.substr(0,13) == "--identifier=")
stateIdentifier = arg.substr(13,arg.length());
else if (arg.substr(0,7) == "--user=")
username = arg.substr(7,arg.length());
else
opArgs.push_back(arg);