chiark / gitweb /
git-debrebase: fixes
[dgit.git] / git-debrebase
index e5e92038fb94a0466f9cdc5d356c70b3dfbdf862..c4fabe3e2302a75c59faea289e7353e72136cf3c 100755 (executable)
@@ -108,6 +108,7 @@ use Memoize;
 use Carp;
 use POSIX;
 use Data::Dumper;
+use Getopt::Long qw(:config posix_default gnu_compat bundling);
 
 use Debian::Dgit qw(:DEFAULT $wa);
 
@@ -147,32 +148,35 @@ our @git = qw(git);
 
 sub get_differs ($$) {
     my ($x,$y) = @_;
-    # This resembles quiltify_trees_differ, in dgit, a bit.  But: we
-    # don't care about modes, or dpkg-source-unrepresentable changes,
-    # and we don't need the plethora of different modes.
+    # This resembles quiltify_trees_differ, in dgit, a bit.
+    # But we don't care about modes, or dpkg-source-unrepresentable
+    # changes, and we don't need the plethora of different modes.
+    # Conversely we need to distinguish different kinds of changes to
+    # debian/ and debian/patches/.
 
     my $differs = 0;
 
-    my $f;
     my $rundiff = sub {
-       my ($opts, $sfx, $fn) = @_;
-       $opts //= [qw(--name-only)];
+       my ($opts, $limits, $fn) = @_;
        my @cmd = (@git, qw(diff-tree -z --no-renames));
        push @cmd, @$opts;
-       push @cmd, "$_:$sfx" foreach $x, $y;
-       my $diffs = cmdoutput @bcmd, $x, $y;
-       foreach $f (split /\0/, $diffs) { $fn->(); }
+       push @cmd, "$_:" foreach $x, $y;
+       push @cmd, @$limits;
+       my $diffs = cmdoutput @cmd;
+       foreach (split /\0/, $diffs) { $fn->(); }
     };
 
-    $rundiff(undef, '', sub {
-        $differs |= $f eq 'debian' ? D_DEB : D_UPS;
+    $rundiff->([qw(--name-only)], [], sub {
+        $differs |= $_ eq 'debian' ? D_DEB : D_UPS;
     });
 
     if ($differs & D_DEB) {
        $differs &= ~D_DEB;
-       $rundiff(undef, ':debian', sub {
-            $differs |= $f eq 'patches' ? D_PAT_OTH : D_DEB;
+       $rundiff->([qw(--name-only -r)], [qw(debian)], sub {
+            $differs |= $_ eq m{^debian/patches/} ? D_PAT_OTH : D_DEB;
        });
+       die "mysterious debian changes $x..$y"
+           unless $differs & (D_PAT_OTH|D_DEB);
     }
 
     if ($differs & D_PAT_OTH) {
@@ -180,28 +184,36 @@ sub get_differs ($$) {
        $differs &= ~D_PAT_OTH;
        my $pat_oth = sub {
            $differs |= D_PAT_OTH;
-           no qw(exiting);  last;
+           no warnings qw(exiting);  last;
        };
-       $rundiff([qw(--name-status)], ':debian/patches', sub {
+       $rundiff->([qw(--name-status -r)], [qw(debian/patches/)], sub {
             no warnings qw(exiting);
             if (!defined $mode) {
-               $mode = $f;  next;
-           } elsif ($mode eq 'A' && $f !~ m/^\w+\.series$/) {
-           } elsif ($mode eq 'M' && $f eq 'series') {
+               $mode = $_;  next;
+           }
+           die unless s{^debian/patches/}{};
+           my $ok;
+           if ($mode eq 'A' && !m/(?:^|\.)series$/s) {
+               $ok = 1;
+           } elsif ($mode eq 'M' && $_ eq 'series') {
                my $x_s = git_cat_file "$x:debian/patches/series", 'blob';
                my $y_s = git_cat_file "$y:debian/patches/series", 'blob';
                chomp $x_s;  $x_s .= "\n";
-               $pat_oth->() unless $x_s = substr($y_s, 0, length $x_s);
+               $ok = $x_s eq substr($y_s, 0, length $x_s);
            } else {
-               $pat_oth->();
+               # nope
            }
            $mode = undef;
+           $differs |= $ok ? D_PAT_ADD : D_PAT_OTH;
         });
-       
-    
-       
-       }
-           $f eq '
+       die "mysterious debian/patches changes $x..$y"
+           unless $differs & (D_PAT_ADD|D_PAT_OTH);
+    }
+
+    printdebug sprintf "get_differs %s, %s = %#x\n", $x, $y, $differs;
+
+    return $differs;
+}
 
 sub commit_pr_info ($) {
     my ($r) = @_;
@@ -258,7 +270,7 @@ sub classify ($) {
     my ($h,$m) = get_commit $objid;
 
     my ($t) = $h =~ m/^tree (\w+)$/m or die $objid;
-    my (@ph) = $h =~ m/^parent (\w+)$/m;
+    my (@ph) = $h =~ m/^parent (\w+)$/mg;
     my @p;
 
     my $r = {
@@ -277,14 +289,24 @@ sub classify ($) {
         };
     }
 
+    printdebug "classify $objid \$t=$t \@p",
+       (map { sprintf " %s/%#x", $_->{CommitId}, $_->{Differs} } @p),
+       "\n";
+
     my $classify = sub {
        my ($type, @rest) = @_;
        $r = { %$r, Type => $type, @rest };
+       if ($debuglevel) {
+           my $dd = new Data::Dumper [ $r ];
+           Terse $dd 1; Indent $dd 0; Useqq $dd 1;
+           printdebug " = $type ".(Dump $dd)."\n";
+       }
        return $r;
     };
     my $unknown = sub {
        my ($why) = @_;
        $r = { %$r, Type => qw(Unknown) };
+       printdebug " ** Unknown\n";
        return $r;
     };
 
@@ -465,10 +487,11 @@ sub walk ($;$$) {
            $cur = $p0;
            next;
        } elsif ($ty eq 'Pseudomerge') {
-           print $report " Contributor=$ty->{Contributor}" if $report;
+           my $contrib = $cl->{Contributor}{CommitId};
+           print $report " Contributor=$contrib" if $report;
            push @pseudomerges, $cl;
            $rewrite_from_here->();
-           $cur = $ty->{Contributor};
+           $cur = $contrib;
            next;
        } elsif ($ty eq 'BreakwaterUpstreamMerge') {
            $build_start->("PreviousBreakwater", $cur);
@@ -656,10 +679,13 @@ sub cmd_analyse () {
        $old = get_head();
     }
     my ($dummy,$breakwater) = walk $old, 1,*STDOUT;
-    print "$breakwater BREAKWATER\n";
     STDOUT->error and die $!;
 }
 
+GetOptions("D+" => \$debuglevel) or die badusage "bad options\n";
+initdebug('git-debrebase ');
+enabledebug if $debuglevel;
+
 my $toplevel = cmdoutput @git, qw(rev-parse --show-toplevel);
 chdir $toplevel or die "chdir $toplevel: $!";