about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libexpr/get-drvs.cc44
-rw-r--r--src/libexpr/get-drvs.hh1
-rw-r--r--src/nix-env/help.txt2
-rw-r--r--src/nix-env/main.cc5
4 files changed, 37 insertions, 15 deletions
diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc
index 05b4897cf75f..c7fc52db15e5 100644
--- a/src/libexpr/get-drvs.cc
+++ b/src/libexpr/get-drvs.cc
@@ -58,7 +58,7 @@ typedef set<Expr> Exprs;
    it makes sense for the caller to recursively search for derivations
    in `e'. */
 static bool getDerivation(EvalState & state, Expr e,
-    DrvInfos & drvs, Exprs & doneExprs)
+    DrvInfos & drvs, Exprs & doneExprs, string attributeName)
 {
     try {
         
@@ -92,6 +92,8 @@ static bool getDerivation(EvalState & state, Expr e,
 
         drv.attrs = attrs;
 
+        drv.attrPath = attributeName;
+
         drvs.push_back(drv);
         return false;
     
@@ -105,15 +107,22 @@ bool getDerivation(EvalState & state, Expr e, DrvInfo & drv)
 {
     Exprs doneExprs;
     DrvInfos drvs;
-    getDerivation(state, e, drvs, doneExprs);
+    getDerivation(state, e, drvs, doneExprs, "");
     if (drvs.size() != 1) return false;
     drv = drvs.front();
     return true;
 }
 
 
+static string addToPath(const string & s1, const string & s2)
+{
+    return s1.empty() ? s2 : s1 + "." + s2;
+}
+
+
 static void getDerivations(EvalState & state, Expr e,
-    DrvInfos & drvs, Exprs & doneExprs, const string & attrPath)
+    DrvInfos & drvs, Exprs & doneExprs, const string & attrPath,
+    const string & pathTaken)
 {
     /* Automatically call functions that have defaults for all
        arguments. */
@@ -129,7 +138,7 @@ static void getDerivations(EvalState & state, Expr e,
         }
         getDerivations(state,
             makeCall(e, makeAttrs(ATermMap(0))),
-            drvs, doneExprs, attrPath);
+            drvs, doneExprs, attrPath, pathTaken);
         return;
     }
 
@@ -160,7 +169,7 @@ static void getDerivations(EvalState & state, Expr e,
     ATermList es;
     DrvInfo drv;
 
-    if (!getDerivation(state, e, drvs, doneExprs)) {
+    if (!getDerivation(state, e, drvs, doneExprs, pathTaken)) {
         if (apType != apNone) throw attrError;
         return;
     }
@@ -175,7 +184,8 @@ static void getDerivations(EvalState & state, Expr e,
             for (ATermMap::const_iterator i = drvMap.begin(); i != drvMap.end(); ++i) {
                 startNest(nest, lvlDebug,
                     format("evaluating attribute `%1%'") % aterm2String(i->key));
