diff options
author | Ludovic Courtès <ludo@gnu.org> | 2014-12-17 10:44:19 +0100 |
---|---|---|
committer | Ludovic Courtès <ludo@gnu.org> | 2014-12-17 22:57:04 +0100 |
commit | d4e18b05e0ab149265d3d09ae017d7337fc4176f (patch) | |
tree | e6faf256d8ec513c85c91684199fa8bf3495f002 /src/nix-env | |
parent | e7720aa10a1da63bb15a4587837d649268944943 (diff) | |
download | guix-d4e18b05e0ab149265d3d09ae017d7337fc4176f.tar.gz |
Keep only libstore, nix-daemon, and related stuff.
Diffstat (limited to 'src/nix-env')
-rw-r--r-- | src/nix-env/local.mk | 7 | ||||
-rw-r--r-- | src/nix-env/nix-env.cc | 1441 | ||||
-rw-r--r-- | src/nix-env/profiles.cc | 147 | ||||
-rw-r--r-- | src/nix-env/profiles.hh | 55 | ||||
-rw-r--r-- | src/nix-env/user-env.cc | 149 | ||||
-rw-r--r-- | src/nix-env/user-env.hh | 13 |
6 files changed, 0 insertions, 1812 deletions
diff --git a/src/nix-env/local.mk b/src/nix-env/local.mk deleted file mode 100644 index e80719cd76..0000000000 --- a/src/nix-env/local.mk +++ /dev/null @@ -1,7 +0,0 @@ -programs += nix-env - -nix-env_DIR := $(d) - -nix-env_SOURCES := $(wildcard $(d)/*.cc) - -nix-env_LIBS = libexpr libmain libstore libutil libformat diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc deleted file mode 100644 index 8a80526347..0000000000 --- a/src/nix-env/nix-env.cc +++ /dev/null @@ -1,1441 +0,0 @@ -#include "profiles.hh" -#include "names.hh" -#include "globals.hh" -#include "misc.hh" -#include "shared.hh" -#include "eval.hh" -#include "get-drvs.hh" -#include "attr-path.hh" -#include "common-opts.hh" -#include "xml-writer.hh" -#include "store-api.hh" -#include "user-env.hh" -#include "util.hh" -#include "value-to-json.hh" - -#include <cerrno> -#include <ctime> -#include <algorithm> -#include <iostream> -#include <sstream> - -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> - - -using namespace nix; -using std::cout; - - -typedef enum { - srcNixExprDrvs, - srcNixExprs, - srcStorePaths, - srcProfile, - srcAttrPath, - srcUnknown -} InstallSourceType; - - -struct InstallSourceInfo -{ - InstallSourceType type; - Path nixExprPath; /* for srcNixExprDrvs, srcNixExprs */ - Path profile; /* for srcProfile */ - string systemFilter; /* for srcNixExprDrvs */ - Bindings autoArgs; -}; - - -struct Globals -{ - InstallSourceInfo instSource; - Path profile; - EvalState state; - bool dryRun; - bool preserveInstalled; - bool removeAll; - string forceName; - bool prebuiltOnly; -}; - - -typedef void (* Operation) (Globals & globals, - Strings args, Strings opFlags, Strings opArgs); - - -void printHelp() -{ - showManPage("nix-env"); -} - - -static string needArg(Strings::iterator & i, - Strings & args, const string & arg) -{ - if (i == args.end()) throw UsageError( - format("`%1%' requires an argument") % arg); - return *i++; -} - - -static bool parseInstallSourceOptions(Globals & globals, - Strings::iterator & i, Strings & args, const string & arg) -{ - if (arg == "--from-expression" || arg == "-E") - globals.instSource.type = srcNixExprs; - else if (arg == "--from-profile") { - globals.instSource.type = srcProfile; - globals.instSource.profile = needArg(i, args, arg); - } - else if (arg == "--attr" || arg == "-A") - globals.instSource.type = srcAttrPath; - else return false; - return true; -} - - -static bool isNixExpr(const Path & path, struct stat & st) -{ - return S_ISREG(st.st_mode) || (S_ISDIR(st.st_mode) && pathExists(path + "/default.nix")); -} - - -static void getAllExprs(EvalState & state, - const Path & path, StringSet & attrs, Value & v) -{ - Strings names = readDirectory(path); - StringSet namesSorted(names.begin(), names.end()); - - foreach (StringSet::iterator, i, namesSorted) { - /* Ignore the manifest.nix used by profiles. This is - necessary to prevent it from showing up in channels (which - are implemented using profiles). */ - if (*i == "manifest.nix") continue; - - Path path2 = path + "/" + *i; - - struct stat st; - if (stat(path2.c_str(), &st) == -1) - continue; // ignore dangling symlinks in ~/.nix-defexpr - - if (isNixExpr(path2, st) && (!S_ISREG(st.st_mode) || hasSuffix(path2, ".nix"))) { - /* Strip off the `.nix' filename suffix (if applicable), - otherwise the attribute cannot be selected with the - `-A' option. Useful if you want to stick a Nix - expression directly in ~/.nix-defexpr. */ - string attrName = *i; - if (hasSuffix(attrName, ".nix")) - attrName = string(attrName, 0, attrName.size() - 4); - if (attrs.find(attrName) != attrs.end()) { - printMsg(lvlError, format("warning: name collision in input Nix expressions, skipping `%1%'") % path2); - continue; - } - attrs.insert(attrName); - /* Load the expression on demand. */ - Value & vFun(*state.allocValue()); - Value & vArg(*state.allocValue()); - state.getBuiltin("import", vFun); - mkString(vArg, path2); - mkApp(*state.allocAttr(v, state.symbols.create(attrName)), vFun, vArg); - } - else if (S_ISDIR(st.st_mode)) - /* `path2' is a directory (with no default.nix in it); - recurse into it. */ - getAllExprs(state, path2, attrs, v); - } -} - - -static void loadSourceExpr(EvalState & state, const Path & path, Value & v) -{ - struct stat st; - if (stat(path.c_str(), &st) == -1) - throw SysError(format("getting information about `%1%'") % path); - - if (isNixExpr(path, st)) { - state.evalFile(path, v); - return; - } - - /* The path is a directory. Put the Nix expressions in the - directory in a set, with the file name of each expression as - the attribute name. Recurse into subdirectories (but keep the - set flat, not nested, to make it easier for a user to have a - ~/.nix-defexpr directory that includes some system-wide - directory). */ - if (S_ISDIR(st.st_mode)) { - state.mkAttrs(v, 16); - state.mkList(*state.allocAttr(v, state.symbols.create("_combineChannels")), 0); - StringSet attrs; - getAllExprs(state, path, attrs, v); - v.attrs->sort(); - } -} - - -static void loadDerivations(EvalState & state, Path nixExprPath, - string systemFilter, Bindings & autoArgs, - const string & pathPrefix, DrvInfos & elems) -{ - Value vRoot; - loadSourceExpr(state, nixExprPath, vRoot); - - Value & v(*findAlongAttrPath(state, pathPrefix, autoArgs, vRoot)); - - getDerivations(state, v, pathPrefix, autoArgs, elems, true); - - /* Filter out all derivations not applicable to the current - system. */ - for (DrvInfos::iterator i = elems.begin(), j; i != elems.end(); i = j) { - j = i; j++; - if (systemFilter != "*" && i->system != systemFilter) - elems.erase(i); - } -} - - -static Path getHomeDir() -{ - Path homeDir(getEnv("HOME", "")); - if (homeDir == "") throw Error("HOME environment variable not set"); - return homeDir; -} - - -static Path getDefNixExprPath() -{ - return getHomeDir() + "/.nix-defexpr"; -} - - -static int getPriority(EvalState & state, DrvInfo & drv) -{ - return drv.queryMetaInt("priority", 0); -} - - -static int comparePriorities(EvalState & state, DrvInfo & drv1, DrvInfo & drv2) -{ - return getPriority(state, drv2) - getPriority(state, drv1); -} - - -// FIXME: this function is rather slow since it checks a single path -// at a time. -static bool isPrebuilt(EvalState & state, DrvInfo & elem) -{ - Path path = elem.queryOutPath(); - if (store->isValidPath(path)) return true; - PathSet ps = store->querySubstitutablePaths(singleton<PathSet>(path)); - return ps.find(path) != ps.end(); -} - - -static void checkSelectorUse(DrvNames & selectors) -{ - /* Check that all selectors have been used. */ - foreach (DrvNames::iterator, i, selectors) - if (i->hits == 0 && i->fullName != "*") - throw Error(format("selector `%1%' matches no derivations") % i->fullName); -} - - -static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems, - const Strings & args, bool newestOnly) -{ - DrvNames selectors = drvNamesFromArgs(args); - if (selectors.empty()) - selectors.push_back(DrvName("*")); - - DrvInfos elems; - set<unsigned int> done; - - foreach (DrvNames::iterator, i, selectors) { - typedef list<std::pair<DrvInfo, unsigned int> > Matches; - Matches matches; - unsigned int n = 0; - for (DrvInfos::const_iterator j = allElems.begin(); - j != allElems.end(); ++j, ++n) - { - DrvName drvName(j->name); - if (i->matches(drvName)) { - i->hits++; - matches.push_back(std::pair<DrvInfo, unsigned int>(*j, n)); - } - } - - /* If `newestOnly', if a selector matches multiple derivations - with the same name, pick the one matching the current - system. If there are still multiple derivations, pick the - one with the highest priority. If there are still multiple - derivations, pick the one with the highest version. - Finally, if there are still multiple derivations, - arbitrarily pick the first one. */ - if (newestOnly) { - - /* Map from package names to derivations. */ - typedef map<string, std::pair<DrvInfo, unsigned int> > Newest; - Newest newest; - StringSet multiple; - - for (Matches::iterator j = matches.begin(); j != matches.end(); ++j) { - DrvName drvName(j->first.name); - int d = 1; - - Newest::iterator k = newest.find(drvName.name); - - if (k != newest.end()) { - d = j->first.system == k->second.first.system ? 0 : - j->first.system == settings.thisSystem ? 1 : - k->second.first.system == settings.thisSystem ? -1 : 0; - if (d == 0) - d = comparePriorities(state, j->first, k->second.first); - if (d == 0) - d = compareVersions(drvName.version, DrvName(k->second.first.name).version); - } - - if (d > 0) { - newest.erase(drvName.name); - newest.insert(Newest::value_type(drvName.name, *j)); - multiple.erase(j->first.name); - } else if (d == 0) { - multiple.insert(j->first.name); - } - } - - matches.clear(); - for (Newest::iterator j = newest.begin(); j != newest.end(); ++j) { - if (multiple.find(j->second.first.name) != multiple.end()) - printMsg(lvlInfo, - format("warning: there are multiple derivations named `%1%'; using the first one") - % j->second.first.name); - matches.push_back(j->second); - } - } - - /* Insert only those elements in the final list that we - haven't inserted before. */ - for (Matches::iterator j = matches.begin(); j != matches.end(); ++j) - if (done.find(j->second) == done.end()) { - done.insert(j->second); - elems.push_back(j->first); - } - } - - checkSelectorUse(selectors); - - return elems; -} - - -static bool isPath(const string & s) -{ - return s.find('/') != string::npos; -} - - -static void queryInstSources(EvalState & state, - InstallSourceInfo & instSource, const Strings & args, - DrvInfos & elems, bool newestOnly) -{ - InstallSourceType type = instSource.type; - if (type == srcUnknown && args.size() > 0 && isPath(args.front())) - type = srcStorePaths; - - switch (type) { - - /* Get the available user environment elements from the - derivations specified in a Nix expression, including only - those with names matching any of the names in `args'. */ - case srcUnknown: - case srcNixExprDrvs: { - - /* Load the derivations from the (default or specified) - Nix expression. */ - DrvInfos allElems; - loadDerivations(state, instSource.nixExprPath, - instSource.systemFilter, instSource.autoArgs, "", allElems); - - elems = filterBySelector(state, allElems, args, newestOnly); - - break; - } - - /* Get the available user environment elements from the Nix - expressions specified on the command line; these should be - functions that take the default Nix expression file as - argument, e.g., if the file is `./foo.nix', then the - argument `x: x.bar' is equivalent to `(x: x.bar) - (import ./foo.nix)' = `(import ./foo.nix).bar'. */ - case srcNixExprs: { - - Value vArg; - loadSourceExpr(state, instSource.nixExprPath, vArg); - - foreach (Strings::const_iterator, i, args) { - Expr * eFun = state.parseExprFromString(*i, absPath(".")); - Value vFun, vTmp; - state.eval(eFun, vFun); - mkApp(vTmp, vFun, vArg); - getDerivations(state, vTmp, "", instSource.autoArgs, elems, true); - } - - break; - } - - /* The available user environment elements are specified as a - list of store paths (which may or may not be - derivations). */ - case srcStorePaths: { - - foreach (Strings::const_iterator, i, args) { - Path path = followLinksToStorePath(*i); - - string name = baseNameOf(path); - string::size_type dash = name.find('-'); - if (dash != string::npos) - name = string(name, dash + 1); - - DrvInfo elem(state, name, "", "", 0); - - if (isDerivation(path)) { - elem.setDrvPath(path); - elem.setOutPath(findOutput(derivationFromPath(*store, path), "out")); - if (name.size() >= drvExtension.size() && - string(name, name.size() - drvExtension.size()) == drvExtension) - name = string(name, 0, name.size() - drvExtension.size()); - } - else elem.setOutPath(path); - - elems.push_back(elem); - } - - break; - } - - /* Get the available user environment elements from another - user environment. These are then filtered as in the - `srcNixExprDrvs' case. */ - case srcProfile: { - elems = filterBySelector(state, - queryInstalled(state, instSource.profile), - args, newestOnly); - break; - } - - case srcAttrPath: { - Value vRoot; - loadSourceExpr(state, instSource.nixExprPath, vRoot); - foreach (Strings::const_iterator, i, args) { - Value & v(*findAlongAttrPath(state, *i, instSource.autoArgs, vRoot)); - getDerivations(state, v, "", instSource.autoArgs, elems, true); - } - break; - } - } -} - - -static void printMissing(EvalState & state, DrvInfos & elems) -{ - PathSet targets; - foreach (DrvInfos::iterator, i, elems) { - Path drvPath = i->queryDrvPath(); - if (drvPath != "") - targets.insert(drvPath); - else - targets.insert(i->queryOutPath()); - } - - printMissing(*store, targets); -} - - -static bool keep(DrvInfo & drv) -{ - return drv.queryMetaBool("keep", false); -} - - -static void installDerivations(Globals & globals, - const Strings & args, const Path & profile) -{ - debug(format("installing derivations")); - - /* Get the set of user environment elements to be installed. */ - DrvInfos newElems, newElemsTmp; - queryInstSources(globals.state, globals.instSource, args, newElemsTmp, true); - - /* If --prebuilt-only is given, filter out source-only packages. */ - foreach (DrvInfos::iterator, i, newElemsTmp) - if (!globals.prebuiltOnly || isPrebuilt(globals.state, *i)) - newElems.push_back(*i); - - StringSet newNames; - for (DrvInfos::iterator i = newElems.begin(); i != newElems.end(); ++i) { - /* `forceName' is a hack to get package names right in some - one-click installs, namely those where the name used in the - path is not the one we want (e.g., `java-front' versus - `java-front-0.9pre15899'). */ - if (globals.forceName != "") - i->name = globals.forceName; - newNames.insert(DrvName(i->name).name); - } - - - while (true) { - string lockToken = optimisticLockProfile(profile); - - DrvInfos allElems(newElems); - - /* Add in the already installed derivations, unless they have - the same name as a to-be-installed element. */ - if (!globals.removeAll) { - DrvInfos installedElems = queryInstalled(globals.state, profile); - - foreach (DrvInfos::iterator, i, installedElems) { - DrvName drvName(i->name); - if (!globals.preserveInstalled && - newNames.find(drvName.name) != newNames.end() && - !keep(*i)) - printMsg(lvlInfo, format("replacing old `%1%'") % i->name); - else - allElems.push_back(*i); - } - - foreach (DrvInfos::iterator, i, newElems) - printMsg(lvlInfo, format("installing `%1%'") % i->name); - } - - printMissing(globals.state, newElems); - - if (globals.dryRun) return; - - if (createUserEnv(globals.state, allElems, - profile, settings.envKeepDerivations, lockToken)) break; - } -} - - -static void opInstall(Globals & globals, - Strings args, Strings opFlags, Strings opArgs) -{ - for (Strings::iterator i = opFlags.begin(); i != opFlags.end(); ) { - string arg = *i++; - if (parseInstallSourceOptions(globals, i, opFlags, arg)) ; - else if (arg == "--preserve-installed" || arg == "-P") - globals.preserveInstalled = true; - else if (arg == "--remove-all" || arg == "-r") - globals.removeAll = true; - else throw UsageError(format("unknown flag `%1%'") % arg); - } - - installDerivations(globals, opArgs, globals.profile); -} - - -typedef enum { utLt, utLeq, utEq, utAlways } UpgradeType; - - -static void upgradeDerivations(Globals & globals, - const Strings & args, UpgradeType upgradeType) -{ - debug(format("upgrading derivations")); - - /* Upgrade works as follows: we take all currently installed - derivations, and for any derivation matching any selector, look - for a derivation in the input Nix expression that has the same - name and a higher version number. */ - - while (true) { - string lockToken = optimisticLockProfile(globals.profile); - - DrvInfos installedElems = queryInstalled(globals.state, globals.profile); - - /* Fetch all derivations from the input file. */ - DrvInfos availElems; - queryInstSources(globals.state, globals.instSource, args, availElems, false); - - /* Go through all installed derivations. */ - DrvInfos newElems; - foreach (DrvInfos::iterator, i, installedElems) { - DrvName drvName(i->name); - - try { - - if (keep(*i)) { - newElems.push_back(*i); - continue; - } - - /* Find the derivation in the input Nix expression - with the same name that satisfies the version - constraints specified by upgradeType. If there are - multiple matches, take the one with the highest - priority. If there are still multiple matches, - take the one with the highest version. */ - DrvInfos::iterator bestElem = availElems.end(); - DrvName bestName; - foreach (DrvInfos::iterator, j, availElems) { - DrvName newName(j->name); - if (newName.name == drvName.name) { - int d = comparePriorities(globals.state, *i, *j); - if (d == 0) d = compareVersions(drvName.version, newName.version); - if ((upgradeType == utLt && d < 0) || - (upgradeType == utLeq && d <= 0) || - (upgradeType == utEq && d == 0) || - upgradeType == utAlways) - { - int d2 = -1; - if (bestElem != availElems.end()) { - d2 = comparePriorities(globals.state, *bestElem, *j); - if (d2 == 0) d2 = compareVersions(bestName.version, newName.version); - } - if (d2 < 0 && (!globals.prebuiltOnly || isPrebuilt(globals.state, *j))) { - bestElem = j; - bestName = newName; - } - } - } - } - - if (bestElem != availElems.end() && - i->queryOutPath() != - bestElem->queryOutPath()) - { - printMsg(lvlInfo, - format("upgrading `%1%' to `%2%'") - % i->name % bestElem->name); - newElems.push_back(*bestElem); - } else newElems.push_back(*i); - - } catch (Error & e) { - e.addPrefix(format("while trying to find an upgrade for `%1%':\n") % i->name); - throw; - } - } - - printMissing(globals.state, newElems); - - if (globals.dryRun) return; - - if (createUserEnv(globals.state, newElems, - globals.profile, settings.envKeepDerivations, lockToken)) break; - } -} - - -static void opUpgrade(Globals & globals, - Strings args, Strings opFlags, Strings opArgs) -{ - UpgradeType upgradeType = utLt; - for (Strings::iterator i = opFlags.begin(); i != opFlags.end(); ) { - string arg = *i++; - if (parseInstallSourceOptions(globals, i, opFlags, arg)) ; - else if (arg == "--lt") upgradeType = utLt; - else if (arg == "--leq") upgradeType = utLeq; - else if (arg == "--eq") upgradeType = utEq; - else if (arg == "--always") upgradeType = utAlways; - else throw UsageError(format("unknown flag `%1%'") % arg); - } - - upgradeDerivations(globals, opArgs, upgradeType); -} - - -static void setMetaFlag(EvalState & state, DrvInfo & drv, - const string & name, const string & value) -{ - Value * v = state.allocValue(); - mkString(*v, value.c_str()); - drv.setMeta(name, v); -} - - -static void opSetFlag(Globals & globals, - Strings args, 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())); - - while (true) { - string lockToken = optimisticLockProfile(globals.profile); - - DrvInfos installedElems = queryInstalled(globals.state, globals.profile); - - /* Update all matching derivations. */ - foreach (DrvInfos::iterator, i, installedElems) { - DrvName drvName(i->name); - foreach (DrvNames::iterator, j, selectors) - if (j->matches(drvName)) { - printMsg(lvlInfo, format("setting flag on `%1%'") % i->name); - j->hits++; - setMetaFlag(globals.state, *i, flagName, flagValue); - break; - } - } - - checkSelectorUse(selectors); - - /* Write the new user environment. */ - if (createUserEnv(globals.state, installedElems, - globals.profile, settings.envKeepDerivations, lockToken)) break; - } -} - - -static void opSet(Globals & globals, - Strings args, Strings opFlags, Strings opArgs) -{ - for (Strings::iterator i = opFlags.begin(); i != opFlags.end(); ) { - string arg = *i++; - if (parseInstallSourceOptions(globals, i, opFlags, arg)) ; - else throw UsageError(format("unknown flag `%1%'") % arg); - } - - DrvInfos elems; - queryInstSources(globals.state, globals.instSource, opArgs, elems, true); - - if (elems.size() != 1) - throw Error("--set requires exactly one derivation"); - - DrvInfo & drv(elems.front()); - - if (drv.queryDrvPath() != "") { - PathSet paths = singleton<PathSet>(drv.queryDrvPath()); - printMissing(*store, paths); - if (globals.dryRun) return; - store->buildPaths(paths, globals.state.repair ? bmRepair : bmNormal); - } - else { - printMissing(*store, singleton<PathSet>(drv.queryOutPath())); - if (globals.dryRun) return; - store->ensurePath(drv.queryOutPath()); - } - - debug(format("switching to new user environment")); - Path generation = createGeneration(globals.profile, drv.queryOutPath()); - switchLink(globals.profile, generation); -} - - -static void uninstallDerivations(Globals & globals, Strings & selectors, - Path & profile) -{ - while (true) { - string lockToken = optimisticLockProfile(profile); - - DrvInfos installedElems = queryInstalled(globals.state, profile); - DrvInfos newElems; - - foreach (DrvInfos::iterator, i, installedElems) { - DrvName drvName(i->name); - bool found = false; - foreach (Strings::iterator, j, selectors) - /* !!! the repeated calls to followLinksToStorePath() - are expensive, should pre-compute them. */ - if ((isPath(*j) && i->queryOutPath() == followLinksToStorePath(*j)) - || DrvName(*j).matches(drvName)) - { - printMsg(lvlInfo, format("uninstalling `%1%'") % i->name); - found = true; - break; - } - if (!found) newElems.push_back(*i); - } - - if (globals.dryRun) return; - - if (createUserEnv(globals.state, newElems, - profile, settings.envKeepDerivations, lockToken)) break; - } -} - - -static void opUninstall(Globals & globals, - Strings args, Strings opFlags, Strings opArgs) -{ - if (opFlags.size() > 0) - throw UsageError(format("unknown flag `%1%'") % opFlags.front()); - uninstallDerivations(globals, opArgs, globals.profile); -} - - -static bool cmpChars(char a, char b) -{ - return toupper(a) < toupper(b); -} - - -static bool cmpElemByName(const DrvInfo & a, const DrvInfo & b) -{ - return lexicographical_compare( - a.name.begin(), a.name.end(), - b.name.begin(), b.name.end(), cmpChars); -} - - -typedef list<Strings> Table; - - -void printTable(Table & table) -{ - unsigned int nrColumns = table.size() > 0 ? table.front().size() : 0; - - vector<unsigned int> widths; - widths.resize(nrColumns); - - foreach (Table::iterator, i, table) { - assert(i->size() == nrColumns); - Strings::iterator j; - unsigned int column; - for (j = i->begin(), column = 0; j != i->end(); ++j, ++column) - if (j->size() > widths[column]) widths[column] = j->size(); - } - - foreach (Table::iterator, i, table) { - Strings::iterator j; - unsigned int column; - for (j = i->begin(), column = 0; j != i->end(); ++j, ++column) { - string s = *j; - replace(s.begin(), s.end(), '\n', ' '); - cout << s; - if (column < nrColumns - 1) - cout << string(widths[column] - s.size() + 2, ' '); - } - cout << std::endl; - } -} - - -/* This function compares the version of an element against the - versions in the given set of elements. `cvLess' means that only - lower versions are in the set, `cvEqual' means that at most an - equal version is in the set, and `cvGreater' means that there is at - least one element with a higher version in the set. `cvUnavail' - means that there are no elements with the same name in the set. */ - -typedef enum { cvLess, cvEqual, cvGreater, cvUnavail } VersionDiff; - -static VersionDiff compareVersionAgainstSet( - const DrvInfo & elem, const DrvInfos & elems, string & version) -{ - DrvName name(elem.name); - - VersionDiff diff = cvUnavail; - version = "?"; - - for (DrvInfos::const_iterator i = elems.begin(); i != elems.end(); ++i) { - DrvName name2(i->name); - if (name.name == name2.name) { - int d = compareVersions(name.version, name2.version); - if (d < 0) { - diff = cvGreater; - version = name2.version; - } - else if (diff != cvGreater && d == 0) { - diff = cvEqual; - version = name2.version; - } - else if (diff != cvGreater && diff != cvEqual && d > 0) { - diff = cvLess; - if (version == "" || compareVersions(version, name2.version) < 0) - version = name2.version; - } - } - } - - return diff; -} - - -static string colorString(const string & s) -{ - if (!isatty(STDOUT_FILENO)) return s; - return "\e[1;31m" + s + "\e[0m"; -} - - -static void queryJSON(Globals & globals, vector<DrvInfo> & elems) -{ - JSONObject topObj(cout); - foreach (vector<DrvInfo>::iterator, i, elems) { - topObj.attr(i->attrPath); - JSONObject pkgObj(cout); - - pkgObj.attr("name", i->name); - pkgObj.attr("system", i->system); - - pkgObj.attr("meta"); - JSONObject metaObj(cout); - StringSet metaNames = i->queryMetaNames(); - foreach (StringSet::iterator, j, metaNames) { - metaObj.attr(*j); - Value * v = i->queryMeta(*j); - if (!v) - printMsg(lvlError, format("derivation `%1%' has invalid meta attribute `%2%'") % i->name % *j); - else { - PathSet context; - printValueAsJSON(globals.state, true, *v, cout, context); - } - } - } -} - - -static void opQuery(Globals & globals, - Strings args, Strings opFlags, Strings opArgs) -{ - Strings remaining; - string attrPath; - - bool printStatus = false; - bool printName = true; - bool printAttrPath = false; - bool printSystem = false; - bool printDrvPath = false; - bool printOutPath = false; - bool printDescription = false; - bool printMeta = false; - bool compareVersions = false; - bool xmlOutput = false; - bool jsonOutput = false; - - enum { sInstalled, sAvailable } source = sInstalled; - - settings.readOnlyMode = true; /* makes evaluation a bit faster */ - - for (Strings::iterator i = args.begin(); i != args.end(); ) { - string arg = *i++; - if (arg == "--status" || arg == "-s") printStatus = true; - else if (arg == "--no-name") printName = false; - else if (arg == "--system") printSystem = true; - else if (arg == "--description") printDescription = true; - else if (arg == "--compare-versions" || arg == "-c") compareVersions = true; - else if (arg == "--drv-path") printDrvPath = true; - else if (arg == "--out-path") printOutPath = true; - else if (arg == "--meta") printMeta = true; - else if (arg == "--installed") source = sInstalled; - else if (arg == "--available" || arg == "-a") source = sAvailable; - else if (arg == "--xml") xmlOutput = true; - else if (arg == "--json") jsonOutput = true; - else if (arg == "--attr-path" || arg == "-P") printAttrPath = true; - else if (arg == "--attr" || arg == "-A") - attrPath = needArg(i, args, arg); - else if (arg[0] == '-') - throw UsageError(format("unknown flag `%1%'") % arg); - else remaining.push_back(arg); - } - - - /* Obtain derivation information from the specified source. */ - DrvInfos availElems, installedElems; - - if (source == sInstalled || compareVersions || printStatus) - installedElems = queryInstalled(globals.state, globals.profile); - - if (source == sAvailable || compareVersions) - loadDerivations(globals.state, globals.instSource.nixExprPath, - globals.instSource.systemFilter, globals.instSource.autoArgs, - attrPath, availElems); - - DrvInfos elems_ = filterBySelector(globals.state, - source == sInstalled ? installedElems : availElems, - remaining, false); - - DrvInfos & otherElems(source == sInstalled ? availElems : installedElems); - - - /* Sort them by name. */ - /* !!! */ - vector<DrvInfo> elems; - for (DrvInfos::iterator i = elems_.begin(); i != elems_.end(); ++i) - elems.push_back(*i); - sort(elems.begin(), elems.end(), cmpElemByName); - - - /* We only need to know the installed paths when we are querying - the status of the derivation. */ - PathSet installed; /* installed paths */ - - if (printStatus) { - for (DrvInfos::iterator i = installedElems.begin(); - i != installedElems.end(); ++i) - installed.insert(i->queryOutPath()); - } - - - /* Query which paths have substitutes. */ - PathSet validPaths, substitutablePaths; - if (printStatus || globals.prebuiltOnly) { - PathSet paths; - foreach (vector<DrvInfo>::iterator, i, elems) - try { - paths.insert(i->queryOutPath()); - } catch (AssertionError & e) { - printMsg(lvlTalkative, format("skipping derivation named `%1%' which gives an assertion failure") % i->name); - i->setFailed(); - } - validPaths = store->queryValidPaths(paths); - substitutablePaths = store->querySubstitutablePaths(paths); - } - - - /* Print the desired columns, or XML output. */ - if (jsonOutput) { - queryJSON(globals, elems); - return; - } - - Table table; - std::ostringstream dummy; - XMLWriter xml(true, *(xmlOutput ? &cout : &dummy)); - XMLOpenElement xmlRoot(xml, "items"); - - foreach (vector<DrvInfo>::iterator, i, elems) { - try { - if (i->hasFailed()) continue; - - startNest(nest, lvlDebug, format("outputting query result `%1%'") % i->attrPath); - - if (globals.prebuiltOnly && - validPaths.find(i->queryOutPath()) == validPaths.end() && - substitutablePaths.find(i->queryOutPath()) == substitutablePaths.end()) - continue; - - /* For table output. */ - Strings columns; - - /* For XML output. */ - XMLAttrs attrs; - - if (printStatus) { - Path outPath = i->queryOutPath(); - bool hasSubs = substitutablePaths.find(outPath) != substitutablePaths.end(); - bool isInstalled = installed.find(outPath) != installed.end(); - bool isValid = validPaths.find(outPath) != validPaths.end(); - if (xmlOutput) { - attrs["installed"] = isInstalled ? "1" : "0"; - attrs["valid"] = isValid ? "1" : "0"; - attrs["substitutable"] = hasSubs ? "1" : "0"; - } else - columns.push_back( - (string) (isInstalled ? "I" : "-") - + (isValid ? "P" : "-") - + (hasSubs ? "S" : "-")); - } - - if (xmlOutput) - attrs["attrPath"] = i->attrPath; - else if (printAttrPath) - columns.push_back(i->attrPath); - - if (xmlOutput) - attrs["name"] = i->name; - else if (printName) - columns.push_back(i->name); - - if (compareVersions) { - /* Compare this element against the versions of the - same named packages in either the set of available - elements, or the set of installed elements. !!! - This is O(N * M), should be O(N * lg M). */ - string version; - VersionDiff diff = compareVersionAgainstSet(*i, otherElems, version); - - char ch; - switch (diff) { - case cvLess: ch = '>'; break; - case cvEqual: ch = '='; break; - case cvGreater: ch = '<'; break; - case cvUnavail: ch = '-'; break; - default: abort(); - } - - if (xmlOutput) { - if (diff != cvUnavail) { - attrs["versionDiff"] = ch; - attrs["maxComparedVersion"] = version; - } - } else { - string column = (string) "" + ch + " " + version; - if (diff == cvGreater) column = colorString(column); - columns.push_back(column); - } - } - - if (xmlOutput) { - if (i->system != "") attrs["system"] = i->system; - } - else if (printSystem) - columns.push_back(i->system); - - if (printDrvPath) { - string drvPath = i->queryDrvPath(); - if (xmlOutput) { - if (drvPath != "") attrs["drvPath"] = drvPath; - } else - columns.push_back(drvPath == "" ? "-" : drvPath); - } - - if (printOutPath && !xmlOutput) { - DrvInfo::Outputs outputs = i->queryOutputs(); - string s; - foreach (DrvInfo::Outputs::iterator, j, outputs) { - if (!s.empty()) s += ';'; - if (j->first != "out") { s += j->first; s += "="; } - s += j->second; - } - columns.push_back(s); - } - - if (printDescription) { - string descr = i->queryMetaString("description"); - if (xmlOutput) { - if (descr != "") attrs["description"] = descr; - } else - columns.push_back(descr); - } - - if (xmlOutput) { - if (printOutPath || printMeta) { - XMLOpenElement item(xml, "item", attrs); - if (printOutPath) { - DrvInfo::Outputs outputs = i->queryOutputs(); - foreach (DrvInfo::Outputs::iterator, j, outputs) { - XMLAttrs attrs2; - attrs2["name"] = j->first; - attrs2["path"] = j->second; - xml.writeEmptyElement("output", attrs2); - } - } - if (printMeta) { - StringSet metaNames = i->queryMetaNames(); - foreach (StringSet::iterator, j, metaNames) { - XMLAttrs attrs2; - attrs2["name"] = *j; - Value * v = i->queryMeta(*j); - if (!v) - printMsg(lvlError, format("derivation `%1%' has invalid meta attribute `%2%'") % i->name % *j); - else { - if (v->type == tString) { - attrs2["type"] = "string"; - attrs2["value"] = v->string.s; - xml.writeEmptyElement("meta", attrs2); - } else if (v->type == tInt) { - attrs2["type"] = "int"; - attrs2["value"] = (format("%1%") % v->integer).str(); - xml.writeEmptyElement("meta", attrs2); - } else if (v->type == tBool) { - attrs2["type"] = "bool"; - attrs2["value"] = v->boolean ? "true" : "false"; - xml.writeEmptyElement("meta", attrs2); - } else if (v->type == tList) { - attrs2["type"] = "strings"; - XMLOpenElement m(xml, "meta", attrs2); - for (unsigned int j = 0; j < v->list.length; ++j) { - if (v->list.elems[j]->type != tString) continue; - XMLAttrs attrs3; - attrs3["value"] = v->list.elems[j]->string.s; - xml.writeEmptyElement("string", attrs3); - } - } - } - } - } - } else - xml.writeEmptyElement("item", attrs); - } else - table.push_back(columns); - - cout.flush(); - - } catch (AssertionError & e) { - printMsg(lvlTalkative, format("skipping derivation named `%1%' which gives an assertion failure") % i->name); - } catch (Error & e) { - e.addPrefix(format("while querying the derivation named `%1%':\n") % i->name); - throw; - } - } - - if (!xmlOutput) printTable(table); -} - - -static void opSwitchProfile(Globals & globals, - Strings args, Strings opFlags, Strings opArgs) -{ - if (opFlags.size() > 0) - throw UsageError(format("unknown flag `%1%'") % opFlags.front()); - if (opArgs.size() != 1) - throw UsageError(format("exactly one argument expected")); - - Path profile = absPath(opArgs.front()); - Path profileLink = getHomeDir() + "/.nix-profile"; - - switchLink(profileLink, profile); -} - - -static const int prevGen = -2; - - -static void switchGeneration(Globals & globals, int dstGen) -{ - PathLocks lock; - lockProfile(lock, globals.profile); - - int curGen; - Generations gens = findGenerations(globals.profile, curGen); - - Generation dst; - for (Generations::iterator i = gens.begin(); i != gens.end(); ++i) - if ((dstGen == prevGen && i->number < curGen) || - (dstGen >= 0 && i->number == dstGen)) - dst = *i; - - if (!dst) { - if (dstGen == prevGen) - throw Error(format("no generation older than the current (%1%) exists") - % curGen); - else - throw Error(format("generation %1% does not exist") % dstGen); - } - - printMsg(lvlInfo, format("switching from generation %1% to %2%") - % curGen % dst.number); - - if (globals.dryRun) return; - - switchLink(globals.profile, dst.path); -} - - -static void opSwitchGeneration(Globals & globals, - Strings args, Strings opFlags, Strings opArgs) -{ - if (opFlags.size() > 0) - throw UsageError(format("unknown flag `%1%'") % opFlags.front()); - if (opArgs.size() != 1) - throw UsageError(format("exactly one argument expected")); - - int dstGen; - if (!string2Int(opArgs.front(), dstGen)) - throw UsageError(format("expected a generation number")); - - switchGeneration(globals, dstGen); -} - - -static void opRollback(Globals & globals, - Strings args, Strings opFlags, Strings opArgs) -{ - if (opFlags.size() > 0) - throw UsageError(format("unknown flag `%1%'") % opFlags.front()); - if (opArgs.size() != 0) - throw UsageError(format("no arguments expected")); - - switchGeneration(globals, prevGen); -} - - -static void opListGenerations(Globals & globals, - Strings args, Strings opFlags, Strings opArgs) -{ - if (opFlags.size() > 0) - throw UsageError(format("unknown flag `%1%'") % opFlags.front()); - if (opArgs.size() != 0) - throw UsageError(format("no arguments expected")); - - PathLocks lock; - lockProfile(lock, globals.profile); - - int curGen; - Generations gens = findGenerations(globals.profile, curGen); - - for (Generations::iterator i = gens.begin(); i != gens.end(); ++i) { - tm t; - if (!localtime_r(&i->creationTime, &t)) throw Error("cannot convert time"); - cout << format("%|4| %|4|-%|02|-%|02| %|02|:%|02|:%|02| %||\n") - % i->number - % (t.tm_year + 1900) % (t.tm_mon + 1) % t.tm_mday - % t.tm_hour % t.tm_min % t.tm_sec - % (i->number == curGen ? "(current)" : ""); - } -} - - -static void deleteGeneration2(Globals & globals, unsigned int gen) -{ - if (globals.dryRun) - printMsg(lvlInfo, format("would remove generation %1%") % gen); - else { - printMsg(lvlInfo, format("removing generation %1%") % gen); - deleteGeneration(globals.profile, gen); - } - -} - - -static void opDeleteGenerations(Globals & globals, - Strings args, Strings opFlags, Strings opArgs) -{ - if (opFlags.size() > 0) - throw UsageError(format("unknown flag `%1%'") % opFlags.front()); - - PathLocks lock; - lockProfile(lock, globals.profile); - - int curGen; - Generations gens = findGenerations(globals.profile, curGen); - - for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); ++i) { - - if (*i == "old") { - for (Generations::iterator j = gens.begin(); j != gens.end(); ++j) - if (j->number != curGen) - deleteGeneration2(globals, j->number); - } else if (i->size() >= 2 && tolower(*i->rbegin()) == 'd') { - time_t curTime = time(NULL); - time_t oldTime; - string strDays = string(*i, 0, i->size() - 1); - int days; - - if (!string2Int(strDays, days) || days < 1) - throw UsageError(format("invalid number of days specifier `%1%'") % *i); - - oldTime = curTime - days * 24 * 3600; - - for (Generations::iterator j = gens.begin(); j != gens.end(); ++j) { - if (j->number == curGen) continue; - - if (j->creationTime < oldTime) - deleteGeneration2(globals, j->number); - } - } else { - int n; - if (!string2Int(*i, n) || n < 0) - throw UsageError(format("invalid generation specifier `%1%'") % *i); - bool found = false; - for (Generations::iterator j = gens.begin(); j != gens.end(); ++j) { - if (j->number == n) { - deleteGeneration2(globals, j->number); - found = true; - break; - } - } - if (!found) - printMsg(lvlError, format("generation %1% does not exist") % n); - } - } -} - - -void run(Strings args) -{ - Strings opFlags, opArgs, remaining; - Operation op = 0; - - Globals globals; - - globals.instSource.type = srcUnknown; - globals.instSource.nixExprPath = getDefNixExprPath(); - globals.instSource.systemFilter = "*"; - - globals.dryRun = false; - globals.preserveInstalled = false; - globals.removeAll = false; - globals.prebuiltOnly = false; - - for (Strings::iterator i = args.begin(); i != args.end(); ) { - string arg = *i++; - - Operation oldOp = op; - - if (arg == "--install" || arg == "-i") - op = opInstall; - else if (parseOptionArg(arg, i, args.end(), - globals.state, globals.instSource.autoArgs)) - ; - else if (parseSearchPathArg(arg, i, args.end(), globals.state)) - ; - else if (arg == "--force-name") // undocumented flag for nix-install-package - globals.forceName = needArg(i, args, arg); - else if (arg == "--uninstall" || arg == "-e") - op = opUninstall; - else if (arg == "--upgrade" || arg == "-u") - op = opUpgrade; - else if (arg == "--set-flag") - op = opSetFlag; - else if (arg == "--set") - op = opSet; - else if (arg == "--query" || arg == "-q") - op = opQuery; - else if (arg == "--profile" || arg == "-p") - globals.profile = absPath(needArg(i, args, arg)); - else if (arg == "--file" || arg == "-f") - globals.instSource.nixExprPath = lookupFileArg(globals.state, needArg(i, args, arg)); - else if (arg == "--switch-profile" || arg == "-S") - op = opSwitchProfile; - else if (arg == "--switch-generation" || arg == "-G") - op = opSwitchGeneration; - else if (arg == "--rollback") - op = opRollback; - else if (arg == "--list-generations") - op = opListGenerations; - else if (arg == "--delete-generations") - op = opDeleteGenerations; - else if (arg == "--dry-run") { - printMsg(lvlInfo, "(dry run; not doing anything)"); - globals.dryRun = true; - } - else if (arg == "--system-filter") - globals.instSource.systemFilter = needArg(i, args, arg); - else if (arg == "--prebuilt-only" || arg == "-b") - globals.prebuiltOnly = true; - else if (arg == "--repair") - globals.state.repair = true; - else { - remaining.push_back(arg); - if (arg[0] == '-') { - opFlags.push_back(arg); - if (arg == "--from-profile") { /* !!! hack */ - if (i != args.end()) opFlags.push_back(*i++); - } - } else opArgs.push_back(arg); - } - - if (oldOp && oldOp != op) - throw UsageError("only one operation may be specified"); - } - - if (!op) throw UsageError("no operation specified"); - - if (globals.profile == "") - globals.profile = getEnv("NIX_PROFILE", ""); - - if (globals.profile == "") { - Path profileLink = getHomeDir() + "/.nix-profile"; - globals.profile = pathExists(profileLink) - ? absPath(readLink(profileLink), dirOf(profileLink)) - : canonPath(settings.nixStateDir + "/profiles/default"); - } - - store = openStore(); - - op(globals, remaining, opFlags, opArgs); - - globals.state.printStats(); -} - - -string programId = "nix-env"; diff --git a/src/nix-env/profiles.cc b/src/nix-env/profiles.cc deleted file mode 100644 index f7b306890d..0000000000 --- a/src/nix-env/profiles.cc +++ /dev/null @@ -1,147 +0,0 @@ -#include "profiles.hh" -#include "store-api.hh" -#include "util.hh" - -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <errno.h> -#include <stdio.h> - - -namespace nix { - - -static bool cmpGensByNumber(const Generation & a, const Generation & b) -{ - return a.number < b.number; -} - - -/* Parse a generation name of the format - `<profilename>-<number>-link'. */ -static int parseName(const string & profileName, const string & name) -{ - if (string(name, 0, profileName.size() + 1) != profileName + "-") return -1; - string s = string(name, profileName.size() + 1); - string::size_type p = s.find("-link"); - if (p == string::npos) return -1; - int n; - if (string2Int(string(s, 0, p), n) && n >= 0) - return n; - else - return -1; -} - - - -Generations findGenerations(Path profile, int & curGen) -{ - Generations gens; - - Path profileDir = dirOf(profile); - string profileName = baseNameOf(profile); - - Strings names = readDirectory(profileDir); - for (Strings::iterator i = names.begin(); i != names.end(); ++i) { - int n; - if ((n = parseName(profileName, *i)) != -1) { - Generation gen; - gen.path = profileDir + "/" + *i; - gen.number = n; - struct stat st; - if (lstat(gen.path.c_str(), &st) != 0) - throw SysError(format("statting `%1%'") % gen.path); - gen.creationTime = st.st_mtime; - gens.push_back(gen); - } - } - - gens.sort(cmpGensByNumber); - - curGen = pathExists(profile) - ? parseName(profileName, readLink(profile)) - : -1; - - return gens; -} - - -static void makeName(const Path & profile, unsigned int num, - Path & outLink) -{ - Path prefix = (format("%1%-%2%") % profile % num).str(); - outLink = prefix + "-link"; -} - - -Path createGeneration(Path profile, Path outPath) -{ - /* The new generation number should be higher than old the - previous ones. */ - int dummy; - Generations gens = findGenerations(profile, dummy); - unsigned int num = gens.size() > 0 ? gens.back().number : 0; - - /* Create the new generation. Note that addPermRoot() blocks if - the garbage collector is running to prevent the stuff we've - built from moving from the temporary roots (which the GC knows) - to the permanent roots (of which the GC would have a stale - view). If we didn't do it this way, the GC might remove the - user environment etc. we've just built. */ - Path generation; - makeName(profile, num + 1, generation); - addPermRoot(*store, outPath, generation, false, true); - - return generation; -} - - -static void removeFile(const Path & path) -{ - if (remove(path.c_str()) == -1) - throw SysError(format("cannot unlink `%1%'") % path); -} - - -void deleteGeneration(const Path & profile, unsigned int gen) -{ - Path generation; - makeName(profile, gen, generation); - removeFile(generation); -} - - -void switchLink(Path link, Path target) -{ - /* Hacky. */ - if (dirOf(target) == dirOf(link)) target = baseNameOf(target); - - Path tmp = canonPath(dirOf(link) + "/.new_" + baseNameOf(link)); - createSymlink(target, tmp); - /* The rename() system call is supposed to be essentially atomic - on Unix. That is, if we have links `current -> X' and - `new_current -> Y', and we rename new_current to current, a - process accessing current will see X or Y, but never a - file-not-found or other error condition. This is sufficient to - atomically switch user environments. */ - if (rename(tmp.c_str(), link.c_str()) != 0) - 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 deleted file mode 100644 index 30d2376d99..0000000000 --- a/src/nix-env/profiles.hh +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include "types.hh" -#include "pathlocks.hh" - -#include <time.h> - - -namespace nix { - - -struct Generation -{ - int number; - Path path; - time_t creationTime; - Generation() - { - number = -1; - } - operator bool() const - { - return number != -1; - } -}; - -typedef list<Generation> Generations; - - -/* Returns the list of currently present generations for the specified - profile, sorted by generation number. */ -Generations findGenerations(Path profile, int & curGen); - -Path createGeneration(Path profile, Path outPath); - -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 deleted file mode 100644 index a95c4cba93..0000000000 --- a/src/nix-env/user-env.cc +++ /dev/null @@ -1,149 +0,0 @@ -#include "user-env.hh" -#include "util.hh" -#include "derivations.hh" -#include "store-api.hh" -#include "globals.hh" -#include "shared.hh" -#include "eval.hh" -#include "eval-inline.hh" -#include "profiles.hh" - - -namespace nix { - - -DrvInfos queryInstalled(EvalState & state, const Path & userEnv) -{ - DrvInfos elems; - Path manifestFile = userEnv + "/manifest.nix"; - if (pathExists(manifestFile)) { - Value v; - state.evalFile(manifestFile, v); - Bindings bindings; - getDerivations(state, v, "", bindings, elems, false); - } - 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::iterator, i, elems) - if (i->queryDrvPath() != "") - drvsToBuild.insert(i->queryDrvPath()); - - debug(format("building user environment dependencies")); - store->buildPaths(drvsToBuild, state.repair ? bmRepair : bmNormal); - - /* 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 paths, and optionally the derivation path, as well - as the meta attributes. */ - Path drvPath = keepDerivations ? i->queryDrvPath() : ""; - - Value & v(*state.allocValue()); - manifest.list.elems[n++] = &v; - state.mkAttrs(v, 16); - - mkString(*state.allocAttr(v, state.sType), "derivation"); - mkString(*state.allocAttr(v, state.sName), i->name); - if (!i->system.empty()) - mkString(*state.allocAttr(v, state.sSystem), i->system); - mkString(*state.allocAttr(v, state.sOutPath), i->queryOutPath()); - if (drvPath != "") - mkString(*state.allocAttr(v, state.sDrvPath), i->queryDrvPath()); - - // Copy each output. - DrvInfo::Outputs outputs = i->queryOutputs(); - Value & vOutputs = *state.allocAttr(v, state.sOutputs); - state.mkList(vOutputs, outputs.size()); - unsigned int m = 0; - foreach (DrvInfo::Outputs::iterator, j, outputs) { - mkString(*(vOutputs.list.elems[m++] = state.allocValue()), j->first); - Value & vOutputs = *state.allocAttr(v, state.symbols.create(j->first)); - state.mkAttrs(vOutputs, 2); - mkString(*state.allocAttr(vOutputs, state.sOutPath), j->second); - - /* This is only necessary when installing store paths, e.g., - `nix-env -i /nix/store/abcd...-foo'. */ - store->addTempRoot(j->second); - store->ensurePath(j->second); - - references.insert(j->second); - } - - // Copy the meta attributes. - Value & vMeta = *state.allocAttr(v, state.sMeta); - state.mkAttrs(vMeta, 16); - StringSet metaNames = i->queryMetaNames(); - foreach (StringSet::iterator, j, metaNames) { - Value * v = i->queryMeta(*j); - if (!v) continue; - vMeta.attrs->push_back(Attr(state.symbols.create(*j), v)); - } - vMeta.attrs->sort(); - v.attrs->sort(); - - 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); - - /* Get the environment builder expression. */ - Value envBuilder; - state.evalFile(state.findFile("nix/buildenv.nix"), envBuilder); - - /* Construct a Nix expression that calls the user environment - builder with the manifest as argument. */ - Value args, topLevel; - state.mkAttrs(args, 3); - mkString(*state.allocAttr(args, state.symbols.create("manifest")), - manifestFile, singleton<PathSet>(manifestFile)); - args.attrs->push_back(Attr(state.symbols.create("derivations"), &manifest)); - args.attrs->sort(); - mkApp(topLevel, envBuilder, args); - - /* Evaluate it. */ - debug("evaluating user environment builder"); - state.forceValue(topLevel); - PathSet context; - Path topLevelDrv = state.coerceToPath(*topLevel.attrs->find(state.sDrvPath)->value, context); - Path topLevelOut = state.coerceToPath(*topLevel.attrs->find(state.sOutPath)->value, context); - - /* Realise the resulting store expression. */ - debug("building user environment"); - store->buildPaths(singleton<PathSet>(topLevelDrv), state.repair ? bmRepair : bmNormal); - - /* 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, topLevelOut); - switchLink(profile, generation); - - return true; -} - - -} diff --git a/src/nix-env/user-env.hh b/src/nix-env/user-env.hh deleted file mode 100644 index f188efe9b4..0000000000 --- a/src/nix-env/user-env.hh +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#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); - -} |