Fossil

Check-in [e94c7cc4de]
Login

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

Overview
Comment:Modify file_simplify_name to accept a parameter used to determine if the trailing slash, if any, should be retained. Make use of this when converting the local root to its canonical form.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | winFiles
Files: files | file ages | folders
SHA1: e94c7cc4dee7e23321b0069f1d46ddf3277ddff5
User & Date: mistachkin 2012-03-19 05:24:43.745
Context
2012-03-20
14:03
Merge the winFiles branch into trunk. check-in: 135ed93375 user: drh tags: trunk
2012-03-19
05:24
Modify file_simplify_name to accept a parameter used to determine if the trailing slash, if any, should be retained. Make use of this when converting the local root to its canonical form. Closed-Leaf check-in: e94c7cc4de user: mistachkin tags: winFiles
04:48
In file_tree_name, since the file name argument is converted to its canonical form prior to the memcmp, the local root must be as well. On Windows, normalize drive letters to uppercase when converting a file name to its canonical form and fix construction of temporary file names used with the gdiff command when the --from and --to options are present. check-in: 6be0898b2c user: mistachkin tags: winFiles
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/add.c.
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
  
  /* Load the names of all files that are to be added into sfile temp table */
  for(i=2; i<g.argc; i++){
    char *zName;
    int isDir;
    Blob fullName;

    file_canonical_name(g.argv[i], &fullName);
    zName = blob_str(&fullName);
    isDir = file_wd_isdir(zName);
    if( isDir==1 ){
      vfile_scan(&fullName, nRoot-1, includeDotFiles, pIgnore);
    }else if( isDir==0 ){
      fossil_fatal("not found: %s", zName);
    }else if( file_access(zName, R_OK) ){







|







239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
  
  /* Load the names of all files that are to be added into sfile temp table */
  for(i=2; i<g.argc; i++){
    char *zName;
    int isDir;
    Blob fullName;

    file_canonical_name(g.argv[i], &fullName, 0);
    zName = blob_str(&fullName);
    isDir = file_wd_isdir(zName);
    if( isDir==1 ){
      vfile_scan(&fullName, nRoot-1, includeDotFiles, pIgnore);
    }else if( isDir==0 ){
      fossil_fatal("not found: %s", zName);
    }else if( file_access(zName, R_OK) ){
Changes to src/allrepo.c.
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
        db_unset(zRepo, 1);
        free(zRepo);
      }else if( !file_is_canonical(zFilename) ){
        Blob cname;
        char *zRepo = mprintf("repo:%s", zFilename);
        db_unset(zRepo, 1);
        free(zRepo);
        file_canonical_name(zFilename, &cname);
        zRepo = mprintf("repo:%s", blob_str(&cname));
        db_set(zRepo, "1", 1);
        free(zRepo);
      }
    }
    db_reset(&q);
    db_end_transaction(0);







|







166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
        db_unset(zRepo, 1);
        free(zRepo);
      }else if( !file_is_canonical(zFilename) ){
        Blob cname;
        char *zRepo = mprintf("repo:%s", zFilename);
        db_unset(zRepo, 1);
        free(zRepo);
        file_canonical_name(zFilename, &cname, 0);
        zRepo = mprintf("repo:%s", blob_str(&cname));
        db_set(zRepo, "1", 1);
        free(zRepo);
      }
    }
    db_reset(&q);
    db_end_transaction(0);
