{"thread":{"id":"6978","subject":"[PATCH 1/6] sha1_file.c: cleanup hdr usage","startedAt":"2007-02-26T19:55:54Z","lastAt":"2007-02-27T17:26:39Z","messageCount":16,"participants":["Nicolas Pitre","Junio C Hamano","Linus Torvalds","Shawn O. Pearce"],"isPatch":true,"patchVersion":1,"patchTotal":6},"messages":[{"id":"35533","messageId":"11725197603476-git-send-email-nico@cam.org","threadId":"6978","inReplyTo":null,"subject":"various cleanups","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2007-02-26T19:55:54Z","receivedAt":"2007-02-26T19:55:54Z","isPatch":false,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"Here's a bunch of cleanups I've accumulated.  I attempted to work on some\npack optimizations last weekend but some other things in the code kept\nbothering me.  So here is what I have so far.\n\nNicolas\n"},{"id":"35532","messageId":"1172519760216-git-send-email-nico@cam.org","threadId":"6978","inReplyTo":"11725197603476-git-send-email-nico@cam.org","subject":"[PATCH 1/6] sha1_file.c: cleanup hdr usage","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2007-02-26T19:55:55Z","receivedAt":"2007-02-26T19:55:55Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"Let's have hdr be a simple char pointer/array when possible, and let's\nreduce its storage to 32 bytes.  Especially for sha1_loose_object_info()\nwhere 128 bytes is way excessive and wastes extra CPU cycles inflating.\n\nThe object type is already restricted to 10 bytes in parse_sha1_header()\nand the size, even if it is 64 bits, will fit in 20 decimal numbers.  So\n32 bytes is plenty.\n\nSigned-off-by: Nicolas Pitre <nico@cam.org>\n---\n sha1_file.c |   24 ++++++++++++------------\n 1 files changed, 12 insertions(+), 12 deletions(-)\n\ndiff --git a/sha1_file.c b/sha1_file.c\nindex 9a1dee0..57a9b53 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -1461,7 +1461,7 @@ static int sha1_loose_object_info(const unsigned char *sha1, char *type, unsigne\n \tunsigned long mapsize, size;\n \tvoid *map;\n \tz_stream stream;\n-\tchar hdr[128];\n+\tchar hdr[32];\n \n \tmap = map_sha1_file(sha1, &mapsize);\n \tif (!map)\n@@ -1628,12 +1628,12 @@ void *read_object_with_reference(const unsigned char *sha1,\n \n static void write_sha1_file_prepare(void *buf, unsigned long len,\n                                     const char *type, unsigned char *sha1,\n-                                    unsigned char *hdr, int *hdrlen)\n+                                    char *hdr, int *hdrlen)\n {\n \tSHA_CTX c;\n \n \t/* Generate the header */\n-\t*hdrlen = sprintf((char *)hdr, \"%s %lu\", type, len)+1;\n+\t*hdrlen = sprintf(hdr, \"%s %lu\", type, len)+1;\n \n \t/* Sha1.. */\n \tSHA1_Init(&c);\n@@ -1740,7 +1740,7 @@ static int write_binary_header(unsigned char *hdr, enum object_type type, unsign\n \n static void setup_object_header(z_stream *stream, const char *type, unsigned long len)\n {\n-\tint obj_type, hdr;\n+\tint obj_type, hdrlen;\n \n \tif (use_legacy_headers) {\n \t\twhile (deflate(stream, 0) == Z_OK)\n@@ -1757,16 +1757,16 @@ static void setup_object_header(z_stream *stream, const char *type, unsigned lon\n \t\tobj_type = OBJ_TAG;\n \telse\n \t\tdie(\"trying to generate bogus object of type '%s'\", type);\n-\thdr = write_binary_header(stream->next_out, obj_type, len);\n-\tstream->total_out = hdr;\n-\tstream->next_out += hdr;\n-\tstream->avail_out -= hdr;\n+\thdrlen = write_binary_header(stream->next_out, obj_type, len);\n+\tstream->total_out = hdrlen;\n+\tstream->next_out += hdrlen;\n+\tstream->avail_out -= hdrlen;\n }\n \n int hash_sha1_file(void *buf, unsigned long len, const char *type,\n                    unsigned char *sha1)\n {\n-\tunsigned char hdr[50];\n+\tchar hdr[32];\n \tint hdrlen;\n \twrite_sha1_file_prepare(buf, len, type, sha1, hdr, &hdrlen);\n \treturn 0;\n@@ -1780,7 +1780,7 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha\n \tunsigned char sha1[20];\n \tchar *filename;\n \tstatic char tmpfile[PATH_MAX];\n-\tunsigned char hdr[50];\n+\tchar hdr[32];\n \tint fd, hdrlen;\n \n \t/* Normally if we have it in the pack then we do not bother writing\n@@ -1827,7 +1827,7 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha\n \tstream.avail_out = size;\n \n \t/* First header.. */\n-\tstream.next_in = hdr;\n+\tstream.next_in = (unsigned char *)hdr;\n \tstream.avail_in = hdrlen;\n \tsetup_object_header(&stream, type, len);\n \n@@ -1859,7 +1859,7 @@ static void *repack_object(const unsigned char *sha1, unsigned long *objsize)\n \tunsigned char *unpacked;\n \tunsigned long len;\n \tchar type[20];\n-\tchar hdr[50];\n+\tchar hdr[32];\n \tint hdrlen;\n \tvoid *buf;\n \n-- \n1.5.0.572.ge86d\n"},{"id":"35534","messageId":"11725197613482-git-send-email-nico@cam.org","threadId":"6978","inReplyTo":"1172519760216-git-send-email-nico@cam.org","subject":"[PATCH 2/6] sha1_file.c: cleanup \"offset\" usage","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2007-02-26T19:55:56Z","receivedAt":"2007-02-26T19:55:56Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"First there are too many offsets there and it is getting confusing.\nSo 'offset' is now 'curpos' to distinguish from other offsets like\n'obj_offset'.\n\nThen structures like x = foo(x, &y) are now done as y = foo(&x).\nIt looks more natural that the result y be returned directly and\nx be passed as reference to be updated in place.  This has the effect\nof reducing some line length and removing a few, needing a bit less\nstack space, and it even reduces the compiled code size.\n\nSigned-off-by: Nicolas Pitre <nico@cam.org>\n---\n sha1_file.c |  110 +++++++++++++++++++++++++++-------------------------------\n 1 files changed, 51 insertions(+), 59 deletions(-)\n\ndiff --git a/sha1_file.c b/sha1_file.c\nindex 57a9b53..8147a4f 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -1043,12 +1043,11 @@ void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned l\n \n static unsigned long get_delta_base(struct packed_git *p,\n \t\t\t\t    struct pack_window **w_curs,\n-\t\t\t\t    unsigned long offset,\n+\t\t\t\t    unsigned long *curpos,\n \t\t\t\t    enum object_type kind,\n-\t\t\t\t    unsigned long delta_obj_offset,\n-\t\t\t\t    unsigned long *base_obj_offset)\n+\t\t\t\t    unsigned long delta_obj_offset)\n {\n-\tunsigned char *base_info = use_pack(p, w_curs, offset, NULL);\n+\tunsigned char *base_info = use_pack(p, w_curs, *curpos, NULL);\n \tunsigned long base_offset;\n \n \t/* use_pack() assured us we have [base_info, base_info + 20)\n@@ -1071,18 +1070,17 @@ static unsigned long get_delta_base(struct packed_git *p,\n \t\tbase_offset = delta_obj_offset - base_offset;\n \t\tif (base_offset >= delta_obj_offset)\n \t\t\tdie(\"delta base offset out of bound\");\n-\t\toffset += used;\n+\t\t*curpos += used;\n \t} else if (kind == OBJ_REF_DELTA) {\n \t\t/* The base entry _must_ be in the same pack */\n \t\tbase_offset = find_pack_entry_one(base_info, p);\n \t\tif (!base_offset)\n \t\t\tdie(\"failed to find delta-pack base object %s\",\n \t\t\t\tsha1_to_hex(base_info));\n-\t\toffset += 20;\n+\t\t*curpos += 20;\n \t} else\n \t\tdie(\"I am totally screwed\");\n-\t*base_obj_offset = base_offset;\n-\treturn offset;\n+\treturn base_offset;\n }\n \n /* forward declaration for a mutually recursive function */\n@@ -1091,7 +1089,7 @@ static int packed_object_info(struct packed_git *p, unsigned long offset,\n \n static int packed_delta_info(struct packed_git *p,\n \t\t\t     struct pack_window **w_curs,\n-\t\t\t     unsigned long offset,\n+\t\t\t     unsigned long curpos,\n \t\t\t     enum object_type kind,\n \t\t\t     unsigned long obj_offset,\n \t\t\t     char *type,\n@@ -1099,8 +1097,7 @@ static int packed_delta_info(struct packed_git *p,\n {\n \tunsigned long base_offset;\n \n-\toffset = get_delta_base(p, w_curs, offset, kind,\n-\t\tobj_offset, &base_offset);\n+\tbase_offset = get_delta_base(p, w_curs, &curpos, kind, obj_offset);\n \n \t/* We choose to only get the type of the base object and\n \t * ignore potentially corrupt pack file that expects the delta\n@@ -1113,7 +1110,6 @@ static int packed_delta_info(struct packed_git *p,\n \tif (sizep) {\n \t\tconst unsigned char *data;\n \t\tunsigned char delta_head[20], *in;\n-\t\tunsigned long result_size;\n \t\tz_stream stream;\n \t\tint st;\n \n@@ -1123,10 +1119,10 @@ static int packed_delta_info(struct packed_git *p,\n \n \t\tinflateInit(&stream);\n \t\tdo {\n-\t\t\tin = use_pack(p, w_curs, offset, &stream.avail_in);\n+\t\t\tin = use_pack(p, w_curs, curpos, &stream.avail_in);\n \t\t\tstream.next_in = in;\n \t\t\tst = inflate(&stream, Z_FINISH);\n-\t\t\toffset += stream.next_in - in;\n+\t\t\tcurpos += stream.next_in - in;\n \t\t} while ((st == Z_OK || st == Z_BUF_ERROR)\n \t\t\t&& stream.total_out < sizeof(delta_head));\n \t\tinflateEnd(&stream);\n@@ -1143,21 +1139,20 @@ static int packed_delta_info(struct packed_git *p,\n \t\tget_delta_hdr_size(&data, delta_head+sizeof(delta_head));\n \n \t\t/* Read the result size */\n-\t\tresult_size = get_delta_hdr_size(&data, delta_head+sizeof(delta_head));\n-\t\t*sizep = result_size;\n+\t\t*sizep = get_delta_hdr_size(&data, delta_head+sizeof(delta_head));\n \t}\n \treturn 0;\n }\n \n-static unsigned long unpack_object_header(struct packed_git *p,\n-\t\tstruct pack_window **w_curs,\n-\t\tunsigned long offset,\n-\t\tenum object_type *type,\n-\t\tunsigned long *sizep)\n+static int unpack_object_header(struct packed_git *p,\n+\t\t\t\tstruct pack_window **w_curs,\n+\t\t\t\tunsigned long *curpos,\n+\t\t\t\tunsigned long *sizep)\n {\n \tunsigned char *base;\n \tunsigned int left;\n \tunsigned long used;\n+\tenum object_type type;\n \n \t/* use_pack() assures us we have [base, base + 20) available\n \t * as a range that we can look at at.  (Its actually the hash\n@@ -1165,16 +1160,17 @@ static unsigned long unpack_object_header(struct packed_git *p,\n \t * the maximum deflated object size is 2^137, which is just\n \t * insane, so we know won't exceed what we have been given.\n \t */\n-\tbase = use_pack(p, w_curs, offset, &left);\n-\tused = unpack_object_header_gently(base, left, type, sizep);\n+\tbase = use_pack(p, w_curs, *curpos, &left);\n+\tused = unpack_object_header_gently(base, left, &type, sizep);\n \tif (!used)\n \t\tdie(\"object offset outside of pack file\");\n+\t*curpos += used;\n \n-\treturn offset + used;\n+\treturn type;\n }\n \n void packed_object_info_detail(struct packed_git *p,\n-\t\t\t       unsigned long offset,\n+\t\t\t       unsigned long obj_offset,\n \t\t\t       char *type,\n \t\t\t       unsigned long *size,\n \t\t\t       unsigned long *store_size,\n@@ -1182,13 +1178,13 @@ void packed_object_info_detail(struct packed_git *p,\n \t\t\t       unsigned char *base_sha1)\n {\n \tstruct pack_window *w_curs = NULL;\n-\tunsigned long obj_offset, val;\n+\tunsigned long curpos, dummy;\n \tunsigned char *next_sha1;\n \tenum object_type kind;\n \n \t*delta_chain_length = 0;\n-\tobj_offset = offset;\n-\toffset = unpack_object_header(p, &w_curs, offset, &kind, size);\n+\tcurpos = obj_offset;\n+\tkind = unpack_object_header(p, &w_curs, &curpos, size);\n \n \tfor (;;) {\n \t\tswitch (kind) {\n@@ -1204,61 +1200,58 @@ void packed_object_info_detail(struct packed_git *p,\n \t\t\tunuse_pack(&w_curs);\n \t\t\treturn;\n \t\tcase OBJ_OFS_DELTA:\n-\t\t\tget_delta_base(p, &w_curs, offset, kind,\n-\t\t\t\tobj_offset, &offset);\n+\t\t\tobj_offset = get_delta_base(p, &w_curs, &curpos, kind, obj_offset);\n \t\t\tif (*delta_chain_length == 0) {\n-\t\t\t\t/* TODO: find base_sha1 as pointed by offset */\n+\t\t\t\t/* TODO: find base_sha1 as pointed by curpos */\n \t\t\t}\n \t\t\tbreak;\n \t\tcase OBJ_REF_DELTA:\n-\t\t\tnext_sha1 = use_pack(p, &w_curs, offset, NULL);\n+\t\t\tnext_sha1 = use_pack(p, &w_curs, curpos, NULL);\n \t\t\tif (*delta_chain_length == 0)\n \t\t\t\thashcpy(base_sha1, next_sha1);\n-\t\t\toffset = find_pack_entry_one(next_sha1, p);\n+\t\t\tobj_offset = find_pack_entry_one(next_sha1, p);\n \t\t\tbreak;\n \t\t}\n-\t\tobj_offset = offset;\n-\t\toffset = unpack_object_header(p, &w_curs, offset, &kind, &val);\n \t\t(*delta_chain_length)++;\n+\t\tcurpos = obj_offset;\n+\t\tkind = unpack_object_header(p, &w_curs, &curpos, &dummy);\n \t}\n }\n \n-static int packed_object_info(struct packed_git *p, unsigned long offset,\n+static int packed_object_info(struct packed_git *p, unsigned long obj_offset,\n \t\t\t      char *type, unsigned long *sizep)\n {\n \tstruct pack_window *w_curs = NULL;\n-\tunsigned long size, obj_offset = offset;\n+\tunsigned long size, curpos = obj_offset;\n \tenum object_type kind;\n-\tint r;\n \n-\toffset = unpack_object_header(p, &w_curs, offset, &kind, &size);\n+\tkind = unpack_object_header(p, &w_curs, &curpos, &size);\n \n \tswitch (kind) {\n \tcase OBJ_OFS_DELTA:\n \tcase OBJ_REF_DELTA:\n-\t\tr = packed_delta_info(p, &w_curs, offset, kind,\n-\t\t\tobj_offset, type, sizep);\n-\t\tunuse_pack(&w_curs);\n-\t\treturn r;\n+\t\tpacked_delta_info(p, &w_curs, curpos, kind,\n+\t\t\t\t  obj_offset, type, sizep);\n+\t\tbreak;\n \tcase OBJ_COMMIT:\n \tcase OBJ_TREE:\n \tcase OBJ_BLOB:\n \tcase OBJ_TAG:\n \t\tstrcpy(type, type_names[kind]);\n-\t\tunuse_pack(&w_curs);\n+\t\tif (sizep)\n+\t\t\t*sizep = size;\n \t\tbreak;\n \tdefault:\n \t\tdie(\"pack %s contains unknown object type %d\",\n \t\t    p->pack_name, kind);\n \t}\n-\tif (sizep)\n-\t\t*sizep = size;\n+\tunuse_pack(&w_curs);\n \treturn 0;\n }\n \n static void *unpack_compressed_entry(struct packed_git *p,\n \t\t\t\t    struct pack_window **w_curs,\n-\t\t\t\t    unsigned long offset,\n+\t\t\t\t    unsigned long curpos,\n \t\t\t\t    unsigned long size)\n {\n \tint st;\n@@ -1273,10 +1266,10 @@ static void *unpack_compressed_entry(struct packed_git *p,\n \n \tinflateInit(&stream);\n \tdo {\n-\t\tin = use_pack(p, w_curs, offset, &stream.avail_in);\n+\t\tin = use_pack(p, w_curs, curpos, &stream.avail_in);\n \t\tstream.next_in = in;\n \t\tst = inflate(&stream, Z_FINISH);\n-\t\toffset += stream.next_in - in;\n+\t\tcurpos += stream.next_in - in;\n \t} while (st == Z_OK || st == Z_BUF_ERROR);\n \tinflateEnd(&stream);\n \tif ((st != Z_STREAM_END) || stream.total_out != size) {\n@@ -1289,7 +1282,7 @@ static void *unpack_compressed_entry(struct packed_git *p,\n \n static void *unpack_delta_entry(struct packed_git *p,\n \t\t\t\tstruct pack_window **w_curs,\n-\t\t\t\tunsigned long offset,\n+\t\t\t\tunsigned long curpos,\n \t\t\t\tunsigned long delta_size,\n \t\t\t\tenum object_type kind,\n \t\t\t\tunsigned long obj_offset,\n@@ -1299,14 +1292,13 @@ static void *unpack_delta_entry(struct packed_git *p,\n \tvoid *delta_data, *result, *base;\n \tunsigned long result_size, base_size, base_offset;\n \n-\toffset = get_delta_base(p, w_curs, offset, kind,\n-\t\tobj_offset, &base_offset);\n+\tbase_offset = get_delta_base(p, w_curs, &curpos, kind, obj_offset);\n \tbase = unpack_entry(p, base_offset, type, &base_size);\n \tif (!base)\n \t\tdie(\"failed to read delta base object at %lu from %s\",\n \t\t    base_offset, p->pack_name);\n \n-\tdelta_data = unpack_compressed_entry(p, w_curs, offset, delta_size);\n+\tdelta_data = unpack_compressed_entry(p, w_curs, curpos, delta_size);\n \tresult = patch_delta(base, base_size,\n \t\t\t     delta_data, delta_size,\n \t\t\t     &result_size);\n@@ -1318,19 +1310,19 @@ static void *unpack_delta_entry(struct packed_git *p,\n \treturn result;\n }\n \n-void *unpack_entry(struct packed_git *p, unsigned long offset,\n-\t\t\t  char *type, unsigned long *sizep)\n+void *unpack_entry(struct packed_git *p, unsigned long obj_offset,\n+\t\t   char *type, unsigned long *sizep)\n {\n \tstruct pack_window *w_curs = NULL;\n-\tunsigned long size, obj_offset = offset;\n+\tunsigned long size, curpos = obj_offset;\n \tenum object_type kind;\n \tvoid *retval;\n \n-\toffset = unpack_object_header(p, &w_curs, offset, &kind, &size);\n+\tkind = unpack_object_header(p, &w_curs, &curpos, &size);\n \tswitch (kind) {\n \tcase OBJ_OFS_DELTA:\n \tcase OBJ_REF_DELTA:\n-\t\tretval = unpack_delta_entry(p, &w_curs, offset, size,\n+\t\tretval = unpack_delta_entry(p, &w_curs, curpos, size,\n \t\t\tkind, obj_offset, type, sizep);\n \t\tbreak;\n \tcase OBJ_COMMIT:\n@@ -1339,7 +1331,7 @@ void *unpack_entry(struct packed_git *p, unsigned long offset,\n \tcase OBJ_TAG:\n \t\tstrcpy(type, type_names[kind]);\n \t\t*sizep = size;\n-\t\tretval = unpack_compressed_entry(p, &w_curs, offset, size);\n+\t\tretval = unpack_compressed_entry(p, &w_curs, curpos, size);\n \t\tbreak;\n \tdefault:\n \t\tdie(\"unknown object type %i in %s\", kind, p->pack_name);\n-- \n1.5.0.572.ge86d\n"},{"id":"35536","messageId":"11725197622423-git-send-email-nico@cam.org","threadId":"6978","inReplyTo":"11725197613482-git-send-email-nico@cam.org","subject":"[PATCH 3/6] sha1_file.c: don't ignore an error condition in sha1_loose_object_info()","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2007-02-26T19:55:57Z","receivedAt":"2007-02-26T19:55:57Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"Signed-off-by: Nicolas Pitre <nico@cam.org>\n---\n sha1_file.c |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/sha1_file.c b/sha1_file.c\nindex 8147a4f..8b7b68c 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -1461,7 +1461,7 @@ static int sha1_loose_object_info(const unsigned char *sha1, char *type, unsigne\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-\tif (parse_sha1_header(hdr, type, &size) < 0)\n+\telse if (parse_sha1_header(hdr, type, &size) < 0)\n \t\tstatus = error(\"unable to parse %s header\", sha1_to_hex(sha1));\n \telse {\n \t\tstatus = 0;\n-- \n1.5.0.572.ge86d\n"},{"id":"35535","messageId":"11725197633144-git-send-email-nico@cam.org","threadId":"6978","inReplyTo":"11725197622423-git-send-email-nico@cam.org","subject":"[PATCH 4/6] formalize typename(), and add its reverse type_from_string()","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2007-02-26T19:55:58Z","receivedAt":"2007-02-26T19:55:58Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"Sometime typename() is used, sometimes type_names[] is accessed directly.\nLet's enforce typename() all the time which allows for validating the\ntype.\n\nAlso let's add a function to go from a name to a type and use it instead\nof manual memcpy() when appropriate.\n\nSigned-off-by: Nicolas Pitre <nico@cam.org>\n---\n builtin-for-each-ref.c |    2 +-\n builtin-pack-objects.c |   13 +------------\n fast-import.c          |   10 +++++-----\n index-pack.c           |    7 +------\n object.c               |   26 +++++++++++++++++++++++---\n object.h               |   10 +++-------\n sha1_file.c            |   19 +++++--------------\n 7 files changed, 39 insertions(+), 48 deletions(-)\n\ndiff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c\nindex ac0b9f6..14fff2b 100644\n--- a/builtin-for-each-ref.c\n+++ b/builtin-for-each-ref.c\n@@ -196,7 +196,7 @@ static void grab_common_values(struct atom_value *val, int deref, struct object\n \t\tif (deref)\n \t\t\tname++;\n \t\tif (!strcmp(name, \"objecttype\"))\n-\t\t\tv->s = type_names[obj->type];\n+\t\t\tv->s = typename(obj->type);\n \t\telse if (!strcmp(name, \"objectsize\")) {\n \t\t\tchar *s = xmalloc(40);\n \t\t\tsprintf(s, \"%lu\", sz);\ndiff --git a/builtin-pack-objects.c b/builtin-pack-objects.c\nindex b5ed9ce..c456f49 100644\n--- a/builtin-pack-objects.c\n+++ b/builtin-pack-objects.c\n@@ -1065,18 +1065,7 @@ static void check_object(struct object_entry *entry)\n \tif (sha1_object_info(entry->sha1, type, &entry->size))\n \t\tdie(\"unable to get type of object %s\",\n \t\t    sha1_to_hex(entry->sha1));\n-\n-\tif (!strcmp(type, commit_type)) {\n-\t\tentry->type = OBJ_COMMIT;\n-\t} else if (!strcmp(type, tree_type)) {\n-\t\tentry->type = OBJ_TREE;\n-\t} else if (!strcmp(type, blob_type)) {\n-\t\tentry->type = OBJ_BLOB;\n-\t} else if (!strcmp(type, tag_type)) {\n-\t\tentry->type = OBJ_TAG;\n-\t} else\n-\t\tdie(\"unable to pack object %s of type %s\",\n-\t\t    sha1_to_hex(entry->sha1), type);\n+\tentry->type = type_from_string(type);\n }\n \n static unsigned int check_delta_limit(struct object_entry *me, unsigned int n)\ndiff --git a/fast-import.c b/fast-import.c\nindex 5d040fd..aa9eac3 100644\n--- a/fast-import.c\n+++ b/fast-import.c\n@@ -891,7 +891,7 @@ static int store_object(\n \tSHA_CTX c;\n \tz_stream s;\n \n-\thdrlen = sprintf((char*)hdr,\"%s %lu\", type_names[type],\n+\thdrlen = sprintf((char*)hdr,\"%s %lu\", typename(type),\n \t\t(unsigned long)datlen) + 1;\n \tSHA1_Init(&c);\n \tSHA1_Update(&c, hdr, hdrlen);\n@@ -1626,7 +1626,7 @@ static void file_change_m(struct branch *b)\n \t} else if (oe) {\n \t\tif (oe->type != OBJ_BLOB)\n \t\t\tdie(\"Not a blob (actually a %s): %s\",\n-\t\t\t\tcommand_buf.buf, type_names[oe->type]);\n+\t\t\t\tcommand_buf.buf, typename(oe->type));\n \t} else {\n \t\tif (sha1_object_info(sha1, type, NULL))\n \t\t\tdie(\"Blob not found: %s\", command_buf.buf);\n@@ -1711,7 +1711,7 @@ static void cmd_from(struct branch *b)\n \t\t\tchar *buf;\n \n \t\t\tbuf = read_object_with_reference(b->sha1,\n-\t\t\t\ttype_names[OBJ_COMMIT], &size, b->sha1);\n+\t\t\t\tcommit_type, &size, b->sha1);\n \t\t\tif (!buf || size < 46)\n \t\t\t\tdie(\"Not a valid commit: %s\", from);\n \t\t\tif (memcmp(\"tree \", buf, 5)\n@@ -1895,7 +1895,7 @@ static void cmd_new_tag(void)\n \t\tchar *buf;\n \n \t\tbuf = read_object_with_reference(sha1,\n-\t\t\ttype_names[OBJ_COMMIT], &size, sha1);\n+\t\t\tcommit_type, &size, sha1);\n \t\tif (!buf || size < 46)\n \t\t\tdie(\"Not a valid commit: %s\", from);\n \t\tfree(buf);\n@@ -1916,7 +1916,7 @@ static void cmd_new_tag(void)\n \tsize_dbuf(&new_data, 67+strlen(t->name)+strlen(tagger)+msglen);\n \tsp = new_data.buffer;\n \tsp += sprintf(sp, \"object %s\\n\", sha1_to_hex(sha1));\n-\tsp += sprintf(sp, \"type %s\\n\", type_names[OBJ_COMMIT]);\n+\tsp += sprintf(sp, \"type %s\\n\", commit_type);\n \tsp += sprintf(sp, \"tag %s\\n\", t->name);\n \tsp += sprintf(sp, \"tagger %s\\n\", tagger);\n \t*sp++ = '\\n';\ndiff --git a/index-pack.c b/index-pack.c\nindex 365f8f3..c25cd40 100644\n--- a/index-pack.c\n+++ b/index-pack.c\n@@ -605,13 +605,8 @@ static void fix_unresolved_deltas(int nr_unresolved)\n \t\tdata = read_sha1_file(d->base.sha1, type, &size);\n \t\tif (!data)\n \t\t\tcontinue;\n-\t\tif      (!strcmp(type, blob_type))   obj_type = OBJ_BLOB;\n-\t\telse if (!strcmp(type, tree_type))   obj_type = OBJ_TREE;\n-\t\telse if (!strcmp(type, commit_type)) obj_type = OBJ_COMMIT;\n-\t\telse if (!strcmp(type, tag_type))    obj_type = OBJ_TAG;\n-\t\telse die(\"base object %s is of type '%s'\",\n-\t\t\t sha1_to_hex(d->base.sha1), type);\n \n+\t\tobj_type = type_from_string(type);\n \t\tfind_delta_children(&d->base, &first, &last);\n \t\tfor (j = first; j <= last; j++) {\n \t\t\tstruct object_entry *child = objects + deltas[j].obj_no;\ndiff --git a/object.c b/object.c\nindex de244e2..37cedc0 100644\n--- a/object.c\n+++ b/object.c\n@@ -18,11 +18,31 @@ struct object *get_indexed_object(unsigned int idx)\n \treturn obj_hash[idx];\n }\n \n-const char *type_names[] = {\n-\t\"none\", \"commit\", \"tree\", \"blob\", \"tag\",\n-\t\"bad type 5\", \"bad type 6\", \"delta\", \"bad\",\n+static const char *object_type_strings[] = {\n+\tNULL,\t\t/* OBJ_NONE = 0 */\n+\t\"commit\",\t/* OBJ_COMMIT = 1 */\n+\t\"tree\",\t\t/* OBJ_TREE = 2 */\n+\t\"blob\",\t\t/* OBJ_BLOB = 3 */\n+\t\"tag\",\t\t/* OBJ_TAG = 4 */\n };\n \n+const char *typename(unsigned int type)\n+{\n+\tif (type >= ARRAY_SIZE(object_type_strings))\n+\t\treturn NULL;\n+\treturn object_type_strings[type];\n+}\n+\n+int type_from_string(const char *str)\n+{\n+\tint i;\n+\n+\tfor (i = 1; i < ARRAY_SIZE(object_type_strings); i++)\n+\t\tif (!strcmp(str, object_type_strings[i]))\n+\t\t\treturn i;\n+\tdie(\"invalid object type \\\"%s\\\"\", str);\n+}\n+\n static unsigned int hash_obj(struct object *obj, unsigned int n)\n {\n \tunsigned int hash = *(unsigned int *)obj->sha1;\ndiff --git a/object.h b/object.h\nindex caee733..ade4dae 100644\n--- a/object.h\n+++ b/object.h\n@@ -36,16 +36,12 @@ struct object {\n };\n \n extern int track_object_refs;\n-extern const char *type_names[9];\n+\n+extern const char *typename(unsigned int type);\n+extern int type_from_string(const char *str);\n \n extern unsigned int get_max_object_index(void);\n extern struct object *get_indexed_object(unsigned int);\n-\n-static inline const char *typename(unsigned int type)\n-{\n-\treturn type_names[type > OBJ_BAD ? OBJ_BAD : type];\n-}\n-\n extern struct object_refs *lookup_object_refs(struct object *);\n \n /** Internal only **/\ndiff --git a/sha1_file.c b/sha1_file.c\nindex 8b7b68c..423ff0a 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -952,7 +952,7 @@ static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned lon\n \n \t/* And generate the fake traditional header */\n \tstream->total_out = 1 + snprintf(buffer, bufsiz, \"%s %lu\",\n-\t\t\t\t\t type_names[type], size);\n+\t\t\t\t\t typename(type), size);\n \treturn 0;\n }\n \n@@ -1195,7 +1195,7 @@ void packed_object_info_detail(struct packed_git *p,\n \t\tcase OBJ_TREE:\n \t\tcase OBJ_BLOB:\n \t\tcase OBJ_TAG:\n-\t\t\tstrcpy(type, type_names[kind]);\n+\t\t\tstrcpy(type, typename(kind));\n \t\t\t*store_size = 0; /* notyet */\n \t\t\tunuse_pack(&w_curs);\n \t\t\treturn;\n@@ -1237,7 +1237,7 @@ static int packed_object_info(struct packed_git *p, unsigned long obj_offset,\n \tcase OBJ_TREE:\n \tcase OBJ_BLOB:\n \tcase OBJ_TAG:\n-\t\tstrcpy(type, type_names[kind]);\n+\t\tstrcpy(type, typename(kind));\n \t\tif (sizep)\n \t\t\t*sizep = size;\n \t\tbreak;\n@@ -1329,7 +1329,7 @@ void *unpack_entry(struct packed_git *p, unsigned long obj_offset,\n \tcase OBJ_TREE:\n \tcase OBJ_BLOB:\n \tcase OBJ_TAG:\n-\t\tstrcpy(type, type_names[kind]);\n+\t\tstrcpy(type, typename(kind));\n \t\t*sizep = size;\n \t\tretval = unpack_compressed_entry(p, &w_curs, curpos, size);\n \t\tbreak;\n@@ -1739,16 +1739,7 @@ static void setup_object_header(z_stream *stream, const char *type, unsigned lon\n \t\t\t/* nothing */;\n \t\treturn;\n \t}\n-\tif (!strcmp(type, blob_type))\n-\t\tobj_type = OBJ_BLOB;\n-\telse if (!strcmp(type, tree_type))\n-\t\tobj_type = OBJ_TREE;\n-\telse if (!strcmp(type, commit_type))\n-\t\tobj_type = OBJ_COMMIT;\n-\telse if (!strcmp(type, tag_type))\n-\t\tobj_type = OBJ_TAG;\n-\telse\n-\t\tdie(\"trying to generate bogus object of type '%s'\", type);\n+\tobj_type = type_from_string(type);\n \thdrlen = write_binary_header(stream->next_out, obj_type, len);\n \tstream->total_out = hdrlen;\n \tstream->next_out += hdrlen;\n-- \n1.5.0.572.ge86d\n"},{"id":"35538","messageId":"11725197632516-git-send-email-nico@cam.org","threadId":"6978","inReplyTo":"11725197633144-git-send-email-nico@cam.org","subject":"[PATCH 5/6] convert object type handling from a string to a number","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2007-02-26T19:55:59Z","receivedAt":"2007-02-26T19:55:59Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"We currently have two parallel notation for dealing with object types\nin the code: a string and a numerical value.  One of them is obviously\nredundent, and the most used one requires more stack space and a bunch\nof strcmp() all over the place.\n\nThis is an initial step for the removal of the version using a char array\nfound in object reading code paths.  The patch is unfortunately large but\nthere is no sane way to split it in smaller parts without breaking the\nsystem.\n\nSigned-off-by: Nicolas Pitre <nico@cam.org>\n---\n archive-tar.c            |    4 +-\n archive-zip.c            |    4 +-\n blob.c                   |    6 +-\n builtin-apply.c          |    8 +-\n builtin-blame.c          |   18 ++---\n builtin-cat-file.c       |   19 +++--\n builtin-commit-tree.c    |    7 +-\n builtin-for-each-ref.c   |    4 +-\n builtin-grep.c           |    8 +-\n builtin-log.c            |    4 +-\n builtin-pack-objects.c   |   32 ++++-----\n builtin-prune.c          |   11 +--\n builtin-reflog.c         |    4 +-\n builtin-unpack-objects.c |   39 ++++-------\n cache.h                  |   36 +++++-----\n combine-diff.c           |    6 +-\n commit.c                 |    6 +-\n convert-objects.c        |   12 ++--\n diff.c                   |    7 +-\n entry.c                  |    6 +-\n fast-import.c            |   18 +++---\n http-push.c              |    6 +-\n index-pack.c             |   10 +--\n merge-file.c             |   10 ++--\n merge-recursive.c        |   14 ++--\n merge-tree.c             |    8 +-\n mktag.c                  |    8 +-\n mktree.c                 |    9 ++-\n object.c                 |   16 ++--\n object.h                 |    2 +-\n pack-check.c             |   14 ++--\n read-cache.c             |    4 +-\n sha1_file.c              |  170 ++++++++++++++++++++++------------------------\n tag.c                    |    6 +-\n tree-diff.c              |    6 +-\n tree.c                   |    6 +-\n unpack-file.c            |    6 +-\n 37 files changed, 265 insertions(+), 289 deletions(-)\n\ndiff --git a/archive-tar.c b/archive-tar.c\nindex 7d52a06..d9c30d3 100644\n--- a/archive-tar.c\n+++ b/archive-tar.c\n@@ -262,7 +262,7 @@ static int write_tar_entry(const unsigned char *sha1,\n \tstatic struct strbuf path;\n \tint filenamelen = strlen(filename);\n \tvoid *buffer;\n-\tchar type[20];\n+\tenum object_type type;\n \tunsigned long size;\n \n \tif (!path.alloc) {\n@@ -283,7 +283,7 @@ static int write_tar_entry(const unsigned char *sha1,\n \t\tbuffer = NULL;\n \t\tsize = 0;\n \t} else {\n-\t\tbuffer = read_sha1_file(sha1, type, &size);\n+\t\tbuffer = read_sha1_file(sha1, &type, &size);\n \t\tif (!buffer)\n \t\t\tdie(\"cannot read %s\", sha1_to_hex(sha1));\n \t}\ndiff --git a/archive-zip.c b/archive-zip.c\nindex f31b8ed..7c49848 100644\n--- a/archive-zip.c\n+++ b/archive-zip.c\n@@ -167,7 +167,7 @@ static int write_zip_entry(const unsigned char *sha1,\n \tint pathlen;\n \tunsigned char *out;\n \tchar *path;\n-\tchar type[20];\n+\tenum object_type type;\n \tvoid *buffer = NULL;\n \tvoid *deflated = NULL;\n \n@@ -195,7 +195,7 @@ static int write_zip_entry(const unsigned char *sha1,\n \t\tif (S_ISREG(mode) && zlib_compression_level != 0)\n \t\t\tmethod = 8;\n \t\tresult = 0;\n-\t\tbuffer = read_sha1_file(sha1, type, &size);\n+\t\tbuffer = read_sha1_file(sha1, &type, &size);\n \t\tif (!buffer)\n \t\t\tdie(\"cannot read %s\", sha1_to_hex(sha1));\n \t\tcrc = crc32(crc, buffer, size);\ndiff --git a/blob.c b/blob.c\nindex 9776bea..0a9ea41 100644\n--- a/blob.c\n+++ b/blob.c\n@@ -30,18 +30,18 @@ int parse_blob_buffer(struct blob *item, void *buffer, unsigned long size)\n \n int parse_blob(struct blob *item)\n {\n-        char type[20];\n+        enum object_type type;\n         void *buffer;\n         unsigned long size;\n \tint ret;\n \n         if (item->object.parsed)\n                 return 0;\n-        buffer = read_sha1_file(item->object.sha1, type, &size);\n+        buffer = read_sha1_file(item->object.sha1, &type, &size);\n         if (!buffer)\n                 return error(\"Could not read %s\",\n                              sha1_to_hex(item->object.sha1));\n-        if (strcmp(type, blob_type))\n+        if (type != OBJ_BLOB)\n                 return error(\"Object %s not a blob\",\n                              sha1_to_hex(item->object.sha1));\n \tret = parse_blob_buffer(item, buffer, size);\ndiff --git a/builtin-apply.c b/builtin-apply.c\nindex 2dde341..bd3372f 100644\n--- a/builtin-apply.c\n+++ b/builtin-apply.c\n@@ -1911,11 +1911,11 @@ static int apply_binary(struct buffer_desc *desc, struct patch *patch)\n \n \tif (has_sha1_file(sha1)) {\n \t\t/* We already have the postimage */\n-\t\tchar type[10];\n+\t\tenum object_type type;\n \t\tunsigned long size;\n \n \t\tfree(desc->buffer);\n-\t\tdesc->buffer = read_sha1_file(sha1, type, &size);\n+\t\tdesc->buffer = read_sha1_file(sha1, &type, &size);\n \t\tif (!desc->buffer)\n \t\t\treturn error(\"the necessary postimage %s for \"\n \t\t\t\t     \"'%s' cannot be read\",\n@@ -1971,8 +1971,8 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *\n \tbuf = NULL;\n \tif (cached) {\n \t\tif (ce) {\n-\t\t\tchar type[20];\n-\t\t\tbuf = read_sha1_file(ce->sha1, type, &size);\n+\t\t\tenum object_type type;\n+\t\t\tbuf = read_sha1_file(ce->sha1, &type, &size);\n \t\t\tif (!buf)\n \t\t\t\treturn error(\"read of %s failed\",\n \t\t\t\t\t     patch->old_name);\ndiff --git a/builtin-blame.c b/builtin-blame.c\nindex 530b97f..9f7dd4e 100644\n--- a/builtin-blame.c\n+++ b/builtin-blame.c\n@@ -87,9 +87,9 @@ struct origin {\n static char *fill_origin_blob(struct origin *o, mmfile_t *file)\n {\n \tif (!o->file.ptr) {\n-\t\tchar type[10];\n+\t\tenum object_type type;\n \t\tnum_read_blob++;\n-\t\tfile->ptr = read_sha1_file(o->blob_sha1, type,\n+\t\tfile->ptr = read_sha1_file(o->blob_sha1, &type,\n \t\t\t\t\t   (unsigned long *)(&(file->size)));\n \t\to->file = *file;\n \t}\n@@ -263,7 +263,6 @@ static struct origin *get_origin(struct scoreboard *sb,\n static int fill_blob_sha1(struct origin *origin)\n {\n \tunsigned mode;\n-\tchar type[10];\n \n \tif (!is_null_sha1(origin->blob_sha1))\n \t\treturn 0;\n@@ -271,8 +270,7 @@ static int fill_blob_sha1(struct origin *origin)\n \t\t\t   origin->path,\n \t\t\t   origin->blob_sha1, &mode))\n \t\tgoto error_out;\n-\tif (sha1_object_info(origin->blob_sha1, type, NULL) ||\n-\t    strcmp(type, blob_type))\n+\tif (sha1_object_info(origin->blob_sha1, NULL) != OBJ_BLOB)\n \t\tgoto error_out;\n \treturn 0;\n  error_out:\n@@ -1322,10 +1320,10 @@ static void get_commit_info(struct commit *commit,\n \t * we now need to populate them for output.\n \t */\n \tif (!commit->buffer) {\n-\t\tchar type[20];\n+\t\tenum object_type type;\n \t\tunsigned long size;\n \t\tcommit->buffer =\n-\t\t\tread_sha1_file(commit->object.sha1, type, &size);\n+\t\t\tread_sha1_file(commit->object.sha1, &type, &size);\n \t}\n \tret->author = author_buf;\n \tget_ac_line(commit->buffer, \"\\nauthor \",\n@@ -2006,7 +2004,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con\n \tbuf[fin_size] = 0;\n \torigin->file.ptr = buf;\n \torigin->file.size = fin_size;\n-\tpretend_sha1_file(buf, fin_size, blob_type, origin->blob_sha1);\n+\tpretend_sha1_file(buf, fin_size, OBJ_BLOB, origin->blob_sha1);\n \tcommit->util = origin;\n \n \t/*\n@@ -2068,7 +2066,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \tint show_stats = 0;\n \tconst char *revs_file = NULL;\n \tconst char *final_commit_name = NULL;\n-\tchar type[10];\n+\tenum object_type type;\n \tconst char *bottomtop = NULL;\n \tconst char *contents_from = NULL;\n \n@@ -2302,7 +2300,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \t\tif (fill_blob_sha1(o))\n \t\t\tdie(\"no such path %s in %s\", path, final_commit_name);\n \n-\t\tsb.final_buf = read_sha1_file(o->blob_sha1, type,\n+\t\tsb.final_buf = read_sha1_file(o->blob_sha1, &type,\n \t\t\t\t\t      &sb.final_buf_size);\n \t}\n \tnum_read_blob++;\ndiff --git a/builtin-cat-file.c b/builtin-cat-file.c\nindex 6c16bfa..d61d3d5 100644\n--- a/builtin-cat-file.c\n+++ b/builtin-cat-file.c\n@@ -79,7 +79,7 @@ static void pprint_tag(const unsigned char *sha1, const char *buf, unsigned long\n int cmd_cat_file(int argc, const char **argv, const char *prefix)\n {\n \tunsigned char sha1[20];\n-\tchar type[20];\n+\tenum object_type type;\n \tvoid *buf;\n \tunsigned long size;\n \tint opt;\n@@ -100,14 +100,16 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)\n \tbuf = NULL;\n \tswitch (opt) {\n \tcase 't':\n-\t\tif (!sha1_object_info(sha1, type, NULL)) {\n-\t\t\tprintf(\"%s\\n\", type);\n+\t\ttype = sha1_object_info(sha1, NULL);\n+\t\tif (type > 0) {\n+\t\t\tprintf(\"%s\\n\", typename(type));\n \t\t\treturn 0;\n \t\t}\n \t\tbreak;\n \n \tcase 's':\n-\t\tif (!sha1_object_info(sha1, type, &size)) {\n+\t\ttype = sha1_object_info(sha1, &size);\n+\t\tif (type > 0) {\n \t\t\tprintf(\"%lu\\n\", size);\n \t\t\treturn 0;\n \t\t}\n@@ -117,17 +119,18 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)\n \t\treturn !has_sha1_file(sha1);\n \n \tcase 'p':\n-\t\tif (sha1_object_info(sha1, type, NULL))\n+\t\ttype = sha1_object_info(sha1, NULL);\n+\t\tif (type < 0)\n \t\t\tdie(\"Not a valid object name %s\", argv[2]);\n \n \t\t/* custom pretty-print here */\n-\t\tif (!strcmp(type, tree_type))\n+\t\tif (type == OBJ_TREE)\n \t\t\treturn cmd_ls_tree(2, argv + 1, NULL);\n \n-\t\tbuf = read_sha1_file(sha1, type, &size);\n+\t\tbuf = read_sha1_file(sha1, &type, &size);\n \t\tif (!buf)\n \t\t\tdie(\"Cannot read object %s\", argv[2]);\n-\t\tif (!strcmp(type, tag_type)) {\n+\t\tif (type == OBJ_TAG) {\n \t\t\tpprint_tag(sha1, buf, size);\n \t\t\treturn 0;\n \t\t}\ndiff --git a/builtin-commit-tree.c b/builtin-commit-tree.c\nindex 2a818a0..04f61d5 100644\n--- a/builtin-commit-tree.c\n+++ b/builtin-commit-tree.c\n@@ -47,11 +47,10 @@ static void add_buffer(char **bufp, unsigned int *sizep, const char *fmt, ...)\n \n static void check_valid(unsigned char *sha1, const char *expect)\n {\n-\tchar type[20];\n-\n-\tif (sha1_object_info(sha1, type, NULL))\n+\tenum object_type type = sha1_object_info(sha1, NULL);\n+\tif (type < 0)\n \t\tdie(\"%s is not a valid object\", sha1_to_hex(sha1));\n-\tif (expect && strcmp(type, expect))\n+\tif (expect && type != type_from_string(expect))\n \t\tdie(\"%s is not a valid '%s' object\", sha1_to_hex(sha1),\n \t\t    expect);\n }\ndiff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c\nindex 14fff2b..b11ca92 100644\n--- a/builtin-for-each-ref.c\n+++ b/builtin-for-each-ref.c\n@@ -173,8 +173,8 @@ static void verify_format(const char *format)\n  */\n static void *get_obj(const unsigned char *sha1, struct object **obj, unsigned long *sz, int *eaten)\n {\n-\tchar type[20];\n-\tvoid *buf = read_sha1_file(sha1, type, sz);\n+\tenum object_type type;\n+\tvoid *buf = read_sha1_file(sha1, &type, sz);\n \n \tif (buf)\n \t\t*obj = parse_object_buffer(sha1, type, *sz, buf, eaten);\ndiff --git a/builtin-grep.c b/builtin-grep.c\nindex f35f2d0..96b7022 100644\n--- a/builtin-grep.c\n+++ b/builtin-grep.c\n@@ -84,11 +84,11 @@ static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1, const char\n {\n \tunsigned long size;\n \tchar *data;\n-\tchar type[20];\n+\tenum object_type type;\n \tchar *to_free = NULL;\n \tint hit;\n \n-\tdata = read_sha1_file(sha1, type, &size);\n+\tdata = read_sha1_file(sha1, &type, &size);\n \tif (!data) {\n \t\terror(\"'%s': unable to read %s\", name, sha1_to_hex(sha1));\n \t\treturn 0;\n@@ -380,10 +380,10 @@ static int grep_tree(struct grep_opt *opt, const char **paths,\n \t\telse if (S_ISREG(entry.mode))\n \t\t\thit |= grep_sha1(opt, entry.sha1, path_buf, tn_len);\n \t\telse if (S_ISDIR(entry.mode)) {\n-\t\t\tchar type[20];\n+\t\t\tenum object_type type;\n \t\t\tstruct tree_desc sub;\n \t\t\tvoid *data;\n-\t\t\tdata = read_sha1_file(entry.sha1, type, &sub.size);\n+\t\t\tdata = read_sha1_file(entry.sha1, &type, &sub.size);\n \t\t\tif (!data)\n \t\t\t\tdie(\"unable to read tree (%s)\",\n \t\t\t\t    sha1_to_hex(entry.sha1));\ndiff --git a/builtin-log.c b/builtin-log.c\nindex f43790c..1c9f7d0 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -89,8 +89,8 @@ int cmd_whatchanged(int argc, const char **argv, const char *prefix)\n static int show_object(const unsigned char *sha1, int suppress_header)\n {\n \tunsigned long size;\n-\tchar type[20];\n-\tchar *buf = read_sha1_file(sha1, type, &size);\n+\tenum object_type type;\n+\tchar *buf = read_sha1_file(sha1, &type, &size);\n \tint offset = 0;\n \n \tif (!buf)\ndiff --git a/builtin-pack-objects.c b/builtin-pack-objects.c\nindex c456f49..010f24a 100644\n--- a/builtin-pack-objects.c\n+++ b/builtin-pack-objects.c\n@@ -230,8 +230,8 @@ static unsigned char *find_packed_object_name(struct packed_git *p,\n static void *delta_against(void *buf, unsigned long size, struct object_entry *entry)\n {\n \tunsigned long othersize, delta_size;\n-\tchar type[10];\n-\tvoid *otherbuf = read_sha1_file(entry->delta->sha1, type, &othersize);\n+\tenum object_type type;\n+\tvoid *otherbuf = read_sha1_file(entry->delta->sha1, &type, &othersize);\n \tvoid *delta_buf;\n \n \tif (!otherbuf)\n@@ -375,7 +375,7 @@ static unsigned long write_object(struct sha1file *f,\n \t\t\t\t  struct object_entry *entry)\n {\n \tunsigned long size;\n-\tchar type[10];\n+\tenum object_type type;\n \tvoid *buf;\n \tunsigned char header[10];\n \tunsigned hdrlen, datalen;\n@@ -416,7 +416,7 @@ static unsigned long write_object(struct sha1file *f,\n \t}\n \n \tif (!to_reuse) {\n-\t\tbuf = read_sha1_file(entry->sha1, type, &size);\n+\t\tbuf = read_sha1_file(entry->sha1, &type, &size);\n \t\tif (!buf)\n \t\t\tdie(\"unable to read %s\", sha1_to_hex(entry->sha1));\n \t\tif (size != entry->size)\n@@ -765,7 +765,7 @@ static struct pbase_tree_cache *pbase_tree_get(const unsigned char *sha1)\n \tstruct pbase_tree_cache *ent, *nent;\n \tvoid *data;\n \tunsigned long size;\n-\tchar type[20];\n+\tenum object_type type;\n \tint neigh;\n \tint my_ix = pbase_tree_cache_ix(sha1);\n \tint available_ix = -1;\n@@ -792,10 +792,10 @@ static struct pbase_tree_cache *pbase_tree_get(const unsigned char *sha1)\n \t/* Did not find one.  Either we got a bogus request or\n \t * we need to read and perhaps cache.\n \t */\n-\tdata = read_sha1_file(sha1, type, &size);\n+\tdata = read_sha1_file(sha1, &type, &size);\n \tif (!data)\n \t\treturn NULL;\n-\tif (strcmp(type, tree_type)) {\n+\tif (type != OBJ_TREE) {\n \t\tfree(data);\n \t\treturn NULL;\n \t}\n@@ -854,19 +854,19 @@ static void add_pbase_object(struct tree_desc *tree,\n \n \twhile (tree_entry(tree,&entry)) {\n \t\tunsigned long size;\n-\t\tchar type[20];\n+\t\tenum object_type type;\n \n \t\tif (entry.pathlen != cmplen ||\n \t\t    memcmp(entry.path, name, cmplen) ||\n \t\t    !has_sha1_file(entry.sha1) ||\n-\t\t    sha1_object_info(entry.sha1, type, &size))\n+\t\t    (type = sha1_object_info(entry.sha1, &size)) < 0)\n \t\t\tcontinue;\n \t\tif (name[cmplen] != '/') {\n \t\t\tunsigned hash = name_hash(fullname);\n \t\t\tadd_object_entry(entry.sha1, hash, 1);\n \t\t\treturn;\n \t\t}\n-\t\tif (!strcmp(type, tree_type)) {\n+\t\tif (type == OBJ_TREE) {\n \t\t\tstruct tree_desc sub;\n \t\t\tstruct pbase_tree_cache *tree;\n \t\t\tconst char *down = name+cmplen+1;\n@@ -978,8 +978,6 @@ static void add_preferred_base(unsigned char *sha1)\n \n static void check_object(struct object_entry *entry)\n {\n-\tchar type[20];\n-\n \tif (entry->in_pack && !entry->preferred_base) {\n \t\tstruct packed_git *p = entry->in_pack;\n \t\tstruct pack_window *w_curs = NULL;\n@@ -1062,10 +1060,10 @@ static void check_object(struct object_entry *entry)\n \t\t/* Otherwise we would do the usual */\n \t}\n \n-\tif (sha1_object_info(entry->sha1, type, &entry->size))\n+\tentry->type = sha1_object_info(entry->sha1, &entry->size);\n+\tif (entry->type < 0)\n \t\tdie(\"unable to get type of object %s\",\n \t\t    sha1_to_hex(entry->sha1));\n-\tentry->type = type_from_string(type);\n }\n \n static unsigned int check_delta_limit(struct object_entry *me, unsigned int n)\n@@ -1195,7 +1193,7 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,\n \tstruct object_entry *trg_entry = trg->entry;\n \tstruct object_entry *src_entry = src->entry;\n \tunsigned long trg_size, src_size, delta_size, sizediff, max_size, sz;\n-\tchar type[10];\n+\tenum object_type type;\n \tvoid *delta_buf;\n \n \t/* Don't bother doing diffs between different types */\n@@ -1246,13 +1244,13 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,\n \n \t/* Load data if not already done */\n \tif (!trg->data) {\n-\t\ttrg->data = read_sha1_file(trg_entry->sha1, type, &sz);\n+\t\ttrg->data = read_sha1_file(trg_entry->sha1, &type, &sz);\n \t\tif (sz != trg_size)\n \t\t\tdie(\"object %s inconsistent object length (%lu vs %lu)\",\n \t\t\t    sha1_to_hex(trg_entry->sha1), sz, trg_size);\n \t}\n \tif (!src->data) {\n-\t\tsrc->data = read_sha1_file(src_entry->sha1, type, &sz);\n+\t\tsrc->data = read_sha1_file(src_entry->sha1, &type, &sz);\n \t\tif (sz != src_size)\n \t\t\tdie(\"object %s inconsistent object length (%lu vs %lu)\",\n \t\t\t    sha1_to_hex(src_entry->sha1), sz, src_size);\ndiff --git a/builtin-prune.c b/builtin-prune.c\nindex 6f0ba0d..09864b7 100644\n--- a/builtin-prune.c\n+++ b/builtin-prune.c\n@@ -10,15 +10,10 @@ static int show_only;\n \n static int prune_object(char *path, const char *filename, const unsigned char *sha1)\n {\n-\tchar buf[20];\n-\tconst char *type;\n-\n \tif (show_only) {\n-\t\tif (sha1_object_info(sha1, buf, NULL))\n-\t\t\ttype = \"unknown\";\n-\t\telse\n-\t\t\ttype = buf;\n-\t\tprintf(\"%s %s\\n\", sha1_to_hex(sha1), type);\n+\t\tenum object_type type = sha1_object_info(sha1, NULL);\n+\t\tprintf(\"%s %s\\n\", sha1_to_hex(sha1),\n+\t\t       (type > 0) ? typename(type) : \"unknown\");\n \t\treturn 0;\n \t}\n \tunlink(mkpath(\"%s/%s\", path, filename));\ndiff --git a/builtin-reflog.c b/builtin-reflog.c\nindex cefb40d..186aabc 100644\n--- a/builtin-reflog.c\n+++ b/builtin-reflog.c\n@@ -55,8 +55,8 @@ static int tree_is_complete(const unsigned char *sha1)\n \tdesc.buf = tree->buffer;\n \tdesc.size = tree->size;\n \tif (!desc.buf) {\n-\t\tchar type[20];\n-\t\tvoid *data = read_sha1_file(sha1, type, &desc.size);\n+\t\tenum object_type type;\n+\t\tvoid *data = read_sha1_file(sha1, &type, &desc.size);\n \t\tif (!data) {\n \t\t\ttree->object.flags |= INCOMPLETE;\n \t\t\treturn 0;\ndiff --git a/builtin-unpack-objects.c b/builtin-unpack-objects.c\nindex 8f8e898..3956c56 100644\n--- a/builtin-unpack-objects.c\n+++ b/builtin-unpack-objects.c\n@@ -119,18 +119,18 @@ struct obj_info {\n \n static struct obj_info *obj_list;\n \n-static void added_object(unsigned nr, const char *type, void *data,\n-\t\t\t unsigned long size);\n+static void added_object(unsigned nr, enum object_type type,\n+\t\t\t void *data, unsigned long size);\n \n-static void write_object(unsigned nr, void *buf, unsigned long size,\n-\t\t\t const char *type)\n+static void write_object(unsigned nr, enum object_type type,\n+\t\t\t void *buf, unsigned long size)\n {\n-\tif (write_sha1_file(buf, size, type, obj_list[nr].sha1) < 0)\n+\tif (write_sha1_file(buf, size, typename(type), obj_list[nr].sha1) < 0)\n \t\tdie(\"failed to write object\");\n \tadded_object(nr, type, buf, size);\n }\n \n-static void resolve_delta(unsigned nr, const char *type,\n+static void resolve_delta(unsigned nr, enum object_type type,\n \t\t\t  void *base, unsigned long base_size,\n \t\t\t  void *delta, unsigned long delta_size)\n {\n@@ -143,12 +143,12 @@ static void resolve_delta(unsigned nr, const char *type,\n \tif (!result)\n \t\tdie(\"failed to apply delta\");\n \tfree(delta);\n-\twrite_object(nr, result, result_size, type);\n+\twrite_object(nr, type, result, result_size);\n \tfree(result);\n }\n \n-static void added_object(unsigned nr, const char *type, void *data,\n-\t\t\t unsigned long size)\n+static void added_object(unsigned nr, enum object_type type,\n+\t\t\t void *data, unsigned long size)\n {\n \tstruct delta_info **p = &delta_list;\n \tstruct delta_info *info;\n@@ -167,33 +167,24 @@ static void added_object(unsigned nr, const char *type, void *data,\n \t}\n }\n \n-static void unpack_non_delta_entry(enum object_type kind, unsigned long size,\n+static void unpack_non_delta_entry(enum object_type type, unsigned long size,\n \t\t\t\t   unsigned nr)\n {\n \tvoid *buf = get_data(size);\n-\tconst char *type;\n-\n-\tswitch (kind) {\n-\tcase OBJ_COMMIT: type = commit_type; break;\n-\tcase OBJ_TREE:   type = tree_type; break;\n-\tcase OBJ_BLOB:   type = blob_type; break;\n-\tcase OBJ_TAG:    type = tag_type; break;\n-\tdefault: die(\"bad type %d\", kind);\n-\t}\n+\n \tif (!dry_run && buf)\n-\t\twrite_object(nr, buf, size, type);\n+\t\twrite_object(nr, type, buf, size);\n \tfree(buf);\n }\n \n-static void unpack_delta_entry(enum object_type kind, unsigned long delta_size,\n+static void unpack_delta_entry(enum object_type type, unsigned long delta_size,\n \t\t\t       unsigned nr)\n {\n \tvoid *delta_data, *base;\n \tunsigned long base_size;\n-\tchar type[20];\n \tunsigned char base_sha1[20];\n \n-\tif (kind == OBJ_REF_DELTA) {\n+\tif (type == OBJ_REF_DELTA) {\n \t\thashcpy(base_sha1, fill(20));\n \t\tuse(20);\n \t\tdelta_data = get_data(delta_size);\n@@ -255,7 +246,7 @@ static void unpack_delta_entry(enum object_type kind, unsigned long delta_size,\n \t\t}\n \t}\n \n-\tbase = read_sha1_file(base_sha1, type, &base_size);\n+\tbase = read_sha1_file(base_sha1, &type, &base_size);\n \tif (!base) {\n \t\terror(\"failed to read delta-pack base object %s\",\n \t\t      sha1_to_hex(base_sha1));\ndiff --git a/cache.h b/cache.h\nindex 8bbc142..0117b7e 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -262,13 +262,25 @@ int adjust_shared_perm(const char *path);\n int safe_create_leading_directories(char *path);\n char *enter_repo(char *path, int strict);\n \n+enum object_type {\n+\tOBJ_NONE = 0,\n+\tOBJ_COMMIT = 1,\n+\tOBJ_TREE = 2,\n+\tOBJ_BLOB = 3,\n+\tOBJ_TAG = 4,\n+\t/* 5 for future expansion */\n+\tOBJ_OFS_DELTA = 6,\n+\tOBJ_REF_DELTA = 7,\n+\tOBJ_BAD,\n+};\n+\n /* Read and unpack a sha1 file into memory, write memory to a sha1 file */\n-extern int sha1_object_info(const unsigned char *, char *, unsigned long *);\n-extern void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned long *size);\n-extern void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size);\n+extern int sha1_object_info(const unsigned char *, unsigned long *);\n+extern void * unpack_sha1_file(void *map, unsigned long mapsize, enum object_type *type, unsigned long *size);\n+extern void * read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size);\n extern int hash_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *sha1);\n extern int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *return_sha1);\n-extern int pretend_sha1_file(void *, unsigned long, const char *, unsigned char *);\n+extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *);\n \n extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned long size, const char *type);\n \n@@ -285,18 +297,6 @@ extern int legacy_loose_object(unsigned char *);\n extern int has_pack_file(const unsigned char *sha1);\n extern int has_pack_index(const unsigned char *sha1);\n \n-enum object_type {\n-\tOBJ_NONE = 0,\n-\tOBJ_COMMIT = 1,\n-\tOBJ_TREE = 2,\n-\tOBJ_BLOB = 3,\n-\tOBJ_TAG = 4,\n-\t/* 5 for future expansion */\n-\tOBJ_OFS_DELTA = 6,\n-\tOBJ_REF_DELTA = 7,\n-\tOBJ_BAD,\n-};\n-\n extern signed char hexval_table[256];\n static inline unsigned int hexval(unsigned int c)\n {\n@@ -422,9 +422,9 @@ extern struct packed_git *add_packed_git(char *, int, int);\n extern int num_packed_objects(const struct packed_git *p);\n extern int nth_packed_object_sha1(const struct packed_git *, int, unsigned char*);\n extern unsigned long find_pack_entry_one(const unsigned char *, struct packed_git *);\n-extern void *unpack_entry(struct packed_git *, unsigned long, char *, unsigned long *);\n+extern void *unpack_entry(struct packed_git *, unsigned long, enum object_type *, unsigned long *);\n extern unsigned long unpack_object_header_gently(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep);\n-extern void packed_object_info_detail(struct packed_git *, unsigned long, char *, unsigned long *, unsigned long *, unsigned int *, unsigned char *);\n+extern const char *packed_object_info_detail(struct packed_git *, unsigned long, unsigned long *, unsigned long *, unsigned int *, unsigned char *);\n \n /* Dumb servers support */\n extern int update_server_info(int);\ndiff --git a/combine-diff.c b/combine-diff.c\nindex a5f2c8d..8205486 100644\n--- a/combine-diff.c\n+++ b/combine-diff.c\n@@ -92,14 +92,14 @@ struct sline {\n static char *grab_blob(const unsigned char *sha1, unsigned long *size)\n {\n \tchar *blob;\n-\tchar type[20];\n+\tenum object_type type;\n \tif (is_null_sha1(sha1)) {\n \t\t/* deleted blob */\n \t\t*size = 0;\n \t\treturn xcalloc(1, 1);\n \t}\n-\tblob = read_sha1_file(sha1, type, size);\n-\tif (strcmp(type, blob_type))\n+\tblob = read_sha1_file(sha1, &type, size);\n+\tif (type != OBJ_BLOB)\n \t\tdie(\"object '%s' is not a blob!\", sha1_to_hex(sha1));\n \treturn blob;\n }\ndiff --git a/commit.c b/commit.c\nindex fb75ae5..5552527 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -352,18 +352,18 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)\n \n int parse_commit(struct commit *item)\n {\n-\tchar type[20];\n+\tenum object_type type;\n \tvoid *buffer;\n \tunsigned long size;\n \tint ret;\n \n \tif (item->object.parsed)\n \t\treturn 0;\n-\tbuffer = read_sha1_file(item->object.sha1, type, &size);\n+\tbuffer = read_sha1_file(item->object.sha1, &type, &size);\n \tif (!buffer)\n \t\treturn error(\"Could not read %s\",\n \t\t\t     sha1_to_hex(item->object.sha1));\n-\tif (strcmp(type, commit_type)) {\n+\tif (type != OBJ_COMMIT) {\n \t\tfree(buffer);\n \t\treturn error(\"Object %s not a commit\",\n \t\t\t     sha1_to_hex(item->object.sha1));\ndiff --git a/convert-objects.c b/convert-objects.c\nindex a630132..b5f41ae 100644\n--- a/convert-objects.c\n+++ b/convert-objects.c\n@@ -284,27 +284,27 @@ static void convert_commit(void *buffer, unsigned long size, unsigned char *resu\n static struct entry * convert_entry(unsigned char *sha1)\n {\n \tstruct entry *entry = lookup_entry(sha1);\n-\tchar type[20];\n+\tenum object_type type;\n \tvoid *buffer, *data;\n \tunsigned long size;\n \n \tif (entry->converted)\n \t\treturn entry;\n-\tdata = read_sha1_file(sha1, type, &size);\n+\tdata = read_sha1_file(sha1, &type, &size);\n \tif (!data)\n \t\tdie(\"unable to read object %s\", sha1_to_hex(sha1));\n \n \tbuffer = xmalloc(size);\n \tmemcpy(buffer, data, size);\n \n-\tif (!strcmp(type, blob_type)) {\n+\tif (type == OBJ_BLOB) {\n \t\twrite_sha1_file(buffer, size, blob_type, entry->new_sha1);\n-\t} else if (!strcmp(type, tree_type))\n+\t} else if (type == OBJ_TREE)\n \t\tconvert_tree(buffer, size, entry->new_sha1);\n-\telse if (!strcmp(type, commit_type))\n+\telse if (type == OBJ_COMMIT)\n \t\tconvert_commit(buffer, size, entry->new_sha1);\n \telse\n-\t\tdie(\"unknown object type '%s' in %s\", type, sha1_to_hex(sha1));\n+\t\tdie(\"unknown object type %d in %s\", type, sha1_to_hex(sha1));\n \tentry->converted = 1;\n \tfree(buffer);\n \tfree(data);\ndiff --git a/diff.c b/diff.c\nindex 6bd456e..f097626 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -1430,7 +1430,7 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)\n \t\t}\n \t}\n \telse {\n-\t\tchar type[20];\n+\t\tenum object_type type;\n \t\tstruct sha1_size_cache *e;\n \n \t\tif (size_only) {\n@@ -1439,11 +1439,12 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)\n \t\t\t\ts->size = e->size;\n \t\t\t\treturn 0;\n \t\t\t}\n-\t\t\tif (!sha1_object_info(s->sha1, type, &s->size))\n+\t\t\ttype = sha1_object_info(s->sha1, &s->size);\n+\t\t\tif (type < 0)\n \t\t\t\tlocate_size_cache(s->sha1, 0, s->size);\n \t\t}\n \t\telse {\n-\t\t\ts->data = read_sha1_file(s->sha1, type, &s->size);\n+\t\t\ts->data = read_sha1_file(s->sha1, &type, &s->size);\n \t\t\ts->should_free = 1;\n \t\t}\n \t}\ndiff --git a/entry.c b/entry.c\nindex 472a9ef..21b5f2e 100644\n--- a/entry.c\n+++ b/entry.c\n@@ -68,10 +68,10 @@ static int write_entry(struct cache_entry *ce, char *path, struct checkout *stat\n \tvoid *new;\n \tunsigned long size;\n \tlong wrote;\n-\tchar type[20];\n+\tenum object_type type;\n \n-\tnew = read_sha1_file(ce->sha1, type, &size);\n-\tif (!new || strcmp(type, blob_type)) {\n+\tnew = read_sha1_file(ce->sha1, &type, &size);\n+\tif (!new || type != OBJ_BLOB) {\n \t\tif (new)\n \t\t\tfree(new);\n \t\treturn error(\"git-checkout-index: unable to read sha1 file of %s (%s)\",\ndiff --git a/fast-import.c b/fast-import.c\nindex aa9eac3..65e99c2 100644\n--- a/fast-import.c\n+++ b/fast-import.c\n@@ -1008,11 +1008,11 @@ static void *gfi_unpack_entry(\n \tstruct object_entry *oe,\n \tunsigned long *sizep)\n {\n-\tstatic char type[20];\n+\tenum object_type type;\n \tstruct packed_git *p = all_packs[oe->pack_id];\n \tif (p == pack_data)\n \t\tp->pack_size = pack_size + 20;\n-\treturn unpack_entry(p, oe->offset, type, sizep);\n+\treturn unpack_entry(p, oe->offset, &type, sizep);\n }\n \n static const char *get_mode(const char *str, uint16_t *modep)\n@@ -1049,9 +1049,9 @@ static void load_tree(struct tree_entry *root)\n \t\tt->delta_depth = 0;\n \t\tbuf = gfi_unpack_entry(myoe, &size);\n \t} else {\n-\t\tchar type[20];\n-\t\tbuf = read_sha1_file(sha1, type, &size);\n-\t\tif (!buf || strcmp(type, tree_type))\n+\t\tenum object_type type;\n+\t\tbuf = read_sha1_file(sha1, &type, &size);\n+\t\tif (!buf || type != OBJ_TREE)\n \t\t\tdie(\"Can't load tree %s\", sha1_to_hex(sha1));\n \t}\n \n@@ -1573,7 +1573,6 @@ static void file_change_m(struct branch *b)\n \tstruct object_entry *oe = oe;\n \tunsigned char sha1[20];\n \tuint16_t mode, inline_data = 0;\n-\tchar type[20];\n \n \tp = get_mode(p, &mode);\n \tif (!p)\n@@ -1628,11 +1627,12 @@ static void file_change_m(struct branch *b)\n \t\t\tdie(\"Not a blob (actually a %s): %s\",\n \t\t\t\tcommand_buf.buf, typename(oe->type));\n \t} else {\n-\t\tif (sha1_object_info(sha1, type, NULL))\n+\t\tenum object_type type = sha1_object_info(sha1, NULL);\n+\t\tif (type < 0)\n \t\t\tdie(\"Blob not found: %s\", command_buf.buf);\n-\t\tif (strcmp(blob_type, type))\n+\t\tif (type != OBJ_BLOB)\n \t\t\tdie(\"Not a blob (actually a %s): %s\",\n-\t\t\t\tcommand_buf.buf, type);\n+\t\t\t    typename(type), command_buf.buf);\n \t}\n \n \ttree_content_set(&b->branch_tree, p, sha1, S_IFREG | mode);\ndiff --git a/http-push.c b/http-push.c\nindex 9ad6fd0..0fd73db 100644\n--- a/http-push.c\n+++ b/http-push.c\n@@ -479,7 +479,7 @@ static void start_put(struct transfer_request *request)\n \tchar *hex = sha1_to_hex(request->obj->sha1);\n \tstruct active_request_slot *slot;\n \tchar *posn;\n-\tchar type[20];\n+\tenum object_type type;\n \tchar hdr[50];\n \tvoid *unpacked;\n \tunsigned long len;\n@@ -487,8 +487,8 @@ static void start_put(struct transfer_request *request)\n \tssize_t size;\n \tz_stream stream;\n \n-\tunpacked = read_sha1_file(request->obj->sha1, type, &len);\n-\thdrlen = sprintf(hdr, \"%s %lu\", type, len) + 1;\n+\tunpacked = read_sha1_file(request->obj->sha1, &type, &len);\n+\thdrlen = sprintf(hdr, \"%s %lu\", typename(type), len) + 1;\n \n \t/* Set it up */\n \tmemset(&stream, 0, sizeof(stream));\ndiff --git a/index-pack.c b/index-pack.c\nindex c25cd40..859ec01 100644\n--- a/index-pack.c\n+++ b/index-pack.c\n@@ -596,25 +596,23 @@ static void fix_unresolved_deltas(int nr_unresolved)\n \t\tstruct delta_entry *d = sorted_by_pos[i];\n \t\tvoid *data;\n \t\tunsigned long size;\n-\t\tchar type[10];\n-\t\tenum object_type obj_type;\n+\t\tenum object_type type;\n \t\tint j, first, last;\n \n \t\tif (objects[d->obj_no].real_type != OBJ_REF_DELTA)\n \t\t\tcontinue;\n-\t\tdata = read_sha1_file(d->base.sha1, type, &size);\n+\t\tdata = read_sha1_file(d->base.sha1, &type, &size);\n \t\tif (!data)\n \t\t\tcontinue;\n \n-\t\tobj_type = type_from_string(type);\n \t\tfind_delta_children(&d->base, &first, &last);\n \t\tfor (j = first; j <= last; j++) {\n \t\t\tstruct object_entry *child = objects + deltas[j].obj_no;\n \t\t\tif (child->real_type == OBJ_REF_DELTA)\n-\t\t\t\tresolve_delta(child, data, size, obj_type);\n+\t\t\t\tresolve_delta(child, data, size, type);\n \t\t}\n \n-\t\tappend_obj_to_pack(data, size, obj_type);\n+\t\tappend_obj_to_pack(data, size, type);\n \t\tfree(data);\n \t\tif (verbose)\n \t\t\tpercent = display_progress(nr_resolved_deltas,\ndiff --git a/merge-file.c b/merge-file.c\nindex 69dc1eb..748d15c 100644\n--- a/merge-file.c\n+++ b/merge-file.c\n@@ -7,12 +7,12 @@ static int fill_mmfile_blob(mmfile_t *f, struct blob *obj)\n {\n \tvoid *buf;\n \tunsigned long size;\n-\tchar type[20];\n+\tenum object_type type;\n \n-\tbuf = read_sha1_file(obj->object.sha1, type, &size);\n+\tbuf = read_sha1_file(obj->object.sha1, &type, &size);\n \tif (!buf)\n \t\treturn -1;\n-\tif (strcmp(type, blob_type))\n+\tif (type != OBJ_BLOB)\n \t\treturn -1;\n \tf->ptr = buf;\n \tf->size = size;\n@@ -86,12 +86,12 @@ void *merge_file(struct blob *base, struct blob *our, struct blob *their, unsign\n \t * modified in the other branch!\n \t */\n \tif (!our || !their) {\n-\t\tchar type[20];\n+\t\tenum object_type type;\n \t\tif (base)\n \t\t\treturn NULL;\n \t\tif (!our)\n \t\t\tour = their;\n-\t\treturn read_sha1_file(our->object.sha1, type, size);\n+\t\treturn read_sha1_file(our->object.sha1, &type, size);\n \t}\n \n \tif (fill_mmfile_blob(&f1, our) < 0)\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex 5898942..ec8294d 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -560,14 +560,14 @@ static void update_file_flags(const unsigned char *sha,\n \t\tupdate_wd = 0;\n \n \tif (update_wd) {\n-\t\tchar type[20];\n+\t\tenum object_type type;\n \t\tvoid *buf;\n \t\tunsigned long size;\n \n-\t\tbuf = read_sha1_file(sha, type, &size);\n+\t\tbuf = read_sha1_file(sha, &type, &size);\n \t\tif (!buf)\n \t\t\tdie(\"cannot read object %s '%s'\", sha1_to_hex(sha), path);\n-\t\tif (strcmp(type, blob_type) != 0)\n+\t\tif (type != OBJ_BLOB)\n \t\t\tdie(\"blob expected for %s '%s'\", sha1_to_hex(sha), path);\n \n \t\tif (S_ISREG(mode)) {\n@@ -620,7 +620,7 @@ struct merge_file_info\n static void fill_mm(const unsigned char *sha1, mmfile_t *mm)\n {\n \tunsigned long size;\n-\tchar type[20];\n+\tenum object_type type;\n \n \tif (!hashcmp(sha1, null_sha1)) {\n \t\tmm->ptr = xstrdup(\"\");\n@@ -628,8 +628,8 @@ static void fill_mm(const unsigned char *sha1, mmfile_t *mm)\n \t\treturn;\n \t}\n \n-\tmm->ptr = read_sha1_file(sha1, type, &size);\n-\tif (!mm->ptr || strcmp(type, blob_type))\n+\tmm->ptr = read_sha1_file(sha1, &type, &size);\n+\tif (!mm->ptr || type != OBJ_BLOB)\n \t\tdie(\"unable to read blob object %s\", sha1_to_hex(sha1));\n \tmm->size = size;\n }\n@@ -1213,7 +1213,7 @@ static int merge(struct commit *h1,\n \n \t\ttree->object.parsed = 1;\n \t\ttree->object.type = OBJ_TREE;\n-\t\tpretend_sha1_file(NULL, 0, tree_type, tree->object.sha1);\n+\t\tpretend_sha1_file(NULL, 0, OBJ_TREE, tree->object.sha1);\n \t\tmerged_common_ancestors = make_virtual_commit(tree, \"ancestor\");\n \t}\n \ndiff --git a/merge-tree.c b/merge-tree.c\nindex 692ede0..b2867ba 100644\n--- a/merge-tree.c\n+++ b/merge-tree.c\n@@ -57,11 +57,11 @@ extern void *merge_file(struct blob *, struct blob *, struct blob *, unsigned lo\n \n static void *result(struct merge_list *entry, unsigned long *size)\n {\n-\tchar type[20];\n+\tenum object_type type;\n \tstruct blob *base, *our, *their;\n \n \tif (!entry->stage)\n-\t\treturn read_sha1_file(entry->blob->object.sha1, type, size);\n+\t\treturn read_sha1_file(entry->blob->object.sha1, &type, size);\n \tbase = NULL;\n \tif (entry->stage == 1) {\n \t\tbase = entry->blob;\n@@ -80,10 +80,10 @@ static void *result(struct merge_list *entry, unsigned long *size)\n \n static void *origin(struct merge_list *entry, unsigned long *size)\n {\n-\tchar type[20];\n+\tenum object_type type;\n \twhile (entry) {\n \t\tif (entry->stage == 2)\n-\t\t\treturn read_sha1_file(entry->blob->object.sha1, type, size);\n+\t\t\treturn read_sha1_file(entry->blob->object.sha1, &type, size);\n \t\tentry = entry->link;\n \t}\n \treturn NULL;\ndiff --git a/mktag.c b/mktag.c\nindex 3448a5d..9310111 100644\n--- a/mktag.c\n+++ b/mktag.c\n@@ -27,13 +27,13 @@\n static int verify_object(unsigned char *sha1, const char *expected_type)\n {\n \tint ret = -1;\n-\tchar type[100];\n+\tenum object_type type;\n \tunsigned long size;\n-\tvoid *buffer = read_sha1_file(sha1, type, &size);\n+\tvoid *buffer = read_sha1_file(sha1, &type, &size);\n \n \tif (buffer) {\n-\t\tif (!strcmp(type, expected_type))\n-\t\t\tret = check_sha1_signature(sha1, buffer, size, type);\n+\t\tif (type == type_from_string(expected_type))\n+\t\t\tret = check_sha1_signature(sha1, buffer, size, expected_type);\n \t\tfree(buffer);\n \t}\n \treturn ret;\ndiff --git a/mktree.c b/mktree.c\nindex 56205d1..d86dde8 100644\n--- a/mktree.c\n+++ b/mktree.c\n@@ -95,7 +95,7 @@ int main(int ac, char **av)\n \t\tint len;\n \t\tchar *ptr, *ntr;\n \t\tunsigned mode;\n-\t\tchar type[20];\n+\t\tenum object_type type;\n \t\tchar *path;\n \n \t\tread_line(&sb, stdin, line_termination);\n@@ -115,11 +115,12 @@ int main(int ac, char **av)\n \t\t    ntr[41] != '\\t' ||\n \t\t    get_sha1_hex(ntr + 1, sha1))\n \t\t\tdie(\"input format error: %s\", sb.buf);\n-\t\tif (sha1_object_info(sha1, type, NULL))\n+\t\ttype = sha1_object_info(sha1, NULL);\n+\t\tif (type < 0)\n \t\t\tdie(\"object %s unavailable\", sha1_to_hex(sha1));\n \t\t*ntr++ = 0; /* now at the beginning of SHA1 */\n-\t\tif (strcmp(ptr, type))\n-\t\t\tdie(\"object type %s mismatch (%s)\", ptr, type);\n+\t\tif (type != type_from_string(ptr))\n+\t\t\tdie(\"object type %s mismatch (%s)\", ptr, typename(type));\n \t\tntr += 41; /* at the beginning of name */\n \t\tif (line_termination && ntr[0] == '\"')\n \t\t\tpath = unquote_c_style(ntr, NULL);\ndiff --git a/object.c b/object.c\nindex 37cedc0..0e67af3 100644\n--- a/object.c\n+++ b/object.c\n@@ -158,23 +158,23 @@ struct object *lookup_unknown_object(const unsigned char *sha1)\n \treturn obj;\n }\n \n-struct object *parse_object_buffer(const unsigned char *sha1, const char *type, unsigned long size, void *buffer, int *eaten_p)\n+struct object *parse_object_buffer(const unsigned char *sha1, enum object_type type, unsigned long size, void *buffer, int *eaten_p)\n {\n \tstruct object *obj;\n \tint eaten = 0;\n \n-\tif (!strcmp(type, blob_type)) {\n+\tif (type == OBJ_BLOB) {\n \t\tstruct blob *blob = lookup_blob(sha1);\n \t\tparse_blob_buffer(blob, buffer, size);\n \t\tobj = &blob->object;\n-\t} else if (!strcmp(type, tree_type)) {\n+\t} else if (type == OBJ_TREE) {\n \t\tstruct tree *tree = lookup_tree(sha1);\n \t\tobj = &tree->object;\n \t\tif (!tree->object.parsed) {\n \t\t\tparse_tree_buffer(tree, buffer, size);\n \t\t\teaten = 1;\n \t\t}\n-\t} else if (!strcmp(type, commit_type)) {\n+\t} else if (type == OBJ_COMMIT) {\n \t\tstruct commit *commit = lookup_commit(sha1);\n \t\tparse_commit_buffer(commit, buffer, size);\n \t\tif (!commit->buffer) {\n@@ -182,7 +182,7 @@ struct object *parse_object_buffer(const unsigned char *sha1, const char *type,\n \t\t\teaten = 1;\n \t\t}\n \t\tobj = &commit->object;\n-\t} else if (!strcmp(type, tag_type)) {\n+\t} else if (type == OBJ_TAG) {\n \t\tstruct tag *tag = lookup_tag(sha1);\n \t\tparse_tag_buffer(tag, buffer, size);\n \t\tobj = &tag->object;\n@@ -196,13 +196,13 @@ struct object *parse_object_buffer(const unsigned char *sha1, const char *type,\n struct object *parse_object(const unsigned char *sha1)\n {\n \tunsigned long size;\n-\tchar type[20];\n+\tenum object_type type;\n \tint eaten;\n-\tvoid *buffer = read_sha1_file(sha1, type, &size);\n+\tvoid *buffer = read_sha1_file(sha1, &type, &size);\n \n \tif (buffer) {\n \t\tstruct object *obj;\n-\t\tif (check_sha1_signature(sha1, buffer, size, type) < 0)\n+\t\tif (check_sha1_signature(sha1, buffer, size, typename(type)) < 0)\n \t\t\tprintf(\"sha1 mismatch %s\\n\", sha1_to_hex(sha1));\n \n \t\tobj = parse_object_buffer(sha1, type, size, buffer, &eaten);\ndiff --git a/object.h b/object.h\nindex ade4dae..749a6f5 100644\n--- a/object.h\n+++ b/object.h\n@@ -59,7 +59,7 @@ struct object *parse_object(const unsigned char *sha1);\n  * parsing it.  eaten_p indicates if the object has a borrowed copy\n  * of buffer and the caller should not free() it.\n  */\n-struct object *parse_object_buffer(const unsigned char *sha1, const char *type, unsigned long size, void *buffer, int *eaten_p);\n+struct object *parse_object_buffer(const unsigned char *sha1, enum object_type type, unsigned long size, void *buffer, int *eaten_p);\n \n /** Returns the object, with potentially excess memory allocated. **/\n struct object *lookup_unknown_object(const unsigned  char *sha1);\ndiff --git a/pack-check.c b/pack-check.c\nindex 08a9fd8..ac7751d 100644\n--- a/pack-check.c\n+++ b/pack-check.c\n@@ -43,7 +43,7 @@ static int verify_packfile(struct packed_git *p,\n \tfor (i = err = 0; i < nr_objects; i++) {\n \t\tunsigned char sha1[20];\n \t\tvoid *data;\n-\t\tchar type[20];\n+\t\tenum object_type type;;\n \t\tunsigned long size, offset;\n \n \t\tif (nth_packed_object_sha1(p, i, sha1))\n@@ -51,13 +51,13 @@ static int verify_packfile(struct packed_git *p,\n \t\toffset = find_pack_entry_one(sha1, p);\n \t\tif (!offset)\n \t\t\tdie(\"internal error pack-check find-pack-entry-one\");\n-\t\tdata = unpack_entry(p, offset, type, &size);\n+\t\tdata = unpack_entry(p, offset, &type, &size);\n \t\tif (!data) {\n \t\t\terr = error(\"cannot unpack %s from %s\",\n \t\t\t\t    sha1_to_hex(sha1), p->pack_name);\n \t\t\tcontinue;\n \t\t}\n-\t\tif (check_sha1_signature(sha1, data, size, type)) {\n+\t\tif (check_sha1_signature(sha1, data, size, typename(type))) {\n \t\t\terr = error(\"packed %s from %s is corrupt\",\n \t\t\t\t    sha1_to_hex(sha1), p->pack_name);\n \t\t\tfree(data);\n@@ -82,7 +82,7 @@ static void show_pack_info(struct packed_git *p)\n \n \tfor (i = 0; i < nr_objects; i++) {\n \t\tunsigned char sha1[20], base_sha1[20];\n-\t\tchar type[20];\n+\t\tconst char *type;\n \t\tunsigned long size;\n \t\tunsigned long store_size;\n \t\tunsigned long offset;\n@@ -94,9 +94,9 @@ static void show_pack_info(struct packed_git *p)\n \t\tif (!offset)\n \t\t\tdie(\"internal error pack-check find-pack-entry-one\");\n \n-\t\tpacked_object_info_detail(p, offset, type, &size, &store_size,\n-\t\t\t\t\t  &delta_chain_length,\n-\t\t\t\t\t  base_sha1);\n+\t\ttype = packed_object_info_detail(p, offset, &size, &store_size,\n+\t\t\t\t\t\t &delta_chain_length,\n+\t\t\t\t\t\t base_sha1);\n \t\tprintf(\"%s \", sha1_to_hex(sha1));\n \t\tif (!delta_chain_length)\n \t\t\tprintf(\"%-6s %lu %lu\\n\", type, size, offset);\ndiff --git a/read-cache.c b/read-cache.c\nindex 605b352..d637464 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -72,7 +72,7 @@ static int ce_compare_link(struct cache_entry *ce, unsigned long expected_size)\n \tchar *target;\n \tvoid *buffer;\n \tunsigned long size;\n-\tchar type[10];\n+\tenum object_type type;\n \tint len;\n \n \ttarget = xmalloc(expected_size);\n@@ -81,7 +81,7 @@ static int ce_compare_link(struct cache_entry *ce, unsigned long expected_size)\n \t\tfree(target);\n \t\treturn -1;\n \t}\n-\tbuffer = read_sha1_file(ce->sha1, type, &size);\n+\tbuffer = read_sha1_file(ce->sha1, &type, &size);\n \tif (!buffer) {\n \t\tfree(target);\n \t\treturn -1;\ndiff --git a/sha1_file.c b/sha1_file.c\nindex 423ff0a..136e79b 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -983,8 +983,9 @@ static void *unpack_sha1_rest(z_stream *stream, void *buffer, unsigned long size\n  * too permissive for what we want to check. So do an anal\n  * object header parse by hand.\n  */\n-static int parse_sha1_header(char *hdr, char *type, unsigned long *sizep)\n+static int parse_sha1_header(const char *hdr, unsigned long *sizep)\n {\n+\tchar type[10];\n \tint i;\n \tunsigned long size;\n \n@@ -993,16 +994,16 @@ static int parse_sha1_header(char *hdr, char *type, unsigned long *sizep)\n \t * terminating '\\0' that we add), and is followed by\n \t * a space. \n \t */\n-\ti = 10;\n+\ti = 0;\n \tfor (;;) {\n \t\tchar c = *hdr++;\n \t\tif (c == ' ')\n \t\t\tbreak;\n-\t\tif (!--i)\n+\t\ttype[i++] = c;\n+\t\tif (i >= sizeof(type))\n \t\t\treturn -1;\n-\t\t*type++ = c;\n \t}\n-\t*type = 0;\n+\ttype[i] = 0;\n \n \t/*\n \t * The length must follow immediately, and be in canonical\n@@ -1025,17 +1026,17 @@ static int parse_sha1_header(char *hdr, char *type, unsigned long *sizep)\n \t/*\n \t * The length must be followed by a zero byte\n \t */\n-\treturn *hdr ? -1 : 0;\n+\treturn *hdr ? -1 : type_from_string(type);\n }\n \n-void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned long *size)\n+void * unpack_sha1_file(void *map, unsigned long mapsize, enum object_type *type, unsigned long *size)\n {\n \tint ret;\n \tz_stream stream;\n \tchar hdr[8192];\n \n \tret = unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr));\n-\tif (ret < Z_OK || parse_sha1_header(hdr, type, size) < 0)\n+\tif (ret < Z_OK || (*type = parse_sha1_header(hdr, size)) < 0)\n \t\treturn NULL;\n \n \treturn unpack_sha1_rest(&stream, hdr, *size);\n@@ -1044,7 +1045,7 @@ void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned l\n static unsigned long get_delta_base(struct packed_git *p,\n \t\t\t\t    struct pack_window **w_curs,\n \t\t\t\t    unsigned long *curpos,\n-\t\t\t\t    enum object_type kind,\n+\t\t\t\t    enum object_type type,\n \t\t\t\t    unsigned long delta_obj_offset)\n {\n \tunsigned char *base_info = use_pack(p, w_curs, *curpos, NULL);\n@@ -1056,7 +1057,7 @@ static unsigned long get_delta_base(struct packed_git *p,\n \t * that is assured.  An OFS_DELTA longer than the hash size\n \t * is stupid, as then a REF_DELTA would be smaller to store.\n \t */\n-\tif (kind == OBJ_OFS_DELTA) {\n+\tif (type == OBJ_OFS_DELTA) {\n \t\tunsigned used = 0;\n \t\tunsigned char c = base_info[used++];\n \t\tbase_offset = c & 127;\n@@ -1071,7 +1072,7 @@ static unsigned long get_delta_base(struct packed_git *p,\n \t\tif (base_offset >= delta_obj_offset)\n \t\t\tdie(\"delta base offset out of bound\");\n \t\t*curpos += used;\n-\t} else if (kind == OBJ_REF_DELTA) {\n+\t} else if (type == OBJ_REF_DELTA) {\n \t\t/* The base entry _must_ be in the same pack */\n \t\tbase_offset = find_pack_entry_one(base_info, p);\n \t\tif (!base_offset)\n@@ -1085,28 +1086,25 @@ static unsigned long get_delta_base(struct packed_git *p,\n \n /* forward declaration for a mutually recursive function */\n static int packed_object_info(struct packed_git *p, unsigned long offset,\n-\t\t\t      char *type, unsigned long *sizep);\n+\t\t\t      unsigned long *sizep);\n \n static int packed_delta_info(struct packed_git *p,\n \t\t\t     struct pack_window **w_curs,\n \t\t\t     unsigned long curpos,\n-\t\t\t     enum object_type kind,\n+\t\t\t     enum object_type type,\n \t\t\t     unsigned long obj_offset,\n-\t\t\t     char *type,\n \t\t\t     unsigned long *sizep)\n {\n \tunsigned long base_offset;\n-\n-\tbase_offset = get_delta_base(p, w_curs, &curpos, kind, obj_offset);\n+\t\n+\tbase_offset = get_delta_base(p, w_curs, &curpos, type, obj_offset);\n+\ttype = packed_object_info(p, base_offset, NULL);\n \n \t/* We choose to only get the type of the base object and\n \t * ignore potentially corrupt pack file that expects the delta\n \t * based on a base with a wrong size.  This saves tons of\n \t * inflate() calls.\n \t */\n-\tif (packed_object_info(p, base_offset, type, NULL))\n-\t\tdie(\"cannot get info for delta-pack base\");\n-\n \tif (sizep) {\n \t\tconst unsigned char *data;\n \t\tunsigned char delta_head[20], *in;\n@@ -1141,7 +1139,8 @@ static int packed_delta_info(struct packed_git *p,\n \t\t/* Read the result size */\n \t\t*sizep = get_delta_hdr_size(&data, delta_head+sizeof(delta_head));\n \t}\n-\treturn 0;\n+\n+\treturn type;\n }\n \n static int unpack_object_header(struct packed_git *p,\n@@ -1169,38 +1168,36 @@ static int unpack_object_header(struct packed_git *p,\n \treturn type;\n }\n \n-void packed_object_info_detail(struct packed_git *p,\n-\t\t\t       unsigned long obj_offset,\n-\t\t\t       char *type,\n-\t\t\t       unsigned long *size,\n-\t\t\t       unsigned long *store_size,\n-\t\t\t       unsigned int *delta_chain_length,\n-\t\t\t       unsigned char *base_sha1)\n+const char *packed_object_info_detail(struct packed_git *p,\n+\t\t\t\t      unsigned long obj_offset,\n+\t\t\t\t      unsigned long *size,\n+\t\t\t\t      unsigned long *store_size,\n+\t\t\t\t      unsigned int *delta_chain_length,\n+\t\t\t\t      unsigned char *base_sha1)\n {\n \tstruct pack_window *w_curs = NULL;\n \tunsigned long curpos, dummy;\n \tunsigned char *next_sha1;\n-\tenum object_type kind;\n+\tenum object_type type;\n \n \t*delta_chain_length = 0;\n \tcurpos = obj_offset;\n-\tkind = unpack_object_header(p, &w_curs, &curpos, size);\n+\ttype = unpack_object_header(p, &w_curs, &curpos, size);\n \n \tfor (;;) {\n-\t\tswitch (kind) {\n+\t\tswitch (type) {\n \t\tdefault:\n \t\t\tdie(\"pack %s contains unknown object type %d\",\n-\t\t\t    p->pack_name, kind);\n+\t\t\t    p->pack_name, type);\n \t\tcase OBJ_COMMIT:\n \t\tcase OBJ_TREE:\n \t\tcase OBJ_BLOB:\n \t\tcase OBJ_TAG:\n-\t\t\tstrcpy(type, typename(kind));\n \t\t\t*store_size = 0; /* notyet */\n \t\t\tunuse_pack(&w_curs);\n-\t\t\treturn;\n+\t\t\treturn typename(type);\n \t\tcase OBJ_OFS_DELTA:\n-\t\t\tobj_offset = get_delta_base(p, &w_curs, &curpos, kind, obj_offset);\n+\t\t\tobj_offset = get_delta_base(p, &w_curs, &curpos, type, obj_offset);\n \t\t\tif (*delta_chain_length == 0) {\n \t\t\t\t/* TODO: find base_sha1 as pointed by curpos */\n \t\t\t}\n@@ -1214,39 +1211,38 @@ void packed_object_info_detail(struct packed_git *p,\n \t\t}\n \t\t(*delta_chain_length)++;\n \t\tcurpos = obj_offset;\n-\t\tkind = unpack_object_header(p, &w_curs, &curpos, &dummy);\n+\t\ttype = unpack_object_header(p, &w_curs, &curpos, &dummy);\n \t}\n }\n \n static int packed_object_info(struct packed_git *p, unsigned long obj_offset,\n-\t\t\t      char *type, unsigned long *sizep)\n+\t\t\t      unsigned long *sizep)\n {\n \tstruct pack_window *w_curs = NULL;\n \tunsigned long size, curpos = obj_offset;\n-\tenum object_type kind;\n+\tenum object_type type;\n \n-\tkind = unpack_object_header(p, &w_curs, &curpos, &size);\n+\ttype = unpack_object_header(p, &w_curs, &curpos, &size);\n \n-\tswitch (kind) {\n+\tswitch (type) {\n \tcase OBJ_OFS_DELTA:\n \tcase OBJ_REF_DELTA:\n-\t\tpacked_delta_info(p, &w_curs, curpos, kind,\n-\t\t\t\t  obj_offset, type, sizep);\n+\t\ttype = packed_delta_info(p, &w_curs, curpos,\n+\t\t\t\t\t type, obj_offset, sizep);\n \t\tbreak;\n \tcase OBJ_COMMIT:\n \tcase OBJ_TREE:\n \tcase OBJ_BLOB:\n \tcase OBJ_TAG:\n-\t\tstrcpy(type, typename(kind));\n \t\tif (sizep)\n \t\t\t*sizep = size;\n \t\tbreak;\n \tdefault:\n \t\tdie(\"pack %s contains unknown object type %d\",\n-\t\t    p->pack_name, kind);\n+\t\t    p->pack_name, type);\n \t}\n \tunuse_pack(&w_curs);\n-\treturn 0;\n+\treturn type;\n }\n \n static void *unpack_compressed_entry(struct packed_git *p,\n@@ -1284,15 +1280,14 @@ static void *unpack_delta_entry(struct packed_git *p,\n \t\t\t\tstruct pack_window **w_curs,\n \t\t\t\tunsigned long curpos,\n \t\t\t\tunsigned long delta_size,\n-\t\t\t\tenum object_type kind,\n \t\t\t\tunsigned long obj_offset,\n-\t\t\t\tchar *type,\n+\t\t\t\tenum object_type *type,\n \t\t\t\tunsigned long *sizep)\n {\n \tvoid *delta_data, *result, *base;\n-\tunsigned long result_size, base_size, base_offset;\n+\tunsigned long base_size, base_offset;\n \n-\tbase_offset = get_delta_base(p, w_curs, &curpos, kind, obj_offset);\n+\tbase_offset = get_delta_base(p, w_curs, &curpos, *type, obj_offset);\n \tbase = unpack_entry(p, base_offset, type, &base_size);\n \tif (!base)\n \t\tdie(\"failed to read delta base object at %lu from %s\",\n@@ -1301,43 +1296,39 @@ static void *unpack_delta_entry(struct packed_git *p,\n \tdelta_data = unpack_compressed_entry(p, w_curs, curpos, delta_size);\n \tresult = patch_delta(base, base_size,\n \t\t\t     delta_data, delta_size,\n-\t\t\t     &result_size);\n+\t\t\t     sizep);\n \tif (!result)\n \t\tdie(\"failed to apply delta\");\n \tfree(delta_data);\n \tfree(base);\n-\t*sizep = result_size;\n \treturn result;\n }\n \n void *unpack_entry(struct packed_git *p, unsigned long obj_offset,\n-\t\t   char *type, unsigned long *sizep)\n+\t\t   enum object_type *type, unsigned long *sizep)\n {\n \tstruct pack_window *w_curs = NULL;\n-\tunsigned long size, curpos = obj_offset;\n-\tenum object_type kind;\n-\tvoid *retval;\n+\tunsigned long curpos = obj_offset;\n+\tvoid *data;\n \n-\tkind = unpack_object_header(p, &w_curs, &curpos, &size);\n-\tswitch (kind) {\n+\t*type = unpack_object_header(p, &w_curs, &curpos, sizep);\n+\tswitch (*type) {\n \tcase OBJ_OFS_DELTA:\n \tcase OBJ_REF_DELTA:\n-\t\tretval = unpack_delta_entry(p, &w_curs, curpos, size,\n-\t\t\tkind, obj_offset, type, sizep);\n+\t\tdata = unpack_delta_entry(p, &w_curs, curpos, *sizep,\n+\t\t\t\t\t  obj_offset, type, sizep);\n \t\tbreak;\n \tcase OBJ_COMMIT:\n \tcase OBJ_TREE:\n \tcase OBJ_BLOB:\n \tcase OBJ_TAG:\n-\t\tstrcpy(type, typename(kind));\n-\t\t*sizep = size;\n-\t\tretval = unpack_compressed_entry(p, &w_curs, curpos, size);\n+\t\tdata = unpack_compressed_entry(p, &w_curs, curpos, *sizep);\n \t\tbreak;\n \tdefault:\n-\t\tdie(\"unknown object type %i in %s\", kind, p->pack_name);\n+\t\tdie(\"unknown object type %i in %s\", *type, p->pack_name);\n \t}\n \tunuse_pack(&w_curs);\n-\treturn retval;\n+\treturn data;\n }\n \n int num_packed_objects(const struct packed_git *p)\n@@ -1447,7 +1438,7 @@ struct packed_git *find_sha1_pack(const unsigned char *sha1,\n \t\n }\n \n-static int sha1_loose_object_info(const unsigned char *sha1, char *type, unsigned long *sizep)\n+static int sha1_loose_object_info(const unsigned char *sha1, unsigned long *sizep)\n {\n \tint status;\n \tunsigned long mapsize, size;\n@@ -1461,31 +1452,29 @@ static int sha1_loose_object_info(const unsigned char *sha1, char *type, unsigne\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 (parse_sha1_header(hdr, type, &size) < 0)\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 {\n-\t\tstatus = 0;\n-\t\tif (sizep)\n-\t\t\t*sizep = size;\n-\t}\n+\telse if (sizep)\n+\t\t*sizep = size;\n \tinflateEnd(&stream);\n \tmunmap(map, mapsize);\n \treturn status;\n }\n \n-int sha1_object_info(const unsigned char *sha1, char *type, unsigned long *sizep)\n+int sha1_object_info(const unsigned char *sha1, unsigned long *sizep)\n {\n \tstruct pack_entry e;\n \n \tif (!find_pack_entry(sha1, &e, NULL)) {\n \t\treprepare_packed_git();\n \t\tif (!find_pack_entry(sha1, &e, NULL))\n-\t\t\treturn sha1_loose_object_info(sha1, type, sizep);\n+\t\t\treturn sha1_loose_object_info(sha1, sizep);\n \t}\n-\treturn packed_object_info(e.p, e.offset, type, sizep);\n+\treturn packed_object_info(e.p, e.offset, sizep);\n }\n \n-static void *read_packed_sha1(const unsigned char *sha1, char *type, unsigned long *size)\n+static void *read_packed_sha1(const unsigned char *sha1,\n+\t\t\t      enum object_type *type, unsigned long *size)\n {\n \tstruct pack_entry e;\n \n@@ -1503,7 +1492,7 @@ static void *read_packed_sha1(const unsigned char *sha1, char *type, unsigned lo\n  */\n static struct cached_object {\n \tunsigned char sha1[20];\n-\tconst char *type;\n+\tenum object_type type;\n \tvoid *buf;\n \tunsigned long size;\n } *cached_objects;\n@@ -1521,11 +1510,12 @@ static struct cached_object *find_cached_object(const unsigned char *sha1)\n \treturn NULL;\n }\n \n-int pretend_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *sha1)\n+int pretend_sha1_file(void *buf, unsigned long len, enum object_type type,\n+\t\t      unsigned char *sha1)\n {\n \tstruct cached_object *co;\n \n-\thash_sha1_file(buf, len, type, sha1);\n+\thash_sha1_file(buf, len, typename(type), sha1);\n \tif (has_sha1_file(sha1) || find_cached_object(sha1))\n \t\treturn 0;\n \tif (cached_object_alloc <= cached_object_nr) {\n@@ -1536,14 +1526,15 @@ int pretend_sha1_file(void *buf, unsigned long len, const char *type, unsigned c\n \t}\n \tco = &cached_objects[cached_object_nr++];\n \tco->size = len;\n-\tco->type = strdup(type);\n+\tco->type = type;\n \tco->buf = xmalloc(len);\n \tmemcpy(co->buf, buf, len);\n \thashcpy(co->sha1, sha1);\n \treturn 0;\n }\n \n-void *read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size)\n+void *read_sha1_file(const unsigned char *sha1, enum object_type *type,\n+\t\t     unsigned long *size)\n {\n \tunsigned long mapsize;\n \tvoid *map, *buf;\n@@ -1554,7 +1545,7 @@ void *read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size)\n \t\tbuf = xmalloc(co->size + 1);\n \t\tmemcpy(buf, co->buf, co->size);\n \t\t((char*)buf)[co->size] = 0;\n-\t\tstrcpy(type, co->type);\n+\t\t*type = co->type;\n \t\t*size = co->size;\n \t\treturn buf;\n \t}\n@@ -1573,33 +1564,34 @@ void *read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size)\n }\n \n void *read_object_with_reference(const unsigned char *sha1,\n-\t\t\t\t const char *required_type,\n+\t\t\t\t const char *required_type_name,\n \t\t\t\t unsigned long *size,\n \t\t\t\t unsigned char *actual_sha1_return)\n {\n-\tchar type[20];\n+\tenum object_type type, required_type;\n \tvoid *buffer;\n \tunsigned long isize;\n \tunsigned char actual_sha1[20];\n \n+\trequired_type = type_from_string(required_type_name);\n \thashcpy(actual_sha1, sha1);\n \twhile (1) {\n \t\tint ref_length = -1;\n \t\tconst char *ref_type = NULL;\n \n-\t\tbuffer = read_sha1_file(actual_sha1, type, &isize);\n+\t\tbuffer = read_sha1_file(actual_sha1, &type, &isize);\n \t\tif (!buffer)\n \t\t\treturn NULL;\n-\t\tif (!strcmp(type, required_type)) {\n+\t\tif (type == required_type) {\n \t\t\t*size = isize;\n \t\t\tif (actual_sha1_return)\n \t\t\t\thashcpy(actual_sha1_return, actual_sha1);\n \t\t\treturn buffer;\n \t\t}\n \t\t/* Handle references */\n-\t\telse if (!strcmp(type, commit_type))\n+\t\telse if (type == OBJ_COMMIT)\n \t\t\tref_type = \"tree \";\n-\t\telse if (!strcmp(type, tag_type))\n+\t\telse if (type == OBJ_TAG)\n \t\t\tref_type = \"object \";\n \t\telse {\n \t\t\tfree(buffer);\n@@ -1841,17 +1833,17 @@ static void *repack_object(const unsigned char *sha1, unsigned long *objsize)\n \tz_stream stream;\n \tunsigned char *unpacked;\n \tunsigned long len;\n-\tchar type[20];\n+\tenum object_type type;;\n \tchar hdr[32];\n \tint hdrlen;\n \tvoid *buf;\n \n \t/* need to unpack and recompress it by itself */\n-\tunpacked = read_packed_sha1(sha1, type, &len);\n+\tunpacked = read_packed_sha1(sha1, &type, &len);\n \tif (!unpacked)\n \t\terror(\"cannot read sha1_file for %s\", sha1_to_hex(sha1));\n \n-\thdrlen = sprintf(hdr, \"%s %lu\", type, len) + 1;\n+\thdrlen = sprintf(hdr, \"%s %lu\", typename(type), len) + 1;\n \n \t/* Set it up */\n \tmemset(&stream, 0, sizeof(stream));\ndiff --git a/tag.c b/tag.c\nindex 864ac1b..30ffc17 100644\n--- a/tag.c\n+++ b/tag.c\n@@ -85,18 +85,18 @@ int parse_tag_buffer(struct tag *item, void *data, unsigned long size)\n \n int parse_tag(struct tag *item)\n {\n-\tchar type[20];\n+\tenum object_type type;\n \tvoid *data;\n \tunsigned long size;\n \tint ret;\n \n \tif (item->object.parsed)\n \t\treturn 0;\n-\tdata = read_sha1_file(item->object.sha1, type, &size);\n+\tdata = read_sha1_file(item->object.sha1, &type, &size);\n \tif (!data)\n \t\treturn error(\"Could not read %s\",\n \t\t\t     sha1_to_hex(item->object.sha1));\n-\tif (strcmp(type, tag_type)) {\n+\tif (type != OBJ_TAG) {\n \t\tfree(data);\n \t\treturn error(\"Object %s not a tag\",\n \t\t\t     sha1_to_hex(item->object.sha1));\ndiff --git a/tree-diff.c b/tree-diff.c\nindex 37d235e..c827582 100644\n--- a/tree-diff.c\n+++ b/tree-diff.c\n@@ -139,13 +139,13 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree\n \tconst unsigned char *sha1 = tree_entry_extract(desc, &path, &mode);\n \n \tif (opt->recursive && S_ISDIR(mode)) {\n-\t\tchar type[20];\n+\t\tenum object_type type;\n \t\tchar *newbase = malloc_base(base, path, strlen(path));\n \t\tstruct tree_desc inner;\n \t\tvoid *tree;\n \n-\t\ttree = read_sha1_file(sha1, type, &inner.size);\n-\t\tif (!tree || strcmp(type, tree_type))\n+\t\ttree = read_sha1_file(sha1, &type, &inner.size);\n+\t\tif (!tree || type != OBJ_TREE)\n \t\t\tdie(\"corrupt tree sha %s\", sha1_to_hex(sha1));\n \n \t\tinner.buf = tree;\ndiff --git a/tree.c b/tree.c\nindex b6f02fe..46923ee 100644\n--- a/tree.c\n+++ b/tree.c\n@@ -190,17 +190,17 @@ int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size)\n \n int parse_tree(struct tree *item)\n {\n-\t char type[20];\n+\t enum object_type type;\n \t void *buffer;\n \t unsigned long size;\n \n \tif (item->object.parsed)\n \t\treturn 0;\n-\tbuffer = read_sha1_file(item->object.sha1, type, &size);\n+\tbuffer = read_sha1_file(item->object.sha1, &type, &size);\n \tif (!buffer)\n \t\treturn error(\"Could not read %s\",\n \t\t\t     sha1_to_hex(item->object.sha1));\n-\tif (strcmp(type, tree_type)) {\n+\tif (type != OBJ_TREE) {\n \t\tfree(buffer);\n \t\treturn error(\"Object %s not a tree\",\n \t\t\t     sha1_to_hex(item->object.sha1));\ndiff --git a/unpack-file.c b/unpack-file.c\nindex d24acc2..25c56b3 100644\n--- a/unpack-file.c\n+++ b/unpack-file.c\n@@ -5,12 +5,12 @@ static char *create_temp_file(unsigned char *sha1)\n {\n \tstatic char path[50];\n \tvoid *buf;\n-\tchar type[100];\n+\tenum object_type type;\n \tunsigned long size;\n \tint fd;\n \n-\tbuf = read_sha1_file(sha1, type, &size);\n-\tif (!buf || strcmp(type, blob_type))\n+\tbuf = read_sha1_file(sha1, &type, &size);\n+\tif (!buf || type != OBJ_BLOB)\n \t\tdie(\"unable to read blob object %s\", sha1_to_hex(sha1));\n \n \tstrcpy(path, \".merge_file_XXXXXX\");\n-- \n1.5.0.572.ge86d\n"},{"id":"35537","messageId":"11725197723910-git-send-email-nico@cam.org","threadId":"6978","inReplyTo":"11725197632516-git-send-email-nico@cam.org","subject":"[PATCH 6/6] get rid of lookup_object_type()","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2007-02-26T19:56:00Z","receivedAt":"2007-02-26T19:56:00Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"This function is called only once in the whole source tree.  Let's move\nits code inline instead, which is also in the spirit of removing as much\nobject type char arrays as possible (not that this patch does anything for\nthat but at least it is now a local matter).\n\nSigned-off-by: Nicolas Pitre <nico@cam.org>\n---\n object.c |   18 ------------------\n object.h |    3 ---\n tag.c    |   21 ++++++++++++++++++---\n 3 files changed, 18 insertions(+), 24 deletions(-)\n\ndiff --git a/object.c b/object.c\nindex 0e67af3..5b46889 100644\n--- a/object.c\n+++ b/object.c\n@@ -120,24 +120,6 @@ void created_object(const unsigned char *sha1, struct object *obj)\n \tnr_objs++;\n }\n \n-struct object *lookup_object_type(const unsigned char *sha1, const char *type)\n-{\n-\tif (!type) {\n-\t\treturn lookup_unknown_object(sha1);\n-\t} else if (!strcmp(type, blob_type)) {\n-\t\treturn &lookup_blob(sha1)->object;\n-\t} else if (!strcmp(type, tree_type)) {\n-\t\treturn &lookup_tree(sha1)->object;\n-\t} else if (!strcmp(type, commit_type)) {\n-\t\treturn &lookup_commit(sha1)->object;\n-\t} else if (!strcmp(type, tag_type)) {\n-\t\treturn &lookup_tag(sha1)->object;\n-\t} else {\n-\t\terror(\"Unknown type %s\", type);\n-\t\treturn NULL;\n-\t}\n-}\n-\n union any_object {\n \tstruct object object;\n \tstruct commit commit;\ndiff --git a/object.h b/object.h\nindex 749a6f5..bdbf0fa 100644\n--- a/object.h\n+++ b/object.h\n@@ -47,9 +47,6 @@ extern struct object_refs *lookup_object_refs(struct object *);\n /** Internal only **/\n struct object *lookup_object(const unsigned char *sha1);\n \n-/** Returns the object, having looked it up as being the given type. **/\n-struct object *lookup_object_type(const unsigned char *sha1, const char *type);\n-\n void created_object(const unsigned char *sha1, struct object *obj);\n \n /** Returns the object, having parsed it to find out what it is. **/\ndiff --git a/tag.c b/tag.c\nindex 30ffc17..56a49f4 100644\n--- a/tag.c\n+++ b/tag.c\n@@ -1,5 +1,8 @@\n #include \"cache.h\"\n #include \"tag.h\"\n+#include \"commit.h\"\n+#include \"tree.h\"\n+#include \"blob.h\"\n \n const char *tag_type = \"tag\";\n \n@@ -37,7 +40,7 @@ struct tag *lookup_tag(const unsigned char *sha1)\n int parse_tag_buffer(struct tag *item, void *data, unsigned long size)\n {\n \tint typelen, taglen;\n-\tunsigned char object[20];\n+\tunsigned char sha1[20];\n \tconst char *type_line, *tag_line, *sig_line;\n \tchar type[20];\n \n@@ -47,7 +50,7 @@ int parse_tag_buffer(struct tag *item, void *data, unsigned long size)\n \n \tif (size < 64)\n \t\treturn -1;\n-\tif (memcmp(\"object \", data, 7) || get_sha1_hex((char *) data + 7, object))\n+\tif (memcmp(\"object \", data, 7) || get_sha1_hex((char *) data + 7, sha1))\n \t\treturn -1;\n \n \ttype_line = (char *) data + 48;\n@@ -73,7 +76,19 @@ int parse_tag_buffer(struct tag *item, void *data, unsigned long size)\n \tmemcpy(item->tag, tag_line + 4, taglen);\n \titem->tag[taglen] = '\\0';\n \n-\titem->tagged = lookup_object_type(object, type);\n+\tif (!strcmp(type, blob_type)) {\n+\t\titem->tagged = &lookup_blob(sha1)->object;\n+\t} else if (!strcmp(type, tree_type)) {\n+\t\titem->tagged = &lookup_tree(sha1)->object;\n+\t} else if (!strcmp(type, commit_type)) {\n+\t\titem->tagged = &lookup_commit(sha1)->object;\n+\t} else if (!strcmp(type, tag_type)) {\n+\t\titem->tagged = &lookup_tag(sha1)->object;\n+\t} else {\n+\t\terror(\"Unknown type %s\", type);\n+\t\titem->tagged = NULL;\n+\t}\n+\n \tif (item->tagged && track_object_refs) {\n \t\tstruct object_refs *refs = alloc_object_refs(1);\n \t\trefs->ref[0] = item->tagged;\n-- \n1.5.0.572.ge86d\n"},{"id":"35586","messageId":"7vejobhor2.fsf@assigned-by-dhcp.cox.net","threadId":"6978","inReplyTo":"11725197632516-git-send-email-nico@cam.org","subject":"Re: [PATCH 5/6] convert object type handling from a string to a number","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-02-27T10:35:29Z","receivedAt":"2007-02-27T10:35:29Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nicolas Pitre <nico@cam.org> writes:\n\n> We currently have two parallel notation for dealing with object types\n> in the code: a string and a numerical value.  One of them is obviously\n> redundent, and the most used one requires more stack space and a bunch\n> of strcmp() all over the place.\n>\n> This is an initial step for the removal of the version using a char array\n> found in object reading code paths.  The patch is unfortunately large but\n> there is no sane way to split it in smaller parts without breaking the\n> system.\n> ...\n> diff --git a/builtin-cat-file.c b/builtin-cat-file.c\n> index 6c16bfa..d61d3d5 100644\n> --- a/builtin-cat-file.c\n> +++ b/builtin-cat-file.c\n> @@ -79,7 +79,7 @@ static void pprint_tag(const unsigned char *sha1, const char *buf, unsigned long\n>  int cmd_cat_file(int argc, const char **argv, const char *prefix)\n>  {\n>  \tunsigned char sha1[20];\n> -\tchar type[20];\n> +\tenum object_type type;\n>  \tvoid *buf;\n>  \tunsigned long size;\n>  \tint opt;\n> ...\n>  \tcase 'p':\n> -\t\tif (sha1_object_info(sha1, type, NULL))\n> +\t\ttype = sha1_object_info(sha1, NULL);\n> +\t\tif (type < 0)\n>  \t\t\tdie(\"Not a valid object name %s\", argv[2]);\n\nI am wondering if \"enum object_type\" and signed comparison here\nare compatible.  sha1_object_info() is of type \"int\" so that is\nclearly signed, but are we safe assuming this would not result\nin \"type is unsigned and condition is always false\"?\n"},{"id":"35588","messageId":"7v8xejhnwd.fsf@assigned-by-dhcp.cox.net","threadId":"6978","inReplyTo":"7vejobhor2.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 5/6] convert object type handling from a string to a number","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-02-27T10:53:54Z","receivedAt":"2007-02-27T10:53:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <junkio@cox.net> writes:\n\n> Nicolas Pitre <nico@cam.org> writes:\n>\n>> We currently have two parallel notation for dealing with object types\n>> in the code: a string and a numerical value.  One of them is obviously\n>> redundent, and the most used one requires more stack space and a bunch\n>> of strcmp() all over the place.\n>>\n>> This is an initial step for the removal of the version using a char array\n>> found in object reading code paths.  The patch is unfortunately large but\n>> there is no sane way to split it in smaller parts without breaking the\n>> system.\n\nWill your next step be to convert write_sha1_file() and friends?\n"},{"id":"35614","messageId":"alpine.LRH.0.82.0702270856360.29426@xanadu.home","threadId":"6978","inReplyTo":"7vejobhor2.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 5/6] convert object type handling from a string to a number","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2007-02-27T13:58:32Z","receivedAt":"2007-02-27T13:58:32Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"On Tue, 27 Feb 2007, Junio C Hamano wrote:\n\n> Nicolas Pitre <nico@cam.org> writes:\n> \n> > We currently have two parallel notation for dealing with object types\n> > in the code: a string and a numerical value.  One of them is obviously\n> > redundent, and the most used one requires more stack space and a bunch\n> > of strcmp() all over the place.\n> >\n> > This is an initial step for the removal of the version using a char array\n> > found in object reading code paths.  The patch is unfortunately large but\n> > there is no sane way to split it in smaller parts without breaking the\n> > system.\n> > ...\n> > diff --git a/builtin-cat-file.c b/builtin-cat-file.c\n> > index 6c16bfa..d61d3d5 100644\n> > --- a/builtin-cat-file.c\n> > +++ b/builtin-cat-file.c\n> > @@ -79,7 +79,7 @@ static void pprint_tag(const unsigned char *sha1, const char *buf, unsigned long\n> >  int cmd_cat_file(int argc, const char **argv, const char *prefix)\n> >  {\n> >  \tunsigned char sha1[20];\n> > -\tchar type[20];\n> > +\tenum object_type type;\n> >  \tvoid *buf;\n> >  \tunsigned long size;\n> >  \tint opt;\n> > ...\n> >  \tcase 'p':\n> > -\t\tif (sha1_object_info(sha1, type, NULL))\n> > +\t\ttype = sha1_object_info(sha1, NULL);\n> > +\t\tif (type < 0)\n> >  \t\t\tdie(\"Not a valid object name %s\", argv[2]);\n> \n> I am wondering if \"enum object_type\" and signed comparison here\n> are compatible.\n\nEnums are signed as far as I know.\n\n> sha1_object_info() is of type \"int\" so that is\n> clearly signed, but are we safe assuming this would not result\n> in \"type is unsigned and condition is always false\"?\n\ngcc would have warned about it if it was the case.\n\n\nNicolas\n"},{"id":"35616","messageId":"alpine.LRH.0.82.0702270858510.29426@xanadu.home","threadId":"6978","inReplyTo":"7v8xejhnwd.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 5/6] convert object type handling from a string to a number","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2007-02-27T14:06:17Z","receivedAt":"2007-02-27T14:06:17Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"On Tue, 27 Feb 2007, Junio C Hamano wrote:\n\n> Junio C Hamano <junkio@cox.net> writes:\n> \n> > Nicolas Pitre <nico@cam.org> writes:\n> >\n> >> We currently have two parallel notation for dealing with object types\n> >> in the code: a string and a numerical value.  One of them is obviously\n> >> redundent, and the most used one requires more stack space and a bunch\n> >> of strcmp() all over the place.\n> >>\n> >> This is an initial step for the removal of the version using a char array\n> >> found in object reading code paths.  The patch is unfortunately large but\n> >> there is no sane way to split it in smaller parts without breaking the\n> >> system.\n> \n> Will your next step be to convert write_sha1_file() and friends?\n\nYes, eventually.\n\nAt least the write paths don't have those strcpy()/strcmp() everywhere \nand no temporary char arrays on the stack.  But for uniformity they have \nto be converted as well.\n\n\nNicolas\n"},{"id":"35675","messageId":"20070227150126.GA3230@spearce.org","threadId":"6978","inReplyTo":"7vejobhor2.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 5/6] convert object type handling from a string to a number","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-02-27T15:01:26Z","receivedAt":"2007-02-27T15:01:26Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Junio C Hamano <junkio@cox.net> wrote:\n> I am wondering if \"enum object_type\" and signed comparison here\n> are compatible.  sha1_object_info() is of type \"int\" so that is\n> clearly signed, but are we safe assuming this would not result\n> in \"type is unsigned and condition is always false\"?\n\nSee my recent patch; I actually rewrote those hunks to use OBJ_BAD\nrather than < 0, as this cleans things up for my packv4.\n\n-- \nShawn.\n"},{"id":"35627","messageId":"alpine.LRH.0.82.0702271029060.29426@xanadu.home","threadId":"6978","inReplyTo":"20070227150126.GA3230@spearce.org","subject":"Re: [PATCH 5/6] convert object type handling from a string to a number","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2007-02-27T15:33:55Z","receivedAt":"2007-02-27T15:33:55Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"On Tue, 27 Feb 2007, Shawn O. Pearce wrote:\n\n> Junio C Hamano <junkio@cox.net> wrote:\n> > I am wondering if \"enum object_type\" and signed comparison here\n> > are compatible.  sha1_object_info() is of type \"int\" so that is\n> > clearly signed, but are we safe assuming this would not result\n> > in \"type is unsigned and condition is always false\"?\n> \n> See my recent patch; I actually rewrote those hunks to use OBJ_BAD\n> rather than < 0, as this cleans things up for my packv4.\n\nI'd prefer if < 0 remained though.  That way we can use negative values \nfor any kind of error status.  And for kernel hackers this is a pretty \ncommon idiom.  And it uses less line realestate.\n\nActually OBJ_BAD could be assigned the value -1 and OBJ_MAX used to \nverify the object number is within range.  That would unify things and \nmake the code a bit more logical.\n\n\nNicolas\n"},{"id":"35676","messageId":"20070227160701.GD3230@spearce.org","threadId":"6978","inReplyTo":"alpine.LRH.0.82.0702271029060.29426@xanadu.home","subject":"Re: [PATCH 5/6] convert object type handling from a string to a number","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-02-27T16:07:01Z","receivedAt":"2007-02-27T16:07:01Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Nicolas Pitre <nico@cam.org> wrote:\n> On Tue, 27 Feb 2007, Shawn O. Pearce wrote:\n> \n> > Junio C Hamano <junkio@cox.net> wrote:\n> > > I am wondering if \"enum object_type\" and signed comparison here\n> > > are compatible.  sha1_object_info() is of type \"int\" so that is\n> > > clearly signed, but are we safe assuming this would not result\n> > > in \"type is unsigned and condition is always false\"?\n> > \n> > See my recent patch; I actually rewrote those hunks to use OBJ_BAD\n> > rather than < 0, as this cleans things up for my packv4.\n\nHmm... I appear to now be banned from posting to the git mailing list\nand I am also no longer recieving email from the mailing list.  Argh!\n \n> I'd prefer if < 0 remained though.  That way we can use negative values \n> for any kind of error status.  And for kernel hackers this is a pretty \n> common idiom.  And it uses less line realestate.\n> \n> Actually OBJ_BAD could be assigned the value -1 and OBJ_MAX used to \n> verify the object number is within range.  That would unify things and \n> make the code a bit more logical.\n\nI guess I could do that; my unify_type() function just needs to add\na new conditional to see if the input is < 0 and if so return it\nunchanged.  I was trying to avoid that extra condition as it appears\ntwice in the critical path of the object sorting in pack-objects.\n\n-- \nShawn.\n"},{"id":"35638","messageId":"Pine.LNX.4.64.0702270816350.12485@woody.linux-foundation.org","threadId":"6978","inReplyTo":"alpine.LRH.0.82.0702270856360.29426@xanadu.home","subject":"Re: [PATCH 5/6] convert object type handling from a string to a number","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-02-27T16:24:32Z","receivedAt":"2007-02-27T16:24:32Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 27 Feb 2007, Nicolas Pitre wrote:\n> > \n> > I am wondering if \"enum object_type\" and signed comparison here\n> > are compatible.\n> \n> Enums are signed as far as I know.\n\nNo they are not.\n\n\"enums\" are traditionally \"int\", but it's not a requirement, and the \ntechnical C requirement is that they be \"an integral size sufficiently \nlarge to hold all the possible values\".\n\nIn other words, with a small set of values, it's entirely possible that \nthe integral type in question be \"unsigned char\", for example.\n\nIt so happens that gcc will never *by*default* pick such a type for the \nparticular set of values you have. By default (to match traditions) gcc \nwill always pick \"int\" (or, thanks to a gcc extension, a bigger type if \nthe values require it), but if you pass it \"-fshort-enums\" it will pick a \nsmaller type. \n\nAnd yes, it will actually pick \"unsigned char\", I think. Try it to be \nsure.\n\nSo to be portable, and to be safe, you really should make the error values \npart of the enum, ie you should add a\n\n\tOBJ_ERROR = -1,\n\nif you want to make sure that the enum really can hold a negative number!\n\n(In fact, on some embedded platforms, \"-fshort-enums\" is actually on by \ndefault - in order to keep data structures smaller)\n\n\t\tLinus\n"},{"id":"35643","messageId":"alpine.LRH.0.82.0702271225330.29426@xanadu.home","threadId":"6978","inReplyTo":"Pine.LNX.4.64.0702270816350.12485@woody.linux-foundation.org","subject":"Re: [PATCH 5/6] convert object type handling from a string to a number","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2007-02-27T17:26:39Z","receivedAt":"2007-02-27T17:26:39Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"On Tue, 27 Feb 2007, Linus Torvalds wrote:\n\n> So to be portable, and to be safe, you really should make the error values \n> part of the enum, ie you should add a\n> \n> \tOBJ_ERROR = -1,\n> \n> if you want to make sure that the enum really can hold a negative number!\n\nFair enough.  That's what I suggested in another email, i.e. to redefine \nOBJ_BAD = -1.\n\n\nNicolas\n"}]}