]> git.neil.brown.name Git - wiggle.git/commitdiff
More options for giving patches to --browse
authorNeil Brown <neilb@suse.de>
Wed, 12 May 2010 06:31:57 +0000 (16:31 +1000)
committerNeil Brown <neilb@suse.de>
Wed, 12 May 2010 06:31:57 +0000 (16:31 +1000)
As well as a 'patch' file (which identifies the target file by
names in the patch file), you can now also browse given a
target file plus a diff,
just the diff if it ends '.rej',
a target file plus old and new versions of the file.

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

index 5e369679e54b29abda4836c8c209ec48a2f65854..4d3847fb02294b0dee9c314e295f5c4f5c663d0c 100644 (file)
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -32,7 +32,7 @@
 char Version[] = "wiggle - v0.8 - 24 March 2010\n";
 
 char short_options1[]="xdmwlrhi123pVRvqB"; /* not mode B */
-char short_options2[]="xdmwlrhi123p:VRvqB"; /* mode B */
+char short_options2[]="xdmwlrhi123p::VRvqB"; /* mode B */
 
 
 struct option long_options[] = {
@@ -148,10 +148,19 @@ char HelpMerge[] = "\n"
 "\n";
 
 char HelpBrowse[] = "\n"
-"wiggle --browse [-R] [--strip=n] multi-file-patch\n"
+"wiggle --browse [-R] [--strip=n] [-p] [files]\n"
 "\n"
 "The 'browse' function provides an interactive mode for browsing a\n"
-"set of patches.  It allows the application of a patch to each file \n"
-"to be inspected and allows limited editing to correct mis-application\n"
-"of patches where wiggling was required, and where conflicts occurred.\n"
+"patch or set of patches.  It allows the application of a patch to each\n"
+"file to be inspected and will eventually allow limited editing to correct\n"
+"mis-application of patches where wiggling was required, and where conflicts\n"
+"occurred.\n"
+"If no files are given, a patch file is read from stdin\n"
+"If one file is given with -p, it is treated as a patch file\n"
+"If one file is given with a name ending .rej, it is treated as a reject for\n"
+"     a file with matching basename\n"
+"Otherwise a single file is assumed to be a merge output with conflicts.\n"
+"If two files are given, the second is a patch to apply to the first.\n"
+"If three files are given then the difference between 2nd and 3rd is applied\n"
+"     to the first\n"
 "\n";
index 96121efd3a8e2d82bc87aa83a7575a767f88821a..4ad39c02be8ef26d352bf76455dd4751b0dbcdef 100644 (file)
--- a/vpatch.c
+++ b/vpatch.c
@@ -47,6 +47,8 @@
 #include <signal.h>
 #include <fcntl.h>
 
+static void term_init();
+
 #define assert(x) do { if (!(x)) abort(); } while (0)
 
 
@@ -65,6 +67,8 @@ struct plist {
        int open;
        int chunks, wiggles, conflicts;
        int calced;
+       int is_merge;
+       char *before, *after;
 };
 static struct stream load_segment(FILE *f,
                                  unsigned int start, unsigned int end);
@@ -1050,22 +1054,43 @@ void merge_window(struct plist *p, FILE *f, int reverse)
                int row, col, searchlen;
        } *anchor = NULL;
 
-       sp = load_segment(f, p->start, p->end);
-       if (reverse)
-               ch = split_patch(sp, &sa, &sb);
-       else
-               ch = split_patch(sp, &sb, &sa);
+       if (f == NULL) {
+               /* three separate files */
+               sm = load_file(p->file);
+               sb = load_file(p->before);
+               sa = load_file(p->after);
+               ch = 0;
+       } else {
+               sp = load_segment(f, p->start, p->end);
+               if (p->is_merge) {
+                       if (reverse)
+                               split_merge(sp, &sm, &sa, &sb);
+                       else
+                               split_merge(sp, &sm, &sb, &sa);
+                       ch = 0;
+               } else {
+                       if (reverse)
+                               ch = split_patch(sp, &sa, &sb);
+                       else
+                               ch = split_patch(sp, &sb, &sa);
 
-       sm = load_file(p->file);
+                       sm = load_file(p->file);
+               }
+       }
        fm = split_stream(sm, ByWord, 0);
        fb = split_stream(sb, ByWord, 0);
        fa = split_stream(sa, ByWord, 0);
 
