forked from lix-project/lix
* Lazily compute the derivation and output paths of derivations. This
makes most query and installation operations much faster (e.g., `nix-env -qa' on the current Nixpkgs is about 10 times faster).
This commit is contained in:
parent
426593162e
commit
edd145d2fb
|
@ -51,11 +51,24 @@ struct UserEnvElem
|
||||||
{
|
{
|
||||||
string name;
|
string name;
|
||||||
string system;
|
string system;
|
||||||
Path drvPath;
|
|
||||||
Path outPath;
|
ATermMap attrs;
|
||||||
|
|
||||||
|
string queryDrvPath(EvalState & state) const
|
||||||
|
{
|
||||||
|
Expr a = attrs.get("drvPath");
|
||||||
|
return a ? evalPath(state, a) : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
string queryOutPath(EvalState & state) const
|
||||||
|
{
|
||||||
|
Expr a = attrs.get("outPath");
|
||||||
|
if (!a) throw Error("output path missing");
|
||||||
|
return evalPath(state, a);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef map<Path, UserEnvElem> UserEnvElems;
|
typedef map<unsigned int, UserEnvElem> UserEnvElems;
|
||||||
|
|
||||||
|
|
||||||
void printHelp()
|
void printHelp()
|
||||||
|
@ -69,30 +82,32 @@ static bool parseDerivation(EvalState & state, Expr e, UserEnvElem & elem)
|
||||||
ATermList es;
|
ATermList es;
|
||||||
e = evalExpr(state, e);
|
e = evalExpr(state, e);
|
||||||
if (!matchAttrs(e, es)) return false;
|
if (!matchAttrs(e, es)) return false;
|
||||||
Expr a = queryAttr(e, "type");
|
|
||||||
|
ATermMap attrs;
|
||||||
|
queryAllAttrs(e, attrs, false);
|
||||||
|
|
||||||
|
Expr a = attrs.get("type");
|
||||||
if (!a || evalString(state, a) != "derivation") return false;
|
if (!a || evalString(state, a) != "derivation") return false;
|
||||||
|
|
||||||
a = queryAttr(e, "name");
|
a = attrs.get("name");
|
||||||
if (!a) throw badTerm("derivation name missing", e);
|
if (!a) throw badTerm("derivation name missing", e);
|
||||||
elem.name = evalString(state, a);
|
elem.name = evalString(state, a);
|
||||||
|
|
||||||
a = queryAttr(e, "system");
|
a = attrs.get("system");
|
||||||
if (!a)
|
if (!a)
|
||||||
elem.system = "unknown";
|
elem.system = "unknown";
|
||||||
else
|
else
|
||||||
elem.system = evalString(state, a);
|
elem.system = evalString(state, a);
|
||||||
|
|
||||||
a = queryAttr(e, "drvPath");
|
elem.attrs = attrs;
|
||||||
if (a) elem.drvPath = evalPath(state, a);
|
|
||||||
|
|
||||||
a = queryAttr(e, "outPath");
|
|
||||||
if (!a) throw badTerm("output path missing", e);
|
|
||||||
elem.outPath = evalPath(state, a);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned int elemCounter = 0;
|
||||||
|
|
||||||
|
|
||||||
static void parseDerivations(EvalState & state, Expr e, UserEnvElems & elems)
|
static void parseDerivations(EvalState & state, Expr e, UserEnvElems & elems)
|
||||||
{
|
{
|
||||||
ATermList es;
|
ATermList es;
|
||||||
|
@ -101,15 +116,15 @@ static void parseDerivations(EvalState & state, Expr e, UserEnvElems & elems)
|
||||||
e = evalExpr(state, e);
|
e = evalExpr(state, e);
|
||||||
|
|
||||||
if (parseDerivation(state, e, elem))
|
if (parseDerivation(state, e, elem))
|
||||||
elems[elem.outPath] = elem;
|
elems[elemCounter++] = elem;
|
||||||
|
|
||||||
else if (matchAttrs(e, es)) {
|
else if (matchAttrs(e, es)) {
|
||||||
ATermMap drvMap;
|
ATermMap drvMap;
|
||||||
queryAllAttrs(e, drvMap);
|
queryAllAttrs(e, drvMap);
|
||||||
for (ATermIterator i(drvMap.keys()); i; ++i) {
|
for (ATermIterator i(drvMap.keys()); i; ++i) {
|
||||||
debug(format("evaluating attribute `%1%'") % *i);
|
debug(format("evaluating attribute `%1%'") % aterm2String(*i));
|
||||||
if (parseDerivation(state, drvMap.get(*i), elem))
|
if (parseDerivation(state, drvMap.get(*i), elem))
|
||||||
elems[elem.outPath] = elem;
|
elems[elemCounter++] = elem;
|
||||||
else
|
else
|
||||||
parseDerivations(state, drvMap.get(*i), elems);
|
parseDerivations(state, drvMap.get(*i), elems);
|
||||||
}
|
}
|
||||||
|
@ -119,7 +134,7 @@ static void parseDerivations(EvalState & state, Expr e, UserEnvElems & elems)
|
||||||
for (ATermIterator i(es); i; ++i) {
|
for (ATermIterator i(es); i; ++i) {
|
||||||
debug(format("evaluating list element"));
|
debug(format("evaluating list element"));
|
||||||
if (parseDerivation(state, *i, elem))
|
if (parseDerivation(state, *i, elem))
|
||||||
elems[elem.outPath] = elem;
|
elems[elemCounter++] = elem;
|
||||||
else
|
else
|
||||||
parseDerivations(state, *i, elems);
|
parseDerivations(state, *i, elems);
|
||||||
}
|
}
|
||||||
|
@ -200,8 +215,9 @@ static void createUserEnv(EvalState & state, const UserEnvElems & elems,
|
||||||
i != elems.end(); ++i)
|
i != elems.end(); ++i)
|
||||||
/* Call to `isDerivation' is for compatibility with Nix <= 0.7
|
/* Call to `isDerivation' is for compatibility with Nix <= 0.7
|
||||||
user environments. */
|
user environments. */
|
||||||
if (i->second.drvPath != "" && isDerivation(i->second.drvPath))
|
if (i->second.queryDrvPath(state) != "" &&
|
||||||
drvsToBuild.insert(i->second.drvPath);
|
isDerivation(i->second.queryDrvPath(state)))
|
||||||
|
drvsToBuild.insert(i->second.queryDrvPath(state));
|
||||||
|
|
||||||
debug(format("building user environment dependencies"));
|
debug(format("building user environment dependencies"));
|
||||||
buildDerivations(drvsToBuild);
|
buildDerivations(drvsToBuild);
|
||||||
|
@ -217,7 +233,7 @@ static void createUserEnv(EvalState & state, const UserEnvElems & elems,
|
||||||
for (UserEnvElems::const_iterator i = elems.begin();
|
for (UserEnvElems::const_iterator i = elems.begin();
|
||||||
i != elems.end(); ++i)
|
i != elems.end(); ++i)
|
||||||
{
|
{
|
||||||
Path drvPath = keepDerivations ? i->second.drvPath : "";
|
Path drvPath = keepDerivations ? i->second.queryDrvPath(state) : "";
|
||||||
ATerm t = makeAttrs(ATmakeList5(
|
ATerm t = makeAttrs(ATmakeList5(
|
||||||
makeBind(toATerm("type"),
|
makeBind(toATerm("type"),
|
||||||
makeStr(toATerm("derivation")), makeNoPos()),
|
makeStr(toATerm("derivation")), makeNoPos()),
|
||||||
|
@ -228,17 +244,17 @@ static void createUserEnv(EvalState & state, const UserEnvElems & elems,
|
||||||
makeBind(toATerm("drvPath"),
|
makeBind(toATerm("drvPath"),
|
||||||
makePath(toATerm(drvPath)), makeNoPos()),
|
makePath(toATerm(drvPath)), makeNoPos()),
|
||||||
makeBind(toATerm("outPath"),
|
makeBind(toATerm("outPath"),
|
||||||
makePath(toATerm(i->second.outPath)), makeNoPos())
|
makePath(toATerm(i->second.queryOutPath(state))), makeNoPos())
|
||||||
));
|
));
|
||||||
manifest = ATinsert(manifest, t);
|
manifest = ATinsert(manifest, t);
|
||||||
inputs = ATinsert(inputs, makeStr(toATerm(i->second.outPath)));
|
inputs = ATinsert(inputs, makeStr(toATerm(i->second.queryOutPath(state))));
|
||||||
|
|
||||||
/* This is only necessary when installing store paths, e.g.,
|
/* This is only necessary when installing store paths, e.g.,
|
||||||
`nix-env -i /nix/store/abcd...-foo'. */
|
`nix-env -i /nix/store/abcd...-foo'. */
|
||||||
addTempRoot(i->second.outPath);
|
addTempRoot(i->second.queryOutPath(state));
|
||||||
ensurePath(i->second.outPath);
|
ensurePath(i->second.queryOutPath(state));
|
||||||
|
|
||||||
references.insert(i->second.outPath);
|
references.insert(i->second.queryOutPath(state));
|
||||||
if (drvPath != "") references.insert(drvPath);
|
if (drvPath != "") references.insert(drvPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,11 +285,11 @@ static void createUserEnv(EvalState & state, const UserEnvElems & elems,
|
||||||
|
|
||||||
/* Realise the resulting store expression. */
|
/* Realise the resulting store expression. */
|
||||||
debug(format("building user environment"));
|
debug(format("building user environment"));
|
||||||
buildDerivations(singleton<PathSet>(topLevelDrv.drvPath));
|
buildDerivations(singleton<PathSet>(topLevelDrv.queryDrvPath(state)));
|
||||||
|
|
||||||
/* Switch the current user environment to the output path. */
|
/* Switch the current user environment to the output path. */
|
||||||
debug(format("switching to new user environment"));
|
debug(format("switching to new user environment"));
|
||||||
Path generation = createGeneration(profile, topLevelDrv.outPath);
|
Path generation = createGeneration(profile, topLevelDrv.queryOutPath(state));
|
||||||
switchLink(profile, generation);
|
switchLink(profile, generation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,17 +394,17 @@ static void queryInstSources(EvalState & state,
|
||||||
name = string(name, dash + 1);
|
name = string(name, dash + 1);
|
||||||
|
|
||||||
if (isDerivation(*i)) {
|
if (isDerivation(*i)) {
|
||||||
elem.drvPath = *i;
|
elem.queryDrvPath(state) = *i;
|
||||||
elem.outPath = findOutput(derivationFromPath(*i), "out");
|
elem.queryOutPath(state) = findOutput(derivationFromPath(*i), "out");
|
||||||
if (name.size() >= drvExtension.size() &&
|
if (name.size() >= drvExtension.size() &&
|
||||||
string(name, name.size() - drvExtension.size()) == drvExtension)
|
string(name, name.size() - drvExtension.size()) == drvExtension)
|
||||||
name = string(name, 0, name.size() - drvExtension.size());
|
name = string(name, 0, name.size() - drvExtension.size());
|
||||||
}
|
}
|
||||||
else elem.outPath = *i;
|
else elem.queryOutPath(state) = *i;
|
||||||
|
|
||||||
elem.name = name;
|
elem.name = name;
|
||||||
|
|
||||||
elems[elem.outPath] = elem;
|
elems[elemCounter++] = elem;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -511,7 +527,8 @@ static void upgradeDerivations(Globals & globals,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bestElem != availElems.end() &&
|
if (bestElem != availElems.end() &&
|
||||||
i->second.outPath != bestElem->second.outPath)
|
i->second.queryOutPath(globals.state) !=
|
||||||
|
bestElem->second.queryOutPath(globals.state))
|
||||||
{
|
{
|
||||||
printMsg(lvlInfo,
|
printMsg(lvlInfo,
|
||||||
format("upgrading `%1%' to `%2%'")
|
format("upgrading `%1%' to `%2%'")
|
||||||
|
@ -678,10 +695,15 @@ static void opQuery(Globals & globals,
|
||||||
|
|
||||||
/* We only need to know the installed paths when we are querying
|
/* We only need to know the installed paths when we are querying
|
||||||
the status of the derivation. */
|
the status of the derivation. */
|
||||||
UserEnvElems installed; /* installed paths */
|
PathSet installed; /* installed paths */
|
||||||
|
|
||||||
if (printStatus)
|
if (printStatus) {
|
||||||
installed = queryInstalled(globals.state, globals.profile);
|
UserEnvElems installedElems;
|
||||||
|
installedElems = queryInstalled(globals.state, globals.profile);
|
||||||
|
for (UserEnvElems::iterator i = installedElems.begin();
|
||||||
|
i != installedElems.end(); ++i)
|
||||||
|
installed.insert(i->second.queryOutPath(globals.state));
|
||||||
|
}
|
||||||
|
|
||||||
/* Print the desired columns. */
|
/* Print the desired columns. */
|
||||||
Table table;
|
Table table;
|
||||||
|
@ -692,11 +714,11 @@ static void opQuery(Globals & globals,
|
||||||
Strings columns;
|
Strings columns;
|
||||||
|
|
||||||
if (printStatus) {
|
if (printStatus) {
|
||||||
Substitutes subs = querySubstitutes(noTxn, i->drvPath);
|
Substitutes subs = querySubstitutes(noTxn, i->queryDrvPath(globals.state));
|
||||||
columns.push_back(
|
columns.push_back(
|
||||||
(string) (installed.find(i->outPath)
|
(string) (installed.find(i->queryOutPath(globals.state))
|
||||||
!= installed.end() ? "I" : "-")
|
!= installed.end() ? "I" : "-")
|
||||||
+ (isValidPath(i->outPath) ? "P" : "-")
|
+ (isValidPath(i->queryOutPath(globals.state)) ? "P" : "-")
|
||||||
+ (subs.size() > 0 ? "S" : "-"));
|
+ (subs.size() > 0 ? "S" : "-"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -704,10 +726,11 @@ static void opQuery(Globals & globals,
|
||||||
|
|
||||||
if (printSystem) columns.push_back(i->system);
|
if (printSystem) columns.push_back(i->system);
|
||||||
|
|
||||||
if (printDrvPath) columns.push_back(i->drvPath == "" ? "-" : i->drvPath);
|
if (printDrvPath) columns.push_back(
|
||||||
|
i->queryDrvPath(globals.state) == ""
|
||||||
if (printOutPath) columns.push_back(i->outPath);
|
? "-" : i->queryDrvPath(globals.state));
|
||||||
|
|
||||||
|
if (printOutPath) columns.push_back(i->queryOutPath(globals.state));
|
||||||
table.push_back(columns);
|
table.push_back(columns);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue