Fossil

Check-in [79533e2b31]
Login

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

Overview
Comment:Improvements to handling of the configuration database.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | th1Hooks
Files: files | file ages | folders
SHA1: 79533e2b31ec5bd9fd00b0c0e10c14c4a6615a6c
User & Date: mistachkin 2014-06-11 01:23:22.538
Context
2014-06-11
01:48
When checking the 'th1-hooks' setting value, refer to the repository settings as well. check-in: 3fb8e171b3 user: mistachkin tags: th1Hooks
01:23
Improvements to handling of the configuration database. check-in: 79533e2b31 user: mistachkin tags: th1Hooks
00:51
Centralize the handling of opening the configuration database and repository on behalf of TH1. check-in: 9773eba5fe user: mistachkin tags: trunk
00:40
Merge updates from trunk. check-in: 715dcd52fe user: mistachkin tags: th1Hooks
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/db.c.
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
819
820
821
822
823
824
825
826
    if( pWasAttached ) *pWasAttached = 0;
  }else{
    assert( g.zMainDbType!=0 );
    db_attach(zDbName, zLabel);
    if( pWasAttached ) *pWasAttached = 1;
  }
}






















/*
** Open the user database in "~/.fossil".  Create the database anew if
** it does not already exist.
**
** If the useAttach flag is 0 (the usual case) then the user database is
** opened on a separate database connection g.dbConfig.  This prevents
** the ~/.fossil database from becoming locked on long check-in or sync
** operations which hold an exclusive transaction.  In a few cases, though,
** it is convenient for the ~/.fossil to be attached to the main database
** connection so that we can join between the various databases.  In that
** case, invoke this routine with useAttach as 1.
*/
void db_open_config(int useAttach){
  char *zDbName;
  char *zHome;
  if( g.zConfigDbName ){
    if( useAttach==g.useAttach ) return;
    if( g.useAttach ){
      db_detach("configdb");
      g.useAttach = 0;
    }else if( g.dbConfig ){
      sqlite3_close(g.dbConfig);
      g.dbConfig = 0;
      g.zConfigDbType = 0;
    }else if( g.db ){
      sqlite3_close(g.db);
      g.db = 0;
      g.zMainDbType = 0;
    }
  }
#if defined(_WIN32) || defined(__CYGWIN__)
  zHome = fossil_getenv("LOCALAPPDATA");
  if( zHome==0 ){
    zHome = fossil_getenv("APPDATA");
    if( zHome==0 ){
      char *zDrive = fossil_getenv("HOMEDRIVE");







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


















<
<
<
<
<
<
<
<
|
<
<
<







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
819
820
821
822
823
824
825
826
827
828








829



830
831
832
833
834
835
836
    if( pWasAttached ) *pWasAttached = 0;
  }else{
    assert( g.zMainDbType!=0 );
    db_attach(zDbName, zLabel);
    if( pWasAttached ) *pWasAttached = 1;
  }
}

/*
** Close the user database.
*/
void db_close_config(){
  if( g.useAttach ){
    db_detach("configdb");
    g.useAttach = 0;
    g.zConfigDbName = 0;
  }else if( g.dbConfig ){
    sqlite3_close(g.dbConfig);
    g.dbConfig = 0;
    g.zConfigDbType = 0;
    g.zConfigDbName = 0;
  }else if( g.db && fossil_strcmp(g.zMainDbType, "configdb")==0 ){
    sqlite3_close(g.db);
    g.db = 0;
    g.zMainDbType = 0;
    g.zConfigDbName = 0;
  }
}

/*
** Open the user database in "~/.fossil".  Create the database anew if
** it does not already exist.
**
** If the useAttach flag is 0 (the usual case) then the user database is
** opened on a separate database connection g.dbConfig.  This prevents
** the ~/.fossil database from becoming locked on long check-in or sync
** operations which hold an exclusive transaction.  In a few cases, though,
** it is convenient for the ~/.fossil to be attached to the main database
** connection so that we can join between the various databases.  In that
** case, invoke this routine with useAttach as 1.
*/
void db_open_config(int useAttach){
  char *zDbName;
  char *zHome;
  if( g.zConfigDbName ){
    if( useAttach==g.useAttach ) return;








    db_close_config();



  }
#if defined(_WIN32) || defined(__CYGWIN__)
  zHome = fossil_getenv("LOCALAPPDATA");
  if( zHome==0 ){
    zHome = fossil_getenv("APPDATA");
    if( zHome==0 ){
      char *zDrive = fossil_getenv("HOMEDRIVE");
Changes to src/th_main.c.
987
988
989
990
991
992
993


























994
995
996
997
998
999
1000
  }else{
    Th_ErrorMessage(interp,
        "synchronous requests are not yet implemented", 0, 0);
    blob_reset(&payload);
    return TH_ERROR;
  }
}



























/*
** Make sure the interpreter has been initialized.  Initialize it if
** it has not been already.
**
** The interpreter is stored in the g.interp global variable.
*/







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







987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
  }else{
    Th_ErrorMessage(interp,
        "synchronous requests are not yet implemented", 0, 0);
    blob_reset(&payload);
    return TH_ERROR;
  }
}

