aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libexpr/get-drvs.cc100
-rw-r--r--src/libexpr/get-drvs.hh3
-rw-r--r--src/nix-instantiate/main.cc15
3 files changed, 87 insertions, 31 deletions
diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc
index eaab867a6..fbcbb9014 100644
--- a/src/libexpr/get-drvs.cc
+++ b/src/libexpr/get-drvs.cc
@@ -53,49 +53,96 @@ bool getDerivation(EvalState & state, Expr e, DrvInfo & drv)
static void getDerivations(EvalState & state, Expr e,
- DrvInfos & drvs, Exprs & doneExprs)
+ DrvInfos & drvs, Exprs & doneExprs, const string & attrPath)
{
+ /* Automatically call functions that have defaults for all
+ arguments. */
+ ATermList formals;
+ ATerm body, pos;
+ if (matchFunction(e, formals, body, pos)) {
+ for (ATermIterator i(formals); i; ++i) {
+ Expr name, def;
+ if (matchNoDefFormal(*i, name))
+ throw Error(format("expression evaluates to a function with no-default arguments (`%1%')")
+ % aterm2String(name));
+ else if (!matchDefFormal(*i, name, def))
+ abort(); /* can't happen */
+ }
+ getDerivations(state,
+ makeCall(e, makeAttrs(ATermMap())),
+ drvs, doneExprs, attrPath);
+ return;
+ }
+
+ /* Parse the start of attrPath. */
+ enum { apNone, apAttr, apIndex } apType;
+ string attrPathRest;
+ string attr;
+ int attrIndex;
+ Error attrError =
+ Error(format("attribute selection path `%1%' does not match expression") % attrPath);
+
+ if (attrPath.empty())
+ apType = apNone;
+ else {
+ string::size_type dot = attrPath.find(".");
+ if (dot == string::npos) {
+ attrPathRest = "";
+ attr = attrPath;
+ } else {
+ attrPathRest = string(attrPath, dot + 1);
+ attr = string(attrPath, 0, dot);
+ }
+ apType = apAttr;
+ if (string2Int(attr, attrIndex)) apType = apIndex;
+ }
+
+ /* Process the expression. */
ATermList es;
DrvInfo drv;
e = evalExpr(state, e);
- if (getDerivation(state, e, drv)) {
- drvs.push_back(drv);
+ if (getDerivation(state, e, drvs, doneExprs)) {
+ if (apType != apNone) throw attrError;
return;
}
if (matchAttrs(e, es)) {
+ if (apType != apNone && apType != apAttr) throw attrError;
ATermMap drvMap;
queryAllAttrs(e, drvMap);
- for (ATermIterator i(drvMap.keys()); i; ++i) {
- debug(format("evaluating attribute `%1%'") % aterm2String(*i));
- getDerivation(state, drvMap.get(*i), drvs, doneExprs);
+ if (apType == apNone) {
+ for (ATermIterator i(drvMap.keys()); i; ++i) {
+ debug(format("evaluating attribute `%1%'") % aterm2String(*i));
+ getDerivation(state, drvMap.get(*i), drvs, doneExprs);
+ }
+ } else {
+ Expr e2 = drvMap.get(attr);
+ if (!e2) throw Error(format("attribute `%1%' in selection path not found") % attr);
+ debug(format("evaluating attribute `%1%'") % attr);
+ getDerivation(state, e2, drvs, doneExprs);
+ if (!attrPath.empty())
+ getDerivations(state, e2, drvs, doneExprs, attrPathRest);
}
return;
}
if (matchList(e, es)) {
- for (ATermIterator i(es); i; ++i) {
+ if (apType != apNone && apType != apIndex) throw attrError;
+ if (apType == apNone) {
+ for (ATermIterator i(es); i; ++i) {
+ debug(format("evaluating list element"));
+ if (!getDerivation(state, *i, drvs, doneExprs))
+ getDerivations(state, *i, drvs, doneExprs, attrPathRest);
+ }
+ } else {
+ Expr e2 = ATelementAt(es, attrIndex);
+ if (!e2) throw Error(format("list index %1% in selection path not found") % attrIndex);
debug(format("evaluating list element"));
- if (!getDerivation(state, *i, drvs, doneExprs))
- getDerivations(state, *i, drvs, doneExprs);
- }
- return;
- }
-
- ATermList formals;
- ATerm body, pos;
- if (matchFunction(e, formals, body, pos)) {
- for (ATermIterator i(formals); i; ++i) {
- Expr name, def;
- if (matchNoDefFormal(*i, name))
- throw Error(format("expression evaluates to a function with no-default arguments (`%1%')")
- % aterm2String(name));
- else if (!matchDefFormal(*i, name, def))
- abort(); /* can't happen */
+ if (!getDerivation(state, e2, drvs, doneExprs))
+ getDerivations(state, e2, drvs, doneExprs, attrPathRest);
}
- getDerivations(state, makeCall(e, makeAttrs(ATermMap())), drvs, doneExprs);
return;
}
@@ -103,8 +150,9 @@ static void getDerivations(EvalState & state, Expr e,
}
-void getDerivations(EvalState & state, Expr e, DrvInfos & drvs)
+void getDerivations(EvalState & state, Expr e, DrvInfos & drvs,
+ const string & attrPath)
{
Exprs doneExprs;
- getDerivations(state, e, drvs, doneExprs);
+ getDerivations(state, e, drvs, doneExprs, attrPath);
}
diff --git a/src/libexpr/get-drvs.hh b/src/libexpr/get-drvs.hh
index bfcff8cca..5b1c0e6d4 100644
--- a/src/libexpr/get-drvs.hh
+++ b/src/libexpr/get-drvs.hh
@@ -58,7 +58,8 @@ typedef list<DrvInfo> DrvInfos;
Otherwise, return false. */
bool getDerivation(EvalState & state, Expr e, DrvInfo & drv);
-void getDerivations(EvalState & state, Expr e, DrvInfos & drvs);
+void getDerivations(EvalState & state, Expr e, DrvInfos & drvs,
+ const string & attrPath = "");
#endif /* !__GET_DRVS_H */
diff --git a/src/nix-instantiate/main.cc b/src/nix-instantiate/main.cc
index 75d03f329..7668958fc 100644
--- a/src/nix-instantiate/main.cc
+++ b/src/nix-instantiate/main.cc
@@ -33,13 +33,14 @@ static int rootNr = 0;
static bool indirectRoot = false;
-static void printResult(EvalState & state, Expr e, bool evalOnly)
+static void printResult(EvalState & state, Expr e, bool evalOnly,
+ const string & attrPath)
{
if (evalOnly)
cout << format("%1%\n") % e;
else {
DrvInfos drvs;
- getDerivations(state, e, drvs);
+ getDerivations(state, e, drvs, attrPath);
for (DrvInfos::iterator i = drvs.begin(); i != drvs.end(); ++i) {
Path drvPath = i->queryDrvPath(state);
if (gcRoot == "")
@@ -61,6 +62,7 @@ void run(Strings args)
bool readStdin = false;
bool evalOnly = false;
bool parseOnly = false;
+ string attrPath;
for (Strings::iterator i = args.begin();
i != args.end(); )
@@ -82,6 +84,11 @@ void run(Strings args)
throw UsageError("`--add-root requires an argument");
gcRoot = absPath(*i++);
}
+ else if (arg == "--attr") {
+ if (i == args.end())
+ throw UsageError("`--attr requires an argument");
+ attrPath = *i++;
+ }
else if (arg == "--indirect")
indirectRoot = true;
else if (arg[0] == '-')
@@ -94,7 +101,7 @@ void run(Strings args)
if (readStdin) {
Expr e = evalStdin(state, parseOnly);
- printResult(state, e, evalOnly);
+ printResult(state, e, evalOnly, attrPath);
}
for (Strings::iterator i = files.begin();
@@ -104,7 +111,7 @@ void run(Strings args)
Expr e = parseOnly
? parseExprFromFile(state, path)
: evalFile(state, path);
- printResult(state, e, evalOnly);
+ printResult(state, e, evalOnly, attrPath);
}
printEvalStats(state);