chiark / gitweb /
Split brain: Better tag format filtering
[dgit.git] / dgit
diff --git a/dgit b/dgit
index 39efa04a2189491f45441039c45f2320c1a22ad4..5dfd97c7fdc45d3a0f4b9f2f53d67669845d8681 100755 (executable)
--- a/dgit
+++ b/dgit
@@ -65,7 +65,7 @@ our $changes_since_version;
 our $rmchanges;
 our $overwrite_version;
 our $quilt_mode;
-our $quilt_modes_re = 'linear|smash|auto|nofix|nocheck|gbp|unapplied';
+our $quilt_modes_re = 'linear|smash|auto|nofix|nocheck|gbp|dpm|unapplied';
 our $we_are_responder;
 our $initiator_tempdir;
 our $patches_applied_dirtily = 00;
@@ -534,6 +534,9 @@ our %defcfg = ('dgit.default.distro' => 'debian',
               'dgit.default.archive-query' => 'madison:',
               'dgit.default.sshpsql-dbname' => 'service=projectb',
               'dgit.default.dgit-tag-format' => 'old,new,maint',
+              # old means "repo server accepts pushes with old dgit tags"
+              # new means "repo server accepts pushes with new dgit tags"
+              # maint means "repo server accepts split brain pushes"
               'dgit-distro.debian.archive-query' => 'ftpmasterapi:',
               'dgit-distro.debian.git-check' => 'url',
               'dgit-distro.debian.git-check-suffix' => '/info/refs',
@@ -1194,7 +1197,7 @@ sub select_tagformat () {
     die 'bug' if $tagformatfn && $tagformat_want;
     # ... $tagformat_want assigned after previous select_tagformat
 
-    my (@supported) = grep { $_ ne 'maint' } access_cfg_tagformats();
+    my (@supported) = grep { $_ =~ m/^(?:old|new)$/ } access_cfg_tagformats();
     printdebug "select_tagformat supported @supported\n";
 
     $tagformat_want //= [ $supported[0], "distro access configuration", 0 ];
@@ -1340,6 +1343,7 @@ sub prep_ud (;$) {
 
 sub mktree_in_ud_here () {
     runcmd qw(git init -q);
+    runcmd qw(git config gc.auto 0);
     rmtree('.git/objects');
     symlink '../../../../objects','.git/objects' or die $!;
 }
@@ -1895,7 +1899,7 @@ sub fetch_from_archive () {
     # Finally: we do not necessarily reify the public view (as
     # described above).  This is so that we do not end up stacking two
     # pseudo-merges.  So what we actually do is figure out the inputs
-    # to any public view psuedo-merge and put them in @mergeinputs.
+    # to any public view pseudo-merge and put them in @mergeinputs.
 
     my @mergeinputs;
     # $mergeinputs[]{Commit}
@@ -2355,6 +2359,42 @@ sub madformat ($) {
     return 1;
 }
 
+# An "infopair" is a tuple [ $thing, $what ]
+# (often $thing is a commit hash; $what is a description)
+
+sub infopair_cond_equal ($$) {
+    my ($x,$y) = @_;
+    $x->[0] eq $y->[0] or fail <<END;
+$x->[1] ($x->[0]) not equal to $y->[1] ($y->[0])
+END
+};
+
+sub infopair_lrf_tag_lookup ($$) {
+    my ($tagnames, $what) = @_;
+    # $tagname may be an array ref
+    my @tagnames = ref $tagnames ? @$tagnames : ($tagnames);
+    printdebug "infopair_lrfetchref_tag_lookup $what @tagnames\n";
+    foreach my $tagname (@tagnames) {
+       my $lrefname = lrfetchrefs."/tags/$tagname";
+       my $tagobj = $lrfetchrefs_f{$lrefname};
+       next unless defined $tagobj;
+       printdebug "infopair_lrfetchref_tag_lookup $tagobj $tagname $what\n";
+       return [ git_rev_parse($tagobj), $what ];
+    }
+    fail @tagnames==1 ? <<END : <<END;
+Wanted tag $what (@tagnames) on dgit server, but not found
+END
+Wanted tag $what (one of: @tagnames) on dgit server, but not found
+END
+}
+
+sub infopair_cond_ff ($$) {
+    my ($anc,$desc) = @_;
+    is_fast_fwd($anc->[0], $desc->[0]) or fail <<END;
+$anc->[1] ($anc->[0]) .. $desc->[1] ($desc->[0]) is not fast forward
+END
+};
+
 sub splitbrain_pseudomerge ($$$$) {
     my ($clogp, $maintview, $dgitview, $archive_hash) = @_;
     # => $merged_dgitview
@@ -2371,34 +2411,6 @@ sub splitbrain_pseudomerge ($$$$) {
     #   this:                                   $dgitview'
     #
 
-    # We work with tuples [ $thing, $what ]
-    # (often $thing is a commit hash; $what is a description)
-
-    my $tag_lookup = sub {
-       my ($tagname, $what) = @_;
-       printdebug "splitbrain_pseudomerge tag_lookup $what\n";
-       my $lrefname = lrfetchrefs."/tags/$tagname";
-       my $tagobj = $lrfetchrefs_f{$lrefname};
-       defined $tagobj or fail <<END;
-Wanted tag $tagname ($what) on dgit server, but not found
-END
-       printdebug "splitbrain_pseudomerge tag_lookup $tagobj $what\n";
-       return [ git_rev_parse($tagobj), $what ];
-    };
-
-    my $cond_equal = sub {
-       my ($x,$y) = @_;
-       $x->[0] eq $y->[0] or fail <<END;
-$x->[1] ($x->[0]) not equal to $y->[1] ($y->[0])
-END
-    };
-    my $cond_ff = sub {
-       my ($anc,$desc) = @_;
-       is_fast_fwd($anc->[0], $desc->[0]) or fail <<END;
-$anc->[1] ($anc->[0]) .. $desc->[1] ($desc->[0]) is not fast forward
-END
-    };
-
     my $arch_clogp = commit_getclogp $archive_hash;
     my $i_arch_v = [ (getfield $arch_clogp, 'Version'),
                     'version currently in archive' ];
@@ -2407,11 +2419,11 @@ END
 
     return $dgitview unless defined $archive_hash;
 
-    if ($overwrite_version) {
+    if (defined $overwrite_version) {
        progress "Declaring that HEAD inciudes all changes in archive...";
        progress "Checking that $overwrite_version does so...";
-       $cond_equal->([ $overwrite_version, '--overwrite= version' ],
-                     $i_arch_v);
+       infopair_cond_equal([ $overwrite_version, '--overwrite= version' ],
+                           $i_arch_v);
     } else {
        progress "Checking that HEAD inciudes all changes in archive...";
     }
@@ -2419,16 +2431,16 @@ END
     return $dgitview if is_fast_fwd $archive_hash, $dgitview;
 
     my $t_dep14 = debiantag_maintview $i_arch_v->[0], access_basedistro;
-    my $i_dep14 = $tag_lookup->($t_dep14, "maintainer view tag");
+    my $i_dep14 = infopair_lrf_tag_lookup($t_dep14, "maintainer view tag");
     my $t_dgit = debiantag_new $i_arch_v->[0], access_basedistro;
-    my $i_dgit = $tag_lookup->($t_dgit, "dgit view tag");
+    my $i_dgit = infopair_lrf_tag_lookup($t_dgit, "dgit view tag");
     my $i_archive = [ $archive_hash, "current archive contents" ];
 
     printdebug "splitbrain_pseudomerge i_archive @$i_archive\n";
 
-    $cond_equal->($i_dgit, $i_archive);
-    $cond_ff->($i_dep14, $i_dgit);
-    $overwrite_version or $cond_ff->($i_dep14, [ $maintview, 'HEAD' ]);
+    infopair_cond_equal($i_dgit, $i_archive);
+    infopair_cond_ff($i_dep14, $i_dgit);
+    $overwrite_version // infopair_cond_ff($i_dep14, [ $maintview, 'HEAD' ]);
 
     my $tree = cmdoutput qw(git rev-parse), "${dgitview}:";
     my $authline = clogp_authline $clogp;
@@ -2444,7 +2456,7 @@ author $authline
 commiter $authline
 
 END
-    if ($overwrite_version) {
+    if (defined $overwrite_version) {
        print MC <<END;
 Declare fast forward from $overwrite_version
 
@@ -2748,7 +2760,7 @@ END
     responder_send_command("param head $dgithead");
     responder_send_command("param csuite $csuite");
     responder_send_command("param tagformat $tagformat");
-    if (quiltmode_splitbrain) {
+    if (defined $maintviewhead) {
        die unless ($protovsn//4) >= 4;
        responder_send_command("param maint-view $maintviewhead");
     }
@@ -3315,6 +3327,13 @@ sub quiltify_splitbrain ($$$$$$) {
        }  
        fail $msg;
     }
+    if ($quilt_mode =~ m/dpm/ &&
+       ($diffbits->{H2A} & 01)) {
+       fail <<END;
+--quilt=$quilt_mode specified, implying patches-applied git tree
+ but git tree differs from result of applying debian/patches to upstream
+END
+    }
     if ($quilt_mode =~ m/gbp|unapplied/ &&
        ($diffbits->{O2A} & 01)) { # some patches
        quiltify_splitbrain_needed();
@@ -3324,6 +3343,14 @@ sub quiltify_splitbrain ($$$$$$) {
        runcmd @git, qw(update-ref refs/heads/dgit-view HEAD);
        runcmd @git, qw(checkout -q dgit-view);
     }
+    if ($quilt_mode =~ m/gbp|dpm/ &&
+       ($diffbits->{O2A} & 02)) {
+       fail <<END
+--quilt=$quilt_mode specified, implying that HEAD is for use with a
+ tool which does not create patches for changes to upstream
+ .gitignores: but, such patches exist in debian/patches.
+END
+    }
     if (($diffbits->{H2O} & 02) && # user has modified .gitignore
        !($diffbits->{O2A} & 02)) { # patches do not change .gitignore
        quiltify_splitbrain_needed();