Re: [PATCH] Additional merge-base tests

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



A Large Angry SCM <gitzilla@xxxxxxxxx> writes:

>> This is a good demonstration that merge-base may not give you
>> minimal set for pathological cases.  If you want to be through
>> you could traverse everything to make sure we do not say 'S' is
>> relevant, but that is quite expensive, so I think there will
>> always be artifacts of horizon effect like this no matter how
>> you try to catch it (didn't I keep saying that already?).
>
> The problem is in mark_reachable_commits(); it is either superfluous
> or it needs to parse_commit() those commits that haven't been parsed
> yet that it needs to traverse.

Yes, you could traverse everything.  But that is not practical.
We have known that the clean-up pass has this horizon effect,
and it is a compromise.

If you apply this testing patch on top of yours, you will see
that parsing more commits at that point makes the clean-up
pass go all the way down to the root commit.

We may alternatively not use the clean-up pass at all, but I
suspect that might give us many false positives.  I don't
remember the details but I think we added it while fixing
merge-base in the real life situation.

It may be interesting to run tests on real merges (I believe the
kernel repository has a handful merges that have more than one
merge bases) to see how effective the current clean-up pass is.
It may turn out to be ineffective in practice, in which case we
could kill it off.


diff --git a/t/t6010-merge-base.sh b/t/t6010-merge-base.sh
index 9a815bd..4c6ed5c 100755
--- a/t/t6010-merge-base.sh
+++ b/t/t6010-merge-base.sh
@@ -89,4 +89,33 @@ test_expect_success 'compute merge-base 
     'MB=$(git-merge-base --all PL PR) &&
      expr "$(git-name-rev "$MB")" : "[0-9a-f]* tags/C2"'
 
+# Setup third set
+# 
+# S-U0-U1-U2-U3-U4
+#  \           X
+#   D0-D1-D2-D3-D4
+
+U0=$(doit 1 U0 $S)
+D0=$(doit 1 D0 $S)
+U1=$(doit 2 U1 $U0)
+D1=$(doit 2 D1 $D0)
+U2=$(doit 3 U2 $U1)
+D2=$(doit 3 D2 $D1)
+U3=$(doit 4 U3 $U2)
+D3=$(doit 4 D3 $D2)
+U4=$(doit 5 U4 $U3 $D3)
+D4=$(doit 5 D4 $D3 $U3)
+
+test_expect_success 'compute merge-base' '
+
+	git merge-base --all U4 D4 >out 2>err 
+	if grep tags/S err
+	then
+		echo "went all the way down to S -- very unhappy"
+		false
+	else
+		echo "stopped before going too far"
+	fi
+'
+
 test_done
diff --git a/merge-base.c b/merge-base.c
index 4856ca0..daab296 100644
--- a/merge-base.c
+++ b/merge-base.c
@@ -6,8 +6,35 @@ #define PARENT1 1
 #define PARENT2 2
 #define UNINTERESTING 4
 
+static void debug_list(struct commit_list *l, const char *msg)
+{
+	fprintf(stderr, "%s\n", msg);
+	while (l) {
+		char buf[1024];
+		int parsed;
+		struct commit *commit = l->item;
+		l = l->next;
+		parsed = commit->object.parsed;
+
+		if (parsed) {
+			pretty_print_commit(CMIT_FMT_ONELINE, commit,
+					    ~0UL, buf, sizeof(buf), 7,
+					    NULL, NULL);
+		}
+		else {
+			sprintf(buf, "git-name-rev %s 1>&2",
+				sha1_to_hex(commit->object.sha1));
+			system(buf);
+			strcpy(buf, sha1_to_hex(commit->object.sha1));
+		}
+		fprintf(stderr, "%d %d %s\n", commit->object.flags,
+			parsed, buf);
+	}
+}
+
 static struct commit *interesting(struct commit_list *list)
 {
+	debug_list(list, "in interesting()");
 	while (list) {
 		struct commit *commit = list->item;
 		list = list->next;
@@ -134,6 +161,9 @@ static void mark_reachable_commits(struc
 	/*
 	 * Postprocess to fully contaminate the well.
 	 */
+	debug_list(list, "list at top of mark-reachable");
+	debug_list(result, "result at top of mark-reachable");
+
 	for (tmp = result; tmp; tmp = tmp->next) {
 		struct commit *c = tmp->item;
 		/* Reinject uninteresting ones to list,
@@ -142,10 +172,12 @@ static void mark_reachable_commits(struc
 		if (c->object.flags & UNINTERESTING)
 			commit_list_insert(c, &list);
 	}
+
 	while (list) {
 		struct commit *c = list->item;
 		struct commit_list *parents;
 
+		debug_list(list, "list in mark-reachable postprocessing");
 		tmp = list;
 		list = list->next;
 		free(tmp);
@@ -155,6 +187,15 @@ static void mark_reachable_commits(struc
 		 * parse new ones (we already parsed all the relevant
 		 * ones).
 		 */
+		
+		/* Parsing object here which is a disaster;
+		 * let's demonstrate it.
+		 */
+#if 1
+		if (!c->object.parsed)
+			parse_commit(c);
+#endif
+
 		parents = c->parents;
 		while (parents) {
 			struct commit *p = parents->item;
@@ -164,6 +205,7 @@ static void mark_reachable_commits(struc
 				commit_list_insert(p, &list);
 			}
 		}
+		debug_list(result, "result in mark-reachable postprocessing");
 	}
 }
 
@@ -196,6 +238,7 @@ static int merge_base(struct commit *rev
 		free(tmp);
 		if (flags == 3) {
 			insert_by_date(commit, &result);
+			debug_list(result, "a new result");
 
 			/* Mark parents of a found merge uninteresting */
 			flags |= UNINTERESTING;
@@ -218,6 +261,7 @@ static int merge_base(struct commit *rev
 	if (result->next && list)
 		mark_reachable_commits(result, list);
 
+	debug_list(result, "final result");
 	while (result) {
 		struct commit *commit = result->item;
 		result = result->next;

-
: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]