about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2005-02-11T16·56+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2005-02-11T16·56+0000
commit20ce2642fc0052a9f70faf194cc0c31d3f88926e (patch)
tree6c578e87f0453af0522ae97a749e66b40f952669
parent80870d9291813f265a6e078c92aa535ef0b70a47 (diff)
* Refactoring to support different installation sources in nix-env.
* Set the references for the user environment manifest properly.
* Don't copy the manifest (this was accidental).
* Don't store derivation paths in the manifest (maybe this should be
  made optional).  This cleans up the semantics of nix-env, which were
  weird.
* Hash on the output paths of activated components, not on derivation
  paths.  This is because we don't know the derivation path of already
  installed components anymore, and it allows the installation of
  components by store path (skipping Nix expressions entirely).
* Query options `--out-path' and `--drv-path' to show the output and
  derivation paths of components, respectively (the latter replaces
  the `--expr' query).

-rw-r--r--src/libexpr/primops.cc21
-rw-r--r--src/libutil/util.hh8
-rw-r--r--src/nix-env/help.txt3
-rw-r--r--src/nix-env/main.cc152
-rw-r--r--src/nix-env/profiles.cc2
5 files changed, 125 insertions, 61 deletions
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 013eba594743..da9d1e635811 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -94,6 +94,7 @@ static void processBinding(EvalState & state, Expr e, Derivation & drv,
 
     else if (matchAttrs(e, es)) {
         Expr a = queryAttr(e, "type");
+        
         if (a && evalString(state, a) == "derivation") {
             a = queryAttr(e, "drvPath");
             if (!a) throw Error("derivation name missing");
@@ -104,12 +105,22 @@ static void processBinding(EvalState & state, Expr e, Derivation & drv,
             /* !!! supports only single output path */
             Path outPath = evalPath(state, a);
 
-            StringSet ids;
-            ids.insert("out");
-            drv.inputDrvs[drvPath] = ids;
+            drv.inputDrvs[drvPath] = singleton<StringSet>("out");
+            ss.push_back(outPath);
+        }
+
+        else if (a && evalString(state, a) == "storePath") {
+
+            a = queryAttr(e, "outPath");
+            if (!a) throw Error("output path missing");
+            /* !!! supports only single output path */
+            Path outPath = evalPath(state, a);
+
+            drv.inputSrcs.insert(outPath);
             ss.push_back(outPath);
-        } else
-            throw Error("invalid derivation attribute");
+        }
+
+        else throw Error("invalid derivation attribute");
     }
 
     else if (matchPath(e, s)) {
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index b67913862408..2577f79e1b87 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -112,6 +112,14 @@ Path createTempDir();
    not already exist. */
 void writeStringToFile(const Path & path, const string & s);
 
+template<class T, class A>
+T singleton(const A & a)
+{
+    T t;
+    t.insert(a);
+    return t;
+}
+
 
 /* Messages. */
 
diff --git a/src/nix-env/help.txt b/src/nix-env/help.txt
index fe9eca79eb90..4fc1602840c4 100644
--- a/src/nix-env/help.txt
+++ b/src/nix-env/help.txt
@@ -37,7 +37,8 @@ Upgrade flags:
 Query types:
 
   --name: print derivation names (default)
-  --expr: print derivation store expression
+  --drv-path: print path of derivation
+  --out-path: print path of derivation output
   --status / -s: print installed/present status
 
 Query sources:
diff --git a/src/nix-env/main.cc b/src/nix-env/main.cc
index da77e2428808..d45dd2bd8c06 100644
--- a/src/nix-env/main.cc
+++ b/src/nix-env/main.cc
@@ -12,14 +12,31 @@
 #include <ctime>
 
 
+typedef enum {
+    srcNixExprDrvs,
+    srcNixExprs,
+    srcStorePaths,
+    srcProfile,
+    srcUnknown
+} InstallSourceType;
+
+
+struct InstallSourceInfo
+{
+    InstallSourceType type;
+    Path nixExprPath; /* for srcNixExprDrvs, srcNixExprs */
+    Path profile; /* for srcProfile */
+    string systemFilter; /* for srcNixExprDrvs */
+};
+
+
 struct Globals
 {
+    InstallSourceInfo instSource;
     Path profile;
-    Path nixExprPath;
     EvalState state;
     bool dryRun;
     bool preserveInstalled;
-    string systemFilter;
 };
 
 
@@ -64,8 +81,7 @@ bool parseDerivation(EvalState & state, Expr e, DrvInfo & drv)
         drv.system = evalString(state, a);
 
     a = queryAttr(e, "drvPath");
-    if (!a) throw badTerm("derivation path missing", e);
-    drv.drvPath = evalPath(state, a);
+    if (a) drv.drvPath = evalPath(state, a);
 
     a = queryAttr(e, "outPath");
     if (!a) throw badTerm("output path missing", e);
@@ -83,7 +99,7 @@ bool parseDerivations(EvalState & state, Expr e, DrvInfos & drvs)
     e = evalExpr(state, e);
 
     if (parseDerivation(state, e, drv)) 
-        drvs[drv.drvPath] = drv;
+        drvs[drv.outPath] = drv;
 
     else if (matchAttrs(e, es)) {
         ATermMap drvMap;
@@ -91,7 +107,7 @@ bool parseDerivations(EvalState & state, Expr e, DrvInfos & drvs)
         for (ATermIterator i(drvMap.keys()); i; ++i) {
             debug(format("evaluating attribute `%1%'") % *i);
             if (parseDerivation(state, drvMap.get(*i), drv))
-                drvs[drv.drvPath] = drv;
+                drvs[drv.outPath] = drv;
             else
                 parseDerivations(state, drvMap.get(*i), drvs);
         }
