This operation allows fixing corrupted or accidentally deleted store paths by redownloading them using substituters, if available. Since the corrupted path cannot be replaced atomically, there is a very small time window (one system call) during which neither the old (corrupted) nor the new (repaired) contents are available. So repairing should be used with some care on critical packages like Glibc.
		
			
				
	
	
		
			98 lines
		
	
	
	
		
			2.7 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			98 lines
		
	
	
	
		
			2.7 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable file
		
	
	
	
	
| #! @perl@ -w @perlFlags@
 | |
| 
 | |
| use strict;
 | |
| use File::Basename;
 | |
| use IO::Handle;
 | |
| 
 | |
| my $binDir = $ENV{"NIX_BIN_DIR"} || "@bindir@";
 | |
| 
 | |
| 
 | |
| STDOUT->autoflush(1);
 | |
| 
 | |
| my @remoteStoresAll = split ':', ($ENV{"NIX_OTHER_STORES"} or "");
 | |
| 
 | |
| my @remoteStores;
 | |
| foreach my $dir (@remoteStoresAll) {
 | |
|     push @remoteStores, glob($dir);
 | |
| }
 | |
| 
 | |
| 
 | |
| $ENV{"NIX_REMOTE"} = "";
 | |
| 
 | |
| 
 | |
| sub findStorePath {
 | |
|     my $storePath = shift;
 | |
|     foreach my $store (@remoteStores) {
 | |
|         my $sourcePath = "$store/store/" . basename $storePath;
 | |
|         next unless -e $sourcePath || -l $sourcePath;
 | |
|         $ENV{"NIX_DB_DIR"} = "$store/var/nix/db";
 | |
|         return ($store, $sourcePath) if
 | |
|             system("@bindir@/nix-store --check-validity $storePath") == 0;
 | |
|     }
 | |
|     return undef;
 | |
| }
 | |
| 
 | |
| 
 | |
| if ($ARGV[0] eq "--query") {
 | |
| 
 | |
|     while (<STDIN>) {
 | |
|         chomp;
 | |
|         my ($cmd, @args) = split " ", $_;
 | |
| 
 | |
|         if ($cmd eq "have") {
 | |
|             foreach my $storePath (@args) {
 | |
|                 print "$storePath\n" if defined findStorePath($storePath);
 | |
|             }
 | |
|             print "\n";
 | |
|         }
 | |
| 
 | |
|         elsif ($cmd eq "info") {
 | |
|             foreach my $storePath (@args) {
 | |
|                 my ($store, $sourcePath) = findStorePath($storePath);
 | |
|                 next unless defined $store;
 | |
| 
 | |
|                 $ENV{"NIX_DB_DIR"} = "$store/var/nix/db";
 | |
| 
 | |
|                 my $deriver = `@bindir@/nix-store --query --deriver $storePath`;
 | |
|                 die "cannot query deriver of `$storePath'" if $? != 0;
 | |
|                 chomp $deriver;
 | |
|                 $deriver = "" if $deriver eq "unknown-deriver";
 | |
| 
 | |
|                 my @references = split "\n",
 | |
|                     `@bindir@/nix-store --query --references $storePath`;
 | |
|                 die "cannot query references of `$storePath'" if $? != 0;
 | |
| 
 | |
|                 my $narSize = `@bindir@/nix-store --query --size $storePath`;
 | |
|                 die "cannot query size of `$storePath'" if $? != 0;
 | |
|                 chomp $narSize;
 | |
| 
 | |
|                 print "$storePath\n";
 | |
|                 print "$deriver\n";
 | |
|                 print scalar @references, "\n";
 | |
|                 print "$_\n" foreach @references;
 | |
|                 print "$narSize\n";
 | |
|                 print "$narSize\n";
 | |
|             }
 | |
| 
 | |
|             print "\n";
 | |
|         }
 | |
| 
 | |
|         else { die "unknown command `$cmd'"; }
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| elsif ($ARGV[0] eq "--substitute") {
 | |
|     die unless scalar @ARGV == 3;
 | |
|     my $storePath = $ARGV[1];
 | |
|     my $destPath = $ARGV[2];
 | |
|     my ($store, $sourcePath) = findStorePath $storePath;
 | |
|     die unless $store;
 | |
|     print STDERR "\n*** Copying `$storePath' from `$sourcePath'\n\n";
 | |
|     system("$binDir/nix-store --dump $sourcePath | $binDir/nix-store --restore $destPath") == 0
 | |
|         or die "cannot copy `$sourcePath' to `$storePath'";
 | |
|     print "\n"; # no hash to verify
 | |
| }
 | |
| 
 | |
| 
 | |
| else { die; }
 |