{"thread":{"id":"4749","subject":"[PATCH] Make git-fmt-merge-msg a builtin","startedAt":"2006-07-03T13:31:32Z","lastAt":"2006-07-03T21:29:46Z","messageCount":7,"participants":["Johannes Schindelin","Timo Hirvonen"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"23103","messageId":"Pine.LNX.4.63.0607031530380.29667@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"4749","inReplyTo":null,"subject":"[PATCH] Make git-fmt-merge-msg a builtin","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-07-03T13:31:32Z","receivedAt":"2006-07-03T13:31:32Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nSigned-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\n\n---\n\n\tThis does not (yet) remove the Perl version.\n\n Makefile                |    2 \n builtin-fmt-merge-msg.c |  357 +++++++++++++++++++++++++++++++++++++++++++++++\n builtin.h               |    1 \n git.c                   |    3 \n 4 files changed, 361 insertions(+), 2 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex c142bdd..c75b8a9 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -245,7 +245,7 @@ BUILTIN_OBJS = \\\n \tbuiltin-apply.o builtin-show-branch.o builtin-diff-files.o \\\n \tbuiltin-diff-index.o builtin-diff-stages.o builtin-diff-tree.o \\\n \tbuiltin-cat-file.o builtin-mailsplit.o builtin-stripspace.o \\\n-\tbuiltin-update-ref.o\n+\tbuiltin-update-ref.o builtin-fmt-merge-msg.o\n \n GITLIBS = $(LIB_FILE) $(XDIFF_LIB)\n EXTLIBS = -lz\ndiff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c\nnew file mode 100644\nindex 0000000..a73b322\n--- /dev/null\n+++ b/builtin-fmt-merge-msg.c\n@@ -0,0 +1,357 @@\n+#include \"cache.h\"\n+#include \"commit.h\"\n+#include \"diff.h\"\n+#include \"revision.h\"\n+#include \"tag.h\"\n+\n+static const char *fmt_merge_msg_usage =\n+\t\"git-fmt-merge-msg [--summary] [--no-summary] [--file <file>]\";\n+\n+static int merge_summary = 0;\n+\n+static int fmt_merge_msg_config(const char *key, const char *value)\n+{\n+\tif (!strcmp(\"merge.summary\", key))\n+\t\tmerge_summary = git_config_bool(key, value);\n+\treturn 0;\n+}\n+\n+struct list {\n+\tchar **list;\n+\tvoid **payload;\n+\tunsigned nr, alloc;\n+};\n+\n+static void append_to_list(struct list *list, char *value)\n+{\n+\tif (list->nr == list->alloc) {\n+\t\tlist->alloc += 32;\n+\t\tlist->list = realloc(list->list, sizeof(char *) * list->alloc);\n+\t\tlist->payload = realloc(list->payload,\n+\t\t\t\tsizeof(char *) * list->alloc);\n+\t}\n+\tlist->payload[list->nr] = NULL;\n+\tlist->list[list->nr++] = value;\n+}\n+\n+static int find_in_list(struct list *list, char *value)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < list->nr; i++)\n+\t\tif (!strcmp(list->list[i], value))\n+\t\t\treturn i;\n+\n+\treturn -1;\n+}\n+\n+static void free_list(struct list *list)\n+{\n+\tint i;\n+\n+\tif (list->alloc == 0)\n+\t\treturn;\n+\n+\tfor (i = 0; i < list->nr; i++) {\n+\t\tfree(list->list[i]);\n+\t\tif (list->payload[i])\n+\t\t\tfree(list->payload[i]);\n+\t}\n+\tfree(list->list);\n+\tfree(list->payload);\n+\tlist->nr = list->alloc = 0;\n+}\n+\n+struct src_data {\n+\tstruct list branch, tag, r_branch, generic;\n+\tint head_status;\n+};\n+\n+static struct list srcs = { NULL, NULL, 0, 0};\n+static struct list origins = { NULL, NULL, 0, 0};\n+\n+static int handle_line(char *line)\n+{\n+\tint i, len = strlen(line);\n+\tunsigned char *sha1;\n+\tchar *src, *origin;\n+\tstruct src_data *src_data;\n+\n+\tif (len < 43 || line[40] != '\\t')\n+\t\treturn 1;\n+\n+\tif (!strncmp(line + 41, \"not-for-merge\", 13))\n+\t\treturn 0;\n+\n+\tif (line[41] != '\\t')\n+\t\treturn 2;\n+\n+\tline[40] = 0;\n+\tsha1 = xmalloc(20);\n+\ti = get_sha1(line, sha1);\n+\tline[40] = '\\t';\n+\tif (i)\n+\t\treturn 3;\n+\n+\tif (line[len - 1] == '\\n')\n+\t\tline[len - 1] = 0;\n+\tline += 42;\n+\n+\tsrc = strstr(line, \" of \");\n+\tif (src) {\n+\t\t*src = 0;\n+\t\tsrc += 4;\n+\t} else\n+\t\tsrc = \"HEAD\";\n+\n+\ti = find_in_list(&srcs, src);\n+\tif (i < 0) {\n+\t\ti = srcs.nr;\n+\t\tappend_to_list(&srcs, strdup(src));\n+\t\tsrcs.payload[i] = xcalloc(1, sizeof(struct src_data));\n+\t}\n+\tsrc_data = srcs.payload[i];\n+\n+\tif (!strncmp(line, \"branch \", 7)) {\n+\t\torigin = strdup(line + 7);\n+\t\tappend_to_list(&(src_data->branch), origin);\n+\t\tsrc_data->head_status |= 2;\n+\t} else if (!strncmp(line, \"tag \", 4)) {\n+\t\torigin = line;\n+\t\tappend_to_list(&(src_data->tag), strdup(origin + 4));\n+\t\tsrc_data->head_status |= 2;\n+\t} else if (!strncmp(line, \"remote branch \", 14)) {\n+\t\torigin = strdup(line + 14);\n+\t\tappend_to_list(&(src_data->r_branch), origin);\n+\t\tsrc_data->head_status |= 2;\n+\t} else if (!strcmp(line, \"HEAD\")) {\n+\t\torigin = strdup(src);\n+\t\tsrc_data->head_status |= 1;\n+\t} else {\n+\t\torigin = strdup(src);\n+\t\tappend_to_list(&(src_data->generic), strdup(line));\n+\t\tsrc_data->head_status |= 2;\n+\t}\n+\n+\tif (!strcmp(\".\", src) || !strcmp(src, origin)) {\n+\t\tint len = strlen(origin);\n+\t\tif (origin[0] == '\\'' && origin[len - 1] == '\\'') {\n+\t\t\tchar *new_origin = malloc(len - 1);\n+\t\t\tmemcpy(new_origin, origin + 1, len - 2);\n+\t\t\tnew_origin[len - 1] = 0;\n+\t\t\torigin = new_origin;\n+\t\t} else\n+\t\t\torigin = strdup(origin);\n+\t} else {\n+\t\tchar *new_origin = malloc(strlen(origin) + strlen(src) + 5);\n+\t\tsprintf(new_origin, \"%s of %s\", origin, src);\n+\t\torigin = new_origin;\n+\t}\n+\tappend_to_list(&origins, origin);\n+\torigins.payload[origins.nr - 1] = sha1;\n+\treturn 0;\n+}\n+\n+static void print_joined(const char *singular, const char *plural,\n+\t\tstruct list *list)\n+{\n+\tif (list->nr == 0)\n+\t\treturn;\n+\tif (list->nr == 1) {\n+\t\tprintf(\"%s%s\", singular, list->list[0]);\n+\t} else {\n+\t\tint i;\n+\t\tprintf(\"%s\", plural);\n+\t\tfor (i = 0; i < list->nr - 1; i++)\n+\t\t\tprintf(\"%s%s\", i > 0 ? \", \" : \"\", list->list[i]);\n+\t\tprintf(\" and %s\", list->list[list->nr - 1]);\n+\t}\n+}\n+\n+static void shortlog(const char *name, unsigned char *sha1,\n+\t\tstruct commit *head, struct rev_info *rev, int limit)\n+{\n+\tint i, count = 0;\n+\tstruct commit *commit;\n+\tstruct object *branch;\n+\tstruct list subjects = { NULL, NULL, 0, 0 };\n+\tint flags = UNINTERESTING | TREECHANGE | SEEN | SHOWN | ADDED;\n+\n+\tbranch = deref_tag(parse_object(sha1), sha1_to_hex(sha1), 40);\n+\tif (!branch || branch->type != TYPE_COMMIT)\n+\t\treturn;\n+\n+\tsetup_revisions(0, NULL, rev, NULL);\n+\trev->ignore_merges = 1;\n+\tadd_pending_object(rev, branch, name);\n+\tadd_pending_object(rev, &(head->object), \"^HEAD\");\n+\thead->object.flags |= UNINTERESTING;\n+        prepare_revision_walk(rev);\n+\twhile ((commit = get_revision(rev)) != NULL) {\n+\t\tchar *oneline, *bol, *eol;\n+\n+\t\t/* ignore merges */\n+\t\tif (commit->parents && commit->parents->next)\n+\t\t\tcontinue;\n+\n+\t\tcount++;\n+\t\tif (subjects.nr > limit)\n+\t\t\tcontinue;\n+\n+\t\tbol = strstr(commit->buffer, \"\\n\\n\");\n+\t\tif (!bol) {\n+\t\t\tappend_to_list(&subjects, strdup(sha1_to_hex(\n+\t\t\t\t\t\t\tcommit->object.sha1)));\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tbol += 2;\n+\t\teol = strchr(bol, '\\n');\n+\t\t\n+\t\tif (eol) {\n+\t\t\tint len = eol - bol;\n+\t\t\toneline = malloc(len + 1);\n+\t\t\tmemcpy(oneline, bol, len);\n+\t\t\toneline[len] = 0;\n+\t\t} else\n+\t\t\toneline = strdup(bol);\n+\t\tappend_to_list(&subjects, oneline);\n+\t}\n+\n+\tif (count > limit)\n+\t\tprintf(\"\\n* %s: (%d commits)\\n\", name, count);\n+\telse\n+\t\tprintf(\"\\n* %s:\\n\", name);\n+\n+\tfor (i = 0; i < subjects.nr; i++)\n+\t\tif (i >= limit)\n+\t\t\tprintf(\"  ...\\n\");\n+\t\telse\n+\t\t\tprintf(\"  %s\\n\", subjects.list[i]);\n+\n+\tclear_commit_marks((struct commit *)branch, flags);\n+\tclear_commit_marks(head, flags);\n+\tfree_commit_list(rev->commits);\n+\trev->commits = NULL;\n+\trev->pending.nr = 0;\n+\n+\tfree_list(&subjects);\n+\t\n+}\n+\n+int cmd_fmt_merge_msg(int argc, char **argv, char **envp)\n+{\n+\tint limit = 20, i = 0;\n+\tchar line[1024];\n+\tFILE *in = stdin;\n+\tconst char *sep = \"\";\n+\tunsigned char head_sha1[20];\n+\tconst char *head, *current_branch;\n+\n+\tgit_config(fmt_merge_msg_config);\n+\n+\twhile (argc > 1) {\n+\t\tif (!strcmp(argv[1], \"--summary\"))\n+\t\t\tmerge_summary = 1;\n+\t\telse if (!strcmp(argv[1], \"--no-summary\"))\n+\t\t\tmerge_summary = 0;\n+\t\telse if (!strcmp(argv[1], \"-F\") || !strcmp(argv[1], \"--file\")) {\n+\t\t\tif (argc < 2)\n+\t\t\t\tdie (\"Which file?\");\n+\t\t\tif (!strcmp(argv[2], \"-\"))\n+\t\t\t\tin = stdin;\n+\t\t\telse {\n+\t\t\t\tfclose(in);\n+\t\t\t\tin = fopen(argv[2], \"r\");\n+\t\t\t}\n+\t\t\targc--; argv++;\n+\t\t} else\n+\t\t\tbreak;\n+\t\targc--; argv++;\n+\t}\n+\n+\tif (argc > 1)\n+\t\tusage(fmt_merge_msg_usage);\n+\n+\t/* get current branch */\n+\thead = strdup(git_path(\"HEAD\"));\n+\tcurrent_branch = resolve_ref(head, head_sha1, 1);\n+\tcurrent_branch += strlen(head) - 4;\n+\tfree((char *)head);\n+\tif (!strncmp(current_branch, \"refs/heads/\", 11))\n+\t\tcurrent_branch += 11;\n+\n+\twhile (fgets(line, sizeof(line), in)) {\n+\t\ti++;\n+\t\tif (line[0] == 0)\n+\t\t\tcontinue;\n+\t\tif (handle_line(line))\n+\t\t\tdie (\"Error in line %d: %s\", i, line);\n+\t}\n+\n+\tprintf(\"Merge \");\n+\tfor (i = 0; i < srcs.nr; i++) {\n+\t\tstruct src_data *src_data = srcs.payload[i];\n+\t\tconst char *subsep = \"\";\n+\n+\t\tprintf(sep);\n+\t\tsep = \"; \";\n+\n+\t\tif (src_data->head_status == 1) {\n+\t\t\tprintf(srcs.list[i]);\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (src_data->head_status == 3) {\n+\t\t\tsubsep = \", \";\n+\t\t\tprintf(\"HEAD\");\n+\t\t}\n+\t\tif (src_data->branch.nr) {\n+\t\t\tprintf(subsep);\n+\t\t\tsubsep = \", \";\n+\t\t\tprint_joined(\"branch \", \"branches \",\n+\t\t\t\t\t&(src_data->branch));\n+\t\t}\n+\t\tif (src_data->r_branch.nr) {\n+\t\t\tprintf(subsep);\n+\t\t\tsubsep = \", \";\n+\t\t\tprint_joined(\"remote branch \", \"remote branches \",\n+\t\t\t\t\t&(src_data->r_branch));\n+\t\t}\n+\t\tif (src_data->tag.nr) {\n+\t\t\tprintf(subsep);\n+\t\t\tsubsep = \", \";\n+\t\t\tprint_joined(\"tag \", \"tags \", &(src_data->tag));\n+\t\t}\n+\t\tif (src_data->generic.nr) {\n+\t\t\tprintf(subsep);\n+\t\t\tprint_joined(\"commit \", \"commits \",\n+\t\t\t\t\t&(src_data->generic));\n+\t\t}\n+\t\tif (strcmp(\".\", srcs.list[i]))\n+\t\t\tprintf(\" of %s\", srcs.list[i]);\n+\t}\n+\n+\tprintf(\" into %s\\n\", current_branch);\n+\n+\tif (merge_summary) {\n+\t\tstruct commit *head;\n+\t\tstruct rev_info rev;\n+\n+\t\thead = lookup_commit(head_sha1);\n+parse_object(head->object.sha1);\n+head = head->parents->item;\n+\t\tinit_revisions(&rev);\n+\t\trev.commit_format = CMIT_FMT_ONELINE;\n+\t\trev.ignore_merges = 1;\n+\t\trev.limited = 1;\n+\n+\t\tfor (i = 0; i < origins.nr; i++)\n+\t\t\tshortlog(origins.list[i], origins.payload[i],\n+\t\t\t\t\thead, &rev, limit);\n+\t}\n+\n+\t/* No cleanup yet; is standalone anyway */\n+\n+\treturn 0;\n+}\n+\ndiff --git a/builtin.h b/builtin.h\nold mode 100644\nnew mode 100755\nindex f12d5e6..d9e5483\n--- a/builtin.h\n+++ b/builtin.h\n@@ -49,6 +49,7 @@ extern int cmd_cat_file(int argc, const \n extern int cmd_rev_parse(int argc, const char **argv, char **envp);\n extern int cmd_update_index(int argc, const char **argv, char **envp);\n extern int cmd_update_ref(int argc, const char **argv, char **envp);\n+extern int cmd_fmt_merge_msg(int argc, const char **argv, char **envp);\n \n extern int cmd_write_tree(int argc, const char **argv, char **envp);\n extern int write_tree(unsigned char *sha1, int missing_ok, const char *prefix);\ndiff --git a/git.c b/git.c\nindex 512fa63..7cc826b 100644\n--- a/git.c\n+++ b/git.c\n@@ -200,7 +200,8 @@ static void handle_internal_command(int \n \t\t{ \"mailinfo\", cmd_mailinfo },\n \t\t{ \"stripspace\", cmd_stripspace },\n \t\t{ \"update-index\", cmd_update_index },\n-\t\t{ \"update-ref\", cmd_update_ref }\n+\t\t{ \"update-ref\", cmd_update_ref },\n+\t\t{ \"fmt-merge-msg\", cmd_fmt_merge_msg }\n \t};\n \tint i;\n \n-- \n1.4.1.ga246\n"},{"id":"23107","messageId":"20060703171751.2ed33220.tihirvon@gmail.com","threadId":"4749","inReplyTo":"Pine.LNX.4.63.0607031530380.29667@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] Make git-fmt-merge-msg a builtin","fromName":"Timo Hirvonen","fromEmail":"tihirvon@gmail.com","sentAt":"2006-07-03T14:17:51Z","receivedAt":"2006-07-03T14:17:51Z","isPatch":true,"sender":{"key":"tihirvon@gmail.com","avatar":null},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n\n> +struct list {\n> +\tchar **list;\n> +\tvoid **payload;\n> +\tunsigned nr, alloc;\n> +};\n\nHow about something like this instead to reduce mallocs to half and\nsimplify the code?\n\nstruct item {\n\tchar *value;\n\tvoid *payload;\n};\n\nstruct list {\n\tstruct item *items;\n\tunsigned int nr, alloc;\n};\n\n(But I realize this isn't performance critical)\n\n> +static void append_to_list(struct list *list, char *value)\n\nAdd void *payload parameter too, would simplify the code.\n\n> +static void free_list(struct list *list)\n> +{\n> +\tint i;\n> +\n> +\tif (list->alloc == 0)\n> +\t\treturn;\n\nUnnecessary if nr is 0 too.\n\n> +\tfor (i = 0; i < list->nr; i++) {\n> +\t\tfree(list->list[i]);\n> +\t\tif (list->payload[i])\n> +\t\t\tfree(list->payload[i]);\n\nfree(NULL) is safe.\n\n> +\t}\n> +\tfree(list->list);\n> +\tfree(list->payload);\n> +\tlist->nr = list->alloc = 0;\n> +}\n\n> +\tif (!strncmp(line, \"branch \", 7)) {\n> +\t\torigin = strdup(line + 7);\n> +\t\tappend_to_list(&(src_data->branch), origin);\n\nParenthesis isn't needed.\n\n> +\thead->object.flags |= UNINTERESTING;\n> +        prepare_revision_walk(rev);\n\nSpaces..\n\n> +\tif (merge_summary) {\n> +\t\tstruct commit *head;\n> +\t\tstruct rev_info rev;\n> +\n> +\t\thead = lookup_commit(head_sha1);\n> +parse_object(head->object.sha1);\n> +head = head->parents->item;\n\nIndentation.\n\n-- \nhttp://onion.dynserv.net/~timo/\n"},{"id":"23109","messageId":"Pine.LNX.4.63.0607031632290.29667@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"4749","inReplyTo":"20060703171751.2ed33220.tihirvon@gmail.com","subject":"Re: [PATCH] Make git-fmt-merge-msg a builtin","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-07-03T14:36:02Z","receivedAt":"2006-07-03T14:36:02Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 3 Jul 2006, Timo Hirvonen wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> \n> > +struct list {\n> > +\tchar **list;\n> > +\tvoid **payload;\n> > +\tunsigned nr, alloc;\n> > +};\n> \n> How about something like this instead to reduce mallocs to half and\n> simplify the code?\n> \n> struct item {\n> \tchar *value;\n> \tvoid *payload;\n> };\n> \n> struct list {\n> \tstruct item *items;\n> \tunsigned int nr, alloc;\n> };\n> \n> (But I realize this isn't performance critical)\n\nI had in mind that I want to use path-list instead (which is cooking in \nthe merge-recursive efforts ATM). And there, I would add a flag \nneeds_payload. Opinions?\n\n> > +static void append_to_list(struct list *list, char *value)\n> \n> Add void *payload parameter too, would simplify the code.\n\nOkay.\n\n> > +static void free_list(struct list *list)\n> > +{\n> > +\tint i;\n> > +\n> > +\tif (list->alloc == 0)\n> > +\t\treturn;\n> \n> Unnecessary if nr is 0 too.\n\nNo. If nr == 0, alloc need not be 0, and if it is not, list and payload \nare still allocated.\n\n> > +\tfor (i = 0; i < list->nr; i++) {\n> > +\t\tfree(list->list[i]);\n> > +\t\tif (list->payload[i])\n> > +\t\t\tfree(list->payload[i]);\n> \n> free(NULL) is safe.\n\nIs it? I vaguely remember that I had problems with this on some obscure \nplatform.\n\n> > +\tif (!strncmp(line, \"branch \", 7)) {\n> > +\t\torigin = strdup(line + 7);\n> > +\t\tappend_to_list(&(src_data->branch), origin);\n> \n> Parenthesis isn't needed.\n\nOkay. Wanted to be on the safe side.\n\n> > +\thead->object.flags |= UNINTERESTING;\n> > +        prepare_revision_walk(rev);\n> \n> Spaces..\n\nTrue. Will fix.\n\n> > +\tif (merge_summary) {\n> > +\t\tstruct commit *head;\n> > +\t\tstruct rev_info rev;\n> > +\n> > +\t\thead = lookup_commit(head_sha1);\n> > +parse_object(head->object.sha1);\n> > +head = head->parents->item;\n> \n> Indentation.\n\nNo. Bug. This was a leftover from my tests (with this, the summary is not \ndone versus HEAD, but HEAD^).\n\nWill fix and resubmit.\n\nCiao,\nDscho\n"},{"id":"23113","messageId":"20060703182621.dbed5b5f.tihirvon@gmail.com","threadId":"4749","inReplyTo":"Pine.LNX.4.63.0607031632290.29667@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] Make git-fmt-merge-msg a builtin","fromName":"Timo Hirvonen","fromEmail":"tihirvon@gmail.com","sentAt":"2006-07-03T15:26:21Z","receivedAt":"2006-07-03T15:26:21Z","isPatch":true,"sender":{"key":"tihirvon@gmail.com","avatar":null},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n\n> I had in mind that I want to use path-list instead (which is cooking in \n> the merge-recursive efforts ATM). And there, I would add a flag \n> needs_payload. Opinions?\n\nThis code is so simple that making the path_list more complex\n(needs_payload special case?) is not worth it.  I have not looked at the\ncode very closely though and have no idea what I'm talking about :)\n\n> > > +static void free_list(struct list *list)\n> > > +{\n> > > +\tint i;\n> > > +\n> > > +\tif (list->alloc == 0)\n> > > +\t\treturn;\n> > \n> > Unnecessary if nr is 0 too.\n> \n> No. If nr == 0, alloc need not be 0, and if it is not, list and payload \n> are still allocated.\n\nIf alloc is 0 then nr is 0 too (at least it _should_ be).  The code would\neffectively become:\n\n\tfor (i = 0; i < 0; i++) {\n\t\t...\n\t}\n\tfree(NULL);\n\tfree(NULL);\n\tlist->nr = list->alloc = 0;\n\nBut this is not important...\n\n> > free(NULL) is safe.\n> \n> Is it? I vaguely remember that I had problems with this on some obscure \n> platform.\n\nI don't think so.\n\n-- \nhttp://onion.dynserv.net/~timo/\n"},{"id":"23114","messageId":"Pine.LNX.4.63.0607031731550.29667@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"4749","inReplyTo":"20060703182621.dbed5b5f.tihirvon@gmail.com","subject":"Re: [PATCH] Make git-fmt-merge-msg a builtin","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-07-03T15:45:48Z","receivedAt":"2006-07-03T15:45:48Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 3 Jul 2006, Timo Hirvonen wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> \n> > I had in mind that I want to use path-list instead (which is cooking in \n> > the merge-recursive efforts ATM). And there, I would add a flag \n> > needs_payload. Opinions?\n> \n> This code is so simple that making the path_list more complex \n> (needs_payload special case?) is not worth it.  I have not looked at the \n> code very closely though and have no idea what I'm talking about :)\n\nOkay. But I'd rather go back to work on merge-recursive, and just reuse \nthe path_list struct.\n\n> > > free(NULL) is safe.\n> > \n> > Is it? I vaguely remember that I had problems with this on some obscure \n> > platform.\n> \n> I don't think so.\n\nWell, after a little Googling, I am more convinced than ever that it is a \nBAD thing to rely on free(NULL) being a NOP.\n\nCiao,\nDscho\n"},{"id":"23117","messageId":"20060703191635.21ba0af3.tihirvon@gmail.com","threadId":"4749","inReplyTo":"Pine.LNX.4.63.0607031731550.29667@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] Make git-fmt-merge-msg a builtin","fromName":"Timo Hirvonen","fromEmail":"tihirvon@gmail.com","sentAt":"2006-07-03T16:16:35Z","receivedAt":"2006-07-03T16:16:35Z","isPatch":true,"sender":{"key":"tihirvon@gmail.com","avatar":null},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n\n> > > > free(NULL) is safe.\n> > > \n> > > Is it? I vaguely remember that I had problems with this on some obscure \n> > > platform.\n> > \n> > I don't think so.\n> \n> Well, after a little Googling, I am more convinced than ever that it is a \n> BAD thing to rely on free(NULL) being a NOP.\n\nI did some research too.  Seems that C89 requires free(NULL) to be a\nno-op but on some old systems (SunOS) it may crash.  IMNSHO these\nsystems were designed to crash valid programs and torture developers.\nThere are probably many free(NULL) and realloc(NULL, ...) uses in the\ngit source code and are not worth fixing.\n\n-- \nhttp://onion.dynserv.net/~timo/\n"},{"id":"23143","messageId":"Pine.LNX.4.63.0607032327470.29667@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"4749","inReplyTo":"20060703191635.21ba0af3.tihirvon@gmail.com","subject":"Re: [PATCH] Make git-fmt-merge-msg a builtin","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-07-03T21:29:46Z","receivedAt":"2006-07-03T21:29:46Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 3 Jul 2006, Timo Hirvonen wrote:\n\n> Seems that C89 requires free(NULL) to be a no-op but on some old systems \n> (SunOS) it may crash.  IMNSHO these systems were designed to crash valid \n> programs and torture developers.\n\nAt least it is not Malbolge. Or even VAX. (In that order.)\n\n> There are probably many free(NULL) and realloc(NULL, ...) uses in the \n> git source code and are not worth fixing.\n\nAFAIK realloc(NULL, ...) was fine even with K&R, whereas free(NULL) poses \nproblems. Anyway, I do not _want_ to say that NULL should be free()d, \nbecause it just sounds wrong.\n\nCiao,\nDscho\n"}]}