chiark / gitweb /
Split brain: dgit-repos-server: Permit pushing maintainer tag too
[dgit.git] / dgit
diff --git a/dgit b/dgit
index 5d1a95c532a19c0c49f6c9538e227c732cc02b76..3905e576620a3410b4ae766657cd50ec7d71243a 100755 (executable)
--- a/dgit
+++ b/dgit
@@ -222,7 +222,7 @@ sub no_such_package () {
 sub changedir ($) {
     my ($newdir) = @_;
     printdebug "CD $newdir\n";
-    chdir $newdir or die "chdir: $newdir: $!";
+    chdir $newdir or confess "chdir: $newdir: $!";
 }
 
 sub deliberately ($) {
@@ -879,6 +879,19 @@ sub parsechangelog {
     return $c;
 }
 
+sub commit_getclogp ($) {
+    # Returns the parsed changelog hashref for a particular commit
+    my ($objid) = @_;
+    our %commit_getclogp_memo;
+    my $memo = $commit_getclogp_memo{$objid};
+    return $memo if $memo;
+    mkpath '.git/dgit';
+    my $mclog = ".git/dgit/clog-$objid";
+    runcmd shell_cmd "exec >$mclog", @git, qw(cat-file blob),
+       "$objid:debian/changelog";
+    $commit_getclogp_memo{$objid} = parsechangelog("-l$mclog");
+}
+
 sub must_getcwd () {
     my $d = getcwd();
     defined $d or fail "getcwd failed: $!";
@@ -1550,10 +1563,7 @@ END
     my @output = ($rawimport_mergeinput);
     progress "synthesised git commit from .dsc $cversion";
     if ($lastpush_mergeinput) {
-       my $lastpush_hash = $lastpush_mergeinput->{Commit};
-       runcmd @git, qw(reset -q --hard), $lastpush_hash;
-       runcmd qw(sh -ec), 'dpkg-parsechangelog >>../changelogold.tmp';
-       my $oldclogp = parsecontrol('../changelogold.tmp','previous changelog');
+       my $oldclogp = mergeinfo_getclogp($lastpush_mergeinput);
        my $oversion = getfield $oldclogp, 'Version';
        my $vcmp =
            version_compare($oversion, $cversion);
@@ -1787,14 +1797,9 @@ END
 }
 
 sub mergeinfo_getclogp ($) {
-    my ($mi) = @_;
     # Ensures thit $mi->{Clogp} exists and returns it
-    return $mi->{Clogp} if $mi->{Clogp};
-    my $mclog = ".git/dgit/clog-$mi->{Commit}";
-    mkpath '.git/dgit';
-    runcmd shell_cmd "exec >$mclog", @git, qw(cat-file blob),
-       "$mi->{Commit}:debian/changelog";
-    $mi->{Clogp} = parsechangelog("-l$mclog");
+    my ($mi) = @_;
+    $mi->{Clogp} = commit_getclogp($mi->{Commit});
 }
 
 sub mergeinfo_version ($) {
@@ -1802,8 +1807,11 @@ sub mergeinfo_version ($) {
 }
 
 sub fetch_from_archive () {
-    # ensures that lrref() is what is actually in the archive,
-    #  one way or another
+    # Ensures that lrref() is what is actually in the archive, one way
+    # or another, according to us - ie this client's
+    # appropritaely-updated archive view.  Also returns the commit id.
+    # If there is nothing in the archive, leaves lrref alone and
+    # returns undef.  git_fetch_us must have already been called.
     get_archive_dsc();
 
     if ($dsc) {
@@ -1921,10 +1929,10 @@ sub fetch_from_archive () {
     my $del_lrfetchrefs = sub {
        changedir $cwd;
        my $gur;
-       printdebug "del_lrfetchrefs\n";
+       printdebug "del_lrfetchrefs...\n";
        foreach my $fullrefname (sort keys %lrfetchrefs_d) {
            my $objid = $lrfetchrefs_d{$fullrefname};
-           printdebug "del_lrfetchrefs: $fullrefname=$objid.\n";
+           printdebug "del_lrfetchrefs: $objid $fullrefname\n";
            if (!$gur) {
                $gur ||= new IO::Handle;
                open $gur, "|-", qw(git update-ref --stdin) or die $!;
@@ -1997,7 +2005,7 @@ But we were not able to obtain any version from the archive or git.
 END
        }
        unshift @end, $del_lrfetchrefs;
-       return 0;
+       return undef;
     }
 
     if ($lastfetch_hash &&
@@ -2119,10 +2127,7 @@ END
     if (defined $skew_warning_vsn) {
        mkpath '.git/dgit';
        printdebug "SKEW CHECK WANT $skew_warning_vsn\n";
-       my $clogf = ".git/dgit/changelog.tmp";
-       runcmd shell_cmd "exec >$clogf",
-           @git, qw(cat-file blob), "$hash:debian/changelog";
-       my $gotclogp = parsechangelog("-l$clogf");
+       my $gotclogp = commit_getclogp($hash);
        my $got_vsn = getfield $gotclogp, 'Version';
        printdebug "SKEW CHECK GOT $got_vsn\n";
        if (version_compare($got_vsn, $skew_warning_vsn) < 0) {
@@ -2148,7 +2153,7 @@ END
     lrfetchref_used lrfetchref();
 
     unshift @end, $del_lrfetchrefs;
-    return 1;
+    return $hash;
 }
 
 sub set_local_git_config ($$) {
@@ -2392,6 +2397,7 @@ sub push_tagwants ($$$$) {
        $tw->{Tag} = $tw->{TagFn}($cversion, access_basedistro);
        $tw->{Tfn} = sub { $tfbase.$tw->{TfSuffix}.$_[0]; };
     }
+    printdebug 'push_tagwants: ', Dumper(\@_, \@tagwants);
     return @tagwants;
 }
 
@@ -2493,9 +2499,23 @@ sub sign_changes ($) {
     }
 }
 
-sub dopush ($) {
-    my ($forceflag) = @_;
+sub dopush () {
     printdebug "actually entering push\n";
+
+    supplementary_message(<<'END');
+Push failed, while checking state of the archive.
+You can retry the push, after fixing the problem, if you like.
+END
+    if (check_for_git()) {
+       git_fetch_us();
+    }
+    my $archive_hash = fetch_from_archive();
+    if (!$archive_hash) {
+       $new_package or
+           fail "package appears to be new in this suite;".
+               " if this is intentional, use --new";
+    }
+
     supplementary_message(<<'END');
 Push failed, while preparing your push.
 You can retry the push, after fixing the problem, if you like.
@@ -2556,6 +2576,23 @@ END
     }
 
     check_not_dirty();
+
+    my $forceflag = '';
+    if ($archive_hash) {
+       if (is_fast_fwd($archive_hash, $dgithead)) {
+           # ok
+       } elsif (deliberately_not_fast_forward) {
+           $forceflag = '+';
+       } else {
+           fail "dgit push: HEAD is not a descendant".
+               " of the archive's version.\n".
+               "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";
+       }
+    }
+
     changedir $ud;
     progress "checking that $dscfn corresponds to HEAD";
     runcmd qw(dpkg-source -x --),
@@ -2590,6 +2627,8 @@ END
        $changesfile = "$buildproductsdir/$changesfile";
     }
 
+    # Checks complete, we're going to try and go ahead:
+
     responder_send_file('changes',$changesfile);
     responder_send_command("param head $dgithead");
     responder_send_command("param csuite $csuite");
@@ -2650,11 +2689,13 @@ END
        create_remote_git_repo();
     }
 
-    my @pushrefs = $forceflag."HEAD:".rrref();
+    my @pushrefs = $forceflag.$dgithead.":".rrref();
     foreach my $tw (@tagwants) {
        my $view = $tw->{View};
        next unless $view eq 'dgit'
            or any { $_ eq $view } access_cfg_tagformats();
+           # ^ $view is "dgit" or "maint" so this looks for "maint"
+           # in archive supported tagformats.
        push @pushrefs, $forceflag."refs/tags/$tw->{Tag}";
     }
 
@@ -2811,33 +2852,7 @@ sub cmd_push {
            fail "dgit push: changelog specifies $isuite ($csuite)".
                " but command line specifies $specsuite";
     }
-    supplementary_message(<<'END');
-Push failed, while checking state of the archive.
-You can retry the push, after fixing the problem, if you like.
-END
-    if (check_for_git()) {
-       git_fetch_us();
-    }
-    my $forceflag = '';
-    if (fetch_from_archive()) {
-       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".
-               "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($forceflag);
+    dopush();
 }
 
 #---------- remote commands' implementation ----------
@@ -3882,6 +3897,7 @@ sub maybe_unapply_patches_again () {
        if $patches_applied_dirtily & 01;
     rmtree '.pc'
        if $patches_applied_dirtily & 02;
+    $patches_applied_dirtily = 0;
 }
 
 #----- other building -----
@@ -4070,16 +4086,15 @@ sub cmd_gbp_build {
        }
        build_prep();
     }
+    maybe_unapply_patches_again();
     if ($wantsrc < 2) {
        unless (grep { m/^--git-debian-branch|^--git-ignore-branch/ } @ARGV) {
            canonicalise_suite();
            push @cmd, "--git-debian-branch=".lbranch();
        }
        push @cmd, changesopts();
-       maybe_apply_patches_dirtily();
        runcmd_ordryrun_local @cmd, @ARGV;
     }
-    maybe_unapply_patches_again();
     printdone "build successful\n";
 }
 sub cmd_git_build { cmd_gbp_build(); } # compatibility with <= 1.0
@@ -4162,6 +4177,7 @@ sub cmd_sbuild {
            " building would result in ambiguity about the intended results"
            if @unwanted;
     }
+    my $wasdir = must_getcwd();
     changedir "..";
     if (act_local()) {
        stat_exists $dscfn or fail "$dscfn (in parent directory): $!";
@@ -4190,6 +4206,7 @@ sub cmd_sbuild {
            rename "$cf", "$cf.inmulti" or fail "$cf\{,.inmulti}: $!";
        }
     }
+    changedir $wasdir;
     maybe_unapply_patches_again();
     printdone "build successful, results in $multichanges\n" or die $!;
 }