about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--configure.ac3
-rw-r--r--corepkgs/Makefile.am8
-rw-r--r--corepkgs/nar/nar.fix8
-rw-r--r--corepkgs/nar/nar.sh3
-rw-r--r--scripts/Makefile.am2
-rw-r--r--scripts/nix-pull2
-rw-r--r--scripts/nix-push60
-rw-r--r--src/fix.cc8
-rw-r--r--src/fstate.cc22
-rw-r--r--src/globals.cc4
-rw-r--r--src/globals.hh2
-rw-r--r--src/nix.cc24
-rw-r--r--src/shared.cc1
-rw-r--r--src/store.cc51
-rw-r--r--src/store.hh8
16 files changed, 154 insertions, 54 deletions
diff --git a/Makefile.am b/Makefile.am
index 83a04399a926..2bed3f3bbcfa 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1 +1 @@
-SUBDIRS = src scripts
+SUBDIRS = src scripts corepkgs
diff --git a/configure.ac b/configure.ac
index e3b0f0c6e04c..110d8f0e12c0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -13,9 +13,10 @@ AC_PROG_RANLIB
 
 # Unix shell scripting should die a slow and painful death.
 AC_DEFINE_UNQUOTED(NIX_STORE_DIR, "$(eval echo $prefix/store)", Nix store directory.)
+AC_DEFINE_UNQUOTED(NIX_DATA_DIR, "$(eval echo $datadir)", Nix data directory.)
 AC_DEFINE_UNQUOTED(NIX_STATE_DIR, "$(eval echo $localstatedir/nix)", Nix state directory.)
 AC_DEFINE_UNQUOTED(NIX_LOG_DIR, "$(eval echo $localstatedir/log/nix)", Nix log file directory.)
 
 AM_CONFIG_HEADER([config.h])
-AC_CONFIG_FILES([Makefile src/Makefile scripts/Makefile])
+AC_CONFIG_FILES([Makefile src/Makefile scripts/Makefile corepkgs/Makefile])
 AC_OUTPUT
diff --git a/corepkgs/Makefile.am b/corepkgs/Makefile.am
new file mode 100644
index 000000000000..9ce9c8c790eb
--- /dev/null
+++ b/corepkgs/Makefile.am
@@ -0,0 +1,8 @@
+install-data-local:
+	$(INSTALL) -d $(datadir)/fix
+	$(INSTALL) -d $(datadir)/fix/fetchurl
+	$(INSTALL_DATA) fetchurl/fetchurl.fix $(datadir)/fix/fetchurl
+	$(INSTALL_DATA) fetchurl/fetchurl.sh $(datadir)/fix/fetchurl
+	$(INSTALL) -d $(datadir)/fix/nar
+	$(INSTALL_DATA) nar/nar.fix $(datadir)/fix/nar
+	$(INSTALL_DATA) nar/nar.sh $(datadir)/fix/nar
diff --git a/corepkgs/nar/nar.fix b/corepkgs/nar/nar.fix
new file mode 100644
index 000000000000..3db6a48a0838
--- /dev/null
+++ b/corepkgs/nar/nar.fix
@@ -0,0 +1,8 @@
+Function(["path", "name"],
+  Package(
+    [ ("name", Var("name"))
+    , ("build", Relative("nar/nar.sh"))
+    , ("path", Var("path"))
+    ]
+  )
+)
\ No newline at end of file
diff --git a/corepkgs/nar/nar.sh b/corepkgs/nar/nar.sh
new file mode 100644
index 000000000000..6ffcf63224a8
--- /dev/null
+++ b/corepkgs/nar/nar.sh
@@ -0,0 +1,3 @@
+#! /bin/sh
+
+/tmp/nix/bin/nix --dump --file "$path" > $out || exit 1
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index cf70f1574464..e4602f2a1fc9 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -1,5 +1,5 @@
 bin_SCRIPTS = nix-switch nix-collect-garbage \
- nix-pull-prebuilts nix-push-prebuilts
+ nix-pull nix-push
 
 install-exec-local:
 	$(INSTALL) -d $(sysconfdir)/profile.d
