Changes On Branch filename-case
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch filename-case Excluding Merge-Ins

This is equivalent to a diff from 83c032de7f to 4fee0ce2d6

2011-08-04
22:17
Merge the --case-sensitive feature into trunk. check-in: 874d0ca303 user: drh tags: trunk
17:13
Add experimental changes to support the case-sensitive setting and the --case-sensitive command-line option for "add", "addremove", and "merge". Closed-Leaf check-in: 4fee0ce2d6 user: drh tags: filename-case
15:54
Merge trunk into ben-testing check-in: 3eb07708b1 user: ben tags: ben-testing
14:32
Merge the ben-minorchanges branch into trunk. check-in: 83c032de7f user: drh tags: trunk
2011-08-02
18:42
Use the automatic background color algorithm for individual file timelines in addition to the global timeline. check-in: abe7b8335f user: drh tags: trunk
2011-07-30
10:14
Correct the winsrv documentation to use the renamed command name. Closed-Leaf check-in: f6b8397e4b user: ben tags: ben-minorchanges

Changes to src/add.c.

    90     90   /*
    91     91   ** Add a single file named zName to the VFILE table with vid.
    92     92   **
    93     93   ** Omit any file whose name is pOmit.
    94     94   */
    95     95   static int add_one_file(
    96     96     const char *zPath,   /* Tree-name of file to add. */
    97         -  int vid              /* Add to this VFILE */
           97  +  int vid,             /* Add to this VFILE */
           98  +  int caseSensitive    /* True if filenames are case sensitive */
    98     99   ){
          100  +  const char *zCollate = caseSensitive ? "binary" : "nocase";
    99    101     if( !file_is_simple_pathname(zPath) ){
   100    102       fossil_fatal("filename contains illegal characters: %s", zPath);
   101    103     }
   102         -#if defined(_WIN32)
   103    104     if( db_exists("SELECT 1 FROM vfile"
   104         -                " WHERE pathname=%Q COLLATE nocase", zPath) ){
          105  +                " WHERE pathname=%Q COLLATE %s", zPath, zCollate) ){
   105    106       db_multi_exec("UPDATE vfile SET deleted=0"
   106         -                  " WHERE pathname=%Q COLLATE nocase", zPath);
   107         -  }
   108         -#else
   109         -  if( db_exists("SELECT 1 FROM vfile WHERE pathname=%Q", zPath) ){
   110         -    db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname=%Q", zPath);
   111         -  }
   112         -#endif
   113         -  else{
          107  +                  " WHERE pathname=%Q COLLATE %s", zPath, zCollate);
          108  +  }else{
   114    109       char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath);
   115    110       db_multi_exec(
   116    111         "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe)"
   117    112         "VALUES(%d,0,0,0,%Q,%d)",
   118    113         vid, zPath, file_isexe(zFullname));
   119    114       fossil_free(zFullname);
   120    115     }
   121         -  fossil_print("ADDED  %s\n", zPath);
   122         -  return 1;
          116  +  if( db_changes() ){
          117  +    fossil_print("ADDED  %s\n", zPath);
          118  +    return 1;
          119  +  }else{
          120  +    fossil_print("SKIP   %s\n", zPath);
          121  +    return 0;
          122  +  }
   123    123   }
   124    124   
   125    125   /*
   126    126   ** Add all files in the sfile temp table.
   127    127   **
   128    128   ** Automatically exclude the repository file.
   129    129   */
   130         -static int add_files_in_sfile(int vid){
          130  +static int add_files_in_sfile(int vid, int caseSensitive){
   131    131     const char *zRepo;        /* Name of the repository database file */
   132    132     int nAdd = 0;             /* Number of files added */
   133    133     int i;                    /* Loop counter */
   134    134     const char *zReserved;    /* Name of a reserved file */
   135    135     Blob repoName;            /* Treename of the repository */
   136    136     Stmt loop;                /* SQL to loop over all files to add */
          137  +  int (*xCmp)(const char*,const char*);
   137    138    
   138    139     if( !file_tree_name(g.zRepositoryName, &repoName, 0) ){
   139    140       blob_zero(&repoName);
   140    141       zRepo = "";
   141    142     }else{
   142    143       zRepo = blob_str(&repoName);
   143    144     }
          145  +  if( caseSensitive ){
          146  +    xCmp = fossil_strcmp;
          147  +  }else{
          148  +    xCmp = fossil_stricmp;
          149  +    db_multi_exec(
          150  +      "CREATE INDEX IF NOT EXISTS vfile_nocase"
          151  +      "    ON vfile(pathname COLLATE nocase)"
          152  +    );
          153  +  }
          154  +  xCmp = caseSensitive ? fossil_strcmp : fossil_stricmp;
   144    155     db_prepare(&loop, "SELECT x FROM sfile ORDER BY x");
   145    156     while( db_step(&loop)==SQLITE_ROW ){
   146    157       const char *zToAdd = db_column_text(&loop, 0);
   147    158       if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
   148    159       for(i=0; (zReserved = fossil_reserved_name(i))!=0; i++){
   149         -      if( fossil_strcmp(zToAdd, zReserved)==0 ) break;
          160  +      if( xCmp(zToAdd, zReserved)==0 ) break;
   150    161       }
   151    162       if( zReserved ) continue;
   152         -    nAdd += add_one_file(zToAdd, vid);
          163  +    nAdd += add_one_file(zToAdd, vid, caseSensitive);
   153    164     }
   154    165     db_finalize(&loop);
   155    166     blob_reset(&repoName);
   156    167     return nAdd;
   157    168   }
   158    169   
   159    170   /*
................................................................................
   178    189   */
   179    190   void add_cmd(void){
   180    191     int i;                     /* Loop counter */
   181    192     int vid;                   /* Currently checked out version */
   182    193     int nRoot;                 /* Full path characters in g.zLocalRoot */
   183    194     const char *zIgnoreFlag;   /* The --ignore option or ignore-glob setting */
   184    195     Glob *pIgnore;             /* Ignore everything matching this glob pattern */
          196  +  int caseSensitive;         /* True if filenames are case sensitive */
   185    197   
   186    198     zIgnoreFlag = find_option("ignore",0,1);
   187    199     includeDotFiles = find_option("dotfiles",0,0)!=0;
          200  +  capture_case_sensitive_option();
   188    201     db_must_be_within_tree();
          202  +  caseSensitive = filenames_are_case_sensitive();
   189    203     if( zIgnoreFlag==0 ){
   190    204       zIgnoreFlag = db_get("ignore-glob", 0);
   191    205     }
   192    206     vid = db_lget_int("checkout",0);
   193    207     if( vid==0 ){
   194    208       fossil_panic("no checkout to add to");
   195    209     }
................................................................................
   227    241            zTreeName, zTreeName
   228    242         );
   229    243       }
   230    244       blob_reset(&fullName);
   231    245     }
   232    246     glob_free(pIgnore);
   233    247   
   234         -  add_files_in_sfile(vid);  
          248  +  add_files_in_sfile(vid, caseSensitive);
   235    249     db_end_transaction(0);
   236    250   }
   237    251   
   238    252   /*
   239    253   ** COMMAND: rm
   240    254   ** COMMAND: delete
   241    255   **
................................................................................
   287    301     db_finalize(&loop);
   288    302     db_multi_exec(
   289    303       "UPDATE vfile SET deleted=1 WHERE pathname IN sfile;"
   290    304       "DELETE FROM vfile WHERE rid=0 AND deleted;"
   291    305     );
   292    306     db_end_transaction(0);
   293    307   }
          308  +
          309  +/*
          310  +** Capture the command-line --case-sensitive option.
          311  +*/
          312  +static const char *zCaseSensitive = 0;
          313  +void capture_case_sensitive_option(void){
          314  +  if( zCaseSensitive==0 ){
          315  +    zCaseSensitive = find_option("case-sensitive",0,1);
          316  +  }
          317  +}
          318  +
          319  +/*
          320  +** This routine determines if files should be case-sensitive or not.
          321  +** In other words, this routine determines if two filenames that
          322  +** differ only in case should be considered the same name or not.
          323  +**
          324  +** The case-sensitive setting determines the default value.  If
          325  +** the case-sensitive setting is undefined, then case sensitivity
          326  +** defaults on for Mac and Windows and off for all other unix.
          327  +**
          328  +** The --case-sensitive BOOLEAN command-line option overrides any
          329  +** setting.
          330  +*/
          331  +int filenames_are_case_sensitive(void){
          332  +  int caseSensitive;
          333  +
          334  +  if( zCaseSensitive ){
          335  +    caseSensitive = is_truth(zCaseSensitive);
          336  +  }else{
          337  +#if !defined(_WIN32) && !defined(__DARWIN__) && !defined(__APPLE__)
          338  +    caseSensitive = 1;
          339  +#else
          340  +    caseSensitive = 0;
          341  +#endif
          342  +    caseSensitive = db_get_boolean("case-sensitive",caseSensitive);
          343  +  }
          344  +  return caseSensitive;
          345  +}
   294    346   
   295    347   /*
   296    348   ** COMMAND: addremove
   297    349   **
   298    350   ** Usage: %fossil addremove ?--dotfiles? ?--ignore GLOBPATTERN? ?--test?
   299    351   **
   300    352   ** Do all necessary "add" and "rm" commands to synchronize the repository
................................................................................
   317    369   ** The --ignore option overrides the "ignore-glob" setting.  See
   318    370   ** documentation on the "settings" command for further information.
   319    371   **
   320    372   ** The --test option shows what would happen without actually doing anything.
   321    373   **
   322    374   ** This command can be used to track third party software.
   323    375   **
   324         -**
   325    376   ** SUMMARY: fossil addremove
   326         -** Options: ?--dotfiles? ?--ignore GLOBPATTERN? ?--test?
          377  +** Options: ?--dotfiles? ?--ignore GLOB? ?--test? ?--case-sensitive BOOL?
   327    378   */
   328         -void import_cmd(void){
          379  +void addremove_cmd(void){
   329    380     Blob path;
   330    381     const char *zIgnoreFlag = find_option("ignore",0,1);
   331    382     int allFlag = find_option("dotfiles",0,0)!=0;
   332    383     int isTest = find_option("test",0,0)!=0;
          384  +  int caseSensitive;
   333    385     int n;
   334    386     Stmt q;
   335    387     int vid;
   336    388     int nAdd = 0;
   337    389     int nDelete = 0;
   338    390     Glob *pIgnore;
   339    391   
          392  +  capture_case_sensitive_option();
   340    393     db_must_be_within_tree();
          394  +  caseSensitive = filenames_are_case_sensitive();
   341    395     if( zIgnoreFlag==0 ){
   342    396       zIgnoreFlag = db_get("ignore-glob", 0);
   343    397     }
   344    398     vid = db_lget_int("checkout",0);
   345    399     if( vid==0 ){
   346    400       fossil_panic("no checkout to add to");
   347    401     }
................................................................................
   356    410     db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
   357    411     n = strlen(g.zLocalRoot);
   358    412     blob_init(&path, g.zLocalRoot, n-1);
   359    413     /* now we read the complete file structure into a temp table */
   360    414     pIgnore = glob_create(zIgnoreFlag);
   361    415     vfile_scan(&path, blob_size(&path), allFlag, pIgnore);
   362    416     glob_free(pIgnore);
   363         -  nAdd = add_files_in_sfile(vid);
          417  +  nAdd = add_files_in_sfile(vid, caseSensitive);
   364    418   
   365    419     /* step 2: search for missing files */
   366    420     db_prepare(&q,
   367    421         "SELECT pathname, %Q || pathname, deleted FROM vfile"
   368    422         " WHERE NOT deleted"
   369    423         " ORDER BY 1",
   370    424         g.zLocalRoot

Changes to src/db.c.

  1364   1364   /*
  1365   1365   ** Return true if the string zVal represents "true" (or "false").
  1366   1366   */
  1367   1367   int is_truth(const char *zVal){
  1368   1368     static const char *azOn[] = { "on", "yes", "true", "1" };
  1369   1369     int i;
  1370   1370     for(i=0; i<sizeof(azOn)/sizeof(azOn[0]); i++){
  1371         -    if( fossil_strcmp(zVal,azOn[i])==0 ) return 1;
         1371  +    if( fossil_stricmp(zVal,azOn[i])==0 ) return 1;
  1372   1372     }
  1373   1373     return 0;
  1374   1374   }
  1375   1375   int is_false(const char *zVal){
  1376   1376     static const char *azOff[] = { "off", "no", "false", "0" };
  1377   1377     int i;
  1378   1378     for(i=0; i<sizeof(azOff)/sizeof(azOff[0]); i++){
  1379         -    if( fossil_strcmp(zVal,azOff[i])==0 ) return 1;
         1379  +    if( fossil_stricmp(zVal,azOff[i])==0 ) return 1;
  1380   1380     }
  1381   1381     return 0;
  1382   1382   }
  1383   1383   
  1384   1384   /*
  1385   1385   ** Swap the g.db and g.dbConfig connections so that the various db_* routines
  1386   1386   ** work on the ~/.fossil database instead of on the repository database.
................................................................................
  1645   1645   #endif /* INTERFACE */
  1646   1646   struct stControlSettings const ctrlSettings[] = {
  1647   1647     { "access-log",    0,                0, "off"                 },
  1648   1648     { "auto-captcha",  "autocaptcha",    0, "on"                  },
  1649   1649     { "auto-shun",     0,                0, "on"                  },
  1650   1650     { "autosync",      0,                0, "on"                  },
  1651   1651     { "binary-glob",   0,               32, ""                    },
         1652  +  { "case-sensitive",0,                0, "on"                  },
  1652   1653     { "clearsign",     0,                0, "off"                 },
  1653   1654     { "crnl-glob",     0,               16, ""                    },
  1654   1655     { "default-perms", 0,               16, "u"                   },
  1655   1656     { "diff-command",  0,               16, ""                    },
  1656   1657     { "dont-push",     0,                0, "off"                 },
  1657   1658     { "editor",        0,               16, ""                    },
  1658   1659     { "gdiff-command", 0,               16, "gdiff"               },
................................................................................
  1701   1702   **                     tag or branch creation.  If the value is "pullonly"
  1702   1703   **                     then only pull operations occur automatically.
  1703   1704   **                     Default: on
  1704   1705   **
  1705   1706   **    binary-glob      The VALUE is a comma-separated list of GLOB patterns
  1706   1707   **                     that should be treated as binary files for merging
  1707   1708   **                     purposes.  Example:   *.xml
         1709  +**
         1710  +**    case-sensitive   If TRUE, the files whose names differ only in case
         1711  +**                     care considered distinct.  If FALSE files whose names
         1712  +**                     differ only in case are the same file.  Defaults to
         1713  +**                     TRUE for unix and FALSE for windows and mac.
  1708   1714   **
  1709   1715   **    clearsign        When enabled, fossil will attempt to sign all commits
  1710   1716   **                     with gpg.  When disabled (the default), commits will
  1711   1717   **                     be unsigned.  Default: off
  1712   1718   **
  1713   1719   **    crnl-glob        A comma-separated list of GLOB patterns for text files
  1714   1720   **                     in which it is ok to have CR+NL line endings.

Changes to src/merge.c.

    51     51   **
    52     52   **   --binary GLOBPATTERN    Treat files that match GLOBPATTERN as binary
    53     53   **                           and do not try to merge parallel changes.  This
    54     54   **                           option overrides the "binary-glob" setting.
    55     55   **
    56     56   **   --nochange | -n         Dryrun:  do not actually make any changes; just
    57     57   **                           show what would have happened.
           58  +**
           59  +**   --case-sensitive BOOL   Overwrite the case-sensitive setting.  If false,
           60  +**                           files whose names differ only in case are taken
           61  +**                           to be the same file.
    58     62   */
    59     63   void merge_cmd(void){
    60     64     int vid;              /* Current version "V" */
    61     65     int mid;              /* Version we are merging from "M" */
    62     66     int pid;              /* The pivot version - most recent common ancestor P */
    63     67     int detailFlag;       /* True if the --detail option is present */
    64     68     int pickFlag;         /* True if the --cherrypick option is present */
................................................................................
    67     71     const char *zBinGlob; /* The value of --binary */
    68     72     const char *zPivot;   /* The value of --baseline */
    69     73     int debugFlag;        /* True if --debug is present */
    70     74     int nChng;            /* Number of file name changes */
    71     75     int *aChng;           /* An array of file name changes */
    72     76     int i;                /* Loop counter */
    73     77     int nConflict = 0;    /* Number of conflicts seen */
           78  +  int caseSensitive;    /* True for case-sensitive filenames */
    74     79     Stmt q;
    75     80   
    76     81   
    77     82     /* Notation:
    78     83     **
    79     84     **      V     The current checkout
    80     85     **      M     The version being merged in
................................................................................
    85     90     detailFlag = find_option("detail",0,0)!=0;
    86     91     pickFlag = find_option("cherrypick",0,0)!=0;
    87     92     backoutFlag = find_option("backout",0,0)!=0;
    88     93     debugFlag = find_option("debug",0,0)!=0;
    89     94     zBinGlob = find_option("binary",0,1);
    90     95     nochangeFlag = find_option("nochange","n",0)!=0;
    91     96     zPivot = find_option("baseline",0,1);
           97  +  capture_case_sensitive_option();
    92     98     if( g.argc!=3 ){
    93     99       usage("VERSION");
    94    100     }
    95    101     db_must_be_within_tree();
          102  +  caseSensitive = filenames_are_case_sensitive();
    96    103     if( zBinGlob==0 ) zBinGlob = db_get("binary-glob",0);
    97    104     vid = db_lget_int("checkout", 0);
    98    105     if( vid==0 ){
    99    106       fossil_fatal("nothing is checked out");
   100    107     }
   101    108     mid = name_to_typed_rid(g.argv[2], "ci");
   102    109     if( mid==0 || !is_a_version(mid) ){
................................................................................
   148    155     ** The vfile.pathname field is used to match files against each other.  The
   149    156     ** FV table contains one row for each each unique filename in
   150    157     ** in the current checkout, the pivot, and the version being merged.
   151    158     */
   152    159     db_multi_exec(
   153    160       "DROP TABLE IF EXISTS fv;"
   154    161       "CREATE TEMP TABLE fv("
   155         -    "  fn TEXT PRIMARY KEY,"      /* The filename */
          162  +    "  fn TEXT PRIMARY KEY COLLATE %s,"  /* The filename */
   156    163       "  idv INTEGER,"              /* VFILE entry for current version */
   157    164       "  idp INTEGER,"              /* VFILE entry for the pivot */
   158    165       "  idm INTEGER,"              /* VFILE entry for version merging in */
   159    166       "  chnged BOOLEAN,"           /* True if current version has been edited */
   160    167       "  ridv INTEGER,"             /* Record ID for current version */
   161    168       "  ridp INTEGER,"             /* Record ID for pivot */
   162    169       "  ridm INTEGER,"             /* Record ID for merge */
   163    170       "  isexe BOOLEAN,"            /* Execute permission enabled */
   164    171       "  fnp TEXT,"                 /* The filename in the pivot */
   165    172       "  fnm TEXT"                  /* the filename in the merged version */
   166         -    ");"
          173  +    ");",
          174  +    caseSensitive ? "binary" : "nocase"
   167    175     );
   168    176   
   169    177     /* Add files found in V
   170    178     */
   171    179     db_multi_exec(
   172    180       "INSERT OR IGNORE"
   173    181       " INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,isexe,chnged)"