diff options
author | Ian Jackson <ijackson@chiark.greenend.org.uk> | 2017-07-09 16:29:38 +0100 |
---|---|---|
committer | Ian Jackson <ijackson@chiark.greenend.org.uk> | 2017-07-09 16:29:38 +0100 |
commit | 18413810f983efbd083a2fd0cbc2c2cbbadc558b (patch) | |
tree | adae9d497537ae2f4faed6de694f0ada08e8ff57 | |
parent | bada5f43152b731b980626f5f995da1899bc568d (diff) | |
parent | 166121d66d38a3f6584222a03558493c1a23de72 (diff) |
Merge branch 'stable'
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
-rw-r--r-- | Debian/Dgit.pm | 3 | ||||
-rw-r--r-- | debian/changelog | 37 | ||||
-rwxr-xr-x | dgit | 105 | ||||
-rwxr-xr-x | dgit-badcommit-fixup | 14 | ||||
-rwxr-xr-x | infra/dgit-repos-server | 24 | ||||
-rw-r--r-- | tests/lib-core | 1 | ||||
-rwxr-xr-x | tests/tests/badcommit-rewrite | 17 | ||||
-rwxr-xr-x | tests/tests/multisuite | 2 | ||||
-rwxr-xr-x | tests/tests/quilt | 4 |
9 files changed, 184 insertions, 23 deletions
diff --git a/Debian/Dgit.pm b/Debian/Dgit.pm index ba1c288..dcecbd1 100644 --- a/Debian/Dgit.pm +++ b/Debian/Dgit.pm @@ -50,7 +50,7 @@ BEGIN { git_get_ref git_for_each_ref git_for_each_tag_referring is_fast_fwd $package_re $component_re $deliberately_re - $distro_re $versiontag_re + $distro_re $versiontag_re $series_filename_re $branchprefix initdebug enabledebug enabledebuglevel printdebug debugcmd @@ -69,6 +69,7 @@ our $deliberately_re = "(?:TEST-)?$package_re"; our $distro_re = $component_re; our $versiontag_re = qr{[-+.\%_0-9a-zA-Z/]+}; our $branchprefix = 'dgit'; +our $series_filename_re = qr{(?:^|\.)series(?!\n)$}s; # policy hook exit status bits # see dgit-repos-server head comment for documentation diff --git a/debian/changelog b/debian/changelog index 9286859..1d57cfa 100644 --- a/debian/changelog +++ b/debian/changelog @@ -12,6 +12,43 @@ dgit (4.0) experimental; urgency=low -- Ian Jackson <ijackson@chiark.greenend.org.uk> Sun, 12 Feb 2017 22:22:31 +0000 +dgit (3.12~) unstable; urgency=medium + + Important bugfixes to dgit: + * Pass --no-renames to git diff-tree -z, avoiding potential trouble. + * Defend against commit subject lines which would generate patches which + look like series files, etc. Involves adding .patch to all generated + patch filenames. + + -- + +dgit (3.11) unstable; urgency=high + + Important bugfixes to dgit: + * Fix rpush+buildinfo: Transfer buildinfos for signing. Closes:#867693. + * Cope if the archive server sends an HTTP redirect, + by passing -L to curl. Closes:#867185,#867309. + * Cope with newer git which hates --local outside a tree. Closes:#865863. + * rpush: Honour local git config from build host working tree. + * Tolerate compressor terminating with SIGPIPE. Closes:#857694. + * Honour more pre-tree git config options in our private trees sharing + the user's object store. In particular, core.sharedRepository. + Prompted by #867603. + * Clone multisuite works even without --no-rm-on-error. Closes:#867434. + * Work if "git init" does not create $GIT/info. Closes:#858054. + * Actually understand foo,-security (!) Closes:#867189. + + Important bugfixes to other components: + * dgit-badcommit-fixup: Honour core.sharedRepository. Closes:#867603. + * infrastructure: Cope with new git-receive-pack which has + quarantine feature: ie, work around #867702. + + Test suite: + * Cope with git restricting ext:: protocols. + * multisuite: Test clone without --rm-on-error. + + -- Ian Jackson <ijackson@chiark.greenend.org.uk> Sat, 08 Jul 2017 22:40:15 +0100 + dgit (3.10) unstable; urgency=medium Bugfixes: @@ -100,7 +100,7 @@ our $rewritemap = 'dgit-rewrite/map'; our (@git) = qw(git); our (@dget) = qw(dget); -our (@curl) = qw(curl); +our (@curl) = (qw(curl --proto-redir), '-all,http,https', qw(-L)); our (@dput) = qw(dput); our (@debsign) = qw(debsign); our (@gpg) = qw(gpg); @@ -316,6 +316,9 @@ sub gbp_pq { # > param tagformat old|new # > param maint-view MAINT-VIEW-HEAD # +# > param buildinfo-filename P_V_X.buildinfo # zero or more times +# > file buildinfo # for buildinfos to sign +# # > previously REFNAME=OBJNAME # if --deliberately-not-fast-forward # # goes into tag, for replay prevention # @@ -332,6 +335,9 @@ sub gbp_pq { # [etc] # < data-block NBYTES [transfer of signed changes] # [etc] +# < data-block NBYTES [transfer of each signed buildinfo +# [etc] same number and order as "file buildinfo"] +# ... # < files-end # # > complete @@ -560,6 +566,9 @@ sub nextarg { return scalar shift @ARGV; } +sub pre_help () { + no_local_git_cfg(); +} sub cmd_help () { print $helpmsg or die $!; exit 0; @@ -698,6 +707,11 @@ sub cfg { "$us: distro or suite appears not to be (properly) supported"; } +sub no_local_git_cfg () { + # needs to be called from pre_* + @gitcfgsources = grep { $_ ne 'local' } @gitcfgsources; +} + sub access_basedistro__noalias () { if (defined $idistro) { return $idistro; @@ -1699,7 +1713,10 @@ sub prep_ud (;$) { sub mktree_in_ud_here () { runcmd qw(git init -q); runcmd qw(git config gc.auto 0); - foreach my $copy (qw(user.email user.name user.useConfigOnly)) { + foreach my $copy (qw(user.email user.name user.useConfigOnly + core.sharedRepository + core.compression core.looseCompression + core.bigFileThreshold core.fsyncObjectFiles)) { my $v = $gitcfgs{local}{$copy}; next unless $v; runcmd qw(git config), $copy, $_ foreach @$v; @@ -2167,7 +2184,7 @@ sub generate_commits_from_dsc () { if defined $compr_ext && !defined $cname; my $compr_proc = new Dpkg::Compression::Process compression => $cname; - my @compr_cmd = $compr_proc->get_uncompress_cmdline(); + @compr_cmd = $compr_proc->get_uncompress_cmdline(); my $compr_fh = new IO::Handle; my $compr_pid = open $compr_fh, "-|" // die $!; if (!$compr_pid) { @@ -2194,7 +2211,7 @@ sub generate_commits_from_dsc () { !$? or failedcmd @tarcmd; close $input or - (@compr_cmd ? failedcmd @compr_cmd + (@compr_cmd ? ($?==SIGPIPE || failedcmd @compr_cmd) : die $!); # finally, we have the results in "tarball", but maybe # with the wrong permissions @@ -2513,7 +2530,7 @@ sub complete_file_from_dsc ($$;$) { $fi->{Digester}->reset(); $fi->{Digester}->addfile(*F); F->error and die $!; - my $got = $fi->{Digester}->hexdigest(); + $got = $fi->{Digester}->hexdigest(); return $got eq $fi->{Hash}; }; @@ -3363,6 +3380,7 @@ END return; } my $af = ".git/info/attributes"; + ensuredir '.git/info'; open GAO, "> $af.new" or die $!; print GAO <<END or die $!; * dgit-defuse-attrs @@ -3481,6 +3499,7 @@ sub fork_for_multisuite ($) { $before_fetch_merge->(); foreach my $tsuite (@suites[1..$#suites]) { + $tsuite =~ s/^-/$cbasesuite-/; my $csubsuite = multisuite_suite_child($tsuite, \@mergeinputs, sub { @end = (); @@ -3595,6 +3614,9 @@ END } sub clone ($) { + # in multisuite, returns twice! + # once in parent after first suite fetched, + # and then again in child after everything is finished my ($dstdir) = @_; badusage "dry run makes no sense with clone" unless act_local(); @@ -3606,7 +3628,7 @@ sub clone ($) { printdebug "multi clone after fetch merge\n"; clone_set_head(); clone_finish($dstdir); - exit 0; + return; } printdebug "clone main body\n"; @@ -4297,6 +4319,14 @@ END responder_send_command("param maint-view $maintviewhead"); } + # Perhaps send buildinfo(s) for signing + my $changes_files = getfield $changes, 'Files'; + my @buildinfos = ($changes_files =~ m/ .* (\S+\.buildinfo)$/mg); + foreach my $bi (@buildinfos) { + responder_send_command("param buildinfo-filename $bi"); + responder_send_file('buildinfo', "$buildproductsdir/$bi"); + } + if (deliberately_not_fast_forward) { git_for_each_ref(lrfetchrefs, sub { my ($objid,$objtype,$lrfetchrefname,$reftail) = @_; @@ -4367,9 +4397,10 @@ If you need to change the package, you must use a new version number. END if ($we_are_responder) { my $dryrunsuffix = act_local() ? "" : ".tmp"; + my @rfiles = ($dscpath, $changesfile); + push @rfiles, map { "$buildproductsdir/$_" } @buildinfos; responder_receive_files('signed-dsc-changes', - "$dscpath$dryrunsuffix", - "$changesfile$dryrunsuffix"); + map { "$_$dryrunsuffix" } @rfiles); } else { if (act_local()) { rename "$dscpath.tmp",$dscpath or die "$dscfn $!"; @@ -4395,6 +4426,9 @@ END responder_send_command("complete"); } +sub pre_clone () { + no_local_git_cfg(); +} sub cmd_clone { parseopts(); my $dstdir; @@ -4528,7 +4562,7 @@ sub cmd_push { #---------- remote commands' implementation ---------- -sub cmd_remote_push_build_host { +sub pre_remote_push_build_host { my ($nrargs) = shift @ARGV; my (@rargs) = @ARGV[0..$nrargs-1]; @ARGV = @ARGV[$nrargs..$#ARGV]; @@ -4558,11 +4592,14 @@ sub cmd_remote_push_build_host { " but invocation host has $vsnwant" unless defined $protovsn; - responder_send_command("dgit-remote-push-ready $protovsn"); changedir $dir; +} +sub cmd_remote_push_build_host { + responder_send_command("dgit-remote-push-ready $protovsn"); &cmd_push; } +sub pre_remote_push_responder { pre_remote_push_build_host(); } 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) @@ -4602,6 +4639,9 @@ sub i_method { { no strict qw(refs); &{"${base}_${selector}"}(@args); } } +sub pre_rpush () { + no_local_git_cfg(); +} sub cmd_rpush { my $host = nextarg; my $dir; @@ -4720,7 +4760,7 @@ sub i_resp_want ($) { print RI "files-end\n" or die $!; } -our ($i_clogp, $i_version, $i_dscfn, $i_changesfn); +our ($i_clogp, $i_version, $i_dscfn, $i_changesfn, @i_buildinfos); sub i_localname_parsed_changelog { return "remote-changelog.822"; @@ -4737,6 +4777,31 @@ sub i_localname_dsc { } sub i_file_dsc { } +sub i_localname_buildinfo ($) { + my $bi = $i_param{'buildinfo-filename'}; + defined $bi or badproto \*RO, "buildinfo before filename"; + defined $i_changesfn or badproto \*RO, "buildinfo before changes"; + $bi =~ m{^\Q$package\E_[!-.0-~]*\.buildinfo$}s + or badproto \*RO, "improper buildinfo filename"; + return $&; +} +sub i_file_buildinfo { + my $bi = $i_param{'buildinfo-filename'}; + my $bd = parsecontrol "$i_tmp/$bi", $bi; + my $ch = parsecontrol "$i_tmp/$i_changesfn", 'changes'; + if (!forceing [qw(buildinfo-changes-mismatch)]) { + files_compare_inputs($bd, $ch); + (getfield $bd, $_) eq (getfield $ch, $_) or + fail "buildinfo mismatch $_" + foreach qw(Source Version); + !defined $bd->{$_} or + fail "buildinfo contains $_" + foreach qw(Changes Changed-by Distribution); + } + push @i_buildinfos, $bi; + delete $i_param{'buildinfo-filename'}; +} + sub i_localname_changes { defined $i_dscfn or badproto \*RO, "dsc (before parsed-changelog)"; $i_changesfn = $i_dscfn; @@ -4778,7 +4843,7 @@ sub i_want_signed_tag { sub i_want_signed_dsc_changes { rename "$i_dscfn.tmp","$i_dscfn" or die "$i_dscfn $!"; sign_changes $i_changesfn; - return ($i_dscfn, $i_changesfn); + return ($i_dscfn, $i_changesfn, @i_buildinfos); } #---------- building etc. ---------- @@ -4827,7 +4892,7 @@ sub quiltify_trees_differ ($$;$$$) { # a list of unrepresentable changes (removals of upstream files # (as messages) local $/=undef; - my @cmd = (@git, qw(diff-tree -z)); + my @cmd = (@git, qw(diff-tree -z --no-renames)); push @cmd, qw(--name-only) unless $unrepres; push @cmd, qw(-r) if $finegrained || $unrepres; push @cmd, $x, $y; @@ -5210,6 +5275,7 @@ sub quiltify ($$$$) { die "contains unexpected slashes\n" if m{//} || m{/$}; die "contains leading punctuation\n" if m{^\W} || m{/\W}; die "contains bad character(s)\n" if m{[^-a-z0-9_.+=~/]}i; + die "is series file\n" if m{$series_filename_re}o; die "too long" if length > 200; }; return $_ unless $@; @@ -5248,6 +5314,7 @@ sub quiltify ($$$$) { $patchname =~ y/-a-z0-9_.+=~//cd; $patchname =~ s/^\W/x-$&/; $patchname = substr($patchname,0,40); + $patchname .= ".patch"; } if (!defined $patchdir) { $patchdir = ''; @@ -6333,6 +6400,9 @@ END "results are in in git ref $dstbranch"; } +sub pre_archive_api_query () { + no_local_git_cfg(); +} sub cmd_archive_api_query { badusage "need only 1 subpath argument" unless @ARGV==1; my ($subpath) = @ARGV; @@ -6349,6 +6419,9 @@ sub repos_server_url () { my $url = access_giturl(); } +sub pre_clone_dgit_repos_server () { + no_local_git_cfg(); +} sub cmd_clone_dgit_repos_server { badusage "need destination argument" unless @ARGV==1; my ($destdir) = @ARGV; @@ -6358,6 +6431,9 @@ sub cmd_clone_dgit_repos_server { exec @cmd or fail "exec git clone: $!\n"; } +sub pre_print_dgit_repos_server_source_url () { + no_local_git_cfg(); +} sub cmd_print_dgit_repos_server_source_url { badusage "no arguments allowed to dgit print-dgit-repos-server-source-url" if @ARGV; @@ -6739,7 +6815,6 @@ if ($ENV{$fakeeditorenv}) { parseopts(); check_env_sanity(); -git_slurp_config(); print STDERR "DRY RUN ONLY\n" if $dryrun_level > 1; print STDERR "DAMP RUN - WILL MAKE LOCAL (UNSIGNED) CHANGES\n" @@ -6754,6 +6829,8 @@ $cmd =~ y/-/_/; my $pre_fn = ${*::}{"pre_$cmd"}; $pre_fn->() if $pre_fn; +git_slurp_config(); + my $fn = ${*::}{"cmd_$cmd"}; $fn or badusage "unknown operation $cmd"; $fn->(); diff --git a/dgit-badcommit-fixup b/dgit-badcommit-fixup index 8b202c0..3995ceb 100755 --- a/dgit-badcommit-fixup +++ b/dgit-badcommit-fixup @@ -59,6 +59,17 @@ my $bare = `git rev-parse --is-bare-repository`; die "$? $!" if $?; chomp $bare or die; +our @configs; +foreach my $k (qw(core.sharedRepository)) { + $?=0; $!=0; my $v = `set -x; git config --local $k`; + if (defined $v && $?==0 && chomp $v) { + push @configs, [ $k, $v ]; + } elsif (defined $v && $?==256 && $v eq '') { + } else { + die "git-config --local $k => $v $? $! ?"; + } +} + sub getobj ($$) { my ($obj, $type) = @_; print GCFI $obj, "\n" or die $!; @@ -163,6 +174,9 @@ sub edit_rewrite_map ($) { runcmd qw(git config gc.auto 0); runcmd qw(rm -rf .git/objects); symlink "../../objects", ".git/objects" or die $!; + foreach my $c (@configs) { + runcmd qw(git config), $c->[0], $c->[1]; + } my %map; diff --git a/infra/dgit-repos-server b/infra/dgit-repos-server index 6131774..55dc81f 100755 --- a/infra/dgit-repos-server +++ b/infra/dgit-repos-server @@ -407,16 +407,21 @@ sub makeworkingclone () { rmtree "${workrepo}_fresh"; } +sub mkscript ($$) { + my ($path,$contents) = @_; + my $fh = new IO::File $path, O_WRONLY|O_CREAT|O_TRUNC, 0777 + or die "$path: $!"; + print $fh $contents or die "$path: $!"; + close $fh or die "$path: $!"; +} + sub setupstunthook () { my $prerecv = "$workrepo/hooks/pre-receive"; - my $fh = new IO::File $prerecv, O_WRONLY|O_CREAT|O_TRUNC, 0777 - or die "$prerecv: $!"; - print $fh <<END or die "$prerecv: $!"; + mkscript $prerecv, <<END; #!/bin/sh set -e exec $0 --pre-receive-hook $package END - close $fh or die "$prerecv: $!"; $ENV{'DGIT_DRS_WORK'}= $workrepo; $ENV{'DGIT_DRS_DEST'}= $destrepo; printdebug " stunt hook set up $prerecv\n"; @@ -938,6 +943,17 @@ sub onwardpush () { my @cmdbase = (qw(git send-pack), $destrepo); push @cmdbase, qw(--force) if $policy & NOFFCHECK; + if ($ENV{GIT_QUARANTINE_PATH}) { + my $recv_wrapper = "$ENV{GIT_QUARANTINE_PATH}/dgit-recv-wrapper"; + mkscript $recv_wrapper, <<'END'; +#!/bin/sh +set -e +unset GIT_QUARANTINE_PATH +exec git receive-pack "$@" +END + push @cmdbase, "--receive-pack=$recv_wrapper"; + } + my @cmd = @cmdbase; push @cmd, "$commit:refs/dgit/$suite", "$tagval:refs/tags/$tagname"; diff --git a/tests/lib-core b/tests/lib-core index 6cdffeb..d65a1ff 100644 --- a/tests/lib-core +++ b/tests/lib-core @@ -24,6 +24,7 @@ t-set-using-tmp () { export GNUPGHOME=$tmp/nonexistent git config --global user.email 'dgit-test@debian.example.net' git config --global user.name 'dgit test git user' + git config --global protocol.ext.allow always } t-filter-out-git-hyphen-dir () { diff --git a/tests/tests/badcommit-rewrite b/tests/tests/badcommit-rewrite index b7fc701..3e2f37e 100755 --- a/tests/tests/badcommit-rewrite +++ b/tests/tests/badcommit-rewrite @@ -5,7 +5,12 @@ set -e t-setup-import examplegit t-tstunt-parsechangelog -cd example +cd $tmp/git/$p.git +git config core.sharedRepository true +chmod -R g+w objects +umask 022 + +cd $tmp/example suite=stable @@ -26,6 +31,9 @@ t-has-parent-or-is $rstable $badcommit fixup=${DGIT_BADCOMMIT_FIXUP-dgit-badcommit-fixup} cd $tmp/git/$p.git +git gc --aggressive --prune=all +rmdir objects/* ||: + $fixup --real cd $tmp/$p @@ -44,4 +52,11 @@ t-dgit fetch stable t-expect-fail "child $rstable lacks parent $badcommit" \ t-has-parent-or-is $rstable $badcommit +check_shared () { + find "$1" -perm -200 \! -perm -020 -ls |tee $tmp/badperm + test -f $tmp/badperm -a ! -s $tmp/badperm +} + +check_shared $tmp/git/$p.git/objects + t-ok diff --git a/tests/tests/multisuite b/tests/tests/multisuite index d39475b..fe655d0 100755 --- a/tests/tests/multisuite +++ b/tests/tests/multisuite @@ -32,7 +32,7 @@ multi-good cd .. -t-dgit clone --no-rm-on-error $p stable,unstable ./$p.clone +t-dgit clone $p stable,unstable ./$p.clone cd $p.clone diff --git a/tests/tests/quilt b/tests/tests/quilt index 1a921b3..f26f744 100755 --- a/tests/tests/quilt +++ b/tests/tests/quilt @@ -41,8 +41,8 @@ iteration diff <<END - debian/patches/series ups-topic/ups-yml -spongiform-upstream-new-file-incl-change -zorkmid-options-=-42 +spongiform-upstream-new-file-incl-change.patch +zorkmid-options-=-42.patch END for f in `cat debian/patches/series`; do |