chiark / gitweb /
Honour policy hook
[dgit.git] / infra / dgit-repos-server
index 56fc4fd0ef766bbfd617aac8dfc34148ccfd55c2..8162fa109cab65e8c66fe2afb8be89ee7b5d7c35 100755 (executable)
@@ -2,7 +2,8 @@
 # dgit-repos-server
 #
 # usages:
-#  .../dgit-repos-server DISTRO SUITES KEYRING-AUTH-SPEC DGIT-REPOS-DIR --ssh
+#  .../dgit-repos-server DISTRO SUITES KEYRING-AUTH-SPEC \
+#      DGIT-REPOS-DIR POLICY-HOOK-SCRIPT --ssh
 # internal usage:
 #  .../dgit-repos-server --pre-receive-hook PACKAGE
 #
@@ -94,6 +95,7 @@ our $func;
 our $dgitrepos;
 our $package;
 our $suitesfile;
+our $policyhook;
 our $realdestrepo;
 our $destrepo;
 our $workrepo;
@@ -186,6 +188,18 @@ sub runcmd {
     die "@_ $? $!" if $r;
 }
 
+sub policyhook {
+    my ($policyallowbits, @polargs) = @_;
+    # => ($exitstatuspolicybitmap, $policylockfh);
+    die if $policyallowbits & ~0x3e;
+    my @cmd = ($policyhook,$distro,$repos,@polargs);
+    debugcmd @_;
+    my $r = system @_;
+    die "system: $!" if $r < 0;
+    die "hook (@cmd) failed ($?)" if $r & ~($policyallowbits << 8);
+    return $r >> 8;
+}
+
 #----- git-receive-pack -----
 
 sub fixmissing__git_receive_pack () {
@@ -490,11 +504,15 @@ sub checks () {
     debug "translated version $v";
     $tagname eq "debian/$v" or die;
 
+    my ($policy) = policyhook(2,'push',$package,
+                             $version,$suite,$tagname,
+                             join(",",@delberatelies));
+
     checksuite();
 
     # check that our ref is being fast-forwarded
     debug "oldcommit $oldcommit";
-    if ($oldcommit =~ m/[^0]/) {
+    if (!($policy & 2) && $oldcommit =~ m/[^0]/) {
        $?=0; $!=0; my $mb = `git merge-base $commit $oldcommit`;
        chomp $mb;
        $mb eq $oldcommit or reject "not fast forward on dgit branch";
@@ -572,6 +590,7 @@ sub parseargsdispatch () {
        defined($workrepo = $ENV{'DGIT_DRS_WORK'}) or die;
        defined($destrepo = $ENV{'DGIT_DRS_DEST'}) or die;
        defined($keyrings = $ENV{'DGIT_DRS_KEYRINGS'}) or die $!;
+       defined($policyhook = $ENV{'DGIT_DRS_POLICYHOOK'}) or die $!;
        open STDOUT, ">&STDERR" or die $!;
        eval {
            stunthook();
@@ -587,6 +606,7 @@ sub parseargsdispatch () {
     $ENV{'DGIT_DRS_SUITES'} = argval();
     $ENV{'DGIT_DRS_KEYRINGS'} = argval();
     $dgitrepos = argval();
+    $ENV{'DGIT_DRS_POLICYHOOK'} = $policyhook = argval();
 
     die unless @ARGV==1 && $ARGV[0] eq '--ssh';
 
@@ -611,6 +631,17 @@ sub parseargsdispatch () {
 
     reject "unknown method" unless $mainfunc;
 
+    my ($policy, $pollock) = policyhook(4, 'check-package',$package);
+    if ($policy & 4) {
+       my $garbagerepo = "$dgitrepos/_tmp/${package}_garbage";
+       acquiretree($garbagerepo,1);
+       rmtree $garbagerepo;
+       rename $realdestrepo, $garbagerepo
+           or $! == ENOENT
+           or die "rename repo $destrepo to $garbagerepo: $!";
+    }
+    close $pollock or die $!;
+
     if (stat $realdestrepo) {
        $destrepo = $realdestrepo;
     } else {