2 * wiggle - apply rejected patches
4 * Copyright (C) 2003-2013 Neil Brown <neilb@suse.de>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program.
21 * Email: <neil@brown.name>
24 #define _GNU_SOURCE /* for asprintf */
31 static inline void assert(int a)
42 /* an 'elmnt' is a word or a line from the file.
43 * 'start' points into a 'body' in a stream.
44 * When a stream is made of 'diff' hunks, there is a special
45 * elmnt at the start of each hunk which starts with '\0' and
46 * records the line offsets of the hunk. These are 20+ bytes long.
47 * "\0\d{5} \d{5} \d{5}{SP funcname}?\n\0"
48 * The 3 numbers are: chunk number, starting line, number of lines.
49 * An element with len==0 marks EOF.
54 short len, plen, prefix;
57 static inline int match(struct elmnt *a, struct elmnt *b)
61 ((a->start[0] == 0 && b->start[0] == 0)
64 strncmp(a->start, b->start, a->len) == 0));
67 /* end-of-line is important for narrowing conflicts.
68 * In line mode, every element is a line and 'ends a line'
69 * In word mode, the newline element and the diff-hunk element
72 static inline int ends_line(struct elmnt e)
74 if (e.len >= 20 && e.start[0] == 0)
76 return e.len && e.start[e.plen-1] == '\n';
89 /* The result of a merger is a series of text sections.
90 * Each section may occur in one or more of the three stream,
91 * and may be different in different stream (e.g. for changed text)
93 * When a conflict occurs we need to treat some surrounding
94 * sections as being involved in that conflict. For
95 * line-based merging, all surrounding sections until an Unchanged
96 * section are part of the conflict - the Unchanged isn't.
97 * For word-based merging, we need to find Unchanged sections
98 * that include a newline. Further, text within the unchanged
99 * section upto the newline (in whichever direction) is treated
100 * as part of the whole conflict.
101 * Actually... it is possibly for a 'Changed' section to bound
102 * a conflict as it indicates a successful match of A and B.
103 * For line-wise merges, any Changed or Unchanged section bounds a conflict
104 * For word-wise merges, any Changed or Unchanged section that matches
105 * a newline, or immediately follows a newline (in all files) can bound
110 End, Unmatched, Unchanged, Extraneous,
111 Changed, Conflict, AlreadyApplied,
113 int a, b, c; /* start of ranges */
114 int al, bl, cl; /* length of ranges */
115 int c1, c2; /* this or next common-sequence */
117 int lo, hi; /* region of a Changed or Unchanged that is not involved
119 * These are distances from start of the "before" section,
120 * not indexes into any file.
125 /* plist stores a list of patched files in an array
126 * Each entry identifies a file, the range of the
127 * original patch which applies to this file, some
128 * statistics concerning how many conflicts etc, and
129 * some linkage information so the list can be viewed
130 * as a directory-tree.
133 char *file, *outfile;
134 unsigned int start, end;
136 int next, prev, last;
138 int chunks, wiggles, conflicts;
141 char *before, *after;
144 extern struct plist *wiggle_sort_patches(struct plist *pl, int *np);
145 extern void wiggle_plist_free(struct plist *pl, int num);
146 extern struct plist *wiggle_parse_patch(FILE *f, FILE *of, int *np);
147 extern struct stream wiggle_load_segment(FILE *f, unsigned int start,
149 extern int wiggle_set_prefix(struct plist *pl, int n, int strip);
150 extern struct stream wiggle_load_file(char *name);
151 extern int wiggle_split_patch(struct stream, struct stream*, struct stream*);
152 extern int wiggle_split_merge(struct stream, struct stream*, struct stream*,
154 extern struct file wiggle_split_stream(struct stream s, int type);
155 extern struct csl *wiggle_pdiff(struct file a, struct file b, int chunks);
156 extern struct csl *wiggle_diff(struct file a, struct file b, int shortest);
157 extern struct csl *wiggle_diff_patch(struct file a, struct file b, int shortest);
158 extern struct csl *wiggle_diff_partial(struct file a, struct file b,
159 int alo, int ahi, int blo, int bhi);
160 extern struct csl *worddiff(struct stream f1, struct stream f2,
161 struct file *fl1p, struct file *fl2p);
162 extern struct csl *wiggle_csl_join(struct csl *c1, struct csl *c2);
165 int conflicts, wiggles, ignored;
166 struct merge *merger;
168 extern int wiggle_print_merge(FILE *out,
169 struct file *a, struct file *b, struct file *c,
170 int words, struct merge *merger,
171 struct merge *mpos, int streampos, int offsetpos);
172 extern void wiggle_printword(FILE *f, struct elmnt e);
174 extern int wiggle_isolate_conflicts(struct file af, struct file bf, struct file cf,
175 struct csl *csl1, struct csl *csl2, int words,
176 struct merge *m, int show_wiggles, int *wigglesp);
177 extern struct ci wiggle_make_merger(struct file a, struct file b, struct file c,
178 struct csl *c1, struct csl *c2, int words,
179 int ignore_already, int show_wiggles);
181 extern void wiggle_die(char *reason);
182 extern void wiggle_check_dir(char *name, int fd);
183 extern void *wiggle_xmalloc(int len);
184 extern int wiggle_do_trace;
186 extern int vpatch(int argc, char *argv[], int patch, int strip,
187 int reverse, int replace, char *outfile,
189 int ignore_blanks, int backup);
191 extern char *wiggle_Cmd;
192 extern char Version[];
193 extern char short_options[];
194 extern struct option long_options[];
204 extern char HelpExtract[];
205 extern char HelpDiff[];
206 extern char HelpMerge[];
207 extern char HelpBrowse[];
209 extern void cleanlist(struct file a, struct file b, struct csl *list);
215 IgnoreBlanks = 8, /* 'or'ed in */