From 8fae70d6eeb8190bc70769daf54072357dde1829 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 22 Aug 2013 17:54:42 +1000 Subject: [PATCH] Add --output option to redirect output. This is particularly useful for "git mergetool" Signed-off-by: NeilBrown --- ReadMe.c | 3 ++- parse.c | 5 ++--- vpatch.c | 28 +++++++++++++++++++--------- wiggle.1 | 15 ++++++++++++++- wiggle.c | 33 +++++++++++++++++++++++++++------ wiggle.h | 5 +++-- 6 files changed, 67 insertions(+), 22 deletions(-) diff --git a/ReadMe.c b/ReadMe.c index 1db6f83..e8025a9 100644 --- a/ReadMe.c +++ b/ReadMe.c @@ -38,7 +38,7 @@ char Version[] = "wiggle " VERSION " " VERS_DATE " GPL-2+ http://neil.brown.name/wiggle/\n"; -char short_options[] = "xdmwlrhiW123p::VRvqBb"; +char short_options[] = "xdmwlrho:iW123p::VRvqBb"; struct option long_options[] = { {"browse", 0, 0, 'B'}, @@ -55,6 +55,7 @@ struct option long_options[] = { {"verbose", 0, 0, 'v'}, {"quiet", 0, 0, 'q'}, {"strip", 1, 0, 'p'}, + {"output", 1, 0, 'o'}, {"no-ignore", 0, 0, 'i'}, {"show-wiggles",0, 0, 'W'}, {"ignore-blanks",0,0, 'b'}, diff --git a/parse.c b/parse.c index 008fd04..474152c 100644 --- a/parse.c +++ b/parse.c @@ -159,14 +159,13 @@ static struct plist *patch_add_file(struct plist *pl, int *np, char *file, } pl = npl; } + memset(&pl[n], 0, sizeof(pl[n])); pl[n].file = file; pl[n].start = start; pl[n].end = end; pl[n].last = pl[n].next = pl[n].prev = pl[n].parent = -1; - pl[n].chunks = pl[n].wiggles = 0; pl[n].conflicts = 100; + pl[n].conflicts = 100; pl[n].open = 1; - pl[n].calced = 0; - pl[n].is_merge = 0; *np = n+1; return pl; } diff --git a/vpatch.c b/vpatch.c index 52c9d3f..a4475f6 100644 --- a/vpatch.c +++ b/vpatch.c @@ -1813,7 +1813,8 @@ static int merge_window(struct plist *p, FILE *f, int reverse, int replace, ci.merger, 0, &p->wiggles); p->chunks = p->conflicts; save_merge(fm, fb, fa, ci.merger, - p->file, !p->is_merge); + p->outfile ?: p->file, + p->outfile ? 0 : !p->is_merge); } if (!just_diff) free(sm.body); @@ -2402,12 +2403,15 @@ static int merge_window(struct plist *p, FILE *f, int reverse, int replace, static int show_merge(char *origname, FILE *patch, int reverse, int is_merge, char *before, char *after, - int replace, int selftest, int ignore_blanks, + int replace, char *outfile, + int selftest, int ignore_blanks, int just_diff) { - struct plist p; + struct plist p = {0}; p.file = origname; + if (replace) + p.outfile = outfile; if (patch) { p.start = 0; fseek(patch, 0, SEEK_END); @@ -3068,7 +3072,8 @@ static void term_init(int doraw) } int vpatch(int argc, char *argv[], int patch, int strip, - int reverse, int replace, int selftest, int ignore_blanks) + int reverse, int replace, char *outfilename, + int selftest, int ignore_blanks) { /* NOTE argv[0] is first arg... * Behaviour depends on number of args and 'patch'. @@ -3150,16 +3155,19 @@ int vpatch(int argc, char *argv[], int patch, int strip, char *origname = strdup(argv[0]); origname[strlen(origname) - 4] = '\0'; show_merge(origname, f, reverse, 0, NULL, NULL, - replace, selftest, ignore_blanks, just_diff); + replace, outfilename, + selftest, ignore_blanks, just_diff); } else show_merge(argv[0], f, reverse, 1, NULL, NULL, - replace, selftest, ignore_blanks, just_diff); + replace, outfilename, + selftest, ignore_blanks, just_diff); break; case 2: /* an orig and a diff/.rej or two files */ if (just_diff) { show_merge(NULL, NULL, reverse, 0, argv[0], argv[1], - replace, selftest, ignore_blanks, just_diff); + replace, outfilename, + selftest, ignore_blanks, just_diff); break; } f = fopen(argv[1], "r"); @@ -3169,11 +3177,13 @@ int vpatch(int argc, char *argv[], int patch, int strip, exit(1); } show_merge(argv[0], f, reverse, 0, NULL, NULL, - replace, selftest, ignore_blanks, just_diff); + replace, outfilename, + selftest, ignore_blanks, just_diff); break; case 3: /* orig, before, after */ show_merge(argv[0], NULL, reverse, 0, argv[1], argv[2], - replace, selftest, ignore_blanks, just_diff); + replace, outfilename, + selftest, ignore_blanks, just_diff); break; } diff --git a/wiggle.1 b/wiggle.1 index ebfeada..4a4978c 100644 --- a/wiggle.1 +++ b/wiggle.1 @@ -221,6 +221,19 @@ mode, this instructs .I wiggle to always save the resulting merge when exiting. +.TP +.BR \-o ", " \-\-output= +Rather than writing the result to stdout or to replace the original +file, this requests that the output be written to the given file. +This is only meaningful with +.B \-\-merge +or +.B \-\-browse +when given a single merge to browse. + +This option overrides +.BR \-r . + .TP .BR -R ", " \-\-reverse When used with the @@ -636,7 +649,7 @@ in the user's home directory. tool = wiggle [mergetool "wiggle"] path = /usr/bin/wiggle - cmd = wiggle \-Br $LOCAL $BASE $REMOTE + cmd = wiggle \-B -o $MERGED $LOCAL $BASE $REMOTE .fi .RE diff --git a/wiggle.c b/wiggle.c index fe71d49..c1e9498 100644 --- a/wiggle.c +++ b/wiggle.c @@ -459,7 +459,8 @@ static int do_diff(int argc, char *argv[], int obj, int ispatch, } static int do_merge(int argc, char *argv[], int obj, int blanks, - int reverse, int replace, int ignore, int show_wiggles, + int reverse, int replace, char *outfilename, + int ignore, int show_wiggles, int quiet) { /* merge three files, A B C, so changed between B and C get made to A @@ -524,7 +525,14 @@ static int do_merge(int argc, char *argv[], int obj, int blanks, return 2; } } - if (replace) { + if (outfilename) { + outfile = fopen(outfilename, "w"); + if (!outfile) { + fprintf(stderr, "%s: could not create %s\n", + Cmd, outfilename); + return 2; + } + } else if (replace) { int fd; replacename = xmalloc(strlen(argv[0]) + 20); orignew = xmalloc(strlen(argv[0]) + 20); @@ -579,7 +587,9 @@ static int do_merge(int argc, char *argv[], int obj, int blanks, ci.ignored, ci.ignored == 1 ? "" : "s"); - if (replace) { + if (outfilename) + fclose(outfile); + else if (replace) { fclose(outfile); if (rename(argv[0], orignew) == 0 && rename(replacename, argv[0]) == 0) @@ -642,7 +652,7 @@ static int multi_merge(int argc, char *argv[], int obj, int blanks, pl[i].start, pl[i].end, filename); av[0] = pl[i].file; av[1] = name; - rv |= do_merge(2, av, obj, blanks, reverse, 1, ignore, + rv |= do_merge(2, av, obj, blanks, reverse, 1, NULL, ignore, show_wiggles, quiet); } return rv; @@ -665,6 +675,7 @@ int main(int argc, char *argv[]) int show_wiggles = 0; char *helpmsg; char *trace; + char *outfile = NULL; int selftest = 0; int ignore_blanks = 0; @@ -735,6 +746,10 @@ int main(int argc, char *argv[]) case 'r': replace = 1; continue; + case 'o': + outfile = optarg; + replace = 1; + continue; case 'R': reverse = 1; continue; @@ -787,7 +802,7 @@ int main(int argc, char *argv[]) if (mode == 'B') { vpatch(argc-optind, argv+optind, ispatch, - strip, reverse, replace, selftest, + strip, reverse, replace, outfile, selftest, ignore_blanks); /* should not return */ exit(1); @@ -801,9 +816,14 @@ int main(int argc, char *argv[]) } if (mode != 'm' && !obj) obj = 'w'; + if (ispatch && outfile) { + fprintf(stderr, "%s: --output incompatible with --patch\n", + Cmd); + exit(2); + } if (replace && mode != 'm') { fprintf(stderr, - "%s: --replace only allowed with --merge\n", Cmd); + "%s: --replace or --output only allowed with --merge\n", Cmd); exit(2); } if (mode == 'x' && !which) { @@ -847,6 +867,7 @@ int main(int argc, char *argv[]) exit_status = do_merge( argc-optind, argv+optind, obj, ignore_blanks, reverse, replace, + outfile, ignore, show_wiggles, quiet); break; } diff --git a/wiggle.h b/wiggle.h index 1795c5a..02fb568 100644 --- a/wiggle.h +++ b/wiggle.h @@ -131,7 +131,7 @@ struct merge { * as a directory-tree. */ struct plist { - char *file; + char *file, *outfile; unsigned int start, end; int parent; int next, prev, last; @@ -190,7 +190,8 @@ extern void *xmalloc(int len); extern int do_trace; extern int vpatch(int argc, char *argv[], int patch, int strip, - int reverse, int replace, int selftest, + int reverse, int replace, char *outfile, + int selftest, int ignore_blanks); extern char *Cmd; -- 2.39.5