Added an exclude-list convenience function.
[rsync/rsync-patches.git] / perdir-exclude-from.diff
CommitLineData
94f29894 1--- exclude.c 14 Apr 2004 23:33:40 -0000 1.67
616f340b
WD
2+++ exclude.c 15 Apr 2004 21:02:10 -0000
3@@ -27,8 +27,10 @@
94f29894
WD
4 #include "rsync.h"
5
6 extern int verbose;
7+extern int protocol_version;
8
9 struct exclude_list_struct exclude_list;
10+struct exclude_list_struct subdir_exclude_list;
11 struct exclude_list_struct local_exclude_list;
12 struct exclude_list_struct server_exclude_list;
94f29894 13 char *exclude_path_prefix = NULL;
616f340b
WD
14@@ -80,6 +82,8 @@ static void make_exclude(struct exclude_
15 for (cp = ret->pattern; (cp = strchr(cp, '/')) != NULL; cp++)
16 ret->slash_cnt++;
94f29894 17
616f340b
WD
18+ ret->next = listp->extra;
19+
20 if (!listp->tail)
21 listp->head = listp->tail = ret;
22 else {
23@@ -101,6 +105,13 @@ void free_exclude_list(struct exclude_li
24 if (verbose > 2)
94f29894
WD
25 rprintf(FINFO, "[%s] clearing exclude list\n", who_am_i());
26
616f340b
WD
27+ if (listp->extra) {
28+ if (listp->tail)
29+ listp->tail->next = NULL;
30+ else
31+ listp->head = NULL;
32+ }
33+
94f29894 34 for (ent = listp->head; ent; ent = next) {
94f29894
WD
35 next = ent->next;
36 free_exclude(ent);
4eddff16
WD
37@@ -109,6 +120,13 @@ void free_exclude_list(struct exclude_li
38 memset(listp, 0, sizeof listp[0]);
39 }
40
41+void clear_exclude_list(struct exclude_list_struct *listp,
42+ struct exclude_struct *extra)
43+{
44+ listp->head = listp->extra = extra;
45+ listp->tail = NULL;
46+}
47+
48 static int check_one_exclude(char *name, struct exclude_struct *ex,
49 int name_is_dir)
50 {
51@@ -209,21 +227,24 @@ static void report_exclude_result(char c
94f29894
WD
52
53 /*
54 * Return true if file NAME is defined to be excluded by the specified
55- * exclude list.
56+ * exclude list. Returns -1 for exclude, 0 for normal include, or 1
57+ * for super include.
58 */
59 int check_exclude(struct exclude_list_struct *listp, char *name, int name_is_dir,
60- const char *type)
61+ const char *type, int current_exclusion)
62 {
63 struct exclude_struct *ent;
64
65 for (ent = listp->head; ent; ent = ent->next) {
66+ if (current_exclusion < 0 && ent->include < 2)
67+ continue;
68 if (check_one_exclude(name, ent, name_is_dir)) {
69 report_exclude_result(name, ent, name_is_dir, type);
70- return !ent->include;
71+ return ent->include - 1;
72 }
73 }
74
75- return 0;
76+ return current_exclusion;
77 }
78
79
4eddff16 80@@ -249,10 +270,10 @@ static const char *get_exclude_tok(const
94f29894
WD
81 p = (const char *)s;
82 }
83
84- /* Is this a '+' or '-' followed by a space (not whitespace)? */
85+ /* Is this a +/-/& followed by a space (not whitespace)? */
86 if (!(xflags & XFLG_NO_PREFIXES)
87- && (*s == '-' || *s == '+') && s[1] == ' ') {
88- *incl_ptr = *s == '+';
89+ && (*s == '-' || *s == '+' || *s == '&') && s[1] == ' ') {
90+ *incl_ptr = *s == '+' ? 1 : *s == '&' ? 2 : 0;
91 s += 2;
92 } else
93 *incl_ptr = xflags & XFLG_DEF_INCLUDE;
4eddff16 94@@ -382,8 +403,12 @@ void send_exclude_list(int f)
94f29894
WD
95
96 if (ent->include) {
97 write_int(f, l + 2);
98- write_buf(f, "+ ", 2);
99- } else if ((*p == '-' || *p == '+') && p[1] == ' ') {
100+ if (ent->include > 1 && protocol_version >= 28)
101+ write_buf(f, "& ", 2);
102+ else
103+ write_buf(f, "+ ", 2);
104+ } else if ((*p == '-' || *p == '+' || *p == '&')
105+ && p[1] == ' ') {
106 write_int(f, l + 2);
107 write_buf(f, "- ", 2);
108 } else
109--- flist.c 14 Apr 2004 23:33:34 -0000 1.213
616f340b 110+++ flist.c 15 Apr 2004 21:02:10 -0000
94f29894
WD
111@@ -40,6 +40,7 @@ extern int ignore_errors;
112 extern int numeric_ids;
113
114 extern int cvs_exclude;
115+extern const char *subdir_exclude_filename;
116
117 extern int recurse;
118 extern char curr_dir[MAXPATHLEN];
616f340b 119@@ -66,6 +67,7 @@ extern int write_batch;
94f29894
WD
120
121 extern struct exclude_list_struct exclude_list;
122 extern struct exclude_list_struct server_exclude_list;
123+extern struct exclude_list_struct subdir_exclude_list;
124 extern struct exclude_list_struct local_exclude_list;
94f29894
WD
125
126 int io_error;
616f340b 127@@ -211,6 +213,12 @@ int link_stat(const char *path, STRUCT_S
94f29894
WD
128 */
129 static int check_exclude_file(char *fname, int is_dir, int exclude_level)
130 {
616f340b 131+ static struct exclude_list_struct *elist[] = {
94f29894 132+ &exclude_list, &subdir_exclude_list, &local_exclude_list, NULL };
616f340b 133+ static char *edesc[] = {
94f29894 134+ "pattern", "subdir-exclude", "local-ignore" };
616f340b 135+ int i, rc;
94f29894
WD
136+
137 #if 0 /* This currently never happens, so avoid a useless compare. */
138 if (exclude_level == NO_EXCLUDES)
139 return 0;
616f340b 140@@ -228,18 +236,18 @@ static int check_exclude_file(char *fnam
94f29894
WD
141 }
142 if (server_exclude_list.head
143 && check_exclude(&server_exclude_list, fname, is_dir,
144- "server pattern"))
145+ "server pattern", 0) < 0)
146 return 1;
147 if (exclude_level != ALL_EXCLUDES)
148 return 0;
149- if (exclude_list.head
150- && check_exclude(&exclude_list, fname, is_dir, "pattern"))
151- return 1;
152- if (local_exclude_list.head
153- && check_exclude(&local_exclude_list, fname, is_dir,
154- "local-cvsignore"))
155- return 1;
156- return 0;
157+ for (i = 0, rc = 0; elist[i]; i++) {
158+ if (!elist[i]->head)
159+ continue;
160+ rc = check_exclude(elist[i], fname, is_dir, edesc[i], rc);
161+ if (rc > 0)
162+ return 0;
163+ }
164+ return rc < 0;
165 }
166
167 /* used by the one_file_system code */
4eddff16 168@@ -957,8 +965,12 @@ void send_file_name(int f, struct file_l
94f29894
WD
169 if (recursive && S_ISDIR(file->mode)
170 && !(file->flags & FLAG_MOUNT_POINT)) {
171 struct exclude_list_struct last_list = local_exclude_list;
4eddff16 172- memset(&local_exclude_list, 0, sizeof local_exclude_list);
94f29894 173+ struct exclude_list_struct sub_list = subdir_exclude_list;
4eddff16
WD
174+ clear_exclude_list(&local_exclude_list, NULL);
175+ clear_exclude_list(&subdir_exclude_list, sub_list.head);
94f29894 176 send_directory(f, flist, f_name_to(file, fbuf));
94f29894
WD
177+ free_exclude_list(&subdir_exclude_list);
178+ subdir_exclude_list = sub_list;
94f29894
WD
179 free_exclude_list(&local_exclude_list);
180 local_exclude_list = last_list;
181 }
4eddff16 182@@ -1004,6 +1016,18 @@ static void send_directory(int f, struct
94f29894
WD
183 io_error |= IOERR_GENERAL;
184 rprintf(FINFO,
185 "cannot cvs-exclude in long-named directory %s\n",
186+ full_fname(fname));
187+ }
188+ }
189+
190+ if (subdir_exclude_filename) {
191+ if (strlcpy(p, subdir_exclude_filename, MAXPATHLEN - offset)
616f340b 192+ < MAXPATHLEN - offset)
94f29894 193+ add_exclude_file(&subdir_exclude_list, fname, 0);
616f340b 194+ else {
94f29894
WD
195+ io_error |= IOERR_GENERAL;
196+ rprintf(FINFO,
197+ "cannot subdir-exclude in long-named directory %s\n",
198 full_fname(fname));
199 }
200 }
201--- options.c 14 Apr 2004 23:33:34 -0000 1.146
616f340b 202+++ options.c 15 Apr 2004 21:02:10 -0000
94f29894
WD
203@@ -70,6 +70,7 @@ int am_server = 0;
204 int am_sender = 0;
205 int am_generator = 0;
206 char *files_from = NULL;
207+char *subdir_exclude_filename = NULL;
208 int filesfrom_fd = -1;
209 char *remote_filesfrom_file = NULL;
210 int eol_nulls = 0;
211@@ -273,6 +274,7 @@ void usage(enum logcode F)
212 rprintf(F," --exclude-from=FILE exclude patterns listed in FILE\n");
213 rprintf(F," --include=PATTERN don't exclude files matching PATTERN\n");
214 rprintf(F," --include-from=FILE don't exclude patterns listed in FILE\n");
215+ rprintf(F," --subdir-exclude=FILE look in each subdir for exclude file FILE\n");
216 rprintf(F," --files-from=FILE read FILE for list of source-file names\n");
217 rprintf(F," -0 --from0 all *-from file lists are delimited by nulls\n");
218 rprintf(F," --version print version number\n");
219@@ -335,6 +337,7 @@ static struct poptOption long_options[]
220 {"dry-run", 'n', POPT_ARG_NONE, &dry_run, 0, 0, 0 },
221 {"sparse", 'S', POPT_ARG_NONE, &sparse_files, 0, 0, 0 },
222 {"cvs-exclude", 'C', POPT_ARG_NONE, &cvs_exclude, 0, 0, 0 },
223+ {"subdir-exclude", 0, POPT_ARG_STRING, &subdir_exclude_filename, 0, 0, 0 },
224 {"update", 'u', POPT_ARG_NONE, &update_only, 0, 0, 0 },
225 {"links", 'l', POPT_ARG_NONE, &preserve_links, 0, 0, 0 },
226 {"copy-links", 'L', POPT_ARG_NONE, &copy_links, 0, 0, 0 },
227--- proto.h 14 Apr 2004 23:33:30 -0000 1.188
616f340b 228+++ proto.h 15 Apr 2004 21:02:11 -0000
4eddff16
WD
229@@ -52,8 +52,10 @@ int daemon_main(void);
230 void setup_protocol(int f_out,int f_in);
94f29894
WD
231 int claim_connection(char *fname,int max_connections);
232 void free_exclude_list(struct exclude_list_struct *listp);
4eddff16
WD
233+void clear_exclude_list(struct exclude_list_struct *listp,
234+ struct exclude_struct *extra);
94f29894
WD
235 int check_exclude(struct exclude_list_struct *listp, char *name, int name_is_dir,
236- const char *type);
237+ const char *type, int current_exclusion);
238 void add_exclude(struct exclude_list_struct *listp, const char *pattern,
239 int xflags);
240 void add_exclude_file(struct exclude_list_struct *listp, const char *fname,
616f340b
WD
241--- rsync.h 14 Apr 2004 23:33:37 -0000 1.196
242+++ rsync.h 15 Apr 2004 21:02:11 -0000
243@@ -504,6 +504,7 @@ struct exclude_struct {
244 struct exclude_list_struct {
245 struct exclude_struct *head;
246 struct exclude_struct *tail;
247+ struct exclude_struct *extra;
248 };
249
250 struct stats {
251--- rsync.yo 15 Apr 2004 18:32:24 -0000 1.157
252+++ rsync.yo 15 Apr 2004 21:02:11 -0000
94f29894
WD
253@@ -331,6 +331,7 @@ verb(
254 --exclude-from=FILE exclude patterns listed in FILE
255 --include=PATTERN don't exclude files matching PATTERN
256 --include-from=FILE don't exclude patterns listed in FILE
257+ --subdir-exclude=FILE look in each subdir for exclude file FILE
258 --files-from=FILE read FILE for list of source-file names
259 -0 --from0 all file lists are delimited by nulls
260 --version print version number
261@@ -651,6 +652,15 @@ dit(bf(--exclude=PATTERN)) This option a
262 certain files from the list of files to be transferred. This is most
263 useful in combination with a recursive transfer.
264
265+dit(bf(--subdir-exclude=FILE)) In any given directory, patterns listed
266+in FILE (one per line) are excluded from the file lists associated with
267+that directory and all of its subdirectories. Rules specified in a subdir
268+take precedence over rules evaluated in a parent dir (think of each set
269+of rules being prefixed to the prior rules). If you don't want to
270+inherit the parent-dir rules, start the FILE with a single exclamation
271+mark ! to clear them out. You may prefix names with an explicit exclude,
272+include, or super-include prefix (see below).
273+
274 You may use as many --exclude options on the command line as you like
275 to build up the list of files to exclude.
276
ce17e35e 277@@ -996,6 +1006,12 @@ itemize(
94f29894
WD
278 it() if the pattern starts with "- " (a minus followed by a space)
279 then it is always considered an exclude pattern, even if specified as
ce17e35e 280 part of an include option. The prefix is discarded before matching.
94f29894
WD
281+
282+ it() if the pattern starts with "& " (an ampersand followed by a space)
283+ then it is considered a super-include pattern. A super-include will
284+ override an exclude from another exclude list (a normal include only
285+ overrides an exclusion from further down in the same list). The
286+ prefix is discarded before matching.
287
288 it() if the pattern is a single exclamation mark ! then the current
289 include/exclude list is reset, removing all previously defined patterns.
290--- util.c 14 Apr 2004 23:33:34 -0000 1.135
616f340b 291+++ util.c 15 Apr 2004 21:02:12 -0000
94f29894
WD
292@@ -477,7 +477,7 @@ static int exclude_server_path(char *arg
293 for (s = arg; (s = strchr(s, '/')) != NULL; ) {
294 *s = '\0';
295 if (check_exclude(&server_exclude_list, arg, 1,
296- "server pattern")) {
297+ "server pattern", 0) < 0) {
298 /* We must leave arg truncated! */
299 return 1;
300 }