X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=dgit.git;a=blobdiff_plain;f=infra%2Fdgit-repos-server;h=8162fa109cab65e8c66fe2afb8be89ee7b5d7c35;hp=7c447d288050856a281c51feb7fabe8770f68c6f;hb=444896a3a9780647f751966f2c0b26f39c5cd8d3;hpb=d0c5d6629f42b2efa52fb48a5f24407ef18f86b2 diff --git a/infra/dgit-repos-server b/infra/dgit-repos-server index 7c447d28..8162fa10 100755 --- a/infra/dgit-repos-server +++ b/infra/dgit-repos-server @@ -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,12 +95,15 @@ our $func; our $dgitrepos; our $package; our $suitesfile; +our $policyhook; our $realdestrepo; our $destrepo; our $workrepo; our $keyrings; our @lockfhs; our $debug=''; +our @deliberatelies; +our $policy; #----- utilities ----- @@ -184,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 () { @@ -336,7 +352,9 @@ sub parsetag () { for (;;) { if (s/^distro\=(\S+) //) { die "$1 != $distro" unless $1 eq $distro; - } elsif (s/^[-+.=0-9a-z]+ //) { + } elsif (s/^(--deliberately-$package_re) //) { + push @deliberatelies, $1; + } elsif (s/^[-+.=0-9a-z]\S* //) { } else { die "unknown dgit info in tag"; } @@ -475,7 +493,7 @@ sub tagh1 ($) { sub checks () { debug "checks"; - checksuite(); + tagh1('type') eq 'commit' or reject "tag refers to wrong kind of object"; tagh1('object') eq $commit or reject "tag refers to wrong commit"; tagh1('tag') eq $tagname or reject "tag name in tag is wrong"; @@ -486,9 +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"; @@ -566,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(); @@ -581,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'; @@ -605,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 {