Here's a more complex version of the wildcard change that attempts to
count slashes in the pattern (if it does not contain "**" anywhere) and
to match at the appropriate level.

In trying to think up patterns where this might mess up, the only thing
I thought of was something like this:

     foo/b[^/]r/baz

My code would mess this up by counting 3 slashes.

This patch is not based on the previous one, but on CVS.

Note that neither this patch nor my previous one makes "**/foo" match
the file matched by "/foo" (which one might expect it to do).  We could
add some extra code to make this happen, if desired.

Optimization note:  I noticed that both this patch and my previous one
were only checking for "**" at the start of the pattern to trigger the
loop-skipping optimization.  I should really change that to check for
any leading "*" because of the code's limitation of treating "*" like
"**" when "**" is on the line somewhere.

..wayne..

---8<------8<------8<------8<---cut here--->8------>8------>8------>8---
Index: exclude.c
--- exclude.c   2002/04/11 02:25:53     1.44
+++ exclude.c   2002/05/13 20:30:33
@@ -35,6 +35,7 @@
 static struct exclude_struct *make_exclude(const char *pattern, int include)
 {
        struct exclude_struct *ret;
+       char *cp;
 
        ret = (struct exclude_struct *)malloc(sizeof(*ret));
        if (!ret) out_of_memory("make_exclude");
@@ -55,7 +56,7 @@
        if (!ret->pattern) out_of_memory("make_exclude");
 
        if (strpbrk(pattern, "*[?")) {
-           ret->regular_exp = 1;
+           ret->wild_exp = 1;
            ret->fnmatch_flags = FNM_PATHNAME;
            if (strstr(pattern, "**")) {
                    static int tested;
@@ -66,6 +67,8 @@
                            }
                    }
                    ret->fnmatch_flags = 0;
+                   if (strncmp(pattern, "**", 2) == 0)
+                           ret->wild_exp = -1;
            }
        }
 
@@ -74,9 +77,8 @@
                ret->directory = 1;
        }
 
-       if (!strchr(ret->pattern,'/')) {
-               ret->local = 1;
-       }
+       for (cp = ret->pattern; (cp = strchr(cp, '/')) != NULL; cp++)
+               ret->slash_cnt++;
 
        return ret;
 }
@@ -95,7 +97,7 @@
        int match_start=0;
        char *pattern = ex->pattern;
 
-       if (ex->local && (p=strrchr(name,'/')))
+       if (!ex->slash_cnt && (p=strrchr(name,'/')))
                name = p+1;
 
        if (!name[0]) return 0;
@@ -107,9 +109,24 @@
                pattern++;
        }
 
-       if (ex->regular_exp) {
+       if (ex->wild_exp) {
+               if (!match_start && ex->slash_cnt && ex->fnmatch_flags != 0) {
+                       int cnt = ex->slash_cnt + 1;
+                       for (p = name + strlen(name) - 1; p >= name; p--) {
+                               if (*p == '/' && !--cnt)
+                                       break;
+                       }
+                       name = p+1;
+               }
                if (fnmatch(pattern, name, ex->fnmatch_flags) == 0) {
                        return 1;
+               }
+               if (!ex->fnmatch_flags && !match_start && ex->wild_exp > 0) {
+                       while ((name = strchr(name, '/')) != NULL) {
+                               name++;
+                               if (fnmatch(pattern, name, ex->fnmatch_flags) == 0)
+                                       return 1;
+                       }
                }
        } else {
                int l1 = strlen(name);
Index: rsync.h
--- rsync.h     2002/04/11 02:18:51     1.131
+++ rsync.h     2002/05/13 20:30:34
@@ -392,11 +392,11 @@
 
 struct exclude_struct {
        char *pattern;
-       int regular_exp;
+       int wild_exp;
        int fnmatch_flags;
        int include;
        int directory;
-       int local;
+       int slash_cnt;
 };
 
 struct stats {
---8<------8<------8<------8<---cut here--->8------>8------>8------>8---


-- 
To unsubscribe or change options: http://lists.samba.org/mailman/listinfo/rsync
Before posting, read: http://www.tuxedo.org/~esr/faqs/smart-questions.html

Reply via email to