static struct exclude_struct **exclude_list;
+/*
+ * Optimization for special case when all included files are explicitly
+ * listed without wildcards in the "exclude" list followed by a "- *"
+ * to exclude the rest.
+ * Contributed by Dave Dykstra <dwd@bell-labs.com>
+ */
+static int only_included_files = 1;
+static struct exclude_struct *exclude_the_rest;
+
+int send_included_file_names(int f,struct file_list *flist)
+{
+ struct exclude_struct *ex, **ex_list;
+ int n;
+ char *p;
+
+ if (!only_included_files || (exclude_the_rest == NULL))
+ return 0;
+
+ if (verbose > 1) {
+ rprintf(FINFO,"(using include-only optimization) ");
+ }
+
+ /* set exclude_list to NULL temporarily so check_exclude */
+ /* will always return true */
+ ex_list = exclude_list;
+ exclude_list = NULL;
+ for (n=0; (ex = ex_list[n]) != NULL; n++) {
+ if (ex == exclude_the_rest)
+ break;
+ p = ex->pattern;
+ while (*p == '/') {
+ /* skip the allowed beginning slashes */
+ p++;
+ }
+ send_file_name(f,flist,p,0,0);
+ }
+ exclude_list = ex_list;
+
+ return 1;
+}
+
/* build an exclude structure given a exclude pattern */
static struct exclude_struct *make_exclude(char *pattern, int include)
{
memset(ret, 0, sizeof(*ret));
- ret->orig = strdup(pattern);
-
if (strncmp(pattern,"- ",2) == 0) {
pattern += 2;
} else if (strncmp(pattern,"+ ",2) == 0) {
ret->pattern = strdup(pattern);
- if (!ret->orig || !ret->pattern) out_of_memory("make_exclude");
-
- if (strpbrk(pattern, "*[?")) ret->regular_exp = 1;
+ if (!ret->pattern) out_of_memory("make_exclude");
+
+ if (strpbrk(pattern, "*[?")) {
+ if (!ret->include && (*pattern == '*') && (*(pattern+1) == '\0')) {
+ exclude_the_rest = ret;
+ } else {
+ only_included_files = 0;
+ }
+ ret->regular_exp = 1;
+ } else if (!ret->include) {
+ only_included_files = 0;
+ }
if (strlen(pattern) > 1 && pattern[strlen(pattern)-1] == '/') {
ret->pattern[strlen(pattern)-1] = 0;
static void free_exclude(struct exclude_struct *ex)
{
- free(ex->orig);
free(ex->pattern);
memset(ex,0,sizeof(*ex));
free(ex);
{
int n;
+ if (name && (name[0] == '.') && !name[1])
+ /* never exclude '.', even if somebody does --exclude '*' */
+ return 0;
+
if (exclude_list) {
for (n=0; exclude_list[n]; n++)
if (check_one_exclude(name,exclude_list[n],st))
}
free((*list));
*list = NULL;
+ only_included_files = 1;
+ exclude_the_rest = NULL;
return;
}
if (!f) {
if (fatal) {
rprintf(FERROR,"%s : %s\n",fname,strerror(errno));
- exit_cleanup(1);
+ exit_cleanup(RERR_FILEIO);
}
return list;
}
}
for (i=0;exclude_list[i];i++) {
- char *pattern = exclude_list[i]->orig;
+ char *pattern = exclude_list[i]->pattern;
int l;
- if (remote_version < 19) {
- if (strncmp(pattern,"+ ", 2)==0) {
+ l = strlen(pattern);
+ if (l == 0) continue;
+ if (exclude_list[i]->include) {
+ if (remote_version < 19) {
rprintf(FERROR,"remote rsync does not support include syntax - aborting\n");
- exit_cleanup(1);
- }
-
- if (strncmp(pattern,"- ", 2) == 0) {
- pattern += 2;
+ exit_cleanup(RERR_UNSUPPORTED);
}
+ write_int(f,l+2);
+ write_buf(f,"+ ",2);
+ } else {
+ write_int(f,l);
}
-
- l = strlen(pattern);
- if (l == 0) continue;
- write_int(f,l);
write_buf(f,pattern,l);
}
free(p);
}
+void add_include_line(char *p)
+{
+ char *tok;
+ if (!p || !*p) return;
+ p = strdup(p);
+ if (!p) out_of_memory("add_include_line");
+ for (tok=strtok(p," "); tok; tok=strtok(NULL," "))
+ add_exclude(tok, 1);
+ free(p);
+}
+
static char *cvs_ignore_list[] = {
"RCS","SCCS","CVS","CVS.adm","RCSLOG","cvslog.*",
add_exclude(cvs_ignore_list[i], 0);
if ((p=getenv("HOME")) && strlen(p) < (MAXPATHLEN-12)) {
- slprintf(fname,sizeof(fname)-1, "%s/.cvsignore",p);
+ slprintf(fname,sizeof(fname), "%s/.cvsignore",p);
add_exclude_file(fname,0,0);
}