summaryrefslogtreecommitdiff
path: root/xdiff/xmerge.c
AgeCommit message (Collapse)Author
2010-01-17xdl_merge(): allow passing down marker_size in xmparam_tJunio C Hamano
This allows the callers of xdl_merge() to pass marker_size (defaults to 7) in xmparam_t argument, to use conflict markers of non-default length. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-17xdl_merge(): introduce xmparam_t for merge specific parametersJunio C Hamano
So far we have only needed to be able to pass an option that is generic to xdiff family of functions to this function. Extend the interface so that we can give it merge specific parameters. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-06-02Merge branch 'cb/maint-1.6.0-xdl-merge-fix' into maintJunio C Hamano
* cb/maint-1.6.0-xdl-merge-fix: Change xdl_merge to generate output even for null merges t6023: merge-file fails to output anything for a degenerate merge Conflicts: xdiff/xmerge.c
2009-05-25Change xdl_merge to generate output even for null mergesCharles Bailey
xdl_merge used to have a check to ensure that there was at least some change in one or other side being merged but this suppressed output for the degenerate case when base, local and remote contents were all identical. Removing this check enables correct output in the degenerate case and xdl_free_script handles freeing NULL scripts so there is no need to have the check for these calls. Signed-off-by: Charles Bailey <charles@hashpling.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-08-31xmerge.c: "diff3 -m" style clips merge reduction level to EAGER or lessJunio C Hamano
When showing a conflicting merge result, and "--diff3 -m" style is asked for, this patch makes sure that the merge reduction level does not exceed XDL_MERGE_EAGER. This is because "diff3 -m" style output would not make sense for anything more aggressive than XDL_MERGE_EAGER, because of the way how the merge reduction works. "git merge-file" no longer has to force MERGE_EAGER when "--diff3" is asked for because of this change. Suppose a common ancestor (shared preimage) is modified to postimage #1 and #2 (each letter represents one line): ##### postimage#1: 1234ABCDE789 | / | / preimage: 123456789 | \ postimage#2: 1234AXYE789 #### XDL_MERGE_MINIMAL and XDL_MERGE_EAGER would: (1) find the s/56/ABCDE/ done on one side and s/56/AXYE/ done on the other side, (2) notice that they touch an overlapping area, and (3) mark it as a conflict, "ABCDE vs AXYE". The difference between the two algorithms is that EAGER drops the hunk altogether if the postimages match (i.e. both sides modified the same way), while MINIMAL keeps it. There is no other operation performed to the hunk. As the result, lines marked with "#" in the above picure will be in the RCS merge style output like this (letters <, = and > represent conflict marker lines): output: 1234<ABCDE=AXYE>789 ; with MINIMAL/EAGER The part from the preimage that corresponds to these conflicting changes is "56", which is what "diff3 -m" style output adds to it: output: 1234<ABCDE|56=AXYE>789 ; in "diff3 -m" style Now, XDL_MERGE_ZEALOUS looks at the differences between the changes two postimages made in order to reduce the number of lines in the conflicting regions. It notices that both sides start their new contents with "A", and excludes it from the output (it also excludes "E" for the same reason). The conflict that used to be "ABCDE vs AXYE" is now "BCD vs XY": output: 1234A<BCD=XY>E789 ; with ZEALOUS There could even be matching parts between two postimages in the middle. Instead of one side rewriting the shared "56" to "ABCDE" and the other side to "AXYE", imagine the case where the postimages are "ABCDE" and "AXCYE", in which case instead of having one conflicted hunk "BCD vs XY", you would have two conflicting hunks "B vs X" and "D vs Y". In either case, once you reduce "ABCDE vs AXYE" to "BCD vs XY" (or "ABCDE vs AXCYE" to "B vs X" and "D vs Y"), there is no part from the preimage that corresponds to the conflicting change made in both postimages anymore. In other words, conflict reduced by ZEALOUS algorithm cannot be expressed in "diff3 -m" style. Representing the last illustration like this is misleading to say the least: output: 1234A<BCD|56=XY>E789 ; broken "diff3 -m" style because the preimage was not ...4A56E... to begin with. "A" and "E" are common only between the postimages. Even worse, once a single conflicting hunk is split into multiple ones (recall the example of breaking "ABCDE vs AXCYE" to "B vs X" and "D vs Y"), there is no sane way to distribute the preimage text across split conflicting hunks. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-08-31xmerge.c: minimum readability fixupsJunio C Hamano
This replaces hardcoded magic constants with symbolic ones for readability, and swaps one if/else blocks to better match the order in which 0/1/2 variables are handled to nearby codepath. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-08-31xdiff-merge: optionally show conflicts in "diff3 -m" styleJunio C Hamano
When showing conflicting merges, we traditionally followed RCS's merge output format. The output shows: <<<<<<< postimage from one side; ======= postimage of the other side; and >>>>>>> Some poeple find it easier to be able to understand what is going on when they can view the common ancestor's version, which is used by "diff3 -m", which shows: <<<<<<< postimage from one side; ||||||| shared preimage; ======= postimage of the other side; and >>>>>>> This is an initial step to bring that as an optional feature to git. Only "git merge-file" has been converted, with "--diff3" option. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-08-31xdl_fill_merge_buffer(): separate out a too deeply nested functionJunio C Hamano
This simply moves code around to make a separate function that prepares a single conflicted hunk with markers into the buffer. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-02-18xdl_merge(): introduce XDL_MERGE_ZEALOUS_ALNUMJohannes Schindelin
When a merge conflicts, there are often common lines that are not really common, such as empty lines or lines containing a single curly bracket. With XDL_MERGE_ZEALOUS_ALNUM, we use the following heuristics: when a hunk does not contain any letters or digits, it is treated as conflicting. In other words, a conflict which used to look like this: <<<<<<< a = 1; ======= output(); >>>>>>> } } } <<<<<<< output(); ======= b = 1; >>>>>>> will look like this with ZEALOUS_ALNUM: <<<<<<< a = 1; } } } output(); ======= output(); } } } b = 1; >>>>>>> To demonstrate this, git-merge-file has been switched from XDL_MERGE_ZEALOUS to XDL_MERGE_ZEALOUS_ALNUM. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-02-18xdl_merge(): make XDL_MERGE_ZEALOUS output simplerJohannes Schindelin
When a merge conflicts, there are often less than three common lines between two conflicting regions. Since a conflict takes up as many lines as are conflicting, plus three lines for the commit markers, the output will be shorter (and thus, simpler) in this case, if the common lines will be merged into the conflicting regions. This patch merges up to three common lines into the conflicts. For example, what looked like this before this patch: <<<<<<< if (a == 1) ======= if (a != 0) >>>>>>> { int i; <<<<<<< a = 0; ======= a = !a; >>>>>>> will now look like this: <<<<<<< if (a == 1) { int i; a = 0; ======= if (a != 0) { int i; a = !a; >>>>>>> Suggested Linus (based on ideas by "Voltage Spike" -- if that name is real, it is mighty cool). Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2006-12-31Fix yet another subtle xdl_merge() bugJohannes Schindelin
In very obscure cases, a merge can hit an unexpected code path (where the original code went as far as saying that this was a bug). This failing merge was noticed by Alexandre Juillard. The problem is that the original file contains something like this: -- snip -- two non-empty lines before two empty lines after two empty lines -- snap -- and this snippet is reduced to _one_ empty line in _both_ new files. However, it is ambiguous as to which hunk takes the empty line: the first or the second one? Indeed in Alexandre's example files, the xdiff algorithm attributes the empty line to the first hunk in one case, and to the second hunk in the other case. (Trimming down the example files _changes_ that behaviour!) Thus, the call to xdl_merge_cmp_lines() has no chance to realize that the change is actually identical in both new files. Therefore, xdl_refine_conflicts() finds an empty diff script, which was not expected there, because (the original author of xdl_merge() thought) xdl_merge_cmp_lines() would catch that case earlier. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-12-28xdl_merge(): fix a segmentation fault when refining conflictsJohannes Schindelin
The function xdl_refine_conflicts() tries to break down huge conflicts by doing a diff on the conflicting regions. However, this does not make sense when one side is empty. Worse, when one side is not only empty, but after EOF, the code accessed unmapped memory. Noticed by Luben Tuikov, Shawn Pearce and Alexandre Julliard, the latter providing a test case. Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de> Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-12-05xdl_merge(): fix and simplify conflict handlingJohannes Schindelin
Suppose you have changes in new1 to the original lines 10-20, and changes in new2 to the original lines 15-25, then the changes to 10-25 conflict. But it is possible that the next changes in new1 still overlap with this change to new2. So, in the next iteration we have to look at the same change to new2 again. The old code tried to be a bit too clever. The new code is shorter and more to the point: do not fiddle with the ranges at all. Also, xdl_append_merge() tries harder to combine conflicts. This is necessary, because with the above simplification, some conflicts would not be recognized as conflicts otherwise: In the above scenario, it is possible that there is no other change to new1. Absent the combine logic, the change in new2 would be recorded _again_, but as a non-conflict. Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
2006-12-03xdl_merge(): fix thinkoJohannes Schindelin
If one side's block (of changed lines) ends later than the other side's block, the former should be tested against the next block of the other side, not vice versa. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-12-03xdl_merge(): fix an off-by-one bugJohannes Schindelin
The line range is i1 .. (i1 + chg1 - 1), not i1 .. (i1 + chg1). Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-12-03xmerge: make return value from xdl_merge() more usable.Junio C Hamano
The callers would want to know if the resulting merge is clean; do not discard that information away after calling xdl_do_merge(). Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-12-03xdiff: add xdl_merge()Johannes Schindelin
This new function implements the functionality of RCS merge, but in-memory. It returns < 0 on error, otherwise the number of conflicts. Finding the conflicting lines can be a very expensive task. You can control the eagerness of this algorithm: - 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. With each increasing level, the algorithm gets slower, but more accurate. Note that the code for level 2 depends on the simple definition of mmfile_t specific to git, and therefore it will be harder to port that to LibXDiff. Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de> Signed-off-by: Junio C Hamano <junkio@cox.net>