chiark / gitweb /
git-debpush: Check upstream source is identical in the upstream tag
[dgit.git] / dgit
diff --git a/dgit b/dgit
index c208e4ea3779551f9dd5e3f870c4ad02b33caf69..0e0ff6575c3e79bc67227b809e36c876b53fb4f1 100755 (executable)
--- a/dgit
+++ b/dgit
@@ -2,8 +2,9 @@
 # dgit
 # Integration between git and Debian-style archives
 #
-# Copyright (C)2013-2018 Ian Jackson
-# Copyright (C)2017-2018 Sean Whitton
+# Copyright (C)2013-2019 Ian Jackson
+# Copyright (C)2017-2019 Sean Whitton
+# Copyright (C)2019      Matthew Vernon / Sanger Institute
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -53,7 +54,7 @@ use Debian::Dgit;
 our $our_version = 'UNRELEASED'; ###substituted###
 our $absurdity = undef; ###substituted###
 
-our @rpushprotovsn_support = qw(4 5); # 5 drops tag format specification
+our @rpushprotovsn_support = qw(6 5 4); # Reverse order!
 our $protovsn;
 
 our $cmd;
@@ -104,7 +105,6 @@ our %forceopts = map { $_=>0 }
 
 our %format_ok = map { $_=>1 } ("1.0","3.0 (native)","3.0 (quilt)");
 
