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: <neilb@suse.de>
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
*sort_patches(struct plist
*pl
, int *np
);
145 extern void plist_free(struct plist
*pl
, int num
);
146 extern struct plist
*parse_patch(FILE *f
, FILE *of
, int *np
);
147 extern struct stream
load_segment(FILE *f
, unsigned int start
,
149 extern int set_prefix(struct plist
*pl
, int n
, int strip
);
150 extern struct stream
load_file(char *name
);
151 extern int split_patch(struct stream
, struct stream
*, struct stream
*);
152 extern int split_merge(struct stream
, struct stream
*, struct stream
*,
154 extern struct file
split_stream(struct stream s
, int type
);
155 extern struct csl
*pdiff(struct file a
, struct file b
, int chunks
);
156 extern struct csl
*diff(struct file a
, struct file b
, int shortest
);
157 extern struct csl
*diff_patch(struct file a
, struct file b
, int shortest
);
158 extern struct csl
*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
*csl_join(struct csl
*c1
, struct csl
*c2
);
165 int conflicts
, wiggles
, ignored
;
166 struct merge
*merger
;
168 extern int 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 printword(FILE *f
, struct elmnt e
);
173 extern int save_merge(struct file a
, struct file b
, struct file c
,
174 struct merge
*merger
, char *file
, int backup
);
175 extern int save_tmp_merge(struct file a
, struct file b
, struct file c
,
176 struct merge
*merger
, char **filep
,
177 struct merge
*mpos
, int streampos
, int offsetpos
);
179 extern int isolate_conflicts(struct file af
, struct file bf
, struct file cf
,
180 struct csl
*csl1
, struct csl
*csl2
, int words
,
181 struct merge
*m
, int show_wiggles
, int *wigglesp
);
182 extern struct ci
make_merger(struct file a
, struct file b
, struct file c
,
183 struct csl
*c1
, struct csl
*c2
, int words
,
184 int ignore_already
, int show_wiggles
);
186 extern void die(char *reason
);
187 extern void check_dir(char *name
, int fd
);
188 extern void *xmalloc(int len
);
191 extern int vpatch(int argc
, char *argv
[], int patch
, int strip
,
192 int reverse
, int replace
, char *outfile
,
194 int ignore_blanks
, int backup
);
197 extern char Version
[];
198 extern char short_options
[];
199 extern struct option long_options
[];
209 extern char HelpExtract
[];
210 extern char HelpDiff
[];
211 extern char HelpMerge
[];
212 extern char HelpBrowse
[];
214 extern void cleanlist(struct file a
, struct file b
, struct csl
*list
);
220 IgnoreBlanks
= 8, /* 'or'ed in */