chiark / gitweb /
Repos policy machinery: better docs, etc.
[dgit.git] / infra / dgit-repos-server
index b0064e792b131020ae9db7ec02420d198a3beb7e..acff1727541491ace4bfc45ba4e56a63a7e40c84 100755 (executable)
@@ -34,6 +34,8 @@ use strict;
 #  PACKAGE_garbage                  }   (also covers executions of
 #  PACKAGE_garbage-old              }    policy hook script for PACKAGE)
 #  PACKAGE_garbage-tmp              }
+#  policy*                          } (for policy hook script, covered by
+#                                   }  lock only when invoked for a package)
 #
 # leaf locks, held during brief operaton only:
 #
@@ -105,6 +107,35 @@ use strict;
 #    the corresponding temporary tree, as the lockfile is also
 #    a stampfile whose presence indicates that there may be
 #    cleanup to do
+#
+# Policy hook script is invoked like this:
+#   POLICY-HOOK-SCRIPT DISTRO DGIT-REPOS-DIR ACTION...
+# ie.
+#   POLICY-HOOK-SCRIPT ... check-list [...]
+#   POLICY-HOOK-SCRIPT ... check-package PACKAGE [...]
+#   POLICY-HOOK-SCRIPT ... push|push-confirm PACKAGE \
+#         VERSION SUITE TAGNAME DELIBERATELIES [...]
+#
+# Exit status is a bitmask.  Bit weight constants are defined in Dgit.pm.
+#    NOFFCHECK   (2)
+#         suppress dgit-repos-server's fast-forward check ("push" only)
+#    FRESHREPO   (4)
+#         blow away repo right away (ie, as if before push or fetch)
+#         ("check-package" and "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"
+# and would be appropriate for an unknown action.
+#
+# cwd for push and push-confirm is a temporary repo where the
+# to-be-pushed objects have been received; TAGNAME is the
+# version-based tag
+#
+# if push requested FRESHREPO, push-confirm happens in said fresh repo
+#
+# policy hook for a particular package will be invoked only once at
+# a time - (see comments about DGIT-REPOS-DIR, above)
+
 
 use POSIX;
 use Fcntl qw(:flock);
@@ -157,7 +188,7 @@ sub acquirelock ($$) {
     return $fh;
 }
 
