mirror of
https://github.com/NixOS/nix.git
synced 2025-11-26 04:00:59 +01:00
This commit is contained in:
parent
40161d0be1
commit
cc7d4c8bd7
8 changed files with 146 additions and 102 deletions
|
|
@ -4,7 +4,7 @@ bin_SCRIPTS = nix-collect-garbage \
|
||||||
nix-pack-closure nix-unpack-closure \
|
nix-pack-closure nix-unpack-closure \
|
||||||
nix-copy-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
|
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) find-runtime-roots.pl $(DESTDIR)$(libexecdir)/nix
|
||||||
$(INSTALL_PROGRAM) generate-patches.pl $(DESTDIR)$(libexecdir)/nix
|
$(INSTALL_PROGRAM) generate-patches.pl $(DESTDIR)$(libexecdir)/nix
|
||||||
$(INSTALL_PROGRAM) nix-statecommit.sh $(DESTDIR)$(libexecdir)/nix
|
$(INSTALL_PROGRAM) nix-statecommit.sh $(DESTDIR)$(libexecdir)/nix
|
||||||
|
$(INSTALL_PROGRAM) nix-readrevisions.sh $(DESTDIR)$(libexecdir)/nix
|
||||||
$(INSTALL) -d $(DESTDIR)$(sysconfdir)/nix
|
$(INSTALL) -d $(DESTDIR)$(sysconfdir)/nix
|
||||||
|
|
||||||
include ../substitute.mk
|
include ../substitute.mk
|
||||||
|
|
@ -34,4 +35,6 @@ EXTRA_DIST = nix-collect-garbage.in \
|
||||||
nix-pack-closure.in nix-unpack-closure.in \
|
nix-pack-closure.in nix-unpack-closure.in \
|
||||||
nix-copy-closure.in \
|
nix-copy-closure.in \
|
||||||
find-runtime-roots.pl.in \
|
find-runtime-roots.pl.in \
|
||||||
nix-statecommit.sh.in
|
nix-statecommit.sh.in \
|
||||||
|
nix-readrevisions.sh
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -498,6 +498,8 @@ bool Database::queryStateReferences(const Transaction & txn, TableId table,
|
||||||
Strings keys;
|
Strings keys;
|
||||||
enumTable(txn, table, keys); //get all revisions
|
enumTable(txn, table, keys); //get all revisions
|
||||||
|
|
||||||
|
///////////////?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! create function
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TODO
|
||||||
string key = ""; //final key that matches revision + statePath
|
string key = ""; //final key that matches revision + statePath
|
||||||
int highestRev = -1;
|
int highestRev = -1;
|
||||||
|
|
||||||
|
|
@ -520,6 +522,7 @@ bool Database::queryStateReferences(const Transaction & txn, TableId table,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
if(key == "" && highestRev == -1) //no records found (TODO throw error?)
|
if(key == "" && highestRev == -1) //no records found (TODO throw error?)
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -548,22 +551,94 @@ bool Database::queryStateReferrers(const Transaction & txn, TableId table,
|
||||||
|
|
||||||
|
|
||||||
void Database::setStateRevisions(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,
|
bool Database::queryStateRevisions(const Transaction & txn, TableId table,
|
||||||
const Path & statePath, RevisionNumbers & revisions, int revision)
|
const Path & statePath, RevisionNumbersClosure & revisions, int revision)
|
||||||
{
|
{
|
||||||
//TODO
|
const string seperator = "|";
|
||||||
return false;
|
|
||||||
|
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,
|
bool Database::queryAllStateRevisions(const Transaction & txn, TableId table,
|
||||||
const Path & statePath, RevisionNumbers & revisions)
|
const Path & statePath, RevisionNumbers & revisions)
|
||||||
{
|
{
|
||||||
//TODO
|
//TODO
|
||||||
|
|
||||||
|
//LIST OF x ..... y which revisions are available for a rollback
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -110,11 +110,11 @@ public:
|
||||||
|
|
||||||
/* Set the revision number of the statePath and the revision numbers of all state paths in the references closure */
|
/* 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,
|
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 */
|
/* Returns all the revision numbers of the state references closure of the given state path */
|
||||||
bool queryStateRevisions(const Transaction & txn, TableId table,
|
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 */
|
/* Returns all available revision numbers of the given state path */
|
||||||
bool queryAllStateRevisions(const Transaction & txn, TableId table,
|
bool queryAllStateRevisions(const Transaction & txn, TableId table,
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,9 @@ void createStateDirs(const DerivationStateOutputDirs & stateOutputDirs, const De
|
||||||
//Initialize the counters for the statePaths that have an interval to 0
|
//Initialize the counters for the statePaths that have an interval to 0
|
||||||
vector<int> empty;
|
vector<int> empty;
|
||||||
store->setStatePathsInterval(intervalPaths, empty, true);
|
store->setStatePathsInterval(intervalPaths, empty, true);
|
||||||
|
|
||||||
|
//TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
|
||||||
|
//Initialize the revisions recursively
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,8 +59,8 @@ typedef list<Path> Paths;
|
||||||
typedef set<Path> PathSet;
|
typedef set<Path> PathSet;
|
||||||
|
|
||||||
//state types
|
//state types
|
||||||
struct RevisionNumbersKey { Path statePath; int revision; } ;
|
|
||||||
typedef list<int> RevisionNumbers; //the Strings (list) of StateReferences and this list are connected by position
|
typedef list<int> RevisionNumbers; //the Strings (list) of StateReferences and this list are connected by position
|
||||||
|
typedef list<RevisionNumbers> RevisionNumbersClosure;
|
||||||
typedef map<int, Strings> StateReferences;
|
typedef map<int, Strings> StateReferences;
|
||||||
|
|
||||||
//typedef std::map<int, Strings> StateReferencesKey;
|
//typedef std::map<int, Strings> StateReferencesKey;
|
||||||
|
|
|
||||||
|
|
@ -769,12 +769,8 @@ void killUser(uid_t uid)
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
string runProgram(Path program, bool searchPath, const Strings & args)
|
string runProgram(Path program, bool searchPath, const Strings & args)
|
||||||
{
|
{
|
||||||
/* Split args based on | for pipe-ing */
|
|
||||||
StringsList l;
|
|
||||||
|
|
||||||
/* Create a pipe. */
|
/* Create a pipe. */
|
||||||
Pipe pipe;
|
Pipe pipe;
|
||||||
pipe.create();
|
pipe.create();
|
||||||
|
|
@ -809,7 +805,6 @@ string runProgram(Path program, bool searchPath, const Strings & args)
|
||||||
} catch (std::exception & e) {
|
} catch (std::exception & e) {
|
||||||
std::cerr << "error: " << e.what() << std::endl;
|
std::cerr << "error: " << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
quickExit(1);
|
quickExit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -817,70 +812,14 @@ string runProgram(Path program, bool searchPath, const Strings & args)
|
||||||
|
|
||||||
pipe.writeSide.close();
|
pipe.writeSide.close();
|
||||||
|
|
||||||
|
string result = drainFD(pipe.readSide);
|
||||||
|
|
||||||
/* Wait for the child to finish. */
|
/* Wait for the child to finish. */
|
||||||
int status = pid.wait(true);
|
int status = pid.wait(true);
|
||||||
if (!statusOk(status))
|
if (!statusOk(status))
|
||||||
throw Error(format("program `%1%' %2%")
|
throw Error(format("program `%1%' %2%")
|
||||||
% program % statusToString(status));
|
% 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<const char *> 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;
|
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
|
set_union(vector1.begin(), vector1.end(),vector2.begin(), vector2.end(), back_inserter(setResult)); //Also available: set_symmetric_difference and set_intersection
|
||||||
|
|
||||||
PathSet diff;
|
PathSet diff;
|
||||||
for(int i=0; i<setResult.size(); i++)
|
for(unsigned int i=0; i<setResult.size(); i++)
|
||||||
diff.insert(setResult[i]);
|
diff.insert(setResult[i]);
|
||||||
|
|
||||||
return diff;
|
return diff;
|
||||||
|
|
|
||||||
|
|
@ -263,7 +263,6 @@ MakeError(Interrupted, Error)
|
||||||
string packStrings(const Strings & strings);
|
string packStrings(const Strings & strings);
|
||||||
Strings unpackStrings(const string & s);
|
Strings unpackStrings(const string & s);
|
||||||
|
|
||||||
|
|
||||||
/* String tokenizer. */
|
/* String tokenizer. */
|
||||||
Strings tokenizeString(const string & s, const string & separators = " \t\n\r");
|
Strings tokenizeString(const string & s, const string & separators = " \t\n\r");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ Derivation getDerivation_andCheckArgs_(Strings opFlags, Strings opArgs, Path & c
|
||||||
}
|
}
|
||||||
|
|
||||||
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]. TODO !!!!!!!!!!!!!!!!!!!! change to *(derivers.begin())
|
||||||
derivationPath = *i;
|
derivationPath = *i;
|
||||||
drv = derivationFromPath(derivationPath);
|
drv = derivationFromPath(derivationPath);
|
||||||
}
|
}
|
||||||
|
|
@ -189,31 +189,41 @@ RevisionNumbers readRevisionNumbers(const Derivation & drv)
|
||||||
string repos = getStateReposPath("stateOutput:staterepospath", statePath, thisdir, drvName, getStateIdentifier); //this is a copy from store-state.cc
|
string repos = getStateReposPath("stateOutput:staterepospath", statePath, thisdir, drvName, getStateIdentifier); //this is a copy from store-state.cc
|
||||||
|
|
||||||
if(IsDirectory(repos)){
|
if(IsDirectory(repos)){
|
||||||
printMsg(lvlError, format("'%1%'") % repos);
|
|
||||||
Strings p_args;
|
Strings p_args;
|
||||||
p_args.push_back("info");
|
p_args.push_back(svnbin);
|
||||||
p_args.push_back("file://" + repos);
|
p_args.push_back("file://" + repos);
|
||||||
|
string output = runProgram(nixLibexecDir + "/nix/nix-readrevisions.sh", true, p_args);
|
||||||
string output = runProgram(svnbin, true, p_args);
|
int pos = output.find("\n",0);
|
||||||
|
output.erase(pos,1);
|
||||||
/*
|
int revision;
|
||||||
p_args.clear();
|
bool succeed = string2Int(output, revision);
|
||||||
p_args.push_back("-n");
|
if(!succeed)
|
||||||
p_args.push_back("/^Revision: /p");
|
throw Error(format("Cannot read revision number of path '%1%'") % repos);
|
||||||
p_args.push_back(output);
|
revisions.push_back(revision);
|
||||||
output = runProgram("sed", true, p_args);
|
|
||||||
*/
|
|
||||||
|
|
||||||
printMsg(lvlError, format("%2%") % repos % output);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
revisions.push_back(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//svn info $repos | sed -n '/^Revision: /p' | sed 's/Revision: //' | tr -d "\12"
|
|
||||||
|
|
||||||
return revisions;
|
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
|
//Comment TODO
|
||||||
PathSet getAllStateDerivationsRecursively(const Path & storePath)
|
PathSet getAllStateDerivationsRecursively(const Path & storePath)
|
||||||
{
|
{
|
||||||
|
|
@ -379,9 +389,11 @@ static void opRunComponent(Strings opFlags, Strings opArgs)
|
||||||
//Scan if needed
|
//Scan if needed
|
||||||
//scanAndUpdateAllReferencesRecusively ...
|
//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);
|
nixDB.splitStatePathRevision(gets, statePath2, revision2);
|
||||||
printMsg(lvlError, format("'%1%' '%2%'") % statePath2 % int2String(revision2));
|
printMsg(lvlError, format("'%1%' '%2%'") % statePath2 % int2String(revision2));
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
store = openStore();
|
store = openStore();
|
||||||
Derivation drv = derivationFromPath("/nix/store/r2lvhrd8zhb877n07cqvcyp11j9ws5p0-hellohardcodedstateworld-dep1-1.0.drv");
|
Derivation drv = derivationFromPath("/nix/store/r2lvhrd8zhb877n07cqvcyp11j9ws5p0-hellohardcodedstateworld-dep1-1.0.drv");
|
||||||
readRevisionNumbers(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 */
|
/* test */
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue