summaryrefslogtreecommitdiff
path: root/dgit-repos-server
diff options
context:
space:
mode:
Diffstat (limited to 'dgit-repos-server')
-rw-r--r--dgit-repos-server60
1 files changed, 42 insertions, 18 deletions
diff --git a/dgit-repos-server b/dgit-repos-server
index 677e3d7..0cbcf35 100644
--- a/dgit-repos-server
+++ b/dgit-repos-server
@@ -20,24 +20,48 @@
use strict;
# What we do is this:
-# - extract the destination repo name somehow
+# - extract the destination repo name
# - make a hardlink clone of the destination repo
# - provide the destination with a stunt pre-receive hook
# - run actual git-receive-pack with that new destination
# as a result of this the stunt pre-receive hook runs; it does this
-# find the keyring(s) to use for verification
-# verify the signed tag
-# check that the signed tag has a suitable name
-# parse the signed tag body to extract the intended
-# distro and suite
-# check that the distro is right
-# check that the suite is the same as the branch we are
-# supposed to update
-# check that the signed tag refers to the same commit
-# as the new suite
-# check that the signer was correct
-# push the signed tag to the actual repo
-# push the new dgit branch head to the actual repo
+# + understand what refs we are allegedly updating and
+# check some correspondences:
+# * we are updating only refs/tags/debian/* and refs/dgit/*
+# * and only one of each
+# * and the tag does not already exist
+# and
+# * recovering the suite name from the destination refs/dgit/ ref
+# + disassemble the signed tag into its various fields and signature
+# including:
+# * parsing the first line of the tag message to recover
+# the package name, version and suite
+# * checking that the package name corresponds to the dest repo name
+# * checking that the suite name is as recovered above
+# + verify the signature on the signed tag
+# and if necessary check that the keyid and package are listed in dm.txt
+# + check various correspondences:
+# * the suite is one of those permitted
+# * the signed tag must refer to a commit
+# * the signed tag commit must be the refs/dgit value
+# * the name in the signed tag must correspond to its ref name
+# * the tag name must be debian/<version> (massaged as needed)
+# * the signed tag has a suitable name
+# * the commit is a fast forward
+# + push the signed tag and new dgit branch to the actual repo
+#
+# If the destination repo does not already exist, we need to make
+# sure that we create it reasonably atomically, and also that
+# we don't every have a destination repo containing no refs at all
+# (because such a thing causes git-fetch-pack to barf). So then we
+# do as above, except:
+# - before starting, we take out our own lock for the destination repo
+# - we don't make a hardline clone of the destination repo; instead
+# we make a copy (not a hardlink clone) of _template
+# - we set up a post-receive hook as well, which does the following:
+# + check that exactly two refs were updated
+# + delete the two stunt hooks
+# + rename the working repo into place as the destination repo
use POSIX;
use Fcntl qw(:flock);
@@ -132,7 +156,6 @@ sub parsetag () {
open PT, ">dgit-tmp/plaintext" or die $!;
open DS, ">dgit-tmp/plaintext.asc" or die $!;
open T, "-|", qw(git cat-file tag), $tagval or die $!;
- my %tagh;
for (;;) {
$!=0; $_=<T>; defined or die $!;
print PT or die $!;
@@ -241,9 +264,10 @@ sub verifytag () {
reject "key not found in keyrings";
}
-sub checktag () {
- tagh1('object') eq $commit or die;
+sub checks () {
+fixme check the suite against the approved list
tagh1('type') eq 'commit' or die;
+ tagh1('object') eq $commit or die;
tagh1('tag') eq $tagname or die;
my $v = $version;
@@ -273,7 +297,7 @@ sub stunthook () {
readupdates();
parsetag();
verifytag();
- checktag();
+ checks();
onwardpush();
}