cat-file: sort and de-dup output of --batch-all-objects

The sorting we could probably live without, but printing duplicates is just a hassle for the user, who must then de-dup themselves (or risk a wrong answer if they are doing something like counting objects with a particular property). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Jun 22, 2015 at 07:06 UTC 3115ee45c8c7c0b753663890b13ec0e14fe4c0d7
3 files changed +18 -12
Documentation/git-cat-file.txt
+1 -2
@@ -74,8 +74,7 @@ OPTIONS
74 requested batch operation on all objects in the repository and
75 any alternate object stores (not just reachable objects).
76 Requires `--batch` or `--batch-check` be specified. Note that
77 - the order of the objects is unspecified, and there may be
78 - duplicate entries.
77 + the objects are visited in order sorted by their hashes.
78
79 --buffer::
80 Normally batch output is flushed after each object is output, so
builtin/cat-file.c
+15 -7
@@ -9,6 +9,7 @@
9 #include "userdiff.h"
10 #include "streaming.h"
11 #include "tree-walk.h"
12 +#include "sha1-array.h"
13
14 struct batch_options {
15 int enabled;
@@ -324,19 +325,19 @@ struct object_cb_data {
325 struct expand_data *expand;
326 };
327
327 -static int batch_object_cb(const unsigned char *sha1,
328 - struct object_cb_data *data)
328 +static void batch_object_cb(const unsigned char sha1[20], void *vdata)
329 {
330 + struct object_cb_data *data = vdata;
331 hashcpy(data->expand->sha1, sha1);
332 batch_object_write(NULL, data->opt, data->expand);
332 - return 0;
333 }
334
335 static int batch_loose_object(const unsigned char *sha1,
336 const char *path,
337 void *data)
338 {
339 - return batch_object_cb(sha1, data);
339 + sha1_array_append(data, sha1);
340 + return 0;
341 }
342
343 static int batch_packed_object(const unsigned char *sha1,
@@ -344,7 +345,8 @@ static int batch_packed_object(const unsigned char *sha1,
345 uint32_t pos,
346 void *data)
347 {
347 - return batch_object_cb(sha1, data);
348 + sha1_array_append(data, sha1);
349 + return 0;
350 }
351
352 static int batch_objects(struct batch_options *opt)
@@ -375,11 +377,17 @@ static int batch_objects(struct batch_options *opt)
377 data.info.typep = &data.type;
378
379 if (opt->all_objects) {
380 + struct sha1_array sa = SHA1_ARRAY_INIT;
381 struct object_cb_data cb;
382 +
383 + for_each_loose_object(batch_loose_object, &sa, 0);
384 + for_each_packed_object(batch_packed_object, &sa, 0);
385 +
386 cb.opt = opt;
387 cb.expand = &data;
381 - for_each_loose_object(batch_loose_object, &cb, 0);
382 - for_each_packed_object(batch_packed_object, &cb, 0);
388 + sha1_array_for_each_unique(&sa, batch_object_cb, &cb);
389 +
390 + sha1_array_clear(&sa);
391 return 0;
392 }
393
t/t1006-cat-file.sh
+2 -3
@@ -548,7 +548,7 @@ test_expect_success 'git cat-file --batch --follow-symlink returns correct sha a
548 '
549
550 test_expect_success 'cat-file --batch-all-objects shows all objects' '
551 - # make new repos so we now the full set of objects; we will
551 + # make new repos so we know the full set of objects; we will
552 # also make sure that there are some packed and some loose
553 # objects, some referenced and some not, and that there are
554 # some available only via alternates.
@@ -569,8 +569,7 @@ test_expect_success 'cat-file --batch-all-objects shows all objects' '
569 ) >>expect.unsorted &&
570 sort <expect.unsorted >expect &&
571 git -C all-two cat-file --batch-all-objects \
572 - --batch-check="%(objectname)" >actual.unsorted &&
573 - sort <actual.unsorted >actual &&
572 + --batch-check="%(objectname)" >actual &&
573 test_cmp expect actual
574 '
575