Index: patch-2.6.1/patch.man =================================================================== --- patch-2.6.1.orig/patch.man +++ patch-2.6.1/patch.man @@ -557,6 +557,15 @@ instead of the default .B \&.rej file. When \fIrejectfile\fP is \fB\-\fP, discard rejects. .TP +.BI \*=global\-reject\-file= rejectfile +Put all rejects into +.I rejectfile +instead of creating separate reject files for all files that have rejects. The +.I rejectfile +will contain headers that identify which file each reject refers to. Note that +the global reject file is created even if \-\-dry\-run is specified (while +non-global reject files will only be created without \-\-dry\-run). +.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: patch-2.6.1/src/patch.c =================================================================== --- patch-2.6.1.orig/src/patch.c +++ patch-2.6.1/src/patch.c @@ -52,6 +52,7 @@ static void reinitialize_almost_everythi static void remove_if_needed (char const *, int volatile *); static void usage (FILE *, int) __attribute__((noreturn)); +static void reject_header (const char *filename); static void abort_hunk (bool, bool); static void abort_hunk_context (bool, bool); static void abort_hunk_unified (bool, bool); @@ -83,6 +84,7 @@ static int Argc; static char * const *Argv; static FILE *rejfp; /* reject file pointer */ +static char *global_reject; static char const *patchname; static char *rejname; @@ -159,6 +161,10 @@ main (int argc, char **argv) /* Make sure we clean up in case of disaster. */ set_signals (false); + /* initialize global reject file */ + if (global_reject) + init_reject (); + if (inname && outfile) { apply_empty_patch = true; @@ -205,8 +211,9 @@ main (int argc, char **argv) init_output (TMPOUTNAME, exclusive, &outstate); } - /* initialize reject file */ - init_reject (); + /* initialize per-patch reject file */ + if (!global_reject) + init_reject (); /* find out where all the lines are */ if (!skip_rest_of_patch) @@ -295,6 +302,8 @@ main (int argc, char **argv) || ! where || ! apply_hunk (&outstate, where)))) { + if (!failed) + reject_header(outname); abort_hunk (! failed, reverse); failed++; if (verbosity == VERBOSE || @@ -331,7 +340,8 @@ main (int argc, char **argv) fclose (outstate.ofp); outstate.ofp = 0; } - fclose (rejfp); + if (!global_reject) + fclose (rejfp); continue; } @@ -430,13 +440,13 @@ main (int argc, char **argv) struct stat rejst; if ((failed && fstat (fileno (rejfp), &rejst) != 0) - || fclose (rejfp) != 0) + || (( !global_reject && fclose (rejfp) != 0))) write_fatal (); if (failed) { somefailed = true; say ("%d out of %d hunk%s %s", failed, hunk, "s" + (hunk == 1), skip_rest_of_patch ? "ignored" : "FAILED"); - if (outname && (! rejname || strcmp (rejname, "-") != 0)) { + if (!global_reject && outname && (! rejname || strcmp (rejname, "-") != 0)) { char *rej = rejname; if (!rejname) { /* FIXME: This should really be done differnely! */ @@ -485,6 +495,23 @@ main (int argc, char **argv) } set_signals (true); } + if (global_reject) + { + struct stat rejst; + + if ((somefailed && fstat (fileno (rejfp), &rejst) != 0) + || fclose (rejfp) != 0) + write_fatal (); + if (somefailed) + { + say (" -- saving rejects to file %s\n", quotearg (global_reject)); + /*if (! dry_run) + {*/ + move_file (TMPREJNAME, &TMPREJNAME_needs_removal, + &rejst, global_reject, 0644, false); + /*}*/ + } + } if (outstate.ofp && (ferror (outstate.ofp) || fclose (outstate.ofp) != 0)) write_fatal (); cleanup (); @@ -572,6 +599,7 @@ static struct option const longopts[] = {"posix", no_argument, NULL, CHAR_MAX + 7}, {"quoting-style", required_argument, NULL, CHAR_MAX + 8}, {"reject-format", required_argument, NULL, CHAR_MAX + 9}, + {"global-reject-file", required_argument, NULL, CHAR_MAX + 10}, {NULL, no_argument, NULL, 0} }; @@ -636,6 +664,7 @@ static char const *const option_help[] = "", " -d DIR --directory=DIR Change the working directory to DIR first.", " --reject-format=FORMAT Create 'context' or 'unified' rejects.", +" --global-reject-file=file Put all rejects into one file.", " --binary Read and write data in binary mode.", "", " -v --version Output version info.", @@ -852,6 +881,9 @@ get_some_switches (void) else usage (stderr, 2); break; + case CHAR_MAX + 10: + global_reject = savestr (optarg); + break; default: usage (stderr, 2); } @@ -1512,6 +1544,37 @@ similar (register char const *a, registe } } + static char * +format_timestamp (char timebuf[37], bool which) +{ + time_t ts = pch_timestamp(which); + if (ts != -1) + { + struct tm *tm = localtime(&ts); + strftime(timebuf, 37, "\t%Y-%m-%d %H:%M:%S.000000000 %z", tm); + } + else + timebuf[0] = 0; + return timebuf; +} + +/* Write a header in a reject file that combines multiple hunks. */ +static void +reject_header (const char *outname) +{ + char timebuf0[37], timebuf1[37]; + if (!global_reject) + return; + if (diff_type == UNI_DIFF) + fprintf(rejfp, "--- %s.orig%s\n+++ %s%s\n", + outname, format_timestamp(timebuf0, reverse), + outname, format_timestamp(timebuf1, !reverse)); + else + fprintf(rejfp, "*** %s.orig%s\n--- %s%s\n", + outname, format_timestamp(timebuf0, reverse), + outname, format_timestamp(timebuf1, !reverse)); +} + /* Make a temporary file. */ #if HAVE_MKTEMP && ! HAVE_DECL_MKTEMP && ! defined mktemp