* In nix-instantiate, allow us to specify a "path" to the

derivation(s) we're interested, e.g.,

    $ nix-instantiate ./all-packages.nix --attr xlibs.libX11

  List elements can also be selected:

    $ nix-instantiate ./build-for-release.nix --attr 0.subversion

  This allows a non-ambiguous specification of a derivation.  Of
  course, this should also be added to nix-env and nix-build.
This commit is contained in:
Eelco Dolstra 2006-02-10 17:25:59 +00:00
parent b505f9eaf5
commit c6120352b3
3 changed files with 94 additions and 38 deletions

View File

@ -53,37 +53,10 @@ 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)
{
ATermList es;
DrvInfo drv;
e = evalExpr(state, e);
if (getDerivation(state, e, drv)) {
drvs.push_back(drv);
return;
}
if (matchAttrs(e, es)) {
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);
}
return;
}
if (matchList(e, es)) {
for (ATermIterator i(es); i; ++i) {
debug(format("evaluating list element"));
if (!getDerivation(state, *i, drvs, doneExprs))
getDerivations(state, *i, drvs, doneExprs);
}
return;
}
/* Automatically call functions that have defaults for all
arguments. */
ATermList formals;
ATerm body, pos;
if (matchFunction(e, formals, body, pos)) {
@ -95,7 +68,81 @@ static void getDerivations(EvalState & state, Expr e,
else if (!matchDefFormal(*i, name, def))
abort(); /* can't happen */
}
getDerivations(state, makeCall(e, makeAttrs(ATermMap())), drvs, doneExprs);
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, drvs, doneExprs)) {
if (apType != apNone) throw attrError;
return;
}
if (matchAttrs(e, es)) {
if (apType != apNone && apType != apAttr) throw attrError;
ATermMap drvMap;
queryAllAttrs(e, drvMap);
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)) {
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, e2, drvs, doneExprs))
getDerivations(state, e2, drvs, doneExprs, attrPathRest);
}
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);
}

View File

@ -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 */

View File

@ -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);