]> git.neil.brown.name Git - wiggle.git/blob - wiggle.h
Disable *all* backups when --no-backups used
[wiggle.git] / wiggle.h
1 /*
2  * wiggle - apply rejected patches
3  *
4  * Copyright (C) 2003-2013 Neil Brown <neilb@suse.de>
5  *
6  *
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.
11  *
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.
16  *
17  *    You should have received a copy of the GNU General Public License
18  *    along with this program.
19  *
20  *    Author: Neil Brown
21  *    Email: <neil@brown.name>
22  */
23
24 #define _GNU_SOURCE /* for asprintf */
25 #include        <stdio.h>
26 #include        <string.h>
27 #include        <memory.h>
28 #include        <getopt.h>
29 #include        <stdlib.h>
30
31 static inline void assert(int a)
32 {
33         if (!a)
34                 abort();
35 }
36
37 struct stream {
38         char *body;
39         int len;
40 };
41
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.
50  */
51 struct elmnt {
52         char *start;
53         int hash;
54         short len, plen, prefix;
55 };
56
57 static inline int match(struct elmnt *a, struct elmnt *b)
58 {
59         return
60                 a->hash == b->hash &&
61                 ((a->start[0] == 0 && b->start[0] == 0)
62                  ||
63                  (a->len == b->len &&
64                   strncmp(a->start, b->start, a->len) == 0));
65 }
66
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
70  * end a line.
71  */
72 static inline int ends_line(struct elmnt e)
73 {
74         if (e.len >= 20 && e.start[0] == 0)
75                 return 1;
76         return e.len &&  e.start[e.plen-1] == '\n';
77 }
78
79 struct csl {
80         int a, b;
81         int len;
82 };
83
84 struct file {
85         struct elmnt *list;
86         int elcnt;
87 };
88
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)
92  * or the same.
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
106  * a conflict.
107  */
108 struct merge {
109         enum mergetype {
110                 End, Unmatched, Unchanged, Extraneous,
111                 Changed, Conflict, AlreadyApplied,
112         } type, oldtype;
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 */
116         int in_conflict;
117         int lo, hi; /* region of a Changed or Unchanged that is not involved
118                     * in a conflict.
119                     * These are distances from start of the "before" section,
120                     * not indexes into any file.
121                     */
122
123 };
124
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.
131  */
132 struct plist {
133         char *file, *outfile;
134         unsigned int start, end;
135         int parent;
136         int next, prev, last;
137         int open;
138         int chunks, wiggles, conflicts;
139         int calced;
140         int is_merge;
141         char *before, *after;
142 };
143
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,
148                                          unsigned int end);
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*,
153                               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);
163
164 struct ci {
165         int conflicts, wiggles, ignored;
166         struct merge *merger;
167 };
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);
173
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);
180
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;
185
186 extern int vpatch(int argc, char *argv[], int patch, int strip,
187                   int reverse, int replace, char *outfile,
188                   int selftest,
189                   int ignore_blanks, int backup);
190
191 extern char *wiggle_Cmd;
192 extern char Version[];
193 extern char short_options[];
194 extern struct option long_options[];
195 enum other_options {
196         SELF_TEST = 300,
197         REPORT_WIGGLES,
198         NO_BACKUP,
199         NON_SPACE,
200         SHORTEST,
201 };
202 extern char Usage[];
203 extern char Help[];
204 extern char HelpExtract[];
205 extern char HelpDiff[];
206 extern char HelpMerge[];
207 extern char HelpBrowse[];
208
209 extern void cleanlist(struct file a, struct file b, struct csl *list);
210
211 enum {
212         ByLine = 0,
213         ByWord = 1,
214         ByMask = 3,
215         IgnoreBlanks = 8, /* 'or'ed in */
216         WholeWord = 16,
217 };