diff --git a/scripts/nix-pull b/scripts/nix-pull
new file mode 100644
index 000000000000..0b09c8e00a1b
--- /dev/null
+++ b/scripts/nix-pull
@@ -0,0 +1,2 @@
+#! /usr/bin/perl -w
+
diff --git a/scripts/nix-push b/scripts/nix-push
new file mode 100644
index 000000000000..14b7e2834675
--- /dev/null
+++ b/scripts/nix-push
@@ -0,0 +1,60 @@
+#! /usr/bin/perl -w
+
+my @pushlist;
+
+foreach my $hash (@ARGV) {
+
+    die unless $hash =~ /^([0-9a-z]{32})$/;
+
+    # Get all paths referenced by the normalisation of the given 
+    # fstate expression.
+    my @paths;
+    open PATHS, "nix -qrh $hash 2> /dev/null |" or die "nix -qrh";
+    while (<PATHS>) {
+	chomp;
+	next unless /^\//;
+	push @paths, $_;
+    }
+    close PATHS;
+
+    # For each path, create a Fix expression that turns the path into
+    # a Nix archive.
+    foreach my $path (@paths) {
+
+	# Hash the path.
+	my $phash = `nix-hash $path`;
+	$? and die "nix-hash";
+	chomp $phash;
+	die unless $phash =~ /^([0-9a-z]{32})$/;
+
+	# Construct a Fix expression that creates a Nar archive.
+	my $fixexpr = 
+          "App(IncludeFix(\"nar/nar.fix\"), " .
+          "[ (\"path\", Path(\"$path\", Hash(\"$phash\"), [Include(\"$hash\")]))" .
+          ", (\"name\", \"$phash.nar\")" .
+          "])";
+	
+	my $fixfile = "/tmp/nix-push-tmp.fix";
+	open FIX, ">$fixfile";
+	print FIX $fixexpr;
+	close FIX;
+
+	# Instantiate a Nix expression from the Fix expression.
+	my $nhash = `fix $fixfile`;
+	$? and die "instantiating Nix archive expression";
+	chomp $nhash;
+	die unless $nhash =~ /^([0-9a-z]{32})$/;
+
+	# Realise the Nix expression.
+	my $npath = `nix -qph $nhash 2> /dev/null`;
+	$? and die "creating Nix archive";
+	chomp $npath;
+
+	push @pushlist, $npath;
+
+	print "$path -> $npath\n";
+    }
+}
+
+# Push the prebuilts to the server. !!! FIXME
+system "rsync -av -e ssh @pushlist eelco\@losser.st-lab.cs.uu.nl:/home/eelco/public_html/nix-dist/";
diff --git a/src/fix.cc b/src/fix.cc
index 9e5b8b5d416a..5c4297bfb760 100644
--- a/src/fix.cc
+++ b/src/fix.cc
@@ -15,6 +15,8 @@ static Strings searchDirs;
 
 static string searchPath(string relPath)
 {
+    if (string(relPath, 0, 1) == "/") return relPath;
+
     for (Strings::iterator i = searchDirs.begin();
          i != searchDirs.end(); i++)
     {
@@ -218,7 +220,10 @@ static Expr evalExpr(Expr e)
 
 static Expr evalFile(string relPath)
 {
-    Expr e = ATreadFromNamedFile(searchPath(relPath).c_str());
+    string path = searchPath(relPath);
+    Expr e = ATreadFromNamedFile(path.c_str());
+    if (!e) 
+        throw Error(format("unable to read a term from `%1%'") % path);
     return evalExpr(e);
 }
 
@@ -228,6 +233,7 @@ void run(Strings args)
     Strings files;
 
     searchDirs.push_back(".");
+    searchDirs.push_back(nixDataDir + "/fix");
     
     for (Strings::iterator it = args.begin();
          it != args.end(); )
diff --git a/src/fstate.cc b/src/fstate.cc
index e289ca7b1958..fdd43d1b1384 100644
--- a/src/fstate.cc
+++ b/src/fstate.cc
@@ -149,7 +149,7 @@ Hash hashTerm(ATerm t)
 
 ATerm termFromHash(const Hash & hash, string * p)
 {
-    string path = queryPathByHash(hash);
+    string path = expandHash(hash);
     if (p) *p = path;
     ATerm t = ATreadFromNamedFile(path.c_str());
     if (!t) throw Error(format("cannot read aterm %1%") % path);
@@ -253,26 +253,6 @@ static FState realise(FState fs, StringSet & paths)
         /* Expand the hash into the target path. */
         expandHash(hash, path);
 
-#if 0
-        /* Perhaps the path already exists and has the right hash? */
-        if (pathExists(path)) {
-
-            if (hash != hashPath(path))
-                throw Error(format("path %1% exists, but does not have hash %2%")
-                    % path % (string) hash);
-
-            debug(format("path %1% already has hash %2%")
-                % path % (string) hash);
-
-        } else {
-            
-            /* Do we know a path with that hash?  If so, copy it. */
-            string path2 = queryPathByHash(hash);
-            copyPath(path2, path);
-            
-        }
-#endif
-        
         return nf;
     }
 
diff --git a/src/globals.cc b/src/globals.cc
index 40a5a981b871..9893d7ad22b4 100644
--- a/src/globals.cc
+++ b/src/globals.cc
@@ -4,8 +4,11 @@
 
 string dbHash2Paths = "hash2paths";
 string dbSuccessors = "successors";
+string dbSubstitutes = "substitutes";
+
 
 string nixStore = "/UNINIT";
+string nixDataDir = "/UNINIT";
 string nixLogDir = "/UNINIT";
 string nixDB = "/UNINIT";
 
@@ -14,4 +17,5 @@ void initDB()
 {
     createDB(nixDB, dbHash2Paths);
     createDB(nixDB, dbSuccessors);
+    createDB(nixDB, dbSubstitutes);
 }
diff --git a/src/globals.hh b/src/globals.hh
index 8d8c63bd7565..0668ac40e57e 100644
--- a/src/globals.hh
+++ b/src/globals.hh
@@ -52,6 +52,8 @@ extern string dbSubstitutes;
    derived files. */
 extern string nixStore;
 
+extern string nixDataDir; /* !!! fix */
+
 /* nixLogDir is the directory where we log various operations. */ 
 extern string nixLogDir;
 
diff --git a/src/nix.cc b/src/nix.cc
index d6f2db4fefd1..4721563fdff5 100644
--- a/src/nix.cc
+++ b/src/nix.cc
@@ -37,7 +37,7 @@ static ArgType argType = atpUnknown;
 
    Source selection for --install, --dump:
 
-     --file / -f: by file name
+     --file / -f: by file name  !!! -> path
      --hash / -h: by hash
 
    Query flags:
@@ -87,6 +87,12 @@ 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)
@@ -98,7 +104,7 @@ static void opInstall(Strings opFlags, Strings opArgs)
          it != opArgs.end(); it++)
     {
         StringSet paths;
-        realiseFState(termFromHash(argToHash(*it)), paths);
+        realiseFState(hash2fstate(argToHash(*it)), paths);
     }
 }
 
