chiark / gitweb /
Split tags: Introduce $mktag in push_mktag
[dgit.git] / dgit
diff --git a/dgit b/dgit
index ba3a2e485524f7b4924404ef59bc6410d721f42b..4aefa085a6b3835d16384b1a218ff5cf18f0cf73 100755 (executable)
--- a/dgit
+++ b/dgit
@@ -39,7 +39,7 @@ use Debian::Dgit;
 
 our $our_version = 'UNRELEASED'; ###substituted###
 
-our @rpushprotovsn_support = qw(3 2);
+our @rpushprotovsn_support = qw(3 2); # 4 is new tag format
 our $protovsn;
 
 our $isuite = 'unstable';
@@ -65,6 +65,9 @@ our $quilt_modes_re = 'linear|smash|auto|nofix|nocheck|gbp|unapplied';
 our $we_are_responder;
 our $initiator_tempdir;
 our $patches_applied_dirtily = 00;
+our $tagformat_want;
+our $tagformat;
+our $tagformatfn;
 
 our %format_ok = map { $_=>1 } ("1.0","3.0 (native)","3.0 (quilt)");
 
@@ -134,7 +137,7 @@ our $instead_distro;
 
 sub debiantag ($$) {
     my ($v,$distro) = @_;
-    return debiantag_old $v, $distro;
+    return $tagformatfn->($v, $distro);
 }
 
 sub lbranch () { return "$branchprefix/$csuite"; }
