> I like the idea of your rsync-exclude.patch and have thought > about hacking it in myself. However as you already have done the work > may I make a small suggestion...... can the name of the exclude file > (your .rsync) be specified in the flags.... e.g. > > rsync --rsync-exclude=.snapshot -axvH /here /there > > In this way different invocations (e.g. system and personal) can exclude > different files. > > Anthony R Iano-Fletcher [EMAIL PROTECTED] > http://cbel.cit.nih.gov/~arif > CBEL, CIT, NIH, Bethesda, MD, USA.
A good idea. I have implemented this as http://www.math.ualberta.ca/imaging/rlbackup/rsync-exclude-file.patch Unfortunately, backwards compatibility with the previous syntax rsync --rsync-exclude -axvH /here /there does not appear to be possible, because of deficiencies in the popt option routines relative to getopt_long: popt doesn't really handle optional arguments correctly, even with POPT_ARGFLAG_OPTIONAL. Anyway, below is the new version of the --rsync-exclude patch. This is a useful and general enough feature that I hope it will be added to the next release of rsync. -- John Bowman University of Alberta This is a patch to add an --rsync-exclude=FILE option to rsync-2.5.6. Patterns in FILE are used to recursively exclude/include files in a directory and all of its subdirectories. For example, rsync --rsync-exclude=.rsync -vaxH /here /there will copy all files from /here to /there, excluding any files listed in a file .rsync from the directory containing this file and all of its subdirectories. As usual, prefixing a pattern with "+ " forces inclusion rather than exclusion. This has advantages over --cvs-exclude for backing up large file systems since the .cvsignore files only apply to the current directory: unless the .cvsignore restrictions apply to the entire tree they must be duplicated in each subdirectory. In any case, the --cvs-exclude option isn't intended for general system backups (for example, unless the default list is cleared with "!", it automatically excludes *.a and *.so libraries). diff -ru rsync-2.5.6/exclude.c rsync-2.5.6J/exclude.c --- rsync-2.5.6/exclude.c Sun Jan 26 13:10:23 2003 +++ rsync-2.5.6J/exclude.c Wed Jan 29 17:16:39 2003 @@ -127,6 +127,7 @@ static void report_exclude_result(char const *name, struct exclude_struct const *ent, + char const *type, STRUCT_STAT const *st) { /* If a trailing slash is present to match only directories, @@ -134,10 +135,10 @@ * case we add it back in here. */ if (verbose >= 2) - rprintf(FINFO, "%s %s %s because of pattern %s%s\n", + rprintf(FINFO, "%s %s %s because of %s pattern %s%s\n", ent->include ? "including" : "excluding", S_ISDIR(st->st_mode) ? "directory" : "file", - name, ent->pattern, + name, type, ent->pattern, ent->directory ? "/" : ""); } @@ -147,6 +148,7 @@ * LOCAL_EXCLUDE_LIST or the globals EXCLUDE_LIST. */ int check_exclude(char *name, struct exclude_struct **local_exclude_list, + struct exclude_struct **recur_local_exclude_list, STRUCT_STAT *st) { int n; @@ -156,21 +158,37 @@ /* never exclude '.', even if somebody does --exclude '*' */ return 0; - if (exclude_list) { - for (n=0; exclude_list[n]; n++) { - ent = exclude_list[n]; + /* Precedence: use the most local and most recent matching pattern, + in this order: FILE, .cvsignore, --exclude */ + + if (recur_local_exclude_list) { + for (n=0; recur_local_exclude_list[n]; n++) ; + for (n--; n >= 0; n--) { + ent = recur_local_exclude_list[n]; if (check_one_exclude(name, ent, st)) { - report_exclude_result(name, ent, st); + report_exclude_result(name, ent, "rsync", st); return !ent->include; } } } if (local_exclude_list) { - for (n=0; local_exclude_list[n]; n++) { + for (n=0; local_exclude_list[n]; n++) ; + for (n--; n >= 0; n--) { ent = local_exclude_list[n]; if (check_one_exclude(name, ent, st)) { - report_exclude_result(name, ent, st); + report_exclude_result(name, ent, "cvsignore", st); + return !ent->include; + } + } + } + + if (exclude_list) { + for (n=0; exclude_list[n]; n++) ; + for (n--; n >= 0; n--) { + ent = exclude_list[n]; + if (check_one_exclude(name, ent, st)) { + report_exclude_result(name, ent, "global", st); return !ent->include; } } diff -ru rsync-2.5.6/flist.c rsync-2.5.6J/flist.c --- rsync-2.5.6/flist.c Sat Jan 18 11:00:23 2003 +++ rsync-2.5.6J/flist.c Thu Feb 13 09:59:40 2003 @@ -39,6 +39,7 @@ extern int always_checksum; extern int cvs_exclude; +extern const char *rsync_exclude; extern int recurse; @@ -62,6 +63,7 @@ extern int write_batch; static struct exclude_struct **local_exclude_list; +static struct exclude_struct **recur_local_exclude_list; static struct file_struct null_file; @@ -258,7 +260,8 @@ if ((f == -1) && delete_excluded) { return 0; } - if (check_exclude(fname, local_exclude_list, st)) { + if (check_exclude(fname, local_exclude_list, + recur_local_exclude_list, st)) { return 1; } return 0; @@ -773,7 +776,32 @@ return file; } +static struct exclude_struct **copy_exclude_list(struct exclude_struct **from) { + struct exclude_struct **to; + int i; + int len=0; + int size; + + if (!from) return NULL; + + for (; from[len]; len++) ; + size=sizeof(struct exclude_struct *)*(len+1); + to = (struct exclude_struct **) malloc(size); + if (!to) out_of_memory("copy_exclude_list"); + + size=sizeof(struct exclude_struct); + for (i=0; i < len; i++) { + struct exclude_struct *p; + p=to[i]=(struct exclude_struct *) malloc(size); + if (!p) out_of_memory("copy_exclude_list"); + *p=*from[i]; + p->pattern=strdup(from[i]->pattern); + if (!p->pattern) out_of_memory("copy_exclude_list"); + } + to[len]=NULL; + return to; +} void send_file_name(int f, struct file_list *flist, char *fname, int recursive, unsigned base_flags) @@ -800,8 +828,11 @@ if (S_ISDIR(file->mode) && recursive) { struct exclude_struct **last_exclude_list = local_exclude_list; + struct exclude_struct **recur_last_exclude_list = + recur_local_exclude_list; send_directory(f, flist, f_name(file)); local_exclude_list = last_exclude_list; + recur_local_exclude_list = recur_last_exclude_list; return; } } @@ -840,6 +871,7 @@ p = fname + strlen(fname); local_exclude_list = NULL; + recur_local_exclude_list = copy_exclude_list(recur_local_exclude_list); if (cvs_exclude) { if (strlen(fname) + strlen(".cvsignore") <= MAXPATHLEN - 1) { @@ -854,6 +886,19 @@ } } + if (rsync_exclude) { + if (strlen(fname) + strlen(rsync_exclude) <= MAXPATHLEN - 1) { + strcpy(p, rsync_exclude); + recur_local_exclude_list = + make_exclude_list(fname, recur_local_exclude_list, 0, 0); + } else { + io_error = 1; + rprintf(FINFO, + "cannot cvs-exclude in long-named directory %s\n", + fname); + } + } + for (di = readdir(d); di; di = readdir(d)) { char *dname = d_name(di); if (strcmp(dname, ".") == 0 || strcmp(dname, "..") == 0) @@ -866,6 +911,10 @@ add_exclude_list("!", &local_exclude_list, 0); } + if (recur_local_exclude_list) { + add_exclude_list("!", &recur_local_exclude_list, 0); + } + closedir(d); } @@ -887,6 +936,8 @@ if (show_filelist_p() && f != -1) start_filelist_progress("building file list"); + recur_local_exclude_list = NULL; + start_write = stats.total_written; flist = flist_new(); diff -ru rsync-2.5.6/options.c rsync-2.5.6J/options.c --- rsync-2.5.6/options.c Mon Jan 27 20:11:57 2003 +++ rsync-2.5.6J/options.c Thu Feb 13 11:13:01 2003 @@ -45,6 +45,7 @@ int preserve_times = 0; int update_only = 0; int cvs_exclude = 0; +const char *rsync_exclude = NULL; int dry_run=0; int local_server=0; int ignore_times=0; @@ -84,7 +85,6 @@ int modify_window=0; int blocking_io=-1; - /** Network address family. **/ #ifdef INET6 int default_af_hint = 0; /* Any protocol */ @@ -233,6 +233,7 @@ rprintf(F," -e, --rsh=COMMAND specify the remote shell\n"); rprintf(F," --rsync-path=PATH specify path to rsync on the remote machine\n"); rprintf(F," -C, --cvs-exclude auto ignore files in the same way CVS does\n"); + rprintf(F," --rsync-exclude=FILE recursively exclude files listed in +FILE\n"); rprintf(F," --existing only update files that already exist\n"); rprintf(F," --ignore-existing ignore files that already exist on the receiving side\n"); rprintf(F," --delete delete files that don't exist on the sending side\n"); @@ -320,6 +321,7 @@ {"dry-run", 'n', POPT_ARG_NONE, &dry_run , 0, 0, 0 }, {"sparse", 'S', POPT_ARG_NONE, &sparse_files , 0, 0, 0 }, {"cvs-exclude", 'C', POPT_ARG_NONE, &cvs_exclude , 0, 0, 0 }, + {"rsync-exclude", 0, POPT_ARG_STRING, &rsync_exclude , 0, 0, 0 }, {"update", 'u', POPT_ARG_NONE, &update_only , 0, 0, 0 }, {"links", 'l', POPT_ARG_NONE, &preserve_links , 0, 0, 0 }, {"copy-links", 'L', POPT_ARG_NONE, ©_links , 0, 0, 0 }, diff -ru rsync-2.5.6/proto.h rsync-2.5.6J/proto.h --- rsync-2.5.6/proto.h Sun Jan 26 20:35:09 2003 +++ rsync-2.5.6J/proto.h Wed Jan 29 17:16:39 2003 @@ -58,6 +58,7 @@ void setup_protocol(int f_out,int f_in); int claim_connection(char *fname,int max_connections); int check_exclude(char *name, struct exclude_struct **local_exclude_list, + struct exclude_struct **recur_local_exclude_list, STRUCT_STAT *st); void add_exclude_list(const char *pattern, struct exclude_struct ***list, int include); void add_exclude(const char *pattern, int include); diff -ru rsync-2.5.6/rsync.yo rsync-2.5.6J/rsync.yo --- rsync-2.5.6/rsync.yo Mon Jan 27 20:11:57 2003 +++ rsync-2.5.6J/rsync.yo Thu Feb 13 11:57:07 2003 @@ -311,6 +311,7 @@ -e, --rsh=COMMAND specify the remote shell to use --rsync-path=PATH specify path to rsync on the remote machine -C, --cvs-exclude auto ignore files in the same way CVS does + --rsync-exclude=FILE recursively exclude files listed in FILE --existing only update files that already exist --ignore-existing ignore files that already exist on the receiving side --delete delete files that don't exist on the sending side @@ -654,6 +655,12 @@ .cvsignore file and matches one of the patterns listed therein. See the bf(cvs(1)) manual for more information. +dit(bf(--rsync-exclude=FILE)) Patterns in FILE are excluded from the file +lists associated with the current directory and all of its subdirectories. +Prefixing the file name with "+ " will force inclusion of the file. +If there are multiplying matching patterns, the most local and most recent +matching pattern will be used, in this order: FILE, .cvsignore, --exclude. + dit(bf(--csum-length=LENGTH)) By default the primary checksum used in rsync is a very strong 16 byte MD4 checksum. In most cases you will find that a truncated version of this checksum is quite efficient, and -- To unsubscribe or change options: http://lists.samba.org/mailman/listinfo/rsync Before posting, read: http://www.tuxedo.org/~esr/faqs/smart-questions.html