X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=git-debrebase;h=6211fb633d85ecee3fcb2f6173dde3f9184d0a1f;hb=acec8e4b8dc36601d94159bdac169b8f13e64913;hp=72b48288e7879ef4a799e8065de49a5e08f15bce;hpb=f58777f379b8fea92d8ae4f80c1bba3299d951b3;p=dgit.git diff --git a/git-debrebase b/git-debrebase index 72b48288..6211fb63 100755 --- a/git-debrebase +++ b/git-debrebase @@ -32,6 +32,7 @@ use Dpkg::Version; use File::FnMatch qw(:fnmatch); our ($opt_force, $opt_noop_ok, @opt_anchors); +our ($opt_defaultcmd_interactive); our $us = qw(git-debrebase); @@ -98,12 +99,18 @@ sub fresh_workarea () { in_workarea sub { playtree_setup }; } +our $snags_forced; +our $snags_tripped; +our $snags_checked; our @deferred_updates; our @deferred_update_messages; sub run_deferred_updates ($) { my ($mrest) = @_; + confess 'dangerous internal error' if + !$snags_checked || $snags_tripped || $snags_forced; + my @upd_cmd = (@git, qw(update-ref --stdin -m), "debrebase: $mrest"); debugcmd '>|', @upd_cmd; open U, "|-", @upd_cmd or die $!; @@ -226,8 +233,6 @@ sub make_commit ($$) { } our @snag_force_opts; -our $snags_forced; -our $snags_tripped; sub snag ($$) { my ($tag,$msg) = @_; if (grep { $_ eq $tag } @snag_force_opts) { @@ -240,16 +245,19 @@ sub snag ($$) { } sub snags_maybe_bail () { + $snags_checked++; if ($snags_forced) { printf STDERR "%s: snags: %d overriden by individual -f options\n", $us, $snags_forced; + $snags_forced=0; } if ($snags_tripped) { if ($opt_force) { printf STDERR "%s: snags: %d overriden by global --force\n", $us, $snags_tripped; + $snags_tripped=0; } else { fail sprintf "%s: snags: %d blockers (you could -f, or --force)", @@ -395,6 +403,15 @@ sub classify ($) { # BreakwaterStart commits are also anchors in the terminology # of git-debrebase(5), but they are untagged (and always # manually generated). + # + # We cannot not tolerate any tagged linear commit (ie, + # BreakwaterStart commits tagged `[anchor:') because such a + # thing could result from an erroneous linearising raw git + # rebase of a merge anchor. That would represent a corruption + # of the branch. and we want to detect and reject the results + # of such corruption before it makes it out anywhere. If we + # reject it here then we avoid making the pseudomerge which + # would be needed to push it. my $badanchor = sub { $unknown->("git-debrebase \`anchor' but @_"); }; @p == 2 or return $badanchor->("has other than two parents"); @@ -550,7 +567,7 @@ sub keycommits ($;$$$) { $breakwater = undef; } elsif ($ty eq 'Mixed') { $x->($unclean, 'mixed', - 'found mixed upstream/packaging commit ($head)'); + "found mixed upstream/packaging commit ($head)"); $clogonly = undef; $breakwater = undef; } elsif ($ty eq 'Pseudomerge' or @@ -891,6 +908,7 @@ sub do_launder_head ($) { my $old = get_head(); record_ffq_auto(); my ($tip,$breakwater) = walk $old; + snags_maybe_bail(); update_head_postlaunder $old, $tip, $reflogmsg; return ($tip,$breakwater); } @@ -906,8 +924,9 @@ sub cmd_launder_v0 () { } sub defaultcmd_rebase () { + push @ARGV, @{ $opt_defaultcmd_interactive // [] }; my ($tip,$breakwater) = do_launder_head 'launder for rebase'; - runcmd @git, qw(rebase), @ARGV, $breakwater; + runcmd @git, qw(rebase), @ARGV, $breakwater if @ARGV; } sub cmd_analyse () { @@ -1072,8 +1091,8 @@ sub stitch ($$$$$) { update_head $old_head, $new_head, "stitch: $prose"; } -sub do_stitch ($) { - my ($prose) = @_; +sub do_stitch ($;$) { + my ($prose, $unclean) = @_; my ($ffq_prev, $gdrlast, $ffq_prev_commitish) = ffq_prev_info(); if (!$ffq_prev_commitish) { @@ -1082,7 +1101,8 @@ sub do_stitch ($) { } my $dangling_head = get_head(); - keycommits $dangling_head, \&snag, \&snag, \&snag; + keycommits $dangling_head, $unclean,$unclean,$unclean; + snags_maybe_bail(); stitch($dangling_head, $ffq_prev, $gdrlast, $ffq_prev_commitish, $prose); } @@ -1232,6 +1252,10 @@ sub cmd_new_upstream_v0 () { "[git-debrebase anchor: new upstream $new_upstream_version, merge]", ]; + my $clogsignoff = cmdoutput qw(git show), + '--pretty=format:%an <%ae> %aD', + $new_bw; + # Now we have to add a changelog stanza so the Debian version # is right. die if unlink "debian"; @@ -1248,7 +1272,7 @@ $p ($new_version) UNRELEASED; urgency=medium * Update to new upstream version $new_upstream_version. - -- + -- $clogsignoff END close CN or die $!; @@ -1301,13 +1325,27 @@ sub cmd_stitch () { my $prose = 'stitch'; GetOptions('prose=s', \$prose) or die badusage("bad options to stitch"); badusage "no arguments allowed" if @ARGV; - do_stitch($prose); + do_stitch $prose, 0; +} +sub cmd_prepush () { cmd_stitch(); } + +sub cmd_quick () { + badusage "no arguments allowed" if @ARGV; + do_launder_head 'launder for git-debrebase quick'; + do_stitch 'quick', \&snag; } sub cmd_conclude () { + my ($ffq_prev, $gdrlast, $ffq_prev_commitish) = ffq_prev_info(); + if (!$ffq_prev_commitish) { + fail "No ongoing git-debrebase session." unless $opt_noop_ok; + return; + } + my $dangling_head = get_head(); + badusage "no arguments allowed" if @ARGV; - do_launder_head 'launder for conclude'; - do_stitch 'conclude'; + do_launder_head 'launder for git-debrebase quick'; + do_stitch 'quick', \&snag; } sub cmd_convert_from_gbp () { @@ -1400,6 +1438,7 @@ sub cmd_convert_to_gbp () { push @deferred_updates, "delete $ffq"; push @deferred_updates, "delete $gdrlast"; } + snags_maybe_bail(); update_head_checkout $head, $out, "convert to gbp (v0)"; print < \$debuglevel, 'noop-ok', => \$opt_noop_ok, 'f=s' => \@snag_force_opts, 'anchor=s' => \@opt_anchors, - 'force!') or die badusage "bad options\n"; + 'force!', + '-i:s' => sub { + my ($opt,$val) = @_; + badusage "git-debrebase: no cuddling to -i for git-rebase" + if length $val; + die if $opt_defaultcmd_interactive; # should not happen + $opt_defaultcmd_interactive = [ qw(-i) ]; + # This access to @ARGV is excessive familiarity with + # Getopt::Long, but there isn't another sensible + # approach. '-i=s{0,}' does not work with bundling. + push @$opt_defaultcmd_interactive, @ARGV; + @ARGV=(); + }) or die badusage "bad options\n"; initdebug('git-debrebase '); enabledebug if $debuglevel; @@ -1472,7 +1523,7 @@ $rd = fresh_playground "$playprefix/misc"; @opt_anchors = map { git_rev_parse $_ } @opt_anchors; -if (!@ARGV || $ARGV[0] =~ m{^-}) { +if (!@ARGV || $opt_defaultcmd_interactive || $ARGV[0] =~ m{^-}) { defaultcmd_rebase(); } else { my $cmd = shift @ARGV;