diff --git a/scripts/nix-statecommit.sh b/scripts/nix-statecommit.sh index a3a8c6aaf..70cd73daa 100755 --- a/scripts/nix-statecommit.sh +++ b/scripts/nix-statecommit.sh @@ -3,7 +3,7 @@ #check if there are enough arguments, if not, exit with an error -debug="echo "; #set to "" for no debugging, set to "echo " to debug the commands +debug=""; #set to "" for no debugging, set to "echo " to debug the commands if [ "$#" != 6 ] && [ "$#" != 7 ] ; then echo "Incorrect number of arguments" @@ -34,6 +34,8 @@ if [ "$debug" != "" ] ; then echo deletesvn: $deletesvn fi +# TODO: we need a solution for symlinks, svn doesnt support them + # # # diff --git a/scripts/nix-statecommit.sh.in b/scripts/nix-statecommit.sh.in index a397b4050..70cd73daa 100755 --- a/scripts/nix-statecommit.sh.in +++ b/scripts/nix-statecommit.sh.in @@ -3,7 +3,7 @@ #check if there are enough arguments, if not, exit with an error -debug="echo "; #set to "" for no debugging, set to "echo " to debug the commands +debug=""; #set to "" for no debugging, set to "echo " to debug the commands if [ "$#" != 6 ] && [ "$#" != 7 ] ; then echo "Incorrect number of arguments" diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 56f01ed1f..06f7e7902 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -449,7 +449,6 @@ static Expr prim_derivationStrict(EvalState & state, const ATermVector & args) drv.args.push_back(s); } } - //Add specific state variables else if(key == "stateDirs") { @@ -508,6 +507,19 @@ static Expr prim_derivationStrict(EvalState & state, const ATermVector & args) } } + else if(key == "solidStateDependencies"){ + ATermList es; + value = evalExpr(state, value); + if (!matchList(value, es)) { + static bool haveWarned = false; + warnOnce(haveWarned, "the `solidStateDependencies' attribute should evaluate to a list"); + es = flattenList(state, value); + } + for (ATermIterator i(es); i; ++i) { + string s = coerceToString(state, *i, context, true); + drv.solidStateDeps.insert(s); + } + } else if(key == "shareState") { shareState = coerceToString(state, value, context, true); } else if(key == "synchronization") { syncState = coerceToString(state, value, context, true); } else if(key == "disableState") { disableState = evalBool(state, value); } @@ -615,6 +627,13 @@ static Expr prim_derivationStrict(EvalState & state, const ATermVector & args) drv.env["out"] = outPath; drv.outputs["out"] = DerivationOutput(outPath, outputHashAlgo, outputHash); + /* Replace $(statePath) in solidStateDeps */ + for (StringSet::iterator i = drv.solidStateDeps.begin(); i != drv.solidStateDeps.end(); ++i) + if(*i == "$(statePath)" || "$statePath" ){ + drv.solidStateDeps.erase(*i); + drv.solidStateDeps.insert(outPath); + } + //printMsg(lvlError, format("DerivationOutput %1% %2% %3%") % outPath % outputHashAlgo % outputHash); //only add state when we have to to keep compitibilty with the 'old' format. //We add state when it's enbaled by the keywords, and not excplicitly disabled by the user diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 9e1a6c2ee..a1089ee40 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -1702,6 +1702,9 @@ void DerivationGoal::computeClosure() /* Get rid of all weird permissions. */ canonicalisePathMetaData(path); + + /* Just before the very first scanForReferences, we insert the solid state references in its table so its references will show up in the scan*/ + setSolidStateReferencesTxn(noTxn, path, drv.solidStateDeps); /* For this output path, find the component references to other paths contained in it. */ PathSet references = scanForReferences(path, allPaths); diff --git a/src/libstore/derivations-ast.def b/src/libstore/derivations-ast.def index 9173383fb..1bddb77d1 100644 --- a/src/libstore/derivations-ast.def +++ b/src/libstore/derivations-ast.def @@ -1,8 +1,6 @@ init initDerivationsHelpers -#wouter added 2 ATermList - -Derive | ATermList ATermList ATermList ATermList ATermList string string ATermList ATermList | ATerm | +Derive | ATermList ATermList ATermList ATermList ATermList ATermList string string ATermList ATermList | ATerm | | string string | ATerm | EnvBinding | | string ATermList | ATerm | DerivationInput | | string string string string | ATerm | DerivationOutput | @@ -10,7 +8,7 @@ Derive | ATermList ATermList ATermList ATermList ATermList string string ATermLi | string string string | ATerm | DerivationStateOutputDir | #We use DeriveWithOutState to create derivations that dont use state, and thus dont have the stateDerivationStateOutput and DerivationStateOutputDir in their derivation -#Ive put this in because eelco requested it, and its easy to stay backwards compatible, but ultimately I think that it should be removed to prevent confusion & duplication +#Ive put this in becuase its easy to stay backwards compatible, but maybe it should be removed somtime to prevent confusion & duplication #The function will be called matchDerivateWithOutState, but it will match the Derive term to remain backwards compatible Derive | ATermList ATermList ATermList string string ATermList ATermList | ATerm | DeriveWithOutState diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index 3a8bf284e..9e140b457 100644 --- a/src/libstore/derivations.cc +++ b/src/libstore/derivations.cc @@ -66,13 +66,13 @@ void throwBadDrv(ATerm t) Derivation parseDerivation(ATerm t) { Derivation drv; - ATermList outs, inDrvs, inSrcs, args, bnds; + ATermList outs, solidStateDeps, inDrvs, inSrcs, args, bnds; ATermList stateOuts = ATempty, stateOutDirs = ATempty; ATerm builder, platform; bool withState; - if (matchDerive(t, outs, stateOuts, stateOutDirs, inDrvs, inSrcs, platform, builder, args, bnds) ) { withState = true; } + if (matchDerive(t, outs, stateOuts, stateOutDirs, solidStateDeps, inDrvs, inSrcs, platform, builder, args, bnds) ) { withState = true; } else if (matchDeriveWithOutState(t, outs, inDrvs, inSrcs, platform, builder, args, bnds) ) { withState = false; } else throwBadDrv(t); @@ -89,7 +89,8 @@ Derivation parseDerivation(ATerm t) drv.outputs[aterm2String(id)] = out; } - if(withState){ + if(withState) + { //parse state part for (ATermIterator i(stateOuts); i; ++i) { ATerm id, statepath, componentHash, hashAlgo, hash, stateIdentifier, enabled, shared, synchronization, createDirsBeforeInstall, runtimeStateParamters, username; @@ -110,9 +111,7 @@ Derivation parseDerivation(ATerm t) stateOut.username = aterm2String(username); drv.stateOutputs[aterm2String(id)] = stateOut; } - } - if(withState){ //parse state dirs part for (ATermIterator i(stateOutDirs); i; ++i) { ATerm id, path, type, interval; @@ -125,6 +124,13 @@ Derivation parseDerivation(ATerm t) stateOutDirs.interval = aterm2String(interval); drv.stateOutputDirs[aterm2String(id)] = stateOutDirs; } + + //parse solid state dependencies + for (ATermIterator i(solidStateDeps); i; ++i) { + if (ATgetType(*i) != AT_APPL) + throw badTerm("string expected", *i); + drv.solidStateDeps.insert(aterm2String(*i)); + } } for (ATermIterator i(inDrvs); i; ++i) { @@ -202,11 +208,14 @@ ATerm unparseDerivation(const Derivation & drv) stateOutputDirs = ATinsert(stateOutputDirs, makeDerivationStateOutputDir( toATerm(i->first), - //toATerm(i->second.path), //removed to prevent duplication since the key is also the path toATerm(i->second.type), toATerm(i->second.interval) )); - + + ATermList solidStateDeps = ATempty; + for (StringSet::const_reverse_iterator i = drv.solidStateDeps.rbegin(); + i != drv.solidStateDeps.rend(); ++i) + solidStateDeps = ATinsert(solidStateDeps, toATerm(*i)); ATermList inDrvs = ATempty; for (DerivationInputs::const_reverse_iterator i = drv.inputDrvs.rbegin(); @@ -234,6 +243,7 @@ ATerm unparseDerivation(const Derivation & drv) outputs, stateOutputs, stateOutputDirs, + solidStateDeps, inDrvs, toATermList(drv.inputSrcs), toATerm(drv.platform), diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh index f4d900891..4e64d55a5 100644 --- a/src/libstore/derivations.hh +++ b/src/libstore/derivations.hh @@ -158,8 +158,9 @@ typedef std::map StringPairs; struct Derivation { DerivationOutputs outputs; /* keyed on symbolic IDs */ - DerivationStateOutputs stateOutputs; /* */ - DerivationStateOutputDirs stateOutputDirs; /* */ + DerivationStateOutputs stateOutputs; /* TODO */ + DerivationStateOutputDirs stateOutputDirs; /* TODO */ + StringSet solidStateDeps; /* TODO */ DerivationInputs inputDrvs; /* inputs that are sub-derivations */ PathSet inputSrcs; /* inputs that are sources */ string platform; diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index c3da4482d..7251f6d00 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -80,6 +80,12 @@ static TableId dbComponentStateReferrers = 0; static TableId dbStateComponentReferrers = 0; static TableId dbStateStateReferrers = 0; +/* dbSolidStateReferences :: Path -> [Path] + * + * TODO Comment!!!!!!!!!!!!!!!!!!!!!!!1 + * + */ +static TableId dbSolidStateReferences = 0; /* dbSubstitutes :: Path -> [[Path]] @@ -190,15 +196,17 @@ LocalStore::LocalStore(bool reserveSpace) dbStateInfo = nixDB.openTable("stateinfo"); dbStateCounters = nixDB.openTable("statecounters"); - dbComponentComponentReferences = nixDB.openTable("references"); + dbComponentComponentReferences = nixDB.openTable("references"); /* c_c */ dbComponentStateReferences = nixDB.openTable("references_c_s"); dbStateComponentReferences = nixDB.openTable("references_s_c"); dbStateStateReferences = nixDB.openTable("references_s_s"); - dbComponentComponentReferrers = nixDB.openTable("referrers", true); /* must be sorted */ + dbComponentComponentReferrers = nixDB.openTable("referrers", true); /* must be sorted */ /* c_c */ 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"); + + dbSolidStateReferences = nixDB.openTable("references_solid_c_s"); /* The contents of this table is included in references_c_s */ int curSchema = 0; Path schemaFN = nixDBPath + "/schema"; @@ -1709,6 +1717,20 @@ void LocalStore::updateRevisionsRecursively(const Path & statePath) nix::updateRevisionsRecursivelyTxn(noTxn, statePath); } +void setSolidStateReferencesTxn(const Transaction & txn, const Path & statePath, const PathSet & paths) +{ + Strings ss = Strings(paths.begin(), paths.end()); + nixDB.setStrings(txn, dbSolidStateReferences, statePath, ss); +} + +bool querySolidStateReferencesTxn(const Transaction & txn, const Path & statePath, PathSet & paths) +{ + Strings ss; + bool notempty = nixDB.queryStrings(txn, dbSolidStateReferences, statePath, ss); + paths.insert(ss.begin(), ss.end()); + return notempty; +} + /* Upgrade from schema 1 (Nix <= 0.7) to schema 2 (Nix >= 0.8). */ static void upgradeStore07() { diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index c782a1508..bf4936d8f 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -240,6 +240,9 @@ void setStateRevisionsTxn(const Transaction & txn, const Path & statePath, const bool isValidPathTxn(const Transaction & txn, const Path & path); bool isValidStatePathTxn(const Transaction & txn, const Path & path); +void setSolidStateReferencesTxn(const Transaction & txn, const Path & statePath, const PathSet & paths); +bool querySolidStateReferencesTxn(const Transaction & txn, const Path & statePath, PathSet & paths); + } diff --git a/src/libstore/references.cc b/src/libstore/references.cc index 44fc3b13d..5d77362af 100644 --- a/src/libstore/references.cc +++ b/src/libstore/references.cc @@ -1,6 +1,7 @@ #include "references.hh" #include "hash.hh" #include "util.hh" +#include "local-store.hh" #include #include @@ -119,6 +120,11 @@ void checkPath(const string & path, PathSet scanForReferences(const string & path, const PathSet & paths) +{ + return scanForReferencesTxn(noTxn, path, paths); +} + +PathSet scanForReferencesTxn(const Transaction & txn, const Path & path, const PathSet & paths) { std::map backMap; StringSet ids; @@ -150,6 +156,14 @@ PathSet scanForReferences(const string & path, const PathSet & paths) found.insert(j->second); } + //Get the solid state dependencies, and also insert them + PathSet solidStateDeps; + querySolidStateReferencesTxn(txn, path, solidStateDeps); + found.insert(solidStateDeps.begin(), solidStateDeps.end()); + + //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! we only scan the paths, if we scan for state references, this STORE path will show up !!!!!!!!!!!!!! + //TODO Create a scanForReferencesState() funtion wrapper !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + return found; } diff --git a/src/libstore/references.hh b/src/libstore/references.hh index 55da8f7fd..580ef9f64 100644 --- a/src/libstore/references.hh +++ b/src/libstore/references.hh @@ -2,11 +2,14 @@ #define __REFERENCES_H #include "types.hh" +#include "db.hh" namespace nix { PathSet scanForReferences(const Path & path, const PathSet & refs); +PathSet scanForReferencesTxn(const Transaction & txn, const Path & path, const PathSet & refs); + } #endif /* !__REFERENCES_H */