about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2003-05-25T22·42+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2003-05-25T22·42+0000
commit7dd91d3779b4f806ac0085e0ccc60416d81c1148 (patch)
treee4c5f7e8d8978df671050fae0c25639cca79e251 /src
parent0ef4b6d0f8dcaec093e3db366b6dfb6ba47f73a6 (diff)
* Prebuilt package sharing. We allow transparent binary deployment by
  sharing package directories (i.e., the result of building a Nix
  descriptor).

  `nix-pull-prebuilts' obtains a list of all known prebuilts by
  consulting the paths and URLs specified in
  $prefix/etc/nix/prebuilts.conf.  The mappings ($pkghash,
  $prebuilthash) and ($prebuilthash, $location) are registered with
  Nix so that it can use the prebuilt with hash $prebuilthash when
  installing a package with hash $pkghash by downloading and unpacking
  $location.

  `nix-push-prebuilts' creates prebuilts for all packages for which no
  prebuilt is known to exist.  It can then optionally upload these
  to the network through rsync.

  `nix-[pull|push]-prebuilts' just provide a policy.  Nix provides the
  mechanism through the `nix [export|regprebuilt|regurl]' commands.


Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am3
-rw-r--r--src/fix.cc69
-rw-r--r--src/nix.cc62
-rw-r--r--src/util.hh36
4 files changed, 112 insertions, 58 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index d6dbdcb734..31fad89258 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,5 +13,8 @@ install-data-local:
 	$(INSTALL) -d $(localstatedir)/nix/descriptors
 	$(INSTALL) -d $(localstatedir)/nix/sources
 	$(INSTALL) -d $(localstatedir)/nix/links
+	$(INSTALL) -d $(localstatedir)/nix/prebuilts
+	$(INSTALL) -d $(localstatedir)/nix/prebuilts/imports
+	$(INSTALL) -d $(localstatedir)/nix/prebuilts/exports
 	$(INSTALL) -d $(prefix)/pkg
 	$(bindir)/nix init
diff --git a/src/fix.cc b/src/fix.cc
index 052c1d4c91..286b552c38 100644
--- a/src/fix.cc
+++ b/src/fix.cc
@@ -13,7 +13,6 @@ extern "C" {
 
 
 static string nixDescriptorDir;
-static string nixSourcesDir;
 
 
 static bool verbose = false;
@@ -33,46 +32,6 @@ void registerFile(string filename)
         throw Error("cannot register " + filename + " with Nix");
 }
 
-
-/* Return the directory part of the given path, i.e., everything
-   before the final `/'. */
-string dirOf(string s)
-{
-    unsigned int pos = s.rfind('/');
-    if (pos == string::npos) throw Error("invalid file name");
-    return string(s, 0, pos);
-}
-
-
-/* Return the base name of the given path, i.e., everything following
-   the final `/'. */
-string baseNameOf(string s)
-{
-    unsigned int pos = s.rfind('/');
-    if (pos == string::npos) throw Error("invalid file name");
-    return string(s, pos + 1);
-}
-
-
-/* Download object referenced by the given URL into the sources
-   directory.  Return the file name it was downloaded to. */
-string fetchURL(string url)
-{
-    string filename = baseNameOf(url);
-    string fullname = nixSourcesDir + "/" + filename;
-    struct stat st;
-    if (stat(fullname.c_str(), &st)) {
-        /* !!! quoting */
-        string shellCmd =
-            "cd " + nixSourcesDir + " && wget --quiet -N \"" + url + "\"";
-        int res = system(shellCmd.c_str());
-        if (WEXITSTATUS(res) != 0)
-            throw Error("cannot fetch " + url);
-    }
-    return fullname;
-}
-
-
 Error badTerm(const string & msg, ATerm e)
 {
     char * s = ATwriteToString(e);
@@ -120,7 +79,7 @@ bool evaluateBool(ATerm e, EvalContext ctx)
 ATerm evaluate(ATerm e, EvalContext ctx)
 {
     char * s;
-    ATerm e2;
+    ATerm e2, e3;
     ATerm eCond, eTrue, eFalse;
 
     /* Check for normal forms first. */
@@ -166,6 +125,7 @@ ATerm evaluate(ATerm e, EvalContext ctx)
             instantiateDescriptor(filename, ctx).c_str());
     }
 
