Re: [PATCH] xdl_merge(): fix a segmentation fault when refining conflicts

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

 



Hi,

On Tue, 2 Jan 2007, Jakub Narebski wrote:

> On Sun, 31 Dec 2006, Johannes Schindelin wrote:
> 
> > On Sat, 30 Dec 2006, Jakub Narebski wrote:
> > 
> >> Johannes Schindelin wrote:
> >> 
> >>> Of course, you can hit mismerges like the illustrated one _without_ 
> >>> being marked as conflict (e.g. if the chunk of identical code is _not_ 
> >>> added, but only the increments), but we should at least avoid them 
> >>> where possible.
> >> 
> >> Perhaps you could make it even more conservating merge conflicts option 
> >> (to tighten merge conflicts even more) to xdl_merge, but not used by 
> >> default because as it removes accidental conflicts it increases 
> >> mismerges (falsely not conflicted).
> > 
> > There is no way to do this sanely. If you want to catch these mismerges, 
> > you have to mark _all_ modifications as conflicting.
> 
> Currently you have:
>  - a level value of 0 means that all overlapping changes are treated
>    as conflicts,
>  - a value of 1 means that if the overlapping changes are identical,
>    it is not treated as a conflict.
>  - If you set level to 2, overlapping changes will be analyzed, so that
>    almost identical changes will not result in huge conflicts. Rather,
>    only the conflicting lines will be shown inside conflict markers.
> 
> I was thinking about:
>  - If you set level to 3, if one part after overlapping changes analysis
>    in level 2 has empty conflict region, resolve this conflict as second
>    side. WARNING: this reduces number of merge conflicts, but might give
>    mismerges!

That is certainly a possibility! But how would you specify it? If you 
do it as a command line option, you'd have to add it to git-merge, 
git-pull, git-merge-recursive and git-merge-file. Ugly.

You could do it as a config variable, but git-merge-file operates without 
a git repository. And you'd want it to be overrideable anyway.

Environment variable? Too unfriendly to users, because it is not really a 
proper UI.

It is certainly easy enough to teach the code (but might introduce 
unwanted side effects, when the _deletion_, not the _addition_ was what 
you wanted):

 xdiff/xdiff.h  |    1 +
 xdiff/xmerge.c |   21 ++++++++++++++++++---
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h
index fa409d5..bdf12e3 100644
--- a/xdiff/xdiff.h
+++ b/xdiff/xdiff.h
@@ -52,6 +52,7 @@ extern "C" {
 #define XDL_MERGE_MINIMAL 0
 #define XDL_MERGE_EAGER 1
 #define XDL_MERGE_ZEALOUS 2
+#define XDL_MERGE_OVERZEALOUS 3
 
 typedef struct s_mmfile {
 	char *ptr;
diff --git a/xdiff/xmerge.c b/xdiff/xmerge.c
index b83b334..e7b740f 100644
--- a/xdiff/xmerge.c
+++ b/xdiff/xmerge.c
@@ -180,7 +180,7 @@ static int xdl_fill_merge_buffer(xdfenv_t *xe1, const char *name1,
  * lines. Try hard to show only these few lines as conflicting.
  */
 static int xdl_refine_conflicts(xdfenv_t *xe1, xdfenv_t *xe2, xdmerge_t *m,
-		xpparam_t const *xpp)
+		int level, xpparam_t const *xpp)
 {
 	for (; m; m = m->next) {
 		mmfile_t t1, t2;
@@ -225,6 +225,12 @@ static int xdl_refine_conflicts(xdfenv_t *xe1, xdfenv_t *xe2, xdmerge_t *m,
 		m->chg1 = xscr->chg1;
 		m->i2 = xscr->i2 + i2;
 		m->chg2 = xscr->chg2;
+		if (level >= XDL_MERGE_OVERZEALOUS) {
+			if (!m->chg1)
+				m->mode = 2;
+			else if (!m->chg2)
+				m->mode = 1;
+		}
 		while (xscr->next) {
 			xdmerge_t *m2 = xdl_malloc(sizeof(xdmerge_t));
 			if (!m2) {
@@ -241,6 +247,12 @@ static int xdl_refine_conflicts(xdfenv_t *xe1, xdfenv_t *xe2, xdmerge_t *m,
 			m->chg1 = xscr->chg1;
 			m->i2 = xscr->i2 + i2;
 			m->chg2 = xscr->chg2;
+			if (level >= XDL_MERGE_OVERZEALOUS) {
+				if (!m->chg1)
+					m->mode = 2;
+				else if (!m->chg2)
+					m->mode = 1;
+			}
 		}
 		xdl_free_env(&xe);
 		xdl_free_script(x);
@@ -252,6 +264,7 @@ static int xdl_refine_conflicts(xdfenv_t *xe1, xdfenv_t *xe2, xdmerge_t *m,
  * level == 0: mark all overlapping changes as conflict
  * level == 1: mark overlapping changes as conflict only if not identical
  * level == 2: analyze non-identical changes for minimal conflict set
+ * level == 3: if one side in the analysis is empty, assume no conflict
  *
  * returns < 0 on error, == 0 for no conflicts, else number of conflicts
  */
@@ -290,7 +303,7 @@ static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1,
 			xscr2 = xscr2->next;
 			continue;
 		}
-		if (level < 1 || xscr1->i1 != xscr2->i1 ||
+		if (level < XDL_MERGE_EAGER || xscr1->i1 != xscr2->i1 ||
 				xscr1->chg1 != xscr2->chg1 ||
 				xscr1->chg2 != xscr2->chg2 ||
 				xdl_merge_cmp_lines(xe1, xscr1->i2,
@@ -355,7 +368,9 @@ static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1,
 	if (!changes)
 		changes = c;
 	/* refine conflicts */
-	if (level > 1 && xdl_refine_conflicts(xe1, xe2, changes, xpp) < 0) {
+	if (level >= XDL_MERGE_ZEALOUS &&
+			xdl_refine_conflicts(xe1, xe2, changes,
+				xpp, level) < 0) {
 		xdl_cleanup_merge(changes);
 		return -1;
 	}

-
To unsubscribe from this list: 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]