1
0
Fork 0
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:
Eelco Dolstra 2010-04-21 15:08:58 +00:00
parent f3b8833a48
commit fe2d869e04
11 changed files with 205 additions and 183 deletions

View file

@ -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)