-       csl1 = pdiff(fm, fb, ch);
+       if (ch)
+               csl1 = pdiff(fm, fb, ch);
+       else
+               csl1 = diff(fm, fb);
        csl2 = diff(fb, fa);
 
        ci = make_merger(fm, fb, fa, csl1, csl2, 0, 1);
 
+       term_init();
+
        row = 1;
        pos.p.m = 0; /* merge node */
        pos.p.s = 0; /* stream number */
@@ -1501,7 +1526,7 @@ void merge_window(struct plist *p, FILE *f, int reverse)
 
                case '|':
                        mode = ORIG|RESULT|BEFORE|AFTER; modename = "sidebyside"; modehelp = sidebyside_help;
-                       refresh = 1;
+                       refresh = 2;
                        break;
 
                case 'H':
@@ -1560,6 +1585,26 @@ void merge_window(struct plist *p, FILE *f, int reverse)
        }
 }
 
+void show_merge(char *origname, FILE *patch, int reverse, int is_merge,
+               char *before, char *after)
+{
+       struct plist p;
+
+       p.file = origname;
+       if (patch) {
+               p.start = 0;
+               fseek(patch, 0, SEEK_END);
+               p.end = ftell(patch);
+               fseek(patch, 0, SEEK_SET);
+       }
+       p.calced = 0;
+       p.is_merge = is_merge;
+       p.before = before;
+       p.after = after;
+
+       merge_window(&p, patch, reverse);
+}
+
 struct plist *patch_add_file(struct plist *pl, int *np, char *file,
               unsigned int start, unsigned int end)
 {
@@ -1598,6 +1643,7 @@ struct plist *patch_add_file(struct plist *pl, int *np, char *file,
        pl[n].chunks = pl[n].wiggles = 0; pl[n].conflicts = 100;
        pl[n].open = 1;
        pl[n].calced = 0;
+       pl[n].is_merge = 0;
        *np = n+1;
        return pl;
 }
@@ -1611,6 +1657,7 @@ struct plist *parse_patch(FILE *f, FILE *of, int *np)
         */
        struct plist *plist = NULL;
 
+       *np = 0;
        while (!feof(f)) {
                /* first, find the start of a patch: "\n+++ "
                 * grab the file name and scan to the end of a line
@@ -1849,12 +1896,20 @@ void calc_one(struct plist *pl, FILE *f, int reverse)
 {
        struct stream s1, s2;
        struct stream s = load_segment(f, pl->start, pl->end);
-       struct stream sf = load_file(pl->file);
-       if (reverse)
-               pl->chunks = split_patch(s, &s2, &s1);
-       else
-               pl->chunks = split_patch(s, &s1, &s2);
-
+       struct stream sf;
+       if (pl->is_merge) {
+               if (reverse)
+                       split_merge(s, &sf, &s2, &s1);
+               else
+                       split_merge(s, &sf, &s1, &s2);
+               pl->chunks = 0;
+       } else {
+               sf = load_file(pl->file);
+               if (reverse)
+                       pl->chunks = split_patch(s, &s2, &s1);
+               else
+                       pl->chunks = split_patch(s, &s1, &s2);
+       }
        if (sf.body == NULL) {
                pl->wiggles = pl->conflicts = -1;
        } else {
@@ -1864,7 +1919,10 @@ void calc_one(struct plist *pl, FILE *f, int reverse)
                ff = split_stream(sf, ByWord, 0);
                fp1 = split_stream(s1, ByWord, 0);
                fp2 = split_stream(s2, ByWord, 0);
-               csl1 = pdiff(ff, fp1, pl->chunks);
+               if (pl->chunks)
+                       csl1 = pdiff(ff, fp1, pl->chunks);
+               else
+                       csl1 = diff(ff, fp1);
                csl2 = diff(fp1,fp2);
                ci = make_merger(ff, fp1, fp2, csl1, csl2, 0, 1);
                pl->wiggles = ci.wiggles;
@@ -1879,6 +1937,7 @@ void calc_one(struct plist *pl, FILE *f, int reverse)
        free(s1.body);
        free(s2.body);
        free(s.body);
+       free(sf.body);
        pl->calced = 1;
 }
 
@@ -2049,6 +2108,9 @@ void main_window(struct plist *pl, int n, FILE *f, int reverse)
        int c=0;
        int mode = 0; /* 0=all, 1= only wiggled, 2=only conflicted */
 
+       term_init();
+       pl = sort_patches(pl, &n);
+
        while(1) {
                if (refresh == 2) {
                        clear(); (void)attrset(0);
@@ -2166,46 +2228,14 @@ void catch(int sig)
        exit(2);
 }
 
-int vpatch(int argc, char *argv[], int strip, int reverse, int replace)
+static void term_init()
 {
-       /* NOTE argv[0] is first arg... */
-       int n = 0;
-       FILE *f = NULL;
-       FILE *in = stdin;
-       struct plist *pl;
-
-       if (argc >=1) {
-               in = fopen(argv[0], "r");
-               if (!in) {
-                       printf("No %s\n", argv[0]);
-                       exit(1);
-               }
-       } else {
-               in = stdin;
-       }
-       if (lseek(fileno(in),0L, 1) == -1) {
-               f = tmpfile();
-               if (!f) {
-                       fprintf(stderr, "Cannot create a temp file\n");
-                       exit(1);
-               }
-       }
 
-       pl = parse_patch(in, f, &n);
-
-       if (set_prefix(pl, n, strip) == 0) {
-               fprintf(stderr, "%s: aborting\n", Cmd);
-               exit(2);
-       }
-       pl = sort_patches(pl, &n);
+       static int init_done = 0;
 
-       if (f) {
-               if (fileno(in) == 0) {
-                       dup2(2,0);
-               } else
-                       fclose(in);
-               in = f;
-       }
+       if (init_done)
+               return;
+       init_done = 1;
 
        signal(SIGINT, catch);
        signal(SIGQUIT, catch);
@@ -2242,10 +2272,89 @@ int vpatch(int argc, char *argv[], int strip, int reverse, int replace)
        }
        nonl(); intrflush(stdscr, FALSE); keypad(stdscr, TRUE);
        mousemask(ALL_MOUSE_EVENTS, NULL);
+}
 
-       main_window(pl, n, in, reverse);
+int vpatch(int argc, char *argv[], int patch, int strip,
+          int reverse, int replace)
+{
+       /* NOTE argv[0] is first arg...
+        * Behaviour depends on number of args:
+        * 0: A multi-file patch is read from stdin
+        * 1: if 'patch', parse it as a multi-file patch and allow
+        *    the files to be browsed.
+        *    if filename ends '.rej', then treat it as a patch again
+        *    a file with the same basename
+        *    Else treat the file as a merge (with conflicts) and view it.
+        * 2: First file is original, second is patch
+        * 3: Files are: original previous new.  The diff between 'previous' and
+        *    'new' needs to be applied to 'original'.
+        *
+        * If a multi-file patch is being read, 'strip' tells how many
+        * path components to stripe.  If it is -1, we guess based on
+        * existing files.
+        * If 'reverse' is given, when we invert any patch or diff
+        * If 'replace' then we save the resulting merge.
+        */
+       FILE *in;
+       FILE *f;
+       struct plist *pl;
+       int num_patches;
+
+       switch (argc) {
+       default:
+               fprintf(stderr, "wiggle: too many file names given.\n");
+               exit(1);
+
+       case 0: /* stdin is a patch */
+               if (lseek(fileno(stdin), 0L, 1) == -1) {
+                       /* cannot seek, so need to copy to a temp file */
+                       f = tmpfile();
+                       if (!f) {
+                               fprintf(stderr, "wiggle: Cannot create temp file\n");
+                               exit(1);
+                       }
+                       pl = parse_patch(stdin, f, &num_patches);
+                       in = f;
+               } else {
+                       pl = parse_patch(stdin, NULL, &num_patches);
+                       in = fdopen(dup(0), "r");
+               }
+               /* use stderr for keyboard input */
+               dup2(2,0);
+               main_window(pl, num_patches, in, reverse);
+               break;
+
+       case 1: /* a patch, a .rej, or a merge file */
+               f = fopen(argv[0], "r");
+               if (!f) {
+                       fprintf(stderr, "wiggle: cannot open %s\n", argv[0]);
+                       exit(1);
+               }
+               if (patch) {
+                       pl = parse_patch(f, NULL, &num_patches);
+                       main_window(pl, num_patches, f, reverse);
+               } else if (strlen(argv[0]) > 4 &&
+                        strcmp(argv[0]+strlen(argv[0])-4, ".rej") == 0) {
+                       char *origname = strdup(argv[0]);
+                       origname[strlen(origname) - 4] = '\0';
+                       show_merge(origname, f, reverse, 0, NULL, NULL);
+               } else
+                       show_merge(argv[0], f, reverse, 1, NULL, NULL);
+
+               break;
+       case 2: /* an orig and a diff/.ref */
+               f = fopen(argv[1], "r");
+               if (!f) {
+                       fprintf(stderr, "wiggle: cannot open %s\n", argv[0]);
+                       exit(1);
+               }
+               show_merge(argv[0], f, reverse, 0, NULL, NULL);
+               break;
+       case 3: /* orig, before, after */
+               show_merge(argv[0], NULL, reverse, 1, argv[1], argv[2]);
+               break;
+       }
 
        nocbreak();nl();endwin();
-       return 0;
        exit(0);
 }
index dc07ffb76e37e83f29d79ddef2094b9845e8a45a..8615c1d1d2c59cc113f9175419ff4359854f49f6 100644 (file)
--- a/wiggle.c
+++ b/wiggle.c
@@ -237,14 +237,10 @@ int main(int argc, char *argv[])
                        fprintf(stderr, "wiggle: can only select one of -1, -2, -3\n");
                        exit(2);
 
-               case 'p':
-                       if (mode == 'B')
-                               strip = atol(optarg?optarg:"0");
-                       else if (optarg) {
-                               fprintf(stderr, "wiggle: SORRY, PARSE ERROR\n");
-                               exit(2);
-                       } else
-                               ispatch = 1;
+               case 'p': /* 'patch' or 'strip' */
+                       if (optarg)
+                               strip = atol(optarg);
+                       ispatch = 1;
                        continue;
 
                case 'v': verbose++; continue;
@@ -254,7 +250,7 @@ int main(int argc, char *argv[])
                mode = 'm';
 
        if (mode == 'B') {
-               vpatch(argc-optind, argv+optind, strip, reverse, replace);
+               vpatch(argc-optind, argv+optind, ispatch, strip, reverse, replace);
                /* should not return */
                exit(1);
        }
index 6494166aad685f17915614950a590a7894e6c0d9..7ce0a754488d05594aa51d3a55bbd37261bf330e 100644 (file)
--- a/wiggle.h
+++ b/wiggle.h
@@ -126,7 +126,8 @@ extern struct ci make_merger(struct file a, struct file b, struct file c,
 
 extern void die(void);
 
-extern int vpatch(int argc, char *argv[], int strip, int reverse, int replace);
+extern int vpatch(int argc, char *argv[], int patch, int strip,
+                 int reverse, int replace);
 
 extern char *Cmd;
 extern char Version[];