Fossil SCM
Merged in UUID-renaming changes from trunk.
Commit
1fd9acb97c6dc73a56cda356b5bb5e5a89e18a5f7915b242a54252f3905ebe1d
Parent
bc56945ea4fe42e…
55 files changed
+1
-1
+1
-1
+19
-15
+8
-1
+4
-4
+4
-4
+1
-1
+37
-17
-1
+6
-5
+1
-1
+47
-20
+8
-8
+36
-32
+10
-9
+29
-27
+29
-27
+1
-1
+1
-1
+1
-1
-2
-1
+1
-1
+18
-11
+1
-1
+6
-6
+1
-1
+1
-1
+3
-3
+6
-6
+7
+270
-82
+1
-1
+54
-34
+3
-3
+1
-1
+8
-8
+1
-1
+1
-1
+1
-1
+79
-79
+5
-1
+2
-2
+2
-2
-2
-2
+1
-1
+2
-2
+4
-4
+90
-80
+16
-14
+3
-3
+5
-4
+9
-8
+2
-1
~
skins/blitz/ticket.txt
~
skins/blitz_no_logo/ticket.txt
~
src/attach.c
~
src/blob.c
~
src/bundle.c
~
src/checkin.c
~
src/checkout.c
~
src/codecheck1.c
~
src/configure.c
~
src/content.c
~
src/event.c
~
src/fileedit.c
~
src/finfo.c
~
src/fossil.fetch.js
~
src/import.c
~
src/info.c
~
src/info.c
~
src/json_finfo.c
~
src/json_tag.c
~
src/main.c
~
src/main.mk
~
src/makemake.tcl
~
src/manifest.c
~
src/name.c
~
src/printf.c
~
src/purge.c
~
src/rebuild.c
~
src/report.c
~
src/rss.c
~
src/schema.c
~
src/security_audit.c
~
src/shell.c
~
src/smtp.c
~
src/sqlite3.c
~
src/sqlite3.h
~
src/tar.c
~
src/timeline.c
~
src/tktsetup.c
~
src/util.c
~
src/zip.c
~
test/amend.test
~
tools/email-sender.tcl
~
win/Makefile.PellesCGMake
~
win/Makefile.dmc
~
win/Makefile.mingw
~
win/Makefile.msc
~
www/concepts.wiki
~
www/fiveminutes.wiki
~
www/fossil-v-git.wiki
~
www/hashes.md
~
www/json-api/api-artifact.md
~
www/json-api/api-diff.md
~
www/json-api/api-tag.md
~
www/json-api/api-timeline.md
~
www/json-api/conventions.md
+1
-1
| --- skins/blitz/ticket.txt | ||
| +++ skins/blitz/ticket.txt | ||
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | <h4>$<title></h4> |
| 2 | 2 | <table class="tktDsp"> |
| 3 | -<tr><td class="tktDspLabel">Ticket UUID</td> | |
| 3 | +<tr><td class="tktDspLabel">Ticket Hash</td> | |
| 4 | 4 | <th1> |
| 5 | 5 | if {[info exists tkt_uuid]} { |
| 6 | 6 | if {[hascap s]} { |
| 7 | 7 | html "<td class='tktDspValue' colspan='3'>$tkt_uuid " |
| 8 | 8 | html "($tkt_id)</td></tr>\n" |
| 9 | 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 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 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 |
+1
-1
| --- skins/blitz_no_logo/ticket.txt | ||
| +++ skins/blitz_no_logo/ticket.txt | ||
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | <h4>$<title></h4> |
| 2 | 2 | <table class="tktDsp"> |
| 3 | -<tr><td class="tktDspLabel">Ticket UUID</td> | |
| 3 | +<tr><td class="tktDspLabel">Ticket Hash</td> | |
| 4 | 4 | <th1> |
| 5 | 5 | if {[info exists tkt_uuid]} { |
| 6 | 6 | if {[hascap s]} { |
| 7 | 7 | html "<td class='tktDspValue' colspan='3'>$tkt_uuid " |
| 8 | 8 | html "($tkt_id)</td></tr>\n" |
| 9 | 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 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 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 @@ | ||
| 23 | 23 | |
| 24 | 24 | /* |
| 25 | 25 | ** WEBPAGE: attachlist |
| 26 | 26 | ** List attachments. |
| 27 | 27 | ** |
| 28 | -** tkt=TICKETUUID | |
| 28 | +** tkt=HASH | |
| 29 | 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. | |
| 30 | 36 | ** |
| 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. | |
| 37 | 40 | */ |
| 38 | 41 | void attachlist_page(void){ |
| 39 | 42 | const char *zPage = P("page"); |
| 40 | 43 | const char *zTkt = P("tkt"); |
| 41 | 44 | const char *zTechNote = P("technote"); |
| @@ -152,15 +155,16 @@ | ||
| 152 | 155 | ** WEBPAGE: attachdownload |
| 153 | 156 | ** WEBPAGE: attachimage |
| 154 | 157 | ** WEBPAGE: attachview |
| 155 | 158 | ** |
| 156 | 159 | ** Download or display an attachment. |
| 160 | +** | |
| 157 | 161 | ** Query parameters: |
| 158 | 162 | ** |
| 159 | -** tkt=TICKETUUID | |
| 163 | +** tkt=HASH | |
| 160 | 164 | ** page=WIKIPAGE |
| 161 | -** technote=TECHNOTEUUID | |
| 165 | +** technote=HASH | |
| 162 | 166 | ** file=FILENAME |
| 163 | 167 | ** attachid=ID |
| 164 | 168 | ** |
| 165 | 169 | */ |
| 166 | 170 | void attachview_page(void){ |
| @@ -250,11 +254,11 @@ | ||
| 250 | 254 | /* |
| 251 | 255 | ** Commit a new attachment into the repository |
| 252 | 256 | */ |
| 253 | 257 | void attach_commit( |
| 254 | 258 | 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 */ | |
| 256 | 260 | const char *aContent, /* The content of the attachment */ |
| 257 | 261 | int szContent, /* The length of the attachment */ |
| 258 | 262 | int needModerator, /* Moderate the attachment? */ |
| 259 | 263 | const char *zComment /* The comment for the attachment */ |
| 260 | 264 | ){ |
| @@ -305,13 +309,13 @@ | ||
| 305 | 309 | |
| 306 | 310 | /* |
| 307 | 311 | ** WEBPAGE: attachadd |
| 308 | 312 | ** Add a new attachment. |
| 309 | 313 | ** |
| 310 | -** tkt=TICKETUUID | |
| 314 | +** tkt=HASH | |
| 311 | 315 | ** page=WIKIPAGE |
| 312 | -** technote=TECHNOTEUUID | |
| 316 | +** technote=HASH | |
| 313 | 317 | ** from=URL |
| 314 | 318 | ** |
| 315 | 319 | */ |
| 316 | 320 | void attachadd_page(void){ |
| 317 | 321 | const char *zPage = P("page"); |
| @@ -420,14 +424,14 @@ | ||
| 420 | 424 | */ |
| 421 | 425 | void ainfo_page(void){ |
| 422 | 426 | int rid; /* RID for the control artifact */ |
| 423 | 427 | int ridSrc; /* RID for the attached file */ |
| 424 | 428 | char *zDate; /* Date attached */ |
| 425 | - const char *zUuid; /* UUID of the control artifact */ | |
| 429 | + const char *zUuid; /* Hash of the control artifact */ | |
| 426 | 430 | Manifest *pAttach; /* Parse of the control artifact */ |
| 427 | 431 | 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 */ | |
| 429 | 433 | const char *zName; /* Name of the attached file */ |
| 430 | 434 | const char *zDesc; /* Description of the attached file */ |
| 431 | 435 | const char *zWikiName = 0; /* Wiki page name when attached to Wiki */ |
| 432 | 436 | const char *zTNUuid = 0; /* Tech Note ID when attached to tech note */ |
| 433 | 437 | const char *zTktUuid = 0; /* Ticket ID when attached to a ticket */ |
| @@ -763,11 +767,11 @@ | ||
| 763 | 767 | } |
| 764 | 768 | blob_read_from_file(&content, zFile, ExtFILE); |
| 765 | 769 | user_select(); |
| 766 | 770 | attach_commit( |
| 767 | 771 | zFile, /* The filename of the attachment */ |
| 768 | - zTarget, /* The artifact uuid to attach to */ | |
| 772 | + zTarget, /* The artifact hash to attach to */ | |
| 769 | 773 | blob_buffer(&content), /* The content of the attachment */ |
| 770 | 774 | blob_size(&content), /* The length of the attachment */ |
| 771 | 775 | 0, /* No need to moderate the attachment */ |
| 772 | 776 | "" /* Empty attachment comment */ |
| 773 | 777 | ); |
| 774 | 778 |
| --- 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 @@ | ||
| 482 | 482 | |
| 483 | 483 | /* |
| 484 | 484 | ** Ensures that the given blob has at least the given amount of memory |
| 485 | 485 | ** allocated to it. Does not modify pBlob->nUsed nor will it reduce |
| 486 | 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. | |
| 487 | 492 | */ |
| 488 | 493 | 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){ | |
| 490 | 497 | pBlob->xRealloc(pBlob, newSize); |
| 491 | 498 | pBlob->aData[newSize] = 0; |
| 492 | 499 | } |
| 493 | 500 | } |
| 494 | 501 | |
| 495 | 502 |
| --- 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 @@ | ||
| 530 | 530 | blob_reset(&h1); |
| 531 | 531 | bag_remove(&busy, blobid); |
| 532 | 532 | db_finalize(&q); |
| 533 | 533 | } |
| 534 | 534 | |
| 535 | -/* fossil bundle cat BUNDLE UUID... | |
| 535 | +/* fossil bundle cat BUNDLE HASH... | |
| 536 | 536 | ** |
| 537 | 537 | ** Write elements of a bundle on standard output |
| 538 | 538 | */ |
| 539 | 539 | static void bundle_cat_cmd(void){ |
| 540 | 540 | int i; |
| 541 | 541 | Blob x; |
| 542 | 542 | verify_all_options(); |
| 543 | - if( g.argc<5 ) usage("cat BUNDLE UUID..."); | |
| 543 | + if( g.argc<5 ) usage("cat BUNDLE HASH..."); | |
| 544 | 544 | bundle_attach_file(g.argv[3], "b1", 1); |
| 545 | 545 | blob_zero(&x); |
| 546 | 546 | for(i=4; i<g.argc; i++){ |
| 547 | 547 | int blobid = db_int(0,"SELECT blobid FROM bblob WHERE uuid LIKE '%q%%'", |
| 548 | 548 | g.argv[i]); |
| @@ -725,11 +725,11 @@ | ||
| 725 | 725 | ** fossil bundle append BUNDLE FILE... |
| 726 | 726 | ** |
| 727 | 727 | ** Add files named on the command line to BUNDLE. This subcommand has |
| 728 | 728 | ** little practical use and is mostly intended for testing. |
| 729 | 729 | ** |
| 730 | -** fossil bundle cat BUNDLE UUID... | |
| 730 | +** fossil bundle cat BUNDLE HASH... | |
| 731 | 731 | ** |
| 732 | 732 | ** Extract one or more artifacts from the bundle and write them |
| 733 | 733 | ** consecutively on standard output. This subcommand was designed |
| 734 | 734 | ** for testing and introspection of bundles and is not something |
| 735 | 735 | ** commonly used. |
| @@ -770,11 +770,11 @@ | ||
| 770 | 770 | ** by check-ins in BUNDLE. This has the effect of undoing a |
| 771 | 771 | ** "fossil bundle import". |
| 772 | 772 | ** |
| 773 | 773 | ** SUMMARY: |
| 774 | 774 | ** 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 | |
| 776 | 776 | ** fossil bundle export BUNDLE ?OPTIONS? Create a new BUNDLE |
| 777 | 777 | ** --branch BRANCH --from TAG1 --to TAG2 Check-ins to include |
| 778 | 778 | ** --checkin TAG Use only check-in TAG |
| 779 | 779 | ** --standalone Omit dependencies |
| 780 | 780 | ** fossil bundle extend BUNDLE Update with newer content |
| 781 | 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 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 @@ | ||
| 1424 | 1424 | ** Make sure the current check-in with timestamp zDate is younger than its |
| 1425 | 1425 | ** ancestor identified rid and zUuid. Throw a fatal error if not. |
| 1426 | 1426 | */ |
| 1427 | 1427 | static void checkin_verify_younger( |
| 1428 | 1428 | 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 */ | |
| 1430 | 1430 | const char *zDate /* Date & time of the current check-in */ |
| 1431 | 1431 | ){ |
| 1432 | 1432 | #ifndef FOSSIL_ALLOW_OUT_OF_ORDER_DATES |
| 1433 | 1433 | if(checkin_is_younger(rid,zDate)==0){ |
| 1434 | 1434 | fossil_fatal("ancestor check-in [%S] (%s) is not older (clock skew?)" |
| @@ -1500,18 +1500,18 @@ | ||
| 1500 | 1500 | /* |
| 1501 | 1501 | ** Create a manifest. |
| 1502 | 1502 | */ |
| 1503 | 1503 | static void create_manifest( |
| 1504 | 1504 | Blob *pOut, /* Write the manifest here */ |
| 1505 | - const char *zBaselineUuid, /* UUID of baseline, or zero */ | |
| 1505 | + const char *zBaselineUuid, /* Hash of baseline, or zero */ | |
| 1506 | 1506 | Manifest *pBaseline, /* Make it a delta manifest if not zero */ |
| 1507 | 1507 | int vid, /* BLOB.id for the parent check-in */ |
| 1508 | 1508 | CheckinInfo *p, /* Information about the check-in */ |
| 1509 | 1509 | int *pnFBcard /* OUT: Number of generated B- and F-cards */ |
| 1510 | 1510 | ){ |
| 1511 | 1511 | 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 */ | |
| 1513 | 1513 | Blob filename; /* A single filename */ |
| 1514 | 1514 | int nBasename; /* Size of base filename */ |
| 1515 | 1515 | Stmt q; /* Various queries */ |
| 1516 | 1516 | Blob mcksum; /* Manifest checksum */ |
| 1517 | 1517 | ManifestFile *pFile; /* File from the baseline */ |
| @@ -2058,11 +2058,11 @@ | ||
| 2058 | 2058 | int nrid; /* blob-id of a modified file */ |
| 2059 | 2059 | int nvid; /* Blob-id of the new check-in */ |
| 2060 | 2060 | Blob comment; /* Check-in comment */ |
| 2061 | 2061 | const char *zComment; /* Check-in comment */ |
| 2062 | 2062 | Stmt q; /* Various queries */ |
| 2063 | - char *zUuid; /* UUID of the new check-in */ | |
| 2063 | + char *zUuid; /* Hash of the new check-in */ | |
| 2064 | 2064 | int useHash = 0; /* True to verify file status using hashing */ |
| 2065 | 2065 | int noSign = 0; /* True to omit signing the manifest using GPG */ |
| 2066 | 2066 | int privateFlag = 0; /* True if the --private option is present */ |
| 2067 | 2067 | int privateParent = 0; /* True if the parent check-in is private */ |
| 2068 | 2068 | int isAMerge = 0; /* True if checking in a merge */ |
| 2069 | 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 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 @@ | ||
| 87 | 87 | db_multi_exec("DELETE FROM vfile WHERE vid=%d", vid); |
| 88 | 88 | } |
| 89 | 89 | |
| 90 | 90 | |
| 91 | 91 | /* |
| 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 | |
| 93 | 93 | ** version in the VFILE table. Return the VID for the version. |
| 94 | 94 | ** |
| 95 | 95 | ** If anything goes wrong, panic. |
| 96 | 96 | */ |
| 97 | 97 | int load_vfile(const char *zName, int forceMissingFlag){ |
| 98 | 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 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 @@ | ||
| 343 | 343 | } |
| 344 | 344 | |
| 345 | 345 | /* |
| 346 | 346 | ** Processing flags |
| 347 | 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 */ | |
| 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 | 352 | |
| 353 | 353 | /* |
| 354 | 354 | ** A list of internal Fossil interfaces that take a printf-style format |
| 355 | 355 | ** string. |
| 356 | 356 | */ |
| 357 | -struct { | |
| 357 | +struct FmtFunc { | |
| 358 | 358 | const char *zFName; /* Name of the function */ |
| 359 | 359 | int iFmtArg; /* Index of format argument. Leftmost is 1. */ |
| 360 | 360 | unsigned fmtFlags; /* Processing flags */ |
| 361 | 361 | } aFmtFunc[] = { |
| 362 | - { "admin_log", 1, 0 }, | |
| 362 | + { "admin_log", 1, FMT_SAFE }, | |
| 363 | + { "audit_append", 3, FMT_SAFE }, | |
| 364 | + { "backofficeTrace", 1, FMT_SAFE }, | |
| 363 | 365 | { "blob_append_sql", 2, FMT_SQL }, |
| 364 | - { "blob_appendf", 2, 0 }, | |
| 366 | + { "blob_appendf", 2, FMT_SAFE }, | |
| 365 | 367 | { "cgi_debug", 1, FMT_SAFE }, |
| 366 | 368 | { "cgi_panic", 1, FMT_SAFE }, |
| 367 | 369 | { "cgi_printf", 1, FMT_HTML }, |
| 370 | + { "cgi_printf_header", 1, FMT_HTML }, | |
| 368 | 371 | { "cgi_redirectf", 1, FMT_URL }, |
| 369 | 372 | { "chref", 2, FMT_URL }, |
| 373 | + { "CX", 1, FMT_HTML }, | |
| 370 | 374 | { "db_blob", 2, FMT_SQL }, |
| 371 | 375 | { "db_debug", 1, FMT_SQL }, |
| 372 | 376 | { "db_double", 2, FMT_SQL }, |
| 373 | - { "db_err", 1, 0 }, | |
| 377 | + { "db_err", 1, FMT_SAFE }, | |
| 374 | 378 | { "db_exists", 1, FMT_SQL }, |
| 375 | - { "db_get_mprintf", 2, 0 }, | |
| 379 | + { "db_get_mprintf", 2, FMT_SAFE }, | |
| 376 | 380 | { "db_int", 2, FMT_SQL }, |
| 377 | 381 | { "db_int64", 2, FMT_SQL }, |
| 378 | 382 | { "db_multi_exec", 1, FMT_SQL }, |
| 379 | 383 | { "db_optional_sql", 2, FMT_SQL }, |
| 380 | 384 | { "db_prepare", 2, FMT_SQL }, |
| 381 | 385 | { "db_prepare_ignore_error", 2, FMT_SQL }, |
| 382 | - { "db_set_mprintf", 3, 0 }, | |
| 386 | + { "db_set_mprintf", 3, FMT_SAFE }, | |
| 383 | 387 | { "db_static_prepare", 2, FMT_SQL }, |
| 384 | 388 | { "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 }, | |
| 386 | 392 | { "form_begin", 2, FMT_URL }, |
| 387 | 393 | { "fossil_error", 2, FMT_SAFE }, |
| 388 | 394 | { "fossil_errorlog", 1, FMT_SAFE }, |
| 389 | 395 | { "fossil_fatal", 1, FMT_SAFE }, |
| 390 | 396 | { "fossil_fatal_recursive", 1, FMT_SAFE }, |
| @@ -391,24 +397,36 @@ | ||
| 391 | 397 | { "fossil_panic", 1, FMT_SAFE }, |
| 392 | 398 | { "fossil_print", 1, FMT_SAFE }, |
| 393 | 399 | { "fossil_trace", 1, FMT_SAFE }, |
| 394 | 400 | { "fossil_warning", 1, FMT_SAFE }, |
| 395 | 401 | { "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 }, | |
| 402 | 411 | { "style_header", 1, FMT_HTML }, |
| 403 | 412 | { "style_js_onload", 1, FMT_HTML }, |
| 404 | 413 | { "style_set_current_page", 1, FMT_URL }, |
| 405 | 414 | { "style_submenu_element", 2, FMT_URL }, |
| 406 | 415 | { "style_submenu_sql", 3, FMT_SQL }, |
| 407 | 416 | { "webpage_error", 1, FMT_SAFE }, |
| 408 | 417 | { "xhref", 2, FMT_URL }, |
| 409 | 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 | +} | |
| 410 | 428 | |
| 411 | 429 | /* |
| 412 | 430 | ** Determine if the indentifier zIdent of length nIndent is a Fossil |
| 413 | 431 | ** internal interface that uses a printf-style argument. Return zero if not. |
| 414 | 432 | ** Return the index of the format string if true with the left-most |
| @@ -625,10 +643,12 @@ | ||
| 625 | 643 | ** The eVerbose global variable is incremented with each "-v" argument. |
| 626 | 644 | */ |
| 627 | 645 | int main(int argc, char **argv){ |
| 628 | 646 | int i; |
| 629 | 647 | int nErr = 0; |
| 648 | + qsort(aFmtFunc, sizeof(aFmtFunc)/sizeof(aFmtFunc[0]), | |
| 649 | + sizeof(aFmtFunc[0]), fmtfunc_cmp); | |
| 630 | 650 | for(i=1; i<argc; i++){ |
| 631 | 651 | char *zFile; |
| 632 | 652 | if( strcmp(argv[i],"-v")==0 ){ |
| 633 | 653 | eVerbose++; |
| 634 | 654 | continue; |
| 635 | 655 |
| --- 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 |
-1
| --- src/configure.c | ||
| +++ src/configure.c | ||
| @@ -148,11 +148,10 @@ | ||
| 148 | 148 | { "parent-project-name", CONFIGSET_PROJ }, |
| 149 | 149 | { "hash-policy", CONFIGSET_PROJ }, |
| 150 | 150 | { "comment-format", CONFIGSET_PROJ }, |
| 151 | 151 | { "mimetypes", CONFIGSET_PROJ }, |
| 152 | 152 | { "forbid-delta-manifests", CONFIGSET_PROJ }, |
| 153 | - { "fileedit-glob", CONFIGSET_PROJ }, | |
| 154 | 153 | |
| 155 | 154 | #ifdef FOSSIL_ENABLE_LEGACY_MV_RM |
| 156 | 155 | { "mv-rm-files", CONFIGSET_PROJ }, |
| 157 | 156 | #endif |
| 158 | 157 | |
| 159 | 158 |
| --- 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 @@ | ||
| 564 | 564 | db_finalize(&s1); |
| 565 | 565 | db_end_transaction(0); |
| 566 | 566 | return rid; |
| 567 | 567 | } |
| 568 | 568 | }else{ |
| 569 | - rid = 0; /* No entry with the same UUID currently exists */ | |
| 569 | + rid = 0; /* No entry with the same hash currently exists */ | |
| 570 | 570 | markAsUnclustered = 1; |
| 571 | 571 | } |
| 572 | 572 | db_finalize(&s1); |
| 573 | 573 | |
| 574 | 574 | /* Construct a received-from ID if we do not already have one */ |
| @@ -659,11 +659,11 @@ | ||
| 659 | 659 | return content_put_ex(pBlob, 0, 0, 0, 0); |
| 660 | 660 | } |
| 661 | 661 | |
| 662 | 662 | |
| 663 | 663 | /* |
| 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. | |
| 665 | 665 | */ |
| 666 | 666 | int content_new(const char *zUuid, int isPrivate){ |
| 667 | 667 | int rid; |
| 668 | 668 | static Stmt s1, s2, s3; |
| 669 | 669 | |
| @@ -1110,15 +1110,16 @@ | ||
| 1110 | 1110 | /* Allowed flags for check_exists */ |
| 1111 | 1111 | #define MISSING_SHUNNED 0x0001 /* Do not report shunned artifacts */ |
| 1112 | 1112 | |
| 1113 | 1113 | /* This is a helper routine for test-artifacts. |
| 1114 | 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. | |
| 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. | |
| 1117 | 1118 | */ |
| 1118 | 1119 | 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 */ | |
| 1120 | 1121 | unsigned flags, /* Flags */ |
| 1121 | 1122 | Manifest *p, /* The control artifact that references zUuid */ |
| 1122 | 1123 | const char *zRole, /* Role of zUuid in p */ |
| 1123 | 1124 | const char *zDetail /* Additional information, such as a filename */ |
| 1124 | 1125 | ){ |
| 1125 | 1126 |
| --- 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 @@ | ||
| 63 | 63 | ** Display an existing tech-note identified by its ID, optionally at a |
| 64 | 64 | ** specific version, and optionally with additional details. |
| 65 | 65 | */ |
| 66 | 66 | void event_page(void){ |
| 67 | 67 | int rid = 0; /* rid of the event artifact */ |
| 68 | - char *zUuid; /* UUID corresponding to rid */ | |
| 68 | + char *zUuid; /* artifact hash corresponding to rid */ | |
| 69 | 69 | const char *zId; /* Event identifier */ |
| 70 | 70 | const char *zVerbose; /* Value of verbose option */ |
| 71 | 71 | char *zETime; /* Time of the tech-note */ |
| 72 | 72 | char *zATime; /* Time the artifact was created */ |
| 73 | 73 | int specRid; /* rid specified by aid= parameter */ |
| 74 | 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; /* 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 @@ | ||
| 888 | 888 | |
| 889 | 889 | /* |
| 890 | 890 | ** If the fileedit-glob setting has a value, this returns its Glob |
| 891 | 891 | ** object (in memory owned by this function), else it returns NULL. |
| 892 | 892 | */ |
| 893 | -static Glob * fileedit_glob(void){ | |
| 893 | +Glob *fileedit_glob(void){ | |
| 894 | 894 | static Glob * pGlobs = 0; |
| 895 | 895 | static int once = 0; |
| 896 | 896 | if(0==pGlobs && once==0){ |
| 897 | 897 | char * zGlobs = db_get("fileedit-glob",0); |
| 898 | 898 | once = 1; |
| @@ -987,11 +987,11 @@ | ||
| 987 | 987 | output_text_with_line_numbers(zContent, "on"); |
| 988 | 988 | }else if(zExt && zExt[1]){ |
| 989 | 989 | CX("<pre><code class='language-%s'>%h</code></pre>", |
| 990 | 990 | zExt+1, zContent); |
| 991 | 991 | }else{ |
| 992 | - CX("<pre>%h</pre>", zExt+1, zContent); | |
| 992 | + CX("<pre>%h</pre>", zContent); | |
| 993 | 993 | } |
| 994 | 994 | break; |
| 995 | 995 | } |
| 996 | 996 | } |
| 997 | 997 | } |
| @@ -1713,13 +1713,13 @@ | ||
| 1713 | 1713 | (CIMINI_DRY_RUN & cimi.flags) ? "true" : "false"); |
| 1714 | 1714 | if(blob_size(&manifest)>0){ |
| 1715 | 1715 | CX(",\"manifest\": %!j", blob_str(&manifest)); |
| 1716 | 1716 | } |
| 1717 | 1717 | CX("}"); |
| 1718 | +end_cleanup: | |
| 1718 | 1719 | db_end_transaction(0/*noting that dry-run mode will have already |
| 1719 | 1720 | ** set this to rollback mode. */); |
| 1720 | -end_cleanup: | |
| 1721 | 1721 | fossil_free(zNewUuid); |
| 1722 | 1722 | blob_reset(&err); |
| 1723 | 1723 | blob_reset(&manifest); |
| 1724 | 1724 | CheckinMiniInfo_cleanup(&cimi); |
| 1725 | 1725 | } |
| @@ -1765,13 +1765,51 @@ | ||
| 1765 | 1765 | end. This content will be |
| 1766 | 1766 | combined into a single JS |
| 1767 | 1767 | function call, thus each |
| 1768 | 1768 | entry must end with a |
| 1769 | 1769 | 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 | + } | |
| 1771 | 1805 | |
| 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 ){ | |
| 1773 | 1811 | if(0==strcmp("content",zAjax)){ |
| 1774 | 1812 | fileedit_ajax_content(); |
| 1775 | 1813 | }else if(0==strcmp("preview",zAjax)){ |
| 1776 | 1814 | fileedit_ajax_preview(); |
| 1777 | 1815 | }else if(0==strcmp("filelist",zAjax)){ |
| @@ -1783,21 +1821,18 @@ | ||
| 1783 | 1821 | }else{ |
| 1784 | 1822 | fileedit_ajax_error(500, "Unhandled ajax route name."); |
| 1785 | 1823 | } |
| 1786 | 1824 | return; |
| 1787 | 1825 | } |
| 1788 | - login_check_credentials(); | |
| 1789 | - if( !g.perm.Write ){ | |
| 1790 | - login_needed(g.anon.Write); | |
| 1791 | - return; | |
| 1792 | - } | |
| 1826 | + | |
| 1793 | 1827 | db_begin_transaction(); |
| 1794 | 1828 | CheckinMiniInfo_init(&cimi); |
| 1795 | 1829 | style_header("File Editor"); |
| 1796 | 1830 | /* As of this point, don't use return or fossil_fatal(). Write any |
| 1797 | 1831 | ** 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. | |
| 1799 | 1834 | */ |
| 1800 | 1835 | { |
| 1801 | 1836 | int isMissingArg = 0; |
| 1802 | 1837 | if(fileedit_setup_cimi_from_p(&cimi, &err, &isMissingArg)==0){ |
| 1803 | 1838 | zFilename = cimi.zFilename; |
| @@ -1805,11 +1840,11 @@ | ||
| 1805 | 1840 | assert(zRev); |
| 1806 | 1841 | assert(zFilename); |
| 1807 | 1842 | zFileMime = mimetype_from_name(cimi.zFilename); |
| 1808 | 1843 | }else if(isMissingArg!=0){ |
| 1809 | 1844 | /* Squelch these startup warnings - they're non-fatal now but |
| 1810 | - ** used to be. */ | |
| 1845 | + ** used to be fatal. */ | |
| 1811 | 1846 | blob_reset(&err); |
| 1812 | 1847 | } |
| 1813 | 1848 | } |
| 1814 | 1849 | |
| 1815 | 1850 | /******************************************************************** |
| @@ -1830,18 +1865,10 @@ | ||
| 1830 | 1865 | */ |
| 1831 | 1866 | style_emit_script_tag(0,0); |
| 1832 | 1867 | CX("document.body.classList.add('fileedit');\n"); |
| 1833 | 1868 | style_emit_script_tag(1,0); |
| 1834 | 1869 | } |
| 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 | 1870 | |
| 1844 | 1871 | /* Status bar */ |
| 1845 | 1872 | CX("<div id='fossil-status-bar' " |
| 1846 | 1873 | "title='Status message area. Double-click to clear them.'>" |
| 1847 | 1874 | "Status messages will go here.</div>\n" |
| 1848 | 1875 |
| --- 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 @@ | ||
| 284 | 284 | ** b=DATETIME Only show changes before DATETIME |
| 285 | 285 | ** m=HASH Mark this particular file version |
| 286 | 286 | ** n=NUM Show the first NUM changes only |
| 287 | 287 | ** brbg Background color by branch name |
| 288 | 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 | |
| 289 | +** ci=HASH Ancestors of a particular check-in | |
| 290 | +** orig=HASH If both ci and orig are supplied, only show those | |
| 291 | 291 | ** changes on a direct path from orig to ci. |
| 292 | 292 | ** showid Show RID values for debugging |
| 293 | 293 | ** |
| 294 | 294 | ** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in |
| 295 | 295 | ** year-month-day form, it may be truncated, and it may also name a |
| @@ -371,13 +371,13 @@ | ||
| 371 | 371 | " datetime(min(event.mtime),toLocal())," /* Date of change */ |
| 372 | 372 | " coalesce(event.ecomment, event.comment)," /* Check-in comment */ |
| 373 | 373 | " coalesce(event.euser, event.user)," /* User who made chng */ |
| 374 | 374 | " mlink.pid," /* Parent file rid */ |
| 375 | 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 */ | |
| 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 | 379 | " event.bgcolor," /* Background color */ |
| 380 | 380 | " (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0" |
| 381 | 381 | " AND tagxref.rid=mlink.mid)," /* Branchname */ |
| 382 | 382 | " mlink.mid," /* check-in ID */ |
| 383 | 383 | " mlink.pfnid," /* Previous filename */ |
| @@ -541,13 +541,13 @@ | ||
| 541 | 541 | if( tmFlags & TIMELINE_COMPACT ){ |
| 542 | 542 | @ <span class='timelineCompactComment' data-id='%d(frid)'> |
| 543 | 543 | }else{ |
| 544 | 544 | @ <span class='timeline%s(zStyle)Comment'> |
| 545 | 545 | if( (tmFlags & TIMELINE_VERBOSE)!=0 && zUuid ){ |
| 546 | - hyperlink_to_uuid(zUuid); | |
| 546 | + hyperlink_to_version(zUuid); | |
| 547 | 547 | @ part of check-in \ |
| 548 | - hyperlink_to_uuid(zCkin); | |
| 548 | + hyperlink_to_version(zCkin); | |
| 549 | 549 | } |
| 550 | 550 | } |
| 551 | 551 | @ %W(zCom)</span> |
| 552 | 552 | if( (tmFlags & TIMELINE_COMPACT)!=0 ){ |
| 553 | 553 | @ <span class='timelineEllipsis' data-id='%d(frid)' \ |
| @@ -576,11 +576,11 @@ | ||
| 576 | 576 | @ id: %d(frid) |
| 577 | 577 | } |
| 578 | 578 | } |
| 579 | 579 | } |
| 580 | 580 | @ check-in: \ |
| 581 | - hyperlink_to_uuid(zCkin); | |
| 581 | + hyperlink_to_version(zCkin); | |
| 582 | 582 | if( fShowId ){ |
| 583 | 583 | @ (%d(fmid)) |
| 584 | 584 | } |
| 585 | 585 | @ user: \ |
| 586 | 586 | hyperlink_to_user(zUser, zDate, ","); |
| 587 | 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=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: %d(frid) |
| 577 | } |
| 578 | } |
| 579 | } |
| 580 | @ check-in: \ |
| 581 | hyperlink_to_uuid(zCkin); |
| 582 | if( fShowId ){ |
| 583 | @ (%d(fmid)) |
| 584 | } |
| 585 | @ user: \ |
| 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: %d(frid) |
| 577 | } |
| 578 | } |
| 579 | } |
| 580 | @ check-in: \ |
| 581 | hyperlink_to_version(zCkin); |
| 582 | if( fShowId ){ |
| 583 | @ (%d(fmid)) |
| 584 | } |
| 585 | @ user: \ |
| 586 | hyperlink_to_user(zUser, zDate, ","); |
| 587 |
+36
-32
| --- src/fossil.fetch.js | ||
| +++ src/fossil.fetch.js | ||
| @@ -22,14 +22,15 @@ | ||
| 22 | 22 | - onload: callback(responseData) (default = output response to the |
| 23 | 23 | console). In the context of the callback, the options object is |
| 24 | 24 | "this", noting that this call may have amended the options object |
| 25 | 25 | with state other than what the caller provided. |
| 26 | 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". | |
| 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". | |
| 31 | 32 | |
| 32 | 33 | - method: 'POST' | 'GET' (default = 'GET'). CASE SENSITIVE! |
| 33 | 34 | |
| 34 | 35 | - payload: anything acceptable by XHR2.send(ARG) (DOMString, |
| 35 | 36 | Document, FormData, Blob, File, ArrayBuffer), or a plain object or |
| @@ -75,48 +76,39 @@ | ||
| 75 | 76 | "this". These can be used to, e.g., keep track of in-flight |
| 76 | 77 | requests and update the UI accordingly, e.g. disabling/enabling DOM |
| 77 | 78 | elements. Any exceptions triggered by beforesend/aftersend are |
| 78 | 79 | caught and silently ignored. |
| 79 | 80 | |
| 81 | + - timeout: integer in milliseconds specifying the XHR timeout | |
| 82 | + duration. Default = fossil.fetch.timeout. | |
| 83 | + | |
| 80 | 84 | When an options object does not provide |
| 81 | 85 | onload/onerror/beforesend/aftersend handlers of its own, this |
| 82 | 86 | function falls to defaults which are member properties of this |
| 83 | 87 | function with the same name, e.g. fossil.fetch.onload(). The |
| 84 | 88 | default onload/onerror implementations route the data through the |
| 85 | 89 | dev console and (for onerror()) through fossil.error(). The default |
| 86 | 90 | beforesend/aftersend are no-ops. Individual pages may overwrite |
| 87 | 91 | those members to provide default implementations suitable for the |
| 88 | 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. | |
| 89 | 96 | |
| 90 | 97 | Returns this object, noting that the XHR request is asynchronous, |
| 91 | 98 | and still in transit (or has yet to be sent) when that happens. |
| 92 | 99 | */ |
| 93 | 100 | window.fossil.fetch = function f(uri,opt){ |
| 94 | 101 | const F = fossil; |
| 95 | 102 | if(!f.onload){ |
| 96 | - f.onload = (r)=>console.debug('ajax response:',r); | |
| 103 | + f.onload = (r)=>console.debug('fossil.fetch() XHR response:',r); | |
| 97 | 104 | } |
| 98 | 105 | 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."); | |
| 118 | 110 | }; |
| 119 | 111 | }/*f.onerror()*/ |
| 120 | 112 | if(!f.parseResponseHeaders){ |
| 121 | 113 | f.parseResponseHeaders = function(h){ |
| 122 | 114 | const rc = {}; |
| @@ -155,50 +147,62 @@ | ||
| 155 | 147 | const url=[F.repoUrl(uri,opt.urlParams)], |
| 156 | 148 | x=new XMLHttpRequest(); |
| 157 | 149 | if('POST'===opt.method && 'string'===typeof opt.contentType){ |
| 158 | 150 | x.setRequestHeader('Content-Type',opt.contentType); |
| 159 | 151 | } |
| 160 | - x.open(opt.method||'GET', url.join(''), true); | |
| 161 | 152 | if('json'===opt.responseType){ |
| 162 | 153 | /* 'json' is an extension to the supported XHR.responseType |
| 163 | 154 | list. We use it as a flag to tell us to JSON.parse() |
| 164 | 155 | the response. */ |
| 165 | 156 | jsonResponse = true; |
| 166 | 157 | x.responseType = 'text'; |
| 167 | 158 | }else{ |
| 168 | 159 | x.responseType = opt.responseType||'text'; |
| 169 | 160 | } |
| 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; | |
| 171 | 167 | 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+".")); | |
| 174 | 175 | return; |
| 175 | 176 | } |
| 176 | 177 | const orh = opt.responseHeaders; |
| 177 | 178 | let head; |
| 178 | 179 | if(true===orh){ |
| 179 | - head = f.parseResponseHeaders(this.getAllResponseHeaders()); | |
| 180 | + head = f.parseResponseHeaders(x.getAllResponseHeaders()); | |
| 180 | 181 | }else if('string'===typeof orh){ |
| 181 | - head = this.getResponseHeader(orh); | |
| 182 | + head = x.getResponseHeader(orh); | |
| 182 | 183 | }else if(orh instanceof Array){ |
| 183 | 184 | head = {}; |
| 184 | 185 | orh.forEach((s)=>{ |
| 185 | 186 | if('string' === typeof s) head[s.toLowerCase()] = x.getResponseHeader(s); |
| 186 | 187 | }); |
| 187 | 188 | } |
| 188 | 189 | 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]; | |
| 191 | 192 | if(head) args.push(head); |
| 192 | 193 | opt.onload.apply(opt, args); |
| 193 | 194 | }catch(e){ |
| 194 | 195 | opt.onerror(e); |
| 195 | 196 | } |
| 196 | 197 | }; |
| 197 | 198 | try{opt.beforesend()}catch(e){/*ignore*/} |
| 199 | + x.open(opt.method||'GET', url.join(''), true); | |
| 200 | + x.timeout = +opt.timeout || f.timeout; | |
| 198 | 201 | if(undefined!==payload) x.send(payload); |
| 199 | 202 | else x.send(); |
| 200 | 203 | return this; |
| 201 | 204 | }; |
| 202 | 205 | |
| 203 | 206 | window.fossil.fetch.beforesend = function(){}; |
| 204 | 207 | window.fossil.fetch.aftersend = function(){}; |
| 208 | +window.fossil.fetch.timeout = 15000/* Default timeout, in ms. */; | |
| 205 | 209 |
| --- 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 @@ | ||
| 26 | 26 | /* |
| 27 | 27 | ** A single file change record. |
| 28 | 28 | */ |
| 29 | 29 | struct ImportFile { |
| 30 | 30 | char *zName; /* Name of a file */ |
| 31 | - char *zUuid; /* UUID of the file */ | |
| 31 | + char *zUuid; /* Hash of the file */ | |
| 32 | 32 | char *zPrior; /* Prior name if the name was changed */ |
| 33 | 33 | char isFrom; /* True if obtained from the parent */ |
| 34 | 34 | char isExe; /* True if executable */ |
| 35 | 35 | char isLink; /* True if symlink */ |
| 36 | 36 | }; |
| @@ -59,11 +59,11 @@ | ||
| 59 | 59 | char *aData; /* Data content */ |
| 60 | 60 | char *zMark; /* The current mark */ |
| 61 | 61 | char *zDate; /* Date/time stamp */ |
| 62 | 62 | char *zUser; /* User name */ |
| 63 | 63 | char *zComment; /* Comment of a commit */ |
| 64 | - char *zFrom; /* from value as a UUID */ | |
| 64 | + char *zFrom; /* from value as a hash */ | |
| 65 | 65 | char *zPrevCheckin; /* Name of the previous check-in */ |
| 66 | 66 | char *zFromMark; /* The mark of the "from" field */ |
| 67 | 67 | int nMerge; /* Number of merge values */ |
| 68 | 68 | int nMergeAlloc; /* Number of slots in azMerge[] */ |
| 69 | 69 | char **azMerge; /* Merge values */ |
| @@ -143,17 +143,17 @@ | ||
| 143 | 143 | /* |
| 144 | 144 | ** Insert an artifact into the BLOB table if it isn't there already. |
| 145 | 145 | ** If zMark is not zero, create a cross-reference from that mark back |
| 146 | 146 | ** to the newly inserted artifact. |
| 147 | 147 | ** |
| 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. | |
| 150 | 150 | */ |
| 151 | 151 | static int fast_insert_content( |
| 152 | 152 | Blob *pContent, /* Content to insert */ |
| 153 | 153 | 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 */ | |
| 155 | 155 | int doParse /* Invoke manifest_crosslink() */ |
| 156 | 156 | ){ |
| 157 | 157 | Blob hash; |
| 158 | 158 | Blob cmpr; |
| 159 | 159 | int rid; |
| @@ -187,11 +187,11 @@ | ||
| 187 | 187 | "INSERT OR IGNORE INTO xmark(tname, trid, tuuid)" |
| 188 | 188 | "VALUES(%B,%d,%B)", |
| 189 | 189 | &hash, rid, &hash |
| 190 | 190 | ); |
| 191 | 191 | } |
| 192 | - if( saveUuid ){ | |
| 192 | + if( saveHash ){ | |
| 193 | 193 | fossil_free(gg.zPrevCheckin); |
| 194 | 194 | gg.zPrevCheckin = fossil_strdup(blob_str(&hash)); |
| 195 | 195 | } |
| 196 | 196 | blob_reset(&hash); |
| 197 | 197 | return rid; |
| @@ -411,11 +411,11 @@ | ||
| 411 | 411 | } |
| 412 | 412 | return z; |
| 413 | 413 | } |
| 414 | 414 | |
| 415 | 415 | /* |
| 416 | -** Convert a "mark" or "committish" into the UUID. | |
| 416 | +** Convert a "mark" or "committish" into the artifact hash. | |
| 417 | 417 | */ |
| 418 | 418 | static char *resolve_committish(const char *zCommittish){ |
| 419 | 419 | char *zRes; |
| 420 | 420 | |
| 421 | 421 | zRes = db_text(0, "SELECT tuuid FROM xmark WHERE tname=%Q", zCommittish); |
| @@ -1828,13 +1828,14 @@ | ||
| 1828 | 1828 | bag_init(&vers); |
| 1829 | 1829 | /* The following temp-tables are used to hold information needed for |
| 1830 | 1830 | ** the import. |
| 1831 | 1831 | ** |
| 1832 | 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). | |
| 1833 | + ** into artifact hashes. | |
| 1834 | + ** | |
| 1834 | 1835 | ** 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. | |
| 1836 | 1837 | ** |
| 1837 | 1838 | ** The XBRANCH table maps commit marks and symbols into the branch those |
| 1838 | 1839 | ** commits belong to. If xbranch.tname is a fast-import symbol for a |
| 1839 | 1840 | ** check-in then xbranch.brnm is the branch that check-in is part of. |
| 1840 | 1841 | ** |
| 1841 | 1842 |
| --- 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 @@ | ||
| 54 | 54 | |
| 55 | 55 | |
| 56 | 56 | /* |
| 57 | 57 | ** Print common information about a particular record. |
| 58 | 58 | ** |
| 59 | -** * The UUID | |
| 59 | +** * The artifact hash | |
| 60 | 60 | ** * The record ID |
| 61 | 61 | ** * mtime and ctime |
| 62 | 62 | ** * who signed it |
| 63 | 63 | ** |
| 64 | 64 | */ |
| 65 | 65 | void show_common_info( |
| 66 | 66 | 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:" */ | |
| 68 | 68 | int showComment, /* True to show the check-in comment */ |
| 69 | 69 | int showFamily /* True to show parents and children */ |
| 70 | 70 | ){ |
| 71 | 71 | Stmt q; |
| 72 | 72 | char *zComment = 0; |
| @@ -78,11 +78,11 @@ | ||
| 78 | 78 | zDate = db_text(0, |
| 79 | 79 | "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d", |
| 80 | 80 | rid |
| 81 | 81 | ); |
| 82 | 82 | /* 01234567890123 */ |
| 83 | - fossil_print("%-13s %.40s %s\n", zUuidName, zUuid, zDate ? zDate : ""); | |
| 83 | + fossil_print("%-13s %.40s %s\n", zRecDesc, zUuid, zDate ? zDate : ""); | |
| 84 | 84 | free(zDate); |
| 85 | 85 | if( showComment ){ |
| 86 | 86 | zComment = db_text(0, |
| 87 | 87 | "SELECT coalesce(ecomment,comment) || " |
| 88 | 88 | " ' (user: ' || coalesce(euser,user,'?') || ')' " |
| @@ -274,11 +274,11 @@ | ||
| 274 | 274 | int rid; |
| 275 | 275 | rid = name_to_rid(g.argv[2]); |
| 276 | 276 | if( rid==0 ){ |
| 277 | 277 | fossil_fatal("no such object: %s", g.argv[2]); |
| 278 | 278 | } |
| 279 | - show_common_info(rid, "uuid:", 1, 1); | |
| 279 | + show_common_info(rid, "hash:", 1, 1); | |
| 280 | 280 | } |
| 281 | 281 | } |
| 282 | 282 | |
| 283 | 283 | /* |
| 284 | 284 | ** Show the context graph (immediate parents and children) for |
| @@ -747,11 +747,11 @@ | ||
| 747 | 747 | @ <span class="infoTag">%h(zTagname)</span> |
| 748 | 748 | } |
| 749 | 749 | if( tagtype==2 ){ |
| 750 | 750 | if( zOrigUuid && zOrigUuid[0] ){ |
| 751 | 751 | @ inherited from |
| 752 | - hyperlink_to_uuid(zOrigUuid); | |
| 752 | + hyperlink_to_version(zOrigUuid); | |
| 753 | 753 | }else{ |
| 754 | 754 | @ propagates to descendants |
| 755 | 755 | } |
| 756 | 756 | } |
| 757 | 757 | if( zSrcUuid && zSrcUuid[0] ){ |
| @@ -758,11 +758,11 @@ | ||
| 758 | 758 | if( tagtype==0 ){ |
| 759 | 759 | @ by |
| 760 | 760 | }else{ |
| 761 | 761 | @ added by |
| 762 | 762 | } |
| 763 | - hyperlink_to_uuid(zSrcUuid); | |
| 763 | + hyperlink_to_version(zSrcUuid); | |
| 764 | 764 | @ on |
| 765 | 765 | hyperlink_to_date(zDate,0); |
| 766 | 766 | } |
| 767 | 767 | @ </li> |
| 768 | 768 | } |
| @@ -829,12 +829,12 @@ | ||
| 829 | 829 | int rid; |
| 830 | 830 | int isLeaf; |
| 831 | 831 | int diffType; /* 0: no diff, 1: unified, 2: side-by-side */ |
| 832 | 832 | u64 diffFlags; /* Flag parameter for text_diff() */ |
| 833 | 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) */ | |
| 834 | + const char *zUuid; /* Hash of zName, found via blob.uuid */ | |
| 835 | + const char *zParent; /* Hash of the parent check-in (if any) */ | |
| 836 | 836 | const char *zRe; /* regex parameter */ |
| 837 | 837 | ReCompiled *pRe = 0; /* regex */ |
| 838 | 838 | const char *zW; /* URL param for ignoring whitespace */ |
| 839 | 839 | const char *zPage = "vinfo"; /* Page that shows diffs */ |
| 840 | 840 | const char *zPageHide = "ci"; /* Page that hides diffs */ |
| @@ -1324,11 +1324,11 @@ | ||
| 1324 | 1324 | db_end_transaction(1); /* ROLLBACK */ |
| 1325 | 1325 | } |
| 1326 | 1326 | |
| 1327 | 1327 | /* |
| 1328 | 1328 | ** WEBPAGE: winfo |
| 1329 | -** URL: /winfo?name=UUID | |
| 1329 | +** URL: /winfo?name=HASH | |
| 1330 | 1330 | ** |
| 1331 | 1331 | ** Display information about a wiki page. |
| 1332 | 1332 | */ |
| 1333 | 1333 | void winfo_page(void){ |
| 1334 | 1334 | int rid; |
| @@ -1485,11 +1485,11 @@ | ||
| 1485 | 1485 | Blob comment; |
| 1486 | 1486 | int wikiFlags = WIKI_INLINE|WIKI_NOBADLINKS; |
| 1487 | 1487 | if( db_get_boolean("timeline-block-markup", 0)==0 ){ |
| 1488 | 1488 | wikiFlags |= WIKI_NOBLOCK; |
| 1489 | 1489 | } |
| 1490 | - hyperlink_to_uuid(zUuid); | |
| 1490 | + hyperlink_to_version(zUuid); | |
| 1491 | 1491 | blob_zero(&comment); |
| 1492 | 1492 | db_column_blob(&q, 2, &comment); |
| 1493 | 1493 | wiki_convert(&comment, 0, wikiFlags); |
| 1494 | 1494 | blob_reset(&comment); |
| 1495 | 1495 | @ (user: |
| @@ -1813,14 +1813,14 @@ | ||
| 1813 | 1813 | } |
| 1814 | 1814 | if( showDetail ){ |
| 1815 | 1815 | @ <li> |
| 1816 | 1816 | hyperlink_to_date(zDate,""); |
| 1817 | 1817 | @ — part of check-in |
| 1818 | - hyperlink_to_uuid(zVers); | |
| 1818 | + hyperlink_to_version(zVers); | |
| 1819 | 1819 | }else{ |
| 1820 | 1820 | @ — part of check-in |
| 1821 | - hyperlink_to_uuid(zVers); | |
| 1821 | + hyperlink_to_version(zVers); | |
| 1822 | 1822 | @ at |
| 1823 | 1823 | hyperlink_to_date(zDate,""); |
| 1824 | 1824 | } |
| 1825 | 1825 | if( zBr && zBr[0] ){ |
| 1826 | 1826 | @ on branch %z(href("%R/timeline?r=%T",zBr))%h(zBr)</a> |
| @@ -1919,11 +1919,11 @@ | ||
| 1919 | 1919 | @ Forum post |
| 1920 | 1920 | }else{ |
| 1921 | 1921 | @ Tag referencing |
| 1922 | 1922 | } |
| 1923 | 1923 | if( zType[0]!='e' || eventTagId == 0){ |
| 1924 | - hyperlink_to_uuid(zUuid); | |
| 1924 | + hyperlink_to_version(zUuid); | |
| 1925 | 1925 | } |
| 1926 | 1926 | @ - %!W(zCom) by |
| 1927 | 1927 | hyperlink_to_user(zUser,zDate," on"); |
| 1928 | 1928 | hyperlink_to_date(zDate, "."); |
| 1929 | 1929 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| @@ -1951,11 +1951,11 @@ | ||
| 1951 | 1951 | @ Also attachment "%h(zFilename)" to |
| 1952 | 1952 | }else{ |
| 1953 | 1953 | @ Attachment "%h(zFilename)" to |
| 1954 | 1954 | } |
| 1955 | 1955 | objType |= OBJTYPE_ATTACHMENT; |
| 1956 | - if( fossil_is_uuid(zTarget) ){ | |
| 1956 | + if( fossil_is_artifact_hash(zTarget) ){ | |
| 1957 | 1957 | if( db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'", |
| 1958 | 1958 | zTarget) |
| 1959 | 1959 | ){ |
| 1960 | 1960 | if( g.perm.Hyperlink && g.anon.RdTkt ){ |
| 1961 | 1961 | @ ticket [%z(href("%R/tktview?name=%!S",zTarget))%S(zTarget)</a>] |
| @@ -2011,11 +2011,11 @@ | ||
| 2011 | 2011 | |
| 2012 | 2012 | |
| 2013 | 2013 | /* |
| 2014 | 2014 | ** WEBPAGE: fdiff |
| 2015 | 2015 | ** WEBPAGE: localdiff |
| 2016 | -** URL: fdiff?v1=UUID&v2=UUID | |
| 2016 | +** URL: fdiff?v1=HASH&v2=HASH | |
| 2017 | 2017 | ** URL: localdiff?name=filename |
| 2018 | 2018 | ** |
| 2019 | 2019 | ** Two arguments, v1 and v2, identify the artifacts to be diffed. |
| 2020 | 2020 | ** Show diff side by side unless sbs is 0. Generate plain text if |
| 2021 | 2021 | ** "patch" is present, otherwise generate "pretty" HTML. |
| @@ -2227,18 +2227,18 @@ | ||
| 2227 | 2227 | ** is by the full-length SHA1 or SHA3 hash. Abbreviations are not |
| 2228 | 2228 | ** accepted. |
| 2229 | 2229 | */ |
| 2230 | 2230 | void secure_rawartifact_page(void){ |
| 2231 | 2231 | int rid = 0; |
| 2232 | - const char *zUuid = PD("name", ""); | |
| 2232 | + const char *zName = PD("name", ""); | |
| 2233 | 2233 | |
| 2234 | 2234 | login_check_credentials(); |
| 2235 | 2235 | 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); | |
| 2237 | 2237 | if( rid==0 ){ |
| 2238 | 2238 | cgi_set_status(404, "Not Found"); |
| 2239 | - @ Unknown artifact: "%h(zUuid)" | |
| 2239 | + @ Unknown artifact: "%h(zName)" | |
| 2240 | 2240 | return; |
| 2241 | 2241 | } |
| 2242 | 2242 | g.isConst = 1; |
| 2243 | 2243 | deliver_artifact(rid, P("m")); |
| 2244 | 2244 | } |
| @@ -3025,16 +3025,18 @@ | ||
| 3025 | 3025 | } |
| 3026 | 3026 | |
| 3027 | 3027 | |
| 3028 | 3028 | /* |
| 3029 | 3029 | ** WEBPAGE: info |
| 3030 | -** URL: info/ARTIFACTID | |
| 3030 | +** URL: info/NAME | |
| 3031 | 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. | |
| 3032 | +** The NAME argument is any valid artifact name: an artifact hash, | |
| 3033 | +** a timestamp, a tag name, etc. | |
| 3034 | 3034 | ** |
| 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. | |
| 3036 | 3038 | */ |
| 3037 | 3039 | void info_page(void){ |
| 3038 | 3040 | const char *zName; |
| 3039 | 3041 | Blob uuid; |
| 3040 | 3042 | int rid; |
| @@ -3644,17 +3646,17 @@ | ||
| 3644 | 3646 | blob_append(&prompt, ".\n# Lines beginning with a # are ignored.\n", -1); |
| 3645 | 3647 | prompt_for_user_comment(pComment, &prompt); |
| 3646 | 3648 | blob_reset(&prompt); |
| 3647 | 3649 | } |
| 3648 | 3650 | |
| 3649 | -#define AMEND_USAGE_STMT "UUID OPTION ?OPTION ...?" | |
| 3651 | +#define AMEND_USAGE_STMT "HASH OPTION ?OPTION ...?" | |
| 3650 | 3652 | /* |
| 3651 | 3653 | ** COMMAND: amend |
| 3652 | 3654 | ** |
| 3653 | -** Usage: %fossil amend UUID OPTION ?OPTION ...? | |
| 3655 | +** Usage: %fossil amend HASH OPTION ?OPTION ...? | |
| 3654 | 3656 | ** |
| 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. | |
| 3656 | 3658 | ** |
| 3657 | 3659 | ** Options: |
| 3658 | 3660 | ** |
| 3659 | 3661 | ** --author USER Make USER the author for check-in |
| 3660 | 3662 | ** -m|--comment COMMENT Make COMMENT the check-in comment |
| @@ -3738,11 +3740,11 @@ | ||
| 3738 | 3740 | verify_all_options(); |
| 3739 | 3741 | if( g.argc<3 || g.argc>=4 ) usage(AMEND_USAGE_STMT); |
| 3740 | 3742 | rid = name_to_typed_rid(g.argv[2], "ci"); |
| 3741 | 3743 | if( rid==0 && !is_a_version(rid) ) fossil_fatal("no such check-in"); |
| 3742 | 3744 | 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"); | |
| 3744 | 3746 | zComment = db_text(0, "SELECT coalesce(ecomment,comment)" |
| 3745 | 3747 | " FROM event WHERE objid=%d", rid); |
| 3746 | 3748 | zUser = db_text(0, "SELECT coalesce(euser,user)" |
| 3747 | 3749 | " FROM event WHERE objid=%d", rid); |
| 3748 | 3750 | zDate = db_text(0, "SELECT datetime(mtime)" |
| @@ -3828,11 +3830,11 @@ | ||
| 3828 | 3830 | if( fHide && !fHasHidden ) hide_branch(); |
| 3829 | 3831 | if( fClose && !fHasClosed ) close_leaf(rid); |
| 3830 | 3832 | if( zNewBranch && zNewBranch[0] ) change_branch(rid,zNewBranch); |
| 3831 | 3833 | apply_newtags(&ctrl, rid, zUuid, zUserOvrd, fDryRun); |
| 3832 | 3834 | if( fDryRun==0 ){ |
| 3833 | - show_common_info(rid, "uuid:", 1, 0); | |
| 3835 | + show_common_info(rid, "hash:", 1, 0); | |
| 3834 | 3836 | } |
| 3835 | 3837 | if( g.localOpen ){ |
| 3836 | 3838 | manifest_to_disk(rid); |
| 3837 | 3839 | } |
| 3838 | 3840 | } |
| 3839 | 3841 |
| --- 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 | @ — part of check-in |
| 1818 | hyperlink_to_uuid(zVers); |
| 1819 | }else{ |
| 1820 | @ — 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 | @ — part of check-in |
| 1818 | hyperlink_to_version(zVers); |
| 1819 | }else{ |
| 1820 | @ — 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 @@ | ||
| 54 | 54 | |
| 55 | 55 | |
| 56 | 56 | /* |
| 57 | 57 | ** Print common information about a particular record. |
| 58 | 58 | ** |
| 59 | -** * The UUID | |
| 59 | +** * The artifact hash | |
| 60 | 60 | ** * The record ID |
| 61 | 61 | ** * mtime and ctime |
| 62 | 62 | ** * who signed it |
| 63 | 63 | ** |
| 64 | 64 | */ |
| 65 | 65 | void show_common_info( |
| 66 | 66 | 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:" */ | |
| 68 | 68 | int showComment, /* True to show the check-in comment */ |
| 69 | 69 | int showFamily /* True to show parents and children */ |
| 70 | 70 | ){ |
| 71 | 71 | Stmt q; |
| 72 | 72 | char *zComment = 0; |
| @@ -78,11 +78,11 @@ | ||
| 78 | 78 | zDate = db_text(0, |
| 79 | 79 | "SELECT datetime(mtime) || ' UTC' FROM event WHERE objid=%d", |
| 80 | 80 | rid |
| 81 | 81 | ); |
| 82 | 82 | /* 01234567890123 */ |
| 83 | - fossil_print("%-13s %.40s %s\n", zUuidName, zUuid, zDate ? zDate : ""); | |
| 83 | + fossil_print("%-13s %.40s %s\n", zRecDesc, zUuid, zDate ? zDate : ""); | |
| 84 | 84 | free(zDate); |
| 85 | 85 | if( showComment ){ |
| 86 | 86 | zComment = db_text(0, |
| 87 | 87 | "SELECT coalesce(ecomment,comment) || " |
| 88 | 88 | " ' (user: ' || coalesce(euser,user,'?') || ')' " |
| @@ -274,11 +274,11 @@ | ||
| 274 | 274 | int rid; |
| 275 | 275 | rid = name_to_rid(g.argv[2]); |
| 276 | 276 | if( rid==0 ){ |
| 277 | 277 | fossil_fatal("no such object: %s", g.argv[2]); |
| 278 | 278 | } |
| 279 | - show_common_info(rid, "uuid:", 1, 1); | |
| 279 | + show_common_info(rid, "hash:", 1, 1); | |
| 280 | 280 | } |
| 281 | 281 | } |
| 282 | 282 | |
| 283 | 283 | /* |
| 284 | 284 | ** Show the context graph (immediate parents and children) for |
| @@ -747,11 +747,11 @@ | ||
| 747 | 747 | @ <span class="infoTag">%h(zTagname)</span> |
| 748 | 748 | } |
| 749 | 749 | if( tagtype==2 ){ |
| 750 | 750 | if( zOrigUuid && zOrigUuid[0] ){ |
| 751 | 751 | @ inherited from |
| 752 | - hyperlink_to_uuid(zOrigUuid); | |
| 752 | + hyperlink_to_version(zOrigUuid); | |
| 753 | 753 | }else{ |
| 754 | 754 | @ propagates to descendants |
| 755 | 755 | } |
| 756 | 756 | } |
| 757 | 757 | if( zSrcUuid && zSrcUuid[0] ){ |
| @@ -758,11 +758,11 @@ | ||
| 758 | 758 | if( tagtype==0 ){ |
| 759 | 759 | @ by |
| 760 | 760 | }else{ |
| 761 | 761 | @ added by |
| 762 | 762 | } |
| 763 | - hyperlink_to_uuid(zSrcUuid); | |
| 763 | + hyperlink_to_version(zSrcUuid); | |
| 764 | 764 | @ on |
| 765 | 765 | hyperlink_to_date(zDate,0); |
| 766 | 766 | } |
| 767 | 767 | @ </li> |
| 768 | 768 | } |
| @@ -829,12 +829,12 @@ | ||
| 829 | 829 | int rid; |
| 830 | 830 | int isLeaf; |
| 831 | 831 | int diffType; /* 0: no diff, 1: unified, 2: side-by-side */ |
| 832 | 832 | u64 diffFlags; /* Flag parameter for text_diff() */ |
| 833 | 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) */ | |
| 834 | + const char *zUuid; /* Hash of zName, found via blob.uuid */ | |
| 835 | + const char *zParent; /* Hash of the parent check-in (if any) */ | |
| 836 | 836 | const char *zRe; /* regex parameter */ |
| 837 | 837 | ReCompiled *pRe = 0; /* regex */ |
| 838 | 838 | const char *zW; /* URL param for ignoring whitespace */ |
| 839 | 839 | const char *zPage = "vinfo"; /* Page that shows diffs */ |
| 840 | 840 | const char *zPageHide = "ci"; /* Page that hides diffs */ |
| @@ -1324,11 +1324,11 @@ | ||
| 1324 | 1324 | db_end_transaction(1); /* ROLLBACK */ |
| 1325 | 1325 | } |
| 1326 | 1326 | |
| 1327 | 1327 | /* |
| 1328 | 1328 | ** WEBPAGE: winfo |
| 1329 | -** URL: /winfo?name=UUID | |
| 1329 | +** URL: /winfo?name=HASH | |
| 1330 | 1330 | ** |
| 1331 | 1331 | ** Display information about a wiki page. |
| 1332 | 1332 | */ |
| 1333 | 1333 | void winfo_page(void){ |
| 1334 | 1334 | int rid; |
| @@ -1485,11 +1485,11 @@ | ||
| 1485 | 1485 | Blob comment; |
| 1486 | 1486 | int wikiFlags = WIKI_INLINE|WIKI_NOBADLINKS; |
| 1487 | 1487 | if( db_get_boolean("timeline-block-markup", 0)==0 ){ |
| 1488 | 1488 | wikiFlags |= WIKI_NOBLOCK; |
| 1489 | 1489 | } |
| 1490 | - hyperlink_to_uuid(zUuid); | |
| 1490 | + hyperlink_to_version(zUuid); | |
| 1491 | 1491 | blob_zero(&comment); |
| 1492 | 1492 | db_column_blob(&q, 2, &comment); |
| 1493 | 1493 | wiki_convert(&comment, 0, wikiFlags); |
| 1494 | 1494 | blob_reset(&comment); |
| 1495 | 1495 | @ (user: |
| @@ -1813,14 +1813,14 @@ | ||
| 1813 | 1813 | } |
| 1814 | 1814 | if( showDetail ){ |
| 1815 | 1815 | @ <li> |
| 1816 | 1816 | hyperlink_to_date(zDate,""); |
| 1817 | 1817 | @ — part of check-in |
| 1818 | - hyperlink_to_uuid(zVers); | |
| 1818 | + hyperlink_to_version(zVers); | |
| 1819 | 1819 | }else{ |
| 1820 | 1820 | @ — part of check-in |
| 1821 | - hyperlink_to_uuid(zVers); | |
| 1821 | + hyperlink_to_version(zVers); | |
| 1822 | 1822 | @ at |
| 1823 | 1823 | hyperlink_to_date(zDate,""); |
| 1824 | 1824 | } |
| 1825 | 1825 | if( zBr && zBr[0] ){ |
| 1826 | 1826 | @ on branch %z(href("%R/timeline?r=%T",zBr))%h(zBr)</a> |
| @@ -1919,11 +1919,11 @@ | ||
| 1919 | 1919 | @ Forum post |
| 1920 | 1920 | }else{ |
| 1921 | 1921 | @ Tag referencing |
| 1922 | 1922 | } |
| 1923 | 1923 | if( zType[0]!='e' || eventTagId == 0){ |
| 1924 | - hyperlink_to_uuid(zUuid); | |
| 1924 | + hyperlink_to_version(zUuid); | |
| 1925 | 1925 | } |
| 1926 | 1926 | @ - %!W(zCom) by |
| 1927 | 1927 | hyperlink_to_user(zUser,zDate," on"); |
| 1928 | 1928 | hyperlink_to_date(zDate, "."); |
| 1929 | 1929 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| @@ -1951,11 +1951,11 @@ | ||
| 1951 | 1951 | @ Also attachment "%h(zFilename)" to |
| 1952 | 1952 | }else{ |
| 1953 | 1953 | @ Attachment "%h(zFilename)" to |
| 1954 | 1954 | } |
| 1955 | 1955 | objType |= OBJTYPE_ATTACHMENT; |
| 1956 | - if( fossil_is_uuid(zTarget) ){ | |
| 1956 | + if( fossil_is_artifact_hash(zTarget) ){ | |
| 1957 | 1957 | if( db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'", |
| 1958 | 1958 | zTarget) |
| 1959 | 1959 | ){ |
| 1960 | 1960 | if( g.perm.Hyperlink && g.anon.RdTkt ){ |
| 1961 | 1961 | @ ticket [%z(href("%R/tktview?name=%!S",zTarget))%S(zTarget)</a>] |
| @@ -2011,11 +2011,11 @@ | ||
| 2011 | 2011 | |
| 2012 | 2012 | |
| 2013 | 2013 | /* |
| 2014 | 2014 | ** WEBPAGE: fdiff |
| 2015 | 2015 | ** WEBPAGE: localdiff |
| 2016 | -** URL: fdiff?v1=UUID&v2=UUID | |
| 2016 | +** URL: fdiff?v1=HASH&v2=HASH | |
| 2017 | 2017 | ** URL: localdiff?name=filename |
| 2018 | 2018 | ** |
| 2019 | 2019 | ** Two arguments, v1 and v2, identify the artifacts to be diffed. |
| 2020 | 2020 | ** Show diff side by side unless sbs is 0. Generate plain text if |
| 2021 | 2021 | ** "patch" is present, otherwise generate "pretty" HTML. |
| @@ -2227,18 +2227,18 @@ | ||
| 2227 | 2227 | ** is by the full-length SHA1 or SHA3 hash. Abbreviations are not |
| 2228 | 2228 | ** accepted. |
| 2229 | 2229 | */ |
| 2230 | 2230 | void secure_rawartifact_page(void){ |
| 2231 | 2231 | int rid = 0; |
| 2232 | - const char *zUuid = PD("name", ""); | |
| 2232 | + const char *zName = PD("name", ""); | |
| 2233 | 2233 | |
| 2234 | 2234 | login_check_credentials(); |
| 2235 | 2235 | 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); | |
| 2237 | 2237 | if( rid==0 ){ |
| 2238 | 2238 | cgi_set_status(404, "Not Found"); |
| 2239 | - @ Unknown artifact: "%h(zUuid)" | |
| 2239 | + @ Unknown artifact: "%h(zName)" | |
| 2240 | 2240 | return; |
| 2241 | 2241 | } |
| 2242 | 2242 | g.isConst = 1; |
| 2243 | 2243 | deliver_artifact(rid, P("m")); |
| 2244 | 2244 | } |
| @@ -3025,16 +3025,18 @@ | ||
| 3025 | 3025 | } |
| 3026 | 3026 | |
| 3027 | 3027 | |
| 3028 | 3028 | /* |
| 3029 | 3029 | ** WEBPAGE: info |
| 3030 | -** URL: info/ARTIFACTID | |
| 3030 | +** URL: info/NAME | |
| 3031 | 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. | |
| 3032 | +** The NAME argument is any valid artifact name: an artifact hash, | |
| 3033 | +** a timestamp, a tag name, etc. | |
| 3034 | 3034 | ** |
| 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. | |
| 3036 | 3038 | */ |
| 3037 | 3039 | void info_page(void){ |
| 3038 | 3040 | const char *zName; |
| 3039 | 3041 | Blob uuid; |
| 3040 | 3042 | int rid; |
| @@ -3644,17 +3646,17 @@ | ||
| 3644 | 3646 | blob_append(&prompt, ".\n# Lines beginning with a # are ignored.\n", -1); |
| 3645 | 3647 | prompt_for_user_comment(pComment, &prompt); |
| 3646 | 3648 | blob_reset(&prompt); |
| 3647 | 3649 | } |
| 3648 | 3650 | |
| 3649 | -#define AMEND_USAGE_STMT "UUID OPTION ?OPTION ...?" | |
| 3651 | +#define AMEND_USAGE_STMT "HASH OPTION ?OPTION ...?" | |
| 3650 | 3652 | /* |
| 3651 | 3653 | ** COMMAND: amend |
| 3652 | 3654 | ** |
| 3653 | -** Usage: %fossil amend UUID OPTION ?OPTION ...? | |
| 3655 | +** Usage: %fossil amend HASH OPTION ?OPTION ...? | |
| 3654 | 3656 | ** |
| 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. | |
| 3656 | 3658 | ** |
| 3657 | 3659 | ** Options: |
| 3658 | 3660 | ** |
| 3659 | 3661 | ** --author USER Make USER the author for check-in |
| 3660 | 3662 | ** -m|--comment COMMENT Make COMMENT the check-in comment |
| @@ -3738,11 +3740,11 @@ | ||
| 3738 | 3740 | verify_all_options(); |
| 3739 | 3741 | if( g.argc<3 || g.argc>=4 ) usage(AMEND_USAGE_STMT); |
| 3740 | 3742 | rid = name_to_typed_rid(g.argv[2], "ci"); |
| 3741 | 3743 | if( rid==0 && !is_a_version(rid) ) fossil_fatal("no such check-in"); |
| 3742 | 3744 | 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"); | |
| 3744 | 3746 | zComment = db_text(0, "SELECT coalesce(ecomment,comment)" |
| 3745 | 3747 | " FROM event WHERE objid=%d", rid); |
| 3746 | 3748 | zUser = db_text(0, "SELECT coalesce(euser,user)" |
| 3747 | 3749 | " FROM event WHERE objid=%d", rid); |
| 3748 | 3750 | zDate = db_text(0, "SELECT datetime(mtime)" |
| @@ -3828,11 +3830,11 @@ | ||
| 3828 | 3830 | if( fHide && !fHasHidden ) hide_branch(); |
| 3829 | 3831 | if( fClose && !fHasClosed ) close_leaf(rid); |
| 3830 | 3832 | if( zNewBranch && zNewBranch[0] ) change_branch(rid,zNewBranch); |
| 3831 | 3833 | apply_newtags(&ctrl, rid, zUuid, zUserOvrd, fDryRun); |
| 3832 | 3834 | if( fDryRun==0 ){ |
| 3833 | - show_common_info(rid, "uuid:", 1, 0); | |
| 3835 | + show_common_info(rid, "hash:", 1, 0); | |
| 3834 | 3836 | } |
| 3835 | 3837 | if( g.localOpen ){ |
| 3836 | 3838 | manifest_to_disk(rid); |
| 3837 | 3839 | } |
| 3838 | 3840 | } |
| 3839 | 3841 |
| --- 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 | @ — part of check-in |
| 1818 | hyperlink_to_uuid(zVers); |
| 1819 | }else{ |
| 1820 | @ — 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 | @ — part of check-in |
| 1818 | hyperlink_to_version(zVers); |
| 1819 | }else{ |
| 1820 | @ — 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 |
+1
-1
| --- src/json_finfo.c | ||
| +++ src/json_finfo.c | ||
| @@ -89,11 +89,11 @@ | ||
| 89 | 89 | char * zU = NULL; |
| 90 | 90 | int rc = name_to_uuid2( zCheckin, "ci", &zU ); |
| 91 | 91 | /*printf("zCheckin=[%s], zU=[%s]", zCheckin, zU);*/ |
| 92 | 92 | if(rc<=0){ |
| 93 | 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"); | |
| 94 | + "Check-in hash %s.", (rc<0) ? "is ambiguous" : "not found"); | |
| 95 | 95 | blob_reset(&sql); |
| 96 | 96 | return NULL; |
| 97 | 97 | } |
| 98 | 98 | blob_append_sql(&sql, " AND ci.uuid='%q'", zU); |
| 99 | 99 | free(zU); |
| 100 | 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 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 @@ | ||
| 117 | 117 | Blob uu = empty_blob; |
| 118 | 118 | int rc; |
| 119 | 119 | blob_append(&uu, zName, -1); |
| 120 | 120 | rc = name_to_uuid(&uu, 9, "*"); |
| 121 | 121 | 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!"); | |
| 123 | 123 | blob_reset(&uu); |
| 124 | 124 | goto error; |
| 125 | 125 | } |
| 126 | 126 | cson_object_set(pay, "appliedTo", json_new_string(blob_buffer(&uu))); |
| 127 | 127 | blob_reset(&uu); |
| 128 | 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 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 @@ | ||
| 159 | 159 | char *zLocalDbName; /* Name of the local database file */ |
| 160 | 160 | char *zOpenRevision; /* Check-in version to use during database open */ |
| 161 | 161 | const char *zCmdName; /* Name of the Fossil command currently running */ |
| 162 | 162 | int localOpen; /* True if the local database is open */ |
| 163 | 163 | 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 */ | |
| 165 | 165 | int eHashPolicy; /* Current hash policy. One of HPOLICY_* */ |
| 166 | 166 | int fSqlTrace; /* True if --sqltrace flag is present */ |
| 167 | 167 | int fSqlStats; /* True if --sqltrace or --sqlstats are present */ |
| 168 | 168 | int fSqlPrint; /* True if --sqlprint flag is present */ |
| 169 | 169 | int fCgiTrace; /* True if --cgitrace is enabled */ |
| 170 | 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 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 |
-2
| --- src/main.mk | ||
| +++ src/main.mk | ||
| @@ -608,11 +608,10 @@ | ||
| 608 | 608 | -DSQLITE_DEFAULT_MEMSTATUS=0 \ |
| 609 | 609 | -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \ |
| 610 | 610 | -DSQLITE_LIKE_DOESNT_MATCH_BLOBS \ |
| 611 | 611 | -DSQLITE_OMIT_DECLTYPE \ |
| 612 | 612 | -DSQLITE_OMIT_DEPRECATED \ |
| 613 | - -DSQLITE_OMIT_GET_TABLE \ | |
| 614 | 613 | -DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 615 | 614 | -DSQLITE_OMIT_SHARED_CACHE \ |
| 616 | 615 | -DSQLITE_OMIT_LOAD_EXTENSION \ |
| 617 | 616 | -DSQLITE_MAX_EXPR_DEPTH=0 \ |
| 618 | 617 | -DSQLITE_USE_ALLOCA \ |
| @@ -636,11 +635,10 @@ | ||
| 636 | 635 | -DSQLITE_DEFAULT_MEMSTATUS=0 \ |
| 637 | 636 | -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \ |
| 638 | 637 | -DSQLITE_LIKE_DOESNT_MATCH_BLOBS \ |
| 639 | 638 | -DSQLITE_OMIT_DECLTYPE \ |
| 640 | 639 | -DSQLITE_OMIT_DEPRECATED \ |
| 641 | - -DSQLITE_OMIT_GET_TABLE \ | |
| 642 | 640 | -DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 643 | 641 | -DSQLITE_OMIT_SHARED_CACHE \ |
| 644 | 642 | -DSQLITE_OMIT_LOAD_EXTENSION \ |
| 645 | 643 | -DSQLITE_MAX_EXPR_DEPTH=0 \ |
| 646 | 644 | -DSQLITE_USE_ALLOCA \ |
| 647 | 645 |
| --- 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 |
-1
| --- src/makemake.tcl | ||
| +++ src/makemake.tcl | ||
| @@ -192,11 +192,10 @@ | ||
| 192 | 192 | -DSQLITE_DEFAULT_MEMSTATUS=0 |
| 193 | 193 | -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 |
| 194 | 194 | -DSQLITE_LIKE_DOESNT_MATCH_BLOBS |
| 195 | 195 | -DSQLITE_OMIT_DECLTYPE |
| 196 | 196 | -DSQLITE_OMIT_DEPRECATED |
| 197 | - -DSQLITE_OMIT_GET_TABLE | |
| 198 | 197 | -DSQLITE_OMIT_PROGRESS_CALLBACK |
| 199 | 198 | -DSQLITE_OMIT_SHARED_CACHE |
| 200 | 199 | -DSQLITE_OMIT_LOAD_EXTENSION |
| 201 | 200 | -DSQLITE_MAX_EXPR_DEPTH=0 |
| 202 | 201 | -DSQLITE_USE_ALLOCA |
| 203 | 202 |
| --- 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 @@ | ||
| 2434 | 2434 | /* We assume that we're attaching to a wiki page until we |
| 2435 | 2435 | ** prove otherwise (which could on a later artifact if we |
| 2436 | 2436 | ** process the attachment artifact before the artifact to |
| 2437 | 2437 | ** which it is attached!) */ |
| 2438 | 2438 | char attachToType = 'w'; |
| 2439 | - if( fossil_is_uuid(p->zAttachTarget) ){ | |
| 2439 | + if( fossil_is_artifact_hash(p->zAttachTarget) ){ | |
| 2440 | 2440 | if( db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'", |
| 2441 | 2441 | p->zAttachTarget) |
| 2442 | 2442 | ){ |
| 2443 | 2443 | attachToType = 't'; /* Attaching to known ticket */ |
| 2444 | 2444 | }else if( db_exists("SELECT 1 FROM tag WHERE tagname='event-%q'", |
| 2445 | 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_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 @@ | ||
| 446 | 446 | } |
| 447 | 447 | return rid; |
| 448 | 448 | } |
| 449 | 449 | |
| 450 | 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. | |
| 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. | |
| 454 | 458 | ** |
| 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 | |
| 456 | 460 | ** 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") | |
| 458 | 464 | ** |
| 459 | 465 | ** If the input is not a tag, then try to match it as an ISO-8601 date |
| 460 | 466 | ** string YYYY-MM-DD HH:MM:SS and pick the nearest check-in to that date. |
| 461 | 467 | ** If the input is of the form "date:*" then always resolve the name as |
| 462 | 468 | ** a date. The forms "utc:*" and "local:" are deprecated. |
| @@ -481,16 +487,16 @@ | ||
| 481 | 487 | } |
| 482 | 488 | |
| 483 | 489 | /* |
| 484 | 490 | ** This routine is similar to name_to_uuid() except in the form it |
| 485 | 491 | ** 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 | |
| 488 | 494 | ** zName does not resolve, 0 is returned. If it is ambiguous, a |
| 489 | 495 | ** negative value is returned. On success the rid is returned and |
| 490 | 496 | ** 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. | |
| 492 | 498 | */ |
| 493 | 499 | int name_to_uuid2(const char *zName, const char *zType, char **pUuid){ |
| 494 | 500 | int rid = symbolic_name_to_rid(zName, zType); |
| 495 | 501 | if((rid>0) && pUuid){ |
| 496 | 502 | *pUuid = db_text(NULL, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| @@ -499,12 +505,13 @@ | ||
| 499 | 505 | } |
| 500 | 506 | |
| 501 | 507 | |
| 502 | 508 | /* |
| 503 | 509 | ** 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. | |
| 506 | 513 | */ |
| 507 | 514 | int name_collisions(const char *zName){ |
| 508 | 515 | int c = 0; /* count of collisions for zName */ |
| 509 | 516 | int nLen; /* length of zName */ |
| 510 | 517 | nLen = strlen(zName); |
| @@ -633,11 +640,11 @@ | ||
| 633 | 640 | const char *zTitle = db_column_text(&q, 2); |
| 634 | 641 | @ <li><p><a href="%R/%T(zSrc)/%!S(zUuid)"> |
| 635 | 642 | @ %s(zUuid)</a> - |
| 636 | 643 | @ <ul></ul> |
| 637 | 644 | @ Ticket |
| 638 | - hyperlink_to_uuid(zUuid); | |
| 645 | + hyperlink_to_version(zUuid); | |
| 639 | 646 | @ - %h(zTitle). |
| 640 | 647 | @ <ul><li> |
| 641 | 648 | object_description(rid, 0, 0, 0); |
| 642 | 649 | @ </li></ul> |
| 643 | 650 | @ </p></li> |
| 644 | 651 |
| --- 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 @@ | ||
| 97 | 97 | #define etHTTPIZE 18 /* Make text safe for HTTP. "/" encoded as %2f */ |
| 98 | 98 | #define etURLIZE 19 /* Make text safe for HTTP. "/" not encoded */ |
| 99 | 99 | #define etFOSSILIZE 20 /* The fossil header encoding format. */ |
| 100 | 100 | #define etPATH 21 /* Path type */ |
| 101 | 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 */ | |
| 102 | +#define etSTRINGID 23 /* String with length limit for a hash prefix: %S */ | |
| 103 | 103 | #define etROOT 24 /* String value of g.zTop: %R */ |
| 104 | 104 | #define etJSONSTR 25 /* String encoded as a JSON string literal: %j |
| 105 | 105 | Use %!j to include double-quotes around it. */ |
| 106 | 106 | |
| 107 | 107 | |
| 108 | 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 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 @@ | ||
| 456 | 456 | ** ==== Make a backup of your repository before using this command! ==== |
| 457 | 457 | ** |
| 458 | 458 | ** ==== FURTHER WARNING: This command is a work-in-progress and may yet ==== |
| 459 | 459 | ** ==== contain bugs. ==== |
| 460 | 460 | ** |
| 461 | -** fossil purge artifacts UUID... ?OPTIONS? | |
| 461 | +** fossil purge artifacts HASH... ?OPTIONS? | |
| 462 | 462 | ** |
| 463 | -** Move arbitrary artifacts identified by the UUID list into the | |
| 463 | +** Move arbitrary artifacts identified by the HASH list into the | |
| 464 | 464 | ** graveyard. |
| 465 | 465 | ** |
| 466 | -** fossil purge cat UUID... | |
| 466 | +** fossil purge cat HASH... | |
| 467 | 467 | ** |
| 468 | 468 | ** Write the content of one or more artifacts in the graveyard onto |
| 469 | 469 | ** standard output. |
| 470 | 470 | ** |
| 471 | 471 | ** fossil purge checkins TAGS... ?OPTIONS? |
| @@ -509,12 +509,12 @@ | ||
| 509 | 509 | ** |
| 510 | 510 | ** --explain Make no changes, but show what would happen. |
| 511 | 511 | ** --dry-run An alias for --explain |
| 512 | 512 | ** |
| 513 | 513 | ** SUMMARY: |
| 514 | -** fossil purge artifacts UUID.. [OPTIONS] | |
| 515 | -** fossil purge cat UUID... | |
| 514 | +** fossil purge artifacts HASH.. [OPTIONS] | |
| 515 | +** fossil purge cat HASH... | |
| 516 | 516 | ** fossil purge checkins TAGS... [OPTIONS] |
| 517 | 517 | ** fossil purge files FILENAME... [OPTIONS] |
| 518 | 518 | ** fossil purge list |
| 519 | 519 | ** fossil purge obliterate ID... |
| 520 | 520 | ** fossil purge tickets NAME... [OPTIONS] |
| @@ -547,11 +547,11 @@ | ||
| 547 | 547 | purge_artifact_list("ok", "", purgeFlags); |
| 548 | 548 | db_end_transaction(0); |
| 549 | 549 | }else if( strncmp(zSubcmd, "cat", n)==0 ){ |
| 550 | 550 | int i, piid; |
| 551 | 551 | Blob content; |
| 552 | - if( g.argc<4 ) usage("cat UUID..."); | |
| 552 | + if( g.argc<4 ) usage("cat HASH..."); | |
| 553 | 553 | for(i=3; i<g.argc; i++){ |
| 554 | 554 | piid = db_int(0, "SELECT piid FROM purgeitem WHERE uuid LIKE '%q%%'", |
| 555 | 555 | g.argv[i]); |
| 556 | 556 | if( piid==0 ) fossil_fatal("no such item: %s", g.argv[3]); |
| 557 | 557 | purge_extract_item(piid, &content); |
| 558 | 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 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 @@ | ||
| 1149 | 1149 | */ |
| 1150 | 1150 | void private_export(char *zFileName) |
| 1151 | 1151 | { |
| 1152 | 1152 | Stmt q; |
| 1153 | 1153 | 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); | |
| 1155 | 1155 | db_prepare(&q, |
| 1156 | 1156 | "SELECT uuid FROM blob WHERE rid IN ( SELECT rid FROM private );"); |
| 1157 | 1157 | while( db_step(&q)==SQLITE_ROW ){ |
| 1158 | 1158 | const char *zUuid = db_column_text(&q, 0); |
| 1159 | 1159 | blob_append(&fctx, zUuid, -1); |
| 1160 | 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 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 @@ | ||
| 670 | 670 | const char **azArg, /* Text of data in all columns */ |
| 671 | 671 | const char **azName /* Names of the columns */ |
| 672 | 672 | ){ |
| 673 | 673 | struct GenerateHTML *pState = (struct GenerateHTML*)pUser; |
| 674 | 674 | int i; |
| 675 | - const char *zTid; /* Ticket UUID. (value of column named '#') */ | |
| 675 | + const char *zTid; /* Ticket hash. (value of column named '#') */ | |
| 676 | 676 | const char *zBg = 0; /* Use this background color */ |
| 677 | 677 | |
| 678 | 678 | /* Do initialization |
| 679 | 679 | */ |
| 680 | 680 | if( pState->nCount==0 ){ |
| 681 | 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 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 @@ | ||
| 22 | 22 | #include "rss.h" |
| 23 | 23 | #include <assert.h> |
| 24 | 24 | |
| 25 | 25 | /* |
| 26 | 26 | ** 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 | |
| 28 | 28 | ** |
| 29 | 29 | ** Produce an RSS feed of the timeline. |
| 30 | 30 | ** |
| 31 | 31 | ** TYPE may be: all, ci (show check-ins only), t (show ticket changes only), |
| 32 | 32 | ** w (show wiki only), e (show tech notes only), f (show forum posts only), |
| 33 | 33 | ** g (show tag/branch changes only). |
| 34 | 34 | ** |
| 35 | 35 | ** LIMIT is the number of items to show. |
| 36 | 36 | ** |
| 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 | |
| 38 | 38 | ** filters for a tag, and wiki=NAME for a wiki page. Only one may be used. |
| 39 | 39 | ** |
| 40 | 40 | ** In addition, name=FILENAME filters for a specific file. This may be |
| 41 | 41 | ** combined with one of the other filters (useful for looking at a specific |
| 42 | 42 | ** branch). |
| @@ -231,11 +231,11 @@ | ||
| 231 | 231 | ** w (show wiki only). |
| 232 | 232 | ** |
| 233 | 233 | ** -limit|n LIMIT |
| 234 | 234 | ** The maximum number of items to show. |
| 235 | 235 | ** |
| 236 | -** -tkt UUID | |
| 236 | +** -tkt HASH | |
| 237 | 237 | ** Filters for only those events for the specified ticket. |
| 238 | 238 | ** |
| 239 | 239 | ** -tag TAG |
| 240 | 240 | ** filters for a tag |
| 241 | 241 | ** |
| 242 | 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=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 @@ | ||
| 266 | 266 | @ mid INTEGER, -- Check-in that contains fid |
| 267 | 267 | @ fid INTEGER, -- New file content. 0 if deleted |
| 268 | 268 | @ pmid INTEGER, -- Check-in that contains pid |
| 269 | 269 | @ pid INTEGER, -- Prev file content. 0 if new. -1 merge |
| 270 | 270 | @ 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 | |
| 272 | 272 | @ mperm INTEGER, -- File permissions. 1==exec |
| 273 | 273 | @ isaux BOOLEAN DEFAULT 0 -- TRUE if pmid is the primary |
| 274 | 274 | @ ); |
| 275 | 275 | @ CREATE INDEX mlink_i1 ON mlink(mid); |
| 276 | 276 | @ CREATE INDEX mlink_i2 ON mlink(fnid); |
| @@ -321,11 +321,11 @@ | ||
| 321 | 321 | @ omtime DATETIME -- Original unchanged date+time, or NULL |
| 322 | 322 | @ ); |
| 323 | 323 | @ CREATE INDEX event_i1 ON event(mtime); |
| 324 | 324 | @ |
| 325 | 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. | |
| 326 | +@ -- file hash but we do not (yet) know the file content. | |
| 327 | 327 | @ -- |
| 328 | 328 | @ CREATE TABLE phantom( |
| 329 | 329 | @ rid INTEGER PRIMARY KEY -- Record ID of the phantom |
| 330 | 330 | @ ); |
| 331 | 331 | @ |
| @@ -362,12 +362,12 @@ | ||
| 362 | 362 | @ |
| 363 | 363 | @ -- Each artifact can have one or more tags. A tag |
| 364 | 364 | @ -- is defined by a row in the next table. |
| 365 | 365 | @ -- |
| 366 | 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 | |
| 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 | 369 | @ -- names to baselines are branches are of the form "sym-NAME" where |
| 370 | 370 | @ -- NAME is the symbolic name. |
| 371 | 371 | @ -- |
| 372 | 372 | @ CREATE TABLE tag( |
| 373 | 373 | @ tagid INTEGER PRIMARY KEY, -- Numeric tag ID |
| @@ -421,12 +421,12 @@ | ||
| 421 | 421 | @ -- |
| 422 | 422 | @ CREATE TABLE attachment( |
| 423 | 423 | @ attachid INTEGER PRIMARY KEY, -- Local id for this attachment |
| 424 | 424 | @ isLatest BOOLEAN DEFAULT 0, -- True if this is the one to use |
| 425 | 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 | |
| 426 | +@ src TEXT, -- Hash of the attachment. NULL to delete | |
| 427 | +@ target TEXT, -- Object attached to. Wikiname or Tkt hash | |
| 428 | 428 | @ filename TEXT, -- Filename for the attachment |
| 429 | 429 | @ comment TEXT, -- Comment associated with this attachment |
| 430 | 430 | @ user TEXT -- Name of user adding attachment |
| 431 | 431 | @ ); |
| 432 | 432 | @ CREATE INDEX attachment_idx1 ON attachment(target, filename, mtime); |
| 433 | 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 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 |
+7
| --- src/security_audit.c | ||
| +++ src/security_audit.c | ||
| @@ -521,10 +521,17 @@ | ||
| 521 | 521 | nCgi = nFile==0 ? 0 : db_int(0,"SELECT count(*) FROM sfile WHERE isexe"); |
| 522 | 522 | @ <li><p> CGI Extensions are enabled with a document root |
| 523 | 523 | @ at <a href='%R/extfilelist'>%h(g.zExtRoot)</a> holding |
| 524 | 524 | @ %d(nCgi) CGIs and %d(nFile-nCgi) static content and data files. |
| 525 | 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 | + } | |
| 526 | 533 | |
| 527 | 534 | @ <li><p> User capability summary: |
| 528 | 535 | capability_summary(); |
| 529 | 536 | |
| 530 | 537 | |
| 531 | 538 |
| --- 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 @@ | ||
| 9700 | 9700 | char **azFilter; /* Array of xFilter rejection GLOB patterns */ |
| 9701 | 9701 | sqlite3_session *p; /* The open session */ |
| 9702 | 9702 | }; |
| 9703 | 9703 | #endif |
| 9704 | 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 | 9705 | typedef struct ExpertInfo ExpertInfo; |
| 9718 | 9706 | struct ExpertInfo { |
| 9719 | 9707 | sqlite3expert *pExpert; |
| 9720 | 9708 | int bVerbose; |
| 9721 | 9709 | }; |
| @@ -9781,12 +9769,13 @@ | ||
| 9781 | 9769 | char zTestcase[30]; /* Name of current test case */ |
| 9782 | 9770 | char colSeparator[20]; /* Column separator character for several modes */ |
| 9783 | 9771 | char rowSeparator[20]; /* Row separator character for MODE_Ascii */ |
| 9784 | 9772 | char colSepPrior[20]; /* Saved column separator */ |
| 9785 | 9773 | 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[] */ | |
| 9788 | 9777 | char nullValue[20]; /* The text to print when a NULL comes back from |
| 9789 | 9778 | ** the database */ |
| 9790 | 9779 | char outfile[FILENAME_MAX]; /* Filename for *out */ |
| 9791 | 9780 | const char *zDbFilename; /* name of the database file */ |
| 9792 | 9781 | char *zFreeOnClose; /* Filename to free when closing */ |
| @@ -9867,10 +9856,13 @@ | ||
| 9867 | 9856 | #define MODE_Csv 8 /* Quote strings, numbers are plain */ |
| 9868 | 9857 | #define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */ |
| 9869 | 9858 | #define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */ |
| 9870 | 9859 | #define MODE_Pretty 11 /* Pretty-print schemas */ |
| 9871 | 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 */ | |
| 9872 | 9864 | |
| 9873 | 9865 | static const char *modeDescr[] = { |
| 9874 | 9866 | "line", |
| 9875 | 9867 | "column", |
| 9876 | 9868 | "list", |
| @@ -9881,11 +9873,14 @@ | ||
| 9881 | 9873 | "tcl", |
| 9882 | 9874 | "csv", |
| 9883 | 9875 | "explain", |
| 9884 | 9876 | "ascii", |
| 9885 | 9877 | "prettyprint", |
| 9886 | - "eqp" | |
| 9878 | + "eqp", | |
| 9879 | + "json", | |
| 9880 | + "markdown", | |
| 9881 | + "table" | |
| 9887 | 9882 | }; |
| 9888 | 9883 | |
| 9889 | 9884 | /* |
| 9890 | 9885 | ** These are the column/row/line separators used by the various |
| 9891 | 9886 | ** import/export modes. |
| @@ -10248,10 +10243,44 @@ | ||
| 10248 | 10243 | fputc(c, out); |
| 10249 | 10244 | } |
| 10250 | 10245 | } |
| 10251 | 10246 | fputc('"', out); |
| 10252 | 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 | +} | |
| 10253 | 10282 | |
| 10254 | 10283 | /* |
| 10255 | 10284 | ** Output the given string with characters that are special to |
| 10256 | 10285 | ** HTML escaped. |
| 10257 | 10286 | */ |
| @@ -10557,10 +10586,40 @@ | ||
| 10557 | 10586 | raw_printf(p->out, "Progress %u\n", p->nProgress); |
| 10558 | 10587 | } |
| 10559 | 10588 | return 0; |
| 10560 | 10589 | } |
| 10561 | 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 | +} | |
| 10562 | 10621 | |
| 10563 | 10622 | /* |
| 10564 | 10623 | ** This is the callback routine that the shell |
| 10565 | 10624 | ** invokes for each row of a query result. |
| 10566 | 10625 | */ |
| @@ -10567,11 +10626,11 @@ | ||
| 10567 | 10626 | static int shell_callback( |
| 10568 | 10627 | void *pArg, |
| 10569 | 10628 | int nArg, /* Number of result columns */ |
| 10570 | 10629 | char **azArg, /* Text of each result column */ |
| 10571 | 10630 | char **azCol, /* Column names */ |
| 10572 | - int *aiType /* Column types */ | |
| 10631 | + int *aiType /* Column types. Might be NULL */ | |
| 10573 | 10632 | ){ |
| 10574 | 10633 | int i; |
| 10575 | 10634 | ShellState *p = (ShellState*)pArg; |
| 10576 | 10635 | |
| 10577 | 10636 | if( azArg==0 ) return 0; |
| @@ -10588,85 +10647,36 @@ | ||
| 10588 | 10647 | utf8_printf(p->out,"%*s = %s%s", w, azCol[i], |
| 10589 | 10648 | azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator); |
| 10590 | 10649 | } |
| 10591 | 10650 | break; |
| 10592 | 10651 | } |
| 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); | |
| 10610 | 10656 | } |
| 10611 | 10657 | if( p->cnt++==0 ){ |
| 10612 | 10658 | 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); | |
| 10647 | 10662 | } |
| 10648 | 10663 | } |
| 10649 | 10664 | if( azArg==0 ) break; |
| 10650 | 10665 | 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 ){ | |
| 10658 | 10668 | w = strlenChar(azArg[i]); |
| 10659 | 10669 | } |
| 10660 | 10670 | if( i==1 && p->aiIndent && p->pStmt ){ |
| 10661 | 10671 | if( p->iIndent<p->nIndent ){ |
| 10662 | 10672 | utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], ""); |
| 10663 | 10673 | } |
| 10664 | 10674 | p->iIndent++; |
| 10665 | 10675 | } |
| 10666 | 10676 | 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); | |
| 10668 | 10678 | } |
| 10669 | 10679 | break; |
| 10670 | 10680 | } |
| 10671 | 10681 | case MODE_Semi: { /* .schema and .fullschema output */ |
| 10672 | 10682 | printSchemaLine(p->out, azArg[0], ";\n"); |
| @@ -10865,23 +10875,65 @@ | ||
| 10865 | 10875 | output_quoted_escaped_string(p->out, azArg[i]); |
| 10866 | 10876 | } |
| 10867 | 10877 | } |
| 10868 | 10878 | raw_printf(p->out,");\n"); |
| 10869 | 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; | |
| 10870 | 10922 | } |
| 10871 | 10923 | case MODE_Quote: { |
| 10872 | 10924 | if( azArg==0 ) break; |
| 10873 | 10925 | if( p->cnt==0 && p->showHeader ){ |
| 10874 | 10926 | for(i=0; i<nArg; i++){ |
| 10875 | - if( i>0 ) raw_printf(p->out, ","); | |
| 10927 | + if( i>0 ) fputs(p->colSeparator, p->out); | |
| 10876 | 10928 | output_quoted_string(p->out, azCol[i]); |
| 10877 | 10929 | } |
| 10878 | - raw_printf(p->out,"\n"); | |
| 10930 | + fputs(p->rowSeparator, p->out); | |
| 10879 | 10931 | } |
| 10880 | 10932 | p->cnt++; |
| 10881 | 10933 | for(i=0; i<nArg; i++){ |
| 10882 | - if( i>0 ) raw_printf(p->out, ","); | |
| 10934 | + if( i>0 ) fputs(p->colSeparator, p->out); | |
| 10883 | 10935 | if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ |
| 10884 | 10936 | utf8_printf(p->out,"NULL"); |
| 10885 | 10937 | }else if( aiType && aiType[i]==SQLITE_TEXT ){ |
| 10886 | 10938 | output_quoted_string(p->out, azArg[i]); |
| 10887 | 10939 | }else if( aiType && aiType[i]==SQLITE_INTEGER ){ |
| @@ -10899,11 +10951,11 @@ | ||
| 10899 | 10951 | utf8_printf(p->out,"%s", azArg[i]); |
| 10900 | 10952 | }else{ |
| 10901 | 10953 | output_quoted_string(p->out, azArg[i]); |
| 10902 | 10954 | } |
| 10903 | 10955 | } |
| 10904 | - raw_printf(p->out,"\n"); | |
| 10956 | + fputs(p->rowSeparator, p->out); | |
| 10905 | 10957 | break; |
| 10906 | 10958 | } |
| 10907 | 10959 | case MODE_Ascii: { |
| 10908 | 10960 | if( p->cnt++==0 && p->showHeader ){ |
| 10909 | 10961 | for(i=0; i<nArg; i++){ |
| @@ -11554,19 +11606,127 @@ | ||
| 11554 | 11606 | } |
| 11555 | 11607 | sqlite3_reset(pQ); |
| 11556 | 11608 | } |
| 11557 | 11609 | sqlite3_finalize(pQ); |
| 11558 | 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 | +} | |
| 11559 | 11711 | |
| 11560 | 11712 | /* |
| 11561 | 11713 | ** Run a prepared statement |
| 11562 | 11714 | */ |
| 11563 | 11715 | static void exec_prepared_stmt( |
| 11564 | 11716 | ShellState *pArg, /* Pointer to ShellState */ |
| 11565 | 11717 | sqlite3_stmt *pStmt /* Statment to run */ |
| 11566 | 11718 | ){ |
| 11567 | 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 | + } | |
| 11568 | 11728 | |
| 11569 | 11729 | /* perform the first step. this will tell us if we |
| 11570 | 11730 | ** have a result set or not and how wide it is. |
| 11571 | 11731 | */ |
| 11572 | 11732 | rc = sqlite3_step(pStmt); |
| @@ -11611,10 +11771,15 @@ | ||
| 11611 | 11771 | rc = sqlite3_step(pStmt); |
| 11612 | 11772 | } |
| 11613 | 11773 | } |
| 11614 | 11774 | } while( SQLITE_ROW == rc ); |
| 11615 | 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 | + } | |
| 11616 | 11781 | } |
| 11617 | 11782 | } |
| 11618 | 11783 | } |
| 11619 | 11784 | |
| 11620 | 11785 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| @@ -16883,19 +17048,28 @@ | ||
| 16883 | 17048 | }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){ |
| 16884 | 17049 | p->mode = MODE_Insert; |
| 16885 | 17050 | set_table_name(p, nArg>=3 ? azArg[2] : "table"); |
| 16886 | 17051 | }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){ |
| 16887 | 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); | |
| 16888 | 17055 | }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){ |
| 16889 | 17056 | p->mode = MODE_Ascii; |
| 16890 | 17057 | sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit); |
| 16891 | 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; | |
| 16892 | 17065 | }else if( nArg==1 ){ |
| 16893 | 17066 | raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]); |
| 16894 | 17067 | }else{ |
| 16895 | 17068 | 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"); | |
| 16897 | 17071 | rc = 1; |
| 16898 | 17072 | } |
| 16899 | 17073 | p->cMode = p->mode; |
| 16900 | 17074 | }else |
| 16901 | 17075 | |
| @@ -17992,11 +18166,11 @@ | ||
| 17992 | 18166 | utf8_printf(p->out,"%12.12s: ", "rowseparator"); |
| 17993 | 18167 | output_c_string(p->out, p->rowSeparator); |
| 17994 | 18168 | raw_printf(p->out, "\n"); |
| 17995 | 18169 | utf8_printf(p->out, "%12.12s: %s\n","stats", azBool[p->statsOn!=0]); |
| 17996 | 18170 | 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++) { | |
| 17998 | 18172 | raw_printf(p->out, "%d ", p->colWidth[i]); |
| 17999 | 18173 | } |
| 18000 | 18174 | raw_printf(p->out, "\n"); |
| 18001 | 18175 | utf8_printf(p->out, "%12.12s: %s\n", "filename", |
| 18002 | 18176 | p->zDbFilename ? p->zDbFilename : ""); |
| @@ -18541,11 +18715,15 @@ | ||
| 18541 | 18715 | #endif |
| 18542 | 18716 | |
| 18543 | 18717 | if( c=='w' && strncmp(azArg[0], "width", n)==0 ){ |
| 18544 | 18718 | int j; |
| 18545 | 18719 | 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++){ | |
| 18547 | 18725 | p->colWidth[j-1] = (int)integerValue(azArg[j]); |
| 18548 | 18726 | } |
| 18549 | 18727 | }else |
| 18550 | 18728 | |
| 18551 | 18729 | { |
| @@ -18901,13 +19079,15 @@ | ||
| 18901 | 19079 | " -heap SIZE Size of heap for memsys3 or memsys5\n" |
| 18902 | 19080 | #endif |
| 18903 | 19081 | " -help show this message\n" |
| 18904 | 19082 | " -html set output mode to HTML\n" |
| 18905 | 19083 | " -interactive force interactive I/O\n" |
| 19084 | + " -json set output mode to 'json'\n" | |
| 18906 | 19085 | " -line set output mode to 'line'\n" |
| 18907 | 19086 | " -list set output mode to 'list'\n" |
| 18908 | 19087 | " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n" |
| 19088 | + " -markdown set output mode to 'markdown'\n" | |
| 18909 | 19089 | #if defined(SQLITE_ENABLE_DESERIALIZE) |
| 18910 | 19090 | " -maxsize N maximum size for a --deserialize database\n" |
| 18911 | 19091 | #endif |
| 18912 | 19092 | " -memtrace trace all memory allocations and deallocations\n" |
| 18913 | 19093 | " -mmap N default mmap size set to N\n" |
| @@ -18923,10 +19103,11 @@ | ||
| 18923 | 19103 | " -separator SEP set output column separator. Default: '|'\n" |
| 18924 | 19104 | #ifdef SQLITE_ENABLE_SORTER_REFERENCES |
| 18925 | 19105 | " -sorterref SIZE sorter references threshold size\n" |
| 18926 | 19106 | #endif |
| 18927 | 19107 | " -stats print memory stats before each finalize\n" |
| 19108 | + " -table set output mode to 'table'\n" | |
| 18928 | 19109 | " -version show SQLite version\n" |
| 18929 | 19110 | " -vfs NAME use NAME as the default VFS\n" |
| 18930 | 19111 | #ifdef SQLITE_ENABLE_VFSTRACE |
| 18931 | 19112 | " -vfstrace enable tracing of all VFS calls\n" |
| 18932 | 19113 | #endif |
| @@ -19324,10 +19505,16 @@ | ||
| 19324 | 19505 | data.mode = MODE_Quote; |
| 19325 | 19506 | }else if( strcmp(z,"-line")==0 ){ |
| 19326 | 19507 | data.mode = MODE_Line; |
| 19327 | 19508 | }else if( strcmp(z,"-column")==0 ){ |
| 19328 | 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; | |
| 19329 | 19516 | }else if( strcmp(z,"-csv")==0 ){ |
| 19330 | 19517 | data.mode = MODE_Csv; |
| 19331 | 19518 | memcpy(data.colSeparator,",",2); |
| 19332 | 19519 | #ifdef SQLITE_HAVE_ZLIB |
| 19333 | 19520 | }else if( strcmp(z,"-zip")==0 ){ |
| @@ -19541,10 +19728,11 @@ | ||
| 19541 | 19728 | clearTempFile(&data); |
| 19542 | 19729 | #if !SQLITE_SHELL_IS_UTF8 |
| 19543 | 19730 | for(i=0; i<argcToFree; i++) free(argvToFree[i]); |
| 19544 | 19731 | free(argvToFree); |
| 19545 | 19732 | #endif |
| 19733 | + free(data.colWidth); | |
| 19546 | 19734 | /* Clear the global data structure so that valgrind will detect memory |
| 19547 | 19735 | ** leaks */ |
| 19548 | 19736 | memset(&data, 0, sizeof(data)); |
| 19549 | 19737 | return rc; |
| 19550 | 19738 | } |
| 19551 | 19739 |
| --- 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 @@ | ||
| 1528 | 1528 | "TOP", "USER", "UIDL", |
| 1529 | 1529 | }; |
| 1530 | 1530 | int i; |
| 1531 | 1531 | pop3_print(pLog, "+OK"); |
| 1532 | 1532 | for(i=0; i<sizeof(azCap)/sizeof(azCap[0]); i++){ |
| 1533 | - pop3_print(pLog, azCap[i]); | |
| 1533 | + pop3_print(pLog, "%s", azCap[i]); | |
| 1534 | 1534 | } |
| 1535 | 1535 | pop3_print(pLog, "."); |
| 1536 | 1536 | continue; |
| 1537 | 1537 | } |
| 1538 | 1538 | if( inAuth ){ |
| 1539 | 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, 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 @@ | ||
| 1 | 1 | /****************************************************************************** |
| 2 | 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 | |
| 3 | +** version 3.33.0. By combining all the individual C code files into this | |
| 4 | 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | 8 | ** translation unit. |
| @@ -1160,13 +1160,13 @@ | ||
| 1160 | 1160 | ** |
| 1161 | 1161 | ** See also: [sqlite3_libversion()], |
| 1162 | 1162 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 1163 | 1163 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 1164 | 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" | |
| 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 | 1168 | |
| 1169 | 1169 | /* |
| 1170 | 1170 | ** CAPI3REF: Run-Time Library Version Numbers |
| 1171 | 1171 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 1172 | 1172 | ** |
| @@ -38285,11 +38285,14 @@ | ||
| 38285 | 38285 | ** 2. Write lock (ofst==0). |
| 38286 | 38286 | ** 3. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK). |
| 38287 | 38287 | ** |
| 38288 | 38288 | ** In other words, if this is a blocking lock, none of the locks that |
| 38289 | 38289 | ** 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 | + */ | |
| 38291 | 38294 | #ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 38292 | 38295 | assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || ( |
| 38293 | 38296 | (ofst!=2) /* not RECOVER */ |
| 38294 | 38297 | && (ofst!=1 || (p->exclMask|p->sharedMask)==0) |
| 38295 | 38298 | && (ofst!=0 || (p->exclMask|p->sharedMask)<3) |
| @@ -80835,11 +80838,15 @@ | ||
| 80835 | 80838 | ** if the VDBE has just been set to run but has not actually executed any |
| 80836 | 80839 | ** instructions yet, leave the main database error information unchanged. |
| 80837 | 80840 | */ |
| 80838 | 80841 | if( p->pc>=0 ){ |
| 80839 | 80842 | vdbeInvokeSqllog(p); |
| 80840 | - sqlite3VdbeTransferError(p); | |
| 80843 | + if( db->pErr || p->zErrMsg ){ | |
| 80844 | + sqlite3VdbeTransferError(p); | |
| 80845 | + }else{ | |
| 80846 | + db->errCode = p->rc; | |
| 80847 | + } | |
| 80841 | 80848 | if( p->runOnlyOnce ) p->expired = 1; |
| 80842 | 80849 | }else if( p->rc && p->expired ){ |
| 80843 | 80850 | /* The expired flag was set on the VDBE before the first call |
| 80844 | 80851 | ** to sqlite3_step(). For consistency (since sqlite3_step() was |
| 80845 | 80852 | ** called), set the database error in this case as well. |
| @@ -80855,12 +80862,14 @@ | ||
| 80855 | 80862 | if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 ); |
| 80856 | 80863 | if( p->aMem ){ |
| 80857 | 80864 | for(i=0; i<p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined ); |
| 80858 | 80865 | } |
| 80859 | 80866 | #endif |
| 80860 | - sqlite3DbFree(db, p->zErrMsg); | |
| 80861 | - p->zErrMsg = 0; | |
| 80867 | + if( p->zErrMsg ){ | |
| 80868 | + sqlite3DbFree(db, p->zErrMsg); | |
| 80869 | + p->zErrMsg = 0; | |
| 80870 | + } | |
| 80862 | 80871 | p->pResultSet = 0; |
| 80863 | 80872 | #ifdef SQLITE_DEBUG |
| 80864 | 80873 | p->nWrite = 0; |
| 80865 | 80874 | #endif |
| 80866 | 80875 | |
| @@ -102032,11 +102041,11 @@ | ||
| 102032 | 102041 | ** satisfy the query. This is preferable to generating a new |
| 102033 | 102042 | ** ephemeral table. */ |
| 102034 | 102043 | if( pParse->nErr==0 && (p = isCandidateForInOpt(pX))!=0 ){ |
| 102035 | 102044 | sqlite3 *db = pParse->db; /* Database connection */ |
| 102036 | 102045 | Table *pTab; /* Table <table>. */ |
| 102037 | - i16 iDb; /* Database idx for pTab */ | |
| 102046 | + int iDb; /* Database idx for pTab */ | |
| 102038 | 102047 | ExprList *pEList = p->pEList; |
| 102039 | 102048 | int nExpr = pEList->nExpr; |
| 102040 | 102049 | |
| 102041 | 102050 | assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */ |
| 102042 | 102051 | assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */ |
| @@ -102043,10 +102052,11 @@ | ||
| 102043 | 102052 | assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */ |
| 102044 | 102053 | pTab = p->pSrc->a[0].pTab; |
| 102045 | 102054 | |
| 102046 | 102055 | /* Code an OP_Transaction and OP_TableLock for <table>. */ |
| 102047 | 102056 | iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
| 102057 | + assert( iDb>=0 && iDb<SQLITE_MAX_ATTACHED ); | |
| 102048 | 102058 | sqlite3CodeVerifySchema(pParse, iDb); |
| 102049 | 102059 | sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); |
| 102050 | 102060 | |
| 102051 | 102061 | assert(v); /* sqlite3GetVdbe() has always been previously called */ |
| 102052 | 102062 | if( nExpr==1 && pEList->a[0].pExpr->iColumn<0 ){ |
| @@ -103276,14 +103286,11 @@ | ||
| 103276 | 103286 | int r1, r2; /* Various register numbers */ |
| 103277 | 103287 | Expr tempX; /* Temporary expression node */ |
| 103278 | 103288 | int p5 = 0; |
| 103279 | 103289 | |
| 103280 | 103290 | assert( target>0 && target<=pParse->nMem ); |
| 103281 | - if( v==0 ){ | |
| 103282 | - assert( pParse->db->mallocFailed ); | |
| 103283 | - return 0; | |
| 103284 | - } | |
| 103291 | + assert( v!=0 ); | |
| 103285 | 103292 | |
| 103286 | 103293 | expr_code_doover: |
| 103287 | 103294 | if( pExpr==0 ){ |
| 103288 | 103295 | op = TK_NULL; |
| 103289 | 103296 | }else{ |
| @@ -104109,13 +104116,14 @@ | ||
| 104109 | 104116 | SQLITE_PRIVATE void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ |
| 104110 | 104117 | int inReg; |
| 104111 | 104118 | |
| 104112 | 104119 | assert( pExpr==0 || !ExprHasVVAProperty(pExpr,EP_Immutable) ); |
| 104113 | 104120 | assert( target>0 && target<=pParse->nMem ); |
| 104114 | - inReg = sqlite3ExprCodeTarget(pParse, pExpr, target); | |
| 104115 | 104121 | 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 ){ | |
| 104117 | 104125 | u8 op; |
| 104118 | 104126 | if( ExprHasProperty(pExpr,EP_Subquery) ){ |
| 104119 | 104127 | op = OP_Copy; |
| 104120 | 104128 | }else{ |
| 104121 | 104129 | op = OP_SCopy; |
| @@ -114091,25 +114099,37 @@ | ||
| 114091 | 114099 | ** Apart from that, we have little to go on besides intuition as to |
| 114092 | 114100 | ** how aiRowEst[] should be initialized. The numbers generated here |
| 114093 | 114101 | ** are based on typical values found in actual indices. |
| 114094 | 114102 | */ |
| 114095 | 114103 | 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 }; | |
| 114098 | 114106 | LogEst *a = pIdx->aiRowLogEst; |
| 114107 | + LogEst x; | |
| 114099 | 114108 | int nCopy = MIN(ArraySize(aVal), pIdx->nKeyCol); |
| 114100 | 114109 | int i; |
| 114101 | 114110 | |
| 114102 | 114111 | /* Indexes with default row estimates should not have stat1 data */ |
| 114103 | 114112 | assert( !pIdx->hasStat1 ); |
| 114104 | 114113 | |
| 114105 | 114114 | /* Set the first entry (number of rows in the index) to the estimated |
| 114106 | 114115 | ** 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; | |
| 114111 | 114131 | |
| 114112 | 114132 | /* Estimate that a[1] is 10, a[2] is 9, a[3] is 8, a[4] is 7, a[5] is |
| 114113 | 114133 | ** 6 and each subsequent value (if any) is 5. */ |
| 114114 | 114134 | memcpy(&a[1], aVal, nCopy*sizeof(LogEst)); |
| 114115 | 114135 | for(i=nCopy+1; i<=pIdx->nKeyCol; i++){ |
| @@ -128405,21 +128425,22 @@ | ||
| 128405 | 128425 | ** |
| 128406 | 128426 | ** If the same database is attached more than once, the first |
| 128407 | 128427 | ** attached database is returned. |
| 128408 | 128428 | */ |
| 128409 | 128429 | SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){ |
| 128410 | - int i = -1000000; | |
| 128430 | + int i = -32768; | |
| 128411 | 128431 | |
| 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 | |
| 128413 | 128433 | ** expr.c is trying to resolve a reference to a transient table (i.e. one |
| 128414 | 128434 | ** created by a sub-select). In this case the return value of this |
| 128415 | 128435 | ** function should never be used. |
| 128416 | 128436 | ** |
| 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 | |
| 128419 | 128439 | ** 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. | |
| 128421 | 128442 | */ |
| 128422 | 128443 | assert( sqlite3_mutex_held(db->mutex) ); |
| 128423 | 128444 | if( pSchema ){ |
| 128424 | 128445 | for(i=0; 1; i++){ |
| 128425 | 128446 | assert( i<db->nDb ); |
| @@ -128970,13 +128991,13 @@ | ||
| 128970 | 128991 | Expr *pHaving, /* the HAVING clause */ |
| 128971 | 128992 | ExprList *pOrderBy, /* the ORDER BY clause */ |
| 128972 | 128993 | u32 selFlags, /* Flag parameters, such as SF_Distinct */ |
| 128973 | 128994 | Expr *pLimit /* LIMIT value. NULL means not used */ |
| 128974 | 128995 | ){ |
| 128975 | - Select *pNew; | |
| 128996 | + Select *pNew, *pAllocated; | |
| 128976 | 128997 | Select standin; |
| 128977 | - pNew = sqlite3DbMallocRawNN(pParse->db, sizeof(*pNew) ); | |
| 128998 | + pAllocated = pNew = sqlite3DbMallocRawNN(pParse->db, sizeof(*pNew) ); | |
| 128978 | 128999 | if( pNew==0 ){ |
| 128979 | 129000 | assert( pParse->db->mallocFailed ); |
| 128980 | 129001 | pNew = &standin; |
| 128981 | 129002 | } |
| 128982 | 129003 | if( pEList==0 ){ |
| @@ -129006,16 +129027,15 @@ | ||
| 129006 | 129027 | pNew->pWin = 0; |
| 129007 | 129028 | pNew->pWinDefn = 0; |
| 129008 | 129029 | #endif |
| 129009 | 129030 | if( pParse->db->mallocFailed ) { |
| 129010 | 129031 | clearSelect(pParse->db, pNew, pNew!=&standin); |
| 129011 | - pNew = 0; | |
| 129032 | + pAllocated = 0; | |
| 129012 | 129033 | }else{ |
| 129013 | 129034 | assert( pNew->pSrc!=0 || pParse->nErr>0 ); |
| 129014 | 129035 | } |
| 129015 | - assert( pNew!=&standin ); | |
| 129016 | - return pNew; | |
| 129036 | + return pAllocated; | |
| 129017 | 129037 | } |
| 129018 | 129038 | |
| 129019 | 129039 | |
| 129020 | 129040 | /* |
| 129021 | 129041 | ** Delete the given Select structure and all of its substructures. |
| @@ -224820,11 +224840,11 @@ | ||
| 224820 | 224840 | int nArg, /* Number of args */ |
| 224821 | 224841 | sqlite3_value **apUnused /* Function arguments */ |
| 224822 | 224842 | ){ |
| 224823 | 224843 | assert( nArg==0 ); |
| 224824 | 224844 | 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); | |
| 224826 | 224846 | } |
| 224827 | 224847 | |
| 224828 | 224848 | /* |
| 224829 | 224849 | ** Return true if zName is the extension on one of the shadow tables used |
| 224830 | 224850 | ** by this module. |
| @@ -229603,12 +229623,12 @@ | ||
| 229603 | 229623 | } |
| 229604 | 229624 | #endif /* SQLITE_CORE */ |
| 229605 | 229625 | #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ |
| 229606 | 229626 | |
| 229607 | 229627 | /************** End of stmt.c ************************************************/ |
| 229608 | -#if __LINE__!=229608 | |
| 229628 | +#if __LINE__!=229628 | |
| 229609 | 229629 | #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" | |
| 229611 | 229631 | #endif |
| 229612 | 229632 | /* Return the source-id for this library */ |
| 229613 | 229633 | SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } |
| 229614 | 229634 | /************************** End of sqlite3.c ******************************/ |
| 229615 | 229635 |
| --- 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 @@ | ||
| 121 | 121 | ** |
| 122 | 122 | ** See also: [sqlite3_libversion()], |
| 123 | 123 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 124 | 124 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 125 | 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" | |
| 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 | 129 | |
| 130 | 130 | /* |
| 131 | 131 | ** CAPI3REF: Run-Time Library Version Numbers |
| 132 | 132 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 133 | 133 | ** |
| 134 | 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.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 @@ | ||
| 466 | 466 | ** |
| 467 | 467 | ** zDir is a "synthetic" subdirectory which all files get |
| 468 | 468 | ** added to as part of the tarball. It may be 0 or an empty string, in |
| 469 | 469 | ** which case it is ignored. The intention is to create a tarball which |
| 470 | 470 | ** 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". | |
| 472 | 472 | ** |
| 473 | 473 | */ |
| 474 | 474 | void tarball_of_checkin( |
| 475 | 475 | int rid, /* The RID of the checkin from which to form a tarball */ |
| 476 | 476 | Blob *pTar, /* Write the tarball into this blob */ |
| 477 | 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 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 @@ | ||
| 48 | 48 | } |
| 49 | 49 | |
| 50 | 50 | /* |
| 51 | 51 | ** Generate a hyperlink to a version. |
| 52 | 52 | */ |
| 53 | -void hyperlink_to_uuid(const char *zUuid){ | |
| 53 | +void hyperlink_to_version(const char *zVerHash){ | |
| 54 | 54 | 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> | |
| 56 | 56 | }else{ |
| 57 | - @ <span class="timelineHistDsp">[%S(zUuid)]</span> | |
| 57 | + @ <span class="timelineHistDsp">[%S(zVerHash)]</span> | |
| 58 | 58 | } |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | 61 | /* |
| 62 | 62 | ** Generate a hyperlink to a date & time. |
| @@ -101,11 +101,11 @@ | ||
| 101 | 101 | #define TIMELINE_FCHANGES 0x0000020 /* Detail file changes */ |
| 102 | 102 | #define TIMELINE_BRCOLOR 0x0000040 /* Background color by branch name */ |
| 103 | 103 | #define TIMELINE_UCOLOR 0x0000080 /* Background color by user */ |
| 104 | 104 | #define TIMELINE_FRENAMES 0x0000100 /* Detail only file name changes */ |
| 105 | 105 | #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 */ | |
| 107 | 107 | #define TIMELINE_BISECT 0x0000800 /* Show supplimental bisect information */ |
| 108 | 108 | #define TIMELINE_COMPACT 0x0001000 /* Use the "compact" view style */ |
| 109 | 109 | #define TIMELINE_VERBOSE 0x0002000 /* Use the "detailed" view style */ |
| 110 | 110 | #define TIMELINE_MODERN 0x0004000 /* Use the "modern" view style */ |
| 111 | 111 | #define TIMELINE_COLUMNAR 0x0008000 /* Use the "columns" view style */ |
| @@ -229,11 +229,11 @@ | ||
| 229 | 229 | /* |
| 230 | 230 | ** Output a timeline in the web format given a query. The query |
| 231 | 231 | ** should return these columns: |
| 232 | 232 | ** |
| 233 | 233 | ** 0. rid |
| 234 | -** 1. UUID | |
| 234 | +** 1. artifact hash | |
| 235 | 235 | ** 2. Date/Time |
| 236 | 236 | ** 3. Comment string |
| 237 | 237 | ** 4. User |
| 238 | 238 | ** 5. True if is a leaf |
| 239 | 239 | ** 6. background color |
| @@ -533,11 +533,11 @@ | ||
| 533 | 533 | }else{ |
| 534 | 534 | @ <span class='timeline%s(zStyle)Comment'> |
| 535 | 535 | } |
| 536 | 536 | if( (tmFlags & TIMELINE_CLASSIC)!=0 ){ |
| 537 | 537 | if( zType[0]=='c' ){ |
| 538 | - hyperlink_to_uuid(zUuid); | |
| 538 | + hyperlink_to_version(zUuid); | |
| 539 | 539 | if( isLeaf ){ |
| 540 | 540 | if( db_exists("SELECT 1 FROM tagxref" |
| 541 | 541 | " WHERE rid=%d AND tagid=%d AND tagtype>0", |
| 542 | 542 | rid, TAG_CLOSED) ){ |
| 543 | 543 | @ <span class="timelineLeaf">Closed-Leaf:</span> |
| @@ -546,11 +546,11 @@ | ||
| 546 | 546 | } |
| 547 | 547 | } |
| 548 | 548 | }else if( zType[0]=='e' && tagid ){ |
| 549 | 549 | hyperlink_to_event_tagid(tagid<0?-tagid:tagid); |
| 550 | 550 | }else if( (tmFlags & TIMELINE_ARTID)!=0 ){ |
| 551 | - hyperlink_to_uuid(zUuid); | |
| 551 | + hyperlink_to_version(zUuid); | |
| 552 | 552 | } |
| 553 | 553 | if( tmFlags & TIMELINE_SHOWRID ){ |
| 554 | 554 | int srcId = delta_source_rid(rid); |
| 555 | 555 | if( srcId ){ |
| 556 | 556 | @ (%d(rid)←%d(srcId)) |
| @@ -3024,11 +3024,11 @@ | ||
| 3024 | 3024 | z = db_text(0, "SELECT date(%Q,'-1 day')", zToday); |
| 3025 | 3025 | style_submenu_element("Yesterday", "%R/thisdayinhistory?today=%t", z); |
| 3026 | 3026 | z = db_text(0, "SELECT date(%Q,'+1 day')", zToday); |
| 3027 | 3027 | style_submenu_element("Tomorrow", "%R/thisdayinhistory?today=%t", z); |
| 3028 | 3028 | zStartOfProject = db_text(0, |
| 3029 | - "SELECT datetime(min(mtime),toLocal()) FROM event;" | |
| 3029 | + "SELECT datetime(min(mtime),toLocal(),'startofday') FROM event;" | |
| 3030 | 3030 | ); |
| 3031 | 3031 | timeline_temp_table(); |
| 3032 | 3032 | db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/"); |
| 3033 | 3033 | for(i=0; i<sizeof(aYearsAgo)/sizeof(aYearsAgo[0]); i++){ |
| 3034 | 3034 | int iAgo = aYearsAgo[i]; |
| 3035 | 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_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)←%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)←%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 @@ | ||
| 448 | 448 | ); |
| 449 | 449 | } |
| 450 | 450 | |
| 451 | 451 | static const char zDefaultView[] = |
| 452 | 452 | @ <table cellpadding="5"> |
| 453 | -@ <tr><td class="tktDspLabel">Ticket UUID:</td> | |
| 453 | +@ <tr><td class="tktDspLabel">Ticket Hash:</td> | |
| 454 | 454 | @ <th1> |
| 455 | 455 | @ if {[info exists tkt_uuid]} { |
| 456 | 456 | @ html "<td class='tktDspValue' colspan='3'>" |
| 457 | 457 | @ copybtn hash-tk 0 $tkt_uuid 2 |
| 458 | 458 | @ if {[hascap s]} { |
| 459 | 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 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 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 @@ | ||
| 416 | 416 | |
| 417 | 417 | /* |
| 418 | 418 | ** Returns TRUE if zSym is exactly HNAME_LEN_SHA1 or HNAME_LEN_K256 |
| 419 | 419 | ** bytes long and contains only lower-case ASCII hexadecimal values. |
| 420 | 420 | */ |
| 421 | -int fossil_is_uuid(const char *zSym){ | |
| 421 | +int fossil_is_artifact_hash(const char *zSym){ | |
| 422 | 422 | int sz = zSym ? (int)strlen(zSym) : 0; |
| 423 | 423 | return (HNAME_LEN_SHA1==sz || HNAME_LEN_K256==sz) && validate16(zSym, sz); |
| 424 | 424 | } |
| 425 | 425 | |
| 426 | 426 | /* |
| 427 | 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_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 @@ | ||
| 614 | 614 | ** |
| 615 | 615 | ** zDir is a "synthetic" subdirectory which all zipped files get |
| 616 | 616 | ** added to as part of the zip file. It may be 0 or an empty string, |
| 617 | 617 | ** in which case it is ignored. The intention is to create a zip which |
| 618 | 618 | ** 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". | |
| 620 | 620 | ** |
| 621 | 621 | */ |
| 622 | 622 | static void zip_of_checkin( |
| 623 | 623 | int eType, /* Type of archive (ZIP or SQLAR) */ |
| 624 | 624 | int rid, /* The RID of the checkin to build the archive from */ |
| 625 | 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 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 @@ | ||
| 26 | 26 | proc manifest_comment {comment} { |
| 27 | 27 | string map [list { } {\\s} \n {\\n} \r {\\r}] $comment |
| 28 | 28 | } |
| 29 | 29 | |
| 30 | 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 | |
| 31 | + upvar $var HASH | |
| 32 | + regexp {^New_Version: ([0-9a-f]{40})[0-9a-f]*$} $res m HASH | |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | 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 | |
| 36 | + upvar $var HASH | |
| 37 | + regexp {^New branch: ([0-9a-f]{40})[0-9a-f]*$} $res m HASH | |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | 40 | proc uuid_from_checkout {var} { |
| 41 | 41 | global RESULT |
| 42 | - upvar $var UUID | |
| 42 | + upvar $var HASH | |
| 43 | 43 | 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 | |
| 45 | 45 | } |
| 46 | 46 | |
| 47 | 47 | # Make sure we are not in an open repository and initialize new repository |
| 48 | 48 | test_setup |
| 49 | 49 | |
| 50 | 50 | ######################################## |
| 51 | 51 | # Setup: Add file and commit # |
| 52 | 52 | ######################################## |
| 53 | 53 | |
| 54 | -if {![uuid_from_checkout UUIDINIT]} { | |
| 54 | +if {![uuid_from_checkout HASHINIT]} { | |
| 55 | 55 | test amend-checkout-failure false |
| 56 | 56 | test_cleanup_then_return |
| 57 | 57 | } |
| 58 | 58 | write_file datafile "data" |
| 59 | 59 | fossil add datafile |
| 60 | 60 | fossil commit -m "c1" |
| 61 | -if {![uuid_from_commit $RESULT UUID]} { | |
| 61 | +if {![uuid_from_commit $RESULT HASH]} { | |
| 62 | 62 | test amend-setup-failure false |
| 63 | 63 | test_cleanup_then_return |
| 64 | 64 | } |
| 65 | 65 | |
| 66 | 66 | ######################################## |
| 67 | 67 | # Test: -branch # |
| 68 | 68 | ######################################## |
| 69 | -set UUIDB UUIDB | |
| 69 | +set HASHB HASHB | |
| 70 | 70 | write_file datafile "data.file" |
| 71 | 71 | fossil commit -m "c2" |
| 72 | -if {![uuid_from_commit $RESULT UUIDB]} { | |
| 72 | +if {![uuid_from_commit $RESULT HASHB]} { | |
| 73 | 73 | test amend-branch.setup false |
| 74 | 74 | } |
| 75 | -fossil amend $UUIDB -branch amended-branch | |
| 75 | +fossil amend $HASHB -branch amended-branch | |
| 76 | 76 | test amend-branch-1.1 {[regexp {tags:\s+amended-branch} $RESULT]} |
| 77 | 77 | fossil branch ls |
| 78 | 78 | test amend-branch-1.2 {[string first "* amended-branch" $RESULT] != -1} |
| 79 | 79 | fossil tag list |
| 80 | 80 | test amend-branch-1.3 {[string first amended-branch $RESULT] != -1} |
| 81 | -fossil tag list --raw $UUIDB | |
| 81 | +fossil tag list --raw $HASHB | |
| 82 | 82 | test amend-branch-1.4 {[string first "branch=amended-branch" $RESULT] != -1} |
| 83 | 83 | test amend-branch-1.5 {[string first "sym-amended-branch" $RESULT] != -1} |
| 84 | 84 | fossil timeline -n 1 |
| 85 | 85 | test amend-branch-1.6 {[string match {*Move*to*branch*amended-branch*} $RESULT]} |
| 86 | 86 | |
| @@ -102,84 +102,84 @@ | ||
| 102 | 102 | #1234 #1234 |
| 103 | 103 | 1234 1234 |
| 104 | 104 | 123456 #123456 |
| 105 | 105 | } { |
| 106 | 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 | |
| 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 | 110 | test amend-bgcolor-1.$tc.b {[string first "bgcolor=$result" $RESULT] != -1} |
| 111 | 111 | fossil timeline -n 1 |
| 112 | 112 | test amend-bgcolor-1.$tc.c { |
| 113 | 113 | [string match "*Change*background*color*to*\"$result\"*" $RESULT] |
| 114 | 114 | } |
| 115 | 115 | if {[artifact_from_timeline $RESULT artid]} { |
| 116 | 116 | fossil artifact $artid |
| 117 | 117 | test amend-bgcolor-1.$tc.d { |
| 118 | - [string match "*T +bgcolor $UUID* $result*" $RESULT] | |
| 118 | + [string match "*T +bgcolor $HASH* $result*" $RESULT] | |
| 119 | 119 | } |
| 120 | 120 | } else { |
| 121 | 121 | if {$VERBOSE} { protOut "No artifact found in timeline output" } |
| 122 | 122 | test amend-bgcolor-1.$tc.d false |
| 123 | 123 | } |
| 124 | 124 | } |
| 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 | |
| 128 | 128 | test amend-bgcolor-2.2 { |
| 129 | 129 | [string first "bgcolor=" $RESULT] == -1 && |
| 130 | 130 | [string first "bgcolor" $RESULT] != -1 |
| 131 | 131 | } |
| 132 | 132 | fossil timeline -n 1 |
| 133 | 133 | test amend-bgcolor-2.3 {[string match "*Cancel*background*color.*" $RESULT]} |
| 134 | 134 | if {[artifact_from_timeline $RESULT artid]} { |
| 135 | 135 | 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]} | |
| 137 | 137 | } else { |
| 138 | 138 | if {$VERBOSE} { protOut "No artifact found in timeline output" } |
| 139 | 139 | test amend-bgcolor-2.4 false |
| 140 | 140 | } |
| 141 | 141 | |
| 142 | 142 | ######################################## |
| 143 | 143 | # Test: -branchcolor # |
| 144 | 144 | ######################################## |
| 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]} { | |
| 148 | 148 | test amend-branchcolor.setup false |
| 149 | 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 | |
| 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 | 154 | test amend-branchcolor-1.2 {[string first "bgcolor=yellow" $RESULT] != -1} |
| 155 | 155 | fossil timeline -n 1 |
| 156 | 156 | test amend-branchcolor-1.3 { |
| 157 | 157 | [string match {*Change*branch*background*color*to*"yellow".*} $RESULT] |
| 158 | 158 | } |
| 159 | 159 | if {[regexp {(?x)[0-9]{2}(?::[0-9]{2}){2}\s+\[([0-9a-f]+)]} $RESULT m artid]} { |
| 160 | 160 | fossil artifact $artid |
| 161 | 161 | test amend-branchcolor-1.4 { |
| 162 | - [string match "*T \*bgcolor $UUID2* yellow*" $RESULT] | |
| 162 | + [string match "*T \*bgcolor $HASH2* yellow*" $RESULT] | |
| 163 | 163 | } |
| 164 | 164 | } else { |
| 165 | 165 | if {$VERBOSE} { protOut "No artifact found in timeline output" } |
| 166 | 166 | test amend-branchcolor-1.4 false |
| 167 | 167 | } |
| 168 | 168 | |
| 169 | -set UUIDN UUIDN | |
| 169 | +set HASHN HASHN | |
| 170 | 170 | write_file datafile "brclr" |
| 171 | 171 | fossil commit -m "brclr" |
| 172 | -if {![uuid_from_commit $RESULT UUIDN]} { | |
| 172 | +if {![uuid_from_commit $RESULT HASHN]} { | |
| 173 | 173 | test amend-branchcolor-propagating.setup false |
| 174 | 174 | } |
| 175 | 175 | write_file datafile "bc1" |
| 176 | 176 | fossil commit -m "mc1" |
| 177 | 177 | write_file datafile "bc2" |
| 178 | 178 | 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]} | |
| 181 | 181 | fossil tag ls --raw current |
| 182 | 182 | test amend-branchcolor-2.2 {[string first "bgcolor=#deadbe" $RESULT] != -1} |
| 183 | 183 | fossil timeline -n 1 |
| 184 | 184 | test amend-branchcolor-2.3 { |
| 185 | 185 | [string match {*Change*branch*background*color*to*"#deadbe".*} $RESULT] |
| @@ -186,13 +186,13 @@ | ||
| 186 | 186 | } |
| 187 | 187 | |
| 188 | 188 | ######################################## |
| 189 | 189 | # Test: -author # |
| 190 | 190 | ######################################## |
| 191 | -fossil amend $UUID -author author-test | |
| 191 | +fossil amend $HASH -author author-test | |
| 192 | 192 | test amend-author-1.1 {[string match {*comment:*(user:*author-test)*} $RESULT]} |
| 193 | -fossil tag ls --raw $UUID | |
| 193 | +fossil tag ls --raw $HASH | |
| 194 | 194 | test amend-author-1.2 {[string first "user=author-test" $RESULT] != -1} |
| 195 | 195 | fossil timeline -n 1 |
| 196 | 196 | test amend-author-1.3 {[string match {*Change*user*to*"author-test".*} $RESULT]} |
| 197 | 197 | |
| 198 | 198 | ######################################## |
| @@ -200,13 +200,13 @@ | ||
| 200 | 200 | ######################################## |
| 201 | 201 | set timestamp [clock scan yesterday] |
| 202 | 202 | set date [clock format $timestamp -format "%Y-%m-%d" -gmt 1] |
| 203 | 203 | set time [clock format $timestamp -format "%H:%M:%S" -gmt 1] |
| 204 | 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 | |
| 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 | 208 | test amend-date-1.2 {[string first "date=$datetime" $RESULT] != -1} |
| 209 | 209 | fossil timeline -n 1 |
| 210 | 210 | test amend-date-1.3 {[string match "*Timestamp*$date*$time*" $RESULT]} |
| 211 | 211 | set badformats { |
| 212 | 212 | "%+" |
| @@ -217,67 +217,67 @@ | ||
| 217 | 217 | } |
| 218 | 218 | set sc 0 |
| 219 | 219 | foreach badformat $badformats { |
| 220 | 220 | incr sc |
| 221 | 221 | set datetime [clock format $timestamp -format $badformat -gmt 1] |
| 222 | - fossil amend $UUIDINIT -date $datetime -expectError | |
| 222 | + fossil amend $HASHINIT -date $datetime -expectError | |
| 223 | 223 | test amend-date-2.$sc {[string first "YYYY-MM-DD HH:MM:SS" $RESULT] != -1} |
| 224 | 224 | } |
| 225 | 225 | |
| 226 | 226 | ######################################## |
| 227 | 227 | # Test: -hide # |
| 228 | 228 | ######################################## |
| 229 | -set UUIDH UUIDH | |
| 229 | +set HASHH HASHH | |
| 230 | 230 | fossil revert |
| 231 | 231 | fossil update trunk |
| 232 | 232 | fossil branch new tohide current |
| 233 | -if {![uuid_from_branch $RESULT UUIDH]} { | |
| 233 | +if {![uuid_from_branch $RESULT HASHH]} { | |
| 234 | 234 | test amend-hide-setup false |
| 235 | 235 | } |
| 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 | |
| 239 | 239 | test amend-hide-1.2 {[string first "hidden" $RESULT] != -1} |
| 240 | 240 | fossil timeline -n 1 |
| 241 | 241 | test amend-hide-1.3 {[string match {*Add*propagating*"hidden".*} $RESULT]} |
| 242 | 242 | |
| 243 | 243 | ######################################## |
| 244 | 244 | # Test: -close # |
| 245 | 245 | ######################################## |
| 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]} { | |
| 249 | 249 | test amend-close.setup false |
| 250 | 250 | } |
| 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]} | |
| 254 | 254 | test amend-close-1.1.b { |
| 255 | 255 | [string match "*comment:*Create*new*branch*named*\"cllf\"*" $RESULT] |
| 256 | 256 | } |
| 257 | -fossil tag ls --raw $UUIDC | |
| 257 | +fossil tag ls --raw $HASHC | |
| 258 | 258 | test amend-close-1.2 {[string first "closed" $RESULT] != -1} |
| 259 | 259 | fossil timeline -n 1 |
| 260 | 260 | test amend-close-1.3 {[string match {*Mark*"Closed".*} $RESULT]} |
| 261 | 261 | write_file datafile "cllf" |
| 262 | 262 | fossil commit -m "should fail" -expectError |
| 263 | 263 | test amend-close-2 {[string first "closed leaf" $RESULT] != -1} |
| 264 | 264 | |
| 265 | -set UUID3 UUID3 | |
| 265 | +set HASH3 HASH3 | |
| 266 | 266 | fossil revert |
| 267 | 267 | fossil update trunk |
| 268 | 268 | write_file datafile "cb" |
| 269 | 269 | fossil commit -m "closed-branch" --branch "closebranch" |
| 270 | -if {![uuid_from_commit $RESULT UUID3]} { | |
| 270 | +if {![uuid_from_commit $RESULT HASH3]} { | |
| 271 | 271 | test amend-close-3.setup false |
| 272 | 272 | } |
| 273 | 273 | write_file datafile "b1" |
| 274 | 274 | fossil commit -m "m1" |
| 275 | 275 | write_file datafile "b2" |
| 276 | 276 | 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]} | |
| 279 | 279 | fossil tag ls --raw current |
| 280 | 280 | test amend-close-3.2 {[string first "closed" $RESULT] != -1} |
| 281 | 281 | fossil timeline -n 1 |
| 282 | 282 | test amend-close-3.3 { |
| 283 | 283 | [string match "*Add*propagating*\"closed\".*" $RESULT] |
| @@ -310,96 +310,96 @@ | ||
| 310 | 310 | append t1exp ", $res" |
| 311 | 311 | append t2exp "sym-$res*" |
| 312 | 312 | append t3exp "Add*tag*\"$res\".*" |
| 313 | 313 | append t5exp "Cancel*tag*\"$res\".*" |
| 314 | 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 | |
| 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 | 318 | test amend-tag-$tc.2 {[string match $t2exp $RESULT]} |
| 319 | 319 | fossil timeline -n 1 |
| 320 | 320 | test amend-tag-$tc.3 {[string match $t3exp $RESULT]} |
| 321 | - eval fossil amend $UUID $cancels | |
| 321 | + eval fossil amend $HASH $cancels | |
| 322 | 322 | test amend-tag-$tc.4 {![string match "*tags:*$t1exp*" $RESULT]} |
| 323 | 323 | fossil timeline -n 1 |
| 324 | 324 | test amend-tag-$tc.5 {[string match $t5exp $RESULT]} |
| 325 | 325 | } |
| 326 | 326 | |
| 327 | 327 | ######################################## |
| 328 | 328 | # Test: -comment # |
| 329 | 329 | ######################################## |
| 330 | 330 | proc prep-test {comment content} { |
| 331 | - global UUID RESULT | |
| 331 | + global HASH RESULT | |
| 332 | 332 | |
| 333 | 333 | fossil revert |
| 334 | 334 | fossil update trunk |
| 335 | 335 | write_file datafile $comment |
| 336 | 336 | fossil commit -m $content |
| 337 | - if {![uuid_from_commit $RESULT UUID]} { | |
| 338 | - set UUID "" | |
| 337 | + if {![uuid_from_commit $RESULT HASH]} { | |
| 338 | + set HASH "" | |
| 339 | 339 | } |
| 340 | 340 | } |
| 341 | 341 | |
| 342 | -proc test-comment {name UUID comment} { | |
| 342 | +proc test-comment {name HASH comment} { | |
| 343 | 343 | global VERBOSE RESULT |
| 344 | 344 | |
| 345 | 345 | test amend-comment-$name.1 { |
| 346 | - [string match "*uuid:*$UUID*comment:*$comment*" $RESULT] | |
| 346 | + [string match "*uuid:*$HASH*comment:*$comment*" $RESULT] | |
| 347 | 347 | } |
| 348 | 348 | fossil timeline -n 1 |
| 349 | 349 | if {[artifact_from_timeline $RESULT artid]} { |
| 350 | 350 | fossil artifact $artid |
| 351 | 351 | 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] | |
| 353 | 353 | } |
| 354 | 354 | } else { |
| 355 | 355 | if {$VERBOSE} { protOut "No artifact found in timeline output: $RESULT" } |
| 356 | 356 | test amend-comment-$name.2 false |
| 357 | 357 | } |
| 358 | 358 | fossil timeline -n 1 |
| 359 | 359 | 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] | |
| 361 | 361 | } |
| 362 | - fossil info $UUID | |
| 362 | + fossil info $HASH | |
| 363 | 363 | test amend-comment-$name.4 { |
| 364 | - [string match "*uuid:*$UUID*comment:*$comment*" $RESULT] | |
| 364 | + [string match "*uuid:*$HASH*comment:*$comment*" $RESULT] | |
| 365 | 365 | } |
| 366 | 366 | } |
| 367 | 367 | |
| 368 | 368 | 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" | |
| 371 | 371 | |
| 372 | 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" | |
| 373 | +fossil amend $HASH -m "revised revision 2 with -m" | |
| 374 | +test-comment 2 $HASH "revised revision 2 with -m" | |
| 375 | 375 | |
| 376 | 376 | prep-test "revision 3" "revision 3" |
| 377 | 377 | 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" | |
| 380 | 380 | |
| 381 | 381 | prep-test "revision 4" "revision 4" |
| 382 | 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" | |
| 383 | +fossil amend $HASH -M commitmsg | |
| 384 | +test-comment 4 $HASH "revision 4 revised with -M" | |
| 385 | 385 | |
| 386 | 386 | prep-test "final comment" "final content" |
| 387 | 387 | if {[catch {exec which ed} result]} { |
| 388 | 388 | 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" | |
| 390 | 390 | } else { |
| 391 | 391 | fossil settings editor "ed -s" |
| 392 | 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 | |
| 393 | + fossil_maybe_answer "a\n$comment\n.\nw\nq\n" amend $HASH --edit-comment | |
| 394 | + test-comment 5 $HASH $comment | |
| 395 | 395 | } |
| 396 | 396 | |
| 397 | 397 | ######################################## |
| 398 | -# Test: NULL UUID # | |
| 398 | +# Test: NULL hash # | |
| 399 | 399 | ######################################## |
| 400 | 400 | fossil amend {} -close -expectError |
| 401 | 401 | test amend-null-uuid {$CODE && [string first "no such check-in" $RESULT] != -1} |
| 402 | 402 | |
| 403 | 403 | ############################################################################### |
| 404 | 404 | |
| 405 | 405 | test_cleanup |
| 406 | 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 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 |
+5
-1
| --- tools/email-sender.tcl | ||
| +++ tools/email-sender.tcl | ||
| @@ -21,11 +21,15 @@ | ||
| 21 | 21 | } |
| 22 | 22 | while {1} { |
| 23 | 23 | db transaction immediate { |
| 24 | 24 | set n 0 |
| 25 | 25 | 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] | |
| 27 | 31 | puts -nonewline $out $msg |
| 28 | 32 | flush $out |
| 29 | 33 | close $out |
| 30 | 34 | incr n |
| 31 | 35 | } |
| 32 | 36 |
| --- 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 |
+2
-2
| --- win/Makefile.PellesCGMake | ||
| +++ win/Makefile.PellesCGMake | ||
| @@ -83,17 +83,17 @@ | ||
| 83 | 83 | |
| 84 | 84 | # define the SQLite files, which need special flags on compile |
| 85 | 85 | SQLITESRC=sqlite3.c |
| 86 | 86 | ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf)) |
| 87 | 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 | |
| 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 | 89 | |
| 90 | 90 | # define the SQLite shell files, which need special flags on compile |
| 91 | 91 | SQLITESHELLSRC=shell.c |
| 92 | 92 | ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf)) |
| 93 | 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 | |
| 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 | 95 | |
| 96 | 96 | # define the th scripting files, which need special flags on compile |
| 97 | 97 | THSRC=th.c th_lang.c |
| 98 | 98 | ORIGTHSRC=$(foreach sf,$(THSRC),$(SRCDIR)$(sf)) |
| 99 | 99 | THOBJ=$(foreach sf,$(THSRC),$(sf:.c=.obj)) |
| 100 | 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_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 |
+2
-2
| --- win/Makefile.dmc | ||
| +++ win/Makefile.dmc | ||
| @@ -24,13 +24,13 @@ | ||
| 24 | 24 | CFLAGS = -o |
| 25 | 25 | BCC = $(DMDIR)\bin\dmc $(CFLAGS) |
| 26 | 26 | TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) |
| 27 | 27 | LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 dnsapi |
| 28 | 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 | |
| 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 | 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 | |
| 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 | 32 | |
| 33 | 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 | 34 | |
| 35 | 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 | 36 | |
| 37 | 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_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 |
-2
| --- win/Makefile.mingw | ||
| +++ win/Makefile.mingw | ||
| @@ -2485,11 +2485,10 @@ | ||
| 2485 | 2485 | -DSQLITE_DEFAULT_MEMSTATUS=0 \ |
| 2486 | 2486 | -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \ |
| 2487 | 2487 | -DSQLITE_LIKE_DOESNT_MATCH_BLOBS \ |
| 2488 | 2488 | -DSQLITE_OMIT_DECLTYPE \ |
| 2489 | 2489 | -DSQLITE_OMIT_DEPRECATED \ |
| 2490 | - -DSQLITE_OMIT_GET_TABLE \ | |
| 2491 | 2490 | -DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 2492 | 2491 | -DSQLITE_OMIT_SHARED_CACHE \ |
| 2493 | 2492 | -DSQLITE_OMIT_LOAD_EXTENSION \ |
| 2494 | 2493 | -DSQLITE_MAX_EXPR_DEPTH=0 \ |
| 2495 | 2494 | -DSQLITE_USE_ALLOCA \ |
| @@ -2516,11 +2515,10 @@ | ||
| 2516 | 2515 | -DSQLITE_DEFAULT_MEMSTATUS=0 \ |
| 2517 | 2516 | -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \ |
| 2518 | 2517 | -DSQLITE_LIKE_DOESNT_MATCH_BLOBS \ |
| 2519 | 2518 | -DSQLITE_OMIT_DECLTYPE \ |
| 2520 | 2519 | -DSQLITE_OMIT_DEPRECATED \ |
| 2521 | - -DSQLITE_OMIT_GET_TABLE \ | |
| 2522 | 2520 | -DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 2523 | 2521 | -DSQLITE_OMIT_SHARED_CACHE \ |
| 2524 | 2522 | -DSQLITE_OMIT_LOAD_EXTENSION \ |
| 2525 | 2523 | -DSQLITE_MAX_EXPR_DEPTH=0 \ |
| 2526 | 2524 | -DSQLITE_USE_ALLOCA \ |
| 2527 | 2525 |
| --- 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 |
-2
| --- win/Makefile.msc | ||
| +++ win/Makefile.msc | ||
| @@ -283,11 +283,10 @@ | ||
| 283 | 283 | /DSQLITE_DEFAULT_MEMSTATUS=0 \ |
| 284 | 284 | /DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \ |
| 285 | 285 | /DSQLITE_LIKE_DOESNT_MATCH_BLOBS \ |
| 286 | 286 | /DSQLITE_OMIT_DECLTYPE \ |
| 287 | 287 | /DSQLITE_OMIT_DEPRECATED \ |
| 288 | - /DSQLITE_OMIT_GET_TABLE \ | |
| 289 | 288 | /DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 290 | 289 | /DSQLITE_OMIT_SHARED_CACHE \ |
| 291 | 290 | /DSQLITE_OMIT_LOAD_EXTENSION \ |
| 292 | 291 | /DSQLITE_MAX_EXPR_DEPTH=0 \ |
| 293 | 292 | /DSQLITE_USE_ALLOCA \ |
| @@ -311,11 +310,10 @@ | ||
| 311 | 310 | /DSQLITE_DEFAULT_MEMSTATUS=0 \ |
| 312 | 311 | /DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \ |
| 313 | 312 | /DSQLITE_LIKE_DOESNT_MATCH_BLOBS \ |
| 314 | 313 | /DSQLITE_OMIT_DECLTYPE \ |
| 315 | 314 | /DSQLITE_OMIT_DEPRECATED \ |
| 316 | - /DSQLITE_OMIT_GET_TABLE \ | |
| 317 | 315 | /DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 318 | 316 | /DSQLITE_OMIT_SHARED_CACHE \ |
| 319 | 317 | /DSQLITE_OMIT_LOAD_EXTENSION \ |
| 320 | 318 | /DSQLITE_MAX_EXPR_DEPTH=0 \ |
| 321 | 319 | /DSQLITE_USE_ALLOCA \ |
| 322 | 320 |
| --- 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 |
+1
-1
| --- www/concepts.wiki | ||
| +++ www/concepts.wiki | ||
| @@ -80,11 +80,11 @@ | ||
| 80 | 80 | Communication between repositories is via HTTP. Remote |
| 81 | 81 | repositories are identified by URL. You can also point a web browser |
| 82 | 82 | at a repository and get human-readable status, history, and tracking |
| 83 | 83 | information about the project. |
| 84 | 84 | |
| 85 | -<h3>2.1 Identification Of Artifacts</h3> | |
| 85 | +<h3><a id="artifacts"></a>2.1 Identification Of Artifacts</h3> | |
| 86 | 86 | |
| 87 | 87 | A particular version of a particular file is called an "artifact". Each |
| 88 | 88 | artifact has a universally unique name which is the <a |
| 89 | 89 | href="http://en.wikipedia.org/wiki/SHA1">SHA1</a> or <a |
| 90 | 90 | href="http://en.wikipedia.org/wiki/SHA3">SHA3-256</a> hash of the |
| 91 | 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>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 |
+2
-2
| --- www/fiveminutes.wiki | ||
| +++ www/fiveminutes.wiki | ||
| @@ -58,12 +58,12 @@ | ||
| 58 | 58 | <h2>Compare two revisions of a file</h2> |
| 59 | 59 | <p>If you wish to compare the last revision of a file and its checked out version |
| 60 | 60 | in your work directory:</p> |
| 61 | 61 | <p>fossil gdiff myfile.c</p> |
| 62 | 62 | <p>If you wish to compare two different revisions of a file in the repository:</p> |
| 63 | -<p>fossil finfo myfile: Note the first hash, which is the UUID of the commit | |
| 63 | +<p>fossil finfo myfile: Note the first hash, which is the hash of the commit | |
| 64 | 64 | 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> | |
| 66 | 66 | <h2>Cancel changes and go back to previous revision</h2> |
| 67 | 67 | <p>fossil revert myfile.c</p> |
| 68 | 68 | <p>Fossil does not prompt when reverting a file. It simply reminds the user about the |
| 69 | 69 | "undo" command, just in case the revert was a mistake.</p> |
| 70 | 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 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 |
+4
-4
| --- www/fossil-v-git.wiki | ||
| +++ www/fossil-v-git.wiki | ||
| @@ -40,22 +40,22 @@ | ||
| 40 | 40 | <td>VCS, tickets, wiki, docs, notes, forum, UI, |
| 41 | 41 | [https://en.wikipedia.org/wiki/Role-based_access_control|RBAC]</td> |
| 42 | 42 | <td><a href="#features">2.1 ↓</a></td> |
| 43 | 43 | </tr> |
| 44 | 44 | <tr> |
| 45 | - <td>Sprawling, incoherent, and inefficient</td> | |
| 45 | + <td>Sprawling and inefficient</td> | |
| 46 | 46 | <td>Self-contained and efficient</td> |
| 47 | 47 | <td><a href="#efficient">2.2 ↓</a></td> |
| 48 | 48 | </tr> |
| 49 | 49 | <tr> |
| 50 | - <td>Ad-hoc pile-of-files key/value database</td> | |
| 50 | + <td>One-off custom pile-of-files data store</td> | |
| 51 | 51 | <td>[https://sqlite.org/famous.html|The most popular database in the world]</td> |
| 52 | 52 | <td><a href="#durable">2.3 ↓</a></td> |
| 53 | 53 | </tr> |
| 54 | 54 | <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> | |
| 57 | 57 | <td><a href="#portable">2.4 ↓</a></td> |
| 58 | 58 | </tr> |
| 59 | 59 | <tr> |
| 60 | 60 | <td>Bazaar-style development</td> |
| 61 | 61 | <td>Cathedral-style development</td> |
| 62 | 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 ↓</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 ↓</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 ↓</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 ↓</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 ↓</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 ↓</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 ↓</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 ↓</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 @@ | ||
| 1 | 1 | # Hashes: Fossil Artifact Identification |
| 2 | 2 | |
| 3 | 3 | All artifacts in Fossil are identified by a unique hash, currently using |
| 4 | 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: | |
| 5 | +algorithm: | |
| 7 | 6 | |
| 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> | |
| 12 | 12 | |
| 13 | 13 | There are many types of artifacts in Fossil: commits (a.k.a. check-ins), |
| 14 | 14 | tickets, ticket comments, wiki articles, forum postings, file data |
| 15 | 15 | belonging to check-ins, etc. ([More info...](./concepts.wiki#artifacts)). |
| 16 | 16 | |
| 17 | 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. | |
| 18 | +parts of the Fossil UI, which we cover in the sections below. | |
| 21 | 19 | |
| 22 | 20 | |
| 23 | 21 | ## Names |
| 24 | 22 | |
| 25 | 23 | Several Fossil interfaces accept [a wide variety of check-in |
| 26 | 24 | 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. | |
| 28 | 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. | |
| 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 | 32 | |
| 33 | 33 | |
| 34 | 34 | ## Versions |
| 35 | 35 | |
| 36 | 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 | - | |
| 37 | +calls it a “VERSION,” a “commit ID,” or a “check-in ID.” | |
| 41 | 38 | We may eventually settle on one of these terms, but all three are |
| 42 | 39 | currently in common use within Fossil’s docs, UI, and programming |
| 43 | 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 | 44 | |
| 45 | 45 | A unique prefix of a VERSION hash is itself a VERSION. That is, if your |
| 46 | 46 | repository has exactly one commit artifact with a hash prefix of |
| 47 | 47 | “abc123”, then that is a valid version string as long as it remains |
| 48 | 48 | unambiguous. |
| 49 | 49 | |
| 50 | 50 | |
| 51 | 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: | |
| 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. | |
| 70 | 86 | |
| 71 | 87 | |
| 72 | 88 | ### Repository DB Schema |
| 73 | 89 | |
| 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. | |
| 90 | 103 | |
| 91 | 104 | 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. | |
| 103 | 110 | |
| 104 | 111 | |
| 105 | 112 | ### TH1 Scripting Interfaces |
| 106 | 113 | |
| 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 — available when [customizing | |
| 117 | +the ticket system][ctkt] — 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. | |
| 117 | 126 | |
| 118 | 127 | |
| 119 | 128 | ### JSON API Parameters and Outputs |
| 120 | 129 | |
| 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. | |
| 127 | 134 | |
| 128 | 135 | |
| 129 | 136 | ### `manifest.uuid` |
| 130 | 137 | |
| 131 | 138 | If you have [the `manifest` setting][mset] enabled, Fossil writes a file |
| 132 | 139 | called `manifest.uuid` at the root of the check-out tree containing the |
| 133 | 140 | 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. | |
| 135 | 143 | |
| 136 | 144 | |
| 137 | 145 | [cin]: ./checkin_names.wiki |
| 138 | 146 | [ctkt]: ./custom_ticket.wiki |
| 139 | 147 | [hpol]: ./hashpolicy.wiki |
| 148 | +[japi]: ./json-api/ | |
| 140 | 149 | [jart]: ./json-api/api-artifact.md |
| 141 | 150 | [jtim]: ./json-api/api-timeline.md |
| 142 | 151 | [mset]: /help?cmd=manifest |
| 152 | +[th1]: ./th1.md | |
| 153 | +[trss]: /help?cmd=/timeline.rss | |
| 143 | 154 | [tvb]: ./branching.wiki |
| 144 | 155 | [uuid]: https://en.wikipedia.org/wiki/Universally_unique_identifier |
| 145 | -[v4]: https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random) | |
| 146 | 156 |
| --- 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 — available when [customizing |
| 117 | the ticket system][ctkt] — 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 |
+16
-14
| --- www/json-api/api-artifact.md | ||
| +++ www/json-api/api-artifact.md | ||
| @@ -14,11 +14,11 @@ | ||
| 14 | 14 | |
| 15 | 15 | Returns information about checkin artifacts (commits). |
| 16 | 16 | |
| 17 | 17 | **Status:** implemented 201110xx |
| 18 | 18 | |
| 19 | -**Request:** `/json/artifact/COMMIT_UUID` | |
| 19 | +**Request:** `/json/artifact/COMMIT_HASH` | |
| 20 | 20 | |
| 21 | 21 | **Required permissions:** "o" (was "h" prior to 20120408) |
| 22 | 22 | |
| 23 | 23 | **Response payload example: (CHANGED SIGNIFICANTLY ON 20120713)** |
| 24 | 24 | |
| @@ -30,43 +30,44 @@ | ||
| 30 | 30 | "isLeaf":false, |
| 31 | 31 | "user":"drh", |
| 32 | 32 | "comment":"Merge wideAnnotateUser and jsonWarnings into trunk.", |
| 33 | 33 | "timestamp":1330090810, |
| 34 | 34 | "parents":[ |
| 35 | - // 1st entry is primary parent UUID: | |
| 35 | + // 1st entry is primary parent hash: | |
| 36 | 36 | "3a44f95f40a193739aaafc2409f155df43e74a6f", |
| 37 | - // Remaining entries are merged-in branch UUIDs: | |
| 37 | + // Remaining entries are merged-in branch hashes: | |
| 38 | 38 | "86f6e675eb3f8761d70d8b82b052ce2b297fffd2",\ |
| 39 | 39 | "dbf4ecf414881c9aad6f4f125dab9762589ef3d7"\ |
| 40 | 40 | ], |
| 41 | 41 | "tags":["trunk"], |
| 42 | 42 | "files":[{ |
| 43 | 43 | "name":"src/diff.c", |
| 44 | - // BLOB uuids, NOT commit UUIDs: | |
| 44 | + // BLOB hashes, NOT commit hashes: | |
| 45 | 45 | "uuid":"78c74c3b37e266f8f7e570d5cf476854b7af9d76", |
| 46 | 46 | "parent":"b1fa7e636cf4e7b6ed20bba2d2680397f80c096a", |
| 47 | 47 | "state":"modified", |
| 48 | 48 | "downloadPath":"/raw/src/diff.c?name=78c74c3b37e266f8f7e570d5cf476854b7af9d76" |
| 49 | 49 | }, |
| 50 | 50 | ...] |
| 51 | 51 | } |
| 52 | 52 | ``` |
| 53 | 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 | |
| 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 | 56 | file. In the case of a merge there may be essentially an arbitrary |
| 57 | 57 | number. The first entry in the list is the "primary" parent. The primary |
| 58 | 58 | parent is the parent which was not pulled in via a merge operation. The |
| 59 | 59 | ordering of remaining entries is unspecified and may even change between |
| 60 | 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 | |
| 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 | 63 | and B in the following entries (in an unspecified, and possibly |
| 64 | 64 | unstable, order). |
| 65 | 65 | |
| 66 | 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). | |
| 67 | +refer to raw blob hashes, not commit (a.k.a. check-in) hashes. See also | |
| 68 | +[the UUID vs. Hash discussion][uvh]. | |
| 68 | 69 | |
| 69 | 70 | <a id="file"></a> |
| 70 | 71 | # File Artifacts |
| 71 | 72 | |
| 72 | 73 | Fetches information about file artifacts. |
| @@ -77,11 +78,11 @@ | ||
| 77 | 78 | |
| 78 | 79 | **Status:** implemented 20111020 |
| 79 | 80 | |
| 80 | 81 | **Required permissions:** "o" |
| 81 | 82 | |
| 82 | -**Request:** `/json/artifact/FILE_UUID` | |
| 83 | +**Request:** `/json/artifact/FILE_HASH` | |
| 83 | 84 | |
| 84 | 85 | **Request options:** |
| 85 | 86 | |
| 86 | 87 | - `format=(raw|html|none)` (default=none). If set, the contents of the |
| 87 | 88 | artifact are included if they are text, else they are not (JSON does |
| @@ -98,13 +99,13 @@ | ||
| 98 | 99 | **Response payload example: (CHANGED SIGNIFICANTLY ON 20120713)** |
| 99 | 100 | |
| 100 | 101 | ```json |
| 101 | 102 | { |
| 102 | 103 | "type":"file", |
| 103 | -"name":"same name specified as FILE_UUID argument", | |
| 104 | +"name":"same name specified as FILE_HASH argument", | |
| 104 | 105 | "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.", | |
| 106 | 107 | "checkins":[{ |
| 107 | 108 | "name":"src/json_detail.h", |
| 108 | 109 | "timestamp":1319058803, |
| 109 | 110 | "comment":"...", |
| 110 | 111 | "user":"stephan", |
| @@ -121,21 +122,21 @@ | ||
| 121 | 122 | } |
| 122 | 123 | ``` |
| 123 | 124 | |
| 124 | 125 | The "checkins" array lists all checkins which include this file, and a |
| 125 | 126 | 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. | |
| 127 | 128 | |
| 128 | 129 | <a id="wiki"></a> |
| 129 | 130 | # Wiki Artifacts |
| 130 | 131 | |
| 131 | 132 | Returns information about wiki artifacts. |
| 132 | 133 | |
| 133 | 134 | **Status:** implemented 20111020, fixed to return the requested version |
| 134 | 135 | (instead of the latest) on 20120302. |
| 135 | 136 | |
| 136 | -**Request:** `/json/artifact/WIKI_UUID` | |
| 137 | +**Request:** `/json/artifact/WIKI_HASH` | |
| 137 | 138 | |
| 138 | 139 | **Required permissions:** "j" |
| 139 | 140 | |
| 140 | 141 | **Options:** |
| 141 | 142 | |
| @@ -149,5 +150,6 @@ | ||
| 149 | 150 | |
| 150 | 151 | **Response payload example:** |
| 151 | 152 | |
| 152 | 153 | Currently the same as [`/json/wiki/get`](api-wiki.md#get). |
| 153 | 154 | |
| 155 | +[uvh]: ../hashes.md#uvh | |
| 154 | 156 |
| --- 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 |
+3
-3
| --- www/json-api/api-diff.md | ||
| +++ www/json-api/api-diff.md | ||
| @@ -33,12 +33,12 @@ | ||
| 33 | 33 | } |
| 34 | 34 | ``` |
| 35 | 35 | |
| 36 | 36 | TODOs: |
| 37 | 37 | |
| 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 | |
| 40 | 40 | provided, a diff of the manifests is returned. (That should be |
| 41 | 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 | |
| 42 | +- If hashes from two different types of artifacts are given, results | |
| 43 | 43 | are unspecified. Garbage in, garbage out, and all that. |
| 44 | 44 | - For file diffs, add the file name(s) to the response payload. |
| 45 | 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 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 |
+5
-4
| --- www/json-api/api-tag.md | ||
| +++ www/json-api/api-tag.md | ||
| @@ -47,12 +47,12 @@ | ||
| 47 | 47 | "raw":false, |
| 48 | 48 | "appliedTo":"626ab2f3743543122cc11bc082a0603d2b5b2b1b" |
| 49 | 49 | } |
| 50 | 50 | ``` |
| 51 | 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 | |
| 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 | 54 | the client. |
| 55 | 55 | |
| 56 | 56 | <a id="cancel"></a> |
| 57 | 57 | # Cancel Tag |
| 58 | 58 | |
| @@ -99,12 +99,13 @@ | ||
| 99 | 99 | - `limit=int` (defalt=0) Limits the number of results (0=no limit). |
| 100 | 100 | Since they are ordered from oldest to newest, the newest N results |
| 101 | 101 | will be returned. |
| 102 | 102 | - `type=string` (default=`*`) Searches only for the given type of |
| 103 | 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 | |
| 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 | |
| 106 | 107 | true, the "name" property is interpretted as-is. If it is false, the |
| 107 | 108 | name is automatically prepended with "sym-" (meaning a branch). |
| 108 | 109 | (FIXME: the current semantics are confusing and hard to remember. |
| 109 | 110 | Re-do them.) |
| 110 | 111 | |
| 111 | 112 |
| --- 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 |
+9
-8
| --- www/json-api/api-timeline.md | ||
| +++ www/json-api/api-timeline.md | ||
| @@ -79,11 +79,11 @@ | ||
| 79 | 79 | "comment":"Added /json/timeline/ci showFiles to ajax test page.", |
| 80 | 80 | "user":"stephan", |
| 81 | 81 | "isLeaf":true, |
| 82 | 82 | "bgColor":null, /* not quite sure why this is null? */ |
| 83 | 83 | "type":"ci", |
| 84 | - "parents": ["primary parent UUID", "...other parent UUIDs"], | |
| 84 | + "parents": ["primary parent hash", "...other parent hashes"], | |
| 85 | 85 | "tags":["json"], |
| 86 | 86 | "files":[{ |
| 87 | 87 | "name":"ajax/index.html", |
| 88 | 88 | "uuid":"9f00773a94cea6191dc3289aa24c0811b6d0d8fe", |
| 89 | 89 | "parent":"50e337c33c27529e08a7037a8679fb84b976ad0b", |
| @@ -101,12 +101,12 @@ | ||
| 101 | 101 | |
| 102 | 102 | **Request options:** |
| 103 | 103 | |
| 104 | 104 | - `files=bool` toggles the addition of a "files" array property which |
| 105 | 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).\ | |
| 106 | + including their hash, previous hash, and state change type | |
| 107 | + (modified, added, or removed). ([“uuid” here means hash][uvh])\ | |
| 108 | 108 | CLI mode: `--show-files|-f` |
| 109 | 109 | - `tag|branch=string` selects only entries with the given tag or "close |
| 110 | 110 | to" the given branch. Only one of these may be specified and if both |
| 111 | 111 | are specified, which one takes precedence is unspecified. If the |
| 112 | 112 | given tag/branch does not exist, an error response is generated. The |
| @@ -172,15 +172,15 @@ | ||
| 172 | 172 | "ticketUuid":"b64435dba9cceb709bd54fbc5883884d73f93491" |
| 173 | 173 | },...] |
| 174 | 174 | } |
| 175 | 175 | ``` |
| 176 | 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 | |
| 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 | 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. | |
| 180 | +hash. We may want to swap `uuid` to mean the ticket hash and change `uuid` | |
| 181 | +to `commitHash`. | |
| 182 | 182 | |
| 183 | 183 | <a id="wiki"></a> |
| 184 | 184 | # Wiki Timeline |
| 185 | 185 | |
| 186 | 186 | **Status:** implemented 201109xx |
| @@ -206,8 +206,9 @@ | ||
| 206 | 206 | },...] |
| 207 | 207 | } |
| 208 | 208 | ``` |
| 209 | 209 | |
| 210 | 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 | |
| 211 | +`/json/wiki/get?uuid=...` to fetch the raw page and the hash of the | |
| 212 | 212 | parent version. |
| 213 | 213 | |
| 214 | +[uvh]: ../hashes.md#uvh | |
| 214 | 215 |
| --- 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 |
+2
-1
| --- www/json-api/conventions.md | ||
| +++ www/json-api/conventions.md | ||
| @@ -584,11 +584,12 @@ | ||
| 584 | 584 | - `FOSSIL-3001`: Invalid argument/parameter type(s) or value(s) in |
| 585 | 585 | request |
| 586 | 586 | - `FOSSIL-3002`: Required argument(s)/parameter(s) missing from |
| 587 | 587 | request |
| 588 | 588 | - `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.) | |
| 590 | 591 | - `FOSSIL-3004`: Unresolved resource identifier. A branch/tag/uuid |
| 591 | 592 | provided by client code could not be resolved. This is a special |
| 592 | 593 | case of #3006. |
| 593 | 594 | - `FOSSIL-3005`: Resource already exists and overwriting/replacing is |
| 594 | 595 | not allowed. e.g. trying to create a wiki page or user which already |
| 595 | 596 |
| --- 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 |