@@ -157,14 +163,16 @@ static void opQuery(Strings opFlags, Strings opArgs)
 
         switch (query) {
 
-        case qPath:
+        case qPath: {
+            StringSet refs;
             cout << format("%s\n") % 
-                (string) fstatePath(termFromHash(hash));
+                (string) fstatePath(realiseFState(termFromHash(hash), refs));
             break;
+        }
 
         case qRefs: {
             StringSet refs;
-            FState fs = ATmake("Include(<str>)", ((string) hash).c_str());
+            FState fs = hash2fstate(hash);
             fstateRefs(realiseFState(fs, refs), refs);
             for (StringSet::iterator j = refs.begin(); 
                  j != refs.end(); j++)
@@ -203,10 +211,8 @@ static void opDump(Strings opFlags, Strings opArgs)
     string arg = *opArgs.begin();
     string path;
     
-    if (argType == atpHash)
-        path = queryPathByHash(parseHash(arg));
-    else if (argType == atpPath)
-        path = arg;
+    if (argType == atpHash) path = expandHash(parseHash(arg));
+    else if (argType == atpPath) path = arg;
 
     dumpPath(path, sink);
 }
diff --git a/src/shared.cc b/src/shared.cc
index bd165ce9781b..bfd7498de16d 100644
--- a/src/shared.cc
+++ b/src/shared.cc
@@ -16,6 +16,7 @@ static void initAndRun(int argc, char * * argv)
 {
     /* Setup Nix paths. */
     nixStore = NIX_STORE_DIR;
+    nixDataDir = NIX_DATA_DIR;
     nixLogDir = NIX_LOG_DIR;
     nixDB = (string) NIX_STATE_DIR + "/nixstate.db";
 
diff --git a/src/store.cc b/src/store.cc
index 38e059a294b5..5a3a4e0678fe 100644
--- a/src/store.cc
+++ b/src/store.cc
@@ -131,25 +131,53 @@ bool isInPrefix(const string & path, const string & _prefix)
 }
 
 
-static string queryPathByHashPrefix(Hash hash, const string & prefix)
+string expandHash(const Hash & hash, const string & target,
+    const string & prefix)
 {
     Strings paths;
 
+    if (!target.empty() && !isInPrefix(target, prefix))
+        abort();
+
     if (!queryListDB(nixDB, dbHash2Paths, hash, paths))
         throw Error(format("no paths known with hash `%1%'") % (string) hash);
 
-    /* Arbitrarily pick the first one that exists and still hash the
-       right hash. */
+    /* !!! we shouldn't check for staleness by default --- too slow */
+
+    /* Pick one equal to `target'. */
+    if (!target.empty()) {
+
+        for (Strings::iterator i = paths.begin();
+             i != paths.end(); i++)
+        {
+            string path = *i;
+            try {
+                if (path == target && hashPath(path) == hash)
+                    return path;
+            } catch (Error & e) {
+                debug(format("stale path: %1%") % e.msg());
+                /* try next one */
+            }
+        }
+        
+    }
 
+    /* Arbitrarily pick the first one that exists and isn't stale. */
     for (Strings::iterator it = paths.begin();
          it != paths.end(); it++)
     {
         string path = *it;
         try {
-            if (isInPrefix(path, prefix) && hashPath(path) == hash)
-                return path;
+            if (isInPrefix(path, prefix) && hashPath(path) == hash) {
+                if (target.empty())
+                    return path;
+                else {
+                    copyPath(path, target);
+                    return target;
+                }
+            }
         } catch (Error & e) {
-            debug(format("checking hash: %1%") % e.msg());
+            debug(format("stale path: %1%") % e.msg());
             /* try next one */
         }
     }
@@ -157,16 +185,7 @@ static string queryPathByHashPrefix(Hash hash, const string & prefix)
     throw Error(format("all paths with hash `%1%' are stale") % (string) hash);
 }
 
-
-string expandHash(const Hash & hash, const string & outPath = "")
-{
     
-string queryPathByHash(Hash hash)
-{
-    return queryPathByHashPrefix(hash, "/");
-}
-
-
 void addToStore(string srcPath, string & dstPath, Hash & hash)
 {
     srcPath = absPath(srcPath);
@@ -174,7 +193,7 @@ void addToStore(string srcPath, string & dstPath, Hash & hash)
     hash = hashPath(srcPath);
 
     try {
-        dstPath = queryPathByHashPrefix(hash, nixStore);
+        dstPath = expandHash(hash, "", nixStore);
         return;
     } catch (...) {
     }
diff --git a/src/store.hh b/src/store.hh
index f747b7ee3aa8..8b02cba99681 100644
--- a/src/store.hh
+++ b/src/store.hh
@@ -13,15 +13,15 @@ void copyPath(string src, string dst);
 /* Register a path keyed on its hash. */
 Hash registerPath(const string & path, Hash hash = Hash());
 
-/* Return a path whose contents have the given hash.  If outPath is
-   not empty, ensure that such a path is realised in outPath (if
+/* Return a path whose contents have the given hash.  If target is
+   not empty, ensure that such a path is realised in target (if
    necessary by copying from another location).  If prefix is not
    empty, only return a path that is an descendent of prefix. 
 
    If no path with the given hash is known to exist in the file
-   system, ...
+   system, 
 */
-string expandHash(const Hash & hash, const string & outPath = "",
+string expandHash(const Hash & hash, const string & target = "",
     const string & prefix = "/");
 
 /* Copy a file to the nixStore directory and register it in dbRefs.