* 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
					
				
					 1 changed files with 63 additions and 40 deletions
				
			
		| 
						 | 
					@ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue