chiark / gitweb /
git-debrebase: test suite: test ff stitching
[dgit.git] / git-debrebase
index 92fa86b7483ca92cea57de2bafb7835573068961..a5329b6b117ffe27211282038edcc40aefd4e32d 100755 (executable)
@@ -29,8 +29,8 @@
 #    git-debrebase [<options> --] [<git-rebase options...>]
 #    git-debrebase [<options>] analyse
 #    git-debrebase [<options>] breakwater      # prints breakwater tip only
-#    git-debrebase [<options>] launder         # prints breakwater tip etc.
 #    git-debrebase [<options>] stitch [--prose=<for commit message>]
+#    git-debrebase [<options>] launder-v0      # prints breakwater tip etc.
 #    git-debrebase [<options>] downstream-rebase-launder-v0  # experimental
 #
 #    git-debrebase [<options>] convert-from-gbp [<upstream-git-rev>]
@@ -412,7 +412,7 @@ sub classify ($) {
 
        my $badanchor = sub { $unknown->("git-debrebase \`anchor' but @_"); };
        @p == 2 or return $badanchor->("has other than two parents");
-       $haspatches and return $unknown->("contains debian/patches");
+       $haspatches and return $badanchor->("contains debian/patches");
 
        # How to decide about l/r ordering of anchors ?  git
        # --topo-order prefers to expand 2nd parent first.  There's
@@ -421,26 +421,14 @@ sub classify ($) {
        # way also there's also an easy rune to look for the upstream
        # patches (--topo-order).
 
-       # The above tells us which way *we* will generate them.  But we
-       # might encounter ad-hoc anchor merges generated manually,
-       # which might be the other way around.  In principle, in some odd
-       # situations, an anchor merge might have two identical parents.
-       # In that case we guess which way round it is (ie, which parent
-       # has the upstream history).  The order of the 2-iteration loop
-       # controls which guess we make.
-
-       # XXX we are going to desupport non-git-debrebase-generated anchors
-
-       foreach my $prevbrw (qw(0 1)) {
-           if (!$p[$prevbrw]{IsOrigin} && # breakwater never starts with an origin
-               !($p[!$prevbrw]{Differs} & ~DS_DEB) && # no non-debian changess
-               !($p[$prevbrw]{Differs} & ~D_UPS)) { # no non-upstream changes
-               return $classify->(qw(Anchor),
-                                  OrigParents => [ $p[!$prevbrw] ]);
-           }
-       }
+       $p[0]{IsOrigin} and $badanchor->("is an origin commit");
+       $p[1]{Differs} & ~DS_DEB and
+           $badanchor->("upstream files differ from left parent");
+       $p[0]{Differs} & ~D_UPS and
+           $badanchor->("debian/ differs from right parent");
 
-       $badanchor->("violation");
+       return $classify->(qw(Anchor),
+                          OrigParents => [ $p[1] ]);
     }
 
     if (@p == 1) {
@@ -584,8 +572,9 @@ sub walk ($;$$) {
        return (Msg => $ms);
     };
     my $rewrite_from_here = sub {
+       my ($cl) = @_;
        my $sp_cl = { SpecialMethod => 'StartRewrite' };
-       push @brw_cl, $sp_cl;
+       push @$cl, $sp_cl;
        push @processed, $sp_cl;
     };
     my $cur = $input;
@@ -635,7 +624,7 @@ sub walk ($;$$) {
        my $p0 = @{ $cl->{Parents} }==1 ? $cl->{Parents}[0]{CommitId} : undef;
        if ($ty eq 'AddPatches') {
            $cur = $p0;
-           $rewrite_from_here->();
+           $rewrite_from_here->(\@upp_cl);
            next;
        } elsif ($ty eq 'Packaging' or $ty eq 'Changelog') {
            push @brw_cl, $cl;
@@ -656,14 +645,14 @@ sub walk ($;$$) {
            };
            $queue->(\@brw_cl, "debian");
            $queue->(\@upp_cl, "upstream");
-           $rewrite_from_here->();
+           $rewrite_from_here->(\@brw_cl);
            $cur = $p0;
            next;
        } elsif ($ty eq 'Pseudomerge') {
            my $contrib = $cl->{Contributor}{CommitId};
            print $report " Contributor=$contrib" if $report;
            push @pseudomerges, $cl;
-           $rewrite_from_here->();
+           $rewrite_from_here->(\@upp_cl);
            $cur = $contrib;
            next;
        } elsif ($ty eq 'Anchor') {
@@ -712,7 +701,7 @@ sub walk ($;$$) {
                            " anchor")
                };
                $prline->(" Import");
-               $rewrite_from_here->();
+               $rewrite_from_here->(\@brw_cl);
                $upp_limit //= $#upp_cl; # further, deeper, patches discarded
                $cur = $ovwr;
                next;
@@ -869,8 +858,8 @@ sub update_head_postlaunder ($$$) {
     runcmd @git, qw(rm --quiet --ignore-unmatch -rf debian/patches);
 }
 
-sub cmd_launder () {
-    badusage "no arguments to launder allowed" if @ARGV;
+sub cmd_launder_v0 () {
+    badusage "no arguments to launder-v0 allowed" if @ARGV;
     my $old = get_head();
     my ($tip,$breakwater,$last_anchor) = walk $old;
     update_head_postlaunder $old, $tip, 'launder';
@@ -1210,13 +1199,25 @@ sub cmd_stitch () {
     if (!$prev) {
        fail "No ffq-prev to stitch." unless $opt_noop_ok;
     }
-    fresh_workarea();
     my $old_head = get_head();
+    if (is_fast_fwd $old_head, $prev) {
+       my $differs = get_differs $old_head, $prev;
+       unless ($differs & ~D_PAT_ADD) {
+           # ffq-prev is ahead of us, and the only tree changes it has
+           # are possibly addition of things in debian/patches/.
+           # Just wind forwards rather than making a pointless pseudomerge.
+           update_head_checkout $old_head, $prev,
+               "debrebase: stitch (fast forward)";
+           runcmd @git, qw(update-ref -d), $ffq_prev; # should be atomic
+           return;
+       }
+    }
+    fresh_workarea();
     my $new_head = make_commit [ $old_head, $ffq_prev ], [
        'Declare fast forward / record previous work',
         "[git-debrebase pseudomerge: stitch$prose]",
     ];
-    my @upd_cmd = (@git, qw(update-ref --stdin));
+    my @upd_cmd = (@git, qw(update-ref --stdin -m), "debrebase: stitch");
     debugcmd '>|', @upd_cmd;
     open U, "|-", @upd_cmd or die $!;
     my $u = <<END;