+++ /dev/null
-This patch adds two modifiers to the filter rule prefixes that allow a
-rule to be marked as sender-side (s), receiver-side (r), or both ("sr"
-or omitted). Sender-side rules prevent files from being transferred,
-while receiver-side rules prevent files from being deleted. The default
-for an unmodified include/exclude rule is to affect both sides, but a
-rule that is explicitly marked as affecting both sides will remain
-unaffected by the --delete-excluded option (that option changes any
-unmodified rules into server-side only rules).
-
-See the updated manpage for the details.
-
---- orig/exclude.c 2005-02-11 10:53:14
-+++ exclude.c 2005-02-12 19:08:30
-@@ -53,7 +53,8 @@ struct filter_list_struct server_filter_
- #define MAX_RULE_PREFIX (16)
-
- #define MODIFIERS_MERGE_FILE "-+Cenw"
--#define MODIFIERS_INCL_EXCL "/!C"
-+#define MODIFIERS_INCL_EXCL "/!Crs"
-+#define MODIFIERS_HIDE_PROTECT "/!"
-
- /* The dirbuf is set by push_local_filters() to the current subdirectory
- * relative to curr_dir that is being processed. The path always has a
-@@ -678,6 +679,10 @@ static const char *parse_rule_tok(const
- if ((s = RULE_STRCMP(s, "exclude")) != NULL)
- ch = '-';
- break;
-+ case 'h':
-+ if ((s = RULE_STRCMP(s, "hide")) != NULL)
-+ ch = 'H';
-+ break;
- case 'i':
- if ((s = RULE_STRCMP(s, "include")) != NULL)
- ch = '+';
-@@ -686,6 +691,19 @@ static const char *parse_rule_tok(const
- if ((s = RULE_STRCMP(s, "merge")) != NULL)
- ch = '.';
- break;
-+ case 'p':
-+ if ((s = RULE_STRCMP(s, "protect")) != NULL)
-+ ch = 'P';
-+ break;
-+ case 'r':
-+ if ((s = RULE_STRCMP(s, "risk")) != NULL)
-+ ch = 'R';
-+ break;
-+ case 's':
-+ if ((s = RULE_STRCMP(s, "show")) != NULL)
-+ ch = 'S';
-+ break;
-+
- default:
- ch = *s;
- if (s[1] == ',')
-@@ -707,6 +725,20 @@ static const char *parse_rule_tok(const
- case '-':
- mods = MODIFIERS_INCL_EXCL;
- break;
-+ case 'S':
-+ new_mflags |= MATCHFLG_INCLUDE;
-+ /* FALL THROUGH */
-+ case 'H':
-+ new_mflags |= MATCHFLG_SENDER_SIDE;
-+ mods = MODIFIERS_HIDE_PROTECT;
-+ break;
-+ case 'R':
-+ new_mflags |= MATCHFLG_INCLUDE;
-+ /* FALL THROUGH */
-+ case 'P':
-+ new_mflags |= MATCHFLG_RECEIVER_SIDE;
-+ mods = MODIFIERS_HIDE_PROTECT;
-+ break;
- case '!':
- new_mflags |= MATCHFLG_CLEAR_LIST;
- mods = NULL;
-@@ -759,6 +791,12 @@ static const char *parse_rule_tok(const
- case 'n':
- new_mflags |= MATCHFLG_NO_INHERIT;
- break;
-+ case 'r':
-+ new_mflags |= MATCHFLG_RECEIVER_SIDE;
-+ break;
-+ case 's':
-+ new_mflags |= MATCHFLG_SENDER_SIDE;
-+ break;
- case 'w':
- new_mflags |= MATCHFLG_WORD_SPLIT;
- break;
-@@ -1013,6 +1051,13 @@ char *get_rule_prefix(int match_flags, c
- }
- if (match_flags & MATCHFLG_EXCLUDE_SELF)
- *op++ = 'e';
-+ if (match_flags & MATCHFLG_SENDER_SIDE
-+ && (!for_xfer || protocol_version >= 29))
-+ *op++ = 's';
-+ if (match_flags & MATCHFLG_RECEIVER_SIDE
-+ && (!for_xfer || protocol_version >= 29
-+ || (delete_excluded && am_sender)))
-+ *op++ = 'r';
- if (legal_len)
- *op++ = ' ';
- if (op - buf > legal_len)
-@@ -1025,18 +1070,34 @@ char *get_rule_prefix(int match_flags, c
-
- static void send_rules(int f_out, struct filter_list_struct *flp)
- {
-- struct filter_struct *ent;
-+ struct filter_struct *ent, *prev = NULL;
-
- for (ent = flp->head; ent; ent = ent->next) {
- unsigned int len, plen, dlen;
-+ int elide = 0;
- char *p;
-
-+ if (ent->match_flags & MATCHFLG_SENDER_SIDE)
-+ elide = am_sender ? 1 : -1;
-+ if (ent->match_flags & MATCHFLG_RECEIVER_SIDE)
-+ elide = elide ? 0 : am_sender ? -1 : 1;
-+ else if (delete_excluded)
-+ elide = am_sender ? 1 : -1;
-+ if (elide < 0) {
-+ if (prev)
-+ prev->next = ent->next;
-+ else
-+ flp->head = ent->next;
-+ } else
-+ prev = ent;
-+ if (elide > 0)
-+ continue;
- if (ent->match_flags & MATCHFLG_CVS_IGNORE
- && !(ent->match_flags & MATCHFLG_MERGE_FILE)) {
-- if (am_sender || protocol_version < 29) {
-- send_rules(f_out, &cvs_filter_list);
-+ int f = am_sender || protocol_version < 29 ? f_out : -1;
-+ send_rules(f, &cvs_filter_list);
-+ if (f >= 0)
- continue;
-- }
- }
- p = get_rule_prefix(ent->match_flags, ent->pattern, 1, &plen);
- if (!p) {
-@@ -1044,6 +1105,8 @@ static void send_rules(int f_out, struct
- "filter rules are too modern for remote rsync.\n");
- exit_cleanup(RERR_SYNTAX);
- }
-+ if (f_out < 0)
-+ continue;
- len = strlen(ent->pattern);
- dlen = ent->match_flags & MATCHFLG_DIRECTORY ? 1 : 0;
- if (!(plen + len + dlen))
-@@ -1055,12 +1118,14 @@ static void send_rules(int f_out, struct
- if (dlen)
- write_byte(f_out, '/');
- }
-+ flp->tail = prev;
- }
-
- /* This is only called by the client. */
- void send_filter_list(int f_out)
- {
-- int receiver_wants_list = delete_mode && !delete_excluded;
-+ int receiver_wants_list = delete_mode
-+ && (!delete_excluded || protocol_version >= 29);
-
- if (local_server || (am_sender && !receiver_wants_list))
- f_out = -1;
-@@ -1075,10 +1140,10 @@ void send_filter_list(int f_out)
- if (list_only == 1 && !recurse)
- parse_rule(&filter_list, "/*/*", MATCHFLG_NO_PREFIXES, 0);
-
-- if (f_out >= 0) {
-- send_rules(f_out, &filter_list);
-+ send_rules(f_out, &filter_list);
-+
-+ if (f_out >= 0)
- write_int(f_out, 0);
-- }
-
- if (cvs_exclude) {
- if (!am_sender || protocol_version < 29)
-@@ -1093,8 +1158,9 @@ void recv_filter_list(int f_in)
- {
- char line[MAXPATHLEN+MAX_RULE_PREFIX+1]; /* +1 for trailing slash. */
- int xflags = protocol_version >= 29 ? 0 : XFLG_OLD_PREFIXES;
-+ int receiver_wants_list = delete_mode
-+ && (!delete_excluded || protocol_version >= 29);
- unsigned int len;
-- int receiver_wants_list = delete_mode && !delete_excluded;
-
- if (!local_server && (am_sender || receiver_wants_list)) {
- while ((len = read_int(f_in)) != 0) {
-@@ -1111,4 +1177,7 @@ void recv_filter_list(int f_in)
- if (local_server || am_sender)
- parse_rule(&filter_list, "-C", 0, 0);
- }
-+
-+ if (local_server) /* filter out any rules that aren't for us. */
-+ send_rules(-1, &filter_list);
- }
---- orig/flist.c 2005-02-12 18:39:09
-+++ flist.c 2005-02-12 19:08:31
-@@ -64,7 +64,6 @@ extern int copy_links;
- extern int copy_unsafe_links;
- extern int protocol_version;
- extern int sanitize_paths;
--extern int delete_excluded;
- extern int max_delete;
- extern int orig_umask;
- extern int list_only;
-@@ -976,11 +975,7 @@ void send_file_name(int f, struct file_l
- struct file_struct *file;
- char fbuf[MAXPATHLEN];
-
-- /* f is set to -1 when calculating deletion file list */
-- file = make_file(fname, flist,
-- f == -1 && delete_excluded? SERVER_FILTERS : ALL_FILTERS);
--
-- if (!file)
-+ if (!(file = make_file(fname, flist, ALL_FILTERS)))
- return;
-
- maybe_emit_filelist_progress(flist);
---- orig/rsync.h 2005-02-07 20:41:57
-+++ rsync.h 2005-02-12 19:08:34
-@@ -565,9 +565,12 @@ struct map_struct {
- #define MATCHFLG_FINISH_SETUP (1<<13)/* per-dir merge file needs setup */
- #define MATCHFLG_NEGATE (1<<14)/* rule matches when pattern does not */
- #define MATCHFLG_CVS_IGNORE (1<<15)/* rule was -C or :C */
-+#define MATCHFLG_SENDER_SIDE (1<<16)/* rule applies to the sending side */
-+#define MATCHFLG_RECEIVER_SIDE (1<<17)/* rule applies to the receiving side */
-
- #define MATCHFLGS_FROM_CONTAINER (MATCHFLG_ABS_PATH | MATCHFLG_INCLUDE \
-- | MATCHFLG_DIRECTORY | MATCHFLG_NEGATE)
-+ | MATCHFLG_DIRECTORY | MATCHFLG_SENDER_SIDE \
-+ | MATCHFLG_NEGATE | MATCHFLG_RECEIVER_SIDE)
-
- struct filter_struct {
- struct filter_struct *next;
---- orig/rsync.yo 2005-02-11 23:14:49
-+++ rsync.yo 2005-02-12 19:08:37
-@@ -679,7 +679,9 @@ send the whole directory (e.g. "dir" or
- for the directory's contents (e.g. "dir/*") since the wildcard is expanded
- by the shell and rsync thus gets a request to transfer individual files, not
- the files' parent directory. Files that are excluded from transfer are
--excluded from being deleted unless you use bf(--delete-excluded).
-+also excluded from being deleted unless you use the bf(--delete-excluded)
-+option or mark the rules as only matching on the sending side (see the
-+include/exclude modifiers in the FILTER RULES section).
-
- This option has no effect unless directory recursion is enabled.
-
-@@ -726,6 +728,9 @@ See bf(--delete) (which is implied) for
- dit(bf(--delete-excluded)) In addition to deleting the files on the
- receiving side that are not on the sending side, this tells rsync to also
- delete any files on the receiving side that are excluded (see bf(--exclude)).
-+See the FILTER RULES section for a way to make individual exclusions behave
-+this way on the receiver, and for a way to protect files from
-+bf(--delete-excluded).
- See bf(--delete) (which is implied) for more details on file-deletion.
-
- dit(bf(--ignore-errors)) Tells bf(--delete) to go ahead and delete files
-@@ -1255,6 +1260,10 @@ bf(exclude, -) specifies an exclude patt
- bf(include, +) specifies an include pattern. nl()
- bf(merge, .) specifies a merge-file to read for more rules. nl()
- bf(dir-merge, :) specifies a per-directory merge-file. nl()
-+bf(hide, H) specifies a pattern for hiding files from the transfer. nl()
-+bf(show, S) files that match the pattern are not hidden. nl()
-+bf(protect, P) specifies a pattern for protecting files from deletion. nl()
-+bf(risk, R) files that match the pattern are not protected. nl()
- bf(clear, !) clears the current include/exclude list (takes no arg) nl()
- )
-
-@@ -1279,8 +1288,8 @@ the bf(--include-from)/bf(--exclude-from
-
- manpagesection(INCLUDE/EXCLUDE PATTERN RULES)
-
--You can include and exclude files by specifying patterns using the "+" and
--"-" filter rules (as introduced in the FILTER RULES section above).
-+You can include and exclude files by specifying patterns using the "+",
-+"-", etc. filter rules (as introduced in the FILTER RULES section above).
- The include/exclude rules each specify a pattern that is matched against
- the names of the files that are going to be transferred. These patterns
- can take several forms:
-@@ -1419,7 +1428,9 @@ itemize(
- it() You may also specify any of the modifiers for the "+" or "-" rules
- (below) in order to have the rules that are read-in from the file
- default to having that modifier set. For instance, "merge,-/ .excl" would
-- treat the contents of .excl as absolute-path excludes.
-+ treat the contents of .excl as absolute-path excludes,
-+ while "dir-merge,s .filt" and ":sC" would each make all their
-+ per-directory rules apply only on the server side.
- )
-
- The following modifiers are accepted after a "+" or "-":
-@@ -1435,7 +1446,18 @@ itemize(
- it() A bf(C) is used to indicate that all the global CVS-exclude rules
- should be inserted as excludes in place of the "-C". No arg should
- follow.
-- )
-+ it() An bf(s) is used to indicate that the rule applies to the sending
-+ side. When a rule affects the sending side, it prevents files from
-+ being transferred. The default is for a rule to affect both sides
-+ unless bf(--delete-excluded) was specified, in which case default rules
-+ become sender-side only. See also the hide (H) and show (S) rules,
-+ which are an alternate way to specify server-side includes/excludes.
-+ it() An bf(r) is used to indicate that the rule applies to the receiving
-+ side. When a rule affects the receiving side, it prevents files from
-+ being deleted. See the bf(s) modifier for more info. See also the
-+ protect (P) and risk (R) rules, which are an alternate way to
-+ specify receiver-side includes/excludes.
-+)
-
- Per-directory rules are inherited in all subdirectories of the directory
- where the merge-file was found unless the 'n' modifier was used. Each