X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=dgit.git;a=blobdiff_plain;f=dgit;h=f314bdaa05af30ca9814c0adbe850726ed23444d;hp=1f1c425d1f95eaded35208faa49946c9b080b0de;hb=f7d222ee9782806cd05d7a82595c142096c3bd04;hpb=85967df816321c56d70cbfda75994285975347d1 diff --git a/dgit b/dgit index 1f1c425d..f314bdaa 100755 --- a/dgit +++ b/dgit @@ -32,7 +32,6 @@ use POSIX; use IPC::Open2; use Digest::SHA; use Digest::MD5; -use Config; use Debian::Dgit; @@ -53,7 +52,7 @@ our $new_package = 0; our $ignoredirty = 0; our $rmonerror = 1; our @deliberatelies; -our %supersedes; +our %previously; our $existing_package = 'dpkg'; our $cleanmode = 'dpkg-source'; our $changes_since_version; @@ -99,9 +98,6 @@ our %opts_opt_cmdonly = ('gpg' => 1); our $keyid; -our $debug = 0; -open DEBUG, ">/dev/null" or die $!; - autoflush STDOUT 1; our $remotename = 'dgit'; @@ -115,6 +111,8 @@ sub lref () { return "refs/heads/".lbranch(); } sub lrref () { return "refs/remotes/$remotename/".server_branch($csuite); } sub rrref () { return server_ref($csuite); } +sub lrfetchrefs () { return "refs/dgit-fetch/$isuite"; } + sub stripepoch ($) { my ($vsn) = @_; $vsn =~ s/^\d+\://; @@ -132,7 +130,7 @@ sub dscfn ($) { } our $us = 'dgit'; -our $debugprefix = ''; +initdebug(''); our @end; END { @@ -143,32 +141,6 @@ END { } }; -our @signames = split / /, $Config{sig_name}; - -sub waitstatusmsg () { - if (!$?) { - return "terminated, reporting successful completion"; - } elsif (!($? & 255)) { - return "failed with error exit status ".WEXITSTATUS($?); - } elsif (WIFSIGNALED($?)) { - my $signum=WTERMSIG($?); - return "died due to fatal signal ". - ($signames[$signum] // "number $signum"). - ($? & 128 ? " (core dumped)" : ""); # POSIX(3pm) has no WCOREDUMP - } else { - return "failed with unknown wait status ".$?; - } -} - -sub printdebug { print DEBUG $debugprefix, @_ or die $!; } - -sub fail { - my $s = "@_\n"; - my $prefix = $us.($we_are_responder ? " (build host)" : "").": "; - $s =~ s/^/$prefix/gm; - die $s; -} - sub badcfg { print STDERR "$us: invalid configuration: @_\n"; exit 12; } sub no_such_package () { @@ -188,7 +160,14 @@ sub changedir ($) { } sub deliberately ($) { - return !!grep { $_[0] eq $_ } @deliberatelies; + my ($enquiry) = @_; + return !!grep { $_ eq "--deliberately-$enquiry" } @deliberatelies; +} + +sub deliberately_not_fast_forward () { + foreach (qw(not-fast-forward fresh-repo)) { + return 1 if deliberately($_) || deliberately("TEST-dgit-only-$_"); + } } #---------- remote protocol support, common ---------- @@ -379,42 +358,8 @@ sub url_get { our ($dscdata,$dscurl,$dsc,$dsc_checked,$skew_warning_vsn); -sub shellquote { - my @out; - local $_; - foreach my $a (@_) { - $_ = $a; - if (m{[^-=_./0-9a-z]}i) { - s{['\\]}{'\\$&'}g; - push @out, "'$_'"; - } else { - push @out, $_; - } - } - return join ' ', @out; -} - -sub printcmd { - my $fh = shift @_; - my $intro = shift @_; - print $fh $intro," " or die $!; - print $fh shellquote @_ or die $!; - print $fh "\n" or die $!; -} - -sub failedcmd { - { local ($!); printcmd \*STDERR, "$us: failed command:", @_ or die $!; }; - if ($!) { - fail "failed to fork/exec: $!"; - } elsif ($?) { - fail "subprocess ".waitstatusmsg(); - } else { - fail "subprocess produced invalid output"; - } -} - sub runcmd { - printcmd(\*DEBUG,$debugprefix."+",@_) if $debug>0; + debugcmd "+",@_; $!=0; $?=0; failedcmd @_ if system @_; } @@ -430,27 +375,6 @@ sub printdone { } } -sub cmdoutput_errok { - die Dumper(\@_)." ?" if grep { !defined } @_; - printcmd(\*DEBUG,$debugprefix."|",@_) if $debug>0; - open P, "-|", @_ or die $!; - my $d; - $!=0; $?=0; - { local $/ = undef; $d =

; } - die $! if P->error; - if (!close P) { printdebug "=>!$?\n" if $debug>0; return undef; } - chomp $d; - $d =~ m/^.*/; - printdebug "=> \`$&'",(length $' ? '...' : ''),"\n" if $debug>0; #'; - return $d; -} - -sub cmdoutput { - my $d = cmdoutput_errok @_; - defined $d or failedcmd @_; - return $d; -} - sub dryrun_report { printcmd(\*STDERR,$debugprefix."#",@_); } @@ -559,7 +483,7 @@ sub cfg { my @cmd = (@git, qw(config --), $c); my $v; { - local ($debug) = $debug-1; + local ($debuglevel) = $debuglevel-2; $v = cmdoutput_errok @cmd; }; if ($?==0) { @@ -751,23 +675,6 @@ sub parsechangelog { return $c; } -sub git_get_ref ($) { - my ($refname) = @_; - my $got = cmdoutput_errok @git, qw(show-ref --), $refname; - if (!defined $got) { - $?==256 or fail "git show-ref failed (status $?)"; - printdebug "ref $refname= [show-ref exited 1]\n"; - return ''; - } - if ($got =~ m/^(\w+) \Q$refname\E$/m) { - printdebug "ref $refname=$1\n"; - return $1; - } else { - printdebug "ref $refname= [no match]\n"; - return ''; - } -} - sub must_getcwd () { my $d = getcwd(); defined $d or fail "getcwd failed: $!"; @@ -938,7 +845,7 @@ sub sshpsql ($$$) { access_runeinfo("ssh-psql $runeinfo"). " export LC_MESSAGES=C; export LC_CTYPE=C;". " ".shellquote qw(psql -A), $dbname, qw(-c), $sql); - printcmd(\*DEBUG,$debugprefix."|",@cmd) if $debug>0; + debugcmd "|",@cmd; open P, "-|", @cmd or die $!; while (

) { chomp or die; @@ -1070,9 +977,9 @@ sub get_archive_dsc () { " archive told us to expect $digest"; } my $dscfh = new IO::File \$dscdata, '<' or die $!; - printdebug Dumper($dscdata) if $debug>1; + printdebug Dumper($dscdata) if $debuglevel>1; $dsc = parsecontrolfh($dscfh,$dscurl,1); - printdebug Dumper($dsc) if $debug>1; + printdebug Dumper($dsc) if $debuglevel>1; my $fmt = getfield $dsc, 'Format'; fail "unsupported source format $fmt, sorry" unless $format_ok{$fmt}; $dsc_checked = !!$digester; @@ -1355,24 +1262,13 @@ sub ensure_we_have_orig () { } } -sub rev_parse ($) { - return cmdoutput @git, qw(rev-parse), "$_[0]~0"; -} - -sub is_fast_fwd ($$) { - my ($ancestor,$child) = @_; - my @cmd = (@git, qw(merge-base), $ancestor, $child); - my $mb = cmdoutput_errok @cmd; - if (defined $mb) { - return rev_parse($mb) eq rev_parse($ancestor); - } else { - $?==256 or failedcmd @cmd; - return 0; - } -} - sub git_fetch_us () { runcmd_ordryrun_local @git, qw(fetch),access_giturl(),fetchspec(); + if (deliberately_not_fast_forward) { + runcmd_ordryrun_local @git, qw(fetch -p), access_giturl(), + map { "+refs/$_/*:".lrfetchrefs."/$_/*" } + qw(tags heads); + } } sub fetch_from_archive () { @@ -1530,7 +1426,7 @@ sub pull () { sub check_not_dirty () { return if $ignoredirty; my @cmd = (@git, qw(diff --quiet HEAD)); - printcmd(\*DEBUG,$debugprefix."+",@cmd) if $debug>0; + debugcmd "+",@cmd; $!=0; $?=0; system @cmd; return if !$! && !$?; if (!$! && $?==256) { @@ -1646,9 +1542,9 @@ tagger $authline $package release $cversion for $clogsuite ($csuite) [dgit] [dgit distro=$declaredistro$delibs] END - foreach my $ref (sort keys %supersedes) { + foreach my $ref (sort keys %previously) { print TO <0 ? '--exit-code' : '--quiet'; + my $diffopt = $debuglevel>0 ? '--exit-code' : '--quiet'; my @diffcmd = (@git, qw(diff), $diffopt, $tree); - printcmd \*DEBUG,$debugprefix."+",@diffcmd; + debugcmd "+",@diffcmd; $!=0; $?=0; my $r = system @diffcmd; if ($r) { @@ -1741,7 +1638,7 @@ sub dopush () { # runcmd @git, qw(fetch -p ), "$alioth_git/$package.git", # map { lref($_).":".rref($_) } # (uploadbranch()); - my $head = rev_parse('HEAD'); + my $head = git_rev_parse('HEAD'); if (!$changesfile) { my $multi = "$buildproductsdir/". "${package}_".(stripepoch $cversion)."_multi.changes"; @@ -1764,12 +1661,12 @@ sub dopush () { responder_send_command("param head $head"); responder_send_command("param csuite $csuite"); - my $forceflag = deliberately('not-fast-forward') ? '+' : ''; - if ($forceflag && defined $lastpush_hash) { - git_for_each_tag_referring($lastpush_hash, sub { - my ($objid,$fullrefname,$tagname) = @_; - responder_send_command("supersedes $fullrefname=$objid"); - $supersedes{$fullrefname} = $objid; + if (deliberately_not_fast_forward) { + git_for_each_ref(lrfetchrefs, sub { + my ($objid,$objtype,$lrfetchrefname,$reftail) = @_; + my $rrefname= substr($lrfetchrefname, length(lrfetchrefs) + 1); + responder_send_command("previously $rrefname=$objid"); + $previously{$rrefname} = $objid; }); } @@ -1929,17 +1826,26 @@ sub cmd_push { if (check_for_git()) { git_fetch_us(); } + my $forceflag = ''; if (fetch_from_archive()) { - is_fast_fwd(lrref(), 'HEAD') or + if (is_fast_fwd(lrref(), 'HEAD')) { + # ok + } elsif (deliberately_not_fast_forward) { + $forceflag = '+'; + } else { fail "dgit push: HEAD is not a descendant". " of the archive's version.\n". - "$us: To overwrite it, use git merge -s ours ".lrref()."."; + "dgit: To overwrite its contents,". + " use git merge -s ours ".lrref().".\n". + "dgit: To rewind history, if permitted by the archive,". + " use --deliberately-not-fast-forward"; + } } else { $new_package or fail "package appears to be new in this suite;". " if this is intentional, use --new"; } - dopush(); + dopush($forceflag); } #---------- remote commands' implementation ---------- @@ -1955,6 +1861,7 @@ sub cmd_remote_push_build_host { # offered several) $debugprefix = ' '; $we_are_responder = 1; + $us .= " (build host)"; open PI, "<&STDIN" or die $!; open STDIN, "/dev/null" or die $!; @@ -2020,7 +1927,7 @@ sub cmd_rpush { push @rdgit, qw(remote-push-build-host), (scalar @rargs), @rargs; push @rdgit, @ARGV; my @cmd = (@ssh, $host, shellquote @rdgit); - printcmd \*DEBUG,$debugprefix."+",@cmd; + debugcmd "+",@cmd; if (defined $initiator_tempdir) { rmtree $initiator_tempdir; @@ -2077,12 +1984,12 @@ sub i_resp_param ($) { $i_param{$1} = $2; } -sub i_resp_supersedes ($) { +sub i_resp_previously ($) { $_[0] =~ m#^(refs/tags/\S+)=(\w+)$# - or badproto \*RO, "bad supersedes spec"; + or badproto \*RO, "bad previously spec"; my $r = system qw(git check-ref-format), $1; - die "bad supersedes ref spec ($r)" if $r; - $supersedes{$1} = $2; + die "bad previously ref spec ($r)" if $r; + $previously{$1} = $2; } our %i_wanted; @@ -2476,7 +2383,7 @@ sub build_maybe_quilt_fixup () { # 6. Back in the main tree, fast forward to the new HEAD my $clogp = parsechangelog(); - my $headref = rev_parse('HEAD'); + my $headref = git_rev_parse('HEAD'); prep_ud(); changedir $ud; @@ -2725,9 +2632,19 @@ sub cmd_archive_api_query { badusage "need only 1 subpath argument" unless @ARGV==1; my ($subpath) = @ARGV; my @cmd = archive_api_query_cmd($subpath); + debugcmd ">",@cmd; exec @cmd or fail "exec curl: $!\n"; } +sub cmd_clone_dgit_repos_server { + badusage "need destination argument" unless @ARGV==1; + my ($destdir) = @ARGV; + $package = '_dgit-repos-server'; + my @cmd = (@git, qw(clone), access_giturl(), $destdir); + debugcmd ">",@cmd; + exec @cmd or fail "exec git clone: $!\n"; +} + #---------- argument parsing and main program ---------- sub cmd_version { @@ -2811,7 +2728,7 @@ sub parseopts () { } elsif (m/^--no-rm-on-error$/s) { push @ropts, $_; $rmonerror = 0; - } elsif (m/^--deliberately-($suite_re)$/s) { + } elsif (m/^--deliberately-($deliberately_re)$/s) { push @ropts, $_; push @deliberatelies, $&; } else { @@ -2829,9 +2746,8 @@ sub parseopts () { cmd_help(); } elsif (s/^-D/-/) { push @ropts, $&; - open DEBUG, ">&STDERR" or die $!; - autoflush DEBUG 1; - $debug++; + $debuglevel++; + enabledebug(); } elsif (s/^-N/-/) { push @ropts, $&; $new_package=1;