Changes to src/blob.c.
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
    nName = strlen(zFilename);
    if( nName>=sizeof(zBuf) ){
      zName = mprintf("%s", zFilename);
    }else{
      zName = zBuf;
      memcpy(zName, zFilename, nName+1);
    }
    nName = file_simplify_name(zName, nName);
    for(i=1; i<nName; i++){
      if( zName[i]=='/' ){
        zName[i] = 0;
#if defined(_WIN32)
        /*
        ** On Windows, local path looks like: C:/develop/project/file.txt
        ** The if stops us from trying to create a directory of a drive letter







|







792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
    nName = strlen(zFilename);
    if( nName>=sizeof(zBuf) ){
      zName = mprintf("%s", zFilename);
    }else{
      zName = zBuf;
      memcpy(zName, zFilename, nName+1);
    }
    nName = file_simplify_name(zName, nName, 0);
    for(i=1; i<nName; i++){
      if( zName[i]=='/' ){
        zName[i] = 0;
#if defined(_WIN32)
        /*
        ** On Windows, local path looks like: C:/develop/project/file.txt
        ** The if stops us from trying to create a directory of a drive letter
Changes to src/checkin.c.
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
    const char *zDisplayName = zPathname;
    int isDeleted = db_column_int(&q, 1);
    int isChnged = db_column_int(&q,2);
    int isNew = db_column_int(&q,3)==0;
    int isRenamed = db_column_int(&q,4);
    char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
    if( cwdRelative ){
      file_relative_name(zFullName, &rewrittenPathname);
      zDisplayName = blob_str(&rewrittenPathname);
      if( zDisplayName[0]=='.' && zDisplayName[1]=='/' ){
        zDisplayName += 2;  /* no unnecessary ./ prefix */
      }
    }
    blob_append(report, zPrefix, nPrefix);
    if( isDeleted ){







|







53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
    const char *zDisplayName = zPathname;
    int isDeleted = db_column_int(&q, 1);
    int isChnged = db_column_int(&q,2);
    int isNew = db_column_int(&q,3)==0;
    int isRenamed = db_column_int(&q,4);
    char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
    if( cwdRelative ){
      file_relative_name(zFullName, &rewrittenPathname, 0);
      zDisplayName = blob_str(&rewrittenPathname);
      if( zDisplayName[0]=='.' && zDisplayName[1]=='/' ){
        zDisplayName += 2;  /* no unnecessary ./ prefix */
      }
    }
    blob_append(report, zPrefix, nPrefix);
    if( isDeleted ){
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
  }
  db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)");
  blob_zero(&rewrittenPathname);
  while( db_step(&q)==SQLITE_ROW ){
    zDisplayName = zPathname = db_column_text(&q, 0);
    if( cwdRelative ) {
      char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
      file_relative_name(zFullName, &rewrittenPathname);
      free(zFullName);
      zDisplayName = blob_str(&rewrittenPathname);
      if( zDisplayName[0]=='.' && zDisplayName[1]=='/' ){
        zDisplayName += 2;  /* no unnecessary ./ prefix */
      }
    }
    fossil_print("%s\n", zDisplayName);







|







311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
  }
  db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)");
  blob_zero(&rewrittenPathname);
  while( db_step(&q)==SQLITE_ROW ){
    zDisplayName = zPathname = db_column_text(&q, 0);
    if( cwdRelative ) {
      char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
      file_relative_name(zFullName, &rewrittenPathname, 0);
      free(zFullName);
      zDisplayName = blob_str(&rewrittenPathname);
      if( zDisplayName[0]=='.' && zDisplayName[1]=='/' ){
        zDisplayName += 2;  /* no unnecessary ./ prefix */
      }
    }
    fossil_print("%s\n", zDisplayName);
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
    }else{
      lastNl++;
      if( lastNl>1000 ) return;   /* Binary if any line longer than 1000 */
    }
  }
  if( nCrNl ){
    char c;
    file_relative_name(zFilename, &fname);
    blob_zero(&ans);
    zMsg = mprintf(
         "%s contains CR/NL line endings; commit anyhow (yes/no/all)?", 
         blob_str(&fname));
    prompt_user(zMsg, &ans);
    fossil_free(zMsg);
    c = blob_str(&ans)[0];







|







824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
    }else{
      lastNl++;
      if( lastNl>1000 ) return;   /* Binary if any line longer than 1000 */
    }
  }
  if( nCrNl ){
    char c;
    file_relative_name(zFilename, &fname, 0);
    blob_zero(&ans);
    zMsg = mprintf(
         "%s contains CR/NL line endings; commit anyhow (yes/no/all)?", 
         blob_str(&fname));
    prompt_user(zMsg, &ans);
    fossil_free(zMsg);
    c = blob_str(&ans)[0];
Changes to src/clone.c.
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
    db_set("content-schema", CONTENT_SCHEMA, 0);
    db_set("aux-schema", AUX_SCHEMA, 0);
    db_set("last-sync-url", g.argv[2], 0);
    if( g.zSSLIdentity!=0 ){
      /* If the --ssl-identity option was specified, store it as a setting */
      Blob fn;
      blob_zero(&fn);
      file_canonical_name(g.zSSLIdentity, &fn);
      db_set("ssl-identity", blob_str(&fn), 0);
      blob_reset(&fn);
    }
    db_multi_exec(
      "REPLACE INTO config(name,value,mtime)"
      " VALUES('server-code', lower(hex(randomblob(20))), now());"
    );







|







148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
    db_set("content-schema", CONTENT_SCHEMA, 0);
    db_set("aux-schema", AUX_SCHEMA, 0);
    db_set("last-sync-url", g.argv[2], 0);
    if( g.zSSLIdentity!=0 ){
      /* If the --ssl-identity option was specified, store it as a setting */
      Blob fn;
      blob_zero(&fn);
      file_canonical_name(g.zSSLIdentity, &fn, 0);
      db_set("ssl-identity", blob_str(&fn), 0);
      blob_reset(&fn);
    }
    db_multi_exec(
      "REPLACE INTO config(name,value,mtime)"
      " VALUES('server-code', lower(hex(randomblob(20))), now());"
    );
Changes to src/db.c.
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
  if( g.argc!=3 ){
    usage("PATHNAME");
  }
  if( db_open_local()==0 ){
    fossil_fatal("not in a local checkout");
    return;
  }
  file_canonical_name(g.argv[2], &repo);
  zRepo = blob_str(&repo);
  if( file_access(zRepo, 0) ){
    fossil_fatal("no such file: %s", zRepo);
  }
  db_open_or_attach(zRepo, "test_repo");
  db_lset("repository", blob_str(&repo));
  db_close(1);







|







1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
  if( g.argc!=3 ){
    usage("PATHNAME");
  }
  if( db_open_local()==0 ){
    fossil_fatal("not in a local checkout");
    return;
  }
  file_canonical_name(g.argv[2], &repo, 0);
  zRepo = blob_str(&repo);
  if( file_access(zRepo, 0) ){
    fossil_fatal("no such file: %s", zRepo);
  }
  db_open_or_attach(zRepo, "test_repo");
  db_lset("repository", blob_str(&repo));
  db_close(1);
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
*/
void db_record_repository_filename(const char *zName){
  Blob full;
  if( zName==0 ){
    if( !g.localOpen ) return;
    zName = db_repository_filename();
  }
  file_canonical_name(zName, &full);
  db_swap_connections();
  db_multi_exec(
     "INSERT OR IGNORE INTO global_config(name,value)"
     "VALUES('repo:%q',1)",
     blob_str(&full)
  );
  if( g.localOpen && g.zLocalRoot && g.zLocalRoot[0] ){
    Blob localRoot;
    file_canonical_name(g.zLocalRoot, &localRoot);
    db_multi_exec(
      "REPLACE INTO global_config(name, value)"
      "VALUES('ckout:%q','%q');",
      blob_str(&localRoot), blob_str(&full)
    );
    blob_reset(&localRoot);
  }







|








|







1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
*/
void db_record_repository_filename(const char *zName){
  Blob full;
  if( zName==0 ){
    if( !g.localOpen ) return;
    zName = db_repository_filename();
  }
  file_canonical_name(zName, &full, 0);
  db_swap_connections();
  db_multi_exec(
     "INSERT OR IGNORE INTO global_config(name,value)"
     "VALUES('repo:%q',1)",
     blob_str(&full)
  );
  if( g.localOpen && g.zLocalRoot && g.zLocalRoot[0] ){
    Blob localRoot;
    file_canonical_name(g.zLocalRoot, &localRoot, 1);
    db_multi_exec(
      "REPLACE INTO global_config(name, value)"
      "VALUES('ckout:%q','%q');",
      blob_str(&localRoot), blob_str(&full)
    );
    blob_reset(&localRoot);
  }
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
  allowNested = find_option("nested",0,0)!=0;
  if( g.argc!=3 && g.argc!=4 ){
    usage("REPOSITORY-FILENAME ?VERSION?");
  }
  if( !allowNested && db_open_local() ){
    fossil_panic("already within an open tree rooted at %s", g.zLocalRoot);
  }
  file_canonical_name(g.argv[2], &path);
  db_open_repository(blob_str(&path));
  db_init_database("./_FOSSIL_", zLocalSchema, (char*)0);
  db_delete_on_failure("./_FOSSIL_");
  db_open_local();
  db_lset("repository", g.argv[2]);
  db_record_repository_filename(blob_str(&path));
  vid = db_int(0, "SELECT pid FROM plink y"







|







1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
  allowNested = find_option("nested",0,0)!=0;
  if( g.argc!=3 && g.argc!=4 ){
    usage("REPOSITORY-FILENAME ?VERSION?");
  }
  if( !allowNested && db_open_local() ){
    fossil_panic("already within an open tree rooted at %s", g.zLocalRoot);
  }
  file_canonical_name(g.argv[2], &path, 0);
  db_open_repository(blob_str(&path));
  db_init_database("./_FOSSIL_", zLocalSchema, (char*)0);
  db_delete_on_failure("./_FOSSIL_");
  db_open_local();
  db_lset("repository", g.argv[2]);
  db_record_repository_filename(blob_str(&path));
  vid = db_int(0, "SELECT pid FROM plink y"
Changes to src/file.c.
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
    nName = strlen(zLinkFile);
    if( nName>=sizeof(zBuf) ){
      zName = mprintf("%s", zLinkFile);
    }else{
      zName = zBuf;
      memcpy(zName, zLinkFile, nName+1);
    }
    nName = file_simplify_name(zName, nName);
    for(i=1; i<nName; i++){
      if( zName[i]=='/' ){
        zName[i] = 0;
          if( file_mkdir(zName, 1) ){
            fossil_fatal_recursive("unable to create directory %s", zName);
            return;
          }







|







173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
    nName = strlen(zLinkFile);
    if( nName>=sizeof(zBuf) ){
      zName = mprintf("%s", zLinkFile);
    }else{
      zName = zBuf;
      memcpy(zName, zLinkFile, nName+1);
    }
    nName = file_simplify_name(zName, nName, 0);
    for(i=1; i<nName; i++){
      if( zName[i]=='/' ){
        zName[i] = 0;
          if( file_mkdir(zName, 1) ){
            fossil_fatal_recursive("unable to create directory %s", zName);
            return;
          }
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
** other than a directory.
*/
int file_isdir(const char *zFilename){
  int rc;

  if( zFilename ){
    char *zFN = mprintf("%s", zFilename);
    file_simplify_name(zFN, -1);
    rc = getStat(zFN, 0);
    free(zFN);
  }else{
    rc = getStat(0, 0);
  }
  return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
}

/*
** Same as file_isdir(), but takes into account symlinks.
*/
int file_wd_isdir(const char *zFilename){
  int rc;

  if( zFilename ){
    char *zFN = mprintf("%s", zFilename);
    file_simplify_name(zFN, -1);
    rc = getStat(zFN, 1);
    free(zFN);
  }else{
    rc = getStat(0, 1);
  }
  return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
}







|
















|







264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
** other than a directory.
*/
int file_isdir(const char *zFilename){
  int rc;

  if( zFilename ){
    char *zFN = mprintf("%s", zFilename);
    file_simplify_name(zFN, -1, 0);
    rc = getStat(zFN, 0);
    free(zFN);
  }else{
    rc = getStat(0, 0);
  }
  return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
}

/*
** Same as file_isdir(), but takes into account symlinks.
*/
int file_wd_isdir(const char *zFilename){
  int rc;

  if( zFilename ){
    char *zFN = mprintf("%s", zFilename);
    file_simplify_name(zFN, -1, 0);
    rc = getStat(zFN, 1);
    free(zFN);
  }else{
    rc = getStat(0, 1);
  }
  return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
}
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
  z = mprintf("%s-%s", zBase, zSuffix);
  while( file_size(z)>=0 ){
    fossil_free(z);
    z = mprintf("%s-%s-%d", zBase, zSuffix, cnt++);
  }
  if( relFlag ){
    Blob x;
    file_relative_name(z, &x);
    fossil_free(z);
    z = blob_str(&x);
  }
  return z;
}

/*







|







319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
  z = mprintf("%s-%s", zBase, zSuffix);
  while( file_size(z)>=0 ){
    fossil_free(z);
    z = mprintf("%s-%s-%d", zBase, zSuffix, cnt++);
  }
  if( relFlag ){
    Blob x;
    file_relative_name(z, &x, 0);
    fossil_free(z);
    z = blob_str(&x);
  }
  return z;
}

/*
478
479
480
481
482
483
484


485
486
487
488
489
490
491
492
493
494
495
496
497

498

499
500
501
502
503
504
505
**
**  * Convert all \ into / on windows
**  * removing any trailing and duplicate /
**  * removing /./
**  * removing /A/../
**
** Changes are made in-place.  Return the new name length.


*/
int file_simplify_name(char *z, int n){
  int i, j;
  if( n<0 ) n = strlen(z);

  /* On windows convert all \ characters to / */
#if defined(_WIN32)
  for(i=0; i<n; i++){
    if( z[i]=='\\' ) z[i] = '/';
  }
#endif

  /* Removing trailing "/" characters */

  while( n>1 && z[n-1]=='/' ){ n--; }


  /* Remove duplicate '/' characters.  Except, two // at the beginning
  ** of a pathname is allowed since this is important on windows. */
  for(i=j=1; i<n; i++){
    z[j++] = z[i];
    while( z[i]=='/' && i<n-1 && z[i+1]=='/' ) i++;
  }







>
>

|











>
|
>







478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
**
**  * Convert all \ into / on windows
**  * removing any trailing and duplicate /
**  * removing /./
**  * removing /A/../
**
** Changes are made in-place.  Return the new name length.
** If the slash parameter is non-zero, the trailing slash, if any,
** is retained.
*/
int file_simplify_name(char *z, int n, int slash){
  int i, j;
  if( n<0 ) n = strlen(z);

  /* On windows convert all \ characters to / */
#if defined(_WIN32)
  for(i=0; i<n; i++){
    if( z[i]=='\\' ) z[i] = '/';
  }
#endif

  /* Removing trailing "/" characters */
  if ( !slash ){
    while( n>1 && z[n-1]=='/' ){ n--; }
  }

  /* Remove duplicate '/' characters.  Except, two // at the beginning
  ** of a pathname is allowed since this is important on windows. */
  for(i=j=1; i<n; i++){
    z[j++] = z[i];
    while( z[i]=='/' && i<n-1 && z[i+1]=='/' ) i++;
  }
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
*/
void cmd_test_simplify_name(void){
  int i;
  char *z;
  for(i=2; i<g.argc; i++){
    z = mprintf("%s", g.argv[i]);
    fossil_print("[%s] -> ", z);
    file_simplify_name(z, -1);
    fossil_print("[%s]\n", z);
    fossil_free(z);
  }
}

/*
** Get the current working directory.







|







549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
*/
void cmd_test_simplify_name(void){
  int i;
  char *z;
  for(i=2; i<g.argc; i++){
    z = mprintf("%s", g.argv[i]);
    fossil_print("[%s] -> ", z);
    file_simplify_name(z, -1, 0);
    fossil_print("[%s]\n", z);
    fossil_free(z);
  }
}

/*
** Get the current working directory.
611
612
613
614
615
616
617


618
619
620
621
622
623
624
625
626

/*
** Compute a canonical pathname for a file or directory.
** Make the name absolute if it is relative.
** Remove redundant / characters
** Remove all /./ path elements.
** Convert /A/../ to just /


*/
void file_canonical_name(const char *zOrigName, Blob *pOut){
  if( file_is_absolute_path(zOrigName) ){
#if defined(_WIN32)
    char *zOut;
#endif
    blob_set(pOut, zOrigName);
    blob_materialize(pOut);
#if defined(_WIN32)







>
>

|







615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632

/*
** Compute a canonical pathname for a file or directory.
** Make the name absolute if it is relative.
** Remove redundant / characters
** Remove all /./ path elements.
** Convert /A/../ to just /
** If the slash parameter is non-zero, the trailing slash, if any,
** is retained.
*/
void file_canonical_name(const char *zOrigName, Blob *pOut, int slash){
  if( file_is_absolute_path(zOrigName) ){
#if defined(_WIN32)
    char *zOut;
#endif
    blob_set(pOut, zOrigName);
    blob_materialize(pOut);
#if defined(_WIN32)
642
643
644
645
646
647
648
649

650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
    if( fossil_isalpha(zPwd[0]) && zPwd[1]==':' ){
      zPwd[0] = fossil_toupper(zPwd[0]);
    }
#endif
    blob_zero(pOut);
    blob_appendf(pOut, "%//%/", zPwd, zOrigName);
  }
  blob_resize(pOut, file_simplify_name(blob_buffer(pOut), blob_size(pOut)));

}

/*
** COMMAND:  test-canonical-name
** Usage: %fossil test-canonical-name FILENAME...
**
** Test the operation of the canonical name generator.
** Also test Fossil's ability to measure attributes of a file.
*/
void cmd_test_canonical_name(void){
  int i;
  Blob x;
  blob_zero(&x);
  for(i=2; i<g.argc; i++){
    char zBuf[100];
    const char *zName = g.argv[i];
    file_canonical_name(zName, &x);
    fossil_print("[%s] -> [%s]\n", zName, blob_buffer(&x));
    blob_reset(&x);
    sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_wd_size(zName));
    fossil_print("  file_size   = %s\n", zBuf);
    sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_wd_mtime(zName));
    fossil_print("  file_mtime  = %s\n", zBuf);
    fossil_print("  file_isfile = %d\n", file_wd_isfile(zName));







|
>
















|







648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
    if( fossil_isalpha(zPwd[0]) && zPwd[1]==':' ){
      zPwd[0] = fossil_toupper(zPwd[0]);
    }
#endif
    blob_zero(pOut);
    blob_appendf(pOut, "%//%/", zPwd, zOrigName);
  }
  blob_resize(pOut, file_simplify_name(blob_buffer(pOut),
                                       blob_size(pOut), slash));
}

/*
** COMMAND:  test-canonical-name
** Usage: %fossil test-canonical-name FILENAME...
**
** Test the operation of the canonical name generator.
** Also test Fossil's ability to measure attributes of a file.
*/
void cmd_test_canonical_name(void){
  int i;
  Blob x;
  blob_zero(&x);
  for(i=2; i<g.argc; i++){
    char zBuf[100];
    const char *zName = g.argv[i];
    file_canonical_name(zName, &x, 0);
    fossil_print("[%s] -> [%s]\n", zName, blob_buffer(&x));
    blob_reset(&x);
    sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_wd_size(zName));
    fossil_print("  file_size   = %s\n", zBuf);
    sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_wd_mtime(zName));
    fossil_print("  file_mtime  = %s\n", zBuf);
    fossil_print("  file_isfile = %d\n", file_wd_isfile(zName));
713
714
715
716
717
718
719
720

721
722
723
724
725

726
727
728
729
730
731
732
  if( fossil_isalpha(zIn[0]) && zIn[1]==':' ) zIn += 2;
#endif
  return zIn;
}

/*
** Compute a pathname for a file or directory that is relative
** to the current directory.

*/
void file_relative_name(const char *zOrigName, Blob *pOut){
  char *zPath;
  blob_set(pOut, zOrigName);
  blob_resize(pOut, file_simplify_name(blob_buffer(pOut), blob_size(pOut))); 

  zPath = file_without_drive_letter(blob_buffer(pOut));
  if( zPath[0]=='/' ){
    int i, j;
    Blob tmp;
    char *zPwd;
    char zBuf[2000];
    zPwd = zBuf;







|
>

|


|
>







720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
  if( fossil_isalpha(zIn[0]) && zIn[1]==':' ) zIn += 2;
#endif
  return zIn;
}

/*
** Compute a pathname for a file or directory that is relative
** to the current directory.  If the slash parameter is non-zero,
** the trailing slash, if any, is retained.
*/
void file_relative_name(const char *zOrigName, Blob *pOut, int slash){
  char *zPath;
  blob_set(pOut, zOrigName);
  blob_resize(pOut, file_simplify_name(blob_buffer(pOut),
                                       blob_size(pOut), slash));
  zPath = file_without_drive_letter(blob_buffer(pOut));
  if( zPath[0]=='/' ){
    int i, j;
    Blob tmp;
    char *zPwd;
    char zBuf[2000];
    zPwd = zBuf;
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
** Test the operation of the relative name generator.
*/
void cmd_test_relative_name(void){
  int i;
  Blob x;
  blob_zero(&x);
  for(i=2; i<g.argc; i++){
    file_relative_name(g.argv[i], &x);
    fossil_print("%s\n", blob_buffer(&x));
    blob_reset(&x);
  }
}

/*
** Compute a pathname for a file relative to the root of the local







|







787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
** Test the operation of the relative name generator.
*/
void cmd_test_relative_name(void){
  int i;
  Blob x;
  blob_zero(&x);
  for(i=2; i<g.argc; i++){
    file_relative_name(g.argv[i], &x, 0);
    fossil_print("%s\n", blob_buffer(&x));
    blob_reset(&x);
  }
}

/*
** Compute a pathname for a file relative to the root of the local
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
  char *zLocalRoot;
  Blob full;
  int nFull;
  char *zFull;

  blob_zero(pOut);
  db_must_be_within_tree();
  file_canonical_name(g.zLocalRoot, &localRoot);
  nLocalRoot = blob_size(&localRoot);
  zLocalRoot = blob_buffer(&localRoot);
  if ( zLocalRoot[nLocalRoot-1]!='/' ){
    blob_append(&localRoot, "/", 1);
    nLocalRoot = blob_size(&localRoot);
    zLocalRoot = blob_buffer(&localRoot);
  }
  assert( nLocalRoot>0 && zLocalRoot[nLocalRoot-1]=='/' );
  file_canonical_name(zOrigName, &full);
  nFull = blob_size(&full);
  zFull = blob_buffer(&full);

  /* Special case.  zOrigName refers to g.zLocalRoot directory. */
  if( nFull==nLocalRoot-1 && memcmp(zLocalRoot, zFull, nFull)==0 ){
    blob_append(pOut, ".", 1);
    blob_reset(&localRoot);







|


<
<
<
<
<

|







811
812
813
814
815
816
817
818
819
820





821
822
823
824
825
826
827
828
829
  char *zLocalRoot;
  Blob full;
  int nFull;
  char *zFull;

  blob_zero(pOut);
  db_must_be_within_tree();
  file_canonical_name(g.zLocalRoot, &localRoot, 1);
  nLocalRoot = blob_size(&localRoot);
  zLocalRoot = blob_buffer(&localRoot);





  assert( nLocalRoot>0 && zLocalRoot[nLocalRoot-1]=='/' );
  file_canonical_name(zOrigName, &full, 0);
  nFull = blob_size(&full);
  zFull = blob_buffer(&full);

  /* Special case.  zOrigName refers to g.zLocalRoot directory. */
  if( nFull==nLocalRoot-1 && memcmp(zLocalRoot, zFull, nFull)==0 ){
    blob_append(pOut, ".", 1);
    blob_reset(&localRoot);
Changes to src/login.c.
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
  char *zSql;                /* SQL to run on all peers */
  const char *zSelf;         /* The ATTACH name of our repository */

  *pzErrMsg = 0;   /* Default to no errors */
  zSelf = db_name("repository");

  /* Get the full pathname of the other repository */  
  file_canonical_name(zRepo, &fullName);
  zRepo = mprintf(blob_str(&fullName));
  blob_reset(&fullName);

  /* Get the full pathname for our repository.  Also the project code
  ** and project name for ourself. */
  file_canonical_name(g.zRepositoryName, &fullName);
  zSelfRepo = mprintf(blob_str(&fullName));
  blob_reset(&fullName);
  zSelfProjCode = db_get("project-code", "unknown");
  zSelfLabel = db_get("project-name", 0);
  if( zSelfLabel==0 ){
    zSelfLabel = zSelfProjCode;
  }







|





|







1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
  char *zSql;                /* SQL to run on all peers */
  const char *zSelf;         /* The ATTACH name of our repository */

  *pzErrMsg = 0;   /* Default to no errors */
  zSelf = db_name("repository");

  /* Get the full pathname of the other repository */  
  file_canonical_name(zRepo, &fullName, 0);
  zRepo = mprintf(blob_str(&fullName));
  blob_reset(&fullName);

  /* Get the full pathname for our repository.  Also the project code
  ** and project name for ourself. */
  file_canonical_name(g.zRepositoryName, &fullName, 0);
  zSelfRepo = mprintf(blob_str(&fullName));
  blob_reset(&fullName);
  zSelfProjCode = db_get("project-code", "unknown");
  zSelfLabel = db_get("project-name", 0);
  if( zSelfLabel==0 ){
    zSelfLabel = zSelfProjCode;
  }
Changes to src/main.c.
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
#if !defined(_WIN32)
  if( getuid()==0 ){
    int i;
    struct stat sStat;
    Blob dir;
    char *zDir;

    file_canonical_name(zRepo, &dir);
    zDir = blob_str(&dir);
    if( file_isdir(zDir)==1 ){
      if( chdir(zDir) || chroot(zDir) || chdir("/") ){
        fossil_fatal("unable to chroot into %s", zDir);
      }
      zRepo = "/";
    }else{







|







1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
#if !defined(_WIN32)
  if( getuid()==0 ){
    int i;
    struct stat sStat;
    Blob dir;
    char *zDir;

    file_canonical_name(zRepo, &dir, 0);
    zDir = blob_str(&dir);
    if( file_isdir(zDir)==1 ){
      if( chdir(zDir) || chroot(zDir) || chdir("/") ){
        fossil_fatal("unable to chroot into %s", zDir);
      }
      zRepo = "/";
    }else{
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
          zAltRepo += jj+1;
        }else{
          zUser = "nobody";
        }
        if( g.zLogin==0 ) zUser = "nobody";
        if( zAltRepo[0]!='/' ){
          zAltRepo = mprintf("%s/../%s", g.zRepositoryName, zAltRepo);
          file_simplify_name(zAltRepo, -1);
        }
        db_close(1);
        db_open_repository(zAltRepo);
        login_as_user(zUser);
        g.perm.Password = 0;
        zPath += i;
        nHost = g.zTop - g.zBaseURL;







|







1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
          zAltRepo += jj+1;
        }else{
          zUser = "nobody";
        }
        if( g.zLogin==0 ) zUser = "nobody";
        if( zAltRepo[0]!='/' ){
          zAltRepo = mprintf("%s/../%s", g.zRepositoryName, zAltRepo);
          file_simplify_name(zAltRepo, -1, 0);
        }
        db_close(1);
        db_open_repository(zAltRepo);
        login_as_user(zUser);
        g.perm.Password = 0;
        zPath += i;
        nHost = g.zTop - g.zBaseURL;
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
** is disallowed.
*/
static void find_server_repository(int disallowDir){
  if( g.argc<3 ){
    db_must_be_within_tree();
  }else if( !disallowDir && file_isdir(g.argv[2])==1 ){
    g.zRepositoryName = mprintf("%s", g.argv[2]);
    file_simplify_name(g.zRepositoryName, -1);
  }else{
    db_open_repository(g.argv[2]);
  }
}

/*
** undocumented format:







|







1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
** is disallowed.
*/
static void find_server_repository(int disallowDir){
  if( g.argc<3 ){
    db_must_be_within_tree();
  }else if( !disallowDir && file_isdir(g.argv[2])==1 ){
    g.zRepositoryName = mprintf("%s", g.argv[2]);
    file_simplify_name(g.zRepositoryName, -1, 0);
  }else{
    db_open_repository(g.argv[2]);
  }
}

/*
** undocumented format:
Changes to src/setup.c.
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
  const char *zPw = PD("pw", "");
  const char *zNewName = PD("newname", "New Login Group");

  login_check_credentials();
  if( !g.perm.Setup ){
    login_needed();
  }
  file_canonical_name(g.zRepositoryName, &fullName);
  zSelfRepo = mprintf(blob_str(&fullName));
  blob_reset(&fullName);
  if( P("join")!=0 ){
    login_group_join(zRepo, zLogin, zPw, zNewName, &zErrMsg);
  }else if( P("leave") ){
    login_group_leave(&zErrMsg);
  }







|







949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
  const char *zPw = PD("pw", "");
  const char *zNewName = PD("newname", "New Login Group");

  login_check_credentials();
  if( !g.perm.Setup ){
    login_needed();
  }
  file_canonical_name(g.zRepositoryName, &fullName, 0);
  zSelfRepo = mprintf(blob_str(&fullName));
  blob_reset(&fullName);
  if( P("join")!=0 ){
    login_group_join(zRepo, zLogin, zPw, zNewName, &zErrMsg);
  }else if( P("leave") ){
    login_group_leave(&zErrMsg);
  }
Changes to src/url.c.
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
    }
  }else{
    fossil_panic("unknown repository: %s", zUrl);
  }
  if( g.urlIsFile ){
    Blob cfile;
    dehttpize(zFile);  
    file_canonical_name(zFile, &cfile);
    free(zFile);
    g.urlProtocol = "file";
    g.urlPath = "";
    g.urlName = mprintf("%b", &cfile);
    g.urlCanonical = mprintf("file://%T", g.urlName);
    blob_reset(&cfile);
  }







|







185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
    }
  }else{
    fossil_panic("unknown repository: %s", zUrl);
  }
  if( g.urlIsFile ){
    Blob cfile;
    dehttpize(zFile);  
    file_canonical_name(zFile, &cfile, 0);
    free(zFile);
    g.urlProtocol = "file";
    g.urlPath = "";
    g.urlName = mprintf("%b", &cfile);
    g.urlCanonical = mprintf("file://%T", g.urlName);
    blob_reset(&cfile);
  }
Changes to src/winhttp.c.
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
    zNotFound = find_option("notfound", 0, 1);
    zLocalAuth = find_option("localauth", 0, 0);
    zRepository = find_option("repository", "R", 1);
    if( !zRepository ){
      db_must_be_within_tree();
    }else if( file_isdir(zRepository)==1 ){
      g.zRepositoryName = mprintf("%s", zRepository);
      file_simplify_name(g.zRepositoryName, -1);
    }else{
      db_open_repository(zRepository);
    }
    db_close(0);
    verify_all_options();
    if( g.argc>4 ) fossil_fatal("to much arguments for create method.");
    /* Build the fully-qualified path to the service binary file. */







|







594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
    zNotFound = find_option("notfound", 0, 1);
    zLocalAuth = find_option("localauth", 0, 0);
    zRepository = find_option("repository", "R", 1);
    if( !zRepository ){
      db_must_be_within_tree();
    }else if( file_isdir(zRepository)==1 ){
      g.zRepositoryName = mprintf("%s", zRepository);
      file_simplify_name(g.zRepositoryName, -1, 0);
    }else{
      db_open_repository(zRepository);
    }
    db_close(0);
    verify_all_options();
    if( g.argc>4 ) fossil_fatal("to much arguments for create method.");
    /* Build the fully-qualified path to the service binary file. */
Changes to win/Makefile.mingw.mistachkin.
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

#### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
#
FOSSIL_ENABLE_SSL = 1

#### Enable scripting support via Tcl/Tk
#
FOSSIL_ENABLE_TCL = 1

#### Use the Tcl source directory instead of the install directory?
#    This is useful when Tcl has been compiled statically with MinGW.
#
FOSSIL_TCL_SOURCE = 1

#### The directories where the zlib include and library files are located.







|







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

#### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
#
FOSSIL_ENABLE_SSL = 1

#### Enable scripting support via Tcl/Tk
#
# FOSSIL_ENABLE_TCL = 1

#### Use the Tcl source directory instead of the install directory?
#    This is useful when Tcl has been compiled statically with MinGW.
#
FOSSIL_TCL_SOURCE = 1

#### The directories where the zlib include and library files are located.