chiark / gitweb /
dgit-repos-server: Deal with FRESHREPO from push hook
[dgit.git] / infra / dgit-repos-server
index 9a66bdbd4b8a5cf5d095bada9792bf9e69d65466..5599061de2a68cb8e997c66f2d81e48c489688a9 100755 (executable)
@@ -205,16 +205,41 @@ sub mkemptyrepo ($$) {
     runcmd qw(git init --bare --quiet), "--shared=$sharedperm", $dir;
 }
 
     runcmd qw(git init --bare --quiet), "--shared=$sharedperm", $dir;
 }
 
+sub mkrepo_fromtemplate ($) {
+    my ($dir) = @_;
+    my $template = "$dgitrepos/_template";
+    debug "copy tempalate $template -> $dir";
+    my $r = system qw(cp -a --), $template, $dir;
+    !$r or die "create new repo $dir failed: $r $!";
+}
+
+sub movetogarbage () {
+    my $garbagerepo = "$dgitrepos/_tmp/${package}_garbage";
+    acquiretree($garbagerepo,1);
+    rmtree $garbagerepo;
+    rename $realdestrepo, $garbagerepo
+       or $! == ENOENT
+       or die "rename repo $realdestrepo to $garbagerepo: $!";
+}
+
+sub onwardpush () {
+    my @cmd = (qw(git send-pack), $destrepo);
+    push @cmd, qw(--force) if $policy & NOFFCHECK;
+    push @cmd, "$commit:refs/dgit/$suite",
+              "$tagval:refs/tags/$tagname");
+    debugcmd @cmd;
+    $!=0;
+    my $r = system @cmd;
+    !$r or die "onward push to $destrepo failed: $r $!";
+}
+
 #----- git-receive-pack -----
 
 sub fixmissing__git_receive_pack () {
     mkrepotmp();
     $destrepo = "$dgitrepos/_tmp/${package}_prospective";
     acquiretree($destrepo, 1);
 #----- git-receive-pack -----
 
 sub fixmissing__git_receive_pack () {
     mkrepotmp();
     $destrepo = "$dgitrepos/_tmp/${package}_prospective";
     acquiretree($destrepo, 1);
-    my $template = "$dgitrepos/_template";
-    debug "fixmissing copy tempalate $template -> $destrepo";
-    my $r = system qw(cp -a --), $template, $destrepo;
-    !$r or die "create new repo failed failed: $r $!";
+    mkrepo_fromtemplate($destrepo);
 }
 
 sub makeworkingclone () {
 }
 
 sub makeworkingclone () {
@@ -222,6 +247,7 @@ sub makeworkingclone () {
     $workrepo = "$dgitrepos/_tmp/${package}_incoming$$";
     acquiretree($workrepo, 1);
     runcmd qw(git clone -l -q --mirror), $destrepo, $workrepo;
     $workrepo = "$dgitrepos/_tmp/${package}_incoming$$";
     acquiretree($workrepo, 1);
     runcmd qw(git clone -l -q --mirror), $destrepo, $workrepo;
+    rmtree "${workrepo}_fresh";
 }
 
 sub setupstunthook () {
 }
 
 sub setupstunthook () {
@@ -239,6 +265,15 @@ END
     debug " stunt hook set up $prerecv";
 }
 
     debug " stunt hook set up $prerecv";
 }
 
+sub dealwithfreshrepo () {
+    my $freshrepo = "${workrepo}_fresh";
+    if (!stat $freshrepo) {
+       $!==ENOENT or die "$freshrepo $!";
+       return;
+    }
+    $destrepo = $freshrepo;
+}
+
 sub maybeinstallprospective () {
     return if $destrepo eq $realdestrepo;
 
 sub maybeinstallprospective () {
     return if $destrepo eq $realdestrepo;
 
@@ -278,6 +313,8 @@ sub maybeinstallprospective () {
     die Dumper(\%got)." -- missing refs in new repo"
        if grep { !$_ } values %got;
 
     die Dumper(\%got)." -- missing refs in new repo"
        if grep { !$_ } values %got;
 
+    movetogarbage; # in case of FRESHREPO
+
     debug "install $destrepo => $realdestrepo";
     rename $destrepo, $realdestrepo or die $!;
     remove "$destrepo.lock" or die $!;
     debug "install $destrepo => $realdestrepo";
     rename $destrepo, $realdestrepo or die $!;
     remove "$destrepo.lock" or die $!;
@@ -287,6 +324,7 @@ sub main__git_receive_pack () {
     makeworkingclone();
     setupstunthook();
     runcmd qw(git receive-pack), $workrepo;
     makeworkingclone();
     setupstunthook();
     runcmd qw(git receive-pack), $workrepo;
+    dealwithfreshrepo();
     maybeinstallprospective();
 }
 
     maybeinstallprospective();
 }
 
@@ -509,9 +547,9 @@ sub checks () {
     debug "translated version $v";
     $tagname eq "debian/$v" or die;
 
     debug "translated version $v";
     $tagname eq "debian/$v" or die;
 
-    my ($policy) = policyhook(NOFFCHECK, 'push',$package,
-                             $version,$suite,$tagname,
-                             join(",",@delberatelies));
+    $policy = policyhook(NOFFCHECK|FRESHREPO, 'push',$package,
+                        $version,$suite,$tagname,
+                        join(",",@delberatelies));
 
     checksuite();
 
 
     checksuite();
 
@@ -522,17 +560,24 @@ sub checks () {
        chomp $mb;
        $mb eq $oldcommit or reject "not fast forward on dgit branch";
     }
        chomp $mb;
        $mb eq $oldcommit or reject "not fast forward on dgit branch";
     }
-}
 
 
-sub onwardpush () {
-    my @cmd = (qw(git send-pack), $destrepo,
-              "$commit:refs/dgit/$suite",
-              "$tagval:refs/tags/$tagname");
-    debugcmd @cmd;
-    $!=0;
-    my $r = system @cmd;
-    !$r or die "onward push failed: $r $!";
-}      
+    if ($policy & FRESHREPO) {
+       # This is troublesome.  We have been asked by the policy hook
+       # to receive the push into a fresh repo.  But of course we
+       # have actually already mostly received the push into the working
+       # repo.  (This is unavoidable because the instruction to use a new
+       # repo comes ultimately from the signed tag for the dgit push,
+       # which has to have been received into some repo.)
+       #
+       # So what we do is generate a fresh working repo right now and
+       # push the head and tag into it.  The presence of this fresh
+       # working repo is detected by the parent, which responds by
+       # making a fresh master repo from the template.
+
+       $destrepo = "${workrepo}_fresh"; # workrepo lock covers
+       mkrepo_fromtemplate $destrepo;
+    }
+}
 
 sub stunthook () {
     debug "stunthook";
 
 sub stunthook () {
     debug "stunthook";
@@ -637,12 +682,7 @@ sub parseargsdispatch () {
 
     my ($policy, $pollock) = policyhook(FRESHREPO,'check-package',$package);
     if ($policy & FRESHREPO) {
 
     my ($policy, $pollock) = policyhook(FRESHREPO,'check-package',$package);
     if ($policy & FRESHREPO) {
-       my $garbagerepo = "$dgitrepos/_tmp/${package}_garbage";
-       acquiretree($garbagerepo,1);
-       rmtree $garbagerepo;
-       rename $realdestrepo, $garbagerepo
-           or $! == ENOENT
-           or die "rename repo $destrepo to $garbagerepo: $!";
+       movetogarbage;
     }
     close $pollock or die $!;
 
     }
     close $pollock or die $!;