Richard,
I would kindly ask you to consider this patch for inclusion into
fossil trunk. It allows for characters like *?[] to be used in
filenames. It also adds escaped characters to glob patterns. More
specifically the patch does the following:

(1) Adds configuration setting "filename-xchars" (versionable) that if
enabled allows for characters *?[]\ to be used in filenames. When
disabled the behavior is the same as now.

(2) Glob patterns now recognize escaped characters '\?', '\[', '\*',
'\\' that represent literal chars  '?', '[', '*', '\'  respectively.

I hope the patch can help all those folks who voiced their support for
this feature in the recent thread
http://lists.fossil-scm.org:8080/pipermail/fossil-users/2012-March/008487.html

Thanks,
--Leo--
Index: src/configure.c
==================================================================
--- src/configure.c
+++ src/configure.c
@@ -85,10 +85,11 @@
   { "manifest",               CONFIGSET_PROJ },
   { "ignore-glob",            CONFIGSET_PROJ },
   { "crnl-glob",              CONFIGSET_PROJ },
   { "empty-dirs",             CONFIGSET_PROJ },
   { "allow-symlinks",         CONFIGSET_PROJ },
+  { "filename-xchars",        CONFIGSET_PROJ },
   { "index-page",             CONFIGSET_SKIN },
 #ifdef FOSSIL_ENABLE_TCL
   { "tcl",                    CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
 #endif
   { "timeline-block-markup",  CONFIGSET_SKIN },

Index: src/db.c
==================================================================
--- src/db.c
+++ src/db.c
@@ -933,10 +933,13 @@
   db_open_or_attach(zDbName, "repository");
   g.repositoryOpen = 1;
   g.zRepositoryName = mprintf("%s", zDbName);
   /* Cache "allow-symlinks" option, because we'll need it on every stat call */
   g.allowSymlinks = db_get_boolean("allow-symlinks", 0);
+  /* Cache "filename-xchars" option, because we'll need it on every 
+   * file_is_simple_pathname(...) call */
+  g.filenameXchars= db_get_boolean("filename-xchars", 0);
 }
 
 /*
 ** Flags for the db_find_and_open_repository() function.
 */
@@ -1850,10 +1853,11 @@
   { "crnl-glob",     0,               16, 1, ""                    },
   { "default-perms", 0,               16, 0, "u"                   },
   { "diff-command",  0,               16, 0, ""                    },
   { "dont-push",     0,                0, 0, "off"                 },
   { "editor",        0,               16, 0, ""                    },
+  { "filename-xchars",0,               0, 1, "off"                 },
   { "gdiff-command", 0,               16, 0, "gdiff"               },
   { "gmerge-command",0,               40, 0, ""                    },
   { "https-login",   0,                0, 0, "off"                 },
   { "ignore-glob",   0,               40, 1, ""                    },
   { "empty-dirs",    0,               40, 1, ""                    },
@@ -1947,10 +1951,16 @@
 **     (versionable)   update and checkout commands, if no file or directory
 **                     exists with that name, an empty directory will be
 **                     created.
 **
 **    editor           Text editor command used for check-in comments.
+**
+**    filename-xchars  Allow eXtra characters '*', '?', '[' in filenames.
+**     (versionable)   In glob patterns they have special meaning. 
+**                     In globs escaped chars '\\*', '\\?', '\\[', '\\\\' 
+**                     represent literal '*', '?', '[', '\\' .
+**                     Default: off
 **
 **    gdiff-command    External command to run when performing a graphical
 **                     diff. If undefined, text diff will be used.
 **
 **    gmerge-command   A graphical merge conflict resolver command operating

