aboutsummaryrefslogtreecommitdiff
path: root/src/nix-env
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2010-05-12 22:13:09 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2010-05-12 22:13:09 +0000
commitaa45027818af8976dc73e6a299d5d918e5c51df1 (patch)
tree6086eb0642bc90477397169d0ee3993c1789200e /src/nix-env
parenta0e3b84fac56cad6377ecd1462058a6b29bb1ea8 (diff)
parent8032f26ca0bd2233de066ce5786ff976bbd641ae (diff)
* Sync with the trunk.
Diffstat (limited to 'src/nix-env')
-rw-r--r--src/nix-env/Makefile.am4
-rw-r--r--src/nix-env/nix-env.cc228
-rw-r--r--src/nix-env/profiles.cc16
-rw-r--r--src/nix-env/profiles.hh15
-rw-r--r--src/nix-env/user-env.cc257
-rw-r--r--src/nix-env/user-env.hh20
6 files changed, 340 insertions, 200 deletions
diff --git a/src/nix-env/Makefile.am b/src/nix-env/Makefile.am
index 53fea3d9d..113baabc4 100644
--- a/src/nix-env/Makefile.am
+++ b/src/nix-env/Makefile.am
@@ -1,6 +1,7 @@
bin_PROGRAMS = nix-env
-nix_env_SOURCES = nix-env.cc profiles.cc profiles.hh help.txt
+nix_env_SOURCES = nix-env.cc profiles.cc profiles.hh user-env.cc user-env.hh help.txt
+
nix_env_LDADD = ../libmain/libmain.la ../libexpr/libexpr.la \
../libstore/libstore.la ../libutil/libutil.la \
../boost/format/libformat.la
@@ -11,7 +12,6 @@ nix-env.o: help.txt.hh
../bin2c/bin2c helpText < $< > $@ || (rm $@ && exit 1)
AM_CXXFLAGS = \
- ${aterm_include} \
-I$(srcdir)/.. \
-I$(srcdir)/../libutil -I$(srcdir)/../libstore \
-I$(srcdir)/../libexpr -I$(srcdir)/../libmain -I../libexpr
diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc
index d3f74c7ed..ca67119e9 100644
--- a/src/nix-env/nix-env.cc
+++ b/src/nix-env/nix-env.cc
@@ -6,15 +6,13 @@
#include "parser.hh"
#include "eval.hh"
#include "help.txt.hh"
-#include "nixexpr-ast.hh"
#include "get-drvs.hh"
#include "attr-path.hh"
-#include "pathlocks.hh"
#include "common-opts.hh"
#include "xml-writer.hh"
#include "store-api.hh"
+#include "user-env.hh"
#include "util.hh"
-#include "aterm.hh"
#include <cerrno>
#include <ctime>
@@ -48,7 +46,7 @@ struct InstallSourceInfo
Path profile; /* for srcProfile */
string systemFilter; /* for srcNixExprDrvs */
bool prebuiltOnly;
- ATermMap autoArgs;
+ Bindings autoArgs;
InstallSourceInfo() : prebuiltOnly(false) { };
};
@@ -113,7 +111,7 @@ static bool isNixExpr(const Path & path)
static void getAllExprs(EvalState & state,
- const Path & path, ATermMap & attrs)
+ const Path & path, ExprAttrs & attrs)
{
Strings names = readDirectory(path);
StringSet namesSorted(names.begin(), names.end());
@@ -133,8 +131,8 @@ static void getAllExprs(EvalState & state,
string attrName = *i;
if (hasSuffix(attrName, ".nix"))
attrName = string(attrName, 0, attrName.size() - 4);
- attrs.set(toATerm(attrName), makeAttrRHS(
- parseExprFromFile(state, absPath(path2)), makeNoPos()));
+ attrs.attrs[state.symbols.create(attrName)] =
+ ExprAttrs::Attr(parseExprFromFile(state, absPath(path2)), noPos);
}
else
/* `path2' is a directory (with no default.nix in it);
@@ -144,7 +142,7 @@ static void getAllExprs(EvalState & state,
}
-static Expr loadSourceExpr(EvalState & state, const Path & path)
+static Expr * loadSourceExpr(EvalState & state, const Path & path)
{
if (isNixExpr(path)) return parseExprFromFile(state, absPath(path));
@@ -154,20 +152,22 @@ static Expr loadSourceExpr(EvalState & state, const Path & path)
(but keep the attribute set flat, not nested, to make it easier
for a user to have a ~/.nix-defexpr directory that includes
some system-wide directory). */
- ATermMap attrs;
- attrs.set(toATerm("_combineChannels"), makeAttrRHS(makeList(ATempty), makeNoPos()));
- getAllExprs(state, path, attrs);
- return makeAttrs(attrs);
+ ExprAttrs * attrs = new ExprAttrs;
+ attrs->attrs[state.symbols.create("_combineChannels")] =
+ ExprAttrs::Attr(new ExprList(), noPos);
+ getAllExprs(state, path, *attrs);
+ return attrs;
}
static void loadDerivations(EvalState & state, Path nixExprPath,
- string systemFilter, const ATermMap & autoArgs,
+ string systemFilter, const Bindings & autoArgs,
const string & pathPrefix, DrvInfos & elems)
{
- getDerivations(state,
- findAlongAttrPath(state, pathPrefix, autoArgs, loadSourceExpr(state, nixExprPath)),
- pathPrefix, autoArgs, elems);
+ Value v;
+ findAlongAttrPath(state, pathPrefix, autoArgs, loadSourceExpr(state, nixExprPath), v);
+
+ getDerivations(state, v, pathPrefix, autoArgs, elems);
/* Filter out all derivations not applicable to the current
system. */
@@ -193,172 +193,6 @@ static Path getDefNixExprPath()
}
-struct AddPos : TermFun
-{
- ATerm operator () (ATerm e)
- {
- ATerm x, y;
- if (matchObsoleteBind(e, x, y))
- return makeBind(x, y, makeNoPos());
- if (matchObsoleteStr(e, x))
- return makeStr(x, ATempty);
- return e;
- }
-};
-
-
-static DrvInfos queryInstalled(EvalState & state, const Path & userEnv)
-{
- Path path = userEnv + "/manifest";
-
- if (!pathExists(path))
- return DrvInfos(); /* not an error, assume nothing installed */
-
- Expr e = ATreadFromNamedFile(path.c_str());
- if (!e) throw Error(format("cannot read Nix expression from `%1%'") % path);
-
- /* Compatibility: Bind(x, y) -> Bind(x, y, NoPos). */
- AddPos addPos;
- e = bottomupRewrite(addPos, e);
-
- DrvInfos elems;
- getDerivations(state, e, "", ATermMap(1), elems);
- return elems;
-}
-
-
-/* Ensure exclusive access to a profile. Any command that modifies
- the profile first acquires this lock. */
-static void lockProfile(PathLocks & lock, const Path & profile)
-{
- lock.lockPaths(singleton<PathSet>(profile),
- (format("waiting for lock on profile `%1%'") % profile).str());
- lock.setDeletion(true);
-}
-
-
-/* Optimistic locking is used by long-running operations like `nix-env
- -i'. Instead of acquiring the exclusive lock for the entire
- duration of the operation, we just perform the operation
- optimistically (without an exclusive lock), and check at the end
- whether the profile changed while we were busy (i.e., the symlink
- target changed). If so, the operation is restarted. Restarting is
- generally cheap, since the build results are still in the Nix
- store. Most of the time, only the user environment has to be
- rebuilt. */
-static string optimisticLockProfile(const Path & profile)
-{
- return pathExists(profile) ? readLink(profile) : "";
-}
-
-
-static 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)
- /* Call to `isDerivation' is for compatibility with Nix <= 0.7
- user environments. */
- if (i->queryDrvPath(state) != "" &&
- isDerivation(i->queryDrvPath(state)))
- drvsToBuild.insert(i->queryDrvPath(state));
-
- debug(format("building user environment dependencies"));
- store->buildDerivations(drvsToBuild);
-
- /* Get the environment builder expression. */
- Expr envBuilder = parseExprFromFile(state,
- nixDataDir + "/nix/corepkgs/buildenv"); /* !!! */
-
- /* Construct the whole top level derivation. */
- PathSet references;
- ATermList manifest = ATempty;
- ATermList inputs = ATempty;
- 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) : "";
-
- /* Round trip to get rid of "bad" meta values (like
- functions). */
- MetaInfo meta = i->queryMetaInfo(state);
- i->setMetaInfo(meta);
-
- ATermList as = ATmakeList5(
- makeBind(toATerm("type"),
- makeStr("derivation"), makeNoPos()),
- makeBind(toATerm("name"),
- makeStr(i->name), makeNoPos()),
- makeBind(toATerm("system"),
- makeStr(i->system), makeNoPos()),
- makeBind(toATerm("outPath"),
- makeStr(i->queryOutPath(state)), makeNoPos()),
- makeBind(toATerm("meta"),
- i->attrs->get(toATerm("meta")), makeNoPos()));
-
- if (drvPath != "") as = ATinsert(as,
- makeBind(toATerm("drvPath"),
- makeStr(drvPath), makeNoPos()));
-
- manifest = ATinsert(manifest, makeAttrs(as));
-
- inputs = ATinsert(inputs, makeStr(i->queryOutPath(state)));
-
- /* 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 inputs to the store; we need
- it for future modifications of the environment. */
- Path manifestFile = store->addTextToStore("env-manifest",
- atPrint(canonicaliseExpr(makeList(ATreverse(manifest)))), references);
-
- Expr topLevel = makeCall(envBuilder, makeAttrs(ATmakeList3(
- makeBind(toATerm("system"),
- makeStr(thisSystem), makeNoPos()),
- makeBind(toATerm("derivations"),
- makeList(ATreverse(manifest)), makeNoPos()),
- makeBind(toATerm("manifest"),
- makeStr(manifestFile, singleton<PathSet>(manifestFile)), makeNoPos())
- )));
-
- /* Instantiate it. */
- debug(format("evaluating builder expression `%1%'") % topLevel);
- DrvInfo topLevelDrv;
- if (!getDerivation(state, topLevel, topLevelDrv))
- abort();
-
- /* Realise the resulting store expression. */
- debug(format("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;
-}
-
-
static int getPriority(EvalState & state, const DrvInfo & drv)
{
MetaValue value = drv.queryMetaInfo(state, "priority");
@@ -517,14 +351,13 @@ static void queryInstSources(EvalState & state,
(import ./foo.nix)' = `(import ./foo.nix).bar'. */
case srcNixExprs: {
- Expr e1 = loadSourceExpr(state, instSource.nixExprPath);
+ Expr * e1 = loadSourceExpr(state, instSource.nixExprPath);
- for (Strings::const_iterator i = args.begin();
- i != args.end(); ++i)
- {
- Expr e2 = parseExprFromString(state, *i, absPath("."));
- Expr call = makeCall(e2, e1);
- getDerivations(state, call, "", instSource.autoArgs, elems);
+ foreach (Strings::const_iterator, i, args) {
+ Expr * e2 = parseExprFromString(state, *i, absPath("."));
+ Expr * call = new ExprApp(e2, e1);
+ Value v; state.eval(call, v);
+ getDerivations(state, v, "", instSource.autoArgs, elems);
}
break;
@@ -541,7 +374,7 @@ static void queryInstSources(EvalState & state,
Path path = followLinksToStorePath(*i);
DrvInfo elem;
- elem.attrs = boost::shared_ptr<ATermMap>(new ATermMap(0)); /* ugh... */
+ elem.attrs = new Bindings;
string name = baseNameOf(path);
string::size_type dash = name.find('-');
if (dash != string::npos)
@@ -575,12 +408,12 @@ static void queryInstSources(EvalState & state,
}
case srcAttrPath: {
- for (Strings::const_iterator i = args.begin();
- i != args.end(); ++i)
- getDerivations(state,
- findAlongAttrPath(state, *i, instSource.autoArgs,
- loadSourceExpr(state, instSource.nixExprPath)),
- "", instSource.autoArgs, elems);
+ foreach (Strings::const_iterator, i, args) {
+ Value v;
+ findAlongAttrPath(state, *i, instSource.autoArgs,
+ loadSourceExpr(state, instSource.nixExprPath), v);
+ getDerivations(state, v, "", instSource.autoArgs, elems);
+ }
break;
}
}
@@ -1103,6 +936,7 @@ static void opQuery(Globals & globals,
foreach (vector<DrvInfo>::iterator, i, elems2) {
try {
+ startNest(nest, lvlDebug, format("outputting query result `%1%'") % i->attrPath);
/* For table output. */
Strings columns;
@@ -1473,7 +1307,7 @@ void run(Strings args)
op(globals, remaining, opFlags, opArgs);
- printEvalStats(globals.state);
+ globals.state.printStats();
}
diff --git a/src/nix-env/profiles.cc b/src/nix-env/profiles.cc
index 75585b1b2..60576f1ae 100644
--- a/src/nix-env/profiles.cc
+++ b/src/nix-env/profiles.cc
@@ -130,6 +130,20 @@ void switchLink(Path link, Path target)
throw SysError(format("renaming `%1%' to `%2%'") % tmp % link);
}
-
+
+void lockProfile(PathLocks & lock, const Path & profile)
+{
+ lock.lockPaths(singleton<PathSet>(profile),
+ (format("waiting for lock on profile `%1%'") % profile).str());
+ lock.setDeletion(true);
+}
+
+
+string optimisticLockProfile(const Path & profile)
+{
+ return pathExists(profile) ? readLink(profile) : "";
+}
+
+
}
diff --git a/src/nix-env/profiles.hh b/src/nix-env/profiles.hh
index 99c20f42d..a64258dae 100644
--- a/src/nix-env/profiles.hh
+++ b/src/nix-env/profiles.hh
@@ -2,6 +2,7 @@
#define __PROFILES_H
#include "types.hh"
+#include "pathlocks.hh"
#include <time.h>
@@ -37,6 +38,20 @@ void deleteGeneration(const Path & profile, unsigned int gen);
void switchLink(Path link, Path target);
+/* Ensure exclusive access to a profile. Any command that modifies
+ the profile first acquires this lock. */
+void lockProfile(PathLocks & lock, const Path & profile);
+
+/* Optimistic locking is used by long-running operations like `nix-env
+ -i'. Instead of acquiring the exclusive lock for the entire
+ duration of the operation, we just perform the operation
+ optimistically (without an exclusive lock), and check at the end
+ whether the profile changed while we were busy (i.e., the symlink
+ target changed). If so, the operation is restarted. Restarting is
+ generally cheap, since the build results are still in the Nix
+ store. Most of the time, only the user environment has to be
+ rebuilt. */
+string optimisticLockProfile(const Path & profile);
}
diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc
new file mode 100644
index 000000000..72e13fceb
--- /dev/null
+++ b/src/nix-env/user-env.cc
@@ -0,0 +1,257 @@
+#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 {
+
+
+static void readLegacyManifest(const Path & path, DrvInfos & elems);
+
+
+DrvInfos queryInstalled(EvalState & state, const Path & userEnv)
+{
+ DrvInfos elems;
+
+ Path manifestFile = userEnv + "/manifest.nix";
+ Path oldManifestFile = userEnv + "/manifest";
+
+ 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].value, "derivation");
+ mkString((*v.attrs)[state.sName].value, i->name);
+ mkString((*v.attrs)[state.sSystem].value, i->system);
+ mkString((*v.attrs)[state.sOutPath].value, i->queryOutPath(state));
+ if (drvPath != "")
+ mkString((*v.attrs)[state.sDrvPath].value, i->queryDrvPath(state));
+
+ state.mkAttrs((*v.attrs)[state.sMeta].value);
+
+ MetaInfo meta = i->queryMetaInfo(state);
+
+ foreach (MetaInfo::const_iterator, j, meta) {
+ Value & v2((*(*v.attrs)[state.sMeta].value.attrs)[state.symbols.create(j->first)].value);
+ 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].value, thisSystem);
+ mkString((*args.attrs)[state.symbols.create("manifest")].value,
+ manifestFile, singleton<PathSet>(manifestFile));
+ (*args.attrs)[state.symbols.create("derivations")].value = 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)
+{
+ expect(str, "Str(");
+ string s = parseString(str);
+ expect(str, ",[])");
+ return s;
+}
+
+
+static string parseWord(std::istream & str)
+{
+ string res;
+ while (isalpha(str.peek()))
+ res += str.get();
+ return res;
+}
+
+
+static MetaInfo parseMeta(std::istream & str)
+{
+ MetaInfo meta;
+
+ expect(str, "Attrs([");
+ while (!endOfList(str)) {
+ expect(str, "Bind(");
+
+ MetaValue value;
+
+ string name = parseString(str);
+ expect(str, ",");
+
+ string type = parseWord(str);
+
+ if (type == "Str") {
+ expect(str, "(");
+ value.type = MetaValue::tpString;
+ value.stringValue = parseString(str);
+ expect(str, ",[])");
+ }
+
+ else if (type == "List") {
+ expect(str, "([");
+ value.type = MetaValue::tpStrings;
+ while (!endOfList(str))
+ value.stringValues.push_back(parseStr(str));
+ expect(str, ")");
+ }
+
+ else throw Error(format("unexpected token `%1%'") % type);
+
+ expect(str, ",NoPos)");
+ meta[name] = value;
+ }
+
+ expect(str, ")");
+
+ return meta;
+}
+
+
+static void readLegacyManifest(const Path & path, DrvInfos & elems)
+{
+ string manifest = readFile(path);
+ std::istringstream str(manifest);
+ expect(str, "List([");
+
+ unsigned int n = 0;
+
+ while (!endOfList(str)) {
+ DrvInfo elem;
+ expect(str, "Attrs([");
+
+ while (!endOfList(str)) {
+ expect(str, "Bind(");
+ string name = parseString(str);
+ expect(str, ",");
+
+ if (name == "meta") elem.setMetaInfo(parseMeta(str));
+ else {
+ string value = parseStr(str);
+ if (name == "name") elem.name = value;
+ else if (name == "outPath") elem.setOutPath(value);
+ else if (name == "drvPath") elem.setDrvPath(value);
+ else if (name == "system") elem.system = value;
+ }
+
+ expect(str, ",NoPos)");
+ }
+
+ expect(str, ")");
+
+ if (elem.name != "") {
+ elem.attrPath = int2String(n++);
+ elems.push_back(elem);
+ }
+ }
+
+ expect(str, ")");
+}
+
+
+}
+
diff --git a/src/nix-env/user-env.hh b/src/nix-env/user-env.hh
new file mode 100644
index 000000000..4125d8217
--- /dev/null
+++ b/src/nix-env/user-env.hh
@@ -0,0 +1,20 @@
+#ifndef __USER_ENV_H
+#define __USER_ENV_H
+
+#include "get-drvs.hh"
+
+namespace nix {
+
+DrvInfos queryInstalled(EvalState & state, const Path & userEnv);
+
+bool createUserEnv(EvalState & state, DrvInfos & elems,
+ const Path & profile, bool keepDerivations,
+ const string & lockToken);
+
+}
+
+#endif /* !__USER_ENV_H */
+
+
+
+