X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=dgit.git;a=blobdiff_plain;f=git-debrebase;h=2a28e720b43d3712fb2910902375fb5113e6370b;hp=37982499351e8365da2ef022c71f9abff5873b29;hb=952a781025083b34762fe6bb2093ef64524c23cd;hpb=a7e1b2feb9013251c5d1c763394170acc95eef65 diff --git a/git-debrebase b/git-debrebase index 37982499..2a28e720 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 ($) { @@ -152,6 +154,14 @@ our $snags_summarised = 0; our @deferred_updates; our @deferred_update_messages; +sub merge_wreckage_cleaning ($) { + my ($updates) = @_; + git_for_each_ref("$wrecknoteprefix/*", sub { + my ($objid,$objtype,$fullrefname,$reftail) = @_; + push @$updates, "delete $fullrefname"; + }); +} + sub all_snags_summarised () { $snags_forced + $snags_tripped == $snags_summarised; } @@ -160,6 +170,7 @@ sub run_deferred_updates ($) { confess 'dangerous internal error' unless all_snags_summarised(); + merge_wreckage_cleaning \@deferred_updates; run_ref_updates_now $mrest, \@deferred_updates; print $_, "\n" foreach @deferred_update_messages; @@ -368,8 +379,36 @@ 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; + merge_wreckage_cleaning \@updates; + 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; } @@ -454,7 +493,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); @@ -1044,7 +1083,8 @@ 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 { &mwrecknote($cl->{MergeWreckNotes}, @_); }; @@ -1053,6 +1093,7 @@ sub walk ($;$$$) { for (;;) { $cl = classify $cur; + $cl->{MergeWreckNotes} //= {}; my $ty = $cl->{Type}; my $st = $cl->{SubType}; $prline->("$cl->{CommitId} $cl->{Type}"); @@ -2594,6 +2635,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"