1 --- exclude.c 22 Apr 2004 09:58:15 -0000 1.70
2 +++ exclude.c 22 Apr 2004 10:32:52 -0000
7 +extern int protocol_version;
12 extern char curr_dir[];
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 " };
21 char *exclude_path_prefix = NULL;
23 /** Build an exclude structure given a exclude pattern */
24 @@ -85,6 +87,8 @@ static void make_exclude(struct exclude_
25 for (cp = ret->pattern; (cp = strchr(cp, '/')) != NULL; cp++)
28 + ret->next = listp->extra;
31 listp->head = listp->tail = ret;
33 @@ -108,12 +112,26 @@ void free_exclude_list(struct exclude_li
34 who_am_i(), listp->debug_type);
39 + listp->tail->next = NULL;
44 for (ent = listp->head; ent; ent = next) {
49 - listp->head = listp->tail = NULL;
50 + clear_exclude_list(listp, NULL);
53 +void clear_exclude_list(struct exclude_list_struct *listp,
54 + struct exclude_struct *extra)
56 + listp->head = listp->extra = extra;
60 static int check_one_exclude(char *name, struct exclude_struct *ex,
61 @@ -215,21 +233,25 @@ static void report_exclude_result(char c
64 * Return true if file NAME is defined to be excluded by the specified
66 + * exclude list. Returns -1 for exclude, 0 for normal include, or 1
67 + * for super include.
69 -int check_exclude(struct exclude_list_struct *listp, char *name, int name_is_dir)
70 +int check_exclude(struct exclude_list_struct *listp, char *name, int name_is_dir,
71 + int current_exclusion)
73 struct exclude_struct *ent;
75 for (ent = listp->head; ent; ent = ent->next) {
76 + if (current_exclusion < 0 && ent->include < 2)
78 if (check_one_exclude(name, ent, name_is_dir)) {
79 report_exclude_result(name, ent, name_is_dir,
81 - return !ent->include;
82 + return ent->include - 1;
87 + return current_exclusion;
91 @@ -255,10 +277,10 @@ static const char *get_exclude_tok(const
95 - /* Is this a '+' or '-' followed by a space (not whitespace)? */
96 + /* Is this a +/-/& followed by a space (not whitespace)? */
97 if (!(xflags & XFLG_NO_PREFIXES)
98 - && (*s == '-' || *s == '+') && s[1] == ' ') {
99 - *incl_ptr = *s == '+';
100 + && (*s == '-' || *s == '+' || *s == '&') && s[1] == ' ') {
101 + *incl_ptr = *s == '+' ? 1 : *s == '&' ? 2 : 0;
104 *incl_ptr = xflags & XFLG_DEF_INCLUDE;
105 @@ -390,8 +412,12 @@ void send_exclude_list(int f)
109 - write_buf(f, "+ ", 2);
110 - } else if ((*p == '-' || *p == '+') && p[1] == ' ') {
111 + if (ent->include > 1 && protocol_version >= 28)
112 + write_buf(f, "& ", 2);
114 + write_buf(f, "+ ", 2);
115 + } else if ((*p == '-' || *p == '+' || *p == '&')
118 write_buf(f, "- ", 2);
120 --- flist.c 22 Apr 2004 09:58:18 -0000 1.215
121 +++ flist.c 22 Apr 2004 10:32:52 -0000
122 @@ -40,6 +40,7 @@ extern int ignore_errors;
123 extern int numeric_ids;
125 extern int cvs_exclude;
126 +extern const char *perdir_exclude_from;
129 extern char curr_dir[MAXPATHLEN];
130 @@ -66,6 +67,7 @@ extern int write_batch;
132 extern struct exclude_list_struct exclude_list;
133 extern struct exclude_list_struct server_exclude_list;
134 +extern struct exclude_list_struct perdir_exclude_list;
135 extern struct exclude_list_struct local_exclude_list;
138 @@ -211,6 +213,10 @@ int link_stat(const char *path, STRUCT_S
140 static int check_exclude_file(char *fname, int is_dir, int exclude_level)
142 + static struct exclude_list_struct *elist[] = {
143 + &exclude_list, &perdir_exclude_list, &local_exclude_list, NULL };
146 #if 0 /* This currently never happens, so avoid a useless compare. */
147 if (exclude_level == NO_EXCLUDES)
149 @@ -227,16 +233,18 @@ static int check_exclude_file(char *fnam
152 if (server_exclude_list.head
153 - && check_exclude(&server_exclude_list, fname, is_dir))
154 + && check_exclude(&server_exclude_list, fname, is_dir, 0) < 0)
156 if (exclude_level != ALL_EXCLUDES)
158 - if (exclude_list.head && check_exclude(&exclude_list, fname, is_dir))
160 - if (local_exclude_list.head
161 - && check_exclude(&local_exclude_list, fname, is_dir))
164 + for (i = 0, rc = 0; elist[i]; i++) {
165 + if (!elist[i]->head)
167 + rc = check_exclude(elist[i], fname, is_dir, rc);
174 /* used by the one_file_system code */
175 @@ -944,8 +952,12 @@ void send_file_name(int f, struct file_l
176 if (recursive && S_ISDIR(file->mode)
177 && !(file->flags & FLAG_MOUNT_POINT)) {
178 struct exclude_list_struct last_list = local_exclude_list;
179 - local_exclude_list.head = local_exclude_list.tail = NULL;
180 + struct exclude_list_struct sub_list = perdir_exclude_list;
181 + clear_exclude_list(&local_exclude_list, NULL);
182 + clear_exclude_list(&perdir_exclude_list, sub_list.head);
183 send_directory(f, flist, f_name_to(file, fbuf));
184 + free_exclude_list(&perdir_exclude_list);
185 + perdir_exclude_list = sub_list;
186 free_exclude_list(&local_exclude_list);
187 local_exclude_list = last_list;
189 @@ -991,6 +1003,18 @@ static void send_directory(int f, struct
190 io_error |= IOERR_GENERAL;
192 "cannot cvs-exclude in long-named directory %s\n",
193 + full_fname(fname));
197 + if (perdir_exclude_from) {
198 + if (strlcpy(p, perdir_exclude_from, MAXPATHLEN - offset)
199 + < MAXPATHLEN - offset)
200 + add_exclude_file(&perdir_exclude_list, fname, 0);
202 + io_error |= IOERR_GENERAL;
204 + "cannot perdir-exclude in long-named directory %s\n",
208 --- options.c 17 Apr 2004 17:07:23 -0000 1.147
209 +++ options.c 22 Apr 2004 10:32:53 -0000
210 @@ -70,6 +70,7 @@ int am_server = 0;
212 int am_generator = 0;
213 char *files_from = NULL;
214 +char *perdir_exclude_from = NULL;
215 int filesfrom_fd = -1;
216 char *remote_filesfrom_file = NULL;
218 @@ -273,6 +274,7 @@ void usage(enum logcode F)
219 rprintf(F," --exclude-from=FILE exclude patterns listed in FILE\n");
220 rprintf(F," --include=PATTERN don't exclude files matching PATTERN\n");
221 rprintf(F," --include-from=FILE don't exclude patterns listed in FILE\n");
222 + rprintf(F," --perdir-exclude-from=F look in each dir for exclude-file F\n");
223 rprintf(F," --files-from=FILE read FILE for list of source-file names\n");
224 rprintf(F," -0 --from0 all *-from file lists are delimited by nulls\n");
225 rprintf(F," --version print version number\n");
226 @@ -335,6 +337,7 @@ static struct poptOption long_options[]
227 {"dry-run", 'n', POPT_ARG_NONE, &dry_run, 0, 0, 0 },
228 {"sparse", 'S', POPT_ARG_NONE, &sparse_files, 0, 0, 0 },
229 {"cvs-exclude", 'C', POPT_ARG_NONE, &cvs_exclude, 0, 0, 0 },
230 + {"perdir-exclude-from",0,POPT_ARG_STRING, &perdir_exclude_from, 0, 0, 0 },
231 {"update", 'u', POPT_ARG_NONE, &update_only, 0, 0, 0 },
232 {"links", 'l', POPT_ARG_NONE, &preserve_links, 0, 0, 0 },
233 {"copy-links", 'L', POPT_ARG_NONE, ©_links, 0, 0, 0 },
234 --- proto.h 22 Apr 2004 09:58:09 -0000 1.189
235 +++ proto.h 22 Apr 2004 10:32:53 -0000
236 @@ -52,7 +52,10 @@ int daemon_main(void);
237 void setup_protocol(int f_out,int f_in);
238 int claim_connection(char *fname,int max_connections);
239 void free_exclude_list(struct exclude_list_struct *listp);
240 -int check_exclude(struct exclude_list_struct *listp, char *name, int name_is_dir);
241 +void clear_exclude_list(struct exclude_list_struct *listp,
242 + struct exclude_struct *extra);
243 +int check_exclude(struct exclude_list_struct *listp, char *name, int name_is_dir,
244 + int current_exclusion);
245 void add_exclude(struct exclude_list_struct *listp, const char *pattern,
247 void add_exclude_file(struct exclude_list_struct *listp, const char *fname,
248 --- rsync.h 22 Apr 2004 09:58:24 -0000 1.198
249 +++ rsync.h 22 Apr 2004 10:32:53 -0000
250 @@ -502,6 +502,7 @@ struct exclude_struct {
251 struct exclude_list_struct {
252 struct exclude_struct *head;
253 struct exclude_struct *tail;
254 + struct exclude_struct *extra;
258 --- rsync.yo 17 Apr 2004 18:40:16 -0000 1.159
259 +++ rsync.yo 22 Apr 2004 10:32:54 -0000
260 @@ -331,6 +331,7 @@ verb(
261 --exclude-from=FILE exclude patterns listed in FILE
262 --include=PATTERN don't exclude files matching PATTERN
263 --include-from=FILE don't exclude patterns listed in FILE
264 + --perdir-exclude-from=F look in each dir for exclude file F
265 --files-from=FILE read FILE for list of source-file names
266 -0 --from0 all file lists are delimited by nulls
267 --version print version number
268 @@ -672,6 +673,15 @@ dit(bf(--include-from=FILE)) This specif
270 If em(FILE) is bf(-) the list will be read from standard input.
272 +dit(bf(--perdir-exclude-from=FILE)) In any given directory, patterns
273 +listed in FILE (one per line) are excluded from the file lists
274 +associated with that directory and all of its subdirectories. Rules
275 +specified in a subdir take precedence over rules evaluated in a parent
276 +dir (think of each file's rules being prefixed to the prior rules). If
277 +you don't want to inherit the parent-dir rules, start the FILE with a
278 +single exclamation mark ! to clear them out. You may prefix names with
279 +an explicit exclude, include, or super-include prefix (see below).
281 dit(bf(--files-from=FILE)) Using this option allows you to specify the
282 exact list of files to transfer (as read from the specified FILE or "-"
283 for stdin). It also tweaks the default behavior of rsync to make
284 @@ -711,7 +721,8 @@ was located on the remote "src" host.
286 dit(bf(-0, --from0)) This tells rsync that the filenames it reads from a
287 file are terminated by a null ('\0') character, not a NL, CR, or CR+LF.
288 -This affects --exclude-from, --include-from, and --files-from.
289 +This affects --exclude-from, --include-from, --perdir-exclude-from,
291 It does not affect --cvs-exclude (since all names read from a .cvsignore
292 file are split on whitespace).
294 @@ -998,6 +1009,12 @@ itemize(
295 it() if the pattern starts with "- " (a minus followed by a space)
296 then it is always considered an exclude pattern, even if specified as
297 part of an include option. The prefix is discarded before matching.
299 + it() if the pattern starts with "& " (an ampersand followed by a space)
300 + then it is considered a super-include pattern. A super-include will
301 + override an exclude from another exclude list (a normal include only
302 + overrides an exclusion from further down in the same list). The
303 + prefix is discarded before matching.
305 it() if the pattern is a single exclamation mark ! then the current
306 include/exclude list is reset, removing all previously defined patterns.
307 --- t_stub.c 22 Apr 2004 09:58:11 -0000 1.7
308 +++ t_stub.c 22 Apr 2004 10:32:54 -0000
309 @@ -46,7 +46,7 @@ struct exclude_list_struct server_exclud
312 int check_exclude(UNUSED(struct exclude_list_struct *listp), UNUSED(char *name),
313 - UNUSED(int name_is_dir))
314 + UNUSED(int name_is_dir), UNUSED(int current_exclusion))
316 /* This function doesn't really get called in this test context, so
318 --- util.c 22 Apr 2004 09:58:21 -0000 1.137
319 +++ util.c 22 Apr 2004 10:32:54 -0000
320 @@ -476,7 +476,7 @@ static int exclude_server_path(char *arg
321 if (server_exclude_list.head) {
322 for (s = arg; (s = strchr(s, '/')) != NULL; ) {
324 - if (check_exclude(&server_exclude_list, arg, 1)) {
325 + if (check_exclude(&server_exclude_list, arg, 1, 0) < 0) {
326 /* We must leave arg truncated! */