+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.
+ # Conversely we need to distinguish different kinds of changes to
+ # debian/ and debian/patches/.
+
+ my $differs = 0;
+
+ my $rundiff = sub {
+ my ($opts, $limits, $fn) = @_;
+ my @cmd = (@git, qw(diff-tree -z --no-renames));
+ push @cmd, @$opts;
+ push @cmd, "$_:" foreach $x, $y;
+ push @cmd, @$limits;
+ my $diffs = cmdoutput @cmd;
+ foreach (split /\0/, $diffs) { $fn->(); }
+ };
+
+ $rundiff->([qw(--name-only)], [], sub {
+ $differs |= $_ eq 'debian' ? D_DEB : D_UPS;
+ });
+
+ if ($differs & D_DEB) {
+ $differs &= ~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) {
+ my $mode;
+ $differs &= ~D_PAT_OTH;
+ my $pat_oth = sub {
+ $differs |= D_PAT_OTH;
+ no warnings qw(exiting); last;
+ };
+ $rundiff->([qw(--name-status -r)], [qw(debian/patches/)], sub {
+ no warnings qw(exiting);
+ if (!defined $mode) {
+ $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";
+ $ok = $x_s eq substr($y_s, 0, length $x_s);
+ } else {
+ # nope
+ }
+ $mode = undef;
+ $differs |= $ok ? D_PAT_ADD : D_PAT_OTH;
+ });
+ 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;
+}