Fossil SCM
Merge trunk
Commit
490daed204be9cd1d6b986e1ef93193e5d230db8
Parent
b5edfa3b3cfe62c…
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
~
Dockerfile
~
auto.def
~
src/allrepo.c
~
src/branch.c
~
src/cgi.c
~
src/db.c
~
src/delta.c
~
src/diff.c
~
src/diffcmd.c
~
src/export.c
~
src/fusefs.c
~
src/graph.c
~
src/import.c
~
src/main.c
~
src/mkindex.c
~
src/search.c
~
src/setup.c
~
src/shell.c
~
src/sqlite3.c
~
src/sqlite3.h
~
src/style.c
~
src/th_main.c
~
src/timeline.c
~
src/timeline.c
~
src/tkt.c
~
src/unversioned.c
~
src/user.c
~
src/util.c
~
src/winhttp.c
~
src/xfer.c
~
test/diff.test
~
test/graph-test-1.wiki
~
test/th1.test
~
www/aboutcgi.wiki
~
www/adding_code.wiki
~
www/antibot.wiki
~
www/blame.wiki
~
www/bugtheory.wiki
~
www/changes.wiki
~
www/changes.wiki
~
www/checkin_names.wiki
~
www/childprojects.wiki
~
www/concepts.wiki
~
www/contribute.wiki
~
www/custom_ticket.wiki
~
www/customskin.md
~
www/delta_encoder_algorithm.wiki
~
www/delta_format.wiki
~
www/embeddeddoc.wiki
~
www/encryptedrepos.wiki
~
www/event.wiki
~
www/faq.wiki
~
www/fileformat.wiki
~
www/fiveminutes.wiki
~
www/foss-cklist.wiki
~
www/fossil-from-msvc.wiki
~
www/index.wiki
~
www/inout.wiki
~
www/makefile.wiki
~
www/mkdownload.tcl
~
www/newrepo.wiki
~
www/pop.wiki
~
www/private.wiki
~
www/qandc.wiki
~
www/quickstart.wiki
~
www/quotes.wiki
~
www/reviews.wiki
~
www/selfcheck.wiki
~
www/selfhost.wiki
~
www/server.wiki
~
www/settings.wiki
~
www/shunning.wiki
~
www/stats.wiki
~
www/sync.wiki
~
www/th1.md
~
www/theory1.wiki
~
www/wikitheory.wiki
+1
-1
| --- Dockerfile | ||
| +++ Dockerfile | ||
| @@ -1,9 +1,9 @@ | ||
| 1 | 1 | ### |
| 2 | 2 | # Dockerfile for Fossil |
| 3 | 3 | ### |
| 4 | -FROM fedora:23 | |
| 4 | +FROM fedora:24 | |
| 5 | 5 | |
| 6 | 6 | ### Now install some additional parts we will need for the build |
| 7 | 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 | 8 | |
| 9 | 9 | ### If you want to build "trunk", change the next line accordingly. |
| 10 | 10 |
| --- 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 |
M
auto.def
+1
| --- auto.def | ||
| +++ auto.def | ||
| @@ -479,10 +479,11 @@ | ||
| 479 | 479 | cc-check-function-in-lib sin m |
| 480 | 480 | |
| 481 | 481 | # Check for the FuseFS library |
| 482 | 482 | if {[opt-bool fusefs]} { |
| 483 | 483 | if {[cc-check-function-in-lib fuse_mount fuse]} { |
| 484 | + define-append EXTRA_CFLAGS -DFOSSIL_HAVE_FUSEFS | |
| 484 | 485 | define FOSSIL_HAVE_FUSEFS 1 |
| 485 | 486 | define-append LIBS -lfuse |
| 486 | 487 | msg-result "FuseFS support enabled" |
| 487 | 488 | } |
| 488 | 489 | } |
| 489 | 490 |
| --- 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 @@ | ||
| 173 | 173 | int useCheckouts = 0; |
| 174 | 174 | int quiet = 0; |
| 175 | 175 | int dryRunFlag = 0; |
| 176 | 176 | int showFile = find_option("showfile",0,0)!=0; |
| 177 | 177 | int stopOnError = find_option("dontstop",0,0)==0; |
| 178 | - int rc; | |
| 179 | 178 | int nToDel = 0; |
| 180 | 179 | int showLabel = 0; |
| 181 | 180 | |
| 182 | 181 | dryRunFlag = find_option("dry-run","n",0)!=0; |
| 183 | 182 | if( !dryRunFlag ){ |
| @@ -378,10 +377,11 @@ | ||
| 378 | 377 | ); |
| 379 | 378 | } |
| 380 | 379 | db_multi_exec("CREATE TEMP TABLE toDel(x TEXT)"); |
| 381 | 380 | db_prepare(&q, "SELECT name, tag FROM repolist ORDER BY 1"); |
| 382 | 381 | while( db_step(&q)==SQLITE_ROW ){ |
| 382 | + int rc; | |
| 383 | 383 | const char *zFilename = db_column_text(&q, 0); |
| 384 | 384 | #if !USE_SEE |
| 385 | 385 | if( sqlite3_strglob("*.efossil", zFilename)==0 ) continue; |
| 386 | 386 | #endif |
| 387 | 387 | if( file_access(zFilename, F_OK) |
| 388 | 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 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 @@ | ||
| 323 | 323 | @ WHERE plink.pid=event.objid |
| 324 | 324 | @ AND tagxref.rid=plink.cid |
| 325 | 325 | @ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch') |
| 326 | 326 | @ AND tagtype>0), |
| 327 | 327 | @ count(*), |
| 328 | -@ (SELECT uuid FROM blob WHERE rid=tagxref.rid) | |
| 328 | +@ (SELECT uuid FROM blob WHERE rid=tagxref.rid), | |
| 329 | +@ event.bgcolor | |
| 329 | 330 | @ FROM tagxref, tag, event |
| 330 | 331 | @ WHERE tagxref.tagid=tag.tagid |
| 331 | 332 | @ AND tagxref.tagtype>0 |
| 332 | 333 | @ AND tag.tagname='branch' |
| 333 | 334 | @ AND event.objid=tagxref.rid |
| @@ -344,14 +345,16 @@ | ||
| 344 | 345 | ** if there are no query parameters. |
| 345 | 346 | */ |
| 346 | 347 | static void new_brlist_page(void){ |
| 347 | 348 | Stmt q; |
| 348 | 349 | double rNow; |
| 350 | + int show_colors = PB("colors"); | |
| 349 | 351 | login_check_credentials(); |
| 350 | 352 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 351 | 353 | style_header("Branches"); |
| 352 | 354 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 355 | + style_submenu_binary("colors", "Color", "B/W", 0); | |
| 353 | 356 | login_anonymous_available(); |
| 354 | 357 | |
| 355 | 358 | db_prepare(&q, brlistQuery/*works-like:""*/); |
| 356 | 359 | rNow = db_double(0.0, "SELECT julianday('now')"); |
| 357 | 360 | @ <div class="brlist"><table id="branchlisttable"> |
| @@ -367,14 +370,26 @@ | ||
| 367 | 370 | double rMtime = db_column_double(&q, 1); |
| 368 | 371 | int isClosed = db_column_int(&q, 2); |
| 369 | 372 | const char *zMergeTo = db_column_text(&q, 3); |
| 370 | 373 | int nCkin = db_column_int(&q, 4); |
| 371 | 374 | const char *zLastCkin = db_column_text(&q, 5); |
| 375 | + const char *zBgClr = db_column_text(&q, 6); | |
| 372 | 376 | char *zAge = human_readable_age(rNow - rMtime); |
| 373 | 377 | sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0); |
| 374 | 378 | 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 | + } | |
| 376 | 391 | @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td> |
| 377 | 392 | @ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td> |
| 378 | 393 | @ <td>%d(nCkin)</td> |
| 379 | 394 | fossil_free(zAge); |
| 380 | 395 | @ <td>%s(isClosed?"closed":"")</td> |
| 381 | 396 |
| --- 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 @@ | ||
| 21 | 21 | ** formatting function and its cousins, and routines to encode and |
| 22 | 22 | ** decode strings in HTML or HTTP. |
| 23 | 23 | */ |
| 24 | 24 | #include "config.h" |
| 25 | 25 | #ifdef _WIN32 |
| 26 | +# if !defined(_WIN32_WINNT) | |
| 27 | +# define _WIN32_WINNT 0x0501 | |
| 28 | +# endif | |
| 26 | 29 | # include <winsock2.h> |
| 27 | 30 | # include <ws2tcpip.h> |
| 28 | 31 | #else |
| 29 | 32 | # include <sys/socket.h> |
| 30 | 33 | # include <netinet/in.h> |
| 31 | 34 |
| --- 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 |
M
src/db.c
+165
-14
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -27,11 +27,15 @@ | ||
| 27 | 27 | ** (3) A local checkout database named "_FOSSIL_" or ".fslckout" |
| 28 | 28 | ** and located at the root of the local copy of the source tree. |
| 29 | 29 | ** |
| 30 | 30 | */ |
| 31 | 31 | #include "config.h" |
| 32 | -#if ! defined(_WIN32) | |
| 32 | +#if defined(_WIN32) | |
| 33 | +# if USE_SEE | |
| 34 | +# include <windows.h> | |
| 35 | +# endif | |
| 36 | +#else | |
| 33 | 37 | # include <pwd.h> |
| 34 | 38 | #endif |
| 35 | 39 | #include <sqlite3.h> |
| 36 | 40 | #include <sys/types.h> |
| 37 | 41 | #include <sys/stat.h> |
| @@ -870,31 +874,170 @@ | ||
| 870 | 874 | db_tolocal_function, 0, 0); |
| 871 | 875 | sqlite3_create_function(db, "fromLocal", 0, SQLITE_UTF8, 0, |
| 872 | 876 | db_fromlocal_function, 0, 0); |
| 873 | 877 | } |
| 874 | 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 | + | |
| 875 | 1018 | /* |
| 876 | 1019 | ** 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. | |
| 880 | 1024 | */ |
| 881 | -static void db_encryption_key( | |
| 1025 | +static void db_maybe_obtain_encryption_key( | |
| 882 | 1026 | const char *zDbFile, /* Name of the database file */ |
| 883 | 1027 | Blob *pKey /* Put the encryption key here */ |
| 884 | 1028 | ){ |
| 885 | - blob_init(pKey, 0, 0); | |
| 886 | 1029 | #if USE_SEE |
| 887 | 1030 | 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); | |
| 891 | 1034 | }else{ |
| 892 | 1035 | char *zPrompt = mprintf("\rencryption key for '%s': ", zDbFile); |
| 893 | 1036 | prompt_for_password(zPrompt, pKey, 0); |
| 894 | 1037 | fossil_free(zPrompt); |
| 895 | - zSavedKey = fossil_strdup(blob_str(pKey)); | |
| 1038 | + db_set_saved_encryption_key(pKey); | |
| 896 | 1039 | } |
| 897 | 1040 | } |
| 898 | 1041 | #endif |
| 899 | 1042 | } |
| 900 | 1043 | |
| @@ -915,14 +1058,16 @@ | ||
| 915 | 1058 | g.zVfsName |
| 916 | 1059 | ); |
| 917 | 1060 | if( rc!=SQLITE_OK ){ |
| 918 | 1061 | db_err("[%s]: %s", zDbName, sqlite3_errmsg(db)); |
| 919 | 1062 | } |
| 920 | - db_encryption_key(zDbName, &key); | |
| 1063 | + blob_init(&key, 0, 0); | |
| 1064 | + db_maybe_obtain_encryption_key(zDbName, &key); | |
| 921 | 1065 | if( blob_size(&key)>0 ){ |
| 922 | 1066 | char *zCmd = sqlite3_mprintf("PRAGMA key(%Q)", blob_str(&key)); |
| 923 | 1067 | sqlite3_exec(db, zCmd, 0, 0, 0); |
| 1068 | + fossil_secure_zero(zCmd, strlen(zCmd)); | |
| 924 | 1069 | sqlite3_free(zCmd); |
| 925 | 1070 | } |
| 926 | 1071 | blob_reset(&key); |
| 927 | 1072 | sqlite3_busy_timeout(db, 5000); |
| 928 | 1073 | sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */ |
| @@ -955,14 +1100,19 @@ | ||
| 955 | 1100 | /* |
| 956 | 1101 | ** zDbName is the name of a database file. Attach zDbName using |
| 957 | 1102 | ** the name zLabel. |
| 958 | 1103 | */ |
| 959 | 1104 | void db_attach(const char *zDbName, const char *zLabel){ |
| 1105 | + char *zCmd; | |
| 960 | 1106 | 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); | |
| 964 | 1114 | blob_reset(&key); |
| 965 | 1115 | } |
| 966 | 1116 | |
| 967 | 1117 | /* |
| 968 | 1118 | ** Change the schema name of the "main" database to zLabel. |
| @@ -1192,10 +1342,11 @@ | ||
| 1192 | 1342 | } |
| 1193 | 1343 | if( db_local_table_exists_but_lacks_column("undo_vfile", "islink") ){ |
| 1194 | 1344 | db_multi_exec("ALTER TABLE undo_vfile ADD COLUMN islink BOOL DEFAULT 0"); |
| 1195 | 1345 | } |
| 1196 | 1346 | } |
| 1347 | + fossil_free(zVFileDef); | |
| 1197 | 1348 | return 1; |
| 1198 | 1349 | } |
| 1199 | 1350 | |
| 1200 | 1351 | /* |
| 1201 | 1352 | ** Locate the root directory of the local repository tree. The root |
| 1202 | 1353 |
| --- 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 @@ | ||
| 377 | 377 | /* Compute the hash table used to locate matching sections in the |
| 378 | 378 | ** source file. |
| 379 | 379 | */ |
| 380 | 380 | nHash = lenSrc/NHASH; |
| 381 | 381 | collide = fossil_malloc( nHash*2*sizeof(int) ); |
| 382 | + memset(collide, -1, nHash*2*sizeof(int)); | |
| 382 | 383 | landmark = &collide[nHash]; |
| 383 | - memset(landmark, -1, nHash*sizeof(int)); | |
| 384 | - memset(collide, -1, nHash*sizeof(int)); | |
| 385 | 384 | for(i=0; i<lenSrc-NHASH; i+=NHASH){ |
| 386 | 385 | int hv = hash_once(&zSrc[i]) % nHash; |
| 387 | 386 | collide[i/NHASH] = landmark[hv]; |
| 388 | 387 | landmark[hv] = i/NHASH; |
| 389 | 388 | } |
| 390 | 389 |
| --- 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 @@ | ||
| 115 | 115 | int nFrom; /* Number of lines in aFrom[] */ |
| 116 | 116 | DLine *aTo; /* File on right side of the diff */ |
| 117 | 117 | int nTo; /* Number of lines in aTo[] */ |
| 118 | 118 | int (*same_fn)(const DLine*,const DLine*); /* comparison function */ |
| 119 | 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 | +} | |
| 120 | 144 | |
| 121 | 145 | /* |
| 122 | 146 | ** Return an array of DLine objects containing a pointer to the |
| 123 | 147 | ** start of each line and a hash of that line. The lower |
| 124 | 148 | ** bits of the hash store the length of each line. |
| @@ -140,32 +164,26 @@ | ||
| 140 | 164 | u64 diffFlags |
| 141 | 165 | ){ |
| 142 | 166 | int nLine, i, k, nn, s, x; |
| 143 | 167 | unsigned int h, h2; |
| 144 | 168 | 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' ); | |
| 157 | 175 | a = fossil_malloc( sizeof(a[0])*nLine ); |
| 158 | 176 | memset(a, 0, sizeof(a[0])*nLine); |
| 159 | 177 | if( nLine==0 ){ |
| 160 | 178 | *pnLine = 0; |
| 161 | 179 | return a; |
| 162 | 180 | } |
| 163 | 181 | i = 0; |
| 164 | 182 | do{ |
| 165 | 183 | zNL = strchr(z,'\n'); |
| 166 | - if( zNL==0 ) zNL = z+strlen(z); | |
| 184 | + if( zNL==0 ) zNL = z+n; | |
| 167 | 185 | nn = (int)(zNL - z); |
| 168 | 186 | if( nn>LENGTH_MASK ){ |
| 169 | 187 | fossil_free(a); |
| 170 | 188 | return 0; |
| 171 | 189 | } |
| @@ -181,14 +199,15 @@ | ||
| 181 | 199 | } |
| 182 | 200 | if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){ |
| 183 | 201 | int numws = 0; |
| 184 | 202 | while( s<k && fossil_isspace(z[s]) ){ s++; } |
| 185 | 203 | for(h=0, x=s; x<k; x++){ |
| 186 | - if( fossil_isspace(z[x]) ){ | |
| 204 | + char c = z[x]; | |
| 205 | + if( fossil_isspace(c) ){ | |
| 187 | 206 | ++numws; |
| 188 | 207 | }else{ |
| 189 | - h += z[x]; | |
| 208 | + h += c; | |
| 190 | 209 | h *= 0x9e3779b1; |
| 191 | 210 | } |
| 192 | 211 | } |
| 193 | 212 | k -= numws; |
| 194 | 213 | }else{ |
| @@ -200,13 +219,13 @@ | ||
| 200 | 219 | a[i].indent = s; |
| 201 | 220 | a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s); |
| 202 | 221 | h2 = h % nLine; |
| 203 | 222 | a[i].iNext = a[h2].iHash; |
| 204 | 223 | a[h2].iHash = i+1; |
| 205 | - z += nn+1; | |
| 224 | + z += nn+1; n -= nn+1; | |
| 206 | 225 | i++; |
| 207 | - }while( zNL[0] && zNL[1] ); | |
| 226 | + }while( zNL[0]!='\0' && zNL[1]!='\0' ); | |
| 208 | 227 | assert( i==nLine ); |
| 209 | 228 | |
| 210 | 229 | /* Return results */ |
| 211 | 230 | *pnLine = nLine; |
| 212 | 231 | return a; |
| 213 | 232 |
| --- 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 |
+1
| --- src/diffcmd.c | ||
| +++ src/diffcmd.c | ||
| @@ -412,10 +412,11 @@ | ||
| 412 | 412 | " ORDER BY pathname /*scan*/", |
| 413 | 413 | vid |
| 414 | 414 | ); |
| 415 | 415 | } |
| 416 | 416 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 417 | + blob_reset(&sql); | |
| 417 | 418 | while( db_step(&q)==SQLITE_ROW ){ |
| 418 | 419 | const char *zPathname = db_column_text(&q,0); |
| 419 | 420 | int isDeleted = db_column_int(&q, 1); |
| 420 | 421 | int isChnged = db_column_int(&q,2); |
| 421 | 422 | int isNew = db_column_int(&q,3); |
| 422 | 423 |
| --- 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 @@ | ||
| 132 | 132 | |
| 133 | 133 | /* |
| 134 | 134 | ** create_mark() |
| 135 | 135 | ** Create a new (mark,rid,uuid) entry for the given rid in the 'xmark' table, |
| 136 | 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. | |
| 137 | 141 | ** This function returns -1 in the case where 'rid' does not exist, otherwise |
| 138 | 142 | ** it returns 0. |
| 139 | 143 | ** mark->name is dynamically allocated and is owned by the caller upon return. |
| 140 | 144 | */ |
| 141 | -int create_mark(int rid, struct mark_t *mark){ | |
| 145 | +int create_mark(int rid, struct mark_t *mark, unsigned int *unused_mark){ | |
| 142 | 146 | char sid[13]; |
| 143 | 147 | char *zUuid = rid_to_uuid(rid); |
| 144 | - if(!zUuid){ | |
| 148 | + if( !zUuid ){ | |
| 145 | 149 | fossil_trace("Undefined rid=%d\n", rid); |
| 146 | 150 | return -1; |
| 147 | 151 | } |
| 148 | 152 | 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; | |
| 150 | 155 | mark->name = fossil_strdup(sid); |
| 151 | 156 | sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", zUuid); |
| 152 | 157 | free(zUuid); |
| 153 | 158 | insert_commit_xref(mark->rid, mark->name, mark->uuid); |
| 154 | 159 | return 0; |
| @@ -156,19 +161,22 @@ | ||
| 156 | 161 | |
| 157 | 162 | /* |
| 158 | 163 | ** mark_name_from_rid() |
| 159 | 164 | ** Find the mark associated with the given rid. Mark names always start |
| 160 | 165 | ** 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. | |
| 164 | 172 | */ |
| 165 | -char * mark_name_from_rid(int rid){ | |
| 173 | +char * mark_name_from_rid(int rid, unsigned int *unused_mark){ | |
| 166 | 174 | char *zMark = db_text(0, "SELECT tname FROM xmark WHERE trid=%d", rid); |
| 167 | - if(zMark==NULL){ | |
| 175 | + if( zMark==NULL ){ | |
| 168 | 176 | struct mark_t mark; |
| 169 | - if(create_mark(rid, &mark)==0){ | |
| 177 | + if( create_mark(rid, &mark, unused_mark)==0 ){ | |
| 170 | 178 | zMark = mark.name; |
| 171 | 179 | }else{ |
| 172 | 180 | return NULL; |
| 173 | 181 | } |
| 174 | 182 | } |
| @@ -185,43 +193,52 @@ | ||
| 185 | 193 | ** database. Otherwise, 0 is returned. |
| 186 | 194 | ** mark->name is dynamically allocated, and owned by the caller. |
| 187 | 195 | */ |
| 188 | 196 | int parse_mark(char *line, struct mark_t *mark){ |
| 189 | 197 | char *cur_tok; |
| 198 | + char type_; | |
| 190 | 199 | cur_tok = strtok(line, " \t"); |
| 191 | - if(!cur_tok||strlen(cur_tok)<2){ | |
| 200 | + if( !cur_tok || strlen(cur_tok)<2 ){ | |
| 192 | 201 | return -1; |
| 193 | 202 | } |
| 194 | 203 | mark->rid = atoi(&cur_tok[1]); |
| 195 | - if(cur_tok[0]!='c'){ | |
| 204 | + type_ = cur_tok[0]; | |
| 205 | + if( type_!='c' && type_!='b' ){ | |
| 196 | 206 | /* This is probably a blob mark */ |
| 197 | 207 | mark->name = NULL; |
| 198 | 208 | return 0; |
| 199 | 209 | } |
| 200 | 210 | |
| 201 | 211 | cur_tok = strtok(NULL, " \t"); |
| 202 | - if(!cur_tok){ | |
| 212 | + if( !cur_tok ){ | |
| 203 | 213 | /* This mark was generated by an older version of Fossil and doesn't |
| 204 | 214 | ** include the mark name and uuid. create_mark() will name the new mark |
| 205 | 215 | ** exactly as it was when exported to git, so that we should have a |
| 206 | 216 | ** 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); | |
| 208 | 225 | }else{ |
| 209 | 226 | mark->name = fossil_strdup(cur_tok); |
| 210 | 227 | } |
| 211 | 228 | |
| 212 | 229 | cur_tok = strtok(NULL, "\n"); |
| 213 | - if(!cur_tok||strlen(cur_tok)!=40){ | |
| 230 | + if( !cur_tok || strlen(cur_tok)!=40 ){ | |
| 214 | 231 | free(mark->name); |
| 215 | 232 | fossil_trace("Invalid SHA-1 in marks file: %s\n", cur_tok); |
| 216 | 233 | return -1; |
| 217 | 234 | }else{ |
| 218 | 235 | sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", cur_tok); |
| 219 | 236 | } |
| 220 | 237 | |
| 221 | 238 | /* 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 ){ | |
| 223 | 240 | free(mark->name); |
| 224 | 241 | fossil_trace("Non-existent SHA-1 in marks file: %s\n", mark->uuid); |
| 225 | 242 | return -1; |
| 226 | 243 | } |
| 227 | 244 | |
| @@ -233,40 +250,66 @@ | ||
| 233 | 250 | /* |
| 234 | 251 | ** import_marks() |
| 235 | 252 | ** Import the marks specified in file 'f' into the 'xmark' table. |
| 236 | 253 | ** If 'blobs' is non-null, insert all blob marks into it. |
| 237 | 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. | |
| 238 | 258 | ** Each line in the file must be at most 100 characters in length. This |
| 239 | 259 | ** seems like a reasonable maximum for a 40-character uuid, and 1-13 |
| 240 | 260 | ** character rid. |
| 241 | 261 | ** The function returns -1 if any of the lines in file 'f' are malformed, |
| 242 | 262 | ** or the rid/uuid information doesn't match what is in the repository |
| 243 | 263 | ** database. Otherwise, 0 is returned. |
| 244 | 264 | */ |
| 245 | -int import_marks(FILE* f, Bag *blobs, Bag *vers){ | |
| 265 | +int import_marks(FILE* f, Bag *blobs, Bag *vers, unsigned int *unused_mark){ | |
| 246 | 266 | char line[101]; |
| 247 | 267 | while(fgets(line, sizeof(line), f)){ |
| 248 | 268 | struct mark_t mark; |
| 249 | - if(strlen(line)==100&&line[99]!='\n'){ | |
| 269 | + if( strlen(line)==100 && line[99]!='\n' ){ | |
| 250 | 270 | /* line too long */ |
| 251 | 271 | return -1; |
| 252 | 272 | } |
| 253 | 273 | if( parse_mark(line, &mark)<0 ){ |
| 254 | 274 | return -1; |
| 255 | 275 | }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 ){ | |
| 259 | 277 | bag_insert(blobs, mark.rid); |
| 260 | 278 | } |
| 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 | + } | |
| 263 | 289 | } |
| 264 | 290 | free(mark.name); |
| 265 | 291 | } |
| 266 | 292 | return 0; |
| 267 | 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 | +} | |
| 268 | 311 | |
| 269 | 312 | /* |
| 270 | 313 | ** If 'blobs' is non-null, it must point to a Bag of blob rids to be |
| 271 | 314 | ** written to disk. Blob rids are written as 'b<rid>'. |
| 272 | 315 | ** If 'vers' is non-null, it must point to a Bag of commit rids to be |
| @@ -275,32 +318,24 @@ | ||
| 275 | 318 | ** This function does not fail, but may produce errors if a uuid cannot |
| 276 | 319 | ** be found for an rid in 'vers'. |
| 277 | 320 | */ |
| 278 | 321 | void export_marks(FILE* f, Bag *blobs, Bag *vers){ |
| 279 | 322 | int rid; |
| 323 | + | |
| 280 | 324 | if( blobs!=NULL ){ |
| 281 | 325 | rid = bag_first(blobs); |
| 282 | - if(rid!=0){ | |
| 326 | + if( rid!=0 ){ | |
| 283 | 327 | 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 ); | |
| 286 | 330 | } |
| 287 | 331 | } |
| 288 | 332 | if( vers!=NULL ){ |
| 289 | 333 | rid = bag_first(vers); |
| 290 | 334 | if( rid!=0 ){ |
| 291 | 335 | 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'); | |
| 302 | 337 | }while( (rid = bag_next(vers, rid))!=0 ); |
| 303 | 338 | } |
| 304 | 339 | } |
| 305 | 340 | } |
| 306 | 341 | |
| @@ -336,10 +371,11 @@ | ||
| 336 | 371 | */ |
| 337 | 372 | void export_cmd(void){ |
| 338 | 373 | Stmt q, q2, q3; |
| 339 | 374 | int i; |
| 340 | 375 | Bag blobs, vers; |
| 376 | + unsigned int unused_mark = 1; | |
| 341 | 377 | const char *markfile_in; |
| 342 | 378 | const char *markfile_out; |
| 343 | 379 | |
| 344 | 380 | bag_init(&blobs); |
| 345 | 381 | bag_init(&vers); |
| @@ -362,25 +398,25 @@ | ||
| 362 | 398 | |
| 363 | 399 | f = fossil_fopen(markfile_in, "r"); |
| 364 | 400 | if( f==0 ){ |
| 365 | 401 | fossil_fatal("cannot open %s for reading", markfile_in); |
| 366 | 402 | } |
| 367 | - if(import_marks(f, &blobs, &vers)<0){ | |
| 403 | + if( import_marks(f, &blobs, &vers, &unused_mark)<0 ){ | |
| 368 | 404 | fossil_fatal("error importing marks from file: %s", markfile_in); |
| 369 | 405 | } |
| 370 | 406 | db_prepare(&qb, "INSERT OR IGNORE INTO oldblob VALUES (:rid)"); |
| 371 | 407 | db_prepare(&qc, "INSERT OR IGNORE INTO oldcommit VALUES (:rid)"); |
| 372 | 408 | rid = bag_first(&blobs); |
| 373 | - if(rid!=0){ | |
| 409 | + if( rid!=0 ){ | |
| 374 | 410 | do{ |
| 375 | 411 | db_bind_int(&qb, ":rid", rid); |
| 376 | 412 | db_step(&qb); |
| 377 | 413 | db_reset(&qb); |
| 378 | 414 | }while((rid = bag_next(&blobs, rid))!=0); |
| 379 | 415 | } |
| 380 | 416 | rid = bag_first(&vers); |
| 381 | - if(rid!=0){ | |
| 417 | + if( rid!=0 ){ | |
| 382 | 418 | do{ |
| 383 | 419 | db_bind_int(&qc, ":rid", rid); |
| 384 | 420 | db_step(&qc); |
| 385 | 421 | db_reset(&qc); |
| 386 | 422 | }while((rid = bag_next(&vers, rid))!=0); |
| @@ -416,15 +452,18 @@ | ||
| 416 | 452 | while( db_step(&q)==SQLITE_ROW ){ |
| 417 | 453 | int rid = db_column_int(&q, 0); |
| 418 | 454 | Blob content; |
| 419 | 455 | |
| 420 | 456 | while( !bag_find(&blobs, rid) ){ |
| 457 | + char *zMark; | |
| 421 | 458 | content_get(rid, &content); |
| 422 | 459 | db_bind_int(&q2, ":rid", rid); |
| 423 | 460 | db_step(&q2); |
| 424 | 461 | 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); | |
| 426 | 465 | bag_insert(&blobs, rid); |
| 427 | 466 | fwrite(blob_buffer(&content), 1, blob_size(&content), stdout); |
| 428 | 467 | printf("\n"); |
| 429 | 468 | blob_reset(&content); |
| 430 | 469 | |
| @@ -470,11 +509,11 @@ | ||
| 470 | 509 | if( zBranch==0 ) zBranch = "trunk"; |
| 471 | 510 | zBr = mprintf("%s", zBranch); |
| 472 | 511 | for(i=0; zBr[i]; i++){ |
| 473 | 512 | if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_'; |
| 474 | 513 | } |
| 475 | - zMark = mark_name_from_rid(ckinId); | |
| 514 | + zMark = mark_name_from_rid(ckinId, &unused_mark); | |
| 476 | 515 | printf("commit refs/heads/%s\nmark %s\n", zBr, zMark); |
| 477 | 516 | free(zMark); |
| 478 | 517 | free(zBr); |
| 479 | 518 | printf("committer"); |
| 480 | 519 | print_person(zUser); |
| @@ -487,21 +526,21 @@ | ||
| 487 | 526 | " AND pid IN (SELECT objid FROM event)", |
| 488 | 527 | ckinId |
| 489 | 528 | ); |
| 490 | 529 | if( db_step(&q3) == SQLITE_ROW ){ |
| 491 | 530 | int pid = db_column_int(&q3, 0); |
| 492 | - zMark = mark_name_from_rid(pid); | |
| 531 | + zMark = mark_name_from_rid(pid, &unused_mark); | |
| 493 | 532 | printf("from %s\n", zMark); |
| 494 | 533 | free(zMark); |
| 495 | 534 | db_prepare(&q4, |
| 496 | 535 | "SELECT pid FROM plink" |
| 497 | 536 | " WHERE cid=%d AND NOT isprim" |
| 498 | 537 | " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)" |
| 499 | 538 | " ORDER BY pid", |
| 500 | 539 | ckinId); |
| 501 | 540 | 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); | |
| 503 | 542 | printf("merge %s\n", zMark); |
| 504 | 543 | free(zMark); |
| 505 | 544 | } |
| 506 | 545 | db_finalize(&q4); |
| 507 | 546 | }else{ |
| @@ -516,20 +555,22 @@ | ||
| 516 | 555 | ); |
| 517 | 556 | while( db_step(&q4)==SQLITE_ROW ){ |
| 518 | 557 | const char *zName = db_column_text(&q4,0); |
| 519 | 558 | int zNew = db_column_int(&q4,1); |
| 520 | 559 | int mPerm = db_column_int(&q4,2); |
| 521 | - if( zNew==0) | |
| 560 | + if( zNew==0 ){ | |
| 522 | 561 | printf("D %s\n", zName); |
| 523 | - else if( bag_find(&blobs, zNew) ) { | |
| 562 | + }else if( bag_find(&blobs, zNew) ){ | |
| 524 | 563 | const char *zPerm; |
| 564 | + zMark = mark_name_from_rid(zNew, &unused_mark); | |
| 525 | 565 | switch( mPerm ){ |
| 526 | 566 | case PERM_LNK: zPerm = "120000"; break; |
| 527 | 567 | case PERM_EXE: zPerm = "100755"; break; |
| 528 | 568 | default: zPerm = "100644"; break; |
| 529 | 569 | } |
| 530 | - printf("M %s :%d %s\n", zPerm, BLOBMARK(zNew), zName); | |
| 570 | + printf("M %s %s %s\n", zPerm, zMark, zName); | |
| 571 | + free(zMark); | |
| 531 | 572 | } |
| 532 | 573 | } |
| 533 | 574 | db_finalize(&q4); |
| 534 | 575 | db_finalize(&q3); |
| 535 | 576 | printf("\n"); |
| @@ -547,20 +588,22 @@ | ||
| 547 | 588 | ); |
| 548 | 589 | while( db_step(&q)==SQLITE_ROW ){ |
| 549 | 590 | const char *zTagname = db_column_text(&q, 0); |
| 550 | 591 | char *zEncoded = 0; |
| 551 | 592 | int rid = db_column_int(&q, 1); |
| 593 | + char *zMark = mark_name_from_rid(rid, &unused_mark); | |
| 552 | 594 | const char *zSecSince1970 = db_column_text(&q, 2); |
| 553 | 595 | int i; |
| 554 | 596 | if( rid==0 || !bag_find(&vers, rid) ) continue; |
| 555 | 597 | zTagname += 4; |
| 556 | 598 | zEncoded = mprintf("%s", zTagname); |
| 557 | 599 | for(i=0; zEncoded[i]; i++){ |
| 558 | 600 | if( !fossil_isalnum(zEncoded[i]) ) zEncoded[i] = '_'; |
| 559 | 601 | } |
| 560 | 602 | printf("tag %s\n", zEncoded); |
| 561 | - printf("from :%d\n", COMMITMARK(rid)); | |
| 603 | + printf("from %s\n", zMark); | |
| 604 | + free(zMark); | |
| 562 | 605 | printf("tagger <tagger> %s +0000\n", zSecSince1970); |
| 563 | 606 | printf("data 0\n"); |
| 564 | 607 | fossil_free(zEncoded); |
| 565 | 608 | } |
| 566 | 609 | db_finalize(&q); |
| @@ -570,12 +613,12 @@ | ||
| 570 | 613 | f = fossil_fopen(markfile_out, "w"); |
| 571 | 614 | if( f == 0 ){ |
| 572 | 615 | fossil_fatal("cannot open %s for writing", markfile_out); |
| 573 | 616 | } |
| 574 | 617 | export_marks(f, &blobs, &vers); |
| 575 | - if( ferror(f)!=0 || fclose(f)!=0 ) { | |
| 618 | + if( ferror(f)!=0 || fclose(f)!=0 ){ | |
| 576 | 619 | fossil_fatal("error while writing %s", markfile_out); |
| 577 | 620 | } |
| 578 | 621 | } |
| 579 | 622 | bag_clear(&blobs); |
| 580 | 623 | bag_clear(&vers); |
| 581 | 624 | } |
| 582 | 625 |
| --- 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 @@ | ||
| 20 | 20 | ** |
| 21 | 21 | ** This module is a mostly a no-op unless compiled with -DFOSSIL_HAVE_FUSEFS. |
| 22 | 22 | ** The FOSSIL_HAVE_FUSEFS should be omitted on systems that lack support for |
| 23 | 23 | ** the Fuse Filesystem, of course. |
| 24 | 24 | */ |
| 25 | +#ifdef FOSSIL_HAVE_FUSEFS | |
| 25 | 26 | #include "config.h" |
| 26 | 27 | #include <stdio.h> |
| 27 | 28 | #include <string.h> |
| 28 | 29 | #include <errno.h> |
| 29 | 30 | #include <fcntl.h> |
| 30 | 31 | #include <stdlib.h> |
| 31 | 32 | #include <unistd.h> |
| 32 | 33 | #include <sys/types.h> |
| 33 | 34 | #include "fusefs.h" |
| 34 | -#ifdef FOSSIL_HAVE_FUSEFS | |
| 35 | 35 | |
| 36 | 36 | #define FUSE_USE_VERSION 26 |
| 37 | 37 | #include <fuse.h> |
| 38 | 38 | |
| 39 | 39 | /* |
| @@ -283,11 +283,10 @@ | ||
| 283 | 283 | static struct fuse_operations fusefs_methods = { |
| 284 | 284 | .getattr = fusefs_getattr, |
| 285 | 285 | .readdir = fusefs_readdir, |
| 286 | 286 | .read = fusefs_read, |
| 287 | 287 | }; |
| 288 | -#endif /* FOSSIL_HAVE_FUSEFS */ | |
| 289 | 288 | |
| 290 | 289 | /* |
| 291 | 290 | ** COMMAND: fusefs |
| 292 | 291 | ** |
| 293 | 292 | ** Usage: %fossil fusefs [--debug] DIRECTORY |
| @@ -315,13 +314,10 @@ | ||
| 315 | 314 | ** After stopping the "fossil fusefs" command, it might also be necessary |
| 316 | 315 | ** to run "fusermount -u DIRECTORY" to reset the FuseFS before using it |
| 317 | 316 | ** again. |
| 318 | 317 | */ |
| 319 | 318 | 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 | 319 | char *zMountPoint; |
| 324 | 320 | char *azNewArgv[5]; |
| 325 | 321 | int doDebug = find_option("debug","d",0)!=0; |
| 326 | 322 | |
| 327 | 323 | db_find_and_open_repository(0,0); |
| @@ -339,7 +335,7 @@ | ||
| 339 | 335 | azNewArgv[4] = 0; |
| 340 | 336 | g.localOpen = 0; /* Prevent tags like "current" and "prev" */ |
| 341 | 337 | fuse_main(4, azNewArgv, &fusefs_methods, NULL); |
| 342 | 338 | fusefs_reset(); |
| 343 | 339 | fusefs_clear_path(); |
| 344 | -#endif | |
| 345 | 340 | } |
| 341 | +#endif /* FOSSIL_HAVE_FUSEFS */ | |
| 346 | 342 |
| --- 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 @@ | ||
| 258 | 258 | int iRail = pBottom->iRail; |
| 259 | 259 | GraphRow *pCurrent; |
| 260 | 260 | GraphRow *pPrior; |
| 261 | 261 | u64 mask = ((u64)1)<<iRail; |
| 262 | 262 | |
| 263 | - pBottom->iRail = iRail; | |
| 264 | 263 | pBottom->railInUse |= mask; |
| 265 | 264 | pPrior = pBottom; |
| 266 | 265 | for(pCurrent=pBottom->pChild; pCurrent; pCurrent=pCurrent->pChild){ |
| 267 | 266 | assert( pPrior->idx > pCurrent->idx ); |
| 268 | 267 | assert( pCurrent->iRail<0 ); |
| @@ -344,14 +343,16 @@ | ||
| 344 | 343 | /* |
| 345 | 344 | ** Compute the complete graph |
| 346 | 345 | */ |
| 347 | 346 | void graph_finish(GraphContext *p, int omitDescenders){ |
| 348 | 347 | GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent; |
| 349 | - int i; | |
| 348 | + int i, j; | |
| 350 | 349 | u64 mask; |
| 351 | 350 | int hasDup = 0; /* True if one or more isDup entries */ |
| 352 | 351 | const char *zTrunk; |
| 352 | + int railRid[GR_MAX_RAIL]; /* Maps rails to rids for lines | |
| 353 | + that enter from bottom of screen */ | |
| 353 | 354 | |
| 354 | 355 | if( p==0 || p->pFirst==0 || p->nErr ) return; |
| 355 | 356 | p->nErr = 1; /* Assume an error until proven otherwise */ |
| 356 | 357 | |
| 357 | 358 | /* Initialize all rows */ |
| @@ -366,10 +367,11 @@ | ||
| 366 | 367 | pDup->isDup = 1; |
| 367 | 368 | } |
| 368 | 369 | hashInsert(p, pRow, 1); |
| 369 | 370 | } |
| 370 | 371 | p->mxRail = -1; |
| 372 | + memset(railRid, 0, sizeof(railRid)); | |
| 371 | 373 | |
| 372 | 374 | /* Purge merge-parents that are out-of-graph if descenders are not |
| 373 | 375 | ** drawn. |
| 374 | 376 | ** |
| 375 | 377 | ** Each node has one primary parent and zero or more "merge" parents. |
| @@ -458,10 +460,13 @@ | ||
| 458 | 460 | } |
| 459 | 461 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 460 | 462 | mask = BIT(pRow->iRail); |
| 461 | 463 | if( !omitDescenders ){ |
| 462 | 464 | pRow->bDescender = pRow->nParent>0; |
| 465 | + if( pRow->bDescender ){ | |
| 466 | + railRid[pRow->iRail] = pRow->aParent[0]; | |
| 467 | + } | |
| 463 | 468 | for(pLoop=pRow; pLoop; pLoop=pLoop->pNext){ |
| 464 | 469 | pLoop->railInUse |= mask; |
| 465 | 470 | } |
| 466 | 471 | } |
| 467 | 472 | assignChildrenToRail(pRow); |
| @@ -536,12 +541,22 @@ | ||
| 536 | 541 | for(i=1; i<pRow->nParent; i++){ |
| 537 | 542 | int parentRid = pRow->aParent[i]; |
| 538 | 543 | pDesc = hashFind(p, parentRid); |
| 539 | 544 | if( pDesc==0 ){ |
| 540 | 545 | /* 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 | + } | |
| 543 | 558 | mask = BIT(iMrail); |
| 544 | 559 | pRow->mergeIn[iMrail] = 1; |
| 545 | 560 | pRow->mergeDown |= mask; |
| 546 | 561 | for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){ |
| 547 | 562 | pLoop->railInUse |= mask; |
| 548 | 563 |
| --- 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 @@ | ||
| 1761 | 1761 | ** times but only the last tag should be used. And we do not know which |
| 1762 | 1762 | ** occurrence of the tag is the last until the import finishes. |
| 1763 | 1763 | */ |
| 1764 | 1764 | db_multi_exec( |
| 1765 | 1765 | "CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT);" |
| 1766 | + "CREATE INDEX temp.i_xmark ON xmark(trid);" | |
| 1766 | 1767 | "CREATE TEMP TABLE xbranch(tname TEXT UNIQUE, brnm TEXT);" |
| 1767 | 1768 | "CREATE TEMP TABLE xtag(tname TEXT UNIQUE, tcontent TEXT);" |
| 1768 | 1769 | ); |
| 1769 | 1770 | |
| 1770 | 1771 | if( markfile_in ){ |
| 1771 | 1772 | FILE *f = fossil_fopen(markfile_in, "r"); |
| 1772 | 1773 | if( !f ){ |
| 1773 | 1774 | fossil_fatal("cannot open %s for reading", markfile_in); |
| 1774 | 1775 | } |
| 1775 | - if(import_marks(f, &blobs, NULL)<0){ | |
| 1776 | + if( import_marks(f, &blobs, NULL, NULL)<0 ){ | |
| 1776 | 1777 | fossil_fatal("error importing marks from file: %s", markfile_in); |
| 1777 | 1778 | } |
| 1778 | 1779 | fclose(f); |
| 1779 | 1780 | } |
| 1780 | 1781 | |
| @@ -1795,13 +1796,13 @@ | ||
| 1795 | 1796 | db_prepare(&q_marks, "SELECT DISTINCT trid FROM xmark"); |
| 1796 | 1797 | while( db_step(&q_marks)==SQLITE_ROW ){ |
| 1797 | 1798 | rid = db_column_int(&q_marks, 0); |
| 1798 | 1799 | if( db_int(0, "SELECT count(objid) FROM event" |
| 1799 | 1800 | " 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 | + */ | |
| 1803 | 1804 | }else{ |
| 1804 | 1805 | bag_insert(&vers, rid); |
| 1805 | 1806 | } |
| 1806 | 1807 | } |
| 1807 | 1808 | db_finalize(&q_marks); |
| 1808 | 1809 |
| --- 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 @@ | ||
| 18 | 18 | ** This module codes the main() procedure that runs first when the |
| 19 | 19 | ** program is invoked. |
| 20 | 20 | */ |
| 21 | 21 | #include "VERSION.h" |
| 22 | 22 | #include "config.h" |
| 23 | +#if defined(_WIN32) | |
| 24 | +# include <windows.h> | |
| 25 | +#endif | |
| 23 | 26 | #include "main.h" |
| 24 | 27 | #include <string.h> |
| 25 | 28 | #include <time.h> |
| 26 | 29 | #include <fcntl.h> |
| 27 | 30 | #include <sys/types.h> |
| 28 | 31 | #include <sys/stat.h> |
| 29 | 32 | #include <stdlib.h> /* atexit() */ |
| 30 | -#if defined(_WIN32) | |
| 31 | -# include <windows.h> | |
| 32 | -#else | |
| 33 | +#if !defined(_WIN32) | |
| 33 | 34 | # include <errno.h> /* errno global */ |
| 34 | 35 | #endif |
| 35 | 36 | #ifdef FOSSIL_ENABLE_SSL |
| 36 | 37 | # include "openssl/crypto.h" |
| 37 | 38 | #endif |
| @@ -299,10 +300,22 @@ | ||
| 299 | 300 | /* |
| 300 | 301 | ** atexit() handler which frees up "some" of the resources |
| 301 | 302 | ** used by fossil. |
| 302 | 303 | */ |
| 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 | |
| 304 | 317 | #if defined(_WIN32) && !defined(_WIN64) && defined(FOSSIL_ENABLE_TCL) && \ |
| 305 | 318 | defined(USE_TCL_STUBS) |
| 306 | 319 | /* |
| 307 | 320 | ** If Tcl is compiled on Windows using the latest MinGW, Fossil can crash |
| 308 | 321 | ** when exiting while a stubs-enabled Tcl is still loaded. This is due to |
| @@ -1917,10 +1930,41 @@ | ||
| 1917 | 1930 | } |
| 1918 | 1931 | } |
| 1919 | 1932 | } |
| 1920 | 1933 | } |
| 1921 | 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 | + | |
| 1922 | 1966 | /* |
| 1923 | 1967 | ** undocumented format: |
| 1924 | 1968 | ** |
| 1925 | 1969 | ** fossil http INFILE OUTFILE IPADDR ?REPOSITORY? |
| 1926 | 1970 | ** |
| @@ -1968,10 +2012,12 @@ | ||
| 1968 | 2012 | ** --notfound URL use URL as "HTTP 404, object not found" page. |
| 1969 | 2013 | ** --repolist If REPOSITORY is directory, URL "/" lists all repos |
| 1970 | 2014 | ** --scgi Interpret input as SCGI rather than HTTP |
| 1971 | 2015 | ** --skin LABEL Use override skin LABEL |
| 1972 | 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. | |
| 1973 | 2019 | ** |
| 1974 | 2020 | ** See also: cgi, server, winsrv |
| 1975 | 2021 | */ |
| 1976 | 2022 | void cmd_http(void){ |
| 1977 | 2023 | const char *zIpAddr = 0; |
| @@ -1980,10 +2026,13 @@ | ||
| 1980 | 2026 | const char *zAltBase; |
| 1981 | 2027 | const char *zFileGlob; |
| 1982 | 2028 | int useSCGI; |
| 1983 | 2029 | int noJail; |
| 1984 | 2030 | int allowRepoList; |
| 2031 | +#if defined(_WIN32) && USE_SEE | |
| 2032 | + const char *zPidKey; | |
| 2033 | +#endif | |
| 1985 | 2034 | |
| 1986 | 2035 | Th_InitTraceLog(); |
| 1987 | 2036 | |
| 1988 | 2037 | /* The winhttp module passes the --files option as --files-urlenc with |
| 1989 | 2038 | ** the argument being URL encoded, to avoid wildcard expansion in the |
| @@ -2010,10 +2059,21 @@ | ||
| 2010 | 2059 | zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */ |
| 2011 | 2060 | cgi_replace_parameter("HTTPS","on"); |
| 2012 | 2061 | } |
| 2013 | 2062 | zHost = find_option("host", 0, 1); |
| 2014 | 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 | |
| 2015 | 2075 | |
| 2016 | 2076 | /* We should be done with options.. */ |
| 2017 | 2077 | verify_all_options(); |
| 2018 | 2078 | |
| 2019 | 2079 | if( g.argc!=2 && g.argc!=3 && g.argc!=5 && g.argc!=6 ){ |
| @@ -2171,11 +2231,12 @@ | ||
| 2171 | 2231 | ** -P|--port TCPPORT listen to request on port TCPPORT |
| 2172 | 2232 | ** --th-trace trace TH1 execution (for debugging purposes) |
| 2173 | 2233 | ** --repolist If REPOSITORY is dir, URL "/" lists repos. |
| 2174 | 2234 | ** --scgi Accept SCGI rather than HTTP |
| 2175 | 2235 | ** --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. | |
| 2177 | 2238 | ** |
| 2178 | 2239 | ** See also: cgi, http, winsrv |
| 2179 | 2240 | */ |
| 2180 | 2241 | void cmd_webserver(void){ |
| 2181 | 2242 | int iPort, mxPort; /* Range of TCP ports allowed */ |
| @@ -2192,10 +2253,13 @@ | ||
| 2192 | 2253 | const char *zAltBase; /* Argument to the --baseurl option */ |
| 2193 | 2254 | const char *zFileGlob; /* Static content must match this */ |
| 2194 | 2255 | char *zIpAddr = 0; /* Bind to this IP address */ |
| 2195 | 2256 | int fCreate = 0; /* The --create flag */ |
| 2196 | 2257 | const char *zInitPage = 0; /* Start on this page. --page option */ |
| 2258 | +#if defined(_WIN32) && USE_SEE | |
| 2259 | + const char *zPidKey; | |
| 2260 | +#endif | |
| 2197 | 2261 | |
| 2198 | 2262 | #if defined(_WIN32) |
| 2199 | 2263 | const char *zStopperFile; /* Name of file used to terminate server */ |
| 2200 | 2264 | zStopperFile = find_option("stopper", 0, 1); |
| 2201 | 2265 | #endif |
| @@ -2235,10 +2299,21 @@ | ||
| 2235 | 2299 | g.sslNotAvailable = 1; |
| 2236 | 2300 | } |
| 2237 | 2301 | if( find_option("localhost", 0, 0)!=0 ){ |
| 2238 | 2302 | flags |= HTTP_SERVER_LOCALHOST; |
| 2239 | 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 | |
| 2240 | 2315 | |
| 2241 | 2316 | /* We should be done with options.. */ |
| 2242 | 2317 | verify_all_options(); |
| 2243 | 2318 | |
| 2244 | 2319 | if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?"); |
| 2245 | 2320 |
| --- 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 @@ | ||
| 223 | 223 | fprintf(stderr, "%s:%d: unknown option: '%.*s'\n", |
| 224 | 224 | zFile, nLine, j, &zLine[i]); |
| 225 | 225 | nErr++; |
| 226 | 226 | } |
| 227 | 227 | } |
| 228 | - | |
| 228 | + | |
| 229 | 229 | nUsed++; |
| 230 | 230 | } |
| 231 | 231 | |
| 232 | 232 | /* |
| 233 | 233 | ** Check to see if the current line is an #if and if it is, add it to |
| 234 | 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 |
| --- 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 @@ | ||
| 407 | 407 | |
| 408 | 408 | /* search_match(TEXT, TEXT, ....) |
| 409 | 409 | ** |
| 410 | 410 | ** Using the full-scan search engine created by the most recent call |
| 411 | 411 | ** 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. | |
| 413 | 413 | ** Return non-zero on a match and zero on a miss. |
| 414 | 414 | */ |
| 415 | 415 | static void search_match_sqlfunc( |
| 416 | 416 | sqlite3_context *context, |
| 417 | 417 | int argc, |
| 418 | 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 |
| --- 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 @@ | ||
| 1537 | 1537 | @ <p>Settings marked with (v) are 'versionable' and will be overridden |
| 1538 | 1538 | @ by the contents of files named <tt>.fossil-settings/PROPERTY</tt> |
| 1539 | 1539 | @ in the check-out root. |
| 1540 | 1540 | @ If such a file is present, the corresponding field above is not |
| 1541 | 1541 | @ editable.</p><hr /><p> |
| 1542 | - @ These settings work the same as the | |
| 1542 | + @ These settings work the same as the | |
| 1543 | 1543 | @ <a href='%R/help?cmd=settings'>fossil set</a> command. |
| 1544 | 1544 | db_end_transaction(0); |
| 1545 | 1545 | style_footer(); |
| 1546 | 1546 | } |
| 1547 | 1547 | |
| 1548 | 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 |
| --- 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 @@ | ||
| 666 | 666 | #define MODE_Column 1 /* One record per line in neat columns */ |
| 667 | 667 | #define MODE_List 2 /* One record per line with a separator */ |
| 668 | 668 | #define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */ |
| 669 | 669 | #define MODE_Html 4 /* Generate an XHTML table */ |
| 670 | 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 */ | |
| 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 */ | |
| 676 | 677 | |
| 677 | 678 | static const char *modeDescr[] = { |
| 678 | 679 | "line", |
| 679 | 680 | "column", |
| 680 | 681 | "list", |
| 681 | 682 | "semi", |
| 682 | 683 | "html", |
| 683 | 684 | "insert", |
| 685 | + "quote", | |
| 684 | 686 | "tcl", |
| 685 | 687 | "csv", |
| 686 | 688 | "explain", |
| 687 | 689 | "ascii", |
| 688 | 690 | "prettyprint", |
| @@ -1196,23 +1198,26 @@ | ||
| 1196 | 1198 | utf8_printf(p->out, "%s", p->rowSeparator); |
| 1197 | 1199 | } |
| 1198 | 1200 | setTextMode(p->out, 1); |
| 1199 | 1201 | break; |
| 1200 | 1202 | } |
| 1203 | + case MODE_Quote: | |
| 1201 | 1204 | case MODE_Insert: { |
| 1202 | 1205 | p->cnt++; |
| 1203 | 1206 | 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 | + } | |
| 1214 | 1219 | for(i=0; i<nArg; i++){ |
| 1215 | 1220 | char *zSep = i>0 ? ",": ""; |
| 1216 | 1221 | if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ |
| 1217 | 1222 | utf8_printf(p->out,"%sNULL",zSep); |
| 1218 | 1223 | }else if( aiType && aiType[i]==SQLITE_TEXT ){ |
| @@ -1231,11 +1236,11 @@ | ||
| 1231 | 1236 | }else{ |
| 1232 | 1237 | if( zSep[0] ) utf8_printf(p->out,"%s",zSep); |
| 1233 | 1238 | output_quoted_string(p->out, azArg[i]); |
| 1234 | 1239 | } |
| 1235 | 1240 | } |
| 1236 | - raw_printf(p->out,");\n"); | |
| 1241 | + raw_printf(p->out,p->cMode==MODE_Quote?"\n":");\n"); | |
| 1237 | 1242 | break; |
| 1238 | 1243 | } |
| 1239 | 1244 | case MODE_Ascii: { |
| 1240 | 1245 | if( p->cnt++==0 && p->showHeader ){ |
| 1241 | 1246 | for(i=0; i<nArg; i++){ |
| @@ -2175,10 +2180,11 @@ | ||
| 2175 | 2180 | " column Left-aligned columns. (See .width)\n" |
| 2176 | 2181 | " html HTML <table> code\n" |
| 2177 | 2182 | " insert SQL insert statements for TABLE\n" |
| 2178 | 2183 | " line One value per line\n" |
| 2179 | 2184 | " list Values delimited by .separator strings\n" |
| 2185 | + " quote Escape answers as for SQL\n" | |
| 2180 | 2186 | " tabs Tab-separated values\n" |
| 2181 | 2187 | " tcl TCL list elements\n" |
| 2182 | 2188 | ".nullvalue STRING Use STRING in place of NULL values\n" |
| 2183 | 2189 | ".once FILENAME Output for the next SQL command only to FILENAME\n" |
| 2184 | 2190 | ".open ?--new? ?FILE? Close existing database and reopen FILE\n" |
| @@ -3975,10 +3981,12 @@ | ||
| 3975 | 3981 | p->mode = MODE_List; |
| 3976 | 3982 | sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab); |
| 3977 | 3983 | }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){ |
| 3978 | 3984 | p->mode = MODE_Insert; |
| 3979 | 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; | |
| 3980 | 3988 | }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){ |
| 3981 | 3989 | p->mode = MODE_Ascii; |
| 3982 | 3990 | sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit); |
| 3983 | 3991 | sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record); |
| 3984 | 3992 | }else { |
| 3985 | 3993 |
| --- 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 @@ | ||
| 1 | 1 | /****************************************************************************** |
| 2 | 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 | |
| 3 | +** version 3.16.0. By combining all the individual C code files into this | |
| 4 | 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | 8 | ** translation unit. |
| @@ -379,13 +379,13 @@ | ||
| 379 | 379 | ** |
| 380 | 380 | ** See also: [sqlite3_libversion()], |
| 381 | 381 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 382 | 382 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 383 | 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" | |
| 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 | 387 | |
| 388 | 388 | /* |
| 389 | 389 | ** CAPI3REF: Run-Time Library Version Numbers |
| 390 | 390 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 391 | 391 | ** |
| @@ -1235,10 +1235,16 @@ | ||
| 1235 | 1235 | ** <li>[[SQLITE_FCNTL_HAS_MOVED]] |
| 1236 | 1236 | ** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a |
| 1237 | 1237 | ** pointer to an integer and it writes a boolean into that integer depending |
| 1238 | 1238 | ** on whether or not the file has been renamed, moved, or deleted since it |
| 1239 | 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. | |
| 1240 | 1246 | ** |
| 1241 | 1247 | ** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]] |
| 1242 | 1248 | ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This |
| 1243 | 1249 | ** opcode causes the xFileControl method to swap the file handle with the one |
| 1244 | 1250 | ** pointed to by the pArg argument. This capability is used during testing |
| @@ -1286,10 +1292,12 @@ | ||
| 1286 | 1292 | #define SQLITE_FCNTL_WAL_BLOCK 24 |
| 1287 | 1293 | #define SQLITE_FCNTL_ZIPVFS 25 |
| 1288 | 1294 | #define SQLITE_FCNTL_RBU 26 |
| 1289 | 1295 | #define SQLITE_FCNTL_VFS_POINTER 27 |
| 1290 | 1296 | #define SQLITE_FCNTL_JOURNAL_POINTER 28 |
| 1297 | +#define SQLITE_FCNTL_WIN32_GET_HANDLE 29 | |
| 1298 | +#define SQLITE_FCNTL_PDB 30 | |
| 1291 | 1299 | |
| 1292 | 1300 | /* deprecated names */ |
| 1293 | 1301 | #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE |
| 1294 | 1302 | #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE |
| 1295 | 1303 | #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| @@ -2238,18 +2246,31 @@ | ||
| 2238 | 2246 | ** does not make a copy of the new main schema name string, so the application |
| 2239 | 2247 | ** must ensure that the argument passed into this DBCONFIG option is unchanged |
| 2240 | 2248 | ** until after the database connection closes. |
| 2241 | 2249 | ** </dd> |
| 2242 | 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 | +** | |
| 2243 | 2263 | ** </dl> |
| 2244 | 2264 | */ |
| 2245 | 2265 | #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ |
| 2246 | 2266 | #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ |
| 2247 | 2267 | #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ |
| 2248 | 2268 | #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ |
| 2249 | 2269 | #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ |
| 2250 | 2270 | #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ |
| 2271 | +#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */ | |
| 2251 | 2272 | |
| 2252 | 2273 | |
| 2253 | 2274 | /* |
| 2254 | 2275 | ** CAPI3REF: Enable Or Disable Extended Result Codes |
| 2255 | 2276 | ** METHOD: sqlite3 |
| @@ -12675,11 +12696,11 @@ | ||
| 12675 | 12696 | #define OP_SorterData 120 /* synopsis: r[P2]=data */ |
| 12676 | 12697 | #define OP_RowKey 121 /* synopsis: r[P2]=key */ |
| 12677 | 12698 | #define OP_RowData 122 /* synopsis: r[P2]=data */ |
| 12678 | 12699 | #define OP_Rowid 123 /* synopsis: r[P2]=rowid */ |
| 12679 | 12700 | #define OP_NullRow 124 |
| 12680 | -#define OP_SorterInsert 125 | |
| 12701 | +#define OP_SorterInsert 125 /* synopsis: key=r[P2] */ | |
| 12681 | 12702 | #define OP_IdxInsert 126 /* synopsis: key=r[P2] */ |
| 12682 | 12703 | #define OP_IdxDelete 127 /* synopsis: key=r[P2@P3] */ |
| 12683 | 12704 | #define OP_Seek 128 /* synopsis: Move P3 to P1.rowid */ |
| 12684 | 12705 | #define OP_IdxRowid 129 /* synopsis: r[P2]=rowid */ |
| 12685 | 12706 | #define OP_Destroy 130 |
| @@ -13030,11 +13051,11 @@ | ||
| 13030 | 13051 | int, |
| 13031 | 13052 | int, |
| 13032 | 13053 | int, |
| 13033 | 13054 | void(*)(DbPage*) |
| 13034 | 13055 | ); |
| 13035 | -SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager); | |
| 13056 | +SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*); | |
| 13036 | 13057 | SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); |
| 13037 | 13058 | |
| 13038 | 13059 | /* Functions used to configure a Pager object. */ |
| 13039 | 13060 | SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); |
| 13040 | 13061 | SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); |
| @@ -13081,19 +13102,22 @@ | ||
| 13081 | 13102 | SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n); |
| 13082 | 13103 | SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); |
| 13083 | 13104 | SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager); |
| 13084 | 13105 | |
| 13085 | 13106 | #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*); | |
| 13087 | 13108 | SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager); |
| 13088 | 13109 | SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); |
| 13089 | 13110 | 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); | |
| 13091 | 13113 | # ifdef SQLITE_ENABLE_SNAPSHOT |
| 13092 | 13114 | SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot); |
| 13093 | 13115 | SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot); |
| 13094 | 13116 | # endif |
| 13117 | +#else | |
| 13118 | +# define sqlite3PagerUseWal(x) 0 | |
| 13095 | 13119 | #endif |
| 13096 | 13120 | |
| 13097 | 13121 | #ifdef SQLITE_ENABLE_ZIPVFS |
| 13098 | 13122 | SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); |
| 13099 | 13123 | #endif |
| @@ -14060,10 +14084,11 @@ | ||
| 14060 | 14084 | #define SQLITE_QueryOnly 0x04000000 /* Disable database changes */ |
| 14061 | 14085 | #define SQLITE_VdbeEQP 0x08000000 /* Debug EXPLAIN QUERY PLAN */ |
| 14062 | 14086 | #define SQLITE_Vacuum 0x10000000 /* Currently in a VACUUM */ |
| 14063 | 14087 | #define SQLITE_CellSizeCk 0x20000000 /* Check btree cell sizes on load */ |
| 14064 | 14088 | #define SQLITE_Fts3Tokenizer 0x40000000 /* Enable fts3_tokenizer(2) */ |
| 14089 | +#define SQLITE_NoCkptOnClose 0x80000000 /* No checkpoint on close()/DETACH */ | |
| 14065 | 14090 | |
| 14066 | 14091 | |
| 14067 | 14092 | /* |
| 14068 | 14093 | ** Bits of the sqlite3.dbOptFlags field that are used by the |
| 14069 | 14094 | ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to |
| @@ -17268,10 +17293,13 @@ | ||
| 17268 | 17293 | #if SQLITE_DEFAULT_LOCKING_MODE |
| 17269 | 17294 | "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), |
| 17270 | 17295 | #endif |
| 17271 | 17296 | #if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc) |
| 17272 | 17297 | "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE), |
| 17298 | +#endif | |
| 17299 | +#if SQLITE_DIRECT_OVERFLOW_READ | |
| 17300 | + "DIRECT_OVERFLOW_READ", | |
| 17273 | 17301 | #endif |
| 17274 | 17302 | #if SQLITE_DISABLE_DIRSYNC |
| 17275 | 17303 | "DISABLE_DIRSYNC", |
| 17276 | 17304 | #endif |
| 17277 | 17305 | #if SQLITE_DISABLE_LFS |
| @@ -17354,10 +17382,13 @@ | ||
| 17354 | 17382 | #if SQLITE_ENABLE_UNLOCK_NOTIFY |
| 17355 | 17383 | "ENABLE_UNLOCK_NOTIFY", |
| 17356 | 17384 | #endif |
| 17357 | 17385 | #if SQLITE_ENABLE_UPDATE_DELETE_LIMIT |
| 17358 | 17386 | "ENABLE_UPDATE_DELETE_LIMIT", |
| 17387 | +#endif | |
| 17388 | +#if defined(SQLITE_ENABLE_URI_00_ERROR) | |
| 17389 | + "ENABLE_URI_00_ERROR", | |
| 17359 | 17390 | #endif |
| 17360 | 17391 | #if SQLITE_HAS_CODEC |
| 17361 | 17392 | "HAS_CODEC", |
| 17362 | 17393 | #endif |
| 17363 | 17394 | #if HAVE_ISNAN || SQLITE_HAVE_ISNAN |
| @@ -18105,12 +18136,12 @@ | ||
| 18105 | 18136 | UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */ |
| 18106 | 18137 | UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */ |
| 18107 | 18138 | int iNewReg; /* Register for new.* values */ |
| 18108 | 18139 | i64 iKey1; /* First key value passed to hook */ |
| 18109 | 18140 | i64 iKey2; /* Second key value passed to hook */ |
| 18110 | - int iPKey; /* If not negative index of IPK column */ | |
| 18111 | 18141 | Mem *aNew; /* Array of new.* values */ |
| 18142 | + Table *pTab; /* Schema object being upated */ | |
| 18112 | 18143 | }; |
| 18113 | 18144 | |
| 18114 | 18145 | /* |
| 18115 | 18146 | ** Function prototypes |
| 18116 | 18147 | */ |
| @@ -24598,13 +24629,12 @@ | ||
| 24598 | 24629 | char *zNew; |
| 24599 | 24630 | size_t n; |
| 24600 | 24631 | if( z==0 ){ |
| 24601 | 24632 | return 0; |
| 24602 | 24633 | } |
| 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); | |
| 24606 | 24636 | if( zNew ){ |
| 24607 | 24637 | memcpy(zNew, z, n); |
| 24608 | 24638 | } |
| 24609 | 24639 | return zNew; |
| 24610 | 24640 | } |
| @@ -29127,11 +29157,11 @@ | ||
| 29127 | 29157 | /* 120 */ "SorterData" OpHelp("r[P2]=data"), |
| 29128 | 29158 | /* 121 */ "RowKey" OpHelp("r[P2]=key"), |
| 29129 | 29159 | /* 122 */ "RowData" OpHelp("r[P2]=data"), |
| 29130 | 29160 | /* 123 */ "Rowid" OpHelp("r[P2]=rowid"), |
| 29131 | 29161 | /* 124 */ "NullRow" OpHelp(""), |
| 29132 | - /* 125 */ "SorterInsert" OpHelp(""), | |
| 29162 | + /* 125 */ "SorterInsert" OpHelp("key=r[P2]"), | |
| 29133 | 29163 | /* 126 */ "IdxInsert" OpHelp("key=r[P2]"), |
| 29134 | 29164 | /* 127 */ "IdxDelete" OpHelp("key=r[P2@P3]"), |
| 29135 | 29165 | /* 128 */ "Seek" OpHelp("Move P3 to P1.rowid"), |
| 29136 | 29166 | /* 129 */ "IdxRowid" OpHelp("r[P2]=rowid"), |
| 29137 | 29167 | /* 130 */ "Destroy" OpHelp(""), |
| @@ -40674,10 +40704,16 @@ | ||
| 40674 | 40704 | a[1] = winIoerrRetryDelay; |
| 40675 | 40705 | } |
| 40676 | 40706 | OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); |
| 40677 | 40707 | return SQLITE_OK; |
| 40678 | 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 | + } | |
| 40679 | 40715 | #ifdef SQLITE_TEST |
| 40680 | 40716 | case SQLITE_FCNTL_WIN32_SET_HANDLE: { |
| 40681 | 40717 | LPHANDLE phFile = (LPHANDLE)pArg; |
| 40682 | 40718 | HANDLE hOldFile = pFile->h; |
| 40683 | 40719 | pFile->h = *phFile; |
| @@ -46249,21 +46285,21 @@ | ||
| 46249 | 46285 | #define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */ |
| 46250 | 46286 | |
| 46251 | 46287 | #ifdef SQLITE_OMIT_WAL |
| 46252 | 46288 | # define sqlite3WalOpen(x,y,z) 0 |
| 46253 | 46289 | # define sqlite3WalLimit(x,y) |
| 46254 | -# define sqlite3WalClose(w,x,y,z) 0 | |
| 46290 | +# define sqlite3WalClose(v,w,x,y,z) 0 | |
| 46255 | 46291 | # define sqlite3WalBeginReadTransaction(y,z) 0 |
| 46256 | 46292 | # define sqlite3WalEndReadTransaction(z) |
| 46257 | 46293 | # define sqlite3WalDbsize(y) 0 |
| 46258 | 46294 | # define sqlite3WalBeginWriteTransaction(y) 0 |
| 46259 | 46295 | # define sqlite3WalEndWriteTransaction(x) 0 |
| 46260 | 46296 | # define sqlite3WalUndo(x,y,z) 0 |
| 46261 | 46297 | # define sqlite3WalSavepoint(y,z) |
| 46262 | 46298 | # define sqlite3WalSavepointUndo(y,z) 0 |
| 46263 | 46299 | # 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 | |
| 46265 | 46301 | # define sqlite3WalCallback(z) 0 |
| 46266 | 46302 | # define sqlite3WalExclusiveMode(y,z) 0 |
| 46267 | 46303 | # define sqlite3WalHeapMemory(z) 0 |
| 46268 | 46304 | # define sqlite3WalFramesize(z) 0 |
| 46269 | 46305 | # define sqlite3WalFindFrame(x,y,z) 0 |
| @@ -46277,11 +46313,11 @@ | ||
| 46277 | 46313 | */ |
| 46278 | 46314 | typedef struct Wal Wal; |
| 46279 | 46315 | |
| 46280 | 46316 | /* Open and close a connection to a write-ahead log. */ |
| 46281 | 46317 | 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 *); | |
| 46283 | 46319 | |
| 46284 | 46320 | /* Set the limiting size of a WAL file. */ |
| 46285 | 46321 | SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64); |
| 46286 | 46322 | |
| 46287 | 46323 | /* Used by readers to open (lock) and close (unlock) a snapshot. A |
| @@ -46320,10 +46356,11 @@ | ||
| 46320 | 46356 | SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int); |
| 46321 | 46357 | |
| 46322 | 46358 | /* Copy pages from the log to the database file */ |
| 46323 | 46359 | SQLITE_PRIVATE int sqlite3WalCheckpoint( |
| 46324 | 46360 | Wal *pWal, /* Write-ahead log connection */ |
| 46361 | + sqlite3 *db, /* Check this handle's interrupt flag */ | |
| 46325 | 46362 | int eMode, /* One of PASSIVE, FULL and RESTART */ |
| 46326 | 46363 | int (*xBusy)(void*), /* Function to call when busy */ |
| 46327 | 46364 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 46328 | 46365 | int sync_flags, /* Flags to sync db file with (or 0) */ |
| 46329 | 46366 | int nBuf, /* Size of buffer nBuf */ |
| @@ -47164,13 +47201,14 @@ | ||
| 47164 | 47201 | /* |
| 47165 | 47202 | ** Return true if this pager uses a write-ahead log instead of the usual |
| 47166 | 47203 | ** rollback journal. Otherwise false. |
| 47167 | 47204 | */ |
| 47168 | 47205 | #ifndef SQLITE_OMIT_WAL |
| 47169 | -static int pagerUseWal(Pager *pPager){ | |
| 47206 | +SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager){ | |
| 47170 | 47207 | return (pPager->pWal!=0); |
| 47171 | 47208 | } |
| 47209 | +# define pagerUseWal(x) sqlite3PagerUseWal(x) | |
| 47172 | 47210 | #else |
| 47173 | 47211 | # define pagerUseWal(x) 0 |
| 47174 | 47212 | # define pagerRollbackWal(x) 0 |
| 47175 | 47213 | # define pagerWalFrames(v,w,x,y) 0 |
| 47176 | 47214 | # define pagerOpenWalIfPresent(z) SQLITE_OK |
| @@ -50368,21 +50406,22 @@ | ||
| 50368 | 50406 | ** This function always succeeds. If a transaction is active an attempt |
| 50369 | 50407 | ** is made to roll it back. If an error occurs during the rollback |
| 50370 | 50408 | ** a hot journal may be left in the filesystem but no error is returned |
| 50371 | 50409 | ** to the caller. |
| 50372 | 50410 | */ |
| 50373 | -SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){ | |
| 50411 | +SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){ | |
| 50374 | 50412 | u8 *pTmp = (u8 *)pPager->pTmpSpace; |
| 50375 | 50413 | |
| 50414 | + assert( db || pagerUseWal(pPager)==0 ); | |
| 50376 | 50415 | assert( assert_pager_state(pPager) ); |
| 50377 | 50416 | disable_simulated_io_errors(); |
| 50378 | 50417 | sqlite3BeginBenignMalloc(); |
| 50379 | 50418 | pagerFreeMapHdrs(pPager); |
| 50380 | 50419 | /* pPager->errCode = 0; */ |
| 50381 | 50420 | pPager->exclusiveMode = 0; |
| 50382 | 50421 | #ifndef SQLITE_OMIT_WAL |
| 50383 | - sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp); | |
| 50422 | + sqlite3WalClose(pPager->pWal,db,pPager->ckptSyncFlags,pPager->pageSize,pTmp); | |
| 50384 | 50423 | pPager->pWal = 0; |
| 50385 | 50424 | #endif |
| 50386 | 50425 | pager_reset(pPager); |
| 50387 | 50426 | if( MEMDB ){ |
| 50388 | 50427 | pager_unlock(pPager); |
| @@ -53541,14 +53580,20 @@ | ||
| 53541 | 53580 | ** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint() |
| 53542 | 53581 | ** or wal_blocking_checkpoint() API functions. |
| 53543 | 53582 | ** |
| 53544 | 53583 | ** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. |
| 53545 | 53584 | */ |
| 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 | +){ | |
| 53547 | 53592 | int rc = SQLITE_OK; |
| 53548 | 53593 | if( pPager->pWal ){ |
| 53549 | - rc = sqlite3WalCheckpoint(pPager->pWal, eMode, | |
| 53594 | + rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode, | |
| 53550 | 53595 | (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), |
| 53551 | 53596 | pPager->pBusyHandlerArg, |
| 53552 | 53597 | pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, |
| 53553 | 53598 | pnLog, pnCkpt |
| 53554 | 53599 | ); |
| @@ -53676,11 +53721,11 @@ | ||
| 53676 | 53721 | ** Before closing the log file, this function attempts to take an |
| 53677 | 53722 | ** EXCLUSIVE lock on the database file. If this cannot be obtained, an |
| 53678 | 53723 | ** error (SQLITE_BUSY) is returned and the log connection is not closed. |
| 53679 | 53724 | ** If successful, the EXCLUSIVE lock is not released before returning. |
| 53680 | 53725 | */ |
| 53681 | -SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){ | |
| 53726 | +SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){ | |
| 53682 | 53727 | int rc = SQLITE_OK; |
| 53683 | 53728 | |
| 53684 | 53729 | assert( pPager->journalMode==PAGER_JOURNALMODE_WAL ); |
| 53685 | 53730 | |
| 53686 | 53731 | /* If the log file is not already open, but does exist in the file-system, |
| @@ -53704,11 +53749,11 @@ | ||
| 53704 | 53749 | ** the database file, the log and log-summary files will be deleted. |
| 53705 | 53750 | */ |
| 53706 | 53751 | if( rc==SQLITE_OK && pPager->pWal ){ |
| 53707 | 53752 | rc = pagerExclusiveLock(pPager); |
| 53708 | 53753 | if( rc==SQLITE_OK ){ |
| 53709 | - rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, | |
| 53754 | + rc = sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags, | |
| 53710 | 53755 | pPager->pageSize, (u8*)pPager->pTmpSpace); |
| 53711 | 53756 | pPager->pWal = 0; |
| 53712 | 53757 | pagerFixMaplimit(pPager); |
| 53713 | 53758 | if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK); |
| 53714 | 53759 | } |
| @@ -55487,10 +55532,11 @@ | ||
| 55487 | 55532 | ** checkpoint is running (in any other thread or process) at the same |
| 55488 | 55533 | ** time. |
| 55489 | 55534 | */ |
| 55490 | 55535 | static int walCheckpoint( |
| 55491 | 55536 | Wal *pWal, /* Wal connection */ |
| 55537 | + sqlite3 *db, /* Check for interrupts on this handle */ | |
| 55492 | 55538 | int eMode, /* One of PASSIVE, FULL or RESTART */ |
| 55493 | 55539 | int (*xBusy)(void*), /* Function to call when busy */ |
| 55494 | 55540 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 55495 | 55541 | int sync_flags, /* Flags for OsSync() (or 0) */ |
| 55496 | 55542 | u8 *zBuf /* Temporary buffer to use */ |
| @@ -55581,10 +55627,14 @@ | ||
| 55581 | 55627 | |
| 55582 | 55628 | /* Iterate through the contents of the WAL, copying data to the db file */ |
| 55583 | 55629 | while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ |
| 55584 | 55630 | i64 iOffset; |
| 55585 | 55631 | assert( walFramePgno(pWal, iFrame)==iDbpage ); |
| 55632 | + if( db->u1.isInterrupted ){ | |
| 55633 | + rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT; | |
| 55634 | + break; | |
| 55635 | + } | |
| 55586 | 55636 | if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){ |
| 55587 | 55637 | continue; |
| 55588 | 55638 | } |
| 55589 | 55639 | iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE; |
| 55590 | 55640 | /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */ |
| @@ -55685,10 +55735,11 @@ | ||
| 55685 | 55735 | /* |
| 55686 | 55736 | ** Close a connection to a log file. |
| 55687 | 55737 | */ |
| 55688 | 55738 | SQLITE_PRIVATE int sqlite3WalClose( |
| 55689 | 55739 | Wal *pWal, /* Wal to close */ |
| 55740 | + sqlite3 *db, /* For interrupt flag */ | |
| 55690 | 55741 | int sync_flags, /* Flags to pass to OsSync() (or 0) */ |
| 55691 | 55742 | int nBuf, |
| 55692 | 55743 | u8 *zBuf /* Buffer of at least nBuf bytes */ |
| 55693 | 55744 | ){ |
| 55694 | 55745 | int rc = SQLITE_OK; |
| @@ -55701,17 +55752,18 @@ | ||
| 55701 | 55752 | ** the database. In this case checkpoint the database and unlink both |
| 55702 | 55753 | ** the wal and wal-index files. |
| 55703 | 55754 | ** |
| 55704 | 55755 | ** The EXCLUSIVE lock is not released before returning. |
| 55705 | 55756 | */ |
| 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 | + ){ | |
| 55708 | 55760 | if( pWal->exclusiveMode==WAL_NORMAL_MODE ){ |
| 55709 | 55761 | pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; |
| 55710 | 55762 | } |
| 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 | |
| 55713 | 55765 | ); |
| 55714 | 55766 | if( rc==SQLITE_OK ){ |
| 55715 | 55767 | int bPersist = -1; |
| 55716 | 55768 | sqlite3OsFileControlHint( |
| 55717 | 55769 | pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersist |
| @@ -56955,10 +57007,11 @@ | ||
| 56955 | 57007 | ** If parameter xBusy is not NULL, it is a pointer to a busy-handler |
| 56956 | 57008 | ** callback. In this case this function runs a blocking checkpoint. |
| 56957 | 57009 | */ |
| 56958 | 57010 | SQLITE_PRIVATE int sqlite3WalCheckpoint( |
| 56959 | 57011 | Wal *pWal, /* Wal connection */ |
| 57012 | + sqlite3 *db, /* Check this handle's interrupt flag */ | |
| 56960 | 57013 | int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */ |
| 56961 | 57014 | int (*xBusy)(void*), /* Function to call when busy */ |
| 56962 | 57015 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 56963 | 57016 | int sync_flags, /* Flags to sync db file with (or 0) */ |
| 56964 | 57017 | int nBuf, /* Size of temporary buffer */ |
| @@ -57029,11 +57082,11 @@ | ||
| 57029 | 57082 | if( rc==SQLITE_OK ){ |
| 57030 | 57083 | |
| 57031 | 57084 | if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ |
| 57032 | 57085 | rc = SQLITE_CORRUPT_BKPT; |
| 57033 | 57086 | }else{ |
| 57034 | - rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); | |
| 57087 | + rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); | |
| 57035 | 57088 | } |
| 57036 | 57089 | |
| 57037 | 57090 | /* If no error occurred, set the output variables. */ |
| 57038 | 57091 | if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ |
| 57039 | 57092 | if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; |
| @@ -60619,23 +60672,30 @@ | ||
| 60619 | 60672 | *ppBtree = p; |
| 60620 | 60673 | |
| 60621 | 60674 | btree_open_out: |
| 60622 | 60675 | if( rc!=SQLITE_OK ){ |
| 60623 | 60676 | if( pBt && pBt->pPager ){ |
| 60624 | - sqlite3PagerClose(pBt->pPager); | |
| 60677 | + sqlite3PagerClose(pBt->pPager, 0); | |
| 60625 | 60678 | } |
| 60626 | 60679 | sqlite3_free(pBt); |
| 60627 | 60680 | sqlite3_free(p); |
| 60628 | 60681 | *ppBtree = 0; |
| 60629 | 60682 | }else{ |
| 60683 | + sqlite3_file *pFile; | |
| 60684 | + | |
| 60630 | 60685 | /* If the B-Tree was successfully opened, set the pager-cache size to the |
| 60631 | 60686 | ** default value. Except, when opening on an existing shared pager-cache, |
| 60632 | 60687 | ** do not change the pager-cache size. |
| 60633 | 60688 | */ |
| 60634 | 60689 | if( sqlite3BtreeSchema(p, 0, 0)==0 ){ |
| 60635 | 60690 | sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE); |
| 60636 | 60691 | } |
| 60692 | + | |
| 60693 | + pFile = sqlite3PagerFile(pBt->pPager); | |
| 60694 | + if( pFile->pMethods ){ | |
| 60695 | + sqlite3OsFileControlHint(pFile, SQLITE_FCNTL_PDB, (void*)&pBt->db); | |
| 60696 | + } | |
| 60637 | 60697 | } |
| 60638 | 60698 | if( mutexOpen ){ |
| 60639 | 60699 | assert( sqlite3_mutex_held(mutexOpen) ); |
| 60640 | 60700 | sqlite3_mutex_leave(mutexOpen); |
| 60641 | 60701 | } |
| @@ -60761,11 +60821,11 @@ | ||
| 60761 | 60821 | ** it without having to hold the mutex. |
| 60762 | 60822 | ** |
| 60763 | 60823 | ** Clean out and delete the BtShared object. |
| 60764 | 60824 | */ |
| 60765 | 60825 | assert( !pBt->pCursor ); |
| 60766 | - sqlite3PagerClose(pBt->pPager); | |
| 60826 | + sqlite3PagerClose(pBt->pPager, p->db); | |
| 60767 | 60827 | if( pBt->xFreeSchema && pBt->pSchema ){ |
| 60768 | 60828 | pBt->xFreeSchema(pBt->pSchema); |
| 60769 | 60829 | } |
| 60770 | 60830 | sqlite3DbFree(0, pBt->pSchema); |
| 60771 | 60831 | freeTempSpace(pBt); |
| @@ -62825,11 +62885,11 @@ | ||
| 62825 | 62885 | if( (eOp&0x01)==0 /* (1) */ |
| 62826 | 62886 | && offset==0 /* (2) */ |
| 62827 | 62887 | && (bEnd || a==ovflSize) /* (6) */ |
| 62828 | 62888 | && pBt->inTransaction==TRANS_READ /* (4) */ |
| 62829 | 62889 | && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */ |
| 62830 | - && pBt->pPage1->aData[19]==0x01 /* (5) */ | |
| 62890 | + && 0==sqlite3PagerUseWal(pBt->pPager) /* (5) */ | |
| 62831 | 62891 | && &pBuf[-4]>=pBufStart /* (7) */ |
| 62832 | 62892 | ){ |
| 62833 | 62893 | u8 aSave[4]; |
| 62834 | 62894 | u8 *aWrite = &pBuf[-4]; |
| 62835 | 62895 | assert( aWrite>=pBufStart ); /* hence (7) */ |
| @@ -63081,13 +63141,16 @@ | ||
| 63081 | 63141 | } |
| 63082 | 63142 | sqlite3BtreeClearCursor(pCur); |
| 63083 | 63143 | } |
| 63084 | 63144 | |
| 63085 | 63145 | 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; | |
| 63089 | 63152 | } |
| 63090 | 63153 | }else if( pCur->pgnoRoot==0 ){ |
| 63091 | 63154 | pCur->eState = CURSOR_INVALID; |
| 63092 | 63155 | return SQLITE_OK; |
| 63093 | 63156 | }else{ |
| @@ -63094,11 +63157,11 @@ | ||
| 63094 | 63157 | assert( pCur->iPage==(-1) ); |
| 63095 | 63158 | rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0], |
| 63096 | 63159 | 0, pCur->curPagerFlags); |
| 63097 | 63160 | if( rc!=SQLITE_OK ){ |
| 63098 | 63161 | pCur->eState = CURSOR_INVALID; |
| 63099 | - return rc; | |
| 63162 | + return rc; | |
| 63100 | 63163 | } |
| 63101 | 63164 | pCur->iPage = 0; |
| 63102 | 63165 | pCur->curIntKey = pCur->apPage[0]->intKey; |
| 63103 | 63166 | } |
| 63104 | 63167 | pRoot = pCur->apPage[0]; |
| @@ -63117,14 +63180,16 @@ | ||
| 63117 | 63180 | assert( pRoot->intKey==1 || pRoot->intKey==0 ); |
| 63118 | 63181 | if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){ |
| 63119 | 63182 | return SQLITE_CORRUPT_BKPT; |
| 63120 | 63183 | } |
| 63121 | 63184 | |
| 63185 | +skip_init: | |
| 63122 | 63186 | pCur->aiIdx[0] = 0; |
| 63123 | 63187 | pCur->info.nSize = 0; |
| 63124 | 63188 | pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl); |
| 63125 | 63189 | |
| 63190 | + pRoot = pCur->apPage[0]; | |
| 63126 | 63191 | if( pRoot->nCell>0 ){ |
| 63127 | 63192 | pCur->eState = CURSOR_VALID; |
| 63128 | 63193 | }else if( !pRoot->leaf ){ |
| 63129 | 63194 | Pgno subpage; |
| 63130 | 63195 | if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT; |
| @@ -67701,11 +67766,11 @@ | ||
| 67701 | 67766 | BtShared *pBt = p->pBt; |
| 67702 | 67767 | sqlite3BtreeEnter(p); |
| 67703 | 67768 | if( pBt->inTransaction!=TRANS_NONE ){ |
| 67704 | 67769 | rc = SQLITE_LOCKED; |
| 67705 | 67770 | }else{ |
| 67706 | - rc = sqlite3PagerCheckpoint(pBt->pPager, eMode, pnLog, pnCkpt); | |
| 67771 | + rc = sqlite3PagerCheckpoint(pBt->pPager, p->db, eMode, pnLog, pnCkpt); | |
| 67707 | 67772 | } |
| 67708 | 67773 | sqlite3BtreeLeave(p); |
| 67709 | 67774 | } |
| 67710 | 67775 | return rc; |
| 67711 | 67776 | } |
| @@ -75076,11 +75141,11 @@ | ||
| 75076 | 75141 | preupdate.keyinfo.enc = ENC(db); |
| 75077 | 75142 | preupdate.keyinfo.nField = pTab->nCol; |
| 75078 | 75143 | preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder; |
| 75079 | 75144 | preupdate.iKey1 = iKey1; |
| 75080 | 75145 | preupdate.iKey2 = iKey2; |
| 75081 | - preupdate.iPKey = pTab->iPKey; | |
| 75146 | + preupdate.pTab = pTab; | |
| 75082 | 75147 | |
| 75083 | 75148 | db->pPreUpdate = &preupdate; |
| 75084 | 75149 | db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2); |
| 75085 | 75150 | db->pPreUpdate = 0; |
| 75086 | 75151 | sqlite3DbFree(db, preupdate.aRecord); |
| @@ -76808,13 +76873,18 @@ | ||
| 76808 | 76873 | } |
| 76809 | 76874 | |
| 76810 | 76875 | if( iIdx>=p->pUnpacked->nField ){ |
| 76811 | 76876 | *ppValue = (sqlite3_value *)columnNullValue(); |
| 76812 | 76877 | }else{ |
| 76878 | + Mem *pMem = *ppValue = &p->pUnpacked->aMem[iIdx]; | |
| 76813 | 76879 | *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 | + } | |
| 76816 | 76886 | } |
| 76817 | 76887 | } |
| 76818 | 76888 | |
| 76819 | 76889 | preupdate_old_out: |
| 76820 | 76890 | sqlite3Error(db, rc); |
| @@ -76887,11 +76957,11 @@ | ||
| 76887 | 76957 | } |
| 76888 | 76958 | if( iIdx>=pUnpack->nField ){ |
| 76889 | 76959 | pMem = (sqlite3_value *)columnNullValue(); |
| 76890 | 76960 | }else{ |
| 76891 | 76961 | pMem = &pUnpack->aMem[iIdx]; |
| 76892 | - if( iIdx==p->iPKey ){ | |
| 76962 | + if( iIdx==p->pTab->iPKey ){ | |
| 76893 | 76963 | sqlite3VdbeMemSetInt64(pMem, p->iKey2); |
| 76894 | 76964 | } |
| 76895 | 76965 | } |
| 76896 | 76966 | }else{ |
| 76897 | 76967 | /* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required |
| @@ -76908,11 +76978,11 @@ | ||
| 76908 | 76978 | } |
| 76909 | 76979 | } |
| 76910 | 76980 | assert( iIdx>=0 && iIdx<p->pCsr->nField ); |
| 76911 | 76981 | pMem = &p->aNew[iIdx]; |
| 76912 | 76982 | if( pMem->flags==0 ){ |
| 76913 | - if( iIdx==p->iPKey ){ | |
| 76983 | + if( iIdx==p->pTab->iPKey ){ | |
| 76914 | 76984 | sqlite3VdbeMemSetInt64(pMem, p->iKey2); |
| 76915 | 76985 | }else{ |
| 76916 | 76986 | rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]); |
| 76917 | 76987 | if( rc!=SQLITE_OK ) goto preupdate_new_out; |
| 76918 | 76988 | } |
| @@ -79286,12 +79356,11 @@ | ||
| 79286 | 79356 | ** or not both operands are null. |
| 79287 | 79357 | */ |
| 79288 | 79358 | assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne ); |
| 79289 | 79359 | assert( (flags1 & MEM_Cleared)==0 ); |
| 79290 | 79360 | assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 ); |
| 79291 | - if( (flags1&MEM_Null)!=0 | |
| 79292 | - && (flags3&MEM_Null)!=0 | |
| 79361 | + if( (flags1&flags3&MEM_Null)!=0 | |
| 79293 | 79362 | && (flags3&MEM_Cleared)==0 |
| 79294 | 79363 | ){ |
| 79295 | 79364 | res = 0; /* Operands are equal */ |
| 79296 | 79365 | }else{ |
| 79297 | 79366 | res = 1; /* Operands are not equal */ |
| @@ -81554,11 +81623,11 @@ | ||
| 81554 | 81623 | |
| 81555 | 81624 | REGISTER_TRACE(pOp->p3, pMem); |
| 81556 | 81625 | sqlite3VdbeMemIntegerify(pMem); |
| 81557 | 81626 | assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ |
| 81558 | 81627 | if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){ |
| 81559 | - rc = SQLITE_FULL; /* IMP: R-12275-61338 */ | |
| 81628 | + rc = SQLITE_FULL; /* IMP: R-17817-00630 */ | |
| 81560 | 81629 | goto abort_due_to_error; |
| 81561 | 81630 | } |
| 81562 | 81631 | if( v<pMem->u.i+1 ){ |
| 81563 | 81632 | v = pMem->u.i + 1; |
| 81564 | 81633 | } |
| @@ -82321,10 +82390,17 @@ | ||
| 82321 | 82390 | ** This flag avoids doing an extra seek. |
| 82322 | 82391 | ** |
| 82323 | 82392 | ** This instruction only works for indices. The equivalent instruction |
| 82324 | 82393 | ** for tables is OP_Insert. |
| 82325 | 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 | +*/ | |
| 82326 | 82402 | case OP_SorterInsert: /* in2 */ |
| 82327 | 82403 | case OP_IdxInsert: { /* in2 */ |
| 82328 | 82404 | VdbeCursor *pC; |
| 82329 | 82405 | BtreePayload x; |
| 82330 | 82406 | |
| @@ -83549,11 +83625,11 @@ | ||
| 83549 | 83625 | /* If leaving WAL mode, close the log file. If successful, the call |
| 83550 | 83626 | ** to PagerCloseWal() checkpoints and deletes the write-ahead-log |
| 83551 | 83627 | ** file. An EXCLUSIVE lock may still be held on the database file |
| 83552 | 83628 | ** after a successful return. |
| 83553 | 83629 | */ |
| 83554 | - rc = sqlite3PagerCloseWal(pPager); | |
| 83630 | + rc = sqlite3PagerCloseWal(pPager, db); | |
| 83555 | 83631 | if( rc==SQLITE_OK ){ |
| 83556 | 83632 | sqlite3PagerSetJournalMode(pPager, eNew); |
| 83557 | 83633 | } |
| 83558 | 83634 | }else if( eOld==PAGER_JOURNALMODE_MEMORY ){ |
| 83559 | 83635 | /* Cannot transition directly from MEMORY to WAL. Use mode OFF |
| @@ -94292,15 +94368,14 @@ | ||
| 94292 | 94368 | && (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab) |
| 94293 | 94369 | || sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) ) |
| 94294 | 94370 | ){ |
| 94295 | 94371 | return 1; |
| 94296 | 94372 | } |
| 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; | |
| 94302 | 94377 | } |
| 94303 | 94378 | return 0; |
| 94304 | 94379 | } |
| 94305 | 94380 | |
| 94306 | 94381 | /* |
| @@ -122354,11 +122429,11 @@ | ||
| 122354 | 122429 | } |
| 122355 | 122430 | #endif |
| 122356 | 122431 | |
| 122357 | 122432 | sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size); |
| 122358 | 122433 | sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0)); |
| 122359 | - sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF); | |
| 122434 | + sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF|PAGER_CACHESPILL); | |
| 122360 | 122435 | |
| 122361 | 122436 | /* Begin a transaction and take an exclusive lock on the main database |
| 122362 | 122437 | ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below, |
| 122363 | 122438 | ** to ensure that we do not try to change the page-size on a WAL database. |
| 122364 | 122439 | */ |
| @@ -127537,10 +127612,11 @@ | ||
| 127537 | 127612 | Expr *pNew; |
| 127538 | 127613 | Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i); |
| 127539 | 127614 | Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i); |
| 127540 | 127615 | |
| 127541 | 127616 | pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight, 0); |
| 127617 | + transferJoinMarkings(pNew, pExpr); | |
| 127542 | 127618 | idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC); |
| 127543 | 127619 | exprAnalyze(pSrc, pWC, idxNew); |
| 127544 | 127620 | } |
| 127545 | 127621 | pTerm = &pWC->a[idxTerm]; |
| 127546 | 127622 | pTerm->wtFlags = TERM_CODED|TERM_VIRTUAL; /* Disable the original */ |
| @@ -127978,15 +128054,17 @@ | ||
| 127978 | 128054 | Expr *pX; /* An expression being tested */ |
| 127979 | 128055 | WhereClause *pWC; /* Shorthand for pScan->pWC */ |
| 127980 | 128056 | WhereTerm *pTerm; /* The term being tested */ |
| 127981 | 128057 | int k = pScan->k; /* Where to start scanning */ |
| 127982 | 128058 | |
| 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){ | |
| 127985 | 128062 | 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{ | |
| 127988 | 128066 | for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){ |
| 127989 | 128067 | if( pTerm->leftCursor==iCur |
| 127990 | 128068 | && pTerm->u.leftColumn==iColumn |
| 127991 | 128069 | && (iColumn!=XN_EXPR |
| 127992 | 128070 | || sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0) |
| @@ -128032,19 +128110,21 @@ | ||
| 128032 | 128110 | && pX->iColumn==pScan->aiColumn[0] |
| 128033 | 128111 | ){ |
| 128034 | 128112 | testcase( pTerm->eOperator & WO_IS ); |
| 128035 | 128113 | continue; |
| 128036 | 128114 | } |
| 128115 | + pScan->pWC = pWC; | |
| 128037 | 128116 | pScan->k = k+1; |
| 128038 | 128117 | return pTerm; |
| 128039 | 128118 | } |
| 128040 | 128119 | } |
| 128041 | 128120 | } |
| 128042 | - pScan->pWC = pScan->pWC->pOuter; | |
| 128121 | + pWC = pWC->pOuter; | |
| 128043 | 128122 | k = 0; |
| 128044 | - } | |
| 128045 | - pScan->pWC = pScan->pOrigWC; | |
| 128123 | + }while( pWC!=0 ); | |
| 128124 | + if( pScan->iEquiv>=pScan->nEquiv ) break; | |
| 128125 | + pWC = pScan->pOrigWC; | |
| 128046 | 128126 | k = 0; |
| 128047 | 128127 | pScan->iEquiv++; |
| 128048 | 128128 | } |
| 128049 | 128129 | return 0; |
| 128050 | 128130 | } |
| @@ -128074,28 +128154,28 @@ | ||
| 128074 | 128154 | int iCur, /* Cursor to scan for */ |
| 128075 | 128155 | int iColumn, /* Column to scan for */ |
| 128076 | 128156 | u32 opMask, /* Operator(s) to scan for */ |
| 128077 | 128157 | Index *pIdx /* Must be compatible with this index */ |
| 128078 | 128158 | ){ |
| 128079 | - int j = 0; | |
| 128080 | - | |
| 128081 | - /* memset(pScan, 0, sizeof(*pScan)); */ | |
| 128082 | 128159 | pScan->pOrigWC = pWC; |
| 128083 | 128160 | pScan->pWC = pWC; |
| 128084 | 128161 | pScan->pIdxExpr = 0; |
| 128162 | + pScan->idxaff = 0; | |
| 128163 | + pScan->zCollName = 0; | |
| 128085 | 128164 | if( pIdx ){ |
| 128086 | - j = iColumn; | |
| 128165 | + int j = iColumn; | |
| 128087 | 128166 | 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; | |
| 128097 | 128177 | } |
| 128098 | 128178 | pScan->opMask = opMask; |
| 128099 | 128179 | pScan->k = 0; |
| 128100 | 128180 | pScan->aiCur[0] = iCur; |
| 128101 | 128181 | pScan->aiColumn[0] = iColumn; |
| @@ -132640,17 +132720,19 @@ | ||
| 132640 | 132720 | pLevel->addrLikeRep); |
| 132641 | 132721 | VdbeCoverage(v); |
| 132642 | 132722 | } |
| 132643 | 132723 | #endif |
| 132644 | 132724 | if( pLevel->iLeftJoin ){ |
| 132725 | + int ws = pLoop->wsFlags; | |
| 132645 | 132726 | 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 ){ | |
| 132649 | 132729 | sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor); |
| 132650 | 132730 | } |
| 132651 | - if( pLoop->wsFlags & WHERE_INDEXED ){ | |
| 132731 | + if( (ws & WHERE_INDEXED) | |
| 132732 | + || ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx) | |
| 132733 | + ){ | |
| 132652 | 132734 | sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur); |
| 132653 | 132735 | } |
| 132654 | 132736 | if( pLevel->op==OP_Return ){ |
| 132655 | 132737 | sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst); |
| 132656 | 132738 | }else{ |
| @@ -138612,10 +138694,11 @@ | ||
| 138612 | 138694 | } aFlagOp[] = { |
| 138613 | 138695 | { SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys }, |
| 138614 | 138696 | { SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger }, |
| 138615 | 138697 | { SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer }, |
| 138616 | 138698 | { SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension }, |
| 138699 | + { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose }, | |
| 138617 | 138700 | }; |
| 138618 | 138701 | unsigned int i; |
| 138619 | 138702 | rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ |
| 138620 | 138703 | for(i=0; i<ArraySize(aFlagOp); i++){ |
| 138621 | 138704 | if( aFlagOp[i].op==op ){ |
| @@ -139908,10 +139991,17 @@ | ||
| 139908 | 139991 | db->busyHandler.nBusy = 0; |
| 139909 | 139992 | rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt); |
| 139910 | 139993 | sqlite3Error(db, rc); |
| 139911 | 139994 | } |
| 139912 | 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 | + | |
| 139913 | 140003 | sqlite3_mutex_leave(db->mutex); |
| 139914 | 140004 | return rc; |
| 139915 | 140005 | #endif |
| 139916 | 140006 | } |
| 139917 | 140007 | |
| @@ -140410,10 +140500,11 @@ | ||
| 140410 | 140500 | int octet = (sqlite3HexToInt(zUri[iIn++]) << 4); |
| 140411 | 140501 | octet += sqlite3HexToInt(zUri[iIn++]); |
| 140412 | 140502 | |
| 140413 | 140503 | assert( octet>=0 && octet<256 ); |
| 140414 | 140504 | if( octet==0 ){ |
| 140505 | +#ifndef SQLITE_ENABLE_URI_00_ERROR | |
| 140415 | 140506 | /* This branch is taken when "%00" appears within the URI. In this |
| 140416 | 140507 | ** case we ignore all text in the remainder of the path, name or |
| 140417 | 140508 | ** value currently being parsed. So ignore the current character |
| 140418 | 140509 | ** and skip to the next "?", "=" or "&", as appropriate. */ |
| 140419 | 140510 | while( (c = zUri[iIn])!=0 && c!='#' |
| @@ -140422,10 +140513,16 @@ | ||
| 140422 | 140513 | && (eState!=2 || c!='&') |
| 140423 | 140514 | ){ |
| 140424 | 140515 | iIn++; |
| 140425 | 140516 | } |
| 140426 | 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 | |
| 140427 | 140524 | } |
| 140428 | 140525 | c = octet; |
| 140429 | 140526 | }else if( eState==1 && (c=='&' || c=='=') ){ |
| 140430 | 140527 | if( zFile[iOut-1]==0 ){ |
| 140431 | 140528 | /* An empty option name. Ignore this option altogether. */ |
| @@ -165207,11 +165304,11 @@ | ||
| 165207 | 165304 | ** of the locale to use. Passing an empty string ("") or SQL NULL value |
| 165208 | 165305 | ** as the second argument is the same as invoking the 1 argument version |
| 165209 | 165306 | ** of upper() or lower(). |
| 165210 | 165307 | ** |
| 165211 | 165308 | ** lower('I', 'en_us') -> 'i' |
| 165212 | -** lower('I', 'tr_tr') -> 'ı' (small dotless i) | |
| 165309 | +** lower('I', 'tr_tr') -> '\u131' (small dotless i) | |
| 165213 | 165310 | ** |
| 165214 | 165311 | ** http://www.icu-project.org/userguide/posix.html#case_mappings |
| 165215 | 165312 | */ |
| 165216 | 165313 | static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){ |
| 165217 | 165314 | const UChar *zInput; /* Pointer to input string */ |
| @@ -195596,11 +195693,11 @@ | ||
| 195596 | 195693 | int nArg, /* Number of args */ |
| 195597 | 195694 | sqlite3_value **apUnused /* Function arguments */ |
| 195598 | 195695 | ){ |
| 195599 | 195696 | assert( nArg==0 ); |
| 195600 | 195697 | 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); | |
| 195602 | 195699 | } |
| 195603 | 195700 | |
| 195604 | 195701 | static int fts5Init(sqlite3 *db){ |
| 195605 | 195702 | static const sqlite3_module fts5Mod = { |
| 195606 | 195703 | /* iVersion */ 2, |
| 195607 | 195704 |
| --- 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 @@ | ||
| 119 | 119 | ** |
| 120 | 120 | ** See also: [sqlite3_libversion()], |
| 121 | 121 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 122 | 122 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 123 | 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" | |
| 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 | 127 | |
| 128 | 128 | /* |
| 129 | 129 | ** CAPI3REF: Run-Time Library Version Numbers |
| 130 | 130 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 131 | 131 | ** |
| @@ -975,10 +975,16 @@ | ||
| 975 | 975 | ** <li>[[SQLITE_FCNTL_HAS_MOVED]] |
| 976 | 976 | ** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a |
| 977 | 977 | ** pointer to an integer and it writes a boolean into that integer depending |
| 978 | 978 | ** on whether or not the file has been renamed, moved, or deleted since it |
| 979 | 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. | |
| 980 | 986 | ** |
| 981 | 987 | ** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]] |
| 982 | 988 | ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This |
| 983 | 989 | ** opcode causes the xFileControl method to swap the file handle with the one |
| 984 | 990 | ** pointed to by the pArg argument. This capability is used during testing |
| @@ -1026,10 +1032,12 @@ | ||
| 1026 | 1032 | #define SQLITE_FCNTL_WAL_BLOCK 24 |
| 1027 | 1033 | #define SQLITE_FCNTL_ZIPVFS 25 |
| 1028 | 1034 | #define SQLITE_FCNTL_RBU 26 |
| 1029 | 1035 | #define SQLITE_FCNTL_VFS_POINTER 27 |
| 1030 | 1036 | #define SQLITE_FCNTL_JOURNAL_POINTER 28 |
| 1037 | +#define SQLITE_FCNTL_WIN32_GET_HANDLE 29 | |
| 1038 | +#define SQLITE_FCNTL_PDB 30 | |
| 1031 | 1039 | |
| 1032 | 1040 | /* deprecated names */ |
| 1033 | 1041 | #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE |
| 1034 | 1042 | #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE |
| 1035 | 1043 | #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| @@ -1978,18 +1986,31 @@ | ||
| 1978 | 1986 | ** does not make a copy of the new main schema name string, so the application |
| 1979 | 1987 | ** must ensure that the argument passed into this DBCONFIG option is unchanged |
| 1980 | 1988 | ** until after the database connection closes. |
| 1981 | 1989 | ** </dd> |
| 1982 | 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 | +** | |
| 1983 | 2003 | ** </dl> |
| 1984 | 2004 | */ |
| 1985 | 2005 | #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ |
| 1986 | 2006 | #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ |
| 1987 | 2007 | #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ |
| 1988 | 2008 | #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ |
| 1989 | 2009 | #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ |
| 1990 | 2010 | #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ |
| 2011 | +#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */ | |
| 1991 | 2012 | |
| 1992 | 2013 | |
| 1993 | 2014 | /* |
| 1994 | 2015 | ** CAPI3REF: Enable Or Disable Extended Result Codes |
| 1995 | 2016 | ** METHOD: sqlite3 |
| 1996 | 2017 |
| --- 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 |
+1
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -400,10 +400,11 @@ | ||
| 400 | 400 | |
| 401 | 401 | if( g.thTrace ) Th_Trace("BEGIN_HEADER<br />\n", -1); |
| 402 | 402 | |
| 403 | 403 | /* Generate the header up through the main menu */ |
| 404 | 404 | Th_Store("project_name", db_get("project-name","Unnamed Fossil Project")); |
| 405 | + Th_Store("project_description", db_get("project-description","")); | |
| 405 | 406 | Th_Store("title", zTitle); |
| 406 | 407 | Th_Store("baseurl", g.zBaseURL); |
| 407 | 408 | Th_Store("secureurl", login_wants_https_redirect()? g.zHttpsURL: g.zBaseURL); |
| 408 | 409 | Th_Store("home", g.zTop); |
| 409 | 410 | Th_Store("index_page", db_get("index-page","/home")); |
| 410 | 411 |
| --- 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 |
+83
| --- src/th_main.c | ||
| +++ src/th_main.c | ||
| @@ -1317,10 +1317,92 @@ | ||
| 1317 | 1317 | }else{ |
| 1318 | 1318 | Th_SetResult(interp, "repository unavailable", -1); |
| 1319 | 1319 | return TH_ERROR; |
| 1320 | 1320 | } |
| 1321 | 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 | +} | |
| 1322 | 1404 | |
| 1323 | 1405 | #ifdef _WIN32 |
| 1324 | 1406 | # include <windows.h> |
| 1325 | 1407 | #else |
| 1326 | 1408 | # include <sys/time.h> |
| @@ -1886,10 +1968,11 @@ | ||
| 1886 | 1968 | {"styleHeader", styleHeaderCmd, 0}, |
| 1887 | 1969 | {"styleFooter", styleFooterCmd, 0}, |
| 1888 | 1970 | {"tclReady", tclReadyCmd, 0}, |
| 1889 | 1971 | {"trace", traceCmd, 0}, |
| 1890 | 1972 | {"stime", stimeCmd, 0}, |
| 1973 | + {"unversioned", unversionedCmd, 0}, | |
| 1891 | 1974 | {"utime", utimeCmd, 0}, |
| 1892 | 1975 | {"verifyCsrf", verifyCsrfCmd, 0}, |
| 1893 | 1976 | {"wiki", wikiCmd, (void*)&aFlags[0]}, |
| 1894 | 1977 | {0, 0, 0} |
| 1895 | 1978 | }; |
| 1896 | 1979 |
| --- 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 @@ | ||
| 737 | 737 | pRow->mergeOut, /* mo */ |
| 738 | 738 | pRow->mergeUpto, /* mu */ |
| 739 | 739 | pRow->aiRiser[pRow->iRail], /* u */ |
| 740 | 740 | pRow->isLeaf ? 1 : 0 /* f */ |
| 741 | 741 | ); |
| 742 | - /* u */ | |
| 742 | + /* au */ | |
| 743 | 743 | cSep = '['; |
| 744 | 744 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 745 | 745 | if( i==pRow->iRail ) continue; |
| 746 | 746 | if( pRow->aiRiser[i]>0 ){ |
| 747 | 747 | cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]); |
| @@ -757,11 +757,11 @@ | ||
| 757 | 757 | cgi_printf("mi:"); |
| 758 | 758 | cSep = '['; |
| 759 | 759 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 760 | 760 | if( pRow->mergeIn[i] ){ |
| 761 | 761 | int mi = i; |
| 762 | - if( pRow->mergeDown & (1<<i) ) mi = -mi; | |
| 762 | + if( (pRow->mergeDown >> i) & 1 ) mi = -mi; | |
| 763 | 763 | cgi_printf("%c%d", cSep, mi); |
| 764 | 764 | cSep = ','; |
| 765 | 765 | } |
| 766 | 766 | } |
| 767 | 767 | if( cSep=='[' ) cgi_printf("["); |
| @@ -1495,11 +1495,11 @@ | ||
| 1495 | 1495 | |
| 1496 | 1496 | if( zTagName && g.perm.Read ){ |
| 1497 | 1497 | style_submenu_element("Related", "Related", "%s", |
| 1498 | 1498 | url_render(&url, "r", zTagName, "t", 0)); |
| 1499 | 1499 | }else if( zBrName && g.perm.Read ){ |
| 1500 | - style_submenu_element("Branch Only", "only", "%s", | |
| 1500 | + style_submenu_element("Omit Related", "only", "%s", | |
| 1501 | 1501 | url_render(&url, "t", zBrName, "r", 0)); |
| 1502 | 1502 | } |
| 1503 | 1503 | if( zMark && zMark[0]==0 ){ |
| 1504 | 1504 | if( zAfter ) zMark = zAfter; |
| 1505 | 1505 | if( zBefore ) zMark = zBefore; |
| 1506 | 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 | /* 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 @@ | ||
| 737 | 737 | pRow->mergeOut, /* mo */ |
| 738 | 738 | pRow->mergeUpto, /* mu */ |
| 739 | 739 | pRow->aiRiser[pRow->iRail], /* u */ |
| 740 | 740 | pRow->isLeaf ? 1 : 0 /* f */ |
| 741 | 741 | ); |
| 742 | - /* u */ | |
| 742 | + /* au */ | |
| 743 | 743 | cSep = '['; |
| 744 | 744 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 745 | 745 | if( i==pRow->iRail ) continue; |
| 746 | 746 | if( pRow->aiRiser[i]>0 ){ |
| 747 | 747 | cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]); |
| @@ -757,11 +757,11 @@ | ||
| 757 | 757 | cgi_printf("mi:"); |
| 758 | 758 | cSep = '['; |
| 759 | 759 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 760 | 760 | if( pRow->mergeIn[i] ){ |
| 761 | 761 | int mi = i; |
| 762 | - if( pRow->mergeDown & (1<<i) ) mi = -mi; | |
| 762 | + if( (pRow->mergeDown >> i) & 1 ) mi = -mi; | |
| 763 | 763 | cgi_printf("%c%d", cSep, mi); |
| 764 | 764 | cSep = ','; |
| 765 | 765 | } |
| 766 | 766 | } |
| 767 | 767 | if( cSep=='[' ) cgi_printf("["); |
| @@ -1495,11 +1495,11 @@ | ||
| 1495 | 1495 | |
| 1496 | 1496 | if( zTagName && g.perm.Read ){ |
| 1497 | 1497 | style_submenu_element("Related", "Related", "%s", |
| 1498 | 1498 | url_render(&url, "r", zTagName, "t", 0)); |
| 1499 | 1499 | }else if( zBrName && g.perm.Read ){ |
| 1500 | - style_submenu_element("Branch Only", "only", "%s", | |
| 1500 | + style_submenu_element("Omit Related", "only", "%s", | |
| 1501 | 1501 | url_render(&url, "t", zBrName, "r", 0)); |
| 1502 | 1502 | } |
| 1503 | 1503 | if( zMark && zMark[0]==0 ){ |
| 1504 | 1504 | if( zAfter ) zMark = zAfter; |
| 1505 | 1505 | if( zBefore ) zMark = zBefore; |
| 1506 | 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 | /* 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 @@ | ||
| 216 | 216 | const char *zBaseName = zName[0]=='+' ? zName+1 : zName; |
| 217 | 217 | j = fieldId(zBaseName); |
| 218 | 218 | if( j<0 ) continue; |
| 219 | 219 | aUsed[j] = 1; |
| 220 | 220 | if( aField[j].mUsed & USEDBY_TICKET ){ |
| 221 | - if( zName[0]=='+' ){ | |
| 222 | - zName++; | |
| 221 | + const char *zUsedByName = zName; | |
| 222 | + if( zUsedByName[0]=='+' ){ | |
| 223 | + zUsedByName++; | |
| 223 | 224 | blob_append_sql(&sql1,", \"%w\"=coalesce(\"%w\",'') || %Q", |
| 224 | - zName, zName, p->aField[i].zValue); | |
| 225 | + zUsedByName, zUsedByName, p->aField[i].zValue); | |
| 225 | 226 | }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); | |
| 227 | 228 | } |
| 228 | 229 | } |
| 229 | 230 | 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); | |
| 231 | 236 | blob_append_sql(&sql3, ",%Q", p->aField[i].zValue); |
| 232 | 237 | } |
| 233 | 238 | if( rid>0 ){ |
| 234 | 239 | wiki_extract_links(p->aField[i].zValue, rid, 1, p->rDate, i==0, 0); |
| 235 | 240 | } |
| 236 | 241 |
| --- 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 |
+5
-1
| --- src/unversioned.c | ||
| +++ src/unversioned.c | ||
| @@ -452,18 +452,20 @@ | ||
| 452 | 452 | ** |
| 453 | 453 | ** Display a list of all unversioned files in the repository. |
| 454 | 454 | ** Query parameters: |
| 455 | 455 | ** |
| 456 | 456 | ** byage=1 Order the initial display be decreasing age |
| 457 | +** showdel=0 Show deleted files | |
| 457 | 458 | */ |
| 458 | 459 | void uvstat_page(void){ |
| 459 | 460 | Stmt q; |
| 460 | 461 | sqlite3_int64 iNow; |
| 461 | 462 | sqlite3_int64 iTotalSz = 0; |
| 462 | 463 | int cnt = 0; |
| 463 | 464 | int n = 0; |
| 464 | 465 | const char *zOrderBy = "name"; |
| 466 | + int showDel = 0; | |
| 465 | 467 | char zSzName[100]; |
| 466 | 468 | |
| 467 | 469 | login_check_credentials(); |
| 468 | 470 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 469 | 471 | style_header("Unversioned Files"); |
| @@ -471,20 +473,22 @@ | ||
| 471 | 473 | @ No unversioned files on this server |
| 472 | 474 | style_footer(); |
| 473 | 475 | return; |
| 474 | 476 | } |
| 475 | 477 | if( PB("byage") ) zOrderBy = "mtime DESC"; |
| 478 | + if( PB("showdel") ) showDel = 1; | |
| 476 | 479 | db_prepare(&q, |
| 477 | 480 | "SELECT" |
| 478 | 481 | " name," |
| 479 | 482 | " mtime," |
| 480 | 483 | " hash," |
| 481 | 484 | " sz," |
| 482 | 485 | " (SELECT login FROM rcvfrom, user" |
| 483 | 486 | " WHERE user.uid=rcvfrom.uid AND rcvfrom.rcvid=unversioned.rcvid)," |
| 484 | 487 | " rcvid" |
| 485 | - " FROM unversioned ORDER BY %s", | |
| 488 | + " FROM unversioned %s ORDER BY %s", | |
| 489 | + showDel ? "" : "WHERE hash IS NOT NULL" /*safe-for-%s*/, | |
| 486 | 490 | zOrderBy/*safe-for-%s*/ |
| 487 | 491 | ); |
| 488 | 492 | iNow = db_int64(0, "SELECT strftime('%%s','now');"); |
| 489 | 493 | while( db_step(&q)==SQLITE_ROW ){ |
| 490 | 494 | const char *zName = db_column_text(&q, 0); |
| 491 | 495 |
| --- 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 @@ | ||
| 19 | 19 | ** querying information about users. |
| 20 | 20 | */ |
| 21 | 21 | #include "config.h" |
| 22 | 22 | #include "user.h" |
| 23 | 23 | |
| 24 | -#if defined(_WIN32) | |
| 25 | -#include <conio.h> | |
| 26 | -#endif | |
| 27 | - | |
| 28 | 24 | /* |
| 29 | 25 | ** Strip leading and trailing space from a string and add the string |
| 30 | 26 | ** onto the end of a blob. |
| 31 | 27 | */ |
| 32 | 28 | static void strip_string(Blob *pBlob, char *z){ |
| @@ -43,53 +39,74 @@ | ||
| 43 | 39 | } |
| 44 | 40 | blob_append(pBlob, z, -1); |
| 45 | 41 | } |
| 46 | 42 | |
| 47 | 43 | #if defined(_WIN32) || defined(__BIONIC__) |
| 48 | -#ifdef __MINGW32__ | |
| 44 | +#ifdef _WIN32 | |
| 49 | 45 | #include <conio.h> |
| 50 | 46 | #endif |
| 47 | + | |
| 51 | 48 | /* |
| 52 | -** getpass for Windows and Android | |
| 49 | +** getpass() for Windows and Android. | |
| 53 | 50 | */ |
| 51 | +static char *zPwdBuffer = 0; | |
| 52 | +static size_t nPwdBuffer = 0; | |
| 53 | + | |
| 54 | 54 | static char *getpass(const char *prompt){ |
| 55 | - static char pwd[64]; | |
| 55 | + char *zPwd; | |
| 56 | + size_t nPwd; | |
| 56 | 57 | size_t i; |
| 57 | 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; | |
| 58 | 67 | fputs(prompt,stderr); |
| 59 | 68 | 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){ | |
| 61 | 72 | #if defined(_WIN32) |
| 62 | - pwd[i] = _getch(); | |
| 73 | + zPwd[i] = _getch(); | |
| 63 | 74 | #else |
| 64 | - pwd[i] = getc(stdin); | |
| 75 | + zPwd[i] = getc(stdin); | |
| 65 | 76 | #endif |
| 66 | - if(pwd[i]=='\r' || pwd[i]=='\n'){ | |
| 77 | + if(zPwd[i]=='\r' || zPwd[i]=='\n'){ | |
| 67 | 78 | break; |
| 68 | 79 | } |
| 69 | 80 | /* 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)){ | |
| 71 | 82 | i -= 2; |
| 72 | 83 | continue; |
| 73 | 84 | } |
| 74 | 85 | /* CTRL-C */ |
| 75 | - else if(pwd[i]==3) { | |
| 86 | + else if(zPwd[i]==3) { | |
| 76 | 87 | i=0; |
| 77 | 88 | break; |
| 78 | 89 | } |
| 79 | 90 | /* ESC */ |
| 80 | - else if(pwd[i]==27){ | |
| 91 | + else if(zPwd[i]==27){ | |
| 81 | 92 | i=0; |
| 82 | 93 | break; |
| 83 | 94 | } |
| 84 | 95 | else{ |
| 85 | 96 | fputc('*',stderr); |
| 86 | 97 | } |
| 87 | 98 | } |
| 88 | - pwd[i]='\0'; | |
| 99 | + zPwd[i]='\0'; | |
| 89 | 100 | 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); | |
| 91 | 108 | } |
| 92 | 109 | #endif |
| 93 | 110 | |
| 94 | 111 | #if defined(_WIN32) || defined(WIN32) |
| 95 | 112 | # include <io.h> |
| 96 | 113 |
| --- 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 @@ | ||
| 55 | 55 | } |
| 56 | 56 | void *fossil_realloc(void *p, size_t n){ |
| 57 | 57 | p = realloc(p, n); |
| 58 | 58 | if( p==0 ) fossil_panic("out of memory"); |
| 59 | 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 | |
| 60 | 117 | } |
| 61 | 118 | |
| 62 | 119 | /* |
| 63 | 120 | ** This function implements a cross-platform "system()" interface. |
| 64 | 121 | */ |
| 65 | 122 |
| --- 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 @@ | ||
| 306 | 306 | SOCKADDR_IN addr; |
| 307 | 307 | int idCnt = 0; |
| 308 | 308 | int iPort = mnPort; |
| 309 | 309 | Blob options; |
| 310 | 310 | wchar_t zTmpPath[MAX_PATH]; |
| 311 | +#if USE_SEE | |
| 312 | + const char *zSavedKey = 0; | |
| 313 | + size_t savedKeySize = 0; | |
| 314 | +#endif | |
| 311 | 315 | |
| 312 | 316 | blob_zero(&options); |
| 313 | 317 | if( zBaseUrl ){ |
| 314 | 318 | blob_appendf(&options, " --baseurl %s", zBaseUrl); |
| 315 | 319 | } |
| @@ -326,10 +330,18 @@ | ||
| 326 | 330 | blob_appendf(&options, " --th-trace"); |
| 327 | 331 | } |
| 328 | 332 | if( flags & HTTP_SERVER_REPOLIST ){ |
| 329 | 333 | blob_appendf(&options, " --repolist"); |
| 330 | 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 | |
| 331 | 343 | if( WSAStartup(MAKEWORD(1,1), &wd) ){ |
| 332 | 344 | fossil_fatal("unable to initialize winsock"); |
| 333 | 345 | } |
| 334 | 346 | while( iPort<=mxPort ){ |
| 335 | 347 | s = socket(AF_INET, SOCK_STREAM, 0); |
| @@ -654,11 +666,13 @@ | ||
| 654 | 666 | } |
| 655 | 667 | } |
| 656 | 668 | return 0; |
| 657 | 669 | } |
| 658 | 670 | |
| 659 | -/* dupe ifdef needed for mkindex | |
| 671 | +/* Duplicate #ifdef needed for mkindex */ | |
| 672 | +#ifdef _WIN32 | |
| 673 | +/* | |
| 660 | 674 | ** COMMAND: winsrv* |
| 661 | 675 | ** |
| 662 | 676 | ** Usage: %fossil winsrv METHOD ?SERVICE-NAME? ?OPTIONS? |
| 663 | 677 | ** |
| 664 | 678 | ** Where METHOD is one of: create delete show start stop. |
| @@ -1103,6 +1117,7 @@ | ||
| 1103 | 1117 | fossil_fatal("METHOD should be one of:" |
| 1104 | 1118 | " create delete show start stop"); |
| 1105 | 1119 | } |
| 1106 | 1120 | return; |
| 1107 | 1121 | } |
| 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 */ | |
| 1109 | 1124 |
| --- 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 @@ | ||
| 2140 | 2140 | } |
| 2141 | 2141 | if( syncFlags & (SYNC_UV_TRACE|SYNC_UV_DRYRUN) ){ |
| 2142 | 2142 | const char *zMsg = 0; |
| 2143 | 2143 | switch( iStatus ){ |
| 2144 | 2144 | case 0: |
| 2145 | - case 1: zMsg = "UV-PULL"; break; | |
| 2145 | + case 1: zMsg = "UV-PULL"; break; | |
| 2146 | 2146 | case 2: zMsg = "UV-PULL-MTIME-ONLY"; break; |
| 2147 | 2147 | case 4: zMsg = "UV-PUSH-MTIME-ONLY"; break; |
| 2148 | 2148 | case 5: zMsg = "UV-PUSH"; break; |
| 2149 | 2149 | } |
| 2150 | 2150 | if( zMsg ) fossil_print("\r%s: %s\n", zMsg, zName); |
| 2151 | 2151 | |
| 2152 | 2152 | 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 |
+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 |
| --- 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 @@ | ||
| 66 | 66 | * <a href="../../../timeline?c=20015206bc" |
| 67 | 67 | target="testwindow"> |
| 68 | 68 | This timeline has a hidden commit.</a> Click Unhide to reveal. |
| 69 | 69 | * <a href="../../../timeline?y=ci&n=15&b=2a4e4cf03e" |
| 70 | 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> | |
| 71 | 74 | |
| 72 | 75 | External: |
| 73 | 76 | |
| 74 | 77 | * <a href="http://www.sqlite.org/src/timeline?c=2010-09-29&nd" |
| 75 | 78 | target="testwindow">Timewarp due to a mis-configured system clock.</a> |
| 76 | 79 |
| --- 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 @@ | ||
| 1038 | 1038 | error expr for getParameter glob_match globalState hascap hasfeature\ |
| 1039 | 1039 | html htmlize http httpize if info insertCsrf lindex linecount list\ |
| 1040 | 1040 | llength lsearch markdown proc puts query randhex redirect regexp\ |
| 1041 | 1041 | reinitialize rename render repository return searchable set\ |
| 1042 | 1042 | setParameter setting stime string styleFooter styleHeader tclReady\ |
| 1043 | - trace unset uplevel upvar utime verifyCsrf wiki} | |
| 1043 | + trace unset unversioned uplevel upvar utime verifyCsrf wiki} | |
| 1044 | 1044 | set tcl_commands {tclEval tclExpr tclInvoke tclIsSafe tclMakeSafe} |
| 1045 | 1045 | if {$th1Tcl} { |
| 1046 | 1046 | test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands $tcl_commands"]} |
| 1047 | 1047 | } else { |
| 1048 | 1048 | test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands"]} |
| @@ -1562,9 +1562,45 @@ | ||
| 1562 | 1562 | } |
| 1563 | 1563 | |
| 1564 | 1564 | fossil test-th-source $th1FileName |
| 1565 | 1565 | test th1-source-1 {$RESULT eq {TH_RETURN: 0 1 2 3 4 5 6 7 8 9}} |
| 1566 | 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}} | |
| 1567 | 1603 | |
| 1568 | 1604 | ############################################################################### |
| 1569 | 1605 | |
| 1570 | 1606 | test_cleanup |
| 1571 | 1607 |
| --- 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 @@ | ||
| 66 | 66 | <p> |
| 67 | 67 | In addition to setting various CGI environment variables, if the HTTP |
| 68 | 68 | request contains POST content, then the web server relays the POST content |
| 69 | 69 | to standard input of the CGI script. |
| 70 | 70 | <p> |
| 71 | -In summary, the task of the | |
| 71 | +In summary, the task of the | |
| 72 | 72 | CGI script is to read the various CGI environment variables and |
| 73 | 73 | the POST content on standard input (if any), figure out an appropriate |
| 74 | 74 | reply, then write that reply on standard output. |
| 75 | 75 | The web server will read the output from the CGI script, reformat it |
| 76 | 76 | into an appropriate HTTP reply, and relay the result back to the |
| @@ -89,31 +89,31 @@ | ||
| 89 | 89 | like the following: |
| 90 | 90 | <blockquote><pre> |
| 91 | 91 | #!/usr/bin/fossil |
| 92 | 92 | repository: /home/www/repos/project.fossil |
| 93 | 93 | </pre></blockquote> |
| 94 | -The first line of the script is a | |
| 94 | +The first line of the script is a | |
| 95 | 95 | "[https://en.wikipedia.org/wiki/Shebang_%28Unix%29|shebang]" |
| 96 | 96 | that tells the operating system what program to use as the interpreter |
| 97 | 97 | for this script. On unix, when you execute a script that starts with |
| 98 | 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 | |
| 99 | +shebang with a single argument that is the full pathname of the script | |
| 100 | 100 | itself. |
| 101 | 101 | In our example, the interpreter is Fossil, and the argument might |
| 102 | 102 | be something like "/var/www/cgi-bin/one/two" (depending on how your |
| 103 | 103 | particular web server is configured). |
| 104 | 104 | <p> |
| 105 | 105 | The Fossil program that is run as the script interpreter |
| 106 | 106 | is the same Fossil that runs when |
| 107 | 107 | you type ordinary Fossil commands like "fossil sync" or "fossil commit". |
| 108 | 108 | 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 | |
| 110 | 110 | set to "CGI/1.0" and it therefore knows that it is being used as |
| 111 | 111 | CGI rather than as an ordinary command-line tool, and behaves accordingly. |
| 112 | 112 | <p> |
| 113 | 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 | |
| 114 | +the file identified by its sole argument (the file named by | |
| 115 | 115 | <code>argv[1]</code>). In our example, the second line of that file |
| 116 | 116 | tells Fossil the location of the repository it will be serving. |
| 117 | 117 | Fossil then starts looking at the CGI environment variables to figure |
| 118 | 118 | out what web page is being requested, generates that one web page, |
| 119 | 119 | then exits. |
| @@ -130,11 +130,11 @@ | ||
| 130 | 130 | <ol type='A'> |
| 131 | 131 | <li> [https://www.fossil-scm.org/fossil/info/c14ecc43] |
| 132 | 132 | <li> [https://www.fossil-scm.org/fossil/info?name=c14ecc43] |
| 133 | 133 | </ol> |
| 134 | 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 | |
| 135 | +the PATH_INFO variable will be "info/c14ecc43" and so the | |
| 136 | 136 | "[/help?cmd=/info|/info]" webpage will be generated and the suffix of |
| 137 | 137 | PATH_INFO will be converted into the "name" query parameter, which |
| 138 | 138 | identifies the artifact about which information is requested. |
| 139 | 139 | In case (B), the PATH_INFO is just "info", but the same "name" |
| 140 | 140 | query parameter is set explicitly by the URL itself. |
| @@ -164,11 +164,11 @@ | ||
| 164 | 164 | <blockquote> |
| 165 | 165 | <b>http://example.com/cgis/example2/subdir/three/timeline</b> |
| 166 | 166 | </blockquote> |
| 167 | 167 | Here is what happens: |
| 168 | 168 | <ol> |
| 169 | -<li> The input URI on the HTTP request is | |
| 169 | +<li> The input URI on the HTTP request is | |
| 170 | 170 | <b>/cgis/example2/subdir/three/timeline</b> |
| 171 | 171 | <li> The web server searches prefixes of the input URI until it finds |
| 172 | 172 | the "cgis/example2" script. The web server then sets |
| 173 | 173 | PATH_INFO to the "subdir/three/timeline" suffix and invokes the |
| 174 | 174 | "cgis/example2" script. |
| @@ -175,11 +175,11 @@ | ||
| 175 | 175 | <li> Fossil runs and sees the "directory:" line pointing to |
| 176 | 176 | "/home/www/repos". Fossil then starts pulling terms off the |
| 177 | 177 | front of the PATH_INFO looking for a repository. It first looks |
| 178 | 178 | at "/home/www/resps/subdir.fossil" but there is no such repository. |
| 179 | 179 | 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 | |
| 181 | 181 | "subdir/three/" leaving it at just "timeline". |
| 182 | 182 | <li> Fossil looks at the rest of PATH_INFO to see that the webpage |
| 183 | 183 | requested is "timeline". |
| 184 | 184 | </ol> |
| 185 | 185 | </blockquote> |
| @@ -201,14 +201,14 @@ | ||
| 201 | 201 | and has a value. |
| 202 | 202 | <li><p> |
| 203 | 203 | The "[/help?cmd=ui|fossil ui]" and "[/help?cmd=server|fossil server]" commands |
| 204 | 204 | are implemented using a simple built-in web server that accepts incoming HTTP |
| 205 | 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 | |
| 206 | +separate child Fossil process to handle each request. In other words, CGI | |
| 207 | 207 | is used internally to implement "fossil ui/server". |
| 208 | 208 | <p> |
| 209 | 209 | SCGI is processed using the same built-in web server, just modified |
| 210 | 210 | 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 | |
| 212 | 212 | process to handle each CGI request. |
| 213 | 213 | </ol> |
| 214 | 214 | </blockquote> |
| 215 | 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[1]</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[1]</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 |
+5
-5
| --- www/adding_code.wiki | ||
| +++ www/adding_code.wiki | ||
| @@ -22,11 +22,11 @@ | ||
| 22 | 22 | |
| 23 | 23 | 2. The <b>makeheaders</b> preprocessor generates all the ".h" files |
| 24 | 24 | automatically. Fossil programmers write ".c" files only and let the |
| 25 | 25 | makeheaders preprocessor create the ".h" files. |
| 26 | 26 | |
| 27 | - 3. The <b>translate</b> preprocessor converts source code lines that | |
| 27 | + 3. The <b>translate</b> preprocessor converts source code lines that | |
| 28 | 28 | begin with "@" into string literals, or into print statements that |
| 29 | 29 | generate web page output, depending on context. |
| 30 | 30 | |
| 31 | 31 | The [./makefile.wiki|Makefile] for Fossil takes care of running these |
| 32 | 32 | preprocessors with all the right arguments and in the right order. So it is |
| @@ -39,13 +39,13 @@ | ||
| 39 | 39 | <h2>3.0 Adding New Source Code Files</h2> |
| 40 | 40 | |
| 41 | 41 | New source code files are added in the "src/" subdirectory of the Fossil |
| 42 | 42 | source tree. Suppose one wants to add a new source code file named |
| 43 | 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 | |
| 44 | +Do so by editing the file src/makemake.tcl and adding "xyzzy" (without | |
| 45 | 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 | |
| 46 | +Save the result and then run the makemake.tcl script using a TCL | |
| 47 | 47 | interpreter. The command to run the makemake.tcl script is: |
| 48 | 48 | |
| 49 | 49 | <b>tclsh makemake.tcl</b> |
| 50 | 50 | |
| 51 | 51 | The working directory must be src/ when the command above is run. |
| @@ -60,11 +60,11 @@ | ||
| 60 | 60 | |
| 61 | 61 | <blockquote><verbatim> |
| 62 | 62 | /* |
| 63 | 63 | ** Copyright boilerplate goes here. |
| 64 | 64 | ***************************************************** |
| 65 | -** High-level description of what this module goes | |
| 65 | +** High-level description of what this module goes | |
| 66 | 66 | ** here. |
| 67 | 67 | */ |
| 68 | 68 | #include "config.h" |
| 69 | 69 | #include "xyzzy.h" |
| 70 | 70 | |
| @@ -83,11 +83,11 @@ | ||
| 83 | 83 | exceptions to this rule. Don't worry about those exceptions. The |
| 84 | 84 | files you write will require this #include line.) |
| 85 | 85 | |
| 86 | 86 | The "#if INTERFACE ... #endif" section is optional and is only needed |
| 87 | 87 | 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 | |
| 89 | 89 | uses definitions in the INTERFACE section to help it generate header |
| 90 | 90 | files. See [../src/makeheaders.html | makeheaders.html] for additional |
| 91 | 91 | information. |
| 92 | 92 | |
| 93 | 93 | After creating a template file such as shown above, and after updating |
| 94 | 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 |
| --- 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 @@ | ||
| 1 | 1 | <title>Defense Against Spiders</title> |
| 2 | 2 | |
| 3 | 3 | The website presented by a Fossil server has many hyperlinks. |
| 4 | 4 | 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 | |
| 6 | 6 | and ZIP archive of older check-ins) can be expensive to compute. |
| 7 | 7 | If a spider or bot tries to walk a website implemented by |
| 8 | 8 | Fossil, it can present a crippling bandwidth and CPU load. |
| 9 | 9 | |
| 10 | 10 | 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 | |
| 12 | 12 | describes the techniques used by Fossil to try to welcome human |
| 13 | 13 | users while keeping out spiders. |
| 14 | 14 | |
| 15 | 15 | <h2>The "hyperlink" user capability</h2> |
| 16 | 16 | |
| 17 | 17 | Every Fossil web session has a "user". For random passers-by on the internet |
| 18 | 18 | (and for spiders) that user is "nobody". The "anonymous" user is also |
| 19 | 19 | available for humans who do not wish to identify themselves. The difference |
| 20 | 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 | |
| 21 | +a CAPTCHA) whereas "nobody" does not require a login. | |
| 22 | +The site administrator can also create logins with | |
| 23 | 23 | passwords for specific individuals. |
| 24 | 24 | |
| 25 | 25 | The "h" or "hyperlink" capability is a permission that can be granted |
| 26 | 26 | to users that enables the display of hyperlinks. Most of the hyperlinks |
| 27 | 27 | generated by Fossil are suppressed if this capability is missing. So |
| @@ -37,11 +37,11 @@ | ||
| 37 | 37 | page inviting the user to log in as anonymous in order to activate hyperlinks. |
| 38 | 38 | |
| 39 | 39 | Removing the "h" capability from user "nobody" is an effective means |
| 40 | 40 | of preventing spiders from walking a Fossil-generated website. But |
| 41 | 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 | |
| 42 | +Hence, Fossil provides other techniques for blocking spiders which | |
| 43 | 43 | are less cumbersome to humans. |
| 44 | 44 | |
| 45 | 45 | <h2>Automatic hyperlinks based on UserAgent</h2> |
| 46 | 46 | |
| 47 | 47 | Fossil has the ability to selectively enable hyperlinks for users |
| @@ -94,25 +94,25 @@ | ||
| 94 | 94 | web browsers implement javascript, so hyperlinks will appears |
| 95 | 95 | normally for human users. |
| 96 | 96 | |
| 97 | 97 | <h2>Further defenses</h2> |
| 98 | 98 | |
| 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 | |
| 100 | 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 | |
| 101 | +by Chinese spiders that use forged UserAgent strings to make them look | |
| 102 | 102 | like normal web browsers and which interpret javascript. We do not |
| 103 | 103 | believe these attacks to be nefarious since SQLite is public domain |
| 104 | 104 | 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 | |
| 106 | 106 | believe these "attacks" are coming from "script kiddies". But regardless |
| 107 | 107 | of whether or not malice is involved, these attacks do present |
| 108 | 108 | an unnecessary load on the server which reduces the responsiveness of |
| 109 | 109 | the SQLite website for well-behaved and socially responsible users. |
| 110 | 110 | For this reason, additional defenses against |
| 111 | 111 | spiders have been put in place. |
| 112 | 112 | |
| 113 | -On the Admin/Access page of Fossil, just below the | |
| 113 | +On the Admin/Access page of Fossil, just below the | |
| 114 | 114 | "<b>Enable hyperlinks for "nobody" based on User-Agent and Javascript</b>" |
| 115 | 115 | setting, there are now two additional subsettings that can be optionally |
| 116 | 116 | enabled to control hyperlinks. |
| 117 | 117 | |
| 118 | 118 | The first subsetting waits to run the |
| @@ -137,11 +137,11 @@ | ||
| 137 | 137 | Fossil currently does a very good job of providing easy access to humans |
| 138 | 138 | while keeping out troublesome robots and spiders. However, spiders and |
| 139 | 139 | bots continue to grow more sophisticated, requiring ever more advanced |
| 140 | 140 | defenses. This "arms race" is unlikely to ever end. The developers of |
| 141 | 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. | |
| 142 | +check back from time to time for the latest releases and updates. | |
| 143 | 143 | |
| 144 | 144 | Readers of this page who have suggestions on how to improve the spider |
| 145 | 145 | defenses in Fossil are invited to submit your ideas to the Fossil Users |
| 146 | -mailing list: | |
| 146 | +mailing list: | |
| 147 | 147 | [mailto:[email protected] | [email protected]]. |
| 148 | 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 |
| --- 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 @@ | ||
| 18 | 18 | <li>Locate the check-in that contains the file that is to be |
| 19 | 19 | annotated. Call this check-in C0. |
| 20 | 20 | <li>Find all direct ancestors of C0. A direct ancestor is the closure |
| 21 | 21 | of the primary parent of C0. Merged in branches are not part of |
| 22 | 22 | 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 | |
| 24 | 24 | check-in in which the file to be annotated was modified. |
| 25 | 25 | <li>Load the complete text of the file to be annotated from check-in C0. |
| 26 | 26 | Call this version of the file F0. |
| 27 | 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), | |
| 28 | +<li>For each ancestor of C0 on the pruned list (call the ancestor CX), | |
| 29 | 29 | beginning with the most |
| 30 | 30 | recent ancestor and moving toward the oldest ancestor, do the |
| 31 | 31 | following steps: |
| 32 | 32 | <ol type='a'> |
| 33 | 33 | <li>Load the text for the file to be annotated as it existed in check-in CX. |
| @@ -44,19 +44,19 @@ | ||
| 44 | 44 | <h2>3.0 Discussion and Notes</h2> |
| 45 | 45 | |
| 46 | 46 | The time-consuming part of this algorithm is step 6b - computing the |
| 47 | 47 | diff from all historical versions of the file to the version of the file |
| 48 | 48 | 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 | |
| 50 | 50 | [/help?cmd=/annotate|/annotate] webpage only shows those lines that where |
| 51 | 51 | changed by the 20 most recent modifications to the file. This allows |
| 52 | 52 | the loop on step 6 to terminate after only 19 diffs instead of the hundreds |
| 53 | 53 | or thousands of diffs that might be required for a frequently modified file. |
| 54 | 54 | |
| 55 | 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 | |
| 56 | +follow files across name changes. File name change information is | |
| 57 | 57 | available in the database, and so the algorithm could be enhanced to follow |
| 58 | 58 | files across name changes by modifications to step 3. |
| 59 | 59 | |
| 60 | 60 | Step 2 is interesting in that it is |
| 61 | 61 | [/artifact/6cb824a0417?ln=196-201 | implemented] using a |
| 62 | 62 | [https://www.sqlite.org/lang_with.html#recursivecte|recursive common table expression]. |
| 63 | 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/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 |
+1
-1
| --- www/bugtheory.wiki | ||
| +++ www/bugtheory.wiki | ||
| @@ -27,11 +27,11 @@ | ||
| 27 | 27 | Recall that a fossil repository consists of an |
| 28 | 28 | unordered collection of <i>artifacts</i>. (See the |
| 29 | 29 | <a href="fileformat.wiki">file format document</a> for details.) |
| 30 | 30 | Some artifacts have a special format, and among those are |
| 31 | 31 | <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 | |
| 33 | 33 | ticket. A ticket is created by a ticket change artifact. |
| 34 | 34 | Each subsequent modification of the ticket is a separate artifact. |
| 35 | 35 | |
| 36 | 36 | The "push", "pull", and "sync" algorithms share ticket change artifacts |
| 37 | 37 | between repositories in the same way as every other artifact. In fact, |
| 38 | 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 |
| --- 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 @@ | ||
| 4 | 4 | <h2>Changes for Version 1.37 (2017-XX-YY)</h2> |
| 5 | 5 | |
| 6 | 6 | * Added support for the ms=EXACT|LIKE|GLOB|REGEXP query parameter on the |
| 7 | 7 | [/help?cmd=/timeline|/timeline] webpage. |
| 8 | 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> | |
| 9 | 22 | |
| 10 | 23 | <a name='v1_36'></a> |
| 11 | 24 | <h2>Changes for Version 1.36 (2016-10-24)</h2> |
| 12 | 25 | |
| 13 | 26 | * Add support for [./unvers.wiki|unversioned content], |
| @@ -16,16 +29,16 @@ | ||
| 16 | 29 | * The [/uv/download.html|download page] is moved into |
| 17 | 30 | [./unvers.wiki|unversioned content] so that the self-hosting Fossil |
| 18 | 31 | websites no longer uses any external content. |
| 19 | 32 | * Added the "Search" button to the graphical diff generated by |
| 20 | 33 | 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 | |
| 22 | 35 | [/help?cmd=diff|diff] command. |
| 23 | 36 | * Various performance enhancements to the [/help?cmd=diff|diff] command. |
| 24 | 37 | * Update internal Unicode character tables, used in regular expression |
| 25 | 38 | 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 | |
| 27 | 40 | the SQLITE_DBCONFIG_MAINDBNAME interface of SQLite which is only available |
| 28 | 41 | in SQLite version 3.15 and later and so Fossil will not work with |
| 29 | 42 | earlier SQLite versions. |
| 30 | 43 | * Fix [https://www.mail-archive.com/[email protected]/msg23618.html|multi-line timeline bug] |
| 31 | 44 | * Enhance the [/help?cmd=purge|fossil purge] command. |
| 32 | 45 |
| --- 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 @@ | ||
| 4 | 4 | <h2>Changes for Version 1.37 (2017-XX-YY)</h2> |
| 5 | 5 | |
| 6 | 6 | * Added support for the ms=EXACT|LIKE|GLOB|REGEXP query parameter on the |
| 7 | 7 | [/help?cmd=/timeline|/timeline] webpage. |
| 8 | 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> | |
| 9 | 22 | |
| 10 | 23 | <a name='v1_36'></a> |
| 11 | 24 | <h2>Changes for Version 1.36 (2016-10-24)</h2> |
| 12 | 25 | |
| 13 | 26 | * Add support for [./unvers.wiki|unversioned content], |
| @@ -16,16 +29,16 @@ | ||
| 16 | 29 | * The [/uv/download.html|download page] is moved into |
| 17 | 30 | [./unvers.wiki|unversioned content] so that the self-hosting Fossil |
| 18 | 31 | websites no longer uses any external content. |
| 19 | 32 | * Added the "Search" button to the graphical diff generated by |
| 20 | 33 | 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 | |
| 22 | 35 | [/help?cmd=diff|diff] command. |
| 23 | 36 | * Various performance enhancements to the [/help?cmd=diff|diff] command. |
| 24 | 37 | * Update internal Unicode character tables, used in regular expression |
| 25 | 38 | 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 | |
| 27 | 40 | the SQLITE_DBCONFIG_MAINDBNAME interface of SQLite which is only available |
| 28 | 41 | in SQLite version 3.15 and later and so Fossil will not work with |
| 29 | 42 | earlier SQLite versions. |
| 30 | 43 | * Fix [https://www.mail-archive.com/[email protected]/msg23618.html|multi-line timeline bug] |
| 31 | 44 | * Enhance the [/help?cmd=purge|fossil purge] command. |
| 32 | 45 |
| --- 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 |
+8
-8
| --- www/checkin_names.wiki | ||
| +++ www/checkin_names.wiki | ||
| @@ -55,20 +55,20 @@ | ||
| 55 | 55 | </pre></blockquote> |
| 56 | 56 | |
| 57 | 57 | The full 40-character SHA1 hash is unwieldy to remember and type, though, |
| 58 | 58 | so Fossil also accepts a unique prefix of the hash, using any combination |
| 59 | 59 | 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 | |
| 61 | 61 | accomplish the same thing as the above: |
| 62 | 62 | |
| 63 | 63 | <blockquote><pre> |
| 64 | 64 | fossil info e5a734a19a9 |
| 65 | 65 | fossil info E5a734A |
| 66 | 66 | fossil info e5a7 |
| 67 | 67 | </blockquote> |
| 68 | 68 | |
| 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 | |
| 70 | 70 | prefix of canonical name. |
| 71 | 71 | |
| 72 | 72 | <h2>Tags And Branch Names</h2> |
| 73 | 73 | |
| 74 | 74 | Using a tag or branch name where a check-in name is expected causes |
| @@ -112,11 +112,11 @@ | ||
| 112 | 112 | |
| 113 | 113 | <blockquote><tt> |
| 114 | 114 | fossil info tag:deed2 |
| 115 | 115 | </tt></blockquote> |
| 116 | 116 | |
| 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 | |
| 118 | 118 | tagged with "deed2" not to the |
| 119 | 119 | check-in whose canonical name begins with "deed2". |
| 120 | 120 | |
| 121 | 121 | <h2>Whole Branches</h2> |
| 122 | 122 | |
| @@ -147,11 +147,11 @@ | ||
| 147 | 147 | * <i>YYYY-MM-DD</i> |
| 148 | 148 | * <i>YYYY-MM-DD HH:MM</i> |
| 149 | 149 | * <i>YYYY-MM-DD HH:MM:SS</i> |
| 150 | 150 | * <i>YYYY-MM-DD HH:MM:SS.SSS</i> |
| 151 | 151 | |
| 152 | -The space between the day and the year can optionally be | |
| 152 | +The space between the day and the year can optionally be | |
| 153 | 153 | replaced by an uppercase <b>T</b> and the entire timestamp can |
| 154 | 154 | optionally be followed by "<b>z</b>" or "<b>Z</b>". In the fourth |
| 155 | 155 | form with fractional seconds, any number of digits may follow the |
| 156 | 156 | decimal point, though due to precision limits only the first three |
| 157 | 157 | digits will be significant. |
| @@ -161,14 +161,14 @@ | ||
| 161 | 161 | distributed projects where participants are scattered around the globe. |
| 162 | 162 | But there is an option on the Admin/Timeline page of the web-interface to |
| 163 | 163 | switch to local time. The "<b>Z</b>" suffix on a timestamp check-in |
| 164 | 164 | name is meaningless if Fossil is in the default mode of using UTC for |
| 165 | 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 | |
| 166 | +"<b>Z</b>" suffix means to interpret that particular timestamp using | |
| 167 | 167 | UTC instead of local time. |
| 168 | 168 | |
| 169 | -For an example of how timestamps are useful, | |
| 169 | +For an example of how timestamps are useful, | |
| 170 | 170 | consider the homepage for the Fossil website itself: |
| 171 | 171 | |
| 172 | 172 | <blockquote> |
| 173 | 173 | http://www.fossil-scm.org/fossil/doc/<b>trunk</b>/www/index.wiki |
| 174 | 174 | </blockquote> |
| @@ -191,11 +191,11 @@ | ||
| 191 | 191 | <blockquote> |
| 192 | 192 | fossil update trunk:2010-07-01T14:30 |
| 193 | 193 | </blockquote> |
| 194 | 194 | |
| 195 | 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 | |
| 196 | +check-in on the trunk that is not more recent that 14:30 (UTC) on | |
| 197 | 197 | July 1, 2010. |
| 198 | 198 | |
| 199 | 199 | <h2>Root Of A Branch</h2> |
| 200 | 200 | |
| 201 | 201 | A branch name that begins with the "<tt>root:</tt>" prefix refers to the |
| @@ -220,11 +220,11 @@ | ||
| 220 | 220 | current check-out. And the "previous" or "prev" tag means the primary |
| 221 | 221 | (non-merge) parent of the current check-out. |
| 222 | 222 | |
| 223 | 223 | For embedded documentation, the tag "ckout" means the version as present in |
| 224 | 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 | |
| 225 | +"fossil ui" or "fossil server" from within the source tree. This tag can be | |
| 226 | 226 | used to preview local changes to documentation before committing them. It does |
| 227 | 227 | not apply to CLI commands. |
| 228 | 228 | |
| 229 | 229 | <h2>Additional Examples</h2> |
| 230 | 230 | |
| 231 | 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/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 |
+3
-3
| --- www/childprojects.wiki | ||
| +++ www/childprojects.wiki | ||
| @@ -37,21 +37,21 @@ | ||
| 37 | 37 | VALUES('project-code',lower(hex(randomblob(20)))); |
| 38 | 38 | INSERT INTO config(name,value) |
| 39 | 39 | VALUES('project-name','CHILD-PROJECT-NAME'); |
| 40 | 40 | </verbatim></blockquote> |
| 41 | 41 | |
| 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 | |
| 43 | 43 | the child project, of course. |
| 44 | 44 | |
| 45 | 45 | The repository is now a separate project, independent from its parent. |
| 46 | 46 | Clone the new project to the developers as needed. |
| 47 | 47 | |
| 48 | 48 | The child project and the parent project will not normally be able to sync |
| 49 | 49 | with one another, since they are now separate projects with distinct |
| 50 | 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 | |
| 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 | 53 | parent repository is also provided on the command-line, then updates to |
| 54 | 54 | the parent project that occurred after the child was created will be added |
| 55 | 55 | to the child repository. Thus, by periodically doing a |
| 56 | 56 | pull --from-parent-project, the child project is able to stay up to date |
| 57 | 57 | with all the latest changes in the parent. |
| 58 | 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/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 |
+8
-8
| --- www/concepts.wiki | ||
| +++ www/concepts.wiki | ||
| @@ -131,11 +131,11 @@ | ||
| 131 | 131 | <h3>2.2 Manifests</h3> |
| 132 | 132 | |
| 133 | 133 | Associated with every check-in is a special file called the |
| 134 | 134 | [./fileformat.wiki#manifest| "manifest"]. The manifest is a |
| 135 | 135 | 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 | |
| 137 | 137 | of the file and the name of the file as it appears on disk, |
| 138 | 138 | and thus serves as a mapping from artifact ID to disk name. The artifact ID |
| 139 | 139 | of the manifest is the identifier for the entire check-in. When |
| 140 | 140 | you look at a "timeline" of changes in Fossil, the ID associated |
| 141 | 141 | with each check-in or commit is really just the artifact ID of the |
| @@ -147,11 +147,11 @@ | ||
| 147 | 147 | manifest file to be materialized to disk, if desired. Both Fossil |
| 148 | 148 | itself, and SQLite cause the manifest file to be materialized to disk |
| 149 | 149 | so that the makefiles for these project can read the manifest and |
| 150 | 150 | embed version information in generated binaries. |
| 151 | 151 | |
| 152 | -<p>Fossil automatically generates a manifest whenever you "commit" | |
| 152 | +<p>Fossil automatically generates a manifest whenever you "commit" | |
| 153 | 153 | a new check-in. So this is not something that you, the developer, |
| 154 | 154 | need to worry with. The format of a manifest is intentionally |
| 155 | 155 | designed to be simple to parse, so that if |
| 156 | 156 | you want to read and interpret a manifest, either by hand or |
| 157 | 157 | with a script, that is easy to do. But you will probably never |
| @@ -200,11 +200,11 @@ | ||
| 200 | 200 | Fossil effectively. You will want to have some kind of text editor |
| 201 | 201 | for entering check-in comments. Fossil will use whatever text editor |
| 202 | 202 | is identified by your VISUAL environment variable. Fossil will also |
| 203 | 203 | use GPG to clearsign your manifests if you happen to have it installed, |
| 204 | 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, | |
| 205 | +You can optionally set up Fossil to use external "diff" programs, | |
| 206 | 206 | though Fossil has an excellent built-in "diff" algorithm that works |
| 207 | 207 | fine for most people. If you happen to have Tcl/Tk installed on your |
| 208 | 208 | system, Fossil will use it to generate a graphical "diff" display when |
| 209 | 209 | you use the --tk option to the "diff" command, but this too is entirely |
| 210 | 210 | optional. |
| @@ -211,11 +211,11 @@ | ||
| 211 | 211 | |
| 212 | 212 | |
| 213 | 213 | To uninstall Fossil, simply delete the executable. |
| 214 | 214 | |
| 215 | 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 | |
| 216 | +replace the old executable with the new one. You might need to | |
| 217 | 217 | run "<b>fossil all rebuild</b>" to restructure your repositories after |
| 218 | 218 | an upgrade. Running "all rebuild" never hurts, so when upgrading it |
| 219 | 219 | is a good policy to run it even if it is not strictly necessary. |
| 220 | 220 | |
| 221 | 221 | To use Fossil, simply type the name of the executable in your |
| @@ -266,11 +266,11 @@ | ||
| 266 | 266 | |
| 267 | 267 | <ol> |
| 268 | 268 | <li> |
| 269 | 269 | Establish a local repository using either the <b>new</b> command |
| 270 | 270 | 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. | |
| 272 | 272 | </li> |
| 273 | 273 | |
| 274 | 274 | <li> |
| 275 | 275 | Establish one or more source trees using |
| 276 | 276 | the <b>open</b> command with the name of the repository file as its |
| @@ -279,11 +279,11 @@ | ||
| 279 | 279 | |
| 280 | 280 | <li> |
| 281 | 281 | The <b>open</b> command in the previous step populates your local source |
| 282 | 282 | tree with a copy of the latest check-in. Usually this is what you want. |
| 283 | 283 | 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. | |
| 285 | 285 | Use the <b>timeline</b> or <b>leaves</b> commands |
| 286 | 286 | to identify alternative check-ins to switch to. |
| 287 | 287 | </li> |
| 288 | 288 | |
| 289 | 289 | <li> |
| @@ -302,17 +302,17 @@ | ||
| 302 | 302 | you cloned from or whatever server you most recently synced with. |
| 303 | 303 | </li> |
| 304 | 304 | |
| 305 | 305 | <li> |
| 306 | 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. | |
| 307 | +into your local local source tree using the <b>update</b> command. | |
| 308 | 308 | In autosync mode, <b>update</b> will first go back to the server you |
| 309 | 309 | cloned from or with which you most recently synced, and pull down all |
| 310 | 310 | recent changes into your local repository. Then it will merge recent |
| 311 | 311 | changes into your local source tree. If you do an <b>update</b> and |
| 312 | 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 | |
| 313 | +checked in incompatible changes) you can use the <b>undo</b> command | |
| 314 | 314 | to back out the changes. |
| 315 | 315 | </li> |
| 316 | 316 | |
| 317 | 317 | <li> |
| 318 | 318 | Repeat all of the above until you have generated great software. |
| 319 | 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/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 |
+7
-7
| --- www/contribute.wiki | ||
| +++ www/contribute.wiki | ||
| @@ -10,11 +10,11 @@ | ||
| 10 | 10 | [./copyright-release.pdf | Contributor Agreement (PDF)] |
| 11 | 11 | (or [./copyright-release.html | as HTML]) on file for you. We require |
| 12 | 12 | this in order to maintain clear title to the Fossil code and prevent |
| 13 | 13 | the introduction of code with incompatible licenses or other entanglements |
| 14 | 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 | |
| 15 | +and other lawyer-rich organizations require this as a precondition to using | |
| 16 | 16 | Fossil. |
| 17 | 17 | |
| 18 | 18 | If you do not wish to submit a Contributor Agreement, we would still |
| 19 | 19 | welcome your suggestions and example code, but we will not use your code |
| 20 | 20 | directly - we will be forced to re-implement your changes from scratch which |
| @@ -21,14 +21,14 @@ | ||
| 21 | 21 | might take longer. |
| 22 | 22 | |
| 23 | 23 | <h2>2.0 Submitting Patches</h2> |
| 24 | 24 | |
| 25 | 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 | |
| 26 | +against the current source tree. Email patches to | |
| 27 | +<a href="mailto:[email protected]">[email protected]</a>. Be sure to | |
| 28 | 28 | describe in detail what the patch does and which version of Fossil |
| 29 | -it is written against. | |
| 29 | +it is written against. | |
| 30 | 30 | |
| 31 | 31 | A contributor agreement is not strictly necessary to submit a patch. |
| 32 | 32 | However, without a contributor agreement on file, your patch will be |
| 33 | 33 | used for reference only - it will not be applied to the code. This |
| 34 | 34 | may delay acceptance of your patch. |
| @@ -53,23 +53,23 @@ | ||
| 53 | 53 | Fossil Architect (Richard Hipp) will merge changes onto the trunk.</p> |
| 54 | 54 | |
| 55 | 55 | Contributors are required to following the |
| 56 | 56 | [./checkin.wiki | pre-checkin checklist] prior to every check-in to |
| 57 | 57 | 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 | |
| 59 | 59 | should print out a copy of the pre-checkin checklist and keep |
| 60 | 60 | it on a notecard beside their workstations, for quick reference. |
| 61 | 61 | |
| 62 | 62 | Contributors should review the |
| 63 | 63 | [./style.wiki | Coding Style Guidelines] and mimic the coding style |
| 64 | 64 | used through the rest of the Fossil source code. Your code should |
| 65 | 65 | 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. | |
| 67 | 67 | |
| 68 | 68 | <h2>4.0 Testing</h2> |
| 69 | 69 | |
| 70 | -Fossil has the beginnings of a | |
| 70 | +Fossil has the beginnings of a | |
| 71 | 71 | [../test/release-checklist.wiki | release checklist] but this is an |
| 72 | 72 | area that needs further work. (Your contributions here are welcomed!) |
| 73 | 73 | Contributors with check-in privileges are expected to run the release |
| 74 | 74 | checklist on any major changes they contribute, and if appropriate expand |
| 75 | 75 | the checklist and/or the automated test scripts to cover their additions. |
| 76 | 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/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 |
+2
-2
| --- www/custom_ticket.wiki | ||
| +++ www/custom_ticket.wiki | ||
| @@ -65,11 +65,11 @@ | ||
| 65 | 65 | </tr> |
| 66 | 66 | <th1>enable_output 1</th1> |
| 67 | 67 | </pre> |
| 68 | 68 | This bit of code will get rid of the "email" field entry for logged-in users. |
| 69 | 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. | |
| 70 | +might be good to automatically scoop up the user's email and put it here. | |
| 71 | 71 | </p> |
| 72 | 72 | </blockquote> |
| 73 | 73 | |
| 74 | 74 | <h2>Modify the 'view ticket' page</h2><blockquote> |
| 75 | 75 | <p> |
| @@ -83,11 +83,11 @@ | ||
| 83 | 83 | <td align="right">Opened by:</td><td bgcolor="#d0d0d0"> |
| 84 | 84 | $<opened_by> |
| 85 | 85 | </td> |
| 86 | 86 | </pre> |
| 87 | 87 | This will add a row which displays these two fields, in the event the user has |
| 88 | -"edit" capability. | |
| 88 | +"edit" capability. | |
| 89 | 89 | </p> |
| 90 | 90 | </blockquote> |
| 91 | 91 | |
| 92 | 92 | <h2>Modify the 'edit ticket' page</h2><blockquote> |
| 93 | 93 | <p> |
| 94 | 94 |
| --- www/custom_ticket.wiki | |
| +++ www/custom_ticket.wiki | |
| @@ -65,11 +65,11 @@ | |
| 65 | </tr> |
| 66 | <th1>enable_output 1</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 | <td align="right">Opened by:</td><td bgcolor="#d0d0d0"> |
| 84 | $<opened_by> |
| 85 | </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 | </tr> |
| 66 | <th1>enable_output 1</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 | <td align="right">Opened by:</td><td bgcolor="#d0d0d0"> |
| 84 | $<opened_by> |
| 85 | </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 |
+4
| --- www/customskin.md | ||
| +++ www/customskin.md | ||
| @@ -144,10 +144,14 @@ | ||
| 144 | 144 | respository settings and the specific page being generated. |
| 145 | 145 | |
| 146 | 146 | * **project_name** - The project_name variable is filled with the |
| 147 | 147 | name of the project as configured under the Admin/Configuration |
| 148 | 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. | |
| 149 | 153 | |
| 150 | 154 | * **title** - The title variable holds the title of the page being |
| 151 | 155 | generated. |
| 152 | 156 | |
| 153 | 157 | The title variable is special in that it is deleted after |
| 154 | 158 |
| --- 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 |
+1
-1
| --- www/delta_encoder_algorithm.wiki | ||
| +++ www/delta_encoder_algorithm.wiki | ||
| @@ -153,11 +153,11 @@ | ||
| 153 | 153 | byte forward. The "base" is left unchanged in that case.</p> |
| 154 | 154 | |
| 155 | 155 | <p>The processing loop stops at one of two conditions: |
| 156 | 156 | <ol> |
| 157 | 157 | <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". | |
| 159 | 159 | </li> |
| 160 | 160 | <li>After the emission of instructions the new "base" location is |
| 161 | 161 | within NHASH bytes of end of the "target", i.e. there are no more than |
| 162 | 162 | at most NHASH bytes left. |
| 163 | 163 | </li> |
| 164 | 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_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 |
+9
-9
| --- www/delta_format.wiki | ||
| +++ www/delta_format.wiki | ||
| @@ -161,49 +161,49 @@ | ||
| 161 | 161 | </table> |
| 162 | 162 | |
| 163 | 163 | <p>The unified diff behind the above delta is</p> |
| 164 | 164 | |
| 165 | 165 | <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 | |
| 167 | 167 | --- ../DELTA/old 2007-08-23 21:14:40.000000000 -0700 |
| 168 | 168 | +++ ../DELTA/new 2007-08-23 21:14:33.000000000 -0700 |
| 169 | 169 | @@ -5,7 +5,7 @@ |
| 170 | - | |
| 170 | + | |
| 171 | 171 | * 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 | |
| 173 | 173 | - it is thus unable to update database because it cannot create |
| 174 | 174 | + it is thus unable to update the database because it cannot create |
| 175 | 175 | a rollback journal) then it currently fails silently on a push. |
| 176 | 176 | It needs to return a helpful error. |
| 177 | - | |
| 177 | + | |
| 178 | 178 | @@ -27,8 +27,8 @@ |
| 179 | 179 | * Additional information displayed for the "vinfo" page: |
| 180 | - | |
| 180 | + | |
| 181 | 181 | + All leaves of this version that are not included in the |
| 182 | 182 | - descendant list. With date, user, comment, and hyperlink. |
| 183 | 183 | - Leaves in the descendant table should be marked as such. |
| 184 | 184 | + descendant list. With date, user, comment, and hyperlink. |
| 185 | 185 | + Leaves in the descendant table should be marked as such. |
| 186 | 186 | See the compute_leaves() function to see how to find all |
| 187 | 187 | leaves. |
| 188 | 188 | + Add file diff links to the file change list. |
| 189 | 189 | @@ -37,7 +37,7 @@ |
| 190 | - | |
| 190 | + | |
| 191 | 191 | * The /xfer handler (for push, pull, and clone) does not do |
| 192 | 192 | delta compression. This results in excess bandwidth usage. |
| 193 | 193 | - There are some code in xfer.c that are sketches of ideas on |
| 194 | 194 | + There are some pieces in xfer.c that are sketches of ideas on |
| 195 | 195 | how to do delta compression, but nothing has been implemented. |
| 196 | - | |
| 196 | + | |
| 197 | 197 | * Enhancements to the diff and tkdiff commands in the cli. |
| 198 | 198 | @@ -45,7 +45,7 @@ |
| 199 | 199 | 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 | |
| 201 | 201 | configuration options to replace tkdiff with some other |
| 202 | 202 | - visual differ of the users choice. |
| 203 | 203 | + visual differ of the users choice. Example: eskil. |
| 204 | - | |
| 204 | + | |
| 205 | 205 | * Ticketing interface (expand this bullet) |
| 206 | 206 | |
| 207 | 207 | </pre></td></tr></table> |
| 208 | 208 | |
| 209 | 209 | |
| 210 | 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/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 |
+9
-9
| --- www/embeddeddoc.wiki | ||
| +++ www/embeddeddoc.wiki | ||
| @@ -42,13 +42,13 @@ | ||
| 42 | 42 | <b>http://www.hwaci.com/cgi-bin/fossil</b>. |
| 43 | 43 | If you launch the web server using the "<b>fossil server</b>" command line, |
| 44 | 44 | then the <i><baseurl></i> is usually |
| 45 | 45 | <b>http://localhost:8080/</b>. |
| 46 | 46 | |
| 47 | -The <i><version></i> is any unique prefix of the check-in ID for | |
| 47 | +The <i><version></i> is any unique prefix of the check-in ID for | |
| 48 | 48 | the check-in containing the documentation you want to access. |
| 49 | -Or <i><version></i> can be the name of a | |
| 49 | +Or <i><version></i> can be the name of a | |
| 50 | 50 | [./branching.wiki | branch] in order to show |
| 51 | 51 | the documentation for the latest version of that branch. |
| 52 | 52 | Or <i><version></i> can be one of the keywords "<b>tip</b>" or |
| 53 | 53 | "<b>ckout</b>". The "<b>tip</b>" keyword means to use the most recent |
| 54 | 54 | check-in. This is useful if you want to see the very latest |
| @@ -62,30 +62,30 @@ | ||
| 62 | 62 | |
| 63 | 63 | Finally, the <i><filename></i> element of the URL is the |
| 64 | 64 | pathname of the documentation file relative to the root of the source |
| 65 | 65 | tree. |
| 66 | 66 | |
| 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 | |
| 69 | 69 | [/mimetype_list|many different file suffixes], |
| 70 | 70 | including all the popular ones such as ".css", ".gif", ".htm", |
| 71 | 71 | ".html", ".jpg", ".jpeg", ".png", and ".txt". |
| 72 | 72 | |
| 73 | -Documentation files whose names end in ".wiki" use the | |
| 73 | +Documentation files whose names end in ".wiki" use the | |
| 74 | 74 | [/wiki_rules | fossil wiki markup] - |
| 75 | 75 | a safe subset of HTML together with some wiki rules for paragraph |
| 76 | -breaks, lists, and hyperlinks. | |
| 76 | +breaks, lists, and hyperlinks. | |
| 77 | 77 | Documentation files ending in ".md" or ".markdown" use the |
| 78 | 78 | [/md_rules | Markdown markup langauge]. |
| 79 | 79 | Documentation files ending in ".txt" are plain text. |
| 80 | 80 | Wiki, markdown, and plain text documentation files |
| 81 | 81 | are rendered with the standard fossil header and footer added. |
| 82 | 82 | Most other mimetypes are delivered directly to the requesting |
| 83 | 83 | web browser without interpretation, additions, or changes. |
| 84 | 84 | |
| 85 | 85 | 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. | |
| 87 | 87 | However, if the file begins with a <div> element like this: |
| 88 | 88 | |
| 89 | 89 | <b><div class='fossil-doc' data-title='<i>Title Text</i>'></b> |
| 90 | 90 | |
| 91 | 91 | Then the standard Fossil header and footer are added to the document |
| @@ -117,11 +117,11 @@ | ||
| 117 | 117 | <blockquote><pre> |
| 118 | 118 | #!/usr/bin/fossil |
| 119 | 119 | repository: /fossil/fossil.fossil |
| 120 | 120 | </pre></blockquote> |
| 121 | 121 | |
| 122 | -This is one of four ways to set up a | |
| 122 | +This is one of four ways to set up a | |
| 123 | 123 | <a href="./server.wiki">fossil web server</a>. |
| 124 | 124 | |
| 125 | 125 | The "<b>/trunk/</b>" part of the URL tells fossil to use |
| 126 | 126 | the documentation files from the most recent trunk check-in. |
| 127 | 127 | If you wanted to see an historical version of this document, |
| @@ -138,11 +138,11 @@ | ||
| 138 | 138 | <li> <i>YYYY-MM-DD</i> |
| 139 | 139 | <li> <i>YYYY-MM-DD</i><b>T</b><i>HH:MM</i> |
| 140 | 140 | <li> <i>YYYY-MM-DD</i><b>T</b><i>HH:MM:SS</i> |
| 141 | 141 | </ul> |
| 142 | 142 | |
| 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 | |
| 144 | 144 | of the document that was most recently checked in as of the date |
| 145 | 145 | and time specified. So, for example, to see what the fossil website |
| 146 | 146 | looked like at the beginning of 2010, enter: |
| 147 | 147 | |
| 148 | 148 | <blockquote> |
| 149 | 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><baseurl></i> is usually |
| 45 | <b>http://localhost:8080/</b>. |
| 46 | |
| 47 | The <i><version></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><version></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><version></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><filename></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 <div> element like this: |
| 88 | |
| 89 | <b><div class='fossil-doc' data-title='<i>Title Text</i>'></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><baseurl></i> is usually |
| 45 | <b>http://localhost:8080/</b>. |
| 46 | |
| 47 | The <i><version></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><version></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><version></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><filename></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 <div> element like this: |
| 88 | |
| 89 | <b><div class='fossil-doc' data-title='<i>Title Text</i>'></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 |
+1
-1
| --- www/encryptedrepos.wiki | ||
| +++ www/encryptedrepos.wiki | ||
| @@ -3,11 +3,11 @@ | ||
| 3 | 3 | Fossil can be compiled so that it works with encrypted repositories using |
| 4 | 4 | the [https://www.sqlite.org/see/doc/trunk/www/readme.wiki|SQLite Encryption Extension]. |
| 5 | 5 | This technical note explains the process. |
| 6 | 6 | </blockquote> |
| 7 | 7 | <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 | |
| 9 | 9 | [http://www.hwaci.com/cgi-bin/see-step1|purchasing a license]. |
| 10 | 10 | <p> |
| 11 | 11 | Assuming you have an SEE license, the first step of compiling Fossil to |
| 12 | 12 | use SEE is to create an SEE-enabled version of the SQLite database source code. |
| 13 | 13 | This alternative SQLite database source file should be called "sqlite3-see.c" |
| 14 | 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 |
| --- 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 @@ | ||
| 23 | 23 | can be something simple like "Version 1.2.3" perhaps with a bright |
| 24 | 24 | color background to draw attention to the entry and the wiki content |
| 25 | 25 | can contain release notes, for example. |
| 26 | 26 | |
| 27 | 27 | * <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 | |
| 29 | 29 | roadmaps for future development, can be entered as technotes. |
| 30 | 30 | |
| 31 | 31 | * <b>Process Checkpoints</b>. For projects that have a formal process, |
| 32 | 32 | technotes can be used to record the completion or the initiation of |
| 33 | 33 | various process steps. For example, a technote can be used to record |
| @@ -49,11 +49,11 @@ | ||
| 49 | 49 | stay better organized and provide a better historical record of the |
| 50 | 50 | development progress. |
| 51 | 51 | |
| 52 | 52 | <h2>Viewing Technotes</h2> |
| 53 | 53 | |
| 54 | -Because technotes are considered a special kind of wiki, | |
| 54 | +Because technotes are considered a special kind of wiki, | |
| 55 | 55 | users must have permission to read wiki in order read technotes. |
| 56 | 56 | Enable the "j" permission under the /Setup/Users menu in order |
| 57 | 57 | to give specific users or user classes the ability to view wiki |
| 58 | 58 | and technotes. |
| 59 | 59 | |
| @@ -64,12 +64,12 @@ | ||
| 64 | 64 | |
| 65 | 65 | There is a hyperlink under the /wikihelp menu that can be used to create |
| 66 | 66 | new technotes. And there is a submenu hyperlink on technote displays for |
| 67 | 67 | editing existing technotes. |
| 68 | 68 | |
| 69 | -Users must have check-in privileges (permission "i") in order to | |
| 69 | +Users must have check-in privileges (permission "i") in order to | |
| 70 | 70 | create or edit technotes. In addition, users must have create-wiki |
| 71 | 71 | privilege (permission "f") to create new technotes and edit-wiki |
| 72 | 72 | privilege (permission "k") in order to edit existing technotes. |
| 73 | 73 | |
| 74 | 74 | Technote content may be formatted as [/wiki_rules | Fossil wiki], |
| 75 | 75 | [/md_rules | Markdown], or a plain text. |
| 76 | 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 |
| --- 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 @@ | ||
| 62 | 62 | If you already have a fork in your check-in tree and you want to convert |
| 63 | 63 | that fork to a branch, you can do this from the web interface. |
| 64 | 64 | First locate the check-in that you want to be |
| 65 | 65 | the initial check-in of your branch on the timeline and click on its |
| 66 | 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 | |
| 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 | 69 | the name of your new branch to the right and press the "Apply Changes" |
| 70 | 70 | button.</blockquote></li> |
| 71 | 71 | |
| 72 | 72 | <a name="q4"></a> |
| 73 | 73 | <p><b>(4) How do I tag a check-in?</b></p> |
| @@ -89,11 +89,11 @@ | ||
| 89 | 89 | |
| 90 | 90 | The CHECK-IN in the previous line can be any |
| 91 | 91 | [./checkin_names.wiki | valid check-in name format]. |
| 92 | 92 | |
| 93 | 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 | |
| 94 | +[./webui.wiki | web interface]. First locate the check-in that you | |
| 95 | 95 | what to tag on the timeline, then click on the link to go the detailed |
| 96 | 96 | information page for that check-in. Then find the "<b>edit</b>" |
| 97 | 97 | link (near the "Commands:" label) and click on that. There are |
| 98 | 98 | controls on the edit page that allow new tags to be added and existing |
| 99 | 99 | tags to be removed.</blockquote></li> |
| @@ -100,13 +100,13 @@ | ||
| 100 | 100 | |
| 101 | 101 | <a name="q5"></a> |
| 102 | 102 | <p><b>(5) How do I create a private branch that won't get pushed back to the |
| 103 | 103 | main repository.</b></p> |
| 104 | 104 | |
| 105 | -<blockquote>Use the <b>--private</b> command-line option on the | |
| 105 | +<blockquote>Use the <b>--private</b> command-line option on the | |
| 106 | 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. | |
| 107 | +your local repository only and is never pushed to other repositories. | |
| 108 | 108 | All descendants of a private check-in are also private. |
| 109 | 109 | |
| 110 | 110 | Unless you specify something different using the <b>--branch</b> and/or |
| 111 | 111 | <b>--bgcolor</b> options, the new private check-in will be put on a branch |
| 112 | 112 | named "private" with an orange background color. |
| 113 | 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/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 |
+26
-26
| --- www/fileformat.wiki | ||
| +++ www/fileformat.wiki | ||
| @@ -2,11 +2,11 @@ | ||
| 2 | 2 | <h1 align="center"> |
| 3 | 3 | Fossil File Formats |
| 4 | 4 | </h1> |
| 5 | 5 | |
| 6 | 6 | 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. | |
| 8 | 8 | A fossil repository is intended to be readable, |
| 9 | 9 | searchable, and extensible by people not yet born. |
| 10 | 10 | |
| 11 | 11 | The global state of a fossil repository is an unordered |
| 12 | 12 | set of <i>artifacts</i>. |
| @@ -14,11 +14,11 @@ | ||
| 14 | 14 | part of a trouble ticket, or one of several special control artifacts |
| 15 | 15 | used to show the relationships between other artifacts within the |
| 16 | 16 | project. Each artifact is normally represented on disk as a separate |
| 17 | 17 | file. Artifacts can be text or binary. |
| 18 | 18 | |
| 19 | -In addition to the global state, | |
| 19 | +In addition to the global state, | |
| 20 | 20 | each fossil repository also contains local state. |
| 21 | 21 | The local state consists of web-page formatting |
| 22 | 22 | preferences, authorized users, ticket display and reporting formats, |
| 23 | 23 | and so forth. The global state is shared in common among all |
| 24 | 24 | repositories for the same project, whereas the local state is often |
| @@ -30,11 +30,11 @@ | ||
| 30 | 30 | mentioned here in order to distinguish it from global state. |
| 31 | 31 | |
| 32 | 32 | Each artifact in the repository is named by its SHA1 hash. |
| 33 | 33 | No prefixes or meta information is added to an artifact before |
| 34 | 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 | |
| 35 | +is exactly the same SHA1 hash that is computed by sha1sum | |
| 36 | 36 | on the file as it exists in your source tree.</p> |
| 37 | 37 | |
| 38 | 38 | Some artifacts have a particular format which gives them special |
| 39 | 39 | meaning to fossil. Fossil recognizes: |
| 40 | 40 | |
| @@ -84,11 +84,11 @@ | ||
| 84 | 84 | Each card begins with a single |
| 85 | 85 | character "card type". Zero or more arguments may follow |
| 86 | 86 | the card type. All arguments are separated from each other |
| 87 | 87 | and from the card-type character by a single space |
| 88 | 88 | 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 | |
| 90 | 90 | character that acts as the card separator. |
| 91 | 91 | |
| 92 | 92 | All cards of the manifest occur in strict sorted lexicographical order. |
| 93 | 93 | No card may be duplicated. |
| 94 | 94 | The entire manifest may be PGP clear-signed, but otherwise it |
| @@ -114,18 +114,18 @@ | ||
| 114 | 114 | another manifest that serves as the "baseline" for this manifest. A |
| 115 | 115 | manifest that has a B-card is called a delta-manifest and a manifest |
| 116 | 116 | that omits the B-card is a baseline-manifest. The other manifest |
| 117 | 117 | identified by the argument of the B-card must be a baseline-manifest. |
| 118 | 118 | 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. | |
| 120 | 120 | |
| 121 | 121 | A manifest must have exactly one C-card. The sole argument to |
| 122 | 122 | the C-card is a check-in comment that describes the check-in that |
| 123 | 123 | the manifest defines. The check-in comment is text. The following |
| 124 | 124 | escape sequences are applied to the text: |
| 125 | 125 | 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 | |
| 127 | 127 | (ASCII 0x5C) is represented as two backslashes "\\". Apart from |
| 128 | 128 | space and newline, no other whitespace characters are allowed in |
| 129 | 129 | the check-in comment. Nor are any unprintable characters allowed |
| 130 | 130 | in the comment. |
| 131 | 131 | |
| @@ -167,11 +167,11 @@ | ||
| 167 | 167 | is used. |
| 168 | 168 | |
| 169 | 169 | A manifest has zero or one P-cards. Most manifests have one P-card. |
| 170 | 170 | The P-card has a varying number of arguments that |
| 171 | 171 | 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 | |
| 173 | 173 | hexadecimal SHA1 of a predecessor manifest. All arguments |
| 174 | 174 | to the P-card must be unique within that card. |
| 175 | 175 | The first argument is the SHA1 of the direct ancestor of the manifest. |
| 176 | 176 | Other arguments define manifests with which the first was |
| 177 | 177 | merged to yield the current manifest. Most manifests have |
| @@ -184,28 +184,28 @@ | ||
| 184 | 184 | whereas a P-card defines the immediate ancestor or a merge |
| 185 | 185 | ancestor, the Q-card is used to identify a single check-in or a small |
| 186 | 186 | range of check-ins which were cherry-picked for inclusion in or |
| 187 | 187 | exclusion from the current manifest. The first argument of |
| 188 | 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. | |
| 189 | +which has had its changes included or excluded in the current manifest. | |
| 190 | 190 | The target is preceded by "+" or "-" to show inclusion or |
| 191 | 191 | exclusion, respectively. The optional second argument to the |
| 192 | 192 | Q-card is another manifest artifact ID which is the "baseline" |
| 193 | 193 | for the cherry-pick. If omitted, the baseline is the primary |
| 194 | 194 | parent of the target. The |
| 195 | 195 | changes included or excluded consist of all changes moving from |
| 196 | -the baseline to the target. | |
| 196 | +the baseline to the target. | |
| 197 | 197 | |
| 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. | |
| 199 | 199 | Older versions of Fossil will reject manifests that contain Q-cards. |
| 200 | 200 | |
| 201 | 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 | |
| 202 | +a single argument which is the MD5 checksum of all files in | |
| 203 | 203 | the check-in except the manifest itself. The checksum is expressed |
| 204 | 204 | as 32 characters of lowercase hexadecimal. The checksum is |
| 205 | 205 | 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, | |
| 207 | 207 | take the pathname of the file relative to the root of the |
| 208 | 208 | repository, append a single space (ASCII 0x20), the |
| 209 | 209 | size of the file in ASCII decimal, a single newline |
| 210 | 210 | character (ASCII 0x0A), and the complete text of the file. |
| 211 | 211 | Compute the MD5 checksum of the result. |
| @@ -228,12 +228,12 @@ | ||
| 228 | 228 | is encoded using the same character escapes as is used for the |
| 229 | 229 | check-in comment argument to the C-card. |
| 230 | 230 | |
| 231 | 231 | A manifest must have a single Z-card as its last line. The argument |
| 232 | 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 | |
| 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 | 235 | a sanity check to prove that the manifest is well-formed and |
| 236 | 236 | consistent. |
| 237 | 237 | |
| 238 | 238 | A sample manifest from Fossil itself can be seen |
| 239 | 239 | [/artifact/28987096ac | here]. |
| @@ -240,11 +240,11 @@ | ||
| 240 | 240 | |
| 241 | 241 | <a name="cluster"></a> |
| 242 | 242 | <h2>2.0 Clusters</h2> |
| 243 | 243 | |
| 244 | 244 | 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 | |
| 246 | 246 | reduce network traffic. As such, clusters are an optimization and |
| 247 | 247 | may be removed from a repository without loss or damage to the |
| 248 | 248 | underlying project code. |
| 249 | 249 | |
| 250 | 250 | Clusters follow a syntax that is very similar to manifests. |
| @@ -252,15 +252,15 @@ | ||
| 252 | 252 | (ASCII 0x0a) separate the artifact into cards. Each card begins with a single |
| 253 | 253 | character "card type". Zero or more arguments may follow |
| 254 | 254 | the card type. All arguments are separated from each other |
| 255 | 255 | and from the card-type character by a single space |
| 256 | 256 | 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 | |
| 258 | 258 | character that acts as the card separator. |
| 259 | 259 | All cards of a cluster occur in strict sorted lexicographical order. |
| 260 | 260 | 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 | |
| 262 | 262 | what is described here. |
| 263 | 263 | Unlike manifests, clusters are never PGP signed. |
| 264 | 264 | |
| 265 | 265 | Allowed cards in the cluster are as follows: |
| 266 | 266 | |
| @@ -268,11 +268,11 @@ | ||
| 268 | 268 | <b>M</b> <i>artifact-id</i><br /> |
| 269 | 269 | <b>Z</b> <i>checksum</i> |
| 270 | 270 | </blockquote> |
| 271 | 271 | |
| 272 | 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 | |
| 273 | +card. Each M card has a single argument which is the artifact ID of | |
| 274 | 274 | another artifact in the repository. The Z card works exactly like |
| 275 | 275 | the Z card of a manifest. The argument to the Z card is the |
| 276 | 276 | lower-case hexadecimal representation of the MD5 checksum of all |
| 277 | 277 | prior cards in the cluster. The Z-card is required. |
| 278 | 278 | |
| @@ -315,11 +315,11 @@ | ||
| 315 | 315 | first value is the tag name. The first character of the tag |
| 316 | 316 | is either "+", "-", or "*". The "+" means the tag should be added |
| 317 | 317 | to the artifact. The "-" means the tag should be removed. |
| 318 | 318 | The "*" character means the tag should be added to the artifact |
| 319 | 319 | 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 | |
| 321 | 321 | more recent "-", "*", or "+" tag with the same name. |
| 322 | 322 | The optional third argument is the value of the tag. A tag |
| 323 | 323 | without a value is a Boolean. |
| 324 | 324 | |
| 325 | 325 | When two or more tags with the same name are applied to the |
| @@ -331,11 +331,11 @@ | ||
| 331 | 331 | for display purposes. The "user" tag overrides the name of the |
| 332 | 332 | check-in user. The "date" tag overrides the check-in date. |
| 333 | 333 | The "branch" tag sets the name of the branch that at check-in |
| 334 | 334 | belongs to. Symbolic tags begin with the "sym-" prefix. |
| 335 | 335 | |
| 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 | |
| 337 | 337 | artifact. The Z card is the usual required artifact checksum. |
| 338 | 338 | |
| 339 | 339 | An example control artifacts can be seen [/info/9d302ccda8 | here]. |
| 340 | 340 | |
| 341 | 341 | |
| @@ -360,11 +360,11 @@ | ||
| 360 | 360 | |
| 361 | 361 | The D card is the date and time when the wiki page was edited. |
| 362 | 362 | The P card specifies the parent wiki pages, if any. The L card |
| 363 | 363 | gives the name of the wiki page. The optional N card specifies |
| 364 | 364 | 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. | |
| 366 | 366 | The U card specifies the login |
| 367 | 367 | of the user who made this edit to the wiki page. The Z card is |
| 368 | 368 | the usual checksum over the entire artifact and is required. |
| 369 | 369 | |
| 370 | 370 | The W card is used to specify the text of the wiki page. The |
| @@ -405,11 +405,11 @@ | ||
| 405 | 405 | If the <i>value</i> parameter of the J card is omitted, then the |
| 406 | 406 | field is set to an empty string. |
| 407 | 407 | Each fossil server has a ticket configuration which specifies the fields its |
| 408 | 408 | understands. The ticket configuration is part of the local state for |
| 409 | 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 | |
| 410 | +Hence a J card might specify a <i>field</i> that do not exist in the | |
| 411 | 411 | local ticket configuration. If a J card specifies a <i>field</i> that |
| 412 | 412 | is not in the local configuration, then that J card |
| 413 | 413 | is simply ignored. |
| 414 | 414 | |
| 415 | 415 | The first argument of the J card is the field name. The second |
| @@ -424,11 +424,11 @@ | ||
| 424 | 424 | |
| 425 | 425 | <a name="attachment"></a> |
| 426 | 426 | <h2>6.0 Attachments</h2> |
| 427 | 427 | |
| 428 | 428 | 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 | |
| 430 | 430 | technical note to which |
| 431 | 431 | the attachment is connected (the target artifact). |
| 432 | 432 | The following cards are allowed on an attachment artifact: |
| 433 | 433 | |
| 434 | 434 | <blockquote> |
| @@ -441,11 +441,11 @@ | ||
| 441 | 441 | </blockquote> |
| 442 | 442 | |
| 443 | 443 | The A card specifies a filename for the attachment in its first argument. |
| 444 | 444 | The second argument to the A card is the name of the wiki page or |
| 445 | 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 | |
| 446 | +third argument is either missing or else it is the 40-character artifact | |
| 447 | 447 | ID of the attachment itself. A missing third argument means that the |
| 448 | 448 | attachment should be deleted. |
| 449 | 449 | |
| 450 | 450 | The C card is an optional comment describing what the attachment is about. |
| 451 | 451 | The C card is optional, but there can only be one. |
| @@ -487,11 +487,11 @@ | ||
| 487 | 487 | </blockquote> |
| 488 | 488 | |
| 489 | 489 | The C card contains text that is displayed on the timeline for the |
| 490 | 490 | technote. The C card is optional, but there can only be one. |
| 491 | 491 | |
| 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 | |
| 493 | 493 | technote artifact was created. This is different from the time at which |
| 494 | 494 | the technote appears on the timeline. |
| 495 | 495 | |
| 496 | 496 | A single E card gives the time of the technote (the point on the timeline |
| 497 | 497 | where the technote is displayed) and a unique identifier for the technote. |
| @@ -525,11 +525,11 @@ | ||
| 525 | 525 | display color for timelines. |
| 526 | 526 | |
| 527 | 527 | The optional U card gives name of the user who entered the technote. |
| 528 | 528 | |
| 529 | 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 | |
| 530 | +technote. The format of the W card is exactly the same as for a | |
| 531 | 531 | [#wikichng | wiki artifact]. |
| 532 | 532 | |
| 533 | 533 | The Z card is the required checksum over the rest of the artifact. |
| 534 | 534 | |
| 535 | 535 | |
| 536 | 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/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 |
+19
-19
| --- www/fiveminutes.wiki | ||
| +++ www/fiveminutes.wiki | ||
| @@ -4,65 +4,65 @@ | ||
| 4 | 4 | The following document was contributed by Gilles Ganault on 2013-01-08. |
| 5 | 5 | </i></b> |
| 6 | 6 | </p><hr> |
| 7 | 7 | |
| 8 | 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 | |
| 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 | 11 | repository, and no need for branching/forking.</p> |
| 12 | 12 | |
| 13 | 13 | <h2>Create a new repository</h2> |
| 14 | 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 | |
| 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 | 18 | after they've been checked out of the repository.</p> |
| 19 | 19 | |
| 20 | 20 | <h2>Open the repository</h2> |
| 21 | 21 | <p>cd c:\temp\test.fossil</p> |
| 22 | 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 | |
| 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 | 25 | file _FOSSIL_ to keep track of changes (on non-Windows systems it is called |
| 26 | 26 | <tt>.fslckout</tt>).</p> |
| 27 | 27 | |
| 28 | 28 | <h2>Add new files</h2> |
| 29 | 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 "commit". When using ".", 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 "commit". When using ".", it tells Fossil | |
| 32 | +to add all the files in the current directory recursively, i.e. including all | |
| 33 | 33 | the files in all the subdirectories.</p> |
| 34 | 34 | <p>Note: To tell Fossil to ignore some extensions:</p> |
| 35 | 35 | <p>fossil settings ignore-glob "*.o,*.obj,*.exe" --global</p> |
| 36 | 36 | |
| 37 | 37 | <h2>Remove files that haven't been committed yet</h2> |
| 38 | 38 | <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 | |
| 40 | 40 | added through "fossil add".</p> |
| 41 | 41 | |
| 42 | 42 | <h2>Check current status</h2> |
| 43 | 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 "fossil commit". 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 "fossil commit". It's a useful command to run before | |
| 46 | 46 | running "fossil commit" just to check that things are OK before proceeding.</p> |
| 47 | 47 | |
| 48 | 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, | |
| 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 | 51 | etc.</p> |
| 52 | 52 | |
| 53 | 53 | <p>fossil commit -m "Added stuff"</p> |
| 54 | 54 | |
| 55 | 55 | If no file names are provided on the command-line then all changes will be checked in, |
| 56 | 56 | otherwise just the listed file(s) will be checked in. |
| 57 | 57 | |
| 58 | 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 | |
| 59 | +<p>If you wish to compare the last revision of a file and its checked out version | |
| 60 | 60 | in your work directory:</p> |
| 61 | 61 | <p>fossil gdiff myfile.c</p> |
| 62 | 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 | |
| 63 | +<p>fossil finfo myfile: Note the first hash, which is the UUID of the commit | |
| 64 | 64 | when the file was committed</p> |
| 65 | 65 | <p>fossil gdiff --from UUID#1 --to UUID#2 myfile.c</p> |
| 66 | 66 | <h2>Cancel changes and go back to previous revision</h2> |
| 67 | 67 | <p>fossil revert myfile.c</p> |
| 68 | 68 | <p>Fossil does not prompt when reverting a file. It simply reminds the user about the |
| @@ -69,8 +69,8 @@ | ||
| 69 | 69 | "undo" command, just in case the revert was a mistake.</p> |
| 70 | 70 | |
| 71 | 71 | |
| 72 | 72 | <h2>Close the repository</h2> |
| 73 | 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 "fossil" | |
| 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 "fossil" | |
| 76 | 76 | will trigger an error since there is no longer any connection.</p> |
| 77 | 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 "commit". When using ".", 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 "*.o,*.obj,*.exe" --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 "fossil add".</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 "fossil commit". It's a useful command to run before |
| 46 | running "fossil commit" 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 "fossil" |
| 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 "commit". When using ".", 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 "*.o,*.obj,*.exe" --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 "fossil add".</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 "fossil commit". It's a useful command to run before |
| 46 | running "fossil commit" 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 "fossil" |
| 76 | will trigger an error since there is no longer any connection.</p> |
| 77 |
+2
-2
| --- www/foss-cklist.wiki | ||
| +++ www/foss-cklist.wiki | ||
| @@ -89,11 +89,11 @@ | ||
| 89 | 89 | |
| 90 | 90 | <li><p>The project has a website. |
| 91 | 91 | |
| 92 | 92 | <li><p>Release version numbers are in the traditional X.Y or X.Y.Z format. |
| 93 | 93 | |
| 94 | -<li><p>Releases can be downloaded as tarball using | |
| 94 | +<li><p>Releases can be downloaded as tarball using | |
| 95 | 95 | gzip or bzip2 compression. |
| 96 | 96 | |
| 97 | 97 | <li><p>Releases unpack into a versioned top-level directory. |
| 98 | 98 | (ex: "projectname-1.2.3/"). |
| 99 | 99 | |
| @@ -102,12 +102,12 @@ | ||
| 102 | 102 | tarball. |
| 103 | 103 | |
| 104 | 104 | <li><p>There are no incompatible licenses in the code. |
| 105 | 105 | |
| 106 | 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 | |
| 107 | +having gone through the tedious and exacting legal steps to actually put it | |
| 108 | 108 | in the public domain. |
| 109 | 109 | |
| 110 | 110 | <li><p>There is an accurate change log in the code and on the website. |
| 111 | 111 | |
| 112 | 112 | <li><p>There is documentation in the code and on the website. |
| 113 | 113 | </ol> |
| 114 | 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/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 |
+11
-11
| --- www/fossil-from-msvc.wiki | ||
| +++ www/fossil-from-msvc.wiki | ||
| @@ -11,41 +11,41 @@ | ||
| 11 | 11 | <li>Tools > External Tools, where the items in this list map |
| 12 | 12 | to "External Tool X" that we'll add to our own Fossil |
| 13 | 13 | menu later: </li> |
| 14 | 14 | <ol type="1"> |
| 15 | 15 | <li>Rename the default "[New Tool 1]" to eg. |
| 16 | - "Commit" 2. | |
| 16 | + "Commit" 2. | |
| 17 | 17 | </li> |
| 18 | 18 | <li>Change Command to where Fossil is located eg. |
| 19 | 19 | "c:\fossil.exe"</li> |
| 20 | 20 | <li>Change Arguments to the required command, eg. |
| 21 | - "commit -m". | |
| 21 | + "commit -m". | |
| 22 | 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 | |
| 23 | + <li>Set "Initial Directory" to point it to the work directory | |
| 24 | 24 | where the source files are currently checked out |
| 25 | 25 | by Fossil (eg. c:\Workspace). It's also possible to use system |
| 26 | 26 | variables such as "$(ProjectDir)" instead of hard-coding the path</li> |
| 27 | 27 | <li>Check "Prompt for arguments", since Commit |
| 28 | 28 | requires typing a comment. Useless for commands like Changes |
| 29 | 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 | |
| 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 | 33 | opening a DOS box</li> |
| 34 | 34 | <li>Click on OK</li> |
| 35 | 35 | </ol> |
| 36 | 36 | <li>Tools > Customize > Commands</li> |
| 37 | 37 | <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 | |
| 39 | 39 | New Menu". A new "Fossil" menu is displayed in the |
| 40 | 40 | IDE's menu bar</li> |
| 41 | 41 | <li>Click on "Modify Selection" to rename it |
| 42 | 42 | "Fossil", and...</li> |
| 43 | 43 | <li>Use the "Move Down" button to move it lower in |
| 44 | 44 | the list</li> |
| 45 | 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 | |
| 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 | 50 | maps to "External Command X".</li> |
| 51 | 51 | </ol> |
| 52 | 52 |
| --- www/fossil-from-msvc.wiki | |
| +++ www/fossil-from-msvc.wiki | |
| @@ -11,41 +11,41 @@ | |
| 11 | <li>Tools > 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 "[New Tool 1]" to eg. |
| 16 | "Commit" 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 > Customize > 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 > 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 "[New Tool 1]" to eg. |
| 16 | "Commit" 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 > Customize > 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 @@ | ||
| 38 | 38 | ([./webpage-ex.md|examples]) designed to promote situational awareness. |
| 39 | 39 | |
| 40 | 40 | This entire website is just a running instance of Fossil. |
| 41 | 41 | The pages you see here are all [./wikitheory.wiki | wiki] or |
| 42 | 42 | [./embeddeddoc.wiki | embedded documentation] or (in the case of |
| 43 | - the [/uv/download.html|download] page) | |
| 43 | + the [/uv/download.html|download] page) | |
| 44 | 44 | [./unvers.wiki | unversioned files]. |
| 45 | 45 | When you clone Fossil from one of its |
| 46 | 46 | [./selfhost.wiki | self-hosting repositories], |
| 47 | 47 | you get more than just source code - you get this entire website. |
| 48 | 48 | |
| 49 | 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 |
| --- 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 @@ | ||
| 1 | 1 | <title>Import And Export</title> |
| 2 | 2 | |
| 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 | |
| 4 | 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 | |
| 5 | +systems will also import/export from Git, that means that you can | |
| 6 | 6 | import/export a Fossil repository to most version control systems using |
| 7 | 7 | Git as an intermediary. |
| 8 | 8 | |
| 9 | 9 | <h2>Git → Fossil</h2> |
| 10 | 10 | |
| @@ -20,11 +20,11 @@ | ||
| 20 | 20 | command is the name of a new Fossil repository that is created to hold the Git |
| 21 | 21 | content. |
| 22 | 22 | |
| 23 | 23 | The --git option is not actually required. The git-fast-export file format |
| 24 | 24 | 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 | |
| 26 | 26 | interchange formats, and so for compatibility, use of the |
| 27 | 27 | --git option is recommended. |
| 28 | 28 | |
| 29 | 29 | <h2>Fossil → Git</h2> |
| 30 | 30 | |
| @@ -43,21 +43,60 @@ | ||
| 43 | 43 | Note that the "fossil export --git" command only exports the versioned files. |
| 44 | 44 | Tickets and wiki and events are not exported, since Git does not understand |
| 45 | 45 | those concepts. |
| 46 | 46 | |
| 47 | 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 | |
| 48 | +since the git-fast-export file format is currently the only VCS interchange | |
| 49 | 49 | format that Fossil will generate. However, |
| 50 | 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 | |
| 51 | +VCS interchange formats, and so for compatibility, the use of the --git | |
| 52 | 52 | option recommended. |
| 53 | 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> | |
| 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> | |
| 64 | 103 |
| --- 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 @@ | ||
| 2 | 2 | |
| 3 | 3 | <h1>1.0 Introduction</h1> |
| 4 | 4 | |
| 5 | 5 | The build process for Fossil is tricky in that the source code |
| 6 | 6 | 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 | |
| 8 | 8 | [http://www.fossil-scm.org/download.html | precompiled binary] |
| 9 | 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]. | |
| 10 | +want to compile the code themselves can use one of the | |
| 11 | +[./build.wiki | existing makefiles]. | |
| 12 | 12 | So must people do not need to be concerned with the |
| 13 | 13 | build complexities of Fossil. But hard-core developers who desire |
| 14 | 14 | a deep understanding of how Fossil is put together can benefit |
| 15 | 15 | from reviewing this article. |
| 16 | 16 | |
| 17 | 17 | <a name="srctour"></a> |
| 18 | 18 | <h1>2.0 Source Code Tour</h1> |
| 19 | 19 | |
| 20 | -The source code for Fossil is found in the | |
| 20 | +The source code for Fossil is found in the | |
| 21 | 21 | [/dir?ci=trunk&name=src | src/] subdirectory of the |
| 22 | 22 | source tree. The src/ subdirectory contains all code, including |
| 23 | 23 | the code for the separate preprocessor programs. |
| 24 | 24 | |
| 25 | 25 | Each preprocessor program is a separate C program implemented in |
| @@ -50,11 +50,11 @@ | ||
| 50 | 50 | The TH1 script engine is implemented using files: |
| 51 | 51 | |
| 52 | 52 | 7. th.c |
| 53 | 53 | 8. th.h |
| 54 | 54 | |
| 55 | -These two files are imports like the SQLite source files, | |
| 55 | +These two files are imports like the SQLite source files, | |
| 56 | 56 | and so are not preprocessed. |
| 57 | 57 | |
| 58 | 58 | The VERSION.h header file is generated from other information sources |
| 59 | 59 | using a small program called: |
| 60 | 60 | |
| @@ -86,11 +86,11 @@ | ||
| 86 | 86 | |
| 87 | 87 | 13. main.mk |
| 88 | 88 | |
| 89 | 89 | The main.mk makefile is invoked from the Makefile in the top-level |
| 90 | 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 | |
| 91 | +be hand edited. Other makefiles generated by makemake.tcl are in | |
| 92 | 92 | other subdirectories (currently all in the win/ subdirectory). |
| 93 | 93 | |
| 94 | 94 | All the other files in the src/ subdirectory (79 files at the time of |
| 95 | 95 | this writing) are C source code files that are subject to the |
| 96 | 96 | preprocessing steps described below. In the sequel, we will call these |
| @@ -109,11 +109,11 @@ | ||
| 109 | 109 | (The "manifest" and "manifest.uuid" files are automatically generated and |
| 110 | 110 | updated by Fossil itself. See the [/help/setting | fossil set manifest] |
| 111 | 111 | command for additional information.) |
| 112 | 112 | |
| 113 | 113 | The VERSION.h header file is generated by |
| 114 | -a C program: src/mkversion.c. | |
| 114 | +a C program: src/mkversion.c. | |
| 115 | 115 | To run the VERSION.h generator, first compile the src/mkversion.c |
| 116 | 116 | source file into a command-line program (named "mkversion.exe") |
| 117 | 117 | then run: |
| 118 | 118 | |
| 119 | 119 | <blockquote><pre> |
| @@ -126,11 +126,11 @@ | ||
| 126 | 126 | in the root of the source tree are the three arguments and |
| 127 | 127 | the generated VERSION.h file appears on standard output. |
| 128 | 128 | |
| 129 | 129 | The builtin_data.h header file is generated by a C program: src/mkbuiltin.c. |
| 130 | 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 | |
| 131 | +the content of resource files used by Fossil. To generate the | |
| 132 | 132 | builtin_data.h file, first compile the mkbuiltin.c program, then run: |
| 133 | 133 | |
| 134 | 134 | <blockquote><pre> |
| 135 | 135 | mkbuiltin.exe diff.tcl <i>OtherFiles...</i> >builtin_data.h |
| 136 | 136 | </pre></blockquote> |
| @@ -163,11 +163,11 @@ | ||
| 163 | 163 | Note that "src.c" in the above is a stand-in for the (79) regular source |
| 164 | 164 | files of Fossil - all source files except for the exceptions described in |
| 165 | 165 | section 2.0 above. |
| 166 | 166 | |
| 167 | 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. | |
| 168 | +the main.c source file during the final compilation step. | |
| 169 | 169 | |
| 170 | 170 | <h2>4.2 The translate preprocessor</h2> |
| 171 | 171 | |
| 172 | 172 | The translate preprocessor looks for lines of source code that begin |
| 173 | 173 | with "@" and converts those lines into string constants or (depending on |
| @@ -181,11 +181,11 @@ | ||
| 181 | 181 | </pre></blockquote> |
| 182 | 182 | |
| 183 | 183 | In this case, the "src.c" file represents any single source file from the |
| 184 | 184 | set of ordinary source files as described in section 2.0 above. Note that |
| 185 | 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 | |
| 186 | +the translated source files are the names of the input sources with a | |
| 187 | 187 | single "_" character at the end. But a new makefile can use any naming |
| 188 | 188 | convention it wants - the "_" is not critical to the build process. |
| 189 | 189 | |
| 190 | 190 | After being translated, the output files (the "src_.c" files) should be |
| 191 | 191 | used for all subsequent preprocessing and compilation steps. |
| @@ -209,16 +209,16 @@ | ||
| 209 | 209 | <blockquote><pre> |
| 210 | 210 | makeheaders src_.c:src.h sqlite3.h th.h VERSION.h |
| 211 | 211 | </pre></blockquote> |
| 212 | 212 | |
| 213 | 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. | |
| 214 | +(79) ordinary C source files, each as a separate argument. | |
| 215 | 215 | |
| 216 | 216 | <h1>5.0 Compilation</h1> |
| 217 | 217 | |
| 218 | 218 | 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 | |
| 220 | 220 | combined into a single executable using a C compiler. This can be done |
| 221 | 221 | all at once, or each preprocessed source file can be compiled into a |
| 222 | 222 | separate object code file and the resulting object code files linked |
| 223 | 223 | together in a final step. |
| 224 | 224 | |
| @@ -247,11 +247,11 @@ | ||
| 247 | 247 | * -Dmain=sqlite3_main |
| 248 | 248 | * -DSQLITE_OMIT_LOAD_EXTENSION=1 |
| 249 | 249 | |
| 250 | 250 | The "main()" routine in the shell must be changed into sqlite3_main() |
| 251 | 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 | |
| 252 | +Fossil an entry point to jump to when the | |
| 253 | 253 | [/help/sqlite3 | fossil sql] command is invoked. |
| 254 | 254 | |
| 255 | 255 | All the other source code files can be compiled without any special |
| 256 | 256 | options. |
| 257 | 257 | |
| 258 | 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> >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> >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 |
+2
-2
| --- www/mkdownload.tcl | ||
| +++ www/mkdownload.tcl | ||
| @@ -1,9 +1,9 @@ | ||
| 1 | 1 | #!/usr/bin/tclsh |
| 2 | 2 | # |
| 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. | |
| 5 | 5 | # |
| 6 | 6 | # Also generate the fossil_download_checksums.html page. |
| 7 | 7 | # |
| 8 | 8 | # |
| 9 | 9 | set out [open download.html w] |
| 10 | 10 |
| --- 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 |
+1
-1
| --- www/newrepo.wiki | ||
| +++ www/newrepo.wiki | ||
| @@ -53,11 +53,11 @@ | ||
| 53 | 53 | |
| 54 | 54 | <verbatim> |
| 55 | 55 | stephan@ludo:~/fossil$ mkdir demo |
| 56 | 56 | stephan@ludo:~/fossil$ cd demo |
| 57 | 57 | stephan@ludo:~/fossil/demo$ fossil open ../demo.fossil |
| 58 | -stephan@ludo:~/fossil/demo$ | |
| 58 | +stephan@ludo:~/fossil/demo$ | |
| 59 | 59 | </verbatim> |
| 60 | 60 | |
| 61 | 61 | That creates a file called <tt>_FOSSIL_</tt> in the current |
| 62 | 62 | directory, and this file contains all kinds of fossil-related |
| 63 | 63 | information about your local repository. You can ignore it |
| 64 | 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 |
| --- 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 @@ | ||
| 4 | 4 | This page attempts to define the foundational principals upon |
| 5 | 5 | which Fossil is built. |
| 6 | 6 | </p> |
| 7 | 7 | |
| 8 | 8 | <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 | |
| 10 | 10 | trouble tickets, and control files (collectively "artifacts"). |
| 11 | 11 | All historical copies of all artifacts |
| 12 | 12 | are saved. The project maintains an audit |
| 13 | 13 | trail.</p></li> |
| 14 | 14 | |
| 15 | 15 | <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 | |
| 17 | 17 | of the others.</p></li> |
| 18 | 18 | |
| 19 | 19 | <li><p>Each repository has both global and local state. The |
| 20 | 20 | global state is common to all repositories (or at least |
| 21 | 21 | has the potential to be shared in common when the |
| @@ -24,28 +24,28 @@ | ||
| 24 | 24 | The global state represents the content of the project. |
| 25 | 25 | The local state identifies the authorized users and |
| 26 | 26 | access policies for a particular repository.</p></li> |
| 27 | 27 | |
| 28 | 28 | <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 | |
| 30 | 30 | its SHA1 hash encoded in lowercase hexadecimal. |
| 31 | 31 | In many contexts, the name can be |
| 32 | 32 | abbreviated to a unique prefix. A five- or six-character |
| 33 | 33 | prefix usually suffices to uniquely identify a file.</p></li> |
| 34 | 34 | |
| 35 | 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 | |
| 36 | +are immutable. Any change to the content of an artifact also | |
| 37 | 37 | changes the hash that forms the artifacts name, thus |
| 38 | 38 | creating a new artifact. Both the old original version of the |
| 39 | 39 | artifact and the new change are preserved under different names.</p></li> |
| 40 | 40 | |
| 41 | 41 | <li><p>It is theoretically possible for two artifacts with different |
| 42 | 42 | content to share the same hash. But finding two such |
| 43 | 43 | artifacts is so incredibly difficult and unlikely that we |
| 44 | 44 | consider it to be an impossibility.</p></li> |
| 45 | 45 | |
| 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 | |
| 47 | 47 | artifact itself, exactly as it would appear in a disk file. No prefix |
| 48 | 48 | or meta-information about the artifact is added before computing |
| 49 | 49 | the hash. So you can |
| 50 | 50 | always find the SHA1 signature of a file by using the |
| 51 | 51 | "sha1sum" command-line utility.</p></li> |
| 52 | 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/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 |
+3
-3
| --- www/private.wiki | ||
| +++ www/private.wiki | ||
| @@ -41,11 +41,11 @@ | ||
| 41 | 41 | <h2>Syncing Private Branches</h2> |
| 42 | 42 | |
| 43 | 43 | A private branch normally stays on the one repository where it was |
| 44 | 44 | originally created. But sometimes you want to share private branches |
| 45 | 45 | 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, | |
| 47 | 47 | your Linux desktop, and your iMac. You can transfer private branches |
| 48 | 48 | between these machines by using the --private option on the "sync", |
| 49 | 49 | "push", "pull", and "clone" commands. For example, if you are running |
| 50 | 50 | "fossil server" on your Linux box and you want to clone that repository |
| 51 | 51 | to your Mac, including all private branches, use: |
| @@ -67,11 +67,11 @@ | ||
| 67 | 67 | only enable "x" for local repositories when you need to share private |
| 68 | 68 | branches. |
| 69 | 69 | |
| 70 | 70 | Private branch sync only works if you use the --private command-line option. |
| 71 | 71 | 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 | |
| 73 | 73 | push private branches beyond their intended audience. |
| 74 | 74 | |
| 75 | 75 | <h2>Purging Private Branches</h2> |
| 76 | 76 | |
| 77 | 77 | You can remove all private branches from a repository using this command: |
| @@ -85,10 +85,10 @@ | ||
| 85 | 85 | removed, they cannot be retrieved (unless you have synced them to another |
| 86 | 86 | repository.) So be careful with the command. |
| 87 | 87 | |
| 88 | 88 | <h2>Additional Notes</h2> |
| 89 | 89 | |
| 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 | |
| 91 | 91 | single repository at once. There is no mechanism in Fossil (currently) |
| 92 | 92 | that allows you to push, pull, clone, sync, or scrub and individual |
| 93 | 93 | private branch within a repository that contains multiple private |
| 94 | 94 | branches. |
| 95 | 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 |
| --- 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 @@ | ||
| 22 | 22 | <li> Integrated <a href="wikitheory.wiki">wiki</a>. </li> |
| 23 | 23 | <li> Integrated <a href="bugtheory.wiki">bug tracking</a> </li> |
| 24 | 24 | <li> Immutable artifacts </li> |
| 25 | 25 | <li> Self-contained, stand-alone executable that can be run in |
| 26 | 26 | a <a href="http://en.wikipedia.org/wiki/Chroot">chroot jail</a> </li> |
| 27 | - <li> Simple, well-defined, | |
| 27 | + <li> Simple, well-defined, | |
| 28 | 28 | <a href="fileformat.wiki">enduring file format</a> </li> |
| 29 | 29 | <li> Integrated <a href="webui.wiki">web interface</a> </li> |
| 30 | 30 | </ol> |
| 31 | 31 | </blockquote> |
| 32 | 32 | |
| @@ -36,11 +36,11 @@ | ||
| 36 | 36 | <ol> |
| 37 | 37 | <li> Fossil is distributed. You can view and/or edit tickets, wiki, and |
| 38 | 38 | code while off network, then sync your changes later. With Trac, you |
| 39 | 39 | can only view and edit tickets and wiki while you are connected to |
| 40 | 40 | 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 | |
| 42 | 42 | to setup on a low-resource machine. Fossil does not require an |
| 43 | 43 | administrator.</li> |
| 44 | 44 | <li> Fossil integrates code versioning into the same repository with |
| 45 | 45 | wiki and tickets. There is nothing extra to add or install. |
| 46 | 46 | Fossil is an all-in-one turnkey solution. </li> |
| @@ -48,25 +48,25 @@ | ||
| 48 | 48 | </blockquote> |
| 49 | 49 | |
| 50 | 50 | <b>Love the concept here. Anyone using this for real work yet?</b> |
| 51 | 51 | |
| 52 | 52 | <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>. | |
| 54 | 54 | In fact, this page was probably delivered |
| 55 | 55 | to your web-browser via a working fossil instance. The same virtual |
| 56 | 56 | machine that hosts http://www.fossil-scm.org/ |
| 57 | 57 | (a <a href="http://www.linode.com/">Linode 720</a>) |
| 58 | 58 | also hosts 24 other fossil repositories for various small projects. |
| 59 | -The documentation files for | |
| 59 | +The documentation files for | |
| 60 | 60 | <a href="http://www.sqlite.org/">SQLite</a> are hosted in a |
| 61 | 61 | fossil repository <a href="http://www.sqlite.org/docsrc/">here</a>, |
| 62 | 62 | for example. |
| 63 | 63 | Other projects are also adopting fossil. But fossil does not yet have |
| 64 | 64 | the massive user base of git or mercurial. |
| 65 | 65 | </blockquote> |
| 66 | 66 | |
| 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 | |
| 68 | 68 | Linksys Router's administration screen.</b> |
| 69 | 69 | |
| 70 | 70 | <blockquote> |
| 71 | 71 | <p>I take a pragmatic approach to software: form follows function. |
| 72 | 72 | To me, it is more important to have a reliable, fast, efficient, |
| @@ -83,11 +83,11 @@ | ||
| 83 | 83 | keeps the bug-tracking database in a versioned file. That file can |
| 84 | 84 | then be pushed and pulled along with the rest repository.</b> |
| 85 | 85 | |
| 86 | 86 | <blockquote> |
| 87 | 87 | <p>Fossil already <u>does</u> push and pull bugs along with the files |
| 88 | -in your repository. | |
| 88 | +in your repository. | |
| 89 | 89 | But fossil does <u>not</u> track bugs as files in the source tree. |
| 90 | 90 | That approach to bug tracking was rejected for three reasons:</p> |
| 91 | 91 | |
| 92 | 92 | <ol> |
| 93 | 93 | <li> Check-ins in fossil are immutable. So if |
| @@ -108,11 +108,11 @@ | ||
| 108 | 108 | |
| 109 | 109 | <p>These points are reiterated in the opening paragraphs of |
| 110 | 110 | the <a href="bugtheory.wiki">Bug-Tracking In Fossil</a> document.</p> |
| 111 | 111 | </blockquote> |
| 112 | 112 | |
| 113 | -<b>Fossil is already the name of a plan9 versioned | |
| 113 | +<b>Fossil is already the name of a plan9 versioned | |
| 114 | 114 | append-only filesystem.</b> |
| 115 | 115 | |
| 116 | 116 | <blockquote> |
| 117 | 117 | I did not know that. Perhaps they selected the name for the same reason that |
| 118 | 118 | I did: because a repository with immutable artifacts preserves |
| @@ -137,22 +137,22 @@ | ||
| 137 | 137 | Subversion or Bazaar.</b> |
| 138 | 138 | |
| 139 | 139 | <blockquote> |
| 140 | 140 | <p>I have no doubt that Trac has many features that fossil lacks. But that |
| 141 | 141 | 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 | |
| 143 | 143 | fossil supports disconnected operation.</p> |
| 144 | 144 | |
| 145 | 145 | <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 | |
| 147 | 147 | (diff, patch, merge, cvs, svn, rcs, git, python, perl, tcl, apache, |
| 148 | 148 | sqlite, and so forth) |
| 149 | 149 | in order to run fossil. Fossil runs just fine in a chroot jail all |
| 150 | 150 | by itself. And the self-contained fossil |
| 151 | 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 | |
| 152 | +grown in the years since the previous sentence was written but is still | |
| 153 | 153 | much less than 2MB according to "size" when compiled using -Os on x64 Linux.) |
| 154 | 154 | Fossil is the very opposite of bloat.</p> |
| 155 | 155 | </blockquote> |
| 156 | 156 | |
| 157 | 157 | |
| 158 | 158 | </nowiki> |
| 159 | 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/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 |
+26
-26
| --- www/quickstart.wiki | ||
| +++ www/quickstart.wiki | ||
| @@ -5,16 +5,16 @@ | ||
| 5 | 5 | and painlessly.</p> |
| 6 | 6 | |
| 7 | 7 | <h2>Installing</h2> |
| 8 | 8 | |
| 9 | 9 | <p>Fossil is a single self-contained C program. You need to |
| 10 | - either download a | |
| 10 | + either download a | |
| 11 | 11 | <a href="http://www.fossil-scm.org/download.html">precompiled binary</a> |
| 12 | 12 | or <a href="build.wiki">compile it yourself</a> from sources. |
| 13 | 13 | Install fossil by putting the fossil binary |
| 14 | 14 | someplace on your $PATH.</p> |
| 15 | - | |
| 15 | + | |
| 16 | 16 | <a name="fslclone"></a> |
| 17 | 17 | <h2>General Work Flow</h2> |
| 18 | 18 | |
| 19 | 19 | <p>Fossil works with repository files (a database with the project's |
| 20 | 20 | complete history) and with checked-out local trees (the working directory |
| @@ -34,11 +34,11 @@ | ||
| 34 | 34 | |
| 35 | 35 | <h2>Starting A New Project</h2> |
| 36 | 36 | |
| 37 | 37 | <p>To start a new project with fossil, create a new empty repository |
| 38 | 38 | this way: ([/help/init | more info]) </p> |
| 39 | - | |
| 39 | + | |
| 40 | 40 | <blockquote> |
| 41 | 41 | <b>fossil init </b><i> repository-filename</i> |
| 42 | 42 | </blockquote> |
| 43 | 43 | |
| 44 | 44 | <h2>Cloning An Existing Repository</h2> |
| @@ -46,36 +46,36 @@ | ||
| 46 | 46 | <p>Most fossil operations interact with a repository that is on the |
| 47 | 47 | local disk drive, not on a remote system. Hence, before accessing |
| 48 | 48 | a remote repository it is necessary to make a local copy of that |
| 49 | 49 | repository. Making a local copy of a remote repository is called |
| 50 | 50 | "cloning".</p> |
| 51 | - | |
| 51 | + | |
| 52 | 52 | <p>Clone a remote repository as follows: ([/help/clone | more info])</p> |
| 53 | - | |
| 53 | + | |
| 54 | 54 | <blockquote> |
| 55 | 55 | <b>fossil clone</b> <i>URL repository-filename</i> |
| 56 | 56 | </blockquote> |
| 57 | - | |
| 57 | + | |
| 58 | 58 | <p>The <i>URL</i> specifies the fossil repository |
| 59 | 59 | you want to clone. The <i>repository-filename</i> is the new local |
| 60 | 60 | filename into which the cloned repository will be written. For |
| 61 | 61 | example: |
| 62 | - | |
| 62 | + | |
| 63 | 63 | <blockquote> |
| 64 | 64 | <b>fossil clone http://www.fossil-scm.org/ myclone.fossil</b> |
| 65 | 65 | </blockquote> |
| 66 | 66 | |
| 67 | - <p>If the remote repository requires a login, include a | |
| 67 | + <p>If the remote repository requires a login, include a | |
| 68 | 68 | userid in the URL like this: |
| 69 | 69 | |
| 70 | 70 | <blockquote> |
| 71 | 71 | <b>fossil clone http://</b><i>userid</i><b>@www.fossil-scm.org/ myclone.fossil</b> |
| 72 | 72 | </blockquote> |
| 73 | - | |
| 73 | + | |
| 74 | 74 | |
| 75 | 75 | <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. | |
| 77 | 77 | Examples: "%40" in place of "@" and "%2F" in place of "/". |
| 78 | 78 | |
| 79 | 79 | <p>If you are behind a restrictive firewall, you might need |
| 80 | 80 | to <a href="#proxy">specify an HTTP proxy</a>.</p> |
| 81 | 81 | |
| @@ -85,31 +85,31 @@ | ||
| 85 | 85 | information above and beyond the versioned files, including some |
| 86 | 86 | sensitive information such as password hashes and email addresses. If you |
| 87 | 87 | want to share Fossil repositories directly, consider running the |
| 88 | 88 | [/help/scrub|fossil scrub] command to remove sensitive information |
| 89 | 89 | before transmitting the file. |
| 90 | - | |
| 90 | + | |
| 91 | 91 | <h2>Importing From Another Version Control System</h2> |
| 92 | 92 | |
| 93 | 93 | <p>Rather than start a new project, or clone an existing Fossil project, |
| 94 | - you might prefer to | |
| 94 | + you might prefer to | |
| 95 | 95 | <a href="./inout.wiki">import an existing Git project</a> |
| 96 | 96 | into Fossil using the [/help/import | fossil import] command. |
| 97 | 97 | |
| 98 | 98 | <h2>Checking Out A Local Tree</h2> |
| 99 | 99 | |
| 100 | 100 | <p>To work on a project in fossil, you need to check out a local |
| 101 | 101 | copy of the source tree. Create the directory you want to be |
| 102 | 102 | the root of your tree and cd into that directory. Then |
| 103 | 103 | do this: ([/help/open | more info])</p> |
| 104 | - | |
| 104 | + | |
| 105 | 105 | <blockquote> |
| 106 | 106 | <b>fossil open </b><i> repository-filename</i> |
| 107 | 107 | </blockquote> |
| 108 | - | |
| 108 | + | |
| 109 | 109 | <p>This leaves you with the newest version of the tree |
| 110 | - checked out. | |
| 110 | + checked out. | |
| 111 | 111 | From anywhere underneath the root of your local tree, you |
| 112 | 112 | can type commands like the following to find out the status of |
| 113 | 113 | your local tree:</p> |
| 114 | 114 | |
| 115 | 115 | <blockquote> |
| @@ -122,11 +122,11 @@ | ||
| 122 | 122 | <b>[/help/branch | fossil branch]</b><br> |
| 123 | 123 | </blockquote> |
| 124 | 124 | |
| 125 | 125 | <p>Note that Fossil allows you to make multiple check-outs in |
| 126 | 126 | 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 | |
| 128 | 128 | the same time without having to generate extra clones.</p> |
| 129 | 129 | |
| 130 | 130 | <p>To switch a checkout between different versions and branches, |
| 131 | 131 | use:</p> |
| 132 | 132 | |
| @@ -140,17 +140,17 @@ | ||
| 140 | 140 | version, whereas [/help/checkout | checkout] does not |
| 141 | 141 | automatically sync and does a "hard" switch, overwriting local |
| 142 | 142 | changes if told to do so.</p> |
| 143 | 143 | |
| 144 | 144 | <h2>Configuring Your Local Repository</h2> |
| 145 | - | |
| 145 | + | |
| 146 | 146 | <p>When you create a new repository, either by cloning an existing |
| 147 | 147 | project or create a new project of your own, you usually want to do some |
| 148 | 148 | local configuration. This is easily accomplished using the web-server |
| 149 | 149 | that is built into fossil. Start the fossil webserver like this: |
| 150 | 150 | ([/help/ui | more info])</p> |
| 151 | - | |
| 151 | + | |
| 152 | 152 | <blockquote> |
| 153 | 153 | <b>fossil ui </b><i> repository-filename</i> |
| 154 | 154 | </blockquote> |
| 155 | 155 | |
| 156 | 156 | <p>You can omit the <i>repository-filename</i> from the command above |
| @@ -163,15 +163,15 @@ | ||
| 163 | 163 | where to find your web browser using a command like this:</p> |
| 164 | 164 | |
| 165 | 165 | <blockquote> |
| 166 | 166 | <b>fossil setting web-browser </b><i> path-to-web-browser</i> |
| 167 | 167 | </blockquote> |
| 168 | - | |
| 168 | + | |
| 169 | 169 | <p>By default, fossil does not require a login for HTTP connections |
| 170 | 170 | coming in from the IP loopback address 127.0.0.1. You can, and perhaps |
| 171 | 171 | should, change this after you create a few users.</p> |
| 172 | - | |
| 172 | + | |
| 173 | 173 | <p>When you are finished configuring, just press Control-C or use |
| 174 | 174 | the <b>kill</b> command to shut down the mini-server.</p> |
| 175 | 175 | |
| 176 | 176 | <h2>Making Changes</h2> |
| 177 | 177 | |
| @@ -194,18 +194,18 @@ | ||
| 194 | 194 | <p>You will be prompted for check-in comments using whatever editor |
| 195 | 195 | is specified by your VISUAL or EDITOR environment variable.</p> |
| 196 | 196 | |
| 197 | 197 | In the default configuration, the [/help/commit|commit] |
| 198 | 198 | 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 | |
| 200 | 200 | [./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 | |
| 202 | 202 | commit and push them.</p> |
| 203 | 203 | |
| 204 | 204 | <h2>Sharing Changes</h2> |
| 205 | 205 | |
| 206 | - <p>When [./concepts.wiki#workflow|autosync] is turned off, | |
| 206 | + <p>When [./concepts.wiki#workflow|autosync] is turned off, | |
| 207 | 207 | the changes you [/help/commit | commit] are only |
| 208 | 208 | on your local repository. |
| 209 | 209 | To share those changes with other repositories, do:</p> |
| 210 | 210 | |
| 211 | 211 | <blockquote> |
| @@ -241,11 +241,11 @@ | ||
| 241 | 241 | the <i>VERSION</i>, then fossil moves you to the |
| 242 | 242 | latest version of the branch your are currently on.</p> |
| 243 | 243 | |
| 244 | 244 | <p>The default behavior is for [./concepts.wiki#workflow|autosync] to |
| 245 | 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 | |
| 246 | + when you run [/help/update|update] and a [/help/push|push] happens | |
| 247 | 247 | automatically after you [/help/commit|commit]. So in normal practice, |
| 248 | 248 | the push, pull, and sync commands are rarely used. But it is important |
| 249 | 249 | to know about them, all the same.</p> |
| 250 | 250 | |
| 251 | 251 | <blockquote> |
| @@ -342,11 +342,11 @@ | ||
| 342 | 342 | <li>[./server.wiki#cgi|CGI] |
| 343 | 343 | <li>[./server.wiki#scgi|SCGI] |
| 344 | 344 | </ul> |
| 345 | 345 | |
| 346 | 346 | <p>The [./selfhost.wiki | self-hosting fossil repositories] use |
| 347 | - CGI. | |
| 347 | + CGI. | |
| 348 | 348 | |
| 349 | 349 | <a name="proxy"></a> |
| 350 | 350 | <h2>HTTP Proxies</h2> |
| 351 | 351 | |
| 352 | 352 | <p>If you are behind a restrictive firewall that requires you to use |
| @@ -382,11 +382,11 @@ | ||
| 382 | 382 | <p>Or unset the environment variable. The fossil setting for the |
| 383 | 383 | HTTP proxy takes precedence over the environment variable and the |
| 384 | 384 | command-line option overrides both. If you have an persistent |
| 385 | 385 | proxy setting that you want to override for a one-time sync, that |
| 386 | 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> | |
| 387 | + a co-workers repository on your LAN, you might type:</p> | |
| 388 | 388 | |
| 389 | 389 | <blockquote> |
| 390 | 390 | <b>fossil sync http://192.168.1.36:8080/ --proxy off</b> |
| 391 | 391 | </blockquote> |
| 392 | 392 | |
| 393 | 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 |
| --- 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 @@ | ||
| 5 | 5 | by the creator of Fossil, so of course there is selection bias... |
| 6 | 6 | |
| 7 | 7 | <h2>On The Usability Of Git:</h2> |
| 8 | 8 | |
| 9 | 9 | <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 | |
| 11 | 11 | unusable unless you have the manpage tattooed on you arm. |
| 12 | 12 | |
| 13 | 13 | <blockquote> |
| 14 | 14 | <i>by mml at [http://news.ycombinator.com/item?id=1433387]</i> |
| 15 | 15 | </blockquote> |
| 16 | 16 | |
| 17 | 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 | |
| 18 | +as a point in a high-dimensional "code-space", in which branches are | |
| 19 | 19 | represented as n-dimensional membranes, mapping the spatial loci of |
| 20 | 20 | successive commits onto the projected manifold of each cloned |
| 21 | 21 | repository.</nowiki> |
| 22 | 22 | |
| 23 | 23 | <blockquote> |
| @@ -25,11 +25,11 @@ | ||
| 25 | 25 | </blockquote> |
| 26 | 26 | |
| 27 | 27 | <li>Git is not a Prius. Git is a Model T. |
| 28 | 28 | Its plumbing and wiring sticks out all over the place. |
| 29 | 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. | |
| 30 | +stuck on the side of the road when it breaks down. | |
| 31 | 31 | And it <b>will</b> break down. |
| 32 | 32 | |
| 33 | 33 | <blockquote> |
| 34 | 34 | <i>Nick Farina at [http://nfarina.com/post/9868516270/git-is-simpler]</i> |
| 35 | 35 | </blockquote> |
| @@ -39,11 +39,11 @@ | ||
| 39 | 39 | <blockquote> |
| 40 | 40 | <i>Linus Torvalds - 2005-04-07 22:13:13<br> |
| 41 | 41 | Commit comment on the very first source-code check-in for git |
| 42 | 42 | </blockquote> |
| 43 | 43 | |
| 44 | -<li>I've been experimenting a lot with git at work. | |
| 44 | +<li>I've been experimenting a lot with git at work. | |
| 45 | 45 | Damn, it's complicated. |
| 46 | 46 | It has things to trip you up with that sane people just wouldn't ever both with |
| 47 | 47 | including the ability to allow you to commit stuff in such a way that you can't find |
| 48 | 48 | it again afterwards (!!!) |
| 49 | 49 | Demented workflow complexity on acid? |
| @@ -104,19 +104,19 @@ | ||
| 104 | 104 | |
| 105 | 105 | <blockquote> |
| 106 | 106 | <i>Joe Prostko at [http://www.mail-archive.com/[email protected]/msg16716.html] |
| 107 | 107 | </blockquote> |
| 108 | 108 | |
| 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, | |
| 110 | 110 | such simplicity and flexibility!!! |
| 111 | 111 | |
| 112 | 112 | <blockquote> |
| 113 | 113 | <i>zengr at [http://stackoverflow.com/questions/138621/best-version-control-for-lone-developer]</i> |
| 114 | 114 | </blockquote> |
| 115 | 115 | |
| 116 | 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 | |
| 117 | +server, ticketing system, Wiki pages, and a very, very helpful timeline visualization. And | |
| 118 | 118 | the entire program in a single file! |
| 119 | 119 | |
| 120 | 120 | <blockquote> |
| 121 | 121 | <i>thunderbong commenting on hacker news: [https://news.ycombinator.com/item?id=9131619]</i> |
| 122 | 122 | </blockquote> |
| @@ -127,30 +127,30 @@ | ||
| 127 | 127 | |
| 128 | 128 | <h2>On Git Versus Fossil</h2> |
| 129 | 129 | |
| 130 | 130 | <ol> |
| 131 | 131 | <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.... | |
| 133 | 133 | Also <nowiki>[for]</nowiki> not having a misanthropic command line interface. |
| 134 | 134 | |
| 135 | 135 | <blockquote> |
| 136 | 136 | <i>Joshua Paine at [http://www.mail-archive.com/[email protected]/msg02736.html]</i> |
| 137 | 137 | </blockquote> |
| 138 | 138 | |
| 139 | 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 | |
| 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 | 144 | been a smoother ride than Git was. |
| 145 | 145 | |
| 146 | 146 | <blockquote> |
| 147 | 147 | <i>viablepanic at [http://www.reddit.com/r/programming/comments/bxcto/why_not_fossil_scm/]</i> |
| 148 | 148 | </blockquote> |
| 149 | 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 | |
| 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 | 152 | reflect the unchanging nature of things in that history. |
| 153 | 153 | |
| 154 | 154 | <p>In git (or rather, the git community), the development history is part of |
| 155 | 155 | the published aspect of the project, so it provides tools for rearranging |
| 156 | 156 | that history so you can present what you "should" have done rather |
| 157 | 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 |
| --- 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 @@ | ||
| 1 | 1 | <title>Reviews</title> |
| 2 | 2 | <b>External links:</b> |
| 3 | - | |
| 3 | + | |
| 4 | 4 | * [http://nixtu.blogspot.com/2010/03/fossil-dvcs-on-go-first-impressions.html | |
| 5 | 5 | Fossil DVCS on the Go - First Impressions] |
| 6 | 6 | * [http://blog.mired.org/2011/02/fossil-sweet-spot-in-vcs-space.html | |
| 7 | 7 | Fossil - a sweet spot in the VCS space] by Mike Meyer. |
| 8 | 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 | 22 | |
| 23 | 23 | |
| 24 | 24 | <b>Joshua Paine on 2010-10-22:</b> |
| 25 | 25 | |
| 26 | 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 | |
| 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 | 37 | features. Also not having a misanthropic command line interface. |
| 38 | 38 | </blockquote> |
| 39 | 39 | |
| 40 | 40 | <b>Stephan Beal writes on 2009-01-11:</b> |
| 41 | 41 | |
| 42 | 42 | <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 | |
| 44 | 44 | <a href="http://www.sqlite.org/">sqlite.org</a>. It |
| 45 | 45 | was a good thing I bookmarked it, because I was never able to find the |
| 46 | 46 | link again (it might have been in a bug report or something). The |
| 47 | 47 | reasons I first took a close look at it were (A) it stemmed from the |
| 48 | 48 | sqlite project, which I've held in high regards for years (e.g. I |
| 49 | 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/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 |
+3
-3
| --- www/selfcheck.wiki | ||
| +++ www/selfcheck.wiki | ||
| @@ -14,11 +14,11 @@ | ||
| 14 | 14 | lost. The integrity checks are doing their job well.</p> |
| 15 | 15 | |
| 16 | 16 | <h2>Atomic Check-ins With Rollback</h2> |
| 17 | 17 | |
| 18 | 18 | 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. | |
| 20 | 20 | ([./tech_overview.wiki | Addition information] about the repository |
| 21 | 21 | file format.) |
| 22 | 22 | SQLite is very mature and stable and has been in wide-spread use for many |
| 23 | 23 | years, so we are confident it will not cause repository |
| 24 | 24 | corruption. SQLite |
| @@ -61,11 +61,11 @@ | ||
| 61 | 61 | message is printed and the transaction rolls back. |
| 62 | 62 | |
| 63 | 63 | So, in other words, fossil always checks to make sure it can |
| 64 | 64 | re-extract a file before it commits a change to that file. |
| 65 | 65 | 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 | |
| 67 | 67 | files. |
| 68 | 68 | |
| 69 | 69 | <h2>Checksum Over All Files In A Check-in</h2> |
| 70 | 70 | |
| 71 | 71 | Manifest artifacts that define a check-in have two fields (the |
| @@ -102,7 +102,7 @@ | ||
| 102 | 102 | <a href="http://en.wikipedia.org/wiki/The_Tortoise_and_the_Hare">tortoise</a>: |
| 103 | 103 | reliability is more important than raw speed. The developers of |
| 104 | 104 | fossil see no merit in getting the wrong answer quickly. |
| 105 | 105 | |
| 106 | 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. | |
| 107 | +Fossil runs quickly enough to stay out of the developers way. | |
| 108 | 108 | Most operations complete in under a second. |
| 109 | 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/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 |
+6
-6
| --- www/selfhost.wiki | ||
| +++ www/selfhost.wiki | ||
| @@ -7,23 +7,23 @@ | ||
| 7 | 7 | 2. [http://www2.fossil-scm.org/] |
| 8 | 8 | 3. [http://www3.fossil-scm.org/site.cgi] |
| 9 | 9 | |
| 10 | 10 | |
| 11 | 11 | 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 | |
| 13 | 13 | <a href="http://en.wikipedia.org/wiki/Cron">cron job</a> that invokes |
| 14 | 14 | "fossil sync" at regular intervals. |
| 15 | 15 | |
| 16 | 16 | Note that the two secondary repositories are more than just read-only mirrors. |
| 17 | 17 | 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 | |
| 19 | 19 | on any of the three servers and those changes automatically propagate to the |
| 20 | 20 | other two servers. |
| 21 | 21 | |
| 22 | 22 | Server (1) runs as a CGI script on a |
| 23 | 23 | <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 | |
| 25 | 25 | hosts <a href="http://www.sqlite.org/">SQLite</a> and over a |
| 26 | 26 | dozen other smaller projects. This demonstrates that Fossil can run on |
| 27 | 27 | a low-power host processor. |
| 28 | 28 | Multiple fossil-based projects can easily be hosted on the same machine, |
| 29 | 29 | even if that machine is itself one of several dozen virtual machines on |
| @@ -34,17 +34,17 @@ | ||
| 34 | 34 | #!/usr/bin/fossil |
| 35 | 35 | repository: /fossil/fossil.fossil |
| 36 | 36 | </pre></blockquote> |
| 37 | 37 | |
| 38 | 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. | |
| 39 | +<a href="http://www.he.net/">Hurricane Electric</a> in Fremont, CA. | |
| 40 | 40 | This server demonstrates the ability of |
| 41 | 41 | Fossil to run on an economical shared-host web account with no |
| 42 | 42 | privileges beyond port 80 HTTP access and CGI. It is not necessary |
| 43 | 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 | |
| 44 | +As far as we are aware, | |
| 45 | +Fossil is the only full-featured configuration management system | |
| 46 | 46 | that can run in |
| 47 | 47 | such a restricted environment. The CGI script that runs on the |
| 48 | 48 | Hurricane Electric server is the same as the CGI script shown above, |
| 49 | 49 | except that the pathnames are modified to suit the environment: |
| 50 | 50 | |
| 51 | 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 |
| --- 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 @@ | ||
| 2 | 2 | <h2>Introduction</h2><blockquote> |
| 3 | 3 | <p>A server is not necessary to use Fossil, but a server does help in collaborating with |
| 4 | 4 | peers. A Fossil server also works well as a complete website for a project. |
| 5 | 5 | For example, the complete [https://www.fossil-scm.org/] website, including the |
| 6 | 6 | 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 | |
| 8 | 8 | self-hosting repository for Fossil.</p> |
| 9 | 9 | <p>This article is a guide for setting up your own Fossil server. |
| 10 | 10 | <p>See "[./aboutcgi.wiki|How CGI Works In Fossil]" for background |
| 11 | 11 | information on the underlying CGI technology. |
| 12 | 12 | See "[./sync.wiki|The Fossil Sync Protocol]" for information on the |
| @@ -18,11 +18,11 @@ | ||
| 18 | 18 | <li>A stand-alone server |
| 19 | 19 | <li>Using inetd or xinetd or stunnel |
| 20 | 20 | <li>CGI |
| 21 | 21 | <li>SCGI (a.k.a. SimpleCGI) |
| 22 | 22 | </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 | |
| 24 | 24 | containing many repositories with names ending in ".fossil". |
| 25 | 25 | </blockquote> |
| 26 | 26 | <a name="standalone"></a> |
| 27 | 27 | <h2>Standalone server</h2><blockquote> |
| 28 | 28 | The easiest way to set up a Fossil server is to use either the |
| @@ -34,11 +34,11 @@ | ||
| 34 | 34 | <p> |
| 35 | 35 | The <i>REPOSITORY</i> argument is either the name of the repository file, or |
| 36 | 36 | a directory containing many repositories. |
| 37 | 37 | Both of these commands start a Fossil server, usually on TCP port 8080, though |
| 38 | 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 | |
| 39 | +access these using URLs of the form <b>http://localhost:8080/</b>, or if | |
| 40 | 40 | <i>REPOSITORY</i> is a directory, URLs of the form |
| 41 | 41 | <b>http://localhost:8080/</b><i>repo</i><b>/</b> where <i>repo</i> is the base |
| 42 | 42 | name of the repository file without the ".fossil" suffix. |
| 43 | 43 | The difference between "ui" and "server" is that "ui" will |
| 44 | 44 | also start a web browser and point it |
| @@ -75,23 +75,23 @@ | ||
| 75 | 75 | need to modify the pathnames for your particular setup. |
| 76 | 76 | The final argument is either the name of the fossil repository to be served, |
| 77 | 77 | or a directory containing multiple repositories. |
| 78 | 78 | </p> |
| 79 | 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 | |
| 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 | 82 | numeric, add the desired name and port to /etc/services. For example, if |
| 83 | 83 | you want your Fossil server running on TCP port 12345 instead of 80, you |
| 84 | 84 | will need to add: |
| 85 | 85 | <blockquote> |
| 86 | 86 | <pre> |
| 87 | 87 | fossil 12345/tcp #fossil server |
| 88 | 88 | </pre> |
| 89 | 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 | |
| 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 | 93 | case you use FreeBSD. |
| 94 | 94 | </p> |
| 95 | 95 | <p> |
| 96 | 96 | If your system is running xinetd, then the configuration is likely to be |
| 97 | 97 | in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d". |
| @@ -119,11 +119,11 @@ | ||
| 119 | 119 | jail for the user who owns the fossil repository before reading any information |
| 120 | 120 | off of the wire. |
| 121 | 121 | </p> |
| 122 | 122 | <p> |
| 123 | 123 | 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. | |
| 125 | 125 | </p> |
| 126 | 126 | <p> |
| 127 | 127 | [https://www.stunnel.org/ | Stunnel version 5] is an inetd-like process that |
| 128 | 128 | accepts and decodes SSL-encrypted connections. Fossil can be run directly from |
| 129 | 129 | stunnel in a manner similar to inetd and xinetd. This can be used to provide |
| @@ -137,15 +137,15 @@ | ||
| 137 | 137 | TIMEOUTclose = 0 |
| 138 | 138 | exec = /usr/bin/fossil |
| 139 | 139 | execargs = /usr/bin/fossil http /home/fossil/ubercool.fossil --https |
| 140 | 140 | </nowiki></pre></blockquote> |
| 141 | 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 | |
| 142 | +configuration file. Note that the [/help/http|fossil http] command should include | |
| 143 | 143 | the --https option to let Fossil know to use "https" instead of "http" as the scheme |
| 144 | 144 | on generated hyperlinks. |
| 145 | 145 | <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 | |
| 147 | 147 | than the "standalone" server, but it has the |
| 148 | 148 | advantage of only using system resources when an actual connection is |
| 149 | 149 | attempted. If no-one ever connects to that port, a Fossil server will |
| 150 | 150 | not (automatically) run. It has the disadvantage of requiring "root" access |
| 151 | 151 | and therefore may not normally be available to lower-priced "shared" servers |
| @@ -155,11 +155,11 @@ | ||
| 155 | 155 | <a name="cgi"></a> |
| 156 | 156 | <h2>Fossil as CGI</h2><blockquote> |
| 157 | 157 | <p> |
| 158 | 158 | A Fossil server can also be run from an ordinary web server as a CGI program. |
| 159 | 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 | |
| 160 | +CGI is how the [./selfhost.wiki | self-hosting fossil repositories] are | |
| 161 | 161 | implemented. |
| 162 | 162 | </p> |
| 163 | 163 | <p> |
| 164 | 164 | To run Fossil as CGI, create a CGI script (here called "repo") in the CGI directory |
| 165 | 165 | of your web server and having content like this: |
| @@ -184,12 +184,12 @@ | ||
| 184 | 184 | script itself must be executable for the user under which it will run (which often differs |
| 185 | 185 | from the one running the web server - consult your site's documentation or administrator).</li> |
| 186 | 186 | <li>The repository file AND the directory containing it must be writable by the same account |
| 187 | 187 | which executes the Fossil binary (again, this might differ from the WWW user). The directory |
| 188 | 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 | |
| 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 | 191 | a chroot, ensure that this directory exists and is readable/writeable |
| 192 | 192 | by the user who executes the Fossil binary.</li> |
| 193 | 193 | </ul> |
| 194 | 194 | </p> |
| 195 | 195 | |
| @@ -219,11 +219,11 @@ | ||
| 219 | 219 | |
| 220 | 220 | <a name="scgi"></a> |
| 221 | 221 | <h2>Fossil as SCGI</h2><blockquote> |
| 222 | 222 | |
| 223 | 223 | <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 | |
| 225 | 225 | starting a stand-alone web server, can also be used for SCGI. Simply add |
| 226 | 226 | the --scgi command-line option and the stand-alone server will interpret |
| 227 | 227 | and respond to the SimpleCGI or SCGI protocol rather than raw HTTP. This can |
| 228 | 228 | be used in combination with a webserver (such as [http://nginx.org|Nginx]) |
| 229 | 229 | that does not support CGI. A typical Nginx configuration to support SCGI |
| @@ -284,27 +284,27 @@ | ||
| 284 | 284 | </blockquote> |
| 285 | 285 | |
| 286 | 286 | <a name="loadmgmt"></a> |
| 287 | 287 | <h2>Managing Server Load</h2><blockquote> |
| 288 | 288 | <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 | |
| 290 | 290 | load on the server. |
| 291 | 291 | The Fossil [./selfhost.wiki | self-hosting server] is a 1/24th slice VM at |
| 292 | 292 | [http://www.linode.com | Linode.com] hosting 65 other repositories in |
| 293 | 293 | addition to Fossil (and including some very high-traffic sites such |
| 294 | 294 | as [http://www.sqlite.org] and [http://system.data.sqlite.org]) and |
| 295 | 295 | it has a typical load of 0.05 to 0.1. A single HTTP request to Fossil |
| 296 | 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 | |
| 297 | +requests can be arriving at a continuous rate of 20 or more per second | |
| 298 | 298 | and the CPU can still be mostly idle. |
| 299 | 299 | <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 | |
| 301 | 301 | amounts of CPU time, especially on repositories with a large number |
| 302 | 302 | of files or with long revision histories. High CPU usage pages include |
| 303 | 303 | [/help?cmd=/zip | /zip], [/help?cmd=/tarball | /tarball], |
| 304 | 304 | [/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. | |
| 306 | 306 | If these kinds of requests arrive too quickly, the load average on the |
| 307 | 307 | server can grow dramatically, making the server unresponsive. |
| 308 | 308 | <p> |
| 309 | 309 | Fossil provides two capabilities to help avoid server overload problems |
| 310 | 310 | due to excessive requests to expensive pages: |
| @@ -312,11 +312,11 @@ | ||
| 312 | 312 | <li><p>An optional cache is available that remembers the 10 most recently |
| 313 | 313 | requested /zip or /tarball pages and returns the precomputed answer |
| 314 | 314 | if the same page is requested again. |
| 315 | 315 | <li><p>Page requests can be configured to fail with a |
| 316 | 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 | |
| 317 | + HTTP error if an expensive request is received while the host load | |
| 318 | 318 | average is too high. |
| 319 | 319 | </ol> |
| 320 | 320 | Both of these load-control mechanisms are turned off by default, but they |
| 321 | 321 | are recommended for high-traffic sites. |
| 322 | 322 | <p> |
| 323 | 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/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 |
+3
-3
| --- www/settings.wiki | ||
| +++ www/settings.wiki | ||
| @@ -4,11 +4,11 @@ | ||
| 4 | 4 | |
| 5 | 5 | Settings control the behaviour of fossil. They are set with the |
| 6 | 6 | <tt>fossil settings</tt> command, or through the web interface in |
| 7 | 7 | the Settings page in the Admin section. |
| 8 | 8 | |
| 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 | |
| 10 | 10 | <tt>fossil help settings</tt> from the command line. |
| 11 | 11 | |
| 12 | 12 | |
| 13 | 13 | <h3>Repository settings</h3> |
| 14 | 14 | |
| @@ -16,17 +16,17 @@ | ||
| 16 | 16 | a subset of settings are copied to your local repository. |
| 17 | 17 | |
| 18 | 18 | If you make a change to a setting on your local repository, it is not |
| 19 | 19 | synced back to the server when you <tt>push</tt> or <tt>sync</tt>. If |
| 20 | 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. | |
| 21 | +all repositories which are cloned from this repository. | |
| 22 | 22 | |
| 23 | 23 | You can also set a setting globally on your local machine. The value |
| 24 | 24 | will be used for all repositories cloned to your machine, unless |
| 25 | 25 | overridden explicitly in a particular repository. Global settings can be |
| 26 | 26 | set by using the <tt>-global</tt> option on the <tt>fossil settings</tt> |
| 27 | -command. | |
| 27 | +command. | |
| 28 | 28 | |
| 29 | 29 | <h3>"Versionable" settings</h3> |
| 30 | 30 | |
| 31 | 31 | Most of the settings control the behaviour of fossil on your local |
| 32 | 32 | machine, largely acting to reflect your preference on how you want to |
| 33 | 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 |
| --- 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 @@ | ||
| 2 | 2 | <h1 align="center">Deleting Content From Fossil</h1> |
| 3 | 3 | |
| 4 | 4 | Fossil is designed to keep all historical content forever. Users |
| 5 | 5 | of Fossil are discouraged from "deleting" content simply because it |
| 6 | 6 | 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. | |
| 8 | 8 | Such is the design intent of Fossil. |
| 9 | 9 | |
| 10 | 10 | Nevertheless, there may occasionally arise legitimate reasons for |
| 11 | 11 | deleting content. Such reasons might include: |
| 12 | 12 | |
| @@ -21,35 +21,35 @@ | ||
| 21 | 21 | disrupting the operation of Fossil. |
| 22 | 22 | |
| 23 | 23 | <h2>Shunning</h2> |
| 24 | 24 | |
| 25 | 25 | Fossil provides a mechanism called "shunning" for removing content from |
| 26 | -a repository. | |
| 26 | +a repository. | |
| 27 | 27 | |
| 28 | 28 | Every Fossil repository maintains a list of the SHA1 hash names of |
| 29 | 29 | "shunned" artifacts. |
| 30 | -Fossil will refuse to push or pull any shunned artifact. | |
| 30 | +Fossil will refuse to push or pull any shunned artifact. | |
| 31 | 31 | Furthermore, all shunned artifacts (but not the shunning list |
| 32 | 32 | itself) are removed from the |
| 33 | 33 | repository whenever the repository is reconstructed using the |
| 34 | 34 | "rebuild" command. |
| 35 | 35 | |
| 36 | 36 | <h3>Shunning lists are local state</h3> |
| 37 | 37 | |
| 38 | 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 | |
| 39 | +In other words, shunning does not propagate to a remote repository | |
| 40 | 40 | using the normal "sync" mechanism. An artifact can be |
| 41 | 41 | shunned from one repository but be allowed to exist in another. The fact that |
| 42 | 42 | the shunning list does not propagate is a security feature. If the |
| 43 | 43 | shunning list propagated then a malicious user (or |
| 44 | 44 | 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 | |
| 46 | 46 | 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 | |
| 48 | 48 | information from your personal repositories without your permission. |
| 49 | 49 | |
| 50 | -The shunning list does not propagate to a remote repository | |
| 50 | +The shunning list does not propagate to a remote repository | |
| 51 | 51 | by the normal "sync" mechanism, |
| 52 | 52 | but it is still possible to copy shuns from one repository to another |
| 53 | 53 | using the "configuration" command: |
| 54 | 54 | |
| 55 | 55 | <b>fossil configuration pull shun</b> <i>remote-url</i><br> |
| @@ -56,12 +56,12 @@ | ||
| 56 | 56 | <b>fossil configuration push shun</b> <i>remote-url</i> |
| 57 | 57 | |
| 58 | 58 | The two command above will pull or push shunning lists from or to |
| 59 | 59 | the <i>remote-url</i> indicated and merge the lists on the receiving |
| 60 | 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 | |
| 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 | 63 | disabled by the "<tt>auto-shun</tt>" setting. |
| 64 | 64 | |
| 65 | 65 | Note that the shunning list remains in the repository even after the |
| 66 | 66 | shunned artifact has been removed. This is to prevent the artifact |
| 67 | 67 | from being reintroduced into the repository the next time it syncs with |
| @@ -68,11 +68,11 @@ | ||
| 68 | 68 | another repository that has not shunned the artifact. |
| 69 | 69 | |
| 70 | 70 | <h3>Managing the shunning list</h3> |
| 71 | 71 | |
| 72 | 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. | |
| 73 | +with "admin" privilege on the "/shun" URL of the web interface to Fossil. | |
| 74 | 74 | That URL is accessible under the "Admin" button on the default menu |
| 75 | 75 | bar. Items can be added to or removed from the shunning list. "Sync" |
| 76 | 76 | operations are inhibited as soon as the artifact is added to the |
| 77 | 77 | shunning list, but the content of the artifact is not actually removed |
| 78 | 78 | from the repository until the next time the repository is rebuilt. |
| 79 | 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 |
| --- 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 @@ | ||
| 1 | 1 | <title>Fossil Performance</title> |
| 2 | 2 | <h1 align="center">Performance Statistics</h1> |
| 3 | 3 | |
| 4 | -The questions will inevitably arise: How does Fossil perform? | |
| 4 | +The questions will inevitably arise: How does Fossil perform? | |
| 5 | 5 | Does it use a lot of disk space or bandwidth? Is it scalable? |
| 6 | 6 | |
| 7 | 7 | In an attempt to answers these questions, this report looks at several |
| 8 | 8 | projects that use fossil for configuration management and examines how |
| 9 | 9 | well they are working. The following table is a summary of the results. |
| @@ -96,21 +96,21 @@ | ||
| 96 | 96 | every ticket, and every check-in is a separate "artifact". One way to |
| 97 | 97 | think of a Fossil project is as a bag of artifacts. Of course, there is |
| 98 | 98 | a lot more than this going on in Fossil. Many of the artifacts have meaning |
| 99 | 99 | and are related to other artifacts. But at a low level (for example when |
| 100 | 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 | |
| 101 | +is the unordered collection of artifacts. In fact, one of the key | |
| 102 | 102 | characteristics of Fossil is that the entire project history can be |
| 103 | 103 | reconstructed simply by scanning the artifacts in an arbitrary order. |
| 104 | 104 | |
| 105 | 105 | The number of check-ins is the number of times that the "commit" command |
| 106 | 106 | has been run. A single check-in might change a 3 or 4 files, or it might |
| 107 | 107 | change dozens or hundreds of files. Regardless of the number of files |
| 108 | 108 | changed, it still only counts as one check-in. |
| 109 | 109 | |
| 110 | 110 | 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 | |
| 112 | 112 | separately on the disk. Fossil makes use of delta compression between related |
| 113 | 113 | versions of the same file, and then uses zlib compression on the resulting |
| 114 | 114 | deltas. The total resulting repository size is shown after the uncompressed |
| 115 | 115 | size. |
| 116 | 116 | |
| 117 | 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 |
| --- 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 @@ | ||
| 1 | 1 | <title>The Fossil Sync Protocol</title> |
| 2 | 2 | |
| 3 | -<p>This document describes the wire protocol used to synchronize | |
| 3 | +<p>This document describes the wire protocol used to synchronize | |
| 4 | 4 | content between two Fossil repositories.</p> |
| 5 | 5 | |
| 6 | 6 | <h2>1.0 Overview</h2> |
| 7 | 7 | |
| 8 | 8 | <p>The global state of a fossil repository consists of an unordered |
| @@ -22,11 +22,11 @@ | ||
| 22 | 22 | shared to a few hundred.</p> |
| 23 | 23 | |
| 24 | 24 | <p>Each repository also has local state. The local state determines |
| 25 | 25 | the web-page formatting preferences, authorized users, ticket formats, |
| 26 | 26 | 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, | |
| 28 | 28 | some local state is transferred during a [/help?cmd=clone|clone] |
| 29 | 29 | in order to initialize the local state of the new repository. And |
| 30 | 30 | the [/help?cmd=configuration|config push] and |
| 31 | 31 | [/help?cmd=configuration|config pull] |
| 32 | 32 | commands can be an administrator to sync local state.</p> |
| @@ -40,15 +40,15 @@ | ||
| 40 | 40 | request.</p> |
| 41 | 41 | |
| 42 | 42 | <p>The server might be running as an independent server |
| 43 | 43 | using the <b>server</b> command, or it might be launched from |
| 44 | 44 | inetd or xinetd using the <b>http</b> command. Or the server might |
| 45 | -be launched from CGI. | |
| 45 | +be launched from CGI. | |
| 46 | 46 | (See "[./server.wiki|How To Configure A Fossil Server]" for details.) |
| 47 | 47 | The specifics of how the server listens |
| 48 | 48 | 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 | |
| 50 | 50 | the client is the issuer of the requests.</p> |
| 51 | 51 | |
| 52 | 52 | <p>A single push, pull, or sync might involve multiple HTTP requests. |
| 53 | 53 | The client maintains state between all requests. But on the server |
| 54 | 54 | side, each request is independent. The server does not preserve |
| @@ -55,11 +55,11 @@ | ||
| 55 | 55 | any information about the client from one request to the next.</p> |
| 56 | 56 | |
| 57 | 57 | <h4>2.0.1 Encrypted Transport</h4> |
| 58 | 58 | |
| 59 | 59 | <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 | |
| 61 | 61 | clear-text HTTP requests or encrypted HTTPS requests. But when |
| 62 | 62 | HTTPS requests are sent, they first must be decrypted by a webserver |
| 63 | 63 | or proxy before being passed to the Fossil server. This limitation |
| 64 | 64 | may be relaxed in a future release.</p> |
| 65 | 65 | |
| @@ -408,11 +408,11 @@ | ||
| 408 | 408 | <b>uvigot</b> <i>name mtime hash size</i> |
| 409 | 409 | </blockquote> |
| 410 | 410 | |
| 411 | 411 | <p>The <i>name</i> argument is the name of an unversioned file. |
| 412 | 412 | The <i>mtime</i> is the last modification time of the unversioned file |
| 413 | -in seconds since 1970. | |
| 413 | +in seconds since 1970. | |
| 414 | 414 | The <i>hash</i> is the SHA1 hash of the unversioned file content, or |
| 415 | 415 | "<b>-</b>" if the file has been deleted. |
| 416 | 416 | The <i>size</i> is the uncompressed size of the file in bytes. |
| 417 | 417 | |
| 418 | 418 | <p>When the server sees a "pragma uv-hash" card for which the hash |
| 419 | 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 |
| --- 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 @@ | ||
| 174 | 174 | * tclInvoke |
| 175 | 175 | * tclIsSafe |
| 176 | 176 | * tclMakeSafe |
| 177 | 177 | * tclReady |
| 178 | 178 | * trace |
| 179 | + * unversioned content | |
| 180 | + * unversioned list | |
| 179 | 181 | * utime |
| 180 | 182 | * verifyCsrf |
| 181 | 183 | * wiki |
| 182 | 184 | |
| 183 | 185 | Each of the commands above is documented by a block comment above their |
| @@ -610,10 +612,27 @@ | ||
| 610 | 612 | ------------------------------------- |
| 611 | 613 | |
| 612 | 614 | * trace STRING |
| 613 | 615 | |
| 614 | 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. | |
| 615 | 634 | |
| 616 | 635 | <a name="utime"></a>TH1 utime Command |
| 617 | 636 | ------------------------------------- |
| 618 | 637 | |
| 619 | 638 | * utime |
| 620 | 639 |
| --- 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 |
+5
-5
| --- www/theory1.wiki | ||
| +++ www/theory1.wiki | ||
| @@ -16,18 +16,18 @@ | ||
| 16 | 16 | |
| 17 | 17 | <h2>Fossil Is A NoSQL Database</h2> |
| 18 | 18 | |
| 19 | 19 | We begin with the first question: Fossil is not based on a distributed |
| 20 | 20 | 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. | |
| 22 | 22 | The current implementation of Fossil uses |
| 23 | 23 | SQLite as a local store for the content of the distributed database and as |
| 24 | 24 | a cache for meta-information about the distributed database that is precomputed |
| 25 | 25 | for quick and easy presentation. But the use of SQLite in this role is an |
| 26 | 26 | implementation detail and is not fundamental to the design. Some future |
| 27 | 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. | |
| 28 | +a key/value database in place of SQLite. | |
| 29 | 29 | (Actually, that is very unlikely |
| 30 | 30 | to happen since SQLite works amazingly well in its current role, but the point |
| 31 | 31 | is that omitting SQLite from Fossil is a theoretical possibility.) |
| 32 | 32 | |
| 33 | 33 | The underlying database that Fossil implements has nothing to do with |
| @@ -64,11 +64,11 @@ | ||
| 64 | 64 | a NoSQL database) and there is the local relational database. The |
| 65 | 65 | bag-of-artifacts database has a fixed format and is what defines a Fossil |
| 66 | 66 | repository. Fossil will never modify the file format of the bag-of-artifacts |
| 67 | 67 | database in an incompatible way because to do so would be to make something |
| 68 | 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. | |
| 69 | +is a cache that contains information derived from the bag-of-artifacts. | |
| 70 | 70 | The schema of the local relational database changes from time to time as |
| 71 | 71 | the Fossil implementation is enhanced, and the content is recomputed from |
| 72 | 72 | the unchanging bag of artifacts. The local relational database is an |
| 73 | 73 | implementation detail which currently happens to use SQLite. |
| 74 | 74 | |
| @@ -89,11 +89,11 @@ | ||
| 89 | 89 | the first question. |
| 90 | 90 | |
| 91 | 91 | <h2>SQL Is A High-Level Scripting Language</h2> |
| 92 | 92 | |
| 93 | 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) | |
| 94 | +language. But that is not true. Fossil uses SQL (as implemented by SQLite) | |
| 95 | 95 | as its scripting language. |
| 96 | 96 | |
| 97 | 97 | This misunderstanding likely arises because people fail |
| 98 | 98 | to appreciate that SQL is a programming language. People are taught that SQL |
| 99 | 99 | is a "query language" as if that were somehow different from a |
| @@ -125,11 +125,11 @@ | ||
| 125 | 125 | out using SQL statements. It is true that these SQL statements are glued |
| 126 | 126 | together with C code, but it turns out that C works surprisingly well in |
| 127 | 127 | that role. Several early prototypes of Fossil were written in a scripting |
| 128 | 128 | language (TCL). We normally find that TCL programs are shorter than the |
| 129 | 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 | |
| 130 | +the use of TCL was actually making the code longer and more difficult to | |
| 131 | 131 | understand. |
| 132 | 132 | And so in the final design, we switched from TCL to C in order to make |
| 133 | 133 | the code easier to implement and debug. |
| 134 | 134 | |
| 135 | 135 | Without the advantages of having SQLite built in, the design might well |
| 136 | 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/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 |
+4
-4
| --- www/wikitheory.wiki | ||
| +++ www/wikitheory.wiki | ||
| @@ -34,26 +34,26 @@ | ||
| 34 | 34 | the wiki page will fork. The web interface will display whichever edit |
| 35 | 35 | was checked in last. The other edit can be found in the history. The |
| 36 | 36 | file format will support merging the branches back together, but there |
| 37 | 37 | is no mechanism in the user interface (yet) to perform the merge. |
| 38 | 38 | |
| 39 | -Every change to a wiki page is a separate | |
| 39 | +Every change to a wiki page is a separate | |
| 40 | 40 | [./fileformat.wiki | control artifact] |
| 41 | 41 | of type [./fileformat.wiki#wikichng | "Wiki Page"]. |
| 42 | 42 | |
| 43 | 43 | <h2>Embedded Documentation</h2> |
| 44 | 44 | |
| 45 | 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. | |
| 46 | +can be accessed and displayed using special URLs to the fossil server. | |
| 47 | 47 | 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 | |
| 49 | 49 | online. (Details are described [./embeddeddoc.wiki | separately].) |
| 50 | 50 | |
| 51 | 51 | Some projects prefer to store their documentation in wiki. There is nothing |
| 52 | 52 | wrong with that. But other projects prefer to keep documentation as part |
| 53 | 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. | |
| 54 | +so that only developers with check-in privileges can change it. | |
| 55 | 55 | Embedded documentation serves this latter purpose. Both forms of documentation |
| 56 | 56 | use the exact same markup. Some projects may choose to |
| 57 | 57 | use both forms of documentation at the same time. Because the same |
| 58 | 58 | format is used, it is trivial to move a file from wiki to embedded documentation |
| 59 | 59 | or back again as the project evolves. |
| 60 | 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 |
| --- 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 |