Fossil SCM

Merge trunk

andygoth 2016-11-04 15:09 andygoth-timeline-ms merge
Commit 490daed204be9cd1d6b986e1ef93193e5d230db8
77 files changed +1 -1 +1 +1 -1 +17 -2 +3 +165 -14 +1 -2 +36 -17 +1 +90 -47 +2 -6 +19 -4 +5 -4 +79 -4 +1 -1 +1 -1 +1 -1 +24 -16 +174 -77 +24 -3 +1 +83 +3 -3 +3 -3 +10 -5 +5 -1 +33 -16 +57 +17 -2 +1 -1 +31 +3 +37 -1 +10 -10 +5 -5 +11 -11 +4 -4 +1 -1 +15 -2 +15 -2 +8 -8 +3 -3 +8 -8 +7 -7 +2 -2 +4 +1 -1 +9 -9 +9 -9 +1 -1 +3 -3 +5 -5 +26 -26 +19 -19 +2 -2 +11 -11 +1 -1 +54 -15 +13 -13 +2 -2 +1 -1 +5 -5 +3 -3 +10 -10 +26 -26 +13 -13 +12 -12 +3 -3 +6 -6 +20 -20 +3 -3 +10 -10 +3 -3 +6 -6 +19 +5 -5 +4 -4
+1 -1
--- Dockerfile
+++ Dockerfile
@@ -1,9 +1,9 @@
11
###
22
# Dockerfile for Fossil
33
###
4
-FROM fedora:23
4
+FROM fedora:24
55
66
### Now install some additional parts we will need for the build
77
RUN dnf update -y && dnf install -y gcc make zlib-devel openssl-devel tar && dnf clean all && groupadd -r fossil -g 433 && useradd -u 431 -r -g fossil -d /opt/fossil -s /sbin/nologin -c "Fossil user" fossil
88
99
### If you want to build "trunk", change the next line accordingly.
1010
--- Dockerfile
+++ Dockerfile
@@ -1,9 +1,9 @@
1 ###
2 # Dockerfile for Fossil
3 ###
4 FROM fedora:23
5
6 ### Now install some additional parts we will need for the build
7 RUN dnf update -y && dnf install -y gcc make zlib-devel openssl-devel tar && dnf clean all && groupadd -r fossil -g 433 && useradd -u 431 -r -g fossil -d /opt/fossil -s /sbin/nologin -c "Fossil user" fossil
8
9 ### If you want to build "trunk", change the next line accordingly.
10
--- Dockerfile
+++ Dockerfile
@@ -1,9 +1,9 @@
1 ###
2 # Dockerfile for Fossil
3 ###
4 FROM fedora:24
5
6 ### Now install some additional parts we will need for the build
7 RUN dnf update -y && dnf install -y gcc make zlib-devel openssl-devel tar && dnf clean all && groupadd -r fossil -g 433 && useradd -u 431 -r -g fossil -d /opt/fossil -s /sbin/nologin -c "Fossil user" fossil
8
9 ### If you want to build "trunk", change the next line accordingly.
10
+1
--- auto.def
+++ auto.def
@@ -479,10 +479,11 @@
479479
cc-check-function-in-lib sin m
480480
481481
# Check for the FuseFS library
482482
if {[opt-bool fusefs]} {
483483
if {[cc-check-function-in-lib fuse_mount fuse]} {
484
+ define-append EXTRA_CFLAGS -DFOSSIL_HAVE_FUSEFS
484485
define FOSSIL_HAVE_FUSEFS 1
485486
define-append LIBS -lfuse
486487
msg-result "FuseFS support enabled"
487488
}
488489
}
489490
--- auto.def
+++ auto.def
@@ -479,10 +479,11 @@
479 cc-check-function-in-lib sin m
480
481 # Check for the FuseFS library
482 if {[opt-bool fusefs]} {
483 if {[cc-check-function-in-lib fuse_mount fuse]} {
 
484 define FOSSIL_HAVE_FUSEFS 1
485 define-append LIBS -lfuse
486 msg-result "FuseFS support enabled"
487 }
488 }
489
--- auto.def
+++ auto.def
@@ -479,10 +479,11 @@
479 cc-check-function-in-lib sin m
480
481 # Check for the FuseFS library
482 if {[opt-bool fusefs]} {
483 if {[cc-check-function-in-lib fuse_mount fuse]} {
484 define-append EXTRA_CFLAGS -DFOSSIL_HAVE_FUSEFS
485 define FOSSIL_HAVE_FUSEFS 1
486 define-append LIBS -lfuse
487 msg-result "FuseFS support enabled"
488 }
489 }
490
+1 -1
--- src/allrepo.c
+++ src/allrepo.c
@@ -173,11 +173,10 @@
173173
int useCheckouts = 0;
174174
int quiet = 0;
175175
int dryRunFlag = 0;
176176
int showFile = find_option("showfile",0,0)!=0;
177177
int stopOnError = find_option("dontstop",0,0)==0;
178
- int rc;
179178
int nToDel = 0;
180179
int showLabel = 0;
181180
182181
dryRunFlag = find_option("dry-run","n",0)!=0;
183182
if( !dryRunFlag ){
@@ -378,10 +377,11 @@
378377
);
379378
}
380379
db_multi_exec("CREATE TEMP TABLE toDel(x TEXT)");
381380
db_prepare(&q, "SELECT name, tag FROM repolist ORDER BY 1");
382381
while( db_step(&q)==SQLITE_ROW ){
382
+ int rc;
383383
const char *zFilename = db_column_text(&q, 0);
384384
#if !USE_SEE
385385
if( sqlite3_strglob("*.efossil", zFilename)==0 ) continue;
386386
#endif
387387
if( file_access(zFilename, F_OK)
388388
--- src/allrepo.c
+++ src/allrepo.c
@@ -173,11 +173,10 @@
173 int useCheckouts = 0;
174 int quiet = 0;
175 int dryRunFlag = 0;
176 int showFile = find_option("showfile",0,0)!=0;
177 int stopOnError = find_option("dontstop",0,0)==0;
178 int rc;
179 int nToDel = 0;
180 int showLabel = 0;
181
182 dryRunFlag = find_option("dry-run","n",0)!=0;
183 if( !dryRunFlag ){
@@ -378,10 +377,11 @@
378 );
379 }
380 db_multi_exec("CREATE TEMP TABLE toDel(x TEXT)");
381 db_prepare(&q, "SELECT name, tag FROM repolist ORDER BY 1");
382 while( db_step(&q)==SQLITE_ROW ){
 
383 const char *zFilename = db_column_text(&q, 0);
384 #if !USE_SEE
385 if( sqlite3_strglob("*.efossil", zFilename)==0 ) continue;
386 #endif
387 if( file_access(zFilename, F_OK)
388
--- src/allrepo.c
+++ src/allrepo.c
@@ -173,11 +173,10 @@
173 int useCheckouts = 0;
174 int quiet = 0;
175 int dryRunFlag = 0;
176 int showFile = find_option("showfile",0,0)!=0;
177 int stopOnError = find_option("dontstop",0,0)==0;
 
178 int nToDel = 0;
179 int showLabel = 0;
180
181 dryRunFlag = find_option("dry-run","n",0)!=0;
182 if( !dryRunFlag ){
@@ -378,10 +377,11 @@
377 );
378 }
379 db_multi_exec("CREATE TEMP TABLE toDel(x TEXT)");
380 db_prepare(&q, "SELECT name, tag FROM repolist ORDER BY 1");
381 while( db_step(&q)==SQLITE_ROW ){
382 int rc;
383 const char *zFilename = db_column_text(&q, 0);
384 #if !USE_SEE
385 if( sqlite3_strglob("*.efossil", zFilename)==0 ) continue;
386 #endif
387 if( file_access(zFilename, F_OK)
388
+17 -2
--- src/branch.c
+++ src/branch.c
@@ -323,11 +323,12 @@
323323
@ WHERE plink.pid=event.objid
324324
@ AND tagxref.rid=plink.cid
325325
@ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch')
326326
@ AND tagtype>0),
327327
@ count(*),
328
-@ (SELECT uuid FROM blob WHERE rid=tagxref.rid)
328
+@ (SELECT uuid FROM blob WHERE rid=tagxref.rid),
329
+@ event.bgcolor
329330
@ FROM tagxref, tag, event
330331
@ WHERE tagxref.tagid=tag.tagid
331332
@ AND tagxref.tagtype>0
332333
@ AND tag.tagname='branch'
333334
@ AND event.objid=tagxref.rid
@@ -344,14 +345,16 @@
344345
** if there are no query parameters.
345346
*/
346347
static void new_brlist_page(void){
347348
Stmt q;
348349
double rNow;
350
+ int show_colors = PB("colors");
349351
login_check_credentials();
350352
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
351353
style_header("Branches");
352354
style_adunit_config(ADUNIT_RIGHT_OK);
355
+ style_submenu_binary("colors", "Color", "B/W", 0);
353356
login_anonymous_available();
354357
355358
db_prepare(&q, brlistQuery/*works-like:""*/);
356359
rNow = db_double(0.0, "SELECT julianday('now')");
357360
@ <div class="brlist"><table id="branchlisttable">
@@ -367,14 +370,26 @@
367370
double rMtime = db_column_double(&q, 1);
368371
int isClosed = db_column_int(&q, 2);
369372
const char *zMergeTo = db_column_text(&q, 3);
370373
int nCkin = db_column_int(&q, 4);
371374
const char *zLastCkin = db_column_text(&q, 5);
375
+ const char *zBgClr = db_column_text(&q, 6);
372376
char *zAge = human_readable_age(rNow - rMtime);
373377
sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0);
374378
if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0;
375
- @ <tr>
379
+ if( zBgClr == 0 ){
380
+ if( zBranch==0 || strcmp(zBranch,"trunk")==0 ){
381
+ zBgClr = 0;
382
+ }else{
383
+ zBgClr = hash_color(zBranch);
384
+ }
385
+ }
386
+ if( zBgClr && zBgClr[0] && show_colors ){
387
+ @ <tr style="background-color:%s(zBgClr)">
388
+ }else{
389
+ @ <tr>
390
+ }
376391
@ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td>
377392
@ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td>
378393
@ <td>%d(nCkin)</td>
379394
fossil_free(zAge);
380395
@ <td>%s(isClosed?"closed":"")</td>
381396
--- src/branch.c
+++ src/branch.c
@@ -323,11 +323,12 @@
323 @ WHERE plink.pid=event.objid
324 @ AND tagxref.rid=plink.cid
325 @ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch')
326 @ AND tagtype>0),
327 @ count(*),
328 @ (SELECT uuid FROM blob WHERE rid=tagxref.rid)
 
329 @ FROM tagxref, tag, event
330 @ WHERE tagxref.tagid=tag.tagid
331 @ AND tagxref.tagtype>0
332 @ AND tag.tagname='branch'
333 @ AND event.objid=tagxref.rid
@@ -344,14 +345,16 @@
344 ** if there are no query parameters.
345 */
346 static void new_brlist_page(void){
347 Stmt q;
348 double rNow;
 
349 login_check_credentials();
350 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
351 style_header("Branches");
352 style_adunit_config(ADUNIT_RIGHT_OK);
 
353 login_anonymous_available();
354
355 db_prepare(&q, brlistQuery/*works-like:""*/);
356 rNow = db_double(0.0, "SELECT julianday('now')");
357 @ <div class="brlist"><table id="branchlisttable">
@@ -367,14 +370,26 @@
367 double rMtime = db_column_double(&q, 1);
368 int isClosed = db_column_int(&q, 2);
369 const char *zMergeTo = db_column_text(&q, 3);
370 int nCkin = db_column_int(&q, 4);
371 const char *zLastCkin = db_column_text(&q, 5);
 
372 char *zAge = human_readable_age(rNow - rMtime);
373 sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0);
374 if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0;
375 @ <tr>
 
 
 
 
 
 
 
 
 
 
 
376 @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td>
377 @ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td>
378 @ <td>%d(nCkin)</td>
379 fossil_free(zAge);
380 @ <td>%s(isClosed?"closed":"")</td>
381
--- src/branch.c
+++ src/branch.c
@@ -323,11 +323,12 @@
323 @ WHERE plink.pid=event.objid
324 @ AND tagxref.rid=plink.cid
325 @ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch')
326 @ AND tagtype>0),
327 @ count(*),
328 @ (SELECT uuid FROM blob WHERE rid=tagxref.rid),
329 @ event.bgcolor
330 @ FROM tagxref, tag, event
331 @ WHERE tagxref.tagid=tag.tagid
332 @ AND tagxref.tagtype>0
333 @ AND tag.tagname='branch'
334 @ AND event.objid=tagxref.rid
@@ -344,14 +345,16 @@
345 ** if there are no query parameters.
346 */
347 static void new_brlist_page(void){
348 Stmt q;
349 double rNow;
350 int show_colors = PB("colors");
351 login_check_credentials();
352 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
353 style_header("Branches");
354 style_adunit_config(ADUNIT_RIGHT_OK);
355 style_submenu_binary("colors", "Color", "B/W", 0);
356 login_anonymous_available();
357
358 db_prepare(&q, brlistQuery/*works-like:""*/);
359 rNow = db_double(0.0, "SELECT julianday('now')");
360 @ <div class="brlist"><table id="branchlisttable">
@@ -367,14 +370,26 @@
370 double rMtime = db_column_double(&q, 1);
371 int isClosed = db_column_int(&q, 2);
372 const char *zMergeTo = db_column_text(&q, 3);
373 int nCkin = db_column_int(&q, 4);
374 const char *zLastCkin = db_column_text(&q, 5);
375 const char *zBgClr = db_column_text(&q, 6);
376 char *zAge = human_readable_age(rNow - rMtime);
377 sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0);
378 if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0;
379 if( zBgClr == 0 ){
380 if( zBranch==0 || strcmp(zBranch,"trunk")==0 ){
381 zBgClr = 0;
382 }else{
383 zBgClr = hash_color(zBranch);
384 }
385 }
386 if( zBgClr && zBgClr[0] && show_colors ){
387 @ <tr style="background-color:%s(zBgClr)">
388 }else{
389 @ <tr>
390 }
391 @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td>
392 @ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td>
393 @ <td>%d(nCkin)</td>
394 fossil_free(zAge);
395 @ <td>%s(isClosed?"closed":"")</td>
396
+3
--- src/cgi.c
+++ src/cgi.c
@@ -21,10 +21,13 @@
2121
** formatting function and its cousins, and routines to encode and
2222
** decode strings in HTML or HTTP.
2323
*/
2424
#include "config.h"
2525
#ifdef _WIN32
26
+# if !defined(_WIN32_WINNT)
27
+# define _WIN32_WINNT 0x0501
28
+# endif
2629
# include <winsock2.h>
2730
# include <ws2tcpip.h>
2831
#else
2932
# include <sys/socket.h>
3033
# include <netinet/in.h>
3134
--- src/cgi.c
+++ src/cgi.c
@@ -21,10 +21,13 @@
21 ** formatting function and its cousins, and routines to encode and
22 ** decode strings in HTML or HTTP.
23 */
24 #include "config.h"
25 #ifdef _WIN32
 
 
 
26 # include <winsock2.h>
27 # include <ws2tcpip.h>
28 #else
29 # include <sys/socket.h>
30 # include <netinet/in.h>
31
--- src/cgi.c
+++ src/cgi.c
@@ -21,10 +21,13 @@
21 ** formatting function and its cousins, and routines to encode and
22 ** decode strings in HTML or HTTP.
23 */
24 #include "config.h"
25 #ifdef _WIN32
26 # if !defined(_WIN32_WINNT)
27 # define _WIN32_WINNT 0x0501
28 # endif
29 # include <winsock2.h>
30 # include <ws2tcpip.h>
31 #else
32 # include <sys/socket.h>
33 # include <netinet/in.h>
34
+165 -14
--- src/db.c
+++ src/db.c
@@ -27,11 +27,15 @@
2727
** (3) A local checkout database named "_FOSSIL_" or ".fslckout"
2828
** and located at the root of the local copy of the source tree.
2929
**
3030
*/
3131
#include "config.h"
32
-#if ! defined(_WIN32)
32
+#if defined(_WIN32)
33
+# if USE_SEE
34
+# include <windows.h>
35
+# endif
36
+#else
3337
# include <pwd.h>
3438
#endif
3539
#include <sqlite3.h>
3640
#include <sys/types.h>
3741
#include <sys/stat.h>
@@ -870,31 +874,170 @@
870874
db_tolocal_function, 0, 0);
871875
sqlite3_create_function(db, "fromLocal", 0, SQLITE_UTF8, 0,
872876
db_fromlocal_function, 0, 0);
873877
}
874878
879
+#if USE_SEE
880
+/*
881
+** This is a pointer to the saved database encryption key string.
882
+*/
883
+static char *zSavedKey = 0;
884
+
885
+/*
886
+** This is the size of the saved database encryption key, in bytes.
887
+*/
888
+size_t savedKeySize = 0;
889
+
890
+/*
891
+** This function returns the saved database encryption key -OR- zero if
892
+** no database encryption key is saved.
893
+*/
894
+char *db_get_saved_encryption_key(){
895
+ return zSavedKey;
896
+}
897
+
898
+/*
899
+** This function returns the size of the saved database encryption key
900
+** -OR- zero if no database encryption key is saved.
901
+*/
902
+size_t db_get_saved_encryption_key_size(){
903
+ return savedKeySize;
904
+}
905
+
906
+/*
907
+** This function arranges for the database encryption key to be securely
908
+** saved in non-pagable memory (on platforms where this is possible).
909
+*/
910
+static void db_save_encryption_key(
911
+ Blob *pKey
912
+){
913
+ void *p = NULL;
914
+ size_t n = 0;
915
+ size_t pageSize = 0;
916
+ size_t blobSize = 0;
917
+
918
+ blobSize = blob_size(pKey);
919
+ if( blobSize==0 ) return;
920
+ fossil_get_page_size(&pageSize);
921
+ assert( pageSize>0 );
922
+ if( blobSize>pageSize ){
923
+ fossil_fatal("key blob too large: %u versus %u", blobSize, pageSize);
924
+ }
925
+ p = fossil_secure_alloc_page(&n);
926
+ assert( p!=NULL );
927
+ assert( n==pageSize );
928
+ assert( n>=blobSize );
929
+ memcpy(p, blob_str(pKey), blobSize);
930
+ zSavedKey = p;
931
+ savedKeySize = n;
932
+}
933
+
934
+/*
935
+** This function arranges for the saved database encryption key to be
936
+** securely zeroed, unlocked (if necessary), and freed.
937
+*/
938
+void db_unsave_encryption_key(){
939
+ fossil_secure_free_page(zSavedKey, savedKeySize);
940
+ zSavedKey = NULL;
941
+ savedKeySize = 0;
942
+}
943
+
944
+/*
945
+** This function sets the saved database encryption key to the specified
946
+** string value, allocating or freeing the underlying memory if needed.
947
+*/
948
+void db_set_saved_encryption_key(
949
+ Blob *pKey
950
+){
951
+ if( zSavedKey!=NULL ){
952
+ size_t blobSize = blob_size(pKey);
953
+ if( blobSize==0 ){
954
+ db_unsave_encryption_key();
955
+ }else{
956
+ if( blobSize>savedKeySize ){
957
+ fossil_fatal("key blob too large: %u versus %u",
958
+ blobSize, savedKeySize);
959
+ }
960
+ fossil_secure_zero(zSavedKey, savedKeySize);
961
+ memcpy(zSavedKey, blob_str(pKey), blobSize);
962
+ }
963
+ }else{
964
+ db_save_encryption_key(pKey);
965
+ }
966
+}
967
+
968
+#if defined(_WIN32)
969
+/*
970
+** This function sets the saved database encryption key to one that gets
971
+** read from the specified Fossil parent process. This is only necessary
972
+** (or functional) on Windows.
973
+*/
974
+void db_read_saved_encryption_key_from_process(
975
+ DWORD processId, /* Identifier for Fossil parent process. */
976
+ LPVOID pAddress, /* Pointer to saved key buffer in the parent process. */
977
+ SIZE_T nSize /* Size of saved key buffer in the parent process. */
978
+){
979
+ void *p = NULL;
980
+ size_t n = 0;
981
+ size_t pageSize = 0;
982
+ HANDLE hProcess = NULL;
983
+
984
+ fossil_get_page_size(&pageSize);
985
+ assert( pageSize>0 );
986
+ if( nSize>pageSize ){
987
+ fossil_fatal("key too large: %u versus %u", nSize, pageSize);
988
+ }
989
+ p = fossil_secure_alloc_page(&n);
990
+ assert( p!=NULL );
991
+ assert( n==pageSize );
992
+ assert( n>=nSize );
993
+ hProcess = OpenProcess(PROCESS_VM_READ, FALSE, processId);
994
+ if( hProcess!=NULL ){
995
+ SIZE_T nRead = 0;
996
+ if( ReadProcessMemory(hProcess, pAddress, p, nSize, &nRead) ){
997
+ CloseHandle(hProcess);
998
+ if( nRead==nSize ){
999
+ db_unsave_encryption_key();
1000
+ zSavedKey = p;
1001
+ savedKeySize = n;
1002
+ }else{
1003
+ fossil_fatal("bad size read, %u out of %u bytes at %p from pid %lu",
1004
+ nRead, nSize, pAddress, processId);
1005
+ }
1006
+ }else{
1007
+ CloseHandle(hProcess);
1008
+ fossil_fatal("failed read, %u bytes at %p from pid %lu: %lu", nSize,
1009
+ pAddress, processId, GetLastError());
1010
+ }
1011
+ }else{
1012
+ fossil_fatal("failed to open pid %lu: %lu", processId, GetLastError());
1013
+ }
1014
+}
1015
+#endif /* defined(_WIN32) */
1016
+#endif /* USE_SEE */
1017
+
8751018
/*
8761019
** If the database file zDbFile has a name that suggests that it is
877
-** encrypted, then prompt for the encryption key and return it in the
878
-** blob *pKey. Or, if the encryption key has previously been requested,
879
-** just return a copy of the previous result.
1020
+** encrypted, then prompt for the database encryption key and return it
1021
+** in the blob *pKey. Or, if the encryption key has previously been
1022
+** requested, just return a copy of the previous result. The blob in
1023
+** *pKey must be initialized.
8801024
*/
881
-static void db_encryption_key(
1025
+static void db_maybe_obtain_encryption_key(
8821026
const char *zDbFile, /* Name of the database file */
8831027
Blob *pKey /* Put the encryption key here */
8841028
){
885
- blob_init(pKey, 0, 0);
8861029
#if USE_SEE
8871030
if( sqlite3_strglob("*.efossil", zDbFile)==0 ){
888
- static char *zSavedKey = 0;
889
- if( zSavedKey ){
890
- blob_set(pKey, zSavedKey);
1031
+ char *zKey = db_get_saved_encryption_key();
1032
+ if( zKey ){
1033
+ blob_set(pKey, zKey);
8911034
}else{
8921035
char *zPrompt = mprintf("\rencryption key for '%s': ", zDbFile);
8931036
prompt_for_password(zPrompt, pKey, 0);
8941037
fossil_free(zPrompt);
895
- zSavedKey = fossil_strdup(blob_str(pKey));
1038
+ db_set_saved_encryption_key(pKey);
8961039
}
8971040
}
8981041
#endif
8991042
}
9001043
@@ -915,14 +1058,16 @@
9151058
g.zVfsName
9161059
);
9171060
if( rc!=SQLITE_OK ){
9181061
db_err("[%s]: %s", zDbName, sqlite3_errmsg(db));
9191062
}
920
- db_encryption_key(zDbName, &key);
1063
+ blob_init(&key, 0, 0);
1064
+ db_maybe_obtain_encryption_key(zDbName, &key);
9211065
if( blob_size(&key)>0 ){
9221066
char *zCmd = sqlite3_mprintf("PRAGMA key(%Q)", blob_str(&key));
9231067
sqlite3_exec(db, zCmd, 0, 0, 0);
1068
+ fossil_secure_zero(zCmd, strlen(zCmd));
9241069
sqlite3_free(zCmd);
9251070
}
9261071
blob_reset(&key);
9271072
sqlite3_busy_timeout(db, 5000);
9281073
sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
@@ -955,14 +1100,19 @@
9551100
/*
9561101
** zDbName is the name of a database file. Attach zDbName using
9571102
** the name zLabel.
9581103
*/
9591104
void db_attach(const char *zDbName, const char *zLabel){
1105
+ char *zCmd;
9601106
Blob key;
961
- db_encryption_key(zDbName, &key);
962
- db_multi_exec("ATTACH DATABASE %Q AS %Q KEY %Q",
963
- zDbName, zLabel, blob_str(&key));
1107
+ blob_init(&key, 0, 0);
1108
+ db_maybe_obtain_encryption_key(zDbName, &key);
1109
+ zCmd = sqlite3_mprintf("ATTACH DATABASE %Q AS %Q KEY %Q",
1110
+ zDbName, zLabel, blob_str(&key));
1111
+ db_multi_exec(zCmd /*works-like:""*/);
1112
+ fossil_secure_zero(zCmd, strlen(zCmd));
1113
+ sqlite3_free(zCmd);
9641114
blob_reset(&key);
9651115
}
9661116
9671117
/*
9681118
** Change the schema name of the "main" database to zLabel.
@@ -1192,10 +1342,11 @@
11921342
}
11931343
if( db_local_table_exists_but_lacks_column("undo_vfile", "islink") ){
11941344
db_multi_exec("ALTER TABLE undo_vfile ADD COLUMN islink BOOL DEFAULT 0");
11951345
}
11961346
}
1347
+ fossil_free(zVFileDef);
11971348
return 1;
11981349
}
11991350
12001351
/*
12011352
** Locate the root directory of the local repository tree. The root
12021353
--- src/db.c
+++ src/db.c
@@ -27,11 +27,15 @@
27 ** (3) A local checkout database named "_FOSSIL_" or ".fslckout"
28 ** and located at the root of the local copy of the source tree.
29 **
30 */
31 #include "config.h"
32 #if ! defined(_WIN32)
 
 
 
 
33 # include <pwd.h>
34 #endif
35 #include <sqlite3.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
@@ -870,31 +874,170 @@
870 db_tolocal_function, 0, 0);
871 sqlite3_create_function(db, "fromLocal", 0, SQLITE_UTF8, 0,
872 db_fromlocal_function, 0, 0);
873 }
874
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
875 /*
876 ** If the database file zDbFile has a name that suggests that it is
877 ** encrypted, then prompt for the encryption key and return it in the
878 ** blob *pKey. Or, if the encryption key has previously been requested,
879 ** just return a copy of the previous result.
 
880 */
881 static void db_encryption_key(
882 const char *zDbFile, /* Name of the database file */
883 Blob *pKey /* Put the encryption key here */
884 ){
885 blob_init(pKey, 0, 0);
886 #if USE_SEE
887 if( sqlite3_strglob("*.efossil", zDbFile)==0 ){
888 static char *zSavedKey = 0;
889 if( zSavedKey ){
890 blob_set(pKey, zSavedKey);
891 }else{
892 char *zPrompt = mprintf("\rencryption key for '%s': ", zDbFile);
893 prompt_for_password(zPrompt, pKey, 0);
894 fossil_free(zPrompt);
895 zSavedKey = fossil_strdup(blob_str(pKey));
896 }
897 }
898 #endif
899 }
900
@@ -915,14 +1058,16 @@
915 g.zVfsName
916 );
917 if( rc!=SQLITE_OK ){
918 db_err("[%s]: %s", zDbName, sqlite3_errmsg(db));
919 }
920 db_encryption_key(zDbName, &key);
 
921 if( blob_size(&key)>0 ){
922 char *zCmd = sqlite3_mprintf("PRAGMA key(%Q)", blob_str(&key));
923 sqlite3_exec(db, zCmd, 0, 0, 0);
 
924 sqlite3_free(zCmd);
925 }
926 blob_reset(&key);
927 sqlite3_busy_timeout(db, 5000);
928 sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
@@ -955,14 +1100,19 @@
955 /*
956 ** zDbName is the name of a database file. Attach zDbName using
957 ** the name zLabel.
958 */
959 void db_attach(const char *zDbName, const char *zLabel){
 
960 Blob key;
961 db_encryption_key(zDbName, &key);
962 db_multi_exec("ATTACH DATABASE %Q AS %Q KEY %Q",
963 zDbName, zLabel, blob_str(&key));
 
 
 
 
964 blob_reset(&key);
965 }
966
967 /*
968 ** Change the schema name of the "main" database to zLabel.
@@ -1192,10 +1342,11 @@
1192 }
1193 if( db_local_table_exists_but_lacks_column("undo_vfile", "islink") ){
1194 db_multi_exec("ALTER TABLE undo_vfile ADD COLUMN islink BOOL DEFAULT 0");
1195 }
1196 }
 
1197 return 1;
1198 }
1199
1200 /*
1201 ** Locate the root directory of the local repository tree. The root
1202
--- src/db.c
+++ src/db.c
@@ -27,11 +27,15 @@
27 ** (3) A local checkout database named "_FOSSIL_" or ".fslckout"
28 ** and located at the root of the local copy of the source tree.
29 **
30 */
31 #include "config.h"
32 #if defined(_WIN32)
33 # if USE_SEE
34 # include <windows.h>
35 # endif
36 #else
37 # include <pwd.h>
38 #endif
39 #include <sqlite3.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
@@ -870,31 +874,170 @@
874 db_tolocal_function, 0, 0);
875 sqlite3_create_function(db, "fromLocal", 0, SQLITE_UTF8, 0,
876 db_fromlocal_function, 0, 0);
877 }
878
879 #if USE_SEE
880 /*
881 ** This is a pointer to the saved database encryption key string.
882 */
883 static char *zSavedKey = 0;
884
885 /*
886 ** This is the size of the saved database encryption key, in bytes.
887 */
888 size_t savedKeySize = 0;
889
890 /*
891 ** This function returns the saved database encryption key -OR- zero if
892 ** no database encryption key is saved.
893 */
894 char *db_get_saved_encryption_key(){
895 return zSavedKey;
896 }
897
898 /*
899 ** This function returns the size of the saved database encryption key
900 ** -OR- zero if no database encryption key is saved.
901 */
902 size_t db_get_saved_encryption_key_size(){
903 return savedKeySize;
904 }
905
906 /*
907 ** This function arranges for the database encryption key to be securely
908 ** saved in non-pagable memory (on platforms where this is possible).
909 */
910 static void db_save_encryption_key(
911 Blob *pKey
912 ){
913 void *p = NULL;
914 size_t n = 0;
915 size_t pageSize = 0;
916 size_t blobSize = 0;
917
918 blobSize = blob_size(pKey);
919 if( blobSize==0 ) return;
920 fossil_get_page_size(&pageSize);
921 assert( pageSize>0 );
922 if( blobSize>pageSize ){
923 fossil_fatal("key blob too large: %u versus %u", blobSize, pageSize);
924 }
925 p = fossil_secure_alloc_page(&n);
926 assert( p!=NULL );
927 assert( n==pageSize );
928 assert( n>=blobSize );
929 memcpy(p, blob_str(pKey), blobSize);
930 zSavedKey = p;
931 savedKeySize = n;
932 }
933
934 /*
935 ** This function arranges for the saved database encryption key to be
936 ** securely zeroed, unlocked (if necessary), and freed.
937 */
938 void db_unsave_encryption_key(){
939 fossil_secure_free_page(zSavedKey, savedKeySize);
940 zSavedKey = NULL;
941 savedKeySize = 0;
942 }
943
944 /*
945 ** This function sets the saved database encryption key to the specified
946 ** string value, allocating or freeing the underlying memory if needed.
947 */
948 void db_set_saved_encryption_key(
949 Blob *pKey
950 ){
951 if( zSavedKey!=NULL ){
952 size_t blobSize = blob_size(pKey);
953 if( blobSize==0 ){
954 db_unsave_encryption_key();
955 }else{
956 if( blobSize>savedKeySize ){
957 fossil_fatal("key blob too large: %u versus %u",
958 blobSize, savedKeySize);
959 }
960 fossil_secure_zero(zSavedKey, savedKeySize);
961 memcpy(zSavedKey, blob_str(pKey), blobSize);
962 }
963 }else{
964 db_save_encryption_key(pKey);
965 }
966 }
967
968 #if defined(_WIN32)
969 /*
970 ** This function sets the saved database encryption key to one that gets
971 ** read from the specified Fossil parent process. This is only necessary
972 ** (or functional) on Windows.
973 */
974 void db_read_saved_encryption_key_from_process(
975 DWORD processId, /* Identifier for Fossil parent process. */
976 LPVOID pAddress, /* Pointer to saved key buffer in the parent process. */
977 SIZE_T nSize /* Size of saved key buffer in the parent process. */
978 ){
979 void *p = NULL;
980 size_t n = 0;
981 size_t pageSize = 0;
982 HANDLE hProcess = NULL;
983
984 fossil_get_page_size(&pageSize);
985 assert( pageSize>0 );
986 if( nSize>pageSize ){
987 fossil_fatal("key too large: %u versus %u", nSize, pageSize);
988 }
989 p = fossil_secure_alloc_page(&n);
990 assert( p!=NULL );
991 assert( n==pageSize );
992 assert( n>=nSize );
993 hProcess = OpenProcess(PROCESS_VM_READ, FALSE, processId);
994 if( hProcess!=NULL ){
995 SIZE_T nRead = 0;
996 if( ReadProcessMemory(hProcess, pAddress, p, nSize, &nRead) ){
997 CloseHandle(hProcess);
998 if( nRead==nSize ){
999 db_unsave_encryption_key();
1000 zSavedKey = p;
1001 savedKeySize = n;
1002 }else{
1003 fossil_fatal("bad size read, %u out of %u bytes at %p from pid %lu",
1004 nRead, nSize, pAddress, processId);
1005 }
1006 }else{
1007 CloseHandle(hProcess);
1008 fossil_fatal("failed read, %u bytes at %p from pid %lu: %lu", nSize,
1009 pAddress, processId, GetLastError());
1010 }
1011 }else{
1012 fossil_fatal("failed to open pid %lu: %lu", processId, GetLastError());
1013 }
1014 }
1015 #endif /* defined(_WIN32) */
1016 #endif /* USE_SEE */
1017
1018 /*
1019 ** If the database file zDbFile has a name that suggests that it is
1020 ** encrypted, then prompt for the database encryption key and return it
1021 ** in the blob *pKey. Or, if the encryption key has previously been
1022 ** requested, just return a copy of the previous result. The blob in
1023 ** *pKey must be initialized.
1024 */
1025 static void db_maybe_obtain_encryption_key(
1026 const char *zDbFile, /* Name of the database file */
1027 Blob *pKey /* Put the encryption key here */
1028 ){
 
1029 #if USE_SEE
1030 if( sqlite3_strglob("*.efossil", zDbFile)==0 ){
1031 char *zKey = db_get_saved_encryption_key();
1032 if( zKey ){
1033 blob_set(pKey, zKey);
1034 }else{
1035 char *zPrompt = mprintf("\rencryption key for '%s': ", zDbFile);
1036 prompt_for_password(zPrompt, pKey, 0);
1037 fossil_free(zPrompt);
1038 db_set_saved_encryption_key(pKey);
1039 }
1040 }
1041 #endif
1042 }
1043
@@ -915,14 +1058,16 @@
1058 g.zVfsName
1059 );
1060 if( rc!=SQLITE_OK ){
1061 db_err("[%s]: %s", zDbName, sqlite3_errmsg(db));
1062 }
1063 blob_init(&key, 0, 0);
1064 db_maybe_obtain_encryption_key(zDbName, &key);
1065 if( blob_size(&key)>0 ){
1066 char *zCmd = sqlite3_mprintf("PRAGMA key(%Q)", blob_str(&key));
1067 sqlite3_exec(db, zCmd, 0, 0, 0);
1068 fossil_secure_zero(zCmd, strlen(zCmd));
1069 sqlite3_free(zCmd);
1070 }
1071 blob_reset(&key);
1072 sqlite3_busy_timeout(db, 5000);
1073 sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
@@ -955,14 +1100,19 @@
1100 /*
1101 ** zDbName is the name of a database file. Attach zDbName using
1102 ** the name zLabel.
1103 */
1104 void db_attach(const char *zDbName, const char *zLabel){
1105 char *zCmd;
1106 Blob key;
1107 blob_init(&key, 0, 0);
1108 db_maybe_obtain_encryption_key(zDbName, &key);
1109 zCmd = sqlite3_mprintf("ATTACH DATABASE %Q AS %Q KEY %Q",
1110 zDbName, zLabel, blob_str(&key));
1111 db_multi_exec(zCmd /*works-like:""*/);
1112 fossil_secure_zero(zCmd, strlen(zCmd));
1113 sqlite3_free(zCmd);
1114 blob_reset(&key);
1115 }
1116
1117 /*
1118 ** Change the schema name of the "main" database to zLabel.
@@ -1192,10 +1342,11 @@
1342 }
1343 if( db_local_table_exists_but_lacks_column("undo_vfile", "islink") ){
1344 db_multi_exec("ALTER TABLE undo_vfile ADD COLUMN islink BOOL DEFAULT 0");
1345 }
1346 }
1347 fossil_free(zVFileDef);
1348 return 1;
1349 }
1350
1351 /*
1352 ** Locate the root directory of the local repository tree. The root
1353
+1 -2
--- src/delta.c
+++ src/delta.c
@@ -377,13 +377,12 @@
377377
/* Compute the hash table used to locate matching sections in the
378378
** source file.
379379
*/
380380
nHash = lenSrc/NHASH;
381381
collide = fossil_malloc( nHash*2*sizeof(int) );
382
+ memset(collide, -1, nHash*2*sizeof(int));
382383
landmark = &collide[nHash];
383
- memset(landmark, -1, nHash*sizeof(int));
384
- memset(collide, -1, nHash*sizeof(int));
385384
for(i=0; i<lenSrc-NHASH; i+=NHASH){
386385
int hv = hash_once(&zSrc[i]) % nHash;
387386
collide[i/NHASH] = landmark[hv];
388387
landmark[hv] = i/NHASH;
389388
}
390389
--- src/delta.c
+++ src/delta.c
@@ -377,13 +377,12 @@
377 /* Compute the hash table used to locate matching sections in the
378 ** source file.
379 */
380 nHash = lenSrc/NHASH;
381 collide = fossil_malloc( nHash*2*sizeof(int) );
 
382 landmark = &collide[nHash];
383 memset(landmark, -1, nHash*sizeof(int));
384 memset(collide, -1, nHash*sizeof(int));
385 for(i=0; i<lenSrc-NHASH; i+=NHASH){
386 int hv = hash_once(&zSrc[i]) % nHash;
387 collide[i/NHASH] = landmark[hv];
388 landmark[hv] = i/NHASH;
389 }
390
--- src/delta.c
+++ src/delta.c
@@ -377,13 +377,12 @@
377 /* Compute the hash table used to locate matching sections in the
378 ** source file.
379 */
380 nHash = lenSrc/NHASH;
381 collide = fossil_malloc( nHash*2*sizeof(int) );
382 memset(collide, -1, nHash*2*sizeof(int));
383 landmark = &collide[nHash];
 
 
384 for(i=0; i<lenSrc-NHASH; i+=NHASH){
385 int hv = hash_once(&zSrc[i]) % nHash;
386 collide[i/NHASH] = landmark[hv];
387 landmark[hv] = i/NHASH;
388 }
389
+36 -17
--- src/diff.c
+++ src/diff.c
@@ -115,10 +115,34 @@
115115
int nFrom; /* Number of lines in aFrom[] */
116116
DLine *aTo; /* File on right side of the diff */
117117
int nTo; /* Number of lines in aTo[] */
118118
int (*same_fn)(const DLine*,const DLine*); /* comparison function */
119119
};
120
+
121
+/*
122
+** Count the number of lines in the input string. Include the last line
123
+** in the count even if it lacks the \n terminator. If an empty string
124
+** is specified, the number of lines is zero. For the purposes of this
125
+** function, a string is considered empty if it contains no characters
126
+** -OR- it contains only NUL characters.
127
+*/
128
+static int count_lines(
129
+ const char *z,
130
+ int n,
131
+ int *pnLine
132
+){
133
+ int nLine;
134
+ const char *zNL, *z2;
135
+ for(nLine=0, z2=z; (zNL = strchr(z2,'\n'))!=0; z2=zNL+1, nLine++){}
136
+ if( z2[0]!='\0' ){
137
+ nLine++;
138
+ do{ z2++; }while( z2[0]!='\0' );
139
+ }
140
+ if( n!=(int)(z2-z) ) return 0;
141
+ if( pnLine ) *pnLine = nLine;
142
+ return 1;
143
+}
120144
121145
/*
122146
** Return an array of DLine objects containing a pointer to the
123147
** start of each line and a hash of that line. The lower
124148
** bits of the hash store the length of each line.
@@ -140,32 +164,26 @@
140164
u64 diffFlags
141165
){
142166
int nLine, i, k, nn, s, x;
143167
unsigned int h, h2;
144168
DLine *a;
145
- const char *zNL, *z2;
146
-
147
- /* Count the number of lines in the input file. Include the last line
148
- ** in the count even if it lacks the \n terminator
149
- */
150
- for(nLine=0, z2=z; (zNL = strchr(z2,'\n'))!=0; z2=zNL+1, nLine++){}
151
- if( z2[0]!=0 ){
152
- nLine++;
153
- do{ z2++; }while( z2[0] );
154
- }
155
- if( n!=(int)(z2-z) ) return 0;
156
-
169
+ const char *zNL;
170
+
171
+ if( count_lines(z, n, &nLine)==0 ){
172
+ return 0;
173
+ }
174
+ assert( nLine>0 || z[0]=='\0' );
157175
a = fossil_malloc( sizeof(a[0])*nLine );
158176
memset(a, 0, sizeof(a[0])*nLine);
159177
if( nLine==0 ){
160178
*pnLine = 0;
161179
return a;
162180
}
163181
i = 0;
164182
do{
165183
zNL = strchr(z,'\n');
166
- if( zNL==0 ) zNL = z+strlen(z);
184
+ if( zNL==0 ) zNL = z+n;
167185
nn = (int)(zNL - z);
168186
if( nn>LENGTH_MASK ){
169187
fossil_free(a);
170188
return 0;
171189
}
@@ -181,14 +199,15 @@
181199
}
182200
if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){
183201
int numws = 0;
184202
while( s<k && fossil_isspace(z[s]) ){ s++; }
185203
for(h=0, x=s; x<k; x++){
186
- if( fossil_isspace(z[x]) ){
204
+ char c = z[x];
205
+ if( fossil_isspace(c) ){
187206
++numws;
188207
}else{
189
- h += z[x];
208
+ h += c;
190209
h *= 0x9e3779b1;
191210
}
192211
}
193212
k -= numws;
194213
}else{
@@ -200,13 +219,13 @@
200219
a[i].indent = s;
201220
a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s);
202221
h2 = h % nLine;
203222
a[i].iNext = a[h2].iHash;
204223
a[h2].iHash = i+1;
205
- z += nn+1;
224
+ z += nn+1; n -= nn+1;
206225
i++;
207
- }while( zNL[0] && zNL[1] );
226
+ }while( zNL[0]!='\0' && zNL[1]!='\0' );
208227
assert( i==nLine );
209228
210229
/* Return results */
211230
*pnLine = nLine;
212231
return a;
213232
--- src/diff.c
+++ src/diff.c
@@ -115,10 +115,34 @@
115 int nFrom; /* Number of lines in aFrom[] */
116 DLine *aTo; /* File on right side of the diff */
117 int nTo; /* Number of lines in aTo[] */
118 int (*same_fn)(const DLine*,const DLine*); /* comparison function */
119 };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
121 /*
122 ** Return an array of DLine objects containing a pointer to the
123 ** start of each line and a hash of that line. The lower
124 ** bits of the hash store the length of each line.
@@ -140,32 +164,26 @@
140 u64 diffFlags
141 ){
142 int nLine, i, k, nn, s, x;
143 unsigned int h, h2;
144 DLine *a;
145 const char *zNL, *z2;
146
147 /* Count the number of lines in the input file. Include the last line
148 ** in the count even if it lacks the \n terminator
149 */
150 for(nLine=0, z2=z; (zNL = strchr(z2,'\n'))!=0; z2=zNL+1, nLine++){}
151 if( z2[0]!=0 ){
152 nLine++;
153 do{ z2++; }while( z2[0] );
154 }
155 if( n!=(int)(z2-z) ) return 0;
156
157 a = fossil_malloc( sizeof(a[0])*nLine );
158 memset(a, 0, sizeof(a[0])*nLine);
159 if( nLine==0 ){
160 *pnLine = 0;
161 return a;
162 }
163 i = 0;
164 do{
165 zNL = strchr(z,'\n');
166 if( zNL==0 ) zNL = z+strlen(z);
167 nn = (int)(zNL - z);
168 if( nn>LENGTH_MASK ){
169 fossil_free(a);
170 return 0;
171 }
@@ -181,14 +199,15 @@
181 }
182 if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){
183 int numws = 0;
184 while( s<k && fossil_isspace(z[s]) ){ s++; }
185 for(h=0, x=s; x<k; x++){
186 if( fossil_isspace(z[x]) ){
 
187 ++numws;
188 }else{
189 h += z[x];
190 h *= 0x9e3779b1;
191 }
192 }
193 k -= numws;
194 }else{
@@ -200,13 +219,13 @@
200 a[i].indent = s;
201 a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s);
202 h2 = h % nLine;
203 a[i].iNext = a[h2].iHash;
204 a[h2].iHash = i+1;
205 z += nn+1;
206 i++;
207 }while( zNL[0] && zNL[1] );
208 assert( i==nLine );
209
210 /* Return results */
211 *pnLine = nLine;
212 return a;
213
--- src/diff.c
+++ src/diff.c
@@ -115,10 +115,34 @@
115 int nFrom; /* Number of lines in aFrom[] */
116 DLine *aTo; /* File on right side of the diff */
117 int nTo; /* Number of lines in aTo[] */
118 int (*same_fn)(const DLine*,const DLine*); /* comparison function */
119 };
120
121 /*
122 ** Count the number of lines in the input string. Include the last line
123 ** in the count even if it lacks the \n terminator. If an empty string
124 ** is specified, the number of lines is zero. For the purposes of this
125 ** function, a string is considered empty if it contains no characters
126 ** -OR- it contains only NUL characters.
127 */
128 static int count_lines(
129 const char *z,
130 int n,
131 int *pnLine
132 ){
133 int nLine;
134 const char *zNL, *z2;
135 for(nLine=0, z2=z; (zNL = strchr(z2,'\n'))!=0; z2=zNL+1, nLine++){}
136 if( z2[0]!='\0' ){
137 nLine++;
138 do{ z2++; }while( z2[0]!='\0' );
139 }
140 if( n!=(int)(z2-z) ) return 0;
141 if( pnLine ) *pnLine = nLine;
142 return 1;
143 }
144
145 /*
146 ** Return an array of DLine objects containing a pointer to the
147 ** start of each line and a hash of that line. The lower
148 ** bits of the hash store the length of each line.
@@ -140,32 +164,26 @@
164 u64 diffFlags
165 ){
166 int nLine, i, k, nn, s, x;
167 unsigned int h, h2;
168 DLine *a;
169 const char *zNL;
170
171 if( count_lines(z, n, &nLine)==0 ){
172 return 0;
173 }
174 assert( nLine>0 || z[0]=='\0' );
 
 
 
 
 
 
175 a = fossil_malloc( sizeof(a[0])*nLine );
176 memset(a, 0, sizeof(a[0])*nLine);
177 if( nLine==0 ){
178 *pnLine = 0;
179 return a;
180 }
181 i = 0;
182 do{
183 zNL = strchr(z,'\n');
184 if( zNL==0 ) zNL = z+n;
185 nn = (int)(zNL - z);
186 if( nn>LENGTH_MASK ){
187 fossil_free(a);
188 return 0;
189 }
@@ -181,14 +199,15 @@
199 }
200 if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){
201 int numws = 0;
202 while( s<k && fossil_isspace(z[s]) ){ s++; }
203 for(h=0, x=s; x<k; x++){
204 char c = z[x];
205 if( fossil_isspace(c) ){
206 ++numws;
207 }else{
208 h += c;
209 h *= 0x9e3779b1;
210 }
211 }
212 k -= numws;
213 }else{
@@ -200,13 +219,13 @@
219 a[i].indent = s;
220 a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s);
221 h2 = h % nLine;
222 a[i].iNext = a[h2].iHash;
223 a[h2].iHash = i+1;
224 z += nn+1; n -= nn+1;
225 i++;
226 }while( zNL[0]!='\0' && zNL[1]!='\0' );
227 assert( i==nLine );
228
229 /* Return results */
230 *pnLine = nLine;
231 return a;
232
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -412,10 +412,11 @@
412412
" ORDER BY pathname /*scan*/",
413413
vid
414414
);
415415
}
416416
db_prepare(&q, "%s", blob_sql_text(&sql));
417
+ blob_reset(&sql);
417418
while( db_step(&q)==SQLITE_ROW ){
418419
const char *zPathname = db_column_text(&q,0);
419420
int isDeleted = db_column_int(&q, 1);
420421
int isChnged = db_column_int(&q,2);
421422
int isNew = db_column_int(&q,3);
422423
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -412,10 +412,11 @@
412 " ORDER BY pathname /*scan*/",
413 vid
414 );
415 }
416 db_prepare(&q, "%s", blob_sql_text(&sql));
 
417 while( db_step(&q)==SQLITE_ROW ){
418 const char *zPathname = db_column_text(&q,0);
419 int isDeleted = db_column_int(&q, 1);
420 int isChnged = db_column_int(&q,2);
421 int isNew = db_column_int(&q,3);
422
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -412,10 +412,11 @@
412 " ORDER BY pathname /*scan*/",
413 vid
414 );
415 }
416 db_prepare(&q, "%s", blob_sql_text(&sql));
417 blob_reset(&sql);
418 while( db_step(&q)==SQLITE_ROW ){
419 const char *zPathname = db_column_text(&q,0);
420 int isDeleted = db_column_int(&q, 1);
421 int isChnged = db_column_int(&q,2);
422 int isNew = db_column_int(&q,3);
423
+90 -47
--- src/export.c
+++ src/export.c
@@ -132,23 +132,28 @@
132132
133133
/*
134134
** create_mark()
135135
** Create a new (mark,rid,uuid) entry for the given rid in the 'xmark' table,
136136
** and return that information as a struct mark_t in *mark.
137
+** *unused_mark is a value representing a mark that is free for use--that is,
138
+** it does not appear in the marks file, and has not been used during this
139
+** export run. Specifically, it is the supremum of the set of used marks
140
+** plus one.
137141
** This function returns -1 in the case where 'rid' does not exist, otherwise
138142
** it returns 0.
139143
** mark->name is dynamically allocated and is owned by the caller upon return.
140144
*/
141
-int create_mark(int rid, struct mark_t *mark){
145
+int create_mark(int rid, struct mark_t *mark, unsigned int *unused_mark){
142146
char sid[13];
143147
char *zUuid = rid_to_uuid(rid);
144
- if(!zUuid){
148
+ if( !zUuid ){
145149
fossil_trace("Undefined rid=%d\n", rid);
146150
return -1;
147151
}
148152
mark->rid = rid;
149
- sqlite3_snprintf(sizeof(sid), sid, ":%d", COMMITMARK(rid));
153
+ sqlite3_snprintf(sizeof(sid), sid, ":%d", *unused_mark);
154
+ *unused_mark += 1;
150155
mark->name = fossil_strdup(sid);
151156
sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", zUuid);
152157
free(zUuid);
153158
insert_commit_xref(mark->rid, mark->name, mark->uuid);
154159
return 0;
@@ -156,19 +161,22 @@
156161
157162
/*
158163
** mark_name_from_rid()
159164
** Find the mark associated with the given rid. Mark names always start
160165
** with ':', and are pulled from the 'xmark' temporary table.
161
-** This function returns NULL if the rid does not exist in the 'xmark' table.
162
-** Otherwise, it returns the name of the mark, which is dynamically allocated
163
-** and is owned by the caller of this function.
166
+** If the given rid doesn't have a mark associated with it yet, one is
167
+** created with a value of *unused_mark.
168
+** *unused_mark functions exactly as in create_mark().
169
+** This function returns NULL if the rid does not have an associated UUID,
170
+** (i.e. is not valid). Otherwise, it returns the name of the mark, which is
171
+** dynamically allocated and is owned by the caller of this function.
164172
*/
165
-char * mark_name_from_rid(int rid){
173
+char * mark_name_from_rid(int rid, unsigned int *unused_mark){
166174
char *zMark = db_text(0, "SELECT tname FROM xmark WHERE trid=%d", rid);
167
- if(zMark==NULL){
175
+ if( zMark==NULL ){
168176
struct mark_t mark;
169
- if(create_mark(rid, &mark)==0){
177
+ if( create_mark(rid, &mark, unused_mark)==0 ){
170178
zMark = mark.name;
171179
}else{
172180
return NULL;
173181
}
174182
}
@@ -185,43 +193,52 @@
185193
** database. Otherwise, 0 is returned.
186194
** mark->name is dynamically allocated, and owned by the caller.
187195
*/
188196
int parse_mark(char *line, struct mark_t *mark){
189197
char *cur_tok;
198
+ char type_;
190199
cur_tok = strtok(line, " \t");
191
- if(!cur_tok||strlen(cur_tok)<2){
200
+ if( !cur_tok || strlen(cur_tok)<2 ){
192201
return -1;
193202
}
194203
mark->rid = atoi(&cur_tok[1]);
195
- if(cur_tok[0]!='c'){
204
+ type_ = cur_tok[0];
205
+ if( type_!='c' && type_!='b' ){
196206
/* This is probably a blob mark */
197207
mark->name = NULL;
198208
return 0;
199209
}
200210
201211
cur_tok = strtok(NULL, " \t");
202
- if(!cur_tok){
212
+ if( !cur_tok ){
203213
/* This mark was generated by an older version of Fossil and doesn't
204214
** include the mark name and uuid. create_mark() will name the new mark
205215
** exactly as it was when exported to git, so that we should have a
206216
** valid mapping from git sha1<->mark name<->fossil sha1. */
207
- return create_mark(mark->rid, mark);
217
+ unsigned int mid;
218
+ if( type_=='c' ){
219
+ mid = COMMITMARK(mark->rid);
220
+ }
221
+ else{
222
+ mid = BLOBMARK(mark->rid);
223
+ }
224
+ return create_mark(mark->rid, mark, &mid);
208225
}else{
209226
mark->name = fossil_strdup(cur_tok);
210227
}
211228
212229
cur_tok = strtok(NULL, "\n");
213
- if(!cur_tok||strlen(cur_tok)!=40){
230
+ if( !cur_tok || strlen(cur_tok)!=40 ){
214231
free(mark->name);
215232
fossil_trace("Invalid SHA-1 in marks file: %s\n", cur_tok);
216233
return -1;
217234
}else{
218235
sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", cur_tok);
219236
}
220237
221238
/* make sure that rid corresponds to UUID */
222
- if(fast_uuid_to_rid(mark->uuid)!=mark->rid){
239
+ if( fast_uuid_to_rid(mark->uuid)!=mark->rid ){
223240
free(mark->name);
224241
fossil_trace("Non-existent SHA-1 in marks file: %s\n", mark->uuid);
225242
return -1;
226243
}
227244
@@ -233,40 +250,66 @@
233250
/*
234251
** import_marks()
235252
** Import the marks specified in file 'f' into the 'xmark' table.
236253
** If 'blobs' is non-null, insert all blob marks into it.
237254
** If 'vers' is non-null, insert all commit marks into it.
255
+** If 'unused_marks' is non-null, upon return of this function, all values
256
+** x >= *unused_marks are free to use as marks, i.e. they do not clash with
257
+** any marks appearing in the marks file.
238258
** Each line in the file must be at most 100 characters in length. This
239259
** seems like a reasonable maximum for a 40-character uuid, and 1-13
240260
** character rid.
241261
** The function returns -1 if any of the lines in file 'f' are malformed,
242262
** or the rid/uuid information doesn't match what is in the repository
243263
** database. Otherwise, 0 is returned.
244264
*/
245
-int import_marks(FILE* f, Bag *blobs, Bag *vers){
265
+int import_marks(FILE* f, Bag *blobs, Bag *vers, unsigned int *unused_mark){
246266
char line[101];
247267
while(fgets(line, sizeof(line), f)){
248268
struct mark_t mark;
249
- if(strlen(line)==100&&line[99]!='\n'){
269
+ if( strlen(line)==100 && line[99]!='\n' ){
250270
/* line too long */
251271
return -1;
252272
}
253273
if( parse_mark(line, &mark)<0 ){
254274
return -1;
255275
}else if( line[0]=='b' ){
256
- /* Don't import blob marks into 'xmark' table--git doesn't use them,
257
- ** so they need to be left free for git to reuse. */
258
- if(blobs!=NULL){
276
+ if( blobs!=NULL ){
259277
bag_insert(blobs, mark.rid);
260278
}
261
- }else if( vers!=NULL ){
262
- bag_insert(vers, mark.rid);
279
+ }else{
280
+ if( vers!=NULL ){
281
+ bag_insert(vers, mark.rid);
282
+ }
283
+ }
284
+ if( unused_mark!=NULL ){
285
+ unsigned int mid = atoi(mark.name + 1);
286
+ if( mid>=*unused_mark ){
287
+ *unused_mark = mid + 1;
288
+ }
263289
}
264290
free(mark.name);
265291
}
266292
return 0;
267293
}
294
+
295
+void export_mark(FILE* f, int rid, char obj_type)
296
+{
297
+ unsigned int z = 0;
298
+ char *zUuid = rid_to_uuid(rid);
299
+ char *zMark;
300
+ if( zUuid==NULL ){
301
+ fossil_trace("No uuid matching rid=%d when exporting marks\n", rid);
302
+ return;
303
+ }
304
+ /* Since rid is already in the 'xmark' table, the value of z won't be
305
+ ** used, but pass in a valid pointer just to be safe. */
306
+ zMark = mark_name_from_rid(rid, &z);
307
+ fprintf(f, "%c%d %s %s\n", obj_type, rid, zMark, zUuid);
308
+ free(zMark);
309
+ free(zUuid);
310
+}
268311
269312
/*
270313
** If 'blobs' is non-null, it must point to a Bag of blob rids to be
271314
** written to disk. Blob rids are written as 'b<rid>'.
272315
** If 'vers' is non-null, it must point to a Bag of commit rids to be
@@ -275,32 +318,24 @@
275318
** This function does not fail, but may produce errors if a uuid cannot
276319
** be found for an rid in 'vers'.
277320
*/
278321
void export_marks(FILE* f, Bag *blobs, Bag *vers){
279322
int rid;
323
+
280324
if( blobs!=NULL ){
281325
rid = bag_first(blobs);
282
- if(rid!=0){
326
+ if( rid!=0 ){
283327
do{
284
- fprintf(f, "b%d\n", rid);
285
- }while((rid = bag_next(blobs, rid))!=0);
328
+ export_mark(f, rid, 'b');
329
+ }while( (rid = bag_next(blobs, rid))!=0 );
286330
}
287331
}
288332
if( vers!=NULL ){
289333
rid = bag_first(vers);
290334
if( rid!=0 ){
291335
do{
292
- char *zUuid = rid_to_uuid(rid);
293
- char *zMark;
294
- if(zUuid==NULL){
295
- fossil_trace("No uuid matching rid=%d when exporting marks\n", rid);
296
- continue;
297
- }
298
- zMark = mark_name_from_rid(rid);
299
- fprintf(f, "c%d %s %s\n", rid, zMark, zUuid);
300
- free(zMark);
301
- free(zUuid);
336
+ export_mark(f, rid, 'c');
302337
}while( (rid = bag_next(vers, rid))!=0 );
303338
}
304339
}
305340
}
306341
@@ -336,10 +371,11 @@
336371
*/
337372
void export_cmd(void){
338373
Stmt q, q2, q3;
339374
int i;
340375
Bag blobs, vers;
376
+ unsigned int unused_mark = 1;
341377
const char *markfile_in;
342378
const char *markfile_out;
343379
344380
bag_init(&blobs);
345381
bag_init(&vers);
@@ -362,25 +398,25 @@
362398
363399
f = fossil_fopen(markfile_in, "r");
364400
if( f==0 ){
365401
fossil_fatal("cannot open %s for reading", markfile_in);
366402
}
367
- if(import_marks(f, &blobs, &vers)<0){
403
+ if( import_marks(f, &blobs, &vers, &unused_mark)<0 ){
368404
fossil_fatal("error importing marks from file: %s", markfile_in);
369405
}
370406
db_prepare(&qb, "INSERT OR IGNORE INTO oldblob VALUES (:rid)");
371407
db_prepare(&qc, "INSERT OR IGNORE INTO oldcommit VALUES (:rid)");
372408
rid = bag_first(&blobs);
373
- if(rid!=0){
409
+ if( rid!=0 ){
374410
do{
375411
db_bind_int(&qb, ":rid", rid);
376412
db_step(&qb);
377413
db_reset(&qb);
378414
}while((rid = bag_next(&blobs, rid))!=0);
379415
}
380416
rid = bag_first(&vers);
381
- if(rid!=0){
417
+ if( rid!=0 ){
382418
do{
383419
db_bind_int(&qc, ":rid", rid);
384420
db_step(&qc);
385421
db_reset(&qc);
386422
}while((rid = bag_next(&vers, rid))!=0);
@@ -416,15 +452,18 @@
416452
while( db_step(&q)==SQLITE_ROW ){
417453
int rid = db_column_int(&q, 0);
418454
Blob content;
419455
420456
while( !bag_find(&blobs, rid) ){
457
+ char *zMark;
421458
content_get(rid, &content);
422459
db_bind_int(&q2, ":rid", rid);
423460
db_step(&q2);
424461
db_reset(&q2);
425
- printf("blob\nmark :%d\ndata %d\n", BLOBMARK(rid), blob_size(&content));
462
+ zMark = mark_name_from_rid(rid, &unused_mark);
463
+ printf("blob\nmark %s\ndata %d\n", zMark, blob_size(&content));
464
+ free(zMark);
426465
bag_insert(&blobs, rid);
427466
fwrite(blob_buffer(&content), 1, blob_size(&content), stdout);
428467
printf("\n");
429468
blob_reset(&content);
430469
@@ -470,11 +509,11 @@
470509
if( zBranch==0 ) zBranch = "trunk";
471510
zBr = mprintf("%s", zBranch);
472511
for(i=0; zBr[i]; i++){
473512
if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_';
474513
}
475
- zMark = mark_name_from_rid(ckinId);
514
+ zMark = mark_name_from_rid(ckinId, &unused_mark);
476515
printf("commit refs/heads/%s\nmark %s\n", zBr, zMark);
477516
free(zMark);
478517
free(zBr);
479518
printf("committer");
480519
print_person(zUser);
@@ -487,21 +526,21 @@
487526
" AND pid IN (SELECT objid FROM event)",
488527
ckinId
489528
);
490529
if( db_step(&q3) == SQLITE_ROW ){
491530
int pid = db_column_int(&q3, 0);
492
- zMark = mark_name_from_rid(pid);
531
+ zMark = mark_name_from_rid(pid, &unused_mark);
493532
printf("from %s\n", zMark);
494533
free(zMark);
495534
db_prepare(&q4,
496535
"SELECT pid FROM plink"
497536
" WHERE cid=%d AND NOT isprim"
498537
" AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)"
499538
" ORDER BY pid",
500539
ckinId);
501540
while( db_step(&q4)==SQLITE_ROW ){
502
- zMark = mark_name_from_rid(db_column_int(&q4, 0));
541
+ zMark = mark_name_from_rid(db_column_int(&q4, 0), &unused_mark);
503542
printf("merge %s\n", zMark);
504543
free(zMark);
505544
}
506545
db_finalize(&q4);
507546
}else{
@@ -516,20 +555,22 @@
516555
);
517556
while( db_step(&q4)==SQLITE_ROW ){
518557
const char *zName = db_column_text(&q4,0);
519558
int zNew = db_column_int(&q4,1);
520559
int mPerm = db_column_int(&q4,2);
521
- if( zNew==0)
560
+ if( zNew==0 ){
522561
printf("D %s\n", zName);
523
- else if( bag_find(&blobs, zNew) ) {
562
+ }else if( bag_find(&blobs, zNew) ){
524563
const char *zPerm;
564
+ zMark = mark_name_from_rid(zNew, &unused_mark);
525565
switch( mPerm ){
526566
case PERM_LNK: zPerm = "120000"; break;
527567
case PERM_EXE: zPerm = "100755"; break;
528568
default: zPerm = "100644"; break;
529569
}
530
- printf("M %s :%d %s\n", zPerm, BLOBMARK(zNew), zName);
570
+ printf("M %s %s %s\n", zPerm, zMark, zName);
571
+ free(zMark);
531572
}
532573
}
533574
db_finalize(&q4);
534575
db_finalize(&q3);
535576
printf("\n");
@@ -547,20 +588,22 @@
547588
);
548589
while( db_step(&q)==SQLITE_ROW ){
549590
const char *zTagname = db_column_text(&q, 0);
550591
char *zEncoded = 0;
551592
int rid = db_column_int(&q, 1);
593
+ char *zMark = mark_name_from_rid(rid, &unused_mark);
552594
const char *zSecSince1970 = db_column_text(&q, 2);
553595
int i;
554596
if( rid==0 || !bag_find(&vers, rid) ) continue;
555597
zTagname += 4;
556598
zEncoded = mprintf("%s", zTagname);
557599
for(i=0; zEncoded[i]; i++){
558600
if( !fossil_isalnum(zEncoded[i]) ) zEncoded[i] = '_';
559601
}
560602
printf("tag %s\n", zEncoded);
561
- printf("from :%d\n", COMMITMARK(rid));
603
+ printf("from %s\n", zMark);
604
+ free(zMark);
562605
printf("tagger <tagger> %s +0000\n", zSecSince1970);
563606
printf("data 0\n");
564607
fossil_free(zEncoded);
565608
}
566609
db_finalize(&q);
@@ -570,12 +613,12 @@
570613
f = fossil_fopen(markfile_out, "w");
571614
if( f == 0 ){
572615
fossil_fatal("cannot open %s for writing", markfile_out);
573616
}
574617
export_marks(f, &blobs, &vers);
575
- if( ferror(f)!=0 || fclose(f)!=0 ) {
618
+ if( ferror(f)!=0 || fclose(f)!=0 ){
576619
fossil_fatal("error while writing %s", markfile_out);
577620
}
578621
}
579622
bag_clear(&blobs);
580623
bag_clear(&vers);
581624
}
582625
--- src/export.c
+++ src/export.c
@@ -132,23 +132,28 @@
132
133 /*
134 ** create_mark()
135 ** Create a new (mark,rid,uuid) entry for the given rid in the 'xmark' table,
136 ** and return that information as a struct mark_t in *mark.
 
 
 
 
137 ** This function returns -1 in the case where 'rid' does not exist, otherwise
138 ** it returns 0.
139 ** mark->name is dynamically allocated and is owned by the caller upon return.
140 */
141 int create_mark(int rid, struct mark_t *mark){
142 char sid[13];
143 char *zUuid = rid_to_uuid(rid);
144 if(!zUuid){
145 fossil_trace("Undefined rid=%d\n", rid);
146 return -1;
147 }
148 mark->rid = rid;
149 sqlite3_snprintf(sizeof(sid), sid, ":%d", COMMITMARK(rid));
 
150 mark->name = fossil_strdup(sid);
151 sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", zUuid);
152 free(zUuid);
153 insert_commit_xref(mark->rid, mark->name, mark->uuid);
154 return 0;
@@ -156,19 +161,22 @@
156
157 /*
158 ** mark_name_from_rid()
159 ** Find the mark associated with the given rid. Mark names always start
160 ** with ':', and are pulled from the 'xmark' temporary table.
161 ** This function returns NULL if the rid does not exist in the 'xmark' table.
162 ** Otherwise, it returns the name of the mark, which is dynamically allocated
163 ** and is owned by the caller of this function.
 
 
 
164 */
165 char * mark_name_from_rid(int rid){
166 char *zMark = db_text(0, "SELECT tname FROM xmark WHERE trid=%d", rid);
167 if(zMark==NULL){
168 struct mark_t mark;
169 if(create_mark(rid, &mark)==0){
170 zMark = mark.name;
171 }else{
172 return NULL;
173 }
174 }
@@ -185,43 +193,52 @@
185 ** database. Otherwise, 0 is returned.
186 ** mark->name is dynamically allocated, and owned by the caller.
187 */
188 int parse_mark(char *line, struct mark_t *mark){
189 char *cur_tok;
 
190 cur_tok = strtok(line, " \t");
191 if(!cur_tok||strlen(cur_tok)<2){
192 return -1;
193 }
194 mark->rid = atoi(&cur_tok[1]);
195 if(cur_tok[0]!='c'){
 
196 /* This is probably a blob mark */
197 mark->name = NULL;
198 return 0;
199 }
200
201 cur_tok = strtok(NULL, " \t");
202 if(!cur_tok){
203 /* This mark was generated by an older version of Fossil and doesn't
204 ** include the mark name and uuid. create_mark() will name the new mark
205 ** exactly as it was when exported to git, so that we should have a
206 ** valid mapping from git sha1<->mark name<->fossil sha1. */
207 return create_mark(mark->rid, mark);
 
 
 
 
 
 
 
208 }else{
209 mark->name = fossil_strdup(cur_tok);
210 }
211
212 cur_tok = strtok(NULL, "\n");
213 if(!cur_tok||strlen(cur_tok)!=40){
214 free(mark->name);
215 fossil_trace("Invalid SHA-1 in marks file: %s\n", cur_tok);
216 return -1;
217 }else{
218 sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", cur_tok);
219 }
220
221 /* make sure that rid corresponds to UUID */
222 if(fast_uuid_to_rid(mark->uuid)!=mark->rid){
223 free(mark->name);
224 fossil_trace("Non-existent SHA-1 in marks file: %s\n", mark->uuid);
225 return -1;
226 }
227
@@ -233,40 +250,66 @@
233 /*
234 ** import_marks()
235 ** Import the marks specified in file 'f' into the 'xmark' table.
236 ** If 'blobs' is non-null, insert all blob marks into it.
237 ** If 'vers' is non-null, insert all commit marks into it.
 
 
 
238 ** Each line in the file must be at most 100 characters in length. This
239 ** seems like a reasonable maximum for a 40-character uuid, and 1-13
240 ** character rid.
241 ** The function returns -1 if any of the lines in file 'f' are malformed,
242 ** or the rid/uuid information doesn't match what is in the repository
243 ** database. Otherwise, 0 is returned.
244 */
245 int import_marks(FILE* f, Bag *blobs, Bag *vers){
246 char line[101];
247 while(fgets(line, sizeof(line), f)){
248 struct mark_t mark;
249 if(strlen(line)==100&&line[99]!='\n'){
250 /* line too long */
251 return -1;
252 }
253 if( parse_mark(line, &mark)<0 ){
254 return -1;
255 }else if( line[0]=='b' ){
256 /* Don't import blob marks into 'xmark' table--git doesn't use them,
257 ** so they need to be left free for git to reuse. */
258 if(blobs!=NULL){
259 bag_insert(blobs, mark.rid);
260 }
261 }else if( vers!=NULL ){
262 bag_insert(vers, mark.rid);
 
 
 
 
 
 
 
 
263 }
264 free(mark.name);
265 }
266 return 0;
267 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
269 /*
270 ** If 'blobs' is non-null, it must point to a Bag of blob rids to be
271 ** written to disk. Blob rids are written as 'b<rid>'.
272 ** If 'vers' is non-null, it must point to a Bag of commit rids to be
@@ -275,32 +318,24 @@
275 ** This function does not fail, but may produce errors if a uuid cannot
276 ** be found for an rid in 'vers'.
277 */
278 void export_marks(FILE* f, Bag *blobs, Bag *vers){
279 int rid;
 
280 if( blobs!=NULL ){
281 rid = bag_first(blobs);
282 if(rid!=0){
283 do{
284 fprintf(f, "b%d\n", rid);
285 }while((rid = bag_next(blobs, rid))!=0);
286 }
287 }
288 if( vers!=NULL ){
289 rid = bag_first(vers);
290 if( rid!=0 ){
291 do{
292 char *zUuid = rid_to_uuid(rid);
293 char *zMark;
294 if(zUuid==NULL){
295 fossil_trace("No uuid matching rid=%d when exporting marks\n", rid);
296 continue;
297 }
298 zMark = mark_name_from_rid(rid);
299 fprintf(f, "c%d %s %s\n", rid, zMark, zUuid);
300 free(zMark);
301 free(zUuid);
302 }while( (rid = bag_next(vers, rid))!=0 );
303 }
304 }
305 }
306
@@ -336,10 +371,11 @@
336 */
337 void export_cmd(void){
338 Stmt q, q2, q3;
339 int i;
340 Bag blobs, vers;
 
341 const char *markfile_in;
342 const char *markfile_out;
343
344 bag_init(&blobs);
345 bag_init(&vers);
@@ -362,25 +398,25 @@
362
363 f = fossil_fopen(markfile_in, "r");
364 if( f==0 ){
365 fossil_fatal("cannot open %s for reading", markfile_in);
366 }
367 if(import_marks(f, &blobs, &vers)<0){
368 fossil_fatal("error importing marks from file: %s", markfile_in);
369 }
370 db_prepare(&qb, "INSERT OR IGNORE INTO oldblob VALUES (:rid)");
371 db_prepare(&qc, "INSERT OR IGNORE INTO oldcommit VALUES (:rid)");
372 rid = bag_first(&blobs);
373 if(rid!=0){
374 do{
375 db_bind_int(&qb, ":rid", rid);
376 db_step(&qb);
377 db_reset(&qb);
378 }while((rid = bag_next(&blobs, rid))!=0);
379 }
380 rid = bag_first(&vers);
381 if(rid!=0){
382 do{
383 db_bind_int(&qc, ":rid", rid);
384 db_step(&qc);
385 db_reset(&qc);
386 }while((rid = bag_next(&vers, rid))!=0);
@@ -416,15 +452,18 @@
416 while( db_step(&q)==SQLITE_ROW ){
417 int rid = db_column_int(&q, 0);
418 Blob content;
419
420 while( !bag_find(&blobs, rid) ){
 
421 content_get(rid, &content);
422 db_bind_int(&q2, ":rid", rid);
423 db_step(&q2);
424 db_reset(&q2);
425 printf("blob\nmark :%d\ndata %d\n", BLOBMARK(rid), blob_size(&content));
 
 
426 bag_insert(&blobs, rid);
427 fwrite(blob_buffer(&content), 1, blob_size(&content), stdout);
428 printf("\n");
429 blob_reset(&content);
430
@@ -470,11 +509,11 @@
470 if( zBranch==0 ) zBranch = "trunk";
471 zBr = mprintf("%s", zBranch);
472 for(i=0; zBr[i]; i++){
473 if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_';
474 }
475 zMark = mark_name_from_rid(ckinId);
476 printf("commit refs/heads/%s\nmark %s\n", zBr, zMark);
477 free(zMark);
478 free(zBr);
479 printf("committer");
480 print_person(zUser);
@@ -487,21 +526,21 @@
487 " AND pid IN (SELECT objid FROM event)",
488 ckinId
489 );
490 if( db_step(&q3) == SQLITE_ROW ){
491 int pid = db_column_int(&q3, 0);
492 zMark = mark_name_from_rid(pid);
493 printf("from %s\n", zMark);
494 free(zMark);
495 db_prepare(&q4,
496 "SELECT pid FROM plink"
497 " WHERE cid=%d AND NOT isprim"
498 " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)"
499 " ORDER BY pid",
500 ckinId);
501 while( db_step(&q4)==SQLITE_ROW ){
502 zMark = mark_name_from_rid(db_column_int(&q4, 0));
503 printf("merge %s\n", zMark);
504 free(zMark);
505 }
506 db_finalize(&q4);
507 }else{
@@ -516,20 +555,22 @@
516 );
517 while( db_step(&q4)==SQLITE_ROW ){
518 const char *zName = db_column_text(&q4,0);
519 int zNew = db_column_int(&q4,1);
520 int mPerm = db_column_int(&q4,2);
521 if( zNew==0)
522 printf("D %s\n", zName);
523 else if( bag_find(&blobs, zNew) ) {
524 const char *zPerm;
 
525 switch( mPerm ){
526 case PERM_LNK: zPerm = "120000"; break;
527 case PERM_EXE: zPerm = "100755"; break;
528 default: zPerm = "100644"; break;
529 }
530 printf("M %s :%d %s\n", zPerm, BLOBMARK(zNew), zName);
 
531 }
532 }
533 db_finalize(&q4);
534 db_finalize(&q3);
535 printf("\n");
@@ -547,20 +588,22 @@
547 );
548 while( db_step(&q)==SQLITE_ROW ){
549 const char *zTagname = db_column_text(&q, 0);
550 char *zEncoded = 0;
551 int rid = db_column_int(&q, 1);
 
552 const char *zSecSince1970 = db_column_text(&q, 2);
553 int i;
554 if( rid==0 || !bag_find(&vers, rid) ) continue;
555 zTagname += 4;
556 zEncoded = mprintf("%s", zTagname);
557 for(i=0; zEncoded[i]; i++){
558 if( !fossil_isalnum(zEncoded[i]) ) zEncoded[i] = '_';
559 }
560 printf("tag %s\n", zEncoded);
561 printf("from :%d\n", COMMITMARK(rid));
 
562 printf("tagger <tagger> %s +0000\n", zSecSince1970);
563 printf("data 0\n");
564 fossil_free(zEncoded);
565 }
566 db_finalize(&q);
@@ -570,12 +613,12 @@
570 f = fossil_fopen(markfile_out, "w");
571 if( f == 0 ){
572 fossil_fatal("cannot open %s for writing", markfile_out);
573 }
574 export_marks(f, &blobs, &vers);
575 if( ferror(f)!=0 || fclose(f)!=0 ) {
576 fossil_fatal("error while writing %s", markfile_out);
577 }
578 }
579 bag_clear(&blobs);
580 bag_clear(&vers);
581 }
582
--- src/export.c
+++ src/export.c
@@ -132,23 +132,28 @@
132
133 /*
134 ** create_mark()
135 ** Create a new (mark,rid,uuid) entry for the given rid in the 'xmark' table,
136 ** and return that information as a struct mark_t in *mark.
137 ** *unused_mark is a value representing a mark that is free for use--that is,
138 ** it does not appear in the marks file, and has not been used during this
139 ** export run. Specifically, it is the supremum of the set of used marks
140 ** plus one.
141 ** This function returns -1 in the case where 'rid' does not exist, otherwise
142 ** it returns 0.
143 ** mark->name is dynamically allocated and is owned by the caller upon return.
144 */
145 int create_mark(int rid, struct mark_t *mark, unsigned int *unused_mark){
146 char sid[13];
147 char *zUuid = rid_to_uuid(rid);
148 if( !zUuid ){
149 fossil_trace("Undefined rid=%d\n", rid);
150 return -1;
151 }
152 mark->rid = rid;
153 sqlite3_snprintf(sizeof(sid), sid, ":%d", *unused_mark);
154 *unused_mark += 1;
155 mark->name = fossil_strdup(sid);
156 sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", zUuid);
157 free(zUuid);
158 insert_commit_xref(mark->rid, mark->name, mark->uuid);
159 return 0;
@@ -156,19 +161,22 @@
161
162 /*
163 ** mark_name_from_rid()
164 ** Find the mark associated with the given rid. Mark names always start
165 ** with ':', and are pulled from the 'xmark' temporary table.
166 ** If the given rid doesn't have a mark associated with it yet, one is
167 ** created with a value of *unused_mark.
168 ** *unused_mark functions exactly as in create_mark().
169 ** This function returns NULL if the rid does not have an associated UUID,
170 ** (i.e. is not valid). Otherwise, it returns the name of the mark, which is
171 ** dynamically allocated and is owned by the caller of this function.
172 */
173 char * mark_name_from_rid(int rid, unsigned int *unused_mark){
174 char *zMark = db_text(0, "SELECT tname FROM xmark WHERE trid=%d", rid);
175 if( zMark==NULL ){
176 struct mark_t mark;
177 if( create_mark(rid, &mark, unused_mark)==0 ){
178 zMark = mark.name;
179 }else{
180 return NULL;
181 }
182 }
@@ -185,43 +193,52 @@
193 ** database. Otherwise, 0 is returned.
194 ** mark->name is dynamically allocated, and owned by the caller.
195 */
196 int parse_mark(char *line, struct mark_t *mark){
197 char *cur_tok;
198 char type_;
199 cur_tok = strtok(line, " \t");
200 if( !cur_tok || strlen(cur_tok)<2 ){
201 return -1;
202 }
203 mark->rid = atoi(&cur_tok[1]);
204 type_ = cur_tok[0];
205 if( type_!='c' && type_!='b' ){
206 /* This is probably a blob mark */
207 mark->name = NULL;
208 return 0;
209 }
210
211 cur_tok = strtok(NULL, " \t");
212 if( !cur_tok ){
213 /* This mark was generated by an older version of Fossil and doesn't
214 ** include the mark name and uuid. create_mark() will name the new mark
215 ** exactly as it was when exported to git, so that we should have a
216 ** valid mapping from git sha1<->mark name<->fossil sha1. */
217 unsigned int mid;
218 if( type_=='c' ){
219 mid = COMMITMARK(mark->rid);
220 }
221 else{
222 mid = BLOBMARK(mark->rid);
223 }
224 return create_mark(mark->rid, mark, &mid);
225 }else{
226 mark->name = fossil_strdup(cur_tok);
227 }
228
229 cur_tok = strtok(NULL, "\n");
230 if( !cur_tok || strlen(cur_tok)!=40 ){
231 free(mark->name);
232 fossil_trace("Invalid SHA-1 in marks file: %s\n", cur_tok);
233 return -1;
234 }else{
235 sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", cur_tok);
236 }
237
238 /* make sure that rid corresponds to UUID */
239 if( fast_uuid_to_rid(mark->uuid)!=mark->rid ){
240 free(mark->name);
241 fossil_trace("Non-existent SHA-1 in marks file: %s\n", mark->uuid);
242 return -1;
243 }
244
@@ -233,40 +250,66 @@
250 /*
251 ** import_marks()
252 ** Import the marks specified in file 'f' into the 'xmark' table.
253 ** If 'blobs' is non-null, insert all blob marks into it.
254 ** If 'vers' is non-null, insert all commit marks into it.
255 ** If 'unused_marks' is non-null, upon return of this function, all values
256 ** x >= *unused_marks are free to use as marks, i.e. they do not clash with
257 ** any marks appearing in the marks file.
258 ** Each line in the file must be at most 100 characters in length. This
259 ** seems like a reasonable maximum for a 40-character uuid, and 1-13
260 ** character rid.
261 ** The function returns -1 if any of the lines in file 'f' are malformed,
262 ** or the rid/uuid information doesn't match what is in the repository
263 ** database. Otherwise, 0 is returned.
264 */
265 int import_marks(FILE* f, Bag *blobs, Bag *vers, unsigned int *unused_mark){
266 char line[101];
267 while(fgets(line, sizeof(line), f)){
268 struct mark_t mark;
269 if( strlen(line)==100 && line[99]!='\n' ){
270 /* line too long */
271 return -1;
272 }
273 if( parse_mark(line, &mark)<0 ){
274 return -1;
275 }else if( line[0]=='b' ){
276 if( blobs!=NULL ){
 
 
277 bag_insert(blobs, mark.rid);
278 }
279 }else{
280 if( vers!=NULL ){
281 bag_insert(vers, mark.rid);
282 }
283 }
284 if( unused_mark!=NULL ){
285 unsigned int mid = atoi(mark.name + 1);
286 if( mid>=*unused_mark ){
287 *unused_mark = mid + 1;
288 }
289 }
290 free(mark.name);
291 }
292 return 0;
293 }
294
295 void export_mark(FILE* f, int rid, char obj_type)
296 {
297 unsigned int z = 0;
298 char *zUuid = rid_to_uuid(rid);
299 char *zMark;
300 if( zUuid==NULL ){
301 fossil_trace("No uuid matching rid=%d when exporting marks\n", rid);
302 return;
303 }
304 /* Since rid is already in the 'xmark' table, the value of z won't be
305 ** used, but pass in a valid pointer just to be safe. */
306 zMark = mark_name_from_rid(rid, &z);
307 fprintf(f, "%c%d %s %s\n", obj_type, rid, zMark, zUuid);
308 free(zMark);
309 free(zUuid);
310 }
311
312 /*
313 ** If 'blobs' is non-null, it must point to a Bag of blob rids to be
314 ** written to disk. Blob rids are written as 'b<rid>'.
315 ** If 'vers' is non-null, it must point to a Bag of commit rids to be
@@ -275,32 +318,24 @@
318 ** This function does not fail, but may produce errors if a uuid cannot
319 ** be found for an rid in 'vers'.
320 */
321 void export_marks(FILE* f, Bag *blobs, Bag *vers){
322 int rid;
323
324 if( blobs!=NULL ){
325 rid = bag_first(blobs);
326 if( rid!=0 ){
327 do{
328 export_mark(f, rid, 'b');
329 }while( (rid = bag_next(blobs, rid))!=0 );
330 }
331 }
332 if( vers!=NULL ){
333 rid = bag_first(vers);
334 if( rid!=0 ){
335 do{
336 export_mark(f, rid, 'c');
 
 
 
 
 
 
 
 
 
337 }while( (rid = bag_next(vers, rid))!=0 );
338 }
339 }
340 }
341
@@ -336,10 +371,11 @@
371 */
372 void export_cmd(void){
373 Stmt q, q2, q3;
374 int i;
375 Bag blobs, vers;
376 unsigned int unused_mark = 1;
377 const char *markfile_in;
378 const char *markfile_out;
379
380 bag_init(&blobs);
381 bag_init(&vers);
@@ -362,25 +398,25 @@
398
399 f = fossil_fopen(markfile_in, "r");
400 if( f==0 ){
401 fossil_fatal("cannot open %s for reading", markfile_in);
402 }
403 if( import_marks(f, &blobs, &vers, &unused_mark)<0 ){
404 fossil_fatal("error importing marks from file: %s", markfile_in);
405 }
406 db_prepare(&qb, "INSERT OR IGNORE INTO oldblob VALUES (:rid)");
407 db_prepare(&qc, "INSERT OR IGNORE INTO oldcommit VALUES (:rid)");
408 rid = bag_first(&blobs);
409 if( rid!=0 ){
410 do{
411 db_bind_int(&qb, ":rid", rid);
412 db_step(&qb);
413 db_reset(&qb);
414 }while((rid = bag_next(&blobs, rid))!=0);
415 }
416 rid = bag_first(&vers);
417 if( rid!=0 ){
418 do{
419 db_bind_int(&qc, ":rid", rid);
420 db_step(&qc);
421 db_reset(&qc);
422 }while((rid = bag_next(&vers, rid))!=0);
@@ -416,15 +452,18 @@
452 while( db_step(&q)==SQLITE_ROW ){
453 int rid = db_column_int(&q, 0);
454 Blob content;
455
456 while( !bag_find(&blobs, rid) ){
457 char *zMark;
458 content_get(rid, &content);
459 db_bind_int(&q2, ":rid", rid);
460 db_step(&q2);
461 db_reset(&q2);
462 zMark = mark_name_from_rid(rid, &unused_mark);
463 printf("blob\nmark %s\ndata %d\n", zMark, blob_size(&content));
464 free(zMark);
465 bag_insert(&blobs, rid);
466 fwrite(blob_buffer(&content), 1, blob_size(&content), stdout);
467 printf("\n");
468 blob_reset(&content);
469
@@ -470,11 +509,11 @@
509 if( zBranch==0 ) zBranch = "trunk";
510 zBr = mprintf("%s", zBranch);
511 for(i=0; zBr[i]; i++){
512 if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_';
513 }
514 zMark = mark_name_from_rid(ckinId, &unused_mark);
515 printf("commit refs/heads/%s\nmark %s\n", zBr, zMark);
516 free(zMark);
517 free(zBr);
518 printf("committer");
519 print_person(zUser);
@@ -487,21 +526,21 @@
526 " AND pid IN (SELECT objid FROM event)",
527 ckinId
528 );
529 if( db_step(&q3) == SQLITE_ROW ){
530 int pid = db_column_int(&q3, 0);
531 zMark = mark_name_from_rid(pid, &unused_mark);
532 printf("from %s\n", zMark);
533 free(zMark);
534 db_prepare(&q4,
535 "SELECT pid FROM plink"
536 " WHERE cid=%d AND NOT isprim"
537 " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)"
538 " ORDER BY pid",
539 ckinId);
540 while( db_step(&q4)==SQLITE_ROW ){
541 zMark = mark_name_from_rid(db_column_int(&q4, 0), &unused_mark);
542 printf("merge %s\n", zMark);
543 free(zMark);
544 }
545 db_finalize(&q4);
546 }else{
@@ -516,20 +555,22 @@
555 );
556 while( db_step(&q4)==SQLITE_ROW ){
557 const char *zName = db_column_text(&q4,0);
558 int zNew = db_column_int(&q4,1);
559 int mPerm = db_column_int(&q4,2);
560 if( zNew==0 ){
561 printf("D %s\n", zName);
562 }else if( bag_find(&blobs, zNew) ){
563 const char *zPerm;
564 zMark = mark_name_from_rid(zNew, &unused_mark);
565 switch( mPerm ){
566 case PERM_LNK: zPerm = "120000"; break;
567 case PERM_EXE: zPerm = "100755"; break;
568 default: zPerm = "100644"; break;
569 }
570 printf("M %s %s %s\n", zPerm, zMark, zName);
571 free(zMark);
572 }
573 }
574 db_finalize(&q4);
575 db_finalize(&q3);
576 printf("\n");
@@ -547,20 +588,22 @@
588 );
589 while( db_step(&q)==SQLITE_ROW ){
590 const char *zTagname = db_column_text(&q, 0);
591 char *zEncoded = 0;
592 int rid = db_column_int(&q, 1);
593 char *zMark = mark_name_from_rid(rid, &unused_mark);
594 const char *zSecSince1970 = db_column_text(&q, 2);
595 int i;
596 if( rid==0 || !bag_find(&vers, rid) ) continue;
597 zTagname += 4;
598 zEncoded = mprintf("%s", zTagname);
599 for(i=0; zEncoded[i]; i++){
600 if( !fossil_isalnum(zEncoded[i]) ) zEncoded[i] = '_';
601 }
602 printf("tag %s\n", zEncoded);
603 printf("from %s\n", zMark);
604 free(zMark);
605 printf("tagger <tagger> %s +0000\n", zSecSince1970);
606 printf("data 0\n");
607 fossil_free(zEncoded);
608 }
609 db_finalize(&q);
@@ -570,12 +613,12 @@
613 f = fossil_fopen(markfile_out, "w");
614 if( f == 0 ){
615 fossil_fatal("cannot open %s for writing", markfile_out);
616 }
617 export_marks(f, &blobs, &vers);
618 if( ferror(f)!=0 || fclose(f)!=0 ){
619 fossil_fatal("error while writing %s", markfile_out);
620 }
621 }
622 bag_clear(&blobs);
623 bag_clear(&vers);
624 }
625
+2 -6
--- src/fusefs.c
+++ src/fusefs.c
@@ -20,20 +20,20 @@
2020
**
2121
** This module is a mostly a no-op unless compiled with -DFOSSIL_HAVE_FUSEFS.
2222
** The FOSSIL_HAVE_FUSEFS should be omitted on systems that lack support for
2323
** the Fuse Filesystem, of course.
2424
*/
25
+#ifdef FOSSIL_HAVE_FUSEFS
2526
#include "config.h"
2627
#include <stdio.h>
2728
#include <string.h>
2829
#include <errno.h>
2930
#include <fcntl.h>
3031
#include <stdlib.h>
3132
#include <unistd.h>
3233
#include <sys/types.h>
3334
#include "fusefs.h"
34
-#ifdef FOSSIL_HAVE_FUSEFS
3535
3636
#define FUSE_USE_VERSION 26
3737
#include <fuse.h>
3838
3939
/*
@@ -283,11 +283,10 @@
283283
static struct fuse_operations fusefs_methods = {
284284
.getattr = fusefs_getattr,
285285
.readdir = fusefs_readdir,
286286
.read = fusefs_read,
287287
};
288
-#endif /* FOSSIL_HAVE_FUSEFS */
289288
290289
/*
291290
** COMMAND: fusefs
292291
**
293292
** Usage: %fossil fusefs [--debug] DIRECTORY
@@ -315,13 +314,10 @@
315314
** After stopping the "fossil fusefs" command, it might also be necessary
316315
** to run "fusermount -u DIRECTORY" to reset the FuseFS before using it
317316
** again.
318317
*/
319318
void fusefs_cmd(void){
320
-#ifndef FOSSIL_HAVE_FUSEFS
321
- fossil_fatal("this build of fossil does not support the fuse filesystem");
322
-#else
323319
char *zMountPoint;
324320
char *azNewArgv[5];
325321
int doDebug = find_option("debug","d",0)!=0;
326322
327323
db_find_and_open_repository(0,0);
@@ -339,7 +335,7 @@
339335
azNewArgv[4] = 0;
340336
g.localOpen = 0; /* Prevent tags like "current" and "prev" */
341337
fuse_main(4, azNewArgv, &fusefs_methods, NULL);
342338
fusefs_reset();
343339
fusefs_clear_path();
344
-#endif
345340
}
341
+#endif /* FOSSIL_HAVE_FUSEFS */
346342
--- src/fusefs.c
+++ src/fusefs.c
@@ -20,20 +20,20 @@
20 **
21 ** This module is a mostly a no-op unless compiled with -DFOSSIL_HAVE_FUSEFS.
22 ** The FOSSIL_HAVE_FUSEFS should be omitted on systems that lack support for
23 ** the Fuse Filesystem, of course.
24 */
 
25 #include "config.h"
26 #include <stdio.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <sys/types.h>
33 #include "fusefs.h"
34 #ifdef FOSSIL_HAVE_FUSEFS
35
36 #define FUSE_USE_VERSION 26
37 #include <fuse.h>
38
39 /*
@@ -283,11 +283,10 @@
283 static struct fuse_operations fusefs_methods = {
284 .getattr = fusefs_getattr,
285 .readdir = fusefs_readdir,
286 .read = fusefs_read,
287 };
288 #endif /* FOSSIL_HAVE_FUSEFS */
289
290 /*
291 ** COMMAND: fusefs
292 **
293 ** Usage: %fossil fusefs [--debug] DIRECTORY
@@ -315,13 +314,10 @@
315 ** After stopping the "fossil fusefs" command, it might also be necessary
316 ** to run "fusermount -u DIRECTORY" to reset the FuseFS before using it
317 ** again.
318 */
319 void fusefs_cmd(void){
320 #ifndef FOSSIL_HAVE_FUSEFS
321 fossil_fatal("this build of fossil does not support the fuse filesystem");
322 #else
323 char *zMountPoint;
324 char *azNewArgv[5];
325 int doDebug = find_option("debug","d",0)!=0;
326
327 db_find_and_open_repository(0,0);
@@ -339,7 +335,7 @@
339 azNewArgv[4] = 0;
340 g.localOpen = 0; /* Prevent tags like "current" and "prev" */
341 fuse_main(4, azNewArgv, &fusefs_methods, NULL);
342 fusefs_reset();
343 fusefs_clear_path();
344 #endif
345 }
 
346
--- src/fusefs.c
+++ src/fusefs.c
@@ -20,20 +20,20 @@
20 **
21 ** This module is a mostly a no-op unless compiled with -DFOSSIL_HAVE_FUSEFS.
22 ** The FOSSIL_HAVE_FUSEFS should be omitted on systems that lack support for
23 ** the Fuse Filesystem, of course.
24 */
25 #ifdef FOSSIL_HAVE_FUSEFS
26 #include "config.h"
27 #include <stdio.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <sys/types.h>
34 #include "fusefs.h"
 
35
36 #define FUSE_USE_VERSION 26
37 #include <fuse.h>
38
39 /*
@@ -283,11 +283,10 @@
283 static struct fuse_operations fusefs_methods = {
284 .getattr = fusefs_getattr,
285 .readdir = fusefs_readdir,
286 .read = fusefs_read,
287 };
 
288
289 /*
290 ** COMMAND: fusefs
291 **
292 ** Usage: %fossil fusefs [--debug] DIRECTORY
@@ -315,13 +314,10 @@
314 ** After stopping the "fossil fusefs" command, it might also be necessary
315 ** to run "fusermount -u DIRECTORY" to reset the FuseFS before using it
316 ** again.
317 */
318 void fusefs_cmd(void){
 
 
 
319 char *zMountPoint;
320 char *azNewArgv[5];
321 int doDebug = find_option("debug","d",0)!=0;
322
323 db_find_and_open_repository(0,0);
@@ -339,7 +335,7 @@
335 azNewArgv[4] = 0;
336 g.localOpen = 0; /* Prevent tags like "current" and "prev" */
337 fuse_main(4, azNewArgv, &fusefs_methods, NULL);
338 fusefs_reset();
339 fusefs_clear_path();
 
340 }
341 #endif /* FOSSIL_HAVE_FUSEFS */
342
+19 -4
--- src/graph.c
+++ src/graph.c
@@ -258,11 +258,10 @@
258258
int iRail = pBottom->iRail;
259259
GraphRow *pCurrent;
260260
GraphRow *pPrior;
261261
u64 mask = ((u64)1)<<iRail;
262262
263
- pBottom->iRail = iRail;
264263
pBottom->railInUse |= mask;
265264
pPrior = pBottom;
266265
for(pCurrent=pBottom->pChild; pCurrent; pCurrent=pCurrent->pChild){
267266
assert( pPrior->idx > pCurrent->idx );
268267
assert( pCurrent->iRail<0 );
@@ -344,14 +343,16 @@
344343
/*
345344
** Compute the complete graph
346345
*/
347346
void graph_finish(GraphContext *p, int omitDescenders){
348347
GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent;
349
- int i;
348
+ int i, j;
350349
u64 mask;
351350
int hasDup = 0; /* True if one or more isDup entries */
352351
const char *zTrunk;
352
+ int railRid[GR_MAX_RAIL]; /* Maps rails to rids for lines
353
+ that enter from bottom of screen */
353354
354355
if( p==0 || p->pFirst==0 || p->nErr ) return;
355356
p->nErr = 1; /* Assume an error until proven otherwise */
356357
357358
/* Initialize all rows */
@@ -366,10 +367,11 @@
366367
pDup->isDup = 1;
367368
}
368369
hashInsert(p, pRow, 1);
369370
}
370371
p->mxRail = -1;
372
+ memset(railRid, 0, sizeof(railRid));
371373
372374
/* Purge merge-parents that are out-of-graph if descenders are not
373375
** drawn.
374376
**
375377
** Each node has one primary parent and zero or more "merge" parents.
@@ -458,10 +460,13 @@
458460
}
459461
if( p->mxRail>=GR_MAX_RAIL ) return;
460462
mask = BIT(pRow->iRail);
461463
if( !omitDescenders ){
462464
pRow->bDescender = pRow->nParent>0;
465
+ if( pRow->bDescender ){
466
+ railRid[pRow->iRail] = pRow->aParent[0];
467
+ }
463468
for(pLoop=pRow; pLoop; pLoop=pLoop->pNext){
464469
pLoop->railInUse |= mask;
465470
}
466471
}
467472
assignChildrenToRail(pRow);
@@ -536,12 +541,22 @@
536541
for(i=1; i<pRow->nParent; i++){
537542
int parentRid = pRow->aParent[i];
538543
pDesc = hashFind(p, parentRid);
539544
if( pDesc==0 ){
540545
/* Merge from a node that is off-screen */
541
- int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0);
542
- if( p->mxRail>=GR_MAX_RAIL ) return;
546
+ int iMrail = -1;
547
+ for(j=0; j<GR_MAX_RAIL; j++){
548
+ if( railRid[j]==parentRid ){
549
+ iMrail = j;
550
+ break;
551
+ }
552
+ }
553
+ if( iMrail==-1 ){
554
+ iMrail = findFreeRail(p, pRow->idx, p->nRow, 0);
555
+ if( p->mxRail>=GR_MAX_RAIL ) return;
556
+ railRid[iMrail] = parentRid;
557
+ }
543558
mask = BIT(iMrail);
544559
pRow->mergeIn[iMrail] = 1;
545560
pRow->mergeDown |= mask;
546561
for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){
547562
pLoop->railInUse |= mask;
548563
--- src/graph.c
+++ src/graph.c
@@ -258,11 +258,10 @@
258 int iRail = pBottom->iRail;
259 GraphRow *pCurrent;
260 GraphRow *pPrior;
261 u64 mask = ((u64)1)<<iRail;
262
263 pBottom->iRail = iRail;
264 pBottom->railInUse |= mask;
265 pPrior = pBottom;
266 for(pCurrent=pBottom->pChild; pCurrent; pCurrent=pCurrent->pChild){
267 assert( pPrior->idx > pCurrent->idx );
268 assert( pCurrent->iRail<0 );
@@ -344,14 +343,16 @@
344 /*
345 ** Compute the complete graph
346 */
347 void graph_finish(GraphContext *p, int omitDescenders){
348 GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent;
349 int i;
350 u64 mask;
351 int hasDup = 0; /* True if one or more isDup entries */
352 const char *zTrunk;
 
 
353
354 if( p==0 || p->pFirst==0 || p->nErr ) return;
355 p->nErr = 1; /* Assume an error until proven otherwise */
356
357 /* Initialize all rows */
@@ -366,10 +367,11 @@
366 pDup->isDup = 1;
367 }
368 hashInsert(p, pRow, 1);
369 }
370 p->mxRail = -1;
 
371
372 /* Purge merge-parents that are out-of-graph if descenders are not
373 ** drawn.
374 **
375 ** Each node has one primary parent and zero or more "merge" parents.
@@ -458,10 +460,13 @@
458 }
459 if( p->mxRail>=GR_MAX_RAIL ) return;
460 mask = BIT(pRow->iRail);
461 if( !omitDescenders ){
462 pRow->bDescender = pRow->nParent>0;
 
 
 
463 for(pLoop=pRow; pLoop; pLoop=pLoop->pNext){
464 pLoop->railInUse |= mask;
465 }
466 }
467 assignChildrenToRail(pRow);
@@ -536,12 +541,22 @@
536 for(i=1; i<pRow->nParent; i++){
537 int parentRid = pRow->aParent[i];
538 pDesc = hashFind(p, parentRid);
539 if( pDesc==0 ){
540 /* Merge from a node that is off-screen */
541 int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0);
542 if( p->mxRail>=GR_MAX_RAIL ) return;
 
 
 
 
 
 
 
 
 
 
543 mask = BIT(iMrail);
544 pRow->mergeIn[iMrail] = 1;
545 pRow->mergeDown |= mask;
546 for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){
547 pLoop->railInUse |= mask;
548
--- src/graph.c
+++ src/graph.c
@@ -258,11 +258,10 @@
258 int iRail = pBottom->iRail;
259 GraphRow *pCurrent;
260 GraphRow *pPrior;
261 u64 mask = ((u64)1)<<iRail;
262
 
263 pBottom->railInUse |= mask;
264 pPrior = pBottom;
265 for(pCurrent=pBottom->pChild; pCurrent; pCurrent=pCurrent->pChild){
266 assert( pPrior->idx > pCurrent->idx );
267 assert( pCurrent->iRail<0 );
@@ -344,14 +343,16 @@
343 /*
344 ** Compute the complete graph
345 */
346 void graph_finish(GraphContext *p, int omitDescenders){
347 GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent;
348 int i, j;
349 u64 mask;
350 int hasDup = 0; /* True if one or more isDup entries */
351 const char *zTrunk;
352 int railRid[GR_MAX_RAIL]; /* Maps rails to rids for lines
353 that enter from bottom of screen */
354
355 if( p==0 || p->pFirst==0 || p->nErr ) return;
356 p->nErr = 1; /* Assume an error until proven otherwise */
357
358 /* Initialize all rows */
@@ -366,10 +367,11 @@
367 pDup->isDup = 1;
368 }
369 hashInsert(p, pRow, 1);
370 }
371 p->mxRail = -1;
372 memset(railRid, 0, sizeof(railRid));
373
374 /* Purge merge-parents that are out-of-graph if descenders are not
375 ** drawn.
376 **
377 ** Each node has one primary parent and zero or more "merge" parents.
@@ -458,10 +460,13 @@
460 }
461 if( p->mxRail>=GR_MAX_RAIL ) return;
462 mask = BIT(pRow->iRail);
463 if( !omitDescenders ){
464 pRow->bDescender = pRow->nParent>0;
465 if( pRow->bDescender ){
466 railRid[pRow->iRail] = pRow->aParent[0];
467 }
468 for(pLoop=pRow; pLoop; pLoop=pLoop->pNext){
469 pLoop->railInUse |= mask;
470 }
471 }
472 assignChildrenToRail(pRow);
@@ -536,12 +541,22 @@
541 for(i=1; i<pRow->nParent; i++){
542 int parentRid = pRow->aParent[i];
543 pDesc = hashFind(p, parentRid);
544 if( pDesc==0 ){
545 /* Merge from a node that is off-screen */
546 int iMrail = -1;
547 for(j=0; j<GR_MAX_RAIL; j++){
548 if( railRid[j]==parentRid ){
549 iMrail = j;
550 break;
551 }
552 }
553 if( iMrail==-1 ){
554 iMrail = findFreeRail(p, pRow->idx, p->nRow, 0);
555 if( p->mxRail>=GR_MAX_RAIL ) return;
556 railRid[iMrail] = parentRid;
557 }
558 mask = BIT(iMrail);
559 pRow->mergeIn[iMrail] = 1;
560 pRow->mergeDown |= mask;
561 for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){
562 pLoop->railInUse |= mask;
563
+5 -4
--- src/import.c
+++ src/import.c
@@ -1761,20 +1761,21 @@
17611761
** times but only the last tag should be used. And we do not know which
17621762
** occurrence of the tag is the last until the import finishes.
17631763
*/
17641764
db_multi_exec(
17651765
"CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT);"
1766
+ "CREATE INDEX temp.i_xmark ON xmark(trid);"
17661767
"CREATE TEMP TABLE xbranch(tname TEXT UNIQUE, brnm TEXT);"
17671768
"CREATE TEMP TABLE xtag(tname TEXT UNIQUE, tcontent TEXT);"
17681769
);
17691770
17701771
if( markfile_in ){
17711772
FILE *f = fossil_fopen(markfile_in, "r");
17721773
if( !f ){
17731774
fossil_fatal("cannot open %s for reading", markfile_in);
17741775
}
1775
- if(import_marks(f, &blobs, NULL)<0){
1776
+ if( import_marks(f, &blobs, NULL, NULL)<0 ){
17761777
fossil_fatal("error importing marks from file: %s", markfile_in);
17771778
}
17781779
fclose(f);
17791780
}
17801781
@@ -1795,13 +1796,13 @@
17951796
db_prepare(&q_marks, "SELECT DISTINCT trid FROM xmark");
17961797
while( db_step(&q_marks)==SQLITE_ROW ){
17971798
rid = db_column_int(&q_marks, 0);
17981799
if( db_int(0, "SELECT count(objid) FROM event"
17991800
" WHERE objid=%d AND type='ci'", rid)==0 ){
1800
- if( bag_find(&blobs, rid)==0 ){
1801
- bag_insert(&blobs, rid);
1802
- }
1801
+ /* Blob marks exported by git aren't saved between runs, so they need
1802
+ ** to be left free for git to re-use in the future.
1803
+ */
18031804
}else{
18041805
bag_insert(&vers, rid);
18051806
}
18061807
}
18071808
db_finalize(&q_marks);
18081809
--- src/import.c
+++ src/import.c
@@ -1761,20 +1761,21 @@
1761 ** times but only the last tag should be used. And we do not know which
1762 ** occurrence of the tag is the last until the import finishes.
1763 */
1764 db_multi_exec(
1765 "CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT);"
 
1766 "CREATE TEMP TABLE xbranch(tname TEXT UNIQUE, brnm TEXT);"
1767 "CREATE TEMP TABLE xtag(tname TEXT UNIQUE, tcontent TEXT);"
1768 );
1769
1770 if( markfile_in ){
1771 FILE *f = fossil_fopen(markfile_in, "r");
1772 if( !f ){
1773 fossil_fatal("cannot open %s for reading", markfile_in);
1774 }
1775 if(import_marks(f, &blobs, NULL)<0){
1776 fossil_fatal("error importing marks from file: %s", markfile_in);
1777 }
1778 fclose(f);
1779 }
1780
@@ -1795,13 +1796,13 @@
1795 db_prepare(&q_marks, "SELECT DISTINCT trid FROM xmark");
1796 while( db_step(&q_marks)==SQLITE_ROW ){
1797 rid = db_column_int(&q_marks, 0);
1798 if( db_int(0, "SELECT count(objid) FROM event"
1799 " WHERE objid=%d AND type='ci'", rid)==0 ){
1800 if( bag_find(&blobs, rid)==0 ){
1801 bag_insert(&blobs, rid);
1802 }
1803 }else{
1804 bag_insert(&vers, rid);
1805 }
1806 }
1807 db_finalize(&q_marks);
1808
--- src/import.c
+++ src/import.c
@@ -1761,20 +1761,21 @@
1761 ** times but only the last tag should be used. And we do not know which
1762 ** occurrence of the tag is the last until the import finishes.
1763 */
1764 db_multi_exec(
1765 "CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT);"
1766 "CREATE INDEX temp.i_xmark ON xmark(trid);"
1767 "CREATE TEMP TABLE xbranch(tname TEXT UNIQUE, brnm TEXT);"
1768 "CREATE TEMP TABLE xtag(tname TEXT UNIQUE, tcontent TEXT);"
1769 );
1770
1771 if( markfile_in ){
1772 FILE *f = fossil_fopen(markfile_in, "r");
1773 if( !f ){
1774 fossil_fatal("cannot open %s for reading", markfile_in);
1775 }
1776 if( import_marks(f, &blobs, NULL, NULL)<0 ){
1777 fossil_fatal("error importing marks from file: %s", markfile_in);
1778 }
1779 fclose(f);
1780 }
1781
@@ -1795,13 +1796,13 @@
1796 db_prepare(&q_marks, "SELECT DISTINCT trid FROM xmark");
1797 while( db_step(&q_marks)==SQLITE_ROW ){
1798 rid = db_column_int(&q_marks, 0);
1799 if( db_int(0, "SELECT count(objid) FROM event"
1800 " WHERE objid=%d AND type='ci'", rid)==0 ){
1801 /* Blob marks exported by git aren't saved between runs, so they need
1802 ** to be left free for git to re-use in the future.
1803 */
1804 }else{
1805 bag_insert(&vers, rid);
1806 }
1807 }
1808 db_finalize(&q_marks);
1809
+79 -4
--- src/main.c
+++ src/main.c
@@ -18,20 +18,21 @@
1818
** This module codes the main() procedure that runs first when the
1919
** program is invoked.
2020
*/
2121
#include "VERSION.h"
2222
#include "config.h"
23
+#if defined(_WIN32)
24
+# include <windows.h>
25
+#endif
2326
#include "main.h"
2427
#include <string.h>
2528
#include <time.h>
2629
#include <fcntl.h>
2730
#include <sys/types.h>
2831
#include <sys/stat.h>
2932
#include <stdlib.h> /* atexit() */
30
-#if defined(_WIN32)
31
-# include <windows.h>
32
-#else
33
+#if !defined(_WIN32)
3334
# include <errno.h> /* errno global */
3435
#endif
3536
#ifdef FOSSIL_ENABLE_SSL
3637
# include "openssl/crypto.h"
3738
#endif
@@ -299,10 +300,22 @@
299300
/*
300301
** atexit() handler which frees up "some" of the resources
301302
** used by fossil.
302303
*/
303304
static void fossil_atexit(void) {
305
+#if USE_SEE
306
+ /*
307
+ ** Zero, unlock, and free the saved database encryption key now.
308
+ */
309
+ db_unsave_encryption_key();
310
+#endif
311
+#if defined(_WIN32) || defined(__BIONIC__)
312
+ /*
313
+ ** Free the secure getpass() buffer now.
314
+ */
315
+ freepass();
316
+#endif
304317
#if defined(_WIN32) && !defined(_WIN64) && defined(FOSSIL_ENABLE_TCL) && \
305318
defined(USE_TCL_STUBS)
306319
/*
307320
** If Tcl is compiled on Windows using the latest MinGW, Fossil can crash
308321
** when exiting while a stubs-enabled Tcl is still loaded. This is due to
@@ -1917,10 +1930,41 @@
19171930
}
19181931
}
19191932
}
19201933
}
19211934
1935
+#if defined(_WIN32) && USE_SEE
1936
+/*
1937
+** This function attempts to parse a string value in the following
1938
+** format:
1939
+**
1940
+** "%lu:%p:%u"
1941
+**
1942
+** There are three parts, which must be delimited by colons. The
1943
+** first part is an unsigned long integer in base-10 (decimal) format.
1944
+** The second part is a numerical representation of a native pointer,
1945
+** in the appropriate implementation defined format. The third part
1946
+** is an unsigned integer in base-10 (decimal) format.
1947
+**
1948
+** If the specified value cannot be parsed, for any reason, a fatal
1949
+** error will be raised and the process will be terminated.
1950
+*/
1951
+void parse_pid_key_value(
1952
+ const char *zPidKey, /* The value to be parsed. */
1953
+ DWORD *pProcessId, /* The extracted process identifier. */
1954
+ LPVOID *ppAddress, /* The extracted pointer value. */
1955
+ SIZE_T *pnSize /* The extracted size value. */
1956
+){
1957
+ unsigned int nSize = 0;
1958
+ if( sscanf(zPidKey, "%lu:%p:%u", pProcessId, ppAddress, &nSize)==3 ){
1959
+ *pnSize = (SIZE_T)nSize;
1960
+ }else{
1961
+ fossil_fatal("failed to parse pid key");
1962
+ }
1963
+}
1964
+#endif
1965
+
19221966
/*
19231967
** undocumented format:
19241968
**
19251969
** fossil http INFILE OUTFILE IPADDR ?REPOSITORY?
19261970
**
@@ -1968,10 +2012,12 @@
19682012
** --notfound URL use URL as "HTTP 404, object not found" page.
19692013
** --repolist If REPOSITORY is directory, URL "/" lists all repos
19702014
** --scgi Interpret input as SCGI rather than HTTP
19712015
** --skin LABEL Use override skin LABEL
19722016
** --th-trace trace TH1 execution (for debugging purposes)
2017
+** --usepidkey Use saved encryption key from parent process. This is
2018
+** only necessary when using SEE on Windows.
19732019
**
19742020
** See also: cgi, server, winsrv
19752021
*/
19762022
void cmd_http(void){
19772023
const char *zIpAddr = 0;
@@ -1980,10 +2026,13 @@
19802026
const char *zAltBase;
19812027
const char *zFileGlob;
19822028
int useSCGI;
19832029
int noJail;
19842030
int allowRepoList;
2031
+#if defined(_WIN32) && USE_SEE
2032
+ const char *zPidKey;
2033
+#endif
19852034
19862035
Th_InitTraceLog();
19872036
19882037
/* The winhttp module passes the --files option as --files-urlenc with
19892038
** the argument being URL encoded, to avoid wildcard expansion in the
@@ -2010,10 +2059,21 @@
20102059
zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */
20112060
cgi_replace_parameter("HTTPS","on");
20122061
}
20132062
zHost = find_option("host", 0, 1);
20142063
if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost);
2064
+
2065
+#if defined(_WIN32) && USE_SEE
2066
+ zPidKey = find_option("usepidkey", 0, 1);
2067
+ if( zPidKey ){
2068
+ DWORD processId = 0;
2069
+ LPVOID pAddress = NULL;
2070
+ SIZE_T nSize = 0;
2071
+ parse_pid_key_value(zPidKey, &processId, &pAddress, &nSize);
2072
+ db_read_saved_encryption_key_from_process(processId, pAddress, nSize);
2073
+ }
2074
+#endif
20152075
20162076
/* We should be done with options.. */
20172077
verify_all_options();
20182078
20192079
if( g.argc!=2 && g.argc!=3 && g.argc!=5 && g.argc!=6 ){
@@ -2171,11 +2231,12 @@
21712231
** -P|--port TCPPORT listen to request on port TCPPORT
21722232
** --th-trace trace TH1 execution (for debugging purposes)
21732233
** --repolist If REPOSITORY is dir, URL "/" lists repos.
21742234
** --scgi Accept SCGI rather than HTTP
21752235
** --skin LABEL Use override skin LABEL
2176
-
2236
+** --usepidkey Use saved encryption key from parent process. This is
2237
+** only necessary when using SEE on Windows.
21772238
**
21782239
** See also: cgi, http, winsrv
21792240
*/
21802241
void cmd_webserver(void){
21812242
int iPort, mxPort; /* Range of TCP ports allowed */
@@ -2192,10 +2253,13 @@
21922253
const char *zAltBase; /* Argument to the --baseurl option */
21932254
const char *zFileGlob; /* Static content must match this */
21942255
char *zIpAddr = 0; /* Bind to this IP address */
21952256
int fCreate = 0; /* The --create flag */
21962257
const char *zInitPage = 0; /* Start on this page. --page option */
2258
+#if defined(_WIN32) && USE_SEE
2259
+ const char *zPidKey;
2260
+#endif
21972261
21982262
#if defined(_WIN32)
21992263
const char *zStopperFile; /* Name of file used to terminate server */
22002264
zStopperFile = find_option("stopper", 0, 1);
22012265
#endif
@@ -2235,10 +2299,21 @@
22352299
g.sslNotAvailable = 1;
22362300
}
22372301
if( find_option("localhost", 0, 0)!=0 ){
22382302
flags |= HTTP_SERVER_LOCALHOST;
22392303
}
2304
+
2305
+#if defined(_WIN32) && USE_SEE
2306
+ zPidKey = find_option("usepidkey", 0, 1);
2307
+ if( zPidKey ){
2308
+ DWORD processId = 0;
2309
+ LPVOID pAddress = NULL;
2310
+ SIZE_T nSize = 0;
2311
+ parse_pid_key_value(zPidKey, &processId, &pAddress, &nSize);
2312
+ db_read_saved_encryption_key_from_process(processId, pAddress, nSize);
2313
+ }
2314
+#endif
22402315
22412316
/* We should be done with options.. */
22422317
verify_all_options();
22432318
22442319
if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
22452320
--- src/main.c
+++ src/main.c
@@ -18,20 +18,21 @@
18 ** This module codes the main() procedure that runs first when the
19 ** program is invoked.
20 */
21 #include "VERSION.h"
22 #include "config.h"
 
 
 
23 #include "main.h"
24 #include <string.h>
25 #include <time.h>
26 #include <fcntl.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <stdlib.h> /* atexit() */
30 #if defined(_WIN32)
31 # include <windows.h>
32 #else
33 # include <errno.h> /* errno global */
34 #endif
35 #ifdef FOSSIL_ENABLE_SSL
36 # include "openssl/crypto.h"
37 #endif
@@ -299,10 +300,22 @@
299 /*
300 ** atexit() handler which frees up "some" of the resources
301 ** used by fossil.
302 */
303 static void fossil_atexit(void) {
 
 
 
 
 
 
 
 
 
 
 
 
304 #if defined(_WIN32) && !defined(_WIN64) && defined(FOSSIL_ENABLE_TCL) && \
305 defined(USE_TCL_STUBS)
306 /*
307 ** If Tcl is compiled on Windows using the latest MinGW, Fossil can crash
308 ** when exiting while a stubs-enabled Tcl is still loaded. This is due to
@@ -1917,10 +1930,41 @@
1917 }
1918 }
1919 }
1920 }
1921
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1922 /*
1923 ** undocumented format:
1924 **
1925 ** fossil http INFILE OUTFILE IPADDR ?REPOSITORY?
1926 **
@@ -1968,10 +2012,12 @@
1968 ** --notfound URL use URL as "HTTP 404, object not found" page.
1969 ** --repolist If REPOSITORY is directory, URL "/" lists all repos
1970 ** --scgi Interpret input as SCGI rather than HTTP
1971 ** --skin LABEL Use override skin LABEL
1972 ** --th-trace trace TH1 execution (for debugging purposes)
 
 
1973 **
1974 ** See also: cgi, server, winsrv
1975 */
1976 void cmd_http(void){
1977 const char *zIpAddr = 0;
@@ -1980,10 +2026,13 @@
1980 const char *zAltBase;
1981 const char *zFileGlob;
1982 int useSCGI;
1983 int noJail;
1984 int allowRepoList;
 
 
 
1985
1986 Th_InitTraceLog();
1987
1988 /* The winhttp module passes the --files option as --files-urlenc with
1989 ** the argument being URL encoded, to avoid wildcard expansion in the
@@ -2010,10 +2059,21 @@
2010 zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */
2011 cgi_replace_parameter("HTTPS","on");
2012 }
2013 zHost = find_option("host", 0, 1);
2014 if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost);
 
 
 
 
 
 
 
 
 
 
 
2015
2016 /* We should be done with options.. */
2017 verify_all_options();
2018
2019 if( g.argc!=2 && g.argc!=3 && g.argc!=5 && g.argc!=6 ){
@@ -2171,11 +2231,12 @@
2171 ** -P|--port TCPPORT listen to request on port TCPPORT
2172 ** --th-trace trace TH1 execution (for debugging purposes)
2173 ** --repolist If REPOSITORY is dir, URL "/" lists repos.
2174 ** --scgi Accept SCGI rather than HTTP
2175 ** --skin LABEL Use override skin LABEL
2176
 
2177 **
2178 ** See also: cgi, http, winsrv
2179 */
2180 void cmd_webserver(void){
2181 int iPort, mxPort; /* Range of TCP ports allowed */
@@ -2192,10 +2253,13 @@
2192 const char *zAltBase; /* Argument to the --baseurl option */
2193 const char *zFileGlob; /* Static content must match this */
2194 char *zIpAddr = 0; /* Bind to this IP address */
2195 int fCreate = 0; /* The --create flag */
2196 const char *zInitPage = 0; /* Start on this page. --page option */
 
 
 
2197
2198 #if defined(_WIN32)
2199 const char *zStopperFile; /* Name of file used to terminate server */
2200 zStopperFile = find_option("stopper", 0, 1);
2201 #endif
@@ -2235,10 +2299,21 @@
2235 g.sslNotAvailable = 1;
2236 }
2237 if( find_option("localhost", 0, 0)!=0 ){
2238 flags |= HTTP_SERVER_LOCALHOST;
2239 }
 
 
 
 
 
 
 
 
 
 
 
2240
2241 /* We should be done with options.. */
2242 verify_all_options();
2243
2244 if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
2245
--- src/main.c
+++ src/main.c
@@ -18,20 +18,21 @@
18 ** This module codes the main() procedure that runs first when the
19 ** program is invoked.
20 */
21 #include "VERSION.h"
22 #include "config.h"
23 #if defined(_WIN32)
24 # include <windows.h>
25 #endif
26 #include "main.h"
27 #include <string.h>
28 #include <time.h>
29 #include <fcntl.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <stdlib.h> /* atexit() */
33 #if !defined(_WIN32)
 
 
34 # include <errno.h> /* errno global */
35 #endif
36 #ifdef FOSSIL_ENABLE_SSL
37 # include "openssl/crypto.h"
38 #endif
@@ -299,10 +300,22 @@
300 /*
301 ** atexit() handler which frees up "some" of the resources
302 ** used by fossil.
303 */
304 static void fossil_atexit(void) {
305 #if USE_SEE
306 /*
307 ** Zero, unlock, and free the saved database encryption key now.
308 */
309 db_unsave_encryption_key();
310 #endif
311 #if defined(_WIN32) || defined(__BIONIC__)
312 /*
313 ** Free the secure getpass() buffer now.
314 */
315 freepass();
316 #endif
317 #if defined(_WIN32) && !defined(_WIN64) && defined(FOSSIL_ENABLE_TCL) && \
318 defined(USE_TCL_STUBS)
319 /*
320 ** If Tcl is compiled on Windows using the latest MinGW, Fossil can crash
321 ** when exiting while a stubs-enabled Tcl is still loaded. This is due to
@@ -1917,10 +1930,41 @@
1930 }
1931 }
1932 }
1933 }
1934
1935 #if defined(_WIN32) && USE_SEE
1936 /*
1937 ** This function attempts to parse a string value in the following
1938 ** format:
1939 **
1940 ** "%lu:%p:%u"
1941 **
1942 ** There are three parts, which must be delimited by colons. The
1943 ** first part is an unsigned long integer in base-10 (decimal) format.
1944 ** The second part is a numerical representation of a native pointer,
1945 ** in the appropriate implementation defined format. The third part
1946 ** is an unsigned integer in base-10 (decimal) format.
1947 **
1948 ** If the specified value cannot be parsed, for any reason, a fatal
1949 ** error will be raised and the process will be terminated.
1950 */
1951 void parse_pid_key_value(
1952 const char *zPidKey, /* The value to be parsed. */
1953 DWORD *pProcessId, /* The extracted process identifier. */
1954 LPVOID *ppAddress, /* The extracted pointer value. */
1955 SIZE_T *pnSize /* The extracted size value. */
1956 ){
1957 unsigned int nSize = 0;
1958 if( sscanf(zPidKey, "%lu:%p:%u", pProcessId, ppAddress, &nSize)==3 ){
1959 *pnSize = (SIZE_T)nSize;
1960 }else{
1961 fossil_fatal("failed to parse pid key");
1962 }
1963 }
1964 #endif
1965
1966 /*
1967 ** undocumented format:
1968 **
1969 ** fossil http INFILE OUTFILE IPADDR ?REPOSITORY?
1970 **
@@ -1968,10 +2012,12 @@
2012 ** --notfound URL use URL as "HTTP 404, object not found" page.
2013 ** --repolist If REPOSITORY is directory, URL "/" lists all repos
2014 ** --scgi Interpret input as SCGI rather than HTTP
2015 ** --skin LABEL Use override skin LABEL
2016 ** --th-trace trace TH1 execution (for debugging purposes)
2017 ** --usepidkey Use saved encryption key from parent process. This is
2018 ** only necessary when using SEE on Windows.
2019 **
2020 ** See also: cgi, server, winsrv
2021 */
2022 void cmd_http(void){
2023 const char *zIpAddr = 0;
@@ -1980,10 +2026,13 @@
2026 const char *zAltBase;
2027 const char *zFileGlob;
2028 int useSCGI;
2029 int noJail;
2030 int allowRepoList;
2031 #if defined(_WIN32) && USE_SEE
2032 const char *zPidKey;
2033 #endif
2034
2035 Th_InitTraceLog();
2036
2037 /* The winhttp module passes the --files option as --files-urlenc with
2038 ** the argument being URL encoded, to avoid wildcard expansion in the
@@ -2010,10 +2059,21 @@
2059 zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */
2060 cgi_replace_parameter("HTTPS","on");
2061 }
2062 zHost = find_option("host", 0, 1);
2063 if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost);
2064
2065 #if defined(_WIN32) && USE_SEE
2066 zPidKey = find_option("usepidkey", 0, 1);
2067 if( zPidKey ){
2068 DWORD processId = 0;
2069 LPVOID pAddress = NULL;
2070 SIZE_T nSize = 0;
2071 parse_pid_key_value(zPidKey, &processId, &pAddress, &nSize);
2072 db_read_saved_encryption_key_from_process(processId, pAddress, nSize);
2073 }
2074 #endif
2075
2076 /* We should be done with options.. */
2077 verify_all_options();
2078
2079 if( g.argc!=2 && g.argc!=3 && g.argc!=5 && g.argc!=6 ){
@@ -2171,11 +2231,12 @@
2231 ** -P|--port TCPPORT listen to request on port TCPPORT
2232 ** --th-trace trace TH1 execution (for debugging purposes)
2233 ** --repolist If REPOSITORY is dir, URL "/" lists repos.
2234 ** --scgi Accept SCGI rather than HTTP
2235 ** --skin LABEL Use override skin LABEL
2236 ** --usepidkey Use saved encryption key from parent process. This is
2237 ** only necessary when using SEE on Windows.
2238 **
2239 ** See also: cgi, http, winsrv
2240 */
2241 void cmd_webserver(void){
2242 int iPort, mxPort; /* Range of TCP ports allowed */
@@ -2192,10 +2253,13 @@
2253 const char *zAltBase; /* Argument to the --baseurl option */
2254 const char *zFileGlob; /* Static content must match this */
2255 char *zIpAddr = 0; /* Bind to this IP address */
2256 int fCreate = 0; /* The --create flag */
2257 const char *zInitPage = 0; /* Start on this page. --page option */
2258 #if defined(_WIN32) && USE_SEE
2259 const char *zPidKey;
2260 #endif
2261
2262 #if defined(_WIN32)
2263 const char *zStopperFile; /* Name of file used to terminate server */
2264 zStopperFile = find_option("stopper", 0, 1);
2265 #endif
@@ -2235,10 +2299,21 @@
2299 g.sslNotAvailable = 1;
2300 }
2301 if( find_option("localhost", 0, 0)!=0 ){
2302 flags |= HTTP_SERVER_LOCALHOST;
2303 }
2304
2305 #if defined(_WIN32) && USE_SEE
2306 zPidKey = find_option("usepidkey", 0, 1);
2307 if( zPidKey ){
2308 DWORD processId = 0;
2309 LPVOID pAddress = NULL;
2310 SIZE_T nSize = 0;
2311 parse_pid_key_value(zPidKey, &processId, &pAddress, &nSize);
2312 db_read_saved_encryption_key_from_process(processId, pAddress, nSize);
2313 }
2314 #endif
2315
2316 /* We should be done with options.. */
2317 verify_all_options();
2318
2319 if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
2320
+1 -1
--- src/mkindex.c
+++ src/mkindex.c
@@ -223,11 +223,11 @@
223223
fprintf(stderr, "%s:%d: unknown option: '%.*s'\n",
224224
zFile, nLine, j, &zLine[i]);
225225
nErr++;
226226
}
227227
}
228
-
228
+
229229
nUsed++;
230230
}
231231
232232
/*
233233
** Check to see if the current line is an #if and if it is, add it to
234234
--- src/mkindex.c
+++ src/mkindex.c
@@ -223,11 +223,11 @@
223 fprintf(stderr, "%s:%d: unknown option: '%.*s'\n",
224 zFile, nLine, j, &zLine[i]);
225 nErr++;
226 }
227 }
228
229 nUsed++;
230 }
231
232 /*
233 ** Check to see if the current line is an #if and if it is, add it to
234
--- src/mkindex.c
+++ src/mkindex.c
@@ -223,11 +223,11 @@
223 fprintf(stderr, "%s:%d: unknown option: '%.*s'\n",
224 zFile, nLine, j, &zLine[i]);
225 nErr++;
226 }
227 }
228
229 nUsed++;
230 }
231
232 /*
233 ** Check to see if the current line is an #if and if it is, add it to
234
+1 -1
--- src/search.c
+++ src/search.c
@@ -407,11 +407,11 @@
407407
408408
/* search_match(TEXT, TEXT, ....)
409409
**
410410
** Using the full-scan search engine created by the most recent call
411411
** to search_init(), match the input the TEXT arguments.
412
-** Remember the results global full-scan search object.
412
+** Remember the results global full-scan search object.
413413
** Return non-zero on a match and zero on a miss.
414414
*/
415415
static void search_match_sqlfunc(
416416
sqlite3_context *context,
417417
int argc,
418418
--- src/search.c
+++ src/search.c
@@ -407,11 +407,11 @@
407
408 /* search_match(TEXT, TEXT, ....)
409 **
410 ** Using the full-scan search engine created by the most recent call
411 ** to search_init(), match the input the TEXT arguments.
412 ** Remember the results global full-scan search object.
413 ** Return non-zero on a match and zero on a miss.
414 */
415 static void search_match_sqlfunc(
416 sqlite3_context *context,
417 int argc,
418
--- src/search.c
+++ src/search.c
@@ -407,11 +407,11 @@
407
408 /* search_match(TEXT, TEXT, ....)
409 **
410 ** Using the full-scan search engine created by the most recent call
411 ** to search_init(), match the input the TEXT arguments.
412 ** Remember the results global full-scan search object.
413 ** Return non-zero on a match and zero on a miss.
414 */
415 static void search_match_sqlfunc(
416 sqlite3_context *context,
417 int argc,
418
+1 -1
--- src/setup.c
+++ src/setup.c
@@ -1537,11 +1537,11 @@
15371537
@ <p>Settings marked with (v) are 'versionable' and will be overridden
15381538
@ by the contents of files named <tt>.fossil-settings/PROPERTY</tt>
15391539
@ in the check-out root.
15401540
@ If such a file is present, the corresponding field above is not
15411541
@ editable.</p><hr /><p>
1542
- @ These settings work the same as the
1542
+ @ These settings work the same as the
15431543
@ <a href='%R/help?cmd=settings'>fossil set</a> command.
15441544
db_end_transaction(0);
15451545
style_footer();
15461546
}
15471547
15481548
--- src/setup.c
+++ src/setup.c
@@ -1537,11 +1537,11 @@
1537 @ <p>Settings marked with (v) are 'versionable' and will be overridden
1538 @ by the contents of files named <tt>.fossil-settings/PROPERTY</tt>
1539 @ in the check-out root.
1540 @ If such a file is present, the corresponding field above is not
1541 @ editable.</p><hr /><p>
1542 @ These settings work the same as the
1543 @ <a href='%R/help?cmd=settings'>fossil set</a> command.
1544 db_end_transaction(0);
1545 style_footer();
1546 }
1547
1548
--- src/setup.c
+++ src/setup.c
@@ -1537,11 +1537,11 @@
1537 @ <p>Settings marked with (v) are 'versionable' and will be overridden
1538 @ by the contents of files named <tt>.fossil-settings/PROPERTY</tt>
1539 @ in the check-out root.
1540 @ If such a file is present, the corresponding field above is not
1541 @ editable.</p><hr /><p>
1542 @ These settings work the same as the
1543 @ <a href='%R/help?cmd=settings'>fossil set</a> command.
1544 db_end_transaction(0);
1545 style_footer();
1546 }
1547
1548
+24 -16
--- src/shell.c
+++ src/shell.c
@@ -666,23 +666,25 @@
666666
#define MODE_Column 1 /* One record per line in neat columns */
667667
#define MODE_List 2 /* One record per line with a separator */
668668
#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
669669
#define MODE_Html 4 /* Generate an XHTML table */
670670
#define MODE_Insert 5 /* Generate SQL "insert" statements */
671
-#define MODE_Tcl 6 /* Generate ANSI-C or TCL quoted elements */
672
-#define MODE_Csv 7 /* Quote strings, numbers are plain */
673
-#define MODE_Explain 8 /* Like MODE_Column, but do not truncate data */
674
-#define MODE_Ascii 9 /* Use ASCII unit and record separators (0x1F/0x1E) */
675
-#define MODE_Pretty 10 /* Pretty-print schemas */
671
+#define MODE_Quote 6 /* Quote values as for SQL */
672
+#define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */
673
+#define MODE_Csv 8 /* Quote strings, numbers are plain */
674
+#define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */
675
+#define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */
676
+#define MODE_Pretty 11 /* Pretty-print schemas */
676677
677678
static const char *modeDescr[] = {
678679
"line",
679680
"column",
680681
"list",
681682
"semi",
682683
"html",
683684
"insert",
685
+ "quote",
684686
"tcl",
685687
"csv",
686688
"explain",
687689
"ascii",
688690
"prettyprint",
@@ -1196,23 +1198,26 @@
11961198
utf8_printf(p->out, "%s", p->rowSeparator);
11971199
}
11981200
setTextMode(p->out, 1);
11991201
break;
12001202
}
1203
+ case MODE_Quote:
12011204
case MODE_Insert: {
12021205
p->cnt++;
12031206
if( azArg==0 ) break;
1204
- utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
1205
- if( p->showHeader ){
1206
- raw_printf(p->out,"(");
1207
- for(i=0; i<nArg; i++){
1208
- char *zSep = i>0 ? ",": "";
1209
- utf8_printf(p->out, "%s%s", zSep, azCol[i]);
1210
- }
1211
- raw_printf(p->out,")");
1212
- }
1213
- raw_printf(p->out," VALUES(");
1207
+ if( p->cMode==MODE_Insert ){
1208
+ utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
1209
+ if( p->showHeader ){
1210
+ raw_printf(p->out,"(");
1211
+ for(i=0; i<nArg; i++){
1212
+ char *zSep = i>0 ? ",": "";
1213
+ utf8_printf(p->out, "%s%s", zSep, azCol[i]);
1214
+ }
1215
+ raw_printf(p->out,")");
1216
+ }
1217
+ raw_printf(p->out," VALUES(");
1218
+ }
12141219
for(i=0; i<nArg; i++){
12151220
char *zSep = i>0 ? ",": "";
12161221
if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
12171222
utf8_printf(p->out,"%sNULL",zSep);
12181223
}else if( aiType && aiType[i]==SQLITE_TEXT ){
@@ -1231,11 +1236,11 @@
12311236
}else{
12321237
if( zSep[0] ) utf8_printf(p->out,"%s",zSep);
12331238
output_quoted_string(p->out, azArg[i]);
12341239
}
12351240
}
1236
- raw_printf(p->out,");\n");
1241
+ raw_printf(p->out,p->cMode==MODE_Quote?"\n":");\n");
12371242
break;
12381243
}
12391244
case MODE_Ascii: {
12401245
if( p->cnt++==0 && p->showHeader ){
12411246
for(i=0; i<nArg; i++){
@@ -2175,10 +2180,11 @@
21752180
" column Left-aligned columns. (See .width)\n"
21762181
" html HTML <table> code\n"
21772182
" insert SQL insert statements for TABLE\n"
21782183
" line One value per line\n"
21792184
" list Values delimited by .separator strings\n"
2185
+ " quote Escape answers as for SQL\n"
21802186
" tabs Tab-separated values\n"
21812187
" tcl TCL list elements\n"
21822188
".nullvalue STRING Use STRING in place of NULL values\n"
21832189
".once FILENAME Output for the next SQL command only to FILENAME\n"
21842190
".open ?--new? ?FILE? Close existing database and reopen FILE\n"
@@ -3975,10 +3981,12 @@
39753981
p->mode = MODE_List;
39763982
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
39773983
}else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
39783984
p->mode = MODE_Insert;
39793985
set_table_name(p, nArg>=3 ? azArg[2] : "table");
3986
+ }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){
3987
+ p->mode = MODE_Quote;
39803988
}else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
39813989
p->mode = MODE_Ascii;
39823990
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
39833991
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
39843992
}else {
39853993
--- src/shell.c
+++ src/shell.c
@@ -666,23 +666,25 @@
666 #define MODE_Column 1 /* One record per line in neat columns */
667 #define MODE_List 2 /* One record per line with a separator */
668 #define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
669 #define MODE_Html 4 /* Generate an XHTML table */
670 #define MODE_Insert 5 /* Generate SQL "insert" statements */
671 #define MODE_Tcl 6 /* Generate ANSI-C or TCL quoted elements */
672 #define MODE_Csv 7 /* Quote strings, numbers are plain */
673 #define MODE_Explain 8 /* Like MODE_Column, but do not truncate data */
674 #define MODE_Ascii 9 /* Use ASCII unit and record separators (0x1F/0x1E) */
675 #define MODE_Pretty 10 /* Pretty-print schemas */
 
676
677 static const char *modeDescr[] = {
678 "line",
679 "column",
680 "list",
681 "semi",
682 "html",
683 "insert",
 
684 "tcl",
685 "csv",
686 "explain",
687 "ascii",
688 "prettyprint",
@@ -1196,23 +1198,26 @@
1196 utf8_printf(p->out, "%s", p->rowSeparator);
1197 }
1198 setTextMode(p->out, 1);
1199 break;
1200 }
 
1201 case MODE_Insert: {
1202 p->cnt++;
1203 if( azArg==0 ) break;
1204 utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
1205 if( p->showHeader ){
1206 raw_printf(p->out,"(");
1207 for(i=0; i<nArg; i++){
1208 char *zSep = i>0 ? ",": "";
1209 utf8_printf(p->out, "%s%s", zSep, azCol[i]);
1210 }
1211 raw_printf(p->out,")");
1212 }
1213 raw_printf(p->out," VALUES(");
 
 
1214 for(i=0; i<nArg; i++){
1215 char *zSep = i>0 ? ",": "";
1216 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
1217 utf8_printf(p->out,"%sNULL",zSep);
1218 }else if( aiType && aiType[i]==SQLITE_TEXT ){
@@ -1231,11 +1236,11 @@
1231 }else{
1232 if( zSep[0] ) utf8_printf(p->out,"%s",zSep);
1233 output_quoted_string(p->out, azArg[i]);
1234 }
1235 }
1236 raw_printf(p->out,");\n");
1237 break;
1238 }
1239 case MODE_Ascii: {
1240 if( p->cnt++==0 && p->showHeader ){
1241 for(i=0; i<nArg; i++){
@@ -2175,10 +2180,11 @@
2175 " column Left-aligned columns. (See .width)\n"
2176 " html HTML <table> code\n"
2177 " insert SQL insert statements for TABLE\n"
2178 " line One value per line\n"
2179 " list Values delimited by .separator strings\n"
 
2180 " tabs Tab-separated values\n"
2181 " tcl TCL list elements\n"
2182 ".nullvalue STRING Use STRING in place of NULL values\n"
2183 ".once FILENAME Output for the next SQL command only to FILENAME\n"
2184 ".open ?--new? ?FILE? Close existing database and reopen FILE\n"
@@ -3975,10 +3981,12 @@
3975 p->mode = MODE_List;
3976 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
3977 }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
3978 p->mode = MODE_Insert;
3979 set_table_name(p, nArg>=3 ? azArg[2] : "table");
 
 
3980 }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
3981 p->mode = MODE_Ascii;
3982 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
3983 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
3984 }else {
3985
--- src/shell.c
+++ src/shell.c
@@ -666,23 +666,25 @@
666 #define MODE_Column 1 /* One record per line in neat columns */
667 #define MODE_List 2 /* One record per line with a separator */
668 #define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
669 #define MODE_Html 4 /* Generate an XHTML table */
670 #define MODE_Insert 5 /* Generate SQL "insert" statements */
671 #define MODE_Quote 6 /* Quote values as for SQL */
672 #define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */
673 #define MODE_Csv 8 /* Quote strings, numbers are plain */
674 #define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */
675 #define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */
676 #define MODE_Pretty 11 /* Pretty-print schemas */
677
678 static const char *modeDescr[] = {
679 "line",
680 "column",
681 "list",
682 "semi",
683 "html",
684 "insert",
685 "quote",
686 "tcl",
687 "csv",
688 "explain",
689 "ascii",
690 "prettyprint",
@@ -1196,23 +1198,26 @@
1198 utf8_printf(p->out, "%s", p->rowSeparator);
1199 }
1200 setTextMode(p->out, 1);
1201 break;
1202 }
1203 case MODE_Quote:
1204 case MODE_Insert: {
1205 p->cnt++;
1206 if( azArg==0 ) break;
1207 if( p->cMode==MODE_Insert ){
1208 utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
1209 if( p->showHeader ){
1210 raw_printf(p->out,"(");
1211 for(i=0; i<nArg; i++){
1212 char *zSep = i>0 ? ",": "";
1213 utf8_printf(p->out, "%s%s", zSep, azCol[i]);
1214 }
1215 raw_printf(p->out,")");
1216 }
1217 raw_printf(p->out," VALUES(");
1218 }
1219 for(i=0; i<nArg; i++){
1220 char *zSep = i>0 ? ",": "";
1221 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
1222 utf8_printf(p->out,"%sNULL",zSep);
1223 }else if( aiType && aiType[i]==SQLITE_TEXT ){
@@ -1231,11 +1236,11 @@
1236 }else{
1237 if( zSep[0] ) utf8_printf(p->out,"%s",zSep);
1238 output_quoted_string(p->out, azArg[i]);
1239 }
1240 }
1241 raw_printf(p->out,p->cMode==MODE_Quote?"\n":");\n");
1242 break;
1243 }
1244 case MODE_Ascii: {
1245 if( p->cnt++==0 && p->showHeader ){
1246 for(i=0; i<nArg; i++){
@@ -2175,10 +2180,11 @@
2180 " column Left-aligned columns. (See .width)\n"
2181 " html HTML <table> code\n"
2182 " insert SQL insert statements for TABLE\n"
2183 " line One value per line\n"
2184 " list Values delimited by .separator strings\n"
2185 " quote Escape answers as for SQL\n"
2186 " tabs Tab-separated values\n"
2187 " tcl TCL list elements\n"
2188 ".nullvalue STRING Use STRING in place of NULL values\n"
2189 ".once FILENAME Output for the next SQL command only to FILENAME\n"
2190 ".open ?--new? ?FILE? Close existing database and reopen FILE\n"
@@ -3975,10 +3981,12 @@
3981 p->mode = MODE_List;
3982 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
3983 }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
3984 p->mode = MODE_Insert;
3985 set_table_name(p, nArg>=3 ? azArg[2] : "table");
3986 }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){
3987 p->mode = MODE_Quote;
3988 }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
3989 p->mode = MODE_Ascii;
3990 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
3991 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
3992 }else {
3993
+174 -77
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
11
/******************************************************************************
22
** This file is an amalgamation of many separate C source files from SQLite
3
-** version 3.15.0. By combining all the individual C code files into this
3
+** version 3.16.0. By combining all the individual C code files into this
44
** single large file, the entire code can be compiled as a single translation
55
** unit. This allows many compilers to do optimizations that would not be
66
** possible if the files were compiled separately. Performance improvements
77
** of 5% or more are commonly seen when SQLite is compiled as a single
88
** translation unit.
@@ -379,13 +379,13 @@
379379
**
380380
** See also: [sqlite3_libversion()],
381381
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
382382
** [sqlite_version()] and [sqlite_source_id()].
383383
*/
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"
384
+#define SQLITE_VERSION "3.16.0"
385
+#define SQLITE_VERSION_NUMBER 3016000
386
+#define SQLITE_SOURCE_ID "2016-11-02 14:50:19 3028845329c9b7acdec2ec8b01d00d782347454c"
387387
388388
/*
389389
** CAPI3REF: Run-Time Library Version Numbers
390390
** KEYWORDS: sqlite3_version, sqlite3_sourceid
391391
**
@@ -1235,10 +1235,16 @@
12351235
** <li>[[SQLITE_FCNTL_HAS_MOVED]]
12361236
** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a
12371237
** pointer to an integer and it writes a boolean into that integer depending
12381238
** on whether or not the file has been renamed, moved, or deleted since it
12391239
** was first opened.
1240
+**
1241
+** <li>[[SQLITE_FCNTL_WIN32_GET_HANDLE]]
1242
+** The [SQLITE_FCNTL_WIN32_GET_HANDLE] opcode can be used to obtain the
1243
+** underlying native file handle associated with a file handle. This file
1244
+** control interprets its argument as a pointer to a native file handle and
1245
+** writes the resulting value there.
12401246
**
12411247
** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]]
12421248
** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This
12431249
** opcode causes the xFileControl method to swap the file handle with the one
12441250
** pointed to by the pArg argument. This capability is used during testing
@@ -1286,10 +1292,12 @@
12861292
#define SQLITE_FCNTL_WAL_BLOCK 24
12871293
#define SQLITE_FCNTL_ZIPVFS 25
12881294
#define SQLITE_FCNTL_RBU 26
12891295
#define SQLITE_FCNTL_VFS_POINTER 27
12901296
#define SQLITE_FCNTL_JOURNAL_POINTER 28
1297
+#define SQLITE_FCNTL_WIN32_GET_HANDLE 29
1298
+#define SQLITE_FCNTL_PDB 30
12911299
12921300
/* deprecated names */
12931301
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
12941302
#define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
12951303
#define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
@@ -2238,18 +2246,31 @@
22382246
** does not make a copy of the new main schema name string, so the application
22392247
** must ensure that the argument passed into this DBCONFIG option is unchanged
22402248
** until after the database connection closes.
22412249
** </dd>
22422250
**
2251
+** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt>
2252
+** <dd> Usually, when a database in wal mode is closed or detached from a
2253
+** database handle, SQLite checks if this will mean that there are now no
2254
+** connections at all to the database. If so, it performs a checkpoint
2255
+** operation before closing the connection. This option may be used to
2256
+** override this behaviour. The first parameter passed to this operation
2257
+** is an integer - non-zero to disable checkpoints-on-close, or zero (the
2258
+** default) to enable them. The second parameter is a pointer to an integer
2259
+** into which is written 0 or 1 to indicate whether checkpoints-on-close
2260
+** have been disabled - 0 if they are not disabled, 1 if they are.
2261
+** </dd>
2262
+**
22432263
** </dl>
22442264
*/
22452265
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
22462266
#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
22472267
#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */
22482268
#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
22492269
#define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */
22502270
#define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */
2271
+#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */
22512272
22522273
22532274
/*
22542275
** CAPI3REF: Enable Or Disable Extended Result Codes
22552276
** METHOD: sqlite3
@@ -12675,11 +12696,11 @@
1267512696
#define OP_SorterData 120 /* synopsis: r[P2]=data */
1267612697
#define OP_RowKey 121 /* synopsis: r[P2]=key */
1267712698
#define OP_RowData 122 /* synopsis: r[P2]=data */
1267812699
#define OP_Rowid 123 /* synopsis: r[P2]=rowid */
1267912700
#define OP_NullRow 124
12680
-#define OP_SorterInsert 125
12701
+#define OP_SorterInsert 125 /* synopsis: key=r[P2] */
1268112702
#define OP_IdxInsert 126 /* synopsis: key=r[P2] */
1268212703
#define OP_IdxDelete 127 /* synopsis: key=r[P2@P3] */
1268312704
#define OP_Seek 128 /* synopsis: Move P3 to P1.rowid */
1268412705
#define OP_IdxRowid 129 /* synopsis: r[P2]=rowid */
1268512706
#define OP_Destroy 130
@@ -13030,11 +13051,11 @@
1303013051
int,
1303113052
int,
1303213053
int,
1303313054
void(*)(DbPage*)
1303413055
);
13035
-SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager);
13056
+SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*);
1303613057
SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
1303713058
1303813059
/* Functions used to configure a Pager object. */
1303913060
SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *);
1304013061
SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int);
@@ -13081,19 +13102,22 @@
1308113102
SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
1308213103
SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
1308313104
SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager);
1308413105
1308513106
#ifndef SQLITE_OMIT_WAL
13086
-SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*);
13107
+SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, sqlite3*, int, int*, int*);
1308713108
SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager);
1308813109
SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager);
1308913110
SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
13090
-SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager);
13111
+SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3*);
13112
+SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager);
1309113113
# ifdef SQLITE_ENABLE_SNAPSHOT
1309213114
SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot);
1309313115
SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot);
1309413116
# endif
13117
+#else
13118
+# define sqlite3PagerUseWal(x) 0
1309513119
#endif
1309613120
1309713121
#ifdef SQLITE_ENABLE_ZIPVFS
1309813122
SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager);
1309913123
#endif
@@ -14060,10 +14084,11 @@
1406014084
#define SQLITE_QueryOnly 0x04000000 /* Disable database changes */
1406114085
#define SQLITE_VdbeEQP 0x08000000 /* Debug EXPLAIN QUERY PLAN */
1406214086
#define SQLITE_Vacuum 0x10000000 /* Currently in a VACUUM */
1406314087
#define SQLITE_CellSizeCk 0x20000000 /* Check btree cell sizes on load */
1406414088
#define SQLITE_Fts3Tokenizer 0x40000000 /* Enable fts3_tokenizer(2) */
14089
+#define SQLITE_NoCkptOnClose 0x80000000 /* No checkpoint on close()/DETACH */
1406514090
1406614091
1406714092
/*
1406814093
** Bits of the sqlite3.dbOptFlags field that are used by the
1406914094
** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
@@ -17268,10 +17293,13 @@
1726817293
#if SQLITE_DEFAULT_LOCKING_MODE
1726917294
"DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
1727017295
#endif
1727117296
#if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc)
1727217297
"DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
17298
+#endif
17299
+#if SQLITE_DIRECT_OVERFLOW_READ
17300
+ "DIRECT_OVERFLOW_READ",
1727317301
#endif
1727417302
#if SQLITE_DISABLE_DIRSYNC
1727517303
"DISABLE_DIRSYNC",
1727617304
#endif
1727717305
#if SQLITE_DISABLE_LFS
@@ -17354,10 +17382,13 @@
1735417382
#if SQLITE_ENABLE_UNLOCK_NOTIFY
1735517383
"ENABLE_UNLOCK_NOTIFY",
1735617384
#endif
1735717385
#if SQLITE_ENABLE_UPDATE_DELETE_LIMIT
1735817386
"ENABLE_UPDATE_DELETE_LIMIT",
17387
+#endif
17388
+#if defined(SQLITE_ENABLE_URI_00_ERROR)
17389
+ "ENABLE_URI_00_ERROR",
1735917390
#endif
1736017391
#if SQLITE_HAS_CODEC
1736117392
"HAS_CODEC",
1736217393
#endif
1736317394
#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
@@ -18105,12 +18136,12 @@
1810518136
UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */
1810618137
UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */
1810718138
int iNewReg; /* Register for new.* values */
1810818139
i64 iKey1; /* First key value passed to hook */
1810918140
i64 iKey2; /* Second key value passed to hook */
18110
- int iPKey; /* If not negative index of IPK column */
1811118141
Mem *aNew; /* Array of new.* values */
18142
+ Table *pTab; /* Schema object being upated */
1811218143
};
1811318144
1811418145
/*
1811518146
** Function prototypes
1811618147
*/
@@ -24598,13 +24629,12 @@
2459824629
char *zNew;
2459924630
size_t n;
2460024631
if( z==0 ){
2460124632
return 0;
2460224633
}
24603
- n = sqlite3Strlen30(z) + 1;
24604
- assert( (n&0x7fffffff)==n );
24605
- zNew = sqlite3DbMallocRaw(db, (int)n);
24634
+ n = strlen(z) + 1;
24635
+ zNew = sqlite3DbMallocRaw(db, n);
2460624636
if( zNew ){
2460724637
memcpy(zNew, z, n);
2460824638
}
2460924639
return zNew;
2461024640
}
@@ -29127,11 +29157,11 @@
2912729157
/* 120 */ "SorterData" OpHelp("r[P2]=data"),
2912829158
/* 121 */ "RowKey" OpHelp("r[P2]=key"),
2912929159
/* 122 */ "RowData" OpHelp("r[P2]=data"),
2913029160
/* 123 */ "Rowid" OpHelp("r[P2]=rowid"),
2913129161
/* 124 */ "NullRow" OpHelp(""),
29132
- /* 125 */ "SorterInsert" OpHelp(""),
29162
+ /* 125 */ "SorterInsert" OpHelp("key=r[P2]"),
2913329163
/* 126 */ "IdxInsert" OpHelp("key=r[P2]"),
2913429164
/* 127 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
2913529165
/* 128 */ "Seek" OpHelp("Move P3 to P1.rowid"),
2913629166
/* 129 */ "IdxRowid" OpHelp("r[P2]=rowid"),
2913729167
/* 130 */ "Destroy" OpHelp(""),
@@ -40674,10 +40704,16 @@
4067440704
a[1] = winIoerrRetryDelay;
4067540705
}
4067640706
OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
4067740707
return SQLITE_OK;
4067840708
}
40709
+ case SQLITE_FCNTL_WIN32_GET_HANDLE: {
40710
+ LPHANDLE phFile = (LPHANDLE)pArg;
40711
+ *phFile = pFile->h;
40712
+ OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
40713
+ return SQLITE_OK;
40714
+ }
4067940715
#ifdef SQLITE_TEST
4068040716
case SQLITE_FCNTL_WIN32_SET_HANDLE: {
4068140717
LPHANDLE phFile = (LPHANDLE)pArg;
4068240718
HANDLE hOldFile = pFile->h;
4068340719
pFile->h = *phFile;
@@ -46249,21 +46285,21 @@
4624946285
#define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */
4625046286
4625146287
#ifdef SQLITE_OMIT_WAL
4625246288
# define sqlite3WalOpen(x,y,z) 0
4625346289
# define sqlite3WalLimit(x,y)
46254
-# define sqlite3WalClose(w,x,y,z) 0
46290
+# define sqlite3WalClose(v,w,x,y,z) 0
4625546291
# define sqlite3WalBeginReadTransaction(y,z) 0
4625646292
# define sqlite3WalEndReadTransaction(z)
4625746293
# define sqlite3WalDbsize(y) 0
4625846294
# define sqlite3WalBeginWriteTransaction(y) 0
4625946295
# define sqlite3WalEndWriteTransaction(x) 0
4626046296
# define sqlite3WalUndo(x,y,z) 0
4626146297
# define sqlite3WalSavepoint(y,z)
4626246298
# define sqlite3WalSavepointUndo(y,z) 0
4626346299
# define sqlite3WalFrames(u,v,w,x,y,z) 0
46264
-# define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0
46300
+# define sqlite3WalCheckpoint(q,r,s,t,u,v,w,x,y,z) 0
4626546301
# define sqlite3WalCallback(z) 0
4626646302
# define sqlite3WalExclusiveMode(y,z) 0
4626746303
# define sqlite3WalHeapMemory(z) 0
4626846304
# define sqlite3WalFramesize(z) 0
4626946305
# define sqlite3WalFindFrame(x,y,z) 0
@@ -46277,11 +46313,11 @@
4627746313
*/
4627846314
typedef struct Wal Wal;
4627946315
4628046316
/* Open and close a connection to a write-ahead log. */
4628146317
SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**);
46282
-SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *);
46318
+SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, sqlite3*, int sync_flags, int, u8 *);
4628346319
4628446320
/* Set the limiting size of a WAL file. */
4628546321
SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64);
4628646322
4628746323
/* Used by readers to open (lock) and close (unlock) a snapshot. A
@@ -46320,10 +46356,11 @@
4632046356
SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int);
4632146357
4632246358
/* Copy pages from the log to the database file */
4632346359
SQLITE_PRIVATE int sqlite3WalCheckpoint(
4632446360
Wal *pWal, /* Write-ahead log connection */
46361
+ sqlite3 *db, /* Check this handle's interrupt flag */
4632546362
int eMode, /* One of PASSIVE, FULL and RESTART */
4632646363
int (*xBusy)(void*), /* Function to call when busy */
4632746364
void *pBusyArg, /* Context argument for xBusyHandler */
4632846365
int sync_flags, /* Flags to sync db file with (or 0) */
4632946366
int nBuf, /* Size of buffer nBuf */
@@ -47164,13 +47201,14 @@
4716447201
/*
4716547202
** Return true if this pager uses a write-ahead log instead of the usual
4716647203
** rollback journal. Otherwise false.
4716747204
*/
4716847205
#ifndef SQLITE_OMIT_WAL
47169
-static int pagerUseWal(Pager *pPager){
47206
+SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager){
4717047207
return (pPager->pWal!=0);
4717147208
}
47209
+# define pagerUseWal(x) sqlite3PagerUseWal(x)
4717247210
#else
4717347211
# define pagerUseWal(x) 0
4717447212
# define pagerRollbackWal(x) 0
4717547213
# define pagerWalFrames(v,w,x,y) 0
4717647214
# define pagerOpenWalIfPresent(z) SQLITE_OK
@@ -50368,21 +50406,22 @@
5036850406
** This function always succeeds. If a transaction is active an attempt
5036950407
** is made to roll it back. If an error occurs during the rollback
5037050408
** a hot journal may be left in the filesystem but no error is returned
5037150409
** to the caller.
5037250410
*/
50373
-SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
50411
+SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){
5037450412
u8 *pTmp = (u8 *)pPager->pTmpSpace;
5037550413
50414
+ assert( db || pagerUseWal(pPager)==0 );
5037650415
assert( assert_pager_state(pPager) );
5037750416
disable_simulated_io_errors();
5037850417
sqlite3BeginBenignMalloc();
5037950418
pagerFreeMapHdrs(pPager);
5038050419
/* pPager->errCode = 0; */
5038150420
pPager->exclusiveMode = 0;
5038250421
#ifndef SQLITE_OMIT_WAL
50383
- sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp);
50422
+ sqlite3WalClose(pPager->pWal,db,pPager->ckptSyncFlags,pPager->pageSize,pTmp);
5038450423
pPager->pWal = 0;
5038550424
#endif
5038650425
pager_reset(pPager);
5038750426
if( MEMDB ){
5038850427
pager_unlock(pPager);
@@ -53541,14 +53580,20 @@
5354153580
** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint()
5354253581
** or wal_blocking_checkpoint() API functions.
5354353582
**
5354453583
** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
5354553584
*/
53546
-SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){
53585
+SQLITE_PRIVATE int sqlite3PagerCheckpoint(
53586
+ Pager *pPager, /* Checkpoint on this pager */
53587
+ sqlite3 *db, /* Db handle used to check for interrupts */
53588
+ int eMode, /* Type of checkpoint */
53589
+ int *pnLog, /* OUT: Final number of frames in log */
53590
+ int *pnCkpt /* OUT: Final number of checkpointed frames */
53591
+){
5354753592
int rc = SQLITE_OK;
5354853593
if( pPager->pWal ){
53549
- rc = sqlite3WalCheckpoint(pPager->pWal, eMode,
53594
+ rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode,
5355053595
(eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
5355153596
pPager->pBusyHandlerArg,
5355253597
pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
5355353598
pnLog, pnCkpt
5355453599
);
@@ -53676,11 +53721,11 @@
5367653721
** Before closing the log file, this function attempts to take an
5367753722
** EXCLUSIVE lock on the database file. If this cannot be obtained, an
5367853723
** error (SQLITE_BUSY) is returned and the log connection is not closed.
5367953724
** If successful, the EXCLUSIVE lock is not released before returning.
5368053725
*/
53681
-SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){
53726
+SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){
5368253727
int rc = SQLITE_OK;
5368353728
5368453729
assert( pPager->journalMode==PAGER_JOURNALMODE_WAL );
5368553730
5368653731
/* If the log file is not already open, but does exist in the file-system,
@@ -53704,11 +53749,11 @@
5370453749
** the database file, the log and log-summary files will be deleted.
5370553750
*/
5370653751
if( rc==SQLITE_OK && pPager->pWal ){
5370753752
rc = pagerExclusiveLock(pPager);
5370853753
if( rc==SQLITE_OK ){
53709
- rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags,
53754
+ rc = sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags,
5371053755
pPager->pageSize, (u8*)pPager->pTmpSpace);
5371153756
pPager->pWal = 0;
5371253757
pagerFixMaplimit(pPager);
5371353758
if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK);
5371453759
}
@@ -55487,10 +55532,11 @@
5548755532
** checkpoint is running (in any other thread or process) at the same
5548855533
** time.
5548955534
*/
5549055535
static int walCheckpoint(
5549155536
Wal *pWal, /* Wal connection */
55537
+ sqlite3 *db, /* Check for interrupts on this handle */
5549255538
int eMode, /* One of PASSIVE, FULL or RESTART */
5549355539
int (*xBusy)(void*), /* Function to call when busy */
5549455540
void *pBusyArg, /* Context argument for xBusyHandler */
5549555541
int sync_flags, /* Flags for OsSync() (or 0) */
5549655542
u8 *zBuf /* Temporary buffer to use */
@@ -55581,10 +55627,14 @@
5558155627
5558255628
/* Iterate through the contents of the WAL, copying data to the db file */
5558355629
while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
5558455630
i64 iOffset;
5558555631
assert( walFramePgno(pWal, iFrame)==iDbpage );
55632
+ if( db->u1.isInterrupted ){
55633
+ rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
55634
+ break;
55635
+ }
5558655636
if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){
5558755637
continue;
5558855638
}
5558955639
iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE;
5559055640
/* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */
@@ -55685,10 +55735,11 @@
5568555735
/*
5568655736
** Close a connection to a log file.
5568755737
*/
5568855738
SQLITE_PRIVATE int sqlite3WalClose(
5568955739
Wal *pWal, /* Wal to close */
55740
+ sqlite3 *db, /* For interrupt flag */
5569055741
int sync_flags, /* Flags to pass to OsSync() (or 0) */
5569155742
int nBuf,
5569255743
u8 *zBuf /* Buffer of at least nBuf bytes */
5569355744
){
5569455745
int rc = SQLITE_OK;
@@ -55701,17 +55752,18 @@
5570155752
** the database. In this case checkpoint the database and unlink both
5570255753
** the wal and wal-index files.
5570355754
**
5570455755
** The EXCLUSIVE lock is not released before returning.
5570555756
*/
55706
- rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE);
55707
- if( rc==SQLITE_OK ){
55757
+ if( (db->flags & SQLITE_NoCkptOnClose)==0
55758
+ && SQLITE_OK==(rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE))
55759
+ ){
5570855760
if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
5570955761
pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
5571055762
}
55711
- rc = sqlite3WalCheckpoint(
55712
- pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0
55763
+ rc = sqlite3WalCheckpoint(pWal, db,
55764
+ SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0
5571355765
);
5571455766
if( rc==SQLITE_OK ){
5571555767
int bPersist = -1;
5571655768
sqlite3OsFileControlHint(
5571755769
pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersist
@@ -56955,10 +57007,11 @@
5695557007
** If parameter xBusy is not NULL, it is a pointer to a busy-handler
5695657008
** callback. In this case this function runs a blocking checkpoint.
5695757009
*/
5695857010
SQLITE_PRIVATE int sqlite3WalCheckpoint(
5695957011
Wal *pWal, /* Wal connection */
57012
+ sqlite3 *db, /* Check this handle's interrupt flag */
5696057013
int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */
5696157014
int (*xBusy)(void*), /* Function to call when busy */
5696257015
void *pBusyArg, /* Context argument for xBusyHandler */
5696357016
int sync_flags, /* Flags to sync db file with (or 0) */
5696457017
int nBuf, /* Size of temporary buffer */
@@ -57029,11 +57082,11 @@
5702957082
if( rc==SQLITE_OK ){
5703057083
5703157084
if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
5703257085
rc = SQLITE_CORRUPT_BKPT;
5703357086
}else{
57034
- rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf);
57087
+ rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf);
5703557088
}
5703657089
5703757090
/* If no error occurred, set the output variables. */
5703857091
if( rc==SQLITE_OK || rc==SQLITE_BUSY ){
5703957092
if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame;
@@ -60619,23 +60672,30 @@
6061960672
*ppBtree = p;
6062060673
6062160674
btree_open_out:
6062260675
if( rc!=SQLITE_OK ){
6062360676
if( pBt && pBt->pPager ){
60624
- sqlite3PagerClose(pBt->pPager);
60677
+ sqlite3PagerClose(pBt->pPager, 0);
6062560678
}
6062660679
sqlite3_free(pBt);
6062760680
sqlite3_free(p);
6062860681
*ppBtree = 0;
6062960682
}else{
60683
+ sqlite3_file *pFile;
60684
+
6063060685
/* If the B-Tree was successfully opened, set the pager-cache size to the
6063160686
** default value. Except, when opening on an existing shared pager-cache,
6063260687
** do not change the pager-cache size.
6063360688
*/
6063460689
if( sqlite3BtreeSchema(p, 0, 0)==0 ){
6063560690
sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE);
6063660691
}
60692
+
60693
+ pFile = sqlite3PagerFile(pBt->pPager);
60694
+ if( pFile->pMethods ){
60695
+ sqlite3OsFileControlHint(pFile, SQLITE_FCNTL_PDB, (void*)&pBt->db);
60696
+ }
6063760697
}
6063860698
if( mutexOpen ){
6063960699
assert( sqlite3_mutex_held(mutexOpen) );
6064060700
sqlite3_mutex_leave(mutexOpen);
6064160701
}
@@ -60761,11 +60821,11 @@
6076160821
** it without having to hold the mutex.
6076260822
**
6076360823
** Clean out and delete the BtShared object.
6076460824
*/
6076560825
assert( !pBt->pCursor );
60766
- sqlite3PagerClose(pBt->pPager);
60826
+ sqlite3PagerClose(pBt->pPager, p->db);
6076760827
if( pBt->xFreeSchema && pBt->pSchema ){
6076860828
pBt->xFreeSchema(pBt->pSchema);
6076960829
}
6077060830
sqlite3DbFree(0, pBt->pSchema);
6077160831
freeTempSpace(pBt);
@@ -62825,11 +62885,11 @@
6282562885
if( (eOp&0x01)==0 /* (1) */
6282662886
&& offset==0 /* (2) */
6282762887
&& (bEnd || a==ovflSize) /* (6) */
6282862888
&& pBt->inTransaction==TRANS_READ /* (4) */
6282962889
&& (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */
62830
- && pBt->pPage1->aData[19]==0x01 /* (5) */
62890
+ && 0==sqlite3PagerUseWal(pBt->pPager) /* (5) */
6283162891
&& &pBuf[-4]>=pBufStart /* (7) */
6283262892
){
6283362893
u8 aSave[4];
6283462894
u8 *aWrite = &pBuf[-4];
6283562895
assert( aWrite>=pBufStart ); /* hence (7) */
@@ -63081,13 +63141,16 @@
6308163141
}
6308263142
sqlite3BtreeClearCursor(pCur);
6308363143
}
6308463144
6308563145
if( pCur->iPage>=0 ){
63086
- while( pCur->iPage ){
63087
- assert( pCur->apPage[pCur->iPage]!=0 );
63088
- releasePageNotNull(pCur->apPage[pCur->iPage--]);
63146
+ if( pCur->iPage ){
63147
+ do{
63148
+ assert( pCur->apPage[pCur->iPage]!=0 );
63149
+ releasePageNotNull(pCur->apPage[pCur->iPage--]);
63150
+ }while( pCur->iPage);
63151
+ goto skip_init;
6308963152
}
6309063153
}else if( pCur->pgnoRoot==0 ){
6309163154
pCur->eState = CURSOR_INVALID;
6309263155
return SQLITE_OK;
6309363156
}else{
@@ -63094,11 +63157,11 @@
6309463157
assert( pCur->iPage==(-1) );
6309563158
rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0],
6309663159
0, pCur->curPagerFlags);
6309763160
if( rc!=SQLITE_OK ){
6309863161
pCur->eState = CURSOR_INVALID;
63099
- return rc;
63162
+ return rc;
6310063163
}
6310163164
pCur->iPage = 0;
6310263165
pCur->curIntKey = pCur->apPage[0]->intKey;
6310363166
}
6310463167
pRoot = pCur->apPage[0];
@@ -63117,14 +63180,16 @@
6311763180
assert( pRoot->intKey==1 || pRoot->intKey==0 );
6311863181
if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){
6311963182
return SQLITE_CORRUPT_BKPT;
6312063183
}
6312163184
63185
+skip_init:
6312263186
pCur->aiIdx[0] = 0;
6312363187
pCur->info.nSize = 0;
6312463188
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl);
6312563189
63190
+ pRoot = pCur->apPage[0];
6312663191
if( pRoot->nCell>0 ){
6312763192
pCur->eState = CURSOR_VALID;
6312863193
}else if( !pRoot->leaf ){
6312963194
Pgno subpage;
6313063195
if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT;
@@ -67701,11 +67766,11 @@
6770167766
BtShared *pBt = p->pBt;
6770267767
sqlite3BtreeEnter(p);
6770367768
if( pBt->inTransaction!=TRANS_NONE ){
6770467769
rc = SQLITE_LOCKED;
6770567770
}else{
67706
- rc = sqlite3PagerCheckpoint(pBt->pPager, eMode, pnLog, pnCkpt);
67771
+ rc = sqlite3PagerCheckpoint(pBt->pPager, p->db, eMode, pnLog, pnCkpt);
6770767772
}
6770867773
sqlite3BtreeLeave(p);
6770967774
}
6771067775
return rc;
6771167776
}
@@ -75076,11 +75141,11 @@
7507675141
preupdate.keyinfo.enc = ENC(db);
7507775142
preupdate.keyinfo.nField = pTab->nCol;
7507875143
preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder;
7507975144
preupdate.iKey1 = iKey1;
7508075145
preupdate.iKey2 = iKey2;
75081
- preupdate.iPKey = pTab->iPKey;
75146
+ preupdate.pTab = pTab;
7508275147
7508375148
db->pPreUpdate = &preupdate;
7508475149
db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2);
7508575150
db->pPreUpdate = 0;
7508675151
sqlite3DbFree(db, preupdate.aRecord);
@@ -76808,13 +76873,18 @@
7680876873
}
7680976874
7681076875
if( iIdx>=p->pUnpacked->nField ){
7681176876
*ppValue = (sqlite3_value *)columnNullValue();
7681276877
}else{
76878
+ Mem *pMem = *ppValue = &p->pUnpacked->aMem[iIdx];
7681376879
*ppValue = &p->pUnpacked->aMem[iIdx];
76814
- if( iIdx==p->iPKey ){
76815
- sqlite3VdbeMemSetInt64(*ppValue, p->iKey1);
76880
+ if( iIdx==p->pTab->iPKey ){
76881
+ sqlite3VdbeMemSetInt64(pMem, p->iKey1);
76882
+ }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
76883
+ if( pMem->flags & MEM_Int ){
76884
+ sqlite3VdbeMemRealify(pMem);
76885
+ }
7681676886
}
7681776887
}
7681876888
7681976889
preupdate_old_out:
7682076890
sqlite3Error(db, rc);
@@ -76887,11 +76957,11 @@
7688776957
}
7688876958
if( iIdx>=pUnpack->nField ){
7688976959
pMem = (sqlite3_value *)columnNullValue();
7689076960
}else{
7689176961
pMem = &pUnpack->aMem[iIdx];
76892
- if( iIdx==p->iPKey ){
76962
+ if( iIdx==p->pTab->iPKey ){
7689376963
sqlite3VdbeMemSetInt64(pMem, p->iKey2);
7689476964
}
7689576965
}
7689676966
}else{
7689776967
/* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required
@@ -76908,11 +76978,11 @@
7690876978
}
7690976979
}
7691076980
assert( iIdx>=0 && iIdx<p->pCsr->nField );
7691176981
pMem = &p->aNew[iIdx];
7691276982
if( pMem->flags==0 ){
76913
- if( iIdx==p->iPKey ){
76983
+ if( iIdx==p->pTab->iPKey ){
7691476984
sqlite3VdbeMemSetInt64(pMem, p->iKey2);
7691576985
}else{
7691676986
rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]);
7691776987
if( rc!=SQLITE_OK ) goto preupdate_new_out;
7691876988
}
@@ -79286,12 +79356,11 @@
7928679356
** or not both operands are null.
7928779357
*/
7928879358
assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
7928979359
assert( (flags1 & MEM_Cleared)==0 );
7929079360
assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 );
79291
- if( (flags1&MEM_Null)!=0
79292
- && (flags3&MEM_Null)!=0
79361
+ if( (flags1&flags3&MEM_Null)!=0
7929379362
&& (flags3&MEM_Cleared)==0
7929479363
){
7929579364
res = 0; /* Operands are equal */
7929679365
}else{
7929779366
res = 1; /* Operands are not equal */
@@ -81554,11 +81623,11 @@
8155481623
8155581624
REGISTER_TRACE(pOp->p3, pMem);
8155681625
sqlite3VdbeMemIntegerify(pMem);
8155781626
assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */
8155881627
if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){
81559
- rc = SQLITE_FULL; /* IMP: R-12275-61338 */
81628
+ rc = SQLITE_FULL; /* IMP: R-17817-00630 */
8156081629
goto abort_due_to_error;
8156181630
}
8156281631
if( v<pMem->u.i+1 ){
8156381632
v = pMem->u.i + 1;
8156481633
}
@@ -82321,10 +82390,17 @@
8232182390
** This flag avoids doing an extra seek.
8232282391
**
8232382392
** This instruction only works for indices. The equivalent instruction
8232482393
** for tables is OP_Insert.
8232582394
*/
82395
+/* Opcode: SorterInsert P1 P2 * * *
82396
+** Synopsis: key=r[P2]
82397
+**
82398
+** Register P2 holds an SQL index key made using the
82399
+** MakeRecord instructions. This opcode writes that key
82400
+** into the sorter P1. Data for the entry is nil.
82401
+*/
8232682402
case OP_SorterInsert: /* in2 */
8232782403
case OP_IdxInsert: { /* in2 */
8232882404
VdbeCursor *pC;
8232982405
BtreePayload x;
8233082406
@@ -83549,11 +83625,11 @@
8354983625
/* If leaving WAL mode, close the log file. If successful, the call
8355083626
** to PagerCloseWal() checkpoints and deletes the write-ahead-log
8355183627
** file. An EXCLUSIVE lock may still be held on the database file
8355283628
** after a successful return.
8355383629
*/
83554
- rc = sqlite3PagerCloseWal(pPager);
83630
+ rc = sqlite3PagerCloseWal(pPager, db);
8355583631
if( rc==SQLITE_OK ){
8355683632
sqlite3PagerSetJournalMode(pPager, eNew);
8355783633
}
8355883634
}else if( eOld==PAGER_JOURNALMODE_MEMORY ){
8355983635
/* Cannot transition directly from MEMORY to WAL. Use mode OFF
@@ -94292,15 +94368,14 @@
9429294368
&& (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab)
9429394369
|| sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) )
9429494370
){
9429594371
return 1;
9429694372
}
94297
- if( pE2->op==TK_NOTNULL
94298
- && sqlite3ExprCompare(pE1->pLeft, pE2->pLeft, iTab)==0
94299
- && (pE1->op!=TK_ISNULL && pE1->op!=TK_IS)
94300
- ){
94301
- return 1;
94373
+ if( pE2->op==TK_NOTNULL && pE1->op!=TK_ISNULL && pE1->op!=TK_IS ){
94374
+ Expr *pX = sqlite3ExprSkipCollate(pE1->pLeft);
94375
+ testcase( pX!=pE1->pLeft );
94376
+ if( sqlite3ExprCompare(pX, pE2->pLeft, iTab)==0 ) return 1;
9430294377
}
9430394378
return 0;
9430494379
}
9430594380
9430694381
/*
@@ -122354,11 +122429,11 @@
122354122429
}
122355122430
#endif
122356122431
122357122432
sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size);
122358122433
sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0));
122359
- sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF);
122434
+ sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF|PAGER_CACHESPILL);
122360122435
122361122436
/* Begin a transaction and take an exclusive lock on the main database
122362122437
** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below,
122363122438
** to ensure that we do not try to change the page-size on a WAL database.
122364122439
*/
@@ -127537,10 +127612,11 @@
127537127612
Expr *pNew;
127538127613
Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i);
127539127614
Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i);
127540127615
127541127616
pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight, 0);
127617
+ transferJoinMarkings(pNew, pExpr);
127542127618
idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC);
127543127619
exprAnalyze(pSrc, pWC, idxNew);
127544127620
}
127545127621
pTerm = &pWC->a[idxTerm];
127546127622
pTerm->wtFlags = TERM_CODED|TERM_VIRTUAL; /* Disable the original */
@@ -127978,15 +128054,17 @@
127978128054
Expr *pX; /* An expression being tested */
127979128055
WhereClause *pWC; /* Shorthand for pScan->pWC */
127980128056
WhereTerm *pTerm; /* The term being tested */
127981128057
int k = pScan->k; /* Where to start scanning */
127982128058
127983
- while( pScan->iEquiv<=pScan->nEquiv ){
127984
- iCur = pScan->aiCur[pScan->iEquiv-1];
128059
+ assert( pScan->iEquiv<=pScan->nEquiv );
128060
+ pWC = pScan->pWC;
128061
+ while(1){
127985128062
iColumn = pScan->aiColumn[pScan->iEquiv-1];
127986
- if( iColumn==XN_EXPR && pScan->pIdxExpr==0 ) return 0;
127987
- while( (pWC = pScan->pWC)!=0 ){
128063
+ iCur = pScan->aiCur[pScan->iEquiv-1];
128064
+ assert( pWC!=0 );
128065
+ do{
127988128066
for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
127989128067
if( pTerm->leftCursor==iCur
127990128068
&& pTerm->u.leftColumn==iColumn
127991128069
&& (iColumn!=XN_EXPR
127992128070
|| sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0)
@@ -128032,19 +128110,21 @@
128032128110
&& pX->iColumn==pScan->aiColumn[0]
128033128111
){
128034128112
testcase( pTerm->eOperator & WO_IS );
128035128113
continue;
128036128114
}
128115
+ pScan->pWC = pWC;
128037128116
pScan->k = k+1;
128038128117
return pTerm;
128039128118
}
128040128119
}
128041128120
}
128042
- pScan->pWC = pScan->pWC->pOuter;
128121
+ pWC = pWC->pOuter;
128043128122
k = 0;
128044
- }
128045
- pScan->pWC = pScan->pOrigWC;
128123
+ }while( pWC!=0 );
128124
+ if( pScan->iEquiv>=pScan->nEquiv ) break;
128125
+ pWC = pScan->pOrigWC;
128046128126
k = 0;
128047128127
pScan->iEquiv++;
128048128128
}
128049128129
return 0;
128050128130
}
@@ -128074,28 +128154,28 @@
128074128154
int iCur, /* Cursor to scan for */
128075128155
int iColumn, /* Column to scan for */
128076128156
u32 opMask, /* Operator(s) to scan for */
128077128157
Index *pIdx /* Must be compatible with this index */
128078128158
){
128079
- int j = 0;
128080
-
128081
- /* memset(pScan, 0, sizeof(*pScan)); */
128082128159
pScan->pOrigWC = pWC;
128083128160
pScan->pWC = pWC;
128084128161
pScan->pIdxExpr = 0;
128162
+ pScan->idxaff = 0;
128163
+ pScan->zCollName = 0;
128085128164
if( pIdx ){
128086
- j = iColumn;
128165
+ int j = iColumn;
128087128166
iColumn = pIdx->aiColumn[j];
128088
- if( iColumn==XN_EXPR ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
128089
- if( iColumn==pIdx->pTable->iPKey ) iColumn = XN_ROWID;
128090
- }
128091
- if( pIdx && iColumn>=0 ){
128092
- pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
128093
- pScan->zCollName = pIdx->azColl[j];
128094
- }else{
128095
- pScan->idxaff = 0;
128096
- pScan->zCollName = 0;
128167
+ if( iColumn==XN_EXPR ){
128168
+ pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
128169
+ }else if( iColumn==pIdx->pTable->iPKey ){
128170
+ iColumn = XN_ROWID;
128171
+ }else if( iColumn>=0 ){
128172
+ pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
128173
+ pScan->zCollName = pIdx->azColl[j];
128174
+ }
128175
+ }else if( iColumn==XN_EXPR ){
128176
+ return 0;
128097128177
}
128098128178
pScan->opMask = opMask;
128099128179
pScan->k = 0;
128100128180
pScan->aiCur[0] = iCur;
128101128181
pScan->aiColumn[0] = iColumn;
@@ -132640,17 +132720,19 @@
132640132720
pLevel->addrLikeRep);
132641132721
VdbeCoverage(v);
132642132722
}
132643132723
#endif
132644132724
if( pLevel->iLeftJoin ){
132725
+ int ws = pLoop->wsFlags;
132645132726
addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
132646
- assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
132647
- || (pLoop->wsFlags & WHERE_INDEXED)!=0 );
132648
- if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 ){
132727
+ assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 );
132728
+ if( (ws & WHERE_IDX_ONLY)==0 ){
132649132729
sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor);
132650132730
}
132651
- if( pLoop->wsFlags & WHERE_INDEXED ){
132731
+ if( (ws & WHERE_INDEXED)
132732
+ || ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx)
132733
+ ){
132652132734
sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
132653132735
}
132654132736
if( pLevel->op==OP_Return ){
132655132737
sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst);
132656132738
}else{
@@ -138612,10 +138694,11 @@
138612138694
} aFlagOp[] = {
138613138695
{ SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys },
138614138696
{ SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger },
138615138697
{ SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer },
138616138698
{ SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension },
138699
+ { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose },
138617138700
};
138618138701
unsigned int i;
138619138702
rc = SQLITE_ERROR; /* IMP: R-42790-23372 */
138620138703
for(i=0; i<ArraySize(aFlagOp); i++){
138621138704
if( aFlagOp[i].op==op ){
@@ -139908,10 +139991,17 @@
139908139991
db->busyHandler.nBusy = 0;
139909139992
rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt);
139910139993
sqlite3Error(db, rc);
139911139994
}
139912139995
rc = sqlite3ApiExit(db, rc);
139996
+
139997
+ /* If there are no active statements, clear the interrupt flag at this
139998
+ ** point. */
139999
+ if( db->nVdbeActive==0 ){
140000
+ db->u1.isInterrupted = 0;
140001
+ }
140002
+
139913140003
sqlite3_mutex_leave(db->mutex);
139914140004
return rc;
139915140005
#endif
139916140006
}
139917140007
@@ -140410,10 +140500,11 @@
140410140500
int octet = (sqlite3HexToInt(zUri[iIn++]) << 4);
140411140501
octet += sqlite3HexToInt(zUri[iIn++]);
140412140502
140413140503
assert( octet>=0 && octet<256 );
140414140504
if( octet==0 ){
140505
+#ifndef SQLITE_ENABLE_URI_00_ERROR
140415140506
/* This branch is taken when "%00" appears within the URI. In this
140416140507
** case we ignore all text in the remainder of the path, name or
140417140508
** value currently being parsed. So ignore the current character
140418140509
** and skip to the next "?", "=" or "&", as appropriate. */
140419140510
while( (c = zUri[iIn])!=0 && c!='#'
@@ -140422,10 +140513,16 @@
140422140513
&& (eState!=2 || c!='&')
140423140514
){
140424140515
iIn++;
140425140516
}
140426140517
continue;
140518
+#else
140519
+ /* If ENABLE_URI_00_ERROR is defined, "%00" in a URI is an error. */
140520
+ *pzErrMsg = sqlite3_mprintf("unexpected %%00 in uri");
140521
+ rc = SQLITE_ERROR;
140522
+ goto parse_uri_out;
140523
+#endif
140427140524
}
140428140525
c = octet;
140429140526
}else if( eState==1 && (c=='&' || c=='=') ){
140430140527
if( zFile[iOut-1]==0 ){
140431140528
/* An empty option name. Ignore this option altogether. */
@@ -165207,11 +165304,11 @@
165207165304
** of the locale to use. Passing an empty string ("") or SQL NULL value
165208165305
** as the second argument is the same as invoking the 1 argument version
165209165306
** of upper() or lower().
165210165307
**
165211165308
** lower('I', 'en_us') -> 'i'
165212
-** lower('I', 'tr_tr') -> 'ı' (small dotless i)
165309
+** lower('I', 'tr_tr') -> '\u131' (small dotless i)
165213165310
**
165214165311
** http://www.icu-project.org/userguide/posix.html#case_mappings
165215165312
*/
165216165313
static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
165217165314
const UChar *zInput; /* Pointer to input string */
@@ -195596,11 +195693,11 @@
195596195693
int nArg, /* Number of args */
195597195694
sqlite3_value **apUnused /* Function arguments */
195598195695
){
195599195696
assert( nArg==0 );
195600195697
UNUSED_PARAM2(nArg, apUnused);
195601
- sqlite3_result_text(pCtx, "fts5: 2016-10-14 10:20:30 707875582fcba352b4906a595ad89198d84711d8", -1, SQLITE_TRANSIENT);
195698
+ sqlite3_result_text(pCtx, "fts5: 2016-10-26 16:05:10 ec9dab8054c71d112c68f58a45821b38c2a45677", -1, SQLITE_TRANSIENT);
195602195699
}
195603195700
195604195701
static int fts5Init(sqlite3 *db){
195605195702
static const sqlite3_module fts5Mod = {
195606195703
/* iVersion */ 2,
195607195704
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
1 /******************************************************************************
2 ** This file is an amalgamation of many separate C source files from SQLite
3 ** version 3.15.0. By combining all the individual C code files into this
4 ** single large file, the entire code can be compiled as a single translation
5 ** unit. This allows many compilers to do optimizations that would not be
6 ** possible if the files were compiled separately. Performance improvements
7 ** of 5% or more are commonly seen when SQLite is compiled as a single
8 ** translation unit.
@@ -379,13 +379,13 @@
379 **
380 ** See also: [sqlite3_libversion()],
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 **
@@ -1235,10 +1235,16 @@
1235 ** <li>[[SQLITE_FCNTL_HAS_MOVED]]
1236 ** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a
1237 ** pointer to an integer and it writes a boolean into that integer depending
1238 ** on whether or not the file has been renamed, moved, or deleted since it
1239 ** was first opened.
 
 
 
 
 
 
1240 **
1241 ** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]]
1242 ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This
1243 ** opcode causes the xFileControl method to swap the file handle with the one
1244 ** pointed to by the pArg argument. This capability is used during testing
@@ -1286,10 +1292,12 @@
1286 #define SQLITE_FCNTL_WAL_BLOCK 24
1287 #define SQLITE_FCNTL_ZIPVFS 25
1288 #define SQLITE_FCNTL_RBU 26
1289 #define SQLITE_FCNTL_VFS_POINTER 27
1290 #define SQLITE_FCNTL_JOURNAL_POINTER 28
 
 
1291
1292 /* deprecated names */
1293 #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
1294 #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
1295 #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
@@ -2238,18 +2246,31 @@
2238 ** does not make a copy of the new main schema name string, so the application
2239 ** must ensure that the argument passed into this DBCONFIG option is unchanged
2240 ** until after the database connection closes.
2241 ** </dd>
2242 **
 
 
 
 
 
 
 
 
 
 
 
 
2243 ** </dl>
2244 */
2245 #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
2246 #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
2247 #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */
2248 #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
2249 #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */
2250 #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */
 
2251
2252
2253 /*
2254 ** CAPI3REF: Enable Or Disable Extended Result Codes
2255 ** METHOD: sqlite3
@@ -12675,11 +12696,11 @@
12675 #define OP_SorterData 120 /* synopsis: r[P2]=data */
12676 #define OP_RowKey 121 /* synopsis: r[P2]=key */
12677 #define OP_RowData 122 /* synopsis: r[P2]=data */
12678 #define OP_Rowid 123 /* synopsis: r[P2]=rowid */
12679 #define OP_NullRow 124
12680 #define OP_SorterInsert 125
12681 #define OP_IdxInsert 126 /* synopsis: key=r[P2] */
12682 #define OP_IdxDelete 127 /* synopsis: key=r[P2@P3] */
12683 #define OP_Seek 128 /* synopsis: Move P3 to P1.rowid */
12684 #define OP_IdxRowid 129 /* synopsis: r[P2]=rowid */
12685 #define OP_Destroy 130
@@ -13030,11 +13051,11 @@
13030 int,
13031 int,
13032 int,
13033 void(*)(DbPage*)
13034 );
13035 SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager);
13036 SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
13037
13038 /* Functions used to configure a Pager object. */
13039 SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *);
13040 SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int);
@@ -13081,19 +13102,22 @@
13081 SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
13082 SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
13083 SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager);
13084
13085 #ifndef SQLITE_OMIT_WAL
13086 SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*);
13087 SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager);
13088 SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager);
13089 SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
13090 SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager);
 
13091 # ifdef SQLITE_ENABLE_SNAPSHOT
13092 SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot);
13093 SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot);
13094 # endif
 
 
13095 #endif
13096
13097 #ifdef SQLITE_ENABLE_ZIPVFS
13098 SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager);
13099 #endif
@@ -14060,10 +14084,11 @@
14060 #define SQLITE_QueryOnly 0x04000000 /* Disable database changes */
14061 #define SQLITE_VdbeEQP 0x08000000 /* Debug EXPLAIN QUERY PLAN */
14062 #define SQLITE_Vacuum 0x10000000 /* Currently in a VACUUM */
14063 #define SQLITE_CellSizeCk 0x20000000 /* Check btree cell sizes on load */
14064 #define SQLITE_Fts3Tokenizer 0x40000000 /* Enable fts3_tokenizer(2) */
 
14065
14066
14067 /*
14068 ** Bits of the sqlite3.dbOptFlags field that are used by the
14069 ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
@@ -17268,10 +17293,13 @@
17268 #if SQLITE_DEFAULT_LOCKING_MODE
17269 "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
17270 #endif
17271 #if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc)
17272 "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
 
 
 
17273 #endif
17274 #if SQLITE_DISABLE_DIRSYNC
17275 "DISABLE_DIRSYNC",
17276 #endif
17277 #if SQLITE_DISABLE_LFS
@@ -17354,10 +17382,13 @@
17354 #if SQLITE_ENABLE_UNLOCK_NOTIFY
17355 "ENABLE_UNLOCK_NOTIFY",
17356 #endif
17357 #if SQLITE_ENABLE_UPDATE_DELETE_LIMIT
17358 "ENABLE_UPDATE_DELETE_LIMIT",
 
 
 
17359 #endif
17360 #if SQLITE_HAS_CODEC
17361 "HAS_CODEC",
17362 #endif
17363 #if HAVE_ISNAN || SQLITE_HAVE_ISNAN
@@ -18105,12 +18136,12 @@
18105 UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */
18106 UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */
18107 int iNewReg; /* Register for new.* values */
18108 i64 iKey1; /* First key value passed to hook */
18109 i64 iKey2; /* Second key value passed to hook */
18110 int iPKey; /* If not negative index of IPK column */
18111 Mem *aNew; /* Array of new.* values */
 
18112 };
18113
18114 /*
18115 ** Function prototypes
18116 */
@@ -24598,13 +24629,12 @@
24598 char *zNew;
24599 size_t n;
24600 if( z==0 ){
24601 return 0;
24602 }
24603 n = sqlite3Strlen30(z) + 1;
24604 assert( (n&0x7fffffff)==n );
24605 zNew = sqlite3DbMallocRaw(db, (int)n);
24606 if( zNew ){
24607 memcpy(zNew, z, n);
24608 }
24609 return zNew;
24610 }
@@ -29127,11 +29157,11 @@
29127 /* 120 */ "SorterData" OpHelp("r[P2]=data"),
29128 /* 121 */ "RowKey" OpHelp("r[P2]=key"),
29129 /* 122 */ "RowData" OpHelp("r[P2]=data"),
29130 /* 123 */ "Rowid" OpHelp("r[P2]=rowid"),
29131 /* 124 */ "NullRow" OpHelp(""),
29132 /* 125 */ "SorterInsert" OpHelp(""),
29133 /* 126 */ "IdxInsert" OpHelp("key=r[P2]"),
29134 /* 127 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
29135 /* 128 */ "Seek" OpHelp("Move P3 to P1.rowid"),
29136 /* 129 */ "IdxRowid" OpHelp("r[P2]=rowid"),
29137 /* 130 */ "Destroy" OpHelp(""),
@@ -40674,10 +40704,16 @@
40674 a[1] = winIoerrRetryDelay;
40675 }
40676 OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
40677 return SQLITE_OK;
40678 }
 
 
 
 
 
 
40679 #ifdef SQLITE_TEST
40680 case SQLITE_FCNTL_WIN32_SET_HANDLE: {
40681 LPHANDLE phFile = (LPHANDLE)pArg;
40682 HANDLE hOldFile = pFile->h;
40683 pFile->h = *phFile;
@@ -46249,21 +46285,21 @@
46249 #define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */
46250
46251 #ifdef SQLITE_OMIT_WAL
46252 # define sqlite3WalOpen(x,y,z) 0
46253 # define sqlite3WalLimit(x,y)
46254 # define sqlite3WalClose(w,x,y,z) 0
46255 # define sqlite3WalBeginReadTransaction(y,z) 0
46256 # define sqlite3WalEndReadTransaction(z)
46257 # define sqlite3WalDbsize(y) 0
46258 # define sqlite3WalBeginWriteTransaction(y) 0
46259 # define sqlite3WalEndWriteTransaction(x) 0
46260 # define sqlite3WalUndo(x,y,z) 0
46261 # define sqlite3WalSavepoint(y,z)
46262 # define sqlite3WalSavepointUndo(y,z) 0
46263 # define sqlite3WalFrames(u,v,w,x,y,z) 0
46264 # define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0
46265 # define sqlite3WalCallback(z) 0
46266 # define sqlite3WalExclusiveMode(y,z) 0
46267 # define sqlite3WalHeapMemory(z) 0
46268 # define sqlite3WalFramesize(z) 0
46269 # define sqlite3WalFindFrame(x,y,z) 0
@@ -46277,11 +46313,11 @@
46277 */
46278 typedef struct Wal Wal;
46279
46280 /* Open and close a connection to a write-ahead log. */
46281 SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**);
46282 SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *);
46283
46284 /* Set the limiting size of a WAL file. */
46285 SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64);
46286
46287 /* Used by readers to open (lock) and close (unlock) a snapshot. A
@@ -46320,10 +46356,11 @@
46320 SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int);
46321
46322 /* Copy pages from the log to the database file */
46323 SQLITE_PRIVATE int sqlite3WalCheckpoint(
46324 Wal *pWal, /* Write-ahead log connection */
 
46325 int eMode, /* One of PASSIVE, FULL and RESTART */
46326 int (*xBusy)(void*), /* Function to call when busy */
46327 void *pBusyArg, /* Context argument for xBusyHandler */
46328 int sync_flags, /* Flags to sync db file with (or 0) */
46329 int nBuf, /* Size of buffer nBuf */
@@ -47164,13 +47201,14 @@
47164 /*
47165 ** Return true if this pager uses a write-ahead log instead of the usual
47166 ** rollback journal. Otherwise false.
47167 */
47168 #ifndef SQLITE_OMIT_WAL
47169 static int pagerUseWal(Pager *pPager){
47170 return (pPager->pWal!=0);
47171 }
 
47172 #else
47173 # define pagerUseWal(x) 0
47174 # define pagerRollbackWal(x) 0
47175 # define pagerWalFrames(v,w,x,y) 0
47176 # define pagerOpenWalIfPresent(z) SQLITE_OK
@@ -50368,21 +50406,22 @@
50368 ** This function always succeeds. If a transaction is active an attempt
50369 ** is made to roll it back. If an error occurs during the rollback
50370 ** a hot journal may be left in the filesystem but no error is returned
50371 ** to the caller.
50372 */
50373 SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
50374 u8 *pTmp = (u8 *)pPager->pTmpSpace;
50375
 
50376 assert( assert_pager_state(pPager) );
50377 disable_simulated_io_errors();
50378 sqlite3BeginBenignMalloc();
50379 pagerFreeMapHdrs(pPager);
50380 /* pPager->errCode = 0; */
50381 pPager->exclusiveMode = 0;
50382 #ifndef SQLITE_OMIT_WAL
50383 sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp);
50384 pPager->pWal = 0;
50385 #endif
50386 pager_reset(pPager);
50387 if( MEMDB ){
50388 pager_unlock(pPager);
@@ -53541,14 +53580,20 @@
53541 ** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint()
53542 ** or wal_blocking_checkpoint() API functions.
53543 **
53544 ** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
53545 */
53546 SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){
 
 
 
 
 
 
53547 int rc = SQLITE_OK;
53548 if( pPager->pWal ){
53549 rc = sqlite3WalCheckpoint(pPager->pWal, eMode,
53550 (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
53551 pPager->pBusyHandlerArg,
53552 pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
53553 pnLog, pnCkpt
53554 );
@@ -53676,11 +53721,11 @@
53676 ** Before closing the log file, this function attempts to take an
53677 ** EXCLUSIVE lock on the database file. If this cannot be obtained, an
53678 ** error (SQLITE_BUSY) is returned and the log connection is not closed.
53679 ** If successful, the EXCLUSIVE lock is not released before returning.
53680 */
53681 SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){
53682 int rc = SQLITE_OK;
53683
53684 assert( pPager->journalMode==PAGER_JOURNALMODE_WAL );
53685
53686 /* If the log file is not already open, but does exist in the file-system,
@@ -53704,11 +53749,11 @@
53704 ** the database file, the log and log-summary files will be deleted.
53705 */
53706 if( rc==SQLITE_OK && pPager->pWal ){
53707 rc = pagerExclusiveLock(pPager);
53708 if( rc==SQLITE_OK ){
53709 rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags,
53710 pPager->pageSize, (u8*)pPager->pTmpSpace);
53711 pPager->pWal = 0;
53712 pagerFixMaplimit(pPager);
53713 if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK);
53714 }
@@ -55487,10 +55532,11 @@
55487 ** checkpoint is running (in any other thread or process) at the same
55488 ** time.
55489 */
55490 static int walCheckpoint(
55491 Wal *pWal, /* Wal connection */
 
55492 int eMode, /* One of PASSIVE, FULL or RESTART */
55493 int (*xBusy)(void*), /* Function to call when busy */
55494 void *pBusyArg, /* Context argument for xBusyHandler */
55495 int sync_flags, /* Flags for OsSync() (or 0) */
55496 u8 *zBuf /* Temporary buffer to use */
@@ -55581,10 +55627,14 @@
55581
55582 /* Iterate through the contents of the WAL, copying data to the db file */
55583 while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
55584 i64 iOffset;
55585 assert( walFramePgno(pWal, iFrame)==iDbpage );
 
 
 
 
55586 if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){
55587 continue;
55588 }
55589 iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE;
55590 /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */
@@ -55685,10 +55735,11 @@
55685 /*
55686 ** Close a connection to a log file.
55687 */
55688 SQLITE_PRIVATE int sqlite3WalClose(
55689 Wal *pWal, /* Wal to close */
 
55690 int sync_flags, /* Flags to pass to OsSync() (or 0) */
55691 int nBuf,
55692 u8 *zBuf /* Buffer of at least nBuf bytes */
55693 ){
55694 int rc = SQLITE_OK;
@@ -55701,17 +55752,18 @@
55701 ** the database. In this case checkpoint the database and unlink both
55702 ** the wal and wal-index files.
55703 **
55704 ** The EXCLUSIVE lock is not released before returning.
55705 */
55706 rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE);
55707 if( rc==SQLITE_OK ){
 
55708 if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
55709 pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
55710 }
55711 rc = sqlite3WalCheckpoint(
55712 pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0
55713 );
55714 if( rc==SQLITE_OK ){
55715 int bPersist = -1;
55716 sqlite3OsFileControlHint(
55717 pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersist
@@ -56955,10 +57007,11 @@
56955 ** If parameter xBusy is not NULL, it is a pointer to a busy-handler
56956 ** callback. In this case this function runs a blocking checkpoint.
56957 */
56958 SQLITE_PRIVATE int sqlite3WalCheckpoint(
56959 Wal *pWal, /* Wal connection */
 
56960 int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */
56961 int (*xBusy)(void*), /* Function to call when busy */
56962 void *pBusyArg, /* Context argument for xBusyHandler */
56963 int sync_flags, /* Flags to sync db file with (or 0) */
56964 int nBuf, /* Size of temporary buffer */
@@ -57029,11 +57082,11 @@
57029 if( rc==SQLITE_OK ){
57030
57031 if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
57032 rc = SQLITE_CORRUPT_BKPT;
57033 }else{
57034 rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf);
57035 }
57036
57037 /* If no error occurred, set the output variables. */
57038 if( rc==SQLITE_OK || rc==SQLITE_BUSY ){
57039 if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame;
@@ -60619,23 +60672,30 @@
60619 *ppBtree = p;
60620
60621 btree_open_out:
60622 if( rc!=SQLITE_OK ){
60623 if( pBt && pBt->pPager ){
60624 sqlite3PagerClose(pBt->pPager);
60625 }
60626 sqlite3_free(pBt);
60627 sqlite3_free(p);
60628 *ppBtree = 0;
60629 }else{
 
 
60630 /* If the B-Tree was successfully opened, set the pager-cache size to the
60631 ** default value. Except, when opening on an existing shared pager-cache,
60632 ** do not change the pager-cache size.
60633 */
60634 if( sqlite3BtreeSchema(p, 0, 0)==0 ){
60635 sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE);
60636 }
 
 
 
 
 
60637 }
60638 if( mutexOpen ){
60639 assert( sqlite3_mutex_held(mutexOpen) );
60640 sqlite3_mutex_leave(mutexOpen);
60641 }
@@ -60761,11 +60821,11 @@
60761 ** it without having to hold the mutex.
60762 **
60763 ** Clean out and delete the BtShared object.
60764 */
60765 assert( !pBt->pCursor );
60766 sqlite3PagerClose(pBt->pPager);
60767 if( pBt->xFreeSchema && pBt->pSchema ){
60768 pBt->xFreeSchema(pBt->pSchema);
60769 }
60770 sqlite3DbFree(0, pBt->pSchema);
60771 freeTempSpace(pBt);
@@ -62825,11 +62885,11 @@
62825 if( (eOp&0x01)==0 /* (1) */
62826 && offset==0 /* (2) */
62827 && (bEnd || a==ovflSize) /* (6) */
62828 && pBt->inTransaction==TRANS_READ /* (4) */
62829 && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */
62830 && pBt->pPage1->aData[19]==0x01 /* (5) */
62831 && &pBuf[-4]>=pBufStart /* (7) */
62832 ){
62833 u8 aSave[4];
62834 u8 *aWrite = &pBuf[-4];
62835 assert( aWrite>=pBufStart ); /* hence (7) */
@@ -63081,13 +63141,16 @@
63081 }
63082 sqlite3BtreeClearCursor(pCur);
63083 }
63084
63085 if( pCur->iPage>=0 ){
63086 while( pCur->iPage ){
63087 assert( pCur->apPage[pCur->iPage]!=0 );
63088 releasePageNotNull(pCur->apPage[pCur->iPage--]);
 
 
 
63089 }
63090 }else if( pCur->pgnoRoot==0 ){
63091 pCur->eState = CURSOR_INVALID;
63092 return SQLITE_OK;
63093 }else{
@@ -63094,11 +63157,11 @@
63094 assert( pCur->iPage==(-1) );
63095 rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0],
63096 0, pCur->curPagerFlags);
63097 if( rc!=SQLITE_OK ){
63098 pCur->eState = CURSOR_INVALID;
63099 return rc;
63100 }
63101 pCur->iPage = 0;
63102 pCur->curIntKey = pCur->apPage[0]->intKey;
63103 }
63104 pRoot = pCur->apPage[0];
@@ -63117,14 +63180,16 @@
63117 assert( pRoot->intKey==1 || pRoot->intKey==0 );
63118 if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){
63119 return SQLITE_CORRUPT_BKPT;
63120 }
63121
 
63122 pCur->aiIdx[0] = 0;
63123 pCur->info.nSize = 0;
63124 pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl);
63125
 
63126 if( pRoot->nCell>0 ){
63127 pCur->eState = CURSOR_VALID;
63128 }else if( !pRoot->leaf ){
63129 Pgno subpage;
63130 if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT;
@@ -67701,11 +67766,11 @@
67701 BtShared *pBt = p->pBt;
67702 sqlite3BtreeEnter(p);
67703 if( pBt->inTransaction!=TRANS_NONE ){
67704 rc = SQLITE_LOCKED;
67705 }else{
67706 rc = sqlite3PagerCheckpoint(pBt->pPager, eMode, pnLog, pnCkpt);
67707 }
67708 sqlite3BtreeLeave(p);
67709 }
67710 return rc;
67711 }
@@ -75076,11 +75141,11 @@
75076 preupdate.keyinfo.enc = ENC(db);
75077 preupdate.keyinfo.nField = pTab->nCol;
75078 preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder;
75079 preupdate.iKey1 = iKey1;
75080 preupdate.iKey2 = iKey2;
75081 preupdate.iPKey = pTab->iPKey;
75082
75083 db->pPreUpdate = &preupdate;
75084 db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2);
75085 db->pPreUpdate = 0;
75086 sqlite3DbFree(db, preupdate.aRecord);
@@ -76808,13 +76873,18 @@
76808 }
76809
76810 if( iIdx>=p->pUnpacked->nField ){
76811 *ppValue = (sqlite3_value *)columnNullValue();
76812 }else{
 
76813 *ppValue = &p->pUnpacked->aMem[iIdx];
76814 if( iIdx==p->iPKey ){
76815 sqlite3VdbeMemSetInt64(*ppValue, p->iKey1);
 
 
 
 
76816 }
76817 }
76818
76819 preupdate_old_out:
76820 sqlite3Error(db, rc);
@@ -76887,11 +76957,11 @@
76887 }
76888 if( iIdx>=pUnpack->nField ){
76889 pMem = (sqlite3_value *)columnNullValue();
76890 }else{
76891 pMem = &pUnpack->aMem[iIdx];
76892 if( iIdx==p->iPKey ){
76893 sqlite3VdbeMemSetInt64(pMem, p->iKey2);
76894 }
76895 }
76896 }else{
76897 /* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required
@@ -76908,11 +76978,11 @@
76908 }
76909 }
76910 assert( iIdx>=0 && iIdx<p->pCsr->nField );
76911 pMem = &p->aNew[iIdx];
76912 if( pMem->flags==0 ){
76913 if( iIdx==p->iPKey ){
76914 sqlite3VdbeMemSetInt64(pMem, p->iKey2);
76915 }else{
76916 rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]);
76917 if( rc!=SQLITE_OK ) goto preupdate_new_out;
76918 }
@@ -79286,12 +79356,11 @@
79286 ** or not both operands are null.
79287 */
79288 assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
79289 assert( (flags1 & MEM_Cleared)==0 );
79290 assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 );
79291 if( (flags1&MEM_Null)!=0
79292 && (flags3&MEM_Null)!=0
79293 && (flags3&MEM_Cleared)==0
79294 ){
79295 res = 0; /* Operands are equal */
79296 }else{
79297 res = 1; /* Operands are not equal */
@@ -81554,11 +81623,11 @@
81554
81555 REGISTER_TRACE(pOp->p3, pMem);
81556 sqlite3VdbeMemIntegerify(pMem);
81557 assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */
81558 if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){
81559 rc = SQLITE_FULL; /* IMP: R-12275-61338 */
81560 goto abort_due_to_error;
81561 }
81562 if( v<pMem->u.i+1 ){
81563 v = pMem->u.i + 1;
81564 }
@@ -82321,10 +82390,17 @@
82321 ** This flag avoids doing an extra seek.
82322 **
82323 ** This instruction only works for indices. The equivalent instruction
82324 ** for tables is OP_Insert.
82325 */
 
 
 
 
 
 
 
82326 case OP_SorterInsert: /* in2 */
82327 case OP_IdxInsert: { /* in2 */
82328 VdbeCursor *pC;
82329 BtreePayload x;
82330
@@ -83549,11 +83625,11 @@
83549 /* If leaving WAL mode, close the log file. If successful, the call
83550 ** to PagerCloseWal() checkpoints and deletes the write-ahead-log
83551 ** file. An EXCLUSIVE lock may still be held on the database file
83552 ** after a successful return.
83553 */
83554 rc = sqlite3PagerCloseWal(pPager);
83555 if( rc==SQLITE_OK ){
83556 sqlite3PagerSetJournalMode(pPager, eNew);
83557 }
83558 }else if( eOld==PAGER_JOURNALMODE_MEMORY ){
83559 /* Cannot transition directly from MEMORY to WAL. Use mode OFF
@@ -94292,15 +94368,14 @@
94292 && (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab)
94293 || sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) )
94294 ){
94295 return 1;
94296 }
94297 if( pE2->op==TK_NOTNULL
94298 && sqlite3ExprCompare(pE1->pLeft, pE2->pLeft, iTab)==0
94299 && (pE1->op!=TK_ISNULL && pE1->op!=TK_IS)
94300 ){
94301 return 1;
94302 }
94303 return 0;
94304 }
94305
94306 /*
@@ -122354,11 +122429,11 @@
122354 }
122355 #endif
122356
122357 sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size);
122358 sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0));
122359 sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF);
122360
122361 /* Begin a transaction and take an exclusive lock on the main database
122362 ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below,
122363 ** to ensure that we do not try to change the page-size on a WAL database.
122364 */
@@ -127537,10 +127612,11 @@
127537 Expr *pNew;
127538 Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i);
127539 Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i);
127540
127541 pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight, 0);
 
127542 idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC);
127543 exprAnalyze(pSrc, pWC, idxNew);
127544 }
127545 pTerm = &pWC->a[idxTerm];
127546 pTerm->wtFlags = TERM_CODED|TERM_VIRTUAL; /* Disable the original */
@@ -127978,15 +128054,17 @@
127978 Expr *pX; /* An expression being tested */
127979 WhereClause *pWC; /* Shorthand for pScan->pWC */
127980 WhereTerm *pTerm; /* The term being tested */
127981 int k = pScan->k; /* Where to start scanning */
127982
127983 while( pScan->iEquiv<=pScan->nEquiv ){
127984 iCur = pScan->aiCur[pScan->iEquiv-1];
 
127985 iColumn = pScan->aiColumn[pScan->iEquiv-1];
127986 if( iColumn==XN_EXPR && pScan->pIdxExpr==0 ) return 0;
127987 while( (pWC = pScan->pWC)!=0 ){
 
127988 for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
127989 if( pTerm->leftCursor==iCur
127990 && pTerm->u.leftColumn==iColumn
127991 && (iColumn!=XN_EXPR
127992 || sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0)
@@ -128032,19 +128110,21 @@
128032 && pX->iColumn==pScan->aiColumn[0]
128033 ){
128034 testcase( pTerm->eOperator & WO_IS );
128035 continue;
128036 }
 
128037 pScan->k = k+1;
128038 return pTerm;
128039 }
128040 }
128041 }
128042 pScan->pWC = pScan->pWC->pOuter;
128043 k = 0;
128044 }
128045 pScan->pWC = pScan->pOrigWC;
 
128046 k = 0;
128047 pScan->iEquiv++;
128048 }
128049 return 0;
128050 }
@@ -128074,28 +128154,28 @@
128074 int iCur, /* Cursor to scan for */
128075 int iColumn, /* Column to scan for */
128076 u32 opMask, /* Operator(s) to scan for */
128077 Index *pIdx /* Must be compatible with this index */
128078 ){
128079 int j = 0;
128080
128081 /* memset(pScan, 0, sizeof(*pScan)); */
128082 pScan->pOrigWC = pWC;
128083 pScan->pWC = pWC;
128084 pScan->pIdxExpr = 0;
 
 
128085 if( pIdx ){
128086 j = iColumn;
128087 iColumn = pIdx->aiColumn[j];
128088 if( iColumn==XN_EXPR ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
128089 if( iColumn==pIdx->pTable->iPKey ) iColumn = XN_ROWID;
128090 }
128091 if( pIdx && iColumn>=0 ){
128092 pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
128093 pScan->zCollName = pIdx->azColl[j];
128094 }else{
128095 pScan->idxaff = 0;
128096 pScan->zCollName = 0;
 
128097 }
128098 pScan->opMask = opMask;
128099 pScan->k = 0;
128100 pScan->aiCur[0] = iCur;
128101 pScan->aiColumn[0] = iColumn;
@@ -132640,17 +132720,19 @@
132640 pLevel->addrLikeRep);
132641 VdbeCoverage(v);
132642 }
132643 #endif
132644 if( pLevel->iLeftJoin ){
 
132645 addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
132646 assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
132647 || (pLoop->wsFlags & WHERE_INDEXED)!=0 );
132648 if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 ){
132649 sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor);
132650 }
132651 if( pLoop->wsFlags & WHERE_INDEXED ){
 
 
132652 sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
132653 }
132654 if( pLevel->op==OP_Return ){
132655 sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst);
132656 }else{
@@ -138612,10 +138694,11 @@
138612 } aFlagOp[] = {
138613 { SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys },
138614 { SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger },
138615 { SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer },
138616 { SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension },
 
138617 };
138618 unsigned int i;
138619 rc = SQLITE_ERROR; /* IMP: R-42790-23372 */
138620 for(i=0; i<ArraySize(aFlagOp); i++){
138621 if( aFlagOp[i].op==op ){
@@ -139908,10 +139991,17 @@
139908 db->busyHandler.nBusy = 0;
139909 rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt);
139910 sqlite3Error(db, rc);
139911 }
139912 rc = sqlite3ApiExit(db, rc);
 
 
 
 
 
 
 
139913 sqlite3_mutex_leave(db->mutex);
139914 return rc;
139915 #endif
139916 }
139917
@@ -140410,10 +140500,11 @@
140410 int octet = (sqlite3HexToInt(zUri[iIn++]) << 4);
140411 octet += sqlite3HexToInt(zUri[iIn++]);
140412
140413 assert( octet>=0 && octet<256 );
140414 if( octet==0 ){
 
140415 /* This branch is taken when "%00" appears within the URI. In this
140416 ** case we ignore all text in the remainder of the path, name or
140417 ** value currently being parsed. So ignore the current character
140418 ** and skip to the next "?", "=" or "&", as appropriate. */
140419 while( (c = zUri[iIn])!=0 && c!='#'
@@ -140422,10 +140513,16 @@
140422 && (eState!=2 || c!='&')
140423 ){
140424 iIn++;
140425 }
140426 continue;
 
 
 
 
 
 
140427 }
140428 c = octet;
140429 }else if( eState==1 && (c=='&' || c=='=') ){
140430 if( zFile[iOut-1]==0 ){
140431 /* An empty option name. Ignore this option altogether. */
@@ -165207,11 +165304,11 @@
165207 ** of the locale to use. Passing an empty string ("") or SQL NULL value
165208 ** as the second argument is the same as invoking the 1 argument version
165209 ** of upper() or lower().
165210 **
165211 ** lower('I', 'en_us') -> 'i'
165212 ** lower('I', 'tr_tr') -> 'ı' (small dotless i)
165213 **
165214 ** http://www.icu-project.org/userguide/posix.html#case_mappings
165215 */
165216 static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
165217 const UChar *zInput; /* Pointer to input string */
@@ -195596,11 +195693,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
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
1 /******************************************************************************
2 ** This file is an amalgamation of many separate C source files from SQLite
3 ** version 3.16.0. By combining all the individual C code files into this
4 ** single large file, the entire code can be compiled as a single translation
5 ** unit. This allows many compilers to do optimizations that would not be
6 ** possible if the files were compiled separately. Performance improvements
7 ** of 5% or more are commonly seen when SQLite is compiled as a single
8 ** translation unit.
@@ -379,13 +379,13 @@
379 **
380 ** See also: [sqlite3_libversion()],
381 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
382 ** [sqlite_version()] and [sqlite_source_id()].
383 */
384 #define SQLITE_VERSION "3.16.0"
385 #define SQLITE_VERSION_NUMBER 3016000
386 #define SQLITE_SOURCE_ID "2016-11-02 14:50:19 3028845329c9b7acdec2ec8b01d00d782347454c"
387
388 /*
389 ** CAPI3REF: Run-Time Library Version Numbers
390 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
391 **
@@ -1235,10 +1235,16 @@
1235 ** <li>[[SQLITE_FCNTL_HAS_MOVED]]
1236 ** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a
1237 ** pointer to an integer and it writes a boolean into that integer depending
1238 ** on whether or not the file has been renamed, moved, or deleted since it
1239 ** was first opened.
1240 **
1241 ** <li>[[SQLITE_FCNTL_WIN32_GET_HANDLE]]
1242 ** The [SQLITE_FCNTL_WIN32_GET_HANDLE] opcode can be used to obtain the
1243 ** underlying native file handle associated with a file handle. This file
1244 ** control interprets its argument as a pointer to a native file handle and
1245 ** writes the resulting value there.
1246 **
1247 ** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]]
1248 ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This
1249 ** opcode causes the xFileControl method to swap the file handle with the one
1250 ** pointed to by the pArg argument. This capability is used during testing
@@ -1286,10 +1292,12 @@
1292 #define SQLITE_FCNTL_WAL_BLOCK 24
1293 #define SQLITE_FCNTL_ZIPVFS 25
1294 #define SQLITE_FCNTL_RBU 26
1295 #define SQLITE_FCNTL_VFS_POINTER 27
1296 #define SQLITE_FCNTL_JOURNAL_POINTER 28
1297 #define SQLITE_FCNTL_WIN32_GET_HANDLE 29
1298 #define SQLITE_FCNTL_PDB 30
1299
1300 /* deprecated names */
1301 #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
1302 #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
1303 #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
@@ -2238,18 +2246,31 @@
2246 ** does not make a copy of the new main schema name string, so the application
2247 ** must ensure that the argument passed into this DBCONFIG option is unchanged
2248 ** until after the database connection closes.
2249 ** </dd>
2250 **
2251 ** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt>
2252 ** <dd> Usually, when a database in wal mode is closed or detached from a
2253 ** database handle, SQLite checks if this will mean that there are now no
2254 ** connections at all to the database. If so, it performs a checkpoint
2255 ** operation before closing the connection. This option may be used to
2256 ** override this behaviour. The first parameter passed to this operation
2257 ** is an integer - non-zero to disable checkpoints-on-close, or zero (the
2258 ** default) to enable them. The second parameter is a pointer to an integer
2259 ** into which is written 0 or 1 to indicate whether checkpoints-on-close
2260 ** have been disabled - 0 if they are not disabled, 1 if they are.
2261 ** </dd>
2262 **
2263 ** </dl>
2264 */
2265 #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
2266 #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
2267 #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */
2268 #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
2269 #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */
2270 #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */
2271 #define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */
2272
2273
2274 /*
2275 ** CAPI3REF: Enable Or Disable Extended Result Codes
2276 ** METHOD: sqlite3
@@ -12675,11 +12696,11 @@
12696 #define OP_SorterData 120 /* synopsis: r[P2]=data */
12697 #define OP_RowKey 121 /* synopsis: r[P2]=key */
12698 #define OP_RowData 122 /* synopsis: r[P2]=data */
12699 #define OP_Rowid 123 /* synopsis: r[P2]=rowid */
12700 #define OP_NullRow 124
12701 #define OP_SorterInsert 125 /* synopsis: key=r[P2] */
12702 #define OP_IdxInsert 126 /* synopsis: key=r[P2] */
12703 #define OP_IdxDelete 127 /* synopsis: key=r[P2@P3] */
12704 #define OP_Seek 128 /* synopsis: Move P3 to P1.rowid */
12705 #define OP_IdxRowid 129 /* synopsis: r[P2]=rowid */
12706 #define OP_Destroy 130
@@ -13030,11 +13051,11 @@
13051 int,
13052 int,
13053 int,
13054 void(*)(DbPage*)
13055 );
13056 SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*);
13057 SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
13058
13059 /* Functions used to configure a Pager object. */
13060 SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *);
13061 SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int);
@@ -13081,19 +13102,22 @@
13102 SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
13103 SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
13104 SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager);
13105
13106 #ifndef SQLITE_OMIT_WAL
13107 SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, sqlite3*, int, int*, int*);
13108 SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager);
13109 SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager);
13110 SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
13111 SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3*);
13112 SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager);
13113 # ifdef SQLITE_ENABLE_SNAPSHOT
13114 SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot);
13115 SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot);
13116 # endif
13117 #else
13118 # define sqlite3PagerUseWal(x) 0
13119 #endif
13120
13121 #ifdef SQLITE_ENABLE_ZIPVFS
13122 SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager);
13123 #endif
@@ -14060,10 +14084,11 @@
14084 #define SQLITE_QueryOnly 0x04000000 /* Disable database changes */
14085 #define SQLITE_VdbeEQP 0x08000000 /* Debug EXPLAIN QUERY PLAN */
14086 #define SQLITE_Vacuum 0x10000000 /* Currently in a VACUUM */
14087 #define SQLITE_CellSizeCk 0x20000000 /* Check btree cell sizes on load */
14088 #define SQLITE_Fts3Tokenizer 0x40000000 /* Enable fts3_tokenizer(2) */
14089 #define SQLITE_NoCkptOnClose 0x80000000 /* No checkpoint on close()/DETACH */
14090
14091
14092 /*
14093 ** Bits of the sqlite3.dbOptFlags field that are used by the
14094 ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
@@ -17268,10 +17293,13 @@
17293 #if SQLITE_DEFAULT_LOCKING_MODE
17294 "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
17295 #endif
17296 #if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc)
17297 "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
17298 #endif
17299 #if SQLITE_DIRECT_OVERFLOW_READ
17300 "DIRECT_OVERFLOW_READ",
17301 #endif
17302 #if SQLITE_DISABLE_DIRSYNC
17303 "DISABLE_DIRSYNC",
17304 #endif
17305 #if SQLITE_DISABLE_LFS
@@ -17354,10 +17382,13 @@
17382 #if SQLITE_ENABLE_UNLOCK_NOTIFY
17383 "ENABLE_UNLOCK_NOTIFY",
17384 #endif
17385 #if SQLITE_ENABLE_UPDATE_DELETE_LIMIT
17386 "ENABLE_UPDATE_DELETE_LIMIT",
17387 #endif
17388 #if defined(SQLITE_ENABLE_URI_00_ERROR)
17389 "ENABLE_URI_00_ERROR",
17390 #endif
17391 #if SQLITE_HAS_CODEC
17392 "HAS_CODEC",
17393 #endif
17394 #if HAVE_ISNAN || SQLITE_HAVE_ISNAN
@@ -18105,12 +18136,12 @@
18136 UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */
18137 UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */
18138 int iNewReg; /* Register for new.* values */
18139 i64 iKey1; /* First key value passed to hook */
18140 i64 iKey2; /* Second key value passed to hook */
 
18141 Mem *aNew; /* Array of new.* values */
18142 Table *pTab; /* Schema object being upated */
18143 };
18144
18145 /*
18146 ** Function prototypes
18147 */
@@ -24598,13 +24629,12 @@
24629 char *zNew;
24630 size_t n;
24631 if( z==0 ){
24632 return 0;
24633 }
24634 n = strlen(z) + 1;
24635 zNew = sqlite3DbMallocRaw(db, n);
 
24636 if( zNew ){
24637 memcpy(zNew, z, n);
24638 }
24639 return zNew;
24640 }
@@ -29127,11 +29157,11 @@
29157 /* 120 */ "SorterData" OpHelp("r[P2]=data"),
29158 /* 121 */ "RowKey" OpHelp("r[P2]=key"),
29159 /* 122 */ "RowData" OpHelp("r[P2]=data"),
29160 /* 123 */ "Rowid" OpHelp("r[P2]=rowid"),
29161 /* 124 */ "NullRow" OpHelp(""),
29162 /* 125 */ "SorterInsert" OpHelp("key=r[P2]"),
29163 /* 126 */ "IdxInsert" OpHelp("key=r[P2]"),
29164 /* 127 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
29165 /* 128 */ "Seek" OpHelp("Move P3 to P1.rowid"),
29166 /* 129 */ "IdxRowid" OpHelp("r[P2]=rowid"),
29167 /* 130 */ "Destroy" OpHelp(""),
@@ -40674,10 +40704,16 @@
40704 a[1] = winIoerrRetryDelay;
40705 }
40706 OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
40707 return SQLITE_OK;
40708 }
40709 case SQLITE_FCNTL_WIN32_GET_HANDLE: {
40710 LPHANDLE phFile = (LPHANDLE)pArg;
40711 *phFile = pFile->h;
40712 OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
40713 return SQLITE_OK;
40714 }
40715 #ifdef SQLITE_TEST
40716 case SQLITE_FCNTL_WIN32_SET_HANDLE: {
40717 LPHANDLE phFile = (LPHANDLE)pArg;
40718 HANDLE hOldFile = pFile->h;
40719 pFile->h = *phFile;
@@ -46249,21 +46285,21 @@
46285 #define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */
46286
46287 #ifdef SQLITE_OMIT_WAL
46288 # define sqlite3WalOpen(x,y,z) 0
46289 # define sqlite3WalLimit(x,y)
46290 # define sqlite3WalClose(v,w,x,y,z) 0
46291 # define sqlite3WalBeginReadTransaction(y,z) 0
46292 # define sqlite3WalEndReadTransaction(z)
46293 # define sqlite3WalDbsize(y) 0
46294 # define sqlite3WalBeginWriteTransaction(y) 0
46295 # define sqlite3WalEndWriteTransaction(x) 0
46296 # define sqlite3WalUndo(x,y,z) 0
46297 # define sqlite3WalSavepoint(y,z)
46298 # define sqlite3WalSavepointUndo(y,z) 0
46299 # define sqlite3WalFrames(u,v,w,x,y,z) 0
46300 # define sqlite3WalCheckpoint(q,r,s,t,u,v,w,x,y,z) 0
46301 # define sqlite3WalCallback(z) 0
46302 # define sqlite3WalExclusiveMode(y,z) 0
46303 # define sqlite3WalHeapMemory(z) 0
46304 # define sqlite3WalFramesize(z) 0
46305 # define sqlite3WalFindFrame(x,y,z) 0
@@ -46277,11 +46313,11 @@
46313 */
46314 typedef struct Wal Wal;
46315
46316 /* Open and close a connection to a write-ahead log. */
46317 SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**);
46318 SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, sqlite3*, int sync_flags, int, u8 *);
46319
46320 /* Set the limiting size of a WAL file. */
46321 SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64);
46322
46323 /* Used by readers to open (lock) and close (unlock) a snapshot. A
@@ -46320,10 +46356,11 @@
46356 SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int);
46357
46358 /* Copy pages from the log to the database file */
46359 SQLITE_PRIVATE int sqlite3WalCheckpoint(
46360 Wal *pWal, /* Write-ahead log connection */
46361 sqlite3 *db, /* Check this handle's interrupt flag */
46362 int eMode, /* One of PASSIVE, FULL and RESTART */
46363 int (*xBusy)(void*), /* Function to call when busy */
46364 void *pBusyArg, /* Context argument for xBusyHandler */
46365 int sync_flags, /* Flags to sync db file with (or 0) */
46366 int nBuf, /* Size of buffer nBuf */
@@ -47164,13 +47201,14 @@
47201 /*
47202 ** Return true if this pager uses a write-ahead log instead of the usual
47203 ** rollback journal. Otherwise false.
47204 */
47205 #ifndef SQLITE_OMIT_WAL
47206 SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager){
47207 return (pPager->pWal!=0);
47208 }
47209 # define pagerUseWal(x) sqlite3PagerUseWal(x)
47210 #else
47211 # define pagerUseWal(x) 0
47212 # define pagerRollbackWal(x) 0
47213 # define pagerWalFrames(v,w,x,y) 0
47214 # define pagerOpenWalIfPresent(z) SQLITE_OK
@@ -50368,21 +50406,22 @@
50406 ** This function always succeeds. If a transaction is active an attempt
50407 ** is made to roll it back. If an error occurs during the rollback
50408 ** a hot journal may be left in the filesystem but no error is returned
50409 ** to the caller.
50410 */
50411 SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){
50412 u8 *pTmp = (u8 *)pPager->pTmpSpace;
50413
50414 assert( db || pagerUseWal(pPager)==0 );
50415 assert( assert_pager_state(pPager) );
50416 disable_simulated_io_errors();
50417 sqlite3BeginBenignMalloc();
50418 pagerFreeMapHdrs(pPager);
50419 /* pPager->errCode = 0; */
50420 pPager->exclusiveMode = 0;
50421 #ifndef SQLITE_OMIT_WAL
50422 sqlite3WalClose(pPager->pWal,db,pPager->ckptSyncFlags,pPager->pageSize,pTmp);
50423 pPager->pWal = 0;
50424 #endif
50425 pager_reset(pPager);
50426 if( MEMDB ){
50427 pager_unlock(pPager);
@@ -53541,14 +53580,20 @@
53580 ** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint()
53581 ** or wal_blocking_checkpoint() API functions.
53582 **
53583 ** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
53584 */
53585 SQLITE_PRIVATE int sqlite3PagerCheckpoint(
53586 Pager *pPager, /* Checkpoint on this pager */
53587 sqlite3 *db, /* Db handle used to check for interrupts */
53588 int eMode, /* Type of checkpoint */
53589 int *pnLog, /* OUT: Final number of frames in log */
53590 int *pnCkpt /* OUT: Final number of checkpointed frames */
53591 ){
53592 int rc = SQLITE_OK;
53593 if( pPager->pWal ){
53594 rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode,
53595 (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
53596 pPager->pBusyHandlerArg,
53597 pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
53598 pnLog, pnCkpt
53599 );
@@ -53676,11 +53721,11 @@
53721 ** Before closing the log file, this function attempts to take an
53722 ** EXCLUSIVE lock on the database file. If this cannot be obtained, an
53723 ** error (SQLITE_BUSY) is returned and the log connection is not closed.
53724 ** If successful, the EXCLUSIVE lock is not released before returning.
53725 */
53726 SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){
53727 int rc = SQLITE_OK;
53728
53729 assert( pPager->journalMode==PAGER_JOURNALMODE_WAL );
53730
53731 /* If the log file is not already open, but does exist in the file-system,
@@ -53704,11 +53749,11 @@
53749 ** the database file, the log and log-summary files will be deleted.
53750 */
53751 if( rc==SQLITE_OK && pPager->pWal ){
53752 rc = pagerExclusiveLock(pPager);
53753 if( rc==SQLITE_OK ){
53754 rc = sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags,
53755 pPager->pageSize, (u8*)pPager->pTmpSpace);
53756 pPager->pWal = 0;
53757 pagerFixMaplimit(pPager);
53758 if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK);
53759 }
@@ -55487,10 +55532,11 @@
55532 ** checkpoint is running (in any other thread or process) at the same
55533 ** time.
55534 */
55535 static int walCheckpoint(
55536 Wal *pWal, /* Wal connection */
55537 sqlite3 *db, /* Check for interrupts on this handle */
55538 int eMode, /* One of PASSIVE, FULL or RESTART */
55539 int (*xBusy)(void*), /* Function to call when busy */
55540 void *pBusyArg, /* Context argument for xBusyHandler */
55541 int sync_flags, /* Flags for OsSync() (or 0) */
55542 u8 *zBuf /* Temporary buffer to use */
@@ -55581,10 +55627,14 @@
55627
55628 /* Iterate through the contents of the WAL, copying data to the db file */
55629 while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
55630 i64 iOffset;
55631 assert( walFramePgno(pWal, iFrame)==iDbpage );
55632 if( db->u1.isInterrupted ){
55633 rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
55634 break;
55635 }
55636 if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){
55637 continue;
55638 }
55639 iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE;
55640 /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */
@@ -55685,10 +55735,11 @@
55735 /*
55736 ** Close a connection to a log file.
55737 */
55738 SQLITE_PRIVATE int sqlite3WalClose(
55739 Wal *pWal, /* Wal to close */
55740 sqlite3 *db, /* For interrupt flag */
55741 int sync_flags, /* Flags to pass to OsSync() (or 0) */
55742 int nBuf,
55743 u8 *zBuf /* Buffer of at least nBuf bytes */
55744 ){
55745 int rc = SQLITE_OK;
@@ -55701,17 +55752,18 @@
55752 ** the database. In this case checkpoint the database and unlink both
55753 ** the wal and wal-index files.
55754 **
55755 ** The EXCLUSIVE lock is not released before returning.
55756 */
55757 if( (db->flags & SQLITE_NoCkptOnClose)==0
55758 && SQLITE_OK==(rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE))
55759 ){
55760 if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
55761 pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
55762 }
55763 rc = sqlite3WalCheckpoint(pWal, db,
55764 SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0
55765 );
55766 if( rc==SQLITE_OK ){
55767 int bPersist = -1;
55768 sqlite3OsFileControlHint(
55769 pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersist
@@ -56955,10 +57007,11 @@
57007 ** If parameter xBusy is not NULL, it is a pointer to a busy-handler
57008 ** callback. In this case this function runs a blocking checkpoint.
57009 */
57010 SQLITE_PRIVATE int sqlite3WalCheckpoint(
57011 Wal *pWal, /* Wal connection */
57012 sqlite3 *db, /* Check this handle's interrupt flag */
57013 int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */
57014 int (*xBusy)(void*), /* Function to call when busy */
57015 void *pBusyArg, /* Context argument for xBusyHandler */
57016 int sync_flags, /* Flags to sync db file with (or 0) */
57017 int nBuf, /* Size of temporary buffer */
@@ -57029,11 +57082,11 @@
57082 if( rc==SQLITE_OK ){
57083
57084 if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
57085 rc = SQLITE_CORRUPT_BKPT;
57086 }else{
57087 rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf);
57088 }
57089
57090 /* If no error occurred, set the output variables. */
57091 if( rc==SQLITE_OK || rc==SQLITE_BUSY ){
57092 if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame;
@@ -60619,23 +60672,30 @@
60672 *ppBtree = p;
60673
60674 btree_open_out:
60675 if( rc!=SQLITE_OK ){
60676 if( pBt && pBt->pPager ){
60677 sqlite3PagerClose(pBt->pPager, 0);
60678 }
60679 sqlite3_free(pBt);
60680 sqlite3_free(p);
60681 *ppBtree = 0;
60682 }else{
60683 sqlite3_file *pFile;
60684
60685 /* If the B-Tree was successfully opened, set the pager-cache size to the
60686 ** default value. Except, when opening on an existing shared pager-cache,
60687 ** do not change the pager-cache size.
60688 */
60689 if( sqlite3BtreeSchema(p, 0, 0)==0 ){
60690 sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE);
60691 }
60692
60693 pFile = sqlite3PagerFile(pBt->pPager);
60694 if( pFile->pMethods ){
60695 sqlite3OsFileControlHint(pFile, SQLITE_FCNTL_PDB, (void*)&pBt->db);
60696 }
60697 }
60698 if( mutexOpen ){
60699 assert( sqlite3_mutex_held(mutexOpen) );
60700 sqlite3_mutex_leave(mutexOpen);
60701 }
@@ -60761,11 +60821,11 @@
60821 ** it without having to hold the mutex.
60822 **
60823 ** Clean out and delete the BtShared object.
60824 */
60825 assert( !pBt->pCursor );
60826 sqlite3PagerClose(pBt->pPager, p->db);
60827 if( pBt->xFreeSchema && pBt->pSchema ){
60828 pBt->xFreeSchema(pBt->pSchema);
60829 }
60830 sqlite3DbFree(0, pBt->pSchema);
60831 freeTempSpace(pBt);
@@ -62825,11 +62885,11 @@
62885 if( (eOp&0x01)==0 /* (1) */
62886 && offset==0 /* (2) */
62887 && (bEnd || a==ovflSize) /* (6) */
62888 && pBt->inTransaction==TRANS_READ /* (4) */
62889 && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */
62890 && 0==sqlite3PagerUseWal(pBt->pPager) /* (5) */
62891 && &pBuf[-4]>=pBufStart /* (7) */
62892 ){
62893 u8 aSave[4];
62894 u8 *aWrite = &pBuf[-4];
62895 assert( aWrite>=pBufStart ); /* hence (7) */
@@ -63081,13 +63141,16 @@
63141 }
63142 sqlite3BtreeClearCursor(pCur);
63143 }
63144
63145 if( pCur->iPage>=0 ){
63146 if( pCur->iPage ){
63147 do{
63148 assert( pCur->apPage[pCur->iPage]!=0 );
63149 releasePageNotNull(pCur->apPage[pCur->iPage--]);
63150 }while( pCur->iPage);
63151 goto skip_init;
63152 }
63153 }else if( pCur->pgnoRoot==0 ){
63154 pCur->eState = CURSOR_INVALID;
63155 return SQLITE_OK;
63156 }else{
@@ -63094,11 +63157,11 @@
63157 assert( pCur->iPage==(-1) );
63158 rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0],
63159 0, pCur->curPagerFlags);
63160 if( rc!=SQLITE_OK ){
63161 pCur->eState = CURSOR_INVALID;
63162 return rc;
63163 }
63164 pCur->iPage = 0;
63165 pCur->curIntKey = pCur->apPage[0]->intKey;
63166 }
63167 pRoot = pCur->apPage[0];
@@ -63117,14 +63180,16 @@
63180 assert( pRoot->intKey==1 || pRoot->intKey==0 );
63181 if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){
63182 return SQLITE_CORRUPT_BKPT;
63183 }
63184
63185 skip_init:
63186 pCur->aiIdx[0] = 0;
63187 pCur->info.nSize = 0;
63188 pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl);
63189
63190 pRoot = pCur->apPage[0];
63191 if( pRoot->nCell>0 ){
63192 pCur->eState = CURSOR_VALID;
63193 }else if( !pRoot->leaf ){
63194 Pgno subpage;
63195 if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT;
@@ -67701,11 +67766,11 @@
67766 BtShared *pBt = p->pBt;
67767 sqlite3BtreeEnter(p);
67768 if( pBt->inTransaction!=TRANS_NONE ){
67769 rc = SQLITE_LOCKED;
67770 }else{
67771 rc = sqlite3PagerCheckpoint(pBt->pPager, p->db, eMode, pnLog, pnCkpt);
67772 }
67773 sqlite3BtreeLeave(p);
67774 }
67775 return rc;
67776 }
@@ -75076,11 +75141,11 @@
75141 preupdate.keyinfo.enc = ENC(db);
75142 preupdate.keyinfo.nField = pTab->nCol;
75143 preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder;
75144 preupdate.iKey1 = iKey1;
75145 preupdate.iKey2 = iKey2;
75146 preupdate.pTab = pTab;
75147
75148 db->pPreUpdate = &preupdate;
75149 db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2);
75150 db->pPreUpdate = 0;
75151 sqlite3DbFree(db, preupdate.aRecord);
@@ -76808,13 +76873,18 @@
76873 }
76874
76875 if( iIdx>=p->pUnpacked->nField ){
76876 *ppValue = (sqlite3_value *)columnNullValue();
76877 }else{
76878 Mem *pMem = *ppValue = &p->pUnpacked->aMem[iIdx];
76879 *ppValue = &p->pUnpacked->aMem[iIdx];
76880 if( iIdx==p->pTab->iPKey ){
76881 sqlite3VdbeMemSetInt64(pMem, p->iKey1);
76882 }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
76883 if( pMem->flags & MEM_Int ){
76884 sqlite3VdbeMemRealify(pMem);
76885 }
76886 }
76887 }
76888
76889 preupdate_old_out:
76890 sqlite3Error(db, rc);
@@ -76887,11 +76957,11 @@
76957 }
76958 if( iIdx>=pUnpack->nField ){
76959 pMem = (sqlite3_value *)columnNullValue();
76960 }else{
76961 pMem = &pUnpack->aMem[iIdx];
76962 if( iIdx==p->pTab->iPKey ){
76963 sqlite3VdbeMemSetInt64(pMem, p->iKey2);
76964 }
76965 }
76966 }else{
76967 /* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required
@@ -76908,11 +76978,11 @@
76978 }
76979 }
76980 assert( iIdx>=0 && iIdx<p->pCsr->nField );
76981 pMem = &p->aNew[iIdx];
76982 if( pMem->flags==0 ){
76983 if( iIdx==p->pTab->iPKey ){
76984 sqlite3VdbeMemSetInt64(pMem, p->iKey2);
76985 }else{
76986 rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]);
76987 if( rc!=SQLITE_OK ) goto preupdate_new_out;
76988 }
@@ -79286,12 +79356,11 @@
79356 ** or not both operands are null.
79357 */
79358 assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
79359 assert( (flags1 & MEM_Cleared)==0 );
79360 assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 );
79361 if( (flags1&flags3&MEM_Null)!=0
 
79362 && (flags3&MEM_Cleared)==0
79363 ){
79364 res = 0; /* Operands are equal */
79365 }else{
79366 res = 1; /* Operands are not equal */
@@ -81554,11 +81623,11 @@
81623
81624 REGISTER_TRACE(pOp->p3, pMem);
81625 sqlite3VdbeMemIntegerify(pMem);
81626 assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */
81627 if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){
81628 rc = SQLITE_FULL; /* IMP: R-17817-00630 */
81629 goto abort_due_to_error;
81630 }
81631 if( v<pMem->u.i+1 ){
81632 v = pMem->u.i + 1;
81633 }
@@ -82321,10 +82390,17 @@
82390 ** This flag avoids doing an extra seek.
82391 **
82392 ** This instruction only works for indices. The equivalent instruction
82393 ** for tables is OP_Insert.
82394 */
82395 /* Opcode: SorterInsert P1 P2 * * *
82396 ** Synopsis: key=r[P2]
82397 **
82398 ** Register P2 holds an SQL index key made using the
82399 ** MakeRecord instructions. This opcode writes that key
82400 ** into the sorter P1. Data for the entry is nil.
82401 */
82402 case OP_SorterInsert: /* in2 */
82403 case OP_IdxInsert: { /* in2 */
82404 VdbeCursor *pC;
82405 BtreePayload x;
82406
@@ -83549,11 +83625,11 @@
83625 /* If leaving WAL mode, close the log file. If successful, the call
83626 ** to PagerCloseWal() checkpoints and deletes the write-ahead-log
83627 ** file. An EXCLUSIVE lock may still be held on the database file
83628 ** after a successful return.
83629 */
83630 rc = sqlite3PagerCloseWal(pPager, db);
83631 if( rc==SQLITE_OK ){
83632 sqlite3PagerSetJournalMode(pPager, eNew);
83633 }
83634 }else if( eOld==PAGER_JOURNALMODE_MEMORY ){
83635 /* Cannot transition directly from MEMORY to WAL. Use mode OFF
@@ -94292,15 +94368,14 @@
94368 && (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab)
94369 || sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) )
94370 ){
94371 return 1;
94372 }
94373 if( pE2->op==TK_NOTNULL && pE1->op!=TK_ISNULL && pE1->op!=TK_IS ){
94374 Expr *pX = sqlite3ExprSkipCollate(pE1->pLeft);
94375 testcase( pX!=pE1->pLeft );
94376 if( sqlite3ExprCompare(pX, pE2->pLeft, iTab)==0 ) return 1;
 
94377 }
94378 return 0;
94379 }
94380
94381 /*
@@ -122354,11 +122429,11 @@
122429 }
122430 #endif
122431
122432 sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size);
122433 sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0));
122434 sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF|PAGER_CACHESPILL);
122435
122436 /* Begin a transaction and take an exclusive lock on the main database
122437 ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below,
122438 ** to ensure that we do not try to change the page-size on a WAL database.
122439 */
@@ -127537,10 +127612,11 @@
127612 Expr *pNew;
127613 Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i);
127614 Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i);
127615
127616 pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight, 0);
127617 transferJoinMarkings(pNew, pExpr);
127618 idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC);
127619 exprAnalyze(pSrc, pWC, idxNew);
127620 }
127621 pTerm = &pWC->a[idxTerm];
127622 pTerm->wtFlags = TERM_CODED|TERM_VIRTUAL; /* Disable the original */
@@ -127978,15 +128054,17 @@
128054 Expr *pX; /* An expression being tested */
128055 WhereClause *pWC; /* Shorthand for pScan->pWC */
128056 WhereTerm *pTerm; /* The term being tested */
128057 int k = pScan->k; /* Where to start scanning */
128058
128059 assert( pScan->iEquiv<=pScan->nEquiv );
128060 pWC = pScan->pWC;
128061 while(1){
128062 iColumn = pScan->aiColumn[pScan->iEquiv-1];
128063 iCur = pScan->aiCur[pScan->iEquiv-1];
128064 assert( pWC!=0 );
128065 do{
128066 for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
128067 if( pTerm->leftCursor==iCur
128068 && pTerm->u.leftColumn==iColumn
128069 && (iColumn!=XN_EXPR
128070 || sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0)
@@ -128032,19 +128110,21 @@
128110 && pX->iColumn==pScan->aiColumn[0]
128111 ){
128112 testcase( pTerm->eOperator & WO_IS );
128113 continue;
128114 }
128115 pScan->pWC = pWC;
128116 pScan->k = k+1;
128117 return pTerm;
128118 }
128119 }
128120 }
128121 pWC = pWC->pOuter;
128122 k = 0;
128123 }while( pWC!=0 );
128124 if( pScan->iEquiv>=pScan->nEquiv ) break;
128125 pWC = pScan->pOrigWC;
128126 k = 0;
128127 pScan->iEquiv++;
128128 }
128129 return 0;
128130 }
@@ -128074,28 +128154,28 @@
128154 int iCur, /* Cursor to scan for */
128155 int iColumn, /* Column to scan for */
128156 u32 opMask, /* Operator(s) to scan for */
128157 Index *pIdx /* Must be compatible with this index */
128158 ){
 
 
 
128159 pScan->pOrigWC = pWC;
128160 pScan->pWC = pWC;
128161 pScan->pIdxExpr = 0;
128162 pScan->idxaff = 0;
128163 pScan->zCollName = 0;
128164 if( pIdx ){
128165 int j = iColumn;
128166 iColumn = pIdx->aiColumn[j];
128167 if( iColumn==XN_EXPR ){
128168 pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
128169 }else if( iColumn==pIdx->pTable->iPKey ){
128170 iColumn = XN_ROWID;
128171 }else if( iColumn>=0 ){
128172 pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
128173 pScan->zCollName = pIdx->azColl[j];
128174 }
128175 }else if( iColumn==XN_EXPR ){
128176 return 0;
128177 }
128178 pScan->opMask = opMask;
128179 pScan->k = 0;
128180 pScan->aiCur[0] = iCur;
128181 pScan->aiColumn[0] = iColumn;
@@ -132640,17 +132720,19 @@
132720 pLevel->addrLikeRep);
132721 VdbeCoverage(v);
132722 }
132723 #endif
132724 if( pLevel->iLeftJoin ){
132725 int ws = pLoop->wsFlags;
132726 addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
132727 assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 );
132728 if( (ws & WHERE_IDX_ONLY)==0 ){
 
132729 sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor);
132730 }
132731 if( (ws & WHERE_INDEXED)
132732 || ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx)
132733 ){
132734 sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
132735 }
132736 if( pLevel->op==OP_Return ){
132737 sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst);
132738 }else{
@@ -138612,10 +138694,11 @@
138694 } aFlagOp[] = {
138695 { SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys },
138696 { SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger },
138697 { SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer },
138698 { SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension },
138699 { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose },
138700 };
138701 unsigned int i;
138702 rc = SQLITE_ERROR; /* IMP: R-42790-23372 */
138703 for(i=0; i<ArraySize(aFlagOp); i++){
138704 if( aFlagOp[i].op==op ){
@@ -139908,10 +139991,17 @@
139991 db->busyHandler.nBusy = 0;
139992 rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt);
139993 sqlite3Error(db, rc);
139994 }
139995 rc = sqlite3ApiExit(db, rc);
139996
139997 /* If there are no active statements, clear the interrupt flag at this
139998 ** point. */
139999 if( db->nVdbeActive==0 ){
140000 db->u1.isInterrupted = 0;
140001 }
140002
140003 sqlite3_mutex_leave(db->mutex);
140004 return rc;
140005 #endif
140006 }
140007
@@ -140410,10 +140500,11 @@
140500 int octet = (sqlite3HexToInt(zUri[iIn++]) << 4);
140501 octet += sqlite3HexToInt(zUri[iIn++]);
140502
140503 assert( octet>=0 && octet<256 );
140504 if( octet==0 ){
140505 #ifndef SQLITE_ENABLE_URI_00_ERROR
140506 /* This branch is taken when "%00" appears within the URI. In this
140507 ** case we ignore all text in the remainder of the path, name or
140508 ** value currently being parsed. So ignore the current character
140509 ** and skip to the next "?", "=" or "&", as appropriate. */
140510 while( (c = zUri[iIn])!=0 && c!='#'
@@ -140422,10 +140513,16 @@
140513 && (eState!=2 || c!='&')
140514 ){
140515 iIn++;
140516 }
140517 continue;
140518 #else
140519 /* If ENABLE_URI_00_ERROR is defined, "%00" in a URI is an error. */
140520 *pzErrMsg = sqlite3_mprintf("unexpected %%00 in uri");
140521 rc = SQLITE_ERROR;
140522 goto parse_uri_out;
140523 #endif
140524 }
140525 c = octet;
140526 }else if( eState==1 && (c=='&' || c=='=') ){
140527 if( zFile[iOut-1]==0 ){
140528 /* An empty option name. Ignore this option altogether. */
@@ -165207,11 +165304,11 @@
165304 ** of the locale to use. Passing an empty string ("") or SQL NULL value
165305 ** as the second argument is the same as invoking the 1 argument version
165306 ** of upper() or lower().
165307 **
165308 ** lower('I', 'en_us') -> 'i'
165309 ** lower('I', 'tr_tr') -> '\u131' (small dotless i)
165310 **
165311 ** http://www.icu-project.org/userguide/posix.html#case_mappings
165312 */
165313 static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
165314 const UChar *zInput; /* Pointer to input string */
@@ -195596,11 +195693,11 @@
195693 int nArg, /* Number of args */
195694 sqlite3_value **apUnused /* Function arguments */
195695 ){
195696 assert( nArg==0 );
195697 UNUSED_PARAM2(nArg, apUnused);
195698 sqlite3_result_text(pCtx, "fts5: 2016-10-26 16:05:10 ec9dab8054c71d112c68f58a45821b38c2a45677", -1, SQLITE_TRANSIENT);
195699 }
195700
195701 static int fts5Init(sqlite3 *db){
195702 static const sqlite3_module fts5Mod = {
195703 /* iVersion */ 2,
195704
+24 -3
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -119,13 +119,13 @@
119119
**
120120
** See also: [sqlite3_libversion()],
121121
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
122122
** [sqlite_version()] and [sqlite_source_id()].
123123
*/
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"
124
+#define SQLITE_VERSION "3.16.0"
125
+#define SQLITE_VERSION_NUMBER 3016000
126
+#define SQLITE_SOURCE_ID "2016-11-02 14:50:19 3028845329c9b7acdec2ec8b01d00d782347454c"
127127
128128
/*
129129
** CAPI3REF: Run-Time Library Version Numbers
130130
** KEYWORDS: sqlite3_version, sqlite3_sourceid
131131
**
@@ -975,10 +975,16 @@
975975
** <li>[[SQLITE_FCNTL_HAS_MOVED]]
976976
** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a
977977
** pointer to an integer and it writes a boolean into that integer depending
978978
** on whether or not the file has been renamed, moved, or deleted since it
979979
** was first opened.
980
+**
981
+** <li>[[SQLITE_FCNTL_WIN32_GET_HANDLE]]
982
+** The [SQLITE_FCNTL_WIN32_GET_HANDLE] opcode can be used to obtain the
983
+** underlying native file handle associated with a file handle. This file
984
+** control interprets its argument as a pointer to a native file handle and
985
+** writes the resulting value there.
980986
**
981987
** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]]
982988
** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This
983989
** opcode causes the xFileControl method to swap the file handle with the one
984990
** pointed to by the pArg argument. This capability is used during testing
@@ -1026,10 +1032,12 @@
10261032
#define SQLITE_FCNTL_WAL_BLOCK 24
10271033
#define SQLITE_FCNTL_ZIPVFS 25
10281034
#define SQLITE_FCNTL_RBU 26
10291035
#define SQLITE_FCNTL_VFS_POINTER 27
10301036
#define SQLITE_FCNTL_JOURNAL_POINTER 28
1037
+#define SQLITE_FCNTL_WIN32_GET_HANDLE 29
1038
+#define SQLITE_FCNTL_PDB 30
10311039
10321040
/* deprecated names */
10331041
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
10341042
#define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
10351043
#define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
@@ -1978,18 +1986,31 @@
19781986
** does not make a copy of the new main schema name string, so the application
19791987
** must ensure that the argument passed into this DBCONFIG option is unchanged
19801988
** until after the database connection closes.
19811989
** </dd>
19821990
**
1991
+** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt>
1992
+** <dd> Usually, when a database in wal mode is closed or detached from a
1993
+** database handle, SQLite checks if this will mean that there are now no
1994
+** connections at all to the database. If so, it performs a checkpoint
1995
+** operation before closing the connection. This option may be used to
1996
+** override this behaviour. The first parameter passed to this operation
1997
+** is an integer - non-zero to disable checkpoints-on-close, or zero (the
1998
+** default) to enable them. The second parameter is a pointer to an integer
1999
+** into which is written 0 or 1 to indicate whether checkpoints-on-close
2000
+** have been disabled - 0 if they are not disabled, 1 if they are.
2001
+** </dd>
2002
+**
19832003
** </dl>
19842004
*/
19852005
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
19862006
#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
19872007
#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */
19882008
#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
19892009
#define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */
19902010
#define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */
2011
+#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */
19912012
19922013
19932014
/*
19942015
** CAPI3REF: Enable Or Disable Extended Result Codes
19952016
** METHOD: sqlite3
19962017
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -119,13 +119,13 @@
119 **
120 ** See also: [sqlite3_libversion()],
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 **
@@ -975,10 +975,16 @@
975 ** <li>[[SQLITE_FCNTL_HAS_MOVED]]
976 ** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a
977 ** pointer to an integer and it writes a boolean into that integer depending
978 ** on whether or not the file has been renamed, moved, or deleted since it
979 ** was first opened.
 
 
 
 
 
 
980 **
981 ** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]]
982 ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This
983 ** opcode causes the xFileControl method to swap the file handle with the one
984 ** pointed to by the pArg argument. This capability is used during testing
@@ -1026,10 +1032,12 @@
1026 #define SQLITE_FCNTL_WAL_BLOCK 24
1027 #define SQLITE_FCNTL_ZIPVFS 25
1028 #define SQLITE_FCNTL_RBU 26
1029 #define SQLITE_FCNTL_VFS_POINTER 27
1030 #define SQLITE_FCNTL_JOURNAL_POINTER 28
 
 
1031
1032 /* deprecated names */
1033 #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
1034 #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
1035 #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
@@ -1978,18 +1986,31 @@
1978 ** does not make a copy of the new main schema name string, so the application
1979 ** must ensure that the argument passed into this DBCONFIG option is unchanged
1980 ** until after the database connection closes.
1981 ** </dd>
1982 **
 
 
 
 
 
 
 
 
 
 
 
 
1983 ** </dl>
1984 */
1985 #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
1986 #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
1987 #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */
1988 #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
1989 #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */
1990 #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */
 
1991
1992
1993 /*
1994 ** CAPI3REF: Enable Or Disable Extended Result Codes
1995 ** METHOD: sqlite3
1996
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -119,13 +119,13 @@
119 **
120 ** See also: [sqlite3_libversion()],
121 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
122 ** [sqlite_version()] and [sqlite_source_id()].
123 */
124 #define SQLITE_VERSION "3.16.0"
125 #define SQLITE_VERSION_NUMBER 3016000
126 #define SQLITE_SOURCE_ID "2016-11-02 14:50:19 3028845329c9b7acdec2ec8b01d00d782347454c"
127
128 /*
129 ** CAPI3REF: Run-Time Library Version Numbers
130 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
131 **
@@ -975,10 +975,16 @@
975 ** <li>[[SQLITE_FCNTL_HAS_MOVED]]
976 ** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a
977 ** pointer to an integer and it writes a boolean into that integer depending
978 ** on whether or not the file has been renamed, moved, or deleted since it
979 ** was first opened.
980 **
981 ** <li>[[SQLITE_FCNTL_WIN32_GET_HANDLE]]
982 ** The [SQLITE_FCNTL_WIN32_GET_HANDLE] opcode can be used to obtain the
983 ** underlying native file handle associated with a file handle. This file
984 ** control interprets its argument as a pointer to a native file handle and
985 ** writes the resulting value there.
986 **
987 ** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]]
988 ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This
989 ** opcode causes the xFileControl method to swap the file handle with the one
990 ** pointed to by the pArg argument. This capability is used during testing
@@ -1026,10 +1032,12 @@
1032 #define SQLITE_FCNTL_WAL_BLOCK 24
1033 #define SQLITE_FCNTL_ZIPVFS 25
1034 #define SQLITE_FCNTL_RBU 26
1035 #define SQLITE_FCNTL_VFS_POINTER 27
1036 #define SQLITE_FCNTL_JOURNAL_POINTER 28
1037 #define SQLITE_FCNTL_WIN32_GET_HANDLE 29
1038 #define SQLITE_FCNTL_PDB 30
1039
1040 /* deprecated names */
1041 #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
1042 #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
1043 #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
@@ -1978,18 +1986,31 @@
1986 ** does not make a copy of the new main schema name string, so the application
1987 ** must ensure that the argument passed into this DBCONFIG option is unchanged
1988 ** until after the database connection closes.
1989 ** </dd>
1990 **
1991 ** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt>
1992 ** <dd> Usually, when a database in wal mode is closed or detached from a
1993 ** database handle, SQLite checks if this will mean that there are now no
1994 ** connections at all to the database. If so, it performs a checkpoint
1995 ** operation before closing the connection. This option may be used to
1996 ** override this behaviour. The first parameter passed to this operation
1997 ** is an integer - non-zero to disable checkpoints-on-close, or zero (the
1998 ** default) to enable them. The second parameter is a pointer to an integer
1999 ** into which is written 0 or 1 to indicate whether checkpoints-on-close
2000 ** have been disabled - 0 if they are not disabled, 1 if they are.
2001 ** </dd>
2002 **
2003 ** </dl>
2004 */
2005 #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
2006 #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
2007 #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */
2008 #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
2009 #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */
2010 #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */
2011 #define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */
2012
2013
2014 /*
2015 ** CAPI3REF: Enable Or Disable Extended Result Codes
2016 ** METHOD: sqlite3
2017
--- src/style.c
+++ src/style.c
@@ -400,10 +400,11 @@
400400
401401
if( g.thTrace ) Th_Trace("BEGIN_HEADER<br />\n", -1);
402402
403403
/* Generate the header up through the main menu */
404404
Th_Store("project_name", db_get("project-name","Unnamed Fossil Project"));
405
+ Th_Store("project_description", db_get("project-description",""));
405406
Th_Store("title", zTitle);
406407
Th_Store("baseurl", g.zBaseURL);
407408
Th_Store("secureurl", login_wants_https_redirect()? g.zHttpsURL: g.zBaseURL);
408409
Th_Store("home", g.zTop);
409410
Th_Store("index_page", db_get("index-page","/home"));
410411
--- src/style.c
+++ src/style.c
@@ -400,10 +400,11 @@
400
401 if( g.thTrace ) Th_Trace("BEGIN_HEADER<br />\n", -1);
402
403 /* Generate the header up through the main menu */
404 Th_Store("project_name", db_get("project-name","Unnamed Fossil Project"));
 
405 Th_Store("title", zTitle);
406 Th_Store("baseurl", g.zBaseURL);
407 Th_Store("secureurl", login_wants_https_redirect()? g.zHttpsURL: g.zBaseURL);
408 Th_Store("home", g.zTop);
409 Th_Store("index_page", db_get("index-page","/home"));
410
--- src/style.c
+++ src/style.c
@@ -400,10 +400,11 @@
400
401 if( g.thTrace ) Th_Trace("BEGIN_HEADER<br />\n", -1);
402
403 /* Generate the header up through the main menu */
404 Th_Store("project_name", db_get("project-name","Unnamed Fossil Project"));
405 Th_Store("project_description", db_get("project-description",""));
406 Th_Store("title", zTitle);
407 Th_Store("baseurl", g.zBaseURL);
408 Th_Store("secureurl", login_wants_https_redirect()? g.zHttpsURL: g.zBaseURL);
409 Th_Store("home", g.zTop);
410 Th_Store("index_page", db_get("index-page","/home"));
411
--- src/th_main.c
+++ src/th_main.c
@@ -1317,10 +1317,92 @@
13171317
}else{
13181318
Th_SetResult(interp, "repository unavailable", -1);
13191319
return TH_ERROR;
13201320
}
13211321
}
1322
+
1323
+/*
1324
+** TH1 command: unversioned content FILENAME
1325
+**
1326
+** Attempts to locate the specified unversioned file and return its contents.
1327
+** An error is generated if the repository is not open or the unversioned file
1328
+** cannot be found.
1329
+*/
1330
+static int unversionedContentCmd(
1331
+ Th_Interp *interp,
1332
+ void *p,
1333
+ int argc,
1334
+ const char **argv,
1335
+ int *argl
1336
+){
1337
+ if( argc!=3 ){
1338
+ return Th_WrongNumArgs(interp, "unversioned content FILENAME");
1339
+ }
1340
+ if( Th_IsRepositoryOpen() ){
1341
+ Blob content;
1342
+ if( unversioned_content(argv[2], &content)==0 ){
1343
+ Th_SetResult(interp, blob_str(&content), blob_size(&content));
1344
+ blob_reset(&content);
1345
+ return TH_OK;
1346
+ }else{
1347
+ return TH_ERROR;
1348
+ }
1349
+ }else{
1350
+ Th_SetResult(interp, "repository unavailable", -1);
1351
+ return TH_ERROR;
1352
+ }
1353
+}
1354
+
1355
+/*
1356
+** TH1 command: unversioned list
1357
+**
1358
+** Returns a list of the names of all unversioned files held in the local
1359
+** repository. An error is generated if the repository is not open.
1360
+*/
1361
+static int unversionedListCmd(
1362
+ Th_Interp *interp,
1363
+ void *p,
1364
+ int argc,
1365
+ const char **argv,
1366
+ int *argl
1367
+){
1368
+ if( argc!=2 ){
1369
+ return Th_WrongNumArgs(interp, "unversioned list");
1370
+ }
1371
+ if( Th_IsRepositoryOpen() ){
1372
+ Stmt q;
1373
+ char *zList = 0;
1374
+ int nList = 0;
1375
+ db_prepare(&q, "SELECT name FROM unversioned WHERE hash IS NOT NULL"
1376
+ " ORDER BY name");
1377
+ while( db_step(&q)==SQLITE_ROW ){
1378
+ Th_ListAppend(interp, &zList, &nList, db_column_text(&q,0), -1);
1379
+ }
1380
+ db_finalize(&q);
1381
+ Th_SetResult(interp, zList, nList);
1382
+ Th_Free(interp, zList);
1383
+ return TH_OK;
1384
+ }else{
1385
+ Th_SetResult(interp, "repository unavailable", -1);
1386
+ return TH_ERROR;
1387
+ }
1388
+}
1389
+
1390
+static int unversionedCmd(
1391
+ Th_Interp *interp,
1392
+ void *p,
1393
+ int argc,
1394
+ const char **argv,
1395
+ int *argl
1396
+){
1397
+ static const Th_SubCommand aSub[] = {
1398
+ { "content", unversionedContentCmd },
1399
+ { "list", unversionedListCmd },
1400
+ { 0, 0 }
1401
+ };
1402
+ return Th_CallSubCommand(interp, p, argc, argv, argl, aSub);
1403
+}
13221404
13231405
#ifdef _WIN32
13241406
# include <windows.h>
13251407
#else
13261408
# include <sys/time.h>
@@ -1886,10 +1968,11 @@
18861968
{"styleHeader", styleHeaderCmd, 0},
18871969
{"styleFooter", styleFooterCmd, 0},
18881970
{"tclReady", tclReadyCmd, 0},
18891971
{"trace", traceCmd, 0},
18901972
{"stime", stimeCmd, 0},
1973
+ {"unversioned", unversionedCmd, 0},
18911974
{"utime", utimeCmd, 0},
18921975
{"verifyCsrf", verifyCsrfCmd, 0},
18931976
{"wiki", wikiCmd, (void*)&aFlags[0]},
18941977
{0, 0, 0}
18951978
};
18961979
--- src/th_main.c
+++ src/th_main.c
@@ -1317,10 +1317,92 @@
1317 }else{
1318 Th_SetResult(interp, "repository unavailable", -1);
1319 return TH_ERROR;
1320 }
1321 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1322
1323 #ifdef _WIN32
1324 # include <windows.h>
1325 #else
1326 # include <sys/time.h>
@@ -1886,10 +1968,11 @@
1886 {"styleHeader", styleHeaderCmd, 0},
1887 {"styleFooter", styleFooterCmd, 0},
1888 {"tclReady", tclReadyCmd, 0},
1889 {"trace", traceCmd, 0},
1890 {"stime", stimeCmd, 0},
 
1891 {"utime", utimeCmd, 0},
1892 {"verifyCsrf", verifyCsrfCmd, 0},
1893 {"wiki", wikiCmd, (void*)&aFlags[0]},
1894 {0, 0, 0}
1895 };
1896
--- src/th_main.c
+++ src/th_main.c
@@ -1317,10 +1317,92 @@
1317 }else{
1318 Th_SetResult(interp, "repository unavailable", -1);
1319 return TH_ERROR;
1320 }
1321 }
1322
1323 /*
1324 ** TH1 command: unversioned content FILENAME
1325 **
1326 ** Attempts to locate the specified unversioned file and return its contents.
1327 ** An error is generated if the repository is not open or the unversioned file
1328 ** cannot be found.
1329 */
1330 static int unversionedContentCmd(
1331 Th_Interp *interp,
1332 void *p,
1333 int argc,
1334 const char **argv,
1335 int *argl
1336 ){
1337 if( argc!=3 ){
1338 return Th_WrongNumArgs(interp, "unversioned content FILENAME");
1339 }
1340 if( Th_IsRepositoryOpen() ){
1341 Blob content;
1342 if( unversioned_content(argv[2], &content)==0 ){
1343 Th_SetResult(interp, blob_str(&content), blob_size(&content));
1344 blob_reset(&content);
1345 return TH_OK;
1346 }else{
1347 return TH_ERROR;
1348 }
1349 }else{
1350 Th_SetResult(interp, "repository unavailable", -1);
1351 return TH_ERROR;
1352 }
1353 }
1354
1355 /*
1356 ** TH1 command: unversioned list
1357 **
1358 ** Returns a list of the names of all unversioned files held in the local
1359 ** repository. An error is generated if the repository is not open.
1360 */
1361 static int unversionedListCmd(
1362 Th_Interp *interp,
1363 void *p,
1364 int argc,
1365 const char **argv,
1366 int *argl
1367 ){
1368 if( argc!=2 ){
1369 return Th_WrongNumArgs(interp, "unversioned list");
1370 }
1371 if( Th_IsRepositoryOpen() ){
1372 Stmt q;
1373 char *zList = 0;
1374 int nList = 0;
1375 db_prepare(&q, "SELECT name FROM unversioned WHERE hash IS NOT NULL"
1376 " ORDER BY name");
1377 while( db_step(&q)==SQLITE_ROW ){
1378 Th_ListAppend(interp, &zList, &nList, db_column_text(&q,0), -1);
1379 }
1380 db_finalize(&q);
1381 Th_SetResult(interp, zList, nList);
1382 Th_Free(interp, zList);
1383 return TH_OK;
1384 }else{
1385 Th_SetResult(interp, "repository unavailable", -1);
1386 return TH_ERROR;
1387 }
1388 }
1389
1390 static int unversionedCmd(
1391 Th_Interp *interp,
1392 void *p,
1393 int argc,
1394 const char **argv,
1395 int *argl
1396 ){
1397 static const Th_SubCommand aSub[] = {
1398 { "content", unversionedContentCmd },
1399 { "list", unversionedListCmd },
1400 { 0, 0 }
1401 };
1402 return Th_CallSubCommand(interp, p, argc, argv, argl, aSub);
1403 }
1404
1405 #ifdef _WIN32
1406 # include <windows.h>
1407 #else
1408 # include <sys/time.h>
@@ -1886,10 +1968,11 @@
1968 {"styleHeader", styleHeaderCmd, 0},
1969 {"styleFooter", styleFooterCmd, 0},
1970 {"tclReady", tclReadyCmd, 0},
1971 {"trace", traceCmd, 0},
1972 {"stime", stimeCmd, 0},
1973 {"unversioned", unversionedCmd, 0},
1974 {"utime", utimeCmd, 0},
1975 {"verifyCsrf", verifyCsrfCmd, 0},
1976 {"wiki", wikiCmd, (void*)&aFlags[0]},
1977 {0, 0, 0}
1978 };
1979
+3 -3
--- src/timeline.c
+++ src/timeline.c
@@ -737,11 +737,11 @@
737737
pRow->mergeOut, /* mo */
738738
pRow->mergeUpto, /* mu */
739739
pRow->aiRiser[pRow->iRail], /* u */
740740
pRow->isLeaf ? 1 : 0 /* f */
741741
);
742
- /* u */
742
+ /* au */
743743
cSep = '[';
744744
for(i=0; i<GR_MAX_RAIL; i++){
745745
if( i==pRow->iRail ) continue;
746746
if( pRow->aiRiser[i]>0 ){
747747
cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]);
@@ -757,11 +757,11 @@
757757
cgi_printf("mi:");
758758
cSep = '[';
759759
for(i=0; i<GR_MAX_RAIL; i++){
760760
if( pRow->mergeIn[i] ){
761761
int mi = i;
762
- if( pRow->mergeDown & (1<<i) ) mi = -mi;
762
+ if( (pRow->mergeDown >> i) & 1 ) mi = -mi;
763763
cgi_printf("%c%d", cSep, mi);
764764
cSep = ',';
765765
}
766766
}
767767
if( cSep=='[' ) cgi_printf("[");
@@ -1495,11 +1495,11 @@
14951495
14961496
if( zTagName && g.perm.Read ){
14971497
style_submenu_element("Related", "Related", "%s",
14981498
url_render(&url, "r", zTagName, "t", 0));
14991499
}else if( zBrName && g.perm.Read ){
1500
- style_submenu_element("Branch Only", "only", "%s",
1500
+ style_submenu_element("Omit Related", "only", "%s",
15011501
url_render(&url, "t", zBrName, "r", 0));
15021502
}
15031503
if( zMark && zMark[0]==0 ){
15041504
if( zAfter ) zMark = zAfter;
15051505
if( zBefore ) zMark = zBefore;
15061506
--- src/timeline.c
+++ src/timeline.c
@@ -737,11 +737,11 @@
737 pRow->mergeOut, /* mo */
738 pRow->mergeUpto, /* mu */
739 pRow->aiRiser[pRow->iRail], /* u */
740 pRow->isLeaf ? 1 : 0 /* f */
741 );
742 /* u */
743 cSep = '[';
744 for(i=0; i<GR_MAX_RAIL; i++){
745 if( i==pRow->iRail ) continue;
746 if( pRow->aiRiser[i]>0 ){
747 cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]);
@@ -757,11 +757,11 @@
757 cgi_printf("mi:");
758 cSep = '[';
759 for(i=0; i<GR_MAX_RAIL; i++){
760 if( pRow->mergeIn[i] ){
761 int mi = i;
762 if( pRow->mergeDown & (1<<i) ) mi = -mi;
763 cgi_printf("%c%d", cSep, mi);
764 cSep = ',';
765 }
766 }
767 if( cSep=='[' ) cgi_printf("[");
@@ -1495,11 +1495,11 @@
1495
1496 if( zTagName && g.perm.Read ){
1497 style_submenu_element("Related", "Related", "%s",
1498 url_render(&url, "r", zTagName, "t", 0));
1499 }else if( zBrName && g.perm.Read ){
1500 style_submenu_element("Branch Only", "only", "%s",
1501 url_render(&url, "t", zBrName, "r", 0));
1502 }
1503 if( zMark && zMark[0]==0 ){
1504 if( zAfter ) zMark = zAfter;
1505 if( zBefore ) zMark = zBefore;
1506
--- src/timeline.c
+++ src/timeline.c
@@ -737,11 +737,11 @@
737 pRow->mergeOut, /* mo */
738 pRow->mergeUpto, /* mu */
739 pRow->aiRiser[pRow->iRail], /* u */
740 pRow->isLeaf ? 1 : 0 /* f */
741 );
742 /* au */
743 cSep = '[';
744 for(i=0; i<GR_MAX_RAIL; i++){
745 if( i==pRow->iRail ) continue;
746 if( pRow->aiRiser[i]>0 ){
747 cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]);
@@ -757,11 +757,11 @@
757 cgi_printf("mi:");
758 cSep = '[';
759 for(i=0; i<GR_MAX_RAIL; i++){
760 if( pRow->mergeIn[i] ){
761 int mi = i;
762 if( (pRow->mergeDown >> i) & 1 ) mi = -mi;
763 cgi_printf("%c%d", cSep, mi);
764 cSep = ',';
765 }
766 }
767 if( cSep=='[' ) cgi_printf("[");
@@ -1495,11 +1495,11 @@
1495
1496 if( zTagName && g.perm.Read ){
1497 style_submenu_element("Related", "Related", "%s",
1498 url_render(&url, "r", zTagName, "t", 0));
1499 }else if( zBrName && g.perm.Read ){
1500 style_submenu_element("Omit Related", "only", "%s",
1501 url_render(&url, "t", zBrName, "r", 0));
1502 }
1503 if( zMark && zMark[0]==0 ){
1504 if( zAfter ) zMark = zAfter;
1505 if( zBefore ) zMark = zBefore;
1506
+3 -3
--- src/timeline.c
+++ src/timeline.c
@@ -737,11 +737,11 @@
737737
pRow->mergeOut, /* mo */
738738
pRow->mergeUpto, /* mu */
739739
pRow->aiRiser[pRow->iRail], /* u */
740740
pRow->isLeaf ? 1 : 0 /* f */
741741
);
742
- /* u */
742
+ /* au */
743743
cSep = '[';
744744
for(i=0; i<GR_MAX_RAIL; i++){
745745
if( i==pRow->iRail ) continue;
746746
if( pRow->aiRiser[i]>0 ){
747747
cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]);
@@ -757,11 +757,11 @@
757757
cgi_printf("mi:");
758758
cSep = '[';
759759
for(i=0; i<GR_MAX_RAIL; i++){
760760
if( pRow->mergeIn[i] ){
761761
int mi = i;
762
- if( pRow->mergeDown & (1<<i) ) mi = -mi;
762
+ if( (pRow->mergeDown >> i) & 1 ) mi = -mi;
763763
cgi_printf("%c%d", cSep, mi);
764764
cSep = ',';
765765
}
766766
}
767767
if( cSep=='[' ) cgi_printf("[");
@@ -1495,11 +1495,11 @@
14951495
14961496
if( zTagName && g.perm.Read ){
14971497
style_submenu_element("Related", "Related", "%s",
14981498
url_render(&url, "r", zTagName, "t", 0));
14991499
}else if( zBrName && g.perm.Read ){
1500
- style_submenu_element("Branch Only", "only", "%s",
1500
+ style_submenu_element("Omit Related", "only", "%s",
15011501
url_render(&url, "t", zBrName, "r", 0));
15021502
}
15031503
if( zMark && zMark[0]==0 ){
15041504
if( zAfter ) zMark = zAfter;
15051505
if( zBefore ) zMark = zBefore;
15061506
--- src/timeline.c
+++ src/timeline.c
@@ -737,11 +737,11 @@
737 pRow->mergeOut, /* mo */
738 pRow->mergeUpto, /* mu */
739 pRow->aiRiser[pRow->iRail], /* u */
740 pRow->isLeaf ? 1 : 0 /* f */
741 );
742 /* u */
743 cSep = '[';
744 for(i=0; i<GR_MAX_RAIL; i++){
745 if( i==pRow->iRail ) continue;
746 if( pRow->aiRiser[i]>0 ){
747 cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]);
@@ -757,11 +757,11 @@
757 cgi_printf("mi:");
758 cSep = '[';
759 for(i=0; i<GR_MAX_RAIL; i++){
760 if( pRow->mergeIn[i] ){
761 int mi = i;
762 if( pRow->mergeDown & (1<<i) ) mi = -mi;
763 cgi_printf("%c%d", cSep, mi);
764 cSep = ',';
765 }
766 }
767 if( cSep=='[' ) cgi_printf("[");
@@ -1495,11 +1495,11 @@
1495
1496 if( zTagName && g.perm.Read ){
1497 style_submenu_element("Related", "Related", "%s",
1498 url_render(&url, "r", zTagName, "t", 0));
1499 }else if( zBrName && g.perm.Read ){
1500 style_submenu_element("Branch Only", "only", "%s",
1501 url_render(&url, "t", zBrName, "r", 0));
1502 }
1503 if( zMark && zMark[0]==0 ){
1504 if( zAfter ) zMark = zAfter;
1505 if( zBefore ) zMark = zBefore;
1506
--- src/timeline.c
+++ src/timeline.c
@@ -737,11 +737,11 @@
737 pRow->mergeOut, /* mo */
738 pRow->mergeUpto, /* mu */
739 pRow->aiRiser[pRow->iRail], /* u */
740 pRow->isLeaf ? 1 : 0 /* f */
741 );
742 /* au */
743 cSep = '[';
744 for(i=0; i<GR_MAX_RAIL; i++){
745 if( i==pRow->iRail ) continue;
746 if( pRow->aiRiser[i]>0 ){
747 cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]);
@@ -757,11 +757,11 @@
757 cgi_printf("mi:");
758 cSep = '[';
759 for(i=0; i<GR_MAX_RAIL; i++){
760 if( pRow->mergeIn[i] ){
761 int mi = i;
762 if( (pRow->mergeDown >> i) & 1 ) mi = -mi;
763 cgi_printf("%c%d", cSep, mi);
764 cSep = ',';
765 }
766 }
767 if( cSep=='[' ) cgi_printf("[");
@@ -1495,11 +1495,11 @@
1495
1496 if( zTagName && g.perm.Read ){
1497 style_submenu_element("Related", "Related", "%s",
1498 url_render(&url, "r", zTagName, "t", 0));
1499 }else if( zBrName && g.perm.Read ){
1500 style_submenu_element("Omit Related", "only", "%s",
1501 url_render(&url, "t", zBrName, "r", 0));
1502 }
1503 if( zMark && zMark[0]==0 ){
1504 if( zAfter ) zMark = zAfter;
1505 if( zBefore ) zMark = zBefore;
1506
+10 -5
--- src/tkt.c
+++ src/tkt.c
@@ -216,20 +216,25 @@
216216
const char *zBaseName = zName[0]=='+' ? zName+1 : zName;
217217
j = fieldId(zBaseName);
218218
if( j<0 ) continue;
219219
aUsed[j] = 1;
220220
if( aField[j].mUsed & USEDBY_TICKET ){
221
- if( zName[0]=='+' ){
222
- zName++;
221
+ const char *zUsedByName = zName;
222
+ if( zUsedByName[0]=='+' ){
223
+ zUsedByName++;
223224
blob_append_sql(&sql1,", \"%w\"=coalesce(\"%w\",'') || %Q",
224
- zName, zName, p->aField[i].zValue);
225
+ zUsedByName, zUsedByName, p->aField[i].zValue);
225226
}else{
226
- blob_append_sql(&sql1,", \"%w\"=%Q", zName, p->aField[i].zValue);
227
+ blob_append_sql(&sql1,", \"%w\"=%Q", zUsedByName, p->aField[i].zValue);
227228
}
228229
}
229230
if( aField[j].mUsed & USEDBY_TICKETCHNG ){
230
- blob_append_sql(&sql2, ",\"%w\"", zName);
231
+ const char *zUsedByName = zName;
232
+ if( zUsedByName[0]=='+' ){
233
+ zUsedByName++;
234
+ }
235
+ blob_append_sql(&sql2, ",\"%w\"", zUsedByName);
231236
blob_append_sql(&sql3, ",%Q", p->aField[i].zValue);
232237
}
233238
if( rid>0 ){
234239
wiki_extract_links(p->aField[i].zValue, rid, 1, p->rDate, i==0, 0);
235240
}
236241
--- src/tkt.c
+++ src/tkt.c
@@ -216,20 +216,25 @@
216 const char *zBaseName = zName[0]=='+' ? zName+1 : zName;
217 j = fieldId(zBaseName);
218 if( j<0 ) continue;
219 aUsed[j] = 1;
220 if( aField[j].mUsed & USEDBY_TICKET ){
221 if( zName[0]=='+' ){
222 zName++;
 
223 blob_append_sql(&sql1,", \"%w\"=coalesce(\"%w\",'') || %Q",
224 zName, zName, p->aField[i].zValue);
225 }else{
226 blob_append_sql(&sql1,", \"%w\"=%Q", zName, p->aField[i].zValue);
227 }
228 }
229 if( aField[j].mUsed & USEDBY_TICKETCHNG ){
230 blob_append_sql(&sql2, ",\"%w\"", zName);
 
 
 
 
231 blob_append_sql(&sql3, ",%Q", p->aField[i].zValue);
232 }
233 if( rid>0 ){
234 wiki_extract_links(p->aField[i].zValue, rid, 1, p->rDate, i==0, 0);
235 }
236
--- src/tkt.c
+++ src/tkt.c
@@ -216,20 +216,25 @@
216 const char *zBaseName = zName[0]=='+' ? zName+1 : zName;
217 j = fieldId(zBaseName);
218 if( j<0 ) continue;
219 aUsed[j] = 1;
220 if( aField[j].mUsed & USEDBY_TICKET ){
221 const char *zUsedByName = zName;
222 if( zUsedByName[0]=='+' ){
223 zUsedByName++;
224 blob_append_sql(&sql1,", \"%w\"=coalesce(\"%w\",'') || %Q",
225 zUsedByName, zUsedByName, p->aField[i].zValue);
226 }else{
227 blob_append_sql(&sql1,", \"%w\"=%Q", zUsedByName, p->aField[i].zValue);
228 }
229 }
230 if( aField[j].mUsed & USEDBY_TICKETCHNG ){
231 const char *zUsedByName = zName;
232 if( zUsedByName[0]=='+' ){
233 zUsedByName++;
234 }
235 blob_append_sql(&sql2, ",\"%w\"", zUsedByName);
236 blob_append_sql(&sql3, ",%Q", p->aField[i].zValue);
237 }
238 if( rid>0 ){
239 wiki_extract_links(p->aField[i].zValue, rid, 1, p->rDate, i==0, 0);
240 }
241
--- src/unversioned.c
+++ src/unversioned.c
@@ -452,18 +452,20 @@
452452
**
453453
** Display a list of all unversioned files in the repository.
454454
** Query parameters:
455455
**
456456
** byage=1 Order the initial display be decreasing age
457
+** showdel=0 Show deleted files
457458
*/
458459
void uvstat_page(void){
459460
Stmt q;
460461
sqlite3_int64 iNow;
461462
sqlite3_int64 iTotalSz = 0;
462463
int cnt = 0;
463464
int n = 0;
464465
const char *zOrderBy = "name";
466
+ int showDel = 0;
465467
char zSzName[100];
466468
467469
login_check_credentials();
468470
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
469471
style_header("Unversioned Files");
@@ -471,20 +473,22 @@
471473
@ No unversioned files on this server
472474
style_footer();
473475
return;
474476
}
475477
if( PB("byage") ) zOrderBy = "mtime DESC";
478
+ if( PB("showdel") ) showDel = 1;
476479
db_prepare(&q,
477480
"SELECT"
478481
" name,"
479482
" mtime,"
480483
" hash,"
481484
" sz,"
482485
" (SELECT login FROM rcvfrom, user"
483486
" WHERE user.uid=rcvfrom.uid AND rcvfrom.rcvid=unversioned.rcvid),"
484487
" rcvid"
485
- " FROM unversioned ORDER BY %s",
488
+ " FROM unversioned %s ORDER BY %s",
489
+ showDel ? "" : "WHERE hash IS NOT NULL" /*safe-for-%s*/,
486490
zOrderBy/*safe-for-%s*/
487491
);
488492
iNow = db_int64(0, "SELECT strftime('%%s','now');");
489493
while( db_step(&q)==SQLITE_ROW ){
490494
const char *zName = db_column_text(&q, 0);
491495
--- src/unversioned.c
+++ src/unversioned.c
@@ -452,18 +452,20 @@
452 **
453 ** Display a list of all unversioned files in the repository.
454 ** Query parameters:
455 **
456 ** byage=1 Order the initial display be decreasing age
 
457 */
458 void uvstat_page(void){
459 Stmt q;
460 sqlite3_int64 iNow;
461 sqlite3_int64 iTotalSz = 0;
462 int cnt = 0;
463 int n = 0;
464 const char *zOrderBy = "name";
 
465 char zSzName[100];
466
467 login_check_credentials();
468 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
469 style_header("Unversioned Files");
@@ -471,20 +473,22 @@
471 @ No unversioned files on this server
472 style_footer();
473 return;
474 }
475 if( PB("byage") ) zOrderBy = "mtime DESC";
 
476 db_prepare(&q,
477 "SELECT"
478 " name,"
479 " mtime,"
480 " hash,"
481 " sz,"
482 " (SELECT login FROM rcvfrom, user"
483 " WHERE user.uid=rcvfrom.uid AND rcvfrom.rcvid=unversioned.rcvid),"
484 " rcvid"
485 " FROM unversioned ORDER BY %s",
 
486 zOrderBy/*safe-for-%s*/
487 );
488 iNow = db_int64(0, "SELECT strftime('%%s','now');");
489 while( db_step(&q)==SQLITE_ROW ){
490 const char *zName = db_column_text(&q, 0);
491
--- src/unversioned.c
+++ src/unversioned.c
@@ -452,18 +452,20 @@
452 **
453 ** Display a list of all unversioned files in the repository.
454 ** Query parameters:
455 **
456 ** byage=1 Order the initial display be decreasing age
457 ** showdel=0 Show deleted files
458 */
459 void uvstat_page(void){
460 Stmt q;
461 sqlite3_int64 iNow;
462 sqlite3_int64 iTotalSz = 0;
463 int cnt = 0;
464 int n = 0;
465 const char *zOrderBy = "name";
466 int showDel = 0;
467 char zSzName[100];
468
469 login_check_credentials();
470 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
471 style_header("Unversioned Files");
@@ -471,20 +473,22 @@
473 @ No unversioned files on this server
474 style_footer();
475 return;
476 }
477 if( PB("byage") ) zOrderBy = "mtime DESC";
478 if( PB("showdel") ) showDel = 1;
479 db_prepare(&q,
480 "SELECT"
481 " name,"
482 " mtime,"
483 " hash,"
484 " sz,"
485 " (SELECT login FROM rcvfrom, user"
486 " WHERE user.uid=rcvfrom.uid AND rcvfrom.rcvid=unversioned.rcvid),"
487 " rcvid"
488 " FROM unversioned %s ORDER BY %s",
489 showDel ? "" : "WHERE hash IS NOT NULL" /*safe-for-%s*/,
490 zOrderBy/*safe-for-%s*/
491 );
492 iNow = db_int64(0, "SELECT strftime('%%s','now');");
493 while( db_step(&q)==SQLITE_ROW ){
494 const char *zName = db_column_text(&q, 0);
495
+33 -16
--- src/user.c
+++ src/user.c
@@ -19,14 +19,10 @@
1919
** querying information about users.
2020
*/
2121
#include "config.h"
2222
#include "user.h"
2323
24
-#if defined(_WIN32)
25
-#include <conio.h>
26
-#endif
27
-
2824
/*
2925
** Strip leading and trailing space from a string and add the string
3026
** onto the end of a blob.
3127
*/
3228
static void strip_string(Blob *pBlob, char *z){
@@ -43,53 +39,74 @@
4339
}
4440
blob_append(pBlob, z, -1);
4541
}
4642
4743
#if defined(_WIN32) || defined(__BIONIC__)
48
-#ifdef __MINGW32__
44
+#ifdef _WIN32
4945
#include <conio.h>
5046
#endif
47
+
5148
/*
52
-** getpass for Windows and Android
49
+** getpass() for Windows and Android.
5350
*/
51
+static char *zPwdBuffer = 0;
52
+static size_t nPwdBuffer = 0;
53
+
5454
static char *getpass(const char *prompt){
55
- static char pwd[64];
55
+ char *zPwd;
56
+ size_t nPwd;
5657
size_t i;
5758
59
+ if( zPwdBuffer==0 ){
60
+ zPwdBuffer = fossil_secure_alloc_page(&nPwdBuffer);
61
+ assert( zPwdBuffer );
62
+ }else{
63
+ fossil_secure_zero(zPwdBuffer, nPwdBuffer);
64
+ }
65
+ zPwd = zPwdBuffer;
66
+ nPwd = nPwdBuffer;
5867
fputs(prompt,stderr);
5968
fflush(stderr);
60
- for(i=0; i<sizeof(pwd)-1; ++i){
69
+ assert( zPwd!=0 );
70
+ assert( nPwd>0 );
71
+ for(i=0; i<nPwd-1; ++i){
6172
#if defined(_WIN32)
62
- pwd[i] = _getch();
73
+ zPwd[i] = _getch();
6374
#else
64
- pwd[i] = getc(stdin);
75
+ zPwd[i] = getc(stdin);
6576
#endif
66
- if(pwd[i]=='\r' || pwd[i]=='\n'){
77
+ if(zPwd[i]=='\r' || zPwd[i]=='\n'){
6778
break;
6879
}
6980
/* BS or DEL */
70
- else if(i>0 && (pwd[i]==8 || pwd[i]==127)){
81
+ else if(i>0 && (zPwd[i]==8 || zPwd[i]==127)){
7182
i -= 2;
7283
continue;
7384
}
7485
/* CTRL-C */
75
- else if(pwd[i]==3) {
86
+ else if(zPwd[i]==3) {
7687
i=0;
7788
break;
7889
}
7990
/* ESC */
80
- else if(pwd[i]==27){
91
+ else if(zPwd[i]==27){
8192
i=0;
8293
break;
8394
}
8495
else{
8596
fputc('*',stderr);
8697
}
8798
}
88
- pwd[i]='\0';
99
+ zPwd[i]='\0';
89100
fputs("\n", stderr);
90
- return pwd;
101
+ assert( zPwd==zPwdBuffer );
102
+ return zPwd;
103
+}
104
+void freepass(){
105
+ if( !zPwdBuffer ) return;
106
+ assert( nPwdBuffer>0 );
107
+ fossil_secure_free_page(zPwdBuffer, nPwdBuffer);
91108
}
92109
#endif
93110
94111
#if defined(_WIN32) || defined(WIN32)
95112
# include <io.h>
96113
--- src/user.c
+++ src/user.c
@@ -19,14 +19,10 @@
19 ** querying information about users.
20 */
21 #include "config.h"
22 #include "user.h"
23
24 #if defined(_WIN32)
25 #include <conio.h>
26 #endif
27
28 /*
29 ** Strip leading and trailing space from a string and add the string
30 ** onto the end of a blob.
31 */
32 static void strip_string(Blob *pBlob, char *z){
@@ -43,53 +39,74 @@
43 }
44 blob_append(pBlob, z, -1);
45 }
46
47 #if defined(_WIN32) || defined(__BIONIC__)
48 #ifdef __MINGW32__
49 #include <conio.h>
50 #endif
 
51 /*
52 ** getpass for Windows and Android
53 */
 
 
 
54 static char *getpass(const char *prompt){
55 static char pwd[64];
 
56 size_t i;
57
 
 
 
 
 
 
 
 
58 fputs(prompt,stderr);
59 fflush(stderr);
60 for(i=0; i<sizeof(pwd)-1; ++i){
 
 
61 #if defined(_WIN32)
62 pwd[i] = _getch();
63 #else
64 pwd[i] = getc(stdin);
65 #endif
66 if(pwd[i]=='\r' || pwd[i]=='\n'){
67 break;
68 }
69 /* BS or DEL */
70 else if(i>0 && (pwd[i]==8 || pwd[i]==127)){
71 i -= 2;
72 continue;
73 }
74 /* CTRL-C */
75 else if(pwd[i]==3) {
76 i=0;
77 break;
78 }
79 /* ESC */
80 else if(pwd[i]==27){
81 i=0;
82 break;
83 }
84 else{
85 fputc('*',stderr);
86 }
87 }
88 pwd[i]='\0';
89 fputs("\n", stderr);
90 return pwd;
 
 
 
 
 
 
91 }
92 #endif
93
94 #if defined(_WIN32) || defined(WIN32)
95 # include <io.h>
96
--- src/user.c
+++ src/user.c
@@ -19,14 +19,10 @@
19 ** querying information about users.
20 */
21 #include "config.h"
22 #include "user.h"
23
 
 
 
 
24 /*
25 ** Strip leading and trailing space from a string and add the string
26 ** onto the end of a blob.
27 */
28 static void strip_string(Blob *pBlob, char *z){
@@ -43,53 +39,74 @@
39 }
40 blob_append(pBlob, z, -1);
41 }
42
43 #if defined(_WIN32) || defined(__BIONIC__)
44 #ifdef _WIN32
45 #include <conio.h>
46 #endif
47
48 /*
49 ** getpass() for Windows and Android.
50 */
51 static char *zPwdBuffer = 0;
52 static size_t nPwdBuffer = 0;
53
54 static char *getpass(const char *prompt){
55 char *zPwd;
56 size_t nPwd;
57 size_t i;
58
59 if( zPwdBuffer==0 ){
60 zPwdBuffer = fossil_secure_alloc_page(&nPwdBuffer);
61 assert( zPwdBuffer );
62 }else{
63 fossil_secure_zero(zPwdBuffer, nPwdBuffer);
64 }
65 zPwd = zPwdBuffer;
66 nPwd = nPwdBuffer;
67 fputs(prompt,stderr);
68 fflush(stderr);
69 assert( zPwd!=0 );
70 assert( nPwd>0 );
71 for(i=0; i<nPwd-1; ++i){
72 #if defined(_WIN32)
73 zPwd[i] = _getch();
74 #else
75 zPwd[i] = getc(stdin);
76 #endif
77 if(zPwd[i]=='\r' || zPwd[i]=='\n'){
78 break;
79 }
80 /* BS or DEL */
81 else if(i>0 && (zPwd[i]==8 || zPwd[i]==127)){
82 i -= 2;
83 continue;
84 }
85 /* CTRL-C */
86 else if(zPwd[i]==3) {
87 i=0;
88 break;
89 }
90 /* ESC */
91 else if(zPwd[i]==27){
92 i=0;
93 break;
94 }
95 else{
96 fputc('*',stderr);
97 }
98 }
99 zPwd[i]='\0';
100 fputs("\n", stderr);
101 assert( zPwd==zPwdBuffer );
102 return zPwd;
103 }
104 void freepass(){
105 if( !zPwdBuffer ) return;
106 assert( nPwdBuffer>0 );
107 fossil_secure_free_page(zPwdBuffer, nPwdBuffer);
108 }
109 #endif
110
111 #if defined(_WIN32) || defined(WIN32)
112 # include <io.h>
113
+57
--- src/util.c
+++ src/util.c
@@ -55,10 +55,67 @@
5555
}
5656
void *fossil_realloc(void *p, size_t n){
5757
p = realloc(p, n);
5858
if( p==0 ) fossil_panic("out of memory");
5959
return p;
60
+}
61
+void fossil_secure_zero(void *p, size_t n){
62
+ volatile unsigned char *vp = (volatile unsigned char *)p;
63
+ size_t i;
64
+
65
+ if( p==0 ) return;
66
+ assert( n>0 );
67
+ if( n==0 ) return;
68
+ for(i=0; i<n; i++){ vp[i] ^= 0xFF; }
69
+ for(i=0; i<n; i++){ vp[i] ^= vp[i]; }
70
+}
71
+void fossil_get_page_size(size_t *piPageSize){
72
+#if defined(_WIN32)
73
+ SYSTEM_INFO sysInfo;
74
+ memset(&sysInfo, 0, sizeof(SYSTEM_INFO));
75
+ GetSystemInfo(&sysInfo);
76
+ *piPageSize = (size_t)sysInfo.dwPageSize;
77
+#else
78
+ *piPageSize = 4096; /* FIXME: What for POSIX? */
79
+#endif
80
+}
81
+void *fossil_secure_alloc_page(size_t *pN){
82
+ void *p;
83
+ size_t pageSize;
84
+
85
+ fossil_get_page_size(&pageSize);
86
+ assert( pageSize>0 );
87
+ assert( pageSize%2==0 );
88
+#if defined(_WIN32)
89
+ p = VirtualAlloc(NULL, pageSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
90
+ if( p==NULL ){
91
+ fossil_fatal("VirtualAlloc failed: %lu\n", GetLastError());
92
+ }
93
+ if( !VirtualLock(p, pageSize) ){
94
+ fossil_fatal("VirtualLock failed: %lu\n", GetLastError());
95
+ }
96
+#else
97
+ p = fossil_malloc(pageSize);
98
+#endif
99
+ fossil_secure_zero(p, pageSize);
100
+ if( pN ) *pN = pageSize;
101
+ return p;
102
+}
103
+void fossil_secure_free_page(void *p, size_t n){
104
+ if( !p ) return;
105
+ assert( n>0 );
106
+ fossil_secure_zero(p, n);
107
+#if defined(_WIN32)
108
+ if( !VirtualUnlock(p, n) ){
109
+ fossil_fatal("VirtualUnlock failed: %lu\n", GetLastError());
110
+ }
111
+ if( !VirtualFree(p, 0, MEM_RELEASE) ){
112
+ fossil_fatal("VirtualFree failed: %lu\n", GetLastError());
113
+ }
114
+#else
115
+ fossil_free(p);
116
+#endif
60117
}
61118
62119
/*
63120
** This function implements a cross-platform "system()" interface.
64121
*/
65122
--- src/util.c
+++ src/util.c
@@ -55,10 +55,67 @@
55 }
56 void *fossil_realloc(void *p, size_t n){
57 p = realloc(p, n);
58 if( p==0 ) fossil_panic("out of memory");
59 return p;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60 }
61
62 /*
63 ** This function implements a cross-platform "system()" interface.
64 */
65
--- src/util.c
+++ src/util.c
@@ -55,10 +55,67 @@
55 }
56 void *fossil_realloc(void *p, size_t n){
57 p = realloc(p, n);
58 if( p==0 ) fossil_panic("out of memory");
59 return p;
60 }
61 void fossil_secure_zero(void *p, size_t n){
62 volatile unsigned char *vp = (volatile unsigned char *)p;
63 size_t i;
64
65 if( p==0 ) return;
66 assert( n>0 );
67 if( n==0 ) return;
68 for(i=0; i<n; i++){ vp[i] ^= 0xFF; }
69 for(i=0; i<n; i++){ vp[i] ^= vp[i]; }
70 }
71 void fossil_get_page_size(size_t *piPageSize){
72 #if defined(_WIN32)
73 SYSTEM_INFO sysInfo;
74 memset(&sysInfo, 0, sizeof(SYSTEM_INFO));
75 GetSystemInfo(&sysInfo);
76 *piPageSize = (size_t)sysInfo.dwPageSize;
77 #else
78 *piPageSize = 4096; /* FIXME: What for POSIX? */
79 #endif
80 }
81 void *fossil_secure_alloc_page(size_t *pN){
82 void *p;
83 size_t pageSize;
84
85 fossil_get_page_size(&pageSize);
86 assert( pageSize>0 );
87 assert( pageSize%2==0 );
88 #if defined(_WIN32)
89 p = VirtualAlloc(NULL, pageSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
90 if( p==NULL ){
91 fossil_fatal("VirtualAlloc failed: %lu\n", GetLastError());
92 }
93 if( !VirtualLock(p, pageSize) ){
94 fossil_fatal("VirtualLock failed: %lu\n", GetLastError());
95 }
96 #else
97 p = fossil_malloc(pageSize);
98 #endif
99 fossil_secure_zero(p, pageSize);
100 if( pN ) *pN = pageSize;
101 return p;
102 }
103 void fossil_secure_free_page(void *p, size_t n){
104 if( !p ) return;
105 assert( n>0 );
106 fossil_secure_zero(p, n);
107 #if defined(_WIN32)
108 if( !VirtualUnlock(p, n) ){
109 fossil_fatal("VirtualUnlock failed: %lu\n", GetLastError());
110 }
111 if( !VirtualFree(p, 0, MEM_RELEASE) ){
112 fossil_fatal("VirtualFree failed: %lu\n", GetLastError());
113 }
114 #else
115 fossil_free(p);
116 #endif
117 }
118
119 /*
120 ** This function implements a cross-platform "system()" interface.
121 */
122
+17 -2
--- src/winhttp.c
+++ src/winhttp.c
@@ -306,10 +306,14 @@
306306
SOCKADDR_IN addr;
307307
int idCnt = 0;
308308
int iPort = mnPort;
309309
Blob options;
310310
wchar_t zTmpPath[MAX_PATH];
311
+#if USE_SEE
312
+ const char *zSavedKey = 0;
313
+ size_t savedKeySize = 0;
314
+#endif
311315
312316
blob_zero(&options);
313317
if( zBaseUrl ){
314318
blob_appendf(&options, " --baseurl %s", zBaseUrl);
315319
}
@@ -326,10 +330,18 @@
326330
blob_appendf(&options, " --th-trace");
327331
}
328332
if( flags & HTTP_SERVER_REPOLIST ){
329333
blob_appendf(&options, " --repolist");
330334
}
335
+#if USE_SEE
336
+ zSavedKey = db_get_saved_encryption_key();
337
+ savedKeySize = db_get_saved_encryption_key_size();
338
+ if( zSavedKey!=0 && savedKeySize>0 ){
339
+ blob_appendf(&options, " --usepidkey %lu:%p:%u", GetCurrentProcessId(),
340
+ zSavedKey, savedKeySize);
341
+ }
342
+#endif
331343
if( WSAStartup(MAKEWORD(1,1), &wd) ){
332344
fossil_fatal("unable to initialize winsock");
333345
}
334346
while( iPort<=mxPort ){
335347
s = socket(AF_INET, SOCK_STREAM, 0);
@@ -654,11 +666,13 @@
654666
}
655667
}
656668
return 0;
657669
}
658670
659
-/* dupe ifdef needed for mkindex
671
+/* Duplicate #ifdef needed for mkindex */
672
+#ifdef _WIN32
673
+/*
660674
** COMMAND: winsrv*
661675
**
662676
** Usage: %fossil winsrv METHOD ?SERVICE-NAME? ?OPTIONS?
663677
**
664678
** Where METHOD is one of: create delete show start stop.
@@ -1103,6 +1117,7 @@
11031117
fossil_fatal("METHOD should be one of:"
11041118
" create delete show start stop");
11051119
}
11061120
return;
11071121
}
1108
-#endif /* _WIN32 -- This code is for win32 only */
1122
+#endif /* _WIN32 -- dupe needed for mkindex */
1123
+#endif /* _WIN32 -- This code is for win32 only */
11091124
--- src/winhttp.c
+++ src/winhttp.c
@@ -306,10 +306,14 @@
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 }
@@ -326,10 +330,18 @@
326 blob_appendf(&options, " --th-trace");
327 }
328 if( flags & HTTP_SERVER_REPOLIST ){
329 blob_appendf(&options, " --repolist");
330 }
 
 
 
 
 
 
 
 
331 if( WSAStartup(MAKEWORD(1,1), &wd) ){
332 fossil_fatal("unable to initialize winsock");
333 }
334 while( iPort<=mxPort ){
335 s = socket(AF_INET, SOCK_STREAM, 0);
@@ -654,11 +666,13 @@
654 }
655 }
656 return 0;
657 }
658
659 /* dupe ifdef needed for mkindex
 
 
660 ** COMMAND: winsrv*
661 **
662 ** Usage: %fossil winsrv METHOD ?SERVICE-NAME? ?OPTIONS?
663 **
664 ** Where METHOD is one of: create delete show start stop.
@@ -1103,6 +1117,7 @@
1103 fossil_fatal("METHOD should be one of:"
1104 " create delete show start stop");
1105 }
1106 return;
1107 }
1108 #endif /* _WIN32 -- This code is for win32 only */
 
1109
--- src/winhttp.c
+++ src/winhttp.c
@@ -306,10 +306,14 @@
306 SOCKADDR_IN addr;
307 int idCnt = 0;
308 int iPort = mnPort;
309 Blob options;
310 wchar_t zTmpPath[MAX_PATH];
311 #if USE_SEE
312 const char *zSavedKey = 0;
313 size_t savedKeySize = 0;
314 #endif
315
316 blob_zero(&options);
317 if( zBaseUrl ){
318 blob_appendf(&options, " --baseurl %s", zBaseUrl);
319 }
@@ -326,10 +330,18 @@
330 blob_appendf(&options, " --th-trace");
331 }
332 if( flags & HTTP_SERVER_REPOLIST ){
333 blob_appendf(&options, " --repolist");
334 }
335 #if USE_SEE
336 zSavedKey = db_get_saved_encryption_key();
337 savedKeySize = db_get_saved_encryption_key_size();
338 if( zSavedKey!=0 && savedKeySize>0 ){
339 blob_appendf(&options, " --usepidkey %lu:%p:%u", GetCurrentProcessId(),
340 zSavedKey, savedKeySize);
341 }
342 #endif
343 if( WSAStartup(MAKEWORD(1,1), &wd) ){
344 fossil_fatal("unable to initialize winsock");
345 }
346 while( iPort<=mxPort ){
347 s = socket(AF_INET, SOCK_STREAM, 0);
@@ -654,11 +666,13 @@
666 }
667 }
668 return 0;
669 }
670
671 /* Duplicate #ifdef needed for mkindex */
672 #ifdef _WIN32
673 /*
674 ** COMMAND: winsrv*
675 **
676 ** Usage: %fossil winsrv METHOD ?SERVICE-NAME? ?OPTIONS?
677 **
678 ** Where METHOD is one of: create delete show start stop.
@@ -1103,6 +1117,7 @@
1117 fossil_fatal("METHOD should be one of:"
1118 " create delete show start stop");
1119 }
1120 return;
1121 }
1122 #endif /* _WIN32 -- dupe needed for mkindex */
1123 #endif /* _WIN32 -- This code is for win32 only */
1124
+1 -1
--- src/xfer.c
+++ src/xfer.c
@@ -2140,11 +2140,11 @@
21402140
}
21412141
if( syncFlags & (SYNC_UV_TRACE|SYNC_UV_DRYRUN) ){
21422142
const char *zMsg = 0;
21432143
switch( iStatus ){
21442144
case 0:
2145
- case 1: zMsg = "UV-PULL"; break;
2145
+ case 1: zMsg = "UV-PULL"; break;
21462146
case 2: zMsg = "UV-PULL-MTIME-ONLY"; break;
21472147
case 4: zMsg = "UV-PUSH-MTIME-ONLY"; break;
21482148
case 5: zMsg = "UV-PUSH"; break;
21492149
}
21502150
if( zMsg ) fossil_print("\r%s: %s\n", zMsg, zName);
21512151
21522152
ADDED test/diff.test
--- src/xfer.c
+++ src/xfer.c
@@ -2140,11 +2140,11 @@
2140 }
2141 if( syncFlags & (SYNC_UV_TRACE|SYNC_UV_DRYRUN) ){
2142 const char *zMsg = 0;
2143 switch( iStatus ){
2144 case 0:
2145 case 1: zMsg = "UV-PULL"; break;
2146 case 2: zMsg = "UV-PULL-MTIME-ONLY"; break;
2147 case 4: zMsg = "UV-PUSH-MTIME-ONLY"; break;
2148 case 5: zMsg = "UV-PUSH"; break;
2149 }
2150 if( zMsg ) fossil_print("\r%s: %s\n", zMsg, zName);
2151
2152 DDED test/diff.test
--- src/xfer.c
+++ src/xfer.c
@@ -2140,11 +2140,11 @@
2140 }
2141 if( syncFlags & (SYNC_UV_TRACE|SYNC_UV_DRYRUN) ){
2142 const char *zMsg = 0;
2143 switch( iStatus ){
2144 case 0:
2145 case 1: zMsg = "UV-PULL"; break;
2146 case 2: zMsg = "UV-PULL-MTIME-ONLY"; break;
2147 case 4: zMsg = "UV-PUSH-MTIME-ONLY"; break;
2148 case 5: zMsg = "UV-PUSH"; break;
2149 }
2150 if( zMsg ) fossil_print("\r%s: %s\n", zMsg, zName);
2151
2152 DDED test/diff.test
--- a/test/diff.test
+++ b/test/diff.test
@@ -0,0 +1,31 @@
1
+16384]"
2
+write_file file4_file file4.dat "test file 4 (l16384]\ntwo"
3
+write_file f163842016 D. Richard Hipp
4
+#
5
+# This program is free software; you can redistribute it and/or
6
+# modify it under the terms of the Simplified BSD License (also
7
+# known as the "2-Clause License" or "FreeBSD License".)
8
+#
9
+# This program is distributed in the hope that it will be useful,
10
+# but without any warranty; without even the implied warranty of
11
+# merchantability or fitness for a particular purpose.
12
+#
13
+# Author contact information:
14
+# [email protected]
15
+# http://www.hwaci.com/drh/
16
+#
17
+############################################################################
18
+#
19
+# Tests for the diff command.
20
+#
21
+
22
+require_no_open_checkout
23
+
24
+test_setup; set rootDir [file normalize [pwd]]
25
+
26
+###################################
27
+# Tests of binary file det#
28
+# Coite_file file1.dat z 32768]
29
+fossil diff file1.dat
30
+
31
+test diff-file1-1 {[normalize_restest_cleanup
--- a/test/diff.test
+++ b/test/diff.test
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/test/diff.test
+++ b/test/diff.test
@@ -0,0 +1,31 @@
1 16384]"
2 write_file file4_file file4.dat "test file 4 (l16384]\ntwo"
3 write_file f163842016 D. Richard Hipp
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the Simplified BSD License (also
7 # known as the "2-Clause License" or "FreeBSD License".)
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but without any warranty; without even the implied warranty of
11 # merchantability or fitness for a particular purpose.
12 #
13 # Author contact information:
14 # [email protected]
15 # http://www.hwaci.com/drh/
16 #
17 ############################################################################
18 #
19 # Tests for the diff command.
20 #
21
22 require_no_open_checkout
23
24 test_setup; set rootDir [file normalize [pwd]]
25
26 ###################################
27 # Tests of binary file det#
28 # Coite_file file1.dat z 32768]
29 fossil diff file1.dat
30
31 test diff-file1-1 {[normalize_restest_cleanup
--- test/graph-test-1.wiki
+++ test/graph-test-1.wiki
@@ -66,10 +66,13 @@
6666
* <a href="../../../timeline?c=20015206bc"
6767
target="testwindow">
6868
This timeline has a hidden commit.</a> Click Unhide to reveal.
6969
* <a href="../../../timeline?y=ci&n=15&b=2a4e4cf03e"
7070
target="testwindow">Isolated check-ins.</a>
71
+ * <a href="../../../timeline?b=0fa60142&n=50"
72
+ target="testwindow">Single branch raiser from bottom of page
73
+ up to checkins 057e4b and d3cc6d</a>
7174
7275
External:
7376
7477
* <a href="http://www.sqlite.org/src/timeline?c=2010-09-29&nd"
7578
target="testwindow">Timewarp due to a mis-configured system clock.</a>
7679
--- test/graph-test-1.wiki
+++ test/graph-test-1.wiki
@@ -66,10 +66,13 @@
66 * <a href="../../../timeline?c=20015206bc"
67 target="testwindow">
68 This timeline has a hidden commit.</a> Click Unhide to reveal.
69 * <a href="../../../timeline?y=ci&n=15&b=2a4e4cf03e"
70 target="testwindow">Isolated check-ins.</a>
 
 
 
71
72 External:
73
74 * <a href="http://www.sqlite.org/src/timeline?c=2010-09-29&nd"
75 target="testwindow">Timewarp due to a mis-configured system clock.</a>
76
--- test/graph-test-1.wiki
+++ test/graph-test-1.wiki
@@ -66,10 +66,13 @@
66 * <a href="../../../timeline?c=20015206bc"
67 target="testwindow">
68 This timeline has a hidden commit.</a> Click Unhide to reveal.
69 * <a href="../../../timeline?y=ci&n=15&b=2a4e4cf03e"
70 target="testwindow">Isolated check-ins.</a>
71 * <a href="../../../timeline?b=0fa60142&n=50"
72 target="testwindow">Single branch raiser from bottom of page
73 up to checkins 057e4b and d3cc6d</a>
74
75 External:
76
77 * <a href="http://www.sqlite.org/src/timeline?c=2010-09-29&nd"
78 target="testwindow">Timewarp due to a mis-configured system clock.</a>
79
+37 -1
--- test/th1.test
+++ test/th1.test
@@ -1038,11 +1038,11 @@
10381038
error expr for getParameter glob_match globalState hascap hasfeature\
10391039
html htmlize http httpize if info insertCsrf lindex linecount list\
10401040
llength lsearch markdown proc puts query randhex redirect regexp\
10411041
reinitialize rename render repository return searchable set\
10421042
setParameter setting stime string styleFooter styleHeader tclReady\
1043
- trace unset uplevel upvar utime verifyCsrf wiki}
1043
+ trace unset unversioned uplevel upvar utime verifyCsrf wiki}
10441044
set tcl_commands {tclEval tclExpr tclInvoke tclIsSafe tclMakeSafe}
10451045
if {$th1Tcl} {
10461046
test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands $tcl_commands"]}
10471047
} else {
10481048
test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands"]}
@@ -1562,9 +1562,45 @@
15621562
}
15631563
15641564
fossil test-th-source $th1FileName
15651565
test th1-source-1 {$RESULT eq {TH_RETURN: 0 1 2 3 4 5 6 7 8 9}}
15661566
file delete $th1FileName
1567
+
1568
+###############################################################################
1569
+
1570
+#
1571
+# TODO: Modify the result of this test if the list of unversioned files
1572
+# changes.
1573
+#
1574
+run_in_checkout {
1575
+ fossil test-th-eval --open-config "unversioned list"
1576
+}
1577
+
1578
+test th1-unversioned-1 {[normalize_result] eq \
1579
+{build-icons/linux.gif build-icons/linux64.gif build-icons/mac.gif\
1580
+build-icons/openbsd.gif build-icons/src.gif build-icons/win32.gif\
1581
+download.html download/fossil-linux-x86-1.32.zip\
1582
+download/fossil-linux-x86-1.33.zip download/fossil-linux-x86-1.34.zip\
1583
+download/fossil-linux-x86-1.35.zip download/fossil-macosx-x86-1.32.zip\
1584
+download/fossil-macosx-x86-1.33.zip download/fossil-macosx-x86-1.34.zip\
1585
+download/fossil-macosx-x86-1.35.zip download/fossil-openbsd-x86-1.32.zip\
1586
+download/fossil-openbsd-x86-1.33.zip download/fossil-openbsd-x86-1.34.tar.gz\
1587
+download/fossil-openbsd-x86-1.35.tar.gz download/fossil-src-1.32.tar.gz\
1588
+download/fossil-src-1.33.tar.gz download/fossil-src-1.34.tar.gz\
1589
+download/fossil-src-1.35.tar.gz download/fossil-w32-1.32.zip\
1590
+download/fossil-w32-1.33.zip download/fossil-w32-1.34.zip\
1591
+download/fossil-w32-1.35.zip download/releasenotes-1.32.html\
1592
+download/releasenotes-1.33.html download/releasenotes-1.34.html\
1593
+download/releasenotes-1.35.html index.wiki}}
1594
+
1595
+###############################################################################
1596
+
1597
+run_in_checkout {
1598
+ fossil test-th-eval --open-config \
1599
+ {string length [unversioned content build-icons/src.gif]}
1600
+}
1601
+
1602
+test th1-unversioned-2 {$RESULT eq {4592}}
15671603
15681604
###############################################################################
15691605
15701606
test_cleanup
15711607
--- test/th1.test
+++ test/th1.test
@@ -1038,11 +1038,11 @@
1038 error expr for getParameter glob_match globalState hascap hasfeature\
1039 html htmlize http httpize if info insertCsrf lindex linecount list\
1040 llength lsearch markdown proc puts query randhex redirect regexp\
1041 reinitialize rename render repository return searchable set\
1042 setParameter setting stime string styleFooter styleHeader tclReady\
1043 trace unset uplevel upvar utime verifyCsrf wiki}
1044 set tcl_commands {tclEval tclExpr tclInvoke tclIsSafe tclMakeSafe}
1045 if {$th1Tcl} {
1046 test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands $tcl_commands"]}
1047 } else {
1048 test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands"]}
@@ -1562,9 +1562,45 @@
1562 }
1563
1564 fossil test-th-source $th1FileName
1565 test th1-source-1 {$RESULT eq {TH_RETURN: 0 1 2 3 4 5 6 7 8 9}}
1566 file delete $th1FileName
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1567
1568 ###############################################################################
1569
1570 test_cleanup
1571
--- test/th1.test
+++ test/th1.test
@@ -1038,11 +1038,11 @@
1038 error expr for getParameter glob_match globalState hascap hasfeature\
1039 html htmlize http httpize if info insertCsrf lindex linecount list\
1040 llength lsearch markdown proc puts query randhex redirect regexp\
1041 reinitialize rename render repository return searchable set\
1042 setParameter setting stime string styleFooter styleHeader tclReady\
1043 trace unset unversioned uplevel upvar utime verifyCsrf wiki}
1044 set tcl_commands {tclEval tclExpr tclInvoke tclIsSafe tclMakeSafe}
1045 if {$th1Tcl} {
1046 test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands $tcl_commands"]}
1047 } else {
1048 test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands"]}
@@ -1562,9 +1562,45 @@
1562 }
1563
1564 fossil test-th-source $th1FileName
1565 test th1-source-1 {$RESULT eq {TH_RETURN: 0 1 2 3 4 5 6 7 8 9}}
1566 file delete $th1FileName
1567
1568 ###############################################################################
1569
1570 #
1571 # TODO: Modify the result of this test if the list of unversioned files
1572 # changes.
1573 #
1574 run_in_checkout {
1575 fossil test-th-eval --open-config "unversioned list"
1576 }
1577
1578 test th1-unversioned-1 {[normalize_result] eq \
1579 {build-icons/linux.gif build-icons/linux64.gif build-icons/mac.gif\
1580 build-icons/openbsd.gif build-icons/src.gif build-icons/win32.gif\
1581 download.html download/fossil-linux-x86-1.32.zip\
1582 download/fossil-linux-x86-1.33.zip download/fossil-linux-x86-1.34.zip\
1583 download/fossil-linux-x86-1.35.zip download/fossil-macosx-x86-1.32.zip\
1584 download/fossil-macosx-x86-1.33.zip download/fossil-macosx-x86-1.34.zip\
1585 download/fossil-macosx-x86-1.35.zip download/fossil-openbsd-x86-1.32.zip\
1586 download/fossil-openbsd-x86-1.33.zip download/fossil-openbsd-x86-1.34.tar.gz\
1587 download/fossil-openbsd-x86-1.35.tar.gz download/fossil-src-1.32.tar.gz\
1588 download/fossil-src-1.33.tar.gz download/fossil-src-1.34.tar.gz\
1589 download/fossil-src-1.35.tar.gz download/fossil-w32-1.32.zip\
1590 download/fossil-w32-1.33.zip download/fossil-w32-1.34.zip\
1591 download/fossil-w32-1.35.zip download/releasenotes-1.32.html\
1592 download/releasenotes-1.33.html download/releasenotes-1.34.html\
1593 download/releasenotes-1.35.html index.wiki}}
1594
1595 ###############################################################################
1596
1597 run_in_checkout {
1598 fossil test-th-eval --open-config \
1599 {string length [unversioned content build-icons/src.gif]}
1600 }
1601
1602 test th1-unversioned-2 {$RESULT eq {4592}}
1603
1604 ###############################################################################
1605
1606 test_cleanup
1607
+10 -10
--- www/aboutcgi.wiki
+++ www/aboutcgi.wiki
@@ -66,11 +66,11 @@
6666
<p>
6767
In addition to setting various CGI environment variables, if the HTTP
6868
request contains POST content, then the web server relays the POST content
6969
to standard input of the CGI script.
7070
<p>
71
-In summary, the task of the
71
+In summary, the task of the
7272
CGI script is to read the various CGI environment variables and
7373
the POST content on standard input (if any), figure out an appropriate
7474
reply, then write that reply on standard output.
7575
The web server will read the output from the CGI script, reformat it
7676
into an appropriate HTTP reply, and relay the result back to the
@@ -89,31 +89,31 @@
8989
like the following:
9090
<blockquote><pre>
9191
#!/usr/bin/fossil
9292
repository: /home/www/repos/project.fossil
9393
</pre></blockquote>
94
-The first line of the script is a
94
+The first line of the script is a
9595
"[https://en.wikipedia.org/wiki/Shebang_%28Unix%29|shebang]"
9696
that tells the operating system what program to use as the interpreter
9797
for this script. On unix, when you execute a script that starts with
9898
a shebang, the operating system runs the program identified by the
99
-shebang with a single argument that is the full pathname of the script
99
+shebang with a single argument that is the full pathname of the script
100100
itself.
101101
In our example, the interpreter is Fossil, and the argument might
102102
be something like "/var/www/cgi-bin/one/two" (depending on how your
103103
particular web server is configured).
104104
<p>
105105
The Fossil program that is run as the script interpreter
106106
is the same Fossil that runs when
107107
you type ordinary Fossil commands like "fossil sync" or "fossil commit".
108108
But in this case, as soon as it launches, the Fossil program
109
-recognizes that the GATEWAY_INTERFACE environment variable is
109
+recognizes that the GATEWAY_INTERFACE environment variable is
110110
set to "CGI/1.0" and it therefore knows that it is being used as
111111
CGI rather than as an ordinary command-line tool, and behaves accordingly.
112112
<p>
113113
When Fossil recognizes that it is being run as CGI, it opens and reads
114
-the file identified by its sole argument (the file named by
114
+the file identified by its sole argument (the file named by
115115
<code>argv&#91;1&#93;</code>). In our example, the second line of that file
116116
tells Fossil the location of the repository it will be serving.
117117
Fossil then starts looking at the CGI environment variables to figure
118118
out what web page is being requested, generates that one web page,
119119
then exits.
@@ -130,11 +130,11 @@
130130
<ol type='A'>
131131
<li> [https://www.fossil-scm.org/fossil/info/c14ecc43]
132132
<li> [https://www.fossil-scm.org/fossil/info?name=c14ecc43]
133133
</ol>
134134
In both cases, the CGI script is called "/fossil". For case (A),
135
-the PATH_INFO variable will be "info/c14ecc43" and so the
135
+the PATH_INFO variable will be "info/c14ecc43" and so the
136136
"[/help?cmd=/info|/info]" webpage will be generated and the suffix of
137137
PATH_INFO will be converted into the "name" query parameter, which
138138
identifies the artifact about which information is requested.
139139
In case (B), the PATH_INFO is just "info", but the same "name"
140140
query parameter is set explicitly by the URL itself.
@@ -164,11 +164,11 @@
164164
<blockquote>
165165
<b>http://example.com/cgis/example2/subdir/three/timeline</b>
166166
</blockquote>
167167
Here is what happens:
168168
<ol>
169
-<li> The input URI on the HTTP request is
169
+<li> The input URI on the HTTP request is
170170
<b>/cgis/example2/subdir/three/timeline</b>
171171
<li> The web server searches prefixes of the input URI until it finds
172172
the "cgis/example2" script. The web server then sets
173173
PATH_INFO to the "subdir/three/timeline" suffix and invokes the
174174
"cgis/example2" script.
@@ -175,11 +175,11 @@
175175
<li> Fossil runs and sees the "directory:" line pointing to
176176
"/home/www/repos". Fossil then starts pulling terms off the
177177
front of the PATH_INFO looking for a repository. It first looks
178178
at "/home/www/resps/subdir.fossil" but there is no such repository.
179179
So then it looks at "/home/www/repos/subdir/three.fossil" and finds
180
- a repository. The PATH_INFO is shortened by removing
180
+ a repository. The PATH_INFO is shortened by removing
181181
"subdir/three/" leaving it at just "timeline".
182182
<li> Fossil looks at the rest of PATH_INFO to see that the webpage
183183
requested is "timeline".
184184
</ol>
185185
</blockquote>
@@ -201,14 +201,14 @@
201201
and has a value.
202202
<li><p>
203203
The "[/help?cmd=ui|fossil ui]" and "[/help?cmd=server|fossil server]" commands
204204
are implemented using a simple built-in web server that accepts incoming HTTP
205205
requests, translates each request into a CGI invocation, then creates a
206
-separate child Fossil process to handle each request. In other words, CGI
206
+separate child Fossil process to handle each request. In other words, CGI
207207
is used internally to implement "fossil ui/server".
208208
<p>
209209
SCGI is processed using the same built-in web server, just modified
210210
to parse SCGI requests instead of HTTP requests. Each SCGI request is
211
-converted into CGI, then Fossil creates a separate child Fossil
211
+converted into CGI, then Fossil creates a separate child Fossil
212212
process to handle each CGI request.
213213
</ol>
214214
</blockquote>
215215
--- www/aboutcgi.wiki
+++ www/aboutcgi.wiki
@@ -66,11 +66,11 @@
66 <p>
67 In addition to setting various CGI environment variables, if the HTTP
68 request contains POST content, then the web server relays the POST content
69 to standard input of the CGI script.
70 <p>
71 In summary, the task of the
72 CGI script is to read the various CGI environment variables and
73 the POST content on standard input (if any), figure out an appropriate
74 reply, then write that reply on standard output.
75 The web server will read the output from the CGI script, reformat it
76 into an appropriate HTTP reply, and relay the result back to the
@@ -89,31 +89,31 @@
89 like the following:
90 <blockquote><pre>
91 #!/usr/bin/fossil
92 repository: /home/www/repos/project.fossil
93 </pre></blockquote>
94 The first line of the script is a
95 "[https://en.wikipedia.org/wiki/Shebang_%28Unix%29|shebang]"
96 that tells the operating system what program to use as the interpreter
97 for this script. On unix, when you execute a script that starts with
98 a shebang, the operating system runs the program identified by the
99 shebang with a single argument that is the full pathname of the script
100 itself.
101 In our example, the interpreter is Fossil, and the argument might
102 be something like "/var/www/cgi-bin/one/two" (depending on how your
103 particular web server is configured).
104 <p>
105 The Fossil program that is run as the script interpreter
106 is the same Fossil that runs when
107 you type ordinary Fossil commands like "fossil sync" or "fossil commit".
108 But in this case, as soon as it launches, the Fossil program
109 recognizes that the GATEWAY_INTERFACE environment variable is
110 set to "CGI/1.0" and it therefore knows that it is being used as
111 CGI rather than as an ordinary command-line tool, and behaves accordingly.
112 <p>
113 When Fossil recognizes that it is being run as CGI, it opens and reads
114 the file identified by its sole argument (the file named by
115 <code>argv&#91;1&#93;</code>). In our example, the second line of that file
116 tells Fossil the location of the repository it will be serving.
117 Fossil then starts looking at the CGI environment variables to figure
118 out what web page is being requested, generates that one web page,
119 then exits.
@@ -130,11 +130,11 @@
130 <ol type='A'>
131 <li> [https://www.fossil-scm.org/fossil/info/c14ecc43]
132 <li> [https://www.fossil-scm.org/fossil/info?name=c14ecc43]
133 </ol>
134 In both cases, the CGI script is called "/fossil". For case (A),
135 the PATH_INFO variable will be "info/c14ecc43" and so the
136 "[/help?cmd=/info|/info]" webpage will be generated and the suffix of
137 PATH_INFO will be converted into the "name" query parameter, which
138 identifies the artifact about which information is requested.
139 In case (B), the PATH_INFO is just "info", but the same "name"
140 query parameter is set explicitly by the URL itself.
@@ -164,11 +164,11 @@
164 <blockquote>
165 <b>http://example.com/cgis/example2/subdir/three/timeline</b>
166 </blockquote>
167 Here is what happens:
168 <ol>
169 <li> The input URI on the HTTP request is
170 <b>/cgis/example2/subdir/three/timeline</b>
171 <li> The web server searches prefixes of the input URI until it finds
172 the "cgis/example2" script. The web server then sets
173 PATH_INFO to the "subdir/three/timeline" suffix and invokes the
174 "cgis/example2" script.
@@ -175,11 +175,11 @@
175 <li> Fossil runs and sees the "directory:" line pointing to
176 "/home/www/repos". Fossil then starts pulling terms off the
177 front of the PATH_INFO looking for a repository. It first looks
178 at "/home/www/resps/subdir.fossil" but there is no such repository.
179 So then it looks at "/home/www/repos/subdir/three.fossil" and finds
180 a repository. The PATH_INFO is shortened by removing
181 "subdir/three/" leaving it at just "timeline".
182 <li> Fossil looks at the rest of PATH_INFO to see that the webpage
183 requested is "timeline".
184 </ol>
185 </blockquote>
@@ -201,14 +201,14 @@
201 and has a value.
202 <li><p>
203 The "[/help?cmd=ui|fossil ui]" and "[/help?cmd=server|fossil server]" commands
204 are implemented using a simple built-in web server that accepts incoming HTTP
205 requests, translates each request into a CGI invocation, then creates a
206 separate child Fossil process to handle each request. In other words, CGI
207 is used internally to implement "fossil ui/server".
208 <p>
209 SCGI is processed using the same built-in web server, just modified
210 to parse SCGI requests instead of HTTP requests. Each SCGI request is
211 converted into CGI, then Fossil creates a separate child Fossil
212 process to handle each CGI request.
213 </ol>
214 </blockquote>
215
--- www/aboutcgi.wiki
+++ www/aboutcgi.wiki
@@ -66,11 +66,11 @@
66 <p>
67 In addition to setting various CGI environment variables, if the HTTP
68 request contains POST content, then the web server relays the POST content
69 to standard input of the CGI script.
70 <p>
71 In summary, the task of the
72 CGI script is to read the various CGI environment variables and
73 the POST content on standard input (if any), figure out an appropriate
74 reply, then write that reply on standard output.
75 The web server will read the output from the CGI script, reformat it
76 into an appropriate HTTP reply, and relay the result back to the
@@ -89,31 +89,31 @@
89 like the following:
90 <blockquote><pre>
91 #!/usr/bin/fossil
92 repository: /home/www/repos/project.fossil
93 </pre></blockquote>
94 The first line of the script is a
95 "[https://en.wikipedia.org/wiki/Shebang_%28Unix%29|shebang]"
96 that tells the operating system what program to use as the interpreter
97 for this script. On unix, when you execute a script that starts with
98 a shebang, the operating system runs the program identified by the
99 shebang with a single argument that is the full pathname of the script
100 itself.
101 In our example, the interpreter is Fossil, and the argument might
102 be something like "/var/www/cgi-bin/one/two" (depending on how your
103 particular web server is configured).
104 <p>
105 The Fossil program that is run as the script interpreter
106 is the same Fossil that runs when
107 you type ordinary Fossil commands like "fossil sync" or "fossil commit".
108 But in this case, as soon as it launches, the Fossil program
109 recognizes that the GATEWAY_INTERFACE environment variable is
110 set to "CGI/1.0" and it therefore knows that it is being used as
111 CGI rather than as an ordinary command-line tool, and behaves accordingly.
112 <p>
113 When Fossil recognizes that it is being run as CGI, it opens and reads
114 the file identified by its sole argument (the file named by
115 <code>argv&#91;1&#93;</code>). In our example, the second line of that file
116 tells Fossil the location of the repository it will be serving.
117 Fossil then starts looking at the CGI environment variables to figure
118 out what web page is being requested, generates that one web page,
119 then exits.
@@ -130,11 +130,11 @@
130 <ol type='A'>
131 <li> [https://www.fossil-scm.org/fossil/info/c14ecc43]
132 <li> [https://www.fossil-scm.org/fossil/info?name=c14ecc43]
133 </ol>
134 In both cases, the CGI script is called "/fossil". For case (A),
135 the PATH_INFO variable will be "info/c14ecc43" and so the
136 "[/help?cmd=/info|/info]" webpage will be generated and the suffix of
137 PATH_INFO will be converted into the "name" query parameter, which
138 identifies the artifact about which information is requested.
139 In case (B), the PATH_INFO is just "info", but the same "name"
140 query parameter is set explicitly by the URL itself.
@@ -164,11 +164,11 @@
164 <blockquote>
165 <b>http://example.com/cgis/example2/subdir/three/timeline</b>
166 </blockquote>
167 Here is what happens:
168 <ol>
169 <li> The input URI on the HTTP request is
170 <b>/cgis/example2/subdir/three/timeline</b>
171 <li> The web server searches prefixes of the input URI until it finds
172 the "cgis/example2" script. The web server then sets
173 PATH_INFO to the "subdir/three/timeline" suffix and invokes the
174 "cgis/example2" script.
@@ -175,11 +175,11 @@
175 <li> Fossil runs and sees the "directory:" line pointing to
176 "/home/www/repos". Fossil then starts pulling terms off the
177 front of the PATH_INFO looking for a repository. It first looks
178 at "/home/www/resps/subdir.fossil" but there is no such repository.
179 So then it looks at "/home/www/repos/subdir/three.fossil" and finds
180 a repository. The PATH_INFO is shortened by removing
181 "subdir/three/" leaving it at just "timeline".
182 <li> Fossil looks at the rest of PATH_INFO to see that the webpage
183 requested is "timeline".
184 </ol>
185 </blockquote>
@@ -201,14 +201,14 @@
201 and has a value.
202 <li><p>
203 The "[/help?cmd=ui|fossil ui]" and "[/help?cmd=server|fossil server]" commands
204 are implemented using a simple built-in web server that accepts incoming HTTP
205 requests, translates each request into a CGI invocation, then creates a
206 separate child Fossil process to handle each request. In other words, CGI
207 is used internally to implement "fossil ui/server".
208 <p>
209 SCGI is processed using the same built-in web server, just modified
210 to parse SCGI requests instead of HTTP requests. Each SCGI request is
211 converted into CGI, then Fossil creates a separate child Fossil
212 process to handle each CGI request.
213 </ol>
214 </blockquote>
215
--- www/adding_code.wiki
+++ www/adding_code.wiki
@@ -22,11 +22,11 @@
2222
2323
2. The <b>makeheaders</b> preprocessor generates all the ".h" files
2424
automatically. Fossil programmers write ".c" files only and let the
2525
makeheaders preprocessor create the ".h" files.
2626
27
- 3. The <b>translate</b> preprocessor converts source code lines that
27
+ 3. The <b>translate</b> preprocessor converts source code lines that
2828
begin with "@" into string literals, or into print statements that
2929
generate web page output, depending on context.
3030
3131
The [./makefile.wiki|Makefile] for Fossil takes care of running these
3232
preprocessors with all the right arguments and in the right order. So it is
@@ -39,13 +39,13 @@
3939
<h2>3.0 Adding New Source Code Files</h2>
4040
4141
New source code files are added in the "src/" subdirectory of the Fossil
4242
source tree. Suppose one wants to add a new source code file named
4343
"xyzzy.c". The first step is to add this file to the various makefiles.
44
-Do so by editing the file src/makemake.tcl and adding "xyzzy" (without
44
+Do so by editing the file src/makemake.tcl and adding "xyzzy" (without
4545
the final ".c") to the list of source modules at the top of that script.
46
-Save the result and then run the makemake.tcl script using a TCL
46
+Save the result and then run the makemake.tcl script using a TCL
4747
interpreter. The command to run the makemake.tcl script is:
4848
4949
<b>tclsh makemake.tcl</b>
5050
5151
The working directory must be src/ when the command above is run.
@@ -60,11 +60,11 @@
6060
6161
<blockquote><verbatim>
6262
/*
6363
** Copyright boilerplate goes here.
6464
*****************************************************
65
-** High-level description of what this module goes
65
+** High-level description of what this module goes
6666
** here.
6767
*/
6868
#include "config.h"
6969
#include "xyzzy.h"
7070
@@ -83,11 +83,11 @@
8383
exceptions to this rule. Don't worry about those exceptions. The
8484
files you write will require this #include line.)
8585
8686
The "#if INTERFACE ... #endif" section is optional and is only needed
8787
if there are structure definitions or typedefs or macros that need to
88
-be used by other source code files. The makeheaders preprocessor
88
+be used by other source code files. The makeheaders preprocessor
8989
uses definitions in the INTERFACE section to help it generate header
9090
files. See [../src/makeheaders.html | makeheaders.html] for additional
9191
information.
9292
9393
After creating a template file such as shown above, and after updating
9494
--- www/adding_code.wiki
+++ www/adding_code.wiki
@@ -22,11 +22,11 @@
22
23 2. The <b>makeheaders</b> preprocessor generates all the ".h" files
24 automatically. Fossil programmers write ".c" files only and let the
25 makeheaders preprocessor create the ".h" files.
26
27 3. The <b>translate</b> preprocessor converts source code lines that
28 begin with "@" into string literals, or into print statements that
29 generate web page output, depending on context.
30
31 The [./makefile.wiki|Makefile] for Fossil takes care of running these
32 preprocessors with all the right arguments and in the right order. So it is
@@ -39,13 +39,13 @@
39 <h2>3.0 Adding New Source Code Files</h2>
40
41 New source code files are added in the "src/" subdirectory of the Fossil
42 source tree. Suppose one wants to add a new source code file named
43 "xyzzy.c". The first step is to add this file to the various makefiles.
44 Do so by editing the file src/makemake.tcl and adding "xyzzy" (without
45 the final ".c") to the list of source modules at the top of that script.
46 Save the result and then run the makemake.tcl script using a TCL
47 interpreter. The command to run the makemake.tcl script is:
48
49 <b>tclsh makemake.tcl</b>
50
51 The working directory must be src/ when the command above is run.
@@ -60,11 +60,11 @@
60
61 <blockquote><verbatim>
62 /*
63 ** Copyright boilerplate goes here.
64 *****************************************************
65 ** High-level description of what this module goes
66 ** here.
67 */
68 #include "config.h"
69 #include "xyzzy.h"
70
@@ -83,11 +83,11 @@
83 exceptions to this rule. Don't worry about those exceptions. The
84 files you write will require this #include line.)
85
86 The "#if INTERFACE ... #endif" section is optional and is only needed
87 if there are structure definitions or typedefs or macros that need to
88 be used by other source code files. The makeheaders preprocessor
89 uses definitions in the INTERFACE section to help it generate header
90 files. See [../src/makeheaders.html | makeheaders.html] for additional
91 information.
92
93 After creating a template file such as shown above, and after updating
94
--- www/adding_code.wiki
+++ www/adding_code.wiki
@@ -22,11 +22,11 @@
22
23 2. The <b>makeheaders</b> preprocessor generates all the ".h" files
24 automatically. Fossil programmers write ".c" files only and let the
25 makeheaders preprocessor create the ".h" files.
26
27 3. The <b>translate</b> preprocessor converts source code lines that
28 begin with "@" into string literals, or into print statements that
29 generate web page output, depending on context.
30
31 The [./makefile.wiki|Makefile] for Fossil takes care of running these
32 preprocessors with all the right arguments and in the right order. So it is
@@ -39,13 +39,13 @@
39 <h2>3.0 Adding New Source Code Files</h2>
40
41 New source code files are added in the "src/" subdirectory of the Fossil
42 source tree. Suppose one wants to add a new source code file named
43 "xyzzy.c". The first step is to add this file to the various makefiles.
44 Do so by editing the file src/makemake.tcl and adding "xyzzy" (without
45 the final ".c") to the list of source modules at the top of that script.
46 Save the result and then run the makemake.tcl script using a TCL
47 interpreter. The command to run the makemake.tcl script is:
48
49 <b>tclsh makemake.tcl</b>
50
51 The working directory must be src/ when the command above is run.
@@ -60,11 +60,11 @@
60
61 <blockquote><verbatim>
62 /*
63 ** Copyright boilerplate goes here.
64 *****************************************************
65 ** High-level description of what this module goes
66 ** here.
67 */
68 #include "config.h"
69 #include "xyzzy.h"
70
@@ -83,11 +83,11 @@
83 exceptions to this rule. Don't worry about those exceptions. The
84 files you write will require this #include line.)
85
86 The "#if INTERFACE ... #endif" section is optional and is only needed
87 if there are structure definitions or typedefs or macros that need to
88 be used by other source code files. The makeheaders preprocessor
89 uses definitions in the INTERFACE section to help it generate header
90 files. See [../src/makeheaders.html | makeheaders.html] for additional
91 information.
92
93 After creating a template file such as shown above, and after updating
94
+11 -11
--- www/antibot.wiki
+++ www/antibot.wiki
@@ -1,27 +1,27 @@
11
<title>Defense Against Spiders</title>
22
33
The website presented by a Fossil server has many hyperlinks.
44
Even a modest project can have millions of pages in its
5
-tree, and many of those pages (for example diffs and annotations
5
+tree, and many of those pages (for example diffs and annotations
66
and ZIP archive of older check-ins) can be expensive to compute.
77
If a spider or bot tries to walk a website implemented by
88
Fossil, it can present a crippling bandwidth and CPU load.
99
1010
The website presented by a Fossil server is intended to be used
11
-interactively by humans, not walked by spiders. This article
11
+interactively by humans, not walked by spiders. This article
1212
describes the techniques used by Fossil to try to welcome human
1313
users while keeping out spiders.
1414
1515
<h2>The "hyperlink" user capability</h2>
1616
1717
Every Fossil web session has a "user". For random passers-by on the internet
1818
(and for spiders) that user is "nobody". The "anonymous" user is also
1919
available for humans who do not wish to identify themselves. The difference
2020
is that "anonymous" requires a login (using a password supplied via
21
-a CAPTCHA) whereas "nobody" does not require a login.
22
-The site administrator can also create logins with
21
+a CAPTCHA) whereas "nobody" does not require a login.
22
+The site administrator can also create logins with
2323
passwords for specific individuals.
2424
2525
The "h" or "hyperlink" capability is a permission that can be granted
2626
to users that enables the display of hyperlinks. Most of the hyperlinks
2727
generated by Fossil are suppressed if this capability is missing. So
@@ -37,11 +37,11 @@
3737
page inviting the user to log in as anonymous in order to activate hyperlinks.
3838
3939
Removing the "h" capability from user "nobody" is an effective means
4040
of preventing spiders from walking a Fossil-generated website. But
4141
it can also be annoying to humans, since it requires them to log in.
42
-Hence, Fossil provides other techniques for blocking spiders which
42
+Hence, Fossil provides other techniques for blocking spiders which
4343
are less cumbersome to humans.
4444
4545
<h2>Automatic hyperlinks based on UserAgent</h2>
4646
4747
Fossil has the ability to selectively enable hyperlinks for users
@@ -94,25 +94,25 @@
9494
web browsers implement javascript, so hyperlinks will appears
9595
normally for human users.
9696
9797
<h2>Further defenses</h2>
9898
99
-Recently (as of this writing, in the spring of 2013) the Fossil server
99
+Recently (as of this writing, in the spring of 2013) the Fossil server
100100
on the SQLite website ([http://www.sqlite.org/src/]) has been hit repeatedly
101
-by Chinese spiders that use forged UserAgent strings to make them look
101
+by Chinese spiders that use forged UserAgent strings to make them look
102102
like normal web browsers and which interpret javascript. We do not
103103
believe these attacks to be nefarious since SQLite is public domain
104104
and the attackers could obtain all information they ever wanted to
105
-know about SQLite simply by cloning the repository. Instead, we
105
+know about SQLite simply by cloning the repository. Instead, we
106106
believe these "attacks" are coming from "script kiddies". But regardless
107107
of whether or not malice is involved, these attacks do present
108108
an unnecessary load on the server which reduces the responsiveness of
109109
the SQLite website for well-behaved and socially responsible users.
110110
For this reason, additional defenses against
111111
spiders have been put in place.
112112
113
-On the Admin/Access page of Fossil, just below the
113
+On the Admin/Access page of Fossil, just below the
114114
"<b>Enable hyperlinks for "nobody" based on User-Agent and Javascript</b>"
115115
setting, there are now two additional subsettings that can be optionally
116116
enabled to control hyperlinks.
117117
118118
The first subsetting waits to run the
@@ -137,11 +137,11 @@
137137
Fossil currently does a very good job of providing easy access to humans
138138
while keeping out troublesome robots and spiders. However, spiders and
139139
bots continue to grow more sophisticated, requiring ever more advanced
140140
defenses. This "arms race" is unlikely to ever end. The developers of
141141
Fossil will continue to try improve the spider defenses of Fossil so
142
-check back from time to time for the latest releases and updates.
142
+check back from time to time for the latest releases and updates.
143143
144144
Readers of this page who have suggestions on how to improve the spider
145145
defenses in Fossil are invited to submit your ideas to the Fossil Users
146
-mailing list:
146
+mailing list:
147147
[mailto:[email protected] | [email protected]].
148148
--- www/antibot.wiki
+++ www/antibot.wiki
@@ -1,27 +1,27 @@
1 <title>Defense Against Spiders</title>
2
3 The website presented by a Fossil server has many hyperlinks.
4 Even a modest project can have millions of pages in its
5 tree, and many of those pages (for example diffs and annotations
6 and ZIP archive of older check-ins) can be expensive to compute.
7 If a spider or bot tries to walk a website implemented by
8 Fossil, it can present a crippling bandwidth and CPU load.
9
10 The website presented by a Fossil server is intended to be used
11 interactively by humans, not walked by spiders. This article
12 describes the techniques used by Fossil to try to welcome human
13 users while keeping out spiders.
14
15 <h2>The "hyperlink" user capability</h2>
16
17 Every Fossil web session has a "user". For random passers-by on the internet
18 (and for spiders) that user is "nobody". The "anonymous" user is also
19 available for humans who do not wish to identify themselves. The difference
20 is that "anonymous" requires a login (using a password supplied via
21 a CAPTCHA) whereas "nobody" does not require a login.
22 The site administrator can also create logins with
23 passwords for specific individuals.
24
25 The "h" or "hyperlink" capability is a permission that can be granted
26 to users that enables the display of hyperlinks. Most of the hyperlinks
27 generated by Fossil are suppressed if this capability is missing. So
@@ -37,11 +37,11 @@
37 page inviting the user to log in as anonymous in order to activate hyperlinks.
38
39 Removing the "h" capability from user "nobody" is an effective means
40 of preventing spiders from walking a Fossil-generated website. But
41 it can also be annoying to humans, since it requires them to log in.
42 Hence, Fossil provides other techniques for blocking spiders which
43 are less cumbersome to humans.
44
45 <h2>Automatic hyperlinks based on UserAgent</h2>
46
47 Fossil has the ability to selectively enable hyperlinks for users
@@ -94,25 +94,25 @@
94 web browsers implement javascript, so hyperlinks will appears
95 normally for human users.
96
97 <h2>Further defenses</h2>
98
99 Recently (as of this writing, in the spring of 2013) the Fossil server
100 on the SQLite website ([http://www.sqlite.org/src/]) has been hit repeatedly
101 by Chinese spiders that use forged UserAgent strings to make them look
102 like normal web browsers and which interpret javascript. We do not
103 believe these attacks to be nefarious since SQLite is public domain
104 and the attackers could obtain all information they ever wanted to
105 know about SQLite simply by cloning the repository. Instead, we
106 believe these "attacks" are coming from "script kiddies". But regardless
107 of whether or not malice is involved, these attacks do present
108 an unnecessary load on the server which reduces the responsiveness of
109 the SQLite website for well-behaved and socially responsible users.
110 For this reason, additional defenses against
111 spiders have been put in place.
112
113 On the Admin/Access page of Fossil, just below the
114 "<b>Enable hyperlinks for "nobody" based on User-Agent and Javascript</b>"
115 setting, there are now two additional subsettings that can be optionally
116 enabled to control hyperlinks.
117
118 The first subsetting waits to run the
@@ -137,11 +137,11 @@
137 Fossil currently does a very good job of providing easy access to humans
138 while keeping out troublesome robots and spiders. However, spiders and
139 bots continue to grow more sophisticated, requiring ever more advanced
140 defenses. This "arms race" is unlikely to ever end. The developers of
141 Fossil will continue to try improve the spider defenses of Fossil so
142 check back from time to time for the latest releases and updates.
143
144 Readers of this page who have suggestions on how to improve the spider
145 defenses in Fossil are invited to submit your ideas to the Fossil Users
146 mailing list:
147 [mailto:[email protected] | [email protected]].
148
--- www/antibot.wiki
+++ www/antibot.wiki
@@ -1,27 +1,27 @@
1 <title>Defense Against Spiders</title>
2
3 The website presented by a Fossil server has many hyperlinks.
4 Even a modest project can have millions of pages in its
5 tree, and many of those pages (for example diffs and annotations
6 and ZIP archive of older check-ins) can be expensive to compute.
7 If a spider or bot tries to walk a website implemented by
8 Fossil, it can present a crippling bandwidth and CPU load.
9
10 The website presented by a Fossil server is intended to be used
11 interactively by humans, not walked by spiders. This article
12 describes the techniques used by Fossil to try to welcome human
13 users while keeping out spiders.
14
15 <h2>The "hyperlink" user capability</h2>
16
17 Every Fossil web session has a "user". For random passers-by on the internet
18 (and for spiders) that user is "nobody". The "anonymous" user is also
19 available for humans who do not wish to identify themselves. The difference
20 is that "anonymous" requires a login (using a password supplied via
21 a CAPTCHA) whereas "nobody" does not require a login.
22 The site administrator can also create logins with
23 passwords for specific individuals.
24
25 The "h" or "hyperlink" capability is a permission that can be granted
26 to users that enables the display of hyperlinks. Most of the hyperlinks
27 generated by Fossil are suppressed if this capability is missing. So
@@ -37,11 +37,11 @@
37 page inviting the user to log in as anonymous in order to activate hyperlinks.
38
39 Removing the "h" capability from user "nobody" is an effective means
40 of preventing spiders from walking a Fossil-generated website. But
41 it can also be annoying to humans, since it requires them to log in.
42 Hence, Fossil provides other techniques for blocking spiders which
43 are less cumbersome to humans.
44
45 <h2>Automatic hyperlinks based on UserAgent</h2>
46
47 Fossil has the ability to selectively enable hyperlinks for users
@@ -94,25 +94,25 @@
94 web browsers implement javascript, so hyperlinks will appears
95 normally for human users.
96
97 <h2>Further defenses</h2>
98
99 Recently (as of this writing, in the spring of 2013) the Fossil server
100 on the SQLite website ([http://www.sqlite.org/src/]) has been hit repeatedly
101 by Chinese spiders that use forged UserAgent strings to make them look
102 like normal web browsers and which interpret javascript. We do not
103 believe these attacks to be nefarious since SQLite is public domain
104 and the attackers could obtain all information they ever wanted to
105 know about SQLite simply by cloning the repository. Instead, we
106 believe these "attacks" are coming from "script kiddies". But regardless
107 of whether or not malice is involved, these attacks do present
108 an unnecessary load on the server which reduces the responsiveness of
109 the SQLite website for well-behaved and socially responsible users.
110 For this reason, additional defenses against
111 spiders have been put in place.
112
113 On the Admin/Access page of Fossil, just below the
114 "<b>Enable hyperlinks for "nobody" based on User-Agent and Javascript</b>"
115 setting, there are now two additional subsettings that can be optionally
116 enabled to control hyperlinks.
117
118 The first subsetting waits to run the
@@ -137,11 +137,11 @@
137 Fossil currently does a very good job of providing easy access to humans
138 while keeping out troublesome robots and spiders. However, spiders and
139 bots continue to grow more sophisticated, requiring ever more advanced
140 defenses. This "arms race" is unlikely to ever end. The developers of
141 Fossil will continue to try improve the spider defenses of Fossil so
142 check back from time to time for the latest releases and updates.
143
144 Readers of this page who have suggestions on how to improve the spider
145 defenses in Fossil are invited to submit your ideas to the Fossil Users
146 mailing list:
147 [mailto:[email protected] | [email protected]].
148
+4 -4
--- www/blame.wiki
+++ www/blame.wiki
@@ -18,16 +18,16 @@
1818
<li>Locate the check-in that contains the file that is to be
1919
annotated. Call this check-in C0.
2020
<li>Find all direct ancestors of C0. A direct ancestor is the closure
2121
of the primary parent of C0. Merged in branches are not part of
2222
the direct ancestors of C0.
23
-<li>Prune the list of ancestors of C0 so that it contains only
23
+<li>Prune the list of ancestors of C0 so that it contains only
2424
check-in in which the file to be annotated was modified.
2525
<li>Load the complete text of the file to be annotated from check-in C0.
2626
Call this version of the file F0.
2727
<li>Parse F0 into lines. Mark each line as "unchanged".
28
-<li>For each ancestor of C0 on the pruned list (call the ancestor CX),
28
+<li>For each ancestor of C0 on the pruned list (call the ancestor CX),
2929
beginning with the most
3030
recent ancestor and moving toward the oldest ancestor, do the
3131
following steps:
3232
<ol type='a'>
3333
<li>Load the text for the file to be annotated as it existed in check-in CX.
@@ -44,19 +44,19 @@
4444
<h2>3.0 Discussion and Notes</h2>
4545
4646
The time-consuming part of this algorithm is step 6b - computing the
4747
diff from all historical versions of the file to the version of the file
4848
under analysis. For a large file that has many historical changes, this
49
-can take several seconds. For this reason, the default
49
+can take several seconds. For this reason, the default
5050
[/help?cmd=/annotate|/annotate] webpage only shows those lines that where
5151
changed by the 20 most recent modifications to the file. This allows
5252
the loop on step 6 to terminate after only 19 diffs instead of the hundreds
5353
or thousands of diffs that might be required for a frequently modified file.
5454
5555
As currently implemented (as of 2015-12-12) the annotate algorithm does not
56
-follow files across name changes. File name change information is
56
+follow files across name changes. File name change information is
5757
available in the database, and so the algorithm could be enhanced to follow
5858
files across name changes by modifications to step 3.
5959
6060
Step 2 is interesting in that it is
6161
[/artifact/6cb824a0417?ln=196-201 | implemented] using a
6262
[https://www.sqlite.org/lang_with.html#recursivecte|recursive common table expression].
6363
--- www/blame.wiki
+++ www/blame.wiki
@@ -18,16 +18,16 @@
18 <li>Locate the check-in that contains the file that is to be
19 annotated. Call this check-in C0.
20 <li>Find all direct ancestors of C0. A direct ancestor is the closure
21 of the primary parent of C0. Merged in branches are not part of
22 the direct ancestors of C0.
23 <li>Prune the list of ancestors of C0 so that it contains only
24 check-in in which the file to be annotated was modified.
25 <li>Load the complete text of the file to be annotated from check-in C0.
26 Call this version of the file F0.
27 <li>Parse F0 into lines. Mark each line as "unchanged".
28 <li>For each ancestor of C0 on the pruned list (call the ancestor CX),
29 beginning with the most
30 recent ancestor and moving toward the oldest ancestor, do the
31 following steps:
32 <ol type='a'>
33 <li>Load the text for the file to be annotated as it existed in check-in CX.
@@ -44,19 +44,19 @@
44 <h2>3.0 Discussion and Notes</h2>
45
46 The time-consuming part of this algorithm is step 6b - computing the
47 diff from all historical versions of the file to the version of the file
48 under analysis. For a large file that has many historical changes, this
49 can take several seconds. For this reason, the default
50 [/help?cmd=/annotate|/annotate] webpage only shows those lines that where
51 changed by the 20 most recent modifications to the file. This allows
52 the loop on step 6 to terminate after only 19 diffs instead of the hundreds
53 or thousands of diffs that might be required for a frequently modified file.
54
55 As currently implemented (as of 2015-12-12) the annotate algorithm does not
56 follow files across name changes. File name change information is
57 available in the database, and so the algorithm could be enhanced to follow
58 files across name changes by modifications to step 3.
59
60 Step 2 is interesting in that it is
61 [/artifact/6cb824a0417?ln=196-201 | implemented] using a
62 [https://www.sqlite.org/lang_with.html#recursivecte|recursive common table expression].
63
--- www/blame.wiki
+++ www/blame.wiki
@@ -18,16 +18,16 @@
18 <li>Locate the check-in that contains the file that is to be
19 annotated. Call this check-in C0.
20 <li>Find all direct ancestors of C0. A direct ancestor is the closure
21 of the primary parent of C0. Merged in branches are not part of
22 the direct ancestors of C0.
23 <li>Prune the list of ancestors of C0 so that it contains only
24 check-in in which the file to be annotated was modified.
25 <li>Load the complete text of the file to be annotated from check-in C0.
26 Call this version of the file F0.
27 <li>Parse F0 into lines. Mark each line as "unchanged".
28 <li>For each ancestor of C0 on the pruned list (call the ancestor CX),
29 beginning with the most
30 recent ancestor and moving toward the oldest ancestor, do the
31 following steps:
32 <ol type='a'>
33 <li>Load the text for the file to be annotated as it existed in check-in CX.
@@ -44,19 +44,19 @@
44 <h2>3.0 Discussion and Notes</h2>
45
46 The time-consuming part of this algorithm is step 6b - computing the
47 diff from all historical versions of the file to the version of the file
48 under analysis. For a large file that has many historical changes, this
49 can take several seconds. For this reason, the default
50 [/help?cmd=/annotate|/annotate] webpage only shows those lines that where
51 changed by the 20 most recent modifications to the file. This allows
52 the loop on step 6 to terminate after only 19 diffs instead of the hundreds
53 or thousands of diffs that might be required for a frequently modified file.
54
55 As currently implemented (as of 2015-12-12) the annotate algorithm does not
56 follow files across name changes. File name change information is
57 available in the database, and so the algorithm could be enhanced to follow
58 files across name changes by modifications to step 3.
59
60 Step 2 is interesting in that it is
61 [/artifact/6cb824a0417?ln=196-201 | implemented] using a
62 [https://www.sqlite.org/lang_with.html#recursivecte|recursive common table expression].
63
--- www/bugtheory.wiki
+++ www/bugtheory.wiki
@@ -27,11 +27,11 @@
2727
Recall that a fossil repository consists of an
2828
unordered collection of <i>artifacts</i>. (See the
2929
<a href="fileformat.wiki">file format document</a> for details.)
3030
Some artifacts have a special format, and among those are
3131
<a href="fileformat.wiki#tktchng">Ticket Change Artifacts</a>.
32
-One or more ticket change artifacts are associated with each
32
+One or more ticket change artifacts are associated with each
3333
ticket. A ticket is created by a ticket change artifact.
3434
Each subsequent modification of the ticket is a separate artifact.
3535
3636
The "push", "pull", and "sync" algorithms share ticket change artifacts
3737
between repositories in the same way as every other artifact. In fact,
3838
--- www/bugtheory.wiki
+++ www/bugtheory.wiki
@@ -27,11 +27,11 @@
27 Recall that a fossil repository consists of an
28 unordered collection of <i>artifacts</i>. (See the
29 <a href="fileformat.wiki">file format document</a> for details.)
30 Some artifacts have a special format, and among those are
31 <a href="fileformat.wiki#tktchng">Ticket Change Artifacts</a>.
32 One or more ticket change artifacts are associated with each
33 ticket. A ticket is created by a ticket change artifact.
34 Each subsequent modification of the ticket is a separate artifact.
35
36 The "push", "pull", and "sync" algorithms share ticket change artifacts
37 between repositories in the same way as every other artifact. In fact,
38
--- www/bugtheory.wiki
+++ www/bugtheory.wiki
@@ -27,11 +27,11 @@
27 Recall that a fossil repository consists of an
28 unordered collection of <i>artifacts</i>. (See the
29 <a href="fileformat.wiki">file format document</a> for details.)
30 Some artifacts have a special format, and among those are
31 <a href="fileformat.wiki#tktchng">Ticket Change Artifacts</a>.
32 One or more ticket change artifacts are associated with each
33 ticket. A ticket is created by a ticket change artifact.
34 Each subsequent modification of the ticket is a separate artifact.
35
36 The "push", "pull", and "sync" algorithms share ticket change artifacts
37 between repositories in the same way as every other artifact. In fact,
38
+15 -2
--- www/changes.wiki
+++ www/changes.wiki
@@ -4,10 +4,23 @@
44
<h2>Changes for Version 1.37 (2017-XX-YY)</h2>
55
66
* Added support for the ms=EXACT|LIKE|GLOB|REGEXP query parameter on the
77
[/help?cmd=/timeline|/timeline] webpage.
88
* Fix a C99-ism that prevents the 1.36 release from building with MSVC.
9
+ * Fix [/help?cmd=ticket|ticket set] when using the "+" prefix with fields
10
+ from the "ticketchng" table.
11
+ * Enhance the "brlist" page to make use of branch colors.
12
+ * Remove the "fusefs" command from builds that do not have the underlying
13
+ support enabled.
14
+ * Fixes for incremental git import/export.
15
+ * Minor security enhancements to
16
+ [./encryptedrepos.wiki|encrypted repositories].
17
+ * TH1 enhancements:
18
+ <ul><li>Add <nowiki>[unversioned content]</nowiki> command.</li>
19
+ <li>Add <nowiki>[unversioned list]</nowiki> command.</li>
20
+ <li>Add project_description variable.</li>
21
+ </ul>
922
1023
<a name='v1_36'></a>
1124
<h2>Changes for Version 1.36 (2016-10-24)</h2>
1225
1326
* Add support for [./unvers.wiki|unversioned content],
@@ -16,16 +29,16 @@
1629
* The [/uv/download.html|download page] is moved into
1730
[./unvers.wiki|unversioned content] so that the self-hosting Fossil
1831
websites no longer uses any external content.
1932
* Added the "Search" button to the graphical diff generated by
2033
the --tk option on the [/help?cmd=diff|diff] command.
21
- * Added the "--checkin VERSION" option to the
34
+ * Added the "--checkin VERSION" option to the
2235
[/help?cmd=diff|diff] command.
2336
* Various performance enhancements to the [/help?cmd=diff|diff] command.
2437
* Update internal Unicode character tables, used in regular expression
2538
handling, from version 8.0 to 9.0.
26
- * Update the built-in SQLite to version 3.15 (beta). Fossil now requires
39
+ * Update the built-in SQLite to version 3.15. Fossil now requires
2740
the SQLITE_DBCONFIG_MAINDBNAME interface of SQLite which is only available
2841
in SQLite version 3.15 and later and so Fossil will not work with
2942
earlier SQLite versions.
3043
* Fix [https://www.mail-archive.com/[email protected]/msg23618.html|multi-line timeline bug]
3144
* Enhance the [/help?cmd=purge|fossil purge] command.
3245
--- www/changes.wiki
+++ www/changes.wiki
@@ -4,10 +4,23 @@
4 <h2>Changes for Version 1.37 (2017-XX-YY)</h2>
5
6 * Added support for the ms=EXACT|LIKE|GLOB|REGEXP query parameter on the
7 [/help?cmd=/timeline|/timeline] webpage.
8 * Fix a C99-ism that prevents the 1.36 release from building with MSVC.
 
 
 
 
 
 
 
 
 
 
 
 
 
9
10 <a name='v1_36'></a>
11 <h2>Changes for Version 1.36 (2016-10-24)</h2>
12
13 * Add support for [./unvers.wiki|unversioned content],
@@ -16,16 +29,16 @@
16 * The [/uv/download.html|download page] is moved into
17 [./unvers.wiki|unversioned content] so that the self-hosting Fossil
18 websites no longer uses any external content.
19 * Added the "Search" button to the graphical diff generated by
20 the --tk option on the [/help?cmd=diff|diff] command.
21 * Added the "--checkin VERSION" option to the
22 [/help?cmd=diff|diff] command.
23 * Various performance enhancements to the [/help?cmd=diff|diff] command.
24 * Update internal Unicode character tables, used in regular expression
25 handling, from version 8.0 to 9.0.
26 * Update the built-in SQLite to version 3.15 (beta). Fossil now requires
27 the SQLITE_DBCONFIG_MAINDBNAME interface of SQLite which is only available
28 in SQLite version 3.15 and later and so Fossil will not work with
29 earlier SQLite versions.
30 * Fix [https://www.mail-archive.com/[email protected]/msg23618.html|multi-line timeline bug]
31 * Enhance the [/help?cmd=purge|fossil purge] command.
32
--- www/changes.wiki
+++ www/changes.wiki
@@ -4,10 +4,23 @@
4 <h2>Changes for Version 1.37 (2017-XX-YY)</h2>
5
6 * Added support for the ms=EXACT|LIKE|GLOB|REGEXP query parameter on the
7 [/help?cmd=/timeline|/timeline] webpage.
8 * Fix a C99-ism that prevents the 1.36 release from building with MSVC.
9 * Fix [/help?cmd=ticket|ticket set] when using the "+" prefix with fields
10 from the "ticketchng" table.
11 * Enhance the "brlist" page to make use of branch colors.
12 * Remove the "fusefs" command from builds that do not have the underlying
13 support enabled.
14 * Fixes for incremental git import/export.
15 * Minor security enhancements to
16 [./encryptedrepos.wiki|encrypted repositories].
17 * TH1 enhancements:
18 <ul><li>Add <nowiki>[unversioned content]</nowiki> command.</li>
19 <li>Add <nowiki>[unversioned list]</nowiki> command.</li>
20 <li>Add project_description variable.</li>
21 </ul>
22
23 <a name='v1_36'></a>
24 <h2>Changes for Version 1.36 (2016-10-24)</h2>
25
26 * Add support for [./unvers.wiki|unversioned content],
@@ -16,16 +29,16 @@
29 * The [/uv/download.html|download page] is moved into
30 [./unvers.wiki|unversioned content] so that the self-hosting Fossil
31 websites no longer uses any external content.
32 * Added the "Search" button to the graphical diff generated by
33 the --tk option on the [/help?cmd=diff|diff] command.
34 * Added the "--checkin VERSION" option to the
35 [/help?cmd=diff|diff] command.
36 * Various performance enhancements to the [/help?cmd=diff|diff] command.
37 * Update internal Unicode character tables, used in regular expression
38 handling, from version 8.0 to 9.0.
39 * Update the built-in SQLite to version 3.15. Fossil now requires
40 the SQLITE_DBCONFIG_MAINDBNAME interface of SQLite which is only available
41 in SQLite version 3.15 and later and so Fossil will not work with
42 earlier SQLite versions.
43 * Fix [https://www.mail-archive.com/[email protected]/msg23618.html|multi-line timeline bug]
44 * Enhance the [/help?cmd=purge|fossil purge] command.
45
+15 -2
--- www/changes.wiki
+++ www/changes.wiki
@@ -4,10 +4,23 @@
44
<h2>Changes for Version 1.37 (2017-XX-YY)</h2>
55
66
* Added support for the ms=EXACT|LIKE|GLOB|REGEXP query parameter on the
77
[/help?cmd=/timeline|/timeline] webpage.
88
* Fix a C99-ism that prevents the 1.36 release from building with MSVC.
9
+ * Fix [/help?cmd=ticket|ticket set] when using the "+" prefix with fields
10
+ from the "ticketchng" table.
11
+ * Enhance the "brlist" page to make use of branch colors.
12
+ * Remove the "fusefs" command from builds that do not have the underlying
13
+ support enabled.
14
+ * Fixes for incremental git import/export.
15
+ * Minor security enhancements to
16
+ [./encryptedrepos.wiki|encrypted repositories].
17
+ * TH1 enhancements:
18
+ <ul><li>Add <nowiki>[unversioned content]</nowiki> command.</li>
19
+ <li>Add <nowiki>[unversioned list]</nowiki> command.</li>
20
+ <li>Add project_description variable.</li>
21
+ </ul>
922
1023
<a name='v1_36'></a>
1124
<h2>Changes for Version 1.36 (2016-10-24)</h2>
1225
1326
* Add support for [./unvers.wiki|unversioned content],
@@ -16,16 +29,16 @@
1629
* The [/uv/download.html|download page] is moved into
1730
[./unvers.wiki|unversioned content] so that the self-hosting Fossil
1831
websites no longer uses any external content.
1932
* Added the "Search" button to the graphical diff generated by
2033
the --tk option on the [/help?cmd=diff|diff] command.
21
- * Added the "--checkin VERSION" option to the
34
+ * Added the "--checkin VERSION" option to the
2235
[/help?cmd=diff|diff] command.
2336
* Various performance enhancements to the [/help?cmd=diff|diff] command.
2437
* Update internal Unicode character tables, used in regular expression
2538
handling, from version 8.0 to 9.0.
26
- * Update the built-in SQLite to version 3.15 (beta). Fossil now requires
39
+ * Update the built-in SQLite to version 3.15. Fossil now requires
2740
the SQLITE_DBCONFIG_MAINDBNAME interface of SQLite which is only available
2841
in SQLite version 3.15 and later and so Fossil will not work with
2942
earlier SQLite versions.
3043
* Fix [https://www.mail-archive.com/[email protected]/msg23618.html|multi-line timeline bug]
3144
* Enhance the [/help?cmd=purge|fossil purge] command.
3245
--- www/changes.wiki
+++ www/changes.wiki
@@ -4,10 +4,23 @@
4 <h2>Changes for Version 1.37 (2017-XX-YY)</h2>
5
6 * Added support for the ms=EXACT|LIKE|GLOB|REGEXP query parameter on the
7 [/help?cmd=/timeline|/timeline] webpage.
8 * Fix a C99-ism that prevents the 1.36 release from building with MSVC.
 
 
 
 
 
 
 
 
 
 
 
 
 
9
10 <a name='v1_36'></a>
11 <h2>Changes for Version 1.36 (2016-10-24)</h2>
12
13 * Add support for [./unvers.wiki|unversioned content],
@@ -16,16 +29,16 @@
16 * The [/uv/download.html|download page] is moved into
17 [./unvers.wiki|unversioned content] so that the self-hosting Fossil
18 websites no longer uses any external content.
19 * Added the "Search" button to the graphical diff generated by
20 the --tk option on the [/help?cmd=diff|diff] command.
21 * Added the "--checkin VERSION" option to the
22 [/help?cmd=diff|diff] command.
23 * Various performance enhancements to the [/help?cmd=diff|diff] command.
24 * Update internal Unicode character tables, used in regular expression
25 handling, from version 8.0 to 9.0.
26 * Update the built-in SQLite to version 3.15 (beta). Fossil now requires
27 the SQLITE_DBCONFIG_MAINDBNAME interface of SQLite which is only available
28 in SQLite version 3.15 and later and so Fossil will not work with
29 earlier SQLite versions.
30 * Fix [https://www.mail-archive.com/[email protected]/msg23618.html|multi-line timeline bug]
31 * Enhance the [/help?cmd=purge|fossil purge] command.
32
--- www/changes.wiki
+++ www/changes.wiki
@@ -4,10 +4,23 @@
4 <h2>Changes for Version 1.37 (2017-XX-YY)</h2>
5
6 * Added support for the ms=EXACT|LIKE|GLOB|REGEXP query parameter on the
7 [/help?cmd=/timeline|/timeline] webpage.
8 * Fix a C99-ism that prevents the 1.36 release from building with MSVC.
9 * Fix [/help?cmd=ticket|ticket set] when using the "+" prefix with fields
10 from the "ticketchng" table.
11 * Enhance the "brlist" page to make use of branch colors.
12 * Remove the "fusefs" command from builds that do not have the underlying
13 support enabled.
14 * Fixes for incremental git import/export.
15 * Minor security enhancements to
16 [./encryptedrepos.wiki|encrypted repositories].
17 * TH1 enhancements:
18 <ul><li>Add <nowiki>[unversioned content]</nowiki> command.</li>
19 <li>Add <nowiki>[unversioned list]</nowiki> command.</li>
20 <li>Add project_description variable.</li>
21 </ul>
22
23 <a name='v1_36'></a>
24 <h2>Changes for Version 1.36 (2016-10-24)</h2>
25
26 * Add support for [./unvers.wiki|unversioned content],
@@ -16,16 +29,16 @@
29 * The [/uv/download.html|download page] is moved into
30 [./unvers.wiki|unversioned content] so that the self-hosting Fossil
31 websites no longer uses any external content.
32 * Added the "Search" button to the graphical diff generated by
33 the --tk option on the [/help?cmd=diff|diff] command.
34 * Added the "--checkin VERSION" option to the
35 [/help?cmd=diff|diff] command.
36 * Various performance enhancements to the [/help?cmd=diff|diff] command.
37 * Update internal Unicode character tables, used in regular expression
38 handling, from version 8.0 to 9.0.
39 * Update the built-in SQLite to version 3.15. Fossil now requires
40 the SQLITE_DBCONFIG_MAINDBNAME interface of SQLite which is only available
41 in SQLite version 3.15 and later and so Fossil will not work with
42 earlier SQLite versions.
43 * Fix [https://www.mail-archive.com/[email protected]/msg23618.html|multi-line timeline bug]
44 * Enhance the [/help?cmd=purge|fossil purge] command.
45
--- www/checkin_names.wiki
+++ www/checkin_names.wiki
@@ -55,20 +55,20 @@
5555
</pre></blockquote>
5656
5757
The full 40-character SHA1 hash is unwieldy to remember and type, though,
5858
so Fossil also accepts a unique prefix of the hash, using any combination
5959
of upper and lower case letters, as long as the prefix is at least 4
60
-characters long. Hence the following commands all
60
+characters long. Hence the following commands all
6161
accomplish the same thing as the above:
6262
6363
<blockquote><pre>
6464
fossil info e5a734a19a9
6565
fossil info E5a734A
6666
fossil info e5a7
6767
</blockquote>
6868
69
-Many web-interface screens identify check-ins by 10- or 16-character
69
+Many web-interface screens identify check-ins by 10- or 16-character
7070
prefix of canonical name.
7171
7272
<h2>Tags And Branch Names</h2>
7373
7474
Using a tag or branch name where a check-in name is expected causes
@@ -112,11 +112,11 @@
112112
113113
<blockquote><tt>
114114
fossil info tag:deed2
115115
</tt></blockquote>
116116
117
-The "tag:deed2" name will refer to the most recent check-in
117
+The "tag:deed2" name will refer to the most recent check-in
118118
tagged with "deed2" not to the
119119
check-in whose canonical name begins with "deed2".
120120
121121
<h2>Whole Branches</h2>
122122
@@ -147,11 +147,11 @@
147147
* <i>YYYY-MM-DD</i>
148148
* <i>YYYY-MM-DD HH:MM</i>
149149
* <i>YYYY-MM-DD HH:MM:SS</i>
150150
* <i>YYYY-MM-DD HH:MM:SS.SSS</i>
151151
152
-The space between the day and the year can optionally be
152
+The space between the day and the year can optionally be
153153
replaced by an uppercase <b>T</b> and the entire timestamp can
154154
optionally be followed by "<b>z</b>" or "<b>Z</b>". In the fourth
155155
form with fractional seconds, any number of digits may follow the
156156
decimal point, though due to precision limits only the first three
157157
digits will be significant.
@@ -161,14 +161,14 @@
161161
distributed projects where participants are scattered around the globe.
162162
But there is an option on the Admin/Timeline page of the web-interface to
163163
switch to local time. The "<b>Z</b>" suffix on a timestamp check-in
164164
name is meaningless if Fossil is in the default mode of using UTC for
165165
everything, but if Fossil has been switched to local time mode, then the
166
-"<b>Z</b>" suffix means to interpret that particular timestamp using
166
+"<b>Z</b>" suffix means to interpret that particular timestamp using
167167
UTC instead of local time.
168168
169
-For an example of how timestamps are useful,
169
+For an example of how timestamps are useful,
170170
consider the homepage for the Fossil website itself:
171171
172172
<blockquote>
173173
http://www.fossil-scm.org/fossil/doc/<b>trunk</b>/www/index.wiki
174174
</blockquote>
@@ -191,11 +191,11 @@
191191
<blockquote>
192192
fossil update trunk:2010-07-01T14:30
193193
</blockquote>
194194
195195
Would cause Fossil to update the working check-out to be the most recent
196
-check-in on the trunk that is not more recent that 14:30 (UTC) on
196
+check-in on the trunk that is not more recent that 14:30 (UTC) on
197197
July 1, 2010.
198198
199199
<h2>Root Of A Branch</h2>
200200
201201
A branch name that begins with the "<tt>root:</tt>" prefix refers to the
@@ -220,11 +220,11 @@
220220
current check-out. And the "previous" or "prev" tag means the primary
221221
(non-merge) parent of the current check-out.
222222
223223
For embedded documentation, the tag "ckout" means the version as present in
224224
the local source tree on disk, provided that the web server is started using
225
-"fossil ui" or "fossil server" from within the source tree. This tag can be
225
+"fossil ui" or "fossil server" from within the source tree. This tag can be
226226
used to preview local changes to documentation before committing them. It does
227227
not apply to CLI commands.
228228
229229
<h2>Additional Examples</h2>
230230
231231
--- www/checkin_names.wiki
+++ www/checkin_names.wiki
@@ -55,20 +55,20 @@
55 </pre></blockquote>
56
57 The full 40-character SHA1 hash is unwieldy to remember and type, though,
58 so Fossil also accepts a unique prefix of the hash, using any combination
59 of upper and lower case letters, as long as the prefix is at least 4
60 characters long. Hence the following commands all
61 accomplish the same thing as the above:
62
63 <blockquote><pre>
64 fossil info e5a734a19a9
65 fossil info E5a734A
66 fossil info e5a7
67 </blockquote>
68
69 Many web-interface screens identify check-ins by 10- or 16-character
70 prefix of canonical name.
71
72 <h2>Tags And Branch Names</h2>
73
74 Using a tag or branch name where a check-in name is expected causes
@@ -112,11 +112,11 @@
112
113 <blockquote><tt>
114 fossil info tag:deed2
115 </tt></blockquote>
116
117 The "tag:deed2" name will refer to the most recent check-in
118 tagged with "deed2" not to the
119 check-in whose canonical name begins with "deed2".
120
121 <h2>Whole Branches</h2>
122
@@ -147,11 +147,11 @@
147 * <i>YYYY-MM-DD</i>
148 * <i>YYYY-MM-DD HH:MM</i>
149 * <i>YYYY-MM-DD HH:MM:SS</i>
150 * <i>YYYY-MM-DD HH:MM:SS.SSS</i>
151
152 The space between the day and the year can optionally be
153 replaced by an uppercase <b>T</b> and the entire timestamp can
154 optionally be followed by "<b>z</b>" or "<b>Z</b>". In the fourth
155 form with fractional seconds, any number of digits may follow the
156 decimal point, though due to precision limits only the first three
157 digits will be significant.
@@ -161,14 +161,14 @@
161 distributed projects where participants are scattered around the globe.
162 But there is an option on the Admin/Timeline page of the web-interface to
163 switch to local time. The "<b>Z</b>" suffix on a timestamp check-in
164 name is meaningless if Fossil is in the default mode of using UTC for
165 everything, but if Fossil has been switched to local time mode, then the
166 "<b>Z</b>" suffix means to interpret that particular timestamp using
167 UTC instead of local time.
168
169 For an example of how timestamps are useful,
170 consider the homepage for the Fossil website itself:
171
172 <blockquote>
173 http://www.fossil-scm.org/fossil/doc/<b>trunk</b>/www/index.wiki
174 </blockquote>
@@ -191,11 +191,11 @@
191 <blockquote>
192 fossil update trunk:2010-07-01T14:30
193 </blockquote>
194
195 Would cause Fossil to update the working check-out to be the most recent
196 check-in on the trunk that is not more recent that 14:30 (UTC) on
197 July 1, 2010.
198
199 <h2>Root Of A Branch</h2>
200
201 A branch name that begins with the "<tt>root:</tt>" prefix refers to the
@@ -220,11 +220,11 @@
220 current check-out. And the "previous" or "prev" tag means the primary
221 (non-merge) parent of the current check-out.
222
223 For embedded documentation, the tag "ckout" means the version as present in
224 the local source tree on disk, provided that the web server is started using
225 "fossil ui" or "fossil server" from within the source tree. This tag can be
226 used to preview local changes to documentation before committing them. It does
227 not apply to CLI commands.
228
229 <h2>Additional Examples</h2>
230
231
--- www/checkin_names.wiki
+++ www/checkin_names.wiki
@@ -55,20 +55,20 @@
55 </pre></blockquote>
56
57 The full 40-character SHA1 hash is unwieldy to remember and type, though,
58 so Fossil also accepts a unique prefix of the hash, using any combination
59 of upper and lower case letters, as long as the prefix is at least 4
60 characters long. Hence the following commands all
61 accomplish the same thing as the above:
62
63 <blockquote><pre>
64 fossil info e5a734a19a9
65 fossil info E5a734A
66 fossil info e5a7
67 </blockquote>
68
69 Many web-interface screens identify check-ins by 10- or 16-character
70 prefix of canonical name.
71
72 <h2>Tags And Branch Names</h2>
73
74 Using a tag or branch name where a check-in name is expected causes
@@ -112,11 +112,11 @@
112
113 <blockquote><tt>
114 fossil info tag:deed2
115 </tt></blockquote>
116
117 The "tag:deed2" name will refer to the most recent check-in
118 tagged with "deed2" not to the
119 check-in whose canonical name begins with "deed2".
120
121 <h2>Whole Branches</h2>
122
@@ -147,11 +147,11 @@
147 * <i>YYYY-MM-DD</i>
148 * <i>YYYY-MM-DD HH:MM</i>
149 * <i>YYYY-MM-DD HH:MM:SS</i>
150 * <i>YYYY-MM-DD HH:MM:SS.SSS</i>
151
152 The space between the day and the year can optionally be
153 replaced by an uppercase <b>T</b> and the entire timestamp can
154 optionally be followed by "<b>z</b>" or "<b>Z</b>". In the fourth
155 form with fractional seconds, any number of digits may follow the
156 decimal point, though due to precision limits only the first three
157 digits will be significant.
@@ -161,14 +161,14 @@
161 distributed projects where participants are scattered around the globe.
162 But there is an option on the Admin/Timeline page of the web-interface to
163 switch to local time. The "<b>Z</b>" suffix on a timestamp check-in
164 name is meaningless if Fossil is in the default mode of using UTC for
165 everything, but if Fossil has been switched to local time mode, then the
166 "<b>Z</b>" suffix means to interpret that particular timestamp using
167 UTC instead of local time.
168
169 For an example of how timestamps are useful,
170 consider the homepage for the Fossil website itself:
171
172 <blockquote>
173 http://www.fossil-scm.org/fossil/doc/<b>trunk</b>/www/index.wiki
174 </blockquote>
@@ -191,11 +191,11 @@
191 <blockquote>
192 fossil update trunk:2010-07-01T14:30
193 </blockquote>
194
195 Would cause Fossil to update the working check-out to be the most recent
196 check-in on the trunk that is not more recent that 14:30 (UTC) on
197 July 1, 2010.
198
199 <h2>Root Of A Branch</h2>
200
201 A branch name that begins with the "<tt>root:</tt>" prefix refers to the
@@ -220,11 +220,11 @@
220 current check-out. And the "previous" or "prev" tag means the primary
221 (non-merge) parent of the current check-out.
222
223 For embedded documentation, the tag "ckout" means the version as present in
224 the local source tree on disk, provided that the web server is started using
225 "fossil ui" or "fossil server" from within the source tree. This tag can be
226 used to preview local changes to documentation before committing them. It does
227 not apply to CLI commands.
228
229 <h2>Additional Examples</h2>
230
231
--- www/childprojects.wiki
+++ www/childprojects.wiki
@@ -37,21 +37,21 @@
3737
VALUES('project-code',lower(hex(randomblob(20))));
3838
INSERT INTO config(name,value)
3939
VALUES('project-name','CHILD-PROJECT-NAME');
4040
</verbatim></blockquote>
4141
42
-Modify the CHILD-PROJECT-NAME in the last statement to be the name of
42
+Modify the CHILD-PROJECT-NAME in the last statement to be the name of
4343
the child project, of course.
4444
4545
The repository is now a separate project, independent from its parent.
4646
Clone the new project to the developers as needed.
4747
4848
The child project and the parent project will not normally be able to sync
4949
with one another, since they are now separate projects with distinct
5050
project codes. However, if the
51
-"--from-parent-project" command-line option is provided to the
52
-"[/help?cmd=pull|fossil pull]" command in the child, and the URL of
51
+"--from-parent-project" command-line option is provided to the
52
+"[/help?cmd=pull|fossil pull]" command in the child, and the URL of
5353
parent repository is also provided on the command-line, then updates to
5454
the parent project that occurred after the child was created will be added
5555
to the child repository. Thus, by periodically doing a
5656
pull --from-parent-project, the child project is able to stay up to date
5757
with all the latest changes in the parent.
5858
--- www/childprojects.wiki
+++ www/childprojects.wiki
@@ -37,21 +37,21 @@
37 VALUES('project-code',lower(hex(randomblob(20))));
38 INSERT INTO config(name,value)
39 VALUES('project-name','CHILD-PROJECT-NAME');
40 </verbatim></blockquote>
41
42 Modify the CHILD-PROJECT-NAME in the last statement to be the name of
43 the child project, of course.
44
45 The repository is now a separate project, independent from its parent.
46 Clone the new project to the developers as needed.
47
48 The child project and the parent project will not normally be able to sync
49 with one another, since they are now separate projects with distinct
50 project codes. However, if the
51 "--from-parent-project" command-line option is provided to the
52 "[/help?cmd=pull|fossil pull]" command in the child, and the URL of
53 parent repository is also provided on the command-line, then updates to
54 the parent project that occurred after the child was created will be added
55 to the child repository. Thus, by periodically doing a
56 pull --from-parent-project, the child project is able to stay up to date
57 with all the latest changes in the parent.
58
--- www/childprojects.wiki
+++ www/childprojects.wiki
@@ -37,21 +37,21 @@
37 VALUES('project-code',lower(hex(randomblob(20))));
38 INSERT INTO config(name,value)
39 VALUES('project-name','CHILD-PROJECT-NAME');
40 </verbatim></blockquote>
41
42 Modify the CHILD-PROJECT-NAME in the last statement to be the name of
43 the child project, of course.
44
45 The repository is now a separate project, independent from its parent.
46 Clone the new project to the developers as needed.
47
48 The child project and the parent project will not normally be able to sync
49 with one another, since they are now separate projects with distinct
50 project codes. However, if the
51 "--from-parent-project" command-line option is provided to the
52 "[/help?cmd=pull|fossil pull]" command in the child, and the URL of
53 parent repository is also provided on the command-line, then updates to
54 the parent project that occurred after the child was created will be added
55 to the child repository. Thus, by periodically doing a
56 pull --from-parent-project, the child project is able to stay up to date
57 with all the latest changes in the parent.
58
--- www/concepts.wiki
+++ www/concepts.wiki
@@ -131,11 +131,11 @@
131131
<h3>2.2 Manifests</h3>
132132
133133
Associated with every check-in is a special file called the
134134
[./fileformat.wiki#manifest| "manifest"]. The manifest is a
135135
listing of all other files in
136
-that source tree. The manifest contains the (complete) artifact ID
136
+that source tree. The manifest contains the (complete) artifact ID
137137
of the file and the name of the file as it appears on disk,
138138
and thus serves as a mapping from artifact ID to disk name. The artifact ID
139139
of the manifest is the identifier for the entire check-in. When
140140
you look at a "timeline" of changes in Fossil, the ID associated
141141
with each check-in or commit is really just the artifact ID of the
@@ -147,11 +147,11 @@
147147
manifest file to be materialized to disk, if desired. Both Fossil
148148
itself, and SQLite cause the manifest file to be materialized to disk
149149
so that the makefiles for these project can read the manifest and
150150
embed version information in generated binaries.
151151
152
-<p>Fossil automatically generates a manifest whenever you "commit"
152
+<p>Fossil automatically generates a manifest whenever you "commit"
153153
a new check-in. So this is not something that you, the developer,
154154
need to worry with. The format of a manifest is intentionally
155155
designed to be simple to parse, so that if
156156
you want to read and interpret a manifest, either by hand or
157157
with a script, that is easy to do. But you will probably never
@@ -200,11 +200,11 @@
200200
Fossil effectively. You will want to have some kind of text editor
201201
for entering check-in comments. Fossil will use whatever text editor
202202
is identified by your VISUAL environment variable. Fossil will also
203203
use GPG to clearsign your manifests if you happen to have it installed,
204204
but Fossil will skip that step if GPG missing from your system.
205
-You can optionally set up Fossil to use external "diff" programs,
205
+You can optionally set up Fossil to use external "diff" programs,
206206
though Fossil has an excellent built-in "diff" algorithm that works
207207
fine for most people. If you happen to have Tcl/Tk installed on your
208208
system, Fossil will use it to generate a graphical "diff" display when
209209
you use the --tk option to the "diff" command, but this too is entirely
210210
optional.
@@ -211,11 +211,11 @@
211211
212212
213213
To uninstall Fossil, simply delete the executable.
214214
215215
To upgrade an older version of Fossil to a newer version, just
216
-replace the old executable with the new one. You might need to
216
+replace the old executable with the new one. You might need to
217217
run "<b>fossil all rebuild</b>" to restructure your repositories after
218218
an upgrade. Running "all rebuild" never hurts, so when upgrading it
219219
is a good policy to run it even if it is not strictly necessary.
220220
221221
To use Fossil, simply type the name of the executable in your
@@ -266,11 +266,11 @@
266266
267267
<ol>
268268
<li>
269269
Establish a local repository using either the <b>new</b> command
270270
to start a new project, or the <b>clone</b> command to make a clone
271
-of a repository for an existing project.
271
+of a repository for an existing project.
272272
</li>
273273
274274
<li>
275275
Establish one or more source trees using
276276
the <b>open</b> command with the name of the repository file as its
@@ -279,11 +279,11 @@
279279
280280
<li>
281281
The <b>open</b> command in the previous step populates your local source
282282
tree with a copy of the latest check-in. Usually this is what you want.
283283
In the rare cases where it is not, use the <b>update</b> command to
284
-switch to a different check-in.
284
+switch to a different check-in.
285285
Use the <b>timeline</b> or <b>leaves</b> commands
286286
to identify alternative check-ins to switch to.
287287
</li>
288288
289289
<li>
@@ -302,17 +302,17 @@
302302
you cloned from or whatever server you most recently synced with.
303303
</li>
304304
305305
<li>
306306
When your coworkers make their own changes, you can merge those changes
307
-into your local local source tree using the <b>update</b> command.
307
+into your local local source tree using the <b>update</b> command.
308308
In autosync mode, <b>update</b> will first go back to the server you
309309
cloned from or with which you most recently synced, and pull down all
310310
recent changes into your local repository. Then it will merge recent
311311
changes into your local source tree. If you do an <b>update</b> and
312312
find that it messes something up in your source tree (perhaps a co-worker
313
-checked in incompatible changes) you can use the <b>undo</b> command
313
+checked in incompatible changes) you can use the <b>undo</b> command
314314
to back out the changes.
315315
</li>
316316
317317
<li>
318318
Repeat all of the above until you have generated great software.
319319
--- www/concepts.wiki
+++ www/concepts.wiki
@@ -131,11 +131,11 @@
131 <h3>2.2 Manifests</h3>
132
133 Associated with every check-in is a special file called the
134 [./fileformat.wiki#manifest| "manifest"]. The manifest is a
135 listing of all other files in
136 that source tree. The manifest contains the (complete) artifact ID
137 of the file and the name of the file as it appears on disk,
138 and thus serves as a mapping from artifact ID to disk name. The artifact ID
139 of the manifest is the identifier for the entire check-in. When
140 you look at a "timeline" of changes in Fossil, the ID associated
141 with each check-in or commit is really just the artifact ID of the
@@ -147,11 +147,11 @@
147 manifest file to be materialized to disk, if desired. Both Fossil
148 itself, and SQLite cause the manifest file to be materialized to disk
149 so that the makefiles for these project can read the manifest and
150 embed version information in generated binaries.
151
152 <p>Fossil automatically generates a manifest whenever you "commit"
153 a new check-in. So this is not something that you, the developer,
154 need to worry with. The format of a manifest is intentionally
155 designed to be simple to parse, so that if
156 you want to read and interpret a manifest, either by hand or
157 with a script, that is easy to do. But you will probably never
@@ -200,11 +200,11 @@
200 Fossil effectively. You will want to have some kind of text editor
201 for entering check-in comments. Fossil will use whatever text editor
202 is identified by your VISUAL environment variable. Fossil will also
203 use GPG to clearsign your manifests if you happen to have it installed,
204 but Fossil will skip that step if GPG missing from your system.
205 You can optionally set up Fossil to use external "diff" programs,
206 though Fossil has an excellent built-in "diff" algorithm that works
207 fine for most people. If you happen to have Tcl/Tk installed on your
208 system, Fossil will use it to generate a graphical "diff" display when
209 you use the --tk option to the "diff" command, but this too is entirely
210 optional.
@@ -211,11 +211,11 @@
211
212
213 To uninstall Fossil, simply delete the executable.
214
215 To upgrade an older version of Fossil to a newer version, just
216 replace the old executable with the new one. You might need to
217 run "<b>fossil all rebuild</b>" to restructure your repositories after
218 an upgrade. Running "all rebuild" never hurts, so when upgrading it
219 is a good policy to run it even if it is not strictly necessary.
220
221 To use Fossil, simply type the name of the executable in your
@@ -266,11 +266,11 @@
266
267 <ol>
268 <li>
269 Establish a local repository using either the <b>new</b> command
270 to start a new project, or the <b>clone</b> command to make a clone
271 of a repository for an existing project.
272 </li>
273
274 <li>
275 Establish one or more source trees using
276 the <b>open</b> command with the name of the repository file as its
@@ -279,11 +279,11 @@
279
280 <li>
281 The <b>open</b> command in the previous step populates your local source
282 tree with a copy of the latest check-in. Usually this is what you want.
283 In the rare cases where it is not, use the <b>update</b> command to
284 switch to a different check-in.
285 Use the <b>timeline</b> or <b>leaves</b> commands
286 to identify alternative check-ins to switch to.
287 </li>
288
289 <li>
@@ -302,17 +302,17 @@
302 you cloned from or whatever server you most recently synced with.
303 </li>
304
305 <li>
306 When your coworkers make their own changes, you can merge those changes
307 into your local local source tree using the <b>update</b> command.
308 In autosync mode, <b>update</b> will first go back to the server you
309 cloned from or with which you most recently synced, and pull down all
310 recent changes into your local repository. Then it will merge recent
311 changes into your local source tree. If you do an <b>update</b> and
312 find that it messes something up in your source tree (perhaps a co-worker
313 checked in incompatible changes) you can use the <b>undo</b> command
314 to back out the changes.
315 </li>
316
317 <li>
318 Repeat all of the above until you have generated great software.
319
--- www/concepts.wiki
+++ www/concepts.wiki
@@ -131,11 +131,11 @@
131 <h3>2.2 Manifests</h3>
132
133 Associated with every check-in is a special file called the
134 [./fileformat.wiki#manifest| "manifest"]. The manifest is a
135 listing of all other files in
136 that source tree. The manifest contains the (complete) artifact ID
137 of the file and the name of the file as it appears on disk,
138 and thus serves as a mapping from artifact ID to disk name. The artifact ID
139 of the manifest is the identifier for the entire check-in. When
140 you look at a "timeline" of changes in Fossil, the ID associated
141 with each check-in or commit is really just the artifact ID of the
@@ -147,11 +147,11 @@
147 manifest file to be materialized to disk, if desired. Both Fossil
148 itself, and SQLite cause the manifest file to be materialized to disk
149 so that the makefiles for these project can read the manifest and
150 embed version information in generated binaries.
151
152 <p>Fossil automatically generates a manifest whenever you "commit"
153 a new check-in. So this is not something that you, the developer,
154 need to worry with. The format of a manifest is intentionally
155 designed to be simple to parse, so that if
156 you want to read and interpret a manifest, either by hand or
157 with a script, that is easy to do. But you will probably never
@@ -200,11 +200,11 @@
200 Fossil effectively. You will want to have some kind of text editor
201 for entering check-in comments. Fossil will use whatever text editor
202 is identified by your VISUAL environment variable. Fossil will also
203 use GPG to clearsign your manifests if you happen to have it installed,
204 but Fossil will skip that step if GPG missing from your system.
205 You can optionally set up Fossil to use external "diff" programs,
206 though Fossil has an excellent built-in "diff" algorithm that works
207 fine for most people. If you happen to have Tcl/Tk installed on your
208 system, Fossil will use it to generate a graphical "diff" display when
209 you use the --tk option to the "diff" command, but this too is entirely
210 optional.
@@ -211,11 +211,11 @@
211
212
213 To uninstall Fossil, simply delete the executable.
214
215 To upgrade an older version of Fossil to a newer version, just
216 replace the old executable with the new one. You might need to
217 run "<b>fossil all rebuild</b>" to restructure your repositories after
218 an upgrade. Running "all rebuild" never hurts, so when upgrading it
219 is a good policy to run it even if it is not strictly necessary.
220
221 To use Fossil, simply type the name of the executable in your
@@ -266,11 +266,11 @@
266
267 <ol>
268 <li>
269 Establish a local repository using either the <b>new</b> command
270 to start a new project, or the <b>clone</b> command to make a clone
271 of a repository for an existing project.
272 </li>
273
274 <li>
275 Establish one or more source trees using
276 the <b>open</b> command with the name of the repository file as its
@@ -279,11 +279,11 @@
279
280 <li>
281 The <b>open</b> command in the previous step populates your local source
282 tree with a copy of the latest check-in. Usually this is what you want.
283 In the rare cases where it is not, use the <b>update</b> command to
284 switch to a different check-in.
285 Use the <b>timeline</b> or <b>leaves</b> commands
286 to identify alternative check-ins to switch to.
287 </li>
288
289 <li>
@@ -302,17 +302,17 @@
302 you cloned from or whatever server you most recently synced with.
303 </li>
304
305 <li>
306 When your coworkers make their own changes, you can merge those changes
307 into your local local source tree using the <b>update</b> command.
308 In autosync mode, <b>update</b> will first go back to the server you
309 cloned from or with which you most recently synced, and pull down all
310 recent changes into your local repository. Then it will merge recent
311 changes into your local source tree. If you do an <b>update</b> and
312 find that it messes something up in your source tree (perhaps a co-worker
313 checked in incompatible changes) you can use the <b>undo</b> command
314 to back out the changes.
315 </li>
316
317 <li>
318 Repeat all of the above until you have generated great software.
319
--- www/contribute.wiki
+++ www/contribute.wiki
@@ -10,11 +10,11 @@
1010
[./copyright-release.pdf | Contributor Agreement (PDF)]
1111
(or [./copyright-release.html | as HTML]) on file for you. We require
1212
this in order to maintain clear title to the Fossil code and prevent
1313
the introduction of code with incompatible licenses or other entanglements
1414
that might cause legal problems for Fossil users. Many larger companies
15
-and other lawyer-rich organizations require this as a precondition to using
15
+and other lawyer-rich organizations require this as a precondition to using
1616
Fossil.
1717
1818
If you do not wish to submit a Contributor Agreement, we would still
1919
welcome your suggestions and example code, but we will not use your code
2020
directly - we will be forced to re-implement your changes from scratch which
@@ -21,14 +21,14 @@
2121
might take longer.
2222
2323
<h2>2.0 Submitting Patches</h2>
2424
2525
Suggested changes or bug fixes can be submitted by creating a patch
26
-against the current source tree. Email patches to
27
-<a href="mailto:[email protected]">[email protected]</a>. Be sure to
26
+against the current source tree. Email patches to
27
+<a href="mailto:[email protected]">[email protected]</a>. Be sure to
2828
describe in detail what the patch does and which version of Fossil
29
-it is written against.
29
+it is written against.
3030
3131
A contributor agreement is not strictly necessary to submit a patch.
3232
However, without a contributor agreement on file, your patch will be
3333
used for reference only - it will not be applied to the code. This
3434
may delay acceptance of your patch.
@@ -53,23 +53,23 @@
5353
Fossil Architect (Richard Hipp) will merge changes onto the trunk.</p>
5454
5555
Contributors are required to following the
5656
[./checkin.wiki | pre-checkin checklist] prior to every check-in to
5757
the Fossil self-hosting repository. This checklist is short and succinct
58
-and should only require a few seconds to follow. Contributors
58
+and should only require a few seconds to follow. Contributors
5959
should print out a copy of the pre-checkin checklist and keep
6060
it on a notecard beside their workstations, for quick reference.
6161
6262
Contributors should review the
6363
[./style.wiki | Coding Style Guidelines] and mimic the coding style
6464
used through the rest of the Fossil source code. Your code should
6565
blend in. A third-party reader should be unable to distinguish your
66
-code from any other code in the source corpus.
66
+code from any other code in the source corpus.
6767
6868
<h2>4.0 Testing</h2>
6969
70
-Fossil has the beginnings of a
70
+Fossil has the beginnings of a
7171
[../test/release-checklist.wiki | release checklist] but this is an
7272
area that needs further work. (Your contributions here are welcomed!)
7373
Contributors with check-in privileges are expected to run the release
7474
checklist on any major changes they contribute, and if appropriate expand
7575
the checklist and/or the automated test scripts to cover their additions.
7676
--- www/contribute.wiki
+++ www/contribute.wiki
@@ -10,11 +10,11 @@
10 [./copyright-release.pdf | Contributor Agreement (PDF)]
11 (or [./copyright-release.html | as HTML]) on file for you. We require
12 this in order to maintain clear title to the Fossil code and prevent
13 the introduction of code with incompatible licenses or other entanglements
14 that might cause legal problems for Fossil users. Many larger companies
15 and other lawyer-rich organizations require this as a precondition to using
16 Fossil.
17
18 If you do not wish to submit a Contributor Agreement, we would still
19 welcome your suggestions and example code, but we will not use your code
20 directly - we will be forced to re-implement your changes from scratch which
@@ -21,14 +21,14 @@
21 might take longer.
22
23 <h2>2.0 Submitting Patches</h2>
24
25 Suggested changes or bug fixes can be submitted by creating a patch
26 against the current source tree. Email patches to
27 <a href="mailto:[email protected]">[email protected]</a>. Be sure to
28 describe in detail what the patch does and which version of Fossil
29 it is written against.
30
31 A contributor agreement is not strictly necessary to submit a patch.
32 However, without a contributor agreement on file, your patch will be
33 used for reference only - it will not be applied to the code. This
34 may delay acceptance of your patch.
@@ -53,23 +53,23 @@
53 Fossil Architect (Richard Hipp) will merge changes onto the trunk.</p>
54
55 Contributors are required to following the
56 [./checkin.wiki | pre-checkin checklist] prior to every check-in to
57 the Fossil self-hosting repository. This checklist is short and succinct
58 and should only require a few seconds to follow. Contributors
59 should print out a copy of the pre-checkin checklist and keep
60 it on a notecard beside their workstations, for quick reference.
61
62 Contributors should review the
63 [./style.wiki | Coding Style Guidelines] and mimic the coding style
64 used through the rest of the Fossil source code. Your code should
65 blend in. A third-party reader should be unable to distinguish your
66 code from any other code in the source corpus.
67
68 <h2>4.0 Testing</h2>
69
70 Fossil has the beginnings of a
71 [../test/release-checklist.wiki | release checklist] but this is an
72 area that needs further work. (Your contributions here are welcomed!)
73 Contributors with check-in privileges are expected to run the release
74 checklist on any major changes they contribute, and if appropriate expand
75 the checklist and/or the automated test scripts to cover their additions.
76
--- www/contribute.wiki
+++ www/contribute.wiki
@@ -10,11 +10,11 @@
10 [./copyright-release.pdf | Contributor Agreement (PDF)]
11 (or [./copyright-release.html | as HTML]) on file for you. We require
12 this in order to maintain clear title to the Fossil code and prevent
13 the introduction of code with incompatible licenses or other entanglements
14 that might cause legal problems for Fossil users. Many larger companies
15 and other lawyer-rich organizations require this as a precondition to using
16 Fossil.
17
18 If you do not wish to submit a Contributor Agreement, we would still
19 welcome your suggestions and example code, but we will not use your code
20 directly - we will be forced to re-implement your changes from scratch which
@@ -21,14 +21,14 @@
21 might take longer.
22
23 <h2>2.0 Submitting Patches</h2>
24
25 Suggested changes or bug fixes can be submitted by creating a patch
26 against the current source tree. Email patches to
27 <a href="mailto:[email protected]">[email protected]</a>. Be sure to
28 describe in detail what the patch does and which version of Fossil
29 it is written against.
30
31 A contributor agreement is not strictly necessary to submit a patch.
32 However, without a contributor agreement on file, your patch will be
33 used for reference only - it will not be applied to the code. This
34 may delay acceptance of your patch.
@@ -53,23 +53,23 @@
53 Fossil Architect (Richard Hipp) will merge changes onto the trunk.</p>
54
55 Contributors are required to following the
56 [./checkin.wiki | pre-checkin checklist] prior to every check-in to
57 the Fossil self-hosting repository. This checklist is short and succinct
58 and should only require a few seconds to follow. Contributors
59 should print out a copy of the pre-checkin checklist and keep
60 it on a notecard beside their workstations, for quick reference.
61
62 Contributors should review the
63 [./style.wiki | Coding Style Guidelines] and mimic the coding style
64 used through the rest of the Fossil source code. Your code should
65 blend in. A third-party reader should be unable to distinguish your
66 code from any other code in the source corpus.
67
68 <h2>4.0 Testing</h2>
69
70 Fossil has the beginnings of a
71 [../test/release-checklist.wiki | release checklist] but this is an
72 area that needs further work. (Your contributions here are welcomed!)
73 Contributors with check-in privileges are expected to run the release
74 checklist on any major changes they contribute, and if appropriate expand
75 the checklist and/or the automated test scripts to cover their additions.
76
--- www/custom_ticket.wiki
+++ www/custom_ticket.wiki
@@ -65,11 +65,11 @@
6565
&lt;/tr>
6666
&lt;th1>enable_output 1&lt;/th1>
6767
</pre>
6868
This bit of code will get rid of the "email" field entry for logged-in users.
6969
Since we know the user's information, we don't have to ask for it. NOTE: it
70
-might be good to automatically scoop up the user's email and put it here.
70
+might be good to automatically scoop up the user's email and put it here.
7171
</p>
7272
</blockquote>
7373
7474
<h2>Modify the 'view ticket' page</h2><blockquote>
7575
<p>
@@ -83,11 +83,11 @@
8383
&lt;td align="right">Opened by:&lt;/td>&lt;td bgcolor="#d0d0d0">
8484
$&lt;opened_by>
8585
&lt;/td>
8686
</pre>
8787
This will add a row which displays these two fields, in the event the user has
88
-"edit" capability.
88
+"edit" capability.
8989
</p>
9090
</blockquote>
9191
9292
<h2>Modify the 'edit ticket' page</h2><blockquote>
9393
<p>
9494
--- www/custom_ticket.wiki
+++ www/custom_ticket.wiki
@@ -65,11 +65,11 @@
65 &lt;/tr>
66 &lt;th1>enable_output 1&lt;/th1>
67 </pre>
68 This bit of code will get rid of the "email" field entry for logged-in users.
69 Since we know the user's information, we don't have to ask for it. NOTE: it
70 might be good to automatically scoop up the user's email and put it here.
71 </p>
72 </blockquote>
73
74 <h2>Modify the 'view ticket' page</h2><blockquote>
75 <p>
@@ -83,11 +83,11 @@
83 &lt;td align="right">Opened by:&lt;/td>&lt;td bgcolor="#d0d0d0">
84 $&lt;opened_by>
85 &lt;/td>
86 </pre>
87 This will add a row which displays these two fields, in the event the user has
88 "edit" capability.
89 </p>
90 </blockquote>
91
92 <h2>Modify the 'edit ticket' page</h2><blockquote>
93 <p>
94
--- www/custom_ticket.wiki
+++ www/custom_ticket.wiki
@@ -65,11 +65,11 @@
65 &lt;/tr>
66 &lt;th1>enable_output 1&lt;/th1>
67 </pre>
68 This bit of code will get rid of the "email" field entry for logged-in users.
69 Since we know the user's information, we don't have to ask for it. NOTE: it
70 might be good to automatically scoop up the user's email and put it here.
71 </p>
72 </blockquote>
73
74 <h2>Modify the 'view ticket' page</h2><blockquote>
75 <p>
@@ -83,11 +83,11 @@
83 &lt;td align="right">Opened by:&lt;/td>&lt;td bgcolor="#d0d0d0">
84 $&lt;opened_by>
85 &lt;/td>
86 </pre>
87 This will add a row which displays these two fields, in the event the user has
88 "edit" capability.
89 </p>
90 </blockquote>
91
92 <h2>Modify the 'edit ticket' page</h2><blockquote>
93 <p>
94
--- www/customskin.md
+++ www/customskin.md
@@ -144,10 +144,14 @@
144144
respository settings and the specific page being generated.
145145
146146
* **project_name** - The project_name variable is filled with the
147147
name of the project as configured under the Admin/Configuration
148148
menu.
149
+
150
+ * **project_description** - The project_description variable is
151
+ filled with the description of the project as configured under
152
+ the Admin/Configuration menu.
149153
150154
* **title** - The title variable holds the title of the page being
151155
generated.
152156
153157
The title variable is special in that it is deleted after
154158
--- www/customskin.md
+++ www/customskin.md
@@ -144,10 +144,14 @@
144 respository settings and the specific page being generated.
145
146 * **project_name** - The project_name variable is filled with the
147 name of the project as configured under the Admin/Configuration
148 menu.
 
 
 
 
149
150 * **title** - The title variable holds the title of the page being
151 generated.
152
153 The title variable is special in that it is deleted after
154
--- www/customskin.md
+++ www/customskin.md
@@ -144,10 +144,14 @@
144 respository settings and the specific page being generated.
145
146 * **project_name** - The project_name variable is filled with the
147 name of the project as configured under the Admin/Configuration
148 menu.
149
150 * **project_description** - The project_description variable is
151 filled with the description of the project as configured under
152 the Admin/Configuration menu.
153
154 * **title** - The title variable holds the title of the page being
155 generated.
156
157 The title variable is special in that it is deleted after
158
--- www/delta_encoder_algorithm.wiki
+++ www/delta_encoder_algorithm.wiki
@@ -153,11 +153,11 @@
153153
byte forward. The "base" is left unchanged in that case.</p>
154154
155155
<p>The processing loop stops at one of two conditions:
156156
<ol>
157157
<li>The encoder decided to move the window forward, but the end of the
158
-window reached the end of the "target".
158
+window reached the end of the "target".
159159
</li>
160160
<li>After the emission of instructions the new "base" location is
161161
within NHASH bytes of end of the "target", i.e. there are no more than
162162
at most NHASH bytes left.
163163
</li>
164164
--- www/delta_encoder_algorithm.wiki
+++ www/delta_encoder_algorithm.wiki
@@ -153,11 +153,11 @@
153 byte forward. The "base" is left unchanged in that case.</p>
154
155 <p>The processing loop stops at one of two conditions:
156 <ol>
157 <li>The encoder decided to move the window forward, but the end of the
158 window reached the end of the "target".
159 </li>
160 <li>After the emission of instructions the new "base" location is
161 within NHASH bytes of end of the "target", i.e. there are no more than
162 at most NHASH bytes left.
163 </li>
164
--- www/delta_encoder_algorithm.wiki
+++ www/delta_encoder_algorithm.wiki
@@ -153,11 +153,11 @@
153 byte forward. The "base" is left unchanged in that case.</p>
154
155 <p>The processing loop stops at one of two conditions:
156 <ol>
157 <li>The encoder decided to move the window forward, but the end of the
158 window reached the end of the "target".
159 </li>
160 <li>After the emission of instructions the new "base" location is
161 within NHASH bytes of end of the "target", i.e. there are no more than
162 at most NHASH bytes left.
163 </li>
164
--- www/delta_format.wiki
+++ www/delta_format.wiki
@@ -161,49 +161,49 @@
161161
</table>
162162
163163
<p>The unified diff behind the above delta is</p>
164164
165165
<table border=1><tr><td><pre>
166
-bluepeak:(761) ~/Projects/Tcl/Fossil/Devel/devel > diff -u ../DELTA/old ../DELTA/new
166
+bluepeak:(761) ~/Projects/Tcl/Fossil/Devel/devel > diff -u ../DELTA/old ../DELTA/new
167167
--- ../DELTA/old 2007-08-23 21:14:40.000000000 -0700
168168
+++ ../DELTA/new 2007-08-23 21:14:33.000000000 -0700
169169
@@ -5,7 +5,7 @@
170
-
170
+
171171
* If the server does not have write permission on the database
172
- file, or on the directory containing the database file (and
172
+ file, or on the directory containing the database file (and
173173
- it is thus unable to update database because it cannot create
174174
+ it is thus unable to update the database because it cannot create
175175
a rollback journal) then it currently fails silently on a push.
176176
It needs to return a helpful error.
177
-
177
+
178178
@@ -27,8 +27,8 @@
179179
* Additional information displayed for the "vinfo" page:
180
-
180
+
181181
+ All leaves of this version that are not included in the
182182
- descendant list. With date, user, comment, and hyperlink.
183183
- Leaves in the descendant table should be marked as such.
184184
+ descendant list. With date, user, comment, and hyperlink.
185185
+ Leaves in the descendant table should be marked as such.
186186
See the compute_leaves() function to see how to find all
187187
leaves.
188188
+ Add file diff links to the file change list.
189189
@@ -37,7 +37,7 @@
190
-
190
+
191191
* The /xfer handler (for push, pull, and clone) does not do
192192
delta compression. This results in excess bandwidth usage.
193193
- There are some code in xfer.c that are sketches of ideas on
194194
+ There are some pieces in xfer.c that are sketches of ideas on
195195
how to do delta compression, but nothing has been implemented.
196
-
196
+
197197
* Enhancements to the diff and tkdiff commands in the cli.
198198
@@ -45,7 +45,7 @@
199199
single file. Allow diffs against any two arbitrary versions,
200
- not just diffs against the current check-out. Allow
200
+ not just diffs against the current check-out. Allow
201201
configuration options to replace tkdiff with some other
202202
- visual differ of the users choice.
203203
+ visual differ of the users choice. Example: eskil.
204
-
204
+
205205
* Ticketing interface (expand this bullet)
206206
207207
</pre></td></tr></table>
208208
209209
210210
--- www/delta_format.wiki
+++ www/delta_format.wiki
@@ -161,49 +161,49 @@
161 </table>
162
163 <p>The unified diff behind the above delta is</p>
164
165 <table border=1><tr><td><pre>
166 bluepeak:(761) ~/Projects/Tcl/Fossil/Devel/devel > diff -u ../DELTA/old ../DELTA/new
167 --- ../DELTA/old 2007-08-23 21:14:40.000000000 -0700
168 +++ ../DELTA/new 2007-08-23 21:14:33.000000000 -0700
169 @@ -5,7 +5,7 @@
170
171 * If the server does not have write permission on the database
172 file, or on the directory containing the database file (and
173 - it is thus unable to update database because it cannot create
174 + it is thus unable to update the database because it cannot create
175 a rollback journal) then it currently fails silently on a push.
176 It needs to return a helpful error.
177
178 @@ -27,8 +27,8 @@
179 * Additional information displayed for the "vinfo" page:
180
181 + All leaves of this version that are not included in the
182 - descendant list. With date, user, comment, and hyperlink.
183 - Leaves in the descendant table should be marked as such.
184 + descendant list. With date, user, comment, and hyperlink.
185 + Leaves in the descendant table should be marked as such.
186 See the compute_leaves() function to see how to find all
187 leaves.
188 + Add file diff links to the file change list.
189 @@ -37,7 +37,7 @@
190
191 * The /xfer handler (for push, pull, and clone) does not do
192 delta compression. This results in excess bandwidth usage.
193 - There are some code in xfer.c that are sketches of ideas on
194 + There are some pieces in xfer.c that are sketches of ideas on
195 how to do delta compression, but nothing has been implemented.
196
197 * Enhancements to the diff and tkdiff commands in the cli.
198 @@ -45,7 +45,7 @@
199 single file. Allow diffs against any two arbitrary versions,
200 not just diffs against the current check-out. Allow
201 configuration options to replace tkdiff with some other
202 - visual differ of the users choice.
203 + visual differ of the users choice. Example: eskil.
204
205 * Ticketing interface (expand this bullet)
206
207 </pre></td></tr></table>
208
209
210
--- www/delta_format.wiki
+++ www/delta_format.wiki
@@ -161,49 +161,49 @@
161 </table>
162
163 <p>The unified diff behind the above delta is</p>
164
165 <table border=1><tr><td><pre>
166 bluepeak:(761) ~/Projects/Tcl/Fossil/Devel/devel > diff -u ../DELTA/old ../DELTA/new
167 --- ../DELTA/old 2007-08-23 21:14:40.000000000 -0700
168 +++ ../DELTA/new 2007-08-23 21:14:33.000000000 -0700
169 @@ -5,7 +5,7 @@
170
171 * If the server does not have write permission on the database
172 file, or on the directory containing the database file (and
173 - it is thus unable to update database because it cannot create
174 + it is thus unable to update the database because it cannot create
175 a rollback journal) then it currently fails silently on a push.
176 It needs to return a helpful error.
177
178 @@ -27,8 +27,8 @@
179 * Additional information displayed for the "vinfo" page:
180
181 + All leaves of this version that are not included in the
182 - descendant list. With date, user, comment, and hyperlink.
183 - Leaves in the descendant table should be marked as such.
184 + descendant list. With date, user, comment, and hyperlink.
185 + Leaves in the descendant table should be marked as such.
186 See the compute_leaves() function to see how to find all
187 leaves.
188 + Add file diff links to the file change list.
189 @@ -37,7 +37,7 @@
190
191 * The /xfer handler (for push, pull, and clone) does not do
192 delta compression. This results in excess bandwidth usage.
193 - There are some code in xfer.c that are sketches of ideas on
194 + There are some pieces in xfer.c that are sketches of ideas on
195 how to do delta compression, but nothing has been implemented.
196
197 * Enhancements to the diff and tkdiff commands in the cli.
198 @@ -45,7 +45,7 @@
199 single file. Allow diffs against any two arbitrary versions,
200 not just diffs against the current check-out. Allow
201 configuration options to replace tkdiff with some other
202 - visual differ of the users choice.
203 + visual differ of the users choice. Example: eskil.
204
205 * Ticketing interface (expand this bullet)
206
207 </pre></td></tr></table>
208
209
210
--- www/embeddeddoc.wiki
+++ www/embeddeddoc.wiki
@@ -42,13 +42,13 @@
4242
<b>http://www.hwaci.com/cgi-bin/fossil</b>.
4343
If you launch the web server using the "<b>fossil server</b>" command line,
4444
then the <i>&lt;baseurl&gt;</i> is usually
4545
<b>http://localhost:8080/</b>.
4646
47
-The <i>&lt;version&gt;</i> is any unique prefix of the check-in ID for
47
+The <i>&lt;version&gt;</i> is any unique prefix of the check-in ID for
4848
the check-in containing the documentation you want to access.
49
-Or <i>&lt;version&gt;</i> can be the name of a
49
+Or <i>&lt;version&gt;</i> can be the name of a
5050
[./branching.wiki | branch] in order to show
5151
the documentation for the latest version of that branch.
5252
Or <i>&lt;version&gt;</i> can be one of the keywords "<b>tip</b>" or
5353
"<b>ckout</b>". The "<b>tip</b>" keyword means to use the most recent
5454
check-in. This is useful if you want to see the very latest
@@ -62,30 +62,30 @@
6262
6363
Finally, the <i>&lt;filename&gt;</i> element of the URL is the
6464
pathname of the documentation file relative to the root of the source
6565
tree.
6666
67
-The mimetype (and thus the rendering) of documentation files is
68
-determined by the file suffix. Fossil currently understands
67
+The mimetype (and thus the rendering) of documentation files is
68
+determined by the file suffix. Fossil currently understands
6969
[/mimetype_list|many different file suffixes],
7070
including all the popular ones such as ".css", ".gif", ".htm",
7171
".html", ".jpg", ".jpeg", ".png", and ".txt".
7272
73
-Documentation files whose names end in ".wiki" use the
73
+Documentation files whose names end in ".wiki" use the
7474
[/wiki_rules | fossil wiki markup] -
7575
a safe subset of HTML together with some wiki rules for paragraph
76
-breaks, lists, and hyperlinks.
76
+breaks, lists, and hyperlinks.
7777
Documentation files ending in ".md" or ".markdown" use the
7878
[/md_rules | Markdown markup langauge].
7979
Documentation files ending in ".txt" are plain text.
8080
Wiki, markdown, and plain text documentation files
8181
are rendered with the standard fossil header and footer added.
8282
Most other mimetypes are delivered directly to the requesting
8383
web browser without interpretation, additions, or changes.
8484
8585
Files with the mimetype "text/html" (the .html or .htm suffix) are
86
-usually rendered directly to the browser without interpretation.
86
+usually rendered directly to the browser without interpretation.
8787
However, if the file begins with a &lt;div&gt; element like this:
8888
8989
<b>&lt;div class='fossil-doc' data-title='<i>Title Text</i>'&gt;</b>
9090
9191
Then the standard Fossil header and footer are added to the document
@@ -117,11 +117,11 @@
117117
<blockquote><pre>
118118
#!/usr/bin/fossil
119119
repository: /fossil/fossil.fossil
120120
</pre></blockquote>
121121
122
-This is one of four ways to set up a
122
+This is one of four ways to set up a
123123
<a href="./server.wiki">fossil web server</a>.
124124
125125
The "<b>/trunk/</b>" part of the URL tells fossil to use
126126
the documentation files from the most recent trunk check-in.
127127
If you wanted to see an historical version of this document,
@@ -138,11 +138,11 @@
138138
<li> <i>YYYY-MM-DD</i>
139139
<li> <i>YYYY-MM-DD</i><b>T</b><i>HH:MM</i>
140140
<li> <i>YYYY-MM-DD</i><b>T</b><i>HH:MM:SS</i>
141141
</ul>
142142
143
-When the symbolic name is a date and time, fossil shows the version
143
+When the symbolic name is a date and time, fossil shows the version
144144
of the document that was most recently checked in as of the date
145145
and time specified. So, for example, to see what the fossil website
146146
looked like at the beginning of 2010, enter:
147147
148148
<blockquote>
149149
--- www/embeddeddoc.wiki
+++ www/embeddeddoc.wiki
@@ -42,13 +42,13 @@
42 <b>http://www.hwaci.com/cgi-bin/fossil</b>.
43 If you launch the web server using the "<b>fossil server</b>" command line,
44 then the <i>&lt;baseurl&gt;</i> is usually
45 <b>http://localhost:8080/</b>.
46
47 The <i>&lt;version&gt;</i> is any unique prefix of the check-in ID for
48 the check-in containing the documentation you want to access.
49 Or <i>&lt;version&gt;</i> can be the name of a
50 [./branching.wiki | branch] in order to show
51 the documentation for the latest version of that branch.
52 Or <i>&lt;version&gt;</i> can be one of the keywords "<b>tip</b>" or
53 "<b>ckout</b>". The "<b>tip</b>" keyword means to use the most recent
54 check-in. This is useful if you want to see the very latest
@@ -62,30 +62,30 @@
62
63 Finally, the <i>&lt;filename&gt;</i> element of the URL is the
64 pathname of the documentation file relative to the root of the source
65 tree.
66
67 The mimetype (and thus the rendering) of documentation files is
68 determined by the file suffix. Fossil currently understands
69 [/mimetype_list|many different file suffixes],
70 including all the popular ones such as ".css", ".gif", ".htm",
71 ".html", ".jpg", ".jpeg", ".png", and ".txt".
72
73 Documentation files whose names end in ".wiki" use the
74 [/wiki_rules | fossil wiki markup] -
75 a safe subset of HTML together with some wiki rules for paragraph
76 breaks, lists, and hyperlinks.
77 Documentation files ending in ".md" or ".markdown" use the
78 [/md_rules | Markdown markup langauge].
79 Documentation files ending in ".txt" are plain text.
80 Wiki, markdown, and plain text documentation files
81 are rendered with the standard fossil header and footer added.
82 Most other mimetypes are delivered directly to the requesting
83 web browser without interpretation, additions, or changes.
84
85 Files with the mimetype "text/html" (the .html or .htm suffix) are
86 usually rendered directly to the browser without interpretation.
87 However, if the file begins with a &lt;div&gt; element like this:
88
89 <b>&lt;div class='fossil-doc' data-title='<i>Title Text</i>'&gt;</b>
90
91 Then the standard Fossil header and footer are added to the document
@@ -117,11 +117,11 @@
117 <blockquote><pre>
118 #!/usr/bin/fossil
119 repository: /fossil/fossil.fossil
120 </pre></blockquote>
121
122 This is one of four ways to set up a
123 <a href="./server.wiki">fossil web server</a>.
124
125 The "<b>/trunk/</b>" part of the URL tells fossil to use
126 the documentation files from the most recent trunk check-in.
127 If you wanted to see an historical version of this document,
@@ -138,11 +138,11 @@
138 <li> <i>YYYY-MM-DD</i>
139 <li> <i>YYYY-MM-DD</i><b>T</b><i>HH:MM</i>
140 <li> <i>YYYY-MM-DD</i><b>T</b><i>HH:MM:SS</i>
141 </ul>
142
143 When the symbolic name is a date and time, fossil shows the version
144 of the document that was most recently checked in as of the date
145 and time specified. So, for example, to see what the fossil website
146 looked like at the beginning of 2010, enter:
147
148 <blockquote>
149
--- www/embeddeddoc.wiki
+++ www/embeddeddoc.wiki
@@ -42,13 +42,13 @@
42 <b>http://www.hwaci.com/cgi-bin/fossil</b>.
43 If you launch the web server using the "<b>fossil server</b>" command line,
44 then the <i>&lt;baseurl&gt;</i> is usually
45 <b>http://localhost:8080/</b>.
46
47 The <i>&lt;version&gt;</i> is any unique prefix of the check-in ID for
48 the check-in containing the documentation you want to access.
49 Or <i>&lt;version&gt;</i> can be the name of a
50 [./branching.wiki | branch] in order to show
51 the documentation for the latest version of that branch.
52 Or <i>&lt;version&gt;</i> can be one of the keywords "<b>tip</b>" or
53 "<b>ckout</b>". The "<b>tip</b>" keyword means to use the most recent
54 check-in. This is useful if you want to see the very latest
@@ -62,30 +62,30 @@
62
63 Finally, the <i>&lt;filename&gt;</i> element of the URL is the
64 pathname of the documentation file relative to the root of the source
65 tree.
66
67 The mimetype (and thus the rendering) of documentation files is
68 determined by the file suffix. Fossil currently understands
69 [/mimetype_list|many different file suffixes],
70 including all the popular ones such as ".css", ".gif", ".htm",
71 ".html", ".jpg", ".jpeg", ".png", and ".txt".
72
73 Documentation files whose names end in ".wiki" use the
74 [/wiki_rules | fossil wiki markup] -
75 a safe subset of HTML together with some wiki rules for paragraph
76 breaks, lists, and hyperlinks.
77 Documentation files ending in ".md" or ".markdown" use the
78 [/md_rules | Markdown markup langauge].
79 Documentation files ending in ".txt" are plain text.
80 Wiki, markdown, and plain text documentation files
81 are rendered with the standard fossil header and footer added.
82 Most other mimetypes are delivered directly to the requesting
83 web browser without interpretation, additions, or changes.
84
85 Files with the mimetype "text/html" (the .html or .htm suffix) are
86 usually rendered directly to the browser without interpretation.
87 However, if the file begins with a &lt;div&gt; element like this:
88
89 <b>&lt;div class='fossil-doc' data-title='<i>Title Text</i>'&gt;</b>
90
91 Then the standard Fossil header and footer are added to the document
@@ -117,11 +117,11 @@
117 <blockquote><pre>
118 #!/usr/bin/fossil
119 repository: /fossil/fossil.fossil
120 </pre></blockquote>
121
122 This is one of four ways to set up a
123 <a href="./server.wiki">fossil web server</a>.
124
125 The "<b>/trunk/</b>" part of the URL tells fossil to use
126 the documentation files from the most recent trunk check-in.
127 If you wanted to see an historical version of this document,
@@ -138,11 +138,11 @@
138 <li> <i>YYYY-MM-DD</i>
139 <li> <i>YYYY-MM-DD</i><b>T</b><i>HH:MM</i>
140 <li> <i>YYYY-MM-DD</i><b>T</b><i>HH:MM:SS</i>
141 </ul>
142
143 When the symbolic name is a date and time, fossil shows the version
144 of the document that was most recently checked in as of the date
145 and time specified. So, for example, to see what the fossil website
146 looked like at the beginning of 2010, enter:
147
148 <blockquote>
149
--- www/encryptedrepos.wiki
+++ www/encryptedrepos.wiki
@@ -3,11 +3,11 @@
33
Fossil can be compiled so that it works with encrypted repositories using
44
the [https://www.sqlite.org/see/doc/trunk/www/readme.wiki|SQLite Encryption Extension].
55
This technical note explains the process.
66
</blockquote>
77
<h2>Building An Encryption-Enabled Fossil</h2><blockquote>
8
-The SQLite Encryption Extension (SEE) is proprietary software and requires
8
+The SQLite Encryption Extension (SEE) is proprietary software and requires
99
[http://www.hwaci.com/cgi-bin/see-step1|purchasing a license].
1010
<p>
1111
Assuming you have an SEE license, the first step of compiling Fossil to
1212
use SEE is to create an SEE-enabled version of the SQLite database source code.
1313
This alternative SQLite database source file should be called "sqlite3-see.c"
1414
--- www/encryptedrepos.wiki
+++ www/encryptedrepos.wiki
@@ -3,11 +3,11 @@
3 Fossil can be compiled so that it works with encrypted repositories using
4 the [https://www.sqlite.org/see/doc/trunk/www/readme.wiki|SQLite Encryption Extension].
5 This technical note explains the process.
6 </blockquote>
7 <h2>Building An Encryption-Enabled Fossil</h2><blockquote>
8 The SQLite Encryption Extension (SEE) is proprietary software and requires
9 [http://www.hwaci.com/cgi-bin/see-step1|purchasing a license].
10 <p>
11 Assuming you have an SEE license, the first step of compiling Fossil to
12 use SEE is to create an SEE-enabled version of the SQLite database source code.
13 This alternative SQLite database source file should be called "sqlite3-see.c"
14
--- www/encryptedrepos.wiki
+++ www/encryptedrepos.wiki
@@ -3,11 +3,11 @@
3 Fossil can be compiled so that it works with encrypted repositories using
4 the [https://www.sqlite.org/see/doc/trunk/www/readme.wiki|SQLite Encryption Extension].
5 This technical note explains the process.
6 </blockquote>
7 <h2>Building An Encryption-Enabled Fossil</h2><blockquote>
8 The SQLite Encryption Extension (SEE) is proprietary software and requires
9 [http://www.hwaci.com/cgi-bin/see-step1|purchasing a license].
10 <p>
11 Assuming you have an SEE license, the first step of compiling Fossil to
12 use SEE is to create an SEE-enabled version of the SQLite database source code.
13 This alternative SQLite database source file should be called "sqlite3-see.c"
14
+3 -3
--- www/event.wiki
+++ www/event.wiki
@@ -23,11 +23,11 @@
2323
can be something simple like "Version 1.2.3" perhaps with a bright
2424
color background to draw attention to the entry and the wiki content
2525
can contain release notes, for example.
2626
2727
* <b>Blog Entries</b>. Blog entries from developers describing the current
28
- state of a project, or rational for various design decisions, or
28
+ state of a project, or rational for various design decisions, or
2929
roadmaps for future development, can be entered as technotes.
3030
3131
* <b>Process Checkpoints</b>. For projects that have a formal process,
3232
technotes can be used to record the completion or the initiation of
3333
various process steps. For example, a technote can be used to record
@@ -49,11 +49,11 @@
4949
stay better organized and provide a better historical record of the
5050
development progress.
5151
5252
<h2>Viewing Technotes</h2>
5353
54
-Because technotes are considered a special kind of wiki,
54
+Because technotes are considered a special kind of wiki,
5555
users must have permission to read wiki in order read technotes.
5656
Enable the "j" permission under the /Setup/Users menu in order
5757
to give specific users or user classes the ability to view wiki
5858
and technotes.
5959
@@ -64,12 +64,12 @@
6464
6565
There is a hyperlink under the /wikihelp menu that can be used to create
6666
new technotes. And there is a submenu hyperlink on technote displays for
6767
editing existing technotes.
6868
69
-Users must have check-in privileges (permission "i") in order to
69
+Users must have check-in privileges (permission "i") in order to
7070
create or edit technotes. In addition, users must have create-wiki
7171
privilege (permission "f") to create new technotes and edit-wiki
7272
privilege (permission "k") in order to edit existing technotes.
7373
7474
Technote content may be formatted as [/wiki_rules | Fossil wiki],
7575
[/md_rules | Markdown], or a plain text.
7676
--- www/event.wiki
+++ www/event.wiki
@@ -23,11 +23,11 @@
23 can be something simple like "Version 1.2.3" perhaps with a bright
24 color background to draw attention to the entry and the wiki content
25 can contain release notes, for example.
26
27 * <b>Blog Entries</b>. Blog entries from developers describing the current
28 state of a project, or rational for various design decisions, or
29 roadmaps for future development, can be entered as technotes.
30
31 * <b>Process Checkpoints</b>. For projects that have a formal process,
32 technotes can be used to record the completion or the initiation of
33 various process steps. For example, a technote can be used to record
@@ -49,11 +49,11 @@
49 stay better organized and provide a better historical record of the
50 development progress.
51
52 <h2>Viewing Technotes</h2>
53
54 Because technotes are considered a special kind of wiki,
55 users must have permission to read wiki in order read technotes.
56 Enable the "j" permission under the /Setup/Users menu in order
57 to give specific users or user classes the ability to view wiki
58 and technotes.
59
@@ -64,12 +64,12 @@
64
65 There is a hyperlink under the /wikihelp menu that can be used to create
66 new technotes. And there is a submenu hyperlink on technote displays for
67 editing existing technotes.
68
69 Users must have check-in privileges (permission "i") in order to
70 create or edit technotes. In addition, users must have create-wiki
71 privilege (permission "f") to create new technotes and edit-wiki
72 privilege (permission "k") in order to edit existing technotes.
73
74 Technote content may be formatted as [/wiki_rules | Fossil wiki],
75 [/md_rules | Markdown], or a plain text.
76
--- www/event.wiki
+++ www/event.wiki
@@ -23,11 +23,11 @@
23 can be something simple like "Version 1.2.3" perhaps with a bright
24 color background to draw attention to the entry and the wiki content
25 can contain release notes, for example.
26
27 * <b>Blog Entries</b>. Blog entries from developers describing the current
28 state of a project, or rational for various design decisions, or
29 roadmaps for future development, can be entered as technotes.
30
31 * <b>Process Checkpoints</b>. For projects that have a formal process,
32 technotes can be used to record the completion or the initiation of
33 various process steps. For example, a technote can be used to record
@@ -49,11 +49,11 @@
49 stay better organized and provide a better historical record of the
50 development progress.
51
52 <h2>Viewing Technotes</h2>
53
54 Because technotes are considered a special kind of wiki,
55 users must have permission to read wiki in order read technotes.
56 Enable the "j" permission under the /Setup/Users menu in order
57 to give specific users or user classes the ability to view wiki
58 and technotes.
59
@@ -64,12 +64,12 @@
64
65 There is a hyperlink under the /wikihelp menu that can be used to create
66 new technotes. And there is a submenu hyperlink on technote displays for
67 editing existing technotes.
68
69 Users must have check-in privileges (permission "i") in order to
70 create or edit technotes. In addition, users must have create-wiki
71 privilege (permission "f") to create new technotes and edit-wiki
72 privilege (permission "k") in order to edit existing technotes.
73
74 Technote content may be formatted as [/wiki_rules | Fossil wiki],
75 [/md_rules | Markdown], or a plain text.
76
+5 -5
--- www/faq.wiki
+++ www/faq.wiki
@@ -62,12 +62,12 @@
6262
If you already have a fork in your check-in tree and you want to convert
6363
that fork to a branch, you can do this from the web interface.
6464
First locate the check-in that you want to be
6565
the initial check-in of your branch on the timeline and click on its
6666
link so that you are on the <b>ci</b> page. Then find the "<b>edit</b>"
67
-link (near the "Commands:" label) and click on that. On the
68
-"Edit Check-in" page, check the box beside "Branching:" and fill in
67
+link (near the "Commands:" label) and click on that. On the
68
+"Edit Check-in" page, check the box beside "Branching:" and fill in
6969
the name of your new branch to the right and press the "Apply Changes"
7070
button.</blockquote></li>
7171
7272
<a name="q4"></a>
7373
<p><b>(4) How do I tag a check-in?</b></p>
@@ -89,11 +89,11 @@
8989
9090
The CHECK-IN in the previous line can be any
9191
[./checkin_names.wiki | valid check-in name format].
9292
9393
You can also add (and remove) tags from a check-in using the
94
-[./webui.wiki | web interface]. First locate the check-in that you
94
+[./webui.wiki | web interface]. First locate the check-in that you
9595
what to tag on the timeline, then click on the link to go the detailed
9696
information page for that check-in. Then find the "<b>edit</b>"
9797
link (near the "Commands:" label) and click on that. There are
9898
controls on the edit page that allow new tags to be added and existing
9999
tags to be removed.</blockquote></li>
@@ -100,13 +100,13 @@
100100
101101
<a name="q5"></a>
102102
<p><b>(5) How do I create a private branch that won't get pushed back to the
103103
main repository.</b></p>
104104
105
-<blockquote>Use the <b>--private</b> command-line option on the
105
+<blockquote>Use the <b>--private</b> command-line option on the
106106
<b>commit</b> command. The result will be a check-in which exists on
107
-your local repository only and is never pushed to other repositories.
107
+your local repository only and is never pushed to other repositories.
108108
All descendants of a private check-in are also private.
109109
110110
Unless you specify something different using the <b>--branch</b> and/or
111111
<b>--bgcolor</b> options, the new private check-in will be put on a branch
112112
named "private" with an orange background color.
113113
--- www/faq.wiki
+++ www/faq.wiki
@@ -62,12 +62,12 @@
62 If you already have a fork in your check-in tree and you want to convert
63 that fork to a branch, you can do this from the web interface.
64 First locate the check-in that you want to be
65 the initial check-in of your branch on the timeline and click on its
66 link so that you are on the <b>ci</b> page. Then find the "<b>edit</b>"
67 link (near the "Commands:" label) and click on that. On the
68 "Edit Check-in" page, check the box beside "Branching:" and fill in
69 the name of your new branch to the right and press the "Apply Changes"
70 button.</blockquote></li>
71
72 <a name="q4"></a>
73 <p><b>(4) How do I tag a check-in?</b></p>
@@ -89,11 +89,11 @@
89
90 The CHECK-IN in the previous line can be any
91 [./checkin_names.wiki | valid check-in name format].
92
93 You can also add (and remove) tags from a check-in using the
94 [./webui.wiki | web interface]. First locate the check-in that you
95 what to tag on the timeline, then click on the link to go the detailed
96 information page for that check-in. Then find the "<b>edit</b>"
97 link (near the "Commands:" label) and click on that. There are
98 controls on the edit page that allow new tags to be added and existing
99 tags to be removed.</blockquote></li>
@@ -100,13 +100,13 @@
100
101 <a name="q5"></a>
102 <p><b>(5) How do I create a private branch that won't get pushed back to the
103 main repository.</b></p>
104
105 <blockquote>Use the <b>--private</b> command-line option on the
106 <b>commit</b> command. The result will be a check-in which exists on
107 your local repository only and is never pushed to other repositories.
108 All descendants of a private check-in are also private.
109
110 Unless you specify something different using the <b>--branch</b> and/or
111 <b>--bgcolor</b> options, the new private check-in will be put on a branch
112 named "private" with an orange background color.
113
--- www/faq.wiki
+++ www/faq.wiki
@@ -62,12 +62,12 @@
62 If you already have a fork in your check-in tree and you want to convert
63 that fork to a branch, you can do this from the web interface.
64 First locate the check-in that you want to be
65 the initial check-in of your branch on the timeline and click on its
66 link so that you are on the <b>ci</b> page. Then find the "<b>edit</b>"
67 link (near the "Commands:" label) and click on that. On the
68 "Edit Check-in" page, check the box beside "Branching:" and fill in
69 the name of your new branch to the right and press the "Apply Changes"
70 button.</blockquote></li>
71
72 <a name="q4"></a>
73 <p><b>(4) How do I tag a check-in?</b></p>
@@ -89,11 +89,11 @@
89
90 The CHECK-IN in the previous line can be any
91 [./checkin_names.wiki | valid check-in name format].
92
93 You can also add (and remove) tags from a check-in using the
94 [./webui.wiki | web interface]. First locate the check-in that you
95 what to tag on the timeline, then click on the link to go the detailed
96 information page for that check-in. Then find the "<b>edit</b>"
97 link (near the "Commands:" label) and click on that. There are
98 controls on the edit page that allow new tags to be added and existing
99 tags to be removed.</blockquote></li>
@@ -100,13 +100,13 @@
100
101 <a name="q5"></a>
102 <p><b>(5) How do I create a private branch that won't get pushed back to the
103 main repository.</b></p>
104
105 <blockquote>Use the <b>--private</b> command-line option on the
106 <b>commit</b> command. The result will be a check-in which exists on
107 your local repository only and is never pushed to other repositories.
108 All descendants of a private check-in are also private.
109
110 Unless you specify something different using the <b>--branch</b> and/or
111 <b>--bgcolor</b> options, the new private check-in will be put on a branch
112 named "private" with an orange background color.
113
--- www/fileformat.wiki
+++ www/fileformat.wiki
@@ -2,11 +2,11 @@
22
<h1 align="center">
33
Fossil File Formats
44
</h1>
55
66
The global state of a fossil repository is kept simple so that it can
7
-endure in useful form for decades or centuries.
7
+endure in useful form for decades or centuries.
88
A fossil repository is intended to be readable,
99
searchable, and extensible by people not yet born.
1010
1111
The global state of a fossil repository is an unordered
1212
set of <i>artifacts</i>.
@@ -14,11 +14,11 @@
1414
part of a trouble ticket, or one of several special control artifacts
1515
used to show the relationships between other artifacts within the
1616
project. Each artifact is normally represented on disk as a separate
1717
file. Artifacts can be text or binary.
1818
19
-In addition to the global state,
19
+In addition to the global state,
2020
each fossil repository also contains local state.
2121
The local state consists of web-page formatting
2222
preferences, authorized users, ticket display and reporting formats,
2323
and so forth. The global state is shared in common among all
2424
repositories for the same project, whereas the local state is often
@@ -30,11 +30,11 @@
3030
mentioned here in order to distinguish it from global state.
3131
3232
Each artifact in the repository is named by its SHA1 hash.
3333
No prefixes or meta information is added to an artifact before
3434
its hash is computed. The name of an artifact in the repository
35
-is exactly the same SHA1 hash that is computed by sha1sum
35
+is exactly the same SHA1 hash that is computed by sha1sum
3636
on the file as it exists in your source tree.</p>
3737
3838
Some artifacts have a particular format which gives them special
3939
meaning to fossil. Fossil recognizes:
4040
@@ -84,11 +84,11 @@
8484
Each card begins with a single
8585
character "card type". Zero or more arguments may follow
8686
the card type. All arguments are separated from each other
8787
and from the card-type character by a single space
8888
character. There is no surplus white space between arguments
89
-and no leading or trailing whitespace except for the newline
89
+and no leading or trailing whitespace except for the newline
9090
character that acts as the card separator.
9191
9292
All cards of the manifest occur in strict sorted lexicographical order.
9393
No card may be duplicated.
9494
The entire manifest may be PGP clear-signed, but otherwise it
@@ -114,18 +114,18 @@
114114
another manifest that serves as the "baseline" for this manifest. A
115115
manifest that has a B-card is called a delta-manifest and a manifest
116116
that omits the B-card is a baseline-manifest. The other manifest
117117
identified by the argument of the B-card must be a baseline-manifest.
118118
A baseline-manifest records the complete contents of a check-in.
119
-A delta-manifest records only changes from its baseline.
119
+A delta-manifest records only changes from its baseline.
120120
121121
A manifest must have exactly one C-card. The sole argument to
122122
the C-card is a check-in comment that describes the check-in that
123123
the manifest defines. The check-in comment is text. The following
124124
escape sequences are applied to the text:
125125
A space (ASCII 0x20) is represented as "\s" (ASCII 0x5C, 0x73). A
126
-newline (ASCII 0x0a) is "\n" (ASCII 0x5C, x6E). A backslash
126
+newline (ASCII 0x0a) is "\n" (ASCII 0x5C, x6E). A backslash
127127
(ASCII 0x5C) is represented as two backslashes "\\". Apart from
128128
space and newline, no other whitespace characters are allowed in
129129
the check-in comment. Nor are any unprintable characters allowed
130130
in the comment.
131131
@@ -167,11 +167,11 @@
167167
is used.
168168
169169
A manifest has zero or one P-cards. Most manifests have one P-card.
170170
The P-card has a varying number of arguments that
171171
define other manifests from which the current manifest
172
-is derived. Each argument is a 40-character lowercase
172
+is derived. Each argument is a 40-character lowercase
173173
hexadecimal SHA1 of a predecessor manifest. All arguments
174174
to the P-card must be unique within that card.
175175
The first argument is the SHA1 of the direct ancestor of the manifest.
176176
Other arguments define manifests with which the first was
177177
merged to yield the current manifest. Most manifests have
@@ -184,28 +184,28 @@
184184
whereas a P-card defines the immediate ancestor or a merge
185185
ancestor, the Q-card is used to identify a single check-in or a small
186186
range of check-ins which were cherry-picked for inclusion in or
187187
exclusion from the current manifest. The first argument of
188188
the Q-card is the artifact ID of another manifest (the "target")
189
-which has had its changes included or excluded in the current manifest.
189
+which has had its changes included or excluded in the current manifest.
190190
The target is preceded by "+" or "-" to show inclusion or
191191
exclusion, respectively. The optional second argument to the
192192
Q-card is another manifest artifact ID which is the "baseline"
193193
for the cherry-pick. If omitted, the baseline is the primary
194194
parent of the target. The
195195
changes included or excluded consist of all changes moving from
196
-the baseline to the target.
196
+the baseline to the target.
197197
198
-The Q-card was added to the interface specification on 2011-02-26.
198
+The Q-card was added to the interface specification on 2011-02-26.
199199
Older versions of Fossil will reject manifests that contain Q-cards.
200200
201201
A manifest may optionally have a single R-card. The R-card has
202
-a single argument which is the MD5 checksum of all files in
202
+a single argument which is the MD5 checksum of all files in
203203
the check-in except the manifest itself. The checksum is expressed
204204
as 32 characters of lowercase hexadecimal. The checksum is
205205
computed as follows: For each file in the check-in (except for
206
-the manifest itself) in strict sorted lexicographical order,
206
+the manifest itself) in strict sorted lexicographical order,
207207
take the pathname of the file relative to the root of the
208208
repository, append a single space (ASCII 0x20), the
209209
size of the file in ASCII decimal, a single newline
210210
character (ASCII 0x0A), and the complete text of the file.
211211
Compute the MD5 checksum of the result.
@@ -228,12 +228,12 @@
228228
is encoded using the same character escapes as is used for the
229229
check-in comment argument to the C-card.
230230
231231
A manifest must have a single Z-card as its last line. The argument
232232
to the Z-card is a 32-character lowercase hexadecimal MD5 hash
233
-of all prior lines of the manifest up to and including the newline
234
-character that immediately precedes the "Z". The Z-card is
233
+of all prior lines of the manifest up to and including the newline
234
+character that immediately precedes the "Z". The Z-card is
235235
a sanity check to prove that the manifest is well-formed and
236236
consistent.
237237
238238
A sample manifest from Fossil itself can be seen
239239
[/artifact/28987096ac | here].
@@ -240,11 +240,11 @@
240240
241241
<a name="cluster"></a>
242242
<h2>2.0 Clusters</h2>
243243
244244
A cluster is an artifact that declares the existence of other artifacts.
245
-Clusters are used during repository synchronization to help
245
+Clusters are used during repository synchronization to help
246246
reduce network traffic. As such, clusters are an optimization and
247247
may be removed from a repository without loss or damage to the
248248
underlying project code.
249249
250250
Clusters follow a syntax that is very similar to manifests.
@@ -252,15 +252,15 @@
252252
(ASCII 0x0a) separate the artifact into cards. Each card begins with a single
253253
character "card type". Zero or more arguments may follow
254254
the card type. All arguments are separated from each other
255255
and from the card-type character by a single space
256256
character. There is no surplus white space between arguments
257
-and no leading or trailing whitespace except for the newline
257
+and no leading or trailing whitespace except for the newline
258258
character that acts as the card separator.
259259
All cards of a cluster occur in strict sorted lexicographical order.
260260
No card may be duplicated.
261
-The cluster may not contain additional text or data beyond
261
+The cluster may not contain additional text or data beyond
262262
what is described here.
263263
Unlike manifests, clusters are never PGP signed.
264264
265265
Allowed cards in the cluster are as follows:
266266
@@ -268,11 +268,11 @@
268268
<b>M</b> <i>artifact-id</i><br />
269269
<b>Z</b> <i>checksum</i>
270270
</blockquote>
271271
272272
A cluster contains one or more "M" cards followed by a single "Z"
273
-card. Each M card has a single argument which is the artifact ID of
273
+card. Each M card has a single argument which is the artifact ID of
274274
another artifact in the repository. The Z card works exactly like
275275
the Z card of a manifest. The argument to the Z card is the
276276
lower-case hexadecimal representation of the MD5 checksum of all
277277
prior cards in the cluster. The Z-card is required.
278278
@@ -315,11 +315,11 @@
315315
first value is the tag name. The first character of the tag
316316
is either "+", "-", or "*". The "+" means the tag should be added
317317
to the artifact. The "-" means the tag should be removed.
318318
The "*" character means the tag should be added to the artifact
319319
and all direct descendants (but not descendants through a merge) down
320
-to but not including the first descendant that contains a
320
+to but not including the first descendant that contains a
321321
more recent "-", "*", or "+" tag with the same name.
322322
The optional third argument is the value of the tag. A tag
323323
without a value is a Boolean.
324324
325325
When two or more tags with the same name are applied to the
@@ -331,11 +331,11 @@
331331
for display purposes. The "user" tag overrides the name of the
332332
check-in user. The "date" tag overrides the check-in date.
333333
The "branch" tag sets the name of the branch that at check-in
334334
belongs to. Symbolic tags begin with the "sym-" prefix.
335335
336
-The U card is the name of the user that created the control
336
+The U card is the name of the user that created the control
337337
artifact. The Z card is the usual required artifact checksum.
338338
339339
An example control artifacts can be seen [/info/9d302ccda8 | here].
340340
341341
@@ -360,11 +360,11 @@
360360
361361
The D card is the date and time when the wiki page was edited.
362362
The P card specifies the parent wiki pages, if any. The L card
363363
gives the name of the wiki page. The optional N card specifies
364364
the mimetype of the wiki text. If the N card is omitted, the
365
-mimetype is assumed to be text/x-fossil-wiki.
365
+mimetype is assumed to be text/x-fossil-wiki.
366366
The U card specifies the login
367367
of the user who made this edit to the wiki page. The Z card is
368368
the usual checksum over the entire artifact and is required.
369369
370370
The W card is used to specify the text of the wiki page. The
@@ -405,11 +405,11 @@
405405
If the <i>value</i> parameter of the J card is omitted, then the
406406
field is set to an empty string.
407407
Each fossil server has a ticket configuration which specifies the fields its
408408
understands. The ticket configuration is part of the local state for
409409
the repository and thus can vary from one repository to another.
410
-Hence a J card might specify a <i>field</i> that do not exist in the
410
+Hence a J card might specify a <i>field</i> that do not exist in the
411411
local ticket configuration. If a J card specifies a <i>field</i> that
412412
is not in the local configuration, then that J card
413413
is simply ignored.
414414
415415
The first argument of the J card is the field name. The second
@@ -424,11 +424,11 @@
424424
425425
<a name="attachment"></a>
426426
<h2>6.0 Attachments</h2>
427427
428428
An attachment artifact associates some other artifact that is the
429
-attachment (the source artifact) with a ticket or wiki page or
429
+attachment (the source artifact) with a ticket or wiki page or
430430
technical note to which
431431
the attachment is connected (the target artifact).
432432
The following cards are allowed on an attachment artifact:
433433
434434
<blockquote>
@@ -441,11 +441,11 @@
441441
</blockquote>
442442
443443
The A card specifies a filename for the attachment in its first argument.
444444
The second argument to the A card is the name of the wiki page or
445445
ticket or technical note to which the attachment is connected. The
446
-third argument is either missing or else it is the 40-character artifact
446
+third argument is either missing or else it is the 40-character artifact
447447
ID of the attachment itself. A missing third argument means that the
448448
attachment should be deleted.
449449
450450
The C card is an optional comment describing what the attachment is about.
451451
The C card is optional, but there can only be one.
@@ -487,11 +487,11 @@
487487
</blockquote>
488488
489489
The C card contains text that is displayed on the timeline for the
490490
technote. The C card is optional, but there can only be one.
491491
492
-A single D card is required to give the date and time when the
492
+A single D card is required to give the date and time when the
493493
technote artifact was created. This is different from the time at which
494494
the technote appears on the timeline.
495495
496496
A single E card gives the time of the technote (the point on the timeline
497497
where the technote is displayed) and a unique identifier for the technote.
@@ -525,11 +525,11 @@
525525
display color for timelines.
526526
527527
The optional U card gives name of the user who entered the technote.
528528
529529
A single W card provides wiki text for the document associated with the
530
-technote. The format of the W card is exactly the same as for a
530
+technote. The format of the W card is exactly the same as for a
531531
[#wikichng | wiki artifact].
532532
533533
The Z card is the required checksum over the rest of the artifact.
534534
535535
536536
--- www/fileformat.wiki
+++ www/fileformat.wiki
@@ -2,11 +2,11 @@
2 <h1 align="center">
3 Fossil File Formats
4 </h1>
5
6 The global state of a fossil repository is kept simple so that it can
7 endure in useful form for decades or centuries.
8 A fossil repository is intended to be readable,
9 searchable, and extensible by people not yet born.
10
11 The global state of a fossil repository is an unordered
12 set of <i>artifacts</i>.
@@ -14,11 +14,11 @@
14 part of a trouble ticket, or one of several special control artifacts
15 used to show the relationships between other artifacts within the
16 project. Each artifact is normally represented on disk as a separate
17 file. Artifacts can be text or binary.
18
19 In addition to the global state,
20 each fossil repository also contains local state.
21 The local state consists of web-page formatting
22 preferences, authorized users, ticket display and reporting formats,
23 and so forth. The global state is shared in common among all
24 repositories for the same project, whereas the local state is often
@@ -30,11 +30,11 @@
30 mentioned here in order to distinguish it from global state.
31
32 Each artifact in the repository is named by its SHA1 hash.
33 No prefixes or meta information is added to an artifact before
34 its hash is computed. The name of an artifact in the repository
35 is exactly the same SHA1 hash that is computed by sha1sum
36 on the file as it exists in your source tree.</p>
37
38 Some artifacts have a particular format which gives them special
39 meaning to fossil. Fossil recognizes:
40
@@ -84,11 +84,11 @@
84 Each card begins with a single
85 character "card type". Zero or more arguments may follow
86 the card type. All arguments are separated from each other
87 and from the card-type character by a single space
88 character. There is no surplus white space between arguments
89 and no leading or trailing whitespace except for the newline
90 character that acts as the card separator.
91
92 All cards of the manifest occur in strict sorted lexicographical order.
93 No card may be duplicated.
94 The entire manifest may be PGP clear-signed, but otherwise it
@@ -114,18 +114,18 @@
114 another manifest that serves as the "baseline" for this manifest. A
115 manifest that has a B-card is called a delta-manifest and a manifest
116 that omits the B-card is a baseline-manifest. The other manifest
117 identified by the argument of the B-card must be a baseline-manifest.
118 A baseline-manifest records the complete contents of a check-in.
119 A delta-manifest records only changes from its baseline.
120
121 A manifest must have exactly one C-card. The sole argument to
122 the C-card is a check-in comment that describes the check-in that
123 the manifest defines. The check-in comment is text. The following
124 escape sequences are applied to the text:
125 A space (ASCII 0x20) is represented as "\s" (ASCII 0x5C, 0x73). A
126 newline (ASCII 0x0a) is "\n" (ASCII 0x5C, x6E). A backslash
127 (ASCII 0x5C) is represented as two backslashes "\\". Apart from
128 space and newline, no other whitespace characters are allowed in
129 the check-in comment. Nor are any unprintable characters allowed
130 in the comment.
131
@@ -167,11 +167,11 @@
167 is used.
168
169 A manifest has zero or one P-cards. Most manifests have one P-card.
170 The P-card has a varying number of arguments that
171 define other manifests from which the current manifest
172 is derived. Each argument is a 40-character lowercase
173 hexadecimal SHA1 of a predecessor manifest. All arguments
174 to the P-card must be unique within that card.
175 The first argument is the SHA1 of the direct ancestor of the manifest.
176 Other arguments define manifests with which the first was
177 merged to yield the current manifest. Most manifests have
@@ -184,28 +184,28 @@
184 whereas a P-card defines the immediate ancestor or a merge
185 ancestor, the Q-card is used to identify a single check-in or a small
186 range of check-ins which were cherry-picked for inclusion in or
187 exclusion from the current manifest. The first argument of
188 the Q-card is the artifact ID of another manifest (the "target")
189 which has had its changes included or excluded in the current manifest.
190 The target is preceded by "+" or "-" to show inclusion or
191 exclusion, respectively. The optional second argument to the
192 Q-card is another manifest artifact ID which is the "baseline"
193 for the cherry-pick. If omitted, the baseline is the primary
194 parent of the target. The
195 changes included or excluded consist of all changes moving from
196 the baseline to the target.
197
198 The Q-card was added to the interface specification on 2011-02-26.
199 Older versions of Fossil will reject manifests that contain Q-cards.
200
201 A manifest may optionally have a single R-card. The R-card has
202 a single argument which is the MD5 checksum of all files in
203 the check-in except the manifest itself. The checksum is expressed
204 as 32 characters of lowercase hexadecimal. The checksum is
205 computed as follows: For each file in the check-in (except for
206 the manifest itself) in strict sorted lexicographical order,
207 take the pathname of the file relative to the root of the
208 repository, append a single space (ASCII 0x20), the
209 size of the file in ASCII decimal, a single newline
210 character (ASCII 0x0A), and the complete text of the file.
211 Compute the MD5 checksum of the result.
@@ -228,12 +228,12 @@
228 is encoded using the same character escapes as is used for the
229 check-in comment argument to the C-card.
230
231 A manifest must have a single Z-card as its last line. The argument
232 to the Z-card is a 32-character lowercase hexadecimal MD5 hash
233 of all prior lines of the manifest up to and including the newline
234 character that immediately precedes the "Z". The Z-card is
235 a sanity check to prove that the manifest is well-formed and
236 consistent.
237
238 A sample manifest from Fossil itself can be seen
239 [/artifact/28987096ac | here].
@@ -240,11 +240,11 @@
240
241 <a name="cluster"></a>
242 <h2>2.0 Clusters</h2>
243
244 A cluster is an artifact that declares the existence of other artifacts.
245 Clusters are used during repository synchronization to help
246 reduce network traffic. As such, clusters are an optimization and
247 may be removed from a repository without loss or damage to the
248 underlying project code.
249
250 Clusters follow a syntax that is very similar to manifests.
@@ -252,15 +252,15 @@
252 (ASCII 0x0a) separate the artifact into cards. Each card begins with a single
253 character "card type". Zero or more arguments may follow
254 the card type. All arguments are separated from each other
255 and from the card-type character by a single space
256 character. There is no surplus white space between arguments
257 and no leading or trailing whitespace except for the newline
258 character that acts as the card separator.
259 All cards of a cluster occur in strict sorted lexicographical order.
260 No card may be duplicated.
261 The cluster may not contain additional text or data beyond
262 what is described here.
263 Unlike manifests, clusters are never PGP signed.
264
265 Allowed cards in the cluster are as follows:
266
@@ -268,11 +268,11 @@
268 <b>M</b> <i>artifact-id</i><br />
269 <b>Z</b> <i>checksum</i>
270 </blockquote>
271
272 A cluster contains one or more "M" cards followed by a single "Z"
273 card. Each M card has a single argument which is the artifact ID of
274 another artifact in the repository. The Z card works exactly like
275 the Z card of a manifest. The argument to the Z card is the
276 lower-case hexadecimal representation of the MD5 checksum of all
277 prior cards in the cluster. The Z-card is required.
278
@@ -315,11 +315,11 @@
315 first value is the tag name. The first character of the tag
316 is either "+", "-", or "*". The "+" means the tag should be added
317 to the artifact. The "-" means the tag should be removed.
318 The "*" character means the tag should be added to the artifact
319 and all direct descendants (but not descendants through a merge) down
320 to but not including the first descendant that contains a
321 more recent "-", "*", or "+" tag with the same name.
322 The optional third argument is the value of the tag. A tag
323 without a value is a Boolean.
324
325 When two or more tags with the same name are applied to the
@@ -331,11 +331,11 @@
331 for display purposes. The "user" tag overrides the name of the
332 check-in user. The "date" tag overrides the check-in date.
333 The "branch" tag sets the name of the branch that at check-in
334 belongs to. Symbolic tags begin with the "sym-" prefix.
335
336 The U card is the name of the user that created the control
337 artifact. The Z card is the usual required artifact checksum.
338
339 An example control artifacts can be seen [/info/9d302ccda8 | here].
340
341
@@ -360,11 +360,11 @@
360
361 The D card is the date and time when the wiki page was edited.
362 The P card specifies the parent wiki pages, if any. The L card
363 gives the name of the wiki page. The optional N card specifies
364 the mimetype of the wiki text. If the N card is omitted, the
365 mimetype is assumed to be text/x-fossil-wiki.
366 The U card specifies the login
367 of the user who made this edit to the wiki page. The Z card is
368 the usual checksum over the entire artifact and is required.
369
370 The W card is used to specify the text of the wiki page. The
@@ -405,11 +405,11 @@
405 If the <i>value</i> parameter of the J card is omitted, then the
406 field is set to an empty string.
407 Each fossil server has a ticket configuration which specifies the fields its
408 understands. The ticket configuration is part of the local state for
409 the repository and thus can vary from one repository to another.
410 Hence a J card might specify a <i>field</i> that do not exist in the
411 local ticket configuration. If a J card specifies a <i>field</i> that
412 is not in the local configuration, then that J card
413 is simply ignored.
414
415 The first argument of the J card is the field name. The second
@@ -424,11 +424,11 @@
424
425 <a name="attachment"></a>
426 <h2>6.0 Attachments</h2>
427
428 An attachment artifact associates some other artifact that is the
429 attachment (the source artifact) with a ticket or wiki page or
430 technical note to which
431 the attachment is connected (the target artifact).
432 The following cards are allowed on an attachment artifact:
433
434 <blockquote>
@@ -441,11 +441,11 @@
441 </blockquote>
442
443 The A card specifies a filename for the attachment in its first argument.
444 The second argument to the A card is the name of the wiki page or
445 ticket or technical note to which the attachment is connected. The
446 third argument is either missing or else it is the 40-character artifact
447 ID of the attachment itself. A missing third argument means that the
448 attachment should be deleted.
449
450 The C card is an optional comment describing what the attachment is about.
451 The C card is optional, but there can only be one.
@@ -487,11 +487,11 @@
487 </blockquote>
488
489 The C card contains text that is displayed on the timeline for the
490 technote. The C card is optional, but there can only be one.
491
492 A single D card is required to give the date and time when the
493 technote artifact was created. This is different from the time at which
494 the technote appears on the timeline.
495
496 A single E card gives the time of the technote (the point on the timeline
497 where the technote is displayed) and a unique identifier for the technote.
@@ -525,11 +525,11 @@
525 display color for timelines.
526
527 The optional U card gives name of the user who entered the technote.
528
529 A single W card provides wiki text for the document associated with the
530 technote. The format of the W card is exactly the same as for a
531 [#wikichng | wiki artifact].
532
533 The Z card is the required checksum over the rest of the artifact.
534
535
536
--- www/fileformat.wiki
+++ www/fileformat.wiki
@@ -2,11 +2,11 @@
2 <h1 align="center">
3 Fossil File Formats
4 </h1>
5
6 The global state of a fossil repository is kept simple so that it can
7 endure in useful form for decades or centuries.
8 A fossil repository is intended to be readable,
9 searchable, and extensible by people not yet born.
10
11 The global state of a fossil repository is an unordered
12 set of <i>artifacts</i>.
@@ -14,11 +14,11 @@
14 part of a trouble ticket, or one of several special control artifacts
15 used to show the relationships between other artifacts within the
16 project. Each artifact is normally represented on disk as a separate
17 file. Artifacts can be text or binary.
18
19 In addition to the global state,
20 each fossil repository also contains local state.
21 The local state consists of web-page formatting
22 preferences, authorized users, ticket display and reporting formats,
23 and so forth. The global state is shared in common among all
24 repositories for the same project, whereas the local state is often
@@ -30,11 +30,11 @@
30 mentioned here in order to distinguish it from global state.
31
32 Each artifact in the repository is named by its SHA1 hash.
33 No prefixes or meta information is added to an artifact before
34 its hash is computed. The name of an artifact in the repository
35 is exactly the same SHA1 hash that is computed by sha1sum
36 on the file as it exists in your source tree.</p>
37
38 Some artifacts have a particular format which gives them special
39 meaning to fossil. Fossil recognizes:
40
@@ -84,11 +84,11 @@
84 Each card begins with a single
85 character "card type". Zero or more arguments may follow
86 the card type. All arguments are separated from each other
87 and from the card-type character by a single space
88 character. There is no surplus white space between arguments
89 and no leading or trailing whitespace except for the newline
90 character that acts as the card separator.
91
92 All cards of the manifest occur in strict sorted lexicographical order.
93 No card may be duplicated.
94 The entire manifest may be PGP clear-signed, but otherwise it
@@ -114,18 +114,18 @@
114 another manifest that serves as the "baseline" for this manifest. A
115 manifest that has a B-card is called a delta-manifest and a manifest
116 that omits the B-card is a baseline-manifest. The other manifest
117 identified by the argument of the B-card must be a baseline-manifest.
118 A baseline-manifest records the complete contents of a check-in.
119 A delta-manifest records only changes from its baseline.
120
121 A manifest must have exactly one C-card. The sole argument to
122 the C-card is a check-in comment that describes the check-in that
123 the manifest defines. The check-in comment is text. The following
124 escape sequences are applied to the text:
125 A space (ASCII 0x20) is represented as "\s" (ASCII 0x5C, 0x73). A
126 newline (ASCII 0x0a) is "\n" (ASCII 0x5C, x6E). A backslash
127 (ASCII 0x5C) is represented as two backslashes "\\". Apart from
128 space and newline, no other whitespace characters are allowed in
129 the check-in comment. Nor are any unprintable characters allowed
130 in the comment.
131
@@ -167,11 +167,11 @@
167 is used.
168
169 A manifest has zero or one P-cards. Most manifests have one P-card.
170 The P-card has a varying number of arguments that
171 define other manifests from which the current manifest
172 is derived. Each argument is a 40-character lowercase
173 hexadecimal SHA1 of a predecessor manifest. All arguments
174 to the P-card must be unique within that card.
175 The first argument is the SHA1 of the direct ancestor of the manifest.
176 Other arguments define manifests with which the first was
177 merged to yield the current manifest. Most manifests have
@@ -184,28 +184,28 @@
184 whereas a P-card defines the immediate ancestor or a merge
185 ancestor, the Q-card is used to identify a single check-in or a small
186 range of check-ins which were cherry-picked for inclusion in or
187 exclusion from the current manifest. The first argument of
188 the Q-card is the artifact ID of another manifest (the "target")
189 which has had its changes included or excluded in the current manifest.
190 The target is preceded by "+" or "-" to show inclusion or
191 exclusion, respectively. The optional second argument to the
192 Q-card is another manifest artifact ID which is the "baseline"
193 for the cherry-pick. If omitted, the baseline is the primary
194 parent of the target. The
195 changes included or excluded consist of all changes moving from
196 the baseline to the target.
197
198 The Q-card was added to the interface specification on 2011-02-26.
199 Older versions of Fossil will reject manifests that contain Q-cards.
200
201 A manifest may optionally have a single R-card. The R-card has
202 a single argument which is the MD5 checksum of all files in
203 the check-in except the manifest itself. The checksum is expressed
204 as 32 characters of lowercase hexadecimal. The checksum is
205 computed as follows: For each file in the check-in (except for
206 the manifest itself) in strict sorted lexicographical order,
207 take the pathname of the file relative to the root of the
208 repository, append a single space (ASCII 0x20), the
209 size of the file in ASCII decimal, a single newline
210 character (ASCII 0x0A), and the complete text of the file.
211 Compute the MD5 checksum of the result.
@@ -228,12 +228,12 @@
228 is encoded using the same character escapes as is used for the
229 check-in comment argument to the C-card.
230
231 A manifest must have a single Z-card as its last line. The argument
232 to the Z-card is a 32-character lowercase hexadecimal MD5 hash
233 of all prior lines of the manifest up to and including the newline
234 character that immediately precedes the "Z". The Z-card is
235 a sanity check to prove that the manifest is well-formed and
236 consistent.
237
238 A sample manifest from Fossil itself can be seen
239 [/artifact/28987096ac | here].
@@ -240,11 +240,11 @@
240
241 <a name="cluster"></a>
242 <h2>2.0 Clusters</h2>
243
244 A cluster is an artifact that declares the existence of other artifacts.
245 Clusters are used during repository synchronization to help
246 reduce network traffic. As such, clusters are an optimization and
247 may be removed from a repository without loss or damage to the
248 underlying project code.
249
250 Clusters follow a syntax that is very similar to manifests.
@@ -252,15 +252,15 @@
252 (ASCII 0x0a) separate the artifact into cards. Each card begins with a single
253 character "card type". Zero or more arguments may follow
254 the card type. All arguments are separated from each other
255 and from the card-type character by a single space
256 character. There is no surplus white space between arguments
257 and no leading or trailing whitespace except for the newline
258 character that acts as the card separator.
259 All cards of a cluster occur in strict sorted lexicographical order.
260 No card may be duplicated.
261 The cluster may not contain additional text or data beyond
262 what is described here.
263 Unlike manifests, clusters are never PGP signed.
264
265 Allowed cards in the cluster are as follows:
266
@@ -268,11 +268,11 @@
268 <b>M</b> <i>artifact-id</i><br />
269 <b>Z</b> <i>checksum</i>
270 </blockquote>
271
272 A cluster contains one or more "M" cards followed by a single "Z"
273 card. Each M card has a single argument which is the artifact ID of
274 another artifact in the repository. The Z card works exactly like
275 the Z card of a manifest. The argument to the Z card is the
276 lower-case hexadecimal representation of the MD5 checksum of all
277 prior cards in the cluster. The Z-card is required.
278
@@ -315,11 +315,11 @@
315 first value is the tag name. The first character of the tag
316 is either "+", "-", or "*". The "+" means the tag should be added
317 to the artifact. The "-" means the tag should be removed.
318 The "*" character means the tag should be added to the artifact
319 and all direct descendants (but not descendants through a merge) down
320 to but not including the first descendant that contains a
321 more recent "-", "*", or "+" tag with the same name.
322 The optional third argument is the value of the tag. A tag
323 without a value is a Boolean.
324
325 When two or more tags with the same name are applied to the
@@ -331,11 +331,11 @@
331 for display purposes. The "user" tag overrides the name of the
332 check-in user. The "date" tag overrides the check-in date.
333 The "branch" tag sets the name of the branch that at check-in
334 belongs to. Symbolic tags begin with the "sym-" prefix.
335
336 The U card is the name of the user that created the control
337 artifact. The Z card is the usual required artifact checksum.
338
339 An example control artifacts can be seen [/info/9d302ccda8 | here].
340
341
@@ -360,11 +360,11 @@
360
361 The D card is the date and time when the wiki page was edited.
362 The P card specifies the parent wiki pages, if any. The L card
363 gives the name of the wiki page. The optional N card specifies
364 the mimetype of the wiki text. If the N card is omitted, the
365 mimetype is assumed to be text/x-fossil-wiki.
366 The U card specifies the login
367 of the user who made this edit to the wiki page. The Z card is
368 the usual checksum over the entire artifact and is required.
369
370 The W card is used to specify the text of the wiki page. The
@@ -405,11 +405,11 @@
405 If the <i>value</i> parameter of the J card is omitted, then the
406 field is set to an empty string.
407 Each fossil server has a ticket configuration which specifies the fields its
408 understands. The ticket configuration is part of the local state for
409 the repository and thus can vary from one repository to another.
410 Hence a J card might specify a <i>field</i> that do not exist in the
411 local ticket configuration. If a J card specifies a <i>field</i> that
412 is not in the local configuration, then that J card
413 is simply ignored.
414
415 The first argument of the J card is the field name. The second
@@ -424,11 +424,11 @@
424
425 <a name="attachment"></a>
426 <h2>6.0 Attachments</h2>
427
428 An attachment artifact associates some other artifact that is the
429 attachment (the source artifact) with a ticket or wiki page or
430 technical note to which
431 the attachment is connected (the target artifact).
432 The following cards are allowed on an attachment artifact:
433
434 <blockquote>
@@ -441,11 +441,11 @@
441 </blockquote>
442
443 The A card specifies a filename for the attachment in its first argument.
444 The second argument to the A card is the name of the wiki page or
445 ticket or technical note to which the attachment is connected. The
446 third argument is either missing or else it is the 40-character artifact
447 ID of the attachment itself. A missing third argument means that the
448 attachment should be deleted.
449
450 The C card is an optional comment describing what the attachment is about.
451 The C card is optional, but there can only be one.
@@ -487,11 +487,11 @@
487 </blockquote>
488
489 The C card contains text that is displayed on the timeline for the
490 technote. The C card is optional, but there can only be one.
491
492 A single D card is required to give the date and time when the
493 technote artifact was created. This is different from the time at which
494 the technote appears on the timeline.
495
496 A single E card gives the time of the technote (the point on the timeline
497 where the technote is displayed) and a unique identifier for the technote.
@@ -525,11 +525,11 @@
525 display color for timelines.
526
527 The optional U card gives name of the user who entered the technote.
528
529 A single W card provides wiki text for the document associated with the
530 technote. The format of the W card is exactly the same as for a
531 [#wikichng | wiki artifact].
532
533 The Z card is the required checksum over the rest of the artifact.
534
535
536
--- www/fiveminutes.wiki
+++ www/fiveminutes.wiki
@@ -4,65 +4,65 @@
44
The following document was contributed by Gilles Ganault on 2013-01-08.
55
</i></b>
66
</p><hr>
77
88
<h1>Up and running in 5 minutes as a single user</h1>
9
-<p>This short document explains the main basic Fossil commands for a single
10
-user, i.e. with no additional users, with no need to synchronize with some remote
9
+<p>This short document explains the main basic Fossil commands for a single
10
+user, i.e. with no additional users, with no need to synchronize with some remote
1111
repository, and no need for branching/forking.</p>
1212
1313
<h2>Create a new repository</h2>
1414
<p>fossil new c:\test.repo</p>
15
-<p>This will create the new SQLite binary file that holds the repository, i.e.
16
-files, tickets, wiki, etc. It can be located anywhere, although it's considered
17
-best practice to keep it outside the work directory where you will work on files
15
+<p>This will create the new SQLite binary file that holds the repository, i.e.
16
+files, tickets, wiki, etc. It can be located anywhere, although it's considered
17
+best practice to keep it outside the work directory where you will work on files
1818
after they've been checked out of the repository.</p>
1919
2020
<h2>Open the repository</h2>
2121
<p>cd c:\temp\test.fossil</p>
2222
<p>fossil open c:\test.repo</p>
23
-<p>This will check out the last revision of all the files in the repository,
24
-if any, into the current work directory. In addition, it will create a binary
23
+<p>This will check out the last revision of all the files in the repository,
24
+if any, into the current work directory. In addition, it will create a binary
2525
file _FOSSIL_ to keep track of changes (on non-Windows systems it is called
2626
<tt>.fslckout</tt>).</p>
2727
2828
<h2>Add new files</h2>
2929
<p>fossil add .</p>
30
-<p>To tell Fossil to add new files to the repository. The files aren't actually
31
-added until you run &quot;commit&quot;. When using &quot;.&quot;, it tells Fossil
32
-to add all the files in the current directory recursively, i.e. including all
30
+<p>To tell Fossil to add new files to the repository. The files aren't actually
31
+added until you run &quot;commit&quot;. When using &quot;.&quot;, it tells Fossil
32
+to add all the files in the current directory recursively, i.e. including all
3333
the files in all the subdirectories.</p>
3434
<p>Note: To tell Fossil to ignore some extensions:</p>
3535
<p>fossil settings ignore-glob &quot;*.o,*.obj,*.exe&quot; --global</p>
3636
3737
<h2>Remove files that haven't been committed yet</h2>
3838
<p>fossil delete myfile.c</p>
39
-<p>This will simply remove the item from the list of files that were previously
39
+<p>This will simply remove the item from the list of files that were previously
4040
added through &quot;fossil add&quot;.</p>
4141
4242
<h2>Check current status</h2>
4343
<p>fossil changes</p>
44
-<p>This shows the list of changes that have been done and will be committed the
45
-next time you run &quot;fossil commit&quot;. It's a useful command to run before
44
+<p>This shows the list of changes that have been done and will be committed the
45
+next time you run &quot;fossil commit&quot;. It's a useful command to run before
4646
running &quot;fossil commit&quot; just to check that things are OK before proceeding.</p>
4747
4848
<h2>Commit changes</h2>
49
-<p>To actually apply the pending changes to the repository, e.g. new files marked
50
-for addition, checked-out files that have been edited and must be checked-in,
49
+<p>To actually apply the pending changes to the repository, e.g. new files marked
50
+for addition, checked-out files that have been edited and must be checked-in,
5151
etc.</p>
5252
5353
<p>fossil commit -m "Added stuff"</p>
5454
5555
If no file names are provided on the command-line then all changes will be checked in,
5656
otherwise just the listed file(s) will be checked in.
5757
5858
<h2>Compare two revisions of a file</h2>
59
-<p>If you wish to compare the last revision of a file and its checked out version
59
+<p>If you wish to compare the last revision of a file and its checked out version
6060
in your work directory:</p>
6161
<p>fossil gdiff myfile.c</p>
6262
<p>If you wish to compare two different revisions of a file in the repository:</p>
63
-<p>fossil finfo myfile: Note the first hash, which is the UUID of the commit
63
+<p>fossil finfo myfile: Note the first hash, which is the UUID of the commit
6464
when the file was committed</p>
6565
<p>fossil gdiff --from UUID#1 --to UUID#2 myfile.c</p>
6666
<h2>Cancel changes and go back to previous revision</h2>
6767
<p>fossil revert myfile.c</p>
6868
<p>Fossil does not prompt when reverting a file. It simply reminds the user about the
@@ -69,8 +69,8 @@
6969
"undo" command, just in case the revert was a mistake.</p>
7070
7171
7272
<h2>Close the repository</h2>
7373
<p>fossil close</p>
74
-<p>This will simply remove the _FOSSIL_ at the root of the work directory but
75
-will not delete the files in the work directory. From then on, any use of &quot;fossil&quot;
74
+<p>This will simply remove the _FOSSIL_ at the root of the work directory but
75
+will not delete the files in the work directory. From then on, any use of &quot;fossil&quot;
7676
will trigger an error since there is no longer any connection.</p>
7777
--- www/fiveminutes.wiki
+++ www/fiveminutes.wiki
@@ -4,65 +4,65 @@
4 The following document was contributed by Gilles Ganault on 2013-01-08.
5 </i></b>
6 </p><hr>
7
8 <h1>Up and running in 5 minutes as a single user</h1>
9 <p>This short document explains the main basic Fossil commands for a single
10 user, i.e. with no additional users, with no need to synchronize with some remote
11 repository, and no need for branching/forking.</p>
12
13 <h2>Create a new repository</h2>
14 <p>fossil new c:\test.repo</p>
15 <p>This will create the new SQLite binary file that holds the repository, i.e.
16 files, tickets, wiki, etc. It can be located anywhere, although it's considered
17 best practice to keep it outside the work directory where you will work on files
18 after they've been checked out of the repository.</p>
19
20 <h2>Open the repository</h2>
21 <p>cd c:\temp\test.fossil</p>
22 <p>fossil open c:\test.repo</p>
23 <p>This will check out the last revision of all the files in the repository,
24 if any, into the current work directory. In addition, it will create a binary
25 file _FOSSIL_ to keep track of changes (on non-Windows systems it is called
26 <tt>.fslckout</tt>).</p>
27
28 <h2>Add new files</h2>
29 <p>fossil add .</p>
30 <p>To tell Fossil to add new files to the repository. The files aren't actually
31 added until you run &quot;commit&quot;. When using &quot;.&quot;, it tells Fossil
32 to add all the files in the current directory recursively, i.e. including all
33 the files in all the subdirectories.</p>
34 <p>Note: To tell Fossil to ignore some extensions:</p>
35 <p>fossil settings ignore-glob &quot;*.o,*.obj,*.exe&quot; --global</p>
36
37 <h2>Remove files that haven't been committed yet</h2>
38 <p>fossil delete myfile.c</p>
39 <p>This will simply remove the item from the list of files that were previously
40 added through &quot;fossil add&quot;.</p>
41
42 <h2>Check current status</h2>
43 <p>fossil changes</p>
44 <p>This shows the list of changes that have been done and will be committed the
45 next time you run &quot;fossil commit&quot;. It's a useful command to run before
46 running &quot;fossil commit&quot; just to check that things are OK before proceeding.</p>
47
48 <h2>Commit changes</h2>
49 <p>To actually apply the pending changes to the repository, e.g. new files marked
50 for addition, checked-out files that have been edited and must be checked-in,
51 etc.</p>
52
53 <p>fossil commit -m "Added stuff"</p>
54
55 If no file names are provided on the command-line then all changes will be checked in,
56 otherwise just the listed file(s) will be checked in.
57
58 <h2>Compare two revisions of a file</h2>
59 <p>If you wish to compare the last revision of a file and its checked out version
60 in your work directory:</p>
61 <p>fossil gdiff myfile.c</p>
62 <p>If you wish to compare two different revisions of a file in the repository:</p>
63 <p>fossil finfo myfile: Note the first hash, which is the UUID of the commit
64 when the file was committed</p>
65 <p>fossil gdiff --from UUID#1 --to UUID#2 myfile.c</p>
66 <h2>Cancel changes and go back to previous revision</h2>
67 <p>fossil revert myfile.c</p>
68 <p>Fossil does not prompt when reverting a file. It simply reminds the user about the
@@ -69,8 +69,8 @@
69 "undo" command, just in case the revert was a mistake.</p>
70
71
72 <h2>Close the repository</h2>
73 <p>fossil close</p>
74 <p>This will simply remove the _FOSSIL_ at the root of the work directory but
75 will not delete the files in the work directory. From then on, any use of &quot;fossil&quot;
76 will trigger an error since there is no longer any connection.</p>
77
--- www/fiveminutes.wiki
+++ www/fiveminutes.wiki
@@ -4,65 +4,65 @@
4 The following document was contributed by Gilles Ganault on 2013-01-08.
5 </i></b>
6 </p><hr>
7
8 <h1>Up and running in 5 minutes as a single user</h1>
9 <p>This short document explains the main basic Fossil commands for a single
10 user, i.e. with no additional users, with no need to synchronize with some remote
11 repository, and no need for branching/forking.</p>
12
13 <h2>Create a new repository</h2>
14 <p>fossil new c:\test.repo</p>
15 <p>This will create the new SQLite binary file that holds the repository, i.e.
16 files, tickets, wiki, etc. It can be located anywhere, although it's considered
17 best practice to keep it outside the work directory where you will work on files
18 after they've been checked out of the repository.</p>
19
20 <h2>Open the repository</h2>
21 <p>cd c:\temp\test.fossil</p>
22 <p>fossil open c:\test.repo</p>
23 <p>This will check out the last revision of all the files in the repository,
24 if any, into the current work directory. In addition, it will create a binary
25 file _FOSSIL_ to keep track of changes (on non-Windows systems it is called
26 <tt>.fslckout</tt>).</p>
27
28 <h2>Add new files</h2>
29 <p>fossil add .</p>
30 <p>To tell Fossil to add new files to the repository. The files aren't actually
31 added until you run &quot;commit&quot;. When using &quot;.&quot;, it tells Fossil
32 to add all the files in the current directory recursively, i.e. including all
33 the files in all the subdirectories.</p>
34 <p>Note: To tell Fossil to ignore some extensions:</p>
35 <p>fossil settings ignore-glob &quot;*.o,*.obj,*.exe&quot; --global</p>
36
37 <h2>Remove files that haven't been committed yet</h2>
38 <p>fossil delete myfile.c</p>
39 <p>This will simply remove the item from the list of files that were previously
40 added through &quot;fossil add&quot;.</p>
41
42 <h2>Check current status</h2>
43 <p>fossil changes</p>
44 <p>This shows the list of changes that have been done and will be committed the
45 next time you run &quot;fossil commit&quot;. It's a useful command to run before
46 running &quot;fossil commit&quot; just to check that things are OK before proceeding.</p>
47
48 <h2>Commit changes</h2>
49 <p>To actually apply the pending changes to the repository, e.g. new files marked
50 for addition, checked-out files that have been edited and must be checked-in,
51 etc.</p>
52
53 <p>fossil commit -m "Added stuff"</p>
54
55 If no file names are provided on the command-line then all changes will be checked in,
56 otherwise just the listed file(s) will be checked in.
57
58 <h2>Compare two revisions of a file</h2>
59 <p>If you wish to compare the last revision of a file and its checked out version
60 in your work directory:</p>
61 <p>fossil gdiff myfile.c</p>
62 <p>If you wish to compare two different revisions of a file in the repository:</p>
63 <p>fossil finfo myfile: Note the first hash, which is the UUID of the commit
64 when the file was committed</p>
65 <p>fossil gdiff --from UUID#1 --to UUID#2 myfile.c</p>
66 <h2>Cancel changes and go back to previous revision</h2>
67 <p>fossil revert myfile.c</p>
68 <p>Fossil does not prompt when reverting a file. It simply reminds the user about the
@@ -69,8 +69,8 @@
69 "undo" command, just in case the revert was a mistake.</p>
70
71
72 <h2>Close the repository</h2>
73 <p>fossil close</p>
74 <p>This will simply remove the _FOSSIL_ at the root of the work directory but
75 will not delete the files in the work directory. From then on, any use of &quot;fossil&quot;
76 will trigger an error since there is no longer any connection.</p>
77
--- www/foss-cklist.wiki
+++ www/foss-cklist.wiki
@@ -89,11 +89,11 @@
8989
9090
<li><p>The project has a website.
9191
9292
<li><p>Release version numbers are in the traditional X.Y or X.Y.Z format.
9393
94
-<li><p>Releases can be downloaded as tarball using
94
+<li><p>Releases can be downloaded as tarball using
9595
gzip or bzip2 compression.
9696
9797
<li><p>Releases unpack into a versioned top-level directory.
9898
(ex: "projectname-1.2.3/").
9999
@@ -102,12 +102,12 @@
102102
tarball.
103103
104104
<li><p>There are no incompatible licenses in the code.
105105
106106
<li><p>The project has not been blithely proclaimed "public domain" without
107
-having gone through the tedious and exacting legal steps to actually put it
107
+having gone through the tedious and exacting legal steps to actually put it
108108
in the public domain.
109109
110110
<li><p>There is an accurate change log in the code and on the website.
111111
112112
<li><p>There is documentation in the code and on the website.
113113
</ol>
114114
--- www/foss-cklist.wiki
+++ www/foss-cklist.wiki
@@ -89,11 +89,11 @@
89
90 <li><p>The project has a website.
91
92 <li><p>Release version numbers are in the traditional X.Y or X.Y.Z format.
93
94 <li><p>Releases can be downloaded as tarball using
95 gzip or bzip2 compression.
96
97 <li><p>Releases unpack into a versioned top-level directory.
98 (ex: "projectname-1.2.3/").
99
@@ -102,12 +102,12 @@
102 tarball.
103
104 <li><p>There are no incompatible licenses in the code.
105
106 <li><p>The project has not been blithely proclaimed "public domain" without
107 having gone through the tedious and exacting legal steps to actually put it
108 in the public domain.
109
110 <li><p>There is an accurate change log in the code and on the website.
111
112 <li><p>There is documentation in the code and on the website.
113 </ol>
114
--- www/foss-cklist.wiki
+++ www/foss-cklist.wiki
@@ -89,11 +89,11 @@
89
90 <li><p>The project has a website.
91
92 <li><p>Release version numbers are in the traditional X.Y or X.Y.Z format.
93
94 <li><p>Releases can be downloaded as tarball using
95 gzip or bzip2 compression.
96
97 <li><p>Releases unpack into a versioned top-level directory.
98 (ex: "projectname-1.2.3/").
99
@@ -102,12 +102,12 @@
102 tarball.
103
104 <li><p>There are no incompatible licenses in the code.
105
106 <li><p>The project has not been blithely proclaimed "public domain" without
107 having gone through the tedious and exacting legal steps to actually put it
108 in the public domain.
109
110 <li><p>There is an accurate change log in the code and on the website.
111
112 <li><p>There is documentation in the code and on the website.
113 </ol>
114
--- www/fossil-from-msvc.wiki
+++ www/fossil-from-msvc.wiki
@@ -11,41 +11,41 @@
1111
<li>Tools &gt; External Tools, where the items in this list map
1212
to "External Tool X" that we'll add to our own Fossil
1313
menu later: </li>
1414
<ol type="1">
1515
<li>Rename the default "&#91;New Tool 1&#93;" to eg.
16
- "Commit"&nbsp;&nbsp;&nbsp;2.
16
+ "Commit"&nbsp;&nbsp;&nbsp;2.
1717
</li>
1818
<li>Change Command to where Fossil is located eg.
1919
"c:\fossil.exe"</li>
2020
<li>Change Arguments to the required command, eg.
21
- "commit -m".
21
+ "commit -m".
2222
The user will be prompted to type the comment that Commit expects</li>
23
- <li>Set "Initial Directory" to point it to the work directory
23
+ <li>Set "Initial Directory" to point it to the work directory
2424
where the source files are currently checked out
2525
by Fossil (eg. c:\Workspace). It's also possible to use system
2626
variables such as "$(ProjectDir)" instead of hard-coding the path</li>
2727
<li>Check "Prompt for arguments", since Commit
2828
requires typing a comment. Useless for commands like Changes
2929
that don't require arguments</li>
30
- <li>Uncheck "Close on Exit", so we can see what Fossil says
31
- before closing the DOS box. Note that "Use Output Window"
32
- will display the output in a child window within the IDE instead of
30
+ <li>Uncheck "Close on Exit", so we can see what Fossil says
31
+ before closing the DOS box. Note that "Use Output Window"
32
+ will display the output in a child window within the IDE instead of
3333
opening a DOS box</li>
3434
<li>Click on OK</li>
3535
</ol>
3636
<li>Tools &gt; Customize &gt; Commands</li>
3737
<ol type="1">
38
- <li>With "Menu bar = Menu Bar" selected, click on "Add
38
+ <li>With "Menu bar = Menu Bar" selected, click on "Add
3939
New Menu". A new "Fossil" menu is displayed in the
4040
IDE's menu bar</li>
4141
<li>Click on "Modify Selection" to rename it
4242
"Fossil", and...</li>
4343
<li>Use the "Move Down" button to move it lower in
4444
the list</li>
4545
</ol>
46
- <li>Still in Customize dialog: In the "Menu bar" combo, select
47
- the new Fossil menu you just created, and Click on "Add Command...":
48
- From Categories, select Tools, and select "External Command 1".
49
- Click on Close. It's unfortunate that the IDE doesn't say which command
46
+ <li>Still in Customize dialog: In the "Menu bar" combo, select
47
+ the new Fossil menu you just created, and Click on "Add Command...":
48
+ From Categories, select Tools, and select "External Command 1".
49
+ Click on Close. It's unfortunate that the IDE doesn't say which command
5050
maps to "External Command X".</li>
5151
</ol>
5252
--- www/fossil-from-msvc.wiki
+++ www/fossil-from-msvc.wiki
@@ -11,41 +11,41 @@
11 <li>Tools &gt; External Tools, where the items in this list map
12 to "External Tool X" that we'll add to our own Fossil
13 menu later: </li>
14 <ol type="1">
15 <li>Rename the default "&#91;New Tool 1&#93;" to eg.
16 "Commit"&nbsp;&nbsp;&nbsp;2.
17 </li>
18 <li>Change Command to where Fossil is located eg.
19 "c:\fossil.exe"</li>
20 <li>Change Arguments to the required command, eg.
21 "commit -m".
22 The user will be prompted to type the comment that Commit expects</li>
23 <li>Set "Initial Directory" to point it to the work directory
24 where the source files are currently checked out
25 by Fossil (eg. c:\Workspace). It's also possible to use system
26 variables such as "$(ProjectDir)" instead of hard-coding the path</li>
27 <li>Check "Prompt for arguments", since Commit
28 requires typing a comment. Useless for commands like Changes
29 that don't require arguments</li>
30 <li>Uncheck "Close on Exit", so we can see what Fossil says
31 before closing the DOS box. Note that "Use Output Window"
32 will display the output in a child window within the IDE instead of
33 opening a DOS box</li>
34 <li>Click on OK</li>
35 </ol>
36 <li>Tools &gt; Customize &gt; Commands</li>
37 <ol type="1">
38 <li>With "Menu bar = Menu Bar" selected, click on "Add
39 New Menu". A new "Fossil" menu is displayed in the
40 IDE's menu bar</li>
41 <li>Click on "Modify Selection" to rename it
42 "Fossil", and...</li>
43 <li>Use the "Move Down" button to move it lower in
44 the list</li>
45 </ol>
46 <li>Still in Customize dialog: In the "Menu bar" combo, select
47 the new Fossil menu you just created, and Click on "Add Command...":
48 From Categories, select Tools, and select "External Command 1".
49 Click on Close. It's unfortunate that the IDE doesn't say which command
50 maps to "External Command X".</li>
51 </ol>
52
--- www/fossil-from-msvc.wiki
+++ www/fossil-from-msvc.wiki
@@ -11,41 +11,41 @@
11 <li>Tools &gt; External Tools, where the items in this list map
12 to "External Tool X" that we'll add to our own Fossil
13 menu later: </li>
14 <ol type="1">
15 <li>Rename the default "&#91;New Tool 1&#93;" to eg.
16 "Commit"&nbsp;&nbsp;&nbsp;2.
17 </li>
18 <li>Change Command to where Fossil is located eg.
19 "c:\fossil.exe"</li>
20 <li>Change Arguments to the required command, eg.
21 "commit -m".
22 The user will be prompted to type the comment that Commit expects</li>
23 <li>Set "Initial Directory" to point it to the work directory
24 where the source files are currently checked out
25 by Fossil (eg. c:\Workspace). It's also possible to use system
26 variables such as "$(ProjectDir)" instead of hard-coding the path</li>
27 <li>Check "Prompt for arguments", since Commit
28 requires typing a comment. Useless for commands like Changes
29 that don't require arguments</li>
30 <li>Uncheck "Close on Exit", so we can see what Fossil says
31 before closing the DOS box. Note that "Use Output Window"
32 will display the output in a child window within the IDE instead of
33 opening a DOS box</li>
34 <li>Click on OK</li>
35 </ol>
36 <li>Tools &gt; Customize &gt; Commands</li>
37 <ol type="1">
38 <li>With "Menu bar = Menu Bar" selected, click on "Add
39 New Menu". A new "Fossil" menu is displayed in the
40 IDE's menu bar</li>
41 <li>Click on "Modify Selection" to rename it
42 "Fossil", and...</li>
43 <li>Use the "Move Down" button to move it lower in
44 the list</li>
45 </ol>
46 <li>Still in Customize dialog: In the "Menu bar" combo, select
47 the new Fossil menu you just created, and Click on "Add Command...":
48 From Categories, select Tools, and select "External Command 1".
49 Click on Close. It's unfortunate that the IDE doesn't say which command
50 maps to "External Command X".</li>
51 </ol>
52
+1 -1
--- www/index.wiki
+++ www/index.wiki
@@ -38,11 +38,11 @@
3838
([./webpage-ex.md|examples]) designed to promote situational awareness.
3939
4040
This entire website is just a running instance of Fossil.
4141
The pages you see here are all [./wikitheory.wiki | wiki] or
4242
[./embeddeddoc.wiki | embedded documentation] or (in the case of
43
- the [/uv/download.html|download] page)
43
+ the [/uv/download.html|download] page)
4444
[./unvers.wiki | unversioned files].
4545
When you clone Fossil from one of its
4646
[./selfhost.wiki | self-hosting repositories],
4747
you get more than just source code - you get this entire website.
4848
4949
--- www/index.wiki
+++ www/index.wiki
@@ -38,11 +38,11 @@
38 ([./webpage-ex.md|examples]) designed to promote situational awareness.
39
40 This entire website is just a running instance of Fossil.
41 The pages you see here are all [./wikitheory.wiki | wiki] or
42 [./embeddeddoc.wiki | embedded documentation] or (in the case of
43 the [/uv/download.html|download] page)
44 [./unvers.wiki | unversioned files].
45 When you clone Fossil from one of its
46 [./selfhost.wiki | self-hosting repositories],
47 you get more than just source code - you get this entire website.
48
49
--- www/index.wiki
+++ www/index.wiki
@@ -38,11 +38,11 @@
38 ([./webpage-ex.md|examples]) designed to promote situational awareness.
39
40 This entire website is just a running instance of Fossil.
41 The pages you see here are all [./wikitheory.wiki | wiki] or
42 [./embeddeddoc.wiki | embedded documentation] or (in the case of
43 the [/uv/download.html|download] page)
44 [./unvers.wiki | unversioned files].
45 When you clone Fossil from one of its
46 [./selfhost.wiki | self-hosting repositories],
47 you get more than just source code - you get this entire website.
48
49
+54 -15
--- www/inout.wiki
+++ www/inout.wiki
@@ -1,10 +1,10 @@
11
<title>Import And Export</title>
22
3
-Fossil has the ability to import and export repositories from and to
3
+Fossil has the ability to import and export repositories from and to
44
[http://git-scm.com/ | Git]. And since most other version control
5
-systems will also import/export from Git, that means that you can
5
+systems will also import/export from Git, that means that you can
66
import/export a Fossil repository to most version control systems using
77
Git as an intermediary.
88
99
<h2>Git → Fossil</h2>
1010
@@ -20,11 +20,11 @@
2020
command is the name of a new Fossil repository that is created to hold the Git
2121
content.
2222
2323
The --git option is not actually required. The git-fast-export file format
2424
is currently the only VCS interchange format that Fossil understands. But
25
-future versions of Fossil might be enhanced to understand other VCS
25
+future versions of Fossil might be enhanced to understand other VCS
2626
interchange formats, and so for compatibility, use of the
2727
--git option is recommended.
2828
2929
<h2>Fossil → Git</h2>
3030
@@ -43,21 +43,60 @@
4343
Note that the "fossil export --git" command only exports the versioned files.
4444
Tickets and wiki and events are not exported, since Git does not understand
4545
those concepts.
4646
4747
As with the "import" command, the --git option is not required
48
-since the git-fast-export file format is currently the only VCS interchange
48
+since the git-fast-export file format is currently the only VCS interchange
4949
format that Fossil will generate. However,
5050
future versions of Fossil might add the ability to generate other
51
-VCS interchange formats, and so for compatibility, the use of the --git
51
+VCS interchange formats, and so for compatibility, the use of the --git
5252
option recommended.
5353
54
-An anonymous user sends this comment:
55
-
56
-<blockquote>
57
-The main Fossil branch is called "trunk", while the main git branch is
58
-called "master". After you've exported your FOSSIL repo to git, you won't
59
-see any files and gitk will complain about a missing "HEAD". You can
60
-resolve this problem by merging "trunk" with "master"
61
-(first verify using git status that you are on the "master" branch):
62
-<tt>git merge trunk</tt>
63
-</blockquote>
54
+<h2>Bidirectional Synchronization</h2>
55
+Fossil also has the ability to synchronize with a Git repository via repeated
56
+imports and/or exports. To do this, it uses marks files to store a record of
57
+artifacts which are known by both Git and Fossil to exist at a given point in
58
+time.
59
+
60
+To illustrate, consider the example of a remote Fossil repository that a
61
+user wants to import into a local Git repository. First, the user would clone
62
+the remote repository and import it into a new Git repository:
63
+
64
+<blockquote><pre>
65
+fossil clone /path/to/remote/repo.fossil repo.fossil
66
+mkdir repo
67
+cd repo
68
+fossil open ../repo.fossil
69
+mkdir ../repo.git
70
+cd ../repo.git
71
+git init .
72
+fossil export --git --export-marks ../repo/fossil.marks \
73
+ ../repo.fossil | git fast-import \
74
+ --export-marks=../repo/git.marks
75
+</pre></blockquote>
76
+
77
+Once the import has completed, the user would need to <tt>git checkout
78
+trunk</tt>. At any point after this, new changes can be imported from the
79
+remote Fossil repository:
80
+
81
+<blockquote><pre>
82
+cd ../repo
83
+fossil pull
84
+cd ../repo.git
85
+fossil export --git --import-marks ../repo/fossil.marks \
86
+ --export-marks ../repo/fossil.marks \
87
+ ../repo.fossil | git fast-import \
88
+ --import-marks=../repo/git.marks \
89
+ --export-marks=../repo/git.marks
90
+</pre></blockquote>
91
+
92
+Changes in the Git repository can be exported to the Fossil repository and then
93
+pushed to the remote:
94
+
95
+<blockquote><pre>
96
+git fast-export --import-marks=../repo/git.marks \
97
+ --export-marks=../repo/git.marks --all | fossil import --git \
98
+ --incremental --import-marks ../repo/fossil.marks \
99
+ --export-marks ../repo/fossil.marks ../repo.fossil
100
+cd ../repo
101
+fossil push
102
+</pre></blockquote>
64103
--- www/inout.wiki
+++ www/inout.wiki
@@ -1,10 +1,10 @@
1 <title>Import And Export</title>
2
3 Fossil has the ability to import and export repositories from and to
4 [http://git-scm.com/ | Git]. And since most other version control
5 systems will also import/export from Git, that means that you can
6 import/export a Fossil repository to most version control systems using
7 Git as an intermediary.
8
9 <h2>Git → Fossil</h2>
10
@@ -20,11 +20,11 @@
20 command is the name of a new Fossil repository that is created to hold the Git
21 content.
22
23 The --git option is not actually required. The git-fast-export file format
24 is currently the only VCS interchange format that Fossil understands. But
25 future versions of Fossil might be enhanced to understand other VCS
26 interchange formats, and so for compatibility, use of the
27 --git option is recommended.
28
29 <h2>Fossil → Git</h2>
30
@@ -43,21 +43,60 @@
43 Note that the "fossil export --git" command only exports the versioned files.
44 Tickets and wiki and events are not exported, since Git does not understand
45 those concepts.
46
47 As with the "import" command, the --git option is not required
48 since the git-fast-export file format is currently the only VCS interchange
49 format that Fossil will generate. However,
50 future versions of Fossil might add the ability to generate other
51 VCS interchange formats, and so for compatibility, the use of the --git
52 option recommended.
53
54 An anonymous user sends this comment:
55
56 <blockquote>
57 The main Fossil branch is called "trunk", while the main git branch is
58 called "master". After you've exported your FOSSIL repo to git, you won't
59 see any files and gitk will complain about a missing "HEAD". You can
60 resolve this problem by merging "trunk" with "master"
61 (first verify using git status that you are on the "master" branch):
62 <tt>git merge trunk</tt>
63 </blockquote>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
--- www/inout.wiki
+++ www/inout.wiki
@@ -1,10 +1,10 @@
1 <title>Import And Export</title>
2
3 Fossil has the ability to import and export repositories from and to
4 [http://git-scm.com/ | Git]. And since most other version control
5 systems will also import/export from Git, that means that you can
6 import/export a Fossil repository to most version control systems using
7 Git as an intermediary.
8
9 <h2>Git → Fossil</h2>
10
@@ -20,11 +20,11 @@
20 command is the name of a new Fossil repository that is created to hold the Git
21 content.
22
23 The --git option is not actually required. The git-fast-export file format
24 is currently the only VCS interchange format that Fossil understands. But
25 future versions of Fossil might be enhanced to understand other VCS
26 interchange formats, and so for compatibility, use of the
27 --git option is recommended.
28
29 <h2>Fossil → Git</h2>
30
@@ -43,21 +43,60 @@
43 Note that the "fossil export --git" command only exports the versioned files.
44 Tickets and wiki and events are not exported, since Git does not understand
45 those concepts.
46
47 As with the "import" command, the --git option is not required
48 since the git-fast-export file format is currently the only VCS interchange
49 format that Fossil will generate. However,
50 future versions of Fossil might add the ability to generate other
51 VCS interchange formats, and so for compatibility, the use of the --git
52 option recommended.
53
54 <h2>Bidirectional Synchronization</h2>
55 Fossil also has the ability to synchronize with a Git repository via repeated
56 imports and/or exports. To do this, it uses marks files to store a record of
57 artifacts which are known by both Git and Fossil to exist at a given point in
58 time.
59
60 To illustrate, consider the example of a remote Fossil repository that a
61 user wants to import into a local Git repository. First, the user would clone
62 the remote repository and import it into a new Git repository:
63
64 <blockquote><pre>
65 fossil clone /path/to/remote/repo.fossil repo.fossil
66 mkdir repo
67 cd repo
68 fossil open ../repo.fossil
69 mkdir ../repo.git
70 cd ../repo.git
71 git init .
72 fossil export --git --export-marks ../repo/fossil.marks \
73 ../repo.fossil | git fast-import \
74 --export-marks=../repo/git.marks
75 </pre></blockquote>
76
77 Once the import has completed, the user would need to <tt>git checkout
78 trunk</tt>. At any point after this, new changes can be imported from the
79 remote Fossil repository:
80
81 <blockquote><pre>
82 cd ../repo
83 fossil pull
84 cd ../repo.git
85 fossil export --git --import-marks ../repo/fossil.marks \
86 --export-marks ../repo/fossil.marks \
87 ../repo.fossil | git fast-import \
88 --import-marks=../repo/git.marks \
89 --export-marks=../repo/git.marks
90 </pre></blockquote>
91
92 Changes in the Git repository can be exported to the Fossil repository and then
93 pushed to the remote:
94
95 <blockquote><pre>
96 git fast-export --import-marks=../repo/git.marks \
97 --export-marks=../repo/git.marks --all | fossil import --git \
98 --incremental --import-marks ../repo/fossil.marks \
99 --export-marks ../repo/fossil.marks ../repo.fossil
100 cd ../repo
101 fossil push
102 </pre></blockquote>
103
+13 -13
--- www/makefile.wiki
+++ www/makefile.wiki
@@ -2,24 +2,24 @@
22
33
<h1>1.0 Introduction</h1>
44
55
The build process for Fossil is tricky in that the source code
66
needs to be processed by three different preprocessor programs
7
-before it is compiled. Most users will download a
7
+before it is compiled. Most users will download a
88
[http://www.fossil-scm.org/download.html | precompiled binary]
99
so this is of no consequence to them, and even those who
10
-want to compile the code themselves can use one of the
11
-[./build.wiki | existing makefiles].
10
+want to compile the code themselves can use one of the
11
+[./build.wiki | existing makefiles].
1212
So must people do not need to be concerned with the
1313
build complexities of Fossil. But hard-core developers who desire
1414
a deep understanding of how Fossil is put together can benefit
1515
from reviewing this article.
1616
1717
<a name="srctour"></a>
1818
<h1>2.0 Source Code Tour</h1>
1919
20
-The source code for Fossil is found in the
20
+The source code for Fossil is found in the
2121
[/dir?ci=trunk&name=src | src/] subdirectory of the
2222
source tree. The src/ subdirectory contains all code, including
2323
the code for the separate preprocessor programs.
2424
2525
Each preprocessor program is a separate C program implemented in
@@ -50,11 +50,11 @@
5050
The TH1 script engine is implemented using files:
5151
5252
7. th.c
5353
8. th.h
5454
55
-These two files are imports like the SQLite source files,
55
+These two files are imports like the SQLite source files,
5656
and so are not preprocessed.
5757
5858
The VERSION.h header file is generated from other information sources
5959
using a small program called:
6060
@@ -86,11 +86,11 @@
8686
8787
13. main.mk
8888
8989
The main.mk makefile is invoked from the Makefile in the top-level
9090
directory. The main.mk is generated by makemake.tcl and should not
91
-be hand edited. Other makefiles generated by makemake.tcl are in
91
+be hand edited. Other makefiles generated by makemake.tcl are in
9292
other subdirectories (currently all in the win/ subdirectory).
9393
9494
All the other files in the src/ subdirectory (79 files at the time of
9595
this writing) are C source code files that are subject to the
9696
preprocessing steps described below. In the sequel, we will call these
@@ -109,11 +109,11 @@
109109
(The "manifest" and "manifest.uuid" files are automatically generated and
110110
updated by Fossil itself. See the [/help/setting | fossil set manifest]
111111
command for additional information.)
112112
113113
The VERSION.h header file is generated by
114
-a C program: src/mkversion.c.
114
+a C program: src/mkversion.c.
115115
To run the VERSION.h generator, first compile the src/mkversion.c
116116
source file into a command-line program (named "mkversion.exe")
117117
then run:
118118
119119
<blockquote><pre>
@@ -126,11 +126,11 @@
126126
in the root of the source tree are the three arguments and
127127
the generated VERSION.h file appears on standard output.
128128
129129
The builtin_data.h header file is generated by a C program: src/mkbuiltin.c.
130130
The builtin_data.h file contains C-langauge byte-array definitions for
131
-the content of resource files used by Fossil. To generate the
131
+the content of resource files used by Fossil. To generate the
132132
builtin_data.h file, first compile the mkbuiltin.c program, then run:
133133
134134
<blockquote><pre>
135135
mkbuiltin.exe diff.tcl <i>OtherFiles...</i> &gt;builtin_data.h
136136
</pre></blockquote>
@@ -163,11 +163,11 @@
163163
Note that "src.c" in the above is a stand-in for the (79) regular source
164164
files of Fossil - all source files except for the exceptions described in
165165
section 2.0 above.
166166
167167
The output of the mkindex program is a header file that is #include-ed by
168
-the main.c source file during the final compilation step.
168
+the main.c source file during the final compilation step.
169169
170170
<h2>4.2 The translate preprocessor</h2>
171171
172172
The translate preprocessor looks for lines of source code that begin
173173
with "@" and converts those lines into string constants or (depending on
@@ -181,11 +181,11 @@
181181
</pre></blockquote>
182182
183183
In this case, the "src.c" file represents any single source file from the
184184
set of ordinary source files as described in section 2.0 above. Note that
185185
each source file is translated separately. By convention, the names of
186
-the translated source files are the names of the input sources with a
186
+the translated source files are the names of the input sources with a
187187
single "_" character at the end. But a new makefile can use any naming
188188
convention it wants - the "_" is not critical to the build process.
189189
190190
After being translated, the output files (the "src_.c" files) should be
191191
used for all subsequent preprocessing and compilation steps.
@@ -209,16 +209,16 @@
209209
<blockquote><pre>
210210
makeheaders src_.c:src.h sqlite3.h th.h VERSION.h
211211
</pre></blockquote>
212212
213213
In the example above the "src_.c" and "src.h" names represent all of the
214
-(79) ordinary C source files, each as a separate argument.
214
+(79) ordinary C source files, each as a separate argument.
215215
216216
<h1>5.0 Compilation</h1>
217217
218218
After all generated files have been created and all ordinary source files
219
-have been preprocessed, the generated and preprocessed files can be
219
+have been preprocessed, the generated and preprocessed files can be
220220
combined into a single executable using a C compiler. This can be done
221221
all at once, or each preprocessed source file can be compiled into a
222222
separate object code file and the resulting object code files linked
223223
together in a final step.
224224
@@ -247,11 +247,11 @@
247247
* -Dmain=sqlite3_main
248248
* -DSQLITE_OMIT_LOAD_EXTENSION=1
249249
250250
The "main()" routine in the shell must be changed into sqlite3_main()
251251
to prevent it from colliding with the real main() in Fossil, and to give
252
-Fossil an entry point to jump to when the
252
+Fossil an entry point to jump to when the
253253
[/help/sqlite3 | fossil sql] command is invoked.
254254
255255
All the other source code files can be compiled without any special
256256
options.
257257
258258
--- www/makefile.wiki
+++ www/makefile.wiki
@@ -2,24 +2,24 @@
2
3 <h1>1.0 Introduction</h1>
4
5 The build process for Fossil is tricky in that the source code
6 needs to be processed by three different preprocessor programs
7 before it is compiled. Most users will download a
8 [http://www.fossil-scm.org/download.html | precompiled binary]
9 so this is of no consequence to them, and even those who
10 want to compile the code themselves can use one of the
11 [./build.wiki | existing makefiles].
12 So must people do not need to be concerned with the
13 build complexities of Fossil. But hard-core developers who desire
14 a deep understanding of how Fossil is put together can benefit
15 from reviewing this article.
16
17 <a name="srctour"></a>
18 <h1>2.0 Source Code Tour</h1>
19
20 The source code for Fossil is found in the
21 [/dir?ci=trunk&name=src | src/] subdirectory of the
22 source tree. The src/ subdirectory contains all code, including
23 the code for the separate preprocessor programs.
24
25 Each preprocessor program is a separate C program implemented in
@@ -50,11 +50,11 @@
50 The TH1 script engine is implemented using files:
51
52 7. th.c
53 8. th.h
54
55 These two files are imports like the SQLite source files,
56 and so are not preprocessed.
57
58 The VERSION.h header file is generated from other information sources
59 using a small program called:
60
@@ -86,11 +86,11 @@
86
87 13. main.mk
88
89 The main.mk makefile is invoked from the Makefile in the top-level
90 directory. The main.mk is generated by makemake.tcl and should not
91 be hand edited. Other makefiles generated by makemake.tcl are in
92 other subdirectories (currently all in the win/ subdirectory).
93
94 All the other files in the src/ subdirectory (79 files at the time of
95 this writing) are C source code files that are subject to the
96 preprocessing steps described below. In the sequel, we will call these
@@ -109,11 +109,11 @@
109 (The "manifest" and "manifest.uuid" files are automatically generated and
110 updated by Fossil itself. See the [/help/setting | fossil set manifest]
111 command for additional information.)
112
113 The VERSION.h header file is generated by
114 a C program: src/mkversion.c.
115 To run the VERSION.h generator, first compile the src/mkversion.c
116 source file into a command-line program (named "mkversion.exe")
117 then run:
118
119 <blockquote><pre>
@@ -126,11 +126,11 @@
126 in the root of the source tree are the three arguments and
127 the generated VERSION.h file appears on standard output.
128
129 The builtin_data.h header file is generated by a C program: src/mkbuiltin.c.
130 The builtin_data.h file contains C-langauge byte-array definitions for
131 the content of resource files used by Fossil. To generate the
132 builtin_data.h file, first compile the mkbuiltin.c program, then run:
133
134 <blockquote><pre>
135 mkbuiltin.exe diff.tcl <i>OtherFiles...</i> &gt;builtin_data.h
136 </pre></blockquote>
@@ -163,11 +163,11 @@
163 Note that "src.c" in the above is a stand-in for the (79) regular source
164 files of Fossil - all source files except for the exceptions described in
165 section 2.0 above.
166
167 The output of the mkindex program is a header file that is #include-ed by
168 the main.c source file during the final compilation step.
169
170 <h2>4.2 The translate preprocessor</h2>
171
172 The translate preprocessor looks for lines of source code that begin
173 with "@" and converts those lines into string constants or (depending on
@@ -181,11 +181,11 @@
181 </pre></blockquote>
182
183 In this case, the "src.c" file represents any single source file from the
184 set of ordinary source files as described in section 2.0 above. Note that
185 each source file is translated separately. By convention, the names of
186 the translated source files are the names of the input sources with a
187 single "_" character at the end. But a new makefile can use any naming
188 convention it wants - the "_" is not critical to the build process.
189
190 After being translated, the output files (the "src_.c" files) should be
191 used for all subsequent preprocessing and compilation steps.
@@ -209,16 +209,16 @@
209 <blockquote><pre>
210 makeheaders src_.c:src.h sqlite3.h th.h VERSION.h
211 </pre></blockquote>
212
213 In the example above the "src_.c" and "src.h" names represent all of the
214 (79) ordinary C source files, each as a separate argument.
215
216 <h1>5.0 Compilation</h1>
217
218 After all generated files have been created and all ordinary source files
219 have been preprocessed, the generated and preprocessed files can be
220 combined into a single executable using a C compiler. This can be done
221 all at once, or each preprocessed source file can be compiled into a
222 separate object code file and the resulting object code files linked
223 together in a final step.
224
@@ -247,11 +247,11 @@
247 * -Dmain=sqlite3_main
248 * -DSQLITE_OMIT_LOAD_EXTENSION=1
249
250 The "main()" routine in the shell must be changed into sqlite3_main()
251 to prevent it from colliding with the real main() in Fossil, and to give
252 Fossil an entry point to jump to when the
253 [/help/sqlite3 | fossil sql] command is invoked.
254
255 All the other source code files can be compiled without any special
256 options.
257
258
--- www/makefile.wiki
+++ www/makefile.wiki
@@ -2,24 +2,24 @@
2
3 <h1>1.0 Introduction</h1>
4
5 The build process for Fossil is tricky in that the source code
6 needs to be processed by three different preprocessor programs
7 before it is compiled. Most users will download a
8 [http://www.fossil-scm.org/download.html | precompiled binary]
9 so this is of no consequence to them, and even those who
10 want to compile the code themselves can use one of the
11 [./build.wiki | existing makefiles].
12 So must people do not need to be concerned with the
13 build complexities of Fossil. But hard-core developers who desire
14 a deep understanding of how Fossil is put together can benefit
15 from reviewing this article.
16
17 <a name="srctour"></a>
18 <h1>2.0 Source Code Tour</h1>
19
20 The source code for Fossil is found in the
21 [/dir?ci=trunk&name=src | src/] subdirectory of the
22 source tree. The src/ subdirectory contains all code, including
23 the code for the separate preprocessor programs.
24
25 Each preprocessor program is a separate C program implemented in
@@ -50,11 +50,11 @@
50 The TH1 script engine is implemented using files:
51
52 7. th.c
53 8. th.h
54
55 These two files are imports like the SQLite source files,
56 and so are not preprocessed.
57
58 The VERSION.h header file is generated from other information sources
59 using a small program called:
60
@@ -86,11 +86,11 @@
86
87 13. main.mk
88
89 The main.mk makefile is invoked from the Makefile in the top-level
90 directory. The main.mk is generated by makemake.tcl and should not
91 be hand edited. Other makefiles generated by makemake.tcl are in
92 other subdirectories (currently all in the win/ subdirectory).
93
94 All the other files in the src/ subdirectory (79 files at the time of
95 this writing) are C source code files that are subject to the
96 preprocessing steps described below. In the sequel, we will call these
@@ -109,11 +109,11 @@
109 (The "manifest" and "manifest.uuid" files are automatically generated and
110 updated by Fossil itself. See the [/help/setting | fossil set manifest]
111 command for additional information.)
112
113 The VERSION.h header file is generated by
114 a C program: src/mkversion.c.
115 To run the VERSION.h generator, first compile the src/mkversion.c
116 source file into a command-line program (named "mkversion.exe")
117 then run:
118
119 <blockquote><pre>
@@ -126,11 +126,11 @@
126 in the root of the source tree are the three arguments and
127 the generated VERSION.h file appears on standard output.
128
129 The builtin_data.h header file is generated by a C program: src/mkbuiltin.c.
130 The builtin_data.h file contains C-langauge byte-array definitions for
131 the content of resource files used by Fossil. To generate the
132 builtin_data.h file, first compile the mkbuiltin.c program, then run:
133
134 <blockquote><pre>
135 mkbuiltin.exe diff.tcl <i>OtherFiles...</i> &gt;builtin_data.h
136 </pre></blockquote>
@@ -163,11 +163,11 @@
163 Note that "src.c" in the above is a stand-in for the (79) regular source
164 files of Fossil - all source files except for the exceptions described in
165 section 2.0 above.
166
167 The output of the mkindex program is a header file that is #include-ed by
168 the main.c source file during the final compilation step.
169
170 <h2>4.2 The translate preprocessor</h2>
171
172 The translate preprocessor looks for lines of source code that begin
173 with "@" and converts those lines into string constants or (depending on
@@ -181,11 +181,11 @@
181 </pre></blockquote>
182
183 In this case, the "src.c" file represents any single source file from the
184 set of ordinary source files as described in section 2.0 above. Note that
185 each source file is translated separately. By convention, the names of
186 the translated source files are the names of the input sources with a
187 single "_" character at the end. But a new makefile can use any naming
188 convention it wants - the "_" is not critical to the build process.
189
190 After being translated, the output files (the "src_.c" files) should be
191 used for all subsequent preprocessing and compilation steps.
@@ -209,16 +209,16 @@
209 <blockquote><pre>
210 makeheaders src_.c:src.h sqlite3.h th.h VERSION.h
211 </pre></blockquote>
212
213 In the example above the "src_.c" and "src.h" names represent all of the
214 (79) ordinary C source files, each as a separate argument.
215
216 <h1>5.0 Compilation</h1>
217
218 After all generated files have been created and all ordinary source files
219 have been preprocessed, the generated and preprocessed files can be
220 combined into a single executable using a C compiler. This can be done
221 all at once, or each preprocessed source file can be compiled into a
222 separate object code file and the resulting object code files linked
223 together in a final step.
224
@@ -247,11 +247,11 @@
247 * -Dmain=sqlite3_main
248 * -DSQLITE_OMIT_LOAD_EXTENSION=1
249
250 The "main()" routine in the shell must be changed into sqlite3_main()
251 to prevent it from colliding with the real main() in Fossil, and to give
252 Fossil an entry point to jump to when the
253 [/help/sqlite3 | fossil sql] command is invoked.
254
255 All the other source code files can be compiled without any special
256 options.
257
258
--- www/mkdownload.tcl
+++ www/mkdownload.tcl
@@ -1,9 +1,9 @@
11
#!/usr/bin/tclsh
22
#
3
-# Run this script to build andn install the "download.html" page of
4
-# unversioned comment.
3
+# Run this script to build and install the "download.html" page of
4
+# unversioned comment.
55
#
66
# Also generate the fossil_download_checksums.html page.
77
#
88
#
99
set out [open download.html w]
1010
--- www/mkdownload.tcl
+++ www/mkdownload.tcl
@@ -1,9 +1,9 @@
1 #!/usr/bin/tclsh
2 #
3 # Run this script to build andn install the "download.html" page of
4 # unversioned comment.
5 #
6 # Also generate the fossil_download_checksums.html page.
7 #
8 #
9 set out [open download.html w]
10
--- www/mkdownload.tcl
+++ www/mkdownload.tcl
@@ -1,9 +1,9 @@
1 #!/usr/bin/tclsh
2 #
3 # Run this script to build and install the "download.html" page of
4 # unversioned comment.
5 #
6 # Also generate the fossil_download_checksums.html page.
7 #
8 #
9 set out [open download.html w]
10
--- www/newrepo.wiki
+++ www/newrepo.wiki
@@ -53,11 +53,11 @@
5353
5454
<verbatim>
5555
stephan@ludo:~/fossil$ mkdir demo
5656
stephan@ludo:~/fossil$ cd demo
5757
stephan@ludo:~/fossil/demo$ fossil open ../demo.fossil
58
-stephan@ludo:~/fossil/demo$
58
+stephan@ludo:~/fossil/demo$
5959
</verbatim>
6060
6161
That creates a file called <tt>_FOSSIL_</tt> in the current
6262
directory, and this file contains all kinds of fossil-related
6363
information about your local repository. You can ignore it
6464
--- www/newrepo.wiki
+++ www/newrepo.wiki
@@ -53,11 +53,11 @@
53
54 <verbatim>
55 stephan@ludo:~/fossil$ mkdir demo
56 stephan@ludo:~/fossil$ cd demo
57 stephan@ludo:~/fossil/demo$ fossil open ../demo.fossil
58 stephan@ludo:~/fossil/demo$
59 </verbatim>
60
61 That creates a file called <tt>_FOSSIL_</tt> in the current
62 directory, and this file contains all kinds of fossil-related
63 information about your local repository. You can ignore it
64
--- www/newrepo.wiki
+++ www/newrepo.wiki
@@ -53,11 +53,11 @@
53
54 <verbatim>
55 stephan@ludo:~/fossil$ mkdir demo
56 stephan@ludo:~/fossil$ cd demo
57 stephan@ludo:~/fossil/demo$ fossil open ../demo.fossil
58 stephan@ludo:~/fossil/demo$
59 </verbatim>
60
61 That creates a file called <tt>_FOSSIL_</tt> in the current
62 directory, and this file contains all kinds of fossil-related
63 information about your local repository. You can ignore it
64
+5 -5
--- www/pop.wiki
+++ www/pop.wiki
@@ -4,18 +4,18 @@
44
This page attempts to define the foundational principals upon
55
which Fossil is built.
66
</p>
77
88
<ul>
9
-<li><p>A project consists of source files, wiki pages, and
9
+<li><p>A project consists of source files, wiki pages, and
1010
trouble tickets, and control files (collectively "artifacts").
1111
All historical copies of all artifacts
1212
are saved. The project maintains an audit
1313
trail.</p></li>
1414
1515
<li><p>A project resides in one or more repositories. Each
16
-repository is administered and operates independently
16
+repository is administered and operates independently
1717
of the others.</p></li>
1818
1919
<li><p>Each repository has both global and local state. The
2020
global state is common to all repositories (or at least
2121
has the potential to be shared in common when the
@@ -24,28 +24,28 @@
2424
The global state represents the content of the project.
2525
The local state identifies the authorized users and
2626
access policies for a particular repository.</p></li>
2727
2828
<li><p>The global state of a repository is an unordered
29
-collection of artifacts. Each artifact is named by
29
+collection of artifacts. Each artifact is named by
3030
its SHA1 hash encoded in lowercase hexadecimal.
3131
In many contexts, the name can be
3232
abbreviated to a unique prefix. A five- or six-character
3333
prefix usually suffices to uniquely identify a file.</p></li>
3434
3535
<li><p>Because artifacts are named by their SHA1 hash, all artifacts
36
-are immutable. Any change to the content of an artifact also
36
+are immutable. Any change to the content of an artifact also
3737
changes the hash that forms the artifacts name, thus
3838
creating a new artifact. Both the old original version of the
3939
artifact and the new change are preserved under different names.</p></li>
4040
4141
<li><p>It is theoretically possible for two artifacts with different
4242
content to share the same hash. But finding two such
4343
artifacts is so incredibly difficult and unlikely that we
4444
consider it to be an impossibility.</p></li>
4545
46
-<li><p>The signature of an artifact is the SHA1 hash of the
46
+<li><p>The signature of an artifact is the SHA1 hash of the
4747
artifact itself, exactly as it would appear in a disk file. No prefix
4848
or meta-information about the artifact is added before computing
4949
the hash. So you can
5050
always find the SHA1 signature of a file by using the
5151
"sha1sum" command-line utility.</p></li>
5252
--- www/pop.wiki
+++ www/pop.wiki
@@ -4,18 +4,18 @@
4 This page attempts to define the foundational principals upon
5 which Fossil is built.
6 </p>
7
8 <ul>
9 <li><p>A project consists of source files, wiki pages, and
10 trouble tickets, and control files (collectively "artifacts").
11 All historical copies of all artifacts
12 are saved. The project maintains an audit
13 trail.</p></li>
14
15 <li><p>A project resides in one or more repositories. Each
16 repository is administered and operates independently
17 of the others.</p></li>
18
19 <li><p>Each repository has both global and local state. The
20 global state is common to all repositories (or at least
21 has the potential to be shared in common when the
@@ -24,28 +24,28 @@
24 The global state represents the content of the project.
25 The local state identifies the authorized users and
26 access policies for a particular repository.</p></li>
27
28 <li><p>The global state of a repository is an unordered
29 collection of artifacts. Each artifact is named by
30 its SHA1 hash encoded in lowercase hexadecimal.
31 In many contexts, the name can be
32 abbreviated to a unique prefix. A five- or six-character
33 prefix usually suffices to uniquely identify a file.</p></li>
34
35 <li><p>Because artifacts are named by their SHA1 hash, all artifacts
36 are immutable. Any change to the content of an artifact also
37 changes the hash that forms the artifacts name, thus
38 creating a new artifact. Both the old original version of the
39 artifact and the new change are preserved under different names.</p></li>
40
41 <li><p>It is theoretically possible for two artifacts with different
42 content to share the same hash. But finding two such
43 artifacts is so incredibly difficult and unlikely that we
44 consider it to be an impossibility.</p></li>
45
46 <li><p>The signature of an artifact is the SHA1 hash of the
47 artifact itself, exactly as it would appear in a disk file. No prefix
48 or meta-information about the artifact is added before computing
49 the hash. So you can
50 always find the SHA1 signature of a file by using the
51 "sha1sum" command-line utility.</p></li>
52
--- www/pop.wiki
+++ www/pop.wiki
@@ -4,18 +4,18 @@
4 This page attempts to define the foundational principals upon
5 which Fossil is built.
6 </p>
7
8 <ul>
9 <li><p>A project consists of source files, wiki pages, and
10 trouble tickets, and control files (collectively "artifacts").
11 All historical copies of all artifacts
12 are saved. The project maintains an audit
13 trail.</p></li>
14
15 <li><p>A project resides in one or more repositories. Each
16 repository is administered and operates independently
17 of the others.</p></li>
18
19 <li><p>Each repository has both global and local state. The
20 global state is common to all repositories (or at least
21 has the potential to be shared in common when the
@@ -24,28 +24,28 @@
24 The global state represents the content of the project.
25 The local state identifies the authorized users and
26 access policies for a particular repository.</p></li>
27
28 <li><p>The global state of a repository is an unordered
29 collection of artifacts. Each artifact is named by
30 its SHA1 hash encoded in lowercase hexadecimal.
31 In many contexts, the name can be
32 abbreviated to a unique prefix. A five- or six-character
33 prefix usually suffices to uniquely identify a file.</p></li>
34
35 <li><p>Because artifacts are named by their SHA1 hash, all artifacts
36 are immutable. Any change to the content of an artifact also
37 changes the hash that forms the artifacts name, thus
38 creating a new artifact. Both the old original version of the
39 artifact and the new change are preserved under different names.</p></li>
40
41 <li><p>It is theoretically possible for two artifacts with different
42 content to share the same hash. But finding two such
43 artifacts is so incredibly difficult and unlikely that we
44 consider it to be an impossibility.</p></li>
45
46 <li><p>The signature of an artifact is the SHA1 hash of the
47 artifact itself, exactly as it would appear in a disk file. No prefix
48 or meta-information about the artifact is added before computing
49 the hash. So you can
50 always find the SHA1 signature of a file by using the
51 "sha1sum" command-line utility.</p></li>
52
--- www/private.wiki
+++ www/private.wiki
@@ -41,11 +41,11 @@
4141
<h2>Syncing Private Branches</h2>
4242
4343
A private branch normally stays on the one repository where it was
4444
originally created. But sometimes you want to share private branches
4545
with another repository. For example, you might be building a cross-platform
46
-application and have separate repositories on your Windows laptop,
46
+application and have separate repositories on your Windows laptop,
4747
your Linux desktop, and your iMac. You can transfer private branches
4848
between these machines by using the --private option on the "sync",
4949
"push", "pull", and "clone" commands. For example, if you are running
5050
"fossil server" on your Linux box and you want to clone that repository
5151
to your Mac, including all private branches, use:
@@ -67,11 +67,11 @@
6767
only enable "x" for local repositories when you need to share private
6868
branches.
6969
7070
Private branch sync only works if you use the --private command-line option.
7171
Private branches are never synced via the auto-sync mechanism. Once
72
-again, this restriction is designed to make it hard to accidently
72
+again, this restriction is designed to make it hard to accidently
7373
push private branches beyond their intended audience.
7474
7575
<h2>Purging Private Branches</h2>
7676
7777
You can remove all private branches from a repository using this command:
@@ -85,10 +85,10 @@
8585
removed, they cannot be retrieved (unless you have synced them to another
8686
repository.) So be careful with the command.
8787
8888
<h2>Additional Notes</h2>
8989
90
-All of the features above apply to <u>all</u> private branches in a
90
+All of the features above apply to <u>all</u> private branches in a
9191
single repository at once. There is no mechanism in Fossil (currently)
9292
that allows you to push, pull, clone, sync, or scrub and individual
9393
private branch within a repository that contains multiple private
9494
branches.
9595
--- www/private.wiki
+++ www/private.wiki
@@ -41,11 +41,11 @@
41 <h2>Syncing Private Branches</h2>
42
43 A private branch normally stays on the one repository where it was
44 originally created. But sometimes you want to share private branches
45 with another repository. For example, you might be building a cross-platform
46 application and have separate repositories on your Windows laptop,
47 your Linux desktop, and your iMac. You can transfer private branches
48 between these machines by using the --private option on the "sync",
49 "push", "pull", and "clone" commands. For example, if you are running
50 "fossil server" on your Linux box and you want to clone that repository
51 to your Mac, including all private branches, use:
@@ -67,11 +67,11 @@
67 only enable "x" for local repositories when you need to share private
68 branches.
69
70 Private branch sync only works if you use the --private command-line option.
71 Private branches are never synced via the auto-sync mechanism. Once
72 again, this restriction is designed to make it hard to accidently
73 push private branches beyond their intended audience.
74
75 <h2>Purging Private Branches</h2>
76
77 You can remove all private branches from a repository using this command:
@@ -85,10 +85,10 @@
85 removed, they cannot be retrieved (unless you have synced them to another
86 repository.) So be careful with the command.
87
88 <h2>Additional Notes</h2>
89
90 All of the features above apply to <u>all</u> private branches in a
91 single repository at once. There is no mechanism in Fossil (currently)
92 that allows you to push, pull, clone, sync, or scrub and individual
93 private branch within a repository that contains multiple private
94 branches.
95
--- www/private.wiki
+++ www/private.wiki
@@ -41,11 +41,11 @@
41 <h2>Syncing Private Branches</h2>
42
43 A private branch normally stays on the one repository where it was
44 originally created. But sometimes you want to share private branches
45 with another repository. For example, you might be building a cross-platform
46 application and have separate repositories on your Windows laptop,
47 your Linux desktop, and your iMac. You can transfer private branches
48 between these machines by using the --private option on the "sync",
49 "push", "pull", and "clone" commands. For example, if you are running
50 "fossil server" on your Linux box and you want to clone that repository
51 to your Mac, including all private branches, use:
@@ -67,11 +67,11 @@
67 only enable "x" for local repositories when you need to share private
68 branches.
69
70 Private branch sync only works if you use the --private command-line option.
71 Private branches are never synced via the auto-sync mechanism. Once
72 again, this restriction is designed to make it hard to accidently
73 push private branches beyond their intended audience.
74
75 <h2>Purging Private Branches</h2>
76
77 You can remove all private branches from a repository using this command:
@@ -85,10 +85,10 @@
85 removed, they cannot be retrieved (unless you have synced them to another
86 repository.) So be careful with the command.
87
88 <h2>Additional Notes</h2>
89
90 All of the features above apply to <u>all</u> private branches in a
91 single repository at once. There is no mechanism in Fossil (currently)
92 that allows you to push, pull, clone, sync, or scrub and individual
93 private branch within a repository that contains multiple private
94 branches.
95
+10 -10
--- www/qandc.wiki
+++ www/qandc.wiki
@@ -22,11 +22,11 @@
2222
<li> Integrated <a href="wikitheory.wiki">wiki</a>. </li>
2323
<li> Integrated <a href="bugtheory.wiki">bug tracking</a> </li>
2424
<li> Immutable artifacts </li>
2525
<li> Self-contained, stand-alone executable that can be run in
2626
a <a href="http://en.wikipedia.org/wiki/Chroot">chroot jail</a> </li>
27
- <li> Simple, well-defined,
27
+ <li> Simple, well-defined,
2828
<a href="fileformat.wiki">enduring file format</a> </li>
2929
<li> Integrated <a href="webui.wiki">web interface</a> </li>
3030
</ol>
3131
</blockquote>
3232
@@ -36,11 +36,11 @@
3636
<ol>
3737
<li> Fossil is distributed. You can view and/or edit tickets, wiki, and
3838
code while off network, then sync your changes later. With Trac, you
3939
can only view and edit tickets and wiki while you are connected to
4040
the server. </li>
41
- <li> Fossil is lightweight and fully self-contained. It is very easy
41
+ <li> Fossil is lightweight and fully self-contained. It is very easy
4242
to setup on a low-resource machine. Fossil does not require an
4343
administrator.</li>
4444
<li> Fossil integrates code versioning into the same repository with
4545
wiki and tickets. There is nothing extra to add or install.
4646
Fossil is an all-in-one turnkey solution. </li>
@@ -48,25 +48,25 @@
4848
</blockquote>
4949
5050
<b>Love the concept here. Anyone using this for real work yet?</b>
5151
5252
<blockquote>
53
-Fossil is <a href="http://www.fossil-scm.org/">self-hosting</a>.
53
+Fossil is <a href="http://www.fossil-scm.org/">self-hosting</a>.
5454
In fact, this page was probably delivered
5555
to your web-browser via a working fossil instance. The same virtual
5656
machine that hosts http://www.fossil-scm.org/
5757
(a <a href="http://www.linode.com/">Linode 720</a>)
5858
also hosts 24 other fossil repositories for various small projects.
59
-The documentation files for
59
+The documentation files for
6060
<a href="http://www.sqlite.org/">SQLite</a> are hosted in a
6161
fossil repository <a href="http://www.sqlite.org/docsrc/">here</a>,
6262
for example.
6363
Other projects are also adopting fossil. But fossil does not yet have
6464
the massive user base of git or mercurial.
6565
</blockquote>
6666
67
-<b>Fossil looks like the bug tracker that would be in your
67
+<b>Fossil looks like the bug tracker that would be in your
6868
Linksys Router's administration screen.</b>
6969
7070
<blockquote>
7171
<p>I take a pragmatic approach to software: form follows function.
7272
To me, it is more important to have a reliable, fast, efficient,
@@ -83,11 +83,11 @@
8383
keeps the bug-tracking database in a versioned file. That file can
8484
then be pushed and pulled along with the rest repository.</b>
8585
8686
<blockquote>
8787
<p>Fossil already <u>does</u> push and pull bugs along with the files
88
-in your repository.
88
+in your repository.
8989
But fossil does <u>not</u> track bugs as files in the source tree.
9090
That approach to bug tracking was rejected for three reasons:</p>
9191
9292
<ol>
9393
<li> Check-ins in fossil are immutable. So if
@@ -108,11 +108,11 @@
108108
109109
<p>These points are reiterated in the opening paragraphs of
110110
the <a href="bugtheory.wiki">Bug-Tracking In Fossil</a> document.</p>
111111
</blockquote>
112112
113
-<b>Fossil is already the name of a plan9 versioned
113
+<b>Fossil is already the name of a plan9 versioned
114114
append-only filesystem.</b>
115115
116116
<blockquote>
117117
I did not know that. Perhaps they selected the name for the same reason that
118118
I did: because a repository with immutable artifacts preserves
@@ -137,22 +137,22 @@
137137
Subversion or Bazaar.</b>
138138
139139
<blockquote>
140140
<p>I have no doubt that Trac has many features that fossil lacks. But that
141141
is not the point. Fossil has several key features that Trac lacks and that
142
-I need: most notably the fact that
142
+I need: most notably the fact that
143143
fossil supports disconnected operation.</p>
144144
145145
<p>As for bloat: Fossil is a single self-contained executable.
146
-You do not need any other packages
146
+You do not need any other packages
147147
(diff, patch, merge, cvs, svn, rcs, git, python, perl, tcl, apache,
148148
sqlite, and so forth)
149149
in order to run fossil. Fossil runs just fine in a chroot jail all
150150
by itself. And the self-contained fossil
151151
executable is much less than 1MB in size. (Update 2015-01-12: Fossil has
152
-grown in the years since the previous sentence was written but is still
152
+grown in the years since the previous sentence was written but is still
153153
much less than 2MB according to "size" when compiled using -Os on x64 Linux.)
154154
Fossil is the very opposite of bloat.</p>
155155
</blockquote>
156156
157157
158158
</nowiki>
159159
--- www/qandc.wiki
+++ www/qandc.wiki
@@ -22,11 +22,11 @@
22 <li> Integrated <a href="wikitheory.wiki">wiki</a>. </li>
23 <li> Integrated <a href="bugtheory.wiki">bug tracking</a> </li>
24 <li> Immutable artifacts </li>
25 <li> Self-contained, stand-alone executable that can be run in
26 a <a href="http://en.wikipedia.org/wiki/Chroot">chroot jail</a> </li>
27 <li> Simple, well-defined,
28 <a href="fileformat.wiki">enduring file format</a> </li>
29 <li> Integrated <a href="webui.wiki">web interface</a> </li>
30 </ol>
31 </blockquote>
32
@@ -36,11 +36,11 @@
36 <ol>
37 <li> Fossil is distributed. You can view and/or edit tickets, wiki, and
38 code while off network, then sync your changes later. With Trac, you
39 can only view and edit tickets and wiki while you are connected to
40 the server. </li>
41 <li> Fossil is lightweight and fully self-contained. It is very easy
42 to setup on a low-resource machine. Fossil does not require an
43 administrator.</li>
44 <li> Fossil integrates code versioning into the same repository with
45 wiki and tickets. There is nothing extra to add or install.
46 Fossil is an all-in-one turnkey solution. </li>
@@ -48,25 +48,25 @@
48 </blockquote>
49
50 <b>Love the concept here. Anyone using this for real work yet?</b>
51
52 <blockquote>
53 Fossil is <a href="http://www.fossil-scm.org/">self-hosting</a>.
54 In fact, this page was probably delivered
55 to your web-browser via a working fossil instance. The same virtual
56 machine that hosts http://www.fossil-scm.org/
57 (a <a href="http://www.linode.com/">Linode 720</a>)
58 also hosts 24 other fossil repositories for various small projects.
59 The documentation files for
60 <a href="http://www.sqlite.org/">SQLite</a> are hosted in a
61 fossil repository <a href="http://www.sqlite.org/docsrc/">here</a>,
62 for example.
63 Other projects are also adopting fossil. But fossil does not yet have
64 the massive user base of git or mercurial.
65 </blockquote>
66
67 <b>Fossil looks like the bug tracker that would be in your
68 Linksys Router's administration screen.</b>
69
70 <blockquote>
71 <p>I take a pragmatic approach to software: form follows function.
72 To me, it is more important to have a reliable, fast, efficient,
@@ -83,11 +83,11 @@
83 keeps the bug-tracking database in a versioned file. That file can
84 then be pushed and pulled along with the rest repository.</b>
85
86 <blockquote>
87 <p>Fossil already <u>does</u> push and pull bugs along with the files
88 in your repository.
89 But fossil does <u>not</u> track bugs as files in the source tree.
90 That approach to bug tracking was rejected for three reasons:</p>
91
92 <ol>
93 <li> Check-ins in fossil are immutable. So if
@@ -108,11 +108,11 @@
108
109 <p>These points are reiterated in the opening paragraphs of
110 the <a href="bugtheory.wiki">Bug-Tracking In Fossil</a> document.</p>
111 </blockquote>
112
113 <b>Fossil is already the name of a plan9 versioned
114 append-only filesystem.</b>
115
116 <blockquote>
117 I did not know that. Perhaps they selected the name for the same reason that
118 I did: because a repository with immutable artifacts preserves
@@ -137,22 +137,22 @@
137 Subversion or Bazaar.</b>
138
139 <blockquote>
140 <p>I have no doubt that Trac has many features that fossil lacks. But that
141 is not the point. Fossil has several key features that Trac lacks and that
142 I need: most notably the fact that
143 fossil supports disconnected operation.</p>
144
145 <p>As for bloat: Fossil is a single self-contained executable.
146 You do not need any other packages
147 (diff, patch, merge, cvs, svn, rcs, git, python, perl, tcl, apache,
148 sqlite, and so forth)
149 in order to run fossil. Fossil runs just fine in a chroot jail all
150 by itself. And the self-contained fossil
151 executable is much less than 1MB in size. (Update 2015-01-12: Fossil has
152 grown in the years since the previous sentence was written but is still
153 much less than 2MB according to "size" when compiled using -Os on x64 Linux.)
154 Fossil is the very opposite of bloat.</p>
155 </blockquote>
156
157
158 </nowiki>
159
--- www/qandc.wiki
+++ www/qandc.wiki
@@ -22,11 +22,11 @@
22 <li> Integrated <a href="wikitheory.wiki">wiki</a>. </li>
23 <li> Integrated <a href="bugtheory.wiki">bug tracking</a> </li>
24 <li> Immutable artifacts </li>
25 <li> Self-contained, stand-alone executable that can be run in
26 a <a href="http://en.wikipedia.org/wiki/Chroot">chroot jail</a> </li>
27 <li> Simple, well-defined,
28 <a href="fileformat.wiki">enduring file format</a> </li>
29 <li> Integrated <a href="webui.wiki">web interface</a> </li>
30 </ol>
31 </blockquote>
32
@@ -36,11 +36,11 @@
36 <ol>
37 <li> Fossil is distributed. You can view and/or edit tickets, wiki, and
38 code while off network, then sync your changes later. With Trac, you
39 can only view and edit tickets and wiki while you are connected to
40 the server. </li>
41 <li> Fossil is lightweight and fully self-contained. It is very easy
42 to setup on a low-resource machine. Fossil does not require an
43 administrator.</li>
44 <li> Fossil integrates code versioning into the same repository with
45 wiki and tickets. There is nothing extra to add or install.
46 Fossil is an all-in-one turnkey solution. </li>
@@ -48,25 +48,25 @@
48 </blockquote>
49
50 <b>Love the concept here. Anyone using this for real work yet?</b>
51
52 <blockquote>
53 Fossil is <a href="http://www.fossil-scm.org/">self-hosting</a>.
54 In fact, this page was probably delivered
55 to your web-browser via a working fossil instance. The same virtual
56 machine that hosts http://www.fossil-scm.org/
57 (a <a href="http://www.linode.com/">Linode 720</a>)
58 also hosts 24 other fossil repositories for various small projects.
59 The documentation files for
60 <a href="http://www.sqlite.org/">SQLite</a> are hosted in a
61 fossil repository <a href="http://www.sqlite.org/docsrc/">here</a>,
62 for example.
63 Other projects are also adopting fossil. But fossil does not yet have
64 the massive user base of git or mercurial.
65 </blockquote>
66
67 <b>Fossil looks like the bug tracker that would be in your
68 Linksys Router's administration screen.</b>
69
70 <blockquote>
71 <p>I take a pragmatic approach to software: form follows function.
72 To me, it is more important to have a reliable, fast, efficient,
@@ -83,11 +83,11 @@
83 keeps the bug-tracking database in a versioned file. That file can
84 then be pushed and pulled along with the rest repository.</b>
85
86 <blockquote>
87 <p>Fossil already <u>does</u> push and pull bugs along with the files
88 in your repository.
89 But fossil does <u>not</u> track bugs as files in the source tree.
90 That approach to bug tracking was rejected for three reasons:</p>
91
92 <ol>
93 <li> Check-ins in fossil are immutable. So if
@@ -108,11 +108,11 @@
108
109 <p>These points are reiterated in the opening paragraphs of
110 the <a href="bugtheory.wiki">Bug-Tracking In Fossil</a> document.</p>
111 </blockquote>
112
113 <b>Fossil is already the name of a plan9 versioned
114 append-only filesystem.</b>
115
116 <blockquote>
117 I did not know that. Perhaps they selected the name for the same reason that
118 I did: because a repository with immutable artifacts preserves
@@ -137,22 +137,22 @@
137 Subversion or Bazaar.</b>
138
139 <blockquote>
140 <p>I have no doubt that Trac has many features that fossil lacks. But that
141 is not the point. Fossil has several key features that Trac lacks and that
142 I need: most notably the fact that
143 fossil supports disconnected operation.</p>
144
145 <p>As for bloat: Fossil is a single self-contained executable.
146 You do not need any other packages
147 (diff, patch, merge, cvs, svn, rcs, git, python, perl, tcl, apache,
148 sqlite, and so forth)
149 in order to run fossil. Fossil runs just fine in a chroot jail all
150 by itself. And the self-contained fossil
151 executable is much less than 1MB in size. (Update 2015-01-12: Fossil has
152 grown in the years since the previous sentence was written but is still
153 much less than 2MB according to "size" when compiled using -Os on x64 Linux.)
154 Fossil is the very opposite of bloat.</p>
155 </blockquote>
156
157
158 </nowiki>
159
--- www/quickstart.wiki
+++ www/quickstart.wiki
@@ -5,16 +5,16 @@
55
and painlessly.</p>
66
77
<h2>Installing</h2>
88
99
<p>Fossil is a single self-contained C program. You need to
10
- either download a
10
+ either download a
1111
<a href="http://www.fossil-scm.org/download.html">precompiled binary</a>
1212
or <a href="build.wiki">compile it yourself</a> from sources.
1313
Install fossil by putting the fossil binary
1414
someplace on your $PATH.</p>
15
-
15
+
1616
<a name="fslclone"></a>
1717
<h2>General Work Flow</h2>
1818
1919
<p>Fossil works with repository files (a database with the project's
2020
complete history) and with checked-out local trees (the working directory
@@ -34,11 +34,11 @@
3434
3535
<h2>Starting A New Project</h2>
3636
3737
<p>To start a new project with fossil, create a new empty repository
3838
this way: ([/help/init | more info]) </p>
39
-
39
+
4040
<blockquote>
4141
<b>fossil init </b><i> repository-filename</i>
4242
</blockquote>
4343
4444
<h2>Cloning An Existing Repository</h2>
@@ -46,36 +46,36 @@
4646
<p>Most fossil operations interact with a repository that is on the
4747
local disk drive, not on a remote system. Hence, before accessing
4848
a remote repository it is necessary to make a local copy of that
4949
repository. Making a local copy of a remote repository is called
5050
"cloning".</p>
51
-
51
+
5252
<p>Clone a remote repository as follows: ([/help/clone | more info])</p>
53
-
53
+
5454
<blockquote>
5555
<b>fossil clone</b> <i>URL repository-filename</i>
5656
</blockquote>
57
-
57
+
5858
<p>The <i>URL</i> specifies the fossil repository
5959
you want to clone. The <i>repository-filename</i> is the new local
6060
filename into which the cloned repository will be written. For
6161
example:
62
-
62
+
6363
<blockquote>
6464
<b>fossil clone http://www.fossil-scm.org/ myclone.fossil</b>
6565
</blockquote>
6666
67
- <p>If the remote repository requires a login, include a
67
+ <p>If the remote repository requires a login, include a
6868
userid in the URL like this:
6969
7070
<blockquote>
7171
<b>fossil clone http://</b><i>userid</i><b>@www.fossil-scm.org/ myclone.fossil</b>
7272
</blockquote>
73
-
73
+
7474
7575
<p>You will be prompted separately for the password.
76
- Use "%HH" escapes for special characters in the userid.
76
+ Use "%HH" escapes for special characters in the userid.
7777
Examples: "%40" in place of "@" and "%2F" in place of "/".
7878
7979
<p>If you are behind a restrictive firewall, you might need
8080
to <a href="#proxy">specify an HTTP proxy</a>.</p>
8181
@@ -85,31 +85,31 @@
8585
information above and beyond the versioned files, including some
8686
sensitive information such as password hashes and email addresses. If you
8787
want to share Fossil repositories directly, consider running the
8888
[/help/scrub|fossil scrub] command to remove sensitive information
8989
before transmitting the file.
90
-
90
+
9191
<h2>Importing From Another Version Control System</h2>
9292
9393
<p>Rather than start a new project, or clone an existing Fossil project,
94
- you might prefer to
94
+ you might prefer to
9595
<a href="./inout.wiki">import an existing Git project</a>
9696
into Fossil using the [/help/import | fossil import] command.
9797
9898
<h2>Checking Out A Local Tree</h2>
9999
100100
<p>To work on a project in fossil, you need to check out a local
101101
copy of the source tree. Create the directory you want to be
102102
the root of your tree and cd into that directory. Then
103103
do this: ([/help/open | more info])</p>
104
-
104
+
105105
<blockquote>
106106
<b>fossil open </b><i> repository-filename</i>
107107
</blockquote>
108
-
108
+
109109
<p>This leaves you with the newest version of the tree
110
- checked out.
110
+ checked out.
111111
From anywhere underneath the root of your local tree, you
112112
can type commands like the following to find out the status of
113113
your local tree:</p>
114114
115115
<blockquote>
@@ -122,11 +122,11 @@
122122
<b>[/help/branch | fossil branch]</b><br>
123123
</blockquote>
124124
125125
<p>Note that Fossil allows you to make multiple check-outs in
126126
separate directories from the same repository. This enables you,
127
- for example, to do builds from multiple branches or versions at
127
+ for example, to do builds from multiple branches or versions at
128128
the same time without having to generate extra clones.</p>
129129
130130
<p>To switch a checkout between different versions and branches,
131131
use:</p>
132132
@@ -140,17 +140,17 @@
140140
version, whereas [/help/checkout | checkout] does not
141141
automatically sync and does a "hard" switch, overwriting local
142142
changes if told to do so.</p>
143143
144144
<h2>Configuring Your Local Repository</h2>
145
-
145
+
146146
<p>When you create a new repository, either by cloning an existing
147147
project or create a new project of your own, you usually want to do some
148148
local configuration. This is easily accomplished using the web-server
149149
that is built into fossil. Start the fossil webserver like this:
150150
([/help/ui | more info])</p>
151
-
151
+
152152
<blockquote>
153153
<b>fossil ui </b><i> repository-filename</i>
154154
</blockquote>
155155
156156
<p>You can omit the <i>repository-filename</i> from the command above
@@ -163,15 +163,15 @@
163163
where to find your web browser using a command like this:</p>
164164
165165
<blockquote>
166166
<b>fossil setting web-browser </b><i> path-to-web-browser</i>
167167
</blockquote>
168
-
168
+
169169
<p>By default, fossil does not require a login for HTTP connections
170170
coming in from the IP loopback address 127.0.0.1. You can, and perhaps
171171
should, change this after you create a few users.</p>
172
-
172
+
173173
<p>When you are finished configuring, just press Control-C or use
174174
the <b>kill</b> command to shut down the mini-server.</p>
175175
176176
<h2>Making Changes</h2>
177177
@@ -194,18 +194,18 @@
194194
<p>You will be prompted for check-in comments using whatever editor
195195
is specified by your VISUAL or EDITOR environment variable.</p>
196196
197197
In the default configuration, the [/help/commit|commit]
198198
command will also automatically [/help/push|push] your changes, but that
199
- feature can be disabled. (More information about
199
+ feature can be disabled. (More information about
200200
[./concepts.wiki#workflow|autosync] and how to disable it.)
201
- Remember that your coworkers can not see your changes until you
201
+ Remember that your coworkers can not see your changes until you
202202
commit and push them.</p>
203203
204204
<h2>Sharing Changes</h2>
205205
206
- <p>When [./concepts.wiki#workflow|autosync] is turned off,
206
+ <p>When [./concepts.wiki#workflow|autosync] is turned off,
207207
the changes you [/help/commit | commit] are only
208208
on your local repository.
209209
To share those changes with other repositories, do:</p>
210210
211211
<blockquote>
@@ -241,11 +241,11 @@
241241
the <i>VERSION</i>, then fossil moves you to the
242242
latest version of the branch your are currently on.</p>
243243
244244
<p>The default behavior is for [./concepts.wiki#workflow|autosync] to
245245
be turned on. That means that a [/help/pull|pull] automatically occurs
246
- when you run [/help/update|update] and a [/help/push|push] happens
246
+ when you run [/help/update|update] and a [/help/push|push] happens
247247
automatically after you [/help/commit|commit]. So in normal practice,
248248
the push, pull, and sync commands are rarely used. But it is important
249249
to know about them, all the same.</p>
250250
251251
<blockquote>
@@ -342,11 +342,11 @@
342342
<li>[./server.wiki#cgi|CGI]
343343
<li>[./server.wiki#scgi|SCGI]
344344
</ul>
345345
346346
<p>The [./selfhost.wiki | self-hosting fossil repositories] use
347
- CGI.
347
+ CGI.
348348
349349
<a name="proxy"></a>
350350
<h2>HTTP Proxies</h2>
351351
352352
<p>If you are behind a restrictive firewall that requires you to use
@@ -382,11 +382,11 @@
382382
<p>Or unset the environment variable. The fossil setting for the
383383
HTTP proxy takes precedence over the environment variable and the
384384
command-line option overrides both. If you have an persistent
385385
proxy setting that you want to override for a one-time sync, that
386386
is easily done on the command-line. For example, to sync with
387
- a co-workers repository on your LAN, you might type:</p>
387
+ a co-workers repository on your LAN, you might type:</p>
388388
389389
<blockquote>
390390
<b>fossil sync http://192.168.1.36:8080/ --proxy off</b>
391391
</blockquote>
392392
393393
--- www/quickstart.wiki
+++ www/quickstart.wiki
@@ -5,16 +5,16 @@
5 and painlessly.</p>
6
7 <h2>Installing</h2>
8
9 <p>Fossil is a single self-contained C program. You need to
10 either download a
11 <a href="http://www.fossil-scm.org/download.html">precompiled binary</a>
12 or <a href="build.wiki">compile it yourself</a> from sources.
13 Install fossil by putting the fossil binary
14 someplace on your $PATH.</p>
15
16 <a name="fslclone"></a>
17 <h2>General Work Flow</h2>
18
19 <p>Fossil works with repository files (a database with the project's
20 complete history) and with checked-out local trees (the working directory
@@ -34,11 +34,11 @@
34
35 <h2>Starting A New Project</h2>
36
37 <p>To start a new project with fossil, create a new empty repository
38 this way: ([/help/init | more info]) </p>
39
40 <blockquote>
41 <b>fossil init </b><i> repository-filename</i>
42 </blockquote>
43
44 <h2>Cloning An Existing Repository</h2>
@@ -46,36 +46,36 @@
46 <p>Most fossil operations interact with a repository that is on the
47 local disk drive, not on a remote system. Hence, before accessing
48 a remote repository it is necessary to make a local copy of that
49 repository. Making a local copy of a remote repository is called
50 "cloning".</p>
51
52 <p>Clone a remote repository as follows: ([/help/clone | more info])</p>
53
54 <blockquote>
55 <b>fossil clone</b> <i>URL repository-filename</i>
56 </blockquote>
57
58 <p>The <i>URL</i> specifies the fossil repository
59 you want to clone. The <i>repository-filename</i> is the new local
60 filename into which the cloned repository will be written. For
61 example:
62
63 <blockquote>
64 <b>fossil clone http://www.fossil-scm.org/ myclone.fossil</b>
65 </blockquote>
66
67 <p>If the remote repository requires a login, include a
68 userid in the URL like this:
69
70 <blockquote>
71 <b>fossil clone http://</b><i>userid</i><b>@www.fossil-scm.org/ myclone.fossil</b>
72 </blockquote>
73
74
75 <p>You will be prompted separately for the password.
76 Use "%HH" escapes for special characters in the userid.
77 Examples: "%40" in place of "@" and "%2F" in place of "/".
78
79 <p>If you are behind a restrictive firewall, you might need
80 to <a href="#proxy">specify an HTTP proxy</a>.</p>
81
@@ -85,31 +85,31 @@
85 information above and beyond the versioned files, including some
86 sensitive information such as password hashes and email addresses. If you
87 want to share Fossil repositories directly, consider running the
88 [/help/scrub|fossil scrub] command to remove sensitive information
89 before transmitting the file.
90
91 <h2>Importing From Another Version Control System</h2>
92
93 <p>Rather than start a new project, or clone an existing Fossil project,
94 you might prefer to
95 <a href="./inout.wiki">import an existing Git project</a>
96 into Fossil using the [/help/import | fossil import] command.
97
98 <h2>Checking Out A Local Tree</h2>
99
100 <p>To work on a project in fossil, you need to check out a local
101 copy of the source tree. Create the directory you want to be
102 the root of your tree and cd into that directory. Then
103 do this: ([/help/open | more info])</p>
104
105 <blockquote>
106 <b>fossil open </b><i> repository-filename</i>
107 </blockquote>
108
109 <p>This leaves you with the newest version of the tree
110 checked out.
111 From anywhere underneath the root of your local tree, you
112 can type commands like the following to find out the status of
113 your local tree:</p>
114
115 <blockquote>
@@ -122,11 +122,11 @@
122 <b>[/help/branch | fossil branch]</b><br>
123 </blockquote>
124
125 <p>Note that Fossil allows you to make multiple check-outs in
126 separate directories from the same repository. This enables you,
127 for example, to do builds from multiple branches or versions at
128 the same time without having to generate extra clones.</p>
129
130 <p>To switch a checkout between different versions and branches,
131 use:</p>
132
@@ -140,17 +140,17 @@
140 version, whereas [/help/checkout | checkout] does not
141 automatically sync and does a "hard" switch, overwriting local
142 changes if told to do so.</p>
143
144 <h2>Configuring Your Local Repository</h2>
145
146 <p>When you create a new repository, either by cloning an existing
147 project or create a new project of your own, you usually want to do some
148 local configuration. This is easily accomplished using the web-server
149 that is built into fossil. Start the fossil webserver like this:
150 ([/help/ui | more info])</p>
151
152 <blockquote>
153 <b>fossil ui </b><i> repository-filename</i>
154 </blockquote>
155
156 <p>You can omit the <i>repository-filename</i> from the command above
@@ -163,15 +163,15 @@
163 where to find your web browser using a command like this:</p>
164
165 <blockquote>
166 <b>fossil setting web-browser </b><i> path-to-web-browser</i>
167 </blockquote>
168
169 <p>By default, fossil does not require a login for HTTP connections
170 coming in from the IP loopback address 127.0.0.1. You can, and perhaps
171 should, change this after you create a few users.</p>
172
173 <p>When you are finished configuring, just press Control-C or use
174 the <b>kill</b> command to shut down the mini-server.</p>
175
176 <h2>Making Changes</h2>
177
@@ -194,18 +194,18 @@
194 <p>You will be prompted for check-in comments using whatever editor
195 is specified by your VISUAL or EDITOR environment variable.</p>
196
197 In the default configuration, the [/help/commit|commit]
198 command will also automatically [/help/push|push] your changes, but that
199 feature can be disabled. (More information about
200 [./concepts.wiki#workflow|autosync] and how to disable it.)
201 Remember that your coworkers can not see your changes until you
202 commit and push them.</p>
203
204 <h2>Sharing Changes</h2>
205
206 <p>When [./concepts.wiki#workflow|autosync] is turned off,
207 the changes you [/help/commit | commit] are only
208 on your local repository.
209 To share those changes with other repositories, do:</p>
210
211 <blockquote>
@@ -241,11 +241,11 @@
241 the <i>VERSION</i>, then fossil moves you to the
242 latest version of the branch your are currently on.</p>
243
244 <p>The default behavior is for [./concepts.wiki#workflow|autosync] to
245 be turned on. That means that a [/help/pull|pull] automatically occurs
246 when you run [/help/update|update] and a [/help/push|push] happens
247 automatically after you [/help/commit|commit]. So in normal practice,
248 the push, pull, and sync commands are rarely used. But it is important
249 to know about them, all the same.</p>
250
251 <blockquote>
@@ -342,11 +342,11 @@
342 <li>[./server.wiki#cgi|CGI]
343 <li>[./server.wiki#scgi|SCGI]
344 </ul>
345
346 <p>The [./selfhost.wiki | self-hosting fossil repositories] use
347 CGI.
348
349 <a name="proxy"></a>
350 <h2>HTTP Proxies</h2>
351
352 <p>If you are behind a restrictive firewall that requires you to use
@@ -382,11 +382,11 @@
382 <p>Or unset the environment variable. The fossil setting for the
383 HTTP proxy takes precedence over the environment variable and the
384 command-line option overrides both. If you have an persistent
385 proxy setting that you want to override for a one-time sync, that
386 is easily done on the command-line. For example, to sync with
387 a co-workers repository on your LAN, you might type:</p>
388
389 <blockquote>
390 <b>fossil sync http://192.168.1.36:8080/ --proxy off</b>
391 </blockquote>
392
393
--- www/quickstart.wiki
+++ www/quickstart.wiki
@@ -5,16 +5,16 @@
5 and painlessly.</p>
6
7 <h2>Installing</h2>
8
9 <p>Fossil is a single self-contained C program. You need to
10 either download a
11 <a href="http://www.fossil-scm.org/download.html">precompiled binary</a>
12 or <a href="build.wiki">compile it yourself</a> from sources.
13 Install fossil by putting the fossil binary
14 someplace on your $PATH.</p>
15
16 <a name="fslclone"></a>
17 <h2>General Work Flow</h2>
18
19 <p>Fossil works with repository files (a database with the project's
20 complete history) and with checked-out local trees (the working directory
@@ -34,11 +34,11 @@
34
35 <h2>Starting A New Project</h2>
36
37 <p>To start a new project with fossil, create a new empty repository
38 this way: ([/help/init | more info]) </p>
39
40 <blockquote>
41 <b>fossil init </b><i> repository-filename</i>
42 </blockquote>
43
44 <h2>Cloning An Existing Repository</h2>
@@ -46,36 +46,36 @@
46 <p>Most fossil operations interact with a repository that is on the
47 local disk drive, not on a remote system. Hence, before accessing
48 a remote repository it is necessary to make a local copy of that
49 repository. Making a local copy of a remote repository is called
50 "cloning".</p>
51
52 <p>Clone a remote repository as follows: ([/help/clone | more info])</p>
53
54 <blockquote>
55 <b>fossil clone</b> <i>URL repository-filename</i>
56 </blockquote>
57
58 <p>The <i>URL</i> specifies the fossil repository
59 you want to clone. The <i>repository-filename</i> is the new local
60 filename into which the cloned repository will be written. For
61 example:
62
63 <blockquote>
64 <b>fossil clone http://www.fossil-scm.org/ myclone.fossil</b>
65 </blockquote>
66
67 <p>If the remote repository requires a login, include a
68 userid in the URL like this:
69
70 <blockquote>
71 <b>fossil clone http://</b><i>userid</i><b>@www.fossil-scm.org/ myclone.fossil</b>
72 </blockquote>
73
74
75 <p>You will be prompted separately for the password.
76 Use "%HH" escapes for special characters in the userid.
77 Examples: "%40" in place of "@" and "%2F" in place of "/".
78
79 <p>If you are behind a restrictive firewall, you might need
80 to <a href="#proxy">specify an HTTP proxy</a>.</p>
81
@@ -85,31 +85,31 @@
85 information above and beyond the versioned files, including some
86 sensitive information such as password hashes and email addresses. If you
87 want to share Fossil repositories directly, consider running the
88 [/help/scrub|fossil scrub] command to remove sensitive information
89 before transmitting the file.
90
91 <h2>Importing From Another Version Control System</h2>
92
93 <p>Rather than start a new project, or clone an existing Fossil project,
94 you might prefer to
95 <a href="./inout.wiki">import an existing Git project</a>
96 into Fossil using the [/help/import | fossil import] command.
97
98 <h2>Checking Out A Local Tree</h2>
99
100 <p>To work on a project in fossil, you need to check out a local
101 copy of the source tree. Create the directory you want to be
102 the root of your tree and cd into that directory. Then
103 do this: ([/help/open | more info])</p>
104
105 <blockquote>
106 <b>fossil open </b><i> repository-filename</i>
107 </blockquote>
108
109 <p>This leaves you with the newest version of the tree
110 checked out.
111 From anywhere underneath the root of your local tree, you
112 can type commands like the following to find out the status of
113 your local tree:</p>
114
115 <blockquote>
@@ -122,11 +122,11 @@
122 <b>[/help/branch | fossil branch]</b><br>
123 </blockquote>
124
125 <p>Note that Fossil allows you to make multiple check-outs in
126 separate directories from the same repository. This enables you,
127 for example, to do builds from multiple branches or versions at
128 the same time without having to generate extra clones.</p>
129
130 <p>To switch a checkout between different versions and branches,
131 use:</p>
132
@@ -140,17 +140,17 @@
140 version, whereas [/help/checkout | checkout] does not
141 automatically sync and does a "hard" switch, overwriting local
142 changes if told to do so.</p>
143
144 <h2>Configuring Your Local Repository</h2>
145
146 <p>When you create a new repository, either by cloning an existing
147 project or create a new project of your own, you usually want to do some
148 local configuration. This is easily accomplished using the web-server
149 that is built into fossil. Start the fossil webserver like this:
150 ([/help/ui | more info])</p>
151
152 <blockquote>
153 <b>fossil ui </b><i> repository-filename</i>
154 </blockquote>
155
156 <p>You can omit the <i>repository-filename</i> from the command above
@@ -163,15 +163,15 @@
163 where to find your web browser using a command like this:</p>
164
165 <blockquote>
166 <b>fossil setting web-browser </b><i> path-to-web-browser</i>
167 </blockquote>
168
169 <p>By default, fossil does not require a login for HTTP connections
170 coming in from the IP loopback address 127.0.0.1. You can, and perhaps
171 should, change this after you create a few users.</p>
172
173 <p>When you are finished configuring, just press Control-C or use
174 the <b>kill</b> command to shut down the mini-server.</p>
175
176 <h2>Making Changes</h2>
177
@@ -194,18 +194,18 @@
194 <p>You will be prompted for check-in comments using whatever editor
195 is specified by your VISUAL or EDITOR environment variable.</p>
196
197 In the default configuration, the [/help/commit|commit]
198 command will also automatically [/help/push|push] your changes, but that
199 feature can be disabled. (More information about
200 [./concepts.wiki#workflow|autosync] and how to disable it.)
201 Remember that your coworkers can not see your changes until you
202 commit and push them.</p>
203
204 <h2>Sharing Changes</h2>
205
206 <p>When [./concepts.wiki#workflow|autosync] is turned off,
207 the changes you [/help/commit | commit] are only
208 on your local repository.
209 To share those changes with other repositories, do:</p>
210
211 <blockquote>
@@ -241,11 +241,11 @@
241 the <i>VERSION</i>, then fossil moves you to the
242 latest version of the branch your are currently on.</p>
243
244 <p>The default behavior is for [./concepts.wiki#workflow|autosync] to
245 be turned on. That means that a [/help/pull|pull] automatically occurs
246 when you run [/help/update|update] and a [/help/push|push] happens
247 automatically after you [/help/commit|commit]. So in normal practice,
248 the push, pull, and sync commands are rarely used. But it is important
249 to know about them, all the same.</p>
250
251 <blockquote>
@@ -342,11 +342,11 @@
342 <li>[./server.wiki#cgi|CGI]
343 <li>[./server.wiki#scgi|SCGI]
344 </ul>
345
346 <p>The [./selfhost.wiki | self-hosting fossil repositories] use
347 CGI.
348
349 <a name="proxy"></a>
350 <h2>HTTP Proxies</h2>
351
352 <p>If you are behind a restrictive firewall that requires you to use
@@ -382,11 +382,11 @@
382 <p>Or unset the environment variable. The fossil setting for the
383 HTTP proxy takes precedence over the environment variable and the
384 command-line option overrides both. If you have an persistent
385 proxy setting that you want to override for a one-time sync, that
386 is easily done on the command-line. For example, to sync with
387 a co-workers repository on your LAN, you might type:</p>
388
389 <blockquote>
390 <b>fossil sync http://192.168.1.36:8080/ --proxy off</b>
391 </blockquote>
392
393
+13 -13
--- www/quotes.wiki
+++ www/quotes.wiki
@@ -5,19 +5,19 @@
55
by the creator of Fossil, so of course there is selection bias...
66
77
<h2>On The Usability Of Git:</h2>
88
99
<ol>
10
-<li>Git approaches the usability of iptables, which is to say, utterly
10
+<li>Git approaches the usability of iptables, which is to say, utterly
1111
unusable unless you have the manpage tattooed on you arm.
1212
1313
<blockquote>
1414
<i>by mml at [http://news.ycombinator.com/item?id=1433387]</i>
1515
</blockquote>
1616
1717
<li><nowiki>It's simplest to think of the state of your [git] repository
18
-as a point in a high-dimensional "code-space", in which branches are
18
+as a point in a high-dimensional "code-space", in which branches are
1919
represented as n-dimensional membranes, mapping the spatial loci of
2020
successive commits onto the projected manifold of each cloned
2121
repository.</nowiki>
2222
2323
<blockquote>
@@ -25,11 +25,11 @@
2525
</blockquote>
2626
2727
<li>Git is not a Prius. Git is a Model T.
2828
Its plumbing and wiring sticks out all over the place.
2929
You have to be a mechanic to operate it successfully or you'll be
30
-stuck on the side of the road when it breaks down.
30
+stuck on the side of the road when it breaks down.
3131
And it <b>will</b> break down.
3232
3333
<blockquote>
3434
<i>Nick Farina at [http://nfarina.com/post/9868516270/git-is-simpler]</i>
3535
</blockquote>
@@ -39,11 +39,11 @@
3939
<blockquote>
4040
<i>Linus Torvalds - 2005-04-07 22:13:13<br>
4141
Commit comment on the very first source-code check-in for git
4242
</blockquote>
4343
44
-<li>I've been experimenting a lot with git at work.
44
+<li>I've been experimenting a lot with git at work.
4545
Damn, it's complicated.
4646
It has things to trip you up with that sane people just wouldn't ever both with
4747
including the ability to allow you to commit stuff in such a way that you can't find
4848
it again afterwards (!!!)
4949
Demented workflow complexity on acid?
@@ -104,19 +104,19 @@
104104
105105
<blockquote>
106106
<i>Joe Prostko at [http://www.mail-archive.com/[email protected]/msg16716.html]
107107
</blockquote>
108108
109
-<li>Fossil is awesome!!! I have never seen an app like that before,
109
+<li>Fossil is awesome!!! I have never seen an app like that before,
110110
such simplicity and flexibility!!!
111111
112112
<blockquote>
113113
<i>zengr at [http://stackoverflow.com/questions/138621/best-version-control-for-lone-developer]</i>
114114
</blockquote>
115115
116116
<li>This is my favourite VCS. I can carry it on a USB. And it's a complete system, with it's own
117
-server, ticketing system, Wiki pages, and a very, very helpful timeline visualization. And
117
+server, ticketing system, Wiki pages, and a very, very helpful timeline visualization. And
118118
the entire program in a single file!
119119
120120
<blockquote>
121121
<i>thunderbong commenting on hacker news: [https://news.ycombinator.com/item?id=9131619]</i>
122122
</blockquote>
@@ -127,30 +127,30 @@
127127
128128
<h2>On Git Versus Fossil</h2>
129129
130130
<ol>
131131
<li value=15>
132
-Just want to say thanks for fossil making my life easier....
132
+Just want to say thanks for fossil making my life easier....
133133
Also <nowiki>[for]</nowiki> not having a misanthropic command line interface.
134134
135135
<blockquote>
136136
<i>Joshua Paine at [http://www.mail-archive.com/[email protected]/msg02736.html]</i>
137137
</blockquote>
138138
139139
<li>We use it at a large university to manage code that small teams write.
140
-The runs everywhere, ease of installation and portability is something that
141
-seems to be a good fit with the environment we have (highly ditrobuted,
142
-sometimes very restrictive firewalls, OSX/Win/Linux). We are happy with it
143
-and teaching a Msc/Phd student (read complete novice) fossil has just
140
+The runs everywhere, ease of installation and portability is something that
141
+seems to be a good fit with the environment we have (highly ditrobuted,
142
+sometimes very restrictive firewalls, OSX/Win/Linux). We are happy with it
143
+and teaching a Msc/Phd student (read complete novice) fossil has just
144144
been a smoother ride than Git was.
145145
146146
<blockquote>
147147
<i>viablepanic at [http://www.reddit.com/r/programming/comments/bxcto/why_not_fossil_scm/]</i>
148148
</blockquote>
149149
150
-<li>In the fossil community - and hence in fossil itself - development history
151
-is pretty much sacrosanct. The very name "fossil" was to chosen to
150
+<li>In the fossil community - and hence in fossil itself - development history
151
+is pretty much sacrosanct. The very name "fossil" was to chosen to
152152
reflect the unchanging nature of things in that history.
153153
154154
<p>In git (or rather, the git community), the development history is part of
155155
the published aspect of the project, so it provides tools for rearranging
156156
that history so you can present what you "should" have done rather
157157
--- www/quotes.wiki
+++ www/quotes.wiki
@@ -5,19 +5,19 @@
5 by the creator of Fossil, so of course there is selection bias...
6
7 <h2>On The Usability Of Git:</h2>
8
9 <ol>
10 <li>Git approaches the usability of iptables, which is to say, utterly
11 unusable unless you have the manpage tattooed on you arm.
12
13 <blockquote>
14 <i>by mml at [http://news.ycombinator.com/item?id=1433387]</i>
15 </blockquote>
16
17 <li><nowiki>It's simplest to think of the state of your [git] repository
18 as a point in a high-dimensional "code-space", in which branches are
19 represented as n-dimensional membranes, mapping the spatial loci of
20 successive commits onto the projected manifold of each cloned
21 repository.</nowiki>
22
23 <blockquote>
@@ -25,11 +25,11 @@
25 </blockquote>
26
27 <li>Git is not a Prius. Git is a Model T.
28 Its plumbing and wiring sticks out all over the place.
29 You have to be a mechanic to operate it successfully or you'll be
30 stuck on the side of the road when it breaks down.
31 And it <b>will</b> break down.
32
33 <blockquote>
34 <i>Nick Farina at [http://nfarina.com/post/9868516270/git-is-simpler]</i>
35 </blockquote>
@@ -39,11 +39,11 @@
39 <blockquote>
40 <i>Linus Torvalds - 2005-04-07 22:13:13<br>
41 Commit comment on the very first source-code check-in for git
42 </blockquote>
43
44 <li>I've been experimenting a lot with git at work.
45 Damn, it's complicated.
46 It has things to trip you up with that sane people just wouldn't ever both with
47 including the ability to allow you to commit stuff in such a way that you can't find
48 it again afterwards (!!!)
49 Demented workflow complexity on acid?
@@ -104,19 +104,19 @@
104
105 <blockquote>
106 <i>Joe Prostko at [http://www.mail-archive.com/[email protected]/msg16716.html]
107 </blockquote>
108
109 <li>Fossil is awesome!!! I have never seen an app like that before,
110 such simplicity and flexibility!!!
111
112 <blockquote>
113 <i>zengr at [http://stackoverflow.com/questions/138621/best-version-control-for-lone-developer]</i>
114 </blockquote>
115
116 <li>This is my favourite VCS. I can carry it on a USB. And it's a complete system, with it's own
117 server, ticketing system, Wiki pages, and a very, very helpful timeline visualization. And
118 the entire program in a single file!
119
120 <blockquote>
121 <i>thunderbong commenting on hacker news: [https://news.ycombinator.com/item?id=9131619]</i>
122 </blockquote>
@@ -127,30 +127,30 @@
127
128 <h2>On Git Versus Fossil</h2>
129
130 <ol>
131 <li value=15>
132 Just want to say thanks for fossil making my life easier....
133 Also <nowiki>[for]</nowiki> not having a misanthropic command line interface.
134
135 <blockquote>
136 <i>Joshua Paine at [http://www.mail-archive.com/[email protected]/msg02736.html]</i>
137 </blockquote>
138
139 <li>We use it at a large university to manage code that small teams write.
140 The runs everywhere, ease of installation and portability is something that
141 seems to be a good fit with the environment we have (highly ditrobuted,
142 sometimes very restrictive firewalls, OSX/Win/Linux). We are happy with it
143 and teaching a Msc/Phd student (read complete novice) fossil has just
144 been a smoother ride than Git was.
145
146 <blockquote>
147 <i>viablepanic at [http://www.reddit.com/r/programming/comments/bxcto/why_not_fossil_scm/]</i>
148 </blockquote>
149
150 <li>In the fossil community - and hence in fossil itself - development history
151 is pretty much sacrosanct. The very name "fossil" was to chosen to
152 reflect the unchanging nature of things in that history.
153
154 <p>In git (or rather, the git community), the development history is part of
155 the published aspect of the project, so it provides tools for rearranging
156 that history so you can present what you "should" have done rather
157
--- www/quotes.wiki
+++ www/quotes.wiki
@@ -5,19 +5,19 @@
5 by the creator of Fossil, so of course there is selection bias...
6
7 <h2>On The Usability Of Git:</h2>
8
9 <ol>
10 <li>Git approaches the usability of iptables, which is to say, utterly
11 unusable unless you have the manpage tattooed on you arm.
12
13 <blockquote>
14 <i>by mml at [http://news.ycombinator.com/item?id=1433387]</i>
15 </blockquote>
16
17 <li><nowiki>It's simplest to think of the state of your [git] repository
18 as a point in a high-dimensional "code-space", in which branches are
19 represented as n-dimensional membranes, mapping the spatial loci of
20 successive commits onto the projected manifold of each cloned
21 repository.</nowiki>
22
23 <blockquote>
@@ -25,11 +25,11 @@
25 </blockquote>
26
27 <li>Git is not a Prius. Git is a Model T.
28 Its plumbing and wiring sticks out all over the place.
29 You have to be a mechanic to operate it successfully or you'll be
30 stuck on the side of the road when it breaks down.
31 And it <b>will</b> break down.
32
33 <blockquote>
34 <i>Nick Farina at [http://nfarina.com/post/9868516270/git-is-simpler]</i>
35 </blockquote>
@@ -39,11 +39,11 @@
39 <blockquote>
40 <i>Linus Torvalds - 2005-04-07 22:13:13<br>
41 Commit comment on the very first source-code check-in for git
42 </blockquote>
43
44 <li>I've been experimenting a lot with git at work.
45 Damn, it's complicated.
46 It has things to trip you up with that sane people just wouldn't ever both with
47 including the ability to allow you to commit stuff in such a way that you can't find
48 it again afterwards (!!!)
49 Demented workflow complexity on acid?
@@ -104,19 +104,19 @@
104
105 <blockquote>
106 <i>Joe Prostko at [http://www.mail-archive.com/[email protected]/msg16716.html]
107 </blockquote>
108
109 <li>Fossil is awesome!!! I have never seen an app like that before,
110 such simplicity and flexibility!!!
111
112 <blockquote>
113 <i>zengr at [http://stackoverflow.com/questions/138621/best-version-control-for-lone-developer]</i>
114 </blockquote>
115
116 <li>This is my favourite VCS. I can carry it on a USB. And it's a complete system, with it's own
117 server, ticketing system, Wiki pages, and a very, very helpful timeline visualization. And
118 the entire program in a single file!
119
120 <blockquote>
121 <i>thunderbong commenting on hacker news: [https://news.ycombinator.com/item?id=9131619]</i>
122 </blockquote>
@@ -127,30 +127,30 @@
127
128 <h2>On Git Versus Fossil</h2>
129
130 <ol>
131 <li value=15>
132 Just want to say thanks for fossil making my life easier....
133 Also <nowiki>[for]</nowiki> not having a misanthropic command line interface.
134
135 <blockquote>
136 <i>Joshua Paine at [http://www.mail-archive.com/[email protected]/msg02736.html]</i>
137 </blockquote>
138
139 <li>We use it at a large university to manage code that small teams write.
140 The runs everywhere, ease of installation and portability is something that
141 seems to be a good fit with the environment we have (highly ditrobuted,
142 sometimes very restrictive firewalls, OSX/Win/Linux). We are happy with it
143 and teaching a Msc/Phd student (read complete novice) fossil has just
144 been a smoother ride than Git was.
145
146 <blockquote>
147 <i>viablepanic at [http://www.reddit.com/r/programming/comments/bxcto/why_not_fossil_scm/]</i>
148 </blockquote>
149
150 <li>In the fossil community - and hence in fossil itself - development history
151 is pretty much sacrosanct. The very name "fossil" was to chosen to
152 reflect the unchanging nature of things in that history.
153
154 <p>In git (or rather, the git community), the development history is part of
155 the published aspect of the project, so it provides tools for rearranging
156 that history so you can present what you "should" have done rather
157
+12 -12
--- www/reviews.wiki
+++ www/reviews.wiki
@@ -1,8 +1,8 @@
11
<title>Reviews</title>
22
<b>External links:</b>
3
-
3
+
44
* [http://nixtu.blogspot.com/2010/03/fossil-dvcs-on-go-first-impressions.html |
55
Fossil DVCS on the Go - First Impressions]
66
* [http://blog.mired.org/2011/02/fossil-sweet-spot-in-vcs-space.html |
77
Fossil - a sweet spot in the VCS space] by Mike Meyer.
88
* [http://blog.s11n.net/?p=72|Four reasons to take a closer look at the Fossil SCM] by Stephan Beal
@@ -22,27 +22,27 @@
2222
2323
2424
<b>Joshua Paine on 2010-10-22:</b>
2525
2626
<blockquote>
27
-With one of my several hats on, I'm in a small team using git. Another
28
-team member just checked some stuff into trunk that should have been on
29
-a branch. Nothing else had happened since, so in fossil I would have
30
-just edited that commit and put it on a new branch. In git that can't
31
-actually be done without danger once other people have pulled, so I had
32
-to create a new commit rolling back the changes, then branch and cherry
33
-pick the earlier changes, then figure out how to make my new branch
34
-shared instead of private. Just want to say thanks for fossil making my
35
-life easier on most of my projects, and being able to move commits to
36
-another branch after the fact and shared-by-default branches are good
27
+With one of my several hats on, I'm in a small team using git. Another
28
+team member just checked some stuff into trunk that should have been on
29
+a branch. Nothing else had happened since, so in fossil I would have
30
+just edited that commit and put it on a new branch. In git that can't
31
+actually be done without danger once other people have pulled, so I had
32
+to create a new commit rolling back the changes, then branch and cherry
33
+pick the earlier changes, then figure out how to make my new branch
34
+shared instead of private. Just want to say thanks for fossil making my
35
+life easier on most of my projects, and being able to move commits to
36
+another branch after the fact and shared-by-default branches are good
3737
features. Also not having a misanthropic command line interface.
3838
</blockquote>
3939
4040
<b>Stephan Beal writes on 2009-01-11:</b>
4141
4242
<blockquote>
43
-Sometime in late 2007 I came across a link to fossil on
43
+Sometime in late 2007 I came across a link to fossil on
4444
<a href="http://www.sqlite.org/">sqlite.org</a>. It
4545
was a good thing I bookmarked it, because I was never able to find the
4646
link again (it might have been in a bug report or something). The
4747
reasons I first took a close look at it were (A) it stemmed from the
4848
sqlite project, which I've held in high regards for years (e.g. I
4949
--- www/reviews.wiki
+++ www/reviews.wiki
@@ -1,8 +1,8 @@
1 <title>Reviews</title>
2 <b>External links:</b>
3
4 * [http://nixtu.blogspot.com/2010/03/fossil-dvcs-on-go-first-impressions.html |
5 Fossil DVCS on the Go - First Impressions]
6 * [http://blog.mired.org/2011/02/fossil-sweet-spot-in-vcs-space.html |
7 Fossil - a sweet spot in the VCS space] by Mike Meyer.
8 * [http://blog.s11n.net/?p=72|Four reasons to take a closer look at the Fossil SCM] by Stephan Beal
@@ -22,27 +22,27 @@
22
23
24 <b>Joshua Paine on 2010-10-22:</b>
25
26 <blockquote>
27 With one of my several hats on, I'm in a small team using git. Another
28 team member just checked some stuff into trunk that should have been on
29 a branch. Nothing else had happened since, so in fossil I would have
30 just edited that commit and put it on a new branch. In git that can't
31 actually be done without danger once other people have pulled, so I had
32 to create a new commit rolling back the changes, then branch and cherry
33 pick the earlier changes, then figure out how to make my new branch
34 shared instead of private. Just want to say thanks for fossil making my
35 life easier on most of my projects, and being able to move commits to
36 another branch after the fact and shared-by-default branches are good
37 features. Also not having a misanthropic command line interface.
38 </blockquote>
39
40 <b>Stephan Beal writes on 2009-01-11:</b>
41
42 <blockquote>
43 Sometime in late 2007 I came across a link to fossil on
44 <a href="http://www.sqlite.org/">sqlite.org</a>. It
45 was a good thing I bookmarked it, because I was never able to find the
46 link again (it might have been in a bug report or something). The
47 reasons I first took a close look at it were (A) it stemmed from the
48 sqlite project, which I've held in high regards for years (e.g. I
49
--- www/reviews.wiki
+++ www/reviews.wiki
@@ -1,8 +1,8 @@
1 <title>Reviews</title>
2 <b>External links:</b>
3
4 * [http://nixtu.blogspot.com/2010/03/fossil-dvcs-on-go-first-impressions.html |
5 Fossil DVCS on the Go - First Impressions]
6 * [http://blog.mired.org/2011/02/fossil-sweet-spot-in-vcs-space.html |
7 Fossil - a sweet spot in the VCS space] by Mike Meyer.
8 * [http://blog.s11n.net/?p=72|Four reasons to take a closer look at the Fossil SCM] by Stephan Beal
@@ -22,27 +22,27 @@
22
23
24 <b>Joshua Paine on 2010-10-22:</b>
25
26 <blockquote>
27 With one of my several hats on, I'm in a small team using git. Another
28 team member just checked some stuff into trunk that should have been on
29 a branch. Nothing else had happened since, so in fossil I would have
30 just edited that commit and put it on a new branch. In git that can't
31 actually be done without danger once other people have pulled, so I had
32 to create a new commit rolling back the changes, then branch and cherry
33 pick the earlier changes, then figure out how to make my new branch
34 shared instead of private. Just want to say thanks for fossil making my
35 life easier on most of my projects, and being able to move commits to
36 another branch after the fact and shared-by-default branches are good
37 features. Also not having a misanthropic command line interface.
38 </blockquote>
39
40 <b>Stephan Beal writes on 2009-01-11:</b>
41
42 <blockquote>
43 Sometime in late 2007 I came across a link to fossil on
44 <a href="http://www.sqlite.org/">sqlite.org</a>. It
45 was a good thing I bookmarked it, because I was never able to find the
46 link again (it might have been in a bug report or something). The
47 reasons I first took a close look at it were (A) it stemmed from the
48 sqlite project, which I've held in high regards for years (e.g. I
49
--- www/selfcheck.wiki
+++ www/selfcheck.wiki
@@ -14,11 +14,11 @@
1414
lost. The integrity checks are doing their job well.</p>
1515
1616
<h2>Atomic Check-ins With Rollback</h2>
1717
1818
The fossil repository is stored in an
19
-<a href="http://www.sqlite.org/">SQLite</a> database file.
19
+<a href="http://www.sqlite.org/">SQLite</a> database file.
2020
([./tech_overview.wiki | Addition information] about the repository
2121
file format.)
2222
SQLite is very mature and stable and has been in wide-spread use for many
2323
years, so we are confident it will not cause repository
2424
corruption. SQLite
@@ -61,11 +61,11 @@
6161
message is printed and the transaction rolls back.
6262
6363
So, in other words, fossil always checks to make sure it can
6464
re-extract a file before it commits a change to that file.
6565
Hence bugs in fossil are unlikely to corrupt the repository in
66
-a way that prevents us from extracting historical versions of
66
+a way that prevents us from extracting historical versions of
6767
files.
6868
6969
<h2>Checksum Over All Files In A Check-in</h2>
7070
7171
Manifest artifacts that define a check-in have two fields (the
@@ -102,7 +102,7 @@
102102
<a href="http://en.wikipedia.org/wiki/The_Tortoise_and_the_Hare">tortoise</a>:
103103
reliability is more important than raw speed. The developers of
104104
fossil see no merit in getting the wrong answer quickly.
105105
106106
Fossil may not be the fastest versioning system, but it is "fast enough".
107
-Fossil runs quickly enough to stay out of the developers way.
107
+Fossil runs quickly enough to stay out of the developers way.
108108
Most operations complete in under a second.
109109
--- www/selfcheck.wiki
+++ www/selfcheck.wiki
@@ -14,11 +14,11 @@
14 lost. The integrity checks are doing their job well.</p>
15
16 <h2>Atomic Check-ins With Rollback</h2>
17
18 The fossil repository is stored in an
19 <a href="http://www.sqlite.org/">SQLite</a> database file.
20 ([./tech_overview.wiki | Addition information] about the repository
21 file format.)
22 SQLite is very mature and stable and has been in wide-spread use for many
23 years, so we are confident it will not cause repository
24 corruption. SQLite
@@ -61,11 +61,11 @@
61 message is printed and the transaction rolls back.
62
63 So, in other words, fossil always checks to make sure it can
64 re-extract a file before it commits a change to that file.
65 Hence bugs in fossil are unlikely to corrupt the repository in
66 a way that prevents us from extracting historical versions of
67 files.
68
69 <h2>Checksum Over All Files In A Check-in</h2>
70
71 Manifest artifacts that define a check-in have two fields (the
@@ -102,7 +102,7 @@
102 <a href="http://en.wikipedia.org/wiki/The_Tortoise_and_the_Hare">tortoise</a>:
103 reliability is more important than raw speed. The developers of
104 fossil see no merit in getting the wrong answer quickly.
105
106 Fossil may not be the fastest versioning system, but it is "fast enough".
107 Fossil runs quickly enough to stay out of the developers way.
108 Most operations complete in under a second.
109
--- www/selfcheck.wiki
+++ www/selfcheck.wiki
@@ -14,11 +14,11 @@
14 lost. The integrity checks are doing their job well.</p>
15
16 <h2>Atomic Check-ins With Rollback</h2>
17
18 The fossil repository is stored in an
19 <a href="http://www.sqlite.org/">SQLite</a> database file.
20 ([./tech_overview.wiki | Addition information] about the repository
21 file format.)
22 SQLite is very mature and stable and has been in wide-spread use for many
23 years, so we are confident it will not cause repository
24 corruption. SQLite
@@ -61,11 +61,11 @@
61 message is printed and the transaction rolls back.
62
63 So, in other words, fossil always checks to make sure it can
64 re-extract a file before it commits a change to that file.
65 Hence bugs in fossil are unlikely to corrupt the repository in
66 a way that prevents us from extracting historical versions of
67 files.
68
69 <h2>Checksum Over All Files In A Check-in</h2>
70
71 Manifest artifacts that define a check-in have two fields (the
@@ -102,7 +102,7 @@
102 <a href="http://en.wikipedia.org/wiki/The_Tortoise_and_the_Hare">tortoise</a>:
103 reliability is more important than raw speed. The developers of
104 fossil see no merit in getting the wrong answer quickly.
105
106 Fossil may not be the fastest versioning system, but it is "fast enough".
107 Fossil runs quickly enough to stay out of the developers way.
108 Most operations complete in under a second.
109
--- www/selfhost.wiki
+++ www/selfhost.wiki
@@ -7,23 +7,23 @@
77
2. [http://www2.fossil-scm.org/]
88
3. [http://www3.fossil-scm.org/site.cgi]
99
1010
1111
The canonical repository is (1). Repositories (2) and (3) automatically
12
-stay in synchronization with (1) via a
12
+stay in synchronization with (1) via a
1313
<a href="http://en.wikipedia.org/wiki/Cron">cron job</a> that invokes
1414
"fossil sync" at regular intervals.
1515
1616
Note that the two secondary repositories are more than just read-only mirrors.
1717
All three servers support full read/write capabilities.
18
-Changes (such as new tickets or wiki or check-ins) can be implemented
18
+Changes (such as new tickets or wiki or check-ins) can be implemented
1919
on any of the three servers and those changes automatically propagate to the
2020
other two servers.
2121
2222
Server (1) runs as a CGI script on a
2323
<a href="http://www.linode.com/">Linode 1024</a> located in Dallas, TX
24
-- on the same virtual machine that
24
+- on the same virtual machine that
2525
hosts <a href="http://www.sqlite.org/">SQLite</a> and over a
2626
dozen other smaller projects. This demonstrates that Fossil can run on
2727
a low-power host processor.
2828
Multiple fossil-based projects can easily be hosted on the same machine,
2929
even if that machine is itself one of several dozen virtual machines on
@@ -34,17 +34,17 @@
3434
#!/usr/bin/fossil
3535
repository: /fossil/fossil.fossil
3636
</pre></blockquote>
3737
3838
Server (3) runs as a CGI script on a shared hosting account at
39
-<a href="http://www.he.net/">Hurricane Electric</a> in Fremont, CA.
39
+<a href="http://www.he.net/">Hurricane Electric</a> in Fremont, CA.
4040
This server demonstrates the ability of
4141
Fossil to run on an economical shared-host web account with no
4242
privileges beyond port 80 HTTP access and CGI. It is not necessary
4343
to have a dedicated computer with administrator privileges to run Fossil.
44
-As far as we are aware,
45
-Fossil is the only full-featured configuration management system
44
+As far as we are aware,
45
+Fossil is the only full-featured configuration management system
4646
that can run in
4747
such a restricted environment. The CGI script that runs on the
4848
Hurricane Electric server is the same as the CGI script shown above,
4949
except that the pathnames are modified to suit the environment:
5050
5151
--- www/selfhost.wiki
+++ www/selfhost.wiki
@@ -7,23 +7,23 @@
7 2. [http://www2.fossil-scm.org/]
8 3. [http://www3.fossil-scm.org/site.cgi]
9
10
11 The canonical repository is (1). Repositories (2) and (3) automatically
12 stay in synchronization with (1) via a
13 <a href="http://en.wikipedia.org/wiki/Cron">cron job</a> that invokes
14 "fossil sync" at regular intervals.
15
16 Note that the two secondary repositories are more than just read-only mirrors.
17 All three servers support full read/write capabilities.
18 Changes (such as new tickets or wiki or check-ins) can be implemented
19 on any of the three servers and those changes automatically propagate to the
20 other two servers.
21
22 Server (1) runs as a CGI script on a
23 <a href="http://www.linode.com/">Linode 1024</a> located in Dallas, TX
24 - on the same virtual machine that
25 hosts <a href="http://www.sqlite.org/">SQLite</a> and over a
26 dozen other smaller projects. This demonstrates that Fossil can run on
27 a low-power host processor.
28 Multiple fossil-based projects can easily be hosted on the same machine,
29 even if that machine is itself one of several dozen virtual machines on
@@ -34,17 +34,17 @@
34 #!/usr/bin/fossil
35 repository: /fossil/fossil.fossil
36 </pre></blockquote>
37
38 Server (3) runs as a CGI script on a shared hosting account at
39 <a href="http://www.he.net/">Hurricane Electric</a> in Fremont, CA.
40 This server demonstrates the ability of
41 Fossil to run on an economical shared-host web account with no
42 privileges beyond port 80 HTTP access and CGI. It is not necessary
43 to have a dedicated computer with administrator privileges to run Fossil.
44 As far as we are aware,
45 Fossil is the only full-featured configuration management system
46 that can run in
47 such a restricted environment. The CGI script that runs on the
48 Hurricane Electric server is the same as the CGI script shown above,
49 except that the pathnames are modified to suit the environment:
50
51
--- www/selfhost.wiki
+++ www/selfhost.wiki
@@ -7,23 +7,23 @@
7 2. [http://www2.fossil-scm.org/]
8 3. [http://www3.fossil-scm.org/site.cgi]
9
10
11 The canonical repository is (1). Repositories (2) and (3) automatically
12 stay in synchronization with (1) via a
13 <a href="http://en.wikipedia.org/wiki/Cron">cron job</a> that invokes
14 "fossil sync" at regular intervals.
15
16 Note that the two secondary repositories are more than just read-only mirrors.
17 All three servers support full read/write capabilities.
18 Changes (such as new tickets or wiki or check-ins) can be implemented
19 on any of the three servers and those changes automatically propagate to the
20 other two servers.
21
22 Server (1) runs as a CGI script on a
23 <a href="http://www.linode.com/">Linode 1024</a> located in Dallas, TX
24 - on the same virtual machine that
25 hosts <a href="http://www.sqlite.org/">SQLite</a> and over a
26 dozen other smaller projects. This demonstrates that Fossil can run on
27 a low-power host processor.
28 Multiple fossil-based projects can easily be hosted on the same machine,
29 even if that machine is itself one of several dozen virtual machines on
@@ -34,17 +34,17 @@
34 #!/usr/bin/fossil
35 repository: /fossil/fossil.fossil
36 </pre></blockquote>
37
38 Server (3) runs as a CGI script on a shared hosting account at
39 <a href="http://www.he.net/">Hurricane Electric</a> in Fremont, CA.
40 This server demonstrates the ability of
41 Fossil to run on an economical shared-host web account with no
42 privileges beyond port 80 HTTP access and CGI. It is not necessary
43 to have a dedicated computer with administrator privileges to run Fossil.
44 As far as we are aware,
45 Fossil is the only full-featured configuration management system
46 that can run in
47 such a restricted environment. The CGI script that runs on the
48 Hurricane Electric server is the same as the CGI script shown above,
49 except that the pathnames are modified to suit the environment:
50
51
+20 -20
--- www/server.wiki
+++ www/server.wiki
@@ -2,11 +2,11 @@
22
<h2>Introduction</h2><blockquote>
33
<p>A server is not necessary to use Fossil, but a server does help in collaborating with
44
peers. A Fossil server also works well as a complete website for a project.
55
For example, the complete [https://www.fossil-scm.org/] website, including the
66
page you are now reading,
7
-is just a Fossil server displaying the content of the
7
+is just a Fossil server displaying the content of the
88
self-hosting repository for Fossil.</p>
99
<p>This article is a guide for setting up your own Fossil server.
1010
<p>See "[./aboutcgi.wiki|How CGI Works In Fossil]" for background
1111
information on the underlying CGI technology.
1212
See "[./sync.wiki|The Fossil Sync Protocol]" for information on the
@@ -18,11 +18,11 @@
1818
<li>A stand-alone server
1919
<li>Using inetd or xinetd or stunnel
2020
<li>CGI
2121
<li>SCGI (a.k.a. SimpleCGI)
2222
</ol>
23
-Each of these can serve either a single repository, or a directory hierarchy
23
+Each of these can serve either a single repository, or a directory hierarchy
2424
containing many repositories with names ending in ".fossil".
2525
</blockquote>
2626
<a name="standalone"></a>
2727
<h2>Standalone server</h2><blockquote>
2828
The easiest way to set up a Fossil server is to use either the
@@ -34,11 +34,11 @@
3434
<p>
3535
The <i>REPOSITORY</i> argument is either the name of the repository file, or
3636
a directory containing many repositories.
3737
Both of these commands start a Fossil server, usually on TCP port 8080, though
3838
a higher numbered port might also be used if 8080 is already occupied. You can
39
-access these using URLs of the form <b>http://localhost:8080/</b>, or if
39
+access these using URLs of the form <b>http://localhost:8080/</b>, or if
4040
<i>REPOSITORY</i> is a directory, URLs of the form
4141
<b>http://localhost:8080/</b><i>repo</i><b>/</b> where <i>repo</i> is the base
4242
name of the repository file without the ".fossil" suffix.
4343
The difference between "ui" and "server" is that "ui" will
4444
also start a web browser and point it
@@ -75,23 +75,23 @@
7575
need to modify the pathnames for your particular setup.
7676
The final argument is either the name of the fossil repository to be served,
7777
or a directory containing multiple repositories.
7878
</p>
7979
<p>
80
-If you use a non-standard TCP port on
81
-systems where the port-specification must be a symbolic name and cannot be
80
+If you use a non-standard TCP port on
81
+systems where the port-specification must be a symbolic name and cannot be
8282
numeric, add the desired name and port to /etc/services. For example, if
8383
you want your Fossil server running on TCP port 12345 instead of 80, you
8484
will need to add:
8585
<blockquote>
8686
<pre>
8787
fossil 12345/tcp #fossil server
8888
</pre>
8989
</blockquote>
90
-and use the symbolic name ('fossil' in this example) instead of the numeral ('12345')
91
-in inetd.conf. For details, see the relevant section in your system's documentation, e.g.
92
-the [https://www.freebsd.org/doc/en/books/handbook/network-inetd.html|FreeBSD Handbook] in
90
+and use the symbolic name ('fossil' in this example) instead of the numeral ('12345')
91
+in inetd.conf. For details, see the relevant section in your system's documentation, e.g.
92
+the [https://www.freebsd.org/doc/en/books/handbook/network-inetd.html|FreeBSD Handbook] in
9393
case you use FreeBSD.
9494
</p>
9595
<p>
9696
If your system is running xinetd, then the configuration is likely to be
9797
in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d".
@@ -119,11 +119,11 @@
119119
jail for the user who owns the fossil repository before reading any information
120120
off of the wire.
121121
</p>
122122
<p>
123123
Inetd or xinetd must be enabled, and must be (re)started whenever their configuration
124
-changes - consult your system's documentation for details.
124
+changes - consult your system's documentation for details.
125125
</p>
126126
<p>
127127
[https://www.stunnel.org/ | Stunnel version 5] is an inetd-like process that
128128
accepts and decodes SSL-encrypted connections. Fossil can be run directly from
129129
stunnel in a manner similar to inetd and xinetd. This can be used to provide
@@ -137,15 +137,15 @@
137137
TIMEOUTclose = 0
138138
exec = /usr/bin/fossil
139139
execargs = /usr/bin/fossil http /home/fossil/ubercool.fossil --https
140140
</nowiki></pre></blockquote>
141141
See the stunnel5 documentation for further details about the /etc/stunnel/stunnel.conf
142
-configuration file. Note that the [/help/http|fossil http] command should include
142
+configuration file. Note that the [/help/http|fossil http] command should include
143143
the --https option to let Fossil know to use "https" instead of "http" as the scheme
144144
on generated hyperlinks.
145145
<p>
146
-Using inetd or xinetd or stunnel is a more complex setup
146
+Using inetd or xinetd or stunnel is a more complex setup
147147
than the "standalone" server, but it has the
148148
advantage of only using system resources when an actual connection is
149149
attempted. If no-one ever connects to that port, a Fossil server will
150150
not (automatically) run. It has the disadvantage of requiring "root" access
151151
and therefore may not normally be available to lower-priced "shared" servers
@@ -155,11 +155,11 @@
155155
<a name="cgi"></a>
156156
<h2>Fossil as CGI</h2><blockquote>
157157
<p>
158158
A Fossil server can also be run from an ordinary web server as a CGI program.
159159
This feature allows Fossil to be seamlessly integrated into a larger website.
160
-CGI is how the [./selfhost.wiki | self-hosting fossil repositories] are
160
+CGI is how the [./selfhost.wiki | self-hosting fossil repositories] are
161161
implemented.
162162
</p>
163163
<p>
164164
To run Fossil as CGI, create a CGI script (here called "repo") in the CGI directory
165165
of your web server and having content like this:
@@ -184,12 +184,12 @@
184184
script itself must be executable for the user under which it will run (which often differs
185185
from the one running the web server - consult your site's documentation or administrator).</li>
186186
<li>The repository file AND the directory containing it must be writable by the same account
187187
which executes the Fossil binary (again, this might differ from the WWW user). The directory
188188
needs to be writable so that sqlite can write its journal files.</li>
189
-<li>Fossil must be able to create temporary files, the default directory
190
-for which depends on the OS. When the CGI process is operating within
189
+<li>Fossil must be able to create temporary files, the default directory
190
+for which depends on the OS. When the CGI process is operating within
191191
a chroot, ensure that this directory exists and is readable/writeable
192192
by the user who executes the Fossil binary.</li>
193193
</ul>
194194
</p>
195195
@@ -219,11 +219,11 @@
219219
220220
<a name="scgi"></a>
221221
<h2>Fossil as SCGI</h2><blockquote>
222222
223223
<p>
224
-The [/help/server|fossil server] command, described above as a way of
224
+The [/help/server|fossil server] command, described above as a way of
225225
starting a stand-alone web server, can also be used for SCGI. Simply add
226226
the --scgi command-line option and the stand-alone server will interpret
227227
and respond to the SimpleCGI or SCGI protocol rather than raw HTTP. This can
228228
be used in combination with a webserver (such as [http://nginx.org|Nginx])
229229
that does not support CGI. A typical Nginx configuration to support SCGI
@@ -284,27 +284,27 @@
284284
</blockquote>
285285
286286
<a name="loadmgmt"></a>
287287
<h2>Managing Server Load</h2><blockquote>
288288
<p>
289
-A Fossil server is very efficient and normally presents a very light
289
+A Fossil server is very efficient and normally presents a very light
290290
load on the server.
291291
The Fossil [./selfhost.wiki | self-hosting server] is a 1/24th slice VM at
292292
[http://www.linode.com | Linode.com] hosting 65 other repositories in
293293
addition to Fossil (and including some very high-traffic sites such
294294
as [http://www.sqlite.org] and [http://system.data.sqlite.org]) and
295295
it has a typical load of 0.05 to 0.1. A single HTTP request to Fossil
296296
normally takes less than 10 milliseconds of CPU time to complete. So
297
-requests can be arriving at a continuous rate of 20 or more per second
297
+requests can be arriving at a continuous rate of 20 or more per second
298298
and the CPU can still be mostly idle.
299299
<p>
300
-However, there are some Fossil web pages that can consume large
300
+However, there are some Fossil web pages that can consume large
301301
amounts of CPU time, especially on repositories with a large number
302302
of files or with long revision histories. High CPU usage pages include
303303
[/help?cmd=/zip | /zip], [/help?cmd=/tarball | /tarball],
304304
[/help?cmd=/annotate | /annotate] and others. On very large repositories,
305
-these commands can take 15 seconds or more of CPU time.
305
+these commands can take 15 seconds or more of CPU time.
306306
If these kinds of requests arrive too quickly, the load average on the
307307
server can grow dramatically, making the server unresponsive.
308308
<p>
309309
Fossil provides two capabilities to help avoid server overload problems
310310
due to excessive requests to expensive pages:
@@ -312,11 +312,11 @@
312312
<li><p>An optional cache is available that remembers the 10 most recently
313313
requested /zip or /tarball pages and returns the precomputed answer
314314
if the same page is requested again.
315315
<li><p>Page requests can be configured to fail with a
316316
[http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.3 | "503 Server Overload"]
317
- HTTP error if an expensive request is received while the host load
317
+ HTTP error if an expensive request is received while the host load
318318
average is too high.
319319
</ol>
320320
Both of these load-control mechanisms are turned off by default, but they
321321
are recommended for high-traffic sites.
322322
<p>
323323
--- www/server.wiki
+++ www/server.wiki
@@ -2,11 +2,11 @@
2 <h2>Introduction</h2><blockquote>
3 <p>A server is not necessary to use Fossil, but a server does help in collaborating with
4 peers. A Fossil server also works well as a complete website for a project.
5 For example, the complete [https://www.fossil-scm.org/] website, including the
6 page you are now reading,
7 is just a Fossil server displaying the content of the
8 self-hosting repository for Fossil.</p>
9 <p>This article is a guide for setting up your own Fossil server.
10 <p>See "[./aboutcgi.wiki|How CGI Works In Fossil]" for background
11 information on the underlying CGI technology.
12 See "[./sync.wiki|The Fossil Sync Protocol]" for information on the
@@ -18,11 +18,11 @@
18 <li>A stand-alone server
19 <li>Using inetd or xinetd or stunnel
20 <li>CGI
21 <li>SCGI (a.k.a. SimpleCGI)
22 </ol>
23 Each of these can serve either a single repository, or a directory hierarchy
24 containing many repositories with names ending in ".fossil".
25 </blockquote>
26 <a name="standalone"></a>
27 <h2>Standalone server</h2><blockquote>
28 The easiest way to set up a Fossil server is to use either the
@@ -34,11 +34,11 @@
34 <p>
35 The <i>REPOSITORY</i> argument is either the name of the repository file, or
36 a directory containing many repositories.
37 Both of these commands start a Fossil server, usually on TCP port 8080, though
38 a higher numbered port might also be used if 8080 is already occupied. You can
39 access these using URLs of the form <b>http://localhost:8080/</b>, or if
40 <i>REPOSITORY</i> is a directory, URLs of the form
41 <b>http://localhost:8080/</b><i>repo</i><b>/</b> where <i>repo</i> is the base
42 name of the repository file without the ".fossil" suffix.
43 The difference between "ui" and "server" is that "ui" will
44 also start a web browser and point it
@@ -75,23 +75,23 @@
75 need to modify the pathnames for your particular setup.
76 The final argument is either the name of the fossil repository to be served,
77 or a directory containing multiple repositories.
78 </p>
79 <p>
80 If you use a non-standard TCP port on
81 systems where the port-specification must be a symbolic name and cannot be
82 numeric, add the desired name and port to /etc/services. For example, if
83 you want your Fossil server running on TCP port 12345 instead of 80, you
84 will need to add:
85 <blockquote>
86 <pre>
87 fossil 12345/tcp #fossil server
88 </pre>
89 </blockquote>
90 and use the symbolic name ('fossil' in this example) instead of the numeral ('12345')
91 in inetd.conf. For details, see the relevant section in your system's documentation, e.g.
92 the [https://www.freebsd.org/doc/en/books/handbook/network-inetd.html|FreeBSD Handbook] in
93 case you use FreeBSD.
94 </p>
95 <p>
96 If your system is running xinetd, then the configuration is likely to be
97 in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d".
@@ -119,11 +119,11 @@
119 jail for the user who owns the fossil repository before reading any information
120 off of the wire.
121 </p>
122 <p>
123 Inetd or xinetd must be enabled, and must be (re)started whenever their configuration
124 changes - consult your system's documentation for details.
125 </p>
126 <p>
127 [https://www.stunnel.org/ | Stunnel version 5] is an inetd-like process that
128 accepts and decodes SSL-encrypted connections. Fossil can be run directly from
129 stunnel in a manner similar to inetd and xinetd. This can be used to provide
@@ -137,15 +137,15 @@
137 TIMEOUTclose = 0
138 exec = /usr/bin/fossil
139 execargs = /usr/bin/fossil http /home/fossil/ubercool.fossil --https
140 </nowiki></pre></blockquote>
141 See the stunnel5 documentation for further details about the /etc/stunnel/stunnel.conf
142 configuration file. Note that the [/help/http|fossil http] command should include
143 the --https option to let Fossil know to use "https" instead of "http" as the scheme
144 on generated hyperlinks.
145 <p>
146 Using inetd or xinetd or stunnel is a more complex setup
147 than the "standalone" server, but it has the
148 advantage of only using system resources when an actual connection is
149 attempted. If no-one ever connects to that port, a Fossil server will
150 not (automatically) run. It has the disadvantage of requiring "root" access
151 and therefore may not normally be available to lower-priced "shared" servers
@@ -155,11 +155,11 @@
155 <a name="cgi"></a>
156 <h2>Fossil as CGI</h2><blockquote>
157 <p>
158 A Fossil server can also be run from an ordinary web server as a CGI program.
159 This feature allows Fossil to be seamlessly integrated into a larger website.
160 CGI is how the [./selfhost.wiki | self-hosting fossil repositories] are
161 implemented.
162 </p>
163 <p>
164 To run Fossil as CGI, create a CGI script (here called "repo") in the CGI directory
165 of your web server and having content like this:
@@ -184,12 +184,12 @@
184 script itself must be executable for the user under which it will run (which often differs
185 from the one running the web server - consult your site's documentation or administrator).</li>
186 <li>The repository file AND the directory containing it must be writable by the same account
187 which executes the Fossil binary (again, this might differ from the WWW user). The directory
188 needs to be writable so that sqlite can write its journal files.</li>
189 <li>Fossil must be able to create temporary files, the default directory
190 for which depends on the OS. When the CGI process is operating within
191 a chroot, ensure that this directory exists and is readable/writeable
192 by the user who executes the Fossil binary.</li>
193 </ul>
194 </p>
195
@@ -219,11 +219,11 @@
219
220 <a name="scgi"></a>
221 <h2>Fossil as SCGI</h2><blockquote>
222
223 <p>
224 The [/help/server|fossil server] command, described above as a way of
225 starting a stand-alone web server, can also be used for SCGI. Simply add
226 the --scgi command-line option and the stand-alone server will interpret
227 and respond to the SimpleCGI or SCGI protocol rather than raw HTTP. This can
228 be used in combination with a webserver (such as [http://nginx.org|Nginx])
229 that does not support CGI. A typical Nginx configuration to support SCGI
@@ -284,27 +284,27 @@
284 </blockquote>
285
286 <a name="loadmgmt"></a>
287 <h2>Managing Server Load</h2><blockquote>
288 <p>
289 A Fossil server is very efficient and normally presents a very light
290 load on the server.
291 The Fossil [./selfhost.wiki | self-hosting server] is a 1/24th slice VM at
292 [http://www.linode.com | Linode.com] hosting 65 other repositories in
293 addition to Fossil (and including some very high-traffic sites such
294 as [http://www.sqlite.org] and [http://system.data.sqlite.org]) and
295 it has a typical load of 0.05 to 0.1. A single HTTP request to Fossil
296 normally takes less than 10 milliseconds of CPU time to complete. So
297 requests can be arriving at a continuous rate of 20 or more per second
298 and the CPU can still be mostly idle.
299 <p>
300 However, there are some Fossil web pages that can consume large
301 amounts of CPU time, especially on repositories with a large number
302 of files or with long revision histories. High CPU usage pages include
303 [/help?cmd=/zip | /zip], [/help?cmd=/tarball | /tarball],
304 [/help?cmd=/annotate | /annotate] and others. On very large repositories,
305 these commands can take 15 seconds or more of CPU time.
306 If these kinds of requests arrive too quickly, the load average on the
307 server can grow dramatically, making the server unresponsive.
308 <p>
309 Fossil provides two capabilities to help avoid server overload problems
310 due to excessive requests to expensive pages:
@@ -312,11 +312,11 @@
312 <li><p>An optional cache is available that remembers the 10 most recently
313 requested /zip or /tarball pages and returns the precomputed answer
314 if the same page is requested again.
315 <li><p>Page requests can be configured to fail with a
316 [http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.3 | "503 Server Overload"]
317 HTTP error if an expensive request is received while the host load
318 average is too high.
319 </ol>
320 Both of these load-control mechanisms are turned off by default, but they
321 are recommended for high-traffic sites.
322 <p>
323
--- www/server.wiki
+++ www/server.wiki
@@ -2,11 +2,11 @@
2 <h2>Introduction</h2><blockquote>
3 <p>A server is not necessary to use Fossil, but a server does help in collaborating with
4 peers. A Fossil server also works well as a complete website for a project.
5 For example, the complete [https://www.fossil-scm.org/] website, including the
6 page you are now reading,
7 is just a Fossil server displaying the content of the
8 self-hosting repository for Fossil.</p>
9 <p>This article is a guide for setting up your own Fossil server.
10 <p>See "[./aboutcgi.wiki|How CGI Works In Fossil]" for background
11 information on the underlying CGI technology.
12 See "[./sync.wiki|The Fossil Sync Protocol]" for information on the
@@ -18,11 +18,11 @@
18 <li>A stand-alone server
19 <li>Using inetd or xinetd or stunnel
20 <li>CGI
21 <li>SCGI (a.k.a. SimpleCGI)
22 </ol>
23 Each of these can serve either a single repository, or a directory hierarchy
24 containing many repositories with names ending in ".fossil".
25 </blockquote>
26 <a name="standalone"></a>
27 <h2>Standalone server</h2><blockquote>
28 The easiest way to set up a Fossil server is to use either the
@@ -34,11 +34,11 @@
34 <p>
35 The <i>REPOSITORY</i> argument is either the name of the repository file, or
36 a directory containing many repositories.
37 Both of these commands start a Fossil server, usually on TCP port 8080, though
38 a higher numbered port might also be used if 8080 is already occupied. You can
39 access these using URLs of the form <b>http://localhost:8080/</b>, or if
40 <i>REPOSITORY</i> is a directory, URLs of the form
41 <b>http://localhost:8080/</b><i>repo</i><b>/</b> where <i>repo</i> is the base
42 name of the repository file without the ".fossil" suffix.
43 The difference between "ui" and "server" is that "ui" will
44 also start a web browser and point it
@@ -75,23 +75,23 @@
75 need to modify the pathnames for your particular setup.
76 The final argument is either the name of the fossil repository to be served,
77 or a directory containing multiple repositories.
78 </p>
79 <p>
80 If you use a non-standard TCP port on
81 systems where the port-specification must be a symbolic name and cannot be
82 numeric, add the desired name and port to /etc/services. For example, if
83 you want your Fossil server running on TCP port 12345 instead of 80, you
84 will need to add:
85 <blockquote>
86 <pre>
87 fossil 12345/tcp #fossil server
88 </pre>
89 </blockquote>
90 and use the symbolic name ('fossil' in this example) instead of the numeral ('12345')
91 in inetd.conf. For details, see the relevant section in your system's documentation, e.g.
92 the [https://www.freebsd.org/doc/en/books/handbook/network-inetd.html|FreeBSD Handbook] in
93 case you use FreeBSD.
94 </p>
95 <p>
96 If your system is running xinetd, then the configuration is likely to be
97 in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d".
@@ -119,11 +119,11 @@
119 jail for the user who owns the fossil repository before reading any information
120 off of the wire.
121 </p>
122 <p>
123 Inetd or xinetd must be enabled, and must be (re)started whenever their configuration
124 changes - consult your system's documentation for details.
125 </p>
126 <p>
127 [https://www.stunnel.org/ | Stunnel version 5] is an inetd-like process that
128 accepts and decodes SSL-encrypted connections. Fossil can be run directly from
129 stunnel in a manner similar to inetd and xinetd. This can be used to provide
@@ -137,15 +137,15 @@
137 TIMEOUTclose = 0
138 exec = /usr/bin/fossil
139 execargs = /usr/bin/fossil http /home/fossil/ubercool.fossil --https
140 </nowiki></pre></blockquote>
141 See the stunnel5 documentation for further details about the /etc/stunnel/stunnel.conf
142 configuration file. Note that the [/help/http|fossil http] command should include
143 the --https option to let Fossil know to use "https" instead of "http" as the scheme
144 on generated hyperlinks.
145 <p>
146 Using inetd or xinetd or stunnel is a more complex setup
147 than the "standalone" server, but it has the
148 advantage of only using system resources when an actual connection is
149 attempted. If no-one ever connects to that port, a Fossil server will
150 not (automatically) run. It has the disadvantage of requiring "root" access
151 and therefore may not normally be available to lower-priced "shared" servers
@@ -155,11 +155,11 @@
155 <a name="cgi"></a>
156 <h2>Fossil as CGI</h2><blockquote>
157 <p>
158 A Fossil server can also be run from an ordinary web server as a CGI program.
159 This feature allows Fossil to be seamlessly integrated into a larger website.
160 CGI is how the [./selfhost.wiki | self-hosting fossil repositories] are
161 implemented.
162 </p>
163 <p>
164 To run Fossil as CGI, create a CGI script (here called "repo") in the CGI directory
165 of your web server and having content like this:
@@ -184,12 +184,12 @@
184 script itself must be executable for the user under which it will run (which often differs
185 from the one running the web server - consult your site's documentation or administrator).</li>
186 <li>The repository file AND the directory containing it must be writable by the same account
187 which executes the Fossil binary (again, this might differ from the WWW user). The directory
188 needs to be writable so that sqlite can write its journal files.</li>
189 <li>Fossil must be able to create temporary files, the default directory
190 for which depends on the OS. When the CGI process is operating within
191 a chroot, ensure that this directory exists and is readable/writeable
192 by the user who executes the Fossil binary.</li>
193 </ul>
194 </p>
195
@@ -219,11 +219,11 @@
219
220 <a name="scgi"></a>
221 <h2>Fossil as SCGI</h2><blockquote>
222
223 <p>
224 The [/help/server|fossil server] command, described above as a way of
225 starting a stand-alone web server, can also be used for SCGI. Simply add
226 the --scgi command-line option and the stand-alone server will interpret
227 and respond to the SimpleCGI or SCGI protocol rather than raw HTTP. This can
228 be used in combination with a webserver (such as [http://nginx.org|Nginx])
229 that does not support CGI. A typical Nginx configuration to support SCGI
@@ -284,27 +284,27 @@
284 </blockquote>
285
286 <a name="loadmgmt"></a>
287 <h2>Managing Server Load</h2><blockquote>
288 <p>
289 A Fossil server is very efficient and normally presents a very light
290 load on the server.
291 The Fossil [./selfhost.wiki | self-hosting server] is a 1/24th slice VM at
292 [http://www.linode.com | Linode.com] hosting 65 other repositories in
293 addition to Fossil (and including some very high-traffic sites such
294 as [http://www.sqlite.org] and [http://system.data.sqlite.org]) and
295 it has a typical load of 0.05 to 0.1. A single HTTP request to Fossil
296 normally takes less than 10 milliseconds of CPU time to complete. So
297 requests can be arriving at a continuous rate of 20 or more per second
298 and the CPU can still be mostly idle.
299 <p>
300 However, there are some Fossil web pages that can consume large
301 amounts of CPU time, especially on repositories with a large number
302 of files or with long revision histories. High CPU usage pages include
303 [/help?cmd=/zip | /zip], [/help?cmd=/tarball | /tarball],
304 [/help?cmd=/annotate | /annotate] and others. On very large repositories,
305 these commands can take 15 seconds or more of CPU time.
306 If these kinds of requests arrive too quickly, the load average on the
307 server can grow dramatically, making the server unresponsive.
308 <p>
309 Fossil provides two capabilities to help avoid server overload problems
310 due to excessive requests to expensive pages:
@@ -312,11 +312,11 @@
312 <li><p>An optional cache is available that remembers the 10 most recently
313 requested /zip or /tarball pages and returns the precomputed answer
314 if the same page is requested again.
315 <li><p>Page requests can be configured to fail with a
316 [http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.3 | "503 Server Overload"]
317 HTTP error if an expensive request is received while the host load
318 average is too high.
319 </ol>
320 Both of these load-control mechanisms are turned off by default, but they
321 are recommended for high-traffic sites.
322 <p>
323
--- www/settings.wiki
+++ www/settings.wiki
@@ -4,11 +4,11 @@
44
55
Settings control the behaviour of fossil. They are set with the
66
<tt>fossil settings</tt> command, or through the web interface in
77
the Settings page in the Admin section.
88
9
-For a list of all settings, view the Settings page, or type
9
+For a list of all settings, view the Settings page, or type
1010
<tt>fossil help settings</tt> from the command line.
1111
1212
1313
<h3>Repository settings</h3>
1414
@@ -16,17 +16,17 @@
1616
a subset of settings are copied to your local repository.
1717
1818
If you make a change to a setting on your local repository, it is not
1919
synced back to the server when you <tt>push</tt> or <tt>sync</tt>. If
2020
you make a change on the server, you need to manually make the change on
21
-all repositories which are cloned from this repository.
21
+all repositories which are cloned from this repository.
2222
2323
You can also set a setting globally on your local machine. The value
2424
will be used for all repositories cloned to your machine, unless
2525
overridden explicitly in a particular repository. Global settings can be
2626
set by using the <tt>-global</tt> option on the <tt>fossil settings</tt>
27
-command.
27
+command.
2828
2929
<h3>"Versionable" settings</h3>
3030
3131
Most of the settings control the behaviour of fossil on your local
3232
machine, largely acting to reflect your preference on how you want to
3333
--- www/settings.wiki
+++ www/settings.wiki
@@ -4,11 +4,11 @@
4
5 Settings control the behaviour of fossil. They are set with the
6 <tt>fossil settings</tt> command, or through the web interface in
7 the Settings page in the Admin section.
8
9 For a list of all settings, view the Settings page, or type
10 <tt>fossil help settings</tt> from the command line.
11
12
13 <h3>Repository settings</h3>
14
@@ -16,17 +16,17 @@
16 a subset of settings are copied to your local repository.
17
18 If you make a change to a setting on your local repository, it is not
19 synced back to the server when you <tt>push</tt> or <tt>sync</tt>. If
20 you make a change on the server, you need to manually make the change on
21 all repositories which are cloned from this repository.
22
23 You can also set a setting globally on your local machine. The value
24 will be used for all repositories cloned to your machine, unless
25 overridden explicitly in a particular repository. Global settings can be
26 set by using the <tt>-global</tt> option on the <tt>fossil settings</tt>
27 command.
28
29 <h3>"Versionable" settings</h3>
30
31 Most of the settings control the behaviour of fossil on your local
32 machine, largely acting to reflect your preference on how you want to
33
--- www/settings.wiki
+++ www/settings.wiki
@@ -4,11 +4,11 @@
4
5 Settings control the behaviour of fossil. They are set with the
6 <tt>fossil settings</tt> command, or through the web interface in
7 the Settings page in the Admin section.
8
9 For a list of all settings, view the Settings page, or type
10 <tt>fossil help settings</tt> from the command line.
11
12
13 <h3>Repository settings</h3>
14
@@ -16,17 +16,17 @@
16 a subset of settings are copied to your local repository.
17
18 If you make a change to a setting on your local repository, it is not
19 synced back to the server when you <tt>push</tt> or <tt>sync</tt>. If
20 you make a change on the server, you need to manually make the change on
21 all repositories which are cloned from this repository.
22
23 You can also set a setting globally on your local machine. The value
24 will be used for all repositories cloned to your machine, unless
25 overridden explicitly in a particular repository. Global settings can be
26 set by using the <tt>-global</tt> option on the <tt>fossil settings</tt>
27 command.
28
29 <h3>"Versionable" settings</h3>
30
31 Most of the settings control the behaviour of fossil on your local
32 machine, largely acting to reflect your preference on how you want to
33
+10 -10
--- www/shunning.wiki
+++ www/shunning.wiki
@@ -2,11 +2,11 @@
22
<h1 align="center">Deleting Content From Fossil</h1>
33
44
Fossil is designed to keep all historical content forever. Users
55
of Fossil are discouraged from "deleting" content simply because it
66
has become obsolete. Old content is part of the historical record
7
-(part of the "fossil record") and should be maintained indefinitely.
7
+(part of the "fossil record") and should be maintained indefinitely.
88
Such is the design intent of Fossil.
99
1010
Nevertheless, there may occasionally arise legitimate reasons for
1111
deleting content. Such reasons might include:
1212
@@ -21,35 +21,35 @@
2121
disrupting the operation of Fossil.
2222
2323
<h2>Shunning</h2>
2424
2525
Fossil provides a mechanism called "shunning" for removing content from
26
-a repository.
26
+a repository.
2727
2828
Every Fossil repository maintains a list of the SHA1 hash names of
2929
"shunned" artifacts.
30
-Fossil will refuse to push or pull any shunned artifact.
30
+Fossil will refuse to push or pull any shunned artifact.
3131
Furthermore, all shunned artifacts (but not the shunning list
3232
itself) are removed from the
3333
repository whenever the repository is reconstructed using the
3434
"rebuild" command.
3535
3636
<h3>Shunning lists are local state</h3>
3737
3838
The shunning list is part of the local state of a Fossil repository.
39
-In other words, shunning does not propagate to a remote repository
39
+In other words, shunning does not propagate to a remote repository
4040
using the normal "sync" mechanism. An artifact can be
4141
shunned from one repository but be allowed to exist in another. The fact that
4242
the shunning list does not propagate is a security feature. If the
4343
shunning list propagated then a malicious user (or
4444
a bug in the fossil code) might introduce a shun record that would
45
-propagate through all repositories in a network and permanently
45
+propagate through all repositories in a network and permanently
4646
destroy vital information. By refusing to propagate the shunning list,
47
-Fossil ensures that no remote user will ever be able to remove
47
+Fossil ensures that no remote user will ever be able to remove
4848
information from your personal repositories without your permission.
4949
50
-The shunning list does not propagate to a remote repository
50
+The shunning list does not propagate to a remote repository
5151
by the normal "sync" mechanism,
5252
but it is still possible to copy shuns from one repository to another
5353
using the "configuration" command:
5454
5555
<b>fossil configuration pull shun</b> <i>remote-url</i><br>
@@ -56,12 +56,12 @@
5656
<b>fossil configuration push shun</b> <i>remote-url</i>
5757
5858
The two command above will pull or push shunning lists from or to
5959
the <i>remote-url</i> indicated and merge the lists on the receiving
6060
end. "Admin" privilege on the remote server is required in order to
61
-push a shun list. In contrast, the shunning list will be automatically
62
-received by default as part of a normal client "pull" operation unless
61
+push a shun list. In contrast, the shunning list will be automatically
62
+received by default as part of a normal client "pull" operation unless
6363
disabled by the "<tt>auto-shun</tt>" setting.
6464
6565
Note that the shunning list remains in the repository even after the
6666
shunned artifact has been removed. This is to prevent the artifact
6767
from being reintroduced into the repository the next time it syncs with
@@ -68,11 +68,11 @@
6868
another repository that has not shunned the artifact.
6969
7070
<h3>Managing the shunning list</h3>
7171
7272
The complete shunning list for a repository can be viewed by a user
73
-with "admin" privilege on the "/shun" URL of the web interface to Fossil.
73
+with "admin" privilege on the "/shun" URL of the web interface to Fossil.
7474
That URL is accessible under the "Admin" button on the default menu
7575
bar. Items can be added to or removed from the shunning list. "Sync"
7676
operations are inhibited as soon as the artifact is added to the
7777
shunning list, but the content of the artifact is not actually removed
7878
from the repository until the next time the repository is rebuilt.
7979
--- www/shunning.wiki
+++ www/shunning.wiki
@@ -2,11 +2,11 @@
2 <h1 align="center">Deleting Content From Fossil</h1>
3
4 Fossil is designed to keep all historical content forever. Users
5 of Fossil are discouraged from "deleting" content simply because it
6 has become obsolete. Old content is part of the historical record
7 (part of the "fossil record") and should be maintained indefinitely.
8 Such is the design intent of Fossil.
9
10 Nevertheless, there may occasionally arise legitimate reasons for
11 deleting content. Such reasons might include:
12
@@ -21,35 +21,35 @@
21 disrupting the operation of Fossil.
22
23 <h2>Shunning</h2>
24
25 Fossil provides a mechanism called "shunning" for removing content from
26 a repository.
27
28 Every Fossil repository maintains a list of the SHA1 hash names of
29 "shunned" artifacts.
30 Fossil will refuse to push or pull any shunned artifact.
31 Furthermore, all shunned artifacts (but not the shunning list
32 itself) are removed from the
33 repository whenever the repository is reconstructed using the
34 "rebuild" command.
35
36 <h3>Shunning lists are local state</h3>
37
38 The shunning list is part of the local state of a Fossil repository.
39 In other words, shunning does not propagate to a remote repository
40 using the normal "sync" mechanism. An artifact can be
41 shunned from one repository but be allowed to exist in another. The fact that
42 the shunning list does not propagate is a security feature. If the
43 shunning list propagated then a malicious user (or
44 a bug in the fossil code) might introduce a shun record that would
45 propagate through all repositories in a network and permanently
46 destroy vital information. By refusing to propagate the shunning list,
47 Fossil ensures that no remote user will ever be able to remove
48 information from your personal repositories without your permission.
49
50 The shunning list does not propagate to a remote repository
51 by the normal "sync" mechanism,
52 but it is still possible to copy shuns from one repository to another
53 using the "configuration" command:
54
55 <b>fossil configuration pull shun</b> <i>remote-url</i><br>
@@ -56,12 +56,12 @@
56 <b>fossil configuration push shun</b> <i>remote-url</i>
57
58 The two command above will pull or push shunning lists from or to
59 the <i>remote-url</i> indicated and merge the lists on the receiving
60 end. "Admin" privilege on the remote server is required in order to
61 push a shun list. In contrast, the shunning list will be automatically
62 received by default as part of a normal client "pull" operation unless
63 disabled by the "<tt>auto-shun</tt>" setting.
64
65 Note that the shunning list remains in the repository even after the
66 shunned artifact has been removed. This is to prevent the artifact
67 from being reintroduced into the repository the next time it syncs with
@@ -68,11 +68,11 @@
68 another repository that has not shunned the artifact.
69
70 <h3>Managing the shunning list</h3>
71
72 The complete shunning list for a repository can be viewed by a user
73 with "admin" privilege on the "/shun" URL of the web interface to Fossil.
74 That URL is accessible under the "Admin" button on the default menu
75 bar. Items can be added to or removed from the shunning list. "Sync"
76 operations are inhibited as soon as the artifact is added to the
77 shunning list, but the content of the artifact is not actually removed
78 from the repository until the next time the repository is rebuilt.
79
--- www/shunning.wiki
+++ www/shunning.wiki
@@ -2,11 +2,11 @@
2 <h1 align="center">Deleting Content From Fossil</h1>
3
4 Fossil is designed to keep all historical content forever. Users
5 of Fossil are discouraged from "deleting" content simply because it
6 has become obsolete. Old content is part of the historical record
7 (part of the "fossil record") and should be maintained indefinitely.
8 Such is the design intent of Fossil.
9
10 Nevertheless, there may occasionally arise legitimate reasons for
11 deleting content. Such reasons might include:
12
@@ -21,35 +21,35 @@
21 disrupting the operation of Fossil.
22
23 <h2>Shunning</h2>
24
25 Fossil provides a mechanism called "shunning" for removing content from
26 a repository.
27
28 Every Fossil repository maintains a list of the SHA1 hash names of
29 "shunned" artifacts.
30 Fossil will refuse to push or pull any shunned artifact.
31 Furthermore, all shunned artifacts (but not the shunning list
32 itself) are removed from the
33 repository whenever the repository is reconstructed using the
34 "rebuild" command.
35
36 <h3>Shunning lists are local state</h3>
37
38 The shunning list is part of the local state of a Fossil repository.
39 In other words, shunning does not propagate to a remote repository
40 using the normal "sync" mechanism. An artifact can be
41 shunned from one repository but be allowed to exist in another. The fact that
42 the shunning list does not propagate is a security feature. If the
43 shunning list propagated then a malicious user (or
44 a bug in the fossil code) might introduce a shun record that would
45 propagate through all repositories in a network and permanently
46 destroy vital information. By refusing to propagate the shunning list,
47 Fossil ensures that no remote user will ever be able to remove
48 information from your personal repositories without your permission.
49
50 The shunning list does not propagate to a remote repository
51 by the normal "sync" mechanism,
52 but it is still possible to copy shuns from one repository to another
53 using the "configuration" command:
54
55 <b>fossil configuration pull shun</b> <i>remote-url</i><br>
@@ -56,12 +56,12 @@
56 <b>fossil configuration push shun</b> <i>remote-url</i>
57
58 The two command above will pull or push shunning lists from or to
59 the <i>remote-url</i> indicated and merge the lists on the receiving
60 end. "Admin" privilege on the remote server is required in order to
61 push a shun list. In contrast, the shunning list will be automatically
62 received by default as part of a normal client "pull" operation unless
63 disabled by the "<tt>auto-shun</tt>" setting.
64
65 Note that the shunning list remains in the repository even after the
66 shunned artifact has been removed. This is to prevent the artifact
67 from being reintroduced into the repository the next time it syncs with
@@ -68,11 +68,11 @@
68 another repository that has not shunned the artifact.
69
70 <h3>Managing the shunning list</h3>
71
72 The complete shunning list for a repository can be viewed by a user
73 with "admin" privilege on the "/shun" URL of the web interface to Fossil.
74 That URL is accessible under the "Admin" button on the default menu
75 bar. Items can be added to or removed from the shunning list. "Sync"
76 operations are inhibited as soon as the artifact is added to the
77 shunning list, but the content of the artifact is not actually removed
78 from the repository until the next time the repository is rebuilt.
79
+3 -3
--- www/stats.wiki
+++ www/stats.wiki
@@ -1,9 +1,9 @@
11
<title>Fossil Performance</title>
22
<h1 align="center">Performance Statistics</h1>
33
4
-The questions will inevitably arise: How does Fossil perform?
4
+The questions will inevitably arise: How does Fossil perform?
55
Does it use a lot of disk space or bandwidth? Is it scalable?
66
77
In an attempt to answers these questions, this report looks at several
88
projects that use fossil for configuration management and examines how
99
well they are working. The following table is a summary of the results.
@@ -96,21 +96,21 @@
9696
every ticket, and every check-in is a separate "artifact". One way to
9797
think of a Fossil project is as a bag of artifacts. Of course, there is
9898
a lot more than this going on in Fossil. Many of the artifacts have meaning
9999
and are related to other artifacts. But at a low level (for example when
100100
synchronizing two instances of the same project) the only thing that matters
101
-is the unordered collection of artifacts. In fact, one of the key
101
+is the unordered collection of artifacts. In fact, one of the key
102102
characteristics of Fossil is that the entire project history can be
103103
reconstructed simply by scanning the artifacts in an arbitrary order.
104104
105105
The number of check-ins is the number of times that the "commit" command
106106
has been run. A single check-in might change a 3 or 4 files, or it might
107107
change dozens or hundreds of files. Regardless of the number of files
108108
changed, it still only counts as one check-in.
109109
110110
The "Uncompressed Size" is the total size of all the artifacts within
111
-the repository assuming they were all uncompressed and stored
111
+the repository assuming they were all uncompressed and stored
112112
separately on the disk. Fossil makes use of delta compression between related
113113
versions of the same file, and then uses zlib compression on the resulting
114114
deltas. The total resulting repository size is shown after the uncompressed
115115
size.
116116
117117
--- www/stats.wiki
+++ www/stats.wiki
@@ -1,9 +1,9 @@
1 <title>Fossil Performance</title>
2 <h1 align="center">Performance Statistics</h1>
3
4 The questions will inevitably arise: How does Fossil perform?
5 Does it use a lot of disk space or bandwidth? Is it scalable?
6
7 In an attempt to answers these questions, this report looks at several
8 projects that use fossil for configuration management and examines how
9 well they are working. The following table is a summary of the results.
@@ -96,21 +96,21 @@
96 every ticket, and every check-in is a separate "artifact". One way to
97 think of a Fossil project is as a bag of artifacts. Of course, there is
98 a lot more than this going on in Fossil. Many of the artifacts have meaning
99 and are related to other artifacts. But at a low level (for example when
100 synchronizing two instances of the same project) the only thing that matters
101 is the unordered collection of artifacts. In fact, one of the key
102 characteristics of Fossil is that the entire project history can be
103 reconstructed simply by scanning the artifacts in an arbitrary order.
104
105 The number of check-ins is the number of times that the "commit" command
106 has been run. A single check-in might change a 3 or 4 files, or it might
107 change dozens or hundreds of files. Regardless of the number of files
108 changed, it still only counts as one check-in.
109
110 The "Uncompressed Size" is the total size of all the artifacts within
111 the repository assuming they were all uncompressed and stored
112 separately on the disk. Fossil makes use of delta compression between related
113 versions of the same file, and then uses zlib compression on the resulting
114 deltas. The total resulting repository size is shown after the uncompressed
115 size.
116
117
--- www/stats.wiki
+++ www/stats.wiki
@@ -1,9 +1,9 @@
1 <title>Fossil Performance</title>
2 <h1 align="center">Performance Statistics</h1>
3
4 The questions will inevitably arise: How does Fossil perform?
5 Does it use a lot of disk space or bandwidth? Is it scalable?
6
7 In an attempt to answers these questions, this report looks at several
8 projects that use fossil for configuration management and examines how
9 well they are working. The following table is a summary of the results.
@@ -96,21 +96,21 @@
96 every ticket, and every check-in is a separate "artifact". One way to
97 think of a Fossil project is as a bag of artifacts. Of course, there is
98 a lot more than this going on in Fossil. Many of the artifacts have meaning
99 and are related to other artifacts. But at a low level (for example when
100 synchronizing two instances of the same project) the only thing that matters
101 is the unordered collection of artifacts. In fact, one of the key
102 characteristics of Fossil is that the entire project history can be
103 reconstructed simply by scanning the artifacts in an arbitrary order.
104
105 The number of check-ins is the number of times that the "commit" command
106 has been run. A single check-in might change a 3 or 4 files, or it might
107 change dozens or hundreds of files. Regardless of the number of files
108 changed, it still only counts as one check-in.
109
110 The "Uncompressed Size" is the total size of all the artifacts within
111 the repository assuming they were all uncompressed and stored
112 separately on the disk. Fossil makes use of delta compression between related
113 versions of the same file, and then uses zlib compression on the resulting
114 deltas. The total resulting repository size is shown after the uncompressed
115 size.
116
117
+6 -6
--- www/sync.wiki
+++ www/sync.wiki
@@ -1,8 +1,8 @@
11
<title>The Fossil Sync Protocol</title>
22
3
-<p>This document describes the wire protocol used to synchronize
3
+<p>This document describes the wire protocol used to synchronize
44
content between two Fossil repositories.</p>
55
66
<h2>1.0 Overview</h2>
77
88
<p>The global state of a fossil repository consists of an unordered
@@ -22,11 +22,11 @@
2222
shared to a few hundred.</p>
2323
2424
<p>Each repository also has local state. The local state determines
2525
the web-page formatting preferences, authorized users, ticket formats,
2626
and similar information that varies from one repository to another.
27
-The local state is not using transferred during a sync. Except,
27
+The local state is not using transferred during a sync. Except,
2828
some local state is transferred during a [/help?cmd=clone|clone]
2929
in order to initialize the local state of the new repository. And
3030
the [/help?cmd=configuration|config push] and
3131
[/help?cmd=configuration|config pull]
3232
commands can be an administrator to sync local state.</p>
@@ -40,15 +40,15 @@
4040
request.</p>
4141
4242
<p>The server might be running as an independent server
4343
using the <b>server</b> command, or it might be launched from
4444
inetd or xinetd using the <b>http</b> command. Or the server might
45
-be launched from CGI.
45
+be launched from CGI.
4646
(See "[./server.wiki|How To Configure A Fossil Server]" for details.)
4747
The specifics of how the server listens
4848
for incoming HTTP requests is immaterial to this protocol.
49
-The important point is that the server is listening for requests and
49
+The important point is that the server is listening for requests and
5050
the client is the issuer of the requests.</p>
5151
5252
<p>A single push, pull, or sync might involve multiple HTTP requests.
5353
The client maintains state between all requests. But on the server
5454
side, each request is independent. The server does not preserve
@@ -55,11 +55,11 @@
5555
any information about the client from one request to the next.</p>
5656
5757
<h4>2.0.1 Encrypted Transport</h4>
5858
5959
<p>In the current implementation of Fossil, the server only
60
-understands HTTP requests. The client can send either
60
+understands HTTP requests. The client can send either
6161
clear-text HTTP requests or encrypted HTTPS requests. But when
6262
HTTPS requests are sent, they first must be decrypted by a webserver
6363
or proxy before being passed to the Fossil server. This limitation
6464
may be relaxed in a future release.</p>
6565
@@ -408,11 +408,11 @@
408408
<b>uvigot</b> <i>name mtime hash size</i>
409409
</blockquote>
410410
411411
<p>The <i>name</i> argument is the name of an unversioned file.
412412
The <i>mtime</i> is the last modification time of the unversioned file
413
-in seconds since 1970.
413
+in seconds since 1970.
414414
The <i>hash</i> is the SHA1 hash of the unversioned file content, or
415415
"<b>-</b>" if the file has been deleted.
416416
The <i>size</i> is the uncompressed size of the file in bytes.
417417
418418
<p>When the server sees a "pragma uv-hash" card for which the hash
419419
--- www/sync.wiki
+++ www/sync.wiki
@@ -1,8 +1,8 @@
1 <title>The Fossil Sync Protocol</title>
2
3 <p>This document describes the wire protocol used to synchronize
4 content between two Fossil repositories.</p>
5
6 <h2>1.0 Overview</h2>
7
8 <p>The global state of a fossil repository consists of an unordered
@@ -22,11 +22,11 @@
22 shared to a few hundred.</p>
23
24 <p>Each repository also has local state. The local state determines
25 the web-page formatting preferences, authorized users, ticket formats,
26 and similar information that varies from one repository to another.
27 The local state is not using transferred during a sync. Except,
28 some local state is transferred during a [/help?cmd=clone|clone]
29 in order to initialize the local state of the new repository. And
30 the [/help?cmd=configuration|config push] and
31 [/help?cmd=configuration|config pull]
32 commands can be an administrator to sync local state.</p>
@@ -40,15 +40,15 @@
40 request.</p>
41
42 <p>The server might be running as an independent server
43 using the <b>server</b> command, or it might be launched from
44 inetd or xinetd using the <b>http</b> command. Or the server might
45 be launched from CGI.
46 (See "[./server.wiki|How To Configure A Fossil Server]" for details.)
47 The specifics of how the server listens
48 for incoming HTTP requests is immaterial to this protocol.
49 The important point is that the server is listening for requests and
50 the client is the issuer of the requests.</p>
51
52 <p>A single push, pull, or sync might involve multiple HTTP requests.
53 The client maintains state between all requests. But on the server
54 side, each request is independent. The server does not preserve
@@ -55,11 +55,11 @@
55 any information about the client from one request to the next.</p>
56
57 <h4>2.0.1 Encrypted Transport</h4>
58
59 <p>In the current implementation of Fossil, the server only
60 understands HTTP requests. The client can send either
61 clear-text HTTP requests or encrypted HTTPS requests. But when
62 HTTPS requests are sent, they first must be decrypted by a webserver
63 or proxy before being passed to the Fossil server. This limitation
64 may be relaxed in a future release.</p>
65
@@ -408,11 +408,11 @@
408 <b>uvigot</b> <i>name mtime hash size</i>
409 </blockquote>
410
411 <p>The <i>name</i> argument is the name of an unversioned file.
412 The <i>mtime</i> is the last modification time of the unversioned file
413 in seconds since 1970.
414 The <i>hash</i> is the SHA1 hash of the unversioned file content, or
415 "<b>-</b>" if the file has been deleted.
416 The <i>size</i> is the uncompressed size of the file in bytes.
417
418 <p>When the server sees a "pragma uv-hash" card for which the hash
419
--- www/sync.wiki
+++ www/sync.wiki
@@ -1,8 +1,8 @@
1 <title>The Fossil Sync Protocol</title>
2
3 <p>This document describes the wire protocol used to synchronize
4 content between two Fossil repositories.</p>
5
6 <h2>1.0 Overview</h2>
7
8 <p>The global state of a fossil repository consists of an unordered
@@ -22,11 +22,11 @@
22 shared to a few hundred.</p>
23
24 <p>Each repository also has local state. The local state determines
25 the web-page formatting preferences, authorized users, ticket formats,
26 and similar information that varies from one repository to another.
27 The local state is not using transferred during a sync. Except,
28 some local state is transferred during a [/help?cmd=clone|clone]
29 in order to initialize the local state of the new repository. And
30 the [/help?cmd=configuration|config push] and
31 [/help?cmd=configuration|config pull]
32 commands can be an administrator to sync local state.</p>
@@ -40,15 +40,15 @@
40 request.</p>
41
42 <p>The server might be running as an independent server
43 using the <b>server</b> command, or it might be launched from
44 inetd or xinetd using the <b>http</b> command. Or the server might
45 be launched from CGI.
46 (See "[./server.wiki|How To Configure A Fossil Server]" for details.)
47 The specifics of how the server listens
48 for incoming HTTP requests is immaterial to this protocol.
49 The important point is that the server is listening for requests and
50 the client is the issuer of the requests.</p>
51
52 <p>A single push, pull, or sync might involve multiple HTTP requests.
53 The client maintains state between all requests. But on the server
54 side, each request is independent. The server does not preserve
@@ -55,11 +55,11 @@
55 any information about the client from one request to the next.</p>
56
57 <h4>2.0.1 Encrypted Transport</h4>
58
59 <p>In the current implementation of Fossil, the server only
60 understands HTTP requests. The client can send either
61 clear-text HTTP requests or encrypted HTTPS requests. But when
62 HTTPS requests are sent, they first must be decrypted by a webserver
63 or proxy before being passed to the Fossil server. This limitation
64 may be relaxed in a future release.</p>
65
@@ -408,11 +408,11 @@
408 <b>uvigot</b> <i>name mtime hash size</i>
409 </blockquote>
410
411 <p>The <i>name</i> argument is the name of an unversioned file.
412 The <i>mtime</i> is the last modification time of the unversioned file
413 in seconds since 1970.
414 The <i>hash</i> is the SHA1 hash of the unversioned file content, or
415 "<b>-</b>" if the file has been deleted.
416 The <i>size</i> is the uncompressed size of the file in bytes.
417
418 <p>When the server sees a "pragma uv-hash" card for which the hash
419
+19
--- www/th1.md
+++ www/th1.md
@@ -174,10 +174,12 @@
174174
* tclInvoke
175175
* tclIsSafe
176176
* tclMakeSafe
177177
* tclReady
178178
* trace
179
+ * unversioned content
180
+ * unversioned list
179181
* utime
180182
* verifyCsrf
181183
* wiki
182184
183185
Each of the commands above is documented by a block comment above their
@@ -610,10 +612,27 @@
610612
-------------------------------------
611613
612614
* trace STRING
613615
614616
Generates a TH1 trace message if TH1 tracing is enabled.
617
+
618
+<a name="unversioned_content"></a>TH1 unversioned content Command
619
+-----------------------------------------------------------------
620
+
621
+ * unversioned content FILENAME
622
+
623
+Attempts to locate the specified unversioned file and return its contents.
624
+An error is generated if the repository is not open or the unversioned file
625
+cannot be found.
626
+
627
+<a name="unversioned_list"></a>TH1 unversioned list Command
628
+-----------------------------------------------------------
629
+
630
+ * unversioned list
631
+
632
+Returns a list of the names of all unversioned files held in the local
633
+repository. An error is generated if the repository is not open.
615634
616635
<a name="utime"></a>TH1 utime Command
617636
-------------------------------------
618637
619638
* utime
620639
--- www/th1.md
+++ www/th1.md
@@ -174,10 +174,12 @@
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
@@ -610,10 +612,27 @@
610 -------------------------------------
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
--- www/th1.md
+++ www/th1.md
@@ -174,10 +174,12 @@
174 * tclInvoke
175 * tclIsSafe
176 * tclMakeSafe
177 * tclReady
178 * trace
179 * unversioned content
180 * unversioned list
181 * utime
182 * verifyCsrf
183 * wiki
184
185 Each of the commands above is documented by a block comment above their
@@ -610,10 +612,27 @@
612 -------------------------------------
613
614 * trace STRING
615
616 Generates a TH1 trace message if TH1 tracing is enabled.
617
618 <a name="unversioned_content"></a>TH1 unversioned content Command
619 -----------------------------------------------------------------
620
621 * unversioned content FILENAME
622
623 Attempts to locate the specified unversioned file and return its contents.
624 An error is generated if the repository is not open or the unversioned file
625 cannot be found.
626
627 <a name="unversioned_list"></a>TH1 unversioned list Command
628 -----------------------------------------------------------
629
630 * unversioned list
631
632 Returns a list of the names of all unversioned files held in the local
633 repository. An error is generated if the repository is not open.
634
635 <a name="utime"></a>TH1 utime Command
636 -------------------------------------
637
638 * utime
639
--- www/theory1.wiki
+++ www/theory1.wiki
@@ -16,18 +16,18 @@
1616
1717
<h2>Fossil Is A NoSQL Database</h2>
1818
1919
We begin with the first question: Fossil is not based on a distributed
2020
NoSQL database because Fossil <u><i>is</i></u> a distributed NoSQL database.
21
-Fossil is <u>not</u> based on SQLite.
21
+Fossil is <u>not</u> based on SQLite.
2222
The current implementation of Fossil uses
2323
SQLite as a local store for the content of the distributed database and as
2424
a cache for meta-information about the distributed database that is precomputed
2525
for quick and easy presentation. But the use of SQLite in this role is an
2626
implementation detail and is not fundamental to the design. Some future
2727
version of Fossil might do away with SQLite and substitute a pile-of-files or
28
-a key/value database in place of SQLite.
28
+a key/value database in place of SQLite.
2929
(Actually, that is very unlikely
3030
to happen since SQLite works amazingly well in its current role, but the point
3131
is that omitting SQLite from Fossil is a theoretical possibility.)
3232
3333
The underlying database that Fossil implements has nothing to do with
@@ -64,11 +64,11 @@
6464
a NoSQL database) and there is the local relational database. The
6565
bag-of-artifacts database has a fixed format and is what defines a Fossil
6666
repository. Fossil will never modify the file format of the bag-of-artifacts
6767
database in an incompatible way because to do so would be to make something
6868
that is no longer "Fossil". The local relational database, on the other hand,
69
-is a cache that contains information derived from the bag-of-artifacts.
69
+is a cache that contains information derived from the bag-of-artifacts.
7070
The schema of the local relational database changes from time to time as
7171
the Fossil implementation is enhanced, and the content is recomputed from
7272
the unchanging bag of artifacts. The local relational database is an
7373
implementation detail which currently happens to use SQLite.
7474
@@ -89,11 +89,11 @@
8989
the first question.
9090
9191
<h2>SQL Is A High-Level Scripting Language</h2>
9292
9393
The second concern states that Fossil does not use a high-level scripting
94
-language. But that is not true. Fossil uses SQL (as implemented by SQLite)
94
+language. But that is not true. Fossil uses SQL (as implemented by SQLite)
9595
as its scripting language.
9696
9797
This misunderstanding likely arises because people fail
9898
to appreciate that SQL is a programming language. People are taught that SQL
9999
is a "query language" as if that were somehow different from a
@@ -125,11 +125,11 @@
125125
out using SQL statements. It is true that these SQL statements are glued
126126
together with C code, but it turns out that C works surprisingly well in
127127
that role. Several early prototypes of Fossil were written in a scripting
128128
language (TCL). We normally find that TCL programs are shorter than the
129129
equivalent C code by a factor of 10 or more. But in the case of Fossil,
130
-the use of TCL was actually making the code longer and more difficult to
130
+the use of TCL was actually making the code longer and more difficult to
131131
understand.
132132
And so in the final design, we switched from TCL to C in order to make
133133
the code easier to implement and debug.
134134
135135
Without the advantages of having SQLite built in, the design might well
136136
--- www/theory1.wiki
+++ www/theory1.wiki
@@ -16,18 +16,18 @@
16
17 <h2>Fossil Is A NoSQL Database</h2>
18
19 We begin with the first question: Fossil is not based on a distributed
20 NoSQL database because Fossil <u><i>is</i></u> a distributed NoSQL database.
21 Fossil is <u>not</u> based on SQLite.
22 The current implementation of Fossil uses
23 SQLite as a local store for the content of the distributed database and as
24 a cache for meta-information about the distributed database that is precomputed
25 for quick and easy presentation. But the use of SQLite in this role is an
26 implementation detail and is not fundamental to the design. Some future
27 version of Fossil might do away with SQLite and substitute a pile-of-files or
28 a key/value database in place of SQLite.
29 (Actually, that is very unlikely
30 to happen since SQLite works amazingly well in its current role, but the point
31 is that omitting SQLite from Fossil is a theoretical possibility.)
32
33 The underlying database that Fossil implements has nothing to do with
@@ -64,11 +64,11 @@
64 a NoSQL database) and there is the local relational database. The
65 bag-of-artifacts database has a fixed format and is what defines a Fossil
66 repository. Fossil will never modify the file format of the bag-of-artifacts
67 database in an incompatible way because to do so would be to make something
68 that is no longer "Fossil". The local relational database, on the other hand,
69 is a cache that contains information derived from the bag-of-artifacts.
70 The schema of the local relational database changes from time to time as
71 the Fossil implementation is enhanced, and the content is recomputed from
72 the unchanging bag of artifacts. The local relational database is an
73 implementation detail which currently happens to use SQLite.
74
@@ -89,11 +89,11 @@
89 the first question.
90
91 <h2>SQL Is A High-Level Scripting Language</h2>
92
93 The second concern states that Fossil does not use a high-level scripting
94 language. But that is not true. Fossil uses SQL (as implemented by SQLite)
95 as its scripting language.
96
97 This misunderstanding likely arises because people fail
98 to appreciate that SQL is a programming language. People are taught that SQL
99 is a "query language" as if that were somehow different from a
@@ -125,11 +125,11 @@
125 out using SQL statements. It is true that these SQL statements are glued
126 together with C code, but it turns out that C works surprisingly well in
127 that role. Several early prototypes of Fossil were written in a scripting
128 language (TCL). We normally find that TCL programs are shorter than the
129 equivalent C code by a factor of 10 or more. But in the case of Fossil,
130 the use of TCL was actually making the code longer and more difficult to
131 understand.
132 And so in the final design, we switched from TCL to C in order to make
133 the code easier to implement and debug.
134
135 Without the advantages of having SQLite built in, the design might well
136
--- www/theory1.wiki
+++ www/theory1.wiki
@@ -16,18 +16,18 @@
16
17 <h2>Fossil Is A NoSQL Database</h2>
18
19 We begin with the first question: Fossil is not based on a distributed
20 NoSQL database because Fossil <u><i>is</i></u> a distributed NoSQL database.
21 Fossil is <u>not</u> based on SQLite.
22 The current implementation of Fossil uses
23 SQLite as a local store for the content of the distributed database and as
24 a cache for meta-information about the distributed database that is precomputed
25 for quick and easy presentation. But the use of SQLite in this role is an
26 implementation detail and is not fundamental to the design. Some future
27 version of Fossil might do away with SQLite and substitute a pile-of-files or
28 a key/value database in place of SQLite.
29 (Actually, that is very unlikely
30 to happen since SQLite works amazingly well in its current role, but the point
31 is that omitting SQLite from Fossil is a theoretical possibility.)
32
33 The underlying database that Fossil implements has nothing to do with
@@ -64,11 +64,11 @@
64 a NoSQL database) and there is the local relational database. The
65 bag-of-artifacts database has a fixed format and is what defines a Fossil
66 repository. Fossil will never modify the file format of the bag-of-artifacts
67 database in an incompatible way because to do so would be to make something
68 that is no longer "Fossil". The local relational database, on the other hand,
69 is a cache that contains information derived from the bag-of-artifacts.
70 The schema of the local relational database changes from time to time as
71 the Fossil implementation is enhanced, and the content is recomputed from
72 the unchanging bag of artifacts. The local relational database is an
73 implementation detail which currently happens to use SQLite.
74
@@ -89,11 +89,11 @@
89 the first question.
90
91 <h2>SQL Is A High-Level Scripting Language</h2>
92
93 The second concern states that Fossil does not use a high-level scripting
94 language. But that is not true. Fossil uses SQL (as implemented by SQLite)
95 as its scripting language.
96
97 This misunderstanding likely arises because people fail
98 to appreciate that SQL is a programming language. People are taught that SQL
99 is a "query language" as if that were somehow different from a
@@ -125,11 +125,11 @@
125 out using SQL statements. It is true that these SQL statements are glued
126 together with C code, but it turns out that C works surprisingly well in
127 that role. Several early prototypes of Fossil were written in a scripting
128 language (TCL). We normally find that TCL programs are shorter than the
129 equivalent C code by a factor of 10 or more. But in the case of Fossil,
130 the use of TCL was actually making the code longer and more difficult to
131 understand.
132 And so in the final design, we switched from TCL to C in order to make
133 the code easier to implement and debug.
134
135 Without the advantages of having SQLite built in, the design might well
136
--- www/wikitheory.wiki
+++ www/wikitheory.wiki
@@ -34,26 +34,26 @@
3434
the wiki page will fork. The web interface will display whichever edit
3535
was checked in last. The other edit can be found in the history. The
3636
file format will support merging the branches back together, but there
3737
is no mechanism in the user interface (yet) to perform the merge.
3838
39
-Every change to a wiki page is a separate
39
+Every change to a wiki page is a separate
4040
[./fileformat.wiki | control artifact]
4141
of type [./fileformat.wiki#wikichng | "Wiki Page"].
4242
4343
<h2>Embedded Documentation</h2>
4444
4545
Files in the source tree that use the ".wiki", ".md", or ".markdown" suffixes
46
-can be accessed and displayed using special URLs to the fossil server.
46
+can be accessed and displayed using special URLs to the fossil server.
4747
This allows
48
-project documentation to be stored in the source tree and accessed
48
+project documentation to be stored in the source tree and accessed
4949
online. (Details are described [./embeddeddoc.wiki | separately].)
5050
5151
Some projects prefer to store their documentation in wiki. There is nothing
5252
wrong with that. But other projects prefer to keep documentation as part
5353
of the source tree, so that it is versioned along with the source tree and
54
-so that only developers with check-in privileges can change it.
54
+so that only developers with check-in privileges can change it.
5555
Embedded documentation serves this latter purpose. Both forms of documentation
5656
use the exact same markup. Some projects may choose to
5757
use both forms of documentation at the same time. Because the same
5858
format is used, it is trivial to move a file from wiki to embedded documentation
5959
or back again as the project evolves.
6060
--- www/wikitheory.wiki
+++ www/wikitheory.wiki
@@ -34,26 +34,26 @@
34 the wiki page will fork. The web interface will display whichever edit
35 was checked in last. The other edit can be found in the history. The
36 file format will support merging the branches back together, but there
37 is no mechanism in the user interface (yet) to perform the merge.
38
39 Every change to a wiki page is a separate
40 [./fileformat.wiki | control artifact]
41 of type [./fileformat.wiki#wikichng | "Wiki Page"].
42
43 <h2>Embedded Documentation</h2>
44
45 Files in the source tree that use the ".wiki", ".md", or ".markdown" suffixes
46 can be accessed and displayed using special URLs to the fossil server.
47 This allows
48 project documentation to be stored in the source tree and accessed
49 online. (Details are described [./embeddeddoc.wiki | separately].)
50
51 Some projects prefer to store their documentation in wiki. There is nothing
52 wrong with that. But other projects prefer to keep documentation as part
53 of the source tree, so that it is versioned along with the source tree and
54 so that only developers with check-in privileges can change it.
55 Embedded documentation serves this latter purpose. Both forms of documentation
56 use the exact same markup. Some projects may choose to
57 use both forms of documentation at the same time. Because the same
58 format is used, it is trivial to move a file from wiki to embedded documentation
59 or back again as the project evolves.
60
--- www/wikitheory.wiki
+++ www/wikitheory.wiki
@@ -34,26 +34,26 @@
34 the wiki page will fork. The web interface will display whichever edit
35 was checked in last. The other edit can be found in the history. The
36 file format will support merging the branches back together, but there
37 is no mechanism in the user interface (yet) to perform the merge.
38
39 Every change to a wiki page is a separate
40 [./fileformat.wiki | control artifact]
41 of type [./fileformat.wiki#wikichng | "Wiki Page"].
42
43 <h2>Embedded Documentation</h2>
44
45 Files in the source tree that use the ".wiki", ".md", or ".markdown" suffixes
46 can be accessed and displayed using special URLs to the fossil server.
47 This allows
48 project documentation to be stored in the source tree and accessed
49 online. (Details are described [./embeddeddoc.wiki | separately].)
50
51 Some projects prefer to store their documentation in wiki. There is nothing
52 wrong with that. But other projects prefer to keep documentation as part
53 of the source tree, so that it is versioned along with the source tree and
54 so that only developers with check-in privileges can change it.
55 Embedded documentation serves this latter purpose. Both forms of documentation
56 use the exact same markup. Some projects may choose to
57 use both forms of documentation at the same time. Because the same
58 format is used, it is trivial to move a file from wiki to embedded documentation
59 or back again as the project evolves.
60

Keyboard Shortcuts

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