[WIP PATCH 20/22] some changes
1. if one parent is responsible for all ranges, then prune the
parents list to only this one;
2. some other minor changes.
Signed-off-by: Bo Yang <struggleyb.nku@gmail.com>
---
line.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 106 insertions(+), 22 deletions(-)
diff --git a/line.c b/line.c
index ca8980d..272f166 100644
--- a/line.c
+++ b/line.c
@@ -470,15 +470,15 @@ void add_line_range(struct rev_info *revs, struct commit *commit, struct diff_li
{
struct diff_line_range *ret = NULL;
- if (r != NULL) {
- ret = lookup_decoration(&revs->line_range, &commit->object);
- if (ret != NULL) {
- diff_line_range_merge(ret, r);
- } else {
- add_decoration(&revs->line_range, &commit->object, r);
- }
- commit->object.flags |= RANGE_UPDATE;
+ ret = lookup_decoration(&revs->line_range, &commit->object);
+ if (ret != NULL && r != NULL) {
+ diff_line_range_merge(ret, r);
+ } else {
+ add_decoration(&revs->line_range, &commit->object, r);
}
+
+ if (r != NULL)
+ commit->object.flags |= RANGE_UPDATE;
}
struct diff_line_range *lookup_line_range(struct rev_info *revs, struct commit *commit)
@@ -544,8 +544,26 @@ void map_lines(long p_start, long p_end, long t_start, long t_end,
return;
}
- if (start == t_start && end == t_end) {
+ if (start == t_start && end == t_end)
+ {
+ *o_start = p_start;
+ *o_end = p_end;
+ return;
+ }
+
+ if (start == t_start)
+ {
*o_start = p_start;
+ *o_end = p_start + (end - start);
+ if (*o_end > p_end)
+ *o_end = p_end;
+ return;
+ }
+
+ if (end == t_end) {
+ *o_start = p_end - (end - start);
+ if (*o_start < p_start)
+ *o_start = p_start;
*o_end = p_end;
return;
}
@@ -771,7 +789,7 @@ static void map_range_cb(void *data, long same, long p_next, long t_next)
d->tlno = t_next;
}
-static void assign_range_to_parent(struct rev_info *rev, struct commit *c,
+static int assign_range_to_parent(struct rev_info *rev, struct commit *c,
struct commit *p, struct diff_line_range *r,
struct diff_options *opt, int map)
{
@@ -917,20 +935,49 @@ static void assign_range_to_parent(struct rev_info *rev, struct commit *c,
}
}
+ if (!map)
+ goto out;
+
if (rr) {
assert(p);
add_line_range(rev, p, rr);
}
+ /* debug output */
+ /*
+ fprintf(stderr, "%8s..%8s:\n", sha1_to_hex(p->object.sha1), sha1_to_hex(c->object.sha1));
+ while (r) {
+ fprintf(stderr, "file: %s\n", r->spec->path);
+ int n = 0;
+ for (; n < r->nr; n++) {
+ fprintf(stderr, "%d-%d, ", r->ranges[n].start, r->ranges[n].end);
+ }
+ r = r->next;
+ }
+ fprintf(stderr, "\n");
+ while (rr) {
+ fprintf(stderr, "file: %s\n", rr->spec->path);
+ int n = 0;
+ for (; n < rr->nr; n++) {
+ fprintf(stderr, "%d-%d, ", rr->ranges[n].start, rr->ranges[n].end);
+ }
+ rr = rr->next;
+ }
+ fprintf(stderr, "\n");
+ */
+
/* and the ranges of current commit c is updated */
c->object.flags &= ~RANGE_UPDATE;
if (diff)
c->object.flags |= NEED_PRINT;
+out:
if (tree1)
free(tree1);
if (tree2)
free(tree2);
+
+ return diff;
}
static void diff_update_parent_range(struct rev_info *rev, struct commit *commit)
@@ -967,16 +1014,46 @@ static void assign_parents_range(struct rev_info *rev, struct commit *commit)
* be an evil merge.
*/
copy = diff_line_range_clone_deeply(r);
+ /* Never print out any diff for a merge commit */
+ commit->object.flags &= ~NEED_PRINT;
parents = commit->parents;
while (parents) {
struct commit *p = parents->item;
- assign_range_to_parent(rev, commit, p, r, &rev->diffopt, 1);
+ int diff = 0;
+ diff = assign_range_to_parent(rev, commit, p, r, &rev->diffopt, 1);
+ /* Since all the ranges comes from this parent, we can ignore others */
+ if (diff == 0) {
+ /* parent rewriting code */
+ parents = commit->parents;
+ while (parents->item != p) {
+ struct commit_list *list = parents;
+ struct diff_line_range *line_range = NULL;
+ parents = parents->next;
+ line_range = lookup_line_range(rev, list->item);
+ add_line_range(rev, list->item, NULL);
+ free(line_range);
+ list->item->object.flags &= ~(RANGE_UPDATE | NEED_PRINT | EVIL_MERGE);
+ free(list);
+ }
+ commit->parents = parents;
+ parents = parents->next;
+ commit->parents->next = NULL;
+ while (parents) {
+ struct commit_list *list = parents;
+ struct diff_line_range *line_range = NULL;
+ parents = parents->next;
+ line_range = lookup_line_range(rev, list->item);
+ add_line_range(rev, list->item, NULL);
+ free(line_range);
+ list->item->object.flags &= ~(RANGE_UPDATE | NEED_PRINT | EVIL_MERGE);
+ free(list);
+ }
+ return;
+ }
assign_range_to_parent(rev, commit, p, copy, &rev->diffopt, 0);
parents = parents->next;
}
- /* Never print out any diff for a merge commit */
- commit->object.flags &= ~NEED_PRINT;
/*
* yes, this must be an evil merge.
*/
@@ -1262,6 +1339,8 @@ static void line_log_flush(struct rev_info *rev, struct commit *c)
c->object.flags & NEED_PRINT))
return;
+ if (rev->graph)
+ graph_update(rev->graph, c);
log.commit = c;
log.parent = NULL;
rev->loginfo = &log;
@@ -1275,12 +1354,21 @@ static void line_log_flush(struct rev_info *rev, struct commit *c)
fprintf(rev->diffopt.file, "%s\n", line_prefix);
if (c->object.flags & EVIL_MERGE)
- return flush_nontrivial_merge(rev, nontrivial);
+ flush_nontrivial_merge(rev, nontrivial);
+ else {
+ while (range) {
+ if (range->diff || (range->nr && rev->full_line_diff))
+ diff_flush_filepair(rev, range);
+ range = range->next;
+ }
+ }
- while (range) {
- if (range->diff || (range->nr && rev->full_line_diff))
- diff_flush_filepair(rev, range);
- range = range->next;
+ while (rev->graph && !graph_is_commit_finished(rev->graph))
+ {
+ struct strbuf sb;
+ strbuf_init(&sb, 0);
+ graph_next_line(rev->graph, &sb);
+ fputs(sb.buf, opt->file);
}
}
@@ -1316,8 +1404,6 @@ int cmd_line_log_walk(struct rev_info *rev)
if (commit->object.flags & NEED_PRINT ||
commit->object.flags & EVIL_MERGE ||
rev->full_line_diff || rev->graph) {
- if (rev->graph)
- graph_update(rev->graph, commit);
line_log_flush(rev, commit);
}
@@ -1350,8 +1436,6 @@ static enum rewrite_result rewrite_one(struct rev_info *rev, struct commit **pp)
p = *pp;
if (p->object.flags & RANGE_UPDATE)
assign_parents_range(rev, p);
- if (p->parents && p->parents->next)
- return rewrite_one_ok;
if (p->object.flags & NEED_PRINT)
return rewrite_one_ok;
if (!p->parents)
--
1.7.0.2.273.gc2413.dirty