chiark / gitweb /
Dgit: forkcheck_*: break out from setup_sigwarn
[dgit.git] / dgit
diff --git a/dgit b/dgit
index f6c845d967da3d2083890f9ff832f999204ac00d..a18d0181542cdb9a0485ad239973a53f87cdcf43 100755 (executable)
--- a/dgit
+++ b/dgit
@@ -73,6 +73,7 @@ our $dodep14tag;
 our $dodep14tag_re = 'want|no|always';
 our $split_brain_save;
 our $we_are_responder;
+our $we_are_initiator;
 our $initiator_tempdir;
 our $patches_applied_dirtily = 00;
 our $tagformat_want;
@@ -2069,23 +2070,44 @@ sub generate_commits_from_dsc () {
     foreach my $fi (@dfi) {
        my $f = $fi->{Filename};
        die "$f ?" if $f =~ m#/|^\.|\.dsc$|\.tmp$#;
+       my $upper_f = "../../../../$f";
+
+       printdebug "considering reusing $f: ";
+
+       if (link_ltarget "$upper_f,fetch", $f) {
+           printdebug "linked (using ...,fetch).\n";
+       } elsif ((printdebug "($!) "),
+                $! != ENOENT) {
+           fail "accessing ../$f,fetch: $!";
+       } elsif (link_ltarget $upper_f, $f) {
+           printdebug "linked.\n";
+       } elsif ((printdebug "($!) "),
+                $! != ENOENT) {
+           fail "accessing ../$f: $!";
+       } else {
+           printdebug "absent.\n";
+       }
 
-       printdebug "considering linking $f: ";
-
-       link_ltarget "../../../../$f", $f
-           or ((printdebug "($!) "), 0)
-           or $!==&ENOENT
-           or die "$f $!";
-
-       printdebug "linked.\n";
-
-       complete_file_from_dsc('.', $fi)
+       my $refetched;
+       complete_file_from_dsc('.', $fi, \$refetched)
            or next;
 
-       if (is_orig_file_in_dsc($f, \@dfi)) {
-           link $f, "../../../../$f"
-               or $!==&EEXIST
-               or die "$f $!";
+       printdebug "considering saving $f: ";
+
+       if (link $f, $upper_f) {
+           printdebug "linked.\n";
+       } elsif ((printdebug "($!) "),
+                $! != EEXIST) {
+           fail "saving ../$f: $!";
+       } elsif (!$refetched) {
+           printdebug "no need.\n";
+       } elsif (link $f, "$upper_f,fetch") {
+           printdebug "linked (using ...,fetch).\n";
+       } elsif ((printdebug "($!) "),
+                $! != EEXIST) {
+           fail "saving ../$f,fetch: $!";
+       } else {
+           printdebug "cannot.\n";
        }
     }
 
@@ -2456,39 +2478,56 @@ END
     return @output;
 }
 
-sub complete_file_from_dsc ($$) {
-    our ($dstdir, $fi) = @_;
-    # Ensures that we have, in $dir, the file $fi, with the correct
+sub complete_file_from_dsc ($$;$) {
+    our ($dstdir, $fi, $refetched) = @_;
+    # Ensures that we have, in $dstdir, the file $fi, with the correct
     # contents.  (Downloading it from alongside $dscurl if necessary.)
+    # If $refetched is defined, can overwrite "$dstdir/$fi->{Filename}"
+    # and will set $$refetched=1 if it did so (or tried to).
 
     my $f = $fi->{Filename};
     my $tf = "$dstdir/$f";
     my $downloaded = 0;
 
+    my $got;
+    my $checkhash = sub {
+       open F, "<", "$tf" or die "$tf: $!";
+       $fi->{Digester}->reset();
+       $fi->{Digester}->addfile(*F);
+       F->error and die $!;
+       my $got = $fi->{Digester}->hexdigest();
+       return $got eq $fi->{Hash};
+    };
+
     if (stat_exists $tf) {
-       progress "using existing $f";
+       if ($checkhash->()) {
+           progress "using existing $f";
+           return 1;
+       }
+       if (!$refetched) {
+           fail "file $f has hash $got but .dsc".
+               " demands hash $fi->{Hash} ".
+               "(perhaps you should delete this file?)";
+       }
+       progress "need to fetch correct version of $f";
+       unlink $tf or die "$tf $!";
+       $$refetched = 1;
     } else {
        printdebug "$tf does not exist, need to fetch\n";
-       my $furl = $dscurl;
-       $furl =~ s{/[^/]+$}{};
-       $furl .= "/$f";
-       die "$f ?" unless $f =~ m/^\Q${package}\E_/;
-       die "$f ?" if $f =~ m#/#;
-       runcmd_ordryrun_local @curl,qw(-f -o),$tf,'--',"$furl";
-       return 0 if !act_local();
-       $downloaded = 1;
-    }
-
-    open F, "<", "$tf" or die "$tf: $!";
-    $fi->{Digester}->reset();
-    $fi->{Digester}->addfile(*F);
-    F->error and die $!;
-    my $got = $fi->{Digester}->hexdigest();
-    $got eq $fi->{Hash} or
+    }
+
+    my $furl = $dscurl;
+    $furl =~ s{/[^/]+$}{};
+    $furl .= "/$f";
+    die "$f ?" unless $f =~ m/^\Q${package}\E_/;
+    die "$f ?" if $f =~ m#/#;
+    runcmd_ordryrun_local @curl,qw(-f -o),$tf,'--',"$furl";
+    return 0 if !act_local();
+
+    $checkhash->() or
        fail "file $f has hash $got but .dsc".
            " demands hash $fi->{Hash} ".
-           ($downloaded ? "(got wrong file from archive!)"
-            : "(perhaps you should delete this file?)");
+           "(got wrong file from archive!)";
 
     return 1;
 }
@@ -2842,8 +2881,10 @@ END
     };
 
     if (parse_cfg_bool 'rewrite-map-enable', 'true', $rewrite_enable) {
-       my $lrf = $do_fetch->("rewrite map", $rewritemap) or return;
-       $mapref = $lrf.'/'.$rewritemap;
+       if (!defined $mapref) {
+           my $lrf = $do_fetch->("rewrite map", $rewritemap) or return;
+           $mapref = $lrf.'/'.$rewritemap;
+       }
        my $rewritemapdata = git_cat_file $mapref.':map';
        if (defined $rewritemapdata
            && $rewritemapdata =~ m/^$dsc_hash(?:[ \t](\w+))/m) {
@@ -3816,8 +3857,12 @@ sub push_parse_changelog ($) {
     fail "-p specified $package but changelog specified $clogpackage"
        unless $package eq $clogpackage;
     my $cversion = getfield $clogp, 'Version';
-    my $tag = debiantag($cversion, access_nomdistro);
-    runcmd @git, qw(check-ref-format), $tag;
+
+    if (!$we_are_initiator) {
+       # rpush initiator can't do this because it doesn't have $isuite yet
+       my $tag = debiantag($cversion, access_nomdistro);
+       runcmd @git, qw(check-ref-format), $tag;
+    }
 
     my $dscfn = dscfn($cversion);
 
@@ -4002,6 +4047,7 @@ END
     prep_ud();
 
     access_giturl(); # check that success is vaguely likely
+    rpush_handle_protovsn_bothends() if $we_are_initiator;
     select_tagformat();
 
     my $clogpfn = ".git/dgit/changelog.822.tmp";
@@ -4130,6 +4176,7 @@ END
     responder_send_file('changes',$changesfile);
     responder_send_command("param head $dgithead");
     responder_send_command("param csuite $csuite");
+    responder_send_command("param isuite $isuite");
     responder_send_command("param tagformat $tagformat");
     if (defined $maintviewhead) {
        die unless ($protovsn//4) >= 4;
@@ -4299,7 +4346,8 @@ sub fetchpullargs () {
        $isuite = branchsuite();
        if (!$isuite) {
            my $clogp = parsechangelog();
-           $isuite = getfield $clogp, 'Distribution';
+           my $clogsuite = getfield $clogp, 'Distribution';
+           $isuite= $clogsuite if $clogsuite ne 'UNRELEASED';
        }
     } elsif (@ARGV==1) {
        ($isuite) = @ARGV;
@@ -4331,7 +4379,6 @@ END
 
 sub cmd_push {
     parseopts();
-    pushing();
     badusage "-p is not allowed with dgit push" if defined $package;
     check_not_dirty();
     my $clogp = parsechangelog();
@@ -4344,6 +4391,7 @@ sub cmd_push {
        badusage "incorrect arguments to dgit push";
     }
     $isuite = getfield $clogp, 'Distribution';
+    pushing();
     if ($new_package) {
        local ($package) = $existing_package; # this is a hack
        canonicalise_suite();
@@ -4374,8 +4422,6 @@ sub cmd_remote_push_build_host {
     $we_are_responder = 1;
     $us .= " (build host)";
 
-    pushing();
-
     open PI, "<&STDIN" or die $!;
     open STDIN, "/dev/null" or die $!;
     open PO, ">&STDOUT" or die $!;
@@ -4394,7 +4440,6 @@ sub cmd_remote_push_build_host {
        unless defined $protovsn;
 
     responder_send_command("dgit-remote-push-ready $protovsn");
-    rpush_handle_protovsn_bothends();
     changedir $dir;
     &cmd_push;
 }
@@ -4436,7 +4481,6 @@ sub i_method {
 }
 
 sub cmd_rpush {
-    pushing();
     my $host = nextarg;
     my $dir;
     if ($host =~ m/^((?:[^][]|\[[^][]*\])*)\:/) {
@@ -4456,6 +4500,8 @@ sub cmd_rpush {
     my @cmd = (@ssh, $host, shellquote @rdgit);
     debugcmd "+",@cmd;
 
+    $we_are_initiator=1;
+
     if (defined $initiator_tempdir) {
        rmtree $initiator_tempdir;
        mkdir $initiator_tempdir, 0700 or die "$initiator_tempdir: $!";
@@ -4469,11 +4515,6 @@ sub cmd_rpush {
     die "$protovsn ?" unless grep { $_ eq $protovsn } @rpushprotovsn_support;
     $supplementary_message = '' unless $protovsn >= 3;
 
-    fail "rpush negotiated protocol version $protovsn".
-       " which does not support quilt mode $quilt_mode"
-       if quiltmode_splitbrain;
-
-    rpush_handle_protovsn_bothends();
     for (;;) {
        my ($icmd,$iargs) = initiator_expect {
            m/^(\S+)(?: (.*))?$/;
@@ -4537,6 +4578,18 @@ our %i_wanted;
 sub i_resp_want ($) {
     my ($keyword) = @_;
     die "$keyword ?" if $i_wanted{$keyword}++;
+    
+    defined $i_param{'csuite'} or badproto \*RO, "premature desire, no csuite";
+    $isuite = $i_param{'isuite'} // $i_param{'csuite'};
+    die unless $isuite =~ m/^$suite_re$/;
+
+    pushing();
+    rpush_handle_protovsn_bothends();
+
+    fail "rpush negotiated protocol version $protovsn".
+       " which does not support quilt mode $quilt_mode"
+       if quiltmode_splitbrain;
+
     my @localpaths = i_method "i_want", $keyword;
     printdebug "[[  $keyword @localpaths\n";
     foreach my $localpath (@localpaths) {
@@ -5415,6 +5468,7 @@ sub quilt_fixup_multipatch ($$$) {
 
     rmtree '.pc';
 
+    runcmd @git, qw(checkout -f), $headref, qw(-- debian);
     my $unapplied=git_add_write_tree();
     printdebug "fake orig tree object $unapplied\n";
 
@@ -5609,12 +5663,12 @@ sub cmd_clean () {
 sub build_prep_early () {
     our $build_prep_early_done //= 0;
     return if $build_prep_early_done++;
-    notpushing();
     badusage "-p is not allowed when building" if defined $package;
     my $clogp = parsechangelog();
     $isuite = getfield $clogp, 'Distribution';
     $package = getfield $clogp, 'Source';
     $version = getfield $clogp, 'Version';
+    notpushing();
     check_not_dirty();
 }
 
@@ -6089,6 +6143,8 @@ Specify  +$specbranch to overwrite, discarding existing history
 END
        if $oldhash && !$force;
 
+    notpushing();
+
     my @dfi = dsc_files_info();
     foreach my $fi (@dfi) {
        my $f = $fi->{Filename};