Fossil SCM

Disconnect the global configuration database in ~/.fossil from the respository database in most cases. This allows multiple "sync" or "commit" operations to be running on different repositories at the same time.

drh 2009-08-13 14:27 trunk
Commit 00ac7945a9ead7200d6ad4404ca432c683b9c4c7
+1 -1
--- src/allrepo.c
+++ src/allrepo.c
@@ -89,11 +89,11 @@
8989
9090
if( g.argc<3 ){
9191
usage("list|ls|pull|push|rebuild|sync");
9292
}
9393
n = strlen(g.argv[2]);
94
- db_open_config();
94
+ db_open_config(1);
9595
zCmd = g.argv[2];
9696
if( strncmp(zCmd, "list", n)==0 ){
9797
zCmd = "list";
9898
}else if( strncmp(zCmd, "ls", n)==0 ){ /* alias for "list" above */
9999
zCmd = "list";
100100
--- src/allrepo.c
+++ src/allrepo.c
@@ -89,11 +89,11 @@
89
90 if( g.argc<3 ){
91 usage("list|ls|pull|push|rebuild|sync");
92 }
93 n = strlen(g.argv[2]);
94 db_open_config();
95 zCmd = g.argv[2];
96 if( strncmp(zCmd, "list", n)==0 ){
97 zCmd = "list";
98 }else if( strncmp(zCmd, "ls", n)==0 ){ /* alias for "list" above */
99 zCmd = "list";
100
--- src/allrepo.c
+++ src/allrepo.c
@@ -89,11 +89,11 @@
89
90 if( g.argc<3 ){
91 usage("list|ls|pull|push|rebuild|sync");
92 }
93 n = strlen(g.argv[2]);
94 db_open_config(1);
95 zCmd = g.argv[2];
96 if( strncmp(zCmd, "list", n)==0 ){
97 zCmd = "list";
98 }else if( strncmp(zCmd, "ls", n)==0 ){ /* alias for "list" above */
99 zCmd = "list";
100
+1 -1
--- src/cgi.c
+++ src/cgi.c
@@ -678,11 +678,11 @@
678678
if( z ){
679679
z = mprintf("%s",z);
680680
add_param_list(z, '&');
681681
}
682682
683
- z = P("REMOTE_ADDR");
683
+ z = (char*)P("REMOTE_ADDR");
684684
if( z ) g.zIpAddr = mprintf("%s", z);
685685
686686
len = atoi(PD("CONTENT_LENGTH", "0"));
687687
g.zContentType = zType = P("CONTENT_TYPE");
688688
if( len>0 && zType ){
689689
--- src/cgi.c
+++ src/cgi.c
@@ -678,11 +678,11 @@
678 if( z ){
679 z = mprintf("%s",z);
680 add_param_list(z, '&');
681 }
682
683 z = P("REMOTE_ADDR");
684 if( z ) g.zIpAddr = mprintf("%s", z);
685
686 len = atoi(PD("CONTENT_LENGTH", "0"));
687 g.zContentType = zType = P("CONTENT_TYPE");
688 if( len>0 && zType ){
689
--- src/cgi.c
+++ src/cgi.c
@@ -678,11 +678,11 @@
678 if( z ){
679 z = mprintf("%s",z);
680 add_param_list(z, '&');
681 }
682
683 z = (char*)P("REMOTE_ADDR");
684 if( z ) g.zIpAddr = mprintf("%s", z);
685
686 len = atoi(PD("CONTENT_LENGTH", "0"));
687 g.zContentType = zType = P("CONTENT_TYPE");
688 if( len>0 && zType ){
689
+1 -2
--- src/clone.c
+++ src/clone.c
@@ -41,20 +41,19 @@
4141
char *zPassword;
4242
url_proxy_options();
4343
if( g.argc!=4 ){
4444
usage("FILE-OR-URL NEW-REPOSITORY");
4545
}
46
- db_open_config();
46
+ db_open_config(0);
4747
if( file_size(g.argv[3])>0 ){
4848
fossil_panic("file already exists: %s", g.argv[3]);
4949
}
5050
url_parse(g.argv[2]);
5151
if( g.urlIsFile ){
5252
file_copy(g.urlName, g.argv[3]);
5353
db_close();
5454
db_open_repository(g.argv[3]);
55
- db_open_config();
5655
db_record_repository_filename(g.argv[3]);
5756
db_multi_exec(
5857
"REPLACE INTO config(name,value)"
5958
" VALUES('server-code', lower(hex(randomblob(20))));"
6059
"REPLACE INTO config(name,value)"
6160
--- src/clone.c
+++ src/clone.c
@@ -41,20 +41,19 @@
41 char *zPassword;
42 url_proxy_options();
43 if( g.argc!=4 ){
44 usage("FILE-OR-URL NEW-REPOSITORY");
45 }
46 db_open_config();
47 if( file_size(g.argv[3])>0 ){
48 fossil_panic("file already exists: %s", g.argv[3]);
49 }
50 url_parse(g.argv[2]);
51 if( g.urlIsFile ){
52 file_copy(g.urlName, g.argv[3]);
53 db_close();
54 db_open_repository(g.argv[3]);
55 db_open_config();
56 db_record_repository_filename(g.argv[3]);
57 db_multi_exec(
58 "REPLACE INTO config(name,value)"
59 " VALUES('server-code', lower(hex(randomblob(20))));"
60 "REPLACE INTO config(name,value)"
61
--- src/clone.c
+++ src/clone.c
@@ -41,20 +41,19 @@
41 char *zPassword;
42 url_proxy_options();
43 if( g.argc!=4 ){
44 usage("FILE-OR-URL NEW-REPOSITORY");
45 }
46 db_open_config(0);
47 if( file_size(g.argv[3])>0 ){
48 fossil_panic("file already exists: %s", g.argv[3]);
49 }
50 url_parse(g.argv[2]);
51 if( g.urlIsFile ){
52 file_copy(g.urlName, g.argv[3]);
53 db_close();
54 db_open_repository(g.argv[3]);
 
55 db_record_repository_filename(g.argv[3]);
56 db_multi_exec(
57 "REPLACE INTO config(name,value)"
58 " VALUES('server-code', lower(hex(randomblob(20))));"
59 "REPLACE INTO config(name,value)"
60
+1 -1
--- src/construct.c
+++ src/construct.c
@@ -137,11 +137,11 @@
137137
}
138138
139139
/* Create the foundation */
140140
db_create_repository(zRepository);
141141
db_open_repository(zRepository);
142
- db_open_config();
142
+ db_open_config(0);
143143
db_begin_transaction();
144144
145145
db_initial_setup(0, 1);
146146
147147
printf("project-id: %s\n", db_get("project-code", 0));
148148
--- src/construct.c
+++ src/construct.c
@@ -137,11 +137,11 @@
137 }
138
139 /* Create the foundation */
140 db_create_repository(zRepository);
141 db_open_repository(zRepository);
142 db_open_config();
143 db_begin_transaction();
144
145 db_initial_setup(0, 1);
146
147 printf("project-id: %s\n", db_get("project-code", 0));
148
--- src/construct.c
+++ src/construct.c
@@ -137,11 +137,11 @@
137 }
138
139 /* Create the foundation */
140 db_create_repository(zRepository);
141 db_open_repository(zRepository);
142 db_open_config(0);
143 db_begin_transaction();
144
145 db_initial_setup(0, 1);
146
147 printf("project-id: %s\n", db_get("project-code", 0));
148
+96 -29
--- src/db.c
+++ src/db.c
@@ -618,10 +618,33 @@
618618
}
619619
va_end(ap);
620620
sqlite3_exec(db, "COMMIT", 0, 0, 0);
621621
sqlite3_close(db);
622622
}
623
+
624
+/*
625
+** Open a database file. Return a pointer to the new database
626
+** connection. An error results in process abort.
627
+*/
628
+static sqlite3 *openDatabase(const char *zDbName){
629
+ int rc;
630
+ const char *zVfs;
631
+ sqlite3 *db;
632
+
633
+ zVfs = getenv("FOSSIL_VFS");
634
+ rc = sqlite3_open_v2(
635
+ zDbName, &db,
636
+ SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
637
+ zVfs
638
+ );
639
+ if( rc!=SQLITE_OK ){
640
+ db_err(sqlite3_errmsg(db));
641
+ }
642
+ sqlite3_busy_timeout(db, 5000);
643
+ return db;
644
+}
645
+
623646
624647
/*
625648
** zDbName is the name of a database file. If no other database
626649
** file is open, then open this one. If another database file is
627650
** already open, then attach zDbName using the name zLabel.
@@ -629,34 +652,30 @@
629652
void db_open_or_attach(const char *zDbName, const char *zLabel){
630653
#ifdef __MINGW32__
631654
zDbName = mbcsToUtf8(zDbName);
632655
#endif
633656
if( !g.db ){
634
- int rc;
635
- const char *zVfs;
636
-
637
- zVfs = getenv("FOSSIL_VFS");
638
- rc = sqlite3_open_v2(
639
- zDbName, &g.db,
640
- SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
641
- zVfs
642
- );
643
- if( rc!=SQLITE_OK ){
644
- db_err(sqlite3_errmsg(g.db));
645
- }
646
- sqlite3_busy_timeout(g.db, 5000);
657
+ g.db = openDatabase(zDbName);
647658
db_connection_init();
648659
}else{
649660
db_multi_exec("ATTACH DATABASE %Q AS %s", zDbName, zLabel);
650661
}
651662
}
652663
653664
/*
654665
** Open the user database in "~/.fossil". Create the database anew if
655666
** it does not already exist.
667
+**
668
+** If the useAttach flag is 0 (the usual case) then the user database is
669
+** opened on a separate database connection g.dbConfig. This prevents
670
+** the ~/.fossil database from becoming locked on long check-in or sync
671
+** operations which hold an exclusive transaction. In a few cases, though,
672
+** it is convenient for the ~/.fossil to be attached to the main database
673
+** connection so that we can join between the various databases. In that
674
+** case, invoke this routine with useAttach as 1.
656675
*/
657
-void db_open_config(void){
676
+void db_open_config(int useAttach){
658677
char *zDbName;
659678
const char *zHome;
660679
if( g.configOpen ) return;
661680
#ifdef __MINGW32__
662681
zHome = getenv("LOCALAPPDATA");
@@ -684,11 +703,17 @@
684703
zDbName = mprintf("%s/.fossil", zHome);
685704
#endif
686705
if( file_size(zDbName)<1024*3 ){
687706
db_init_database(zDbName, zConfigSchema, (char*)0);
688707
}
689
- db_open_or_attach(zDbName, "configdb");
708
+ g.useAttach = useAttach;
709
+ if( useAttach ){
710
+ db_open_or_attach(zDbName, "configdb");
711
+ g.dbConfig = 0;
712
+ }else{
713
+ g.dbConfig = openDatabase(zDbName);
714
+ }
690715
g.configOpen = 1;
691716
}
692717
693718
/*
694719
** If zDbName is a valid local database file, open it and return
@@ -702,11 +727,11 @@
702727
if( access(zDbName, F_OK) ) return 0;
703728
lsize = file_size(zDbName);
704729
if( lsize%1024!=0 || lsize<4096 ) return 0;
705730
db_open_or_attach(zDbName, "localdb");
706731
g.localOpen = 1;
707
- db_open_config();
732
+ db_open_config(0);
708733
db_open_repository(0);
709734
710735
/* If the "mtime" column is missing from the vfile table, then
711736
** add it now. This code added on 2008-12-06. After all users have
712737
** upgraded, this code can be safely deleted.
@@ -987,11 +1012,11 @@
9871012
if( g.argc!=3 ){
9881013
usage("REPOSITORY-NAME");
9891014
}
9901015
db_create_repository(g.argv[2]);
9911016
db_open_repository(g.argv[2]);
992
- db_open_config();
1017
+ db_open_config(0);
9931018
db_begin_transaction();
9941019
db_initial_setup(zDate, 1);
9951020
db_end_transaction(0);
9961021
printf("project-id: %s\n", db_get("project-code", 0));
9971022
printf("server-id: %s\n", db_get("server-code", 0));
@@ -1145,10 +1170,27 @@
11451170
for(i=0; i<sizeof(azOff)/sizeof(azOff[0]); i++){
11461171
if( strcmp(zVal,azOff[i])==0 ) return 1;
11471172
}
11481173
return 0;
11491174
}
1175
+
1176
+/*
1177
+** Swap the g.db and g.dbConfig connections so that the various db_* routines
1178
+** work on the ~/.fossil database instead of on the repository database.
1179
+** Be sure to swap them back after doing the operation.
1180
+**
1181
+** If g.useAttach that means the ~/.fossil database was opened with
1182
+** the useAttach flag set to 1. In that case no connection swap is required
1183
+** so this routine is a no-op.
1184
+*/
1185
+void db_swap_connections(void){
1186
+ if( !g.useAttach ){
1187
+ sqlite3 *dbTemp = g.db;
1188
+ g.db = g.dbConfig;
1189
+ g.dbConfig = dbTemp;
1190
+ }
1191
+}
11501192
11511193
/*
11521194
** Get and set values from the CONFIG, GLOBAL_CONFIG and VVAR table in the
11531195
** repository and local databases.
11541196
*/
@@ -1156,41 +1198,57 @@
11561198
char *z = 0;
11571199
if( g.repositoryOpen ){
11581200
z = db_text(0, "SELECT value FROM config WHERE name=%Q", zName);
11591201
}
11601202
if( z==0 && g.configOpen ){
1203
+ db_swap_connections();
11611204
z = db_text(0, "SELECT value FROM global_config WHERE name=%Q", zName);
1205
+ db_swap_connections();
11621206
}
11631207
if( z==0 ){
11641208
z = zDefault;
11651209
}
11661210
return z;
11671211
}
11681212
void db_set(const char *zName, const char *zValue, int globalFlag){
11691213
db_begin_transaction();
1170
- db_multi_exec("REPLACE INTO %sconfig(name,value) VALUES(%Q,%Q)",
1171
- globalFlag ? "global_" : "", zName, zValue);
1214
+ if( globalFlag ){
1215
+ db_swap_connections();
1216
+ db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%Q)",
1217
+ zName, zValue);
1218
+ db_swap_connections();
1219
+ }else{
1220
+ db_multi_exec("REPLACE INTO config(name,value) VALUES(%Q,%Q)",
1221
+ zName, zValue);
1222
+ }
11721223
if( globalFlag && g.repositoryOpen ){
11731224
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
11741225
}
11751226
db_end_transaction(0);
11761227
}
11771228
void db_unset(const char *zName, int globalFlag){
11781229
db_begin_transaction();
1179
- db_multi_exec("DELETE FROM %sconfig WHERE name=%Q",
1180
- globalFlag ? "global_" : "", zName);
1230
+ if( globalFlag ){
1231
+ db_swap_connections();
1232
+ db_multi_exec("DELETE INTO global_config WHERE name=%Q", zName);
1233
+ db_swap_connections();
1234
+ }else{
1235
+ db_multi_exec("DELETE INTO config WHERE name=%Q", zName);
1236
+ }
11811237
if( globalFlag && g.repositoryOpen ){
11821238
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
11831239
}
11841240
db_end_transaction(0);
11851241
}
11861242
int db_is_global(const char *zName){
1243
+ int rc = 0;
11871244
if( g.configOpen ){
1188
- return db_exists("SELECT 1 FROM global_config WHERE name=%Q", zName);
1189
- }else{
1190
- return 0;
1245
+ db_swap_connections();
1246
+ rc = db_exists("SELECT 1 FROM global_config WHERE name=%Q", zName);
1247
+ db_swap_connections();
11911248
}
1249
+ return rc;
11921250
}
11931251
int db_get_int(const char *zName, int dflt){
11941252
int v = dflt;
11951253
int rc;
11961254
if( g.repositoryOpen ){
@@ -1203,22 +1261,29 @@
12031261
db_finalize(&q);
12041262
}else{
12051263
rc = SQLITE_DONE;
12061264
}
12071265
if( rc==SQLITE_DONE && g.configOpen ){
1266
+ db_swap_connections();
12081267
v = db_int(dflt, "SELECT value FROM global_config WHERE name=%Q", zName);
1268
+ db_swap_connections();
12091269
}
12101270
return v;
12111271
}
12121272
void db_set_int(const char *zName, int value, int globalFlag){
1213
- db_begin_transaction();
1214
- db_multi_exec("REPLACE INTO %sconfig(name,value) VALUES(%Q,%d)",
1215
- globalFlag ? "global_" : "", zName, value);
1273
+ if( globalFlag ){
1274
+ db_swap_connections();
1275
+ db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%d)",
1276
+ zName, value);
1277
+ db_swap_connections();
1278
+ }else{
1279
+ db_multi_exec("REPLACE INTO config(name,value) VALUES(%Q,%d)",
1280
+ zName, value);
1281
+ }
12161282
if( globalFlag && g.repositoryOpen ){
12171283
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
12181284
}
1219
- db_end_transaction(0);
12201285
}
12211286
int db_get_boolean(const char *zName, int dflt){
12221287
char *zVal = db_get(zName, dflt ? "on" : "off");
12231288
if( is_truth(zVal) ) return 1;
12241289
if( is_false(zVal) ) return 0;
@@ -1252,15 +1317,17 @@
12521317
if( zName==0 ){
12531318
if( !g.localOpen ) return;
12541319
zName = db_lget("repository", 0);
12551320
}
12561321
file_canonical_name(zName, &full);
1322
+ db_swap_connections();
12571323
db_multi_exec(
12581324
"INSERT OR IGNORE INTO global_config(name,value)"
12591325
"VALUES('repo:%q',1)",
12601326
blob_str(&full)
12611327
);
1328
+ db_swap_connections();
12621329
blob_reset(&full);
12631330
}
12641331
12651332
/*
12661333
** COMMAND: open
@@ -1412,15 +1479,15 @@
14121479
"web-browser",
14131480
};
14141481
int i;
14151482
int globalFlag = find_option("global","g",0)!=0;
14161483
int unsetFlag = g.argv[1][0]=='u';
1484
+ db_open_config(1);
14171485
db_find_and_open_repository(0);
14181486
if( !g.repositoryOpen ){
14191487
globalFlag = 1;
14201488
}
1421
- db_open_config();
14221489
if( unsetFlag && g.argc!=3 ){
14231490
usage("PROPERTY ?-global?");
14241491
}
14251492
if( g.argc==2 ){
14261493
for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){
14271494
--- src/db.c
+++ src/db.c
@@ -618,10 +618,33 @@
618 }
619 va_end(ap);
620 sqlite3_exec(db, "COMMIT", 0, 0, 0);
621 sqlite3_close(db);
622 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
623
624 /*
625 ** zDbName is the name of a database file. If no other database
626 ** file is open, then open this one. If another database file is
627 ** already open, then attach zDbName using the name zLabel.
@@ -629,34 +652,30 @@
629 void db_open_or_attach(const char *zDbName, const char *zLabel){
630 #ifdef __MINGW32__
631 zDbName = mbcsToUtf8(zDbName);
632 #endif
633 if( !g.db ){
634 int rc;
635 const char *zVfs;
636
637 zVfs = getenv("FOSSIL_VFS");
638 rc = sqlite3_open_v2(
639 zDbName, &g.db,
640 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
641 zVfs
642 );
643 if( rc!=SQLITE_OK ){
644 db_err(sqlite3_errmsg(g.db));
645 }
646 sqlite3_busy_timeout(g.db, 5000);
647 db_connection_init();
648 }else{
649 db_multi_exec("ATTACH DATABASE %Q AS %s", zDbName, zLabel);
650 }
651 }
652
653 /*
654 ** Open the user database in "~/.fossil". Create the database anew if
655 ** it does not already exist.
 
 
 
 
 
 
 
 
656 */
657 void db_open_config(void){
658 char *zDbName;
659 const char *zHome;
660 if( g.configOpen ) return;
661 #ifdef __MINGW32__
662 zHome = getenv("LOCALAPPDATA");
@@ -684,11 +703,17 @@
684 zDbName = mprintf("%s/.fossil", zHome);
685 #endif
686 if( file_size(zDbName)<1024*3 ){
687 db_init_database(zDbName, zConfigSchema, (char*)0);
688 }
689 db_open_or_attach(zDbName, "configdb");
 
 
 
 
 
 
690 g.configOpen = 1;
691 }
692
693 /*
694 ** If zDbName is a valid local database file, open it and return
@@ -702,11 +727,11 @@
702 if( access(zDbName, F_OK) ) return 0;
703 lsize = file_size(zDbName);
704 if( lsize%1024!=0 || lsize<4096 ) return 0;
705 db_open_or_attach(zDbName, "localdb");
706 g.localOpen = 1;
707 db_open_config();
708 db_open_repository(0);
709
710 /* If the "mtime" column is missing from the vfile table, then
711 ** add it now. This code added on 2008-12-06. After all users have
712 ** upgraded, this code can be safely deleted.
@@ -987,11 +1012,11 @@
987 if( g.argc!=3 ){
988 usage("REPOSITORY-NAME");
989 }
990 db_create_repository(g.argv[2]);
991 db_open_repository(g.argv[2]);
992 db_open_config();
993 db_begin_transaction();
994 db_initial_setup(zDate, 1);
995 db_end_transaction(0);
996 printf("project-id: %s\n", db_get("project-code", 0));
997 printf("server-id: %s\n", db_get("server-code", 0));
@@ -1145,10 +1170,27 @@
1145 for(i=0; i<sizeof(azOff)/sizeof(azOff[0]); i++){
1146 if( strcmp(zVal,azOff[i])==0 ) return 1;
1147 }
1148 return 0;
1149 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1150
1151 /*
1152 ** Get and set values from the CONFIG, GLOBAL_CONFIG and VVAR table in the
1153 ** repository and local databases.
1154 */
@@ -1156,41 +1198,57 @@
1156 char *z = 0;
1157 if( g.repositoryOpen ){
1158 z = db_text(0, "SELECT value FROM config WHERE name=%Q", zName);
1159 }
1160 if( z==0 && g.configOpen ){
 
1161 z = db_text(0, "SELECT value FROM global_config WHERE name=%Q", zName);
 
1162 }
1163 if( z==0 ){
1164 z = zDefault;
1165 }
1166 return z;
1167 }
1168 void db_set(const char *zName, const char *zValue, int globalFlag){
1169 db_begin_transaction();
1170 db_multi_exec("REPLACE INTO %sconfig(name,value) VALUES(%Q,%Q)",
1171 globalFlag ? "global_" : "", zName, zValue);
 
 
 
 
 
 
 
1172 if( globalFlag && g.repositoryOpen ){
1173 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
1174 }
1175 db_end_transaction(0);
1176 }
1177 void db_unset(const char *zName, int globalFlag){
1178 db_begin_transaction();
1179 db_multi_exec("DELETE FROM %sconfig WHERE name=%Q",
1180 globalFlag ? "global_" : "", zName);
 
 
 
 
 
1181 if( globalFlag && g.repositoryOpen ){
1182 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
1183 }
1184 db_end_transaction(0);
1185 }
1186 int db_is_global(const char *zName){
 
1187 if( g.configOpen ){
1188 return db_exists("SELECT 1 FROM global_config WHERE name=%Q", zName);
1189 }else{
1190 return 0;
1191 }
 
1192 }
1193 int db_get_int(const char *zName, int dflt){
1194 int v = dflt;
1195 int rc;
1196 if( g.repositoryOpen ){
@@ -1203,22 +1261,29 @@
1203 db_finalize(&q);
1204 }else{
1205 rc = SQLITE_DONE;
1206 }
1207 if( rc==SQLITE_DONE && g.configOpen ){
 
1208 v = db_int(dflt, "SELECT value FROM global_config WHERE name=%Q", zName);
 
1209 }
1210 return v;
1211 }
1212 void db_set_int(const char *zName, int value, int globalFlag){
1213 db_begin_transaction();
1214 db_multi_exec("REPLACE INTO %sconfig(name,value) VALUES(%Q,%d)",
1215 globalFlag ? "global_" : "", zName, value);
 
 
 
 
 
 
1216 if( globalFlag && g.repositoryOpen ){
1217 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
1218 }
1219 db_end_transaction(0);
1220 }
1221 int db_get_boolean(const char *zName, int dflt){
1222 char *zVal = db_get(zName, dflt ? "on" : "off");
1223 if( is_truth(zVal) ) return 1;
1224 if( is_false(zVal) ) return 0;
@@ -1252,15 +1317,17 @@
1252 if( zName==0 ){
1253 if( !g.localOpen ) return;
1254 zName = db_lget("repository", 0);
1255 }
1256 file_canonical_name(zName, &full);
 
1257 db_multi_exec(
1258 "INSERT OR IGNORE INTO global_config(name,value)"
1259 "VALUES('repo:%q',1)",
1260 blob_str(&full)
1261 );
 
1262 blob_reset(&full);
1263 }
1264
1265 /*
1266 ** COMMAND: open
@@ -1412,15 +1479,15 @@
1412 "web-browser",
1413 };
1414 int i;
1415 int globalFlag = find_option("global","g",0)!=0;
1416 int unsetFlag = g.argv[1][0]=='u';
 
1417 db_find_and_open_repository(0);
1418 if( !g.repositoryOpen ){
1419 globalFlag = 1;
1420 }
1421 db_open_config();
1422 if( unsetFlag && g.argc!=3 ){
1423 usage("PROPERTY ?-global?");
1424 }
1425 if( g.argc==2 ){
1426 for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){
1427
--- src/db.c
+++ src/db.c
@@ -618,10 +618,33 @@
618 }
619 va_end(ap);
620 sqlite3_exec(db, "COMMIT", 0, 0, 0);
621 sqlite3_close(db);
622 }
623
624 /*
625 ** Open a database file. Return a pointer to the new database
626 ** connection. An error results in process abort.
627 */
628 static sqlite3 *openDatabase(const char *zDbName){
629 int rc;
630 const char *zVfs;
631 sqlite3 *db;
632
633 zVfs = getenv("FOSSIL_VFS");
634 rc = sqlite3_open_v2(
635 zDbName, &db,
636 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
637 zVfs
638 );
639 if( rc!=SQLITE_OK ){
640 db_err(sqlite3_errmsg(db));
641 }
642 sqlite3_busy_timeout(db, 5000);
643 return db;
644 }
645
646
647 /*
648 ** zDbName is the name of a database file. If no other database
649 ** file is open, then open this one. If another database file is
650 ** already open, then attach zDbName using the name zLabel.
@@ -629,34 +652,30 @@
652 void db_open_or_attach(const char *zDbName, const char *zLabel){
653 #ifdef __MINGW32__
654 zDbName = mbcsToUtf8(zDbName);
655 #endif
656 if( !g.db ){
657 g.db = openDatabase(zDbName);
 
 
 
 
 
 
 
 
 
 
 
 
658 db_connection_init();
659 }else{
660 db_multi_exec("ATTACH DATABASE %Q AS %s", zDbName, zLabel);
661 }
662 }
663
664 /*
665 ** Open the user database in "~/.fossil". Create the database anew if
666 ** it does not already exist.
667 **
668 ** If the useAttach flag is 0 (the usual case) then the user database is
669 ** opened on a separate database connection g.dbConfig. This prevents
670 ** the ~/.fossil database from becoming locked on long check-in or sync
671 ** operations which hold an exclusive transaction. In a few cases, though,
672 ** it is convenient for the ~/.fossil to be attached to the main database
673 ** connection so that we can join between the various databases. In that
674 ** case, invoke this routine with useAttach as 1.
675 */
676 void db_open_config(int useAttach){
677 char *zDbName;
678 const char *zHome;
679 if( g.configOpen ) return;
680 #ifdef __MINGW32__
681 zHome = getenv("LOCALAPPDATA");
@@ -684,11 +703,17 @@
703 zDbName = mprintf("%s/.fossil", zHome);
704 #endif
705 if( file_size(zDbName)<1024*3 ){
706 db_init_database(zDbName, zConfigSchema, (char*)0);
707 }
708 g.useAttach = useAttach;
709 if( useAttach ){
710 db_open_or_attach(zDbName, "configdb");
711 g.dbConfig = 0;
712 }else{
713 g.dbConfig = openDatabase(zDbName);
714 }
715 g.configOpen = 1;
716 }
717
718 /*
719 ** If zDbName is a valid local database file, open it and return
@@ -702,11 +727,11 @@
727 if( access(zDbName, F_OK) ) return 0;
728 lsize = file_size(zDbName);
729 if( lsize%1024!=0 || lsize<4096 ) return 0;
730 db_open_or_attach(zDbName, "localdb");
731 g.localOpen = 1;
732 db_open_config(0);
733 db_open_repository(0);
734
735 /* If the "mtime" column is missing from the vfile table, then
736 ** add it now. This code added on 2008-12-06. After all users have
737 ** upgraded, this code can be safely deleted.
@@ -987,11 +1012,11 @@
1012 if( g.argc!=3 ){
1013 usage("REPOSITORY-NAME");
1014 }
1015 db_create_repository(g.argv[2]);
1016 db_open_repository(g.argv[2]);
1017 db_open_config(0);
1018 db_begin_transaction();
1019 db_initial_setup(zDate, 1);
1020 db_end_transaction(0);
1021 printf("project-id: %s\n", db_get("project-code", 0));
1022 printf("server-id: %s\n", db_get("server-code", 0));
@@ -1145,10 +1170,27 @@
1170 for(i=0; i<sizeof(azOff)/sizeof(azOff[0]); i++){
1171 if( strcmp(zVal,azOff[i])==0 ) return 1;
1172 }
1173 return 0;
1174 }
1175
1176 /*
1177 ** Swap the g.db and g.dbConfig connections so that the various db_* routines
1178 ** work on the ~/.fossil database instead of on the repository database.
1179 ** Be sure to swap them back after doing the operation.
1180 **
1181 ** If g.useAttach that means the ~/.fossil database was opened with
1182 ** the useAttach flag set to 1. In that case no connection swap is required
1183 ** so this routine is a no-op.
1184 */
1185 void db_swap_connections(void){
1186 if( !g.useAttach ){
1187 sqlite3 *dbTemp = g.db;
1188 g.db = g.dbConfig;
1189 g.dbConfig = dbTemp;
1190 }
1191 }
1192
1193 /*
1194 ** Get and set values from the CONFIG, GLOBAL_CONFIG and VVAR table in the
1195 ** repository and local databases.
1196 */
@@ -1156,41 +1198,57 @@
1198 char *z = 0;
1199 if( g.repositoryOpen ){
1200 z = db_text(0, "SELECT value FROM config WHERE name=%Q", zName);
1201 }
1202 if( z==0 && g.configOpen ){
1203 db_swap_connections();
1204 z = db_text(0, "SELECT value FROM global_config WHERE name=%Q", zName);
1205 db_swap_connections();
1206 }
1207 if( z==0 ){
1208 z = zDefault;
1209 }
1210 return z;
1211 }
1212 void db_set(const char *zName, const char *zValue, int globalFlag){
1213 db_begin_transaction();
1214 if( globalFlag ){
1215 db_swap_connections();
1216 db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%Q)",
1217 zName, zValue);
1218 db_swap_connections();
1219 }else{
1220 db_multi_exec("REPLACE INTO config(name,value) VALUES(%Q,%Q)",
1221 zName, zValue);
1222 }
1223 if( globalFlag && g.repositoryOpen ){
1224 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
1225 }
1226 db_end_transaction(0);
1227 }
1228 void db_unset(const char *zName, int globalFlag){
1229 db_begin_transaction();
1230 if( globalFlag ){
1231 db_swap_connections();
1232 db_multi_exec("DELETE INTO global_config WHERE name=%Q", zName);
1233 db_swap_connections();
1234 }else{
1235 db_multi_exec("DELETE INTO config WHERE name=%Q", zName);
1236 }
1237 if( globalFlag && g.repositoryOpen ){
1238 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
1239 }
1240 db_end_transaction(0);
1241 }
1242 int db_is_global(const char *zName){
1243 int rc = 0;
1244 if( g.configOpen ){
1245 db_swap_connections();
1246 rc = db_exists("SELECT 1 FROM global_config WHERE name=%Q", zName);
1247 db_swap_connections();
1248 }
1249 return rc;
1250 }
1251 int db_get_int(const char *zName, int dflt){
1252 int v = dflt;
1253 int rc;
1254 if( g.repositoryOpen ){
@@ -1203,22 +1261,29 @@
1261 db_finalize(&q);
1262 }else{
1263 rc = SQLITE_DONE;
1264 }
1265 if( rc==SQLITE_DONE && g.configOpen ){
1266 db_swap_connections();
1267 v = db_int(dflt, "SELECT value FROM global_config WHERE name=%Q", zName);
1268 db_swap_connections();
1269 }
1270 return v;
1271 }
1272 void db_set_int(const char *zName, int value, int globalFlag){
1273 if( globalFlag ){
1274 db_swap_connections();
1275 db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%d)",
1276 zName, value);
1277 db_swap_connections();
1278 }else{
1279 db_multi_exec("REPLACE INTO config(name,value) VALUES(%Q,%d)",
1280 zName, value);
1281 }
1282 if( globalFlag && g.repositoryOpen ){
1283 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
1284 }
 
