aboutsummaryrefslogtreecommitdiff
path: root/merge-base.c
diff options
context:
space:
mode:
authorJunio C Hamano <junkio@cox.net>2005-11-10 22:41:44 -0800
committerJunio C Hamano <junkio@cox.net>2005-11-11 10:52:31 -0800
commit9e5f4a5539fe0e6ed31f26f34f1832a729facf4b (patch)
tree8964221663383b46653eda3e95e0e17fdce6d066 /merge-base.c
parented9a540b2b351ea305e26bb0d9028f21c976b67c (diff)
downloadgit-9e5f4a5539fe0e6ed31f26f34f1832a729facf4b.tar.gz
git-9e5f4a5539fe0e6ed31f26f34f1832a729facf4b.tar.xz
merge-base: avoid unnecessary postprocessing.
When we have only one merge-base candidates in the result list, there is no point going back to mark the reachable commits again. And that is the most common case, so try not to waste time on it. Suggested by Linus. Signed-off-by: Junio C Hamano <junkio@cox.net>
Diffstat (limited to 'merge-base.c')
-rw-r--r--merge-base.c77
1 files changed, 43 insertions, 34 deletions
diff --git a/merge-base.c b/merge-base.c
index 43a681836..751c3c281 100644
--- a/merge-base.c
+++ b/merge-base.c
@@ -123,6 +123,47 @@ static struct commit *interesting(struct commit_list *list)
static int show_all = 0;
+static void mark_reachable_commits(struct commit_list *result,
+ struct commit_list *list)
+{
+ struct commit_list *tmp;
+
+ /*
+ * Postprocess to fully contaminate the well.
+ */
+ for (tmp = result; tmp; tmp = tmp->next) {
+ struct commit *c = tmp->item;
+ /* Reinject uninteresting ones to list,
+ * so we can scan their parents.
+ */
+ if (c->object.flags & UNINTERESTING)
+ commit_list_insert(c, &list);
+ }
+ while (list) {
+ struct commit *c = list->item;
+ struct commit_list *parents;
+
+ tmp = list;
+ list = list->next;
+ free(tmp);
+
+ /* Anything taken out of the list is uninteresting, so
+ * mark all its parents uninteresting. We do not
+ * parse new ones (we already parsed all the relevant
+ * ones).
+ */
+ parents = c->parents;
+ while (parents) {
+ struct commit *p = parents->item;
+ parents = parents->next;
+ if (!(p->object.flags & UNINTERESTING)) {
+ p->object.flags |= UNINTERESTING;
+ commit_list_insert(p, &list);
+ }
+ }
+ }
+}
+
static int merge_base(struct commit *rev1, struct commit *rev2)
{
struct commit_list *list = NULL;
@@ -171,40 +212,8 @@ static int merge_base(struct commit *rev1, struct commit *rev2)
if (!result)
return 1;
- /*
- * Postprocess to fully contaminate the well.
- */
- for (tmp = result; tmp; tmp = tmp->next) {
- struct commit *c = tmp->item;
- /* Reinject uninteresting ones to list,
- * so we can scan their parents.
- */
- if (c->object.flags & UNINTERESTING)
- commit_list_insert(c, &list);
- }
- while (list) {
- struct commit *c = list->item;
- struct commit_list *parents;
-
- tmp = list;
- list = list->next;
- free(tmp);
-
- /* Anything taken out of the list is uninteresting, so
- * mark all its parents uninteresting. We do not
- * parse new ones (we already parsed all the relevant
- * ones).
- */
- parents = c->parents;
- while (parents) {
- struct commit *p = parents->item;
- parents = parents->next;
- if (!(p->object.flags & UNINTERESTING)) {
- p->object.flags |= UNINTERESTING;
- commit_list_insert(p, &list);
- }
- }
- }
+ if (result->next && list)
+ mark_reachable_commits(result, list);
while (result) {
struct commit *commit = result->item;