about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nix-env/nix-env.cc181
1 files changed, 103 insertions, 78 deletions
diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc
index 89a92fdbb392..ad5a1b095875 100644
--- a/src/nix-env/nix-env.cc
+++ b/src/nix-env/nix-env.cc
@@ -65,7 +65,7 @@ struct Globals
 
 
 typedef void (* Operation) (Globals & globals,
-    Strings opFlags, Strings opArgs);
+    Strings args, Strings opFlags, Strings opArgs);
 
 
 void printHelp()
@@ -74,6 +74,31 @@ void printHelp()
 }
 
 
+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;
@@ -93,7 +118,7 @@ static void getAllExprs(EvalState & state,
         Path path2 = path + "/" + *i;
         if (isNixExpr(path2))
             attrs.set(toATerm(*i), makeAttrRHS(
-                    parseExprFromFile(state, absPath(path2)), makeNoPos()));
+                parseExprFromFile(state, absPath(path2)), makeNoPos()));
         else
             getAllExprs(state, path2, attrs);
     }
@@ -118,9 +143,12 @@ static Expr loadSourceExpr(EvalState & state, const Path & path)
 
 
 static void loadDerivations(EvalState & state, Path nixExprPath,
-    string systemFilter, const ATermMap & autoArgs, DrvInfos & elems)
+    string systemFilter, const ATermMap & autoArgs,
+    const string & pathPrefix, DrvInfos & elems)
 {
-    getDerivations(state, loadSourceExpr(state, nixExprPath), "", autoArgs, elems);
+    getDerivations(state,
+        findAlongAttrPath(state, pathPrefix, autoArgs, loadSourceExpr(state, nixExprPath)),
+        pathPrefix, autoArgs, elems);
 
     /* Filter out all derivations not applicable to the current
        system. */
@@ -394,7 +422,7 @@ static void queryInstSources(EvalState & state,
                Nix expression. */
             DrvInfos allElems;
             loadDerivations(state, instSource.nixExprPath,
-                instSource.systemFilter, instSource.autoArgs, allElems);
+                instSource.systemFilter, instSource.autoArgs, "", allElems);
 
             elems = filterBySelector(state, allElems, args, newestOnly);
     
@@ -570,10 +598,15 @@ static void installDerivations(Globals & globals,
 
 
 static void opInstall(Globals & globals,
-    Strings opFlags, Strings opArgs)
+    Strings args, Strings opFlags, Strings opArgs)
 {
-    if (opFlags.size() > 0)
-        throw UsageError(format("unknown flag `%1%'") % opFlags.front());
+    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 throw UsageError(format("unknown flag `%1%'") % arg);
+    }
 
     installDerivations(globals, opArgs, globals.profile);
 }
@@ -668,16 +701,18 @@ static void upgradeDerivations(Globals & globals,
 
 
 static void opUpgrade(Globals & globals,
-    Strings opFlags, Strings opArgs)
+    Strings args, Strings opFlags, Strings opArgs)
 {
     UpgradeType upgradeType = utLt;
-    for (Strings::iterator i = opFlags.begin();
-         i != opFlags.end(); ++i)
-        if (*i == "--lt") upgradeType = utLt;
-        else if (*i == "--leq") upgradeType = utLeq;
-        else if (*i == "--eq") upgradeType = utEq;
-        else if (*i == "--always") upgradeType = utAlways;
-        else throw UsageError(format("unknown flag `%1%'") % *i);
+    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);
 }
@@ -693,7 +728,7 @@ static void setMetaFlag(EvalState & state, DrvInfo & drv,
 
 
 static void opSetFlag(Globals & globals,
-    Strings opFlags, Strings opArgs)
+    Strings args, Strings opFlags, Strings opArgs)
 {
     if (opFlags.size() > 0)
         throw UsageError(format("unknown flag `%1%'") % opFlags.front());
@@ -732,10 +767,13 @@ static void opSetFlag(Globals & globals,
 
 
 static void opSet(Globals & globals,
-    Strings opFlags, Strings opArgs)
+    Strings args, Strings opFlags, Strings opArgs)
 {
-    if (opFlags.size() > 0)
-        throw UsageError(format("unknown flag `%1%'") % opFlags.front());
+    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);
@@ -788,7 +826,7 @@ static void uninstallDerivations(Globals & globals, DrvNames & selectors,
 
 
 static void opUninstall(Globals & globals,
-    Strings opFlags, Strings opArgs)
+    Strings args, Strings opFlags, Strings opArgs)
 {
     if (opFlags.size() > 0)
         throw UsageError(format("unknown flag `%1%'") % opFlags.front());
@@ -895,9 +933,11 @@ static string colorString(const string & s)
 
 
 static void opQuery(Globals & globals,
-    Strings opFlags, Strings opArgs)
+    Strings args, Strings opFlags, Strings opArgs)
 {
     typedef vector< map<string, string> > ResultSet;
+    Strings remaining;
+    string attrPath;
         
     bool printStatus = false;
     bool printName = true;
@@ -915,45 +955,46 @@ static void opQuery(Globals & globals,
 
     readOnlyMode = true; /* makes evaluation a bit faster */
 
-    for (Strings::iterator i = opFlags.begin();
-         i != opFlags.end(); ++i)
-        if (*i == "--status" || *i == "-s") printStatus = true;
-        else if (*i == "--no-name") printName = false;
-        else if (*i == "--system") printSystem = true;
-        else if (*i == "--description") printDescription = true;
-        else if (*i == "--compare-versions" || *i == "-c") compareVersions = true;
-        else if (*i == "--drv-path") printDrvPath = true;
-        else if (*i == "--out-path") printOutPath = true;
-        else if (*i == "--meta") printMeta = true;
-        else if (*i == "--installed") source = sInstalled;
-        else if (*i == "--available" || *i == "-a") source = sAvailable;
-        else if (*i == "--prebuilt-only" || *i == "-b") prebuiltOnly = true;
-        else if (*i == "--xml") xmlOutput = true;
-        else throw UsageError(format("unknown flag `%1%'") % *i);
-
-    if (globals.instSource.type == srcAttrPath) printAttrPath = true; /* hack */
-
-    if (opArgs.size() == 0) {
-        printMsg(lvlInfo, "warning: you probably meant to specify the argument '*' to show all packages");
+    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 == "--prebuilt-only" || arg == "-b") prebuiltOnly = true;
+        else if (arg == "--xml") xmlOutput = 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);
     }
 
+    if (remaining.size() == 0)
+        printMsg(lvlInfo, "warning: you probably meant to specify the argument '*' to show all packages");
+
     
     /* Obtain derivation information from the specified source. */
     DrvInfos availElems, installedElems;
 
-    if (source == sInstalled || compareVersions || printStatus) {
+    if (source == sInstalled || compareVersions || printStatus)
         installedElems = queryInstalled(globals.state, globals.profile);
-    }
 
-    if (source == sAvailable || compareVersions) {
+    if (source == sAvailable || compareVersions)
         loadDerivations(globals.state, globals.instSource.nixExprPath,
             globals.instSource.systemFilter, globals.instSource.autoArgs,
-            availElems);
-    }
+            attrPath, availElems);
 
     DrvInfos elems = filterBySelector(globals.state,
         source == sInstalled ? installedElems : availElems,
-        opArgs, false);
+        remaining, false);
     
     DrvInfos & otherElems(source == sInstalled ? availElems : installedElems);
 