Index: src/file.c
==================================================================
--- src/file.c
+++ src/file.c
@@ -434,11 +434,12 @@
   if( c=='.' ){
     if( z[1]=='/' || z[1]==0 ) return 0;
     if( z[1]=='.' && (z[2]=='/' || z[2]==0) ) return 0;
   }
   for(i=0; (c=z[i])!=0; i++){
-    if( c=='\\' || c=='*' || c=='[' || c==']' || c=='?' ){
+    if( g.filenameXchars==0 && 
+        (c=='\\' || c=='*' || c=='[' || c==']' || c=='?') ){
       return 0;
     }
     if( c=='/' ){
       if( z[i+1]=='/' ) return 0;
       if( z[i+1]=='.' ){

Index: src/glob.c
==================================================================
--- src/glob.c
+++ src/glob.c
@@ -139,18 +139,20 @@
 ** Return non-zero if string z matches glob pattern zGlob and zero if the
 ** pattern does not match.
 **
 ** Globbing rules:
 **
-**      '*'       Matches any sequence of zero or more characters.
+**      '*'         Matches any sequence of zero or more characters.
+**
+**      '?'         Matches exactly one character.
 **
-**      '?'       Matches exactly one character.
+**    [...]         Matches one character from the enclosed list of
+**                  characters.
 **
-**     [...]      Matches one character from the enclosed list of
-**                characters.
+**    [^...]        Matches one character not in the enclosed list.
 **
-**     [^...]     Matches one character not in the enclosed list.
+**    \[ \* \? \\   Match literal [ * ? \ chars, (escape rules)
 */
 int strglob(const char *zGlob, const char *z){
   int c, c2;
   int invert;
   int seen;
@@ -165,10 +167,12 @@
       }else if( c=='[' ){
         while( *z && strglob(zGlob-1,z)==0 ){
           z++;
         }
         return (*z)!=0;
+      }else if( c=='\\' ){
+        c= *(zGlob++);
       }
       while( (c2 = (*(z++)))!=0 ){
         while( c2!=c ){
           c2 = *(z++);
           if( c2==0 ) return 0;
@@ -205,10 +209,13 @@
           prior_c = c2;
         }
         c2 = *(zGlob++);
       }
       if( c2==0 || (seen ^ invert)==0 ) return 0;
+    }else if( c=='\\' ){
+      c= *(zGlob++);
+      if( c!=(*(z++)) ) return 0;
     }else{
       if( c!=(*(z++)) ) return 0;
     }
   }
   return *z==0;

Index: src/json_config.c
==================================================================
--- src/json_config.c
+++ src/json_config.c
@@ -67,10 +67,11 @@
 { "manifest",               CONFIGSET_PROJ },
 { "ignore-glob",            CONFIGSET_PROJ },
 { "crnl-glob",              CONFIGSET_PROJ },
 { "empty-dirs",             CONFIGSET_PROJ },
 { "allow-symlinks",         CONFIGSET_PROJ },
+{ "filename-xchars",        CONFIGSET_PROJ },
 
 { "ticket-table",           CONFIGSET_TKT  },
 { "ticket-common",          CONFIGSET_TKT  },
 { "ticket-change",          CONFIGSET_TKT  },
 { "ticket-newpage",         CONFIGSET_TKT  },

Index: src/main.c
==================================================================
--- src/main.c
+++ src/main.c
@@ -192,10 +192,11 @@
   const char *azAuxVal[MX_AUX];  /* Value of each aux() or option() value */
   const char **azAuxOpt[MX_AUX]; /* Options of each option() value */
   int anAuxCols[MX_AUX];         /* Number of columns for option() values */
   
   int allowSymlinks;             /* Cached "allow-symlinks" option */
+  int filenameXchars;            /* Cached "filename-xchars" option */
 
 #ifdef FOSSIL_ENABLE_JSON
   struct FossilJsonBits {
     int isJsonMode;            /* True if running in JSON mode, else
                                   false. This changes how errors are

_______________________________________________
fossil-users mailing list
[email protected]
http://lists.fossil-scm.org:8080/cgi-bin/mailman/listinfo/fossil-users

Reply via email to