From a5c419b7254478168ba6709bd612ca49eef571d4 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 16 Apr 2009 09:25:42 +0000 Subject: [PATCH] * 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 --- mirror-channel.pl | 74 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 mirror-channel.pl 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);