chiark / gitweb /
dgit-repos-server: wip
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 12 Jan 2014 20:06:54 +0000 (20:06 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Wed, 5 Mar 2014 18:29:02 +0000 (18:29 +0000)
dgit-repos-server

index 677e3d7..0cbcf35 100644 (file)
 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();
 }