Fossil SCM

More improvements to "fossil open": Make sure the --repodir is converted into a full pathname so that it is unaffected by --workdir. Report an error with --nested if the new repo would be rooted in the same directory as another repository.

drh 2020-08-08 15:01 trunk
Commit 15a7b1fd377dd67b4c302ad708fd918ad380e9e383599c699233b724155028d4
2 files changed +15 -7 +17
+15 -7
--- src/db.c
+++ src/db.c
@@ -1714,16 +1714,20 @@
17141714
**
17151715
** If no valid _FOSSIL_ or .fslckout file is found, we move up one level and
17161716
** try again. Once the file is found, the g.zLocalRoot variable is set
17171717
** to the root of the repository tree and this routine returns 1. If
17181718
** no database is found, then this routine return 0.
1719
+**
1720
+** In db_open_local_v2(), if the bRootOnly flag is true, then only
1721
+** look in the CWD for the checkout database. Do not scan upwards in
1722
+** the file hierarchy.
17191723
**
17201724
** This routine always opens the user database regardless of whether or
17211725
** not the repository database is found. If the _FOSSIL_ or .fslckout file
17221726
** is found, it is attached to the open database connection too.
17231727
*/
1724
-int db_open_local(const char *zDbName){
1728
+int db_open_local_v2(const char *zDbName, int bRootOnly){
17251729
int i, n;
17261730
char zPwd[2000];
17271731
static const char *(aDbName[]) = { "_FOSSIL_", ".fslckout", ".fos" };
17281732
17291733
if( g.localOpen ) return 1;
@@ -1747,18 +1751,22 @@
17471751
g.localOpen = 1;
17481752
db_open_repository(zDbName);
17491753
return 1;
17501754
}
17511755
}
1756
+ if( bRootOnly ) break;
17521757
n--;
17531758
while( n>1 && zPwd[n]!='/' ){ n--; }
17541759
while( n>1 && zPwd[n-1]=='/' ){ n--; }
17551760
zPwd[n] = 0;
17561761
}
17571762
17581763
/* A checkout database file could not be found */
17591764
return 0;
1765
+}
1766
+int db_open_local(const char *zDbName){
1767
+ return db_open_local_v2(zDbName, 0);
17601768
}
17611769
17621770
/*
17631771
** Get the full pathname to the repository database file. The
17641772
** local database (the _FOSSIL_ or .fslckout database) must have already
@@ -3121,11 +3129,10 @@
31213129
int setmtimeFlag; /* --setmtime. Set mtimes on files */
31223130
static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0, 0 };
31233131
const char *zWorkDir; /* --workdir value */
31243132
const char *zRepo = 0; /* Name of the repository file */
31253133
const char *zRepoDir = 0; /* --repodir value */
3126
- Blob normalizedRepoName; /* Normalized repository filename */
31273134
char *zPwd; /* Initial working directory */
31283135
int isUri = 0; /* True if REPOSITORY is a URI */
31293136
31303137
url_proxy_options();
31313138
emptyFlag = find_option("empty",0,0)!=0;
@@ -3143,11 +3150,10 @@
31433150
31443151
if( g.argc!=3 && g.argc!=4 ){
31453152
usage("REPOSITORY-FILENAME ?VERSION?");
31463153
}
31473154
zRepo = g.argv[2];
3148
- blob_init(&normalizedRepoName, 0, 0);
31493155
if( sqlite3_strglob("http://*", zRepo)==0
31503156
|| sqlite3_strglob("https://*", zRepo)==0
31513157
|| sqlite3_strglob("ssh:*", zRepo)==0
31523158
|| sqlite3_strglob("file:*", zRepo)==0
31533159
){
@@ -3155,12 +3161,14 @@
31553161
}
31563162
31573163
/* If --workdir is specified, change to the requested working directory */
31583164
if( zWorkDir ){
31593165
if( !isUri ){
3160
- file_canonical_name(zRepo, &normalizedRepoName, 0);
3161
- zRepo = blob_str(&normalizedRepoName);
3166
+ zRepo = file_canonical_name_dup(zRepo);
3167
+ }
3168
+ if( zRepoDir ){
3169
+ zRepoDir = file_canonical_name_dup(zRepoDir);
31623170
}
31633171
if( file_isdir(zWorkDir, ExtFILE)!=1 ){
31643172
file_mkfolder(zWorkDir, ExtFILE, 0, 0);
31653173
if( file_mkdir(zWorkDir, ExtFILE, 0) ){
31663174
fossil_fatal("cannot create directory %s", zWorkDir);
@@ -3169,12 +3177,12 @@
31693177
if( file_chdir(zWorkDir, 0) ){
31703178
fossil_fatal("unable to make %s the working directory", zWorkDir);
31713179
}
31723180
}
31733181
3174
- if( !allowNested && db_open_local(0) ){
3175
- fossil_fatal("already within an open tree rooted at %s", g.zLocalRoot);
3182
+ if( db_open_local_v2(0, allowNested) ){
3183
+ fossil_fatal("there is already an open tree at %s", g.zLocalRoot);
31763184
}
31773185
31783186
/* If REPOSITORY looks like a URI, then try to clone it first */
31793187
if( isUri ){
31803188
char *zNewBase; /* Base name of the cloned repository file */
31813189
--- src/db.c
+++ src/db.c
@@ -1714,16 +1714,20 @@
1714 **
1715 ** If no valid _FOSSIL_ or .fslckout file is found, we move up one level and
1716 ** try again. Once the file is found, the g.zLocalRoot variable is set
1717 ** to the root of the repository tree and this routine returns 1. If
1718 ** no database is found, then this routine return 0.
 
 
 
 
1719 **
1720 ** This routine always opens the user database regardless of whether or
1721 ** not the repository database is found. If the _FOSSIL_ or .fslckout file
1722 ** is found, it is attached to the open database connection too.
1723 */
1724 int db_open_local(const char *zDbName){
1725 int i, n;
1726 char zPwd[2000];
1727 static const char *(aDbName[]) = { "_FOSSIL_", ".fslckout", ".fos" };
1728
1729 if( g.localOpen ) return 1;
@@ -1747,18 +1751,22 @@
1747 g.localOpen = 1;
1748 db_open_repository(zDbName);
1749 return 1;
1750 }
1751 }
 
1752 n--;
1753 while( n>1 && zPwd[n]!='/' ){ n--; }
1754 while( n>1 && zPwd[n-1]=='/' ){ n--; }
1755 zPwd[n] = 0;
1756 }
1757
1758 /* A checkout database file could not be found */
1759 return 0;
 
 
 
1760 }
1761
1762 /*
1763 ** Get the full pathname to the repository database file. The
1764 ** local database (the _FOSSIL_ or .fslckout database) must have already
@@ -3121,11 +3129,10 @@
3121 int setmtimeFlag; /* --setmtime. Set mtimes on files */
3122 static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0, 0 };
3123 const char *zWorkDir; /* --workdir value */
3124 const char *zRepo = 0; /* Name of the repository file */
3125 const char *zRepoDir = 0; /* --repodir value */
3126 Blob normalizedRepoName; /* Normalized repository filename */
3127 char *zPwd; /* Initial working directory */
3128 int isUri = 0; /* True if REPOSITORY is a URI */
3129
3130 url_proxy_options();
3131 emptyFlag = find_option("empty",0,0)!=0;
@@ -3143,11 +3150,10 @@
3143
3144 if( g.argc!=3 && g.argc!=4 ){
3145 usage("REPOSITORY-FILENAME ?VERSION?");
3146 }
3147 zRepo = g.argv[2];
3148 blob_init(&normalizedRepoName, 0, 0);
3149 if( sqlite3_strglob("http://*", zRepo)==0
3150 || sqlite3_strglob("https://*", zRepo)==0
3151 || sqlite3_strglob("ssh:*", zRepo)==0
3152 || sqlite3_strglob("file:*", zRepo)==0
3153 ){
@@ -3155,12 +3161,14 @@
3155 }
3156
3157 /* If --workdir is specified, change to the requested working directory */
3158 if( zWorkDir ){
3159 if( !isUri ){
3160 file_canonical_name(zRepo, &normalizedRepoName, 0);
3161 zRepo = blob_str(&normalizedRepoName);
 
 
3162 }
3163 if( file_isdir(zWorkDir, ExtFILE)!=1 ){
3164 file_mkfolder(zWorkDir, ExtFILE, 0, 0);
3165 if( file_mkdir(zWorkDir, ExtFILE, 0) ){
3166 fossil_fatal("cannot create directory %s", zWorkDir);
@@ -3169,12 +3177,12 @@
3169 if( file_chdir(zWorkDir, 0) ){
3170 fossil_fatal("unable to make %s the working directory", zWorkDir);
3171 }
3172 }
3173
3174 if( !allowNested && db_open_local(0) ){
3175 fossil_fatal("already within an open tree rooted at %s", g.zLocalRoot);
3176 }
3177
3178 /* If REPOSITORY looks like a URI, then try to clone it first */
3179 if( isUri ){
3180 char *zNewBase; /* Base name of the cloned repository file */
3181
--- src/db.c
+++ src/db.c
@@ -1714,16 +1714,20 @@
1714 **
1715 ** If no valid _FOSSIL_ or .fslckout file is found, we move up one level and
1716 ** try again. Once the file is found, the g.zLocalRoot variable is set
1717 ** to the root of the repository tree and this routine returns 1. If
1718 ** no database is found, then this routine return 0.
1719 **
1720 ** In db_open_local_v2(), if the bRootOnly flag is true, then only
1721 ** look in the CWD for the checkout database. Do not scan upwards in
1722 ** the file hierarchy.
1723 **
1724 ** This routine always opens the user database regardless of whether or
1725 ** not the repository database is found. If the _FOSSIL_ or .fslckout file
1726 ** is found, it is attached to the open database connection too.
1727 */
1728 int db_open_local_v2(const char *zDbName, int bRootOnly){
1729 int i, n;
1730 char zPwd[2000];
1731 static const char *(aDbName[]) = { "_FOSSIL_", ".fslckout", ".fos" };
1732
1733 if( g.localOpen ) return 1;
@@ -1747,18 +1751,22 @@
1751 g.localOpen = 1;
1752 db_open_repository(zDbName);
1753 return 1;
1754 }
1755 }
1756 if( bRootOnly ) break;
1757 n--;
1758 while( n>1 && zPwd[n]!='/' ){ n--; }
1759 while( n>1 && zPwd[n-1]=='/' ){ n--; }
1760 zPwd[n] = 0;
1761 }
1762
1763 /* A checkout database file could not be found */
1764 return 0;
1765 }
1766 int db_open_local(const char *zDbName){
1767 return db_open_local_v2(zDbName, 0);
1768 }
1769
1770 /*
1771 ** Get the full pathname to the repository database file. The
1772 ** local database (the _FOSSIL_ or .fslckout database) must have already
@@ -3121,11 +3129,10 @@
3129 int setmtimeFlag; /* --setmtime. Set mtimes on files */
3130 static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0, 0 };
3131 const char *zWorkDir; /* --workdir value */
3132 const char *zRepo = 0; /* Name of the repository file */
3133 const char *zRepoDir = 0; /* --repodir value */
 
