Fossil SCM

Merged in UUID-renaming changes from trunk.

graham 2020-05-30 19:32 ui-local-diff merge
Commit 1fd9acb97c6dc73a56cda356b5bb5e5a89e18a5f7915b242a54252f3905ebe1d
--- skins/blitz/ticket.txt
+++ skins/blitz/ticket.txt
@@ -1,8 +1,8 @@
11
<h4>$<title></h4>
22
<table class="tktDsp">
3
-<tr><td class="tktDspLabel">Ticket&nbsp;UUID</td>
3
+<tr><td class="tktDspLabel">Ticket&nbsp;Hash</td>
44
<th1>
55
if {[info exists tkt_uuid]} {
66
if {[hascap s]} {
77
html "<td class='tktDspValue' colspan='3'>$tkt_uuid "
88
html "($tkt_id)</td></tr>\n"
99
--- skins/blitz/ticket.txt
+++ skins/blitz/ticket.txt
@@ -1,8 +1,8 @@
1 <h4>$<title></h4>
2 <table class="tktDsp">
3 <tr><td class="tktDspLabel">Ticket&nbsp;UUID</td>
4 <th1>
5 if {[info exists tkt_uuid]} {
6 if {[hascap s]} {
7 html "<td class='tktDspValue' colspan='3'>$tkt_uuid "
8 html "($tkt_id)</td></tr>\n"
9
--- skins/blitz/ticket.txt
+++ skins/blitz/ticket.txt
@@ -1,8 +1,8 @@
1 <h4>$<title></h4>
2 <table class="tktDsp">
3 <tr><td class="tktDspLabel">Ticket&nbsp;Hash</td>
4 <th1>
5 if {[info exists tkt_uuid]} {
6 if {[hascap s]} {
7 html "<td class='tktDspValue' colspan='3'>$tkt_uuid "
8 html "($tkt_id)</td></tr>\n"
9
--- skins/blitz_no_logo/ticket.txt
+++ skins/blitz_no_logo/ticket.txt
@@ -1,8 +1,8 @@
11
<h4>$<title></h4>
22
<table class="tktDsp">
3
-<tr><td class="tktDspLabel">Ticket&nbsp;UUID</td>
3
+<tr><td class="tktDspLabel">Ticket&nbsp;Hash</td>
44
<th1>
55
if {[info exists tkt_uuid]} {
66
if {[hascap s]} {
77
html "<td class='tktDspValue' colspan='3'>$tkt_uuid "
88
html "($tkt_id)</td></tr>\n"
99
--- skins/blitz_no_logo/ticket.txt
+++ skins/blitz_no_logo/ticket.txt
@@ -1,8 +1,8 @@
1 <h4>$<title></h4>
2 <table class="tktDsp">
3 <tr><td class="tktDspLabel">Ticket&nbsp;UUID</td>
4 <th1>
5 if {[info exists tkt_uuid]} {
6 if {[hascap s]} {
7 html "<td class='tktDspValue' colspan='3'>$tkt_uuid "
8 html "($tkt_id)</td></tr>\n"
9
--- skins/blitz_no_logo/ticket.txt
+++ skins/blitz_no_logo/ticket.txt
@@ -1,8 +1,8 @@
1 <h4>$<title></h4>
2 <table class="tktDsp">
3 <tr><td class="tktDspLabel">Ticket&nbsp;Hash</td>
4 <th1>
5 if {[info exists tkt_uuid]} {
6 if {[hascap s]} {
7 html "<td class='tktDspValue' colspan='3'>$tkt_uuid "
8 html "($tkt_id)</td></tr>\n"
9
+19 -15
--- src/attach.c
+++ src/attach.c
@@ -23,19 +23,22 @@
2323
2424
/*
2525
** WEBPAGE: attachlist
2626
** List attachments.
2727
**
28
-** tkt=TICKETUUID
28
+** tkt=HASH
2929
** page=WIKIPAGE
30
+** technote=HASH
31
+**
32
+** At most one of technote=, tkt= or page= may be supplied.
33
+**
34
+** If none are given, all attachments are listed. If one is given, only
35
+** attachments for the designated technote, ticket or wiki page are shown.
3036
**
31
-** At most one of technote=, tkt= or page= are supplied.
32
-** If none is given, all attachments are listed. If one is given,
33
-** only attachments for the designated technote, ticket or wiki page
34
-** are shown. TECHNOTEUUID and TICKETUUID may be just a prefix of the
35
-** relevant technical note or ticket, in which case all attachments
36
-** of all technical notes or tickets with the prefix will be listed.
37
+** HASH may be just a prefix of the relevant technical note or ticket
38
+** artifact hash, in which case all attachments of all technical notes or
39
+** tickets with the prefix will be listed.
3740
*/
3841
void attachlist_page(void){
3942
const char *zPage = P("page");
4043
const char *zTkt = P("tkt");
4144
const char *zTechNote = P("technote");
@@ -152,15 +155,16 @@
152155
** WEBPAGE: attachdownload
153156
** WEBPAGE: attachimage
154157
** WEBPAGE: attachview
155158
**
156159
** Download or display an attachment.
160
+**
157161
** Query parameters:
158162
**
159
-** tkt=TICKETUUID
163
+** tkt=HASH
160164
** page=WIKIPAGE
161
-** technote=TECHNOTEUUID
165
+** technote=HASH
162166
** file=FILENAME
163167
** attachid=ID
164168
**
165169
*/
166170
void attachview_page(void){
@@ -250,11 +254,11 @@
250254
/*
251255
** Commit a new attachment into the repository
252256
*/
253257
void attach_commit(
254258
const char *zName, /* The filename of the attachment */
255
- const char *zTarget, /* The artifact uuid to attach to */
259
+ const char *zTarget, /* The artifact hash to attach to */
256260
const char *aContent, /* The content of the attachment */
257261
int szContent, /* The length of the attachment */
258262
int needModerator, /* Moderate the attachment? */
259263
const char *zComment /* The comment for the attachment */
260264
){
@@ -305,13 +309,13 @@
305309
306310
/*
307311
** WEBPAGE: attachadd
308312
** Add a new attachment.
309313
**
310
-** tkt=TICKETUUID
314
+** tkt=HASH
311315
** page=WIKIPAGE
312
-** technote=TECHNOTEUUID
316
+** technote=HASH
313317
** from=URL
314318
**
315319
*/
316320
void attachadd_page(void){
317321
const char *zPage = P("page");
@@ -420,14 +424,14 @@
420424
*/
421425
void ainfo_page(void){
422426
int rid; /* RID for the control artifact */
423427
int ridSrc; /* RID for the attached file */
424428
char *zDate; /* Date attached */
425
- const char *zUuid; /* UUID of the control artifact */
429
+ const char *zUuid; /* Hash of the control artifact */
426430
Manifest *pAttach; /* Parse of the control artifact */
427431
const char *zTarget; /* Wiki, ticket or tech note attached to */
428
- const char *zSrc; /* UUID of the attached file */
432
+ const char *zSrc; /* Hash of the attached file */
429433
const char *zName; /* Name of the attached file */
430434
const char *zDesc; /* Description of the attached file */
431435
const char *zWikiName = 0; /* Wiki page name when attached to Wiki */
432436
const char *zTNUuid = 0; /* Tech Note ID when attached to tech note */
433437
const char *zTktUuid = 0; /* Ticket ID when attached to a ticket */
@@ -763,11 +767,11 @@
763767
}
764768
blob_read_from_file(&content, zFile, ExtFILE);
765769
user_select();
766770
attach_commit(
767771
zFile, /* The filename of the attachment */
768
- zTarget, /* The artifact uuid to attach to */
772
+ zTarget, /* The artifact hash to attach to */
769773
blob_buffer(&content), /* The content of the attachment */
770774
blob_size(&content), /* The length of the attachment */
771775
0, /* No need to moderate the attachment */
772776
"" /* Empty attachment comment */
773777
);
774778
--- src/attach.c
+++ src/attach.c
@@ -23,19 +23,22 @@
23
24 /*
25 ** WEBPAGE: attachlist
26 ** List attachments.
27 **
28 ** tkt=TICKETUUID
29 ** page=WIKIPAGE
 
 
 
 
 
 
30 **
31 ** At most one of technote=, tkt= or page= are supplied.
32 ** If none is given, all attachments are listed. If one is given,
33 ** only attachments for the designated technote, ticket or wiki page
34 ** are shown. TECHNOTEUUID and TICKETUUID may be just a prefix of the
35 ** relevant technical note or ticket, in which case all attachments
36 ** of all technical notes or tickets with the prefix will be listed.
37 */
38 void attachlist_page(void){
39 const char *zPage = P("page");
40 const char *zTkt = P("tkt");
41 const char *zTechNote = P("technote");
@@ -152,15 +155,16 @@
152 ** WEBPAGE: attachdownload
153 ** WEBPAGE: attachimage
154 ** WEBPAGE: attachview
155 **
156 ** Download or display an attachment.
 
157 ** Query parameters:
158 **
159 ** tkt=TICKETUUID
160 ** page=WIKIPAGE
161 ** technote=TECHNOTEUUID
162 ** file=FILENAME
163 ** attachid=ID
164 **
165 */
166 void attachview_page(void){
@@ -250,11 +254,11 @@
250 /*
251 ** Commit a new attachment into the repository
252 */
253 void attach_commit(
254 const char *zName, /* The filename of the attachment */
255 const char *zTarget, /* The artifact uuid to attach to */
256 const char *aContent, /* The content of the attachment */
257 int szContent, /* The length of the attachment */
258 int needModerator, /* Moderate the attachment? */
259 const char *zComment /* The comment for the attachment */
260 ){
@@ -305,13 +309,13 @@
305
306 /*
307 ** WEBPAGE: attachadd
308 ** Add a new attachment.
309 **
310 ** tkt=TICKETUUID
311 ** page=WIKIPAGE
312 ** technote=TECHNOTEUUID
313 ** from=URL
314 **
315 */
316 void attachadd_page(void){
317 const char *zPage = P("page");
@@ -420,14 +424,14 @@
420 */
421 void ainfo_page(void){
422 int rid; /* RID for the control artifact */
423 int ridSrc; /* RID for the attached file */
424 char *zDate; /* Date attached */
425 const char *zUuid; /* UUID of the control artifact */
426 Manifest *pAttach; /* Parse of the control artifact */
427 const char *zTarget; /* Wiki, ticket or tech note attached to */
428 const char *zSrc; /* UUID of the attached file */
429 const char *zName; /* Name of the attached file */
430 const char *zDesc; /* Description of the attached file */
431 const char *zWikiName = 0; /* Wiki page name when attached to Wiki */
432 const char *zTNUuid = 0; /* Tech Note ID when attached to tech note */
433 const char *zTktUuid = 0; /* Ticket ID when attached to a ticket */
@@ -763,11 +767,11 @@
763 }
764 blob_read_from_file(&content, zFile, ExtFILE);
765 user_select();
766 attach_commit(
767 zFile, /* The filename of the attachment */
768 zTarget, /* The artifact uuid to attach to */
769 blob_buffer(&content), /* The content of the attachment */
770 blob_size(&content), /* The length of the attachment */
771 0, /* No need to moderate the attachment */
772 "" /* Empty attachment comment */
773 );
774
--- src/attach.c
+++ src/attach.c
@@ -23,19 +23,22 @@
23
24 /*
25 ** WEBPAGE: attachlist
26 ** List attachments.
27 **
28 ** tkt=HASH
29 ** page=WIKIPAGE
30 ** technote=HASH
31 **
32 ** At most one of technote=, tkt= or page= may be supplied.
33 **
34 ** If none are given, all attachments are listed. If one is given, only
35 ** attachments for the designated technote, ticket or wiki page are shown.
36 **
37 ** HASH may be just a prefix of the relevant technical note or ticket
38 ** artifact hash, in which case all attachments of all technical notes or
39 ** tickets with the prefix will be listed.
 
 
 
40 */
41 void attachlist_page(void){
42 const char *zPage = P("page");
43 const char *zTkt = P("tkt");
44 const char *zTechNote = P("technote");
@@ -152,15 +155,16 @@
155 ** WEBPAGE: attachdownload
156 ** WEBPAGE: attachimage
157 ** WEBPAGE: attachview
158 **
159 ** Download or display an attachment.
160 **
161 ** Query parameters:
162 **
163 ** tkt=HASH
164 ** page=WIKIPAGE
165 ** technote=HASH
166 ** file=FILENAME
167 ** attachid=ID
168 **
169 */
170 void attachview_page(void){
@@ -250,11 +254,11 @@
254 /*
255 ** Commit a new attachment into the repository
256 */
257 void attach_commit(
258 const char *zName, /* The filename of the attachment */
259 const char *zTarget, /* The artifact hash to attach to */
260 const char *aContent, /* The content of the attachment */
261 int szContent, /* The length of the attachment */
262 int needModerator, /* Moderate the attachment? */
263 const char *zComment /* The comment for the attachment */
264 ){
@@ -305,13 +309,13 @@
309
310 /*
311 ** WEBPAGE: attachadd
312 ** Add a new attachment.
313 **
314 ** tkt=HASH
315 ** page=WIKIPAGE
316 ** technote=HASH
317 ** from=URL
318 **
319 */
320 void attachadd_page(void){
321 const char *zPage = P("page");
@@ -420,14 +424,14 @@
424 */
425 void ainfo_page(void){
426 int rid; /* RID for the control artifact */
427 int ridSrc; /* RID for the attached file */
428 char *zDate; /* Date attached */
429 const char *zUuid; /* Hash of the control artifact */
430 Manifest *pAttach; /* Parse of the control artifact */
431 const char *zTarget; /* Wiki, ticket or tech note attached to */
432 const char *zSrc; /* Hash of the attached file */
433 const char *zName; /* Name of the attached file */
434 const char *zDesc; /* Description of the attached file */
435 const char *zWikiName = 0; /* Wiki page name when attached to Wiki */
436 const char *zTNUuid = 0; /* Tech Note ID when attached to tech note */
437 const char *zTktUuid = 0; /* Ticket ID when attached to a ticket */
@@ -763,11 +767,11 @@
767 }
768 blob_read_from_file(&content, zFile, ExtFILE);
769 user_select();
770 attach_commit(
771 zFile, /* The filename of the attachment */
772 zTarget, /* The artifact hash to attach to */
773 blob_buffer(&content), /* The content of the attachment */
774 blob_size(&content), /* The length of the attachment */
775 0, /* No need to moderate the attachment */
776 "" /* Empty attachment comment */
777 );
778
+8 -1
--- src/blob.c
+++ src/blob.c
@@ -482,13 +482,20 @@
482482
483483
/*
484484
** Ensures that the given blob has at least the given amount of memory
485485
** allocated to it. Does not modify pBlob->nUsed nor will it reduce
486486
** the currently-allocated amount of memory.
487
+**
488
+** For semantic compatibility with blob_append_full(), if newSize is
489
+** >=0x7fff000 (~2GB) then this function will trigger blob_panic(). If
490
+** it didn't, it would be possible to bypass that hard-coded limit via
491
+** this function.
487492
*/
488493
void blob_reserve(Blob *pBlob, unsigned int newSize){
489
- if(newSize>pBlob->nUsed){
494
+ if(newSize>=0x7fff0000 ){
495
+ blob_panic();
496
+ }else if(newSize>pBlob->nUsed){
490497
pBlob->xRealloc(pBlob, newSize);
491498
pBlob->aData[newSize] = 0;
492499
}
493500
}
494501
495502
--- src/blob.c
+++ src/blob.c
@@ -482,13 +482,20 @@
482
483 /*
484 ** Ensures that the given blob has at least the given amount of memory
485 ** allocated to it. Does not modify pBlob->nUsed nor will it reduce
486 ** the currently-allocated amount of memory.
 
 
 
 
 
487 */
488 void blob_reserve(Blob *pBlob, unsigned int newSize){
489 if(newSize>pBlob->nUsed){
 
 
490 pBlob->xRealloc(pBlob, newSize);
491 pBlob->aData[newSize] = 0;
492 }
493 }
494
495
--- src/blob.c
+++ src/blob.c
@@ -482,13 +482,20 @@
482
483 /*
484 ** Ensures that the given blob has at least the given amount of memory
485 ** allocated to it. Does not modify pBlob->nUsed nor will it reduce
486 ** the currently-allocated amount of memory.
487 **
488 ** For semantic compatibility with blob_append_full(), if newSize is
489 ** >=0x7fff000 (~2GB) then this function will trigger blob_panic(). If
490 ** it didn't, it would be possible to bypass that hard-coded limit via
491 ** this function.
492 */
493 void blob_reserve(Blob *pBlob, unsigned int newSize){
494 if(newSize>=0x7fff0000 ){
495 blob_panic();
496 }else if(newSize>pBlob->nUsed){
497 pBlob->xRealloc(pBlob, newSize);
498 pBlob->aData[newSize] = 0;
499 }
500 }
501
502
+4 -4
--- src/bundle.c
+++ src/bundle.c
@@ -530,19 +530,19 @@
530530
blob_reset(&h1);
531531
bag_remove(&busy, blobid);
532532
db_finalize(&q);
533533
}
534534
535
-/* fossil bundle cat BUNDLE UUID...
535
+/* fossil bundle cat BUNDLE HASH...
536536
**
537537
** Write elements of a bundle on standard output
538538
*/
539539
static void bundle_cat_cmd(void){
540540
int i;
541541
Blob x;
542542
verify_all_options();
543
- if( g.argc<5 ) usage("cat BUNDLE UUID...");
543
+ if( g.argc<5 ) usage("cat BUNDLE HASH...");
544544
bundle_attach_file(g.argv[3], "b1", 1);
545545
blob_zero(&x);
546546
for(i=4; i<g.argc; i++){
547547
int blobid = db_int(0,"SELECT blobid FROM bblob WHERE uuid LIKE '%q%%'",
548548
g.argv[i]);
@@ -725,11 +725,11 @@
725725
** fossil bundle append BUNDLE FILE...
726726
**
727727
** Add files named on the command line to BUNDLE. This subcommand has
728728
** little practical use and is mostly intended for testing.
729729
**
730
-** fossil bundle cat BUNDLE UUID...
730
+** fossil bundle cat BUNDLE HASH...
731731
**
732732
** Extract one or more artifacts from the bundle and write them
733733
** consecutively on standard output. This subcommand was designed
734734
** for testing and introspection of bundles and is not something
735735
** commonly used.
@@ -770,11 +770,11 @@
770770
** by check-ins in BUNDLE. This has the effect of undoing a
771771
** "fossil bundle import".
772772
**
773773
** SUMMARY:
774774
** fossil bundle append BUNDLE FILE... Add files to BUNDLE
775
-** fossil bundle cat BUNDLE UUID... Extract file from BUNDLE
775
+** fossil bundle cat BUNDLE HASH... Extract file from BUNDLE
776776
** fossil bundle export BUNDLE ?OPTIONS? Create a new BUNDLE
777777
** --branch BRANCH --from TAG1 --to TAG2 Check-ins to include
778778
** --checkin TAG Use only check-in TAG
779779
** --standalone Omit dependencies
780780
** fossil bundle extend BUNDLE Update with newer content
781781
--- src/bundle.c
+++ src/bundle.c
@@ -530,19 +530,19 @@
530 blob_reset(&h1);
531 bag_remove(&busy, blobid);
532 db_finalize(&q);
533 }
534
535 /* fossil bundle cat BUNDLE UUID...
536 **
537 ** Write elements of a bundle on standard output
538 */
539 static void bundle_cat_cmd(void){
540 int i;
541 Blob x;
542 verify_all_options();
543 if( g.argc<5 ) usage("cat BUNDLE UUID...");
544 bundle_attach_file(g.argv[3], "b1", 1);
545 blob_zero(&x);
546 for(i=4; i<g.argc; i++){
547 int blobid = db_int(0,"SELECT blobid FROM bblob WHERE uuid LIKE '%q%%'",
548 g.argv[i]);
@@ -725,11 +725,11 @@
725 ** fossil bundle append BUNDLE FILE...
726 **
727 ** Add files named on the command line to BUNDLE. This subcommand has
728 ** little practical use and is mostly intended for testing.
729 **
730 ** fossil bundle cat BUNDLE UUID...
731 **
732 ** Extract one or more artifacts from the bundle and write them
733 ** consecutively on standard output. This subcommand was designed
734 ** for testing and introspection of bundles and is not something
735 ** commonly used.
@@ -770,11 +770,11 @@
770 ** by check-ins in BUNDLE. This has the effect of undoing a
771 ** "fossil bundle import".
772 **
773 ** SUMMARY:
774 ** fossil bundle append BUNDLE FILE... Add files to BUNDLE
775 ** fossil bundle cat BUNDLE UUID... Extract file from BUNDLE
776 ** fossil bundle export BUNDLE ?OPTIONS? Create a new BUNDLE
777 ** --branch BRANCH --from TAG1 --to TAG2 Check-ins to include
778 ** --checkin TAG Use only check-in TAG
779 ** --standalone Omit dependencies
780 ** fossil bundle extend BUNDLE Update with newer content
781
--- src/bundle.c
+++ src/bundle.c
@@ -530,19 +530,19 @@
530 blob_reset(&h1);
531 bag_remove(&busy, blobid);
532 db_finalize(&q);
533 }
534
535 /* fossil bundle cat BUNDLE HASH...
536 **
537 ** Write elements of a bundle on standard output
538 */
539 static void bundle_cat_cmd(void){
540 int i;
541 Blob x;
542 verify_all_options();
543 if( g.argc<5 ) usage("cat BUNDLE HASH...");
544 bundle_attach_file(g.argv[3], "b1", 1);
545 blob_zero(&x);
546 for(i=4; i<g.argc; i++){
547 int blobid = db_int(0,"SELECT blobid FROM bblob WHERE uuid LIKE '%q%%'",
548 g.argv[i]);
@@ -725,11 +725,11 @@
725 ** fossil bundle append BUNDLE FILE...
726 **
727 ** Add files named on the command line to BUNDLE. This subcommand has
728 ** little practical use and is mostly intended for testing.
729 **
730 ** fossil bundle cat BUNDLE HASH...
731 **
732 ** Extract one or more artifacts from the bundle and write them
733 ** consecutively on standard output. This subcommand was designed
734 ** for testing and introspection of bundles and is not something
735 ** commonly used.
@@ -770,11 +770,11 @@
770 ** by check-ins in BUNDLE. This has the effect of undoing a
771 ** "fossil bundle import".
772 **
773 ** SUMMARY:
774 ** fossil bundle append BUNDLE FILE... Add files to BUNDLE
775 ** fossil bundle cat BUNDLE HASH... Extract file from BUNDLE
776 ** fossil bundle export BUNDLE ?OPTIONS? Create a new BUNDLE
777 ** --branch BRANCH --from TAG1 --to TAG2 Check-ins to include
778 ** --checkin TAG Use only check-in TAG
779 ** --standalone Omit dependencies
780 ** fossil bundle extend BUNDLE Update with newer content
781
+4 -4
--- src/checkin.c
+++ src/checkin.c
@@ -1424,11 +1424,11 @@
14241424
** Make sure the current check-in with timestamp zDate is younger than its
14251425
** ancestor identified rid and zUuid. Throw a fatal error if not.
14261426
*/
14271427
static void checkin_verify_younger(
14281428
int rid, /* The record ID of the ancestor */
1429
- const char *zUuid, /* The artifact ID of the ancestor */
1429
+ const char *zUuid, /* The artifact hash of the ancestor */
14301430
const char *zDate /* Date & time of the current check-in */
14311431
){
14321432
#ifndef FOSSIL_ALLOW_OUT_OF_ORDER_DATES
14331433
if(checkin_is_younger(rid,zDate)==0){
14341434
fossil_fatal("ancestor check-in [%S] (%s) is not older (clock skew?)"
@@ -1500,18 +1500,18 @@
15001500
/*
15011501
** Create a manifest.
15021502
*/
15031503
static void create_manifest(
15041504
Blob *pOut, /* Write the manifest here */
1505
- const char *zBaselineUuid, /* UUID of baseline, or zero */
1505
+ const char *zBaselineUuid, /* Hash of baseline, or zero */
15061506
Manifest *pBaseline, /* Make it a delta manifest if not zero */
15071507
int vid, /* BLOB.id for the parent check-in */
15081508
CheckinInfo *p, /* Information about the check-in */
15091509
int *pnFBcard /* OUT: Number of generated B- and F-cards */
15101510
){
15111511
char *zDate; /* Date of the check-in */
1512
- char *zParentUuid = 0; /* UUID of parent check-in */
1512
+ char *zParentUuid = 0; /* Hash of parent check-in */
15131513
Blob filename; /* A single filename */
15141514
int nBasename; /* Size of base filename */
15151515
Stmt q; /* Various queries */
15161516
Blob mcksum; /* Manifest checksum */
15171517
ManifestFile *pFile; /* File from the baseline */
@@ -2058,11 +2058,11 @@
20582058
int nrid; /* blob-id of a modified file */
20592059
int nvid; /* Blob-id of the new check-in */
20602060
Blob comment; /* Check-in comment */
20612061
const char *zComment; /* Check-in comment */
20622062
Stmt q; /* Various queries */
2063
- char *zUuid; /* UUID of the new check-in */
2063
+ char *zUuid; /* Hash of the new check-in */
20642064
int useHash = 0; /* True to verify file status using hashing */
20652065
int noSign = 0; /* True to omit signing the manifest using GPG */
20662066
int privateFlag = 0; /* True if the --private option is present */
20672067
int privateParent = 0; /* True if the parent check-in is private */
20682068
int isAMerge = 0; /* True if checking in a merge */
20692069
--- src/checkin.c
+++ src/checkin.c
@@ -1424,11 +1424,11 @@
1424 ** Make sure the current check-in with timestamp zDate is younger than its
1425 ** ancestor identified rid and zUuid. Throw a fatal error if not.
1426 */
1427 static void checkin_verify_younger(
1428 int rid, /* The record ID of the ancestor */
1429 const char *zUuid, /* The artifact ID of the ancestor */
1430 const char *zDate /* Date & time of the current check-in */
1431 ){
1432 #ifndef FOSSIL_ALLOW_OUT_OF_ORDER_DATES
1433 if(checkin_is_younger(rid,zDate)==0){
1434 fossil_fatal("ancestor check-in [%S] (%s) is not older (clock skew?)"
@@ -1500,18 +1500,18 @@
1500 /*
1501 ** Create a manifest.
1502 */
1503 static void create_manifest(
1504 Blob *pOut, /* Write the manifest here */
1505 const char *zBaselineUuid, /* UUID of baseline, or zero */
1506 Manifest *pBaseline, /* Make it a delta manifest if not zero */
1507 int vid, /* BLOB.id for the parent check-in */
1508 CheckinInfo *p, /* Information about the check-in */
1509 int *pnFBcard /* OUT: Number of generated B- and F-cards */
1510 ){
1511 char *zDate; /* Date of the check-in */
1512 char *zParentUuid = 0; /* UUID of parent check-in */
1513 Blob filename; /* A single filename */
1514 int nBasename; /* Size of base filename */
1515 Stmt q; /* Various queries */
1516 Blob mcksum; /* Manifest checksum */
1517 ManifestFile *pFile; /* File from the baseline */
@@ -2058,11 +2058,11 @@
2058 int nrid; /* blob-id of a modified file */
2059 int nvid; /* Blob-id of the new check-in */
2060 Blob comment; /* Check-in comment */
2061 const char *zComment; /* Check-in comment */
2062 Stmt q; /* Various queries */
2063 char *zUuid; /* UUID of the new check-in */
2064 int useHash = 0; /* True to verify file status using hashing */
2065 int noSign = 0; /* True to omit signing the manifest using GPG */
2066 int privateFlag = 0; /* True if the --private option is present */
2067 int privateParent = 0; /* True if the parent check-in is private */
2068 int isAMerge = 0; /* True if checking in a merge */
2069
--- src/checkin.c
+++ src/checkin.c
@@ -1424,11 +1424,11 @@
1424 ** Make sure the current check-in with timestamp zDate is younger than its
1425 ** ancestor identified rid and zUuid. Throw a fatal error if not.
1426 */
1427 static void checkin_verify_younger(
1428 int rid, /* The record ID of the ancestor */
1429 const char *zUuid, /* The artifact hash of the ancestor */
1430 const char *zDate /* Date & time of the current check-in */
1431 ){
1432 #ifndef FOSSIL_ALLOW_OUT_OF_ORDER_DATES
1433 if(checkin_is_younger(rid,zDate)==0){
1434 fossil_fatal("ancestor check-in [%S] (%s) is not older (clock skew?)"
@@ -1500,18 +1500,18 @@
1500 /*
1501 ** Create a manifest.
1502 */
1503 static void create_manifest(
1504 Blob *pOut, /* Write the manifest here */
1505 const char *zBaselineUuid, /* Hash of baseline, or zero */
1506 Manifest *pBaseline, /* Make it a delta manifest if not zero */
1507 int vid, /* BLOB.id for the parent check-in */
1508 CheckinInfo *p, /* Information about the check-in */
1509 int *pnFBcard /* OUT: Number of generated B- and F-cards */
1510 ){
1511 char *zDate; /* Date of the check-in */
1512 char *zParentUuid = 0; /* Hash of parent check-in */
1513 Blob filename; /* A single filename */
1514 int nBasename; /* Size of base filename */
1515 Stmt q; /* Various queries */
1516 Blob mcksum; /* Manifest checksum */
1517 ManifestFile *pFile; /* File from the baseline */
@@ -2058,11 +2058,11 @@
2058 int nrid; /* blob-id of a modified file */
2059 int nvid; /* Blob-id of the new check-in */
2060 Blob comment; /* Check-in comment */
2061 const char *zComment; /* Check-in comment */
2062 Stmt q; /* Various queries */
2063 char *zUuid; /* Hash of the new check-in */
2064 int useHash = 0; /* True to verify file status using hashing */
2065 int noSign = 0; /* True to omit signing the manifest using GPG */
2066 int privateFlag = 0; /* True if the --private option is present */
2067 int privateParent = 0; /* True if the parent check-in is private */
2068 int isAMerge = 0; /* True if checking in a merge */
2069
+1 -1
--- src/checkout.c
+++ src/checkout.c
@@ -87,11 +87,11 @@
8787
db_multi_exec("DELETE FROM vfile WHERE vid=%d", vid);
8888
}
8989
9090
9191
/*
92
-** Given the abbreviated UUID name of a version, load the content of that
92
+** Given the abbreviated hash of a version, load the content of that
9393
** version in the VFILE table. Return the VID for the version.
9494
**
9595
** If anything goes wrong, panic.
9696
*/
9797
int load_vfile(const char *zName, int forceMissingFlag){
9898
--- src/checkout.c
+++ src/checkout.c
@@ -87,11 +87,11 @@
87 db_multi_exec("DELETE FROM vfile WHERE vid=%d", vid);
88 }
89
90
91 /*
92 ** Given the abbreviated UUID name of a version, load the content of that
93 ** version in the VFILE table. Return the VID for the version.
94 **
95 ** If anything goes wrong, panic.
96 */
97 int load_vfile(const char *zName, int forceMissingFlag){
98
--- src/checkout.c
+++ src/checkout.c
@@ -87,11 +87,11 @@
87 db_multi_exec("DELETE FROM vfile WHERE vid=%d", vid);
88 }
89
90
91 /*
92 ** Given the abbreviated hash of a version, load the content of that
93 ** version in the VFILE table. Return the VID for the version.
94 **
95 ** If anything goes wrong, panic.
96 */
97 int load_vfile(const char *zName, int forceMissingFlag){
98
+37 -17
--- src/codecheck1.c
+++ src/codecheck1.c
@@ -343,48 +343,54 @@
343343
}
344344
345345
/*
346346
** Processing flags
347347
*/
348
-#define FMT_SQL 0x00001 /* Generates SQL text */
349
-#define FMT_HTML 0x00002 /* Generates HTML text */
350
-#define FMT_URL 0x00004 /* Generates URLs */
351
-#define FMT_SAFE 0x00008 /* Always safe for %s */
348
+#define FMT_SQL 0x00001 /* Generator for SQL text */
349
+#define FMT_HTML 0x00002 /* Generator for HTML text */
350
+#define FMT_URL 0x00004 /* Generator for URLs */
351
+#define FMT_SAFE 0x00008 /* Generator for human-readable text */
352352
353353
/*
354354
** A list of internal Fossil interfaces that take a printf-style format
355355
** string.
356356
*/
357
-struct {
357
+struct FmtFunc {
358358
const char *zFName; /* Name of the function */
359359
int iFmtArg; /* Index of format argument. Leftmost is 1. */
360360
unsigned fmtFlags; /* Processing flags */
361361
} aFmtFunc[] = {
362
- { "admin_log", 1, 0 },
362
+ { "admin_log", 1, FMT_SAFE },
363
+ { "audit_append", 3, FMT_SAFE },
364
+ { "backofficeTrace", 1, FMT_SAFE },
363365
{ "blob_append_sql", 2, FMT_SQL },
364
- { "blob_appendf", 2, 0 },
366
+ { "blob_appendf", 2, FMT_SAFE },
365367
{ "cgi_debug", 1, FMT_SAFE },
366368
{ "cgi_panic", 1, FMT_SAFE },
367369
{ "cgi_printf", 1, FMT_HTML },
370
+ { "cgi_printf_header", 1, FMT_HTML },
368371
{ "cgi_redirectf", 1, FMT_URL },
369372
{ "chref", 2, FMT_URL },
373
+ { "CX", 1, FMT_HTML },
370374
{ "db_blob", 2, FMT_SQL },
371375
{ "db_debug", 1, FMT_SQL },
372376
{ "db_double", 2, FMT_SQL },
373
- { "db_err", 1, 0 },
377
+ { "db_err", 1, FMT_SAFE },
374378
{ "db_exists", 1, FMT_SQL },
375
- { "db_get_mprintf", 2, 0 },
379
+ { "db_get_mprintf", 2, FMT_SAFE },
376380
{ "db_int", 2, FMT_SQL },
377381
{ "db_int64", 2, FMT_SQL },
378382
{ "db_multi_exec", 1, FMT_SQL },
379383
{ "db_optional_sql", 2, FMT_SQL },
380384
{ "db_prepare", 2, FMT_SQL },
381385
{ "db_prepare_ignore_error", 2, FMT_SQL },
382
- { "db_set_mprintf", 3, 0 },
386
+ { "db_set_mprintf", 3, FMT_SAFE },
383387
{ "db_static_prepare", 2, FMT_SQL },
384388
{ "db_text", 2, FMT_SQL },
385
- { "db_unset_mprintf", 2, 0 },
389
+ { "db_unset_mprintf", 2, FMT_SAFE },
390
+ { "emailerError", 2, FMT_SAFE },
391
+ { "fileedit_ajax_error", 2, FMT_SAFE },
386392
{ "form_begin", 2, FMT_URL },
387393
{ "fossil_error", 2, FMT_SAFE },
388394
{ "fossil_errorlog", 1, FMT_SAFE },
389395
{ "fossil_fatal", 1, FMT_SAFE },
390396
{ "fossil_fatal_recursive", 1, FMT_SAFE },
@@ -391,24 +397,36 @@
391397
{ "fossil_panic", 1, FMT_SAFE },
392398
{ "fossil_print", 1, FMT_SAFE },
393399
{ "fossil_trace", 1, FMT_SAFE },
394400
{ "fossil_warning", 1, FMT_SAFE },
395401
{ "href", 1, FMT_URL },
396
- { "json_new_string_f", 1, 0 },
397
- { "json_set_err", 2, 0 },
398
- { "json_warn", 2, 0 },
399
- { "mprintf", 1, 0 },
400
- { "socket_set_errmsg", 1, 0 },
401
- { "ssl_set_errmsg", 1, 0 },
402
+ { "json_new_string_f", 1, FMT_SAFE },
403
+ { "json_set_err", 2, FMT_SAFE },
404
+ { "json_warn", 2, FMT_SAFE },
405
+ { "mprintf", 1, FMT_SAFE },
406
+ { "pop3_print", 2, FMT_SAFE },
407
+ { "smtp_send_line", 2, FMT_SAFE },
408
+ { "smtp_server_send", 2, FMT_SAFE },
409
+ { "socket_set_errmsg", 1, FMT_SAFE },
410
+ { "ssl_set_errmsg", 1, FMT_SAFE },
402411
{ "style_header", 1, FMT_HTML },
403412
{ "style_js_onload", 1, FMT_HTML },
404413
{ "style_set_current_page", 1, FMT_URL },
405414
{ "style_submenu_element", 2, FMT_URL },
406415
{ "style_submenu_sql", 3, FMT_SQL },
407416
{ "webpage_error", 1, FMT_SAFE },
408417
{ "xhref", 2, FMT_URL },
409418
};
419
+
420
+/*
421
+** Comparison function for two FmtFunc entries
422
+*/
423
+static int fmtfunc_cmp(const void *pAA, const void *pBB){
424
+ const struct FmtFunc *pA = (const struct FmtFunc*)pAA;
425
+ const struct FmtFunc *pB = (const struct FmtFunc*)pBB;
426
+ return strcmp(pA->zFName, pB->zFName);
427
+}
410428
411429
/*
412430
** Determine if the indentifier zIdent of length nIndent is a Fossil
413431
** internal interface that uses a printf-style argument. Return zero if not.
414432
** Return the index of the format string if true with the left-most
@@ -625,10 +643,12 @@
625643
** The eVerbose global variable is incremented with each "-v" argument.
626644
*/
627645
int main(int argc, char **argv){
628646
int i;
629647
int nErr = 0;
648
+ qsort(aFmtFunc, sizeof(aFmtFunc)/sizeof(aFmtFunc[0]),
649
+ sizeof(aFmtFunc[0]), fmtfunc_cmp);
630650
for(i=1; i<argc; i++){
631651
char *zFile;
632652
if( strcmp(argv[i],"-v")==0 ){
633653
eVerbose++;
634654
continue;
635655
--- src/codecheck1.c
+++ src/codecheck1.c
@@ -343,48 +343,54 @@
343 }
344
345 /*
346 ** Processing flags
347 */
348 #define FMT_SQL 0x00001 /* Generates SQL text */
349 #define FMT_HTML 0x00002 /* Generates HTML text */
350 #define FMT_URL 0x00004 /* Generates URLs */
351 #define FMT_SAFE 0x00008 /* Always safe for %s */
352
353 /*
354 ** A list of internal Fossil interfaces that take a printf-style format
355 ** string.
356 */
357 struct {
358 const char *zFName; /* Name of the function */
359 int iFmtArg; /* Index of format argument. Leftmost is 1. */
360 unsigned fmtFlags; /* Processing flags */
361 } aFmtFunc[] = {
362 { "admin_log", 1, 0 },
 
 
363 { "blob_append_sql", 2, FMT_SQL },
364 { "blob_appendf", 2, 0 },
365 { "cgi_debug", 1, FMT_SAFE },
366 { "cgi_panic", 1, FMT_SAFE },
367 { "cgi_printf", 1, FMT_HTML },
 
368 { "cgi_redirectf", 1, FMT_URL },
369 { "chref", 2, FMT_URL },
 
370 { "db_blob", 2, FMT_SQL },
371 { "db_debug", 1, FMT_SQL },
372 { "db_double", 2, FMT_SQL },
373 { "db_err", 1, 0 },
374 { "db_exists", 1, FMT_SQL },
375 { "db_get_mprintf", 2, 0 },
376 { "db_int", 2, FMT_SQL },
377 { "db_int64", 2, FMT_SQL },
378 { "db_multi_exec", 1, FMT_SQL },
379 { "db_optional_sql", 2, FMT_SQL },
380 { "db_prepare", 2, FMT_SQL },
381 { "db_prepare_ignore_error", 2, FMT_SQL },
382 { "db_set_mprintf", 3, 0 },
383 { "db_static_prepare", 2, FMT_SQL },
384 { "db_text", 2, FMT_SQL },
385 { "db_unset_mprintf", 2, 0 },
 
 
386 { "form_begin", 2, FMT_URL },
387 { "fossil_error", 2, FMT_SAFE },
388 { "fossil_errorlog", 1, FMT_SAFE },
389 { "fossil_fatal", 1, FMT_SAFE },
390 { "fossil_fatal_recursive", 1, FMT_SAFE },
@@ -391,24 +397,36 @@
391 { "fossil_panic", 1, FMT_SAFE },
392 { "fossil_print", 1, FMT_SAFE },
393 { "fossil_trace", 1, FMT_SAFE },
394 { "fossil_warning", 1, FMT_SAFE },
395 { "href", 1, FMT_URL },
396 { "json_new_string_f", 1, 0 },
397 { "json_set_err", 2, 0 },
398 { "json_warn", 2, 0 },
399 { "mprintf", 1, 0 },
400 { "socket_set_errmsg", 1, 0 },
401 { "ssl_set_errmsg", 1, 0 },
 
 
 
402 { "style_header", 1, FMT_HTML },
403 { "style_js_onload", 1, FMT_HTML },
404 { "style_set_current_page", 1, FMT_URL },
405 { "style_submenu_element", 2, FMT_URL },
406 { "style_submenu_sql", 3, FMT_SQL },
407 { "webpage_error", 1, FMT_SAFE },
408 { "xhref", 2, FMT_URL },
409 };
 
 
 
 
 
 
 
 
 
410
411 /*
412 ** Determine if the indentifier zIdent of length nIndent is a Fossil
413 ** internal interface that uses a printf-style argument. Return zero if not.
414 ** Return the index of the format string if true with the left-most
@@ -625,10 +643,12 @@
625 ** The eVerbose global variable is incremented with each "-v" argument.
626 */
627 int main(int argc, char **argv){
628 int i;
629 int nErr = 0;
 
 
630 for(i=1; i<argc; i++){
631 char *zFile;
632 if( strcmp(argv[i],"-v")==0 ){
633 eVerbose++;
634 continue;
635
--- src/codecheck1.c
+++ src/codecheck1.c
@@ -343,48 +343,54 @@
343 }
344
345 /*
346 ** Processing flags
347 */
348 #define FMT_SQL 0x00001 /* Generator for SQL text */
349 #define FMT_HTML 0x00002 /* Generator for HTML text */
350 #define FMT_URL 0x00004 /* Generator for URLs */
351 #define FMT_SAFE 0x00008 /* Generator for human-readable text */
352
353 /*
354 ** A list of internal Fossil interfaces that take a printf-style format
355 ** string.
356 */
357 struct FmtFunc {
358 const char *zFName; /* Name of the function */
359 int iFmtArg; /* Index of format argument. Leftmost is 1. */
360 unsigned fmtFlags; /* Processing flags */
361 } aFmtFunc[] = {
362 { "admin_log", 1, FMT_SAFE },
363 { "audit_append", 3, FMT_SAFE },
364 { "backofficeTrace", 1, FMT_SAFE },
365 { "blob_append_sql", 2, FMT_SQL },
366 { "blob_appendf", 2, FMT_SAFE },
367 { "cgi_debug", 1, FMT_SAFE },
368 { "cgi_panic", 1, FMT_SAFE },
369 { "cgi_printf", 1, FMT_HTML },
370 { "cgi_printf_header", 1, FMT_HTML },
371 { "cgi_redirectf", 1, FMT_URL },
372 { "chref", 2, FMT_URL },
373 { "CX", 1, FMT_HTML },
374 { "db_blob", 2, FMT_SQL },
375 { "db_debug", 1, FMT_SQL },
376 { "db_double", 2, FMT_SQL },
377 { "db_err", 1, FMT_SAFE },
378 { "db_exists", 1, FMT_SQL },
379 { "db_get_mprintf", 2, FMT_SAFE },
380 { "db_int", 2, FMT_SQL },
381 { "db_int64", 2, FMT_SQL },
382 { "db_multi_exec", 1, FMT_SQL },
383 { "db_optional_sql", 2, FMT_SQL },
384 { "db_prepare", 2, FMT_SQL },
385 { "db_prepare_ignore_error", 2, FMT_SQL },
386 { "db_set_mprintf", 3, FMT_SAFE },
387 { "db_static_prepare", 2, FMT_SQL },
388 { "db_text", 2, FMT_SQL },
389 { "db_unset_mprintf", 2, FMT_SAFE },
390 { "emailerError", 2, FMT_SAFE },
391 { "fileedit_ajax_error", 2, FMT_SAFE },
392 { "form_begin", 2, FMT_URL },
393 { "fossil_error", 2, FMT_SAFE },
394 { "fossil_errorlog", 1, FMT_SAFE },
395 { "fossil_fatal", 1, FMT_SAFE },
396 { "fossil_fatal_recursive", 1, FMT_SAFE },
@@ -391,24 +397,36 @@
397 { "fossil_panic", 1, FMT_SAFE },
398 { "fossil_print", 1, FMT_SAFE },
399 { "fossil_trace", 1, FMT_SAFE },
400 { "fossil_warning", 1, FMT_SAFE },
401 { "href", 1, FMT_URL },
402 { "json_new_string_f", 1, FMT_SAFE },
403 { "json_set_err", 2, FMT_SAFE },
404 { "json_warn", 2, FMT_SAFE },
405 { "mprintf", 1, FMT_SAFE },
406 { "pop3_print", 2, FMT_SAFE },
407 { "smtp_send_line", 2, FMT_SAFE },
408 { "smtp_server_send", 2, FMT_SAFE },
409 { "socket_set_errmsg", 1, FMT_SAFE },
410 { "ssl_set_errmsg", 1, FMT_SAFE },
411 { "style_header", 1, FMT_HTML },
412 { "style_js_onload", 1, FMT_HTML },
413 { "style_set_current_page", 1, FMT_URL },
414 { "style_submenu_element", 2, FMT_URL },
415 { "style_submenu_sql", 3, FMT_SQL },
416 { "webpage_error", 1, FMT_SAFE },
417 { "xhref", 2, FMT_URL },
418 };
419
420 /*
421 ** Comparison function for two FmtFunc entries
422 */
423 static int fmtfunc_cmp(const void *pAA, const void *pBB){
424 const struct FmtFunc *pA = (const struct FmtFunc*)pAA;
425 const struct FmtFunc *pB = (const struct FmtFunc*)pBB;
426 return strcmp(pA->zFName, pB->zFName);
427 }
428
429 /*
430 ** Determine if the indentifier zIdent of length nIndent is a Fossil
431 ** internal interface that uses a printf-style argument. Return zero if not.
432 ** Return the index of the format string if true with the left-most
@@ -625,10 +643,12 @@
643 ** The eVerbose global variable is incremented with each "-v" argument.
644 */
645 int main(int argc, char **argv){
646 int i;
647 int nErr = 0;
648 qsort(aFmtFunc, sizeof(aFmtFunc)/sizeof(aFmtFunc[0]),
649 sizeof(aFmtFunc[0]), fmtfunc_cmp);
650 for(i=1; i<argc; i++){
651 char *zFile;
652 if( strcmp(argv[i],"-v")==0 ){
653 eVerbose++;
654 continue;
655
--- src/configure.c
+++ src/configure.c
@@ -148,11 +148,10 @@
148148
{ "parent-project-name", CONFIGSET_PROJ },
149149
{ "hash-policy", CONFIGSET_PROJ },
150150
{ "comment-format", CONFIGSET_PROJ },
151151
{ "mimetypes", CONFIGSET_PROJ },
152152
{ "forbid-delta-manifests", CONFIGSET_PROJ },
153
- { "fileedit-glob", CONFIGSET_PROJ },
154153
155154
#ifdef FOSSIL_ENABLE_LEGACY_MV_RM
156155
{ "mv-rm-files", CONFIGSET_PROJ },
157156
#endif
158157
159158
--- src/configure.c
+++ src/configure.c
@@ -148,11 +148,10 @@
148 { "parent-project-name", CONFIGSET_PROJ },
149 { "hash-policy", CONFIGSET_PROJ },
150 { "comment-format", CONFIGSET_PROJ },
151 { "mimetypes", CONFIGSET_PROJ },
152 { "forbid-delta-manifests", CONFIGSET_PROJ },
153 { "fileedit-glob", CONFIGSET_PROJ },
154
155 #ifdef FOSSIL_ENABLE_LEGACY_MV_RM
156 { "mv-rm-files", CONFIGSET_PROJ },
157 #endif
158
159
--- src/configure.c
+++ src/configure.c
@@ -148,11 +148,10 @@
148 { "parent-project-name", CONFIGSET_PROJ },
149 { "hash-policy", CONFIGSET_PROJ },
150 { "comment-format", CONFIGSET_PROJ },
151 { "mimetypes", CONFIGSET_PROJ },
152 { "forbid-delta-manifests", CONFIGSET_PROJ },
 
153
154 #ifdef FOSSIL_ENABLE_LEGACY_MV_RM
155 { "mv-rm-files", CONFIGSET_PROJ },
156 #endif
157
158
+6 -5
--- src/content.c
+++ src/content.c
@@ -564,11 +564,11 @@
564564
db_finalize(&s1);
565565
db_end_transaction(0);
566566
return rid;
567567
}
568568
}else{
569
- rid = 0; /* No entry with the same UUID currently exists */
569
+ rid = 0; /* No entry with the same hash currently exists */
570570
markAsUnclustered = 1;
571571
}
572572
db_finalize(&s1);
573573
574574
/* Construct a received-from ID if we do not already have one */
@@ -659,11 +659,11 @@
659659
return content_put_ex(pBlob, 0, 0, 0, 0);
660660
}
661661
662662
663663
/*
664
-** Create a new phantom with the given UUID and return its artifact ID.
664
+** Create a new phantom with the given hash and return its artifact ID.
665665
*/
666666
int content_new(const char *zUuid, int isPrivate){
667667
int rid;
668668
static Stmt s1, s2, s3;
669669
@@ -1110,15 +1110,16 @@
11101110
/* Allowed flags for check_exists */
11111111
#define MISSING_SHUNNED 0x0001 /* Do not report shunned artifacts */
11121112
11131113
/* This is a helper routine for test-artifacts.
11141114
**
1115
-** Check to see that artifact zUuid exists in the repository. If it does,
1116
-** return 0. If it does not, generate an error message and return 1.
1115
+** Check to see that the artifact hash referenced by zUuid exists in the
1116
+** repository. If it does, return 0. If it does not, generate an error
1117
+** message and return 1.
11171118
*/
11181119
static int check_exists(
1119
- const char *zUuid, /* The artifact we are checking for */
1120
+ const char *zUuid, /* Hash of the artifact we are checking for */
11201121
unsigned flags, /* Flags */
11211122
Manifest *p, /* The control artifact that references zUuid */
11221123
const char *zRole, /* Role of zUuid in p */
11231124
const char *zDetail /* Additional information, such as a filename */
11241125
){
11251126
--- src/content.c
+++ src/content.c
@@ -564,11 +564,11 @@
564 db_finalize(&s1);
565 db_end_transaction(0);
566 return rid;
567 }
568 }else{
569 rid = 0; /* No entry with the same UUID currently exists */
570 markAsUnclustered = 1;
571 }
572 db_finalize(&s1);
573
574 /* Construct a received-from ID if we do not already have one */
@@ -659,11 +659,11 @@
659 return content_put_ex(pBlob, 0, 0, 0, 0);
660 }
661
662
663 /*
664 ** Create a new phantom with the given UUID and return its artifact ID.
665 */
666 int content_new(const char *zUuid, int isPrivate){
667 int rid;
668 static Stmt s1, s2, s3;
669
@@ -1110,15 +1110,16 @@
1110 /* Allowed flags for check_exists */
1111 #define MISSING_SHUNNED 0x0001 /* Do not report shunned artifacts */
1112
1113 /* This is a helper routine for test-artifacts.
1114 **
1115 ** Check to see that artifact zUuid exists in the repository. If it does,
1116 ** return 0. If it does not, generate an error message and return 1.
 
1117 */
1118 static int check_exists(
1119 const char *zUuid, /* The artifact we are checking for */
1120 unsigned flags, /* Flags */
1121 Manifest *p, /* The control artifact that references zUuid */
1122 const char *zRole, /* Role of zUuid in p */
1123 const char *zDetail /* Additional information, such as a filename */
1124 ){
1125
--- src/content.c
+++ src/content.c
@@ -564,11 +564,11 @@
564 db_finalize(&s1);
565 db_end_transaction(0);
566 return rid;
567 }
568 }else{
569 rid = 0; /* No entry with the same hash currently exists */
570 markAsUnclustered = 1;
571 }
572 db_finalize(&s1);
573
574 /* Construct a received-from ID if we do not already have one */
@@ -659,11 +659,11 @@
659 return content_put_ex(pBlob, 0, 0, 0, 0);
660 }
661
662
663 /*
664 ** Create a new phantom with the given hash and return its artifact ID.
665 */
666 int content_new(const char *zUuid, int isPrivate){
667 int rid;
668 static Stmt s1, s2, s3;
669
@@ -1110,15 +1110,16 @@
1110 /* Allowed flags for check_exists */
1111 #define MISSING_SHUNNED 0x0001 /* Do not report shunned artifacts */
1112
1113 /* This is a helper routine for test-artifacts.
1114 **
1115 ** Check to see that the artifact hash referenced by zUuid exists in the
1116 ** repository. If it does, return 0. If it does not, generate an error
1117 ** message and return 1.
1118 */
1119 static int check_exists(
1120 const char *zUuid, /* Hash of the artifact we are checking for */
1121 unsigned flags, /* Flags */
1122 Manifest *p, /* The control artifact that references zUuid */
1123 const char *zRole, /* Role of zUuid in p */
1124 const char *zDetail /* Additional information, such as a filename */
1125 ){
1126
+1 -1
--- src/event.c
+++ src/event.c
@@ -63,11 +63,11 @@
6363
** Display an existing tech-note identified by its ID, optionally at a
6464
** specific version, and optionally with additional details.
6565
*/
6666
void event_page(void){
6767
int rid = 0; /* rid of the event artifact */
68
- char *zUuid; /* UUID corresponding to rid */
68
+ char *zUuid; /* artifact hash corresponding to rid */
6969
const char *zId; /* Event identifier */
7070
const char *zVerbose; /* Value of verbose option */
7171
char *zETime; /* Time of the tech-note */
7272
char *zATime; /* Time the artifact was created */
7373
int specRid; /* rid specified by aid= parameter */
7474
--- src/event.c
+++ src/event.c
@@ -63,11 +63,11 @@
63 ** Display an existing tech-note identified by its ID, optionally at a
64 ** specific version, and optionally with additional details.
65 */
66 void event_page(void){
67 int rid = 0; /* rid of the event artifact */
68 char *zUuid; /* UUID corresponding to rid */
69 const char *zId; /* Event identifier */
70 const char *zVerbose; /* Value of verbose option */
71 char *zETime; /* Time of the tech-note */
72 char *zATime; /* Time the artifact was created */
73 int specRid; /* rid specified by aid= parameter */
74
--- src/event.c
+++ src/event.c
@@ -63,11 +63,11 @@
63 ** Display an existing tech-note identified by its ID, optionally at a
64 ** specific version, and optionally with additional details.
65 */
66 void event_page(void){
67 int rid = 0; /* rid of the event artifact */
68 char *zUuid; /* artifact hash corresponding to rid */
69 const char *zId; /* Event identifier */
70 const char *zVerbose; /* Value of verbose option */
71 char *zETime; /* Time of the tech-note */
72 char *zATime; /* Time the artifact was created */
73 int specRid; /* rid specified by aid= parameter */
74
+47 -20
--- src/fileedit.c
+++ src/fileedit.c
@@ -888,11 +888,11 @@
888888
889889
/*
890890
** If the fileedit-glob setting has a value, this returns its Glob
891891
** object (in memory owned by this function), else it returns NULL.
892892
*/
893
-static Glob * fileedit_glob(void){
893
+Glob *fileedit_glob(void){
894894
static Glob * pGlobs = 0;
895895
static int once = 0;
896896
if(0==pGlobs && once==0){
897897
char * zGlobs = db_get("fileedit-glob",0);
898898
once = 1;
@@ -987,11 +987,11 @@
987987
output_text_with_line_numbers(zContent, "on");
988988
}else if(zExt && zExt[1]){
989989
CX("<pre><code class='language-%s'>%h</code></pre>",
990990
zExt+1, zContent);
991991
}else{
992
- CX("<pre>%h</pre>", zExt+1, zContent);
992
+ CX("<pre>%h</pre>", zContent);
993993
}
994994
break;
995995
}
996996
}
997997
}
@@ -1713,13 +1713,13 @@
17131713
(CIMINI_DRY_RUN & cimi.flags) ? "true" : "false");
17141714
if(blob_size(&manifest)>0){
17151715
CX(",\"manifest\": %!j", blob_str(&manifest));
17161716
}
17171717
CX("}");
1718
+end_cleanup:
17181719
db_end_transaction(0/*noting that dry-run mode will have already
17191720
** set this to rollback mode. */);
1720
-end_cleanup:
17211721
fossil_free(zNewUuid);
17221722
blob_reset(&err);
17231723
blob_reset(&manifest);
17241724
CheckinMiniInfo_cleanup(&cimi);
17251725
}
@@ -1765,13 +1765,51 @@
17651765
end. This content will be
17661766
combined into a single JS
17671767
function call, thus each
17681768
entry must end with a
17691769
semicolon. */
1770
- const char *zAjax = P("name");
1770
+ const char *zAjax = P("name"); /* Name of AJAX route for
1771
+ sub-dispatching. */
1772
+
1773
+ /* Allow no access to this page without check-in privilege */
1774
+ login_check_credentials();
1775
+ if( !g.perm.Write ){
1776
+ if(zAjax!=0){
1777
+ fileedit_ajax_error(403, "Write permissions required.");
1778
+ }else{
1779
+ login_needed(g.anon.Write);
1780
+ }
1781
+ return;
1782
+ }
1783
+ /* No access to anything on this page if the fileedit-glob is empty */
1784
+ if( fileedit_glob()==0 ){
1785
+ if(zAjax!=0){
1786
+ fileedit_ajax_error(403, "Online editing is disabled for this "
1787
+ "repository.");
1788
+ return;
1789
+ }
1790
+ style_header("File Editor (disabled)");
1791
+ CX("<h1>Online File Editing Is Disabled</h1>\n");
1792
+ if( g.perm.Admin ){
1793
+ CX("<p>To enable online editing, the "
1794
+ "<a href='%R/setup_settings'>"
1795
+ "<code>fileedit-glob</code> repository setting</a>\n"
1796
+ "must be set to a comma- and/or newine-delimited list of glob\n"
1797
+ "values matching files which may be edited online."
1798
+ "</p>\n");
1799
+ }else{
1800
+ CX("<p>Online editing is disabled for this repository.</p>\n");
1801
+ }
1802
+ style_footer();
1803
+ return;
1804
+ }
17711805
1772
- if(0!=zAjax){
1806
+ /* Dispatch AJAX methods based tail of the request URI.
1807
+ ** The AJAX parts do their own permissions/CSRF check and
1808
+ ** fail with a JSON-format response if needed.
1809
+ */
1810
+ if( 0!=zAjax ){
17731811
if(0==strcmp("content",zAjax)){
17741812
fileedit_ajax_content();
17751813
}else if(0==strcmp("preview",zAjax)){
17761814
fileedit_ajax_preview();
17771815
}else if(0==strcmp("filelist",zAjax)){
@@ -1783,21 +1821,18 @@
17831821
}else{
17841822
fileedit_ajax_error(500, "Unhandled ajax route name.");
17851823
}
17861824
return;
17871825
}
1788
- login_check_credentials();
1789
- if( !g.perm.Write ){
1790
- login_needed(g.anon.Write);
1791
- return;
1792
- }
1826
+
17931827
db_begin_transaction();
17941828
CheckinMiniInfo_init(&cimi);
17951829
style_header("File Editor");
17961830
/* As of this point, don't use return or fossil_fatal(). Write any
17971831
** error in (&err) and goto end_footer instead so that we can be
1798
- ** sure to do any cleanup and end the transaction cleanly.
1832
+ ** sure to emit the error message, do any cleanup, and end the
1833
+ ** transaction cleanly.
17991834
*/
18001835
{
18011836
int isMissingArg = 0;
18021837
if(fileedit_setup_cimi_from_p(&cimi, &err, &isMissingArg)==0){
18031838
zFilename = cimi.zFilename;
@@ -1805,11 +1840,11 @@
18051840
assert(zRev);
18061841
assert(zFilename);
18071842
zFileMime = mimetype_from_name(cimi.zFilename);
18081843
}else if(isMissingArg!=0){
18091844
/* Squelch these startup warnings - they're non-fatal now but
1810
- ** used to be. */
1845
+ ** used to be fatal. */
18111846
blob_reset(&err);
18121847
}
18131848
}
18141849
18151850
/********************************************************************
@@ -1830,18 +1865,10 @@
18301865
*/
18311866
style_emit_script_tag(0,0);
18321867
CX("document.body.classList.add('fileedit');\n");
18331868
style_emit_script_tag(1,0);
18341869
}
1835
-
1836
- if(fileedit_glob()==0){
1837
- CX("<div class='error'>To enable online editing, the "
1838
- "<code>fileedit-glob</code> repository setting must be set to a "
1839
- "comma- or newine-delimited list of glob values matching files "
1840
- "which may be edited online."
1841
- "</div>");
1842
- }
18431870
18441871
/* Status bar */
18451872
CX("<div id='fossil-status-bar' "
18461873
"title='Status message area. Double-click to clear them.'>"
18471874
"Status messages will go here.</div>\n"
18481875
--- src/fileedit.c
+++ src/fileedit.c
@@ -888,11 +888,11 @@
888
889 /*
890 ** If the fileedit-glob setting has a value, this returns its Glob
891 ** object (in memory owned by this function), else it returns NULL.
892 */
893 static Glob * fileedit_glob(void){
894 static Glob * pGlobs = 0;
895 static int once = 0;
896 if(0==pGlobs && once==0){
897 char * zGlobs = db_get("fileedit-glob",0);
898 once = 1;
@@ -987,11 +987,11 @@
987 output_text_with_line_numbers(zContent, "on");
988 }else if(zExt && zExt[1]){
989 CX("<pre><code class='language-%s'>%h</code></pre>",
990 zExt+1, zContent);
991 }else{
992 CX("<pre>%h</pre>", zExt+1, zContent);
993 }
994 break;
995 }
996 }
997 }
@@ -1713,13 +1713,13 @@
1713 (CIMINI_DRY_RUN & cimi.flags) ? "true" : "false");
1714 if(blob_size(&manifest)>0){
1715 CX(",\"manifest\": %!j", blob_str(&manifest));
1716 }
1717 CX("}");
 
1718 db_end_transaction(0/*noting that dry-run mode will have already
1719 ** set this to rollback mode. */);
1720 end_cleanup:
1721 fossil_free(zNewUuid);
1722 blob_reset(&err);
1723 blob_reset(&manifest);
1724 CheckinMiniInfo_cleanup(&cimi);
1725 }
@@ -1765,13 +1765,51 @@
1765 end. This content will be
1766 combined into a single JS
1767 function call, thus each
1768 entry must end with a
1769 semicolon. */
1770 const char *zAjax = P("name");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1771
1772 if(0!=zAjax){
 
 
 
 
1773 if(0==strcmp("content",zAjax)){
1774 fileedit_ajax_content();
1775 }else if(0==strcmp("preview",zAjax)){
1776 fileedit_ajax_preview();
1777 }else if(0==strcmp("filelist",zAjax)){
@@ -1783,21 +1821,18 @@
1783 }else{
1784 fileedit_ajax_error(500, "Unhandled ajax route name.");
1785 }
1786 return;
1787 }
1788 login_check_credentials();
1789 if( !g.perm.Write ){
1790 login_needed(g.anon.Write);
1791 return;
1792 }
1793 db_begin_transaction();
1794 CheckinMiniInfo_init(&cimi);
1795 style_header("File Editor");
1796 /* As of this point, don't use return or fossil_fatal(). Write any
1797 ** error in (&err) and goto end_footer instead so that we can be
1798 ** sure to do any cleanup and end the transaction cleanly.
 
1799 */
1800 {
1801 int isMissingArg = 0;
1802 if(fileedit_setup_cimi_from_p(&cimi, &err, &isMissingArg)==0){
1803 zFilename = cimi.zFilename;
@@ -1805,11 +1840,11 @@
1805 assert(zRev);
1806 assert(zFilename);
1807 zFileMime = mimetype_from_name(cimi.zFilename);
1808 }else if(isMissingArg!=0){
1809 /* Squelch these startup warnings - they're non-fatal now but
1810 ** used to be. */
1811 blob_reset(&err);
1812 }
1813 }
1814
1815 /********************************************************************
@@ -1830,18 +1865,10 @@
1830 */
1831 style_emit_script_tag(0,0);
1832 CX("document.body.classList.add('fileedit');\n");
1833 style_emit_script_tag(1,0);
1834 }
1835
1836 if(fileedit_glob()==0){
1837 CX("<div class='error'>To enable online editing, the "
1838 "<code>fileedit-glob</code> repository setting must be set to a "
1839 "comma- or newine-delimited list of glob values matching files "
1840 "which may be edited online."
1841 "</div>");
1842 }
1843
1844 /* Status bar */
1845 CX("<div id='fossil-status-bar' "
1846 "title='Status message area. Double-click to clear them.'>"
1847 "Status messages will go here.</div>\n"
1848
--- src/fileedit.c
+++ src/fileedit.c
@@ -888,11 +888,11 @@
888
889 /*
890 ** If the fileedit-glob setting has a value, this returns its Glob
891 ** object (in memory owned by this function), else it returns NULL.
892 */
893 Glob *fileedit_glob(void){
894 static Glob * pGlobs = 0;
895 static int once = 0;
896 if(0==pGlobs && once==0){
897 char * zGlobs = db_get("fileedit-glob",0);
898 once = 1;
@@ -987,11 +987,11 @@
987 output_text_with_line_numbers(zContent, "on");
988 }else if(zExt && zExt[1]){
989 CX("<pre><code class='language-%s'>%h</code></pre>",
990 zExt+1, zContent);
991 }else{
992 CX("<pre>%h</pre>", zContent);
993 }
994 break;
995 }
996 }
997 }
@@ -1713,13 +1713,13 @@
1713 (CIMINI_DRY_RUN & cimi.flags) ? "true" : "false");
1714 if(blob_size(&manifest)>0){
1715 CX(",\"manifest\": %!j", blob_str(&manifest));
1716 }
1717 CX("}");
1718 end_cleanup:
1719 db_end_transaction(0/*noting that dry-run mode will have already
1720 ** set this to rollback mode. */);
 
1721 fossil_free(zNewUuid);
1722 blob_reset(&err);
1723 blob_reset(&manifest);
1724 CheckinMiniInfo_cleanup(&cimi);
1725 }
@@ -1765,13 +1765,51 @@
1765 end. This content will be
1766 combined into a single JS
1767 function call, thus each
1768 entry must end with a
1769 semicolon. */
1770 const char *zAjax = P("name"); /* Name of AJAX route for
1771 sub-dispatching. */
1772
1773 /* Allow no access to this page without check-in privilege */
1774 login_check_credentials();
1775 if( !g.perm.Write ){
1776 if(zAjax!=0){
1777 fileedit_ajax_error(403, "Write permissions required.");
1778 }else{
1779 login_needed(g.anon.Write);
1780 }
1781 return;
1782 }
1783 /* No access to anything on this page if the fileedit-glob is empty */
1784 if( fileedit_glob()==0 ){
1785 if(zAjax!=0){
1786 fileedit_ajax_error(403, "Online editing is disabled for this "
1787 "repository.");
1788 return;
1789 }
1790 style_header("File Editor (disabled)");
1791 CX("<h1>Online File Editing Is Disabled</h1>\n");
1792 if( g.perm.Admin ){
1793 CX("<p>To enable online editing, the "
1794 "<a href='%R/setup_settings'>"
1795 "<code>fileedit-glob</code> repository setting</a>\n"
1796 "must be set to a comma- and/or newine-delimited list of glob\n"
1797 "values matching files which may be edited online."
1798 "</p>\n");
1799 }else{
1800 CX("<p>Online editing is disabled for this repository.</p>\n");
1801 }
1802 style_footer();
1803 return;
1804 }
1805
1806 /* Dispatch AJAX methods based tail of the request URI.
1807 ** The AJAX parts do their own permissions/CSRF check and
1808 ** fail with a JSON-format response if needed.
1809 */
1810 if( 0!=zAjax ){
1811 if(0==strcmp("content",zAjax)){
1812 fileedit_ajax_content();
1813 }else if(0==strcmp("preview",zAjax)){
1814 fileedit_ajax_preview();
1815 }else if(0==strcmp("filelist",zAjax)){
@@ -1783,21 +1821,18 @@
1821 }else{
1822 fileedit_ajax_error(500, "Unhandled ajax route name.");
1823 }
1824 return;
1825 }
1826
 
 
 
 
1827 db_begin_transaction();
1828 CheckinMiniInfo_init(&cimi);
1829 style_header("File Editor");
1830 /* As of this point, don't use return or fossil_fatal(). Write any
1831 ** error in (&err) and goto end_footer instead so that we can be
1832 ** sure to emit the error message, do any cleanup, and end the
1833 ** transaction cleanly.
1834 */
1835 {
1836 int isMissingArg = 0;
1837 if(fileedit_setup_cimi_from_p(&cimi, &err, &isMissingArg)==0){
1838 zFilename = cimi.zFilename;
@@ -1805,11 +1840,11 @@
1840 assert(zRev);
1841 assert(zFilename);
1842 zFileMime = mimetype_from_name(cimi.zFilename);
1843 }else if(isMissingArg!=0){
1844 /* Squelch these startup warnings - they're non-fatal now but
1845 ** used to be fatal. */
1846 blob_reset(&err);
1847 }
1848 }
1849
1850 /********************************************************************
@@ -1830,18 +1865,10 @@
1865 */
1866 style_emit_script_tag(0,0);
1867 CX("document.body.classList.add('fileedit');\n");
1868 style_emit_script_tag(1,0);
1869 }
 
 
 
 
 
 
 
 
1870
1871 /* Status bar */
1872 CX("<div id='fossil-status-bar' "
1873 "title='Status message area. Double-click to clear them.'>"
1874 "Status messages will go here.</div>\n"
1875
+8 -8
--- src/finfo.c
+++ src/finfo.c
@@ -284,12 +284,12 @@
284284
** b=DATETIME Only show changes before DATETIME
285285
** m=HASH Mark this particular file version
286286
** n=NUM Show the first NUM changes only
287287
** brbg Background color by branch name
288288
** ubg Background color by user name
289
-** ci=UUID Ancestors of a particular check-in
290
-** orig=UUID If both ci and orig are supplied, only show those
289
+** ci=HASH Ancestors of a particular check-in
290
+** orig=HASH If both ci and orig are supplied, only show those
291291
** changes on a direct path from orig to ci.
292292
** showid Show RID values for debugging
293293
**
294294
** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
295295
** year-month-day form, it may be truncated, and it may also name a
@@ -371,13 +371,13 @@
371371
" datetime(min(event.mtime),toLocal())," /* Date of change */
372372
" coalesce(event.ecomment, event.comment)," /* Check-in comment */
373373
" coalesce(event.euser, event.user)," /* User who made chng */
374374
" mlink.pid," /* Parent file rid */
375375
" mlink.fid," /* File rid */
376
- " (SELECT uuid FROM blob WHERE rid=mlink.pid)," /* Parent file uuid */
377
- " blob.uuid," /* Current file uuid */
378
- " (SELECT uuid FROM blob WHERE rid=mlink.mid)," /* Check-in uuid */
376
+ " (SELECT uuid FROM blob WHERE rid=mlink.pid)," /* Parent file hash */
377
+ " blob.uuid," /* Current file hash */
378
+ " (SELECT uuid FROM blob WHERE rid=mlink.mid)," /* Check-in hash */
379379
" event.bgcolor," /* Background color */
380380
" (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0"
381381
" AND tagxref.rid=mlink.mid)," /* Branchname */
382382
" mlink.mid," /* check-in ID */
383383
" mlink.pfnid," /* Previous filename */
@@ -541,13 +541,13 @@
541541
if( tmFlags & TIMELINE_COMPACT ){
542542
@ <span class='timelineCompactComment' data-id='%d(frid)'>
543543
}else{
544544
@ <span class='timeline%s(zStyle)Comment'>
545545
if( (tmFlags & TIMELINE_VERBOSE)!=0 && zUuid ){
546
- hyperlink_to_uuid(zUuid);
546
+ hyperlink_to_version(zUuid);
547547
@ part of check-in \
548
- hyperlink_to_uuid(zCkin);
548
+ hyperlink_to_version(zCkin);
549549
}
550550
}
551551
@ %W(zCom)</span>
552552
if( (tmFlags & TIMELINE_COMPACT)!=0 ){
553553
@ <span class='timelineEllipsis' data-id='%d(frid)' \
@@ -576,11 +576,11 @@
576576
@ id:&nbsp;%d(frid)
577577
}
578578
}
579579
}
580580
@ check-in:&nbsp;\
581
- hyperlink_to_uuid(zCkin);
581
+ hyperlink_to_version(zCkin);
582582
if( fShowId ){
583583
@ (%d(fmid))
584584
}
585585
@ user:&nbsp;\
586586
hyperlink_to_user(zUser, zDate, ",");
587587
--- src/finfo.c
+++ src/finfo.c
@@ -284,12 +284,12 @@
284 ** b=DATETIME Only show changes before DATETIME
285 ** m=HASH Mark this particular file version
286 ** n=NUM Show the first NUM changes only
287 ** brbg Background color by branch name
288 ** ubg Background color by user name
289 ** ci=UUID Ancestors of a particular check-in
290 ** orig=UUID If both ci and orig are supplied, only show those
291 ** changes on a direct path from orig to ci.
292 ** showid Show RID values for debugging
293 **
294 ** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
295 ** year-month-day form, it may be truncated, and it may also name a
@@ -371,13 +371,13 @@
371 " datetime(min(event.mtime),toLocal())," /* Date of change */
372 " coalesce(event.ecomment, event.comment)," /* Check-in comment */
373 " coalesce(event.euser, event.user)," /* User who made chng */
374 " mlink.pid," /* Parent file rid */
375 " mlink.fid," /* File rid */
376 " (SELECT uuid FROM blob WHERE rid=mlink.pid)," /* Parent file uuid */
377 " blob.uuid," /* Current file uuid */
378 " (SELECT uuid FROM blob WHERE rid=mlink.mid)," /* Check-in uuid */
379 " event.bgcolor," /* Background color */
380 " (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0"
381 " AND tagxref.rid=mlink.mid)," /* Branchname */
382 " mlink.mid," /* check-in ID */
383 " mlink.pfnid," /* Previous filename */
@@ -541,13 +541,13 @@
541 if( tmFlags & TIMELINE_COMPACT ){
542 @ <span class='timelineCompactComment' data-id='%d(frid)'>
543 }else{
544 @ <span class='timeline%s(zStyle)Comment'>
545 if( (tmFlags & TIMELINE_VERBOSE)!=0 && zUuid ){
546 hyperlink_to_uuid(zUuid);
547 @ part of check-in \
548 hyperlink_to_uuid(zCkin);
549 }
550 }
551 @ %W(zCom)</span>
552 if( (tmFlags & TIMELINE_COMPACT)!=0 ){
553 @ <span class='timelineEllipsis' data-id='%d(frid)' \
@@ -576,11 +576,11 @@
576 @ id:&nbsp;%d(frid)
577 }
578 }
579 }
580 @ check-in:&nbsp;\
581 hyperlink_to_uuid(zCkin);
582 if( fShowId ){
583 @ (%d(fmid))
584 }
585 @ user:&nbsp;\
586 hyperlink_to_user(zUser, zDate, ",");
587
--- src/finfo.c
+++ src/finfo.c
@@ -284,12 +284,12 @@
284 ** b=DATETIME Only show changes before DATETIME
285 ** m=HASH Mark this particular file version
286 ** n=NUM Show the first NUM changes only
287 ** brbg Background color by branch name
288 ** ubg Background color by user name
289 ** ci=HASH Ancestors of a particular check-in
290 ** orig=HASH If both ci and orig are supplied, only show those
291 ** changes on a direct path from orig to ci.
292 ** showid Show RID values for debugging
293 **
294 ** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
295 ** year-month-day form, it may be truncated, and it may also name a
@@ -371,13 +371,13 @@
371 " datetime(min(event.mtime),toLocal())," /* Date of change */
372 " coalesce(event.ecomment, event.comment)," /* Check-in comment */
373 " coalesce(event.euser, event.user)," /* User who made chng */
374 " mlink.pid," /* Parent file rid */
375 " mlink.fid," /* File rid */
376 " (SELECT uuid FROM blob WHERE rid=mlink.pid)," /* Parent file hash */
377 " blob.uuid," /* Current file hash */
378 " (SELECT uuid FROM blob WHERE rid=mlink.mid)," /* Check-in hash */
379 " event.bgcolor," /* Background color */
380 " (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0"
381 " AND tagxref.rid=mlink.mid)," /* Branchname */
382 " mlink.mid," /* check-in ID */
383 " mlink.pfnid," /* Previous filename */
@@ -541,13 +541,13 @@
541 if( tmFlags & TIMELINE_COMPACT ){
542 @ <span class='timelineCompactComment' data-id='%d(frid)'>
543 }else{
544 @ <span class='timeline%s(zStyle)Comment'>
545 if( (tmFlags & TIMELINE_VERBOSE)!=0 && zUuid ){
546 hyperlink_to_version(zUuid);
547 @ part of check-in \
548 hyperlink_to_version(zCkin);
549 }
550 }
551 @ %W(zCom)</span>
552 if( (tmFlags & TIMELINE_COMPACT)!=0 ){
553 @ <span class='timelineEllipsis' data-id='%d(frid)' \
@@ -576,11 +576,11 @@
576 @ id:&nbsp;%d(frid)
577 }
578 }
579 }
580 @ check-in:&nbsp;\
581 hyperlink_to_version(zCkin);
582 if( fShowId ){
583 @ (%d(fmid))
584 }
585 @ user:&nbsp;\
586 hyperlink_to_user(zUser, zDate, ",");
587
--- src/fossil.fetch.js
+++ src/fossil.fetch.js
@@ -22,14 +22,15 @@
2222
- onload: callback(responseData) (default = output response to the
2323
console). In the context of the callback, the options object is
2424
"this", noting that this call may have amended the options object
2525
with state other than what the caller provided.
2626
27
- - onerror: callback(XHR onload event | exception) (default = event
28
- or exception to the console). Triggered if the request generates
29
- any response other than HTTP 200. In the context of the callback,
30
- the options object is "this".
27
+ - onerror: callback(Error object) (default = output error message
28
+ to console.error() and fossil.error()). Triggered if the request
29
+ generates any response other than HTTP 200 or suffers a connection
30
+ error or timeout while awaiting a response. In the context of the
31
+ callback, the options object is "this".
3132
3233
- method: 'POST' | 'GET' (default = 'GET'). CASE SENSITIVE!
3334
3435
- payload: anything acceptable by XHR2.send(ARG) (DOMString,
3536
Document, FormData, Blob, File, ArrayBuffer), or a plain object or
@@ -75,48 +76,39 @@
7576
"this". These can be used to, e.g., keep track of in-flight
7677
requests and update the UI accordingly, e.g. disabling/enabling DOM
7778
elements. Any exceptions triggered by beforesend/aftersend are
7879
caught and silently ignored.
7980
81
+ - timeout: integer in milliseconds specifying the XHR timeout
82
+ duration. Default = fossil.fetch.timeout.
83
+
8084
When an options object does not provide
8185
onload/onerror/beforesend/aftersend handlers of its own, this
8286
function falls to defaults which are member properties of this
8387
function with the same name, e.g. fossil.fetch.onload(). The
8488
default onload/onerror implementations route the data through the
8589
dev console and (for onerror()) through fossil.error(). The default
8690
beforesend/aftersend are no-ops. Individual pages may overwrite
8791
those members to provide default implementations suitable for the
8892
page's use, e.g. keeping track of how many in-flight
93
+
94
+ Note that this routine may add properties to the 2nd argument, so
95
+ that instance should not be kept around for later use.
8996
9097
Returns this object, noting that the XHR request is asynchronous,
9198
and still in transit (or has yet to be sent) when that happens.
9299
*/
93100
window.fossil.fetch = function f(uri,opt){
94101
const F = fossil;
95102
if(!f.onload){
96
- f.onload = (r)=>console.debug('ajax response:',r);
103
+ f.onload = (r)=>console.debug('fossil.fetch() XHR response:',r);
97104
}
98105
if(!f.onerror){
99
- f.onerror = function(e/*event or exception*/){
100
- console.error("Ajax error:",e);
101
- if(e instanceof Error){
102
- F.error('Exception:',e);
103
- }
104
- else if(e.originalTarget && e.originalTarget.responseType==='text'){
105
- const txt = e.originalTarget.responseText;
106
- try{
107
- /* The convention from the /filepage_xyz routes is to
108
- return error responses in JSON form if possible:
109
- {error: "..."}
110
- */
111
- const j = JSON.parse(txt);
112
- console.error("Error JSON:",j);
113
- if(j.error){ F.error(j.error) };
114
- }catch(e){/* Try harder */
115
- F.error(txt)
116
- }
117
- }
106
+ f.onerror = function(e/*exception*/){
107
+ console.error("fossil.fetch() XHR error:",e);
108
+ if(e instanceof Error) F.error('Exception:',e);
109
+ else F.error("Unknown error in handling of XHR request.");
118110
};
119111
}/*f.onerror()*/
120112
if(!f.parseResponseHeaders){
121113
f.parseResponseHeaders = function(h){
122114
const rc = {};
@@ -155,50 +147,62 @@
155147
const url=[F.repoUrl(uri,opt.urlParams)],
156148
x=new XMLHttpRequest();
157149
if('POST'===opt.method && 'string'===typeof opt.contentType){
158150
x.setRequestHeader('Content-Type',opt.contentType);
159151
}
160
- x.open(opt.method||'GET', url.join(''), true);
161152
if('json'===opt.responseType){
162153
/* 'json' is an extension to the supported XHR.responseType
163154
list. We use it as a flag to tell us to JSON.parse()
164155
the response. */
165156
jsonResponse = true;
166157
x.responseType = 'text';
167158
}else{
168159
x.responseType = opt.responseType||'text';
169160
}
170
- x.onload = function(e){
161
+ x.ontimeout = function(){
162
+ try{opt.aftersend()}catch(e){/*ignore*/}
163
+ opt.onerror(new Error("XHR timeout of "+x.timeout+"ms expired."));
164
+ };
165
+ x.onreadystatechange = function(){
166
+ if(XMLHttpRequest.DONE !== x.readyState) return;
171167
try{opt.aftersend()}catch(e){/*ignore*/}
172
- if(200!==this.status){
173
- opt.onerror(e);
168
+ if(200!==x.status){
169
+ let err;
170
+ try{
171
+ const j = JSON.parse(x.response);
172
+ if(j.error) err = new Error(j.error);
173
+ }catch(ex){/*ignore*/}
174
+ opt.onerror(err || new Error("HTTP response status "+x.status+"."));
174175
return;
175176
}
176177
const orh = opt.responseHeaders;
177178
let head;
178179
if(true===orh){
179
- head = f.parseResponseHeaders(this.getAllResponseHeaders());
180
+ head = f.parseResponseHeaders(x.getAllResponseHeaders());
180181
}else if('string'===typeof orh){
181
- head = this.getResponseHeader(orh);
182
+ head = x.getResponseHeader(orh);
182183
}else if(orh instanceof Array){
183184
head = {};
184185
orh.forEach((s)=>{
185186
if('string' === typeof s) head[s.toLowerCase()] = x.getResponseHeader(s);
186187
});
187188
}
188189
try{
189
- const args = [(jsonResponse && this.response)
190
- ? JSON.parse(this.response) : this.response];
190
+ const args = [(jsonResponse && x.response)
191
+ ? JSON.parse(x.response) : x.response];
191192
if(head) args.push(head);
192193
opt.onload.apply(opt, args);
193194
}catch(e){
194195
opt.onerror(e);
195196
}
196197
};
197198
try{opt.beforesend()}catch(e){/*ignore*/}
199
+ x.open(opt.method||'GET', url.join(''), true);
200
+ x.timeout = +opt.timeout || f.timeout;
198201
if(undefined!==payload) x.send(payload);
199202
else x.send();
200203
return this;
201204
};
202205
203206
window.fossil.fetch.beforesend = function(){};
204207
window.fossil.fetch.aftersend = function(){};
208
+window.fossil.fetch.timeout = 15000/* Default timeout, in ms. */;
205209
--- src/fossil.fetch.js
+++ src/fossil.fetch.js
@@ -22,14 +22,15 @@
22 - onload: callback(responseData) (default = output response to the
23 console). In the context of the callback, the options object is
24 "this", noting that this call may have amended the options object
25 with state other than what the caller provided.
26
27 - onerror: callback(XHR onload event | exception) (default = event
28 or exception to the console). Triggered if the request generates
29 any response other than HTTP 200. In the context of the callback,
30 the options object is "this".
 
31
32 - method: 'POST' | 'GET' (default = 'GET'). CASE SENSITIVE!
33
34 - payload: anything acceptable by XHR2.send(ARG) (DOMString,
35 Document, FormData, Blob, File, ArrayBuffer), or a plain object or
@@ -75,48 +76,39 @@
75 "this". These can be used to, e.g., keep track of in-flight
76 requests and update the UI accordingly, e.g. disabling/enabling DOM
77 elements. Any exceptions triggered by beforesend/aftersend are
78 caught and silently ignored.
79
 
 
 
80 When an options object does not provide
81 onload/onerror/beforesend/aftersend handlers of its own, this
82 function falls to defaults which are member properties of this
83 function with the same name, e.g. fossil.fetch.onload(). The
84 default onload/onerror implementations route the data through the
85 dev console and (for onerror()) through fossil.error(). The default
86 beforesend/aftersend are no-ops. Individual pages may overwrite
87 those members to provide default implementations suitable for the
88 page's use, e.g. keeping track of how many in-flight
 
 
 
89
90 Returns this object, noting that the XHR request is asynchronous,
91 and still in transit (or has yet to be sent) when that happens.
92 */
93 window.fossil.fetch = function f(uri,opt){
94 const F = fossil;
95 if(!f.onload){
96 f.onload = (r)=>console.debug('ajax response:',r);
97 }
98 if(!f.onerror){
99 f.onerror = function(e/*event or exception*/){
100 console.error("Ajax error:",e);
101 if(e instanceof Error){
102 F.error('Exception:',e);
103 }
104 else if(e.originalTarget && e.originalTarget.responseType==='text'){
105 const txt = e.originalTarget.responseText;
106 try{
107 /* The convention from the /filepage_xyz routes is to
108 return error responses in JSON form if possible:
109 {error: "..."}
110 */
111 const j = JSON.parse(txt);
112 console.error("Error JSON:",j);
113 if(j.error){ F.error(j.error) };
114 }catch(e){/* Try harder */
115 F.error(txt)
116 }
117 }
118 };
119 }/*f.onerror()*/
120 if(!f.parseResponseHeaders){
121 f.parseResponseHeaders = function(h){
122 const rc = {};
@@ -155,50 +147,62 @@
155 const url=[F.repoUrl(uri,opt.urlParams)],
156 x=new XMLHttpRequest();
157 if('POST'===opt.method && 'string'===typeof opt.contentType){
158 x.setRequestHeader('Content-Type',opt.contentType);
159 }
160 x.open(opt.method||'GET', url.join(''), true);
161 if('json'===opt.responseType){
162 /* 'json' is an extension to the supported XHR.responseType
163 list. We use it as a flag to tell us to JSON.parse()
164 the response. */
165 jsonResponse = true;
166 x.responseType = 'text';
167 }else{
168 x.responseType = opt.responseType||'text';
169 }
170 x.onload = function(e){
 
 
 
 
 
171 try{opt.aftersend()}catch(e){/*ignore*/}
172 if(200!==this.status){
173 opt.onerror(e);
 
 
 
 
 
174 return;
175 }
176 const orh = opt.responseHeaders;
177 let head;
178 if(true===orh){
179 head = f.parseResponseHeaders(this.getAllResponseHeaders());
180 }else if('string'===typeof orh){
181 head = this.getResponseHeader(orh);
182 }else if(orh instanceof Array){
183 head = {};
184 orh.forEach((s)=>{
185 if('string' === typeof s) head[s.toLowerCase()] = x.getResponseHeader(s);
186 });
187 }
188 try{
189 const args = [(jsonResponse && this.response)
190 ? JSON.parse(this.response) : this.response];
191 if(head) args.push(head);
192 opt.onload.apply(opt, args);
193 }catch(e){
194 opt.onerror(e);
195 }
196 };
197 try{opt.beforesend()}catch(e){/*ignore*/}
 
 
198 if(undefined!==payload) x.send(payload);
199 else x.send();
200 return this;
201 };
202
203 window.fossil.fetch.beforesend = function(){};
204 window.fossil.fetch.aftersend = function(){};
 
205
--- src/fossil.fetch.js
+++ src/fossil.fetch.js
@@ -22,14 +22,15 @@
22 - onload: callback(responseData) (default = output response to the
23 console). In the context of the callback, the options object is
24 "this", noting that this call may have amended the options object
25 with state other than what the caller provided.
26
27 - onerror: callback(Error object) (default = output error message
28 to console.error() and fossil.error()). Triggered if the request
29 generates any response other than HTTP 200 or suffers a connection
30 error or timeout while awaiting a response. In the context of the
31 callback, the options object is "this".
32
33 - method: 'POST' | 'GET' (default = 'GET'). CASE SENSITIVE!
34
35 - payload: anything acceptable by XHR2.send(ARG) (DOMString,
36 Document, FormData, Blob, File, ArrayBuffer), or a plain object or
@@ -75,48 +76,39 @@
76 "this". These can be used to, e.g., keep track of in-flight
77 requests and update the UI accordingly, e.g. disabling/enabling DOM
78 elements. Any exceptions triggered by beforesend/aftersend are
79 caught and silently ignored.
80
81 - timeout: integer in milliseconds specifying the XHR timeout
82 duration. Default = fossil.fetch.timeout.
83
84 When an options object does not provide
85 onload/onerror/beforesend/aftersend handlers of its own, this
86 function falls to defaults which are member properties of this
87 function with the same name, e.g. fossil.fetch.onload(). The
88 default onload/onerror implementations route the data through the
89 dev console and (for onerror()) through fossil.error(). The default
90 beforesend/aftersend are no-ops. Individual pages may overwrite
91 those members to provide default implementations suitable for the
92 page's use, e.g. keeping track of how many in-flight
93
94 Note that this routine may add properties to the 2nd argument, so
95 that instance should not be kept around for later use.
96
97 Returns this object, noting that the XHR request is asynchronous,
98 and still in transit (or has yet to be sent) when that happens.
99 */
100 window.fossil.fetch = function f(uri,opt){
101 const F = fossil;
102 if(!f.onload){
103 f.onload = (r)=>console.debug('fossil.fetch() XHR response:',r);
104 }
105 if(!f.onerror){
106 f.onerror = function(e/*exception*/){
107 console.error("fossil.fetch() XHR error:",e);
108 if(e instanceof Error) F.error('Exception:',e);
109 else F.error("Unknown error in handling of XHR request.");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110 };
111 }/*f.onerror()*/
112 if(!f.parseResponseHeaders){
113 f.parseResponseHeaders = function(h){
114 const rc = {};
@@ -155,50 +147,62 @@
147 const url=[F.repoUrl(uri,opt.urlParams)],
148 x=new XMLHttpRequest();
149 if('POST'===opt.method && 'string'===typeof opt.contentType){
150 x.setRequestHeader('Content-Type',opt.contentType);
151 }
 
152 if('json'===opt.responseType){
153 /* 'json' is an extension to the supported XHR.responseType
154 list. We use it as a flag to tell us to JSON.parse()
155 the response. */
156 jsonResponse = true;
157 x.responseType = 'text';
158 }else{
159 x.responseType = opt.responseType||'text';
160 }
161 x.ontimeout = function(){
162 try{opt.aftersend()}catch(e){/*ignore*/}
163 opt.onerror(new Error("XHR timeout of "+x.timeout+"ms expired."));
164 };
165 x.onreadystatechange = function(){
166 if(XMLHttpRequest.DONE !== x.readyState) return;
167 try{opt.aftersend()}catch(e){/*ignore*/}
168 if(200!==x.status){
169 let err;
170 try{
171 const j = JSON.parse(x.response);
172 if(j.error) err = new Error(j.error);
173 }catch(ex){/*ignore*/}
174 opt.onerror(err || new Error("HTTP response status "+x.status+"."));
175 return;
176 }
177 const orh = opt.responseHeaders;
178 let head;
179 if(true===orh){
180 head = f.parseResponseHeaders(x.getAllResponseHeaders());
181 }else if('string'===typeof orh){
182 head = x.getResponseHeader(orh);
183 }else if(orh instanceof Array){
184 head = {};
185 orh.forEach((s)=>{
186 if('string' === typeof s) head[s.toLowerCase()] = x.getResponseHeader(s);
187 });
188 }
189 try{
190 const args = [(jsonResponse && x.response)
191 ? JSON.parse(x.response) : x.response];
192 if(head) args.push(head);
193 opt.onload.apply(opt, args);
194 }catch(e){
195 opt.onerror(e);
196 }
197 };
198 try{opt.beforesend()}catch(e){/*ignore*/}
199 x.open(opt.method||'GET', url.join(''), true);
200 x.timeout = +opt.timeout || f.timeout;
201 if(undefined!==payload) x.send(payload);
202 else x.send();
203 return this;
204 };
205
206 window.fossil.fetch.beforesend = function(){};
207 window.fossil.fetch.aftersend = function(){};
208 window.fossil.fetch.timeout = 15000/* Default timeout, in ms. */;
209
+10 -9
--- src/import.c
+++ src/import.c
@@ -26,11 +26,11 @@
2626
/*
2727
** A single file change record.
2828
*/
2929
struct ImportFile {
3030
char *zName; /* Name of a file */
31
- char *zUuid; /* UUID of the file */
31
+ char *zUuid; /* Hash of the file */
3232
char *zPrior; /* Prior name if the name was changed */
3333
char isFrom; /* True if obtained from the parent */
3434
char isExe; /* True if executable */
3535
char isLink; /* True if symlink */
3636
};
@@ -59,11 +59,11 @@
5959
char *aData; /* Data content */
6060
char *zMark; /* The current mark */
6161
char *zDate; /* Date/time stamp */
6262
char *zUser; /* User name */
6363
char *zComment; /* Comment of a commit */
64
- char *zFrom; /* from value as a UUID */
64
+ char *zFrom; /* from value as a hash */
6565
char *zPrevCheckin; /* Name of the previous check-in */
6666
char *zFromMark; /* The mark of the "from" field */
6767
int nMerge; /* Number of merge values */
6868
int nMergeAlloc; /* Number of slots in azMerge[] */
6969
char **azMerge; /* Merge values */
@@ -143,17 +143,17 @@
143143
/*
144144
** Insert an artifact into the BLOB table if it isn't there already.
145145
** If zMark is not zero, create a cross-reference from that mark back
146146
** to the newly inserted artifact.
147147
**
148
-** If saveUuid is true, then pContent is a commit record. Record its
149
-** UUID in gg.zPrevCheckin.
148
+** If saveHash is true, then pContent is a commit record. Record its
149
+** artifact hash in gg.zPrevCheckin.
150150
*/
151151
static int fast_insert_content(
152152
Blob *pContent, /* Content to insert */
153153
const char *zMark, /* Label using this mark, if not NULL */
154
- int saveUuid, /* Save artifact hash in gg.zPrevCheckin */
154
+ int saveHash, /* Save artifact hash in gg.zPrevCheckin */
155155
int doParse /* Invoke manifest_crosslink() */
156156
){
157157
Blob hash;
158158
Blob cmpr;
159159
int rid;
@@ -187,11 +187,11 @@
187187
"INSERT OR IGNORE INTO xmark(tname, trid, tuuid)"
188188
"VALUES(%B,%d,%B)",
189189
&hash, rid, &hash
190190
);
191191
}
192
- if( saveUuid ){
192
+ if( saveHash ){
193193
fossil_free(gg.zPrevCheckin);
194194
gg.zPrevCheckin = fossil_strdup(blob_str(&hash));
195195
}
196196
blob_reset(&hash);
197197
return rid;
@@ -411,11 +411,11 @@
411411
}
412412
return z;
413413
}
414414
415415
/*
416
-** Convert a "mark" or "committish" into the UUID.
416
+** Convert a "mark" or "committish" into the artifact hash.
417417
*/
418418
static char *resolve_committish(const char *zCommittish){
419419
char *zRes;
420420
421421
zRes = db_text(0, "SELECT tuuid FROM xmark WHERE tname=%Q", zCommittish);
@@ -1828,13 +1828,14 @@
18281828
bag_init(&vers);
18291829
/* The following temp-tables are used to hold information needed for
18301830
** the import.
18311831
**
18321832
** The XMARK table provides a mapping from fast-import "marks" and symbols
1833
- ** into artifact ids (UUIDs - the 40-byte hex SHA1 hash of artifacts).
1833
+ ** into artifact hashes.
1834
+ **
18341835
** Given any valid fast-import symbol, the corresponding fossil rid and
1835
- ** uuid can found by searching against the xmark.tname field.
1836
+ ** hash can found by searching against the xmark.tname field.
18361837
**
18371838
** The XBRANCH table maps commit marks and symbols into the branch those
18381839
** commits belong to. If xbranch.tname is a fast-import symbol for a
18391840
** check-in then xbranch.brnm is the branch that check-in is part of.
18401841
**
18411842
--- src/import.c
+++ src/import.c
@@ -26,11 +26,11 @@
26 /*
27 ** A single file change record.
28 */
29 struct ImportFile {
30 char *zName; /* Name of a file */
31 char *zUuid; /* UUID of the file */
32 char *zPrior; /* Prior name if the name was changed */
33 char isFrom; /* True if obtained from the parent */
34 char isExe; /* True if executable */
35 char isLink; /* True if symlink */
36 };
@@ -59,11 +59,11 @@
59 char *aData; /* Data content */
60 char *zMark; /* The current mark */
61 char *zDate; /* Date/time stamp */
62 char *zUser; /* User name */
63 char *zComment; /* Comment of a commit */
64 char *zFrom; /* from value as a UUID */
65 char *zPrevCheckin; /* Name of the previous check-in */
66 char *zFromMark; /* The mark of the "from" field */
67 int nMerge; /* Number of merge values */
68 int nMergeAlloc; /* Number of slots in azMerge[] */
69 char **azMerge; /* Merge values */
@@ -143,17 +143,17 @@
143 /*
144 ** Insert an artifact into the BLOB table if it isn't there already.
145 ** If zMark is not zero, create a cross-reference from that mark back
146 ** to the newly inserted artifact.
147 **
148 ** If saveUuid is true, then pContent is a commit record. Record its
149 ** UUID in gg.zPrevCheckin.
150 */
151 static int fast_insert_content(
152 Blob *pContent, /* Content to insert */
153 const char *zMark, /* Label using this mark, if not NULL */
154 int saveUuid, /* Save artifact hash in gg.zPrevCheckin */
155 int doParse /* Invoke manifest_crosslink() */
156 ){
157 Blob hash;
158 Blob cmpr;
159 int rid;
@@ -187,11 +187,11 @@
187 "INSERT OR IGNORE INTO xmark(tname, trid, tuuid)"
188 "VALUES(%B,%d,%B)",
189 &hash, rid, &hash
190 );
191 }
192 if( saveUuid ){
193 fossil_free(gg.zPrevCheckin);
194 gg.zPrevCheckin = fossil_strdup(blob_str(&hash));
195 }
196 blob_reset(&hash);
197 return rid;
@@ -411,11 +411,11 @@
411 }
412 return z;
413 }
414
415 /*
416 ** Convert a "mark" or "committish" into the UUID.
417 */
418 static char *resolve_committish(const char *zCommittish){
419 char *zRes;
420
421 zRes = db_text(0, "SELECT tuuid FROM xmark WHERE tname=%Q", zCommittish);
@@ -1828,13 +1828,14 @@
1828 bag_init(&vers);
1829 /* The following temp-tables are used to hold information needed for
1830 ** the import.
1831 **
1832 ** The XMARK table provides a mapping from fast-import "marks" and symbols
1833 ** into artifact ids (UUIDs - the 40-byte hex SHA1 hash of artifacts).
 
1834 ** Given any valid fast-import symbol, the corresponding fossil rid and
1835 ** uuid can found by searching against the xmark.tname field.
1836 **
1837 ** The XBRANCH table maps commit marks and symbols into the branch those
1838 ** commits belong to. If xbranch.tname is a fast-import symbol for a
1839 ** check-in then xbranch.brnm is the branch that check-in is part of.
1840 **
1841
--- src/import.c
+++ src/import.c
@@ -26,11 +26,11 @@
26 /*
27 ** A single file change record.
28 */
29 struct ImportFile {
30 char *zName; /* Name of a file */
31 char *zUuid; /* Hash of the file */
32 char *zPrior; /* Prior name if the name was changed */
33 char isFrom; /* True if obtained from the parent */
34 char isExe; /* True if executable */
35 char isLink; /* True if symlink */
36 };
@@ -59,11 +59,11 @@
59 char *aData; /* Data content */
60 char *zMark; /* The current mark */
61 char *zDate; /* Date/time stamp */
62 char *zUser; /* User name */
63 char *zComment; /* Comment of a commit */
64 char *zFrom; /* from value as a hash */
65 char *zPrevCheckin; /* Name of the previous check-in */
66 char *zFromMark; /* The mark of the "from" field */
67 int nMerge; /* Number of merge values */
68 int nMergeAlloc; /* Number of slots in azMerge[] */
69 char **azMerge; /* Merge values */
@@ -143,17 +143,17 @@
143 /*
144 ** Insert an artifact into the BLOB table if it isn't there already.
145 ** If zMark is not zero, create a cross-reference from that mark back
146 ** to the newly inserted artifact.
147 **
148 ** If saveHash is true, then pContent is a commit record. Record its
149 ** artifact hash in gg.zPrevCheckin.
150 */
151 static int fast_insert_content(
152 Blob *pContent, /* Content to insert */
153 const char *zMark, /* Label using this mark, if not NULL */
154 int saveHash, /* Save artifact hash in gg.zPrevCheckin */
155 int doParse /* Invoke manifest_crosslink() */
156 ){
157 Blob hash;
158 Blob cmpr;
159 int rid;
@@ -187,11 +187,11 @@
187 "INSERT OR IGNORE INTO xmark(tname, trid, tuuid)"
188 "VALUES(%B,%d,%B)",
189 &hash, rid, &hash
190 );
191 }
192 if( saveHash ){
193 fossil_free(gg.zPrevCheckin);
194 gg.zPrevCheckin = fossil_strdup(blob_str(&hash));
195 }
196 blob_reset(&hash);
197 return rid;
@@ -411,11 +411,11 @@
411 }
412 return z;
413 }
414
415 /*
416 ** Convert a "mark" or "committish" into the artifact hash.
417 */
418 static char *resolve_committish(const char *zCommittish){
419 char *zRes;
420
421 zRes = db_text(0, "SELECT tuuid FROM xmark WHERE tname=%Q", zCommittish);
@@ -1828,13 +1828,14 @@
1828 bag_init(&vers);
1829 /* The following temp-tables are used to hold information needed for
1830 ** the import.
1831 **
1832 ** The XMARK table provides a mapping from fast-import "marks" and symbols
1833 ** into artifact hashes.
1834 **
1835 ** Given any valid fast-import symbol, the corresponding fossil rid and
1836 ** hash can found by searching against the xmark.tname field.
1837 **
1838 ** The XBRANCH table maps commit marks and symbols into the branch those
1839 ** commits belong to. If xbranch.tname is a fast-import symbol for a
1840 ** check-in then xbranch.brnm is the branch that check-in is part of.
1841 **
1842
+29 -27
--- src/info.c
+++ src/info.c
@@ -54,19 +54,19 @@
5454
5555
5656
/*
5757
** Print common information about a particular record.
5858
**
59
-** * The UUID
59
+** * The artifact hash
6060
** * The record ID
6161
** * mtime and ctime
6262
** * who signed it
6363
**
6464
*/
6565
void show_common_info(
6666
int rid, /* The rid for the check-in to display info for */
67
- const char *zUuidName, /* Name of the UUID */
67
+ const char *zRecDesc, /* Brief record description; e.g. "checkout:" */
6868
int showComment, /* True to show the check-in comment */
6969
int showFamily /* True to show parents and children */
7070
){
7171
Stmt q;
7272
char *zComment = 0;
@@ -78,11 +78,11 @@
7878
zDate = db_text(0,
7979
"SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
8080
rid
8181
);
8282
/* 01234567890123 */
83
- fossil_print("%-13s %.40s %s\n", zUuidName, zUuid, zDate ? zDate : "");
83
+ fossil_print("%-13s %.40s %s\n", zRecDesc, zUuid, zDate ? zDate : "");
8484
free(zDate);
8585
if( showComment ){
8686
zComment = db_text(0,
8787
"SELECT coalesce(ecomment,comment) || "
8888
" ' (user: ' || coalesce(euser,user,'?') || ')' "
@@ -274,11 +274,11 @@
274274
int rid;
275275
rid = name_to_rid(g.argv[2]);
276276
if( rid==0 ){
277277
fossil_fatal("no such object: %s", g.argv[2]);
278278
}
279
- show_common_info(rid, "uuid:", 1, 1);
279
+ show_common_info(rid, "hash:", 1, 1);
280280
}
281281
}
282282
283283
/*
284284
** Show the context graph (immediate parents and children) for
@@ -747,11 +747,11 @@
747747
@ <span class="infoTag">%h(zTagname)</span>
748748
}
749749
if( tagtype==2 ){
750750
if( zOrigUuid && zOrigUuid[0] ){
751751
@ inherited from
752
- hyperlink_to_uuid(zOrigUuid);
752
+ hyperlink_to_version(zOrigUuid);
753753
}else{
754754
@ propagates to descendants
755755
}
756756
}
757757
if( zSrcUuid && zSrcUuid[0] ){
@@ -758,11 +758,11 @@
758758
if( tagtype==0 ){
759759
@ by
760760
}else{
761761
@ added by
762762
}
763
- hyperlink_to_uuid(zSrcUuid);
763
+ hyperlink_to_version(zSrcUuid);
764764
@ on
765765
hyperlink_to_date(zDate,0);
766766
}
767767
@ </li>
768768
}
@@ -829,12 +829,12 @@
829829
int rid;
830830
int isLeaf;
831831
int diffType; /* 0: no diff, 1: unified, 2: side-by-side */
832832
u64 diffFlags; /* Flag parameter for text_diff() */
833833
const char *zName; /* Name of the check-in to be displayed */
834
- const char *zUuid; /* UUID of zName */
835
- const char *zParent; /* UUID of the parent check-in (if any) */
834
+ const char *zUuid; /* Hash of zName, found via blob.uuid */
835
+ const char *zParent; /* Hash of the parent check-in (if any) */
836836
const char *zRe; /* regex parameter */
837837
ReCompiled *pRe = 0; /* regex */
838838
const char *zW; /* URL param for ignoring whitespace */
839839
const char *zPage = "vinfo"; /* Page that shows diffs */
840840
const char *zPageHide = "ci"; /* Page that hides diffs */
@@ -1324,11 +1324,11 @@
13241324
db_end_transaction(1); /* ROLLBACK */
13251325
}
13261326
13271327
/*
13281328
** WEBPAGE: winfo
1329
-** URL: /winfo?name=UUID
1329
+** URL: /winfo?name=HASH
13301330
**
13311331
** Display information about a wiki page.
13321332
*/
13331333
void winfo_page(void){
13341334
int rid;
@@ -1485,11 +1485,11 @@
14851485
Blob comment;
14861486
int wikiFlags = WIKI_INLINE|WIKI_NOBADLINKS;
14871487
if( db_get_boolean("timeline-block-markup", 0)==0 ){
14881488
wikiFlags |= WIKI_NOBLOCK;
14891489
}
1490
- hyperlink_to_uuid(zUuid);
1490
+ hyperlink_to_version(zUuid);
14911491
blob_zero(&comment);
14921492
db_column_blob(&q, 2, &comment);
14931493
wiki_convert(&comment, 0, wikiFlags);
14941494
blob_reset(&comment);
14951495
@ (user:
@@ -1813,14 +1813,14 @@
18131813
}
18141814
if( showDetail ){
18151815
@ <li>
18161816
hyperlink_to_date(zDate,"");
18171817
@ &mdash; part of check-in
1818
- hyperlink_to_uuid(zVers);
1818
+ hyperlink_to_version(zVers);
18191819
}else{
18201820
@ &mdash; part of check-in
1821
- hyperlink_to_uuid(zVers);
1821
+ hyperlink_to_version(zVers);
18221822
@ at
18231823
hyperlink_to_date(zDate,"");
18241824
}
18251825
if( zBr && zBr[0] ){
18261826
@ on branch %z(href("%R/timeline?r=%T",zBr))%h(zBr)</a>
@@ -1919,11 +1919,11 @@
19191919
@ Forum post
19201920
}else{
19211921
@ Tag referencing
19221922
}
19231923
if( zType[0]!='e' || eventTagId == 0){
1924
- hyperlink_to_uuid(zUuid);
1924
+ hyperlink_to_version(zUuid);
19251925
}
19261926
@ - %!W(zCom) by
19271927
hyperlink_to_user(zUser,zDate," on");
19281928
hyperlink_to_date(zDate, ".");
19291929
if( pDownloadName && blob_size(pDownloadName)==0 ){
@@ -1951,11 +1951,11 @@
19511951
@ Also attachment "%h(zFilename)" to
19521952
}else{
19531953
@ Attachment "%h(zFilename)" to
19541954
}
19551955
objType |= OBJTYPE_ATTACHMENT;
1956
- if( fossil_is_uuid(zTarget) ){
1956
+ if( fossil_is_artifact_hash(zTarget) ){
19571957
if( db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'",
19581958
zTarget)
19591959
){
19601960
if( g.perm.Hyperlink && g.anon.RdTkt ){
19611961
@ ticket [%z(href("%R/tktview?name=%!S",zTarget))%S(zTarget)</a>]
@@ -2011,11 +2011,11 @@
20112011
20122012
20132013
/*
20142014
** WEBPAGE: fdiff
20152015
** WEBPAGE: localdiff
2016
-** URL: fdiff?v1=UUID&v2=UUID
2016
+** URL: fdiff?v1=HASH&v2=HASH
20172017
** URL: localdiff?name=filename
20182018
**
20192019
** Two arguments, v1 and v2, identify the artifacts to be diffed.
20202020
** Show diff side by side unless sbs is 0. Generate plain text if
20212021
** "patch" is present, otherwise generate "pretty" HTML.
@@ -2227,18 +2227,18 @@
22272227
** is by the full-length SHA1 or SHA3 hash. Abbreviations are not
22282228
** accepted.
22292229
*/
22302230
void secure_rawartifact_page(void){
22312231
int rid = 0;
2232
- const char *zUuid = PD("name", "");
2232
+ const char *zName = PD("name", "");
22332233
22342234
login_check_credentials();
22352235
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
2236
- rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", zUuid);
2236
+ rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", zName);
22372237
if( rid==0 ){
22382238
cgi_set_status(404, "Not Found");
2239
- @ Unknown artifact: "%h(zUuid)"
2239
+ @ Unknown artifact: "%h(zName)"
22402240
return;
22412241
}
22422242
g.isConst = 1;
22432243
deliver_artifact(rid, P("m"));
22442244
}
@@ -3025,16 +3025,18 @@
30253025
}
30263026
30273027
30283028
/*
30293029
** WEBPAGE: info
3030
-** URL: info/ARTIFACTID
3030
+** URL: info/NAME
30313031
**
3032
-** The argument is a artifact ID which might be a check-in or a file or
3033
-** a ticket changes or a wiki edit or something else.
3032
+** The NAME argument is any valid artifact name: an artifact hash,
3033
+** a timestamp, a tag name, etc.
30343034
**
3035
-** Figure out what the artifact ID is and display it appropriately.
3035
+** Because NAME can match so many different things (commit artifacts,
3036
+** wiki pages, ticket comments, forum posts...) the format of the output
3037
+** page depends on the type of artifact that NAME matches.
30363038
*/
30373039
void info_page(void){
30383040
const char *zName;
30393041
Blob uuid;
30403042
int rid;
@@ -3644,17 +3646,17 @@
36443646
blob_append(&prompt, ".\n# Lines beginning with a # are ignored.\n", -1);
36453647
prompt_for_user_comment(pComment, &prompt);
36463648
blob_reset(&prompt);
36473649
}
36483650
3649
-#define AMEND_USAGE_STMT "UUID OPTION ?OPTION ...?"
3651
+#define AMEND_USAGE_STMT "HASH OPTION ?OPTION ...?"
36503652
/*
36513653
** COMMAND: amend
36523654
**
3653
-** Usage: %fossil amend UUID OPTION ?OPTION ...?
3655
+** Usage: %fossil amend HASH OPTION ?OPTION ...?
36543656
**
3655
-** Amend the tags on check-in UUID to change how it displays in the timeline.
3657
+** Amend the tags on check-in HASH to change how it displays in the timeline.
36563658
**
36573659
** Options:
36583660
**
36593661
** --author USER Make USER the author for check-in
36603662
** -m|--comment COMMENT Make COMMENT the check-in comment
@@ -3738,11 +3740,11 @@
37383740
verify_all_options();
37393741
if( g.argc<3 || g.argc>=4 ) usage(AMEND_USAGE_STMT);
37403742
rid = name_to_typed_rid(g.argv[2], "ci");
37413743
if( rid==0 && !is_a_version(rid) ) fossil_fatal("no such check-in");
37423744
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
3743
- if( zUuid==0 ) fossil_fatal("Unable to find UUID");
3745
+ if( zUuid==0 ) fossil_fatal("Unable to find artifact hash");
37443746
zComment = db_text(0, "SELECT coalesce(ecomment,comment)"
37453747
" FROM event WHERE objid=%d", rid);
37463748
zUser = db_text(0, "SELECT coalesce(euser,user)"
37473749
" FROM event WHERE objid=%d", rid);
37483750
zDate = db_text(0, "SELECT datetime(mtime)"
@@ -3828,11 +3830,11 @@
38283830
if( fHide && !fHasHidden ) hide_branch();
38293831
if( fClose && !fHasClosed ) close_leaf(rid);
38303832
if( zNewBranch && zNewBranch[0] ) change_branch(rid,zNewBranch);
38313833
apply_newtags(&ctrl, rid, zUuid, zUserOvrd, fDryRun);
38323834
if( fDryRun==0 ){
3833
- show_common_info(rid, "uuid:", 1, 0);
3835
+ show_common_info(rid, "hash:", 1, 0);
38343836
}
38353837
if( g.localOpen ){
38363838
manifest_to_disk(rid);
38373839
}
38383840
}
38393841
--- src/info.c
+++ src/info.c
@@ -54,19 +54,19 @@
54
55
56 /*
57 ** Print common information about a particular record.
58 **
59 ** * The UUID
60 ** * The record ID
61 ** * mtime and ctime
62 ** * who signed it
63 **
64 */
65 void show_common_info(
66 int rid, /* The rid for the check-in to display info for */
67 const char *zUuidName, /* Name of the UUID */
68 int showComment, /* True to show the check-in comment */
69 int showFamily /* True to show parents and children */
70 ){
71 Stmt q;
72 char *zComment = 0;
@@ -78,11 +78,11 @@
78 zDate = db_text(0,
79 "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
80 rid
81 );
82 /* 01234567890123 */
83 fossil_print("%-13s %.40s %s\n", zUuidName, zUuid, zDate ? zDate : "");
84 free(zDate);
85 if( showComment ){
86 zComment = db_text(0,
87 "SELECT coalesce(ecomment,comment) || "
88 " ' (user: ' || coalesce(euser,user,'?') || ')' "
@@ -274,11 +274,11 @@
274 int rid;
275 rid = name_to_rid(g.argv[2]);
276 if( rid==0 ){
277 fossil_fatal("no such object: %s", g.argv[2]);
278 }
279 show_common_info(rid, "uuid:", 1, 1);
280 }
281 }
282
283 /*
284 ** Show the context graph (immediate parents and children) for
@@ -747,11 +747,11 @@
747 @ <span class="infoTag">%h(zTagname)</span>
748 }
749 if( tagtype==2 ){
750 if( zOrigUuid && zOrigUuid[0] ){
751 @ inherited from
752 hyperlink_to_uuid(zOrigUuid);
753 }else{
754 @ propagates to descendants
755 }
756 }
757 if( zSrcUuid && zSrcUuid[0] ){
@@ -758,11 +758,11 @@
758 if( tagtype==0 ){
759 @ by
760 }else{
761 @ added by
762 }
763 hyperlink_to_uuid(zSrcUuid);
764 @ on
765 hyperlink_to_date(zDate,0);
766 }
767 @ </li>
768 }
@@ -829,12 +829,12 @@
829 int rid;
830 int isLeaf;
831 int diffType; /* 0: no diff, 1: unified, 2: side-by-side */
832 u64 diffFlags; /* Flag parameter for text_diff() */
833 const char *zName; /* Name of the check-in to be displayed */
834 const char *zUuid; /* UUID of zName */
835 const char *zParent; /* UUID of the parent check-in (if any) */
836 const char *zRe; /* regex parameter */
837 ReCompiled *pRe = 0; /* regex */
838 const char *zW; /* URL param for ignoring whitespace */
839 const char *zPage = "vinfo"; /* Page that shows diffs */
840 const char *zPageHide = "ci"; /* Page that hides diffs */
@@ -1324,11 +1324,11 @@
1324 db_end_transaction(1); /* ROLLBACK */
1325 }
1326
1327 /*
1328 ** WEBPAGE: winfo
1329 ** URL: /winfo?name=UUID
1330 **
1331 ** Display information about a wiki page.
1332 */
1333 void winfo_page(void){
1334 int rid;
@@ -1485,11 +1485,11 @@
1485 Blob comment;
1486 int wikiFlags = WIKI_INLINE|WIKI_NOBADLINKS;
1487 if( db_get_boolean("timeline-block-markup", 0)==0 ){
1488 wikiFlags |= WIKI_NOBLOCK;
1489 }
1490 hyperlink_to_uuid(zUuid);
1491 blob_zero(&comment);
1492 db_column_blob(&q, 2, &comment);
1493 wiki_convert(&comment, 0, wikiFlags);
1494 blob_reset(&comment);
1495 @ (user:
@@ -1813,14 +1813,14 @@
1813 }
1814 if( showDetail ){
1815 @ <li>
1816 hyperlink_to_date(zDate,"");
1817 @ &mdash; part of check-in
1818 hyperlink_to_uuid(zVers);
1819 }else{
1820 @ &mdash; part of check-in
1821 hyperlink_to_uuid(zVers);
1822 @ at
1823 hyperlink_to_date(zDate,"");
1824 }
1825 if( zBr && zBr[0] ){
1826 @ on branch %z(href("%R/timeline?r=%T",zBr))%h(zBr)</a>
@@ -1919,11 +1919,11 @@
1919 @ Forum post
1920 }else{
1921 @ Tag referencing
1922 }
1923 if( zType[0]!='e' || eventTagId == 0){
1924 hyperlink_to_uuid(zUuid);
1925 }
1926 @ - %!W(zCom) by
1927 hyperlink_to_user(zUser,zDate," on");
1928 hyperlink_to_date(zDate, ".");
1929 if( pDownloadName && blob_size(pDownloadName)==0 ){
@@ -1951,11 +1951,11 @@
1951 @ Also attachment "%h(zFilename)" to
1952 }else{
1953 @ Attachment "%h(zFilename)" to
1954 }
1955 objType |= OBJTYPE_ATTACHMENT;
1956 if( fossil_is_uuid(zTarget) ){
1957 if( db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'",
1958 zTarget)
1959 ){
1960 if( g.perm.Hyperlink && g.anon.RdTkt ){
1961 @ ticket [%z(href("%R/tktview?name=%!S",zTarget))%S(zTarget)</a>]
@@ -2011,11 +2011,11 @@
2011
2012
2013 /*
2014 ** WEBPAGE: fdiff
2015 ** WEBPAGE: localdiff
2016 ** URL: fdiff?v1=UUID&v2=UUID
2017 ** URL: localdiff?name=filename
2018 **
2019 ** Two arguments, v1 and v2, identify the artifacts to be diffed.
2020 ** Show diff side by side unless sbs is 0. Generate plain text if
2021 ** "patch" is present, otherwise generate "pretty" HTML.
@@ -2227,18 +2227,18 @@
2227 ** is by the full-length SHA1 or SHA3 hash. Abbreviations are not
2228 ** accepted.
2229 */
2230 void secure_rawartifact_page(void){
2231 int rid = 0;
2232 const char *zUuid = PD("name", "");
2233
2234 login_check_credentials();
2235 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
2236 rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", zUuid);
2237 if( rid==0 ){
2238 cgi_set_status(404, "Not Found");
2239 @ Unknown artifact: "%h(zUuid)"
2240 return;
2241 }
2242 g.isConst = 1;
2243 deliver_artifact(rid, P("m"));
2244 }
@@ -3025,16 +3025,18 @@
3025 }
3026
3027
3028 /*
3029 ** WEBPAGE: info
3030 ** URL: info/ARTIFACTID
3031 **
3032 ** The argument is a artifact ID which might be a check-in or a file or
3033 ** a ticket changes or a wiki edit or something else.
3034 **
3035 ** Figure out what the artifact ID is and display it appropriately.
 
 
3036 */
3037 void info_page(void){
3038 const char *zName;
3039 Blob uuid;
3040 int rid;
@@ -3644,17 +3646,17 @@
3644 blob_append(&prompt, ".\n# Lines beginning with a # are ignored.\n", -1);
3645 prompt_for_user_comment(pComment, &prompt);
3646 blob_reset(&prompt);
3647 }
3648
3649 #define AMEND_USAGE_STMT "UUID OPTION ?OPTION ...?"
3650 /*
3651 ** COMMAND: amend
3652 **
3653 ** Usage: %fossil amend UUID OPTION ?OPTION ...?
3654 **
3655 ** Amend the tags on check-in UUID to change how it displays in the timeline.
3656 **
3657 ** Options:
3658 **
3659 ** --author USER Make USER the author for check-in
3660 ** -m|--comment COMMENT Make COMMENT the check-in comment
@@ -3738,11 +3740,11 @@
3738 verify_all_options();
3739 if( g.argc<3 || g.argc>=4 ) usage(AMEND_USAGE_STMT);
3740 rid = name_to_typed_rid(g.argv[2], "ci");
3741 if( rid==0 && !is_a_version(rid) ) fossil_fatal("no such check-in");
3742 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
3743 if( zUuid==0 ) fossil_fatal("Unable to find UUID");
3744 zComment = db_text(0, "SELECT coalesce(ecomment,comment)"
3745 " FROM event WHERE objid=%d", rid);
3746 zUser = db_text(0, "SELECT coalesce(euser,user)"
3747 " FROM event WHERE objid=%d", rid);
3748 zDate = db_text(0, "SELECT datetime(mtime)"
@@ -3828,11 +3830,11 @@
3828 if( fHide && !fHasHidden ) hide_branch();
3829 if( fClose && !fHasClosed ) close_leaf(rid);
3830 if( zNewBranch && zNewBranch[0] ) change_branch(rid,zNewBranch);
3831 apply_newtags(&ctrl, rid, zUuid, zUserOvrd, fDryRun);
3832 if( fDryRun==0 ){
3833 show_common_info(rid, "uuid:", 1, 0);
3834 }
3835 if( g.localOpen ){
3836 manifest_to_disk(rid);
3837 }
3838 }
3839
--- src/info.c
+++ src/info.c
@@ -54,19 +54,19 @@
54
55
56 /*
57 ** Print common information about a particular record.
58 **
59 ** * The artifact hash
60 ** * The record ID
61 ** * mtime and ctime
62 ** * who signed it
63 **
64 */
65 void show_common_info(
66 int rid, /* The rid for the check-in to display info for */
67 const char *zRecDesc, /* Brief record description; e.g. "checkout:" */
68 int showComment, /* True to show the check-in comment */
69 int showFamily /* True to show parents and children */
70 ){
71 Stmt q;
72 char *zComment = 0;
@@ -78,11 +78,11 @@
78 zDate = db_text(0,
79 "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
80 rid
81 );
82 /* 01234567890123 */
83 fossil_print("%-13s %.40s %s\n", zRecDesc, zUuid, zDate ? zDate : "");
84 free(zDate);
85 if( showComment ){
86 zComment = db_text(0,
87 "SELECT coalesce(ecomment,comment) || "
88 " ' (user: ' || coalesce(euser,user,'?') || ')' "
@@ -274,11 +274,11 @@
274 int rid;
275 rid = name_to_rid(g.argv[2]);
276 if( rid==0 ){
277 fossil_fatal("no such object: %s", g.argv[2]);
278 }
279 show_common_info(rid, "hash:", 1, 1);
280 }
281 }
282
283 /*
284 ** Show the context graph (immediate parents and children) for
@@ -747,11 +747,11 @@
747 @ <span class="infoTag">%h(zTagname)</span>
748 }
749 if( tagtype==2 ){
750 if( zOrigUuid && zOrigUuid[0] ){
751 @ inherited from
752 hyperlink_to_version(zOrigUuid);
753 }else{
754 @ propagates to descendants
755 }
756 }
757 if( zSrcUuid && zSrcUuid[0] ){
@@ -758,11 +758,11 @@
758 if( tagtype==0 ){
759 @ by
760 }else{
761 @ added by
762 }
763 hyperlink_to_version(zSrcUuid);
764 @ on
765 hyperlink_to_date(zDate,0);
766 }
767 @ </li>
768 }
@@ -829,12 +829,12 @@
829 int rid;
830 int isLeaf;
831 int diffType; /* 0: no diff, 1: unified, 2: side-by-side */
832 u64 diffFlags; /* Flag parameter for text_diff() */
833 const char *zName; /* Name of the check-in to be displayed */
834 const char *zUuid; /* Hash of zName, found via blob.uuid */
835 const char *zParent; /* Hash of the parent check-in (if any) */
836 const char *zRe; /* regex parameter */
837 ReCompiled *pRe = 0; /* regex */
838 const char *zW; /* URL param for ignoring whitespace */
839 const char *zPage = "vinfo"; /* Page that shows diffs */
840 const char *zPageHide = "ci"; /* Page that hides diffs */
@@ -1324,11 +1324,11 @@
1324 db_end_transaction(1); /* ROLLBACK */
1325 }
1326
1327 /*
1328 ** WEBPAGE: winfo
1329 ** URL: /winfo?name=HASH
1330 **
1331 ** Display information about a wiki page.
1332 */
1333 void winfo_page(void){
1334 int rid;
@@ -1485,11 +1485,11 @@
1485 Blob comment;
1486 int wikiFlags = WIKI_INLINE|WIKI_NOBADLINKS;
1487 if( db_get_boolean("timeline-block-markup", 0)==0 ){
1488 wikiFlags |= WIKI_NOBLOCK;
1489 }
1490 hyperlink_to_version(zUuid);
1491 blob_zero(&comment);
1492 db_column_blob(&q, 2, &comment);
1493 wiki_convert(&comment, 0, wikiFlags);
1494 blob_reset(&comment);
1495 @ (user:
@@ -1813,14 +1813,14 @@
1813 }
1814 if( showDetail ){
1815 @ <li>
1816 hyperlink_to_date(zDate,"");
1817 @ &mdash; part of check-in
1818 hyperlink_to_version(zVers);
1819 }else{
1820 @ &mdash; part of check-in
1821 hyperlink_to_version(zVers);
1822 @ at
1823 hyperlink_to_date(zDate,"");
1824 }
1825 if( zBr && zBr[0] ){
1826 @ on branch %z(href("%R/timeline?r=%T",zBr))%h(zBr)</a>
@@ -1919,11 +1919,11 @@
1919 @ Forum post
1920 }else{
1921 @ Tag referencing
1922 }
1923 if( zType[0]!='e' || eventTagId == 0){
1924 hyperlink_to_version(zUuid);
1925 }
1926 @ - %!W(zCom) by
1927 hyperlink_to_user(zUser,zDate," on");
1928 hyperlink_to_date(zDate, ".");
1929 if( pDownloadName && blob_size(pDownloadName)==0 ){
@@ -1951,11 +1951,11 @@
1951 @ Also attachment "%h(zFilename)" to
1952 }else{
1953 @ Attachment "%h(zFilename)" to
1954 }
1955 objType |= OBJTYPE_ATTACHMENT;
1956 if( fossil_is_artifact_hash(zTarget) ){
1957 if( db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'",
1958 zTarget)
1959 ){
1960 if( g.perm.Hyperlink && g.anon.RdTkt ){
1961 @ ticket [%z(href("%R/tktview?name=%!S",zTarget))%S(zTarget)</a>]
@@ -2011,11 +2011,11 @@
2011
2012
2013 /*
2014 ** WEBPAGE: fdiff
2015 ** WEBPAGE: localdiff
2016 ** URL: fdiff?v1=HASH&v2=HASH
2017 ** URL: localdiff?name=filename
2018 **
2019 ** Two arguments, v1 and v2, identify the artifacts to be diffed.
2020 ** Show diff side by side unless sbs is 0. Generate plain text if
2021 ** "patch" is present, otherwise generate "pretty" HTML.
@@ -2227,18 +2227,18 @@
2227 ** is by the full-length SHA1 or SHA3 hash. Abbreviations are not
2228 ** accepted.
2229 */
2230 void secure_rawartifact_page(void){
2231 int rid = 0;
2232 const char *zName = PD("name", "");
2233
2234 login_check_credentials();
2235 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
2236 rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", zName);
2237 if( rid==0 ){
2238 cgi_set_status(404, "Not Found");
2239 @ Unknown artifact: "%h(zName)"
2240 return;
2241 }
2242 g.isConst = 1;
2243 deliver_artifact(rid, P("m"));
2244 }
@@ -3025,16 +3025,18 @@
3025 }
3026
3027
3028 /*
3029 ** WEBPAGE: info
3030 ** URL: info/NAME
3031 **
3032 ** The NAME argument is any valid artifact name: an artifact hash,
3033 ** a timestamp, a tag name, etc.
3034 **
3035 ** Because NAME can match so many different things (commit artifacts,
3036 ** wiki pages, ticket comments, forum posts...) the format of the output
3037 ** page depends on the type of artifact that NAME matches.
3038 */
3039 void info_page(void){
3040 const char *zName;
3041 Blob uuid;
3042 int rid;
@@ -3644,17 +3646,17 @@
3646 blob_append(&prompt, ".\n# Lines beginning with a # are ignored.\n", -1);
3647 prompt_for_user_comment(pComment, &prompt);
3648 blob_reset(&prompt);
3649 }
3650
3651 #define AMEND_USAGE_STMT "HASH OPTION ?OPTION ...?"
3652 /*
3653 ** COMMAND: amend
3654 **
3655 ** Usage: %fossil amend HASH OPTION ?OPTION ...?
3656 **
3657 ** Amend the tags on check-in HASH to change how it displays in the timeline.
3658 **
3659 ** Options:
3660 **
3661 ** --author USER Make USER the author for check-in
3662 ** -m|--comment COMMENT Make COMMENT the check-in comment
@@ -3738,11 +3740,11 @@
3740 verify_all_options();
3741 if( g.argc<3 || g.argc>=4 ) usage(AMEND_USAGE_STMT);
3742 rid = name_to_typed_rid(g.argv[2], "ci");
3743 if( rid==0 && !is_a_version(rid) ) fossil_fatal("no such check-in");
3744 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
3745 if( zUuid==0 ) fossil_fatal("Unable to find artifact hash");
3746 zComment = db_text(0, "SELECT coalesce(ecomment,comment)"
3747 " FROM event WHERE objid=%d", rid);
3748 zUser = db_text(0, "SELECT coalesce(euser,user)"
3749 " FROM event WHERE objid=%d", rid);
3750 zDate = db_text(0, "SELECT datetime(mtime)"
@@ -3828,11 +3830,11 @@
3830 if( fHide && !fHasHidden ) hide_branch();
3831 if( fClose && !fHasClosed ) close_leaf(rid);
3832 if( zNewBranch && zNewBranch[0] ) change_branch(rid,zNewBranch);
3833 apply_newtags(&ctrl, rid, zUuid, zUserOvrd, fDryRun);
3834 if( fDryRun==0 ){
3835 show_common_info(rid, "hash:", 1, 0);
3836 }
3837 if( g.localOpen ){
3838 manifest_to_disk(rid);
3839 }
3840 }
3841
+29 -27
--- src/info.c
+++ src/info.c
@@ -54,19 +54,19 @@
5454
5555
5656
/*
5757
** Print common information about a particular record.
5858
**
59
-** * The UUID
59
+** * The artifact hash
6060
** * The record ID
6161
** * mtime and ctime
6262
** * who signed it
6363
**
6464
*/
6565
void show_common_info(
6666
int rid, /* The rid for the check-in to display info for */
67
- const char *zUuidName, /* Name of the UUID */
67
+ const char *zRecDesc, /* Brief record description; e.g. "checkout:" */
6868
int showComment, /* True to show the check-in comment */
6969
int showFamily /* True to show parents and children */
7070
){
7171
Stmt q;
7272
char *zComment = 0;
@@ -78,11 +78,11 @@
7878
zDate = db_text(0,
7979
"SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
8080
rid
8181
);
8282
/* 01234567890123 */
83
- fossil_print("%-13s %.40s %s\n", zUuidName, zUuid, zDate ? zDate : "");
83
+ fossil_print("%-13s %.40s %s\n", zRecDesc, zUuid, zDate ? zDate : "");
8484
free(zDate);
8585
if( showComment ){
8686
zComment = db_text(0,
8787
"SELECT coalesce(ecomment,comment) || "
8888
" ' (user: ' || coalesce(euser,user,'?') || ')' "
@@ -274,11 +274,11 @@
274274
int rid;
275275
rid = name_to_rid(g.argv[2]);
276276
if( rid==0 ){
277277
fossil_fatal("no such object: %s", g.argv[2]);
278278
}
279
- show_common_info(rid, "uuid:", 1, 1);
279
+ show_common_info(rid, "hash:", 1, 1);
280280
}
281281
}
282282
283283
/*
284284
** Show the context graph (immediate parents and children) for
@@ -747,11 +747,11 @@
747747
@ <span class="infoTag">%h(zTagname)</span>
748748
}
749749
if( tagtype==2 ){
750750
if( zOrigUuid && zOrigUuid[0] ){
751751
@ inherited from
752
- hyperlink_to_uuid(zOrigUuid);
752
+ hyperlink_to_version(zOrigUuid);
753753
}else{
754754
@ propagates to descendants
755755
}
756756
}
757757
if( zSrcUuid && zSrcUuid[0] ){
@@ -758,11 +758,11 @@
758758
if( tagtype==0 ){
759759
@ by
760760
}else{
761761
@ added by
762762
}
763
- hyperlink_to_uuid(zSrcUuid);
763
+ hyperlink_to_version(zSrcUuid);
764764
@ on
765765
hyperlink_to_date(zDate,0);
766766
}
767767
@ </li>
768768
}
@@ -829,12 +829,12 @@
829829
int rid;
830830
int isLeaf;
831831
int diffType; /* 0: no diff, 1: unified, 2: side-by-side */
832832
u64 diffFlags; /* Flag parameter for text_diff() */
833833
const char *zName; /* Name of the check-in to be displayed */
834
- const char *zUuid; /* UUID of zName */
835
- const char *zParent; /* UUID of the parent check-in (if any) */
834
+ const char *zUuid; /* Hash of zName, found via blob.uuid */
835
+ const char *zParent; /* Hash of the parent check-in (if any) */
836836
const char *zRe; /* regex parameter */
837837
ReCompiled *pRe = 0; /* regex */
838838
const char *zW; /* URL param for ignoring whitespace */
839839
const char *zPage = "vinfo"; /* Page that shows diffs */
840840
const char *zPageHide = "ci"; /* Page that hides diffs */
@@ -1324,11 +1324,11 @@
13241324
db_end_transaction(1); /* ROLLBACK */
13251325
}
13261326
13271327
/*
13281328
** WEBPAGE: winfo
1329
-** URL: /winfo?name=UUID
1329
+** URL: /winfo?name=HASH
13301330
**
13311331
** Display information about a wiki page.
13321332
*/
13331333
void winfo_page(void){
13341334
int rid;
@@ -1485,11 +1485,11 @@
14851485
Blob comment;
14861486
int wikiFlags = WIKI_INLINE|WIKI_NOBADLINKS;
14871487
if( db_get_boolean("timeline-block-markup", 0)==0 ){
14881488
wikiFlags |= WIKI_NOBLOCK;
14891489
}
1490
- hyperlink_to_uuid(zUuid);
1490
+ hyperlink_to_version(zUuid);
14911491
blob_zero(&comment);
14921492
db_column_blob(&q, 2, &comment);
14931493
wiki_convert(&comment, 0, wikiFlags);
14941494
blob_reset(&comment);
14951495
@ (user:
@@ -1813,14 +1813,14 @@
18131813
}
18141814
if( showDetail ){
18151815
@ <li>
18161816
hyperlink_to_date(zDate,"");
18171817
@ &mdash; part of check-in
1818
- hyperlink_to_uuid(zVers);
1818
+ hyperlink_to_version(zVers);
18191819
}else{
18201820
@ &mdash; part of check-in
1821
- hyperlink_to_uuid(zVers);
1821
+ hyperlink_to_version(zVers);
18221822
@ at
18231823
hyperlink_to_date(zDate,"");
18241824
}
18251825
if( zBr && zBr[0] ){
18261826
@ on branch %z(href("%R/timeline?r=%T",zBr))%h(zBr)</a>
@@ -1919,11 +1919,11 @@
19191919
@ Forum post
19201920
}else{
19211921
@ Tag referencing
19221922
}
19231923
if( zType[0]!='e' || eventTagId == 0){
1924
- hyperlink_to_uuid(zUuid);
1924
+ hyperlink_to_version(zUuid);
19251925
}
19261926
@ - %!W(zCom) by
19271927
hyperlink_to_user(zUser,zDate," on");
19281928
hyperlink_to_date(zDate, ".");
19291929
if( pDownloadName && blob_size(pDownloadName)==0 ){
@@ -1951,11 +1951,11 @@
19511951
@ Also attachment "%h(zFilename)" to
19521952
}else{
19531953
@ Attachment "%h(zFilename)" to
19541954
}
19551955
objType |= OBJTYPE_ATTACHMENT;
1956
- if( fossil_is_uuid(zTarget) ){
1956
+ if( fossil_is_artifact_hash(zTarget) ){
19571957
if( db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'",
19581958
zTarget)
19591959
){
19601960
if( g.perm.Hyperlink && g.anon.RdTkt ){
19611961
@ ticket [%z(href("%R/tktview?name=%!S",zTarget))%S(zTarget)</a>]
@@ -2011,11 +2011,11 @@
20112011
20122012
20132013
/*
20142014
** WEBPAGE: fdiff
20152015
** WEBPAGE: localdiff
2016
-** URL: fdiff?v1=UUID&v2=UUID
2016
+** URL: fdiff?v1=HASH&v2=HASH
20172017
** URL: localdiff?name=filename
20182018
**
20192019
** Two arguments, v1 and v2, identify the artifacts to be diffed.
20202020
** Show diff side by side unless sbs is 0. Generate plain text if
20212021
** "patch" is present, otherwise generate "pretty" HTML.
@@ -2227,18 +2227,18 @@
22272227
** is by the full-length SHA1 or SHA3 hash. Abbreviations are not
22282228
** accepted.
22292229
*/
22302230
void secure_rawartifact_page(void){
22312231
int rid = 0;
2232
- const char *zUuid = PD("name", "");
2232
+ const char *zName = PD("name", "");
22332233
22342234
login_check_credentials();
22352235
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
2236
- rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", zUuid);
2236
+ rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", zName);
22372237
if( rid==0 ){
22382238
cgi_set_status(404, "Not Found");
2239
- @ Unknown artifact: "%h(zUuid)"
2239
+ @ Unknown artifact: "%h(zName)"
22402240
return;
22412241
}
22422242
g.isConst = 1;
22432243
deliver_artifact(rid, P("m"));
22442244
}
@@ -3025,16 +3025,18 @@
30253025
}
30263026
30273027
30283028
/*
30293029
** WEBPAGE: info
3030
-** URL: info/ARTIFACTID
3030
+** URL: info/NAME
30313031
**
3032
-** The argument is a artifact ID which might be a check-in or a file or
3033
-** a ticket changes or a wiki edit or something else.
3032
+** The NAME argument is any valid artifact name: an artifact hash,
3033
+** a timestamp, a tag name, etc.
30343034
**
3035
-** Figure out what the artifact ID is and display it appropriately.
3035
+** Because NAME can match so many different things (commit artifacts,
3036
+** wiki pages, ticket comments, forum posts...) the format of the output
3037
+** page depends on the type of artifact that NAME matches.
30363038
*/
30373039
void info_page(void){
30383040
const char *zName;
30393041
Blob uuid;
30403042
int rid;
@@ -3644,17 +3646,17 @@
36443646
blob_append(&prompt, ".\n# Lines beginning with a # are ignored.\n", -1);
36453647
prompt_for_user_comment(pComment, &prompt);
36463648
blob_reset(&prompt);
36473649
}
36483650
3649
-#define AMEND_USAGE_STMT "UUID OPTION ?OPTION ...?"
3651
+#define AMEND_USAGE_STMT "HASH OPTION ?OPTION ...?"
36503652
/*
36513653
** COMMAND: amend
36523654
**
3653
-** Usage: %fossil amend UUID OPTION ?OPTION ...?
3655
+** Usage: %fossil amend HASH OPTION ?OPTION ...?
36543656
**
3655
-** Amend the tags on check-in UUID to change how it displays in the timeline.
3657
+** Amend the tags on check-in HASH to change how it displays in the timeline.
36563658
**
36573659
** Options:
36583660
**
36593661
** --author USER Make USER the author for check-in
36603662
** -m|--comment COMMENT Make COMMENT the check-in comment
@@ -3738,11 +3740,11 @@
37383740
verify_all_options();
37393741
if( g.argc<3 || g.argc>=4 ) usage(AMEND_USAGE_STMT);
37403742
rid = name_to_typed_rid(g.argv[2], "ci");
37413743
if( rid==0 && !is_a_version(rid) ) fossil_fatal("no such check-in");
37423744
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
3743
- if( zUuid==0 ) fossil_fatal("Unable to find UUID");
3745
+ if( zUuid==0 ) fossil_fatal("Unable to find artifact hash");
37443746
zComment = db_text(0, "SELECT coalesce(ecomment,comment)"
37453747
" FROM event WHERE objid=%d", rid);
37463748
zUser = db_text(0, "SELECT coalesce(euser,user)"
37473749
" FROM event WHERE objid=%d", rid);
37483750
zDate = db_text(0, "SELECT datetime(mtime)"
@@ -3828,11 +3830,11 @@
38283830
if( fHide && !fHasHidden ) hide_branch();
38293831
if( fClose && !fHasClosed ) close_leaf(rid);
38303832
if( zNewBranch && zNewBranch[0] ) change_branch(rid,zNewBranch);
38313833
apply_newtags(&ctrl, rid, zUuid, zUserOvrd, fDryRun);
38323834
if( fDryRun==0 ){
3833
- show_common_info(rid, "uuid:", 1, 0);
3835
+ show_common_info(rid, "hash:", 1, 0);
38343836
}
38353837
if( g.localOpen ){
38363838
manifest_to_disk(rid);
38373839
}
38383840
}
38393841
--- src/info.c
+++ src/info.c
@@ -54,19 +54,19 @@
54
55
56 /*
57 ** Print common information about a particular record.
58 **
59 ** * The UUID
60 ** * The record ID
61 ** * mtime and ctime
62 ** * who signed it
63 **
64 */
65 void show_common_info(
66 int rid, /* The rid for the check-in to display info for */
67 const char *zUuidName, /* Name of the UUID */
68 int showComment, /* True to show the check-in comment */
69 int showFamily /* True to show parents and children */
70 ){
71 Stmt q;
72 char *zComment = 0;
@@ -78,11 +78,11 @@
78 zDate = db_text(0,
79 "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
80 rid
81 );
82 /* 01234567890123 */
83 fossil_print("%-13s %.40s %s\n", zUuidName, zUuid, zDate ? zDate : "");
84 free(zDate);
85 if( showComment ){
86 zComment = db_text(0,
87 "SELECT coalesce(ecomment,comment) || "
88 " ' (user: ' || coalesce(euser,user,'?') || ')' "
@@ -274,11 +274,11 @@
274 int rid;
275 rid = name_to_rid(g.argv[2]);
276 if( rid==0 ){
277 fossil_fatal("no such object: %s", g.argv[2]);
278 }
279 show_common_info(rid, "uuid:", 1, 1);
280 }
281 }
282
283 /*
284 ** Show the context graph (immediate parents and children) for
@@ -747,11 +747,11 @@
747 @ <span class="infoTag">%h(zTagname)</span>
748 }
749 if( tagtype==2 ){
750 if( zOrigUuid && zOrigUuid[0] ){
751 @ inherited from
752 hyperlink_to_uuid(zOrigUuid);
753 }else{
754 @ propagates to descendants
755 }
756 }
757 if( zSrcUuid && zSrcUuid[0] ){
@@ -758,11 +758,11 @@
758 if( tagtype==0 ){
759 @ by
760 }else{
761 @ added by
762 }
763 hyperlink_to_uuid(zSrcUuid);
764 @ on
765 hyperlink_to_date(zDate,0);
766 }
767 @ </li>
768 }
@@ -829,12 +829,12 @@
829 int rid;
830 int isLeaf;
831 int diffType; /* 0: no diff, 1: unified, 2: side-by-side */
832 u64 diffFlags; /* Flag parameter for text_diff() */
833 const char *zName; /* Name of the check-in to be displayed */
834 const char *zUuid; /* UUID of zName */
835 const char *zParent; /* UUID of the parent check-in (if any) */
836 const char *zRe; /* regex parameter */
837 ReCompiled *pRe = 0; /* regex */
838 const char *zW; /* URL param for ignoring whitespace */
839 const char *zPage = "vinfo"; /* Page that shows diffs */
840 const char *zPageHide = "ci"; /* Page that hides diffs */
@@ -1324,11 +1324,11 @@
1324 db_end_transaction(1); /* ROLLBACK */
1325 }
1326
1327 /*
1328 ** WEBPAGE: winfo
1329 ** URL: /winfo?name=UUID
1330 **
1331 ** Display information about a wiki page.
1332 */
1333 void winfo_page(void){
1334 int rid;
@@ -1485,11 +1485,11 @@
1485 Blob comment;
1486 int wikiFlags = WIKI_INLINE|WIKI_NOBADLINKS;
1487 if( db_get_boolean("timeline-block-markup", 0)==0 ){
1488 wikiFlags |= WIKI_NOBLOCK;
1489 }
1490 hyperlink_to_uuid(zUuid);
1491 blob_zero(&comment);
1492 db_column_blob(&q, 2, &comment);
1493 wiki_convert(&comment, 0, wikiFlags);
1494 blob_reset(&comment);
1495 @ (user:
@@ -1813,14 +1813,14 @@
1813 }
1814 if( showDetail ){
1815 @ <li>
1816 hyperlink_to_date(zDate,"");
1817 @ &mdash; part of check-in
1818 hyperlink_to_uuid(zVers);
1819 }else{
1820 @ &mdash; part of check-in
1821 hyperlink_to_uuid(zVers);
1822 @ at
1823 hyperlink_to_date(zDate,"");
1824 }
1825 if( zBr && zBr[0] ){
1826 @ on branch %z(href("%R/timeline?r=%T",zBr))%h(zBr)</a>
@@ -1919,11 +1919,11 @@
1919 @ Forum post
1920 }else{
1921 @ Tag referencing
1922 }
1923 if( zType[0]!='e' || eventTagId == 0){
1924 hyperlink_to_uuid(zUuid);
1925 }
1926 @ - %!W(zCom) by
1927 hyperlink_to_user(zUser,zDate," on");
1928 hyperlink_to_date(zDate, ".");
1929 if( pDownloadName && blob_size(pDownloadName)==0 ){
@@ -1951,11 +1951,11 @@
1951 @ Also attachment "%h(zFilename)" to
1952 }else{
1953 @ Attachment "%h(zFilename)" to
1954 }
1955 objType |= OBJTYPE_ATTACHMENT;
1956 if( fossil_is_uuid(zTarget) ){
1957 if( db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'",
1958 zTarget)
1959 ){
1960 if( g.perm.Hyperlink && g.anon.RdTkt ){
1961 @ ticket [%z(href("%R/tktview?name=%!S",zTarget))%S(zTarget)</a>]
@@ -2011,11 +2011,11 @@
2011
2012
2013 /*
2014 ** WEBPAGE: fdiff
2015 ** WEBPAGE: localdiff
2016 ** URL: fdiff?v1=UUID&v2=UUID
2017 ** URL: localdiff?name=filename
2018 **
2019 ** Two arguments, v1 and v2, identify the artifacts to be diffed.
2020 ** Show diff side by side unless sbs is 0. Generate plain text if
2021 ** "patch" is present, otherwise generate "pretty" HTML.
@@ -2227,18 +2227,18 @@
2227 ** is by the full-length SHA1 or SHA3 hash. Abbreviations are not
2228 ** accepted.
2229 */
2230 void secure_rawartifact_page(void){
2231 int rid = 0;
2232 const char *zUuid = PD("name", "");
2233
2234 login_check_credentials();
2235 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
2236 rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", zUuid);
2237 if( rid==0 ){
2238 cgi_set_status(404, "Not Found");
2239 @ Unknown artifact: "%h(zUuid)"
2240 return;
2241 }
2242 g.isConst = 1;
2243 deliver_artifact(rid, P("m"));
2244 }
@@ -3025,16 +3025,18 @@
3025 }
3026
3027
3028 /*
3029 ** WEBPAGE: info
3030 ** URL: info/ARTIFACTID
3031 **
3032 ** The argument is a artifact ID which might be a check-in or a file or
3033 ** a ticket changes or a wiki edit or something else.
3034 **
3035 ** Figure out what the artifact ID is and display it appropriately.
 
 
3036 */
3037 void info_page(void){
3038 const char *zName;
3039 Blob uuid;
3040 int rid;
@@ -3644,17 +3646,17 @@
3644 blob_append(&prompt, ".\n# Lines beginning with a # are ignored.\n", -1);
3645 prompt_for_user_comment(pComment, &prompt);
3646 blob_reset(&prompt);
3647 }
3648
3649 #define AMEND_USAGE_STMT "UUID OPTION ?OPTION ...?"
3650 /*
3651 ** COMMAND: amend
3652 **
3653 ** Usage: %fossil amend UUID OPTION ?OPTION ...?
3654 **
3655 ** Amend the tags on check-in UUID to change how it displays in the timeline.
3656 **
3657 ** Options:
3658 **
3659 ** --author USER Make USER the author for check-in
3660 ** -m|--comment COMMENT Make COMMENT the check-in comment
@@ -3738,11 +3740,11 @@
3738 verify_all_options();
3739 if( g.argc<3 || g.argc>=4 ) usage(AMEND_USAGE_STMT);
3740 rid = name_to_typed_rid(g.argv[2], "ci");
3741 if( rid==0 && !is_a_version(rid) ) fossil_fatal("no such check-in");
3742 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
3743 if( zUuid==0 ) fossil_fatal("Unable to find UUID");
3744 zComment = db_text(0, "SELECT coalesce(ecomment,comment)"
3745 " FROM event WHERE objid=%d", rid);
3746 zUser = db_text(0, "SELECT coalesce(euser,user)"
3747 " FROM event WHERE objid=%d", rid);
3748 zDate = db_text(0, "SELECT datetime(mtime)"
@@ -3828,11 +3830,11 @@
3828 if( fHide && !fHasHidden ) hide_branch();
3829 if( fClose && !fHasClosed ) close_leaf(rid);
3830 if( zNewBranch && zNewBranch[0] ) change_branch(rid,zNewBranch);
3831 apply_newtags(&ctrl, rid, zUuid, zUserOvrd, fDryRun);
3832 if( fDryRun==0 ){
3833 show_common_info(rid, "uuid:", 1, 0);
3834 }
3835 if( g.localOpen ){
3836 manifest_to_disk(rid);
3837 }
3838 }
3839
--- src/info.c
+++ src/info.c
@@ -54,19 +54,19 @@
54
55
56 /*
57 ** Print common information about a particular record.
58 **
59 ** * The artifact hash
60 ** * The record ID
61 ** * mtime and ctime
62 ** * who signed it
63 **
64 */
65 void show_common_info(
66 int rid, /* The rid for the check-in to display info for */
67 const char *zRecDesc, /* Brief record description; e.g. "checkout:" */
68 int showComment, /* True to show the check-in comment */
69 int showFamily /* True to show parents and children */
70 ){
71 Stmt q;
72 char *zComment = 0;
@@ -78,11 +78,11 @@
78 zDate = db_text(0,
79 "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d",
80 rid
81 );
82 /* 01234567890123 */
83 fossil_print("%-13s %.40s %s\n", zRecDesc, zUuid, zDate ? zDate : "");
84 free(zDate);
85 if( showComment ){
86 zComment = db_text(0,
87 "SELECT coalesce(ecomment,comment) || "
88 " ' (user: ' || coalesce(euser,user,'?') || ')' "
@@ -274,11 +274,11 @@
274 int rid;
275 rid = name_to_rid(g.argv[2]);
276 if( rid==0 ){
277 fossil_fatal("no such object: %s", g.argv[2]);
278 }
279 show_common_info(rid, "hash:", 1, 1);
280 }
281 }
282
283 /*
284 ** Show the context graph (immediate parents and children) for
@@ -747,11 +747,11 @@
747 @ <span class="infoTag">%h(zTagname)</span>
748 }
749 if( tagtype==2 ){
750 if( zOrigUuid && zOrigUuid[0] ){
751 @ inherited from
752 hyperlink_to_version(zOrigUuid);
753 }else{
754 @ propagates to descendants
755 }
756 }
757 if( zSrcUuid && zSrcUuid[0] ){
@@ -758,11 +758,11 @@
758 if( tagtype==0 ){
759 @ by
760 }else{
761 @ added by
762 }
763 hyperlink_to_version(zSrcUuid);
764 @ on
765 hyperlink_to_date(zDate,0);
766 }
767 @ </li>
768 }
@@ -829,12 +829,12 @@
829 int rid;
830 int isLeaf;
831 int diffType; /* 0: no diff, 1: unified, 2: side-by-side */
832 u64 diffFlags; /* Flag parameter for text_diff() */
833 const char *zName; /* Name of the check-in to be displayed */
834 const char *zUuid; /* Hash of zName, found via blob.uuid */
835 const char *zParent; /* Hash of the parent check-in (if any) */
836 const char *zRe; /* regex parameter */
837 ReCompiled *pRe = 0; /* regex */
838 const char *zW; /* URL param for ignoring whitespace */
839 const char *zPage = "vinfo"; /* Page that shows diffs */
840 const char *zPageHide = "ci"; /* Page that hides diffs */
@@ -1324,11 +1324,11 @@
1324 db_end_transaction(1); /* ROLLBACK */
1325 }
1326
1327 /*
1328 ** WEBPAGE: winfo
1329 ** URL: /winfo?name=HASH
1330 **
1331 ** Display information about a wiki page.
1332 */
1333 void winfo_page(void){
1334 int rid;
@@ -1485,11 +1485,11 @@
1485 Blob comment;
1486 int wikiFlags = WIKI_INLINE|WIKI_NOBADLINKS;
1487 if( db_get_boolean("timeline-block-markup", 0)==0 ){
1488 wikiFlags |= WIKI_NOBLOCK;
1489 }
1490 hyperlink_to_version(zUuid);
1491 blob_zero(&comment);
1492 db_column_blob(&q, 2, &comment);
1493 wiki_convert(&comment, 0, wikiFlags);
1494 blob_reset(&comment);
1495 @ (user:
@@ -1813,14 +1813,14 @@
1813 }
1814 if( showDetail ){
1815 @ <li>
1816 hyperlink_to_date(zDate,"");
1817 @ &mdash; part of check-in
1818 hyperlink_to_version(zVers);
1819 }else{
1820 @ &mdash; part of check-in
1821 hyperlink_to_version(zVers);
1822 @ at
1823 hyperlink_to_date(zDate,"");
1824 }
1825 if( zBr && zBr[0] ){
1826 @ on branch %z(href("%R/timeline?r=%T",zBr))%h(zBr)</a>
@@ -1919,11 +1919,11 @@
1919 @ Forum post
1920 }else{
1921 @ Tag referencing
1922 }
1923 if( zType[0]!='e' || eventTagId == 0){
1924 hyperlink_to_version(zUuid);
1925 }
1926 @ - %!W(zCom) by
1927 hyperlink_to_user(zUser,zDate," on");
1928 hyperlink_to_date(zDate, ".");
1929 if( pDownloadName && blob_size(pDownloadName)==0 ){
@@ -1951,11 +1951,11 @@
1951 @ Also attachment "%h(zFilename)" to
1952 }else{
1953 @ Attachment "%h(zFilename)" to
1954 }
1955 objType |= OBJTYPE_ATTACHMENT;
1956 if( fossil_is_artifact_hash(zTarget) ){
1957 if( db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'",
1958 zTarget)
1959 ){
1960 if( g.perm.Hyperlink && g.anon.RdTkt ){
1961 @ ticket [%z(href("%R/tktview?name=%!S",zTarget))%S(zTarget)</a>]
@@ -2011,11 +2011,11 @@
2011
2012
2013 /*
2014 ** WEBPAGE: fdiff
2015 ** WEBPAGE: localdiff
2016 ** URL: fdiff?v1=HASH&v2=HASH
2017 ** URL: localdiff?name=filename
2018 **
2019 ** Two arguments, v1 and v2, identify the artifacts to be diffed.
2020 ** Show diff side by side unless sbs is 0. Generate plain text if
2021 ** "patch" is present, otherwise generate "pretty" HTML.
@@ -2227,18 +2227,18 @@
2227 ** is by the full-length SHA1 or SHA3 hash. Abbreviations are not
2228 ** accepted.
2229 */
2230 void secure_rawartifact_page(void){
2231 int rid = 0;
2232 const char *zName = PD("name", "");
2233
2234 login_check_credentials();
2235 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
2236 rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", zName);
2237 if( rid==0 ){
2238 cgi_set_status(404, "Not Found");
2239 @ Unknown artifact: "%h(zName)"
2240 return;
2241 }
2242 g.isConst = 1;
2243 deliver_artifact(rid, P("m"));
2244 }
@@ -3025,16 +3025,18 @@
3025 }
3026
3027
3028 /*
3029 ** WEBPAGE: info
3030 ** URL: info/NAME
3031 **
3032 ** The NAME argument is any valid artifact name: an artifact hash,
3033 ** a timestamp, a tag name, etc.
3034 **
3035 ** Because NAME can match so many different things (commit artifacts,
3036 ** wiki pages, ticket comments, forum posts...) the format of the output
3037 ** page depends on the type of artifact that NAME matches.
3038 */
3039 void info_page(void){
3040 const char *zName;
3041 Blob uuid;
3042 int rid;
@@ -3644,17 +3646,17 @@
3646 blob_append(&prompt, ".\n# Lines beginning with a # are ignored.\n", -1);
3647 prompt_for_user_comment(pComment, &prompt);
3648 blob_reset(&prompt);
3649 }
3650
3651 #define AMEND_USAGE_STMT "HASH OPTION ?OPTION ...?"
3652 /*
3653 ** COMMAND: amend
3654 **
3655 ** Usage: %fossil amend HASH OPTION ?OPTION ...?
3656 **
3657 ** Amend the tags on check-in HASH to change how it displays in the timeline.
3658 **
3659 ** Options:
3660 **
3661 ** --author USER Make USER the author for check-in
3662 ** -m|--comment COMMENT Make COMMENT the check-in comment
@@ -3738,11 +3740,11 @@
3740 verify_all_options();
3741 if( g.argc<3 || g.argc>=4 ) usage(AMEND_USAGE_STMT);
3742 rid = name_to_typed_rid(g.argv[2], "ci");
3743 if( rid==0 && !is_a_version(rid) ) fossil_fatal("no such check-in");
3744 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
3745 if( zUuid==0 ) fossil_fatal("Unable to find artifact hash");
3746 zComment = db_text(0, "SELECT coalesce(ecomment,comment)"
3747 " FROM event WHERE objid=%d", rid);
3748 zUser = db_text(0, "SELECT coalesce(euser,user)"
3749 " FROM event WHERE objid=%d", rid);
3750 zDate = db_text(0, "SELECT datetime(mtime)"
@@ -3828,11 +3830,11 @@
3830 if( fHide && !fHasHidden ) hide_branch();
3831 if( fClose && !fHasClosed ) close_leaf(rid);
3832 if( zNewBranch && zNewBranch[0] ) change_branch(rid,zNewBranch);
3833 apply_newtags(&ctrl, rid, zUuid, zUserOvrd, fDryRun);
3834 if( fDryRun==0 ){
3835 show_common_info(rid, "hash:", 1, 0);
3836 }
3837 if( g.localOpen ){
3838 manifest_to_disk(rid);
3839 }
3840 }
3841
--- src/json_finfo.c
+++ src/json_finfo.c
@@ -89,11 +89,11 @@
8989
char * zU = NULL;
9090
int rc = name_to_uuid2( zCheckin, "ci", &zU );
9191
/*printf("zCheckin=[%s], zU=[%s]", zCheckin, zU);*/
9292
if(rc<=0){
9393
json_set_err((rc<0) ? FSL_JSON_E_AMBIGUOUS_UUID : FSL_JSON_E_RESOURCE_NOT_FOUND,
94
- "Check-in UUID %s.", (rc<0) ? "is ambiguous" : "not found");
94
+ "Check-in hash %s.", (rc<0) ? "is ambiguous" : "not found");
9595
blob_reset(&sql);
9696
return NULL;
9797
}
9898
blob_append_sql(&sql, " AND ci.uuid='%q'", zU);
9999
free(zU);
100100
--- src/json_finfo.c
+++ src/json_finfo.c
@@ -89,11 +89,11 @@
89 char * zU = NULL;
90 int rc = name_to_uuid2( zCheckin, "ci", &zU );
91 /*printf("zCheckin=[%s], zU=[%s]", zCheckin, zU);*/
92 if(rc<=0){
93 json_set_err((rc<0) ? FSL_JSON_E_AMBIGUOUS_UUID : FSL_JSON_E_RESOURCE_NOT_FOUND,
94 "Check-in UUID %s.", (rc<0) ? "is ambiguous" : "not found");
95 blob_reset(&sql);
96 return NULL;
97 }
98 blob_append_sql(&sql, " AND ci.uuid='%q'", zU);
99 free(zU);
100
--- src/json_finfo.c
+++ src/json_finfo.c
@@ -89,11 +89,11 @@
89 char * zU = NULL;
90 int rc = name_to_uuid2( zCheckin, "ci", &zU );
91 /*printf("zCheckin=[%s], zU=[%s]", zCheckin, zU);*/
92 if(rc<=0){
93 json_set_err((rc<0) ? FSL_JSON_E_AMBIGUOUS_UUID : FSL_JSON_E_RESOURCE_NOT_FOUND,
94 "Check-in hash %s.", (rc<0) ? "is ambiguous" : "not found");
95 blob_reset(&sql);
96 return NULL;
97 }
98 blob_append_sql(&sql, " AND ci.uuid='%q'", zU);
99 free(zU);
100
+1 -1
--- src/json_tag.c
+++ src/json_tag.c
@@ -117,11 +117,11 @@
117117
Blob uu = empty_blob;
118118
int rc;
119119
blob_append(&uu, zName, -1);
120120
rc = name_to_uuid(&uu, 9, "*");
121121
if(0!=rc){
122
- json_set_err(FSL_JSON_E_UNKNOWN,"Could not convert name back to UUID!");
122
+ json_set_err(FSL_JSON_E_UNKNOWN,"Could not convert name back to artifact hash!");
123123
blob_reset(&uu);
124124
goto error;
125125
}
126126
cson_object_set(pay, "appliedTo", json_new_string(blob_buffer(&uu)));
127127
blob_reset(&uu);
128128
--- src/json_tag.c
+++ src/json_tag.c
@@ -117,11 +117,11 @@
117 Blob uu = empty_blob;
118 int rc;
119 blob_append(&uu, zName, -1);
120 rc = name_to_uuid(&uu, 9, "*");
121 if(0!=rc){
122 json_set_err(FSL_JSON_E_UNKNOWN,"Could not convert name back to UUID!");
123 blob_reset(&uu);
124 goto error;
125 }
126 cson_object_set(pay, "appliedTo", json_new_string(blob_buffer(&uu)));
127 blob_reset(&uu);
128
--- src/json_tag.c
+++ src/json_tag.c
@@ -117,11 +117,11 @@
117 Blob uu = empty_blob;
118 int rc;
119 blob_append(&uu, zName, -1);
120 rc = name_to_uuid(&uu, 9, "*");
121 if(0!=rc){
122 json_set_err(FSL_JSON_E_UNKNOWN,"Could not convert name back to artifact hash!");
123 blob_reset(&uu);
124 goto error;
125 }
126 cson_object_set(pay, "appliedTo", json_new_string(blob_buffer(&uu)));
127 blob_reset(&uu);
128
+1 -1
--- src/main.c
+++ src/main.c
@@ -159,11 +159,11 @@
159159
char *zLocalDbName; /* Name of the local database file */
160160
char *zOpenRevision; /* Check-in version to use during database open */
161161
const char *zCmdName; /* Name of the Fossil command currently running */
162162
int localOpen; /* True if the local database is open */
163163
char *zLocalRoot; /* The directory holding the local database */
164
- int minPrefix; /* Number of digits needed for a distinct UUID */
164
+ int minPrefix; /* Number of digits needed for a distinct hash */
165165
int eHashPolicy; /* Current hash policy. One of HPOLICY_* */
166166
int fSqlTrace; /* True if --sqltrace flag is present */
167167
int fSqlStats; /* True if --sqltrace or --sqlstats are present */
168168
int fSqlPrint; /* True if --sqlprint flag is present */
169169
int fCgiTrace; /* True if --cgitrace is enabled */
170170
--- src/main.c
+++ src/main.c
@@ -159,11 +159,11 @@
159 char *zLocalDbName; /* Name of the local database file */
160 char *zOpenRevision; /* Check-in version to use during database open */
161 const char *zCmdName; /* Name of the Fossil command currently running */
162 int localOpen; /* True if the local database is open */
163 char *zLocalRoot; /* The directory holding the local database */
164 int minPrefix; /* Number of digits needed for a distinct UUID */
165 int eHashPolicy; /* Current hash policy. One of HPOLICY_* */
166 int fSqlTrace; /* True if --sqltrace flag is present */
167 int fSqlStats; /* True if --sqltrace or --sqlstats are present */
168 int fSqlPrint; /* True if --sqlprint flag is present */
169 int fCgiTrace; /* True if --cgitrace is enabled */
170
--- src/main.c
+++ src/main.c
@@ -159,11 +159,11 @@
159 char *zLocalDbName; /* Name of the local database file */
160 char *zOpenRevision; /* Check-in version to use during database open */
161 const char *zCmdName; /* Name of the Fossil command currently running */
162 int localOpen; /* True if the local database is open */
163 char *zLocalRoot; /* The directory holding the local database */
164 int minPrefix; /* Number of digits needed for a distinct hash */
165 int eHashPolicy; /* Current hash policy. One of HPOLICY_* */
166 int fSqlTrace; /* True if --sqltrace flag is present */
167 int fSqlStats; /* True if --sqltrace or --sqlstats are present */
168 int fSqlPrint; /* True if --sqlprint flag is present */
169 int fCgiTrace; /* True if --cgitrace is enabled */
170
--- src/main.mk
+++ src/main.mk
@@ -608,11 +608,10 @@
608608
-DSQLITE_DEFAULT_MEMSTATUS=0 \
609609
-DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \
610610
-DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
611611
-DSQLITE_OMIT_DECLTYPE \
612612
-DSQLITE_OMIT_DEPRECATED \
613
- -DSQLITE_OMIT_GET_TABLE \
614613
-DSQLITE_OMIT_PROGRESS_CALLBACK \
615614
-DSQLITE_OMIT_SHARED_CACHE \
616615
-DSQLITE_OMIT_LOAD_EXTENSION \
617616
-DSQLITE_MAX_EXPR_DEPTH=0 \
618617
-DSQLITE_USE_ALLOCA \
@@ -636,11 +635,10 @@
636635
-DSQLITE_DEFAULT_MEMSTATUS=0 \
637636
-DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \
638637
-DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
639638
-DSQLITE_OMIT_DECLTYPE \
640639
-DSQLITE_OMIT_DEPRECATED \
641
- -DSQLITE_OMIT_GET_TABLE \
642640
-DSQLITE_OMIT_PROGRESS_CALLBACK \
643641
-DSQLITE_OMIT_SHARED_CACHE \
644642
-DSQLITE_OMIT_LOAD_EXTENSION \
645643
-DSQLITE_MAX_EXPR_DEPTH=0 \
646644
-DSQLITE_USE_ALLOCA \
647645
--- src/main.mk
+++ src/main.mk
@@ -608,11 +608,10 @@
608 -DSQLITE_DEFAULT_MEMSTATUS=0 \
609 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \
610 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
611 -DSQLITE_OMIT_DECLTYPE \
612 -DSQLITE_OMIT_DEPRECATED \
613 -DSQLITE_OMIT_GET_TABLE \
614 -DSQLITE_OMIT_PROGRESS_CALLBACK \
615 -DSQLITE_OMIT_SHARED_CACHE \
616 -DSQLITE_OMIT_LOAD_EXTENSION \
617 -DSQLITE_MAX_EXPR_DEPTH=0 \
618 -DSQLITE_USE_ALLOCA \
@@ -636,11 +635,10 @@
636 -DSQLITE_DEFAULT_MEMSTATUS=0 \
637 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \
638 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
639 -DSQLITE_OMIT_DECLTYPE \
640 -DSQLITE_OMIT_DEPRECATED \
641 -DSQLITE_OMIT_GET_TABLE \
642 -DSQLITE_OMIT_PROGRESS_CALLBACK \
643 -DSQLITE_OMIT_SHARED_CACHE \
644 -DSQLITE_OMIT_LOAD_EXTENSION \
645 -DSQLITE_MAX_EXPR_DEPTH=0 \
646 -DSQLITE_USE_ALLOCA \
647
--- src/main.mk
+++ src/main.mk
@@ -608,11 +608,10 @@
608 -DSQLITE_DEFAULT_MEMSTATUS=0 \
609 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \
610 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
611 -DSQLITE_OMIT_DECLTYPE \
612 -DSQLITE_OMIT_DEPRECATED \
 
613 -DSQLITE_OMIT_PROGRESS_CALLBACK \
614 -DSQLITE_OMIT_SHARED_CACHE \
615 -DSQLITE_OMIT_LOAD_EXTENSION \
616 -DSQLITE_MAX_EXPR_DEPTH=0 \
617 -DSQLITE_USE_ALLOCA \
@@ -636,11 +635,10 @@
635 -DSQLITE_DEFAULT_MEMSTATUS=0 \
636 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \
637 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
638 -DSQLITE_OMIT_DECLTYPE \
639 -DSQLITE_OMIT_DEPRECATED \
 
640 -DSQLITE_OMIT_PROGRESS_CALLBACK \
641 -DSQLITE_OMIT_SHARED_CACHE \
642 -DSQLITE_OMIT_LOAD_EXTENSION \
643 -DSQLITE_MAX_EXPR_DEPTH=0 \
644 -DSQLITE_USE_ALLOCA \
645
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -192,11 +192,10 @@
192192
-DSQLITE_DEFAULT_MEMSTATUS=0
193193
-DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1
194194
-DSQLITE_LIKE_DOESNT_MATCH_BLOBS
195195
-DSQLITE_OMIT_DECLTYPE
196196
-DSQLITE_OMIT_DEPRECATED
197
- -DSQLITE_OMIT_GET_TABLE
198197
-DSQLITE_OMIT_PROGRESS_CALLBACK
199198
-DSQLITE_OMIT_SHARED_CACHE
200199
-DSQLITE_OMIT_LOAD_EXTENSION
201200
-DSQLITE_MAX_EXPR_DEPTH=0
202201
-DSQLITE_USE_ALLOCA
203202
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -192,11 +192,10 @@
192 -DSQLITE_DEFAULT_MEMSTATUS=0
193 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1
194 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS
195 -DSQLITE_OMIT_DECLTYPE
196 -DSQLITE_OMIT_DEPRECATED
197 -DSQLITE_OMIT_GET_TABLE
198 -DSQLITE_OMIT_PROGRESS_CALLBACK
199 -DSQLITE_OMIT_SHARED_CACHE
200 -DSQLITE_OMIT_LOAD_EXTENSION
201 -DSQLITE_MAX_EXPR_DEPTH=0
202 -DSQLITE_USE_ALLOCA
203
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -192,11 +192,10 @@
192 -DSQLITE_DEFAULT_MEMSTATUS=0
193 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1
194 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS
195 -DSQLITE_OMIT_DECLTYPE
196 -DSQLITE_OMIT_DEPRECATED
 
197 -DSQLITE_OMIT_PROGRESS_CALLBACK
198 -DSQLITE_OMIT_SHARED_CACHE
199 -DSQLITE_OMIT_LOAD_EXTENSION
200 -DSQLITE_MAX_EXPR_DEPTH=0
201 -DSQLITE_USE_ALLOCA
202
+1 -1
--- src/manifest.c
+++ src/manifest.c
@@ -2434,11 +2434,11 @@
24342434
/* We assume that we're attaching to a wiki page until we
24352435
** prove otherwise (which could on a later artifact if we
24362436
** process the attachment artifact before the artifact to
24372437
** which it is attached!) */
24382438
char attachToType = 'w';
2439
- if( fossil_is_uuid(p->zAttachTarget) ){
2439
+ if( fossil_is_artifact_hash(p->zAttachTarget) ){
24402440
if( db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'",
24412441
p->zAttachTarget)
24422442
){
24432443
attachToType = 't'; /* Attaching to known ticket */
24442444
}else if( db_exists("SELECT 1 FROM tag WHERE tagname='event-%q'",
24452445
--- src/manifest.c
+++ src/manifest.c
@@ -2434,11 +2434,11 @@
2434 /* We assume that we're attaching to a wiki page until we
2435 ** prove otherwise (which could on a later artifact if we
2436 ** process the attachment artifact before the artifact to
2437 ** which it is attached!) */
2438 char attachToType = 'w';
2439 if( fossil_is_uuid(p->zAttachTarget) ){
2440 if( db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'",
2441 p->zAttachTarget)
2442 ){
2443 attachToType = 't'; /* Attaching to known ticket */
2444 }else if( db_exists("SELECT 1 FROM tag WHERE tagname='event-%q'",
2445
--- src/manifest.c
+++ src/manifest.c
@@ -2434,11 +2434,11 @@
2434 /* We assume that we're attaching to a wiki page until we
2435 ** prove otherwise (which could on a later artifact if we
2436 ** process the attachment artifact before the artifact to
2437 ** which it is attached!) */
2438 char attachToType = 'w';
2439 if( fossil_is_artifact_hash(p->zAttachTarget) ){
2440 if( db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'",
2441 p->zAttachTarget)
2442 ){
2443 attachToType = 't'; /* Attaching to known ticket */
2444 }else if( db_exists("SELECT 1 FROM tag WHERE tagname='event-%q'",
2445
+18 -11
--- src/name.c
+++ src/name.c
@@ -446,17 +446,23 @@
446446
}
447447
return rid;
448448
}
449449
450450
/*
451
-** This routine takes a user-entered UUID which might be in mixed
452
-** case and might only be a prefix of the full UUID and converts it
453
-** into the full-length UUID in canonical form.
451
+** This routine takes a user-entered string and tries to convert it to
452
+** an artifact hash.
453
+**
454
+** We first try to treat the string as an artifact hash, or at least a
455
+** unique prefix of an artifact hash. The input may be in mixed case.
456
+** If we are passed such a string, this routine has the effect of
457
+** converting the hash [prefix] to canonical form.
454458
**
455
-** If the input is not a UUID or a UUID prefix, then try to resolve
459
+** If the input is not a hash or a hash prefix, then try to resolve
456460
** the name as a tag. If multiple tags match, pick the latest.
457
-** If the input name matches "tag:*" then always resolve as a tag.
461
+** A caller can force this routine to skip the hash case above by
462
+** prefixing the string with "tag:", a useful property when the tag
463
+** may be misinterpreted as a hex ASCII string. (e.g. "decade" or "facade")
458464
**
459465
** If the input is not a tag, then try to match it as an ISO-8601 date
460466
** string YYYY-MM-DD HH:MM:SS and pick the nearest check-in to that date.
461467
** If the input is of the form "date:*" then always resolve the name as
462468
** a date. The forms "utc:*" and "local:" are deprecated.
@@ -481,16 +487,16 @@
481487
}
482488
483489
/*
484490
** This routine is similar to name_to_uuid() except in the form it
485491
** takes its parameters and returns its value, and in that it does not
486
-** treat errors as fatal. zName must be a UUID, as described for
487
-** name_to_uuid(). zType is also as described for that function. If
492
+** treat errors as fatal. zName must be an artifact hash or prefix of
493
+** a hash. zType is also as described for name_to_uuid(). If
488494
** zName does not resolve, 0 is returned. If it is ambiguous, a
489495
** negative value is returned. On success the rid is returned and
490496
** pUuid (if it is not NULL) is set to a newly-allocated string,
491
-** the full UUID, which must eventually be free()d by the caller.
497
+** the full hash, which must eventually be free()d by the caller.
492498
*/
493499
int name_to_uuid2(const char *zName, const char *zType, char **pUuid){
494500
int rid = symbolic_name_to_rid(zName, zType);
495501
if((rid>0) && pUuid){
496502
*pUuid = db_text(NULL, "SELECT uuid FROM blob WHERE rid=%d", rid);
@@ -499,12 +505,13 @@
499505
}
500506
501507
502508
/*
503509
** name_collisions searches through events, blobs, and tickets for
504
-** collisions of a given UUID based on its length on UUIDs no shorter
505
-** than 4 characters in length.
510
+** collisions of a given hash based on its length, counting only
511
+** hashes greater than or equal to 4 hex ASCII characters (16 bits)
512
+** in length.
506513
*/
507514
int name_collisions(const char *zName){
508515
int c = 0; /* count of collisions for zName */
509516
int nLen; /* length of zName */
510517
nLen = strlen(zName);
@@ -633,11 +640,11 @@
633640
const char *zTitle = db_column_text(&q, 2);
634641
@ <li><p><a href="%R/%T(zSrc)/%!S(zUuid)">
635642
@ %s(zUuid)</a> -
636643
@ <ul></ul>
637644
@ Ticket
638
- hyperlink_to_uuid(zUuid);
645
+ hyperlink_to_version(zUuid);
639646
@ - %h(zTitle).
640647
@ <ul><li>
641648
object_description(rid, 0, 0, 0);
642649
@ </li></ul>
643650
@ </p></li>
644651
--- src/name.c
+++ src/name.c
@@ -446,17 +446,23 @@
446 }
447 return rid;
448 }
449
450 /*
451 ** This routine takes a user-entered UUID which might be in mixed
452 ** case and might only be a prefix of the full UUID and converts it
453 ** into the full-length UUID in canonical form.
 
 
 
 
454 **
455 ** If the input is not a UUID or a UUID prefix, then try to resolve
456 ** the name as a tag. If multiple tags match, pick the latest.
457 ** If the input name matches "tag:*" then always resolve as a tag.
 
 
458 **
459 ** If the input is not a tag, then try to match it as an ISO-8601 date
460 ** string YYYY-MM-DD HH:MM:SS and pick the nearest check-in to that date.
461 ** If the input is of the form "date:*" then always resolve the name as
462 ** a date. The forms "utc:*" and "local:" are deprecated.
@@ -481,16 +487,16 @@
481 }
482
483 /*
484 ** This routine is similar to name_to_uuid() except in the form it
485 ** takes its parameters and returns its value, and in that it does not
486 ** treat errors as fatal. zName must be a UUID, as described for
487 ** name_to_uuid(). zType is also as described for that function. If
488 ** zName does not resolve, 0 is returned. If it is ambiguous, a
489 ** negative value is returned. On success the rid is returned and
490 ** pUuid (if it is not NULL) is set to a newly-allocated string,
491 ** the full UUID, which must eventually be free()d by the caller.
492 */
493 int name_to_uuid2(const char *zName, const char *zType, char **pUuid){
494 int rid = symbolic_name_to_rid(zName, zType);
495 if((rid>0) && pUuid){
496 *pUuid = db_text(NULL, "SELECT uuid FROM blob WHERE rid=%d", rid);
@@ -499,12 +505,13 @@
499 }
500
501
502 /*
503 ** name_collisions searches through events, blobs, and tickets for
504 ** collisions of a given UUID based on its length on UUIDs no shorter
505 ** than 4 characters in length.
 
506 */
507 int name_collisions(const char *zName){
508 int c = 0; /* count of collisions for zName */
509 int nLen; /* length of zName */
510 nLen = strlen(zName);
@@ -633,11 +640,11 @@
633 const char *zTitle = db_column_text(&q, 2);
634 @ <li><p><a href="%R/%T(zSrc)/%!S(zUuid)">
635 @ %s(zUuid)</a> -
636 @ <ul></ul>
637 @ Ticket
638 hyperlink_to_uuid(zUuid);
639 @ - %h(zTitle).
640 @ <ul><li>
641 object_description(rid, 0, 0, 0);
642 @ </li></ul>
643 @ </p></li>
644
--- src/name.c
+++ src/name.c
@@ -446,17 +446,23 @@
446 }
447 return rid;
448 }
449
450 /*
451 ** This routine takes a user-entered string and tries to convert it to
452 ** an artifact hash.
453 **
454 ** We first try to treat the string as an artifact hash, or at least a
455 ** unique prefix of an artifact hash. The input may be in mixed case.
456 ** If we are passed such a string, this routine has the effect of
457 ** converting the hash [prefix] to canonical form.
458 **
459 ** If the input is not a hash or a hash prefix, then try to resolve
460 ** the name as a tag. If multiple tags match, pick the latest.
461 ** A caller can force this routine to skip the hash case above by
462 ** prefixing the string with "tag:", a useful property when the tag
463 ** may be misinterpreted as a hex ASCII string. (e.g. "decade" or "facade")
464 **
465 ** If the input is not a tag, then try to match it as an ISO-8601 date
466 ** string YYYY-MM-DD HH:MM:SS and pick the nearest check-in to that date.
467 ** If the input is of the form "date:*" then always resolve the name as
468 ** a date. The forms "utc:*" and "local:" are deprecated.
@@ -481,16 +487,16 @@
487 }
488
489 /*
490 ** This routine is similar to name_to_uuid() except in the form it
491 ** takes its parameters and returns its value, and in that it does not
492 ** treat errors as fatal. zName must be an artifact hash or prefix of
493 ** a hash. zType is also as described for name_to_uuid(). If
494 ** zName does not resolve, 0 is returned. If it is ambiguous, a
495 ** negative value is returned. On success the rid is returned and
496 ** pUuid (if it is not NULL) is set to a newly-allocated string,
497 ** the full hash, which must eventually be free()d by the caller.
498 */
499 int name_to_uuid2(const char *zName, const char *zType, char **pUuid){
500 int rid = symbolic_name_to_rid(zName, zType);
501 if((rid>0) && pUuid){
502 *pUuid = db_text(NULL, "SELECT uuid FROM blob WHERE rid=%d", rid);
@@ -499,12 +505,13 @@
505 }
506
507
508 /*
509 ** name_collisions searches through events, blobs, and tickets for
510 ** collisions of a given hash based on its length, counting only
511 ** hashes greater than or equal to 4 hex ASCII characters (16 bits)
512 ** in length.
513 */
514 int name_collisions(const char *zName){
515 int c = 0; /* count of collisions for zName */
516 int nLen; /* length of zName */
517 nLen = strlen(zName);
@@ -633,11 +640,11 @@
640 const char *zTitle = db_column_text(&q, 2);
641 @ <li><p><a href="%R/%T(zSrc)/%!S(zUuid)">
642 @ %s(zUuid)</a> -
643 @ <ul></ul>
644 @ Ticket
645 hyperlink_to_version(zUuid);
646 @ - %h(zTitle).
647 @ <ul><li>
648 object_description(rid, 0, 0, 0);
649 @ </li></ul>
650 @ </p></li>
651
+1 -1
--- src/printf.c
+++ src/printf.c
@@ -97,11 +97,11 @@
9797
#define etHTTPIZE 18 /* Make text safe for HTTP. "/" encoded as %2f */
9898
#define etURLIZE 19 /* Make text safe for HTTP. "/" not encoded */
9999
#define etFOSSILIZE 20 /* The fossil header encoding format. */
100100
#define etPATH 21 /* Path type */
101101
#define etWIKISTR 22 /* Timeline comment text rendered from a char*: %W */
102
-#define etSTRINGID 23 /* String with length limit for a UUID prefix: %S */
102
+#define etSTRINGID 23 /* String with length limit for a hash prefix: %S */
103103
#define etROOT 24 /* String value of g.zTop: %R */
104104
#define etJSONSTR 25 /* String encoded as a JSON string literal: %j
105105
Use %!j to include double-quotes around it. */
106106
107107
108108
--- src/printf.c
+++ src/printf.c
@@ -97,11 +97,11 @@
97 #define etHTTPIZE 18 /* Make text safe for HTTP. "/" encoded as %2f */
98 #define etURLIZE 19 /* Make text safe for HTTP. "/" not encoded */
99 #define etFOSSILIZE 20 /* The fossil header encoding format. */
100 #define etPATH 21 /* Path type */
101 #define etWIKISTR 22 /* Timeline comment text rendered from a char*: %W */
102 #define etSTRINGID 23 /* String with length limit for a UUID prefix: %S */
103 #define etROOT 24 /* String value of g.zTop: %R */
104 #define etJSONSTR 25 /* String encoded as a JSON string literal: %j
105 Use %!j to include double-quotes around it. */
106
107
108
--- src/printf.c
+++ src/printf.c
@@ -97,11 +97,11 @@
97 #define etHTTPIZE 18 /* Make text safe for HTTP. "/" encoded as %2f */
98 #define etURLIZE 19 /* Make text safe for HTTP. "/" not encoded */
99 #define etFOSSILIZE 20 /* The fossil header encoding format. */
100 #define etPATH 21 /* Path type */
101 #define etWIKISTR 22 /* Timeline comment text rendered from a char*: %W */
102 #define etSTRINGID 23 /* String with length limit for a hash prefix: %S */
103 #define etROOT 24 /* String value of g.zTop: %R */
104 #define etJSONSTR 25 /* String encoded as a JSON string literal: %j
105 Use %!j to include double-quotes around it. */
106
107
108
+6 -6
--- src/purge.c
+++ src/purge.c
@@ -456,16 +456,16 @@
456456
** ==== Make a backup of your repository before using this command! ====
457457
**
458458
** ==== FURTHER WARNING: This command is a work-in-progress and may yet ====
459459
** ==== contain bugs. ====
460460
**
461
-** fossil purge artifacts UUID... ?OPTIONS?
461
+** fossil purge artifacts HASH... ?OPTIONS?
462462
**
463
-** Move arbitrary artifacts identified by the UUID list into the
463
+** Move arbitrary artifacts identified by the HASH list into the
464464
** graveyard.
465465
**
466
-** fossil purge cat UUID...
466
+** fossil purge cat HASH...
467467
**
468468
** Write the content of one or more artifacts in the graveyard onto
469469
** standard output.
470470
**
471471
** fossil purge checkins TAGS... ?OPTIONS?
@@ -509,12 +509,12 @@
509509
**
510510
** --explain Make no changes, but show what would happen.
511511
** --dry-run An alias for --explain
512512
**
513513
** SUMMARY:
514
-** fossil purge artifacts UUID.. [OPTIONS]
515
-** fossil purge cat UUID...
514
+** fossil purge artifacts HASH.. [OPTIONS]
515
+** fossil purge cat HASH...
516516
** fossil purge checkins TAGS... [OPTIONS]
517517
** fossil purge files FILENAME... [OPTIONS]
518518
** fossil purge list
519519
** fossil purge obliterate ID...
520520
** fossil purge tickets NAME... [OPTIONS]
@@ -547,11 +547,11 @@
547547
purge_artifact_list("ok", "", purgeFlags);
548548
db_end_transaction(0);
549549
}else if( strncmp(zSubcmd, "cat", n)==0 ){
550550
int i, piid;
551551
Blob content;
552
- if( g.argc<4 ) usage("cat UUID...");
552
+ if( g.argc<4 ) usage("cat HASH...");
553553
for(i=3; i<g.argc; i++){
554554
piid = db_int(0, "SELECT piid FROM purgeitem WHERE uuid LIKE '%q%%'",
555555
g.argv[i]);
556556
if( piid==0 ) fossil_fatal("no such item: %s", g.argv[3]);
557557
purge_extract_item(piid, &content);
558558
--- src/purge.c
+++ src/purge.c
@@ -456,16 +456,16 @@
456 ** ==== Make a backup of your repository before using this command! ====
457 **
458 ** ==== FURTHER WARNING: This command is a work-in-progress and may yet ====
459 ** ==== contain bugs. ====
460 **
461 ** fossil purge artifacts UUID... ?OPTIONS?
462 **
463 ** Move arbitrary artifacts identified by the UUID list into the
464 ** graveyard.
465 **
466 ** fossil purge cat UUID...
467 **
468 ** Write the content of one or more artifacts in the graveyard onto
469 ** standard output.
470 **
471 ** fossil purge checkins TAGS... ?OPTIONS?
@@ -509,12 +509,12 @@
509 **
510 ** --explain Make no changes, but show what would happen.
511 ** --dry-run An alias for --explain
512 **
513 ** SUMMARY:
514 ** fossil purge artifacts UUID.. [OPTIONS]
515 ** fossil purge cat UUID...
516 ** fossil purge checkins TAGS... [OPTIONS]
517 ** fossil purge files FILENAME... [OPTIONS]
518 ** fossil purge list
519 ** fossil purge obliterate ID...
520 ** fossil purge tickets NAME... [OPTIONS]
@@ -547,11 +547,11 @@
547 purge_artifact_list("ok", "", purgeFlags);
548 db_end_transaction(0);
549 }else if( strncmp(zSubcmd, "cat", n)==0 ){
550 int i, piid;
551 Blob content;
552 if( g.argc<4 ) usage("cat UUID...");
553 for(i=3; i<g.argc; i++){
554 piid = db_int(0, "SELECT piid FROM purgeitem WHERE uuid LIKE '%q%%'",
555 g.argv[i]);
556 if( piid==0 ) fossil_fatal("no such item: %s", g.argv[3]);
557 purge_extract_item(piid, &content);
558
--- src/purge.c
+++ src/purge.c
@@ -456,16 +456,16 @@
456 ** ==== Make a backup of your repository before using this command! ====
457 **
458 ** ==== FURTHER WARNING: This command is a work-in-progress and may yet ====
459 ** ==== contain bugs. ====
460 **
461 ** fossil purge artifacts HASH... ?OPTIONS?
462 **
463 ** Move arbitrary artifacts identified by the HASH list into the
464 ** graveyard.
465 **
466 ** fossil purge cat HASH...
467 **
468 ** Write the content of one or more artifacts in the graveyard onto
469 ** standard output.
470 **
471 ** fossil purge checkins TAGS... ?OPTIONS?
@@ -509,12 +509,12 @@
509 **
510 ** --explain Make no changes, but show what would happen.
511 ** --dry-run An alias for --explain
512 **
513 ** SUMMARY:
514 ** fossil purge artifacts HASH.. [OPTIONS]
515 ** fossil purge cat HASH...
516 ** fossil purge checkins TAGS... [OPTIONS]
517 ** fossil purge files FILENAME... [OPTIONS]
518 ** fossil purge list
519 ** fossil purge obliterate ID...
520 ** fossil purge tickets NAME... [OPTIONS]
@@ -547,11 +547,11 @@
547 purge_artifact_list("ok", "", purgeFlags);
548 db_end_transaction(0);
549 }else if( strncmp(zSubcmd, "cat", n)==0 ){
550 int i, piid;
551 Blob content;
552 if( g.argc<4 ) usage("cat HASH...");
553 for(i=3; i<g.argc; i++){
554 piid = db_int(0, "SELECT piid FROM purgeitem WHERE uuid LIKE '%q%%'",
555 g.argv[i]);
556 if( piid==0 ) fossil_fatal("no such item: %s", g.argv[3]);
557 purge_extract_item(piid, &content);
558
+1 -1
--- src/rebuild.c
+++ src/rebuild.c
@@ -1149,11 +1149,11 @@
11491149
*/
11501150
void private_export(char *zFileName)
11511151
{
11521152
Stmt q;
11531153
Blob fctx = empty_blob;
1154
- blob_append(&fctx, "# The UUIDs of private artifacts\n", -1);
1154
+ blob_append(&fctx, "# The hashes of private artifacts\n", -1);
11551155
db_prepare(&q,
11561156
"SELECT uuid FROM blob WHERE rid IN ( SELECT rid FROM private );");
11571157
while( db_step(&q)==SQLITE_ROW ){
11581158
const char *zUuid = db_column_text(&q, 0);
11591159
blob_append(&fctx, zUuid, -1);
11601160
--- src/rebuild.c
+++ src/rebuild.c
@@ -1149,11 +1149,11 @@
1149 */
1150 void private_export(char *zFileName)
1151 {
1152 Stmt q;
1153 Blob fctx = empty_blob;
1154 blob_append(&fctx, "# The UUIDs of private artifacts\n", -1);
1155 db_prepare(&q,
1156 "SELECT uuid FROM blob WHERE rid IN ( SELECT rid FROM private );");
1157 while( db_step(&q)==SQLITE_ROW ){
1158 const char *zUuid = db_column_text(&q, 0);
1159 blob_append(&fctx, zUuid, -1);
1160
--- src/rebuild.c
+++ src/rebuild.c
@@ -1149,11 +1149,11 @@
1149 */
1150 void private_export(char *zFileName)
1151 {
1152 Stmt q;
1153 Blob fctx = empty_blob;
1154 blob_append(&fctx, "# The hashes of private artifacts\n", -1);
1155 db_prepare(&q,
1156 "SELECT uuid FROM blob WHERE rid IN ( SELECT rid FROM private );");
1157 while( db_step(&q)==SQLITE_ROW ){
1158 const char *zUuid = db_column_text(&q, 0);
1159 blob_append(&fctx, zUuid, -1);
1160
+1 -1
--- src/report.c
+++ src/report.c
@@ -670,11 +670,11 @@
670670
const char **azArg, /* Text of data in all columns */
671671
const char **azName /* Names of the columns */
672672
){
673673
struct GenerateHTML *pState = (struct GenerateHTML*)pUser;
674674
int i;
675
- const char *zTid; /* Ticket UUID. (value of column named '#') */
675
+ const char *zTid; /* Ticket hash. (value of column named '#') */
676676
const char *zBg = 0; /* Use this background color */
677677
678678
/* Do initialization
679679
*/
680680
if( pState->nCount==0 ){
681681
--- src/report.c
+++ src/report.c
@@ -670,11 +670,11 @@
670 const char **azArg, /* Text of data in all columns */
671 const char **azName /* Names of the columns */
672 ){
673 struct GenerateHTML *pState = (struct GenerateHTML*)pUser;
674 int i;
675 const char *zTid; /* Ticket UUID. (value of column named '#') */
676 const char *zBg = 0; /* Use this background color */
677
678 /* Do initialization
679 */
680 if( pState->nCount==0 ){
681
--- src/report.c
+++ src/report.c
@@ -670,11 +670,11 @@
670 const char **azArg, /* Text of data in all columns */
671 const char **azName /* Names of the columns */
672 ){
673 struct GenerateHTML *pState = (struct GenerateHTML*)pUser;
674 int i;
675 const char *zTid; /* Ticket hash. (value of column named '#') */
676 const char *zBg = 0; /* Use this background color */
677
678 /* Do initialization
679 */
680 if( pState->nCount==0 ){
681
+3 -3
--- src/rss.c
+++ src/rss.c
@@ -22,21 +22,21 @@
2222
#include "rss.h"
2323
#include <assert.h>
2424
2525
/*
2626
** WEBPAGE: timeline.rss
27
-** URL: /timeline.rss?y=TYPE&n=LIMIT&tkt=UUID&tag=TAG&wiki=NAME&name=FILENAME
27
+** URL: /timeline.rss?y=TYPE&n=LIMIT&tkt=HASH&tag=TAG&wiki=NAME&name=FILENAME
2828
**
2929
** Produce an RSS feed of the timeline.
3030
**
3131
** TYPE may be: all, ci (show check-ins only), t (show ticket changes only),
3232
** w (show wiki only), e (show tech notes only), f (show forum posts only),
3333
** g (show tag/branch changes only).
3434
**
3535
** LIMIT is the number of items to show.
3636
**
37
-** tkt=UUID filters for only those events for the specified ticket. tag=TAG
37
+** tkt=HASH filters for only those events for the specified ticket. tag=TAG
3838
** filters for a tag, and wiki=NAME for a wiki page. Only one may be used.
3939
**
4040
** In addition, name=FILENAME filters for a specific file. This may be
4141
** combined with one of the other filters (useful for looking at a specific
4242
** branch).
@@ -231,11 +231,11 @@
231231
** w (show wiki only).
232232
**
233233
** -limit|n LIMIT
234234
** The maximum number of items to show.
235235
**
236
-** -tkt UUID
236
+** -tkt HASH
237237
** Filters for only those events for the specified ticket.
238238
**
239239
** -tag TAG
240240
** filters for a tag
241241
**
242242
--- src/rss.c
+++ src/rss.c
@@ -22,21 +22,21 @@
22 #include "rss.h"
23 #include <assert.h>
24
25 /*
26 ** WEBPAGE: timeline.rss
27 ** URL: /timeline.rss?y=TYPE&n=LIMIT&tkt=UUID&tag=TAG&wiki=NAME&name=FILENAME
28 **
29 ** Produce an RSS feed of the timeline.
30 **
31 ** TYPE may be: all, ci (show check-ins only), t (show ticket changes only),
32 ** w (show wiki only), e (show tech notes only), f (show forum posts only),
33 ** g (show tag/branch changes only).
34 **
35 ** LIMIT is the number of items to show.
36 **
37 ** tkt=UUID filters for only those events for the specified ticket. tag=TAG
38 ** filters for a tag, and wiki=NAME for a wiki page. Only one may be used.
39 **
40 ** In addition, name=FILENAME filters for a specific file. This may be
41 ** combined with one of the other filters (useful for looking at a specific
42 ** branch).
@@ -231,11 +231,11 @@
231 ** w (show wiki only).
232 **
233 ** -limit|n LIMIT
234 ** The maximum number of items to show.
235 **
236 ** -tkt UUID
237 ** Filters for only those events for the specified ticket.
238 **
239 ** -tag TAG
240 ** filters for a tag
241 **
242
--- src/rss.c
+++ src/rss.c
@@ -22,21 +22,21 @@
22 #include "rss.h"
23 #include <assert.h>
24
25 /*
26 ** WEBPAGE: timeline.rss
27 ** URL: /timeline.rss?y=TYPE&n=LIMIT&tkt=HASH&tag=TAG&wiki=NAME&name=FILENAME
28 **
29 ** Produce an RSS feed of the timeline.
30 **
31 ** TYPE may be: all, ci (show check-ins only), t (show ticket changes only),
32 ** w (show wiki only), e (show tech notes only), f (show forum posts only),
33 ** g (show tag/branch changes only).
34 **
35 ** LIMIT is the number of items to show.
36 **
37 ** tkt=HASH filters for only those events for the specified ticket. tag=TAG
38 ** filters for a tag, and wiki=NAME for a wiki page. Only one may be used.
39 **
40 ** In addition, name=FILENAME filters for a specific file. This may be
41 ** combined with one of the other filters (useful for looking at a specific
42 ** branch).
@@ -231,11 +231,11 @@
231 ** w (show wiki only).
232 **
233 ** -limit|n LIMIT
234 ** The maximum number of items to show.
235 **
236 ** -tkt HASH
237 ** Filters for only those events for the specified ticket.
238 **
239 ** -tag TAG
240 ** filters for a tag
241 **
242
+6 -6
--- src/schema.c
+++ src/schema.c
@@ -266,11 +266,11 @@
266266
@ mid INTEGER, -- Check-in that contains fid
267267
@ fid INTEGER, -- New file content. 0 if deleted
268268
@ pmid INTEGER, -- Check-in that contains pid
269269
@ pid INTEGER, -- Prev file content. 0 if new. -1 merge
270270
@ fnid INTEGER REFERENCES filename, -- Name of the file
271
-@ pfnid INTEGER REFERENCES filename, -- Previous name. 0 if unchanged
271
+@ pfnid INTEGER, -- Previous name. 0 if unchanged
272272
@ mperm INTEGER, -- File permissions. 1==exec
273273
@ isaux BOOLEAN DEFAULT 0 -- TRUE if pmid is the primary
274274
@ );
275275
@ CREATE INDEX mlink_i1 ON mlink(mid);
276276
@ CREATE INDEX mlink_i2 ON mlink(fnid);
@@ -321,11 +321,11 @@
321321
@ omtime DATETIME -- Original unchanged date+time, or NULL
322322
@ );
323323
@ CREATE INDEX event_i1 ON event(mtime);
324324
@
325325
@ -- A record of phantoms. A phantom is a record for which we know the
326
-@ -- UUID but we do not (yet) know the file content.
326
+@ -- file hash but we do not (yet) know the file content.
327327
@ --
328328
@ CREATE TABLE phantom(
329329
@ rid INTEGER PRIMARY KEY -- Record ID of the phantom
330330
@ );
331331
@
@@ -362,12 +362,12 @@
362362
@
363363
@ -- Each artifact can have one or more tags. A tag
364364
@ -- is defined by a row in the next table.
365365
@ --
366366
@ -- Wiki pages are tagged with "wiki-NAME" where NAME is the name of
367
-@ -- the wiki page. Tickets changes are tagged with "ticket-UUID" where
368
-@ -- UUID is the indentifier of the ticket. Tags used to assign symbolic
367
+@ -- the wiki page. Tickets changes are tagged with "ticket-HASH" where
368
+@ -- HASH is the indentifier of the ticket. Tags used to assign symbolic
369369
@ -- names to baselines are branches are of the form "sym-NAME" where
370370
@ -- NAME is the symbolic name.
371371
@ --
372372
@ CREATE TABLE tag(
373373
@ tagid INTEGER PRIMARY KEY, -- Numeric tag ID
@@ -421,12 +421,12 @@
421421
@ --
422422
@ CREATE TABLE attachment(
423423
@ attachid INTEGER PRIMARY KEY, -- Local id for this attachment
424424
@ isLatest BOOLEAN DEFAULT 0, -- True if this is the one to use
425425
@ mtime TIMESTAMP, -- Last changed. Julian day.
426
-@ src TEXT, -- UUID of the attachment. NULL to delete
427
-@ target TEXT, -- Object attached to. Wikiname or Tkt UUID
426
+@ src TEXT, -- Hash of the attachment. NULL to delete
427
+@ target TEXT, -- Object attached to. Wikiname or Tkt hash
428428
@ filename TEXT, -- Filename for the attachment
429429
@ comment TEXT, -- Comment associated with this attachment
430430
@ user TEXT -- Name of user adding attachment
431431
@ );
432432
@ CREATE INDEX attachment_idx1 ON attachment(target, filename, mtime);
433433
--- src/schema.c
+++ src/schema.c
@@ -266,11 +266,11 @@
266 @ mid INTEGER, -- Check-in that contains fid
267 @ fid INTEGER, -- New file content. 0 if deleted
268 @ pmid INTEGER, -- Check-in that contains pid
269 @ pid INTEGER, -- Prev file content. 0 if new. -1 merge
270 @ fnid INTEGER REFERENCES filename, -- Name of the file
271 @ pfnid INTEGER REFERENCES filename, -- Previous name. 0 if unchanged
272 @ mperm INTEGER, -- File permissions. 1==exec
273 @ isaux BOOLEAN DEFAULT 0 -- TRUE if pmid is the primary
274 @ );
275 @ CREATE INDEX mlink_i1 ON mlink(mid);
276 @ CREATE INDEX mlink_i2 ON mlink(fnid);
@@ -321,11 +321,11 @@
321 @ omtime DATETIME -- Original unchanged date+time, or NULL
322 @ );
323 @ CREATE INDEX event_i1 ON event(mtime);
324 @
325 @ -- A record of phantoms. A phantom is a record for which we know the
326 @ -- UUID but we do not (yet) know the file content.
327 @ --
328 @ CREATE TABLE phantom(
329 @ rid INTEGER PRIMARY KEY -- Record ID of the phantom
330 @ );
331 @
@@ -362,12 +362,12 @@
362 @
363 @ -- Each artifact can have one or more tags. A tag
364 @ -- is defined by a row in the next table.
365 @ --
366 @ -- Wiki pages are tagged with "wiki-NAME" where NAME is the name of
367 @ -- the wiki page. Tickets changes are tagged with "ticket-UUID" where
368 @ -- UUID is the indentifier of the ticket. Tags used to assign symbolic
369 @ -- names to baselines are branches are of the form "sym-NAME" where
370 @ -- NAME is the symbolic name.
371 @ --
372 @ CREATE TABLE tag(
373 @ tagid INTEGER PRIMARY KEY, -- Numeric tag ID
@@ -421,12 +421,12 @@
421 @ --
422 @ CREATE TABLE attachment(
423 @ attachid INTEGER PRIMARY KEY, -- Local id for this attachment
424 @ isLatest BOOLEAN DEFAULT 0, -- True if this is the one to use
425 @ mtime TIMESTAMP, -- Last changed. Julian day.
426 @ src TEXT, -- UUID of the attachment. NULL to delete
427 @ target TEXT, -- Object attached to. Wikiname or Tkt UUID
428 @ filename TEXT, -- Filename for the attachment
429 @ comment TEXT, -- Comment associated with this attachment
430 @ user TEXT -- Name of user adding attachment
431 @ );
432 @ CREATE INDEX attachment_idx1 ON attachment(target, filename, mtime);
433
--- src/schema.c
+++ src/schema.c
@@ -266,11 +266,11 @@
266 @ mid INTEGER, -- Check-in that contains fid
267 @ fid INTEGER, -- New file content. 0 if deleted
268 @ pmid INTEGER, -- Check-in that contains pid
269 @ pid INTEGER, -- Prev file content. 0 if new. -1 merge
270 @ fnid INTEGER REFERENCES filename, -- Name of the file
271 @ pfnid INTEGER, -- Previous name. 0 if unchanged
272 @ mperm INTEGER, -- File permissions. 1==exec
273 @ isaux BOOLEAN DEFAULT 0 -- TRUE if pmid is the primary
274 @ );
275 @ CREATE INDEX mlink_i1 ON mlink(mid);
276 @ CREATE INDEX mlink_i2 ON mlink(fnid);
@@ -321,11 +321,11 @@
321 @ omtime DATETIME -- Original unchanged date+time, or NULL
322 @ );
323 @ CREATE INDEX event_i1 ON event(mtime);
324 @
325 @ -- A record of phantoms. A phantom is a record for which we know the
326 @ -- file hash but we do not (yet) know the file content.
327 @ --
328 @ CREATE TABLE phantom(
329 @ rid INTEGER PRIMARY KEY -- Record ID of the phantom
330 @ );
331 @
@@ -362,12 +362,12 @@
362 @
363 @ -- Each artifact can have one or more tags. A tag
364 @ -- is defined by a row in the next table.
365 @ --
366 @ -- Wiki pages are tagged with "wiki-NAME" where NAME is the name of
367 @ -- the wiki page. Tickets changes are tagged with "ticket-HASH" where
368 @ -- HASH is the indentifier of the ticket. Tags used to assign symbolic
369 @ -- names to baselines are branches are of the form "sym-NAME" where
370 @ -- NAME is the symbolic name.
371 @ --
372 @ CREATE TABLE tag(
373 @ tagid INTEGER PRIMARY KEY, -- Numeric tag ID
@@ -421,12 +421,12 @@
421 @ --
422 @ CREATE TABLE attachment(
423 @ attachid INTEGER PRIMARY KEY, -- Local id for this attachment
424 @ isLatest BOOLEAN DEFAULT 0, -- True if this is the one to use
425 @ mtime TIMESTAMP, -- Last changed. Julian day.
426 @ src TEXT, -- Hash of the attachment. NULL to delete
427 @ target TEXT, -- Object attached to. Wikiname or Tkt hash
428 @ filename TEXT, -- Filename for the attachment
429 @ comment TEXT, -- Comment associated with this attachment
430 @ user TEXT -- Name of user adding attachment
431 @ );
432 @ CREATE INDEX attachment_idx1 ON attachment(target, filename, mtime);
433
--- src/security_audit.c
+++ src/security_audit.c
@@ -521,10 +521,17 @@
521521
nCgi = nFile==0 ? 0 : db_int(0,"SELECT count(*) FROM sfile WHERE isexe");
522522
@ <li><p> CGI Extensions are enabled with a document root
523523
@ at <a href='%R/extfilelist'>%h(g.zExtRoot)</a> holding
524524
@ %d(nCgi) CGIs and %d(nFile-nCgi) static content and data files.
525525
}
526
+
527
+ if( fileedit_glob()!=0 ){
528
+ @ <li><p><a href='%R/fileedit'>Online File Editing</a> is enabled
529
+ @ for this repository. Clear the
530
+ @ <a href='%R/setup_settings'>"fileedit-glob" setting</a> to
531
+ @ disable online editing.</p>
532
+ }
526533
527534
@ <li><p> User capability summary:
528535
capability_summary();
529536
530537
531538
--- src/security_audit.c
+++ src/security_audit.c
@@ -521,10 +521,17 @@
521 nCgi = nFile==0 ? 0 : db_int(0,"SELECT count(*) FROM sfile WHERE isexe");
522 @ <li><p> CGI Extensions are enabled with a document root
523 @ at <a href='%R/extfilelist'>%h(g.zExtRoot)</a> holding
524 @ %d(nCgi) CGIs and %d(nFile-nCgi) static content and data files.
525 }
 
 
 
 
 
 
 
526
527 @ <li><p> User capability summary:
528 capability_summary();
529
530
531
--- src/security_audit.c
+++ src/security_audit.c
@@ -521,10 +521,17 @@
521 nCgi = nFile==0 ? 0 : db_int(0,"SELECT count(*) FROM sfile WHERE isexe");
522 @ <li><p> CGI Extensions are enabled with a document root
523 @ at <a href='%R/extfilelist'>%h(g.zExtRoot)</a> holding
524 @ %d(nCgi) CGIs and %d(nFile-nCgi) static content and data files.
525 }
526
527 if( fileedit_glob()!=0 ){
528 @ <li><p><a href='%R/fileedit'>Online File Editing</a> is enabled
529 @ for this repository. Clear the
530 @ <a href='%R/setup_settings'>"fileedit-glob" setting</a> to
531 @ disable online editing.</p>
532 }
533
534 @ <li><p> User capability summary:
535 capability_summary();
536
537
538
+270 -82
--- src/shell.c
+++ src/shell.c
@@ -9700,22 +9700,10 @@
97009700
char **azFilter; /* Array of xFilter rejection GLOB patterns */
97019701
sqlite3_session *p; /* The open session */
97029702
};
97039703
#endif
97049704
9705
-/*
9706
-** Shell output mode information from before ".explain on",
9707
-** saved so that it can be restored by ".explain off"
9708
-*/
9709
-typedef struct SavedModeInfo SavedModeInfo;
9710
-struct SavedModeInfo {
9711
- int valid; /* Is there legit data in here? */
9712
- int mode; /* Mode prior to ".explain on" */
9713
- int showHeader; /* The ".header" setting prior to ".explain on" */
9714
- int colWidth[100]; /* Column widths prior to ".explain on" */
9715
-};
9716
-
97179705
typedef struct ExpertInfo ExpertInfo;
97189706
struct ExpertInfo {
97199707
sqlite3expert *pExpert;
97209708
int bVerbose;
97219709
};
@@ -9781,12 +9769,13 @@
97819769
char zTestcase[30]; /* Name of current test case */
97829770
char colSeparator[20]; /* Column separator character for several modes */
97839771
char rowSeparator[20]; /* Row separator character for MODE_Ascii */
97849772
char colSepPrior[20]; /* Saved column separator */
97859773
char rowSepPrior[20]; /* Saved row separator */
9786
- int colWidth[100]; /* Requested width of each column when in column mode*/
9787
- int actualWidth[100]; /* Actual width of each column */
9774
+ int *colWidth; /* Requested width of each column in columnar modes */
9775
+ int *actualWidth; /* Actual width of each column */
9776
+ int nWidth; /* Number of slots in colWidth[] and actualWidth[] */
97889777
char nullValue[20]; /* The text to print when a NULL comes back from
97899778
** the database */
97909779
char outfile[FILENAME_MAX]; /* Filename for *out */
97919780
const char *zDbFilename; /* name of the database file */
97929781
char *zFreeOnClose; /* Filename to free when closing */
@@ -9867,10 +9856,13 @@
98679856
#define MODE_Csv 8 /* Quote strings, numbers are plain */
98689857
#define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */
98699858
#define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */
98709859
#define MODE_Pretty 11 /* Pretty-print schemas */
98719860
#define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */
9861
+#define MODE_Json 13 /* Output JSON */
9862
+#define MODE_Markdown 14 /* Markdown formatting */
9863
+#define MODE_Table 15 /* MySQL-style table formatting */
98729864
98739865
static const char *modeDescr[] = {
98749866
"line",
98759867
"column",
98769868
"list",
@@ -9881,11 +9873,14 @@
98819873
"tcl",
98829874
"csv",
98839875
"explain",
98849876
"ascii",
98859877
"prettyprint",
9886
- "eqp"
9878
+ "eqp",
9879
+ "json",
9880
+ "markdown",
9881
+ "table"
98879882
};
98889883
98899884
/*
98909885
** These are the column/row/line separators used by the various
98919886
** import/export modes.
@@ -10248,10 +10243,44 @@
1024810243
fputc(c, out);
1024910244
}
1025010245
}
1025110246
fputc('"', out);
1025210247
}
10248
+
10249
+/*
10250
+** Output the given string as a quoted according to JSON quoting rules.
10251
+*/
10252
+static void output_json_string(FILE *out, const char *z, int n){
10253
+ unsigned int c;
10254
+ if( n<0 ) n = (int)strlen(z);
10255
+ fputc('"', out);
10256
+ while( n-- ){
10257
+ c = *(z++);
10258
+ if( c=='\\' || c=='"' ){
10259
+ fputc('\\', out);
10260
+ fputc(c, out);
10261
+ }else if( c<=0x1f ){
10262
+ fputc('\\', out);
10263
+ if( c=='\b' ){
10264
+ fputc('b', out);
10265
+ }else if( c=='\f' ){
10266
+ fputc('f', out);
10267
+ }else if( c=='\n' ){
10268
+ fputc('n', out);
10269
+ }else if( c=='\r' ){
10270
+ fputc('r', out);
10271
+ }else if( c=='\t' ){
10272
+ fputc('t', out);
10273
+ }else{
10274
+ raw_printf(out, "u%04x",c);
10275
+ }
10276
+ }else{
10277
+ fputc(c, out);
10278
+ }
10279
+ }
10280
+ fputc('"', out);
10281
+}
1025310282
1025410283
/*
1025510284
** Output the given string with characters that are special to
1025610285
** HTML escaped.
1025710286
*/
@@ -10557,10 +10586,40 @@
1055710586
raw_printf(p->out, "Progress %u\n", p->nProgress);
1055810587
}
1055910588
return 0;
1056010589
}
1056110590
#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
10591
+
10592
+/*
10593
+** Print N dashes
10594
+*/
10595
+static void print_dashes(FILE *out, int N){
10596
+ const char zDash[] = "--------------------------------------------------";
10597
+ const int nDash = sizeof(zDash) - 1;
10598
+ while( N>nDash ){
10599
+ fputs(zDash, out);
10600
+ N -= nDash;
10601
+ }
10602
+ raw_printf(out, "%.*s", N, zDash);
10603
+}
10604
+
10605
+/*
10606
+** Print a markdown or table-style row separator
10607
+*/
10608
+static void print_row_separator(
10609
+ ShellState *p,
10610
+ int nArg,
10611
+ const char *zSep
10612
+){
10613
+ int i;
10614
+ for(i=0; i<nArg; i++){
10615
+ fputs(zSep, p->out);
10616
+ print_dashes(p->out, p->actualWidth[i]+2);
10617
+ }
10618
+ fputs(zSep, p->out);
10619
+ fputs("\n", p->out);
10620
+}
1056210621
1056310622
/*
1056410623
** This is the callback routine that the shell
1056510624
** invokes for each row of a query result.
1056610625
*/
@@ -10567,11 +10626,11 @@
1056710626
static int shell_callback(
1056810627
void *pArg,
1056910628
int nArg, /* Number of result columns */
1057010629
char **azArg, /* Text of each result column */
1057110630
char **azCol, /* Column names */
10572
- int *aiType /* Column types */
10631
+ int *aiType /* Column types. Might be NULL */
1057310632
){
1057410633
int i;
1057510634
ShellState *p = (ShellState*)pArg;
1057610635
1057710636
if( azArg==0 ) return 0;
@@ -10588,85 +10647,36 @@
1058810647
utf8_printf(p->out,"%*s = %s%s", w, azCol[i],
1058910648
azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
1059010649
}
1059110650
break;
1059210651
}
10593
- case MODE_Explain:
10594
- case MODE_Column: {
10595
- static const int aExplainWidths[] = {4, 13, 4, 4, 4, 13, 2, 13};
10596
- const int *colWidth;
10597
- int showHdr;
10598
- char *rowSep;
10599
- int nWidth;
10600
- if( p->cMode==MODE_Column ){
10601
- colWidth = p->colWidth;
10602
- nWidth = ArraySize(p->colWidth);
10603
- showHdr = p->showHeader;
10604
- rowSep = p->rowSeparator;
10605
- }else{
10606
- colWidth = aExplainWidths;
10607
- nWidth = ArraySize(aExplainWidths);
10608
- showHdr = 1;
10609
- rowSep = SEP_Row;
10652
+ case MODE_Explain: {
10653
+ static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13};
10654
+ if( nArg>ArraySize(aExplainWidth) ){
10655
+ nArg = ArraySize(aExplainWidth);
1061010656
}
1061110657
if( p->cnt++==0 ){
1061210658
for(i=0; i<nArg; i++){
10613
- int w, n;
10614
- if( i<nWidth ){
10615
- w = colWidth[i];
10616
- }else{
10617
- w = 0;
10618
- }
10619
- if( w==0 ){
10620
- w = strlenChar(azCol[i] ? azCol[i] : "");
10621
- if( w<10 ) w = 10;
10622
- n = strlenChar(azArg && azArg[i] ? azArg[i] : p->nullValue);
10623
- if( w<n ) w = n;
10624
- }
10625
- if( i<ArraySize(p->actualWidth) ){
10626
- p->actualWidth[i] = w;
10627
- }
10628
- if( showHdr ){
10629
- utf8_width_print(p->out, w, azCol[i]);
10630
- utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : " ");
10631
- }
10632
- }
10633
- if( showHdr ){
10634
- for(i=0; i<nArg; i++){
10635
- int w;
10636
- if( i<ArraySize(p->actualWidth) ){
10637
- w = p->actualWidth[i];
10638
- if( w<0 ) w = -w;
10639
- }else{
10640
- w = 10;
10641
- }
10642
- utf8_printf(p->out,"%-*.*s%s",w,w,
10643
- "----------------------------------------------------------"
10644
- "----------------------------------------------------------",
10645
- i==nArg-1 ? rowSep : " ");
10646
- }
10659
+ int w = aExplainWidth[i];
10660
+ utf8_width_print(p->out, w, azCol[i]);
10661
+ fputs(i==nArg-1 ? "\n" : " ", p->out);
1064710662
}
1064810663
}
1064910664
if( azArg==0 ) break;
1065010665
for(i=0; i<nArg; i++){
10651
- int w;
10652
- if( i<ArraySize(p->actualWidth) ){
10653
- w = p->actualWidth[i];
10654
- }else{
10655
- w = 10;
10656
- }
10657
- if( p->cMode==MODE_Explain && azArg[i] && strlenChar(azArg[i])>w ){
10666
+ int w = aExplainWidth[i];
10667
+ if( azArg[i] && strlenChar(azArg[i])>w ){
1065810668
w = strlenChar(azArg[i]);
1065910669
}
1066010670
if( i==1 && p->aiIndent && p->pStmt ){
1066110671
if( p->iIndent<p->nIndent ){
1066210672
utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
1066310673
}
1066410674
p->iIndent++;
1066510675
}
1066610676
utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);
10667
- utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : " ");
10677
+ fputs(i==nArg-1 ? "\n" : " ", p->out);
1066810678
}
1066910679
break;
1067010680
}
1067110681
case MODE_Semi: { /* .schema and .fullschema output */
1067210682
printSchemaLine(p->out, azArg[0], ";\n");
@@ -10865,23 +10875,65 @@
1086510875
output_quoted_escaped_string(p->out, azArg[i]);
1086610876
}
1086710877
}
1086810878
raw_printf(p->out,");\n");
1086910879
break;
10880
+ }
10881
+ case MODE_Json: {
10882
+ if( azArg==0 ) break;
10883
+ if( p->cnt==0 ){
10884
+ fputs("[{", p->out);
10885
+ }else{
10886
+ fputs(",\n{", p->out);
10887
+ }
10888
+ p->cnt++;
10889
+ for(i=0; i<nArg; i++){
10890
+ output_json_string(p->out, azCol[i], -1);
10891
+ putc(':', p->out);
10892
+ if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
10893
+ fputs("null",p->out);
10894
+ }else if( aiType && aiType[i]==SQLITE_FLOAT ){
10895
+ char z[50];
10896
+ double r = sqlite3_column_double(p->pStmt, i);
10897
+ sqlite3_uint64 ur;
10898
+ memcpy(&ur,&r,sizeof(r));
10899
+ if( ur==0x7ff0000000000000LL ){
10900
+ raw_printf(p->out, "1e999");
10901
+ }else if( ur==0xfff0000000000000LL ){
10902
+ raw_printf(p->out, "-1e999");
10903
+ }else{
10904
+ sqlite3_snprintf(50,z,"%!.20g", r);
10905
+ raw_printf(p->out, "%s", z);
10906
+ }
10907
+ }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
10908
+ const void *pBlob = sqlite3_column_blob(p->pStmt, i);
10909
+ int nBlob = sqlite3_column_bytes(p->pStmt, i);
10910
+ output_json_string(p->out, pBlob, nBlob);
10911
+ }else if( aiType && aiType[i]==SQLITE_TEXT ){
10912
+ output_json_string(p->out, azArg[i], -1);
10913
+ }else{
10914
+ utf8_printf(p->out,"%s", azArg[i]);
10915
+ }
10916
+ if( i<nArg-1 ){
10917
+ putc(',', p->out);
10918
+ }
10919
+ }
10920
+ putc('}', p->out);
10921
+ break;
1087010922
}
1087110923
case MODE_Quote: {
1087210924
if( azArg==0 ) break;
1087310925
if( p->cnt==0 && p->showHeader ){
1087410926
for(i=0; i<nArg; i++){
10875
- if( i>0 ) raw_printf(p->out, ",");
10927
+ if( i>0 ) fputs(p->colSeparator, p->out);
1087610928
output_quoted_string(p->out, azCol[i]);
1087710929
}
10878
- raw_printf(p->out,"\n");
10930
+ fputs(p->rowSeparator, p->out);
1087910931
}
1088010932
p->cnt++;
1088110933
for(i=0; i<nArg; i++){
10882
- if( i>0 ) raw_printf(p->out, ",");
10934
+ if( i>0 ) fputs(p->colSeparator, p->out);
1088310935
if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
1088410936
utf8_printf(p->out,"NULL");
1088510937
}else if( aiType && aiType[i]==SQLITE_TEXT ){
1088610938
output_quoted_string(p->out, azArg[i]);
1088710939
}else if( aiType && aiType[i]==SQLITE_INTEGER ){
@@ -10899,11 +10951,11 @@
1089910951
utf8_printf(p->out,"%s", azArg[i]);
1090010952
}else{
1090110953
output_quoted_string(p->out, azArg[i]);
1090210954
}
1090310955
}
10904
- raw_printf(p->out,"\n");
10956
+ fputs(p->rowSeparator, p->out);
1090510957
break;
1090610958
}
1090710959
case MODE_Ascii: {
1090810960
if( p->cnt++==0 && p->showHeader ){
1090910961
for(i=0; i<nArg; i++){
@@ -11554,19 +11606,127 @@
1155411606
}
1155511607
sqlite3_reset(pQ);
1155611608
}
1155711609
sqlite3_finalize(pQ);
1155811610
}
11611
+
11612
+/*
11613
+** Run a prepared statement and output the result in one of the
11614
+** table-oriented formats: MODE_Column, MODE_Markdown, or MODE_Table.
11615
+**
11616
+** This is different from ordinary exec_prepared_stmt() in that
11617
+** it has to run the entire query and gather the results into memory
11618
+** first, in order to determine column widths, before providing
11619
+** any output.
11620
+*/
11621
+static void exec_prepared_stmt_columnar(
11622
+ ShellState *p, /* Pointer to ShellState */
11623
+ sqlite3_stmt *pStmt /* Statment to run */
11624
+){
11625
+ int nRow = 0;
11626
+ int nColumn = 0;
11627
+ char **azData = 0;
11628
+ char *zMsg = 0;
11629
+ const char *z;
11630
+ int rc;
11631
+ int i, j, nTotal, w, n;
11632
+ const char *colSep;
11633
+ const char *rowSep;
11634
+
11635
+ rc = sqlite3_get_table(p->db, sqlite3_sql(pStmt),
11636
+ &azData, &nRow, &nColumn, &zMsg);
11637
+ if( rc ){
11638
+ utf8_printf(p->out, "ERROR: %s\n", zMsg);
11639
+ sqlite3_free(zMsg);
11640
+ sqlite3_free_table(azData);
11641
+ return;
11642
+ }
11643
+ if( nColumn>p->nWidth ){
11644
+ p->colWidth = realloc(p->colWidth, nColumn*2*sizeof(int));
11645
+ if( p->colWidth==0 ) shell_out_of_memory();
11646
+ for(i=p->nWidth; i<nColumn; i++) p->colWidth[i] = 0;
11647
+ p->nWidth = nColumn;
11648
+ p->actualWidth = &p->colWidth[nColumn];
11649
+ }
11650
+ memset(p->actualWidth, 0, nColumn*sizeof(int));
11651
+ for(i=0; i<nColumn; i++){
11652
+ w = p->colWidth[i];
11653
+ if( w<0 ) w = -w;
11654
+ p->actualWidth[i] = w;
11655
+ }
11656
+ nTotal = nColumn*(nRow+1);
11657
+ for(i=0; i<nTotal; i++){
11658
+ z = azData[i];
11659
+ if( z==0 ) z = p->nullValue;
11660
+ n = strlenChar(z);
11661
+ j = i%nColumn;
11662
+ if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
11663
+ }
11664
+ if( p->cMode==MODE_Column ){
11665
+ colSep = " ";
11666
+ rowSep = "\n";
11667
+ if( p->showHeader ){
11668
+ for(i=0; i<nColumn; i++){
11669
+ w = p->actualWidth[i];
11670
+ if( p->colWidth[i]<0 ) w = -w;
11671
+ utf8_width_print(p->out, w, azData[i]);
11672
+ fputs(i==nColumn-1?"\n":" ", p->out);
11673
+ }
11674
+ for(i=0; i<nColumn; i++){
11675
+ print_dashes(p->out, p->actualWidth[i]);
11676
+ fputs(i==nColumn-1?"\n":" ", p->out);
11677
+ }
11678
+ }
11679
+ }else{
11680
+ colSep = " | ";
11681
+ rowSep = " |\n";
11682
+ if( p->cMode==MODE_Table ) print_row_separator(p, nColumn, "+");
11683
+ fputs("| ", p->out);
11684
+ for(i=0; i<nColumn; i++){
11685
+ w = p->actualWidth[i];
11686
+ n = strlenChar(azData[i]);
11687
+ utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
11688
+ fputs(i==nColumn-1?" |\n":" | ", p->out);
11689
+ }
11690
+ print_row_separator(p, nColumn, p->cMode==MODE_Table ? "+" : "|");
11691
+ }
11692
+ for(i=nColumn, j=0; i<nTotal; i++, j++){
11693
+ if( j==0 && p->cMode!=MODE_Column ) fputs("| ", p->out);
11694
+ z = azData[i];
11695
+ if( z==0 ) z = p->nullValue;
11696
+ w = p->actualWidth[j];
11697
+ if( p->colWidth[j]<0 ) w = -w;
11698
+ utf8_width_print(p->out, w, z);
11699
+ if( j==nColumn-1 ){
11700
+ fputs(rowSep, p->out);
11701
+ j = -1;
11702
+ }else{
11703
+ fputs(colSep, p->out);
11704
+ }
11705
+ }
11706
+ if( p->cMode==MODE_Table ){
11707
+ print_row_separator(p, nColumn, "+");
11708
+ }
11709
+ sqlite3_free_table(azData);
11710
+}
1155911711
1156011712
/*
1156111713
** Run a prepared statement
1156211714
*/
1156311715
static void exec_prepared_stmt(
1156411716
ShellState *pArg, /* Pointer to ShellState */
1156511717
sqlite3_stmt *pStmt /* Statment to run */
1156611718
){
1156711719
int rc;
11720
+
11721
+ if( pArg->cMode==MODE_Column
11722
+ || pArg->cMode==MODE_Table
11723
+ || pArg->cMode==MODE_Markdown
11724
+ ){
11725
+ exec_prepared_stmt_columnar(pArg, pStmt);
11726
+ return;
11727
+ }
1156811728
1156911729
/* perform the first step. this will tell us if we
1157011730
** have a result set or not and how wide it is.
1157111731
*/
1157211732
rc = sqlite3_step(pStmt);
@@ -11611,10 +11771,15 @@
1161111771
rc = sqlite3_step(pStmt);
1161211772
}
1161311773
}
1161411774
} while( SQLITE_ROW == rc );
1161511775
sqlite3_free(pData);
11776
+ if( pArg->cMode==MODE_Table ){
11777
+ print_row_separator(pArg, nCol, "+");
11778
+ }else if( pArg->cMode==MODE_Json ){
11779
+ fputs("]\n", pArg->out);
11780
+ }
1161611781
}
1161711782
}
1161811783
}
1161911784
1162011785
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -16883,19 +17048,28 @@
1688317048
}else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
1688417049
p->mode = MODE_Insert;
1688517050
set_table_name(p, nArg>=3 ? azArg[2] : "table");
1688617051
}else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){
1688717052
p->mode = MODE_Quote;
17053
+ sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
17054
+ sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
1688817055
}else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
1688917056
p->mode = MODE_Ascii;
1689017057
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
1689117058
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
17059
+ }else if( c2=='m' && strncmp(azArg[1],"markdown",n2)==0 ){
17060
+ p->mode = MODE_Markdown;
17061
+ }else if( c2=='t' && strncmp(azArg[1],"table",n2)==0 ){
17062
+ p->mode = MODE_Table;
17063
+ }else if( c2=='j' && strncmp(azArg[1],"json",n2)==0 ){
17064
+ p->mode = MODE_Json;
1689217065
}else if( nArg==1 ){
1689317066
raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
1689417067
}else{
1689517068
raw_printf(stderr, "Error: mode should be one of: "
16896
- "ascii column csv html insert line list quote tabs tcl\n");
17069
+ "ascii column csv html insert json line list markdown "
17070
+ "quote table tabs tcl\n");
1689717071
rc = 1;
1689817072
}
1689917073
p->cMode = p->mode;
1690017074
}else
1690117075
@@ -17992,11 +18166,11 @@
1799218166
utf8_printf(p->out,"%12.12s: ", "rowseparator");
1799318167
output_c_string(p->out, p->rowSeparator);
1799418168
raw_printf(p->out, "\n");
1799518169
utf8_printf(p->out, "%12.12s: %s\n","stats", azBool[p->statsOn!=0]);
1799618170
utf8_printf(p->out, "%12.12s: ", "width");
17997
- for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
18171
+ for (i=0;i<p->nWidth;i++) {
1799818172
raw_printf(p->out, "%d ", p->colWidth[i]);
1799918173
}
1800018174
raw_printf(p->out, "\n");
1800118175
utf8_printf(p->out, "%12.12s: %s\n", "filename",
1800218176
p->zDbFilename ? p->zDbFilename : "");
@@ -18541,11 +18715,15 @@
1854118715
#endif
1854218716
1854318717
if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
1854418718
int j;
1854518719
assert( nArg<=ArraySize(azArg) );
18546
- for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
18720
+ p->nWidth = nArg-1;
18721
+ p->colWidth = realloc(p->colWidth, p->nWidth*sizeof(int)*2);
18722
+ if( p->colWidth==0 && p->nWidth>0 ) shell_out_of_memory();
18723
+ if( p->nWidth ) p->actualWidth = &p->colWidth[p->nWidth];
18724
+ for(j=1; j<nArg; j++){
1854718725
p->colWidth[j-1] = (int)integerValue(azArg[j]);
1854818726
}
1854918727
}else
1855018728
1855118729
{
@@ -18901,13 +19079,15 @@
1890119079
" -heap SIZE Size of heap for memsys3 or memsys5\n"
1890219080
#endif
1890319081
" -help show this message\n"
1890419082
" -html set output mode to HTML\n"
1890519083
" -interactive force interactive I/O\n"
19084
+ " -json set output mode to 'json'\n"
1890619085
" -line set output mode to 'line'\n"
1890719086
" -list set output mode to 'list'\n"
1890819087
" -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
19088
+ " -markdown set output mode to 'markdown'\n"
1890919089
#if defined(SQLITE_ENABLE_DESERIALIZE)
1891019090
" -maxsize N maximum size for a --deserialize database\n"
1891119091
#endif
1891219092
" -memtrace trace all memory allocations and deallocations\n"
1891319093
" -mmap N default mmap size set to N\n"
@@ -18923,10 +19103,11 @@
1892319103
" -separator SEP set output column separator. Default: '|'\n"
1892419104
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
1892519105
" -sorterref SIZE sorter references threshold size\n"
1892619106
#endif
1892719107
" -stats print memory stats before each finalize\n"
19108
+ " -table set output mode to 'table'\n"
1892819109
" -version show SQLite version\n"
1892919110
" -vfs NAME use NAME as the default VFS\n"
1893019111
#ifdef SQLITE_ENABLE_VFSTRACE
1893119112
" -vfstrace enable tracing of all VFS calls\n"
1893219113
#endif
@@ -19324,10 +19505,16 @@
1932419505
data.mode = MODE_Quote;
1932519506
}else if( strcmp(z,"-line")==0 ){
1932619507
data.mode = MODE_Line;
1932719508
}else if( strcmp(z,"-column")==0 ){
1932819509
data.mode = MODE_Column;
19510
+ }else if( strcmp(z,"-json")==0 ){
19511
+ data.mode = MODE_Json;
19512
+ }else if( strcmp(z,"-markdown")==0 ){
19513
+ data.mode = MODE_Markdown;
19514
+ }else if( strcmp(z,"-table")==0 ){
19515
+ data.mode = MODE_Table;
1932919516
}else if( strcmp(z,"-csv")==0 ){
1933019517
data.mode = MODE_Csv;
1933119518
memcpy(data.colSeparator,",",2);
1933219519
#ifdef SQLITE_HAVE_ZLIB
1933319520
}else if( strcmp(z,"-zip")==0 ){
@@ -19541,10 +19728,11 @@
1954119728
clearTempFile(&data);
1954219729
#if !SQLITE_SHELL_IS_UTF8
1954319730
for(i=0; i<argcToFree; i++) free(argvToFree[i]);
1954419731
free(argvToFree);
1954519732
#endif
19733
+ free(data.colWidth);
1954619734
/* Clear the global data structure so that valgrind will detect memory
1954719735
** leaks */
1954819736
memset(&data, 0, sizeof(data));
1954919737
return rc;
1955019738
}
1955119739
--- src/shell.c
+++ src/shell.c
@@ -9700,22 +9700,10 @@
9700 char **azFilter; /* Array of xFilter rejection GLOB patterns */
9701 sqlite3_session *p; /* The open session */
9702 };
9703 #endif
9704
9705 /*
9706 ** Shell output mode information from before ".explain on",
9707 ** saved so that it can be restored by ".explain off"
9708 */
9709 typedef struct SavedModeInfo SavedModeInfo;
9710 struct SavedModeInfo {
9711 int valid; /* Is there legit data in here? */
9712 int mode; /* Mode prior to ".explain on" */
9713 int showHeader; /* The ".header" setting prior to ".explain on" */
9714 int colWidth[100]; /* Column widths prior to ".explain on" */
9715 };
9716
9717 typedef struct ExpertInfo ExpertInfo;
9718 struct ExpertInfo {
9719 sqlite3expert *pExpert;
9720 int bVerbose;
9721 };
@@ -9781,12 +9769,13 @@
9781 char zTestcase[30]; /* Name of current test case */
9782 char colSeparator[20]; /* Column separator character for several modes */
9783 char rowSeparator[20]; /* Row separator character for MODE_Ascii */
9784 char colSepPrior[20]; /* Saved column separator */
9785 char rowSepPrior[20]; /* Saved row separator */
9786 int colWidth[100]; /* Requested width of each column when in column mode*/
9787 int actualWidth[100]; /* Actual width of each column */
 
9788 char nullValue[20]; /* The text to print when a NULL comes back from
9789 ** the database */
9790 char outfile[FILENAME_MAX]; /* Filename for *out */
9791 const char *zDbFilename; /* name of the database file */
9792 char *zFreeOnClose; /* Filename to free when closing */
@@ -9867,10 +9856,13 @@
9867 #define MODE_Csv 8 /* Quote strings, numbers are plain */
9868 #define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */
9869 #define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */
9870 #define MODE_Pretty 11 /* Pretty-print schemas */
9871 #define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */
 
 
 
9872
9873 static const char *modeDescr[] = {
9874 "line",
9875 "column",
9876 "list",
@@ -9881,11 +9873,14 @@
9881 "tcl",
9882 "csv",
9883 "explain",
9884 "ascii",
9885 "prettyprint",
9886 "eqp"
 
 
 
9887 };
9888
9889 /*
9890 ** These are the column/row/line separators used by the various
9891 ** import/export modes.
@@ -10248,10 +10243,44 @@
10248 fputc(c, out);
10249 }
10250 }
10251 fputc('"', out);
10252 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10253
10254 /*
10255 ** Output the given string with characters that are special to
10256 ** HTML escaped.
10257 */
@@ -10557,10 +10586,40 @@
10557 raw_printf(p->out, "Progress %u\n", p->nProgress);
10558 }
10559 return 0;
10560 }
10561 #endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10562
10563 /*
10564 ** This is the callback routine that the shell
10565 ** invokes for each row of a query result.
10566 */
@@ -10567,11 +10626,11 @@
10567 static int shell_callback(
10568 void *pArg,
10569 int nArg, /* Number of result columns */
10570 char **azArg, /* Text of each result column */
10571 char **azCol, /* Column names */
10572 int *aiType /* Column types */
10573 ){
10574 int i;
10575 ShellState *p = (ShellState*)pArg;
10576
10577 if( azArg==0 ) return 0;
@@ -10588,85 +10647,36 @@
10588 utf8_printf(p->out,"%*s = %s%s", w, azCol[i],
10589 azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
10590 }
10591 break;
10592 }
10593 case MODE_Explain:
10594 case MODE_Column: {
10595 static const int aExplainWidths[] = {4, 13, 4, 4, 4, 13, 2, 13};
10596 const int *colWidth;
10597 int showHdr;
10598 char *rowSep;
10599 int nWidth;
10600 if( p->cMode==MODE_Column ){
10601 colWidth = p->colWidth;
10602 nWidth = ArraySize(p->colWidth);
10603 showHdr = p->showHeader;
10604 rowSep = p->rowSeparator;
10605 }else{
10606 colWidth = aExplainWidths;
10607 nWidth = ArraySize(aExplainWidths);
10608 showHdr = 1;
10609 rowSep = SEP_Row;
10610 }
10611 if( p->cnt++==0 ){
10612 for(i=0; i<nArg; i++){
10613 int w, n;
10614 if( i<nWidth ){
10615 w = colWidth[i];
10616 }else{
10617 w = 0;
10618 }
10619 if( w==0 ){
10620 w = strlenChar(azCol[i] ? azCol[i] : "");
10621 if( w<10 ) w = 10;
10622 n = strlenChar(azArg && azArg[i] ? azArg[i] : p->nullValue);
10623 if( w<n ) w = n;
10624 }
10625 if( i<ArraySize(p->actualWidth) ){
10626 p->actualWidth[i] = w;
10627 }
10628 if( showHdr ){
10629 utf8_width_print(p->out, w, azCol[i]);
10630 utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : " ");
10631 }
10632 }
10633 if( showHdr ){
10634 for(i=0; i<nArg; i++){
10635 int w;
10636 if( i<ArraySize(p->actualWidth) ){
10637 w = p->actualWidth[i];
10638 if( w<0 ) w = -w;
10639 }else{
10640 w = 10;
10641 }
10642 utf8_printf(p->out,"%-*.*s%s",w,w,
10643 "----------------------------------------------------------"
10644 "----------------------------------------------------------",
10645 i==nArg-1 ? rowSep : " ");
10646 }
10647 }
10648 }
10649 if( azArg==0 ) break;
10650 for(i=0; i<nArg; i++){
10651 int w;
10652 if( i<ArraySize(p->actualWidth) ){
10653 w = p->actualWidth[i];
10654 }else{
10655 w = 10;
10656 }
10657 if( p->cMode==MODE_Explain && azArg[i] && strlenChar(azArg[i])>w ){
10658 w = strlenChar(azArg[i]);
10659 }
10660 if( i==1 && p->aiIndent && p->pStmt ){
10661 if( p->iIndent<p->nIndent ){
10662 utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
10663 }
10664 p->iIndent++;
10665 }
10666 utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);
10667 utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : " ");
10668 }
10669 break;
10670 }
10671 case MODE_Semi: { /* .schema and .fullschema output */
10672 printSchemaLine(p->out, azArg[0], ";\n");
@@ -10865,23 +10875,65 @@
10865 output_quoted_escaped_string(p->out, azArg[i]);
10866 }
10867 }
10868 raw_printf(p->out,");\n");
10869 break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10870 }
10871 case MODE_Quote: {
10872 if( azArg==0 ) break;
10873 if( p->cnt==0 && p->showHeader ){
10874 for(i=0; i<nArg; i++){
10875 if( i>0 ) raw_printf(p->out, ",");
10876 output_quoted_string(p->out, azCol[i]);
10877 }
10878 raw_printf(p->out,"\n");
10879 }
10880 p->cnt++;
10881 for(i=0; i<nArg; i++){
10882 if( i>0 ) raw_printf(p->out, ",");
10883 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
10884 utf8_printf(p->out,"NULL");
10885 }else if( aiType && aiType[i]==SQLITE_TEXT ){
10886 output_quoted_string(p->out, azArg[i]);
10887 }else if( aiType && aiType[i]==SQLITE_INTEGER ){
@@ -10899,11 +10951,11 @@
10899 utf8_printf(p->out,"%s", azArg[i]);
10900 }else{
10901 output_quoted_string(p->out, azArg[i]);
10902 }
10903 }
10904 raw_printf(p->out,"\n");
10905 break;
10906 }
10907 case MODE_Ascii: {
10908 if( p->cnt++==0 && p->showHeader ){
10909 for(i=0; i<nArg; i++){
@@ -11554,19 +11606,127 @@
11554 }
11555 sqlite3_reset(pQ);
11556 }
11557 sqlite3_finalize(pQ);
11558 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11559
11560 /*
11561 ** Run a prepared statement
11562 */
11563 static void exec_prepared_stmt(
11564 ShellState *pArg, /* Pointer to ShellState */
11565 sqlite3_stmt *pStmt /* Statment to run */
11566 ){
11567 int rc;
 
 
 
 
 
 
 
 
11568
11569 /* perform the first step. this will tell us if we
11570 ** have a result set or not and how wide it is.
11571 */
11572 rc = sqlite3_step(pStmt);
@@ -11611,10 +11771,15 @@
11611 rc = sqlite3_step(pStmt);
11612 }
11613 }
11614 } while( SQLITE_ROW == rc );
11615 sqlite3_free(pData);
 
 
 
 
 
11616 }
11617 }
11618 }
11619
11620 #ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -16883,19 +17048,28 @@
16883 }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
16884 p->mode = MODE_Insert;
16885 set_table_name(p, nArg>=3 ? azArg[2] : "table");
16886 }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){
16887 p->mode = MODE_Quote;
 
 
16888 }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
16889 p->mode = MODE_Ascii;
16890 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
16891 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
 
 
 
 
 
 
16892 }else if( nArg==1 ){
16893 raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
16894 }else{
16895 raw_printf(stderr, "Error: mode should be one of: "
16896 "ascii column csv html insert line list quote tabs tcl\n");
 
16897 rc = 1;
16898 }
16899 p->cMode = p->mode;
16900 }else
16901
@@ -17992,11 +18166,11 @@
17992 utf8_printf(p->out,"%12.12s: ", "rowseparator");
17993 output_c_string(p->out, p->rowSeparator);
17994 raw_printf(p->out, "\n");
17995 utf8_printf(p->out, "%12.12s: %s\n","stats", azBool[p->statsOn!=0]);
17996 utf8_printf(p->out, "%12.12s: ", "width");
17997 for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
17998 raw_printf(p->out, "%d ", p->colWidth[i]);
17999 }
18000 raw_printf(p->out, "\n");
18001 utf8_printf(p->out, "%12.12s: %s\n", "filename",
18002 p->zDbFilename ? p->zDbFilename : "");
@@ -18541,11 +18715,15 @@
18541 #endif
18542
18543 if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
18544 int j;
18545 assert( nArg<=ArraySize(azArg) );
18546 for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
 
 
 
 
18547 p->colWidth[j-1] = (int)integerValue(azArg[j]);
18548 }
18549 }else
18550
18551 {
@@ -18901,13 +19079,15 @@
18901 " -heap SIZE Size of heap for memsys3 or memsys5\n"
18902 #endif
18903 " -help show this message\n"
18904 " -html set output mode to HTML\n"
18905 " -interactive force interactive I/O\n"
 
18906 " -line set output mode to 'line'\n"
18907 " -list set output mode to 'list'\n"
18908 " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
 
18909 #if defined(SQLITE_ENABLE_DESERIALIZE)
18910 " -maxsize N maximum size for a --deserialize database\n"
18911 #endif
18912 " -memtrace trace all memory allocations and deallocations\n"
18913 " -mmap N default mmap size set to N\n"
@@ -18923,10 +19103,11 @@
18923 " -separator SEP set output column separator. Default: '|'\n"
18924 #ifdef SQLITE_ENABLE_SORTER_REFERENCES
18925 " -sorterref SIZE sorter references threshold size\n"
18926 #endif
18927 " -stats print memory stats before each finalize\n"
 
18928 " -version show SQLite version\n"
18929 " -vfs NAME use NAME as the default VFS\n"
18930 #ifdef SQLITE_ENABLE_VFSTRACE
18931 " -vfstrace enable tracing of all VFS calls\n"
18932 #endif
@@ -19324,10 +19505,16 @@
19324 data.mode = MODE_Quote;
19325 }else if( strcmp(z,"-line")==0 ){
19326 data.mode = MODE_Line;
19327 }else if( strcmp(z,"-column")==0 ){
19328 data.mode = MODE_Column;
 
 
 
 
 
 
19329 }else if( strcmp(z,"-csv")==0 ){
19330 data.mode = MODE_Csv;
19331 memcpy(data.colSeparator,",",2);
19332 #ifdef SQLITE_HAVE_ZLIB
19333 }else if( strcmp(z,"-zip")==0 ){
@@ -19541,10 +19728,11 @@
19541 clearTempFile(&data);
19542 #if !SQLITE_SHELL_IS_UTF8
19543 for(i=0; i<argcToFree; i++) free(argvToFree[i]);
19544 free(argvToFree);
19545 #endif
 
19546 /* Clear the global data structure so that valgrind will detect memory
19547 ** leaks */
19548 memset(&data, 0, sizeof(data));
19549 return rc;
19550 }
19551
--- src/shell.c
+++ src/shell.c
@@ -9700,22 +9700,10 @@
9700 char **azFilter; /* Array of xFilter rejection GLOB patterns */
9701 sqlite3_session *p; /* The open session */
9702 };
9703 #endif
9704
 
 
 
 
 
 
 
 
 
 
 
 
9705 typedef struct ExpertInfo ExpertInfo;
9706 struct ExpertInfo {
9707 sqlite3expert *pExpert;
9708 int bVerbose;
9709 };
@@ -9781,12 +9769,13 @@
9769 char zTestcase[30]; /* Name of current test case */
9770 char colSeparator[20]; /* Column separator character for several modes */
9771 char rowSeparator[20]; /* Row separator character for MODE_Ascii */
9772 char colSepPrior[20]; /* Saved column separator */
9773 char rowSepPrior[20]; /* Saved row separator */
9774 int *colWidth; /* Requested width of each column in columnar modes */
9775 int *actualWidth; /* Actual width of each column */
9776 int nWidth; /* Number of slots in colWidth[] and actualWidth[] */
9777 char nullValue[20]; /* The text to print when a NULL comes back from
9778 ** the database */
9779 char outfile[FILENAME_MAX]; /* Filename for *out */
9780 const char *zDbFilename; /* name of the database file */
9781 char *zFreeOnClose; /* Filename to free when closing */
@@ -9867,10 +9856,13 @@
9856 #define MODE_Csv 8 /* Quote strings, numbers are plain */
9857 #define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */
9858 #define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */
9859 #define MODE_Pretty 11 /* Pretty-print schemas */
9860 #define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */
9861 #define MODE_Json 13 /* Output JSON */
9862 #define MODE_Markdown 14 /* Markdown formatting */
9863 #define MODE_Table 15 /* MySQL-style table formatting */
9864
9865 static const char *modeDescr[] = {
9866 "line",
9867 "column",
9868 "list",
@@ -9881,11 +9873,14 @@
9873 "tcl",
9874 "csv",
9875 "explain",
9876 "ascii",
9877 "prettyprint",
9878 "eqp",
9879 "json",
9880 "markdown",
9881 "table"
9882 };
9883
9884 /*
9885 ** These are the column/row/line separators used by the various
9886 ** import/export modes.
@@ -10248,10 +10243,44 @@
10243 fputc(c, out);
10244 }
10245 }
10246 fputc('"', out);
10247 }
10248
10249 /*
10250 ** Output the given string as a quoted according to JSON quoting rules.
10251 */
10252 static void output_json_string(FILE *out, const char *z, int n){
10253 unsigned int c;
10254 if( n<0 ) n = (int)strlen(z);
10255 fputc('"', out);
10256 while( n-- ){
10257 c = *(z++);
10258 if( c=='\\' || c=='"' ){
10259 fputc('\\', out);
10260 fputc(c, out);
10261 }else if( c<=0x1f ){
10262 fputc('\\', out);
10263 if( c=='\b' ){
10264 fputc('b', out);
10265 }else if( c=='\f' ){
10266 fputc('f', out);
10267 }else if( c=='\n' ){
10268 fputc('n', out);
10269 }else if( c=='\r' ){
10270 fputc('r', out);
10271 }else if( c=='\t' ){
10272 fputc('t', out);
10273 }else{
10274 raw_printf(out, "u%04x",c);
10275 }
10276 }else{
10277 fputc(c, out);
10278 }
10279 }
10280 fputc('"', out);
10281 }
10282
10283 /*
10284 ** Output the given string with characters that are special to
10285 ** HTML escaped.
10286 */
@@ -10557,10 +10586,40 @@
10586 raw_printf(p->out, "Progress %u\n", p->nProgress);
10587 }
10588 return 0;
10589 }
10590 #endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
10591
10592 /*
10593 ** Print N dashes
10594 */
10595 static void print_dashes(FILE *out, int N){
10596 const char zDash[] = "--------------------------------------------------";
10597 const int nDash = sizeof(zDash) - 1;
10598 while( N>nDash ){
10599 fputs(zDash, out);
10600 N -= nDash;
10601 }
10602 raw_printf(out, "%.*s", N, zDash);
10603 }
10604
10605 /*
10606 ** Print a markdown or table-style row separator
10607 */
10608 static void print_row_separator(
10609 ShellState *p,
10610 int nArg,
10611 const char *zSep
10612 ){
10613 int i;
10614 for(i=0; i<nArg; i++){
10615 fputs(zSep, p->out);
10616 print_dashes(p->out, p->actualWidth[i]+2);
10617 }
10618 fputs(zSep, p->out);
10619 fputs("\n", p->out);
10620 }
10621
10622 /*
10623 ** This is the callback routine that the shell
10624 ** invokes for each row of a query result.
10625 */
@@ -10567,11 +10626,11 @@
10626 static int shell_callback(
10627 void *pArg,
10628 int nArg, /* Number of result columns */
10629 char **azArg, /* Text of each result column */
10630 char **azCol, /* Column names */
10631 int *aiType /* Column types. Might be NULL */
10632 ){
10633 int i;
10634 ShellState *p = (ShellState*)pArg;
10635
10636 if( azArg==0 ) return 0;
@@ -10588,85 +10647,36 @@
10647 utf8_printf(p->out,"%*s = %s%s", w, azCol[i],
10648 azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
10649 }
10650 break;
10651 }
10652 case MODE_Explain: {
10653 static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13};
10654 if( nArg>ArraySize(aExplainWidth) ){
10655 nArg = ArraySize(aExplainWidth);
 
 
 
 
 
 
 
 
 
 
 
 
 
10656 }
10657 if( p->cnt++==0 ){
10658 for(i=0; i<nArg; i++){
10659 int w = aExplainWidth[i];
10660 utf8_width_print(p->out, w, azCol[i]);
10661 fputs(i==nArg-1 ? "\n" : " ", p->out);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10662 }
10663 }
10664 if( azArg==0 ) break;
10665 for(i=0; i<nArg; i++){
10666 int w = aExplainWidth[i];
10667 if( azArg[i] && strlenChar(azArg[i])>w ){
 
 
 
 
 
10668 w = strlenChar(azArg[i]);
10669 }
10670 if( i==1 && p->aiIndent && p->pStmt ){
10671 if( p->iIndent<p->nIndent ){
10672 utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
10673 }
10674 p->iIndent++;
10675 }
10676 utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);
10677 fputs(i==nArg-1 ? "\n" : " ", p->out);
10678 }
10679 break;
10680 }
10681 case MODE_Semi: { /* .schema and .fullschema output */
10682 printSchemaLine(p->out, azArg[0], ";\n");
@@ -10865,23 +10875,65 @@
10875 output_quoted_escaped_string(p->out, azArg[i]);
10876 }
10877 }
10878 raw_printf(p->out,");\n");
10879 break;
10880 }
10881 case MODE_Json: {
10882 if( azArg==0 ) break;
10883 if( p->cnt==0 ){
10884 fputs("[{", p->out);
10885 }else{
10886 fputs(",\n{", p->out);
10887 }
10888 p->cnt++;
10889 for(i=0; i<nArg; i++){
10890 output_json_string(p->out, azCol[i], -1);
10891 putc(':', p->out);
10892 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
10893 fputs("null",p->out);
10894 }else if( aiType && aiType[i]==SQLITE_FLOAT ){
10895 char z[50];
10896 double r = sqlite3_column_double(p->pStmt, i);
10897 sqlite3_uint64 ur;
10898 memcpy(&ur,&r,sizeof(r));
10899 if( ur==0x7ff0000000000000LL ){
10900 raw_printf(p->out, "1e999");
10901 }else if( ur==0xfff0000000000000LL ){
10902 raw_printf(p->out, "-1e999");
10903 }else{
10904 sqlite3_snprintf(50,z,"%!.20g", r);
10905 raw_printf(p->out, "%s", z);
10906 }
10907 }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
10908 const void *pBlob = sqlite3_column_blob(p->pStmt, i);
10909 int nBlob = sqlite3_column_bytes(p->pStmt, i);
10910 output_json_string(p->out, pBlob, nBlob);
10911 }else if( aiType && aiType[i]==SQLITE_TEXT ){
10912 output_json_string(p->out, azArg[i], -1);
10913 }else{
10914 utf8_printf(p->out,"%s", azArg[i]);
10915 }
10916 if( i<nArg-1 ){
10917 putc(',', p->out);
10918 }
10919 }
10920 putc('}', p->out);
10921 break;
10922 }
10923 case MODE_Quote: {
10924 if( azArg==0 ) break;
10925 if( p->cnt==0 && p->showHeader ){
10926 for(i=0; i<nArg; i++){
10927 if( i>0 ) fputs(p->colSeparator, p->out);
10928 output_quoted_string(p->out, azCol[i]);
10929 }
10930 fputs(p->rowSeparator, p->out);
10931 }
10932 p->cnt++;
10933 for(i=0; i<nArg; i++){
10934 if( i>0 ) fputs(p->colSeparator, p->out);
10935 if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
10936 utf8_printf(p->out,"NULL");
10937 }else if( aiType && aiType[i]==SQLITE_TEXT ){
10938 output_quoted_string(p->out, azArg[i]);
10939 }else if( aiType && aiType[i]==SQLITE_INTEGER ){
@@ -10899,11 +10951,11 @@
10951 utf8_printf(p->out,"%s", azArg[i]);
10952 }else{
10953 output_quoted_string(p->out, azArg[i]);
10954 }
10955 }
10956 fputs(p->rowSeparator, p->out);
10957 break;
10958 }
10959 case MODE_Ascii: {
10960 if( p->cnt++==0 && p->showHeader ){
10961 for(i=0; i<nArg; i++){
@@ -11554,19 +11606,127 @@
11606 }
11607 sqlite3_reset(pQ);
11608 }
11609 sqlite3_finalize(pQ);
11610 }
11611
11612 /*
11613 ** Run a prepared statement and output the result in one of the
11614 ** table-oriented formats: MODE_Column, MODE_Markdown, or MODE_Table.
11615 **
11616 ** This is different from ordinary exec_prepared_stmt() in that
11617 ** it has to run the entire query and gather the results into memory
11618 ** first, in order to determine column widths, before providing
11619 ** any output.
11620 */
11621 static void exec_prepared_stmt_columnar(
11622 ShellState *p, /* Pointer to ShellState */
11623 sqlite3_stmt *pStmt /* Statment to run */
11624 ){
11625 int nRow = 0;
11626 int nColumn = 0;
11627 char **azData = 0;
11628 char *zMsg = 0;
11629 const char *z;
11630 int rc;
11631 int i, j, nTotal, w, n;
11632 const char *colSep;
11633 const char *rowSep;
11634
11635 rc = sqlite3_get_table(p->db, sqlite3_sql(pStmt),
11636 &azData, &nRow, &nColumn, &zMsg);
11637 if( rc ){
11638 utf8_printf(p->out, "ERROR: %s\n", zMsg);
11639 sqlite3_free(zMsg);
11640 sqlite3_free_table(azData);
11641 return;
11642 }
11643 if( nColumn>p->nWidth ){
11644 p->colWidth = realloc(p->colWidth, nColumn*2*sizeof(int));
11645 if( p->colWidth==0 ) shell_out_of_memory();
11646 for(i=p->nWidth; i<nColumn; i++) p->colWidth[i] = 0;
11647 p->nWidth = nColumn;
11648 p->actualWidth = &p->colWidth[nColumn];
11649 }
11650 memset(p->actualWidth, 0, nColumn*sizeof(int));
11651 for(i=0; i<nColumn; i++){
11652 w = p->colWidth[i];
11653 if( w<0 ) w = -w;
11654 p->actualWidth[i] = w;
11655 }
11656 nTotal = nColumn*(nRow+1);
11657 for(i=0; i<nTotal; i++){
11658 z = azData[i];
11659 if( z==0 ) z = p->nullValue;
11660 n = strlenChar(z);
11661 j = i%nColumn;
11662 if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
11663 }
11664 if( p->cMode==MODE_Column ){
11665 colSep = " ";
11666 rowSep = "\n";
11667 if( p->showHeader ){
11668 for(i=0; i<nColumn; i++){
11669 w = p->actualWidth[i];
11670 if( p->colWidth[i]<0 ) w = -w;
11671 utf8_width_print(p->out, w, azData[i]);
11672 fputs(i==nColumn-1?"\n":" ", p->out);
11673 }
11674 for(i=0; i<nColumn; i++){
11675 print_dashes(p->out, p->actualWidth[i]);
11676 fputs(i==nColumn-1?"\n":" ", p->out);
11677 }
11678 }
11679 }else{
11680 colSep = " | ";
11681 rowSep = " |\n";
11682 if( p->cMode==MODE_Table ) print_row_separator(p, nColumn, "+");
11683 fputs("| ", p->out);
11684 for(i=0; i<nColumn; i++){
11685 w = p->actualWidth[i];
11686 n = strlenChar(azData[i]);
11687 utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
11688 fputs(i==nColumn-1?" |\n":" | ", p->out);
11689 }
11690 print_row_separator(p, nColumn, p->cMode==MODE_Table ? "+" : "|");
11691 }
11692 for(i=nColumn, j=0; i<nTotal; i++, j++){
11693 if( j==0 && p->cMode!=MODE_Column ) fputs("| ", p->out);
11694 z = azData[i];
11695 if( z==0 ) z = p->nullValue;
11696 w = p->actualWidth[j];
11697 if( p->colWidth[j]<0 ) w = -w;
11698 utf8_width_print(p->out, w, z);
11699 if( j==nColumn-1 ){
11700 fputs(rowSep, p->out);
11701 j = -1;
11702 }else{
11703 fputs(colSep, p->out);
11704 }
11705 }
11706 if( p->cMode==MODE_Table ){
11707 print_row_separator(p, nColumn, "+");
11708 }
11709 sqlite3_free_table(azData);
11710 }
11711
11712 /*
11713 ** Run a prepared statement
11714 */
11715 static void exec_prepared_stmt(
11716 ShellState *pArg, /* Pointer to ShellState */
11717 sqlite3_stmt *pStmt /* Statment to run */
11718 ){
11719 int rc;
11720
11721 if( pArg->cMode==MODE_Column
11722 || pArg->cMode==MODE_Table
11723 || pArg->cMode==MODE_Markdown
11724 ){
11725 exec_prepared_stmt_columnar(pArg, pStmt);
11726 return;
11727 }
11728
11729 /* perform the first step. this will tell us if we
11730 ** have a result set or not and how wide it is.
11731 */
11732 rc = sqlite3_step(pStmt);
@@ -11611,10 +11771,15 @@
11771 rc = sqlite3_step(pStmt);
11772 }
11773 }
11774 } while( SQLITE_ROW == rc );
11775 sqlite3_free(pData);
11776 if( pArg->cMode==MODE_Table ){
11777 print_row_separator(pArg, nCol, "+");
11778 }else if( pArg->cMode==MODE_Json ){
11779 fputs("]\n", pArg->out);
11780 }
11781 }
11782 }
11783 }
11784
11785 #ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -16883,19 +17048,28 @@
17048 }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
17049 p->mode = MODE_Insert;
17050 set_table_name(p, nArg>=3 ? azArg[2] : "table");
17051 }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){
17052 p->mode = MODE_Quote;
17053 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
17054 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
17055 }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
17056 p->mode = MODE_Ascii;
17057 sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
17058 sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
17059 }else if( c2=='m' && strncmp(azArg[1],"markdown",n2)==0 ){
17060 p->mode = MODE_Markdown;
17061 }else if( c2=='t' && strncmp(azArg[1],"table",n2)==0 ){
17062 p->mode = MODE_Table;
17063 }else if( c2=='j' && strncmp(azArg[1],"json",n2)==0 ){
17064 p->mode = MODE_Json;
17065 }else if( nArg==1 ){
17066 raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
17067 }else{
17068 raw_printf(stderr, "Error: mode should be one of: "
17069 "ascii column csv html insert json line list markdown "
17070 "quote table tabs tcl\n");
17071 rc = 1;
17072 }
17073 p->cMode = p->mode;
17074 }else
17075
@@ -17992,11 +18166,11 @@
18166 utf8_printf(p->out,"%12.12s: ", "rowseparator");
18167 output_c_string(p->out, p->rowSeparator);
18168 raw_printf(p->out, "\n");
18169 utf8_printf(p->out, "%12.12s: %s\n","stats", azBool[p->statsOn!=0]);
18170 utf8_printf(p->out, "%12.12s: ", "width");
18171 for (i=0;i<p->nWidth;i++) {
18172 raw_printf(p->out, "%d ", p->colWidth[i]);
18173 }
18174 raw_printf(p->out, "\n");
18175 utf8_printf(p->out, "%12.12s: %s\n", "filename",
18176 p->zDbFilename ? p->zDbFilename : "");
@@ -18541,11 +18715,15 @@
18715 #endif
18716
18717 if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
18718 int j;
18719 assert( nArg<=ArraySize(azArg) );
18720 p->nWidth = nArg-1;
18721 p->colWidth = realloc(p->colWidth, p->nWidth*sizeof(int)*2);
18722 if( p->colWidth==0 && p->nWidth>0 ) shell_out_of_memory();
18723 if( p->nWidth ) p->actualWidth = &p->colWidth[p->nWidth];
18724 for(j=1; j<nArg; j++){
18725 p->colWidth[j-1] = (int)integerValue(azArg[j]);
18726 }
18727 }else
18728
18729 {
@@ -18901,13 +19079,15 @@
19079 " -heap SIZE Size of heap for memsys3 or memsys5\n"
19080 #endif
19081 " -help show this message\n"
19082 " -html set output mode to HTML\n"
19083 " -interactive force interactive I/O\n"
19084 " -json set output mode to 'json'\n"
19085 " -line set output mode to 'line'\n"
19086 " -list set output mode to 'list'\n"
19087 " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
19088 " -markdown set output mode to 'markdown'\n"
19089 #if defined(SQLITE_ENABLE_DESERIALIZE)
19090 " -maxsize N maximum size for a --deserialize database\n"
19091 #endif
19092 " -memtrace trace all memory allocations and deallocations\n"
19093 " -mmap N default mmap size set to N\n"
@@ -18923,10 +19103,11 @@
19103 " -separator SEP set output column separator. Default: '|'\n"
19104 #ifdef SQLITE_ENABLE_SORTER_REFERENCES
19105 " -sorterref SIZE sorter references threshold size\n"
19106 #endif
19107 " -stats print memory stats before each finalize\n"
19108 " -table set output mode to 'table'\n"
19109 " -version show SQLite version\n"
19110 " -vfs NAME use NAME as the default VFS\n"
19111 #ifdef SQLITE_ENABLE_VFSTRACE
19112 " -vfstrace enable tracing of all VFS calls\n"
19113 #endif
@@ -19324,10 +19505,16 @@
19505 data.mode = MODE_Quote;
19506 }else if( strcmp(z,"-line")==0 ){
19507 data.mode = MODE_Line;
19508 }else if( strcmp(z,"-column")==0 ){
19509 data.mode = MODE_Column;
19510 }else if( strcmp(z,"-json")==0 ){
19511 data.mode = MODE_Json;
19512 }else if( strcmp(z,"-markdown")==0 ){
19513 data.mode = MODE_Markdown;
19514 }else if( strcmp(z,"-table")==0 ){
19515 data.mode = MODE_Table;
19516 }else if( strcmp(z,"-csv")==0 ){
19517 data.mode = MODE_Csv;
19518 memcpy(data.colSeparator,",",2);
19519 #ifdef SQLITE_HAVE_ZLIB
19520 }else if( strcmp(z,"-zip")==0 ){
@@ -19541,10 +19728,11 @@
19728 clearTempFile(&data);
19729 #if !SQLITE_SHELL_IS_UTF8
19730 for(i=0; i<argcToFree; i++) free(argvToFree[i]);
19731 free(argvToFree);
19732 #endif
19733 free(data.colWidth);
19734 /* Clear the global data structure so that valgrind will detect memory
19735 ** leaks */
19736 memset(&data, 0, sizeof(data));
19737 return rc;
19738 }
19739
+1 -1
--- src/smtp.c
+++ src/smtp.c
@@ -1528,11 +1528,11 @@
15281528
"TOP", "USER", "UIDL",
15291529
};
15301530
int i;
15311531
pop3_print(pLog, "+OK");
15321532
for(i=0; i<sizeof(azCap)/sizeof(azCap[0]); i++){
1533
- pop3_print(pLog, azCap[i]);
1533
+ pop3_print(pLog, "%s", azCap[i]);
15341534
}
15351535
pop3_print(pLog, ".");
15361536
continue;
15371537
}
15381538
if( inAuth ){
15391539
--- src/smtp.c
+++ src/smtp.c
@@ -1528,11 +1528,11 @@
1528 "TOP", "USER", "UIDL",
1529 };
1530 int i;
1531 pop3_print(pLog, "+OK");
1532 for(i=0; i<sizeof(azCap)/sizeof(azCap[0]); i++){
1533 pop3_print(pLog, azCap[i]);
1534 }
1535 pop3_print(pLog, ".");
1536 continue;
1537 }
1538 if( inAuth ){
1539
--- src/smtp.c
+++ src/smtp.c
@@ -1528,11 +1528,11 @@
1528 "TOP", "USER", "UIDL",
1529 };
1530 int i;
1531 pop3_print(pLog, "+OK");
1532 for(i=0; i<sizeof(azCap)/sizeof(azCap[0]); i++){
1533 pop3_print(pLog, "%s", azCap[i]);
1534 }
1535 pop3_print(pLog, ".");
1536 continue;
1537 }
1538 if( inAuth ){
1539
+54 -34
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
11
/******************************************************************************
22
** This file is an amalgamation of many separate C source files from SQLite
3
-** version 3.32.1. By combining all the individual C code files into this
3
+** version 3.33.0. By combining all the individual C code files into this
44
** single large file, the entire code can be compiled as a single translation
55
** unit. This allows many compilers to do optimizations that would not be
66
** possible if the files were compiled separately. Performance improvements
77
** of 5% or more are commonly seen when SQLite is compiled as a single
88
** translation unit.
@@ -1160,13 +1160,13 @@
11601160
**
11611161
** See also: [sqlite3_libversion()],
11621162
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
11631163
** [sqlite_version()] and [sqlite_source_id()].
11641164
*/
1165
-#define SQLITE_VERSION "3.32.1"
1166
-#define SQLITE_VERSION_NUMBER 3032001
1167
-#define SQLITE_SOURCE_ID "2020-05-25 16:19:56 0c1fcf4711a2e66c813aed38cf41cd3e2123ee8eb6db98118086764c4ba83350"
1165
+#define SQLITE_VERSION "3.33.0"
1166
+#define SQLITE_VERSION_NUMBER 3033000
1167
+#define SQLITE_SOURCE_ID "2020-05-29 16:15:58 4e1db8e9a9ee370a398f13fd8546a520111b8cfb84460389535b5bc5bd9f4f82"
11681168
11691169
/*
11701170
** CAPI3REF: Run-Time Library Version Numbers
11711171
** KEYWORDS: sqlite3_version sqlite3_sourceid
11721172
**
@@ -38285,11 +38285,14 @@
3828538285
** 2. Write lock (ofst==0).
3828638286
** 3. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK).
3828738287
**
3828838288
** In other words, if this is a blocking lock, none of the locks that
3828938289
** occur later in the above list than the lock being obtained may be
38290
- ** held. */
38290
+ ** held.
38291
+ **
38292
+ ** It is not permitted to block on the RECOVER lock.
38293
+ */
3829138294
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
3829238295
assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
3829338296
(ofst!=2) /* not RECOVER */
3829438297
&& (ofst!=1 || (p->exclMask|p->sharedMask)==0)
3829538298
&& (ofst!=0 || (p->exclMask|p->sharedMask)<3)
@@ -80835,11 +80838,15 @@
8083580838
** if the VDBE has just been set to run but has not actually executed any
8083680839
** instructions yet, leave the main database error information unchanged.
8083780840
*/
8083880841
if( p->pc>=0 ){
8083980842
vdbeInvokeSqllog(p);
80840
- sqlite3VdbeTransferError(p);
80843
+ if( db->pErr || p->zErrMsg ){
80844
+ sqlite3VdbeTransferError(p);
80845
+ }else{
80846
+ db->errCode = p->rc;
80847
+ }
8084180848
if( p->runOnlyOnce ) p->expired = 1;
8084280849
}else if( p->rc && p->expired ){
8084380850
/* The expired flag was set on the VDBE before the first call
8084480851
** to sqlite3_step(). For consistency (since sqlite3_step() was
8084580852
** called), set the database error in this case as well.
@@ -80855,12 +80862,14 @@
8085580862
if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 );
8085680863
if( p->aMem ){
8085780864
for(i=0; i<p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined );
8085880865
}
8085980866
#endif
80860
- sqlite3DbFree(db, p->zErrMsg);
80861
- p->zErrMsg = 0;
80867
+ if( p->zErrMsg ){
80868
+ sqlite3DbFree(db, p->zErrMsg);
80869
+ p->zErrMsg = 0;
80870
+ }
8086280871
p->pResultSet = 0;
8086380872
#ifdef SQLITE_DEBUG
8086480873
p->nWrite = 0;
8086580874
#endif
8086680875
@@ -102032,11 +102041,11 @@
102032102041
** satisfy the query. This is preferable to generating a new
102033102042
** ephemeral table. */
102034102043
if( pParse->nErr==0 && (p = isCandidateForInOpt(pX))!=0 ){
102035102044
sqlite3 *db = pParse->db; /* Database connection */
102036102045
Table *pTab; /* Table <table>. */
102037
- i16 iDb; /* Database idx for pTab */
102046
+ int iDb; /* Database idx for pTab */
102038102047
ExprList *pEList = p->pEList;
102039102048
int nExpr = pEList->nExpr;
102040102049
102041102050
assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */
102042102051
assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */
@@ -102043,10 +102052,11 @@
102043102052
assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */
102044102053
pTab = p->pSrc->a[0].pTab;
102045102054
102046102055
/* Code an OP_Transaction and OP_TableLock for <table>. */
102047102056
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
102057
+ assert( iDb>=0 && iDb<SQLITE_MAX_ATTACHED );
102048102058
sqlite3CodeVerifySchema(pParse, iDb);
102049102059
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
102050102060
102051102061
assert(v); /* sqlite3GetVdbe() has always been previously called */
102052102062
if( nExpr==1 && pEList->a[0].pExpr->iColumn<0 ){
@@ -103276,14 +103286,11 @@
103276103286
int r1, r2; /* Various register numbers */
103277103287
Expr tempX; /* Temporary expression node */
103278103288
int p5 = 0;
103279103289
103280103290
assert( target>0 && target<=pParse->nMem );
103281
- if( v==0 ){
103282
- assert( pParse->db->mallocFailed );
103283
- return 0;
103284
- }
103291
+ assert( v!=0 );
103285103292
103286103293
expr_code_doover:
103287103294
if( pExpr==0 ){
103288103295
op = TK_NULL;
103289103296
}else{
@@ -104109,13 +104116,14 @@
104109104116
SQLITE_PRIVATE void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
104110104117
int inReg;
104111104118
104112104119
assert( pExpr==0 || !ExprHasVVAProperty(pExpr,EP_Immutable) );
104113104120
assert( target>0 && target<=pParse->nMem );
104114
- inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
104115104121
assert( pParse->pVdbe!=0 || pParse->db->mallocFailed );
104116
- if( inReg!=target && pParse->pVdbe ){
104122
+ if( pParse->pVdbe==0 ) return;
104123
+ inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
104124
+ if( inReg!=target ){
104117104125
u8 op;
104118104126
if( ExprHasProperty(pExpr,EP_Subquery) ){
104119104127
op = OP_Copy;
104120104128
}else{
104121104129
op = OP_SCopy;
@@ -114091,25 +114099,37 @@
114091114099
** Apart from that, we have little to go on besides intuition as to
114092114100
** how aiRowEst[] should be initialized. The numbers generated here
114093114101
** are based on typical values found in actual indices.
114094114102
*/
114095114103
SQLITE_PRIVATE void sqlite3DefaultRowEst(Index *pIdx){
114096
- /* 10, 9, 8, 7, 6 */
114097
- LogEst aVal[] = { 33, 32, 30, 28, 26 };
114104
+ /* 10, 9, 8, 7, 6 */
114105
+ static const LogEst aVal[] = { 33, 32, 30, 28, 26 };
114098114106
LogEst *a = pIdx->aiRowLogEst;
114107
+ LogEst x;
114099114108
int nCopy = MIN(ArraySize(aVal), pIdx->nKeyCol);
114100114109
int i;
114101114110
114102114111
/* Indexes with default row estimates should not have stat1 data */
114103114112
assert( !pIdx->hasStat1 );
114104114113
114105114114
/* Set the first entry (number of rows in the index) to the estimated
114106114115
** number of rows in the table, or half the number of rows in the table
114107
- ** for a partial index. But do not let the estimate drop below 10. */
114108
- a[0] = pIdx->pTable->nRowLogEst;
114109
- if( pIdx->pPartIdxWhere!=0 ) a[0] -= 10; assert( 10==sqlite3LogEst(2) );
114110
- if( a[0]<33 ) a[0] = 33; assert( 33==sqlite3LogEst(10) );
114116
+ ** for a partial index.
114117
+ **
114118
+ ** 2020-05-27: If some of the stat data is coming from the sqlite_stat1
114119
+ ** table but other parts we are having to guess at, then do not let the
114120
+ ** estimated number of rows in the table be less than 1000 (LogEst 99).
114121
+ ** Failure to do this can cause the indexes for which we do not have
114122
+ ** stat1 data to be ignored by the query planner. tag-20200527-1
114123
+ */
114124
+ x = pIdx->pTable->nRowLogEst;
114125
+ assert( 99==sqlite3LogEst(1000) );
114126
+ if( x<99 ){
114127
+ pIdx->pTable->nRowLogEst = x = 99;
114128
+ }
114129
+ if( pIdx->pPartIdxWhere!=0 ) x -= 10; assert( 10==sqlite3LogEst(2) );
114130
+ a[0] = x;
114111114131
114112114132
/* Estimate that a[1] is 10, a[2] is 9, a[3] is 8, a[4] is 7, a[5] is
114113114133
** 6 and each subsequent value (if any) is 5. */
114114114134
memcpy(&a[1], aVal, nCopy*sizeof(LogEst));
114115114135
for(i=nCopy+1; i<=pIdx->nKeyCol; i++){
@@ -128405,21 +128425,22 @@
128405128425
**
128406128426
** If the same database is attached more than once, the first
128407128427
** attached database is returned.
128408128428
*/
128409128429
SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
128410
- int i = -1000000;
128430
+ int i = -32768;
128411128431
128412
- /* If pSchema is NULL, then return -1000000. This happens when code in
128432
+ /* If pSchema is NULL, then return -32768. This happens when code in
128413128433
** expr.c is trying to resolve a reference to a transient table (i.e. one
128414128434
** created by a sub-select). In this case the return value of this
128415128435
** function should never be used.
128416128436
**
128417
- ** We return -1000000 instead of the more usual -1 simply because using
128418
- ** -1000000 as the incorrect index into db->aDb[] is much
128437
+ ** We return -32768 instead of the more usual -1 simply because using
128438
+ ** -32768 as the incorrect index into db->aDb[] is much
128419128439
** more likely to cause a segfault than -1 (of course there are assert()
128420
- ** statements too, but it never hurts to play the odds).
128440
+ ** statements too, but it never hurts to play the odds) and
128441
+ ** -32768 will still fit into a 16-bit signed integer.
128421128442
*/
128422128443
assert( sqlite3_mutex_held(db->mutex) );
128423128444
if( pSchema ){
128424128445
for(i=0; 1; i++){
128425128446
assert( i<db->nDb );
@@ -128970,13 +128991,13 @@
128970128991
Expr *pHaving, /* the HAVING clause */
128971128992
ExprList *pOrderBy, /* the ORDER BY clause */
128972128993
u32 selFlags, /* Flag parameters, such as SF_Distinct */
128973128994
Expr *pLimit /* LIMIT value. NULL means not used */
128974128995
){
128975
- Select *pNew;
128996
+ Select *pNew, *pAllocated;
128976128997
Select standin;
128977
- pNew = sqlite3DbMallocRawNN(pParse->db, sizeof(*pNew) );
128998
+ pAllocated = pNew = sqlite3DbMallocRawNN(pParse->db, sizeof(*pNew) );
128978128999
if( pNew==0 ){
128979129000
assert( pParse->db->mallocFailed );
128980129001
pNew = &standin;
128981129002
}
128982129003
if( pEList==0 ){
@@ -129006,16 +129027,15 @@
129006129027
pNew->pWin = 0;
129007129028
pNew->pWinDefn = 0;
129008129029
#endif
129009129030
if( pParse->db->mallocFailed ) {
129010129031
clearSelect(pParse->db, pNew, pNew!=&standin);
129011
- pNew = 0;
129032
+ pAllocated = 0;
129012129033
}else{
129013129034
assert( pNew->pSrc!=0 || pParse->nErr>0 );
129014129035
}
129015
- assert( pNew!=&standin );
129016
- return pNew;
129036
+ return pAllocated;
129017129037
}
129018129038
129019129039
129020129040
/*
129021129041
** Delete the given Select structure and all of its substructures.
@@ -224820,11 +224840,11 @@
224820224840
int nArg, /* Number of args */
224821224841
sqlite3_value **apUnused /* Function arguments */
224822224842
){
224823224843
assert( nArg==0 );
224824224844
UNUSED_PARAM2(nArg, apUnused);
224825
- sqlite3_result_text(pCtx, "fts5: 2020-05-25 16:19:56 0c1fcf4711a2e66c813aed38cf41cd3e2123ee8eb6db98118086764c4ba83350", -1, SQLITE_TRANSIENT);
224845
+ sqlite3_result_text(pCtx, "fts5: 2020-05-29 16:15:58 4e1db8e9a9ee370a398f13fd8546a520111b8cfb84460389535b5bc5bd9f4f82", -1, SQLITE_TRANSIENT);
224826224846
}
224827224847
224828224848
/*
224829224849
** Return true if zName is the extension on one of the shadow tables used
224830224850
** by this module.
@@ -229603,12 +229623,12 @@
229603229623
}
229604229624
#endif /* SQLITE_CORE */
229605229625
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
229606229626
229607229627
/************** End of stmt.c ************************************************/
229608
-#if __LINE__!=229608
229628
+#if __LINE__!=229628
229609229629
#undef SQLITE_SOURCE_ID
229610
-#define SQLITE_SOURCE_ID "2020-05-25 16:19:56 0c1fcf4711a2e66c813aed38cf41cd3e2123ee8eb6db98118086764c4ba8alt2"
229630
+#define SQLITE_SOURCE_ID "2020-05-29 16:15:58 4e1db8e9a9ee370a398f13fd8546a520111b8cfb84460389535b5bc5bd9falt2"
229611229631
#endif
229612229632
/* Return the source-id for this library */
229613229633
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
229614229634
/************************** End of sqlite3.c ******************************/
229615229635
--- 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.32.1. 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.
@@ -1160,13 +1160,13 @@
1160 **
1161 ** See also: [sqlite3_libversion()],
1162 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
1163 ** [sqlite_version()] and [sqlite_source_id()].
1164 */
1165 #define SQLITE_VERSION "3.32.1"
1166 #define SQLITE_VERSION_NUMBER 3032001
1167 #define SQLITE_SOURCE_ID "2020-05-25 16:19:56 0c1fcf4711a2e66c813aed38cf41cd3e2123ee8eb6db98118086764c4ba83350"
1168
1169 /*
1170 ** CAPI3REF: Run-Time Library Version Numbers
1171 ** KEYWORDS: sqlite3_version sqlite3_sourceid
1172 **
@@ -38285,11 +38285,14 @@
38285 ** 2. Write lock (ofst==0).
38286 ** 3. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK).
38287 **
38288 ** In other words, if this is a blocking lock, none of the locks that
38289 ** occur later in the above list than the lock being obtained may be
38290 ** held. */
 
 
 
38291 #ifdef SQLITE_ENABLE_SETLK_TIMEOUT
38292 assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
38293 (ofst!=2) /* not RECOVER */
38294 && (ofst!=1 || (p->exclMask|p->sharedMask)==0)
38295 && (ofst!=0 || (p->exclMask|p->sharedMask)<3)
@@ -80835,11 +80838,15 @@
80835 ** if the VDBE has just been set to run but has not actually executed any
80836 ** instructions yet, leave the main database error information unchanged.
80837 */
80838 if( p->pc>=0 ){
80839 vdbeInvokeSqllog(p);
80840 sqlite3VdbeTransferError(p);
 
 
 
 
80841 if( p->runOnlyOnce ) p->expired = 1;
80842 }else if( p->rc && p->expired ){
80843 /* The expired flag was set on the VDBE before the first call
80844 ** to sqlite3_step(). For consistency (since sqlite3_step() was
80845 ** called), set the database error in this case as well.
@@ -80855,12 +80862,14 @@
80855 if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 );
80856 if( p->aMem ){
80857 for(i=0; i<p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined );
80858 }
80859 #endif
80860 sqlite3DbFree(db, p->zErrMsg);
80861 p->zErrMsg = 0;
 
 
80862 p->pResultSet = 0;
80863 #ifdef SQLITE_DEBUG
80864 p->nWrite = 0;
80865 #endif
80866
@@ -102032,11 +102041,11 @@
102032 ** satisfy the query. This is preferable to generating a new
102033 ** ephemeral table. */
102034 if( pParse->nErr==0 && (p = isCandidateForInOpt(pX))!=0 ){
102035 sqlite3 *db = pParse->db; /* Database connection */
102036 Table *pTab; /* Table <table>. */
102037 i16 iDb; /* Database idx for pTab */
102038 ExprList *pEList = p->pEList;
102039 int nExpr = pEList->nExpr;
102040
102041 assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */
102042 assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */
@@ -102043,10 +102052,11 @@
102043 assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */
102044 pTab = p->pSrc->a[0].pTab;
102045
102046 /* Code an OP_Transaction and OP_TableLock for <table>. */
102047 iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
 
102048 sqlite3CodeVerifySchema(pParse, iDb);
102049 sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
102050
102051 assert(v); /* sqlite3GetVdbe() has always been previously called */
102052 if( nExpr==1 && pEList->a[0].pExpr->iColumn<0 ){
@@ -103276,14 +103286,11 @@
103276 int r1, r2; /* Various register numbers */
103277 Expr tempX; /* Temporary expression node */
103278 int p5 = 0;
103279
103280 assert( target>0 && target<=pParse->nMem );
103281 if( v==0 ){
103282 assert( pParse->db->mallocFailed );
103283 return 0;
103284 }
103285
103286 expr_code_doover:
103287 if( pExpr==0 ){
103288 op = TK_NULL;
103289 }else{
@@ -104109,13 +104116,14 @@
104109 SQLITE_PRIVATE void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
104110 int inReg;
104111
104112 assert( pExpr==0 || !ExprHasVVAProperty(pExpr,EP_Immutable) );
104113 assert( target>0 && target<=pParse->nMem );
104114 inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
104115 assert( pParse->pVdbe!=0 || pParse->db->mallocFailed );
104116 if( inReg!=target && pParse->pVdbe ){
 
 
104117 u8 op;
104118 if( ExprHasProperty(pExpr,EP_Subquery) ){
104119 op = OP_Copy;
104120 }else{
104121 op = OP_SCopy;
@@ -114091,25 +114099,37 @@
114091 ** Apart from that, we have little to go on besides intuition as to
114092 ** how aiRowEst[] should be initialized. The numbers generated here
114093 ** are based on typical values found in actual indices.
114094 */
114095 SQLITE_PRIVATE void sqlite3DefaultRowEst(Index *pIdx){
114096 /* 10, 9, 8, 7, 6 */
114097 LogEst aVal[] = { 33, 32, 30, 28, 26 };
114098 LogEst *a = pIdx->aiRowLogEst;
 
114099 int nCopy = MIN(ArraySize(aVal), pIdx->nKeyCol);
114100 int i;
114101
114102 /* Indexes with default row estimates should not have stat1 data */
114103 assert( !pIdx->hasStat1 );
114104
114105 /* Set the first entry (number of rows in the index) to the estimated
114106 ** number of rows in the table, or half the number of rows in the table
114107 ** for a partial index. But do not let the estimate drop below 10. */
114108 a[0] = pIdx->pTable->nRowLogEst;
114109 if( pIdx->pPartIdxWhere!=0 ) a[0] -= 10; assert( 10==sqlite3LogEst(2) );
114110 if( a[0]<33 ) a[0] = 33; assert( 33==sqlite3LogEst(10) );
 
 
 
 
 
 
 
 
 
 
 
114111
114112 /* Estimate that a[1] is 10, a[2] is 9, a[3] is 8, a[4] is 7, a[5] is
114113 ** 6 and each subsequent value (if any) is 5. */
114114 memcpy(&a[1], aVal, nCopy*sizeof(LogEst));
114115 for(i=nCopy+1; i<=pIdx->nKeyCol; i++){
@@ -128405,21 +128425,22 @@
128405 **
128406 ** If the same database is attached more than once, the first
128407 ** attached database is returned.
128408 */
128409 SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
128410 int i = -1000000;
128411
128412 /* If pSchema is NULL, then return -1000000. This happens when code in
128413 ** expr.c is trying to resolve a reference to a transient table (i.e. one
128414 ** created by a sub-select). In this case the return value of this
128415 ** function should never be used.
128416 **
128417 ** We return -1000000 instead of the more usual -1 simply because using
128418 ** -1000000 as the incorrect index into db->aDb[] is much
128419 ** more likely to cause a segfault than -1 (of course there are assert()
128420 ** statements too, but it never hurts to play the odds).
 
128421 */
128422 assert( sqlite3_mutex_held(db->mutex) );
128423 if( pSchema ){
128424 for(i=0; 1; i++){
128425 assert( i<db->nDb );
@@ -128970,13 +128991,13 @@
128970 Expr *pHaving, /* the HAVING clause */
128971 ExprList *pOrderBy, /* the ORDER BY clause */
128972 u32 selFlags, /* Flag parameters, such as SF_Distinct */
128973 Expr *pLimit /* LIMIT value. NULL means not used */
128974 ){
128975 Select *pNew;
128976 Select standin;
128977 pNew = sqlite3DbMallocRawNN(pParse->db, sizeof(*pNew) );
128978 if( pNew==0 ){
128979 assert( pParse->db->mallocFailed );
128980 pNew = &standin;
128981 }
128982 if( pEList==0 ){
@@ -129006,16 +129027,15 @@
129006 pNew->pWin = 0;
129007 pNew->pWinDefn = 0;
129008 #endif
129009 if( pParse->db->mallocFailed ) {
129010 clearSelect(pParse->db, pNew, pNew!=&standin);
129011 pNew = 0;
129012 }else{
129013 assert( pNew->pSrc!=0 || pParse->nErr>0 );
129014 }
129015 assert( pNew!=&standin );
129016 return pNew;
129017 }
129018
129019
129020 /*
129021 ** Delete the given Select structure and all of its substructures.
@@ -224820,11 +224840,11 @@
224820 int nArg, /* Number of args */
224821 sqlite3_value **apUnused /* Function arguments */
224822 ){
224823 assert( nArg==0 );
224824 UNUSED_PARAM2(nArg, apUnused);
224825 sqlite3_result_text(pCtx, "fts5: 2020-05-25 16:19:56 0c1fcf4711a2e66c813aed38cf41cd3e2123ee8eb6db98118086764c4ba83350", -1, SQLITE_TRANSIENT);
224826 }
224827
224828 /*
224829 ** Return true if zName is the extension on one of the shadow tables used
224830 ** by this module.
@@ -229603,12 +229623,12 @@
229603 }
229604 #endif /* SQLITE_CORE */
229605 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
229606
229607 /************** End of stmt.c ************************************************/
229608 #if __LINE__!=229608
229609 #undef SQLITE_SOURCE_ID
229610 #define SQLITE_SOURCE_ID "2020-05-25 16:19:56 0c1fcf4711a2e66c813aed38cf41cd3e2123ee8eb6db98118086764c4ba8alt2"
229611 #endif
229612 /* Return the source-id for this library */
229613 SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
229614 /************************** End of sqlite3.c ******************************/
229615
--- 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.33.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.
@@ -1160,13 +1160,13 @@
1160 **
1161 ** See also: [sqlite3_libversion()],
1162 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
1163 ** [sqlite_version()] and [sqlite_source_id()].
1164 */
1165 #define SQLITE_VERSION "3.33.0"
1166 #define SQLITE_VERSION_NUMBER 3033000
1167 #define SQLITE_SOURCE_ID "2020-05-29 16:15:58 4e1db8e9a9ee370a398f13fd8546a520111b8cfb84460389535b5bc5bd9f4f82"
1168
1169 /*
1170 ** CAPI3REF: Run-Time Library Version Numbers
1171 ** KEYWORDS: sqlite3_version sqlite3_sourceid
1172 **
@@ -38285,11 +38285,14 @@
38285 ** 2. Write lock (ofst==0).
38286 ** 3. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK).
38287 **
38288 ** In other words, if this is a blocking lock, none of the locks that
38289 ** occur later in the above list than the lock being obtained may be
38290 ** held.
38291 **
38292 ** It is not permitted to block on the RECOVER lock.
38293 */
38294 #ifdef SQLITE_ENABLE_SETLK_TIMEOUT
38295 assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
38296 (ofst!=2) /* not RECOVER */
38297 && (ofst!=1 || (p->exclMask|p->sharedMask)==0)
38298 && (ofst!=0 || (p->exclMask|p->sharedMask)<3)
@@ -80835,11 +80838,15 @@
80838 ** if the VDBE has just been set to run but has not actually executed any
80839 ** instructions yet, leave the main database error information unchanged.
80840 */
80841 if( p->pc>=0 ){
80842 vdbeInvokeSqllog(p);
80843 if( db->pErr || p->zErrMsg ){
80844 sqlite3VdbeTransferError(p);
80845 }else{
80846 db->errCode = p->rc;
80847 }
80848 if( p->runOnlyOnce ) p->expired = 1;
80849 }else if( p->rc && p->expired ){
80850 /* The expired flag was set on the VDBE before the first call
80851 ** to sqlite3_step(). For consistency (since sqlite3_step() was
80852 ** called), set the database error in this case as well.
@@ -80855,12 +80862,14 @@
80862 if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 );
80863 if( p->aMem ){
80864 for(i=0; i<p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined );
80865 }
80866 #endif
80867 if( p->zErrMsg ){
80868 sqlite3DbFree(db, p->zErrMsg);
80869 p->zErrMsg = 0;
80870 }
80871 p->pResultSet = 0;
80872 #ifdef SQLITE_DEBUG
80873 p->nWrite = 0;
80874 #endif
80875
@@ -102032,11 +102041,11 @@
102041 ** satisfy the query. This is preferable to generating a new
102042 ** ephemeral table. */
102043 if( pParse->nErr==0 && (p = isCandidateForInOpt(pX))!=0 ){
102044 sqlite3 *db = pParse->db; /* Database connection */
102045 Table *pTab; /* Table <table>. */
102046 int iDb; /* Database idx for pTab */
102047 ExprList *pEList = p->pEList;
102048 int nExpr = pEList->nExpr;
102049
102050 assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */
102051 assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */
@@ -102043,10 +102052,11 @@
102052 assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */
102053 pTab = p->pSrc->a[0].pTab;
102054
102055 /* Code an OP_Transaction and OP_TableLock for <table>. */
102056 iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
102057 assert( iDb>=0 && iDb<SQLITE_MAX_ATTACHED );
102058 sqlite3CodeVerifySchema(pParse, iDb);
102059 sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
102060
102061 assert(v); /* sqlite3GetVdbe() has always been previously called */
102062 if( nExpr==1 && pEList->a[0].pExpr->iColumn<0 ){
@@ -103276,14 +103286,11 @@
103286 int r1, r2; /* Various register numbers */
103287 Expr tempX; /* Temporary expression node */
103288 int p5 = 0;
103289
103290 assert( target>0 && target<=pParse->nMem );
103291 assert( v!=0 );
 
 
 
103292
103293 expr_code_doover:
103294 if( pExpr==0 ){
103295 op = TK_NULL;
103296 }else{
@@ -104109,13 +104116,14 @@
104116 SQLITE_PRIVATE void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
104117 int inReg;
104118
104119 assert( pExpr==0 || !ExprHasVVAProperty(pExpr,EP_Immutable) );
104120 assert( target>0 && target<=pParse->nMem );
 
104121 assert( pParse->pVdbe!=0 || pParse->db->mallocFailed );
104122 if( pParse->pVdbe==0 ) return;
104123 inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
104124 if( inReg!=target ){
104125 u8 op;
104126 if( ExprHasProperty(pExpr,EP_Subquery) ){
104127 op = OP_Copy;
104128 }else{
104129 op = OP_SCopy;
@@ -114091,25 +114099,37 @@
114099 ** Apart from that, we have little to go on besides intuition as to
114100 ** how aiRowEst[] should be initialized. The numbers generated here
114101 ** are based on typical values found in actual indices.
114102 */
114103 SQLITE_PRIVATE void sqlite3DefaultRowEst(Index *pIdx){
114104 /* 10, 9, 8, 7, 6 */
114105 static const LogEst aVal[] = { 33, 32, 30, 28, 26 };
114106 LogEst *a = pIdx->aiRowLogEst;
114107 LogEst x;
114108 int nCopy = MIN(ArraySize(aVal), pIdx->nKeyCol);
114109 int i;
114110
114111 /* Indexes with default row estimates should not have stat1 data */
114112 assert( !pIdx->hasStat1 );
114113
114114 /* Set the first entry (number of rows in the index) to the estimated
114115 ** number of rows in the table, or half the number of rows in the table
114116 ** for a partial index.
114117 **
114118 ** 2020-05-27: If some of the stat data is coming from the sqlite_stat1
114119 ** table but other parts we are having to guess at, then do not let the
114120 ** estimated number of rows in the table be less than 1000 (LogEst 99).
114121 ** Failure to do this can cause the indexes for which we do not have
114122 ** stat1 data to be ignored by the query planner. tag-20200527-1
114123 */
114124 x = pIdx->pTable->nRowLogEst;
114125 assert( 99==sqlite3LogEst(1000) );
114126 if( x<99 ){
114127 pIdx->pTable->nRowLogEst = x = 99;
114128 }
114129 if( pIdx->pPartIdxWhere!=0 ) x -= 10; assert( 10==sqlite3LogEst(2) );
114130 a[0] = x;
114131
114132 /* Estimate that a[1] is 10, a[2] is 9, a[3] is 8, a[4] is 7, a[5] is
114133 ** 6 and each subsequent value (if any) is 5. */
114134 memcpy(&a[1], aVal, nCopy*sizeof(LogEst));
114135 for(i=nCopy+1; i<=pIdx->nKeyCol; i++){
@@ -128405,21 +128425,22 @@
128425 **
128426 ** If the same database is attached more than once, the first
128427 ** attached database is returned.
128428 */
128429 SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
128430 int i = -32768;
128431
128432 /* If pSchema is NULL, then return -32768. This happens when code in
128433 ** expr.c is trying to resolve a reference to a transient table (i.e. one
128434 ** created by a sub-select). In this case the return value of this
128435 ** function should never be used.
128436 **
128437 ** We return -32768 instead of the more usual -1 simply because using
128438 ** -32768 as the incorrect index into db->aDb[] is much
128439 ** more likely to cause a segfault than -1 (of course there are assert()
128440 ** statements too, but it never hurts to play the odds) and
128441 ** -32768 will still fit into a 16-bit signed integer.
128442 */
128443 assert( sqlite3_mutex_held(db->mutex) );
128444 if( pSchema ){
128445 for(i=0; 1; i++){
128446 assert( i<db->nDb );
@@ -128970,13 +128991,13 @@
128991 Expr *pHaving, /* the HAVING clause */
128992 ExprList *pOrderBy, /* the ORDER BY clause */
128993 u32 selFlags, /* Flag parameters, such as SF_Distinct */
128994 Expr *pLimit /* LIMIT value. NULL means not used */
128995 ){
128996 Select *pNew, *pAllocated;
128997 Select standin;
128998 pAllocated = pNew = sqlite3DbMallocRawNN(pParse->db, sizeof(*pNew) );
128999 if( pNew==0 ){
129000 assert( pParse->db->mallocFailed );
129001 pNew = &standin;
129002 }
129003 if( pEList==0 ){
@@ -129006,16 +129027,15 @@
129027 pNew->pWin = 0;
129028 pNew->pWinDefn = 0;
129029 #endif
129030 if( pParse->db->mallocFailed ) {
129031 clearSelect(pParse->db, pNew, pNew!=&standin);
129032 pAllocated = 0;
129033 }else{
129034 assert( pNew->pSrc!=0 || pParse->nErr>0 );
129035 }
129036 return pAllocated;
 
129037 }
129038
129039
129040 /*
129041 ** Delete the given Select structure and all of its substructures.
@@ -224820,11 +224840,11 @@
224840 int nArg, /* Number of args */
224841 sqlite3_value **apUnused /* Function arguments */
224842 ){
224843 assert( nArg==0 );
224844 UNUSED_PARAM2(nArg, apUnused);
224845 sqlite3_result_text(pCtx, "fts5: 2020-05-29 16:15:58 4e1db8e9a9ee370a398f13fd8546a520111b8cfb84460389535b5bc5bd9f4f82", -1, SQLITE_TRANSIENT);
224846 }
224847
224848 /*
224849 ** Return true if zName is the extension on one of the shadow tables used
224850 ** by this module.
@@ -229603,12 +229623,12 @@
229623 }
229624 #endif /* SQLITE_CORE */
229625 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
229626
229627 /************** End of stmt.c ************************************************/
229628 #if __LINE__!=229628
229629 #undef SQLITE_SOURCE_ID
229630 #define SQLITE_SOURCE_ID "2020-05-29 16:15:58 4e1db8e9a9ee370a398f13fd8546a520111b8cfb84460389535b5bc5bd9falt2"
229631 #endif
229632 /* Return the source-id for this library */
229633 SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
229634 /************************** End of sqlite3.c ******************************/
229635
+3 -3
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -121,13 +121,13 @@
121121
**
122122
** See also: [sqlite3_libversion()],
123123
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
124124
** [sqlite_version()] and [sqlite_source_id()].
125125
*/
126
-#define SQLITE_VERSION "3.32.1"
127
-#define SQLITE_VERSION_NUMBER 3032001
128
-#define SQLITE_SOURCE_ID "2020-05-25 16:19:56 0c1fcf4711a2e66c813aed38cf41cd3e2123ee8eb6db98118086764c4ba83350"
126
+#define SQLITE_VERSION "3.33.0"
127
+#define SQLITE_VERSION_NUMBER 3033000
128
+#define SQLITE_SOURCE_ID "2020-05-29 16:15:58 4e1db8e9a9ee370a398f13fd8546a520111b8cfb84460389535b5bc5bd9f4f82"
129129
130130
/*
131131
** CAPI3REF: Run-Time Library Version Numbers
132132
** KEYWORDS: sqlite3_version sqlite3_sourceid
133133
**
134134
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -121,13 +121,13 @@
121 **
122 ** See also: [sqlite3_libversion()],
123 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
124 ** [sqlite_version()] and [sqlite_source_id()].
125 */
126 #define SQLITE_VERSION "3.32.1"
127 #define SQLITE_VERSION_NUMBER 3032001
128 #define SQLITE_SOURCE_ID "2020-05-25 16:19:56 0c1fcf4711a2e66c813aed38cf41cd3e2123ee8eb6db98118086764c4ba83350"
129
130 /*
131 ** CAPI3REF: Run-Time Library Version Numbers
132 ** KEYWORDS: sqlite3_version sqlite3_sourceid
133 **
134
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -121,13 +121,13 @@
121 **
122 ** See also: [sqlite3_libversion()],
123 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
124 ** [sqlite_version()] and [sqlite_source_id()].
125 */
126 #define SQLITE_VERSION "3.33.0"
127 #define SQLITE_VERSION_NUMBER 3033000
128 #define SQLITE_SOURCE_ID "2020-05-29 16:15:58 4e1db8e9a9ee370a398f13fd8546a520111b8cfb84460389535b5bc5bd9f4f82"
129
130 /*
131 ** CAPI3REF: Run-Time Library Version Numbers
132 ** KEYWORDS: sqlite3_version sqlite3_sourceid
133 **
134
+1 -1
--- src/tar.c
+++ src/tar.c
@@ -466,11 +466,11 @@
466466
**
467467
** zDir is a "synthetic" subdirectory which all files get
468468
** added to as part of the tarball. It may be 0 or an empty string, in
469469
** which case it is ignored. The intention is to create a tarball which
470470
** politely expands into a subdir instead of filling your current dir
471
-** with source files. For example, pass a UUID or "ProjectName".
471
+** with source files. For example, pass an artifact hash or "ProjectName".
472472
**
473473
*/
474474
void tarball_of_checkin(
475475
int rid, /* The RID of the checkin from which to form a tarball */
476476
Blob *pTar, /* Write the tarball into this blob */
477477
--- src/tar.c
+++ src/tar.c
@@ -466,11 +466,11 @@
466 **
467 ** zDir is a "synthetic" subdirectory which all files get
468 ** added to as part of the tarball. It may be 0 or an empty string, in
469 ** which case it is ignored. The intention is to create a tarball which
470 ** politely expands into a subdir instead of filling your current dir
471 ** with source files. For example, pass a UUID or "ProjectName".
472 **
473 */
474 void tarball_of_checkin(
475 int rid, /* The RID of the checkin from which to form a tarball */
476 Blob *pTar, /* Write the tarball into this blob */
477
--- src/tar.c
+++ src/tar.c
@@ -466,11 +466,11 @@
466 **
467 ** zDir is a "synthetic" subdirectory which all files get
468 ** added to as part of the tarball. It may be 0 or an empty string, in
469 ** which case it is ignored. The intention is to create a tarball which
470 ** politely expands into a subdir instead of filling your current dir
471 ** with source files. For example, pass an artifact hash or "ProjectName".
472 **
473 */
474 void tarball_of_checkin(
475 int rid, /* The RID of the checkin from which to form a tarball */
476 Blob *pTar, /* Write the tarball into this blob */
477
+8 -8
--- src/timeline.c
+++ src/timeline.c
@@ -48,15 +48,15 @@
4848
}
4949
5050
/*
5151
** Generate a hyperlink to a version.
5252
*/
53
-void hyperlink_to_uuid(const char *zUuid){
53
+void hyperlink_to_version(const char *zVerHash){
5454
if( g.perm.Hyperlink ){
55
- @ %z(chref("timelineHistLink","%R/info/%!S",zUuid))[%S(zUuid)]</a>
55
+ @ %z(chref("timelineHistLink","%R/info/%!S",zVerHash))[%S(zVerHash)]</a>
5656
}else{
57
- @ <span class="timelineHistDsp">[%S(zUuid)]</span>
57
+ @ <span class="timelineHistDsp">[%S(zVerHash)]</span>
5858
}
5959
}
6060
6161
/*
6262
** Generate a hyperlink to a date & time.
@@ -101,11 +101,11 @@
101101
#define TIMELINE_FCHANGES 0x0000020 /* Detail file changes */
102102
#define TIMELINE_BRCOLOR 0x0000040 /* Background color by branch name */
103103
#define TIMELINE_UCOLOR 0x0000080 /* Background color by user */
104104
#define TIMELINE_FRENAMES 0x0000100 /* Detail only file name changes */
105105
#define TIMELINE_UNHIDE 0x0000200 /* Unhide check-ins with "hidden" tag */
106
-#define TIMELINE_SHOWRID 0x0000400 /* Show RID values in addition to UUIDs */
106
+#define TIMELINE_SHOWRID 0x0000400 /* Show RID values in addition to hashes */
107107
#define TIMELINE_BISECT 0x0000800 /* Show supplimental bisect information */
108108
#define TIMELINE_COMPACT 0x0001000 /* Use the "compact" view style */
109109
#define TIMELINE_VERBOSE 0x0002000 /* Use the "detailed" view style */
110110
#define TIMELINE_MODERN 0x0004000 /* Use the "modern" view style */
111111
#define TIMELINE_COLUMNAR 0x0008000 /* Use the "columns" view style */
@@ -229,11 +229,11 @@
229229
/*
230230
** Output a timeline in the web format given a query. The query
231231
** should return these columns:
232232
**
233233
** 0. rid
234
-** 1. UUID
234
+** 1. artifact hash
235235
** 2. Date/Time
236236
** 3. Comment string
237237
** 4. User
238238
** 5. True if is a leaf
239239
** 6. background color
@@ -533,11 +533,11 @@
533533
}else{
534534
@ <span class='timeline%s(zStyle)Comment'>
535535
}
536536
if( (tmFlags & TIMELINE_CLASSIC)!=0 ){
537537
if( zType[0]=='c' ){
538
- hyperlink_to_uuid(zUuid);
538
+ hyperlink_to_version(zUuid);
539539
if( isLeaf ){
540540
if( db_exists("SELECT 1 FROM tagxref"
541541
" WHERE rid=%d AND tagid=%d AND tagtype>0",
542542
rid, TAG_CLOSED) ){
543543
@ <span class="timelineLeaf">Closed-Leaf:</span>
@@ -546,11 +546,11 @@
546546
}
547547
}
548548
}else if( zType[0]=='e' && tagid ){
549549
hyperlink_to_event_tagid(tagid<0?-tagid:tagid);
550550
}else if( (tmFlags & TIMELINE_ARTID)!=0 ){
551
- hyperlink_to_uuid(zUuid);
551
+ hyperlink_to_version(zUuid);
552552
}
553553
if( tmFlags & TIMELINE_SHOWRID ){
554554
int srcId = delta_source_rid(rid);
555555
if( srcId ){
556556
@ (%d(rid)&larr;%d(srcId))
@@ -3024,11 +3024,11 @@
30243024
z = db_text(0, "SELECT date(%Q,'-1 day')", zToday);
30253025
style_submenu_element("Yesterday", "%R/thisdayinhistory?today=%t", z);
30263026
z = db_text(0, "SELECT date(%Q,'+1 day')", zToday);
30273027
style_submenu_element("Tomorrow", "%R/thisdayinhistory?today=%t", z);
30283028
zStartOfProject = db_text(0,
3029
- "SELECT datetime(min(mtime),toLocal()) FROM event;"
3029
+ "SELECT datetime(min(mtime),toLocal(),'startofday') FROM event;"
30303030
);
30313031
timeline_temp_table();
30323032
db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/");
30333033
for(i=0; i<sizeof(aYearsAgo)/sizeof(aYearsAgo[0]); i++){
30343034
int iAgo = aYearsAgo[i];
30353035
--- src/timeline.c
+++ src/timeline.c
@@ -48,15 +48,15 @@
48 }
49
50 /*
51 ** Generate a hyperlink to a version.
52 */
53 void hyperlink_to_uuid(const char *zUuid){
54 if( g.perm.Hyperlink ){
55 @ %z(chref("timelineHistLink","%R/info/%!S",zUuid))[%S(zUuid)]</a>
56 }else{
57 @ <span class="timelineHistDsp">[%S(zUuid)]</span>
58 }
59 }
60
61 /*
62 ** Generate a hyperlink to a date & time.
@@ -101,11 +101,11 @@
101 #define TIMELINE_FCHANGES 0x0000020 /* Detail file changes */
102 #define TIMELINE_BRCOLOR 0x0000040 /* Background color by branch name */
103 #define TIMELINE_UCOLOR 0x0000080 /* Background color by user */
104 #define TIMELINE_FRENAMES 0x0000100 /* Detail only file name changes */
105 #define TIMELINE_UNHIDE 0x0000200 /* Unhide check-ins with "hidden" tag */
106 #define TIMELINE_SHOWRID 0x0000400 /* Show RID values in addition to UUIDs */
107 #define TIMELINE_BISECT 0x0000800 /* Show supplimental bisect information */
108 #define TIMELINE_COMPACT 0x0001000 /* Use the "compact" view style */
109 #define TIMELINE_VERBOSE 0x0002000 /* Use the "detailed" view style */
110 #define TIMELINE_MODERN 0x0004000 /* Use the "modern" view style */
111 #define TIMELINE_COLUMNAR 0x0008000 /* Use the "columns" view style */
@@ -229,11 +229,11 @@
229 /*
230 ** Output a timeline in the web format given a query. The query
231 ** should return these columns:
232 **
233 ** 0. rid
234 ** 1. UUID
235 ** 2. Date/Time
236 ** 3. Comment string
237 ** 4. User
238 ** 5. True if is a leaf
239 ** 6. background color
@@ -533,11 +533,11 @@
533 }else{
534 @ <span class='timeline%s(zStyle)Comment'>
535 }
536 if( (tmFlags & TIMELINE_CLASSIC)!=0 ){
537 if( zType[0]=='c' ){
538 hyperlink_to_uuid(zUuid);
539 if( isLeaf ){
540 if( db_exists("SELECT 1 FROM tagxref"
541 " WHERE rid=%d AND tagid=%d AND tagtype>0",
542 rid, TAG_CLOSED) ){
543 @ <span class="timelineLeaf">Closed-Leaf:</span>
@@ -546,11 +546,11 @@
546 }
547 }
548 }else if( zType[0]=='e' && tagid ){
549 hyperlink_to_event_tagid(tagid<0?-tagid:tagid);
550 }else if( (tmFlags & TIMELINE_ARTID)!=0 ){
551 hyperlink_to_uuid(zUuid);
552 }
553 if( tmFlags & TIMELINE_SHOWRID ){
554 int srcId = delta_source_rid(rid);
555 if( srcId ){
556 @ (%d(rid)&larr;%d(srcId))
@@ -3024,11 +3024,11 @@
3024 z = db_text(0, "SELECT date(%Q,'-1 day')", zToday);
3025 style_submenu_element("Yesterday", "%R/thisdayinhistory?today=%t", z);
3026 z = db_text(0, "SELECT date(%Q,'+1 day')", zToday);
3027 style_submenu_element("Tomorrow", "%R/thisdayinhistory?today=%t", z);
3028 zStartOfProject = db_text(0,
3029 "SELECT datetime(min(mtime),toLocal()) FROM event;"
3030 );
3031 timeline_temp_table();
3032 db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/");
3033 for(i=0; i<sizeof(aYearsAgo)/sizeof(aYearsAgo[0]); i++){
3034 int iAgo = aYearsAgo[i];
3035
--- src/timeline.c
+++ src/timeline.c
@@ -48,15 +48,15 @@
48 }
49
50 /*
51 ** Generate a hyperlink to a version.
52 */
53 void hyperlink_to_version(const char *zVerHash){
54 if( g.perm.Hyperlink ){
55 @ %z(chref("timelineHistLink","%R/info/%!S",zVerHash))[%S(zVerHash)]</a>
56 }else{
57 @ <span class="timelineHistDsp">[%S(zVerHash)]</span>
58 }
59 }
60
61 /*
62 ** Generate a hyperlink to a date & time.
@@ -101,11 +101,11 @@
101 #define TIMELINE_FCHANGES 0x0000020 /* Detail file changes */
102 #define TIMELINE_BRCOLOR 0x0000040 /* Background color by branch name */
103 #define TIMELINE_UCOLOR 0x0000080 /* Background color by user */
104 #define TIMELINE_FRENAMES 0x0000100 /* Detail only file name changes */
105 #define TIMELINE_UNHIDE 0x0000200 /* Unhide check-ins with "hidden" tag */
106 #define TIMELINE_SHOWRID 0x0000400 /* Show RID values in addition to hashes */
107 #define TIMELINE_BISECT 0x0000800 /* Show supplimental bisect information */
108 #define TIMELINE_COMPACT 0x0001000 /* Use the "compact" view style */
109 #define TIMELINE_VERBOSE 0x0002000 /* Use the "detailed" view style */
110 #define TIMELINE_MODERN 0x0004000 /* Use the "modern" view style */
111 #define TIMELINE_COLUMNAR 0x0008000 /* Use the "columns" view style */
@@ -229,11 +229,11 @@
229 /*
230 ** Output a timeline in the web format given a query. The query
231 ** should return these columns:
232 **
233 ** 0. rid
234 ** 1. artifact hash
235 ** 2. Date/Time
236 ** 3. Comment string
237 ** 4. User
238 ** 5. True if is a leaf
239 ** 6. background color
@@ -533,11 +533,11 @@
533 }else{
534 @ <span class='timeline%s(zStyle)Comment'>
535 }
536 if( (tmFlags & TIMELINE_CLASSIC)!=0 ){
537 if( zType[0]=='c' ){
538 hyperlink_to_version(zUuid);
539 if( isLeaf ){
540 if( db_exists("SELECT 1 FROM tagxref"
541 " WHERE rid=%d AND tagid=%d AND tagtype>0",
542 rid, TAG_CLOSED) ){
543 @ <span class="timelineLeaf">Closed-Leaf:</span>
@@ -546,11 +546,11 @@
546 }
547 }
548 }else if( zType[0]=='e' && tagid ){
549 hyperlink_to_event_tagid(tagid<0?-tagid:tagid);
550 }else if( (tmFlags & TIMELINE_ARTID)!=0 ){
551 hyperlink_to_version(zUuid);
552 }
553 if( tmFlags & TIMELINE_SHOWRID ){
554 int srcId = delta_source_rid(rid);
555 if( srcId ){
556 @ (%d(rid)&larr;%d(srcId))
@@ -3024,11 +3024,11 @@
3024 z = db_text(0, "SELECT date(%Q,'-1 day')", zToday);
3025 style_submenu_element("Yesterday", "%R/thisdayinhistory?today=%t", z);
3026 z = db_text(0, "SELECT date(%Q,'+1 day')", zToday);
3027 style_submenu_element("Tomorrow", "%R/thisdayinhistory?today=%t", z);
3028 zStartOfProject = db_text(0,
3029 "SELECT datetime(min(mtime),toLocal(),'startofday') FROM event;"
3030 );
3031 timeline_temp_table();
3032 db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/");
3033 for(i=0; i<sizeof(aYearsAgo)/sizeof(aYearsAgo[0]); i++){
3034 int iAgo = aYearsAgo[i];
3035
+1 -1
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -448,11 +448,11 @@
448448
);
449449
}
450450
451451
static const char zDefaultView[] =
452452
@ <table cellpadding="5">
453
-@ <tr><td class="tktDspLabel">Ticket&nbsp;UUID:</td>
453
+@ <tr><td class="tktDspLabel">Ticket&nbsp;Hash:</td>
454454
@ <th1>
455455
@ if {[info exists tkt_uuid]} {
456456
@ html "<td class='tktDspValue' colspan='3'>"
457457
@ copybtn hash-tk 0 $tkt_uuid 2
458458
@ if {[hascap s]} {
459459
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -448,11 +448,11 @@
448 );
449 }
450
451 static const char zDefaultView[] =
452 @ <table cellpadding="5">
453 @ <tr><td class="tktDspLabel">Ticket&nbsp;UUID:</td>
454 @ <th1>
455 @ if {[info exists tkt_uuid]} {
456 @ html "<td class='tktDspValue' colspan='3'>"
457 @ copybtn hash-tk 0 $tkt_uuid 2
458 @ if {[hascap s]} {
459
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -448,11 +448,11 @@
448 );
449 }
450
451 static const char zDefaultView[] =
452 @ <table cellpadding="5">
453 @ <tr><td class="tktDspLabel">Ticket&nbsp;Hash:</td>
454 @ <th1>
455 @ if {[info exists tkt_uuid]} {
456 @ html "<td class='tktDspValue' colspan='3'>"
457 @ copybtn hash-tk 0 $tkt_uuid 2
458 @ if {[hascap s]} {
459
+1 -1
--- src/util.c
+++ src/util.c
@@ -416,11 +416,11 @@
416416
417417
/*
418418
** Returns TRUE if zSym is exactly HNAME_LEN_SHA1 or HNAME_LEN_K256
419419
** bytes long and contains only lower-case ASCII hexadecimal values.
420420
*/
421
-int fossil_is_uuid(const char *zSym){
421
+int fossil_is_artifact_hash(const char *zSym){
422422
int sz = zSym ? (int)strlen(zSym) : 0;
423423
return (HNAME_LEN_SHA1==sz || HNAME_LEN_K256==sz) && validate16(zSym, sz);
424424
}
425425
426426
/*
427427
--- src/util.c
+++ src/util.c
@@ -416,11 +416,11 @@
416
417 /*
418 ** Returns TRUE if zSym is exactly HNAME_LEN_SHA1 or HNAME_LEN_K256
419 ** bytes long and contains only lower-case ASCII hexadecimal values.
420 */
421 int fossil_is_uuid(const char *zSym){
422 int sz = zSym ? (int)strlen(zSym) : 0;
423 return (HNAME_LEN_SHA1==sz || HNAME_LEN_K256==sz) && validate16(zSym, sz);
424 }
425
426 /*
427
--- src/util.c
+++ src/util.c
@@ -416,11 +416,11 @@
416
417 /*
418 ** Returns TRUE if zSym is exactly HNAME_LEN_SHA1 or HNAME_LEN_K256
419 ** bytes long and contains only lower-case ASCII hexadecimal values.
420 */
421 int fossil_is_artifact_hash(const char *zSym){
422 int sz = zSym ? (int)strlen(zSym) : 0;
423 return (HNAME_LEN_SHA1==sz || HNAME_LEN_K256==sz) && validate16(zSym, sz);
424 }
425
426 /*
427
+1 -1
--- src/zip.c
+++ src/zip.c
@@ -614,11 +614,11 @@
614614
**
615615
** zDir is a "synthetic" subdirectory which all zipped files get
616616
** added to as part of the zip file. It may be 0 or an empty string,
617617
** in which case it is ignored. The intention is to create a zip which
618618
** politely expands into a subdir instead of filling your current dir
619
-** with source files. For example, pass a UUID or "ProjectName".
619
+** with source files. For example, pass a commit hash or "ProjectName".
620620
**
621621
*/
622622
static void zip_of_checkin(
623623
int eType, /* Type of archive (ZIP or SQLAR) */
624624
int rid, /* The RID of the checkin to build the archive from */
625625
--- src/zip.c
+++ src/zip.c
@@ -614,11 +614,11 @@
614 **
615 ** zDir is a "synthetic" subdirectory which all zipped files get
616 ** added to as part of the zip file. It may be 0 or an empty string,
617 ** in which case it is ignored. The intention is to create a zip which
618 ** politely expands into a subdir instead of filling your current dir
619 ** with source files. For example, pass a UUID or "ProjectName".
620 **
621 */
622 static void zip_of_checkin(
623 int eType, /* Type of archive (ZIP or SQLAR) */
624 int rid, /* The RID of the checkin to build the archive from */
625
--- src/zip.c
+++ src/zip.c
@@ -614,11 +614,11 @@
614 **
615 ** zDir is a "synthetic" subdirectory which all zipped files get
616 ** added to as part of the zip file. It may be 0 or an empty string,
617 ** in which case it is ignored. The intention is to create a zip which
618 ** politely expands into a subdir instead of filling your current dir
619 ** with source files. For example, pass a commit hash or "ProjectName".
620 **
621 */
622 static void zip_of_checkin(
623 int eType, /* Type of archive (ZIP or SQLAR) */
624 int rid, /* The RID of the checkin to build the archive from */
625
+79 -79
--- test/amend.test
+++ test/amend.test
@@ -26,61 +26,61 @@
2626
proc manifest_comment {comment} {
2727
string map [list { } {\\s} \n {\\n} \r {\\r}] $comment
2828
}
2929
3030
proc uuid_from_commit {res var} {
31
- upvar $var UUID
32
- regexp {^New_Version: ([0-9a-f]{40})[0-9a-f]*$} $res m UUID
31
+ upvar $var HASH
32
+ regexp {^New_Version: ([0-9a-f]{40})[0-9a-f]*$} $res m HASH
3333
}
3434
3535
proc uuid_from_branch {res var} {
36
- upvar $var UUID
37
- regexp {^New branch: ([0-9a-f]{40})[0-9a-f]*$} $res m UUID
36
+ upvar $var HASH
37
+ regexp {^New branch: ([0-9a-f]{40})[0-9a-f]*$} $res m HASH
3838
}
3939
4040
proc uuid_from_checkout {var} {
4141
global RESULT
42
- upvar $var UUID
42
+ upvar $var HASH
4343
fossil status
44
- regexp {checkout:\s+([0-9a-f]{40})} $RESULT m UUID
44
+ regexp {checkout:\s+([0-9a-f]{40})[0-9a-f]*} $RESULT m HASH
4545
}
4646
4747
# Make sure we are not in an open repository and initialize new repository
4848
test_setup
4949
5050
########################################
5151
# Setup: Add file and commit #
5252
########################################
5353
54
-if {![uuid_from_checkout UUIDINIT]} {
54
+if {![uuid_from_checkout HASHINIT]} {
5555
test amend-checkout-failure false
5656
test_cleanup_then_return
5757
}
5858
write_file datafile "data"
5959
fossil add datafile
6060
fossil commit -m "c1"
61
-if {![uuid_from_commit $RESULT UUID]} {
61
+if {![uuid_from_commit $RESULT HASH]} {
6262
test amend-setup-failure false
6363
test_cleanup_then_return
6464
}
6565
6666
########################################
6767
# Test: -branch #
6868
########################################
69
-set UUIDB UUIDB
69
+set HASHB HASHB
7070
write_file datafile "data.file"
7171
fossil commit -m "c2"
72
-if {![uuid_from_commit $RESULT UUIDB]} {
72
+if {![uuid_from_commit $RESULT HASHB]} {
7373
test amend-branch.setup false
7474
}
75
-fossil amend $UUIDB -branch amended-branch
75
+fossil amend $HASHB -branch amended-branch
7676
test amend-branch-1.1 {[regexp {tags:\s+amended-branch} $RESULT]}
7777
fossil branch ls
7878
test amend-branch-1.2 {[string first "* amended-branch" $RESULT] != -1}
7979
fossil tag list
8080
test amend-branch-1.3 {[string first amended-branch $RESULT] != -1}
81
-fossil tag list --raw $UUIDB
81
+fossil tag list --raw $HASHB
8282
test amend-branch-1.4 {[string first "branch=amended-branch" $RESULT] != -1}
8383
test amend-branch-1.5 {[string first "sym-amended-branch" $RESULT] != -1}
8484
fossil timeline -n 1
8585
test amend-branch-1.6 {[string match {*Move*to*branch*amended-branch*} $RESULT]}
8686
@@ -102,84 +102,84 @@
102102
#1234 #1234
103103
1234 1234
104104
123456 #123456
105105
} {
106106
incr tc
107
- fossil amend $UUID -bgcolor $color
108
- test amend-bgcolor-1.$tc.a {[string match "*uuid:*$UUID*" $RESULT]}
109
- fossil tag list --raw $UUID
107
+ fossil amend $HASH -bgcolor $color
108
+ test amend-bgcolor-1.$tc.a {[string match "*uuid:*$HASH*" $RESULT]}
109
+ fossil tag list --raw $HASH
110110
test amend-bgcolor-1.$tc.b {[string first "bgcolor=$result" $RESULT] != -1}
111111
fossil timeline -n 1
112112
test amend-bgcolor-1.$tc.c {
113113
[string match "*Change*background*color*to*\"$result\"*" $RESULT]
114114
}
115115
if {[artifact_from_timeline $RESULT artid]} {
116116
fossil artifact $artid
117117
test amend-bgcolor-1.$tc.d {
118
- [string match "*T +bgcolor $UUID* $result*" $RESULT]
118
+ [string match "*T +bgcolor $HASH* $result*" $RESULT]
119119
}
120120
} else {
121121
if {$VERBOSE} { protOut "No artifact found in timeline output" }
122122
test amend-bgcolor-1.$tc.d false
123123
}
124124
}
125
-fossil amend $UUID -bgcolor {}
126
-test amend-bgcolor-2.1 {[string match "*uuid:*$UUID*" $RESULT]}
127
-fossil tag list --raw $UUID
125
+fossil amend $HASH -bgcolor {}
126
+test amend-bgcolor-2.1 {[string match "*uuid:*$HASH*" $RESULT]}
127
+fossil tag list --raw $HASH
128128
test amend-bgcolor-2.2 {
129129
[string first "bgcolor=" $RESULT] == -1 &&
130130
[string first "bgcolor" $RESULT] != -1
131131
}
132132
fossil timeline -n 1
133133
test amend-bgcolor-2.3 {[string match "*Cancel*background*color.*" $RESULT]}
134134
if {[artifact_from_timeline $RESULT artid]} {
135135
fossil artifact $artid
136
- test amend-bgcolor-2.4 {[string match "*T -bgcolor $UUID*" $RESULT]}
136
+ test amend-bgcolor-2.4 {[string match "*T -bgcolor $HASH*" $RESULT]}
137137
} else {
138138
if {$VERBOSE} { protOut "No artifact found in timeline output" }
139139
test amend-bgcolor-2.4 false
140140
}
141141
142142
########################################
143143
# Test: -branchcolor #
144144
########################################
145
-set UUID2 UUID2
146
-fossil branch new brclr $UUID
147
-if {![uuid_from_branch $RESULT UUID2]} {
145
+set HASH2 HASH2
146
+fossil branch new brclr $HASH
147
+if {![uuid_from_branch $RESULT HASH2]} {
148148
test amend-branchcolor.setup false
149149
}
150
-fossil update $UUID2
151
-fossil amend $UUID2 -branchcolor yellow
152
-test amend-branchcolor-1.1 {[string match "*uuid:*$UUID2*" $RESULT]}
153
-fossil tag ls --raw $UUID2
150
+fossil update $HASH2
151
+fossil amend $HASH2 -branchcolor yellow
152
+test amend-branchcolor-1.1 {[string match "*uuid:*$HASH2*" $RESULT]}
153
+fossil tag ls --raw $HASH2
154154
test amend-branchcolor-1.2 {[string first "bgcolor=yellow" $RESULT] != -1}
155155
fossil timeline -n 1
156156
test amend-branchcolor-1.3 {
157157
[string match {*Change*branch*background*color*to*"yellow".*} $RESULT]
158158
}
159159
if {[regexp {(?x)[0-9]{2}(?::[0-9]{2}){2}\s+\[([0-9a-f]+)]} $RESULT m artid]} {
160160
fossil artifact $artid
161161
test amend-branchcolor-1.4 {
162
- [string match "*T \*bgcolor $UUID2* yellow*" $RESULT]
162
+ [string match "*T \*bgcolor $HASH2* yellow*" $RESULT]
163163
}
164164
} else {
165165
if {$VERBOSE} { protOut "No artifact found in timeline output" }
166166
test amend-branchcolor-1.4 false
167167
}
168168
169
-set UUIDN UUIDN
169
+set HASHN HASHN
170170
write_file datafile "brclr"
171171
fossil commit -m "brclr"
172
-if {![uuid_from_commit $RESULT UUIDN]} {
172
+if {![uuid_from_commit $RESULT HASHN]} {
173173
test amend-branchcolor-propagating.setup false
174174
}
175175
write_file datafile "bc1"
176176
fossil commit -m "mc1"
177177
write_file datafile "bc2"
178178
fossil commit -m "mc2"
179
-fossil amend $UUIDN -branchcolor deadbe
180
-test amend-branchcolor-2.1 {[string match "*uuid:*$UUIDN*" $RESULT]}
179
+fossil amend $HASHN -branchcolor deadbe
180
+test amend-branchcolor-2.1 {[string match "*uuid:*$HASHN*" $RESULT]}
181181
fossil tag ls --raw current
182182
test amend-branchcolor-2.2 {[string first "bgcolor=#deadbe" $RESULT] != -1}
183183
fossil timeline -n 1
184184
test amend-branchcolor-2.3 {
185185
[string match {*Change*branch*background*color*to*"#deadbe".*} $RESULT]
@@ -186,13 +186,13 @@
186186
}
187187
188188
########################################
189189
# Test: -author #
190190
########################################
191
-fossil amend $UUID -author author-test
191
+fossil amend $HASH -author author-test
192192
test amend-author-1.1 {[string match {*comment:*(user:*author-test)*} $RESULT]}
193
-fossil tag ls --raw $UUID
193
+fossil tag ls --raw $HASH
194194
test amend-author-1.2 {[string first "user=author-test" $RESULT] != -1}
195195
fossil timeline -n 1
196196
test amend-author-1.3 {[string match {*Change*user*to*"author-test".*} $RESULT]}
197197
198198
########################################
@@ -200,13 +200,13 @@
200200
########################################
201201
set timestamp [clock scan yesterday]
202202
set date [clock format $timestamp -format "%Y-%m-%d" -gmt 1]
203203
set time [clock format $timestamp -format "%H:%M:%S" -gmt 1]
204204
set datetime "$date $time"
205
-fossil amend $UUIDINIT -date $datetime
206
-test amend-date-1.1 {[string match "*uuid:*$UUIDINIT*$datetime*" $RESULT]}
207
-fossil tag ls --raw $UUIDINIT
205
+fossil amend $HASHINIT -date $datetime
206
+test amend-date-1.1 {[string match "*uuid:*$HASHINIT*$datetime*" $RESULT]}
207
+fossil tag ls --raw $HASHINIT
208208
test amend-date-1.2 {[string first "date=$datetime" $RESULT] != -1}
209209
fossil timeline -n 1
210210
test amend-date-1.3 {[string match "*Timestamp*$date*$time*" $RESULT]}
211211
set badformats {
212212
"%+"
@@ -217,67 +217,67 @@
217217
}
218218
set sc 0
219219
foreach badformat $badformats {
220220
incr sc
221221
set datetime [clock format $timestamp -format $badformat -gmt 1]
222
- fossil amend $UUIDINIT -date $datetime -expectError
222
+ fossil amend $HASHINIT -date $datetime -expectError
223223
test amend-date-2.$sc {[string first "YYYY-MM-DD HH:MM:SS" $RESULT] != -1}
224224
}
225225
226226
########################################
227227
# Test: -hide #
228228
########################################
229
-set UUIDH UUIDH
229
+set HASHH HASHH
230230
fossil revert
231231
fossil update trunk
232232
fossil branch new tohide current
233
-if {![uuid_from_branch $RESULT UUIDH]} {
233
+if {![uuid_from_branch $RESULT HASHH]} {
234234
test amend-hide-setup false
235235
}
236
-fossil amend $UUIDH -hide
237
-test amend-hide-1.1 {[string match "*uuid:*$UUIDH*" $RESULT]}
238
-fossil tag ls --raw $UUIDH
236
+fossil amend $HASHH -hide
237
+test amend-hide-1.1 {[string match "*uuid:*$HASHH*" $RESULT]}
238
+fossil tag ls --raw $HASHH
239239
test amend-hide-1.2 {[string first "hidden" $RESULT] != -1}
240240
fossil timeline -n 1
241241
test amend-hide-1.3 {[string match {*Add*propagating*"hidden".*} $RESULT]}
242242
243243
########################################
244244
# Test: -close #
245245
########################################
246
-set UUIDC UUIDC
247
-fossil branch new cllf $UUID
248
-if {![uuid_from_branch $RESULT UUIDC]} {
246
+set HASHC HASHC
247
+fossil branch new cllf $HASH
248
+if {![uuid_from_branch $RESULT HASHC]} {
249249
test amend-close.setup false
250250
}
251
-fossil update $UUIDC
252
-fossil amend $UUIDC -close
253
-test amend-close-1.1.a {[string match "*uuid:*$UUIDC*" $RESULT]}
251
+fossil update $HASHC
252
+fossil amend $HASHC -close
253
+test amend-close-1.1.a {[string match "*uuid:*$HASHC*" $RESULT]}
254254
test amend-close-1.1.b {
255255
[string match "*comment:*Create*new*branch*named*\"cllf\"*" $RESULT]
256256
}
257
-fossil tag ls --raw $UUIDC
257
+fossil tag ls --raw $HASHC
258258
test amend-close-1.2 {[string first "closed" $RESULT] != -1}
259259
fossil timeline -n 1
260260
test amend-close-1.3 {[string match {*Mark*"Closed".*} $RESULT]}
261261
write_file datafile "cllf"
262262
fossil commit -m "should fail" -expectError
263263
test amend-close-2 {[string first "closed leaf" $RESULT] != -1}
264264
265
-set UUID3 UUID3
265
+set HASH3 HASH3
266266
fossil revert
267267
fossil update trunk
268268
write_file datafile "cb"
269269
fossil commit -m "closed-branch" --branch "closebranch"
270
-if {![uuid_from_commit $RESULT UUID3]} {
270
+if {![uuid_from_commit $RESULT HASH3]} {
271271
test amend-close-3.setup false
272272
}
273273
write_file datafile "b1"
274274
fossil commit -m "m1"
275275
write_file datafile "b2"
276276
fossil commit -m "m2"
277
-fossil amend $UUID3 --close
278
-test amend-close-3.1 {[string match "*uuid:*$UUID3*" $RESULT]}
277
+fossil amend $HASH3 --close
278
+test amend-close-3.1 {[string match "*uuid:*$HASH3*" $RESULT]}
279279
fossil tag ls --raw current
280280
test amend-close-3.2 {[string first "closed" $RESULT] != -1}
281281
fossil timeline -n 1
282282
test amend-close-3.3 {
283283
[string match "*Add*propagating*\"closed\".*" $RESULT]
@@ -310,96 +310,96 @@
310310
append t1exp ", $res"
311311
append t2exp "sym-$res*"
312312
append t3exp "Add*tag*\"$res\".*"
313313
append t5exp "Cancel*tag*\"$res\".*"
314314
}
315
- eval fossil amend $UUID $tags
316
- test amend-tag-$tc.1 {[string match "*uuid:*$UUID*tags:*$t1exp*" $RESULT]}
317
- fossil tag ls --raw $UUID
315
+ eval fossil amend $HASH $tags
316
+ test amend-tag-$tc.1 {[string match "*uuid:*$HASH*tags:*$t1exp*" $RESULT]}
317
+ fossil tag ls --raw $HASH
318318
test amend-tag-$tc.2 {[string match $t2exp $RESULT]}
319319
fossil timeline -n 1
320320
test amend-tag-$tc.3 {[string match $t3exp $RESULT]}
321
- eval fossil amend $UUID $cancels
321
+ eval fossil amend $HASH $cancels
322322
test amend-tag-$tc.4 {![string match "*tags:*$t1exp*" $RESULT]}
323323
fossil timeline -n 1
324324
test amend-tag-$tc.5 {[string match $t5exp $RESULT]}
325325
}
326326
327327
########################################
328328
# Test: -comment #
329329
########################################
330330
proc prep-test {comment content} {
331
- global UUID RESULT
331
+ global HASH RESULT
332332
333333
fossil revert
334334
fossil update trunk
335335
write_file datafile $comment
336336
fossil commit -m $content
337
- if {![uuid_from_commit $RESULT UUID]} {
338
- set UUID ""
337
+ if {![uuid_from_commit $RESULT HASH]} {
338
+ set HASH ""
339339
}
340340
}
341341
342
-proc test-comment {name UUID comment} {
342
+proc test-comment {name HASH comment} {
343343
global VERBOSE RESULT
344344
345345
test amend-comment-$name.1 {
346
- [string match "*uuid:*$UUID*comment:*$comment*" $RESULT]
346
+ [string match "*uuid:*$HASH*comment:*$comment*" $RESULT]
347347
}
348348
fossil timeline -n 1
349349
if {[artifact_from_timeline $RESULT artid]} {
350350
fossil artifact $artid
351351
test amend-comment-$name.2 {
352
- [string match "*T +comment $UUID* *[manifest_comment $comment]*" $RESULT]
352
+ [string match "*T +comment $HASH* *[manifest_comment $comment]*" $RESULT]
353353
}
354354
} else {
355355
if {$VERBOSE} { protOut "No artifact found in timeline output: $RESULT" }
356356
test amend-comment-$name.2 false
357357
}
358358
fossil timeline -n 1
359359
test amend-comment-$name.3 {
360
- [string match "*[short_uuid $UUID]*Edit*check-in*comment.*" $RESULT]
360
+ [string match "*[short_uuid $HASH]*Edit*check-in*comment.*" $RESULT]
361361
}
362
- fossil info $UUID
362
+ fossil info $HASH
363363
test amend-comment-$name.4 {
364
- [string match "*uuid:*$UUID*comment:*$comment*" $RESULT]
364
+ [string match "*uuid:*$HASH*comment:*$comment*" $RESULT]
365365
}
366366
}
367367
368368
prep-test "revision 1" "revision 1"
369
-fossil amend $UUID -comment "revised revision 1"
370
-test-comment 1 $UUID "revised revision 1"
369
+fossil amend $HASH -comment "revised revision 1"
370
+test-comment 1 $HASH "revised revision 1"
371371
372372
prep-test "revision 2" "revision 2"
373
-fossil amend $UUID -m "revised revision 2 with -m"
374
-test-comment 2 $UUID "revised revision 2 with -m"
373
+fossil amend $HASH -m "revised revision 2 with -m"
374
+test-comment 2 $HASH "revised revision 2 with -m"
375375
376376
prep-test "revision 3" "revision 3"
377377
write_file commitmsg "revision 3 revised"
378
-fossil amend $UUID -message-file commitmsg
379
-test-comment 3 $UUID "revision 3 revised"
378
+fossil amend $HASH -message-file commitmsg
379
+test-comment 3 $HASH "revision 3 revised"
380380
381381
prep-test "revision 4" "revision 4"
382382
write_file commitmsg "revision 4 revised with -M"
383
-fossil amend $UUID -M commitmsg
384
-test-comment 4 $UUID "revision 4 revised with -M"
383
+fossil amend $HASH -M commitmsg
384
+test-comment 4 $HASH "revision 4 revised with -M"
385385
386386
prep-test "final comment" "final content"
387387
if {[catch {exec which ed} result]} {
388388
if {$VERBOSE} { protOut "Install ed for interactive comment test: $result" }
389
- test-comment 5 $UUID "ed required for interactive edit"
389
+ test-comment 5 $HASH "ed required for interactive edit"
390390
} else {
391391
fossil settings editor "ed -s"
392392
set comment "interactive edited comment"
393
- fossil_maybe_answer "a\n$comment\n.\nw\nq\n" amend $UUID --edit-comment
394
- test-comment 5 $UUID $comment
393
+ fossil_maybe_answer "a\n$comment\n.\nw\nq\n" amend $HASH --edit-comment
394
+ test-comment 5 $HASH $comment
395395
}
396396
397397
########################################
398
-# Test: NULL UUID #
398
+# Test: NULL hash #
399399
########################################
400400
fossil amend {} -close -expectError
401401
test amend-null-uuid {$CODE && [string first "no such check-in" $RESULT] != -1}
402402
403403
###############################################################################
404404
405405
test_cleanup
406406
--- test/amend.test
+++ test/amend.test
@@ -26,61 +26,61 @@
26 proc manifest_comment {comment} {
27 string map [list { } {\\s} \n {\\n} \r {\\r}] $comment
28 }
29
30 proc uuid_from_commit {res var} {
31 upvar $var UUID
32 regexp {^New_Version: ([0-9a-f]{40})[0-9a-f]*$} $res m UUID
33 }
34
35 proc uuid_from_branch {res var} {
36 upvar $var UUID
37 regexp {^New branch: ([0-9a-f]{40})[0-9a-f]*$} $res m UUID
38 }
39
40 proc uuid_from_checkout {var} {
41 global RESULT
42 upvar $var UUID
43 fossil status
44 regexp {checkout:\s+([0-9a-f]{40})} $RESULT m UUID
45 }
46
47 # Make sure we are not in an open repository and initialize new repository
48 test_setup
49
50 ########################################
51 # Setup: Add file and commit #
52 ########################################
53
54 if {![uuid_from_checkout UUIDINIT]} {
55 test amend-checkout-failure false
56 test_cleanup_then_return
57 }
58 write_file datafile "data"
59 fossil add datafile
60 fossil commit -m "c1"
61 if {![uuid_from_commit $RESULT UUID]} {
62 test amend-setup-failure false
63 test_cleanup_then_return
64 }
65
66 ########################################
67 # Test: -branch #
68 ########################################
69 set UUIDB UUIDB
70 write_file datafile "data.file"
71 fossil commit -m "c2"
72 if {![uuid_from_commit $RESULT UUIDB]} {
73 test amend-branch.setup false
74 }
75 fossil amend $UUIDB -branch amended-branch
76 test amend-branch-1.1 {[regexp {tags:\s+amended-branch} $RESULT]}
77 fossil branch ls
78 test amend-branch-1.2 {[string first "* amended-branch" $RESULT] != -1}
79 fossil tag list
80 test amend-branch-1.3 {[string first amended-branch $RESULT] != -1}
81 fossil tag list --raw $UUIDB
82 test amend-branch-1.4 {[string first "branch=amended-branch" $RESULT] != -1}
83 test amend-branch-1.5 {[string first "sym-amended-branch" $RESULT] != -1}
84 fossil timeline -n 1
85 test amend-branch-1.6 {[string match {*Move*to*branch*amended-branch*} $RESULT]}
86
@@ -102,84 +102,84 @@
102 #1234 #1234
103 1234 1234
104 123456 #123456
105 } {
106 incr tc
107 fossil amend $UUID -bgcolor $color
108 test amend-bgcolor-1.$tc.a {[string match "*uuid:*$UUID*" $RESULT]}
109 fossil tag list --raw $UUID
110 test amend-bgcolor-1.$tc.b {[string first "bgcolor=$result" $RESULT] != -1}
111 fossil timeline -n 1
112 test amend-bgcolor-1.$tc.c {
113 [string match "*Change*background*color*to*\"$result\"*" $RESULT]
114 }
115 if {[artifact_from_timeline $RESULT artid]} {
116 fossil artifact $artid
117 test amend-bgcolor-1.$tc.d {
118 [string match "*T +bgcolor $UUID* $result*" $RESULT]
119 }
120 } else {
121 if {$VERBOSE} { protOut "No artifact found in timeline output" }
122 test amend-bgcolor-1.$tc.d false
123 }
124 }
125 fossil amend $UUID -bgcolor {}
126 test amend-bgcolor-2.1 {[string match "*uuid:*$UUID*" $RESULT]}
127 fossil tag list --raw $UUID
128 test amend-bgcolor-2.2 {
129 [string first "bgcolor=" $RESULT] == -1 &&
130 [string first "bgcolor" $RESULT] != -1
131 }
132 fossil timeline -n 1
133 test amend-bgcolor-2.3 {[string match "*Cancel*background*color.*" $RESULT]}
134 if {[artifact_from_timeline $RESULT artid]} {
135 fossil artifact $artid
136 test amend-bgcolor-2.4 {[string match "*T -bgcolor $UUID*" $RESULT]}
137 } else {
138 if {$VERBOSE} { protOut "No artifact found in timeline output" }
139 test amend-bgcolor-2.4 false
140 }
141
142 ########################################
143 # Test: -branchcolor #
144 ########################################
145 set UUID2 UUID2
146 fossil branch new brclr $UUID
147 if {![uuid_from_branch $RESULT UUID2]} {
148 test amend-branchcolor.setup false
149 }
150 fossil update $UUID2
151 fossil amend $UUID2 -branchcolor yellow
152 test amend-branchcolor-1.1 {[string match "*uuid:*$UUID2*" $RESULT]}
153 fossil tag ls --raw $UUID2
154 test amend-branchcolor-1.2 {[string first "bgcolor=yellow" $RESULT] != -1}
155 fossil timeline -n 1
156 test amend-branchcolor-1.3 {
157 [string match {*Change*branch*background*color*to*"yellow".*} $RESULT]
158 }
159 if {[regexp {(?x)[0-9]{2}(?::[0-9]{2}){2}\s+\[([0-9a-f]+)]} $RESULT m artid]} {
160 fossil artifact $artid
161 test amend-branchcolor-1.4 {
162 [string match "*T \*bgcolor $UUID2* yellow*" $RESULT]
163 }
164 } else {
165 if {$VERBOSE} { protOut "No artifact found in timeline output" }
166 test amend-branchcolor-1.4 false
167 }
168
169 set UUIDN UUIDN
170 write_file datafile "brclr"
171 fossil commit -m "brclr"
172 if {![uuid_from_commit $RESULT UUIDN]} {
173 test amend-branchcolor-propagating.setup false
174 }
175 write_file datafile "bc1"
176 fossil commit -m "mc1"
177 write_file datafile "bc2"
178 fossil commit -m "mc2"
179 fossil amend $UUIDN -branchcolor deadbe
180 test amend-branchcolor-2.1 {[string match "*uuid:*$UUIDN*" $RESULT]}
181 fossil tag ls --raw current
182 test amend-branchcolor-2.2 {[string first "bgcolor=#deadbe" $RESULT] != -1}
183 fossil timeline -n 1
184 test amend-branchcolor-2.3 {
185 [string match {*Change*branch*background*color*to*"#deadbe".*} $RESULT]
@@ -186,13 +186,13 @@
186 }
187
188 ########################################
189 # Test: -author #
190 ########################################
191 fossil amend $UUID -author author-test
192 test amend-author-1.1 {[string match {*comment:*(user:*author-test)*} $RESULT]}
193 fossil tag ls --raw $UUID
194 test amend-author-1.2 {[string first "user=author-test" $RESULT] != -1}
195 fossil timeline -n 1
196 test amend-author-1.3 {[string match {*Change*user*to*"author-test".*} $RESULT]}
197
198 ########################################
@@ -200,13 +200,13 @@
200 ########################################
201 set timestamp [clock scan yesterday]
202 set date [clock format $timestamp -format "%Y-%m-%d" -gmt 1]
203 set time [clock format $timestamp -format "%H:%M:%S" -gmt 1]
204 set datetime "$date $time"
205 fossil amend $UUIDINIT -date $datetime
206 test amend-date-1.1 {[string match "*uuid:*$UUIDINIT*$datetime*" $RESULT]}
207 fossil tag ls --raw $UUIDINIT
208 test amend-date-1.2 {[string first "date=$datetime" $RESULT] != -1}
209 fossil timeline -n 1
210 test amend-date-1.3 {[string match "*Timestamp*$date*$time*" $RESULT]}
211 set badformats {
212 "%+"
@@ -217,67 +217,67 @@
217 }
218 set sc 0
219 foreach badformat $badformats {
220 incr sc
221 set datetime [clock format $timestamp -format $badformat -gmt 1]
222 fossil amend $UUIDINIT -date $datetime -expectError
223 test amend-date-2.$sc {[string first "YYYY-MM-DD HH:MM:SS" $RESULT] != -1}
224 }
225
226 ########################################
227 # Test: -hide #
228 ########################################
229 set UUIDH UUIDH
230 fossil revert
231 fossil update trunk
232 fossil branch new tohide current
233 if {![uuid_from_branch $RESULT UUIDH]} {
234 test amend-hide-setup false
235 }
236 fossil amend $UUIDH -hide
237 test amend-hide-1.1 {[string match "*uuid:*$UUIDH*" $RESULT]}
238 fossil tag ls --raw $UUIDH
239 test amend-hide-1.2 {[string first "hidden" $RESULT] != -1}
240 fossil timeline -n 1
241 test amend-hide-1.3 {[string match {*Add*propagating*"hidden".*} $RESULT]}
242
243 ########################################
244 # Test: -close #
245 ########################################
246 set UUIDC UUIDC
247 fossil branch new cllf $UUID
248 if {![uuid_from_branch $RESULT UUIDC]} {
249 test amend-close.setup false
250 }
251 fossil update $UUIDC
252 fossil amend $UUIDC -close
253 test amend-close-1.1.a {[string match "*uuid:*$UUIDC*" $RESULT]}
254 test amend-close-1.1.b {
255 [string match "*comment:*Create*new*branch*named*\"cllf\"*" $RESULT]
256 }
257 fossil tag ls --raw $UUIDC
258 test amend-close-1.2 {[string first "closed" $RESULT] != -1}
259 fossil timeline -n 1
260 test amend-close-1.3 {[string match {*Mark*"Closed".*} $RESULT]}
261 write_file datafile "cllf"
262 fossil commit -m "should fail" -expectError
263 test amend-close-2 {[string first "closed leaf" $RESULT] != -1}
264
265 set UUID3 UUID3
266 fossil revert
267 fossil update trunk
268 write_file datafile "cb"
269 fossil commit -m "closed-branch" --branch "closebranch"
270 if {![uuid_from_commit $RESULT UUID3]} {
271 test amend-close-3.setup false
272 }
273 write_file datafile "b1"
274 fossil commit -m "m1"
275 write_file datafile "b2"
276 fossil commit -m "m2"
277 fossil amend $UUID3 --close
278 test amend-close-3.1 {[string match "*uuid:*$UUID3*" $RESULT]}
279 fossil tag ls --raw current
280 test amend-close-3.2 {[string first "closed" $RESULT] != -1}
281 fossil timeline -n 1
282 test amend-close-3.3 {
283 [string match "*Add*propagating*\"closed\".*" $RESULT]
@@ -310,96 +310,96 @@
310 append t1exp ", $res"
311 append t2exp "sym-$res*"
312 append t3exp "Add*tag*\"$res\".*"
313 append t5exp "Cancel*tag*\"$res\".*"
314 }
315 eval fossil amend $UUID $tags
316 test amend-tag-$tc.1 {[string match "*uuid:*$UUID*tags:*$t1exp*" $RESULT]}
317 fossil tag ls --raw $UUID
318 test amend-tag-$tc.2 {[string match $t2exp $RESULT]}
319 fossil timeline -n 1
320 test amend-tag-$tc.3 {[string match $t3exp $RESULT]}
321 eval fossil amend $UUID $cancels
322 test amend-tag-$tc.4 {![string match "*tags:*$t1exp*" $RESULT]}
323 fossil timeline -n 1
324 test amend-tag-$tc.5 {[string match $t5exp $RESULT]}
325 }
326
327 ########################################
328 # Test: -comment #
329 ########################################
330 proc prep-test {comment content} {
331 global UUID RESULT
332
333 fossil revert
334 fossil update trunk
335 write_file datafile $comment
336 fossil commit -m $content
337 if {![uuid_from_commit $RESULT UUID]} {
338 set UUID ""
339 }
340 }
341
342 proc test-comment {name UUID comment} {
343 global VERBOSE RESULT
344
345 test amend-comment-$name.1 {
346 [string match "*uuid:*$UUID*comment:*$comment*" $RESULT]
347 }
348 fossil timeline -n 1
349 if {[artifact_from_timeline $RESULT artid]} {
350 fossil artifact $artid
351 test amend-comment-$name.2 {
352 [string match "*T +comment $UUID* *[manifest_comment $comment]*" $RESULT]
353 }
354 } else {
355 if {$VERBOSE} { protOut "No artifact found in timeline output: $RESULT" }
356 test amend-comment-$name.2 false
357 }
358 fossil timeline -n 1
359 test amend-comment-$name.3 {
360 [string match "*[short_uuid $UUID]*Edit*check-in*comment.*" $RESULT]
361 }
362 fossil info $UUID
363 test amend-comment-$name.4 {
364 [string match "*uuid:*$UUID*comment:*$comment*" $RESULT]
365 }
366 }
367
368 prep-test "revision 1" "revision 1"
369 fossil amend $UUID -comment "revised revision 1"
370 test-comment 1 $UUID "revised revision 1"
371
372 prep-test "revision 2" "revision 2"
373 fossil amend $UUID -m "revised revision 2 with -m"
374 test-comment 2 $UUID "revised revision 2 with -m"
375
376 prep-test "revision 3" "revision 3"
377 write_file commitmsg "revision 3 revised"
378 fossil amend $UUID -message-file commitmsg
379 test-comment 3 $UUID "revision 3 revised"
380
381 prep-test "revision 4" "revision 4"
382 write_file commitmsg "revision 4 revised with -M"
383 fossil amend $UUID -M commitmsg
384 test-comment 4 $UUID "revision 4 revised with -M"
385
386 prep-test "final comment" "final content"
387 if {[catch {exec which ed} result]} {
388 if {$VERBOSE} { protOut "Install ed for interactive comment test: $result" }
389 test-comment 5 $UUID "ed required for interactive edit"
390 } else {
391 fossil settings editor "ed -s"
392 set comment "interactive edited comment"
393 fossil_maybe_answer "a\n$comment\n.\nw\nq\n" amend $UUID --edit-comment
394 test-comment 5 $UUID $comment
395 }
396
397 ########################################
398 # Test: NULL UUID #
399 ########################################
400 fossil amend {} -close -expectError
401 test amend-null-uuid {$CODE && [string first "no such check-in" $RESULT] != -1}
402
403 ###############################################################################
404
405 test_cleanup
406
--- test/amend.test
+++ test/amend.test
@@ -26,61 +26,61 @@
26 proc manifest_comment {comment} {
27 string map [list { } {\\s} \n {\\n} \r {\\r}] $comment
28 }
29
30 proc uuid_from_commit {res var} {
31 upvar $var HASH
32 regexp {^New_Version: ([0-9a-f]{40})[0-9a-f]*$} $res m HASH
33 }
34
35 proc uuid_from_branch {res var} {
36 upvar $var HASH
37 regexp {^New branch: ([0-9a-f]{40})[0-9a-f]*$} $res m HASH
38 }
39
40 proc uuid_from_checkout {var} {
41 global RESULT
42 upvar $var HASH
43 fossil status
44 regexp {checkout:\s+([0-9a-f]{40})[0-9a-f]*} $RESULT m HASH
45 }
46
47 # Make sure we are not in an open repository and initialize new repository
48 test_setup
49
50 ########################################
51 # Setup: Add file and commit #
52 ########################################
53
54 if {![uuid_from_checkout HASHINIT]} {
55 test amend-checkout-failure false
56 test_cleanup_then_return
57 }
58 write_file datafile "data"
59 fossil add datafile
60 fossil commit -m "c1"
61 if {![uuid_from_commit $RESULT HASH]} {
62 test amend-setup-failure false
63 test_cleanup_then_return
64 }
65
66 ########################################
67 # Test: -branch #
68 ########################################
69 set HASHB HASHB
70 write_file datafile "data.file"
71 fossil commit -m "c2"
72 if {![uuid_from_commit $RESULT HASHB]} {
73 test amend-branch.setup false
74 }
75 fossil amend $HASHB -branch amended-branch
76 test amend-branch-1.1 {[regexp {tags:\s+amended-branch} $RESULT]}
77 fossil branch ls
78 test amend-branch-1.2 {[string first "* amended-branch" $RESULT] != -1}
79 fossil tag list
80 test amend-branch-1.3 {[string first amended-branch $RESULT] != -1}
81 fossil tag list --raw $HASHB
82 test amend-branch-1.4 {[string first "branch=amended-branch" $RESULT] != -1}
83 test amend-branch-1.5 {[string first "sym-amended-branch" $RESULT] != -1}
84 fossil timeline -n 1
85 test amend-branch-1.6 {[string match {*Move*to*branch*amended-branch*} $RESULT]}
86
@@ -102,84 +102,84 @@
102 #1234 #1234
103 1234 1234
104 123456 #123456
105 } {
106 incr tc
107 fossil amend $HASH -bgcolor $color
108 test amend-bgcolor-1.$tc.a {[string match "*uuid:*$HASH*" $RESULT]}
109 fossil tag list --raw $HASH
110 test amend-bgcolor-1.$tc.b {[string first "bgcolor=$result" $RESULT] != -1}
111 fossil timeline -n 1
112 test amend-bgcolor-1.$tc.c {
113 [string match "*Change*background*color*to*\"$result\"*" $RESULT]
114 }
115 if {[artifact_from_timeline $RESULT artid]} {
116 fossil artifact $artid
117 test amend-bgcolor-1.$tc.d {
118 [string match "*T +bgcolor $HASH* $result*" $RESULT]
119 }
120 } else {
121 if {$VERBOSE} { protOut "No artifact found in timeline output" }
122 test amend-bgcolor-1.$tc.d false
123 }
124 }
125 fossil amend $HASH -bgcolor {}
126 test amend-bgcolor-2.1 {[string match "*uuid:*$HASH*" $RESULT]}
127 fossil tag list --raw $HASH
128 test amend-bgcolor-2.2 {
129 [string first "bgcolor=" $RESULT] == -1 &&
130 [string first "bgcolor" $RESULT] != -1
131 }
132 fossil timeline -n 1
133 test amend-bgcolor-2.3 {[string match "*Cancel*background*color.*" $RESULT]}
134 if {[artifact_from_timeline $RESULT artid]} {
135 fossil artifact $artid
136 test amend-bgcolor-2.4 {[string match "*T -bgcolor $HASH*" $RESULT]}
137 } else {
138 if {$VERBOSE} { protOut "No artifact found in timeline output" }
139 test amend-bgcolor-2.4 false
140 }
141
142 ########################################
143 # Test: -branchcolor #
144 ########################################
145 set HASH2 HASH2
146 fossil branch new brclr $HASH
147 if {![uuid_from_branch $RESULT HASH2]} {
148 test amend-branchcolor.setup false
149 }
150 fossil update $HASH2
151 fossil amend $HASH2 -branchcolor yellow
152 test amend-branchcolor-1.1 {[string match "*uuid:*$HASH2*" $RESULT]}
153 fossil tag ls --raw $HASH2
154 test amend-branchcolor-1.2 {[string first "bgcolor=yellow" $RESULT] != -1}
155 fossil timeline -n 1
156 test amend-branchcolor-1.3 {
157 [string match {*Change*branch*background*color*to*"yellow".*} $RESULT]
158 }
159 if {[regexp {(?x)[0-9]{2}(?::[0-9]{2}){2}\s+\[([0-9a-f]+)]} $RESULT m artid]} {
160 fossil artifact $artid
161 test amend-branchcolor-1.4 {
162 [string match "*T \*bgcolor $HASH2* yellow*" $RESULT]
163 }
164 } else {
165 if {$VERBOSE} { protOut "No artifact found in timeline output" }
166 test amend-branchcolor-1.4 false
167 }
168
169 set HASHN HASHN
170 write_file datafile "brclr"
171 fossil commit -m "brclr"
172 if {![uuid_from_commit $RESULT HASHN]} {
173 test amend-branchcolor-propagating.setup false
174 }
175 write_file datafile "bc1"
176 fossil commit -m "mc1"
177 write_file datafile "bc2"
178 fossil commit -m "mc2"
179 fossil amend $HASHN -branchcolor deadbe
180 test amend-branchcolor-2.1 {[string match "*uuid:*$HASHN*" $RESULT]}
181 fossil tag ls --raw current
182 test amend-branchcolor-2.2 {[string first "bgcolor=#deadbe" $RESULT] != -1}
183 fossil timeline -n 1
184 test amend-branchcolor-2.3 {
185 [string match {*Change*branch*background*color*to*"#deadbe".*} $RESULT]
@@ -186,13 +186,13 @@
186 }
187
188 ########################################
189 # Test: -author #
190 ########################################
191 fossil amend $HASH -author author-test
192 test amend-author-1.1 {[string match {*comment:*(user:*author-test)*} $RESULT]}
193 fossil tag ls --raw $HASH
194 test amend-author-1.2 {[string first "user=author-test" $RESULT] != -1}
195 fossil timeline -n 1
196 test amend-author-1.3 {[string match {*Change*user*to*"author-test".*} $RESULT]}
197
198 ########################################
@@ -200,13 +200,13 @@
200 ########################################
201 set timestamp [clock scan yesterday]
202 set date [clock format $timestamp -format "%Y-%m-%d" -gmt 1]
203 set time [clock format $timestamp -format "%H:%M:%S" -gmt 1]
204 set datetime "$date $time"
205 fossil amend $HASHINIT -date $datetime
206 test amend-date-1.1 {[string match "*uuid:*$HASHINIT*$datetime*" $RESULT]}
207 fossil tag ls --raw $HASHINIT
208 test amend-date-1.2 {[string first "date=$datetime" $RESULT] != -1}
209 fossil timeline -n 1
210 test amend-date-1.3 {[string match "*Timestamp*$date*$time*" $RESULT]}
211 set badformats {
212 "%+"
@@ -217,67 +217,67 @@
217 }
218 set sc 0
219 foreach badformat $badformats {
220 incr sc
221 set datetime [clock format $timestamp -format $badformat -gmt 1]
222 fossil amend $HASHINIT -date $datetime -expectError
223 test amend-date-2.$sc {[string first "YYYY-MM-DD HH:MM:SS" $RESULT] != -1}
224 }
225
226 ########################################
227 # Test: -hide #
228 ########################################
229 set HASHH HASHH
230 fossil revert
231 fossil update trunk
232 fossil branch new tohide current
233 if {![uuid_from_branch $RESULT HASHH]} {
234 test amend-hide-setup false
235 }
236 fossil amend $HASHH -hide
237 test amend-hide-1.1 {[string match "*uuid:*$HASHH*" $RESULT]}
238 fossil tag ls --raw $HASHH
239 test amend-hide-1.2 {[string first "hidden" $RESULT] != -1}
240 fossil timeline -n 1
241 test amend-hide-1.3 {[string match {*Add*propagating*"hidden".*} $RESULT]}
242
243 ########################################
244 # Test: -close #
245 ########################################
246 set HASHC HASHC
247 fossil branch new cllf $HASH
248 if {![uuid_from_branch $RESULT HASHC]} {
249 test amend-close.setup false
250 }
251 fossil update $HASHC
252 fossil amend $HASHC -close
253 test amend-close-1.1.a {[string match "*uuid:*$HASHC*" $RESULT]}
254 test amend-close-1.1.b {
255 [string match "*comment:*Create*new*branch*named*\"cllf\"*" $RESULT]
256 }
257 fossil tag ls --raw $HASHC
258 test amend-close-1.2 {[string first "closed" $RESULT] != -1}
259 fossil timeline -n 1
260 test amend-close-1.3 {[string match {*Mark*"Closed".*} $RESULT]}
261 write_file datafile "cllf"
262 fossil commit -m "should fail" -expectError
263 test amend-close-2 {[string first "closed leaf" $RESULT] != -1}
264
265 set HASH3 HASH3
266 fossil revert
267 fossil update trunk
268 write_file datafile "cb"
269 fossil commit -m "closed-branch" --branch "closebranch"
270 if {![uuid_from_commit $RESULT HASH3]} {
271 test amend-close-3.setup false
272 }
273 write_file datafile "b1"
274 fossil commit -m "m1"
275 write_file datafile "b2"
276 fossil commit -m "m2"
277 fossil amend $HASH3 --close
278 test amend-close-3.1 {[string match "*uuid:*$HASH3*" $RESULT]}
279 fossil tag ls --raw current
280 test amend-close-3.2 {[string first "closed" $RESULT] != -1}
281 fossil timeline -n 1
282 test amend-close-3.3 {
283 [string match "*Add*propagating*\"closed\".*" $RESULT]
@@ -310,96 +310,96 @@
310 append t1exp ", $res"
311 append t2exp "sym-$res*"
312 append t3exp "Add*tag*\"$res\".*"
313 append t5exp "Cancel*tag*\"$res\".*"
314 }
315 eval fossil amend $HASH $tags
316 test amend-tag-$tc.1 {[string match "*uuid:*$HASH*tags:*$t1exp*" $RESULT]}
317 fossil tag ls --raw $HASH
318 test amend-tag-$tc.2 {[string match $t2exp $RESULT]}
319 fossil timeline -n 1
320 test amend-tag-$tc.3 {[string match $t3exp $RESULT]}
321 eval fossil amend $HASH $cancels
322 test amend-tag-$tc.4 {![string match "*tags:*$t1exp*" $RESULT]}
323 fossil timeline -n 1
324 test amend-tag-$tc.5 {[string match $t5exp $RESULT]}
325 }
326
327 ########################################
328 # Test: -comment #
329 ########################################
330 proc prep-test {comment content} {
331 global HASH RESULT
332
333 fossil revert
334 fossil update trunk
335 write_file datafile $comment
336 fossil commit -m $content
337 if {![uuid_from_commit $RESULT HASH]} {
338 set HASH ""
339 }
340 }
341
342 proc test-comment {name HASH comment} {
343 global VERBOSE RESULT
344
345 test amend-comment-$name.1 {
346 [string match "*uuid:*$HASH*comment:*$comment*" $RESULT]
347 }
348 fossil timeline -n 1
349 if {[artifact_from_timeline $RESULT artid]} {
350 fossil artifact $artid
351 test amend-comment-$name.2 {
352 [string match "*T +comment $HASH* *[manifest_comment $comment]*" $RESULT]
353 }
354 } else {
355 if {$VERBOSE} { protOut "No artifact found in timeline output: $RESULT" }
356 test amend-comment-$name.2 false
357 }
358 fossil timeline -n 1
359 test amend-comment-$name.3 {
360 [string match "*[short_uuid $HASH]*Edit*check-in*comment.*" $RESULT]
361 }
362 fossil info $HASH
363 test amend-comment-$name.4 {
364 [string match "*uuid:*$HASH*comment:*$comment*" $RESULT]
365 }
366 }
367
368 prep-test "revision 1" "revision 1"
369 fossil amend $HASH -comment "revised revision 1"
370 test-comment 1 $HASH "revised revision 1"
371
372 prep-test "revision 2" "revision 2"
373 fossil amend $HASH -m "revised revision 2 with -m"
374 test-comment 2 $HASH "revised revision 2 with -m"
375
376 prep-test "revision 3" "revision 3"
377 write_file commitmsg "revision 3 revised"
378 fossil amend $HASH -message-file commitmsg
379 test-comment 3 $HASH "revision 3 revised"
380
381 prep-test "revision 4" "revision 4"
382 write_file commitmsg "revision 4 revised with -M"
383 fossil amend $HASH -M commitmsg
384 test-comment 4 $HASH "revision 4 revised with -M"
385
386 prep-test "final comment" "final content"
387 if {[catch {exec which ed} result]} {
388 if {$VERBOSE} { protOut "Install ed for interactive comment test: $result" }
389 test-comment 5 $HASH "ed required for interactive edit"
390 } else {
391 fossil settings editor "ed -s"
392 set comment "interactive edited comment"
393 fossil_maybe_answer "a\n$comment\n.\nw\nq\n" amend $HASH --edit-comment
394 test-comment 5 $HASH $comment
395 }
396
397 ########################################
398 # Test: NULL hash #
399 ########################################
400 fossil amend {} -close -expectError
401 test amend-null-uuid {$CODE && [string first "no such check-in" $RESULT] != -1}
402
403 ###############################################################################
404
405 test_cleanup
406
--- tools/email-sender.tcl
+++ tools/email-sender.tcl
@@ -21,11 +21,15 @@
2121
}
2222
while {1} {
2323
db transaction immediate {
2424
set n 0
2525
db eval {SELECT msg FROM email} {
26
- set out [open |$PIPE w]
26
+ set pipe $PIPE
27
+ if {[regexp {\nFrom:[^\n]*<([^>]+)>} $msg all addr]} {
28
+ append pipe " -f $addr"
29
+ }
30
+ set out [open |$pipe w]
2731
puts -nonewline $out $msg
2832
flush $out
2933
close $out
3034
incr n
3135
}
3236
--- tools/email-sender.tcl
+++ tools/email-sender.tcl
@@ -21,11 +21,15 @@
21 }
22 while {1} {
23 db transaction immediate {
24 set n 0
25 db eval {SELECT msg FROM email} {
26 set out [open |$PIPE w]
 
 
 
 
27 puts -nonewline $out $msg
28 flush $out
29 close $out
30 incr n
31 }
32
--- tools/email-sender.tcl
+++ tools/email-sender.tcl
@@ -21,11 +21,15 @@
21 }
22 while {1} {
23 db transaction immediate {
24 set n 0
25 db eval {SELECT msg FROM email} {
26 set pipe $PIPE
27 if {[regexp {\nFrom:[^\n]*<([^>]+)>} $msg all addr]} {
28 append pipe " -f $addr"
29 }
30 set out [open |$pipe w]
31 puts -nonewline $out $msg
32 flush $out
33 close $out
34 incr n
35 }
36
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -83,17 +83,17 @@
8383
8484
# define the SQLite files, which need special flags on compile
8585
SQLITESRC=sqlite3.c
8686
ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf))
8787
SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj))
88
-SQLITEDEFINES=-DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_GET_TABLE -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -DSQLITE_WIN32_NO_ANSI
88
+SQLITEDEFINES=-DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -DSQLITE_WIN32_NO_ANSI
8989
9090
# define the SQLite shell files, which need special flags on compile
9191
SQLITESHELLSRC=shell.c
9292
ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf))
9393
SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj))
94
-SQLITESHELLDEFINES=-DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_GET_TABLE -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
94
+SQLITESHELLDEFINES=-DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
9595
9696
# define the th scripting files, which need special flags on compile
9797
THSRC=th.c th_lang.c
9898
ORIGTHSRC=$(foreach sf,$(THSRC),$(SRCDIR)$(sf))
9999
THOBJ=$(foreach sf,$(THSRC),$(sf:.c=.obj))
100100
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -83,17 +83,17 @@
83
84 # define the SQLite files, which need special flags on compile
85 SQLITESRC=sqlite3.c
86 ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf))
87 SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj))
88 SQLITEDEFINES=-DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_GET_TABLE -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -DSQLITE_WIN32_NO_ANSI
89
90 # define the SQLite shell files, which need special flags on compile
91 SQLITESHELLSRC=shell.c
92 ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf))
93 SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj))
94 SQLITESHELLDEFINES=-DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_GET_TABLE -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
95
96 # define the th scripting files, which need special flags on compile
97 THSRC=th.c th_lang.c
98 ORIGTHSRC=$(foreach sf,$(THSRC),$(SRCDIR)$(sf))
99 THOBJ=$(foreach sf,$(THSRC),$(sf:.c=.obj))
100
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -83,17 +83,17 @@
83
84 # define the SQLite files, which need special flags on compile
85 SQLITESRC=sqlite3.c
86 ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf))
87 SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj))
88 SQLITEDEFINES=-DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -DSQLITE_WIN32_NO_ANSI
89
90 # define the SQLite shell files, which need special flags on compile
91 SQLITESHELLSRC=shell.c
92 ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf))
93 SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj))
94 SQLITESHELLDEFINES=-DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
95
96 # define the th scripting files, which need special flags on compile
97 THSRC=th.c th_lang.c
98 ORIGTHSRC=$(foreach sf,$(THSRC),$(SRCDIR)$(sf))
99 THOBJ=$(foreach sf,$(THSRC),$(sf:.c=.obj))
100
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -24,13 +24,13 @@
2424
CFLAGS = -o
2525
BCC = $(DMDIR)\bin\dmc $(CFLAGS)
2626
TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
2727
LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 dnsapi
2828
29
-SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_GET_TABLE -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0
29
+SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0
3030
31
-SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_GET_TABLE -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
31
+SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
3232
3333
SRC = add_.c alerts_.c allrepo_.c attach_.c backlink_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c deltafunc_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c extcgi_.c file_.c fileedit_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.c glob_.c graph_.c gzip_.c hname_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c piechart_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c repolist_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c terminal_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c webmail_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
3434
3535
OBJ = $(OBJDIR)\add$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\backlink$O $(OBJDIR)\backoffice$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\capabilities$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\cookies$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\deltafunc$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\etag$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\extcgi$O $(OBJDIR)\file$O $(OBJDIR)\fileedit$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\forum$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\fuzz$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\hname$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\repolist$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\setupuser$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\smtp$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\terminal$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\unversioned$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\webmail$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
3636
3737
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -24,13 +24,13 @@
24 CFLAGS = -o
25 BCC = $(DMDIR)\bin\dmc $(CFLAGS)
26 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
27 LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 dnsapi
28
29 SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_GET_TABLE -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0
30
31 SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_GET_TABLE -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
32
33 SRC = add_.c alerts_.c allrepo_.c attach_.c backlink_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c deltafunc_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c extcgi_.c file_.c fileedit_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.c glob_.c graph_.c gzip_.c hname_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c piechart_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c repolist_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c terminal_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c webmail_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
34
35 OBJ = $(OBJDIR)\add$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\backlink$O $(OBJDIR)\backoffice$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\capabilities$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\cookies$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\deltafunc$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\etag$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\extcgi$O $(OBJDIR)\file$O $(OBJDIR)\fileedit$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\forum$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\fuzz$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\hname$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\repolist$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\setupuser$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\smtp$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\terminal$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\unversioned$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\webmail$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
36
37
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -24,13 +24,13 @@
24 CFLAGS = -o
25 BCC = $(DMDIR)\bin\dmc $(CFLAGS)
26 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
27 LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 dnsapi
28
29 SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0
30
31 SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
32
33 SRC = add_.c alerts_.c allrepo_.c attach_.c backlink_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c deltafunc_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c extcgi_.c file_.c fileedit_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.c glob_.c graph_.c gzip_.c hname_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c piechart_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c repolist_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c terminal_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c webmail_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
34
35 OBJ = $(OBJDIR)\add$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\backlink$O $(OBJDIR)\backoffice$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\capabilities$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\cookies$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\deltafunc$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\etag$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\extcgi$O $(OBJDIR)\file$O $(OBJDIR)\fileedit$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\forum$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\fuzz$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\hname$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\repolist$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\setupuser$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\smtp$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\terminal$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\unversioned$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\webmail$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
36
37
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -2485,11 +2485,10 @@
24852485
-DSQLITE_DEFAULT_MEMSTATUS=0 \
24862486
-DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \
24872487
-DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
24882488
-DSQLITE_OMIT_DECLTYPE \
24892489
-DSQLITE_OMIT_DEPRECATED \
2490
- -DSQLITE_OMIT_GET_TABLE \
24912490
-DSQLITE_OMIT_PROGRESS_CALLBACK \
24922491
-DSQLITE_OMIT_SHARED_CACHE \
24932492
-DSQLITE_OMIT_LOAD_EXTENSION \
24942493
-DSQLITE_MAX_EXPR_DEPTH=0 \
24952494
-DSQLITE_USE_ALLOCA \
@@ -2516,11 +2515,10 @@
25162515
-DSQLITE_DEFAULT_MEMSTATUS=0 \
25172516
-DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \
25182517
-DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
25192518
-DSQLITE_OMIT_DECLTYPE \
25202519
-DSQLITE_OMIT_DEPRECATED \
2521
- -DSQLITE_OMIT_GET_TABLE \
25222520
-DSQLITE_OMIT_PROGRESS_CALLBACK \
25232521
-DSQLITE_OMIT_SHARED_CACHE \
25242522
-DSQLITE_OMIT_LOAD_EXTENSION \
25252523
-DSQLITE_MAX_EXPR_DEPTH=0 \
25262524
-DSQLITE_USE_ALLOCA \
25272525
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -2485,11 +2485,10 @@
2485 -DSQLITE_DEFAULT_MEMSTATUS=0 \
2486 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \
2487 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
2488 -DSQLITE_OMIT_DECLTYPE \
2489 -DSQLITE_OMIT_DEPRECATED \
2490 -DSQLITE_OMIT_GET_TABLE \
2491 -DSQLITE_OMIT_PROGRESS_CALLBACK \
2492 -DSQLITE_OMIT_SHARED_CACHE \
2493 -DSQLITE_OMIT_LOAD_EXTENSION \
2494 -DSQLITE_MAX_EXPR_DEPTH=0 \
2495 -DSQLITE_USE_ALLOCA \
@@ -2516,11 +2515,10 @@
2516 -DSQLITE_DEFAULT_MEMSTATUS=0 \
2517 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \
2518 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
2519 -DSQLITE_OMIT_DECLTYPE \
2520 -DSQLITE_OMIT_DEPRECATED \
2521 -DSQLITE_OMIT_GET_TABLE \
2522 -DSQLITE_OMIT_PROGRESS_CALLBACK \
2523 -DSQLITE_OMIT_SHARED_CACHE \
2524 -DSQLITE_OMIT_LOAD_EXTENSION \
2525 -DSQLITE_MAX_EXPR_DEPTH=0 \
2526 -DSQLITE_USE_ALLOCA \
2527
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -2485,11 +2485,10 @@
2485 -DSQLITE_DEFAULT_MEMSTATUS=0 \
2486 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \
2487 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
2488 -DSQLITE_OMIT_DECLTYPE \
2489 -DSQLITE_OMIT_DEPRECATED \
 
2490 -DSQLITE_OMIT_PROGRESS_CALLBACK \
2491 -DSQLITE_OMIT_SHARED_CACHE \
2492 -DSQLITE_OMIT_LOAD_EXTENSION \
2493 -DSQLITE_MAX_EXPR_DEPTH=0 \
2494 -DSQLITE_USE_ALLOCA \
@@ -2516,11 +2515,10 @@
2515 -DSQLITE_DEFAULT_MEMSTATUS=0 \
2516 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \
2517 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
2518 -DSQLITE_OMIT_DECLTYPE \
2519 -DSQLITE_OMIT_DEPRECATED \
 
2520 -DSQLITE_OMIT_PROGRESS_CALLBACK \
2521 -DSQLITE_OMIT_SHARED_CACHE \
2522 -DSQLITE_OMIT_LOAD_EXTENSION \
2523 -DSQLITE_MAX_EXPR_DEPTH=0 \
2524 -DSQLITE_USE_ALLOCA \
2525
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -283,11 +283,10 @@
283283
/DSQLITE_DEFAULT_MEMSTATUS=0 \
284284
/DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \
285285
/DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
286286
/DSQLITE_OMIT_DECLTYPE \
287287
/DSQLITE_OMIT_DEPRECATED \
288
- /DSQLITE_OMIT_GET_TABLE \
289288
/DSQLITE_OMIT_PROGRESS_CALLBACK \
290289
/DSQLITE_OMIT_SHARED_CACHE \
291290
/DSQLITE_OMIT_LOAD_EXTENSION \
292291
/DSQLITE_MAX_EXPR_DEPTH=0 \
293292
/DSQLITE_USE_ALLOCA \
@@ -311,11 +310,10 @@
311310
/DSQLITE_DEFAULT_MEMSTATUS=0 \
312311
/DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \
313312
/DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
314313
/DSQLITE_OMIT_DECLTYPE \
315314
/DSQLITE_OMIT_DEPRECATED \
316
- /DSQLITE_OMIT_GET_TABLE \
317315
/DSQLITE_OMIT_PROGRESS_CALLBACK \
318316
/DSQLITE_OMIT_SHARED_CACHE \
319317
/DSQLITE_OMIT_LOAD_EXTENSION \
320318
/DSQLITE_MAX_EXPR_DEPTH=0 \
321319
/DSQLITE_USE_ALLOCA \
322320
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -283,11 +283,10 @@
283 /DSQLITE_DEFAULT_MEMSTATUS=0 \
284 /DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \
285 /DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
286 /DSQLITE_OMIT_DECLTYPE \
287 /DSQLITE_OMIT_DEPRECATED \
288 /DSQLITE_OMIT_GET_TABLE \
289 /DSQLITE_OMIT_PROGRESS_CALLBACK \
290 /DSQLITE_OMIT_SHARED_CACHE \
291 /DSQLITE_OMIT_LOAD_EXTENSION \
292 /DSQLITE_MAX_EXPR_DEPTH=0 \
293 /DSQLITE_USE_ALLOCA \
@@ -311,11 +310,10 @@
311 /DSQLITE_DEFAULT_MEMSTATUS=0 \
312 /DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \
313 /DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
314 /DSQLITE_OMIT_DECLTYPE \
315 /DSQLITE_OMIT_DEPRECATED \
316 /DSQLITE_OMIT_GET_TABLE \
317 /DSQLITE_OMIT_PROGRESS_CALLBACK \
318 /DSQLITE_OMIT_SHARED_CACHE \
319 /DSQLITE_OMIT_LOAD_EXTENSION \
320 /DSQLITE_MAX_EXPR_DEPTH=0 \
321 /DSQLITE_USE_ALLOCA \
322
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -283,11 +283,10 @@
283 /DSQLITE_DEFAULT_MEMSTATUS=0 \
284 /DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \
285 /DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
286 /DSQLITE_OMIT_DECLTYPE \
287 /DSQLITE_OMIT_DEPRECATED \
 
288 /DSQLITE_OMIT_PROGRESS_CALLBACK \
289 /DSQLITE_OMIT_SHARED_CACHE \
290 /DSQLITE_OMIT_LOAD_EXTENSION \
291 /DSQLITE_MAX_EXPR_DEPTH=0 \
292 /DSQLITE_USE_ALLOCA \
@@ -311,11 +310,10 @@
310 /DSQLITE_DEFAULT_MEMSTATUS=0 \
311 /DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \
312 /DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
313 /DSQLITE_OMIT_DECLTYPE \
314 /DSQLITE_OMIT_DEPRECATED \
 
315 /DSQLITE_OMIT_PROGRESS_CALLBACK \
316 /DSQLITE_OMIT_SHARED_CACHE \
317 /DSQLITE_OMIT_LOAD_EXTENSION \
318 /DSQLITE_MAX_EXPR_DEPTH=0 \
319 /DSQLITE_USE_ALLOCA \
320
--- www/concepts.wiki
+++ www/concepts.wiki
@@ -80,11 +80,11 @@
8080
Communication between repositories is via HTTP. Remote
8181
repositories are identified by URL. You can also point a web browser
8282
at a repository and get human-readable status, history, and tracking
8383
information about the project.
8484
85
-<h3>2.1 Identification Of Artifacts</h3>
85
+<h3><a id="artifacts"></a>2.1 Identification Of Artifacts</h3>
8686
8787
A particular version of a particular file is called an "artifact". Each
8888
artifact has a universally unique name which is the <a
8989
href="http://en.wikipedia.org/wiki/SHA1">SHA1</a> or <a
9090
href="http://en.wikipedia.org/wiki/SHA3">SHA3-256</a> hash of the
9191
--- www/concepts.wiki
+++ www/concepts.wiki
@@ -80,11 +80,11 @@
80 Communication between repositories is via HTTP. Remote
81 repositories are identified by URL. You can also point a web browser
82 at a repository and get human-readable status, history, and tracking
83 information about the project.
84
85 <h3>2.1 Identification Of Artifacts</h3>
86
87 A particular version of a particular file is called an "artifact". Each
88 artifact has a universally unique name which is the <a
89 href="http://en.wikipedia.org/wiki/SHA1">SHA1</a> or <a
90 href="http://en.wikipedia.org/wiki/SHA3">SHA3-256</a> hash of the
91
--- www/concepts.wiki
+++ www/concepts.wiki
@@ -80,11 +80,11 @@
80 Communication between repositories is via HTTP. Remote
81 repositories are identified by URL. You can also point a web browser
82 at a repository and get human-readable status, history, and tracking
83 information about the project.
84
85 <h3><a id="artifacts"></a>2.1 Identification Of Artifacts</h3>
86
87 A particular version of a particular file is called an "artifact". Each
88 artifact has a universally unique name which is the <a
89 href="http://en.wikipedia.org/wiki/SHA1">SHA1</a> or <a
90 href="http://en.wikipedia.org/wiki/SHA3">SHA3-256</a> hash of the
91
--- www/fiveminutes.wiki
+++ www/fiveminutes.wiki
@@ -58,12 +58,12 @@
5858
<h2>Compare two revisions of a file</h2>
5959
<p>If you wish to compare the last revision of a file and its checked out version
6060
in your work directory:</p>
6161
<p>fossil gdiff myfile.c</p>
6262
<p>If you wish to compare two different revisions of a file in the repository:</p>
63
-<p>fossil finfo myfile: Note the first hash, which is the UUID of the commit
63
+<p>fossil finfo myfile: Note the first hash, which is the hash of the commit
6464
when the file was committed</p>
65
-<p>fossil gdiff --from UUID#1 --to UUID#2 myfile.c</p>
65
+<p>fossil gdiff --from HASH#1 --to HASH#2 myfile.c</p>
6666
<h2>Cancel changes and go back to previous revision</h2>
6767
<p>fossil revert myfile.c</p>
6868
<p>Fossil does not prompt when reverting a file. It simply reminds the user about the
6969
"undo" command, just in case the revert was a mistake.</p>
7070
--- www/fiveminutes.wiki
+++ www/fiveminutes.wiki
@@ -58,12 +58,12 @@
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 "undo" command, just in case the revert was a mistake.</p>
70
--- www/fiveminutes.wiki
+++ www/fiveminutes.wiki
@@ -58,12 +58,12 @@
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 hash of the commit
64 when the file was committed</p>
65 <p>fossil gdiff --from HASH#1 --to HASH#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 "undo" command, just in case the revert was a mistake.</p>
70
--- www/fossil-v-git.wiki
+++ www/fossil-v-git.wiki
@@ -40,22 +40,22 @@
4040
<td>VCS, tickets, wiki, docs, notes, forum, UI,
4141
[https://en.wikipedia.org/wiki/Role-based_access_control|RBAC]</td>
4242
<td><a href="#features">2.1&nbsp;&darr;</a></td>
4343
</tr>
4444
<tr>
45
- <td>Sprawling, incoherent, and inefficient</td>
45
+ <td>Sprawling and inefficient</td>
4646
<td>Self-contained and efficient</td>
4747
<td><a href="#efficient">2.2&nbsp;&darr;</a></td>
4848
</tr>
4949
<tr>
50
- <td>Ad-hoc pile-of-files key/value database</td>
50
+ <td>One-off custom pile-of-files data store</td>
5151
<td>[https://sqlite.org/famous.html|The most popular database in the world]</td>
5252
<td><a href="#durable">2.3&nbsp;&darr;</a></td>
5353
</tr>
5454
<tr>
55
- <td>Portable to POSIX systems only</td>
56
- <td>Runs just about anywhere</td>
55
+ <td>Runs natively on POSIX systems only</td>
56
+ <td>Native on common desktop & server platforms</td>
5757
<td><a href="#portable">2.4&nbsp;&darr;</a></td>
5858
</tr>
5959
<tr>
6060
<td>Bazaar-style development</td>
6161
<td>Cathedral-style development</td>
6262
--- www/fossil-v-git.wiki
+++ www/fossil-v-git.wiki
@@ -40,22 +40,22 @@
40 <td>VCS, tickets, wiki, docs, notes, forum, UI,
41 [https://en.wikipedia.org/wiki/Role-based_access_control|RBAC]</td>
42 <td><a href="#features">2.1&nbsp;&darr;</a></td>
43 </tr>
44 <tr>
45 <td>Sprawling, incoherent, and inefficient</td>
46 <td>Self-contained and efficient</td>
47 <td><a href="#efficient">2.2&nbsp;&darr;</a></td>
48 </tr>
49 <tr>
50 <td>Ad-hoc pile-of-files key/value database</td>
51 <td>[https://sqlite.org/famous.html|The most popular database in the world]</td>
52 <td><a href="#durable">2.3&nbsp;&darr;</a></td>
53 </tr>
54 <tr>
55 <td>Portable to POSIX systems only</td>
56 <td>Runs just about anywhere</td>
57 <td><a href="#portable">2.4&nbsp;&darr;</a></td>
58 </tr>
59 <tr>
60 <td>Bazaar-style development</td>
61 <td>Cathedral-style development</td>
62
--- www/fossil-v-git.wiki
+++ www/fossil-v-git.wiki
@@ -40,22 +40,22 @@
40 <td>VCS, tickets, wiki, docs, notes, forum, UI,
41 [https://en.wikipedia.org/wiki/Role-based_access_control|RBAC]</td>
42 <td><a href="#features">2.1&nbsp;&darr;</a></td>
43 </tr>
44 <tr>
45 <td>Sprawling and inefficient</td>
46 <td>Self-contained and efficient</td>
47 <td><a href="#efficient">2.2&nbsp;&darr;</a></td>
48 </tr>
49 <tr>
50 <td>One-off custom pile-of-files data store</td>
51 <td>[https://sqlite.org/famous.html|The most popular database in the world]</td>
52 <td><a href="#durable">2.3&nbsp;&darr;</a></td>
53 </tr>
54 <tr>
55 <td>Runs natively on POSIX systems only</td>
56 <td>Native on common desktop & server platforms</td>
57 <td><a href="#portable">2.4&nbsp;&darr;</a></td>
58 </tr>
59 <tr>
60 <td>Bazaar-style development</td>
61 <td>Cathedral-style development</td>
62
+90 -80
--- www/hashes.md
+++ www/hashes.md
@@ -1,145 +1,155 @@
11
# Hashes: Fossil Artifact Identification
22
33
All artifacts in Fossil are identified by a unique hash, currently using
44
[the SHA3 algorithm by default][hpol], but historically using the SHA1
5
-algorithm. Therefore, there are two full-length hash formats used by
6
-Fossil:
5
+algorithm:
76
8
-| Algorithm | Raw Bits | Hex ASCII Bytes |
9
-|-----------|----------|-----------------|
10
-| SHA3-256 | 256 | 64 |
11
-| SHA1 | 160 | 40 |
7
+<table border="1" cellspacing="0" cellpadding="10">
8
+<tr><th>Algorithm<</th><th>Raw Bits</th> <th>Hexadecimal digits</th></tr>
9
+<tr><td>SHA3-256</td> <td>256</td> <td>64</td></tr>
10
+<tr><td>SHA1</td> <td>160</td> <td>40</td></tr>
11
+</table>
1212
1313
There are many types of artifacts in Fossil: commits (a.k.a. check-ins),
1414
tickets, ticket comments, wiki articles, forum postings, file data
1515
belonging to check-ins, etc. ([More info...](./concepts.wiki#artifacts)).
1616
1717
There is a loose hierarchy of terms used instead of “hash” in various
18
-parts of the Fossil UI, terms we try to use consistently, though we have
19
-not always succeeded. We cover each of those terms in the sections
20
-below.
18
+parts of the Fossil UI, which we cover in the sections below.
2119
2220
2321
## Names
2422
2523
Several Fossil interfaces accept [a wide variety of check-in
2624
names][cin]: commit artifact hashes, ISO8601 date strings, branch names,
27
-etc.
25
+etc. Fossil interfaces that accept any of these options usually
26
+document the parameter as “NAME”, so we will use that form to refer to
27
+this specialized use.
2828
29
-Artifact hashes are names, but not all names are artifact hashes. We use
30
-the broader term to refer to the whole class of options, and we use the
31
-specific terms when we mean one particular type of name.
29
+Artifact hashes are only one of many different types of NAME. We use
30
+the broad term “NAME” to refer to the whole class of options. We use
31
+more specific terms when we mean one particular type of NAME.
3232
3333
3434
## Versions
3535
3636
When an artifact hash refers to a specific commit, Fossil sometimes
37
-calls it a “VERSION,” a “commit ID,” or a “check-in ID.” This is a
38
-specific type of artifact hash, distinct from, let us say, a wiki
39
-article artifact hash.
40
-
37
+calls it a “VERSION,” a “commit ID,” or a “check-in ID.”
4138
We may eventually settle on one of these terms, but all three are
4239
currently in common use within Fossil’s docs, UI, and programming
4340
interfaces.
41
+
42
+A VERSION is a specific type of artifact hash, distinct
43
+from, let us say, a wiki article artifact hash.
4444
4545
A unique prefix of a VERSION hash is itself a VERSION. That is, if your
4646
repository has exactly one commit artifact with a hash prefix of
4747
“abc123”, then that is a valid version string as long as it remains
4848
unambiguous.
4949
5050
5151
52
-## <a id="uvh"></a>UUIDs: An Unfortunate Historical Artifact
53
-
54
-Historically, Fossil incorrectly used the term “[UUID][uuid]” where it
55
-should use the term “artifact hash” instead. There are two primary
56
-problems with miscalling Fossil artifact hashes UUIDs:
57
-
58
-1. UUIDs are always 128 bits in length — 32 hex ASCII bytes — making
59
- them shorter than any actual Fossil artifact hash.
60
-
61
-2. Artifact hashes are necessarily highly pseudorandom blobs, but only
62
- [version 4 UUIDs][v4] are pseudorandom in the same way. Other UUID
63
- types have non-random meanings for certain subgroups of the bits,
64
- restrictions that Fossil artifact hashes do not meet.
65
-
66
-Therefore, no Fossil hash can ever be a proper UUID.
67
-
68
-Nevertheless, there are several places in Fossil where we still use the
69
-term UUID, primarily for backwards compatibility:
52
+## <a id="uvh"></a>UUIDs
53
+
54
+Fossil uses the term “UUID” as a short alias for “artifact hash” in its
55
+internals. There are a few places where this leaks out into external
56
+interfaces, which we cover in the sections below. Going forward, we
57
+prefer one of the terms above in public interfaces instead.
58
+
59
+Whether this short alias is correct is debateable.
60
+
61
+One argument is that since "UUID" is an acronym for “Univerially Unique
62
+Identifier,” and both SHA1 and SHA3-256 are larger and stronger than the
63
+128-bit algorithms used by “proper” UUIDs, Fossil artifact hashes are
64
+*more universally unique*. It is therefore quibbling to say that Fossil
65
+UUIDs are not actually UUIDs. One wag suggested that Fossil artifact
66
+hashes be called MUIDs: multiversally unique IDs.
67
+
68
+The common counterargument is that the acronym “UUID” was created for [a
69
+particular type of universally-unique ID][uuid], with particular ASCII
70
+and bitfield formats, and with particular meaning given to certain of
71
+its bits. In that sense, no Fossil “UUID” can be used as a proper UUID.
72
+
73
+Be warned: attempting to advance the second position on the Fossil
74
+discussion forum will get you nowhere at this late date. We’ve had the
75
+debates, we’ve done the engineering, and we’ve made our evaluation. It’s
76
+a settled matter: internally within Fossil, “UUID” is defined as in this
77
+section’s leading paragraph.
78
+
79
+To those who remain unconvinced, “fixing” this would require touching
80
+almost every source code file in Fossil in a total of about a thousand
81
+separate locations. (Not exaggeration, actual data.) This would be a
82
+massive undertaking simply to deal with a small matter of terminology,
83
+with a high risk of creating bugs and downstream incompatibilities.
84
+Therefore, we are highly unlikely to change this ourselves, and we are
85
+also unlikely to accept a patch that attempts to fix it.
7086
7187
7288
### Repository DB Schema
7389
74
-Almost all of these uses flow from the `blob.uuid` table column. This is
75
-a key lookup column in the most important persistent Fossil DB table, so
76
-it influences broad swaths of the Fossil internals.
77
-
78
-Someday we may rename this column and those it has influenced (e.g.
79
-`purgeitem.uuid`, `shun.uuid`, and `ticket.tkt_uuid`) by making Fossil
80
-detect the outdated schema and silently upgrade it, coincident with
81
-updating all of the SQL in Fossil that refers to these columns. Until
82
-then, Fossil will continue to have “UUID” all through its internals.
83
-
84
-In order to avoid needless terminology conflicts, Fossil code that
85
-refers to these misnamed columns also uses some variant of “UUID.” For
86
-example, C code that refers to SQL result data on `blob.uuid` usually
87
-calls the variable `zUuid`. Another example is the internal function
88
-`uuid_to_rid()`. Until and unless we decide to rename these DB columns,
89
-we will keep these associated internal identifiers unchanged.
90
+The primary place where you find "UUID" in Fossil is in the `blob.uuid`
91
+table column, in code dealing with that column, and in code manipulating
92
+*other* data that *refers* to that column. This is a key lookup column
93
+in the most important Fossil DB table, so it influences broad swaths of
94
+the Fossil internals.
95
+
96
+For example, C code that refers to SQL result data on `blob.uuid`
97
+usually calls the variable `zUuid`. That value may then be inserted into
98
+a table like `ticket.tkt_uuid`, creating a reference back to
99
+`blob.uuid`, and then be passed to a function like `uuid_to_rid()`.
100
+There is no point renaming a single one of these in isolation: it would
101
+create needless terminology conflicts, making the code hard to read and
102
+understand, risking the creation of new bugs.
90103
91104
You may have local SQL code that digs into the repository DB using these
92
-column names. If so, be warned: we are not inclined to consider
93
-existence of such code sufficient reason to avoid renaming the columns.
94
-The Fossil repository DB schema is not considered an external user
95
-interface, and internal interfaces are subject to change at any time. We
96
-suggest switching to a more stable API: the JSON API, `/timeline.rss`,
97
-TH1, etc.
98
-
99
-There are also some temporary tables that misuse “UUID” in this way.
100
-(`description.uuid`, `timeline.uuid`, `xmark.uuid`, etc.) There’s a good
101
-chance we’ll fix these before we fix the on-disk DB schema since no
102
-other code can depend on them.
105
+column names. While you may rest easy, assured now that we are highly
106
+unlikely to ever rename these columns, the Fossil repository DB schema
107
+is not considered an external user interface, and internal interfaces
108
+are subject to change at any time. We suggest switching to a more stable
109
+API: [the JSON API][japi], [`timeline.rss`][trss], [TH1][th1], etc.
103110
104111
105112
### TH1 Scripting Interfaces
106113
107
-Some [TH1](./th1.md) interfaces use “UUID” where they actually mean some
108
-kind of hash. For example, the `$tkt_uuid` variable, available via TH1
109
-when [customizing Fossil’s ticket system][ctkt].
110
-
111
-Because this is considered a public programming interface, we are
112
-unwilling to unilaterally rename such TH1 variables, even though they
113
-are “wrong.” For now, we are simply documenting the misuse. Later, we
114
-may provide a parallel interface — e.g. `$tkt_hash` in this case — and
115
-drop mention of the old interface from the documentation, but still
116
-support it.
114
+Some [TH1][th1] interfaces expose Fossil internals flowing from
115
+`blob.uuid`, so “UUID” is a short alias for “artifact hash” in TH1. For
116
+example, the `$tkt_uuid` variable &mdash; available when [customizing
117
+the ticket system][ctkt] &mdash; is a ticket artifact hash, exposing the
118
+`ticket.tkt_uuid` column, which has a SQL relation to `blob.uuid`.
119
+
120
+TH1 is a longstanding public programming interface. We cannot rename its
121
+interfaces without breaking existing TH1 Fossil customizations. We are
122
+also unlikely to provide a parallel set of variables with “better”
123
+names, since that would create a mismatch with respect to the internals
124
+they expose, creating a different sort of developer confusion in its
125
+place.
117126
118127
119128
### JSON API Parameters and Outputs
120129
121
-The JSON API frequently misuses the term “UUID” in the same sort of way,
122
-most commonly in [artifact][jart] and [timeline][jtim] APIs. As with the
123
-prior case, we can’t fix these without breaking code that uses the JSON
124
-API as originally designed, so our solutions are the same: document the
125
-misuse here for now, then possibly provide a backwards-compatible fix
126
-later.
130
+[The JSON API][japi] frequently uses the term “UUID” in the same sort of way,
131
+most commonly in [artifact][jart] and [timeline][jtim] APIs. As with
132
+TH1, we can’t change this without breaking code that uses the JSON
133
+API as originally designed, so we take the same stance.
127134
128135
129136
### `manifest.uuid`
130137
131138
If you have [the `manifest` setting][mset] enabled, Fossil writes a file
132139
called `manifest.uuid` at the root of the check-out tree containing the
133140
commit hash for the current checked-out version. Because this is a
134
-public interface, we are unwilling to rename the file for correctness.
141
+public interface that existing code depends on, we are unwilling to
142
+rename the file.
135143
136144
137145
[cin]: ./checkin_names.wiki
138146
[ctkt]: ./custom_ticket.wiki
139147
[hpol]: ./hashpolicy.wiki
148
+[japi]: ./json-api/
140149
[jart]: ./json-api/api-artifact.md
141150
[jtim]: ./json-api/api-timeline.md
142151
[mset]: /help?cmd=manifest
152
+[th1]: ./th1.md
153
+[trss]: /help?cmd=/timeline.rss
143154
[tvb]: ./branching.wiki
144155
[uuid]: https://en.wikipedia.org/wiki/Universally_unique_identifier
145
-[v4]: https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)
146156
--- www/hashes.md
+++ www/hashes.md
@@ -1,145 +1,155 @@
1 # Hashes: Fossil Artifact Identification
2
3 All artifacts in Fossil are identified by a unique hash, currently using
4 [the SHA3 algorithm by default][hpol], but historically using the SHA1
5 algorithm. Therefore, there are two full-length hash formats used by
6 Fossil:
7
8 | Algorithm | Raw Bits | Hex ASCII Bytes |
9 |-----------|----------|-----------------|
10 | SHA3-256 | 256 | 64 |
11 | SHA1 | 160 | 40 |
 
12
13 There are many types of artifacts in Fossil: commits (a.k.a. check-ins),
14 tickets, ticket comments, wiki articles, forum postings, file data
15 belonging to check-ins, etc. ([More info...](./concepts.wiki#artifacts)).
16
17 There is a loose hierarchy of terms used instead of “hash” in various
18 parts of the Fossil UI, terms we try to use consistently, though we have
19 not always succeeded. We cover each of those terms in the sections
20 below.
21
22
23 ## Names
24
25 Several Fossil interfaces accept [a wide variety of check-in
26 names][cin]: commit artifact hashes, ISO8601 date strings, branch names,
27 etc.
 
 
28
29 Artifact hashes are names, but not all names are artifact hashes. We use
30 the broader term to refer to the whole class of options, and we use the
31 specific terms when we mean one particular type of name.
32
33
34 ## Versions
35
36 When an artifact hash refers to a specific commit, Fossil sometimes
37 calls it a “VERSION,” a “commit ID,” or a “check-in ID.” This is a
38 specific type of artifact hash, distinct from, let us say, a wiki
39 article artifact hash.
40
41 We may eventually settle on one of these terms, but all three are
42 currently in common use within Fossil’s docs, UI, and programming
43 interfaces.
 
 
 
44
45 A unique prefix of a VERSION hash is itself a VERSION. That is, if your
46 repository has exactly one commit artifact with a hash prefix of
47 “abc123”, then that is a valid version string as long as it remains
48 unambiguous.
49
50
51
52 ## <a id="uvh"></a>UUIDs: An Unfortunate Historical Artifact
53
54 Historically, Fossil incorrectly used the term “[UUID][uuid]” where it
55 should use the term “artifact hash” instead. There are two primary
56 problems with miscalling Fossil artifact hashes UUIDs:
57
58 1. UUIDs are always 128 bits in length — 32 hex ASCII bytes — making
59 them shorter than any actual Fossil artifact hash.
60
61 2. Artifact hashes are necessarily highly pseudorandom blobs, but only
62 [version 4 UUIDs][v4] are pseudorandom in the same way. Other UUID
63 types have non-random meanings for certain subgroups of the bits,
64 restrictions that Fossil artifact hashes do not meet.
65
66 Therefore, no Fossil hash can ever be a proper UUID.
67
68 Nevertheless, there are several places in Fossil where we still use the
69 term UUID, primarily for backwards compatibility:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
71
72 ### Repository DB Schema
73
74 Almost all of these uses flow from the `blob.uuid` table column. This is
75 a key lookup column in the most important persistent Fossil DB table, so
76 it influences broad swaths of the Fossil internals.
77
78 Someday we may rename this column and those it has influenced (e.g.
79 `purgeitem.uuid`, `shun.uuid`, and `ticket.tkt_uuid`) by making Fossil
80 detect the outdated schema and silently upgrade it, coincident with
81 updating all of the SQL in Fossil that refers to these columns. Until
82 then, Fossil will continue to have “UUID” all through its internals.
83
84 In order to avoid needless terminology conflicts, Fossil code that
85 refers to these misnamed columns also uses some variant of “UUID.” For
86 example, C code that refers to SQL result data on `blob.uuid` usually
87 calls the variable `zUuid`. Another example is the internal function
88 `uuid_to_rid()`. Until and unless we decide to rename these DB columns,
89 we will keep these associated internal identifiers unchanged.
90
91 You may have local SQL code that digs into the repository DB using these
92 column names. If so, be warned: we are not inclined to consider
93 existence of such code sufficient reason to avoid renaming the columns.
94 The Fossil repository DB schema is not considered an external user
95 interface, and internal interfaces are subject to change at any time. We
96 suggest switching to a more stable API: the JSON API, `/timeline.rss`,
97 TH1, etc.
98
99 There are also some temporary tables that misuse “UUID” in this way.
100 (`description.uuid`, `timeline.uuid`, `xmark.uuid`, etc.) There’s a good
101 chance we’ll fix these before we fix the on-disk DB schema since no
102 other code can depend on them.
103
104
105 ### TH1 Scripting Interfaces
106
107 Some [TH1](./th1.md) interfaces use “UUID” where they actually mean some
108 kind of hash. For example, the `$tkt_uuid` variable, available via TH1
109 when [customizing Fossil’s ticket system][ctkt].
110
111 Because this is considered a public programming interface, we are
112 unwilling to unilaterally rename such TH1 variables, even though they
113 are “wrong.” For now, we are simply documenting the misuse. Later, we
114 may provide a parallel interface — e.g. `$tkt_hash` in this case — and
115 drop mention of the old interface from the documentation, but still
116 support it.
 
 
117
118
119 ### JSON API Parameters and Outputs
120
121 The JSON API frequently misuses the term “UUID” in the same sort of way,
122 most commonly in [artifact][jart] and [timeline][jtim] APIs. As with the
123 prior case, we can’t fix these without breaking code that uses the JSON
124 API as originally designed, so our solutions are the same: document the
125 misuse here for now, then possibly provide a backwards-compatible fix
126 later.
127
128
129 ### `manifest.uuid`
130
131 If you have [the `manifest` setting][mset] enabled, Fossil writes a file
132 called `manifest.uuid` at the root of the check-out tree containing the
133 commit hash for the current checked-out version. Because this is a
134 public interface, we are unwilling to rename the file for correctness.
 
135
136
137 [cin]: ./checkin_names.wiki
138 [ctkt]: ./custom_ticket.wiki
139 [hpol]: ./hashpolicy.wiki
 
140 [jart]: ./json-api/api-artifact.md
141 [jtim]: ./json-api/api-timeline.md
142 [mset]: /help?cmd=manifest
 
 
143 [tvb]: ./branching.wiki
144 [uuid]: https://en.wikipedia.org/wiki/Universally_unique_identifier
145 [v4]: https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)
146
--- www/hashes.md
+++ www/hashes.md
@@ -1,145 +1,155 @@
1 # Hashes: Fossil Artifact Identification
2
3 All artifacts in Fossil are identified by a unique hash, currently using
4 [the SHA3 algorithm by default][hpol], but historically using the SHA1
5 algorithm:
 
6
7 <table border="1" cellspacing="0" cellpadding="10">
8 <tr><th>Algorithm<</th><th>Raw Bits</th> <th>Hexadecimal digits</th></tr>
9 <tr><td>SHA3-256</td> <td>256</td> <td>64</td></tr>
10 <tr><td>SHA1</td> <td>160</td> <td>40</td></tr>
11 </table>
12
13 There are many types of artifacts in Fossil: commits (a.k.a. check-ins),
14 tickets, ticket comments, wiki articles, forum postings, file data
15 belonging to check-ins, etc. ([More info...](./concepts.wiki#artifacts)).
16
17 There is a loose hierarchy of terms used instead of “hash” in various
18 parts of the Fossil UI, which we cover in the sections below.
 
 
19
20
21 ## Names
22
23 Several Fossil interfaces accept [a wide variety of check-in
24 names][cin]: commit artifact hashes, ISO8601 date strings, branch names,
25 etc. Fossil interfaces that accept any of these options usually
26 document the parameter as “NAME”, so we will use that form to refer to
27 this specialized use.
28
29 Artifact hashes are only one of many different types of NAME. We use
30 the broad term “NAME” to refer to the whole class of options. We use
31 more specific terms when we mean one particular type of NAME.
32
33
34 ## Versions
35
36 When an artifact hash refers to a specific commit, Fossil sometimes
37 calls it a “VERSION,” a “commit ID,” or a “check-in ID.”
 
 
 
38 We may eventually settle on one of these terms, but all three are
39 currently in common use within Fossil’s docs, UI, and programming
40 interfaces.
41
42 A VERSION is a specific type of artifact hash, distinct
43 from, let us say, a wiki article artifact hash.
44
45 A unique prefix of a VERSION hash is itself a VERSION. That is, if your
46 repository has exactly one commit artifact with a hash prefix of
47 “abc123”, then that is a valid version string as long as it remains
48 unambiguous.
49
50
51
52 ## <a id="uvh"></a>UUIDs
53
54 Fossil uses the term “UUID” as a short alias for “artifact hash” in its
55 internals. There are a few places where this leaks out into external
56 interfaces, which we cover in the sections below. Going forward, we
57 prefer one of the terms above in public interfaces instead.
58
59 Whether this short alias is correct is debateable.
60
61 One argument is that since "UUID" is an acronym for “Univerially Unique
62 Identifier,” and both SHA1 and SHA3-256 are larger and stronger than the
63 128-bit algorithms used by “proper” UUIDs, Fossil artifact hashes are
64 *more universally unique*. It is therefore quibbling to say that Fossil
65 UUIDs are not actually UUIDs. One wag suggested that Fossil artifact
66 hashes be called MUIDs: multiversally unique IDs.
67
68 The common counterargument is that the acronym “UUID” was created for [a
69 particular type of universally-unique ID][uuid], with particular ASCII
70 and bitfield formats, and with particular meaning given to certain of
71 its bits. In that sense, no Fossil “UUID” can be used as a proper UUID.
72
73 Be warned: attempting to advance the second position on the Fossil
74 discussion forum will get you nowhere at this late date. We’ve had the
75 debates, we’ve done the engineering, and we’ve made our evaluation. It’s
76 a settled matter: internally within Fossil, “UUID” is defined as in this
77 section’s leading paragraph.
78
79 To those who remain unconvinced, “fixing” this would require touching
80 almost every source code file in Fossil in a total of about a thousand
81 separate locations. (Not exaggeration, actual data.) This would be a
82 massive undertaking simply to deal with a small matter of terminology,
83 with a high risk of creating bugs and downstream incompatibilities.
84 Therefore, we are highly unlikely to change this ourselves, and we are
85 also unlikely to accept a patch that attempts to fix it.
86
87
88 ### Repository DB Schema
89
90 The primary place where you find "UUID" in Fossil is in the `blob.uuid`
91 table column, in code dealing with that column, and in code manipulating
92 *other* data that *refers* to that column. This is a key lookup column
93 in the most important Fossil DB table, so it influences broad swaths of
94 the Fossil internals.
95
96 For example, C code that refers to SQL result data on `blob.uuid`
97 usually calls the variable `zUuid`. That value may then be inserted into
98 a table like `ticket.tkt_uuid`, creating a reference back to
99 `blob.uuid`, and then be passed to a function like `uuid_to_rid()`.
100 There is no point renaming a single one of these in isolation: it would
101 create needless terminology conflicts, making the code hard to read and
102 understand, risking the creation of new bugs.
 
 
 
103
104 You may have local SQL code that digs into the repository DB using these
105 column names. While you may rest easy, assured now that we are highly
106 unlikely to ever rename these columns, the Fossil repository DB schema
107 is not considered an external user interface, and internal interfaces
108 are subject to change at any time. We suggest switching to a more stable
109 API: [the JSON API][japi], [`timeline.rss`][trss], [TH1][th1], etc.
 
 
 
 
 
 
110
111
112 ### TH1 Scripting Interfaces
113
114 Some [TH1][th1] interfaces expose Fossil internals flowing from
115 `blob.uuid`, so “UUID” is a short alias for “artifact hash” in TH1. For
116 example, the `$tkt_uuid` variable &mdash; available when [customizing
117 the ticket system][ctkt] &mdash; is a ticket artifact hash, exposing the
118 `ticket.tkt_uuid` column, which has a SQL relation to `blob.uuid`.
119
120 TH1 is a longstanding public programming interface. We cannot rename its
121 interfaces without breaking existing TH1 Fossil customizations. We are
122 also unlikely to provide a parallel set of variables with “better”
123 names, since that would create a mismatch with respect to the internals
124 they expose, creating a different sort of developer confusion in its
125 place.
126
127
128 ### JSON API Parameters and Outputs
129
130 [The JSON API][japi] frequently uses the term “UUID” in the same sort of way,
131 most commonly in [artifact][jart] and [timeline][jtim] APIs. As with
132 TH1, we can’t change this without breaking code that uses the JSON
133 API as originally designed, so we take the same stance.
 
 
134
135
136 ### `manifest.uuid`
137
138 If you have [the `manifest` setting][mset] enabled, Fossil writes a file
139 called `manifest.uuid` at the root of the check-out tree containing the
140 commit hash for the current checked-out version. Because this is a
141 public interface that existing code depends on, we are unwilling to
142 rename the file.
143
144
145 [cin]: ./checkin_names.wiki
146 [ctkt]: ./custom_ticket.wiki
147 [hpol]: ./hashpolicy.wiki
148 [japi]: ./json-api/
149 [jart]: ./json-api/api-artifact.md
150 [jtim]: ./json-api/api-timeline.md
151 [mset]: /help?cmd=manifest
152 [th1]: ./th1.md
153 [trss]: /help?cmd=/timeline.rss
154 [tvb]: ./branching.wiki
155 [uuid]: https://en.wikipedia.org/wiki/Universally_unique_identifier
 
156
--- www/json-api/api-artifact.md
+++ www/json-api/api-artifact.md
@@ -14,11 +14,11 @@
1414
1515
Returns information about checkin artifacts (commits).
1616
1717
**Status:** implemented 201110xx
1818
19
-**Request:** `/json/artifact/COMMIT_UUID`
19
+**Request:** `/json/artifact/COMMIT_HASH`
2020
2121
**Required permissions:** "o" (was "h" prior to 20120408)
2222
2323
**Response payload example: (CHANGED SIGNIFICANTLY ON 20120713)**
2424
@@ -30,43 +30,44 @@
3030
"isLeaf":false,
3131
"user":"drh",
3232
"comment":"Merge wideAnnotateUser and jsonWarnings into trunk.",
3333
"timestamp":1330090810,
3434
"parents":[
35
- // 1st entry is primary parent UUID:
35
+ // 1st entry is primary parent hash:
3636
"3a44f95f40a193739aaafc2409f155df43e74a6f",
37
- // Remaining entries are merged-in branch UUIDs:
37
+ // Remaining entries are merged-in branch hashes:
3838
"86f6e675eb3f8761d70d8b82b052ce2b297fffd2",\
3939
"dbf4ecf414881c9aad6f4f125dab9762589ef3d7"\
4040
],
4141
"tags":["trunk"],
4242
"files":[{
4343
"name":"src/diff.c",
44
- // BLOB uuids, NOT commit UUIDs:
44
+ // BLOB hashes, NOT commit hashes:
4545
"uuid":"78c74c3b37e266f8f7e570d5cf476854b7af9d76",
4646
"parent":"b1fa7e636cf4e7b6ed20bba2d2680397f80c096a",
4747
"state":"modified",
4848
"downloadPath":"/raw/src/diff.c?name=78c74c3b37e266f8f7e570d5cf476854b7af9d76"
4949
},
5050
...]
5151
}
5252
```
5353
54
-The "parents" property lists the parent UUIDs of the checkin. The
55
-"parent" property of file entries refers to the parent UUID of that
54
+The "parents" property lists the parent hashes of the checkin. The
55
+"parent" property of file entries refers to the parent hash of that
5656
file. In the case of a merge there may be essentially an arbitrary
5757
number. The first entry in the list is the "primary" parent. The primary
5858
parent is the parent which was not pulled in via a merge operation. The
5959
ordering of remaining entries is unspecified and may even change between
6060
calls. For example: if, from branch C, we merge in A and B and then
61
-commit, then in the artifact response for that commit the UUID of branch
62
-C will be in the first (primary) position, with the UUIDs for branches A
61
+commit, then in the artifact response for that commit the hash of branch
62
+C will be in the first (primary) position, with the hashes for branches A
6363
and B in the following entries (in an unspecified, and possibly
6464
unstable, order).
6565
6666
Note that the "uuid" and "parent" properties of the "files" entries
67
-refer to raw blob uuids, not commit uuids (i.e. not checkins).
67
+refer to raw blob hashes, not commit (a.k.a. check-in) hashes. See also
68
+[the UUID vs. Hash discussion][uvh].
6869
6970
<a id="file"></a>
7071
# File Artifacts
7172
7273
Fetches information about file artifacts.
@@ -77,11 +78,11 @@
7778
7879
**Status:** implemented 20111020
7980
8081
**Required permissions:** "o"
8182
82
-**Request:** `/json/artifact/FILE_UUID`
83
+**Request:** `/json/artifact/FILE_HASH`
8384
8485
**Request options:**
8586
8687
- `format=(raw|html|none)` (default=none). If set, the contents of the
8788
artifact are included if they are text, else they are not (JSON does
@@ -98,13 +99,13 @@
9899
**Response payload example: (CHANGED SIGNIFICANTLY ON 20120713)**
99100
100101
```json
101102
{
102103
"type":"file",
103
-"name":"same name specified as FILE_UUID argument",
104
+"name":"same name specified as FILE_HASH argument",
104105
"size": 12345, // in bytes, independent of format=...
105
-"parent": "uuid of parent file blob. Not set for first generation.",
106
+"parent": "hash of parent file blob. Not set for first generation.",
106107
"checkins":[{
107108
"name":"src/json_detail.h",
108109
"timestamp":1319058803,
109110
"comment":"...",
110111
"user":"stephan",
@@ -121,21 +122,21 @@
121122
}
122123
```
123124
124125
The "checkins" array lists all checkins which include this file, and a
125126
file might have different names across different branches. The size and
126
-uuid, however, are the same across all checkins for a given blob.
127
+hash, however, are the same across all checkins for a given blob.
127128
128129
<a id="wiki"></a>
129130
# Wiki Artifacts
130131
131132
Returns information about wiki artifacts.
132133
133134
**Status:** implemented 20111020, fixed to return the requested version
134135
(instead of the latest) on 20120302.
135136
136
-**Request:** `/json/artifact/WIKI_UUID`
137
+**Request:** `/json/artifact/WIKI_HASH`
137138
138139
**Required permissions:** "j"
139140
140141
**Options:**
141142
@@ -149,5 +150,6 @@
149150
150151
**Response payload example:**
151152
152153
Currently the same as [`/json/wiki/get`](api-wiki.md#get).
153154
155
+[uvh]: ../hashes.md#uvh
154156
--- www/json-api/api-artifact.md
+++ www/json-api/api-artifact.md
@@ -14,11 +14,11 @@
14
15 Returns information about checkin artifacts (commits).
16
17 **Status:** implemented 201110xx
18
19 **Request:** `/json/artifact/COMMIT_UUID`
20
21 **Required permissions:** "o" (was "h" prior to 20120408)
22
23 **Response payload example: (CHANGED SIGNIFICANTLY ON 20120713)**
24
@@ -30,43 +30,44 @@
30 "isLeaf":false,
31 "user":"drh",
32 "comment":"Merge wideAnnotateUser and jsonWarnings into trunk.",
33 "timestamp":1330090810,
34 "parents":[
35 // 1st entry is primary parent UUID:
36 "3a44f95f40a193739aaafc2409f155df43e74a6f",
37 // Remaining entries are merged-in branch UUIDs:
38 "86f6e675eb3f8761d70d8b82b052ce2b297fffd2",\
39 "dbf4ecf414881c9aad6f4f125dab9762589ef3d7"\
40 ],
41 "tags":["trunk"],
42 "files":[{
43 "name":"src/diff.c",
44 // BLOB uuids, NOT commit UUIDs:
45 "uuid":"78c74c3b37e266f8f7e570d5cf476854b7af9d76",
46 "parent":"b1fa7e636cf4e7b6ed20bba2d2680397f80c096a",
47 "state":"modified",
48 "downloadPath":"/raw/src/diff.c?name=78c74c3b37e266f8f7e570d5cf476854b7af9d76"
49 },
50 ...]
51 }
52 ```
53
54 The "parents" property lists the parent UUIDs of the checkin. The
55 "parent" property of file entries refers to the parent UUID of that
56 file. In the case of a merge there may be essentially an arbitrary
57 number. The first entry in the list is the "primary" parent. The primary
58 parent is the parent which was not pulled in via a merge operation. The
59 ordering of remaining entries is unspecified and may even change between
60 calls. For example: if, from branch C, we merge in A and B and then
61 commit, then in the artifact response for that commit the UUID of branch
62 C will be in the first (primary) position, with the UUIDs for branches A
63 and B in the following entries (in an unspecified, and possibly
64 unstable, order).
65
66 Note that the "uuid" and "parent" properties of the "files" entries
67 refer to raw blob uuids, not commit uuids (i.e. not checkins).
 
68
69 <a id="file"></a>
70 # File Artifacts
71
72 Fetches information about file artifacts.
@@ -77,11 +78,11 @@
77
78 **Status:** implemented 20111020
79
80 **Required permissions:** "o"
81
82 **Request:** `/json/artifact/FILE_UUID`
83
84 **Request options:**
85
86 - `format=(raw|html|none)` (default=none). If set, the contents of the
87 artifact are included if they are text, else they are not (JSON does
@@ -98,13 +99,13 @@
98 **Response payload example: (CHANGED SIGNIFICANTLY ON 20120713)**
99
100 ```json
101 {
102 "type":"file",
103 "name":"same name specified as FILE_UUID argument",
104 "size": 12345, // in bytes, independent of format=...
105 "parent": "uuid of parent file blob. Not set for first generation.",
106 "checkins":[{
107 "name":"src/json_detail.h",
108 "timestamp":1319058803,
109 "comment":"...",
110 "user":"stephan",
@@ -121,21 +122,21 @@
121 }
122 ```
123
124 The "checkins" array lists all checkins which include this file, and a
125 file might have different names across different branches. The size and
126 uuid, however, are the same across all checkins for a given blob.
127
128 <a id="wiki"></a>
129 # Wiki Artifacts
130
131 Returns information about wiki artifacts.
132
133 **Status:** implemented 20111020, fixed to return the requested version
134 (instead of the latest) on 20120302.
135
136 **Request:** `/json/artifact/WIKI_UUID`
137
138 **Required permissions:** "j"
139
140 **Options:**
141
@@ -149,5 +150,6 @@
149
150 **Response payload example:**
151
152 Currently the same as [`/json/wiki/get`](api-wiki.md#get).
153
 
154
--- www/json-api/api-artifact.md
+++ www/json-api/api-artifact.md
@@ -14,11 +14,11 @@
14
15 Returns information about checkin artifacts (commits).
16
17 **Status:** implemented 201110xx
18
19 **Request:** `/json/artifact/COMMIT_HASH`
20
21 **Required permissions:** "o" (was "h" prior to 20120408)
22
23 **Response payload example: (CHANGED SIGNIFICANTLY ON 20120713)**
24
@@ -30,43 +30,44 @@
30 "isLeaf":false,
31 "user":"drh",
32 "comment":"Merge wideAnnotateUser and jsonWarnings into trunk.",
33 "timestamp":1330090810,
34 "parents":[
35 // 1st entry is primary parent hash:
36 "3a44f95f40a193739aaafc2409f155df43e74a6f",
37 // Remaining entries are merged-in branch hashes:
38 "86f6e675eb3f8761d70d8b82b052ce2b297fffd2",\
39 "dbf4ecf414881c9aad6f4f125dab9762589ef3d7"\
40 ],
41 "tags":["trunk"],
42 "files":[{
43 "name":"src/diff.c",
44 // BLOB hashes, NOT commit hashes:
45 "uuid":"78c74c3b37e266f8f7e570d5cf476854b7af9d76",
46 "parent":"b1fa7e636cf4e7b6ed20bba2d2680397f80c096a",
47 "state":"modified",
48 "downloadPath":"/raw/src/diff.c?name=78c74c3b37e266f8f7e570d5cf476854b7af9d76"
49 },
50 ...]
51 }
52 ```
53
54 The "parents" property lists the parent hashes of the checkin. The
55 "parent" property of file entries refers to the parent hash of that
56 file. In the case of a merge there may be essentially an arbitrary
57 number. The first entry in the list is the "primary" parent. The primary
58 parent is the parent which was not pulled in via a merge operation. The
59 ordering of remaining entries is unspecified and may even change between
60 calls. For example: if, from branch C, we merge in A and B and then
61 commit, then in the artifact response for that commit the hash of branch
62 C will be in the first (primary) position, with the hashes for branches A
63 and B in the following entries (in an unspecified, and possibly
64 unstable, order).
65
66 Note that the "uuid" and "parent" properties of the "files" entries
67 refer to raw blob hashes, not commit (a.k.a. check-in) hashes. See also
68 [the UUID vs. Hash discussion][uvh].
69
70 <a id="file"></a>
71 # File Artifacts
72
73 Fetches information about file artifacts.
@@ -77,11 +78,11 @@
78
79 **Status:** implemented 20111020
80
81 **Required permissions:** "o"
82
83 **Request:** `/json/artifact/FILE_HASH`
84
85 **Request options:**
86
87 - `format=(raw|html|none)` (default=none). If set, the contents of the
88 artifact are included if they are text, else they are not (JSON does
@@ -98,13 +99,13 @@
99 **Response payload example: (CHANGED SIGNIFICANTLY ON 20120713)**
100
101 ```json
102 {
103 "type":"file",
104 "name":"same name specified as FILE_HASH argument",
105 "size": 12345, // in bytes, independent of format=...
106 "parent": "hash of parent file blob. Not set for first generation.",
107 "checkins":[{
108 "name":"src/json_detail.h",
109 "timestamp":1319058803,
110 "comment":"...",
111 "user":"stephan",
@@ -121,21 +122,21 @@
122 }
123 ```
124
125 The "checkins" array lists all checkins which include this file, and a
126 file might have different names across different branches. The size and
127 hash, however, are the same across all checkins for a given blob.
128
129 <a id="wiki"></a>
130 # Wiki Artifacts
131
132 Returns information about wiki artifacts.
133
134 **Status:** implemented 20111020, fixed to return the requested version
135 (instead of the latest) on 20120302.
136
137 **Request:** `/json/artifact/WIKI_HASH`
138
139 **Required permissions:** "j"
140
141 **Options:**
142
@@ -149,5 +150,6 @@
150
151 **Response payload example:**
152
153 Currently the same as [`/json/wiki/get`](api-wiki.md#get).
154
155 [uvh]: ../hashes.md#uvh
156
--- www/json-api/api-diff.md
+++ www/json-api/api-diff.md
@@ -33,12 +33,12 @@
3333
}
3434
```
3535
3636
TODOs:
3737
38
-- Unlike the standard diff command, which apparently requires commit
39
- UUID, this one diffs individual file versions. If a commit UUID is
38
+- Unlike the standard diff command, which apparently requires a commit
39
+ hash, this one diffs individual file versions. If a commit hash is
4040
provided, a diff of the manifests is returned. (That should be
4141
considered a bug - we should return a combined diff in that case.)
42
-- If UUIDs from two different types of artifacts are given, results
42
+- If hashes from two different types of artifacts are given, results
4343
are unspecified. Garbage in, garbage out, and all that.
4444
- For file diffs, add the file name(s) to the response payload.
4545
--- www/json-api/api-diff.md
+++ www/json-api/api-diff.md
@@ -33,12 +33,12 @@
33 }
34 ```
35
36 TODOs:
37
38 - Unlike the standard diff command, which apparently requires commit
39 UUID, this one diffs individual file versions. If a commit UUID is
40 provided, a diff of the manifests is returned. (That should be
41 considered a bug - we should return a combined diff in that case.)
42 - If UUIDs from two different types of artifacts are given, results
43 are unspecified. Garbage in, garbage out, and all that.
44 - For file diffs, add the file name(s) to the response payload.
45
--- www/json-api/api-diff.md
+++ www/json-api/api-diff.md
@@ -33,12 +33,12 @@
33 }
34 ```
35
36 TODOs:
37
38 - Unlike the standard diff command, which apparently requires a commit
39 hash, this one diffs individual file versions. If a commit hash is
40 provided, a diff of the manifests is returned. (That should be
41 considered a bug - we should return a combined diff in that case.)
42 - If hashes from two different types of artifacts are given, results
43 are unspecified. Garbage in, garbage out, and all that.
44 - For file diffs, add the file name(s) to the response payload.
45
--- www/json-api/api-tag.md
+++ www/json-api/api-tag.md
@@ -47,12 +47,12 @@
4747
"raw":false,
4848
"appliedTo":"626ab2f3743543122cc11bc082a0603d2b5b2b1b"
4949
}
5050
```
5151
52
-The appliedTo property is the UUID of the checkin to which the tag was
53
-applied. This is the "resolved" version of the checkin name provided by
52
+The `appliedTo` property is the hash of the check-in to which the tag was
53
+applied. This is the "resolved" version of the check-in name provided by
5454
the client.
5555
5656
<a id="cancel"></a>
5757
# Cancel Tag
5858
@@ -99,12 +99,13 @@
9999
- `limit=int` (defalt=0) Limits the number of results (0=no limit).
100100
Since they are ordered from oldest to newest, the newest N results
101101
will be returned.
102102
- `type=string` (default=`*`) Searches only for the given type of
103103
artifact (using fossil's conventional type naming: ci, e, t, w.
104
-- `raw=bool` (=false) If enabled, the response is an array of UUID
105
- strings, else it is an array of higher-level objects. If this is
104
+- `raw=bool` (=false) If enabled, the response is an array of hashes
105
+ of the requested artifact type; otherwise,
106
+ it is an array of higher-level objects. If this is
106107
true, the "name" property is interpretted as-is. If it is false, the
107108
name is automatically prepended with "sym-" (meaning a branch).
108109
(FIXME: the current semantics are confusing and hard to remember.
109110
Re-do them.)
110111
111112
--- www/json-api/api-tag.md
+++ www/json-api/api-tag.md
@@ -47,12 +47,12 @@
47 "raw":false,
48 "appliedTo":"626ab2f3743543122cc11bc082a0603d2b5b2b1b"
49 }
50 ```
51
52 The appliedTo property is the UUID of the checkin to which the tag was
53 applied. This is the "resolved" version of the checkin name provided by
54 the client.
55
56 <a id="cancel"></a>
57 # Cancel Tag
58
@@ -99,12 +99,13 @@
99 - `limit=int` (defalt=0) Limits the number of results (0=no limit).
100 Since they are ordered from oldest to newest, the newest N results
101 will be returned.
102 - `type=string` (default=`*`) Searches only for the given type of
103 artifact (using fossil's conventional type naming: ci, e, t, w.
104 - `raw=bool` (=false) If enabled, the response is an array of UUID
105 strings, else it is an array of higher-level objects. If this is
 
106 true, the "name" property is interpretted as-is. If it is false, the
107 name is automatically prepended with "sym-" (meaning a branch).
108 (FIXME: the current semantics are confusing and hard to remember.
109 Re-do them.)
110
111
--- www/json-api/api-tag.md
+++ www/json-api/api-tag.md
@@ -47,12 +47,12 @@
47 "raw":false,
48 "appliedTo":"626ab2f3743543122cc11bc082a0603d2b5b2b1b"
49 }
50 ```
51
52 The `appliedTo` property is the hash of the check-in to which the tag was
53 applied. This is the "resolved" version of the check-in name provided by
54 the client.
55
56 <a id="cancel"></a>
57 # Cancel Tag
58
@@ -99,12 +99,13 @@
99 - `limit=int` (defalt=0) Limits the number of results (0=no limit).
100 Since they are ordered from oldest to newest, the newest N results
101 will be returned.
102 - `type=string` (default=`*`) Searches only for the given type of
103 artifact (using fossil's conventional type naming: ci, e, t, w.
104 - `raw=bool` (=false) If enabled, the response is an array of hashes
105 of the requested artifact type; otherwise,
106 it is an array of higher-level objects. If this is
107 true, the "name" property is interpretted as-is. If it is false, the
108 name is automatically prepended with "sym-" (meaning a branch).
109 (FIXME: the current semantics are confusing and hard to remember.
110 Re-do them.)
111
112
--- www/json-api/api-timeline.md
+++ www/json-api/api-timeline.md
@@ -79,11 +79,11 @@
7979
"comment":"Added /json/timeline/ci showFiles to ajax test page.",
8080
"user":"stephan",
8181
"isLeaf":true,
8282
"bgColor":null, /* not quite sure why this is null? */
8383
"type":"ci",
84
- "parents": ["primary parent UUID", "...other parent UUIDs"],
84
+ "parents": ["primary parent hash", "...other parent hashes"],
8585
"tags":["json"],
8686
"files":[{
8787
"name":"ajax/index.html",
8888
"uuid":"9f00773a94cea6191dc3289aa24c0811b6d0d8fe",
8989
"parent":"50e337c33c27529e08a7037a8679fb84b976ad0b",
@@ -101,12 +101,12 @@
101101
102102
**Request options:**
103103
104104
- `files=bool` toggles the addition of a "files" array property which
105105
contains objects describing the files changed by the commit,
106
- including their uuid, previous uuid, and state change type
107
- (modified, added, or removed).\
106
+ including their hash, previous hash, and state change type
107
+ (modified, added, or removed). ([“uuid” here means hash][uvh])\
108108
CLI mode: `--show-files|-f`
109109
- `tag|branch=string` selects only entries with the given tag or "close
110110
to" the given branch. Only one of these may be specified and if both
111111
are specified, which one takes precedence is unspecified. If the
112112
given tag/branch does not exist, an error response is generated. The
@@ -172,15 +172,15 @@
172172
"ticketUuid":"b64435dba9cceb709bd54fbc5883884d73f93491"
173173
},...]
174174
}
175175
```
176176
177
-**Notice that there are two UUIDs for tickets** - `uuid` is the change
178
-UUID and `ticketUuid` is the actual ticket. This is an unfortunate
177
+**Notice that there are two [hashes][uvh] for tickets** - `uuid` is the change
178
+hash and `ticketUuid` is the actual ticket’s hash. This is an unfortunate
179179
discrepancy vis-a-vis the other timeline entries, which only have one
180
-uuid. We may want to swap uuid to mean the ticket uuid and change uuid
181
-to commitUuid.
180
+hash. We may want to swap `uuid` to mean the ticket hash and change `uuid`
181
+to `commitHash`.
182182
183183
<a id="wiki"></a>
184184
# Wiki Timeline
185185
186186
**Status:** implemented 201109xx
@@ -206,8 +206,9 @@
206206
},...]
207207
}
208208
```
209209
210210
The `uuid` of each entry can be passed to `/json/artifact` or
211
-`/json/wiki/get?uuid=...` to fetch the raw page and the uuid of the
211
+`/json/wiki/get?uuid=...` to fetch the raw page and the hash of the
212212
parent version.
213213
214
+[uvh]: ../hashes.md#uvh
214215
--- www/json-api/api-timeline.md
+++ www/json-api/api-timeline.md
@@ -79,11 +79,11 @@
79 "comment":"Added /json/timeline/ci showFiles to ajax test page.",
80 "user":"stephan",
81 "isLeaf":true,
82 "bgColor":null, /* not quite sure why this is null? */
83 "type":"ci",
84 "parents": ["primary parent UUID", "...other parent UUIDs"],
85 "tags":["json"],
86 "files":[{
87 "name":"ajax/index.html",
88 "uuid":"9f00773a94cea6191dc3289aa24c0811b6d0d8fe",
89 "parent":"50e337c33c27529e08a7037a8679fb84b976ad0b",
@@ -101,12 +101,12 @@
101
102 **Request options:**
103
104 - `files=bool` toggles the addition of a "files" array property which
105 contains objects describing the files changed by the commit,
106 including their uuid, previous uuid, and state change type
107 (modified, added, or removed).\
108 CLI mode: `--show-files|-f`
109 - `tag|branch=string` selects only entries with the given tag or "close
110 to" the given branch. Only one of these may be specified and if both
111 are specified, which one takes precedence is unspecified. If the
112 given tag/branch does not exist, an error response is generated. The
@@ -172,15 +172,15 @@
172 "ticketUuid":"b64435dba9cceb709bd54fbc5883884d73f93491"
173 },...]
174 }
175 ```
176
177 **Notice that there are two UUIDs for tickets** - `uuid` is the change
178 UUID and `ticketUuid` is the actual ticket. This is an unfortunate
179 discrepancy vis-a-vis the other timeline entries, which only have one
180 uuid. We may want to swap uuid to mean the ticket uuid and change uuid
181 to commitUuid.
182
183 <a id="wiki"></a>
184 # Wiki Timeline
185
186 **Status:** implemented 201109xx
@@ -206,8 +206,9 @@
206 },...]
207 }
208 ```
209
210 The `uuid` of each entry can be passed to `/json/artifact` or
211 `/json/wiki/get?uuid=...` to fetch the raw page and the uuid of the
212 parent version.
213
 
214
--- www/json-api/api-timeline.md
+++ www/json-api/api-timeline.md
@@ -79,11 +79,11 @@
79 "comment":"Added /json/timeline/ci showFiles to ajax test page.",
80 "user":"stephan",
81 "isLeaf":true,
82 "bgColor":null, /* not quite sure why this is null? */
83 "type":"ci",
84 "parents": ["primary parent hash", "...other parent hashes"],
85 "tags":["json"],
86 "files":[{
87 "name":"ajax/index.html",
88 "uuid":"9f00773a94cea6191dc3289aa24c0811b6d0d8fe",
89 "parent":"50e337c33c27529e08a7037a8679fb84b976ad0b",
@@ -101,12 +101,12 @@
101
102 **Request options:**
103
104 - `files=bool` toggles the addition of a "files" array property which
105 contains objects describing the files changed by the commit,
106 including their hash, previous hash, and state change type
107 (modified, added, or removed). ([“uuid” here means hash][uvh])\
108 CLI mode: `--show-files|-f`
109 - `tag|branch=string` selects only entries with the given tag or "close
110 to" the given branch. Only one of these may be specified and if both
111 are specified, which one takes precedence is unspecified. If the
112 given tag/branch does not exist, an error response is generated. The
@@ -172,15 +172,15 @@
172 "ticketUuid":"b64435dba9cceb709bd54fbc5883884d73f93491"
173 },...]
174 }
175 ```
176
177 **Notice that there are two [hashes][uvh] for tickets** - `uuid` is the change
178 hash and `ticketUuid` is the actual ticket’s hash. This is an unfortunate
179 discrepancy vis-a-vis the other timeline entries, which only have one
180 hash. We may want to swap `uuid` to mean the ticket hash and change `uuid`
181 to `commitHash`.
182
183 <a id="wiki"></a>
184 # Wiki Timeline
185
186 **Status:** implemented 201109xx
@@ -206,8 +206,9 @@
206 },...]
207 }
208 ```
209
210 The `uuid` of each entry can be passed to `/json/artifact` or
211 `/json/wiki/get?uuid=...` to fetch the raw page and the hash of the
212 parent version.
213
214 [uvh]: ../hashes.md#uvh
215
--- www/json-api/conventions.md
+++ www/json-api/conventions.md
@@ -584,11 +584,12 @@
584584
- `FOSSIL-3001`: Invalid argument/parameter type(s) or value(s) in
585585
request
586586
- `FOSSIL-3002`: Required argument(s)/parameter(s) missing from
587587
request
588588
- `FOSSIL-3003`: Requested resource identifier is ambiguous (e.g. a
589
- shortened UUID can be ambiguous).
589
+ shortened hash that matches multiple artifacts, an abbreviated
590
+ date that matches multiple commits, etc.)
590591
- `FOSSIL-3004`: Unresolved resource identifier. A branch/tag/uuid
591592
provided by client code could not be resolved. This is a special
592593
case of #3006.
593594
- `FOSSIL-3005`: Resource already exists and overwriting/replacing is
594595
not allowed. e.g. trying to create a wiki page or user which already
595596
--- www/json-api/conventions.md
+++ www/json-api/conventions.md
@@ -584,11 +584,12 @@
584 - `FOSSIL-3001`: Invalid argument/parameter type(s) or value(s) in
585 request
586 - `FOSSIL-3002`: Required argument(s)/parameter(s) missing from
587 request
588 - `FOSSIL-3003`: Requested resource identifier is ambiguous (e.g. a
589 shortened UUID can be ambiguous).
 
590 - `FOSSIL-3004`: Unresolved resource identifier. A branch/tag/uuid
591 provided by client code could not be resolved. This is a special
592 case of #3006.
593 - `FOSSIL-3005`: Resource already exists and overwriting/replacing is
594 not allowed. e.g. trying to create a wiki page or user which already
595
--- www/json-api/conventions.md
+++ www/json-api/conventions.md
@@ -584,11 +584,12 @@
584 - `FOSSIL-3001`: Invalid argument/parameter type(s) or value(s) in
585 request
586 - `FOSSIL-3002`: Required argument(s)/parameter(s) missing from
587 request
588 - `FOSSIL-3003`: Requested resource identifier is ambiguous (e.g. a
589 shortened hash that matches multiple artifacts, an abbreviated
590 date that matches multiple commits, etc.)
591 - `FOSSIL-3004`: Unresolved resource identifier. A branch/tag/uuid
592 provided by client code could not be resolved. This is a special
593 case of #3006.
594 - `FOSSIL-3005`: Resource already exists and overwriting/replacing is
595 not allowed. e.g. trying to create a wiki page or user which already
596

Keyboard Shortcuts

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