+#if 0
     /* `Source' copies the specified file to nixSourcesDir, registers
        it with Nix, and returns the hash of the file. */
     else if (ATmatch(e, "Source(<term>)", &e2)) {
@@ -185,15 +145,29 @@ ATerm evaluate(ATerm e, EvalContext ctx)
         registerFile(target);
         return ATmake("File(<str>)", hashFile(target).c_str());
     }
+#endif
+
+    /* `Local' registers a file with Nix, and returns the file's
+       hash. */
+    else if (ATmatch(e, "Local(<term>)", &e2)) {
+        string filename = absPath(evaluateStr(e2, ctx), ctx.dir); /* !!! */
+        string hash = hashFile(filename);
+        return ATmake("File(<str>)", hash.c_str());
+    }
 
-    /* `Url' fetches a file from the network, caching it in
-       nixSourcesDir and returning the file name. */
-    else if (ATmatch(e, "Url(<term>)", &e2)) {
-        string url = evaluateStr(e2, ctx);
+    /* `Url' registers a mapping from a hash to an url with Nix, and
+       returns the hash. */
+    else if (ATmatch(e, "Url(<term>, <term>)", &e2, &e3)) {
+        string hash = evaluateStr(e2, ctx);
+        checkHash(hash);
+        string url = evaluateStr(e3, ctx);
+#if 0
         if (verbose)
             cerr << "fetching " << url << endl;
         string filename = fetchURL(url);
-        return ATmake("Str(<str>)", filename.c_str());
+#endif
+        /* !!! register */
+        return ATmake("File(<str>)", hash.c_str());
     }
 
     /* `If' provides conditional evaluation. */
@@ -329,7 +303,6 @@ void run(Strings::iterator argCur, Strings::iterator argEnd)
     if (homeDir) nixHomeDir = homeDir;
 
     nixDescriptorDir = nixHomeDir + "/var/nix/descriptors";
-    nixSourcesDir = nixHomeDir + "/var/nix/sources";
 
     for ( ; argCur != argEnd; argCur++) {
         string arg(*argCur);
diff --git a/src/nix.cc b/src/nix.cc
index 973c36727a..cfe879952c 100644
--- a/src/nix.cc
+++ b/src/nix.cc
@@ -28,6 +28,9 @@ static string dbInstPkgs = "pkginst";
 static string dbPrebuilts = "prebuilts";
 
 
+static string nixSourcesDir;
+
+
 /* Wrapper classes that ensures that the database is closed upon
    object destruction. */
 class Db2 : public Db 
@@ -435,9 +438,9 @@ void exportPkgs(string outDir,
         string pkgDir = getPkg(hash);
         string tmpFile = outDir + "/export_tmp";
 
-        string cmd = "cd " + pkgDir + " && tar cvfj " + tmpFile + " .";
+        string cmd = "cd " + pkgDir + " && tar cfj " + tmpFile + " .";
         int res = system(cmd.c_str()); // !!! escaping
-        if (WEXITSTATUS(res) != 0)
+        if (!WIFEXITED(res) || WEXITSTATUS(res) != 0)
             throw Error("cannot tar " + pkgDir);
 
         string prebuiltHash = hashFile(tmpFile);
@@ -458,10 +461,12 @@ void regPrebuilt(string pkgHash, string prebuiltHash)
 }
 
 
-void registerFile(string filename)
+string registerFile(string filename)
 {
     filename = absPath(filename);
-    setDB(dbRefs, hashFile(filename), filename);
+    string hash = hashFile(filename);
+    setDB(dbRefs, hash, filename);
+    return hash;
 }
 
 
@@ -618,8 +623,46 @@ void printGraph(Strings::iterator first, Strings::iterator last)
 }
 
 
-void run(Strings args)
+/* Download object referenced by the given URL into the sources
+   directory.  Return the file name it was downloaded to. */
+string fetchURL(string url)
+{
+    string filename = baseNameOf(url);
+    string fullname = nixSourcesDir + "/" + filename;
+    struct stat st;
+    if (stat(fullname.c_str(), &st)) {
+        /* !!! quoting */
+        string shellCmd =
+            "cd " + nixSourcesDir + " && wget --quiet -N \"" + url + "\"";
+        int res = system(shellCmd.c_str());
+        if (WEXITSTATUS(res) != 0)
+            throw Error("cannot fetch " + url);
+    }
+    return fullname;
+}
+
+
+void fetch(string id)
 {
+    string fn;
+
+    /* Fetch the object referenced by id. */
+    if (isHash(id)) {
+        throw Error("not implemented");
+    } else {
+        fn = fetchURL(id);
+    }
+
+    /* Register it by hash. */
+    string hash = registerFile(fn);
+    cout << hash << endl;
+}
+
+
+void fetch(Strings::iterator first, Strings::iterator last)
+{
+    for (Strings::iterator it = first; it != last; it++)
+        fetch(*it);
 }
 
 
@@ -675,6 +718,11 @@ Subcommands:
 
   graph HASH...
     Like closure, but print a dot graph specification.
+
+  fetch ID...  
+    Fetch the objects identified by ID and place them in the Nix
+    sources directory.  ID can be a hash or URL.  Print out the hash
+    of the object.
 ";
 }
 
