Fossil SCM

Merge updates from trunk.

mistachkin 2016-10-16 00:22 stash-fixes merge
Commit 5634375d0bb84cd9bb98d8bde013601b970dde36
+8 -9
--- src/db.c
+++ src/db.c
@@ -2287,23 +2287,22 @@
22872287
** which letters can be used to represent flags (any permutation of flags must
22882288
** not be able to fully form one of the boolean values).
22892289
*/
22902290
int db_get_manifest_setting(void){
22912291
int flg;
2292
- char *zNVVal = db_get("manifest", "off");
2293
- char *zVal = db_get_versioned("manifest", zNVVal);
2294
- if( is_false(zVal) ){
2292
+ char *zVal = db_get("manifest", 0);
2293
+ if( zVal==0 || is_false(zVal) ){
22952294
return 0;
2296
- }else if( is_truth(zVal) ) {
2295
+ }else if( is_truth(zVal) ){
22972296
return MFESTFLG_RAW|MFESTFLG_UUID;
22982297
}
22992298
flg = 0;
23002299
while( *zVal ){
2301
- switch( *zVal ){
2302
- case 'r': flg |= MFESTFLG_RAW; break;
2303
- case 'u': flg |= MFESTFLG_UUID; break;
2304
- case 't': flg |= MFESTFLG_TAGS; break;
2300
+ switch( *zVal ){
2301
+ case 'r': flg |= MFESTFLG_RAW; break;
2302
+ case 'u': flg |= MFESTFLG_UUID; break;
2303
+ case 't': flg |= MFESTFLG_TAGS; break;
23052304
}
23062305
zVal++;
23072306
}
23082307
return flg;
23092308
}
@@ -2606,11 +2605,11 @@
26062605
{ "https-login", 0, 0, 0, 0, "off" },
26072606
{ "ignore-glob", 0, 40, 1, 0, "" },
26082607
{ "keep-glob", 0, 40, 1, 0, "" },
26092608
{ "localauth", 0, 0, 0, 0, "off" },
26102609
{ "main-branch", 0, 40, 0, 0, "trunk" },
2611
- { "manifest", 0, 5, 0, 0, "off" },
2610
+ { "manifest", 0, 5, 1, 0, "off" },
26122611
{ "max-loadavg", 0, 25, 0, 0, "0.0" },
26132612
{ "max-upload", 0, 25, 0, 0, "250000" },
26142613
{ "mtime-changes", 0, 0, 0, 0, "on" },
26152614
#if FOSSIL_ENABLE_LEGACY_MV_RM
26162615
{ "mv-rm-files", 0, 0, 0, 0, "off" },
26172616
--- src/db.c
+++ src/db.c
@@ -2287,23 +2287,22 @@
2287 ** which letters can be used to represent flags (any permutation of flags must
2288 ** not be able to fully form one of the boolean values).
2289 */
2290 int db_get_manifest_setting(void){
2291 int flg;
2292 char *zNVVal = db_get("manifest", "off");
2293 char *zVal = db_get_versioned("manifest", zNVVal);
2294 if( is_false(zVal) ){
2295 return 0;
2296 }else if( is_truth(zVal) ) {
2297 return MFESTFLG_RAW|MFESTFLG_UUID;
2298 }
2299 flg = 0;
2300 while( *zVal ){
2301 switch( *zVal ){
2302 case 'r': flg |= MFESTFLG_RAW; break;
2303 case 'u': flg |= MFESTFLG_UUID; break;
2304 case 't': flg |= MFESTFLG_TAGS; break;
2305 }
2306 zVal++;
2307 }
2308 return flg;
2309 }
@@ -2606,11 +2605,11 @@
2606 { "https-login", 0, 0, 0, 0, "off" },
2607 { "ignore-glob", 0, 40, 1, 0, "" },
2608 { "keep-glob", 0, 40, 1, 0, "" },
2609 { "localauth", 0, 0, 0, 0, "off" },
2610 { "main-branch", 0, 40, 0, 0, "trunk" },
2611 { "manifest", 0, 5, 0, 0, "off" },
2612 { "max-loadavg", 0, 25, 0, 0, "0.0" },
2613 { "max-upload", 0, 25, 0, 0, "250000" },
2614 { "mtime-changes", 0, 0, 0, 0, "on" },
2615 #if FOSSIL_ENABLE_LEGACY_MV_RM
2616 { "mv-rm-files", 0, 0, 0, 0, "off" },
2617
--- src/db.c
+++ src/db.c
@@ -2287,23 +2287,22 @@
2287 ** which letters can be used to represent flags (any permutation of flags must
2288 ** not be able to fully form one of the boolean values).
2289 */
2290 int db_get_manifest_setting(void){
2291 int flg;
2292 char *zVal = db_get("manifest", 0);
2293 if( zVal==0 || is_false(zVal) ){
 
2294 return 0;
2295 }else if( is_truth(zVal) ){
2296 return MFESTFLG_RAW|MFESTFLG_UUID;
2297 }
2298 flg = 0;
2299 while( *zVal ){
2300 switch( *zVal ){
2301 case 'r': flg |= MFESTFLG_RAW; break;
2302 case 'u': flg |= MFESTFLG_UUID; break;
2303 case 't': flg |= MFESTFLG_TAGS; break;
2304 }
2305 zVal++;
2306 }
2307 return flg;
2308 }
@@ -2606,11 +2605,11 @@
2605 { "https-login", 0, 0, 0, 0, "off" },
2606 { "ignore-glob", 0, 40, 1, 0, "" },
2607 { "keep-glob", 0, 40, 1, 0, "" },
2608 { "localauth", 0, 0, 0, 0, "off" },
2609 { "main-branch", 0, 40, 0, 0, "trunk" },
2610 { "manifest", 0, 5, 1, 0, "off" },
2611 { "max-loadavg", 0, 25, 0, 0, "0.0" },
2612 { "max-upload", 0, 25, 0, 0, "250000" },
2613 { "mtime-changes", 0, 0, 0, 0, "on" },
2614 #if FOSSIL_ENABLE_LEGACY_MV_RM
2615 { "mv-rm-files", 0, 0, 0, 0, "off" },
2616
+3 -3
--- src/deltacmd.c
+++ src/deltacmd.c
@@ -29,16 +29,16 @@
2929
const char *zOrig, *zTarg;
3030
int lenOrig, lenTarg;
3131
int len;
3232
char *zRes;
3333
blob_zero(pDelta);
34
- zOrig = blob_buffer(pOriginal);
34
+ zOrig = blob_materialize(pOriginal);
3535
lenOrig = blob_size(pOriginal);
36
- zTarg = blob_buffer(pTarget);
36
+ zTarg = blob_materialize(pTarget);
3737
lenTarg = blob_size(pTarget);
3838
blob_resize(pDelta, lenTarg+16);
39
- zRes = blob_buffer(pDelta);
39
+ zRes = blob_materialize(pDelta);
4040
len = delta_create(zOrig, lenOrig, zTarg, lenTarg, zRes);
4141
blob_resize(pDelta, len);
4242
return 0;
4343
}
4444
4545
--- src/deltacmd.c
+++ src/deltacmd.c
@@ -29,16 +29,16 @@
29 const char *zOrig, *zTarg;
30 int lenOrig, lenTarg;
31 int len;
32 char *zRes;
33 blob_zero(pDelta);
34 zOrig = blob_buffer(pOriginal);
35 lenOrig = blob_size(pOriginal);
36 zTarg = blob_buffer(pTarget);
37 lenTarg = blob_size(pTarget);
38 blob_resize(pDelta, lenTarg+16);
39 zRes = blob_buffer(pDelta);
40 len = delta_create(zOrig, lenOrig, zTarg, lenTarg, zRes);
41 blob_resize(pDelta, len);
42 return 0;
43 }
44
45
--- src/deltacmd.c
+++ src/deltacmd.c
@@ -29,16 +29,16 @@
29 const char *zOrig, *zTarg;
30 int lenOrig, lenTarg;
31 int len;
32 char *zRes;
33 blob_zero(pDelta);
34 zOrig = blob_materialize(pOriginal);
35 lenOrig = blob_size(pOriginal);
36 zTarg = blob_materialize(pTarget);
37 lenTarg = blob_size(pTarget);
38 blob_resize(pDelta, lenTarg+16);
39 zRes = blob_materialize(pDelta);
40 len = delta_create(zOrig, lenOrig, zTarg, lenTarg, zRes);
41 blob_resize(pDelta, len);
42 return 0;
43 }
44
45
+2 -1
--- src/fusefs.c
+++ src/fusefs.c
@@ -207,11 +207,12 @@
207207
filler(buf, ".", NULL, 0);
208208
filler(buf, "..", NULL, 0);
209209
manifest_file_rewind(fusefs.pMan);
210210
if( n==2 ){
211211
while( (pFile = manifest_file_next(fusefs.pMan, 0))!=0 ){
212
- if( nPrev>0 && strncmp(pFile->zName, zPrev, nPrev)==0 ) continue;
212
+ if( nPrev>0 && strncmp(pFile->zName, zPrev, nPrev)==0
213
+ && pFile->zName[nPrev]=='/' ) continue;
213214
zPrev = pFile->zName;
214215
for(nPrev=0; zPrev[nPrev] && zPrev[nPrev]!='/'; nPrev++){}
215216
z = mprintf("%.*s", nPrev, zPrev);
216217
filler(buf, z, NULL, 0);
217218
fossil_free(z);
218219
--- src/fusefs.c
+++ src/fusefs.c
@@ -207,11 +207,12 @@
207 filler(buf, ".", NULL, 0);
208 filler(buf, "..", NULL, 0);
209 manifest_file_rewind(fusefs.pMan);
210 if( n==2 ){
211 while( (pFile = manifest_file_next(fusefs.pMan, 0))!=0 ){
212 if( nPrev>0 && strncmp(pFile->zName, zPrev, nPrev)==0 ) continue;
 
213 zPrev = pFile->zName;
214 for(nPrev=0; zPrev[nPrev] && zPrev[nPrev]!='/'; nPrev++){}
215 z = mprintf("%.*s", nPrev, zPrev);
216 filler(buf, z, NULL, 0);
217 fossil_free(z);
218
--- src/fusefs.c
+++ src/fusefs.c
@@ -207,11 +207,12 @@
207 filler(buf, ".", NULL, 0);
208 filler(buf, "..", NULL, 0);
209 manifest_file_rewind(fusefs.pMan);
210 if( n==2 ){
211 while( (pFile = manifest_file_next(fusefs.pMan, 0))!=0 ){
212 if( nPrev>0 && strncmp(pFile->zName, zPrev, nPrev)==0
213 && pFile->zName[nPrev]=='/' ) continue;
214 zPrev = pFile->zName;
215 for(nPrev=0; zPrev[nPrev] && zPrev[nPrev]!='/'; nPrev++){}
216 z = mprintf("%.*s", nPrev, zPrev);
217 filler(buf, z, NULL, 0);
218 fossil_free(z);
219
+34 -25
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -381,11 +381,11 @@
381381
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
382382
** [sqlite_version()] and [sqlite_source_id()].
383383
*/
384384
#define SQLITE_VERSION "3.15.0"
385385
#define SQLITE_VERSION_NUMBER 3015000
386
-#define SQLITE_SOURCE_ID "2016-10-04 12:20:12 3a9d802fda10585654332b314d317250dc5d894e"
386
+#define SQLITE_SOURCE_ID "2016-10-14 10:20:30 707875582fcba352b4906a595ad89198d84711d8"
387387
388388
/*
389389
** CAPI3REF: Run-Time Library Version Numbers
390390
** KEYWORDS: sqlite3_version, sqlite3_sourceid
391391
**
@@ -44715,11 +44715,11 @@
4471544715
szBulk = pCache->szAlloc * (i64)pcache1.nInitPage;
4471644716
}else{
4471744717
szBulk = -1024 * (i64)pcache1.nInitPage;
4471844718
}
4471944719
if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){
44720
- szBulk = pCache->szAlloc*pCache->nMax;
44720
+ szBulk = pCache->szAlloc*(i64)pCache->nMax;
4472144721
}
4472244722
zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
4472344723
sqlite3EndBenignMalloc();
4472444724
if( zBulk ){
4472544725
int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
@@ -69336,11 +69336,11 @@
6933669336
switch( aff ){
6933769337
case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */
6933869338
if( (pMem->flags & MEM_Blob)==0 ){
6933969339
sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding);
6934069340
assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
69341
- MemSetTypeFlag(pMem, MEM_Blob);
69341
+ if( pMem->flags & MEM_Str ) MemSetTypeFlag(pMem, MEM_Blob);
6934269342
}else{
6934369343
pMem->flags &= ~(MEM_TypeMask&~MEM_Blob);
6934469344
}
6934569345
break;
6934669346
}
@@ -88812,11 +88812,10 @@
8881288812
const char *zId; /* The function name. */
8881388813
FuncDef *pDef; /* Information about the function */
8881488814
u8 enc = ENC(pParse->db); /* The database encoding */
8881588815
8881688816
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
88817
-// notValid(pParse, pNC, "functions", NC_PartIdx);
8881888817
zId = pExpr->u.zToken;
8881988818
nId = sqlite3Strlen30(zId);
8882088819
pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0);
8882188820
if( pDef==0 ){
8882288821
pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0);
@@ -124663,11 +124662,10 @@
124663124662
**
124664124663
** * the comparison will be performed with no affinity, or
124665124664
** * the affinity change in zAff is guaranteed not to change the value.
124666124665
*/
124667124666
static void updateRangeAffinityStr(
124668
- Parse *pParse, /* Parse context */
124669124667
Expr *pRight, /* RHS of comparison */
124670124668
int n, /* Number of vector elements in comparison */
124671124669
char *zAff /* Affinity string to modify */
124672124670
){
124673124671
int i;
@@ -125749,15 +125747,15 @@
125749125747
assert( (bRev & ~1)==0 );
125750125748
pLevel->iLikeRepCntr <<=1;
125751125749
pLevel->iLikeRepCntr |= bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC);
125752125750
}
125753125751
#endif
125754
- if( pRangeStart==0
125755
- && (j = pIdx->aiColumn[nEq])>=0
125756
- && pIdx->pTable->aCol[j].notNull==0
125757
- ){
125758
- bSeekPastNull = 1;
125752
+ if( pRangeStart==0 ){
125753
+ j = pIdx->aiColumn[nEq];
125754
+ if( (j>=0 && pIdx->pTable->aCol[j].notNull==0) || j==XN_EXPR ){
125755
+ bSeekPastNull = 1;
125756
+ }
125759125757
}
125760125758
}
125761125759
assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 );
125762125760
125763125761
/* If we are doing a reverse order scan on an ascending index, or
@@ -125803,11 +125801,11 @@
125803125801
){
125804125802
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
125805125803
VdbeCoverage(v);
125806125804
}
125807125805
if( zStartAff ){
125808
- updateRangeAffinityStr(pParse, pRight, nBtm, &zStartAff[nEq]);
125806
+ updateRangeAffinityStr(pRight, nBtm, &zStartAff[nEq]);
125809125807
}
125810125808
nConstraint += nBtm;
125811125809
testcase( pRangeStart->wtFlags & TERM_VIRTUAL );
125812125810
if( sqlite3ExprIsVector(pRight)==0 ){
125813125811
disableTerm(pLevel, pRangeStart);
@@ -125853,11 +125851,11 @@
125853125851
){
125854125852
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
125855125853
VdbeCoverage(v);
125856125854
}
125857125855
if( zEndAff ){
125858
- updateRangeAffinityStr(pParse, pRight, nTop, zEndAff);
125856
+ updateRangeAffinityStr(pRight, nTop, zEndAff);
125859125857
codeApplyAffinity(pParse, regBase+nEq, nTop, zEndAff);
125860125858
}else{
125861125859
assert( pParse->db->mallocFailed );
125862125860
}
125863125861
nConstraint += nTop;
@@ -130005,11 +130003,11 @@
130005130003
** CREATE INDEX ... ON (a, b, c, d, e)
130006130004
**
130007130005
** then this function would be invoked with nEq=1. The value returned in
130008130006
** this case is 3.
130009130007
*/
130010
-int whereRangeVectorLen(
130008
+static int whereRangeVectorLen(
130011130009
Parse *pParse, /* Parsing context */
130012130010
int iCur, /* Cursor open on pIdx */
130013130011
Index *pIdx, /* The index to be used for a inequality constraint */
130014130012
int nEq, /* Number of prior equality constraints on same index */
130015130013
WhereTerm *pTerm /* The vector inequality constraint */
@@ -131451,11 +131449,11 @@
131451131449
if( rev ) *pRevMask |= MASKBIT(iLoop);
131452131450
revSet = 1;
131453131451
}
131454131452
}
131455131453
if( isMatch ){
131456
- if( iColumn<0 ){
131454
+ if( iColumn==XN_ROWID ){
131457131455
testcase( distinctColumns==0 );
131458131456
distinctColumns = 1;
131459131457
}
131460131458
obSat |= MASKBIT(i);
131461131459
}else{
@@ -131906,17 +131904,24 @@
131906131904
}else{
131907131905
pWInfo->nOBSat = pFrom->isOrdered;
131908131906
pWInfo->revMask = pFrom->revLoop;
131909131907
if( pWInfo->nOBSat<=0 ){
131910131908
pWInfo->nOBSat = 0;
131911
- if( nLoop>0 && (pFrom->aLoop[nLoop-1]->wsFlags & WHERE_ONEROW)==0 ){
131912
- Bitmask m = 0;
131913
- int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom,
131909
+ if( nLoop>0 ){
131910
+ u32 wsFlags = pFrom->aLoop[nLoop-1]->wsFlags;
131911
+ if( (wsFlags & WHERE_ONEROW)==0
131912
+ && (wsFlags&(WHERE_IPK|WHERE_COLUMN_IN))!=(WHERE_IPK|WHERE_COLUMN_IN)
131913
+ ){
131914
+ Bitmask m = 0;
131915
+ int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom,
131914131916
WHERE_ORDERBY_LIMIT, nLoop-1, pFrom->aLoop[nLoop-1], &m);
131915
- if( rc==pWInfo->pOrderBy->nExpr ){
131916
- pWInfo->bOrderedInnerLoop = 1;
131917
- pWInfo->revMask = m;
131917
+ testcase( wsFlags & WHERE_IPK );
131918
+ testcase( wsFlags & WHERE_COLUMN_IN );
131919
+ if( rc==pWInfo->pOrderBy->nExpr ){
131920
+ pWInfo->bOrderedInnerLoop = 1;
131921
+ pWInfo->revMask = m;
131922
+ }
131918131923
}
131919131924
}
131920131925
}
131921131926
}
131922131927
if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP)
@@ -164296,14 +164301,16 @@
164296164301
char *zSql;
164297164302
sqlite3_stmt *p;
164298164303
int rc;
164299164304
i64 nRow = 0;
164300164305
164301
- if( sqlite3_table_column_metadata(db,pRtree->zDb,"sqlite_stat1",
164302
- 0,0,0,0,0,0)==SQLITE_ERROR ){
164306
+ rc = sqlite3_table_column_metadata(
164307
+ db, pRtree->zDb, "sqlite_stat1",0,0,0,0,0,0
164308
+ );
164309
+ if( rc!=SQLITE_OK ){
164303164310
pRtree->nRowEst = RTREE_DEFAULT_ROWEST;
164304
- return SQLITE_OK;
164311
+ return rc==SQLITE_ERROR ? SQLITE_OK : rc;
164305164312
}
164306164313
zSql = sqlite3_mprintf(zFmt, pRtree->zDb, pRtree->zName);
164307164314
if( zSql==0 ){
164308164315
rc = SQLITE_NOMEM;
164309164316
}else{
@@ -181496,10 +181503,13 @@
181496181503
int nToken, /* Size of token in bytes */
181497181504
int iStartOff, /* Start offset of token */
181498181505
int iEndOff /* End offset of token */
181499181506
){
181500181507
int rc = SQLITE_OK;
181508
+
181509
+ UNUSED_PARAM2(pToken, nToken);
181510
+ UNUSED_PARAM(iEndOff);
181501181511
181502181512
if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){
181503181513
Fts5SFinder *p = (Fts5SFinder*)pContext;
181504181514
if( p->iPos>0 ){
181505181515
int i;
@@ -181652,11 +181662,10 @@
181652181662
for(jj=0; jj<(sFinder.nFirst-1); jj++){
181653181663
if( sFinder.aFirst[jj+1]>io ) break;
181654181664
}
181655181665
181656181666
if( sFinder.aFirst[jj]<io ){
181657
- int nScore;
181658181667
memset(aSeen, 0, nPhrase);
181659181668
rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i,
181660181669
sFinder.aFirst[jj], nToken, &nScore, 0
181661181670
);
181662181671
@@ -195587,11 +195596,11 @@
195587195596
int nArg, /* Number of args */
195588195597
sqlite3_value **apUnused /* Function arguments */
195589195598
){
195590195599
assert( nArg==0 );
195591195600
UNUSED_PARAM2(nArg, apUnused);
195592
- sqlite3_result_text(pCtx, "fts5: 2016-10-04 00:47:26 b10d0f939c82c4de3faa90b86de9ec4a89992856", -1, SQLITE_TRANSIENT);
195601
+ sqlite3_result_text(pCtx, "fts5: 2016-10-14 10:20:30 707875582fcba352b4906a595ad89198d84711d8", -1, SQLITE_TRANSIENT);
195593195602
}
195594195603
195595195604
static int fts5Init(sqlite3 *db){
195596195605
static const sqlite3_module fts5Mod = {
195597195606
/* iVersion */ 2,
195598195607
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -381,11 +381,11 @@
381 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
382 ** [sqlite_version()] and [sqlite_source_id()].
383 */
384 #define SQLITE_VERSION "3.15.0"
385 #define SQLITE_VERSION_NUMBER 3015000
386 #define SQLITE_SOURCE_ID "2016-10-04 12:20:12 3a9d802fda10585654332b314d317250dc5d894e"
387
388 /*
389 ** CAPI3REF: Run-Time Library Version Numbers
390 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
391 **
@@ -44715,11 +44715,11 @@
44715 szBulk = pCache->szAlloc * (i64)pcache1.nInitPage;
44716 }else{
44717 szBulk = -1024 * (i64)pcache1.nInitPage;
44718 }
44719 if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){
44720 szBulk = pCache->szAlloc*pCache->nMax;
44721 }
44722 zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
44723 sqlite3EndBenignMalloc();
44724 if( zBulk ){
44725 int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
@@ -69336,11 +69336,11 @@
69336 switch( aff ){
69337 case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */
69338 if( (pMem->flags & MEM_Blob)==0 ){
69339 sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding);
69340 assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
69341 MemSetTypeFlag(pMem, MEM_Blob);
69342 }else{
69343 pMem->flags &= ~(MEM_TypeMask&~MEM_Blob);
69344 }
69345 break;
69346 }
@@ -88812,11 +88812,10 @@
88812 const char *zId; /* The function name. */
88813 FuncDef *pDef; /* Information about the function */
88814 u8 enc = ENC(pParse->db); /* The database encoding */
88815
88816 assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
88817 // notValid(pParse, pNC, "functions", NC_PartIdx);
88818 zId = pExpr->u.zToken;
88819 nId = sqlite3Strlen30(zId);
88820 pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0);
88821 if( pDef==0 ){
88822 pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0);
@@ -124663,11 +124662,10 @@
124663 **
124664 ** * the comparison will be performed with no affinity, or
124665 ** * the affinity change in zAff is guaranteed not to change the value.
124666 */
124667 static void updateRangeAffinityStr(
124668 Parse *pParse, /* Parse context */
124669 Expr *pRight, /* RHS of comparison */
124670 int n, /* Number of vector elements in comparison */
124671 char *zAff /* Affinity string to modify */
124672 ){
124673 int i;
@@ -125749,15 +125747,15 @@
125749 assert( (bRev & ~1)==0 );
125750 pLevel->iLikeRepCntr <<=1;
125751 pLevel->iLikeRepCntr |= bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC);
125752 }
125753 #endif
125754 if( pRangeStart==0
125755 && (j = pIdx->aiColumn[nEq])>=0
125756 && pIdx->pTable->aCol[j].notNull==0
125757 ){
125758 bSeekPastNull = 1;
125759 }
125760 }
125761 assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 );
125762
125763 /* If we are doing a reverse order scan on an ascending index, or
@@ -125803,11 +125801,11 @@
125803 ){
125804 sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
125805 VdbeCoverage(v);
125806 }
125807 if( zStartAff ){
125808 updateRangeAffinityStr(pParse, pRight, nBtm, &zStartAff[nEq]);
125809 }
125810 nConstraint += nBtm;
125811 testcase( pRangeStart->wtFlags & TERM_VIRTUAL );
125812 if( sqlite3ExprIsVector(pRight)==0 ){
125813 disableTerm(pLevel, pRangeStart);
@@ -125853,11 +125851,11 @@
125853 ){
125854 sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
125855 VdbeCoverage(v);
125856 }
125857 if( zEndAff ){
125858 updateRangeAffinityStr(pParse, pRight, nTop, zEndAff);
125859 codeApplyAffinity(pParse, regBase+nEq, nTop, zEndAff);
125860 }else{
125861 assert( pParse->db->mallocFailed );
125862 }
125863 nConstraint += nTop;
@@ -130005,11 +130003,11 @@
130005 ** CREATE INDEX ... ON (a, b, c, d, e)
130006 **
130007 ** then this function would be invoked with nEq=1. The value returned in
130008 ** this case is 3.
130009 */
130010 int whereRangeVectorLen(
130011 Parse *pParse, /* Parsing context */
130012 int iCur, /* Cursor open on pIdx */
130013 Index *pIdx, /* The index to be used for a inequality constraint */
130014 int nEq, /* Number of prior equality constraints on same index */
130015 WhereTerm *pTerm /* The vector inequality constraint */
@@ -131451,11 +131449,11 @@
131451 if( rev ) *pRevMask |= MASKBIT(iLoop);
131452 revSet = 1;
131453 }
131454 }
131455 if( isMatch ){
131456 if( iColumn<0 ){
131457 testcase( distinctColumns==0 );
131458 distinctColumns = 1;
131459 }
131460 obSat |= MASKBIT(i);
131461 }else{
@@ -131906,17 +131904,24 @@
131906 }else{
131907 pWInfo->nOBSat = pFrom->isOrdered;
131908 pWInfo->revMask = pFrom->revLoop;
131909 if( pWInfo->nOBSat<=0 ){
131910 pWInfo->nOBSat = 0;
131911 if( nLoop>0 && (pFrom->aLoop[nLoop-1]->wsFlags & WHERE_ONEROW)==0 ){
131912 Bitmask m = 0;
131913 int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom,
 
 
 
 
131914 WHERE_ORDERBY_LIMIT, nLoop-1, pFrom->aLoop[nLoop-1], &m);
131915 if( rc==pWInfo->pOrderBy->nExpr ){
131916 pWInfo->bOrderedInnerLoop = 1;
131917 pWInfo->revMask = m;
 
 
 
131918 }
131919 }
131920 }
131921 }
131922 if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP)
@@ -164296,14 +164301,16 @@
164296 char *zSql;
164297 sqlite3_stmt *p;
164298 int rc;
164299 i64 nRow = 0;
164300
164301 if( sqlite3_table_column_metadata(db,pRtree->zDb,"sqlite_stat1",
164302 0,0,0,0,0,0)==SQLITE_ERROR ){
 
 
164303 pRtree->nRowEst = RTREE_DEFAULT_ROWEST;
164304 return SQLITE_OK;
164305 }
164306 zSql = sqlite3_mprintf(zFmt, pRtree->zDb, pRtree->zName);
164307 if( zSql==0 ){
164308 rc = SQLITE_NOMEM;
164309 }else{
@@ -181496,10 +181503,13 @@
181496 int nToken, /* Size of token in bytes */
181497 int iStartOff, /* Start offset of token */
181498 int iEndOff /* End offset of token */
181499 ){
181500 int rc = SQLITE_OK;
 
 
 
181501
181502 if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){
181503 Fts5SFinder *p = (Fts5SFinder*)pContext;
181504 if( p->iPos>0 ){
181505 int i;
@@ -181652,11 +181662,10 @@
181652 for(jj=0; jj<(sFinder.nFirst-1); jj++){
181653 if( sFinder.aFirst[jj+1]>io ) break;
181654 }
181655
181656 if( sFinder.aFirst[jj]<io ){
181657 int nScore;
181658 memset(aSeen, 0, nPhrase);
181659 rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i,
181660 sFinder.aFirst[jj], nToken, &nScore, 0
181661 );
181662
@@ -195587,11 +195596,11 @@
195587 int nArg, /* Number of args */
195588 sqlite3_value **apUnused /* Function arguments */
195589 ){
195590 assert( nArg==0 );
195591 UNUSED_PARAM2(nArg, apUnused);
195592 sqlite3_result_text(pCtx, "fts5: 2016-10-04 00:47:26 b10d0f939c82c4de3faa90b86de9ec4a89992856", -1, SQLITE_TRANSIENT);
195593 }
195594
195595 static int fts5Init(sqlite3 *db){
195596 static const sqlite3_module fts5Mod = {
195597 /* iVersion */ 2,
195598
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -381,11 +381,11 @@
381 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
382 ** [sqlite_version()] and [sqlite_source_id()].
383 */
384 #define SQLITE_VERSION "3.15.0"
385 #define SQLITE_VERSION_NUMBER 3015000
386 #define SQLITE_SOURCE_ID "2016-10-14 10:20:30 707875582fcba352b4906a595ad89198d84711d8"
387
388 /*
389 ** CAPI3REF: Run-Time Library Version Numbers
390 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
391 **
@@ -44715,11 +44715,11 @@
44715 szBulk = pCache->szAlloc * (i64)pcache1.nInitPage;
44716 }else{
44717 szBulk = -1024 * (i64)pcache1.nInitPage;
44718 }
44719 if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){
44720 szBulk = pCache->szAlloc*(i64)pCache->nMax;
44721 }
44722 zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
44723 sqlite3EndBenignMalloc();
44724 if( zBulk ){
44725 int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
@@ -69336,11 +69336,11 @@
69336 switch( aff ){
69337 case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */
69338 if( (pMem->flags & MEM_Blob)==0 ){
69339 sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding);
69340 assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
69341 if( pMem->flags & MEM_Str ) MemSetTypeFlag(pMem, MEM_Blob);
69342 }else{
69343 pMem->flags &= ~(MEM_TypeMask&~MEM_Blob);
69344 }
69345 break;
69346 }
@@ -88812,11 +88812,10 @@
88812 const char *zId; /* The function name. */
88813 FuncDef *pDef; /* Information about the function */
88814 u8 enc = ENC(pParse->db); /* The database encoding */
88815
88816 assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
 
88817 zId = pExpr->u.zToken;
88818 nId = sqlite3Strlen30(zId);
88819 pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0);
88820 if( pDef==0 ){
88821 pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0);
@@ -124663,11 +124662,10 @@
124662 **
124663 ** * the comparison will be performed with no affinity, or
124664 ** * the affinity change in zAff is guaranteed not to change the value.
124665 */
124666 static void updateRangeAffinityStr(
 
124667 Expr *pRight, /* RHS of comparison */
124668 int n, /* Number of vector elements in comparison */
124669 char *zAff /* Affinity string to modify */
124670 ){
124671 int i;
@@ -125749,15 +125747,15 @@
125747 assert( (bRev & ~1)==0 );
125748 pLevel->iLikeRepCntr <<=1;
125749 pLevel->iLikeRepCntr |= bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC);
125750 }
125751 #endif
125752 if( pRangeStart==0 ){
125753 j = pIdx->aiColumn[nEq];
125754 if( (j>=0 && pIdx->pTable->aCol[j].notNull==0) || j==XN_EXPR ){
125755 bSeekPastNull = 1;
125756 }
125757 }
125758 }
125759 assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 );
125760
125761 /* If we are doing a reverse order scan on an ascending index, or
@@ -125803,11 +125801,11 @@
125801 ){
125802 sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
125803 VdbeCoverage(v);
125804 }
125805 if( zStartAff ){
125806 updateRangeAffinityStr(pRight, nBtm, &zStartAff[nEq]);
125807 }
125808 nConstraint += nBtm;
125809 testcase( pRangeStart->wtFlags & TERM_VIRTUAL );
125810 if( sqlite3ExprIsVector(pRight)==0 ){
125811 disableTerm(pLevel, pRangeStart);
@@ -125853,11 +125851,11 @@
125851 ){
125852 sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
125853 VdbeCoverage(v);
125854 }
125855 if( zEndAff ){
125856 updateRangeAffinityStr(pRight, nTop, zEndAff);
125857 codeApplyAffinity(pParse, regBase+nEq, nTop, zEndAff);
125858 }else{
125859 assert( pParse->db->mallocFailed );
125860 }
125861 nConstraint += nTop;
@@ -130005,11 +130003,11 @@
130003 ** CREATE INDEX ... ON (a, b, c, d, e)
130004 **
130005 ** then this function would be invoked with nEq=1. The value returned in
130006 ** this case is 3.
130007 */
130008 static int whereRangeVectorLen(
130009 Parse *pParse, /* Parsing context */
130010 int iCur, /* Cursor open on pIdx */
130011 Index *pIdx, /* The index to be used for a inequality constraint */
130012 int nEq, /* Number of prior equality constraints on same index */
130013 WhereTerm *pTerm /* The vector inequality constraint */
@@ -131451,11 +131449,11 @@
131449 if( rev ) *pRevMask |= MASKBIT(iLoop);
131450 revSet = 1;
131451 }
131452 }
131453 if( isMatch ){
131454 if( iColumn==XN_ROWID ){
131455 testcase( distinctColumns==0 );
131456 distinctColumns = 1;
131457 }
131458 obSat |= MASKBIT(i);
131459 }else{
@@ -131906,17 +131904,24 @@
131904 }else{
131905 pWInfo->nOBSat = pFrom->isOrdered;
131906 pWInfo->revMask = pFrom->revLoop;
131907 if( pWInfo->nOBSat<=0 ){
131908 pWInfo->nOBSat = 0;
131909 if( nLoop>0 ){
131910 u32 wsFlags = pFrom->aLoop[nLoop-1]->wsFlags;
131911 if( (wsFlags & WHERE_ONEROW)==0
131912 && (wsFlags&(WHERE_IPK|WHERE_COLUMN_IN))!=(WHERE_IPK|WHERE_COLUMN_IN)
131913 ){
131914 Bitmask m = 0;
131915 int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom,
131916 WHERE_ORDERBY_LIMIT, nLoop-1, pFrom->aLoop[nLoop-1], &m);
131917 testcase( wsFlags & WHERE_IPK );
131918 testcase( wsFlags & WHERE_COLUMN_IN );
131919 if( rc==pWInfo->pOrderBy->nExpr ){
131920 pWInfo->bOrderedInnerLoop = 1;
131921 pWInfo->revMask = m;
131922 }
131923 }
131924 }
131925 }
131926 }
131927 if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP)
@@ -164296,14 +164301,16 @@
164301 char *zSql;
164302 sqlite3_stmt *p;
164303 int rc;
164304 i64 nRow = 0;
164305
164306 rc = sqlite3_table_column_metadata(
164307 db, pRtree->zDb, "sqlite_stat1",0,0,0,0,0,0
164308 );
164309 if( rc!=SQLITE_OK ){
164310 pRtree->nRowEst = RTREE_DEFAULT_ROWEST;
164311 return rc==SQLITE_ERROR ? SQLITE_OK : rc;
164312 }
164313 zSql = sqlite3_mprintf(zFmt, pRtree->zDb, pRtree->zName);
164314 if( zSql==0 ){
164315 rc = SQLITE_NOMEM;
164316 }else{
@@ -181496,10 +181503,13 @@
181503 int nToken, /* Size of token in bytes */
181504 int iStartOff, /* Start offset of token */
181505 int iEndOff /* End offset of token */
181506 ){
181507 int rc = SQLITE_OK;
181508
181509 UNUSED_PARAM2(pToken, nToken);
181510 UNUSED_PARAM(iEndOff);
181511
181512 if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){
181513 Fts5SFinder *p = (Fts5SFinder*)pContext;
181514 if( p->iPos>0 ){
181515 int i;
@@ -181652,11 +181662,10 @@
181662 for(jj=0; jj<(sFinder.nFirst-1); jj++){
181663 if( sFinder.aFirst[jj+1]>io ) break;
181664 }
181665
181666 if( sFinder.aFirst[jj]<io ){
 
181667 memset(aSeen, 0, nPhrase);
181668 rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i,
181669 sFinder.aFirst[jj], nToken, &nScore, 0
181670 );
181671
@@ -195587,11 +195596,11 @@
195596 int nArg, /* Number of args */
195597 sqlite3_value **apUnused /* Function arguments */
195598 ){
195599 assert( nArg==0 );
195600 UNUSED_PARAM2(nArg, apUnused);
195601 sqlite3_result_text(pCtx, "fts5: 2016-10-14 10:20:30 707875582fcba352b4906a595ad89198d84711d8", -1, SQLITE_TRANSIENT);
195602 }
195603
195604 static int fts5Init(sqlite3 *db){
195605 static const sqlite3_module fts5Mod = {
195606 /* iVersion */ 2,
195607
+1 -1
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -121,11 +121,11 @@
121121
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
122122
** [sqlite_version()] and [sqlite_source_id()].
123123
*/
124124
#define SQLITE_VERSION "3.15.0"
125125
#define SQLITE_VERSION_NUMBER 3015000
126
-#define SQLITE_SOURCE_ID "2016-10-04 12:20:12 3a9d802fda10585654332b314d317250dc5d894e"
126
+#define SQLITE_SOURCE_ID "2016-10-14 10:20:30 707875582fcba352b4906a595ad89198d84711d8"
127127
128128
/*
129129
** CAPI3REF: Run-Time Library Version Numbers
130130
** KEYWORDS: sqlite3_version, sqlite3_sourceid
131131
**
132132
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -121,11 +121,11 @@
121 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
122 ** [sqlite_version()] and [sqlite_source_id()].
123 */
124 #define SQLITE_VERSION "3.15.0"
125 #define SQLITE_VERSION_NUMBER 3015000
126 #define SQLITE_SOURCE_ID "2016-10-04 12:20:12 3a9d802fda10585654332b314d317250dc5d894e"
127
128 /*
129 ** CAPI3REF: Run-Time Library Version Numbers
130 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
131 **
132
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -121,11 +121,11 @@
121 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
122 ** [sqlite_version()] and [sqlite_source_id()].
123 */
124 #define SQLITE_VERSION "3.15.0"
125 #define SQLITE_VERSION_NUMBER 3015000
126 #define SQLITE_SOURCE_ID "2016-10-14 10:20:30 707875582fcba352b4906a595ad89198d84711d8"
127
128 /*
129 ** CAPI3REF: Run-Time Library Version Numbers
130 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
131 **
132
+14 -16
--- src/stash.c
+++ src/stash.c
@@ -25,11 +25,11 @@
2525
** SQL code to implement the tables needed by the stash.
2626
*/
2727
static const char zStashInit[] =
2828
@ CREATE TABLE IF NOT EXISTS localdb.stash(
2929
@ stashid INTEGER PRIMARY KEY, -- Unique stash identifier
30
-@ vid INTEGER, -- The baseline check-out for this stash
30
+@ vid INTEGER, -- The baseline checkout for this stash
3131
@ comment TEXT, -- Comment for this stash. Or NULL
3232
@ ctime TIMESTAMP -- When the stash was created
3333
@ );
3434
@ CREATE TABLE IF NOT EXISTS localdb.stashfile(
3535
@ stashid INTEGER REFERENCES stash, -- Stash that contains this file
@@ -196,11 +196,11 @@
196196
}
197197
return stashid;
198198
}
199199
200200
/*
201
-** Apply a stash to the current check-out.
201
+** Apply a stash to the current checkout.
202202
*/
203203
static void stash_apply(int stashid, int nConflict){
204204
int vid;
205205
Stmt q;
206206
db_prepare(&q,
@@ -425,60 +425,58 @@
425425
** Save the current changes in the working tree as a new stash.
426426
** Then revert the changes back to the last check-in. If FILES
427427
** are listed, then only stash and revert the named files. The
428428
** "save" verb can be omitted if and only if there are no other
429429
** arguments. The "snapshot" verb works the same as "save" but
430
-** omits the revert, keeping the check-out unchanged.
430
+** omits the revert, keeping the checkout unchanged.
431431
**
432
-** fossil stash list ?-v|--verbose?
433
-** fossil stash ls ?-v|--verbose?
432
+** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>?
434433
**
435434
** List all changes sets currently stashed. Show information about
436435
** individual files in each changeset if -v or --verbose is used.
437436
**
438437
** fossil stash show|cat ?STASHID? ?DIFF-FLAGS?
439438
**
440
-** Show the content of a stash
439
+** Show the contents of a stash.
441440
**
442441
** fossil stash pop
443442
** fossil stash apply ?STASHID?
444443
**
445444
** Apply STASHID or the most recently create stash to the current
446
-** working check-out. The "pop" command deletes that changeset from
445
+** working checkout. The "pop" command deletes that changeset from
447446
** the stash after applying it but the "apply" command retains the
448447
** changeset.
449448
**
450449
** fossil stash goto ?STASHID?
451450
**
452451
** Update to the baseline checkout for STASHID then apply the
453452
** changes of STASHID. Keep STASHID so that it can be reused
454453
** This command is undoable.
455454
**
456
-** fossil stash drop ?STASHID? ?-a|--all?
457
-** fossil stash rm ?STASHID? ?-a|--all?
455
+** fossil stash drop|rm ?STASHID? ?-a|--all?
458456
**
459457
** Forget everything about STASHID. Forget the whole stash if the
460458
** -a|--all flag is used. Individual drops are undoable but -a|--all
461459
** is not.
462460
**
463
-** fossil stash diff ?STASHID?
464
-** fossil stash gdiff ?STASHID?
461
+** fossil stash diff ?STASHID? ?DIFF-OPTIONS?
462
+** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS?
465463
**
466464
** Show diffs of the current working directory and what that
467465
** directory would be if STASHID were applied.
468466
**
469467
** SUMMARY:
470468
** fossil stash
471469
** fossil stash save ?-m|--comment COMMENT? ?FILES...?
472470
** fossil stash snapshot ?-m|--comment COMMENT? ?FILES...?
473
-** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>?
471
+** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>?
474472
** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS?
475473
** fossil stash pop
476
-** fossil stash apply ?STASHID?
477
-** fossil stash goto ?STASHID?
478
-** fossil stash rm|drop ?STASHID? ?-a|--all?
479
-** fossil stash [g]diff ?STASHID? ?DIFF-OPTIONS?
474
+** fossil stash apply|goto ?STASHID?
475
+** fossil stash drop|rm ?STASHID? ?-a|--all?
476
+** fossil stash diff ?STASHID? ?DIFF-OPTIONS?
477
+** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS?
480478
*/
481479
void stash_cmd(void){
482480
const char *zCmd;
483481
int nCmd;
484482
int stashid = 0;
485483
--- src/stash.c
+++ src/stash.c
@@ -25,11 +25,11 @@
25 ** SQL code to implement the tables needed by the stash.
26 */
27 static const char zStashInit[] =
28 @ CREATE TABLE IF NOT EXISTS localdb.stash(
29 @ stashid INTEGER PRIMARY KEY, -- Unique stash identifier
30 @ vid INTEGER, -- The baseline check-out for this stash
31 @ comment TEXT, -- Comment for this stash. Or NULL
32 @ ctime TIMESTAMP -- When the stash was created
33 @ );
34 @ CREATE TABLE IF NOT EXISTS localdb.stashfile(
35 @ stashid INTEGER REFERENCES stash, -- Stash that contains this file
@@ -196,11 +196,11 @@
196 }
197 return stashid;
198 }
199
200 /*
201 ** Apply a stash to the current check-out.
202 */
203 static void stash_apply(int stashid, int nConflict){
204 int vid;
205 Stmt q;
206 db_prepare(&q,
@@ -425,60 +425,58 @@
425 ** Save the current changes in the working tree as a new stash.
426 ** Then revert the changes back to the last check-in. If FILES
427 ** are listed, then only stash and revert the named files. The
428 ** "save" verb can be omitted if and only if there are no other
429 ** arguments. The "snapshot" verb works the same as "save" but
430 ** omits the revert, keeping the check-out unchanged.
431 **
432 ** fossil stash list ?-v|--verbose?
433 ** fossil stash ls ?-v|--verbose?
434 **
435 ** List all changes sets currently stashed. Show information about
436 ** individual files in each changeset if -v or --verbose is used.
437 **
438 ** fossil stash show|cat ?STASHID? ?DIFF-FLAGS?
439 **
440 ** Show the content of a stash
441 **
442 ** fossil stash pop
443 ** fossil stash apply ?STASHID?
444 **
445 ** Apply STASHID or the most recently create stash to the current
446 ** working check-out. The "pop" command deletes that changeset from
447 ** the stash after applying it but the "apply" command retains the
448 ** changeset.
449 **
450 ** fossil stash goto ?STASHID?
451 **
452 ** Update to the baseline checkout for STASHID then apply the
453 ** changes of STASHID. Keep STASHID so that it can be reused
454 ** This command is undoable.
455 **
456 ** fossil stash drop ?STASHID? ?-a|--all?
457 ** fossil stash rm ?STASHID? ?-a|--all?
458 **
459 ** Forget everything about STASHID. Forget the whole stash if the
460 ** -a|--all flag is used. Individual drops are undoable but -a|--all
461 ** is not.
462 **
463 ** fossil stash diff ?STASHID?
464 ** fossil stash gdiff ?STASHID?
465 **
466 ** Show diffs of the current working directory and what that
467 ** directory would be if STASHID were applied.
468 **
469 ** SUMMARY:
470 ** fossil stash
471 ** fossil stash save ?-m|--comment COMMENT? ?FILES...?
472 ** fossil stash snapshot ?-m|--comment COMMENT? ?FILES...?
473 ** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>?
474 ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS?
475 ** fossil stash pop
476 ** fossil stash apply ?STASHID?
477 ** fossil stash goto ?STASHID?
478 ** fossil stash rm|drop ?STASHID? ?-a|--all?
479 ** fossil stash [g]diff ?STASHID? ?DIFF-OPTIONS?
480 */
481 void stash_cmd(void){
482 const char *zCmd;
483 int nCmd;
484 int stashid = 0;
485
--- src/stash.c
+++ src/stash.c
@@ -25,11 +25,11 @@
25 ** SQL code to implement the tables needed by the stash.
26 */
27 static const char zStashInit[] =
28 @ CREATE TABLE IF NOT EXISTS localdb.stash(
29 @ stashid INTEGER PRIMARY KEY, -- Unique stash identifier
30 @ vid INTEGER, -- The baseline checkout for this stash
31 @ comment TEXT, -- Comment for this stash. Or NULL
32 @ ctime TIMESTAMP -- When the stash was created
33 @ );
34 @ CREATE TABLE IF NOT EXISTS localdb.stashfile(
35 @ stashid INTEGER REFERENCES stash, -- Stash that contains this file
@@ -196,11 +196,11 @@
196 }
197 return stashid;
198 }
199
200 /*
201 ** Apply a stash to the current checkout.
202 */
203 static void stash_apply(int stashid, int nConflict){
204 int vid;
205 Stmt q;
206 db_prepare(&q,
@@ -425,60 +425,58 @@
425 ** Save the current changes in the working tree as a new stash.
426 ** Then revert the changes back to the last check-in. If FILES
427 ** are listed, then only stash and revert the named files. The
428 ** "save" verb can be omitted if and only if there are no other
429 ** arguments. The "snapshot" verb works the same as "save" but
430 ** omits the revert, keeping the checkout unchanged.
431 **
432 ** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>?
 
433 **
434 ** List all changes sets currently stashed. Show information about
435 ** individual files in each changeset if -v or --verbose is used.
436 **
437 ** fossil stash show|cat ?STASHID? ?DIFF-FLAGS?
438 **
439 ** Show the contents of a stash.
440 **
441 ** fossil stash pop
442 ** fossil stash apply ?STASHID?
443 **
444 ** Apply STASHID or the most recently create stash to the current
445 ** working checkout. The "pop" command deletes that changeset from
446 ** the stash after applying it but the "apply" command retains the
447 ** changeset.
448 **
449 ** fossil stash goto ?STASHID?
450 **
451 ** Update to the baseline checkout for STASHID then apply the
452 ** changes of STASHID. Keep STASHID so that it can be reused
453 ** This command is undoable.
454 **
455 ** fossil stash drop|rm ?STASHID? ?-a|--all?
 
456 **
457 ** Forget everything about STASHID. Forget the whole stash if the
458 ** -a|--all flag is used. Individual drops are undoable but -a|--all
459 ** is not.
460 **
461 ** fossil stash diff ?STASHID? ?DIFF-OPTIONS?
462 ** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS?
463 **
464 ** Show diffs of the current working directory and what that
465 ** directory would be if STASHID were applied.
466 **
467 ** SUMMARY:
468 ** fossil stash
469 ** fossil stash save ?-m|--comment COMMENT? ?FILES...?
470 ** fossil stash snapshot ?-m|--comment COMMENT? ?FILES...?
471 ** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>?
472 ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS?
473 ** fossil stash pop
474 ** fossil stash apply|goto ?STASHID?
475 ** fossil stash drop|rm ?STASHID? ?-a|--all?
476 ** fossil stash diff ?STASHID? ?DIFF-OPTIONS?
477 ** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS?
478 */
479 void stash_cmd(void){
480 const char *zCmd;
481 int nCmd;
482 int stashid = 0;
483
+14 -16
--- src/stash.c
+++ src/stash.c
@@ -25,11 +25,11 @@
2525
** SQL code to implement the tables needed by the stash.
2626
*/
2727
static const char zStashInit[] =
2828
@ CREATE TABLE IF NOT EXISTS localdb.stash(
2929
@ stashid INTEGER PRIMARY KEY, -- Unique stash identifier
30
-@ vid INTEGER, -- The baseline check-out for this stash
30
+@ vid INTEGER, -- The baseline checkout for this stash
3131
@ comment TEXT, -- Comment for this stash. Or NULL
3232
@ ctime TIMESTAMP -- When the stash was created
3333
@ );
3434
@ CREATE TABLE IF NOT EXISTS localdb.stashfile(
3535
@ stashid INTEGER REFERENCES stash, -- Stash that contains this file
@@ -196,11 +196,11 @@
196196
}
197197
return stashid;
198198
}
199199
200200
/*
201
-** Apply a stash to the current check-out.
201
+** Apply a stash to the current checkout.
202202
*/
203203
static void stash_apply(int stashid, int nConflict){
204204
int vid;
205205
Stmt q;
206206
db_prepare(&q,
@@ -425,60 +425,58 @@
425425
** Save the current changes in the working tree as a new stash.
426426
** Then revert the changes back to the last check-in. If FILES
427427
** are listed, then only stash and revert the named files. The
428428
** "save" verb can be omitted if and only if there are no other
429429
** arguments. The "snapshot" verb works the same as "save" but
430
-** omits the revert, keeping the check-out unchanged.
430
+** omits the revert, keeping the checkout unchanged.
431431
**
432
-** fossil stash list ?-v|--verbose?
433
-** fossil stash ls ?-v|--verbose?
432
+** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>?
434433
**
435434
** List all changes sets currently stashed. Show information about
436435
** individual files in each changeset if -v or --verbose is used.
437436
**
438437
** fossil stash show|cat ?STASHID? ?DIFF-FLAGS?
439438
**
440
-** Show the content of a stash
439
+** Show the contents of a stash.
441440
**
442441
** fossil stash pop
443442
** fossil stash apply ?STASHID?
444443
**
445444
** Apply STASHID or the most recently create stash to the current
446
-** working check-out. The "pop" command deletes that changeset from
445
+** working checkout. The "pop" command deletes that changeset from
447446
** the stash after applying it but the "apply" command retains the
448447
** changeset.
449448
**
450449
** fossil stash goto ?STASHID?
451450
**
452451
** Update to the baseline checkout for STASHID then apply the
453452
** changes of STASHID. Keep STASHID so that it can be reused
454453
** This command is undoable.
455454
**
456
-** fossil stash drop ?STASHID? ?-a|--all?
457
-** fossil stash rm ?STASHID? ?-a|--all?
455
+** fossil stash drop|rm ?STASHID? ?-a|--all?
458456
**
459457
** Forget everything about STASHID. Forget the whole stash if the
460458
** -a|--all flag is used. Individual drops are undoable but -a|--all
461459
** is not.
462460
**
463
-** fossil stash diff ?STASHID?
464
-** fossil stash gdiff ?STASHID?
461
+** fossil stash diff ?STASHID? ?DIFF-OPTIONS?
462
+** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS?
465463
**
466464
** Show diffs of the current working directory and what that
467465
** directory would be if STASHID were applied.
468466
**
469467
** SUMMARY:
470468
** fossil stash
471469
** fossil stash save ?-m|--comment COMMENT? ?FILES...?
472470
** fossil stash snapshot ?-m|--comment COMMENT? ?FILES...?
473
-** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>?
471
+** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>?
474472
** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS?
475473
** fossil stash pop
476
-** fossil stash apply ?STASHID?
477
-** fossil stash goto ?STASHID?
478
-** fossil stash rm|drop ?STASHID? ?-a|--all?
479
-** fossil stash [g]diff ?STASHID? ?DIFF-OPTIONS?
474
+** fossil stash apply|goto ?STASHID?
475
+** fossil stash drop|rm ?STASHID? ?-a|--all?
476
+** fossil stash diff ?STASHID? ?DIFF-OPTIONS?
477
+** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS?
480478
*/
481479
void stash_cmd(void){
482480
const char *zCmd;
483481
int nCmd;
484482
int stashid = 0;
485483
--- src/stash.c
+++ src/stash.c
@@ -25,11 +25,11 @@
25 ** SQL code to implement the tables needed by the stash.
26 */
27 static const char zStashInit[] =
28 @ CREATE TABLE IF NOT EXISTS localdb.stash(
29 @ stashid INTEGER PRIMARY KEY, -- Unique stash identifier
30 @ vid INTEGER, -- The baseline check-out for this stash
31 @ comment TEXT, -- Comment for this stash. Or NULL
32 @ ctime TIMESTAMP -- When the stash was created
33 @ );
34 @ CREATE TABLE IF NOT EXISTS localdb.stashfile(
35 @ stashid INTEGER REFERENCES stash, -- Stash that contains this file
@@ -196,11 +196,11 @@
196 }
197 return stashid;
198 }
199
200 /*
201 ** Apply a stash to the current check-out.
202 */
203 static void stash_apply(int stashid, int nConflict){
204 int vid;
205 Stmt q;
206 db_prepare(&q,
@@ -425,60 +425,58 @@
425 ** Save the current changes in the working tree as a new stash.
426 ** Then revert the changes back to the last check-in. If FILES
427 ** are listed, then only stash and revert the named files. The
428 ** "save" verb can be omitted if and only if there are no other
429 ** arguments. The "snapshot" verb works the same as "save" but
430 ** omits the revert, keeping the check-out unchanged.
431 **
432 ** fossil stash list ?-v|--verbose?
433 ** fossil stash ls ?-v|--verbose?
434 **
435 ** List all changes sets currently stashed. Show information about
436 ** individual files in each changeset if -v or --verbose is used.
437 **
438 ** fossil stash show|cat ?STASHID? ?DIFF-FLAGS?
439 **
440 ** Show the content of a stash
441 **
442 ** fossil stash pop
443 ** fossil stash apply ?STASHID?
444 **
445 ** Apply STASHID or the most recently create stash to the current
446 ** working check-out. The "pop" command deletes that changeset from
447 ** the stash after applying it but the "apply" command retains the
448 ** changeset.
449 **
450 ** fossil stash goto ?STASHID?
451 **
452 ** Update to the baseline checkout for STASHID then apply the
453 ** changes of STASHID. Keep STASHID so that it can be reused
454 ** This command is undoable.
455 **
456 ** fossil stash drop ?STASHID? ?-a|--all?
457 ** fossil stash rm ?STASHID? ?-a|--all?
458 **
459 ** Forget everything about STASHID. Forget the whole stash if the
460 ** -a|--all flag is used. Individual drops are undoable but -a|--all
461 ** is not.
462 **
463 ** fossil stash diff ?STASHID?
464 ** fossil stash gdiff ?STASHID?
465 **
466 ** Show diffs of the current working directory and what that
467 ** directory would be if STASHID were applied.
468 **
469 ** SUMMARY:
470 ** fossil stash
471 ** fossil stash save ?-m|--comment COMMENT? ?FILES...?
472 ** fossil stash snapshot ?-m|--comment COMMENT? ?FILES...?
473 ** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>?
474 ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS?
475 ** fossil stash pop
476 ** fossil stash apply ?STASHID?
477 ** fossil stash goto ?STASHID?
478 ** fossil stash rm|drop ?STASHID? ?-a|--all?
479 ** fossil stash [g]diff ?STASHID? ?DIFF-OPTIONS?
480 */
481 void stash_cmd(void){
482 const char *zCmd;
483 int nCmd;
484 int stashid = 0;
485
--- src/stash.c
+++ src/stash.c
@@ -25,11 +25,11 @@
25 ** SQL code to implement the tables needed by the stash.
26 */
27 static const char zStashInit[] =
28 @ CREATE TABLE IF NOT EXISTS localdb.stash(
29 @ stashid INTEGER PRIMARY KEY, -- Unique stash identifier
30 @ vid INTEGER, -- The baseline checkout for this stash
31 @ comment TEXT, -- Comment for this stash. Or NULL
32 @ ctime TIMESTAMP -- When the stash was created
33 @ );
34 @ CREATE TABLE IF NOT EXISTS localdb.stashfile(
35 @ stashid INTEGER REFERENCES stash, -- Stash that contains this file
@@ -196,11 +196,11 @@
196 }
197 return stashid;
198 }
199
200 /*
201 ** Apply a stash to the current checkout.
202 */
203 static void stash_apply(int stashid, int nConflict){
204 int vid;
205 Stmt q;
206 db_prepare(&q,
@@ -425,60 +425,58 @@
425 ** Save the current changes in the working tree as a new stash.
426 ** Then revert the changes back to the last check-in. If FILES
427 ** are listed, then only stash and revert the named files. The
428 ** "save" verb can be omitted if and only if there are no other
429 ** arguments. The "snapshot" verb works the same as "save" but
430 ** omits the revert, keeping the checkout unchanged.
431 **
432 ** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>?
 
433 **
434 ** List all changes sets currently stashed. Show information about
435 ** individual files in each changeset if -v or --verbose is used.
436 **
437 ** fossil stash show|cat ?STASHID? ?DIFF-FLAGS?
438 **
439 ** Show the contents of a stash.
440 **
441 ** fossil stash pop
442 ** fossil stash apply ?STASHID?
443 **
444 ** Apply STASHID or the most recently create stash to the current
445 ** working checkout. The "pop" command deletes that changeset from
446 ** the stash after applying it but the "apply" command retains the
447 ** changeset.
448 **
449 ** fossil stash goto ?STASHID?
450 **
451 ** Update to the baseline checkout for STASHID then apply the
452 ** changes of STASHID. Keep STASHID so that it can be reused
453 ** This command is undoable.
454 **
455 ** fossil stash drop|rm ?STASHID? ?-a|--all?
 
456 **
457 ** Forget everything about STASHID. Forget the whole stash if the
458 ** -a|--all flag is used. Individual drops are undoable but -a|--all
459 ** is not.
460 **
461 ** fossil stash diff ?STASHID? ?DIFF-OPTIONS?
462 ** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS?
463 **
464 ** Show diffs of the current working directory and what that
465 ** directory would be if STASHID were applied.
466 **
467 ** SUMMARY:
468 ** fossil stash
469 ** fossil stash save ?-m|--comment COMMENT? ?FILES...?
470 ** fossil stash snapshot ?-m|--comment COMMENT? ?FILES...?
471 ** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>?
472 ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS?
473 ** fossil stash pop
474 ** fossil stash apply|goto ?STASHID?
475 ** fossil stash drop|rm ?STASHID? ?-a|--all?
476 ** fossil stash diff ?STASHID? ?DIFF-OPTIONS?
477 ** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS?
478 */
479 void stash_cmd(void){
480 const char *zCmd;
481 int nCmd;
482 int stashid = 0;
483
+88 -15
--- src/winhttp.c
+++ src/winhttp.c
@@ -24,10 +24,24 @@
2424
/* This code is for win32 only */
2525
#include <windows.h>
2626
#include <process.h>
2727
#include "winhttp.h"
2828
29
+/*
30
+** The HttpServer structure holds information about an instance of
31
+** the HTTP server itself.
32
+*/
33
+typedef struct HttpServer HttpServer;
34
+struct HttpServer {
35
+ HANDLE hStoppedEvent; /* Event to signal when server is stopped,
36
+ ** must be closed by callee. */
37
+ char *zStopper; /* The stopper file name, must be freed by
38
+ ** callee. */
39
+ SOCKET listener; /* Socket on which the server is listening,
40
+ ** may be closed by callee. */
41
+};
42
+
2943
/*
3044
** The HttpRequest structure holds information about each incoming
3145
** HTTP request.
3246
*/
3347
typedef struct HttpRequest HttpRequest;
@@ -70,10 +84,51 @@
7084
const char *zService,
7185
const char *zErr
7286
){
7387
fossil_fatal("unable to %s service '%s': %s", zOp, zService, zErr);
7488
}
89
+
90
+/*
91
+** Make sure the server stops as soon as possible after the stopper file
92
+** is found. If there is no stopper file name, do nothing.
93
+*/
94
+static void win32_server_stopper(void *pAppData){
95
+ HttpServer *p = (HttpServer*)pAppData;
96
+ if( p!=0 ){
97
+ HANDLE hStoppedEvent = p->hStoppedEvent;
98
+ const char *zStopper = p->zStopper;
99
+ SOCKET listener = p->listener;
100
+ if( hStoppedEvent!=NULL && zStopper!=0 && listener!=INVALID_SOCKET ){
101
+ while( 1 ){
102
+ DWORD dwResult = WaitForMultipleObjectsEx(1, &hStoppedEvent, FALSE,
103
+ 1000, TRUE);
104
+ if( dwResult!=WAIT_IO_COMPLETION && dwResult!=WAIT_TIMEOUT ){
105
+ /* The event is either invalid, signaled, or abandoned. Bail
106
+ ** out now because those conditions should indicate the parent
107
+ ** thread is dead or dying. */
108
+ break;
109
+ }
110
+ if( file_size(zStopper)>=0 ){
111
+ /* The stopper file has been found. Attempt to close the server
112
+ ** listener socket now and then exit. */
113
+ closesocket(listener);
114
+ p->listener = INVALID_SOCKET;
115
+ break;
116
+ }
117
+ }
118
+ }
119
+ if( hStoppedEvent!=NULL ){
120
+ CloseHandle(hStoppedEvent);
121
+ p->hStoppedEvent = NULL;
122
+ }
123
+ if( zStopper!=0 ){
124
+ fossil_free(p->zStopper);
125
+ p->zStopper = 0;
126
+ }
127
+ fossil_free(p);
128
+ }
129
+}
75130
76131
/*
77132
** Process a single incoming HTTP request.
78133
*/
79134
static void win32_http_request(void *pAppData){
@@ -163,11 +218,11 @@
163218
if( in ) fclose(in);
164219
closesocket(p->s);
165220
file_delete(zRequestFName);
166221
file_delete(zReplyFName);
167222
file_delete(zCmdFName);
168
- free(p);
223
+ fossil_free(p);
169224
}
170225
171226
/*
172227
** Process a single incoming SCGI request.
173228
*/
@@ -225,11 +280,11 @@
225280
if( out ) fclose(out);
226281
if( in ) fclose(in);
227282
closesocket(p->s);
228283
file_delete(zRequestFName);
229284
file_delete(zReplyFName);
230
- free(p);
285
+ fossil_free(p);
231286
}
232287
233288
234289
/*
235290
** Start a listening socket and process incoming HTTP requests on
@@ -243,19 +298,19 @@
243298
const char *zNotFound, /* The --notfound option, or NULL */
244299
const char *zFileGlob, /* The --fileglob option, or NULL */
245300
const char *zIpAddr, /* Bind to this IP address, if not NULL */
246301
int flags /* One or more HTTP_SERVER_ flags */
247302
){
303
+ HANDLE hStoppedEvent;
248304
WSADATA wd;
249305
SOCKET s = INVALID_SOCKET;
250306
SOCKADDR_IN addr;
251307
int idCnt = 0;
252308
int iPort = mnPort;
253309
Blob options;
254310
wchar_t zTmpPath[MAX_PATH];
255311
256
- if( zStopper ) file_delete(zStopper);
257312
blob_zero(&options);
258313
if( zBaseUrl ){
259314
blob_appendf(&options, " --baseurl %s", zBaseUrl);
260315
}
261316
if( zNotFound ){
@@ -324,17 +379,35 @@
324379
zBrowser = mprintf(zBrowser /*works-like:"%d"*/, iPort);
325380
fossil_print("Launch webbrowser: %s\n", zBrowser);
326381
fossil_system(zBrowser);
327382
}
328383
fossil_print("Type Ctrl-C to stop the HTTP server\n");
384
+ /* Create an event used to signal when this server is exiting. */
385
+ hStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
386
+ assert( hStoppedEvent!=NULL );
387
+ /* If there is a stopper file name, start the dedicated thread now.
388
+ ** It will attempt to close the listener socket within 1 second of
389
+ ** the stopper file being created. */
390
+ if( zStopper ){
391
+ HttpServer *pServer = fossil_malloc(sizeof(HttpServer));
392
+ memset(pServer, 0, sizeof(HttpServer));
393
+ DuplicateHandle(GetCurrentProcess(), hStoppedEvent,
394
+ GetCurrentProcess(), &pServer->hStoppedEvent,
395
+ 0, FALSE, DUPLICATE_SAME_ACCESS);
396
+ assert( pServer->hStoppedEvent!=NULL );
397
+ pServer->zStopper = fossil_strdup(zStopper);
398
+ pServer->listener = s;
399
+ file_delete(zStopper);
400
+ _beginthread(win32_server_stopper, 0, (void*)pServer);
401
+ }
329402
/* Set the service status to running and pass the listener socket to the
330403
** service handling procedures. */
331404
win32_http_service_running(s);
332405
for(;;){
333406
SOCKET client;
334407
SOCKADDR_IN client_addr;
335
- HttpRequest *p;
408
+ HttpRequest *pRequest;
336409
int len = sizeof(client_addr);
337410
int wsaError;
338411
339412
client = accept(s, (struct sockaddr*)&client_addr, &len);
340413
if( client==INVALID_SOCKET ){
@@ -347,27 +420,27 @@
347420
}else{
348421
closesocket(s);
349422
WSACleanup();
350423
fossil_fatal("error from accept()");
351424
}
352
- }else if( zStopper && file_size(zStopper)>=0 ){
353
- break;
354
- }
355
- p = fossil_malloc( sizeof(*p) );
356
- p->id = ++idCnt;
357
- p->s = client;
358
- p->addr = client_addr;
359
- p->flags = flags;
360
- p->zOptions = blob_str(&options);
425
+ }
426
+ pRequest = fossil_malloc(sizeof(HttpRequest));
427
+ pRequest->id = ++idCnt;
428
+ pRequest->s = client;
429
+ pRequest->addr = client_addr;
430
+ pRequest->flags = flags;
431
+ pRequest->zOptions = blob_str(&options);
361432
if( flags & HTTP_SERVER_SCGI ){
362
- _beginthread(win32_scgi_request, 0, (void*)p);
433
+ _beginthread(win32_scgi_request, 0, (void*)pRequest);
363434
}else{
364
- _beginthread(win32_http_request, 0, (void*)p);
435
+ _beginthread(win32_http_request, 0, (void*)pRequest);
365436
}
366437
}
367438
closesocket(s);
368439
WSACleanup();
440
+ SetEvent(hStoppedEvent);
441
+ CloseHandle(hStoppedEvent);
369442
}
370443
371444
/*
372445
** The HttpService structure is used to pass information to the service main
373446
** function and to the service control handler function.
374447
--- src/winhttp.c
+++ src/winhttp.c
@@ -24,10 +24,24 @@
24 /* This code is for win32 only */
25 #include <windows.h>
26 #include <process.h>
27 #include "winhttp.h"
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29 /*
30 ** The HttpRequest structure holds information about each incoming
31 ** HTTP request.
32 */
33 typedef struct HttpRequest HttpRequest;
@@ -70,10 +84,51 @@
70 const char *zService,
71 const char *zErr
72 ){
73 fossil_fatal("unable to %s service '%s': %s", zOp, zService, zErr);
74 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
76 /*
77 ** Process a single incoming HTTP request.
78 */
79 static void win32_http_request(void *pAppData){
@@ -163,11 +218,11 @@
163 if( in ) fclose(in);
164 closesocket(p->s);
165 file_delete(zRequestFName);
166 file_delete(zReplyFName);
167 file_delete(zCmdFName);
168 free(p);
169 }
170
171 /*
172 ** Process a single incoming SCGI request.
173 */
@@ -225,11 +280,11 @@
225 if( out ) fclose(out);
226 if( in ) fclose(in);
227 closesocket(p->s);
228 file_delete(zRequestFName);
229 file_delete(zReplyFName);
230 free(p);
231 }
232
233
234 /*
235 ** Start a listening socket and process incoming HTTP requests on
@@ -243,19 +298,19 @@
243 const char *zNotFound, /* The --notfound option, or NULL */
244 const char *zFileGlob, /* The --fileglob option, or NULL */
245 const char *zIpAddr, /* Bind to this IP address, if not NULL */
246 int flags /* One or more HTTP_SERVER_ flags */
247 ){
 
248 WSADATA wd;
249 SOCKET s = INVALID_SOCKET;
250 SOCKADDR_IN addr;
251 int idCnt = 0;
252 int iPort = mnPort;
253 Blob options;
254 wchar_t zTmpPath[MAX_PATH];
255
256 if( zStopper ) file_delete(zStopper);
257 blob_zero(&options);
258 if( zBaseUrl ){
259 blob_appendf(&options, " --baseurl %s", zBaseUrl);
260 }
261 if( zNotFound ){
@@ -324,17 +379,35 @@
324 zBrowser = mprintf(zBrowser /*works-like:"%d"*/, iPort);
325 fossil_print("Launch webbrowser: %s\n", zBrowser);
326 fossil_system(zBrowser);
327 }
328 fossil_print("Type Ctrl-C to stop the HTTP server\n");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
329 /* Set the service status to running and pass the listener socket to the
330 ** service handling procedures. */
331 win32_http_service_running(s);
332 for(;;){
333 SOCKET client;
334 SOCKADDR_IN client_addr;
335 HttpRequest *p;
336 int len = sizeof(client_addr);
337 int wsaError;
338
339 client = accept(s, (struct sockaddr*)&client_addr, &len);
340 if( client==INVALID_SOCKET ){
@@ -347,27 +420,27 @@
347 }else{
348 closesocket(s);
349 WSACleanup();
350 fossil_fatal("error from accept()");
351 }
352 }else if( zStopper && file_size(zStopper)>=0 ){
353 break;
354 }
355 p = fossil_malloc( sizeof(*p) );
356 p->id = ++idCnt;
357 p->s = client;
358 p->addr = client_addr;
359 p->flags = flags;
360 p->zOptions = blob_str(&options);
361 if( flags & HTTP_SERVER_SCGI ){
362 _beginthread(win32_scgi_request, 0, (void*)p);
363 }else{
364 _beginthread(win32_http_request, 0, (void*)p);
365 }
366 }
367 closesocket(s);
368 WSACleanup();
 
 
369 }
370
371 /*
372 ** The HttpService structure is used to pass information to the service main
373 ** function and to the service control handler function.
374
--- src/winhttp.c
+++ src/winhttp.c
@@ -24,10 +24,24 @@
24 /* This code is for win32 only */
25 #include <windows.h>
26 #include <process.h>
27 #include "winhttp.h"
28
29 /*
30 ** The HttpServer structure holds information about an instance of
31 ** the HTTP server itself.
32 */
33 typedef struct HttpServer HttpServer;
34 struct HttpServer {
35 HANDLE hStoppedEvent; /* Event to signal when server is stopped,
36 ** must be closed by callee. */
37 char *zStopper; /* The stopper file name, must be freed by
38 ** callee. */
39 SOCKET listener; /* Socket on which the server is listening,
40 ** may be closed by callee. */
41 };
42
43 /*
44 ** The HttpRequest structure holds information about each incoming
45 ** HTTP request.
46 */
47 typedef struct HttpRequest HttpRequest;
@@ -70,10 +84,51 @@
84 const char *zService,
85 const char *zErr
86 ){
87 fossil_fatal("unable to %s service '%s': %s", zOp, zService, zErr);
88 }
89
90 /*
91 ** Make sure the server stops as soon as possible after the stopper file
92 ** is found. If there is no stopper file name, do nothing.
93 */
94 static void win32_server_stopper(void *pAppData){
95 HttpServer *p = (HttpServer*)pAppData;
96 if( p!=0 ){
97 HANDLE hStoppedEvent = p->hStoppedEvent;
98 const char *zStopper = p->zStopper;
99 SOCKET listener = p->listener;
100 if( hStoppedEvent!=NULL && zStopper!=0 && listener!=INVALID_SOCKET ){
101 while( 1 ){
102 DWORD dwResult = WaitForMultipleObjectsEx(1, &hStoppedEvent, FALSE,
103 1000, TRUE);
104 if( dwResult!=WAIT_IO_COMPLETION && dwResult!=WAIT_TIMEOUT ){
105 /* The event is either invalid, signaled, or abandoned. Bail
106 ** out now because those conditions should indicate the parent
107 ** thread is dead or dying. */
108 break;
109 }
110 if( file_size(zStopper)>=0 ){
111 /* The stopper file has been found. Attempt to close the server
112 ** listener socket now and then exit. */
113 closesocket(listener);
114 p->listener = INVALID_SOCKET;
115 break;
116 }
117 }
118 }
119 if( hStoppedEvent!=NULL ){
120 CloseHandle(hStoppedEvent);
121 p->hStoppedEvent = NULL;
122 }
123 if( zStopper!=0 ){
124 fossil_free(p->zStopper);
125 p->zStopper = 0;
126 }
127 fossil_free(p);
128 }
129 }
130
131 /*
132 ** Process a single incoming HTTP request.
133 */
134 static void win32_http_request(void *pAppData){
@@ -163,11 +218,11 @@
218 if( in ) fclose(in);
219 closesocket(p->s);
220 file_delete(zRequestFName);
221 file_delete(zReplyFName);
222 file_delete(zCmdFName);
223 fossil_free(p);
224 }
225
226 /*
227 ** Process a single incoming SCGI request.
228 */
@@ -225,11 +280,11 @@
280 if( out ) fclose(out);
281 if( in ) fclose(in);
282 closesocket(p->s);
283 file_delete(zRequestFName);
284 file_delete(zReplyFName);
285 fossil_free(p);
286 }
287
288
289 /*
290 ** Start a listening socket and process incoming HTTP requests on
@@ -243,19 +298,19 @@
298 const char *zNotFound, /* The --notfound option, or NULL */
299 const char *zFileGlob, /* The --fileglob option, or NULL */
300 const char *zIpAddr, /* Bind to this IP address, if not NULL */
301 int flags /* One or more HTTP_SERVER_ flags */
302 ){
303 HANDLE hStoppedEvent;
304 WSADATA wd;
305 SOCKET s = INVALID_SOCKET;
306 SOCKADDR_IN addr;
307 int idCnt = 0;
308 int iPort = mnPort;
309 Blob options;
310 wchar_t zTmpPath[MAX_PATH];
311
 
312 blob_zero(&options);
313 if( zBaseUrl ){
314 blob_appendf(&options, " --baseurl %s", zBaseUrl);
315 }
316 if( zNotFound ){
@@ -324,17 +379,35 @@
379 zBrowser = mprintf(zBrowser /*works-like:"%d"*/, iPort);
380 fossil_print("Launch webbrowser: %s\n", zBrowser);
381 fossil_system(zBrowser);
382 }
383 fossil_print("Type Ctrl-C to stop the HTTP server\n");
384 /* Create an event used to signal when this server is exiting. */
385 hStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
386 assert( hStoppedEvent!=NULL );
387 /* If there is a stopper file name, start the dedicated thread now.
388 ** It will attempt to close the listener socket within 1 second of
389 ** the stopper file being created. */
390 if( zStopper ){
391 HttpServer *pServer = fossil_malloc(sizeof(HttpServer));
392 memset(pServer, 0, sizeof(HttpServer));
393 DuplicateHandle(GetCurrentProcess(), hStoppedEvent,
394 GetCurrentProcess(), &pServer->hStoppedEvent,
395 0, FALSE, DUPLICATE_SAME_ACCESS);
396 assert( pServer->hStoppedEvent!=NULL );
397 pServer->zStopper = fossil_strdup(zStopper);
398 pServer->listener = s;
399 file_delete(zStopper);
400 _beginthread(win32_server_stopper, 0, (void*)pServer);
401 }
402 /* Set the service status to running and pass the listener socket to the
403 ** service handling procedures. */
404 win32_http_service_running(s);
405 for(;;){
406 SOCKET client;
407 SOCKADDR_IN client_addr;
408 HttpRequest *pRequest;
409 int len = sizeof(client_addr);
410 int wsaError;
411
412 client = accept(s, (struct sockaddr*)&client_addr, &len);
413 if( client==INVALID_SOCKET ){
@@ -347,27 +420,27 @@
420 }else{
421 closesocket(s);
422 WSACleanup();
423 fossil_fatal("error from accept()");
424 }
425 }
426 pRequest = fossil_malloc(sizeof(HttpRequest));
427 pRequest->id = ++idCnt;
428 pRequest->s = client;
429 pRequest->addr = client_addr;
430 pRequest->flags = flags;
431 pRequest->zOptions = blob_str(&options);
 
 
432 if( flags & HTTP_SERVER_SCGI ){
433 _beginthread(win32_scgi_request, 0, (void*)pRequest);
434 }else{
435 _beginthread(win32_http_request, 0, (void*)pRequest);
436 }
437 }
438 closesocket(s);
439 WSACleanup();
440 SetEvent(hStoppedEvent);
441 CloseHandle(hStoppedEvent);
442 }
443
444 /*
445 ** The HttpService structure is used to pass information to the service main
446 ** function and to the service control handler function.
447
+12 -3
--- test/delta1.test
+++ test/delta1.test
@@ -34,18 +34,27 @@
3434
set f1 [read_file $f]
3535
write_file t1 $f1
3636
for {set i 0} {$i<100} {incr i} {
3737
write_file t2 [random_changes $f1 1 1 0 0.1]
3838
fossil test-delta t1 t2
39
- test delta-$base-$i-1 {$RESULT=="ok"}
39
+ test delta-$base-$i-1 {[normalize_result]=="ok"}
4040
write_file t2 [random_changes $f1 1 1 0 0.2]
4141
fossil test-delta t1 t2
42
- test delta-$base-$i-2 {$RESULT=="ok"}
42
+ test delta-$base-$i-2 {[normalize_result]=="ok"}
4343
write_file t2 [random_changes $f1 1 1 0 0.4]
4444
fossil test-delta t1 t2
45
- test delta-$base-$i-3 {$RESULT=="ok"}
45
+ test delta-$base-$i-3 {[normalize_result]=="ok"}
4646
}
4747
}
4848
49
+set empties { "" "" "" a a "" }
50
+set i 0
51
+foreach {f1 f2} $empties {
52
+ incr i
53
+ write_file t1 $f1
54
+ write_file t2 $f2
55
+ fossil test-delta t1 t2
56
+ test delta-empty-$i {[normalize_result]=="ok"}
57
+}
4958
###############################################################################
5059
5160
test_cleanup
5261
--- test/delta1.test
+++ test/delta1.test
@@ -34,18 +34,27 @@
34 set f1 [read_file $f]
35 write_file t1 $f1
36 for {set i 0} {$i<100} {incr i} {
37 write_file t2 [random_changes $f1 1 1 0 0.1]
38 fossil test-delta t1 t2
39 test delta-$base-$i-1 {$RESULT=="ok"}
40 write_file t2 [random_changes $f1 1 1 0 0.2]
41 fossil test-delta t1 t2
42 test delta-$base-$i-2 {$RESULT=="ok"}
43 write_file t2 [random_changes $f1 1 1 0 0.4]
44 fossil test-delta t1 t2
45 test delta-$base-$i-3 {$RESULT=="ok"}
46 }
47 }
48
 
 
 
 
 
 
 
 
 
49 ###############################################################################
50
51 test_cleanup
52
--- test/delta1.test
+++ test/delta1.test
@@ -34,18 +34,27 @@
34 set f1 [read_file $f]
35 write_file t1 $f1
36 for {set i 0} {$i<100} {incr i} {
37 write_file t2 [random_changes $f1 1 1 0 0.1]
38 fossil test-delta t1 t2
39 test delta-$base-$i-1 {[normalize_result]=="ok"}
40 write_file t2 [random_changes $f1 1 1 0 0.2]
41 fossil test-delta t1 t2
42 test delta-$base-$i-2 {[normalize_result]=="ok"}
43 write_file t2 [random_changes $f1 1 1 0 0.4]
44 fossil test-delta t1 t2
45 test delta-$base-$i-3 {[normalize_result]=="ok"}
46 }
47 }
48
49 set empties { "" "" "" a a "" }
50 set i 0
51 foreach {f1 f2} $empties {
52 incr i
53 write_file t1 $f1
54 write_file t2 $f2
55 fossil test-delta t1 t2
56 test delta-empty-$i {[normalize_result]=="ok"}
57 }
58 ###############################################################################
59
60 test_cleanup
61
+1 -1
--- test/json.test
+++ test/json.test
@@ -23,11 +23,11 @@
2323
# practice of eliminating all trace of the fossil json command when
2424
# not configured. If that changes, these conditions might not prevent
2525
# the rest of this file from running.
2626
fossil test-th-eval "hasfeature json"
2727
28
-if {$::RESULT ne "1"} then {
28
+if {[normalize_result] ne "1"} then {
2929
puts "Fossil was not compiled with JSON support."
3030
test_cleanup_then_return
3131
}
3232
3333
# We need a JSON parser to effectively test the JSON produced by
3434
--- test/json.test
+++ test/json.test
@@ -23,11 +23,11 @@
23 # practice of eliminating all trace of the fossil json command when
24 # not configured. If that changes, these conditions might not prevent
25 # the rest of this file from running.
26 fossil test-th-eval "hasfeature json"
27
28 if {$::RESULT ne "1"} then {
29 puts "Fossil was not compiled with JSON support."
30 test_cleanup_then_return
31 }
32
33 # We need a JSON parser to effectively test the JSON produced by
34
--- test/json.test
+++ test/json.test
@@ -23,11 +23,11 @@
23 # practice of eliminating all trace of the fossil json command when
24 # not configured. If that changes, these conditions might not prevent
25 # the rest of this file from running.
26 fossil test-th-eval "hasfeature json"
27
28 if {[normalize_result] ne "1"} then {
29 puts "Fossil was not compiled with JSON support."
30 test_cleanup_then_return
31 }
32
33 # We need a JSON parser to effectively test the JSON produced by
34
+125 -18
--- test/tester.tcl
+++ test/tester.tcl
@@ -136,13 +136,20 @@
136136
#
137137
proc fossil_maybe_answer {answer args} {
138138
global fossilexe
139139
set cmd $fossilexe
140140
set expectError 0
141
- if {[lindex $args end] eq "-expectError"} {
141
+ set index [lsearch -exact $args -expectError]
142
+ if {$index != -1} {
142143
set expectError 1
143
- set args [lrange $args 0 end-1]
144
+ set args [lreplace $args $index $index]
145
+ }
146
+ set keepNewline 0
147
+ set index [lsearch -exact $args -keepNewline]
148
+ if {$index != -1} {
149
+ set keepNewline 1
150
+ set args [lreplace $args $index $index]
144151
}
145152
foreach a $args {
146153
lappend cmd $a
147154
}
148155
protOut $cmd
@@ -150,14 +157,22 @@
150157
flush stdout
151158
if {[string length $answer] > 0} {
152159
protOut $answer
153160
set prompt_file [file join $::tempPath fossil_prompt_answer]
154161
write_file $prompt_file $answer\n
155
- set rc [catch {eval exec -keepnewline $cmd <$prompt_file} result]
162
+ if {$keepNewline} {
163
+ set rc [catch {eval exec -keepnewline $cmd <$prompt_file} result]
164
+ } else {
165
+ set rc [catch {eval exec $cmd <$prompt_file} result]
166
+ }
156167
file delete $prompt_file
157168
} else {
158
- set rc [catch {eval exec -keepnewline $cmd} result]
169
+ if {$keepNewline} {
170
+ set rc [catch {eval exec -keepnewline $cmd} result]
171
+ } else {
172
+ set rc [catch {eval exec $cmd} result]
173
+ }
159174
}
160175
global RESULT CODE
161176
set CODE $rc
162177
if {($rc && !$expectError) || (!$rc && $expectError)} {
163178
protOut "ERROR: $result" 1
@@ -210,11 +225,11 @@
210225
th1-setup \
211226
th1-uri-regexp]
212227
213228
fossil test-th-eval "hasfeature tcl"
214229
215
- if {$::RESULT eq "1"} {
230
+ if {[normalize_result] eq "1"} {
216231
lappend result tcl-setup
217232
}
218233
219234
return [lsort -dictionary $result]
220235
}
@@ -275,29 +290,29 @@
275290
uv-sync \
276291
web-browser]
277292
278293
fossil test-th-eval "hasfeature legacyMvRm"
279294
280
- if {$::RESULT eq "1"} {
295
+ if {[normalize_result] eq "1"} {
281296
lappend result mv-rm-files
282297
}
283298
284299
fossil test-th-eval "hasfeature tcl"
285300
286
- if {$::RESULT eq "1"} {
301
+ if {[normalize_result] eq "1"} {
287302
lappend result tcl tcl-setup
288303
}
289304
290305
fossil test-th-eval "hasfeature th1Docs"
291306
292
- if {$::RESULT eq "1"} {
307
+ if {[normalize_result] eq "1"} {
293308
lappend result th1-docs
294309
}
295310
296311
fossil test-th-eval "hasfeature th1Hooks"
297312
298
- if {$::RESULT eq "1"} {
313
+ if {[normalize_result] eq "1"} {
299314
lappend result th1-hooks
300315
}
301316
302317
return [lsort -dictionary $result]
303318
}
@@ -440,27 +455,27 @@
440455
441456
# This procedure only returns non-zero if the Tcl integration feature was
442457
# enabled at compile-time and is now enabled at runtime.
443458
proc is_tcl_usable_by_fossil {} {
444459
fossil test-th-eval "hasfeature tcl"
445
- if {$::RESULT ne "1"} {return 0}
460
+ if {[normalize_result] ne "1"} {return 0}
446461
fossil test-th-eval "setting tcl"
447
- if {$::RESULT eq "1"} {return 1}
462
+ if {[normalize_result] eq "1"} {return 1}
448463
fossil test-th-eval --open-config "setting tcl"
449
- if {$::RESULT eq "1"} {return 1}
464
+ if {[normalize_result] eq "1"} {return 1}
450465
return [info exists ::env(TH1_ENABLE_TCL)]
451466
}
452467
453468
# This procedure only returns non-zero if the TH1 hooks feature was enabled
454469
# at compile-time and is now enabled at runtime.
455470
proc are_th1_hooks_usable_by_fossil {} {
456471
fossil test-th-eval "hasfeature th1Hooks"
457
- if {$::RESULT ne "1"} {return 0}
472
+ if {[normalize_result] ne "1"} {return 0}
458473
fossil test-th-eval "setting th1-hooks"
459
- if {$::RESULT eq "1"} {return 1}
474
+ if {[normalize_result] eq "1"} {return 1}
460475
fossil test-th-eval --open-config "setting th1-hooks"
461
- if {$::RESULT eq "1"} {return 1}
476
+ if {[normalize_result] eq "1"} {return 1}
462477
return [info exists ::env(TH1_ENABLE_HOOKS)]
463478
}
464479
465480
# This (rarely used) procedure is designed to run a test within the Fossil
466481
# source checkout (e.g. one that does NOT modify any state), while saving
@@ -560,14 +575,14 @@
560575
# NOTE: Check if we can use any of the environment variables.
561576
#
562577
foreach name $names {
563578
set value [getEnvironmentVariable $name]
564579
565
- if {[string length $value] > 0} then {
580
+ if {[string length $value] > 0} {
566581
set value [file normalize $value]
567582
568
- if {[file exists $value] && [file isdirectory $value]} then {
583
+ if {[file exists $value] && [file isdirectory $value]} {
569584
return $value
570585
}
571586
}
572587
}
573588
@@ -575,11 +590,11 @@
575590
# NOTE: On non-Windows systems, fallback to /tmp if it is usable.
576591
#
577592
if {$::tcl_platform(platform) ne "windows"} {
578593
set value /tmp
579594
580
- if {[file exists $value] && [file isdirectory $value]} then {
595
+ if {[file exists $value] && [file isdirectory $value]} {
581596
return $value
582597
}
583598
}
584599
585600
#
@@ -732,10 +747,102 @@
732747
}
733748
append out \n$line
734749
}
735750
return [string range $out 1 end]
736751
}
752
+
753
+# This procedure executes the "fossil server" command. The return value
754
+# is a list comprised of the new process identifier and the port on which
755
+# the server started. The varName argument refers to a variable
756
+# where the "stop argument" is to be stored. This value must eventually be
757
+# passed to the [test_stop_server] procedure.
758
+proc test_start_server { repository {varName ""} } {
759
+ global fossilexe tempPath
760
+ set command [list exec $fossilexe server --localhost]
761
+ if {[string length $varName] > 0} {
762
+ upvar 1 $varName stopArg
763
+ }
764
+ if {$::tcl_platform(platform) eq "windows"} {
765
+ set stopArg [file join [getTemporaryPath] [appendArgs \
766
+ [string trim [clock seconds] -] _ [getSeqNo] .stopper]]
767
+ lappend command --stopper $stopArg
768
+ }
769
+ set outFileName [file join $tempPath [appendArgs \
770
+ fossil_server_ [string trim [clock seconds] -] _ \
771
+ [getSeqNo]]].out
772
+ lappend command $repository >&$outFileName &
773
+ set pid [eval $command]
774
+ if {$::tcl_platform(platform) ne "windows"} {
775
+ set stopArg $pid
776
+ }
777
+ after 1000; # output might not be there yet
778
+ set output [read_file $outFileName]
779
+ if {![regexp {Listening.*TCP port (\d+)} $output dummy port]} {
780
+ puts stdout "Could not detect Fossil server port, using default..."
781
+ set port 8080; # return the default port just in case
782
+ }
783
+ return [list $pid $port $outFileName]
784
+}
785
+
786
+# This procedure stops a Fossil server instance that was previously started
787
+# by the [test_start_server] procedure. The value of the "stop argument"
788
+# will vary by platform as will the exact method used to stop the server.
789
+# The fileName argument is the name of a temporary output file to delete.
790
+proc test_stop_server { stopArg pid fileName } {
791
+ if {$::tcl_platform(platform) eq "windows"} {
792
+ #
793
+ # NOTE: On Windows, the "stop argument" must be the name of a file
794
+ # that does NOT already exist.
795
+ #
796
+ if {[string length $stopArg] > 0 && \
797
+ ![file exists $stopArg] && \
798
+ [catch {write_file $stopArg [clock seconds]}] == 0} {
799
+ while {1} {
800
+ if {[catch {
801
+ #
802
+ # NOTE: Using the TaskList utility requires Windows XP or
803
+ # later.
804
+ #
805
+ exec tasklist.exe /FI "PID eq $pid"
806
+ } result] != 0 || ![regexp -- " $pid " $result]} {
807
+ break
808
+ }
809
+ after 1000; # wait a bit...
810
+ }
811
+ file delete $stopArg
812
+ if {[string length $fileName] > 0} {
813
+ file delete $fileName
814
+ }
815
+ return true
816
+ }
817
+ } else {
818
+ #
819
+ # NOTE: On Unix, the "stop argument" must be an integer identifier
820
+ # that refers to an existing process.
821
+ #
822
+ if {[regexp {^(?:-)?\d+$} $stopArg] && \
823
+ [catch {exec kill -TERM $stopArg}] == 0} {
824
+ while {1} {
825
+ if {[catch {
826
+ #
827
+ # TODO: Is this portable to all the supported variants of
828
+ # Unix? It should be, it's POSIX.
829
+ #
830
+ exec ps -p $pid
831
+ } result] != 0 || ![regexp -- "(?:^$pid| $pid) " $result]} {
832
+ break
833
+ }
834
+ after 1000; # wait a bit...
835
+ }
836
+ if {[string length $fileName] > 0} {
837
+ file delete $fileName
838
+ }
839
+ return true
840
+ }
841
+ }
842
+ return false
843
+}
737844
738845
# Executes the "fossil http" command. The entire content of the HTTP request
739846
# is read from the data file name, with [subst] being performed on it prior to
740847
# submission. Temporary input and output files are created and deleted. The
741848
# result will be the contents of the temoprary output file.
742849
--- test/tester.tcl
+++ test/tester.tcl
@@ -136,13 +136,20 @@
136 #
137 proc fossil_maybe_answer {answer args} {
138 global fossilexe
139 set cmd $fossilexe
140 set expectError 0
141 if {[lindex $args end] eq "-expectError"} {
 
142 set expectError 1
143 set args [lrange $args 0 end-1]
 
 
 
 
 
 
144 }
145 foreach a $args {
146 lappend cmd $a
147 }
148 protOut $cmd
@@ -150,14 +157,22 @@
150 flush stdout
151 if {[string length $answer] > 0} {
152 protOut $answer
153 set prompt_file [file join $::tempPath fossil_prompt_answer]
154 write_file $prompt_file $answer\n
155 set rc [catch {eval exec -keepnewline $cmd <$prompt_file} result]
 
 
 
 
156 file delete $prompt_file
157 } else {
158 set rc [catch {eval exec -keepnewline $cmd} result]
 
 
 
 
159 }
160 global RESULT CODE
161 set CODE $rc
162 if {($rc && !$expectError) || (!$rc && $expectError)} {
163 protOut "ERROR: $result" 1
@@ -210,11 +225,11 @@
210 th1-setup \
211 th1-uri-regexp]
212
213 fossil test-th-eval "hasfeature tcl"
214
215 if {$::RESULT eq "1"} {
216 lappend result tcl-setup
217 }
218
219 return [lsort -dictionary $result]
220 }
@@ -275,29 +290,29 @@
275 uv-sync \
276 web-browser]
277
278 fossil test-th-eval "hasfeature legacyMvRm"
279
280 if {$::RESULT eq "1"} {
281 lappend result mv-rm-files
282 }
283
284 fossil test-th-eval "hasfeature tcl"
285
286 if {$::RESULT eq "1"} {
287 lappend result tcl tcl-setup
288 }
289
290 fossil test-th-eval "hasfeature th1Docs"
291
292 if {$::RESULT eq "1"} {
293 lappend result th1-docs
294 }
295
296 fossil test-th-eval "hasfeature th1Hooks"
297
298 if {$::RESULT eq "1"} {
299 lappend result th1-hooks
300 }
301
302 return [lsort -dictionary $result]
303 }
@@ -440,27 +455,27 @@
440
441 # This procedure only returns non-zero if the Tcl integration feature was
442 # enabled at compile-time and is now enabled at runtime.
443 proc is_tcl_usable_by_fossil {} {
444 fossil test-th-eval "hasfeature tcl"
445 if {$::RESULT ne "1"} {return 0}
446 fossil test-th-eval "setting tcl"
447 if {$::RESULT eq "1"} {return 1}
448 fossil test-th-eval --open-config "setting tcl"
449 if {$::RESULT eq "1"} {return 1}
450 return [info exists ::env(TH1_ENABLE_TCL)]
451 }
452
453 # This procedure only returns non-zero if the TH1 hooks feature was enabled
454 # at compile-time and is now enabled at runtime.
455 proc are_th1_hooks_usable_by_fossil {} {
456 fossil test-th-eval "hasfeature th1Hooks"
457 if {$::RESULT ne "1"} {return 0}
458 fossil test-th-eval "setting th1-hooks"
459 if {$::RESULT eq "1"} {return 1}
460 fossil test-th-eval --open-config "setting th1-hooks"
461 if {$::RESULT eq "1"} {return 1}
462 return [info exists ::env(TH1_ENABLE_HOOKS)]
463 }
464
465 # This (rarely used) procedure is designed to run a test within the Fossil
466 # source checkout (e.g. one that does NOT modify any state), while saving
@@ -560,14 +575,14 @@
560 # NOTE: Check if we can use any of the environment variables.
561 #
562 foreach name $names {
563 set value [getEnvironmentVariable $name]
564
565 if {[string length $value] > 0} then {
566 set value [file normalize $value]
567
568 if {[file exists $value] && [file isdirectory $value]} then {
569 return $value
570 }
571 }
572 }
573
@@ -575,11 +590,11 @@
575 # NOTE: On non-Windows systems, fallback to /tmp if it is usable.
576 #
577 if {$::tcl_platform(platform) ne "windows"} {
578 set value /tmp
579
580 if {[file exists $value] && [file isdirectory $value]} then {
581 return $value
582 }
583 }
584
585 #
@@ -732,10 +747,102 @@
732 }
733 append out \n$line
734 }
735 return [string range $out 1 end]
736 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
737
738 # Executes the "fossil http" command. The entire content of the HTTP request
739 # is read from the data file name, with [subst] being performed on it prior to
740 # submission. Temporary input and output files are created and deleted. The
741 # result will be the contents of the temoprary output file.
742
--- test/tester.tcl
+++ test/tester.tcl
@@ -136,13 +136,20 @@
136 #
137 proc fossil_maybe_answer {answer args} {
138 global fossilexe
139 set cmd $fossilexe
140 set expectError 0
141 set index [lsearch -exact $args -expectError]
142 if {$index != -1} {
143 set expectError 1
144 set args [lreplace $args $index $index]
145 }
146 set keepNewline 0
147 set index [lsearch -exact $args -keepNewline]
148 if {$index != -1} {
149 set keepNewline 1
150 set args [lreplace $args $index $index]
151 }
152 foreach a $args {
153 lappend cmd $a
154 }
155 protOut $cmd
@@ -150,14 +157,22 @@
157 flush stdout
158 if {[string length $answer] > 0} {
159 protOut $answer
160 set prompt_file [file join $::tempPath fossil_prompt_answer]
161 write_file $prompt_file $answer\n
162 if {$keepNewline} {
163 set rc [catch {eval exec -keepnewline $cmd <$prompt_file} result]
164 } else {
165 set rc [catch {eval exec $cmd <$prompt_file} result]
166 }
167 file delete $prompt_file
168 } else {
169 if {$keepNewline} {
170 set rc [catch {eval exec -keepnewline $cmd} result]
171 } else {
172 set rc [catch {eval exec $cmd} result]
173 }
174 }
175 global RESULT CODE
176 set CODE $rc
177 if {($rc && !$expectError) || (!$rc && $expectError)} {
178 protOut "ERROR: $result" 1
@@ -210,11 +225,11 @@
225 th1-setup \
226 th1-uri-regexp]
227
228 fossil test-th-eval "hasfeature tcl"
229
230 if {[normalize_result] eq "1"} {
231 lappend result tcl-setup
232 }
233
234 return [lsort -dictionary $result]
235 }
@@ -275,29 +290,29 @@
290 uv-sync \
291 web-browser]
292
293 fossil test-th-eval "hasfeature legacyMvRm"
294
295 if {[normalize_result] eq "1"} {
296 lappend result mv-rm-files
297 }
298
299 fossil test-th-eval "hasfeature tcl"
300
301 if {[normalize_result] eq "1"} {
302 lappend result tcl tcl-setup
303 }
304
305 fossil test-th-eval "hasfeature th1Docs"
306
307 if {[normalize_result] eq "1"} {
308 lappend result th1-docs
309 }
310
311 fossil test-th-eval "hasfeature th1Hooks"
312
313 if {[normalize_result] eq "1"} {
314 lappend result th1-hooks
315 }
316
317 return [lsort -dictionary $result]
318 }
@@ -440,27 +455,27 @@
455
456 # This procedure only returns non-zero if the Tcl integration feature was
457 # enabled at compile-time and is now enabled at runtime.
458 proc is_tcl_usable_by_fossil {} {
459 fossil test-th-eval "hasfeature tcl"
460 if {[normalize_result] ne "1"} {return 0}
461 fossil test-th-eval "setting tcl"
462 if {[normalize_result] eq "1"} {return 1}
463 fossil test-th-eval --open-config "setting tcl"
464 if {[normalize_result] eq "1"} {return 1}
465 return [info exists ::env(TH1_ENABLE_TCL)]
466 }
467
468 # This procedure only returns non-zero if the TH1 hooks feature was enabled
469 # at compile-time and is now enabled at runtime.
470 proc are_th1_hooks_usable_by_fossil {} {
471 fossil test-th-eval "hasfeature th1Hooks"
472 if {[normalize_result] ne "1"} {return 0}
473 fossil test-th-eval "setting th1-hooks"
474 if {[normalize_result] eq "1"} {return 1}
475 fossil test-th-eval --open-config "setting th1-hooks"
476 if {[normalize_result] eq "1"} {return 1}
477 return [info exists ::env(TH1_ENABLE_HOOKS)]
478 }
479
480 # This (rarely used) procedure is designed to run a test within the Fossil
481 # source checkout (e.g. one that does NOT modify any state), while saving
@@ -560,14 +575,14 @@
575 # NOTE: Check if we can use any of the environment variables.
576 #
577 foreach name $names {
578 set value [getEnvironmentVariable $name]
579
580 if {[string length $value] > 0} {
581 set value [file normalize $value]
582
583 if {[file exists $value] && [file isdirectory $value]} {
584 return $value
585 }
586 }
587 }
588
@@ -575,11 +590,11 @@
590 # NOTE: On non-Windows systems, fallback to /tmp if it is usable.
591 #
592 if {$::tcl_platform(platform) ne "windows"} {
593 set value /tmp
594
595 if {[file exists $value] && [file isdirectory $value]} {
596 return $value
597 }
598 }
599
600 #
@@ -732,10 +747,102 @@
747 }
748 append out \n$line
749 }
750 return [string range $out 1 end]
751 }
752
753 # This procedure executes the "fossil server" command. The return value
754 # is a list comprised of the new process identifier and the port on which
755 # the server started. The varName argument refers to a variable
756 # where the "stop argument" is to be stored. This value must eventually be
757 # passed to the [test_stop_server] procedure.
758 proc test_start_server { repository {varName ""} } {
759 global fossilexe tempPath
760 set command [list exec $fossilexe server --localhost]
761 if {[string length $varName] > 0} {
762 upvar 1 $varName stopArg
763 }
764 if {$::tcl_platform(platform) eq "windows"} {
765 set stopArg [file join [getTemporaryPath] [appendArgs \
766 [string trim [clock seconds] -] _ [getSeqNo] .stopper]]
767 lappend command --stopper $stopArg
768 }
769 set outFileName [file join $tempPath [appendArgs \
770 fossil_server_ [string trim [clock seconds] -] _ \
771 [getSeqNo]]].out
772 lappend command $repository >&$outFileName &
773 set pid [eval $command]
774 if {$::tcl_platform(platform) ne "windows"} {
775 set stopArg $pid
776 }
777 after 1000; # output might not be there yet
778 set output [read_file $outFileName]
779 if {![regexp {Listening.*TCP port (\d+)} $output dummy port]} {
780 puts stdout "Could not detect Fossil server port, using default..."
781 set port 8080; # return the default port just in case
782 }
783 return [list $pid $port $outFileName]
784 }
785
786 # This procedure stops a Fossil server instance that was previously started
787 # by the [test_start_server] procedure. The value of the "stop argument"
788 # will vary by platform as will the exact method used to stop the server.
789 # The fileName argument is the name of a temporary output file to delete.
790 proc test_stop_server { stopArg pid fileName } {
791 if {$::tcl_platform(platform) eq "windows"} {
792 #
793 # NOTE: On Windows, the "stop argument" must be the name of a file
794 # that does NOT already exist.
795 #
796 if {[string length $stopArg] > 0 && \
797 ![file exists $stopArg] && \
798 [catch {write_file $stopArg [clock seconds]}] == 0} {
799 while {1} {
800 if {[catch {
801 #
802 # NOTE: Using the TaskList utility requires Windows XP or
803 # later.
804 #
805 exec tasklist.exe /FI "PID eq $pid"
806 } result] != 0 || ![regexp -- " $pid " $result]} {
807 break
808 }
809 after 1000; # wait a bit...
810 }
811 file delete $stopArg
812 if {[string length $fileName] > 0} {
813 file delete $fileName
814 }
815 return true
816 }
817 } else {
818 #
819 # NOTE: On Unix, the "stop argument" must be an integer identifier
820 # that refers to an existing process.
821 #
822 if {[regexp {^(?:-)?\d+$} $stopArg] && \
823 [catch {exec kill -TERM $stopArg}] == 0} {
824 while {1} {
825 if {[catch {
826 #
827 # TODO: Is this portable to all the supported variants of
828 # Unix? It should be, it's POSIX.
829 #
830 exec ps -p $pid
831 } result] != 0 || ![regexp -- "(?:^$pid| $pid) " $result]} {
832 break
833 }
834 after 1000; # wait a bit...
835 }
836 if {[string length $fileName] > 0} {
837 file delete $fileName
838 }
839 return true
840 }
841 }
842 return false
843 }
844
845 # Executes the "fossil http" command. The entire content of the HTTP request
846 # is read from the data file name, with [subst] being performed on it prior to
847 # submission. Temporary input and output files are created and deleted. The
848 # result will be the contents of the temoprary output file.
849
--- test/th1-docs.test
+++ test/th1-docs.test
@@ -18,18 +18,18 @@
1818
# TH1 Docs
1919
#
2020
2121
fossil test-th-eval "hasfeature th1Docs"
2222
23
-if {$::RESULT ne "1"} {
23
+if {[normalize_result] ne "1"} {
2424
puts "Fossil was not compiled with TH1 docs support."
2525
test_cleanup_then_return
2626
}
2727
2828
fossil test-th-eval "hasfeature tcl"
2929
30
-if {$::RESULT ne "1"} {
30
+if {[normalize_result] ne "1"} {
3131
puts "Fossil was not compiled with Tcl support."
3232
test_cleanup_then_return
3333
}
3434
3535
###############################################################################
3636
--- test/th1-docs.test
+++ test/th1-docs.test
@@ -18,18 +18,18 @@
18 # TH1 Docs
19 #
20
21 fossil test-th-eval "hasfeature th1Docs"
22
23 if {$::RESULT ne "1"} {
24 puts "Fossil was not compiled with TH1 docs support."
25 test_cleanup_then_return
26 }
27
28 fossil test-th-eval "hasfeature tcl"
29
30 if {$::RESULT ne "1"} {
31 puts "Fossil was not compiled with Tcl support."
32 test_cleanup_then_return
33 }
34
35 ###############################################################################
36
--- test/th1-docs.test
+++ test/th1-docs.test
@@ -18,18 +18,18 @@
18 # TH1 Docs
19 #
20
21 fossil test-th-eval "hasfeature th1Docs"
22
23 if {[normalize_result] ne "1"} {
24 puts "Fossil was not compiled with TH1 docs support."
25 test_cleanup_then_return
26 }
27
28 fossil test-th-eval "hasfeature tcl"
29
30 if {[normalize_result] ne "1"} {
31 puts "Fossil was not compiled with Tcl support."
32 test_cleanup_then_return
33 }
34
35 ###############################################################################
36
--- test/th1-hooks.test
+++ test/th1-hooks.test
@@ -18,11 +18,11 @@
1818
# TH1 Hooks
1919
#
2020
2121
fossil test-th-eval "hasfeature th1Hooks"
2222
23
-if {$::RESULT ne "1"} {
23
+if {[normalize_result] ne "1"} {
2424
puts "Fossil was not compiled with TH1 hooks support."
2525
test_cleanup_then_return
2626
}
2727
2828
###############################################################################
@@ -75,12 +75,17 @@
7575
return -code 2 "TH_RETURN return code"
7676
} elseif {$::cmd_name eq "timeline"} {
7777
set length [llength $::cmd_args]
7878
set length [expr {$length - 1}]
7979
if {[lindex $::cmd_args $length] eq "custom"} {
80
+ append_hook_log "CUSTOM TIMELINE"
8081
emit_hook_log
8182
return "custom timeline"
83
+ } elseif {[lindex $::cmd_args $length] eq "custom2"} {
84
+ emit_hook_log
85
+ puts "+++ some stuff here +++"
86
+ continue "custom2 timeline"
8287
} elseif {[lindex $::cmd_args $length] eq "now"} {
8388
emit_hook_log
8489
return "now timeline"
8590
} else {
8691
emit_hook_log
@@ -122,15 +127,21 @@
122127
123128
saveTh1SetupFile; writeTh1SetupFile $testTh1Setup
124129
125130
###############################################################################
126131
127
-fossil timeline custom; # NOTE: Bad "WHEN" argument.
132
+fossil timeline custom -expectError; # NOTE: Bad "WHEN" argument.
128133
test th1-cmd-hooks-1a {[normalize_result] eq \
134
+{<h1><b>command_hook timeline CUSTOM TIMELINE</b></h1>
135
+unknown check-in or invalid date: custom}}
136
+
137
+###############################################################################
138
+
139
+fossil timeline custom2; # NOTE: Bad "WHEN" argument.
140
+test th1-cmd-hooks-1b {[normalize_result] eq \
129141
{<h1><b>command_hook timeline</b></h1>
130
-+++ no more data (0) +++
131
-
++++ some stuff here +++
132142
<h1><b>command_hook timeline command_notify timeline</b></h1>}}
133143
134144
###############################################################################
135145
136146
fossil timeline
137147
--- test/th1-hooks.test
+++ test/th1-hooks.test
@@ -18,11 +18,11 @@
18 # TH1 Hooks
19 #
20
21 fossil test-th-eval "hasfeature th1Hooks"
22
23 if {$::RESULT ne "1"} {
24 puts "Fossil was not compiled with TH1 hooks support."
25 test_cleanup_then_return
26 }
27
28 ###############################################################################
@@ -75,12 +75,17 @@
75 return -code 2 "TH_RETURN return code"
76 } elseif {$::cmd_name eq "timeline"} {
77 set length [llength $::cmd_args]
78 set length [expr {$length - 1}]
79 if {[lindex $::cmd_args $length] eq "custom"} {
 
80 emit_hook_log
81 return "custom timeline"
 
 
 
 
82 } elseif {[lindex $::cmd_args $length] eq "now"} {
83 emit_hook_log
84 return "now timeline"
85 } else {
86 emit_hook_log
@@ -122,15 +127,21 @@
122
123 saveTh1SetupFile; writeTh1SetupFile $testTh1Setup
124
125 ###############################################################################
126
127 fossil timeline custom; # NOTE: Bad "WHEN" argument.
128 test th1-cmd-hooks-1a {[normalize_result] eq \
 
 
 
 
 
 
 
129 {<h1><b>command_hook timeline</b></h1>
130 +++ no more data (0) +++
131
++++ some stuff here +++
132 <h1><b>command_hook timeline command_notify timeline</b></h1>}}
133
134 ###############################################################################
135
136 fossil timeline
137
--- test/th1-hooks.test
+++ test/th1-hooks.test
@@ -18,11 +18,11 @@
18 # TH1 Hooks
19 #
20
21 fossil test-th-eval "hasfeature th1Hooks"
22
23 if {[normalize_result] ne "1"} {
24 puts "Fossil was not compiled with TH1 hooks support."
25 test_cleanup_then_return
26 }
27
28 ###############################################################################
@@ -75,12 +75,17 @@
75 return -code 2 "TH_RETURN return code"
76 } elseif {$::cmd_name eq "timeline"} {
77 set length [llength $::cmd_args]
78 set length [expr {$length - 1}]
79 if {[lindex $::cmd_args $length] eq "custom"} {
80 append_hook_log "CUSTOM TIMELINE"
81 emit_hook_log
82 return "custom timeline"
83 } elseif {[lindex $::cmd_args $length] eq "custom2"} {
84 emit_hook_log
85 puts "+++ some stuff here +++"
86 continue "custom2 timeline"
87 } elseif {[lindex $::cmd_args $length] eq "now"} {
88 emit_hook_log
89 return "now timeline"
90 } else {
91 emit_hook_log
@@ -122,15 +127,21 @@
127
128 saveTh1SetupFile; writeTh1SetupFile $testTh1Setup
129
130 ###############################################################################
131
132 fossil timeline custom -expectError; # NOTE: Bad "WHEN" argument.
133 test th1-cmd-hooks-1a {[normalize_result] eq \
134 {<h1><b>command_hook timeline CUSTOM TIMELINE</b></h1>
135 unknown check-in or invalid date: custom}}
136
137 ###############################################################################
138
139 fossil timeline custom2; # NOTE: Bad "WHEN" argument.
140 test th1-cmd-hooks-1b {[normalize_result] eq \
141 {<h1><b>command_hook timeline</b></h1>
 
 
++++ some stuff here +++
142 <h1><b>command_hook timeline command_notify timeline</b></h1>}}
143
144 ###############################################################################
145
146 fossil timeline
147
--- test/th1-tcl.test
+++ test/th1-tcl.test
@@ -22,11 +22,11 @@
2222
2323
###############################################################################
2424
2525
fossil test-th-eval "hasfeature tcl"
2626
27
-if {$::RESULT ne "1"} {
27
+if {[normalize_result] ne "1"} {
2828
puts "Fossil was not compiled with Tcl support."
2929
test_cleanup_then_return
3030
}
3131
3232
###############################################################################
3333
--- test/th1-tcl.test
+++ test/th1-tcl.test
@@ -22,11 +22,11 @@
22
23 ###############################################################################
24
25 fossil test-th-eval "hasfeature tcl"
26
27 if {$::RESULT ne "1"} {
28 puts "Fossil was not compiled with Tcl support."
29 test_cleanup_then_return
30 }
31
32 ###############################################################################
33
--- test/th1-tcl.test
+++ test/th1-tcl.test
@@ -22,11 +22,11 @@
22
23 ###############################################################################
24
25 fossil test-th-eval "hasfeature tcl"
26
27 if {[normalize_result] ne "1"} {
28 puts "Fossil was not compiled with Tcl support."
29 test_cleanup_then_return
30 }
31
32 ###############################################################################
33
--- test/unversioned.test
+++ test/unversioned.test
@@ -26,17 +26,28 @@
2626
}
2727
2828
require_no_open_checkout
2929
3030
test_setup; set rootDir [file normalize [pwd]]
31
+
32
+fossil test-th-eval --open-config {repository}
33
+set repository [normalize_result]
34
+
35
+if {[string length $repository] == 0} {
36
+ puts "Detection of the open repository file failed."
37
+ test_cleanup_then_return
38
+}
3139
3240
write_file unversioned1.txt "This is unversioned file #1."
3341
write_file unversioned2.txt " This is unversioned file #2. "
3442
write_file "unversioned space.txt" "\nThis is unversioned file #3.\n"
3543
write_file unversioned4.txt "This is unversioned file #4."
3644
write_file unversioned5.txt "This is unversioned file #5."
3745
46
+set env(VISUAL) [appendArgs \
47
+ [info nameofexecutable] " " [file join $path fake-editor.tcl]]
48
+
3849
###############################################################################
3950
4051
fossil unversioned
4152
test unversioned-1 {[normalize_result] eq \
4253
[string map [list %fossil% [file nativename $fossilexe]] {Usage: %fossil%\
@@ -167,11 +178,11 @@
167178
test unversioned-23 {[::sha1::sha1 $RESULT] eq \
168179
{962f96ebd613e4fdd9aa2d20bd9fe21a64e925f2}}
169180
170181
###############################################################################
171182
172
-fossil unversioned cat unversioned3.txt
183
+fossil unversioned cat unversioned3.txt -keepNewline
173184
test unversioned-24 {[::sha1::sha1 $RESULT] eq \
174185
{c6b95509120d9703cc4fbe5cdfcb435b5912b3e4}}
175186
176187
###############################################################################
177188
@@ -190,13 +201,10 @@
190201
test unversioned-27 {$hash(before) eq \
191202
{b48ba8e2d0b498321dfd13de84867effda399af5}}
192203
193204
###############################################################################
194205
195
-set env(VISUAL) [appendArgs \
196
- [info nameofexecutable] " " [file join $path fake-editor.tcl]]
197
-
198206
fossil unversioned edit unversioned4.txt
199207
test unversioned-28 {[normalize_result] eq {}}
200208
201209
###############################################################################
202210
@@ -295,14 +303,155 @@
295303
{^[0-9a-f]{12} 2016-10-01 00:00:00 30 30 unversioned2\.txt
296304
[0-9a-f]{12} \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} 28 28\
297305
unversioned5\.txt$} [normalize_result]]}
298306
299307
###############################################################################
300
-#
301
-# TODO: Add tests for the unversioned "revert" and "sync" sub-commands.
302
-#
303
-# revert --verbose --dryrun
304
-# sync
305
-#
308
+
309
+set password [string trim [clock seconds] -]
310
+
311
+fossil user new uvtester "Unversioned Test User" $password
312
+fossil user capabilities uvtester oy
313
+
314
+###############################################################################
315
+
316
+foreach {pid port outTmpFile} [test_start_server $repository stopArg] {}
317
+puts [appendArgs "Started Fossil server, pid \"" $pid \" ", port \"" $port \".]
318
+set remote [appendArgs http://uvtester: $password @localhost: $port /]
319
+
320
+###############################################################################
321
+
322
+set clientDir [file join $tempPath [appendArgs \
323
+ uvtest_ [string trim [clock seconds] -] _ [getSeqNo]]]
324
+
325
+set savedPwd [pwd]
326
+file mkdir $clientDir; cd $clientDir
327
+puts [appendArgs "Now in client directory \"" [pwd] \".]
328
+write_file unversioned-client1.txt "This is unversioned client file #1."
329
+
330
+###############################################################################
331
+
332
+fossil_maybe_answer y clone $remote uvrepo.fossil
333
+fossil open uvrepo.fossil
334
+
335
+###############################################################################
336
+
337
+fossil unversioned list
338
+test unversioned-45 {[normalize_result] eq {}}
339
+
340
+###############################################################################
341
+
342
+fossil_maybe_answer y unversioned sync $remote
343
+test unversioned-46 {[regexp \
344
+{Round-trips: 1 Artifacts sent: 0 received: 0
345
+Round-trips: 1 Artifacts sent: 0 received: 0
346
+Round-trips: 2 Artifacts sent: 0 received: 0
347
+Round-trips: 2 Artifacts sent: 0 received: 2
348
+\n? done, sent: \d+ received: \d+ ip: 127.0.0.1} [normalize_result]]}
349
+
350
+###############################################################################
351
+
352
+fossil unversioned ls
353
+test unversioned-47 {[normalize_result] eq {unversioned2.txt
354
+unversioned5.txt}}
355
+
356
+###############################################################################
357
+
358
+set env(FAKE_EDITOR_SCRIPT) "append data this_is_a_test"; # deterministic
359
+
360
+fossil unversioned edit unversioned2.txt
361
+test unversioned-48 {[normalize_result] eq {}}
362
+
363
+unset env(FAKE_EDITOR_SCRIPT)
364
+
365
+###############################################################################
366
+
367
+fossil unversioned cat unversioned2.txt
368
+test unversioned-49 {[::sha1::sha1 $RESULT] eq \
369
+{e15d4b576fc04e3bb5e44a33d44d104dd5b19428}}
370
+
371
+###############################################################################
372
+
373
+fossil unversioned remove unversioned5.txt
374
+test unversioned-50 {[normalize_result] eq {}}
375
+
376
+###############################################################################
377
+
378
+fossil unversioned list --all
379
+test unversioned-51 {[regexp \
380
+{^[0-9a-f]{12} \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} 44 44\
381
+unversioned2\.txt
382
+ \(deleted\) \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} 0 0\
383
+unversioned5\.txt$} [normalize_result]]}
384
+
385
+###############################################################################
386
+
387
+fossil_maybe_answer y unversioned revert $remote
388
+test unversioned-52 {[regexp \
389
+{Round-trips: 1 Artifacts sent: 0 received: 0
390
+Round-trips: 1 Artifacts sent: 0 received: 0
391
+Round-trips: 2 Artifacts sent: 0 received: 0
392
+Round-trips: 2 Artifacts sent: 0 received: 2
393
+\n? done, sent: \d+ received: \d+ ip: 127.0.0.1} [normalize_result]]}
394
+
395
+###############################################################################
396
+
397
+fossil unversioned list
398
+test unversioned-53 {[regexp \
399
+{^[0-9a-f]{12} 2016-10-01 00:00:00 30 30\
400
+unversioned2\.txt
401
+[0-9a-f]{12} \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} 28 28\
402
+unversioned5\.txt$} [normalize_result]]}
403
+
404
+###############################################################################
405
+
406
+fossil unversioned add unversioned-client1.txt
407
+test unversioned-54 {[normalize_result] eq {}}
408
+
409
+###############################################################################
410
+
411
+fossil_maybe_answer y unversioned sync $remote
412
+test unversioned-55 {[regexp \
413
+{Round-trips: 1 Artifacts sent: 0 received: 0
414
+Round-trips: 1 Artifacts sent: 0 received: 0
415
+Round-trips: 2 Artifacts sent: 1 received: 0
416
+Round-trips: 2 Artifacts sent: 1 received: 0
417
+\n? done, sent: \d+ received: \d+ ip: 127.0.0.1} [normalize_result]]}
418
+
419
+###############################################################################
420
+
421
+fossil close
422
+test unversioned-56 {[normalize_result] eq {}}
423
+
424
+###############################################################################
425
+
426
+cd $savedPwd; unset savedPwd
427
+file delete -force $clientDir
428
+puts [appendArgs "Now in server directory \"" [pwd] \".]
429
+
430
+###############################################################################
431
+
432
+set stopped [test_stop_server $stopArg $pid $outTmpFile]
433
+
434
+puts [appendArgs \
435
+ [expr {$stopped ? "Stopped" : "Could not stop"}] \
436
+ " Fossil server, pid \"" $pid "\", using argument \"" \
437
+ $stopArg \".]
438
+
439
+###############################################################################
440
+
441
+fossil unversioned list
442
+test unversioned-57 {[regexp \
443
+{^[0-9a-f]{12} \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} 35 35\
444
+unversioned-client1\.txt
445
+[0-9a-f]{12} 2016-10-01 00:00:00 30 30 unversioned2\.txt
446
+[0-9a-f]{12} \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} 28 28\
447
+unversioned5\.txt$} [normalize_result]]}
448
+
449
+###############################################################################
450
+
451
+fossil unversioned cat unversioned-client1.txt
452
+test unversioned-58 {[::sha1::sha1 $RESULT] eq \
453
+{a34606f714afe309bb531fba6051eaf25201e8a2}}
454
+
306455
###############################################################################
307456
308457
test_cleanup
309458
--- test/unversioned.test
+++ test/unversioned.test
@@ -26,17 +26,28 @@
26 }
27
28 require_no_open_checkout
29
30 test_setup; set rootDir [file normalize [pwd]]
 
 
 
 
 
 
 
 
31
32 write_file unversioned1.txt "This is unversioned file #1."
33 write_file unversioned2.txt " This is unversioned file #2. "
34 write_file "unversioned space.txt" "\nThis is unversioned file #3.\n"
35 write_file unversioned4.txt "This is unversioned file #4."
36 write_file unversioned5.txt "This is unversioned file #5."
37
 
 
 
38 ###############################################################################
39
40 fossil unversioned
41 test unversioned-1 {[normalize_result] eq \
42 [string map [list %fossil% [file nativename $fossilexe]] {Usage: %fossil%\
@@ -167,11 +178,11 @@
167 test unversioned-23 {[::sha1::sha1 $RESULT] eq \
168 {962f96ebd613e4fdd9aa2d20bd9fe21a64e925f2}}
169
170 ###############################################################################
171
172 fossil unversioned cat unversioned3.txt
173 test unversioned-24 {[::sha1::sha1 $RESULT] eq \
174 {c6b95509120d9703cc4fbe5cdfcb435b5912b3e4}}
175
176 ###############################################################################
177
@@ -190,13 +201,10 @@
190 test unversioned-27 {$hash(before) eq \
191 {b48ba8e2d0b498321dfd13de84867effda399af5}}
192
193 ###############################################################################
194
195 set env(VISUAL) [appendArgs \
196 [info nameofexecutable] " " [file join $path fake-editor.tcl]]
197
198 fossil unversioned edit unversioned4.txt
199 test unversioned-28 {[normalize_result] eq {}}
200
201 ###############################################################################
202
@@ -295,14 +303,155 @@
295 {^[0-9a-f]{12} 2016-10-01 00:00:00 30 30 unversioned2\.txt
296 [0-9a-f]{12} \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} 28 28\
297 unversioned5\.txt$} [normalize_result]]}
298
299 ###############################################################################
300 #
301 # TODO: Add tests for the unversioned "revert" and "sync" sub-commands.
302 #
303 # revert --verbose --dryrun
304 # sync
305 #
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
306 ###############################################################################
307
308 test_cleanup
309
--- test/unversioned.test
+++ test/unversioned.test
@@ -26,17 +26,28 @@
26 }
27
28 require_no_open_checkout
29
30 test_setup; set rootDir [file normalize [pwd]]
31
32 fossil test-th-eval --open-config {repository}
33 set repository [normalize_result]
34
35 if {[string length $repository] == 0} {
36 puts "Detection of the open repository file failed."
37 test_cleanup_then_return
38 }
39
40 write_file unversioned1.txt "This is unversioned file #1."
41 write_file unversioned2.txt " This is unversioned file #2. "
42 write_file "unversioned space.txt" "\nThis is unversioned file #3.\n"
43 write_file unversioned4.txt "This is unversioned file #4."
44 write_file unversioned5.txt "This is unversioned file #5."
45
46 set env(VISUAL) [appendArgs \
47 [info nameofexecutable] " " [file join $path fake-editor.tcl]]
48
49 ###############################################################################
50
51 fossil unversioned
52 test unversioned-1 {[normalize_result] eq \
53 [string map [list %fossil% [file nativename $fossilexe]] {Usage: %fossil%\
@@ -167,11 +178,11 @@
178 test unversioned-23 {[::sha1::sha1 $RESULT] eq \
179 {962f96ebd613e4fdd9aa2d20bd9fe21a64e925f2}}
180
181 ###############################################################################
182
183 fossil unversioned cat unversioned3.txt -keepNewline
184 test unversioned-24 {[::sha1::sha1 $RESULT] eq \
185 {c6b95509120d9703cc4fbe5cdfcb435b5912b3e4}}
186
187 ###############################################################################
188
@@ -190,13 +201,10 @@
201 test unversioned-27 {$hash(before) eq \
202 {b48ba8e2d0b498321dfd13de84867effda399af5}}
203
204 ###############################################################################
205
 
 
 
206 fossil unversioned edit unversioned4.txt
207 test unversioned-28 {[normalize_result] eq {}}
208
209 ###############################################################################
210
@@ -295,14 +303,155 @@
303 {^[0-9a-f]{12} 2016-10-01 00:00:00 30 30 unversioned2\.txt
304 [0-9a-f]{12} \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} 28 28\
305 unversioned5\.txt$} [normalize_result]]}
306
307 ###############################################################################
308
309 set password [string trim [clock seconds] -]
310
311 fossil user new uvtester "Unversioned Test User" $password
312 fossil user capabilities uvtester oy
313
314 ###############################################################################
315
316 foreach {pid port outTmpFile} [test_start_server $repository stopArg] {}
317 puts [appendArgs "Started Fossil server, pid \"" $pid \" ", port \"" $port \".]
318 set remote [appendArgs http://uvtester: $password @localhost: $port /]
319
320 ###############################################################################
321
322 set clientDir [file join $tempPath [appendArgs \
323 uvtest_ [string trim [clock seconds] -] _ [getSeqNo]]]
324
325 set savedPwd [pwd]
326 file mkdir $clientDir; cd $clientDir
327 puts [appendArgs "Now in client directory \"" [pwd] \".]
328 write_file unversioned-client1.txt "This is unversioned client file #1."
329
330 ###############################################################################
331
332 fossil_maybe_answer y clone $remote uvrepo.fossil
333 fossil open uvrepo.fossil
334
335 ###############################################################################
336
337 fossil unversioned list
338 test unversioned-45 {[normalize_result] eq {}}
339
340 ###############################################################################
341
342 fossil_maybe_answer y unversioned sync $remote
343 test unversioned-46 {[regexp \
344 {Round-trips: 1 Artifacts sent: 0 received: 0
345 Round-trips: 1 Artifacts sent: 0 received: 0
346 Round-trips: 2 Artifacts sent: 0 received: 0
347 Round-trips: 2 Artifacts sent: 0 received: 2
348 \n? done, sent: \d+ received: \d+ ip: 127.0.0.1} [normalize_result]]}
349
350 ###############################################################################
351
352 fossil unversioned ls
353 test unversioned-47 {[normalize_result] eq {unversioned2.txt
354 unversioned5.txt}}
355
356 ###############################################################################
357
358 set env(FAKE_EDITOR_SCRIPT) "append data this_is_a_test"; # deterministic
359
360 fossil unversioned edit unversioned2.txt
361 test unversioned-48 {[normalize_result] eq {}}
362
363 unset env(FAKE_EDITOR_SCRIPT)
364
365 ###############################################################################
366
367 fossil unversioned cat unversioned2.txt
368 test unversioned-49 {[::sha1::sha1 $RESULT] eq \
369 {e15d4b576fc04e3bb5e44a33d44d104dd5b19428}}
370
371 ###############################################################################
372
373 fossil unversioned remove unversioned5.txt
374 test unversioned-50 {[normalize_result] eq {}}
375
376 ###############################################################################
377
378 fossil unversioned list --all
379 test unversioned-51 {[regexp \
380 {^[0-9a-f]{12} \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} 44 44\
381 unversioned2\.txt
382 \(deleted\) \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} 0 0\
383 unversioned5\.txt$} [normalize_result]]}
384
385 ###############################################################################
386
387 fossil_maybe_answer y unversioned revert $remote
388 test unversioned-52 {[regexp \
389 {Round-trips: 1 Artifacts sent: 0 received: 0
390 Round-trips: 1 Artifacts sent: 0 received: 0
391 Round-trips: 2 Artifacts sent: 0 received: 0
392 Round-trips: 2 Artifacts sent: 0 received: 2
393 \n? done, sent: \d+ received: \d+ ip: 127.0.0.1} [normalize_result]]}
394
395 ###############################################################################
396
397 fossil unversioned list
398 test unversioned-53 {[regexp \
399 {^[0-9a-f]{12} 2016-10-01 00:00:00 30 30\
400 unversioned2\.txt
401 [0-9a-f]{12} \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} 28 28\
402 unversioned5\.txt$} [normalize_result]]}
403
404 ###############################################################################
405
406 fossil unversioned add unversioned-client1.txt
407 test unversioned-54 {[normalize_result] eq {}}
408
409 ###############################################################################
410
411 fossil_maybe_answer y unversioned sync $remote
412 test unversioned-55 {[regexp \
413 {Round-trips: 1 Artifacts sent: 0 received: 0
414 Round-trips: 1 Artifacts sent: 0 received: 0
415 Round-trips: 2 Artifacts sent: 1 received: 0
416 Round-trips: 2 Artifacts sent: 1 received: 0
417 \n? done, sent: \d+ received: \d+ ip: 127.0.0.1} [normalize_result]]}
418
419 ###############################################################################
420
421 fossil close
422 test unversioned-56 {[normalize_result] eq {}}
423
424 ###############################################################################
425
426 cd $savedPwd; unset savedPwd
427 file delete -force $clientDir
428 puts [appendArgs "Now in server directory \"" [pwd] \".]
429
430 ###############################################################################
431
432 set stopped [test_stop_server $stopArg $pid $outTmpFile]
433
434 puts [appendArgs \
435 [expr {$stopped ? "Stopped" : "Could not stop"}] \
436 " Fossil server, pid \"" $pid "\", using argument \"" \
437 $stopArg \".]
438
439 ###############################################################################
440
441 fossil unversioned list
442 test unversioned-57 {[regexp \
443 {^[0-9a-f]{12} \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} 35 35\
444 unversioned-client1\.txt
445 [0-9a-f]{12} 2016-10-01 00:00:00 30 30 unversioned2\.txt
446 [0-9a-f]{12} \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} 28 28\
447 unversioned5\.txt$} [normalize_result]]}
448
449 ###############################################################################
450
451 fossil unversioned cat unversioned-client1.txt
452 test unversioned-58 {[::sha1::sha1 $RESULT] eq \
453 {a34606f714afe309bb531fba6051eaf25201e8a2}}
454
455 ###############################################################################
456
457 test_cleanup
458
+12 -8
--- www/th1.md
+++ www/th1.md
@@ -164,20 +164,20 @@
164164
* render
165165
* repository
166166
* searchable
167167
* setParameter
168168
* setting
169
+ * stime
169170
* styleHeader
170171
* styleFooter
171172
* tclEval
172173
* tclExpr
173174
* tclInvoke
174175
* tclIsSafe
175176
* tclMakeSafe
176177
* tclReady
177178
* trace
178
- * stime
179179
* utime
180180
* verifyCsrf
181181
* wiki
182182
183183
Each of the commands above is documented by a block comment above their
@@ -249,11 +249,11 @@
249249
250250
Renders STRING as wiki content; however, only links are handled. No
251251
other markup is processed.
252252
253253
<a name="dir"></a>TH1 dir Command
--------------------------------------------
254
+---------------------------------
254255
255256
* dir CHECKIN ?GLOB? ?DETAILS?
256257
257258
Returns a list containing all files in CHECKIN. If GLOB is given only
258259
the files matching the pattern GLOB within CHECKIN will be returned.
@@ -400,11 +400,11 @@
400400
401401
Returns one more than the number of \n characters in STRING. But
402402
never returns less than MIN or more than MAX.
403403
404404
<a name="markdown"></a>TH1 markdown Command
----------------------------------------------
405
+-------------------------------------------
405406
406407
* markdown STRING
407408
408409
Renders the input string as markdown. The result is a two-element list.
409410
The first element contains the body, rendered as HTML. The second element
@@ -517,10 +517,18 @@
517517
-----------------------------------------
518518
519519
* setting name
520520
521521
Gets and returns the value of the specified setting.
522
+
523
+<a name="stime"></a>TH1 stime Command
524
+-------------------------------------
525
+
526
+ * stime
527
+
528
+Returns the number of microseconds of CPU time consumed by the current
529
+process in system space.
522530
523531
<a name="styleHeader"></a>TH1 styleHeader Command
524532
-------------------------------------------------
525533
526534
* styleHeader TITLE
@@ -577,11 +585,11 @@
577585
578586
Returns non-zero if the Tcl interpreter is "safe". The Tcl interpreter
579587
will be created automatically if it has not been already.
580588
581589
<a name="tclMakeSafe"></a>TH1 tclMakeSafe Command
----------------------------------------------
590
+-------------------------------------------------
582591
583592
**This command requires the Tcl integration feature.**
584593
585594
* tclMakeSafe
586595
@@ -603,18 +611,10 @@
603611
604612
* trace STRING
605613
606614
Generates a TH1 trace message if TH1 tracing is enabled.
607615
608
-<a name="stime"></a>TH1 stime Command
--------------------------------------
609
-
610
- * stime
611
-
612
-Returns the number of microseconds of CPU time consumed by the current
613
-process in system space.
614
-
615616
<a name="utime"></a>TH1 utime Command
616617
-------------------------------------
617618
618619
* utime
619620
620621
--- www/th1.md
+++ www/th1.md
@@ -164,20 +164,20 @@
164 * render
165 * repository
166 * searchable
167 * setParameter
168 * setting
 
169 * styleHeader
170 * styleFooter
171 * tclEval
172 * tclExpr
173 * tclInvoke
174 * tclIsSafe
175 * tclMakeSafe
176 * tclReady
177 * trace
178 * stime
179 * utime
180 * verifyCsrf
181 * wiki
182
183 Each of the commands above is documented by a block comment above their
@@ -249,11 +249,11 @@
249
250 Renders STRING as wiki content; however, only links are handled. No
251 other markup is processed.
252
253 <a name="dir"></a>TH1 dir Command
--------------------------------------------
 
254
255 * dir CHECKIN ?GLOB? ?DETAILS?
256
257 Returns a list containing all files in CHECKIN. If GLOB is given only
258 the files matching the pattern GLOB within CHECKIN will be returned.
@@ -400,11 +400,11 @@
400
401 Returns one more than the number of \n characters in STRING. But
402 never returns less than MIN or more than MAX.
403
404 <a name="markdown"></a>TH1 markdown Command
----------------------------------------------
 
405
406 * markdown STRING
407
408 Renders the input string as markdown. The result is a two-element list.
409 The first element contains the body, rendered as HTML. The second element
@@ -517,10 +517,18 @@
517 -----------------------------------------
518
519 * setting name
520
521 Gets and returns the value of the specified setting.
 
 
 
 
 
 
 
 
522
523 <a name="styleHeader"></a>TH1 styleHeader Command
524 -------------------------------------------------
525
526 * styleHeader TITLE
@@ -577,11 +585,11 @@
577
578 Returns non-zero if the Tcl interpreter is "safe". The Tcl interpreter
579 will be created automatically if it has not been already.
580
581 <a name="tclMakeSafe"></a>TH1 tclMakeSafe Command
----------------------------------------------
 
582
583 **This command requires the Tcl integration feature.**
584
585 * tclMakeSafe
586
@@ -603,18 +611,10 @@
603
604 * trace STRING
605
606 Generates a TH1 trace message if TH1 tracing is enabled.
607
608 <a name="stime"></a>TH1 stime Command
--------------------------------------
609
610 * stime
611
612 Returns the number of microseconds of CPU time consumed by the current
613 process in system space.
614
615 <a name="utime"></a>TH1 utime Command
616 -------------------------------------
617
618 * utime
619
620
--- www/th1.md
+++ www/th1.md
@@ -164,20 +164,20 @@
164 * render
165 * repository
166 * searchable
167 * setParameter
168 * setting
169 * stime
170 * styleHeader
171 * styleFooter
172 * tclEval
173 * tclExpr
174 * tclInvoke
175 * tclIsSafe
176 * tclMakeSafe
177 * tclReady
178 * trace
 
179 * utime
180 * verifyCsrf
181 * wiki
182
183 Each of the commands above is documented by a block comment above their
@@ -249,11 +249,11 @@
249
250 Renders STRING as wiki content; however, only links are handled. No
251 other markup is processed.
252
253 <a name="dir"></a>TH1 dir Command
--------------------------------------------
254 ---------------------------------
255
256 * dir CHECKIN ?GLOB? ?DETAILS?
257
258 Returns a list containing all files in CHECKIN. If GLOB is given only
259 the files matching the pattern GLOB within CHECKIN will be returned.
@@ -400,11 +400,11 @@
400
401 Returns one more than the number of \n characters in STRING. But
402 never returns less than MIN or more than MAX.
403
404 <a name="markdown"></a>TH1 markdown Command
----------------------------------------------
405 -------------------------------------------
406
407 * markdown STRING
408
409 Renders the input string as markdown. The result is a two-element list.
410 The first element contains the body, rendered as HTML. The second element
@@ -517,10 +517,18 @@
517 -----------------------------------------
518
519 * setting name
520
521 Gets and returns the value of the specified setting.
522
523 <a name="stime"></a>TH1 stime Command
524 -------------------------------------
525
526 * stime
527
528 Returns the number of microseconds of CPU time consumed by the current
529 process in system space.
530
531 <a name="styleHeader"></a>TH1 styleHeader Command
532 -------------------------------------------------
533
534 * styleHeader TITLE
@@ -577,11 +585,11 @@
585
586 Returns non-zero if the Tcl interpreter is "safe". The Tcl interpreter
587 will be created automatically if it has not been already.
588
589 <a name="tclMakeSafe"></a>TH1 tclMakeSafe Command
----------------------------------------------
590 -------------------------------------------------
591
592 **This command requires the Tcl integration feature.**
593
594 * tclMakeSafe
595
@@ -603,18 +611,10 @@
611
612 * trace STRING
613
614 Generates a TH1 trace message if TH1 tracing is enabled.
615
 
--------------------------------------
 
 
 
 
 
 
616 <a name="utime"></a>TH1 utime Command
617 -------------------------------------
618
619 * utime
620
621
+1 -2
--- www/webui.wiki
+++ www/webui.wiki
@@ -25,12 +25,11 @@
2525
There are no extra programs to install or setup.
2626
Everything you need is already pre-configured and built into the
2727
self-contained, stand-alone Fossil executable.
2828
2929
As an example of how useful this web interface can be,
30
-the entire [./index.wiki | Fossil website] (except for the
31
-[http://www.fossil-scm.org/download.html | download page]),
30
+the entire [./index.wiki | Fossil website],
3231
including the document you are now reading,
3332
is rendered using the Fossil web interface, with no enhancements,
3433
and little customization.
3534
3635
<blockquote>
3736
--- www/webui.wiki
+++ www/webui.wiki
@@ -25,12 +25,11 @@
25 There are no extra programs to install or setup.
26 Everything you need is already pre-configured and built into the
27 self-contained, stand-alone Fossil executable.
28
29 As an example of how useful this web interface can be,
30 the entire [./index.wiki | Fossil website] (except for the
31 [http://www.fossil-scm.org/download.html | download page]),
32 including the document you are now reading,
33 is rendered using the Fossil web interface, with no enhancements,
34 and little customization.
35
36 <blockquote>
37
--- www/webui.wiki
+++ www/webui.wiki
@@ -25,12 +25,11 @@
25 There are no extra programs to install or setup.
26 Everything you need is already pre-configured and built into the
27 self-contained, stand-alone Fossil executable.
28
29 As an example of how useful this web interface can be,
30 the entire [./index.wiki | Fossil website],
 
31 including the document you are now reading,
32 is rendered using the Fossil web interface, with no enhancements,
33 and little customization.
34
35 <blockquote>
36

Keyboard Shortcuts

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