X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=dgit;h=fedc7fb015d8cd255f568b47e978aa9e0dd887b0;hb=fbdbb1232bc9f06f6da84e07a2f7b0f427ce03ce;hp=5b6f6a1fdade65e6b1a9a6698106cc1c0c60bf57;hpb=fd839af91633221c00872131c34d51e203aa185f;p=dgit.git diff --git a/dgit b/dgit index 5b6f6a1f..fedc7fb0 100755 --- a/dgit +++ b/dgit @@ -71,6 +71,7 @@ our $suite_re = '[-+.0-9a-z]+'; our $cleanmode_re = 'dpkg-source(?:-d)?|git|git-ff|check|none'; our $git_authline_re = '^([^<>]+) \<(\S+)\> (\d+ [-+]\d+)$'; +our $splitbraincache = 'dgit-intern/quilt-cache'; our (@git) = qw(git); our (@dget) = qw(dget); @@ -199,6 +200,10 @@ sub deliberately_not_fast_forward () { } } +sub quiltmode_splitbrain () { + $quilt_mode =~ m/gbp|dpm|unapplied/; +} + #---------- remote protocol support, common ---------- # remote push initiator/responder protocol: @@ -2556,8 +2561,9 @@ sub quiltify_splitbrain_needed () { } } -sub quiltify_splitbrain ($$$$$) { - my ($clogp, $unapplied, $headref, $diffbits, $editedignores) = @_; +sub quiltify_splitbrain ($$$$$$) { + my ($clogp, $unapplied, $headref, $diffbits, + $editedignores, $cachekey) = @_; if ($quilt_mode !~ m/gbp|dpm/) { # treat .gitignore just like any other upstream file $diffbits = { %$diffbits }; @@ -2575,11 +2581,15 @@ sub quiltify_splitbrain ($$$$$) { progress "creating patches-applied version using gbp-pq"; open STDOUT, ">/dev/null" or die $!; runcmd shell_cmd 'exec >/dev/null', @gbppq, qw(import); + # gbp-pq import creates a fresh branch; push back to dgit-view + runcmd @git, qw(update-ref refs/heads/dgit-view HEAD); + runcmd @git, qw(checkout dgit-view); } if (($diffbits->{H2O} & 02) && # user has modified .gitignore !($diffbits->{O2A} & 02)) { # patches do not change .gitignore quiltify_splitbrain_needed(); progress "creating patch to represent .gitignore changes"; + ensuredir "debian/patches"; my $gipatch = "debian/patches/auto-gitignore"; open GIPATCH, ">>", "$gipatch" or die "$gipatch: $!"; stat GIPATCH or die "$gipatch: $!"; @@ -2595,11 +2605,31 @@ updates to users of the official Debian archive view of the package. [dgit version $our_version] --- END - die 'xxx gitignore'; - - } - die 'xxx memoisation via git-reflog'; + close GIPATCH or die "$gipatch: $!"; + runcmd shell_cmd "exec >>$gipatch", @git, qw(diff), + $unapplied, $headref, "--", sort keys %$editedignores; + open SERIES, "+>>", "debian/patches/series" or die $!; + defined seek SERIES, -1, 2 or $!==EINVAL or die $!; + my $newline; + defined read SERIES, $newline, 1 or die $!; + print SERIES "\n" or die $! unless $newline eq "\n"; + print SERIES "auto-gitignore\n" or die $!; + close SERIES or die $!; + runcmd @git, qw(add -- debian/patches/series), $gipatch; + commit_admin "Commit patch to update .gitignore"; + } + + my $dgitview = git_rev_parse 'refs/heads/dgit-view'; + + changedir '../../../..'; + ensuredir ".git/logs/refs/dgit-intern"; + my $makelogfh = new IO::File ".git/logs/refs/$splitbraincache", '>>' + or die $!; + runcmd @git, qw(update-ref -m), $cachekey, "refs/$splitbraincache", + $dgitview; + die 'xxx fast forward (should not depend on quilt mode, but will always be needed if we did $split_brain)'; + changedir '.git/dgit/unpack/work'; } sub quiltify ($$$$) { @@ -3011,6 +3041,63 @@ END $dscaddfile->($debtar); close $fakedsc or die $!; + my $splitbrain_cachekey; + if (quiltmode_splitbrain()) { + # we look in the reflog of dgit-intern/quilt-cache + # we look for an entry whose message is the key for the cache lookup + my @cachekey = (qw(dgit), $our_version); + push @cachekey, $upstreamversion; + push @cachekey, $headref; + + push @cachekey, hashfile('fake.dsc'); + + my $srcshash = Digest::SHA->new(256); + my %sfs = ( %INC, '$0(dgit)' => $0 ); + foreach my $sfk (sort keys %sfs) { + $srcshash->add($sfk," "); + $srcshash->add(hashfile($sfs{$sfk})); + $srcshash->add("\n"); + } + push @cachekey, $srcshash->hexdigest(); + $splitbrain_cachekey = "@cachekey"; + + my @cmd = (@git, qw(reflog), '--pretty=format:%H %gs', + $splitbraincache); + printdebug "splitbrain cachekey $splitbrain_cachekey\n"; + debugcmd "|(probably)",@cmd; + my $child = open GC, "-|"; defined $child or die $!; + if (!$child) { + chdir '../../..' or die $!; + if (!stat ".git/logs/refs/$splitbraincache") { + $! == ENOENT or die $!; + printdebug ">(no reflog)\n"; + exit 0; + } + exec @cmd; die $!; + } + while () { + chomp; + printdebug ">| ", $_, "\n" if $debuglevel > 1; + next unless m/^(\w+) (\S.*\S)$/ && $2 eq $splitbrain_cachekey; + + my $cachehit = $1; + quilt_fixup_mkwork($headref); + if ($cachehit ne $headref) { + progress "quilt fixup ($quilt_mode mode) found cached tree"; + runcmd @git, qw(checkout -q -b dgit-view), $cachehit; + $split_brain = 1; + return; + } + progress "quilt fixup ($quilt_mode mode)". + " found cached indication that no changes needed"; + return; + } + die $! if GC->error; + failedcmd unless close GC; + + printdebug "splitbrain cache miss\n"; + } + runcmd qw(sh -ec), 'exec dpkg-source --no-check --skip-patches -x fake.dsc >/dev/null'; @@ -3090,9 +3177,10 @@ END push @failsuggestion, "Maybe you need to specify one of". " --quilt=gbp --quilt=dpm --quilt=unapplied ?"; - if ($quilt_mode =~ m/gbp|dpm|unapplied/) { + if (quiltmode_splitbrain()) { quiltify_splitbrain($clogp, $unapplied, $headref, - $diffbits, \%editedignores); + $diffbits, \%editedignores, + $splitbrain_cachekey); return; }