cat-file: teach cat-file a '--allow-unknown-type' option

'git cat-file' throws an error while trying to print the type or size of a broken/corrupt object. This is because these objects are usually of unknown types. Teach git cat-file a '--allow-unknown-type' option where it prints the type or size of a broken/corrupt object without throwing an error. Modify '-t' and '-s' options to call sha1_object_info_extended() directly to support the '--allow-unknown-type' option. Add documentation for 'cat-file --allow-unknown-type'. Helped-by: Junio C Hamano <gitster@pobox.com> Helped-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Karthik Nayak <karthik.188@gmail.com> cat-file: add documentation for '--allow-unknown-type' option. Signed-off-by: Karthik Nayak <karthik.188@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Karthik Nayak committed May 3, 2015 at 20:00 UTC 39e4ae388047bd7f6f3a4ad86ba5eba523dd0668
2 files changed +30 -13
Documentation/git-cat-file.txt
+4 -1
@@ -9,7 +9,7 @@ git-cat-file - Provide content or type and size information for repository objec
9 SYNOPSIS
10 --------
11 [verse]
12 -'git cat-file' (-t | -s | -e | -p | <type> | --textconv ) <object>
12 +'git cat-file' (-t [--allow-unknown-type]| -s [--allow-unknown-type]| -e | -p | <type> | --textconv ) <object>
13 'git cat-file' (--batch | --batch-check) < <list-of-objects>
14
15 DESCRIPTION
@@ -69,6 +69,9 @@ OPTIONS
69 not be combined with any other options or arguments. See the
70 section `BATCH OUTPUT` below for details.
71
72 +--allow-unknown-type::
73 + Allow -s or -t to query broken/corrupt objects of unknown type.
74 +
75 OUTPUT
76 ------
77 If '-t' is specified, one of the <type>.
builtin/cat-file.c
+26 -12
@@ -9,13 +9,20 @@
9 #include "userdiff.h"
10 #include "streaming.h"
11
12 -static int cat_one_file(int opt, const char *exp_type, const char *obj_name)
12 +static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
13 + int unknown_type)
14 {
15 unsigned char sha1[20];
16 enum object_type type;
17 char *buf;
18 unsigned long size;
19 struct object_context obj_context;
20 + struct object_info oi = {NULL};
21 + struct strbuf sb = STRBUF_INIT;
22 + unsigned flags = LOOKUP_REPLACE_OBJECT;
23 +
24 + if (unknown_type)
25 + flags |= LOOKUP_UNKNOWN_OBJECT;
26
27 if (get_sha1_with_context(obj_name, 0, sha1, &obj_context))
28 die("Not a valid object name %s", obj_name);
@@ -23,20 +30,22 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name)
30 buf = NULL;
31 switch (opt) {
32 case 't':
26 - type = sha1_object_info(sha1, NULL);
27 - if (type > 0) {
28 - printf("%s\n", typename(type));
33 + oi.typename = &sb;
34 + if (sha1_object_info_extended(sha1, &oi, flags) < 0)
35 + die("git cat-file: could not get object info");
36 + if (sb.len) {
37 + printf("%s\n", sb.buf);
38 + strbuf_release(&sb);
39 return 0;
40 }
41 break;
42
43 case 's':
34 - type = sha1_object_info(sha1, &size);
35 - if (type > 0) {
36 - printf("%lu\n", size);
37 - return 0;
38 - }
39 - break;
44 + oi.sizep = &size;
45 + if (sha1_object_info_extended(sha1, &oi, flags) < 0)
46 + die("git cat-file: could not get object info");
47 + printf("%lu\n", size);
48 + return 0;
49
50 case 'e':
51 return !has_sha1_file(sha1);
@@ -323,7 +332,7 @@ static int batch_objects(struct batch_options *opt)
332 }
333
334 static const char * const cat_file_usage[] = {
326 - N_("git cat-file (-t | -s | -e | -p | <type> | --textconv) <object>"),
335 + N_("git cat-file (-t [--allow-unknown-type]|-s [--allow-unknown-type]|-e|-p|<type>|--textconv) <object>"),
336 N_("git cat-file (--batch | --batch-check) < <list-of-objects>"),
337 NULL
338 };
@@ -359,6 +368,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
368 int opt = 0;
369 const char *exp_type = NULL, *obj_name = NULL;
370 struct batch_options batch = {0};
371 + int unknown_type = 0;
372
373 const struct option options[] = {
374 OPT_GROUP(N_("<type> can be one of: blob, tree, commit, tag")),
@@ -369,6 +379,8 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
379 OPT_CMDMODE('p', NULL, &opt, N_("pretty-print object's content"), 'p'),
380 OPT_CMDMODE(0, "textconv", &opt,
381 N_("for blob objects, run textconv on object's content"), 'c'),
382 + OPT_BOOL( 0, "allow-unknown-type", &unknown_type,
383 + N_("allow -s and -t to work with broken/corrupt objects")),
384 { OPTION_CALLBACK, 0, "batch", &batch, "format",
385 N_("show info and content of objects fed from the standard input"),
386 PARSE_OPT_OPTARG, batch_option_callback },
@@ -402,5 +414,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
414 if (batch.enabled)
415 return batch_objects(&batch);
416
405 - return cat_one_file(opt, exp_type, obj_name);
417 + if (unknown_type && opt != 't' && opt != 's')
418 + die("git cat-file --allow-unknown-type: use with -s or -t");
419 + return cat_one_file(opt, exp_type, obj_name, unknown_type);
420 }