{"thread":{"id":"38976","subject":"[PATCH v6 0/4] cat-file: add a '--literally' option","startedAt":"2015-04-02T10:53:13Z","lastAt":"2015-04-04T04:13:00Z","messageCount":10,"participants":["karthik nayak","Karthik Nayak","Junio C Hamano"],"isPatch":true,"patchVersion":6,"patchTotal":4},"messages":[{"id":"258851","messageId":"551D1F99.5040306@gmail.com","threadId":"38976","inReplyTo":null,"subject":"[PATCH v6 0/4] cat-file: add a '--literally' option","fromName":"karthik nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-04-02T10:53:13Z","receivedAt":"2015-04-02T10:53:13Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"The changes made in this version are :\n\n*  unpack_sha1_header_to_strbuf() now checks for Z_STREAM_END and also\nthe return is not changed to status (as per Junios suggestion) as this \nbreaks the check done in sha1_loose_object_info() as the return is \nsometimes Z_BUF_ERROR (-5).\n\n* In sha1_loose_object_info() if the status is set, then change the type \nto status. Also check for this in cat-file.c\n\n* Add documentation and tests for the same.\n\nThanks for your suggestions.\n"},{"id":"258852","messageId":"1427972288-15298-1-git-send-email-karthik.188@gmail.com","threadId":"38976","inReplyTo":"551D1F99.5040306@gmail.com","subject":"[PATCH v6 1/4] sha1_file.c: support reading from a loose object of unknown type","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-04-02T10:58:08Z","receivedAt":"2015-04-02T10:58:08Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Update sha1_loose_object_info() to optionally allow it to read\nfrom a loose object file of unknown/bogus type; as the function\nusually returns the type of the object it read in the form of enum\nfor known types, add an optional \"typename\" field to receive the\nname of the type in textual form and a flag to indicate the reading\nof a loose object file of unknown/bogus type.\n\nAdd parse_sha1_header_extended() which acts as a wrapper around\nparse_sha1_header() allowing more information to be obtained.\n\nAdd unpack_sha1_header_to_strbuf() to unpack sha1 headers of\nunknown/corrupt objects which have a unknown sha1 header size to\na strbuf structure. This was written by Junio C Hamano but tested\nby me.\n\nHelped-by: Junio C Hamano <gitster@pobox.com>\nHelped-by: Eric Sunshine <sunshine@sunshineco.com>\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n cache.h     |   2 ++\n sha1_file.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++------------\n 2 files changed, 91 insertions(+), 22 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex 4d02efc..949ef4c 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -830,6 +830,7 @@ extern int is_ntfs_dotgit(const char *name);\n \n /* object replacement */\n #define LOOKUP_REPLACE_OBJECT 1\n+#define LOOKUP_LITERALLY 2\n extern void *read_sha1_file_extended(const unsigned char *sha1, enum object_type *type, unsigned long *size, unsigned flag);\n static inline void *read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size)\n {\n@@ -1296,6 +1297,7 @@ struct object_info {\n \tunsigned long *sizep;\n \tunsigned long *disk_sizep;\n \tunsigned char *delta_base_sha1;\n+\tstruct strbuf *typename;\n \n \t/* Response */\n \tenum {\ndiff --git a/sha1_file.c b/sha1_file.c\nindex 69a60ec..8b58b94 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -1564,6 +1564,34 @@ int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long ma\n \treturn git_inflate(stream, 0);\n }\n \n+static int unpack_sha1_header_to_strbuf(git_zstream *stream, unsigned char *map,\n+\t\t\t\t\tunsigned long mapsize,\n+\t\t\t\t\tstruct strbuf *header)\n+{\n+\tunsigned char buffer[32], *cp;\n+\tunsigned long bufsiz = sizeof(buffer);\n+\tint status;\n+\n+\tstatus = unpack_sha1_header(stream, map, mapsize, buffer, bufsiz);\n+\n+\tif (status) {\n+\t\tstrbuf_add(header, buffer, stream->next_out - buffer);\n+\t\treturn status;\n+\t}\n+\n+\tdo {\n+\t\tstatus = git_inflate(stream, 0);\n+\t\tstrbuf_add(header, buffer, stream->next_out - buffer);\n+\t\tfor (cp = buffer; cp < stream->next_out; cp++)\n+\t\t\tif (!*cp)\n+\t\t\t\t/* Found the NUL at the end of the header */\n+\t\t\t\treturn 0;\n+\t\tstream->next_out = buffer;\n+\t\tstream->avail_out = bufsiz;\n+\t} while (status != Z_STREAM_END);\n+\treturn -1;\n+}\n+\n static void *unpack_sha1_rest(git_zstream *stream, void *buffer, unsigned long size, const unsigned char *sha1)\n {\n \tint bytes = strlen(buffer) + 1;\n@@ -1614,27 +1642,24 @@ static void *unpack_sha1_rest(git_zstream *stream, void *buffer, unsigned long s\n  * too permissive for what we want to check. So do an anal\n  * object header parse by hand.\n  */\n-int parse_sha1_header(const char *hdr, unsigned long *sizep)\n+int parse_sha1_header_extended(const char *hdr, struct object_info *oi,\n+\t\t\t       unsigned int flags)\n {\n-\tchar type[10];\n-\tint i;\n+\tstruct strbuf typename = STRBUF_INIT;\n \tunsigned long size;\n+\tint type;\n \n \t/*\n \t * The type can be at most ten bytes (including the\n \t * terminating '\\0' that we add), and is followed by\n \t * a space.\n \t */\n-\ti = 0;\n \tfor (;;) {\n \t\tchar c = *hdr++;\n \t\tif (c == ' ')\n \t\t\tbreak;\n-\t\ttype[i++] = c;\n-\t\tif (i >= sizeof(type))\n-\t\t\treturn -1;\n+\t\tstrbuf_addch(&typename, c);\n \t}\n-\ttype[i] = 0;\n \n \t/*\n \t * The length must follow immediately, and be in canonical\n@@ -1652,12 +1677,39 @@ int parse_sha1_header(const char *hdr, unsigned long *sizep)\n \t\t\tsize = size * 10 + c;\n \t\t}\n \t}\n-\t*sizep = size;\n \n+\ttype = type_from_string_gently(typename.buf, typename.len, 1);\n+\tif (oi->sizep)\n+\t\t*oi->sizep = size;\n+\tif (oi->typename)\n+\t\tstrbuf_addbuf(oi->typename, &typename);\n+\tstrbuf_release(&typename);\n+\n+\t/*\n+\t * Set type to 0 if its an unknown object and\n+\t * we're obtaining the type using '--literally'\n+\t * option.\n+\t */\n+\tif ((flags & LOOKUP_LITERALLY) && (type == -1))\n+\t\ttype = 0;\n+\telse if (type == -1)\n+\t\tdie(\"invalid object type\");\n+\tif (oi->typep)\n+\t\t*oi->typep = type;\n \t/*\n \t * The length must be followed by a zero byte\n \t */\n-\treturn *hdr ? -1 : type_from_string(type);\n+\treturn *hdr ? -1 : type;\n+}\n+\n+int parse_sha1_header(const char *hdr, unsigned long *sizep)\n+{\n+\tstruct object_info oi;\n+\n+\toi.sizep = sizep;\n+\toi.typename = NULL;\n+\toi.typep = NULL;\n+\treturn parse_sha1_header_extended(hdr, &oi, LOOKUP_REPLACE_OBJECT);\n }\n \n static void *unpack_sha1_file(void *map, unsigned long mapsize, enum object_type *type, unsigned long *size, const unsigned char *sha1)\n@@ -2524,13 +2576,15 @@ struct packed_git *find_sha1_pack(const unsigned char *sha1,\n }\n \n static int sha1_loose_object_info(const unsigned char *sha1,\n-\t\t\t\t  struct object_info *oi)\n+\t\t\t\t  struct object_info *oi,\n+\t\t\t\t  int flags)\n {\n-\tint status;\n-\tunsigned long mapsize, size;\n+\tint status = 0;\n+\tunsigned long mapsize;\n \tvoid *map;\n \tgit_zstream stream;\n \tchar hdr[32];\n+\tstruct strbuf hdrbuf = STRBUF_INIT;\n \n \tif (oi->delta_base_sha1)\n \t\thashclr(oi->delta_base_sha1);\n@@ -2557,17 +2611,26 @@ static int sha1_loose_object_info(const unsigned char *sha1,\n \t\treturn -1;\n \tif (oi->disk_sizep)\n \t\t*oi->disk_sizep = mapsize;\n-\tif (unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr)) < 0)\n-\t\tstatus = error(\"unable to unpack %s header\",\n-\t\t\t       sha1_to_hex(sha1));\n-\telse if ((status = parse_sha1_header(hdr, &size)) < 0)\n-\t\tstatus = error(\"unable to parse %s header\", sha1_to_hex(sha1));\n-\telse if (oi->sizep)\n-\t\t*oi->sizep = size;\n+\tif ((flags & LOOKUP_LITERALLY)) {\n+\t\tif (unpack_sha1_header_to_strbuf(&stream, map, mapsize, &hdrbuf) < 0)\n+\t\t\tstatus = error(\"unable to unpack %s header with --literally\",\n+\t\t\t\t       sha1_to_hex(sha1));\n+\t\telse if ((status = parse_sha1_header_extended(hdrbuf.buf, oi, flags)) < 0)\n+\t\t\tstatus = error(\"unable to parse %s header with --literally\",\n+\t\t\t\t       sha1_to_hex(sha1));\n+\t} else {\n+\t\tif (unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr)) < 0)\n+\t\t\tstatus = error(\"unable to unpack %s header\",\n+\t\t\t\t       sha1_to_hex(sha1));\n+\t\telse if ((status = parse_sha1_header_extended(hdr, oi, flags)) < 0)\n+\t\t\tstatus = error(\"unable to parse %s header\", sha1_to_hex(sha1));\n+\t}\n \tgit_inflate_end(&stream);\n \tmunmap(map, mapsize);\n-\tif (oi->typep)\n+\tif (status && oi->typep)\n \t\t*oi->typep = status;\n+\tif (hdrbuf.buf)\n+\t\tstrbuf_release(&hdrbuf);\n \treturn 0;\n }\n \n@@ -2588,13 +2651,15 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,\n \t\t\t*(oi->disk_sizep) = 0;\n \t\tif (oi->delta_base_sha1)\n \t\t\thashclr(oi->delta_base_sha1);\n+\t\tif (oi->typename)\n+\t\t\tstrbuf_addstr(oi->typename, typename(co->type));\n \t\toi->whence = OI_CACHED;\n \t\treturn 0;\n \t}\n \n \tif (!find_pack_entry(real, &e)) {\n \t\t/* Most likely it's a loose object. */\n-\t\tif (!sha1_loose_object_info(real, oi)) {\n+\t\tif (!sha1_loose_object_info(real, oi, flags)) {\n \t\t\toi->whence = OI_LOOSE;\n \t\t\treturn 0;\n \t\t}\n@@ -2618,6 +2683,8 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,\n \t\toi->u.packed.is_delta = (rtype == OBJ_REF_DELTA ||\n \t\t\t\t\t rtype == OBJ_OFS_DELTA);\n \t}\n+\tif (oi->typename)\n+\t\tstrbuf_addstr(oi->typename, typename(rtype));\n \n \treturn 0;\n }\n-- \n2.3.1.172.g04a1281\n"},{"id":"258853","messageId":"1427972382-15477-1-git-send-email-karthik.188@gmail.com","threadId":"38976","inReplyTo":"551D1F99.5040306@gmail.com","subject":"[PATCH v6 2/4] cat-file: teach cat-file a '--literally' option","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-04-02T10:59:42Z","receivedAt":"2015-04-02T10:59:42Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Currently 'git cat-file' throws an error while trying to\nprint the type or size of a broken/corrupt object which is\ncreated using 'git hash-object --literally'. This is\nbecause these objects are usually of unknown types.\n\nTeach git cat-file a '--literally' option where it prints\nthe type or size of a broken/corrupt object without throwing\nan error.\n\nModify '-t' and '-s' options to call sha1_object_info_extended()\ndirectly to support the '--literally' option.\n\nHelped-by: Junio C Hamano <gitster@pobox.com>\nHelped-by: Eric Sunshine <sunshine@sunshineco\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n builtin/cat-file.c | 38 +++++++++++++++++++++++++++++---------\n 1 file changed, 29 insertions(+), 9 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex df99df4..91ceae0 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -9,13 +9,20 @@\n #include \"userdiff.h\"\n #include \"streaming.h\"\n \n-static int cat_one_file(int opt, const char *exp_type, const char *obj_name)\n+static int cat_one_file(int opt, const char *exp_type, const char *obj_name,\n+\t\t\tint literally)\n {\n \tunsigned char sha1[20];\n \tenum object_type type;\n \tchar *buf;\n \tunsigned long size;\n \tstruct object_context obj_context;\n+\tstruct object_info oi = {NULL};\n+\tstruct strbuf sb = STRBUF_INIT;\n+\tunsigned flags = LOOKUP_REPLACE_OBJECT;\n+\n+\tif (literally)\n+\t\tflags |= LOOKUP_LITERALLY;\n \n \tif (get_sha1_with_context(obj_name, 0, sha1, &obj_context))\n \t\tdie(\"Not a valid object name %s\", obj_name);\n@@ -23,16 +30,24 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name)\n \tbuf = NULL;\n \tswitch (opt) {\n \tcase 't':\n-\t\ttype = sha1_object_info(sha1, NULL);\n-\t\tif (type > 0) {\n-\t\t\tprintf(\"%s\\n\", typename(type));\n+\t\toi.typep = &type;\n+\t\toi.typename = &sb;\n+\t\tif (sha1_object_info_extended(sha1, &oi, flags) < 0)\n+\t\t\tdie(\"git cat-file: could not get object info\");\n+\t\tif (type >= 0 && sb.len) {\n+\t\t\tprintf(\"%s\\n\", sb.buf);\n+\t\t\tstrbuf_release(&sb);\n \t\t\treturn 0;\n \t\t}\n \t\tbreak;\n \n \tcase 's':\n-\t\ttype = sha1_object_info(sha1, &size);\n-\t\tif (type > 0) {\n+\t\toi.typep = &type;\n+\t\toi.typename = &sb;\n+\t\toi.sizep = &size;\n+\t\tif (sha1_object_info_extended(sha1, &oi, flags) < 0)\n+\t\t\tdie(\"git cat-file: could not get object info\");\n+\t\tif (type >= 0 && sb.len) {\n \t\t\tprintf(\"%lu\\n\", size);\n \t\t\treturn 0;\n \t\t}\n@@ -323,7 +338,7 @@ static int batch_objects(struct batch_options *opt)\n }\n \n static const char * const cat_file_usage[] = {\n-\tN_(\"git cat-file (-t | -s | -e | -p | <type> | --textconv) <object>\"),\n+\tN_(\"git cat-file (-t [--literally]|-s [--literally]|-e|-p|<type>|--textconv) <object>\"),\n \tN_(\"git cat-file (--batch | --batch-check) < <list-of-objects>\"),\n \tNULL\n };\n@@ -359,6 +374,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)\n \tint opt = 0;\n \tconst char *exp_type = NULL, *obj_name = NULL;\n \tstruct batch_options batch = {0};\n+\tint literally = 0;\n \n \tconst struct option options[] = {\n \t\tOPT_GROUP(N_(\"<type> can be one of: blob, tree, commit, tag\")),\n@@ -369,6 +385,8 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)\n \t\tOPT_SET_INT('p', NULL, &opt, N_(\"pretty-print object's content\"), 'p'),\n \t\tOPT_SET_INT(0, \"textconv\", &opt,\n \t\t\t    N_(\"for blob objects, run textconv on object's content\"), 'c'),\n+\t\tOPT_BOOL( 0, \"literally\", &literally,\n+\t\t\t  N_(\"get information about corrupt objects for debugging Git\")),\n \t\t{ OPTION_CALLBACK, 0, \"batch\", &batch, \"format\",\n \t\t\tN_(\"show info and content of objects fed from the standard input\"),\n \t\t\tPARSE_OPT_OPTARG, batch_option_callback },\n@@ -380,7 +398,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)\n \n \tgit_config(git_cat_file_config, NULL);\n \n-\tif (argc != 3 && argc != 2)\n+\tif (argc < 2 || argc > 4)\n \t\tusage_with_options(cat_file_usage, options);\n \n \targc = parse_options(argc, argv, prefix, options, cat_file_usage, 0);\n@@ -405,5 +423,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)\n \tif (batch.enabled)\n \t\treturn batch_objects(&batch);\n \n-\treturn cat_one_file(opt, exp_type, obj_name);\n+\tif (literally && opt != 't' && opt != 's')\n+\t\tdie(\"git cat-file --literally: use with -s or -t\");\n+\treturn cat_one_file(opt, exp_type, obj_name, literally);\n }\n-- \n2.3.1.172.g04a1281\n"},{"id":"258854","messageId":"1427972404-15565-1-git-send-email-karthik.188@gmail.com","threadId":"38976","inReplyTo":"551D1F99.5040306@gmail.com","subject":"[PATCH v6 3/4] cat-file: add documentation for '--literally' option.","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-04-02T11:00:04Z","receivedAt":"2015-04-02T11:00:04Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n Documentation/git-cat-file.txt | 6 +++++-\n 1 file changed, 5 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt\nindex f6a16f4..8bac7bd 100644\n--- a/Documentation/git-cat-file.txt\n+++ b/Documentation/git-cat-file.txt\n@@ -9,7 +9,7 @@ git-cat-file - Provide content or type and size information for repository objec\n SYNOPSIS\n --------\n [verse]\n-'git cat-file' (-t | -s | -e | -p | <type> | --textconv ) <object>\n+'git cat-file' (-t [--literally]| -s [--literally]| -e | -p | <type> | --textconv ) <object>\n 'git cat-file' (--batch | --batch-check) < <list-of-objects>\n \n DESCRIPTION\n@@ -69,6 +69,10 @@ OPTIONS\n \tnot be combined with any other options or arguments.  See the\n \tsection `BATCH OUTPUT` below for details.\n \n+--literally::\n+\tPrint information of broken/corrupt objects of unknown type without\n+\tthrowing an error. To be used combined with '-s' or '-t' option.\n+\n OUTPUT\n ------\n If '-t' is specified, one of the <type>.\n-- \n2.3.1.172.g04a1281\n"},{"id":"258855","messageId":"1427972435-15682-1-git-send-email-karthik.188@gmail.com","threadId":"38976","inReplyTo":"551D1F99.5040306@gmail.com","subject":"[PATCH v6 4/4] t1006: add tests for git cat-file --literally","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-04-02T11:00:35Z","receivedAt":"2015-04-02T11:00:35Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n t/t1006-cat-file.sh | 27 +++++++++++++++++++++++++++\n 1 file changed, 27 insertions(+)\n\ndiff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh\nindex a72e700..3015062 100755\n--- a/t/t1006-cat-file.sh\n+++ b/t/t1006-cat-file.sh\n@@ -47,6 +47,18 @@ $content\"\n \ttest_cmp expect actual\n     '\n \n+    test_expect_success \"Type of $type is correct using --literally\" '\n+\techo $type >expect &&\n+\tgit cat-file -t --literally $sha1 >actual &&\n+\ttest_cmp expect actual\n+    '\n+\n+    test_expect_success \"Size of $type is correct using --literally\" '\n+\techo $size >expect &&\n+\tgit cat-file -s --literally $sha1 >actual &&\n+\ttest_cmp expect actual\n+    '\n+\n     test -z \"$content\" ||\n     test_expect_success \"Content of $type is correct\" '\n \tmaybe_remove_timestamp \"$content\" $no_ts >expect &&\n@@ -296,4 +308,19 @@ test_expect_success '%(deltabase) reports packed delta bases' '\n \t}\n '\n \n+bogus_type=\"bogus\"\n+bogus_sha1=$(git hash-object -t $bogus_type --literally -w --stdin </dev/null)\n+\n+test_expect_success \"Type of broken object is correct\" '\n+\techo $bogus_type >expect &&\n+\tgit cat-file -t --literally $bogus_sha1 >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success \"Size of broken object is correct\" '\n+\techo \"0\" >expect &&\n+\tgit cat-file -s --literally $bogus_sha1 >actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\n-- \n2.3.1.172.g04a1281\n"},{"id":"258874","messageId":"xmqqd23mjqkm.fsf@gitster.dls.corp.google.com","threadId":"38976","inReplyTo":"1427972382-15477-1-git-send-email-karthik.188@gmail.com","subject":"Re: [PATCH v6 2/4] cat-file: teach cat-file a '--literally' option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-04-02T19:08:41Z","receivedAt":"2015-04-02T19:08:41Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n> Currently 'git cat-file' throws an error while trying to\n> print the type or size of a broken/corrupt object which is\n> created using 'git hash-object --literally'. This is\n> because these objects are usually of unknown types.\n>\n> Teach git cat-file a '--literally' option where it prints\n> the type or size of a broken/corrupt object without throwing\n> an error.\n>\n> Modify '-t' and '-s' options to call sha1_object_info_extended()\n> directly to support the '--literally' option.\n>\n> Helped-by: Junio C Hamano <gitster@pobox.com>\n> Helped-by: Eric Sunshine <sunshine@sunshineco\n\ns/$/.com/ perhaps?\n\n> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n> ---\n>  builtin/cat-file.c | 38 +++++++++++++++++++++++++++++---------\n>  1 file changed, 29 insertions(+), 9 deletions(-)\n>\n> diff --git a/builtin/cat-file.c b/builtin/cat-file.c\n> index df99df4..91ceae0 100644\n> --- a/builtin/cat-file.c\n> +++ b/builtin/cat-file.c\n> @@ -9,13 +9,20 @@\n>  #include \"userdiff.h\"\n>  #include \"streaming.h\"\n>  \n> -static int cat_one_file(int opt, const char *exp_type, const char *obj_name)\n> +static int cat_one_file(int opt, const char *exp_type, const char *obj_name,\n> +\t\t\tint literally)\n>  {\n>  \tunsigned char sha1[20];\n>  \tenum object_type type;\n>  \tchar *buf;\n>  \tunsigned long size;\n>  \tstruct object_context obj_context;\n> +\tstruct object_info oi = {NULL};\n> +\tstruct strbuf sb = STRBUF_INIT;\n> +\tunsigned flags = LOOKUP_REPLACE_OBJECT;\n> +\n> +\tif (literally)\n> +\t\tflags |= LOOKUP_LITERALLY;\n>  \n>  \tif (get_sha1_with_context(obj_name, 0, sha1, &obj_context))\n>  \t\tdie(\"Not a valid object name %s\", obj_name);\n> @@ -23,16 +30,24 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name)\n>  \tbuf = NULL;\n>  \tswitch (opt) {\n>  \tcase 't':\n> -\t\ttype = sha1_object_info(sha1, NULL);\n> -\t\tif (type > 0) {\n> -\t\t\tprintf(\"%s\\n\", typename(type));\n> +\t\toi.typep = &type;\n> +\t\toi.typename = &sb;\n> +\t\tif (sha1_object_info_extended(sha1, &oi, flags) < 0)\n> +\t\t\tdie(\"git cat-file: could not get object info\");\n> +\t\tif (type >= 0 && sb.len) {\n> +\t\t\tprintf(\"%s\\n\", sb.buf);\n> +\t\t\tstrbuf_release(&sb);\n>  \t\t\treturn 0;\n>  \t\t}\n>  \t\tbreak;\n>  \n>  \tcase 's':\n> -\t\ttype = sha1_object_info(sha1, &size);\n> -\t\tif (type > 0) {\n> +\t\toi.typep = &type;\n> +\t\toi.typename = &sb;\n> +\t\toi.sizep = &size;\n> +\t\tif (sha1_object_info_extended(sha1, &oi, flags) < 0)\n> +\t\t\tdie(\"git cat-file: could not get object info\");\n> +\t\tif (type >= 0 && sb.len) {\n>  \t\t\tprintf(\"%lu\\n\", size);\n>  \t\t\treturn 0;\n>  \t\t}\n> @@ -323,7 +338,7 @@ static int batch_objects(struct batch_options *opt)\n>  }\n>  \n>  static const char * const cat_file_usage[] = {\n> -\tN_(\"git cat-file (-t | -s | -e | -p | <type> | --textconv) <object>\"),\n> +\tN_(\"git cat-file (-t [--literally]|-s [--literally]|-e|-p|<type>|--textconv) <object>\"),\n>  \tN_(\"git cat-file (--batch | --batch-check) < <list-of-objects>\"),\n>  \tNULL\n>  };\n> @@ -359,6 +374,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)\n>  \tint opt = 0;\n>  \tconst char *exp_type = NULL, *obj_name = NULL;\n>  \tstruct batch_options batch = {0};\n> +\tint literally = 0;\n>  \n>  \tconst struct option options[] = {\n>  \t\tOPT_GROUP(N_(\"<type> can be one of: blob, tree, commit, tag\")),\n> @@ -369,6 +385,8 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)\n>  \t\tOPT_SET_INT('p', NULL, &opt, N_(\"pretty-print object's content\"), 'p'),\n>  \t\tOPT_SET_INT(0, \"textconv\", &opt,\n>  \t\t\t    N_(\"for blob objects, run textconv on object's content\"), 'c'),\n> +\t\tOPT_BOOL( 0, \"literally\", &literally,\n> +\t\t\t  N_(\"get information about corrupt objects for debugging Git\")),\n>  \t\t{ OPTION_CALLBACK, 0, \"batch\", &batch, \"format\",\n>  \t\t\tN_(\"show info and content of objects fed from the standard input\"),\n>  \t\t\tPARSE_OPT_OPTARG, batch_option_callback },\n> @@ -380,7 +398,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)\n>  \n>  \tgit_config(git_cat_file_config, NULL);\n>  \n> -\tif (argc != 3 && argc != 2)\n> +\tif (argc < 2 || argc > 4)\n>  \t\tusage_with_options(cat_file_usage, options);\n>  \n>  \targc = parse_options(argc, argv, prefix, options, cat_file_usage, 0);\n> @@ -405,5 +423,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)\n>  \tif (batch.enabled)\n>  \t\treturn batch_objects(&batch);\n>  \n> -\treturn cat_one_file(opt, exp_type, obj_name);\n> +\tif (literally && opt != 't' && opt != 's')\n> +\t\tdie(\"git cat-file --literally: use with -s or -t\");\n> +\treturn cat_one_file(opt, exp_type, obj_name, literally);\n>  }\n"},{"id":"258875","messageId":"xmqqbnj6jqe5.fsf@gitster.dls.corp.google.com","threadId":"38976","inReplyTo":"1427972288-15298-1-git-send-email-karthik.188@gmail.com","subject":"Re: [PATCH v6 1/4] sha1_file.c: support reading from a loose object of unknown type","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-04-02T19:12:34Z","receivedAt":"2015-04-02T19:12:34Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n> +static int unpack_sha1_header_to_strbuf(git_zstream *stream, unsigned char *map,\n> +\t\t\t\t\tunsigned long mapsize,\n> +\t\t\t\t\tstruct strbuf *header)\n> +{\n> +\tunsigned char buffer[32], *cp;\n> +\tunsigned long bufsiz = sizeof(buffer);\n> +\tint status;\n> +\n> +\tstatus = unpack_sha1_header(stream, map, mapsize, buffer, bufsiz);\n\nI briefly wondered if this can return Z_BUF_ERROR, but it is OK\nbecause we do not call inflate with Z_FINISH in unpack_sha1_header()\nfor obvious reasons ;-)\n\n> +\tif (status) {\n> +\t\tstrbuf_add(header, buffer, stream->next_out - buffer);\n> +\t\treturn status;\n> +\t}\n\n> +\tdo {\n> +\t\tstatus = git_inflate(stream, 0);\n> +\t\tstrbuf_add(header, buffer, stream->next_out - buffer);\n> +\t\tfor (cp = buffer; cp < stream->next_out; cp++)\n> +\t\t\tif (!*cp)\n> +\t\t\t\t/* Found the NUL at the end of the header */\n> +\t\t\t\treturn 0;\n> +\t\tstream->next_out = buffer;\n> +\t\tstream->avail_out = bufsiz;\n> +\t} while (status != Z_STREAM_END);\n> +\treturn -1;\n> +}\n\nOK.\n\n> @@ -1614,27 +1642,24 @@ static void *unpack_sha1_rest(git_zstream *stream, void *buffer, unsigned long s\n>   * too permissive for what we want to check. So do an anal\n>   * object header parse by hand.\n>   */\n> -int parse_sha1_header(const char *hdr, unsigned long *sizep)\n> +int parse_sha1_header_extended(const char *hdr, struct object_info *oi,\n> +\t\t\t       unsigned int flags)\n>  {\n> -\tchar type[10];\n> -\tint i;\n> +\tstruct strbuf typename = STRBUF_INIT;\n>  \tunsigned long size;\n> +\tint type;\n>  \n>  \t/*\n>  \t * The type can be at most ten bytes (including the\n\nIs this still a valid comment?\n\n>  \t * terminating '\\0' that we add), and is followed by\n>  \t * a space.\n>  \t */\n> -\ti = 0;\n>  \tfor (;;) {\n>  \t\tchar c = *hdr++;\n>  \t\tif (c == ' ')\n>  \t\t\tbreak;\n> -\t\ttype[i++] = c;\n> -\t\tif (i >= sizeof(type))\n> -\t\t\treturn -1;\n> +\t\tstrbuf_addch(&typename, c);\n>  \t}\n> -\ttype[i] = 0;\n>  \n>  \t/*\n>  \t * The length must follow immediately, and be in canonical\n"},{"id":"258890","messageId":"xmqq384ijmj7.fsf@gitster.dls.corp.google.com","threadId":"38976","inReplyTo":"551D1F99.5040306@gmail.com","subject":"Re: [PATCH v6 0/4] cat-file: add a '--literally' option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-04-02T20:35:56Z","receivedAt":"2015-04-02T20:35:56Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"When merged to 'pu', this seems to break at least 5309 and 5300\ntests (there might be others, but I didn't check).\n"},{"id":"258930","messageId":"551EBF0B.3060401@gmail.com","threadId":"38976","inReplyTo":"xmqqd23mjqkm.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH v6 2/4] cat-file: teach cat-file a '--literally' option","fromName":"karthik nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-04-03T16:25:47Z","receivedAt":"2015-04-03T16:25:47Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"\n\nOn 04/03/2015 12:38 AM, Junio C Hamano wrote:\n> Karthik Nayak <karthik.188@gmail.com> writes:\n>\n>> Currently 'git cat-file' throws an error while trying to\n>> print the type or size of a broken/corrupt object which is\n>> created using 'git hash-object --literally'. This is\n>> because these objects are usually of unknown types.\n>>\n>> Teach git cat-file a '--literally' option where it prints\n>> the type or size of a broken/corrupt object without throwing\n>> an error.\n>>\n>> Modify '-t' and '-s' options to call sha1_object_info_extended()\n>> directly to support the '--literally' option.\n>>\n>> Helped-by: Junio C Hamano <gitster@pobox.com>\n>> Helped-by: Eric Sunshine <sunshine@sunshineco\n>\n> s/$/.com/ perhaps?\nDefinitely!\n>\n>> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n>> ---\n>>   builtin/cat-file.c | 38 +++++++++++++++++++++++++++++---------\n>>   1 file changed, 29 insertions(+), 9 deletions(-)\n>>\n>> diff --git a/builtin/cat-file.c b/builtin/cat-file.c\n>> index df99df4..91ceae0 100644\n>> --- a/builtin/cat-file.c\n>> +++ b/builtin/cat-file.c\n>> @@ -9,13 +9,20 @@\n>>   #include \"userdiff.h\"\n>>   #include \"streaming.h\"\n>>\n>> -static int cat_one_file(int opt, const char *exp_type, const char *obj_name)\n>> +static int cat_one_file(int opt, const char *exp_type, const char *obj_name,\n>> +\t\t\tint literally)\n>>   {\n>>   \tunsigned char sha1[20];\n>>   \tenum object_type type;\n>>   \tchar *buf;\n>>   \tunsigned long size;\n>>   \tstruct object_context obj_context;\n>> +\tstruct object_info oi = {NULL};\n>> +\tstruct strbuf sb = STRBUF_INIT;\n>> +\tunsigned flags = LOOKUP_REPLACE_OBJECT;\n>> +\n>> +\tif (literally)\n>> +\t\tflags |= LOOKUP_LITERALLY;\n>>\n>>   \tif (get_sha1_with_context(obj_name, 0, sha1, &obj_context))\n>>   \t\tdie(\"Not a valid object name %s\", obj_name);\n>> @@ -23,16 +30,24 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name)\n>>   \tbuf = NULL;\n>>   \tswitch (opt) {\n>>   \tcase 't':\n>> -\t\ttype = sha1_object_info(sha1, NULL);\n>> -\t\tif (type > 0) {\n>> -\t\t\tprintf(\"%s\\n\", typename(type));\n>> +\t\toi.typep = &type;\n>> +\t\toi.typename = &sb;\n>> +\t\tif (sha1_object_info_extended(sha1, &oi, flags) < 0)\n>> +\t\t\tdie(\"git cat-file: could not get object info\");\n>> +\t\tif (type >= 0 && sb.len) {\n>> +\t\t\tprintf(\"%s\\n\", sb.buf);\n>> +\t\t\tstrbuf_release(&sb);\n>>   \t\t\treturn 0;\n>>   \t\t}\n>>   \t\tbreak;\n>>\n>>   \tcase 's':\n>> -\t\ttype = sha1_object_info(sha1, &size);\n>> -\t\tif (type > 0) {\n>> +\t\toi.typep = &type;\n>> +\t\toi.typename = &sb;\n>> +\t\toi.sizep = &size;\n>> +\t\tif (sha1_object_info_extended(sha1, &oi, flags) < 0)\n>> +\t\t\tdie(\"git cat-file: could not get object info\");\n>> +\t\tif (type >= 0 && sb.len) {\n>>   \t\t\tprintf(\"%lu\\n\", size);\n>>   \t\t\treturn 0;\n>>   \t\t}\n>> @@ -323,7 +338,7 @@ static int batch_objects(struct batch_options *opt)\n>>   }\n>>\n>>   static const char * const cat_file_usage[] = {\n>> -\tN_(\"git cat-file (-t | -s | -e | -p | <type> | --textconv) <object>\"),\n>> +\tN_(\"git cat-file (-t [--literally]|-s [--literally]|-e|-p|<type>|--textconv) <object>\"),\n>>   \tN_(\"git cat-file (--batch | --batch-check) < <list-of-objects>\"),\n>>   \tNULL\n>>   };\n>> @@ -359,6 +374,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)\n>>   \tint opt = 0;\n>>   \tconst char *exp_type = NULL, *obj_name = NULL;\n>>   \tstruct batch_options batch = {0};\n>> +\tint literally = 0;\n>>\n>>   \tconst struct option options[] = {\n>>   \t\tOPT_GROUP(N_(\"<type> can be one of: blob, tree, commit, tag\")),\n>> @@ -369,6 +385,8 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)\n>>   \t\tOPT_SET_INT('p', NULL, &opt, N_(\"pretty-print object's content\"), 'p'),\n>>   \t\tOPT_SET_INT(0, \"textconv\", &opt,\n>>   \t\t\t    N_(\"for blob objects, run textconv on object's content\"), 'c'),\n>> +\t\tOPT_BOOL( 0, \"literally\", &literally,\n>> +\t\t\t  N_(\"get information about corrupt objects for debugging Git\")),\n>>   \t\t{ OPTION_CALLBACK, 0, \"batch\", &batch, \"format\",\n>>   \t\t\tN_(\"show info and content of objects fed from the standard input\"),\n>>   \t\t\tPARSE_OPT_OPTARG, batch_option_callback },\n>> @@ -380,7 +398,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)\n>>\n>>   \tgit_config(git_cat_file_config, NULL);\n>>\n>> -\tif (argc != 3 && argc != 2)\n>> +\tif (argc < 2 || argc > 4)\n>>   \t\tusage_with_options(cat_file_usage, options);\n>>\n>>   \targc = parse_options(argc, argv, prefix, options, cat_file_usage, 0);\n>> @@ -405,5 +423,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)\n>>   \tif (batch.enabled)\n>>   \t\treturn batch_objects(&batch);\n>>\n>> -\treturn cat_one_file(opt, exp_type, obj_name);\n>> +\tif (literally && opt != 't' && opt != 's')\n>> +\t\tdie(\"git cat-file --literally: use with -s or -t\");\n>> +\treturn cat_one_file(opt, exp_type, obj_name, literally);\n>>   }\n"},{"id":"258976","messageId":"551F64CC.2030208@gmail.com","threadId":"38976","inReplyTo":"xmqq384ijmj7.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH v6 0/4] cat-file: add a '--literally' option","fromName":"karthik nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-04-04T04:13:00Z","receivedAt":"2015-04-04T04:13:00Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"\n\nOn 04/03/2015 02:05 AM, Junio C Hamano wrote:\n> When merged to 'pu', this seems to break at least 5309 and 5300\n> tests (there might be others, but I didn't check).\n>\n\nThere was a problem with packed object types. I have it fixed, will send \na re-roll.\n"}]}