]> git.neil.brown.name Git - wiggle.git/commitdiff
Merge: allow merging a multi-patch patchfile.
authorNeil Brown <neilb@suse.de>
Mon, 14 May 2012 01:01:11 +0000 (11:01 +1000)
committerNeil Brown <neilb@suse.de>
Mon, 14 May 2012 01:01:11 +0000 (11:01 +1000)
If
  wiggle -p -r patchfilename
is given, multiple patches - each identifying the target
file - are read from patchfilename and each is applied to the
relevant file.  Note that '-r' is required with this usage of
-p.

Signed-off-by: NeilBrown <neilb@suse.de>
ReadMe.c
wiggle.1
wiggle.c
wiggle.h

index 18440056a53ec2902af830089ea0be3fb2028c0e..a2bce3460b82d4397410e859daa396cd048fb854 100644 (file)
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -31,8 +31,7 @@
 
 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'},
@@ -142,6 +141,8 @@ char HelpMerge[] = "\n"
 "\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"
index 0123600c043cbe4b01f000d64bc24a125abc3aed..a5321a209cd929ecddc862ff48b1d20cbc0394ef 100644 (file)
--- a/wiggle.1
+++ b/wiggle.1
@@ -144,6 +144,25 @@ Request that all operations and display be line based.
 .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
@@ -233,7 +252,9 @@ extracts the three texts that it needs from files listed on the
 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
@@ -246,6 +267,16 @@ or "diff\ \-c", or a ".rej" file from
 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.
 
index 842c47911ad8ee9eb4600ef62ed5f89a0519d3d4..a3cba3e534eed1186922a096d6184ec9f31f45a3 100644 (file)
--- a/wiggle.c
+++ b/wiggle.c
  * 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";
@@ -581,6 +582,56 @@ static int do_merge(int argc, char *argv[], int obj,
        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;
@@ -604,7 +655,7 @@ int main(int argc, char *argv[])
                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':
@@ -731,11 +782,7 @@ int main(int argc, char *argv[])
                        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);
@@ -750,8 +797,16 @@ int main(int argc, char *argv[])
                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);
index 8e55489f6e1712c2136ae47a6cc7db7e67f9c80f..91b4110d3835ca1f0a80ab241e798cc8c014e502 100644 (file)
--- a/wiggle.h
+++ b/wiggle.h
@@ -184,11 +184,7 @@ extern int vpatch(int argc, char *argv[], int patch, int strip,
 
 extern char *Cmd;
 extern char Version[];
-extern char short_options1[], short_options2[];
-static inline char *short_options(char mode)
-{
-       return mode == 'B' ? short_options2 : short_options1;
-}
+extern char short_options[];
 extern struct option long_options[];
 extern char Usage[];
 extern char Help[];