Fossil SCM

Minor refactoring and general cleanup of the "fossil setting" logic.

drh 2015-02-01 21:21 trunk
Commit 32f8da0ce785b63ad8a53fa851b5416b0887391a
2 files changed +123 -79 +7 -7
+123 -79
--- src/db.c
+++ src/db.c
@@ -1520,12 +1520,12 @@
15201520
int i;
15211521
const char *zSep = "";
15221522
15231523
blob_zero(&x);
15241524
blob_append_sql(&x, "(");
1525
- for(i=0; ctrlSettings[i].name; i++){
1526
- blob_append_sql(&x, "%s%Q", zSep/*safe-for-%s*/, ctrlSettings[i].name);
1525
+ for(i=0; aSetting[i].name; i++){
1526
+ blob_append_sql(&x, "%s%Q", zSep/*safe-for-%s*/, aSetting[i].name);
15271527
zSep = ",";
15281528
}
15291529
blob_append_sql(&x, ")");
15301530
return blob_sql_text(&x);
15311531
}
@@ -1918,16 +1918,21 @@
19181918
g.zConfigDbType = zTempDbType;
19191919
}
19201920
}
19211921
19221922
/*
1923
-** Logic for reading potentially versioned settings from
1924
-** .fossil-settings/<name> , and emits warnings if necessary.
1925
-** Returns the non-versioned value without modification if there is no
1926
-** versioned value.
1923
+** Try to read a versioned setting string from .fossil-settings/<name>.
1924
+**
1925
+** Return the text of the string if it is found. Return NULL if not
1926
+** found.
1927
+**
1928
+** If the zNonVersionedSetting parameter is not NULL then it holds the
1929
+** non-versioned value for this setting. If both a versioned and ad
1930
+** non-versioned value exist and are not equal, then a warning message
1931
+** might be generated.
19271932
*/
1928
-char *db_get_do_versionable(const char *zName, char *zNonVersionedSetting){
1933
+char *db_get_versioned(const char *zName, char *zNonVersionedSetting){
19291934
char *zVersionedSetting = 0;
19301935
int noWarn = 0;
19311936
struct _cacheEntry {
19321937
struct _cacheEntry *next;
19331938
const char *zName, *zValue;
@@ -1998,37 +2003,38 @@
19982003
19992004
20002005
/*
20012006
** Get and set values from the CONFIG, GLOBAL_CONFIG and VVAR table in the
20022007
** repository and local databases.
2008
+**
2009
+** If no such variable exists, return zDefault. Or, if zName is the name
2010
+** of a setting, then the zDefault is ignored and the default value of the
2011
+** setting is returned instead. If zName is a versioned setting, then
2012
+** versioned value takes priority.
20032013
*/
20042014
char *db_get(const char *zName, char *zDefault){
20052015
char *z = 0;
2006
- int i;
2007
- const struct stControlSettings *ctrlSetting = 0;
2008
- /* Is this a setting? */
2009
- for(i=0; ctrlSettings[i].name; i++){
2010
- if( strcmp(ctrlSettings[i].name, zName)==0 ){
2011
- ctrlSetting = &(ctrlSettings[i]);
2012
- break;
2013
- }
2014
- }
2016
+ const Setting *pSetting = db_find_setting(zName, 0);
20152017
if( g.repositoryOpen ){
20162018
z = db_text(0, "SELECT value FROM config WHERE name=%Q", zName);
20172019
}
20182020
if( z==0 && g.zConfigDbName ){
20192021
db_swap_connections();
20202022
z = db_text(0, "SELECT value FROM global_config WHERE name=%Q", zName);
20212023
db_swap_connections();
20222024
}
2023
- if( ctrlSetting!=0 && ctrlSetting->versionable ){
2025
+ if( pSetting!=0 && pSetting->versionable ){
20242026
/* This is a versionable setting, try and get the info from a
20252027
** checked out file */
2026
- z = db_get_do_versionable(zName, z);
2028
+ z = db_get_versioned(zName, z);
20272029
}
20282030
if( z==0 ){
2029
- z = zDefault;
2031
+ if( zDefault==0 && pSetting && pSetting->def[0] ){
2032
+ z = fossil_strdup(pSetting->def);
2033
+ }else{
2034
+ z = zDefault;
2035
+ }
20302036
}
20312037
return z;
20322038
}
20332039
char *db_get_mtime(const char *zName, char *zFormat, char *zDefault){
20342040
char *z = 0;
@@ -2290,88 +2296,91 @@
22902296
g.argc = 2;
22912297
info_cmd();
22922298
}
22932299
22942300
/*
2295
-** Print the value of a setting named zName
2301
+** Print the current value of a setting identified by the pSetting
2302
+** pointer.
22962303
*/
2297
-static void print_setting(
2298
- const struct stControlSettings *ctrlSetting,
2299
- int localOpen
2300
-){
2304
+static void print_setting(const Setting *pSetting){
23012305
Stmt q;
23022306
if( g.repositoryOpen ){
23032307
db_prepare(&q,
23042308
"SELECT '(local)', value FROM config WHERE name=%Q"
23052309
" UNION ALL "
23062310
"SELECT '(global)', value FROM global_config WHERE name=%Q",
2307
- ctrlSetting->name, ctrlSetting->name
2311
+ pSetting->name, pSetting->name
23082312
);
23092313
}else{
23102314
db_prepare(&q,
23112315
"SELECT '(global)', value FROM global_config WHERE name=%Q",
2312
- ctrlSetting->name
2316
+ pSetting->name
23132317
);
23142318
}
23152319
if( db_step(&q)==SQLITE_ROW ){
2316
- fossil_print("%-20s %-8s %s\n", ctrlSetting->name, db_column_text(&q, 0),
2320
+ fossil_print("%-20s %-8s %s\n", pSetting->name, db_column_text(&q, 0),
23172321
db_column_text(&q, 1));
23182322
}else{
2319
- fossil_print("%-20s\n", ctrlSetting->name);
2323
+ fossil_print("%-20s\n", pSetting->name);
23202324
}
2321
- if( ctrlSetting->versionable && localOpen ){
2325
+ if( pSetting->versionable && g.localOpen ){
23222326
/* Check to see if this is overridden by a versionable settings file */
23232327
Blob versionedPathname;
23242328
blob_zero(&versionedPathname);
23252329
blob_appendf(&versionedPathname, "%s/.fossil-settings/%s",
2326
- g.zLocalRoot, ctrlSetting->name);
2330
+ g.zLocalRoot, pSetting->name);
23272331
if( file_size(blob_str(&versionedPathname))>=0 ){
23282332
fossil_print(" (overridden by contents of file .fossil-settings/%s)\n",
2329
- ctrlSetting->name);
2333
+ pSetting->name);
23302334
}
23312335
}
23322336
db_finalize(&q);
23332337
}
23342338
23352339
2340
+#if INTERFACE
23362341
/*
2337
-** define all settings, which can be controlled via the set/unset
2338
-** command. var is the name of the internal configuration name for db_(un)set.
2342
+** Define all settings, which can be controlled via the set/unset
2343
+** command.
2344
+**
2345
+** var is the name of the internal configuration name for db_(un)set.
23392346
** If var is 0, the settings name is used.
2347
+**
23402348
** width is the length for the edit field on the behavior page, 0
23412349
** is used for on/off checkboxes.
2350
+**
23422351
** The behaviour page doesn't use a special layout. It lists all
23432352
** set-commands and displays the 'set'-help as info.
23442353
*/
2345
-#if INTERFACE
2346
-struct stControlSettings {
2354
+struct Setting {
23472355
const char *name; /* Name of the setting */
23482356
const char *var; /* Internal variable name used by db_set() */
23492357
int width; /* Width of display. 0 for boolean values. */
23502358
int versionable; /* Is this setting versionable? */
23512359
int forceTextArea; /* Force using a text area for display? */
23522360
const char *def; /* Default value */
23532361
};
23542362
#endif /* INTERFACE */
2355
-struct stControlSettings const ctrlSettings[] = {
2363
+
2364
+const Setting aSetting[] = {
23562365
{ "access-log", 0, 0, 0, 0, "off" },
23572366
{ "admin-log", 0, 0, 0, 0, "off" },
23582367
{ "allow-symlinks", 0, 0, 1, 0, "off" },
23592368
{ "auto-captcha", "autocaptcha", 0, 0, 0, "on" },
23602369
{ "auto-hyperlink", 0, 0, 0, 0, "on", },
23612370
{ "auto-shun", 0, 0, 0, 0, "on" },
23622371
{ "autosync", 0, 0, 0, 0, "on" },
23632372
{ "autosync-tries", 0, 16, 0, 0, "1" },
23642373
{ "binary-glob", 0, 40, 1, 0, "" },
2365
- { "clearsign", 0, 0, 0, 0, "off" },
23662374
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__DARWIN__) || \
23672375
defined(__APPLE__)
23682376
{ "case-sensitive", 0, 0, 0, 0, "off" },
23692377
#else
23702378
{ "case-sensitive", 0, 0, 0, 0, "on" },
23712379
#endif
23722380
{ "clean-glob", 0, 40, 1, 0, "" },
2381
+ { "clearsign", 0, 0, 0, 0, "off" },
23732382
{ "crnl-glob", 0, 40, 1, 0, "" },
23742383
{ "default-perms", 0, 16, 0, 0, "u" },
23752384
{ "diff-binary", 0, 0, 0, 0, "on" },
23762385
{ "diff-command", 0, 40, 0, 0, "" },
23772386
{ "dont-push", 0, 0, 0, 0, "off" },
@@ -2412,10 +2421,41 @@
24122421
{ "th1-uri-regexp", 0, 40, 1, 0, "" },
24132422
{ "web-browser", 0, 32, 0, 0, "" },
24142423
{ "white-foreground", 0, 0, 0, 0, "off" },
24152424
{ 0,0,0,0,0,0 }
24162425
};
2426
+
2427
+/*
2428
+** Look up a control setting by its name. Return a pointer to the Setting
2429
+** object, or NULL if there is no such setting.
2430
+**
2431
+** If allowPrefix is true, then the Setting returned is the first one for
2432
+** which zName is a prefix of the Setting name.
2433
+*/
2434
+const Setting *db_find_setting(const char *zName, int allowPrefix){
2435
+ int lwr, mid, upr, c;
2436
+ int n = (int)strlen(zName) + !allowPrefix;
2437
+ lwr = 0;
2438
+ upr = ArraySize(aSetting)-2;
2439
+ while( upr>=lwr ){
2440
+ mid = (upr+lwr)/2;
2441
+ c = fossil_strncmp(zName, aSetting[mid].name, n);
2442
+ if( c<0 ){
2443
+ upr = mid - 1;
2444
+ }else if( c>0 ){
2445
+ lwr = mid + 1;
2446
+ }else{
2447
+ if( allowPrefix ){
2448
+ while( mid>lwr && fossil_strncmp(zName, aSetting[mid-1].name, n)==0 ){
2449
+ mid--;
2450
+ }
2451
+ }
2452
+ return &aSetting[mid];
2453
+ }
2454
+ }
2455
+ return 0;
2456
+}
24172457
24182458
/*
24192459
** COMMAND: settings
24202460
** COMMAND: unset*
24212461
**
@@ -2663,61 +2703,65 @@
26632703
globalFlag = 1;
26642704
}
26652705
if( unsetFlag && g.argc!=3 ){
26662706
usage("PROPERTY ?-global?");
26672707
}
2708
+
2709
+ /* Verify that the aSetting[] entries are in sorted order. This is
2710
+ ** necessary for the binary search in db_find_setting() to work correctly.
2711
+ */
2712
+ for(i=1; aSetting[i].name; i++){
2713
+ if( fossil_strcmp(aSetting[i-1].name, aSetting[i].name)>=0 ){
2714
+ fossil_panic("Internal Error: aSetting[] entries for \"%s\""
2715
+ " and \"%s\" are out of order.",
2716
+ aSetting[i-1].name, aSetting[i].name);
2717
+ }
2718
+ }
2719
+
26682720
if( g.argc==2 ){
2669
- int openLocal = db_open_local(0);
2670
- for(i=0; ctrlSettings[i].name; i++){
2671
- print_setting(&ctrlSettings[i], openLocal);
2721
+ for(i=0; aSetting[i].name; i++){
2722
+ print_setting(&aSetting[i]);
26722723
}
26732724
}else if( g.argc==3 || g.argc==4 ){
26742725
const char *zName = g.argv[2];
2675
- int isManifest;
2676
- int n = strlen(zName);
2677
- for(i=0; ctrlSettings[i].name; i++){
2678
- if( strncmp(ctrlSettings[i].name, zName, n)==0 ) break;
2679
- }
2680
- if( !ctrlSettings[i].name ){
2726
+ int n = (int)strlen(zName);
2727
+ const Setting *pSetting = db_find_setting(zName, 1);
2728
+ if( pSetting==0 ){
26812729
fossil_fatal("no such setting: %s", zName);
26822730
}
2683
- isManifest = fossil_strcmp(ctrlSettings[i].name, "manifest")==0;
2684
- if( isManifest && globalFlag ){
2731
+ if( globalFlag && fossil_strcmp(pSetting->name, "manifest")==0 ){
26852732
fossil_fatal("cannot set 'manifest' globally");
26862733
}
26872734
if( unsetFlag || g.argc==4 ){
2688
- if( ctrlSettings[i+1].name
2689
- && strncmp(ctrlSettings[i+1].name, zName, n)==0
2690
- && ctrlSettings[i].name[n]!=0
2691
- ){
2692
- fossil_print("ambiguous property prefix: %s\nMatching properties:\n",
2693
- zName);
2694
- while( ctrlSettings[i].name
2695
- && strncmp(ctrlSettings[i].name, zName, n)==0
2696
- ){
2697
- fossil_print("%s\n", ctrlSettings[i].name);
2698
- i++;
2699
- }
2700
- fossil_exit(1);
2701
- }else{
2702
- if( unsetFlag ){
2703
- db_unset(ctrlSettings[i].name, globalFlag);
2704
- }else{
2705
- db_set(ctrlSettings[i].name, g.argv[3], globalFlag);
2706
- }
2707
- }
2708
- }else{
2709
- isManifest = 0;
2710
- while( ctrlSettings[i].name
2711
- && strncmp(ctrlSettings[i].name, zName, n)==0
2712
- ){
2713
- print_setting(&ctrlSettings[i], db_open_local(0));
2714
- i++;
2715
- }
2716
- }
2717
- if( isManifest && g.localOpen ){
2718
- manifest_to_disk(db_lget_int("checkout", 0));
2735
+ int isManifest = fossil_strcmp(pSetting->name, "manifest")==0;
2736
+ if( pSetting[1].name && fossil_strncmp(pSetting[1].name, zName, n)==0 ){
2737
+ Blob x;
2738
+ int i;
2739
+ blob_init(&x,0,0);
2740
+ for(i=0; pSetting[i].name; i++){
2741
+ if( fossil_strncmp(pSetting[i].name,zName,n)!=0 ) break;
2742
+ blob_appendf(&x, " %s", pSetting[i].name);
2743
+ }
2744
+ fossil_fatal("ambiguous setting \"%s\" - might be:%s",
2745
+ zName, blob_str(&x));
2746
+ }
2747
+ if( globalFlag && isManifest ){
2748
+ fossil_fatal("cannot set 'manifest' globally");
2749
+ }
2750
+ if( unsetFlag ){
2751
+ db_unset(pSetting->name, globalFlag);
2752
+ }else{
2753
+ db_set(pSetting->name, g.argv[3], globalFlag);
2754
+ }
2755
+ if( isManifest && g.localOpen ){
2756
+ manifest_to_disk(db_lget_int("checkout", 0));
2757
+ }
2758
+ }else{
2759
+ while( pSetting->name && fossil_strncmp(pSetting->name,zName,n)==0 ){
2760
+ print_setting(pSetting);
2761
+ pSetting++;
2762
+ }
27192763
}
27202764
}else{
27212765
usage("?PROPERTY? ?VALUE? ?-global?");
27222766
}
27232767
}
27242768
--- src/db.c
+++ src/db.c
@@ -1520,12 +1520,12 @@
1520 int i;
1521 const char *zSep = "";
1522
1523 blob_zero(&x);
1524 blob_append_sql(&x, "(");
1525 for(i=0; ctrlSettings[i].name; i++){
1526 blob_append_sql(&x, "%s%Q", zSep/*safe-for-%s*/, ctrlSettings[i].name);
1527 zSep = ",";
1528 }
1529 blob_append_sql(&x, ")");
1530 return blob_sql_text(&x);
1531 }
@@ -1918,16 +1918,21 @@
1918 g.zConfigDbType = zTempDbType;
1919 }
1920 }
1921
1922 /*
1923 ** Logic for reading potentially versioned settings from
1924 ** .fossil-settings/<name> , and emits warnings if necessary.
1925 ** Returns the non-versioned value without modification if there is no
1926 ** versioned value.
 
 
 
 
 
1927 */
1928 char *db_get_do_versionable(const char *zName, char *zNonVersionedSetting){
1929 char *zVersionedSetting = 0;
1930 int noWarn = 0;
1931 struct _cacheEntry {
1932 struct _cacheEntry *next;
1933 const char *zName, *zValue;
@@ -1998,37 +2003,38 @@
1998
1999
2000 /*
2001 ** Get and set values from the CONFIG, GLOBAL_CONFIG and VVAR table in the
2002 ** repository and local databases.
 
 
 
 
 
2003 */
2004 char *db_get(const char *zName, char *zDefault){
2005 char *z = 0;
2006 int i;
2007 const struct stControlSettings *ctrlSetting = 0;
2008 /* Is this a setting? */
2009 for(i=0; ctrlSettings[i].name; i++){
2010 if( strcmp(ctrlSettings[i].name, zName)==0 ){
2011 ctrlSetting = &(ctrlSettings[i]);
2012 break;
2013 }
2014 }
2015 if( g.repositoryOpen ){
2016 z = db_text(0, "SELECT value FROM config WHERE name=%Q", zName);
2017 }
2018 if( z==0 && g.zConfigDbName ){
2019 db_swap_connections();
2020 z = db_text(0, "SELECT value FROM global_config WHERE name=%Q", zName);
2021 db_swap_connections();
2022 }
2023 if( ctrlSetting!=0 && ctrlSetting->versionable ){
2024 /* This is a versionable setting, try and get the info from a
2025 ** checked out file */
2026 z = db_get_do_versionable(zName, z);
2027 }
2028 if( z==0 ){
2029 z = zDefault;
 
 
 
 
2030 }
2031 return z;
2032 }
2033 char *db_get_mtime(const char *zName, char *zFormat, char *zDefault){
2034 char *z = 0;
@@ -2290,88 +2296,91 @@
2290 g.argc = 2;
2291 info_cmd();
2292 }
2293
2294 /*
2295 ** Print the value of a setting named zName
 
2296 */
2297 static void print_setting(
2298 const struct stControlSettings *ctrlSetting,
2299 int localOpen
2300 ){
2301 Stmt q;
2302 if( g.repositoryOpen ){
2303 db_prepare(&q,
2304 "SELECT '(local)', value FROM config WHERE name=%Q"
2305 " UNION ALL "
2306 "SELECT '(global)', value FROM global_config WHERE name=%Q",
2307 ctrlSetting->name, ctrlSetting->name
2308 );
2309 }else{
2310 db_prepare(&q,
2311 "SELECT '(global)', value FROM global_config WHERE name=%Q",
2312 ctrlSetting->name
2313 );
2314 }
2315 if( db_step(&q)==SQLITE_ROW ){
2316 fossil_print("%-20s %-8s %s\n", ctrlSetting->name, db_column_text(&q, 0),
2317 db_column_text(&q, 1));
2318 }else{
2319 fossil_print("%-20s\n", ctrlSetting->name);
2320 }
2321 if( ctrlSetting->versionable && localOpen ){
2322 /* Check to see if this is overridden by a versionable settings file */
2323 Blob versionedPathname;
2324 blob_zero(&versionedPathname);
2325 blob_appendf(&versionedPathname, "%s/.fossil-settings/%s",
2326 g.zLocalRoot, ctrlSetting->name);
2327 if( file_size(blob_str(&versionedPathname))>=0 ){
2328 fossil_print(" (overridden by contents of file .fossil-settings/%s)\n",
2329 ctrlSetting->name);
2330 }
2331 }
2332 db_finalize(&q);
2333 }
2334
2335
 
2336 /*
2337 ** define all settings, which can be controlled via the set/unset
2338 ** command. var is the name of the internal configuration name for db_(un)set.
 
 
2339 ** If var is 0, the settings name is used.
 
2340 ** width is the length for the edit field on the behavior page, 0
2341 ** is used for on/off checkboxes.
 
2342 ** The behaviour page doesn't use a special layout. It lists all
2343 ** set-commands and displays the 'set'-help as info.
2344 */
2345 #if INTERFACE
2346 struct stControlSettings {
2347 const char *name; /* Name of the setting */
2348 const char *var; /* Internal variable name used by db_set() */
2349 int width; /* Width of display. 0 for boolean values. */
2350 int versionable; /* Is this setting versionable? */
2351 int forceTextArea; /* Force using a text area for display? */
2352 const char *def; /* Default value */
2353 };
2354 #endif /* INTERFACE */
2355 struct stControlSettings const ctrlSettings[] = {
 
2356 { "access-log", 0, 0, 0, 0, "off" },
2357 { "admin-log", 0, 0, 0, 0, "off" },
2358 { "allow-symlinks", 0, 0, 1, 0, "off" },
2359 { "auto-captcha", "autocaptcha", 0, 0, 0, "on" },
2360 { "auto-hyperlink", 0, 0, 0, 0, "on", },
2361 { "auto-shun", 0, 0, 0, 0, "on" },
2362 { "autosync", 0, 0, 0, 0, "on" },
2363 { "autosync-tries", 0, 16, 0, 0, "1" },
2364 { "binary-glob", 0, 40, 1, 0, "" },
2365 { "clearsign", 0, 0, 0, 0, "off" },
2366 #if defined(_WIN32) || defined(__CYGWIN__) || defined(__DARWIN__) || \
2367 defined(__APPLE__)
2368 { "case-sensitive", 0, 0, 0, 0, "off" },
2369 #else
2370 { "case-sensitive", 0, 0, 0, 0, "on" },
2371 #endif
2372 { "clean-glob", 0, 40, 1, 0, "" },
 
2373 { "crnl-glob", 0, 40, 1, 0, "" },
2374 { "default-perms", 0, 16, 0, 0, "u" },
2375 { "diff-binary", 0, 0, 0, 0, "on" },
2376 { "diff-command", 0, 40, 0, 0, "" },
2377 { "dont-push", 0, 0, 0, 0, "off" },
@@ -2412,10 +2421,41 @@
2412 { "th1-uri-regexp", 0, 40, 1, 0, "" },
2413 { "web-browser", 0, 32, 0, 0, "" },
2414 { "white-foreground", 0, 0, 0, 0, "off" },
2415 { 0,0,0,0,0,0 }
2416 };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2417
2418 /*
2419 ** COMMAND: settings
2420 ** COMMAND: unset*
2421 **
@@ -2663,61 +2703,65 @@
2663 globalFlag = 1;
2664 }
2665 if( unsetFlag && g.argc!=3 ){
2666 usage("PROPERTY ?-global?");
2667 }
 
 
 
 
 
 
 
 
 
 
 
 
2668 if( g.argc==2 ){
2669 int openLocal = db_open_local(0);
2670 for(i=0; ctrlSettings[i].name; i++){
2671 print_setting(&ctrlSettings[i], openLocal);
2672 }
2673 }else if( g.argc==3 || g.argc==4 ){
2674 const char *zName = g.argv[2];
2675 int isManifest;
2676 int n = strlen(zName);
2677 for(i=0; ctrlSettings[i].name; i++){
2678 if( strncmp(ctrlSettings[i].name, zName, n)==0 ) break;
2679 }
2680 if( !ctrlSettings[i].name ){
2681 fossil_fatal("no such setting: %s", zName);
2682 }
2683 isManifest = fossil_strcmp(ctrlSettings[i].name, "manifest")==0;
2684 if( isManifest && globalFlag ){
2685 fossil_fatal("cannot set 'manifest' globally");
2686 }
2687 if( unsetFlag || g.argc==4 ){
2688 if( ctrlSettings[i+1].name
2689 && strncmp(ctrlSettings[i+1].name, zName, n)==0
2690 && ctrlSettings[i].name[n]!=0
2691 ){
2692 fossil_print("ambiguous property prefix: %s\nMatching properties:\n",
2693 zName);
2694 while( ctrlSettings[i].name
2695 && strncmp(ctrlSettings[i].name, zName, n)==0
2696 ){
2697 fossil_print("%s\n", ctrlSettings[i].name);
2698 i++;
2699 }
2700 fossil_exit(1);
2701 }else{
2702 if( unsetFlag ){
2703 db_unset(ctrlSettings[i].name, globalFlag);
2704 }else{
2705 db_set(ctrlSettings[i].name, g.argv[3], globalFlag);
2706 }
2707 }
2708 }else{
2709 isManifest = 0;
2710 while( ctrlSettings[i].name
2711 && strncmp(ctrlSettings[i].name, zName, n)==0
2712 ){
2713 print_setting(&ctrlSettings[i], db_open_local(0));
2714 i++;
2715 }
2716 }
2717 if( isManifest && g.localOpen ){
2718 manifest_to_disk(db_lget_int("checkout", 0));
2719 }
2720 }else{
2721 usage("?PROPERTY? ?VALUE? ?-global?");
2722 }
2723 }
2724
--- src/db.c
+++ src/db.c
@@ -1520,12 +1520,12 @@
1520 int i;
1521 const char *zSep = "";
1522
1523 blob_zero(&x);
1524 blob_append_sql(&x, "(");
1525 for(i=0; aSetting[i].name; i++){
1526 blob_append_sql(&x, "%s%Q", zSep/*safe-for-%s*/, aSetting[i].name);
1527 zSep = ",";
1528 }
1529 blob_append_sql(&x, ")");
1530 return blob_sql_text(&x);
1531 }
@@ -1918,16 +1918,21 @@
1918 g.zConfigDbType = zTempDbType;
1919 }
1920 }
1921
1922 /*
1923 ** Try to read a versioned setting string from .fossil-settings/<name>.
1924 **
1925 ** Return the text of the string if it is found. Return NULL if not
1926 ** found.
1927 **
1928 ** If the zNonVersionedSetting parameter is not NULL then it holds the
1929 ** non-versioned value for this setting. If both a versioned and ad
1930 ** non-versioned value exist and are not equal, then a warning message
1931 ** might be generated.
1932 */
1933 char *db_get_versioned(const char *zName, char *zNonVersionedSetting){
1934 char *zVersionedSetting = 0;
1935 int noWarn = 0;
1936 struct _cacheEntry {
1937 struct _cacheEntry *next;
1938 const char *zName, *zValue;
@@ -1998,37 +2003,38 @@
2003
2004
2005 /*
2006 ** Get and set values from the CONFIG, GLOBAL_CONFIG and VVAR table in the
2007 ** repository and local databases.
2008 **
2009 ** If no such variable exists, return zDefault. Or, if zName is the name
2010 ** of a setting, then the zDefault is ignored and the default value of the
2011 ** setting is returned instead. If zName is a versioned setting, then
2012 ** versioned value takes priority.
2013 */
2014 char *db_get(const char *zName, char *zDefault){
2015 char *z = 0;
2016 const Setting *pSetting = db_find_setting(zName, 0);
 
 
 
 
 
 
 
 
2017 if( g.repositoryOpen ){
2018 z = db_text(0, "SELECT value FROM config WHERE name=%Q", zName);
2019 }
2020 if( z==0 && g.zConfigDbName ){
2021 db_swap_connections();
2022 z = db_text(0, "SELECT value FROM global_config WHERE name=%Q", zName);
2023 db_swap_connections();
2024 }
2025 if( pSetting!=0 && pSetting->versionable ){
2026 /* This is a versionable setting, try and get the info from a
2027 ** checked out file */
2028 z = db_get_versioned(zName, z);
2029 }
2030 if( z==0 ){
2031 if( zDefault==0 && pSetting && pSetting->def[0] ){
2032 z = fossil_strdup(pSetting->def);
2033 }else{
2034 z = zDefault;
2035 }
2036 }
2037 return z;
2038 }
2039 char *db_get_mtime(const char *zName, char *zFormat, char *zDefault){
2040 char *z = 0;
@@ -2290,88 +2296,91 @@
2296 g.argc = 2;
2297 info_cmd();
2298 }
2299
2300 /*
2301 ** Print the current value of a setting identified by the pSetting
2302 ** pointer.
2303 */
2304 static void print_setting(const Setting *pSetting){
 
 
 
2305 Stmt q;
2306 if( g.repositoryOpen ){
2307 db_prepare(&q,
2308 "SELECT '(local)', value FROM config WHERE name=%Q"
2309 " UNION ALL "
2310 "SELECT '(global)', value FROM global_config WHERE name=%Q",
2311 pSetting->name, pSetting->name
2312 );
2313 }else{
2314 db_prepare(&q,
2315 "SELECT '(global)', value FROM global_config WHERE name=%Q",
2316 pSetting->name
2317 );
2318 }
2319 if( db_step(&q)==SQLITE_ROW ){
2320 fossil_print("%-20s %-8s %s\n", pSetting->name, db_column_text(&q, 0),
2321 db_column_text(&q, 1));
2322 }else{
2323 fossil_print("%-20s\n", pSetting->name);
2324 }
2325 if( pSetting->versionable && g.localOpen ){
2326 /* Check to see if this is overridden by a versionable settings file */
2327 Blob versionedPathname;
2328 blob_zero(&versionedPathname);
2329 blob_appendf(&versionedPathname, "%s/.fossil-settings/%s",
2330 g.zLocalRoot, pSetting->name);
2331 if( file_size(blob_str(&versionedPathname))>=0 ){
2332 fossil_print(" (overridden by contents of file .fossil-settings/%s)\n",
2333 pSetting->name);
2334 }
2335 }
2336 db_finalize(&q);
2337 }
2338
2339
2340 #if INTERFACE
2341 /*
2342 ** Define all settings, which can be controlled via the set/unset
2343 ** command.
2344 **
2345 ** var is the name of the internal configuration name for db_(un)set.
2346 ** If var is 0, the settings name is used.
2347 **
2348 ** width is the length for the edit field on the behavior page, 0
2349 ** is used for on/off checkboxes.
2350 **
2351 ** The behaviour page doesn't use a special layout. It lists all
2352 ** set-commands and displays the 'set'-help as info.
2353 */
2354 struct Setting {
 
2355 const char *name; /* Name of the setting */
2356 const char *var; /* Internal variable name used by db_set() */
2357 int width; /* Width of display. 0 for boolean values. */
2358 int versionable; /* Is this setting versionable? */
2359 int forceTextArea; /* Force using a text area for display? */
2360 const char *def; /* Default value */
2361 };
2362 #endif /* INTERFACE */
2363
2364 const Setting aSetting[] = {
2365 { "access-log", 0, 0, 0, 0, "off" },
2366 { "admin-log", 0, 0, 0, 0, "off" },
2367 { "allow-symlinks", 0, 0, 1, 0, "off" },
2368 { "auto-captcha", "autocaptcha", 0, 0, 0, "on" },
2369 { "auto-hyperlink", 0, 0, 0, 0, "on", },
2370 { "auto-shun", 0, 0, 0, 0, "on" },
2371 { "autosync", 0, 0, 0, 0, "on" },
2372 { "autosync-tries", 0, 16, 0, 0, "1" },
2373 { "binary-glob", 0, 40, 1, 0, "" },
 
2374 #if defined(_WIN32) || defined(__CYGWIN__) || defined(__DARWIN__) || \
2375 defined(__APPLE__)
2376 { "case-sensitive", 0, 0, 0, 0, "off" },
2377 #else
2378 { "case-sensitive", 0, 0, 0, 0, "on" },
2379 #endif
2380 { "clean-glob", 0, 40, 1, 0, "" },
2381 { "clearsign", 0, 0, 0, 0, "off" },
2382 { "crnl-glob", 0, 40, 1, 0, "" },
2383 { "default-perms", 0, 16, 0, 0, "u" },
2384 { "diff-binary", 0, 0, 0, 0, "on" },
2385 { "diff-command", 0, 40, 0, 0, "" },
2386 { "dont-push", 0, 0, 0, 0, "off" },
@@ -2412,10 +2421,41 @@
2421 { "th1-uri-regexp", 0, 40, 1, 0, "" },
2422 { "web-browser", 0, 32, 0, 0, "" },
2423 { "white-foreground", 0, 0, 0, 0, "off" },
2424 { 0,0,0,0,0,0 }
2425 };
2426
2427 /*
2428 ** Look up a control setting by its name. Return a pointer to the Setting
2429 ** object, or NULL if there is no such setting.
2430 **
2431 ** If allowPrefix is true, then the Setting returned is the first one for
2432 ** which zName is a prefix of the Setting name.
2433 */
2434 const Setting *db_find_setting(const char *zName, int allowPrefix){
2435 int lwr, mid, upr, c;
2436 int n = (int)strlen(zName) + !allowPrefix;
2437 lwr = 0;
2438 upr = ArraySize(aSetting)-2;
2439 while( upr>=lwr ){
2440 mid = (upr+lwr)/2;
2441 c = fossil_strncmp(zName, aSetting[mid].name, n);
2442 if( c<0 ){
2443 upr = mid - 1;
2444 }else if( c>0 ){
2445 lwr = mid + 1;
2446 }else{
2447 if( allowPrefix ){
2448 while( mid>lwr && fossil_strncmp(zName, aSetting[mid-1].name, n)==0 ){
2449 mid--;
2450 }
2451 }
2452 return &aSetting[mid];
2453 }
2454 }
2455 return 0;
2456 }
2457
2458 /*
2459 ** COMMAND: settings
2460 ** COMMAND: unset*
2461 **
@@ -2663,61 +2703,65 @@
2703 globalFlag = 1;
2704 }
2705 if( unsetFlag && g.argc!=3 ){
2706 usage("PROPERTY ?-global?");
2707 }
2708
2709 /* Verify that the aSetting[] entries are in sorted order. This is
2710 ** necessary for the binary search in db_find_setting() to work correctly.
2711 */
2712 for(i=1; aSetting[i].name; i++){
2713 if( fossil_strcmp(aSetting[i-1].name, aSetting[i].name)>=0 ){
2714 fossil_panic("Internal Error: aSetting[] entries for \"%s\""
2715 " and \"%s\" are out of order.",
2716 aSetting[i-1].name, aSetting[i].name);
2717 }
2718 }
2719
2720 if( g.argc==2 ){
2721 for(i=0; aSetting[i].name; i++){
2722 print_setting(&aSetting[i]);
 
2723 }
2724 }else if( g.argc==3 || g.argc==4 ){
2725 const char *zName = g.argv[2];
2726 int n = (int)strlen(zName);
2727 const Setting *pSetting = db_find_setting(zName, 1);
2728 if( pSetting==0 ){
 
 
 
2729 fossil_fatal("no such setting: %s", zName);
2730 }
2731 if( globalFlag && fossil_strcmp(pSetting->name, "manifest")==0 ){
 
2732 fossil_fatal("cannot set 'manifest' globally");
2733 }
2734 if( unsetFlag || g.argc==4 ){
2735 int isManifest = fossil_strcmp(pSetting->name, "manifest")==0;
2736 if( pSetting[1].name && fossil_strncmp(pSetting[1].name, zName, n)==0 ){
2737 Blob x;
2738 int i;
2739 blob_init(&x,0,0);
2740 for(i=0; pSetting[i].name; i++){
2741 if( fossil_strncmp(pSetting[i].name,zName,n)!=0 ) break;
2742 blob_appendf(&x, " %s", pSetting[i].name);
2743 }
2744 fossil_fatal("ambiguous setting \"%s\" - might be:%s",
2745 zName, blob_str(&x));
2746 }
2747 if( globalFlag && isManifest ){
2748 fossil_fatal("cannot set 'manifest' globally");
2749 }
2750 if( unsetFlag ){
2751 db_unset(pSetting->name, globalFlag);
2752 }else{
2753 db_set(pSetting->name, g.argv[3], globalFlag);
2754 }
2755 if( isManifest && g.localOpen ){
2756 manifest_to_disk(db_lget_int("checkout", 0));
2757 }
2758 }else{
2759 while( pSetting->name && fossil_strncmp(pSetting->name,zName,n)==0 ){
2760 print_setting(pSetting);
2761 pSetting++;
2762 }
 
 
 
2763 }
2764 }else{
2765 usage("?PROPERTY? ?VALUE? ?-global?");
2766 }
2767 }
2768
+7 -7
--- src/setup.c
+++ src/setup.c
@@ -1354,11 +1354,11 @@
13541354
13551355
/*
13561356
** WEBPAGE: setup_settings
13571357
*/
13581358
void setup_settings(void){
1359
- struct stControlSettings const *pSet;
1359
+ Setting const *pSet;
13601360
13611361
login_check_credentials();
13621362
if( !g.perm.Setup ){
13631363
login_needed();
13641364
}
@@ -1375,14 +1375,14 @@
13751375
@ See the "fossil help setting" output below for further information on
13761376
@ the meaning of each setting.</p><hr />
13771377
@ <form action="%s(g.zTop)/setup_settings" method="post"><div>
13781378
@ <table border="0"><tr><td valign="top">
13791379
login_insert_csrf_secret();
1380
- for(pSet=ctrlSettings; pSet->name!=0; pSet++){
1380
+ for(pSet=aSetting; pSet->name!=0; pSet++){
13811381
if( pSet->width==0 ){
13821382
int hasVersionableValue = pSet->versionable &&
1383
- (db_get_do_versionable(pSet->name, NULL)!=0);
1383
+ (db_get_versioned(pSet->name, NULL)!=0);
13841384
onoff_attribute(pSet->name, pSet->name,
13851385
pSet->var!=0 ? pSet->var : pSet->name,
13861386
is_truth(pSet->def), hasVersionableValue);
13871387
if( pSet->versionable ){
13881388
@ (v)<br />
@@ -1391,31 +1391,31 @@
13911391
}
13921392
}
13931393
}
13941394
@ <br /><input type="submit" name="submit" value="Apply Changes" />
13951395
@ </td><td style="width:50px;"></td><td valign="top">
1396
- for(pSet=ctrlSettings; pSet->name!=0; pSet++){
1396
+ for(pSet=aSetting; pSet->name!=0; pSet++){
13971397
if( pSet->width!=0 && !pSet->versionable && !pSet->forceTextArea ){
13981398
entry_attribute(pSet->name, /*pSet->width*/ 25, pSet->name,
13991399
pSet->var!=0 ? pSet->var : pSet->name,
14001400
(char*)pSet->def, 0);
14011401
@ <br />
14021402
}
14031403
}
1404
- for(pSet=ctrlSettings; pSet->name!=0; pSet++){
1404
+ for(pSet=aSetting; pSet->name!=0; pSet++){
14051405
if( pSet->width!=0 && !pSet->versionable && pSet->forceTextArea ){
14061406
@<b>%s(pSet->name)</b><br />
14071407
textarea_attribute("", /*rows*/ 3, /*cols*/ 50, pSet->name,
14081408
pSet->var!=0 ? pSet->var : pSet->name,
14091409
(char*)pSet->def, 0);
14101410
@ <br />
14111411
}
14121412
}
14131413
@ </td><td style="width:50px;"></td><td valign="top">
1414
- for(pSet=ctrlSettings; pSet->name!=0; pSet++){
1414
+ for(pSet=aSetting; pSet->name!=0; pSet++){
14151415
if( pSet->width!=0 && pSet->versionable ){
1416
- int hasVersionableValue = db_get_do_versionable(pSet->name, NULL)!=0;
1416
+ int hasVersionableValue = db_get_versioned(pSet->name, NULL)!=0;
14171417
@<b>%s(pSet->name)</b> (v)<br />
14181418
textarea_attribute("", /*rows*/ 3, /*cols*/ 20, pSet->name,
14191419
pSet->var!=0 ? pSet->var : pSet->name,
14201420
(char*)pSet->def, hasVersionableValue);
14211421
@<br />
14221422
--- src/setup.c
+++ src/setup.c
@@ -1354,11 +1354,11 @@
1354
1355 /*
1356 ** WEBPAGE: setup_settings
1357 */
1358 void setup_settings(void){
1359 struct stControlSettings const *pSet;
1360
1361 login_check_credentials();
1362 if( !g.perm.Setup ){
1363 login_needed();
1364 }
@@ -1375,14 +1375,14 @@
1375 @ See the "fossil help setting" output below for further information on
1376 @ the meaning of each setting.</p><hr />
1377 @ <form action="%s(g.zTop)/setup_settings" method="post"><div>
1378 @ <table border="0"><tr><td valign="top">
1379 login_insert_csrf_secret();
1380 for(pSet=ctrlSettings; pSet->name!=0; pSet++){
1381 if( pSet->width==0 ){
1382 int hasVersionableValue = pSet->versionable &&
1383 (db_get_do_versionable(pSet->name, NULL)!=0);
1384 onoff_attribute(pSet->name, pSet->name,
1385 pSet->var!=0 ? pSet->var : pSet->name,
1386 is_truth(pSet->def), hasVersionableValue);
1387 if( pSet->versionable ){
1388 @ (v)<br />
@@ -1391,31 +1391,31 @@
1391 }
1392 }
1393 }
1394 @ <br /><input type="submit" name="submit" value="Apply Changes" />
1395 @ </td><td style="width:50px;"></td><td valign="top">
1396 for(pSet=ctrlSettings; pSet->name!=0; pSet++){
1397 if( pSet->width!=0 && !pSet->versionable && !pSet->forceTextArea ){
1398 entry_attribute(pSet->name, /*pSet->width*/ 25, pSet->name,
1399 pSet->var!=0 ? pSet->var : pSet->name,
1400 (char*)pSet->def, 0);
1401 @ <br />
1402 }
1403 }
1404 for(pSet=ctrlSettings; pSet->name!=0; pSet++){
1405 if( pSet->width!=0 && !pSet->versionable && pSet->forceTextArea ){
1406 @<b>%s(pSet->name)</b><br />
1407 textarea_attribute("", /*rows*/ 3, /*cols*/ 50, pSet->name,
1408 pSet->var!=0 ? pSet->var : pSet->name,
1409 (char*)pSet->def, 0);
1410 @ <br />
1411 }
1412 }
1413 @ </td><td style="width:50px;"></td><td valign="top">
1414 for(pSet=ctrlSettings; pSet->name!=0; pSet++){
1415 if( pSet->width!=0 && pSet->versionable ){
1416 int hasVersionableValue = db_get_do_versionable(pSet->name, NULL)!=0;
1417 @<b>%s(pSet->name)</b> (v)<br />
1418 textarea_attribute("", /*rows*/ 3, /*cols*/ 20, pSet->name,
1419 pSet->var!=0 ? pSet->var : pSet->name,
1420 (char*)pSet->def, hasVersionableValue);
1421 @<br />
1422
--- src/setup.c
+++ src/setup.c
@@ -1354,11 +1354,11 @@
1354
1355 /*
1356 ** WEBPAGE: setup_settings
1357 */
1358 void setup_settings(void){
1359 Setting const *pSet;
1360
1361 login_check_credentials();
1362 if( !g.perm.Setup ){
1363 login_needed();
1364 }
@@ -1375,14 +1375,14 @@
1375 @ See the "fossil help setting" output below for further information on
1376 @ the meaning of each setting.</p><hr />
1377 @ <form action="%s(g.zTop)/setup_settings" method="post"><div>
1378 @ <table border="0"><tr><td valign="top">
1379 login_insert_csrf_secret();
1380 for(pSet=aSetting; pSet->name!=0; pSet++){
1381 if( pSet->width==0 ){
1382 int hasVersionableValue = pSet->versionable &&
1383 (db_get_versioned(pSet->name, NULL)!=0);
1384 onoff_attribute(pSet->name, pSet->name,
1385 pSet->var!=0 ? pSet->var : pSet->name,
1386 is_truth(pSet->def), hasVersionableValue);
1387 if( pSet->versionable ){
1388 @ (v)<br />
@@ -1391,31 +1391,31 @@
1391 }
1392 }
1393 }
1394 @ <br /><input type="submit" name="submit" value="Apply Changes" />
1395 @ </td><td style="width:50px;"></td><td valign="top">
1396 for(pSet=aSetting; pSet->name!=0; pSet++){
1397 if( pSet->width!=0 && !pSet->versionable && !pSet->forceTextArea ){
1398 entry_attribute(pSet->name, /*pSet->width*/ 25, pSet->name,
1399 pSet->var!=0 ? pSet->var : pSet->name,
1400 (char*)pSet->def, 0);
1401 @ <br />
1402 }
1403 }
1404 for(pSet=aSetting; pSet->name!=0; pSet++){
1405 if( pSet->width!=0 && !pSet->versionable && pSet->forceTextArea ){
1406 @<b>%s(pSet->name)</b><br />
1407 textarea_attribute("", /*rows*/ 3, /*cols*/ 50, pSet->name,
1408 pSet->var!=0 ? pSet->var : pSet->name,
1409 (char*)pSet->def, 0);
1410 @ <br />
1411 }
1412 }
1413 @ </td><td style="width:50px;"></td><td valign="top">
1414 for(pSet=aSetting; pSet->name!=0; pSet++){
1415 if( pSet->width!=0 && pSet->versionable ){
1416 int hasVersionableValue = db_get_versioned(pSet->name, NULL)!=0;
1417 @<b>%s(pSet->name)</b> (v)<br />
1418 textarea_attribute("", /*rows*/ 3, /*cols*/ 20, pSet->name,
1419 pSet->var!=0 ? pSet->var : pSet->name,
1420 (char*)pSet->def, hasVersionableValue);
1421 @<br />
1422

Keyboard Shortcuts

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