ee42f25e672b846292ae26009847c03fcd515db0
[rsync/rsync-patches.git] / sender-receiver-excludes.diff
1 This patch adds two modifiers to the filter rule prefixes that allow a
2 rule to be marked as sender-side (s), receiver-side (r), or both ("sr"
3 or omitted).  Sender-side rules prevent files from being transferred,
4 while receiver-side rules prevent files from being deleted.  The default
5 for an unmodified include/exclude rule is to affect both sides, but a
6 rule that is explicitly marked as affecting both sides will remain
7 unaffected by the --delete-excluded option (that option changes any
8 unmodified rules into server-side only rules).
9
10 See 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);
35 --- orig/exclude.c      2005-02-05 06:48:21
36 +++ exclude.c   2005-02-05 06:56:47
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
47 @@ -667,6 +668,14 @@ static const char *parse_rule_tok(const 
48                 case '-':
49                         mods = MODIFIERS_INCL_EXCL;
50                         break;
51 +               case 'H':
52 +                       new_mflags |= MATCHFLG_SENDER_SIDE;
53 +                       mods = MODIFIERS_HIDE_PROTECT;
54 +                       break;
55 +               case 'P':
56 +                       new_mflags |= MATCHFLG_RECEIVER_SIDE;
57 +                       mods = MODIFIERS_HIDE_PROTECT;
58 +                       break;
59                 case '!':
60                         new_mflags |= MATCHFLG_CLEAR_LIST;
61                         mods = NULL;
62 @@ -719,6 +728,12 @@ static const char *parse_rule_tok(const 
63                         case 'n':
64                                 new_mflags |= MATCHFLG_NO_INHERIT;
65                                 break;
66 +                       case 'r':
67 +                               new_mflags |= MATCHFLG_RECEIVER_SIDE;
68 +                               break;
69 +                       case 's':
70 +                               new_mflags |= MATCHFLG_SENDER_SIDE;
71 +                               break;
72                         case 'w':
73                                 new_mflags |= MATCHFLG_WORD_SPLIT;
74                                 break;
75 @@ -973,6 +988,11 @@ char *get_rule_prefix(int match_flags, c
76         }
77         if (match_flags & MATCHFLG_EXCLUDE_SELF)
78                 *op++ = 'e';
79 +       if (match_flags & MATCHFLG_SENDER_SIDE && !for_xfer)
80 +               *op++ = 's';
81 +       if (match_flags & MATCHFLG_RECEIVER_SIDE
82 +           && (!for_xfer || delete_excluded))
83 +               *op++ = 'r';
84         if (legal_len)
85                 *op++ = ' ';
86         if (op - buf > legal_len)
87 @@ -985,19 +1005,37 @@ char *get_rule_prefix(int match_flags, c
88  
89  static void send_rules(int f_out, struct filter_list_struct *flp)
90  {
91 -       struct filter_struct *ent;
92 +       struct filter_struct *ent, *prev = NULL;
93  
94         for (ent = flp->head; ent; ent = ent->next) {
95                 unsigned int len, plen, dlen;
96 +               int elide = 0;
97                 char *p;
98  
99 +               if (ent->match_flags & MATCHFLG_SENDER_SIDE)
100 +                       elide = am_sender ? 1 : -1;
101 +               if (ent->match_flags & MATCHFLG_RECEIVER_SIDE)
102 +                       elide = elide ? 0 : am_sender ? -1 : 1;
103 +               else if (delete_excluded)
104 +                       elide = am_sender ? 1 : -1;
105 +               if (elide < 0) {
106 +                       if (prev)
107 +                               prev->next = ent->next;
108 +                       else
109 +                               flp->head = ent->next;
110 +               } else
111 +                       prev = ent;
112 +               if (elide > 0)
113 +                       continue;
114                 if (ent->match_flags & MATCHFLG_CVS_IGNORE
115                     && !(ent->match_flags & MATCHFLG_MERGE_FILE)) {
116 -                       if (am_sender || protocol_version < 29) {
117 -                               send_rules(f_out, &cvs_filter_list);
118 +                       int f = am_sender || protocol_version < 29 ? f_out : -1;
119 +                       send_rules(f, &cvs_filter_list);
120 +                       if (f >= 0)
121                                 continue;
122 -                       }
123                 }
124 +               if (f_out < 0)
125 +                       continue;
126                 p = get_rule_prefix(ent->match_flags, ent->pattern, 1, &plen);
127                 if (!p) {
128                         rprintf(FERROR,
129 @@ -1015,12 +1053,13 @@ static void send_rules(int f_out, struct
130                 if (dlen)
131                         write_byte(f_out, '/');
132         }
133 +       flp->tail = prev;
134  }
135  
136  /* This is only called by the client. */
137  void send_filter_list(int f_out)
138  {
139 -       int receiver_wants_list = delete_mode && !delete_excluded;
140 +       int receiver_wants_list = delete_mode && delete_excluded != 1;
141  
142         if (local_server || (am_sender && !receiver_wants_list))
143                 f_out = -1;
144 @@ -1035,10 +1074,10 @@ void send_filter_list(int f_out)
145         if (list_only == 1 && !recurse)
146                 parse_rule(&filter_list, "/*/*", MATCHFLG_NO_PREFIXES, 0);
147  
148 -       if (f_out >= 0) {
149 -               send_rules(f_out, &filter_list);
150 +       send_rules(f_out, &filter_list);
151 +
152 +       if (f_out >= 0)
153                 write_int(f_out, 0);
154 -       }
155  
156         if (cvs_exclude) {
157                 if (!am_sender || protocol_version < 29)
158 @@ -1054,7 +1093,7 @@ void recv_filter_list(int f_in)
159         char line[MAXPATHLEN+MAX_RULE_PREFIX+1]; /* +1 for trailing slash. */
160         int xflags = protocol_version >= 29 ? 0 : XFLG_OLD_PREFIXES;
161         unsigned int len;
162 -       int receiver_wants_list = delete_mode && !delete_excluded;
163 +       int receiver_wants_list = delete_mode && delete_excluded != 1;
164  
165         if (!local_server && (am_sender || receiver_wants_list)) {
166                 while ((len = read_int(f_in)) != 0) {
167 @@ -1071,4 +1110,7 @@ void recv_filter_list(int f_in)
168                 if (local_server || am_sender)
169                         parse_rule(&filter_list, "-C", 0, 0);
170         }
171 +
172 +       if (local_server) /* filter out any rules that aren't for us. */
173 +               send_rules(-1, &filter_list);
174  }
175 --- orig/flist.c        2005-02-03 19:23:55
176 +++ flist.c     2005-02-05 05:31:09
177 @@ -979,7 +979,7 @@ void send_file_name(int f, struct file_l
178  
179         /* f is set to -1 when calculating deletion file list */
180         file = make_file(fname, flist,
181 -           f == -1 && delete_excluded? SERVER_FILTERS : ALL_FILTERS);
182 +           f == -1 && delete_excluded == 1 ? SERVER_FILTERS : ALL_FILTERS);
183  
184         if (!file)
185                 return;
186 --- orig/rsync.h        2005-02-04 22:28:09
187 +++ rsync.h     2005-02-05 05:31:10
188 @@ -565,9 +565,12 @@ struct map_struct {
189  #define MATCHFLG_FINISH_SETUP  (1<<13)/* per-dir merge file needs setup */
190  #define MATCHFLG_NEGATE        (1<<14)/* rule matches when pattern does not */
191  #define MATCHFLG_CVS_IGNORE    (1<<15)/* rule was -C or :C */
192 +#define MATCHFLG_SENDER_SIDE   (1<<16)/* rule applies to the sender side */
193 +#define MATCHFLG_RECEIVER_SIDE (1<<17)/* rule applies to the receiver side */
194  
195  #define MATCHFLGS_FROM_CONTAINER (MATCHFLG_ABS_PATH | MATCHFLG_INCLUDE \
196 -                               | MATCHFLG_DIRECTORY | MATCHFLG_NEGATE)
197 +                               | MATCHFLG_DIRECTORY | MATCHFLG_SENDER_SIDE \
198 +                               | MATCHFLG_NEGATE | MATCHFLG_RECEIVER_SIDE)
199  
200  struct filter_struct {
201         struct filter_struct *next;
202 --- orig/rsync.yo       2005-02-05 01:23:49
203 +++ rsync.yo    2005-02-05 05:31:11
204 @@ -678,7 +678,9 @@ send the whole directory (e.g. "dir" or 
205  for the directory's contents (e.g. "dir/*") since the wildcard is expanded
206  by the shell and rsync thus gets a request to transfer individual files, not
207  the files' parent directory.  Files that are excluded from transfer are
208 -excluded from being deleted unless you use bf(--delete-excluded).
209 +also excluded from being deleted unless you use the bf(--delete-excluded)
210 +option or mark the rules as only matching on the sending side (see the
211 +include/exclude modifiers in the FILTER RULES section).
212  
213  This option has no effect unless directory recursion is enabled.
214  
215 @@ -725,6 +727,9 @@ See bf(--delete) (which is implied) for 
216  dit(bf(--delete-excluded)) In addition to deleting the files on the
217  receiving side that are not on the sending side, this tells rsync to also
218  delete any files on the receiving side that are excluded (see bf(--exclude)).
219 +See the FILTER RULES section for a way to make individual exclusions behave
220 +this way on the receiver, and for a way to protect files from
221 +bf(--delete-excluded).
222  See bf(--delete) (which is implied) for more details on file-deletion.
223  
224  dit(bf(--ignore-errors)) Tells bf(--delete) to go ahead and delete files
225 @@ -1241,6 +1246,8 @@ bf(-) specifies an exclude pattern. nl()
226  bf(+) specifies an include pattern. nl()
227  bf(.) specifies a merge-file to read for more rules. nl()
228  bf(:) specifies a per-directory merge-file. nl()
229 +bf(H) specifies a pattern for hiding files from the transfer. nl()
230 +bf(P) specifies a pattern for protecting files from deletion. nl()
231  bf(!) clears the current include/exclude list (takes no arg) nl()
232  )
233  
234 @@ -1263,10 +1270,17 @@ comment lines that start with a "#".
235  
236  manpagesection(INCLUDE/EXCLUDE PATTERN RULES)
237  
238 -You can include and exclude files by specifying patterns using the "+" and
239 -"-" filter rules (as introduced in the FILTER RULES section above).  These
240 -rules specify a pattern that is matched against the names of the files
241 -that are going to be transferred.  These patterns can take several forms:
242 +You can include and exclude files by specifying patterns using the "+",
243 +"-", "H", and "P" filter rules (as introduced in the FILTER RULES section
244 +above).
245 +Note that the "H" (hide) rule is just a more intuitive way to specify a "-"
246 +rule with an "s" modifier (a sender-only exclusion) and "P" (protect) is
247 +just a more intuitive way to specify a "-" rule with an "r" modifier (a
248 +receiver-only exclusion).  See the modifiers below for more information.
249 +
250 +The include/exclude rules each specify a pattern that is matched against
251 +the names of the files that are going to be transferred.  These patterns
252 +can take several forms:
253  
254  itemize(
255    it() if the pattern starts with a / then it is anchored to a
256 @@ -1398,6 +1412,9 @@ itemize(
257    space that separates the prefix from the rule is treated specially, so
258    "- foo + bar" is parsed as two rules (assuming that bf(-) or bf(+) was not
259    specified to turn off the parsing of prefixes).
260 +  it() You may also specify any of the modifiers for "+" or "-" to have the
261 +  rules that are read-in default to having that option set.  For instance,
262 +  ":s_.excl" would make all the rules in .excl server-side only.
263  )
264  
265  The following modifiers are accepted after a "+" or "-":
266 @@ -1413,6 +1430,16 @@ itemize(
267    it() A bf(C) is used to indicate that all the global CVS-exclude rules
268    should be inserted as excludes in place of the "-C".  No arg should
269    follow.
270 +  it() An bf(s) is used to indicate that the rule applies to the sending
271 +  side.  When a rule affects the sending side it, prevents files from
272 +  being transferred.  The default is for a rule to affect both sides
273 +  unless bf(--delete-excluded) was specified, in which case default rules
274 +  become sender-side only.  See also the "H" (hide) rule, which is an
275 +  alias for the "-" rule with the "s" modifer.
276 +  it() An bf(r) is used to indicate that the rule applies to the receiving
277 +  side.  When a rule affects the receiving side it, prevents files from
278 +  being deleted.  See the bf(s) modifier for more info.  See also the "P"
279 +  (protect) rule, which is an alias for the "-" rule with the "r" modifier.
280  )
281  
282  Per-directory rules are inherited in all subdirectories of the directory
283 @@ -1706,10 +1733,10 @@ error.
284  When reading a batch file, rsync will force the value of certain options
285  to match the data in the batch file if you didn't set them to the same
286  as the batch-writing command.  Other options can (and should) be changed.
287 -For instance
288 -bf(--write-batch) changes to bf(--read-batch), bf(--files-from) is dropped, and the
289 -bf(--filter)/bf(--include)/bf(--exclude) options are not needed unless one of the
290 -bf(--delete) options is specified without bf(--delete-excluded).
291 +For instance bf(--write-batch) changes to bf(--read-batch),
292 +bf(--files-from) is dropped, and the
293 +bf(--filter)/bf(--include)/bf(--exclude) options are not needed unless
294 +one of the bf(--delete) options is specified.
295  
296  The code that creates the BATCH.sh file transforms any filter/include/exclude
297  options into a single list that is appended as a "here" document to the