chiark / gitweb /
dgit: Drop an obsolete xxx comment
[dgit.git] / infra / dgit-repos-server
index 5bf4416267c72c4cec207e20908faf64ade5af26..a8b9400b5a4729a2c92e0c86d318385dd1512c6c 100755 (executable)
@@ -1,6 +1,23 @@
 #!/usr/bin/perl -w
 # dgit-repos-server
 #
+# git protocol proxy to check dgit pushes etc.
+#
+# Copyright (C) 2014-2016  Ian Jackson
+#
+#    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
+#    the Free Software Foundation; either version 3 of the License, or
+#    (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU General Public License for more details.
+#
+#    You should have received a copy of the GNU General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
 # usages:
 #   dgit-repos-server DISTRO DISTRO-DIR AUTH-SPEC [<settings>] --ssh
 #   dgit-repos-server DISTRO DISTRO-DIR AUTH-SPEC [<settings>] --cron
@@ -34,6 +51,7 @@
 
 use strict;
 
+use Debian::Dgit::Infra; # must precede Debian::Dgit; - can change @INC!
 use Debian::Dgit qw(:DEFAULT :policyflags);
 setup_sigwarn();
 
@@ -142,6 +160,10 @@ setup_sigwarn();
 #    FRESHREPO   (4)
 #         blow away repo right away (ie, as if before push or fetch)
 #         ("check-package" and "push" only)
+#    NOCOMMITCHECK   (8)
+#         suppress dgit-repos-server's check that commits do
+#         not lack "committer" info (eg as produced by #849041)
+#         ("push" only)
 # any unexpected bits mean failure, and then known set bits are ignored
 # if no unexpected bits set, operation continues (subject to meaning
 # of any expected bits set).  So, eg, exit 0 means "continue normally"
@@ -281,13 +303,6 @@ sub reject ($) {
     die "\ndgit-repos-server: reject: $why\n\n";
 }
 
-sub runcmd {
-    debugcmd '+',@_;
-    $!=0; $?=0;
-    my $r = system @_;
-    die (shellquote @_)." $? $!" if $r;
-}
-
 sub policyhook {
     my ($policyallowbits, @polargs) = @_;
     # => ($exitstatuspolicybitmap);
@@ -385,16 +400,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";
@@ -852,7 +872,7 @@ sub checks () {
 
     @policy_args = ($package,$version,$suite,$tagname,
                    join(",",@deliberatelies));
-    $policy = policyhook(NOFFCHECK|FRESHREPO, 'push', @policy_args);
+    $policy = policyhook(NOFFCHECK|FRESHREPO|NOCOMMITCHECK, 'push', @policy_args);
 
     if (defined $tagexists_error) {
        if ($policy & FRESHREPO) {
@@ -872,6 +892,27 @@ sub checks () {
        chomp $mb;
        $mb eq $oldcommit or reject "not fast forward on dgit branch";
     }
+
+    # defend against commits generated by #849041
+    if (!($policy & NOCOMMITCHECK)) {
+       my @checks = qw(%at
+                       %ct);
+       my @chk = qw(git log -z);
+       push @chk, '--pretty=tformat:%H%n'.
+           (join "", map { $_, '%n' } @checks);
+       push @chk, "^$oldcommit" if $oldcommit =~ m/[^0]/;
+       push @chk, $commit;;
+       printdebug " ~NOCOMMITCHECK @chk\n";
+       open CHK, "-|", @chk or die $!;
+       local $/ = "\0";
+       while (<CHK>) {
+           next unless m/^$/m;
+           m/^\w+(?=\n)/ or die;
+           reject "corrupted object $& (missing metadata)";
+       }
+       $!=0; $?=0; close CHK or $?==256 or die "$? $!";
+    }
+
     if ($policy & FRESHREPO) {
        # It's a bit late to be discovering this here, isn't it ?
        #
@@ -895,6 +936,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";