diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt index de29e6d79d9133..69b50d2042ff2f 100644 --- a/Documentation/git-cat-file.txt +++ b/Documentation/git-cat-file.txt @@ -412,6 +412,11 @@ 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. +Submodules are handled specially in `git cat-file`, as the objects +corresponding to the recorded OIDs are not expected to be present in the +current repository. For that reason, submodules are reported as having +type `submodule` and mode 1600000 and all other fields are zeroed out. + GIT --- Part of the linkgit:git[1] suite diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 73bd78c0b63005..c59ad682d1f6d9 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -128,7 +128,9 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name, switch (opt) { case 't': oi.type_name = &sb; - if (oid_object_info_extended(the_repository, &oid, &oi, flags) < 0) + if (obj_context.mode == S_IFGITLINK) + strbuf_addstr(&sb, "submodule"); + else if (oid_object_info_extended(the_repository, &oid, &oi, flags) < 0) die("git cat-file: could not get object info"); if (sb.len) { printf("%s\n", sb.buf); @@ -319,17 +321,26 @@ static void expand_atom(struct strbuf *sb, const char *atom, int len, if (!data->mark_query) strbuf_addstr(sb, oid_to_hex(&data->oid)); } else if (is_atom("objecttype", atom, len)) { - if (data->mark_query) + if (data->mode == S_IFGITLINK) { + if (!data->mark_query) + strbuf_addstr(sb, "submodule"); + } else if (data->mark_query) data->info.typep = &data->type; else strbuf_addstr(sb, type_name(data->type)); } else if (is_atom("objectsize", atom, len)) { - if (data->mark_query) + if (data->mode == S_IFGITLINK) { + if (!data->mark_query) + strbuf_addstr(sb, "0"); + } else if (data->mark_query) data->info.sizep = &data->size; else strbuf_addf(sb, "%"PRIuMAX , (uintmax_t)data->size); } else if (is_atom("objectsize:disk", atom, len)) { - if (data->mark_query) + if (data->mode == S_IFGITLINK) { + if (!data->mark_query) + strbuf_addstr(sb, "0"); + } else if (data->mark_query) data->info.disk_sizep = &data->disk_size; else strbuf_addf(sb, "%"PRIuMAX, (uintmax_t)data->disk_size); @@ -448,7 +459,8 @@ static void print_default_format(struct strbuf *scratch, struct expand_data *dat struct batch_options *opt) { strbuf_addf(scratch, "%s %s %"PRIuMAX"%c", oid_to_hex(&data->oid), - type_name(data->type), + data->mode == S_IFGITLINK ? + "submodule" : type_name(data->type), (uintmax_t)data->size, opt->output_delim); } @@ -470,7 +482,15 @@ static void batch_object_write(const char *obj_name, if (use_mailmap) data->info.typep = &data->type; - if (pack) + if (data->mode == S_IFGITLINK) { + data->type = OBJ_BAD; /* `type_name()` does not know submodules */ + data->size = 0; + data->disk_size = 0; + data->rest = NULL; + oidcpy(&data->delta_base_oid, null_oid()); + memset(&data->info, 0, sizeof(data->info)); + ret = 0; /* no info to look up */ + } else if (pack) ret = packed_object_info(the_repository, pack, offset, &data->info); else diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh index 6f25cc20ec6fe2..3368b663ef3fda 100755 --- a/t/t1006-cat-file.sh +++ b/t/t1006-cat-file.sh @@ -1178,6 +1178,16 @@ test_expect_success 'cat-file --batch-check respects replace objects' ' test_cmp expect actual ' +test_expect_success 'batch-command with a submodule' ' + printf "160000 commit %0.*d\tsub\n" $(test_oid hexsz) 17 >tree-with-sub && + tree=$(git mktree actual <<-EOF && + $tree:sub + EOF + printf "%0.*d submodule 0\n" $(test_oid hexsz) 17 >expect && + test_cmp expect actual +' + # Pull the entry for object with oid "$1" out of the output of # "cat-file --batch", including its object content (which requires # parsing and reading a set amount of bytes, hence perl).