1285 }
1286 int db_get_boolean(const char *zName, int dflt){
1287 char *zVal = db_get(zName, dflt ? "on" : "off");
1288 if( is_truth(zVal) ) return 1;
1289 if( is_false(zVal) ) return 0;
@@ -1252,15 +1317,17 @@
1317 if( zName==0 ){
1318 if( !g.localOpen ) return;
1319 zName = db_lget("repository", 0);
1320 }
1321 file_canonical_name(zName, &full);
1322 db_swap_connections();
1323 db_multi_exec(
1324 "INSERT OR IGNORE INTO global_config(name,value)"
1325 "VALUES('repo:%q',1)",
1326 blob_str(&full)
1327 );
1328 db_swap_connections();
1329 blob_reset(&full);
1330 }
1331
1332 /*
1333 ** COMMAND: open
@@ -1412,15 +1479,15 @@
1479 "web-browser",
1480 };
1481 int i;
1482 int globalFlag = find_option("global","g",0)!=0;
1483 int unsetFlag = g.argv[1][0]=='u';
1484 db_open_config(1);
1485 db_find_and_open_repository(0);
1486 if( !g.repositoryOpen ){
1487 globalFlag = 1;
1488 }
 
1489 if( unsetFlag && g.argc!=3 ){
1490 usage("PROPERTY ?-global?");
1491 }
1492 if( g.argc==2 ){
1493 for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){
1494
+1 -1
--- src/info.c
+++ src/info.c
@@ -97,11 +97,11 @@
9797
i64 fsize;
9898
if( g.argc!=2 && g.argc!=3 ){
9999
usage("?FILENAME|ARTIFACT-ID?");
100100
}
101101
if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){
102
- db_open_config();
102
+ db_open_config(0);
103103
db_record_repository_filename(g.argv[2]);
104104
db_open_repository(g.argv[2]);
105105
printf("project-code: %s\n", db_get("project-code", "<none>"));
106106
printf("project-name: %s\n", db_get("project-name", "<unnamed>"));
107107
printf("server-code: %s\n", db_get("server-code", "<none>"));
108108
--- src/info.c
+++ src/info.c
@@ -97,11 +97,11 @@
97 i64 fsize;
98 if( g.argc!=2 && g.argc!=3 ){
99 usage("?FILENAME|ARTIFACT-ID?");
100 }
101 if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){
102 db_open_config();
103 db_record_repository_filename(g.argv[2]);
104 db_open_repository(g.argv[2]);
105 printf("project-code: %s\n", db_get("project-code", "<none>"));
106 printf("project-name: %s\n", db_get("project-name", "<unnamed>"));
107 printf("server-code: %s\n", db_get("server-code", "<none>"));
108
--- src/info.c
+++ src/info.c
@@ -97,11 +97,11 @@
97 i64 fsize;
98 if( g.argc!=2 && g.argc!=3 ){
99 usage("?FILENAME|ARTIFACT-ID?");
100 }
101 if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){
102 db_open_config(0);
103 db_record_repository_filename(g.argv[2]);
104 db_open_repository(g.argv[2]);
105 printf("project-code: %s\n", db_get("project-code", "<none>"));
106 printf("project-name: %s\n", db_get("project-name", "<unnamed>"));
107 printf("server-code: %s\n", db_get("server-code", "<none>"));
108
+2
--- src/main.c
+++ src/main.c
@@ -52,10 +52,12 @@
5252
*/
5353
struct Global {
5454
int argc; char **argv; /* Command-line arguments to the program */
5555
int isConst; /* True if the output is unchanging */
5656
sqlite3 *db; /* The connection to the databases */
57
+ sqlite3 *dbConfig; /* Separate connection for global_config table */
58
+ int useAttach; /* True if global_config is attached to repository */
5759
int configOpen; /* True if the config database is open */
5860
long long int now; /* Seconds since 1970 */
5961
int repositoryOpen; /* True if the main repository database is open */
6062
char *zRepositoryName; /* Name of the repository database */
6163
int localOpen; /* True if the local database is open */
6264
--- src/main.c
+++ src/main.c
@@ -52,10 +52,12 @@
52 */
53 struct Global {
54 int argc; char **argv; /* Command-line arguments to the program */
55 int isConst; /* True if the output is unchanging */
56 sqlite3 *db; /* The connection to the databases */
 
 
57 int configOpen; /* True if the config database is open */
58 long long int now; /* Seconds since 1970 */
59 int repositoryOpen; /* True if the main repository database is open */
60 char *zRepositoryName; /* Name of the repository database */
61 int localOpen; /* True if the local database is open */
62
--- src/main.c
+++ src/main.c
@@ -52,10 +52,12 @@
52 */
53 struct Global {
54 int argc; char **argv; /* Command-line arguments to the program */
55 int isConst; /* True if the output is unchanging */
56 sqlite3 *db; /* The connection to the databases */
57 sqlite3 *dbConfig; /* Separate connection for global_config table */
58 int useAttach; /* True if global_config is attached to repository */
59 int configOpen; /* True if the config database is open */
60 long long int now; /* Seconds since 1970 */
61 int repositoryOpen; /* True if the main repository database is open */
62 char *zRepositoryName; /* Name of the repository database */
63 int localOpen; /* True if the local database is open */
64

Keyboard Shortcuts

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