aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/fstate.cc6
-rw-r--r--src/fstate.hh2
-rw-r--r--src/nix.cc25
-rw-r--r--src/store.cc45
-rw-r--r--src/store.hh4
5 files changed, 73 insertions, 9 deletions
diff --git a/src/fstate.cc b/src/fstate.cc
index fdd43d1b1..97532c162 100644
--- a/src/fstate.cc
+++ b/src/fstate.cc
@@ -147,6 +147,12 @@ Hash hashTerm(ATerm t)
}
+FState hash2fstate(Hash hash)
+{
+ return ATmake("Include(<str>)", ((string) hash).c_str());
+}
+
+
ATerm termFromHash(const Hash & hash, string * p)
{
string path = expandHash(hash);
diff --git a/src/fstate.hh b/src/fstate.hh
index 159c7ba46..8a873a5ac 100644
--- a/src/fstate.hh
+++ b/src/fstate.hh
@@ -85,6 +85,8 @@ Error badTerm(const format & f, ATerm t);
/* Hash an aterm. */
Hash hashTerm(ATerm t);
+FState hash2fstate(Hash hash);
+
/* Read an aterm from disk, given its hash. */
ATerm termFromHash(const Hash & hash, string * p = 0);
diff --git a/src/nix.cc b/src/nix.cc
index 4721563fd..53057328d 100644
--- a/src/nix.cc
+++ b/src/nix.cc
@@ -26,6 +26,8 @@ static ArgType argType = atpUnknown;
--add / -A: copy a path to the Nix store
--query / -q: query information
+ --substitute: register a substitute expression
+
--dump: dump a path as a Nix archive
--restore: restore a path from a Nix archive
@@ -87,12 +89,6 @@ static Hash argToHash(const string & arg)
}
-static FState hash2fstate(Hash hash)
-{
- return ATmake("Include(<str>)", ((string) hash).c_str());
-}
-
-
/* Realise (or install) paths from the given Nix fstate
expressions. */
static void opInstall(Strings opFlags, Strings opArgs)
@@ -187,6 +183,21 @@ static void opQuery(Strings opFlags, Strings opArgs)
}
+static void opSubstitute(Strings opFlags, Strings opArgs)
+{
+ if (!opFlags.empty()) throw UsageError("unknown flag");
+ if (opArgs.size() % 2) throw UsageError("expecting even number of arguments");
+
+ for (Strings::iterator i = opArgs.begin();
+ i != opArgs.end(); )
+ {
+ Hash srcHash = parseHash(*i++);
+ Hash subHash = parseHash(*i++);
+ registerSubstitute(srcHash, subHash);
+ }
+}
+
+
/* A sink that writes dump output to stdout. */
struct StdoutSink : DumpSink
{
@@ -277,6 +288,8 @@ void run(Strings args)
op = opAdd;
else if (arg == "--query" || arg == "-q")
op = opQuery;
+ else if (arg == "--substitute")
+ op = opSubstitute;
else if (arg == "--dump")
op = opDump;
else if (arg == "--restore")
diff --git a/src/store.cc b/src/store.cc
index 5a3a4e067..435ac5cc6 100644
--- a/src/store.cc
+++ b/src/store.cc
@@ -7,6 +7,7 @@
#include "globals.hh"
#include "db.hh"
#include "archive.hh"
+#include "fstate.hh"
struct CopySink : DumpSink
@@ -83,6 +84,20 @@ void copyPath(string src, string dst)
}
+void registerSubstitute(const Hash & srcHash, const Hash & subHash)
+{
+ Strings subs;
+ queryListDB(nixDB, dbSubstitutes, srcHash, subs); /* non-existence = ok */
+
+ for (Strings::iterator it = subs.begin(); it != subs.end(); it++)
+ if (parseHash(*it) == subHash) return;
+
+ subs.push_back(subHash);
+
+ setListDB(nixDB, dbSubstitutes, srcHash, subs);
+}
+
+
Hash registerPath(const string & _path, Hash hash)
{
string path(canonPath(_path));
@@ -139,8 +154,7 @@ string expandHash(const Hash & hash, const string & target,
if (!target.empty() && !isInPrefix(target, prefix))
abort();
- if (!queryListDB(nixDB, dbHash2Paths, hash, paths))
- throw Error(format("no paths known with hash `%1%'") % (string) hash);
+ queryListDB(nixDB, dbHash2Paths, hash, paths);
/* !!! we shouldn't check for staleness by default --- too slow */
@@ -181,8 +195,32 @@ string expandHash(const Hash & hash, const string & target,
/* try next one */
}
}
+
+ /* Try to realise the substitutes. */
+
+ Strings subs;
+ queryListDB(nixDB, dbSubstitutes, hash, subs); /* non-existence = ok */
+
+ for (Strings::iterator it = subs.begin(); it != subs.end(); it++) {
+ StringSet dummy;
+ FState nf = realiseFState(hash2fstate(parseHash(*it)), dummy);
+ string path = fstatePath(nf);
+
+ if (hashPath(path) != hash)
+ throw Error(format("bad substitute in `%1%'") % (string) path);
+
+ if (target.empty())
+ return path; /* !!! prefix */
+ else {
+ if (path != target) {
+ copyPath(path, target);
+ registerPath(target, hash);
+ }
+ return target;
+ }
+ }
- throw Error(format("all paths with hash `%1%' are stale") % (string) hash);
+ throw Error(format("cannot expand hash `%1%'") % (string) hash);
}
@@ -193,6 +231,7 @@ void addToStore(string srcPath, string & dstPath, Hash & hash)
hash = hashPath(srcPath);
try {
+ /* !!! should not use the substitutes! */
dstPath = expandHash(hash, "", nixStore);
return;
} catch (...) {
diff --git a/src/store.hh b/src/store.hh
index 8b02cba99..8b41478a2 100644
--- a/src/store.hh
+++ b/src/store.hh
@@ -8,8 +8,12 @@
using namespace std;
+/* Copy a path recursively. */
void copyPath(string src, string dst);
+/* Register a substitute. */
+void registerSubstitute(const Hash & srcHash, const Hash & subHash);
+
/* Register a path keyed on its hash. */
Hash registerPath(const string & path, Hash hash = Hash());