-our $suite_re = '[-+.0-9a-z]+';
 our $cleanmode_re = qr{(?: dpkg-source (?: -d )? (?: ,no-check | ,all-check )?
                      | (?: git | git-ff ) (?: ,always )?
                          | check (?: ,ignores )?
@@ -473,6 +473,7 @@ sub branch_is_gdr ($) {
 #  > param head DGIT-VIEW-HEAD
 #  > param csuite SUITE
 #  > param tagformat new              # $protovsn == 4
+#  > param splitbrain 0|1             # $protovsn >= 6
 #  > param maint-view MAINT-VIEW-HEAD
 #
 #  > param buildinfo-filename P_V_X.buildinfo   # zero or more times
@@ -783,6 +784,12 @@ our %defcfg = ('dgit.default.distro' => 'debian',
  'dgit-distro.debian-backports.mirror' => 'http://backports.debian.org/debian-backports/',
               'dgit-distro.ubuntu.git-check' => 'false',
  'dgit-distro.ubuntu.mirror' => 'http://archive.ubuntu.com/ubuntu',
+              'dgit-distro.ubuntucloud.git-check' => 'false',
+ 'dgit-distro.ubuntucloud.nominal-distro' => 'ubuntu',
+ 'dgit-distro.ubuntucloud.archive-query' => 'aptget:',
+ 'dgit-distro.ubuntucloud.mirror' => 'http://ubuntu-cloud.archive.canonical.com/ubuntu',
+ 'dgit-distro.ubuntucloud.aptget-suite-map' => 's#^([^-]+):([^:]+)$#${1}-updates/$2#; s#^(.+)-(.+):(.+)#$1-$2/$3#;',
+ 'dgit-distro.ubuntucloud.aptget-suite-rmap' => 's#/(.+)$#-$1#',
               'dgit-distro.test-dummy.ssh' => "$td/ssh",
               'dgit-distro.test-dummy.username' => "alice",
               'dgit-distro.test-dummy.git-check' => "ssh-cmd",
@@ -977,9 +984,8 @@ sub notpushing () {
     parseopts_late_defaults();
 }
 
-sub determine_whether_split_brain () {
-    my ($format,) = get_source_format();
-
+sub determine_whether_split_brain ($) {
+    my ($format) = @_;
     {
        local $access_forpush;
        default_from_access_cfg(\$splitview_mode, 'split-view', 'auto',
@@ -997,8 +1003,6 @@ sub determine_whether_split_brain () {
        $do_split_brain = 1;
     }
     $do_split_brain //= 0;
-
-    return ($format);
 }
 
 sub supplementary_message ($) {
@@ -1438,11 +1442,11 @@ sub canonicalise_suite_aptget {
        my $val = $release->{$name};
        if (defined $val) {
            printdebug "release file $name: $val\n";
+           cfg_apply_map(\$val, 'suite rmap',
+                         access_cfg('aptget-suite-rmap', 'RETURN-UNDEF'));
            $val =~ m/^$suite_re$/o or fail f_
                "Release file (%s) specifies intolerable %s",
                $aptget_releasefile, $name;
-           cfg_apply_map(\$val, 'suite rmap',
-                         access_cfg('aptget-suite-rmap', 'RETURN-UNDEF'));
            return $val
        }
     }
@@ -4361,11 +4365,11 @@ sub push_mktags ($$ $$ $) {
 
     my $cversion = getfield $clogp, 'Version';
     my $clogsuite = getfield $clogp, 'Distribution';
+    my $format = getfield $dsc, 'Format';
 
     # We make the git tag by hand because (a) that makes it easier
     # to control the "tagger" (b) we can do remote signing
     my $authline = clogp_authline $clogp;
-    my @dtxinfo = @deliberatelies;
 
     my $mktag = sub {
        my ($tw) = @_;
@@ -4381,23 +4385,33 @@ tag $tag
 tagger $authline
 
 END
-       if ($tw->{View} eq 'dgit') {
-           print TO f_ <<ENDT, $package, $cversion, $clogsuite, $csuite
-%s release %s for %s (%s) [dgit]
-ENDT
-               or confess "$!";
-           my $dtxinfo = join(" ", "",@dtxinfo);
-           print TO <<END or confess "$!";
+
+       my @dtxinfo = @deliberatelies;
+       unshift @dtxinfo, "--quilt=$quilt_mode" if madformat($format);
+       unshift @dtxinfo, do_split_brain() ? "split" : "no-split"
+           # rpush protocol 5 and earlier don't tell us
+           unless $we_are_initiator && $protovsn < 6;
+       my $dtxinfo = join(" ", "",@dtxinfo);
+       my $tag_metadata = <<END;
 [dgit distro=$declaredistro$dtxinfo]
 END
-           foreach my $ref (sort keys %previously) {
-               print TO <<END or confess "$!";
+       foreach my $ref (sort keys %previously) {
+           $tag_metadata .= <<END or confess "$!";
 [dgit previously:$ref=$previously{$ref}]
 END
-           }
+       }
+
+       if ($tw->{View} eq 'dgit') {
+           print TO sprintf <<ENDT, $package, $cversion, $clogsuite, $csuite
+%s release %s for %s (%s) [dgit]
+ENDT
+               or confess "$!";
        } elsif ($tw->{View} eq 'maint') {
-           print TO f_ <<END, $package, $cversion, $clogsuite, $csuite,
+           print TO sprintf <<END, $package, $cversion, $clogsuite, $csuite;
 %s release %s for %s (%s)
+
+END
+           print TO f_ <<END,
 (maintainer view tag generated by dgit --quilt=%s)
 END
                $quilt_mode
@@ -4405,6 +4419,7 @@ END
        } else {
            confess Dumper($tw)."?";
        }
+       print TO "\n", $tag_metadata;
 
        close TO or confess "$!";
 
@@ -4683,6 +4698,7 @@ ENDT
     responder_send_command("param csuite $csuite");
     responder_send_command("param isuite $isuite");
     responder_send_command("param tagformat new"); # needed in $protovsn==4
+    responder_send_command("param splitbrain $do_split_brain");
     if (defined $maintviewhead) {
        responder_send_command("param maint-view $maintviewhead");
     }
@@ -4886,7 +4902,7 @@ sub cmd_fetch {
 sub cmd_pull {
     parseopts();
     fetchpullargs();
-    determine_whether_split_brain();
+    determine_whether_split_brain get_source_format();
     if (do_split_brain()) {
        my ($format, $fopts) = get_source_format();
        madformat($format) and fail f_ <<END, $quilt_mode
@@ -5181,6 +5197,7 @@ sub i_resp_previously ($) {
 }
 
 our %i_wanted;
+our ($i_clogp, $i_version, $i_dscfn, $i_changesfn, @i_buildinfos);
 
 sub i_resp_want ($) {
     my ($keyword) = @_;
@@ -5190,8 +5207,18 @@ sub i_resp_want ($) {
     $isuite = $i_param{'isuite'} // $i_param{'csuite'};
     die unless $isuite =~ m/^$suite_re$/;
 
-    pushing();
-    rpush_handle_protovsn_bothends();
+    if (!defined $dsc) {
+       pushing();
+       rpush_handle_protovsn_bothends();
+       push_parse_dsc $i_dscfn, 'remote dsc', $i_version;
+       if ($protovsn >= 6) {
+           determine_whether_split_brain getfield $dsc, 'Format';
+           $do_split_brain eq ($i_param{'splitbrain'} // '<unsent>')
+               or badproto \*RO,
+ "split brain mismatch, $do_split_brain != $i_param{'split_brain'}";
+           printdebug "rpush split brain $do_split_brain\n";
+       }
+    }
 
     my @localpaths = i_method "i_want", $keyword;
     printdebug "[[  $keyword @localpaths\n";
@@ -5201,8 +5228,6 @@ sub i_resp_want ($) {
     print RI "files-end\n" or confess "$!";
 }
 
-our ($i_clogp, $i_version, $i_dscfn, $i_changesfn, @i_buildinfos);
-
 sub i_localname_parsed_changelog {
     return "remote-changelog.822";
 }
@@ -5270,7 +5295,7 @@ sub i_want_signed_tag {
 
     die unless $i_param{'csuite'} =~ m/^$suite_re$/;
     $csuite = $&;
-    push_parse_dsc $i_dscfn, 'remote dsc', $i_version;
+    defined $dsc or badproto \*RO, "dsc (before parsed-changelog)";
 
     my @tagwants = push_tagwants $i_version, $head, $maintview, "tag";
 
@@ -6563,17 +6588,21 @@ sub WANTSRC_BUILDER () { 02; } # caller should run dpkg-buildpackage
 sub build_or_push_prep_early () {
     our $build_or_push_prep_early_done //= 0;
     return if $build_or_push_prep_early_done++;
-    badusage f_ "-p is not allowed with dgit %s", $subcommand
-       if defined $package;
     my $clogp = parsechangelog();
     $isuite = getfield $clogp, 'Distribution';
-    $package = getfield $clogp, 'Source';
+    my $gotpackage = getfield $clogp, 'Source';
     $version = getfield $clogp, 'Version';
+    $package //= $gotpackage;
+    if ($package ne $gotpackage) {
+       fail f_ "-p specified package %s, but changelog says %s",
+           $package, $gotpackage;
+    }
     $dscfn = dscfn($version);
 }
 
 sub build_or_push_prep_modes () {
-    my ($format,) = determine_whether_split_brain();
+    my ($format) = get_source_format();
+    determine_whether_split_brain($format);
 
     fail __ "dgit: --include-dirty is not supported with split view".
             " (including with view-splitting quilt modes)"