X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=dgit;h=ebf44de800ed399aa56644928f01461c9694d67a;hb=4eee70a2b1710c1a8fc71fbd3cdc7064682a799c;hp=3920d86d6b2a13b595933f7ff325ad00fe6e6e30;hpb=b24b60a4cc84fe61b86844c2f670435c78548112;p=dgit.git
diff --git a/dgit b/dgit
index 3920d86d..ebf44de8 100755
--- a/dgit
+++ b/dgit
@@ -2,7 +2,8 @@
# dgit
# Integration between git and Debian-style archives
#
-# Copyright (C)2013-2016 Ian Jackson
+# Copyright (C)2013-2017 Ian Jackson
+# Copyright (C)2017 Sean Whitton
#
# 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
@@ -17,6 +18,9 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
+END { $? = $Debian::Dgit::ExitStatus::desired // -1; };
+use Debian::Dgit::ExitStatus;
+
use strict;
use Debian::Dgit qw(:DEFAULT :playground);
@@ -94,7 +98,7 @@ our %format_ok = map { $_=>1 } ("1.0","3.0 (native)","3.0 (quilt)");
our $suite_re = '[-+.0-9a-z]+';
our $cleanmode_re = 'dpkg-source(?:-d)?|git|git-ff|check|none';
-our $orig_f_comp_re = 'orig(?:-[-0-9a-z]+)?';
+our $orig_f_comp_re = qr{orig(?:-$extra_orig_namepart_re)?};
our $orig_f_sig_re = '\\.(?:asc|gpg|pgp)';
our $orig_f_tail_re = "$orig_f_comp_re\\.tar(?:\\.\\w+)?(?:$orig_f_sig_re)?";
@@ -113,6 +117,7 @@ our (@gpg) = qw(gpg);
our (@sbuild) = qw(sbuild);
our (@ssh) = 'ssh';
our (@dgit) = qw(dgit);
+our (@git_debrebase) = qw(git-debrebase);
our (@aptget) = qw(apt-get);
our (@aptcache) = qw(apt-cache);
our (@dpkgbuildpackage) = (qw(dpkg-buildpackage), @dpkg_source_ignores);
@@ -132,6 +137,7 @@ our %opts_opt_map = ('dget' => \@dget, # accept for compatibility
'ssh' => \@ssh,
'dgit' => \@dgit,
'git' => \@git,
+ 'git-debrebase' => \@git_debrebase,
'apt-get' => \@aptget,
'apt-cache' => \@aptcache,
'dpkg-source' => \@dpkgsource,
@@ -152,6 +158,7 @@ sub parseopts_late_defaults();
sub setup_gitattrs(;$);
sub check_gitattrs($$);
+our $playground;
our $keyid;
autoflush STDOUT 1;
@@ -234,7 +241,7 @@ END {
}
};
-sub badcfg { print STDERR "$us: invalid configuration: @_\n"; exit 12; }
+sub badcfg { print STDERR "$us: invalid configuration: @_\n"; finish 12; }
sub forceable_fail ($$) {
my ($forceoptsl, $msg) = @_;
@@ -252,7 +259,7 @@ sub forceing ($) {
sub no_such_package () {
print STDERR "$us: package $package does not exist in suite $isuite\n";
- exit 4;
+ finish 4;
}
sub deliberately ($) {
@@ -285,6 +292,32 @@ sub dgit_privdir () {
our $dgit_privdir_made //= ensure_a_playground 'dgit';
}
+sub branch_gdr_info ($$) {
+ my ($symref, $head) = @_;
+ my ($status, $msg, $current, $ffq_prev, $gdrlast) =
+ gdr_ffq_prev_branchinfo($symref);
+ return () unless $status eq 'branch';
+ $ffq_prev = git_get_ref $ffq_prev;
+ $gdrlast = git_get_ref $gdrlast;
+ $gdrlast &&= is_fast_fwd $gdrlast, $head;
+ return ($ffq_prev, $gdrlast);
+}
+
+sub branch_is_gdr ($$) {
+ my ($symref, $head) = @_;
+ my ($ffq_prev, $gdrlast) = branch_gdr_info($symref, $head);
+ return 0 unless $ffq_prev || $gdrlast;
+ return 1;
+}
+
+sub branch_is_gdr_unstitched_ff ($$$) {
+ my ($symref, $head, $ancestor) = @_;
+ my ($ffq_prev, $gdrlast) = branch_gdr_info($symref, $head);
+ return 0 unless $ffq_prev;
+ return 0 unless is_fast_fwd $ancestor, $ffq_prev;
+ return 1;
+}
+
#---------- remote protocol support, common ----------
# remote push initiator/responder protocol:
@@ -540,6 +573,7 @@ main usages:
dgit [dgit-opts] build [dpkg-buildpackage-opts]
dgit [dgit-opts] sbuild [sbuild-opts]
dgit [dgit-opts] push [dgit-opts] [suite]
+ dgit [dgit-opts] push-source [dgit-opts] [suite]
dgit [dgit-opts] rpush build-host:build-dir ...
important dgit options:
-k sign tag and package with instead of default
@@ -556,7 +590,7 @@ END
sub badusage {
print STDERR "$us: @_\n", $helpmsg or die $!;
- exit 8;
+ finish 8;
}
sub nextarg {
@@ -569,7 +603,7 @@ sub pre_help () {
}
sub cmd_help () {
print $helpmsg or die $!;
- exit 0;
+ finish 0;
}
our $td = $ENV{DGIT_TEST_DUMMY_DIR} || "DGIT_TEST_DUMMY_DIR-unset";
@@ -1681,7 +1715,7 @@ our ($dsc_distro, $dsc_hint_tag, $dsc_hint_url);
sub prep_ud () {
dgit_privdir(); # ensures that $dgit_privdir_made is based on $maindir
- fresh_playground 'dgit/unpack';
+ $playground = fresh_playground 'dgit/unpack';
}
sub mktree_in_ud_here () {
@@ -1848,6 +1882,40 @@ sub is_orig_file_of_vsn ($$) {
return 1;
}
+# This function determines whether a .changes file is source-only from
+# the point of view of dak. Thus, it permits *_source.buildinfo
+# files.
+#
+# It does not, however, permit any other buildinfo files. After a
+# source-only upload, the buildds will try to upload files like
+# foo_1.2.3_amd64.buildinfo. If the package maintainer included files
+# named like this in their (otherwise) source-only upload, the uploads
+# of the buildd can be rejected by dak. Fixing the resultant
+# situation can require manual intervention. So we block such
+# .buildinfo files when the user tells us to perform a source-only
+# upload (such as when using the push-source subcommand with the -C
+# option, which calls this function).
+#
+# Note, though, that when dgit is told to prepare a source-only
+# upload, such as when subcommands like build-source and push-source
+# without -C are used, dgit has a more restrictive notion of
+# source-only .changes than dak: such uploads will never include
+# *_source.buildinfo files. This is because there is no use for such
+# files when using a tool like dgit to produce the source package, as
+# dgit ensures the source is identical to git HEAD.
+sub test_source_only_changes ($) {
+ my ($changes) = @_;
+ foreach my $l (split /\n/, getfield $changes, 'Files') {
+ $l =~ m/\S+$/ or next;
+ # \.tar\.[a-z0-9]+ covers orig.tar and the tarballs in native packages
+ unless ($& =~ m/(?:\.dsc|\.diff\.gz|\.tar\.[a-z0-9]+|_source\.buildinfo)$/) {
+ print "purportedly source-only changes polluted by $&\n";
+ return 0;
+ }
+ }
+ return 1;
+}
+
sub changes_update_origs_from_dsc ($$$$) {
my ($dsc, $changes, $upstreamvsn, $changesfile) = @_;
my %changes_f;
@@ -3471,7 +3539,7 @@ sub fork_for_multisuite ($) {
sub {
@end = ();
fetch();
- exit 0;
+ finish 0;
});
# xxx collecte the ref here
@@ -3655,15 +3723,7 @@ sub check_not_dirty () {
return if $ignoredirty;
- my @cmd = (@git, qw(diff --quiet HEAD));
- debugcmd "+",@cmd;
- $!=0; $?=-1; system @cmd;
- return if !$?;
- if ($?==256) {
- fail "working tree is dirty (does not match HEAD)";
- } else {
- failedcmd @cmd;
- }
+ git_check_unmodified();
}
sub commit_admin ($) {
@@ -3672,6 +3732,15 @@ sub commit_admin ($) {
runcmd_ordryrun_local @git, qw(commit -m), $m;
}
+sub quiltify_nofix_bail ($$) {
+ my ($headinfo, $xinfo) = @_;
+ if ($quilt_mode eq 'nofix') {
+ fail "quilt fixup required but quilt mode is \`nofix'\n".
+ "HEAD commit".$headinfo." differs from tree implied by ".
+ " debian/patches".$xinfo;
+ }
+}
+
sub commit_quilty_patch () {
my $output = cmdoutput @git, qw(status --porcelain);
my %adds;
@@ -3686,6 +3755,7 @@ sub commit_quilty_patch () {
progress "nothing quilty to commit, ok.";
return;
}
+ quiltify_nofix_bail "", " (wanted to commit patch update)";
my @adds = map { s/[][*?\\]/\\$&/g; $_; } sort keys %adds;
runcmd_ordryrun_local @git, qw(add -f), @adds;
commit_admin <", $pmf or die "$pmf $!";
print MC <{Commit} differs from tree implied by ".
- " debian/patches (tree object $oldtiptree)";
- }
+ quiltify_nofix_bail " $c->{Commit}", " (tree object $oldtiptree)";
if ($quilt_mode eq 'smash') {
printdebug " search quitting smash\n";
last;
@@ -5373,6 +5458,32 @@ END
my $clogp = parsechangelog();
my $headref = git_rev_parse('HEAD');
+ my $symref = git_get_symref();
+
+ if ($quilt_mode eq 'linear'
+ && !$fopts->{'single-debian-patch'}
+ && branch_is_gdr($symref, $headref)) {
+ # This is much faster. It also makes patches that gdr
+ # likes better for future updates without laundering.
+ #
+ # However, it can fail in some casses where we would
+ # succeed: if there are existing patches, which correspond
+ # to a prefix of the branch, but are not in gbp/gdr
+ # format, gdr will fail (exiting status 7), but we might
+ # be able to figure out where to start linearising. That
+ # will be slower so hopefully there's not much to do.
+ my @cmd = (@git_debrebase,
+ qw(--noop-ok -funclean-mixed -funclean-ordering
+ make-patches --quiet-would-amend));
+ # We tolerate soe snags that gdr wouldn't, by default.
+ if (act_local()) {
+ $!=0; $?=-1;
+ failedcmd @cmd if system @cmd and $?!=7;
+ } else {
+ dryrun_report @cmd;
+ }
+ $headref = git_rev_parse('HEAD');
+ }
prep_ud();
changedir $playground;
@@ -5536,7 +5647,7 @@ sub quilt_check_splitbrain_cache ($$) {
if (!stat "$maindir_gitcommon/logs/refs/$splitbraincache") {
$! == ENOENT or die $!;
printdebug ">(no reflog)\n";
- exit 0;
+ finish 0;
}
exec @cmd; die $!;
}
@@ -5662,6 +5773,7 @@ sub quilt_fixup_multipatch ($$$) {
rmtree '.pc';
+ rmtree 'debian'; # git checkout commitish paths does not delete!
runcmd @git, qw(checkout -f), $headref, qw(-- debian);
my $unapplied=git_add_write_tree();
printdebug "fake orig tree object $unapplied\n";
@@ -5788,7 +5900,7 @@ sub quilt_fixup_editor () {
}
I2->error and die $!;
close O or die $1;
- exit 0;
+ finish 0;
}
sub maybe_apply_patches_dirtily () {
@@ -6143,6 +6255,12 @@ sub cmd_gbp_build {
}
sub cmd_git_build { cmd_gbp_build(); } # compatibility with <= 1.0
+sub build_source_for_push {
+ build_source();
+ maybe_unapply_patches_again();
+ $changesfile = $sourcechanges;
+}
+
sub build_source {
build_prep_early();
build_prep();
@@ -6399,6 +6517,7 @@ sub pre_archive_api_query () {
sub cmd_archive_api_query {
badusage "need only 1 subpath argument" unless @ARGV==1;
my ($subpath) = @ARGV;
+ local $isuite = 'DGIT-API-QUERY-CMD';
my @cmd = archive_api_query_cmd($subpath);
push @cmd, qw(-f);
debugcmd ">",@cmd;
@@ -6471,7 +6590,7 @@ sub cmd_setup_new_tree {
sub cmd_version {
print "dgit version $our_version\n" or die $!;
- exit 0;
+ finish 0;
}
our (%valopts_long, %valopts_short);
@@ -6823,7 +6942,7 @@ print STDERR "DAMP RUN - WILL MAKE LOCAL (UNSIGNED) CHANGES\n"
if $dryrun_level == 1;
if (!@ARGV) {
print STDERR $helpmsg or die $!;
- exit 8;
+ finish 8;
}
$cmd = $subcommand = shift @ARGV;
$cmd =~ y/-/_/;
@@ -6837,3 +6956,5 @@ git_slurp_config();
my $fn = ${*::}{"cmd_$cmd"};
$fn or badusage "unknown operation $cmd";
$fn->();
+
+finish 0;