{"thread":{"id":"24365","subject":"[PATCH v1 0/4] add parent rewrite feature to line level log","startedAt":"2010-07-11T06:27:33Z","lastAt":"2010-07-14T19:10:52Z","messageCount":8,"participants":["Bo Yang","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":4},"messages":[{"id":"145307","messageId":"1278829657-26607-1-git-send-email-struggleyb.nku@gmail.com","threadId":"24365","inReplyTo":null,"subject":"[PATCH v1 0/4] add parent rewrite feature to line level log","fromName":"Bo Yang","fromEmail":"struggleyb.nku@gmail.com","sentAt":"2010-07-11T06:27:33Z","receivedAt":"2010-07-11T06:27:33Z","isPatch":true,"sender":{"key":"struggleyb.nku@gmail.com","avatar":"https://avatars.githubusercontent.com/u/233030?v=4"},"body":"With this series of patches, one can provide options such as '--graph', '--parents', '--simplify-merges' and etc to 'git log -L' command and get the right result.\nNote that, this series is based on the previous series 'the version 3 of 13 commits just posted to the list'. :-)\n\nBo Yang (4):\n  make rewrite_parents a external function\n  add parent rewrite feature to line level log\n  line.c output the '--graph' padding before each line\n  add test cases for '--graph' of line level log\n\n Documentation/git-log.txt          |    2 +\n line.c                             |  177 ++++++++++++++++++++++++-----\n line.h                             |    2 +\n revision.c                         |   14 +--\n revision.h                         |   10 ++\n t/t4301-log-line-single-history.sh |  225 ++++++++++++++++++++++++++++++++++++\n t/t4302-log-line-merge-history.sh  |   51 ++++++++-\n 7 files changed, 445 insertions(+), 36 deletions(-)\n"},{"id":"145310","messageId":"1278829657-26607-2-git-send-email-struggleyb.nku@gmail.com","threadId":"24365","inReplyTo":"1278829657-26607-1-git-send-email-struggleyb.nku@gmail.com","subject":"[PATCH v1 1/4] make rewrite_parents an external function","fromName":"Bo Yang","fromEmail":"struggleyb.nku@gmail.com","sentAt":"2010-07-11T06:27:34Z","receivedAt":"2010-07-11T06:27:34Z","isPatch":true,"sender":{"key":"struggleyb.nku@gmail.com","avatar":"https://avatars.githubusercontent.com/u/233030?v=4"},"body":"The function rewrite_one is used to rewrite a single\nparent of the current commit, and is used by rewrite_parents\nto rewrite all the parents.\nThis commit decouple the dependence between them, make\nrewrite_one as a callback function and be passed to\nrewrite_parents. Make rewrite_parents public to other\npart of git.\nWe will use this function in line.c.\n\nSigned-off-by: Bo Yang <struggleyb.nku@gmail.com>\n---\n revision.c |   11 +++--------\n revision.h |   10 ++++++++++\n 2 files changed, 13 insertions(+), 8 deletions(-)\n\ndiff --git a/revision.c b/revision.c\nindex 63f37ea..72d9654 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1893,12 +1893,6 @@ int prepare_revision_walk(struct rev_info *revs)\n \treturn 0;\n }\n \n-enum rewrite_result {\n-\trewrite_one_ok,\n-\trewrite_one_noparents,\n-\trewrite_one_error\n-};\n-\n static enum rewrite_result rewrite_one(struct rev_info *revs, struct commit **pp)\n {\n \tstruct commit_list *cache = NULL;\n@@ -1920,7 +1914,8 @@ static enum rewrite_result rewrite_one(struct rev_info *revs, struct commit **pp\n \t}\n }\n \n-static int rewrite_parents(struct rev_info *revs, struct commit *commit)\n+int rewrite_parents(struct rev_info *revs, struct commit *commit,\n+\trewrite_parent rewrite_one)\n {\n \tstruct commit_list **pp = &commit->parents;\n \twhile (*pp) {\n@@ -1993,7 +1988,7 @@ enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit)\n \tif (action == commit_show &&\n \t    !revs->show_all &&\n \t    revs->prune && revs->dense && want_ancestry(revs)) {\n-\t\tif (rewrite_parents(revs, commit) < 0)\n+\t\tif (rewrite_parents(revs, commit, rewrite_one) < 0)\n \t\t\treturn commit_error;\n \t}\n \treturn action;\ndiff --git a/revision.h b/revision.h\nindex 433da9a..9b8e3d9 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -200,4 +200,14 @@ enum commit_action {\n extern enum commit_action get_commit_action(struct rev_info *revs, struct commit *commit);\n extern enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit);\n \n+enum rewrite_result {\n+\trewrite_one_ok,\n+\trewrite_one_noparents,\n+\trewrite_one_error\n+};\n+\n+typedef enum rewrite_result (*rewrite_parent)(struct rev_info *revs, struct commit **pp);\n+\n+extern int rewrite_parents(struct rev_info *revs, struct commit *commit,\n+\trewrite_parent rewrite_one);\n #endif\n-- \n1.7.0.2.273.gc2413.dirty\n"},{"id":"145309","messageId":"1278829657-26607-3-git-send-email-struggleyb.nku@gmail.com","threadId":"24365","inReplyTo":"1278829657-26607-1-git-send-email-struggleyb.nku@gmail.com","subject":"[PATCH v1 2/4] add parent rewrite feature to line level log","fromName":"Bo Yang","fromEmail":"struggleyb.nku@gmail.com","sentAt":"2010-07-11T06:27:35Z","receivedAt":"2010-07-11T06:27:35Z","isPatch":true,"sender":{"key":"struggleyb.nku@gmail.com","avatar":"https://avatars.githubusercontent.com/u/233030?v=4"},"body":"Two kinds of commit are qualified as a parent:\n 1. The commit touch some lines of the current\n    interesting range;\n 2. The commit is a merge commit.\n\nSo, there will be more commits output than the\nsituation which parent rewrite is not set on.\n\nSigned-off-by: Bo Yang <struggleyb.nku@gmail.com>\n---\n line.c     |   94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--\n line.h     |    2 +\n revision.c |    3 ++\n 3 files changed, 96 insertions(+), 3 deletions(-)\n\ndiff --git a/line.c b/line.c\nindex c08b510..0d62732 100644\n--- a/line.c\n+++ b/line.c\n@@ -10,6 +10,9 @@\n #include \"xdiff-interface.h\"\n #include \"strbuf.h\"\n #include \"log-tree.h\"\n+#include \"graph.h\"\n+\n+static int limited = 0;\n \n static void cleanup(struct diff_line_range *r)\n {\n@@ -1213,12 +1216,12 @@ int cmd_line_log_walk(struct rev_info *rev)\n \t\tdie(\"revision walk prepare failed\");\n \n \tlist = rev->commits;\n-\tif (list) {\n+\tif (list && !limited) {\n \t\tlist->item->object.flags |= RANGE_UPDATE;\n \t\tlist = list->next;\n \t}\n \t/* Clear the flags */\n-\twhile (list) {\n+\twhile (list && !limited) {\n \t\tlist->item->object.flags &= 0x0;\n \t\tlist = list->next;\n \t}\n@@ -1232,7 +1235,9 @@ int cmd_line_log_walk(struct rev_info *rev)\n \t\t\tassign_parents_range(rev, commit);\n \t\t}\n \n-\t\tif (commit->object.flags & NEED_PRINT || rev->always_print) {\n+\t\tif (commit->object.flags & NEED_PRINT || rev->always_print || rev->graph) {\n+\t\t\tif (rev->graph)\n+\t\t\t\tgraph_update(rev->graph, commit);\n \t\t\tline_log_flush(rev, commit);\n \t\t}\n \n@@ -1257,3 +1262,86 @@ int cmd_line_log_walk(struct rev_info *rev)\n \treturn 0;\n }\n \n+static enum rewrite_result rewrite_one(struct rev_info *rev, struct commit **pp)\n+{\n+\tstruct diff_line_range *r = NULL;\n+\tstruct commit *p;\n+\twhile (1) {\n+\t\tp = *pp;\n+\t\tif (p->object.flags & RANGE_UPDATE)\n+\t\t\tassign_parents_range(rev, p);\n+\t\tif (p->parents && p->parents->next)\n+\t\t\treturn rewrite_one_ok;\n+\t\tif (p->object.flags & NEED_PRINT)\n+\t\t\treturn rewrite_one_ok;\n+\t\tif (!p->parents)\n+\t\t\treturn rewrite_one_noparents;\n+\n+\t\tr = lookup_line_range(rev, p);\n+\t\tif (!r)\n+\t\t\treturn rewrite_one_noparents;\n+\t\t*pp = p->parents->item;\n+\t}\n+}\n+\n+/* The rev->commits must be sorted in topologically order */\n+void limit_list_line(struct rev_info *rev)\n+{\n+\tstruct commit_list *list = rev->commits;\n+\tstruct commit_list *commits = xmalloc(sizeof(struct commit_list));\n+\tstruct commit_list *out = commits, *prev = commits;\n+\tstruct commit *c;\n+\tstruct diff_line_range *r;\n+\n+\tif (list) {\n+\t\tlist->item->object.flags |= RANGE_UPDATE;\n+\t\tlist = list->next;\n+\t}\n+\t/* Clear the flags */\n+\twhile (list) {\n+\t\tlist->item->object.flags &= 0x0;\n+\t\tlist = list->next;\n+\t}\n+\n+\tlist = rev->commits;\n+\twhile (list) {\n+\t\tc = list->item;\n+\n+\t\tif (c->object.flags & RANGE_UPDATE)\n+\t\t\tassign_parents_range(rev, c);\n+\n+\t\tif (c->object.flags & NEED_PRINT ||\n+\t\t\t(c->parents && c->parents->next)) {\n+\t\t\tif (rewrite_parents(rev, c, rewrite_one))\n+\t\t\t\tdie(\"Can't rewrite parent for commit %s\",\n+\t\t\t\t\tsha1_to_hex(c->object.sha1));\n+\t\t\tcommits->item = c;\n+\t\t\tcommits->next = xmalloc(sizeof(struct commit_list));\n+\t\t\tprev = commits;\n+\t\t\tcommits = commits->next;\n+\t\t} else {\n+\t\t\tr = lookup_line_range(rev, c);\n+\t\t\tif (r) {\n+\t\t\t\tcleanup(r);\n+\t\t\t\tr = NULL;\n+\t\t\t\tadd_line_range(rev, c, r);\n+\t\t\t}\n+\t\t}\n+\n+\t\tlist = list->next;\n+\t}\n+\n+\tprev->next = NULL;\n+\tfree(commits);\n+\n+\tlist = rev->commits;\n+\twhile (list) {\n+\t\tstruct commit_list *l = list;\n+\t\tlist = list->next;\n+\t\tfree(l);\n+\t}\n+\n+\trev->commits = out;\n+\tlimited = 1;\n+}\n+\ndiff --git a/line.h b/line.h\nindex b293894..90d7c1a 100644\n--- a/line.h\n+++ b/line.h\n@@ -130,4 +130,6 @@ const char *parse_loc(const char *spec, nth_line_fn_t nth_line,\n \n extern int cmd_line_log_walk(struct rev_info *rev);\n \n+extern void limit_list_line(struct rev_info *rev);\n+\n #endif\ndiff --git a/revision.c b/revision.c\nindex 72d9654..659cec7 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -13,6 +13,7 @@\n #include \"decorate.h\"\n #include \"log-tree.h\"\n #include \"string-list.h\"\n+#include \"line.h\"\n \n volatile show_early_output_fn_t show_early_output;\n \n@@ -1886,6 +1887,8 @@ int prepare_revision_walk(struct rev_info *revs)\n \t\t\treturn -1;\n \tif (revs->topo_order)\n \t\tsort_in_topological_order(&revs->commits, revs->lifo);\n+\tif (revs->rewrite_parents && revs->line)\n+\t\tlimit_list_line(revs);\n \tif (revs->simplify_merges)\n \t\tsimplify_merges(revs);\n \tif (revs->children.name)\n-- \n1.7.0.2.273.gc2413.dirty\n"},{"id":"145308","messageId":"1278829657-26607-4-git-send-email-struggleyb.nku@gmail.com","threadId":"24365","inReplyTo":"1278829657-26607-1-git-send-email-struggleyb.nku@gmail.com","subject":"[PATCH v1 3/4] line.c output the '--graph' padding before each line","fromName":"Bo Yang","fromEmail":"struggleyb.nku@gmail.com","sentAt":"2010-07-11T06:27:36Z","receivedAt":"2010-07-11T06:27:36Z","isPatch":true,"sender":{"key":"struggleyb.nku@gmail.com","avatar":"https://avatars.githubusercontent.com/u/233030?v=4"},"body":"Make line level log output looks well with '--graph'\noption.\n\nSigned-off-by: Bo Yang <struggleyb.nku@gmail.com>\n---\n line.c |   83 +++++++++++++++++++++++++++++++++++++++++++++------------------\n 1 files changed, 59 insertions(+), 24 deletions(-)\n\ndiff --git a/line.c b/line.c\nindex 0d62732..04a3500 100644\n--- a/line.c\n+++ b/line.c\n@@ -967,6 +967,13 @@ static void flush_lines(struct diff_options *opt, const char **ptr, const char *\n \tconst char *p = *ptr;\n \tstruct strbuf buf = STRBUF_INIT;\n \tconst char *reset;\n+\tchar *line_prefix = \"\";\n+\tstruct strbuf *msgbuf;\n+\n+\tif (opt && opt->output_prefix) {\n+\t\tmsgbuf = opt->output_prefix(opt, opt->output_prefix_data);\n+\t\tline_prefix = msgbuf->buf;\n+\t}\n \n \tif (strcmp(color, \"\"))\n \t\treset = \"\";\n@@ -987,13 +994,9 @@ static void flush_lines(struct diff_options *opt, const char **ptr, const char *\n \tassert(*ptr <= end);\n \tp = *ptr;\n \n-\t/*\n-\t * todo: when --graph landed on master, this should be changed\n-\t * a little.\n-\t */\n \twhile (*ptr < end && *lno <= elno) {\n \t\tif (**ptr == '\\n') {\n-\t\t\tfprintf(opt->file, \"%s\", buf.buf);\n+\t\t\tfprintf(opt->file, \"%s%s\", line_prefix, buf.buf);\n \t\t\tif (*ptr - p) {\n \t\t\t\tfwrite(p, *ptr - p, 1, opt->file);\n \t\t\t}\n@@ -1004,7 +1007,7 @@ static void flush_lines(struct diff_options *opt, const char **ptr, const char *\n \t\t(*ptr)++;\n \t}\n \tif (*lno <= elno) {\n-\t\tfprintf(opt->file, \"%s\", buf.buf);\n+\t\tfprintf(opt->file, \"%s%s\", line_prefix, buf.buf);\n \t\tif (*ptr - p) {\n \t\t\tfwrite(p, *ptr - p, 1, opt->file);\n \t\t}\n@@ -1047,8 +1050,15 @@ static void diff_flush_chunks(struct diff_options *opt, struct line_chunk *chunk\n \tstruct diff_line_range *range = chunk->range;\n \tconst char *set = diff_get_color_opt(opt, DIFF_FRAGINFO);\n \tconst char *reset = diff_get_color_opt(opt, DIFF_RESET);\n+\tchar *line_prefix = \"\";\n+\tstruct strbuf *msgbuf;\n \tint i;\n \n+\tif (opt && opt->output_prefix) {\n+\t\tmsgbuf = opt->output_prefix(opt, opt->output_prefix_data);\n+\t\tline_prefix = msgbuf->buf;\n+\t}\n+\n \tfor (i = 0; i < range->nr; i++) {\n \t\tstruct range *r = range->ranges + i;\n \t\tlong lenp = r->pend - r->pstart + 1, pstart = r->pstart;\n@@ -1056,8 +1066,8 @@ static void diff_flush_chunks(struct diff_options *opt, struct line_chunk *chunk\n \t\tif (pstart == 0)\n \t\t\tlenp = 0;\n \n-\t\tfprintf(opt->file, \"%s@@ -%ld,%ld +%ld,%ld @@%s\\n\",\n-\t\t\tset, pstart, lenp, r->start, len, reset);\n+\t\tfprintf(opt->file, \"%s%s@@ -%ld,%ld +%ld,%ld @@%s\\n\",\n+\t\t\tline_prefix, set, pstart, lenp, r->start, len, reset);\n \n \t\tdiff_flush_range(opt, chunk, r);\n \t}\n@@ -1076,6 +1086,13 @@ static void diff_flush_filepair(struct rev_info *rev, struct diff_line_range *ra\n \tconst char *reset = diff_get_color_opt(opt, DIFF_RESET);\n \tstruct line_chunk chunk;\n \tint must_show_header;\n+\tchar *line_prefix = \"\";\n+\tstruct strbuf *msgbuf;\n+\n+\tif (opt && opt->output_prefix) {\n+\t\tmsgbuf = opt->output_prefix(opt, opt->output_prefix_data);\n+\t\tline_prefix = msgbuf->buf;\n+\t}\n \n \t/*\n \t * the ranges that touch no different file, in this case\n@@ -1117,21 +1134,26 @@ static void diff_flush_filepair(struct rev_info *rev, struct diff_line_range *ra\n \tb_two = quote_two(b_prefix, name_b + (*name_b == '/'));\n \tlbl[0] = DIFF_FILE_VALID(one) ? a_one : \"/dev/null\";\n \tlbl[1] = DIFF_FILE_VALID(two) ? b_two : \"/dev/null\";\n-\tstrbuf_addf(&header, \"%sdiff --git %s %s%s\\n\", set, a_one, b_two, reset);\n+\tstrbuf_addf(&header, \"%s%sdiff --git %s %s%s\\n\", line_prefix,\n+\t\t\tset, a_one, b_two, reset);\n \tif (lbl[0][0] == '/') {\n-\t\tstrbuf_addf(&header, \"%snew file mode %06o%s\\n\", set, two->mode, reset);\n+\t\tstrbuf_addf(&header, \"%s%snew file mode %06o%s\\n\",\n+\t\t\tline_prefix, set, two->mode, reset);\n \t} else if (lbl[1][0] == '/') {\n-\t\tstrbuf_addf(&header, \"%sdeleted file mode %06o%s\\n\", set, one->mode, reset);\n+\t\tstrbuf_addf(&header, \"%s%sdeleted file mode %06o%s\\n\",\n+\t\t\tline_prefix, set, one->mode, reset);\n \t} else if (one->mode != two->mode) {\n-\t\t\tstrbuf_addf(&header, \"%sold mode %06o%s\\n\", set, one->mode, reset);\n-\t\t\tstrbuf_addf(&header, \"%snew mode %06o%s\\n\", set, two->mode, reset);\n+\t\t\tstrbuf_addf(&header, \"%s%sold mode %06o%s\\n\",\n+\t\t\t\tline_prefix, set, one->mode, reset);\n+\t\t\tstrbuf_addf(&header, \"%s%snew mode %06o%s\\n\",\n+\t\t\t\tline_prefix, set, two->mode, reset);\n \t}\n \n \tfprintf(opt->file, \"%s%s\", header.buf, meta.buf);\n \tstrbuf_release(&meta);\n \tstrbuf_release(&header);\n-\tfprintf(opt->file, \"%s--- %s%s\\n\", set, lbl[0], reset);\n-\tfprintf(opt->file, \"%s+++ %s%s\\n\", set, lbl[1], reset);\n+\tfprintf(opt->file, \"%s%s--- %s%s\\n\", line_prefix, set, lbl[0], reset);\n+\tfprintf(opt->file, \"%s%s+++ %s%s\\n\", line_prefix, set, lbl[1], reset);\n \tfree((void *)a_one);\n \tfree((void *)b_two);\n \n@@ -1153,24 +1175,33 @@ static void flush_nontrivial_merge(struct rev_info *rev, struct diff_line_range\n \tconst char *frag = diff_get_color_opt(opt, DIFF_FRAGINFO);\n \tconst char *meta = diff_get_color_opt(opt, DIFF_METAINFO);\n \tconst char *new = diff_get_color_opt(opt, DIFF_FILE_NEW);\n+\tchar *line_prefix = \"\";\n+\tstruct strbuf *msgbuf;\n \n-\tfprintf(opt->file, \"%s%s%s\\n\", meta, EVIL_MERGE_STR, reset);\n+\tif (opt && opt->output_prefix) {\n+\t\tmsgbuf = opt->output_prefix(opt, opt->output_prefix_data);\n+\t\tline_prefix = msgbuf->buf;\n+\t}\n+\n+\tfprintf(opt->file, \"%s%s%s%s\\n\", line_prefix, meta, EVIL_MERGE_STR, reset);\n \n \twhile (range) {\n \t\tif (range->nr) {\n-\t\t\tfprintf(opt->file, \"%s%s%s\\n\\n\", meta, range->spec->path, reset);\n+\t\t\tfprintf(opt->file, \"%s%s%s%s\\n%s\\n\", line_prefix,\n+\t\t\t\tmeta, range->spec->path, reset, line_prefix);\n \t\t\tint lno = 1;\n \t\t\tconst char *ptr = range->spec->data;\n \t\t\tconst char *end = range->spec->data + range->spec->size;\n \t\t\tint i = 0;\n \t\t\tfor (; i < range->nr; i++) {\n \t\t\t\tstruct range *r = range->ranges + i;\n-\t\t\t\tfprintf(opt->file, \"%s@@ %ld,%ld @@%s\\n\", frag, r->start,\n+\t\t\t\tfprintf(opt->file, \"%s%s@@ %ld,%ld @@%s\\n\",\n+\t\t\t\t\tline_prefix, frag, r->start,\n \t\t\t\t\tr->end - r->start + 1, reset);\n \t\t\t\tflush_lines(opt, &ptr, end, r->start, r->end,\n \t\t\t\t\t&lno, new, ' ');\n \t\t\t}\n-\t\t\tfprintf(opt->file, \"\\n\");\n+\t\t\tfprintf(opt->file, \"%s\\n\", line_prefix);\n \t\t}\n \t\trange = range->next;\n \t}\n@@ -1181,6 +1212,9 @@ static void line_log_flush(struct rev_info *rev, struct commit *c)\n \tstruct diff_line_range *range = lookup_line_range(rev, c);\n \tstruct diff_line_range *nontrivial = lookup_decoration(&rev->nontrivial_merge, &c->object);\n \tstruct log_info log;\n+\tstruct diff_options *opt = &rev->diffopt;\n+\tchar *line_prefix = \"\";\n+\tstruct strbuf *msgbuf;\n \n \tif (range == NULL)\n \t\treturn;\n@@ -1190,11 +1224,12 @@ static void line_log_flush(struct rev_info *rev, struct commit *c)\n \trev->loginfo = &log;\n \tshow_log(rev);\n \trev->loginfo = NULL;\n-\t/*\n-\t * Add a new line after each commit message, of course we should\n-\t * add --graph alignment later when the patches comes to master.\n-\t */\n-\tfprintf(rev->diffopt.file, \"\\n\");\n+\n+\tif (opt && opt->output_prefix) {\n+\t\tmsgbuf = opt->output_prefix(opt, opt->output_prefix_data);\n+\t\tline_prefix = msgbuf->buf;\n+\t}\n+\tfprintf(rev->diffopt.file, \"%s\\n\", line_prefix);\n \n \tif (c->object.flags & EVIL_MERGE)\n \t\treturn flush_nontrivial_merge(rev, nontrivial);\n-- \n1.7.0.2.273.gc2413.dirty\n"},{"id":"145311","messageId":"1278829657-26607-5-git-send-email-struggleyb.nku@gmail.com","threadId":"24365","inReplyTo":"1278829657-26607-1-git-send-email-struggleyb.nku@gmail.com","subject":"[PATCH v1 4/4] add test cases for '--graph' of line level log","fromName":"Bo Yang","fromEmail":"struggleyb.nku@gmail.com","sentAt":"2010-07-11T06:27:37Z","receivedAt":"2010-07-11T06:27:37Z","isPatch":true,"sender":{"key":"struggleyb.nku@gmail.com","avatar":"https://avatars.githubusercontent.com/u/233030?v=4"},"body":"t/t4301-log-line-single-history.sh:\n  test the linear line of history with '--graph' option;\n\nt/t4302-log-line-merge-history.sh:\n  test the case that there are merges in the history with\n  '--graph' option.\n\nNote that, '--always-print' option will take no effect when\n'--graph' is also given.\n\nSigned-off-by: Bo Yang <struggleyb.nku@gmail.com>\n---\n Documentation/git-log.txt          |    2 +\n t/t4301-log-line-single-history.sh |  225 ++++++++++++++++++++++++++++++++++++\n t/t4302-log-line-merge-history.sh  |   51 ++++++++-\n 3 files changed, 277 insertions(+), 1 deletions(-)\n\ndiff --git a/Documentation/git-log.txt b/Documentation/git-log.txt\nindex 14a9703..96ae0fe 100644\n--- a/Documentation/git-log.txt\n+++ b/Documentation/git-log.txt\n@@ -101,6 +101,8 @@ of lines before or after the line given by <start>.\n --always-print::\n \tAlways print the interesting range even if the current commit\n \tdoes not change any line of the range.\n+\tNote that this option will take no effect when '--graph' is\n+\talso given.\n \n \n include::rev-list-options.txt[]\ndiff --git a/t/t4301-log-line-single-history.sh b/t/t4301-log-line-single-history.sh\nindex 9981496..29091af 100755\n--- a/t/t4301-log-line-single-history.sh\n+++ b/t/t4301-log-line-single-history.sh\n@@ -339,4 +339,229 @@ test_expect_success \\\n \t test_cmp current-linenum expected-linenum &&\n \t test_cmp current-always expected-always'\n \n+# Rerun all log with graph\n+test_expect_success \\\n+    'Show the line level log of path0 with --graph' \\\n+    'git log --pretty=format:%s%n%b --graph -L /func/,/^}/ path0 > current-path0-graph'\n+\n+test_expect_success \\\n+    'Show the line level log of path1 with --graph' \\\n+    'git log --pretty=format:%s%n%b --graph -L /output/,/^}/ path1 > current-path1-graph'\n+\n+test_expect_success \\\n+    'Show the line level log of two files with --graph' \\\n+    'git log --pretty=format:%s%n%b --graph -L /func/,/^}/ path0 --graph -L /output/,/^}/ path1 > current-pathall-graph'\n+\n+test_expect_success \\\n+    'Test the line number argument with --graph' \\\n+    'git log --pretty=format:%s%n%b --graph -L 1,2 path0 > current-linenum-graph'\n+\n+test_expect_success \\\n+\t'Test the --always-print option with --graph option' \\\n+\t'git log --pretty=format:%s%n%b --always-print --graph -L 1,2 path0 > current-always-graph'\n+\n+cat > expected-path0-graph <<\\EOF\n+* Final change of path0\n+| \n+| diff --git a/path0 b/path0\n+| index 44db133..1518c15 100644\n+| --- a/path0\n+| +++ b/path0\n+| @@ -1,6 +1,5 @@\n+|  void func(){\n+|  \tint a = 10;\n+|  \tint b = 11;\n+| -\tint c;\n+| -\tc = 10 * (a + b);\n+| +\tprintf(\"%d\", a - b);\n+|  }\n+|  \n+* Change the 5th line of path0\n+| \n+| diff --git a/path0 b/path0\n+| index 9ef1692..44db133 100644\n+| --- a/path0\n+| +++ b/path0\n+| @@ -1,6 +1,6 @@\n+|  void func(){\n+|  \tint a = 10;\n+|  \tint b = 11;\n+|  \tint c;\n+| -\tc = a + b;\n+| +\tc = 10 * (a + b);\n+|  }\n+|  \n+* Change 2,3 lines of path0 and path1\n+| \n+| diff --git a/path0 b/path0\n+| index aabffdf..9ef1692 100644\n+| --- a/path0\n+| +++ b/path0\n+| @@ -1,6 +1,6 @@\n+|  void func(){\n+| -\tint a = 0;\n+| -\tint b = 1;\n+| +\tint a = 10;\n+| +\tint b = 11;\n+|  \tint c;\n+|  \tc = a + b;\n+|  }\n+|  \n+* Base commit\n+  \n+  diff --git a/path0 b/path0\n+  new file mode 100644\n+  index 0000000..aabffdf\n+  --- /dev/null\n+  +++ b/path0\n+  @@ -0,0 +1,6 @@\n+  +void func(){\n+  +\tint a = 0;\n+  +\tint b = 1;\n+  +\tint c;\n+  +\tc = a + b;\n+  +}\n+EOF\n+\n+cat > expected-path1-graph <<\\EOF\n+* Change 2,3 lines of path0 and path1\n+| \n+| diff --git a/path1 b/path1\n+| index 997d841..1d711b5 100644\n+| --- a/path1\n+| +++ b/path1\n+| @@ -1,3 +1,4 @@\n+|  void output(){\n+| -\tprintf(\"hello world\");\n+| +\tconst char *str = \"hello world!\";\n+| +\tprintf(\"%s\", str);\n+|  }\n+|  \n+* Base commit\n+  \n+  diff --git a/path1 b/path1\n+  new file mode 100644\n+  index 0000000..997d841\n+  --- /dev/null\n+  +++ b/path1\n+  @@ -0,0 +1,3 @@\n+  +void output(){\n+  +\tprintf(\"hello world\");\n+  +}\n+EOF\n+\n+cat > expected-pathall-graph <<\\EOF\n+* Final change of path0\n+| \n+| diff --git a/path0 b/path0\n+| index 44db133..1518c15 100644\n+| --- a/path0\n+| +++ b/path0\n+| @@ -1,6 +1,5 @@\n+|  void func(){\n+|  \tint a = 10;\n+|  \tint b = 11;\n+| -\tint c;\n+| -\tc = 10 * (a + b);\n+| +\tprintf(\"%d\", a - b);\n+|  }\n+|  \n+* Change the 5th line of path0\n+| \n+| diff --git a/path0 b/path0\n+| index 9ef1692..44db133 100644\n+| --- a/path0\n+| +++ b/path0\n+| @@ -1,6 +1,6 @@\n+|  void func(){\n+|  \tint a = 10;\n+|  \tint b = 11;\n+|  \tint c;\n+| -\tc = a + b;\n+| +\tc = 10 * (a + b);\n+|  }\n+|  \n+* Change 2,3 lines of path0 and path1\n+| \n+| diff --git a/path0 b/path0\n+| index aabffdf..9ef1692 100644\n+| --- a/path0\n+| +++ b/path0\n+| @@ -1,6 +1,6 @@\n+|  void func(){\n+| -\tint a = 0;\n+| -\tint b = 1;\n+| +\tint a = 10;\n+| +\tint b = 11;\n+|  \tint c;\n+|  \tc = a + b;\n+|  }\n+| diff --git a/path1 b/path1\n+| index 997d841..1d711b5 100644\n+| --- a/path1\n+| +++ b/path1\n+| @@ -1,3 +1,4 @@\n+|  void output(){\n+| -\tprintf(\"hello world\");\n+| +\tconst char *str = \"hello world!\";\n+| +\tprintf(\"%s\", str);\n+|  }\n+|  \n+* Base commit\n+  \n+  diff --git a/path0 b/path0\n+  new file mode 100644\n+  index 0000000..aabffdf\n+  --- /dev/null\n+  +++ b/path0\n+  @@ -0,0 +1,6 @@\n+  +void func(){\n+  +\tint a = 0;\n+  +\tint b = 1;\n+  +\tint c;\n+  +\tc = a + b;\n+  +}\n+  diff --git a/path1 b/path1\n+  new file mode 100644\n+  index 0000000..997d841\n+  --- /dev/null\n+  +++ b/path1\n+  @@ -0,0 +1,3 @@\n+  +void output(){\n+  +\tprintf(\"hello world\");\n+  +}\n+EOF\n+\n+cat > expected-linenum-graph <<\\EOF\n+* Change 2,3 lines of path0 and path1\n+| \n+| diff --git a/path0 b/path0\n+| index aabffdf..9ef1692 100644\n+| --- a/path0\n+| +++ b/path0\n+| @@ -1,2 +1,2 @@\n+|  void func(){\n+| -\tint a = 0;\n+| +\tint a = 10;\n+|  \n+* Base commit\n+  \n+  diff --git a/path0 b/path0\n+  new file mode 100644\n+  index 0000000..aabffdf\n+  --- /dev/null\n+  +++ b/path0\n+  @@ -0,0 +1,2 @@\n+  +void func(){\n+  +\tint a = 0;\n+EOF\n+\n+test_expect_success \\\n+    'validate the output.' \\\n+    'test_cmp current-path0-graph expected-path0-graph &&\n+\t test_cmp current-path1-graph expected-path1-graph &&\n+\t test_cmp current-pathall-graph expected-pathall-graph &&\n+\t test_cmp current-linenum-graph expected-linenum-graph &&\n+\t test_cmp current-always-graph expected-linenum-graph'\n+\n test_done\ndiff --git a/t/t4302-log-line-merge-history.sh b/t/t4302-log-line-merge-history.sh\nindex 02e7439..cd417d3 100755\n--- a/t/t4302-log-line-merge-history.sh\n+++ b/t/t4302-log-line-merge-history.sh\n@@ -107,8 +107,57 @@ index 0000000..f628dea\n +\tprintf(\"hello\");\n +}\n EOF\n+\n+cat > expected-graph <<\\EOF\n+*   Merge two branches\n+|\\  \n+| | \n+| | nontrivial merge found\n+| | path0\n+| | \n+| | @@ 2,1 @@\n+| |  \tprintf(\"hello earth and moon\");\n+| | \n+| |   \n+| * Change path0 in master\n+| | \n+| | diff --git a/path0 b/path0\n+| | index f628dea..bef7fa3 100644\n+| | --- a/path0\n+| | +++ b/path0\n+| | @@ -2,1 +2,1 @@\n+| | -\tprintf(\"hello\");\n+| | +\tprintf(\"hello earth\");\n+| |   \n+* | Change path0 in feature\n+|/  \n+|   \n+|   diff --git a/path0 b/path0\n+|   index f628dea..a940ef6 100644\n+|   --- a/path0\n+|   +++ b/path0\n+|   @@ -2,1 +2,1 @@\n+|   -\tprintf(\"hello\");\n+|   +\tprint(\"hello moon\");\n+|  \n+* Base commit\n+  \n+  diff --git a/path0 b/path0\n+  new file mode 100644\n+  index 0000000..f628dea\n+  --- /dev/null\n+  +++ b/path0\n+  @@ -0,0 +2,1 @@\n+  +\tprintf(\"hello\");\n+EOF\n+\n+test_expect_success \\\n+    'Show the line log of the 2 line of path0 with graph' \\\n+    'git log --pretty=format:%s%n%b --graph -L 2,+1 path0 > current-graph'\n+\n test_expect_success \\\n     'validate the output.' \\\n-    'test_cmp current expected'\n+    'test_cmp current expected &&\n+     test_cmp current-graph expected-graph'\n \n test_done\n-- \n1.7.0.2.273.gc2413.dirty\n"},{"id":"145458","messageId":"7vy6df2jns.fsf@alter.siamese.dyndns.org","threadId":"24365","inReplyTo":"1278829657-26607-3-git-send-email-struggleyb.nku@gmail.com","subject":"Re: [PATCH v1 2/4] add parent rewrite feature to line level log","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-07-13T20:47:51Z","receivedAt":"2010-07-13T20:47:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Bo Yang <struggleyb.nku@gmail.com> writes:\n\n> Two kinds of commit are qualified as a parent:\n>  1. The commit touch some lines of the current\n>     interesting range;\n>  2. The commit is a merge commit.\n>\n> So, there will be more commits output than the\n> situation which parent rewrite is not set on.\n\nSorry, but -ECANTPARSEATALL.  What do you mean by \"qualified\" and in what\ncontext?  What makes these two conditions significant?\n"},{"id":"145459","messageId":"7vsk3n2jkp.fsf@alter.siamese.dyndns.org","threadId":"24365","inReplyTo":"1278829657-26607-4-git-send-email-struggleyb.nku@gmail.com","subject":"Re: [PATCH v1 3/4] line.c output the '--graph' padding before each line","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-07-13T20:49:42Z","receivedAt":"2010-07-13T20:49:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Bo Yang <struggleyb.nku@gmail.com> writes:\n\n> Make line level log output looks well with '--graph'\n> option.\n\nThis is probably better done as part of rebasing the previous line-range\nseries to a more recent codebase that already has the --graph fixes, not\nas a separate \"oops, my codebase was stale--here is a fix-up\" patch.\n"},{"id":"145575","messageId":"7vpqypyj43.fsf@alter.siamese.dyndns.org","threadId":"24365","inReplyTo":"1278829657-26607-2-git-send-email-struggleyb.nku@gmail.com","subject":"Re: [PATCH v1 1/4] make rewrite_parents an external function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-07-14T19:10:52Z","receivedAt":"2010-07-14T19:10:52Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Bo Yang <struggleyb.nku@gmail.com> writes:\n\n> The function rewrite_one is used to rewrite a single\n> parent of the current commit, and is used by rewrite_parents\n> to rewrite all the parents.\n> This commit decouple the dependence between them, make\n> rewrite_one as a callback function and be passed to\n> rewrite_parents. Make rewrite_parents public to other\n> part of git.\n> We will use this function in line.c.\n\nSorry, but -ECANTREALLYPARSE.\n\nThis particular refactoring is probably harmless, but we would need to see\nhow it is used to convince ourselves it is a good change.\n\n> @@ -1920,7 +1914,8 @@ static enum rewrite_result rewrite_one(struct rev_info *revs, struct commit **pp\n>  \t}\n>  }\n>  \n> -static int rewrite_parents(struct rev_info *revs, struct commit *commit)\n> +int rewrite_parents(struct rev_info *revs, struct commit *commit,\n> +\trewrite_parent rewrite_one)\n>  {\n>  \tstruct commit_list **pp = &commit->parents;\n>  \twhile (*pp) {\n> @@ -1993,7 +1988,7 @@ enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit)\n>  \tif (action == commit_show &&\n>  \t    !revs->show_all &&\n>  \t    revs->prune && revs->dense && want_ancestry(revs)) {\n> -\t\tif (rewrite_parents(revs, commit) < 0)\n> +\t\tif (rewrite_parents(revs, commit, rewrite_one) < 0)\n>  \t\t\treturn commit_error;\n>  \t}\n>  \treturn action;\n\nIt would probably make sense to rename this \"rewrite_one\" (local function\npointer variable) not to collide with the \"rewrite_one\" (static function)\nfor readability.\n\n> diff --git a/revision.h b/revision.h\n> index 433da9a..9b8e3d9 100644\n> --- a/revision.h\n> +++ b/revision.h\n> @@ -200,4 +200,14 @@ enum commit_action {\n>  extern enum commit_action get_commit_action(struct rev_info *revs, struct commit *commit);\n>  extern enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit);\n>  \n> +enum rewrite_result {\n> +\trewrite_one_ok,\n> +\trewrite_one_noparents,\n> +\trewrite_one_error\n> +};\n> +\n> +typedef enum rewrite_result (*rewrite_parent)(struct rev_info *revs, struct commit **pp);\n\nYikes; at least name the type rewrite_parent_fn or something for readability.\n\n\n> +extern int rewrite_parents(struct rev_info *revs, struct commit *commit,\n> +\trewrite_parent rewrite_one);\n>  #endif\n> -- \n> 1.7.0.2.273.gc2413.dirty\n"}]}