{"thread":{"id":"38686","subject":"[PATCH v2 0/3] cat-file: add \"--literally\" option","startedAt":"2015-03-03T10:10:19Z","lastAt":"2015-03-05T06:25:10Z","messageCount":7,"participants":["karthik nayak","Karthik Nayak","Junio C Hamano"],"isPatch":true,"patchVersion":2,"patchTotal":3},"messages":[{"id":"256884","messageId":"54F5888B.7040400@gmail.com","threadId":"38686","inReplyTo":null,"subject":"[PATCH v2 0/3] cat-file: add \"--literally\" option","fromName":"karthik nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-03-03T10:10:19Z","receivedAt":"2015-03-03T10:10:19Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Second version of the patch submitted to add \"-literlly\" option\nto \"cat-file\"\nhttp://article.gmane.org/gmane.comp.version-control.git/264383\n\nThanks to Eric, Junio and David for suggesting changes on my\nfirst version.\n"},{"id":"256885","messageId":"1425377514-25272-1-git-send-email-karthik.188@gmail.com","threadId":"38686","inReplyTo":"54F5888B.7040400@gmail.com","subject":"[PATCH v2 1/3] cache: modify for \"cat-file --literally -t\"","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-03-03T10:11:54Z","receivedAt":"2015-03-03T10:11:54Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Add a \"struct strbuf *typename\" to object_info to hold the\ntypename when the literally option is used. Add a flag to\nnotify functions when literally is used.\n\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n cache.h | 2 ++\n 1 file changed, 2 insertions(+)\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 {\n-- \n2.3.1.169.ga243085.dirty\n"},{"id":"256886","messageId":"1425377556-25332-1-git-send-email-karthik.188@gmail.com","threadId":"38686","inReplyTo":"54F5888B.7040400@gmail.com","subject":"[PATCH v2 2/3] sha1_file: implement changes for \"cat-file --literally -t\"","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-03-03T10:12:36Z","receivedAt":"2015-03-03T10:12:36Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"add \"sha1_object_info_literally()\" which is to be used when\nthe \"literally\" option is given to get the type of object\nand print it, using \"sha1_object_info_extended()\".\n\nadd \"unpack_sha1_header_literally()\" to unpack sha headers\nwhich may be greater than 32 bytes, which is the threshold\nfor a regular object header.\n\nmodify \"sha1_loose_object_info()\" to include a flag argument\nand also include changes to call \"unpack_sha1_header_literally()\"\nwhen the literally flag is passed. Also copies the obtained\ntype to the typename field of object_info.\n\nmodify \"sha1_object_info_extended()\" to call the function\n\"sha1_loose_object_info()\" with flags.\n\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n sha1_file.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------\n 1 file changed, 77 insertions(+), 7 deletions(-)\n\ndiff --git a/sha1_file.c b/sha1_file.c\nindex 69a60ec..1068ca0 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -1564,6 +1564,36 @@ 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_literally(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+\t/* Get the data stream */\n+\tmemset(stream, 0, sizeof(*stream));\n+\tstream->next_in = map;\n+\tstream->avail_in = mapsize;\n+\tstream->next_out = buffer;\n+\tstream->avail_out = bufsiz;\n+\n+\tgit_inflate_init(stream);\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_OK);\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@@ -2524,13 +2554,16 @@ 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+\tint status = 0;\n \tunsigned long mapsize, size;\n \tvoid *map;\n \tgit_zstream stream;\n \tchar hdr[32];\n+\tstruct strbuf hdrbuf = STRBUF_INIT;\n+\tchar *hdrp;\n \n \tif (oi->delta_base_sha1)\n \t\thashclr(oi->delta_base_sha1);\n@@ -2557,10 +2590,25 @@ 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+\tif ((flags & LOOKUP_LITERALLY)) {\n+\t\tif (unpack_sha1_header_literally(&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\thdrp = hdrbuf.buf;\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\t}\n+\t\thdrp = hdr;\n+\t}\n+\tif (status)\n+\t\t; /* We're already checking for errors */\n+\telse if ((flags & LOOKUP_LITERALLY)) {\n+\t\tsize_t typelen = strcspn(hdrbuf.buf, \" \");\n+\t\tstrbuf_add(oi->typename, hdrbuf.buf, typelen);\n+\t}\n+\telse if ((status = parse_sha1_header(hdrp, &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@@ -2568,6 +2616,10 @@ static int sha1_loose_object_info(const unsigned char *sha1,\n \tmunmap(map, mapsize);\n \tif (oi->typep)\n \t\t*oi->typep = status;\n+\tif (oi->typename && 0 <= status && typename(status))\n+\t\tstrbuf_addstr(oi->typename, typename(status));\n+\tif (hdrp == hdrbuf.buf)\n+\t\tstrbuf_release(&hdrbuf);\n \treturn 0;\n }\n \n@@ -2594,7 +2646,7 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,\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@@ -2635,6 +2687,24 @@ int sha1_object_info(const unsigned char *sha1, unsigned long *sizep)\n \treturn type;\n }\n \n+int sha1_object_info_literally(const unsigned char *sha1)\n+{\n+\tenum object_type type;\n+\tstruct strbuf sb = STRBUF_INIT;\n+\tstruct object_info oi = {NULL};\n+\n+\toi.typename = &sb;\n+\toi.typep = &type;\n+\tif (sha1_object_info_extended(sha1, &oi, LOOKUP_LITERALLY) < 0)\n+\t\treturn -1;\n+\tif (*oi.typep > 0)\n+\t\tprintf(\"%s\\n\", typename(*oi.typep));\n+\telse\n+\t\tprintf(\"%s\\n\", oi.typename->buf);\n+\tstrbuf_release(oi.typename);\n+\treturn 0;\n+}\n+\n static void *read_packed_sha1(const unsigned char *sha1,\n \t\t\t      enum object_type *type, unsigned long *size)\n {\n-- \n2.3.1.169.ga243085.dirty\n"},{"id":"256887","messageId":"1425377582-25388-1-git-send-email-karthik.188@gmail.com","threadId":"38686","inReplyTo":"54F5888B.7040400@gmail.com","subject":"[PATCH v2 3/3] cat-file: add \"--literally\" option","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-03-03T10:13:02Z","receivedAt":"2015-03-03T10:13:02Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"made changes to \"cat-file\" to include a \"--literally\"\noption which prints the type of the object without any\ncomplaints.\n\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n builtin/cat-file.c | 19 +++++++++++++++----\n 1 file changed, 15 insertions(+), 4 deletions(-)\n\ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex df99df4..2af9f40 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -9,7 +9,8 @@\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@@ -23,6 +24,8 @@ 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\tif (literally)\n+\t\t\treturn sha1_object_info_literally(sha1);\n \t\ttype = sha1_object_info(sha1, NULL);\n \t\tif (type > 0) {\n \t\t\tprintf(\"%s\\n\", typename(type));\n@@ -323,7 +326,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|-s|-e|-p|<type>|--textconv|-t --literally) <object>\"),\n \tN_(\"git cat-file (--batch | --batch-check) < <list-of-objects>\"),\n \tNULL\n };\n@@ -359,6 +362,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 +373,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_(\"show the type of the given loose object, use for debugging\")),\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 +386,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 != 3 && 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 +411,10 @@ 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')\n+\t\treturn cat_one_file(opt, exp_type, obj_name, literally);\n+\telse if (literally)\n+\t\tusage_with_options(cat_file_usage, options);\n+\n+\treturn cat_one_file(opt, exp_type, obj_name, literally);\n }\n-- \n2.3.1.169.ga243085.dirty\n"},{"id":"257017","messageId":"xmqqy4nc7a4w.fsf@gitster.dls.corp.google.com","threadId":"38686","inReplyTo":"1425377556-25332-1-git-send-email-karthik.188@gmail.com","subject":"Re: [PATCH v2 2/3] sha1_file: implement changes for \"cat-file --literally -t\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-03-04T20:58:23Z","receivedAt":"2015-03-04T20:58:23Z","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> add \"sha1_object_info_literally()\" which is to be used when\n> the \"literally\" option is given to get the type of object\n> and print it, using \"sha1_object_info_extended()\".\n>\n> add \"unpack_sha1_header_literally()\" to unpack sha headers\n> which may be greater than 32 bytes, which is the threshold\n> for a regular object header.\n>\n> modify \"sha1_loose_object_info()\" to include a flag argument\n> and also include changes to call \"unpack_sha1_header_literally()\"\n> when the literally flag is passed. Also copies the obtained\n> type to the typename field of object_info.\n>\n> modify \"sha1_object_info_extended()\" to call the function\n> \"sha1_loose_object_info()\" with flags.\n>\n> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n> ---\n>  sha1_file.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------\n>  1 file changed, 77 insertions(+), 7 deletions(-)\n>\n> diff --git a/sha1_file.c b/sha1_file.c\n> index 69a60ec..1068ca0 100644\n> --- a/sha1_file.c\n> +++ b/sha1_file.c\n> @@ -1564,6 +1564,36 @@ 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_literally(git_zstream *stream, unsigned char *map,\n> +\t\t\t\t\tunsigned long mapsize,\n> +\t\t\t\t\tstruct strbuf *header)\n> +{\n> +...\n> +}\n\nLooks suspiciously familiar...\n\n> +int sha1_object_info_literally(const unsigned char *sha1)\n> +{\n> +\tenum object_type type;\n> +\tstruct strbuf sb = STRBUF_INIT;\n> +\tstruct object_info oi = {NULL};\n> +\n> +\toi.typename = &sb;\n> +\toi.typep = &type;\n> +\tif (sha1_object_info_extended(sha1, &oi, LOOKUP_LITERALLY) < 0)\n> +\t\treturn -1;\n> +\tif (*oi.typep > 0)\n> +\t\tprintf(\"%s\\n\", typename(*oi.typep));\n> +\telse\n> +\t\tprintf(\"%s\\n\", oi.typename->buf);\n> +\tstrbuf_release(oi.typename);\n> +\treturn 0;\n> +}\n> +\n\nNAK.\n\nPlease don't add end-user facing final output to sha1_file.c;\ninstead have the caller use a helper function like this one to\nextract necessary information and perform the end-user interaction\nthere.\n"},{"id":"257047","messageId":"54F7B0CE.4070006@gmail.com","threadId":"38686","inReplyTo":"xmqqy4nc7a4w.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH v2 2/3] sha1_file: implement changes for \"cat-file --literally -t\"","fromName":"karthik nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2015-03-05T01:26:38Z","receivedAt":"2015-03-05T01:26:38Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"\nOn 03/05/2015 02:28 AM, Junio C Hamano wrote:\n> Karthik Nayak <karthik.188@gmail.com> writes:\n>\n> > add \"sha1_object_info_literally()\" which is to be used when\n> > the \"literally\" option is given to get the type of object\n> > and print it, using \"sha1_object_info_extended()\".\n> >\n> > add \"unpack_sha1_header_literally()\" to unpack sha headers\n> > which may be greater than 32 bytes, which is the threshold\n> > for a regular object header.\n> >\n> > modify \"sha1_loose_object_info()\" to include a flag argument\n> > and also include changes to call \"unpack_sha1_header_literally()\"\n> > when the literally flag is passed. Also copies the obtained\n> > type to the typename field of object_info.\n> >\n> > modify \"sha1_object_info_extended()\" to call the function\n> > \"sha1_loose_object_info()\" with flags.\n> >\n> > Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n> > ---\n> >   sha1_file.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------\n> >   1 file changed, 77 insertions(+), 7 deletions(-)\n> >\n> > diff --git a/sha1_file.c b/sha1_file.c\n> > index 69a60ec..1068ca0 100644\n> > --- a/sha1_file.c\n> > +++ b/sha1_file.c\n> > @@ -1564,6 +1564,36 @@ int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long ma\n> >       return git_inflate(stream, 0);\n> >   }\n> >\n> > +static int unpack_sha1_header_literally(git_zstream *stream, unsigned char *map,\n> > +                    unsigned long mapsize,\n> > +                    struct strbuf *header)\n> > +{\n> > +...\n> > +}\n>\n> Looks suspiciously familiar...\nYes, you suggested it.\nIt has a similar structure to unpack_sha1_header().\nAnything wrong with it?\n>\n> > +int sha1_object_info_literally(const unsigned char *sha1)\n> > +{\n> > +    enum object_type type;\n> > +    struct strbuf sb = STRBUF_INIT;\n> > +    struct object_info oi = {NULL};\n> > +\n> > +    oi.typename = &sb;\n> > +    oi.typep = &type;\n> > +    if (sha1_object_info_extended(sha1, &oi, LOOKUP_LITERALLY) < 0)\n> > +        return -1;\n> > +    if (*oi.typep > 0)\n> > +        printf(\"%s\\n\", typename(*oi.typep));\n> > +    else\n> > +        printf(\"%s\\n\", oi.typename->buf);\n> > +    strbuf_release(oi.typename);\n> > +    return 0;\n> > +}\n> > +\n>\n> NAK.\n>\n> Please don't add end-user facing final output to sha1_file.c;\n> instead have the caller use a helper function like this one to\n> extract necessary information and perform the end-user interaction\n> there.\n>\nOk, will do that.\n"},{"id":"257057","messageId":"xmqqoao83qrd.fsf@gitster.dls.corp.google.com","threadId":"38686","inReplyTo":"54F7B0CE.4070006@gmail.com","subject":"Re: [PATCH v2 2/3] sha1_file: implement changes for \"cat-file --literally -t\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-03-05T06:25:10Z","receivedAt":"2015-03-05T06:25:10Z","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>> Looks suspiciously familiar...\n> Yes, you suggested it.\n> It has a similar structure to unpack_sha1_header().\n> Anything wrong with it?\n\nI don't know if there is something wrong with the code, or not, but\nit wasn't mentioned in the log message at all that it is not your\ncode, and I was mostly reacting to that.\n\nIt is fairly common around here to take somebody else's code and run\nwith it, but people say things like \"This is based on suggestion\nfrom X\", \"This function was stolen from Y\", etc. and then conclude\nwith \"but I adjusted it to match the caller I wrote, so bugs are\nmine.\" when they do so.\n"}]}