SHA256
3
0
forked from pool/patch
patch/diff3-style-merges-locate-merge.diff

111 lines
3.3 KiB
Diff

---
patch.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 72 insertions(+), 6 deletions(-)
Index: b/patch.c
===================================================================
--- a/patch.c
+++ b/patch.c
@@ -62,6 +62,8 @@ static FILE *create_output_file (char co
static LINENUM locate_hunk (LINENUM);
static bool apply_hunk (struct outstate *, LINENUM);
static bool common_context(LINENUM, LINENUM, LINENUM);
+static LINENUM min_mismatches(LINENUM, LINENUM);
+static LINENUM locate_merge (void);
static bool merge_hunk (struct outstate *, LINENUM, LINENUM);
static void merge_ends_here(struct outstate *outstate);
static bool copy_till (struct outstate *, LINENUM);
@@ -304,15 +306,11 @@ main (int argc, char **argv)
goto skip_hunk;
} else if (!where) {
if (mergetype & MERGE_REJECTS) {
- LINENUM guess = pch_first () + last_offset;
-
- if (merge_hunk(&outstate, guess, -1)) {
+ if (merge_hunk(&outstate, locate_merge(), -1)) {
merged++;
mismatch = 1;
- } else {
- /* FIXME: guess harder! */
+ } else
goto skip_hunk;
- }
} else
goto skip_hunk;
} else {
@@ -1356,6 +1354,74 @@ static bool common_context(LINENUM where
memcmp(line, pfetch(new), size) == 0));
}
+static LINENUM min_mismatches(LINENUM where, LINENUM lowest)
+{
+ register LINENUM ptrn_lines = pch_ptrn_lines();
+ register LINENUM old, mismatched = 0;
+
+ for (old = 1; old <= ptrn_lines; old++, where++) {
+ size_t size;
+ const char *line;
+
+ line = ifetch (where, false, &size);
+ if (!size ||
+ !(canonicalize ?
+ similar(pfetch(old), pch_line_len(old), line, size) :
+ (size == pch_line_len(old) &&
+ memcmp(line, pfetch(old), size) == 0))) {
+ mismatched++;
+ if (mismatched >= lowest)
+ break;
+ }
+ }
+ return mismatched;
+}
+
+static LINENUM locate_merge ()
+{
+ register LINENUM first_guess = pch_first () + last_offset;
+ register LINENUM lowest = input_lines, where = first_guess;
+ register LINENUM offset;
+ LINENUM pat_lines = pch_ptrn_lines();
+ LINENUM suffix_context = pch_suffix_context ();
+ LINENUM max_where = input_lines - (pat_lines - suffix_context) + 1;
+ LINENUM min_where = last_frozen_line + 1;
+ LINENUM max_pos_offset = max_where - first_guess;
+ LINENUM max_neg_offset = first_guess - min_where;
+ LINENUM max_offset = (max_pos_offset < max_neg_offset
+ ? max_neg_offset : max_pos_offset);
+
+ /* Do not try lines <= 0. */
+ if (first_guess <= max_neg_offset)
+ max_neg_offset = first_guess - 1;
+
+ for (offset = 0; offset <= max_offset; offset++) {
+ if (offset <= max_pos_offset) {
+ register LINENUM mismatched;
+
+ mismatched = min_mismatches(first_guess - offset, lowest);
+ if (mismatched < lowest) {
+ lowest = mismatched;
+ where = first_guess - offset;
+ if (lowest == 1)
+ break;
+ }
+ }
+ if (0 < offset && offset <= max_neg_offset) {
+ register LINENUM mismatched;
+
+ mismatched = min_mismatches(first_guess + offset, lowest);
+ if (mismatched < lowest) {
+ lowest = mismatched;
+ where = first_guess + offset;
+ if (lowest == 1)
+ break;
+ }
+ }
+ }
+ return where;
+}
+
/* A FUZZ value of -1 indicates that the hunk could not be applied. */
static bool merge_hunk (struct outstate *outstate, LINENUM where, LINENUM fuzz)