| | @@ -30,14 +30,23 @@ |
| 30 | 30 | #define TH_INIT_NONE ((u32)0x00000000) /* No flags. */ |
| 31 | 31 | #define TH_INIT_NEED_CONFIG ((u32)0x00000001) /* Open configuration first? */ |
| 32 | 32 | #define TH_INIT_FORCE_TCL ((u32)0x00000002) /* Force Tcl to be enabled? */ |
| 33 | 33 | #define TH_INIT_FORCE_RESET ((u32)0x00000004) /* Force TH1 commands re-added? */ |
| 34 | 34 | #define TH_INIT_FORCE_SETUP ((u32)0x00000008) /* Force eval of setup script? */ |
| 35 | +#define TH_INIT_MASK ((u32)0x0000000F) /* All possible init flags. */ |
| 35 | 36 | #define TH_INIT_DEFAULT (TH_INIT_NONE) /* Default flags. */ |
| 36 | 37 | #define TH_INIT_HOOK (TH_INIT_NEED_CONFIG | TH_INIT_FORCE_SETUP) |
| 37 | 38 | #endif |
| 38 | 39 | |
| 40 | +/* |
| 41 | +** Flags set by functions in this file to keep track of integration state |
| 42 | +** information. These flags should not be used outside of this file. |
| 43 | +*/ |
| 44 | +#define TH_STATE_CONFIG ((u32)0x00000010) /* We opened the config. */ |
| 45 | +#define TH_STATE_REPOSITORY ((u32)0x00000020) /* We opened the repository. */ |
| 46 | +#define TH_STATE_MASK ((u32)0x00000030) /* All possible state flags. */ |
| 47 | + |
| 39 | 48 | #ifdef FOSSIL_ENABLE_TH1_HOOKS |
| 40 | 49 | /* |
| 41 | 50 | ** These are the "well-known" TH1 error messages that occur when no hook is |
| 42 | 51 | ** registered to be called prior to executing a command or processing a web |
| 43 | 52 | ** page, respectively. If one of these errors is seen, it will not be sent |
| | @@ -45,10 +54,17 @@ |
| 45 | 54 | */ |
| 46 | 55 | #define NO_COMMAND_HOOK_ERROR "no such command: command_hook" |
| 47 | 56 | #define NO_WEBPAGE_HOOK_ERROR "no such command: webpage_hook" |
| 48 | 57 | #endif |
| 49 | 58 | |
| 59 | +/* |
| 60 | +** These macros are used within this file to detect if the repository and |
| 61 | +** configuration ("user") database are currently open. |
| 62 | +*/ |
| 63 | +#define Th_IsRepositoryOpen() (g.repositoryOpen) |
| 64 | +#define Th_IsConfigOpen() (g.zConfigDbName!=0) |
| 65 | + |
| 50 | 66 | /* |
| 51 | 67 | ** Global variable counting the number of outstanding calls to malloc() |
| 52 | 68 | ** made by the th1 implementation. This is used to catch memory leaks |
| 53 | 69 | ** in the interpreter. Obviously, it also means th1 is not threadsafe. |
| 54 | 70 | */ |
| | @@ -595,11 +611,13 @@ |
| 595 | 611 | |
| 596 | 612 | /* |
| 597 | 613 | ** TH1 command: checkout ?BOOLEAN? |
| 598 | 614 | ** |
| 599 | 615 | ** Return the fully qualified directory name of the current checkout or an |
| 600 | | -** empty string if it is not available. |
| 616 | +** empty string if it is not available. Optionally, it will attempt to find |
| 617 | +** the current checkout, opening the configuration ("user") database and the |
| 618 | +** repository as necessary, if the boolean argument is non-zero. |
| 601 | 619 | */ |
| 602 | 620 | static int checkoutCmd( |
| 603 | 621 | Th_Interp *interp, |
| 604 | 622 | void *p, |
| 605 | 623 | int argc, |
| | @@ -608,15 +626,15 @@ |
| 608 | 626 | ){ |
| 609 | 627 | if( argc!=1 && argc!=2 ){ |
| 610 | 628 | return Th_WrongNumArgs(interp, "checkout ?BOOLEAN?"); |
| 611 | 629 | } |
| 612 | 630 | if( argc==2 ){ |
| 613 | | - int openRepository = 0; |
| 614 | | - if( Th_ToInt(interp, argv[1], argl[1], &openRepository) ){ |
| 631 | + int openCheckout = 0; |
| 632 | + if( Th_ToInt(interp, argv[1], argl[1], &openCheckout) ){ |
| 615 | 633 | return TH_ERROR; |
| 616 | 634 | } |
| 617 | | - if( openRepository ) db_find_and_open_repository(OPEN_OK_NOT_FOUND, 0); |
| 635 | + if( openCheckout ) db_open_local(0); |
| 618 | 636 | } |
| 619 | 637 | Th_SetResult(interp, g.zLocalRoot, -1); |
| 620 | 638 | return TH_OK; |
| 621 | 639 | } |
| 622 | 640 | |
| | @@ -719,16 +737,16 @@ |
| 719 | 737 | int *argl |
| 720 | 738 | ){ |
| 721 | 739 | if( argc!=2 ){ |
| 722 | 740 | return Th_WrongNumArgs(interp, "styleHeader TITLE"); |
| 723 | 741 | } |
| 724 | | - if( g.zConfigDbName ){ |
| 742 | + if( Th_IsRepositoryOpen() ){ |
| 725 | 743 | style_header("%s", argv[1]); |
| 726 | 744 | Th_SetResult(interp, 0, 0); |
| 727 | 745 | return TH_OK; |
| 728 | 746 | }else{ |
| 729 | | - Th_SetResult(interp, "configuration unavailable", -1); |
| 747 | + Th_SetResult(interp, "repository unavailable", -1); |
| 730 | 748 | return TH_ERROR; |
| 731 | 749 | } |
| 732 | 750 | } |
| 733 | 751 | |
| 734 | 752 | /* |
| | @@ -744,16 +762,16 @@ |
| 744 | 762 | int *argl |
| 745 | 763 | ){ |
| 746 | 764 | if( argc!=1 ){ |
| 747 | 765 | return Th_WrongNumArgs(interp, "styleFooter"); |
| 748 | 766 | } |
| 749 | | - if( g.zConfigDbName ){ |
| 767 | + if( Th_IsRepositoryOpen() ){ |
| 750 | 768 | style_footer(); |
| 751 | 769 | Th_SetResult(interp, 0, 0); |
| 752 | 770 | return TH_OK; |
| 753 | 771 | }else{ |
| 754 | | - Th_SetResult(interp, "configuration unavailable", -1); |
| 772 | + Th_SetResult(interp, "repository unavailable", -1); |
| 755 | 773 | return TH_ERROR; |
| 756 | 774 | } |
| 757 | 775 | } |
| 758 | 776 | |
| 759 | 777 | #ifdef _WIN32 |
| | @@ -1160,26 +1178,42 @@ |
| 1160 | 1178 | ** attempts to try to find the repository and open it. |
| 1161 | 1179 | */ |
| 1162 | 1180 | void Th_OpenConfig( |
| 1163 | 1181 | int openRepository |
| 1164 | 1182 | ){ |
| 1165 | | - if( openRepository ){ |
| 1183 | + if( openRepository && !Th_IsRepositoryOpen() ){ |
| 1166 | 1184 | db_find_and_open_repository(OPEN_ANY_SCHEMA | OPEN_OK_NOT_FOUND, 0); |
| 1185 | + if( Th_IsRepositoryOpen() ){ |
| 1186 | + g.th1Flags |= TH_STATE_REPOSITORY; |
| 1187 | + }else{ |
| 1188 | + g.th1Flags &= ~TH_STATE_REPOSITORY; |
| 1189 | + } |
| 1167 | 1190 | } |
| 1168 | | - db_open_config(0); |
| 1191 | + if( !Th_IsConfigOpen() ){ |
| 1192 | + db_open_config(0); |
| 1193 | + if( Th_IsConfigOpen() ){ |
| 1194 | + g.th1Flags |= TH_STATE_CONFIG; |
| 1195 | + }else{ |
| 1196 | + g.th1Flags &= ~TH_STATE_CONFIG; |
| 1197 | + } |
| 1198 | + } |
| 1169 | 1199 | } |
| 1170 | 1200 | |
| 1171 | 1201 | /* |
| 1172 | 1202 | ** Attempts to close the configuration ("user") database. Optionally, also |
| 1173 | 1203 | ** attempts to close the repository. |
| 1174 | 1204 | */ |
| 1175 | 1205 | void Th_CloseConfig( |
| 1176 | 1206 | int closeRepository |
| 1177 | 1207 | ){ |
| 1178 | | - db_close_config(); |
| 1179 | | - if( closeRepository ){ |
| 1208 | + if( g.th1Flags & TH_STATE_CONFIG ){ |
| 1209 | + db_close_config(); |
| 1210 | + g.th1Flags &= ~TH_STATE_CONFIG; |
| 1211 | + } |
| 1212 | + if( closeRepository && (g.th1Flags & TH_STATE_REPOSITORY) ){ |
| 1180 | 1213 | db_close(1); |
| 1214 | + g.th1Flags &= ~TH_STATE_REPOSITORY; |
| 1181 | 1215 | } |
| 1182 | 1216 | } |
| 1183 | 1217 | |
| 1184 | 1218 | /* |
| 1185 | 1219 | ** Make sure the interpreter has been initialized. Initialize it if |
| | @@ -1282,10 +1316,12 @@ |
| 1282 | 1316 | if( g.thTrace ){ |
| 1283 | 1317 | Th_Trace("th1-setup {%h} => %h<br />\n", g.th1Setup, |
| 1284 | 1318 | Th_ReturnCodeName(rc, 0)); |
| 1285 | 1319 | } |
| 1286 | 1320 | } |
| 1321 | + g.th1Flags &= ~TH_INIT_MASK; |
| 1322 | + g.th1Flags |= (flags & TH_INIT_MASK); |
| 1287 | 1323 | } |
| 1288 | 1324 | |
| 1289 | 1325 | /* |
| 1290 | 1326 | ** Store a string value in a variable in the interpreter. |
| 1291 | 1327 | */ |
| | @@ -1432,10 +1468,11 @@ |
| 1432 | 1468 | char cmdFlags |
| 1433 | 1469 | ){ |
| 1434 | 1470 | int rc = TH_OK; |
| 1435 | 1471 | Th_OpenConfig(1); |
| 1436 | 1472 | if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){ |
| 1473 | + Th_CloseConfig(1); |
| 1437 | 1474 | return rc; |
| 1438 | 1475 | } |
| 1439 | 1476 | Th_CloseConfig(1); |
| 1440 | 1477 | Th_FossilInit(TH_INIT_HOOK); |
| 1441 | 1478 | Th_Store("cmd_name", zName); |
| | @@ -1479,10 +1516,11 @@ |
| 1479 | 1516 | char cmdFlags |
| 1480 | 1517 | ){ |
| 1481 | 1518 | int rc = TH_OK; |
| 1482 | 1519 | Th_OpenConfig(1); |
| 1483 | 1520 | if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){ |
| 1521 | + Th_CloseConfig(1); |
| 1484 | 1522 | return rc; |
| 1485 | 1523 | } |
| 1486 | 1524 | Th_CloseConfig(1); |
| 1487 | 1525 | Th_FossilInit(TH_INIT_HOOK); |
| 1488 | 1526 | Th_Store("cmd_name", zName); |
| | @@ -1507,10 +1545,11 @@ |
| 1507 | 1545 | char cmdFlags |
| 1508 | 1546 | ){ |
| 1509 | 1547 | int rc = TH_OK; |
| 1510 | 1548 | Th_OpenConfig(1); |
| 1511 | 1549 | if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){ |
| 1550 | + Th_CloseConfig(1); |
| 1512 | 1551 | return rc; |
| 1513 | 1552 | } |
| 1514 | 1553 | Th_CloseConfig(1); |
| 1515 | 1554 | Th_FossilInit(TH_INIT_HOOK); |
| 1516 | 1555 | Th_Store("web_name", zName); |
| | @@ -1554,10 +1593,11 @@ |
| 1554 | 1593 | char cmdFlags |
| 1555 | 1594 | ){ |
| 1556 | 1595 | int rc = TH_OK; |
| 1557 | 1596 | Th_OpenConfig(1); |
| 1558 | 1597 | if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){ |
| 1598 | + Th_CloseConfig(1); |
| 1559 | 1599 | return rc; |
| 1560 | 1600 | } |
| 1561 | 1601 | Th_CloseConfig(1); |
| 1562 | 1602 | Th_FossilInit(TH_INIT_HOOK); |
| 1563 | 1603 | Th_Store("web_name", zName); |
| | @@ -1678,10 +1718,11 @@ |
| 1678 | 1718 | */ |
| 1679 | 1719 | void test_th_hook(void){ |
| 1680 | 1720 | int rc = TH_OK; |
| 1681 | 1721 | int nResult = 0; |
| 1682 | 1722 | char *zResult; |
| 1723 | + Th_InitTraceLog(); |
| 1683 | 1724 | if( g.argc<5 ){ |
| 1684 | 1725 | usage("TYPE NAME FLAGS"); |
| 1685 | 1726 | } |
| 1686 | 1727 | if( fossil_stricmp(g.argv[2], "cmdhook")==0 ){ |
| 1687 | 1728 | rc = Th_CommandHook(g.argv[3], (char)atoi(g.argv[4])); |
| | @@ -1698,7 +1739,8 @@ |
| 1698 | 1739 | sendText("RESULT (", -1, 0); |
| 1699 | 1740 | sendText(Th_ReturnCodeName(rc, 0), -1, 0); |
| 1700 | 1741 | sendText("): ", -1, 0); |
| 1701 | 1742 | sendText(zResult, nResult, 0); |
| 1702 | 1743 | sendText("\n", -1, 0); |
| 1744 | + Th_PrintTraceLog(); |
| 1703 | 1745 | } |
| 1704 | 1746 | #endif |
| 1705 | 1747 | |