X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=dgit.git;a=blobdiff_plain;f=dgit;h=c8567ed473d838cab555bfd5c118a7d695eb4bef;hp=aa8f7717248023e2fc86029b206fc0050109010d;hb=17474e7732a9a3fcba657bec60264c2629724d5e;hpb=ef9fb96766ba8b8eaba540a760efa4db4b1bb5da diff --git a/dgit b/dgit index aa8f7717..c8567ed4 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); @@ -30,6 +34,8 @@ use File::Path; use File::Temp qw(tempdir); use File::Basename; use Dpkg::Version; +use Dpkg::Compression; +use Dpkg::Compression::Process; use POSIX; use IPC::Open2; use Digest::SHA; @@ -92,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)?"; @@ -111,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); @@ -130,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, @@ -150,6 +158,7 @@ sub parseopts_late_defaults(); sub setup_gitattrs(;$); sub check_gitattrs($$); +our $playground; our $keyid; autoflush STDOUT 1; @@ -232,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) = @_; @@ -250,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 ($) { @@ -538,6 +547,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 @@ -554,7 +564,7 @@ END sub badusage { print STDERR "$us: @_\n", $helpmsg or die $!; - exit 8; + finish 8; } sub nextarg { @@ -567,7 +577,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"; @@ -1679,7 +1689,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 () { @@ -1846,6 +1856,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; @@ -3469,7 +3513,7 @@ sub fork_for_multisuite ($) { sub { @end = (); fetch(); - exit 0; + finish 0; }); # xxx collecte the ref here @@ -3653,15 +3697,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 ($) { @@ -3670,6 +3706,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; @@ -3684,6 +3729,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; @@ -5506,7 +5588,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 $!; } @@ -5632,6 +5714,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"; @@ -5758,7 +5841,7 @@ sub quilt_fixup_editor () { } I2->error and die $!; close O or die $1; - exit 0; + finish 0; } sub maybe_apply_patches_dirtily () { @@ -6113,21 +6196,14 @@ 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(); - my $our_cleanmode = $cleanmode; - if ($need_split_build_invocation) { - # Pretend that clean is being done some other way. This - # forces us not to try to use dpkg-buildpackage to clean and - # build source all in one go; and instead we run dpkg-source - # (and build_prep() will do the clean since $clean_using_builder - # is false). - $our_cleanmode = 'ELSEWHERE'; - } - if ($our_cleanmode =~ m/^dpkg-source/) { - # dpkg-source invocation (below) will clean, so build_prep shouldn't - $clean_using_builder = 1; - } build_prep(); $sourcechanges = changespat $version,'source'; if (act_local()) { @@ -6135,43 +6211,33 @@ sub build_source { or fail "remove $sourcechanges: $!"; } $dscfn = dscfn($version); - if ($our_cleanmode eq 'dpkg-source') { - maybe_apply_patches_dirtily(); - runcmd_ordryrun_local @dpkgbuildpackage, qw(-us -uc -S), - changesopts(); - } elsif ($our_cleanmode eq 'dpkg-source-d') { - maybe_apply_patches_dirtily(); - runcmd_ordryrun_local @dpkgbuildpackage, qw(-us -uc -S -d), - changesopts(); + my @cmd = (@dpkgsource, qw(-b --)); + if ($split_brain) { + changedir $playground; + runcmd_ordryrun_local @cmd, "work"; + my @udfiles = <${package}_*>; + changedir $maindir; + foreach my $f (@udfiles) { + printdebug "source copy, found $f\n"; + next unless + $f eq $dscfn or + ($f =~ m/\.debian\.tar(?:\.\w+)$/ && + $f eq srcfn($version, $&)); + printdebug "source copy, found $f - renaming\n"; + rename "$playground/$f", "../$f" or $!==ENOENT + or fail "put in place new source file ($f): $!"; + } } else { - my @cmd = (@dpkgsource, qw(-b --)); - if ($split_brain) { - changedir $playground; - runcmd_ordryrun_local @cmd, "work"; - my @udfiles = <${package}_*>; - changedir $maindir; - foreach my $f (@udfiles) { - printdebug "source copy, found $f\n"; - next unless - $f eq $dscfn or - ($f =~ m/\.debian\.tar(?:\.\w+)$/ && - $f eq srcfn($version, $&)); - printdebug "source copy, found $f - renaming\n"; - rename "$playground/$f", "../$f" or $!==ENOENT - or fail "put in place new source file ($f): $!"; - } - } else { - my $pwd = must_getcwd(); - my $leafdir = basename $pwd; - changedir ".."; - runcmd_ordryrun_local @cmd, $leafdir; - changedir $pwd; - } - runcmd_ordryrun_local qw(sh -ec), - 'exec >$1; shift; exec "$@"','x', - "../$sourcechanges", - @dpkggenchanges, qw(-S), changesopts(); + my $pwd = must_getcwd(); + my $leafdir = basename $pwd; + changedir ".."; + runcmd_ordryrun_local @cmd, $leafdir; + changedir $pwd; } + runcmd_ordryrun_local qw(sh -ec), + 'exec >$1; shift; exec "$@"','x', + "../$sourcechanges", + @dpkggenchanges, qw(-S), changesopts(); } sub cmd_build_source { @@ -6392,6 +6458,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; @@ -6464,7 +6531,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); @@ -6816,7 +6883,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/-/_/; @@ -6830,3 +6897,5 @@ git_slurp_config(); my $fn = ${*::}{"cmd_$cmd"}; $fn or badusage "unknown operation $cmd"; $fn->(); + +finish 0;