about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2008-07-12T18·58+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2008-07-12T18·58+0000
commit15f39aba8ceb2dabc4f019bd1c985ca9d13bfdb4 (patch)
treedd3a35ea37ca84ec5c978f3ecd661ad66dab6edf
parent7cd88b1dec29f33188e789d780ec2e4ebb155d20 (diff)
* Quick prototype of a substituter that copies paths from other Nix
  stores (typically remote Nix stores mounted via e.g. NFS, or the Nix
  store on the NixOS installation CD).  Example use:

  $ sshfs foo@example.org:/ /mnt
  $ NIX_OTHER_STORES=/mnt/nix \
    NIX_SUBSTITUTERS=.../copy-from-other-stores.pl \
    nix-env -i foo

  This will be especially useful for the installation CD since it
  doesn't require a manifest for the CD contents.

-rw-r--r--scripts/Makefile.am3
-rw-r--r--scripts/copy-from-other-stores.pl.in82
2 files changed, 84 insertions, 1 deletions
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index fa66e58949dc..6a6226ebe73b 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -9,7 +9,7 @@ noinst_SCRIPTS = nix-profile.sh generate-patches.pl \
 
 nix-pull nix-push: readmanifest.pm readconfig.pm download-using-manifests.pl
 
-install-exec-local: readmanifest.pm download-using-manifests.pl find-runtime-roots.pl
+install-exec-local: readmanifest.pm download-using-manifests.pl copy-from-other-stores.pl find-runtime-roots.pl
 	$(INSTALL) -d $(DESTDIR)$(sysconfdir)/profile.d
 	$(INSTALL_PROGRAM) nix-profile.sh $(DESTDIR)$(sysconfdir)/profile.d/nix.sh
 	$(INSTALL) -d $(DESTDIR)$(libexecdir)/nix
@@ -31,6 +31,7 @@ EXTRA_DIST = nix-collect-garbage.in \
   readconfig.pm.in \
   nix-build.in \
   download-using-manifests.pl.in \
+  copy-from-other-stores.pl.in \
   generate-patches.pl.in \
   nix-pack-closure.in nix-unpack-closure.in \
   nix-copy-closure.in \
diff --git a/scripts/copy-from-other-stores.pl.in b/scripts/copy-from-other-stores.pl.in
new file mode 100644
index 000000000000..4f829108b0b8
--- /dev/null
+++ b/scripts/copy-from-other-stores.pl.in
@@ -0,0 +1,82 @@
+#! @perl@ -w
+
+use strict;
+use File::Basename;
+
+#print STDERR "FOO: @ARGV\n";
+
+die unless defined $ENV{"NIX_OTHER_STORES"};
+my @remoteStores = split ':', $ENV{"NIX_OTHER_STORES"};
+
+
+sub findStorePath {
+    my $storePath = shift;
+    
+    my $storePathName = basename $storePath;
+    #print STDERR "GET $storePath\n";
+    
+    foreach my $store (@remoteStores) {
+        # Determine whether $storePath exists by looking for the
+        # existence of the info file, and if so, get store path info
+        # from that file.  This rather breaks abstraction: we should
+        # be using `nix-store' for that.  But right now there is no
+        # good way to tell nix-store to access a store mounted under a
+        # different location (there's $NIX_STORE, but that only works
+        # if the remote store is mounted under its "real" location).
+        my $infoFile = "$store/var/nix/db/info/$storePathName";
+        my $storePath2 = "$store/store/$storePathName";
+        if (-f $infoFile && -e $storePath2) {
+            #print STDERR "FOUND IN $infoFile\n";
+            return ($infoFile, $storePath2);
+        }
+    }
+}
+
+
+if ($ARGV[0] eq "--query-paths") {
+    # !!! not implemented yet; needed for `nix-env -qas'
+}
+
+
+elsif ($ARGV[0] eq "--query-info") {
+    shift @ARGV;
+    
+    foreach my $storePath (@ARGV) {
+
+        (my $infoFile) = findStorePath $storePath;
+        #print STDERR "XXX $infoFile\n";
+        
+        my $deriver = "";
+        my @references = ();
+
+        open INFO, "<$infoFile" or die "cannot read info file $infoFile\n";
+        while (<INFO>) {
+            chomp;
+            #print STDERR "GOT $_\n";
+            /^([\w-]+): (.*)$/ or die "bad info file";
+            my $key = $1;
+            my $value = $2;
+            if ($key eq "Deriver") { $deriver = $value; }
+            elsif ($key eq "References") { @references = split ' ', $value; }
+        }
+        close INFO;
+
+        print "$storePath\n";
+        print "$deriver\n";
+        print scalar @references, "\n";
+        print "$_\n" foreach @references;
+    }
+}
+
+
+elsif ($ARGV[0] eq "--substitute") {
+    die unless scalar @ARGV == 2;
+    my $storePath = $ARGV[1];
+    (my $infoFile, my $sourcePath) = findStorePath $storePath;
+    print "\n*** Copying `$storePath' from `$sourcePath'\n\n";
+    system("nix-store --dump $sourcePath | nix-store --restore $storePath") == 0
+        or die "cannot copy `$sourcePath' to `$storePath'";
+}
+
+
+else { die; }