@@ -101,7 +117,7 @@ bool parseDerivations(EvalState & state, Expr e, DrvInfos & drvs)
         for (ATermIterator i(es); i; ++i) {
             debug(format("evaluating list element"));
             if (parseDerivation(state, *i, drv))
-                drvs[drv.drvPath] = drv;
+                drvs[drv.outPath] = drv;
             else
                 parseDerivations(state, *i, drvs);
         }
@@ -111,10 +127,10 @@ bool parseDerivations(EvalState & state, Expr e, DrvInfos & drvs)
 }
 
 
-void loadDerivations(EvalState & state, Path nePath, DrvInfos & drvs,
-    string systemFilter)
+static void loadDerivations(EvalState & state, Path nixExprPath,
+    string systemFilter, DrvInfos & drvs)
 {
-    Expr e = parseExprFromFile(state, absPath(nePath));
+    Expr e = parseExprFromFile(state, absPath(nixExprPath));
     if (!parseDerivations(state, e, drvs))
         throw Error("set of derivations expected");
 
@@ -128,6 +144,18 @@ void loadDerivations(EvalState & state, Path nePath, DrvInfos & drvs,
 }
 
 
+static void queryInstSources(EvalState & state,
+    const InstallSourceInfo & instSource, DrvInfos & drvs)
+{
+    switch (instSource.type) {
+        case srcUnknown:
+            loadDerivations(state, instSource.nixExprPath,
+                instSource.systemFilter, drvs);
+            break;
+    }
+}
+
+
 static Path getHomeDir()
 {
     Path homeDir(getEnv("HOME", ""));
@@ -177,43 +205,62 @@ void queryInstalled(EvalState & state, DrvInfos & drvs,
 void createUserEnv(EvalState & state, const DrvInfos & drvs,
     const Path & profile)
 {
+    /* Build the components in the user environment, if they don't
+       exist already. */
+    PathSet drvsToBuild;
+    for (DrvInfos::const_iterator i = drvs.begin(); 
+         i != drvs.end(); ++i)
+        if (i->second.drvPath != "")
+            drvsToBuild.insert(i->second.drvPath);
+
+    debug(format("building user environment dependencies"));
+    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;
     for (DrvInfos::const_iterator i = drvs.begin(); 
          i != drvs.end(); ++i)
     {
-        ATerm t = makeAttrs(ATmakeList5(
+        ATerm t = makeAttrs(ATmakeList4(
             makeBind(toATerm("type"),
                 makeStr(toATerm("derivation")), makeNoPos()),
             makeBind(toATerm("name"),
                 makeStr(toATerm(i->second.name)), makeNoPos()),
             makeBind(toATerm("system"),
                 makeStr(toATerm(i->second.system)), makeNoPos()),
-            makeBind(toATerm("drvPath"),
-                makePath(toATerm(i->second.drvPath)), makeNoPos()),
             makeBind(toATerm("outPath"),
                 makePath(toATerm(i->second.outPath)), makeNoPos())
             ));
-        inputs = ATinsert(inputs, t);
+        manifest = ATinsert(manifest, t);
+        inputs = ATinsert(inputs, makeStr(toATerm(i->second.outPath)));
+        references.insert(i->second.outPath);
     }
 
-    ATerm inputs2 = makeList(ATreverse(inputs));
-
     /* Also write a copy of the list of inputs to the store; we need
        it for future modifications of the environment. */
-    Path inputsFile = addTextToStore("env-inputs", atPrint(inputs2),
-        PathSet() /* !!! incorrect */);
+    Path manifestFile = addTextToStore("env-manifest",
+        atPrint(makeList(ATreverse(manifest))), references);
+
+    printMsg(lvlError, format("manifest is %1%") % manifestFile);
 
     Expr topLevel = makeCall(envBuilder, makeAttrs(ATmakeList3(
         makeBind(toATerm("system"),
             makeStr(toATerm(thisSystem)), makeNoPos()),
-        makeBind(toATerm("derivations"), inputs2, makeNoPos()),
+        makeBind(toATerm("derivations"),
+            makeList(ATreverse(inputs)), makeNoPos()),
         makeBind(toATerm("manifest"),
-            makePath(toATerm(inputsFile)), makeNoPos())
+            makeAttrs(ATmakeList2(
+                makeBind(toATerm("type"),
+                    makeStr(toATerm("storePath")), makeNoPos()),
+                makeBind(toATerm("outPath"),
+                    makePath(toATerm(manifestFile)), makeNoPos())
+                )), makeNoPos())
         )));
 
     /* Instantiate it. */
@@ -224,9 +271,7 @@ void createUserEnv(EvalState & state, const DrvInfos & drvs,
     
     /* Realise the resulting store expression. */
     debug(format("building user environment"));
-    PathSet drvPaths;
-    drvPaths.insert(topLevelDrv.drvPath);
-    buildDerivations(drvPaths);
+    buildDerivations(singleton<PathSet>(topLevelDrv.drvPath));
 
     /* Switch the current user environment to the output path. */
     debug(format("switching to new user environment"));
@@ -237,14 +282,14 @@ void createUserEnv(EvalState & state, const DrvInfos & drvs,
 
 
 static void installDerivations(EvalState & state,
-    Path nePath, DrvNames & selectors, const Path & profile,
-    bool dryRun, bool preserveInstalled, string systemFilter)
+    const InstallSourceInfo & instSource, DrvNames & selectors,
+    const Path & profile, bool dryRun, bool preserveInstalled)
 {
-    debug(format("installing derivations from `%1%'") % nePath);
+    debug(format("installing derivations"));
 
     /* Fetch all derivations from the input file. */
     DrvInfos availDrvs;
-    loadDerivations(state, nePath, availDrvs, systemFilter);
+    queryInstSources(state, instSource, availDrvs);
 
     /* Filter out the ones we're not interested in. */
     DrvInfos selectedDrvs;
@@ -303,9 +348,9 @@ static void opInstall(Globals & globals,
 
     DrvNames drvNames = drvNamesFromArgs(opArgs);
     
-    installDerivations(globals.state, globals.nixExprPath,
+    installDerivations(globals.state, globals.instSource,
         drvNames, globals.profile, globals.dryRun,
-        globals.preserveInstalled, globals.systemFilter);
+        globals.preserveInstalled);
 }
 
 
@@ -313,10 +358,10 @@ typedef enum { utLt, utLeq, utAlways } UpgradeType;
 
 
 static void upgradeDerivations(EvalState & state,
-    Path nePath, DrvNames & selectors, const Path & profile,
-    UpgradeType upgradeType, bool dryRun, string systemFilter)
+    const InstallSourceInfo & instSource, DrvNames & selectors, const Path & profile,
+    UpgradeType upgradeType, bool dryRun)
 {
-    debug(format("upgrading derivations from `%1%'") % nePath);
+    debug(format("upgrading derivations"));
 
     /* Upgrade works as follows: we take all currently installed
        derivations, and for any derivation matching any selector, look
@@ -329,7 +374,7 @@ static void upgradeDerivations(EvalState & state,
 
     /* Fetch all derivations from the input file. */
     DrvInfos availDrvs;
-    loadDerivations(state, nePath, availDrvs, systemFilter);
+    // xxx    loadDerivations(state, nePath, availDrvs, systemFilter);
 
     /* Go through all installed derivations. */
     DrvInfos newDrvs;
@@ -414,9 +459,8 @@ static void opUpgrade(Globals & globals,
 
     DrvNames drvNames = drvNamesFromArgs(opArgs);
     
-    upgradeDerivations(globals.state, globals.nixExprPath,
-        drvNames, globals.profile, upgradeType, globals.dryRun,
-        globals.systemFilter);
+    upgradeDerivations(globals.state, globals.instSource,
+        drvNames, globals.profile, upgradeType, globals.dryRun);
 }
 
 
@@ -511,6 +555,7 @@ static void opQuery(Globals & globals,
     bool printName = true;
     bool printSystem = false;
     bool printDrvPath = false;
+    bool printOutPath = false;
 
     enum { sInstalled, sAvailable } source = sInstalled;
 
@@ -521,7 +566,8 @@ static void opQuery(Globals & globals,
         if (*i == "--status" || *i == "-s") printStatus = true;
         else if (*i == "--no-name") printName = false;
         else if (*i == "--system") printSystem = true;
-        else if (*i == "--expr") printDrvPath = true;
+        else if (*i == "--drv-path") printDrvPath = true;
+        else if (*i == "--out-path") printOutPath = true;
         else if (*i == "--installed") source = sInstalled;
         else if (*i == "--available" || *i == "-a") source = sAvailable;
         else throw UsageError(format("unknown flag `%1%'") % *i);
@@ -536,8 +582,8 @@ static void opQuery(Globals & globals,
             break;
 
         case sAvailable: {
-            loadDerivations(globals.state, globals.nixExprPath,
-                drvs, globals.systemFilter);
+            loadDerivations(globals.state, globals.instSource.nixExprPath,
+                globals.instSource.systemFilter, drvs);
             break;
         }
 
@@ -554,16 +600,10 @@ static void opQuery(Globals & globals,
 
     /* We only need to know the installed paths when we are querying
        the status of the derivation. */
-    PathSet installedPaths; /* output paths of installed drvs */
+    DrvInfos installed; /* installed paths */
     
-    if (printStatus) {
-        DrvInfos installed;
+    if (printStatus)
         queryInstalled(globals.state, installed, globals.profile);
-        
-        for (DrvInfos::iterator i = installed.begin();
-             i != installed.end(); ++i)
-            installedPaths.insert(i->second.outPath);
-    }
             
     /* Print the desired columns. */
     Table table;
@@ -575,8 +615,8 @@ static void opQuery(Globals & globals,
         if (printStatus) {
             Substitutes subs = querySubstitutes(noTxn, i->drvPath);
             columns.push_back(
-                (string) (installedPaths.find(i->outPath)
-                    != installedPaths.end() ? "I" : "-")
+                (string) (installed.find(i->outPath)
+                    != installed.end() ? "I" : "-")
                 + (isValidPath(i->outPath) ? "P" : "-")
                 + (subs.size() > 0 ? "S" : "-"));
         }
@@ -585,7 +625,9 @@ static void opQuery(Globals & globals,
 
         if (printSystem) columns.push_back(i->system);
 
-        if (printDrvPath) columns.push_back(i->drvPath);
+        if (printDrvPath) columns.push_back(i->drvPath == "" ? "-" : i->drvPath);
+        
+        if (printOutPath) columns.push_back(i->outPath);
 
         table.push_back(columns);
     }
@@ -756,10 +798,12 @@ void run(Strings args)
     Operation op = 0;
     
     Globals globals;
-    globals.nixExprPath = getDefNixExprPath();
+    globals.instSource.type = srcUnknown;
+    globals.instSource.nixExprPath = getDefNixExprPath();
+    globals.instSource.systemFilter = thisSystem;
+    
     globals.dryRun = false;
     globals.preserveInstalled = false;
-    globals.systemFilter = thisSystem;
 
     for (Strings::iterator i = args.begin(); i != args.end(); ++i) {
         string arg = *i;
@@ -786,7 +830,7 @@ void run(Strings args)
             ++i;
             if (i == args.end()) throw UsageError(
                 format("`%1%' requires an argument") % arg);
-            globals.nixExprPath = absPath(*i);
+            globals.instSource.nixExprPath = absPath(*i);
         }
         else if (arg == "--switch-profile" || arg == "-S")
             op = opSwitchProfile;
@@ -808,7 +852,7 @@ void run(Strings args)
             ++i;
             if (i == args.end()) throw UsageError(
                 format("`%1%' requires an argument") % arg);
-            globals.systemFilter = *i;
+            globals.instSource.systemFilter = *i;
         }
         else if (arg[0] == '-')
             opFlags.push_back(arg);
diff --git a/src/nix-env/profiles.cc b/src/nix-env/profiles.cc
index abfdf9fede3d..20aaded776e6 100644
--- a/src/nix-env/profiles.cc
+++ b/src/nix-env/profiles.cc
@@ -65,7 +65,7 @@ static void makeNames(const Path & profile, unsigned int num,
     Path & outLink, Path & drvLink)
 {
     Path prefix = (format("%1%-%2%") % profile % num).str();
-    outLink = prefix + "-output";
+    outLink = prefix + "-link";
     drvLink = prefix + "-drv";
 }