-sub acquiretree ($$) {
+sub acquirermtree ($$) {
     my ($tree, $must) = @_;
     my $fh = acquirelock("$tree.lock", $must);
     if ($fh) {
@@ -167,6 +198,15 @@ sub acquiretree ($$) {
     return $fh;
 }
 
+sub locksometree ($) {
+    my ($tree) = @_;
+    acquirelock("$tree.lock", 1);
+}
+
+sub lockrealtree () {
+    locksometree($realdestrepo);
+}
+
 sub mkrepotmp () {
     my $tmpdir = "$dgitrepos/_tmp";
     return if mkdir $tmpdir;
@@ -211,7 +251,7 @@ sub runcmd {
 
 sub policyhook {
     my ($policyallowbits, @polargs) = @_;
-    # => ($exitstatuspolicybitmap, $policylockfh);
+    # => ($exitstatuspolicybitmap);
     die if $policyallowbits & ~0x3e;
     my @cmd = ($policyhook,$distro,$repos,@polargs);
     debugcmd @_;
@@ -229,7 +269,7 @@ sub mkemptyrepo ($$) {
 sub mkrepo_fromtemplate ($) {
     my ($dir) = @_;
     my $template = "$dgitrepos/_template";
-    acquiretree($template,1);
+    locksometree($template);
     debug "copy template $template -> $dir";
     my $r = system qw(cp -a --), $template, $dir;
     !$r or die "create new repo $dir failed: $r $!";
@@ -271,15 +311,15 @@ sub onwardpush () {
 sub fixmissing__git_receive_pack () {
     mkrepotmp();
     $destrepo = "$dgitrepos/_tmp/${package}_prospective";
-    acquiretree($destrepo, 1);
+    acquirermtree($destrepo, 1);
     mkrepo_fromtemplate($destrepo);
 }
 
 sub makeworkingclone () {
     mkrepotmp();
     $workrepo = "$dgitrepos/_tmp/${package}_incoming$$";
-    acquiretree($workrepo, 1);
-    my $lfh = acquiretree($realdestrepo, 1);
+    acquirermtree($workrepo, 1);
+    my $lfh = lockrealtree();
     runcmd qw(git clone -l -q --mirror), $destrepo, $workrepo;
     close $lfh;
     rmtree "${workrepo}_fresh";
@@ -345,7 +385,7 @@ sub maybeinstallprospective () {
     die Dumper(\%got)." -- missing refs in new repo"
        if grep { !$_ } values %got;
 
-    acquiretree($realdestrepo,1);
+    lockrealtree();
 
     if ($destrepo eq "${workrepo}_fresh") {
        movetogarbage;
@@ -574,7 +614,7 @@ sub checktagnoreplay () {
     return unless $policy & (FRESHREPO|NOFFCHECK);
 
     my $garbagerepo = "$dgitrepos/${package}_garbage";
-    acquiretree($realdestrepo,1);
+    lockrealtree();
 
     local $ENV{GIT_DIR};
     foreach my $garb ("$garbagerepo", "$garbagerepo-old") {
@@ -654,11 +694,11 @@ sub checks () {
     debug "translated version $v";
     $tagname eq "debian/$v" or die;
 
-    acquiretree($realdestrepo,1);
+    lockrealtree();
 
-    $policy = policyhook(NOFFCHECK|FRESHREPO, 'push',$package,
-                        $version,$suite,$tagname,
-                        join(",",@delberatelies));
+    my @policy_args = ($package,$version,$suite,$tagname,
+                      join(",",@delberatelies));
+    $policy = policyhook(NOFFCHECK|FRESHREPO, 'push', @policy_args);
 
     checktagnoreplay();
     checksuite();
@@ -687,6 +727,8 @@ sub checks () {
        $destrepo = "${workrepo}_fresh"; # workrepo lock covers
        mkrepo_fromtemplate $destrepo;
     }
+
+    policyhook(0, 'push-confirm', @policy_args);
 }
 
 sub stunthook () {
@@ -705,7 +747,7 @@ sub stunthook () {
 
 sub fixmissing__git_upload_pack () {
     $destrepo = "$dgitrepos/_empty";
-    my $lfh = acquiretree($destrepo,1);
+    my $lfh = locksometree($destrepo);
     return if stat_exists $destrepo;
     rmtree "$destrepo.new";
     mkemptyrepo "$destrepo.new", "0644";
@@ -715,7 +757,7 @@ sub fixmissing__git_upload_pack () {
 }
 
 sub main__git_upload_pack () {
-    my $lfh = acquiretree($destrepo,1);
+    my $lfh = locksometree($destrepo);
     chdir $destrepo or die "$destrepo: $!";
     close $lfh;
     runcmd qw(git upload-pack), ".";
@@ -792,13 +834,12 @@ sub parseargsdispatch () {
 
     reject "unknown method" unless $mainfunc;
 
-    my $lfh = acquiretree($realdestrepo,1);
+    my $lfh = lockrealtree();
 
-    my ($policy, $pollock) = policyhook(FRESHREPO,'check-package',$package);
+    $policy = policyhook(FRESHREPO,'check-package',$package);
     if ($policy & FRESHREPO) {
        movetogarbage;
     }
-    close $pollock or die $!;
 
     close $lfh;
 
@@ -827,7 +868,7 @@ sub cleanup () {
     foreach my $lf (<*.lock>) {
        my $tree = $lf;
        $tree =~ s/\.lock$//;
-       next unless acquiretree($tree, 0);
+       next unless acquirermtree($tree, 0);
        remove $lf or warn $!;
        unlockall();
     }