#! @perl@ -w @perlFlags@ use strict; use File::Temp qw(tempdir); use Nix::Config; use Nix::Manifest; my $tmpDir = tempdir("nix-pull.XXXXXX", CLEANUP => 1, TMPDIR => 1) or die "cannot create a temporary directory"; my $libexecDir = ($ENV{"NIX_LIBEXEC_DIR"} or "@libexecdir@"); my $storeDir = ($ENV{"NIX_STORE_DIR"} or "@storedir@"); my $stateDir = ($ENV{"NIX_STATE_DIR"} or "@localstatedir@/nix"); my $manifestDir = $Nix::Config::manifestDir; # Prevent access problems in shared-stored installations. umask 0022; # Create the manifests directory if it doesn't exist. if (! -e $manifestDir) { mkdir $manifestDir, 0755 or die "cannot create directory `$manifestDir'"; } # Make sure that the manifests directory is scanned for GC roots. my $gcRootsDir = "$stateDir/gcroots"; my $manifestDirLink = "$gcRootsDir/manifests"; if (! -l $manifestDirLink) { symlink($manifestDir, $manifestDirLink) or die "cannot create symlink `$manifestDirLink'"; } # Process the URLs specified on the command line. my %narFiles; my %patches; my $skipWrongStore = 0; sub downloadFile { my $url = shift; $ENV{"PRINT_PATH"} = 1; $ENV{"QUIET"} = 1; my ($dummy, $path) = `$Nix::Config::binDir/nix-prefetch-url '$url'`; die "cannot fetch `$url'" if $? != 0; die "nix-prefetch-url did not return a path" unless defined $path; chomp $path; return $path; } sub processURL { my $url = shift; $url =~ s/\/$//; my $manifest; # First see if a bzipped manifest is available. if (system("$Nix::Config::curl --fail --silent --head '$url'.bz2 > /dev/null") == 0) { print "fetching list of Nix archives at `$url.bz2'...\n"; my $bzipped = downloadFile "$url.bz2"; $manifest = "$tmpDir/MANIFEST"; system("$Nix::Config::bzip2 -d < $bzipped > $manifest") == 0 or die "cannot decompress manifest"; $manifest = (`$Nix::Config::binDir/nix-store --add $manifest` or die "cannot copy $manifest to the store"); chomp $manifest; } # Otherwise, just get the uncompressed manifest. else { print "obtaining list of Nix archives at `$url'...\n"; $manifest = downloadFile $url; } my $version = readManifest($manifest, \%narFiles, \%patches); die "`$url' is not a manifest or it is too old (i.e., for Nix <= 0.7)\n" if $version < 3; die "manifest `$url' is too new\n" if $version >= 5; if ($skipWrongStore) { foreach my $path (keys %narFiles) { if (substr($path, 0, length($storeDir) + 1) ne "$storeDir/") { print STDERR "warning: manifest `$url' assumes a Nix store at a different location than $storeDir, skipping...\n"; exit 0; } } } my $baseName = "unnamed"; if ($url =~ /\/([^\/]+)\/[^\/]+$/) { # get the forelast component $baseName = $1; } my $hash = `$Nix::Config::binDir/nix-hash --flat '$manifest'` or die "cannot hash `$manifest'"; chomp $hash; my $urlFile = "$manifestDir/$baseName-$hash.url"; open URL, ">$urlFile" or die "cannot create `$urlFile'"; print URL "$url"; close URL; my $finalPath = "$manifestDir/$baseName-$hash.nixmanifest"; unlink $finalPath if -e $finalPath; symlink("$manifest", "$finalPath") or die "cannot link `$finalPath to `$manifest'"; # Delete all old manifests downloaded from this URL. for my $urlFile2 (glob "$manifestDir/*.url") { next if $urlFile eq $urlFile2; open URL, "<$urlFile2" or die; my $url2 = ; chomp $url2; close URL; next unless $url eq $url2; my $base = $urlFile2; $base =~ s/.url$//; unlink "${base}.url"; unlink "${base}.nixmanifest"; } } while (@ARGV) { my $url = shift @ARGV; if ($url eq "--skip-wrong-store") { $skipWrongStore = 1; } else { processURL $url; } } my $size = scalar (keys %narFiles); print "$size store paths in manifest\n";