This commit is contained in:
parent
ea52ba878c
commit
e553963af3
92
diff3-style-merges-add-file-labels.diff
Normal file
92
diff3-style-merges-add-file-labels.diff
Normal file
@ -0,0 +1,92 @@
|
||||
From: Andreas Gruenbacher <agruen@suse.de>
|
||||
Subject: diff3-style merges: add file labels
|
||||
|
||||
Add a --label=LABEL option for overriding the labels in the diff3-style
|
||||
format. The option can be given up to three times for overriding the
|
||||
old, new, and output filename.
|
||||
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
|
||||
---
|
||||
patch.c | 19 +++++++++++++++----
|
||||
1 file changed, 15 insertions(+), 4 deletions(-)
|
||||
|
||||
Index: b/patch.c
|
||||
===================================================================
|
||||
--- a/patch.c
|
||||
+++ b/patch.c
|
||||
@@ -82,6 +82,7 @@ static void usage (FILE *, int) __attrib
|
||||
enum mergetype { SHOW_ALL = 1, SHOW_FUZZ = 2, MERGE_REJECTS = 4 };
|
||||
static enum mergetype mergetype;
|
||||
|
||||
+const char *file_label[2];
|
||||
static bool make_backups;
|
||||
static bool backup_if_mismatch;
|
||||
static char const *version_control;
|
||||
@@ -538,7 +539,7 @@ reinitialize_almost_everything (void)
|
||||
skip_rest_of_patch = false;
|
||||
}
|
||||
|
||||
-static char const shortopts[] = "bB:cd:D:eEfF:g:i:lMnNo:p:r:RstTuvV:x:Y:z:Z";
|
||||
+static char const shortopts[] = "bB:cd:D:eEfF:g:i:lL:MnNo:p:r:RstTuvV:x:Y:z:Z";
|
||||
static struct option const longopts[] =
|
||||
{
|
||||
{"backup", no_argument, NULL, 'b'},
|
||||
@@ -553,6 +554,7 @@ static struct option const longopts[] =
|
||||
{"get", no_argument, NULL, 'g'},
|
||||
{"input", required_argument, NULL, 'i'},
|
||||
{"ignore-whitespace", no_argument, NULL, 'l'},
|
||||
+ {"label", required_argument, NULL, 'L'},
|
||||
{"normal", no_argument, NULL, 'n'},
|
||||
{"forward", no_argument, NULL, 'N'},
|
||||
{"output", required_argument, NULL, 'o'},
|
||||
@@ -609,6 +611,7 @@ static char const *const option_help[] =
|
||||
"",
|
||||
" -D NAME --ifdef=NAME Make merged if-then-else output using NAME.",
|
||||
" --merge={rejects,fuzz,all} Produce a diff3-style merge.",
|
||||
+" -L LABEL --label=LABEL Use LABEL instead of file name in merge.",
|
||||
" -E --remove-empty-files Remove output files that are empty after patching.",
|
||||
"",
|
||||
" -Z --set-utc Set times of patched files, assuming diff uses UTC (GMT).",
|
||||
@@ -747,6 +750,14 @@ get_some_switches (void)
|
||||
case 'l':
|
||||
canonicalize = true;
|
||||
break;
|
||||
+ case 'L':
|
||||
+ if (!file_label[0])
|
||||
+ file_label[0] = optarg;
|
||||
+ else if (!file_label[1])
|
||||
+ file_label[1] = optarg;
|
||||
+ else
|
||||
+ fatal ("too many file label options");
|
||||
+ break;
|
||||
case 'M':
|
||||
mergetype |= MERGE_REJECTS;
|
||||
break;
|
||||
@@ -1411,7 +1422,7 @@ static bool merge_hunk (struct outstate
|
||||
}
|
||||
|
||||
/* "From" lines in the patch */
|
||||
- name = pch_name(OLD);
|
||||
+ name = file_label[OLD] ? file_label[OLD] : pch_name(OLD);
|
||||
if (!name)
|
||||
name = "";
|
||||
fprintf(fp, outstate->after_newline + "\n<<<<<<<%*s\n",
|
||||
@@ -1426,7 +1437,7 @@ static bool merge_hunk (struct outstate
|
||||
|
||||
if (fuzz) {
|
||||
/* "To" lines in the patch */
|
||||
- name = pch_name(NEW);
|
||||
+ name = file_label[NEW] ? file_label[NEW] : pch_name(NEW);
|
||||
if (!name)
|
||||
name = "";
|
||||
fprintf(fp, outstate->after_newline + "\n|||||||%*s\n",
|
||||
@@ -1453,7 +1464,7 @@ static bool merge_hunk (struct outstate
|
||||
|
||||
/* If the merge result and the new file are the same, label the merge
|
||||
result with the new file's name. */
|
||||
- name = fuzz ? NULL : pch_name(NEW);
|
||||
+ name = fuzz ? NULL : (file_label[NEW] ? file_label[NEW] : pch_name(NEW));
|
||||
if (!name)
|
||||
name = "";
|
||||
fprintf(fp, outstate->after_newline + "\n>>>>>>>%*s\n",
|
293
diff3-style-merges-base.diff
Normal file
293
diff3-style-merges-base.diff
Normal file
@ -0,0 +1,293 @@
|
||||
From: Andreas Gruenbacher <agruen@suse.de>
|
||||
Subject: diff3-style merges
|
||||
|
||||
Implement a diff3-style merge format: with the --merge option alone,
|
||||
all hunks that apply without fuzz will be applied as usual, and
|
||||
hunks that apply within the allowed fuzz limit will be bracketed as:
|
||||
|
||||
<<<<<<<
|
||||
old lines from patch
|
||||
|||||||
|
||||
new lines from patch
|
||||
=======
|
||||
merge result
|
||||
>>>>>>>
|
||||
|
||||
When the --show-all option is given in addition, hunks that apply without
|
||||
fuzz will be bracketed as:
|
||||
|
||||
<<<<<<<
|
||||
old lines from patch
|
||||
=======
|
||||
merge result
|
||||
>>>>>>>
|
||||
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
|
||||
---
|
||||
patch.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 170 insertions(+), 5 deletions(-)
|
||||
|
||||
Index: b/patch.c
|
||||
===================================================================
|
||||
--- a/patch.c
|
||||
+++ b/patch.c
|
||||
@@ -61,6 +61,8 @@ struct outstate
|
||||
static FILE *create_output_file (char const *, int);
|
||||
static LINENUM locate_hunk (LINENUM);
|
||||
static bool apply_hunk (struct outstate *, LINENUM);
|
||||
+static bool common_context(LINENUM, LINENUM, LINENUM);
|
||||
+static bool merge_hunk (struct outstate *, LINENUM, LINENUM);
|
||||
static bool copy_till (struct outstate *, LINENUM);
|
||||
static bool patch_match (LINENUM, LINENUM, LINENUM, LINENUM);
|
||||
static bool similar (char const *, size_t, char const *, size_t);
|
||||
@@ -77,6 +79,9 @@ static void reinitialize_almost_everythi
|
||||
static void remove_if_needed (char const *, int volatile *);
|
||||
static void usage (FILE *, int) __attribute__((noreturn));
|
||||
|
||||
+enum mergetype { SHOW_ALL = 1, SHOW_FUZZ = 2 };
|
||||
+static enum mergetype mergetype;
|
||||
+
|
||||
static bool make_backups;
|
||||
static bool backup_if_mismatch;
|
||||
static char const *version_control;
|
||||
@@ -117,7 +122,7 @@ int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
char const *val;
|
||||
- bool somefailed = false;
|
||||
+ bool somemerged = false, somefailed = false;
|
||||
struct outstate outstate;
|
||||
char numbuf[LINENUM_LENGTH_BOUND + 1];
|
||||
|
||||
@@ -184,6 +189,7 @@ main (int argc, char **argv)
|
||||
reinitialize_almost_everything()
|
||||
) { /* for each patch in patch file */
|
||||
int hunk = 0;
|
||||
+ int merged = 0;
|
||||
int failed = 0;
|
||||
bool mismatch = false;
|
||||
char *outname = outfile ? outfile : inname;
|
||||
@@ -295,8 +301,17 @@ main (int argc, char **argv)
|
||||
} else if (!where) {
|
||||
goto skip_hunk;
|
||||
} else {
|
||||
- if (!apply_hunk (&outstate, where))
|
||||
- goto skip_hunk;
|
||||
+ if ((mergetype & SHOW_ALL) ||
|
||||
+ (fuzz && (mergetype & SHOW_FUZZ))) {
|
||||
+ if (merge_hunk(&outstate, where, fuzz)) {
|
||||
+ merged++;
|
||||
+ mismatch = true;
|
||||
+ } else
|
||||
+ goto skip_hunk;
|
||||
+ } else {
|
||||
+ if (!apply_hunk (&outstate, where))
|
||||
+ goto skip_hunk;
|
||||
+ }
|
||||
}
|
||||
|
||||
if (verbosity == VERBOSE
|
||||
@@ -325,6 +340,9 @@ skip_hunk:
|
||||
format_linenum (numbuf, newwhere));
|
||||
}
|
||||
|
||||
+ if (merged)
|
||||
+ somemerged = true;
|
||||
+
|
||||
if (!skip_rest_of_patch)
|
||||
{
|
||||
if (got_hunk < 0 && using_plan_a)
|
||||
@@ -374,7 +392,8 @@ skip_hunk:
|
||||
else
|
||||
{
|
||||
if (! outstate.zero_output
|
||||
- && pch_says_nonexistent (! reverse))
|
||||
+ && pch_says_nonexistent (! reverse)
|
||||
+ && !merged)
|
||||
{
|
||||
mismatch = true;
|
||||
if (verbosity != SILENT)
|
||||
@@ -468,7 +487,7 @@ skip_hunk:
|
||||
if (outstate.ofp && (ferror (outstate.ofp) || fclose (outstate.ofp) != 0))
|
||||
write_fatal ();
|
||||
cleanup ();
|
||||
- if (somefailed)
|
||||
+ if (somemerged || somefailed)
|
||||
exit (1);
|
||||
return 0;
|
||||
}
|
||||
@@ -544,6 +563,7 @@ static struct option const longopts[] =
|
||||
{"quoting-style", required_argument, NULL, CHAR_MAX + 8},
|
||||
{"unified-reject-files", no_argument, NULL, CHAR_MAX + 9},
|
||||
{"global-reject-file", required_argument, NULL, CHAR_MAX + 10},
|
||||
+ {"merge", required_argument, NULL, CHAR_MAX + 11},
|
||||
{NULL, no_argument, NULL, 0}
|
||||
};
|
||||
|
||||
@@ -571,6 +591,7 @@ static char const *const option_help[] =
|
||||
" -r FILE --reject-file=FILE Output rejects to FILE.",
|
||||
"",
|
||||
" -D NAME --ifdef=NAME Make merged if-then-else output using NAME.",
|
||||
+" --merge={fuzz,all} Produce a diff3-style merge.",
|
||||
" -E --remove-empty-files Remove output files that are empty after patching.",
|
||||
"",
|
||||
" -Z --set-utc Set times of patched files, assuming diff uses UTC (GMT).",
|
||||
@@ -809,6 +830,23 @@ get_some_switches (void)
|
||||
case CHAR_MAX + 10:
|
||||
global_reject = savestr (optarg);
|
||||
break;
|
||||
+ case CHAR_MAX + 11:
|
||||
+ {
|
||||
+ char *tok = strtok(optarg, ",");
|
||||
+
|
||||
+ do {
|
||||
+ if (!strcmp(tok, "fuzz"))
|
||||
+ mergetype |= SHOW_FUZZ;
|
||||
+ else if (!strcmp(tok, "all"))
|
||||
+ mergetype |= SHOW_ALL;
|
||||
+ else {
|
||||
+ fprintf(stderr, "%s: invalid merge option %s\n",
|
||||
+ program_name, quotearg(tok));
|
||||
+ usage (stderr, 2);
|
||||
+ }
|
||||
+ } while ((tok = strtok(NULL, ",")));
|
||||
+ }
|
||||
+ break;
|
||||
default:
|
||||
usage (stderr, 2);
|
||||
}
|
||||
@@ -1264,6 +1302,133 @@ apply_hunk (struct outstate *outstate, L
|
||||
return true;
|
||||
}
|
||||
|
||||
+static bool common_context(LINENUM where, LINENUM old, LINENUM new)
|
||||
+{
|
||||
+ size_t size;
|
||||
+ const char *line;
|
||||
+
|
||||
+ if (pch_char(old) != ' ' || pch_char(new) != ' ')
|
||||
+ return false;
|
||||
+
|
||||
+ line = ifetch (where, false, &size);
|
||||
+ return size &&
|
||||
+ (canonicalize ?
|
||||
+ (similar(pfetch(old), pch_line_len(old), line, size) &&
|
||||
+ similar(pfetch(new), pch_line_len(new), line, size)) :
|
||||
+ (size == pch_line_len(old) && size == pch_line_len(new) &&
|
||||
+ memcmp(line, pfetch(old), size) == 0 &&
|
||||
+ memcmp(line, pfetch(new), size) == 0));
|
||||
+}
|
||||
+
|
||||
+/* A FUZZ value of -1 indicates that the hunk could not be applied. */
|
||||
+
|
||||
+static bool merge_hunk (struct outstate *outstate, LINENUM where, LINENUM fuzz)
|
||||
+{
|
||||
+ register LINENUM old = 1;
|
||||
+ register LINENUM lastline = pch_ptrn_lines ();
|
||||
+ register LINENUM new = lastline + 1;
|
||||
+ register LINENUM pat_end = pch_end ();
|
||||
+ register LINENUM merge, merge_end;
|
||||
+ register FILE *fp = outstate->ofp;
|
||||
+ bool succeeded = true;
|
||||
+
|
||||
+ while (pch_char(new) == '=' || pch_char(new) == '\n' /* ??? */)
|
||||
+ new++;
|
||||
+
|
||||
+ /* Hide common prefix context */
|
||||
+ merge = where;
|
||||
+ while (old <= lastline && new <= pat_end) {
|
||||
+ if (!common_context(merge, old, new))
|
||||
+ break;
|
||||
+ old++;
|
||||
+ new++;
|
||||
+ merge++;
|
||||
+ }
|
||||
+
|
||||
+ if (fuzz != -1) {
|
||||
+ /* Hide common suffix context */
|
||||
+ merge_end = where + lastline - 1;
|
||||
+ while (old <= lastline && new <= pat_end) {
|
||||
+ if (!common_context(merge_end, lastline, pat_end))
|
||||
+ break;
|
||||
+ lastline--;
|
||||
+ pat_end--;
|
||||
+ merge_end--;
|
||||
+ }
|
||||
+ } else {
|
||||
+ LINENUM overlap = pch_suffix_context ();
|
||||
+
|
||||
+ /* Hide common suffix context: check how much overlap we have! */
|
||||
+ merge_end = merge - 1;
|
||||
+ while (overlap) {
|
||||
+ LINENUM n = 0;
|
||||
+
|
||||
+ merge_end += overlap;
|
||||
+ while (n < overlap && old <= lastline && new <= pat_end) {
|
||||
+ if (!common_context(merge_end, lastline, pat_end))
|
||||
+ break;
|
||||
+ lastline--;
|
||||
+ pat_end--;
|
||||
+ merge_end--;
|
||||
+ n++;
|
||||
+ }
|
||||
+ merge_end -= overlap - n;
|
||||
+ if (n == overlap)
|
||||
+ break;
|
||||
+ lastline += n;
|
||||
+ pat_end += n;
|
||||
+ overlap--;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ assert (outstate->after_newline);
|
||||
+ if (last_frozen_line < merge) {
|
||||
+ if (!copy_till(outstate, merge - 1))
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /* "From" lines in the patch */
|
||||
+ fprintf(fp, outstate->after_newline + "\n<<<<<<<\n");
|
||||
+ if (ferror (fp))
|
||||
+ write_fatal ();
|
||||
+ outstate->after_newline = true;
|
||||
+ while (old <= lastline) {
|
||||
+ outstate->after_newline = pch_write_line(old, fp);
|
||||
+ old++;
|
||||
+ }
|
||||
+
|
||||
+ if (fuzz) {
|
||||
+ /* "To" lines in the patch */
|
||||
+ fprintf(fp, outstate->after_newline + "\n|||||||\n");
|
||||
+ if (ferror (fp))
|
||||
+ write_fatal ();
|
||||
+ outstate->after_newline = true;
|
||||
+ while (new <= pat_end) {
|
||||
+ outstate->after_newline = pch_write_line(new, fp);
|
||||
+ new++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (fuzz != -1) {
|
||||
+ /* Merge result */
|
||||
+ fprintf(fp, outstate->after_newline + "\n=======\n");
|
||||
+ if (ferror (fp))
|
||||
+ write_fatal ();
|
||||
+ outstate->after_newline = true;
|
||||
+
|
||||
+ succeeded = apply_hunk(outstate, where) &&
|
||||
+ copy_till(outstate, merge_end);
|
||||
+ }
|
||||
+
|
||||
+ fprintf(fp, outstate->after_newline + "\n>>>>>>>\n");
|
||||
+ if (ferror (fp))
|
||||
+ write_fatal ();
|
||||
+ outstate->after_newline = true;
|
||||
+
|
||||
+ outstate->zero_output = false;
|
||||
+ return succeeded;
|
||||
+}
|
||||
+
|
||||
/* Create an output file. */
|
||||
|
||||
static FILE *
|
73
diff3-style-merges-include-filenames.diff
Normal file
73
diff3-style-merges-include-filenames.diff
Normal file
@ -0,0 +1,73 @@
|
||||
From: Andreas Gruenbacher <agruen@suse.de>
|
||||
Subject: diff3-style merges: include filenames
|
||||
|
||||
Include the filenames from the patch header in the diff3-style format.
|
||||
Use the name of the output file as the third filename.
|
||||
|
||||
<<<<<<< old-filename
|
||||
old lines from patch
|
||||
||||||| new-filename
|
||||
new lines from patch
|
||||
=======
|
||||
merge result
|
||||
>>>>>>> output-filename
|
||||
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
|
||||
---
|
||||
patch.c | 21 ++++++++++++++++++---
|
||||
1 file changed, 18 insertions(+), 3 deletions(-)
|
||||
|
||||
Index: b/patch.c
|
||||
===================================================================
|
||||
--- a/patch.c
|
||||
+++ b/patch.c
|
||||
@@ -1353,6 +1353,7 @@ static bool merge_hunk (struct outstate
|
||||
register LINENUM merge, merge_end;
|
||||
register FILE *fp = outstate->ofp;
|
||||
bool succeeded = true;
|
||||
+ const char *name;
|
||||
|
||||
while (pch_char(new) == '=' || pch_char(new) == '\n' /* ??? */)
|
||||
new++;
|
||||
@@ -1410,7 +1411,11 @@ static bool merge_hunk (struct outstate
|
||||
}
|
||||
|
||||
/* "From" lines in the patch */
|
||||
- fprintf(fp, outstate->after_newline + "\n<<<<<<<\n");
|
||||
+ name = pch_name(OLD);
|
||||
+ if (!name)
|
||||
+ name = "";
|
||||
+ fprintf(fp, outstate->after_newline + "\n<<<<<<<%*s\n",
|
||||
+ strlen(name) ? strlen(name) + 1 : 0, name);
|
||||
if (ferror (fp))
|
||||
write_fatal ();
|
||||
outstate->after_newline = true;
|
||||
@@ -1421,7 +1426,11 @@ static bool merge_hunk (struct outstate
|
||||
|
||||
if (fuzz) {
|
||||
/* "To" lines in the patch */
|
||||
- fprintf(fp, outstate->after_newline + "\n|||||||\n");
|
||||
+ name = pch_name(NEW);
|
||||
+ if (!name)
|
||||
+ name = "";
|
||||
+ fprintf(fp, outstate->after_newline + "\n|||||||%*s\n",
|
||||
+ strlen(name) ? strlen(name) + 1 : 0, name);
|
||||
if (ferror (fp))
|
||||
write_fatal ();
|
||||
outstate->after_newline = true;
|
||||
@@ -1442,7 +1451,13 @@ static bool merge_hunk (struct outstate
|
||||
copy_till(outstate, merge_end);
|
||||
}
|
||||
|
||||
- fprintf(fp, outstate->after_newline + "\n>>>>>>>\n");
|
||||
+ /* If the merge result and the new file are the same, label the merge
|
||||
+ result with the new file's name. */
|
||||
+ name = fuzz ? NULL : pch_name(NEW);
|
||||
+ if (!name)
|
||||
+ name = "";
|
||||
+ fprintf(fp, outstate->after_newline + "\n>>>>>>>%*s\n",
|
||||
+ strlen(name) ? strlen(name) + 1 : 0, name);
|
||||
if (ferror (fp))
|
||||
write_fatal ();
|
||||
outstate->after_newline = true;
|
110
diff3-style-merges-locate-merge.diff
Normal file
110
diff3-style-merges-locate-merge.diff
Normal file
@ -0,0 +1,110 @@
|
||||
---
|
||||
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)
|
36
diff3-style-merges-other-strategy.diff
Normal file
36
diff3-style-merges-other-strategy.diff
Normal file
@ -0,0 +1,36 @@
|
||||
---
|
||||
patch.c | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
Index: b/patch.c
|
||||
===================================================================
|
||||
--- a/patch.c
|
||||
+++ b/patch.c
|
||||
@@ -1459,6 +1459,18 @@ static bool merge_hunk (struct outstate
|
||||
R_merge_end--;
|
||||
}
|
||||
} else {
|
||||
+#if 1
|
||||
+ /* Hide common suffix context */
|
||||
+ R_merge_end = where + lastline - 1;
|
||||
+ while (old <= lastline && new <= pat_end) {
|
||||
+ if (!common_context(R_merge_end, lastline, pat_end))
|
||||
+ break;
|
||||
+ lastline--;
|
||||
+ pat_end--;
|
||||
+ R_merge_end--;
|
||||
+ }
|
||||
+ R_merge_end = merge - 1;
|
||||
+#else
|
||||
LINENUM overlap = pch_suffix_context ();
|
||||
|
||||
/* Hide common suffix context: check how much overlap we have! */
|
||||
@@ -1482,6 +1494,8 @@ static bool merge_hunk (struct outstate
|
||||
pat_end += n;
|
||||
overlap--;
|
||||
}
|
||||
+ /*assert(R_merge_end == merge - 1);*/
|
||||
+#endif
|
||||
}
|
||||
|
||||
assert (outstate->after_newline);
|
249
diff3-style-merges-overlap.diff
Normal file
249
diff3-style-merges-overlap.diff
Normal file
@ -0,0 +1,249 @@
|
||||
From: Andreas Gruenbacher <agruen@suse.de>
|
||||
Subject: diff3-style merges: overlapping merges
|
||||
|
||||
In some situations, hunks in a patch may apply so that their context
|
||||
lines overlap. Patch never commits context lines to the output until
|
||||
their contents are fully determined.
|
||||
|
||||
The diff3-style merge format may include context lines. For example,
|
||||
when he following patch:
|
||||
|
||||
# --- a
|
||||
# +++ b
|
||||
# @@ -2,3 +2,3 @@
|
||||
# x
|
||||
# -3
|
||||
# +3b
|
||||
# x
|
||||
|
||||
is applied to `seq 1 6` file with --merge=all, this is what you get (with
|
||||
fuzz 1):
|
||||
|
||||
1
|
||||
<<<<<<< a
|
||||
x
|
||||
3
|
||||
x
|
||||
||||||| b
|
||||
x
|
||||
3b
|
||||
x
|
||||
=======
|
||||
2
|
||||
3b
|
||||
4
|
||||
>>>>>>>
|
||||
5
|
||||
6
|
||||
|
||||
At this point, the first four lines of the output file are "frozen", and
|
||||
the next hunk cannot modify the fourth line anymore. This can cause the diff3-
|
||||
style merge format to reject hunks that would otherwise be accepted. To
|
||||
avoid this regression, this patch adds delayed printing of the end marker,
|
||||
with this effect on the merge format:
|
||||
|
||||
1
|
||||
<<<<<<< a
|
||||
x
|
||||
3
|
||||
x
|
||||
||||||| b
|
||||
x
|
||||
3b
|
||||
x
|
||||
=======
|
||||
2
|
||||
3b
|
||||
>>>>>>>
|
||||
<<<<<<< a
|
||||
x
|
||||
4
|
||||
x
|
||||
||||||| b
|
||||
x
|
||||
4b
|
||||
x
|
||||
=======
|
||||
4b
|
||||
5
|
||||
>>>>>>>
|
||||
6
|
||||
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
|
||||
---
|
||||
patch.c | 71 +++++++++++++++++++++++++++++++++++++++++++---------------------
|
||||
1 file changed, 48 insertions(+), 23 deletions(-)
|
||||
|
||||
Index: b/patch.c
|
||||
===================================================================
|
||||
--- a/patch.c
|
||||
+++ b/patch.c
|
||||
@@ -63,6 +63,7 @@ static LINENUM locate_hunk (LINENUM);
|
||||
static bool apply_hunk (struct outstate *, LINENUM);
|
||||
static bool common_context(LINENUM, LINENUM, LINENUM);
|
||||
static bool merge_hunk (struct outstate *, LINENUM, LINENUM);
|
||||
+static void merge_ends_here(struct outstate *outstate);
|
||||
static bool copy_till (struct outstate *, LINENUM);
|
||||
static bool patch_match (LINENUM, LINENUM, LINENUM, LINENUM);
|
||||
static bool similar (char const *, size_t, char const *, size_t);
|
||||
@@ -81,6 +82,8 @@ static void usage (FILE *, int) __attrib
|
||||
|
||||
enum mergetype { SHOW_ALL = 1, SHOW_FUZZ = 2, MERGE_REJECTS = 4 };
|
||||
static enum mergetype mergetype;
|
||||
+static LINENUM merge_end = -1;
|
||||
+static const char *merge_name;
|
||||
|
||||
const char *file_label[2];
|
||||
static bool make_backups;
|
||||
@@ -1361,7 +1364,7 @@ static bool merge_hunk (struct outstate
|
||||
register LINENUM lastline = pch_ptrn_lines ();
|
||||
register LINENUM new = lastline + 1;
|
||||
register LINENUM pat_end = pch_end ();
|
||||
- register LINENUM merge, merge_end;
|
||||
+ register LINENUM merge, R_merge_end;
|
||||
register FILE *fp = outstate->ofp;
|
||||
bool succeeded = true;
|
||||
const char *name;
|
||||
@@ -1381,32 +1384,32 @@ static bool merge_hunk (struct outstate
|
||||
|
||||
if (fuzz != -1) {
|
||||
/* Hide common suffix context */
|
||||
- merge_end = where + lastline - 1;
|
||||
+ R_merge_end = where + lastline - 1;
|
||||
while (old <= lastline && new <= pat_end) {
|
||||
- if (!common_context(merge_end, lastline, pat_end))
|
||||
+ if (!common_context(R_merge_end, lastline, pat_end))
|
||||
break;
|
||||
lastline--;
|
||||
pat_end--;
|
||||
- merge_end--;
|
||||
+ R_merge_end--;
|
||||
}
|
||||
} else {
|
||||
LINENUM overlap = pch_suffix_context ();
|
||||
|
||||
/* Hide common suffix context: check how much overlap we have! */
|
||||
- merge_end = merge - 1;
|
||||
+ R_merge_end = merge - 1;
|
||||
while (overlap) {
|
||||
LINENUM n = 0;
|
||||
|
||||
- merge_end += overlap;
|
||||
+ R_merge_end += overlap;
|
||||
while (n < overlap && old <= lastline && new <= pat_end) {
|
||||
- if (!common_context(merge_end, lastline, pat_end))
|
||||
+ if (!common_context(R_merge_end, lastline, pat_end))
|
||||
break;
|
||||
lastline--;
|
||||
pat_end--;
|
||||
- merge_end--;
|
||||
+ R_merge_end--;
|
||||
n++;
|
||||
}
|
||||
- merge_end -= overlap - n;
|
||||
+ R_merge_end -= overlap - n;
|
||||
if (n == overlap)
|
||||
break;
|
||||
lastline += n;
|
||||
@@ -1419,7 +1422,8 @@ static bool merge_hunk (struct outstate
|
||||
if (last_frozen_line < merge) {
|
||||
if (!copy_till(outstate, merge - 1))
|
||||
return false;
|
||||
- }
|
||||
+ } else
|
||||
+ merge_ends_here(outstate);
|
||||
|
||||
/* "From" lines in the patch */
|
||||
name = file_label[OLD] ? file_label[OLD] : pch_name(OLD);
|
||||
@@ -1458,25 +1462,41 @@ static bool merge_hunk (struct outstate
|
||||
write_fatal ();
|
||||
outstate->after_newline = true;
|
||||
|
||||
- succeeded = apply_hunk(outstate, where) &&
|
||||
- copy_till(outstate, merge_end);
|
||||
+ succeeded = apply_hunk(outstate, where);
|
||||
}
|
||||
|
||||
+ assert(merge_end == -1);
|
||||
+ merge_end = R_merge_end;
|
||||
+
|
||||
/* If the merge result and the new file are the same, label the merge
|
||||
result with the new file's name. */
|
||||
- name = fuzz ? NULL : (file_label[NEW] ? file_label[NEW] : pch_name(NEW));
|
||||
- if (!name)
|
||||
- name = "";
|
||||
- fprintf(fp, outstate->after_newline + "\n>>>>>>>%*s\n",
|
||||
- strlen(name) ? strlen(name) + 1 : 0, name);
|
||||
- if (ferror (fp))
|
||||
- write_fatal ();
|
||||
- outstate->after_newline = true;
|
||||
+ merge_name = fuzz ? NULL : (file_label[NEW] ? file_label[NEW] :
|
||||
+ pch_name(NEW));
|
||||
|
||||
outstate->zero_output = false;
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
+static void
|
||||
+merge_ends_here(struct outstate *outstate)
|
||||
+{
|
||||
+ register FILE *fp = outstate->ofp;
|
||||
+
|
||||
+ if (merge_end != -1)
|
||||
+ {
|
||||
+ if (!merge_name)
|
||||
+ merge_name = "";
|
||||
+ fprintf(fp, outstate->after_newline + "\n>>>>>>>%*s\n",
|
||||
+ strlen(merge_name) ? strlen(merge_name) + 1 : 0,
|
||||
+ merge_name);
|
||||
+ if (ferror (fp))
|
||||
+ write_fatal ();
|
||||
+ outstate->after_newline = true;
|
||||
+ outstate->zero_output = false;
|
||||
+ merge_end = -1;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* Create an output file. */
|
||||
|
||||
static FILE *
|
||||
@@ -1516,6 +1536,7 @@ static bool
|
||||
copy_till (register struct outstate *outstate, register LINENUM lastline)
|
||||
{
|
||||
register LINENUM R_last_frozen_line = last_frozen_line;
|
||||
+ register LINENUM R_merge_end = (merge_end != -1) ? merge_end : lastline;
|
||||
register FILE *fp = outstate->ofp;
|
||||
register char const *s;
|
||||
size_t size;
|
||||
@@ -1527,6 +1548,9 @@ copy_till (register struct outstate *out
|
||||
}
|
||||
while (R_last_frozen_line < lastline)
|
||||
{
|
||||
+ if (R_merge_end == R_last_frozen_line)
|
||||
+ merge_ends_here(outstate);
|
||||
+
|
||||
s = ifetch (++R_last_frozen_line, false, &size);
|
||||
if (size)
|
||||
{
|
||||
@@ -1538,6 +1562,8 @@ copy_till (register struct outstate *out
|
||||
}
|
||||
}
|
||||
last_frozen_line = R_last_frozen_line;
|
||||
+ if (merge_end != -1)
|
||||
+ merge_ends_here(outstate);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1555,9 +1581,8 @@ spew_output (struct outstate *outstate)
|
||||
format_linenum (numbuf1, last_frozen_line));
|
||||
}
|
||||
|
||||
- if (last_frozen_line < input_lines)
|
||||
- if (! copy_till (outstate, input_lines))
|
||||
- return false;
|
||||
+ if (! copy_till (outstate, input_lines))
|
||||
+ return false;
|
||||
|
||||
if (outstate->ofp && ! outfile)
|
||||
{
|
281
diff3-style-merges-pch_name.diff
Normal file
281
diff3-style-merges-pch_name.diff
Normal file
@ -0,0 +1,281 @@
|
||||
From: Andreas Gruenbacher <agruen@suse.de>
|
||||
Subject: diff3-style merges: pch_name()
|
||||
|
||||
Make a pch_name() function available for accessing the old and the new
|
||||
filename in the patch header.
|
||||
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
|
||||
---
|
||||
pch.c | 88 ++++++++++++++++++++++++++++++++++--------------------------------
|
||||
pch.h | 3 ++
|
||||
2 files changed, 49 insertions(+), 42 deletions(-)
|
||||
|
||||
Index: b/pch.c
|
||||
===================================================================
|
||||
--- a/pch.c
|
||||
+++ b/pch.c
|
||||
@@ -43,6 +43,7 @@ static int p_says_nonexistent[2]; /* [0]
|
||||
1 for existent and probably (but not necessarily) empty,
|
||||
2 for nonexistent */
|
||||
static int p_rfc934_nesting; /* RFC 934 nesting level */
|
||||
+static char *p_name[3]; /* filenames in patch headers */
|
||||
static time_t p_timestamp[2]; /* timestamps in patch headers */
|
||||
static off_t p_filesize; /* size of the patch file */
|
||||
static LINENUM p_first; /* 1st line number */
|
||||
@@ -70,8 +71,6 @@ static LINENUM p_efake = -1; /* end of
|
||||
static LINENUM p_bfake = -1; /* beg of faked up lines */
|
||||
static char *p_c_function; /* the C function a hunk is in */
|
||||
|
||||
-enum nametype { OLD, NEW, INDEX, NONE };
|
||||
-
|
||||
static char *scan_linenum (char *, LINENUM *);
|
||||
static enum diff intuit_diff_type (void);
|
||||
static enum nametype best_name (char * const *, int const *);
|
||||
@@ -300,13 +299,17 @@ intuit_diff_type (void)
|
||||
register bool this_is_a_command = false;
|
||||
register bool stars_this_line = false;
|
||||
enum nametype i;
|
||||
- char *name[3];
|
||||
struct stat st[3];
|
||||
int stat_errno[3];
|
||||
int version_controlled[3];
|
||||
register enum diff retval;
|
||||
|
||||
- name[OLD] = name[NEW] = name[INDEX] = 0;
|
||||
+ for (i = OLD; i <= INDEX; i++)
|
||||
+ if (p_name[i]) {
|
||||
+ free (p_name[i]);
|
||||
+ p_name[i] = 0;
|
||||
+ }
|
||||
+
|
||||
version_controlled[OLD] = -1;
|
||||
version_controlled[NEW] = -1;
|
||||
version_controlled[INDEX] = -1;
|
||||
@@ -365,16 +368,16 @@ intuit_diff_type (void)
|
||||
p_strip_trailing_cr = strip_trailing_cr;
|
||||
}
|
||||
if (!stars_last_line && strnEQ(s, "*** ", 4))
|
||||
- name[OLD] = fetchname (s+4, strippath, &p_timestamp[OLD]);
|
||||
+ p_name[OLD] = fetchname (s+4, strippath, &p_timestamp[OLD]);
|
||||
else if (strnEQ(s, "+++ ", 4))
|
||||
{
|
||||
/* Swap with NEW below. */
|
||||
- name[OLD] = fetchname (s+4, strippath, &p_timestamp[OLD]);
|
||||
+ p_name[OLD] = fetchname (s+4, strippath, &p_timestamp[OLD]);
|
||||
p_strip_trailing_cr = strip_trailing_cr;
|
||||
}
|
||||
else if (strnEQ(s, "Index:", 6))
|
||||
{
|
||||
- name[INDEX] = fetchname (s+6, strippath, (time_t *) 0);
|
||||
+ p_name[INDEX] = fetchname (s+6, strippath, (time_t *) 0);
|
||||
p_strip_trailing_cr = strip_trailing_cr;
|
||||
}
|
||||
else if (strnEQ(s, "Prereq:", 7)) {
|
||||
@@ -410,7 +413,7 @@ intuit_diff_type (void)
|
||||
if (strnEQ(t, "--- ", 4))
|
||||
{
|
||||
time_t timestamp = (time_t) -1;
|
||||
- name[NEW] = fetchname (t+4, strippath, ×tamp);
|
||||
+ p_name[NEW] = fetchname (t+4, strippath, ×tamp);
|
||||
if (timestamp != (time_t) -1)
|
||||
{
|
||||
p_timestamp[NEW] = timestamp;
|
||||
@@ -430,13 +433,13 @@ intuit_diff_type (void)
|
||||
if ((diff_type == NO_DIFF || diff_type == UNI_DIFF)
|
||||
&& strnEQ(s, "@@ -", 4)) {
|
||||
|
||||
- /* `name' and `p_timestamp' are backwards; swap them. */
|
||||
+ /* `p_name' and `p_timestamp' are backwards; swap them. */
|
||||
time_t ti = p_timestamp[OLD];
|
||||
p_timestamp[OLD] = p_timestamp[NEW];
|
||||
p_timestamp[NEW] = ti;
|
||||
- t = name[OLD];
|
||||
- name[OLD] = name[NEW];
|
||||
- name[NEW] = t;
|
||||
+ t = p_name[OLD];
|
||||
+ p_name[OLD] = p_name[NEW];
|
||||
+ p_name[NEW] = t;
|
||||
|
||||
s += 4;
|
||||
if (s[0] == '0' && !ISDIGIT (s[1]))
|
||||
@@ -451,9 +454,9 @@ intuit_diff_type (void)
|
||||
p_start = this_line;
|
||||
p_sline = p_input_line;
|
||||
retval = UNI_DIFF;
|
||||
- if (! ((name[OLD] || ! p_timestamp[OLD])
|
||||
- && (name[NEW] || ! p_timestamp[NEW]))
|
||||
- && ! name[INDEX])
|
||||
+ if (! ((p_name[OLD] || ! p_timestamp[OLD])
|
||||
+ && (p_name[NEW] || ! p_timestamp[NEW]))
|
||||
+ && ! p_name[INDEX])
|
||||
{
|
||||
char numbuf[LINENUM_LENGTH_BOUND + 1];
|
||||
say ("missing header for unified diff at line %s of patch\n",
|
||||
@@ -492,9 +495,9 @@ intuit_diff_type (void)
|
||||
next_intuit_at (saved_p_base, saved_p_bline);
|
||||
}
|
||||
|
||||
- if (! ((name[OLD] || ! p_timestamp[OLD])
|
||||
- && (name[NEW] || ! p_timestamp[NEW]))
|
||||
- && ! name[INDEX])
|
||||
+ if (! ((p_name[OLD] || ! p_timestamp[OLD])
|
||||
+ && (p_name[NEW] || ! p_timestamp[NEW]))
|
||||
+ && ! p_name[INDEX])
|
||||
{
|
||||
char numbuf[LINENUM_LENGTH_BOUND + 1];
|
||||
say ("missing header for context diff at line %s of patch\n",
|
||||
@@ -543,23 +546,23 @@ intuit_diff_type (void)
|
||||
{
|
||||
enum nametype i0 = NONE;
|
||||
|
||||
- if (! posixly_correct && (name[OLD] || name[NEW]) && name[INDEX])
|
||||
+ if (! posixly_correct && (p_name[OLD] || p_name[NEW]) && p_name[INDEX])
|
||||
{
|
||||
- free (name[INDEX]);
|
||||
- name[INDEX] = 0;
|
||||
+ free (p_name[INDEX]);
|
||||
+ p_name[INDEX] = 0;
|
||||
}
|
||||
|
||||
for (i = OLD; i <= INDEX; i++)
|
||||
- if (name[i])
|
||||
+ if (p_name[i])
|
||||
{
|
||||
- if (i0 != NONE && strcmp (name[i0], name[i]) == 0)
|
||||
+ if (i0 != NONE && strcmp (p_name[i0], p_name[i]) == 0)
|
||||
{
|
||||
/* It's the same name as before; reuse stat results. */
|
||||
stat_errno[i] = stat_errno[i0];
|
||||
if (! stat_errno[i])
|
||||
st[i] = st[i0];
|
||||
}
|
||||
- else if (stat (name[i], &st[i]) != 0)
|
||||
+ else if (stat (p_name[i], &st[i]) != 0)
|
||||
stat_errno[i] = errno;
|
||||
else
|
||||
{
|
||||
@@ -574,30 +577,30 @@ intuit_diff_type (void)
|
||||
{
|
||||
bool is_empty;
|
||||
|
||||
- i = best_name (name, stat_errno);
|
||||
+ i = best_name (p_name, stat_errno);
|
||||
|
||||
if (i == NONE && patch_get)
|
||||
{
|
||||
enum nametype nope = NONE;
|
||||
|
||||
for (i = OLD; i <= INDEX; i++)
|
||||
- if (name[i])
|
||||
+ if (p_name[i])
|
||||
{
|
||||
char const *cs;
|
||||
char *getbuf;
|
||||
char *diffbuf;
|
||||
bool readonly = (outfile
|
||||
- && strcmp (outfile, name[i]) != 0);
|
||||
+ && strcmp (outfile, p_name[i]) != 0);
|
||||
|
||||
- if (nope == NONE || strcmp (name[nope], name[i]) != 0)
|
||||
+ if (nope == NONE || strcmp (p_name[nope], p_name[i]) != 0)
|
||||
{
|
||||
cs = (version_controller
|
||||
- (name[i], readonly, (struct stat *) 0,
|
||||
+ (p_name[i], readonly, (struct stat *) 0,
|
||||
&getbuf, &diffbuf));
|
||||
version_controlled[i] = !! cs;
|
||||
if (cs)
|
||||
{
|
||||
- if (version_get (name[i], cs, false, readonly,
|
||||
+ if (version_get (p_name[i], cs, false, readonly,
|
||||
getbuf, &st[i]))
|
||||
stat_errno[i] = 0;
|
||||
else
|
||||
@@ -627,7 +630,7 @@ intuit_diff_type (void)
|
||||
(i == NONE ? "delete"
|
||||
: st[i].st_size == 0 ? "empty out"
|
||||
: "create"),
|
||||
- quotearg (name[i == NONE || st[i].st_size == 0 ? i0 : i]),
|
||||
+ quotearg (p_name[i == NONE || st[i].st_size == 0 ? i0 : i]),
|
||||
(i == NONE ? "does not exist"
|
||||
: st[i].st_size == 0 ? "is already empty"
|
||||
: "already exists"));
|
||||
@@ -640,19 +643,19 @@ intuit_diff_type (void)
|
||||
int distance_from_minimum[3];
|
||||
|
||||
for (i = OLD; i <= INDEX; i++)
|
||||
- if (name[i])
|
||||
+ if (p_name[i])
|
||||
{
|
||||
- newdirs[i] = (prefix_components (name[i], false)
|
||||
- - prefix_components (name[i], true));
|
||||
+ newdirs[i] = (prefix_components (p_name[i], false)
|
||||
+ - prefix_components (p_name[i], true));
|
||||
if (newdirs[i] < newdirs_min)
|
||||
newdirs_min = newdirs[i];
|
||||
}
|
||||
|
||||
for (i = OLD; i <= INDEX; i++)
|
||||
- if (name[i])
|
||||
+ if (p_name[i])
|
||||
distance_from_minimum[i] = newdirs[i] - newdirs_min;
|
||||
|
||||
- i = best_name (name, distance_from_minimum);
|
||||
+ i = best_name (p_name, distance_from_minimum);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -661,17 +664,12 @@ intuit_diff_type (void)
|
||||
inerrno = -1;
|
||||
else
|
||||
{
|
||||
- inname = name[i];
|
||||
- name[i] = 0;
|
||||
+ inname = savestr(p_name[i]);
|
||||
inerrno = stat_errno[i];
|
||||
invc = version_controlled[i];
|
||||
instat = st[i];
|
||||
}
|
||||
|
||||
- for (i = OLD; i <= INDEX; i++)
|
||||
- if (name[i])
|
||||
- free (name[i]);
|
||||
-
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -1803,6 +1801,12 @@ pch_says_nonexistent (bool which)
|
||||
/* Return timestamp of patch header for file WHICH (false = old, true = new),
|
||||
or -1 if there was no timestamp or an error in the timestamp. */
|
||||
|
||||
+const char *
|
||||
+pch_name (enum nametype type)
|
||||
+{
|
||||
+ return type == NONE ? NULL : p_name[type];
|
||||
+}
|
||||
+
|
||||
time_t
|
||||
pch_timestamp (bool which)
|
||||
{
|
||||
Index: b/pch.h
|
||||
===================================================================
|
||||
--- a/pch.h
|
||||
+++ b/pch.h
|
||||
@@ -22,6 +22,8 @@
|
||||
If not, write to the Free Software Foundation,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
+enum nametype { OLD, NEW, INDEX, NONE };
|
||||
+
|
||||
LINENUM pch_end (void);
|
||||
LINENUM pch_first (void);
|
||||
LINENUM pch_hunk_beg (void);
|
||||
@@ -39,6 +41,7 @@ char pch_char (LINENUM);
|
||||
int another_hunk (enum diff, bool);
|
||||
int pch_says_nonexistent (bool);
|
||||
size_t pch_line_len (LINENUM);
|
||||
+const char *pch_name(enum nametype);
|
||||
time_t pch_timestamp (bool);
|
||||
void do_ed_script (FILE *);
|
||||
void open_patch_file (char const *);
|
61
diff3-style-merges-refactoring-2.diff
Normal file
61
diff3-style-merges-refactoring-2.diff
Normal file
@ -0,0 +1,61 @@
|
||||
---
|
||||
patch.c | 42 ++++++++++++++++++++----------------------
|
||||
1 file changed, 20 insertions(+), 22 deletions(-)
|
||||
|
||||
Index: b/patch.c
|
||||
===================================================================
|
||||
--- a/patch.c
|
||||
+++ b/patch.c
|
||||
@@ -286,32 +286,30 @@ main (int argc, char **argv)
|
||||
newwhere = pch_newfirst() + last_offset;
|
||||
if (skip_rest_of_patch) {
|
||||
goto skip_hunk;
|
||||
- }
|
||||
- else if (!where
|
||||
- || (where == 1 && pch_says_nonexistent (reverse) == 2
|
||||
- && instat.st_size)) {
|
||||
-
|
||||
- if (where)
|
||||
- say ("Patch attempted to create file %s, which already exists.\n",
|
||||
- quotearg (inname));
|
||||
+ } else if (where == 1 && pch_says_nonexistent (reverse) == 2
|
||||
+ && instat.st_size) {
|
||||
+ say ("Patch attempted to create file %s, "
|
||||
+ "which already exists.\n", quotearg (inname));
|
||||
|
||||
goto skip_hunk;
|
||||
- }
|
||||
- else if (! apply_hunk (&outstate, where)) {
|
||||
+ } else if (!where) {
|
||||
goto skip_hunk;
|
||||
} else {
|
||||
- if (verbosity == VERBOSE
|
||||
- || (verbosity != SILENT && (fuzz || last_offset))) {
|
||||
- say ("Hunk #%d succeeded at %s", hunk,
|
||||
- format_linenum (numbuf, newwhere));
|
||||
- if (fuzz)
|
||||
- say (" with fuzz %s", format_linenum (numbuf, fuzz));
|
||||
- if (last_offset)
|
||||
- say (" (offset %s line%s)",
|
||||
- format_linenum (numbuf, last_offset),
|
||||
- "s" + (last_offset == 1));
|
||||
- say (".\n");
|
||||
- }
|
||||
+ if (!apply_hunk (&outstate, where))
|
||||
+ goto skip_hunk;
|
||||
+ }
|
||||
+
|
||||
+ if (verbosity == VERBOSE
|
||||
+ || (verbosity != SILENT && (fuzz || last_offset))) {
|
||||
+ say ("Hunk #%d succeeded at %s", hunk,
|
||||
+ format_linenum (numbuf, newwhere));
|
||||
+ if (fuzz)
|
||||
+ say (" with fuzz %s", format_linenum (numbuf, fuzz));
|
||||
+ if (last_offset)
|
||||
+ say (" (offset %s line%s)",
|
||||
+ format_linenum (numbuf, last_offset),
|
||||
+ "s" + (last_offset == 1));
|
||||
+ say (".\n");
|
||||
}
|
||||
continue;
|
||||
|
67
diff3-style-merges-refactoring.diff
Normal file
67
diff3-style-merges-refactoring.diff
Normal file
@ -0,0 +1,67 @@
|
||||
---
|
||||
patch.c | 36 +++++++++++++++---------------------
|
||||
1 file changed, 15 insertions(+), 21 deletions(-)
|
||||
|
||||
Index: b/patch.c
|
||||
===================================================================
|
||||
--- a/patch.c
|
||||
+++ b/patch.c
|
||||
@@ -285,13 +285,7 @@ main (int argc, char **argv)
|
||||
|
||||
newwhere = pch_newfirst() + last_offset;
|
||||
if (skip_rest_of_patch) {
|
||||
- if (!failed)
|
||||
- reject_header(outname);
|
||||
- abort_hunk();
|
||||
- failed++;
|
||||
- if (verbosity == VERBOSE)
|
||||
- say ("Hunk #%d ignored at %s.\n", hunk,
|
||||
- format_linenum (numbuf, newwhere));
|
||||
+ goto skip_hunk;
|
||||
}
|
||||
else if (!where
|
||||
|| (where == 1 && pch_says_nonexistent (reverse) == 2
|
||||
@@ -301,22 +295,10 @@ main (int argc, char **argv)
|
||||
say ("Patch attempted to create file %s, which already exists.\n",
|
||||
quotearg (inname));
|
||||
|
||||
- if (!failed)
|
||||
- reject_header(outname);
|
||||
- abort_hunk();
|
||||
- failed++;
|
||||
- if (verbosity != SILENT)
|
||||
- say ("Hunk #%d FAILED at %s.\n", hunk,
|
||||
- format_linenum (numbuf, newwhere));
|
||||
+ goto skip_hunk;
|
||||
}
|
||||
else if (! apply_hunk (&outstate, where)) {
|
||||
- if (!failed)
|
||||
- reject_header(outname);
|
||||
- abort_hunk ();
|
||||
- failed++;
|
||||
- if (verbosity != SILENT)
|
||||
- say ("Hunk #%d FAILED at %s.\n", hunk,
|
||||
- format_linenum (numbuf, newwhere));
|
||||
+ goto skip_hunk;
|
||||
} else {
|
||||
if (verbosity == VERBOSE
|
||||
|| (verbosity != SILENT && (fuzz || last_offset))) {
|
||||
@@ -331,6 +313,18 @@ main (int argc, char **argv)
|
||||
say (".\n");
|
||||
}
|
||||
}
|
||||
+ continue;
|
||||
+
|
||||
+skip_hunk:
|
||||
+ if (!failed)
|
||||
+ reject_header(outname);
|
||||
+ abort_hunk ();
|
||||
+ failed++;
|
||||
+ if (verbosity == VERBOSE ||
|
||||
+ (!skip_rest_of_patch && verbosity != SILENT))
|
||||
+ say ("Hunk #%d %s at %s.\n", hunk,
|
||||
+ skip_rest_of_patch ? "ignored" : "FAILED",
|
||||
+ format_linenum (numbuf, newwhere));
|
||||
}
|
||||
|
||||
if (!skip_rest_of_patch)
|
116
diff3-style-merges-rejects.diff
Normal file
116
diff3-style-merges-rejects.diff
Normal file
@ -0,0 +1,116 @@
|
||||
From: Andreas Gruenbacher <agruen@suse.de>
|
||||
Subject: diff3-style merges: merge rejects
|
||||
|
||||
With the --merge-all option, hunks which do not apply and which would
|
||||
end up in a *.rej file will also get added to output files. They will
|
||||
be bracketed like this:
|
||||
|
||||
<<<<<<<
|
||||
old lines from patch
|
||||
|||||||
|
||||
new lines from patch
|
||||
>>>>>>>
|
||||
|
||||
With this change, all pieces of a patch can be applied, and all the
|
||||
resulting merge conflicts can be fixed in the patched files instead
|
||||
of looking at the reject files.
|
||||
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
|
||||
---
|
||||
patch.c | 40 +++++++++++++++++++++++++++++++---------
|
||||
1 file changed, 31 insertions(+), 9 deletions(-)
|
||||
|
||||
Index: b/patch.c
|
||||
===================================================================
|
||||
--- a/patch.c
|
||||
+++ b/patch.c
|
||||
@@ -79,7 +79,7 @@ static void reinitialize_almost_everythi
|
||||
static void remove_if_needed (char const *, int volatile *);
|
||||
static void usage (FILE *, int) __attribute__((noreturn));
|
||||
|
||||
-enum mergetype { SHOW_ALL = 1, SHOW_FUZZ = 2 };
|
||||
+enum mergetype { SHOW_ALL = 1, SHOW_FUZZ = 2, MERGE_REJECTS = 4 };
|
||||
static enum mergetype mergetype;
|
||||
|
||||
static bool make_backups;
|
||||
@@ -299,7 +299,18 @@ main (int argc, char **argv)
|
||||
|
||||
goto skip_hunk;
|
||||
} else if (!where) {
|
||||
- goto skip_hunk;
|
||||
+ if (mergetype & MERGE_REJECTS) {
|
||||
+ LINENUM guess = pch_first () + last_offset;
|
||||
+
|
||||
+ if (merge_hunk(&outstate, guess, -1)) {
|
||||
+ merged++;
|
||||
+ mismatch = 1;
|
||||
+ } else {
|
||||
+ /* FIXME: guess harder! */
|
||||
+ goto skip_hunk;
|
||||
+ }
|
||||
+ } else
|
||||
+ goto skip_hunk;
|
||||
} else {
|
||||
if ((mergetype & SHOW_ALL) ||
|
||||
(fuzz && (mergetype & SHOW_FUZZ))) {
|
||||
@@ -316,10 +327,16 @@ main (int argc, char **argv)
|
||||
|
||||
if (verbosity == VERBOSE
|
||||
|| (verbosity != SILENT && (fuzz || last_offset))) {
|
||||
- say ("Hunk #%d succeeded at %s", hunk,
|
||||
- format_linenum (numbuf, newwhere));
|
||||
- if (fuzz)
|
||||
- say (" with fuzz %s", format_linenum (numbuf, fuzz));
|
||||
+ if (fuzz > mymaxfuzz) {
|
||||
+ say ("Hunk #%d merged at %s with errors", hunk,
|
||||
+ format_linenum (numbuf, newwhere));
|
||||
+ somefailed = true;
|
||||
+ } else {
|
||||
+ say ("Hunk #%d succeeded at %s", hunk,
|
||||
+ format_linenum (numbuf, newwhere));
|
||||
+ if (fuzz)
|
||||
+ say (" with fuzz %s", format_linenum (numbuf, fuzz));
|
||||
+ }
|
||||
if (last_offset)
|
||||
say (" (offset %s line%s)",
|
||||
format_linenum (numbuf, last_offset),
|
||||
@@ -521,7 +538,7 @@ reinitialize_almost_everything (void)
|
||||
skip_rest_of_patch = false;
|
||||
}
|
||||
|
||||
-static char const shortopts[] = "bB:cd:D:eEfF:g:i:lnNo:p:r:RstTuvV:x:Y:z:Z";
|
||||
+static char const shortopts[] = "bB:cd:D:eEfF:g:i:lMnNo:p:r:RstTuvV:x:Y:z:Z";
|
||||
static struct option const longopts[] =
|
||||
{
|
||||
{"backup", no_argument, NULL, 'b'},
|
||||
@@ -591,7 +608,7 @@ static char const *const option_help[] =
|
||||
" -r FILE --reject-file=FILE Output rejects to FILE.",
|
||||
"",
|
||||
" -D NAME --ifdef=NAME Make merged if-then-else output using NAME.",
|
||||
-" --merge={fuzz,all} Produce a diff3-style merge.",
|
||||
+" --merge={rejects,fuzz,all} Produce a diff3-style merge.",
|
||||
" -E --remove-empty-files Remove output files that are empty after patching.",
|
||||
"",
|
||||
" -Z --set-utc Set times of patched files, assuming diff uses UTC (GMT).",
|
||||
@@ -730,6 +747,9 @@ get_some_switches (void)
|
||||
case 'l':
|
||||
canonicalize = true;
|
||||
break;
|
||||
+ case 'M':
|
||||
+ mergetype |= MERGE_REJECTS;
|
||||
+ break;
|
||||
case 'n':
|
||||
diff_type = NORMAL_DIFF;
|
||||
break;
|
||||
@@ -835,7 +855,9 @@ get_some_switches (void)
|
||||
char *tok = strtok(optarg, ",");
|
||||
|
||||
do {
|
||||
- if (!strcmp(tok, "fuzz"))
|
||||
+ if (!strcmp(tok, "rejects"))
|
||||
+ mergetype |= MERGE_REJECTS;
|
||||
+ else if (!strcmp(tok, "fuzz"))
|
||||
mergetype |= SHOW_FUZZ;
|
||||
else if (!strcmp(tok, "all"))
|
||||
mergetype |= SHOW_ALL;
|
492
diff3-style-merges-tests.diff
Normal file
492
diff3-style-merges-tests.diff
Normal file
@ -0,0 +1,492 @@
|
||||
---
|
||||
merge-tests/diff3-merge.test | 35 +++++++++
|
||||
merge-tests/locate-rejects.test | 77 ++++++++++++++++++++
|
||||
merge-tests/modes.test | 148 ++++++++++++++++++++++++++++++++++++++++
|
||||
merge-tests/overlap-patch.test | 94 +++++++++++++++++++++++++
|
||||
merge-tests/prefix-suffix.test | 105 ++++++++++++++++++++++++++++
|
||||
5 files changed, 459 insertions(+)
|
||||
|
||||
Index: b/merge-tests/diff3-merge.test
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ b/merge-tests/diff3-merge.test
|
||||
@@ -0,0 +1,35 @@
|
||||
+$ tmpdir=$(mktemp -d)
|
||||
+$ trap "cd /; rm -rf $tmpdir" EXIT
|
||||
+$ cd $tmpdir
|
||||
+
|
||||
+ $ seq 1 4 > a
|
||||
+ $ sed -e 's/2/2b/' a > b
|
||||
+ $ sed -e 's/4/4d/' a > c
|
||||
+
|
||||
+Diff3 will merge changes if they are one line apart:
|
||||
+
|
||||
+ $ diff3 -m b a c
|
||||
+ > 1
|
||||
+ > 2b
|
||||
+ > 3
|
||||
+ > 4d
|
||||
+
|
||||
+But it will not merge adjacent changes:
|
||||
+
|
||||
+ $ sed -e 's/3/3c/' a > d
|
||||
+
|
||||
+ $ diff3 -m b a d
|
||||
+ > 1
|
||||
+ > <<<<<<< b
|
||||
+ > 2b
|
||||
+ > 3
|
||||
+ > ||||||| a
|
||||
+ > 2
|
||||
+ > 3
|
||||
+ > =======
|
||||
+ > 2
|
||||
+ > 3c
|
||||
+ > >>>>>>> d
|
||||
+ > 4
|
||||
+
|
||||
+Patch will merge the changes in either case.
|
||||
Index: b/merge-tests/modes.test
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ b/merge-tests/modes.test
|
||||
@@ -0,0 +1,148 @@
|
||||
+$ tmpdir=$(mktemp -d)
|
||||
+$ trap "cd /; rm -rf $tmpdir" EXIT
|
||||
+$ cd $tmpdir
|
||||
+
|
||||
+$ cat > clean.diff
|
||||
+< --- a
|
||||
+< +++ b
|
||||
+< @@ -2 +2 @@
|
||||
+< -2
|
||||
+< +2clean
|
||||
+
|
||||
+$ seq 1 3 > c ; patch c < clean.diff
|
||||
+> patching file c
|
||||
+
|
||||
+$ cat c
|
||||
+> 1
|
||||
+> 2clean
|
||||
+> 3
|
||||
+
|
||||
+$ seq 1 3 > c ; patch --merge=all c < clean.diff
|
||||
+> patching file c
|
||||
+
|
||||
+$ cat c
|
||||
+> 1
|
||||
+> <<<<<<< a
|
||||
+> 2
|
||||
+> =======
|
||||
+> 2clean
|
||||
+> >>>>>>> b
|
||||
+> 3
|
||||
+
|
||||
+$ seq 1 3 > c ; patch --merge=fuzz c < clean.diff
|
||||
+> patching file c
|
||||
+
|
||||
+$ cat c
|
||||
+> 1
|
||||
+> 2clean
|
||||
+> 3
|
||||
+
|
||||
+$ seq 1 3 > c ; patch --merge=rejects c < clean.diff
|
||||
+> patching file c
|
||||
+
|
||||
+$ cat c
|
||||
+> 1
|
||||
+> 2clean
|
||||
+> 3
|
||||
+
|
||||
+$ cat > fuzz.diff
|
||||
+< --- a
|
||||
+< +++ b
|
||||
+< @@ -1,3 +1,3 @@
|
||||
+< x
|
||||
+< -2
|
||||
+< +2fuzz
|
||||
+< x
|
||||
+
|
||||
+$ seq 1 3 > c ; patch c < fuzz.diff
|
||||
+> patching file c
|
||||
+> Hunk #1 succeeded at 1 with fuzz 1.
|
||||
+
|
||||
+$ cat c
|
||||
+> 1
|
||||
+> 2fuzz
|
||||
+> 3
|
||||
+
|
||||
+$ seq 1 3 > c ; patch --merge=all c < fuzz.diff
|
||||
+> patching file c
|
||||
+> Hunk #1 succeeded at 1 with fuzz 1.
|
||||
+
|
||||
+$ cat c
|
||||
+> <<<<<<< a
|
||||
+> x
|
||||
+> 2
|
||||
+> x
|
||||
+> ||||||| b
|
||||
+> x
|
||||
+> 2fuzz
|
||||
+> x
|
||||
+> =======
|
||||
+> 1
|
||||
+> 2fuzz
|
||||
+> 3
|
||||
+> >>>>>>>
|
||||
+
|
||||
+$ seq 1 3 > c ; patch --merge=fuzz c < fuzz.diff
|
||||
+> patching file c
|
||||
+> Hunk #1 succeeded at 1 with fuzz 1.
|
||||
+
|
||||
+$ cat c
|
||||
+> <<<<<<< a
|
||||
+> x
|
||||
+> 2
|
||||
+> x
|
||||
+> ||||||| b
|
||||
+> x
|
||||
+> 2fuzz
|
||||
+> x
|
||||
+> =======
|
||||
+> 1
|
||||
+> 2fuzz
|
||||
+> 3
|
||||
+> >>>>>>>
|
||||
+
|
||||
+$ seq 1 3 > c ; patch --merge=rejects c < fuzz.diff
|
||||
+> patching file c
|
||||
+> Hunk #1 succeeded at 1 with fuzz 1.
|
||||
+
|
||||
+$ cat c
|
||||
+> 1
|
||||
+> 2fuzz
|
||||
+> 3
|
||||
+
|
||||
+$ cat > reject.diff
|
||||
+< --- a
|
||||
+< +++ b
|
||||
+< @@ -2 +2 @@
|
||||
+< -2reject
|
||||
+< +2reject
|
||||
+
|
||||
+$ seq 1 3 > c ; patch c < reject.diff
|
||||
+> patching file c
|
||||
+> Hunk #1 FAILED at 2.
|
||||
+> 1 out of 1 hunk FAILED -- saving rejects to file c.rej
|
||||
+
|
||||
+$ seq 1 3 > c ; patch --merge=all c < reject.diff
|
||||
+> patching file c
|
||||
+> Hunk #1 FAILED at 2.
|
||||
+> 1 out of 1 hunk FAILED -- saving rejects to file c.rej
|
||||
+
|
||||
+$ seq 1 3 > c ; patch --merge=fuzz c < reject.diff
|
||||
+> patching file c
|
||||
+> Hunk #1 FAILED at 2.
|
||||
+> 1 out of 1 hunk FAILED -- saving rejects to file c.rej
|
||||
+
|
||||
+$ seq 1 3 > c ; patch --merge=rejects c < reject.diff
|
||||
+> patching file c
|
||||
+> Hunk #1 merged at 2 with errors.
|
||||
+
|
||||
+$ cat c
|
||||
+> 1
|
||||
+> <<<<<<< a
|
||||
+> 2reject
|
||||
+> ||||||| b
|
||||
+> 2reject
|
||||
+> >>>>>>>
|
||||
+> 2
|
||||
+> 3
|
||||
+
|
||||
Index: b/merge-tests/prefix-suffix.test
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ b/merge-tests/prefix-suffix.test
|
||||
@@ -0,0 +1,105 @@
|
||||
+$ tmpdir=$(mktemp -d)
|
||||
+$ trap "cd /; rm -rf $tmpdir" EXIT
|
||||
+$ cd $tmpdir
|
||||
+
|
||||
+$ seq 1 7 > a
|
||||
+$ seq 1 7 | sed -e '4d' > b
|
||||
+$ diff -u -L a -L b a b > ab.diff
|
||||
+$ diff -u -L b -L a b a > ba.diff
|
||||
+
|
||||
+$ cp a c
|
||||
+$ patch --merge=all c < ab.diff
|
||||
+> patching file c
|
||||
+
|
||||
+$ cat c
|
||||
+> 1
|
||||
+> 2
|
||||
+> 3
|
||||
+> <<<<<<< a
|
||||
+> 4
|
||||
+> =======
|
||||
+> >>>>>>> b
|
||||
+> 5
|
||||
+> 6
|
||||
+> 7
|
||||
+
|
||||
+$ cp b c
|
||||
+$ patch --merge=all c < ba.diff
|
||||
+> patching file c
|
||||
+
|
||||
+$ cat c
|
||||
+> 1
|
||||
+> 2
|
||||
+> 3
|
||||
+> <<<<<<< b
|
||||
+> =======
|
||||
+> 4
|
||||
+> >>>>>>> a
|
||||
+> 5
|
||||
+> 6
|
||||
+> 7
|
||||
+
|
||||
+$ diff -u /dev/null a > a.diff
|
||||
+$ echo -n '' > c
|
||||
+$ patch --merge=all c < a.diff
|
||||
+> patching file c
|
||||
+
|
||||
+$ cat c
|
||||
+> <<<<<<<
|
||||
+> =======
|
||||
+> 1
|
||||
+> 2
|
||||
+> 3
|
||||
+> 4
|
||||
+> 5
|
||||
+> 6
|
||||
+> 7
|
||||
+> >>>>>>> a
|
||||
+
|
||||
+$ diff -u a /dev/null > a-.diff
|
||||
+$ cp a c
|
||||
+$ patch --merge=all c < a-.diff
|
||||
+> patching file c
|
||||
+
|
||||
+$ cat c
|
||||
+#
|
||||
+> <<<<<<< a
|
||||
+> 1
|
||||
+> 2
|
||||
+> 3
|
||||
+> 4
|
||||
+> 5
|
||||
+> 6
|
||||
+> 7
|
||||
+> =======
|
||||
+> >>>>>>>
|
||||
+
|
||||
+$ seq -f '%gc' 1 7 > c
|
||||
+$ patch --merge=rejects c < ab.diff
|
||||
+> patching file c
|
||||
+> Hunk #1 merged at 1 with errors.
|
||||
+
|
||||
+$ cat c
|
||||
+> <<<<<<< a
|
||||
+> 1
|
||||
+> 2
|
||||
+> 3
|
||||
+> 4
|
||||
+> 5
|
||||
+> 6
|
||||
+> 7
|
||||
+> ||||||| b
|
||||
+> 1
|
||||
+> 2
|
||||
+> 3
|
||||
+> 5
|
||||
+> 6
|
||||
+> 7
|
||||
+> >>>>>>>
|
||||
+> 1c
|
||||
+> 2c
|
||||
+> 3c
|
||||
+> 4c
|
||||
+> 5c
|
||||
+> 6c
|
||||
+> 7c
|
||||
Index: b/merge-tests/overlap-patch.test
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ b/merge-tests/overlap-patch.test
|
||||
@@ -0,0 +1,94 @@
|
||||
+$ tmpdir=$(mktemp -d)
|
||||
+$ trap "cd /; rm -rf $tmpdir" EXIT
|
||||
+$ cd $tmpdir
|
||||
+
|
||||
+$ cat > patch
|
||||
+< --- a
|
||||
+< +++ b
|
||||
+< @@ -2,3 +2,3 @@
|
||||
+< x
|
||||
+< -3
|
||||
+< +3b
|
||||
+< x
|
||||
+
|
||||
+$ seq 1 6 > file
|
||||
+$ patch file < patch
|
||||
+> patching file file
|
||||
+> Hunk #1 succeeded at 2 with fuzz 1.
|
||||
+
|
||||
+$ seq 1 6 > file
|
||||
+$ patch --merge=all file < patch
|
||||
+> patching file file
|
||||
+> Hunk #1 succeeded at 2 with fuzz 1.
|
||||
+
|
||||
+$ cat file
|
||||
+> 1
|
||||
+> <<<<<<< a
|
||||
+> x
|
||||
+> 3
|
||||
+> x
|
||||
+> ||||||| b
|
||||
+> x
|
||||
+> 3b
|
||||
+> x
|
||||
+> =======
|
||||
+> 2
|
||||
+> 3b
|
||||
+> 4
|
||||
+> >>>>>>>
|
||||
+> 5
|
||||
+> 6
|
||||
+
|
||||
+$ cat > patch
|
||||
+< --- a
|
||||
+< +++ b
|
||||
+< @@ -2,3 +2,3 @@
|
||||
+< x
|
||||
+< -3
|
||||
+< +3b
|
||||
+< x
|
||||
+< @@ -3,3 +3,3 @@
|
||||
+< x
|
||||
+< -4
|
||||
+< +4b
|
||||
+< x
|
||||
+
|
||||
+$ seq 1 6 > file
|
||||
+$ patch file < patch
|
||||
+> patching file file
|
||||
+> Hunk #1 succeeded at 2 with fuzz 1.
|
||||
+> Hunk #2 succeeded at 3 with fuzz 1.
|
||||
+
|
||||
+$ seq 1 6 > file
|
||||
+$ patch --merge=all file < patch
|
||||
+> patching file file
|
||||
+> Hunk #1 succeeded at 2 with fuzz 1.
|
||||
+> Hunk #2 succeeded at 3 with fuzz 1.
|
||||
+
|
||||
+$ cat file
|
||||
+> 1
|
||||
+> <<<<<<< a
|
||||
+> x
|
||||
+> 3
|
||||
+> x
|
||||
+> ||||||| b
|
||||
+> x
|
||||
+> 3b
|
||||
+> x
|
||||
+> =======
|
||||
+> 2
|
||||
+> 3b
|
||||
+> >>>>>>>
|
||||
+> <<<<<<< a
|
||||
+> x
|
||||
+> 4
|
||||
+> x
|
||||
+> ||||||| b
|
||||
+> x
|
||||
+> 4b
|
||||
+> x
|
||||
+> =======
|
||||
+> 4b
|
||||
+> 5
|
||||
+> >>>>>>>
|
||||
+> 6
|
||||
Index: b/merge-tests/locate-rejects.test
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ b/merge-tests/locate-rejects.test
|
||||
@@ -0,0 +1,77 @@
|
||||
+$ tmpdir=$(mktemp -d)
|
||||
+$ trap "cd /; rm -rf $tmpdir" EXIT
|
||||
+$ cd $tmpdir
|
||||
+
|
||||
+$ seq 1 7 > a
|
||||
+$ seq 1 7 | sed -e 's/4/4b/' > b
|
||||
+$ seq 1 7 | sed -e 's/4/4c/' > c
|
||||
+$ seq 1 7 | sed -e '4d' > d
|
||||
+
|
||||
+$ diff -u a b > ab.diff
|
||||
+
|
||||
+$ patch c < ab.diff
|
||||
+> patching file c
|
||||
+> Hunk #1 FAILED at 1.
|
||||
+> 1 out of 1 hunk FAILED -- saving rejects to file c.rej
|
||||
+
|
||||
+$ patch --merge=rejects c < ab.diff
|
||||
+> patching file c
|
||||
+> Hunk #1 merged at 1 with errors.
|
||||
+
|
||||
+$ cat c
|
||||
+> 1
|
||||
+> 2
|
||||
+> 3
|
||||
+> <<<<<<< a
|
||||
+> 4
|
||||
+> 5
|
||||
+> 6
|
||||
+> 7
|
||||
+> ||||||| b
|
||||
+> 4b
|
||||
+> 5
|
||||
+> 6
|
||||
+> 7
|
||||
+> >>>>>>>
|
||||
+> 4c
|
||||
+> 5
|
||||
+> 6
|
||||
+> 7
|
||||
+
|
||||
+$ (seq 1 3; echo 7) > c
|
||||
+$ patch --merge=rejects c < ab.diff
|
||||
+> patching file c
|
||||
+> Hunk #1 merged at 1 with errors.
|
||||
+
|
||||
+$ cat c
|
||||
+> 1
|
||||
+> 2
|
||||
+> 3
|
||||
+> <<<<<<< a
|
||||
+> 4
|
||||
+> 5
|
||||
+> 6
|
||||
+> ||||||| b
|
||||
+> 4b
|
||||
+> 5
|
||||
+> 6
|
||||
+> >>>>>>>
|
||||
+> 7
|
||||
+
|
||||
+$ patch --merge=rejects d < ab.diff
|
||||
+> patching file d
|
||||
+> Hunk #1 merged at 1 with errors.
|
||||
+
|
||||
+$ cat d
|
||||
+> 1
|
||||
+> 2
|
||||
+> 3
|
||||
+> <<<<<<< a
|
||||
+> 4
|
||||
+> ||||||| b
|
||||
+> 4b
|
||||
+> >>>>>>>
|
||||
+> 5
|
||||
+> 6
|
||||
+> 7
|
||||
+
|
19
fail.test
19
fail.test
@ -1,19 +0,0 @@
|
||||
$ mkdir d
|
||||
$ cd d
|
||||
|
||||
$ mkdir sub
|
||||
$ echo 1 > f
|
||||
$ echo 2 > f.new
|
||||
$ diff -Nu f f.new > f.diff
|
||||
$ mv f.new f
|
||||
$ echo 3 > f.new
|
||||
$ diff -Nu f f.new >> f.diff
|
||||
$ rm f.new
|
||||
$ echo 1 > f
|
||||
$ chmod a=r f
|
||||
$ strace -o ../log patch -p0 --backup < f.diff
|
||||
> patching file f
|
||||
> patching file f
|
||||
|
||||
$ cd ..
|
||||
$ rm -rf d
|
@ -1,3 +1,9 @@
|
||||
-------------------------------------------------------------------
|
||||
Tue Feb 3 06:10:49 CET 2009 - agruen@suse.de
|
||||
|
||||
- Implement diff3-style merges (including several fixes and
|
||||
improvements).
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Apr 23 10:53:19 CEST 2008 - agruen@suse.de
|
||||
|
||||
|
40
patch.spec
40
patch.spec
@ -1,10 +1,17 @@
|
||||
#
|
||||
# spec file for package patch (Version 2.5.9)
|
||||
#
|
||||
# Copyright (c) 2008 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
||||
# This file and all modifications and additions to the pristine
|
||||
# package are under the same license as the package itself.
|
||||
# Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
||||
#
|
||||
# All modifications and additions to the file contributed by third parties
|
||||
# remain the property of their copyright owners, unless otherwise agreed
|
||||
# upon. The license for this file, and modifications and additions to the
|
||||
# file, is the same license as for the pristine package itself (unless the
|
||||
# license for the pristine package is not an Open Source License, in which
|
||||
# case the license is the MIT License). An "Open Source License" is a
|
||||
# license that conforms to the Open Source Definition (Version 1.9)
|
||||
# published by the Open Source Initiative.
|
||||
|
||||
# Please submit bugfixes or comments via http://bugs.opensuse.org/
|
||||
#
|
||||
|
||||
@ -16,7 +23,7 @@ License: GPL v2 or later
|
||||
Group: Productivity/Text/Utilities
|
||||
AutoReqProv: on
|
||||
Version: 2.5.9
|
||||
Release: 252
|
||||
Release: 287
|
||||
Summary: GNU patch
|
||||
Source: ftp://prep.ai.mit.edu/pub/gnu/patch/%{name}-%{version}.tar.bz2
|
||||
Url: ftp://alpha.gnu.org/gnu/diffutils/
|
||||
@ -28,6 +35,17 @@ Patch4: if_else_endif_comments.diff
|
||||
Patch5: patch-2.5.9-cat_if_device.diff
|
||||
Patch6: patch-man-unified-reject.diff
|
||||
Patch7: fix-partial-context.diff
|
||||
Patch8: diff3-style-merges-tests.diff
|
||||
Patch9: diff3-style-merges-refactoring.diff
|
||||
Patch10: diff3-style-merges-refactoring-2.diff
|
||||
Patch11: diff3-style-merges-base.diff
|
||||
Patch12: diff3-style-merges-rejects.diff
|
||||
Patch13: diff3-style-merges-pch_name.diff
|
||||
Patch14: diff3-style-merges-include-filenames.diff
|
||||
Patch15: diff3-style-merges-add-file-labels.diff
|
||||
Patch16: diff3-style-merges-overlap.diff
|
||||
Patch17: diff3-style-merges-locate-merge.diff
|
||||
Patch18: diff3-style-merges-other-strategy.diff
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
|
||||
%description
|
||||
@ -51,6 +69,17 @@ Authors:
|
||||
%patch5 -p1
|
||||
%patch6 -p1
|
||||
%patch7 -p1
|
||||
%patch8 -p1
|
||||
%patch9 -p1
|
||||
%patch10 -p1
|
||||
%patch11 -p1
|
||||
%patch12 -p1
|
||||
%patch13 -p1
|
||||
%patch14 -p1
|
||||
%patch15 -p1
|
||||
%patch16 -p1
|
||||
%patch17 -p1
|
||||
%patch18 -p1
|
||||
|
||||
%build
|
||||
aclocal --acdir=m4
|
||||
@ -76,6 +105,9 @@ make install \
|
||||
%doc %{_mandir}/man1/patch.1.gz
|
||||
|
||||
%changelog
|
||||
* Tue Feb 03 2009 agruen@suse.de
|
||||
- Implement diff3-style merges (including several fixes and
|
||||
improvements).
|
||||
* Wed Apr 23 2008 agruen@suse.de
|
||||
- remember-backup-files.diff: Fix bug when a file is touched by
|
||||
the same patch more than twice. Move the test cases from the
|
||||
|
Loading…
Reference in New Issue
Block a user