Commit | Line | Data |
---|---|---|
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, ©_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 | } |