* New tools nix-pack-closure and nix-unpack-closure. These provide a
useful way to transfer the closure of a store path to another machine. These commands provide functionality previously possible through `nix-push --copy'. However, they are much more convenient in many situations (though possibly less efficient). Example: $ nix-pack-closure /nix/store/hj232g1r...-subversion-1.3.0 > svn.closure (on another machine:) $ nix-unpack-closure < svn.closure Note that Subversion is added to the store, but not installed into a user environment. One should do `nix-env -i /nix/store/hj232g1r...-subversion-1.3.0' for that. Another example: copy the application Azureus to the machine `scratchy' through ssh: $ nix-pack-closure $(which azureus) | ssh scratchy nix-unpack-closure
This commit is contained in:
		
							parent
							
								
									5b527901ae
								
							
						
					
					
						commit
						e4d4969ae9
					
				
					 3 changed files with 152 additions and 2 deletions
				
			
		| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
bin_SCRIPTS = nix-collect-garbage \
 | 
					bin_SCRIPTS = nix-collect-garbage \
 | 
				
			||||||
  nix-pull nix-push nix-prefetch-url \
 | 
					  nix-pull nix-push nix-prefetch-url \
 | 
				
			||||||
  nix-install-package nix-channel nix-build
 | 
					  nix-install-package nix-channel nix-build \
 | 
				
			||||||
 | 
					  nix-pack-closure nix-unpack-closure
 | 
				
			||||||
 | 
					
 | 
				
			||||||
noinst_SCRIPTS = nix-profile.sh generate-patches.pl
 | 
					noinst_SCRIPTS = nix-profile.sh generate-patches.pl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,4 +24,5 @@ EXTRA_DIST = nix-collect-garbage.in \
 | 
				
			||||||
  readmanifest.pm.in \
 | 
					  readmanifest.pm.in \
 | 
				
			||||||
  nix-build.in \
 | 
					  nix-build.in \
 | 
				
			||||||
  download-using-manifests.pl.in \
 | 
					  download-using-manifests.pl.in \
 | 
				
			||||||
  generate-patches.pl.in
 | 
					  generate-patches.pl.in \
 | 
				
			||||||
 | 
					  nix-pack-closure.in nix-unpack-closure.in
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										67
									
								
								scripts/nix-pack-closure.in
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								scripts/nix-pack-closure.in
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,67 @@
 | 
				
			||||||
 | 
					#! @perl@ -w
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This tool computes the closure of a path (using "nix-store --query
 | 
				
			||||||
 | 
					# --requisites") and puts the contents of each path in the closure in
 | 
				
			||||||
 | 
					# a big NAR archive that can be installed on another Nix installation
 | 
				
			||||||
 | 
					# using "nix-unpack-closure".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# TODO: make this program "streamy", i.e., don't use a temporary
 | 
				
			||||||
 | 
					# directory.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use POSIX qw(tmpnam);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my $binDir = $ENV{"NIX_BIN_DIR"};
 | 
				
			||||||
 | 
					$binDir = "@bindir@" unless defined $binDir;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my $tmpDir;
 | 
				
			||||||
 | 
					do { $tmpDir = tmpnam(); }
 | 
				
			||||||
 | 
					until mkdir $tmpDir, 0777;
 | 
				
			||||||
 | 
					END { system "rm -rf '$tmpDir'"; }
 | 
				
			||||||
 | 
					mkdir "$tmpDir/contents", 0777 or die;
 | 
				
			||||||
 | 
					mkdir "$tmpDir/references", 0777 or die;
 | 
				
			||||||
 | 
					mkdir "$tmpDir/derivers", 0777 or die;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my %storePaths;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					while (@ARGV) {
 | 
				
			||||||
 | 
					    my $storePath = shift @ARGV;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Get the closure of this path.
 | 
				
			||||||
 | 
					    my $pid = open(READ,
 | 
				
			||||||
 | 
					        "$binDir/nix-store --query --requisites " .
 | 
				
			||||||
 | 
					        "--force-realise '$storePath'|") or die;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    while (<READ>) {
 | 
				
			||||||
 | 
					        chomp;
 | 
				
			||||||
 | 
					        die "bad: $_" unless /^\//;
 | 
				
			||||||
 | 
					        $storePaths{$_} = "";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    close READ or die "nix-store failed: $?";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					foreach my $storePath (sort(keys %storePaths)) {
 | 
				
			||||||
 | 
					    print STDERR "packing `$storePath'...\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $storePath =~ /\/([^\/]+)$/;
 | 
				
			||||||
 | 
					    my $name = $1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    system("$binDir/nix-store --dump '$storePath' > $tmpDir/contents/$name") == 0
 | 
				
			||||||
 | 
					        or die "nix-store --dump failed on `$storePath': $?";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    system("$binDir/nix-store --query --references '$storePath' > $tmpDir/references/$name") == 0
 | 
				
			||||||
 | 
					        or die "nix-store --query --references failed on `$storePath': $?";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    system("$binDir/nix-store --query --deriver '$storePath' > $tmpDir/derivers/$name") == 0
 | 
				
			||||||
 | 
					        or die "nix-store --query --deriver failed on `$storePath': $?";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Write a NAR archive of everything to standard output.
 | 
				
			||||||
 | 
					system("nix-store --dump '$tmpDir'") == 0
 | 
				
			||||||
 | 
					    or die "nix-store --dump failed";
 | 
				
			||||||
							
								
								
									
										81
									
								
								scripts/nix-unpack-closure.in
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								scripts/nix-unpack-closure.in
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,81 @@
 | 
				
			||||||
 | 
					#! @perl@ -w
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This tool unpacks the closures created by "nix-pack-closure" and
 | 
				
			||||||
 | 
					# adds them to the Nix store.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# TODO: make this program "streamy", i.e., don't use a temporary
 | 
				
			||||||
 | 
					# directory.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use POSIX qw(tmpnam);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my $binDir = $ENV{"NIX_BIN_DIR"};
 | 
				
			||||||
 | 
					$binDir = "@bindir@" unless defined $binDir;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my $tmpDir;
 | 
				
			||||||
 | 
					do { $tmpDir = tmpnam(); }
 | 
				
			||||||
 | 
					until mkdir $tmpDir, 0777;
 | 
				
			||||||
 | 
					END { system "rm -rf '$tmpDir'"; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Unpack the NAR archive on standard input.
 | 
				
			||||||
 | 
					system("nix-store --restore '$tmpDir/unpacked'") == 0
 | 
				
			||||||
 | 
					    or die "nix-store --restore failed";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					open VALID, ">$tmpDir/validity" or die;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# For each path in the closure that is not yet valid, add it to the
 | 
				
			||||||
 | 
					# store.  TODO: use proper locking.  Or even better, let nix-store do
 | 
				
			||||||
 | 
					# this.
 | 
				
			||||||
 | 
					opendir(DIR, "$tmpDir/unpacked/contents") or die "cannot open directory: $!";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					foreach my $name (sort(readdir DIR)) {
 | 
				
			||||||
 | 
					    next if $name eq "." or $name eq "..";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    my $storePath = "/nix/store/$name"; # !!!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # !!! this really isn't a good validity check!
 | 
				
			||||||
 | 
					    system "/nix/bin/nix-store --check-validity '$storePath' 2> /dev/null";
 | 
				
			||||||
 | 
					    if ($? != 0) {
 | 
				
			||||||
 | 
					        print STDERR "unpacking `$storePath'...\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # !!! race
 | 
				
			||||||
 | 
					        system("rm -rf '$storePath'") == 0
 | 
				
			||||||
 | 
					            or die "cannot remove `$storePath': $?";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        system("$binDir/nix-store --restore '$storePath' < '$tmpDir/unpacked/contents/$name'") == 0
 | 
				
			||||||
 | 
					            or die "nix-store --dump failed on `$storePath': $?";
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        print VALID "$storePath\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        open DRV, "<$tmpDir/unpacked/derivers/$name" or die;
 | 
				
			||||||
 | 
					        my $deriver = <DRV>;
 | 
				
			||||||
 | 
					        chomp $deriver;
 | 
				
			||||||
 | 
					        $deriver = "" if $deriver eq "unknown-deriver";
 | 
				
			||||||
 | 
					        close DRV;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        my @refs;
 | 
				
			||||||
 | 
					        open REFS, "<$tmpDir/unpacked/references/$name" or die;
 | 
				
			||||||
 | 
					        while (<REFS>) {
 | 
				
			||||||
 | 
					            chomp;
 | 
				
			||||||
 | 
					            push @refs, $_;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        close REFS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        print VALID "$deriver\n";
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        print VALID (scalar @refs), "\n";
 | 
				
			||||||
 | 
					        foreach my $ref (@refs) {
 | 
				
			||||||
 | 
					            print VALID "$ref\n";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					closedir(DIR) or die;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Register the invalid paths as valid.
 | 
				
			||||||
 | 
					system("nix-store --register-validity <'$tmpDir/validity'") == 0
 | 
				
			||||||
 | 
					    or die "nix-store --register-validity failed";
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue