* Really fix the substitute mechanism, i.e., ensure the closure
invariant by registering references through the manifest. * Added a test for nix-pull.
This commit is contained in:
		
							parent
							
								
									c6290e42bc
								
							
						
					
					
						commit
						066da4ab85
					
				
					 16 changed files with 255 additions and 89 deletions
				
			
		|  | @ -1,13 +1,11 @@ | ||||||
| all-local: nar.sh unnar.sh | all-local: nar.sh | ||||||
| 
 | 
 | ||||||
| install-exec-local: | install-exec-local: | ||||||
| 	$(INSTALL) -d $(DESTDIR)$(datadir)/nix/corepkgs | 	$(INSTALL) -d $(DESTDIR)$(datadir)/nix/corepkgs | ||||||
| 	$(INSTALL) -d $(DESTDIR)$(datadir)/nix/corepkgs/nar | 	$(INSTALL) -d $(DESTDIR)$(datadir)/nix/corepkgs/nar | ||||||
| 	$(INSTALL_DATA) nar.nix $(DESTDIR)$(datadir)/nix/corepkgs/nar | 	$(INSTALL_DATA) nar.nix $(DESTDIR)$(datadir)/nix/corepkgs/nar | ||||||
| 	$(INSTALL_PROGRAM) nar.sh $(DESTDIR)$(datadir)/nix/corepkgs/nar | 	$(INSTALL_PROGRAM) nar.sh $(DESTDIR)$(datadir)/nix/corepkgs/nar | ||||||
| 	$(INSTALL_DATA) unnar.nix $(DESTDIR)$(datadir)/nix/corepkgs/nar |  | ||||||
| 	$(INSTALL_PROGRAM) unnar.sh $(DESTDIR)$(datadir)/nix/corepkgs/nar |  | ||||||
| 
 | 
 | ||||||
| include ../../substitute.mk | include ../../substitute.mk | ||||||
| 
 | 
 | ||||||
| EXTRA_DIST = nar.nix nar.sh.in unnar.nix unnar.sh.in | EXTRA_DIST = nar.nix nar.sh.in | ||||||
|  |  | ||||||
|  | @ -10,10 +10,6 @@ dst=$out/$(basename $path).nar.bz2 | ||||||
| 
 | 
 | ||||||
| @bzip2@ < tmp > $dst | @bzip2@ < tmp > $dst | ||||||
| 
 | 
 | ||||||
| narHash=$(md5sum -b tmp | cut -c1-32) | @bindir@/nix-hash -vvvvv --flat --type sha1 --base32 tmp > $out/nar-hash | ||||||
| if test $? != 0; then exit 1; fi |  | ||||||
| echo $narHash > $out/nar-hash |  | ||||||
| 
 | 
 | ||||||
| narbz2Hash=$(md5sum -b $dst | cut -c1-32) | @bindir@/nix-hash --flat --type sha1 --base32 $dst > $out/narbz2-hash | ||||||
| if test $? != 0; then exit 1; fi |  | ||||||
| echo $narbz2Hash > $out/narbz2-hash |  | ||||||
|  |  | ||||||
|  | @ -1,7 +0,0 @@ | ||||||
| {system, narFile, outPath}: derivation { |  | ||||||
|   name = "unnar"; |  | ||||||
|   builder = ./unnar.sh; |  | ||||||
|   system = system; |  | ||||||
|   narFile = narFile; |  | ||||||
|   outPath = outPath; |  | ||||||
| } |  | ||||||
|  | @ -1,4 +0,0 @@ | ||||||
| #! @shell@ -e |  | ||||||
| 
 |  | ||||||
| echo "unpacking $narFile to $out..." |  | ||||||
| @bunzip2@ < $narFile | @bindir@/nix-store --restore "$out" |  | ||||||
|  | @ -13,7 +13,7 @@ open LOGFILE, ">>$logFile" or die "cannot open log file $logFile"; | ||||||
| die unless scalar @ARGV == 1; | die unless scalar @ARGV == 1; | ||||||
| my $targetPath = $ARGV[0]; | my $targetPath = $ARGV[0]; | ||||||
| 
 | 
 | ||||||
| my $date = `date`; | my $date = `date` or die; | ||||||
| chomp $date; | chomp $date; | ||||||
| print LOGFILE "$$ get $targetPath $date\n"; | print LOGFILE "$$ get $targetPath $date\n"; | ||||||
| 
 | 
 | ||||||
|  | @ -180,7 +180,7 @@ sub downloadFile { | ||||||
|     my ($hash2, $path) = `@bindir@/nix-prefetch-url '$url' '$hash'`; |     my ($hash2, $path) = `@bindir@/nix-prefetch-url '$url' '$hash'`; | ||||||
|     chomp $hash2; |     chomp $hash2; | ||||||
|     chomp $path; |     chomp $path; | ||||||
|     die "hash mismatch" if $hash ne $hash2; |     die "hash mismatch, expected $hash, got $hash2" if $hash ne $hash2; | ||||||
|     return $path; |     return $path; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -236,7 +236,7 @@ while (scalar @path > 0) { | ||||||
| 
 | 
 | ||||||
|         # Unpack the archive into the target path. |         # Unpack the archive into the target path. | ||||||
|         print "  unpacking archive...\n"; |         print "  unpacking archive...\n"; | ||||||
|         system "@bunzip2@ < '$narFilePath' | nix-store --restore '$v'"; |         system "@bunzip2@ < '$narFilePath' | @bindir@/nix-store --restore '$v'"; | ||||||
|         die "cannot unpack `$narFilePath' into `$v'" if ($? != 0); |         die "cannot unpack `$narFilePath' into `$v'" if ($? != 0); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -46,10 +46,8 @@ storeExpr=$( \ | ||||||
|         {url = $url; outputHashAlgo = \"$hashType\"; outputHash = \"$hash\"; system = \"@system@\";}" \ |         {url = $url; outputHashAlgo = \"$hashType\"; outputHash = \"$hash\"; system = \"@system@\";}" \ | ||||||
|     | @bindir@/nix-instantiate -) |     | @bindir@/nix-instantiate -) | ||||||
| 
 | 
 | ||||||
| echo "$storeExpr"     |  | ||||||
| 
 |  | ||||||
| # Realise it. | # Realise it. | ||||||
| finalPath=$(@bindir@/nix-store -qnB --force-realise $storeExpr) | finalPath=$(@bindir@/nix-store -q --force-realise $storeExpr) | ||||||
|      |      | ||||||
| if ! test -n "$QUIET"; then echo "path is $finalPath" >&2; fi | if ! test -n "$QUIET"; then echo "path is $finalPath" >&2; fi | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -13,6 +13,15 @@ my $manifest = "$tmpdir/manifest"; | ||||||
| 
 | 
 | ||||||
| END { unlink $manifest; rmdir $tmpdir; } | END { unlink $manifest; rmdir $tmpdir; } | ||||||
| 
 | 
 | ||||||
|  | my $binDir = $ENV{"NIX_BIN_DIR"}; | ||||||
|  | $binDir = "@bindir@" unless defined $binDir; | ||||||
|  | 
 | ||||||
|  | my $libexecDir = $ENV{"NIX_LIBEXEC_DIR"}; | ||||||
|  | $libexecDir = "@libexecdir@" unless defined $libexecDir; | ||||||
|  | 
 | ||||||
|  | my $localStateDir = $ENV{"NIX_LOCALSTATE_DIR"}; | ||||||
|  | $localStateDir = "@localstatedir@" unless defined $localStateDir; | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| # Obtain URLs either from the command line or from a configuration file. | # Obtain URLs either from the command line or from a configuration file. | ||||||
| my %narFiles; | my %narFiles; | ||||||
|  | @ -36,11 +45,11 @@ sub processURL { | ||||||
|         $baseName = $1; |         $baseName = $1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     my $hash = `@bindir@/nix-hash --flat '$manifest'` |     my $hash = `$binDir/nix-hash --flat '$manifest'` | ||||||
|         or die "cannot hash `$manifest'"; |         or die "cannot hash `$manifest'"; | ||||||
|     chomp $hash; |     chomp $hash; | ||||||
|      |      | ||||||
|     my $finalPath = "@localstatedir@/nix/manifests/$baseName-$hash.nixmanifest"; |     my $finalPath = "$localStateDir/nix/manifests/$baseName-$hash.nixmanifest"; | ||||||
|      |      | ||||||
|     system("mv '$manifest' '$finalPath'") == 0 |     system("mv '$manifest' '$finalPath'") == 0 | ||||||
|         or die "cannot move `$manifest' to `$finalPath"; |         or die "cannot move `$manifest' to `$finalPath"; | ||||||
|  | @ -59,7 +68,7 @@ print "$size store paths in manifest\n"; | ||||||
| # Register all substitutes. | # Register all substitutes. | ||||||
| print STDERR "registering substitutes...\n"; | print STDERR "registering substitutes...\n"; | ||||||
| 
 | 
 | ||||||
| my $pid = open2(\*READ, \*WRITE, "@bindir@/nix-store --substitute") | my $pid = open2(\*READ, \*WRITE, "$binDir/nix-store --substitute") | ||||||
|     or die "cannot run nix-store"; |     or die "cannot run nix-store"; | ||||||
| 
 | 
 | ||||||
| close READ; | close READ; | ||||||
|  | @ -68,8 +77,14 @@ foreach my $storePath (keys %narFiles) { | ||||||
|     my $narFileList = $narFiles{$storePath}; |     my $narFileList = $narFiles{$storePath}; | ||||||
|     foreach my $narFile (@{$narFileList}) { |     foreach my $narFile (@{$narFileList}) { | ||||||
|         print WRITE "$storePath\n"; |         print WRITE "$storePath\n"; | ||||||
|         print WRITE "@libexecdir@/nix/download-using-manifests.pl\n"; |         print WRITE "$libexecDir/nix/download-using-manifests.pl\n"; | ||||||
|         print WRITE "0\n"; |         print WRITE "0\n"; | ||||||
|  |         my @references = split " ", $narFile->{references}; | ||||||
|  |         my $count = scalar @references; | ||||||
|  |         print WRITE "$count\n"; | ||||||
|  |         foreach my $reference (@references) { | ||||||
|  |             print WRITE "$reference\n"; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -77,16 +92,3 @@ close WRITE; | ||||||
| 
 | 
 | ||||||
| waitpid $pid, 0; | waitpid $pid, 0; | ||||||
| $? == 0 or die "nix-store failed"; | $? == 0 or die "nix-store failed"; | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Register all successors. |  | ||||||
| print STDERR "registering successors...\n"; |  | ||||||
| my @sucs = %successors; |  | ||||||
| while (scalar @sucs > 0) { |  | ||||||
|     my $n = scalar @sucs; |  | ||||||
|     if ($n > 256) { $n = 256 }; |  | ||||||
|     my @sucs2 = @sucs[0..$n - 1]; |  | ||||||
|     @sucs = @sucs[$n..scalar @sucs - 1]; |  | ||||||
|     system "@bindir@/nix-store --successor @sucs2"; |  | ||||||
|     if ($?) { die "`nix-store --successor' failed"; } |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| #! @perl@ -w -I@libexecdir@/nix | #! @perl@ -w -I@libexecdir@/nix | ||||||
| 
 | 
 | ||||||
| use strict; | use strict; | ||||||
|  | use IPC::Open2; | ||||||
| use POSIX qw(tmpnam); | use POSIX qw(tmpnam); | ||||||
| use readmanifest; | use readmanifest; | ||||||
| 
 | 
 | ||||||
|  | @ -17,32 +18,62 @@ my $curl = "@curl@ --fail --silent"; | ||||||
| my $extraCurlFlags = ${ENV{'CURL_FLAGS'}}; | my $extraCurlFlags = ${ENV{'CURL_FLAGS'}}; | ||||||
| $curl = "$curl $extraCurlFlags" if defined $extraCurlFlags; | $curl = "$curl $extraCurlFlags" if defined $extraCurlFlags; | ||||||
| 
 | 
 | ||||||
|  | my $binDir = $ENV{"NIX_BIN_DIR"}; | ||||||
|  | $binDir = "@bindir@" unless defined $binDir; | ||||||
|  | 
 | ||||||
|  | my $dataDir = $ENV{"NIX_DATA_DIR"}; | ||||||
|  | $dataDir = "@datadir@" unless defined $dataDir; | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| # Parse the command line. | # Parse the command line. | ||||||
| my $archives_put_url = shift @ARGV; | my $localCopy; | ||||||
| my $archives_get_url = shift @ARGV; | my $localArchivesDir; | ||||||
| my $manifest_put_url = shift @ARGV; | my $localManifestFile; | ||||||
|  | 
 | ||||||
|  | my $archives_put_url; | ||||||
|  | my $archives_get_url; | ||||||
|  | my $manifest_put_url; | ||||||
|  | 
 | ||||||
|  | if ($ARGV[0] eq "--copy") { | ||||||
|  |     die "syntax: nix-push --copy ARCHIVES_DIR MANIFEST_FILE PATHS...\n" if scalar @ARGV < 3; | ||||||
|  |     $localCopy = 1; | ||||||
|  |     shift @ARGV; | ||||||
|  |     $localArchivesDir = shift @ARGV; | ||||||
|  |     $localManifestFile = shift @ARGV; | ||||||
|  | } | ||||||
|  | else { | ||||||
|  |     die "syntax: nix-push ARCHIVES_PUT_URL ARCHIVES_GET_URL " . | ||||||
|  |         "MANIFEST_PUT_URL PATHS...\n" if scalar @ARGV < 3; | ||||||
|  |     $localCopy = 0; | ||||||
|  |     $archives_put_url = shift @ARGV; | ||||||
|  |     $archives_get_url = shift @ARGV; | ||||||
|  |     $manifest_put_url = shift @ARGV; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # From the given store expressions, determine the requisite store | # From the given store paths, determine the set of requisite store | ||||||
| # paths. | # paths, i.e, the paths required to realise them. | ||||||
| my %storePaths; | my %storePaths; | ||||||
| 
 | 
 | ||||||
| foreach my $storeexpr (@ARGV) { | foreach my $path (@ARGV) { | ||||||
|     die unless $storeexpr =~ /^\//; |     die unless $path =~ /^\//; | ||||||
| 
 | 
 | ||||||
|     # Get all paths referenced by the normalisation of the given  |     # Get all paths referenced by the normalisation of the given  | ||||||
|     # Nix expression. |     # Nix expression. | ||||||
|     system "@bindir@/nix-store --realise $storeexpr > /dev/null"; |     my $pid = open2(\*READ, \*WRITE, | ||||||
|     die if ($?); |         "$binDir/nix-store --query --requisites --force-realise " . | ||||||
|  |         "--include-outputs '$path'") or die; | ||||||
|  |     close WRITE; | ||||||
|      |      | ||||||
|     open PATHS, "@bindir@/nix-store --query --requisites --include-successors $storeexpr 2> /dev/null |" or die; |     while (<READ>) { | ||||||
|     while (<PATHS>) { |  | ||||||
|         chomp; |         chomp; | ||||||
|         die "bad: $_" unless /^\//; |         die "bad: $_" unless /^\//; | ||||||
|         $storePaths{$_} = ""; |         $storePaths{$_} = ""; | ||||||
|     } |     } | ||||||
|     close PATHS; |     close READ; | ||||||
|  |      | ||||||
|  |     waitpid $pid, 0; | ||||||
|  |     $? == 0 or die "nix-store failed"; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| my @storePaths = keys %storePaths; | my @storePaths = keys %storePaths; | ||||||
|  | @ -58,8 +89,7 @@ foreach my $storePath (@storePaths) { | ||||||
| 
 | 
 | ||||||
|     # Construct a Nix expression that creates a Nix archive. |     # Construct a Nix expression that creates a Nix archive. | ||||||
|     my $nixexpr =  |     my $nixexpr =  | ||||||
|         "((import @datadir@/nix/corepkgs/nar/nar.nix) " . |         "((import $dataDir/nix/corepkgs/nar/nar.nix) " . | ||||||
|         # !!! $storePath should be represented as a closure |  | ||||||
|         "{path = \"$storePath\"; system = \"@system@\";}) "; |         "{path = \"$storePath\"; system = \"@system@\";}) "; | ||||||
|      |      | ||||||
|     print NIX $nixexpr; |     print NIX $nixexpr; | ||||||
|  | @ -72,7 +102,7 @@ close NIX; | ||||||
| # Instantiate store expressions from the Nix expression. | # Instantiate store expressions from the Nix expression. | ||||||
| my @storeexprs; | my @storeexprs; | ||||||
| print STDERR "instantiating store expressions...\n"; | print STDERR "instantiating store expressions...\n"; | ||||||
| open STOREEXPRS, "@bindir@/nix-instantiate $nixfile |" or die "cannot run nix-instantiate"; | open STOREEXPRS, "$binDir/nix-instantiate $nixfile |" or die "cannot run nix-instantiate"; | ||||||
| while (<STOREEXPRS>) { | while (<STOREEXPRS>) { | ||||||
|     chomp; |     chomp; | ||||||
|     die unless /^\//; |     die unless /^\//; | ||||||
|  | @ -93,10 +123,7 @@ while (scalar @tmp > 0) { | ||||||
|     my @tmp2 = @tmp[0..$n - 1]; |     my @tmp2 = @tmp[0..$n - 1]; | ||||||
|     @tmp = @tmp[$n..scalar @tmp - 1]; |     @tmp = @tmp[$n..scalar @tmp - 1]; | ||||||
| 
 | 
 | ||||||
|     system "@bindir@/nix-store --realise @tmp2 > /dev/null"; |     open NARPATHS, "$binDir/nix-store --realise @tmp2 |" or die "cannot run nix-store"; | ||||||
|     if ($?) { die "`nix-store --realise' failed"; } |  | ||||||
| 
 |  | ||||||
|     open NARPATHS, "@bindir@/nix-store --query --list @tmp2 |" or die "cannot run nix"; |  | ||||||
|     while (<NARPATHS>) { |     while (<NARPATHS>) { | ||||||
|         chomp; |         chomp; | ||||||
|         die unless (/^\//); |         die unless (/^\//); | ||||||
|  | @ -142,16 +169,26 @@ for (my $n = 0; $n < scalar @storePaths; $n++) { | ||||||
|      |      | ||||||
|     my $narbz2Size = (stat $narfile)[7]; |     my $narbz2Size = (stat $narfile)[7]; | ||||||
| 
 | 
 | ||||||
|  |     my $references = join(" ", split(" ", `$binDir/nix-store --query --references '$storePath'`)); | ||||||
|  | 
 | ||||||
|  |     my $url; | ||||||
|  |     if ($localCopy) { | ||||||
|  |         $url = "file://$localArchivesDir/$narname"; | ||||||
|  |     } else { | ||||||
|  |         $url = "$archives_get_url/$narname"; | ||||||
|  |     } | ||||||
|     $narFiles{$storePath} = [ |     $narFiles{$storePath} = [ | ||||||
|         { url => $archives_get_url/$narname |         { url => $url | ||||||
|         , hash => $narbz2Hash |         , hash => $narbz2Hash | ||||||
|         , size => $narbz2Size |         , size => $narbz2Size | ||||||
|         , narHash => $narHash |         , narHash => $narHash | ||||||
|  |         , hashAlgo => "sha1" | ||||||
|  |         , references => $references | ||||||
|         } |         } | ||||||
|     ]; |     ]; | ||||||
|                              |                              | ||||||
|     if ($storePath =~ /\.store$/) { |     if ($storePath =~ /\.store$/) { | ||||||
|         open PREDS, "@bindir@/nix-store --query --predecessors $storePath |" or die "cannot run nix"; |         open PREDS, "$binDir/nix-store --query --predecessors $storePath |" or die "cannot run nix"; | ||||||
|         while (<PREDS>) { |         while (<PREDS>) { | ||||||
|             chomp; |             chomp; | ||||||
|             die unless (/^\//); |             die unless (/^\//); | ||||||
|  | @ -170,6 +207,14 @@ for (my $n = 0; $n < scalar @storePaths; $n++) { | ||||||
| writeManifest $manifest, \%narFiles, \%patches, \%successors; | writeManifest $manifest, \%narFiles, \%patches, \%successors; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | sub copyFile { | ||||||
|  |     my $src = shift; | ||||||
|  |     my $dst = shift; | ||||||
|  |     system("cp '$src' '$dst.tmp'") == 0 or die "cannot copy file"; | ||||||
|  |     rename("$dst.tmp", "$dst") or die "cannot rename file"; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| # Upload the archives. | # Upload the archives. | ||||||
| print STDERR "uploading archives...\n"; | print STDERR "uploading archives...\n"; | ||||||
| foreach my $nararchive (@nararchives) { | foreach my $nararchive (@nararchives) { | ||||||
|  | @ -177,17 +222,29 @@ foreach my $nararchive (@nararchives) { | ||||||
|     $nararchive =~ /\/([^\/]*)$/; |     $nararchive =~ /\/([^\/]*)$/; | ||||||
|     my $basename = $1; |     my $basename = $1; | ||||||
| 
 | 
 | ||||||
|     if (system("$curl --head $archives_get_url/$basename > /dev/null") != 0) { |     if ($localCopy) { | ||||||
|         print STDERR "  $nararchive\n"; |         if (! -f "$localArchivesDir/$basename") { | ||||||
|         system("$curl --show-error --upload-file " . |             print STDERR "  $nararchive\n"; | ||||||
|                "'$nararchive' '$archives_put_url/$basename' > /dev/null") == 0 or |             copyFile $nararchive, "$localArchivesDir/$basename"; | ||||||
|             die "curl failed on $nararchive: $?"; |         } | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |         if (system("$curl --head $archives_get_url/$basename > /dev/null") != 0) { | ||||||
|  |             print STDERR "  $nararchive\n"; | ||||||
|  |             system("$curl --show-error --upload-file " . | ||||||
|  |                    "'$nararchive' '$archives_put_url/$basename' > /dev/null") == 0 or | ||||||
|  |                    die "curl failed on $nararchive: $?"; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # Upload the manifest. | # Upload the manifest. | ||||||
| print STDERR "uploading manifest...\n"; | print STDERR "uploading manifest...\n"; | ||||||
| system("$curl  --show-error --upload-file " . | if ($localCopy) { | ||||||
|        "'$manifest' '$manifest_put_url' > /dev/null") == 0 or |     copyFile $manifest, $localManifestFile; | ||||||
|     die "curl failed on $manifest: $?"; | } else { | ||||||
|  |     system("$curl  --show-error --upload-file " . | ||||||
|  |            "'$manifest' '$manifest_put_url' > /dev/null") == 0 or | ||||||
|  |            die "curl failed on $manifest: $?"; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -49,6 +49,7 @@ sub readManifest { | ||||||
|     my $baseHash; |     my $baseHash; | ||||||
|     my $patchType; |     my $patchType; | ||||||
|     my $narHash; |     my $narHash; | ||||||
|  |     my $references; | ||||||
| 
 | 
 | ||||||
|     while (<MANIFEST>) { |     while (<MANIFEST>) { | ||||||
|         chomp; |         chomp; | ||||||
|  | @ -70,6 +71,7 @@ sub readManifest { | ||||||
|                 undef $basePath; |                 undef $basePath; | ||||||
|                 undef $baseHash; |                 undef $baseHash; | ||||||
|                 undef $patchType; |                 undef $patchType; | ||||||
|  |                 $references = ""; | ||||||
| 	    } | 	    } | ||||||
| 
 | 
 | ||||||
|         } else { |         } else { | ||||||
|  | @ -98,7 +100,7 @@ sub readManifest { | ||||||
|                     if (!$found) { |                     if (!$found) { | ||||||
|                         push @{$narFileList}, |                         push @{$narFileList}, | ||||||
|                             { url => $url, hash => $hash, size => $size |                             { url => $url, hash => $hash, size => $size | ||||||
|                             , narHash => $narHash |                             , narHash => $narHash, references => $references | ||||||
|                             }; |                             }; | ||||||
|                     } |                     } | ||||||
|                  |                  | ||||||
|  | @ -127,6 +129,7 @@ sub readManifest { | ||||||
|             elsif (/^\s*BaseHash:\s*(\S+)\s*$/) { $baseHash = $1; } |             elsif (/^\s*BaseHash:\s*(\S+)\s*$/) { $baseHash = $1; } | ||||||
|             elsif (/^\s*Type:\s*(\S+)\s*$/) { $patchType = $1; } |             elsif (/^\s*Type:\s*(\S+)\s*$/) { $patchType = $1; } | ||||||
|             elsif (/^\s*NarHash:\s*(\S+)\s*$/) { $narHash = $1; } |             elsif (/^\s*NarHash:\s*(\S+)\s*$/) { $narHash = $1; } | ||||||
|  |             elsif (/^\s*References:\s*(.*)\s*$/) { $references = $1; } | ||||||
| 
 | 
 | ||||||
|             # Compatibility; |             # Compatibility; | ||||||
|             elsif (/^\s*NarURL:\s*(\S+)\s*$/) { $url = $1; } |             elsif (/^\s*NarURL:\s*(\S+)\s*$/) { $url = $1; } | ||||||
|  | @ -153,10 +156,13 @@ sub writeManifest | ||||||
|         foreach my $narFile (@{$narFileList}) { |         foreach my $narFile (@{$narFileList}) { | ||||||
|             print MANIFEST "{\n"; |             print MANIFEST "{\n"; | ||||||
|             print MANIFEST "  StorePath: $storePath\n"; |             print MANIFEST "  StorePath: $storePath\n"; | ||||||
|  |             print MANIFEST "  HashAlgo: $narFile->{hashAlgo}\n"; | ||||||
|             print MANIFEST "  NarURL: $narFile->{url}\n"; |             print MANIFEST "  NarURL: $narFile->{url}\n"; | ||||||
|             print MANIFEST "  MD5: $narFile->{hash}\n"; |             print MANIFEST "  MD5: $narFile->{hash}\n"; | ||||||
|             print MANIFEST "  NarHash: $narFile->{narHash}\n"; |             print MANIFEST "  NarHash: $narFile->{narHash}\n"; | ||||||
|             print MANIFEST "  Size: $narFile->{size}\n"; |             print MANIFEST "  Size: $narFile->{size}\n"; | ||||||
|  |             print MANIFEST "  References: $narFile->{references}\n" | ||||||
|  |                 if defined $narFile->{references} && $narFile->{references} ne ""; | ||||||
|             foreach my $p (keys %{$successors}) { # !!! quadratic |             foreach my $p (keys %{$successors}) { # !!! quadratic | ||||||
|                 if ($$successors{$p} eq $storePath) { |                 if ($$successors{$p} eq $storePath) { | ||||||
|                     print MANIFEST "  SuccOf: $p\n"; |                     print MANIFEST "  SuccOf: $p\n"; | ||||||
|  | @ -171,6 +177,7 @@ sub writeManifest | ||||||
|         foreach my $patch (@{$patchList}) { |         foreach my $patch (@{$patchList}) { | ||||||
|             print MANIFEST "patch {\n"; |             print MANIFEST "patch {\n"; | ||||||
|             print MANIFEST "  StorePath: $storePath\n"; |             print MANIFEST "  StorePath: $storePath\n"; | ||||||
|  |             print MANIFEST "  HashAlgo: $patch->{hashAlgo}\n"; | ||||||
|             print MANIFEST "  NarURL: $patch->{url}\n"; |             print MANIFEST "  NarURL: $patch->{url}\n"; | ||||||
|             print MANIFEST "  MD5: $patch->{hash}\n"; |             print MANIFEST "  MD5: $patch->{hash}\n"; | ||||||
|             print MANIFEST "  NarHash: $patch->{narHash}\n"; |             print MANIFEST "  NarHash: $patch->{narHash}\n"; | ||||||
|  |  | ||||||
|  | @ -472,9 +472,8 @@ void DerivationGoal::outputsSubstituted() | ||||||
| { | { | ||||||
|     trace("all outputs substituted (maybe)"); |     trace("all outputs substituted (maybe)"); | ||||||
| 
 | 
 | ||||||
|     if (nrFailed > 0 && !tryFallback) { |     if (nrFailed > 0 && !tryFallback) | ||||||
|         throw Error(format("some substitutes for the outputs of derivation `%1%' failed; try `--fallback'") % drvPath); |         throw Error(format("some substitutes for the outputs of derivation `%1%' failed; try `--fallback'") % drvPath); | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     nrFailed = 0; |     nrFailed = 0; | ||||||
| 
 | 
 | ||||||
|  | @ -1252,6 +1251,9 @@ private: | ||||||
|     /* The current substitute. */ |     /* The current substitute. */ | ||||||
|     Substitute sub; |     Substitute sub; | ||||||
| 
 | 
 | ||||||
|  |     /* Outgoing references for this path. */ | ||||||
|  |     PathSet references; | ||||||
|  | 
 | ||||||
|     /* Pipe for the substitute's standard output/error. */ |     /* Pipe for the substitute's standard output/error. */ | ||||||
|     Pipe logPipe; |     Pipe logPipe; | ||||||
| 
 | 
 | ||||||
|  | @ -1272,6 +1274,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     /* The states. */ |     /* The states. */ | ||||||
|     void init(); |     void init(); | ||||||
|  |     void referencesValid(); | ||||||
|     void tryNext(); |     void tryNext(); | ||||||
|     void tryToRun(); |     void tryToRun(); | ||||||
|     void finished(); |     void finished(); | ||||||
|  | @ -1313,13 +1316,35 @@ void SubstitutionGoal::init() | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* !!! build the outgoing references of this path first to
 |     /* Read the substitutes. */ | ||||||
|        maintain the closure invariant! */ |  | ||||||
| 
 |  | ||||||
|     /* Otherwise, get the substitutes. */ |  | ||||||
|     subs = querySubstitutes(storePath); |     subs = querySubstitutes(storePath); | ||||||
| 
 | 
 | ||||||
|     /* Try the first one. */ |     /* To maintain the closure invairant, we first have to realise the
 | ||||||
|  |        paths referenced by this one. */ | ||||||
|  |     queryReferences(storePath, references); | ||||||
|  | 
 | ||||||
|  |     for (PathSet::iterator i = references.begin(); | ||||||
|  |          i != references.end(); ++i) | ||||||
|  |         addWaitee(worker.makeSubstitutionGoal(*i)); | ||||||
|  | 
 | ||||||
|  |     if (waitees.empty()) /* to prevent hang (no wake-up event) */ | ||||||
|  |         referencesValid(); | ||||||
|  |     else | ||||||
|  |         state = &SubstitutionGoal::referencesValid; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | void SubstitutionGoal::referencesValid() | ||||||
|  | { | ||||||
|  |     trace("all referenced realised"); | ||||||
|  | 
 | ||||||
|  |     if (nrFailed > 0) | ||||||
|  |         throw Error(format("some references of path `%1%' could not be realised") % storePath); | ||||||
|  | 
 | ||||||
|  |     for (PathSet::iterator i = references.begin(); | ||||||
|  |          i != references.end(); ++i) | ||||||
|  |         assert(isValidPath(*i)); | ||||||
|  |      | ||||||
|     tryNext(); |     tryNext(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -265,8 +265,8 @@ void setReferences(const Transaction & txn, const Path & storePath, | ||||||
| void queryReferences(const Path & storePath, PathSet & references) | void queryReferences(const Path & storePath, PathSet & references) | ||||||
| { | { | ||||||
|     Paths references2; |     Paths references2; | ||||||
|     if (!isValidPath(storePath)) |     //    if (!isValidPath(storePath))
 | ||||||
|         throw Error(format("path `%1%' is not valid") % storePath); |     //        throw Error(format("path `%1%' is not valid") % storePath);
 | ||||||
|     nixDB.queryStrings(noTxn, dbReferences, storePath, references2); |     nixDB.queryStrings(noTxn, dbReferences, storePath, references2); | ||||||
|     references.insert(references2.begin(), references2.end()); |     references.insert(references2.begin(), references2.end()); | ||||||
| } | } | ||||||
|  | @ -275,8 +275,8 @@ void queryReferences(const Path & storePath, PathSet & references) | ||||||
| void queryReferers(const Path & storePath, PathSet & referers) | void queryReferers(const Path & storePath, PathSet & referers) | ||||||
| { | { | ||||||
|     Paths referers2; |     Paths referers2; | ||||||
|     if (!isValidPath(storePath)) |     //    if (!isValidPath(storePath))
 | ||||||
|         throw Error(format("path `%1%' is not valid") % storePath); |     //        throw Error(format("path `%1%' is not valid") % storePath);
 | ||||||
|     nixDB.queryStrings(noTxn, dbReferers, storePath, referers2); |     nixDB.queryStrings(noTxn, dbReferers, storePath, referers2); | ||||||
|     referers.insert(referers2.begin(), referers2.end()); |     referers.insert(referers2.begin(), referers2.end()); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -177,19 +177,27 @@ static void opSubstitute(Strings opFlags, Strings opArgs) | ||||||
|     while (1) { |     while (1) { | ||||||
|         Path srcPath; |         Path srcPath; | ||||||
|         Substitute sub; |         Substitute sub; | ||||||
|  |         PathSet references; | ||||||
|         getline(cin, srcPath); |         getline(cin, srcPath); | ||||||
|         if (cin.eof()) break; |         if (cin.eof()) break; | ||||||
|         getline(cin, sub.program); |         getline(cin, sub.program); | ||||||
|         string s; |         string s; | ||||||
|         getline(cin, s); |  | ||||||
|         int n; |         int n; | ||||||
|  |         getline(cin, s); | ||||||
|         if (!string2Int(s, n)) throw Error("number expected"); |         if (!string2Int(s, n)) throw Error("number expected"); | ||||||
|         while (n--) { |         while (n--) { | ||||||
|             getline(cin, s); |             getline(cin, s); | ||||||
|             sub.args.push_back(s); |             sub.args.push_back(s); | ||||||
|         } |         } | ||||||
|  |         getline(cin, s); | ||||||
|  |         if (!string2Int(s, n)) throw Error("number expected"); | ||||||
|  |         while (n--) { | ||||||
|  |             getline(cin, s); | ||||||
|  |             references.insert(s); | ||||||
|  |         } | ||||||
|         if (!cin || cin.eof()) throw Error("missing input"); |         if (!cin || cin.eof()) throw Error("missing input"); | ||||||
|         subPairs.push_back(pair<Path, Substitute>(srcPath, sub)); |         subPairs.push_back(pair<Path, Substitute>(srcPath, sub)); | ||||||
|  |         setReferences(txn, srcPath, references); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     registerSubstitutes(txn, subPairs); |     registerSubstitutes(txn, subPairs); | ||||||
|  |  | ||||||
|  | @ -8,7 +8,16 @@ TESTS_ENVIRONMENT = TEST_ROOT=$(TEST_ROOT) \ | ||||||
|   NIX_LOG_DIR=$(TEST_ROOT)/log \ |   NIX_LOG_DIR=$(TEST_ROOT)/log \ | ||||||
|   NIX_STATE_DIR=$(TEST_ROOT)/state \ |   NIX_STATE_DIR=$(TEST_ROOT)/state \ | ||||||
|   NIX_DB_DIR=$(TEST_ROOT)/db \ |   NIX_DB_DIR=$(TEST_ROOT)/db \ | ||||||
|  |   NIX_BIN_DIR=$(TEST_ROOT)/bin \ | ||||||
|  |   NIX_LIBEXEC_DIR=$(TEST_ROOT)/bin \ | ||||||
|  |   NIX_LOCALSTATE_DIR=$(TEST_ROOT)/state \ | ||||||
|  |   REAL_BIN_DIR=$(bindir) \ | ||||||
|  |   REAL_LIBEXEC_DIR=$(libexecdir) \ | ||||||
|  |   REAL_LOCALSTATE_DIR=$(localstatedir) \ | ||||||
|  |   REAL_DATA_DIR=$(datadir) \ | ||||||
|  |   REAL_STORE_DIR=$(storedir) \ | ||||||
|   NIX_BUILD_HOOK= \ |   NIX_BUILD_HOOK= \ | ||||||
|  |   PERL=$(perl) \ | ||||||
|   TOP=$(shell pwd)/.. \ |   TOP=$(shell pwd)/.. \ | ||||||
|   SHARED=$(extra1) \ |   SHARED=$(extra1) \ | ||||||
|   aterm_bin=$(aterm_bin) \ |   aterm_bin=$(aterm_bin) \ | ||||||
|  | @ -22,9 +31,14 @@ build-hook.sh: build-hook.nix | ||||||
| substitutes.sh: substitutes.nix | substitutes.sh: substitutes.nix | ||||||
| substitutes2.sh: substitutes2.nix | substitutes2.sh: substitutes2.nix | ||||||
| fallback.sh: fallback.nix | fallback.sh: fallback.nix | ||||||
|  | nix-push.sh: dependencies.nix | ||||||
|  | nix-pull.sh: dependencies.nix | ||||||
| 
 | 
 | ||||||
| TESTS = init.sh hash.sh lang.sh simple.sh dependencies.sh locking.sh parallel.sh \ | #TESTS = init.sh hash.sh lang.sh simple.sh dependencies.sh locking.sh parallel.sh \ | ||||||
|   build-hook.sh substitutes.sh substitutes2.sh fallback.sh verify.sh | #  build-hook.sh substitutes.sh substitutes2.sh fallback.sh nix-push.sh verify.sh \ | ||||||
|  | #  nix-pull.sh | ||||||
|  | 
 | ||||||
|  | TESTS = init.sh nix-push.sh nix-pull.sh | ||||||
| 
 | 
 | ||||||
| XFAIL_TESTS = | XFAIL_TESTS = | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -13,6 +13,36 @@ mkdir "$NIX_LOG_DIR" | ||||||
| mkdir "$NIX_STATE_DIR" | mkdir "$NIX_STATE_DIR" | ||||||
| mkdir "$NIX_DB_DIR" | mkdir "$NIX_DB_DIR" | ||||||
| 
 | 
 | ||||||
|  | mkdir $NIX_BIN_DIR | ||||||
|  | ln -s $TOP/src/nix-store/nix-store $NIX_BIN_DIR/ | ||||||
|  | ln -s $TOP/src/nix-instantiate/nix-instantiate $NIX_BIN_DIR/ | ||||||
|  | ln -s $TOP/src/nix-hash/nix-hash $NIX_BIN_DIR/ | ||||||
|  | ln -s $TOP/scripts/nix-prefetch-url $NIX_BIN_DIR/ | ||||||
|  | mkdir $NIX_BIN_DIR/nix | ||||||
|  | ln -s $TOP/scripts/download-using-manifests.pl $NIX_BIN_DIR/nix/ | ||||||
|  | ln -s $TOP/scripts/readmanifest.pm $NIX_BIN_DIR/nix/ | ||||||
|  | 
 | ||||||
|  | mkdir -p "$NIX_LOCALSTATE_DIR"/nix/manifests | ||||||
|  | mkdir -p "$NIX_LOCALSTATE_DIR"/log/nix | ||||||
|  | 
 | ||||||
|  | mkdir $NIX_DATA_DIR/nix | ||||||
|  | cp -prd $TOP/corepkgs $NIX_DATA_DIR/nix/ | ||||||
|  | # Bah, script has the prefix hard-coded. | ||||||
|  | for i in $NIX_DATA_DIR/nix/corepkgs/nar/nar.sh \ | ||||||
|  |     $NIX_BIN_DIR/nix/download-using-manifests.pl \ | ||||||
|  |     $NIX_BIN_DIR/nix-prefetch-url \ | ||||||
|  |     ; do | ||||||
|  |     echo "$REAL_BIN_DIR" | ||||||
|  |     sed < $i > $i.tmp \ | ||||||
|  |         -e "s^$REAL_BIN_DIR^$NIX_BIN_DIR^" \ | ||||||
|  |         -e "s^$REAL_LIBEXEC_DIR^$NIX_LIBEXEC_DIR^" \ | ||||||
|  |         -e "s^$REAL_LOCALSTATE_DIR^$NIX_LOCALSTATE_DIR^" \ | ||||||
|  |         -e "s^$REAL_DATA_DIR^$NIX_DATA_DIR^" \ | ||||||
|  |         -e "s^$REAL_STORE_DIR^$NIX_STORE_DIR^" | ||||||
|  |     mv $i.tmp $i | ||||||
|  |     chmod +x $i | ||||||
|  | done | ||||||
|  | 
 | ||||||
| # Initialise the database. | # Initialise the database. | ||||||
| $TOP/src/nix-store/nix-store --init | $TOP/src/nix-store/nix-store --init | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										33
									
								
								tests/nix-pull.sh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								tests/nix-pull.sh
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,33 @@ | ||||||
|  | clearStore () { | ||||||
|  |     echo "clearing store..." | ||||||
|  |     chmod -R +w "$NIX_STORE_DIR" | ||||||
|  |     rm -rf "$NIX_STORE_DIR" | ||||||
|  |     mkdir "$NIX_STORE_DIR" | ||||||
|  |     rm -rf "$NIX_DB_DIR" | ||||||
|  |     mkdir "$NIX_DB_DIR" | ||||||
|  |     $TOP/src/nix-store/nix-store --init | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pullCache () { | ||||||
|  |     echo "pulling cache..." | ||||||
|  |     $PERL -w -I$TOP/scripts $TOP/scripts/nix-pull file://$TEST_ROOT/manifest | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | clearStore | ||||||
|  | pullCache | ||||||
|  | 
 | ||||||
|  | drvPath=$($TOP/src/nix-instantiate/nix-instantiate dependencies.nix) | ||||||
|  | outPath=$($TOP/src/nix-store/nix-store -q $drvPath) | ||||||
|  | 
 | ||||||
|  | echo "building $outPath using substitutes..." | ||||||
|  | $TOP/src/nix-store/nix-store -r $outPath | ||||||
|  | 
 | ||||||
|  | cat $outPath/input-2/bar | ||||||
|  | 
 | ||||||
|  | clearStore | ||||||
|  | pullCache | ||||||
|  | 
 | ||||||
|  | echo "building $drvPath using substitutes..." | ||||||
|  | $TOP/src/nix-store/nix-store -r $drvPath | ||||||
|  | 
 | ||||||
|  | cat $outPath/input-2/bar | ||||||
							
								
								
									
										9
									
								
								tests/nix-push.sh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								tests/nix-push.sh
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | ||||||
|  | drvPath=$($TOP/src/nix-instantiate/nix-instantiate dependencies.nix) | ||||||
|  | outPath=$($TOP/src/nix-store/nix-store -r $drvPath) | ||||||
|  | 
 | ||||||
|  | echo "pushing $drvPath" | ||||||
|  | 
 | ||||||
|  | mkdir $TEST_ROOT/cache | ||||||
|  | 
 | ||||||
|  | $PERL -w -I$TOP/scripts $TOP/scripts/nix-push \ | ||||||
|  |     --copy $TEST_ROOT/cache $TEST_ROOT/manifest $drvPath | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue