- Fixed a failing hunk.
[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);
85f55536 35--- orig/exclude.c 2005-02-11 10:53:14
92172906 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 47@@ -678,6 +679,10 @@ static const char *parse_rule_tok(const
85f55536 48 if ((s = RULE_STRCMP(s, "exclude")) != NULL)
92172906
WD
49 ch = '-';
50 break;
51+ case 'h':
85f55536 52+ if ((s = RULE_STRCMP(s, "hide")) != NULL)
92172906
WD
53+ ch = 'H';
54+ break;
55 case 'i':
85f55536 56 if ((s = RULE_STRCMP(s, "include")) != NULL)
92172906
WD
57 ch = '+';
58@@ -686,6 +691,19 @@ static const char *parse_rule_tok(const
85f55536 59 if ((s = RULE_STRCMP(s, "merge")) != NULL)
92172906
WD
60 ch = '.';
61 break;
62+ case 'p':
85f55536 63+ if ((s = RULE_STRCMP(s, "protect")) != NULL)
92172906
WD
64+ ch = 'P';
65+ break;
66+ case 's':
85f55536 67+ if ((s = RULE_STRCMP(s, "send")) != NULL)
92172906
WD
68+ ch = 'S';
69+ break;
70+ case 'u':
85f55536 71+ if ((s = RULE_STRCMP(s, "unprotect")) != NULL)
92172906
WD
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 */
85f55536
WD
229+#define MATCHFLG_SENDER_SIDE (1<<16)/* rule applies to the sending side */
230+#define MATCHFLG_RECEIVER_SIDE (1<<17)/* rule applies to the receiving side */
66b47d42
WD
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;
85f55536
WD
239--- orig/rsync.yo 2005-02-11 10:53:15
240+++ rsync.yo 2005-02-11 10:58:06
241@@ -679,7 +679,9 @@ send the whole directory (e.g. "dir" or
66b47d42
WD
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
85f55536 252@@ -726,6 +728,9 @@ See bf(--delete) (which is implied) for
66b47d42
WD
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
85f55536 262@@ -1255,6 +1260,10 @@ bf(exclude, -) specifies an exclude patt
92172906
WD
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
85f55536 273@@ -1279,8 +1288,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 283 can take several forms:
85f55536 284@@ -1419,7 +1428,9 @@ itemize(
92172906
WD
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 "-":
85f55536 295@@ -1435,7 +1446,18 @@ 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.
85f55536 299- )
66b47d42 300+ it() An bf(s) is used to indicate that the rule applies to the sending
85f55536 301+ side. When a rule affects the sending side, it prevents files from
66b47d42
WD
302+ being transferred. The default is for a rule to affect both sides
303+ unless bf(--delete-excluded) was specified, in which case default rules
85f55536
WD
304+ become sender-side only. See also the hide (H) and show (S) rules,
305+ which are an alternate way to specify server-side includes/excludes.
66b47d42 306+ it() An bf(r) is used to indicate that the rule applies to the receiving
85f55536
WD
307+ side. When a rule affects the receiving side, it prevents files from
308+ being deleted. See the bf(s) modifier for more info. See also the
309+ protect (P) and unprotect (U) rules, which are an alternate way to
310+ specify receiver-side includes/excludes.
311+)
66b47d42
WD
312
313 Per-directory rules are inherited in all subdirectories of the directory
85f55536 314 where the merge-file was found unless the 'n' modifier was used. Each