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