Fixed a bug in the propagation of a filter rule's "r" modifier
[rsync/rsync-patches.git] / sender-receiver-excludes.diff
CommitLineData
66b47d42
WD
1This patch adds two modifiers to the filter rule prefixes that allow a
2rule to be marked as sender-side (s), receiver-side (r), or both ("sr"
3or omitted). Sender-side rules prevent files from being transferred,
4while receiver-side rules prevent files from being deleted. The default
5for an unmodified include/exclude rule is to affect both sides, but a
6rule that is explicitly marked as affecting both sides will remain
7unaffected by the --delete-excluded option (that option changes any
8unmodified rules into server-side only rules).
9
10See the updated manpage for the details.
11
12--- orig/compat.c 2005-02-01 10:39:22
13+++ compat.c 2005-02-05 05:31:06
14@@ -31,6 +31,7 @@ extern int verbose;
15 extern int am_server;
16 extern int am_sender;
17 extern int read_batch;
18+extern int delete_excluded;
19 extern int checksum_seed;
20 extern int protocol_version;
21
22@@ -74,6 +75,12 @@ void setup_protocol(int f_out,int f_in)
23 exit_cleanup(RERR_PROTOCOL);
24 }
25
26+ /* In newer protocols, --delete-excluded does not avoid the exclude-
27+ * list transfer to the receiver, so mark a modern --delete-excluded
28+ * conversation with a 2 instead of a 1. */
29+ if (protocol_version >= 29 && delete_excluded)
30+ delete_excluded = 2;
31+
32 if (am_server) {
33 if (!checksum_seed)
34 checksum_seed = time(NULL);
92172906
WD
35--- orig/exclude.c 2005-02-08 19:06:38
36+++ exclude.c 2005-02-08 18:34:22
66b47d42
WD
37@@ -53,7 +53,8 @@ struct filter_list_struct server_filter_
38 #define MAX_RULE_PREFIX (16)
39
40 #define MODIFIERS_MERGE_FILE "-+Cenw"
41-#define MODIFIERS_INCL_EXCL "/!C"
42+#define MODIFIERS_INCL_EXCL "/!Crs"
43+#define MODIFIERS_HIDE_PROTECT "/!"
44
45 /* The dirbuf is set by push_local_filters() to the current subdirectory
46 * relative to curr_dir that is being processed. The path always has a
92172906
WD
47@@ -678,6 +679,10 @@ static const char *parse_rule_tok(const
48 if ((s = RULE_MATCH(s, "exclude")) != NULL)
49 ch = '-';
50 break;
51+ case 'h':
52+ if ((s = RULE_MATCH(s, "hide")) != NULL)
53+ ch = 'H';
54+ break;
55 case 'i':
56 if ((s = RULE_MATCH(s, "include")) != NULL)
57 ch = '+';
58@@ -686,6 +691,19 @@ static const char *parse_rule_tok(const
59 if ((s = RULE_MATCH(s, "merge")) != NULL)
60 ch = '.';
61 break;
62+ case 'p':
63+ if ((s = RULE_MATCH(s, "protect")) != NULL)
64+ ch = 'P';
65+ break;
66+ case 's':
67+ if ((s = RULE_MATCH(s, "send")) != NULL)
68+ ch = 'S';
69+ break;
70+ case 'u':
71+ if ((s = RULE_MATCH(s, "unprotect")) != NULL)
72+ ch = 'U';
73+ break;
74+
75 default:
76 ch = *s;
77 if (s[1] == ',')
78@@ -707,6 +725,20 @@ static const char *parse_rule_tok(const
66b47d42
WD
79 case '-':
80 mods = MODIFIERS_INCL_EXCL;
81 break;
92172906
WD
82+ case 'S':
83+ new_mflags |= MATCHFLG_INCLUDE;
84+ /* FALL THROUGH */
66b47d42
WD
85+ case 'H':
86+ new_mflags |= MATCHFLG_SENDER_SIDE;
87+ mods = MODIFIERS_HIDE_PROTECT;
88+ break;
92172906
WD
89+ case 'U':
90+ new_mflags |= MATCHFLG_INCLUDE;
91+ /* FALL THROUGH */
66b47d42
WD
92+ case 'P':
93+ new_mflags |= MATCHFLG_RECEIVER_SIDE;
94+ mods = MODIFIERS_HIDE_PROTECT;
95+ break;
96 case '!':
97 new_mflags |= MATCHFLG_CLEAR_LIST;
98 mods = NULL;
92172906 99@@ -759,6 +791,12 @@ static const char *parse_rule_tok(const
66b47d42
WD
100 case 'n':
101 new_mflags |= MATCHFLG_NO_INHERIT;
102 break;
103+ case 'r':
104+ new_mflags |= MATCHFLG_RECEIVER_SIDE;
105+ break;
106+ case 's':
107+ new_mflags |= MATCHFLG_SENDER_SIDE;
108+ break;
109 case 'w':
110 new_mflags |= MATCHFLG_WORD_SPLIT;
111 break;
92172906 112@@ -1013,6 +1051,11 @@ char *get_rule_prefix(int match_flags, c
66b47d42
WD
113 }
114 if (match_flags & MATCHFLG_EXCLUDE_SELF)
115 *op++ = 'e';
116+ if (match_flags & MATCHFLG_SENDER_SIDE && !for_xfer)
117+ *op++ = 's';
118+ if (match_flags & MATCHFLG_RECEIVER_SIDE
afc5ee90 119+ && (!for_xfer || (delete_excluded && am_sender)))
66b47d42
WD
120+ *op++ = 'r';
121 if (legal_len)
122 *op++ = ' ';
123 if (op - buf > legal_len)
92172906 124@@ -1025,19 +1068,37 @@ char *get_rule_prefix(int match_flags, c
66b47d42
WD
125
126 static void send_rules(int f_out, struct filter_list_struct *flp)
127 {
128- struct filter_struct *ent;
129+ struct filter_struct *ent, *prev = NULL;
130
131 for (ent = flp->head; ent; ent = ent->next) {
132 unsigned int len, plen, dlen;
133+ int elide = 0;
134 char *p;
135
136+ if (ent->match_flags & MATCHFLG_SENDER_SIDE)
137+ elide = am_sender ? 1 : -1;
138+ if (ent->match_flags & MATCHFLG_RECEIVER_SIDE)
139+ elide = elide ? 0 : am_sender ? -1 : 1;
140+ else if (delete_excluded)
141+ elide = am_sender ? 1 : -1;
142+ if (elide < 0) {
143+ if (prev)
144+ prev->next = ent->next;
145+ else
146+ flp->head = ent->next;
147+ } else
148+ prev = ent;
149+ if (elide > 0)
150+ continue;
151 if (ent->match_flags & MATCHFLG_CVS_IGNORE
152 && !(ent->match_flags & MATCHFLG_MERGE_FILE)) {
153- if (am_sender || protocol_version < 29) {
154- send_rules(f_out, &cvs_filter_list);
155+ int f = am_sender || protocol_version < 29 ? f_out : -1;
156+ send_rules(f, &cvs_filter_list);
157+ if (f >= 0)
158 continue;
159- }
160 }
161+ if (f_out < 0)
162+ continue;
163 p = get_rule_prefix(ent->match_flags, ent->pattern, 1, &plen);
164 if (!p) {
165 rprintf(FERROR,
92172906 166@@ -1055,12 +1116,13 @@ static void send_rules(int f_out, struct
66b47d42
WD
167 if (dlen)
168 write_byte(f_out, '/');
169 }
170+ flp->tail = prev;
171 }
172
173 /* This is only called by the client. */
174 void send_filter_list(int f_out)
175 {
176- int receiver_wants_list = delete_mode && !delete_excluded;
177+ int receiver_wants_list = delete_mode && delete_excluded != 1;
178
179 if (local_server || (am_sender && !receiver_wants_list))
180 f_out = -1;
92172906 181@@ -1075,10 +1137,10 @@ void send_filter_list(int f_out)
66b47d42
WD
182 if (list_only == 1 && !recurse)
183 parse_rule(&filter_list, "/*/*", MATCHFLG_NO_PREFIXES, 0);
184
185- if (f_out >= 0) {
186- send_rules(f_out, &filter_list);
187+ send_rules(f_out, &filter_list);
188+
189+ if (f_out >= 0)
190 write_int(f_out, 0);
191- }
192
193 if (cvs_exclude) {
194 if (!am_sender || protocol_version < 29)
92172906 195@@ -1094,7 +1156,7 @@ void recv_filter_list(int f_in)
66b47d42
WD
196 char line[MAXPATHLEN+MAX_RULE_PREFIX+1]; /* +1 for trailing slash. */
197 int xflags = protocol_version >= 29 ? 0 : XFLG_OLD_PREFIXES;
198 unsigned int len;
199- int receiver_wants_list = delete_mode && !delete_excluded;
200+ int receiver_wants_list = delete_mode && delete_excluded != 1;
201
202 if (!local_server && (am_sender || receiver_wants_list)) {
203 while ((len = read_int(f_in)) != 0) {
92172906 204@@ -1111,4 +1173,7 @@ void recv_filter_list(int f_in)
66b47d42
WD
205 if (local_server || am_sender)
206 parse_rule(&filter_list, "-C", 0, 0);
207 }
208+
209+ if (local_server) /* filter out any rules that aren't for us. */
210+ send_rules(-1, &filter_list);
211 }
afc5ee90 212--- orig/flist.c 2005-02-09 02:37:15
66b47d42 213+++ flist.c 2005-02-05 05:31:09
afc5ee90 214@@ -978,7 +978,7 @@ void send_file_name(int f, struct file_l
66b47d42
WD
215
216 /* f is set to -1 when calculating deletion file list */
217 file = make_file(fname, flist,
218- f == -1 && delete_excluded? SERVER_FILTERS : ALL_FILTERS);
219+ f == -1 && delete_excluded == 1 ? SERVER_FILTERS : ALL_FILTERS);
220
221 if (!file)
222 return;
92172906 223--- orig/rsync.h 2005-02-07 20:41:57
66b47d42
WD
224+++ rsync.h 2005-02-05 05:31:10
225@@ -565,9 +565,12 @@ struct map_struct {
226 #define MATCHFLG_FINISH_SETUP (1<<13)/* per-dir merge file needs setup */
227 #define MATCHFLG_NEGATE (1<<14)/* rule matches when pattern does not */
228 #define MATCHFLG_CVS_IGNORE (1<<15)/* rule was -C or :C */
229+#define MATCHFLG_SENDER_SIDE (1<<16)/* rule applies to the sender side */
230+#define MATCHFLG_RECEIVER_SIDE (1<<17)/* rule applies to the receiver side */
231
232 #define MATCHFLGS_FROM_CONTAINER (MATCHFLG_ABS_PATH | MATCHFLG_INCLUDE \
233- | MATCHFLG_DIRECTORY | MATCHFLG_NEGATE)
234+ | MATCHFLG_DIRECTORY | MATCHFLG_SENDER_SIDE \
235+ | MATCHFLG_NEGATE | MATCHFLG_RECEIVER_SIDE)
236
237 struct filter_struct {
238 struct filter_struct *next;
92172906
WD
239--- orig/rsync.yo 2005-02-08 19:06:38
240+++ rsync.yo 2005-02-08 19:10:12
66b47d42
WD
241@@ -678,7 +678,9 @@ send the whole directory (e.g. "dir" or
242 for the directory's contents (e.g. "dir/*") since the wildcard is expanded
243 by the shell and rsync thus gets a request to transfer individual files, not
244 the files' parent directory. Files that are excluded from transfer are
245-excluded from being deleted unless you use bf(--delete-excluded).
246+also excluded from being deleted unless you use the bf(--delete-excluded)
247+option or mark the rules as only matching on the sending side (see the
248+include/exclude modifiers in the FILTER RULES section).
249
250 This option has no effect unless directory recursion is enabled.
251
252@@ -725,6 +727,9 @@ See bf(--delete) (which is implied) for
253 dit(bf(--delete-excluded)) In addition to deleting the files on the
254 receiving side that are not on the sending side, this tells rsync to also
255 delete any files on the receiving side that are excluded (see bf(--exclude)).
256+See the FILTER RULES section for a way to make individual exclusions behave
257+this way on the receiver, and for a way to protect files from
258+bf(--delete-excluded).
259 See bf(--delete) (which is implied) for more details on file-deletion.
260
261 dit(bf(--ignore-errors)) Tells bf(--delete) to go ahead and delete files
92172906
WD
262@@ -1243,6 +1248,10 @@ bf(exclude, -) specifies an exclude patt
263 bf(include, +) specifies an include pattern. nl()
264 bf(merge, .) specifies a merge-file to read for more rules. nl()
265 bf(dir-merge, :) specifies a per-directory merge-file. nl()
266+bf(hide, H) specifies a pattern for hiding files from the transfer. nl()
267+bf(send, S) the opposite of a "hide". nl()
268+bf(protect, P) specifies a pattern for protecting files from deletion. nl()
269+bf(unprotect, U) the opposite of a "protect". nl()
270 bf(clear, !) clears the current include/exclude list (takes no arg) nl()
66b47d42
WD
271 )
272
92172906 273@@ -1267,8 +1276,8 @@ the bf(--include-from)/bf(--exclude-from
66b47d42
WD
274
275 manpagesection(INCLUDE/EXCLUDE PATTERN RULES)
276
277-You can include and exclude files by specifying patterns using the "+" and
34ec332e 278-"-" filter rules (as introduced in the FILTER RULES section above).
66b47d42 279+You can include and exclude files by specifying patterns using the "+",
92172906 280+"-", etc. filter rules (as introduced in the FILTER RULES section above).
34ec332e
WD
281 The include/exclude rules each specify a pattern that is matched against
282 the names of the files that are going to be transferred. These patterns
92172906
WD
283 can take several forms:
284@@ -1407,7 +1416,9 @@ itemize(
285 it() You may also specify any of the modifiers for the "+" or "-" rules
286 (below) in order to have the rules that are read-in from the file
287 default to having that modifier set. For instance, "merge,-/_.excl" would
288- treat the contents of .excl as absolute-path excludes.
289+ treat the contents of .excl as absolute-path excludes,
290+ while "dir-merge,s_.filt" and ":sC" would each make all their
291+ per-directory rules apply only on the server side.
66b47d42
WD
292 )
293
294 The following modifiers are accepted after a "+" or "-":
92172906 295@@ -1423,6 +1434,16 @@ itemize(
66b47d42
WD
296 it() A bf(C) is used to indicate that all the global CVS-exclude rules
297 should be inserted as excludes in place of the "-C". No arg should
298 follow.
299+ it() An bf(s) is used to indicate that the rule applies to the sending
300+ side. When a rule affects the sending side it, prevents files from
301+ being transferred. The default is for a rule to affect both sides
302+ unless bf(--delete-excluded) was specified, in which case default rules
303+ become sender-side only. See also the "H" (hide) rule, which is an
304+ alias for the "-" rule with the "s" modifer.
305+ it() An bf(r) is used to indicate that the rule applies to the receiving
306+ side. When a rule affects the receiving side it, prevents files from
307+ being deleted. See the bf(s) modifier for more info. See also the "P"
308+ (protect) rule, which is an alias for the "-" rule with the "r" modifier.
309 )
310
311 Per-directory rules are inherited in all subdirectories of the directory