X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=dgit.git;a=blobdiff_plain;f=git-debrebase;h=589fa901af95f5b1158f850b205e9defc20331ac;hp=d101742114246a8bd61f63c102bad234252b1eac;hb=332806a67a034c88c2884b516ce2aaf8b317dd25;hpb=c1e0f468347b80d739d6eefa9eb9d614b18c3c15 diff --git a/git-debrebase b/git-debrebase index d1017421..589fa901 100755 --- a/git-debrebase +++ b/git-debrebase @@ -51,10 +51,12 @@ See git-debrebase(1), git-debrebase(5), dgit-maint-debrebase(7) (in dgit). END our ($opt_force, $opt_noop_ok, @opt_anchors); -our ($opt_defaultcmd_interactive); +our ($opt_defaultcmd_interactive, $opt_save_wreckage); our $us = qw(git-debrebase); +our $wrecknoteprefix = 'refs/debrebase-wreckage'; + $|=1; sub badusage ($) { @@ -131,6 +133,21 @@ sub fresh_workarea () { in_workarea sub { playtree_setup }; } +sub run_ref_updates_now ($$) { + my ($mrest, $updates) = @_; + # @$updates is a list of lines for git-update-ref, without \ns + + my @upd_cmd = (git_update_ref_cmd "debrebase: $mrest", qw(--stdin)); + debugcmd '>|', @upd_cmd; + open U, "|-", @upd_cmd or die $!; + foreach (@$updates) { + printdebug ">= ", $_, "\n"; + print U $_, "\n" or die $!; + } + printdebug ">\$\n"; + close U or failedcmd @upd_cmd; +} + our $snags_forced = 0; our $snags_tripped = 0; our $snags_summarised = 0; @@ -145,16 +162,7 @@ sub run_deferred_updates ($) { confess 'dangerous internal error' unless all_snags_summarised(); - my @upd_cmd = (git_update_ref_cmd "debrebase: $mrest", qw(--stdin)); - debugcmd '>|', @upd_cmd; - open U, "|-", @upd_cmd or die $!; - foreach (@deferred_updates) { - printdebug ">= ", $_, "\n"; - print U $_, "\n" or die $!; - } - printdebug ">\$\n"; - close U or failedcmd @upd_cmd; - + run_ref_updates_now $mrest, \@deferred_updates; print $_, "\n" foreach @deferred_update_messages; @deferred_updates = (); @@ -362,6 +370,42 @@ sub gbp_pq_export ($$$) { # our own patch identification algorithm? # this is an alternative strategy +sub merge_failed ($$) { + my ($wrecknotes, $emsg) = @_; + my @m; + push @m, "Merge resolution failed: $emsg"; + + $opt_save_wreckage //= do { + my $c = cfg 'git-debrebase.merge.save-wreckage', 1; + # ^ xxx documentation + $c && $c =~ m/^[1ty]/; + }; + + if ($opt_save_wreckage) { + my @updates; + git_for_each_ref("$wrecknoteprefix/*", sub { + my ($objid,$objtype,$fullrefname,$reftail) = @_; + push @updates, "delete $fullrefname"; + }); + keys %$wrecknotes; + while (my ($k,$v) = each %$wrecknotes) { + push @updates, "create $wrecknoteprefix/$k $v"; + } + run_ref_updates_now "merge failed", \@updates; + push @m, "Wreckage left in $wrecknoteprefix/* as requested."; + } + push @m, "See git-debrebase(1) section FAILED MERGES for suggestions."; + # ^ xxx this section does not yet exist + fail join '', map { "$_\n" } @m; +} + +sub mwrecknote ($$$) { + my ($wrecknotes, $reftail, $commitish) = @_; + confess unless defined $commitish; + printdebug "mwrecknote $reftail $commitish\n"; + $wrecknotes->{$reftail} = $commitish; +} + sub merge_series ($$$;@) { my ($newbase, $wrecknotes, $base_q, @input_qs) = @_; # $base_q{SeriesBase} $input_qs[]{SeriesBase} @@ -388,10 +432,7 @@ sub merge_series ($$$;@) { my $result; - my $mwrecknote = sub { - my ($reftail, $commitish) = @_; - $wrecknotes->{$reftail} = $commitish; - }; + my $mwrecknote = sub { &mwrecknote($wrecknotes, @_); }; local $workarea = fresh_playground "$playprefix/merge"; my $seriesfile = "debian/patches/series"; @@ -446,7 +487,7 @@ sub merge_series ($$$;@) { printdebug "pec' $pec\n"; runcmd @git, qw(reset -q --hard), $pec; $q->{MR}{PEC} = $pec; - $mwrecknote->("$q->{LeftRight}-patchqueue"); + $mwrecknote->("$q->{LeftRight}-patchqueue", $pec); } # now, because of reverse, we are on $input_q->{MR}{OQC} runcmd @git, qw(checkout -q -b merge); @@ -1036,18 +1077,17 @@ sub walk ($;$$$) { }; my $nomerge = sub { - fail "something useful about failed merge attempt @_ xxx".Dumper($cl); + my ($emsg) = @_; + merge_failed $cl->{MergeWreckNotes}, $emsg; }; - my $mwrecknote = sub { - my ($reftail, $commitish) = @_; - $cl->{MergeWreckNotes}{$reftail} = $commitish; - }; + my $mwrecknote = sub { &mwrecknote($cl->{MergeWreckNotes}, @_); }; my $last_anchor; for (;;) { $cl = classify $cur; + $cl->{MergeWreckNotes} //= {}; my $ty = $cl->{Type}; my $st = $cl->{SubType}; $prline->("$cl->{CommitId} $cl->{Type}"); @@ -2589,6 +2629,7 @@ getoptions_main 'anchor=s' => \@opt_anchors, '--dgit=s' => \($dgit[0]), 'force!', + '--save-wreckage', \$opt_save_wreckage, '-i:s' => sub { my ($opt,$val) = @_; badusage "git-debrebase: no cuddling to -i for git-rebase"