Fossil

Check-in [af194dbb]
Login

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

Overview
Comment:Merge again checkout_on_root_fix.

Fix more cases when working from '/', should not affect when working normally.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:af194dbb16b74d8b6b3e9b4731fc48a57788d617
User & Date: mgagnon 2014-01-09 11:24:23
References
2014-01-10
12:42 Fixed ticket [ee97701f]: "fossil add" broken for repos opened into "/" plus 5 other changes artifact: 18f9fdc2 user: mgagnon
Context
2014-01-09
11:57
Change C++ comments to C commenting style check-in: 25950f8b user: jan.nijtmans tags: trunk
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

10:41
Upgrade mingw and msc makefiles to use openssl-1.0.1f in stead of openssl-1.0.1e check-in: ef47028a user: jan.nijtmans 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
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 */