SHA256
1
0
forked from pool/patch
patch/unified-reject-files.diff

296 lines
7.7 KiB
Diff

Generate unified diff style reject files.
---
patch.c | 104 +++++++++++++++++++++++++++++++++++++--
patch.man | 3 +
tests/unified-reject-files.shrun | 104 +++++++++++++++++++++++++++++++++++++++
3 files changed, 208 insertions(+), 3 deletions(-)
Index: b/patch.man
===================================================================
--- a/patch.man
+++ b/patch.man
@@ -517,6 +517,9 @@ instead of the default
.B \&.rej
file.
.TP
+\fB\*=unified\-reject\-files\fP
+Produce unified reject files. The default is to produce context type reject files.
+.TP
\fB\-R\fP or \fB\*=reverse\fP
Assume that this patch was created with the old and new files swapped.
(Yes, I'm afraid that does happen occasionally, human nature being what it
Index: b/patch.c
===================================================================
--- a/patch.c
+++ b/patch.c
@@ -66,8 +66,9 @@ static bool patch_match (LINENUM, LINENU
static bool similar (char const *, size_t, char const *, size_t);
static bool spew_output (struct outstate *);
static char const *make_temp (char);
+static void abort_hunk_context (void);
+static void abort_hunk_unified (void);
static int numeric_string (char const *, bool, char const *);
-static void abort_hunk (void);
static void cleanup (void);
static void get_some_switches (void);
static void init_output (char const *, int, struct outstate *);
@@ -76,6 +77,8 @@ static void reinitialize_almost_everythi
static void remove_if_needed (char const *, int volatile *);
static void usage (FILE *, int) __attribute__((noreturn));
+static void (*abort_hunk) (void) = abort_hunk_context;
+
static bool make_backups;
static bool backup_if_mismatch;
static char const *version_control;
@@ -522,6 +525,7 @@ static struct option const longopts[] =
{"no-backup-if-mismatch", no_argument, NULL, CHAR_MAX + 6},
{"posix", no_argument, NULL, CHAR_MAX + 7},
{"quoting-style", required_argument, NULL, CHAR_MAX + 8},
+ {"unified-reject-files", no_argument, NULL, CHAR_MAX + 9},
{NULL, no_argument, NULL, 0}
};
@@ -580,6 +584,7 @@ static char const *const option_help[] =
" --verbose Output extra information about the work being done.",
" --dry-run Do not actually change any files; just print what would happen.",
" --posix Conform to the POSIX standard.",
+" --unified-reject-files Create unified reject files.",
"",
" -d DIR --directory=DIR Change the working directory to DIR first.",
#if HAVE_SETMODE_DOS
@@ -779,6 +784,9 @@ get_some_switches (void)
(enum quoting_style) i);
}
break;
+ case CHAR_MAX + 9:
+ abort_hunk = abort_hunk_unified;
+ break;
default:
usage (stderr, 2);
}
@@ -930,7 +938,7 @@ locate_hunk (LINENUM fuzz)
/* We did not find the pattern, dump out the hunk so they can handle it. */
static void
-abort_hunk (void)
+abort_hunk_context (void)
{
register LINENUM i;
register LINENUM pat_end = pch_end ();
@@ -979,13 +987,103 @@ abort_hunk (void)
pch_write_line (i, rejfp);
break;
default:
- fatal ("fatal internal error in abort_hunk");
+ fatal ("fatal internal error in abort_hunk_context");
}
if (ferror (rejfp))
write_fatal ();
}
}
+/* Produce unified reject files */
+
+static void
+print_unified(FILE *fp)
+{
+ register LINENUM old = 1;
+ register LINENUM lastline = pch_ptrn_lines ();
+ register LINENUM new = lastline + 1;
+ register LINENUM pat_end = pch_end ();
+
+ while (pch_char (new) == '=' || pch_char (new) == '\n')
+ new++;
+
+ while (old <= lastline)
+ {
+ if (pch_char (old) == '-')
+ {
+ fputc ('-', fp);
+ pch_write_line (old++, fp);
+ }
+ else if (new > pat_end)
+ break;
+ else if (pch_char (new) == '+')
+ {
+ fputc ('+', fp);
+ pch_write_line (new++, fp);
+ }
+ else if (pch_char (new) != pch_char (old))
+ {
+ char numbuf0[LINENUM_LENGTH_BOUND + 1];
+ char numbuf1[LINENUM_LENGTH_BOUND + 1];
+ if (debug & 1)
+ say ("oldchar = '%c', newchar = '%c'\n",
+ pch_char (old), pch_char (new));
+ fatal ("Out-of-sync patch, lines %s,%s -- mangled text or "
+ "line numbers, maybe?",
+ format_linenum (numbuf0, pch_hunk_beg () + old),
+ format_linenum (numbuf1, pch_hunk_beg () + new));
+ }
+ else if (pch_char (new) == '!')
+ {
+ do
+ {
+ fputc ('-', fp);
+ pch_write_line (old++, fp);
+ }
+ while (pch_char (old) == '!');
+ do
+ {
+ fputc ('+', fp);
+ pch_write_line (new++, fp);
+ }
+ while (pch_char (new) == '!');
+ }
+ else
+ {
+ assert (pch_char (new) == ' ');
+ fputc (' ', fp);
+ pch_write_line (new, fp);
+ old++;
+ new++;
+ }
+ }
+ while (pch_char (new) == '+' || pch_char (new) == ' ')
+ {
+ fputc ('+', fp);
+ pch_write_line (new++, fp);
+ }
+ assert (new > pat_end);
+}
+
+static void
+abort_hunk_unified (void)
+{
+ char rangebuf0[LINERANGE_LENGTH_BOUND + 1];
+ char rangebuf1[LINERANGE_LENGTH_BOUND + 1];
+ LINENUM oldfirst = pch_first () + last_offset;
+ LINENUM newfirst = pch_newfirst () + last_offset;
+ char const *c_function = pch_c_function ();
+
+ fprintf (rejfp, "@@ -%s +%s @@%s\n",
+ format_startcount (rangebuf0, oldfirst, pch_ptrn_lines ()),
+ format_startcount (rangebuf1, newfirst, pch_repl_lines ()),
+ c_function ? c_function : "");
+ print_unified (rejfp);
+
+ if (ferror (rejfp))
+ write_fatal ();
+}
+
/* We found where to apply it (we hope), so do it. */
static bool
Index: b/tests/unified-reject-files.shrun
===================================================================
--- /dev/null
+++ b/tests/unified-reject-files.shrun
@@ -0,0 +1,104 @@
+$ PATCH=$(pwd)/patch
+$ tmpdir=$(mktemp -d)
+$ trap "cd /; rm -rf $tmpdir" EXIT
+$ cd $tmpdir
+$ cat > f.orig
+< a() {
+< 2
+< 3
+<
+< 5
+< 6
+< }
+
+$ sed -e 's/5/5a/' f.orig > f
+$ diff -U0 -p \
++ -L "f.orig 2009-02-07 14:49:02.000000000 +0100" \
++ -L "f 2009-02-07 14:49:03.000000000 +0100" \
++ f.orig f > f.diff
+
+$ $PATCH -f -F0 -s --no-backup-if-mismatch f < f.diff
+> 1 out of 1 hunk FAILED -- saving rejects to file f.rej
+
+Note: patch cannot deal with nanosecond timestamps :-(
+
+$ cat f.rej
+> *************** a() {
+> *** 5 ****
+> - 5
+> --- 5 ----
+> + 5a
+
+$ diff -U0 -p -L f.orig -L f f.orig f > f.diff
+$ $PATCH -f -F0 -s --no-backup-if-mismatch --unified-reject-files f < f.diff
+> 1 out of 1 hunk FAILED -- saving rejects to file f.rej
+
+$ cat f.rej
+> @@ -5 +5 @@ a() {
+> -5
+> +5a
+
+$ $PATCH -f -F0 -s --no-backup-if-mismatch f < f.diff
+> 1 out of 1 hunk FAILED -- saving rejects to file f.rej
+
+$ cat f.rej
+> *************** a() {
+> *** 5 ****
+> - 5
+> --- 5 ----
+> + 5a
+
+$ $PATCH -f -F0 -s --no-backup-if-mismatch --unified-reject-files -R f.orig < f.diff
+> 1 out of 1 hunk FAILED -- saving rejects to file f.orig.rej
+
+$ cat f.orig.rej
+> @@ -5 +5 @@ a() {
+> -5a
+> +5
+
+$ diff -U2 -p -L f.orig -L f f.orig f > f.diff
+$ sed -e 's/5/5a/' -e 's/6/6x/' f.orig > f
+$ $PATCH -F0 -s --no-backup-if-mismatch --unified-reject-files f < f.diff
+> 1 out of 1 hunk FAILED -- saving rejects to file f.rej
+
+$ cat f.rej
+> @@ -3,5 +3,5 @@ a() {
+> 3
+>
+> -5
+> +5a
+> 6
+> }
+
+$ $PATCH -F0 -s --no-backup-if-mismatch f < f.diff
+> 1 out of 1 hunk FAILED -- saving rejects to file f.rej
+
+$ cat f.rej
+> *************** a() {
+> *** 3,7 ****
+> 3
+>
+> - 5
+> 6
+> }
+> --- 3,7 ----
+> 3
+>
+> + 5a
+> 6
+> }
+
+$ diff -Nu -p -L /dev/null -L f.orig /dev/null f.orig > f2.diff
+$ $PATCH -F0 -s --no-backup-if-mismatch --unified-reject-files f --set-utc < f2.diff
+> Patch attempted to create file f, which already exists.
+> 1 out of 1 hunk FAILED -- saving rejects to file f.rej
+
+$ cat f.rej
+> @@ -0,0 +1,7 @@
+> +a() {
+> +2
+> +3
+> +
+> +5
+> +6
+> +}