@@ -686,6 +734,8 @@ void run(Strings::iterator argCur, Strings::iterator argEnd)
     char * homeDir = getenv(nixHomeDirEnvVar.c_str());
     if (homeDir) nixHomeDir = homeDir;
 
+    nixSourcesDir = nixHomeDir + "/var/nix/sources";
+
     /* Parse the global flags. */
     for ( ; argCur != argEnd; argCur++) {
         string arg(*argCur);
@@ -742,6 +792,8 @@ void run(Strings::iterator argCur, Strings::iterator argEnd)
         printClosure(argCur, argEnd);
     } else if (cmd == "graph") {
         printGraph(argCur, argEnd);
+    } else if (cmd == "fetch") {
+        fetch(argCur, argEnd);
     } else
         throw UsageError("unknown command: " + string(cmd));
 }
diff --git a/src/util.hh b/src/util.hh
index fb405b0f12..9b3f212de3 100644
--- a/src/util.hh
+++ b/src/util.hh
@@ -85,17 +85,22 @@ string printHash(unsigned char * buf)
 
     
 /* Verify that a reference is valid (that is, is a MD5 hash code). */
-void checkHash(const string & s)
+bool isHash(const string & s)
 {
-    string err = "invalid reference: " + s;
-    if (s.length() != 32)
-        throw BadRefError(err);
+    if (s.length() != 32) return false;
     for (int i = 0; i < 32; i++) {
         char c = s[i];
         if (!((c >= '0' && c <= '9') ||
               (c >= 'a' && c <= 'f')))
-            throw BadRefError(err);
+            return false;
     }
+    return true;
+}
+
+
+void checkHash(const string & s)
+{
+    if (!isHash(s)) throw BadRefError("invalid reference: " + s);
 }
 
 
@@ -113,4 +118,25 @@ string hashFile(string filename)
 }
 
 
+
+/* Return the directory part of the given path, i.e., everything
+   before the final `/'. */
+string dirOf(string s)
+{
+    unsigned int pos = s.rfind('/');
+    if (pos == string::npos) throw Error("invalid file name");
+    return string(s, 0, pos);
+}
+
+
+/* Return the base name of the given path, i.e., everything following
+   the final `/'. */
+string baseNameOf(string s)
+{
+    unsigned int pos = s.rfind('/');
+    if (pos == string::npos) throw Error("invalid file name");
+    return string(s, pos + 1);
+}
+
+
 #endif /* !__UTIL_H */