Fossil

Check-in [89ad123f]
Login

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

Overview
Comment:Fix some remaining corner cases when having a checkout on '/'..

Update command:

  • Was asserting when localroot is '/'

file_cannonical_name():

  • Return '/' instead of '.' when refering to '/'.
  • Avoid the double '/' on beginning.
  • Refactoring to avoid some duplicated code.

file_relative_name():

  • Handle properly relative path when working on '/'.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | checkout_on_root_fix
Files: files | file ages | folders
SHA1:89ad123f5ceec73d44d24925313ef9700dd80f96
User & Date: mgagnon 2014-01-08 17:40:58
Original Comment: Fix some remaining corner cases when having a checkout on '/'..

- update was asserting when localroot is '/'

- fix file_canonical_name() so it doesn't return '.' path must be '/' and avoid the double '/' on beginning in some case.

- refactor file_canonical_name() function to avoid some duplicated code.

- fix file_relative_name() so it handle properly relative path when working on '/'.

Context
2014-01-09
11:24
Merge again checkout_on_root_fix.

Fix more cases when working from '/', should not affect when working normally. check-in: af194dbb user: mgagnon tags: trunk

2014-01-08
17:40
Fix some remaining corner cases when having a checkout on '/'..

Update command:

  • Was asserting when localroot is '/'

file_cannonical_name():

  • Return '/' instead of '.' when refering to '/'.
  • Avoid the double '/' on beginning.
  • Refactoring to avoid some duplicated code.

file_relative_name():

  • Handle properly relative path when working on '/'.
Closed-Leaf check-in: 89ad123f user: mgagnon tags: checkout_on_root_fix
04:59
Remove traces.

Waiting approval to merge on trunk.. check-in: 84abd455 user: mgagnon tags: checkout_on_root_fix

Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/file.c.

701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
...
775
776
777
778
779
780
781

782
















783

784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
...
926
927
928
929
930
931
932




933

934
935
936
937
938
939
940
...
988
989
990
991
992
993
994
995

996
997
998
999
1000
1001
1002
        i += 2;
        continue;
      }
    }
    if( j>=0 ) z[j] = z[i];
    j++;
  }
  if( j==0 ) z[j++] = '.';
  z[j] = 0;
  return j;
}

/*
** COMMAND: test-simplify-name
**
................................................................................
** 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) || defined(__CYGWIN__)

    char *zOut;
#endif
    blob_set(pOut, zOrigName);
    blob_materialize(pOut);
#if defined(_WIN32) || defined(__CYGWIN__)
    /*
    ** On Windows/cygwin, normalize the drive letter to upper case.
    */
    zOut = blob_str(pOut);
    if( fossil_islower(zOut[0]) && zOut[1]==':' ){
      zOut[0] = fossil_toupper(zOut[0]);
    }
#endif
  }else{
    char zPwd[2000];
    file_getcwd(zPwd, sizeof(zPwd)-strlen(zOrigName));
#if defined(_WIN32)
    /*
    ** On Windows, normalize the drive letter to upper case.
    */
    if( fossil_islower(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...
................................................................................
      memcpy(&tmp, pOut, sizeof(tmp));
      blob_set(pOut, "./");
      blob_append(pOut, &zPath[i+1], -1);
      blob_reset(&tmp);
      return;
    }
    while( zPath[i-1]!='/' ){ i--; }




    blob_set(&tmp, "../");

    for(j=i; zPwd[j]; j++){
      if( zPwd[j]=='/' ){
        blob_append(&tmp, "../", 3);
      }
    }
    blob_append(&tmp, &zPath[i], -1);
    blob_reset(pOut);
................................................................................
  if( filenames_are_case_sensitive() ){
    xCmp = fossil_strncmp;
  }else{
    xCmp = fossil_strnicmp;
  }

  /* Special case.  zOrigName refers to g.zLocalRoot directory. */
  if( nFull==nLocalRoot-1 && xCmp(zLocalRoot, zFull, nFull)==0 ){

    blob_append(pOut, ".", 1);
    blob_reset(&localRoot);
    blob_reset(&full);
    return 1;
  }

  if( nFull<=nLocalRoot || xCmp(zLocalRoot, zFull, nLocalRoot) ){







|







 







>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>

<
<
<
<




|


<
<
<
<
<
<
<
<
<
<
|

<
<
<







 







>
>
>
>
|
>







 







|
>







701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
...
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802




803
804
805
806
807
808
809










810
811



812
813
814
815
816
817
818
...
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
...
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
        i += 2;
        continue;
      }
    }
    if( j>=0 ) z[j] = z[i];
    j++;
  }
  if( j==0 ) z[j++] = '/';
  z[j] = 0;
  return j;
}

/*
** COMMAND: test-simplify-name
**
................................................................................
** 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){
  blob_zero(pOut);
  if( file_is_absolute_path(zOrigName) ){
    blob_appendf(pOut, "%/", zOrigName);
  }else{
    char zPwd[2000];
    file_getcwd(zPwd, sizeof(zPwd)-strlen(zOrigName));
    if( zPwd[0]=='/' && strlen(zPwd)==1 ){
      // when on '/', don't add an extra '/'
      if( zOrigName[0]=='.' && strlen(zOrigName)==1 ){
        // '.' when on '/' mean '/'
        blob_appendf(pOut, "%/", zPwd);
      }else{
        blob_appendf(pOut, "%/%/", zPwd, zOrigName);
      }
    }else{
      blob_appendf(pOut, "%//%/", zPwd, zOrigName);
    }
  }
#if defined(_WIN32) || defined(__CYGWIN__)
  {
    char *zOut;




    /*
    ** On Windows/cygwin, normalize the drive letter to upper case.
    */
    zOut = blob_str(pOut);
    if( fossil_islower(zOut[0]) && zOut[1]==':' && zOut[2]=='/' ){
      zOut[0] = fossil_toupper(zOut[0]);
    }










  }
#endif



  blob_resize(pOut, file_simplify_name(blob_buffer(pOut),
                                       blob_size(pOut), slash));
}

/*
** COMMAND:  test-canonical-name
** Usage: %fossil test-canonical-name FILENAME...
................................................................................
      memcpy(&tmp, pOut, sizeof(tmp));
      blob_set(pOut, "./");
      blob_append(pOut, &zPath[i+1], -1);
      blob_reset(&tmp);
      return;
    }
    while( zPath[i-1]!='/' ){ i--; }
    if( zPwd[0]=='/' && strlen(zPwd)==1 ){
      // If on '/', don't go to higher level
      blob_zero(&tmp);
    }else{
      blob_set(&tmp, "../");
    }
    for(j=i; zPwd[j]; j++){
      if( zPwd[j]=='/' ){
        blob_append(&tmp, "../", 3);
      }
    }
    blob_append(&tmp, &zPath[i], -1);
    blob_reset(pOut);
................................................................................
  if( filenames_are_case_sensitive() ){
    xCmp = fossil_strncmp;
  }else{
    xCmp = fossil_strnicmp;
  }

  /* Special case.  zOrigName refers to g.zLocalRoot directory. */
  if( nFull==nLocalRoot-1 && xCmp(zLocalRoot, zFull, nFull)==0 
      || (nFull==1 && zFull[0]=='/' && nLocalRoot==1 && zLocalRoot[0]=='/') ){
    blob_append(pOut, ".", 1);
    blob_reset(&localRoot);
    blob_reset(&full);
    return 1;
  }

  if( nFull<=nLocalRoot || xCmp(zLocalRoot, zFull, nLocalRoot) ){

Changes to src/update.c.

351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
    "       isexe, islinkv, islinkt, deleted FROM fv ORDER BY 1"
  );
  db_prepare(&mtimeXfer,
    "UPDATE vfile SET mtime=(SELECT mtime FROM vfile WHERE id=:idv)"
    " WHERE id=:idt"
  );
  assert( g.zLocalRoot!=0 );
  assert( strlen(g.zLocalRoot)>1 );
  assert( g.zLocalRoot[strlen(g.zLocalRoot)-1]=='/' );
  while( db_step(&q)==SQLITE_ROW ){
    const char *zName = db_column_text(&q, 0);  /* The filename from root */
    int idv = db_column_int(&q, 1);             /* VFILE entry for current */
    int ridv = db_column_int(&q, 2);            /* RecordID for current */
    int idt = db_column_int(&q, 3);             /* VFILE entry for target */
    int ridt = db_column_int(&q, 4);            /* RecordID for target */







|







351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
    "       isexe, islinkv, islinkt, deleted FROM fv ORDER BY 1"
  );
  db_prepare(&mtimeXfer,
    "UPDATE vfile SET mtime=(SELECT mtime FROM vfile WHERE id=:idv)"
    " WHERE id=:idt"
  );
  assert( g.zLocalRoot!=0 );
  assert( strlen(g.zLocalRoot)>0 );
  assert( g.zLocalRoot[strlen(g.zLocalRoot)-1]=='/' );
  while( db_step(&q)==SQLITE_ROW ){
    const char *zName = db_column_text(&q, 0);  /* The filename from root */
    int idv = db_column_int(&q, 1);             /* VFILE entry for current */
    int ridv = db_column_int(&q, 2);            /* RecordID for current */
    int idt = db_column_int(&q, 3);             /* VFILE entry for target */
    int ridt = db_column_int(&q, 4);            /* RecordID for target */