head 1.2; access; symbols OPENPKG_2_STABLE_MP:1.2 OPENPKG_E1_MP_HEAD:1.2 OPENPKG_E1_MP:1.2 OPENPKG_E1_MP_2_STABLE:1.2 OPENPKG_E1_FP:1.2 OPENPKG_2_STABLE_20061018:1.2 OPENPKG_2_STABLE:1.2.0.6 OPENPKG_2_STABLE_BP:1.2 OPENPKG_2_5_SOLID:1.2.0.4 OPENPKG_2_5_SOLID_BP:1.2 OPENPKG_2_4_RELEASE:1.2 OPENPKG_2_4_SOLID:1.2.0.2 OPENPKG_2_4_SOLID_BP:1.2 OPENPKG_CW_FP:1.1 OPENPKG_2_3_RELEASE:1.1 OPENPKG_2_3_SOLID:1.1.0.2 OPENPKG_2_3_SOLID_BP:1.1; locks; strict; comment @# @; 1.2 date 2005.06.13.18.16.46; author rse; state dead; branches; next 1.1; 1.1 date 2005.01.03.14.56.28; author rse; state Exp; branches; next ; desc @@ 1.2 log @upgrading package: rsync 2.6.3 -> 2.6.5 @ text @This patch adds a --last-match command line option to RSYNC 2.6.3 which switches the include/exclude pattern processing from "first-match" (the default) to "last-match" semantics plus the possibility to specify short-circuit patterns (which stop processing immediately if matching) with the operators "-!" and "+!" in addition to the regular operators "-" and "+". The "last-match" is a super-set of the "first-match" semantics, providing more flexible include/exclude specifications by allowing arbitrary nesting of matches. Ralf S. Engelschall rse@@engelschall.com 03-Jan-2005 Index: options.c --- options.c.orig 2004-09-23 19:39:05 +0200 +++ options.c 2005-01-02 18:57:15 +0100 @@@@ -96,6 +96,7 @@@@ int checksum_seed = 0; int inplace = 0; unsigned int block_size = 0; +int last_match = 0; /** Network address family. **/ @@@@ -286,6 +287,7 @@@@ rprintf(F," --exclude-from=FILE exclude patterns listed in FILE\n"); rprintf(F," --include=PATTERN don't exclude files matching PATTERN\n"); rprintf(F," --include-from=FILE don't exclude patterns listed in FILE\n"); + rprintf(F," --last-match perform a last-match include/exclude checking\n"); rprintf(F," --files-from=FILE read FILE for list of source-file names\n"); rprintf(F," -0, --from0 all *-from file lists are delimited by nulls\n"); rprintf(F," --version print version number\n"); @@@@ -316,7 +318,7 @@@@ rprintf(F,"See http://rsync.samba.org/ for updates, bug reports, and answers\n"); } -enum {OPT_VERSION = 1000, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM, +enum {OPT_VERSION = 1000, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM, OPT_LAST_MATCH, OPT_DELETE_AFTER, OPT_DELETE_EXCLUDED, OPT_LINK_DEST, OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW, OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_TIMEOUT, @@@@ -343,6 +345,7 @@@@ {"include", 0, POPT_ARG_STRING, 0, OPT_INCLUDE, 0, 0 }, {"exclude-from", 0, POPT_ARG_STRING, 0, OPT_EXCLUDE_FROM, 0, 0 }, {"include-from", 0, POPT_ARG_STRING, 0, OPT_INCLUDE_FROM, 0, 0 }, + {"last-match", 0, POPT_ARG_NONE, 0, OPT_LAST_MATCH, 0, 0 }, {"safe-links", 0, POPT_ARG_NONE, &safe_symlinks, 0, 0, 0 }, {"help", 'h', POPT_ARG_NONE, 0, 'h', 0, 0 }, {"backup", 'b', POPT_ARG_NONE, &make_backups, 0, 0, 0 }, @@@@ -564,6 +567,10 @@@@ ? XFLG_DEF_INCLUDE : 0)); break; + case OPT_LAST_MATCH: + last_match = 1; + break; + case 'h': usage(FINFO); exit_cleanup(0); Index: rsync.h --- rsync.h.orig 2004-09-22 06:10:10 +0200 +++ rsync.h 2005-01-02 19:00:57 +0100 @@@@ -500,6 +500,7 @@@@ #define MATCHFLG_INCLUDE (1<<4) /* this is an include, not an exclude */ #define MATCHFLG_DIRECTORY (1<<5) /* this matches only directories */ #define MATCHFLG_CLEAR_LIST (1<<6) /* this item is the "!" token */ +#define MATCHFLG_SHORT_CIRCUIT (1<<7) /* this item stops processing */ struct exclude_struct { struct exclude_struct *next; char *pattern; Index: exclude.c --- exclude.c.orig 2004-09-22 06:11:15 +0200 +++ exclude.c 2005-01-03 15:47:03 +0100 @@@@ -30,6 +30,7 @@@@ extern int eol_nulls; extern int list_only; extern int recurse; +extern int last_match; extern char curr_dir[]; @@@@ -219,14 +220,23 @@@@ int check_exclude(struct exclude_list_struct *listp, char *name, int name_is_dir) { struct exclude_struct *ent; + struct exclude_struct *ent_last = NULL; for (ent = listp->head; ent; ent = ent->next) { if (check_one_exclude(name, ent, name_is_dir)) { - report_exclude_result(name, ent, name_is_dir, - listp->debug_type); - return ent->match_flags & MATCHFLG_INCLUDE ? 1 : -1; + if (last_match && !(ent->match_flags & MATCHFLG_SHORT_CIRCUIT)) { + ent_last = ent; + } + else { + report_exclude_result(name, ent, name_is_dir, listp->debug_type); + return ent->match_flags & MATCHFLG_INCLUDE ? 1 : -1; + } } } + if (ent_last != NULL) { + report_exclude_result(name, ent_last, name_is_dir, listp->debug_type); + return ent_last->match_flags & MATCHFLG_INCLUDE ? 1 : -1; + } return 0; } @@@@ -259,6 +269,12 @@@@ if (*s == '+') mflags |= MATCHFLG_INCLUDE; s += 2; + } else if (!(xflags & XFLG_WORDS_ONLY) + && last_match && strlen(s) >= 3 && (s[0] == '-' || s[0] == '+') && s[1] == '!' && s[2] == ' ') { + mflags |= MATCHFLG_SHORT_CIRCUIT; + if (*s == '+') + mflags |= MATCHFLG_INCLUDE; + s += 3; } else if (xflags & XFLG_DEF_INCLUDE) mflags |= MATCHFLG_INCLUDE; if (xflags & XFLG_DIRECTORY) @@@@ -323,7 +339,7 @@@@ int xflags) { FILE *fp; - char line[MAXPATHLEN+3]; /* Room for "x " prefix and trailing slash. */ + char line[MAXPATHLEN+4]; /* Room for "x " prefix and trailing slash. */ char *eob = line + sizeof line - 1; int word_split = xflags & XFLG_WORD_SPLIT; @@@@ -403,10 +419,16 @@@@ if (ent->match_flags & MATCHFLG_INCLUDE) { write_int(f, l + 2); - write_buf(f, "+ ", 2); + if (ent->match_flags & MATCHFLG_SHORT_CIRCUIT) + write_buf(f, "+! ", 3); + else + write_buf(f, "+ ", 2); } else if ((*p == '-' || *p == '+') && p[1] == ' ') { write_int(f, l + 2); - write_buf(f, "- ", 2); + if (ent->match_flags & MATCHFLG_SHORT_CIRCUIT) + write_buf(f, "-! ", 3); + else + write_buf(f, "- ", 2); } else write_int(f, l); write_buf(f, p, l); @ 1.1 log @apply my patch for adding a --last-match option which makes rsync's include/exclude facility really usable the first time IMHO @ text @@