aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nix-env/help.txt5
-rw-r--r--src/nix-env/main.cc135
2 files changed, 106 insertions, 34 deletions
diff --git a/src/nix-env/help.txt b/src/nix-env/help.txt
index cebffc99d..d940bd209 100644
--- a/src/nix-env/help.txt
+++ b/src/nix-env/help.txt
@@ -4,8 +4,9 @@ nix-env [OPTIONS...] [ARGUMENTS...]
Operations:
- --install / -i FILE: add a derivation to the user environment
- --uninstall / -e: remove a derivation to the user environment
+ --install / -i FILE: add derivations to the user environment
+ --uninstall / -e: remove derivations from the user environment
+ --upgrade / -u FILE: upgrade derivation in the user environment
--query / -q: perform a query on an environment or Nix expression
The previous operations take a list of derivation names. The special
diff --git a/src/nix-env/main.cc b/src/nix-env/main.cc
index 9190660cb..fc37f01be 100644
--- a/src/nix-env/main.cc
+++ b/src/nix-env/main.cc
@@ -230,20 +230,71 @@ void createUserEnv(EvalState & state, const DrvInfos & drvs,
}
-typedef map<string, Path> NameMap;
+class DrvName
+{
+ string fullName;
+ string name;
+ string version;
+ unsigned int hits;
+
+public:
+
+ /* Parse a derivation name. The `name' part of a derivation name
+ is everything up to but not including the first dash *not*
+ followed by a letter. The `version' part is the rest
+ (excluding the separating dash). E.g., `apache-httpd-2.0.48'
+ is parsed to (`apache-httpd', '2.0.48'). */
+ DrvName(const string & s) : hits(0)
+ {
+ name = fullName = s;
+ for (unsigned int i = 0; i < s.size(); ++i) {
+ if (s[i] == '-' && i + 1 < s.size() && !isalpha(s[i + 1])) {
+ name = string(s, 0, i);
+ version = string(s, i + 1);
+ break;
+ }
+ }
+ }
+
+ bool matches(DrvName & n)
+ {
+ if (name != "*" && name != n.name) return false;
+ if (version != "" && version != n.version) return false;
+ return true;
+ }
+
+ void hit()
+ {
+ hits++;
+ }
+
+ unsigned int getHits()
+ {
+ return hits;
+ }
+
+ string getFullName()
+ {
+ return fullName;
+ }
+};
-NameMap mapByNames(DrvInfos & drvs)
+typedef list<DrvName> DrvNames;
+
+
+static DrvNames drvNamesFromArgs(const Strings & opArgs)
{
- NameMap nameMap;
- for (DrvInfos::iterator i = drvs.begin(); i != drvs.end(); ++i)
- nameMap[i->second.name] = i->first;
- return nameMap;
+ DrvNames result;
+ for (Strings::const_iterator i = opArgs.begin();
+ i != opArgs.end(); ++i)
+ result.push_back(DrvName(*i));
+ return result;
}
void installDerivations(EvalState & state,
- Path nePath, Strings drvNames, const Path & linkPath)
+ Path nePath, DrvNames & selectors, const Path & linkPath)
{
debug(format("installing derivations from `%1%'") % nePath);
@@ -251,24 +302,29 @@ void installDerivations(EvalState & state,
DrvInfos availDrvs;
loadDerivations(state, nePath, availDrvs);
- NameMap nameMap = mapByNames(availDrvs);
-
/* Filter out the ones we're not interested in. */
DrvInfos selectedDrvs;
- if (drvNames.size() > 0 && drvNames.front() == "*") { /* !!! hack */
- selectedDrvs = availDrvs;
- } else {
- for (Strings::iterator i = drvNames.begin();
- i != drvNames.end(); ++i)
+ for (DrvInfos::iterator i = availDrvs.begin();
+ i != availDrvs.end(); ++i)
+ {
+ DrvName drvName(i->second.name);
+ for (DrvNames::iterator j = selectors.begin();
+ j != selectors.end(); ++j)
{
- NameMap::iterator j = nameMap.find(*i);
- if (j == nameMap.end())
- throw Error(format("unknown derivation `%1%'") % *i);
- else
- selectedDrvs[j->second] = availDrvs[j->second];
+ if (j->matches(drvName)) {
+ j->hit();
+ selectedDrvs.insert(*i);
+ }
}
}
+ /* Check that all selectors have been used. */
+ for (DrvNames::iterator i = selectors.begin();
+ i != selectors.end(); ++i)
+ if (i->getHits() == 0)
+ throw Error(format("selector `%1%' matches no derivations")
+ % i->getFullName());
+
/* Add in the already installed derivations. */
DrvInfos installedDrvs;
queryInstalled(state, installedDrvs, linkPath);
@@ -286,29 +342,40 @@ static void opInstall(Globals & globals,
if (opArgs.size() < 1) throw UsageError("Nix file expected");
Path nePath = opArgs.front();
+ DrvNames drvNames = drvNamesFromArgs(
+ Strings(++opArgs.begin(), opArgs.end()));
+
+ installDerivations(globals.state, nePath, drvNames, globals.linkPath);
+}
+
+
+static void opUpgrade(Globals & globals,
+ Strings opFlags, Strings opArgs)
+{
+ if (opFlags.size() > 0)
+ throw UsageError(format("unknown flags `%1%'") % opFlags.front());
+ if (opArgs.size() < 1) throw UsageError("Nix file expected");
+
+ Path nePath = opArgs.front();
opArgs.pop_front();
- installDerivations(globals.state, nePath,
- Strings(opArgs.begin(), opArgs.end()), globals.linkPath);
}
-void uninstallDerivations(EvalState & state, Strings drvNames,
+void uninstallDerivations(EvalState & state, DrvNames & selectors,
Path & linkPath)
{
DrvInfos installedDrvs;
queryInstalled(state, installedDrvs, linkPath);
- NameMap nameMap = mapByNames(installedDrvs);
-
- for (Strings::iterator i = drvNames.begin();
- i != drvNames.end(); ++i)
+ for (DrvInfos::iterator i = installedDrvs.begin();
+ i != installedDrvs.end(); ++i)
{
- NameMap::iterator j = nameMap.find(*i);
- if (j == nameMap.end())
- throw Error(format("unknown derivation `%1%'") % *i);
- else
- installedDrvs.erase(j->second);
+ DrvName drvName(i->second.name);
+ for (DrvNames::iterator j = selectors.begin();
+ j != selectors.end(); ++j)
+ if (j->matches(drvName))
+ installedDrvs.erase(i);
}
createUserEnv(state, installedDrvs, linkPath);
@@ -321,7 +388,9 @@ static void opUninstall(Globals & globals,
if (opFlags.size() > 0)
throw UsageError(format("unknown flags `%1%'") % opFlags.front());
- uninstallDerivations(globals.state, opArgs, globals.linkPath);
+ DrvNames drvNames = drvNamesFromArgs(opArgs);
+
+ uninstallDerivations(globals.state, drvNames, globals.linkPath);
}
@@ -412,6 +481,8 @@ void run(Strings args)
op = opInstall;
else if (arg == "--uninstall" || arg == "-e")
op = opUninstall;
+ else if (arg == "--upgrade" || arg == "-u")
+ op = opUpgrade;
else if (arg == "--query" || arg == "-q")
op = opQuery;
else if (arg == "--link" || arg == "-l") {