]> Pileus Git - ~andy/git/commitdiff
cat-file: provide %(deltabase) batch format
authorJeff King <peff@peff.net>
Sat, 21 Dec 2013 14:25:22 +0000 (09:25 -0500)
committerJunio C Hamano <gitster@pobox.com>
Thu, 26 Dec 2013 19:54:26 +0000 (11:54 -0800)
It can be useful for debugging or analysis to see which
objects are stored as delta bases on top of others. This
information is available by running `git verify-pack`, but
that is extremely expensive (and is harder than necessary to
parse).

Instead, let's make it available as a cat-file query format,
which makes it fast and simple to get the bases for a subset
of the objects.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git-cat-file.txt
builtin/cat-file.c
t/t1006-cat-file.sh

index 322f5ed3155887ef69876bd439a12c4641007c9e..f6a16f4300b15669a518faa3d8a63d7586233258 100644 (file)
@@ -109,6 +109,11 @@ newline. The available atoms are:
        The size, in bytes, that the object takes up on disk. See the
        note about on-disk sizes in the `CAVEATS` section below.
 
+`deltabase`::
+       If the object is stored as a delta on-disk, this expands to the
+       40-hex sha1 of the delta base object. Otherwise, expands to the
+       null sha1 (40 zeroes). See `CAVEATS` below.
+
 `rest`::
        If this atom is used in the output string, input lines are split
        at the first whitespace boundary. All characters before that
@@ -152,10 +157,11 @@ should be taken in drawing conclusions about which refs or objects are
 responsible for disk usage. The size of a packed non-delta object may be
 much larger than the size of objects which delta against it, but the
 choice of which object is the base and which is the delta is arbitrary
-and is subject to change during a repack. Note also that multiple copies
-of an object may be present in the object database; in this case, it is
-undefined which copy's size will be reported.
+and is subject to change during a repack.
 
+Note also that multiple copies of an object may be present in the object
+database; in this case, it is undefined which copy's size or delta base
+will be reported.
 
 GIT
 ---
index b2ca775a80f54fcceba344d5545fe3cb34ba0184..2e0af2e617e400a5c99465edd82f0dd1f8927680 100644 (file)
@@ -118,6 +118,7 @@ struct expand_data {
        unsigned long size;
        unsigned long disk_size;
        const char *rest;
+       unsigned char delta_base_sha1[20];
 
        /*
         * If mark_query is true, we do not expand anything, but rather
@@ -174,6 +175,11 @@ static void expand_atom(struct strbuf *sb, const char *atom, int len,
                        data->split_on_whitespace = 1;
                else if (data->rest)
                        strbuf_addstr(sb, data->rest);
+       } else if (is_atom("deltabase", atom, len)) {
+               if (data->mark_query)
+                       data->info.delta_base_sha1 = data->delta_base_sha1;
+               else
+                       strbuf_addstr(sb, sha1_to_hex(data->delta_base_sha1));
        } else
                die("unknown format element: %.*s", len, atom);
 }
index 8a1bc5c53281eb6f44c15d68dd0ae737bc0125f3..633dc825ec49eb98be10c8f75545a6978c290231 100755 (executable)
@@ -240,4 +240,38 @@ test_expect_success "--batch-check with multiple sha1s gives correct format" '
     "$(echo_without_newline "$batch_check_input" | git cat-file --batch-check)"
 '
 
+test_expect_success 'setup blobs which are likely to delta' '
+       test-genrandom foo 10240 >foo &&
+       { cat foo; echo plus; } >foo-plus &&
+       git add foo foo-plus &&
+       git commit -m foo &&
+       cat >blobs <<-\EOF
+       HEAD:foo
+       HEAD:foo-plus
+       EOF
+'
+
+test_expect_success 'confirm that neither loose blob is a delta' '
+       cat >expect <<-EOF
+       $_z40
+       $_z40
+       EOF
+       git cat-file --batch-check="%(deltabase)" <blobs >actual &&
+       test_cmp expect actual
+'
+
+# To avoid relying too much on the current delta heuristics,
+# we will check only that one of the two objects is a delta
+# against the other, but not the order. We can do so by just
+# asking for the base of both, and checking whether either
+# sha1 appears in the output.
+test_expect_success '%(deltabase) reports packed delta bases' '
+       git repack -ad &&
+       git cat-file --batch-check="%(deltabase)" <blobs >actual &&
+       {
+               grep "$(git rev-parse HEAD:foo)" actual ||
+               grep "$(git rev-parse HEAD:foo-plus)" actual
+       }
+'
+
 test_done