/*
** Attempts to open the configuration ("user") database.  Optionally, also
** attempts to try to find the repository and open it.
*/
void Th_OpenConfig(
  int openRepository
){
  if( openRepository ){
    db_find_and_open_repository(OPEN_ANY_SCHEMA | OPEN_OK_NOT_FOUND, 0);
  }
  db_open_config(0);
}

/*
** Attempts to close the configuration ("user") database.  Optionally, also
** attempts to close the repository.
*/
void Th_CloseConfig(
  int closeRepository
){
  db_close_config();
  if( closeRepository ){
    db_close(1);
  }
}

/*
** Make sure the interpreter has been initialized.  Initialize it if
** it has not been already.
**
** The interpreter is stored in the g.interp global variable.
*/
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
  if( needConfig ){
    /*
    ** This function uses several settings which may be defined in the
    ** repository and/or the global configuration.  Since the caller
    ** passed a non-zero value for the needConfig parameter, make sure
    ** the necessary database connections are open prior to continuing.
    */
    db_find_and_open_repository(OPEN_ANY_SCHEMA | OPEN_OK_NOT_FOUND, 0);
    db_open_config(0);
  }
  if( forceReset || forceTcl || g.interp==0 ){
    int created = 0;
    int i;
    if( g.interp==0 ){
      g.interp = Th_CreateInterp(&vtab);
      created = 1;







<
|







1063
1064
1065
1066
1067
1068
1069

1070
1071
1072
1073
1074
1075
1076
1077
  if( needConfig ){
    /*
    ** This function uses several settings which may be defined in the
    ** repository and/or the global configuration.  Since the caller
    ** passed a non-zero value for the needConfig parameter, make sure
    ** the necessary database connections are open prior to continuing.
    */

    Th_OpenConfig(1);
  }
  if( forceReset || forceTcl || g.interp==0 ){
    int created = 0;
    int i;
    if( g.interp==0 ){
      g.interp = Th_CreateInterp(&vtab);
      created = 1;
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243


1244
1245
1246
1247
1248
1249
1250
** cause the actual command execution to be skipped.
*/
int Th_CommandHook(
  const char *zName,
  char cmdFlags
){
  int rc = TH_OK;
  Th_FossilInit(TH_INIT_HOOK);
  if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){
    return rc;
  }


  Th_Store("cmd_name", zName);
  Th_StoreList("cmd_args", g.argv, g.argc);
  Th_StoreInt("cmd_flags", cmdFlags);
  rc = Th_Eval(g.interp, 0, "command_hook", -1);
  if( rc==TH_ERROR ){
    int nResult = 0;
    char *zResult = (char*)Th_GetResult(g.interp, &nResult);







|



>
>







1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
** cause the actual command execution to be skipped.
*/
int Th_CommandHook(
  const char *zName,
  char cmdFlags
){
  int rc = TH_OK;
  Th_OpenConfig(0); /* NOTE: Minimum needed to check "th1-hooks" setting. */
  if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){
    return rc;
  }
  Th_CloseConfig(0);
  Th_FossilInit(TH_INIT_HOOK);
  Th_Store("cmd_name", zName);
  Th_StoreList("cmd_args", g.argv, g.argc);
  Th_StoreInt("cmd_flags", cmdFlags);
  rc = Th_Eval(g.interp, 0, "command_hook", -1);
  if( rc==TH_ERROR ){
    int nResult = 0;
    char *zResult = (char*)Th_GetResult(g.interp, &nResult);
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288


1289
1290
1291
1292
1293
1294
1295
** Currently, TH1 error messages generated by this function are ignored.
*/
int Th_CommandNotify(
  const char *zName,
  char cmdFlags
){
  int rc = TH_OK;
  Th_FossilInit(TH_INIT_HOOK);
  if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){
    return rc;
  }


  Th_Store("cmd_name", zName);
  Th_StoreList("cmd_args", g.argv, g.argc);
  Th_StoreInt("cmd_flags", cmdFlags);
  rc = Th_Eval(g.interp, 0, "command_notify", -1);
  if( g.thTrace ){
    Th_Trace("[command_notify {%h}] => %h<br />\n", zName,
             Th_ReturnCodeName(rc, 0));







|



>
>







1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
** Currently, TH1 error messages generated by this function are ignored.
*/
int Th_CommandNotify(
  const char *zName,
  char cmdFlags
){
  int rc = TH_OK;
  Th_OpenConfig(0); /* NOTE: Minimum needed to check "th1-hooks" setting. */
  if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){
    return rc;
  }
  Th_CloseConfig(0);
  Th_FossilInit(TH_INIT_HOOK);
  Th_Store("cmd_name", zName);
  Th_StoreList("cmd_args", g.argv, g.argc);
  Th_StoreInt("cmd_flags", cmdFlags);
  rc = Th_Eval(g.interp, 0, "command_notify", -1);
  if( g.thTrace ){
    Th_Trace("[command_notify {%h}] => %h<br />\n", zName,
             Th_ReturnCodeName(rc, 0));
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314


1315
1316
1317
1318
1319
1320
1321
** cause the actual web page processing to be skipped.
*/
int Th_WebpageHook(
  const char *zName,
  char cmdFlags
){
  int rc = TH_OK;
  Th_FossilInit(TH_INIT_HOOK);
  if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){
    return rc;
  }


  Th_Store("web_name", zName);
  Th_StoreList("web_args", g.argv, g.argc);
  Th_StoreInt("web_flags", cmdFlags);
  rc = Th_Eval(g.interp, 0, "webpage_hook", -1);
  if( rc==TH_ERROR ){
    int nResult = 0;
    char *zResult = (char*)Th_GetResult(g.interp, &nResult);







|



>
>







1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
** cause the actual web page processing to be skipped.
*/
int Th_WebpageHook(
  const char *zName,
  char cmdFlags
){
  int rc = TH_OK;
  Th_OpenConfig(0); /* NOTE: Minimum needed to check "th1-hooks" setting. */
  if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){
    return rc;
  }
  Th_CloseConfig(0);
  Th_FossilInit(TH_INIT_HOOK);
  Th_Store("web_name", zName);
  Th_StoreList("web_args", g.argv, g.argc);
  Th_StoreInt("web_flags", cmdFlags);
  rc = Th_Eval(g.interp, 0, "webpage_hook", -1);
  if( rc==TH_ERROR ){
    int nResult = 0;
    char *zResult = (char*)Th_GetResult(g.interp, &nResult);
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359


1360
1361
1362
1363
1364
1365
1366
** Currently, TH1 error messages generated by this function are ignored.
*/
int Th_WebpageNotify(
  const char *zName,
  char cmdFlags
){
  int rc = TH_OK;
  Th_FossilInit(TH_INIT_HOOK);
  if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){
    return rc;
  }


  Th_Store("web_name", zName);
  Th_StoreList("web_args", g.argv, g.argc);
  Th_StoreInt("web_flags", cmdFlags);
  rc = Th_Eval(g.interp, 0, "webpage_notify", -1);
  if( g.thTrace ){
    Th_Trace("[webpage_notify {%h}] => %h<br />\n", zName,
             Th_ReturnCodeName(rc, 0));







|



>
>







1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
** Currently, TH1 error messages generated by this function are ignored.
*/
int Th_WebpageNotify(
  const char *zName,
  char cmdFlags
){
  int rc = TH_OK;
  Th_OpenConfig(0); /* NOTE: Minimum needed to check "th1-hooks" setting. */
  if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){
    return rc;
  }
  Th_CloseConfig(0);
  Th_FossilInit(TH_INIT_HOOK);
  Th_Store("web_name", zName);
  Th_StoreList("web_args", g.argv, g.argc);
  Th_StoreInt("web_flags", cmdFlags);
  rc = Th_Eval(g.interp, 0, "webpage_notify", -1);
  if( g.thTrace ){
    Th_Trace("[webpage_notify {%h}] => %h<br />\n", zName,
             Th_ReturnCodeName(rc, 0));
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
/*
** COMMAND: test-th-render
*/
void test_th_render(void){
  Blob in;
  Th_InitTraceLog();
  if( find_option("th-open-config", 0, 0)!=0 ){
    db_find_and_open_repository(OPEN_ANY_SCHEMA | OPEN_OK_NOT_FOUND, 0);
    db_open_config(0);
  }
  if( g.argc<3 ){
    usage("FILE");
  }
  blob_zero(&in);
  blob_read_from_file(&in, g.argv[2]);
  Th_Render(blob_str(&in));
  Th_PrintTraceLog();
}

/*
** COMMAND: test-th-eval
*/
void test_th_eval(void){
  int rc;
  const char *zRc;
  Th_InitTraceLog();
  if( find_option("th-open-config", 0, 0)!=0 ){
    db_find_and_open_repository(OPEN_ANY_SCHEMA | OPEN_OK_NOT_FOUND, 0);
    db_open_config(0);
  }
  if( g.argc!=3 ){
    usage("script");
  }
  Th_FossilInit(TH_INIT_DEFAULT);
  rc = Th_Eval(g.interp, 0, g.argv[2], -1);
  zRc = Th_ReturnCodeName(rc, 1);







<
|


















<
|







1467
1468
1469
1470
1471
1472
1473

1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492

1493
1494
1495
1496
1497
1498
1499
1500
/*
** COMMAND: test-th-render
*/
void test_th_render(void){
  Blob in;
  Th_InitTraceLog();
  if( find_option("th-open-config", 0, 0)!=0 ){

    Th_OpenConfig(1);
  }
  if( g.argc<3 ){
    usage("FILE");
  }
  blob_zero(&in);
  blob_read_from_file(&in, g.argv[2]);
  Th_Render(blob_str(&in));
  Th_PrintTraceLog();
}

/*
** COMMAND: test-th-eval
*/
void test_th_eval(void){
  int rc;
  const char *zRc;
  Th_InitTraceLog();
  if( find_option("th-open-config", 0, 0)!=0 ){

    Th_OpenConfig(1);
  }
  if( g.argc!=3 ){
    usage("script");
  }
  Th_FossilInit(TH_INIT_DEFAULT);
  rc = Th_Eval(g.interp, 0, g.argv[2], -1);
  zRc = Th_ReturnCodeName(rc, 1);