mirror of
https://github.com/NixOS/nix
synced 2025-06-27 08:31:16 +02:00
* Store user environment manifests as a Nix expression in
$out/manifest.nix rather than as an ATerm. (Hm, I thought I committed this two days ago...)
This commit is contained in:
parent
f3b8833a48
commit
fe2d869e04
11 changed files with 205 additions and 183 deletions
|
@ -1,5 +1,12 @@
|
|||
#include "util.hh"
|
||||
#include "get-drvs.hh"
|
||||
#include "derivations.hh"
|
||||
#include "store-api.hh"
|
||||
#include "globals.hh"
|
||||
#include "shared.hh"
|
||||
#include "eval.hh"
|
||||
#include "parser.hh"
|
||||
#include "profiles.hh"
|
||||
|
||||
|
||||
namespace nix {
|
||||
|
@ -11,18 +18,138 @@ static void readLegacyManifest(const Path & path, DrvInfos & elems);
|
|||
DrvInfos queryInstalled(EvalState & state, const Path & userEnv)
|
||||
{
|
||||
DrvInfos elems;
|
||||
|
||||
Path path = userEnv + "/manifest";
|
||||
|
||||
if (!pathExists(path))
|
||||
return DrvInfos(); /* not an error, assume nothing installed */
|
||||
Path manifestFile = userEnv + "/manifest.nix";
|
||||
Path oldManifestFile = userEnv + "/manifest";
|
||||
|
||||
readLegacyManifest(path, elems);
|
||||
if (pathExists(manifestFile)) {
|
||||
Value v;
|
||||
state.eval(parseExprFromFile(state, manifestFile), v);
|
||||
getDerivations(state, v, "", Bindings(), elems);
|
||||
} else if (pathExists(oldManifestFile))
|
||||
readLegacyManifest(oldManifestFile, elems);
|
||||
|
||||
return elems;
|
||||
}
|
||||
|
||||
|
||||
bool createUserEnv(EvalState & state, DrvInfos & elems,
|
||||
const Path & profile, bool keepDerivations,
|
||||
const string & lockToken)
|
||||
{
|
||||
/* Build the components in the user environment, if they don't
|
||||
exist already. */
|
||||
PathSet drvsToBuild;
|
||||
foreach (DrvInfos::const_iterator, i, elems)
|
||||
if (i->queryDrvPath(state) != "")
|
||||
drvsToBuild.insert(i->queryDrvPath(state));
|
||||
|
||||
debug(format("building user environment dependencies"));
|
||||
store->buildDerivations(drvsToBuild);
|
||||
|
||||
/* Construct the whole top level derivation. */
|
||||
PathSet references;
|
||||
Value manifest;
|
||||
state.mkList(manifest, elems.size());
|
||||
unsigned int n = 0;
|
||||
foreach (DrvInfos::iterator, i, elems) {
|
||||
/* 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) : "";
|
||||
|
||||
Value & v(*state.allocValues(1));
|
||||
manifest.list.elems[n++] = &v;
|
||||
state.mkAttrs(v);
|
||||
|
||||
mkString((*v.attrs)[state.sType], "derivation");
|
||||
mkString((*v.attrs)[state.sName], i->name);
|
||||
mkString((*v.attrs)[state.sSystem], i->system);
|
||||
mkString((*v.attrs)[state.sOutPath], i->queryOutPath(state));
|
||||
if (drvPath != "")
|
||||
mkString((*v.attrs)[state.sDrvPath], i->queryDrvPath(state));
|
||||
|
||||
state.mkAttrs((*v.attrs)[state.sMeta]);
|
||||
|
||||
MetaInfo meta = i->queryMetaInfo(state);
|
||||
|
||||
foreach (MetaInfo::const_iterator, j, meta) {
|
||||
Value & v2((*(*v.attrs)[state.sMeta].attrs)[state.symbols.create(j->first)]);
|
||||
switch (j->second.type) {
|
||||
case MetaValue::tpInt: mkInt(v2, j->second.intValue); break;
|
||||
case MetaValue::tpString: mkString(v2, j->second.stringValue); break;
|
||||
case MetaValue::tpStrings: {
|
||||
state.mkList(v2, j->second.stringValues.size());
|
||||
unsigned int m = 0;
|
||||
foreach (Strings::const_iterator, k, j->second.stringValues) {
|
||||
v2.list.elems[m] = state.allocValues(1);
|
||||
mkString(*v2.list.elems[m++], *k);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: abort();
|
||||
}
|
||||
}
|
||||
|
||||
/* This is only necessary when installing store paths, e.g.,
|
||||
`nix-env -i /nix/store/abcd...-foo'. */
|
||||
store->addTempRoot(i->queryOutPath(state));
|
||||
store->ensurePath(i->queryOutPath(state));
|
||||
|
||||
references.insert(i->queryOutPath(state));
|
||||
if (drvPath != "") references.insert(drvPath);
|
||||
}
|
||||
|
||||
/* Also write a copy of the list of user environment elements to
|
||||
the store; we need it for future modifications of the
|
||||
environment. */
|
||||
Path manifestFile = store->addTextToStore("env-manifest.nix",
|
||||
(format("%1%") % manifest).str(), references);
|
||||
|
||||
printMsg(lvlError, manifestFile);
|
||||
|
||||
/* Get the environment builder expression. */
|
||||
Value envBuilder;
|
||||
state.eval(parseExprFromFile(state, nixDataDir + "/nix/corepkgs/buildenv"), envBuilder);
|
||||
|
||||
/* Construct a Nix expression that calls the user environment
|
||||
builder with the manifest as argument. */
|
||||
Value args, topLevel;
|
||||
state.mkAttrs(args);
|
||||
mkString((*args.attrs)[state.sSystem], thisSystem);
|
||||
mkString((*args.attrs)[state.symbols.create("manifest")],
|
||||
manifestFile, singleton<PathSet>(manifestFile));
|
||||
(*args.attrs)[state.symbols.create("derivations")] = manifest;
|
||||
mkApp(topLevel, envBuilder, args);
|
||||
|
||||
/* Evaluate it. */
|
||||
debug("evaluating user environment builder");
|
||||
DrvInfo topLevelDrv;
|
||||
if (!getDerivation(state, topLevel, topLevelDrv))
|
||||
abort();
|
||||
|
||||
/* Realise the resulting store expression. */
|
||||
debug("building user environment");
|
||||
store->buildDerivations(singleton<PathSet>(topLevelDrv.queryDrvPath(state)));
|
||||
|
||||
/* Switch the current user environment to the output path. */
|
||||
PathLocks lock;
|
||||
lockProfile(lock, profile);
|
||||
|
||||
Path lockTokenCur = optimisticLockProfile(profile);
|
||||
if (lockToken != lockTokenCur) {
|
||||
printMsg(lvlError, format("profile `%1%' changed while we were busy; restarting") % profile);
|
||||
return false;
|
||||
}
|
||||
|
||||
debug(format("switching to new user environment"));
|
||||
Path generation = createGeneration(profile, topLevelDrv.queryOutPath(state));
|
||||
switchLink(profile, generation);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Code for parsing manifests in the old textual ATerm format. */
|
||||
|
||||
static string parseStr(std::istream & str)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue