* nix-unpack-closure: extract the top-level paths from the closure and print them on stdout. This allows them to be installed, e.g., "nix-env -i $(nix-unpack-closure)". (NIX-64)
		
			
				
	
	
		
			88 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			88 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| #! @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 File::Temp qw(tempdir);
 | |
| 
 | |
| my $binDir = $ENV{"NIX_BIN_DIR"};
 | |
| $binDir = "@bindir@" unless defined $binDir;
 | |
| 
 | |
| my $tmpDir = tempdir("nix-unpack-closure.XXXXXX", CLEANUP => 1, TMPDIR => 1)
 | |
|     or die "cannot create a temporary directory";
 | |
| 
 | |
| 
 | |
| # 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 = "@storedir@/$name"; # !!!
 | |
| 
 | |
|     # !!! this really isn't a good validity check!
 | |
|     system "$binDir/nix-store --check-validity '$storePath' 2> /dev/null";
 | |
|     if ($? != 0) {
 | |
|         print STDERR "unpacking `$storePath'...\n";
 | |
| 
 | |
|         # !!! race
 | |
|         system("@coreutils@/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";
 | |
| 
 | |
| 
 | |
| # Show the top-level paths so that something useful can be done with
 | |
| # them, e.g., passing them to `nix-env -i'.
 | |
| if (-e "$tmpDir/unpacked/top-level") {
 | |
|     open TOPLEVEL, "<$tmpDir/unpacked/top-level" or die;
 | |
|     while (<TOPLEVEL>) { print "$_"; }
 | |
|     close TOPLEVEL;
 | |
| }
 |