@@ -243,6 +246,7 @@ sub quiltmode_splitbrain () {
 #
 #  > param head HEAD
 #  > param csuite SUITE
+#  > param tagformat old|new
 #
 #  > previously REFNAME=OBJNAME       # if --deliberately-not-fast-forward
 #                                     # goes into tag, for replay prevention
@@ -501,10 +505,12 @@ our %defcfg = ('dgit.default.distro' => 'debian',
               'dgit.default.ssh' => 'ssh',
               'dgit.default.archive-query' => 'madison:',
               'dgit.default.sshpsql-dbname' => 'service=projectb',
+              'dgit.default.dgit-tag-format' => 'old,new',
               'dgit-distro.debian.archive-query' => 'ftpmasterapi:',
               'dgit-distro.debian.git-check' => 'url',
               'dgit-distro.debian.git-check-suffix' => '/info/refs',
               'dgit-distro.debian.new-private-pushers' => 't',
+              'dgit-distro.debian.dgit-tag-format' => 'old',
               'dgit-distro.debian/push.git-url' => '',
               'dgit-distro.debian/push.git-host' => 'push.dgit.debian.org',
               'dgit-distro.debian/push.git-user-force' => 'dgit',
@@ -1235,6 +1241,33 @@ sub create_remote_git_repo () {
     }
 }
 
+sub select_tagformat () {
+    # sets $tagformatfn
+    return if $tagformatfn && !$tagformat_want;
+    die 'bug' if $tagformatfn && $tagformat_want;
+    # ... $tagformat_want assigned after previous select_tagformat
+
+    my (@supported) = split /\,/, access_cfg('dgit-tag-format');
+    printdebug "select_tagformat supported @supported\n";
+
+    $tagformat_want //= [ $supported[0], "distro access configuration", 0 ];
+    printdebug "select_tagformat specified @$tagformat_want\n";
+
+    my ($fmt,$why,$override) = @$tagformat_want;
+
+    fail "target distro supports tag formats @supported".
+       " but have to use $fmt ($why)"
+       unless $override
+           or grep { $_ eq $fmt } @supported;
+
+    $tagformat_want = undef;
+    $tagformat = $fmt;
+    $tagformatfn = ${*::}{"debiantag_$fmt"};
+
+    fail "trying to use unknown tag format \`$fmt' ($why) !"
+       unless $tagformatfn;
+}
+
 our ($dsc_hash,$lastpush_hash);
 
 our $ud = '.git/dgit/unpack';
@@ -1908,12 +1941,12 @@ sub push_parse_dsc ($$$) {
 }
 
 sub push_mktag ($$$$$$$) {
-    my ($head,$clogp,$tag,
+    my ($dgithead,$clogp,$dgittag,
        $dscfn,
        $changesfile,$changesfilewhat,
-       $tfn) = @_;
+       $tfnbase) = @_;
 
-    $dsc->{$ourdscfield[0]} = $head;
+    $dsc->{$ourdscfield[0]} = $dgithead;
     $dsc->save("$dscfn.tmp") or die $!;
 
     my $changes = parsecontrol($changesfile,$changesfilewhat);
@@ -1931,8 +1964,12 @@ sub push_mktag ($$$$$$$) {
     my $authline = clogp_authline $clogp;
     my $delibs = join(" ", "",@deliberatelies);
     my $declaredistro = access_basedistro();
-    open TO, '>', $tfn->('.tmp') or die $!;
-    print TO <<END or die $!;
+
+    my $mktag = sub {
+       my ($tfn, $head, $tag) = @_;
+
+       open TO, '>', $tfn->('.tmp') or die $!;
+       print TO <<END or die $!;
 object $head
 type commit
 tag $tag
@@ -1941,35 +1978,39 @@ tagger $authline
 $package release $cversion for $clogsuite ($csuite) [dgit]
 [dgit distro=$declaredistro$delibs]
 END
-    foreach my $ref (sort keys %previously) {
-                   print TO <<END or die $!;
+       foreach my $ref (sort keys %previously) {
+           print TO <<END or die $!;
 [dgit previously:$ref=$previously{$ref}]
 END
-    }
+       }
 
-    close TO or die $!;
+       close TO or die $!;
 
-    my $tagobjfn = $tfn->('.tmp');
-    if ($sign) {
-       if (!defined $keyid) {
-           $keyid = access_cfg('keyid','RETURN-UNDEF');
-       }
-        if (!defined $keyid) {
-           $keyid = getfield $clogp, 'Maintainer';
-        }
-       unlink $tfn->('.tmp.asc') or $!==&ENOENT or die $!;
-       my @sign_cmd = (@gpg, qw(--detach-sign --armor));
-       push @sign_cmd, qw(-u),$keyid if defined $keyid;
-       push @sign_cmd, $tfn->('.tmp');
-       runcmd_ordryrun @sign_cmd;
-       if (act_scary()) {
-           $tagobjfn = $tfn->('.signed.tmp');
-           runcmd shell_cmd "exec >$tagobjfn", qw(cat --),
-               $tfn->('.tmp'), $tfn->('.tmp.asc');
+       my $tagobjfn = $tfn->('.tmp');
+       if ($sign) {
+           if (!defined $keyid) {
+               $keyid = access_cfg('keyid','RETURN-UNDEF');
+           }
+           if (!defined $keyid) {
+               $keyid = getfield $clogp, 'Maintainer';
+           }
+           unlink $tfn->('.tmp.asc') or $!==&ENOENT or die $!;
+           my @sign_cmd = (@gpg, qw(--detach-sign --armor));
+           push @sign_cmd, qw(-u),$keyid if defined $keyid;
+           push @sign_cmd, $tfn->('.tmp');
+           runcmd_ordryrun @sign_cmd;
+           if (act_scary()) {
+               $tagobjfn = $tfn->('.signed.tmp');
+               runcmd shell_cmd "exec >$tagobjfn", qw(cat --),
+                   $tfn->('.tmp'), $tfn->('.tmp.asc');
+           }
        }
-    }
+       return $tagobjfn;
+    };
 
-    return ($tagobjfn);
+    my @r;
+    push @r, $mktag->($tfnbase, $dgithead, $dgittag);
+    return @r;
 }
 
 sub sign_changes ($) {
@@ -1993,6 +2034,7 @@ END
     prep_ud();
 
     access_giturl(); # check that success is vaguely likely
+    select_tagformat();
 
     my $clogpfn = ".git/dgit/changelog.822.tmp";
     runcmd shell_cmd "exec >$clogpfn", qw(dpkg-parsechangelog);
@@ -2076,6 +2118,7 @@ END
     responder_send_file('changes',$changesfile);
     responder_send_command("param head $head");
     responder_send_command("param csuite $csuite");
+    responder_send_command("param tagformat $tagformat");
 
     if (deliberately_not_fast_forward) {
        git_for_each_ref(lrfetchrefs, sub {
@@ -2098,7 +2141,7 @@ END
        $tagobjfn = $tfn->('.signed.tmp');
        responder_receive_files('signed-tag', $tagobjfn);
     } else {
-       $tagobjfn =
+       ($tagobjfn) =
            push_mktag($head,$clogp,$tag,
                       $dscpath,
                       $changesfile,$changesfile,
@@ -2338,7 +2381,7 @@ sub cmd_remote_push_build_host {
        unless defined $protovsn;
 
     responder_send_command("dgit-remote-push-ready $protovsn");
-
+    rpush_handle_protovsn_bothends();
     changedir $dir;
     &cmd_push;
 }
@@ -2347,6 +2390,17 @@ sub cmd_remote_push_responder { cmd_remote_push_build_host(); }
 # ... for compatibility with proto vsn.1 dgit (just so that user gets
 #     a good error message)
 
+sub rpush_handle_protovsn_bothends () {
+    if ($protovsn < 4) {
+       fail "rpush negotiated protocol version $protovsn".
+           " which supports old tag format only".
+           " but trying to use new format (".$tagformat_want->[1].")"
+           if $tagformat_want && $tagformat_want->[0] ne 'old';
+       $tagformat_want = ['old', "rpush negotiated protocol $protovsn", 0];
+    }
+    select_tagformat();
+}
+
 our $i_tmp;
 
 sub i_cleanup {
@@ -2405,6 +2459,7 @@ sub cmd_rpush {
     ($protovsn) = initiator_expect { m/^dgit-remote-push-ready (\S+)/ };
     die "$protovsn ?" unless grep { $_ eq $protovsn } @rpushprotovsn_support;
     $supplementary_message = '' unless $protovsn >= 3;
+    rpush_handle_protovsn_bothends();
     for (;;) {
        my ($icmd,$iargs) = initiator_expect {
            m/^(\S+)(?: (.*))?$/;
@@ -2509,11 +2564,18 @@ sub i_want_signed_tag {
     my $head = $i_param{'head'};
     die if $head =~ m/[^0-9a-f]/ || $head !~ m/^../;
 
+    select_tagformat();
+    if ($protovsn >= 4) {
+       my $p = $i_param{'tagformat'} // '<undef>';
+       $p eq $tagformat
+           or badproto \*RO, "tag format mismatch: $p vs. $tagformat";
+    }
+
     die unless $i_param{'csuite'} =~ m/^$suite_re$/;
     $csuite = $&;
     push_parse_dsc $i_dscfn, 'remote dsc', $i_version;
 
-    my $tagobjfn =
+    my ($tagobjfn) =
        push_mktag $head, $i_clogp, $i_tag,
            $i_dscfn,
            $i_changesfn, 'remote changes',
@@ -2837,7 +2899,8 @@ sub quiltify ($$$$) {
            die "$quilt_mode ?";
        }
 
-       my $time = time;
+       my $time = $ENV{'GIT_COMMITTER_DATE'} || time;
+       $time =~ s/\s.*//; # trim timezone from GIT_COMMITTER_DATE
        my $ncommits = 3;
        my $msg = cmdoutput @git, qw(log), "-n$ncommits";
 
@@ -3797,6 +3860,11 @@ sub parseopts () {
            } elsif (m/^--deliberately-($deliberately_re)$/s) {
                push @ropts, $_;
                push @deliberatelies, $&;
+           } elsif (m/^--dgit-tag-format=(old|new)$/s) {
+               # undocumented, for testing
+               push @ropts, $_;
+               $tagformat_want = [ $1, 'command line', 1 ];
+               # 1 menas overrides distro configuration
            } elsif (m/^--always-split-source-build$/s) {
                # undocumented, for testing
                push @ropts, $_;