diff options
-rw-r--r-- | Documentation/git-cat-file.txt | 8 | ||||
-rw-r--r-- | builtin/cat-file.c | 44 | ||||
-rwxr-xr-x | t/t1006-cat-file.sh | 27 |
3 files changed, 77 insertions, 2 deletions
diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt index 0058bd42aa..6831b08efb 100644 --- a/Documentation/git-cat-file.txt +++ b/Documentation/git-cat-file.txt @@ -69,6 +69,14 @@ OPTIONS not be combined with any other options or arguments. See the section `BATCH OUTPUT` below for details. +--batch-all-objects:: + Instead of reading a list of objects on stdin, perform the + requested batch operation on all objects in the repository and + any alternate object stores (not just reachable objects). + Requires `--batch` or `--batch-check` be specified. Note that + the order of the objects is unspecified, and there may be + duplicate entries. + --buffer:: Normally batch output is flushed after each object is output, so that a process can interactively read and write from diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 499ccda6b6..95604c4a63 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -15,6 +15,7 @@ struct batch_options { int follow_symlinks; int print_contents; int buffer_output; + int all_objects; const char *format; }; @@ -257,7 +258,7 @@ static void batch_object_write(const char *obj_name, struct batch_options *opt, struct strbuf buf = STRBUF_INIT; if (sha1_object_info_extended(data->sha1, &data->info, LOOKUP_REPLACE_OBJECT) < 0) { - printf("%s missing\n", obj_name); + printf("%s missing\n", obj_name ? obj_name : sha1_to_hex(data->sha1)); fflush(stdout); return; } @@ -318,6 +319,34 @@ static void batch_one_object(const char *obj_name, struct batch_options *opt, batch_object_write(obj_name, opt, data); } +struct object_cb_data { + struct batch_options *opt; + struct expand_data *expand; +}; + +static int batch_object_cb(const unsigned char *sha1, + struct object_cb_data *data) +{ + hashcpy(data->expand->sha1, sha1); + batch_object_write(NULL, data->opt, data->expand); + return 0; +} + +static int batch_loose_object(const unsigned char *sha1, + const char *path, + void *data) +{ + return batch_object_cb(sha1, data); +} + +static int batch_packed_object(const unsigned char *sha1, + struct packed_git *pack, + uint32_t pos, + void *data) +{ + return batch_object_cb(sha1, data); +} + static int batch_objects(struct batch_options *opt) { struct strbuf buf = STRBUF_INIT; @@ -345,6 +374,15 @@ static int batch_objects(struct batch_options *opt) if (opt->print_contents) data.info.typep = &data.type; + if (opt->all_objects) { + struct object_cb_data cb; + cb.opt = opt; + cb.expand = &data; + for_each_loose_object(batch_loose_object, &cb, 0); + for_each_packed_object(batch_packed_object, &cb, 0); + return 0; + } + /* * We are going to call get_sha1 on a potentially very large number of * objects. In most large cases, these will be actual object sha1s. The @@ -436,6 +474,8 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) PARSE_OPT_OPTARG, batch_option_callback }, OPT_BOOL(0, "follow-symlinks", &batch.follow_symlinks, N_("follow in-tree symlinks (used with --batch or --batch-check)")), + OPT_BOOL(0, "batch-all-objects", &batch.all_objects, + N_("show all objects with --batch or --batch-check")), OPT_END() }; @@ -460,7 +500,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) usage_with_options(cat_file_usage, options); } - if (batch.follow_symlinks && !batch.enabled) { + if ((batch.follow_symlinks || batch.all_objects) && !batch.enabled) { usage_with_options(cat_file_usage, options); } diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh index 93a4794930..2b4220a604 100755 --- a/t/t1006-cat-file.sh +++ b/t/t1006-cat-file.sh @@ -547,4 +547,31 @@ test_expect_success 'git cat-file --batch --follow-symlink returns correct sha a test_cmp expect actual ' +test_expect_success 'cat-file --batch-all-objects shows all objects' ' + # make new repos so we now the full set of objects; we will + # also make sure that there are some packed and some loose + # objects, some referenced and some not, and that there are + # some available only via alternates. + git init all-one && + ( + cd all-one && + echo content >file && + git add file && + git commit -qm base && + git rev-parse HEAD HEAD^{tree} HEAD:file && + git repack -ad && + echo not-cloned | git hash-object -w --stdin + ) >expect.unsorted && + git clone -s all-one all-two && + ( + cd all-two && + echo local-unref | git hash-object -w --stdin + ) >>expect.unsorted && + sort <expect.unsorted >expect && + git -C all-two cat-file --batch-all-objects \ + --batch-check="%(objectname)" >actual.unsorted && + sort <actual.unsorted >actual && + test_cmp expect actual +' + test_done |