aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libexpr/primops.cc67
-rw-r--r--src/libstore/local-store.cc22
-rw-r--r--src/libstore/local-store.hh2
-rw-r--r--src/libstore/remote-store.cc10
-rw-r--r--src/libstore/remote-store.hh2
-rw-r--r--src/libstore/store-api.hh3
-rw-r--r--src/libstore/worker-protocol.hh1
-rw-r--r--src/nix-worker/nix-worker.cc10
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();