* 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:
parent
b505f9eaf5
commit
c6120352b3
3 changed files with 94 additions and 38 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue