chiark / gitweb /
git-debrebase: merge: Comment about laundry of merge of unstitched
[dgit.git] / git-debrebase
index b015e885a2bb195cec1418c0123ae366cd5e41b4..2b257dd6bfea76d923a1e3da918f10c4d911ac1d 100755 (executable)
@@ -36,6 +36,8 @@ use Dpkg::Version;
 use File::FnMatch qw(:fnmatch);
 use File::Copy;
 
+$debugcmd_when_debuglevel = 2;
+
 our ($usage_message) = <<'END';
 usages:
   git-debrebase [<options>] [--|-i <git rebase options...>]
@@ -226,7 +228,7 @@ sub get_differs ($$) {
            unless $differs & (D_PAT_ADD|D_PAT_OTH);
     }
 
-    printdebug sprintf "get_differs %s, %s = %#x\n", $x, $y, $differs;
+    printdebug sprintf "get_differs %s %s = %#x\n", $x, $y, $differs;
 
     return $differs;
 }
@@ -329,6 +331,7 @@ sub gbp_pq_export ($$$) {
     # must be run in a workarea.  $bname and patch-queue/$bname
     # ought not to exist.  Leaves you on patch-queue/$bname with
     # the patches staged but not committed.
+    printdebug "gbp_pq_export $bname $base $tip\n";
     runcmd @git, qw(checkout -q -b), $bname, $base;
     runcmd @git, qw(checkout -q -b), "patch-queue/$bname", $tip;
     my @gbp_cmd = (qw(gbp pq export));
@@ -341,11 +344,11 @@ sub gbp_pq_export ($$$) {
 }
 
 
-# xxx allow merge separately from laundering
+# xxx allow merge resolution separately from laundering, before git merge
 #
-# xxx docs highlight forbidden things
-# xxx docs list allowable things ?
-# xxx docs explicitly forbid some rebase
+# xxx general gdr docs highlight forbidden things
+# xxx general gdr docs list allowable things ?
+# xxx general gdr docs explicitly forbid some rebase
 #
 # xxx provide a way for the user to help
 # xxx (eg, provide wreckage provide way to continue)
@@ -369,6 +372,8 @@ sub merge_series ($$;@) {
 
     # Creates, in *_q, a key MR for its private use
 
+    printdebug "merge_series newbase=$newbase\n";
+
     $input_qs[$_]{MR}{S} = $_ foreach (0..$#input_qs);
     $base_q->{MR}{S} = 'base';
 
@@ -390,6 +395,7 @@ sub merge_series ($$;@) {
                my @earlier;
                while (my $patch = <S>) {
                    chomp $patch or die $!;
+                   $prereq{$patch} //= {};
                    foreach my $earlier (@earlier) {
                        $prereq{$patch}{$earlier}{$s}++ and die;
                    }
@@ -407,17 +413,20 @@ sub merge_series ($$;@) {
                 "[git-debrebase merge-innards patch-queue import:".
                 " $q->{SeriesTip}]"
             ];
+           printdebug "merge_series  pec $pec ";
            runcmd @git, qw(rm -q --cached), $seriesfile;
            $pec = make_commit [ $pec ], [
                 "Drop series file from $s to avoid merge trouble",
                 "[git-debrebase merge-innards patch-queue prep:".
                 " $q->{SeriesTip}]"
             ];
+           printdebug "pec' $pec\n";
             runcmd @git, qw(reset -q --hard), $pec;
            $q->{MR}{PEC} = $pec;
        }
        # now, because of reverse, we are on $input_q->{MR}{OQC}
        runcmd @git, qw(checkout -q -b merge);
+       printdebug "merge_series merging...\n";
        my @mergecmd = (@git, qw(merge --quiet --no-edit), "p-1");
        debugcmd '+', @mergecmd;
        $!=0; $?=-1;
@@ -425,23 +434,29 @@ sub merge_series ($$;@) {
            failedcmd @mergecmd;
        }
 
+       printdebug "merge_series merge ok, series...\n";
        # We need to construct a new series file
        # Firstly, resolve prereq
-       foreach my $f (keys %prereq) {
+       foreach my $f (sort keys %prereq) {
+           printdebug "merge_series  patch\t$f\t";
            if (!stat_exists "debian/patches/$f") {
+               print DEBUG " drop\n" if $debuglevel;
                # git merge deleted it; that's how we tell it's not wanted
                delete $prereq{$f};
                next;
            }
-           foreach my $g (keys %{ $prereq{$f} }) {
+           print DEBUG " keep\n" if $debuglevel;
+           foreach my $g (sort keys %{ $prereq{$f} }) {
                my $gfp = $prereq{$f}{$g};
-               next unless
-                   # want to keep it
-                   !!$gfp->{0} == !!$gfp->{1}
+               printdebug "merge_series  prereq\t$f\t-> $g\t";
+               if (!!$gfp->{0} == !!$gfp->{1}
                    ? $gfp->{0}
-                   : !$gfp->{base}
-                   ;
-               delete $prereq{$f}{$g};
+                   : !$gfp->{base}) {
+                   print DEBUG "\tkeep\n" if $debuglevel;
+               } else {
+                   print DEBUG "\tdrop\n" if $debuglevel;
+                   delete $prereq{$f}{$g};
+               }
            }
        }
 
@@ -480,6 +495,7 @@ sub merge_series ($$;@) {
                }
                $best = $try;
            }
+           printdebug "merge_series series next $best\n";
            print NS "$best\n" or die $!;
            delete $prereq{$best};
            foreach my $gp (values %prereq) {
@@ -490,15 +506,18 @@ sub merge_series ($$;@) {
        runcmd @git, qw(add), $seriesfile;
        runcmd @git, qw(commit --quiet -m), 'Merged series';
 
+       printdebug "merge_series series gbp pq import\n";
        runcmd qw(gbp pq import);
 
        # OK now we are on patch-queue/merge, and we need to rebase
        # onto the intended parent and drop the patches from each one
 
+       printdebug "merge_series series ok, building...\n";
        my $build = $newbase;
        my @lcmd = (@git, qw(rev-list --reverse merge..patch-queue/merge));
        foreach my $c (grep /./, split /\n/, cmdoutput @lcmd) {
            my $commit = git_cat_file $c, 'commit';
+           printdebug "merge_series series ok, building $c\n";
            read_tree_upstream $c;
            my $tree = cmdoutput @git, qw(write-tree);
            $commit =~ s{^parent (\S+)$}{parent $build}m or confess;
@@ -1063,8 +1082,16 @@ sub walk ($;$$$) {
            }
            die "$ty ?";
        } elsif ($ty eq 'VanillaMerge' or $ty eq 'MergedBreakwaters') {
-           # xxx need to handle ffq if one side was unstitched
-           # wait both of them may be!
+           # User may have merged unstitched branch(es).  We will
+           # have now lost what ffq-prev was then (since the later
+           # pseudomerge may introduce further changes).  The effect
+           # of resolving such a merge is that we may have to go back
+           # further in history to find a merge base, since the one
+           # which was reachable via ffq-prev is no longer findable.
+           # This is suboptimal, but if it all works we'll have done
+           # the right thing.
+           # xxx we should warn the user in the docs about this
+
            my $ok=1;
            my $best_anchor;
            # We expect to find a dominating anchor amongst the
@@ -1310,7 +1337,7 @@ sub walk ($;$$$) {
     };
 
     my $final_check = get_differs $build, $input;
-    die sprintf "internal error %#x %s %s", $final_check, $build, $input
+    die sprintf "internal error %#x %s %s", $final_check, $input, $build
        if $final_check & ~D_PAT_ADD;
 
     my @r = ($build, $breakwater, $last_anchor);