3134 char *zPwd; /* Initial working directory */
3135 int isUri = 0; /* True if REPOSITORY is a URI */
3136
3137 url_proxy_options();
3138 emptyFlag = find_option("empty",0,0)!=0;
@@ -3143,11 +3150,10 @@
3150
3151 if( g.argc!=3 && g.argc!=4 ){
3152 usage("REPOSITORY-FILENAME ?VERSION?");
3153 }
3154 zRepo = g.argv[2];
 
3155 if( sqlite3_strglob("http://*", zRepo)==0
3156 || sqlite3_strglob("https://*", zRepo)==0
3157 || sqlite3_strglob("ssh:*", zRepo)==0
3158 || sqlite3_strglob("file:*", zRepo)==0
3159 ){
@@ -3155,12 +3161,14 @@
3161 }
3162
3163 /* If --workdir is specified, change to the requested working directory */
3164 if( zWorkDir ){
3165 if( !isUri ){
3166 zRepo = file_canonical_name_dup(zRepo);
3167 }
3168 if( zRepoDir ){
3169 zRepoDir = file_canonical_name_dup(zRepoDir);
3170 }
3171 if( file_isdir(zWorkDir, ExtFILE)!=1 ){
3172 file_mkfolder(zWorkDir, ExtFILE, 0, 0);
3173 if( file_mkdir(zWorkDir, ExtFILE, 0) ){
3174 fossil_fatal("cannot create directory %s", zWorkDir);
@@ -3169,12 +3177,12 @@
3177 if( file_chdir(zWorkDir, 0) ){
3178 fossil_fatal("unable to make %s the working directory", zWorkDir);
3179 }
3180 }
3181
3182 if( db_open_local_v2(0, allowNested) ){
3183 fossil_fatal("there is already an open tree at %s", g.zLocalRoot);
3184 }
3185
3186 /* If REPOSITORY looks like a URI, then try to clone it first */
3187 if( isUri ){
3188 char *zNewBase; /* Base name of the cloned repository file */
3189
+17
--- src/file.c
+++ src/file.c
@@ -1105,10 +1105,12 @@
11051105
** Remove redundant / characters
11061106
** Remove all /./ path elements.
11071107
** Convert /A/../ to just /
11081108
** If the slash parameter is non-zero, the trailing slash, if any,
11091109
** is retained.
1110
+**
1111
+** See also: file_canonical_name_dup()
11101112
*/
11111113
void file_canonical_name(const char *zOrigName, Blob *pOut, int slash){
11121114
blob_zero(pOut);
11131115
if( file_is_absolute_path(zOrigName) ){
11141116
blob_appendf(pOut, "%/", zOrigName);
@@ -1140,10 +1142,25 @@
11401142
}
11411143
#endif
11421144
blob_resize(pOut, file_simplify_name(blob_buffer(pOut),
11431145
blob_size(pOut), slash));
11441146
}
1147
+
1148
+/*
1149
+** Compute the canonical name of a file. Store that name in
1150
+** memory obtained from fossil_malloc() and return a pointer to the
1151
+** name.
1152
+**
1153
+** See also: file_canonical_name()
1154
+*/
1155
+char *file_canonical_name_dup(const char *zOrigName){
1156
+ Blob x;
1157
+ if( zOrigName==0 ) return 0;
1158
+ blob_init(&x, 0, 0);
1159
+ file_canonical_name(zOrigName, &x, 0);
1160
+ return blob_str(&x);
1161
+}
11451162
11461163
/*
11471164
** The input is the name of an executable, such as one might
11481165
** type on a command-line. This routine resolves that name into
11491166
** a full pathname. The result is obtained from fossil_malloc()
11501167
--- src/file.c
+++ src/file.c
@@ -1105,10 +1105,12 @@
1105 ** Remove redundant / characters
1106 ** Remove all /./ path elements.
1107 ** Convert /A/../ to just /
1108 ** If the slash parameter is non-zero, the trailing slash, if any,
1109 ** is retained.
 
 
1110 */
1111 void file_canonical_name(const char *zOrigName, Blob *pOut, int slash){
1112 blob_zero(pOut);
1113 if( file_is_absolute_path(zOrigName) ){
1114 blob_appendf(pOut, "%/", zOrigName);
@@ -1140,10 +1142,25 @@
1140 }
1141 #endif
1142 blob_resize(pOut, file_simplify_name(blob_buffer(pOut),
1143 blob_size(pOut), slash));
1144 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1145
1146 /*
1147 ** The input is the name of an executable, such as one might
1148 ** type on a command-line. This routine resolves that name into
1149 ** a full pathname. The result is obtained from fossil_malloc()
1150
--- src/file.c
+++ src/file.c
@@ -1105,10 +1105,12 @@
1105 ** Remove redundant / characters
1106 ** Remove all /./ path elements.
1107 ** Convert /A/../ to just /
1108 ** If the slash parameter is non-zero, the trailing slash, if any,
1109 ** is retained.
1110 **
1111 ** See also: file_canonical_name_dup()
1112 */
1113 void file_canonical_name(const char *zOrigName, Blob *pOut, int slash){
1114 blob_zero(pOut);
1115 if( file_is_absolute_path(zOrigName) ){
1116 blob_appendf(pOut, "%/", zOrigName);
@@ -1140,10 +1142,25 @@
1142 }
1143 #endif
1144 blob_resize(pOut, file_simplify_name(blob_buffer(pOut),
1145 blob_size(pOut), slash));
1146 }
1147
1148 /*
1149 ** Compute the canonical name of a file. Store that name in
1150 ** memory obtained from fossil_malloc() and return a pointer to the
1151 ** name.
1152 **
1153 ** See also: file_canonical_name()
1154 */
1155 char *file_canonical_name_dup(const char *zOrigName){
1156 Blob x;
1157 if( zOrigName==0 ) return 0;
1158 blob_init(&x, 0, 0);
1159 file_canonical_name(zOrigName, &x, 0);
1160 return blob_str(&x);
1161 }
1162
1163 /*
1164 ** The input is the name of an executable, such as one might
1165 ** type on a command-line. This routine resolves that name into
1166 ** a full pathname. The result is obtained from fossil_malloc()
1167

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button