diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libexpr/primops.cc | 67 | ||||
-rw-r--r-- | src/libstore/local-store.cc | 22 | ||||
-rw-r--r-- | src/libstore/local-store.hh | 2 | ||||
-rw-r--r-- | src/libstore/remote-store.cc | 10 | ||||
-rw-r--r-- | src/libstore/remote-store.hh | 2 | ||||
-rw-r--r-- | src/libstore/store-api.hh | 3 | ||||
-rw-r--r-- | src/libstore/worker-protocol.hh | 1 | ||||
-rw-r--r-- | src/nix-worker/nix-worker.cc | 10 |
8 files changed, 96 insertions, 21 deletions
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 66173cdaf..ca7766487 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -356,27 +356,31 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) inputs to ensure that they are available when the builder runs. */ if (path.at(0) == '=') { - path = string(path, 1); - PathSet refs; computeFSClosure(*store, path, refs); + /* !!! This doesn't work if readOnlyMode is set. */ + PathSet refs; computeFSClosure(*store, string(path, 1), refs); foreach (PathSet::iterator, j, refs) { drv.inputSrcs.insert(*j); if (isDerivation(*j)) - drv.inputDrvs[*j] = singleton<StringSet>("out"); + drv.inputDrvs[*j] = store->queryDerivationOutputNames(*j); } } /* See prim_unsafeDiscardOutputDependency. */ - bool useDrvAsSrc = false; - if (path.at(0) == '~') { - path = string(path, 1); - useDrvAsSrc = true; + else if (path.at(0) == '~') + drv.inputSrcs.insert(string(path, 1)); + + /* Handle derivation outputs of the form ‘!<name>!<path>’. */ + else if (path.at(0) == '!') { + size_t index = path.find("!", 1); + drv.inputDrvs[string(path, index + 1)].insert(string(path, 1, index - 1)); } - assert(isStorePath(path)); + /* Handle derivation contexts returned by + ‘builtins.storePath’. */ + else if (isDerivation(path)) + drv.inputDrvs[path] = store->queryDerivationOutputNames(path); - debug(format("derivation uses `%1%'") % path); - if (!useDrvAsSrc && isDerivation(path)) - drv.inputDrvs[path] = singleton<StringSet>("out"); + /* Otherwise it's a source file. */ else drv.inputSrcs.insert(path); } @@ -450,7 +454,7 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) /* The output path of an output X is ‘<X>Path’, e.g. ‘outPath’. */ mkString(*state.allocAttr(v, state.symbols.create(i->first + "Path")), - i->second.path, singleton<PathSet>(drvPath)); + i->second.path, singleton<PathSet>("!" + i->first + "!" + drvPath)); } v.attrs->sort(); } @@ -1042,15 +1046,6 @@ void EvalState::createBaseEnv() addPrimOp("__getEnv", 1, prim_getEnv); addPrimOp("__trace", 2, prim_trace); - // Derivations - addPrimOp("derivationStrict", 1, prim_derivationStrict); - - /* Add a wrapper around the derivation primop that computes the - `drvPath' and `outPath' attributes lazily. */ - string s = "attrs: let res = derivationStrict attrs; in attrs // { drvPath = res.drvPath; outPath = res.outPath; type = \"derivation\"; }"; - mkThunk_(v, parseExprFromString(s, "/")); - addConstant("derivation", v); - // Paths addPrimOp("__toPath", 1, prim_toPath); addPrimOp("__storePath", 1, prim_storePath); @@ -1099,6 +1094,36 @@ void EvalState::createBaseEnv() addPrimOp("__parseDrvName", 1, prim_parseDrvName); addPrimOp("__compareVersions", 2, prim_compareVersions); + // Derivations + addPrimOp("derivationStrict", 1, prim_derivationStrict); + + /* Add a wrapper around the derivation primop that computes the + `drvPath' and `outPath' attributes lazily. */ + string s = "attrs: \ + let \ + strict = derivationStrict attrs; \ + attrValues = attrs: \ + map (name: builtins.getAttr name attrs) (builtins.attrNames attrs); \ + outputToAttrListElement = output: \ + { \ + name = output; \ + value = attrs // { \ + outPath = builtins.getAttr (output + \"Path\") strict; \ + drvPath = strict.drvPath; \ + type = \"derivation\"; \ + currentOutput = output; \ + } // outputsAttrs // { all = allList; }; \ + }; \ + outputsList = if attrs ? outputs then \ + map outputToAttrListElement attrs.outputs else \ + [ (outputToAttrListElement \"out\") ]; \ + outputsAttrs = builtins.listToAttrs outputsList; \ + allList = attrValues outputsAttrs; \ + head = if attrs ? outputs then builtins.head attrs.outputs else \"out\"; \ + in builtins.getAttr head outputsAttrs"; + mkThunk_(v, parseExprFromString(s, "/")); + addConstant("derivation", v); + /* Now that we've added all primops, sort the `builtins' attribute set, because attribute lookups expect it to be sorted. */ baseEnv.values[0]->attrs->sort(); diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index cf0e2ad1b..29817df9d 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -820,6 +820,28 @@ PathSet LocalStore::queryDerivationOutputs(const Path & path) } +StringSet LocalStore::queryDerivationOutputNames(const Path & path) +{ + SQLiteTxn txn(db); + + SQLiteStmtUse use(stmtQueryDerivationOutputs); + stmtQueryDerivationOutputs.bind(queryValidPathId(path)); + + StringSet outputNames; + int r; + while ((r = sqlite3_step(stmtQueryDerivationOutputs)) == SQLITE_ROW) { + const char * s = (const char *) sqlite3_column_text(stmtQueryDerivationOutputs, 0); + assert(s); + outputNames.insert(s); + } + + if (r != SQLITE_DONE) + throwSQLiteError(db, format("error getting output names of `%1%'") % path); + + return outputNames; +} + + void LocalStore::startSubstituter(const Path & substituter, RunningSubstituter & run) { if (run.pid != -1) return; diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index 4cb905f67..2739c4eea 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -118,6 +118,8 @@ public: PathSet queryValidDerivers(const Path & path); PathSet queryDerivationOutputs(const Path & path); + + StringSet queryDerivationOutputNames(const Path & path); PathSet querySubstitutablePaths(); diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index 942c5bcf1..6e9921ede 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -326,6 +326,16 @@ PathSet RemoteStore::queryDerivationOutputs(const Path & path) } +PathSet RemoteStore::queryDerivationOutputNames(const Path & path) +{ + openConnection(); + writeInt(wopQueryDerivationOutputNames, to); + writeString(path, to); + processStderr(); + return readStrings<PathSet>(from); +} + + Path RemoteStore::addToStore(const Path & _srcPath, bool recursive, HashType hashAlgo, PathFilter & filter) { diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh index 34a2d91df..c5853ef53 100644 --- a/src/libstore/remote-store.hh +++ b/src/libstore/remote-store.hh @@ -41,6 +41,8 @@ public: PathSet queryDerivationOutputs(const Path & path); + StringSet queryDerivationOutputNames(const Path & path); + bool hasSubstitutes(const Path & path); bool querySubstitutablePathInfo(const Path & path, diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index d4997c886..14890f522 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -140,6 +140,9 @@ public: /* Query the outputs of the derivation denoted by `path'. */ virtual PathSet queryDerivationOutputs(const Path & path) = 0; + + /* Query the output names of the derivation denoted by `path'. */ + virtual StringSet queryDerivationOutputNames(const Path & path) = 0; /* Query whether a path has substitutes. */ virtual bool hasSubstitutes(const Path & path) = 0; diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh index 760d08a74..ef1e0993d 100644 --- a/src/libstore/worker-protocol.hh +++ b/src/libstore/worker-protocol.hh @@ -39,6 +39,7 @@ typedef enum { wopClearFailedPaths = 25, wopQueryPathInfo = 26, wopImportPaths = 27, + wopQueryDerivationOutputNames = 28, } WorkerOp; diff --git a/src/nix-worker/nix-worker.cc b/src/nix-worker/nix-worker.cc index 5f57b2981..f28905a24 100644 --- a/src/nix-worker/nix-worker.cc +++ b/src/nix-worker/nix-worker.cc @@ -331,6 +331,16 @@ static void performOp(unsigned int clientVersion, break; } + case wopQueryDerivationOutputNames: { + Path path = readStorePath(from); + startWork(); + StringSet names; + names = store->queryDerivationOutputNames(path); + stopWork(); + writeStrings(names, to); + break; + } + case wopQueryDeriver: { Path path = readStorePath(from); startWork(); |