upload-pack: feed "kind [clone|fetch]" to post-upload-pack hook
authorJunio C Hamano <gitster@pobox.com>
Sat, 29 Aug 2009 05:19:45 +0000 (22:19 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sat, 29 Aug 2009 05:39:24 +0000 (22:39 -0700)
A request to clone the repository does not give any "have" but asks for
all the refs we offer with "want". When a request does not ask to clone
the repository fully, but asks to fetch some refs into an empty
repository, it will not give any "have" but its "want" won't ask for all
the refs we offer.

If we suppose (and I would say this is a rather big if) that it makes
sense to distinguish these two cases, a hook cannot reliably do this
alone. The hook can detect lack of "have" and bunch of "want", but there
is no direct way to tell if the other end asked for all refs we offered,
or merely most of them.

Between the time we talked with the other end and the time the hook got
called, we may have acquired more refs or lost some refs in the repository
by concurrent operations. Given that we plan to introduce selective
advertisement of refs with a protocol extension, it would become even more
difficult for hooks to guess between these two cases.

This adds "kind [clone|fetch]" to hook's input, as a stable interface to
allow the hooks to tell these cases apart.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/githooks.txt
t/t5501-post-upload-pack.sh
upload-pack.c
index 036f6c79973655188a55dd048f72df34f92a0d29..c308d2943c11e46fe781724a5fef04fb567a791f 100644 (file)
@@ -332,6 +332,10 @@ time float::
 size decimal::
     Size of the resulting packfile in bytes.
 
+kind string:
+    Either "clone" (when the client did not give us any "have", and asked
+    for all our refs with "want"), or "fetch" (otherwise).
+
 pre-auto-gc
 -----------
 
index 47ee7b5039a02d0bc5ca3a3ada305ac860d3aaa8..d89fb51bad36acd9affc862a5086674aad5847d9 100755 (executable)
@@ -29,7 +29,9 @@ test_expect_success initial '
        ) &&
        want=$(sed -n "s/^want //p" "$LOGFILE") &&
        test "$want" = "$(git rev-parse --verify B)" &&
-       ! grep "^have " "$LOGFILE"
+       ! grep "^have " "$LOGFILE" &&
+       kind=$(sed -n "s/^kind //p" "$LOGFILE") &&
+       test "$kind" = fetch
 '
 
 test_expect_success second '
@@ -43,7 +45,25 @@ test_expect_success second '
        want=$(sed -n "s/^want //p" "$LOGFILE") &&
        test "$want" = "$(git rev-parse --verify C)" &&
        have=$(sed -n "s/^have //p" "$LOGFILE") &&
-       test "$have" = "$(git rev-parse --verify B)"
+       test "$have" = "$(git rev-parse --verify B)" &&
+       kind=$(sed -n "s/^kind //p" "$LOGFILE") &&
+       test "$kind" = fetch
+'
+
+test_expect_success all '
+       rm -fr sub &&
+       HERE=$(pwd) &&
+       git init sub &&
+       (
+               cd sub &&
+               git clone "file://$HERE/.git" new
+       ) &&
+       sed -n "s/^want //p" "$LOGFILE" | sort >actual &&
+       git rev-parse A B C | sort >expect &&
+       test_cmp expect actual &&
+       ! grep "^have " "$LOGFILE" &&
+       kind=$(sed -n "s/^kind //p" "$LOGFILE") &&
+       test "$kind" = clone
 '
 
 test_done
index 857440d5798be4a175ecffb23dc96be1cae497ad..8e82179c93b8286329670a9b236da6632c3aba6b 100644 (file)
@@ -187,6 +187,10 @@ static int run_post_upload_pack_hook(size_t total, struct timeval *tv)
                                        (long)tv->tv_sec, (long)tv->tv_usec);
        if (!err)
                err |= feed_msg_to_hook(proc.in, "size %ld\n", (long)total);
+       if (!err)
+               err |= feed_msg_to_hook(proc.in, "kind %s\n",
+                                       (nr_our_refs == want_obj.nr && !have_obj.nr)
+                                       ? "clone" : "fetch");
        if (close(proc.in))
                err = 1;
        if (finish_command(&proc))