Tweaked the output a little.
[rsync/rsync.git] / exclude.c
index 38bbd0c..11b187c 100644 (file)
--- a/exclude.c
+++ b/exclude.c
@@ -32,6 +32,7 @@ extern int recurse;
 extern int io_error;
 extern int local_server;
 extern int prune_empty_dirs;
+extern int ignore_perishable;
 extern int delete_mode;
 extern int delete_excluded;
 extern int cvs_exclude;
@@ -51,8 +52,8 @@ struct filter_list_struct server_filter_list = { 0, 0, " [daemon]" };
 #define MAX_RULE_PREFIX (16)
 
 #define MODIFIERS_MERGE_FILE "-+Cenw"
-#define MODIFIERS_INCL_EXCL "/!Crs"
-#define MODIFIERS_HIDE_PROTECT "/!"
+#define MODIFIERS_INCL_EXCL "/!Crsp"
+#define MODIFIERS_HIDE_PROTECT "/!p"
 
 /* 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
@@ -601,6 +602,8 @@ int check_filter(struct filter_list_struct *listp, char *name, int name_is_dir)
        struct filter_struct *ent;
 
        for (ent = listp->head; ent; ent = ent->next) {
+               if (ignore_perishable && ent->match_flags & MATCHFLG_PERISHABLE)
+                       continue;
                if (ent->match_flags & MATCHFLG_PERDIR_MERGE) {
                        int rc = check_filter(ent->u.mergelist, name,
                                              name_is_dir);
@@ -808,6 +811,9 @@ static const char *parse_rule_tok(const char *p, uint32 mflags, int xflags,
                        case 'n':
                                new_mflags |= MATCHFLG_NO_INHERIT;
                                break;
+                       case 'p':
+                               new_mflags |= MATCHFLG_PERISHABLE;
+                               break;
                        case 'r':
                                new_mflags |= MATCHFLG_RECEIVER_SIDE;
                                break;
@@ -880,7 +886,7 @@ static void get_cvs_excludes(uint32 mflags)
                return;
        initialized = 1;
 
-       parse_rule(&cvs_filter_list, default_cvsignore, mflags, 0);
+       parse_rule(&cvs_filter_list, default_cvsignore, mflags | MATCHFLG_PERISHABLE, 0);
 
        p = module_id >= 0 && lp_use_chroot(module_id) ? "/" : getenv("HOME");
        if (p && pathjoin(fname, MAXPATHLEN, p, ".cvsignore") < MAXPATHLEN)
@@ -906,12 +912,14 @@ void parse_rule(struct filter_list_struct *listp, const char *pattern,
                                    &pat_len, &new_mflags);
                if (!cp)
                        break;
+
+               pattern = cp + pat_len;
+
                if (pat_len >= MAXPATHLEN) {
-                       rprintf(FERROR, "discarding over-long filter: %s\n",
-                               cp);
+                       rprintf(FERROR, "discarding over-long filter: %.*s\n",
+                               (int)pat_len, cp);
                        continue;
                }
-               pattern = cp + pat_len;
 
                if (new_mflags & MATCHFLG_CLEAR_LIST) {
                        if (verbose > 2) {
@@ -931,11 +939,9 @@ void parse_rule(struct filter_list_struct *listp, const char *pattern,
                        }
                        len = pat_len;
                        if (new_mflags & MATCHFLG_EXCLUDE_SELF) {
-                               const char *name = strrchr(cp, '/');
-                               if (name)
-                                       len -= ++name - cp;
-                               else
-                                       name = cp;
+                               const char *name = cp + len;
+                               while (name > cp && name[-1] != '/') name--;
+                               len -= name - cp;
                                add_rule(listp, name, len, 0, 0);
                                new_mflags &= ~MATCHFLG_EXCLUDE_SELF;
                                len = pat_len;
@@ -1064,6 +1070,8 @@ char *get_rule_prefix(int match_flags, const char *pat, int for_xfer,
        else
                legal_len = 0;
 
+       if (match_flags & MATCHFLG_NEGATE)
+               *op++ = '!';
        if (match_flags & MATCHFLG_CVS_IGNORE)
                *op++ = 'C';
        else {
@@ -1087,6 +1095,12 @@ char *get_rule_prefix(int match_flags, const char *pat, int for_xfer,
            && (!for_xfer || protocol_version >= 29
             || (delete_excluded && am_sender)))
                *op++ = 'r';
+       if (match_flags & MATCHFLG_PERISHABLE) {
+               if (!for_xfer || protocol_version >= 30)
+                       *op++ = 'p';
+               else if (am_sender)
+                       return NULL;
+       }
        if (op - buf > legal_len)
                return NULL;
        if (legal_len)
@@ -1141,7 +1155,7 @@ static void send_rules(int f_out, struct filter_list_struct *flp)
                if (!p) {
                        rprintf(FERROR,
                                "filter rules are too modern for remote rsync.\n");
-                       exit_cleanup(RERR_SYNTAX);
+                       exit_cleanup(RERR_PROTOCOL);
                }
                if (f_out < 0)
                        continue;