Fossil SCM
Merge updates from trunk.
Commit
5634375d0bb84cd9bb98d8bde013601b970dde36
Parent
43e122c763091c1…
17 files changed
+8
-9
+3
-3
+2
-1
+34
-25
+1
-1
+14
-16
+14
-16
+88
-15
+12
-3
+1
-1
+125
-18
+2
-2
+14
-4
+1
-1
+159
-10
+12
-8
+1
-2
M
src/db.c
+8
-9
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -2287,23 +2287,22 @@ | ||
| 2287 | 2287 | ** which letters can be used to represent flags (any permutation of flags must |
| 2288 | 2288 | ** not be able to fully form one of the boolean values). |
| 2289 | 2289 | */ |
| 2290 | 2290 | int db_get_manifest_setting(void){ |
| 2291 | 2291 | 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) ){ | |
| 2295 | 2294 | return 0; |
| 2296 | - }else if( is_truth(zVal) ) { | |
| 2295 | + }else if( is_truth(zVal) ){ | |
| 2297 | 2296 | return MFESTFLG_RAW|MFESTFLG_UUID; |
| 2298 | 2297 | } |
| 2299 | 2298 | flg = 0; |
| 2300 | 2299 | 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; | |
| 2305 | 2304 | } |
| 2306 | 2305 | zVal++; |
| 2307 | 2306 | } |
| 2308 | 2307 | return flg; |
| 2309 | 2308 | } |
| @@ -2606,11 +2605,11 @@ | ||
| 2606 | 2605 | { "https-login", 0, 0, 0, 0, "off" }, |
| 2607 | 2606 | { "ignore-glob", 0, 40, 1, 0, "" }, |
| 2608 | 2607 | { "keep-glob", 0, 40, 1, 0, "" }, |
| 2609 | 2608 | { "localauth", 0, 0, 0, 0, "off" }, |
| 2610 | 2609 | { "main-branch", 0, 40, 0, 0, "trunk" }, |
| 2611 | - { "manifest", 0, 5, 0, 0, "off" }, | |
| 2610 | + { "manifest", 0, 5, 1, 0, "off" }, | |
| 2612 | 2611 | { "max-loadavg", 0, 25, 0, 0, "0.0" }, |
| 2613 | 2612 | { "max-upload", 0, 25, 0, 0, "250000" }, |
| 2614 | 2613 | { "mtime-changes", 0, 0, 0, 0, "on" }, |
| 2615 | 2614 | #if FOSSIL_ENABLE_LEGACY_MV_RM |
| 2616 | 2615 | { "mv-rm-files", 0, 0, 0, 0, "off" }, |
| 2617 | 2616 |
| --- 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 @@ | ||
| 29 | 29 | const char *zOrig, *zTarg; |
| 30 | 30 | int lenOrig, lenTarg; |
| 31 | 31 | int len; |
| 32 | 32 | char *zRes; |
| 33 | 33 | blob_zero(pDelta); |
| 34 | - zOrig = blob_buffer(pOriginal); | |
| 34 | + zOrig = blob_materialize(pOriginal); | |
| 35 | 35 | lenOrig = blob_size(pOriginal); |
| 36 | - zTarg = blob_buffer(pTarget); | |
| 36 | + zTarg = blob_materialize(pTarget); | |
| 37 | 37 | lenTarg = blob_size(pTarget); |
| 38 | 38 | blob_resize(pDelta, lenTarg+16); |
| 39 | - zRes = blob_buffer(pDelta); | |
| 39 | + zRes = blob_materialize(pDelta); | |
| 40 | 40 | len = delta_create(zOrig, lenOrig, zTarg, lenTarg, zRes); |
| 41 | 41 | blob_resize(pDelta, len); |
| 42 | 42 | return 0; |
| 43 | 43 | } |
| 44 | 44 | |
| 45 | 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_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 @@ | ||
| 207 | 207 | filler(buf, ".", NULL, 0); |
| 208 | 208 | filler(buf, "..", NULL, 0); |
| 209 | 209 | manifest_file_rewind(fusefs.pMan); |
| 210 | 210 | if( n==2 ){ |
| 211 | 211 | 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; | |
| 213 | 214 | zPrev = pFile->zName; |
| 214 | 215 | for(nPrev=0; zPrev[nPrev] && zPrev[nPrev]!='/'; nPrev++){} |
| 215 | 216 | z = mprintf("%.*s", nPrev, zPrev); |
| 216 | 217 | filler(buf, z, NULL, 0); |
| 217 | 218 | fossil_free(z); |
| 218 | 219 |
| --- 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 @@ | ||
| 381 | 381 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 382 | 382 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 383 | 383 | */ |
| 384 | 384 | #define SQLITE_VERSION "3.15.0" |
| 385 | 385 | #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" | |
| 387 | 387 | |
| 388 | 388 | /* |
| 389 | 389 | ** CAPI3REF: Run-Time Library Version Numbers |
| 390 | 390 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 391 | 391 | ** |
| @@ -44715,11 +44715,11 @@ | ||
| 44715 | 44715 | szBulk = pCache->szAlloc * (i64)pcache1.nInitPage; |
| 44716 | 44716 | }else{ |
| 44717 | 44717 | szBulk = -1024 * (i64)pcache1.nInitPage; |
| 44718 | 44718 | } |
| 44719 | 44719 | if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){ |
| 44720 | - szBulk = pCache->szAlloc*pCache->nMax; | |
| 44720 | + szBulk = pCache->szAlloc*(i64)pCache->nMax; | |
| 44721 | 44721 | } |
| 44722 | 44722 | zBulk = pCache->pBulk = sqlite3Malloc( szBulk ); |
| 44723 | 44723 | sqlite3EndBenignMalloc(); |
| 44724 | 44724 | if( zBulk ){ |
| 44725 | 44725 | int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc; |
| @@ -69336,11 +69336,11 @@ | ||
| 69336 | 69336 | switch( aff ){ |
| 69337 | 69337 | case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */ |
| 69338 | 69338 | if( (pMem->flags & MEM_Blob)==0 ){ |
| 69339 | 69339 | sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding); |
| 69340 | 69340 | assert( pMem->flags & MEM_Str || pMem->db->mallocFailed ); |
| 69341 | - MemSetTypeFlag(pMem, MEM_Blob); | |
| 69341 | + if( pMem->flags & MEM_Str ) MemSetTypeFlag(pMem, MEM_Blob); | |
| 69342 | 69342 | }else{ |
| 69343 | 69343 | pMem->flags &= ~(MEM_TypeMask&~MEM_Blob); |
| 69344 | 69344 | } |
| 69345 | 69345 | break; |
| 69346 | 69346 | } |
| @@ -88812,11 +88812,10 @@ | ||
| 88812 | 88812 | const char *zId; /* The function name. */ |
| 88813 | 88813 | FuncDef *pDef; /* Information about the function */ |
| 88814 | 88814 | u8 enc = ENC(pParse->db); /* The database encoding */ |
| 88815 | 88815 | |
| 88816 | 88816 | assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); |
| 88817 | -// notValid(pParse, pNC, "functions", NC_PartIdx); | |
| 88818 | 88817 | zId = pExpr->u.zToken; |
| 88819 | 88818 | nId = sqlite3Strlen30(zId); |
| 88820 | 88819 | pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0); |
| 88821 | 88820 | if( pDef==0 ){ |
| 88822 | 88821 | pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0); |
| @@ -124663,11 +124662,10 @@ | ||
| 124663 | 124662 | ** |
| 124664 | 124663 | ** * the comparison will be performed with no affinity, or |
| 124665 | 124664 | ** * the affinity change in zAff is guaranteed not to change the value. |
| 124666 | 124665 | */ |
| 124667 | 124666 | static void updateRangeAffinityStr( |
| 124668 | - Parse *pParse, /* Parse context */ | |
| 124669 | 124667 | Expr *pRight, /* RHS of comparison */ |
| 124670 | 124668 | int n, /* Number of vector elements in comparison */ |
| 124671 | 124669 | char *zAff /* Affinity string to modify */ |
| 124672 | 124670 | ){ |
| 124673 | 124671 | int i; |
| @@ -125749,15 +125747,15 @@ | ||
| 125749 | 125747 | assert( (bRev & ~1)==0 ); |
| 125750 | 125748 | pLevel->iLikeRepCntr <<=1; |
| 125751 | 125749 | pLevel->iLikeRepCntr |= bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC); |
| 125752 | 125750 | } |
| 125753 | 125751 | #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 | + } | |
| 125759 | 125757 | } |
| 125760 | 125758 | } |
| 125761 | 125759 | assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 ); |
| 125762 | 125760 | |
| 125763 | 125761 | /* If we are doing a reverse order scan on an ascending index, or |
| @@ -125803,11 +125801,11 @@ | ||
| 125803 | 125801 | ){ |
| 125804 | 125802 | sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); |
| 125805 | 125803 | VdbeCoverage(v); |
| 125806 | 125804 | } |
| 125807 | 125805 | if( zStartAff ){ |
| 125808 | - updateRangeAffinityStr(pParse, pRight, nBtm, &zStartAff[nEq]); | |
| 125806 | + updateRangeAffinityStr(pRight, nBtm, &zStartAff[nEq]); | |
| 125809 | 125807 | } |
| 125810 | 125808 | nConstraint += nBtm; |
| 125811 | 125809 | testcase( pRangeStart->wtFlags & TERM_VIRTUAL ); |
| 125812 | 125810 | if( sqlite3ExprIsVector(pRight)==0 ){ |
| 125813 | 125811 | disableTerm(pLevel, pRangeStart); |
| @@ -125853,11 +125851,11 @@ | ||
| 125853 | 125851 | ){ |
| 125854 | 125852 | sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); |
| 125855 | 125853 | VdbeCoverage(v); |
| 125856 | 125854 | } |
| 125857 | 125855 | if( zEndAff ){ |
| 125858 | - updateRangeAffinityStr(pParse, pRight, nTop, zEndAff); | |
| 125856 | + updateRangeAffinityStr(pRight, nTop, zEndAff); | |
| 125859 | 125857 | codeApplyAffinity(pParse, regBase+nEq, nTop, zEndAff); |
| 125860 | 125858 | }else{ |
| 125861 | 125859 | assert( pParse->db->mallocFailed ); |
| 125862 | 125860 | } |
| 125863 | 125861 | nConstraint += nTop; |
| @@ -130005,11 +130003,11 @@ | ||
| 130005 | 130003 | ** CREATE INDEX ... ON (a, b, c, d, e) |
| 130006 | 130004 | ** |
| 130007 | 130005 | ** then this function would be invoked with nEq=1. The value returned in |
| 130008 | 130006 | ** this case is 3. |
| 130009 | 130007 | */ |
| 130010 | -int whereRangeVectorLen( | |
| 130008 | +static int whereRangeVectorLen( | |
| 130011 | 130009 | Parse *pParse, /* Parsing context */ |
| 130012 | 130010 | int iCur, /* Cursor open on pIdx */ |
| 130013 | 130011 | Index *pIdx, /* The index to be used for a inequality constraint */ |
| 130014 | 130012 | int nEq, /* Number of prior equality constraints on same index */ |
| 130015 | 130013 | WhereTerm *pTerm /* The vector inequality constraint */ |
| @@ -131451,11 +131449,11 @@ | ||
| 131451 | 131449 | if( rev ) *pRevMask |= MASKBIT(iLoop); |
| 131452 | 131450 | revSet = 1; |
| 131453 | 131451 | } |
| 131454 | 131452 | } |
| 131455 | 131453 | if( isMatch ){ |
| 131456 | - if( iColumn<0 ){ | |
| 131454 | + if( iColumn==XN_ROWID ){ | |
| 131457 | 131455 | testcase( distinctColumns==0 ); |
| 131458 | 131456 | distinctColumns = 1; |
| 131459 | 131457 | } |
| 131460 | 131458 | obSat |= MASKBIT(i); |
| 131461 | 131459 | }else{ |
| @@ -131906,17 +131904,24 @@ | ||
| 131906 | 131904 | }else{ |
| 131907 | 131905 | pWInfo->nOBSat = pFrom->isOrdered; |
| 131908 | 131906 | pWInfo->revMask = pFrom->revLoop; |
| 131909 | 131907 | if( pWInfo->nOBSat<=0 ){ |
| 131910 | 131908 | 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, | |
| 131914 | 131916 | 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 | + } | |
| 131918 | 131923 | } |
| 131919 | 131924 | } |
| 131920 | 131925 | } |
| 131921 | 131926 | } |
| 131922 | 131927 | if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP) |
| @@ -164296,14 +164301,16 @@ | ||
| 164296 | 164301 | char *zSql; |
| 164297 | 164302 | sqlite3_stmt *p; |
| 164298 | 164303 | int rc; |
| 164299 | 164304 | i64 nRow = 0; |
| 164300 | 164305 | |
| 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 ){ | |
| 164303 | 164310 | pRtree->nRowEst = RTREE_DEFAULT_ROWEST; |
| 164304 | - return SQLITE_OK; | |
| 164311 | + return rc==SQLITE_ERROR ? SQLITE_OK : rc; | |
| 164305 | 164312 | } |
| 164306 | 164313 | zSql = sqlite3_mprintf(zFmt, pRtree->zDb, pRtree->zName); |
| 164307 | 164314 | if( zSql==0 ){ |
| 164308 | 164315 | rc = SQLITE_NOMEM; |
| 164309 | 164316 | }else{ |
| @@ -181496,10 +181503,13 @@ | ||
| 181496 | 181503 | int nToken, /* Size of token in bytes */ |
| 181497 | 181504 | int iStartOff, /* Start offset of token */ |
| 181498 | 181505 | int iEndOff /* End offset of token */ |
| 181499 | 181506 | ){ |
| 181500 | 181507 | int rc = SQLITE_OK; |
| 181508 | + | |
| 181509 | + UNUSED_PARAM2(pToken, nToken); | |
| 181510 | + UNUSED_PARAM(iEndOff); | |
| 181501 | 181511 | |
| 181502 | 181512 | if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){ |
| 181503 | 181513 | Fts5SFinder *p = (Fts5SFinder*)pContext; |
| 181504 | 181514 | if( p->iPos>0 ){ |
| 181505 | 181515 | int i; |
| @@ -181652,11 +181662,10 @@ | ||
| 181652 | 181662 | for(jj=0; jj<(sFinder.nFirst-1); jj++){ |
| 181653 | 181663 | if( sFinder.aFirst[jj+1]>io ) break; |
| 181654 | 181664 | } |
| 181655 | 181665 | |
| 181656 | 181666 | if( sFinder.aFirst[jj]<io ){ |
| 181657 | - int nScore; | |
| 181658 | 181667 | memset(aSeen, 0, nPhrase); |
| 181659 | 181668 | rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i, |
| 181660 | 181669 | sFinder.aFirst[jj], nToken, &nScore, 0 |
| 181661 | 181670 | ); |
| 181662 | 181671 | |
| @@ -195587,11 +195596,11 @@ | ||
| 195587 | 195596 | int nArg, /* Number of args */ |
| 195588 | 195597 | sqlite3_value **apUnused /* Function arguments */ |
| 195589 | 195598 | ){ |
| 195590 | 195599 | assert( nArg==0 ); |
| 195591 | 195600 | 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); | |
| 195593 | 195602 | } |
| 195594 | 195603 | |
| 195595 | 195604 | static int fts5Init(sqlite3 *db){ |
| 195596 | 195605 | static const sqlite3_module fts5Mod = { |
| 195597 | 195606 | /* iVersion */ 2, |
| 195598 | 195607 |
| --- 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 @@ | ||
| 121 | 121 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 122 | 122 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 123 | 123 | */ |
| 124 | 124 | #define SQLITE_VERSION "3.15.0" |
| 125 | 125 | #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" | |
| 127 | 127 | |
| 128 | 128 | /* |
| 129 | 129 | ** CAPI3REF: Run-Time Library Version Numbers |
| 130 | 130 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 131 | 131 | ** |
| 132 | 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-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 @@ | ||
| 25 | 25 | ** SQL code to implement the tables needed by the stash. |
| 26 | 26 | */ |
| 27 | 27 | static const char zStashInit[] = |
| 28 | 28 | @ CREATE TABLE IF NOT EXISTS localdb.stash( |
| 29 | 29 | @ 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 | |
| 31 | 31 | @ comment TEXT, -- Comment for this stash. Or NULL |
| 32 | 32 | @ ctime TIMESTAMP -- When the stash was created |
| 33 | 33 | @ ); |
| 34 | 34 | @ CREATE TABLE IF NOT EXISTS localdb.stashfile( |
| 35 | 35 | @ stashid INTEGER REFERENCES stash, -- Stash that contains this file |
| @@ -196,11 +196,11 @@ | ||
| 196 | 196 | } |
| 197 | 197 | return stashid; |
| 198 | 198 | } |
| 199 | 199 | |
| 200 | 200 | /* |
| 201 | -** Apply a stash to the current check-out. | |
| 201 | +** Apply a stash to the current checkout. | |
| 202 | 202 | */ |
| 203 | 203 | static void stash_apply(int stashid, int nConflict){ |
| 204 | 204 | int vid; |
| 205 | 205 | Stmt q; |
| 206 | 206 | db_prepare(&q, |
| @@ -425,60 +425,58 @@ | ||
| 425 | 425 | ** Save the current changes in the working tree as a new stash. |
| 426 | 426 | ** Then revert the changes back to the last check-in. If FILES |
| 427 | 427 | ** are listed, then only stash and revert the named files. The |
| 428 | 428 | ** "save" verb can be omitted if and only if there are no other |
| 429 | 429 | ** 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. | |
| 431 | 431 | ** |
| 432 | -** fossil stash list ?-v|--verbose? | |
| 433 | -** fossil stash ls ?-v|--verbose? | |
| 432 | +** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>? | |
| 434 | 433 | ** |
| 435 | 434 | ** List all changes sets currently stashed. Show information about |
| 436 | 435 | ** individual files in each changeset if -v or --verbose is used. |
| 437 | 436 | ** |
| 438 | 437 | ** fossil stash show|cat ?STASHID? ?DIFF-FLAGS? |
| 439 | 438 | ** |
| 440 | -** Show the content of a stash | |
| 439 | +** Show the contents of a stash. | |
| 441 | 440 | ** |
| 442 | 441 | ** fossil stash pop |
| 443 | 442 | ** fossil stash apply ?STASHID? |
| 444 | 443 | ** |
| 445 | 444 | ** 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 | |
| 447 | 446 | ** the stash after applying it but the "apply" command retains the |
| 448 | 447 | ** changeset. |
| 449 | 448 | ** |
| 450 | 449 | ** fossil stash goto ?STASHID? |
| 451 | 450 | ** |
| 452 | 451 | ** Update to the baseline checkout for STASHID then apply the |
| 453 | 452 | ** changes of STASHID. Keep STASHID so that it can be reused |
| 454 | 453 | ** This command is undoable. |
| 455 | 454 | ** |
| 456 | -** fossil stash drop ?STASHID? ?-a|--all? | |
| 457 | -** fossil stash rm ?STASHID? ?-a|--all? | |
| 455 | +** fossil stash drop|rm ?STASHID? ?-a|--all? | |
| 458 | 456 | ** |
| 459 | 457 | ** Forget everything about STASHID. Forget the whole stash if the |
| 460 | 458 | ** -a|--all flag is used. Individual drops are undoable but -a|--all |
| 461 | 459 | ** is not. |
| 462 | 460 | ** |
| 463 | -** fossil stash diff ?STASHID? | |
| 464 | -** fossil stash gdiff ?STASHID? | |
| 461 | +** fossil stash diff ?STASHID? ?DIFF-OPTIONS? | |
| 462 | +** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS? | |
| 465 | 463 | ** |
| 466 | 464 | ** Show diffs of the current working directory and what that |
| 467 | 465 | ** directory would be if STASHID were applied. |
| 468 | 466 | ** |
| 469 | 467 | ** SUMMARY: |
| 470 | 468 | ** fossil stash |
| 471 | 469 | ** fossil stash save ?-m|--comment COMMENT? ?FILES...? |
| 472 | 470 | ** 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>? | |
| 474 | 472 | ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS? |
| 475 | 473 | ** 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? | |
| 480 | 478 | */ |
| 481 | 479 | void stash_cmd(void){ |
| 482 | 480 | const char *zCmd; |
| 483 | 481 | int nCmd; |
| 484 | 482 | int stashid = 0; |
| 485 | 483 |
| --- 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 @@ | ||
| 25 | 25 | ** SQL code to implement the tables needed by the stash. |
| 26 | 26 | */ |
| 27 | 27 | static const char zStashInit[] = |
| 28 | 28 | @ CREATE TABLE IF NOT EXISTS localdb.stash( |
| 29 | 29 | @ 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 | |
| 31 | 31 | @ comment TEXT, -- Comment for this stash. Or NULL |
| 32 | 32 | @ ctime TIMESTAMP -- When the stash was created |
| 33 | 33 | @ ); |
| 34 | 34 | @ CREATE TABLE IF NOT EXISTS localdb.stashfile( |
| 35 | 35 | @ stashid INTEGER REFERENCES stash, -- Stash that contains this file |
| @@ -196,11 +196,11 @@ | ||
| 196 | 196 | } |
| 197 | 197 | return stashid; |
| 198 | 198 | } |
| 199 | 199 | |
| 200 | 200 | /* |
| 201 | -** Apply a stash to the current check-out. | |
| 201 | +** Apply a stash to the current checkout. | |
| 202 | 202 | */ |
| 203 | 203 | static void stash_apply(int stashid, int nConflict){ |
| 204 | 204 | int vid; |
| 205 | 205 | Stmt q; |
| 206 | 206 | db_prepare(&q, |
| @@ -425,60 +425,58 @@ | ||
| 425 | 425 | ** Save the current changes in the working tree as a new stash. |
| 426 | 426 | ** Then revert the changes back to the last check-in. If FILES |
| 427 | 427 | ** are listed, then only stash and revert the named files. The |
| 428 | 428 | ** "save" verb can be omitted if and only if there are no other |
| 429 | 429 | ** 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. | |
| 431 | 431 | ** |
| 432 | -** fossil stash list ?-v|--verbose? | |
| 433 | -** fossil stash ls ?-v|--verbose? | |
| 432 | +** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>? | |
| 434 | 433 | ** |
| 435 | 434 | ** List all changes sets currently stashed. Show information about |
| 436 | 435 | ** individual files in each changeset if -v or --verbose is used. |
| 437 | 436 | ** |
| 438 | 437 | ** fossil stash show|cat ?STASHID? ?DIFF-FLAGS? |
| 439 | 438 | ** |
| 440 | -** Show the content of a stash | |
| 439 | +** Show the contents of a stash. | |
| 441 | 440 | ** |
| 442 | 441 | ** fossil stash pop |
| 443 | 442 | ** fossil stash apply ?STASHID? |
| 444 | 443 | ** |
| 445 | 444 | ** 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 | |
| 447 | 446 | ** the stash after applying it but the "apply" command retains the |
| 448 | 447 | ** changeset. |
| 449 | 448 | ** |
| 450 | 449 | ** fossil stash goto ?STASHID? |
| 451 | 450 | ** |
| 452 | 451 | ** Update to the baseline checkout for STASHID then apply the |
| 453 | 452 | ** changes of STASHID. Keep STASHID so that it can be reused |
| 454 | 453 | ** This command is undoable. |
| 455 | 454 | ** |
| 456 | -** fossil stash drop ?STASHID? ?-a|--all? | |
| 457 | -** fossil stash rm ?STASHID? ?-a|--all? | |
| 455 | +** fossil stash drop|rm ?STASHID? ?-a|--all? | |
| 458 | 456 | ** |
| 459 | 457 | ** Forget everything about STASHID. Forget the whole stash if the |
| 460 | 458 | ** -a|--all flag is used. Individual drops are undoable but -a|--all |
| 461 | 459 | ** is not. |
| 462 | 460 | ** |
| 463 | -** fossil stash diff ?STASHID? | |
| 464 | -** fossil stash gdiff ?STASHID? | |
| 461 | +** fossil stash diff ?STASHID? ?DIFF-OPTIONS? | |
| 462 | +** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS? | |
| 465 | 463 | ** |
| 466 | 464 | ** Show diffs of the current working directory and what that |
| 467 | 465 | ** directory would be if STASHID were applied. |
| 468 | 466 | ** |
| 469 | 467 | ** SUMMARY: |
| 470 | 468 | ** fossil stash |
| 471 | 469 | ** fossil stash save ?-m|--comment COMMENT? ?FILES...? |
| 472 | 470 | ** 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>? | |
| 474 | 472 | ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS? |
| 475 | 473 | ** 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? | |
| 480 | 478 | */ |
| 481 | 479 | void stash_cmd(void){ |
| 482 | 480 | const char *zCmd; |
| 483 | 481 | int nCmd; |
| 484 | 482 | int stashid = 0; |
| 485 | 483 |
| --- 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 @@ | ||
| 24 | 24 | /* This code is for win32 only */ |
| 25 | 25 | #include <windows.h> |
| 26 | 26 | #include <process.h> |
| 27 | 27 | #include "winhttp.h" |
| 28 | 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 | + | |
| 29 | 43 | /* |
| 30 | 44 | ** The HttpRequest structure holds information about each incoming |
| 31 | 45 | ** HTTP request. |
| 32 | 46 | */ |
| 33 | 47 | typedef struct HttpRequest HttpRequest; |
| @@ -70,10 +84,51 @@ | ||
| 70 | 84 | const char *zService, |
| 71 | 85 | const char *zErr |
| 72 | 86 | ){ |
| 73 | 87 | fossil_fatal("unable to %s service '%s': %s", zOp, zService, zErr); |
| 74 | 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 | +} | |
| 75 | 130 | |
| 76 | 131 | /* |
| 77 | 132 | ** Process a single incoming HTTP request. |
| 78 | 133 | */ |
| 79 | 134 | static void win32_http_request(void *pAppData){ |
| @@ -163,11 +218,11 @@ | ||
| 163 | 218 | if( in ) fclose(in); |
| 164 | 219 | closesocket(p->s); |
| 165 | 220 | file_delete(zRequestFName); |
| 166 | 221 | file_delete(zReplyFName); |
| 167 | 222 | file_delete(zCmdFName); |
| 168 | - free(p); | |
| 223 | + fossil_free(p); | |
| 169 | 224 | } |
| 170 | 225 | |
| 171 | 226 | /* |
| 172 | 227 | ** Process a single incoming SCGI request. |
| 173 | 228 | */ |
| @@ -225,11 +280,11 @@ | ||
| 225 | 280 | if( out ) fclose(out); |
| 226 | 281 | if( in ) fclose(in); |
| 227 | 282 | closesocket(p->s); |
| 228 | 283 | file_delete(zRequestFName); |
| 229 | 284 | file_delete(zReplyFName); |
| 230 | - free(p); | |
| 285 | + fossil_free(p); | |
| 231 | 286 | } |
| 232 | 287 | |
| 233 | 288 | |
| 234 | 289 | /* |
| 235 | 290 | ** Start a listening socket and process incoming HTTP requests on |
| @@ -243,19 +298,19 @@ | ||
| 243 | 298 | const char *zNotFound, /* The --notfound option, or NULL */ |
| 244 | 299 | const char *zFileGlob, /* The --fileglob option, or NULL */ |
| 245 | 300 | const char *zIpAddr, /* Bind to this IP address, if not NULL */ |
| 246 | 301 | int flags /* One or more HTTP_SERVER_ flags */ |
| 247 | 302 | ){ |
| 303 | + HANDLE hStoppedEvent; | |
| 248 | 304 | WSADATA wd; |
| 249 | 305 | SOCKET s = INVALID_SOCKET; |
| 250 | 306 | SOCKADDR_IN addr; |
| 251 | 307 | int idCnt = 0; |
| 252 | 308 | int iPort = mnPort; |
| 253 | 309 | Blob options; |
| 254 | 310 | wchar_t zTmpPath[MAX_PATH]; |
| 255 | 311 | |
| 256 | - if( zStopper ) file_delete(zStopper); | |
| 257 | 312 | blob_zero(&options); |
| 258 | 313 | if( zBaseUrl ){ |
| 259 | 314 | blob_appendf(&options, " --baseurl %s", zBaseUrl); |
| 260 | 315 | } |
| 261 | 316 | if( zNotFound ){ |
| @@ -324,17 +379,35 @@ | ||
| 324 | 379 | zBrowser = mprintf(zBrowser /*works-like:"%d"*/, iPort); |
| 325 | 380 | fossil_print("Launch webbrowser: %s\n", zBrowser); |
| 326 | 381 | fossil_system(zBrowser); |
| 327 | 382 | } |
| 328 | 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 | + } | |
| 329 | 402 | /* Set the service status to running and pass the listener socket to the |
| 330 | 403 | ** service handling procedures. */ |
| 331 | 404 | win32_http_service_running(s); |
| 332 | 405 | for(;;){ |
| 333 | 406 | SOCKET client; |
| 334 | 407 | SOCKADDR_IN client_addr; |
| 335 | - HttpRequest *p; | |
| 408 | + HttpRequest *pRequest; | |
| 336 | 409 | int len = sizeof(client_addr); |
| 337 | 410 | int wsaError; |
| 338 | 411 | |
| 339 | 412 | client = accept(s, (struct sockaddr*)&client_addr, &len); |
| 340 | 413 | if( client==INVALID_SOCKET ){ |
| @@ -347,27 +420,27 @@ | ||
| 347 | 420 | }else{ |
| 348 | 421 | closesocket(s); |
| 349 | 422 | WSACleanup(); |
| 350 | 423 | fossil_fatal("error from accept()"); |
| 351 | 424 | } |
| 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); | |
| 361 | 432 | if( flags & HTTP_SERVER_SCGI ){ |
| 362 | - _beginthread(win32_scgi_request, 0, (void*)p); | |
| 433 | + _beginthread(win32_scgi_request, 0, (void*)pRequest); | |
| 363 | 434 | }else{ |
| 364 | - _beginthread(win32_http_request, 0, (void*)p); | |
| 435 | + _beginthread(win32_http_request, 0, (void*)pRequest); | |
| 365 | 436 | } |
| 366 | 437 | } |
| 367 | 438 | closesocket(s); |
| 368 | 439 | WSACleanup(); |
| 440 | + SetEvent(hStoppedEvent); | |
| 441 | + CloseHandle(hStoppedEvent); | |
| 369 | 442 | } |
| 370 | 443 | |
| 371 | 444 | /* |
| 372 | 445 | ** The HttpService structure is used to pass information to the service main |
| 373 | 446 | ** function and to the service control handler function. |
| 374 | 447 |
| --- 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 @@ | ||
| 34 | 34 | set f1 [read_file $f] |
| 35 | 35 | write_file t1 $f1 |
| 36 | 36 | for {set i 0} {$i<100} {incr i} { |
| 37 | 37 | write_file t2 [random_changes $f1 1 1 0 0.1] |
| 38 | 38 | fossil test-delta t1 t2 |
| 39 | - test delta-$base-$i-1 {$RESULT=="ok"} | |
| 39 | + test delta-$base-$i-1 {[normalize_result]=="ok"} | |
| 40 | 40 | write_file t2 [random_changes $f1 1 1 0 0.2] |
| 41 | 41 | fossil test-delta t1 t2 |
| 42 | - test delta-$base-$i-2 {$RESULT=="ok"} | |
| 42 | + test delta-$base-$i-2 {[normalize_result]=="ok"} | |
| 43 | 43 | write_file t2 [random_changes $f1 1 1 0 0.4] |
| 44 | 44 | fossil test-delta t1 t2 |
| 45 | - test delta-$base-$i-3 {$RESULT=="ok"} | |
| 45 | + test delta-$base-$i-3 {[normalize_result]=="ok"} | |
| 46 | 46 | } |
| 47 | 47 | } |
| 48 | 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 | +} | |
| 49 | 58 | ############################################################################### |
| 50 | 59 | |
| 51 | 60 | test_cleanup |
| 52 | 61 |
| --- 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 @@ | ||
| 23 | 23 | # practice of eliminating all trace of the fossil json command when |
| 24 | 24 | # not configured. If that changes, these conditions might not prevent |
| 25 | 25 | # the rest of this file from running. |
| 26 | 26 | fossil test-th-eval "hasfeature json" |
| 27 | 27 | |
| 28 | -if {$::RESULT ne "1"} then { | |
| 28 | +if {[normalize_result] ne "1"} then { | |
| 29 | 29 | puts "Fossil was not compiled with JSON support." |
| 30 | 30 | test_cleanup_then_return |
| 31 | 31 | } |
| 32 | 32 | |
| 33 | 33 | # We need a JSON parser to effectively test the JSON produced by |
| 34 | 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 {$::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 @@ | ||
| 136 | 136 | # |
| 137 | 137 | proc fossil_maybe_answer {answer args} { |
| 138 | 138 | global fossilexe |
| 139 | 139 | set cmd $fossilexe |
| 140 | 140 | set expectError 0 |
| 141 | - if {[lindex $args end] eq "-expectError"} { | |
| 141 | + set index [lsearch -exact $args -expectError] | |
| 142 | + if {$index != -1} { | |
| 142 | 143 | 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] | |
| 144 | 151 | } |
| 145 | 152 | foreach a $args { |
| 146 | 153 | lappend cmd $a |
| 147 | 154 | } |
| 148 | 155 | protOut $cmd |
| @@ -150,14 +157,22 @@ | ||
| 150 | 157 | flush stdout |
| 151 | 158 | if {[string length $answer] > 0} { |
| 152 | 159 | protOut $answer |
| 153 | 160 | set prompt_file [file join $::tempPath fossil_prompt_answer] |
| 154 | 161 | 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 | + } | |
| 156 | 167 | file delete $prompt_file |
| 157 | 168 | } 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 | + } | |
| 159 | 174 | } |
| 160 | 175 | global RESULT CODE |
| 161 | 176 | set CODE $rc |
| 162 | 177 | if {($rc && !$expectError) || (!$rc && $expectError)} { |
| 163 | 178 | protOut "ERROR: $result" 1 |
| @@ -210,11 +225,11 @@ | ||
| 210 | 225 | th1-setup \ |
| 211 | 226 | th1-uri-regexp] |
| 212 | 227 | |
| 213 | 228 | fossil test-th-eval "hasfeature tcl" |
| 214 | 229 | |
| 215 | - if {$::RESULT eq "1"} { | |
| 230 | + if {[normalize_result] eq "1"} { | |
| 216 | 231 | lappend result tcl-setup |
| 217 | 232 | } |
| 218 | 233 | |
| 219 | 234 | return [lsort -dictionary $result] |
| 220 | 235 | } |
| @@ -275,29 +290,29 @@ | ||
| 275 | 290 | uv-sync \ |
| 276 | 291 | web-browser] |
| 277 | 292 | |
| 278 | 293 | fossil test-th-eval "hasfeature legacyMvRm" |
| 279 | 294 | |
| 280 | - if {$::RESULT eq "1"} { | |
| 295 | + if {[normalize_result] eq "1"} { | |
| 281 | 296 | lappend result mv-rm-files |
| 282 | 297 | } |
| 283 | 298 | |
| 284 | 299 | fossil test-th-eval "hasfeature tcl" |
| 285 | 300 | |
| 286 | - if {$::RESULT eq "1"} { | |
| 301 | + if {[normalize_result] eq "1"} { | |
| 287 | 302 | lappend result tcl tcl-setup |
| 288 | 303 | } |
| 289 | 304 | |
| 290 | 305 | fossil test-th-eval "hasfeature th1Docs" |
| 291 | 306 | |
| 292 | - if {$::RESULT eq "1"} { | |
| 307 | + if {[normalize_result] eq "1"} { | |
| 293 | 308 | lappend result th1-docs |
| 294 | 309 | } |
| 295 | 310 | |
| 296 | 311 | fossil test-th-eval "hasfeature th1Hooks" |
| 297 | 312 | |
| 298 | - if {$::RESULT eq "1"} { | |
| 313 | + if {[normalize_result] eq "1"} { | |
| 299 | 314 | lappend result th1-hooks |
| 300 | 315 | } |
| 301 | 316 | |
| 302 | 317 | return [lsort -dictionary $result] |
| 303 | 318 | } |
| @@ -440,27 +455,27 @@ | ||
| 440 | 455 | |
| 441 | 456 | # This procedure only returns non-zero if the Tcl integration feature was |
| 442 | 457 | # enabled at compile-time and is now enabled at runtime. |
| 443 | 458 | proc is_tcl_usable_by_fossil {} { |
| 444 | 459 | fossil test-th-eval "hasfeature tcl" |
| 445 | - if {$::RESULT ne "1"} {return 0} | |
| 460 | + if {[normalize_result] ne "1"} {return 0} | |
| 446 | 461 | fossil test-th-eval "setting tcl" |
| 447 | - if {$::RESULT eq "1"} {return 1} | |
| 462 | + if {[normalize_result] eq "1"} {return 1} | |
| 448 | 463 | fossil test-th-eval --open-config "setting tcl" |
| 449 | - if {$::RESULT eq "1"} {return 1} | |
| 464 | + if {[normalize_result] eq "1"} {return 1} | |
| 450 | 465 | return [info exists ::env(TH1_ENABLE_TCL)] |
| 451 | 466 | } |
| 452 | 467 | |
| 453 | 468 | # This procedure only returns non-zero if the TH1 hooks feature was enabled |
| 454 | 469 | # at compile-time and is now enabled at runtime. |
| 455 | 470 | proc are_th1_hooks_usable_by_fossil {} { |
| 456 | 471 | fossil test-th-eval "hasfeature th1Hooks" |
| 457 | - if {$::RESULT ne "1"} {return 0} | |
| 472 | + if {[normalize_result] ne "1"} {return 0} | |
| 458 | 473 | fossil test-th-eval "setting th1-hooks" |
| 459 | - if {$::RESULT eq "1"} {return 1} | |
| 474 | + if {[normalize_result] eq "1"} {return 1} | |
| 460 | 475 | fossil test-th-eval --open-config "setting th1-hooks" |
| 461 | - if {$::RESULT eq "1"} {return 1} | |
| 476 | + if {[normalize_result] eq "1"} {return 1} | |
| 462 | 477 | return [info exists ::env(TH1_ENABLE_HOOKS)] |
| 463 | 478 | } |
| 464 | 479 | |
| 465 | 480 | # This (rarely used) procedure is designed to run a test within the Fossil |
| 466 | 481 | # source checkout (e.g. one that does NOT modify any state), while saving |
| @@ -560,14 +575,14 @@ | ||
| 560 | 575 | # NOTE: Check if we can use any of the environment variables. |
| 561 | 576 | # |
| 562 | 577 | foreach name $names { |
| 563 | 578 | set value [getEnvironmentVariable $name] |
| 564 | 579 | |
| 565 | - if {[string length $value] > 0} then { | |
| 580 | + if {[string length $value] > 0} { | |
| 566 | 581 | set value [file normalize $value] |
| 567 | 582 | |
| 568 | - if {[file exists $value] && [file isdirectory $value]} then { | |
| 583 | + if {[file exists $value] && [file isdirectory $value]} { | |
| 569 | 584 | return $value |
| 570 | 585 | } |
| 571 | 586 | } |
| 572 | 587 | } |
| 573 | 588 | |
| @@ -575,11 +590,11 @@ | ||
| 575 | 590 | # NOTE: On non-Windows systems, fallback to /tmp if it is usable. |
| 576 | 591 | # |
| 577 | 592 | if {$::tcl_platform(platform) ne "windows"} { |
| 578 | 593 | set value /tmp |
| 579 | 594 | |
| 580 | - if {[file exists $value] && [file isdirectory $value]} then { | |
| 595 | + if {[file exists $value] && [file isdirectory $value]} { | |
| 581 | 596 | return $value |
| 582 | 597 | } |
| 583 | 598 | } |
| 584 | 599 | |
| 585 | 600 | # |
| @@ -732,10 +747,102 @@ | ||
| 732 | 747 | } |
| 733 | 748 | append out \n$line |
| 734 | 749 | } |
| 735 | 750 | return [string range $out 1 end] |
| 736 | 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 | +} | |
| 737 | 844 | |
| 738 | 845 | # Executes the "fossil http" command. The entire content of the HTTP request |
| 739 | 846 | # is read from the data file name, with [subst] being performed on it prior to |
| 740 | 847 | # submission. Temporary input and output files are created and deleted. The |
| 741 | 848 | # result will be the contents of the temoprary output file. |
| 742 | 849 |
| --- 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 |
+2
-2
| --- test/th1-docs.test | ||
| +++ test/th1-docs.test | ||
| @@ -18,18 +18,18 @@ | ||
| 18 | 18 | # TH1 Docs |
| 19 | 19 | # |
| 20 | 20 | |
| 21 | 21 | fossil test-th-eval "hasfeature th1Docs" |
| 22 | 22 | |
| 23 | -if {$::RESULT ne "1"} { | |
| 23 | +if {[normalize_result] ne "1"} { | |
| 24 | 24 | puts "Fossil was not compiled with TH1 docs support." |
| 25 | 25 | test_cleanup_then_return |
| 26 | 26 | } |
| 27 | 27 | |
| 28 | 28 | fossil test-th-eval "hasfeature tcl" |
| 29 | 29 | |
| 30 | -if {$::RESULT ne "1"} { | |
| 30 | +if {[normalize_result] ne "1"} { | |
| 31 | 31 | puts "Fossil was not compiled with Tcl support." |
| 32 | 32 | test_cleanup_then_return |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | 35 | ############################################################################### |
| 36 | 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 {$::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 |
+14
-4
| --- test/th1-hooks.test | ||
| +++ test/th1-hooks.test | ||
| @@ -18,11 +18,11 @@ | ||
| 18 | 18 | # TH1 Hooks |
| 19 | 19 | # |
| 20 | 20 | |
| 21 | 21 | fossil test-th-eval "hasfeature th1Hooks" |
| 22 | 22 | |
| 23 | -if {$::RESULT ne "1"} { | |
| 23 | +if {[normalize_result] ne "1"} { | |
| 24 | 24 | puts "Fossil was not compiled with TH1 hooks support." |
| 25 | 25 | test_cleanup_then_return |
| 26 | 26 | } |
| 27 | 27 | |
| 28 | 28 | ############################################################################### |
| @@ -75,12 +75,17 @@ | ||
| 75 | 75 | return -code 2 "TH_RETURN return code" |
| 76 | 76 | } elseif {$::cmd_name eq "timeline"} { |
| 77 | 77 | set length [llength $::cmd_args] |
| 78 | 78 | set length [expr {$length - 1}] |
| 79 | 79 | if {[lindex $::cmd_args $length] eq "custom"} { |
| 80 | + append_hook_log "CUSTOM TIMELINE" | |
| 80 | 81 | emit_hook_log |
| 81 | 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" | |
| 82 | 87 | } elseif {[lindex $::cmd_args $length] eq "now"} { |
| 83 | 88 | emit_hook_log |
| 84 | 89 | return "now timeline" |
| 85 | 90 | } else { |
| 86 | 91 | emit_hook_log |
| @@ -122,15 +127,21 @@ | ||
| 122 | 127 | |
| 123 | 128 | saveTh1SetupFile; writeTh1SetupFile $testTh1Setup |
| 124 | 129 | |
| 125 | 130 | ############################################################################### |
| 126 | 131 | |
| 127 | -fossil timeline custom; # NOTE: Bad "WHEN" argument. | |
| 132 | +fossil timeline custom -expectError; # NOTE: Bad "WHEN" argument. | |
| 128 | 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 \ | |
| 129 | 141 | {<h1><b>command_hook timeline</b></h1> |
| 130 | -+++ no more data (0) +++ | |
| 131 | - | |
| ++++ some stuff here +++ | ||
| 132 | 142 | <h1><b>command_hook timeline command_notify timeline</b></h1>}} |
| 133 | 143 | |
| 134 | 144 | ############################################################################### |
| 135 | 145 | |
| 136 | 146 | fossil timeline |
| 137 | 147 |
| --- 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 |
+1
-1
| --- test/th1-tcl.test | ||
| +++ test/th1-tcl.test | ||
| @@ -22,11 +22,11 @@ | ||
| 22 | 22 | |
| 23 | 23 | ############################################################################### |
| 24 | 24 | |
| 25 | 25 | fossil test-th-eval "hasfeature tcl" |
| 26 | 26 | |
| 27 | -if {$::RESULT ne "1"} { | |
| 27 | +if {[normalize_result] ne "1"} { | |
| 28 | 28 | puts "Fossil was not compiled with Tcl support." |
| 29 | 29 | test_cleanup_then_return |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | 32 | ############################################################################### |
| 33 | 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 {$::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 |
+159
-10
| --- test/unversioned.test | ||
| +++ test/unversioned.test | ||
| @@ -26,17 +26,28 @@ | ||
| 26 | 26 | } |
| 27 | 27 | |
| 28 | 28 | require_no_open_checkout |
| 29 | 29 | |
| 30 | 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 | +} | |
| 31 | 39 | |
| 32 | 40 | write_file unversioned1.txt "This is unversioned file #1." |
| 33 | 41 | write_file unversioned2.txt " This is unversioned file #2. " |
| 34 | 42 | write_file "unversioned space.txt" "\nThis is unversioned file #3.\n" |
| 35 | 43 | write_file unversioned4.txt "This is unversioned file #4." |
| 36 | 44 | write_file unversioned5.txt "This is unversioned file #5." |
| 37 | 45 | |
| 46 | +set env(VISUAL) [appendArgs \ | |
| 47 | + [info nameofexecutable] " " [file join $path fake-editor.tcl]] | |
| 48 | + | |
| 38 | 49 | ############################################################################### |
| 39 | 50 | |
| 40 | 51 | fossil unversioned |
| 41 | 52 | test unversioned-1 {[normalize_result] eq \ |
| 42 | 53 | [string map [list %fossil% [file nativename $fossilexe]] {Usage: %fossil%\ |
| @@ -167,11 +178,11 @@ | ||
| 167 | 178 | test unversioned-23 {[::sha1::sha1 $RESULT] eq \ |
| 168 | 179 | {962f96ebd613e4fdd9aa2d20bd9fe21a64e925f2}} |
| 169 | 180 | |
| 170 | 181 | ############################################################################### |
| 171 | 182 | |
| 172 | -fossil unversioned cat unversioned3.txt | |
| 183 | +fossil unversioned cat unversioned3.txt -keepNewline | |
| 173 | 184 | test unversioned-24 {[::sha1::sha1 $RESULT] eq \ |
| 174 | 185 | {c6b95509120d9703cc4fbe5cdfcb435b5912b3e4}} |
| 175 | 186 | |
| 176 | 187 | ############################################################################### |
| 177 | 188 | |
| @@ -190,13 +201,10 @@ | ||
| 190 | 201 | test unversioned-27 {$hash(before) eq \ |
| 191 | 202 | {b48ba8e2d0b498321dfd13de84867effda399af5}} |
| 192 | 203 | |
| 193 | 204 | ############################################################################### |
| 194 | 205 | |
| 195 | -set env(VISUAL) [appendArgs \ | |
| 196 | - [info nameofexecutable] " " [file join $path fake-editor.tcl]] | |
| 197 | - | |
| 198 | 206 | fossil unversioned edit unversioned4.txt |
| 199 | 207 | test unversioned-28 {[normalize_result] eq {}} |
| 200 | 208 | |
| 201 | 209 | ############################################################################### |
| 202 | 210 | |
| @@ -295,14 +303,155 @@ | ||
| 295 | 303 | {^[0-9a-f]{12} 2016-10-01 00:00:00 30 30 unversioned2\.txt |
| 296 | 304 | [0-9a-f]{12} \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} 28 28\ |
| 297 | 305 | unversioned5\.txt$} [normalize_result]]} |
| 298 | 306 | |
| 299 | 307 | ############################################################################### |
| 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 | + | |
| 306 | 455 | ############################################################################### |
| 307 | 456 | |
| 308 | 457 | test_cleanup |
| 309 | 458 |
| --- 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 @@ | ||
| 164 | 164 | * render |
| 165 | 165 | * repository |
| 166 | 166 | * searchable |
| 167 | 167 | * setParameter |
| 168 | 168 | * setting |
| 169 | + * stime | |
| 169 | 170 | * styleHeader |
| 170 | 171 | * styleFooter |
| 171 | 172 | * tclEval |
| 172 | 173 | * tclExpr |
| 173 | 174 | * tclInvoke |
| 174 | 175 | * tclIsSafe |
| 175 | 176 | * tclMakeSafe |
| 176 | 177 | * tclReady |
| 177 | 178 | * trace |
| 178 | - * stime | |
| 179 | 179 | * utime |
| 180 | 180 | * verifyCsrf |
| 181 | 181 | * wiki |
| 182 | 182 | |
| 183 | 183 | Each of the commands above is documented by a block comment above their |
| @@ -249,11 +249,11 @@ | ||
| 249 | 249 | |
| 250 | 250 | Renders STRING as wiki content; however, only links are handled. No |
| 251 | 251 | other markup is processed. |
| 252 | 252 | |
| 253 | 253 | <a name="dir"></a>TH1 dir Command |
| -------------------------------------------- | ||
| 254 | +--------------------------------- | |
| 254 | 255 | |
| 255 | 256 | * dir CHECKIN ?GLOB? ?DETAILS? |
| 256 | 257 | |
| 257 | 258 | Returns a list containing all files in CHECKIN. If GLOB is given only |
| 258 | 259 | the files matching the pattern GLOB within CHECKIN will be returned. |
| @@ -400,11 +400,11 @@ | ||
| 400 | 400 | |
| 401 | 401 | Returns one more than the number of \n characters in STRING. But |
| 402 | 402 | never returns less than MIN or more than MAX. |
| 403 | 403 | |
| 404 | 404 | <a name="markdown"></a>TH1 markdown Command |
| ---------------------------------------------- | ||
| 405 | +------------------------------------------- | |
| 405 | 406 | |
| 406 | 407 | * markdown STRING |
| 407 | 408 | |
| 408 | 409 | Renders the input string as markdown. The result is a two-element list. |
| 409 | 410 | The first element contains the body, rendered as HTML. The second element |
| @@ -517,10 +517,18 @@ | ||
| 517 | 517 | ----------------------------------------- |
| 518 | 518 | |
| 519 | 519 | * setting name |
| 520 | 520 | |
| 521 | 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. | |
| 522 | 530 | |
| 523 | 531 | <a name="styleHeader"></a>TH1 styleHeader Command |
| 524 | 532 | ------------------------------------------------- |
| 525 | 533 | |
| 526 | 534 | * styleHeader TITLE |
| @@ -577,11 +585,11 @@ | ||
| 577 | 585 | |
| 578 | 586 | Returns non-zero if the Tcl interpreter is "safe". The Tcl interpreter |
| 579 | 587 | will be created automatically if it has not been already. |
| 580 | 588 | |
| 581 | 589 | <a name="tclMakeSafe"></a>TH1 tclMakeSafe Command |
| ---------------------------------------------- | ||
| 590 | +------------------------------------------------- | |
| 582 | 591 | |
| 583 | 592 | **This command requires the Tcl integration feature.** |
| 584 | 593 | |
| 585 | 594 | * tclMakeSafe |
| 586 | 595 | |
| @@ -603,18 +611,10 @@ | ||
| 603 | 611 | |
| 604 | 612 | * trace STRING |
| 605 | 613 | |
| 606 | 614 | Generates a TH1 trace message if TH1 tracing is enabled. |
| 607 | 615 | |
| 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 | 616 | <a name="utime"></a>TH1 utime Command |
| 616 | 617 | ------------------------------------- |
| 617 | 618 | |
| 618 | 619 | * utime |
| 619 | 620 | |
| 620 | 621 |
| --- 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 @@ | ||
| 25 | 25 | There are no extra programs to install or setup. |
| 26 | 26 | Everything you need is already pre-configured and built into the |
| 27 | 27 | self-contained, stand-alone Fossil executable. |
| 28 | 28 | |
| 29 | 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]), | |
| 30 | +the entire [./index.wiki | Fossil website], | |
| 32 | 31 | including the document you are now reading, |
| 33 | 32 | is rendered using the Fossil web interface, with no enhancements, |
| 34 | 33 | and little customization. |
| 35 | 34 | |
| 36 | 35 | <blockquote> |
| 37 | 36 |
| --- 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 |