chiark / gitweb /
Move stat_exists to Dgit.pm
[dgit.git] / infra / dgit-repos-server
index ef9f968..d2f94f1 100755 (executable)
@@ -124,10 +124,7 @@ sub acquirelock ($$) {
            debug " locking $lock failed";
            return undef;
        }
-       if (!stat $lock) {
-           next if $! == ENOENT;
-           die "stat $lock: $!";
-       }
+       next unless stat_exists $lock;
        my $want = (stat _)[1];
        stat $fh or die $!;
        my $got = (stat _)[1];
@@ -247,6 +244,7 @@ sub makeworkingclone () {
     $workrepo = "$dgitrepos/_tmp/${package}_incoming$$";
     acquiretree($workrepo, 1);
     runcmd qw(git clone -l -q --mirror), $destrepo, $workrepo;
+    rmtree "${workrepo}_fresh";
 }
 
 sub setupstunthook () {
@@ -264,6 +262,12 @@ END
     debug " stunt hook set up $prerecv";
 }
 
+sub dealwithfreshrepo () {
+    my $freshrepo = "${workrepo}_fresh";
+    return unless stat_exists $freshrepo;
+    $destrepo = $freshrepo;
+}
+
 sub maybeinstallprospective () {
     return if $destrepo eq $realdestrepo;
 
@@ -303,6 +307,8 @@ sub maybeinstallprospective () {
     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 $!;
@@ -312,6 +318,7 @@ sub main__git_receive_pack () {
     makeworkingclone();
     setupstunthook();
     runcmd qw(git receive-pack), $workrepo;
+    dealwithfreshrepo();
     maybeinstallprospective();
 }
 
@@ -547,6 +554,23 @@ sub checks () {
        chomp $mb;
        $mb eq $oldcommit or reject "not fast forward on dgit branch";
     }
+
+    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 () {
@@ -566,8 +590,7 @@ sub stunthook () {
 sub fixmissing__git_upload_pack () {
     $destrepo = "$dgitrepos/_empty";
     my $lfh = acquiretree($destrepo,1);
-    return if stat $destrepo;
-    die $! unless $!==ENOENT;
+    return if stat_exists $destrepo;
     rmtree "$destrepo.new";
     mkemptyrepo "$destrepo.new", "0644";
     rename "$destrepo.new", $destrepo or die $!;
@@ -656,10 +679,9 @@ sub parseargsdispatch () {
     }
     close $pollock or die $!;
 
-    if (stat $realdestrepo) {
+    if (stat_exists $realdestrepo) {
        $destrepo = $realdestrepo;
     } else {
-       $! == ENOENT or die "stat dest repo $destrepo: $!";
        debug " fixmissing $funcn";
        my $fixfunc = $main::{"fixmissing__$funcn"};
        &$fixfunc;