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=c70bc27fd13b8a7d50ea3d25dba2bd9a7588f3ef;hb=444896a3a9780647f751966f2c0b26f39c5cd8d3;hpb=1b2c10f57b0257aac61a696378e9c8c05df8bf4f diff --git a/infra/dgit-repos-server b/infra/dgit-repos-server index c70bc27f..8162fa10 100755 --- a/infra/dgit-repos-server +++ b/infra/dgit-repos-server @@ -2,7 +2,8 @@ # dgit-repos-server # # usages: -# .../dgit-repos-server 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 () { @@ -331,6 +347,20 @@ sub parsetag () { for (;;) { print PT or die $!; $!=0; $_=; defined or die "missing signature? $!"; + if (m/^\[dgit ([^"].*)\]$/) { # [dgit "something"] is for future + $_ = $1." "; + for (;;) { + if (s/^distro\=(\S+) //) { + die "$1 != $distro" unless $1 eq $distro; + } elsif (s/^(--deliberately-$package_re) //) { + push @deliberatelies, $1; + } elsif (s/^[-+.=0-9a-z]\S* //) { + } else { + die "unknown dgit info in tag"; + } + } + next; + } last if m/^-----BEGIN PGP/; } for (;;) { @@ -463,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"; @@ -474,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"; @@ -549,10 +585,12 @@ sub parseargsdispatch () { shift @ARGV; @ARGV == 1 or die; $package = shift @ARGV; + defined($distro = $ENV{'DGIT_DRS_DISTRO'}) or die; defined($suitesfile = $ENV{'DGIT_DRS_SUITES'}) or die; 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(); @@ -564,9 +602,11 @@ sub parseargsdispatch () { exit 0; } + $ENV{'DGIT_DRS_DISTRO'} = argval(); $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'; @@ -591,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 {