diff --git a/scripts/download-using-manifests.pl.in b/scripts/download-using-manifests.pl.in index 058fa9965..eee1bdec2 100644 --- a/scripts/download-using-manifests.pl.in +++ b/scripts/download-using-manifests.pl.in @@ -193,7 +193,7 @@ while (scalar @path > 0) { # Apply the patch. print " applying patch...\n"; - system "bspatch /tmp/nar /tmp/nar2 $patchPath"; + system "@libexecdir@/bspatch /tmp/nar /tmp/nar2 $patchPath"; die "cannot apply patch `$patchPath' to /tmp/nar" if ($? != 0); # Unpack the resulting NAR archive into the target path. diff --git a/scripts/generate-patches.pl b/scripts/generate-patches.pl index b20360fc6..fdbc65ad6 100755 --- a/scripts/generate-patches.pl +++ b/scripts/generate-patches.pl @@ -1,4 +1,4 @@ -#! /usr/bin/perl -w -I. +#! /usr/bin/perl -w -I/home/eelco/nix/scripts use strict; use POSIX qw(tmpnam); @@ -110,6 +110,21 @@ sub getNarBz2 { } +sub containsPatch { + my $patches = shift; + my $storePath = shift; + my $basePath = shift; + my $patchList = $$patches{$storePath}; + return 0 if !defined $patchList; + my $found = 0; + foreach my $patch (@{$patchList}) { + # !!! baseHash might differ + return 1 if $patch->{basePath} eq $basePath; + } + return 0; +} + + # For each output path in the destination, see if we need to / can # create a patch. @@ -159,19 +174,14 @@ foreach my $p (keys %dstOutPaths) { print " $p <- $closest\n"; # If the patch already exists, skip it. - my $patchList = $dstPatches{$p}; - if (defined $patchList) { - my $found = 0; - foreach my $patch (@{$patchList}) { - if ($patch->{basePath} eq $closest) { - # !!! baseHash might differ - print " skipping, already exists\n"; - $found = 1; - last; - } - } - next if $found; + if (containsPatch(\%srcPatches, $p, $closest) || + containsPatch(\%dstPatches, $p, $closest)) + { + print " skipping, already exists\n"; + next; } + +# next; my $srcNarBz2 = getNarBz2 \%srcNarFiles, $closest; my $dstNarBz2 = getNarBz2 \%dstNarFiles, $p; @@ -203,7 +213,7 @@ foreach my $p (keys %dstOutPaths) { } my $finalName = - "$narDiffHash-$name-$closestVersion-to-$version.nar-diff"; + "$narDiffHash-$name-$closestVersion-to-$version.nar-bsdiff"; if (-e "$patchesDir/$finalName") { print " not copying, already exists\n"; @@ -226,5 +236,45 @@ foreach my $p (keys %dstOutPaths) { } } + +# Add in any potentially useful patches in the source (namely, those +# patches that produce either paths in the destination or paths that +# can be used as the base for other useful patches). + +my $changed; +do { + # !!! we repeat this to reach the transitive closure; inefficient + $changed = 0; + + foreach my $p (keys %srcPatches) { + my $patchList = $srcPatches{$p}; + + my $include = 0; + + # Is path $p included in the destination? If so, include + # patches that produce it. + $include = 1 if (defined $dstNarFiles{$p}); + + # Is path $p a path that serves as a base for paths in the + # destination? If so, include patches that produce it. + foreach my $q (keys %dstPatches) { + foreach my $patch (@{$dstPatches{$q}}) { + # !!! check baseHash + $include = 1 if ($p eq $patch->{basePath}); + } + } + + if ($include) { + foreach my $patch (@{$patchList}) { + $changed = 1 if addPatch \%dstPatches, $p, $patch; + } + } + + } + +} while $changed; + + +# Rewrite the manifest of the destination (with the new patches). writeManifest "$dstDir/MANIFEST", \%dstNarFiles, \%dstPatches, \%dstSuccessors; diff --git a/scripts/readmanifest.pm.in b/scripts/readmanifest.pm.in index 31ea5f43c..8b9920b79 100644 --- a/scripts/readmanifest.pm.in +++ b/scripts/readmanifest.pm.in @@ -23,9 +23,9 @@ sub addPatch { } } - if (!$found) { - push @{$patchList}, $patch; - } + push @{$patchList}, $patch if !$found; + + return !$found; }