-                if (getDerivation(state, i->value, drvs, doneExprs)) {
+                string pathTaken2 = addToPath(pathTaken, aterm2String(i->key));
+                if (getDerivation(state, i->value, drvs, doneExprs, pathTaken2)) {
                     /* If the value of this attribute is itself an
                        attribute set, should we recurse into it?
                        => Only if it has a `recurseForDerivations = true'
@@ -187,7 +197,7 @@ static void getDerivations(EvalState & state, Expr e,
                         queryAllAttrs(e, attrs, false);
                         Expr e2 = attrs.get(toATerm("recurseForDerivations"));
                         if (e2 && evalBool(state, e2))
-                            getDerivations(state, e, drvs, doneExprs, attrPathRest);
+                            getDerivations(state, e, drvs, doneExprs, attrPathRest, pathTaken2);
                     }
                 }
             }
@@ -196,9 +206,10 @@ static void getDerivations(EvalState & state, Expr e,
             if (!e2) throw Error(format("attribute `%1%' in selection path not found") % attr);
             startNest(nest, lvlDebug,
                 format("evaluating attribute `%1%'") % attr);
-            getDerivation(state, e2, drvs, doneExprs);
+            string pathTaken2 = addToPath(pathTaken, attr);
+            getDerivation(state, e2, drvs, doneExprs, pathTaken2);
             if (!attrPath.empty())
-                getDerivations(state, e2, drvs, doneExprs, attrPathRest);
+                getDerivations(state, e2, drvs, doneExprs, attrPathRest, pathTaken2);
         }
         return;
     }
@@ -206,19 +217,22 @@ static void getDerivations(EvalState & state, Expr e,
     if (matchList(e, es)) {
         if (apType != apNone && apType != apIndex) throw attrError;
         if (apType == apNone) {
-            for (ATermIterator i(es); i; ++i) {
+            int n = 0;
+            for (ATermIterator i(es); i; ++i, ++n) {
                 startNest(nest, lvlDebug,
                     format("evaluating list element"));
-                if (getDerivation(state, *i, drvs, doneExprs))
-                    getDerivations(state, *i, drvs, doneExprs, attrPathRest);
+                string pathTaken2 = addToPath(pathTaken, (format("%1%") % n).str());
+                if (getDerivation(state, *i, drvs, doneExprs, pathTaken2))
+                    getDerivations(state, *i, drvs, doneExprs, attrPathRest, pathTaken2);
             }
         } else {
             Expr e2 = ATelementAt(es, attrIndex);
             if (!e2) throw Error(format("list index %1% in selection path not found") % attrIndex);
             startNest(nest, lvlDebug,
                 format("evaluating list element"));
-            if (getDerivation(state, e2, drvs, doneExprs))
-                getDerivations(state, e2, drvs, doneExprs, attrPathRest);
+            string pathTaken2 = addToPath(pathTaken, (format("%1%") % attrIndex).str());
+            if (getDerivation(state, e2, drvs, doneExprs, pathTaken2))
+                getDerivations(state, e2, drvs, doneExprs, attrPathRest, pathTaken2);
         }
         return;
     }
@@ -231,5 +245,5 @@ void getDerivations(EvalState & state, Expr e, DrvInfos & drvs,
     const string & attrPath)
 {
     Exprs doneExprs;
-    getDerivations(state, e, drvs, doneExprs, attrPath);
+    getDerivations(state, e, drvs, doneExprs, attrPath, "");
 }
diff --git a/src/libexpr/get-drvs.hh b/src/libexpr/get-drvs.hh
index 2b88111b2c84..4fb8f43feea9 100644
--- a/src/libexpr/get-drvs.hh
+++ b/src/libexpr/get-drvs.hh
@@ -20,6 +20,7 @@ private:
     
 public:
     string name;
+    string attrPath; /* path towards the derivation */
     string system;
 
     shared_ptr<ATermMap> attrs;
diff --git a/src/nix-env/help.txt b/src/nix-env/help.txt
index 3287bab28eae..a97df87576b3 100644
--- a/src/nix-env/help.txt
+++ b/src/nix-env/help.txt
@@ -48,6 +48,8 @@ Query types:
 
   --status / -s: print installed/present status
   --no-name: hide derivation names
+  --attr-path / -A: shows the unambiguous attribute name of the
+      derivation which can be used when installing with -A
   --system: print the platform type of the derivation 
   --compare-versions / -c: compare version to available or installed
   --drv-path: print path of derivation
diff --git a/src/nix-env/main.cc b/src/nix-env/main.cc
index 633c85b618f7..875cdd7447e8 100644
--- a/src/nix-env/main.cc
+++ b/src/nix-env/main.cc
@@ -724,6 +724,7 @@ static void opQuery(Globals & globals,
 {
     bool printStatus = false;
     bool printName = true;
+    bool printAttrPath = false;
     bool printSystem = false;
     bool printDrvPath = false;
     bool printOutPath = false;
@@ -747,6 +748,8 @@ static void opQuery(Globals & globals,
         else if (*i == "--available" || *i == "-a") source = sAvailable;
         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");
     }
@@ -809,6 +812,8 @@ static void opQuery(Globals & globals,
                     + (subs.size() > 0 ? "S" : "-"));
             }
 
+            if (printAttrPath) columns.push_back(i->attrPath);
+
             if (printName) columns.push_back(i->name);
 
             if (compareVersions) {