X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=dgit.git;a=blobdiff_plain;f=infra%2Fdgit-repos-server;h=ab831364ddb8577284cc5cf3f4019f3d44fc2d27;hp=f700df81ca1f507e711afff2bceea5097919f0ee;hb=fb73b55ade7687b65727b1146b860ea892425cc6;hpb=03894a4813bd99f86c188de61d72c0a05833e5cb diff --git a/infra/dgit-repos-server b/infra/dgit-repos-server index f700df81..ab831364 100755 --- a/infra/dgit-repos-server +++ b/infra/dgit-repos-server @@ -234,12 +234,9 @@ sub lockrealtree () { locksometree(realdestrepo); } -sub mkrepotmp () { - my $tmpdir = "$dgitrepos/_tmp"; - return if mkdir $tmpdir; - return if $! == EEXIST; - die $!; -} +sub mkrepotmp () { ensuredir "$dgitrepos/_tmp" }; + +sub removedtagsfile () { "$dgitrepos/_removed-tags/$package"; } sub recorderror ($) { my ($why) = @_; @@ -635,10 +632,10 @@ sub checksuite () { } sub checktagnoreplay () { - # We check that the signed tag mentions the name and value of + # We check that the signed tag mentions the name and tag object id of # (a) in the case of FRESHREPO all tags in the repo; # (b) in the case of just NOFFCHECK all tags referring to - # the current head for the suite (there must be at least one). + # the current head for the suite (there must be at least one). # This prevents a replay attack using an earlier signed tag. return unless $policy & (FRESHREPO|NOFFCHECK); @@ -680,14 +677,29 @@ sub checktagnoreplay () { my @problems; git_for_each_tag_referring($onlyreferring, sub { - my ($objid,$refobjid,$fullrefname,$tagname) = @_; - printdebug "checktagnoreplay - overwriting $fullrefname=$objid\n"; + my ($tagobjid,$refobjid,$fullrefname,$tagname) = @_; + printdebug "checktagnoreplay - overwriting". + " $fullrefname=$tagobjid->$refobjid\n"; my $supers = $supersedes{$fullrefname}; if (!defined $supers) { - push @problems, "does not supersede $fullrefname"; - } elsif ($supers ne $objid) { + printdebug "checktagnoreply - fallbacks\n"; + my $super_fallback = 0; + foreach my $didsuper (sort keys %supersedes) { + my $didsuper_tagobjid = $supersedes{$didsuper}; + my $didsuper_refobjid = git_rev_parse $didsuper_tagobjid; + printdebug "checktagnoreply - fallback". + " $didsuper=$didsuper_refobjid->$didsuper_tagobjid\n"; + last if + $refobjid ne $didsuper_refobjid + and is_fast_fwd($refobjid, $didsuper_refobjid); + printdebug "checktagnoreply - fallback $didsuper OK\n"; + $super_fallback = 1; + } + push @problems, "does not supersede $fullrefname" + unless $super_fallback; + } elsif ($supers ne $tagobjid) { push @problems, - "supersedes $fullrefname=$supers but previously $fullrefname=$objid"; + "supersedes $fullrefname=$supers but previously $fullrefname=$tagobjid"; } else { # ok; }