From: Junio C Hamano Date: Thu, 28 Jun 2012 22:20:16 +0000 (-0700) Subject: Merge branch 'jc/rev-list-simplify-merges-first-parent' X-Git-Tag: v1.7.12-rc0~71 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/331512f9888b1c95f61851e678201bfafb1e9245?ds=inline;hp=-c Merge branch 'jc/rev-list-simplify-merges-first-parent' When "--simplify-merges/by-decoration" is given together with "--first-parent" to "git log", the combination of these options makes the simplification logic to use in-core commit objects that haven't been examined for relevance, either producing incorrect result or taking too long to produce any output. Teach the simplification logic to ignore commits that the first-parent traversal logic ignored when both are in effect to work around the issue. --- 331512f9888b1c95f61851e678201bfafb1e9245 diff --combined revision.c index 39cc6b0eab,d1a4ef5da0..5b81a92e3a --- a/revision.c +++ b/revision.c @@@ -1358,11 -1358,13 +1358,13 @@@ static int handle_revision_opt(struct r revs->topo_order = 1; } else if (!strcmp(arg, "--simplify-merges")) { revs->simplify_merges = 1; + revs->topo_order = 1; revs->rewrite_parents = 1; revs->simplify_history = 0; revs->limited = 1; } else if (!strcmp(arg, "--simplify-by-decoration")) { revs->simplify_merges = 1; + revs->topo_order = 1; revs->rewrite_parents = 1; revs->simplify_history = 0; revs->simplify_by_decoration = 1; @@@ -1781,7 -1783,7 +1783,7 @@@ int setup_revisions(int argc, const cha * but the latter we have checked in the main loop. */ for (j = i; j < argc; j++) - verify_filename(revs->prefix, argv[j]); + verify_filename(revs->prefix, argv[j], j == i); append_prune_data(&prune_data, argv + i); break; @@@ -1947,8 -1949,9 +1949,9 @@@ static struct commit_list **simplify_on } /* - * Do we know what commit all of our parents should be rewritten to? - * Otherwise we are not ready to rewrite this one yet. + * Do we know what commit all of our parents that matter + * should be rewritten to? Otherwise we are not ready to + * rewrite this one yet. */ for (cnt = 0, p = commit->parents; p; p = p->next) { pst = locate_simplify_state(revs, p->item); @@@ -1956,6 -1959,8 +1959,8 @@@ tail = &commit_list_insert(p->item, tail)->next; cnt++; } + if (revs->first_parent_only) + break; } if (cnt) { tail = &commit_list_insert(commit, tail)->next; @@@ -1968,8 -1973,13 +1973,13 @@@ for (p = commit->parents; p; p = p->next) { pst = locate_simplify_state(revs, p->item); p->item = pst->simplified; + if (revs->first_parent_only) + break; } - cnt = remove_duplicate_parents(commit); + if (!revs->first_parent_only) + cnt = remove_duplicate_parents(commit); + else + cnt = 1; /* * It is possible that we are a merge and one side branch @@@ -2013,25 -2023,31 +2023,31 @@@ static void simplify_merges(struct rev_info *revs) { - struct commit_list *list; + struct commit_list *list, *next; struct commit_list *yet_to_do, **tail; + struct commit *commit; - if (!revs->topo_order) - sort_in_topological_order(&revs->commits, revs->lifo); if (!revs->prune) return; /* feed the list reversed */ yet_to_do = NULL; - for (list = revs->commits; list; list = list->next) - commit_list_insert(list->item, &yet_to_do); + for (list = revs->commits; list; list = next) { + commit = list->item; + next = list->next; + /* + * Do not free(list) here yet; the original list + * is used later in this function. + */ + commit_list_insert(commit, &yet_to_do); + } while (yet_to_do) { list = yet_to_do; yet_to_do = NULL; tail = &yet_to_do; while (list) { - struct commit *commit = list->item; - struct commit_list *next = list->next; + commit = list->item; + next = list->next; free(list); list = next; tail = simplify_one(revs, commit, tail); @@@ -2043,9 -2059,10 +2059,10 @@@ revs->commits = NULL; tail = &revs->commits; while (list) { - struct commit *commit = list->item; - struct commit_list *next = list->next; struct merge_simplify_state *st; + + commit = list->item; + next = list->next; free(list); list = next; st = locate_simplify_state(revs, commit);