char Version[] = "wiggle 0.8 2010-03-24 GPL-2+ http://neil.brown.name/wiggle/\n";
-char short_options1[] = "xdmwlrhiW123pVRvqB"; /* not mode B */
-char short_options2[] = "xdmwlrhiW123p::VRvqB"; /* mode B */
+char short_options[] = "xdmwlrhiW123p::VRvqB";
struct option long_options[] = {
{"browse", 0, 0, 'B'},
"\n"
"If --merge is given one file, it is treated as a merge (merge -A\n"
"output) and the three needed streams are extracted from it.\n"
+"If --merge is given one file and -p, it is a patch which identifies\n"
+"the files that should be patched.\n"
"If --merge is given two files, the second is treated as a patch\n"
"file and the first is the original file.\n"
"If --merge is given three files, they are each treated as whole files\n"
.BR -p ", " \-\-patch
Treat the last named file as a patch instead of a file (with \-\-diff)
or a merge (\-\-extract).
+In
+.I merge
+mode,
+.B -p
+requires there be exactly one file which is a patch and which can
+contain patches to multiple file. The patches are merged into each
+file. This usage requires the
+.B \-\-replace
+option as writing lots of merged files to standard-out is impractical.
+
+When used in
+.I merge
+mode,
+B -p
+can be followed by a numeric argument indicating how many patch name
+components to be stripped from files named in the patch file. If no
+numeric argument is given,
+.I wiggle
+will deduce an appropriate number based what files are visible.
.TP
.BR -r ", " \-\-replace
command line. Either 1, 2, or 3 files may be listed, and any one of
them may be a lone hyphen signifying standard-input.
-If one file is given, it is treated as a
+If one file is given and the
+.B \-p
+option is not present, the file is treated as a
.B merge
file, i.e. the output of "merge \-A" or "wiggle". Such a file
implicitly contains three streams and these are extracted and
and the two other texts
are extracted from that.
+If one file is given together with the
+.B \-p
+option, the file is treated as a patch file containing the names of
+the files that it patches. In this case multiple merge operations can
+happen and each takes one stream from a file named in the patch, and
+the other to from the patch itself. The
+.B \-\-replace
+option is required and the results are written back to the
+target files.
+
Finally if three files are listed, they are taken to contain the given
text and the two other texts, in order.
* Defaults are --merge --words
*
*/
-
+#define _GNU_SOURCE
#include "wiggle.h"
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
+#include <stdio.h>
#include <ctype.h>
char *Cmd = "wiggle";
return (ci.conflicts > 0);
}
+static int multi_merge(int argc, char *argv[], int obj,
+ int reverse, int ignore, int show_wiggles,
+ int replace, int strip,
+ int quiet)
+{
+ FILE *f;
+ char *filename;
+ struct plist *pl;
+ int num_patches;
+ int rv = 0;
+ int i;
+
+ if (!replace) {
+ fprintf(stderr,
+ "%s: -p in merge mode requires -r\n",
+ Cmd);
+ return 2;
+ }
+ if (argc != 1) {
+ fprintf(stderr,
+ "%s: -p in merge mode requires exactly one file\n",
+ Cmd);
+ return 2;
+ }
+ filename = argv[0];
+ f = fopen(filename, "r");
+ if (!f) {
+ fprintf(stderr, "%s: cannot open %s\n",
+ Cmd, filename);
+ return 2;
+ }
+ pl = parse_patch(f, NULL, &num_patches);
+ fclose(f);
+ if (set_prefix(pl, num_patches, strip) == 0) {
+ fprintf(stderr, "%s: aborting\n", Cmd);
+ return 2;
+ }
+ for (i = 0; i < num_patches; i++) {
+ char *name;
+ char *av[2];
+ asprintf(&name, "_wiggle_:%d:%d:%s",
+ pl[i].start, pl[i].end, filename);
+ av[0] = pl[i].file;
+ av[1] = name;
+ rv |= do_merge(2, av, obj, reverse, 1, ignore,
+ show_wiggles, quiet);
+ }
+ return rv;
+}
+
int main(int argc, char *argv[])
{
int opt;
do_trace = 1;
while ((opt = getopt_long(argc, argv,
- short_options(mode), long_options,
+ short_options, long_options,
&option_index)) != -1)
switch (opt) {
case 'h':
Cmd);
exit(2);
}
- if (ispatch && (mode != 'x' && mode != 'd')) {
- fprintf(stderr,
- "%s: --patch only allowed with --extract or --diff\n", Cmd);
- exit(2);
- }
+
if (ispatch && which == '3') {
fprintf(stderr,
"%s: cannot extract -3 from a patch.\n", Cmd);
exit_status = do_diff(argc-optind, argv+optind, obj, ispatch, which, reverse);
break;
case 'm':
- exit_status = do_merge(argc-optind, argv+optind, obj, reverse, replace,
- ignore, show_wiggles, quiet);
+ if (ispatch)
+ exit_status = multi_merge(argc-optind,
+ argv+optind, obj,
+ reverse, ignore,
+ show_wiggles,
+ replace, strip,
+ quiet);
+ else
+ exit_status = do_merge(argc-optind, argv+optind, obj, reverse, replace,
+ ignore, show_wiggles, quiet);
break;
}
exit(exit_status);