{"thread":{"id":"28146","subject":"[PATCH 3/3] revision.c: update show_object_with_name() without using malloc()","startedAt":"2011-08-17T21:30:32Z","lastAt":"2011-08-17T21:30:35Z","messageCount":4,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"173699","messageId":"1313616635-25331-1-git-send-email-gitster@pobox.com","threadId":"28146","inReplyTo":null,"subject":"[PATCH 0/3] Minor \"list-objects\" updates","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-08-17T21:30:32Z","receivedAt":"2011-08-17T21:30:32Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Unify two codepaths that list objects in \"rev-list --objects\" format, and\nget rid of unnecessary malloc()/free() done per each line of output.\n\nJunio C Hamano (3):\n  rev-list: fix finish_object() call\n  revision.c: add show_object_with_name() helper function\n  revision.c: update show_object_with_name() without using malloc()\n\n builtin/rev-list.c |   17 ++---------------\n revision.c         |   41 +++++++++++++++++++++++++++++++++++++++++\n revision.h         |    2 ++\n upload-pack.c      |   15 +--------------\n 4 files changed, 46 insertions(+), 29 deletions(-)\n\n-- \n1.7.6.472.g4bfe7c\n"},{"id":"173698","messageId":"1313616635-25331-2-git-send-email-gitster@pobox.com","threadId":"28146","inReplyTo":"1313616635-25331-1-git-send-email-gitster@pobox.com","subject":"[PATCH 1/3] rev-list: fix finish_object() call","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-08-17T21:30:33Z","receivedAt":"2011-08-17T21:30:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"The callback to traverse_commit_list() are to take linked name_path and\na string for the last path component.\n\nIf the callee used its parameters, it would have seen duplicated leading\npaths. In this particular case, the callee does not use this argument but\nthat is not a reason to leave the call broken.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/rev-list.c |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/builtin/rev-list.c b/builtin/rev-list.c\nindex 56727e8..d789279 100644\n--- a/builtin/rev-list.c\n+++ b/builtin/rev-list.c\n@@ -182,7 +182,7 @@ static void show_object(struct object *obj, const struct name_path *path, const\n \t */\n \tconst char *ep = strchr(name, '\\n');\n \n-\tfinish_object(obj, path, name);\n+\tfinish_object(obj, path, component);\n \tif (ep) {\n \t\tprintf(\"%s %.*s\\n\", sha1_to_hex(obj->sha1),\n \t\t       (int) (ep - name),\n-- \n1.7.6.472.g4bfe7c\n"},{"id":"173700","messageId":"1313616635-25331-3-git-send-email-gitster@pobox.com","threadId":"28146","inReplyTo":"1313616635-25331-1-git-send-email-gitster@pobox.com","subject":"[PATCH 2/3] revision.c: add show_object_with_name() helper function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-08-17T21:30:34Z","receivedAt":"2011-08-17T21:30:34Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"There are two copies of traverse_commit_list callback that show the object\nname followed by pathname the object was found, to produce output similar\nto \"rev-list --objects\".\n\nUnify them.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/rev-list.c |   15 +--------------\n revision.c         |   19 +++++++++++++++++++\n revision.h         |    2 ++\n upload-pack.c      |   15 +--------------\n 4 files changed, 23 insertions(+), 28 deletions(-)\n\ndiff --git a/builtin/rev-list.c b/builtin/rev-list.c\nindex d789279..f5ce487 100644\n--- a/builtin/rev-list.c\n+++ b/builtin/rev-list.c\n@@ -176,21 +176,8 @@ static void finish_object(struct object *obj, const struct name_path *path, cons\n \n static void show_object(struct object *obj, const struct name_path *path, const char *component)\n {\n-\tchar *name = path_name(path, component);\n-\t/* An object with name \"foo\\n0000000...\" can be used to\n-\t * confuse downstream \"git pack-objects\" very badly.\n-\t */\n-\tconst char *ep = strchr(name, '\\n');\n-\n \tfinish_object(obj, path, component);\n-\tif (ep) {\n-\t\tprintf(\"%s %.*s\\n\", sha1_to_hex(obj->sha1),\n-\t\t       (int) (ep - name),\n-\t\t       name);\n-\t}\n-\telse\n-\t\tprintf(\"%s %s\\n\", sha1_to_hex(obj->sha1), name);\n-\tfree(name);\n+\tshow_object_with_name(stdout, obj, path, component);\n }\n \n static void show_edge(struct commit *commit)\ndiff --git a/revision.c b/revision.c\nindex c46cfaa..c5b38cc 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -40,6 +40,25 @@ char *path_name(const struct name_path *path, const char *name)\n \treturn n;\n }\n \n+void show_object_with_name(FILE *out, struct object *obj, const struct name_path *path, const char *component)\n+{\n+\tchar *name = path_name(path, component);\n+\tconst char *ep = strchr(name, '\\n');\n+\n+\t/*\n+\t * An object with name \"foo\\n0000000...\" can be used to\n+\t * confuse downstream \"git pack-objects\" very badly.\n+\t */\n+\tif (ep) {\n+\t\tfprintf(out, \"%s %.*s\\n\", sha1_to_hex(obj->sha1),\n+\t\t\t(int) (ep - name),\n+\t\t\tname);\n+\t}\n+\telse\n+\t\tfprintf(out, \"%s %s\\n\", sha1_to_hex(obj->sha1), name);\n+\tfree(name);\n+}\n+\n void add_object(struct object *obj,\n \t\tstruct object_array *p,\n \t\tstruct name_path *path,\ndiff --git a/revision.h b/revision.h\nindex 3d64ada..da00a58 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -185,6 +185,8 @@ struct name_path {\n \n char *path_name(const struct name_path *path, const char *name);\n \n+extern void show_object_with_name(FILE *, struct object *, const struct name_path *, const char *);\n+\n extern void add_object(struct object *obj,\n \t\t       struct object_array *p,\n \t\t       struct name_path *path,\ndiff --git a/upload-pack.c b/upload-pack.c\nindex ce5cbbe..970a1eb 100644\n--- a/upload-pack.c\n+++ b/upload-pack.c\n@@ -85,20 +85,7 @@ static void show_commit(struct commit *commit, void *data)\n \n static void show_object(struct object *obj, const struct name_path *path, const char *component)\n {\n-\t/* An object with name \"foo\\n0000000...\" can be used to\n-\t * confuse downstream git-pack-objects very badly.\n-\t */\n-\tconst char *name = path_name(path, component);\n-\tconst char *ep = strchr(name, '\\n');\n-\tif (ep) {\n-\t\tfprintf(pack_pipe, \"%s %.*s\\n\", sha1_to_hex(obj->sha1),\n-\t\t       (int) (ep - name),\n-\t\t       name);\n-\t}\n-\telse\n-\t\tfprintf(pack_pipe, \"%s %s\\n\",\n-\t\t\t\tsha1_to_hex(obj->sha1), name);\n-\tfree((char *)name);\n+\tshow_object_with_name(pack_pipe, obj, path, component);\n }\n \n static void show_edge(struct commit *commit)\n-- \n1.7.6.472.g4bfe7c\n"},{"id":"173697","messageId":"1313616635-25331-4-git-send-email-gitster@pobox.com","threadId":"28146","inReplyTo":"1313616635-25331-1-git-send-email-gitster@pobox.com","subject":"[PATCH 3/3] revision.c: update show_object_with_name() without using malloc()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-08-17T21:30:35Z","receivedAt":"2011-08-17T21:30:35Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Allocating and then immediately freeing temporary memory a million times\nwhen listing a million objects is distasteful.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n * It may also be an option to keep a single static strbuf in\n   show_object_with_name() and reuse it.\n\n revision.c |   50 ++++++++++++++++++++++++++++++++++++--------------\n 1 files changed, 36 insertions(+), 14 deletions(-)\n\ndiff --git a/revision.c b/revision.c\nindex c5b38cc..072ddac 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -40,23 +40,45 @@ char *path_name(const struct name_path *path, const char *name)\n \treturn n;\n }\n \n+static int show_path_component_truncated(FILE *out, const char *name, int len)\n+{\n+\tint cnt;\n+\tfor (cnt = 0; cnt < len; cnt++) {\n+\t\tint ch = name[cnt];\n+\t\tif (!ch || ch == '\\n')\n+\t\t\treturn -1;\n+\t\tfputc(ch, out);\n+\t}\n+\treturn len;\n+}\n+\n+static int show_path_truncated(FILE *out, const struct name_path *path)\n+{\n+\tint emitted, ours;\n+\n+\tif (!path)\n+\t\treturn 0;\n+\temitted = show_path_truncated(out, path->up);\n+\tif (emitted < 0)\n+\t\treturn emitted;\n+\tif (emitted)\n+\t\tfputc('/', out);\n+\tours = show_path_component_truncated(out, path->elem, path->elem_len);\n+\tif (ours < 0)\n+\t\treturn ours;\n+\treturn ours || emitted;\n+}\n+\n void show_object_with_name(FILE *out, struct object *obj, const struct name_path *path, const char *component)\n {\n-\tchar *name = path_name(path, component);\n-\tconst char *ep = strchr(name, '\\n');\n+\tstruct name_path leaf;\n+\tleaf.up = (struct name_path *)path;\n+\tleaf.elem = component;\n+\tleaf.elem_len = strlen(component);\n \n-\t/*\n-\t * An object with name \"foo\\n0000000...\" can be used to\n-\t * confuse downstream \"git pack-objects\" very badly.\n-\t */\n-\tif (ep) {\n-\t\tfprintf(out, \"%s %.*s\\n\", sha1_to_hex(obj->sha1),\n-\t\t\t(int) (ep - name),\n-\t\t\tname);\n-\t}\n-\telse\n-\t\tfprintf(out, \"%s %s\\n\", sha1_to_hex(obj->sha1), name);\n-\tfree(name);\n+\tfprintf(out, \"%s \", sha1_to_hex(obj->sha1));\n+\tshow_path_truncated(out, &leaf);\n+\tfputc('\\n', out);\n }\n \n void add_object(struct object *obj,\n-- \n1.7.6.472.g4bfe7c\n"}]}