@@ -1113,7 +1154,7 @@ static void opQuery(Globals & globals,
 
 
 static void opSwitchProfile(Globals & globals,
-    Strings opFlags, Strings opArgs)
+    Strings args, Strings opFlags, Strings opArgs)
 {
     if (opFlags.size() > 0)
         throw UsageError(format("unknown flag `%1%'") % opFlags.front());
@@ -1161,7 +1202,7 @@ static void switchGeneration(Globals & globals, int dstGen)
 
 
 static void opSwitchGeneration(Globals & globals,
-    Strings opFlags, Strings opArgs)
+    Strings args, Strings opFlags, Strings opArgs)
 {
     if (opFlags.size() > 0)
         throw UsageError(format("unknown flag `%1%'") % opFlags.front());
@@ -1177,7 +1218,7 @@ static void opSwitchGeneration(Globals & globals,
 
 
 static void opRollback(Globals & globals,
-    Strings opFlags, Strings opArgs)
+    Strings args, Strings opFlags, Strings opArgs)
 {
     if (opFlags.size() > 0)
         throw UsageError(format("unknown flag `%1%'") % opFlags.front());
@@ -1189,7 +1230,7 @@ static void opRollback(Globals & globals,
 
 
 static void opListGenerations(Globals & globals,
-    Strings opFlags, Strings opArgs)
+    Strings args, Strings opFlags, Strings opArgs)
 {
     if (opFlags.size() > 0)
         throw UsageError(format("unknown flag `%1%'") % opFlags.front());
@@ -1222,7 +1263,7 @@ static void deleteGeneration2(const Path & profile, unsigned int gen)
 
 
 static void opDeleteGenerations(Globals & globals,
-    Strings opFlags, Strings opArgs)
+    Strings args, Strings opFlags, Strings opArgs)
 {
     if (opFlags.size() > 0)
         throw UsageError(format("unknown flag `%1%'") % opFlags.front());
@@ -1260,18 +1301,9 @@ static void opDeleteGenerations(Globals & globals,
 }
 
 
-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++;
-}
-
-
 void run(Strings args)
 {
-    Strings opFlags, opArgs;
+    Strings opFlags, opArgs, remaining;
     Operation op = 0;
     
     Globals globals;
@@ -1293,14 +1325,6 @@ void run(Strings args)
 
         if (arg == "--install" || arg == "-i")
             op = opInstall;
-        else 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 if (parseOptionArg(arg, i, args.end(),
                      globals.state, globals.instSource.autoArgs))
             ;
@@ -1334,14 +1358,15 @@ void run(Strings args)
             printMsg(lvlInfo, "(dry run; not doing anything)");
             globals.dryRun = true;
         }
-        else if (arg == "--preserve-installed" || arg == "-P")
-            globals.preserveInstalled = true;
         else if (arg == "--system-filter")
             globals.instSource.systemFilter = needArg(i, args, arg);
-        else if (arg[0] == '-')
-            opFlags.push_back(arg);
-        else
-            opArgs.push_back(arg);
+        else {
+            remaining.push_back(arg);
+            if (arg[0] == '-') 
+                opFlags.push_back(arg);
+            else
+                opArgs.push_back(arg);
+        }
 
         if (oldOp && oldOp != op)
             throw UsageError("only one operation may be specified");
@@ -1358,7 +1383,7 @@ void run(Strings args)
     
     store = openStore();
 
-    op(globals, opFlags, opArgs);
+    op(globals, remaining, opFlags, opArgs);
 
     printEvalStats(globals.state);
 }