Index: patch-2.5.9/patch.man =================================================================== --- patch-2.5.9.orig/patch.man +++ patch-2.5.9/patch.man @@ -520,6 +520,15 @@ file. \fB\*=reject\-unified\fP Produce unified reject files. The default is to produce context type reject files. .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.5.9/patch.c =================================================================== --- patch-2.5.9.orig/patch.c +++ patch-2.5.9/patch.c @@ -67,6 +67,7 @@ static bool similar (char const *, size_ static bool spew_output (struct outstate *); static char const *make_temp (char); static int numeric_string (char const *, bool, char const *); +static void reject_header (const char *filename); static void abort_hunk (void); static void cleanup (void); static void get_some_switches (void); @@ -98,6 +99,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; @@ -172,6 +174,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 (); + for ( open_patch_file (patchname); there_is_another_patch(); @@ -208,8 +214,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) @@ -278,6 +285,8 @@ 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) @@ -292,6 +301,8 @@ 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) @@ -299,6 +310,8 @@ main (int argc, char **argv) format_linenum (numbuf, newwhere)); } else if (! apply_hunk (&outstate, where)) { + if (!failed) + reject_header(outname); abort_hunk (); failed++; if (verbosity != SILENT) @@ -332,7 +345,8 @@ main (int argc, char **argv) fclose (outstate.ofp); outstate.ofp = 0; } - fclose (rejfp); + if (!global_reject) + fclose (rejfp); continue; } @@ -412,13 +426,13 @@ main (int argc, char **argv) } } if (diff_type != ED_DIFF) { - if (fclose (rejfp) != 0) + if (!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) { + if (!global_reject && outname) { char *rej = rejname; if (!rejname) { rej = xmalloc (strlen (outname) + 5); @@ -445,6 +459,20 @@ main (int argc, char **argv) } set_signals (true); } + if (global_reject) + { + if (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, + global_reject, 0644, false); + /*}*/ + } + } if (outstate.ofp && (ferror (outstate.ofp) || fclose (outstate.ofp) != 0)) write_fatal (); cleanup (); @@ -523,6 +551,7 @@ static struct option const longopts[] = {"posix", no_argument, NULL, CHAR_MAX + 7}, {"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}, {NULL, no_argument, NULL, 0} }; @@ -582,6 +611,7 @@ static char const *const option_help[] = " --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.", +" --global-reject-file=file Put all rejects into one file.", "", " -d DIR --directory=DIR Change the working directory to DIR first.", #if HAVE_SETMODE_DOS @@ -784,6 +814,9 @@ get_some_switches (void) case CHAR_MAX + 9: unified_reject_files = true; break; + case CHAR_MAX + 10: + global_reject = savestr (optarg); + break; default: usage (stderr, 2); } @@ -933,6 +966,37 @@ locate_hunk (LINENUM fuzz) } 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)); +} + +static char * format_linerange (char rangebuf[LINENUM_LENGTH_BOUND*2 + 2], LINENUM first, LINENUM lines) {