* nix-env now maintains meta info (from the `meta' derivation
attribute) about installed packages in user environments. Thus, an operation like `nix-env -q --description' shows useful information not only on available packages but also on installed packages. * nix-env now passes the entire manifest as an argument to the Nix expression of the user environment builder (not just a list of paths), so that in particular the user environment builder has access to the meta attributes. * New operation `--set-flag' in nix-env to change meta info of installed packages. This will be useful to pass per-package policies to the user environment builder (e.g., how to resolve collision or whether to disable a package (NIX-80)) or upgrade policies in nix-env (e.g., that a package should be "masked", that is, left untouched by upgrade actions). Example: $ nix-env --set-flag enabled false ghc-6.4
This commit is contained in:
		
							parent
							
								
									f52de527c7
								
							
						
					
					
						commit
						451dbf687f
					
				
					 6 changed files with 105 additions and 16 deletions
				
			
		|  | @ -14,6 +14,14 @@ | ||||||
| 
 | 
 | ||||||
|   <listitem><para>TODO: multi-user support.</para></listitem> |   <listitem><para>TODO: multi-user support.</para></listitem> | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  |   <listitem><para><command>nix-prefetch-url</command> now by default | ||||||
|  |   computes the SHA-256 hash of the file instead of the MD5 hash.  In | ||||||
|  |   calls to <function>fetchurl</function> you should pass an | ||||||
|  |   <literal>sha256</literal> attribute instead of | ||||||
|  |   <literal>md5</literal>.  You can pass either a hexadecimal or a | ||||||
|  |   base-32 encoding of the hash.</para></listitem> | ||||||
|  | 
 | ||||||
|    |    | ||||||
|   <listitem><para><command>nix-store</command> has a new operation |   <listitem><para><command>nix-store</command> has a new operation | ||||||
|   <option>--read-log</option> (<option>-l</option>) |   <option>--read-log</option> (<option>-l</option>) | ||||||
|  | @ -51,6 +59,14 @@ | ||||||
|    |    | ||||||
| 
 | 
 | ||||||
|   <listitem><para>TODO: <option>--argstr</option>.</para></listitem> |   <listitem><para>TODO: <option>--argstr</option>.</para></listitem> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   <listitem><para>TODO: <command>nix-env</command> now maintains meta | ||||||
|  |   info about installed packages in user | ||||||
|  |   environments.</para></listitem> | ||||||
|  | 
 | ||||||
|  |   <listitem><para>TODO: <command>nix-env</command> | ||||||
|  |   <option>--set-flag</option>.</para></listitem> | ||||||
|    |    | ||||||
| 
 | 
 | ||||||
|   <listitem><para>TODO: new built-ins |   <listitem><para>TODO: new built-ins | ||||||
|  |  | ||||||
|  | @ -60,6 +60,16 @@ MetaInfo DrvInfo::queryMetaInfo(EvalState & state) const | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | void DrvInfo::setMetaInfo(const MetaInfo & meta) | ||||||
|  | { | ||||||
|  |     ATermMap metaAttrs; | ||||||
|  |     for (MetaInfo::const_iterator i = meta.begin(); i != meta.end(); ++i) | ||||||
|  |         metaAttrs.set(toATerm(i->first), | ||||||
|  |             makeAttrRHS(makeStr(i->second), makeNoPos())); | ||||||
|  |     attrs->set(toATerm("meta"), makeAttrs(metaAttrs)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| /* Cache for already evaluated derivations.  Usually putting ATerms in
 | /* Cache for already evaluated derivations.  Usually putting ATerms in
 | ||||||
|    a STL container is unsafe (they're not scanning for GC roots), but |    a STL container is unsafe (they're not scanning for GC roots), but | ||||||
|    here it doesn't matter; everything in this set is reachable from |    here it doesn't matter; everything in this set is reachable from | ||||||
|  |  | ||||||
|  | @ -26,6 +26,9 @@ public: | ||||||
|     string attrPath; /* path towards the derivation */ |     string attrPath; /* path towards the derivation */ | ||||||
|     string system; |     string system; | ||||||
| 
 | 
 | ||||||
|  |     /* !!! these should really be hidden, and setMetaInfo() should
 | ||||||
|  |        make a copy since the ATermMap can be shared between multiple | ||||||
|  |        DrvInfos. */ | ||||||
|     boost::shared_ptr<ATermMap> attrs; |     boost::shared_ptr<ATermMap> attrs; | ||||||
| 
 | 
 | ||||||
|     string queryDrvPath(EvalState & state) const; |     string queryDrvPath(EvalState & state) const; | ||||||
|  | @ -41,6 +44,8 @@ public: | ||||||
|     { |     { | ||||||
|         outPath = s; |         outPath = s; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     void setMetaInfo(const MetaInfo & meta); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -319,7 +319,7 @@ struct Canonicalise : TermFun | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| Expr canonicaliseExpr(Expr & e) | Expr canonicaliseExpr(Expr e) | ||||||
| { | { | ||||||
|     Canonicalise canonicalise; |     Canonicalise canonicalise; | ||||||
|     return bottomupRewrite(canonicalise, e); |     return bottomupRewrite(canonicalise, e); | ||||||
|  |  | ||||||
|  | @ -96,7 +96,7 @@ void checkVarDefs(const ATermMap & def, Expr e); | ||||||
| 
 | 
 | ||||||
| /* Canonicalise a Nix expression by sorting attributes and removing
 | /* Canonicalise a Nix expression by sorting attributes and removing
 | ||||||
|    location information. */ |    location information. */ | ||||||
| Expr canonicaliseExpr(Expr & e); | Expr canonicaliseExpr(Expr e); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Create an expression representing a boolean. */ | /* Create an expression representing a boolean. */ | ||||||
|  |  | ||||||
|  | @ -164,7 +164,11 @@ static void createUserEnv(EvalState & state, const DrvInfos & elems, | ||||||
|     for (DrvInfos::const_iterator i = elems.begin();  |     for (DrvInfos::const_iterator i = elems.begin();  | ||||||
|          i != elems.end(); ++i) |          i != elems.end(); ++i) | ||||||
|     { |     { | ||||||
|  |         /* Create a pseudo-derivation containing the name, system,
 | ||||||
|  |            output path, and optionally the derivation path, as well as | ||||||
|  |            the meta attributes. */ | ||||||
|         Path drvPath = keepDerivations ? i->queryDrvPath(state) : ""; |         Path drvPath = keepDerivations ? i->queryDrvPath(state) : ""; | ||||||
|  |          | ||||||
|         ATermList as = ATmakeList4( |         ATermList as = ATmakeList4( | ||||||
|             makeBind(toATerm("type"), |             makeBind(toATerm("type"), | ||||||
|                 makeStr("derivation"), makeNoPos()), |                 makeStr("derivation"), makeNoPos()), | ||||||
|  | @ -174,10 +178,18 @@ static void createUserEnv(EvalState & state, const DrvInfos & elems, | ||||||
|                 makeStr(i->system), makeNoPos()), |                 makeStr(i->system), makeNoPos()), | ||||||
|             makeBind(toATerm("outPath"), |             makeBind(toATerm("outPath"), | ||||||
|                 makeStr(i->queryOutPath(state)), makeNoPos())); |                 makeStr(i->queryOutPath(state)), makeNoPos())); | ||||||
|  |          | ||||||
|         if (drvPath != "") as = ATinsert(as,  |         if (drvPath != "") as = ATinsert(as,  | ||||||
|             makeBind(toATerm("drvPath"), |             makeBind(toATerm("drvPath"), | ||||||
|                 makeStr(drvPath), makeNoPos())); |                 makeStr(drvPath), makeNoPos())); | ||||||
|  |          | ||||||
|  |         if (i->attrs->get(toATerm("meta"))) as = ATinsert(as,  | ||||||
|  |             makeBind(toATerm("meta"), | ||||||
|  |                 strictEvalExpr(state, i->attrs->get(toATerm("meta"))), | ||||||
|  |                 makeNoPos())); | ||||||
|  | 
 | ||||||
|         manifest = ATinsert(manifest, makeAttrs(as)); |         manifest = ATinsert(manifest, makeAttrs(as)); | ||||||
|  |          | ||||||
|         inputs = ATinsert(inputs, makeStr(i->queryOutPath(state))); |         inputs = ATinsert(inputs, makeStr(i->queryOutPath(state))); | ||||||
| 
 | 
 | ||||||
|         /* This is only necessary when installing store paths, e.g.,
 |         /* This is only necessary when installing store paths, e.g.,
 | ||||||
|  | @ -192,13 +204,13 @@ static void createUserEnv(EvalState & state, const DrvInfos & elems, | ||||||
|     /* Also write a copy of the list of inputs to the store; we need
 |     /* Also write a copy of the list of inputs to the store; we need
 | ||||||
|        it for future modifications of the environment. */ |        it for future modifications of the environment. */ | ||||||
|     Path manifestFile = store->addTextToStore("env-manifest", |     Path manifestFile = store->addTextToStore("env-manifest", | ||||||
|         atPrint(makeList(ATreverse(manifest))), references); |         atPrint(canonicaliseExpr(makeList(ATreverse(manifest)))), references); | ||||||
| 
 | 
 | ||||||
|     Expr topLevel = makeCall(envBuilder, makeAttrs(ATmakeList3( |     Expr topLevel = makeCall(envBuilder, makeAttrs(ATmakeList3( | ||||||
|         makeBind(toATerm("system"), |         makeBind(toATerm("system"), | ||||||
|             makeStr(thisSystem), makeNoPos()), |             makeStr(thisSystem), makeNoPos()), | ||||||
|         makeBind(toATerm("derivations"), |         makeBind(toATerm("derivations"), | ||||||
|             makeList(ATreverse(inputs)), makeNoPos()), |             makeList(ATreverse(manifest)), makeNoPos()), | ||||||
|         makeBind(toATerm("manifest"), |         makeBind(toATerm("manifest"), | ||||||
|             makeStr(manifestFile, singleton<PathSet>(manifestFile)), makeNoPos()) |             makeStr(manifestFile, singleton<PathSet>(manifestFile)), makeNoPos()) | ||||||
|         ))); |         ))); | ||||||
|  | @ -506,8 +518,7 @@ typedef enum { utLt, utLeq, utEq, utAlways } UpgradeType; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static void upgradeDerivations(Globals & globals, | static void upgradeDerivations(Globals & globals, | ||||||
|     const Strings & args, const Path & profile, |     const Strings & args, UpgradeType upgradeType) | ||||||
|     UpgradeType upgradeType) |  | ||||||
| { | { | ||||||
|     debug(format("upgrading derivations")); |     debug(format("upgrading derivations")); | ||||||
| 
 | 
 | ||||||
|  | @ -518,8 +529,8 @@ static void upgradeDerivations(Globals & globals, | ||||||
| 
 | 
 | ||||||
|     /* Load the currently installed derivations. */ |     /* Load the currently installed derivations. */ | ||||||
|     PathLocks lock; |     PathLocks lock; | ||||||
|     lockProfile(lock, profile); |     lockProfile(lock, globals.profile); | ||||||
|     DrvInfos installedElems = queryInstalled(globals.state, profile); |     DrvInfos installedElems = queryInstalled(globals.state, globals.profile); | ||||||
| 
 | 
 | ||||||
|     /* Fetch all derivations from the input file. */ |     /* Fetch all derivations from the input file. */ | ||||||
|     DrvInfos availElems; |     DrvInfos availElems; | ||||||
|  | @ -577,7 +588,7 @@ static void upgradeDerivations(Globals & globals, | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     createUserEnv(globals.state, newElems, |     createUserEnv(globals.state, newElems, | ||||||
|         profile, globals.keepDerivations); |         globals.profile, globals.keepDerivations); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -593,7 +604,55 @@ static void opUpgrade(Globals & globals, | ||||||
|         else if (*i == "--always") upgradeType = utAlways; |         else if (*i == "--always") upgradeType = utAlways; | ||||||
|         else throw UsageError(format("unknown flag `%1%'") % *i); |         else throw UsageError(format("unknown flag `%1%'") % *i); | ||||||
| 
 | 
 | ||||||
|     upgradeDerivations(globals, opArgs, globals.profile, upgradeType); |     upgradeDerivations(globals, opArgs, upgradeType); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static void setMetaFlag(EvalState & state, DrvInfo & drv, | ||||||
|  |     const string & name, const string & value) | ||||||
|  | { | ||||||
|  |     MetaInfo meta = drv.queryMetaInfo(state); | ||||||
|  |     meta[name] = value; | ||||||
|  |     drv.setMetaInfo(meta); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static void opSetFlag(Globals & globals, | ||||||
|  |     Strings opFlags, Strings opArgs) | ||||||
|  | { | ||||||
|  |     if (opFlags.size() > 0) | ||||||
|  |         throw UsageError(format("unknown flag `%1%'") % opFlags.front()); | ||||||
|  |     if (opArgs.size() < 2) | ||||||
|  |         throw UsageError("not enough arguments to `--set-flag'"); | ||||||
|  | 
 | ||||||
|  |     Strings::iterator arg = opArgs.begin(); | ||||||
|  |     string flagName = *arg++; | ||||||
|  |     string flagValue = *arg++; | ||||||
|  |     DrvNames selectors = drvNamesFromArgs(Strings(arg, opArgs.end())); | ||||||
|  | 
 | ||||||
|  |     /* Load the currently installed derivations. */ | ||||||
|  |     PathLocks lock; | ||||||
|  |     lockProfile(lock, globals.profile); | ||||||
|  |     DrvInfos installedElems = queryInstalled(globals.state, globals.profile); | ||||||
|  | 
 | ||||||
|  |     /* Update all matching derivations. */ | ||||||
|  |     for (DrvInfos::iterator i = installedElems.begin(); | ||||||
|  |          i != installedElems.end(); ++i) | ||||||
|  |     { | ||||||
|  |         DrvName drvName(i->name); | ||||||
|  |         for (DrvNames::iterator j = selectors.begin(); | ||||||
|  |              j != selectors.end(); ++j) | ||||||
|  |             if (j->matches(drvName)) { | ||||||
|  |                 printMsg(lvlInfo, | ||||||
|  |                     format("setting flag on `%1%'") % i->name); | ||||||
|  |                 setMetaFlag(globals.state, *i, flagName, flagValue); | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* Write the new user environment. */ | ||||||
|  |     createUserEnv(globals.state, installedElems, | ||||||
|  |         globals.profile, globals.keepDerivations); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -1167,18 +1226,18 @@ void run(Strings args) | ||||||
|             op = opUninstall; |             op = opUninstall; | ||||||
|         else if (arg == "--upgrade" || arg == "-u") |         else if (arg == "--upgrade" || arg == "-u") | ||||||
|             op = opUpgrade; |             op = opUpgrade; | ||||||
|  |         else if (arg == "--set-flag") | ||||||
|  |             op = opSetFlag; | ||||||
|         else if (arg == "--set") |         else if (arg == "--set") | ||||||
|             op = opSet; |             op = opSet; | ||||||
|         else if (arg == "--query" || arg == "-q") |         else if (arg == "--query" || arg == "-q") | ||||||
|             op = opQuery; |             op = opQuery; | ||||||
|         else if (arg == "--import" || arg == "-I") /* !!! bad name */ |         else if (arg == "--import" || arg == "-I") /* !!! bad name */ | ||||||
|             op = opDefaultExpr; |             op = opDefaultExpr; | ||||||
|         else if (arg == "--profile" || arg == "-p") { |         else if (arg == "--profile" || arg == "-p") | ||||||
|             globals.profile = absPath(needArg(i, args, arg)); |             globals.profile = absPath(needArg(i, args, arg)); | ||||||
|         } |         else if (arg == "--file" || arg == "-f") | ||||||
|         else if (arg == "--file" || arg == "-f") { |  | ||||||
|             globals.instSource.nixExprPath = absPath(needArg(i, args, arg)); |             globals.instSource.nixExprPath = absPath(needArg(i, args, arg)); | ||||||
|         } |  | ||||||
|         else if (arg == "--switch-profile" || arg == "-S") |         else if (arg == "--switch-profile" || arg == "-S") | ||||||
|             op = opSwitchProfile; |             op = opSwitchProfile; | ||||||
|         else if (arg == "--switch-generation" || arg == "-G") |         else if (arg == "--switch-generation" || arg == "-G") | ||||||
|  | @ -1195,9 +1254,8 @@ void run(Strings args) | ||||||
|         } |         } | ||||||
|         else if (arg == "--preserve-installed" || arg == "-P") |         else if (arg == "--preserve-installed" || arg == "-P") | ||||||
|             globals.preserveInstalled = true; |             globals.preserveInstalled = true; | ||||||
|         else if (arg == "--system-filter") { |         else if (arg == "--system-filter") | ||||||
|             globals.instSource.systemFilter = needArg(i, args, arg); |             globals.instSource.systemFilter = needArg(i, args, arg); | ||||||
|         } |  | ||||||
|         else if (arg[0] == '-') |         else if (arg[0] == '-') | ||||||
|             opFlags.push_back(arg); |             opFlags.push_back(arg); | ||||||
|         else |         else | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue