commit a5c419b7254478168ba6709bd612ca49eef571d4 Author: Eelco Dolstra Date: Thu Apr 16 09:25:42 2009 +0000 * Quick script to mirror Nix channels. Ideally it should be possible to do this with a `wget -r' but the manifest contains absolute rather than relative URLs, so those have to be rewritten. And since they have to be rewritten anyway, we can add size and hash fields to make the manifest compatible with older version of Nix (and make the download size estimate work). git-svn-id: https://nixos.org/repos/nix/release/trunk/channels@15076 70bd8c7a-acb8-0310-9f0d-9cc1c95dcdbb diff --git a/mirror-channel.pl b/mirror-channel.pl new file mode 100644 index 0000000..e72e647 --- /dev/null +++ b/mirror-channel.pl @@ -0,0 +1,74 @@ +use strict; +use readmanifest; +use File::Basename; +use File::stat; +use File::Temp qw/tempfile/; + +if (scalar @ARGV != 3) { + print STDERR "Syntax: perl mirror-channel.pl \n"; + exit 1; +} + +my $srcChannelURL = $ARGV[0]; +my $dstChannelURL = $ARGV[1]; +my $dstChannelPath = $ARGV[2]; + +die "$dstChannelPath doesn't exist\n" unless -d $dstChannelPath; + +my ($fh, $tmpManifest) = tempfile(UNLINK => 1); +print "$tmpManifest\n"; +system("curl '$srcChannelURL/MANIFEST' > $tmpManifest") == 0 or die; + +# Read the manifest. +my %narFiles; +my %localPaths; +my %patches; + +my $version = readManifest($tmpManifest, \%narFiles, \%localPaths, \%patches); + +%localPaths = (); +%patches = (); # not supported yet + +my $size = scalar (keys %narFiles); +print "$size store paths in manifest\n"; + +# Download every file that we don't already have, and update every URL +# to point to the mirror. Also fill in the size and hash fields in +# the manifest in order to be compatible with Nix < 0.13. + +while (my ($storePath, $files) = each %narFiles) { + foreach my $file (@{$files}) { + my $srcURL = $file->{url}; + my $dstName = basename $srcURL; + my $dstFile = "$dstChannelPath/$dstName"; + my $dstURL = "$dstChannelURL/$dstName"; + + $file->{url} = $dstURL; + if (! -e $dstFile) { + print "downloading $srcURL\n"; + my $dstFileTmp = "$dstChannelPath/.tmp.$$.nar.$dstName"; + system("curl '$srcURL' > $dstFileTmp") == 0 or die; + rename($dstFileTmp, $dstFile) or die "cannot rename $dstFileTmp"; + } + + $file->{size} = stat($dstFile)->size or die; + + my $hashFile = "$dstChannelPath/.hash.$dstName"; + my $hash; + if (-e $hashFile) { + open HASH, "<$hashFile" or die; + $hash = ; + close HASH; + } else { + $hash = `nix-hash --flat --type sha256 --base32 '$dstFile'` or die; + chomp $hash; + open HASH, ">$hashFile" or die; + print HASH $hash; + close HASH; + } + $file->{hash} = "sha256:$hash"; + } +} + +# Write the new manifest. +writeManifest("$dstChannelPath/MANIFEST", \%narFiles, \%patches);