X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=dgit.git;a=blobdiff_plain;f=infra%2Fdgit-repos-server;h=8e939d025f904e2e7900cb761b40857fab005f26;hp=560f1ad3664f0d2134adc003b7a81f00b0a57096;hb=4628b8fd6ea2e7efe9ecb676bd061232f8eae72e;hpb=8c6209aa29c81ff6a02d9ab8de50b8392d0610b1 diff --git a/infra/dgit-repos-server b/infra/dgit-repos-server index 560f1ad3..8e939d02 100755 --- a/infra/dgit-repos-server +++ b/infra/dgit-repos-server @@ -8,6 +8,7 @@ # --repos=GIT-REPOS-DIR default DISTRO-DIR/repos/ # --suites=SUITES-FILE default DISTRO-DIR/suites # --policy-hook=POLICY-HOOK default DISTRO-DIR/policy-hook +# --dgit-live=DGIT-LIVE-DIR default DISTRO-DIR/dgit-live # (DISTRO-DIR is not used other than as default) # internal usage: # .../dgit-repos-server --pre-receive-hook PACKAGE @@ -24,8 +25,10 @@ # where AUTH-SPEC is one of # a # mDM.TXT +# (With --cron AUTH-SPEC is not used and may be the empty string.) use strict; +$SIG{__WARN__} = sub { die $_[0]; }; # DGIT-REPOS-DIR contains: # git tree (or other object) lock (in acquisition order, outer first) @@ -114,12 +117,14 @@ use strict; # cleanup to do # # Policy hook script is invoked like this: -# POLICY-HOOK-SCRIPT DISTRO DGIT-REPOS-DIR ACTION... +# POLICY-HOOK-SCRIPT DISTRO DGIT-REPOS-DIR DGIT-LIVE-DIR ACTION... # ie. # POLICY-HOOK-SCRIPT ... check-list [...] # POLICY-HOOK-SCRIPT ... check-package PACKAGE [...] -# POLICY-HOOK-SCRIPT ... push|push-confirm PACKAGE \ +# POLICY-HOOK-SCRIPT ... push PACKAGE \ # VERSION SUITE TAGNAME DELIBERATELIES [...] +# POLICY-HOOK-SCRIPT ... push-confirm PACKAGE \ +# VERSION SUITE TAGNAME DELIBERATELIES FRESH-REPO|'' [...] # # Exit status is a bitmask. Bit weight constants are defined in Dgit.pm. # NOFFCHECK (2) @@ -136,20 +141,32 @@ use strict; # to-be-pushed objects have been received; TAGNAME is the # version-based tag # +# FRESH-REPO is '' iff the repo for this package already existed, or +# the pathname of the newly-created repo which will be renamed into +# place if everything goes well. (NB that this is generally not the +# same repo as the cwd, because the objects are first received into a +# temporary repo so they can be examined.) +# # if push requested FRESHREPO, push-confirm happens in said fresh repo +# and FRESH-REPO is guaranteed not to be ''. # # policy hook for a particular package will be invoked only once at # a time - (see comments about DGIT-REPOS-DIR, above) # # check-list and check-package are invoked via the --cron option. # First, without any locking, check-list is called. It should produce -# a list of package names. Then check-package will be invoked for -# each named package, in each case after taking an appropriate lock. +# a list of package names (one per line). Then check-package will be +# invoked for each named package, in each case after taking an +# appropriate lock. +# +# If policy hook wants to run dgit (or something else in the dgit +# package), it should use DGIT-LIVE-DIR/dgit (etc.) use POSIX; use Fcntl qw(:flock); use File::Path qw(rmtree); +use File::Temp qw(tempfile); use Debian::Dgit qw(:DEFAULT :policyflags); @@ -161,6 +178,7 @@ our $package; our $distro; our $suitesfile; our $policyhook; +our $dgitlive; our $destrepo; our $workrepo; our $keyrings; @@ -265,11 +283,12 @@ sub policyhook { my ($policyallowbits, @polargs) = @_; # => ($exitstatuspolicybitmap); die if $policyallowbits & ~0x3e; - my @cmd = ($policyhook,$distro,$dgitrepos,@polargs); + my @cmd = ($policyhook,$distro,$dgitrepos,$dgitlive,@polargs); debugcmd @cmd; my $r = system @cmd; die "system: $!" if $r < 0; die "hook (@cmd) failed ($?)" if $r & ~($policyallowbits << 8); + debug sprintf "hook (%s) => %#x", "@polargs", $r; return $r >> 8; } @@ -307,6 +326,17 @@ sub movetogarbage () { or die "$garbagerepo $!"; } +sub policy_checkpackage () { + my $lfh = lockrealtree(); + + $policy = policyhook(FRESHREPO,'check-package',$package); + if ($policy & FRESHREPO) { + movetogarbage(); + } + + close $lfh; +} + #----- git-receive-pack ----- sub fixmissing__git_receive_pack () { @@ -732,7 +762,8 @@ sub checks () { mkrepo_fromtemplate $destrepo; } - policyhook(0, 'push-confirm', @policy_args); + my $willinstall = ($destrepo eq realdestrepo ? '' : $destrepo); + policyhook(0, 'push-confirm', @policy_args, $willinstall); } sub onwardpush () { @@ -747,7 +778,7 @@ sub onwardpush () { } sub stunthook () { - debug "stunthook"; + debug "stunthook in $workrepo"; chdir $workrepo or die "chdir $workrepo: $!"; mkdir "dgit-tmp" or $!==EEXIST or die $!; readupdates(); @@ -773,6 +804,7 @@ sub fixmissing__git_upload_pack () { sub main__git_upload_pack () { my $lfh = locksometree($destrepo); + debug "git-upload-pack in $destrepo"; chdir $destrepo or die "$destrepo: $!"; close $lfh; runcmd qw(git upload-pack), "."; @@ -792,9 +824,10 @@ our %indistrodir = ( 'repos' => \$dgitrepos, 'suites' => \$suitesfile, 'policy-hook' => \$policyhook, + 'dgit-live' => \$dgitlive, ); -our @hookenvs = qw(distro suitesfile policyhook keyrings dgitrepos); +our @hookenvs = qw(distro suitesfile policyhook dgitlive keyrings dgitrepos); # workrepo and destrepo handled ad-hoc @@ -821,14 +854,7 @@ sub mode_ssh () { reject "unknown method" unless $mainfunc; - my $lfh = lockrealtree(); - - $policy = policyhook(FRESHREPO,'check-package',$package); - if ($policy & FRESHREPO) { - movetogarbage; - } - - close $lfh; + policy_checkpackage(); if (stat_exists realdestrepo) { $destrepo = realdestrepo; @@ -842,6 +868,27 @@ sub mode_ssh () { &$mainfunc; } +sub mode_cron () { + die if @ARGV; + + my $listfh = tempfile(); + open STDOUT, ">&", $listfh or die $!; + policyhook(0,'check-list'); + open STDOUT, ">&STDERR" or die $!; + + seek $listfh, 0, 0 or die $!; + while (<$listfh>) { + chomp or die; + next if m/^\s*\#/; + next unless m/\S/; + die unless m/^($package_re)$/; + + $package = $1; + policy_checkpackage(); + } + die $! if $listfh->error; +} + sub parseargsdispatch () { die unless @ARGV; @@ -854,7 +901,13 @@ sub parseargsdispatch () { } if ($ARGV[0] eq '--pre-receive-hook') { - if ($debug) { $debug.="="; } + if ($debug) { + $debug.="="; + debug "in stunthook @ARGV"; + foreach my $k (sort keys %ENV) { + debug "$k=$ENV{$k}" if $k =~ m/^DGIT/; + } + } shift @ARGV; @ARGV == 1 or die; $package = shift @ARGV;