chiark / gitweb /
git-debrebase: convert-from-*: Snag on unused patches
[dgit.git] / git-debrebase
index 61507ea..66167b2 100755 (executable)
@@ -183,23 +183,30 @@ sub run_deferred_updates ($) {
     @deferred_update_messages = ();
 }
 
-sub get_tree ($) {
+sub get_tree ($;$$) {
     # tree object name => ([ $name, $info ], ...)
     # where $name is the sort key, ie has / at end for subtrees
     # $info is the LHS from git-ls-tree (<mode> <type> <hash>)
-    # will crash if $x does not exist, so don't do that;
+    # without $precheck, will crash if $x does not exist, so don't do that;
     # instead pass '' to get ().
-    my ($x) = @_;
+    my ($x, $precheck, $recurse) = @_;
 
     return () if !length $x;
 
+    if ($precheck) {
+       my ($type, $dummy) = git_cat_file $x, [qw(tree missing)];
+       return () if $type eq 'missing';
+    }
+
     our (@get_tree_memo, %get_tree_memo);
     my $memo = $get_tree_memo{$x};
     return @$memo if $memo;
 
     local $Debian::Dgit::debugcmd_when_debuglevel = 3;
     my @l;
-    my @cmd = (qw(git ls-tree -z --full-tree --), $x);
+    my @cmd = (qw(git ls-tree -z --full-tree));
+    push @cmd, qw(-r) if $recurse;
+    push @cmd, qw(--), $x;
     my $o = cmdoutput @cmd;
     $o =~ s/\0$//s;
     my $last = '';
@@ -1672,7 +1679,7 @@ sub update_head_checkout ($$$) {
 
 sub update_head_postlaunder ($$$) {
     my ($old, $tip, $reflogmsg) = @_;
-    return if $tip eq $old;
+    return if $tip eq $old && !@deferred_updates;
     print "git-debrebase: laundered (head was $old)\n";
     update_head $old, $tip, $reflogmsg;
     # no tree changes except debian/patches
@@ -2275,7 +2282,10 @@ sub cmd_stitch () {
     badusage "no arguments allowed" if @ARGV;
     do_stitch $prose, 0;
 }
-sub cmd_prepush () { cmd_stitch(); }
+sub cmd_prepush () {
+    $opt_noop_ok = 1;
+    cmd_stitch();
+}
 
 sub cmd_quick () {
     badusage "no arguments allowed" if @ARGV;
@@ -2380,6 +2390,24 @@ sub cmd_make_patches () {
     }
 }
 
+sub check_series_has_all_patches ($) {
+    my ($head) = @_;
+    my $seriesfn = 'debian/patches/series';
+    my ($dummy, $series) = git_cat_file "$head:$seriesfn",
+       [qw(blob missing)];
+    $series //= '';
+    my %series;
+    foreach my $f (grep /\S/, grep {!m/^\s\#/} split /\n/, $series) {
+       fail "patch $f repeated in $seriesfn !" if $series{$f}++;
+    }
+    foreach my $patchfile (get_tree "$head:debian/patches", 1,1) {
+       my ($f,$i) = @$patchfile;
+       next if $series{$f};
+       next if $f eq 'series';
+       snag 'unused-patches', "Unused patch file $f will be discarded";
+    }
+}
+
 sub cmd_convert_from_gbp () {
     badusage "want only 1 optional argument, the upstream git commitish"
        unless @ARGV<=1;
@@ -2427,6 +2455,8 @@ END
            "upstream ($upstream) contains debian/ directory";
     }
 
+    check_series_has_all_patches $old_head;
+
     my $previous_dgit_view = eval {
        my @clogcmd = qw(dpkg-parsechangelog --format rfc822 -n2);
        my ($lvsn, $suite);
@@ -2577,6 +2607,8 @@ END
        }
     }
 
+    check_series_has_all_patches $head;
+
     snags_maybe_bail_early();
 
     my $version = upstreamversion $clogp->{Version};