Fossil SCM
Merge trunk
Commit
9f507ffe494859c604109f735f4962ecdfc2c184
Parent
c1416fd1339ffcc…
54 files changed
+1
-1
+1
+2
-2
+48
-4
+7
-6
+1
+8
-2
+1
+2
-2
+33
-7
+52
-23
+5
-3
+5
-3
+12
-5
+3
-8
+8
-15
+2
-2
+28
-15
+28
-15
+1
+13
-5
+14
-1
+2
+56
-56
+28
-10
+19
+26
-20
+1
-1
+44
-18
+2
-2
+92
+270
-264
+162
-16
+245
-276
+5
-5
+16
-24
+6
-4
+35
-7
+3
-1
+1
-1
+1
-1
+43
+1
-1
+11
-5
+13
+13
+11
+33
-14
+35
-2
+144
+5
+1
+5
-1
+78
-39
~
VERSION
~
auto.def
~
skins/default/details.txt
~
skins/eagle/css.txt
~
skins/xekri/css.txt
~
skins/xekri/header.txt
~
src/add.c
~
src/allrepo.c
~
src/blob.c
~
src/checkin.c
~
src/db.c
~
src/descendants.c
~
src/descendants.c
~
src/file.c
~
src/finfo.c
~
src/graph.c
~
src/http.c
~
src/info.c
~
src/info.c
~
src/json.c
~
src/main.c
~
src/main.mk
~
src/makemake.tcl
~
src/markdown_html.c
~
src/name.c
~
src/piechart.c
~
src/rebuild.c
~
src/search.c
~
src/sqlite3.c
~
src/sqlite3.h
~
src/stat.c
~
src/statrep.c
~
src/style.c
~
src/timeline.c
~
src/translate.c
~
src/update.c
~
src/url.c
~
src/vfile.c
~
src/wikiformat.c
~
src/xfer.c
~
src/xfer.c
~
test/contains-selector.test
~
win/Makefile.PellesCGMake
~
win/Makefile.dmc
~
win/Makefile.mingw
~
win/Makefile.mingw.mistachkin
~
win/Makefile.msc
~
www/build.wiki
~
www/changes.wiki
~
www/customgraph.md
~
www/customskin.md
~
www/mkindex.tcl
~
www/permutedindex.html
~
www/th1.md
M
VERSION
+1
-1
| --- VERSION | ||
| +++ VERSION | ||
| @@ -1,1 +1,1 @@ | ||
| 1 | -1.32 | |
| 1 | +1.33 | |
| 2 | 2 |
| --- VERSION | |
| +++ VERSION | |
| @@ -1,1 +1,1 @@ | |
| 1 | 1.32 |
| 2 |
| --- VERSION | |
| +++ VERSION | |
| @@ -1,1 +1,1 @@ | |
| 1 | 1.33 |
| 2 |
M
auto.def
+1
| --- auto.def | ||
| +++ auto.def | ||
| @@ -299,10 +299,11 @@ | ||
| 299 | 299 | if {![cc-check-functions getpassphrase]} { |
| 300 | 300 | # Haiku needs this |
| 301 | 301 | cc-check-function-in-lib getpass bsd |
| 302 | 302 | } |
| 303 | 303 | cc-check-function-in-lib dlopen dl |
| 304 | +cc-check-function-in-lib sin m | |
| 304 | 305 | |
| 305 | 306 | # Check for the FuseFS library |
| 306 | 307 | if {[opt-bool fusefs]} { |
| 307 | 308 | if {[cc-check-function-in-lib fuse_mount fuse]} { |
| 308 | 309 | define FOSSIL_HAVE_FUSEFS 1 |
| 309 | 310 |
| --- auto.def | |
| +++ auto.def | |
| @@ -299,10 +299,11 @@ | |
| 299 | if {![cc-check-functions getpassphrase]} { |
| 300 | # Haiku needs this |
| 301 | cc-check-function-in-lib getpass bsd |
| 302 | } |
| 303 | cc-check-function-in-lib dlopen dl |
| 304 | |
| 305 | # Check for the FuseFS library |
| 306 | if {[opt-bool fusefs]} { |
| 307 | if {[cc-check-function-in-lib fuse_mount fuse]} { |
| 308 | define FOSSIL_HAVE_FUSEFS 1 |
| 309 |
| --- auto.def | |
| +++ auto.def | |
| @@ -299,10 +299,11 @@ | |
| 299 | if {![cc-check-functions getpassphrase]} { |
| 300 | # Haiku needs this |
| 301 | cc-check-function-in-lib getpass bsd |
| 302 | } |
| 303 | cc-check-function-in-lib dlopen dl |
| 304 | cc-check-function-in-lib sin m |
| 305 | |
| 306 | # Check for the FuseFS library |
| 307 | if {[opt-bool fusefs]} { |
| 308 | if {[cc-check-function-in-lib fuse_mount fuse]} { |
| 309 | define FOSSIL_HAVE_FUSEFS 1 |
| 310 |
+2
-2
| --- skins/default/details.txt | ||
| +++ skins/default/details.txt | ||
| @@ -1,4 +1,4 @@ | ||
| 1 | 1 | timeline-arrowheads: 1 |
| 2 | -timeline-circle-nodes: 0 | |
| 3 | -timeline-color-graph-lines: 0 | |
| 2 | +timeline-circle-nodes: 1 | |
| 3 | +timeline-color-graph-lines: 1 | |
| 4 | 4 | white-foreground: 0 |
| 5 | 5 |
| --- skins/default/details.txt | |
| +++ skins/default/details.txt | |
| @@ -1,4 +1,4 @@ | |
| 1 | timeline-arrowheads: 1 |
| 2 | timeline-circle-nodes: 0 |
| 3 | timeline-color-graph-lines: 0 |
| 4 | white-foreground: 0 |
| 5 |
| --- skins/default/details.txt | |
| +++ skins/default/details.txt | |
| @@ -1,4 +1,4 @@ | |
| 1 | timeline-arrowheads: 1 |
| 2 | timeline-circle-nodes: 1 |
| 3 | timeline-color-graph-lines: 1 |
| 4 | white-foreground: 0 |
| 5 |
+48
-4
| --- skins/eagle/css.txt | ||
| +++ skins/eagle/css.txt | ||
| @@ -168,10 +168,58 @@ | ||
| 168 | 168 | } |
| 169 | 169 | |
| 170 | 170 | tr.timelineSelected { |
| 171 | 171 | background-color: #7EA2D9; |
| 172 | 172 | } |
| 173 | + | |
| 174 | +/* commit node */ | |
| 175 | +.tl-node { | |
| 176 | + width: 10px; | |
| 177 | + height: 10px; | |
| 178 | + border: 1px solid #fff; | |
| 179 | + background: #485D7B; | |
| 180 | + cursor: pointer; | |
| 181 | +} | |
| 182 | + | |
| 183 | +/* leaf commit marker */ | |
| 184 | +.tl-node.leaf:after { | |
| 185 | + content: ''; | |
| 186 | + position: absolute; | |
| 187 | + top: 3px; | |
| 188 | + left: 3px; | |
| 189 | + width: 4px; | |
| 190 | + height: 4px; | |
| 191 | + background: #fff; | |
| 192 | +} | |
| 193 | + | |
| 194 | +/* up arrow */ | |
| 195 | +.tl-arrow.u { | |
| 196 | + margin-top: -1px; | |
| 197 | + border-width: 0 3px; | |
| 198 | + border-bottom: 7px solid #fff; | |
| 199 | +} | |
| 200 | + | |
| 201 | +/* small up arrow */ | |
| 202 | +.tl-arrow.u.sm { | |
| 203 | + border-bottom: 5px solid #fff; | |
| 204 | +} | |
| 205 | + | |
| 206 | +/* line */ | |
| 207 | +.tl-line { | |
| 208 | + background: #fff; | |
| 209 | + width: 2px; | |
| 210 | +} | |
| 211 | + | |
| 212 | +/* left merge arrow */ | |
| 213 | +.tl-arrow.merge.l { | |
| 214 | + border-right: 3px solid #fff; | |
| 215 | +} | |
| 216 | + | |
| 217 | +/* right merge arrow */ | |
| 218 | +.tl-arrow.merge.r { | |
| 219 | + border-left: 3px solid #fff; | |
| 220 | +} | |
| 173 | 221 | |
| 174 | 222 | /* Side-by-side diff */ |
| 175 | 223 | table.sbsdiff { |
| 176 | 224 | background-color: #485D7B; |
| 177 | 225 | font-family: fixed, Dejavu Sans Mono, Monaco, Lucida Console, monospace; |
| @@ -264,14 +312,10 @@ | ||
| 264 | 312 | /* line numbers in a diff */ |
| 265 | 313 | span.diffln { |
| 266 | 314 | color: white; |
| 267 | 315 | } |
| 268 | 316 | |
| 269 | -#canvas { | |
| 270 | - background-color: #485D7B; | |
| 271 | -} | |
| 272 | - | |
| 273 | 317 | .fileage tr:hover { |
| 274 | 318 | background-color: #7EA2D9; |
| 275 | 319 | } |
| 276 | 320 | |
| 277 | 321 | .fileage td { |
| 278 | 322 |
| --- skins/eagle/css.txt | |
| +++ skins/eagle/css.txt | |
| @@ -168,10 +168,58 @@ | |
| 168 | } |
| 169 | |
| 170 | tr.timelineSelected { |
| 171 | background-color: #7EA2D9; |
| 172 | } |
| 173 | |
| 174 | /* Side-by-side diff */ |
| 175 | table.sbsdiff { |
| 176 | background-color: #485D7B; |
| 177 | font-family: fixed, Dejavu Sans Mono, Monaco, Lucida Console, monospace; |
| @@ -264,14 +312,10 @@ | |
| 264 | /* line numbers in a diff */ |
| 265 | span.diffln { |
| 266 | color: white; |
| 267 | } |
| 268 | |
| 269 | #canvas { |
| 270 | background-color: #485D7B; |
| 271 | } |
| 272 | |
| 273 | .fileage tr:hover { |
| 274 | background-color: #7EA2D9; |
| 275 | } |
| 276 | |
| 277 | .fileage td { |
| 278 |
| --- skins/eagle/css.txt | |
| +++ skins/eagle/css.txt | |
| @@ -168,10 +168,58 @@ | |
| 168 | } |
| 169 | |
| 170 | tr.timelineSelected { |
| 171 | background-color: #7EA2D9; |
| 172 | } |
| 173 | |
| 174 | /* commit node */ |
| 175 | .tl-node { |
| 176 | width: 10px; |
| 177 | height: 10px; |
| 178 | border: 1px solid #fff; |
| 179 | background: #485D7B; |
| 180 | cursor: pointer; |
| 181 | } |
| 182 | |
| 183 | /* leaf commit marker */ |
| 184 | .tl-node.leaf:after { |
| 185 | content: ''; |
| 186 | position: absolute; |
| 187 | top: 3px; |
| 188 | left: 3px; |
| 189 | width: 4px; |
| 190 | height: 4px; |
| 191 | background: #fff; |
| 192 | } |
| 193 | |
| 194 | /* up arrow */ |
| 195 | .tl-arrow.u { |
| 196 | margin-top: -1px; |
| 197 | border-width: 0 3px; |
| 198 | border-bottom: 7px solid #fff; |
| 199 | } |
| 200 | |
| 201 | /* small up arrow */ |
| 202 | .tl-arrow.u.sm { |
| 203 | border-bottom: 5px solid #fff; |
| 204 | } |
| 205 | |
| 206 | /* line */ |
| 207 | .tl-line { |
| 208 | background: #fff; |
| 209 | width: 2px; |
| 210 | } |
| 211 | |
| 212 | /* left merge arrow */ |
| 213 | .tl-arrow.merge.l { |
| 214 | border-right: 3px solid #fff; |
| 215 | } |
| 216 | |
| 217 | /* right merge arrow */ |
| 218 | .tl-arrow.merge.r { |
| 219 | border-left: 3px solid #fff; |
| 220 | } |
| 221 | |
| 222 | /* Side-by-side diff */ |
| 223 | table.sbsdiff { |
| 224 | background-color: #485D7B; |
| 225 | font-family: fixed, Dejavu Sans Mono, Monaco, Lucida Console, monospace; |
| @@ -264,14 +312,10 @@ | |
| 312 | /* line numbers in a diff */ |
| 313 | span.diffln { |
| 314 | color: white; |
| 315 | } |
| 316 | |
| 317 | .fileage tr:hover { |
| 318 | background-color: #7EA2D9; |
| 319 | } |
| 320 | |
| 321 | .fileage td { |
| 322 |
+7
-6
| --- skins/xekri/css.txt | ||
| +++ skins/xekri/css.txt | ||
| @@ -202,10 +202,17 @@ | ||
| 202 | 202 | } |
| 203 | 203 | |
| 204 | 204 | div.content table[bgcolor="white"] { |
| 205 | 205 | color: #000; |
| 206 | 206 | } |
| 207 | + | |
| 208 | +.piechartLabel { | |
| 209 | + fill: white; | |
| 210 | +} | |
| 211 | +.piechartLine { | |
| 212 | + stroke: white; | |
| 213 | +} | |
| 207 | 214 | |
| 208 | 215 | /************************************** |
| 209 | 216 | * Main Area: Footer |
| 210 | 217 | */ |
| 211 | 218 | |
| @@ -700,15 +707,10 @@ | ||
| 700 | 707 | |
| 701 | 708 | /************************************** |
| 702 | 709 | * Timeline |
| 703 | 710 | */ |
| 704 | 711 | |
| 705 | -#canvas { | |
| 706 | - color: #000; | |
| 707 | - background-color: #fff; | |
| 708 | -} | |
| 709 | - | |
| 710 | 712 | div.divider { |
| 711 | 713 | color: #ee0; |
| 712 | 714 | font-size: 1.2rem; |
| 713 | 715 | font-weight: bold; |
| 714 | 716 | margin-top: 1rem; |
| @@ -1027,6 +1029,5 @@ | ||
| 1027 | 1029 | } |
| 1028 | 1030 | /* odd table row color */ |
| 1029 | 1031 | tr.row1 { |
| 1030 | 1032 | /* Use default */ |
| 1031 | 1033 | } |
| 1032 | - | |
| 1033 | 1034 |
| --- skins/xekri/css.txt | |
| +++ skins/xekri/css.txt | |
| @@ -202,10 +202,17 @@ | |
| 202 | } |
| 203 | |
| 204 | div.content table[bgcolor="white"] { |
| 205 | color: #000; |
| 206 | } |
| 207 | |
| 208 | /************************************** |
| 209 | * Main Area: Footer |
| 210 | */ |
| 211 | |
| @@ -700,15 +707,10 @@ | |
| 700 | |
| 701 | /************************************** |
| 702 | * Timeline |
| 703 | */ |
| 704 | |
| 705 | #canvas { |
| 706 | color: #000; |
| 707 | background-color: #fff; |
| 708 | } |
| 709 | |
| 710 | div.divider { |
| 711 | color: #ee0; |
| 712 | font-size: 1.2rem; |
| 713 | font-weight: bold; |
| 714 | margin-top: 1rem; |
| @@ -1027,6 +1029,5 @@ | |
| 1027 | } |
| 1028 | /* odd table row color */ |
| 1029 | tr.row1 { |
| 1030 | /* Use default */ |
| 1031 | } |
| 1032 | |
| 1033 |
| --- skins/xekri/css.txt | |
| +++ skins/xekri/css.txt | |
| @@ -202,10 +202,17 @@ | |
| 202 | } |
| 203 | |
| 204 | div.content table[bgcolor="white"] { |
| 205 | color: #000; |
| 206 | } |
| 207 | |
| 208 | .piechartLabel { |
| 209 | fill: white; |
| 210 | } |
| 211 | .piechartLine { |
| 212 | stroke: white; |
| 213 | } |
| 214 | |
| 215 | /************************************** |
| 216 | * Main Area: Footer |
| 217 | */ |
| 218 | |
| @@ -700,15 +707,10 @@ | |
| 707 | |
| 708 | /************************************** |
| 709 | * Timeline |
| 710 | */ |
| 711 | |
| 712 | div.divider { |
| 713 | color: #ee0; |
| 714 | font-size: 1.2rem; |
| 715 | font-weight: bold; |
| 716 | margin-top: 1rem; |
| @@ -1027,6 +1029,5 @@ | |
| 1029 | } |
| 1030 | /* odd table row color */ |
| 1031 | tr.row1 { |
| 1032 | /* Use default */ |
| 1033 | } |
| 1034 |
| --- skins/xekri/header.txt | ||
| +++ skins/xekri/header.txt | ||
| @@ -127,10 +127,11 @@ | ||
| 127 | 127 | menulink /ticket Tickets |
| 128 | 128 | } |
| 129 | 129 | if {[anoncap j]} { |
| 130 | 130 | menulink /wiki Wiki |
| 131 | 131 | } |
| 132 | + menulink /sitemap More... | |
| 132 | 133 | if {[hascap s]} { |
| 133 | 134 | menulink /setup Admin |
| 134 | 135 | } elseif {[hascap a]} { |
| 135 | 136 | menulink /setup_ulist Users |
| 136 | 137 | } |
| 137 | 138 |
| --- skins/xekri/header.txt | |
| +++ skins/xekri/header.txt | |
| @@ -127,10 +127,11 @@ | |
| 127 | menulink /ticket Tickets |
| 128 | } |
| 129 | if {[anoncap j]} { |
| 130 | menulink /wiki Wiki |
| 131 | } |
| 132 | if {[hascap s]} { |
| 133 | menulink /setup Admin |
| 134 | } elseif {[hascap a]} { |
| 135 | menulink /setup_ulist Users |
| 136 | } |
| 137 |
| --- skins/xekri/header.txt | |
| +++ skins/xekri/header.txt | |
| @@ -127,10 +127,11 @@ | |
| 127 | menulink /ticket Tickets |
| 128 | } |
| 129 | if {[anoncap j]} { |
| 130 | menulink /wiki Wiki |
| 131 | } |
| 132 | menulink /sitemap More... |
| 133 | if {[hascap s]} { |
| 134 | menulink /setup Admin |
| 135 | } elseif {[hascap a]} { |
| 136 | menulink /setup_ulist Users |
| 137 | } |
| 138 |
+8
-2
| --- src/add.c | ||
| +++ src/add.c | ||
| @@ -317,12 +317,10 @@ | ||
| 317 | 317 | isDir = file_wd_isdir(zName); |
| 318 | 318 | if( isDir==1 ){ |
| 319 | 319 | vfile_scan(&fullName, nRoot-1, scanFlags, pClean, pIgnore); |
| 320 | 320 | }else if( isDir==0 ){ |
| 321 | 321 | fossil_warning("not found: %s", zName); |
| 322 | - }else if( file_access(zName, R_OK) ){ | |
| 323 | - fossil_fatal("cannot open %s", zName); | |
| 324 | 322 | }else{ |
| 325 | 323 | char *zTreeName = &zName[nRoot]; |
| 326 | 324 | if( !forceFlag && glob_match(pIgnore, zTreeName) ){ |
| 327 | 325 | Blob ans; |
| 328 | 326 | char cReply; |
| @@ -632,10 +630,18 @@ | ||
| 632 | 630 | } |
| 633 | 631 | |
| 634 | 632 | /* We should be done with options.. */ |
| 635 | 633 | verify_all_options(); |
| 636 | 634 | |
| 635 | + /* Fail if unprocessed arguments are present, in case user expect the | |
| 636 | + ** addremove command to accept a list of file or directory. | |
| 637 | + */ | |
| 638 | + if( g.argc>2 ){ | |
| 639 | + fossil_fatal( | |
| 640 | + "%s: Can only work on the entire checkout, no arguments supported.", | |
| 641 | + g.argv[1]); | |
| 642 | + } | |
| 637 | 643 | db_must_be_within_tree(); |
| 638 | 644 | if( zCleanFlag==0 ){ |
| 639 | 645 | zCleanFlag = db_get("clean-glob", 0); |
| 640 | 646 | } |
| 641 | 647 | if( zIgnoreFlag==0 ){ |
| 642 | 648 |
| --- src/add.c | |
| +++ src/add.c | |
| @@ -317,12 +317,10 @@ | |
| 317 | isDir = file_wd_isdir(zName); |
| 318 | if( isDir==1 ){ |
| 319 | vfile_scan(&fullName, nRoot-1, scanFlags, pClean, pIgnore); |
| 320 | }else if( isDir==0 ){ |
| 321 | fossil_warning("not found: %s", zName); |
| 322 | }else if( file_access(zName, R_OK) ){ |
| 323 | fossil_fatal("cannot open %s", zName); |
| 324 | }else{ |
| 325 | char *zTreeName = &zName[nRoot]; |
| 326 | if( !forceFlag && glob_match(pIgnore, zTreeName) ){ |
| 327 | Blob ans; |
| 328 | char cReply; |
| @@ -632,10 +630,18 @@ | |
| 632 | } |
| 633 | |
| 634 | /* We should be done with options.. */ |
| 635 | verify_all_options(); |
| 636 | |
| 637 | db_must_be_within_tree(); |
| 638 | if( zCleanFlag==0 ){ |
| 639 | zCleanFlag = db_get("clean-glob", 0); |
| 640 | } |
| 641 | if( zIgnoreFlag==0 ){ |
| 642 |
| --- src/add.c | |
| +++ src/add.c | |
| @@ -317,12 +317,10 @@ | |
| 317 | isDir = file_wd_isdir(zName); |
| 318 | if( isDir==1 ){ |
| 319 | vfile_scan(&fullName, nRoot-1, scanFlags, pClean, pIgnore); |
| 320 | }else if( isDir==0 ){ |
| 321 | fossil_warning("not found: %s", zName); |
| 322 | }else{ |
| 323 | char *zTreeName = &zName[nRoot]; |
| 324 | if( !forceFlag && glob_match(pIgnore, zTreeName) ){ |
| 325 | Blob ans; |
| 326 | char cReply; |
| @@ -632,10 +630,18 @@ | |
| 630 | } |
| 631 | |
| 632 | /* We should be done with options.. */ |
| 633 | verify_all_options(); |
| 634 | |
| 635 | /* Fail if unprocessed arguments are present, in case user expect the |
| 636 | ** addremove command to accept a list of file or directory. |
| 637 | */ |
| 638 | if( g.argc>2 ){ |
| 639 | fossil_fatal( |
| 640 | "%s: Can only work on the entire checkout, no arguments supported.", |
| 641 | g.argv[1]); |
| 642 | } |
| 643 | db_must_be_within_tree(); |
| 644 | if( zCleanFlag==0 ){ |
| 645 | zCleanFlag = db_get("clean-glob", 0); |
| 646 | } |
| 647 | if( zIgnoreFlag==0 ){ |
| 648 |
+1
| --- src/allrepo.c | ||
| +++ src/allrepo.c | ||
| @@ -231,10 +231,11 @@ | ||
| 231 | 231 | collect_argument(&extra, "verbose","v"); |
| 232 | 232 | }else if( strncmp(zCmd, "rebuild", n)==0 ){ |
| 233 | 233 | zCmd = "rebuild"; |
| 234 | 234 | collect_argument(&extra, "cluster",0); |
| 235 | 235 | collect_argument(&extra, "compress",0); |
| 236 | + collect_argument(&extra, "compress-only",0); | |
| 236 | 237 | collect_argument(&extra, "noverify",0); |
| 237 | 238 | collect_argument_value(&extra, "pagesize"); |
| 238 | 239 | collect_argument(&extra, "vacuum",0); |
| 239 | 240 | collect_argument(&extra, "deanalyze",0); |
| 240 | 241 | collect_argument(&extra, "analyze",0); |
| 241 | 242 |
| --- src/allrepo.c | |
| +++ src/allrepo.c | |
| @@ -231,10 +231,11 @@ | |
| 231 | collect_argument(&extra, "verbose","v"); |
| 232 | }else if( strncmp(zCmd, "rebuild", n)==0 ){ |
| 233 | zCmd = "rebuild"; |
| 234 | collect_argument(&extra, "cluster",0); |
| 235 | collect_argument(&extra, "compress",0); |
| 236 | collect_argument(&extra, "noverify",0); |
| 237 | collect_argument_value(&extra, "pagesize"); |
| 238 | collect_argument(&extra, "vacuum",0); |
| 239 | collect_argument(&extra, "deanalyze",0); |
| 240 | collect_argument(&extra, "analyze",0); |
| 241 |
| --- src/allrepo.c | |
| +++ src/allrepo.c | |
| @@ -231,10 +231,11 @@ | |
| 231 | collect_argument(&extra, "verbose","v"); |
| 232 | }else if( strncmp(zCmd, "rebuild", n)==0 ){ |
| 233 | zCmd = "rebuild"; |
| 234 | collect_argument(&extra, "cluster",0); |
| 235 | collect_argument(&extra, "compress",0); |
| 236 | collect_argument(&extra, "compress-only",0); |
| 237 | collect_argument(&extra, "noverify",0); |
| 238 | collect_argument_value(&extra, "pagesize"); |
| 239 | collect_argument(&extra, "vacuum",0); |
| 240 | collect_argument(&extra, "deanalyze",0); |
| 241 | collect_argument(&extra, "analyze",0); |
| 242 |
+2
-2
| --- src/blob.c | ||
| +++ src/blob.c | ||
| @@ -300,11 +300,11 @@ | ||
| 300 | 300 | ** Return a pointer to a null-terminated string for a blob. |
| 301 | 301 | */ |
| 302 | 302 | char *blob_str(Blob *p){ |
| 303 | 303 | blob_is_init(p); |
| 304 | 304 | if( p->nUsed==0 ){ |
| 305 | - blob_append(p, "", 1); | |
| 305 | + blob_append(p, "", 1); /* NOTE: Changes nUsed. */ | |
| 306 | 306 | p->nUsed = 0; |
| 307 | 307 | } |
| 308 | 308 | if( p->aData[p->nUsed]!=0 ){ |
| 309 | 309 | blob_materialize(p); |
| 310 | 310 | } |
| @@ -839,11 +839,11 @@ | ||
| 839 | 839 | #if defined(_WIN32) |
| 840 | 840 | fflush(stdout); |
| 841 | 841 | _setmode(_fileno(stdout), _O_TEXT); |
| 842 | 842 | #endif |
| 843 | 843 | }else{ |
| 844 | - file_mkfolder(zFilename, 1); | |
| 844 | + file_mkfolder(zFilename, 1, 0); | |
| 845 | 845 | out = fossil_fopen(zFilename, "wb"); |
| 846 | 846 | if( out==0 ){ |
| 847 | 847 | fossil_fatal_recursive("unable to open file \"%s\" for writing", |
| 848 | 848 | zFilename); |
| 849 | 849 | return 0; |
| 850 | 850 |
| --- src/blob.c | |
| +++ src/blob.c | |
| @@ -300,11 +300,11 @@ | |
| 300 | ** Return a pointer to a null-terminated string for a blob. |
| 301 | */ |
| 302 | char *blob_str(Blob *p){ |
| 303 | blob_is_init(p); |
| 304 | if( p->nUsed==0 ){ |
| 305 | blob_append(p, "", 1); |
| 306 | p->nUsed = 0; |
| 307 | } |
| 308 | if( p->aData[p->nUsed]!=0 ){ |
| 309 | blob_materialize(p); |
| 310 | } |
| @@ -839,11 +839,11 @@ | |
| 839 | #if defined(_WIN32) |
| 840 | fflush(stdout); |
| 841 | _setmode(_fileno(stdout), _O_TEXT); |
| 842 | #endif |
| 843 | }else{ |
| 844 | file_mkfolder(zFilename, 1); |
| 845 | out = fossil_fopen(zFilename, "wb"); |
| 846 | if( out==0 ){ |
| 847 | fossil_fatal_recursive("unable to open file \"%s\" for writing", |
| 848 | zFilename); |
| 849 | return 0; |
| 850 |
| --- src/blob.c | |
| +++ src/blob.c | |
| @@ -300,11 +300,11 @@ | |
| 300 | ** Return a pointer to a null-terminated string for a blob. |
| 301 | */ |
| 302 | char *blob_str(Blob *p){ |
| 303 | blob_is_init(p); |
| 304 | if( p->nUsed==0 ){ |
| 305 | blob_append(p, "", 1); /* NOTE: Changes nUsed. */ |
| 306 | p->nUsed = 0; |
| 307 | } |
| 308 | if( p->aData[p->nUsed]!=0 ){ |
| 309 | blob_materialize(p); |
| 310 | } |
| @@ -839,11 +839,11 @@ | |
| 839 | #if defined(_WIN32) |
| 840 | fflush(stdout); |
| 841 | _setmode(_fileno(stdout), _O_TEXT); |
| 842 | #endif |
| 843 | }else{ |
| 844 | file_mkfolder(zFilename, 1, 0); |
| 845 | out = fossil_fopen(zFilename, "wb"); |
| 846 | if( out==0 ){ |
| 847 | fossil_fatal_recursive("unable to open file \"%s\" for writing", |
| 848 | zFilename); |
| 849 | return 0; |
| 850 |
+33
-7
| --- src/checkin.c | ||
| +++ src/checkin.c | ||
| @@ -113,10 +113,18 @@ | ||
| 113 | 113 | blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName); |
| 114 | 114 | }else if( isChnged==4 ){ |
| 115 | 115 | blob_appendf(report, "UPDATED_BY_INTEGRATE %s\n", zDisplayName); |
| 116 | 116 | }else if( isChnged==5 ){ |
| 117 | 117 | blob_appendf(report, "ADDED_BY_INTEGRATE %s\n", zDisplayName); |
| 118 | + }else if( isChnged==6 ){ | |
| 119 | + blob_appendf(report, "EXECUTABLE %s\n", zDisplayName); | |
| 120 | + }else if( isChnged==7 ){ | |
| 121 | + blob_appendf(report, "SYMLINK %s\n", zDisplayName); | |
| 122 | + }else if( isChnged==8 ){ | |
| 123 | + blob_appendf(report, "UNEXEC %s\n", zDisplayName); | |
| 124 | + }else if( isChnged==9 ){ | |
| 125 | + blob_appendf(report, "UNLINK %s\n", zDisplayName); | |
| 118 | 126 | }else if( file_contains_merge_marker(zFullName) ){ |
| 119 | 127 | blob_appendf(report, "CONFLICT %s\n", zDisplayName); |
| 120 | 128 | }else{ |
| 121 | 129 | blob_appendf(report, "EDITED %s\n", zDisplayName); |
| 122 | 130 | } |
| @@ -1633,10 +1641,12 @@ | ||
| 1633 | 1641 | int dryRunFlag; /* True for a test run. Debugging only */ |
| 1634 | 1642 | CheckinInfo sCiInfo; /* Information about this check-in */ |
| 1635 | 1643 | const char *zComFile; /* Read commit message from this file */ |
| 1636 | 1644 | int nTag = 0; /* Number of --tag arguments */ |
| 1637 | 1645 | const char *zTag; /* A single --tag argument */ |
| 1646 | + ManifestFile *pFile; /* File structure in the manifest */ | |
| 1647 | + Manifest *pManifest; /* Manifest structure */ | |
| 1638 | 1648 | Blob manifest; /* Manifest in baseline form */ |
| 1639 | 1649 | Blob muuid; /* Manifest uuid */ |
| 1640 | 1650 | Blob cksum1, cksum2; /* Before and after commit checksums */ |
| 1641 | 1651 | Blob cksum1b; /* Checksum recorded in the manifest */ |
| 1642 | 1652 | int szD; /* Size of the delta manifest */ |
| @@ -1900,11 +1910,11 @@ | ||
| 1900 | 1910 | /* Step 2: Insert records for all modified files into the blob |
| 1901 | 1911 | ** table. If there were arguments passed to this command, only |
| 1902 | 1912 | ** the identified files are inserted (if they have been modified). |
| 1903 | 1913 | */ |
| 1904 | 1914 | db_prepare(&q, |
| 1905 | - "SELECT id, %Q || pathname, mrid, %s, chnged, %s, %s FROM vfile " | |
| 1915 | + "SELECT id, %Q || pathname, mrid, %s, %s, %s FROM vfile " | |
| 1906 | 1916 | "WHERE chnged==1 AND NOT deleted AND is_selected(id)", |
| 1907 | 1917 | g.zLocalRoot, |
| 1908 | 1918 | glob_expr("pathname", db_get("crnl-glob","")), |
| 1909 | 1919 | glob_expr("pathname", db_get("binary-glob","")), |
| 1910 | 1920 | glob_expr("pathname", db_get("encoding-glob","")) |
| @@ -1911,19 +1921,18 @@ | ||
| 1911 | 1921 | ); |
| 1912 | 1922 | while( db_step(&q)==SQLITE_ROW ){ |
| 1913 | 1923 | int id, rid; |
| 1914 | 1924 | const char *zFullname; |
| 1915 | 1925 | Blob content; |
| 1916 | - int crnlOk, binOk, encodingOk, chnged; | |
| 1926 | + int crnlOk, binOk, encodingOk; | |
| 1917 | 1927 | |
| 1918 | 1928 | id = db_column_int(&q, 0); |
| 1919 | 1929 | zFullname = db_column_text(&q, 1); |
| 1920 | 1930 | rid = db_column_int(&q, 2); |
| 1921 | 1931 | crnlOk = db_column_int(&q, 3); |
| 1922 | - chnged = db_column_int(&q, 4); | |
| 1923 | - binOk = db_column_int(&q, 5); | |
| 1924 | - encodingOk = db_column_int(&q, 6); | |
| 1932 | + binOk = db_column_int(&q, 4); | |
| 1933 | + encodingOk = db_column_int(&q, 5); | |
| 1925 | 1934 | |
| 1926 | 1935 | blob_zero(&content); |
| 1927 | 1936 | if( file_wd_islink(zFullname) ){ |
| 1928 | 1937 | /* Instead of file content, put link destination path */ |
| 1929 | 1938 | blob_read_link(&content, zFullname); |
| @@ -1933,11 +1942,11 @@ | ||
| 1933 | 1942 | /* Do not emit any warnings when they are disabled. */ |
| 1934 | 1943 | if( !noWarningFlag ){ |
| 1935 | 1944 | abortCommit |= commit_warning(&content, crnlOk, binOk, |
| 1936 | 1945 | encodingOk, zFullname); |
| 1937 | 1946 | } |
| 1938 | - if( chnged==1 && contains_merge_marker(&content) ){ | |
| 1947 | + if( contains_merge_marker(&content) ){ | |
| 1939 | 1948 | Blob fname; /* Relative pathname of the file */ |
| 1940 | 1949 | |
| 1941 | 1950 | nConflict++; |
| 1942 | 1951 | file_relative_name(zFullname, &fname, 0); |
| 1943 | 1952 | fossil_print("possible unresolved merge conflict in %s\n", |
| @@ -2071,11 +2080,10 @@ | ||
| 2071 | 2080 | blob_write_to_file(&muuid, zManifestFile); |
| 2072 | 2081 | free(zManifestFile); |
| 2073 | 2082 | blob_reset(&muuid); |
| 2074 | 2083 | } |
| 2075 | 2084 | |
| 2076 | - | |
| 2077 | 2085 | /* Update the vfile and vmerge tables */ |
| 2078 | 2086 | db_multi_exec( |
| 2079 | 2087 | "DELETE FROM vfile WHERE (vid!=%d OR deleted) AND is_selected(id);" |
| 2080 | 2088 | "DELETE FROM vmerge;" |
| 2081 | 2089 | "UPDATE vfile SET vid=%d;" |
| @@ -2082,10 +2090,28 @@ | ||
| 2082 | 2090 | "UPDATE vfile SET rid=mrid, chnged=0, deleted=0, origname=NULL" |
| 2083 | 2091 | " WHERE is_selected(id);" |
| 2084 | 2092 | , vid, nvid |
| 2085 | 2093 | ); |
| 2086 | 2094 | db_lset_int("checkout", nvid); |
| 2095 | + | |
| 2096 | + /* Update the isexe and islink columns of the vfile table */ | |
| 2097 | + db_prepare(&q, | |
| 2098 | + "UPDATE vfile SET isexe=:exec, islink=:link" | |
| 2099 | + " WHERE vid=:vid AND pathname=:path AND (isexe!=:exec OR islink!=:link)" | |
| 2100 | + ); | |
| 2101 | + db_bind_int(&q, ":vid", nvid); | |
| 2102 | + pManifest = manifest_get(nvid, CFTYPE_MANIFEST, 0); | |
| 2103 | + manifest_file_rewind(pManifest); | |
| 2104 | + while( (pFile = manifest_file_next(pManifest, 0)) ){ | |
| 2105 | + db_bind_int(&q, ":exec", pFile->zPerm && strstr(pFile->zPerm, "x")); | |
| 2106 | + db_bind_int(&q, ":link", pFile->zPerm && strstr(pFile->zPerm, "l")); | |
| 2107 | + db_bind_text(&q, ":path", pFile->zName); | |
| 2108 | + db_step(&q); | |
| 2109 | + db_reset(&q); | |
| 2110 | + } | |
| 2111 | + db_finalize(&q); | |
| 2112 | + manifest_destroy(pManifest); | |
| 2087 | 2113 | |
| 2088 | 2114 | if( useCksum ){ |
| 2089 | 2115 | /* Verify that the repository checksum matches the expected checksum |
| 2090 | 2116 | ** calculated before the check-in started (and stored as the R record |
| 2091 | 2117 | ** of the manifest file). |
| 2092 | 2118 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -113,10 +113,18 @@ | |
| 113 | blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName); |
| 114 | }else if( isChnged==4 ){ |
| 115 | blob_appendf(report, "UPDATED_BY_INTEGRATE %s\n", zDisplayName); |
| 116 | }else if( isChnged==5 ){ |
| 117 | blob_appendf(report, "ADDED_BY_INTEGRATE %s\n", zDisplayName); |
| 118 | }else if( file_contains_merge_marker(zFullName) ){ |
| 119 | blob_appendf(report, "CONFLICT %s\n", zDisplayName); |
| 120 | }else{ |
| 121 | blob_appendf(report, "EDITED %s\n", zDisplayName); |
| 122 | } |
| @@ -1633,10 +1641,12 @@ | |
| 1633 | int dryRunFlag; /* True for a test run. Debugging only */ |
| 1634 | CheckinInfo sCiInfo; /* Information about this check-in */ |
| 1635 | const char *zComFile; /* Read commit message from this file */ |
| 1636 | int nTag = 0; /* Number of --tag arguments */ |
| 1637 | const char *zTag; /* A single --tag argument */ |
| 1638 | Blob manifest; /* Manifest in baseline form */ |
| 1639 | Blob muuid; /* Manifest uuid */ |
| 1640 | Blob cksum1, cksum2; /* Before and after commit checksums */ |
| 1641 | Blob cksum1b; /* Checksum recorded in the manifest */ |
| 1642 | int szD; /* Size of the delta manifest */ |
| @@ -1900,11 +1910,11 @@ | |
| 1900 | /* Step 2: Insert records for all modified files into the blob |
| 1901 | ** table. If there were arguments passed to this command, only |
| 1902 | ** the identified files are inserted (if they have been modified). |
| 1903 | */ |
| 1904 | db_prepare(&q, |
| 1905 | "SELECT id, %Q || pathname, mrid, %s, chnged, %s, %s FROM vfile " |
| 1906 | "WHERE chnged==1 AND NOT deleted AND is_selected(id)", |
| 1907 | g.zLocalRoot, |
| 1908 | glob_expr("pathname", db_get("crnl-glob","")), |
| 1909 | glob_expr("pathname", db_get("binary-glob","")), |
| 1910 | glob_expr("pathname", db_get("encoding-glob","")) |
| @@ -1911,19 +1921,18 @@ | |
| 1911 | ); |
| 1912 | while( db_step(&q)==SQLITE_ROW ){ |
| 1913 | int id, rid; |
| 1914 | const char *zFullname; |
| 1915 | Blob content; |
| 1916 | int crnlOk, binOk, encodingOk, chnged; |
| 1917 | |
| 1918 | id = db_column_int(&q, 0); |
| 1919 | zFullname = db_column_text(&q, 1); |
| 1920 | rid = db_column_int(&q, 2); |
| 1921 | crnlOk = db_column_int(&q, 3); |
| 1922 | chnged = db_column_int(&q, 4); |
| 1923 | binOk = db_column_int(&q, 5); |
| 1924 | encodingOk = db_column_int(&q, 6); |
| 1925 | |
| 1926 | blob_zero(&content); |
| 1927 | if( file_wd_islink(zFullname) ){ |
| 1928 | /* Instead of file content, put link destination path */ |
| 1929 | blob_read_link(&content, zFullname); |
| @@ -1933,11 +1942,11 @@ | |
| 1933 | /* Do not emit any warnings when they are disabled. */ |
| 1934 | if( !noWarningFlag ){ |
| 1935 | abortCommit |= commit_warning(&content, crnlOk, binOk, |
| 1936 | encodingOk, zFullname); |
| 1937 | } |
| 1938 | if( chnged==1 && contains_merge_marker(&content) ){ |
| 1939 | Blob fname; /* Relative pathname of the file */ |
| 1940 | |
| 1941 | nConflict++; |
| 1942 | file_relative_name(zFullname, &fname, 0); |
| 1943 | fossil_print("possible unresolved merge conflict in %s\n", |
| @@ -2071,11 +2080,10 @@ | |
| 2071 | blob_write_to_file(&muuid, zManifestFile); |
| 2072 | free(zManifestFile); |
| 2073 | blob_reset(&muuid); |
| 2074 | } |
| 2075 | |
| 2076 | |
| 2077 | /* Update the vfile and vmerge tables */ |
| 2078 | db_multi_exec( |
| 2079 | "DELETE FROM vfile WHERE (vid!=%d OR deleted) AND is_selected(id);" |
| 2080 | "DELETE FROM vmerge;" |
| 2081 | "UPDATE vfile SET vid=%d;" |
| @@ -2082,10 +2090,28 @@ | |
| 2082 | "UPDATE vfile SET rid=mrid, chnged=0, deleted=0, origname=NULL" |
| 2083 | " WHERE is_selected(id);" |
| 2084 | , vid, nvid |
| 2085 | ); |
| 2086 | db_lset_int("checkout", nvid); |
| 2087 | |
| 2088 | if( useCksum ){ |
| 2089 | /* Verify that the repository checksum matches the expected checksum |
| 2090 | ** calculated before the check-in started (and stored as the R record |
| 2091 | ** of the manifest file). |
| 2092 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -113,10 +113,18 @@ | |
| 113 | blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName); |
| 114 | }else if( isChnged==4 ){ |
| 115 | blob_appendf(report, "UPDATED_BY_INTEGRATE %s\n", zDisplayName); |
| 116 | }else if( isChnged==5 ){ |
| 117 | blob_appendf(report, "ADDED_BY_INTEGRATE %s\n", zDisplayName); |
| 118 | }else if( isChnged==6 ){ |
| 119 | blob_appendf(report, "EXECUTABLE %s\n", zDisplayName); |
| 120 | }else if( isChnged==7 ){ |
| 121 | blob_appendf(report, "SYMLINK %s\n", zDisplayName); |
| 122 | }else if( isChnged==8 ){ |
| 123 | blob_appendf(report, "UNEXEC %s\n", zDisplayName); |
| 124 | }else if( isChnged==9 ){ |
| 125 | blob_appendf(report, "UNLINK %s\n", zDisplayName); |
| 126 | }else if( file_contains_merge_marker(zFullName) ){ |
| 127 | blob_appendf(report, "CONFLICT %s\n", zDisplayName); |
| 128 | }else{ |
| 129 | blob_appendf(report, "EDITED %s\n", zDisplayName); |
| 130 | } |
| @@ -1633,10 +1641,12 @@ | |
| 1641 | int dryRunFlag; /* True for a test run. Debugging only */ |
| 1642 | CheckinInfo sCiInfo; /* Information about this check-in */ |
| 1643 | const char *zComFile; /* Read commit message from this file */ |
| 1644 | int nTag = 0; /* Number of --tag arguments */ |
| 1645 | const char *zTag; /* A single --tag argument */ |
| 1646 | ManifestFile *pFile; /* File structure in the manifest */ |
| 1647 | Manifest *pManifest; /* Manifest structure */ |
| 1648 | Blob manifest; /* Manifest in baseline form */ |
| 1649 | Blob muuid; /* Manifest uuid */ |
| 1650 | Blob cksum1, cksum2; /* Before and after commit checksums */ |
| 1651 | Blob cksum1b; /* Checksum recorded in the manifest */ |
| 1652 | int szD; /* Size of the delta manifest */ |
| @@ -1900,11 +1910,11 @@ | |
| 1910 | /* Step 2: Insert records for all modified files into the blob |
| 1911 | ** table. If there were arguments passed to this command, only |
| 1912 | ** the identified files are inserted (if they have been modified). |
| 1913 | */ |
| 1914 | db_prepare(&q, |
| 1915 | "SELECT id, %Q || pathname, mrid, %s, %s, %s FROM vfile " |
| 1916 | "WHERE chnged==1 AND NOT deleted AND is_selected(id)", |
| 1917 | g.zLocalRoot, |
| 1918 | glob_expr("pathname", db_get("crnl-glob","")), |
| 1919 | glob_expr("pathname", db_get("binary-glob","")), |
| 1920 | glob_expr("pathname", db_get("encoding-glob","")) |
| @@ -1911,19 +1921,18 @@ | |
| 1921 | ); |
| 1922 | while( db_step(&q)==SQLITE_ROW ){ |
| 1923 | int id, rid; |
| 1924 | const char *zFullname; |
| 1925 | Blob content; |
| 1926 | int crnlOk, binOk, encodingOk; |
| 1927 | |
| 1928 | id = db_column_int(&q, 0); |
| 1929 | zFullname = db_column_text(&q, 1); |
| 1930 | rid = db_column_int(&q, 2); |
| 1931 | crnlOk = db_column_int(&q, 3); |
| 1932 | binOk = db_column_int(&q, 4); |
| 1933 | encodingOk = db_column_int(&q, 5); |
| 1934 | |
| 1935 | blob_zero(&content); |
| 1936 | if( file_wd_islink(zFullname) ){ |
| 1937 | /* Instead of file content, put link destination path */ |
| 1938 | blob_read_link(&content, zFullname); |
| @@ -1933,11 +1942,11 @@ | |
| 1942 | /* Do not emit any warnings when they are disabled. */ |
| 1943 | if( !noWarningFlag ){ |
| 1944 | abortCommit |= commit_warning(&content, crnlOk, binOk, |
| 1945 | encodingOk, zFullname); |
| 1946 | } |
| 1947 | if( contains_merge_marker(&content) ){ |
| 1948 | Blob fname; /* Relative pathname of the file */ |
| 1949 | |
| 1950 | nConflict++; |
| 1951 | file_relative_name(zFullname, &fname, 0); |
| 1952 | fossil_print("possible unresolved merge conflict in %s\n", |
| @@ -2071,11 +2080,10 @@ | |
| 2080 | blob_write_to_file(&muuid, zManifestFile); |
| 2081 | free(zManifestFile); |
| 2082 | blob_reset(&muuid); |
| 2083 | } |
| 2084 | |
| 2085 | /* Update the vfile and vmerge tables */ |
| 2086 | db_multi_exec( |
| 2087 | "DELETE FROM vfile WHERE (vid!=%d OR deleted) AND is_selected(id);" |
| 2088 | "DELETE FROM vmerge;" |
| 2089 | "UPDATE vfile SET vid=%d;" |
| @@ -2082,10 +2090,28 @@ | |
| 2090 | "UPDATE vfile SET rid=mrid, chnged=0, deleted=0, origname=NULL" |
| 2091 | " WHERE is_selected(id);" |
| 2092 | , vid, nvid |
| 2093 | ); |
| 2094 | db_lset_int("checkout", nvid); |
| 2095 | |
| 2096 | /* Update the isexe and islink columns of the vfile table */ |
| 2097 | db_prepare(&q, |
| 2098 | "UPDATE vfile SET isexe=:exec, islink=:link" |
| 2099 | " WHERE vid=:vid AND pathname=:path AND (isexe!=:exec OR islink!=:link)" |
| 2100 | ); |
| 2101 | db_bind_int(&q, ":vid", nvid); |
| 2102 | pManifest = manifest_get(nvid, CFTYPE_MANIFEST, 0); |
| 2103 | manifest_file_rewind(pManifest); |
| 2104 | while( (pFile = manifest_file_next(pManifest, 0)) ){ |
| 2105 | db_bind_int(&q, ":exec", pFile->zPerm && strstr(pFile->zPerm, "x")); |
| 2106 | db_bind_int(&q, ":link", pFile->zPerm && strstr(pFile->zPerm, "l")); |
| 2107 | db_bind_text(&q, ":path", pFile->zName); |
| 2108 | db_step(&q); |
| 2109 | db_reset(&q); |
| 2110 | } |
| 2111 | db_finalize(&q); |
| 2112 | manifest_destroy(pManifest); |
| 2113 | |
| 2114 | if( useCksum ){ |
| 2115 | /* Verify that the repository checksum matches the expected checksum |
| 2116 | ** calculated before the check-in started (and stored as the R record |
| 2117 | ** of the manifest file). |
| 2118 |
M
src/db.c
+52
-23
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -1894,53 +1894,72 @@ | ||
| 1894 | 1894 | ** might be generated. |
| 1895 | 1895 | */ |
| 1896 | 1896 | char *db_get_versioned(const char *zName, char *zNonVersionedSetting){ |
| 1897 | 1897 | char *zVersionedSetting = 0; |
| 1898 | 1898 | int noWarn = 0; |
| 1899 | + int found = 0; | |
| 1899 | 1900 | struct _cacheEntry { |
| 1900 | 1901 | struct _cacheEntry *next; |
| 1901 | 1902 | const char *zName, *zValue; |
| 1902 | 1903 | } *cacheEntry = 0; |
| 1903 | 1904 | static struct _cacheEntry *cache = 0; |
| 1904 | 1905 | |
| 1905 | - if( !g.localOpen) return zNonVersionedSetting; | |
| 1906 | + if( !g.localOpen && g.zOpenRevision==0 ) return zNonVersionedSetting; | |
| 1906 | 1907 | /* Look up name in cache */ |
| 1907 | 1908 | cacheEntry = cache; |
| 1908 | 1909 | while( cacheEntry!=0 ){ |
| 1909 | 1910 | if( fossil_strcmp(cacheEntry->zName, zName)==0 ){ |
| 1910 | 1911 | zVersionedSetting = fossil_strdup(cacheEntry->zValue); |
| 1911 | 1912 | break; |
| 1912 | 1913 | } |
| 1913 | 1914 | cacheEntry = cacheEntry->next; |
| 1914 | 1915 | } |
| 1915 | - /* Attempt to read value from file in checkout if there wasn't a cache hit | |
| 1916 | - ** and a checkout is open. */ | |
| 1916 | + /* Attempt to read value from file in checkout if there wasn't a cache hit. */ | |
| 1917 | 1917 | if( cacheEntry==0 ){ |
| 1918 | 1918 | Blob versionedPathname; |
| 1919 | - char *zVersionedPathname; | |
| 1919 | + Blob setting; | |
| 1920 | 1920 | blob_zero(&versionedPathname); |
| 1921 | + blob_zero(&setting); | |
| 1921 | 1922 | blob_appendf(&versionedPathname, "%s.fossil-settings/%s", |
| 1922 | 1923 | g.zLocalRoot, zName); |
| 1923 | - zVersionedPathname = blob_str(&versionedPathname); | |
| 1924 | - if( file_size(zVersionedPathname)>=0 ){ | |
| 1924 | + if( !g.localOpen ){ | |
| 1925 | + /* Repository is in the process of being opened, but files have not been | |
| 1926 | + * written to disk. Load from the database. */ | |
| 1927 | + Blob noWarnFile; | |
| 1928 | + if( historical_version_of_file(g.zOpenRevision, | |
| 1929 | + blob_str(&versionedPathname), | |
| 1930 | + &setting, 0, 0, 0, 2)!=2 ){ | |
| 1931 | + found = 1; | |
| 1932 | + } | |
| 1933 | + /* See if there's a no-warn flag */ | |
| 1934 | + blob_append(&versionedPathname, ".no-warn", -1); | |
| 1935 | + blob_zero(&noWarnFile); | |
| 1936 | + if( historical_version_of_file(g.zOpenRevision, | |
| 1937 | + blob_str(&versionedPathname), | |
| 1938 | + &noWarnFile, 0, 0, 0, 2)!=2 ){ | |
| 1939 | + noWarn = 1; | |
| 1940 | + } | |
| 1941 | + blob_reset(&noWarnFile); | |
| 1942 | + }else if( file_size(blob_str(&versionedPathname))>=0 ){ | |
| 1925 | 1943 | /* File exists, and contains the value for this setting. Load from |
| 1926 | 1944 | ** the file. */ |
| 1927 | - Blob setting; | |
| 1928 | - blob_zero(&setting); | |
| 1929 | - if( blob_read_from_file(&setting, zVersionedPathname) >= 0 ){ | |
| 1930 | - blob_trim(&setting); /* Avoid non-obvious problems with line endings | |
| 1931 | - ** on boolean properties */ | |
| 1932 | - zVersionedSetting = fossil_strdup(blob_str(&setting)); | |
| 1933 | - } | |
| 1934 | - blob_reset(&setting); | |
| 1945 | + if( blob_read_from_file(&setting, blob_str(&versionedPathname))>=0 ){ | |
| 1946 | + found = 1; | |
| 1947 | + } | |
| 1935 | 1948 | /* See if there's a no-warn flag */ |
| 1936 | 1949 | blob_append(&versionedPathname, ".no-warn", -1); |
| 1937 | 1950 | if( file_size(blob_str(&versionedPathname))>=0 ){ |
| 1938 | 1951 | noWarn = 1; |
| 1939 | 1952 | } |
| 1940 | 1953 | } |
| 1941 | 1954 | blob_reset(&versionedPathname); |
| 1955 | + if( found ){ | |
| 1956 | + blob_trim(&setting); /* Avoid non-obvious problems with line endings | |
| 1957 | + ** on boolean properties */ | |
| 1958 | + zVersionedSetting = fossil_strdup(blob_str(&setting)); | |
| 1959 | + } | |
| 1960 | + blob_reset(&setting); | |
| 1942 | 1961 | /* Store result in cache, which can be the value or 0 if not found */ |
| 1943 | 1962 | cacheEntry = (struct _cacheEntry*)fossil_malloc(sizeof(struct _cacheEntry)); |
| 1944 | 1963 | cacheEntry->next = cache; |
| 1945 | 1964 | cacheEntry->zName = zName; |
| 1946 | 1965 | cacheEntry->zValue = fossil_strdup(zVersionedSetting); |
| @@ -2198,12 +2217,10 @@ | ||
| 2198 | 2217 | void cmd_open(void){ |
| 2199 | 2218 | int emptyFlag; |
| 2200 | 2219 | int keepFlag; |
| 2201 | 2220 | int forceMissingFlag; |
| 2202 | 2221 | int allowNested; |
| 2203 | - char **oldArgv; | |
| 2204 | - int oldArgc; | |
| 2205 | 2222 | static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0, 0 }; |
| 2206 | 2223 | |
| 2207 | 2224 | url_proxy_options(); |
| 2208 | 2225 | emptyFlag = find_option("empty",0,0)!=0; |
| 2209 | 2226 | keepFlag = find_option("keep",0,0)!=0; |
| @@ -2218,10 +2235,26 @@ | ||
| 2218 | 2235 | } |
| 2219 | 2236 | if( !allowNested && db_open_local(0) ){ |
| 2220 | 2237 | fossil_fatal("already within an open tree rooted at %s", g.zLocalRoot); |
| 2221 | 2238 | } |
| 2222 | 2239 | db_open_repository(g.argv[2]); |
| 2240 | + | |
| 2241 | + /* Figure out which revision to open. */ | |
| 2242 | + if( !emptyFlag ){ | |
| 2243 | + if( g.argc==4 ){ | |
| 2244 | + g.zOpenRevision = g.argv[3]; | |
| 2245 | + }else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){ | |
| 2246 | + g.zOpenRevision = db_get("main-branch", "trunk"); | |
| 2247 | + } | |
| 2248 | + } | |
| 2249 | + | |
| 2250 | + if( g.zOpenRevision ){ | |
| 2251 | + /* Since the repository is open and we know the revision now, | |
| 2252 | + ** refresh the allow-symlinks flag. */ | |
| 2253 | + g.allowSymlinks = db_get_boolean("allow-symlinks", 0); | |
| 2254 | + } | |
| 2255 | + | |
| 2223 | 2256 | #if defined(_WIN32) || defined(__CYGWIN__) |
| 2224 | 2257 | # define LOCALDB_NAME "./_FOSSIL_" |
| 2225 | 2258 | #else |
| 2226 | 2259 | # define LOCALDB_NAME "./.fslckout" |
| 2227 | 2260 | #endif |
| @@ -2233,22 +2266,18 @@ | ||
| 2233 | 2266 | db_delete_on_failure(LOCALDB_NAME); |
| 2234 | 2267 | db_open_local(0); |
| 2235 | 2268 | db_lset("repository", g.argv[2]); |
| 2236 | 2269 | db_record_repository_filename(g.argv[2]); |
| 2237 | 2270 | db_lset_int("checkout", 0); |
| 2238 | - oldArgv = g.argv; | |
| 2239 | - oldArgc = g.argc; | |
| 2240 | 2271 | azNewArgv[0] = g.argv[0]; |
| 2241 | 2272 | g.argv = azNewArgv; |
| 2242 | 2273 | if( !emptyFlag ){ |
| 2243 | 2274 | g.argc = 3; |
| 2244 | - if( oldArgc==4 ){ | |
| 2245 | - azNewArgv[g.argc-1] = oldArgv[3]; | |
| 2246 | - }else if( !db_exists("SELECT 1 FROM event WHERE type='ci'") ){ | |
| 2247 | - azNewArgv[g.argc-1] = "--latest"; | |
| 2275 | + if( g.zOpenRevision ){ | |
| 2276 | + azNewArgv[g.argc-1] = g.zOpenRevision; | |
| 2248 | 2277 | }else{ |
| 2249 | - azNewArgv[g.argc-1] = db_get("main-branch", "trunk"); | |
| 2278 | + azNewArgv[g.argc-1] = "--latest"; | |
| 2250 | 2279 | } |
| 2251 | 2280 | if( keepFlag ){ |
| 2252 | 2281 | azNewArgv[g.argc++] = "--keep"; |
| 2253 | 2282 | } |
| 2254 | 2283 | if( forceMissingFlag ){ |
| 2255 | 2284 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -1894,53 +1894,72 @@ | |
| 1894 | ** might be generated. |
| 1895 | */ |
| 1896 | char *db_get_versioned(const char *zName, char *zNonVersionedSetting){ |
| 1897 | char *zVersionedSetting = 0; |
| 1898 | int noWarn = 0; |
| 1899 | struct _cacheEntry { |
| 1900 | struct _cacheEntry *next; |
| 1901 | const char *zName, *zValue; |
| 1902 | } *cacheEntry = 0; |
| 1903 | static struct _cacheEntry *cache = 0; |
| 1904 | |
| 1905 | if( !g.localOpen) return zNonVersionedSetting; |
| 1906 | /* Look up name in cache */ |
| 1907 | cacheEntry = cache; |
| 1908 | while( cacheEntry!=0 ){ |
| 1909 | if( fossil_strcmp(cacheEntry->zName, zName)==0 ){ |
| 1910 | zVersionedSetting = fossil_strdup(cacheEntry->zValue); |
| 1911 | break; |
| 1912 | } |
| 1913 | cacheEntry = cacheEntry->next; |
| 1914 | } |
| 1915 | /* Attempt to read value from file in checkout if there wasn't a cache hit |
| 1916 | ** and a checkout is open. */ |
| 1917 | if( cacheEntry==0 ){ |
| 1918 | Blob versionedPathname; |
| 1919 | char *zVersionedPathname; |
| 1920 | blob_zero(&versionedPathname); |
| 1921 | blob_appendf(&versionedPathname, "%s.fossil-settings/%s", |
| 1922 | g.zLocalRoot, zName); |
| 1923 | zVersionedPathname = blob_str(&versionedPathname); |
| 1924 | if( file_size(zVersionedPathname)>=0 ){ |
| 1925 | /* File exists, and contains the value for this setting. Load from |
| 1926 | ** the file. */ |
| 1927 | Blob setting; |
| 1928 | blob_zero(&setting); |
| 1929 | if( blob_read_from_file(&setting, zVersionedPathname) >= 0 ){ |
| 1930 | blob_trim(&setting); /* Avoid non-obvious problems with line endings |
| 1931 | ** on boolean properties */ |
| 1932 | zVersionedSetting = fossil_strdup(blob_str(&setting)); |
| 1933 | } |
| 1934 | blob_reset(&setting); |
| 1935 | /* See if there's a no-warn flag */ |
| 1936 | blob_append(&versionedPathname, ".no-warn", -1); |
| 1937 | if( file_size(blob_str(&versionedPathname))>=0 ){ |
| 1938 | noWarn = 1; |
| 1939 | } |
| 1940 | } |
| 1941 | blob_reset(&versionedPathname); |
| 1942 | /* Store result in cache, which can be the value or 0 if not found */ |
| 1943 | cacheEntry = (struct _cacheEntry*)fossil_malloc(sizeof(struct _cacheEntry)); |
| 1944 | cacheEntry->next = cache; |
| 1945 | cacheEntry->zName = zName; |
| 1946 | cacheEntry->zValue = fossil_strdup(zVersionedSetting); |
| @@ -2198,12 +2217,10 @@ | |
| 2198 | void cmd_open(void){ |
| 2199 | int emptyFlag; |
| 2200 | int keepFlag; |
| 2201 | int forceMissingFlag; |
| 2202 | int allowNested; |
| 2203 | char **oldArgv; |
| 2204 | int oldArgc; |
| 2205 | static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0, 0 }; |
| 2206 | |
| 2207 | url_proxy_options(); |
| 2208 | emptyFlag = find_option("empty",0,0)!=0; |
| 2209 | keepFlag = find_option("keep",0,0)!=0; |
| @@ -2218,10 +2235,26 @@ | |
| 2218 | } |
| 2219 | if( !allowNested && db_open_local(0) ){ |
| 2220 | fossil_fatal("already within an open tree rooted at %s", g.zLocalRoot); |
| 2221 | } |
| 2222 | db_open_repository(g.argv[2]); |
| 2223 | #if defined(_WIN32) || defined(__CYGWIN__) |
| 2224 | # define LOCALDB_NAME "./_FOSSIL_" |
| 2225 | #else |
| 2226 | # define LOCALDB_NAME "./.fslckout" |
| 2227 | #endif |
| @@ -2233,22 +2266,18 @@ | |
| 2233 | db_delete_on_failure(LOCALDB_NAME); |
| 2234 | db_open_local(0); |
| 2235 | db_lset("repository", g.argv[2]); |
| 2236 | db_record_repository_filename(g.argv[2]); |
| 2237 | db_lset_int("checkout", 0); |
| 2238 | oldArgv = g.argv; |
| 2239 | oldArgc = g.argc; |
| 2240 | azNewArgv[0] = g.argv[0]; |
| 2241 | g.argv = azNewArgv; |
| 2242 | if( !emptyFlag ){ |
| 2243 | g.argc = 3; |
| 2244 | if( oldArgc==4 ){ |
| 2245 | azNewArgv[g.argc-1] = oldArgv[3]; |
| 2246 | }else if( !db_exists("SELECT 1 FROM event WHERE type='ci'") ){ |
| 2247 | azNewArgv[g.argc-1] = "--latest"; |
| 2248 | }else{ |
| 2249 | azNewArgv[g.argc-1] = db_get("main-branch", "trunk"); |
| 2250 | } |
| 2251 | if( keepFlag ){ |
| 2252 | azNewArgv[g.argc++] = "--keep"; |
| 2253 | } |
| 2254 | if( forceMissingFlag ){ |
| 2255 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -1894,53 +1894,72 @@ | |
| 1894 | ** might be generated. |
| 1895 | */ |
| 1896 | char *db_get_versioned(const char *zName, char *zNonVersionedSetting){ |
| 1897 | char *zVersionedSetting = 0; |
| 1898 | int noWarn = 0; |
| 1899 | int found = 0; |
| 1900 | struct _cacheEntry { |
| 1901 | struct _cacheEntry *next; |
| 1902 | const char *zName, *zValue; |
| 1903 | } *cacheEntry = 0; |
| 1904 | static struct _cacheEntry *cache = 0; |
| 1905 | |
| 1906 | if( !g.localOpen && g.zOpenRevision==0 ) return zNonVersionedSetting; |
| 1907 | /* Look up name in cache */ |
| 1908 | cacheEntry = cache; |
| 1909 | while( cacheEntry!=0 ){ |
| 1910 | if( fossil_strcmp(cacheEntry->zName, zName)==0 ){ |
| 1911 | zVersionedSetting = fossil_strdup(cacheEntry->zValue); |
| 1912 | break; |
| 1913 | } |
| 1914 | cacheEntry = cacheEntry->next; |
| 1915 | } |
| 1916 | /* Attempt to read value from file in checkout if there wasn't a cache hit. */ |
| 1917 | if( cacheEntry==0 ){ |
| 1918 | Blob versionedPathname; |
| 1919 | Blob setting; |
| 1920 | blob_zero(&versionedPathname); |
| 1921 | blob_zero(&setting); |
| 1922 | blob_appendf(&versionedPathname, "%s.fossil-settings/%s", |
| 1923 | g.zLocalRoot, zName); |
| 1924 | if( !g.localOpen ){ |
| 1925 | /* Repository is in the process of being opened, but files have not been |
| 1926 | * written to disk. Load from the database. */ |
| 1927 | Blob noWarnFile; |
| 1928 | if( historical_version_of_file(g.zOpenRevision, |
| 1929 | blob_str(&versionedPathname), |
| 1930 | &setting, 0, 0, 0, 2)!=2 ){ |
| 1931 | found = 1; |
| 1932 | } |
| 1933 | /* See if there's a no-warn flag */ |
| 1934 | blob_append(&versionedPathname, ".no-warn", -1); |
| 1935 | blob_zero(&noWarnFile); |
| 1936 | if( historical_version_of_file(g.zOpenRevision, |
| 1937 | blob_str(&versionedPathname), |
| 1938 | &noWarnFile, 0, 0, 0, 2)!=2 ){ |
| 1939 | noWarn = 1; |
| 1940 | } |
| 1941 | blob_reset(&noWarnFile); |
| 1942 | }else if( file_size(blob_str(&versionedPathname))>=0 ){ |
| 1943 | /* File exists, and contains the value for this setting. Load from |
| 1944 | ** the file. */ |
| 1945 | if( blob_read_from_file(&setting, blob_str(&versionedPathname))>=0 ){ |
| 1946 | found = 1; |
| 1947 | } |
| 1948 | /* See if there's a no-warn flag */ |
| 1949 | blob_append(&versionedPathname, ".no-warn", -1); |
| 1950 | if( file_size(blob_str(&versionedPathname))>=0 ){ |
| 1951 | noWarn = 1; |
| 1952 | } |
| 1953 | } |
| 1954 | blob_reset(&versionedPathname); |
| 1955 | if( found ){ |
| 1956 | blob_trim(&setting); /* Avoid non-obvious problems with line endings |
| 1957 | ** on boolean properties */ |
| 1958 | zVersionedSetting = fossil_strdup(blob_str(&setting)); |
| 1959 | } |
| 1960 | blob_reset(&setting); |
| 1961 | /* Store result in cache, which can be the value or 0 if not found */ |
| 1962 | cacheEntry = (struct _cacheEntry*)fossil_malloc(sizeof(struct _cacheEntry)); |
| 1963 | cacheEntry->next = cache; |
| 1964 | cacheEntry->zName = zName; |
| 1965 | cacheEntry->zValue = fossil_strdup(zVersionedSetting); |
| @@ -2198,12 +2217,10 @@ | |
| 2217 | void cmd_open(void){ |
| 2218 | int emptyFlag; |
| 2219 | int keepFlag; |
| 2220 | int forceMissingFlag; |
| 2221 | int allowNested; |
| 2222 | static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0, 0 }; |
| 2223 | |
| 2224 | url_proxy_options(); |
| 2225 | emptyFlag = find_option("empty",0,0)!=0; |
| 2226 | keepFlag = find_option("keep",0,0)!=0; |
| @@ -2218,10 +2235,26 @@ | |
| 2235 | } |
| 2236 | if( !allowNested && db_open_local(0) ){ |
| 2237 | fossil_fatal("already within an open tree rooted at %s", g.zLocalRoot); |
| 2238 | } |
| 2239 | db_open_repository(g.argv[2]); |
| 2240 | |
| 2241 | /* Figure out which revision to open. */ |
| 2242 | if( !emptyFlag ){ |
| 2243 | if( g.argc==4 ){ |
| 2244 | g.zOpenRevision = g.argv[3]; |
| 2245 | }else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){ |
| 2246 | g.zOpenRevision = db_get("main-branch", "trunk"); |
| 2247 | } |
| 2248 | } |
| 2249 | |
| 2250 | if( g.zOpenRevision ){ |
| 2251 | /* Since the repository is open and we know the revision now, |
| 2252 | ** refresh the allow-symlinks flag. */ |
| 2253 | g.allowSymlinks = db_get_boolean("allow-symlinks", 0); |
| 2254 | } |
| 2255 | |
| 2256 | #if defined(_WIN32) || defined(__CYGWIN__) |
| 2257 | # define LOCALDB_NAME "./_FOSSIL_" |
| 2258 | #else |
| 2259 | # define LOCALDB_NAME "./.fslckout" |
| 2260 | #endif |
| @@ -2233,22 +2266,18 @@ | |
| 2266 | db_delete_on_failure(LOCALDB_NAME); |
| 2267 | db_open_local(0); |
| 2268 | db_lset("repository", g.argv[2]); |
| 2269 | db_record_repository_filename(g.argv[2]); |
| 2270 | db_lset_int("checkout", 0); |
| 2271 | azNewArgv[0] = g.argv[0]; |
| 2272 | g.argv = azNewArgv; |
| 2273 | if( !emptyFlag ){ |
| 2274 | g.argc = 3; |
| 2275 | if( g.zOpenRevision ){ |
| 2276 | azNewArgv[g.argc-1] = g.zOpenRevision; |
| 2277 | }else{ |
| 2278 | azNewArgv[g.argc-1] = "--latest"; |
| 2279 | } |
| 2280 | if( keepFlag ){ |
| 2281 | azNewArgv[g.argc++] = "--keep"; |
| 2282 | } |
| 2283 | if( forceMissingFlag ){ |
| 2284 |
+5
-3
| --- src/descendants.c | ||
| +++ src/descendants.c | ||
| @@ -369,18 +369,17 @@ | ||
| 369 | 369 | Blob sql; |
| 370 | 370 | int showAll = find_option("all", "a", 0)!=0; |
| 371 | 371 | int showClosed = find_option("closed", "c", 0)!=0; |
| 372 | 372 | int recomputeFlag = find_option("recompute",0,0)!=0; |
| 373 | 373 | int showForks = g.argv[1][0]!='l'; |
| 374 | - int byBranch = (find_option("bybranch",0,0)!=0) || showForks; | |
| 375 | 374 | int multipleFlag = (find_option("multiple","m",0))!=0 || showForks; |
| 375 | + int byBranch = (find_option("bybranch",0,0)!=0) || multipleFlag; | |
| 376 | 376 | const char *zWidth = find_option("width","W",1); |
| 377 | 377 | char *zLastBr = 0; |
| 378 | 378 | int n, width; |
| 379 | 379 | char zLineNo[10]; |
| 380 | 380 | |
| 381 | - if( multipleFlag ) byBranch = 1; | |
| 382 | 381 | if( zWidth ){ |
| 383 | 382 | width = atoi(zWidth); |
| 384 | 383 | if( (width!=0) && (width<=39) ){ |
| 385 | 384 | fossil_fatal("-W|--width value must be >39 or 0"); |
| 386 | 385 | } |
| @@ -447,10 +446,14 @@ | ||
| 447 | 446 | const char *zCom = db_column_text(&q, 3); |
| 448 | 447 | const char *zBr = db_column_text(&q, 7); |
| 449 | 448 | char *z; |
| 450 | 449 | |
| 451 | 450 | if( byBranch && fossil_strcmp(zBr, zLastBr)!=0 ){ |
| 451 | + if( showForks ){ | |
| 452 | + fossil_print("WARNING: multiple open leaves on the following branches:\n"); | |
| 453 | + showForks = 0; | |
| 454 | + } | |
| 452 | 455 | fossil_print("*** %s ***\n", zBr); |
| 453 | 456 | fossil_free(zLastBr); |
| 454 | 457 | zLastBr = fossil_strdup(zBr); |
| 455 | 458 | if( multipleFlag ) n = 0; |
| 456 | 459 | } |
| @@ -461,11 +464,10 @@ | ||
| 461 | 464 | comment_print(z, zCom, 7, width, g.comFmtFlags); |
| 462 | 465 | fossil_free(z); |
| 463 | 466 | } |
| 464 | 467 | fossil_free(zLastBr); |
| 465 | 468 | db_finalize(&q); |
| 466 | - if( showForks && !zLastBr ) fossil_print("*** OK, no multiple leaves on the same branch found ***\n"); | |
| 467 | 469 | } |
| 468 | 470 | |
| 469 | 471 | /* |
| 470 | 472 | ** WEBPAGE: leaves |
| 471 | 473 | ** |
| 472 | 474 |
| --- src/descendants.c | |
| +++ src/descendants.c | |
| @@ -369,18 +369,17 @@ | |
| 369 | Blob sql; |
| 370 | int showAll = find_option("all", "a", 0)!=0; |
| 371 | int showClosed = find_option("closed", "c", 0)!=0; |
| 372 | int recomputeFlag = find_option("recompute",0,0)!=0; |
| 373 | int showForks = g.argv[1][0]!='l'; |
| 374 | int byBranch = (find_option("bybranch",0,0)!=0) || showForks; |
| 375 | int multipleFlag = (find_option("multiple","m",0))!=0 || showForks; |
| 376 | const char *zWidth = find_option("width","W",1); |
| 377 | char *zLastBr = 0; |
| 378 | int n, width; |
| 379 | char zLineNo[10]; |
| 380 | |
| 381 | if( multipleFlag ) byBranch = 1; |
| 382 | if( zWidth ){ |
| 383 | width = atoi(zWidth); |
| 384 | if( (width!=0) && (width<=39) ){ |
| 385 | fossil_fatal("-W|--width value must be >39 or 0"); |
| 386 | } |
| @@ -447,10 +446,14 @@ | |
| 447 | const char *zCom = db_column_text(&q, 3); |
| 448 | const char *zBr = db_column_text(&q, 7); |
| 449 | char *z; |
| 450 | |
| 451 | if( byBranch && fossil_strcmp(zBr, zLastBr)!=0 ){ |
| 452 | fossil_print("*** %s ***\n", zBr); |
| 453 | fossil_free(zLastBr); |
| 454 | zLastBr = fossil_strdup(zBr); |
| 455 | if( multipleFlag ) n = 0; |
| 456 | } |
| @@ -461,11 +464,10 @@ | |
| 461 | comment_print(z, zCom, 7, width, g.comFmtFlags); |
| 462 | fossil_free(z); |
| 463 | } |
| 464 | fossil_free(zLastBr); |
| 465 | db_finalize(&q); |
| 466 | if( showForks && !zLastBr ) fossil_print("*** OK, no multiple leaves on the same branch found ***\n"); |
| 467 | } |
| 468 | |
| 469 | /* |
| 470 | ** WEBPAGE: leaves |
| 471 | ** |
| 472 |
| --- src/descendants.c | |
| +++ src/descendants.c | |
| @@ -369,18 +369,17 @@ | |
| 369 | Blob sql; |
| 370 | int showAll = find_option("all", "a", 0)!=0; |
| 371 | int showClosed = find_option("closed", "c", 0)!=0; |
| 372 | int recomputeFlag = find_option("recompute",0,0)!=0; |
| 373 | int showForks = g.argv[1][0]!='l'; |
| 374 | int multipleFlag = (find_option("multiple","m",0))!=0 || showForks; |
| 375 | int byBranch = (find_option("bybranch",0,0)!=0) || multipleFlag; |
| 376 | const char *zWidth = find_option("width","W",1); |
| 377 | char *zLastBr = 0; |
| 378 | int n, width; |
| 379 | char zLineNo[10]; |
| 380 | |
| 381 | if( zWidth ){ |
| 382 | width = atoi(zWidth); |
| 383 | if( (width!=0) && (width<=39) ){ |
| 384 | fossil_fatal("-W|--width value must be >39 or 0"); |
| 385 | } |
| @@ -447,10 +446,14 @@ | |
| 446 | const char *zCom = db_column_text(&q, 3); |
| 447 | const char *zBr = db_column_text(&q, 7); |
| 448 | char *z; |
| 449 | |
| 450 | if( byBranch && fossil_strcmp(zBr, zLastBr)!=0 ){ |
| 451 | if( showForks ){ |
| 452 | fossil_print("WARNING: multiple open leaves on the following branches:\n"); |
| 453 | showForks = 0; |
| 454 | } |
| 455 | fossil_print("*** %s ***\n", zBr); |
| 456 | fossil_free(zLastBr); |
| 457 | zLastBr = fossil_strdup(zBr); |
| 458 | if( multipleFlag ) n = 0; |
| 459 | } |
| @@ -461,11 +464,10 @@ | |
| 464 | comment_print(z, zCom, 7, width, g.comFmtFlags); |
| 465 | fossil_free(z); |
| 466 | } |
| 467 | fossil_free(zLastBr); |
| 468 | db_finalize(&q); |
| 469 | } |
| 470 | |
| 471 | /* |
| 472 | ** WEBPAGE: leaves |
| 473 | ** |
| 474 |
+5
-3
| --- src/descendants.c | ||
| +++ src/descendants.c | ||
| @@ -369,18 +369,17 @@ | ||
| 369 | 369 | Blob sql; |
| 370 | 370 | int showAll = find_option("all", "a", 0)!=0; |
| 371 | 371 | int showClosed = find_option("closed", "c", 0)!=0; |
| 372 | 372 | int recomputeFlag = find_option("recompute",0,0)!=0; |
| 373 | 373 | int showForks = g.argv[1][0]!='l'; |
| 374 | - int byBranch = (find_option("bybranch",0,0)!=0) || showForks; | |
| 375 | 374 | int multipleFlag = (find_option("multiple","m",0))!=0 || showForks; |
| 375 | + int byBranch = (find_option("bybranch",0,0)!=0) || multipleFlag; | |
| 376 | 376 | const char *zWidth = find_option("width","W",1); |
| 377 | 377 | char *zLastBr = 0; |
| 378 | 378 | int n, width; |
| 379 | 379 | char zLineNo[10]; |
| 380 | 380 | |
| 381 | - if( multipleFlag ) byBranch = 1; | |
| 382 | 381 | if( zWidth ){ |
| 383 | 382 | width = atoi(zWidth); |
| 384 | 383 | if( (width!=0) && (width<=39) ){ |
| 385 | 384 | fossil_fatal("-W|--width value must be >39 or 0"); |
| 386 | 385 | } |
| @@ -447,10 +446,14 @@ | ||
| 447 | 446 | const char *zCom = db_column_text(&q, 3); |
| 448 | 447 | const char *zBr = db_column_text(&q, 7); |
| 449 | 448 | char *z; |
| 450 | 449 | |
| 451 | 450 | if( byBranch && fossil_strcmp(zBr, zLastBr)!=0 ){ |
| 451 | + if( showForks ){ | |
| 452 | + fossil_print("WARNING: multiple open leaves on the following branches:\n"); | |
| 453 | + showForks = 0; | |
| 454 | + } | |
| 452 | 455 | fossil_print("*** %s ***\n", zBr); |
| 453 | 456 | fossil_free(zLastBr); |
| 454 | 457 | zLastBr = fossil_strdup(zBr); |
| 455 | 458 | if( multipleFlag ) n = 0; |
| 456 | 459 | } |
| @@ -461,11 +464,10 @@ | ||
| 461 | 464 | comment_print(z, zCom, 7, width, g.comFmtFlags); |
| 462 | 465 | fossil_free(z); |
| 463 | 466 | } |
| 464 | 467 | fossil_free(zLastBr); |
| 465 | 468 | db_finalize(&q); |
| 466 | - if( showForks && !zLastBr ) fossil_print("*** OK, no multiple leaves on the same branch found ***\n"); | |
| 467 | 469 | } |
| 468 | 470 | |
| 469 | 471 | /* |
| 470 | 472 | ** WEBPAGE: leaves |
| 471 | 473 | ** |
| 472 | 474 |
| --- src/descendants.c | |
| +++ src/descendants.c | |
| @@ -369,18 +369,17 @@ | |
| 369 | Blob sql; |
| 370 | int showAll = find_option("all", "a", 0)!=0; |
| 371 | int showClosed = find_option("closed", "c", 0)!=0; |
| 372 | int recomputeFlag = find_option("recompute",0,0)!=0; |
| 373 | int showForks = g.argv[1][0]!='l'; |
| 374 | int byBranch = (find_option("bybranch",0,0)!=0) || showForks; |
| 375 | int multipleFlag = (find_option("multiple","m",0))!=0 || showForks; |
| 376 | const char *zWidth = find_option("width","W",1); |
| 377 | char *zLastBr = 0; |
| 378 | int n, width; |
| 379 | char zLineNo[10]; |
| 380 | |
| 381 | if( multipleFlag ) byBranch = 1; |
| 382 | if( zWidth ){ |
| 383 | width = atoi(zWidth); |
| 384 | if( (width!=0) && (width<=39) ){ |
| 385 | fossil_fatal("-W|--width value must be >39 or 0"); |
| 386 | } |
| @@ -447,10 +446,14 @@ | |
| 447 | const char *zCom = db_column_text(&q, 3); |
| 448 | const char *zBr = db_column_text(&q, 7); |
| 449 | char *z; |
| 450 | |
| 451 | if( byBranch && fossil_strcmp(zBr, zLastBr)!=0 ){ |
| 452 | fossil_print("*** %s ***\n", zBr); |
| 453 | fossil_free(zLastBr); |
| 454 | zLastBr = fossil_strdup(zBr); |
| 455 | if( multipleFlag ) n = 0; |
| 456 | } |
| @@ -461,11 +464,10 @@ | |
| 461 | comment_print(z, zCom, 7, width, g.comFmtFlags); |
| 462 | fossil_free(z); |
| 463 | } |
| 464 | fossil_free(zLastBr); |
| 465 | db_finalize(&q); |
| 466 | if( showForks && !zLastBr ) fossil_print("*** OK, no multiple leaves on the same branch found ***\n"); |
| 467 | } |
| 468 | |
| 469 | /* |
| 470 | ** WEBPAGE: leaves |
| 471 | ** |
| 472 |
| --- src/descendants.c | |
| +++ src/descendants.c | |
| @@ -369,18 +369,17 @@ | |
| 369 | Blob sql; |
| 370 | int showAll = find_option("all", "a", 0)!=0; |
| 371 | int showClosed = find_option("closed", "c", 0)!=0; |
| 372 | int recomputeFlag = find_option("recompute",0,0)!=0; |
| 373 | int showForks = g.argv[1][0]!='l'; |
| 374 | int multipleFlag = (find_option("multiple","m",0))!=0 || showForks; |
| 375 | int byBranch = (find_option("bybranch",0,0)!=0) || multipleFlag; |
| 376 | const char *zWidth = find_option("width","W",1); |
| 377 | char *zLastBr = 0; |
| 378 | int n, width; |
| 379 | char zLineNo[10]; |
| 380 | |
| 381 | if( zWidth ){ |
| 382 | width = atoi(zWidth); |
| 383 | if( (width!=0) && (width<=39) ){ |
| 384 | fossil_fatal("-W|--width value must be >39 or 0"); |
| 385 | } |
| @@ -447,10 +446,14 @@ | |
| 446 | const char *zCom = db_column_text(&q, 3); |
| 447 | const char *zBr = db_column_text(&q, 7); |
| 448 | char *z; |
| 449 | |
| 450 | if( byBranch && fossil_strcmp(zBr, zLastBr)!=0 ){ |
| 451 | if( showForks ){ |
| 452 | fossil_print("WARNING: multiple open leaves on the following branches:\n"); |
| 453 | showForks = 0; |
| 454 | } |
| 455 | fossil_print("*** %s ***\n", zBr); |
| 456 | fossil_free(zLastBr); |
| 457 | zLastBr = fossil_strdup(zBr); |
| 458 | if( multipleFlag ) n = 0; |
| 459 | } |
| @@ -461,11 +464,10 @@ | |
| 464 | comment_print(z, zCom, 7, width, g.comFmtFlags); |
| 465 | fossil_free(z); |
| 466 | } |
| 467 | fossil_free(zLastBr); |
| 468 | db_finalize(&q); |
| 469 | } |
| 470 | |
| 471 | /* |
| 472 | ** WEBPAGE: leaves |
| 473 | ** |
| 474 |
+12
-5
| --- src/file.c | ||
| +++ src/file.c | ||
| @@ -386,11 +386,11 @@ | ||
| 386 | 386 | FILE *in, *out; |
| 387 | 387 | int got; |
| 388 | 388 | char zBuf[8192]; |
| 389 | 389 | in = fossil_fopen(zFrom, "rb"); |
| 390 | 390 | if( in==0 ) fossil_fatal("cannot open \"%s\" for reading", zFrom); |
| 391 | - file_mkfolder(zTo, 0); | |
| 391 | + file_mkfolder(zTo, 0, 0); | |
| 392 | 392 | out = fossil_fopen(zTo, "wb"); |
| 393 | 393 | if( out==0 ) fossil_fatal("cannot open \"%s\" for writing", zTo); |
| 394 | 394 | while( (got=fread(zBuf, 1, sizeof(zBuf), in))>0 ){ |
| 395 | 395 | fwrite(zBuf, 1, got, out); |
| 396 | 396 | } |
| @@ -530,13 +530,16 @@ | ||
| 530 | 530 | } |
| 531 | 531 | |
| 532 | 532 | /* |
| 533 | 533 | ** Create the tree of directories in which zFilename belongs, if that sequence |
| 534 | 534 | ** of directories does not already exist. |
| 535 | +** | |
| 536 | +** On success, return zero. On error, return errorReturn if positive, otherwise | |
| 537 | +** print an error message and abort. | |
| 535 | 538 | */ |
| 536 | -void file_mkfolder(const char *zFilename, int forceFlag){ | |
| 537 | - int i, nName; | |
| 539 | +int file_mkfolder(const char *zFilename, int forceFlag, int errorReturn){ | |
| 540 | + int i, nName, rc = 0; | |
| 538 | 541 | char *zName; |
| 539 | 542 | |
| 540 | 543 | nName = strlen(zFilename); |
| 541 | 544 | zName = mprintf("%s", zFilename); |
| 542 | 545 | nName = file_simplify_name(zName, nName, 0); |
| @@ -550,20 +553,24 @@ | ||
| 550 | 553 | ** C: in this example. |
| 551 | 554 | */ |
| 552 | 555 | if( !(i==2 && zName[1]==':') ){ |
| 553 | 556 | #endif |
| 554 | 557 | if( file_mkdir(zName, forceFlag) && file_isdir(zName)!=1 ){ |
| 555 | - fossil_fatal_recursive("unable to create directory %s", zName); | |
| 556 | - return; | |
| 558 | + if (errorReturn <= 0) { | |
| 559 | + fossil_fatal_recursive("unable to create directory %s", zName); | |
| 560 | + } | |
| 561 | + rc = errorReturn; | |
| 562 | + break; | |
| 557 | 563 | } |
| 558 | 564 | #if defined(_WIN32) || defined(__CYGWIN__) |
| 559 | 565 | } |
| 560 | 566 | #endif |
| 561 | 567 | zName[i] = '/'; |
| 562 | 568 | } |
| 563 | 569 | } |
| 564 | 570 | free(zName); |
| 571 | + return rc; | |
| 565 | 572 | } |
| 566 | 573 | |
| 567 | 574 | /* |
| 568 | 575 | ** Removes the directory named in the argument, if it exists. The directory |
| 569 | 576 | ** must be empty and cannot be the current directory or the root directory. |
| 570 | 577 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -386,11 +386,11 @@ | |
| 386 | FILE *in, *out; |
| 387 | int got; |
| 388 | char zBuf[8192]; |
| 389 | in = fossil_fopen(zFrom, "rb"); |
| 390 | if( in==0 ) fossil_fatal("cannot open \"%s\" for reading", zFrom); |
| 391 | file_mkfolder(zTo, 0); |
| 392 | out = fossil_fopen(zTo, "wb"); |
| 393 | if( out==0 ) fossil_fatal("cannot open \"%s\" for writing", zTo); |
| 394 | while( (got=fread(zBuf, 1, sizeof(zBuf), in))>0 ){ |
| 395 | fwrite(zBuf, 1, got, out); |
| 396 | } |
| @@ -530,13 +530,16 @@ | |
| 530 | } |
| 531 | |
| 532 | /* |
| 533 | ** Create the tree of directories in which zFilename belongs, if that sequence |
| 534 | ** of directories does not already exist. |
| 535 | */ |
| 536 | void file_mkfolder(const char *zFilename, int forceFlag){ |
| 537 | int i, nName; |
| 538 | char *zName; |
| 539 | |
| 540 | nName = strlen(zFilename); |
| 541 | zName = mprintf("%s", zFilename); |
| 542 | nName = file_simplify_name(zName, nName, 0); |
| @@ -550,20 +553,24 @@ | |
| 550 | ** C: in this example. |
| 551 | */ |
| 552 | if( !(i==2 && zName[1]==':') ){ |
| 553 | #endif |
| 554 | if( file_mkdir(zName, forceFlag) && file_isdir(zName)!=1 ){ |
| 555 | fossil_fatal_recursive("unable to create directory %s", zName); |
| 556 | return; |
| 557 | } |
| 558 | #if defined(_WIN32) || defined(__CYGWIN__) |
| 559 | } |
| 560 | #endif |
| 561 | zName[i] = '/'; |
| 562 | } |
| 563 | } |
| 564 | free(zName); |
| 565 | } |
| 566 | |
| 567 | /* |
| 568 | ** Removes the directory named in the argument, if it exists. The directory |
| 569 | ** must be empty and cannot be the current directory or the root directory. |
| 570 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -386,11 +386,11 @@ | |
| 386 | FILE *in, *out; |
| 387 | int got; |
| 388 | char zBuf[8192]; |
| 389 | in = fossil_fopen(zFrom, "rb"); |
| 390 | if( in==0 ) fossil_fatal("cannot open \"%s\" for reading", zFrom); |
| 391 | file_mkfolder(zTo, 0, 0); |
| 392 | out = fossil_fopen(zTo, "wb"); |
| 393 | if( out==0 ) fossil_fatal("cannot open \"%s\" for writing", zTo); |
| 394 | while( (got=fread(zBuf, 1, sizeof(zBuf), in))>0 ){ |
| 395 | fwrite(zBuf, 1, got, out); |
| 396 | } |
| @@ -530,13 +530,16 @@ | |
| 530 | } |
| 531 | |
| 532 | /* |
| 533 | ** Create the tree of directories in which zFilename belongs, if that sequence |
| 534 | ** of directories does not already exist. |
| 535 | ** |
| 536 | ** On success, return zero. On error, return errorReturn if positive, otherwise |
| 537 | ** print an error message and abort. |
| 538 | */ |
| 539 | int file_mkfolder(const char *zFilename, int forceFlag, int errorReturn){ |
| 540 | int i, nName, rc = 0; |
| 541 | char *zName; |
| 542 | |
| 543 | nName = strlen(zFilename); |
| 544 | zName = mprintf("%s", zFilename); |
| 545 | nName = file_simplify_name(zName, nName, 0); |
| @@ -550,20 +553,24 @@ | |
| 553 | ** C: in this example. |
| 554 | */ |
| 555 | if( !(i==2 && zName[1]==':') ){ |
| 556 | #endif |
| 557 | if( file_mkdir(zName, forceFlag) && file_isdir(zName)!=1 ){ |
| 558 | if (errorReturn <= 0) { |
| 559 | fossil_fatal_recursive("unable to create directory %s", zName); |
| 560 | } |
| 561 | rc = errorReturn; |
| 562 | break; |
| 563 | } |
| 564 | #if defined(_WIN32) || defined(__CYGWIN__) |
| 565 | } |
| 566 | #endif |
| 567 | zName[i] = '/'; |
| 568 | } |
| 569 | } |
| 570 | free(zName); |
| 571 | return rc; |
| 572 | } |
| 573 | |
| 574 | /* |
| 575 | ** Removes the directory named in the argument, if it exists. The directory |
| 576 | ** must be empty and cannot be the current directory or the root directory. |
| 577 |
+3
-8
| --- src/finfo.c | ||
| +++ src/finfo.c | ||
| @@ -182,11 +182,11 @@ | ||
| 182 | 182 | if( rid==0 ){ |
| 183 | 183 | fossil_fatal("no history for file: %b", &fname); |
| 184 | 184 | } |
| 185 | 185 | zFilename = blob_str(&fname); |
| 186 | 186 | db_prepare(&q, |
| 187 | - "SELECT b.uuid, ci.uuid, date(event.mtime%s)," | |
| 187 | + "SELECT DISTINCT b.uuid, ci.uuid, date(event.mtime%s)," | |
| 188 | 188 | " coalesce(event.ecomment, event.comment)," |
| 189 | 189 | " coalesce(event.euser, event.user)," |
| 190 | 190 | " (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0" |
| 191 | 191 | " AND tagxref.rid=mlink.mid)" /* Tags */ |
| 192 | 192 | " FROM mlink, blob b, event, blob ci, filename" |
| @@ -403,12 +403,10 @@ | ||
| 403 | 403 | if( fShowId ) blob_appendf(&title, " (%d)", fnid); |
| 404 | 404 | } |
| 405 | 405 | @ <h2>%b(&title)</h2> |
| 406 | 406 | blob_reset(&title); |
| 407 | 407 | pGraph = graph_init(); |
| 408 | - @ <div id="canvas" style="position:relative;width:1px;height:1px;" | |
| 409 | - @ onclick="clickOnGraph(event)"></div> | |
| 410 | 408 | @ <table id="timelineTable" class="timelineTable"> |
| 411 | 409 | while( db_step(&q)==SQLITE_ROW ){ |
| 412 | 410 | const char *zDate = db_column_text(&q, 0); |
| 413 | 411 | const char *zCom = db_column_text(&q, 1); |
| 414 | 412 | const char *zUser = db_column_text(&q, 2); |
| @@ -459,11 +457,11 @@ | ||
| 459 | 457 | } |
| 460 | 458 | memcpy(zTime, &zDate[11], 5); |
| 461 | 459 | zTime[5] = 0; |
| 462 | 460 | @ <tr><td class="timelineTime"> |
| 463 | 461 | @ %z(href("%R/timeline?c=%t",zDate))%s(zTime)</a></td> |
| 464 | - @ <td class="timelineGraph"><div id="m%d(gidx)"></div></td> | |
| 462 | + @ <td class="timelineGraph"><div id="m%d(gidx)" class="tl-nodemark"></div></td> | |
| 465 | 463 | if( zBgClr && zBgClr[0] ){ |
| 466 | 464 | @ <td class="timelineTableCell" style="background-color: %h(zBgClr);"> |
| 467 | 465 | }else{ |
| 468 | 466 | @ <td class="timelineTableCell"> |
| 469 | 467 | } |
| @@ -536,15 +534,12 @@ | ||
| 536 | 534 | graph_finish(pGraph, 1); |
| 537 | 535 | if( pGraph->nErr ){ |
| 538 | 536 | graph_free(pGraph); |
| 539 | 537 | pGraph = 0; |
| 540 | 538 | }else{ |
| 541 | - int w = pGraph->mxRail*pGraph->iRailPitch + 28; | |
| 542 | - @ <tr><td></td><td> | |
| 543 | - @ <div id="grbtm" style="width:%d(w)px;"></div> | |
| 544 | - @ </td><td></td></tr> | |
| 539 | + @ <tr class="timelineBottom"><td></td><td></td><td></td></tr> | |
| 545 | 540 | } |
| 546 | 541 | } |
| 547 | 542 | @ </table> |
| 548 | 543 | timeline_output_graph_javascript(pGraph, 0, 1); |
| 549 | 544 | style_footer(); |
| 550 | 545 | } |
| 551 | 546 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -182,11 +182,11 @@ | |
| 182 | if( rid==0 ){ |
| 183 | fossil_fatal("no history for file: %b", &fname); |
| 184 | } |
| 185 | zFilename = blob_str(&fname); |
| 186 | db_prepare(&q, |
| 187 | "SELECT b.uuid, ci.uuid, date(event.mtime%s)," |
| 188 | " coalesce(event.ecomment, event.comment)," |
| 189 | " coalesce(event.euser, event.user)," |
| 190 | " (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0" |
| 191 | " AND tagxref.rid=mlink.mid)" /* Tags */ |
| 192 | " FROM mlink, blob b, event, blob ci, filename" |
| @@ -403,12 +403,10 @@ | |
| 403 | if( fShowId ) blob_appendf(&title, " (%d)", fnid); |
| 404 | } |
| 405 | @ <h2>%b(&title)</h2> |
| 406 | blob_reset(&title); |
| 407 | pGraph = graph_init(); |
| 408 | @ <div id="canvas" style="position:relative;width:1px;height:1px;" |
| 409 | @ onclick="clickOnGraph(event)"></div> |
| 410 | @ <table id="timelineTable" class="timelineTable"> |
| 411 | while( db_step(&q)==SQLITE_ROW ){ |
| 412 | const char *zDate = db_column_text(&q, 0); |
| 413 | const char *zCom = db_column_text(&q, 1); |
| 414 | const char *zUser = db_column_text(&q, 2); |
| @@ -459,11 +457,11 @@ | |
| 459 | } |
| 460 | memcpy(zTime, &zDate[11], 5); |
| 461 | zTime[5] = 0; |
| 462 | @ <tr><td class="timelineTime"> |
| 463 | @ %z(href("%R/timeline?c=%t",zDate))%s(zTime)</a></td> |
| 464 | @ <td class="timelineGraph"><div id="m%d(gidx)"></div></td> |
| 465 | if( zBgClr && zBgClr[0] ){ |
| 466 | @ <td class="timelineTableCell" style="background-color: %h(zBgClr);"> |
| 467 | }else{ |
| 468 | @ <td class="timelineTableCell"> |
| 469 | } |
| @@ -536,15 +534,12 @@ | |
| 536 | graph_finish(pGraph, 1); |
| 537 | if( pGraph->nErr ){ |
| 538 | graph_free(pGraph); |
| 539 | pGraph = 0; |
| 540 | }else{ |
| 541 | int w = pGraph->mxRail*pGraph->iRailPitch + 28; |
| 542 | @ <tr><td></td><td> |
| 543 | @ <div id="grbtm" style="width:%d(w)px;"></div> |
| 544 | @ </td><td></td></tr> |
| 545 | } |
| 546 | } |
| 547 | @ </table> |
| 548 | timeline_output_graph_javascript(pGraph, 0, 1); |
| 549 | style_footer(); |
| 550 | } |
| 551 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -182,11 +182,11 @@ | |
| 182 | if( rid==0 ){ |
| 183 | fossil_fatal("no history for file: %b", &fname); |
| 184 | } |
| 185 | zFilename = blob_str(&fname); |
| 186 | db_prepare(&q, |
| 187 | "SELECT DISTINCT b.uuid, ci.uuid, date(event.mtime%s)," |
| 188 | " coalesce(event.ecomment, event.comment)," |
| 189 | " coalesce(event.euser, event.user)," |
| 190 | " (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0" |
| 191 | " AND tagxref.rid=mlink.mid)" /* Tags */ |
| 192 | " FROM mlink, blob b, event, blob ci, filename" |
| @@ -403,12 +403,10 @@ | |
| 403 | if( fShowId ) blob_appendf(&title, " (%d)", fnid); |
| 404 | } |
| 405 | @ <h2>%b(&title)</h2> |
| 406 | blob_reset(&title); |
| 407 | pGraph = graph_init(); |
| 408 | @ <table id="timelineTable" class="timelineTable"> |
| 409 | while( db_step(&q)==SQLITE_ROW ){ |
| 410 | const char *zDate = db_column_text(&q, 0); |
| 411 | const char *zCom = db_column_text(&q, 1); |
| 412 | const char *zUser = db_column_text(&q, 2); |
| @@ -459,11 +457,11 @@ | |
| 457 | } |
| 458 | memcpy(zTime, &zDate[11], 5); |
| 459 | zTime[5] = 0; |
| 460 | @ <tr><td class="timelineTime"> |
| 461 | @ %z(href("%R/timeline?c=%t",zDate))%s(zTime)</a></td> |
| 462 | @ <td class="timelineGraph"><div id="m%d(gidx)" class="tl-nodemark"></div></td> |
| 463 | if( zBgClr && zBgClr[0] ){ |
| 464 | @ <td class="timelineTableCell" style="background-color: %h(zBgClr);"> |
| 465 | }else{ |
| 466 | @ <td class="timelineTableCell"> |
| 467 | } |
| @@ -536,15 +534,12 @@ | |
| 534 | graph_finish(pGraph, 1); |
| 535 | if( pGraph->nErr ){ |
| 536 | graph_free(pGraph); |
| 537 | pGraph = 0; |
| 538 | }else{ |
| 539 | @ <tr class="timelineBottom"><td></td><td></td><td></td></tr> |
| 540 | } |
| 541 | } |
| 542 | @ </table> |
| 543 | timeline_output_graph_javascript(pGraph, 0, 1); |
| 544 | style_footer(); |
| 545 | } |
| 546 |
+8
-15
| --- src/graph.c | ||
| +++ src/graph.c | ||
| @@ -47,11 +47,11 @@ | ||
| 47 | 47 | u8 isDup; /* True if this is duplicate of a prior entry */ |
| 48 | 48 | u8 isLeaf; /* True if this is a leaf node */ |
| 49 | 49 | u8 timeWarp; /* Child is earlier in time */ |
| 50 | 50 | u8 bDescender; /* True if riser from bottom of graph to here. */ |
| 51 | 51 | i8 iRail; /* Which rail this check-in appears on. 0-based.*/ |
| 52 | - i8 mergeOut; /* Merge out on rail mergeOut/4. -1 for none */ | |
| 52 | + i8 mergeOut; /* Merge out to this rail. -1 if no merge-out */ | |
| 53 | 53 | u8 mergeIn[GR_MAX_RAIL]; /* Merge in from non-zero rails */ |
| 54 | 54 | int aiRiser[GR_MAX_RAIL]; /* Risers from this node to a higher row. */ |
| 55 | 55 | int mergeUpto; /* Draw the mergeOut rail up to this level */ |
| 56 | 56 | u64 mergeDown; /* Draw merge lines up from bottom of graph */ |
| 57 | 57 | |
| @@ -61,11 +61,10 @@ | ||
| 61 | 61 | /* Context while building a graph |
| 62 | 62 | */ |
| 63 | 63 | struct GraphContext { |
| 64 | 64 | int nErr; /* Number of errors encountered */ |
| 65 | 65 | int mxRail; /* Number of rails required to render the graph */ |
| 66 | - int iRailPitch; /* Pixels between rail centers */ | |
| 67 | 66 | GraphRow *pFirst; /* First row in the list */ |
| 68 | 67 | GraphRow *pLast; /* Last row in the list */ |
| 69 | 68 | int nBranch; /* Number of distinct branches */ |
| 70 | 69 | char **azBranch; /* Names of the branches */ |
| 71 | 70 | int nRow; /* Number of rows */ |
| @@ -294,28 +293,27 @@ | ||
| 294 | 293 | u = pParent->aiRiser[pParent->iRail]; |
| 295 | 294 | if( u>=0 && u<pChild->idx ){ |
| 296 | 295 | /* The thick arrow up to the next primary child of pDesc goes |
| 297 | 296 | ** further up than the thin merge arrow riser, so draw them both |
| 298 | 297 | ** on the same rail. */ |
| 299 | - pParent->mergeOut = pParent->iRail*4; | |
| 300 | - if( pParent->iRail<pChild->iRail ) pParent->mergeOut += 2; | |
| 298 | + pParent->mergeOut = pParent->iRail; | |
| 301 | 299 | pParent->mergeUpto = pChild->idx; |
| 302 | 300 | }else{ |
| 303 | 301 | /* The thin merge arrow riser is taller than the thick primary |
| 304 | 302 | ** child riser, so use separate rails. */ |
| 305 | 303 | int iTarget = pParent->iRail; |
| 306 | 304 | pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1, |
| 307 | - 0, iTarget)*4 + 1; | |
| 305 | + 0, iTarget); | |
| 308 | 306 | pParent->mergeUpto = pChild->idx; |
| 309 | - mask = BIT(pParent->mergeOut/4); | |
| 307 | + mask = BIT(pParent->mergeOut); | |
| 310 | 308 | for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid; |
| 311 | 309 | pLoop=pLoop->pNext){ |
| 312 | 310 | pLoop->railInUse |= mask; |
| 313 | 311 | } |
| 314 | 312 | } |
| 315 | 313 | } |
| 316 | - pChild->mergeIn[pParent->mergeOut/4] = (pParent->mergeOut&3)+1; | |
| 314 | + pChild->mergeIn[pParent->mergeOut] = 1; | |
| 317 | 315 | } |
| 318 | 316 | |
| 319 | 317 | /* |
| 320 | 318 | ** Compute the maximum rail number. |
| 321 | 319 | */ |
| @@ -322,11 +320,11 @@ | ||
| 322 | 320 | static void find_max_rail(GraphContext *p){ |
| 323 | 321 | GraphRow *pRow; |
| 324 | 322 | p->mxRail = 0; |
| 325 | 323 | for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ |
| 326 | 324 | if( pRow->iRail>p->mxRail ) p->mxRail = pRow->iRail; |
| 327 | - if( pRow->mergeOut/4>p->mxRail ) p->mxRail = pRow->mergeOut/4; | |
| 325 | + if( pRow->mergeOut>p->mxRail ) p->mxRail = pRow->mergeOut; | |
| 328 | 326 | while( p->mxRail<GR_MAX_RAIL && pRow->mergeDown>(BIT(p->mxRail+1)-1) ){ |
| 329 | 327 | p->mxRail++; |
| 330 | 328 | } |
| 331 | 329 | } |
| 332 | 330 | } |
| @@ -540,11 +538,11 @@ | ||
| 540 | 538 | if( pDesc==0 ){ |
| 541 | 539 | /* Merge from a node that is off-screen */ |
| 542 | 540 | int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0, 0); |
| 543 | 541 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 544 | 542 | mask = BIT(iMrail); |
| 545 | - pRow->mergeIn[iMrail] = 2; | |
| 543 | + pRow->mergeIn[iMrail] = 1; | |
| 546 | 544 | pRow->mergeDown |= mask; |
| 547 | 545 | for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){ |
| 548 | 546 | pLoop->railInUse |= mask; |
| 549 | 547 | } |
| 550 | 548 | }else{ |
| @@ -569,11 +567,11 @@ | ||
| 569 | 567 | if( !pRow->isDup ) continue; |
| 570 | 568 | pRow->iRail = dupRail; |
| 571 | 569 | pDesc = hashFind(p, pRow->rid); |
| 572 | 570 | assert( pDesc!=0 && pDesc!=pRow ); |
| 573 | 571 | createMergeRiser(p, pDesc, pRow); |
| 574 | - if( pDesc->mergeOut/4>mxRail ) mxRail = pDesc->mergeOut/4; | |
| 572 | + if( pDesc->mergeOut>mxRail ) mxRail = pDesc->mergeOut; | |
| 575 | 573 | } |
| 576 | 574 | if( dupRail<=mxRail ){ |
| 577 | 575 | dupRail = mxRail+1; |
| 578 | 576 | for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ |
| 579 | 577 | if( pRow->isDup ) pRow->iRail = dupRail; |
| @@ -584,12 +582,7 @@ | ||
| 584 | 582 | |
| 585 | 583 | /* |
| 586 | 584 | ** Find the maximum rail number. |
| 587 | 585 | */ |
| 588 | 586 | find_max_rail(p); |
| 589 | - p->iRailPitch = atoi(PD("railpitch","0")); | |
| 590 | - if( p->iRailPitch<=0 ){ | |
| 591 | - p->iRailPitch = 18 - (p->mxRail/3); | |
| 592 | - if( p->iRailPitch<11 ) p->iRailPitch = 11; | |
| 593 | - } | |
| 594 | 587 | p->nErr = 0; |
| 595 | 588 | } |
| 596 | 589 |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -47,11 +47,11 @@ | |
| 47 | u8 isDup; /* True if this is duplicate of a prior entry */ |
| 48 | u8 isLeaf; /* True if this is a leaf node */ |
| 49 | u8 timeWarp; /* Child is earlier in time */ |
| 50 | u8 bDescender; /* True if riser from bottom of graph to here. */ |
| 51 | i8 iRail; /* Which rail this check-in appears on. 0-based.*/ |
| 52 | i8 mergeOut; /* Merge out on rail mergeOut/4. -1 for none */ |
| 53 | u8 mergeIn[GR_MAX_RAIL]; /* Merge in from non-zero rails */ |
| 54 | int aiRiser[GR_MAX_RAIL]; /* Risers from this node to a higher row. */ |
| 55 | int mergeUpto; /* Draw the mergeOut rail up to this level */ |
| 56 | u64 mergeDown; /* Draw merge lines up from bottom of graph */ |
| 57 | |
| @@ -61,11 +61,10 @@ | |
| 61 | /* Context while building a graph |
| 62 | */ |
| 63 | struct GraphContext { |
| 64 | int nErr; /* Number of errors encountered */ |
| 65 | int mxRail; /* Number of rails required to render the graph */ |
| 66 | int iRailPitch; /* Pixels between rail centers */ |
| 67 | GraphRow *pFirst; /* First row in the list */ |
| 68 | GraphRow *pLast; /* Last row in the list */ |
| 69 | int nBranch; /* Number of distinct branches */ |
| 70 | char **azBranch; /* Names of the branches */ |
| 71 | int nRow; /* Number of rows */ |
| @@ -294,28 +293,27 @@ | |
| 294 | u = pParent->aiRiser[pParent->iRail]; |
| 295 | if( u>=0 && u<pChild->idx ){ |
| 296 | /* The thick arrow up to the next primary child of pDesc goes |
| 297 | ** further up than the thin merge arrow riser, so draw them both |
| 298 | ** on the same rail. */ |
| 299 | pParent->mergeOut = pParent->iRail*4; |
| 300 | if( pParent->iRail<pChild->iRail ) pParent->mergeOut += 2; |
| 301 | pParent->mergeUpto = pChild->idx; |
| 302 | }else{ |
| 303 | /* The thin merge arrow riser is taller than the thick primary |
| 304 | ** child riser, so use separate rails. */ |
| 305 | int iTarget = pParent->iRail; |
| 306 | pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1, |
| 307 | 0, iTarget)*4 + 1; |
| 308 | pParent->mergeUpto = pChild->idx; |
| 309 | mask = BIT(pParent->mergeOut/4); |
| 310 | for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid; |
| 311 | pLoop=pLoop->pNext){ |
| 312 | pLoop->railInUse |= mask; |
| 313 | } |
| 314 | } |
| 315 | } |
| 316 | pChild->mergeIn[pParent->mergeOut/4] = (pParent->mergeOut&3)+1; |
| 317 | } |
| 318 | |
| 319 | /* |
| 320 | ** Compute the maximum rail number. |
| 321 | */ |
| @@ -322,11 +320,11 @@ | |
| 322 | static void find_max_rail(GraphContext *p){ |
| 323 | GraphRow *pRow; |
| 324 | p->mxRail = 0; |
| 325 | for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ |
| 326 | if( pRow->iRail>p->mxRail ) p->mxRail = pRow->iRail; |
| 327 | if( pRow->mergeOut/4>p->mxRail ) p->mxRail = pRow->mergeOut/4; |
| 328 | while( p->mxRail<GR_MAX_RAIL && pRow->mergeDown>(BIT(p->mxRail+1)-1) ){ |
| 329 | p->mxRail++; |
| 330 | } |
| 331 | } |
| 332 | } |
| @@ -540,11 +538,11 @@ | |
| 540 | if( pDesc==0 ){ |
| 541 | /* Merge from a node that is off-screen */ |
| 542 | int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0, 0); |
| 543 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 544 | mask = BIT(iMrail); |
| 545 | pRow->mergeIn[iMrail] = 2; |
| 546 | pRow->mergeDown |= mask; |
| 547 | for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){ |
| 548 | pLoop->railInUse |= mask; |
| 549 | } |
| 550 | }else{ |
| @@ -569,11 +567,11 @@ | |
| 569 | if( !pRow->isDup ) continue; |
| 570 | pRow->iRail = dupRail; |
| 571 | pDesc = hashFind(p, pRow->rid); |
| 572 | assert( pDesc!=0 && pDesc!=pRow ); |
| 573 | createMergeRiser(p, pDesc, pRow); |
| 574 | if( pDesc->mergeOut/4>mxRail ) mxRail = pDesc->mergeOut/4; |
| 575 | } |
| 576 | if( dupRail<=mxRail ){ |
| 577 | dupRail = mxRail+1; |
| 578 | for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ |
| 579 | if( pRow->isDup ) pRow->iRail = dupRail; |
| @@ -584,12 +582,7 @@ | |
| 584 | |
| 585 | /* |
| 586 | ** Find the maximum rail number. |
| 587 | */ |
| 588 | find_max_rail(p); |
| 589 | p->iRailPitch = atoi(PD("railpitch","0")); |
| 590 | if( p->iRailPitch<=0 ){ |
| 591 | p->iRailPitch = 18 - (p->mxRail/3); |
| 592 | if( p->iRailPitch<11 ) p->iRailPitch = 11; |
| 593 | } |
| 594 | p->nErr = 0; |
| 595 | } |
| 596 |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -47,11 +47,11 @@ | |
| 47 | u8 isDup; /* True if this is duplicate of a prior entry */ |
| 48 | u8 isLeaf; /* True if this is a leaf node */ |
| 49 | u8 timeWarp; /* Child is earlier in time */ |
| 50 | u8 bDescender; /* True if riser from bottom of graph to here. */ |
| 51 | i8 iRail; /* Which rail this check-in appears on. 0-based.*/ |
| 52 | i8 mergeOut; /* Merge out to this rail. -1 if no merge-out */ |
| 53 | u8 mergeIn[GR_MAX_RAIL]; /* Merge in from non-zero rails */ |
| 54 | int aiRiser[GR_MAX_RAIL]; /* Risers from this node to a higher row. */ |
| 55 | int mergeUpto; /* Draw the mergeOut rail up to this level */ |
| 56 | u64 mergeDown; /* Draw merge lines up from bottom of graph */ |
| 57 | |
| @@ -61,11 +61,10 @@ | |
| 61 | /* Context while building a graph |
| 62 | */ |
| 63 | struct GraphContext { |
| 64 | int nErr; /* Number of errors encountered */ |
| 65 | int mxRail; /* Number of rails required to render the graph */ |
| 66 | GraphRow *pFirst; /* First row in the list */ |
| 67 | GraphRow *pLast; /* Last row in the list */ |
| 68 | int nBranch; /* Number of distinct branches */ |
| 69 | char **azBranch; /* Names of the branches */ |
| 70 | int nRow; /* Number of rows */ |
| @@ -294,28 +293,27 @@ | |
| 293 | u = pParent->aiRiser[pParent->iRail]; |
| 294 | if( u>=0 && u<pChild->idx ){ |
| 295 | /* The thick arrow up to the next primary child of pDesc goes |
| 296 | ** further up than the thin merge arrow riser, so draw them both |
| 297 | ** on the same rail. */ |
| 298 | pParent->mergeOut = pParent->iRail; |
| 299 | pParent->mergeUpto = pChild->idx; |
| 300 | }else{ |
| 301 | /* The thin merge arrow riser is taller than the thick primary |
| 302 | ** child riser, so use separate rails. */ |
| 303 | int iTarget = pParent->iRail; |
| 304 | pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1, |
| 305 | 0, iTarget); |
| 306 | pParent->mergeUpto = pChild->idx; |
| 307 | mask = BIT(pParent->mergeOut); |
| 308 | for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid; |
| 309 | pLoop=pLoop->pNext){ |
| 310 | pLoop->railInUse |= mask; |
| 311 | } |
| 312 | } |
| 313 | } |
| 314 | pChild->mergeIn[pParent->mergeOut] = 1; |
| 315 | } |
| 316 | |
| 317 | /* |
| 318 | ** Compute the maximum rail number. |
| 319 | */ |
| @@ -322,11 +320,11 @@ | |
| 320 | static void find_max_rail(GraphContext *p){ |
| 321 | GraphRow *pRow; |
| 322 | p->mxRail = 0; |
| 323 | for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ |
| 324 | if( pRow->iRail>p->mxRail ) p->mxRail = pRow->iRail; |
| 325 | if( pRow->mergeOut>p->mxRail ) p->mxRail = pRow->mergeOut; |
| 326 | while( p->mxRail<GR_MAX_RAIL && pRow->mergeDown>(BIT(p->mxRail+1)-1) ){ |
| 327 | p->mxRail++; |
| 328 | } |
| 329 | } |
| 330 | } |
| @@ -540,11 +538,11 @@ | |
| 538 | if( pDesc==0 ){ |
| 539 | /* Merge from a node that is off-screen */ |
| 540 | int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0, 0); |
| 541 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 542 | mask = BIT(iMrail); |
| 543 | pRow->mergeIn[iMrail] = 1; |
| 544 | pRow->mergeDown |= mask; |
| 545 | for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){ |
| 546 | pLoop->railInUse |= mask; |
| 547 | } |
| 548 | }else{ |
| @@ -569,11 +567,11 @@ | |
| 567 | if( !pRow->isDup ) continue; |
| 568 | pRow->iRail = dupRail; |
| 569 | pDesc = hashFind(p, pRow->rid); |
| 570 | assert( pDesc!=0 && pDesc!=pRow ); |
| 571 | createMergeRiser(p, pDesc, pRow); |
| 572 | if( pDesc->mergeOut>mxRail ) mxRail = pDesc->mergeOut; |
| 573 | } |
| 574 | if( dupRail<=mxRail ){ |
| 575 | dupRail = mxRail+1; |
| 576 | for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ |
| 577 | if( pRow->isDup ) pRow->iRail = dupRail; |
| @@ -584,12 +582,7 @@ | |
| 582 | |
| 583 | /* |
| 584 | ** Find the maximum rail number. |
| 585 | */ |
| 586 | find_max_rail(p); |
| 587 | p->nErr = 0; |
| 588 | } |
| 589 |
+2
-2
| --- src/http.c | ||
| +++ src/http.c | ||
| @@ -338,14 +338,14 @@ | ||
| 338 | 338 | j = strlen(zLine) - 1; |
| 339 | 339 | while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){ |
| 340 | 340 | j -= 4; |
| 341 | 341 | zLine[j] = 0; |
| 342 | 342 | } |
| 343 | + fossil_print("redirect with status %d to %s\n", rc, &zLine[i]); | |
| 344 | + url_parse(&zLine[i], 0); | |
| 343 | 345 | transport_close(&g.url); |
| 344 | 346 | transport_global_shutdown(&g.url); |
| 345 | - fossil_print("redirect with status %d to %s\n", rc, &zLine[i]); | |
| 346 | - url_parse(&zLine[i], 0); | |
| 347 | 347 | fSeenHttpAuth = 0; |
| 348 | 348 | if( g.zHttpAuth ) free(g.zHttpAuth); |
| 349 | 349 | g.zHttpAuth = get_httpauth(); |
| 350 | 350 | return http_exchange(pSend, pReply, useLogin, maxRedirect); |
| 351 | 351 | }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){ |
| 352 | 352 |
| --- src/http.c | |
| +++ src/http.c | |
| @@ -338,14 +338,14 @@ | |
| 338 | j = strlen(zLine) - 1; |
| 339 | while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){ |
| 340 | j -= 4; |
| 341 | zLine[j] = 0; |
| 342 | } |
| 343 | transport_close(&g.url); |
| 344 | transport_global_shutdown(&g.url); |
| 345 | fossil_print("redirect with status %d to %s\n", rc, &zLine[i]); |
| 346 | url_parse(&zLine[i], 0); |
| 347 | fSeenHttpAuth = 0; |
| 348 | if( g.zHttpAuth ) free(g.zHttpAuth); |
| 349 | g.zHttpAuth = get_httpauth(); |
| 350 | return http_exchange(pSend, pReply, useLogin, maxRedirect); |
| 351 | }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){ |
| 352 |
| --- src/http.c | |
| +++ src/http.c | |
| @@ -338,14 +338,14 @@ | |
| 338 | j = strlen(zLine) - 1; |
| 339 | while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){ |
| 340 | j -= 4; |
| 341 | zLine[j] = 0; |
| 342 | } |
| 343 | fossil_print("redirect with status %d to %s\n", rc, &zLine[i]); |
| 344 | url_parse(&zLine[i], 0); |
| 345 | transport_close(&g.url); |
| 346 | transport_global_shutdown(&g.url); |
| 347 | fSeenHttpAuth = 0; |
| 348 | if( g.zHttpAuth ) free(g.zHttpAuth); |
| 349 | g.zHttpAuth = get_httpauth(); |
| 350 | return http_exchange(pSend, pReply, useLogin, maxRedirect); |
| 351 | }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){ |
| 352 |
+28
-15
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -222,11 +222,10 @@ | ||
| 222 | 222 | if( rid==0 ){ |
| 223 | 223 | fossil_fatal("no such object: %s\n", g.argv[2]); |
| 224 | 224 | } |
| 225 | 225 | show_common_info(rid, "uuid:", 1, 1); |
| 226 | 226 | } |
| 227 | - fossil_print("multiple leaves on the same branch:\n"); | |
| 228 | 227 | leaves_cmd(); |
| 229 | 228 | } |
| 230 | 229 | |
| 231 | 230 | /* |
| 232 | 231 | ** Show information about all tags on a given check-in. |
| @@ -370,54 +369,68 @@ | ||
| 370 | 369 | const char *zOldName, /* Prior name. NULL if no name change. */ |
| 371 | 370 | u64 diffFlags, /* Flags for text_diff(). Zero to omit diffs */ |
| 372 | 371 | ReCompiled *pRe, /* Only show diffs that match this regex, if not NULL */ |
| 373 | 372 | int mperm /* executable or symlink permission for zNew */ |
| 374 | 373 | ){ |
| 374 | + @ <p> | |
| 375 | 375 | if( !g.perm.Hyperlink ){ |
| 376 | 376 | if( zNew==0 ){ |
| 377 | - @ <p>Deleted %h(zName)</p> | |
| 377 | + @ Deleted %h(zName). | |
| 378 | 378 | }else if( zOld==0 ){ |
| 379 | - @ <p>Added %h(zName)</p> | |
| 379 | + @ Added %h(zName). | |
| 380 | 380 | }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ |
| 381 | - @ <p>Name change from %h(zOldName) to %h(zName) | |
| 381 | + @ Name change from %h(zOldName) to %h(zName). | |
| 382 | 382 | }else if( fossil_strcmp(zNew, zOld)==0 ){ |
| 383 | - @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared") | |
| 384 | - @ for %h(zName)</p> | |
| 383 | + if( mperm==PERM_EXE ){ | |
| 384 | + @ %h(zName) became executable. | |
| 385 | + }else if( mperm==PERM_LNK ){ | |
| 386 | + @ %h(zName) became a symlink. | |
| 387 | + }else{ | |
| 388 | + @ %h(zName) became a regular file. | |
| 389 | + } | |
| 385 | 390 | }else{ |
| 386 | - @ <p>Changes to %h(zName)</p> | |
| 391 | + @ Changes to %h(zName). | |
| 387 | 392 | } |
| 388 | 393 | if( diffFlags ){ |
| 389 | 394 | append_diff(zOld, zNew, diffFlags, pRe); |
| 390 | 395 | } |
| 391 | 396 | }else{ |
| 392 | 397 | if( zOld && zNew ){ |
| 393 | 398 | if( fossil_strcmp(zOld, zNew)!=0 ){ |
| 394 | - @ <p>Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a> | |
| 399 | + @ Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a> | |
| 395 | 400 | @ from %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a> |
| 396 | 401 | @ to %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a>. |
| 397 | 402 | }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ |
| 398 | - @ <p>Name change | |
| 403 | + @ Name change | |
| 399 | 404 | @ from %z(href("%R/finfo?name=%T",zOldName))%h(zOldName)</a> |
| 400 | 405 | @ to %z(href("%R/finfo?name=%T",zName))%h(zName)</a>. |
| 401 | 406 | }else{ |
| 402 | - @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared") for | |
| 403 | - @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a> | |
| 407 | + @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a> became | |
| 408 | + if( mperm==PERM_EXE ){ | |
| 409 | + @ executable with contents | |
| 410 | + }else if( mperm==PERM_LNK ){ | |
| 411 | + @ a symlink with target | |
| 412 | + }else{ | |
| 413 | + @ a regular file with contents | |
| 414 | + } | |
| 415 | + @ %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a>. | |
| 404 | 416 | } |
| 405 | 417 | }else if( zOld ){ |
| 406 | - @ <p>Deleted %z(href("%R/finfo?name=%T",zName))%h(zName)</a> | |
| 407 | - @ version %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a> | |
| 418 | + @ Deleted %z(href("%R/finfo?name=%T",zName))%h(zName)</a> | |
| 419 | + @ version %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a>. | |
| 408 | 420 | }else{ |
| 409 | - @ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a> | |
| 410 | - @ version %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a> | |
| 421 | + @ Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a> | |
| 422 | + @ version %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a>. | |
| 411 | 423 | } |
| 412 | 424 | if( diffFlags ){ |
| 413 | 425 | append_diff(zOld, zNew, diffFlags, pRe); |
| 414 | 426 | }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){ |
| 415 | 427 | @ |
| 416 | 428 | @ %z(href("%R/fdiff?v1=%!S&v2=%!S&sbs=1",zOld,zNew))[diff]</a> |
| 417 | 429 | } |
| 418 | 430 | } |
| 431 | + @ </p> | |
| 419 | 432 | } |
| 420 | 433 | |
| 421 | 434 | /* |
| 422 | 435 | ** Generate javascript to enhance HTML diffs. |
| 423 | 436 | */ |
| 424 | 437 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -222,11 +222,10 @@ | |
| 222 | if( rid==0 ){ |
| 223 | fossil_fatal("no such object: %s\n", g.argv[2]); |
| 224 | } |
| 225 | show_common_info(rid, "uuid:", 1, 1); |
| 226 | } |
| 227 | fossil_print("multiple leaves on the same branch:\n"); |
| 228 | leaves_cmd(); |
| 229 | } |
| 230 | |
| 231 | /* |
| 232 | ** Show information about all tags on a given check-in. |
| @@ -370,54 +369,68 @@ | |
| 370 | const char *zOldName, /* Prior name. NULL if no name change. */ |
| 371 | u64 diffFlags, /* Flags for text_diff(). Zero to omit diffs */ |
| 372 | ReCompiled *pRe, /* Only show diffs that match this regex, if not NULL */ |
| 373 | int mperm /* executable or symlink permission for zNew */ |
| 374 | ){ |
| 375 | if( !g.perm.Hyperlink ){ |
| 376 | if( zNew==0 ){ |
| 377 | @ <p>Deleted %h(zName)</p> |
| 378 | }else if( zOld==0 ){ |
| 379 | @ <p>Added %h(zName)</p> |
| 380 | }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ |
| 381 | @ <p>Name change from %h(zOldName) to %h(zName) |
| 382 | }else if( fossil_strcmp(zNew, zOld)==0 ){ |
| 383 | @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared") |
| 384 | @ for %h(zName)</p> |
| 385 | }else{ |
| 386 | @ <p>Changes to %h(zName)</p> |
| 387 | } |
| 388 | if( diffFlags ){ |
| 389 | append_diff(zOld, zNew, diffFlags, pRe); |
| 390 | } |
| 391 | }else{ |
| 392 | if( zOld && zNew ){ |
| 393 | if( fossil_strcmp(zOld, zNew)!=0 ){ |
| 394 | @ <p>Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 395 | @ from %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a> |
| 396 | @ to %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a>. |
| 397 | }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ |
| 398 | @ <p>Name change |
| 399 | @ from %z(href("%R/finfo?name=%T",zOldName))%h(zOldName)</a> |
| 400 | @ to %z(href("%R/finfo?name=%T",zName))%h(zName)</a>. |
| 401 | }else{ |
| 402 | @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared") for |
| 403 | @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 404 | } |
| 405 | }else if( zOld ){ |
| 406 | @ <p>Deleted %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 407 | @ version %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a> |
| 408 | }else{ |
| 409 | @ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 410 | @ version %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a> |
| 411 | } |
| 412 | if( diffFlags ){ |
| 413 | append_diff(zOld, zNew, diffFlags, pRe); |
| 414 | }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){ |
| 415 | @ |
| 416 | @ %z(href("%R/fdiff?v1=%!S&v2=%!S&sbs=1",zOld,zNew))[diff]</a> |
| 417 | } |
| 418 | } |
| 419 | } |
| 420 | |
| 421 | /* |
| 422 | ** Generate javascript to enhance HTML diffs. |
| 423 | */ |
| 424 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -222,11 +222,10 @@ | |
| 222 | if( rid==0 ){ |
| 223 | fossil_fatal("no such object: %s\n", g.argv[2]); |
| 224 | } |
| 225 | show_common_info(rid, "uuid:", 1, 1); |
| 226 | } |
| 227 | leaves_cmd(); |
| 228 | } |
| 229 | |
| 230 | /* |
| 231 | ** Show information about all tags on a given check-in. |
| @@ -370,54 +369,68 @@ | |
| 369 | const char *zOldName, /* Prior name. NULL if no name change. */ |
| 370 | u64 diffFlags, /* Flags for text_diff(). Zero to omit diffs */ |
| 371 | ReCompiled *pRe, /* Only show diffs that match this regex, if not NULL */ |
| 372 | int mperm /* executable or symlink permission for zNew */ |
| 373 | ){ |
| 374 | @ <p> |
| 375 | if( !g.perm.Hyperlink ){ |
| 376 | if( zNew==0 ){ |
| 377 | @ Deleted %h(zName). |
| 378 | }else if( zOld==0 ){ |
| 379 | @ Added %h(zName). |
| 380 | }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ |
| 381 | @ Name change from %h(zOldName) to %h(zName). |
| 382 | }else if( fossil_strcmp(zNew, zOld)==0 ){ |
| 383 | if( mperm==PERM_EXE ){ |
| 384 | @ %h(zName) became executable. |
| 385 | }else if( mperm==PERM_LNK ){ |
| 386 | @ %h(zName) became a symlink. |
| 387 | }else{ |
| 388 | @ %h(zName) became a regular file. |
| 389 | } |
| 390 | }else{ |
| 391 | @ Changes to %h(zName). |
| 392 | } |
| 393 | if( diffFlags ){ |
| 394 | append_diff(zOld, zNew, diffFlags, pRe); |
| 395 | } |
| 396 | }else{ |
| 397 | if( zOld && zNew ){ |
| 398 | if( fossil_strcmp(zOld, zNew)!=0 ){ |
| 399 | @ Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 400 | @ from %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a> |
| 401 | @ to %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a>. |
| 402 | }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ |
| 403 | @ Name change |
| 404 | @ from %z(href("%R/finfo?name=%T",zOldName))%h(zOldName)</a> |
| 405 | @ to %z(href("%R/finfo?name=%T",zName))%h(zName)</a>. |
| 406 | }else{ |
| 407 | @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a> became |
| 408 | if( mperm==PERM_EXE ){ |
| 409 | @ executable with contents |
| 410 | }else if( mperm==PERM_LNK ){ |
| 411 | @ a symlink with target |
| 412 | }else{ |
| 413 | @ a regular file with contents |
| 414 | } |
| 415 | @ %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a>. |
| 416 | } |
| 417 | }else if( zOld ){ |
| 418 | @ Deleted %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 419 | @ version %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a>. |
| 420 | }else{ |
| 421 | @ Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 422 | @ version %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a>. |
| 423 | } |
| 424 | if( diffFlags ){ |
| 425 | append_diff(zOld, zNew, diffFlags, pRe); |
| 426 | }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){ |
| 427 | @ |
| 428 | @ %z(href("%R/fdiff?v1=%!S&v2=%!S&sbs=1",zOld,zNew))[diff]</a> |
| 429 | } |
| 430 | } |
| 431 | @ </p> |
| 432 | } |
| 433 | |
| 434 | /* |
| 435 | ** Generate javascript to enhance HTML diffs. |
| 436 | */ |
| 437 |
+28
-15
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -222,11 +222,10 @@ | ||
| 222 | 222 | if( rid==0 ){ |
| 223 | 223 | fossil_fatal("no such object: %s\n", g.argv[2]); |
| 224 | 224 | } |
| 225 | 225 | show_common_info(rid, "uuid:", 1, 1); |
| 226 | 226 | } |
| 227 | - fossil_print("multiple leaves on the same branch:\n"); | |
| 228 | 227 | leaves_cmd(); |
| 229 | 228 | } |
| 230 | 229 | |
| 231 | 230 | /* |
| 232 | 231 | ** Show information about all tags on a given check-in. |
| @@ -370,54 +369,68 @@ | ||
| 370 | 369 | const char *zOldName, /* Prior name. NULL if no name change. */ |
| 371 | 370 | u64 diffFlags, /* Flags for text_diff(). Zero to omit diffs */ |
| 372 | 371 | ReCompiled *pRe, /* Only show diffs that match this regex, if not NULL */ |
| 373 | 372 | int mperm /* executable or symlink permission for zNew */ |
| 374 | 373 | ){ |
| 374 | + @ <p> | |
| 375 | 375 | if( !g.perm.Hyperlink ){ |
| 376 | 376 | if( zNew==0 ){ |
| 377 | - @ <p>Deleted %h(zName)</p> | |
| 377 | + @ Deleted %h(zName). | |
| 378 | 378 | }else if( zOld==0 ){ |
| 379 | - @ <p>Added %h(zName)</p> | |
| 379 | + @ Added %h(zName). | |
| 380 | 380 | }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ |
| 381 | - @ <p>Name change from %h(zOldName) to %h(zName) | |
| 381 | + @ Name change from %h(zOldName) to %h(zName). | |
| 382 | 382 | }else if( fossil_strcmp(zNew, zOld)==0 ){ |
| 383 | - @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared") | |
| 384 | - @ for %h(zName)</p> | |
| 383 | + if( mperm==PERM_EXE ){ | |
| 384 | + @ %h(zName) became executable. | |
| 385 | + }else if( mperm==PERM_LNK ){ | |
| 386 | + @ %h(zName) became a symlink. | |
| 387 | + }else{ | |
| 388 | + @ %h(zName) became a regular file. | |
| 389 | + } | |
| 385 | 390 | }else{ |
| 386 | - @ <p>Changes to %h(zName)</p> | |
| 391 | + @ Changes to %h(zName). | |
| 387 | 392 | } |
| 388 | 393 | if( diffFlags ){ |
| 389 | 394 | append_diff(zOld, zNew, diffFlags, pRe); |
| 390 | 395 | } |
| 391 | 396 | }else{ |
| 392 | 397 | if( zOld && zNew ){ |
| 393 | 398 | if( fossil_strcmp(zOld, zNew)!=0 ){ |
| 394 | - @ <p>Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a> | |
| 399 | + @ Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a> | |
| 395 | 400 | @ from %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a> |
| 396 | 401 | @ to %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a>. |
| 397 | 402 | }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ |
| 398 | - @ <p>Name change | |
| 403 | + @ Name change | |
| 399 | 404 | @ from %z(href("%R/finfo?name=%T",zOldName))%h(zOldName)</a> |
| 400 | 405 | @ to %z(href("%R/finfo?name=%T",zName))%h(zName)</a>. |
| 401 | 406 | }else{ |
| 402 | - @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared") for | |
| 403 | - @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a> | |
| 407 | + @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a> became | |
| 408 | + if( mperm==PERM_EXE ){ | |
| 409 | + @ executable with contents | |
| 410 | + }else if( mperm==PERM_LNK ){ | |
| 411 | + @ a symlink with target | |
| 412 | + }else{ | |
| 413 | + @ a regular file with contents | |
| 414 | + } | |
| 415 | + @ %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a>. | |
| 404 | 416 | } |
| 405 | 417 | }else if( zOld ){ |
| 406 | - @ <p>Deleted %z(href("%R/finfo?name=%T",zName))%h(zName)</a> | |
| 407 | - @ version %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a> | |
| 418 | + @ Deleted %z(href("%R/finfo?name=%T",zName))%h(zName)</a> | |
| 419 | + @ version %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a>. | |
| 408 | 420 | }else{ |
| 409 | - @ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a> | |
| 410 | - @ version %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a> | |
| 421 | + @ Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a> | |
| 422 | + @ version %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a>. | |
| 411 | 423 | } |
| 412 | 424 | if( diffFlags ){ |
| 413 | 425 | append_diff(zOld, zNew, diffFlags, pRe); |
| 414 | 426 | }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){ |
| 415 | 427 | @ |
| 416 | 428 | @ %z(href("%R/fdiff?v1=%!S&v2=%!S&sbs=1",zOld,zNew))[diff]</a> |
| 417 | 429 | } |
| 418 | 430 | } |
| 431 | + @ </p> | |
| 419 | 432 | } |
| 420 | 433 | |
| 421 | 434 | /* |
| 422 | 435 | ** Generate javascript to enhance HTML diffs. |
| 423 | 436 | */ |
| 424 | 437 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -222,11 +222,10 @@ | |
| 222 | if( rid==0 ){ |
| 223 | fossil_fatal("no such object: %s\n", g.argv[2]); |
| 224 | } |
| 225 | show_common_info(rid, "uuid:", 1, 1); |
| 226 | } |
| 227 | fossil_print("multiple leaves on the same branch:\n"); |
| 228 | leaves_cmd(); |
| 229 | } |
| 230 | |
| 231 | /* |
| 232 | ** Show information about all tags on a given check-in. |
| @@ -370,54 +369,68 @@ | |
| 370 | const char *zOldName, /* Prior name. NULL if no name change. */ |
| 371 | u64 diffFlags, /* Flags for text_diff(). Zero to omit diffs */ |
| 372 | ReCompiled *pRe, /* Only show diffs that match this regex, if not NULL */ |
| 373 | int mperm /* executable or symlink permission for zNew */ |
| 374 | ){ |
| 375 | if( !g.perm.Hyperlink ){ |
| 376 | if( zNew==0 ){ |
| 377 | @ <p>Deleted %h(zName)</p> |
| 378 | }else if( zOld==0 ){ |
| 379 | @ <p>Added %h(zName)</p> |
| 380 | }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ |
| 381 | @ <p>Name change from %h(zOldName) to %h(zName) |
| 382 | }else if( fossil_strcmp(zNew, zOld)==0 ){ |
| 383 | @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared") |
| 384 | @ for %h(zName)</p> |
| 385 | }else{ |
| 386 | @ <p>Changes to %h(zName)</p> |
| 387 | } |
| 388 | if( diffFlags ){ |
| 389 | append_diff(zOld, zNew, diffFlags, pRe); |
| 390 | } |
| 391 | }else{ |
| 392 | if( zOld && zNew ){ |
| 393 | if( fossil_strcmp(zOld, zNew)!=0 ){ |
| 394 | @ <p>Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 395 | @ from %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a> |
| 396 | @ to %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a>. |
| 397 | }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ |
| 398 | @ <p>Name change |
| 399 | @ from %z(href("%R/finfo?name=%T",zOldName))%h(zOldName)</a> |
| 400 | @ to %z(href("%R/finfo?name=%T",zName))%h(zName)</a>. |
| 401 | }else{ |
| 402 | @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared") for |
| 403 | @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 404 | } |
| 405 | }else if( zOld ){ |
| 406 | @ <p>Deleted %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 407 | @ version %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a> |
| 408 | }else{ |
| 409 | @ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 410 | @ version %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a> |
| 411 | } |
| 412 | if( diffFlags ){ |
| 413 | append_diff(zOld, zNew, diffFlags, pRe); |
| 414 | }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){ |
| 415 | @ |
| 416 | @ %z(href("%R/fdiff?v1=%!S&v2=%!S&sbs=1",zOld,zNew))[diff]</a> |
| 417 | } |
| 418 | } |
| 419 | } |
| 420 | |
| 421 | /* |
| 422 | ** Generate javascript to enhance HTML diffs. |
| 423 | */ |
| 424 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -222,11 +222,10 @@ | |
| 222 | if( rid==0 ){ |
| 223 | fossil_fatal("no such object: %s\n", g.argv[2]); |
| 224 | } |
| 225 | show_common_info(rid, "uuid:", 1, 1); |
| 226 | } |
| 227 | leaves_cmd(); |
| 228 | } |
| 229 | |
| 230 | /* |
| 231 | ** Show information about all tags on a given check-in. |
| @@ -370,54 +369,68 @@ | |
| 369 | const char *zOldName, /* Prior name. NULL if no name change. */ |
| 370 | u64 diffFlags, /* Flags for text_diff(). Zero to omit diffs */ |
| 371 | ReCompiled *pRe, /* Only show diffs that match this regex, if not NULL */ |
| 372 | int mperm /* executable or symlink permission for zNew */ |
| 373 | ){ |
| 374 | @ <p> |
| 375 | if( !g.perm.Hyperlink ){ |
| 376 | if( zNew==0 ){ |
| 377 | @ Deleted %h(zName). |
| 378 | }else if( zOld==0 ){ |
| 379 | @ Added %h(zName). |
| 380 | }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ |
| 381 | @ Name change from %h(zOldName) to %h(zName). |
| 382 | }else if( fossil_strcmp(zNew, zOld)==0 ){ |
| 383 | if( mperm==PERM_EXE ){ |
| 384 | @ %h(zName) became executable. |
| 385 | }else if( mperm==PERM_LNK ){ |
| 386 | @ %h(zName) became a symlink. |
| 387 | }else{ |
| 388 | @ %h(zName) became a regular file. |
| 389 | } |
| 390 | }else{ |
| 391 | @ Changes to %h(zName). |
| 392 | } |
| 393 | if( diffFlags ){ |
| 394 | append_diff(zOld, zNew, diffFlags, pRe); |
| 395 | } |
| 396 | }else{ |
| 397 | if( zOld && zNew ){ |
| 398 | if( fossil_strcmp(zOld, zNew)!=0 ){ |
| 399 | @ Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 400 | @ from %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a> |
| 401 | @ to %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a>. |
| 402 | }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ |
| 403 | @ Name change |
| 404 | @ from %z(href("%R/finfo?name=%T",zOldName))%h(zOldName)</a> |
| 405 | @ to %z(href("%R/finfo?name=%T",zName))%h(zName)</a>. |
| 406 | }else{ |
| 407 | @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a> became |
| 408 | if( mperm==PERM_EXE ){ |
| 409 | @ executable with contents |
| 410 | }else if( mperm==PERM_LNK ){ |
| 411 | @ a symlink with target |
| 412 | }else{ |
| 413 | @ a regular file with contents |
| 414 | } |
| 415 | @ %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a>. |
| 416 | } |
| 417 | }else if( zOld ){ |
| 418 | @ Deleted %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 419 | @ version %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a>. |
| 420 | }else{ |
| 421 | @ Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 422 | @ version %z(href("%R/artifact/%!S",zNew))[%S(zNew)]</a>. |
| 423 | } |
| 424 | if( diffFlags ){ |
| 425 | append_diff(zOld, zNew, diffFlags, pRe); |
| 426 | }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){ |
| 427 | @ |
| 428 | @ %z(href("%R/fdiff?v1=%!S&v2=%!S&sbs=1",zOld,zNew))[diff]</a> |
| 429 | } |
| 430 | } |
| 431 | @ </p> |
| 432 | } |
| 433 | |
| 434 | /* |
| 435 | ** Generate javascript to enhance HTML diffs. |
| 436 | */ |
| 437 |
+1
| --- src/json.c | ||
| +++ src/json.c | ||
| @@ -1292,10 +1292,11 @@ | ||
| 1292 | 1292 | INT(g, nAux); |
| 1293 | 1293 | INT(g, allowSymlinks); |
| 1294 | 1294 | |
| 1295 | 1295 | CSTR(g, zMainDbType); |
| 1296 | 1296 | CSTR(g, zConfigDbType); |
| 1297 | + CSTR(g, zOpenRevision); | |
| 1297 | 1298 | CSTR(g, zLocalRoot); |
| 1298 | 1299 | CSTR(g, zPath); |
| 1299 | 1300 | CSTR(g, zExtra); |
| 1300 | 1301 | CSTR(g, zBaseURL); |
| 1301 | 1302 | CSTR(g, zTop); |
| 1302 | 1303 |
| --- src/json.c | |
| +++ src/json.c | |
| @@ -1292,10 +1292,11 @@ | |
| 1292 | INT(g, nAux); |
| 1293 | INT(g, allowSymlinks); |
| 1294 | |
| 1295 | CSTR(g, zMainDbType); |
| 1296 | CSTR(g, zConfigDbType); |
| 1297 | CSTR(g, zLocalRoot); |
| 1298 | CSTR(g, zPath); |
| 1299 | CSTR(g, zExtra); |
| 1300 | CSTR(g, zBaseURL); |
| 1301 | CSTR(g, zTop); |
| 1302 |
| --- src/json.c | |
| +++ src/json.c | |
| @@ -1292,10 +1292,11 @@ | |
| 1292 | INT(g, nAux); |
| 1293 | INT(g, allowSymlinks); |
| 1294 | |
| 1295 | CSTR(g, zMainDbType); |
| 1296 | CSTR(g, zConfigDbType); |
| 1297 | CSTR(g, zOpenRevision); |
| 1298 | CSTR(g, zLocalRoot); |
| 1299 | CSTR(g, zPath); |
| 1300 | CSTR(g, zExtra); |
| 1301 | CSTR(g, zBaseURL); |
| 1302 | CSTR(g, zTop); |
| 1303 |
+13
-5
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -135,10 +135,11 @@ | ||
| 135 | 135 | char *zRepositoryOption; /* Most recent cached repository option value */ |
| 136 | 136 | char *zRepositoryName; /* Name of the repository database */ |
| 137 | 137 | char *zLocalDbName; /* Name of the local database */ |
| 138 | 138 | const char *zMainDbType;/* "configdb", "localdb", or "repository" */ |
| 139 | 139 | const char *zConfigDbType; /* "configdb", "localdb", or "repository" */ |
| 140 | + char *zOpenRevision; /* Check-in version to use during database open */ | |
| 140 | 141 | int localOpen; /* True if the local database is open */ |
| 141 | 142 | char *zLocalRoot; /* The directory holding the local database */ |
| 142 | 143 | int minPrefix; /* Number of digits needed for a distinct UUID */ |
| 143 | 144 | int fSqlTrace; /* True if --sqltrace flag is present */ |
| 144 | 145 | int fSqlStats; /* True if --sqltrace or --sqlstats are present */ |
| @@ -1441,20 +1442,27 @@ | ||
| 1441 | 1442 | vfile_scan(&base, blob_size(&base), 0, 0, 0); |
| 1442 | 1443 | db_multi_exec("DELETE FROM sfile WHERE x NOT GLOB '*.fossil'"); |
| 1443 | 1444 | n = db_int(0, "SELECT count(*) FROM sfile"); |
| 1444 | 1445 | if( n>0 ){ |
| 1445 | 1446 | Stmt q; |
| 1447 | + @ <html> | |
| 1448 | + @ <head> | |
| 1449 | + @ <title>Repository List</title> | |
| 1450 | + @ </head> | |
| 1451 | + @ <body> | |
| 1446 | 1452 | @ <h1>Available Repositories:</h1> |
| 1447 | 1453 | @ <ol> |
| 1448 | 1454 | db_prepare(&q, "SELECT x, substr(x,-7,-100000)||'/home'" |
| 1449 | 1455 | " FROM sfile ORDER BY x COLLATE nocase;"); |
| 1450 | 1456 | while( db_step(&q)==SQLITE_ROW ){ |
| 1451 | 1457 | const char *zName = db_column_text(&q, 0); |
| 1452 | 1458 | const char *zUrl = db_column_text(&q, 1); |
| 1453 | - @ <li><a href="%h(zUrl)">%h(zName)</a></li> | |
| 1459 | + @ <li><a href="%h(zUrl)" target="_blank">%h(zName)</a></li> | |
| 1454 | 1460 | } |
| 1455 | 1461 | @ </ol> |
| 1462 | + @ </body> | |
| 1463 | + @ </html> | |
| 1456 | 1464 | cgi_reply(); |
| 1457 | 1465 | } |
| 1458 | 1466 | sqlite3_close(g.db); |
| 1459 | 1467 | g.db = 0; |
| 1460 | 1468 | return n; |
| @@ -1563,16 +1571,16 @@ | ||
| 1563 | 1571 | zRepo[j] = '.'; |
| 1564 | 1572 | } |
| 1565 | 1573 | |
| 1566 | 1574 | if( szFile<1024 ){ |
| 1567 | 1575 | set_base_url(0); |
| 1568 | - if( zNotFound ){ | |
| 1569 | - cgi_redirect(zNotFound); | |
| 1570 | - }else if( strcmp(zPathInfo,"/")==0 | |
| 1576 | + if( strcmp(zPathInfo,"/")==0 | |
| 1571 | 1577 | && allowRepoList |
| 1572 | 1578 | && repo_list_page() ){ |
| 1573 | 1579 | /* Will return a list of repositories */ |
| 1580 | + }else if( zNotFound ){ | |
| 1581 | + cgi_redirect(zNotFound); | |
| 1574 | 1582 | }else{ |
| 1575 | 1583 | #ifdef FOSSIL_ENABLE_JSON |
| 1576 | 1584 | if(g.json.isJsonMode){ |
| 1577 | 1585 | json_err(FSL_JSON_E_RESOURCE_NOT_FOUND,NULL,1); |
| 1578 | 1586 | return; |
| @@ -2169,18 +2177,18 @@ | ||
| 2169 | 2177 | zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */ |
| 2170 | 2178 | cgi_replace_parameter("HTTPS","on"); |
| 2171 | 2179 | } |
| 2172 | 2180 | zHost = find_option("host", 0, 1); |
| 2173 | 2181 | if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost); |
| 2174 | - g.cgiOutput = 1; | |
| 2175 | 2182 | |
| 2176 | 2183 | /* We should be done with options.. */ |
| 2177 | 2184 | verify_all_options(); |
| 2178 | 2185 | |
| 2179 | 2186 | if( g.argc!=2 && g.argc!=3 && g.argc!=5 && g.argc!=6 ){ |
| 2180 | 2187 | fossil_fatal("no repository specified"); |
| 2181 | 2188 | } |
| 2189 | + g.cgiOutput = 1; | |
| 2182 | 2190 | g.fullHttpReply = 1; |
| 2183 | 2191 | if( g.argc>=5 ){ |
| 2184 | 2192 | g.httpIn = fossil_fopen(g.argv[2], "rb"); |
| 2185 | 2193 | g.httpOut = fossil_fopen(g.argv[3], "wb"); |
| 2186 | 2194 | zIpAddr = g.argv[4]; |
| 2187 | 2195 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -135,10 +135,11 @@ | |
| 135 | char *zRepositoryOption; /* Most recent cached repository option value */ |
| 136 | char *zRepositoryName; /* Name of the repository database */ |
| 137 | char *zLocalDbName; /* Name of the local database */ |
| 138 | const char *zMainDbType;/* "configdb", "localdb", or "repository" */ |
| 139 | const char *zConfigDbType; /* "configdb", "localdb", or "repository" */ |
| 140 | int localOpen; /* True if the local database is open */ |
| 141 | char *zLocalRoot; /* The directory holding the local database */ |
| 142 | int minPrefix; /* Number of digits needed for a distinct UUID */ |
| 143 | int fSqlTrace; /* True if --sqltrace flag is present */ |
| 144 | int fSqlStats; /* True if --sqltrace or --sqlstats are present */ |
| @@ -1441,20 +1442,27 @@ | |
| 1441 | vfile_scan(&base, blob_size(&base), 0, 0, 0); |
| 1442 | db_multi_exec("DELETE FROM sfile WHERE x NOT GLOB '*.fossil'"); |
| 1443 | n = db_int(0, "SELECT count(*) FROM sfile"); |
| 1444 | if( n>0 ){ |
| 1445 | Stmt q; |
| 1446 | @ <h1>Available Repositories:</h1> |
| 1447 | @ <ol> |
| 1448 | db_prepare(&q, "SELECT x, substr(x,-7,-100000)||'/home'" |
| 1449 | " FROM sfile ORDER BY x COLLATE nocase;"); |
| 1450 | while( db_step(&q)==SQLITE_ROW ){ |
| 1451 | const char *zName = db_column_text(&q, 0); |
| 1452 | const char *zUrl = db_column_text(&q, 1); |
| 1453 | @ <li><a href="%h(zUrl)">%h(zName)</a></li> |
| 1454 | } |
| 1455 | @ </ol> |
| 1456 | cgi_reply(); |
| 1457 | } |
| 1458 | sqlite3_close(g.db); |
| 1459 | g.db = 0; |
| 1460 | return n; |
| @@ -1563,16 +1571,16 @@ | |
| 1563 | zRepo[j] = '.'; |
| 1564 | } |
| 1565 | |
| 1566 | if( szFile<1024 ){ |
| 1567 | set_base_url(0); |
| 1568 | if( zNotFound ){ |
| 1569 | cgi_redirect(zNotFound); |
| 1570 | }else if( strcmp(zPathInfo,"/")==0 |
| 1571 | && allowRepoList |
| 1572 | && repo_list_page() ){ |
| 1573 | /* Will return a list of repositories */ |
| 1574 | }else{ |
| 1575 | #ifdef FOSSIL_ENABLE_JSON |
| 1576 | if(g.json.isJsonMode){ |
| 1577 | json_err(FSL_JSON_E_RESOURCE_NOT_FOUND,NULL,1); |
| 1578 | return; |
| @@ -2169,18 +2177,18 @@ | |
| 2169 | zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */ |
| 2170 | cgi_replace_parameter("HTTPS","on"); |
| 2171 | } |
| 2172 | zHost = find_option("host", 0, 1); |
| 2173 | if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost); |
| 2174 | g.cgiOutput = 1; |
| 2175 | |
| 2176 | /* We should be done with options.. */ |
| 2177 | verify_all_options(); |
| 2178 | |
| 2179 | if( g.argc!=2 && g.argc!=3 && g.argc!=5 && g.argc!=6 ){ |
| 2180 | fossil_fatal("no repository specified"); |
| 2181 | } |
| 2182 | g.fullHttpReply = 1; |
| 2183 | if( g.argc>=5 ){ |
| 2184 | g.httpIn = fossil_fopen(g.argv[2], "rb"); |
| 2185 | g.httpOut = fossil_fopen(g.argv[3], "wb"); |
| 2186 | zIpAddr = g.argv[4]; |
| 2187 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -135,10 +135,11 @@ | |
| 135 | char *zRepositoryOption; /* Most recent cached repository option value */ |
| 136 | char *zRepositoryName; /* Name of the repository database */ |
| 137 | char *zLocalDbName; /* Name of the local database */ |
| 138 | const char *zMainDbType;/* "configdb", "localdb", or "repository" */ |
| 139 | const char *zConfigDbType; /* "configdb", "localdb", or "repository" */ |
| 140 | char *zOpenRevision; /* Check-in version to use during database open */ |
| 141 | int localOpen; /* True if the local database is open */ |
| 142 | char *zLocalRoot; /* The directory holding the local database */ |
| 143 | int minPrefix; /* Number of digits needed for a distinct UUID */ |
| 144 | int fSqlTrace; /* True if --sqltrace flag is present */ |
| 145 | int fSqlStats; /* True if --sqltrace or --sqlstats are present */ |
| @@ -1441,20 +1442,27 @@ | |
| 1442 | vfile_scan(&base, blob_size(&base), 0, 0, 0); |
| 1443 | db_multi_exec("DELETE FROM sfile WHERE x NOT GLOB '*.fossil'"); |
| 1444 | n = db_int(0, "SELECT count(*) FROM sfile"); |
| 1445 | if( n>0 ){ |
| 1446 | Stmt q; |
| 1447 | @ <html> |
| 1448 | @ <head> |
| 1449 | @ <title>Repository List</title> |
| 1450 | @ </head> |
| 1451 | @ <body> |
| 1452 | @ <h1>Available Repositories:</h1> |
| 1453 | @ <ol> |
| 1454 | db_prepare(&q, "SELECT x, substr(x,-7,-100000)||'/home'" |
| 1455 | " FROM sfile ORDER BY x COLLATE nocase;"); |
| 1456 | while( db_step(&q)==SQLITE_ROW ){ |
| 1457 | const char *zName = db_column_text(&q, 0); |
| 1458 | const char *zUrl = db_column_text(&q, 1); |
| 1459 | @ <li><a href="%h(zUrl)" target="_blank">%h(zName)</a></li> |
| 1460 | } |
| 1461 | @ </ol> |
| 1462 | @ </body> |
| 1463 | @ </html> |
| 1464 | cgi_reply(); |
| 1465 | } |
| 1466 | sqlite3_close(g.db); |
| 1467 | g.db = 0; |
| 1468 | return n; |
| @@ -1563,16 +1571,16 @@ | |
| 1571 | zRepo[j] = '.'; |
| 1572 | } |
| 1573 | |
| 1574 | if( szFile<1024 ){ |
| 1575 | set_base_url(0); |
| 1576 | if( strcmp(zPathInfo,"/")==0 |
| 1577 | && allowRepoList |
| 1578 | && repo_list_page() ){ |
| 1579 | /* Will return a list of repositories */ |
| 1580 | }else if( zNotFound ){ |
| 1581 | cgi_redirect(zNotFound); |
| 1582 | }else{ |
| 1583 | #ifdef FOSSIL_ENABLE_JSON |
| 1584 | if(g.json.isJsonMode){ |
| 1585 | json_err(FSL_JSON_E_RESOURCE_NOT_FOUND,NULL,1); |
| 1586 | return; |
| @@ -2169,18 +2177,18 @@ | |
| 2177 | zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */ |
| 2178 | cgi_replace_parameter("HTTPS","on"); |
| 2179 | } |
| 2180 | zHost = find_option("host", 0, 1); |
| 2181 | if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost); |
| 2182 | |
| 2183 | /* We should be done with options.. */ |
| 2184 | verify_all_options(); |
| 2185 | |
| 2186 | if( g.argc!=2 && g.argc!=3 && g.argc!=5 && g.argc!=6 ){ |
| 2187 | fossil_fatal("no repository specified"); |
| 2188 | } |
| 2189 | g.cgiOutput = 1; |
| 2190 | g.fullHttpReply = 1; |
| 2191 | if( g.argc>=5 ){ |
| 2192 | g.httpIn = fossil_fopen(g.argv[2], "rb"); |
| 2193 | g.httpOut = fossil_fopen(g.argv[3], "wb"); |
| 2194 | zIpAddr = g.argv[4]; |
| 2195 |
+14
-1
| --- src/main.mk | ||
| +++ src/main.mk | ||
| @@ -84,10 +84,11 @@ | ||
| 84 | 84 | $(SRCDIR)/merge.c \ |
| 85 | 85 | $(SRCDIR)/merge3.c \ |
| 86 | 86 | $(SRCDIR)/moderate.c \ |
| 87 | 87 | $(SRCDIR)/name.c \ |
| 88 | 88 | $(SRCDIR)/path.c \ |
| 89 | + $(SRCDIR)/piechart.c \ | |
| 89 | 90 | $(SRCDIR)/pivot.c \ |
| 90 | 91 | $(SRCDIR)/popen.c \ |
| 91 | 92 | $(SRCDIR)/pqueue.c \ |
| 92 | 93 | $(SRCDIR)/printf.c \ |
| 93 | 94 | $(SRCDIR)/publish.c \ |
| @@ -255,10 +256,11 @@ | ||
| 255 | 256 | $(OBJDIR)/merge_.c \ |
| 256 | 257 | $(OBJDIR)/merge3_.c \ |
| 257 | 258 | $(OBJDIR)/moderate_.c \ |
| 258 | 259 | $(OBJDIR)/name_.c \ |
| 259 | 260 | $(OBJDIR)/path_.c \ |
| 261 | + $(OBJDIR)/piechart_.c \ | |
| 260 | 262 | $(OBJDIR)/pivot_.c \ |
| 261 | 263 | $(OBJDIR)/popen_.c \ |
| 262 | 264 | $(OBJDIR)/pqueue_.c \ |
| 263 | 265 | $(OBJDIR)/printf_.c \ |
| 264 | 266 | $(OBJDIR)/publish_.c \ |
| @@ -375,10 +377,11 @@ | ||
| 375 | 377 | $(OBJDIR)/merge.o \ |
| 376 | 378 | $(OBJDIR)/merge3.o \ |
| 377 | 379 | $(OBJDIR)/moderate.o \ |
| 378 | 380 | $(OBJDIR)/name.o \ |
| 379 | 381 | $(OBJDIR)/path.o \ |
| 382 | + $(OBJDIR)/piechart.o \ | |
| 380 | 383 | $(OBJDIR)/pivot.o \ |
| 381 | 384 | $(OBJDIR)/popen.o \ |
| 382 | 385 | $(OBJDIR)/pqueue.o \ |
| 383 | 386 | $(OBJDIR)/printf.o \ |
| 384 | 387 | $(OBJDIR)/publish.o \ |
| @@ -474,11 +477,12 @@ | ||
| 474 | 477 | -DSQLITE_THREADSAFE=0 \ |
| 475 | 478 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 476 | 479 | -DSQLITE_OMIT_DEPRECATED \ |
| 477 | 480 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 478 | 481 | -DSQLITE_ENABLE_FTS4 \ |
| 479 | - -DSQLITE_ENABLE_FTS3_PARENTHESIS | |
| 482 | + -DSQLITE_ENABLE_FTS3_PARENTHESIS \ | |
| 483 | + -DSQLITE_ENABLE_DBSTAT_VTAB | |
| 480 | 484 | |
| 481 | 485 | # Setup the options used to compile the included SQLite shell. |
| 482 | 486 | SHELL_OPTIONS = -Dmain=sqlite3_shell \ |
| 483 | 487 | -DSQLITE_OMIT_LOAD_EXTENSION=1 \ |
| 484 | 488 | -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \ |
| @@ -606,10 +610,11 @@ | ||
| 606 | 610 | $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \ |
| 607 | 611 | $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \ |
| 608 | 612 | $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \ |
| 609 | 613 | $(OBJDIR)/name_.c:$(OBJDIR)/name.h \ |
| 610 | 614 | $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ |
| 615 | + $(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \ | |
| 611 | 616 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 612 | 617 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 613 | 618 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 614 | 619 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 615 | 620 | $(OBJDIR)/publish_.c:$(OBJDIR)/publish.h \ |
| @@ -1234,10 +1239,18 @@ | ||
| 1234 | 1239 | |
| 1235 | 1240 | $(OBJDIR)/path.o: $(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h |
| 1236 | 1241 | $(XTCC) -o $(OBJDIR)/path.o -c $(OBJDIR)/path_.c |
| 1237 | 1242 | |
| 1238 | 1243 | $(OBJDIR)/path.h: $(OBJDIR)/headers |
| 1244 | + | |
| 1245 | +$(OBJDIR)/piechart_.c: $(SRCDIR)/piechart.c $(OBJDIR)/translate | |
| 1246 | + $(OBJDIR)/translate $(SRCDIR)/piechart.c >$@ | |
| 1247 | + | |
| 1248 | +$(OBJDIR)/piechart.o: $(OBJDIR)/piechart_.c $(OBJDIR)/piechart.h $(SRCDIR)/config.h | |
| 1249 | + $(XTCC) -o $(OBJDIR)/piechart.o -c $(OBJDIR)/piechart_.c | |
| 1250 | + | |
| 1251 | +$(OBJDIR)/piechart.h: $(OBJDIR)/headers | |
| 1239 | 1252 | |
| 1240 | 1253 | $(OBJDIR)/pivot_.c: $(SRCDIR)/pivot.c $(OBJDIR)/translate |
| 1241 | 1254 | $(OBJDIR)/translate $(SRCDIR)/pivot.c >$@ |
| 1242 | 1255 | |
| 1243 | 1256 | $(OBJDIR)/pivot.o: $(OBJDIR)/pivot_.c $(OBJDIR)/pivot.h $(SRCDIR)/config.h |
| 1244 | 1257 |
| --- src/main.mk | |
| +++ src/main.mk | |
| @@ -84,10 +84,11 @@ | |
| 84 | $(SRCDIR)/merge.c \ |
| 85 | $(SRCDIR)/merge3.c \ |
| 86 | $(SRCDIR)/moderate.c \ |
| 87 | $(SRCDIR)/name.c \ |
| 88 | $(SRCDIR)/path.c \ |
| 89 | $(SRCDIR)/pivot.c \ |
| 90 | $(SRCDIR)/popen.c \ |
| 91 | $(SRCDIR)/pqueue.c \ |
| 92 | $(SRCDIR)/printf.c \ |
| 93 | $(SRCDIR)/publish.c \ |
| @@ -255,10 +256,11 @@ | |
| 255 | $(OBJDIR)/merge_.c \ |
| 256 | $(OBJDIR)/merge3_.c \ |
| 257 | $(OBJDIR)/moderate_.c \ |
| 258 | $(OBJDIR)/name_.c \ |
| 259 | $(OBJDIR)/path_.c \ |
| 260 | $(OBJDIR)/pivot_.c \ |
| 261 | $(OBJDIR)/popen_.c \ |
| 262 | $(OBJDIR)/pqueue_.c \ |
| 263 | $(OBJDIR)/printf_.c \ |
| 264 | $(OBJDIR)/publish_.c \ |
| @@ -375,10 +377,11 @@ | |
| 375 | $(OBJDIR)/merge.o \ |
| 376 | $(OBJDIR)/merge3.o \ |
| 377 | $(OBJDIR)/moderate.o \ |
| 378 | $(OBJDIR)/name.o \ |
| 379 | $(OBJDIR)/path.o \ |
| 380 | $(OBJDIR)/pivot.o \ |
| 381 | $(OBJDIR)/popen.o \ |
| 382 | $(OBJDIR)/pqueue.o \ |
| 383 | $(OBJDIR)/printf.o \ |
| 384 | $(OBJDIR)/publish.o \ |
| @@ -474,11 +477,12 @@ | |
| 474 | -DSQLITE_THREADSAFE=0 \ |
| 475 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 476 | -DSQLITE_OMIT_DEPRECATED \ |
| 477 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 478 | -DSQLITE_ENABLE_FTS4 \ |
| 479 | -DSQLITE_ENABLE_FTS3_PARENTHESIS |
| 480 | |
| 481 | # Setup the options used to compile the included SQLite shell. |
| 482 | SHELL_OPTIONS = -Dmain=sqlite3_shell \ |
| 483 | -DSQLITE_OMIT_LOAD_EXTENSION=1 \ |
| 484 | -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \ |
| @@ -606,10 +610,11 @@ | |
| 606 | $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \ |
| 607 | $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \ |
| 608 | $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \ |
| 609 | $(OBJDIR)/name_.c:$(OBJDIR)/name.h \ |
| 610 | $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ |
| 611 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 612 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 613 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 614 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 615 | $(OBJDIR)/publish_.c:$(OBJDIR)/publish.h \ |
| @@ -1234,10 +1239,18 @@ | |
| 1234 | |
| 1235 | $(OBJDIR)/path.o: $(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h |
| 1236 | $(XTCC) -o $(OBJDIR)/path.o -c $(OBJDIR)/path_.c |
| 1237 | |
| 1238 | $(OBJDIR)/path.h: $(OBJDIR)/headers |
| 1239 | |
| 1240 | $(OBJDIR)/pivot_.c: $(SRCDIR)/pivot.c $(OBJDIR)/translate |
| 1241 | $(OBJDIR)/translate $(SRCDIR)/pivot.c >$@ |
| 1242 | |
| 1243 | $(OBJDIR)/pivot.o: $(OBJDIR)/pivot_.c $(OBJDIR)/pivot.h $(SRCDIR)/config.h |
| 1244 |
| --- src/main.mk | |
| +++ src/main.mk | |
| @@ -84,10 +84,11 @@ | |
| 84 | $(SRCDIR)/merge.c \ |
| 85 | $(SRCDIR)/merge3.c \ |
| 86 | $(SRCDIR)/moderate.c \ |
| 87 | $(SRCDIR)/name.c \ |
| 88 | $(SRCDIR)/path.c \ |
| 89 | $(SRCDIR)/piechart.c \ |
| 90 | $(SRCDIR)/pivot.c \ |
| 91 | $(SRCDIR)/popen.c \ |
| 92 | $(SRCDIR)/pqueue.c \ |
| 93 | $(SRCDIR)/printf.c \ |
| 94 | $(SRCDIR)/publish.c \ |
| @@ -255,10 +256,11 @@ | |
| 256 | $(OBJDIR)/merge_.c \ |
| 257 | $(OBJDIR)/merge3_.c \ |
| 258 | $(OBJDIR)/moderate_.c \ |
| 259 | $(OBJDIR)/name_.c \ |
| 260 | $(OBJDIR)/path_.c \ |
| 261 | $(OBJDIR)/piechart_.c \ |
| 262 | $(OBJDIR)/pivot_.c \ |
| 263 | $(OBJDIR)/popen_.c \ |
| 264 | $(OBJDIR)/pqueue_.c \ |
| 265 | $(OBJDIR)/printf_.c \ |
| 266 | $(OBJDIR)/publish_.c \ |
| @@ -375,10 +377,11 @@ | |
| 377 | $(OBJDIR)/merge.o \ |
| 378 | $(OBJDIR)/merge3.o \ |
| 379 | $(OBJDIR)/moderate.o \ |
| 380 | $(OBJDIR)/name.o \ |
| 381 | $(OBJDIR)/path.o \ |
| 382 | $(OBJDIR)/piechart.o \ |
| 383 | $(OBJDIR)/pivot.o \ |
| 384 | $(OBJDIR)/popen.o \ |
| 385 | $(OBJDIR)/pqueue.o \ |
| 386 | $(OBJDIR)/printf.o \ |
| 387 | $(OBJDIR)/publish.o \ |
| @@ -474,11 +477,12 @@ | |
| 477 | -DSQLITE_THREADSAFE=0 \ |
| 478 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 479 | -DSQLITE_OMIT_DEPRECATED \ |
| 480 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 481 | -DSQLITE_ENABLE_FTS4 \ |
| 482 | -DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 483 | -DSQLITE_ENABLE_DBSTAT_VTAB |
| 484 | |
| 485 | # Setup the options used to compile the included SQLite shell. |
| 486 | SHELL_OPTIONS = -Dmain=sqlite3_shell \ |
| 487 | -DSQLITE_OMIT_LOAD_EXTENSION=1 \ |
| 488 | -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \ |
| @@ -606,10 +610,11 @@ | |
| 610 | $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \ |
| 611 | $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \ |
| 612 | $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \ |
| 613 | $(OBJDIR)/name_.c:$(OBJDIR)/name.h \ |
| 614 | $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ |
| 615 | $(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \ |
| 616 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 617 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 618 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 619 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 620 | $(OBJDIR)/publish_.c:$(OBJDIR)/publish.h \ |
| @@ -1234,10 +1239,18 @@ | |
| 1239 | |
| 1240 | $(OBJDIR)/path.o: $(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h |
| 1241 | $(XTCC) -o $(OBJDIR)/path.o -c $(OBJDIR)/path_.c |
| 1242 | |
| 1243 | $(OBJDIR)/path.h: $(OBJDIR)/headers |
| 1244 | |
| 1245 | $(OBJDIR)/piechart_.c: $(SRCDIR)/piechart.c $(OBJDIR)/translate |
| 1246 | $(OBJDIR)/translate $(SRCDIR)/piechart.c >$@ |
| 1247 | |
| 1248 | $(OBJDIR)/piechart.o: $(OBJDIR)/piechart_.c $(OBJDIR)/piechart.h $(SRCDIR)/config.h |
| 1249 | $(XTCC) -o $(OBJDIR)/piechart.o -c $(OBJDIR)/piechart_.c |
| 1250 | |
| 1251 | $(OBJDIR)/piechart.h: $(OBJDIR)/headers |
| 1252 | |
| 1253 | $(OBJDIR)/pivot_.c: $(SRCDIR)/pivot.c $(OBJDIR)/translate |
| 1254 | $(OBJDIR)/translate $(SRCDIR)/pivot.c >$@ |
| 1255 | |
| 1256 | $(OBJDIR)/pivot.o: $(OBJDIR)/pivot_.c $(OBJDIR)/pivot.h $(SRCDIR)/config.h |
| 1257 |
+2
| --- src/makemake.tcl | ||
| +++ src/makemake.tcl | ||
| @@ -90,10 +90,11 @@ | ||
| 90 | 90 | merge |
| 91 | 91 | merge3 |
| 92 | 92 | moderate |
| 93 | 93 | name |
| 94 | 94 | path |
| 95 | + piechart | |
| 95 | 96 | pivot |
| 96 | 97 | popen |
| 97 | 98 | pqueue |
| 98 | 99 | printf |
| 99 | 100 | publish |
| @@ -159,10 +160,11 @@ | ||
| 159 | 160 | -DSQLITE_DEFAULT_FILE_FORMAT=4 |
| 160 | 161 | -DSQLITE_OMIT_DEPRECATED |
| 161 | 162 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS |
| 162 | 163 | -DSQLITE_ENABLE_FTS4 |
| 163 | 164 | -DSQLITE_ENABLE_FTS3_PARENTHESIS |
| 165 | + -DSQLITE_ENABLE_DBSTAT_VTAB | |
| 164 | 166 | } |
| 165 | 167 | #lappend SQLITE_OPTIONS -DSQLITE_ENABLE_FTS3=1 |
| 166 | 168 | #lappend SQLITE_OPTIONS -DSQLITE_ENABLE_STAT4 |
| 167 | 169 | #lappend SQLITE_OPTIONS -DSQLITE_WIN32_NO_ANSI |
| 168 | 170 | #lappend SQLITE_OPTIONS -DSQLITE_WINNT_MAX_PATH_CHARS=4096 |
| 169 | 171 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -90,10 +90,11 @@ | |
| 90 | merge |
| 91 | merge3 |
| 92 | moderate |
| 93 | name |
| 94 | path |
| 95 | pivot |
| 96 | popen |
| 97 | pqueue |
| 98 | printf |
| 99 | publish |
| @@ -159,10 +160,11 @@ | |
| 159 | -DSQLITE_DEFAULT_FILE_FORMAT=4 |
| 160 | -DSQLITE_OMIT_DEPRECATED |
| 161 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS |
| 162 | -DSQLITE_ENABLE_FTS4 |
| 163 | -DSQLITE_ENABLE_FTS3_PARENTHESIS |
| 164 | } |
| 165 | #lappend SQLITE_OPTIONS -DSQLITE_ENABLE_FTS3=1 |
| 166 | #lappend SQLITE_OPTIONS -DSQLITE_ENABLE_STAT4 |
| 167 | #lappend SQLITE_OPTIONS -DSQLITE_WIN32_NO_ANSI |
| 168 | #lappend SQLITE_OPTIONS -DSQLITE_WINNT_MAX_PATH_CHARS=4096 |
| 169 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -90,10 +90,11 @@ | |
| 90 | merge |
| 91 | merge3 |
| 92 | moderate |
| 93 | name |
| 94 | path |
| 95 | piechart |
| 96 | pivot |
| 97 | popen |
| 98 | pqueue |
| 99 | printf |
| 100 | publish |
| @@ -159,10 +160,11 @@ | |
| 160 | -DSQLITE_DEFAULT_FILE_FORMAT=4 |
| 161 | -DSQLITE_OMIT_DEPRECATED |
| 162 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS |
| 163 | -DSQLITE_ENABLE_FTS4 |
| 164 | -DSQLITE_ENABLE_FTS3_PARENTHESIS |
| 165 | -DSQLITE_ENABLE_DBSTAT_VTAB |
| 166 | } |
| 167 | #lappend SQLITE_OPTIONS -DSQLITE_ENABLE_FTS3=1 |
| 168 | #lappend SQLITE_OPTIONS -DSQLITE_ENABLE_STAT4 |
| 169 | #lappend SQLITE_OPTIONS -DSQLITE_WIN32_NO_ANSI |
| 170 | #lappend SQLITE_OPTIONS -DSQLITE_WINNT_MAX_PATH_CHARS=4096 |
| 171 |
+56
-56
| --- src/markdown_html.c | ||
| +++ src/markdown_html.c | ||
| @@ -34,16 +34,16 @@ | ||
| 34 | 34 | |
| 35 | 35 | /* INTER_BLOCK -- skip a line between block level elements */ |
| 36 | 36 | #define INTER_BLOCK(ob) \ |
| 37 | 37 | do { if( blob_size(ob)>0 ) blob_append(ob, "\n", 1); } while (0) |
| 38 | 38 | |
| 39 | -/* BLOB_APPEND_LITTERAL -- append a string litteral to a blob */ | |
| 40 | -#define BLOB_APPEND_LITTERAL(blob, litteral) \ | |
| 41 | - blob_append((blob), "" litteral, (sizeof litteral)-1) | |
| 39 | +/* BLOB_APPEND_LITERAL -- append a string literal to a blob */ | |
| 40 | +#define BLOB_APPEND_LITERAL(blob, literal) \ | |
| 41 | + blob_append((blob), "" literal, (sizeof literal)-1) | |
| 42 | 42 | /* |
| 43 | 43 | * The empty string in the second argument leads to a syntax error |
| 44 | - * when the macro is not used with a string litteral. Unfortunately | |
| 44 | + * when the macro is not used with a string literal. Unfortunately | |
| 45 | 45 | * the error is not overly explicit. |
| 46 | 46 | */ |
| 47 | 47 | |
| 48 | 48 | /* BLOB_APPEND_BLOB -- append blob contents to another */ |
| 49 | 49 | #define BLOB_APPEND_BLOB(dest, src) \ |
| @@ -65,17 +65,17 @@ | ||
| 65 | 65 | i++; |
| 66 | 66 | } |
| 67 | 67 | blob_append(ob, data+beg, i-beg); |
| 68 | 68 | while( i<size ){ |
| 69 | 69 | if( data[i]=='<' ){ |
| 70 | - BLOB_APPEND_LITTERAL(ob, "<"); | |
| 70 | + BLOB_APPEND_LITERAL(ob, "<"); | |
| 71 | 71 | }else if( data[i]=='>' ){ |
| 72 | - BLOB_APPEND_LITTERAL(ob, ">"); | |
| 72 | + BLOB_APPEND_LITERAL(ob, ">"); | |
| 73 | 73 | }else if( data[i]=='&' ){ |
| 74 | - BLOB_APPEND_LITTERAL(ob, "&"); | |
| 74 | + BLOB_APPEND_LITERAL(ob, "&"); | |
| 75 | 75 | }else if( data[i]=='"' ){ |
| 76 | - BLOB_APPEND_LITTERAL(ob, """); | |
| 76 | + BLOB_APPEND_LITERAL(ob, """); | |
| 77 | 77 | }else{ |
| 78 | 78 | break; |
| 79 | 79 | } |
| 80 | 80 | i++; |
| 81 | 81 | } |
| @@ -88,41 +88,41 @@ | ||
| 88 | 88 | /* Size of the prolog: "<div class='markdown'>\n" */ |
| 89 | 89 | #define PROLOG_SIZE 23 |
| 90 | 90 | |
| 91 | 91 | static void html_prolog(struct Blob *ob, void *opaque){ |
| 92 | 92 | INTER_BLOCK(ob); |
| 93 | - BLOB_APPEND_LITTERAL(ob, "<div class=\"markdown\">\n"); | |
| 93 | + BLOB_APPEND_LITERAL(ob, "<div class=\"markdown\">\n"); | |
| 94 | 94 | assert( blob_size(ob)==PROLOG_SIZE ); |
| 95 | 95 | } |
| 96 | 96 | |
| 97 | 97 | static void html_epilog(struct Blob *ob, void *opaque){ |
| 98 | 98 | INTER_BLOCK(ob); |
| 99 | - BLOB_APPEND_LITTERAL(ob, "</div>\n"); | |
| 99 | + BLOB_APPEND_LITERAL(ob, "</div>\n"); | |
| 100 | 100 | } |
| 101 | 101 | |
| 102 | 102 | static void html_raw_block(struct Blob *ob, struct Blob *text, void *opaque){ |
| 103 | 103 | char *data = blob_buffer(text); |
| 104 | 104 | size_t first = 0, size = blob_size(text); |
| 105 | 105 | INTER_BLOCK(ob); |
| 106 | 106 | while( first<size && data[first]=='\n' ) first++; |
| 107 | 107 | while( size>first && data[size-1]=='\n' ) size--; |
| 108 | 108 | blob_append(ob, data+first, size-first); |
| 109 | - BLOB_APPEND_LITTERAL(ob, "\n"); | |
| 109 | + BLOB_APPEND_LITERAL(ob, "\n"); | |
| 110 | 110 | } |
| 111 | 111 | |
| 112 | 112 | static void html_blockcode(struct Blob *ob, struct Blob *text, void *opaque){ |
| 113 | 113 | INTER_BLOCK(ob); |
| 114 | - BLOB_APPEND_LITTERAL(ob, "<pre><code>"); | |
| 114 | + BLOB_APPEND_LITERAL(ob, "<pre><code>"); | |
| 115 | 115 | html_escape(ob, blob_buffer(text), blob_size(text)); |
| 116 | - BLOB_APPEND_LITTERAL(ob, "</code></pre>\n"); | |
| 116 | + BLOB_APPEND_LITERAL(ob, "</code></pre>\n"); | |
| 117 | 117 | } |
| 118 | 118 | |
| 119 | 119 | static void html_blockquote(struct Blob *ob, struct Blob *text, void *opaque){ |
| 120 | 120 | INTER_BLOCK(ob); |
| 121 | - BLOB_APPEND_LITTERAL(ob, "<blockquote>\n"); | |
| 121 | + BLOB_APPEND_LITERAL(ob, "<blockquote>\n"); | |
| 122 | 122 | BLOB_APPEND_BLOB(ob, text); |
| 123 | - BLOB_APPEND_LITTERAL(ob, "</blockquote>\n"); | |
| 123 | + BLOB_APPEND_LITERAL(ob, "</blockquote>\n"); | |
| 124 | 124 | } |
| 125 | 125 | |
| 126 | 126 | static void html_header( |
| 127 | 127 | struct Blob *ob, |
| 128 | 128 | struct Blob *text, |
| @@ -141,11 +141,11 @@ | ||
| 141 | 141 | blob_appendf(ob, "</h%d>", level); |
| 142 | 142 | } |
| 143 | 143 | |
| 144 | 144 | static void html_hrule(struct Blob *ob, void *opaque){ |
| 145 | 145 | INTER_BLOCK(ob); |
| 146 | - BLOB_APPEND_LITTERAL(ob, "<hr />\n"); | |
| 146 | + BLOB_APPEND_LITERAL(ob, "<hr />\n"); | |
| 147 | 147 | } |
| 148 | 148 | |
| 149 | 149 | |
| 150 | 150 | static void html_list( |
| 151 | 151 | struct Blob *ob, |
| @@ -169,20 +169,20 @@ | ||
| 169 | 169 | void *opaque |
| 170 | 170 | ){ |
| 171 | 171 | char *text_data = blob_buffer(text); |
| 172 | 172 | size_t text_size = blob_size(text); |
| 173 | 173 | while( text_size>0 && text_data[text_size-1]=='\n' ) text_size--; |
| 174 | - BLOB_APPEND_LITTERAL(ob, "<li>"); | |
| 174 | + BLOB_APPEND_LITERAL(ob, "<li>"); | |
| 175 | 175 | blob_append(ob, text_data, text_size); |
| 176 | - BLOB_APPEND_LITTERAL(ob, "</li>\n"); | |
| 176 | + BLOB_APPEND_LITERAL(ob, "</li>\n"); | |
| 177 | 177 | } |
| 178 | 178 | |
| 179 | 179 | static void html_paragraph(struct Blob *ob, struct Blob *text, void *opaque){ |
| 180 | 180 | INTER_BLOCK(ob); |
| 181 | - BLOB_APPEND_LITTERAL(ob, "<p>"); | |
| 181 | + BLOB_APPEND_LITERAL(ob, "<p>"); | |
| 182 | 182 | BLOB_APPEND_BLOB(ob, text); |
| 183 | - BLOB_APPEND_LITTERAL(ob, "</p>\n"); | |
| 183 | + BLOB_APPEND_LITERAL(ob, "</p>\n"); | |
| 184 | 184 | } |
| 185 | 185 | |
| 186 | 186 | |
| 187 | 187 | static void html_table( |
| 188 | 188 | struct Blob *ob, |
| @@ -189,68 +189,68 @@ | ||
| 189 | 189 | struct Blob *head_row, |
| 190 | 190 | struct Blob *rows, |
| 191 | 191 | void *opaque |
| 192 | 192 | ){ |
| 193 | 193 | INTER_BLOCK(ob); |
| 194 | - BLOB_APPEND_LITTERAL(ob, "<table>\n"); | |
| 194 | + BLOB_APPEND_LITERAL(ob, "<table>\n"); | |
| 195 | 195 | if( head_row && blob_size(head_row)>0 ){ |
| 196 | - BLOB_APPEND_LITTERAL(ob, "<thead>\n"); | |
| 196 | + BLOB_APPEND_LITERAL(ob, "<thead>\n"); | |
| 197 | 197 | BLOB_APPEND_BLOB(ob, head_row); |
| 198 | - BLOB_APPEND_LITTERAL(ob, "</thead>\n<tbody>\n"); | |
| 198 | + BLOB_APPEND_LITERAL(ob, "</thead>\n<tbody>\n"); | |
| 199 | 199 | } |
| 200 | 200 | if( rows ){ |
| 201 | 201 | BLOB_APPEND_BLOB(ob, rows); |
| 202 | 202 | } |
| 203 | 203 | if( head_row && blob_size(head_row)>0 ){ |
| 204 | - BLOB_APPEND_LITTERAL(ob, "</tbody>\n"); | |
| 204 | + BLOB_APPEND_LITERAL(ob, "</tbody>\n"); | |
| 205 | 205 | } |
| 206 | - BLOB_APPEND_LITTERAL(ob, "</table>\n"); | |
| 206 | + BLOB_APPEND_LITERAL(ob, "</table>\n"); | |
| 207 | 207 | } |
| 208 | 208 | |
| 209 | 209 | static void html_table_cell( |
| 210 | 210 | struct Blob *ob, |
| 211 | 211 | struct Blob *text, |
| 212 | 212 | int flags, |
| 213 | 213 | void *opaque |
| 214 | 214 | ){ |
| 215 | 215 | if( flags & MKD_CELL_HEAD ){ |
| 216 | - BLOB_APPEND_LITTERAL(ob, " <th"); | |
| 216 | + BLOB_APPEND_LITERAL(ob, " <th"); | |
| 217 | 217 | }else{ |
| 218 | - BLOB_APPEND_LITTERAL(ob, " <td"); | |
| 218 | + BLOB_APPEND_LITERAL(ob, " <td"); | |
| 219 | 219 | } |
| 220 | 220 | switch( flags & MKD_CELL_ALIGN_MASK ){ |
| 221 | 221 | case MKD_CELL_ALIGN_LEFT: { |
| 222 | - BLOB_APPEND_LITTERAL(ob, " align=\"left\""); | |
| 222 | + BLOB_APPEND_LITERAL(ob, " align=\"left\""); | |
| 223 | 223 | break; |
| 224 | 224 | } |
| 225 | 225 | case MKD_CELL_ALIGN_RIGHT: { |
| 226 | - BLOB_APPEND_LITTERAL(ob, " align=\"right\""); | |
| 226 | + BLOB_APPEND_LITERAL(ob, " align=\"right\""); | |
| 227 | 227 | break; |
| 228 | 228 | } |
| 229 | 229 | case MKD_CELL_ALIGN_CENTER: { |
| 230 | - BLOB_APPEND_LITTERAL(ob, " align=\"center\""); | |
| 230 | + BLOB_APPEND_LITERAL(ob, " align=\"center\""); | |
| 231 | 231 | break; |
| 232 | 232 | } |
| 233 | 233 | } |
| 234 | - BLOB_APPEND_LITTERAL(ob, ">"); | |
| 234 | + BLOB_APPEND_LITERAL(ob, ">"); | |
| 235 | 235 | BLOB_APPEND_BLOB(ob, text); |
| 236 | 236 | if( flags & MKD_CELL_HEAD ){ |
| 237 | - BLOB_APPEND_LITTERAL(ob, "</th>\n"); | |
| 237 | + BLOB_APPEND_LITERAL(ob, "</th>\n"); | |
| 238 | 238 | }else{ |
| 239 | - BLOB_APPEND_LITTERAL(ob, "</td>\n"); | |
| 239 | + BLOB_APPEND_LITERAL(ob, "</td>\n"); | |
| 240 | 240 | } |
| 241 | 241 | } |
| 242 | 242 | |
| 243 | 243 | static void html_table_row( |
| 244 | 244 | struct Blob *ob, |
| 245 | 245 | struct Blob *cells, |
| 246 | 246 | int flags, |
| 247 | 247 | void *opaque |
| 248 | 248 | ){ |
| 249 | - BLOB_APPEND_LITTERAL(ob, " <tr>\n"); | |
| 249 | + BLOB_APPEND_LITERAL(ob, " <tr>\n"); | |
| 250 | 250 | BLOB_APPEND_BLOB(ob, cells); |
| 251 | - BLOB_APPEND_LITTERAL(ob, " </tr>\n"); | |
| 251 | + BLOB_APPEND_LITERAL(ob, " </tr>\n"); | |
| 252 | 252 | } |
| 253 | 253 | |
| 254 | 254 | |
| 255 | 255 | |
| 256 | 256 | /* HTML span tags */ |
| @@ -265,52 +265,52 @@ | ||
| 265 | 265 | struct Blob *link, |
| 266 | 266 | enum mkd_autolink type, |
| 267 | 267 | void *opaque |
| 268 | 268 | ){ |
| 269 | 269 | if( !link || blob_size(link)<=0 ) return 0; |
| 270 | - BLOB_APPEND_LITTERAL(ob, "<a href=\""); | |
| 271 | - if( type==MKDA_IMPLICIT_EMAIL ) BLOB_APPEND_LITTERAL(ob, "mailto:"); | |
| 270 | + BLOB_APPEND_LITERAL(ob, "<a href=\""); | |
| 271 | + if( type==MKDA_IMPLICIT_EMAIL ) BLOB_APPEND_LITERAL(ob, "mailto:"); | |
| 272 | 272 | html_escape(ob, blob_buffer(link), blob_size(link)); |
| 273 | - BLOB_APPEND_LITTERAL(ob, "\">"); | |
| 273 | + BLOB_APPEND_LITERAL(ob, "\">"); | |
| 274 | 274 | if( type==MKDA_EXPLICIT_EMAIL && blob_size(link)>7 ){ |
| 275 | 275 | /* remove "mailto:" from displayed text */ |
| 276 | 276 | html_escape(ob, blob_buffer(link)+7, blob_size(link)-7); |
| 277 | 277 | }else{ |
| 278 | 278 | html_escape(ob, blob_buffer(link), blob_size(link)); |
| 279 | 279 | } |
| 280 | - BLOB_APPEND_LITTERAL(ob, "</a>"); | |
| 280 | + BLOB_APPEND_LITERAL(ob, "</a>"); | |
| 281 | 281 | return 1; |
| 282 | 282 | } |
| 283 | 283 | |
| 284 | 284 | static int html_code_span(struct Blob *ob, struct Blob *text, void *opaque){ |
| 285 | - BLOB_APPEND_LITTERAL(ob, "<code>"); | |
| 285 | + BLOB_APPEND_LITERAL(ob, "<code>"); | |
| 286 | 286 | html_escape(ob, blob_buffer(text), blob_size(text)); |
| 287 | - BLOB_APPEND_LITTERAL(ob, "</code>"); | |
| 287 | + BLOB_APPEND_LITERAL(ob, "</code>"); | |
| 288 | 288 | return 1; |
| 289 | 289 | } |
| 290 | 290 | |
| 291 | 291 | static int html_double_emphasis( |
| 292 | 292 | struct Blob *ob, |
| 293 | 293 | struct Blob *text, |
| 294 | 294 | char c, |
| 295 | 295 | void *opaque |
| 296 | 296 | ){ |
| 297 | - BLOB_APPEND_LITTERAL(ob, "<strong>"); | |
| 297 | + BLOB_APPEND_LITERAL(ob, "<strong>"); | |
| 298 | 298 | BLOB_APPEND_BLOB(ob, text); |
| 299 | - BLOB_APPEND_LITTERAL(ob, "</strong>"); | |
| 299 | + BLOB_APPEND_LITERAL(ob, "</strong>"); | |
| 300 | 300 | return 1; |
| 301 | 301 | } |
| 302 | 302 | |
| 303 | 303 | static int html_emphasis( |
| 304 | 304 | struct Blob *ob, |
| 305 | 305 | struct Blob *text, |
| 306 | 306 | char c, |
| 307 | 307 | void *opaque |
| 308 | 308 | ){ |
| 309 | - BLOB_APPEND_LITTERAL(ob, "<em>"); | |
| 309 | + BLOB_APPEND_LITERAL(ob, "<em>"); | |
| 310 | 310 | BLOB_APPEND_BLOB(ob, text); |
| 311 | - BLOB_APPEND_LITTERAL(ob, "</em>"); | |
| 311 | + BLOB_APPEND_LITERAL(ob, "</em>"); | |
| 312 | 312 | return 1; |
| 313 | 313 | } |
| 314 | 314 | |
| 315 | 315 | static int html_image( |
| 316 | 316 | struct Blob *ob, |
| @@ -317,24 +317,24 @@ | ||
| 317 | 317 | struct Blob *link, |
| 318 | 318 | struct Blob *title, |
| 319 | 319 | struct Blob *alt, |
| 320 | 320 | void *opaque |
| 321 | 321 | ){ |
| 322 | - BLOB_APPEND_LITTERAL(ob, "<img src=\""); | |
| 322 | + BLOB_APPEND_LITERAL(ob, "<img src=\""); | |
| 323 | 323 | html_escape(ob, blob_buffer(link), blob_size(link)); |
| 324 | - BLOB_APPEND_LITTERAL(ob, "\" alt=\""); | |
| 324 | + BLOB_APPEND_LITERAL(ob, "\" alt=\""); | |
| 325 | 325 | html_escape(ob, blob_buffer(alt), blob_size(alt)); |
| 326 | 326 | if( title && blob_size(title)>0 ){ |
| 327 | - BLOB_APPEND_LITTERAL(ob, "\" title=\""); | |
| 327 | + BLOB_APPEND_LITERAL(ob, "\" title=\""); | |
| 328 | 328 | html_escape(ob, blob_buffer(title), blob_size(title)); |
| 329 | 329 | } |
| 330 | - BLOB_APPEND_LITTERAL(ob, "\" />"); | |
| 330 | + BLOB_APPEND_LITERAL(ob, "\" />"); | |
| 331 | 331 | return 1; |
| 332 | 332 | } |
| 333 | 333 | |
| 334 | 334 | static int html_line_break(struct Blob *ob, void *opaque){ |
| 335 | - BLOB_APPEND_LITTERAL(ob, "<br />\n"); | |
| 335 | + BLOB_APPEND_LITERAL(ob, "<br />\n"); | |
| 336 | 336 | return 1; |
| 337 | 337 | } |
| 338 | 338 | |
| 339 | 339 | static int html_link( |
| 340 | 340 | struct Blob *ob, |
| @@ -341,31 +341,31 @@ | ||
| 341 | 341 | struct Blob *link, |
| 342 | 342 | struct Blob *title, |
| 343 | 343 | struct Blob *content, |
| 344 | 344 | void *opaque |
| 345 | 345 | ){ |
| 346 | - BLOB_APPEND_LITTERAL(ob, "<a href=\""); | |
| 346 | + BLOB_APPEND_LITERAL(ob, "<a href=\""); | |
| 347 | 347 | html_escape(ob, blob_buffer(link), blob_size(link)); |
| 348 | 348 | if( title && blob_size(title)>0 ){ |
| 349 | - BLOB_APPEND_LITTERAL(ob, "\" title=\""); | |
| 349 | + BLOB_APPEND_LITERAL(ob, "\" title=\""); | |
| 350 | 350 | html_escape(ob, blob_buffer(title), blob_size(title)); |
| 351 | 351 | } |
| 352 | - BLOB_APPEND_LITTERAL(ob, "\">"); | |
| 352 | + BLOB_APPEND_LITERAL(ob, "\">"); | |
| 353 | 353 | BLOB_APPEND_BLOB(ob, content); |
| 354 | - BLOB_APPEND_LITTERAL(ob, "</a>"); | |
| 354 | + BLOB_APPEND_LITERAL(ob, "</a>"); | |
| 355 | 355 | return 1; |
| 356 | 356 | } |
| 357 | 357 | |
| 358 | 358 | static int html_triple_emphasis( |
| 359 | 359 | struct Blob *ob, |
| 360 | 360 | struct Blob *text, |
| 361 | 361 | char c, |
| 362 | 362 | void *opaque |
| 363 | 363 | ){ |
| 364 | - BLOB_APPEND_LITTERAL(ob, "<strong><em>"); | |
| 364 | + BLOB_APPEND_LITERAL(ob, "<strong><em>"); | |
| 365 | 365 | BLOB_APPEND_BLOB(ob, text); |
| 366 | - BLOB_APPEND_LITTERAL(ob, "</em></strong>"); | |
| 366 | + BLOB_APPEND_LITERAL(ob, "</em></strong>"); | |
| 367 | 367 | return 1; |
| 368 | 368 | } |
| 369 | 369 | |
| 370 | 370 | |
| 371 | 371 | static void html_normal_text(struct Blob *ob, struct Blob *text, void *opaque){ |
| 372 | 372 |
| --- src/markdown_html.c | |
| +++ src/markdown_html.c | |
| @@ -34,16 +34,16 @@ | |
| 34 | |
| 35 | /* INTER_BLOCK -- skip a line between block level elements */ |
| 36 | #define INTER_BLOCK(ob) \ |
| 37 | do { if( blob_size(ob)>0 ) blob_append(ob, "\n", 1); } while (0) |
| 38 | |
| 39 | /* BLOB_APPEND_LITTERAL -- append a string litteral to a blob */ |
| 40 | #define BLOB_APPEND_LITTERAL(blob, litteral) \ |
| 41 | blob_append((blob), "" litteral, (sizeof litteral)-1) |
| 42 | /* |
| 43 | * The empty string in the second argument leads to a syntax error |
| 44 | * when the macro is not used with a string litteral. Unfortunately |
| 45 | * the error is not overly explicit. |
| 46 | */ |
| 47 | |
| 48 | /* BLOB_APPEND_BLOB -- append blob contents to another */ |
| 49 | #define BLOB_APPEND_BLOB(dest, src) \ |
| @@ -65,17 +65,17 @@ | |
| 65 | i++; |
| 66 | } |
| 67 | blob_append(ob, data+beg, i-beg); |
| 68 | while( i<size ){ |
| 69 | if( data[i]=='<' ){ |
| 70 | BLOB_APPEND_LITTERAL(ob, "<"); |
| 71 | }else if( data[i]=='>' ){ |
| 72 | BLOB_APPEND_LITTERAL(ob, ">"); |
| 73 | }else if( data[i]=='&' ){ |
| 74 | BLOB_APPEND_LITTERAL(ob, "&"); |
| 75 | }else if( data[i]=='"' ){ |
| 76 | BLOB_APPEND_LITTERAL(ob, """); |
| 77 | }else{ |
| 78 | break; |
| 79 | } |
| 80 | i++; |
| 81 | } |
| @@ -88,41 +88,41 @@ | |
| 88 | /* Size of the prolog: "<div class='markdown'>\n" */ |
| 89 | #define PROLOG_SIZE 23 |
| 90 | |
| 91 | static void html_prolog(struct Blob *ob, void *opaque){ |
| 92 | INTER_BLOCK(ob); |
| 93 | BLOB_APPEND_LITTERAL(ob, "<div class=\"markdown\">\n"); |
| 94 | assert( blob_size(ob)==PROLOG_SIZE ); |
| 95 | } |
| 96 | |
| 97 | static void html_epilog(struct Blob *ob, void *opaque){ |
| 98 | INTER_BLOCK(ob); |
| 99 | BLOB_APPEND_LITTERAL(ob, "</div>\n"); |
| 100 | } |
| 101 | |
| 102 | static void html_raw_block(struct Blob *ob, struct Blob *text, void *opaque){ |
| 103 | char *data = blob_buffer(text); |
| 104 | size_t first = 0, size = blob_size(text); |
| 105 | INTER_BLOCK(ob); |
| 106 | while( first<size && data[first]=='\n' ) first++; |
| 107 | while( size>first && data[size-1]=='\n' ) size--; |
| 108 | blob_append(ob, data+first, size-first); |
| 109 | BLOB_APPEND_LITTERAL(ob, "\n"); |
| 110 | } |
| 111 | |
| 112 | static void html_blockcode(struct Blob *ob, struct Blob *text, void *opaque){ |
| 113 | INTER_BLOCK(ob); |
| 114 | BLOB_APPEND_LITTERAL(ob, "<pre><code>"); |
| 115 | html_escape(ob, blob_buffer(text), blob_size(text)); |
| 116 | BLOB_APPEND_LITTERAL(ob, "</code></pre>\n"); |
| 117 | } |
| 118 | |
| 119 | static void html_blockquote(struct Blob *ob, struct Blob *text, void *opaque){ |
| 120 | INTER_BLOCK(ob); |
| 121 | BLOB_APPEND_LITTERAL(ob, "<blockquote>\n"); |
| 122 | BLOB_APPEND_BLOB(ob, text); |
| 123 | BLOB_APPEND_LITTERAL(ob, "</blockquote>\n"); |
| 124 | } |
| 125 | |
| 126 | static void html_header( |
| 127 | struct Blob *ob, |
| 128 | struct Blob *text, |
| @@ -141,11 +141,11 @@ | |
| 141 | blob_appendf(ob, "</h%d>", level); |
| 142 | } |
| 143 | |
| 144 | static void html_hrule(struct Blob *ob, void *opaque){ |
| 145 | INTER_BLOCK(ob); |
| 146 | BLOB_APPEND_LITTERAL(ob, "<hr />\n"); |
| 147 | } |
| 148 | |
| 149 | |
| 150 | static void html_list( |
| 151 | struct Blob *ob, |
| @@ -169,20 +169,20 @@ | |
| 169 | void *opaque |
| 170 | ){ |
| 171 | char *text_data = blob_buffer(text); |
| 172 | size_t text_size = blob_size(text); |
| 173 | while( text_size>0 && text_data[text_size-1]=='\n' ) text_size--; |
| 174 | BLOB_APPEND_LITTERAL(ob, "<li>"); |
| 175 | blob_append(ob, text_data, text_size); |
| 176 | BLOB_APPEND_LITTERAL(ob, "</li>\n"); |
| 177 | } |
| 178 | |
| 179 | static void html_paragraph(struct Blob *ob, struct Blob *text, void *opaque){ |
| 180 | INTER_BLOCK(ob); |
| 181 | BLOB_APPEND_LITTERAL(ob, "<p>"); |
| 182 | BLOB_APPEND_BLOB(ob, text); |
| 183 | BLOB_APPEND_LITTERAL(ob, "</p>\n"); |
| 184 | } |
| 185 | |
| 186 | |
| 187 | static void html_table( |
| 188 | struct Blob *ob, |
| @@ -189,68 +189,68 @@ | |
| 189 | struct Blob *head_row, |
| 190 | struct Blob *rows, |
| 191 | void *opaque |
| 192 | ){ |
| 193 | INTER_BLOCK(ob); |
| 194 | BLOB_APPEND_LITTERAL(ob, "<table>\n"); |
| 195 | if( head_row && blob_size(head_row)>0 ){ |
| 196 | BLOB_APPEND_LITTERAL(ob, "<thead>\n"); |
| 197 | BLOB_APPEND_BLOB(ob, head_row); |
| 198 | BLOB_APPEND_LITTERAL(ob, "</thead>\n<tbody>\n"); |
| 199 | } |
| 200 | if( rows ){ |
| 201 | BLOB_APPEND_BLOB(ob, rows); |
| 202 | } |
| 203 | if( head_row && blob_size(head_row)>0 ){ |
| 204 | BLOB_APPEND_LITTERAL(ob, "</tbody>\n"); |
| 205 | } |
| 206 | BLOB_APPEND_LITTERAL(ob, "</table>\n"); |
| 207 | } |
| 208 | |
| 209 | static void html_table_cell( |
| 210 | struct Blob *ob, |
| 211 | struct Blob *text, |
| 212 | int flags, |
| 213 | void *opaque |
| 214 | ){ |
| 215 | if( flags & MKD_CELL_HEAD ){ |
| 216 | BLOB_APPEND_LITTERAL(ob, " <th"); |
| 217 | }else{ |
| 218 | BLOB_APPEND_LITTERAL(ob, " <td"); |
| 219 | } |
| 220 | switch( flags & MKD_CELL_ALIGN_MASK ){ |
| 221 | case MKD_CELL_ALIGN_LEFT: { |
| 222 | BLOB_APPEND_LITTERAL(ob, " align=\"left\""); |
| 223 | break; |
| 224 | } |
| 225 | case MKD_CELL_ALIGN_RIGHT: { |
| 226 | BLOB_APPEND_LITTERAL(ob, " align=\"right\""); |
| 227 | break; |
| 228 | } |
| 229 | case MKD_CELL_ALIGN_CENTER: { |
| 230 | BLOB_APPEND_LITTERAL(ob, " align=\"center\""); |
| 231 | break; |
| 232 | } |
| 233 | } |
| 234 | BLOB_APPEND_LITTERAL(ob, ">"); |
| 235 | BLOB_APPEND_BLOB(ob, text); |
| 236 | if( flags & MKD_CELL_HEAD ){ |
| 237 | BLOB_APPEND_LITTERAL(ob, "</th>\n"); |
| 238 | }else{ |
| 239 | BLOB_APPEND_LITTERAL(ob, "</td>\n"); |
| 240 | } |
| 241 | } |
| 242 | |
| 243 | static void html_table_row( |
| 244 | struct Blob *ob, |
| 245 | struct Blob *cells, |
| 246 | int flags, |
| 247 | void *opaque |
| 248 | ){ |
| 249 | BLOB_APPEND_LITTERAL(ob, " <tr>\n"); |
| 250 | BLOB_APPEND_BLOB(ob, cells); |
| 251 | BLOB_APPEND_LITTERAL(ob, " </tr>\n"); |
| 252 | } |
| 253 | |
| 254 | |
| 255 | |
| 256 | /* HTML span tags */ |
| @@ -265,52 +265,52 @@ | |
| 265 | struct Blob *link, |
| 266 | enum mkd_autolink type, |
| 267 | void *opaque |
| 268 | ){ |
| 269 | if( !link || blob_size(link)<=0 ) return 0; |
| 270 | BLOB_APPEND_LITTERAL(ob, "<a href=\""); |
| 271 | if( type==MKDA_IMPLICIT_EMAIL ) BLOB_APPEND_LITTERAL(ob, "mailto:"); |
| 272 | html_escape(ob, blob_buffer(link), blob_size(link)); |
| 273 | BLOB_APPEND_LITTERAL(ob, "\">"); |
| 274 | if( type==MKDA_EXPLICIT_EMAIL && blob_size(link)>7 ){ |
| 275 | /* remove "mailto:" from displayed text */ |
| 276 | html_escape(ob, blob_buffer(link)+7, blob_size(link)-7); |
| 277 | }else{ |
| 278 | html_escape(ob, blob_buffer(link), blob_size(link)); |
| 279 | } |
| 280 | BLOB_APPEND_LITTERAL(ob, "</a>"); |
| 281 | return 1; |
| 282 | } |
| 283 | |
| 284 | static int html_code_span(struct Blob *ob, struct Blob *text, void *opaque){ |
| 285 | BLOB_APPEND_LITTERAL(ob, "<code>"); |
| 286 | html_escape(ob, blob_buffer(text), blob_size(text)); |
| 287 | BLOB_APPEND_LITTERAL(ob, "</code>"); |
| 288 | return 1; |
| 289 | } |
| 290 | |
| 291 | static int html_double_emphasis( |
| 292 | struct Blob *ob, |
| 293 | struct Blob *text, |
| 294 | char c, |
| 295 | void *opaque |
| 296 | ){ |
| 297 | BLOB_APPEND_LITTERAL(ob, "<strong>"); |
| 298 | BLOB_APPEND_BLOB(ob, text); |
| 299 | BLOB_APPEND_LITTERAL(ob, "</strong>"); |
| 300 | return 1; |
| 301 | } |
| 302 | |
| 303 | static int html_emphasis( |
| 304 | struct Blob *ob, |
| 305 | struct Blob *text, |
| 306 | char c, |
| 307 | void *opaque |
| 308 | ){ |
| 309 | BLOB_APPEND_LITTERAL(ob, "<em>"); |
| 310 | BLOB_APPEND_BLOB(ob, text); |
| 311 | BLOB_APPEND_LITTERAL(ob, "</em>"); |
| 312 | return 1; |
| 313 | } |
| 314 | |
| 315 | static int html_image( |
| 316 | struct Blob *ob, |
| @@ -317,24 +317,24 @@ | |
| 317 | struct Blob *link, |
| 318 | struct Blob *title, |
| 319 | struct Blob *alt, |
| 320 | void *opaque |
| 321 | ){ |
| 322 | BLOB_APPEND_LITTERAL(ob, "<img src=\""); |
| 323 | html_escape(ob, blob_buffer(link), blob_size(link)); |
| 324 | BLOB_APPEND_LITTERAL(ob, "\" alt=\""); |
| 325 | html_escape(ob, blob_buffer(alt), blob_size(alt)); |
| 326 | if( title && blob_size(title)>0 ){ |
| 327 | BLOB_APPEND_LITTERAL(ob, "\" title=\""); |
| 328 | html_escape(ob, blob_buffer(title), blob_size(title)); |
| 329 | } |
| 330 | BLOB_APPEND_LITTERAL(ob, "\" />"); |
| 331 | return 1; |
| 332 | } |
| 333 | |
| 334 | static int html_line_break(struct Blob *ob, void *opaque){ |
| 335 | BLOB_APPEND_LITTERAL(ob, "<br />\n"); |
| 336 | return 1; |
| 337 | } |
| 338 | |
| 339 | static int html_link( |
| 340 | struct Blob *ob, |
| @@ -341,31 +341,31 @@ | |
| 341 | struct Blob *link, |
| 342 | struct Blob *title, |
| 343 | struct Blob *content, |
| 344 | void *opaque |
| 345 | ){ |
| 346 | BLOB_APPEND_LITTERAL(ob, "<a href=\""); |
| 347 | html_escape(ob, blob_buffer(link), blob_size(link)); |
| 348 | if( title && blob_size(title)>0 ){ |
| 349 | BLOB_APPEND_LITTERAL(ob, "\" title=\""); |
| 350 | html_escape(ob, blob_buffer(title), blob_size(title)); |
| 351 | } |
| 352 | BLOB_APPEND_LITTERAL(ob, "\">"); |
| 353 | BLOB_APPEND_BLOB(ob, content); |
| 354 | BLOB_APPEND_LITTERAL(ob, "</a>"); |
| 355 | return 1; |
| 356 | } |
| 357 | |
| 358 | static int html_triple_emphasis( |
| 359 | struct Blob *ob, |
| 360 | struct Blob *text, |
| 361 | char c, |
| 362 | void *opaque |
| 363 | ){ |
| 364 | BLOB_APPEND_LITTERAL(ob, "<strong><em>"); |
| 365 | BLOB_APPEND_BLOB(ob, text); |
| 366 | BLOB_APPEND_LITTERAL(ob, "</em></strong>"); |
| 367 | return 1; |
| 368 | } |
| 369 | |
| 370 | |
| 371 | static void html_normal_text(struct Blob *ob, struct Blob *text, void *opaque){ |
| 372 |
| --- src/markdown_html.c | |
| +++ src/markdown_html.c | |
| @@ -34,16 +34,16 @@ | |
| 34 | |
| 35 | /* INTER_BLOCK -- skip a line between block level elements */ |
| 36 | #define INTER_BLOCK(ob) \ |
| 37 | do { if( blob_size(ob)>0 ) blob_append(ob, "\n", 1); } while (0) |
| 38 | |
| 39 | /* BLOB_APPEND_LITERAL -- append a string literal to a blob */ |
| 40 | #define BLOB_APPEND_LITERAL(blob, literal) \ |
| 41 | blob_append((blob), "" literal, (sizeof literal)-1) |
| 42 | /* |
| 43 | * The empty string in the second argument leads to a syntax error |
| 44 | * when the macro is not used with a string literal. Unfortunately |
| 45 | * the error is not overly explicit. |
| 46 | */ |
| 47 | |
| 48 | /* BLOB_APPEND_BLOB -- append blob contents to another */ |
| 49 | #define BLOB_APPEND_BLOB(dest, src) \ |
| @@ -65,17 +65,17 @@ | |
| 65 | i++; |
| 66 | } |
| 67 | blob_append(ob, data+beg, i-beg); |
| 68 | while( i<size ){ |
| 69 | if( data[i]=='<' ){ |
| 70 | BLOB_APPEND_LITERAL(ob, "<"); |
| 71 | }else if( data[i]=='>' ){ |
| 72 | BLOB_APPEND_LITERAL(ob, ">"); |
| 73 | }else if( data[i]=='&' ){ |
| 74 | BLOB_APPEND_LITERAL(ob, "&"); |
| 75 | }else if( data[i]=='"' ){ |
| 76 | BLOB_APPEND_LITERAL(ob, """); |
| 77 | }else{ |
| 78 | break; |
| 79 | } |
| 80 | i++; |
| 81 | } |
| @@ -88,41 +88,41 @@ | |
| 88 | /* Size of the prolog: "<div class='markdown'>\n" */ |
| 89 | #define PROLOG_SIZE 23 |
| 90 | |
| 91 | static void html_prolog(struct Blob *ob, void *opaque){ |
| 92 | INTER_BLOCK(ob); |
| 93 | BLOB_APPEND_LITERAL(ob, "<div class=\"markdown\">\n"); |
| 94 | assert( blob_size(ob)==PROLOG_SIZE ); |
| 95 | } |
| 96 | |
| 97 | static void html_epilog(struct Blob *ob, void *opaque){ |
| 98 | INTER_BLOCK(ob); |
| 99 | BLOB_APPEND_LITERAL(ob, "</div>\n"); |
| 100 | } |
| 101 | |
| 102 | static void html_raw_block(struct Blob *ob, struct Blob *text, void *opaque){ |
| 103 | char *data = blob_buffer(text); |
| 104 | size_t first = 0, size = blob_size(text); |
| 105 | INTER_BLOCK(ob); |
| 106 | while( first<size && data[first]=='\n' ) first++; |
| 107 | while( size>first && data[size-1]=='\n' ) size--; |
| 108 | blob_append(ob, data+first, size-first); |
| 109 | BLOB_APPEND_LITERAL(ob, "\n"); |
| 110 | } |
| 111 | |
| 112 | static void html_blockcode(struct Blob *ob, struct Blob *text, void *opaque){ |
| 113 | INTER_BLOCK(ob); |
| 114 | BLOB_APPEND_LITERAL(ob, "<pre><code>"); |
| 115 | html_escape(ob, blob_buffer(text), blob_size(text)); |
| 116 | BLOB_APPEND_LITERAL(ob, "</code></pre>\n"); |
| 117 | } |
| 118 | |
| 119 | static void html_blockquote(struct Blob *ob, struct Blob *text, void *opaque){ |
| 120 | INTER_BLOCK(ob); |
| 121 | BLOB_APPEND_LITERAL(ob, "<blockquote>\n"); |
| 122 | BLOB_APPEND_BLOB(ob, text); |
| 123 | BLOB_APPEND_LITERAL(ob, "</blockquote>\n"); |
| 124 | } |
| 125 | |
| 126 | static void html_header( |
| 127 | struct Blob *ob, |
| 128 | struct Blob *text, |
| @@ -141,11 +141,11 @@ | |
| 141 | blob_appendf(ob, "</h%d>", level); |
| 142 | } |
| 143 | |
| 144 | static void html_hrule(struct Blob *ob, void *opaque){ |
| 145 | INTER_BLOCK(ob); |
| 146 | BLOB_APPEND_LITERAL(ob, "<hr />\n"); |
| 147 | } |
| 148 | |
| 149 | |
| 150 | static void html_list( |
| 151 | struct Blob *ob, |
| @@ -169,20 +169,20 @@ | |
| 169 | void *opaque |
| 170 | ){ |
| 171 | char *text_data = blob_buffer(text); |
| 172 | size_t text_size = blob_size(text); |
| 173 | while( text_size>0 && text_data[text_size-1]=='\n' ) text_size--; |
| 174 | BLOB_APPEND_LITERAL(ob, "<li>"); |
| 175 | blob_append(ob, text_data, text_size); |
| 176 | BLOB_APPEND_LITERAL(ob, "</li>\n"); |
| 177 | } |
| 178 | |
| 179 | static void html_paragraph(struct Blob *ob, struct Blob *text, void *opaque){ |
| 180 | INTER_BLOCK(ob); |
| 181 | BLOB_APPEND_LITERAL(ob, "<p>"); |
| 182 | BLOB_APPEND_BLOB(ob, text); |
| 183 | BLOB_APPEND_LITERAL(ob, "</p>\n"); |
| 184 | } |
| 185 | |
| 186 | |
| 187 | static void html_table( |
| 188 | struct Blob *ob, |
| @@ -189,68 +189,68 @@ | |
| 189 | struct Blob *head_row, |
| 190 | struct Blob *rows, |
| 191 | void *opaque |
| 192 | ){ |
| 193 | INTER_BLOCK(ob); |
| 194 | BLOB_APPEND_LITERAL(ob, "<table>\n"); |
| 195 | if( head_row && blob_size(head_row)>0 ){ |
| 196 | BLOB_APPEND_LITERAL(ob, "<thead>\n"); |
| 197 | BLOB_APPEND_BLOB(ob, head_row); |
| 198 | BLOB_APPEND_LITERAL(ob, "</thead>\n<tbody>\n"); |
| 199 | } |
| 200 | if( rows ){ |
| 201 | BLOB_APPEND_BLOB(ob, rows); |
| 202 | } |
| 203 | if( head_row && blob_size(head_row)>0 ){ |
| 204 | BLOB_APPEND_LITERAL(ob, "</tbody>\n"); |
| 205 | } |
| 206 | BLOB_APPEND_LITERAL(ob, "</table>\n"); |
| 207 | } |
| 208 | |
| 209 | static void html_table_cell( |
| 210 | struct Blob *ob, |
| 211 | struct Blob *text, |
| 212 | int flags, |
| 213 | void *opaque |
| 214 | ){ |
| 215 | if( flags & MKD_CELL_HEAD ){ |
| 216 | BLOB_APPEND_LITERAL(ob, " <th"); |
| 217 | }else{ |
| 218 | BLOB_APPEND_LITERAL(ob, " <td"); |
| 219 | } |
| 220 | switch( flags & MKD_CELL_ALIGN_MASK ){ |
| 221 | case MKD_CELL_ALIGN_LEFT: { |
| 222 | BLOB_APPEND_LITERAL(ob, " align=\"left\""); |
| 223 | break; |
| 224 | } |
| 225 | case MKD_CELL_ALIGN_RIGHT: { |
| 226 | BLOB_APPEND_LITERAL(ob, " align=\"right\""); |
| 227 | break; |
| 228 | } |
| 229 | case MKD_CELL_ALIGN_CENTER: { |
| 230 | BLOB_APPEND_LITERAL(ob, " align=\"center\""); |
| 231 | break; |
| 232 | } |
| 233 | } |
| 234 | BLOB_APPEND_LITERAL(ob, ">"); |
| 235 | BLOB_APPEND_BLOB(ob, text); |
| 236 | if( flags & MKD_CELL_HEAD ){ |
| 237 | BLOB_APPEND_LITERAL(ob, "</th>\n"); |
| 238 | }else{ |
| 239 | BLOB_APPEND_LITERAL(ob, "</td>\n"); |
| 240 | } |
| 241 | } |
| 242 | |
| 243 | static void html_table_row( |
| 244 | struct Blob *ob, |
| 245 | struct Blob *cells, |
| 246 | int flags, |
| 247 | void *opaque |
| 248 | ){ |
| 249 | BLOB_APPEND_LITERAL(ob, " <tr>\n"); |
| 250 | BLOB_APPEND_BLOB(ob, cells); |
| 251 | BLOB_APPEND_LITERAL(ob, " </tr>\n"); |
| 252 | } |
| 253 | |
| 254 | |
| 255 | |
| 256 | /* HTML span tags */ |
| @@ -265,52 +265,52 @@ | |
| 265 | struct Blob *link, |
| 266 | enum mkd_autolink type, |
| 267 | void *opaque |
| 268 | ){ |
| 269 | if( !link || blob_size(link)<=0 ) return 0; |
| 270 | BLOB_APPEND_LITERAL(ob, "<a href=\""); |
| 271 | if( type==MKDA_IMPLICIT_EMAIL ) BLOB_APPEND_LITERAL(ob, "mailto:"); |
| 272 | html_escape(ob, blob_buffer(link), blob_size(link)); |
| 273 | BLOB_APPEND_LITERAL(ob, "\">"); |
| 274 | if( type==MKDA_EXPLICIT_EMAIL && blob_size(link)>7 ){ |
| 275 | /* remove "mailto:" from displayed text */ |
| 276 | html_escape(ob, blob_buffer(link)+7, blob_size(link)-7); |
| 277 | }else{ |
| 278 | html_escape(ob, blob_buffer(link), blob_size(link)); |
| 279 | } |
| 280 | BLOB_APPEND_LITERAL(ob, "</a>"); |
| 281 | return 1; |
| 282 | } |
| 283 | |
| 284 | static int html_code_span(struct Blob *ob, struct Blob *text, void *opaque){ |
| 285 | BLOB_APPEND_LITERAL(ob, "<code>"); |
| 286 | html_escape(ob, blob_buffer(text), blob_size(text)); |
| 287 | BLOB_APPEND_LITERAL(ob, "</code>"); |
| 288 | return 1; |
| 289 | } |
| 290 | |
| 291 | static int html_double_emphasis( |
| 292 | struct Blob *ob, |
| 293 | struct Blob *text, |
| 294 | char c, |
| 295 | void *opaque |
| 296 | ){ |
| 297 | BLOB_APPEND_LITERAL(ob, "<strong>"); |
| 298 | BLOB_APPEND_BLOB(ob, text); |
| 299 | BLOB_APPEND_LITERAL(ob, "</strong>"); |
| 300 | return 1; |
| 301 | } |
| 302 | |
| 303 | static int html_emphasis( |
| 304 | struct Blob *ob, |
| 305 | struct Blob *text, |
| 306 | char c, |
| 307 | void *opaque |
| 308 | ){ |
| 309 | BLOB_APPEND_LITERAL(ob, "<em>"); |
| 310 | BLOB_APPEND_BLOB(ob, text); |
| 311 | BLOB_APPEND_LITERAL(ob, "</em>"); |
| 312 | return 1; |
| 313 | } |
| 314 | |
| 315 | static int html_image( |
| 316 | struct Blob *ob, |
| @@ -317,24 +317,24 @@ | |
| 317 | struct Blob *link, |
| 318 | struct Blob *title, |
| 319 | struct Blob *alt, |
| 320 | void *opaque |
| 321 | ){ |
| 322 | BLOB_APPEND_LITERAL(ob, "<img src=\""); |
| 323 | html_escape(ob, blob_buffer(link), blob_size(link)); |
| 324 | BLOB_APPEND_LITERAL(ob, "\" alt=\""); |
| 325 | html_escape(ob, blob_buffer(alt), blob_size(alt)); |
| 326 | if( title && blob_size(title)>0 ){ |
| 327 | BLOB_APPEND_LITERAL(ob, "\" title=\""); |
| 328 | html_escape(ob, blob_buffer(title), blob_size(title)); |
| 329 | } |
| 330 | BLOB_APPEND_LITERAL(ob, "\" />"); |
| 331 | return 1; |
| 332 | } |
| 333 | |
| 334 | static int html_line_break(struct Blob *ob, void *opaque){ |
| 335 | BLOB_APPEND_LITERAL(ob, "<br />\n"); |
| 336 | return 1; |
| 337 | } |
| 338 | |
| 339 | static int html_link( |
| 340 | struct Blob *ob, |
| @@ -341,31 +341,31 @@ | |
| 341 | struct Blob *link, |
| 342 | struct Blob *title, |
| 343 | struct Blob *content, |
| 344 | void *opaque |
| 345 | ){ |
| 346 | BLOB_APPEND_LITERAL(ob, "<a href=\""); |
| 347 | html_escape(ob, blob_buffer(link), blob_size(link)); |
| 348 | if( title && blob_size(title)>0 ){ |
| 349 | BLOB_APPEND_LITERAL(ob, "\" title=\""); |
| 350 | html_escape(ob, blob_buffer(title), blob_size(title)); |
| 351 | } |
| 352 | BLOB_APPEND_LITERAL(ob, "\">"); |
| 353 | BLOB_APPEND_BLOB(ob, content); |
| 354 | BLOB_APPEND_LITERAL(ob, "</a>"); |
| 355 | return 1; |
| 356 | } |
| 357 | |
| 358 | static int html_triple_emphasis( |
| 359 | struct Blob *ob, |
| 360 | struct Blob *text, |
| 361 | char c, |
| 362 | void *opaque |
| 363 | ){ |
| 364 | BLOB_APPEND_LITERAL(ob, "<strong><em>"); |
| 365 | BLOB_APPEND_BLOB(ob, text); |
| 366 | BLOB_APPEND_LITERAL(ob, "</em></strong>"); |
| 367 | return 1; |
| 368 | } |
| 369 | |
| 370 | |
| 371 | static void html_normal_text(struct Blob *ob, struct Blob *text, void *opaque){ |
| 372 |
+28
-10
| --- src/name.c | ||
| +++ src/name.c | ||
| @@ -1068,29 +1068,26 @@ | ||
| 1068 | 1068 | |
| 1069 | 1069 | /* Maximum number of collision examples to remember */ |
| 1070 | 1070 | #define MAX_COLLIDE 25 |
| 1071 | 1071 | |
| 1072 | 1072 | /* |
| 1073 | -** WEBPAGE: hash-collisions | |
| 1074 | -** | |
| 1075 | -** Show the number of hash collisions for hash prefixes of various lengths. | |
| 1073 | +** Generate a report on the number of collisions in SHA1 hashes | |
| 1074 | +** generated by the SQL given in the argument. | |
| 1076 | 1075 | */ |
| 1077 | -void hash_collisions_webpage(void){ | |
| 1076 | +static void collision_report(const char *zSql){ | |
| 1078 | 1077 | int i, j, kk; |
| 1079 | 1078 | int nHash = 0; |
| 1080 | 1079 | Stmt q; |
| 1081 | 1080 | char zPrev[UUID_SIZE+1]; |
| 1082 | 1081 | struct { |
| 1083 | 1082 | int cnt; |
| 1084 | 1083 | char *azHit[MAX_COLLIDE]; |
| 1085 | 1084 | char z[UUID_SIZE+1]; |
| 1086 | 1085 | } aCollide[UUID_SIZE+1]; |
| 1087 | - login_check_credentials(); | |
| 1088 | - if( !g.perm.Read ){ login_needed(g.anon.Read); return; } | |
| 1089 | 1086 | memset(aCollide, 0, sizeof(aCollide)); |
| 1090 | 1087 | memset(zPrev, 0, sizeof(zPrev)); |
| 1091 | - db_prepare(&q,"SELECT uuid FROM blob ORDER BY 1"); | |
| 1088 | + db_prepare(&q,"%s",zSql/*safe-for-%s*/); | |
| 1092 | 1089 | while( db_step(&q)==SQLITE_ROW ){ |
| 1093 | 1090 | const char *zUuid = db_column_text(&q,0); |
| 1094 | 1091 | int n = db_column_bytes(&q,0); |
| 1095 | 1092 | int i; |
| 1096 | 1093 | nHash++; |
| @@ -1103,13 +1100,10 @@ | ||
| 1103 | 1100 | if( aCollide[i].z[0]==0 ) memcpy(aCollide[i].z, zPrev, n+1); |
| 1104 | 1101 | } |
| 1105 | 1102 | memcpy(zPrev, zUuid, n+1); |
| 1106 | 1103 | } |
| 1107 | 1104 | db_finalize(&q); |
| 1108 | - style_header("SHA1 Prefix Collisions"); | |
| 1109 | - style_submenu_element("Activity Reports", 0, "reports"); | |
| 1110 | - style_submenu_element("Stats", 0, "stat"); | |
| 1111 | 1105 | @ <table border=1><thead> |
| 1112 | 1106 | @ <tr><th>Length<th>Instances<th>First Instance</tr> |
| 1113 | 1107 | @ </thead><tbody> |
| 1114 | 1108 | for(i=1; i<=UUID_SIZE; i++){ |
| 1115 | 1109 | if( aCollide[i].cnt==0 ) continue; |
| @@ -1131,7 +1125,31 @@ | ||
| 1131 | 1125 | char *zId = aCollide[i].azHit[j]; |
| 1132 | 1126 | if( zId==0 ) continue; |
| 1133 | 1127 | @ %z(href("%R/whatis/%s",zId))%h(zId)</a> |
| 1134 | 1128 | } |
| 1135 | 1129 | } |
| 1130 | + for(i=4; i<ArraySize(aCollide); i++){ | |
| 1131 | + for(j=0; j<aCollide[i].cnt && j<MAX_COLLIDE; j++){ | |
| 1132 | + fossil_free(aCollide[i].azHit[j]); | |
| 1133 | + } | |
| 1134 | + } | |
| 1135 | +} | |
| 1136 | + | |
| 1137 | +/* | |
| 1138 | +** WEBPAGE: hash-collisions | |
| 1139 | +** | |
| 1140 | +** Show the number of hash collisions for hash prefixes of various lengths. | |
| 1141 | +*/ | |
| 1142 | +void hash_collisions_webpage(void){ | |
| 1143 | + login_check_credentials(); | |
| 1144 | + if( !g.perm.Read ){ login_needed(g.anon.Read); return; } | |
| 1145 | + style_header("SHA1 Prefix Collisions"); | |
| 1146 | + style_submenu_element("Activity Reports", 0, "reports"); | |
| 1147 | + style_submenu_element("Stats", 0, "stat"); | |
| 1148 | + @ <h1>Hash Prefix Collisions on Check-ins</h1> | |
| 1149 | + collision_report("SELECT (SELECT uuid FROM blob WHERE rid=objid)" | |
| 1150 | + " FROM event WHERE event.type='ci'" | |
| 1151 | + " ORDER BY 1"); | |
| 1152 | + @ <h1>Hash Prefix Collisions on All Artifacts</h1> | |
| 1153 | + collision_report("SELECT uuid FROM blob ORDER BY 1"); | |
| 1136 | 1154 | style_footer(); |
| 1137 | 1155 | } |
| 1138 | 1156 | |
| 1139 | 1157 | ADDED src/piechart.c |
| --- src/name.c | |
| +++ src/name.c | |
| @@ -1068,29 +1068,26 @@ | |
| 1068 | |
| 1069 | /* Maximum number of collision examples to remember */ |
| 1070 | #define MAX_COLLIDE 25 |
| 1071 | |
| 1072 | /* |
| 1073 | ** WEBPAGE: hash-collisions |
| 1074 | ** |
| 1075 | ** Show the number of hash collisions for hash prefixes of various lengths. |
| 1076 | */ |
| 1077 | void hash_collisions_webpage(void){ |
| 1078 | int i, j, kk; |
| 1079 | int nHash = 0; |
| 1080 | Stmt q; |
| 1081 | char zPrev[UUID_SIZE+1]; |
| 1082 | struct { |
| 1083 | int cnt; |
| 1084 | char *azHit[MAX_COLLIDE]; |
| 1085 | char z[UUID_SIZE+1]; |
| 1086 | } aCollide[UUID_SIZE+1]; |
| 1087 | login_check_credentials(); |
| 1088 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1089 | memset(aCollide, 0, sizeof(aCollide)); |
| 1090 | memset(zPrev, 0, sizeof(zPrev)); |
| 1091 | db_prepare(&q,"SELECT uuid FROM blob ORDER BY 1"); |
| 1092 | while( db_step(&q)==SQLITE_ROW ){ |
| 1093 | const char *zUuid = db_column_text(&q,0); |
| 1094 | int n = db_column_bytes(&q,0); |
| 1095 | int i; |
| 1096 | nHash++; |
| @@ -1103,13 +1100,10 @@ | |
| 1103 | if( aCollide[i].z[0]==0 ) memcpy(aCollide[i].z, zPrev, n+1); |
| 1104 | } |
| 1105 | memcpy(zPrev, zUuid, n+1); |
| 1106 | } |
| 1107 | db_finalize(&q); |
| 1108 | style_header("SHA1 Prefix Collisions"); |
| 1109 | style_submenu_element("Activity Reports", 0, "reports"); |
| 1110 | style_submenu_element("Stats", 0, "stat"); |
| 1111 | @ <table border=1><thead> |
| 1112 | @ <tr><th>Length<th>Instances<th>First Instance</tr> |
| 1113 | @ </thead><tbody> |
| 1114 | for(i=1; i<=UUID_SIZE; i++){ |
| 1115 | if( aCollide[i].cnt==0 ) continue; |
| @@ -1131,7 +1125,31 @@ | |
| 1131 | char *zId = aCollide[i].azHit[j]; |
| 1132 | if( zId==0 ) continue; |
| 1133 | @ %z(href("%R/whatis/%s",zId))%h(zId)</a> |
| 1134 | } |
| 1135 | } |
| 1136 | style_footer(); |
| 1137 | } |
| 1138 | |
| 1139 | DDED src/piechart.c |
| --- src/name.c | |
| +++ src/name.c | |
| @@ -1068,29 +1068,26 @@ | |
| 1068 | |
| 1069 | /* Maximum number of collision examples to remember */ |
| 1070 | #define MAX_COLLIDE 25 |
| 1071 | |
| 1072 | /* |
| 1073 | ** Generate a report on the number of collisions in SHA1 hashes |
| 1074 | ** generated by the SQL given in the argument. |
| 1075 | */ |
| 1076 | static void collision_report(const char *zSql){ |
| 1077 | int i, j, kk; |
| 1078 | int nHash = 0; |
| 1079 | Stmt q; |
| 1080 | char zPrev[UUID_SIZE+1]; |
| 1081 | struct { |
| 1082 | int cnt; |
| 1083 | char *azHit[MAX_COLLIDE]; |
| 1084 | char z[UUID_SIZE+1]; |
| 1085 | } aCollide[UUID_SIZE+1]; |
| 1086 | memset(aCollide, 0, sizeof(aCollide)); |
| 1087 | memset(zPrev, 0, sizeof(zPrev)); |
| 1088 | db_prepare(&q,"%s",zSql/*safe-for-%s*/); |
| 1089 | while( db_step(&q)==SQLITE_ROW ){ |
| 1090 | const char *zUuid = db_column_text(&q,0); |
| 1091 | int n = db_column_bytes(&q,0); |
| 1092 | int i; |
| 1093 | nHash++; |
| @@ -1103,13 +1100,10 @@ | |
| 1100 | if( aCollide[i].z[0]==0 ) memcpy(aCollide[i].z, zPrev, n+1); |
| 1101 | } |
| 1102 | memcpy(zPrev, zUuid, n+1); |
| 1103 | } |
| 1104 | db_finalize(&q); |
| 1105 | @ <table border=1><thead> |
| 1106 | @ <tr><th>Length<th>Instances<th>First Instance</tr> |
| 1107 | @ </thead><tbody> |
| 1108 | for(i=1; i<=UUID_SIZE; i++){ |
| 1109 | if( aCollide[i].cnt==0 ) continue; |
| @@ -1131,7 +1125,31 @@ | |
| 1125 | char *zId = aCollide[i].azHit[j]; |
| 1126 | if( zId==0 ) continue; |
| 1127 | @ %z(href("%R/whatis/%s",zId))%h(zId)</a> |
| 1128 | } |
| 1129 | } |
| 1130 | for(i=4; i<ArraySize(aCollide); i++){ |
| 1131 | for(j=0; j<aCollide[i].cnt && j<MAX_COLLIDE; j++){ |
| 1132 | fossil_free(aCollide[i].azHit[j]); |
| 1133 | } |
| 1134 | } |
| 1135 | } |
| 1136 | |
| 1137 | /* |
| 1138 | ** WEBPAGE: hash-collisions |
| 1139 | ** |
| 1140 | ** Show the number of hash collisions for hash prefixes of various lengths. |
| 1141 | */ |
| 1142 | void hash_collisions_webpage(void){ |
| 1143 | login_check_credentials(); |
| 1144 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1145 | style_header("SHA1 Prefix Collisions"); |
| 1146 | style_submenu_element("Activity Reports", 0, "reports"); |
| 1147 | style_submenu_element("Stats", 0, "stat"); |
| 1148 | @ <h1>Hash Prefix Collisions on Check-ins</h1> |
| 1149 | collision_report("SELECT (SELECT uuid FROM blob WHERE rid=objid)" |
| 1150 | " FROM event WHERE event.type='ci'" |
| 1151 | " ORDER BY 1"); |
| 1152 | @ <h1>Hash Prefix Collisions on All Artifacts</h1> |
| 1153 | collision_report("SELECT uuid FROM blob ORDER BY 1"); |
| 1154 | style_footer(); |
| 1155 | } |
| 1156 | |
| 1157 | DDED src/piechart.c |
+19
| --- a/src/piechart.c | ||
| +++ b/src/piechart.c | ||
| @@ -0,0 +1,19 @@ | ||
| 1 | +/* | |
| 2 | +** Copyright (c) 2015 D. Richard Hipp | |
| 3 | +** | |
| 4 | +** This program is free software; you can redistribute it and/or | |
| 5 | +** modify it under the terms o return;test_piecharpiechart_tes, q; | |
| 6 | + Bloblob_init(&all, zData, -1); | |
| 7 | + whif( blob_token(&line, &token1)==0 ) continue; | |
| 8 | + rAmt = atof(blob_str(&token1)); | |
| 9 | + if( rAmt<=0.0 ) continue; | |
| 10 | + blob_tail(&line, &token2blob_str(&token2)n++ins); | |
| 11 | + blob_reset(&all); | |
| 12 | + if( n>0postOne slice per line. Value and then Label.<p> | |
| 13 | + @ <textarea name='data' rows='20' cohidden<input type='hiddenhr /><p>Previous Data:<rowid,"); | |
| 14 | + while( ){ | |
| 15 | + @ <tr><td>%d(db_column_int1))</td> | |
| 16 | + @ <td>%h(db_c. @ </table> | |
| 17 | + style_footer(); | |
| 18 | +} | |
| 19 | += |
| --- a/src/piechart.c | |
| +++ b/src/piechart.c | |
| @@ -0,0 +1,19 @@ | |
| --- a/src/piechart.c | |
| +++ b/src/piechart.c | |
| @@ -0,0 +1,19 @@ | |
| 1 | /* |
| 2 | ** Copyright (c) 2015 D. Richard Hipp |
| 3 | ** |
| 4 | ** This program is free software; you can redistribute it and/or |
| 5 | ** modify it under the terms o return;test_piecharpiechart_tes, q; |
| 6 | Bloblob_init(&all, zData, -1); |
| 7 | whif( blob_token(&line, &token1)==0 ) continue; |
| 8 | rAmt = atof(blob_str(&token1)); |
| 9 | if( rAmt<=0.0 ) continue; |
| 10 | blob_tail(&line, &token2blob_str(&token2)n++ins); |
| 11 | blob_reset(&all); |
| 12 | if( n>0postOne slice per line. Value and then Label.<p> |
| 13 | @ <textarea name='data' rows='20' cohidden<input type='hiddenhr /><p>Previous Data:<rowid,"); |
| 14 | while( ){ |
| 15 | @ <tr><td>%d(db_column_int1))</td> |
| 16 | @ <td>%h(db_c. @ </table> |
| 17 | style_footer(); |
| 18 | } |
| 19 | = |
+26
-20
| --- src/rebuild.c | ||
| +++ src/rebuild.c | ||
| @@ -522,31 +522,32 @@ | ||
| 522 | 522 | ** Reconstruct the named repository database from the core |
| 523 | 523 | ** records. Run this command after updating the fossil |
| 524 | 524 | ** executable in a way that changes the database schema. |
| 525 | 525 | ** |
| 526 | 526 | ** Options: |
| 527 | -** --analyze Run ANALYZE on the database after rebuilding | |
| 528 | -** --cluster Compute clusters for unclustered artifacts | |
| 529 | -** --compress Strive to make the database as small as possible | |
| 530 | -** --deanalyze Remove ANALYZE tables from the database | |
| 531 | -** --force Force the rebuild to complete even if errors are seen | |
| 532 | -** --ifneeded Only do the rebuild if it would change the schema version | |
| 533 | -** --index Always add in the full-text search index | |
| 534 | -** --noverify Skip the verification of changes to the BLOB table | |
| 535 | -** --noindex Always omit the full-text search index | |
| 536 | -** --pagesize N Set the database pagesize to N. (512..65536 and power of 2) | |
| 537 | -** --randomize Scan artifacts in a random order | |
| 538 | -** --stats Show artifact statistics after rebuilding | |
| 539 | -** --vacuum Run VACUUM on the database after rebuilding | |
| 540 | -** --wal Set Write-Ahead-Log journalling mode on the database | |
| 527 | +** --analyze Run ANALYZE on the database after rebuilding | |
| 528 | +** --cluster Compute clusters for unclustered artifacts | |
| 529 | +** --compress Strive to make the database as small as possible | |
| 530 | +** --compress-only Skip the rebuilding step. Do --compress only | |
| 531 | +** --deanalyze Remove ANALYZE tables from the database | |
| 532 | +** --force Force the rebuild to complete even if errors are seen | |
| 533 | +** --ifneeded Only do the rebuild if it would change the schema version | |
| 534 | +** --index Always add in the full-text search index | |
| 535 | +** --noverify Skip the verification of changes to the BLOB table | |
| 536 | +** --noindex Always omit the full-text search index | |
| 537 | +** --pagesize N Set the database pagesize to N. (512..65536 and power of 2) | |
| 538 | +** --randomize Scan artifacts in a random order | |
| 539 | +** --stats Show artifact statistics after rebuilding | |
| 540 | +** --vacuum Run VACUUM on the database after rebuilding | |
| 541 | +** --wal Set Write-Ahead-Log journalling mode on the database | |
| 541 | 542 | ** |
| 542 | 543 | ** See also: deconstruct, reconstruct |
| 543 | 544 | */ |
| 544 | 545 | void rebuild_database(void){ |
| 545 | 546 | int forceFlag; |
| 546 | 547 | int randomizeFlag; |
| 547 | - int errCnt; | |
| 548 | + int errCnt = 0; | |
| 548 | 549 | int omitVerify; |
| 549 | 550 | int doClustering; |
| 550 | 551 | const char *zPagesize; |
| 551 | 552 | int newPagesize = 0; |
| 552 | 553 | int activateWal; |
| @@ -557,10 +558,11 @@ | ||
| 557 | 558 | int showStats; |
| 558 | 559 | int runReindex; |
| 559 | 560 | int optNoIndex; |
| 560 | 561 | int optIndex; |
| 561 | 562 | int optIfNeeded; |
| 563 | + int compressOnlyFlag; | |
| 562 | 564 | |
| 563 | 565 | omitVerify = find_option("noverify",0,0)!=0; |
| 564 | 566 | forceFlag = find_option("force","f",0)!=0; |
| 565 | 567 | randomizeFlag = find_option("randomize", 0, 0)!=0; |
| 566 | 568 | doClustering = find_option("cluster", 0, 0)!=0; |
| @@ -571,10 +573,12 @@ | ||
| 571 | 573 | zPagesize = find_option("pagesize",0,1); |
| 572 | 574 | showStats = find_option("stats",0,0)!=0; |
| 573 | 575 | optIndex = find_option("index",0,0)!=0; |
| 574 | 576 | optNoIndex = find_option("noindex",0,0)!=0; |
| 575 | 577 | optIfNeeded = find_option("ifneeded",0,0)!=0; |
| 578 | + compressOnlyFlag = find_option("compress-only",0,0)!=0; | |
| 579 | + if( compressOnlyFlag ) runCompress = runVacuum = 1; | |
| 576 | 580 | if( zPagesize ){ |
| 577 | 581 | newPagesize = atoi(zPagesize); |
| 578 | 582 | if( newPagesize<512 || newPagesize>65536 |
| 579 | 583 | || (newPagesize&(newPagesize-1))!=0 |
| 580 | 584 | ){ |
| @@ -590,11 +594,11 @@ | ||
| 590 | 594 | usage("?REPOSITORY-FILENAME?"); |
| 591 | 595 | } |
| 592 | 596 | db_close(1); |
| 593 | 597 | db_open_repository(g.zRepositoryName); |
| 594 | 598 | } |
| 595 | - runReindex = search_index_exists(); | |
| 599 | + runReindex = search_index_exists() && !compressOnlyFlag; | |
| 596 | 600 | if( optIndex ) runReindex = 1; |
| 597 | 601 | if( optNoIndex ) runReindex = 0; |
| 598 | 602 | if( optIfNeeded && fossil_strcmp(db_get("aux-schema",""),AUX_SCHEMA_MAX)==0 ){ |
| 599 | 603 | return; |
| 600 | 604 | } |
| @@ -601,14 +605,16 @@ | ||
| 601 | 605 | |
| 602 | 606 | /* We should be done with options.. */ |
| 603 | 607 | verify_all_options(); |
| 604 | 608 | |
| 605 | 609 | db_begin_transaction(); |
| 606 | - search_drop_index(); | |
| 607 | - ttyOutput = 1; | |
| 608 | - errCnt = rebuild_db(randomizeFlag, 1, doClustering); | |
| 609 | - reconstruct_private_table(); | |
| 610 | + if( !compressOnlyFlag ){ | |
| 611 | + search_drop_index(); | |
| 612 | + ttyOutput = 1; | |
| 613 | + errCnt = rebuild_db(randomizeFlag, 1, doClustering); | |
| 614 | + reconstruct_private_table(); | |
| 615 | + } | |
| 610 | 616 | db_multi_exec( |
| 611 | 617 | "REPLACE INTO config(name,value,mtime) VALUES('content-schema',%Q,now());" |
| 612 | 618 | "REPLACE INTO config(name,value,mtime) VALUES('aux-schema',%Q,now());" |
| 613 | 619 | "REPLACE INTO config(name,value,mtime) VALUES('rebuilt',%Q,now());", |
| 614 | 620 | CONTENT_SCHEMA, AUX_SCHEMA_MAX, get_version() |
| 615 | 621 |
| --- src/rebuild.c | |
| +++ src/rebuild.c | |
| @@ -522,31 +522,32 @@ | |
| 522 | ** Reconstruct the named repository database from the core |
| 523 | ** records. Run this command after updating the fossil |
| 524 | ** executable in a way that changes the database schema. |
| 525 | ** |
| 526 | ** Options: |
| 527 | ** --analyze Run ANALYZE on the database after rebuilding |
| 528 | ** --cluster Compute clusters for unclustered artifacts |
| 529 | ** --compress Strive to make the database as small as possible |
| 530 | ** --deanalyze Remove ANALYZE tables from the database |
| 531 | ** --force Force the rebuild to complete even if errors are seen |
| 532 | ** --ifneeded Only do the rebuild if it would change the schema version |
| 533 | ** --index Always add in the full-text search index |
| 534 | ** --noverify Skip the verification of changes to the BLOB table |
| 535 | ** --noindex Always omit the full-text search index |
| 536 | ** --pagesize N Set the database pagesize to N. (512..65536 and power of 2) |
| 537 | ** --randomize Scan artifacts in a random order |
| 538 | ** --stats Show artifact statistics after rebuilding |
| 539 | ** --vacuum Run VACUUM on the database after rebuilding |
| 540 | ** --wal Set Write-Ahead-Log journalling mode on the database |
| 541 | ** |
| 542 | ** See also: deconstruct, reconstruct |
| 543 | */ |
| 544 | void rebuild_database(void){ |
| 545 | int forceFlag; |
| 546 | int randomizeFlag; |
| 547 | int errCnt; |
| 548 | int omitVerify; |
| 549 | int doClustering; |
| 550 | const char *zPagesize; |
| 551 | int newPagesize = 0; |
| 552 | int activateWal; |
| @@ -557,10 +558,11 @@ | |
| 557 | int showStats; |
| 558 | int runReindex; |
| 559 | int optNoIndex; |
| 560 | int optIndex; |
| 561 | int optIfNeeded; |
| 562 | |
| 563 | omitVerify = find_option("noverify",0,0)!=0; |
| 564 | forceFlag = find_option("force","f",0)!=0; |
| 565 | randomizeFlag = find_option("randomize", 0, 0)!=0; |
| 566 | doClustering = find_option("cluster", 0, 0)!=0; |
| @@ -571,10 +573,12 @@ | |
| 571 | zPagesize = find_option("pagesize",0,1); |
| 572 | showStats = find_option("stats",0,0)!=0; |
| 573 | optIndex = find_option("index",0,0)!=0; |
| 574 | optNoIndex = find_option("noindex",0,0)!=0; |
| 575 | optIfNeeded = find_option("ifneeded",0,0)!=0; |
| 576 | if( zPagesize ){ |
| 577 | newPagesize = atoi(zPagesize); |
| 578 | if( newPagesize<512 || newPagesize>65536 |
| 579 | || (newPagesize&(newPagesize-1))!=0 |
| 580 | ){ |
| @@ -590,11 +594,11 @@ | |
| 590 | usage("?REPOSITORY-FILENAME?"); |
| 591 | } |
| 592 | db_close(1); |
| 593 | db_open_repository(g.zRepositoryName); |
| 594 | } |
| 595 | runReindex = search_index_exists(); |
| 596 | if( optIndex ) runReindex = 1; |
| 597 | if( optNoIndex ) runReindex = 0; |
| 598 | if( optIfNeeded && fossil_strcmp(db_get("aux-schema",""),AUX_SCHEMA_MAX)==0 ){ |
| 599 | return; |
| 600 | } |
| @@ -601,14 +605,16 @@ | |
| 601 | |
| 602 | /* We should be done with options.. */ |
| 603 | verify_all_options(); |
| 604 | |
| 605 | db_begin_transaction(); |
| 606 | search_drop_index(); |
| 607 | ttyOutput = 1; |
| 608 | errCnt = rebuild_db(randomizeFlag, 1, doClustering); |
| 609 | reconstruct_private_table(); |
| 610 | db_multi_exec( |
| 611 | "REPLACE INTO config(name,value,mtime) VALUES('content-schema',%Q,now());" |
| 612 | "REPLACE INTO config(name,value,mtime) VALUES('aux-schema',%Q,now());" |
| 613 | "REPLACE INTO config(name,value,mtime) VALUES('rebuilt',%Q,now());", |
| 614 | CONTENT_SCHEMA, AUX_SCHEMA_MAX, get_version() |
| 615 |
| --- src/rebuild.c | |
| +++ src/rebuild.c | |
| @@ -522,31 +522,32 @@ | |
| 522 | ** Reconstruct the named repository database from the core |
| 523 | ** records. Run this command after updating the fossil |
| 524 | ** executable in a way that changes the database schema. |
| 525 | ** |
| 526 | ** Options: |
| 527 | ** --analyze Run ANALYZE on the database after rebuilding |
| 528 | ** --cluster Compute clusters for unclustered artifacts |
| 529 | ** --compress Strive to make the database as small as possible |
| 530 | ** --compress-only Skip the rebuilding step. Do --compress only |
| 531 | ** --deanalyze Remove ANALYZE tables from the database |
| 532 | ** --force Force the rebuild to complete even if errors are seen |
| 533 | ** --ifneeded Only do the rebuild if it would change the schema version |
| 534 | ** --index Always add in the full-text search index |
| 535 | ** --noverify Skip the verification of changes to the BLOB table |
| 536 | ** --noindex Always omit the full-text search index |
| 537 | ** --pagesize N Set the database pagesize to N. (512..65536 and power of 2) |
| 538 | ** --randomize Scan artifacts in a random order |
| 539 | ** --stats Show artifact statistics after rebuilding |
| 540 | ** --vacuum Run VACUUM on the database after rebuilding |
| 541 | ** --wal Set Write-Ahead-Log journalling mode on the database |
| 542 | ** |
| 543 | ** See also: deconstruct, reconstruct |
| 544 | */ |
| 545 | void rebuild_database(void){ |
| 546 | int forceFlag; |
| 547 | int randomizeFlag; |
| 548 | int errCnt = 0; |
| 549 | int omitVerify; |
| 550 | int doClustering; |
| 551 | const char *zPagesize; |
| 552 | int newPagesize = 0; |
| 553 | int activateWal; |
| @@ -557,10 +558,11 @@ | |
| 558 | int showStats; |
| 559 | int runReindex; |
| 560 | int optNoIndex; |
| 561 | int optIndex; |
| 562 | int optIfNeeded; |
| 563 | int compressOnlyFlag; |
| 564 | |
| 565 | omitVerify = find_option("noverify",0,0)!=0; |
| 566 | forceFlag = find_option("force","f",0)!=0; |
| 567 | randomizeFlag = find_option("randomize", 0, 0)!=0; |
| 568 | doClustering = find_option("cluster", 0, 0)!=0; |
| @@ -571,10 +573,12 @@ | |
| 573 | zPagesize = find_option("pagesize",0,1); |
| 574 | showStats = find_option("stats",0,0)!=0; |
| 575 | optIndex = find_option("index",0,0)!=0; |
| 576 | optNoIndex = find_option("noindex",0,0)!=0; |
| 577 | optIfNeeded = find_option("ifneeded",0,0)!=0; |
| 578 | compressOnlyFlag = find_option("compress-only",0,0)!=0; |
| 579 | if( compressOnlyFlag ) runCompress = runVacuum = 1; |
| 580 | if( zPagesize ){ |
| 581 | newPagesize = atoi(zPagesize); |
| 582 | if( newPagesize<512 || newPagesize>65536 |
| 583 | || (newPagesize&(newPagesize-1))!=0 |
| 584 | ){ |
| @@ -590,11 +594,11 @@ | |
| 594 | usage("?REPOSITORY-FILENAME?"); |
| 595 | } |
| 596 | db_close(1); |
| 597 | db_open_repository(g.zRepositoryName); |
| 598 | } |
| 599 | runReindex = search_index_exists() && !compressOnlyFlag; |
| 600 | if( optIndex ) runReindex = 1; |
| 601 | if( optNoIndex ) runReindex = 0; |
| 602 | if( optIfNeeded && fossil_strcmp(db_get("aux-schema",""),AUX_SCHEMA_MAX)==0 ){ |
| 603 | return; |
| 604 | } |
| @@ -601,14 +605,16 @@ | |
| 605 | |
| 606 | /* We should be done with options.. */ |
| 607 | verify_all_options(); |
| 608 | |
| 609 | db_begin_transaction(); |
| 610 | if( !compressOnlyFlag ){ |
| 611 | search_drop_index(); |
| 612 | ttyOutput = 1; |
| 613 | errCnt = rebuild_db(randomizeFlag, 1, doClustering); |
| 614 | reconstruct_private_table(); |
| 615 | } |
| 616 | db_multi_exec( |
| 617 | "REPLACE INTO config(name,value,mtime) VALUES('content-schema',%Q,now());" |
| 618 | "REPLACE INTO config(name,value,mtime) VALUES('aux-schema',%Q,now());" |
| 619 | "REPLACE INTO config(name,value,mtime) VALUES('rebuilt',%Q,now());", |
| 620 | CONTENT_SCHEMA, AUX_SCHEMA_MAX, get_version() |
| 621 |
+1
-1
| --- src/search.c | ||
| +++ src/search.c | ||
| @@ -102,11 +102,11 @@ | ||
| 102 | 102 | } |
| 103 | 103 | |
| 104 | 104 | /* |
| 105 | 105 | ** Compile a search pattern |
| 106 | 106 | */ |
| 107 | -Search *search_init( | |
| 107 | +static Search *search_init( | |
| 108 | 108 | const char *zPattern, /* The search pattern */ |
| 109 | 109 | const char *zMarkBegin, /* Start of a match */ |
| 110 | 110 | const char *zMarkEnd, /* End of a match */ |
| 111 | 111 | const char *zMarkGap, /* A gap between two matches */ |
| 112 | 112 | unsigned fSrchFlg /* Flags */ |
| 113 | 113 |
| --- src/search.c | |
| +++ src/search.c | |
| @@ -102,11 +102,11 @@ | |
| 102 | } |
| 103 | |
| 104 | /* |
| 105 | ** Compile a search pattern |
| 106 | */ |
| 107 | Search *search_init( |
| 108 | const char *zPattern, /* The search pattern */ |
| 109 | const char *zMarkBegin, /* Start of a match */ |
| 110 | const char *zMarkEnd, /* End of a match */ |
| 111 | const char *zMarkGap, /* A gap between two matches */ |
| 112 | unsigned fSrchFlg /* Flags */ |
| 113 |
| --- src/search.c | |
| +++ src/search.c | |
| @@ -102,11 +102,11 @@ | |
| 102 | } |
| 103 | |
| 104 | /* |
| 105 | ** Compile a search pattern |
| 106 | */ |
| 107 | static Search *search_init( |
| 108 | const char *zPattern, /* The search pattern */ |
| 109 | const char *zMarkBegin, /* Start of a match */ |
| 110 | const char *zMarkEnd, /* End of a match */ |
| 111 | const char *zMarkGap, /* A gap between two matches */ |
| 112 | unsigned fSrchFlg /* Flags */ |
| 113 |
+44
-18
| --- 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.8.10. By combining all the individual C code files into this | |
| 3 | +** version 3.8.10.1. 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. |
| @@ -316,13 +316,13 @@ | ||
| 316 | 316 | ** |
| 317 | 317 | ** See also: [sqlite3_libversion()], |
| 318 | 318 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 319 | 319 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 320 | 320 | */ |
| 321 | -#define SQLITE_VERSION "3.8.10" | |
| 321 | +#define SQLITE_VERSION "3.8.10.1" | |
| 322 | 322 | #define SQLITE_VERSION_NUMBER 3008010 |
| 323 | -#define SQLITE_SOURCE_ID "2015-05-07 11:53:08 cf975957b9ae671f34bb65f049acf351e650d437" | |
| 323 | +#define SQLITE_SOURCE_ID "2015-05-09 12:14:55 05b4b1f2a937c06c90db70c09890038f6c98ec40" | |
| 324 | 324 | |
| 325 | 325 | /* |
| 326 | 326 | ** CAPI3REF: Run-Time Library Version Numbers |
| 327 | 327 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 328 | 328 | ** |
| @@ -14123,10 +14123,13 @@ | ||
| 14123 | 14123 | #if SQLITE_ENABLE_CEROD |
| 14124 | 14124 | "ENABLE_CEROD", |
| 14125 | 14125 | #endif |
| 14126 | 14126 | #if SQLITE_ENABLE_COLUMN_METADATA |
| 14127 | 14127 | "ENABLE_COLUMN_METADATA", |
| 14128 | +#endif | |
| 14129 | +#if SQLITE_ENABLE_DBSTAT_VTAB | |
| 14130 | + "ENABLE_DBSTAT_VTAB", | |
| 14128 | 14131 | #endif |
| 14129 | 14132 | #if SQLITE_ENABLE_EXPENSIVE_ASSERT |
| 14130 | 14133 | "ENABLE_EXPENSIVE_ASSERT", |
| 14131 | 14134 | #endif |
| 14132 | 14135 | #if SQLITE_ENABLE_FTS1 |
| @@ -155331,10 +155334,11 @@ | ||
| 155331 | 155334 | }; |
| 155332 | 155335 | |
| 155333 | 155336 | struct StatTable { |
| 155334 | 155337 | sqlite3_vtab base; |
| 155335 | 155338 | sqlite3 *db; |
| 155339 | + int iDb; /* Index of database to analyze */ | |
| 155336 | 155340 | }; |
| 155337 | 155341 | |
| 155338 | 155342 | #ifndef get2byte |
| 155339 | 155343 | # define get2byte(x) ((x)[0]<<8 | (x)[1]) |
| 155340 | 155344 | #endif |
| @@ -155349,11 +155353,21 @@ | ||
| 155349 | 155353 | sqlite3_vtab **ppVtab, |
| 155350 | 155354 | char **pzErr |
| 155351 | 155355 | ){ |
| 155352 | 155356 | StatTable *pTab = 0; |
| 155353 | 155357 | int rc = SQLITE_OK; |
| 155358 | + int iDb; | |
| 155354 | 155359 | |
| 155360 | + if( argc>=4 ){ | |
| 155361 | + iDb = sqlite3FindDbName(db, argv[3]); | |
| 155362 | + if( iDb<0 ){ | |
| 155363 | + *pzErr = sqlite3_mprintf("no such database: %s", argv[3]); | |
| 155364 | + return SQLITE_ERROR; | |
| 155365 | + } | |
| 155366 | + }else{ | |
| 155367 | + iDb = 0; | |
| 155368 | + } | |
| 155355 | 155369 | rc = sqlite3_declare_vtab(db, VTAB_SCHEMA); |
| 155356 | 155370 | if( rc==SQLITE_OK ){ |
| 155357 | 155371 | pTab = (StatTable *)sqlite3_malloc64(sizeof(StatTable)); |
| 155358 | 155372 | if( pTab==0 ) rc = SQLITE_NOMEM; |
| 155359 | 155373 | } |
| @@ -155360,10 +155374,11 @@ | ||
| 155360 | 155374 | |
| 155361 | 155375 | assert( rc==SQLITE_OK || pTab==0 ); |
| 155362 | 155376 | if( rc==SQLITE_OK ){ |
| 155363 | 155377 | memset(pTab, 0, sizeof(StatTable)); |
| 155364 | 155378 | pTab->db = db; |
| 155379 | + pTab->iDb = iDb; | |
| 155365 | 155380 | } |
| 155366 | 155381 | |
| 155367 | 155382 | *ppVtab = (sqlite3_vtab*)pTab; |
| 155368 | 155383 | return rc; |
| 155369 | 155384 | } |
| @@ -155414,20 +155429,26 @@ | ||
| 155414 | 155429 | |
| 155415 | 155430 | pCsr = (StatCursor *)sqlite3_malloc64(sizeof(StatCursor)); |
| 155416 | 155431 | if( pCsr==0 ){ |
| 155417 | 155432 | rc = SQLITE_NOMEM; |
| 155418 | 155433 | }else{ |
| 155434 | + char *zSql; | |
| 155419 | 155435 | memset(pCsr, 0, sizeof(StatCursor)); |
| 155420 | 155436 | pCsr->base.pVtab = pVTab; |
| 155421 | 155437 | |
| 155422 | - rc = sqlite3_prepare_v2(pTab->db, | |
| 155438 | + zSql = sqlite3_mprintf( | |
| 155423 | 155439 | "SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type" |
| 155424 | 155440 | " UNION ALL " |
| 155425 | - "SELECT name, rootpage, type FROM sqlite_master WHERE rootpage!=0" | |
| 155426 | - " ORDER BY name", -1, | |
| 155427 | - &pCsr->pStmt, 0 | |
| 155428 | - ); | |
| 155441 | + "SELECT name, rootpage, type" | |
| 155442 | + " FROM \"%w\".sqlite_master WHERE rootpage!=0" | |
| 155443 | + " ORDER BY name", pTab->db->aDb[pTab->iDb].zName); | |
| 155444 | + if( zSql==0 ){ | |
| 155445 | + rc = SQLITE_NOMEM; | |
| 155446 | + }else{ | |
| 155447 | + rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pStmt, 0); | |
| 155448 | + sqlite3_free(zSql); | |
| 155449 | + } | |
| 155429 | 155450 | if( rc!=SQLITE_OK ){ |
| 155430 | 155451 | sqlite3_free(pCsr); |
| 155431 | 155452 | pCsr = 0; |
| 155432 | 155453 | } |
| 155433 | 155454 | } |
| @@ -155589,11 +155610,11 @@ | ||
| 155589 | 155610 | ** Populate the pCsr->iOffset and pCsr->szPage member variables. Based on |
| 155590 | 155611 | ** the current value of pCsr->iPageno. |
| 155591 | 155612 | */ |
| 155592 | 155613 | static void statSizeAndOffset(StatCursor *pCsr){ |
| 155593 | 155614 | StatTable *pTab = (StatTable *)((sqlite3_vtab_cursor *)pCsr)->pVtab; |
| 155594 | - Btree *pBt = pTab->db->aDb[0].pBt; | |
| 155615 | + Btree *pBt = pTab->db->aDb[pTab->iDb].pBt; | |
| 155595 | 155616 | Pager *pPager = sqlite3BtreePager(pBt); |
| 155596 | 155617 | sqlite3_file *fd; |
| 155597 | 155618 | sqlite3_int64 x[2]; |
| 155598 | 155619 | |
| 155599 | 155620 | /* The default page size and offset */ |
| @@ -155603,11 +155624,11 @@ | ||
| 155603 | 155624 | /* If connected to a ZIPVFS backend, override the page size and |
| 155604 | 155625 | ** offset with actual values obtained from ZIPVFS. |
| 155605 | 155626 | */ |
| 155606 | 155627 | fd = sqlite3PagerFile(pPager); |
| 155607 | 155628 | x[0] = pCsr->iPageno; |
| 155608 | - if( sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){ | |
| 155629 | + if( fd->pMethods!=0 && sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){ | |
| 155609 | 155630 | pCsr->iOffset = x[0]; |
| 155610 | 155631 | pCsr->szPage = (int)x[1]; |
| 155611 | 155632 | } |
| 155612 | 155633 | } |
| 155613 | 155634 | |
| @@ -155615,13 +155636,14 @@ | ||
| 155615 | 155636 | ** Move a statvfs cursor to the next entry in the file. |
| 155616 | 155637 | */ |
| 155617 | 155638 | static int statNext(sqlite3_vtab_cursor *pCursor){ |
| 155618 | 155639 | int rc; |
| 155619 | 155640 | int nPayload; |
| 155641 | + char *z; | |
| 155620 | 155642 | StatCursor *pCsr = (StatCursor *)pCursor; |
| 155621 | 155643 | StatTable *pTab = (StatTable *)pCursor->pVtab; |
| 155622 | - Btree *pBt = pTab->db->aDb[0].pBt; | |
| 155644 | + Btree *pBt = pTab->db->aDb[pTab->iDb].pBt; | |
| 155623 | 155645 | Pager *pPager = sqlite3BtreePager(pBt); |
| 155624 | 155646 | |
| 155625 | 155647 | sqlite3_free(pCsr->zPath); |
| 155626 | 155648 | pCsr->zPath = 0; |
| 155627 | 155649 | |
| @@ -155637,12 +155659,13 @@ | ||
| 155637 | 155659 | return sqlite3_reset(pCsr->pStmt); |
| 155638 | 155660 | } |
| 155639 | 155661 | rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg); |
| 155640 | 155662 | pCsr->aPage[0].iPgno = iRoot; |
| 155641 | 155663 | pCsr->aPage[0].iCell = 0; |
| 155642 | - pCsr->aPage[0].zPath = sqlite3_mprintf("/"); | |
| 155664 | + pCsr->aPage[0].zPath = z = sqlite3_mprintf("/"); | |
| 155643 | 155665 | pCsr->iPage = 0; |
| 155666 | + if( z==0 ) rc = SQLITE_NOMEM; | |
| 155644 | 155667 | }else{ |
| 155645 | 155668 | pCsr->isEof = 1; |
| 155646 | 155669 | return sqlite3_reset(pCsr->pStmt); |
| 155647 | 155670 | } |
| 155648 | 155671 | }else{ |
| @@ -155661,11 +155684,11 @@ | ||
| 155661 | 155684 | pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0); |
| 155662 | 155685 | pCsr->iPageno = pCell->aOvfl[pCell->iOvfl]; |
| 155663 | 155686 | pCsr->zPagetype = "overflow"; |
| 155664 | 155687 | pCsr->nCell = 0; |
| 155665 | 155688 | pCsr->nMxPayload = 0; |
| 155666 | - pCsr->zPath = sqlite3_mprintf( | |
| 155689 | + pCsr->zPath = z = sqlite3_mprintf( | |
| 155667 | 155690 | "%s%.3x+%.6x", p->zPath, p->iCell, pCell->iOvfl |
| 155668 | 155691 | ); |
| 155669 | 155692 | if( pCell->iOvfl<pCell->nOvfl-1 ){ |
| 155670 | 155693 | pCsr->nUnused = 0; |
| 155671 | 155694 | pCsr->nPayload = nUsable - 4; |
| @@ -155673,11 +155696,11 @@ | ||
| 155673 | 155696 | pCsr->nPayload = pCell->nLastOvfl; |
| 155674 | 155697 | pCsr->nUnused = nUsable - 4 - pCsr->nPayload; |
| 155675 | 155698 | } |
| 155676 | 155699 | pCell->iOvfl++; |
| 155677 | 155700 | statSizeAndOffset(pCsr); |
| 155678 | - return SQLITE_OK; | |
| 155701 | + return z==0 ? SQLITE_NOMEM : SQLITE_OK; | |
| 155679 | 155702 | } |
| 155680 | 155703 | if( p->iRightChildPg ) break; |
| 155681 | 155704 | p->iCell++; |
| 155682 | 155705 | } |
| 155683 | 155706 | |
| @@ -155695,12 +155718,13 @@ | ||
| 155695 | 155718 | }else{ |
| 155696 | 155719 | p[1].iPgno = p->aCell[p->iCell].iChildPg; |
| 155697 | 155720 | } |
| 155698 | 155721 | rc = sqlite3PagerGet(pPager, p[1].iPgno, &p[1].pPg); |
| 155699 | 155722 | p[1].iCell = 0; |
| 155700 | - p[1].zPath = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell); | |
| 155723 | + p[1].zPath = z = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell); | |
| 155701 | 155724 | p->iCell++; |
| 155725 | + if( z==0 ) rc = SQLITE_NOMEM; | |
| 155702 | 155726 | } |
| 155703 | 155727 | |
| 155704 | 155728 | |
| 155705 | 155729 | /* Populate the StatCursor fields with the values to be returned |
| 155706 | 155730 | ** by the xColumn() and xRowid() methods. |
| @@ -155729,11 +155753,12 @@ | ||
| 155729 | 155753 | break; |
| 155730 | 155754 | } |
| 155731 | 155755 | pCsr->nCell = p->nCell; |
| 155732 | 155756 | pCsr->nUnused = p->nUnused; |
| 155733 | 155757 | pCsr->nMxPayload = p->nMxPayload; |
| 155734 | - pCsr->zPath = sqlite3_mprintf("%s", p->zPath); | |
| 155758 | + pCsr->zPath = z = sqlite3_mprintf("%s", p->zPath); | |
| 155759 | + if( z==0 ) rc = SQLITE_NOMEM; | |
| 155735 | 155760 | nPayload = 0; |
| 155736 | 155761 | for(i=0; i<p->nCell; i++){ |
| 155737 | 155762 | nPayload += p->aCell[i].nLocal; |
| 155738 | 155763 | } |
| 155739 | 155764 | pCsr->nPayload = nPayload; |
| @@ -155765,11 +155790,11 @@ | ||
| 155765 | 155790 | int i |
| 155766 | 155791 | ){ |
| 155767 | 155792 | StatCursor *pCsr = (StatCursor *)pCursor; |
| 155768 | 155793 | switch( i ){ |
| 155769 | 155794 | case 0: /* name */ |
| 155770 | - sqlite3_result_text(ctx, pCsr->zName, -1, SQLITE_STATIC); | |
| 155795 | + sqlite3_result_text(ctx, pCsr->zName, -1, SQLITE_TRANSIENT); | |
| 155771 | 155796 | break; |
| 155772 | 155797 | case 1: /* path */ |
| 155773 | 155798 | sqlite3_result_text(ctx, pCsr->zPath, -1, SQLITE_TRANSIENT); |
| 155774 | 155799 | break; |
| 155775 | 155800 | case 2: /* pageno */ |
| @@ -155791,11 +155816,12 @@ | ||
| 155791 | 155816 | sqlite3_result_int(ctx, pCsr->nMxPayload); |
| 155792 | 155817 | break; |
| 155793 | 155818 | case 8: /* pgoffset */ |
| 155794 | 155819 | sqlite3_result_int64(ctx, pCsr->iOffset); |
| 155795 | 155820 | break; |
| 155796 | - case 9: /* pgsize */ | |
| 155821 | + default: /* pgsize */ | |
| 155822 | + assert( i==9 ); | |
| 155797 | 155823 | sqlite3_result_int(ctx, pCsr->szPage); |
| 155798 | 155824 | break; |
| 155799 | 155825 | } |
| 155800 | 155826 | return SQLITE_OK; |
| 155801 | 155827 | } |
| 155802 | 155828 |
| --- 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.8.10. 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. |
| @@ -316,13 +316,13 @@ | |
| 316 | ** |
| 317 | ** See also: [sqlite3_libversion()], |
| 318 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 319 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 320 | */ |
| 321 | #define SQLITE_VERSION "3.8.10" |
| 322 | #define SQLITE_VERSION_NUMBER 3008010 |
| 323 | #define SQLITE_SOURCE_ID "2015-05-07 11:53:08 cf975957b9ae671f34bb65f049acf351e650d437" |
| 324 | |
| 325 | /* |
| 326 | ** CAPI3REF: Run-Time Library Version Numbers |
| 327 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 328 | ** |
| @@ -14123,10 +14123,13 @@ | |
| 14123 | #if SQLITE_ENABLE_CEROD |
| 14124 | "ENABLE_CEROD", |
| 14125 | #endif |
| 14126 | #if SQLITE_ENABLE_COLUMN_METADATA |
| 14127 | "ENABLE_COLUMN_METADATA", |
| 14128 | #endif |
| 14129 | #if SQLITE_ENABLE_EXPENSIVE_ASSERT |
| 14130 | "ENABLE_EXPENSIVE_ASSERT", |
| 14131 | #endif |
| 14132 | #if SQLITE_ENABLE_FTS1 |
| @@ -155331,10 +155334,11 @@ | |
| 155331 | }; |
| 155332 | |
| 155333 | struct StatTable { |
| 155334 | sqlite3_vtab base; |
| 155335 | sqlite3 *db; |
| 155336 | }; |
| 155337 | |
| 155338 | #ifndef get2byte |
| 155339 | # define get2byte(x) ((x)[0]<<8 | (x)[1]) |
| 155340 | #endif |
| @@ -155349,11 +155353,21 @@ | |
| 155349 | sqlite3_vtab **ppVtab, |
| 155350 | char **pzErr |
| 155351 | ){ |
| 155352 | StatTable *pTab = 0; |
| 155353 | int rc = SQLITE_OK; |
| 155354 | |
| 155355 | rc = sqlite3_declare_vtab(db, VTAB_SCHEMA); |
| 155356 | if( rc==SQLITE_OK ){ |
| 155357 | pTab = (StatTable *)sqlite3_malloc64(sizeof(StatTable)); |
| 155358 | if( pTab==0 ) rc = SQLITE_NOMEM; |
| 155359 | } |
| @@ -155360,10 +155374,11 @@ | |
| 155360 | |
| 155361 | assert( rc==SQLITE_OK || pTab==0 ); |
| 155362 | if( rc==SQLITE_OK ){ |
| 155363 | memset(pTab, 0, sizeof(StatTable)); |
| 155364 | pTab->db = db; |
| 155365 | } |
| 155366 | |
| 155367 | *ppVtab = (sqlite3_vtab*)pTab; |
| 155368 | return rc; |
| 155369 | } |
| @@ -155414,20 +155429,26 @@ | |
| 155414 | |
| 155415 | pCsr = (StatCursor *)sqlite3_malloc64(sizeof(StatCursor)); |
| 155416 | if( pCsr==0 ){ |
| 155417 | rc = SQLITE_NOMEM; |
| 155418 | }else{ |
| 155419 | memset(pCsr, 0, sizeof(StatCursor)); |
| 155420 | pCsr->base.pVtab = pVTab; |
| 155421 | |
| 155422 | rc = sqlite3_prepare_v2(pTab->db, |
| 155423 | "SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type" |
| 155424 | " UNION ALL " |
| 155425 | "SELECT name, rootpage, type FROM sqlite_master WHERE rootpage!=0" |
| 155426 | " ORDER BY name", -1, |
| 155427 | &pCsr->pStmt, 0 |
| 155428 | ); |
| 155429 | if( rc!=SQLITE_OK ){ |
| 155430 | sqlite3_free(pCsr); |
| 155431 | pCsr = 0; |
| 155432 | } |
| 155433 | } |
| @@ -155589,11 +155610,11 @@ | |
| 155589 | ** Populate the pCsr->iOffset and pCsr->szPage member variables. Based on |
| 155590 | ** the current value of pCsr->iPageno. |
| 155591 | */ |
| 155592 | static void statSizeAndOffset(StatCursor *pCsr){ |
| 155593 | StatTable *pTab = (StatTable *)((sqlite3_vtab_cursor *)pCsr)->pVtab; |
| 155594 | Btree *pBt = pTab->db->aDb[0].pBt; |
| 155595 | Pager *pPager = sqlite3BtreePager(pBt); |
| 155596 | sqlite3_file *fd; |
| 155597 | sqlite3_int64 x[2]; |
| 155598 | |
| 155599 | /* The default page size and offset */ |
| @@ -155603,11 +155624,11 @@ | |
| 155603 | /* If connected to a ZIPVFS backend, override the page size and |
| 155604 | ** offset with actual values obtained from ZIPVFS. |
| 155605 | */ |
| 155606 | fd = sqlite3PagerFile(pPager); |
| 155607 | x[0] = pCsr->iPageno; |
| 155608 | if( sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){ |
| 155609 | pCsr->iOffset = x[0]; |
| 155610 | pCsr->szPage = (int)x[1]; |
| 155611 | } |
| 155612 | } |
| 155613 | |
| @@ -155615,13 +155636,14 @@ | |
| 155615 | ** Move a statvfs cursor to the next entry in the file. |
| 155616 | */ |
| 155617 | static int statNext(sqlite3_vtab_cursor *pCursor){ |
| 155618 | int rc; |
| 155619 | int nPayload; |
| 155620 | StatCursor *pCsr = (StatCursor *)pCursor; |
| 155621 | StatTable *pTab = (StatTable *)pCursor->pVtab; |
| 155622 | Btree *pBt = pTab->db->aDb[0].pBt; |
| 155623 | Pager *pPager = sqlite3BtreePager(pBt); |
| 155624 | |
| 155625 | sqlite3_free(pCsr->zPath); |
| 155626 | pCsr->zPath = 0; |
| 155627 | |
| @@ -155637,12 +155659,13 @@ | |
| 155637 | return sqlite3_reset(pCsr->pStmt); |
| 155638 | } |
| 155639 | rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg); |
| 155640 | pCsr->aPage[0].iPgno = iRoot; |
| 155641 | pCsr->aPage[0].iCell = 0; |
| 155642 | pCsr->aPage[0].zPath = sqlite3_mprintf("/"); |
| 155643 | pCsr->iPage = 0; |
| 155644 | }else{ |
| 155645 | pCsr->isEof = 1; |
| 155646 | return sqlite3_reset(pCsr->pStmt); |
| 155647 | } |
| 155648 | }else{ |
| @@ -155661,11 +155684,11 @@ | |
| 155661 | pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0); |
| 155662 | pCsr->iPageno = pCell->aOvfl[pCell->iOvfl]; |
| 155663 | pCsr->zPagetype = "overflow"; |
| 155664 | pCsr->nCell = 0; |
| 155665 | pCsr->nMxPayload = 0; |
| 155666 | pCsr->zPath = sqlite3_mprintf( |
| 155667 | "%s%.3x+%.6x", p->zPath, p->iCell, pCell->iOvfl |
| 155668 | ); |
| 155669 | if( pCell->iOvfl<pCell->nOvfl-1 ){ |
| 155670 | pCsr->nUnused = 0; |
| 155671 | pCsr->nPayload = nUsable - 4; |
| @@ -155673,11 +155696,11 @@ | |
| 155673 | pCsr->nPayload = pCell->nLastOvfl; |
| 155674 | pCsr->nUnused = nUsable - 4 - pCsr->nPayload; |
| 155675 | } |
| 155676 | pCell->iOvfl++; |
| 155677 | statSizeAndOffset(pCsr); |
| 155678 | return SQLITE_OK; |
| 155679 | } |
| 155680 | if( p->iRightChildPg ) break; |
| 155681 | p->iCell++; |
| 155682 | } |
| 155683 | |
| @@ -155695,12 +155718,13 @@ | |
| 155695 | }else{ |
| 155696 | p[1].iPgno = p->aCell[p->iCell].iChildPg; |
| 155697 | } |
| 155698 | rc = sqlite3PagerGet(pPager, p[1].iPgno, &p[1].pPg); |
| 155699 | p[1].iCell = 0; |
| 155700 | p[1].zPath = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell); |
| 155701 | p->iCell++; |
| 155702 | } |
| 155703 | |
| 155704 | |
| 155705 | /* Populate the StatCursor fields with the values to be returned |
| 155706 | ** by the xColumn() and xRowid() methods. |
| @@ -155729,11 +155753,12 @@ | |
| 155729 | break; |
| 155730 | } |
| 155731 | pCsr->nCell = p->nCell; |
| 155732 | pCsr->nUnused = p->nUnused; |
| 155733 | pCsr->nMxPayload = p->nMxPayload; |
| 155734 | pCsr->zPath = sqlite3_mprintf("%s", p->zPath); |
| 155735 | nPayload = 0; |
| 155736 | for(i=0; i<p->nCell; i++){ |
| 155737 | nPayload += p->aCell[i].nLocal; |
| 155738 | } |
| 155739 | pCsr->nPayload = nPayload; |
| @@ -155765,11 +155790,11 @@ | |
| 155765 | int i |
| 155766 | ){ |
| 155767 | StatCursor *pCsr = (StatCursor *)pCursor; |
| 155768 | switch( i ){ |
| 155769 | case 0: /* name */ |
| 155770 | sqlite3_result_text(ctx, pCsr->zName, -1, SQLITE_STATIC); |
| 155771 | break; |
| 155772 | case 1: /* path */ |
| 155773 | sqlite3_result_text(ctx, pCsr->zPath, -1, SQLITE_TRANSIENT); |
| 155774 | break; |
| 155775 | case 2: /* pageno */ |
| @@ -155791,11 +155816,12 @@ | |
| 155791 | sqlite3_result_int(ctx, pCsr->nMxPayload); |
| 155792 | break; |
| 155793 | case 8: /* pgoffset */ |
| 155794 | sqlite3_result_int64(ctx, pCsr->iOffset); |
| 155795 | break; |
| 155796 | case 9: /* pgsize */ |
| 155797 | sqlite3_result_int(ctx, pCsr->szPage); |
| 155798 | break; |
| 155799 | } |
| 155800 | return SQLITE_OK; |
| 155801 | } |
| 155802 |
| --- 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.8.10.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. |
| @@ -316,13 +316,13 @@ | |
| 316 | ** |
| 317 | ** See also: [sqlite3_libversion()], |
| 318 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 319 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 320 | */ |
| 321 | #define SQLITE_VERSION "3.8.10.1" |
| 322 | #define SQLITE_VERSION_NUMBER 3008010 |
| 323 | #define SQLITE_SOURCE_ID "2015-05-09 12:14:55 05b4b1f2a937c06c90db70c09890038f6c98ec40" |
| 324 | |
| 325 | /* |
| 326 | ** CAPI3REF: Run-Time Library Version Numbers |
| 327 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 328 | ** |
| @@ -14123,10 +14123,13 @@ | |
| 14123 | #if SQLITE_ENABLE_CEROD |
| 14124 | "ENABLE_CEROD", |
| 14125 | #endif |
| 14126 | #if SQLITE_ENABLE_COLUMN_METADATA |
| 14127 | "ENABLE_COLUMN_METADATA", |
| 14128 | #endif |
| 14129 | #if SQLITE_ENABLE_DBSTAT_VTAB |
| 14130 | "ENABLE_DBSTAT_VTAB", |
| 14131 | #endif |
| 14132 | #if SQLITE_ENABLE_EXPENSIVE_ASSERT |
| 14133 | "ENABLE_EXPENSIVE_ASSERT", |
| 14134 | #endif |
| 14135 | #if SQLITE_ENABLE_FTS1 |
| @@ -155331,10 +155334,11 @@ | |
| 155334 | }; |
| 155335 | |
| 155336 | struct StatTable { |
| 155337 | sqlite3_vtab base; |
| 155338 | sqlite3 *db; |
| 155339 | int iDb; /* Index of database to analyze */ |
| 155340 | }; |
| 155341 | |
| 155342 | #ifndef get2byte |
| 155343 | # define get2byte(x) ((x)[0]<<8 | (x)[1]) |
| 155344 | #endif |
| @@ -155349,11 +155353,21 @@ | |
| 155353 | sqlite3_vtab **ppVtab, |
| 155354 | char **pzErr |
| 155355 | ){ |
| 155356 | StatTable *pTab = 0; |
| 155357 | int rc = SQLITE_OK; |
| 155358 | int iDb; |
| 155359 | |
| 155360 | if( argc>=4 ){ |
| 155361 | iDb = sqlite3FindDbName(db, argv[3]); |
| 155362 | if( iDb<0 ){ |
| 155363 | *pzErr = sqlite3_mprintf("no such database: %s", argv[3]); |
| 155364 | return SQLITE_ERROR; |
| 155365 | } |
| 155366 | }else{ |
| 155367 | iDb = 0; |
| 155368 | } |
| 155369 | rc = sqlite3_declare_vtab(db, VTAB_SCHEMA); |
| 155370 | if( rc==SQLITE_OK ){ |
| 155371 | pTab = (StatTable *)sqlite3_malloc64(sizeof(StatTable)); |
| 155372 | if( pTab==0 ) rc = SQLITE_NOMEM; |
| 155373 | } |
| @@ -155360,10 +155374,11 @@ | |
| 155374 | |
| 155375 | assert( rc==SQLITE_OK || pTab==0 ); |
| 155376 | if( rc==SQLITE_OK ){ |
| 155377 | memset(pTab, 0, sizeof(StatTable)); |
| 155378 | pTab->db = db; |
| 155379 | pTab->iDb = iDb; |
| 155380 | } |
| 155381 | |
| 155382 | *ppVtab = (sqlite3_vtab*)pTab; |
| 155383 | return rc; |
| 155384 | } |
| @@ -155414,20 +155429,26 @@ | |
| 155429 | |
| 155430 | pCsr = (StatCursor *)sqlite3_malloc64(sizeof(StatCursor)); |
| 155431 | if( pCsr==0 ){ |
| 155432 | rc = SQLITE_NOMEM; |
| 155433 | }else{ |
| 155434 | char *zSql; |
| 155435 | memset(pCsr, 0, sizeof(StatCursor)); |
| 155436 | pCsr->base.pVtab = pVTab; |
| 155437 | |
| 155438 | zSql = sqlite3_mprintf( |
| 155439 | "SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type" |
| 155440 | " UNION ALL " |
| 155441 | "SELECT name, rootpage, type" |
| 155442 | " FROM \"%w\".sqlite_master WHERE rootpage!=0" |
| 155443 | " ORDER BY name", pTab->db->aDb[pTab->iDb].zName); |
| 155444 | if( zSql==0 ){ |
| 155445 | rc = SQLITE_NOMEM; |
| 155446 | }else{ |
| 155447 | rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pStmt, 0); |
| 155448 | sqlite3_free(zSql); |
| 155449 | } |
| 155450 | if( rc!=SQLITE_OK ){ |
| 155451 | sqlite3_free(pCsr); |
| 155452 | pCsr = 0; |
| 155453 | } |
| 155454 | } |
| @@ -155589,11 +155610,11 @@ | |
| 155610 | ** Populate the pCsr->iOffset and pCsr->szPage member variables. Based on |
| 155611 | ** the current value of pCsr->iPageno. |
| 155612 | */ |
| 155613 | static void statSizeAndOffset(StatCursor *pCsr){ |
| 155614 | StatTable *pTab = (StatTable *)((sqlite3_vtab_cursor *)pCsr)->pVtab; |
| 155615 | Btree *pBt = pTab->db->aDb[pTab->iDb].pBt; |
| 155616 | Pager *pPager = sqlite3BtreePager(pBt); |
| 155617 | sqlite3_file *fd; |
| 155618 | sqlite3_int64 x[2]; |
| 155619 | |
| 155620 | /* The default page size and offset */ |
| @@ -155603,11 +155624,11 @@ | |
| 155624 | /* If connected to a ZIPVFS backend, override the page size and |
| 155625 | ** offset with actual values obtained from ZIPVFS. |
| 155626 | */ |
| 155627 | fd = sqlite3PagerFile(pPager); |
| 155628 | x[0] = pCsr->iPageno; |
| 155629 | if( fd->pMethods!=0 && sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){ |
| 155630 | pCsr->iOffset = x[0]; |
| 155631 | pCsr->szPage = (int)x[1]; |
| 155632 | } |
| 155633 | } |
| 155634 | |
| @@ -155615,13 +155636,14 @@ | |
| 155636 | ** Move a statvfs cursor to the next entry in the file. |
| 155637 | */ |
| 155638 | static int statNext(sqlite3_vtab_cursor *pCursor){ |
| 155639 | int rc; |
| 155640 | int nPayload; |
| 155641 | char *z; |
| 155642 | StatCursor *pCsr = (StatCursor *)pCursor; |
| 155643 | StatTable *pTab = (StatTable *)pCursor->pVtab; |
| 155644 | Btree *pBt = pTab->db->aDb[pTab->iDb].pBt; |
| 155645 | Pager *pPager = sqlite3BtreePager(pBt); |
| 155646 | |
| 155647 | sqlite3_free(pCsr->zPath); |
| 155648 | pCsr->zPath = 0; |
| 155649 | |
| @@ -155637,12 +155659,13 @@ | |
| 155659 | return sqlite3_reset(pCsr->pStmt); |
| 155660 | } |
| 155661 | rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg); |
| 155662 | pCsr->aPage[0].iPgno = iRoot; |
| 155663 | pCsr->aPage[0].iCell = 0; |
| 155664 | pCsr->aPage[0].zPath = z = sqlite3_mprintf("/"); |
| 155665 | pCsr->iPage = 0; |
| 155666 | if( z==0 ) rc = SQLITE_NOMEM; |
| 155667 | }else{ |
| 155668 | pCsr->isEof = 1; |
| 155669 | return sqlite3_reset(pCsr->pStmt); |
| 155670 | } |
| 155671 | }else{ |
| @@ -155661,11 +155684,11 @@ | |
| 155684 | pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0); |
| 155685 | pCsr->iPageno = pCell->aOvfl[pCell->iOvfl]; |
| 155686 | pCsr->zPagetype = "overflow"; |
| 155687 | pCsr->nCell = 0; |
| 155688 | pCsr->nMxPayload = 0; |
| 155689 | pCsr->zPath = z = sqlite3_mprintf( |
| 155690 | "%s%.3x+%.6x", p->zPath, p->iCell, pCell->iOvfl |
| 155691 | ); |
| 155692 | if( pCell->iOvfl<pCell->nOvfl-1 ){ |
| 155693 | pCsr->nUnused = 0; |
| 155694 | pCsr->nPayload = nUsable - 4; |
| @@ -155673,11 +155696,11 @@ | |
| 155696 | pCsr->nPayload = pCell->nLastOvfl; |
| 155697 | pCsr->nUnused = nUsable - 4 - pCsr->nPayload; |
| 155698 | } |
| 155699 | pCell->iOvfl++; |
| 155700 | statSizeAndOffset(pCsr); |
| 155701 | return z==0 ? SQLITE_NOMEM : SQLITE_OK; |
| 155702 | } |
| 155703 | if( p->iRightChildPg ) break; |
| 155704 | p->iCell++; |
| 155705 | } |
| 155706 | |
| @@ -155695,12 +155718,13 @@ | |
| 155718 | }else{ |
| 155719 | p[1].iPgno = p->aCell[p->iCell].iChildPg; |
| 155720 | } |
| 155721 | rc = sqlite3PagerGet(pPager, p[1].iPgno, &p[1].pPg); |
| 155722 | p[1].iCell = 0; |
| 155723 | p[1].zPath = z = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell); |
| 155724 | p->iCell++; |
| 155725 | if( z==0 ) rc = SQLITE_NOMEM; |
| 155726 | } |
| 155727 | |
| 155728 | |
| 155729 | /* Populate the StatCursor fields with the values to be returned |
| 155730 | ** by the xColumn() and xRowid() methods. |
| @@ -155729,11 +155753,12 @@ | |
| 155753 | break; |
| 155754 | } |
| 155755 | pCsr->nCell = p->nCell; |
| 155756 | pCsr->nUnused = p->nUnused; |
| 155757 | pCsr->nMxPayload = p->nMxPayload; |
| 155758 | pCsr->zPath = z = sqlite3_mprintf("%s", p->zPath); |
| 155759 | if( z==0 ) rc = SQLITE_NOMEM; |
| 155760 | nPayload = 0; |
| 155761 | for(i=0; i<p->nCell; i++){ |
| 155762 | nPayload += p->aCell[i].nLocal; |
| 155763 | } |
| 155764 | pCsr->nPayload = nPayload; |
| @@ -155765,11 +155790,11 @@ | |
| 155790 | int i |
| 155791 | ){ |
| 155792 | StatCursor *pCsr = (StatCursor *)pCursor; |
| 155793 | switch( i ){ |
| 155794 | case 0: /* name */ |
| 155795 | sqlite3_result_text(ctx, pCsr->zName, -1, SQLITE_TRANSIENT); |
| 155796 | break; |
| 155797 | case 1: /* path */ |
| 155798 | sqlite3_result_text(ctx, pCsr->zPath, -1, SQLITE_TRANSIENT); |
| 155799 | break; |
| 155800 | case 2: /* pageno */ |
| @@ -155791,11 +155816,12 @@ | |
| 155816 | sqlite3_result_int(ctx, pCsr->nMxPayload); |
| 155817 | break; |
| 155818 | case 8: /* pgoffset */ |
| 155819 | sqlite3_result_int64(ctx, pCsr->iOffset); |
| 155820 | break; |
| 155821 | default: /* pgsize */ |
| 155822 | assert( i==9 ); |
| 155823 | sqlite3_result_int(ctx, pCsr->szPage); |
| 155824 | break; |
| 155825 | } |
| 155826 | return SQLITE_OK; |
| 155827 | } |
| 155828 |
+2
-2
| --- src/sqlite3.h | ||
| +++ src/sqlite3.h | ||
| @@ -109,13 +109,13 @@ | ||
| 109 | 109 | ** |
| 110 | 110 | ** See also: [sqlite3_libversion()], |
| 111 | 111 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 112 | 112 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 113 | 113 | */ |
| 114 | -#define SQLITE_VERSION "3.8.10" | |
| 114 | +#define SQLITE_VERSION "3.8.10.1" | |
| 115 | 115 | #define SQLITE_VERSION_NUMBER 3008010 |
| 116 | -#define SQLITE_SOURCE_ID "2015-05-07 11:53:08 cf975957b9ae671f34bb65f049acf351e650d437" | |
| 116 | +#define SQLITE_SOURCE_ID "2015-05-09 12:14:55 05b4b1f2a937c06c90db70c09890038f6c98ec40" | |
| 117 | 117 | |
| 118 | 118 | /* |
| 119 | 119 | ** CAPI3REF: Run-Time Library Version Numbers |
| 120 | 120 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 121 | 121 | ** |
| 122 | 122 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -109,13 +109,13 @@ | |
| 109 | ** |
| 110 | ** See also: [sqlite3_libversion()], |
| 111 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 112 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 113 | */ |
| 114 | #define SQLITE_VERSION "3.8.10" |
| 115 | #define SQLITE_VERSION_NUMBER 3008010 |
| 116 | #define SQLITE_SOURCE_ID "2015-05-07 11:53:08 cf975957b9ae671f34bb65f049acf351e650d437" |
| 117 | |
| 118 | /* |
| 119 | ** CAPI3REF: Run-Time Library Version Numbers |
| 120 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 121 | ** |
| 122 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -109,13 +109,13 @@ | |
| 109 | ** |
| 110 | ** See also: [sqlite3_libversion()], |
| 111 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 112 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 113 | */ |
| 114 | #define SQLITE_VERSION "3.8.10.1" |
| 115 | #define SQLITE_VERSION_NUMBER 3008010 |
| 116 | #define SQLITE_SOURCE_ID "2015-05-09 12:14:55 05b4b1f2a937c06c90db70c09890038f6c98ec40" |
| 117 | |
| 118 | /* |
| 119 | ** CAPI3REF: Run-Time Library Version Numbers |
| 120 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 121 | ** |
| 122 |
+92
| --- src/stat.c | ||
| +++ src/stat.c | ||
| @@ -36,10 +36,25 @@ | ||
| 36 | 36 | }else{ |
| 37 | 37 | sqlite3_snprintf(nOut, zOut, "%lld bytes (%.1fGB)", |
| 38 | 38 | v, (double)v/1000000000.0); |
| 39 | 39 | } |
| 40 | 40 | } |
| 41 | + | |
| 42 | +/* | |
| 43 | +** Return the approximate size as KB, MB, GB, or TB. | |
| 44 | +*/ | |
| 45 | +void approxSizeName(int nOut, char *zOut, sqlite3_int64 v){ | |
| 46 | + if( v<1000 ){ | |
| 47 | + sqlite3_snprintf(nOut, zOut, "%lld bytes", v); | |
| 48 | + }else if( v<1000000 ){ | |
| 49 | + sqlite3_snprintf(nOut, zOut, "%.1fKB", (double)v/1000.0); | |
| 50 | + }else if( v<1000000000 ){ | |
| 51 | + sqlite3_snprintf(nOut, zOut, "%.1fMB", (double)v/1000000.0); | |
| 52 | + }else{ | |
| 53 | + sqlite3_snprintf(nOut, zOut, "%.1fGB", (double)v/1000000000.0); | |
| 54 | + } | |
| 55 | +} | |
| 41 | 56 | |
| 42 | 57 | /* |
| 43 | 58 | ** WEBPAGE: stat |
| 44 | 59 | ** |
| 45 | 60 | ** Show statistics and global information about the repository. |
| @@ -63,10 +78,13 @@ | ||
| 63 | 78 | style_submenu_element("Schema", "Repository Schema", "repo_schema"); |
| 64 | 79 | style_submenu_element("Web-Cache", "Web-Cache Stats", "cachestat"); |
| 65 | 80 | } |
| 66 | 81 | style_submenu_element("Activity Reports", 0, "reports"); |
| 67 | 82 | style_submenu_element("SHA1 Collisions", 0, "hash-collisions"); |
| 83 | + if( sqlite3_libversion_number()>=3008010 ){ | |
| 84 | + style_submenu_element("Table Sizes", 0, "repo-tabsize"); | |
| 85 | + } | |
| 68 | 86 | @ <table class="label-value"> |
| 69 | 87 | @ <tr><th>Repository Size:</th><td> |
| 70 | 88 | fsize = file_size(g.zRepositoryName); |
| 71 | 89 | bigSizeName(sizeof(zBuf), zBuf, fsize); |
| 72 | 90 | @ %s(zBuf) |
| @@ -355,5 +373,79 @@ | ||
| 355 | 373 | } |
| 356 | 374 | @ </pre> |
| 357 | 375 | db_finalize(&q); |
| 358 | 376 | style_footer(); |
| 359 | 377 | } |
| 378 | + | |
| 379 | +/* | |
| 380 | +** WEBPAGE: repo-tabsize | |
| 381 | +** | |
| 382 | +** Show relative sizes of tables in the repository database. | |
| 383 | +*/ | |
| 384 | +void repo_tabsize_page(void){ | |
| 385 | + int nPageFree; | |
| 386 | + sqlite3_int64 fsize; | |
| 387 | + char zBuf[100]; | |
| 388 | + | |
| 389 | + login_check_credentials(); | |
| 390 | + if( !g.perm.Read ){ login_needed(g.anon.Read); return; } | |
| 391 | + style_header("Repository Table Sizes"); | |
| 392 | + style_adunit_config(ADUNIT_RIGHT_OK); | |
| 393 | + style_submenu_element("Stat", "Repository Stats", "stat"); | |
| 394 | + db_multi_exec( | |
| 395 | + "CREATE VIRTUAL TABLE temp.dbx USING dbstat(%s);" | |
| 396 | + "CREATE TEMP TABLE trans(name TEXT PRIMARY KEY, tabname TEXT)WITHOUT ROWID;" | |
| 397 | + "INSERT INTO trans(name,tabname)" | |
| 398 | + " SELECT name, tbl_name FROM %s.sqlite_master;" | |
| 399 | + "CREATE TEMP TABLE piechart(amt REAL, label TEXT);" | |
| 400 | + "INSERT INTO piechart(amt,label)" | |
| 401 | + " SELECT count(*), " | |
| 402 | + " coalesce((SELECT tabname FROM trans WHERE trans.name=dbx.name),name)" | |
| 403 | + " FROM dbx" | |
| 404 | + " GROUP BY 2 ORDER BY 2;", | |
| 405 | + db_name("repository"), db_name("repository") | |
| 406 | + ); | |
| 407 | + nPageFree = db_int(0, "PRAGMA \"%w\".freelist_count", db_name("repository")); | |
| 408 | + if( nPageFree>0 ){ | |
| 409 | + db_multi_exec( | |
| 410 | + "INSERT INTO piechart(amt,label) VALUES(%d,'freelist')", | |
| 411 | + nPageFree | |
| 412 | + ); | |
| 413 | + } | |
| 414 | + fsize = file_size(g.zRepositoryName); | |
| 415 | + approxSizeName(sizeof(zBuf), zBuf, fsize); | |
| 416 | + @ <h2>Repository Size: %s(zBuf)</h2> | |
| 417 | + @ <center><svg width='800' height='500'> | |
| 418 | + piechart_render(800,500,PIE_OTHER|PIE_PERCENT); | |
| 419 | + @ </svg></center> | |
| 420 | + | |
| 421 | + if( g.localOpen ){ | |
| 422 | + db_multi_exec( | |
| 423 | + "DROP TABLE temp.dbx;" | |
| 424 | + "CREATE VIRTUAL TABLE temp.dbx USING dbstat(%s);" | |
| 425 | + "DELETE FROM trans;" | |
| 426 | + "INSERT INTO trans(name,tabname)" | |
| 427 | + " SELECT name, tbl_name FROM %s.sqlite_master;" | |
| 428 | + "DELETE FROM piechart;" | |
| 429 | + "INSERT INTO piechart(amt,label)" | |
| 430 | + " SELECT count(*), " | |
| 431 | + " coalesce((SELECT tabname FROM trans WHERE trans.name=dbx.name),name)" | |
| 432 | + " FROM dbx" | |
| 433 | + " GROUP BY 2 ORDER BY 2;", | |
| 434 | + db_name("localdb"), db_name("localdb") | |
| 435 | + ); | |
| 436 | + nPageFree = db_int(0, "PRAGMA \"%s\".freelist_count", db_name("localdb")); | |
| 437 | + if( nPageFree>0 ){ | |
| 438 | + db_multi_exec( | |
| 439 | + "INSERT INTO piechart(amt,label) VALUES(%d,'freelist')", | |
| 440 | + nPageFree | |
| 441 | + ); | |
| 442 | + } | |
| 443 | + fsize = file_size(g.zLocalDbName); | |
| 444 | + approxSizeName(sizeof(zBuf), zBuf, fsize); | |
| 445 | + @ <h2>%h(file_tail(g.zLocalDbName)) Size: %s(zBuf)</h2> | |
| 446 | + @ <center><svg width='800' height='500'> | |
| 447 | + piechart_render(800,500,PIE_OTHER|PIE_PERCENT); | |
| 448 | + @ </svg></center> | |
| 449 | + } | |
| 450 | + style_footer(); | |
| 451 | +} | |
| 360 | 452 |
| --- src/stat.c | |
| +++ src/stat.c | |
| @@ -36,10 +36,25 @@ | |
| 36 | }else{ |
| 37 | sqlite3_snprintf(nOut, zOut, "%lld bytes (%.1fGB)", |
| 38 | v, (double)v/1000000000.0); |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | /* |
| 43 | ** WEBPAGE: stat |
| 44 | ** |
| 45 | ** Show statistics and global information about the repository. |
| @@ -63,10 +78,13 @@ | |
| 63 | style_submenu_element("Schema", "Repository Schema", "repo_schema"); |
| 64 | style_submenu_element("Web-Cache", "Web-Cache Stats", "cachestat"); |
| 65 | } |
| 66 | style_submenu_element("Activity Reports", 0, "reports"); |
| 67 | style_submenu_element("SHA1 Collisions", 0, "hash-collisions"); |
| 68 | @ <table class="label-value"> |
| 69 | @ <tr><th>Repository Size:</th><td> |
| 70 | fsize = file_size(g.zRepositoryName); |
| 71 | bigSizeName(sizeof(zBuf), zBuf, fsize); |
| 72 | @ %s(zBuf) |
| @@ -355,5 +373,79 @@ | |
| 355 | } |
| 356 | @ </pre> |
| 357 | db_finalize(&q); |
| 358 | style_footer(); |
| 359 | } |
| 360 |
| --- src/stat.c | |
| +++ src/stat.c | |
| @@ -36,10 +36,25 @@ | |
| 36 | }else{ |
| 37 | sqlite3_snprintf(nOut, zOut, "%lld bytes (%.1fGB)", |
| 38 | v, (double)v/1000000000.0); |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | /* |
| 43 | ** Return the approximate size as KB, MB, GB, or TB. |
| 44 | */ |
| 45 | void approxSizeName(int nOut, char *zOut, sqlite3_int64 v){ |
| 46 | if( v<1000 ){ |
| 47 | sqlite3_snprintf(nOut, zOut, "%lld bytes", v); |
| 48 | }else if( v<1000000 ){ |
| 49 | sqlite3_snprintf(nOut, zOut, "%.1fKB", (double)v/1000.0); |
| 50 | }else if( v<1000000000 ){ |
| 51 | sqlite3_snprintf(nOut, zOut, "%.1fMB", (double)v/1000000.0); |
| 52 | }else{ |
| 53 | sqlite3_snprintf(nOut, zOut, "%.1fGB", (double)v/1000000000.0); |
| 54 | } |
| 55 | } |
| 56 | |
| 57 | /* |
| 58 | ** WEBPAGE: stat |
| 59 | ** |
| 60 | ** Show statistics and global information about the repository. |
| @@ -63,10 +78,13 @@ | |
| 78 | style_submenu_element("Schema", "Repository Schema", "repo_schema"); |
| 79 | style_submenu_element("Web-Cache", "Web-Cache Stats", "cachestat"); |
| 80 | } |
| 81 | style_submenu_element("Activity Reports", 0, "reports"); |
| 82 | style_submenu_element("SHA1 Collisions", 0, "hash-collisions"); |
| 83 | if( sqlite3_libversion_number()>=3008010 ){ |
| 84 | style_submenu_element("Table Sizes", 0, "repo-tabsize"); |
| 85 | } |
| 86 | @ <table class="label-value"> |
| 87 | @ <tr><th>Repository Size:</th><td> |
| 88 | fsize = file_size(g.zRepositoryName); |
| 89 | bigSizeName(sizeof(zBuf), zBuf, fsize); |
| 90 | @ %s(zBuf) |
| @@ -355,5 +373,79 @@ | |
| 373 | } |
| 374 | @ </pre> |
| 375 | db_finalize(&q); |
| 376 | style_footer(); |
| 377 | } |
| 378 | |
| 379 | /* |
| 380 | ** WEBPAGE: repo-tabsize |
| 381 | ** |
| 382 | ** Show relative sizes of tables in the repository database. |
| 383 | */ |
| 384 | void repo_tabsize_page(void){ |
| 385 | int nPageFree; |
| 386 | sqlite3_int64 fsize; |
| 387 | char zBuf[100]; |
| 388 | |
| 389 | login_check_credentials(); |
| 390 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 391 | style_header("Repository Table Sizes"); |
| 392 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 393 | style_submenu_element("Stat", "Repository Stats", "stat"); |
| 394 | db_multi_exec( |
| 395 | "CREATE VIRTUAL TABLE temp.dbx USING dbstat(%s);" |
| 396 | "CREATE TEMP TABLE trans(name TEXT PRIMARY KEY, tabname TEXT)WITHOUT ROWID;" |
| 397 | "INSERT INTO trans(name,tabname)" |
| 398 | " SELECT name, tbl_name FROM %s.sqlite_master;" |
| 399 | "CREATE TEMP TABLE piechart(amt REAL, label TEXT);" |
| 400 | "INSERT INTO piechart(amt,label)" |
| 401 | " SELECT count(*), " |
| 402 | " coalesce((SELECT tabname FROM trans WHERE trans.name=dbx.name),name)" |
| 403 | " FROM dbx" |
| 404 | " GROUP BY 2 ORDER BY 2;", |
| 405 | db_name("repository"), db_name("repository") |
| 406 | ); |
| 407 | nPageFree = db_int(0, "PRAGMA \"%w\".freelist_count", db_name("repository")); |
| 408 | if( nPageFree>0 ){ |
| 409 | db_multi_exec( |
| 410 | "INSERT INTO piechart(amt,label) VALUES(%d,'freelist')", |
| 411 | nPageFree |
| 412 | ); |
| 413 | } |
| 414 | fsize = file_size(g.zRepositoryName); |
| 415 | approxSizeName(sizeof(zBuf), zBuf, fsize); |
| 416 | @ <h2>Repository Size: %s(zBuf)</h2> |
| 417 | @ <center><svg width='800' height='500'> |
| 418 | piechart_render(800,500,PIE_OTHER|PIE_PERCENT); |
| 419 | @ </svg></center> |
| 420 | |
| 421 | if( g.localOpen ){ |
| 422 | db_multi_exec( |
| 423 | "DROP TABLE temp.dbx;" |
| 424 | "CREATE VIRTUAL TABLE temp.dbx USING dbstat(%s);" |
| 425 | "DELETE FROM trans;" |
| 426 | "INSERT INTO trans(name,tabname)" |
| 427 | " SELECT name, tbl_name FROM %s.sqlite_master;" |
| 428 | "DELETE FROM piechart;" |
| 429 | "INSERT INTO piechart(amt,label)" |
| 430 | " SELECT count(*), " |
| 431 | " coalesce((SELECT tabname FROM trans WHERE trans.name=dbx.name),name)" |
| 432 | " FROM dbx" |
| 433 | " GROUP BY 2 ORDER BY 2;", |
| 434 | db_name("localdb"), db_name("localdb") |
| 435 | ); |
| 436 | nPageFree = db_int(0, "PRAGMA \"%s\".freelist_count", db_name("localdb")); |
| 437 | if( nPageFree>0 ){ |
| 438 | db_multi_exec( |
| 439 | "INSERT INTO piechart(amt,label) VALUES(%d,'freelist')", |
| 440 | nPageFree |
| 441 | ); |
| 442 | } |
| 443 | fsize = file_size(g.zLocalDbName); |
| 444 | approxSizeName(sizeof(zBuf), zBuf, fsize); |
| 445 | @ <h2>%h(file_tail(g.zLocalDbName)) Size: %s(zBuf)</h2> |
| 446 | @ <center><svg width='800' height='500'> |
| 447 | piechart_render(800,500,PIE_OTHER|PIE_PERCENT); |
| 448 | @ </svg></center> |
| 449 | } |
| 450 | style_footer(); |
| 451 | } |
| 452 |
+270
-264
| --- src/statrep.c | ||
| +++ src/statrep.c | ||
| @@ -141,63 +141,10 @@ | ||
| 141 | 141 | default: |
| 142 | 142 | return "all types"; |
| 143 | 143 | } |
| 144 | 144 | } |
| 145 | 145 | |
| 146 | -/* | |
| 147 | -** A helper for the /reports family of pages which prints out a menu | |
| 148 | -** of links for the various type=XXX flags. zCurrentViewName must be | |
| 149 | -** the name/value of the 'view' parameter which is in effect at the | |
| 150 | -** time this is called. e.g. if called from the 'byuser' view then | |
| 151 | -** zCurrentViewName must be "byuser". Any URL parameters which need to | |
| 152 | -** be added to the generated URLs should be passed in zParam. The | |
| 153 | -** caller is expected to have already encoded any zParam in the %T or | |
| 154 | -** %t encoding. */ | |
| 155 | -static void stats_report_event_types_menu(const char *zCurrentViewName, | |
| 156 | - const char *zParam){ | |
| 157 | - char *zTop; | |
| 158 | - if(zParam && !*zParam){ | |
| 159 | - zParam = NULL; | |
| 160 | - } | |
| 161 | - zTop = mprintf("%s/reports?view=%s%s%s", g.zTop, zCurrentViewName, | |
| 162 | - zParam ? "&" : "", zParam); | |
| 163 | - cgi_printf("<div>"); | |
| 164 | - cgi_printf("<span>Types:</span> "); | |
| 165 | - if('*' == statsReportType){ | |
| 166 | - cgi_printf(" <strong>all</strong>", zTop); | |
| 167 | - }else{ | |
| 168 | - cgi_printf(" <a href='%s'>all</a>", zTop); | |
| 169 | - } | |
| 170 | - if('c' == statsReportType){ | |
| 171 | - cgi_printf(" <strong>check-ins</strong>", zTop); | |
| 172 | - }else{ | |
| 173 | - cgi_printf(" <a href='%s&type=ci'>check-ins</a>", zTop); | |
| 174 | - } | |
| 175 | - if('e' == statsReportType){ | |
| 176 | - cgi_printf(" <strong>technotes</strong>", zTop); | |
| 177 | - }else{ | |
| 178 | - cgi_printf(" <a href='%s&type=e'>technotes</a>", zTop); | |
| 179 | - } | |
| 180 | - if( 't' == statsReportType ){ | |
| 181 | - cgi_printf(" <strong>tickets</strong>", zTop); | |
| 182 | - }else{ | |
| 183 | - cgi_printf(" <a href='%s&type=t'>tickets</a>", zTop); | |
| 184 | - } | |
| 185 | - if( 'g' == statsReportType ){ | |
| 186 | - cgi_printf(" <strong>tags</strong>", zTop); | |
| 187 | - }else{ | |
| 188 | - cgi_printf(" <a href='%s&type=g'>tags</a>", zTop); | |
| 189 | - } | |
| 190 | - if( 'w' == statsReportType ){ | |
| 191 | - cgi_printf(" <strong>wiki</strong>", zTop); | |
| 192 | - }else{ | |
| 193 | - cgi_printf(" <a href='%s&type=w'>wiki</a>", zTop); | |
| 194 | - } | |
| 195 | - fossil_free(zTop); | |
| 196 | - cgi_printf("</div>"); | |
| 197 | -} | |
| 198 | - | |
| 199 | 146 | |
| 200 | 147 | /* |
| 201 | 148 | ** Helper for stats_report_by_month_year(), which generates a list of |
| 202 | 149 | ** week numbers. zTimeframe should be either a timeframe in the form YYYY |
| 203 | 150 | ** or YYYY-MM. |
| @@ -227,23 +174,21 @@ | ||
| 227 | 174 | } |
| 228 | 175 | |
| 229 | 176 | /* |
| 230 | 177 | ** Implements the "byyear" and "bymonth" reports for /reports. |
| 231 | 178 | ** If includeMonth is true then it generates the "bymonth" report, |
| 232 | -** else the "byyear" report. If zUserName is not NULL and not empty | |
| 233 | -** then the report is restricted to events created by the named user | |
| 234 | -** account. | |
| 179 | +** else the "byyear" report. If zUserName is not NULL then the report is | |
| 180 | +** restricted to events created by the named user account. | |
| 235 | 181 | */ |
| 236 | 182 | static void stats_report_by_month_year(char includeMonth, |
| 237 | 183 | char includeWeeks, |
| 238 | 184 | const char *zUserName){ |
| 239 | 185 | Stmt query = empty_Stmt; |
| 240 | 186 | int nRowNumber = 0; /* current TR number */ |
| 241 | 187 | int nEventTotal = 0; /* Total event count */ |
| 242 | 188 | int rowClass = 0; /* counter for alternating |
| 243 | 189 | row colors */ |
| 244 | - Blob sql = empty_blob; /* SQL */ | |
| 245 | 190 | const char *zTimeLabel = includeMonth ? "Year/Month" : "Year"; |
| 246 | 191 | char zPrevYear[5] = {0}; /* For keeping track of when |
| 247 | 192 | we change years while looping */ |
| 248 | 193 | int nEventsPerYear = 0; /* Total event count for the |
| 249 | 194 | current year */ |
| @@ -252,39 +197,37 @@ | ||
| 252 | 197 | Blob header = empty_blob; /* Page header text */ |
| 253 | 198 | int nMaxEvents = 1; /* for calculating length of graph |
| 254 | 199 | bars. */ |
| 255 | 200 | int iterations = 0; /* number of weeks/months we iterate |
| 256 | 201 | over */ |
| 202 | + Blob userFilter = empty_blob; /* Optional user=johndoe query string */ | |
| 257 | 203 | stats_report_init_view(); |
| 258 | - stats_report_event_types_menu( includeMonth ? "bymonth" : "byyear", NULL ); | |
| 259 | - blob_appendf(&header, "Timeline Events (%s) by year%s", | |
| 260 | - stats_report_label_for_type(), | |
| 261 | - (includeMonth ? "/month" : "")); | |
| 262 | - blob_append_sql(&sql, | |
| 263 | - "SELECT substr(date(mtime),1,%d) AS timeframe, " | |
| 264 | - "count(*) AS eventCount " | |
| 265 | - "FROM v_reports ", | |
| 266 | - includeMonth ? 7 : 4); | |
| 267 | - if(zUserName&&*zUserName){ | |
| 268 | - blob_append_sql(&sql, " WHERE user=%Q ", zUserName); | |
| 269 | - blob_appendf(&header," for user %q", zUserName); | |
| 270 | - } | |
| 271 | - blob_append(&sql, | |
| 272 | - " GROUP BY timeframe" | |
| 273 | - " ORDER BY timeframe DESC", | |
| 274 | - -1); | |
| 275 | - db_prepare(&query, "%s", blob_sql_text(&sql)); | |
| 276 | - blob_reset(&sql); | |
| 277 | - @ <h1>%b(&header)</h1> | |
| 204 | + if( zUserName ){ | |
| 205 | + blob_appendf(&userFilter, "user=%s", zUserName); | |
| 206 | + } | |
| 207 | + blob_reset(&userFilter); | |
| 208 | + db_prepare(&query, | |
| 209 | + "SELECT substr(date(mtime),1,%d) AS timeframe," | |
| 210 | + " count(*) AS eventCount" | |
| 211 | + " FROM v_reports" | |
| 212 | + " WHERE ifnull(coalesce(euser,user,'')=%Q,1)" | |
| 213 | + " GROUP BY timeframe" | |
| 214 | + " ORDER BY timeframe DESC", | |
| 215 | + includeMonth ? 7 : 4, zUserName); | |
| 216 | + @ <h1>Timeline Events (%s(stats_report_label_for_type())) | |
| 217 | + @ by year%s(includeMonth ? "/month" : "") | |
| 218 | + if( zUserName ){ | |
| 219 | + @ for user %h(zUserName) | |
| 220 | + } | |
| 221 | + @ </h1> | |
| 278 | 222 | @ <table class='statistics-report-table-events' border='0' cellpadding='2' |
| 279 | 223 | @ cellspacing='0' id='statsTable'> |
| 280 | 224 | @ <thead> |
| 281 | 225 | @ <th>%s(zTimeLabel)</th> |
| 282 | 226 | @ <th>Events</th> |
| 283 | 227 | @ <th width='90%%'><!-- relative commits graph --></th> |
| 284 | 228 | @ </thead><tbody> |
| 285 | - blob_reset(&header); | |
| 286 | 229 | /* |
| 287 | 230 | Run the query twice. The first time we calculate the maximum |
| 288 | 231 | number of events for a given row. Maybe someone with better SQL |
| 289 | 232 | Fu can re-implement this with a single query. |
| 290 | 233 | */ |
| @@ -335,18 +278,18 @@ | ||
| 335 | 278 | zTimeframe, nCount, |
| 336 | 279 | statsReportTimelineYFlag ); |
| 337 | 280 | /* Reminder: n=nCount is not actually correct for bymonth unless |
| 338 | 281 | that was the only user who caused events. |
| 339 | 282 | */ |
| 340 | - if( zUserName && *zUserName ){ | |
| 283 | + if( zUserName ){ | |
| 341 | 284 | cgi_printf("&u=%t", zUserName); |
| 342 | 285 | } |
| 343 | 286 | cgi_printf("' target='_new'>%s</a>",zTimeframe); |
| 344 | 287 | }else { |
| 345 | 288 | cgi_printf("<a href='?view=byweek&y=%s&type=%c", |
| 346 | 289 | zTimeframe, (char)statsReportType); |
| 347 | - if(zUserName && *zUserName){ | |
| 290 | + if( zUserName ){ | |
| 348 | 291 | cgi_printf("&u=%t", zUserName); |
| 349 | 292 | } |
| 350 | 293 | cgi_printf("'>%s</a>", zTimeframe); |
| 351 | 294 | } |
| 352 | 295 | @ </td><td>%d(nCount)</td> |
| @@ -403,25 +346,34 @@ | ||
| 403 | 346 | int rowClass = 0; /* counter for alternating |
| 404 | 347 | row colors */ |
| 405 | 348 | int nMaxEvents = 1; /* max number of events for |
| 406 | 349 | all rows. */ |
| 407 | 350 | stats_report_init_view(); |
| 408 | - stats_report_event_types_menu("byuser", NULL); | |
| 409 | - db_prepare(&query, | |
| 410 | - "SELECT user, " | |
| 411 | - "COUNT(*) AS eventCount " | |
| 412 | - "FROM v_reports " | |
| 413 | - "GROUP BY user ORDER BY eventCount DESC"); | |
| 414 | 351 | @ <h1>Timeline Events |
| 415 | 352 | @ (%s(stats_report_label_for_type())) by User</h1> |
| 353 | + db_multi_exec( | |
| 354 | + "CREATE TEMP TABLE piechart(amt,label);" | |
| 355 | + "INSERT INTO piechart SELECT count(*), ifnull(euser,user) FROM v_reports" | |
| 356 | + " GROUP BY ifnull(euser,user) ORDER BY count(*) DESC;" | |
| 357 | + ); | |
| 358 | + if( db_int(0, "SELECT count(*) FROM piechart")>=2 ){ | |
| 359 | + @ <center><svg width=700 height=400> | |
| 360 | + piechart_render(700, 400, PIE_OTHER|PIE_PERCENT); | |
| 361 | + @ </svg></centre><hr/> | |
| 362 | + } | |
| 416 | 363 | @ <table class='statistics-report-table-events' border='0' |
| 417 | 364 | @ cellpadding='2' cellspacing='0' id='statsTable'> |
| 418 | 365 | @ <thead><tr> |
| 419 | 366 | @ <th>User</th> |
| 420 | 367 | @ <th>Events</th> |
| 421 | 368 | @ <th width='90%%'><!-- relative commits graph --></th> |
| 422 | 369 | @ </tr></thead><tbody> |
| 370 | + db_prepare(&query, | |
| 371 | + "SELECT ifnull(euser,user), " | |
| 372 | + "COUNT(*) AS eventCount " | |
| 373 | + "FROM v_reports " | |
| 374 | + "GROUP BY ifnull(euser,user) ORDER BY eventCount DESC"); | |
| 423 | 375 | while( SQLITE_ROW == db_step(&query) ){ |
| 424 | 376 | const int nCount = db_column_int(&query, 1); |
| 425 | 377 | if(nCount>nMaxEvents){ |
| 426 | 378 | nMaxEvents = nCount; |
| 427 | 379 | } |
| @@ -428,20 +380,21 @@ | ||
| 428 | 380 | } |
| 429 | 381 | db_reset(&query); |
| 430 | 382 | while( SQLITE_ROW == db_step(&query) ){ |
| 431 | 383 | const char *zUser = db_column_text(&query, 0); |
| 432 | 384 | const int nCount = db_column_int(&query, 1); |
| 385 | + char y = (char)statsReportType; | |
| 433 | 386 | int nSize = nCount |
| 434 | 387 | ? (int)(100 * nCount / nMaxEvents) |
| 435 | 388 | : 0; |
| 436 | 389 | if(!nCount) continue /* arguable! Possible? */; |
| 437 | 390 | else if(!nSize) nSize = 1; |
| 438 | 391 | rowClass = ++nRowNumber % 2; |
| 439 | 392 | nEventTotal += nCount; |
| 440 | - @<tr class='row%d(rowClass)'> | |
| 393 | + @ <tr class='row%d(rowClass)'> | |
| 441 | 394 | @ <td> |
| 442 | - @ <a href="?view=bymonth&user=%h(zUser)&type=%c((char)statsReportType)">%h(zUser)</a> | |
| 395 | + @ <a href="?view=bymonth&user=%h(zUser)&type=%c(y)">%h(zUser)</a> | |
| 443 | 396 | @ </td><td data-sortkey='%08x(-nCount)'>%d(nCount)</td> |
| 444 | 397 | @ <td> |
| 445 | 398 | @ <div class='statistics-report-graph-line' |
| 446 | 399 | @ style='width:%d(nSize)%%;'> </div> |
| 447 | 400 | @ </td> |
| @@ -455,30 +408,37 @@ | ||
| 455 | 408 | db_finalize(&query); |
| 456 | 409 | output_table_sorting_javascript("statsTable","tkx",2); |
| 457 | 410 | } |
| 458 | 411 | |
| 459 | 412 | /* |
| 460 | -** Implements the "byfile" view for /reports. | |
| 413 | +** Implements the "byfile" view for /reports. If zUserName is not NULL then the | |
| 414 | +** report is restricted to events created by the named user account. | |
| 461 | 415 | */ |
| 462 | -static void stats_report_by_file(){ | |
| 416 | +static void stats_report_by_file(const char *zUserName){ | |
| 463 | 417 | Stmt query; |
| 464 | 418 | int mxEvent = 1; /* max number of events across all rows */ |
| 465 | 419 | int nRowNumber = 0; |
| 466 | 420 | |
| 467 | 421 | db_multi_exec( |
| 468 | 422 | "CREATE TEMP TABLE statrep(filename, cnt);" |
| 469 | 423 | "INSERT INTO statrep(filename, cnt)" |
| 470 | 424 | " SELECT filename.name, count(distinct mlink.mid)" |
| 471 | - " FROM filename, mlink" | |
| 425 | + " FROM filename, mlink, event" | |
| 472 | 426 | " WHERE filename.fnid=mlink.fnid" |
| 473 | - " GROUP BY 1" | |
| 427 | + " AND mlink.mid=event.objid" | |
| 428 | + " AND ifnull(coalesce(euser,user,'')=%Q,1)" | |
| 429 | + " GROUP BY 1", zUserName | |
| 474 | 430 | ); |
| 475 | 431 | db_prepare(&query, |
| 476 | 432 | "SELECT filename, cnt FROM statrep ORDER BY cnt DESC, filename /*sort*/" |
| 477 | 433 | ); |
| 478 | 434 | mxEvent = db_int(1, "SELECT max(cnt) FROM statrep"); |
| 479 | - @ <h1>Check-ins Per File</h1> | |
| 435 | + @ <h1>Check-ins Per File | |
| 436 | + if( zUserName ){ | |
| 437 | + @ for user %h(zUserName) | |
| 438 | + } | |
| 439 | + @ </h1> | |
| 480 | 440 | @ <table class='statistics-report-table-events' border='0' |
| 481 | 441 | @ cellpadding='2' cellspacing='0' id='statsTable'> |
| 482 | 442 | @ <thead><tr> |
| 483 | 443 | @ <th>File</th> |
| 484 | 444 | @ <th>Check-ins</th> |
| @@ -504,34 +464,62 @@ | ||
| 504 | 464 | db_finalize(&query); |
| 505 | 465 | output_table_sorting_javascript("statsTable","tNx",2); |
| 506 | 466 | } |
| 507 | 467 | |
| 508 | 468 | /* |
| 509 | -** Implements the "byweekday" view for /reports. | |
| 469 | +** Implements the "byweekday" view for /reports. If zUserName is not NULL then | |
| 470 | +** the report is restricted to events created by the named user account. | |
| 510 | 471 | */ |
| 511 | -static void stats_report_day_of_week(){ | |
| 472 | +static void stats_report_day_of_week(const char *zUserName){ | |
| 512 | 473 | Stmt query = empty_Stmt; |
| 513 | 474 | int nRowNumber = 0; /* current TR number */ |
| 514 | 475 | int nEventTotal = 0; /* Total event count */ |
| 515 | 476 | int rowClass = 0; /* counter for alternating |
| 516 | 477 | row colors */ |
| 517 | 478 | int nMaxEvents = 1; /* max number of events for |
| 518 | 479 | all rows. */ |
| 480 | + Blob userFilter = empty_blob; /* Optional user=johndoe query string */ | |
| 519 | 481 | static const char *const daysOfWeek[] = { |
| 520 | 482 | "Monday", "Tuesday", "Wednesday", "Thursday", |
| 521 | 483 | "Friday", "Saturday", "Sunday" |
| 522 | 484 | }; |
| 523 | 485 | |
| 524 | 486 | stats_report_init_view(); |
| 525 | - stats_report_event_types_menu("byweekday", NULL); | |
| 487 | + if( zUserName ){ | |
| 488 | + blob_appendf(&userFilter, "user=%s", zUserName); | |
| 489 | + } | |
| 526 | 490 | db_prepare(&query, |
| 527 | - "SELECT cast(mtime %% 7 AS INTEGER) dow, " | |
| 528 | - "COUNT(*) AS eventCount " | |
| 529 | - "FROM v_reports " | |
| 530 | - "GROUP BY dow ORDER BY dow"); | |
| 531 | - @ <h1>Timeline Events | |
| 532 | - @ (%s(stats_report_label_for_type())) by Day of the Week</h1> | |
| 491 | + "SELECT cast(mtime %% 7 AS INTEGER) dow," | |
| 492 | + " COUNT(*) AS eventCount" | |
| 493 | + " FROM v_reports" | |
| 494 | + " WHERE ifnull(coalesce(euser,user,'')=%Q,1)" | |
| 495 | + " GROUP BY dow ORDER BY dow", zUserName); | |
| 496 | + @ <h1>Timeline Events (%h(stats_report_label_for_type())) by Day of the Week | |
| 497 | + if( zUserName ){ | |
| 498 | + @ for user %h(zUserName) | |
| 499 | + } | |
| 500 | + @ </h1> | |
| 501 | + db_multi_exec( | |
| 502 | + "CREATE TEMP TABLE piechart(amt,label);" | |
| 503 | + "INSERT INTO piechart" | |
| 504 | + " SELECT count(*), cast(mtime %% 7 AS INT) FROM v_reports" | |
| 505 | + " WHERE ifnull(coalesce(euser,user,'')=%Q,1)" | |
| 506 | + " GROUP BY 2 ORDER BY 2;" | |
| 507 | + "UPDATE piechart SET label = CASE label" | |
| 508 | + " WHEN 0 THEN 'Monday'" | |
| 509 | + " WHEN 1 THEN 'Tuesday'" | |
| 510 | + " WHEN 2 THEN 'Wednesday'" | |
| 511 | + " WHEN 3 THEN 'Thursday'" | |
| 512 | + " WHEN 4 THEN 'Friday'" | |
| 513 | + " WHEN 5 THEN 'Saturday'" | |
| 514 | + " ELSE 'Sunday' END;", zUserName | |
| 515 | + ); | |
| 516 | + if( db_int(0, "SELECT count(*) FROM piechart")>=2 ){ | |
| 517 | + @ <center><svg width=700 height=400> | |
| 518 | + piechart_render(700, 400, PIE_OTHER|PIE_PERCENT); | |
| 519 | + @ </svg></centre><hr/> | |
| 520 | + } | |
| 533 | 521 | @ <table class='statistics-report-table-events' border='0' |
| 534 | 522 | @ cellpadding='2' cellspacing='0' id='statsTable'> |
| 535 | 523 | @ <thead><tr> |
| 536 | 524 | @ <th>DoW</th> |
| 537 | 525 | @ <th>Day</th> |
| @@ -572,139 +560,114 @@ | ||
| 572 | 560 | |
| 573 | 561 | |
| 574 | 562 | /* |
| 575 | 563 | ** Helper for stats_report_by_month_year(), which generates a list of |
| 576 | 564 | ** week numbers. zTimeframe should be either a timeframe in the form YYYY |
| 577 | -** or YYYY-MM. | |
| 565 | +** or YYYY-MM. If zUserName is not NULL then the report is restricted to events | |
| 566 | +** created by the named user account. | |
| 578 | 567 | */ |
| 579 | 568 | static void stats_report_year_weeks(const char *zUserName){ |
| 580 | - const char *zYear = P("y"); | |
| 581 | - int nYear = zYear ? strlen(zYear) : 0; | |
| 569 | + const char *zYear = P("y"); /* Year for which report shown */ | |
| 570 | + int isValidYear = 0; /* True if a valid year */ | |
| 582 | 571 | int i = 0; |
| 583 | - Stmt qYears = empty_Stmt; | |
| 584 | - char *zDefaultYear = NULL; | |
| 585 | - Blob sql = empty_blob; | |
| 572 | + Stmt q; | |
| 586 | 573 | int nMaxEvents = 1; /* max number of events for |
| 587 | 574 | all rows. */ |
| 588 | 575 | int iterations = 0; /* # of active time periods. */ |
| 589 | - stats_report_init_view(); | |
| 590 | - if(4==nYear){ | |
| 591 | - Blob urlParams = empty_blob; | |
| 592 | - blob_appendf(&urlParams, "y=%T", zYear); | |
| 593 | - stats_report_event_types_menu("byweek", blob_str(&urlParams)); | |
| 594 | - blob_reset(&urlParams); | |
| 595 | - }else{ | |
| 596 | - stats_report_event_types_menu("byweek", NULL); | |
| 597 | - } | |
| 598 | - blob_append(&sql, | |
| 599 | - "SELECT DISTINCT substr(date(mtime),1,4) AS y " | |
| 600 | - "FROM v_reports WHERE 1 ", -1); | |
| 601 | - if(zUserName&&*zUserName){ | |
| 602 | - blob_append_sql(&sql,"AND user=%Q ", zUserName); | |
| 603 | - } | |
| 604 | - blob_append(&sql,"GROUP BY y ORDER BY y", -1); | |
| 605 | - db_prepare(&qYears, "%s", blob_sql_text(&sql)); | |
| 606 | - blob_reset(&sql); | |
| 607 | - cgi_printf("Select year: "); | |
| 608 | - while( SQLITE_ROW == db_step(&qYears) ){ | |
| 609 | - const char *zT = db_column_text(&qYears, 0); | |
| 610 | - if( i++ ){ | |
| 611 | - cgi_printf(" "); | |
| 612 | - } | |
| 613 | - cgi_printf("<a href='?view=byweek&y=%s&type=%c", zT, | |
| 614 | - (char)statsReportType); | |
| 615 | - if(zUserName && *zUserName){ | |
| 616 | - cgi_printf("&user=%t",zUserName); | |
| 617 | - } | |
| 618 | - cgi_printf("'>%s</a>",zT); | |
| 619 | - } | |
| 620 | - db_finalize(&qYears); | |
| 621 | - cgi_printf("<br/>"); | |
| 622 | - if(!zYear || !*zYear){ | |
| 623 | - zDefaultYear = db_text("????", "SELECT strftime('%%Y')"); | |
| 624 | - zYear = zDefaultYear; | |
| 625 | - nYear = 4; | |
| 626 | - } | |
| 627 | - if(4 == nYear){ | |
| 628 | - Stmt stWeek = empty_Stmt; | |
| 629 | - int rowCount = 0; | |
| 630 | - int total = 0; | |
| 631 | - Blob header = empty_blob; | |
| 632 | - blob_appendf(&header, "Timeline events (%s) for the calendar weeks " | |
| 633 | - "of %h", stats_report_label_for_type(), | |
| 634 | - zYear); | |
| 635 | - blob_append_sql(&sql, | |
| 636 | - "SELECT DISTINCT strftime('%%W',mtime) AS wk, " | |
| 637 | - "count(*) AS n " | |
| 638 | - "FROM v_reports " | |
| 639 | - "WHERE %Q=substr(date(mtime),1,4) " | |
| 640 | - "AND mtime < current_timestamp ", | |
| 641 | - zYear); | |
| 642 | - if(zUserName&&*zUserName){ | |
| 643 | - blob_append_sql(&sql, " AND user=%Q ", zUserName); | |
| 644 | - blob_appendf(&header," for user %h", zUserName); | |
| 645 | - } | |
| 646 | - blob_append_sql(&sql, "GROUP BY wk ORDER BY wk DESC"); | |
| 647 | - cgi_printf("<h1>%h</h1>", blob_str(&header)); | |
| 648 | - blob_reset(&header); | |
| 649 | - cgi_printf("<table class='statistics-report-table-events' " | |
| 650 | - "border='0' cellpadding='2' width='100%%' " | |
| 651 | - "cellspacing='0' id='statsTable'>"); | |
| 652 | - cgi_printf("<thead><tr>" | |
| 653 | - "<th>Week</th>" | |
| 654 | - "<th>Events</th>" | |
| 655 | - "<th width='90%%'><!-- relative commits graph --></th>" | |
| 656 | - "</tr></thead>" | |
| 657 | - "<tbody>"); | |
| 658 | - db_prepare(&stWeek, "%s", blob_sql_text(&sql)); | |
| 659 | - blob_reset(&sql); | |
| 660 | - while( SQLITE_ROW == db_step(&stWeek) ){ | |
| 661 | - const int nCount = db_column_int(&stWeek, 1); | |
| 662 | - if(nCount>nMaxEvents){ | |
| 663 | - nMaxEvents = nCount; | |
| 664 | - } | |
| 665 | - ++iterations; | |
| 666 | - } | |
| 667 | - db_reset(&stWeek); | |
| 668 | - while( SQLITE_ROW == db_step(&stWeek) ){ | |
| 669 | - const char *zWeek = db_column_text(&stWeek,0); | |
| 670 | - const int nCount = db_column_int(&stWeek,1); | |
| 671 | - int nSize = nCount | |
| 672 | - ? (int)(100 * nCount / nMaxEvents) | |
| 673 | - : 0; | |
| 674 | - if(!nSize) nSize = 1; | |
| 675 | - total += nCount; | |
| 676 | - cgi_printf("<tr class='row%d'>", ++rowCount % 2 ); | |
| 677 | - cgi_printf("<td><a href='%R/timeline?yw=%t-%s&n=%d&y=%s", | |
| 678 | - zYear, zWeek, nCount, | |
| 679 | - statsReportTimelineYFlag); | |
| 680 | - if(zUserName && *zUserName){ | |
| 681 | - cgi_printf("&u=%t",zUserName); | |
| 682 | - } | |
| 683 | - cgi_printf("'>%s</a></td>",zWeek); | |
| 684 | - | |
| 685 | - cgi_printf("<td>%d</td>",nCount); | |
| 686 | - cgi_printf("<td>"); | |
| 687 | - if(nCount){ | |
| 688 | - cgi_printf("<div class='statistics-report-graph-line'" | |
| 689 | - "style='width:%d%%;'> </div>", | |
| 690 | - nSize); | |
| 691 | - } | |
| 692 | - cgi_printf("</td></tr>"); | |
| 693 | - } | |
| 694 | - db_finalize(&stWeek); | |
| 695 | - free(zDefaultYear); | |
| 696 | - cgi_printf("</tbody></table>"); | |
| 697 | - if(total){ | |
| 698 | - int nAvg = iterations ? (total/iterations) : 0; | |
| 699 | - cgi_printf("<br><div>Total events: %d<br>" | |
| 700 | - "Average per active week: %d</div>", | |
| 701 | - total, nAvg); | |
| 702 | - } | |
| 703 | - output_table_sorting_javascript("statsTable","tnx",-1); | |
| 704 | - } | |
| 705 | -} | |
| 576 | + int n = 0; /* Number of entries in azYear */ | |
| 577 | + char **azYear = 0; /* Year dropdown menu */ | |
| 578 | + int rowCount = 0; | |
| 579 | + int total = 0; | |
| 580 | + | |
| 581 | + stats_report_init_view(); | |
| 582 | + style_submenu_sql("y", "Year:", | |
| 583 | + "WITH RECURSIVE a(b) AS (" | |
| 584 | + " SELECT substr(date('now'),1,4) UNION ALL" | |
| 585 | + " SELECT b-1 FROM a" | |
| 586 | + " WHERE b>0+(SELECT substr(date(min(mtime)),1,4) FROM event)" | |
| 587 | + ") SELECT b, b FROM a ORDER BY b DESC"); | |
| 588 | + if( zYear==0 || strlen(zYear)!=4 ){ | |
| 589 | + zYear = db_text("1970","SELECT substr(date('now'),1,4);"); | |
| 590 | + } | |
| 591 | + cgi_printf("<br/>"); | |
| 592 | + db_prepare(&q, | |
| 593 | + "SELECT DISTINCT strftime('%%W',mtime) AS wk, " | |
| 594 | + " count(*) AS n " | |
| 595 | + " FROM v_reports " | |
| 596 | + " WHERE %Q=substr(date(mtime),1,4) " | |
| 597 | + " AND mtime < current_timestamp " | |
| 598 | + " AND ifnull(coalesce(euser,user,'')=%Q,1)" | |
| 599 | + " GROUP BY wk ORDER BY wk DESC", zYear, zUserName); | |
| 600 | + @ <h1>Timeline events (%h(stats_report_label_for_type())) | |
| 601 | + @ for the calendar weeks of %h(zYear) | |
| 602 | + if( zUserName ){ | |
| 603 | + @ for user %h(zUserName) | |
| 604 | + } | |
| 605 | + @ </h1> | |
| 606 | + cgi_printf("<table class='statistics-report-table-events' " | |
| 607 | + "border='0' cellpadding='2' width='100%%' " | |
| 608 | + "cellspacing='0' id='statsTable'>"); | |
| 609 | + cgi_printf("<thead><tr>" | |
| 610 | + "<th>Week</th>" | |
| 611 | + "<th>Events</th>" | |
| 612 | + "<th width='90%%'><!-- relative commits graph --></th>" | |
| 613 | + "</tr></thead>" | |
| 614 | + "<tbody>"); | |
| 615 | + while( SQLITE_ROW == db_step(&q) ){ | |
| 616 | + const int nCount = db_column_int(&q, 1); | |
| 617 | + if(nCount>nMaxEvents){ | |
| 618 | + nMaxEvents = nCount; | |
| 619 | + } | |
| 620 | + ++iterations; | |
| 621 | + } | |
| 622 | + db_reset(&q); | |
| 623 | + while( SQLITE_ROW == db_step(&q) ){ | |
| 624 | + const char *zWeek = db_column_text(&q,0); | |
| 625 | + const int nCount = db_column_int(&q,1); | |
| 626 | + int nSize = nCount | |
| 627 | + ? (int)(100 * nCount / nMaxEvents) | |
| 628 | + : 0; | |
| 629 | + if(!nSize) nSize = 1; | |
| 630 | + total += nCount; | |
| 631 | + cgi_printf("<tr class='row%d'>", ++rowCount % 2 ); | |
| 632 | + cgi_printf("<td><a href='%R/timeline?yw=%t-%s&n=%d&y=%s", | |
| 633 | + zYear, zWeek, nCount, | |
| 634 | + statsReportTimelineYFlag); | |
| 635 | + if( zUserName ){ | |
| 636 | + cgi_printf("&u=%t",zUserName); | |
| 637 | + } | |
| 638 | + cgi_printf("'>%s</a></td>",zWeek); | |
| 639 | + | |
| 640 | + cgi_printf("<td>%d</td>",nCount); | |
| 641 | + cgi_printf("<td>"); | |
| 642 | + if(nCount){ | |
| 643 | + cgi_printf("<div class='statistics-report-graph-line'" | |
| 644 | + "style='width:%d%%;'> </div>", | |
| 645 | + nSize); | |
| 646 | + } | |
| 647 | + cgi_printf("</td></tr>"); | |
| 648 | + } | |
| 649 | + db_finalize(&q); | |
| 650 | + cgi_printf("</tbody></table>"); | |
| 651 | + if(total){ | |
| 652 | + int nAvg = iterations ? (total/iterations) : 0; | |
| 653 | + cgi_printf("<br><div>Total events: %d<br>" | |
| 654 | + "Average per active week: %d</div>", | |
| 655 | + total, nAvg); | |
| 656 | + } | |
| 657 | + output_table_sorting_javascript("statsTable","tnx",-1); | |
| 658 | +} | |
| 659 | + | |
| 660 | +/* Report types | |
| 661 | +*/ | |
| 662 | +#define RPT_BYFILE 1 | |
| 663 | +#define RPT_BYMONTH 2 | |
| 664 | +#define RPT_BYUSER 3 | |
| 665 | +#define RPT_BYWEEK 4 | |
| 666 | +#define RPT_BYWEEKDAY 5 | |
| 667 | +#define RPT_BYYEAR 6 | |
| 668 | +#define RPT_NONE 0 /* None of the above */ | |
| 706 | 669 | |
| 707 | 670 | /* |
| 708 | 671 | ** WEBPAGE: reports |
| 709 | 672 | ** |
| 710 | 673 | ** Shows activity reports for the repository. |
| @@ -724,51 +687,94 @@ | ||
| 724 | 687 | ** y=YYYY The year to report (default is the server's |
| 725 | 688 | ** current year). |
| 726 | 689 | */ |
| 727 | 690 | void stats_report_page(){ |
| 728 | 691 | HQuery url; /* URL for various branch links */ |
| 729 | - const char *zView = P("view"); /* Which view/report to show. */ | |
| 730 | - const char *zUserName = P("user"); | |
| 731 | - | |
| 692 | + const char *zView = P("view"); /* Which view/report to show. */ | |
| 693 | + int eType = RPT_NONE; /* Numeric code for view/report to show */ | |
| 694 | + int i; /* Loop counter */ | |
| 695 | + const char *zUserName; /* Name of user */ | |
| 696 | + const struct { | |
| 697 | + const char *zName; /* Name of view= screen type */ | |
| 698 | + const char *zVal; /* Value of view= query parameter */ | |
| 699 | + int eType; /* Corresponding RPT_* define */ | |
| 700 | + } aViewType[] = { | |
| 701 | + { "File Changes","byfile", RPT_BYFILE }, | |
| 702 | + { "By Month", "bymonth", RPT_BYMONTH }, | |
| 703 | + { "By User", "byuser", RPT_BYUSER }, | |
| 704 | + { "By Week", "byweek", RPT_BYWEEK }, | |
| 705 | + { "By Weekday", "byweekday", RPT_BYWEEKDAY }, | |
| 706 | + { "By Year", "byyear", RPT_BYYEAR }, | |
| 707 | + }; | |
| 708 | + const char *azType[] = { | |
| 709 | + "a", "All Changes", | |
| 710 | + "ci", "Check-ins", | |
| 711 | + "g", "Tags", | |
| 712 | + "e", "Tech Notes", | |
| 713 | + "t", "Tickets", | |
| 714 | + "w", "Wiki" | |
| 715 | + }; | |
| 716 | + | |
| 732 | 717 | login_check_credentials(); |
| 733 | 718 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 734 | - if(!zUserName) zUserName = P("u"); | |
| 735 | - url_initialize(&url, "reports"); | |
| 736 | - if(zUserName && *zUserName){ | |
| 737 | - url_add_parameter(&url,"user", zUserName); | |
| 738 | - statrep_submenu(&url, "(Remove User Flag)", "view", zView, "user"); | |
| 739 | - } | |
| 740 | - statrep_submenu(&url, "By Year", "view", "byyear", 0); | |
| 741 | - statrep_submenu(&url, "By Month", "view", "bymonth", 0); | |
| 742 | - statrep_submenu(&url, "By Week", "view", "byweek", 0); | |
| 743 | - statrep_submenu(&url, "By Weekday", "view", "byweekday", 0); | |
| 744 | - statrep_submenu(&url, "By User", "view", "byuser", "user"); | |
| 745 | - statrep_submenu(&url, "By File", "view", "byfile", "file"); | |
| 719 | + zUserName = P("user"); | |
| 720 | + if( zUserName==0 ) zUserName = P("u"); | |
| 721 | + if( zUserName && zUserName[0]==0 ) zUserName = 0; | |
| 722 | + if( zView==0 ){ | |
| 723 | + zView = "byuser"; | |
| 724 | + cgi_replace_query_parameter("view","byuser"); | |
| 725 | + } | |
| 726 | + for(i=0; i<ArraySize(aViewType); i++){ | |
| 727 | + if( fossil_strcmp(zView, aViewType[i].zVal)==0 ){ | |
| 728 | + eType = aViewType[i].eType; | |
| 729 | + break; | |
| 730 | + } | |
| 731 | + } | |
| 732 | + url_initialize(&url, "reports"); | |
| 733 | + cgi_query_parameters_to_url(&url); | |
| 734 | + if( eType!=RPT_NONE ){ | |
| 735 | + int nView = 0; /* Slots used in azView[] */ | |
| 736 | + const char *azView[16]; /* Drop-down menu of view types */ | |
| 737 | + for(i=0; i<ArraySize(aViewType); i++){ | |
| 738 | + azView[nView++] = aViewType[i].zVal; | |
| 739 | + azView[nView++] = aViewType[i].zName; | |
| 740 | + } | |
| 741 | + if( eType!=RPT_BYFILE ){ | |
| 742 | + style_submenu_multichoice("type", ArraySize(azType)/2, azType, 0); | |
| 743 | + } | |
| 744 | + style_submenu_multichoice("view", nView/2, azView, 0); | |
| 745 | + if( eType!=RPT_BYUSER ){ | |
| 746 | + style_submenu_sql("u","User:", | |
| 747 | + "SELECT '', 'All Users' UNION ALL " | |
| 748 | + "SELECT x, x FROM (" | |
| 749 | + " SELECT DISTINCT trim(coalesce(euser,user)) AS x FROM event %s" | |
| 750 | + " ORDER BY 1 COLLATE nocase) WHERE x!=''", | |
| 751 | + eType==RPT_BYFILE ? "WHERE type='ci'" : "" | |
| 752 | + ); | |
| 753 | + } | |
| 754 | + } | |
| 746 | 755 | style_submenu_element("Stats", "Stats", "%R/stat"); |
| 747 | 756 | url_reset(&url); |
| 748 | 757 | style_header("Activity Reports"); |
| 749 | - if(0==fossil_strcmp(zView,"byyear")){ | |
| 750 | - stats_report_by_month_year(0, 0, zUserName); | |
| 751 | - }else if(0==fossil_strcmp(zView,"bymonth")){ | |
| 752 | - stats_report_by_month_year(1, 0, zUserName); | |
| 753 | - }else if(0==fossil_strcmp(zView,"byweek")){ | |
| 754 | - stats_report_year_weeks(zUserName); | |
| 755 | - }else if(0==fossil_strcmp(zView,"byuser")){ | |
| 756 | - stats_report_by_user(); | |
| 757 | - }else if(0==fossil_strcmp(zView,"byweekday")){ | |
| 758 | - stats_report_day_of_week(); | |
| 759 | - }else if(0==fossil_strcmp(zView,"byfile")){ | |
| 760 | - stats_report_by_file(); | |
| 761 | - }else{ | |
| 762 | - @ <h1>Activity Reports:</h1> | |
| 763 | - @ <ul> | |
| 764 | - @ <li>%z(href("?view=byyear"))Events by year</a></li> | |
| 765 | - @ <li>%z(href("?view=bymonth"))Events by month</a></li> | |
| 766 | - @ <li>%z(href("?view=byweek"))Events by calendar week</a></li> | |
| 767 | - @ <li>%z(href("?view=byweekday"))Events by day of the week</a></li> | |
| 768 | - @ <li>%z(href("?view=byuser"))Events by user</a></li> | |
| 769 | - @ <li>%z(href("?view=byfile"))Events by file</a></li> | |
| 770 | - @ </ul> | |
| 771 | - } | |
| 772 | - | |
| 758 | + switch( eType ){ | |
| 759 | + case RPT_BYYEAR: | |
| 760 | + stats_report_by_month_year(0, 0, zUserName); | |
| 761 | + break; | |
| 762 | + case RPT_BYMONTH: | |
| 763 | + stats_report_by_month_year(1, 0, zUserName); | |
| 764 | + break; | |
| 765 | + case RPT_BYWEEK: | |
| 766 | + stats_report_year_weeks(zUserName); | |
| 767 | + break; | |
| 768 | + default: | |
| 769 | + case RPT_BYUSER: | |
| 770 | + stats_report_by_user(); | |
| 771 | + break; | |
| 772 | + case RPT_BYWEEKDAY: | |
| 773 | + stats_report_day_of_week(zUserName); | |
| 774 | + break; | |
| 775 | + case RPT_BYFILE: | |
| 776 | + stats_report_by_file(zUserName); | |
| 777 | + break; | |
| 778 | + } | |
| 773 | 779 | style_footer(); |
| 774 | 780 | } |
| 775 | 781 |
| --- src/statrep.c | |
| +++ src/statrep.c | |
| @@ -141,63 +141,10 @@ | |
| 141 | default: |
| 142 | return "all types"; |
| 143 | } |
| 144 | } |
| 145 | |
| 146 | /* |
| 147 | ** A helper for the /reports family of pages which prints out a menu |
| 148 | ** of links for the various type=XXX flags. zCurrentViewName must be |
| 149 | ** the name/value of the 'view' parameter which is in effect at the |
| 150 | ** time this is called. e.g. if called from the 'byuser' view then |
| 151 | ** zCurrentViewName must be "byuser". Any URL parameters which need to |
| 152 | ** be added to the generated URLs should be passed in zParam. The |
| 153 | ** caller is expected to have already encoded any zParam in the %T or |
| 154 | ** %t encoding. */ |
| 155 | static void stats_report_event_types_menu(const char *zCurrentViewName, |
| 156 | const char *zParam){ |
| 157 | char *zTop; |
| 158 | if(zParam && !*zParam){ |
| 159 | zParam = NULL; |
| 160 | } |
| 161 | zTop = mprintf("%s/reports?view=%s%s%s", g.zTop, zCurrentViewName, |
| 162 | zParam ? "&" : "", zParam); |
| 163 | cgi_printf("<div>"); |
| 164 | cgi_printf("<span>Types:</span> "); |
| 165 | if('*' == statsReportType){ |
| 166 | cgi_printf(" <strong>all</strong>", zTop); |
| 167 | }else{ |
| 168 | cgi_printf(" <a href='%s'>all</a>", zTop); |
| 169 | } |
| 170 | if('c' == statsReportType){ |
| 171 | cgi_printf(" <strong>check-ins</strong>", zTop); |
| 172 | }else{ |
| 173 | cgi_printf(" <a href='%s&type=ci'>check-ins</a>", zTop); |
| 174 | } |
| 175 | if('e' == statsReportType){ |
| 176 | cgi_printf(" <strong>technotes</strong>", zTop); |
| 177 | }else{ |
| 178 | cgi_printf(" <a href='%s&type=e'>technotes</a>", zTop); |
| 179 | } |
| 180 | if( 't' == statsReportType ){ |
| 181 | cgi_printf(" <strong>tickets</strong>", zTop); |
| 182 | }else{ |
| 183 | cgi_printf(" <a href='%s&type=t'>tickets</a>", zTop); |
| 184 | } |
| 185 | if( 'g' == statsReportType ){ |
| 186 | cgi_printf(" <strong>tags</strong>", zTop); |
| 187 | }else{ |
| 188 | cgi_printf(" <a href='%s&type=g'>tags</a>", zTop); |
| 189 | } |
| 190 | if( 'w' == statsReportType ){ |
| 191 | cgi_printf(" <strong>wiki</strong>", zTop); |
| 192 | }else{ |
| 193 | cgi_printf(" <a href='%s&type=w'>wiki</a>", zTop); |
| 194 | } |
| 195 | fossil_free(zTop); |
| 196 | cgi_printf("</div>"); |
| 197 | } |
| 198 | |
| 199 | |
| 200 | /* |
| 201 | ** Helper for stats_report_by_month_year(), which generates a list of |
| 202 | ** week numbers. zTimeframe should be either a timeframe in the form YYYY |
| 203 | ** or YYYY-MM. |
| @@ -227,23 +174,21 @@ | |
| 227 | } |
| 228 | |
| 229 | /* |
| 230 | ** Implements the "byyear" and "bymonth" reports for /reports. |
| 231 | ** If includeMonth is true then it generates the "bymonth" report, |
| 232 | ** else the "byyear" report. If zUserName is not NULL and not empty |
| 233 | ** then the report is restricted to events created by the named user |
| 234 | ** account. |
| 235 | */ |
| 236 | static void stats_report_by_month_year(char includeMonth, |
| 237 | char includeWeeks, |
| 238 | const char *zUserName){ |
| 239 | Stmt query = empty_Stmt; |
| 240 | int nRowNumber = 0; /* current TR number */ |
| 241 | int nEventTotal = 0; /* Total event count */ |
| 242 | int rowClass = 0; /* counter for alternating |
| 243 | row colors */ |
| 244 | Blob sql = empty_blob; /* SQL */ |
| 245 | const char *zTimeLabel = includeMonth ? "Year/Month" : "Year"; |
| 246 | char zPrevYear[5] = {0}; /* For keeping track of when |
| 247 | we change years while looping */ |
| 248 | int nEventsPerYear = 0; /* Total event count for the |
| 249 | current year */ |
| @@ -252,39 +197,37 @@ | |
| 252 | Blob header = empty_blob; /* Page header text */ |
| 253 | int nMaxEvents = 1; /* for calculating length of graph |
| 254 | bars. */ |
| 255 | int iterations = 0; /* number of weeks/months we iterate |
| 256 | over */ |
| 257 | stats_report_init_view(); |
| 258 | stats_report_event_types_menu( includeMonth ? "bymonth" : "byyear", NULL ); |
| 259 | blob_appendf(&header, "Timeline Events (%s) by year%s", |
| 260 | stats_report_label_for_type(), |
| 261 | (includeMonth ? "/month" : "")); |
| 262 | blob_append_sql(&sql, |
| 263 | "SELECT substr(date(mtime),1,%d) AS timeframe, " |
| 264 | "count(*) AS eventCount " |
| 265 | "FROM v_reports ", |
| 266 | includeMonth ? 7 : 4); |
| 267 | if(zUserName&&*zUserName){ |
| 268 | blob_append_sql(&sql, " WHERE user=%Q ", zUserName); |
| 269 | blob_appendf(&header," for user %q", zUserName); |
| 270 | } |
| 271 | blob_append(&sql, |
| 272 | " GROUP BY timeframe" |
| 273 | " ORDER BY timeframe DESC", |
| 274 | -1); |
| 275 | db_prepare(&query, "%s", blob_sql_text(&sql)); |
| 276 | blob_reset(&sql); |
| 277 | @ <h1>%b(&header)</h1> |
| 278 | @ <table class='statistics-report-table-events' border='0' cellpadding='2' |
| 279 | @ cellspacing='0' id='statsTable'> |
| 280 | @ <thead> |
| 281 | @ <th>%s(zTimeLabel)</th> |
| 282 | @ <th>Events</th> |
| 283 | @ <th width='90%%'><!-- relative commits graph --></th> |
| 284 | @ </thead><tbody> |
| 285 | blob_reset(&header); |
| 286 | /* |
| 287 | Run the query twice. The first time we calculate the maximum |
| 288 | number of events for a given row. Maybe someone with better SQL |
| 289 | Fu can re-implement this with a single query. |
| 290 | */ |
| @@ -335,18 +278,18 @@ | |
| 335 | zTimeframe, nCount, |
| 336 | statsReportTimelineYFlag ); |
| 337 | /* Reminder: n=nCount is not actually correct for bymonth unless |
| 338 | that was the only user who caused events. |
| 339 | */ |
| 340 | if( zUserName && *zUserName ){ |
| 341 | cgi_printf("&u=%t", zUserName); |
| 342 | } |
| 343 | cgi_printf("' target='_new'>%s</a>",zTimeframe); |
| 344 | }else { |
| 345 | cgi_printf("<a href='?view=byweek&y=%s&type=%c", |
| 346 | zTimeframe, (char)statsReportType); |
| 347 | if(zUserName && *zUserName){ |
| 348 | cgi_printf("&u=%t", zUserName); |
| 349 | } |
| 350 | cgi_printf("'>%s</a>", zTimeframe); |
| 351 | } |
| 352 | @ </td><td>%d(nCount)</td> |
| @@ -403,25 +346,34 @@ | |
| 403 | int rowClass = 0; /* counter for alternating |
| 404 | row colors */ |
| 405 | int nMaxEvents = 1; /* max number of events for |
| 406 | all rows. */ |
| 407 | stats_report_init_view(); |
| 408 | stats_report_event_types_menu("byuser", NULL); |
| 409 | db_prepare(&query, |
| 410 | "SELECT user, " |
| 411 | "COUNT(*) AS eventCount " |
| 412 | "FROM v_reports " |
| 413 | "GROUP BY user ORDER BY eventCount DESC"); |
| 414 | @ <h1>Timeline Events |
| 415 | @ (%s(stats_report_label_for_type())) by User</h1> |
| 416 | @ <table class='statistics-report-table-events' border='0' |
| 417 | @ cellpadding='2' cellspacing='0' id='statsTable'> |
| 418 | @ <thead><tr> |
| 419 | @ <th>User</th> |
| 420 | @ <th>Events</th> |
| 421 | @ <th width='90%%'><!-- relative commits graph --></th> |
| 422 | @ </tr></thead><tbody> |
| 423 | while( SQLITE_ROW == db_step(&query) ){ |
| 424 | const int nCount = db_column_int(&query, 1); |
| 425 | if(nCount>nMaxEvents){ |
| 426 | nMaxEvents = nCount; |
| 427 | } |
| @@ -428,20 +380,21 @@ | |
| 428 | } |
| 429 | db_reset(&query); |
| 430 | while( SQLITE_ROW == db_step(&query) ){ |
| 431 | const char *zUser = db_column_text(&query, 0); |
| 432 | const int nCount = db_column_int(&query, 1); |
| 433 | int nSize = nCount |
| 434 | ? (int)(100 * nCount / nMaxEvents) |
| 435 | : 0; |
| 436 | if(!nCount) continue /* arguable! Possible? */; |
| 437 | else if(!nSize) nSize = 1; |
| 438 | rowClass = ++nRowNumber % 2; |
| 439 | nEventTotal += nCount; |
| 440 | @<tr class='row%d(rowClass)'> |
| 441 | @ <td> |
| 442 | @ <a href="?view=bymonth&user=%h(zUser)&type=%c((char)statsReportType)">%h(zUser)</a> |
| 443 | @ </td><td data-sortkey='%08x(-nCount)'>%d(nCount)</td> |
| 444 | @ <td> |
| 445 | @ <div class='statistics-report-graph-line' |
| 446 | @ style='width:%d(nSize)%%;'> </div> |
| 447 | @ </td> |
| @@ -455,30 +408,37 @@ | |
| 455 | db_finalize(&query); |
| 456 | output_table_sorting_javascript("statsTable","tkx",2); |
| 457 | } |
| 458 | |
| 459 | /* |
| 460 | ** Implements the "byfile" view for /reports. |
| 461 | */ |
| 462 | static void stats_report_by_file(){ |
| 463 | Stmt query; |
| 464 | int mxEvent = 1; /* max number of events across all rows */ |
| 465 | int nRowNumber = 0; |
| 466 | |
| 467 | db_multi_exec( |
| 468 | "CREATE TEMP TABLE statrep(filename, cnt);" |
| 469 | "INSERT INTO statrep(filename, cnt)" |
| 470 | " SELECT filename.name, count(distinct mlink.mid)" |
| 471 | " FROM filename, mlink" |
| 472 | " WHERE filename.fnid=mlink.fnid" |
| 473 | " GROUP BY 1" |
| 474 | ); |
| 475 | db_prepare(&query, |
| 476 | "SELECT filename, cnt FROM statrep ORDER BY cnt DESC, filename /*sort*/" |
| 477 | ); |
| 478 | mxEvent = db_int(1, "SELECT max(cnt) FROM statrep"); |
| 479 | @ <h1>Check-ins Per File</h1> |
| 480 | @ <table class='statistics-report-table-events' border='0' |
| 481 | @ cellpadding='2' cellspacing='0' id='statsTable'> |
| 482 | @ <thead><tr> |
| 483 | @ <th>File</th> |
| 484 | @ <th>Check-ins</th> |
| @@ -504,34 +464,62 @@ | |
| 504 | db_finalize(&query); |
| 505 | output_table_sorting_javascript("statsTable","tNx",2); |
| 506 | } |
| 507 | |
| 508 | /* |
| 509 | ** Implements the "byweekday" view for /reports. |
| 510 | */ |
| 511 | static void stats_report_day_of_week(){ |
| 512 | Stmt query = empty_Stmt; |
| 513 | int nRowNumber = 0; /* current TR number */ |
| 514 | int nEventTotal = 0; /* Total event count */ |
| 515 | int rowClass = 0; /* counter for alternating |
| 516 | row colors */ |
| 517 | int nMaxEvents = 1; /* max number of events for |
| 518 | all rows. */ |
| 519 | static const char *const daysOfWeek[] = { |
| 520 | "Monday", "Tuesday", "Wednesday", "Thursday", |
| 521 | "Friday", "Saturday", "Sunday" |
| 522 | }; |
| 523 | |
| 524 | stats_report_init_view(); |
| 525 | stats_report_event_types_menu("byweekday", NULL); |
| 526 | db_prepare(&query, |
| 527 | "SELECT cast(mtime %% 7 AS INTEGER) dow, " |
| 528 | "COUNT(*) AS eventCount " |
| 529 | "FROM v_reports " |
| 530 | "GROUP BY dow ORDER BY dow"); |
| 531 | @ <h1>Timeline Events |
| 532 | @ (%s(stats_report_label_for_type())) by Day of the Week</h1> |
| 533 | @ <table class='statistics-report-table-events' border='0' |
| 534 | @ cellpadding='2' cellspacing='0' id='statsTable'> |
| 535 | @ <thead><tr> |
| 536 | @ <th>DoW</th> |
| 537 | @ <th>Day</th> |
| @@ -572,139 +560,114 @@ | |
| 572 | |
| 573 | |
| 574 | /* |
| 575 | ** Helper for stats_report_by_month_year(), which generates a list of |
| 576 | ** week numbers. zTimeframe should be either a timeframe in the form YYYY |
| 577 | ** or YYYY-MM. |
| 578 | */ |
| 579 | static void stats_report_year_weeks(const char *zUserName){ |
| 580 | const char *zYear = P("y"); |
| 581 | int nYear = zYear ? strlen(zYear) : 0; |
| 582 | int i = 0; |
| 583 | Stmt qYears = empty_Stmt; |
| 584 | char *zDefaultYear = NULL; |
| 585 | Blob sql = empty_blob; |
| 586 | int nMaxEvents = 1; /* max number of events for |
| 587 | all rows. */ |
| 588 | int iterations = 0; /* # of active time periods. */ |
| 589 | stats_report_init_view(); |
| 590 | if(4==nYear){ |
| 591 | Blob urlParams = empty_blob; |
| 592 | blob_appendf(&urlParams, "y=%T", zYear); |
| 593 | stats_report_event_types_menu("byweek", blob_str(&urlParams)); |
| 594 | blob_reset(&urlParams); |
| 595 | }else{ |
| 596 | stats_report_event_types_menu("byweek", NULL); |
| 597 | } |
| 598 | blob_append(&sql, |
| 599 | "SELECT DISTINCT substr(date(mtime),1,4) AS y " |
| 600 | "FROM v_reports WHERE 1 ", -1); |
| 601 | if(zUserName&&*zUserName){ |
| 602 | blob_append_sql(&sql,"AND user=%Q ", zUserName); |
| 603 | } |
| 604 | blob_append(&sql,"GROUP BY y ORDER BY y", -1); |
| 605 | db_prepare(&qYears, "%s", blob_sql_text(&sql)); |
| 606 | blob_reset(&sql); |
| 607 | cgi_printf("Select year: "); |
| 608 | while( SQLITE_ROW == db_step(&qYears) ){ |
| 609 | const char *zT = db_column_text(&qYears, 0); |
| 610 | if( i++ ){ |
| 611 | cgi_printf(" "); |
| 612 | } |
| 613 | cgi_printf("<a href='?view=byweek&y=%s&type=%c", zT, |
| 614 | (char)statsReportType); |
| 615 | if(zUserName && *zUserName){ |
| 616 | cgi_printf("&user=%t",zUserName); |
| 617 | } |
| 618 | cgi_printf("'>%s</a>",zT); |
| 619 | } |
| 620 | db_finalize(&qYears); |
| 621 | cgi_printf("<br/>"); |
| 622 | if(!zYear || !*zYear){ |
| 623 | zDefaultYear = db_text("????", "SELECT strftime('%%Y')"); |
| 624 | zYear = zDefaultYear; |
| 625 | nYear = 4; |
| 626 | } |
| 627 | if(4 == nYear){ |
| 628 | Stmt stWeek = empty_Stmt; |
| 629 | int rowCount = 0; |
| 630 | int total = 0; |
| 631 | Blob header = empty_blob; |
| 632 | blob_appendf(&header, "Timeline events (%s) for the calendar weeks " |
| 633 | "of %h", stats_report_label_for_type(), |
| 634 | zYear); |
| 635 | blob_append_sql(&sql, |
| 636 | "SELECT DISTINCT strftime('%%W',mtime) AS wk, " |
| 637 | "count(*) AS n " |
| 638 | "FROM v_reports " |
| 639 | "WHERE %Q=substr(date(mtime),1,4) " |
| 640 | "AND mtime < current_timestamp ", |
| 641 | zYear); |
| 642 | if(zUserName&&*zUserName){ |
| 643 | blob_append_sql(&sql, " AND user=%Q ", zUserName); |
| 644 | blob_appendf(&header," for user %h", zUserName); |
| 645 | } |
| 646 | blob_append_sql(&sql, "GROUP BY wk ORDER BY wk DESC"); |
| 647 | cgi_printf("<h1>%h</h1>", blob_str(&header)); |
| 648 | blob_reset(&header); |
| 649 | cgi_printf("<table class='statistics-report-table-events' " |
| 650 | "border='0' cellpadding='2' width='100%%' " |
| 651 | "cellspacing='0' id='statsTable'>"); |
| 652 | cgi_printf("<thead><tr>" |
| 653 | "<th>Week</th>" |
| 654 | "<th>Events</th>" |
| 655 | "<th width='90%%'><!-- relative commits graph --></th>" |
| 656 | "</tr></thead>" |
| 657 | "<tbody>"); |
| 658 | db_prepare(&stWeek, "%s", blob_sql_text(&sql)); |
| 659 | blob_reset(&sql); |
| 660 | while( SQLITE_ROW == db_step(&stWeek) ){ |
| 661 | const int nCount = db_column_int(&stWeek, 1); |
| 662 | if(nCount>nMaxEvents){ |
| 663 | nMaxEvents = nCount; |
| 664 | } |
| 665 | ++iterations; |
| 666 | } |
| 667 | db_reset(&stWeek); |
| 668 | while( SQLITE_ROW == db_step(&stWeek) ){ |
| 669 | const char *zWeek = db_column_text(&stWeek,0); |
| 670 | const int nCount = db_column_int(&stWeek,1); |
| 671 | int nSize = nCount |
| 672 | ? (int)(100 * nCount / nMaxEvents) |
| 673 | : 0; |
| 674 | if(!nSize) nSize = 1; |
| 675 | total += nCount; |
| 676 | cgi_printf("<tr class='row%d'>", ++rowCount % 2 ); |
| 677 | cgi_printf("<td><a href='%R/timeline?yw=%t-%s&n=%d&y=%s", |
| 678 | zYear, zWeek, nCount, |
| 679 | statsReportTimelineYFlag); |
| 680 | if(zUserName && *zUserName){ |
| 681 | cgi_printf("&u=%t",zUserName); |
| 682 | } |
| 683 | cgi_printf("'>%s</a></td>",zWeek); |
| 684 | |
| 685 | cgi_printf("<td>%d</td>",nCount); |
| 686 | cgi_printf("<td>"); |
| 687 | if(nCount){ |
| 688 | cgi_printf("<div class='statistics-report-graph-line'" |
| 689 | "style='width:%d%%;'> </div>", |
| 690 | nSize); |
| 691 | } |
| 692 | cgi_printf("</td></tr>"); |
| 693 | } |
| 694 | db_finalize(&stWeek); |
| 695 | free(zDefaultYear); |
| 696 | cgi_printf("</tbody></table>"); |
| 697 | if(total){ |
| 698 | int nAvg = iterations ? (total/iterations) : 0; |
| 699 | cgi_printf("<br><div>Total events: %d<br>" |
| 700 | "Average per active week: %d</div>", |
| 701 | total, nAvg); |
| 702 | } |
| 703 | output_table_sorting_javascript("statsTable","tnx",-1); |
| 704 | } |
| 705 | } |
| 706 | |
| 707 | /* |
| 708 | ** WEBPAGE: reports |
| 709 | ** |
| 710 | ** Shows activity reports for the repository. |
| @@ -724,51 +687,94 @@ | |
| 724 | ** y=YYYY The year to report (default is the server's |
| 725 | ** current year). |
| 726 | */ |
| 727 | void stats_report_page(){ |
| 728 | HQuery url; /* URL for various branch links */ |
| 729 | const char *zView = P("view"); /* Which view/report to show. */ |
| 730 | const char *zUserName = P("user"); |
| 731 | |
| 732 | login_check_credentials(); |
| 733 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 734 | if(!zUserName) zUserName = P("u"); |
| 735 | url_initialize(&url, "reports"); |
| 736 | if(zUserName && *zUserName){ |
| 737 | url_add_parameter(&url,"user", zUserName); |
| 738 | statrep_submenu(&url, "(Remove User Flag)", "view", zView, "user"); |
| 739 | } |
| 740 | statrep_submenu(&url, "By Year", "view", "byyear", 0); |
| 741 | statrep_submenu(&url, "By Month", "view", "bymonth", 0); |
| 742 | statrep_submenu(&url, "By Week", "view", "byweek", 0); |
| 743 | statrep_submenu(&url, "By Weekday", "view", "byweekday", 0); |
| 744 | statrep_submenu(&url, "By User", "view", "byuser", "user"); |
| 745 | statrep_submenu(&url, "By File", "view", "byfile", "file"); |
| 746 | style_submenu_element("Stats", "Stats", "%R/stat"); |
| 747 | url_reset(&url); |
| 748 | style_header("Activity Reports"); |
| 749 | if(0==fossil_strcmp(zView,"byyear")){ |
| 750 | stats_report_by_month_year(0, 0, zUserName); |
| 751 | }else if(0==fossil_strcmp(zView,"bymonth")){ |
| 752 | stats_report_by_month_year(1, 0, zUserName); |
| 753 | }else if(0==fossil_strcmp(zView,"byweek")){ |
| 754 | stats_report_year_weeks(zUserName); |
| 755 | }else if(0==fossil_strcmp(zView,"byuser")){ |
| 756 | stats_report_by_user(); |
| 757 | }else if(0==fossil_strcmp(zView,"byweekday")){ |
| 758 | stats_report_day_of_week(); |
| 759 | }else if(0==fossil_strcmp(zView,"byfile")){ |
| 760 | stats_report_by_file(); |
| 761 | }else{ |
| 762 | @ <h1>Activity Reports:</h1> |
| 763 | @ <ul> |
| 764 | @ <li>%z(href("?view=byyear"))Events by year</a></li> |
| 765 | @ <li>%z(href("?view=bymonth"))Events by month</a></li> |
| 766 | @ <li>%z(href("?view=byweek"))Events by calendar week</a></li> |
| 767 | @ <li>%z(href("?view=byweekday"))Events by day of the week</a></li> |
| 768 | @ <li>%z(href("?view=byuser"))Events by user</a></li> |
| 769 | @ <li>%z(href("?view=byfile"))Events by file</a></li> |
| 770 | @ </ul> |
| 771 | } |
| 772 | |
| 773 | style_footer(); |
| 774 | } |
| 775 |
| --- src/statrep.c | |
| +++ src/statrep.c | |
| @@ -141,63 +141,10 @@ | |
| 141 | default: |
| 142 | return "all types"; |
| 143 | } |
| 144 | } |
| 145 | |
| 146 | |
| 147 | /* |
| 148 | ** Helper for stats_report_by_month_year(), which generates a list of |
| 149 | ** week numbers. zTimeframe should be either a timeframe in the form YYYY |
| 150 | ** or YYYY-MM. |
| @@ -227,23 +174,21 @@ | |
| 174 | } |
| 175 | |
| 176 | /* |
| 177 | ** Implements the "byyear" and "bymonth" reports for /reports. |
| 178 | ** If includeMonth is true then it generates the "bymonth" report, |
| 179 | ** else the "byyear" report. If zUserName is not NULL then the report is |
| 180 | ** restricted to events created by the named user account. |
| 181 | */ |
| 182 | static void stats_report_by_month_year(char includeMonth, |
| 183 | char includeWeeks, |
| 184 | const char *zUserName){ |
| 185 | Stmt query = empty_Stmt; |
| 186 | int nRowNumber = 0; /* current TR number */ |
| 187 | int nEventTotal = 0; /* Total event count */ |
| 188 | int rowClass = 0; /* counter for alternating |
| 189 | row colors */ |
| 190 | const char *zTimeLabel = includeMonth ? "Year/Month" : "Year"; |
| 191 | char zPrevYear[5] = {0}; /* For keeping track of when |
| 192 | we change years while looping */ |
| 193 | int nEventsPerYear = 0; /* Total event count for the |
| 194 | current year */ |
| @@ -252,39 +197,37 @@ | |
| 197 | Blob header = empty_blob; /* Page header text */ |
| 198 | int nMaxEvents = 1; /* for calculating length of graph |
| 199 | bars. */ |
| 200 | int iterations = 0; /* number of weeks/months we iterate |
| 201 | over */ |
| 202 | Blob userFilter = empty_blob; /* Optional user=johndoe query string */ |
| 203 | stats_report_init_view(); |
| 204 | if( zUserName ){ |
| 205 | blob_appendf(&userFilter, "user=%s", zUserName); |
| 206 | } |
| 207 | blob_reset(&userFilter); |
| 208 | db_prepare(&query, |
| 209 | "SELECT substr(date(mtime),1,%d) AS timeframe," |
| 210 | " count(*) AS eventCount" |
| 211 | " FROM v_reports" |
| 212 | " WHERE ifnull(coalesce(euser,user,'')=%Q,1)" |
| 213 | " GROUP BY timeframe" |
| 214 | " ORDER BY timeframe DESC", |
| 215 | includeMonth ? 7 : 4, zUserName); |
| 216 | @ <h1>Timeline Events (%s(stats_report_label_for_type())) |
| 217 | @ by year%s(includeMonth ? "/month" : "") |
| 218 | if( zUserName ){ |
| 219 | @ for user %h(zUserName) |
| 220 | } |
| 221 | @ </h1> |
| 222 | @ <table class='statistics-report-table-events' border='0' cellpadding='2' |
| 223 | @ cellspacing='0' id='statsTable'> |
| 224 | @ <thead> |
| 225 | @ <th>%s(zTimeLabel)</th> |
| 226 | @ <th>Events</th> |
| 227 | @ <th width='90%%'><!-- relative commits graph --></th> |
| 228 | @ </thead><tbody> |
| 229 | /* |
| 230 | Run the query twice. The first time we calculate the maximum |
| 231 | number of events for a given row. Maybe someone with better SQL |
| 232 | Fu can re-implement this with a single query. |
| 233 | */ |
| @@ -335,18 +278,18 @@ | |
| 278 | zTimeframe, nCount, |
| 279 | statsReportTimelineYFlag ); |
| 280 | /* Reminder: n=nCount is not actually correct for bymonth unless |
| 281 | that was the only user who caused events. |
| 282 | */ |
| 283 | if( zUserName ){ |
| 284 | cgi_printf("&u=%t", zUserName); |
| 285 | } |
| 286 | cgi_printf("' target='_new'>%s</a>",zTimeframe); |
| 287 | }else { |
| 288 | cgi_printf("<a href='?view=byweek&y=%s&type=%c", |
| 289 | zTimeframe, (char)statsReportType); |
| 290 | if( zUserName ){ |
| 291 | cgi_printf("&u=%t", zUserName); |
| 292 | } |
| 293 | cgi_printf("'>%s</a>", zTimeframe); |
| 294 | } |
| 295 | @ </td><td>%d(nCount)</td> |
| @@ -403,25 +346,34 @@ | |
| 346 | int rowClass = 0; /* counter for alternating |
| 347 | row colors */ |
| 348 | int nMaxEvents = 1; /* max number of events for |
| 349 | all rows. */ |
| 350 | stats_report_init_view(); |
| 351 | @ <h1>Timeline Events |
| 352 | @ (%s(stats_report_label_for_type())) by User</h1> |
| 353 | db_multi_exec( |
| 354 | "CREATE TEMP TABLE piechart(amt,label);" |
| 355 | "INSERT INTO piechart SELECT count(*), ifnull(euser,user) FROM v_reports" |
| 356 | " GROUP BY ifnull(euser,user) ORDER BY count(*) DESC;" |
| 357 | ); |
| 358 | if( db_int(0, "SELECT count(*) FROM piechart")>=2 ){ |
| 359 | @ <center><svg width=700 height=400> |
| 360 | piechart_render(700, 400, PIE_OTHER|PIE_PERCENT); |
| 361 | @ </svg></centre><hr/> |
| 362 | } |
| 363 | @ <table class='statistics-report-table-events' border='0' |
| 364 | @ cellpadding='2' cellspacing='0' id='statsTable'> |
| 365 | @ <thead><tr> |
| 366 | @ <th>User</th> |
| 367 | @ <th>Events</th> |
| 368 | @ <th width='90%%'><!-- relative commits graph --></th> |
| 369 | @ </tr></thead><tbody> |
| 370 | db_prepare(&query, |
| 371 | "SELECT ifnull(euser,user), " |
| 372 | "COUNT(*) AS eventCount " |
| 373 | "FROM v_reports " |
| 374 | "GROUP BY ifnull(euser,user) ORDER BY eventCount DESC"); |
| 375 | while( SQLITE_ROW == db_step(&query) ){ |
| 376 | const int nCount = db_column_int(&query, 1); |
| 377 | if(nCount>nMaxEvents){ |
| 378 | nMaxEvents = nCount; |
| 379 | } |
| @@ -428,20 +380,21 @@ | |
| 380 | } |
| 381 | db_reset(&query); |
| 382 | while( SQLITE_ROW == db_step(&query) ){ |
| 383 | const char *zUser = db_column_text(&query, 0); |
| 384 | const int nCount = db_column_int(&query, 1); |
| 385 | char y = (char)statsReportType; |
| 386 | int nSize = nCount |
| 387 | ? (int)(100 * nCount / nMaxEvents) |
| 388 | : 0; |
| 389 | if(!nCount) continue /* arguable! Possible? */; |
| 390 | else if(!nSize) nSize = 1; |
| 391 | rowClass = ++nRowNumber % 2; |
| 392 | nEventTotal += nCount; |
| 393 | @ <tr class='row%d(rowClass)'> |
| 394 | @ <td> |
| 395 | @ <a href="?view=bymonth&user=%h(zUser)&type=%c(y)">%h(zUser)</a> |
| 396 | @ </td><td data-sortkey='%08x(-nCount)'>%d(nCount)</td> |
| 397 | @ <td> |
| 398 | @ <div class='statistics-report-graph-line' |
| 399 | @ style='width:%d(nSize)%%;'> </div> |
| 400 | @ </td> |
| @@ -455,30 +408,37 @@ | |
| 408 | db_finalize(&query); |
| 409 | output_table_sorting_javascript("statsTable","tkx",2); |
| 410 | } |
| 411 | |
| 412 | /* |
| 413 | ** Implements the "byfile" view for /reports. If zUserName is not NULL then the |
| 414 | ** report is restricted to events created by the named user account. |
| 415 | */ |
| 416 | static void stats_report_by_file(const char *zUserName){ |
| 417 | Stmt query; |
| 418 | int mxEvent = 1; /* max number of events across all rows */ |
| 419 | int nRowNumber = 0; |
| 420 | |
| 421 | db_multi_exec( |
| 422 | "CREATE TEMP TABLE statrep(filename, cnt);" |
| 423 | "INSERT INTO statrep(filename, cnt)" |
| 424 | " SELECT filename.name, count(distinct mlink.mid)" |
| 425 | " FROM filename, mlink, event" |
| 426 | " WHERE filename.fnid=mlink.fnid" |
| 427 | " AND mlink.mid=event.objid" |
| 428 | " AND ifnull(coalesce(euser,user,'')=%Q,1)" |
| 429 | " GROUP BY 1", zUserName |
| 430 | ); |
| 431 | db_prepare(&query, |
| 432 | "SELECT filename, cnt FROM statrep ORDER BY cnt DESC, filename /*sort*/" |
| 433 | ); |
| 434 | mxEvent = db_int(1, "SELECT max(cnt) FROM statrep"); |
| 435 | @ <h1>Check-ins Per File |
| 436 | if( zUserName ){ |
| 437 | @ for user %h(zUserName) |
| 438 | } |
| 439 | @ </h1> |
| 440 | @ <table class='statistics-report-table-events' border='0' |
| 441 | @ cellpadding='2' cellspacing='0' id='statsTable'> |
| 442 | @ <thead><tr> |
| 443 | @ <th>File</th> |
| 444 | @ <th>Check-ins</th> |
| @@ -504,34 +464,62 @@ | |
| 464 | db_finalize(&query); |
| 465 | output_table_sorting_javascript("statsTable","tNx",2); |
| 466 | } |
| 467 | |
| 468 | /* |
| 469 | ** Implements the "byweekday" view for /reports. If zUserName is not NULL then |
| 470 | ** the report is restricted to events created by the named user account. |
| 471 | */ |
| 472 | static void stats_report_day_of_week(const char *zUserName){ |
| 473 | Stmt query = empty_Stmt; |
| 474 | int nRowNumber = 0; /* current TR number */ |
| 475 | int nEventTotal = 0; /* Total event count */ |
| 476 | int rowClass = 0; /* counter for alternating |
| 477 | row colors */ |
| 478 | int nMaxEvents = 1; /* max number of events for |
| 479 | all rows. */ |
| 480 | Blob userFilter = empty_blob; /* Optional user=johndoe query string */ |
| 481 | static const char *const daysOfWeek[] = { |
| 482 | "Monday", "Tuesday", "Wednesday", "Thursday", |
| 483 | "Friday", "Saturday", "Sunday" |
| 484 | }; |
| 485 | |
| 486 | stats_report_init_view(); |
| 487 | if( zUserName ){ |
| 488 | blob_appendf(&userFilter, "user=%s", zUserName); |
| 489 | } |
| 490 | db_prepare(&query, |
| 491 | "SELECT cast(mtime %% 7 AS INTEGER) dow," |
| 492 | " COUNT(*) AS eventCount" |
| 493 | " FROM v_reports" |
| 494 | " WHERE ifnull(coalesce(euser,user,'')=%Q,1)" |
| 495 | " GROUP BY dow ORDER BY dow", zUserName); |
| 496 | @ <h1>Timeline Events (%h(stats_report_label_for_type())) by Day of the Week |
| 497 | if( zUserName ){ |
| 498 | @ for user %h(zUserName) |
| 499 | } |
| 500 | @ </h1> |
| 501 | db_multi_exec( |
| 502 | "CREATE TEMP TABLE piechart(amt,label);" |
| 503 | "INSERT INTO piechart" |
| 504 | " SELECT count(*), cast(mtime %% 7 AS INT) FROM v_reports" |
| 505 | " WHERE ifnull(coalesce(euser,user,'')=%Q,1)" |
| 506 | " GROUP BY 2 ORDER BY 2;" |
| 507 | "UPDATE piechart SET label = CASE label" |
| 508 | " WHEN 0 THEN 'Monday'" |
| 509 | " WHEN 1 THEN 'Tuesday'" |
| 510 | " WHEN 2 THEN 'Wednesday'" |
| 511 | " WHEN 3 THEN 'Thursday'" |
| 512 | " WHEN 4 THEN 'Friday'" |
| 513 | " WHEN 5 THEN 'Saturday'" |
| 514 | " ELSE 'Sunday' END;", zUserName |
| 515 | ); |
| 516 | if( db_int(0, "SELECT count(*) FROM piechart")>=2 ){ |
| 517 | @ <center><svg width=700 height=400> |
| 518 | piechart_render(700, 400, PIE_OTHER|PIE_PERCENT); |
| 519 | @ </svg></centre><hr/> |
| 520 | } |
| 521 | @ <table class='statistics-report-table-events' border='0' |
| 522 | @ cellpadding='2' cellspacing='0' id='statsTable'> |
| 523 | @ <thead><tr> |
| 524 | @ <th>DoW</th> |
| 525 | @ <th>Day</th> |
| @@ -572,139 +560,114 @@ | |
| 560 | |
| 561 | |
| 562 | /* |
| 563 | ** Helper for stats_report_by_month_year(), which generates a list of |
| 564 | ** week numbers. zTimeframe should be either a timeframe in the form YYYY |
| 565 | ** or YYYY-MM. If zUserName is not NULL then the report is restricted to events |
| 566 | ** created by the named user account. |
| 567 | */ |
| 568 | static void stats_report_year_weeks(const char *zUserName){ |
| 569 | const char *zYear = P("y"); /* Year for which report shown */ |
| 570 | int isValidYear = 0; /* True if a valid year */ |
| 571 | int i = 0; |
| 572 | Stmt q; |
| 573 | int nMaxEvents = 1; /* max number of events for |
| 574 | all rows. */ |
| 575 | int iterations = 0; /* # of active time periods. */ |
| 576 | int n = 0; /* Number of entries in azYear */ |
| 577 | char **azYear = 0; /* Year dropdown menu */ |
| 578 | int rowCount = 0; |
| 579 | int total = 0; |
| 580 | |
| 581 | stats_report_init_view(); |
| 582 | style_submenu_sql("y", "Year:", |
| 583 | "WITH RECURSIVE a(b) AS (" |
| 584 | " SELECT substr(date('now'),1,4) UNION ALL" |
| 585 | " SELECT b-1 FROM a" |
| 586 | " WHERE b>0+(SELECT substr(date(min(mtime)),1,4) FROM event)" |
| 587 | ") SELECT b, b FROM a ORDER BY b DESC"); |
| 588 | if( zYear==0 || strlen(zYear)!=4 ){ |
| 589 | zYear = db_text("1970","SELECT substr(date('now'),1,4);"); |
| 590 | } |
| 591 | cgi_printf("<br/>"); |
| 592 | db_prepare(&q, |
| 593 | "SELECT DISTINCT strftime('%%W',mtime) AS wk, " |
| 594 | " count(*) AS n " |
| 595 | " FROM v_reports " |
| 596 | " WHERE %Q=substr(date(mtime),1,4) " |
| 597 | " AND mtime < current_timestamp " |
| 598 | " AND ifnull(coalesce(euser,user,'')=%Q,1)" |
| 599 | " GROUP BY wk ORDER BY wk DESC", zYear, zUserName); |
| 600 | @ <h1>Timeline events (%h(stats_report_label_for_type())) |
| 601 | @ for the calendar weeks of %h(zYear) |
| 602 | if( zUserName ){ |
| 603 | @ for user %h(zUserName) |
| 604 | } |
| 605 | @ </h1> |
| 606 | cgi_printf("<table class='statistics-report-table-events' " |
| 607 | "border='0' cellpadding='2' width='100%%' " |
| 608 | "cellspacing='0' id='statsTable'>"); |
| 609 | cgi_printf("<thead><tr>" |
| 610 | "<th>Week</th>" |
| 611 | "<th>Events</th>" |
| 612 | "<th width='90%%'><!-- relative commits graph --></th>" |
| 613 | "</tr></thead>" |
| 614 | "<tbody>"); |
| 615 | while( SQLITE_ROW == db_step(&q) ){ |
| 616 | const int nCount = db_column_int(&q, 1); |
| 617 | if(nCount>nMaxEvents){ |
| 618 | nMaxEvents = nCount; |
| 619 | } |
| 620 | ++iterations; |
| 621 | } |
| 622 | db_reset(&q); |
| 623 | while( SQLITE_ROW == db_step(&q) ){ |
| 624 | const char *zWeek = db_column_text(&q,0); |
| 625 | const int nCount = db_column_int(&q,1); |
| 626 | int nSize = nCount |
| 627 | ? (int)(100 * nCount / nMaxEvents) |
| 628 | : 0; |
| 629 | if(!nSize) nSize = 1; |
| 630 | total += nCount; |
| 631 | cgi_printf("<tr class='row%d'>", ++rowCount % 2 ); |
| 632 | cgi_printf("<td><a href='%R/timeline?yw=%t-%s&n=%d&y=%s", |
| 633 | zYear, zWeek, nCount, |
| 634 | statsReportTimelineYFlag); |
| 635 | if( zUserName ){ |
| 636 | cgi_printf("&u=%t",zUserName); |
| 637 | } |
| 638 | cgi_printf("'>%s</a></td>",zWeek); |
| 639 | |
| 640 | cgi_printf("<td>%d</td>",nCount); |
| 641 | cgi_printf("<td>"); |
| 642 | if(nCount){ |
| 643 | cgi_printf("<div class='statistics-report-graph-line'" |
| 644 | "style='width:%d%%;'> </div>", |
| 645 | nSize); |
| 646 | } |
| 647 | cgi_printf("</td></tr>"); |
| 648 | } |
| 649 | db_finalize(&q); |
| 650 | cgi_printf("</tbody></table>"); |
| 651 | if(total){ |
| 652 | int nAvg = iterations ? (total/iterations) : 0; |
| 653 | cgi_printf("<br><div>Total events: %d<br>" |
| 654 | "Average per active week: %d</div>", |
| 655 | total, nAvg); |
| 656 | } |
| 657 | output_table_sorting_javascript("statsTable","tnx",-1); |
| 658 | } |
| 659 | |
| 660 | /* Report types |
| 661 | */ |
| 662 | #define RPT_BYFILE 1 |
| 663 | #define RPT_BYMONTH 2 |
| 664 | #define RPT_BYUSER 3 |
| 665 | #define RPT_BYWEEK 4 |
| 666 | #define RPT_BYWEEKDAY 5 |
| 667 | #define RPT_BYYEAR 6 |
| 668 | #define RPT_NONE 0 /* None of the above */ |
| 669 | |
| 670 | /* |
| 671 | ** WEBPAGE: reports |
| 672 | ** |
| 673 | ** Shows activity reports for the repository. |
| @@ -724,51 +687,94 @@ | |
| 687 | ** y=YYYY The year to report (default is the server's |
| 688 | ** current year). |
| 689 | */ |
| 690 | void stats_report_page(){ |
| 691 | HQuery url; /* URL for various branch links */ |
| 692 | const char *zView = P("view"); /* Which view/report to show. */ |
| 693 | int eType = RPT_NONE; /* Numeric code for view/report to show */ |
| 694 | int i; /* Loop counter */ |
| 695 | const char *zUserName; /* Name of user */ |
| 696 | const struct { |
| 697 | const char *zName; /* Name of view= screen type */ |
| 698 | const char *zVal; /* Value of view= query parameter */ |
| 699 | int eType; /* Corresponding RPT_* define */ |
| 700 | } aViewType[] = { |
| 701 | { "File Changes","byfile", RPT_BYFILE }, |
| 702 | { "By Month", "bymonth", RPT_BYMONTH }, |
| 703 | { "By User", "byuser", RPT_BYUSER }, |
| 704 | { "By Week", "byweek", RPT_BYWEEK }, |
| 705 | { "By Weekday", "byweekday", RPT_BYWEEKDAY }, |
| 706 | { "By Year", "byyear", RPT_BYYEAR }, |
| 707 | }; |
| 708 | const char *azType[] = { |
| 709 | "a", "All Changes", |
| 710 | "ci", "Check-ins", |
| 711 | "g", "Tags", |
| 712 | "e", "Tech Notes", |
| 713 | "t", "Tickets", |
| 714 | "w", "Wiki" |
| 715 | }; |
| 716 | |
| 717 | login_check_credentials(); |
| 718 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 719 | zUserName = P("user"); |
| 720 | if( zUserName==0 ) zUserName = P("u"); |
| 721 | if( zUserName && zUserName[0]==0 ) zUserName = 0; |
| 722 | if( zView==0 ){ |
| 723 | zView = "byuser"; |
| 724 | cgi_replace_query_parameter("view","byuser"); |
| 725 | } |
| 726 | for(i=0; i<ArraySize(aViewType); i++){ |
| 727 | if( fossil_strcmp(zView, aViewType[i].zVal)==0 ){ |
| 728 | eType = aViewType[i].eType; |
| 729 | break; |
| 730 | } |
| 731 | } |
| 732 | url_initialize(&url, "reports"); |
| 733 | cgi_query_parameters_to_url(&url); |
| 734 | if( eType!=RPT_NONE ){ |
| 735 | int nView = 0; /* Slots used in azView[] */ |
| 736 | const char *azView[16]; /* Drop-down menu of view types */ |
| 737 | for(i=0; i<ArraySize(aViewType); i++){ |
| 738 | azView[nView++] = aViewType[i].zVal; |
| 739 | azView[nView++] = aViewType[i].zName; |
| 740 | } |
| 741 | if( eType!=RPT_BYFILE ){ |
| 742 | style_submenu_multichoice("type", ArraySize(azType)/2, azType, 0); |
| 743 | } |
| 744 | style_submenu_multichoice("view", nView/2, azView, 0); |
| 745 | if( eType!=RPT_BYUSER ){ |
| 746 | style_submenu_sql("u","User:", |
| 747 | "SELECT '', 'All Users' UNION ALL " |
| 748 | "SELECT x, x FROM (" |
| 749 | " SELECT DISTINCT trim(coalesce(euser,user)) AS x FROM event %s" |
| 750 | " ORDER BY 1 COLLATE nocase) WHERE x!=''", |
| 751 | eType==RPT_BYFILE ? "WHERE type='ci'" : "" |
| 752 | ); |
| 753 | } |
| 754 | } |
| 755 | style_submenu_element("Stats", "Stats", "%R/stat"); |
| 756 | url_reset(&url); |
| 757 | style_header("Activity Reports"); |
| 758 | switch( eType ){ |
| 759 | case RPT_BYYEAR: |
| 760 | stats_report_by_month_year(0, 0, zUserName); |
| 761 | break; |
| 762 | case RPT_BYMONTH: |
| 763 | stats_report_by_month_year(1, 0, zUserName); |
| 764 | break; |
| 765 | case RPT_BYWEEK: |
| 766 | stats_report_year_weeks(zUserName); |
| 767 | break; |
| 768 | default: |
| 769 | case RPT_BYUSER: |
| 770 | stats_report_by_user(); |
| 771 | break; |
| 772 | case RPT_BYWEEKDAY: |
| 773 | stats_report_day_of_week(zUserName); |
| 774 | break; |
| 775 | case RPT_BYFILE: |
| 776 | stats_report_by_file(zUserName); |
| 777 | break; |
| 778 | } |
| 779 | style_footer(); |
| 780 | } |
| 781 |
+162
-16
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -285,11 +285,45 @@ | ||
| 285 | 285 | aSubmenuCtrl[nSubmenuCtrl].azChoice = azChoice; |
| 286 | 286 | aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled; |
| 287 | 287 | aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI; |
| 288 | 288 | nSubmenuCtrl++; |
| 289 | 289 | } |
| 290 | +void style_submenu_sql( | |
| 291 | + const char *zName, /* Query parameter name */ | |
| 292 | + const char *zLabel, /* Label on the control */ | |
| 293 | + const char *zFormat, /* Format string for SQL command for choices */ | |
| 294 | + ... /* Arguments to the format string */ | |
| 295 | +){ | |
| 296 | + Stmt q; | |
| 297 | + int n = 0; | |
| 298 | + int nAlloc = 0; | |
| 299 | + char **az = 0; | |
| 300 | + va_list ap; | |
| 290 | 301 | |
| 302 | + va_start(ap, zFormat); | |
| 303 | + db_vprepare(&q, 0, zFormat, ap); | |
| 304 | + va_end(ap); | |
| 305 | + while( SQLITE_ROW==db_step(&q) ){ | |
| 306 | + if( n+2>=nAlloc ){ | |
| 307 | + nAlloc += nAlloc + 20; | |
| 308 | + az = fossil_realloc(az, sizeof(char*)*nAlloc); | |
| 309 | + } | |
| 310 | + az[n++] = fossil_strdup(db_column_text(&q,0)); | |
| 311 | + az[n++] = fossil_strdup(db_column_text(&q,1)); | |
| 312 | + } | |
| 313 | + db_finalize(&q); | |
| 314 | + if( n>0 ){ | |
| 315 | + aSubmenuCtrl[nSubmenuCtrl].zName = zName; | |
| 316 | + aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel; | |
| 317 | + aSubmenuCtrl[nSubmenuCtrl].iSize = n/2; | |
| 318 | + aSubmenuCtrl[nSubmenuCtrl].azChoice = (const char**)az; | |
| 319 | + aSubmenuCtrl[nSubmenuCtrl].isDisabled = 0; | |
| 320 | + aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI; | |
| 321 | + nSubmenuCtrl++; | |
| 322 | + } | |
| 323 | +} | |
| 324 | + | |
| 291 | 325 | |
| 292 | 326 | /* |
| 293 | 327 | ** Compare two submenu items for sorting purposes |
| 294 | 328 | */ |
| 295 | 329 | static int submenuCompare(const void *a, const void *b){ |
| @@ -514,10 +548,13 @@ | ||
| 514 | 548 | break; |
| 515 | 549 | } |
| 516 | 550 | case FF_MULTI: { |
| 517 | 551 | int j; |
| 518 | 552 | const char *zVal = P(zQPN); |
| 553 | + if( aSubmenuCtrl[i].zLabel ){ | |
| 554 | + cgi_printf(" %h", aSubmenuCtrl[i].zLabel); | |
| 555 | + } | |
| 519 | 556 | cgi_printf( |
| 520 | 557 | "<select class='submenuctrl' size='1' name='%s'%s " |
| 521 | 558 | "onchange='gebi(\"f01\").submit();'>\n", |
| 522 | 559 | zQPN, zDisabled |
| 523 | 560 | ); |
| @@ -701,15 +738,108 @@ | ||
| 701 | 738 | @ vertical-align: top; |
| 702 | 739 | @ text-align: right; |
| 703 | 740 | @ white-space: nowrap; |
| 704 | 741 | }, |
| 705 | 742 | { "td.timelineGraph", |
| 706 | - "the format for the grap placeholder cells in timelines", | |
| 743 | + "the format for the graph placeholder cells in timelines", | |
| 707 | 744 | @ width: 20px; |
| 708 | 745 | @ text-align: left; |
| 709 | 746 | @ vertical-align: top; |
| 710 | 747 | }, |
| 748 | + { ".tl-canvas", | |
| 749 | + "timeline graph canvas", | |
| 750 | + @ margin: 0 6px 0 10px; | |
| 751 | + }, | |
| 752 | + { ".tl-rail", | |
| 753 | + "maximum rail spacing", | |
| 754 | + @ width: 18px; | |
| 755 | + }, | |
| 756 | + { ".tl-mergeoffset", | |
| 757 | + "maximum spacing between merge risers and primary child risers", | |
| 758 | + @ width: 2px; | |
| 759 | + }, | |
| 760 | + { ".tl-nodemark", | |
| 761 | + "adjusts the vertical position of graph nodes", | |
| 762 | + @ margin-top: 5px; | |
| 763 | + }, | |
| 764 | + { ".tl-node", | |
| 765 | + "commit node", | |
| 766 | + @ width: 10px; | |
| 767 | + @ height: 10px; | |
| 768 | + @ border: 1px solid #000; | |
| 769 | + @ background: #fff; | |
| 770 | + @ cursor: pointer; | |
| 771 | + }, | |
| 772 | + { ".tl-node.leaf:after", | |
| 773 | + "leaf commit marker", | |
| 774 | + @ content: ''; | |
| 775 | + @ position: absolute; | |
| 776 | + @ top: 3px; | |
| 777 | + @ left: 3px; | |
| 778 | + @ width: 4px; | |
| 779 | + @ height: 4px; | |
| 780 | + @ background: #000; | |
| 781 | + }, | |
| 782 | + { ".tl-node.sel:after", | |
| 783 | + "selected commit node marker", | |
| 784 | + @ content: ''; | |
| 785 | + @ position: absolute; | |
| 786 | + @ top: 2px; | |
| 787 | + @ left: 2px; | |
| 788 | + @ width: 6px; | |
| 789 | + @ height: 6px; | |
| 790 | + @ background: red; | |
| 791 | + }, | |
| 792 | + { ".tl-arrow", | |
| 793 | + "arrow", | |
| 794 | + @ width: 0; | |
| 795 | + @ height: 0; | |
| 796 | + @ transform: scale(.999); | |
| 797 | + @ border: 0 solid transparent; | |
| 798 | + }, | |
| 799 | + { ".tl-arrow.u", | |
| 800 | + "up arrow", | |
| 801 | + @ margin-top: -1px; | |
| 802 | + @ border-width: 0 3px; | |
| 803 | + @ border-bottom: 7px solid #000; | |
| 804 | + }, | |
| 805 | + { ".tl-arrow.u.sm", | |
| 806 | + "small up arrow", | |
| 807 | + @ border-bottom: 5px solid #000; | |
| 808 | + }, | |
| 809 | + { ".tl-line", | |
| 810 | + "line", | |
| 811 | + @ background: #000; | |
| 812 | + @ width: 2px; | |
| 813 | + }, | |
| 814 | + { ".tl-arrow.merge", | |
| 815 | + "merge arrow", | |
| 816 | + @ height: 1px; | |
| 817 | + @ border-width: 2px 0; | |
| 818 | + }, | |
| 819 | + { ".tl-arrow.merge.l", | |
| 820 | + "left merge arrow", | |
| 821 | + @ border-right: 3px solid #000; | |
| 822 | + }, | |
| 823 | + { ".tl-arrow.merge.r", | |
| 824 | + "right merge arrow", | |
| 825 | + @ border-left: 3px solid #000; | |
| 826 | + }, | |
| 827 | + { ".tl-line.merge", | |
| 828 | + "merge line", | |
| 829 | + @ width: 1px; | |
| 830 | + }, | |
| 831 | + { ".tl-arrow.warp", | |
| 832 | + "timewarp arrow", | |
| 833 | + @ margin-left: 1px; | |
| 834 | + @ border-width: 3px 0; | |
| 835 | + @ border-left: 7px solid #600000; | |
| 836 | + }, | |
| 837 | + { ".tl-line.warp", | |
| 838 | + "timewarp line", | |
| 839 | + @ background: #600000; | |
| 840 | + }, | |
| 711 | 841 | { "a.tagLink", |
| 712 | 842 | "the format for the tag links", |
| 713 | 843 | @ |
| 714 | 844 | }, |
| 715 | 845 | { "span.tagDsp", |
| @@ -1226,14 +1356,10 @@ | ||
| 1226 | 1356 | }, |
| 1227 | 1357 | { "#usetupEditCapability", |
| 1228 | 1358 | "format for capabilities string, mentioned on the user edit page", |
| 1229 | 1359 | @ font-weight: bold; |
| 1230 | 1360 | }, |
| 1231 | - { "#canvas", "timeline graph node colors", | |
| 1232 | - @ color: black; | |
| 1233 | - @ background-color: white; | |
| 1234 | - }, | |
| 1235 | 1361 | { "table.adminLogTable", |
| 1236 | 1362 | "Class for the /admin_log table", |
| 1237 | 1363 | @ text-align: left; |
| 1238 | 1364 | }, |
| 1239 | 1365 | { ".adminLogTable .adminTime", |
| @@ -1336,30 +1462,50 @@ | ||
| 1336 | 1462 | } |
| 1337 | 1463 | } |
| 1338 | 1464 | } |
| 1339 | 1465 | |
| 1340 | 1466 | /* |
| 1341 | -** Search string zHaystack for zNeedle. zNeedle must be an isolated | |
| 1342 | -** word with space or punctuation on either size. | |
| 1467 | +** Search string zCss for zSelector. | |
| 1343 | 1468 | ** |
| 1344 | 1469 | ** Return true if found. Return false if not found |
| 1345 | 1470 | */ |
| 1346 | -static int containsString(const char *zHaystack, const char *zNeedle){ | |
| 1347 | - char *z; | |
| 1471 | +static int containsSelector(const char *zCss, const char *zSelector){ | |
| 1472 | + const char *z; | |
| 1348 | 1473 | int n; |
| 1474 | + int selectorLen = (int)strlen(zSelector); | |
| 1349 | 1475 | |
| 1350 | - while( zHaystack[0] ){ | |
| 1351 | - z = strstr(zHaystack, zNeedle); | |
| 1476 | + for(z=zCss; *z; z+=selectorLen){ | |
| 1477 | + z = strstr(z, zSelector); | |
| 1352 | 1478 | if( z==0 ) return 0; |
| 1353 | - n = (int)strlen(zNeedle); | |
| 1354 | - if( (z==zHaystack || !fossil_isalnum(z[-1])) && !fossil_isalnum(z[n]) ){ | |
| 1355 | - return 1; | |
| 1479 | + if( z!=zCss ){ | |
| 1480 | + for( n=-1; z+n!=zCss && fossil_isspace(z[n]); n--); | |
| 1481 | + if( z+n!=zCss && z[n]!=',' && z[n]!= '}' && z[n]!='/' ) continue; | |
| 1356 | 1482 | } |
| 1357 | - zHaystack = z + n; | |
| 1483 | + for( n=selectorLen; z[n] && fossil_isspace(z[n]); n++ ); | |
| 1484 | + if( z[n]==',' || z[n]=='{' || z[n]=='/' ) return 1; | |
| 1358 | 1485 | } |
| 1359 | 1486 | return 0; |
| 1360 | 1487 | } |
| 1488 | + | |
| 1489 | +/* | |
| 1490 | +** COMMAND: test-contains-selector | |
| 1491 | +** | |
| 1492 | +** Usage: %fossil test-contains-selector FILENAME SELECTOR | |
| 1493 | +** | |
| 1494 | +** Determine if the CSS stylesheet FILENAME contains SELECTOR. | |
| 1495 | +*/ | |
| 1496 | +void contains_selector_cmd(void){ | |
| 1497 | + int found; | |
| 1498 | + char *zSelector; | |
| 1499 | + Blob css; | |
| 1500 | + if( g.argc!=4 ) usage("FILENAME SELECTOR"); | |
| 1501 | + blob_read_from_file(&css, g.argv[2]); | |
| 1502 | + zSelector = g.argv[3]; | |
| 1503 | + found = containsSelector(blob_str(&css), zSelector); | |
| 1504 | + fossil_print("%s %s\n", zSelector, found ? "found" : "not found"); | |
| 1505 | + blob_reset(&css); | |
| 1506 | +} | |
| 1361 | 1507 | |
| 1362 | 1508 | |
| 1363 | 1509 | /* |
| 1364 | 1510 | ** WEBPAGE: style.css |
| 1365 | 1511 | ** |
| @@ -1373,11 +1519,11 @@ | ||
| 1373 | 1519 | blob_init(&css,skin_get("css"),-1); |
| 1374 | 1520 | |
| 1375 | 1521 | /* add special missing definitions */ |
| 1376 | 1522 | for(i=1; cssDefaultList[i].elementClass; i++){ |
| 1377 | 1523 | char *z = blob_str(&css); |
| 1378 | - if( !containsString(z, cssDefaultList[i].elementClass) ){ | |
| 1524 | + if( !containsSelector(z, cssDefaultList[i].elementClass) ){ | |
| 1379 | 1525 | blob_appendf(&css, "/* %s */\n%s {\n%s}\n", |
| 1380 | 1526 | cssDefaultList[i].comment, |
| 1381 | 1527 | cssDefaultList[i].elementClass, |
| 1382 | 1528 | cssDefaultList[i].value); |
| 1383 | 1529 | } |
| 1384 | 1530 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -285,11 +285,45 @@ | |
| 285 | aSubmenuCtrl[nSubmenuCtrl].azChoice = azChoice; |
| 286 | aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled; |
| 287 | aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI; |
| 288 | nSubmenuCtrl++; |
| 289 | } |
| 290 | |
| 291 | |
| 292 | /* |
| 293 | ** Compare two submenu items for sorting purposes |
| 294 | */ |
| 295 | static int submenuCompare(const void *a, const void *b){ |
| @@ -514,10 +548,13 @@ | |
| 514 | break; |
| 515 | } |
| 516 | case FF_MULTI: { |
| 517 | int j; |
| 518 | const char *zVal = P(zQPN); |
| 519 | cgi_printf( |
| 520 | "<select class='submenuctrl' size='1' name='%s'%s " |
| 521 | "onchange='gebi(\"f01\").submit();'>\n", |
| 522 | zQPN, zDisabled |
| 523 | ); |
| @@ -701,15 +738,108 @@ | |
| 701 | @ vertical-align: top; |
| 702 | @ text-align: right; |
| 703 | @ white-space: nowrap; |
| 704 | }, |
| 705 | { "td.timelineGraph", |
| 706 | "the format for the grap placeholder cells in timelines", |
| 707 | @ width: 20px; |
| 708 | @ text-align: left; |
| 709 | @ vertical-align: top; |
| 710 | }, |
| 711 | { "a.tagLink", |
| 712 | "the format for the tag links", |
| 713 | @ |
| 714 | }, |
| 715 | { "span.tagDsp", |
| @@ -1226,14 +1356,10 @@ | |
| 1226 | }, |
| 1227 | { "#usetupEditCapability", |
| 1228 | "format for capabilities string, mentioned on the user edit page", |
| 1229 | @ font-weight: bold; |
| 1230 | }, |
| 1231 | { "#canvas", "timeline graph node colors", |
| 1232 | @ color: black; |
| 1233 | @ background-color: white; |
| 1234 | }, |
| 1235 | { "table.adminLogTable", |
| 1236 | "Class for the /admin_log table", |
| 1237 | @ text-align: left; |
| 1238 | }, |
| 1239 | { ".adminLogTable .adminTime", |
| @@ -1336,30 +1462,50 @@ | |
| 1336 | } |
| 1337 | } |
| 1338 | } |
| 1339 | |
| 1340 | /* |
| 1341 | ** Search string zHaystack for zNeedle. zNeedle must be an isolated |
| 1342 | ** word with space or punctuation on either size. |
| 1343 | ** |
| 1344 | ** Return true if found. Return false if not found |
| 1345 | */ |
| 1346 | static int containsString(const char *zHaystack, const char *zNeedle){ |
| 1347 | char *z; |
| 1348 | int n; |
| 1349 | |
| 1350 | while( zHaystack[0] ){ |
| 1351 | z = strstr(zHaystack, zNeedle); |
| 1352 | if( z==0 ) return 0; |
| 1353 | n = (int)strlen(zNeedle); |
| 1354 | if( (z==zHaystack || !fossil_isalnum(z[-1])) && !fossil_isalnum(z[n]) ){ |
| 1355 | return 1; |
| 1356 | } |
| 1357 | zHaystack = z + n; |
| 1358 | } |
| 1359 | return 0; |
| 1360 | } |
| 1361 | |
| 1362 | |
| 1363 | /* |
| 1364 | ** WEBPAGE: style.css |
| 1365 | ** |
| @@ -1373,11 +1519,11 @@ | |
| 1373 | blob_init(&css,skin_get("css"),-1); |
| 1374 | |
| 1375 | /* add special missing definitions */ |
| 1376 | for(i=1; cssDefaultList[i].elementClass; i++){ |
| 1377 | char *z = blob_str(&css); |
| 1378 | if( !containsString(z, cssDefaultList[i].elementClass) ){ |
| 1379 | blob_appendf(&css, "/* %s */\n%s {\n%s}\n", |
| 1380 | cssDefaultList[i].comment, |
| 1381 | cssDefaultList[i].elementClass, |
| 1382 | cssDefaultList[i].value); |
| 1383 | } |
| 1384 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -285,11 +285,45 @@ | |
| 285 | aSubmenuCtrl[nSubmenuCtrl].azChoice = azChoice; |
| 286 | aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled; |
| 287 | aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI; |
| 288 | nSubmenuCtrl++; |
| 289 | } |
| 290 | void style_submenu_sql( |
| 291 | const char *zName, /* Query parameter name */ |
| 292 | const char *zLabel, /* Label on the control */ |
| 293 | const char *zFormat, /* Format string for SQL command for choices */ |
| 294 | ... /* Arguments to the format string */ |
| 295 | ){ |
| 296 | Stmt q; |
| 297 | int n = 0; |
| 298 | int nAlloc = 0; |
| 299 | char **az = 0; |
| 300 | va_list ap; |
| 301 | |
| 302 | va_start(ap, zFormat); |
| 303 | db_vprepare(&q, 0, zFormat, ap); |
| 304 | va_end(ap); |
| 305 | while( SQLITE_ROW==db_step(&q) ){ |
| 306 | if( n+2>=nAlloc ){ |
| 307 | nAlloc += nAlloc + 20; |
| 308 | az = fossil_realloc(az, sizeof(char*)*nAlloc); |
| 309 | } |
| 310 | az[n++] = fossil_strdup(db_column_text(&q,0)); |
| 311 | az[n++] = fossil_strdup(db_column_text(&q,1)); |
| 312 | } |
| 313 | db_finalize(&q); |
| 314 | if( n>0 ){ |
| 315 | aSubmenuCtrl[nSubmenuCtrl].zName = zName; |
| 316 | aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel; |
| 317 | aSubmenuCtrl[nSubmenuCtrl].iSize = n/2; |
| 318 | aSubmenuCtrl[nSubmenuCtrl].azChoice = (const char**)az; |
| 319 | aSubmenuCtrl[nSubmenuCtrl].isDisabled = 0; |
| 320 | aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI; |
| 321 | nSubmenuCtrl++; |
| 322 | } |
| 323 | } |
| 324 | |
| 325 | |
| 326 | /* |
| 327 | ** Compare two submenu items for sorting purposes |
| 328 | */ |
| 329 | static int submenuCompare(const void *a, const void *b){ |
| @@ -514,10 +548,13 @@ | |
| 548 | break; |
| 549 | } |
| 550 | case FF_MULTI: { |
| 551 | int j; |
| 552 | const char *zVal = P(zQPN); |
| 553 | if( aSubmenuCtrl[i].zLabel ){ |
| 554 | cgi_printf(" %h", aSubmenuCtrl[i].zLabel); |
| 555 | } |
| 556 | cgi_printf( |
| 557 | "<select class='submenuctrl' size='1' name='%s'%s " |
| 558 | "onchange='gebi(\"f01\").submit();'>\n", |
| 559 | zQPN, zDisabled |
| 560 | ); |
| @@ -701,15 +738,108 @@ | |
| 738 | @ vertical-align: top; |
| 739 | @ text-align: right; |
| 740 | @ white-space: nowrap; |
| 741 | }, |
| 742 | { "td.timelineGraph", |
| 743 | "the format for the graph placeholder cells in timelines", |
| 744 | @ width: 20px; |
| 745 | @ text-align: left; |
| 746 | @ vertical-align: top; |
| 747 | }, |
| 748 | { ".tl-canvas", |
| 749 | "timeline graph canvas", |
| 750 | @ margin: 0 6px 0 10px; |
| 751 | }, |
| 752 | { ".tl-rail", |
| 753 | "maximum rail spacing", |
| 754 | @ width: 18px; |
| 755 | }, |
| 756 | { ".tl-mergeoffset", |
| 757 | "maximum spacing between merge risers and primary child risers", |
| 758 | @ width: 2px; |
| 759 | }, |
| 760 | { ".tl-nodemark", |
| 761 | "adjusts the vertical position of graph nodes", |
| 762 | @ margin-top: 5px; |
| 763 | }, |
| 764 | { ".tl-node", |
| 765 | "commit node", |
| 766 | @ width: 10px; |
| 767 | @ height: 10px; |
| 768 | @ border: 1px solid #000; |
| 769 | @ background: #fff; |
| 770 | @ cursor: pointer; |
| 771 | }, |
| 772 | { ".tl-node.leaf:after", |
| 773 | "leaf commit marker", |
| 774 | @ content: ''; |
| 775 | @ position: absolute; |
| 776 | @ top: 3px; |
| 777 | @ left: 3px; |
| 778 | @ width: 4px; |
| 779 | @ height: 4px; |
| 780 | @ background: #000; |
| 781 | }, |
| 782 | { ".tl-node.sel:after", |
| 783 | "selected commit node marker", |
| 784 | @ content: ''; |
| 785 | @ position: absolute; |
| 786 | @ top: 2px; |
| 787 | @ left: 2px; |
| 788 | @ width: 6px; |
| 789 | @ height: 6px; |
| 790 | @ background: red; |
| 791 | }, |
| 792 | { ".tl-arrow", |
| 793 | "arrow", |
| 794 | @ width: 0; |
| 795 | @ height: 0; |
| 796 | @ transform: scale(.999); |
| 797 | @ border: 0 solid transparent; |
| 798 | }, |
| 799 | { ".tl-arrow.u", |
| 800 | "up arrow", |
| 801 | @ margin-top: -1px; |
| 802 | @ border-width: 0 3px; |
| 803 | @ border-bottom: 7px solid #000; |
| 804 | }, |
| 805 | { ".tl-arrow.u.sm", |
| 806 | "small up arrow", |
| 807 | @ border-bottom: 5px solid #000; |
| 808 | }, |
| 809 | { ".tl-line", |
| 810 | "line", |
| 811 | @ background: #000; |
| 812 | @ width: 2px; |
| 813 | }, |
| 814 | { ".tl-arrow.merge", |
| 815 | "merge arrow", |
| 816 | @ height: 1px; |
| 817 | @ border-width: 2px 0; |
| 818 | }, |
| 819 | { ".tl-arrow.merge.l", |
| 820 | "left merge arrow", |
| 821 | @ border-right: 3px solid #000; |
| 822 | }, |
| 823 | { ".tl-arrow.merge.r", |
| 824 | "right merge arrow", |
| 825 | @ border-left: 3px solid #000; |
| 826 | }, |
| 827 | { ".tl-line.merge", |
| 828 | "merge line", |
| 829 | @ width: 1px; |
| 830 | }, |
| 831 | { ".tl-arrow.warp", |
| 832 | "timewarp arrow", |
| 833 | @ margin-left: 1px; |
| 834 | @ border-width: 3px 0; |
| 835 | @ border-left: 7px solid #600000; |
| 836 | }, |
| 837 | { ".tl-line.warp", |
| 838 | "timewarp line", |
| 839 | @ background: #600000; |
| 840 | }, |
| 841 | { "a.tagLink", |
| 842 | "the format for the tag links", |
| 843 | @ |
| 844 | }, |
| 845 | { "span.tagDsp", |
| @@ -1226,14 +1356,10 @@ | |
| 1356 | }, |
| 1357 | { "#usetupEditCapability", |
| 1358 | "format for capabilities string, mentioned on the user edit page", |
| 1359 | @ font-weight: bold; |
| 1360 | }, |
| 1361 | { "table.adminLogTable", |
| 1362 | "Class for the /admin_log table", |
| 1363 | @ text-align: left; |
| 1364 | }, |
| 1365 | { ".adminLogTable .adminTime", |
| @@ -1336,30 +1462,50 @@ | |
| 1462 | } |
| 1463 | } |
| 1464 | } |
| 1465 | |
| 1466 | /* |
| 1467 | ** Search string zCss for zSelector. |
| 1468 | ** |
| 1469 | ** Return true if found. Return false if not found |
| 1470 | */ |
| 1471 | static int containsSelector(const char *zCss, const char *zSelector){ |
| 1472 | const char *z; |
| 1473 | int n; |
| 1474 | int selectorLen = (int)strlen(zSelector); |
| 1475 | |
| 1476 | for(z=zCss; *z; z+=selectorLen){ |
| 1477 | z = strstr(z, zSelector); |
| 1478 | if( z==0 ) return 0; |
| 1479 | if( z!=zCss ){ |
| 1480 | for( n=-1; z+n!=zCss && fossil_isspace(z[n]); n--); |
| 1481 | if( z+n!=zCss && z[n]!=',' && z[n]!= '}' && z[n]!='/' ) continue; |
| 1482 | } |
| 1483 | for( n=selectorLen; z[n] && fossil_isspace(z[n]); n++ ); |
| 1484 | if( z[n]==',' || z[n]=='{' || z[n]=='/' ) return 1; |
| 1485 | } |
| 1486 | return 0; |
| 1487 | } |
| 1488 | |
| 1489 | /* |
| 1490 | ** COMMAND: test-contains-selector |
| 1491 | ** |
| 1492 | ** Usage: %fossil test-contains-selector FILENAME SELECTOR |
| 1493 | ** |
| 1494 | ** Determine if the CSS stylesheet FILENAME contains SELECTOR. |
| 1495 | */ |
| 1496 | void contains_selector_cmd(void){ |
| 1497 | int found; |
| 1498 | char *zSelector; |
| 1499 | Blob css; |
| 1500 | if( g.argc!=4 ) usage("FILENAME SELECTOR"); |
| 1501 | blob_read_from_file(&css, g.argv[2]); |
| 1502 | zSelector = g.argv[3]; |
| 1503 | found = containsSelector(blob_str(&css), zSelector); |
| 1504 | fossil_print("%s %s\n", zSelector, found ? "found" : "not found"); |
| 1505 | blob_reset(&css); |
| 1506 | } |
| 1507 | |
| 1508 | |
| 1509 | /* |
| 1510 | ** WEBPAGE: style.css |
| 1511 | ** |
| @@ -1373,11 +1519,11 @@ | |
| 1519 | blob_init(&css,skin_get("css"),-1); |
| 1520 | |
| 1521 | /* add special missing definitions */ |
| 1522 | for(i=1; cssDefaultList[i].elementClass; i++){ |
| 1523 | char *z = blob_str(&css); |
| 1524 | if( !containsSelector(z, cssDefaultList[i].elementClass) ){ |
| 1525 | blob_appendf(&css, "/* %s */\n%s {\n%s}\n", |
| 1526 | cssDefaultList[i].comment, |
| 1527 | cssDefaultList[i].elementClass, |
| 1528 | cssDefaultList[i].value); |
| 1529 | } |
| 1530 |
+245
-276
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -241,23 +241,17 @@ | ||
| 241 | 241 | dateFormat = db_get_int("timeline-date-format", 0); |
| 242 | 242 | zDateFmt = P("datefmt"); |
| 243 | 243 | if( zDateFmt ) dateFormat = atoi(zDateFmt); |
| 244 | 244 | if( tmFlags & TIMELINE_GRAPH ){ |
| 245 | 245 | pGraph = graph_init(); |
| 246 | - /* style is not moved to css, because this is | |
| 247 | - ** a technical div for the timeline graph | |
| 248 | - */ | |
| 249 | - @ <div id="canvas" style="position:relative;height:0px;width:0px;" | |
| 250 | - @ onclick="clickOnGraph(event)"></div> | |
| 251 | 246 | } |
| 252 | 247 | db_static_prepare(&qbranch, |
| 253 | 248 | "SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0 AND rid=:rid", |
| 254 | 249 | TAG_BRANCH |
| 255 | 250 | ); |
| 256 | 251 | |
| 257 | - @ <table id="timelineTable" class="timelineTable" | |
| 258 | - @ onclick="clickOnGraph(event)"> | |
| 252 | + @ <table id="timelineTable" class="timelineTable"> | |
| 259 | 253 | blob_zero(&comment); |
| 260 | 254 | while( db_step(pQuery)==SQLITE_ROW ){ |
| 261 | 255 | int rid = db_column_int(pQuery, 0); |
| 262 | 256 | const char *zUuid = db_column_text(pQuery, 1); |
| 263 | 257 | int isLeaf = db_column_int(pQuery, 5); |
| @@ -391,11 +385,11 @@ | ||
| 391 | 385 | } |
| 392 | 386 | db_reset(&qparent); |
| 393 | 387 | gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr, |
| 394 | 388 | zUuid, isLeaf); |
| 395 | 389 | db_reset(&qbranch); |
| 396 | - @ <div id="m%d(gidx)"></div> | |
| 390 | + @ <div id="m%d(gidx)" class="tl-nodemark"></div> | |
| 397 | 391 | } |
| 398 | 392 | @</td> |
| 399 | 393 | if( zBgClr && zBgClr[0] && rid!=selectedRid ){ |
| 400 | 394 | @ <td class="timelineTableCell" style="background-color: %h(zBgClr);"> |
| 401 | 395 | }else{ |
| @@ -589,18 +583,11 @@ | ||
| 589 | 583 | graph_finish(pGraph, (tmFlags & TIMELINE_DISJOINT)!=0); |
| 590 | 584 | if( pGraph->nErr ){ |
| 591 | 585 | graph_free(pGraph); |
| 592 | 586 | pGraph = 0; |
| 593 | 587 | }else{ |
| 594 | - int w; | |
| 595 | - /* style is not moved to css, because this is | |
| 596 | - ** a technical div for the timeline graph | |
| 597 | - */ | |
| 598 | - w = pGraph->mxRail*pGraph->iRailPitch + 28; | |
| 599 | - @ <tr class="timelineBottom"><td></td><td> | |
| 600 | - @ <div id="grbtm" style="width:%d(w)px;"></div> | |
| 601 | - @ </td><td></td></tr> | |
| 588 | + @ <tr class="timelineBottom"><td></td><td></td><td></td></tr> | |
| 602 | 589 | } |
| 603 | 590 | } |
| 604 | 591 | @ </table> |
| 605 | 592 | if( fchngQueryInit ) db_finalize(&fchngQuery); |
| 606 | 593 | timeline_output_graph_javascript(pGraph, (tmFlags & TIMELINE_DISJOINT)!=0, 0); |
| @@ -648,31 +635,34 @@ | ||
| 648 | 635 | ){ |
| 649 | 636 | if( pGraph && pGraph->nErr==0 && pGraph->nRow>0 ){ |
| 650 | 637 | GraphRow *pRow; |
| 651 | 638 | int i; |
| 652 | 639 | char cSep; |
| 653 | - int mergeOffset; /* Pixel offset from rail to merge riser */ | |
| 654 | 640 | int iRailPitch; /* Pixels between consecutive rails */ |
| 655 | 641 | int showArrowheads; /* True to draw arrowheads. False to omit. */ |
| 656 | 642 | int circleNodes; /* True for circle nodes. False for square nodes */ |
| 657 | 643 | int colorGraph; /* Use colors for graph lines */ |
| 658 | 644 | |
| 659 | - iRailPitch = pGraph->iRailPitch; | |
| 645 | + iRailPitch = atoi(PD("railpitch","0")); | |
| 660 | 646 | showArrowheads = skin_detail_boolean("timeline-arrowheads"); |
| 661 | 647 | circleNodes = skin_detail_boolean("timeline-circle-nodes"); |
| 662 | 648 | colorGraph = skin_detail_boolean("timeline-color-graph-lines"); |
| 663 | 649 | |
| 664 | - /* Number of pixels that the thin merge lines are offset from the | |
| 665 | - ** the center of the think rail lines. If zero, then the vertical | |
| 666 | - ** merge lines overlap with the thicker rail lines. | |
| 667 | - */ | |
| 668 | - mergeOffset = iRailPitch>=14 ? 4 : iRailPitch>=13 ? 3 : 0; | |
| 669 | - if( PB("nomo") ) mergeOffset = 0; | |
| 670 | - | |
| 671 | - @ <script> | |
| 672 | - @ var railPitch=%d(iRailPitch); | |
| 673 | - | |
| 650 | + @ <script>(function(){ | |
| 651 | + @ "use strict"; | |
| 652 | + @ var css = ""; | |
| 653 | + if( circleNodes ){ | |
| 654 | + @ css += ".tl-node, .tl-node:after { border-radius: 50%%; }"; | |
| 655 | + } | |
| 656 | + if( !showArrowheads ){ | |
| 657 | + @ css += ".tl-arrow.u { display: none; }"; | |
| 658 | + } | |
| 659 | + @ if( css!=="" ){ | |
| 660 | + @ var style = document.createElement("style"); | |
| 661 | + @ style.textContent = css; | |
| 662 | + @ document.querySelector("head").appendChild(style); | |
| 663 | + @ } | |
| 674 | 664 | /* the rowinfo[] array contains all the information needed to generate |
| 675 | 665 | ** the graph. Each entry contains information for a single row: |
| 676 | 666 | ** |
| 677 | 667 | ** id: The id of the <div> element for the row. This is an integer. |
| 678 | 668 | ** to get an actual id, prepend "m" to the integer. The top node |
| @@ -680,13 +670,13 @@ | ||
| 680 | 670 | ** bg: The background color for this row |
| 681 | 671 | ** r: The "rail" that the node for this row sits on. The left-most |
| 682 | 672 | ** rail is 0 and the number increases to the right. |
| 683 | 673 | ** d: True if there is a "descender" - an arrow coming from the bottom |
| 684 | 674 | ** of the page straight up to this node. |
| 685 | - ** mo: "merge-out". If non-zero, this is one more than the x-coordinate | |
| 675 | + ** mo: "merge-out". If non-negative, this is the rail position | |
| 686 | 676 | ** for the upward portion of a merge arrow. The merge arrow goes up |
| 687 | - ** to the row identified by mu:. If this value is zero then | |
| 677 | + ** to the row identified by mu:. If this value is negative then | |
| 688 | 678 | ** node has no merge children and no merge-out line is drawn. |
| 689 | 679 | ** mu: The id of the row which is the top of the merge-out arrow. |
| 690 | 680 | ** u: Draw a thick child-line out of the top of this node and up to |
| 691 | 681 | ** the node with an id equal to this value. 0 if it is straight to |
| 692 | 682 | ** the top of the page, -1 if there is no thick-line riser. |
| @@ -693,37 +683,25 @@ | ||
| 693 | 683 | ** f: 0x01: a leaf node. |
| 694 | 684 | ** au: An array of integers that define thick-line risers for branches. |
| 695 | 685 | ** The integers are in pairs. For each pair, the first integer is |
| 696 | 686 | ** is the rail on which the riser should run and the second integer |
| 697 | 687 | ** is the id of the node upto which the riser should run. |
| 698 | - ** mi: "merge-in". An array of integer x-coordinates from which | |
| 688 | + ** mi: "merge-in". An array of integer rail positions from which | |
| 699 | 689 | ** merge arrows should be drawn into this node. If the value is |
| 700 | - ** negative, then the x-coordinate is the absolute value of mi[] | |
| 690 | + ** negative, then the rail position is the absolute value of mi[] | |
| 701 | 691 | ** and a thin merge-arrow descender is drawn to the bottom of |
| 702 | 692 | ** the screen. |
| 703 | 693 | ** h: The SHA1 hash of the object being graphed |
| 704 | 694 | */ |
| 705 | 695 | cgi_printf("var rowinfo = [\n"); |
| 706 | 696 | for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){ |
| 707 | - int mo = pRow->mergeOut; | |
| 708 | - if( mo<0 ){ | |
| 709 | - mo = 0; | |
| 710 | - }else{ | |
| 711 | - int x = (mo/4)*iRailPitch; | |
| 712 | - switch( mo&3 ){ | |
| 713 | - case 0: x -= mergeOffset-2; break; | |
| 714 | - case 1: x += 1; break; | |
| 715 | - case 2: x += mergeOffset+1; break; | |
| 716 | - } | |
| 717 | - mo = x; | |
| 718 | - } | |
| 719 | 697 | cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,u:%d,f:%d,au:", |
| 720 | 698 | pRow->idx, /* id */ |
| 721 | 699 | pRow->zBgClr, /* bg */ |
| 722 | 700 | pRow->iRail, /* r */ |
| 723 | 701 | pRow->bDescender, /* d */ |
| 724 | - mo, /* mo */ | |
| 702 | + pRow->mergeOut, /* mo */ | |
| 725 | 703 | pRow->mergeUpto, /* mu */ |
| 726 | 704 | pRow->aiRiser[pRow->iRail], /* u */ |
| 727 | 705 | pRow->isLeaf ? 1 : 0 /* f */ |
| 728 | 706 | ); |
| 729 | 707 | /* u */ |
| @@ -743,13 +721,11 @@ | ||
| 743 | 721 | /* mi */ |
| 744 | 722 | cgi_printf("mi:"); |
| 745 | 723 | cSep = '['; |
| 746 | 724 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 747 | 725 | if( pRow->mergeIn[i] ){ |
| 748 | - int mi = i*iRailPitch; | |
| 749 | - if( pRow->mergeIn[i]==1 ) mi -= mergeOffset-1; | |
| 750 | - if( pRow->mergeIn[i]==3 ) mi += mergeOffset; | |
| 726 | + int mi = i; | |
| 751 | 727 | if( pRow->mergeDown & (1<<i) ) mi = -mi; |
| 752 | 728 | cgi_printf("%c%d", cSep, mi); |
| 753 | 729 | cSep = ','; |
| 754 | 730 | } |
| 755 | 731 | } |
| @@ -756,246 +732,238 @@ | ||
| 756 | 732 | if( cSep=='[' ) cgi_printf("["); |
| 757 | 733 | cgi_printf("],h:\"%s\"}%s", pRow->zUuid, pRow->pNext ? ",\n" : "];\n"); |
| 758 | 734 | } |
| 759 | 735 | cgi_printf("var nrail = %d\n", pGraph->mxRail+1); |
| 760 | 736 | graph_free(pGraph); |
| 761 | - @ var cDiv = gebi("canvas"); | |
| 762 | - @ var csty = window.getComputedStyle && window.getComputedStyle(cDiv,null); | |
| 763 | - @ var lineClr = (csty && csty.getPropertyValue('color')) || 'black'; | |
| 764 | - @ var bgClr = (csty && csty.getPropertyValue('background-color')) ||'white'; | |
| 765 | - @ if( bgClr=='transparent' ) bgClr = 'white'; | |
| 766 | - @ var boxColor = lineClr; | |
| 767 | - @ function drawBox(color,x0,y0,x1,y1){ | |
| 737 | + @ var canvasDiv; | |
| 738 | + @ var railPitch; | |
| 739 | + @ var mergeOffset; | |
| 740 | + @ var node, arrow, arrowSmall, line, mArrow, mLine, wArrow, wLine; | |
| 741 | + @ function initGraph(){ | |
| 742 | + @ var parent = gebi("timelineTable").rows[0].cells[1]; | |
| 743 | + @ parent.style.verticalAlign = "top"; | |
| 744 | + @ canvasDiv = document.createElement("div"); | |
| 745 | + @ canvasDiv.className = "tl-canvas"; | |
| 746 | + @ canvasDiv.style.position = "absolute"; | |
| 747 | + @ parent.appendChild(canvasDiv); | |
| 748 | + @ | |
| 749 | + @ var elems = {}; | |
| 750 | + @ var elemClasses = [ | |
| 751 | + @ "rail", "mergeoffset", "node", "arrow u", "arrow u sm", "line", | |
| 752 | + @ "arrow merge r", "line merge", "arrow warp", "line warp" | |
| 753 | + @ ]; | |
| 754 | + @ for( var i=0; i<elemClasses.length; i++ ){ | |
| 755 | + @ var cls = elemClasses[i]; | |
| 756 | + @ var elem = document.createElement("div"); | |
| 757 | + @ elem.className = "tl-" + cls; | |
| 758 | + @ if( cls.indexOf("line")==0 ) elem.className += " v"; | |
| 759 | + @ canvasDiv.appendChild(elem); | |
| 760 | + @ var k = cls.replace(/\s/g, "_"); | |
| 761 | + @ var r = elem.getBoundingClientRect(); | |
| 762 | + @ var w = Math.round(r.right - r.left); | |
| 763 | + @ var h = Math.round(r.bottom - r.top); | |
| 764 | + @ elems[k] = {w: w, h: h, cls: cls}; | |
| 765 | + @ } | |
| 766 | + @ node = elems.node; | |
| 767 | + @ arrow = elems.arrow_u; | |
| 768 | + @ arrowSmall = elems.arrow_u_sm; | |
| 769 | + @ line = elems.line; | |
| 770 | + @ mArrow = elems.arrow_merge_r; | |
| 771 | + @ mLine = elems.line_merge; | |
| 772 | + @ wArrow = elems.arrow_warp; | |
| 773 | + @ wLine = elems.line_warp; | |
| 774 | + @ | |
| 775 | + @ var minRailPitch = Math.ceil((node.w+line.w)/2 + mArrow.w + 1); | |
| 776 | + if( iRailPitch ){ | |
| 777 | + @ railPitch = %d(iRailPitch); | |
| 778 | + }else{ | |
| 779 | + @ railPitch = elems.rail.w; | |
| 780 | + @ railPitch -= Math.floor((nrail-1)*(railPitch-minRailPitch)/21); | |
| 781 | + } | |
| 782 | + @ railPitch = Math.max(railPitch, minRailPitch); | |
| 783 | + @ | |
| 784 | + if( PB("nomo") ){ | |
| 785 | + @ mergeOffset = 0; | |
| 786 | + }else{ | |
| 787 | + @ mergeOffset = railPitch-minRailPitch-mLine.w; | |
| 788 | + @ mergeOffset = Math.min(mergeOffset, elems.mergeoffset.w); | |
| 789 | + @ mergeOffset = mergeOffset>0 ? mergeOffset + line.w/2 : 0; | |
| 790 | + } | |
| 791 | + @ | |
| 792 | + @ var canvasWidth = (nrail-1)*railPitch + node.w; | |
| 793 | + @ canvasDiv.style.width = canvasWidth + "px"; | |
| 794 | + @ canvasDiv.style.position = "relative"; | |
| 795 | + @ } | |
| 796 | + @ function drawBox(cls,color,x0,y0,x1,y1){ | |
| 768 | 797 | @ var n = document.createElement("div"); |
| 798 | + @ x0 = Math.floor(x0); | |
| 799 | + @ y0 = Math.floor(y0); | |
| 800 | + @ x1 = x1 || x1===0 ? Math.floor(x1) : x0; | |
| 801 | + @ y1 = y1 || y1===0 ? Math.floor(y1) : y0; | |
| 769 | 802 | @ if( x0>x1 ){ var t=x0; x0=x1; x1=t; } |
| 770 | 803 | @ if( y0>y1 ){ var t=y0; y0=y1; y1=t; } |
| 771 | - @ var w = x1-x0+1; | |
| 772 | - @ var h = y1-y0+1; | |
| 804 | + @ var w = x1-x0; | |
| 805 | + @ var h = y1-y0; | |
| 773 | 806 | @ n.style.position = "absolute"; |
| 774 | - @ n.style.overflow = "hidden"; | |
| 775 | 807 | @ n.style.left = x0+"px"; |
| 776 | 808 | @ n.style.top = y0+"px"; |
| 777 | - @ n.style.width = w+"px"; | |
| 778 | - @ n.style.height = h+"px"; | |
| 779 | - @ n.style.backgroundColor = color; | |
| 780 | - @ cDiv.appendChild(n); | |
| 809 | + @ if( w ) n.style.width = w+"px"; | |
| 810 | + @ if( h ) n.style.height = h+"px"; | |
| 811 | + @ if( color ) n.style.backgroundColor = color; | |
| 812 | + @ n.className = "tl-"+cls; | |
| 813 | + @ canvasDiv.appendChild(n); | |
| 781 | 814 | @ return n; |
| 782 | 815 | @ } |
| 783 | - @ function absoluteY(id){ | |
| 784 | - @ var obj = gebi(id); | |
| 785 | - @ if( !obj ) return; | |
| 816 | + @ function absoluteY(obj){ | |
| 786 | 817 | @ var top = 0; |
| 787 | 818 | @ if( obj.offsetParent ){ |
| 788 | 819 | @ do{ |
| 789 | 820 | @ top += obj.offsetTop; |
| 790 | 821 | @ }while( obj = obj.offsetParent ); |
| 791 | 822 | @ } |
| 792 | 823 | @ return top; |
| 793 | 824 | @ } |
| 794 | - @ function absoluteX(id){ | |
| 795 | - @ var obj = gebi(id); | |
| 796 | - @ if( !obj ) return; | |
| 797 | - @ var left = 0; | |
| 798 | - @ if( obj.offsetParent ){ | |
| 799 | - @ do{ | |
| 800 | - @ left += obj.offsetLeft; | |
| 801 | - @ }while( obj = obj.offsetParent ); | |
| 802 | - @ } | |
| 803 | - @ return left; | |
| 804 | - @ } | |
| 805 | - if( showArrowheads ){ | |
| 806 | - @ function drawUpArrow(x,y0,y1,clr){ | |
| 807 | - @ drawBox(clr,x,y0+4,x+1,y1); | |
| 808 | - @ var n = document.createElement("div"), | |
| 809 | - @ l = x-2, | |
| 810 | - @ t = y0; | |
| 811 | - @ n.style.position = "absolute"; | |
| 812 | - @ n.style.left = l+"px"; | |
| 813 | - @ n.style.top = t+"px"; | |
| 814 | - @ n.style.width = 0; | |
| 815 | - @ n.style.height = 0; | |
| 816 | - @ n.style.transform = "scale(.999)"; | |
| 817 | - @ n.style.borderWidth = 0; | |
| 818 | - @ n.style.borderStyle = "solid"; | |
| 819 | - @ n.style.borderColor = "transparent"; | |
| 820 | - @ n.style.borderRightWidth = "3px"; | |
| 821 | - @ n.style.borderBottomColor = clr; | |
| 822 | - @ n.style.borderLeftWidth = "3px"; | |
| 823 | - @ if( y0+10>=y1 ){ | |
| 824 | - @ n.style.borderBottomWidth = "5px"; | |
| 825 | - @ } else { | |
| 826 | - @ n.style.borderBottomWidth = "7px"; | |
| 827 | - @ } | |
| 828 | - @ cDiv.appendChild(n); | |
| 829 | - @ } | |
| 830 | - }else{ | |
| 831 | - @ function drawUpArrow(x,y0,y1,clr){ | |
| 832 | - @ drawBox(clr,x,y0+1,x+1,y1); | |
| 833 | - @ } | |
| 834 | - } | |
| 835 | - @ function drawThinArrow(y,xFrom,xTo){ | |
| 836 | - @ var n = document.createElement("div"), | |
| 837 | - @ t = y-2; | |
| 838 | - @ n.style.position = "absolute"; | |
| 839 | - @ n.style.top = t+"px"; | |
| 840 | - @ n.style.width = 0; | |
| 841 | - @ n.style.height = "1px"; | |
| 842 | - @ n.style.transform = "scale(.999)"; | |
| 843 | - @ n.style.borderWidth = 0; | |
| 844 | - @ n.style.borderStyle = "solid"; | |
| 845 | - @ n.style.borderColor = "transparent"; | |
| 846 | - @ n.style.borderTopWidth = "2px"; | |
| 847 | - @ n.style.borderBottomWidth = "2px"; | |
| 848 | - @ if( xFrom<xTo ){ | |
| 849 | - @ drawBox(lineClr,xFrom,y,xTo-3,y); | |
| 850 | - @ n.style.left = xTo-3+"px"; | |
| 851 | - @ n.style.borderLeftWidth = "3px"; | |
| 852 | - @ n.style.borderLeftColor = lineClr; | |
| 853 | - @ }else{ | |
| 854 | - @ drawBox(lineClr,xTo+3,y,xFrom,y); | |
| 855 | - @ n.style.left = xTo+1+"px"; | |
| 856 | - @ n.style.borderRightWidth = "3px"; | |
| 857 | - @ n.style.borderRightColor = lineClr; | |
| 858 | - @ } | |
| 859 | - @ cDiv.appendChild(n); | |
| 860 | - @ } | |
| 861 | - @ function drawThinLine(x0,y0,x1,y1){ | |
| 862 | - @ drawBox(lineClr,x0,y0,x1,y1); | |
| 863 | - @ } | |
| 864 | - @ function drawNodeBox(color,x0,y0,x1,y1){ | |
| 865 | - @ var n = drawBox(color,x0,y0,x1,y1); | |
| 866 | - @ n.style.cursor = "pointer"; | |
| 867 | - if( circleNodes ){ | |
| 868 | - @ n.style.borderRadius = "6px"; | |
| 869 | - } | |
| 870 | - @ } | |
| 871 | - @ function drawNode(p, left, btm){ | |
| 872 | - @ drawNodeBox(boxColor,p.x-5,p.y-5,p.x+6,p.y+6); | |
| 873 | - @ drawNodeBox(p.bg||bgClr,p.x-4,p.y-4,p.x+5,p.y+5); | |
| 874 | - @ if( p.u>0 ) drawUpArrow(p.x,rowinfo[p.u-1].y+6,p.y-6,p.fg||lineClr); | |
| 875 | - @ if( p.f&1 ) drawNodeBox(boxColor,p.x-1,p.y-1,p.x+2,p.y+2); | |
| 876 | - if( !omitDescenders ){ | |
| 877 | - @ if( p.u==0 ) drawUpArrow(p.x,0,p.y-6,p.fg||lineClr); | |
| 878 | - @ if( p.d ) drawUpArrow(p.x,p.y+6,btm,p.fg||lineClr); | |
| 879 | - } | |
| 880 | - @ if( p.mo>0 ){ | |
| 881 | - @ var x1 = p.mo + left - 1; | |
| 882 | - @ var y1 = p.y-3; | |
| 883 | - @ var x0 = x1>p.x ? p.x+7 : p.x-6; | |
| 884 | - @ var u = rowinfo[p.mu-1]; | |
| 885 | - @ var y0 = u.y+5; | |
| 886 | - @ if( x1>=p.x-5 && x1<=p.x+5 ){ | |
| 887 | - @ y1 = p.y-5; | |
| 888 | - @ }else{ | |
| 889 | - @ drawThinLine(x0,y1,x1,y1); | |
| 890 | - @ } | |
| 891 | - if( mergeOffset==0 ) cgi_printf("if( p.mo!=p.u-1 ) "); | |
| 892 | - @ drawThinLine(x1,y0,x1,y1); | |
| 893 | - @ } | |
| 894 | - @ var n = p.au.length; | |
| 895 | - @ for(var i=0; i<n; i+=2){ | |
| 896 | - @ var x1 = p.au[i]*railPitch + left; | |
| 897 | - @ var x0 = x1>p.x ? p.x+7 : p.x-6; | |
| 898 | - @ var u = rowinfo[p.au[i+1]-1]; | |
| 899 | - @ if(u.id<p.id){ | |
| 900 | - @ drawBox(u.fg||lineClr,x0,p.y,x1+1,p.y+1); | |
| 901 | - @ drawUpArrow(x1,u.y+6,p.y,u.fg||lineClr); | |
| 902 | - @ }else{ | |
| 903 | - @ drawBox("#600000",x0,p.y,x1,p.y+1); | |
| 904 | - @ drawBox("#600000",x1-1,p.y,x1,u.y+1); | |
| 905 | - @ drawBox("#600000",x1,u.y,u.x-10,u.y+1); | |
| 906 | - @ var n = document.createElement("div"), | |
| 907 | - @ t = u.y-2, | |
| 908 | - @ l = u.x-11; | |
| 909 | - @ n.style.position = "absolute"; | |
| 910 | - @ n.style.top = t+"px"; | |
| 911 | - @ n.style.left = l+"px"; | |
| 912 | - @ n.style.width = 0; | |
| 913 | - @ n.style.height = 0; | |
| 914 | - @ n.style.transform = "scale(.999)"; | |
| 915 | - @ n.style.borderWidth = 0; | |
| 916 | - @ n.style.borderStyle = "solid"; | |
| 917 | - @ n.style.borderColor = "transparent"; | |
| 918 | - @ n.style.borderTopWidth = "3px"; | |
| 919 | - @ n.style.borderBottomWidth = "3px"; | |
| 920 | - @ n.style.borderLeftWidth = "7px"; | |
| 921 | - @ n.style.borderLeftColor = "#600000"; | |
| 922 | - @ cDiv.appendChild(n); | |
| 923 | - @ } | |
| 924 | - @ } | |
| 925 | - @ for(var j in p.mi){ | |
| 926 | - @ var y0 = p.y+5; | |
| 927 | - @ var mx = p.mi[j]; | |
| 928 | - @ if( mx<0 ){ | |
| 929 | - @ mx = left-mx; | |
| 930 | - @ drawThinLine(mx,y0,mx,btm); | |
| 931 | - @ }else{ | |
| 932 | - @ mx += left; | |
| 933 | - @ } | |
| 934 | - @ if( mx>p.x ){ | |
| 935 | - @ drawThinArrow(y0,mx,p.x+6); | |
| 936 | - @ }else{ | |
| 937 | - @ drawThinArrow(y0,mx,p.x-5); | |
| 938 | - @ } | |
| 939 | - @ } | |
| 940 | - @ } | |
| 941 | - @ var selBox = null; | |
| 942 | - @ var selRow = null; | |
| 943 | - @ function renderGraph(){ | |
| 944 | - @ var canvasDiv = gebi("canvas"); | |
| 945 | - @ while( canvasDiv.hasChildNodes() ){ | |
| 946 | - @ canvasDiv.removeChild(canvasDiv.firstChild); | |
| 947 | - @ } | |
| 948 | - @ var canvasY = absoluteY("timelineTable"); | |
| 949 | - @ var left = absoluteX("m"+rowinfo[0].id) - absoluteX("canvas") + 15; | |
| 950 | - @ for(var i in rowinfo){ | |
| 951 | - @ rowinfo[i].y = absoluteY("m"+rowinfo[i].id) + 10 - canvasY; | |
| 952 | - @ rowinfo[i].x = left + rowinfo[i].r*railPitch; | |
| 953 | - @ } | |
| 954 | - @ var btm = absoluteY("grbtm") + 10 - canvasY; | |
| 955 | - @ for(var i in rowinfo){ | |
| 956 | - @ drawNode(rowinfo[i], left, btm); | |
| 957 | - @ } | |
| 958 | - @ if( selRow!=null ) clickOnRow(selRow); | |
| 959 | - @ } | |
| 960 | - @ function clickOnGraph(event){ | |
| 961 | - @ var x=event.clientX-absoluteX("canvas"); | |
| 962 | - @ var y=event.clientY-absoluteY("canvas"); | |
| 963 | - @ if(window.pageXOffset!=null){ | |
| 964 | - @ x += window.pageXOffset; | |
| 965 | - @ y += window.pageYOffset; | |
| 966 | - @ }else{ | |
| 967 | - @ var d = window.document.documentElement; | |
| 968 | - @ if(document.compatMode!="CSS1Compat") d = d.body; | |
| 969 | - @ x += d.scrollLeft; | |
| 970 | - @ y += d.scrollTop; | |
| 971 | - @ } | |
| 972 | - if( P("clicktest")!=0 ){ | |
| 973 | - @ alert("click at "+x+","+y) | |
| 974 | - } | |
| 975 | - @ for(var i in rowinfo){ | |
| 976 | - @ p = rowinfo[i]; | |
| 977 | - @ if( p.y<y-11 ) continue; | |
| 978 | - @ if( p.y>y+9 ) break; | |
| 979 | - @ if( p.x>x-11 && p.x<x+9 ){ | |
| 980 | - @ clickOnRow(p); | |
| 981 | - @ break; | |
| 982 | - @ } | |
| 983 | - @ } | |
| 984 | - @ } | |
| 985 | - @ function clickOnRow(p){ | |
| 986 | - @ if( selRow==null ){ | |
| 987 | - @ selBox = drawBox("red",p.x-2,p.y-2,p.x+3,p.y+3); | |
| 988 | - if( circleNodes ){ | |
| 989 | - @ selBox.style.borderRadius="6px"; | |
| 990 | - } | |
| 991 | - @ selRow = p; | |
| 992 | - @ }else if( selRow==p ){ | |
| 993 | - @ var canvasDiv = gebi("canvas"); | |
| 994 | - @ canvasDiv.removeChild(selBox); | |
| 995 | - @ selBox = null; | |
| 996 | - @ selRow = null; | |
| 825 | + @ function miLineY(p){ | |
| 826 | + @ return p.y + node.h - mLine.w - 1; | |
| 827 | + @ } | |
| 828 | + @ function drawLine(elem,color,x0,y0,x1,y1){ | |
| 829 | + @ var cls = elem.cls + " "; | |
| 830 | + @ if( x1===null ){ | |
| 831 | + @ x1 = x0+elem.w; | |
| 832 | + @ cls += "v"; | |
| 833 | + @ }else{ | |
| 834 | + @ y1 = y0+elem.w; | |
| 835 | + @ cls += "h"; | |
| 836 | + @ } | |
| 837 | + @ drawBox(cls,color,x0,y0,x1,y1); | |
| 838 | + @ } | |
| 839 | + @ function drawUpArrow(from,to,color){ | |
| 840 | + @ var y = to.y + node.h; | |
| 841 | + @ var arrowSpace = from.y - y + (!from.id || from.r!=to.r ? node.h/2 : 0); | |
| 842 | + @ var arw = arrowSpace < arrow.h*1.5 ? arrowSmall : arrow; | |
| 843 | + @ var x = to.x + (node.w-line.w)/2; | |
| 844 | + @ var y0 = from.y + node.h/2; | |
| 845 | + @ var y1 = Math.ceil(to.y + node.h + arw.h/2); | |
| 846 | + @ drawLine(line,color,x,y0,null,y1); | |
| 847 | + @ x = to.x + (node.w-arw.w)/2; | |
| 848 | + @ var n = drawBox(arw.cls,null,x,y); | |
| 849 | + @ n.style.borderBottomColor = color; | |
| 850 | + @ } | |
| 851 | + @ function drawMergeLine(x0,y0,x1,y1){ | |
| 852 | + @ drawLine(mLine,null,x0,y0,x1,y1); | |
| 853 | + @ } | |
| 854 | + @ function drawMergeArrow(p,rail){ | |
| 855 | + @ var x0 = rail*railPitch + node.w/2; | |
| 856 | + @ if( rail in mergeLines ){ | |
| 857 | + @ x0 += mergeLines[rail]; | |
| 858 | + @ if( p.r<rail ) x0 += mLine.w; | |
| 859 | + @ }else{ | |
| 860 | + @ x0 += (p.r<rail ? -1 : 1)*line.w/2; | |
| 861 | + @ } | |
| 862 | + @ var x1 = mArrow.w ? mArrow.w/2 : -node.w/2; | |
| 863 | + @ x1 = p.x + (p.r<rail ? node.w + Math.ceil(x1) : -x1); | |
| 864 | + @ var y = miLineY(p); | |
| 865 | + @ drawMergeLine(x0,y,x1,null); | |
| 866 | + @ var x = p.x + (p.r<rail ? node.w : -mArrow.w); | |
| 867 | + @ var cls = "arrow merge " + (p.r<rail ? "l" : "r"); | |
| 868 | + @ drawBox(cls,null,x,y+(mLine.w-mArrow.h)/2); | |
| 869 | + @ } | |
| 870 | + @ function drawNode(p, btm){ | |
| 871 | + @ if( p.u>0 ) drawUpArrow(p,rowinfo[p.u-1],p.fg); | |
| 872 | + @ var cls = node.cls; | |
| 873 | + @ if( p.mi.length ) cls += " merge"; | |
| 874 | + @ if( p.f&1 ) cls += " leaf"; | |
| 875 | + @ var n = drawBox(cls,p.bg,p.x,p.y); | |
| 876 | + @ n.id = "tln"+p.id; | |
| 877 | + @ n.onclick = clickOnNode; | |
| 878 | + @ n.style.zIndex = 10; | |
| 879 | + if( !omitDescenders ){ | |
| 880 | + @ if( p.u==0 ) drawUpArrow(p,{x: p.x, y: -node.h},p.fg); | |
| 881 | + @ if( p.d ) drawUpArrow({x: p.x, y: btm-node.h/2},p,p.fg); | |
| 882 | + } | |
| 883 | + @ if( p.mo>=0 ){ | |
| 884 | + @ var x0 = p.x + node.w/2; | |
| 885 | + @ var x1 = p.mo*railPitch + node.w/2; | |
| 886 | + @ var u = rowinfo[p.mu-1]; | |
| 887 | + @ var y1 = miLineY(u); | |
| 888 | + @ if( p.u<0 || p.mo!=p.r ){ | |
| 889 | + @ x1 += mergeLines[p.mo] = -mLine.w/2; | |
| 890 | + @ var y0 = p.y+2; | |
| 891 | + @ if( p.r!=p.mo ) drawMergeLine(x0,y0,x1+(x0<x1 ? mLine.w : 0),null); | |
| 892 | + @ drawMergeLine(x1,y0+mLine.w,null,y1); | |
| 893 | + @ }else if( mergeOffset ){ | |
| 894 | + @ mergeLines[p.mo] = u.r<p.r ? -mergeOffset-mLine.w : mergeOffset; | |
| 895 | + @ x1 += mergeLines[p.mo]; | |
| 896 | + @ drawMergeLine(x1,p.y+node.h/2,null,y1); | |
| 897 | + @ }else{ | |
| 898 | + @ delete mergeLines[p.mo]; | |
| 899 | + @ } | |
| 900 | + @ } | |
| 901 | + @ for( var i=0; i<p.au.length; i+=2 ){ | |
| 902 | + @ var rail = p.au[i]; | |
| 903 | + @ var x0 = p.x + node.w/2; | |
| 904 | + @ var x1 = rail*railPitch + (node.w-line.w)/2; | |
| 905 | + @ if( x0<x1 ){ | |
| 906 | + @ x0 = Math.ceil(x0); | |
| 907 | + @ x1 += line.w; | |
| 908 | + @ } | |
| 909 | + @ var y0 = p.y + (node.h-line.w)/2; | |
| 910 | + @ var u = rowinfo[p.au[i+1]-1]; | |
| 911 | + @ if( u.id<p.id ){ | |
| 912 | + @ drawLine(line,u.fg,x0,y0,x1,null); | |
| 913 | + @ drawUpArrow(p,u,u.fg); | |
| 914 | + @ }else{ | |
| 915 | + @ var y1 = u.y + (node.h-line.w)/2; | |
| 916 | + @ drawLine(wLine,u.fg,x0,y0,x1,null); | |
| 917 | + @ drawLine(wLine,u.fg,x1-line.w,y0,null,y1+line.w); | |
| 918 | + @ drawLine(wLine,u.fg,x1,y1,u.x-wArrow.w/2,null); | |
| 919 | + @ var x = u.x-wArrow.w; | |
| 920 | + @ var y = u.y+(node.h-wArrow.h)/2; | |
| 921 | + @ var n = drawBox(wArrow.cls,null,x,y); | |
| 922 | + @ if( u.fg ) n.style.borderLeftColor = u.fg; | |
| 923 | + @ } | |
| 924 | + @ } | |
| 925 | + @ for( var i=0; i<p.mi.length; i++ ){ | |
| 926 | + @ var rail = p.mi[i]; | |
| 927 | + @ if( rail<0 ){ | |
| 928 | + @ rail = -rail; | |
| 929 | + @ mergeLines[rail] = -mLine.w/2; | |
| 930 | + @ var x = rail*railPitch + (node.w-mLine.w)/2; | |
| 931 | + @ drawMergeLine(x,miLineY(p),null,btm); | |
| 932 | + @ } | |
| 933 | + @ drawMergeArrow(p,rail); | |
| 934 | + @ } | |
| 935 | + @ } | |
| 936 | + @ var mergeLines; | |
| 937 | + @ function renderGraph(){ | |
| 938 | + @ mergeLines = {}; | |
| 939 | + @ canvasDiv.innerHTML = ""; | |
| 940 | + @ var canvasY = absoluteY(canvasDiv); | |
| 941 | + @ for( var i=0; i<rowinfo.length; i++ ){ | |
| 942 | + @ rowinfo[i].y = absoluteY(gebi("m"+rowinfo[i].id)) - canvasY; | |
| 943 | + @ rowinfo[i].x = rowinfo[i].r*railPitch; | |
| 944 | + @ } | |
| 945 | + @ var tlBtm = document.querySelector(".timelineBottom"); | |
| 946 | + @ if( tlBtm.offsetHeight<node.h ){ | |
| 947 | + @ tlBtm.style.height = node.h + "px"; | |
| 948 | + @ } | |
| 949 | + @ var btm = absoluteY(tlBtm) - canvasY + tlBtm.offsetHeight; | |
| 950 | + @ for( var i=rowinfo.length-1; i>=0; i-- ){ | |
| 951 | + @ drawNode(rowinfo[i], btm); | |
| 952 | + @ } | |
| 953 | + @ } | |
| 954 | + @ var selRow; | |
| 955 | + @ function clickOnNode(){ | |
| 956 | + @ var p = rowinfo[parseInt(this.id.match(/\d+$/)[0], 10)-1]; | |
| 957 | + @ if( !selRow ){ | |
| 958 | + @ selRow = p; | |
| 959 | + @ this.className += " sel"; | |
| 960 | + @ canvasDiv.className += " sel"; | |
| 961 | + @ }else if( selRow==p ){ | |
| 962 | + @ selRow = null; | |
| 963 | + @ this.className = this.className.replace(" sel", ""); | |
| 964 | + @ canvasDiv.className = canvasDiv.className.replace(" sel", ""); | |
| 997 | 965 | @ }else{ |
| 998 | 966 | if( fileDiff ){ |
| 999 | 967 | @ location.href="%R/fdiff?v1="+selRow.h+"&v2="+p.h+"&sbs=1"; |
| 1000 | 968 | }else{ |
| 1001 | 969 | if( db_get_boolean("show-version-diffs", 0)==0 ){ |
| @@ -1004,22 +972,23 @@ | ||
| 1004 | 972 | @ location.href="%R/vdiff?from="+selRow.h+"&to="+p.h+"&sbs=1"; |
| 1005 | 973 | } |
| 1006 | 974 | } |
| 1007 | 975 | @ } |
| 1008 | 976 | @ } |
| 1009 | - @ var lastId = "m"+rowinfo[rowinfo.length-1].id; | |
| 977 | + @ var lastRow = gebi("m"+rowinfo[rowinfo.length-1].id); | |
| 1010 | 978 | @ var lastY = 0; |
| 1011 | 979 | @ function checkHeight(){ |
| 1012 | - @ var h = absoluteY(lastId); | |
| 980 | + @ var h = absoluteY(lastRow); | |
| 1013 | 981 | @ if( h!=lastY ){ |
| 1014 | 982 | @ renderGraph(); |
| 1015 | 983 | @ lastY = h; |
| 1016 | 984 | @ } |
| 1017 | - @ setTimeout("checkHeight();", 1000); | |
| 985 | + @ setTimeout(checkHeight, 1000); | |
| 1018 | 986 | @ } |
| 987 | + @ initGraph(); | |
| 1019 | 988 | @ checkHeight(); |
| 1020 | - @ </script> | |
| 989 | + @ }())</script> | |
| 1021 | 990 | } |
| 1022 | 991 | } |
| 1023 | 992 | |
| 1024 | 993 | /* |
| 1025 | 994 | ** Create a temporary table suitable for storing timeline data. |
| @@ -1308,24 +1277,24 @@ | ||
| 1308 | 1277 | return; |
| 1309 | 1278 | } |
| 1310 | 1279 | url_initialize(&url, "timeline"); |
| 1311 | 1280 | cgi_query_parameters_to_url(&url); |
| 1312 | 1281 | if( zTagName && g.perm.Read ){ |
| 1313 | - tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", zTagName); | |
| 1282 | + tagid = db_int(-1,"SELECT tagid FROM tag WHERE tagname='sym-%q'",zTagName); | |
| 1314 | 1283 | zThisTag = zTagName; |
| 1315 | 1284 | }else if( zBrName && g.perm.Read ){ |
| 1316 | - tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'",zBrName); | |
| 1285 | + tagid = db_int(-1,"SELECT tagid FROM tag WHERE tagname='sym-%q'",zBrName); | |
| 1317 | 1286 | zThisTag = zBrName; |
| 1318 | 1287 | }else{ |
| 1319 | 1288 | tagid = 0; |
| 1320 | 1289 | } |
| 1321 | 1290 | if( zMark && zMark[0]==0 ){ |
| 1322 | 1291 | if( zAfter ) zMark = zAfter; |
| 1323 | 1292 | if( zBefore ) zMark = zBefore; |
| 1324 | 1293 | if( zCirca ) zMark = zCirca; |
| 1325 | 1294 | } |
| 1326 | - if( tagid>0 | |
| 1295 | + if( tagid | |
| 1327 | 1296 | && db_int(0,"SELECT count(*) FROM tagxref WHERE tagid=%d",tagid)<=nEntry |
| 1328 | 1297 | ){ |
| 1329 | 1298 | nEntry = -1; |
| 1330 | 1299 | zCirca = 0; |
| 1331 | 1300 | } |
| @@ -1524,11 +1493,11 @@ | ||
| 1524 | 1493 | } |
| 1525 | 1494 | else if( zYearWeek ){ |
| 1526 | 1495 | blob_append_sql(&sql, " AND %Q=strftime('%%Y-%%W',event.mtime) ", |
| 1527 | 1496 | zYearWeek); |
| 1528 | 1497 | } |
| 1529 | - if( tagid>0 ){ | |
| 1498 | + if( tagid ){ | |
| 1530 | 1499 | blob_append_sql(&sql, |
| 1531 | 1500 | " AND (EXISTS(SELECT 1 FROM tagxref" |
| 1532 | 1501 | " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)\n", tagid); |
| 1533 | 1502 | |
| 1534 | 1503 | if( zBrName ){ |
| 1535 | 1504 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -241,23 +241,17 @@ | |
| 241 | dateFormat = db_get_int("timeline-date-format", 0); |
| 242 | zDateFmt = P("datefmt"); |
| 243 | if( zDateFmt ) dateFormat = atoi(zDateFmt); |
| 244 | if( tmFlags & TIMELINE_GRAPH ){ |
| 245 | pGraph = graph_init(); |
| 246 | /* style is not moved to css, because this is |
| 247 | ** a technical div for the timeline graph |
| 248 | */ |
| 249 | @ <div id="canvas" style="position:relative;height:0px;width:0px;" |
| 250 | @ onclick="clickOnGraph(event)"></div> |
| 251 | } |
| 252 | db_static_prepare(&qbranch, |
| 253 | "SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0 AND rid=:rid", |
| 254 | TAG_BRANCH |
| 255 | ); |
| 256 | |
| 257 | @ <table id="timelineTable" class="timelineTable" |
| 258 | @ onclick="clickOnGraph(event)"> |
| 259 | blob_zero(&comment); |
| 260 | while( db_step(pQuery)==SQLITE_ROW ){ |
| 261 | int rid = db_column_int(pQuery, 0); |
| 262 | const char *zUuid = db_column_text(pQuery, 1); |
| 263 | int isLeaf = db_column_int(pQuery, 5); |
| @@ -391,11 +385,11 @@ | |
| 391 | } |
| 392 | db_reset(&qparent); |
| 393 | gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr, |
| 394 | zUuid, isLeaf); |
| 395 | db_reset(&qbranch); |
| 396 | @ <div id="m%d(gidx)"></div> |
| 397 | } |
| 398 | @</td> |
| 399 | if( zBgClr && zBgClr[0] && rid!=selectedRid ){ |
| 400 | @ <td class="timelineTableCell" style="background-color: %h(zBgClr);"> |
| 401 | }else{ |
| @@ -589,18 +583,11 @@ | |
| 589 | graph_finish(pGraph, (tmFlags & TIMELINE_DISJOINT)!=0); |
| 590 | if( pGraph->nErr ){ |
| 591 | graph_free(pGraph); |
| 592 | pGraph = 0; |
| 593 | }else{ |
| 594 | int w; |
| 595 | /* style is not moved to css, because this is |
| 596 | ** a technical div for the timeline graph |
| 597 | */ |
| 598 | w = pGraph->mxRail*pGraph->iRailPitch + 28; |
| 599 | @ <tr class="timelineBottom"><td></td><td> |
| 600 | @ <div id="grbtm" style="width:%d(w)px;"></div> |
| 601 | @ </td><td></td></tr> |
| 602 | } |
| 603 | } |
| 604 | @ </table> |
| 605 | if( fchngQueryInit ) db_finalize(&fchngQuery); |
| 606 | timeline_output_graph_javascript(pGraph, (tmFlags & TIMELINE_DISJOINT)!=0, 0); |
| @@ -648,31 +635,34 @@ | |
| 648 | ){ |
| 649 | if( pGraph && pGraph->nErr==0 && pGraph->nRow>0 ){ |
| 650 | GraphRow *pRow; |
| 651 | int i; |
| 652 | char cSep; |
| 653 | int mergeOffset; /* Pixel offset from rail to merge riser */ |
| 654 | int iRailPitch; /* Pixels between consecutive rails */ |
| 655 | int showArrowheads; /* True to draw arrowheads. False to omit. */ |
| 656 | int circleNodes; /* True for circle nodes. False for square nodes */ |
| 657 | int colorGraph; /* Use colors for graph lines */ |
| 658 | |
| 659 | iRailPitch = pGraph->iRailPitch; |
| 660 | showArrowheads = skin_detail_boolean("timeline-arrowheads"); |
| 661 | circleNodes = skin_detail_boolean("timeline-circle-nodes"); |
| 662 | colorGraph = skin_detail_boolean("timeline-color-graph-lines"); |
| 663 | |
| 664 | /* Number of pixels that the thin merge lines are offset from the |
| 665 | ** the center of the think rail lines. If zero, then the vertical |
| 666 | ** merge lines overlap with the thicker rail lines. |
| 667 | */ |
| 668 | mergeOffset = iRailPitch>=14 ? 4 : iRailPitch>=13 ? 3 : 0; |
| 669 | if( PB("nomo") ) mergeOffset = 0; |
| 670 | |
| 671 | @ <script> |
| 672 | @ var railPitch=%d(iRailPitch); |
| 673 | |
| 674 | /* the rowinfo[] array contains all the information needed to generate |
| 675 | ** the graph. Each entry contains information for a single row: |
| 676 | ** |
| 677 | ** id: The id of the <div> element for the row. This is an integer. |
| 678 | ** to get an actual id, prepend "m" to the integer. The top node |
| @@ -680,13 +670,13 @@ | |
| 680 | ** bg: The background color for this row |
| 681 | ** r: The "rail" that the node for this row sits on. The left-most |
| 682 | ** rail is 0 and the number increases to the right. |
| 683 | ** d: True if there is a "descender" - an arrow coming from the bottom |
| 684 | ** of the page straight up to this node. |
| 685 | ** mo: "merge-out". If non-zero, this is one more than the x-coordinate |
| 686 | ** for the upward portion of a merge arrow. The merge arrow goes up |
| 687 | ** to the row identified by mu:. If this value is zero then |
| 688 | ** node has no merge children and no merge-out line is drawn. |
| 689 | ** mu: The id of the row which is the top of the merge-out arrow. |
| 690 | ** u: Draw a thick child-line out of the top of this node and up to |
| 691 | ** the node with an id equal to this value. 0 if it is straight to |
| 692 | ** the top of the page, -1 if there is no thick-line riser. |
| @@ -693,37 +683,25 @@ | |
| 693 | ** f: 0x01: a leaf node. |
| 694 | ** au: An array of integers that define thick-line risers for branches. |
| 695 | ** The integers are in pairs. For each pair, the first integer is |
| 696 | ** is the rail on which the riser should run and the second integer |
| 697 | ** is the id of the node upto which the riser should run. |
| 698 | ** mi: "merge-in". An array of integer x-coordinates from which |
| 699 | ** merge arrows should be drawn into this node. If the value is |
| 700 | ** negative, then the x-coordinate is the absolute value of mi[] |
| 701 | ** and a thin merge-arrow descender is drawn to the bottom of |
| 702 | ** the screen. |
| 703 | ** h: The SHA1 hash of the object being graphed |
| 704 | */ |
| 705 | cgi_printf("var rowinfo = [\n"); |
| 706 | for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){ |
| 707 | int mo = pRow->mergeOut; |
| 708 | if( mo<0 ){ |
| 709 | mo = 0; |
| 710 | }else{ |
| 711 | int x = (mo/4)*iRailPitch; |
| 712 | switch( mo&3 ){ |
| 713 | case 0: x -= mergeOffset-2; break; |
| 714 | case 1: x += 1; break; |
| 715 | case 2: x += mergeOffset+1; break; |
| 716 | } |
| 717 | mo = x; |
| 718 | } |
| 719 | cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,u:%d,f:%d,au:", |
| 720 | pRow->idx, /* id */ |
| 721 | pRow->zBgClr, /* bg */ |
| 722 | pRow->iRail, /* r */ |
| 723 | pRow->bDescender, /* d */ |
| 724 | mo, /* mo */ |
| 725 | pRow->mergeUpto, /* mu */ |
| 726 | pRow->aiRiser[pRow->iRail], /* u */ |
| 727 | pRow->isLeaf ? 1 : 0 /* f */ |
| 728 | ); |
| 729 | /* u */ |
| @@ -743,13 +721,11 @@ | |
| 743 | /* mi */ |
| 744 | cgi_printf("mi:"); |
| 745 | cSep = '['; |
| 746 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 747 | if( pRow->mergeIn[i] ){ |
| 748 | int mi = i*iRailPitch; |
| 749 | if( pRow->mergeIn[i]==1 ) mi -= mergeOffset-1; |
| 750 | if( pRow->mergeIn[i]==3 ) mi += mergeOffset; |
| 751 | if( pRow->mergeDown & (1<<i) ) mi = -mi; |
| 752 | cgi_printf("%c%d", cSep, mi); |
| 753 | cSep = ','; |
| 754 | } |
| 755 | } |
| @@ -756,246 +732,238 @@ | |
| 756 | if( cSep=='[' ) cgi_printf("["); |
| 757 | cgi_printf("],h:\"%s\"}%s", pRow->zUuid, pRow->pNext ? ",\n" : "];\n"); |
| 758 | } |
| 759 | cgi_printf("var nrail = %d\n", pGraph->mxRail+1); |
| 760 | graph_free(pGraph); |
| 761 | @ var cDiv = gebi("canvas"); |
| 762 | @ var csty = window.getComputedStyle && window.getComputedStyle(cDiv,null); |
| 763 | @ var lineClr = (csty && csty.getPropertyValue('color')) || 'black'; |
| 764 | @ var bgClr = (csty && csty.getPropertyValue('background-color')) ||'white'; |
| 765 | @ if( bgClr=='transparent' ) bgClr = 'white'; |
| 766 | @ var boxColor = lineClr; |
| 767 | @ function drawBox(color,x0,y0,x1,y1){ |
| 768 | @ var n = document.createElement("div"); |
| 769 | @ if( x0>x1 ){ var t=x0; x0=x1; x1=t; } |
| 770 | @ if( y0>y1 ){ var t=y0; y0=y1; y1=t; } |
| 771 | @ var w = x1-x0+1; |
| 772 | @ var h = y1-y0+1; |
| 773 | @ n.style.position = "absolute"; |
| 774 | @ n.style.overflow = "hidden"; |
| 775 | @ n.style.left = x0+"px"; |
| 776 | @ n.style.top = y0+"px"; |
| 777 | @ n.style.width = w+"px"; |
| 778 | @ n.style.height = h+"px"; |
| 779 | @ n.style.backgroundColor = color; |
| 780 | @ cDiv.appendChild(n); |
| 781 | @ return n; |
| 782 | @ } |
| 783 | @ function absoluteY(id){ |
| 784 | @ var obj = gebi(id); |
| 785 | @ if( !obj ) return; |
| 786 | @ var top = 0; |
| 787 | @ if( obj.offsetParent ){ |
| 788 | @ do{ |
| 789 | @ top += obj.offsetTop; |
| 790 | @ }while( obj = obj.offsetParent ); |
| 791 | @ } |
| 792 | @ return top; |
| 793 | @ } |
| 794 | @ function absoluteX(id){ |
| 795 | @ var obj = gebi(id); |
| 796 | @ if( !obj ) return; |
| 797 | @ var left = 0; |
| 798 | @ if( obj.offsetParent ){ |
| 799 | @ do{ |
| 800 | @ left += obj.offsetLeft; |
| 801 | @ }while( obj = obj.offsetParent ); |
| 802 | @ } |
| 803 | @ return left; |
| 804 | @ } |
| 805 | if( showArrowheads ){ |
| 806 | @ function drawUpArrow(x,y0,y1,clr){ |
| 807 | @ drawBox(clr,x,y0+4,x+1,y1); |
| 808 | @ var n = document.createElement("div"), |
| 809 | @ l = x-2, |
| 810 | @ t = y0; |
| 811 | @ n.style.position = "absolute"; |
| 812 | @ n.style.left = l+"px"; |
| 813 | @ n.style.top = t+"px"; |
| 814 | @ n.style.width = 0; |
| 815 | @ n.style.height = 0; |
| 816 | @ n.style.transform = "scale(.999)"; |
| 817 | @ n.style.borderWidth = 0; |
| 818 | @ n.style.borderStyle = "solid"; |
| 819 | @ n.style.borderColor = "transparent"; |
| 820 | @ n.style.borderRightWidth = "3px"; |
| 821 | @ n.style.borderBottomColor = clr; |
| 822 | @ n.style.borderLeftWidth = "3px"; |
| 823 | @ if( y0+10>=y1 ){ |
| 824 | @ n.style.borderBottomWidth = "5px"; |
| 825 | @ } else { |
| 826 | @ n.style.borderBottomWidth = "7px"; |
| 827 | @ } |
| 828 | @ cDiv.appendChild(n); |
| 829 | @ } |
| 830 | }else{ |
| 831 | @ function drawUpArrow(x,y0,y1,clr){ |
| 832 | @ drawBox(clr,x,y0+1,x+1,y1); |
| 833 | @ } |
| 834 | } |
| 835 | @ function drawThinArrow(y,xFrom,xTo){ |
| 836 | @ var n = document.createElement("div"), |
| 837 | @ t = y-2; |
| 838 | @ n.style.position = "absolute"; |
| 839 | @ n.style.top = t+"px"; |
| 840 | @ n.style.width = 0; |
| 841 | @ n.style.height = "1px"; |
| 842 | @ n.style.transform = "scale(.999)"; |
| 843 | @ n.style.borderWidth = 0; |
| 844 | @ n.style.borderStyle = "solid"; |
| 845 | @ n.style.borderColor = "transparent"; |
| 846 | @ n.style.borderTopWidth = "2px"; |
| 847 | @ n.style.borderBottomWidth = "2px"; |
| 848 | @ if( xFrom<xTo ){ |
| 849 | @ drawBox(lineClr,xFrom,y,xTo-3,y); |
| 850 | @ n.style.left = xTo-3+"px"; |
| 851 | @ n.style.borderLeftWidth = "3px"; |
| 852 | @ n.style.borderLeftColor = lineClr; |
| 853 | @ }else{ |
| 854 | @ drawBox(lineClr,xTo+3,y,xFrom,y); |
| 855 | @ n.style.left = xTo+1+"px"; |
| 856 | @ n.style.borderRightWidth = "3px"; |
| 857 | @ n.style.borderRightColor = lineClr; |
| 858 | @ } |
| 859 | @ cDiv.appendChild(n); |
| 860 | @ } |
| 861 | @ function drawThinLine(x0,y0,x1,y1){ |
| 862 | @ drawBox(lineClr,x0,y0,x1,y1); |
| 863 | @ } |
| 864 | @ function drawNodeBox(color,x0,y0,x1,y1){ |
| 865 | @ var n = drawBox(color,x0,y0,x1,y1); |
| 866 | @ n.style.cursor = "pointer"; |
| 867 | if( circleNodes ){ |
| 868 | @ n.style.borderRadius = "6px"; |
| 869 | } |
| 870 | @ } |
| 871 | @ function drawNode(p, left, btm){ |
| 872 | @ drawNodeBox(boxColor,p.x-5,p.y-5,p.x+6,p.y+6); |
| 873 | @ drawNodeBox(p.bg||bgClr,p.x-4,p.y-4,p.x+5,p.y+5); |
| 874 | @ if( p.u>0 ) drawUpArrow(p.x,rowinfo[p.u-1].y+6,p.y-6,p.fg||lineClr); |
| 875 | @ if( p.f&1 ) drawNodeBox(boxColor,p.x-1,p.y-1,p.x+2,p.y+2); |
| 876 | if( !omitDescenders ){ |
| 877 | @ if( p.u==0 ) drawUpArrow(p.x,0,p.y-6,p.fg||lineClr); |
| 878 | @ if( p.d ) drawUpArrow(p.x,p.y+6,btm,p.fg||lineClr); |
| 879 | } |
| 880 | @ if( p.mo>0 ){ |
| 881 | @ var x1 = p.mo + left - 1; |
| 882 | @ var y1 = p.y-3; |
| 883 | @ var x0 = x1>p.x ? p.x+7 : p.x-6; |
| 884 | @ var u = rowinfo[p.mu-1]; |
| 885 | @ var y0 = u.y+5; |
| 886 | @ if( x1>=p.x-5 && x1<=p.x+5 ){ |
| 887 | @ y1 = p.y-5; |
| 888 | @ }else{ |
| 889 | @ drawThinLine(x0,y1,x1,y1); |
| 890 | @ } |
| 891 | if( mergeOffset==0 ) cgi_printf("if( p.mo!=p.u-1 ) "); |
| 892 | @ drawThinLine(x1,y0,x1,y1); |
| 893 | @ } |
| 894 | @ var n = p.au.length; |
| 895 | @ for(var i=0; i<n; i+=2){ |
| 896 | @ var x1 = p.au[i]*railPitch + left; |
| 897 | @ var x0 = x1>p.x ? p.x+7 : p.x-6; |
| 898 | @ var u = rowinfo[p.au[i+1]-1]; |
| 899 | @ if(u.id<p.id){ |
| 900 | @ drawBox(u.fg||lineClr,x0,p.y,x1+1,p.y+1); |
| 901 | @ drawUpArrow(x1,u.y+6,p.y,u.fg||lineClr); |
| 902 | @ }else{ |
| 903 | @ drawBox("#600000",x0,p.y,x1,p.y+1); |
| 904 | @ drawBox("#600000",x1-1,p.y,x1,u.y+1); |
| 905 | @ drawBox("#600000",x1,u.y,u.x-10,u.y+1); |
| 906 | @ var n = document.createElement("div"), |
| 907 | @ t = u.y-2, |
| 908 | @ l = u.x-11; |
| 909 | @ n.style.position = "absolute"; |
| 910 | @ n.style.top = t+"px"; |
| 911 | @ n.style.left = l+"px"; |
| 912 | @ n.style.width = 0; |
| 913 | @ n.style.height = 0; |
| 914 | @ n.style.transform = "scale(.999)"; |
| 915 | @ n.style.borderWidth = 0; |
| 916 | @ n.style.borderStyle = "solid"; |
| 917 | @ n.style.borderColor = "transparent"; |
| 918 | @ n.style.borderTopWidth = "3px"; |
| 919 | @ n.style.borderBottomWidth = "3px"; |
| 920 | @ n.style.borderLeftWidth = "7px"; |
| 921 | @ n.style.borderLeftColor = "#600000"; |
| 922 | @ cDiv.appendChild(n); |
| 923 | @ } |
| 924 | @ } |
| 925 | @ for(var j in p.mi){ |
| 926 | @ var y0 = p.y+5; |
| 927 | @ var mx = p.mi[j]; |
| 928 | @ if( mx<0 ){ |
| 929 | @ mx = left-mx; |
| 930 | @ drawThinLine(mx,y0,mx,btm); |
| 931 | @ }else{ |
| 932 | @ mx += left; |
| 933 | @ } |
| 934 | @ if( mx>p.x ){ |
| 935 | @ drawThinArrow(y0,mx,p.x+6); |
| 936 | @ }else{ |
| 937 | @ drawThinArrow(y0,mx,p.x-5); |
| 938 | @ } |
| 939 | @ } |
| 940 | @ } |
| 941 | @ var selBox = null; |
| 942 | @ var selRow = null; |
| 943 | @ function renderGraph(){ |
| 944 | @ var canvasDiv = gebi("canvas"); |
| 945 | @ while( canvasDiv.hasChildNodes() ){ |
| 946 | @ canvasDiv.removeChild(canvasDiv.firstChild); |
| 947 | @ } |
| 948 | @ var canvasY = absoluteY("timelineTable"); |
| 949 | @ var left = absoluteX("m"+rowinfo[0].id) - absoluteX("canvas") + 15; |
| 950 | @ for(var i in rowinfo){ |
| 951 | @ rowinfo[i].y = absoluteY("m"+rowinfo[i].id) + 10 - canvasY; |
| 952 | @ rowinfo[i].x = left + rowinfo[i].r*railPitch; |
| 953 | @ } |
| 954 | @ var btm = absoluteY("grbtm") + 10 - canvasY; |
| 955 | @ for(var i in rowinfo){ |
| 956 | @ drawNode(rowinfo[i], left, btm); |
| 957 | @ } |
| 958 | @ if( selRow!=null ) clickOnRow(selRow); |
| 959 | @ } |
| 960 | @ function clickOnGraph(event){ |
| 961 | @ var x=event.clientX-absoluteX("canvas"); |
| 962 | @ var y=event.clientY-absoluteY("canvas"); |
| 963 | @ if(window.pageXOffset!=null){ |
| 964 | @ x += window.pageXOffset; |
| 965 | @ y += window.pageYOffset; |
| 966 | @ }else{ |
| 967 | @ var d = window.document.documentElement; |
| 968 | @ if(document.compatMode!="CSS1Compat") d = d.body; |
| 969 | @ x += d.scrollLeft; |
| 970 | @ y += d.scrollTop; |
| 971 | @ } |
| 972 | if( P("clicktest")!=0 ){ |
| 973 | @ alert("click at "+x+","+y) |
| 974 | } |
| 975 | @ for(var i in rowinfo){ |
| 976 | @ p = rowinfo[i]; |
| 977 | @ if( p.y<y-11 ) continue; |
| 978 | @ if( p.y>y+9 ) break; |
| 979 | @ if( p.x>x-11 && p.x<x+9 ){ |
| 980 | @ clickOnRow(p); |
| 981 | @ break; |
| 982 | @ } |
| 983 | @ } |
| 984 | @ } |
| 985 | @ function clickOnRow(p){ |
| 986 | @ if( selRow==null ){ |
| 987 | @ selBox = drawBox("red",p.x-2,p.y-2,p.x+3,p.y+3); |
| 988 | if( circleNodes ){ |
| 989 | @ selBox.style.borderRadius="6px"; |
| 990 | } |
| 991 | @ selRow = p; |
| 992 | @ }else if( selRow==p ){ |
| 993 | @ var canvasDiv = gebi("canvas"); |
| 994 | @ canvasDiv.removeChild(selBox); |
| 995 | @ selBox = null; |
| 996 | @ selRow = null; |
| 997 | @ }else{ |
| 998 | if( fileDiff ){ |
| 999 | @ location.href="%R/fdiff?v1="+selRow.h+"&v2="+p.h+"&sbs=1"; |
| 1000 | }else{ |
| 1001 | if( db_get_boolean("show-version-diffs", 0)==0 ){ |
| @@ -1004,22 +972,23 @@ | |
| 1004 | @ location.href="%R/vdiff?from="+selRow.h+"&to="+p.h+"&sbs=1"; |
| 1005 | } |
| 1006 | } |
| 1007 | @ } |
| 1008 | @ } |
| 1009 | @ var lastId = "m"+rowinfo[rowinfo.length-1].id; |
| 1010 | @ var lastY = 0; |
| 1011 | @ function checkHeight(){ |
| 1012 | @ var h = absoluteY(lastId); |
| 1013 | @ if( h!=lastY ){ |
| 1014 | @ renderGraph(); |
| 1015 | @ lastY = h; |
| 1016 | @ } |
| 1017 | @ setTimeout("checkHeight();", 1000); |
| 1018 | @ } |
| 1019 | @ checkHeight(); |
| 1020 | @ </script> |
| 1021 | } |
| 1022 | } |
| 1023 | |
| 1024 | /* |
| 1025 | ** Create a temporary table suitable for storing timeline data. |
| @@ -1308,24 +1277,24 @@ | |
| 1308 | return; |
| 1309 | } |
| 1310 | url_initialize(&url, "timeline"); |
| 1311 | cgi_query_parameters_to_url(&url); |
| 1312 | if( zTagName && g.perm.Read ){ |
| 1313 | tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", zTagName); |
| 1314 | zThisTag = zTagName; |
| 1315 | }else if( zBrName && g.perm.Read ){ |
| 1316 | tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'",zBrName); |
| 1317 | zThisTag = zBrName; |
| 1318 | }else{ |
| 1319 | tagid = 0; |
| 1320 | } |
| 1321 | if( zMark && zMark[0]==0 ){ |
| 1322 | if( zAfter ) zMark = zAfter; |
| 1323 | if( zBefore ) zMark = zBefore; |
| 1324 | if( zCirca ) zMark = zCirca; |
| 1325 | } |
| 1326 | if( tagid>0 |
| 1327 | && db_int(0,"SELECT count(*) FROM tagxref WHERE tagid=%d",tagid)<=nEntry |
| 1328 | ){ |
| 1329 | nEntry = -1; |
| 1330 | zCirca = 0; |
| 1331 | } |
| @@ -1524,11 +1493,11 @@ | |
| 1524 | } |
| 1525 | else if( zYearWeek ){ |
| 1526 | blob_append_sql(&sql, " AND %Q=strftime('%%Y-%%W',event.mtime) ", |
| 1527 | zYearWeek); |
| 1528 | } |
| 1529 | if( tagid>0 ){ |
| 1530 | blob_append_sql(&sql, |
| 1531 | " AND (EXISTS(SELECT 1 FROM tagxref" |
| 1532 | " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)\n", tagid); |
| 1533 | |
| 1534 | if( zBrName ){ |
| 1535 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -241,23 +241,17 @@ | |
| 241 | dateFormat = db_get_int("timeline-date-format", 0); |
| 242 | zDateFmt = P("datefmt"); |
| 243 | if( zDateFmt ) dateFormat = atoi(zDateFmt); |
| 244 | if( tmFlags & TIMELINE_GRAPH ){ |
| 245 | pGraph = graph_init(); |
| 246 | } |
| 247 | db_static_prepare(&qbranch, |
| 248 | "SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0 AND rid=:rid", |
| 249 | TAG_BRANCH |
| 250 | ); |
| 251 | |
| 252 | @ <table id="timelineTable" class="timelineTable"> |
| 253 | blob_zero(&comment); |
| 254 | while( db_step(pQuery)==SQLITE_ROW ){ |
| 255 | int rid = db_column_int(pQuery, 0); |
| 256 | const char *zUuid = db_column_text(pQuery, 1); |
| 257 | int isLeaf = db_column_int(pQuery, 5); |
| @@ -391,11 +385,11 @@ | |
| 385 | } |
| 386 | db_reset(&qparent); |
| 387 | gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr, |
| 388 | zUuid, isLeaf); |
| 389 | db_reset(&qbranch); |
| 390 | @ <div id="m%d(gidx)" class="tl-nodemark"></div> |
| 391 | } |
| 392 | @</td> |
| 393 | if( zBgClr && zBgClr[0] && rid!=selectedRid ){ |
| 394 | @ <td class="timelineTableCell" style="background-color: %h(zBgClr);"> |
| 395 | }else{ |
| @@ -589,18 +583,11 @@ | |
| 583 | graph_finish(pGraph, (tmFlags & TIMELINE_DISJOINT)!=0); |
| 584 | if( pGraph->nErr ){ |
| 585 | graph_free(pGraph); |
| 586 | pGraph = 0; |
| 587 | }else{ |
| 588 | @ <tr class="timelineBottom"><td></td><td></td><td></td></tr> |
| 589 | } |
| 590 | } |
| 591 | @ </table> |
| 592 | if( fchngQueryInit ) db_finalize(&fchngQuery); |
| 593 | timeline_output_graph_javascript(pGraph, (tmFlags & TIMELINE_DISJOINT)!=0, 0); |
| @@ -648,31 +635,34 @@ | |
| 635 | ){ |
| 636 | if( pGraph && pGraph->nErr==0 && pGraph->nRow>0 ){ |
| 637 | GraphRow *pRow; |
| 638 | int i; |
| 639 | char cSep; |
| 640 | int iRailPitch; /* Pixels between consecutive rails */ |
| 641 | int showArrowheads; /* True to draw arrowheads. False to omit. */ |
| 642 | int circleNodes; /* True for circle nodes. False for square nodes */ |
| 643 | int colorGraph; /* Use colors for graph lines */ |
| 644 | |
| 645 | iRailPitch = atoi(PD("railpitch","0")); |
| 646 | showArrowheads = skin_detail_boolean("timeline-arrowheads"); |
| 647 | circleNodes = skin_detail_boolean("timeline-circle-nodes"); |
| 648 | colorGraph = skin_detail_boolean("timeline-color-graph-lines"); |
| 649 | |
| 650 | @ <script>(function(){ |
| 651 | @ "use strict"; |
| 652 | @ var css = ""; |
| 653 | if( circleNodes ){ |
| 654 | @ css += ".tl-node, .tl-node:after { border-radius: 50%%; }"; |
| 655 | } |
| 656 | if( !showArrowheads ){ |
| 657 | @ css += ".tl-arrow.u { display: none; }"; |
| 658 | } |
| 659 | @ if( css!=="" ){ |
| 660 | @ var style = document.createElement("style"); |
| 661 | @ style.textContent = css; |
| 662 | @ document.querySelector("head").appendChild(style); |
| 663 | @ } |
| 664 | /* the rowinfo[] array contains all the information needed to generate |
| 665 | ** the graph. Each entry contains information for a single row: |
| 666 | ** |
| 667 | ** id: The id of the <div> element for the row. This is an integer. |
| 668 | ** to get an actual id, prepend "m" to the integer. The top node |
| @@ -680,13 +670,13 @@ | |
| 670 | ** bg: The background color for this row |
| 671 | ** r: The "rail" that the node for this row sits on. The left-most |
| 672 | ** rail is 0 and the number increases to the right. |
| 673 | ** d: True if there is a "descender" - an arrow coming from the bottom |
| 674 | ** of the page straight up to this node. |
| 675 | ** mo: "merge-out". If non-negative, this is the rail position |
| 676 | ** for the upward portion of a merge arrow. The merge arrow goes up |
| 677 | ** to the row identified by mu:. If this value is negative then |
| 678 | ** node has no merge children and no merge-out line is drawn. |
| 679 | ** mu: The id of the row which is the top of the merge-out arrow. |
| 680 | ** u: Draw a thick child-line out of the top of this node and up to |
| 681 | ** the node with an id equal to this value. 0 if it is straight to |
| 682 | ** the top of the page, -1 if there is no thick-line riser. |
| @@ -693,37 +683,25 @@ | |
| 683 | ** f: 0x01: a leaf node. |
| 684 | ** au: An array of integers that define thick-line risers for branches. |
| 685 | ** The integers are in pairs. For each pair, the first integer is |
| 686 | ** is the rail on which the riser should run and the second integer |
| 687 | ** is the id of the node upto which the riser should run. |
| 688 | ** mi: "merge-in". An array of integer rail positions from which |
| 689 | ** merge arrows should be drawn into this node. If the value is |
| 690 | ** negative, then the rail position is the absolute value of mi[] |
| 691 | ** and a thin merge-arrow descender is drawn to the bottom of |
| 692 | ** the screen. |
| 693 | ** h: The SHA1 hash of the object being graphed |
| 694 | */ |
| 695 | cgi_printf("var rowinfo = [\n"); |
| 696 | for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){ |
| 697 | cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,u:%d,f:%d,au:", |
| 698 | pRow->idx, /* id */ |
| 699 | pRow->zBgClr, /* bg */ |
| 700 | pRow->iRail, /* r */ |
| 701 | pRow->bDescender, /* d */ |
| 702 | pRow->mergeOut, /* mo */ |
| 703 | pRow->mergeUpto, /* mu */ |
| 704 | pRow->aiRiser[pRow->iRail], /* u */ |
| 705 | pRow->isLeaf ? 1 : 0 /* f */ |
| 706 | ); |
| 707 | /* u */ |
| @@ -743,13 +721,11 @@ | |
| 721 | /* mi */ |
| 722 | cgi_printf("mi:"); |
| 723 | cSep = '['; |
| 724 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 725 | if( pRow->mergeIn[i] ){ |
| 726 | int mi = i; |
| 727 | if( pRow->mergeDown & (1<<i) ) mi = -mi; |
| 728 | cgi_printf("%c%d", cSep, mi); |
| 729 | cSep = ','; |
| 730 | } |
| 731 | } |
| @@ -756,246 +732,238 @@ | |
| 732 | if( cSep=='[' ) cgi_printf("["); |
| 733 | cgi_printf("],h:\"%s\"}%s", pRow->zUuid, pRow->pNext ? ",\n" : "];\n"); |
| 734 | } |
| 735 | cgi_printf("var nrail = %d\n", pGraph->mxRail+1); |
| 736 | graph_free(pGraph); |
| 737 | @ var canvasDiv; |
| 738 | @ var railPitch; |
| 739 | @ var mergeOffset; |
| 740 | @ var node, arrow, arrowSmall, line, mArrow, mLine, wArrow, wLine; |
| 741 | @ function initGraph(){ |
| 742 | @ var parent = gebi("timelineTable").rows[0].cells[1]; |
| 743 | @ parent.style.verticalAlign = "top"; |
| 744 | @ canvasDiv = document.createElement("div"); |
| 745 | @ canvasDiv.className = "tl-canvas"; |
| 746 | @ canvasDiv.style.position = "absolute"; |
| 747 | @ parent.appendChild(canvasDiv); |
| 748 | @ |
| 749 | @ var elems = {}; |
| 750 | @ var elemClasses = [ |
| 751 | @ "rail", "mergeoffset", "node", "arrow u", "arrow u sm", "line", |
| 752 | @ "arrow merge r", "line merge", "arrow warp", "line warp" |
| 753 | @ ]; |
| 754 | @ for( var i=0; i<elemClasses.length; i++ ){ |
| 755 | @ var cls = elemClasses[i]; |
| 756 | @ var elem = document.createElement("div"); |
| 757 | @ elem.className = "tl-" + cls; |
| 758 | @ if( cls.indexOf("line")==0 ) elem.className += " v"; |
| 759 | @ canvasDiv.appendChild(elem); |
| 760 | @ var k = cls.replace(/\s/g, "_"); |
| 761 | @ var r = elem.getBoundingClientRect(); |
| 762 | @ var w = Math.round(r.right - r.left); |
| 763 | @ var h = Math.round(r.bottom - r.top); |
| 764 | @ elems[k] = {w: w, h: h, cls: cls}; |
| 765 | @ } |
| 766 | @ node = elems.node; |
| 767 | @ arrow = elems.arrow_u; |
| 768 | @ arrowSmall = elems.arrow_u_sm; |
| 769 | @ line = elems.line; |
| 770 | @ mArrow = elems.arrow_merge_r; |
| 771 | @ mLine = elems.line_merge; |
| 772 | @ wArrow = elems.arrow_warp; |
| 773 | @ wLine = elems.line_warp; |
| 774 | @ |
| 775 | @ var minRailPitch = Math.ceil((node.w+line.w)/2 + mArrow.w + 1); |
| 776 | if( iRailPitch ){ |
| 777 | @ railPitch = %d(iRailPitch); |
| 778 | }else{ |
| 779 | @ railPitch = elems.rail.w; |
| 780 | @ railPitch -= Math.floor((nrail-1)*(railPitch-minRailPitch)/21); |
| 781 | } |
| 782 | @ railPitch = Math.max(railPitch, minRailPitch); |
| 783 | @ |
| 784 | if( PB("nomo") ){ |
| 785 | @ mergeOffset = 0; |
| 786 | }else{ |
| 787 | @ mergeOffset = railPitch-minRailPitch-mLine.w; |
| 788 | @ mergeOffset = Math.min(mergeOffset, elems.mergeoffset.w); |
| 789 | @ mergeOffset = mergeOffset>0 ? mergeOffset + line.w/2 : 0; |
| 790 | } |
| 791 | @ |
| 792 | @ var canvasWidth = (nrail-1)*railPitch + node.w; |
| 793 | @ canvasDiv.style.width = canvasWidth + "px"; |
| 794 | @ canvasDiv.style.position = "relative"; |
| 795 | @ } |
| 796 | @ function drawBox(cls,color,x0,y0,x1,y1){ |
| 797 | @ var n = document.createElement("div"); |
| 798 | @ x0 = Math.floor(x0); |
| 799 | @ y0 = Math.floor(y0); |
| 800 | @ x1 = x1 || x1===0 ? Math.floor(x1) : x0; |
| 801 | @ y1 = y1 || y1===0 ? Math.floor(y1) : y0; |
| 802 | @ if( x0>x1 ){ var t=x0; x0=x1; x1=t; } |
| 803 | @ if( y0>y1 ){ var t=y0; y0=y1; y1=t; } |
| 804 | @ var w = x1-x0; |
| 805 | @ var h = y1-y0; |
| 806 | @ n.style.position = "absolute"; |
| 807 | @ n.style.left = x0+"px"; |
| 808 | @ n.style.top = y0+"px"; |
| 809 | @ if( w ) n.style.width = w+"px"; |
| 810 | @ if( h ) n.style.height = h+"px"; |
| 811 | @ if( color ) n.style.backgroundColor = color; |
| 812 | @ n.className = "tl-"+cls; |
| 813 | @ canvasDiv.appendChild(n); |
| 814 | @ return n; |
| 815 | @ } |
| 816 | @ function absoluteY(obj){ |
| 817 | @ var top = 0; |
| 818 | @ if( obj.offsetParent ){ |
| 819 | @ do{ |
| 820 | @ top += obj.offsetTop; |
| 821 | @ }while( obj = obj.offsetParent ); |
| 822 | @ } |
| 823 | @ return top; |
| 824 | @ } |
| 825 | @ function miLineY(p){ |
| 826 | @ return p.y + node.h - mLine.w - 1; |
| 827 | @ } |
| 828 | @ function drawLine(elem,color,x0,y0,x1,y1){ |
| 829 | @ var cls = elem.cls + " "; |
| 830 | @ if( x1===null ){ |
| 831 | @ x1 = x0+elem.w; |
| 832 | @ cls += "v"; |
| 833 | @ }else{ |
| 834 | @ y1 = y0+elem.w; |
| 835 | @ cls += "h"; |
| 836 | @ } |
| 837 | @ drawBox(cls,color,x0,y0,x1,y1); |
| 838 | @ } |
| 839 | @ function drawUpArrow(from,to,color){ |
| 840 | @ var y = to.y + node.h; |
| 841 | @ var arrowSpace = from.y - y + (!from.id || from.r!=to.r ? node.h/2 : 0); |
| 842 | @ var arw = arrowSpace < arrow.h*1.5 ? arrowSmall : arrow; |
| 843 | @ var x = to.x + (node.w-line.w)/2; |
| 844 | @ var y0 = from.y + node.h/2; |
| 845 | @ var y1 = Math.ceil(to.y + node.h + arw.h/2); |
| 846 | @ drawLine(line,color,x,y0,null,y1); |
| 847 | @ x = to.x + (node.w-arw.w)/2; |
| 848 | @ var n = drawBox(arw.cls,null,x,y); |
| 849 | @ n.style.borderBottomColor = color; |
| 850 | @ } |
| 851 | @ function drawMergeLine(x0,y0,x1,y1){ |
| 852 | @ drawLine(mLine,null,x0,y0,x1,y1); |
| 853 | @ } |
| 854 | @ function drawMergeArrow(p,rail){ |
| 855 | @ var x0 = rail*railPitch + node.w/2; |
| 856 | @ if( rail in mergeLines ){ |
| 857 | @ x0 += mergeLines[rail]; |
| 858 | @ if( p.r<rail ) x0 += mLine.w; |
| 859 | @ }else{ |
| 860 | @ x0 += (p.r<rail ? -1 : 1)*line.w/2; |
| 861 | @ } |
| 862 | @ var x1 = mArrow.w ? mArrow.w/2 : -node.w/2; |
| 863 | @ x1 = p.x + (p.r<rail ? node.w + Math.ceil(x1) : -x1); |
| 864 | @ var y = miLineY(p); |
| 865 | @ drawMergeLine(x0,y,x1,null); |
| 866 | @ var x = p.x + (p.r<rail ? node.w : -mArrow.w); |
| 867 | @ var cls = "arrow merge " + (p.r<rail ? "l" : "r"); |
| 868 | @ drawBox(cls,null,x,y+(mLine.w-mArrow.h)/2); |
| 869 | @ } |
| 870 | @ function drawNode(p, btm){ |
| 871 | @ if( p.u>0 ) drawUpArrow(p,rowinfo[p.u-1],p.fg); |
| 872 | @ var cls = node.cls; |
| 873 | @ if( p.mi.length ) cls += " merge"; |
| 874 | @ if( p.f&1 ) cls += " leaf"; |
| 875 | @ var n = drawBox(cls,p.bg,p.x,p.y); |
| 876 | @ n.id = "tln"+p.id; |
| 877 | @ n.onclick = clickOnNode; |
| 878 | @ n.style.zIndex = 10; |
| 879 | if( !omitDescenders ){ |
| 880 | @ if( p.u==0 ) drawUpArrow(p,{x: p.x, y: -node.h},p.fg); |
| 881 | @ if( p.d ) drawUpArrow({x: p.x, y: btm-node.h/2},p,p.fg); |
| 882 | } |
| 883 | @ if( p.mo>=0 ){ |
| 884 | @ var x0 = p.x + node.w/2; |
| 885 | @ var x1 = p.mo*railPitch + node.w/2; |
| 886 | @ var u = rowinfo[p.mu-1]; |
| 887 | @ var y1 = miLineY(u); |
| 888 | @ if( p.u<0 || p.mo!=p.r ){ |
| 889 | @ x1 += mergeLines[p.mo] = -mLine.w/2; |
| 890 | @ var y0 = p.y+2; |
| 891 | @ if( p.r!=p.mo ) drawMergeLine(x0,y0,x1+(x0<x1 ? mLine.w : 0),null); |
| 892 | @ drawMergeLine(x1,y0+mLine.w,null,y1); |
| 893 | @ }else if( mergeOffset ){ |
| 894 | @ mergeLines[p.mo] = u.r<p.r ? -mergeOffset-mLine.w : mergeOffset; |
| 895 | @ x1 += mergeLines[p.mo]; |
| 896 | @ drawMergeLine(x1,p.y+node.h/2,null,y1); |
| 897 | @ }else{ |
| 898 | @ delete mergeLines[p.mo]; |
| 899 | @ } |
| 900 | @ } |
| 901 | @ for( var i=0; i<p.au.length; i+=2 ){ |
| 902 | @ var rail = p.au[i]; |
| 903 | @ var x0 = p.x + node.w/2; |
| 904 | @ var x1 = rail*railPitch + (node.w-line.w)/2; |
| 905 | @ if( x0<x1 ){ |
| 906 | @ x0 = Math.ceil(x0); |
| 907 | @ x1 += line.w; |
| 908 | @ } |
| 909 | @ var y0 = p.y + (node.h-line.w)/2; |
| 910 | @ var u = rowinfo[p.au[i+1]-1]; |
| 911 | @ if( u.id<p.id ){ |
| 912 | @ drawLine(line,u.fg,x0,y0,x1,null); |
| 913 | @ drawUpArrow(p,u,u.fg); |
| 914 | @ }else{ |
| 915 | @ var y1 = u.y + (node.h-line.w)/2; |
| 916 | @ drawLine(wLine,u.fg,x0,y0,x1,null); |
| 917 | @ drawLine(wLine,u.fg,x1-line.w,y0,null,y1+line.w); |
| 918 | @ drawLine(wLine,u.fg,x1,y1,u.x-wArrow.w/2,null); |
| 919 | @ var x = u.x-wArrow.w; |
| 920 | @ var y = u.y+(node.h-wArrow.h)/2; |
| 921 | @ var n = drawBox(wArrow.cls,null,x,y); |
| 922 | @ if( u.fg ) n.style.borderLeftColor = u.fg; |
| 923 | @ } |
| 924 | @ } |
| 925 | @ for( var i=0; i<p.mi.length; i++ ){ |
| 926 | @ var rail = p.mi[i]; |
| 927 | @ if( rail<0 ){ |
| 928 | @ rail = -rail; |
| 929 | @ mergeLines[rail] = -mLine.w/2; |
| 930 | @ var x = rail*railPitch + (node.w-mLine.w)/2; |
| 931 | @ drawMergeLine(x,miLineY(p),null,btm); |
| 932 | @ } |
| 933 | @ drawMergeArrow(p,rail); |
| 934 | @ } |
| 935 | @ } |
| 936 | @ var mergeLines; |
| 937 | @ function renderGraph(){ |
| 938 | @ mergeLines = {}; |
| 939 | @ canvasDiv.innerHTML = ""; |
| 940 | @ var canvasY = absoluteY(canvasDiv); |
| 941 | @ for( var i=0; i<rowinfo.length; i++ ){ |
| 942 | @ rowinfo[i].y = absoluteY(gebi("m"+rowinfo[i].id)) - canvasY; |
| 943 | @ rowinfo[i].x = rowinfo[i].r*railPitch; |
| 944 | @ } |
| 945 | @ var tlBtm = document.querySelector(".timelineBottom"); |
| 946 | @ if( tlBtm.offsetHeight<node.h ){ |
| 947 | @ tlBtm.style.height = node.h + "px"; |
| 948 | @ } |
| 949 | @ var btm = absoluteY(tlBtm) - canvasY + tlBtm.offsetHeight; |
| 950 | @ for( var i=rowinfo.length-1; i>=0; i-- ){ |
| 951 | @ drawNode(rowinfo[i], btm); |
| 952 | @ } |
| 953 | @ } |
| 954 | @ var selRow; |
| 955 | @ function clickOnNode(){ |
| 956 | @ var p = rowinfo[parseInt(this.id.match(/\d+$/)[0], 10)-1]; |
| 957 | @ if( !selRow ){ |
| 958 | @ selRow = p; |
| 959 | @ this.className += " sel"; |
| 960 | @ canvasDiv.className += " sel"; |
| 961 | @ }else if( selRow==p ){ |
| 962 | @ selRow = null; |
| 963 | @ this.className = this.className.replace(" sel", ""); |
| 964 | @ canvasDiv.className = canvasDiv.className.replace(" sel", ""); |
| 965 | @ }else{ |
| 966 | if( fileDiff ){ |
| 967 | @ location.href="%R/fdiff?v1="+selRow.h+"&v2="+p.h+"&sbs=1"; |
| 968 | }else{ |
| 969 | if( db_get_boolean("show-version-diffs", 0)==0 ){ |
| @@ -1004,22 +972,23 @@ | |
| 972 | @ location.href="%R/vdiff?from="+selRow.h+"&to="+p.h+"&sbs=1"; |
| 973 | } |
| 974 | } |
| 975 | @ } |
| 976 | @ } |
| 977 | @ var lastRow = gebi("m"+rowinfo[rowinfo.length-1].id); |
| 978 | @ var lastY = 0; |
| 979 | @ function checkHeight(){ |
| 980 | @ var h = absoluteY(lastRow); |
| 981 | @ if( h!=lastY ){ |
| 982 | @ renderGraph(); |
| 983 | @ lastY = h; |
| 984 | @ } |
| 985 | @ setTimeout(checkHeight, 1000); |
| 986 | @ } |
| 987 | @ initGraph(); |
| 988 | @ checkHeight(); |
| 989 | @ }())</script> |
| 990 | } |
| 991 | } |
| 992 | |
| 993 | /* |
| 994 | ** Create a temporary table suitable for storing timeline data. |
| @@ -1308,24 +1277,24 @@ | |
| 1277 | return; |
| 1278 | } |
| 1279 | url_initialize(&url, "timeline"); |
| 1280 | cgi_query_parameters_to_url(&url); |
| 1281 | if( zTagName && g.perm.Read ){ |
| 1282 | tagid = db_int(-1,"SELECT tagid FROM tag WHERE tagname='sym-%q'",zTagName); |
| 1283 | zThisTag = zTagName; |
| 1284 | }else if( zBrName && g.perm.Read ){ |
| 1285 | tagid = db_int(-1,"SELECT tagid FROM tag WHERE tagname='sym-%q'",zBrName); |
| 1286 | zThisTag = zBrName; |
| 1287 | }else{ |
| 1288 | tagid = 0; |
| 1289 | } |
| 1290 | if( zMark && zMark[0]==0 ){ |
| 1291 | if( zAfter ) zMark = zAfter; |
| 1292 | if( zBefore ) zMark = zBefore; |
| 1293 | if( zCirca ) zMark = zCirca; |
| 1294 | } |
| 1295 | if( tagid |
| 1296 | && db_int(0,"SELECT count(*) FROM tagxref WHERE tagid=%d",tagid)<=nEntry |
| 1297 | ){ |
| 1298 | nEntry = -1; |
| 1299 | zCirca = 0; |
| 1300 | } |
| @@ -1524,11 +1493,11 @@ | |
| 1493 | } |
| 1494 | else if( zYearWeek ){ |
| 1495 | blob_append_sql(&sql, " AND %Q=strftime('%%Y-%%W',event.mtime) ", |
| 1496 | zYearWeek); |
| 1497 | } |
| 1498 | if( tagid ){ |
| 1499 | blob_append_sql(&sql, |
| 1500 | " AND (EXISTS(SELECT 1 FROM tagxref" |
| 1501 | " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)\n", tagid); |
| 1502 | |
| 1503 | if( zBrName ){ |
| 1504 |
+5
-5
| --- src/translate.c | ||
| +++ src/translate.c | ||
| @@ -40,15 +40,15 @@ | ||
| 40 | 40 | ** rather than text that is to be output via cgi_printf(). Render it |
| 41 | 41 | ** as such. |
| 42 | 42 | ** |
| 43 | 43 | ** Enhancement #2: |
| 44 | 44 | ** |
| 45 | -** Comments of the form: "/* @-comment: CC" cause CC to become a | |
| 46 | -** comment character for the @-substitution. Typical values for CC are | |
| 47 | -** "--" (for SQL text) or "#" (for Tcl script) or "//" (for C++ code). | |
| 48 | -** Lines of subsequent @-blocks that begin with CC are omitted from the | |
| 49 | -** output. | |
| 45 | +** Comments of the form: "|* @-comment: CC" (where "|" is really "/") | |
| 46 | +** cause CC to become a comment character for the @-substitution. | |
| 47 | +** Typical values for CC are "--" (for SQL text) or "#" (for Tcl script) | |
| 48 | +** or "//" (for C++ code). Lines of subsequent @-blocks that begin with | |
| 49 | +** CC are omitted from the output. | |
| 50 | 50 | ** |
| 51 | 51 | */ |
| 52 | 52 | #include <stdio.h> |
| 53 | 53 | #include <ctype.h> |
| 54 | 54 | #include <stdlib.h> |
| 55 | 55 |
| --- src/translate.c | |
| +++ src/translate.c | |
| @@ -40,15 +40,15 @@ | |
| 40 | ** rather than text that is to be output via cgi_printf(). Render it |
| 41 | ** as such. |
| 42 | ** |
| 43 | ** Enhancement #2: |
| 44 | ** |
| 45 | ** Comments of the form: "/* @-comment: CC" cause CC to become a |
| 46 | ** comment character for the @-substitution. Typical values for CC are |
| 47 | ** "--" (for SQL text) or "#" (for Tcl script) or "//" (for C++ code). |
| 48 | ** Lines of subsequent @-blocks that begin with CC are omitted from the |
| 49 | ** output. |
| 50 | ** |
| 51 | */ |
| 52 | #include <stdio.h> |
| 53 | #include <ctype.h> |
| 54 | #include <stdlib.h> |
| 55 |
| --- src/translate.c | |
| +++ src/translate.c | |
| @@ -40,15 +40,15 @@ | |
| 40 | ** rather than text that is to be output via cgi_printf(). Render it |
| 41 | ** as such. |
| 42 | ** |
| 43 | ** Enhancement #2: |
| 44 | ** |
| 45 | ** Comments of the form: "|* @-comment: CC" (where "|" is really "/") |
| 46 | ** cause CC to become a comment character for the @-substitution. |
| 47 | ** Typical values for CC are "--" (for SQL text) or "#" (for Tcl script) |
| 48 | ** or "//" (for C++ code). Lines of subsequent @-blocks that begin with |
| 49 | ** CC are omitted from the output. |
| 50 | ** |
| 51 | */ |
| 52 | #include <stdio.h> |
| 53 | #include <ctype.h> |
| 54 | #include <stdlib.h> |
| 55 |
+16
-24
| --- src/update.c | ||
| +++ src/update.c | ||
| @@ -586,43 +586,32 @@ | ||
| 586 | 586 | db_end_transaction(0); |
| 587 | 587 | } |
| 588 | 588 | } |
| 589 | 589 | |
| 590 | 590 | /* |
| 591 | -** Make sure empty directories are created | |
| 591 | +** Create empty directories specified by the empty-dirs setting. | |
| 592 | 592 | */ |
| 593 | 593 | void ensure_empty_dirs_created(void){ |
| 594 | - /* Make empty directories? */ | |
| 595 | 594 | char *zEmptyDirs = db_get("empty-dirs", 0); |
| 596 | 595 | if( zEmptyDirs!=0 ){ |
| 597 | - char *bc; | |
| 596 | + int i; | |
| 598 | 597 | Blob dirName; |
| 599 | 598 | Blob dirsList; |
| 600 | 599 | |
| 601 | - blob_zero(&dirsList); | |
| 602 | - blob_init(&dirsList, zEmptyDirs, strlen(zEmptyDirs)); | |
| 603 | - /* Replace commas by spaces */ | |
| 604 | - bc = blob_str(&dirsList); | |
| 605 | - while( (*bc)!='\0' ){ | |
| 606 | - if( (*bc)==',' ) { *bc = ' '; } | |
| 607 | - ++bc; | |
| 608 | - } | |
| 609 | - /* Make directories */ | |
| 610 | - blob_zero(&dirName); | |
| 600 | + zEmptyDirs = fossil_strdup(zEmptyDirs); | |
| 601 | + for(i=0; zEmptyDirs[i]; i++){ | |
| 602 | + if( zEmptyDirs[i]==',' ) zEmptyDirs[i] = ' '; | |
| 603 | + } | |
| 604 | + blob_init(&dirsList, zEmptyDirs, -1); | |
| 611 | 605 | while( blob_token(&dirsList, &dirName) ){ |
| 612 | - const char *zDir = blob_str(&dirName); | |
| 613 | - /* Make full pathname of the directory */ | |
| 614 | - Blob path; | |
| 615 | - const char *zPath; | |
| 616 | - | |
| 617 | - blob_zero(&path); | |
| 618 | - blob_appendf(&path, "%s/%s", g.zLocalRoot, zDir); | |
| 619 | - zPath = blob_str(&path); | |
| 620 | - /* Handle various cases of existence of the directory */ | |
| 606 | + char *zDir = blob_str(&dirName); | |
| 607 | + char *zPath = mprintf("%s/%s", g.zLocalRoot, zDir); | |
| 621 | 608 | switch( file_wd_isdir(zPath) ){ |
| 622 | 609 | case 0: { /* doesn't exist */ |
| 623 | - if( file_mkdir(zPath, 0)!=0 ) { | |
| 610 | + fossil_free(zPath); | |
| 611 | + zPath = mprintf("%s/%s/x", g.zLocalRoot, zDir); | |
| 612 | + if( file_mkfolder(zPath, 0, 1)!=0 ) { | |
| 624 | 613 | fossil_warning("couldn't create directory %s as " |
| 625 | 614 | "required by empty-dirs setting", zDir); |
| 626 | 615 | } |
| 627 | 616 | break; |
| 628 | 617 | } |
| @@ -633,12 +622,15 @@ | ||
| 633 | 622 | case 2: { /* exists, but isn't a directory */ |
| 634 | 623 | fossil_warning("file %s found, but a directory is required " |
| 635 | 624 | "by empty-dirs setting", zDir); |
| 636 | 625 | } |
| 637 | 626 | } |
| 638 | - blob_reset(&path); | |
| 627 | + fossil_free(zPath); | |
| 628 | + blob_reset(&dirName); | |
| 639 | 629 | } |
| 630 | + blob_reset(&dirsList); | |
| 631 | + fossil_free(zEmptyDirs); | |
| 640 | 632 | } |
| 641 | 633 | } |
| 642 | 634 | |
| 643 | 635 | |
| 644 | 636 | /* |
| 645 | 637 |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -586,43 +586,32 @@ | |
| 586 | db_end_transaction(0); |
| 587 | } |
| 588 | } |
| 589 | |
| 590 | /* |
| 591 | ** Make sure empty directories are created |
| 592 | */ |
| 593 | void ensure_empty_dirs_created(void){ |
| 594 | /* Make empty directories? */ |
| 595 | char *zEmptyDirs = db_get("empty-dirs", 0); |
| 596 | if( zEmptyDirs!=0 ){ |
| 597 | char *bc; |
| 598 | Blob dirName; |
| 599 | Blob dirsList; |
| 600 | |
| 601 | blob_zero(&dirsList); |
| 602 | blob_init(&dirsList, zEmptyDirs, strlen(zEmptyDirs)); |
| 603 | /* Replace commas by spaces */ |
| 604 | bc = blob_str(&dirsList); |
| 605 | while( (*bc)!='\0' ){ |
| 606 | if( (*bc)==',' ) { *bc = ' '; } |
| 607 | ++bc; |
| 608 | } |
| 609 | /* Make directories */ |
| 610 | blob_zero(&dirName); |
| 611 | while( blob_token(&dirsList, &dirName) ){ |
| 612 | const char *zDir = blob_str(&dirName); |
| 613 | /* Make full pathname of the directory */ |
| 614 | Blob path; |
| 615 | const char *zPath; |
| 616 | |
| 617 | blob_zero(&path); |
| 618 | blob_appendf(&path, "%s/%s", g.zLocalRoot, zDir); |
| 619 | zPath = blob_str(&path); |
| 620 | /* Handle various cases of existence of the directory */ |
| 621 | switch( file_wd_isdir(zPath) ){ |
| 622 | case 0: { /* doesn't exist */ |
| 623 | if( file_mkdir(zPath, 0)!=0 ) { |
| 624 | fossil_warning("couldn't create directory %s as " |
| 625 | "required by empty-dirs setting", zDir); |
| 626 | } |
| 627 | break; |
| 628 | } |
| @@ -633,12 +622,15 @@ | |
| 633 | case 2: { /* exists, but isn't a directory */ |
| 634 | fossil_warning("file %s found, but a directory is required " |
| 635 | "by empty-dirs setting", zDir); |
| 636 | } |
| 637 | } |
| 638 | blob_reset(&path); |
| 639 | } |
| 640 | } |
| 641 | } |
| 642 | |
| 643 | |
| 644 | /* |
| 645 |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -586,43 +586,32 @@ | |
| 586 | db_end_transaction(0); |
| 587 | } |
| 588 | } |
| 589 | |
| 590 | /* |
| 591 | ** Create empty directories specified by the empty-dirs setting. |
| 592 | */ |
| 593 | void ensure_empty_dirs_created(void){ |
| 594 | char *zEmptyDirs = db_get("empty-dirs", 0); |
| 595 | if( zEmptyDirs!=0 ){ |
| 596 | int i; |
| 597 | Blob dirName; |
| 598 | Blob dirsList; |
| 599 | |
| 600 | zEmptyDirs = fossil_strdup(zEmptyDirs); |
| 601 | for(i=0; zEmptyDirs[i]; i++){ |
| 602 | if( zEmptyDirs[i]==',' ) zEmptyDirs[i] = ' '; |
| 603 | } |
| 604 | blob_init(&dirsList, zEmptyDirs, -1); |
| 605 | while( blob_token(&dirsList, &dirName) ){ |
| 606 | char *zDir = blob_str(&dirName); |
| 607 | char *zPath = mprintf("%s/%s", g.zLocalRoot, zDir); |
| 608 | switch( file_wd_isdir(zPath) ){ |
| 609 | case 0: { /* doesn't exist */ |
| 610 | fossil_free(zPath); |
| 611 | zPath = mprintf("%s/%s/x", g.zLocalRoot, zDir); |
| 612 | if( file_mkfolder(zPath, 0, 1)!=0 ) { |
| 613 | fossil_warning("couldn't create directory %s as " |
| 614 | "required by empty-dirs setting", zDir); |
| 615 | } |
| 616 | break; |
| 617 | } |
| @@ -633,12 +622,15 @@ | |
| 622 | case 2: { /* exists, but isn't a directory */ |
| 623 | fossil_warning("file %s found, but a directory is required " |
| 624 | "by empty-dirs setting", zDir); |
| 625 | } |
| 626 | } |
| 627 | fossil_free(zPath); |
| 628 | blob_reset(&dirName); |
| 629 | } |
| 630 | blob_reset(&dirsList); |
| 631 | fossil_free(zEmptyDirs); |
| 632 | } |
| 633 | } |
| 634 | |
| 635 | |
| 636 | /* |
| 637 |
+6
-4
| --- src/url.c | ||
| +++ src/url.c | ||
| @@ -454,12 +454,12 @@ | ||
| 454 | 454 | ** Resets the given URL object, deallocating any memory |
| 455 | 455 | ** it uses. |
| 456 | 456 | */ |
| 457 | 457 | void url_reset(HQuery *p){ |
| 458 | 458 | blob_reset(&p->url); |
| 459 | - fossil_free(p->azName); | |
| 460 | - fossil_free(p->azValue); | |
| 459 | + fossil_free((void *)p->azName); | |
| 460 | + fossil_free((void *)p->azValue); | |
| 461 | 461 | url_initialize(p, p->zBase); |
| 462 | 462 | } |
| 463 | 463 | |
| 464 | 464 | /* |
| 465 | 465 | ** Add a fixed parameter to an HQuery. Or remove the parameters if zValue==0. |
| @@ -480,12 +480,14 @@ | ||
| 480 | 480 | } |
| 481 | 481 | assert( i==p->nParam ); |
| 482 | 482 | if( zValue==0 ) return; |
| 483 | 483 | if( i>=p->nAlloc ){ |
| 484 | 484 | p->nAlloc = p->nAlloc*2 + 10; |
| 485 | - p->azName = fossil_realloc(p->azName, sizeof(p->azName[0])*p->nAlloc); | |
| 486 | - p->azValue = fossil_realloc(p->azValue, sizeof(p->azValue[0])*p->nAlloc); | |
| 485 | + p->azName = fossil_realloc((void *)p->azName, | |
| 486 | + sizeof(p->azName[0])*p->nAlloc); | |
| 487 | + p->azValue = fossil_realloc((void *)p->azValue, | |
| 488 | + sizeof(p->azValue[0])*p->nAlloc); | |
| 487 | 489 | } |
| 488 | 490 | p->azName[i] = zName; |
| 489 | 491 | p->azValue[i] = zValue; |
| 490 | 492 | p->nParam++; |
| 491 | 493 | } |
| 492 | 494 |
| --- src/url.c | |
| +++ src/url.c | |
| @@ -454,12 +454,12 @@ | |
| 454 | ** Resets the given URL object, deallocating any memory |
| 455 | ** it uses. |
| 456 | */ |
| 457 | void url_reset(HQuery *p){ |
| 458 | blob_reset(&p->url); |
| 459 | fossil_free(p->azName); |
| 460 | fossil_free(p->azValue); |
| 461 | url_initialize(p, p->zBase); |
| 462 | } |
| 463 | |
| 464 | /* |
| 465 | ** Add a fixed parameter to an HQuery. Or remove the parameters if zValue==0. |
| @@ -480,12 +480,14 @@ | |
| 480 | } |
| 481 | assert( i==p->nParam ); |
| 482 | if( zValue==0 ) return; |
| 483 | if( i>=p->nAlloc ){ |
| 484 | p->nAlloc = p->nAlloc*2 + 10; |
| 485 | p->azName = fossil_realloc(p->azName, sizeof(p->azName[0])*p->nAlloc); |
| 486 | p->azValue = fossil_realloc(p->azValue, sizeof(p->azValue[0])*p->nAlloc); |
| 487 | } |
| 488 | p->azName[i] = zName; |
| 489 | p->azValue[i] = zValue; |
| 490 | p->nParam++; |
| 491 | } |
| 492 |
| --- src/url.c | |
| +++ src/url.c | |
| @@ -454,12 +454,12 @@ | |
| 454 | ** Resets the given URL object, deallocating any memory |
| 455 | ** it uses. |
| 456 | */ |
| 457 | void url_reset(HQuery *p){ |
| 458 | blob_reset(&p->url); |
| 459 | fossil_free((void *)p->azName); |
| 460 | fossil_free((void *)p->azValue); |
| 461 | url_initialize(p, p->zBase); |
| 462 | } |
| 463 | |
| 464 | /* |
| 465 | ** Add a fixed parameter to an HQuery. Or remove the parameters if zValue==0. |
| @@ -480,12 +480,14 @@ | |
| 480 | } |
| 481 | assert( i==p->nParam ); |
| 482 | if( zValue==0 ) return; |
| 483 | if( i>=p->nAlloc ){ |
| 484 | p->nAlloc = p->nAlloc*2 + 10; |
| 485 | p->azName = fossil_realloc((void *)p->azName, |
| 486 | sizeof(p->azName[0])*p->nAlloc); |
| 487 | p->azValue = fossil_realloc((void *)p->azValue, |
| 488 | sizeof(p->azValue[0])*p->nAlloc); |
| 489 | } |
| 490 | p->azName[i] = zName; |
| 491 | p->azValue[i] = zValue; |
| 492 | p->nParam++; |
| 493 | } |
| 494 |
+35
-7
| --- src/vfile.c | ||
| +++ src/vfile.c | ||
| @@ -136,15 +136,22 @@ | ||
| 136 | 136 | #define CKSIG_SETMTIME 0x004 /* Set mtime to last check-out time */ |
| 137 | 137 | |
| 138 | 138 | #endif /* INTERFACE */ |
| 139 | 139 | |
| 140 | 140 | /* |
| 141 | -** Look at every VFILE entry with the given vid and update | |
| 142 | -** VFILE.CHNGED field according to whether or not | |
| 143 | -** the file has changed. 0 means no change. 1 means edited. 2 means | |
| 144 | -** the file has changed due to a merge. 3 means the file was added | |
| 145 | -** by a merge. | |
| 141 | +** Look at every VFILE entry with the given vid and update VFILE.CHNGED field | |
| 142 | +** according to whether or not the file has changed. | |
| 143 | +** - 0 means no change. | |
| 144 | +** - 1 means edited. | |
| 145 | +** - 2 means changed due to a merge. | |
| 146 | +** - 3 means added by a merge. | |
| 147 | +** - 4 means changed due to an integrate merge. | |
| 148 | +** - 5 means added by an integrate merge. | |
| 149 | +** - 6 means became executable but has unmodified contents. | |
| 150 | +** - 7 means became a symlink whose target equals its old contents. | |
| 151 | +** - 8 means lost executable status but has unmodified contents. | |
| 152 | +** - 9 means lost symlink status and has contents equal to its old target. | |
| 146 | 153 | ** |
| 147 | 154 | ** If VFILE.DELETED is true or if VFILE.RID is zero, then the file was either |
| 148 | 155 | ** removed from configuration management via "fossil rm" or added via |
| 149 | 156 | ** "fossil add", respectively, and in both cases we always know that |
| 150 | 157 | ** the file has changed without having the check the size, mtime, |
| @@ -170,18 +177,22 @@ | ||
| 170 | 177 | int useMtime = (cksigFlags & CKSIG_SHA1)==0 |
| 171 | 178 | && db_get_boolean("mtime-changes", 1); |
| 172 | 179 | |
| 173 | 180 | db_begin_transaction(); |
| 174 | 181 | db_prepare(&q, "SELECT id, %Q || pathname," |
| 175 | - " vfile.mrid, deleted, chnged, uuid, size, mtime" | |
| 182 | + " vfile.mrid, deleted, chnged, uuid, size, mtime," | |
| 183 | + " CASE WHEN isexe THEN %d WHEN islink THEN %d ELSE %d END" | |
| 176 | 184 | " FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid" |
| 177 | - " WHERE vid=%d ", g.zLocalRoot, vid); | |
| 185 | + " WHERE vid=%d ", g.zLocalRoot, PERM_EXE, PERM_LNK, PERM_REG, | |
| 186 | + vid); | |
| 178 | 187 | while( db_step(&q)==SQLITE_ROW ){ |
| 179 | 188 | int id, rid, isDeleted; |
| 180 | 189 | const char *zName; |
| 181 | 190 | int chnged = 0; |
| 182 | 191 | int oldChnged; |
| 192 | + int origPerm; | |
| 193 | + int currentPerm; | |
| 183 | 194 | i64 oldMtime; |
| 184 | 195 | i64 currentMtime; |
| 185 | 196 | i64 origSize; |
| 186 | 197 | i64 currentSize; |
| 187 | 198 | |
| @@ -192,10 +203,12 @@ | ||
| 192 | 203 | oldChnged = chnged = db_column_int(&q, 4); |
| 193 | 204 | oldMtime = db_column_int64(&q, 7); |
| 194 | 205 | origSize = db_column_int64(&q, 6); |
| 195 | 206 | currentSize = file_wd_size(zName); |
| 196 | 207 | currentMtime = file_wd_mtime(0); |
| 208 | + origPerm = db_column_int(&q, 8); | |
| 209 | + currentPerm = file_wd_perm(zName); | |
| 197 | 210 | if( chnged==0 && (isDeleted || rid==0) ){ |
| 198 | 211 | /* "fossil rm" or "fossil add" always change the file */ |
| 199 | 212 | chnged = 1; |
| 200 | 213 | }else if( !file_wd_isfile_or_link(0) && currentSize>=0 ){ |
| 201 | 214 | if( cksigFlags & CKSIG_ENOTFILE ){ |
| @@ -245,10 +258,25 @@ | ||
| 245 | 258 | file_set_mtime(zName, desiredMtime); |
| 246 | 259 | currentMtime = file_wd_mtime(zName); |
| 247 | 260 | } |
| 248 | 261 | } |
| 249 | 262 | } |
| 263 | +#ifndef _WIN32 | |
| 264 | + if( chnged==0 || chnged==6 || chnged==7 || chnged==8 || chnged==9 ){ | |
| 265 | + if( origPerm == currentPerm ){ | |
| 266 | + chnged = 0; | |
| 267 | + }else if( currentPerm == PERM_EXE ){ | |
| 268 | + chnged = 6; | |
| 269 | + }else if( currentPerm == PERM_LNK ){ | |
| 270 | + chnged = 7; | |
| 271 | + }else if( origPerm == PERM_EXE ){ | |
| 272 | + chnged = 8; | |
| 273 | + }else if( origPerm == PERM_LNK ){ | |
| 274 | + chnged = 9; | |
| 275 | + } | |
| 276 | + } | |
| 277 | +#endif | |
| 250 | 278 | if( currentMtime!=oldMtime || chnged!=oldChnged ){ |
| 251 | 279 | db_multi_exec("UPDATE vfile SET mtime=%lld, chnged=%d WHERE id=%d", |
| 252 | 280 | currentMtime, chnged, id); |
| 253 | 281 | } |
| 254 | 282 | } |
| 255 | 283 |
| --- src/vfile.c | |
| +++ src/vfile.c | |
| @@ -136,15 +136,22 @@ | |
| 136 | #define CKSIG_SETMTIME 0x004 /* Set mtime to last check-out time */ |
| 137 | |
| 138 | #endif /* INTERFACE */ |
| 139 | |
| 140 | /* |
| 141 | ** Look at every VFILE entry with the given vid and update |
| 142 | ** VFILE.CHNGED field according to whether or not |
| 143 | ** the file has changed. 0 means no change. 1 means edited. 2 means |
| 144 | ** the file has changed due to a merge. 3 means the file was added |
| 145 | ** by a merge. |
| 146 | ** |
| 147 | ** If VFILE.DELETED is true or if VFILE.RID is zero, then the file was either |
| 148 | ** removed from configuration management via "fossil rm" or added via |
| 149 | ** "fossil add", respectively, and in both cases we always know that |
| 150 | ** the file has changed without having the check the size, mtime, |
| @@ -170,18 +177,22 @@ | |
| 170 | int useMtime = (cksigFlags & CKSIG_SHA1)==0 |
| 171 | && db_get_boolean("mtime-changes", 1); |
| 172 | |
| 173 | db_begin_transaction(); |
| 174 | db_prepare(&q, "SELECT id, %Q || pathname," |
| 175 | " vfile.mrid, deleted, chnged, uuid, size, mtime" |
| 176 | " FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid" |
| 177 | " WHERE vid=%d ", g.zLocalRoot, vid); |
| 178 | while( db_step(&q)==SQLITE_ROW ){ |
| 179 | int id, rid, isDeleted; |
| 180 | const char *zName; |
| 181 | int chnged = 0; |
| 182 | int oldChnged; |
| 183 | i64 oldMtime; |
| 184 | i64 currentMtime; |
| 185 | i64 origSize; |
| 186 | i64 currentSize; |
| 187 | |
| @@ -192,10 +203,12 @@ | |
| 192 | oldChnged = chnged = db_column_int(&q, 4); |
| 193 | oldMtime = db_column_int64(&q, 7); |
| 194 | origSize = db_column_int64(&q, 6); |
| 195 | currentSize = file_wd_size(zName); |
| 196 | currentMtime = file_wd_mtime(0); |
| 197 | if( chnged==0 && (isDeleted || rid==0) ){ |
| 198 | /* "fossil rm" or "fossil add" always change the file */ |
| 199 | chnged = 1; |
| 200 | }else if( !file_wd_isfile_or_link(0) && currentSize>=0 ){ |
| 201 | if( cksigFlags & CKSIG_ENOTFILE ){ |
| @@ -245,10 +258,25 @@ | |
| 245 | file_set_mtime(zName, desiredMtime); |
| 246 | currentMtime = file_wd_mtime(zName); |
| 247 | } |
| 248 | } |
| 249 | } |
| 250 | if( currentMtime!=oldMtime || chnged!=oldChnged ){ |
| 251 | db_multi_exec("UPDATE vfile SET mtime=%lld, chnged=%d WHERE id=%d", |
| 252 | currentMtime, chnged, id); |
| 253 | } |
| 254 | } |
| 255 |
| --- src/vfile.c | |
| +++ src/vfile.c | |
| @@ -136,15 +136,22 @@ | |
| 136 | #define CKSIG_SETMTIME 0x004 /* Set mtime to last check-out time */ |
| 137 | |
| 138 | #endif /* INTERFACE */ |
| 139 | |
| 140 | /* |
| 141 | ** Look at every VFILE entry with the given vid and update VFILE.CHNGED field |
| 142 | ** according to whether or not the file has changed. |
| 143 | ** - 0 means no change. |
| 144 | ** - 1 means edited. |
| 145 | ** - 2 means changed due to a merge. |
| 146 | ** - 3 means added by a merge. |
| 147 | ** - 4 means changed due to an integrate merge. |
| 148 | ** - 5 means added by an integrate merge. |
| 149 | ** - 6 means became executable but has unmodified contents. |
| 150 | ** - 7 means became a symlink whose target equals its old contents. |
| 151 | ** - 8 means lost executable status but has unmodified contents. |
| 152 | ** - 9 means lost symlink status and has contents equal to its old target. |
| 153 | ** |
| 154 | ** If VFILE.DELETED is true or if VFILE.RID is zero, then the file was either |
| 155 | ** removed from configuration management via "fossil rm" or added via |
| 156 | ** "fossil add", respectively, and in both cases we always know that |
| 157 | ** the file has changed without having the check the size, mtime, |
| @@ -170,18 +177,22 @@ | |
| 177 | int useMtime = (cksigFlags & CKSIG_SHA1)==0 |
| 178 | && db_get_boolean("mtime-changes", 1); |
| 179 | |
| 180 | db_begin_transaction(); |
| 181 | db_prepare(&q, "SELECT id, %Q || pathname," |
| 182 | " vfile.mrid, deleted, chnged, uuid, size, mtime," |
| 183 | " CASE WHEN isexe THEN %d WHEN islink THEN %d ELSE %d END" |
| 184 | " FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid" |
| 185 | " WHERE vid=%d ", g.zLocalRoot, PERM_EXE, PERM_LNK, PERM_REG, |
| 186 | vid); |
| 187 | while( db_step(&q)==SQLITE_ROW ){ |
| 188 | int id, rid, isDeleted; |
| 189 | const char *zName; |
| 190 | int chnged = 0; |
| 191 | int oldChnged; |
| 192 | int origPerm; |
| 193 | int currentPerm; |
| 194 | i64 oldMtime; |
| 195 | i64 currentMtime; |
| 196 | i64 origSize; |
| 197 | i64 currentSize; |
| 198 | |
| @@ -192,10 +203,12 @@ | |
| 203 | oldChnged = chnged = db_column_int(&q, 4); |
| 204 | oldMtime = db_column_int64(&q, 7); |
| 205 | origSize = db_column_int64(&q, 6); |
| 206 | currentSize = file_wd_size(zName); |
| 207 | currentMtime = file_wd_mtime(0); |
| 208 | origPerm = db_column_int(&q, 8); |
| 209 | currentPerm = file_wd_perm(zName); |
| 210 | if( chnged==0 && (isDeleted || rid==0) ){ |
| 211 | /* "fossil rm" or "fossil add" always change the file */ |
| 212 | chnged = 1; |
| 213 | }else if( !file_wd_isfile_or_link(0) && currentSize>=0 ){ |
| 214 | if( cksigFlags & CKSIG_ENOTFILE ){ |
| @@ -245,10 +258,25 @@ | |
| 258 | file_set_mtime(zName, desiredMtime); |
| 259 | currentMtime = file_wd_mtime(zName); |
| 260 | } |
| 261 | } |
| 262 | } |
| 263 | #ifndef _WIN32 |
| 264 | if( chnged==0 || chnged==6 || chnged==7 || chnged==8 || chnged==9 ){ |
| 265 | if( origPerm == currentPerm ){ |
| 266 | chnged = 0; |
| 267 | }else if( currentPerm == PERM_EXE ){ |
| 268 | chnged = 6; |
| 269 | }else if( currentPerm == PERM_LNK ){ |
| 270 | chnged = 7; |
| 271 | }else if( origPerm == PERM_EXE ){ |
| 272 | chnged = 8; |
| 273 | }else if( origPerm == PERM_LNK ){ |
| 274 | chnged = 9; |
| 275 | } |
| 276 | } |
| 277 | #endif |
| 278 | if( currentMtime!=oldMtime || chnged!=oldChnged ){ |
| 279 | db_multi_exec("UPDATE vfile SET mtime=%lld, chnged=%d WHERE id=%d", |
| 280 | currentMtime, chnged, id); |
| 281 | } |
| 282 | } |
| 283 |
+3
-1
| --- src/wikiformat.c | ||
| +++ src/wikiformat.c | ||
| @@ -1151,11 +1151,13 @@ | ||
| 1151 | 1151 | return zTarget+5; |
| 1152 | 1152 | } |
| 1153 | 1153 | if( strcmp(zTarget, "Sandbox")==0 ) return zTarget; |
| 1154 | 1154 | if( wiki_name_is_wellformed((const unsigned char *)zTarget) |
| 1155 | 1155 | && ((p->state & WIKI_NOBADLINKS)==0 || |
| 1156 | - db_exists("SELECT 1 FROM tag WHERE tagname GLOB 'wiki-%q'", zTarget)) | |
| 1156 | + db_exists("SELECT 1 FROM tag WHERE tagname GLOB 'wiki-%q'" | |
| 1157 | + " AND (SELECT value FROM tagxref WHERE tagid=tag.tagid" | |
| 1158 | + " ORDER BY mtime DESC LIMIT 1) > 0", zTarget)) | |
| 1157 | 1159 | ){ |
| 1158 | 1160 | return zTarget; |
| 1159 | 1161 | } |
| 1160 | 1162 | return 0; |
| 1161 | 1163 | } |
| 1162 | 1164 |
| --- src/wikiformat.c | |
| +++ src/wikiformat.c | |
| @@ -1151,11 +1151,13 @@ | |
| 1151 | return zTarget+5; |
| 1152 | } |
| 1153 | if( strcmp(zTarget, "Sandbox")==0 ) return zTarget; |
| 1154 | if( wiki_name_is_wellformed((const unsigned char *)zTarget) |
| 1155 | && ((p->state & WIKI_NOBADLINKS)==0 || |
| 1156 | db_exists("SELECT 1 FROM tag WHERE tagname GLOB 'wiki-%q'", zTarget)) |
| 1157 | ){ |
| 1158 | return zTarget; |
| 1159 | } |
| 1160 | return 0; |
| 1161 | } |
| 1162 |
| --- src/wikiformat.c | |
| +++ src/wikiformat.c | |
| @@ -1151,11 +1151,13 @@ | |
| 1151 | return zTarget+5; |
| 1152 | } |
| 1153 | if( strcmp(zTarget, "Sandbox")==0 ) return zTarget; |
| 1154 | if( wiki_name_is_wellformed((const unsigned char *)zTarget) |
| 1155 | && ((p->state & WIKI_NOBADLINKS)==0 || |
| 1156 | db_exists("SELECT 1 FROM tag WHERE tagname GLOB 'wiki-%q'" |
| 1157 | " AND (SELECT value FROM tagxref WHERE tagid=tag.tagid" |
| 1158 | " ORDER BY mtime DESC LIMIT 1) > 0", zTarget)) |
| 1159 | ){ |
| 1160 | return zTarget; |
| 1161 | } |
| 1162 | return 0; |
| 1163 | } |
| 1164 |
+1
-1
| --- src/xfer.c | ||
| +++ src/xfer.c | ||
| @@ -1973,10 +1973,10 @@ | ||
| 1973 | 1973 | manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 1974 | 1974 | content_enable_dephantomize(1); |
| 1975 | 1975 | db_end_transaction(0); |
| 1976 | 1976 | } |
| 1977 | 1977 | if( (syncFlags & SYNC_CLONE)==0 && g.rcvid && fossil_any_has_fork(g.rcvid) ){ |
| 1978 | - fossil_warning("***** WARNING: multiple leaves on the same branch are formed *****\n" | |
| 1978 | + fossil_warning("***** WARNING: a fork has occurred *****\n" | |
| 1979 | 1979 | "use \"fossil info\" for more details."); |
| 1980 | 1980 | } |
| 1981 | 1981 | return nErr; |
| 1982 | 1982 | } |
| 1983 | 1983 | |
| 1984 | 1984 | ADDED test/contains-selector.test |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -1973,10 +1973,10 @@ | |
| 1973 | manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 1974 | content_enable_dephantomize(1); |
| 1975 | db_end_transaction(0); |
| 1976 | } |
| 1977 | if( (syncFlags & SYNC_CLONE)==0 && g.rcvid && fossil_any_has_fork(g.rcvid) ){ |
| 1978 | fossil_warning("***** WARNING: multiple leaves on the same branch are formed *****\n" |
| 1979 | "use \"fossil info\" for more details."); |
| 1980 | } |
| 1981 | return nErr; |
| 1982 | } |
| 1983 | |
| 1984 | DDED test/contains-selector.test |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -1973,10 +1973,10 @@ | |
| 1973 | manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 1974 | content_enable_dephantomize(1); |
| 1975 | db_end_transaction(0); |
| 1976 | } |
| 1977 | if( (syncFlags & SYNC_CLONE)==0 && g.rcvid && fossil_any_has_fork(g.rcvid) ){ |
| 1978 | fossil_warning("***** WARNING: a fork has occurred *****\n" |
| 1979 | "use \"fossil info\" for more details."); |
| 1980 | } |
| 1981 | return nErr; |
| 1982 | } |
| 1983 | |
| 1984 | DDED test/contains-selector.test |
+1
-1
| --- src/xfer.c | ||
| +++ src/xfer.c | ||
| @@ -1973,10 +1973,10 @@ | ||
| 1973 | 1973 | manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 1974 | 1974 | content_enable_dephantomize(1); |
| 1975 | 1975 | db_end_transaction(0); |
| 1976 | 1976 | } |
| 1977 | 1977 | if( (syncFlags & SYNC_CLONE)==0 && g.rcvid && fossil_any_has_fork(g.rcvid) ){ |
| 1978 | - fossil_warning("***** WARNING: multiple leaves on the same branch are formed *****\n" | |
| 1978 | + fossil_warning("***** WARNING: a fork has occurred *****\n" | |
| 1979 | 1979 | "use \"fossil info\" for more details."); |
| 1980 | 1980 | } |
| 1981 | 1981 | return nErr; |
| 1982 | 1982 | } |
| 1983 | 1983 | |
| 1984 | 1984 | ADDED test/contains-selector.test |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -1973,10 +1973,10 @@ | |
| 1973 | manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 1974 | content_enable_dephantomize(1); |
| 1975 | db_end_transaction(0); |
| 1976 | } |
| 1977 | if( (syncFlags & SYNC_CLONE)==0 && g.rcvid && fossil_any_has_fork(g.rcvid) ){ |
| 1978 | fossil_warning("***** WARNING: multiple leaves on the same branch are formed *****\n" |
| 1979 | "use \"fossil info\" for more details."); |
| 1980 | } |
| 1981 | return nErr; |
| 1982 | } |
| 1983 | |
| 1984 | DDED test/contains-selector.test |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -1973,10 +1973,10 @@ | |
| 1973 | manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 1974 | content_enable_dephantomize(1); |
| 1975 | db_end_transaction(0); |
| 1976 | } |
| 1977 | if( (syncFlags & SYNC_CLONE)==0 && g.rcvid && fossil_any_has_fork(g.rcvid) ){ |
| 1978 | fossil_warning("***** WARNING: a fork has occurred *****\n" |
| 1979 | "use \"fossil info\" for more details."); |
| 1980 | } |
| 1981 | return nErr; |
| 1982 | } |
| 1983 | |
| 1984 | DDED test/contains-selector.test |
| --- a/test/contains-selector.test | ||
| +++ b/test/contains-selector.test | ||
| @@ -0,0 +1,43 @@ | ||
| 1 | +# | |
| 2 | +# Copyright (c) 2015 D. Richard Hipp | |
| 3 | +# | |
| 4 | +# This program is free software; you can redistribute it and/or | |
| 5 | +# modify it under the terms of the Simplified BSD License (also | |
| 6 | +# known as the "2-Clause License" or "FreeBSD License".) | |
| 7 | +# | |
| 8 | +# This program is distributed in the hope that it will be useful, | |
| 9 | +# but without any warranty; without even the implied warranty of | |
| 10 | +# merchantability or fitness for a particular purpose. | |
| 11 | +# | |
| 12 | +# Author contact information: | |
| 13 | +# [email protected] | |
| 14 | +# http://www.hwaci.com/drh/ | |
| 15 | +# | |
| 16 | +############################################################################ | |
| 17 | +# | |
| 18 | +# Test containsSelector() proc contains-selector {testId css selectorResultMap} { | |
| 19 | + set css [string trim $css] | |
| 20 | + set filename [file join $::tempPath compare-selector.css] | |
| 21 | + set fh [open $filename w] | |
| 22 | + puts -nonewline $fh $css | |
| 23 | + close $fh | |
| 24 | + foreach {selector found} $selectorResultMap { | |
| 25 | + set expected "$selector [expr {$found ? "found" : "not found"}]" | |
| 26 | + set result [fossil test-contains-selector $filename $selector] | |
| 27 | + test "contains-selector $testId $selector" {$result eq $expected} | |
| 28 | + } | |
| 29 | + file delete $filename | |
| 30 | +} | |
| 31 | + | |
| 32 | +contains-selector 1 { | |
| 33 | + .a.b {} | |
| 34 | + .c .de {} | |
| 35 | + /* comment */ | |
| 36 | + .c .d, .e /* comment */ {} | |
| 37 | +} { | |
| 38 | + .a 0 | |
| 39 | + .b 0 | |
| 40 | + .a.b 1 | |
| 41 | + .c 0 | |
| 42 | + .d 0 | |
| 43 | + {.c |
| --- a/test/contains-selector.test | |
| +++ b/test/contains-selector.test | |
| @@ -0,0 +1,43 @@ | |
| --- a/test/contains-selector.test | |
| +++ b/test/contains-selector.test | |
| @@ -0,0 +1,43 @@ | |
| 1 | # |
| 2 | # Copyright (c) 2015 D. Richard Hipp |
| 3 | # |
| 4 | # This program is free software; you can redistribute it and/or |
| 5 | # modify it under the terms of the Simplified BSD License (also |
| 6 | # known as the "2-Clause License" or "FreeBSD License".) |
| 7 | # |
| 8 | # This program is distributed in the hope that it will be useful, |
| 9 | # but without any warranty; without even the implied warranty of |
| 10 | # merchantability or fitness for a particular purpose. |
| 11 | # |
| 12 | # Author contact information: |
| 13 | # [email protected] |
| 14 | # http://www.hwaci.com/drh/ |
| 15 | # |
| 16 | ############################################################################ |
| 17 | # |
| 18 | # Test containsSelector() proc contains-selector {testId css selectorResultMap} { |
| 19 | set css [string trim $css] |
| 20 | set filename [file join $::tempPath compare-selector.css] |
| 21 | set fh [open $filename w] |
| 22 | puts -nonewline $fh $css |
| 23 | close $fh |
| 24 | foreach {selector found} $selectorResultMap { |
| 25 | set expected "$selector [expr {$found ? "found" : "not found"}]" |
| 26 | set result [fossil test-contains-selector $filename $selector] |
| 27 | test "contains-selector $testId $selector" {$result eq $expected} |
| 28 | } |
| 29 | file delete $filename |
| 30 | } |
| 31 | |
| 32 | contains-selector 1 { |
| 33 | .a.b {} |
| 34 | .c .de {} |
| 35 | /* comment */ |
| 36 | .c .d, .e /* comment */ {} |
| 37 | } { |
| 38 | .a 0 |
| 39 | .b 0 |
| 40 | .a.b 1 |
| 41 | .c 0 |
| 42 | .d 0 |
| 43 | {.c |
+1
-1
| --- win/Makefile.PellesCGMake | ||
| +++ win/Makefile.PellesCGMake | ||
| @@ -83,11 +83,11 @@ | ||
| 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_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_WIN32_NO_ANSI | |
| 88 | +SQLITEDEFINES=-DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -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 | 94 |
| --- win/Makefile.PellesCGMake | |
| +++ win/Makefile.PellesCGMake | |
| @@ -83,11 +83,11 @@ | |
| 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_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -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 |
| --- win/Makefile.PellesCGMake | |
| +++ win/Makefile.PellesCGMake | |
| @@ -83,11 +83,11 @@ | |
| 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_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -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 |
+11
-5
| --- win/Makefile.dmc | ||
| +++ win/Makefile.dmc | ||
| @@ -24,17 +24,17 @@ | ||
| 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 |
| 28 | 28 | |
| 29 | -SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS | |
| 29 | +SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB | |
| 30 | 30 | |
| 31 | 31 | SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen |
| 32 | 32 | |
| 33 | -SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fusefs_.c glob_.c graph_.c gzip_.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 pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c | |
| 33 | +SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fusefs_.c glob_.c graph_.c gzip_.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 report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c | |
| 34 | 34 | |
| 35 | -OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$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)\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)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$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)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$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)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$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 | |
| 35 | +OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$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)\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)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$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)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$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)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$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 | |
| 38 | 38 | RC=$(DMDIR)\bin\rcc |
| 39 | 39 | RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ |
| 40 | 40 | |
| @@ -49,11 +49,11 @@ | ||
| 49 | 49 | |
| 50 | 50 | $(OBJDIR)\fossil.res: $B\win\fossil.rc |
| 51 | 51 | $(RC) $(RCFLAGS) -o$@ $** |
| 52 | 52 | |
| 53 | 53 | $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res |
| 54 | - +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo foci fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup sha1 shun sitemap skins sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ | |
| 54 | + +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo foci fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path piechart pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup sha1 shun sitemap skins sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ | |
| 55 | 55 | +echo fossil >> $@ |
| 56 | 56 | +echo fossil >> $@ |
| 57 | 57 | +echo $(LIBS) >> $@ |
| 58 | 58 | +echo. >> $@ |
| 59 | 59 | +echo fossil >> $@ |
| @@ -554,10 +554,16 @@ | ||
| 554 | 554 | $(OBJDIR)\path$O : path_.c path.h |
| 555 | 555 | $(TCC) -o$@ -c path_.c |
| 556 | 556 | |
| 557 | 557 | path_.c : $(SRCDIR)\path.c |
| 558 | 558 | +translate$E $** > $@ |
| 559 | + | |
| 560 | +$(OBJDIR)\piechart$O : piechart_.c piechart.h | |
| 561 | + $(TCC) -o$@ -c piechart_.c | |
| 562 | + | |
| 563 | +piechart_.c : $(SRCDIR)\piechart.c | |
| 564 | + +translate$E $** > $@ | |
| 559 | 565 | |
| 560 | 566 | $(OBJDIR)\pivot$O : pivot_.c pivot.h |
| 561 | 567 | $(TCC) -o$@ -c pivot_.c |
| 562 | 568 | |
| 563 | 569 | pivot_.c : $(SRCDIR)\pivot.c |
| @@ -832,7 +838,7 @@ | ||
| 832 | 838 | |
| 833 | 839 | zip_.c : $(SRCDIR)\zip.c |
| 834 | 840 | +translate$E $** > $@ |
| 835 | 841 | |
| 836 | 842 | headers: makeheaders$E page_index.h builtin_data.h VERSION.h |
| 837 | - +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h | |
| 843 | + +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h piechart_.c:piechart.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h | |
| 838 | 844 | @copy /Y nul: headers |
| 839 | 845 |
| --- win/Makefile.dmc | |
| +++ win/Makefile.dmc | |
| @@ -24,17 +24,17 @@ | |
| 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 |
| 28 | |
| 29 | SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS |
| 30 | |
| 31 | SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen |
| 32 | |
| 33 | SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fusefs_.c glob_.c graph_.c gzip_.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 pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c |
| 34 | |
| 35 | OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$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)\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)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$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)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$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)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$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 | |
| 38 | RC=$(DMDIR)\bin\rcc |
| 39 | RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ |
| 40 | |
| @@ -49,11 +49,11 @@ | |
| 49 | |
| 50 | $(OBJDIR)\fossil.res: $B\win\fossil.rc |
| 51 | $(RC) $(RCFLAGS) -o$@ $** |
| 52 | |
| 53 | $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res |
| 54 | +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo foci fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup sha1 shun sitemap skins sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ |
| 55 | +echo fossil >> $@ |
| 56 | +echo fossil >> $@ |
| 57 | +echo $(LIBS) >> $@ |
| 58 | +echo. >> $@ |
| 59 | +echo fossil >> $@ |
| @@ -554,10 +554,16 @@ | |
| 554 | $(OBJDIR)\path$O : path_.c path.h |
| 555 | $(TCC) -o$@ -c path_.c |
| 556 | |
| 557 | path_.c : $(SRCDIR)\path.c |
| 558 | +translate$E $** > $@ |
| 559 | |
| 560 | $(OBJDIR)\pivot$O : pivot_.c pivot.h |
| 561 | $(TCC) -o$@ -c pivot_.c |
| 562 | |
| 563 | pivot_.c : $(SRCDIR)\pivot.c |
| @@ -832,7 +838,7 @@ | |
| 832 | |
| 833 | zip_.c : $(SRCDIR)\zip.c |
| 834 | +translate$E $** > $@ |
| 835 | |
| 836 | headers: makeheaders$E page_index.h builtin_data.h VERSION.h |
| 837 | +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h |
| 838 | @copy /Y nul: headers |
| 839 |
| --- win/Makefile.dmc | |
| +++ win/Makefile.dmc | |
| @@ -24,17 +24,17 @@ | |
| 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 |
| 28 | |
| 29 | SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB |
| 30 | |
| 31 | SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen |
| 32 | |
| 33 | SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fusefs_.c glob_.c graph_.c gzip_.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 report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c |
| 34 | |
| 35 | OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$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)\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)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$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)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$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)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$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 | |
| 38 | RC=$(DMDIR)\bin\rcc |
| 39 | RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ |
| 40 | |
| @@ -49,11 +49,11 @@ | |
| 49 | |
| 50 | $(OBJDIR)\fossil.res: $B\win\fossil.rc |
| 51 | $(RC) $(RCFLAGS) -o$@ $** |
| 52 | |
| 53 | $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res |
| 54 | +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo foci fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path piechart pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup sha1 shun sitemap skins sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ |
| 55 | +echo fossil >> $@ |
| 56 | +echo fossil >> $@ |
| 57 | +echo $(LIBS) >> $@ |
| 58 | +echo. >> $@ |
| 59 | +echo fossil >> $@ |
| @@ -554,10 +554,16 @@ | |
| 554 | $(OBJDIR)\path$O : path_.c path.h |
| 555 | $(TCC) -o$@ -c path_.c |
| 556 | |
| 557 | path_.c : $(SRCDIR)\path.c |
| 558 | +translate$E $** > $@ |
| 559 | |
| 560 | $(OBJDIR)\piechart$O : piechart_.c piechart.h |
| 561 | $(TCC) -o$@ -c piechart_.c |
| 562 | |
| 563 | piechart_.c : $(SRCDIR)\piechart.c |
| 564 | +translate$E $** > $@ |
| 565 | |
| 566 | $(OBJDIR)\pivot$O : pivot_.c pivot.h |
| 567 | $(TCC) -o$@ -c pivot_.c |
| 568 | |
| 569 | pivot_.c : $(SRCDIR)\pivot.c |
| @@ -832,7 +838,7 @@ | |
| 838 | |
| 839 | zip_.c : $(SRCDIR)\zip.c |
| 840 | +translate$E $** > $@ |
| 841 | |
| 842 | headers: makeheaders$E page_index.h builtin_data.h VERSION.h |
| 843 | +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h piechart_.c:piechart.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h |
| 844 | @copy /Y nul: headers |
| 845 |
+13
| --- win/Makefile.mingw | ||
| +++ win/Makefile.mingw | ||
| @@ -447,10 +447,11 @@ | ||
| 447 | 447 | $(SRCDIR)/merge.c \ |
| 448 | 448 | $(SRCDIR)/merge3.c \ |
| 449 | 449 | $(SRCDIR)/moderate.c \ |
| 450 | 450 | $(SRCDIR)/name.c \ |
| 451 | 451 | $(SRCDIR)/path.c \ |
| 452 | + $(SRCDIR)/piechart.c \ | |
| 452 | 453 | $(SRCDIR)/pivot.c \ |
| 453 | 454 | $(SRCDIR)/popen.c \ |
| 454 | 455 | $(SRCDIR)/pqueue.c \ |
| 455 | 456 | $(SRCDIR)/printf.c \ |
| 456 | 457 | $(SRCDIR)/publish.c \ |
| @@ -618,10 +619,11 @@ | ||
| 618 | 619 | $(OBJDIR)/merge_.c \ |
| 619 | 620 | $(OBJDIR)/merge3_.c \ |
| 620 | 621 | $(OBJDIR)/moderate_.c \ |
| 621 | 622 | $(OBJDIR)/name_.c \ |
| 622 | 623 | $(OBJDIR)/path_.c \ |
| 624 | + $(OBJDIR)/piechart_.c \ | |
| 623 | 625 | $(OBJDIR)/pivot_.c \ |
| 624 | 626 | $(OBJDIR)/popen_.c \ |
| 625 | 627 | $(OBJDIR)/pqueue_.c \ |
| 626 | 628 | $(OBJDIR)/printf_.c \ |
| 627 | 629 | $(OBJDIR)/publish_.c \ |
| @@ -738,10 +740,11 @@ | ||
| 738 | 740 | $(OBJDIR)/merge.o \ |
| 739 | 741 | $(OBJDIR)/merge3.o \ |
| 740 | 742 | $(OBJDIR)/moderate.o \ |
| 741 | 743 | $(OBJDIR)/name.o \ |
| 742 | 744 | $(OBJDIR)/path.o \ |
| 745 | + $(OBJDIR)/piechart.o \ | |
| 743 | 746 | $(OBJDIR)/pivot.o \ |
| 744 | 747 | $(OBJDIR)/popen.o \ |
| 745 | 748 | $(OBJDIR)/pqueue.o \ |
| 746 | 749 | $(OBJDIR)/printf.o \ |
| 747 | 750 | $(OBJDIR)/publish.o \ |
| @@ -1051,10 +1054,11 @@ | ||
| 1051 | 1054 | $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \ |
| 1052 | 1055 | $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \ |
| 1053 | 1056 | $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \ |
| 1054 | 1057 | $(OBJDIR)/name_.c:$(OBJDIR)/name.h \ |
| 1055 | 1058 | $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ |
| 1059 | + $(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \ | |
| 1056 | 1060 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 1057 | 1061 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 1058 | 1062 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 1059 | 1063 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 1060 | 1064 | $(OBJDIR)/publish_.c:$(OBJDIR)/publish.h \ |
| @@ -1681,10 +1685,18 @@ | ||
| 1681 | 1685 | |
| 1682 | 1686 | $(OBJDIR)/path.o: $(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h |
| 1683 | 1687 | $(XTCC) -o $(OBJDIR)/path.o -c $(OBJDIR)/path_.c |
| 1684 | 1688 | |
| 1685 | 1689 | $(OBJDIR)/path.h: $(OBJDIR)/headers |
| 1690 | + | |
| 1691 | +$(OBJDIR)/piechart_.c: $(SRCDIR)/piechart.c $(TRANSLATE) | |
| 1692 | + $(TRANSLATE) $(SRCDIR)/piechart.c >$@ | |
| 1693 | + | |
| 1694 | +$(OBJDIR)/piechart.o: $(OBJDIR)/piechart_.c $(OBJDIR)/piechart.h $(SRCDIR)/config.h | |
| 1695 | + $(XTCC) -o $(OBJDIR)/piechart.o -c $(OBJDIR)/piechart_.c | |
| 1696 | + | |
| 1697 | +$(OBJDIR)/piechart.h: $(OBJDIR)/headers | |
| 1686 | 1698 | |
| 1687 | 1699 | $(OBJDIR)/pivot_.c: $(SRCDIR)/pivot.c $(TRANSLATE) |
| 1688 | 1700 | $(TRANSLATE) $(SRCDIR)/pivot.c >$@ |
| 1689 | 1701 | |
| 1690 | 1702 | $(OBJDIR)/pivot.o: $(OBJDIR)/pivot_.c $(OBJDIR)/pivot.h $(SRCDIR)/config.h |
| @@ -2059,10 +2071,11 @@ | ||
| 2059 | 2071 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 2060 | 2072 | -DSQLITE_OMIT_DEPRECATED \ |
| 2061 | 2073 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 2062 | 2074 | -DSQLITE_ENABLE_FTS4 \ |
| 2063 | 2075 | -DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 2076 | + -DSQLITE_ENABLE_DBSTAT_VTAB \ | |
| 2064 | 2077 | -DSQLITE_WIN32_NO_ANSI \ |
| 2065 | 2078 | -D_HAVE__MINGW_H \ |
| 2066 | 2079 | -DSQLITE_USE_MALLOC_H \ |
| 2067 | 2080 | -DSQLITE_USE_MSIZE |
| 2068 | 2081 | |
| 2069 | 2082 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -447,10 +447,11 @@ | |
| 447 | $(SRCDIR)/merge.c \ |
| 448 | $(SRCDIR)/merge3.c \ |
| 449 | $(SRCDIR)/moderate.c \ |
| 450 | $(SRCDIR)/name.c \ |
| 451 | $(SRCDIR)/path.c \ |
| 452 | $(SRCDIR)/pivot.c \ |
| 453 | $(SRCDIR)/popen.c \ |
| 454 | $(SRCDIR)/pqueue.c \ |
| 455 | $(SRCDIR)/printf.c \ |
| 456 | $(SRCDIR)/publish.c \ |
| @@ -618,10 +619,11 @@ | |
| 618 | $(OBJDIR)/merge_.c \ |
| 619 | $(OBJDIR)/merge3_.c \ |
| 620 | $(OBJDIR)/moderate_.c \ |
| 621 | $(OBJDIR)/name_.c \ |
| 622 | $(OBJDIR)/path_.c \ |
| 623 | $(OBJDIR)/pivot_.c \ |
| 624 | $(OBJDIR)/popen_.c \ |
| 625 | $(OBJDIR)/pqueue_.c \ |
| 626 | $(OBJDIR)/printf_.c \ |
| 627 | $(OBJDIR)/publish_.c \ |
| @@ -738,10 +740,11 @@ | |
| 738 | $(OBJDIR)/merge.o \ |
| 739 | $(OBJDIR)/merge3.o \ |
| 740 | $(OBJDIR)/moderate.o \ |
| 741 | $(OBJDIR)/name.o \ |
| 742 | $(OBJDIR)/path.o \ |
| 743 | $(OBJDIR)/pivot.o \ |
| 744 | $(OBJDIR)/popen.o \ |
| 745 | $(OBJDIR)/pqueue.o \ |
| 746 | $(OBJDIR)/printf.o \ |
| 747 | $(OBJDIR)/publish.o \ |
| @@ -1051,10 +1054,11 @@ | |
| 1051 | $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \ |
| 1052 | $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \ |
| 1053 | $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \ |
| 1054 | $(OBJDIR)/name_.c:$(OBJDIR)/name.h \ |
| 1055 | $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ |
| 1056 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 1057 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 1058 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 1059 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 1060 | $(OBJDIR)/publish_.c:$(OBJDIR)/publish.h \ |
| @@ -1681,10 +1685,18 @@ | |
| 1681 | |
| 1682 | $(OBJDIR)/path.o: $(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h |
| 1683 | $(XTCC) -o $(OBJDIR)/path.o -c $(OBJDIR)/path_.c |
| 1684 | |
| 1685 | $(OBJDIR)/path.h: $(OBJDIR)/headers |
| 1686 | |
| 1687 | $(OBJDIR)/pivot_.c: $(SRCDIR)/pivot.c $(TRANSLATE) |
| 1688 | $(TRANSLATE) $(SRCDIR)/pivot.c >$@ |
| 1689 | |
| 1690 | $(OBJDIR)/pivot.o: $(OBJDIR)/pivot_.c $(OBJDIR)/pivot.h $(SRCDIR)/config.h |
| @@ -2059,10 +2071,11 @@ | |
| 2059 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 2060 | -DSQLITE_OMIT_DEPRECATED \ |
| 2061 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 2062 | -DSQLITE_ENABLE_FTS4 \ |
| 2063 | -DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 2064 | -DSQLITE_WIN32_NO_ANSI \ |
| 2065 | -D_HAVE__MINGW_H \ |
| 2066 | -DSQLITE_USE_MALLOC_H \ |
| 2067 | -DSQLITE_USE_MSIZE |
| 2068 | |
| 2069 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -447,10 +447,11 @@ | |
| 447 | $(SRCDIR)/merge.c \ |
| 448 | $(SRCDIR)/merge3.c \ |
| 449 | $(SRCDIR)/moderate.c \ |
| 450 | $(SRCDIR)/name.c \ |
| 451 | $(SRCDIR)/path.c \ |
| 452 | $(SRCDIR)/piechart.c \ |
| 453 | $(SRCDIR)/pivot.c \ |
| 454 | $(SRCDIR)/popen.c \ |
| 455 | $(SRCDIR)/pqueue.c \ |
| 456 | $(SRCDIR)/printf.c \ |
| 457 | $(SRCDIR)/publish.c \ |
| @@ -618,10 +619,11 @@ | |
| 619 | $(OBJDIR)/merge_.c \ |
| 620 | $(OBJDIR)/merge3_.c \ |
| 621 | $(OBJDIR)/moderate_.c \ |
| 622 | $(OBJDIR)/name_.c \ |
| 623 | $(OBJDIR)/path_.c \ |
| 624 | $(OBJDIR)/piechart_.c \ |
| 625 | $(OBJDIR)/pivot_.c \ |
| 626 | $(OBJDIR)/popen_.c \ |
| 627 | $(OBJDIR)/pqueue_.c \ |
| 628 | $(OBJDIR)/printf_.c \ |
| 629 | $(OBJDIR)/publish_.c \ |
| @@ -738,10 +740,11 @@ | |
| 740 | $(OBJDIR)/merge.o \ |
| 741 | $(OBJDIR)/merge3.o \ |
| 742 | $(OBJDIR)/moderate.o \ |
| 743 | $(OBJDIR)/name.o \ |
| 744 | $(OBJDIR)/path.o \ |
| 745 | $(OBJDIR)/piechart.o \ |
| 746 | $(OBJDIR)/pivot.o \ |
| 747 | $(OBJDIR)/popen.o \ |
| 748 | $(OBJDIR)/pqueue.o \ |
| 749 | $(OBJDIR)/printf.o \ |
| 750 | $(OBJDIR)/publish.o \ |
| @@ -1051,10 +1054,11 @@ | |
| 1054 | $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \ |
| 1055 | $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \ |
| 1056 | $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \ |
| 1057 | $(OBJDIR)/name_.c:$(OBJDIR)/name.h \ |
| 1058 | $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ |
| 1059 | $(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \ |
| 1060 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 1061 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 1062 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 1063 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 1064 | $(OBJDIR)/publish_.c:$(OBJDIR)/publish.h \ |
| @@ -1681,10 +1685,18 @@ | |
| 1685 | |
| 1686 | $(OBJDIR)/path.o: $(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h |
| 1687 | $(XTCC) -o $(OBJDIR)/path.o -c $(OBJDIR)/path_.c |
| 1688 | |
| 1689 | $(OBJDIR)/path.h: $(OBJDIR)/headers |
| 1690 | |
| 1691 | $(OBJDIR)/piechart_.c: $(SRCDIR)/piechart.c $(TRANSLATE) |
| 1692 | $(TRANSLATE) $(SRCDIR)/piechart.c >$@ |
| 1693 | |
| 1694 | $(OBJDIR)/piechart.o: $(OBJDIR)/piechart_.c $(OBJDIR)/piechart.h $(SRCDIR)/config.h |
| 1695 | $(XTCC) -o $(OBJDIR)/piechart.o -c $(OBJDIR)/piechart_.c |
| 1696 | |
| 1697 | $(OBJDIR)/piechart.h: $(OBJDIR)/headers |
| 1698 | |
| 1699 | $(OBJDIR)/pivot_.c: $(SRCDIR)/pivot.c $(TRANSLATE) |
| 1700 | $(TRANSLATE) $(SRCDIR)/pivot.c >$@ |
| 1701 | |
| 1702 | $(OBJDIR)/pivot.o: $(OBJDIR)/pivot_.c $(OBJDIR)/pivot.h $(SRCDIR)/config.h |
| @@ -2059,10 +2071,11 @@ | |
| 2071 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 2072 | -DSQLITE_OMIT_DEPRECATED \ |
| 2073 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 2074 | -DSQLITE_ENABLE_FTS4 \ |
| 2075 | -DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 2076 | -DSQLITE_ENABLE_DBSTAT_VTAB \ |
| 2077 | -DSQLITE_WIN32_NO_ANSI \ |
| 2078 | -D_HAVE__MINGW_H \ |
| 2079 | -DSQLITE_USE_MALLOC_H \ |
| 2080 | -DSQLITE_USE_MSIZE |
| 2081 | |
| 2082 |
| --- win/Makefile.mingw.mistachkin | ||
| +++ win/Makefile.mingw.mistachkin | ||
| @@ -447,10 +447,11 @@ | ||
| 447 | 447 | $(SRCDIR)/merge.c \ |
| 448 | 448 | $(SRCDIR)/merge3.c \ |
| 449 | 449 | $(SRCDIR)/moderate.c \ |
| 450 | 450 | $(SRCDIR)/name.c \ |
| 451 | 451 | $(SRCDIR)/path.c \ |
| 452 | + $(SRCDIR)/piechart.c \ | |
| 452 | 453 | $(SRCDIR)/pivot.c \ |
| 453 | 454 | $(SRCDIR)/popen.c \ |
| 454 | 455 | $(SRCDIR)/pqueue.c \ |
| 455 | 456 | $(SRCDIR)/printf.c \ |
| 456 | 457 | $(SRCDIR)/publish.c \ |
| @@ -618,10 +619,11 @@ | ||
| 618 | 619 | $(OBJDIR)/merge_.c \ |
| 619 | 620 | $(OBJDIR)/merge3_.c \ |
| 620 | 621 | $(OBJDIR)/moderate_.c \ |
| 621 | 622 | $(OBJDIR)/name_.c \ |
| 622 | 623 | $(OBJDIR)/path_.c \ |
| 624 | + $(OBJDIR)/piechart_.c \ | |
| 623 | 625 | $(OBJDIR)/pivot_.c \ |
| 624 | 626 | $(OBJDIR)/popen_.c \ |
| 625 | 627 | $(OBJDIR)/pqueue_.c \ |
| 626 | 628 | $(OBJDIR)/printf_.c \ |
| 627 | 629 | $(OBJDIR)/publish_.c \ |
| @@ -738,10 +740,11 @@ | ||
| 738 | 740 | $(OBJDIR)/merge.o \ |
| 739 | 741 | $(OBJDIR)/merge3.o \ |
| 740 | 742 | $(OBJDIR)/moderate.o \ |
| 741 | 743 | $(OBJDIR)/name.o \ |
| 742 | 744 | $(OBJDIR)/path.o \ |
| 745 | + $(OBJDIR)/piechart.o \ | |
| 743 | 746 | $(OBJDIR)/pivot.o \ |
| 744 | 747 | $(OBJDIR)/popen.o \ |
| 745 | 748 | $(OBJDIR)/pqueue.o \ |
| 746 | 749 | $(OBJDIR)/printf.o \ |
| 747 | 750 | $(OBJDIR)/publish.o \ |
| @@ -1051,10 +1054,11 @@ | ||
| 1051 | 1054 | $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \ |
| 1052 | 1055 | $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \ |
| 1053 | 1056 | $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \ |
| 1054 | 1057 | $(OBJDIR)/name_.c:$(OBJDIR)/name.h \ |
| 1055 | 1058 | $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ |
| 1059 | + $(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \ | |
| 1056 | 1060 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 1057 | 1061 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 1058 | 1062 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 1059 | 1063 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 1060 | 1064 | $(OBJDIR)/publish_.c:$(OBJDIR)/publish.h \ |
| @@ -1681,10 +1685,18 @@ | ||
| 1681 | 1685 | |
| 1682 | 1686 | $(OBJDIR)/path.o: $(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h |
| 1683 | 1687 | $(XTCC) -o $(OBJDIR)/path.o -c $(OBJDIR)/path_.c |
| 1684 | 1688 | |
| 1685 | 1689 | $(OBJDIR)/path.h: $(OBJDIR)/headers |
| 1690 | + | |
| 1691 | +$(OBJDIR)/piechart_.c: $(SRCDIR)/piechart.c $(TRANSLATE) | |
| 1692 | + $(TRANSLATE) $(SRCDIR)/piechart.c >$@ | |
| 1693 | + | |
| 1694 | +$(OBJDIR)/piechart.o: $(OBJDIR)/piechart_.c $(OBJDIR)/piechart.h $(SRCDIR)/config.h | |
| 1695 | + $(XTCC) -o $(OBJDIR)/piechart.o -c $(OBJDIR)/piechart_.c | |
| 1696 | + | |
| 1697 | +$(OBJDIR)/piechart.h: $(OBJDIR)/headers | |
| 1686 | 1698 | |
| 1687 | 1699 | $(OBJDIR)/pivot_.c: $(SRCDIR)/pivot.c $(TRANSLATE) |
| 1688 | 1700 | $(TRANSLATE) $(SRCDIR)/pivot.c >$@ |
| 1689 | 1701 | |
| 1690 | 1702 | $(OBJDIR)/pivot.o: $(OBJDIR)/pivot_.c $(OBJDIR)/pivot.h $(SRCDIR)/config.h |
| @@ -2059,10 +2071,11 @@ | ||
| 2059 | 2071 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 2060 | 2072 | -DSQLITE_OMIT_DEPRECATED \ |
| 2061 | 2073 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 2062 | 2074 | -DSQLITE_ENABLE_FTS4 \ |
| 2063 | 2075 | -DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 2076 | + -DSQLITE_ENABLE_DBSTAT_VTAB \ | |
| 2064 | 2077 | -DSQLITE_WIN32_NO_ANSI \ |
| 2065 | 2078 | -D_HAVE__MINGW_H \ |
| 2066 | 2079 | -DSQLITE_USE_MALLOC_H \ |
| 2067 | 2080 | -DSQLITE_USE_MSIZE |
| 2068 | 2081 | |
| 2069 | 2082 |
| --- win/Makefile.mingw.mistachkin | |
| +++ win/Makefile.mingw.mistachkin | |
| @@ -447,10 +447,11 @@ | |
| 447 | $(SRCDIR)/merge.c \ |
| 448 | $(SRCDIR)/merge3.c \ |
| 449 | $(SRCDIR)/moderate.c \ |
| 450 | $(SRCDIR)/name.c \ |
| 451 | $(SRCDIR)/path.c \ |
| 452 | $(SRCDIR)/pivot.c \ |
| 453 | $(SRCDIR)/popen.c \ |
| 454 | $(SRCDIR)/pqueue.c \ |
| 455 | $(SRCDIR)/printf.c \ |
| 456 | $(SRCDIR)/publish.c \ |
| @@ -618,10 +619,11 @@ | |
| 618 | $(OBJDIR)/merge_.c \ |
| 619 | $(OBJDIR)/merge3_.c \ |
| 620 | $(OBJDIR)/moderate_.c \ |
| 621 | $(OBJDIR)/name_.c \ |
| 622 | $(OBJDIR)/path_.c \ |
| 623 | $(OBJDIR)/pivot_.c \ |
| 624 | $(OBJDIR)/popen_.c \ |
| 625 | $(OBJDIR)/pqueue_.c \ |
| 626 | $(OBJDIR)/printf_.c \ |
| 627 | $(OBJDIR)/publish_.c \ |
| @@ -738,10 +740,11 @@ | |
| 738 | $(OBJDIR)/merge.o \ |
| 739 | $(OBJDIR)/merge3.o \ |
| 740 | $(OBJDIR)/moderate.o \ |
| 741 | $(OBJDIR)/name.o \ |
| 742 | $(OBJDIR)/path.o \ |
| 743 | $(OBJDIR)/pivot.o \ |
| 744 | $(OBJDIR)/popen.o \ |
| 745 | $(OBJDIR)/pqueue.o \ |
| 746 | $(OBJDIR)/printf.o \ |
| 747 | $(OBJDIR)/publish.o \ |
| @@ -1051,10 +1054,11 @@ | |
| 1051 | $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \ |
| 1052 | $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \ |
| 1053 | $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \ |
| 1054 | $(OBJDIR)/name_.c:$(OBJDIR)/name.h \ |
| 1055 | $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ |
| 1056 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 1057 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 1058 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 1059 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 1060 | $(OBJDIR)/publish_.c:$(OBJDIR)/publish.h \ |
| @@ -1681,10 +1685,18 @@ | |
| 1681 | |
| 1682 | $(OBJDIR)/path.o: $(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h |
| 1683 | $(XTCC) -o $(OBJDIR)/path.o -c $(OBJDIR)/path_.c |
| 1684 | |
| 1685 | $(OBJDIR)/path.h: $(OBJDIR)/headers |
| 1686 | |
| 1687 | $(OBJDIR)/pivot_.c: $(SRCDIR)/pivot.c $(TRANSLATE) |
| 1688 | $(TRANSLATE) $(SRCDIR)/pivot.c >$@ |
| 1689 | |
| 1690 | $(OBJDIR)/pivot.o: $(OBJDIR)/pivot_.c $(OBJDIR)/pivot.h $(SRCDIR)/config.h |
| @@ -2059,10 +2071,11 @@ | |
| 2059 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 2060 | -DSQLITE_OMIT_DEPRECATED \ |
| 2061 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 2062 | -DSQLITE_ENABLE_FTS4 \ |
| 2063 | -DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 2064 | -DSQLITE_WIN32_NO_ANSI \ |
| 2065 | -D_HAVE__MINGW_H \ |
| 2066 | -DSQLITE_USE_MALLOC_H \ |
| 2067 | -DSQLITE_USE_MSIZE |
| 2068 | |
| 2069 |
| --- win/Makefile.mingw.mistachkin | |
| +++ win/Makefile.mingw.mistachkin | |
| @@ -447,10 +447,11 @@ | |
| 447 | $(SRCDIR)/merge.c \ |
| 448 | $(SRCDIR)/merge3.c \ |
| 449 | $(SRCDIR)/moderate.c \ |
| 450 | $(SRCDIR)/name.c \ |
| 451 | $(SRCDIR)/path.c \ |
| 452 | $(SRCDIR)/piechart.c \ |
| 453 | $(SRCDIR)/pivot.c \ |
| 454 | $(SRCDIR)/popen.c \ |
| 455 | $(SRCDIR)/pqueue.c \ |
| 456 | $(SRCDIR)/printf.c \ |
| 457 | $(SRCDIR)/publish.c \ |
| @@ -618,10 +619,11 @@ | |
| 619 | $(OBJDIR)/merge_.c \ |
| 620 | $(OBJDIR)/merge3_.c \ |
| 621 | $(OBJDIR)/moderate_.c \ |
| 622 | $(OBJDIR)/name_.c \ |
| 623 | $(OBJDIR)/path_.c \ |
| 624 | $(OBJDIR)/piechart_.c \ |
| 625 | $(OBJDIR)/pivot_.c \ |
| 626 | $(OBJDIR)/popen_.c \ |
| 627 | $(OBJDIR)/pqueue_.c \ |
| 628 | $(OBJDIR)/printf_.c \ |
| 629 | $(OBJDIR)/publish_.c \ |
| @@ -738,10 +740,11 @@ | |
| 740 | $(OBJDIR)/merge.o \ |
| 741 | $(OBJDIR)/merge3.o \ |
| 742 | $(OBJDIR)/moderate.o \ |
| 743 | $(OBJDIR)/name.o \ |
| 744 | $(OBJDIR)/path.o \ |
| 745 | $(OBJDIR)/piechart.o \ |
| 746 | $(OBJDIR)/pivot.o \ |
| 747 | $(OBJDIR)/popen.o \ |
| 748 | $(OBJDIR)/pqueue.o \ |
| 749 | $(OBJDIR)/printf.o \ |
| 750 | $(OBJDIR)/publish.o \ |
| @@ -1051,10 +1054,11 @@ | |
| 1054 | $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \ |
| 1055 | $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \ |
| 1056 | $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \ |
| 1057 | $(OBJDIR)/name_.c:$(OBJDIR)/name.h \ |
| 1058 | $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ |
| 1059 | $(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \ |
| 1060 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 1061 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 1062 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 1063 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 1064 | $(OBJDIR)/publish_.c:$(OBJDIR)/publish.h \ |
| @@ -1681,10 +1685,18 @@ | |
| 1685 | |
| 1686 | $(OBJDIR)/path.o: $(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h |
| 1687 | $(XTCC) -o $(OBJDIR)/path.o -c $(OBJDIR)/path_.c |
| 1688 | |
| 1689 | $(OBJDIR)/path.h: $(OBJDIR)/headers |
| 1690 | |
| 1691 | $(OBJDIR)/piechart_.c: $(SRCDIR)/piechart.c $(TRANSLATE) |
| 1692 | $(TRANSLATE) $(SRCDIR)/piechart.c >$@ |
| 1693 | |
| 1694 | $(OBJDIR)/piechart.o: $(OBJDIR)/piechart_.c $(OBJDIR)/piechart.h $(SRCDIR)/config.h |
| 1695 | $(XTCC) -o $(OBJDIR)/piechart.o -c $(OBJDIR)/piechart_.c |
| 1696 | |
| 1697 | $(OBJDIR)/piechart.h: $(OBJDIR)/headers |
| 1698 | |
| 1699 | $(OBJDIR)/pivot_.c: $(SRCDIR)/pivot.c $(TRANSLATE) |
| 1700 | $(TRANSLATE) $(SRCDIR)/pivot.c >$@ |
| 1701 | |
| 1702 | $(OBJDIR)/pivot.o: $(OBJDIR)/pivot_.c $(OBJDIR)/pivot.h $(SRCDIR)/config.h |
| @@ -2059,10 +2071,11 @@ | |
| 2071 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 2072 | -DSQLITE_OMIT_DEPRECATED \ |
| 2073 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 2074 | -DSQLITE_ENABLE_FTS4 \ |
| 2075 | -DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 2076 | -DSQLITE_ENABLE_DBSTAT_VTAB \ |
| 2077 | -DSQLITE_WIN32_NO_ANSI \ |
| 2078 | -D_HAVE__MINGW_H \ |
| 2079 | -DSQLITE_USE_MALLOC_H \ |
| 2080 | -DSQLITE_USE_MSIZE |
| 2081 | |
| 2082 |
+11
| --- win/Makefile.msc | ||
| +++ win/Makefile.msc | ||
| @@ -199,10 +199,11 @@ | ||
| 199 | 199 | /DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 200 | 200 | /DSQLITE_OMIT_DEPRECATED \ |
| 201 | 201 | /DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 202 | 202 | /DSQLITE_ENABLE_FTS4 \ |
| 203 | 203 | /DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 204 | + /DSQLITE_ENABLE_DBSTAT_VTAB \ | |
| 204 | 205 | /DSQLITE_WIN32_NO_ANSI |
| 205 | 206 | |
| 206 | 207 | SHELL_OPTIONS = /Dmain=sqlite3_shell \ |
| 207 | 208 | /DSQLITE_OMIT_LOAD_EXTENSION=1 \ |
| 208 | 209 | /DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \ |
| @@ -286,10 +287,11 @@ | ||
| 286 | 287 | merge_.c \ |
| 287 | 288 | merge3_.c \ |
| 288 | 289 | moderate_.c \ |
| 289 | 290 | name_.c \ |
| 290 | 291 | path_.c \ |
| 292 | + piechart_.c \ | |
| 291 | 293 | pivot_.c \ |
| 292 | 294 | popen_.c \ |
| 293 | 295 | pqueue_.c \ |
| 294 | 296 | printf_.c \ |
| 295 | 297 | publish_.c \ |
| @@ -456,10 +458,11 @@ | ||
| 456 | 458 | $(OX)\merge$O \ |
| 457 | 459 | $(OX)\merge3$O \ |
| 458 | 460 | $(OX)\moderate$O \ |
| 459 | 461 | $(OX)\name$O \ |
| 460 | 462 | $(OX)\path$O \ |
| 463 | + $(OX)\piechart$O \ | |
| 461 | 464 | $(OX)\pivot$O \ |
| 462 | 465 | $(OX)\popen$O \ |
| 463 | 466 | $(OX)\pqueue$O \ |
| 464 | 467 | $(OX)\printf$O \ |
| 465 | 468 | $(OX)\publish$O \ |
| @@ -631,10 +634,11 @@ | ||
| 631 | 634 | echo $(OX)\merge.obj >> $@ |
| 632 | 635 | echo $(OX)\merge3.obj >> $@ |
| 633 | 636 | echo $(OX)\moderate.obj >> $@ |
| 634 | 637 | echo $(OX)\name.obj >> $@ |
| 635 | 638 | echo $(OX)\path.obj >> $@ |
| 639 | + echo $(OX)\piechart.obj >> $@ | |
| 636 | 640 | echo $(OX)\pivot.obj >> $@ |
| 637 | 641 | echo $(OX)\popen.obj >> $@ |
| 638 | 642 | echo $(OX)\pqueue.obj >> $@ |
| 639 | 643 | echo $(OX)\printf.obj >> $@ |
| 640 | 644 | echo $(OX)\publish.obj >> $@ |
| @@ -1212,10 +1216,16 @@ | ||
| 1212 | 1216 | $(OX)\path$O : path_.c path.h |
| 1213 | 1217 | $(TCC) /Fo$@ -c path_.c |
| 1214 | 1218 | |
| 1215 | 1219 | path_.c : $(SRCDIR)\path.c |
| 1216 | 1220 | translate$E $** > $@ |
| 1221 | + | |
| 1222 | +$(OX)\piechart$O : piechart_.c piechart.h | |
| 1223 | + $(TCC) /Fo$@ -c piechart_.c | |
| 1224 | + | |
| 1225 | +piechart_.c : $(SRCDIR)\piechart.c | |
| 1226 | + translate$E $** > $@ | |
| 1217 | 1227 | |
| 1218 | 1228 | $(OX)\pivot$O : pivot_.c pivot.h |
| 1219 | 1229 | $(TCC) /Fo$@ -c pivot_.c |
| 1220 | 1230 | |
| 1221 | 1231 | pivot_.c : $(SRCDIR)\pivot.c |
| @@ -1565,10 +1575,11 @@ | ||
| 1565 | 1575 | merge_.c:merge.h \ |
| 1566 | 1576 | merge3_.c:merge3.h \ |
| 1567 | 1577 | moderate_.c:moderate.h \ |
| 1568 | 1578 | name_.c:name.h \ |
| 1569 | 1579 | path_.c:path.h \ |
| 1580 | + piechart_.c:piechart.h \ | |
| 1570 | 1581 | pivot_.c:pivot.h \ |
| 1571 | 1582 | popen_.c:popen.h \ |
| 1572 | 1583 | pqueue_.c:pqueue.h \ |
| 1573 | 1584 | printf_.c:printf.h \ |
| 1574 | 1585 | publish_.c:publish.h \ |
| 1575 | 1586 |
| --- win/Makefile.msc | |
| +++ win/Makefile.msc | |
| @@ -199,10 +199,11 @@ | |
| 199 | /DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 200 | /DSQLITE_OMIT_DEPRECATED \ |
| 201 | /DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 202 | /DSQLITE_ENABLE_FTS4 \ |
| 203 | /DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 204 | /DSQLITE_WIN32_NO_ANSI |
| 205 | |
| 206 | SHELL_OPTIONS = /Dmain=sqlite3_shell \ |
| 207 | /DSQLITE_OMIT_LOAD_EXTENSION=1 \ |
| 208 | /DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \ |
| @@ -286,10 +287,11 @@ | |
| 286 | merge_.c \ |
| 287 | merge3_.c \ |
| 288 | moderate_.c \ |
| 289 | name_.c \ |
| 290 | path_.c \ |
| 291 | pivot_.c \ |
| 292 | popen_.c \ |
| 293 | pqueue_.c \ |
| 294 | printf_.c \ |
| 295 | publish_.c \ |
| @@ -456,10 +458,11 @@ | |
| 456 | $(OX)\merge$O \ |
| 457 | $(OX)\merge3$O \ |
| 458 | $(OX)\moderate$O \ |
| 459 | $(OX)\name$O \ |
| 460 | $(OX)\path$O \ |
| 461 | $(OX)\pivot$O \ |
| 462 | $(OX)\popen$O \ |
| 463 | $(OX)\pqueue$O \ |
| 464 | $(OX)\printf$O \ |
| 465 | $(OX)\publish$O \ |
| @@ -631,10 +634,11 @@ | |
| 631 | echo $(OX)\merge.obj >> $@ |
| 632 | echo $(OX)\merge3.obj >> $@ |
| 633 | echo $(OX)\moderate.obj >> $@ |
| 634 | echo $(OX)\name.obj >> $@ |
| 635 | echo $(OX)\path.obj >> $@ |
| 636 | echo $(OX)\pivot.obj >> $@ |
| 637 | echo $(OX)\popen.obj >> $@ |
| 638 | echo $(OX)\pqueue.obj >> $@ |
| 639 | echo $(OX)\printf.obj >> $@ |
| 640 | echo $(OX)\publish.obj >> $@ |
| @@ -1212,10 +1216,16 @@ | |
| 1212 | $(OX)\path$O : path_.c path.h |
| 1213 | $(TCC) /Fo$@ -c path_.c |
| 1214 | |
| 1215 | path_.c : $(SRCDIR)\path.c |
| 1216 | translate$E $** > $@ |
| 1217 | |
| 1218 | $(OX)\pivot$O : pivot_.c pivot.h |
| 1219 | $(TCC) /Fo$@ -c pivot_.c |
| 1220 | |
| 1221 | pivot_.c : $(SRCDIR)\pivot.c |
| @@ -1565,10 +1575,11 @@ | |
| 1565 | merge_.c:merge.h \ |
| 1566 | merge3_.c:merge3.h \ |
| 1567 | moderate_.c:moderate.h \ |
| 1568 | name_.c:name.h \ |
| 1569 | path_.c:path.h \ |
| 1570 | pivot_.c:pivot.h \ |
| 1571 | popen_.c:popen.h \ |
| 1572 | pqueue_.c:pqueue.h \ |
| 1573 | printf_.c:printf.h \ |
| 1574 | publish_.c:publish.h \ |
| 1575 |
| --- win/Makefile.msc | |
| +++ win/Makefile.msc | |
| @@ -199,10 +199,11 @@ | |
| 199 | /DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 200 | /DSQLITE_OMIT_DEPRECATED \ |
| 201 | /DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 202 | /DSQLITE_ENABLE_FTS4 \ |
| 203 | /DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 204 | /DSQLITE_ENABLE_DBSTAT_VTAB \ |
| 205 | /DSQLITE_WIN32_NO_ANSI |
| 206 | |
| 207 | SHELL_OPTIONS = /Dmain=sqlite3_shell \ |
| 208 | /DSQLITE_OMIT_LOAD_EXTENSION=1 \ |
| 209 | /DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \ |
| @@ -286,10 +287,11 @@ | |
| 287 | merge_.c \ |
| 288 | merge3_.c \ |
| 289 | moderate_.c \ |
| 290 | name_.c \ |
| 291 | path_.c \ |
| 292 | piechart_.c \ |
| 293 | pivot_.c \ |
| 294 | popen_.c \ |
| 295 | pqueue_.c \ |
| 296 | printf_.c \ |
| 297 | publish_.c \ |
| @@ -456,10 +458,11 @@ | |
| 458 | $(OX)\merge$O \ |
| 459 | $(OX)\merge3$O \ |
| 460 | $(OX)\moderate$O \ |
| 461 | $(OX)\name$O \ |
| 462 | $(OX)\path$O \ |
| 463 | $(OX)\piechart$O \ |
| 464 | $(OX)\pivot$O \ |
| 465 | $(OX)\popen$O \ |
| 466 | $(OX)\pqueue$O \ |
| 467 | $(OX)\printf$O \ |
| 468 | $(OX)\publish$O \ |
| @@ -631,10 +634,11 @@ | |
| 634 | echo $(OX)\merge.obj >> $@ |
| 635 | echo $(OX)\merge3.obj >> $@ |
| 636 | echo $(OX)\moderate.obj >> $@ |
| 637 | echo $(OX)\name.obj >> $@ |
| 638 | echo $(OX)\path.obj >> $@ |
| 639 | echo $(OX)\piechart.obj >> $@ |
| 640 | echo $(OX)\pivot.obj >> $@ |
| 641 | echo $(OX)\popen.obj >> $@ |
| 642 | echo $(OX)\pqueue.obj >> $@ |
| 643 | echo $(OX)\printf.obj >> $@ |
| 644 | echo $(OX)\publish.obj >> $@ |
| @@ -1212,10 +1216,16 @@ | |
| 1216 | $(OX)\path$O : path_.c path.h |
| 1217 | $(TCC) /Fo$@ -c path_.c |
| 1218 | |
| 1219 | path_.c : $(SRCDIR)\path.c |
| 1220 | translate$E $** > $@ |
| 1221 | |
| 1222 | $(OX)\piechart$O : piechart_.c piechart.h |
| 1223 | $(TCC) /Fo$@ -c piechart_.c |
| 1224 | |
| 1225 | piechart_.c : $(SRCDIR)\piechart.c |
| 1226 | translate$E $** > $@ |
| 1227 | |
| 1228 | $(OX)\pivot$O : pivot_.c pivot.h |
| 1229 | $(TCC) /Fo$@ -c pivot_.c |
| 1230 | |
| 1231 | pivot_.c : $(SRCDIR)\pivot.c |
| @@ -1565,10 +1575,11 @@ | |
| 1575 | merge_.c:merge.h \ |
| 1576 | merge3_.c:merge3.h \ |
| 1577 | moderate_.c:moderate.h \ |
| 1578 | name_.c:name.h \ |
| 1579 | path_.c:path.h \ |
| 1580 | piechart_.c:piechart.h \ |
| 1581 | pivot_.c:pivot.h \ |
| 1582 | popen_.c:popen.h \ |
| 1583 | pqueue_.c:pqueue.h \ |
| 1584 | printf_.c:printf.h \ |
| 1585 | publish_.c:publish.h \ |
| 1586 |
+33
-14
| --- www/build.wiki | ||
| +++ www/build.wiki | ||
| @@ -26,39 +26,39 @@ | ||
| 26 | 26 | <p><hr> |
| 27 | 27 | |
| 28 | 28 | <h2>1.0 Obtaining The Source Code</h2> |
| 29 | 29 | |
| 30 | 30 | <p>Fossil is self-hosting, so you can obtain a ZIP archive or tarball |
| 31 | -containing a snapshot of the <em>latest</em> version directly from | |
| 32 | -Fossil's own fossil repository. Additionally, source archives of | |
| 31 | +containing a snapshot of the <em>latest</em> version directly from | |
| 32 | +Fossil's own fossil repository. Additionally, source archives of | |
| 33 | 33 | <em>released</em> versions of |
| 34 | 34 | fossil are available from the <a href="http://www.fossil-scm.org/download.html">downloads page</a>. |
| 35 | 35 | To obtain a development version of fossil, follow these steps:</p> |
| 36 | 36 | |
| 37 | 37 | <ol> |
| 38 | 38 | <li><p>Point your web browser to |
| 39 | 39 | <a href="http://www.fossil-scm.org/"> |
| 40 | 40 | http://www.fossil-scm.org/</a>.</p></li> |
| 41 | 41 | |
| 42 | -<li><p>Click on the | |
| 43 | -<a href="http://www.fossil-scm.org/fossil/timeline">Timeline</a> | |
| 42 | +<li><p>Click on the | |
| 43 | +<a href="http://www.fossil-scm.org/fossil/timeline">Timeline</a> | |
| 44 | 44 | link at the top of the page.</p></li> |
| 45 | 45 | |
| 46 | 46 | <li><p>Select a version of of Fossil you want to download. The latest |
| 47 | 47 | version on the trunk branch is usually a good choice. Click on its |
| 48 | 48 | link.</p></li> |
| 49 | 49 | |
| 50 | 50 | <li><p>Finally, click on one of the |
| 51 | 51 | "Zip Archive" or "Tarball" links, according to your preference. |
| 52 | -These link will build a ZIP archive or a gzip-compressed tarball of the | |
| 52 | +These link will build a ZIP archive or a gzip-compressed tarball of the | |
| 53 | 53 | complete source code and download it to your computer. |
| 54 | 54 | </ol> |
| 55 | 55 | |
| 56 | 56 | <h2>Aside: Is it really safe to use an unreleased development version of |
| 57 | 57 | the Fossil source code?</h2> |
| 58 | 58 | |
| 59 | -Yes! Any check-in on the | |
| 59 | +Yes! Any check-in on the | |
| 60 | 60 | [/timeline?t=trunk | trunk branch] of the Fossil |
| 61 | 61 | [http://fossil-scm.org/fossil/timeline | Fossil self-hosting repository] |
| 62 | 62 | will work fine. (Dodgy code is always on a branch.) In the unlikely |
| 63 | 63 | event that you pick a version with a serious bug, it still won't |
| 64 | 64 | clobber your files. Fossil uses several |
| @@ -90,10 +90,14 @@ | ||
| 90 | 90 | |
| 91 | 91 | <li><p> |
| 92 | 92 | To build a statically linked binary (suitable for use inside a chroot |
| 93 | 93 | jail) add the <b>--static</b> option. |
| 94 | 94 | |
| 95 | +<li><p> | |
| 96 | +To enable the native [./th1.md#tclEval | Tcl integration feature] feature, | |
| 97 | +add the <b>--with-tcl=1</b> and <b>--with-tcl-private-stubs=1</b> options. | |
| 98 | + | |
| 95 | 99 | <li><p> |
| 96 | 100 | Other configuration options can be seen by running |
| 97 | 101 | <b>./configure --help</b> |
| 98 | 102 | </ol> |
| 99 | 103 | |
| @@ -102,20 +106,26 @@ | ||
| 102 | 106 | |
| 103 | 107 | <ol type="a"> |
| 104 | 108 | <li><p><i>Unix</i> → the configure-generated Makefile should work on |
| 105 | 109 | all Unix and Unix-like systems. Simply type "<b>make</b>". |
| 106 | 110 | |
| 107 | -<li><p><i>Unix without running "configure"</i> → if you prefer to avoid running configure, you | |
| 108 | -can also use: <b>make -f Makefile.classic</b>. You may want to make minor | |
| 109 | -edits to Makefile.classic to configure the build for your system. | |
| 111 | +<li><p><i>Unix without running "configure"</i> → if you prefer to avoid | |
| 112 | +running configure, you can also use: <b>make -f Makefile.classic</b>. You may | |
| 113 | +want to make minor edits to Makefile.classic to configure the build for your | |
| 114 | +system. | |
| 110 | 115 | |
| 111 | 116 | <li><p><i>MinGW3.x (not 4.0)/MinGW-w64</i> → Use the mingw makefile: |
| 112 | 117 | "<b>make -f win/Makefile.mingw</b>". On a Windows box you will |
| 113 | 118 | need either Cygwin or Msys as build environment. On Cygwin, Linux |
| 114 | 119 | or Darwin you may want to make minor edits to win/Makefile.mingw |
| 115 | 120 | to configure the cross-compile environment. |
| 116 | 121 | |
| 122 | +To enable the native [./th1.md#tclEval | Tcl integration feature], use a | |
| 123 | +command line like the following (all on one line): | |
| 124 | + | |
| 125 | +<b>make -f win/Makefile.mingw FOSSIL_ENABLE_TCL=1 FOSSIL_ENABLE_TCL_STUBS=1 FOSSIL_ENABLE_TCL_PRIVATE_STUBS=1</b> | |
| 126 | + | |
| 117 | 127 | Hint: don't use MinGW-4.0, it will compile but fossil won't work correctly, see |
| 118 | 128 | <a href="https://www.fossil-scm.org/index.html/tktview/18cff45a4e210430e24c">https://www.fossil-scm.org/index.html/tktview/18cff45a4e210430e24c</a>. |
| 119 | 129 | |
| 120 | 130 | <li><p><i>MSVC</i> → Use the MSVC makefile. First |
| 121 | 131 | change to the "win/" subdirectory ("<b>cd win</b>") then run |
| @@ -134,10 +144,19 @@ | ||
| 134 | 144 | nmake /f Makefile.msc FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin |
| 135 | 145 | </pre></blockquote> |
| 136 | 146 | <blockquote><pre> |
| 137 | 147 | buildmsvc.bat FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin |
| 138 | 148 | </pre></blockquote> |
| 149 | +To enable the optional native [./th1.md#tclEval | Tcl integration feature], | |
| 150 | +run one of the following commands or add the "FOSSIL_ENABLE_TCL=1" | |
| 151 | +argument to one of the other NMAKE command lines: | |
| 152 | +<blockquote><pre> | |
| 153 | +nmake /f Makefile.msc FOSSIL_ENABLE_TCL=1 | |
| 154 | +</pre></blockquote> | |
| 155 | +<blockquote><pre> | |
| 156 | +buildmsvc.bat FOSSIL_ENABLE_TCL=1 | |
| 157 | +</pre></blockquote> | |
| 139 | 158 | |
| 140 | 159 | <li><p><i>Cygwin</i> → The same as other Unix-like systems. It is |
| 141 | 160 | recommended to configure using: "<b>configure --disable-internal-sqlite</b>", |
| 142 | 161 | making sure you have the "libsqlite3-devel" , "zlib-devel" and |
| 143 | 162 | "openssl-devel" packages installed first. |
| @@ -146,12 +165,12 @@ | ||
| 146 | 165 | |
| 147 | 166 | <h2>3.0 Installing</h2> |
| 148 | 167 | |
| 149 | 168 | <ol> |
| 150 | 169 | <li value="8"> |
| 151 | -<p>The finished binary is named "fossil" (or "fossil.exe" on Windows). | |
| 152 | -Put this binary in a | |
| 170 | +<p>The finished binary is named "fossil" (or "fossil.exe" on Windows). | |
| 171 | +Put this binary in a | |
| 153 | 172 | directory that is somewhere on your PATH environment variable. |
| 154 | 173 | It does not matter where.</p> |
| 155 | 174 | |
| 156 | 175 | <li> |
| 157 | 176 | <p><b>(Optional:)</b> |
| @@ -167,14 +186,14 @@ | ||
| 167 | 186 | Fossil manually, then refer to the |
| 168 | 187 | [./makefile.wiki | Fossil Build Process] document which describes |
| 169 | 188 | in detail what the makefiles do behind the scenes. |
| 170 | 189 | |
| 171 | 190 | <li><p> |
| 172 | - The fossil executable is self-contained and stand-alone and usually | |
| 173 | - requires no special libraries or other software to be installed. However, | |
| 191 | + The fossil executable is self-contained and stand-alone and usually | |
| 192 | + requires no special libraries or other software to be installed. However, | |
| 174 | 193 | the "--tk" option to the [/help/diff|diff command] requires that Tcl/Tk |
| 175 | - be installed on the local machine. You can get Tcl/Tk from | |
| 194 | + be installed on the local machine. You can get Tcl/Tk from | |
| 176 | 195 | [http://www.activestate.com/activetcl|ActiveState]. |
| 177 | 196 | |
| 178 | 197 | <li><p> |
| 179 | 198 | To build on older Macs (circa 2002, MacOS 10.2) edit the Makefile |
| 180 | 199 | generated by configure to add the following lines: |
| 181 | 200 |
| --- www/build.wiki | |
| +++ www/build.wiki | |
| @@ -26,39 +26,39 @@ | |
| 26 | <p><hr> |
| 27 | |
| 28 | <h2>1.0 Obtaining The Source Code</h2> |
| 29 | |
| 30 | <p>Fossil is self-hosting, so you can obtain a ZIP archive or tarball |
| 31 | containing a snapshot of the <em>latest</em> version directly from |
| 32 | Fossil's own fossil repository. Additionally, source archives of |
| 33 | <em>released</em> versions of |
| 34 | fossil are available from the <a href="http://www.fossil-scm.org/download.html">downloads page</a>. |
| 35 | To obtain a development version of fossil, follow these steps:</p> |
| 36 | |
| 37 | <ol> |
| 38 | <li><p>Point your web browser to |
| 39 | <a href="http://www.fossil-scm.org/"> |
| 40 | http://www.fossil-scm.org/</a>.</p></li> |
| 41 | |
| 42 | <li><p>Click on the |
| 43 | <a href="http://www.fossil-scm.org/fossil/timeline">Timeline</a> |
| 44 | link at the top of the page.</p></li> |
| 45 | |
| 46 | <li><p>Select a version of of Fossil you want to download. The latest |
| 47 | version on the trunk branch is usually a good choice. Click on its |
| 48 | link.</p></li> |
| 49 | |
| 50 | <li><p>Finally, click on one of the |
| 51 | "Zip Archive" or "Tarball" links, according to your preference. |
| 52 | These link will build a ZIP archive or a gzip-compressed tarball of the |
| 53 | complete source code and download it to your computer. |
| 54 | </ol> |
| 55 | |
| 56 | <h2>Aside: Is it really safe to use an unreleased development version of |
| 57 | the Fossil source code?</h2> |
| 58 | |
| 59 | Yes! Any check-in on the |
| 60 | [/timeline?t=trunk | trunk branch] of the Fossil |
| 61 | [http://fossil-scm.org/fossil/timeline | Fossil self-hosting repository] |
| 62 | will work fine. (Dodgy code is always on a branch.) In the unlikely |
| 63 | event that you pick a version with a serious bug, it still won't |
| 64 | clobber your files. Fossil uses several |
| @@ -90,10 +90,14 @@ | |
| 90 | |
| 91 | <li><p> |
| 92 | To build a statically linked binary (suitable for use inside a chroot |
| 93 | jail) add the <b>--static</b> option. |
| 94 | |
| 95 | <li><p> |
| 96 | Other configuration options can be seen by running |
| 97 | <b>./configure --help</b> |
| 98 | </ol> |
| 99 | |
| @@ -102,20 +106,26 @@ | |
| 102 | |
| 103 | <ol type="a"> |
| 104 | <li><p><i>Unix</i> → the configure-generated Makefile should work on |
| 105 | all Unix and Unix-like systems. Simply type "<b>make</b>". |
| 106 | |
| 107 | <li><p><i>Unix without running "configure"</i> → if you prefer to avoid running configure, you |
| 108 | can also use: <b>make -f Makefile.classic</b>. You may want to make minor |
| 109 | edits to Makefile.classic to configure the build for your system. |
| 110 | |
| 111 | <li><p><i>MinGW3.x (not 4.0)/MinGW-w64</i> → Use the mingw makefile: |
| 112 | "<b>make -f win/Makefile.mingw</b>". On a Windows box you will |
| 113 | need either Cygwin or Msys as build environment. On Cygwin, Linux |
| 114 | or Darwin you may want to make minor edits to win/Makefile.mingw |
| 115 | to configure the cross-compile environment. |
| 116 | |
| 117 | Hint: don't use MinGW-4.0, it will compile but fossil won't work correctly, see |
| 118 | <a href="https://www.fossil-scm.org/index.html/tktview/18cff45a4e210430e24c">https://www.fossil-scm.org/index.html/tktview/18cff45a4e210430e24c</a>. |
| 119 | |
| 120 | <li><p><i>MSVC</i> → Use the MSVC makefile. First |
| 121 | change to the "win/" subdirectory ("<b>cd win</b>") then run |
| @@ -134,10 +144,19 @@ | |
| 134 | nmake /f Makefile.msc FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin |
| 135 | </pre></blockquote> |
| 136 | <blockquote><pre> |
| 137 | buildmsvc.bat FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin |
| 138 | </pre></blockquote> |
| 139 | |
| 140 | <li><p><i>Cygwin</i> → The same as other Unix-like systems. It is |
| 141 | recommended to configure using: "<b>configure --disable-internal-sqlite</b>", |
| 142 | making sure you have the "libsqlite3-devel" , "zlib-devel" and |
| 143 | "openssl-devel" packages installed first. |
| @@ -146,12 +165,12 @@ | |
| 146 | |
| 147 | <h2>3.0 Installing</h2> |
| 148 | |
| 149 | <ol> |
| 150 | <li value="8"> |
| 151 | <p>The finished binary is named "fossil" (or "fossil.exe" on Windows). |
| 152 | Put this binary in a |
| 153 | directory that is somewhere on your PATH environment variable. |
| 154 | It does not matter where.</p> |
| 155 | |
| 156 | <li> |
| 157 | <p><b>(Optional:)</b> |
| @@ -167,14 +186,14 @@ | |
| 167 | Fossil manually, then refer to the |
| 168 | [./makefile.wiki | Fossil Build Process] document which describes |
| 169 | in detail what the makefiles do behind the scenes. |
| 170 | |
| 171 | <li><p> |
| 172 | The fossil executable is self-contained and stand-alone and usually |
| 173 | requires no special libraries or other software to be installed. However, |
| 174 | the "--tk" option to the [/help/diff|diff command] requires that Tcl/Tk |
| 175 | be installed on the local machine. You can get Tcl/Tk from |
| 176 | [http://www.activestate.com/activetcl|ActiveState]. |
| 177 | |
| 178 | <li><p> |
| 179 | To build on older Macs (circa 2002, MacOS 10.2) edit the Makefile |
| 180 | generated by configure to add the following lines: |
| 181 |
| --- www/build.wiki | |
| +++ www/build.wiki | |
| @@ -26,39 +26,39 @@ | |
| 26 | <p><hr> |
| 27 | |
| 28 | <h2>1.0 Obtaining The Source Code</h2> |
| 29 | |
| 30 | <p>Fossil is self-hosting, so you can obtain a ZIP archive or tarball |
| 31 | containing a snapshot of the <em>latest</em> version directly from |
| 32 | Fossil's own fossil repository. Additionally, source archives of |
| 33 | <em>released</em> versions of |
| 34 | fossil are available from the <a href="http://www.fossil-scm.org/download.html">downloads page</a>. |
| 35 | To obtain a development version of fossil, follow these steps:</p> |
| 36 | |
| 37 | <ol> |
| 38 | <li><p>Point your web browser to |
| 39 | <a href="http://www.fossil-scm.org/"> |
| 40 | http://www.fossil-scm.org/</a>.</p></li> |
| 41 | |
| 42 | <li><p>Click on the |
| 43 | <a href="http://www.fossil-scm.org/fossil/timeline">Timeline</a> |
| 44 | link at the top of the page.</p></li> |
| 45 | |
| 46 | <li><p>Select a version of of Fossil you want to download. The latest |
| 47 | version on the trunk branch is usually a good choice. Click on its |
| 48 | link.</p></li> |
| 49 | |
| 50 | <li><p>Finally, click on one of the |
| 51 | "Zip Archive" or "Tarball" links, according to your preference. |
| 52 | These link will build a ZIP archive or a gzip-compressed tarball of the |
| 53 | complete source code and download it to your computer. |
| 54 | </ol> |
| 55 | |
| 56 | <h2>Aside: Is it really safe to use an unreleased development version of |
| 57 | the Fossil source code?</h2> |
| 58 | |
| 59 | Yes! Any check-in on the |
| 60 | [/timeline?t=trunk | trunk branch] of the Fossil |
| 61 | [http://fossil-scm.org/fossil/timeline | Fossil self-hosting repository] |
| 62 | will work fine. (Dodgy code is always on a branch.) In the unlikely |
| 63 | event that you pick a version with a serious bug, it still won't |
| 64 | clobber your files. Fossil uses several |
| @@ -90,10 +90,14 @@ | |
| 90 | |
| 91 | <li><p> |
| 92 | To build a statically linked binary (suitable for use inside a chroot |
| 93 | jail) add the <b>--static</b> option. |
| 94 | |
| 95 | <li><p> |
| 96 | To enable the native [./th1.md#tclEval | Tcl integration feature] feature, |
| 97 | add the <b>--with-tcl=1</b> and <b>--with-tcl-private-stubs=1</b> options. |
| 98 | |
| 99 | <li><p> |
| 100 | Other configuration options can be seen by running |
| 101 | <b>./configure --help</b> |
| 102 | </ol> |
| 103 | |
| @@ -102,20 +106,26 @@ | |
| 106 | |
| 107 | <ol type="a"> |
| 108 | <li><p><i>Unix</i> → the configure-generated Makefile should work on |
| 109 | all Unix and Unix-like systems. Simply type "<b>make</b>". |
| 110 | |
| 111 | <li><p><i>Unix without running "configure"</i> → if you prefer to avoid |
| 112 | running configure, you can also use: <b>make -f Makefile.classic</b>. You may |
| 113 | want to make minor edits to Makefile.classic to configure the build for your |
| 114 | system. |
| 115 | |
| 116 | <li><p><i>MinGW3.x (not 4.0)/MinGW-w64</i> → Use the mingw makefile: |
| 117 | "<b>make -f win/Makefile.mingw</b>". On a Windows box you will |
| 118 | need either Cygwin or Msys as build environment. On Cygwin, Linux |
| 119 | or Darwin you may want to make minor edits to win/Makefile.mingw |
| 120 | to configure the cross-compile environment. |
| 121 | |
| 122 | To enable the native [./th1.md#tclEval | Tcl integration feature], use a |
| 123 | command line like the following (all on one line): |
| 124 | |
| 125 | <b>make -f win/Makefile.mingw FOSSIL_ENABLE_TCL=1 FOSSIL_ENABLE_TCL_STUBS=1 FOSSIL_ENABLE_TCL_PRIVATE_STUBS=1</b> |
| 126 | |
| 127 | Hint: don't use MinGW-4.0, it will compile but fossil won't work correctly, see |
| 128 | <a href="https://www.fossil-scm.org/index.html/tktview/18cff45a4e210430e24c">https://www.fossil-scm.org/index.html/tktview/18cff45a4e210430e24c</a>. |
| 129 | |
| 130 | <li><p><i>MSVC</i> → Use the MSVC makefile. First |
| 131 | change to the "win/" subdirectory ("<b>cd win</b>") then run |
| @@ -134,10 +144,19 @@ | |
| 144 | nmake /f Makefile.msc FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin |
| 145 | </pre></blockquote> |
| 146 | <blockquote><pre> |
| 147 | buildmsvc.bat FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin |
| 148 | </pre></blockquote> |
| 149 | To enable the optional native [./th1.md#tclEval | Tcl integration feature], |
| 150 | run one of the following commands or add the "FOSSIL_ENABLE_TCL=1" |
| 151 | argument to one of the other NMAKE command lines: |
| 152 | <blockquote><pre> |
| 153 | nmake /f Makefile.msc FOSSIL_ENABLE_TCL=1 |
| 154 | </pre></blockquote> |
| 155 | <blockquote><pre> |
| 156 | buildmsvc.bat FOSSIL_ENABLE_TCL=1 |
| 157 | </pre></blockquote> |
| 158 | |
| 159 | <li><p><i>Cygwin</i> → The same as other Unix-like systems. It is |
| 160 | recommended to configure using: "<b>configure --disable-internal-sqlite</b>", |
| 161 | making sure you have the "libsqlite3-devel" , "zlib-devel" and |
| 162 | "openssl-devel" packages installed first. |
| @@ -146,12 +165,12 @@ | |
| 165 | |
| 166 | <h2>3.0 Installing</h2> |
| 167 | |
| 168 | <ol> |
| 169 | <li value="8"> |
| 170 | <p>The finished binary is named "fossil" (or "fossil.exe" on Windows). |
| 171 | Put this binary in a |
| 172 | directory that is somewhere on your PATH environment variable. |
| 173 | It does not matter where.</p> |
| 174 | |
| 175 | <li> |
| 176 | <p><b>(Optional:)</b> |
| @@ -167,14 +186,14 @@ | |
| 186 | Fossil manually, then refer to the |
| 187 | [./makefile.wiki | Fossil Build Process] document which describes |
| 188 | in detail what the makefiles do behind the scenes. |
| 189 | |
| 190 | <li><p> |
| 191 | The fossil executable is self-contained and stand-alone and usually |
| 192 | requires no special libraries or other software to be installed. However, |
| 193 | the "--tk" option to the [/help/diff|diff command] requires that Tcl/Tk |
| 194 | be installed on the local machine. You can get Tcl/Tk from |
| 195 | [http://www.activestate.com/activetcl|ActiveState]. |
| 196 | |
| 197 | <li><p> |
| 198 | To build on older Macs (circa 2002, MacOS 10.2) edit the Makefile |
| 199 | generated by configure to add the following lines: |
| 200 |
+35
-2
| --- www/changes.wiki | ||
| +++ www/changes.wiki | ||
| @@ -1,22 +1,55 @@ | ||
| 1 | 1 | <title>Change Log</title> |
| 2 | 2 | |
| 3 | 3 | <h2>Changes for Version 1.33 (not released yet)</h2> |
| 4 | + * Improved fork detection on [/help?cmd=update|fossil update], | |
| 5 | + [/help?cmd=status|fossil status] and related commands. | |
| 6 | + * Change the default skin to what used to be called "San Francisco Modern". | |
| 7 | + * Add the [/repo-tabsize] web page | |
| 4 | 8 | * Add [/help?cmd=import|fossil import --svn], for importing a subversion |
| 5 | 9 | repository into fossil which was exported using "svnadmin dump". |
| 10 | + * Add the "--compress-only" option to [/help?cmd=rebuild|fossil rebuild]. | |
| 11 | + * Use a pie chart on the [/reports?view=byuser] page. | |
| 12 | + * Enhanced [/help?cmd=clean|fossil clean --verily] so that it ignores | |
| 13 | + keep-glob and ignore-glob settings. Added the -x alias for --verily. | |
| 14 | + * Add the --soft and --hard options to [/help?cmd=rm|fossil rm] and | |
| 15 | + [/help?cmd=mv|fossil mv]. The default is still --soft, but that is | |
| 16 | + now configurable at compile-time or by the mv-rm-files setting. | |
| 17 | + * Improved ability to [./customgraph.md|customize the timelime graph]. | |
| 18 | + * Improvements to the [/sitemap] page. | |
| 19 | + * Automatically adjust the [/help?cmd=timeline|CLI timeline] to the terminal | |
| 20 | + width on Linux. | |
| 6 | 21 | * Added <nowiki>[info commands] and [info vars]</nowiki> commands to TH1. |
| 7 | 22 | These commands perform the same function as their Tcl counterparts, |
| 8 | 23 | except they do not accept a pattern argument. |
| 9 | 24 | * Fix some obscure issues with TH1 expression processing. |
| 10 | 25 | * Fix titles in search results for documents that are not wiki, markdown, |
| 11 | 26 | or HTML. |
| 12 | 27 | * Formally translate TH1 to Tcl return codes and vice-versa, where |
| 13 | 28 | necessary, in the Tcl integration subsystem. |
| 14 | - * Better fork detection on [/help?cmd=update|fossil update], | |
| 15 | - [/help?cmd=status|fossil status] and related commands. | |
| 16 | 29 | * Add [/help?cmd=leaves|fossil leaves -multiple], for finding multiple |
| 17 | 30 | leaves on the same branch. |
| 31 | + * Added the "Blitz" skin option. | |
| 32 | + * Removed the ".fossil-settings/keep-glob" file. It should not have been | |
| 33 | + checked into the repository. | |
| 34 | + * Update the built-in SQLite to version 3.8.10.1. | |
| 35 | + * Make [/help?cmd=open|fossil open] honor ".fossil-settings/allow-symlinks". | |
| 36 | + * Allow [/help?cmd=add|fossil add] to be used on symlinks to nonexistent or | |
| 37 | + unreadable files in the same way as [/help?cmd=addremove|fossil addremove]. | |
| 38 | + * Added fork warning to be issued if sync produced a fork | |
| 39 | + * Update the [/help?cmd=/info|info] page to report when a file becomes a | |
| 40 | + symlink. Additionally show the UUID for files whose types have changed | |
| 41 | + without changing contents or symlink target. | |
| 42 | + * Have [/help?cmd=changes|fossil changes] and | |
| 43 | + [/help?cmd=status|fossil status] report when executable or symlink status | |
| 44 | + changes on otherwise unmodified files. | |
| 45 | + * Permit filtering weekday and file [/help?cmd=/reports|reports] by user. | |
| 46 | + Also ensure the user parameter is preserved when changing types. Add a | |
| 47 | + field for direct entry of the user name to each applicable report. | |
| 48 | + * Create parent directories of [/help?cmd=settings|empty-dirs] if they don't | |
| 49 | + already exist. | |
| 50 | + * Inhibit timeline links to wiki pages that have been deleted. | |
| 18 | 51 | |
| 19 | 52 | <h2>Changes for Version 1.32 (2015-03-14)</h2> |
| 20 | 53 | * When creating a new repository using [/help?cmd=init|fossil init], ensure |
| 21 | 54 | that the new repository is fully compatible with historical versions of |
| 22 | 55 | Fossil by having a valid manifest as RID 1. |
| 23 | 56 | |
| 24 | 57 | ADDED www/customgraph.md |
| --- www/changes.wiki | |
| +++ www/changes.wiki | |
| @@ -1,22 +1,55 @@ | |
| 1 | <title>Change Log</title> |
| 2 | |
| 3 | <h2>Changes for Version 1.33 (not released yet)</h2> |
| 4 | * Add [/help?cmd=import|fossil import --svn], for importing a subversion |
| 5 | repository into fossil which was exported using "svnadmin dump". |
| 6 | * Added <nowiki>[info commands] and [info vars]</nowiki> commands to TH1. |
| 7 | These commands perform the same function as their Tcl counterparts, |
| 8 | except they do not accept a pattern argument. |
| 9 | * Fix some obscure issues with TH1 expression processing. |
| 10 | * Fix titles in search results for documents that are not wiki, markdown, |
| 11 | or HTML. |
| 12 | * Formally translate TH1 to Tcl return codes and vice-versa, where |
| 13 | necessary, in the Tcl integration subsystem. |
| 14 | * Better fork detection on [/help?cmd=update|fossil update], |
| 15 | [/help?cmd=status|fossil status] and related commands. |
| 16 | * Add [/help?cmd=leaves|fossil leaves -multiple], for finding multiple |
| 17 | leaves on the same branch. |
| 18 | |
| 19 | <h2>Changes for Version 1.32 (2015-03-14)</h2> |
| 20 | * When creating a new repository using [/help?cmd=init|fossil init], ensure |
| 21 | that the new repository is fully compatible with historical versions of |
| 22 | Fossil by having a valid manifest as RID 1. |
| 23 | |
| 24 | DDED www/customgraph.md |
| --- www/changes.wiki | |
| +++ www/changes.wiki | |
| @@ -1,22 +1,55 @@ | |
| 1 | <title>Change Log</title> |
| 2 | |
| 3 | <h2>Changes for Version 1.33 (not released yet)</h2> |
| 4 | * Improved fork detection on [/help?cmd=update|fossil update], |
| 5 | [/help?cmd=status|fossil status] and related commands. |
| 6 | * Change the default skin to what used to be called "San Francisco Modern". |
| 7 | * Add the [/repo-tabsize] web page |
| 8 | * Add [/help?cmd=import|fossil import --svn], for importing a subversion |
| 9 | repository into fossil which was exported using "svnadmin dump". |
| 10 | * Add the "--compress-only" option to [/help?cmd=rebuild|fossil rebuild]. |
| 11 | * Use a pie chart on the [/reports?view=byuser] page. |
| 12 | * Enhanced [/help?cmd=clean|fossil clean --verily] so that it ignores |
| 13 | keep-glob and ignore-glob settings. Added the -x alias for --verily. |
| 14 | * Add the --soft and --hard options to [/help?cmd=rm|fossil rm] and |
| 15 | [/help?cmd=mv|fossil mv]. The default is still --soft, but that is |
| 16 | now configurable at compile-time or by the mv-rm-files setting. |
| 17 | * Improved ability to [./customgraph.md|customize the timelime graph]. |
| 18 | * Improvements to the [/sitemap] page. |
| 19 | * Automatically adjust the [/help?cmd=timeline|CLI timeline] to the terminal |
| 20 | width on Linux. |
| 21 | * Added <nowiki>[info commands] and [info vars]</nowiki> commands to TH1. |
| 22 | These commands perform the same function as their Tcl counterparts, |
| 23 | except they do not accept a pattern argument. |
| 24 | * Fix some obscure issues with TH1 expression processing. |
| 25 | * Fix titles in search results for documents that are not wiki, markdown, |
| 26 | or HTML. |
| 27 | * Formally translate TH1 to Tcl return codes and vice-versa, where |
| 28 | necessary, in the Tcl integration subsystem. |
| 29 | * Add [/help?cmd=leaves|fossil leaves -multiple], for finding multiple |
| 30 | leaves on the same branch. |
| 31 | * Added the "Blitz" skin option. |
| 32 | * Removed the ".fossil-settings/keep-glob" file. It should not have been |
| 33 | checked into the repository. |
| 34 | * Update the built-in SQLite to version 3.8.10.1. |
| 35 | * Make [/help?cmd=open|fossil open] honor ".fossil-settings/allow-symlinks". |
| 36 | * Allow [/help?cmd=add|fossil add] to be used on symlinks to nonexistent or |
| 37 | unreadable files in the same way as [/help?cmd=addremove|fossil addremove]. |
| 38 | * Added fork warning to be issued if sync produced a fork |
| 39 | * Update the [/help?cmd=/info|info] page to report when a file becomes a |
| 40 | symlink. Additionally show the UUID for files whose types have changed |
| 41 | without changing contents or symlink target. |
| 42 | * Have [/help?cmd=changes|fossil changes] and |
| 43 | [/help?cmd=status|fossil status] report when executable or symlink status |
| 44 | changes on otherwise unmodified files. |
| 45 | * Permit filtering weekday and file [/help?cmd=/reports|reports] by user. |
| 46 | Also ensure the user parameter is preserved when changing types. Add a |
| 47 | field for direct entry of the user name to each applicable report. |
| 48 | * Create parent directories of [/help?cmd=settings|empty-dirs] if they don't |
| 49 | already exist. |
| 50 | * Inhibit timeline links to wiki pages that have been deleted. |
| 51 | |
| 52 | <h2>Changes for Version 1.32 (2015-03-14)</h2> |
| 53 | * When creating a new repository using [/help?cmd=init|fossil init], ensure |
| 54 | that the new repository is fully compatible with historical versions of |
| 55 | Fossil by having a valid manifest as RID 1. |
| 56 | |
| 57 | DDED www/customgraph.md |
+144
| --- a/www/customgraph.md | ||
| +++ b/www/customgraph.md | ||
| @@ -0,0 +1,144 @@ | ||
| 1 | +# Customizing the Timeline Graph | |
| 2 | + | |
| 3 | +Beginning with version 1.33, Fossil gives users and skin authors significantly | |
| 4 | +more control over the look and feel of the timeline graph. | |
| 5 | + | |
| 6 | +## <a id="basic-style"></a>Basic Style Options | |
| 7 | + | |
| 8 | +Fossil includes several options for changing the graph's style without having | |
| 9 | +to delve into CSS. These can be found in the details.txt file of your skin or | |
| 10 | +under Admin/Skins/D###`timeline-arrowheads` | |
| 11 | + | |
| 12 | + Set this to `0` to hide arrowheads on primary child lines. | |
| 13 | + | |
| 14 | +* ### Set this to `node s`** | |
| 15 | + | |
| 16 | + Set this to `1` to### `timeline-color-graph-line` | |
| 17 | + | |
| 18 | + Set this to `1` to colorize### `white-foreground` | |
| 19 | + | |
| 20 | + Set this to `round`** | |
| 21 | + | |
| 22 | + Seses white (or any light color) text. | |
| 23 | + This tells Fossil to generate darker background colors for branches. | |
| 24 | + | |
| 25 | + | |
| 26 | +## <a id="adv-style"></a>Advanced Styling | |
| 27 | + | |
| 28 | +If the above options aren't enough for you, it's time to get your hands dirty | |
| 29 | +with CSS. To get started, I recommend first copying all the [graph-related CSS | |
| 30 | +rules](#default-css) to your stylesheet. Then it's simply a matter of making | |
| 31 | +the necessary changes to achieve the look you want. So, next, let's look at the | |
| 32 | +various graph elements and what purpose they serve. | |
| 33 | + | |
| 34 | +Each element used to construct the timeline graph falls into one of two | |
| 35 | +categories: visible elements and positioning elements. We'll start with the | |
| 36 | +latter, less obvious type. | |
| 37 | + | |
| 38 | +## <a id="pos-elems"></a>Positioning Elements | |
| 39 | + | |
| 40 | +These elements aren't intended to be seen. They're only used to h### <a id=" | |
| 41 | + | |
| 42 | + Set the left and right margins on this class to give the desired amount | |
| 43 | + of space between tunt | |
| 44 | + of space between the graph and its adjacent columns in the timeline. | |
| 45 | + | |
| 46 | + #### Ad ditional Classes | |
| 47 | + **Additional Classes** | |
| 48 | + | |
| 49 | + * `.sel`: See [`.tl-node`](#tl-node) ### <a id="tl-rail"></a>`.tl-rail`tl-rail"></a>**`.tl-rail`** | |
| 50 | + | |
| 51 | + Think of rails as invisibl Think of rails as invisible vertical lines o placed. The more simultaneous branches in a graph, the more rails required | |
| 52 | + to draw it. Setting the `width` property on this class determines the | |
| 53 | + maximum spacing between rails. This spacing is automatically reduced as | |
| 54 | + the number of rails increases. If you change the `width` of `.tl-node` | |
| 55 | + elements, you'll probably need to ch###ing the Timeline Graph | |
| 56 | + | |
| 57 | +Begi# Customizing theoreground`** | |
| 58 | + | |
| 59 | + Set this to `1` if your skin uses white (or any light color) text. | |
| 60 | + T` | |
| 61 | + | |
| 62 | + Set this to `round`** | |
| 63 | + | |
| 64 | + Set this to `1` if your skin uses white (or any light color) text. | |
| 65 | + This tells Fossil to generate darker background colors for branches. | |
| 66 | + | |
| 67 | + | |
| 68 | +## <a id="adv-style"></a>Advanced Styling | |
| 69 | + | |
| 70 | +If the above options aren't enough for you, it's time to get your hands dirty | |
| 71 | +with CSS. To get started, I recommend first copying all the [graph-related CSS | |
| 72 | +rules](#default-css) to yourcessary changes to achieve the look you want. So, next, let's look at the | |
| 73 | +various graph elements and what purpose they serve. | |
| 74 | + | |
| 75 | +Each element used to construct the timeline graph falls into one of two | |
| 76 | +categories: visible elements and positioning elements. We'll start with the | |
| 77 | +latter, less obvious type. | |
| 78 | + | |
| 79 | +## <a id="pos-elems"></a>Positioning Elements | |
| 80 | + | |
| 81 | +These elements aren't intended to be seen. They're only used to h### <a id=" | |
| 82 | + | |
| 83 | + Set the left and right margins on this class to give the desired amount | |
| 84 | + of space between the graph and its adjaidth` of `.tl-node` | |
| 85 | + elements, you'll probably need to ch###ing the Timeline Graph | |
| 86 | + | |
| 87 | +Begi# Customizing theoreground`** | |
| 88 | + | |
| 89 | + Set this to ` Think of rails as invisibl node`](#tl-node) ### <a id="tl-rail"></a>`.tl-rail`tl-rail"></a>**`.tl-rail`** | |
| 90 | + | |
| 91 | + Thin more simultaneous branches in a graph, the more rails required | |
| 92 | + to draw it. Setting the `width` property on this class determines the | |
| 93 | + maximum spacing between rails. This spacing is automatically reduced as | |
| 94 | + the number of rails increases. If you change the `width` of `.tl-node` | |
| 95 | + elements, you'll probably need to ch###ing the Timeline Graph | |
| 96 | + | |
| 97 | +Begi# Customizing theoreground`** | |
| 98 | + | |
| 99 | + Set this to `1` if your skin uses white (or any light color) text. | |
| 100 | + T` | |
| 101 | + | |
| 102 | + Set this to `round`** | |
| 103 | + | |
| 104 | + Set this to `1` if your skin uses white (or any light color) text. | |
| 105 | + This tells Fossil to generate darker background colors for branches. | |
| 106 | + | |
| 107 | + | |
| 108 | +## <a id="adv-style"></a>Advanced Styling | |
| 109 | + | |
| 110 | +If the above options ar round: transparent; | |
| 111 | + border: 0 dotted #000; | |
| 112 | + } | |
| 113 | + . d #000; | |
| 114 | + } | |
| 115 | + .tl-line.merge.h { | |
| 116 | + border-top-width: 1px; | |
| 117 | + -#### Additional Classesl-node) for more infasses** | |
| 118 | + | |
| 119 | + * `.merge`: A merge line. | |
| 120 | + | |
| 121 | + * skin authors significantly | |
| 122 | +more# Customizing the Timeline Graph | |
| 123 | + | |
| 124 | +Beginning with version 1.33, Fossil gives users and skin authors significantly | |
| 125 | +more control over the look and feel of the timeline graph. | |
| 126 | + | |
| 127 | +## <a id="basic-style"></a>Basic Sty skin authors significantly | |
| 128 | +more control over the look and feel of the timeline graph. | |
| 129 | + | |
| 130 | +## <a id="basic-style"></a>Basic Style Options | |
| 131 | + | |
| 132 | +Fossil includes several options for changing the graph's style without having | |
| 133 | +to delve into CSS. These can be found in the details.txt file of your skin or | |
| 134 | +under Admin/Skins/D###`timeline-arrowheads` | |
| 135 | + | |
| 136 | + Set this to `0` to hide arrowheads on primary child lines. | |
| 137 | + | |
| 138 | +* ### Set this to `nodes`** | |
| 139 | + | |
| 140 | + Set this to `1` to### `timeline-color-graph-line` | |
| 141 | + | |
| 142 | + Set this to `1` to colorize### `white-foreground` | |
| 143 | + | |
| 144 | + Set this to `round`** |
| --- a/www/customgraph.md | |
| +++ b/www/customgraph.md | |
| @@ -0,0 +1,144 @@ | |
| --- a/www/customgraph.md | |
| +++ b/www/customgraph.md | |
| @@ -0,0 +1,144 @@ | |
| 1 | # Customizing the Timeline Graph |
| 2 | |
| 3 | Beginning with version 1.33, Fossil gives users and skin authors significantly |
| 4 | more control over the look and feel of the timeline graph. |
| 5 | |
| 6 | ## <a id="basic-style"></a>Basic Style Options |
| 7 | |
| 8 | Fossil includes several options for changing the graph's style without having |
| 9 | to delve into CSS. These can be found in the details.txt file of your skin or |
| 10 | under Admin/Skins/D###`timeline-arrowheads` |
| 11 | |
| 12 | Set this to `0` to hide arrowheads on primary child lines. |
| 13 | |
| 14 | * ### Set this to `node s`** |
| 15 | |
| 16 | Set this to `1` to### `timeline-color-graph-line` |
| 17 | |
| 18 | Set this to `1` to colorize### `white-foreground` |
| 19 | |
| 20 | Set this to `round`** |
| 21 | |
| 22 | Seses white (or any light color) text. |
| 23 | This tells Fossil to generate darker background colors for branches. |
| 24 | |
| 25 | |
| 26 | ## <a id="adv-style"></a>Advanced Styling |
| 27 | |
| 28 | If the above options aren't enough for you, it's time to get your hands dirty |
| 29 | with CSS. To get started, I recommend first copying all the [graph-related CSS |
| 30 | rules](#default-css) to your stylesheet. Then it's simply a matter of making |
| 31 | the necessary changes to achieve the look you want. So, next, let's look at the |
| 32 | various graph elements and what purpose they serve. |
| 33 | |
| 34 | Each element used to construct the timeline graph falls into one of two |
| 35 | categories: visible elements and positioning elements. We'll start with the |
| 36 | latter, less obvious type. |
| 37 | |
| 38 | ## <a id="pos-elems"></a>Positioning Elements |
| 39 | |
| 40 | These elements aren't intended to be seen. They're only used to h### <a id=" |
| 41 | |
| 42 | Set the left and right margins on this class to give the desired amount |
| 43 | of space between tunt |
| 44 | of space between the graph and its adjacent columns in the timeline. |
| 45 | |
| 46 | #### Ad ditional Classes |
| 47 | **Additional Classes** |
| 48 | |
| 49 | * `.sel`: See [`.tl-node`](#tl-node) ### <a id="tl-rail"></a>`.tl-rail`tl-rail"></a>**`.tl-rail`** |
| 50 | |
| 51 | Think of rails as invisibl Think of rails as invisible vertical lines o placed. The more simultaneous branches in a graph, the more rails required |
| 52 | to draw it. Setting the `width` property on this class determines the |
| 53 | maximum spacing between rails. This spacing is automatically reduced as |
| 54 | the number of rails increases. If you change the `width` of `.tl-node` |
| 55 | elements, you'll probably need to ch###ing the Timeline Graph |
| 56 | |
| 57 | Begi# Customizing theoreground`** |
| 58 | |
| 59 | Set this to `1` if your skin uses white (or any light color) text. |
| 60 | T` |
| 61 | |
| 62 | Set this to `round`** |
| 63 | |
| 64 | Set this to `1` if your skin uses white (or any light color) text. |
| 65 | This tells Fossil to generate darker background colors for branches. |
| 66 | |
| 67 | |
| 68 | ## <a id="adv-style"></a>Advanced Styling |
| 69 | |
| 70 | If the above options aren't enough for you, it's time to get your hands dirty |
| 71 | with CSS. To get started, I recommend first copying all the [graph-related CSS |
| 72 | rules](#default-css) to yourcessary changes to achieve the look you want. So, next, let's look at the |
| 73 | various graph elements and what purpose they serve. |
| 74 | |
| 75 | Each element used to construct the timeline graph falls into one of two |
| 76 | categories: visible elements and positioning elements. We'll start with the |
| 77 | latter, less obvious type. |
| 78 | |
| 79 | ## <a id="pos-elems"></a>Positioning Elements |
| 80 | |
| 81 | These elements aren't intended to be seen. They're only used to h### <a id=" |
| 82 | |
| 83 | Set the left and right margins on this class to give the desired amount |
| 84 | of space between the graph and its adjaidth` of `.tl-node` |
| 85 | elements, you'll probably need to ch###ing the Timeline Graph |
| 86 | |
| 87 | Begi# Customizing theoreground`** |
| 88 | |
| 89 | Set this to ` Think of rails as invisibl node`](#tl-node) ### <a id="tl-rail"></a>`.tl-rail`tl-rail"></a>**`.tl-rail`** |
| 90 | |
| 91 | Thin more simultaneous branches in a graph, the more rails required |
| 92 | to draw it. Setting the `width` property on this class determines the |
| 93 | maximum spacing between rails. This spacing is automatically reduced as |
| 94 | the number of rails increases. If you change the `width` of `.tl-node` |
| 95 | elements, you'll probably need to ch###ing the Timeline Graph |
| 96 | |
| 97 | Begi# Customizing theoreground`** |
| 98 | |
| 99 | Set this to `1` if your skin uses white (or any light color) text. |
| 100 | T` |
| 101 | |
| 102 | Set this to `round`** |
| 103 | |
| 104 | Set this to `1` if your skin uses white (or any light color) text. |
| 105 | This tells Fossil to generate darker background colors for branches. |
| 106 | |
| 107 | |
| 108 | ## <a id="adv-style"></a>Advanced Styling |
| 109 | |
| 110 | If the above options ar round: transparent; |
| 111 | border: 0 dotted #000; |
| 112 | } |
| 113 | . d #000; |
| 114 | } |
| 115 | .tl-line.merge.h { |
| 116 | border-top-width: 1px; |
| 117 | -#### Additional Classesl-node) for more infasses** |
| 118 | |
| 119 | * `.merge`: A merge line. |
| 120 | |
| 121 | * skin authors significantly |
| 122 | more# Customizing the Timeline Graph |
| 123 | |
| 124 | Beginning with version 1.33, Fossil gives users and skin authors significantly |
| 125 | more control over the look and feel of the timeline graph. |
| 126 | |
| 127 | ## <a id="basic-style"></a>Basic Sty skin authors significantly |
| 128 | more control over the look and feel of the timeline graph. |
| 129 | |
| 130 | ## <a id="basic-style"></a>Basic Style Options |
| 131 | |
| 132 | Fossil includes several options for changing the graph's style without having |
| 133 | to delve into CSS. These can be found in the details.txt file of your skin or |
| 134 | under Admin/Skins/D###`timeline-arrowheads` |
| 135 | |
| 136 | Set this to `0` to hide arrowheads on primary child lines. |
| 137 | |
| 138 | * ### Set this to `nodes`** |
| 139 | |
| 140 | Set this to `1` to### `timeline-color-graph-line` |
| 141 | |
| 142 | Set this to `1` to colorize### `white-foreground` |
| 143 | |
| 144 | Set this to `round`** |
+5
| --- www/customskin.md | ||
| +++ www/customskin.md | ||
| @@ -232,5 +232,10 @@ | ||
| 232 | 232 | |
| 233 | 233 | 4. Copy/paste the resulting css.txt, details.txt, |
| 234 | 234 | header.txt, and footer.txt files |
| 235 | 235 | into the CSS, details, header, and footer configuration screens |
| 236 | 236 | under the Admin/Skins menu. |
| 237 | + | |
| 238 | +See Also | |
| 239 | +-------- | |
| 240 | + | |
| 241 | +* [Customizing the Timeline Graph](customgraph.md) | |
| 237 | 242 |
| --- www/customskin.md | |
| +++ www/customskin.md | |
| @@ -232,5 +232,10 @@ | |
| 232 | |
| 233 | 4. Copy/paste the resulting css.txt, details.txt, |
| 234 | header.txt, and footer.txt files |
| 235 | into the CSS, details, header, and footer configuration screens |
| 236 | under the Admin/Skins menu. |
| 237 |
| --- www/customskin.md | |
| +++ www/customskin.md | |
| @@ -232,5 +232,10 @@ | |
| 232 | |
| 233 | 4. Copy/paste the resulting css.txt, details.txt, |
| 234 | header.txt, and footer.txt files |
| 235 | into the CSS, details, header, and footer configuration screens |
| 236 | under the Admin/Skins menu. |
| 237 | |
| 238 | See Also |
| 239 | -------- |
| 240 | |
| 241 | * [Customizing the Timeline Graph](customgraph.md) |
| 242 |
+1
| --- www/mkindex.tcl | ||
| +++ www/mkindex.tcl | ||
| @@ -17,10 +17,11 @@ | ||
| 17 | 17 | checkin.wiki {Check-in Checklist} |
| 18 | 18 | changes.wiki {Fossil Changelog} |
| 19 | 19 | copyright-release.html {Contributor License Agreement} |
| 20 | 20 | concepts.wiki {Fossil Core Concepts} |
| 21 | 21 | contribute.wiki {Contributing Code or Documentation To The Fossil Project} |
| 22 | + customgraph.md {Theming: Customizing the Timeline Graph} | |
| 22 | 23 | customskin.md {Theming: Customizing The Appearance of Web Pages} |
| 23 | 24 | custom_ticket.wiki {Customizing The Ticket System} |
| 24 | 25 | delta_encoder_algorithm.wiki {Fossil Delta Encoding Algorithm} |
| 25 | 26 | delta_format.wiki {Fossil Delta Format} |
| 26 | 27 | embeddeddoc.wiki {Embedded Project Documentation} |
| 27 | 28 |
| --- www/mkindex.tcl | |
| +++ www/mkindex.tcl | |
| @@ -17,10 +17,11 @@ | |
| 17 | checkin.wiki {Check-in Checklist} |
| 18 | changes.wiki {Fossil Changelog} |
| 19 | copyright-release.html {Contributor License Agreement} |
| 20 | concepts.wiki {Fossil Core Concepts} |
| 21 | contribute.wiki {Contributing Code or Documentation To The Fossil Project} |
| 22 | customskin.md {Theming: Customizing The Appearance of Web Pages} |
| 23 | custom_ticket.wiki {Customizing The Ticket System} |
| 24 | delta_encoder_algorithm.wiki {Fossil Delta Encoding Algorithm} |
| 25 | delta_format.wiki {Fossil Delta Format} |
| 26 | embeddeddoc.wiki {Embedded Project Documentation} |
| 27 |
| --- www/mkindex.tcl | |
| +++ www/mkindex.tcl | |
| @@ -17,10 +17,11 @@ | |
| 17 | checkin.wiki {Check-in Checklist} |
| 18 | changes.wiki {Fossil Changelog} |
| 19 | copyright-release.html {Contributor License Agreement} |
| 20 | concepts.wiki {Fossil Core Concepts} |
| 21 | contribute.wiki {Contributing Code or Documentation To The Fossil Project} |
| 22 | customgraph.md {Theming: Customizing the Timeline Graph} |
| 23 | customskin.md {Theming: Customizing The Appearance of Web Pages} |
| 24 | custom_ticket.wiki {Customizing The Ticket System} |
| 25 | delta_encoder_algorithm.wiki {Fossil Delta Encoding Algorithm} |
| 26 | delta_format.wiki {Fossil Delta Format} |
| 27 | embeddeddoc.wiki {Embedded Project Documentation} |
| 28 |
+5
-1
| --- www/permutedindex.html | ||
| +++ www/permutedindex.html | ||
| @@ -34,12 +34,12 @@ | ||
| 34 | 34 | <li><a href="private.wiki">Branches — Creating, Syncing, and Deleting Private</a></li> |
| 35 | 35 | <li><a href="branching.wiki">Branching, Forking, Merging, and Tagging</a></li> |
| 36 | 36 | <li><a href="bugtheory.wiki">Bug Tracking In Fossil</a></li> |
| 37 | 37 | <li><a href="makefile.wiki">Build Process — The Fossil</a></li> |
| 38 | 38 | <li><a href="changes.wiki">Changelog — Fossil</a></li> |
| 39 | -<li><a href="checkin.wiki">Check-in Checklist</a></li> | |
| 40 | 39 | <li><a href="checkin_names.wiki">Check-in And Version Names</a></li> |
| 40 | +<li><a href="checkin.wiki">Check-in Checklist</a></li> | |
| 41 | 41 | <li><a href="checkin.wiki">Checklist — Check-in</a></li> |
| 42 | 42 | <li><a href="../test/release-checklist.wiki">Checklist — Pre-Release Testing</a></li> |
| 43 | 43 | <li><a href="foss-cklist.wiki">Checklist For Successful Open-Source Projects</a></li> |
| 44 | 44 | <li><a href="selfcheck.wiki">Checks — Fossil Repository Integrity Self</a></li> |
| 45 | 45 | <li><a href="contribute.wiki">Code or Documentation To The Fossil Project — Contributing</a></li> |
| @@ -54,10 +54,11 @@ | ||
| 54 | 54 | <li><a href="newrepo.wiki">Create A New Fossil Repository — How To</a></li> |
| 55 | 55 | <li><a href="private.wiki">Creating, Syncing, and Deleting Private Branches</a></li> |
| 56 | 56 | <li><a href="qandc.wiki">Criticisms — Questions And</a></li> |
| 57 | 57 | <li><a href="customskin.md">Customizing The Appearance of Web Pages — Theming:</a></li> |
| 58 | 58 | <li><a href="custom_ticket.wiki">Customizing The Ticket System</a></li> |
| 59 | +<li><a href="customgraph.md">Customizing the Timeline Graph — Theming:</a></li> | |
| 59 | 60 | <li><a href="tech_overview.wiki">Databases Used By Fossil — SQLite</a></li> |
| 60 | 61 | <li><a href="antibot.wiki">Defense against Spiders and Bots</a></li> |
| 61 | 62 | <li><a href="shunning.wiki">Deleting Content From Fossil — Shunning:</a></li> |
| 62 | 63 | <li><a href="private.wiki">Deleting Private Branches — Creating, Syncing, and</a></li> |
| 63 | 64 | <li><a href="delta_encoder_algorithm.wiki">Delta Encoding Algorithm — Fossil</a></li> |
| @@ -95,10 +96,11 @@ | ||
| 95 | 96 | <li><a href="inout.wiki">From Git — Import And Export To And</a></li> |
| 96 | 97 | <li><a href="quotes.wiki">General — Quotes: What People Are Saying About Fossil, Git, and DVCSes in</a></li> |
| 97 | 98 | <li><a href="fossil-v-git.wiki">Git — Fossil Versus</a></li> |
| 98 | 99 | <li><a href="inout.wiki">Git — Import And Export To And From</a></li> |
| 99 | 100 | <li><a href="quotes.wiki">Git, and DVCSes in General — Quotes: What People Are Saying About Fossil,</a></li> |
| 101 | +<li><a href="customgraph.md">Graph — Theming: Customizing the Timeline</a></li> | |
| 100 | 102 | <li><a href="quickstart.wiki">Guide — Fossil Quick Start</a></li> |
| 101 | 103 | <li><a href="style.wiki">Guidelines — Source Code Style</a></li> |
| 102 | 104 | <li><a href="hacker-howto.wiki">Hacker How-To</a></li> |
| 103 | 105 | <li><a href="adding_code.wiki">Hacking Fossil</a></li> |
| 104 | 106 | <li><a href="hints.wiki">Hints — Fossil Tips And Usage</a></li> |
| @@ -176,13 +178,15 @@ | ||
| 176 | 178 | <li><a href="sync.wiki">The Fossil Sync Protocol</a></li> |
| 177 | 179 | <li><a href="tickets.wiki">The Fossil Ticket System</a></li> |
| 178 | 180 | <li><a href="webui.wiki">The Fossil Web Interface</a></li> |
| 179 | 181 | <li><a href="th1.md">The TH1 Scripting Language</a></li> |
| 180 | 182 | <li><a href="customskin.md">Theming: Customizing The Appearance of Web Pages</a></li> |
| 183 | +<li><a href="customgraph.md">Theming: Customizing the Timeline Graph</a></li> | |
| 181 | 184 | <li><a href="theory1.wiki">Thoughts On The Design Of The Fossil DVCS</a></li> |
| 182 | 185 | <li><a href="custom_ticket.wiki">Ticket System — Customizing The</a></li> |
| 183 | 186 | <li><a href="tickets.wiki">Ticket System — The Fossil</a></li> |
| 187 | +<li><a href="customgraph.md">Timeline Graph — Theming: Customizing the</a></li> | |
| 184 | 188 | <li><a href="hints.wiki">Tips And Usage Hints — Fossil</a></li> |
| 185 | 189 | <li><a href="bugtheory.wiki">Tracking In Fossil — Bug</a></li> |
| 186 | 190 | <li><a href="fiveminutes.wiki">Update and Running in 5 Minutes as a Single User</a></li> |
| 187 | 191 | <li><a href="hints.wiki">Usage Hints — Fossil Tips And</a></li> |
| 188 | 192 | <li><a href="fiveminutes.wiki">User — Update and Running in 5 Minutes as a Single</a></li> |
| 189 | 193 |
| --- www/permutedindex.html | |
| +++ www/permutedindex.html | |
| @@ -34,12 +34,12 @@ | |
| 34 | <li><a href="private.wiki">Branches — Creating, Syncing, and Deleting Private</a></li> |
| 35 | <li><a href="branching.wiki">Branching, Forking, Merging, and Tagging</a></li> |
| 36 | <li><a href="bugtheory.wiki">Bug Tracking In Fossil</a></li> |
| 37 | <li><a href="makefile.wiki">Build Process — The Fossil</a></li> |
| 38 | <li><a href="changes.wiki">Changelog — Fossil</a></li> |
| 39 | <li><a href="checkin.wiki">Check-in Checklist</a></li> |
| 40 | <li><a href="checkin_names.wiki">Check-in And Version Names</a></li> |
| 41 | <li><a href="checkin.wiki">Checklist — Check-in</a></li> |
| 42 | <li><a href="../test/release-checklist.wiki">Checklist — Pre-Release Testing</a></li> |
| 43 | <li><a href="foss-cklist.wiki">Checklist For Successful Open-Source Projects</a></li> |
| 44 | <li><a href="selfcheck.wiki">Checks — Fossil Repository Integrity Self</a></li> |
| 45 | <li><a href="contribute.wiki">Code or Documentation To The Fossil Project — Contributing</a></li> |
| @@ -54,10 +54,11 @@ | |
| 54 | <li><a href="newrepo.wiki">Create A New Fossil Repository — How To</a></li> |
| 55 | <li><a href="private.wiki">Creating, Syncing, and Deleting Private Branches</a></li> |
| 56 | <li><a href="qandc.wiki">Criticisms — Questions And</a></li> |
| 57 | <li><a href="customskin.md">Customizing The Appearance of Web Pages — Theming:</a></li> |
| 58 | <li><a href="custom_ticket.wiki">Customizing The Ticket System</a></li> |
| 59 | <li><a href="tech_overview.wiki">Databases Used By Fossil — SQLite</a></li> |
| 60 | <li><a href="antibot.wiki">Defense against Spiders and Bots</a></li> |
| 61 | <li><a href="shunning.wiki">Deleting Content From Fossil — Shunning:</a></li> |
| 62 | <li><a href="private.wiki">Deleting Private Branches — Creating, Syncing, and</a></li> |
| 63 | <li><a href="delta_encoder_algorithm.wiki">Delta Encoding Algorithm — Fossil</a></li> |
| @@ -95,10 +96,11 @@ | |
| 95 | <li><a href="inout.wiki">From Git — Import And Export To And</a></li> |
| 96 | <li><a href="quotes.wiki">General — Quotes: What People Are Saying About Fossil, Git, and DVCSes in</a></li> |
| 97 | <li><a href="fossil-v-git.wiki">Git — Fossil Versus</a></li> |
| 98 | <li><a href="inout.wiki">Git — Import And Export To And From</a></li> |
| 99 | <li><a href="quotes.wiki">Git, and DVCSes in General — Quotes: What People Are Saying About Fossil,</a></li> |
| 100 | <li><a href="quickstart.wiki">Guide — Fossil Quick Start</a></li> |
| 101 | <li><a href="style.wiki">Guidelines — Source Code Style</a></li> |
| 102 | <li><a href="hacker-howto.wiki">Hacker How-To</a></li> |
| 103 | <li><a href="adding_code.wiki">Hacking Fossil</a></li> |
| 104 | <li><a href="hints.wiki">Hints — Fossil Tips And Usage</a></li> |
| @@ -176,13 +178,15 @@ | |
| 176 | <li><a href="sync.wiki">The Fossil Sync Protocol</a></li> |
| 177 | <li><a href="tickets.wiki">The Fossil Ticket System</a></li> |
| 178 | <li><a href="webui.wiki">The Fossil Web Interface</a></li> |
| 179 | <li><a href="th1.md">The TH1 Scripting Language</a></li> |
| 180 | <li><a href="customskin.md">Theming: Customizing The Appearance of Web Pages</a></li> |
| 181 | <li><a href="theory1.wiki">Thoughts On The Design Of The Fossil DVCS</a></li> |
| 182 | <li><a href="custom_ticket.wiki">Ticket System — Customizing The</a></li> |
| 183 | <li><a href="tickets.wiki">Ticket System — The Fossil</a></li> |
| 184 | <li><a href="hints.wiki">Tips And Usage Hints — Fossil</a></li> |
| 185 | <li><a href="bugtheory.wiki">Tracking In Fossil — Bug</a></li> |
| 186 | <li><a href="fiveminutes.wiki">Update and Running in 5 Minutes as a Single User</a></li> |
| 187 | <li><a href="hints.wiki">Usage Hints — Fossil Tips And</a></li> |
| 188 | <li><a href="fiveminutes.wiki">User — Update and Running in 5 Minutes as a Single</a></li> |
| 189 |
| --- www/permutedindex.html | |
| +++ www/permutedindex.html | |
| @@ -34,12 +34,12 @@ | |
| 34 | <li><a href="private.wiki">Branches — Creating, Syncing, and Deleting Private</a></li> |
| 35 | <li><a href="branching.wiki">Branching, Forking, Merging, and Tagging</a></li> |
| 36 | <li><a href="bugtheory.wiki">Bug Tracking In Fossil</a></li> |
| 37 | <li><a href="makefile.wiki">Build Process — The Fossil</a></li> |
| 38 | <li><a href="changes.wiki">Changelog — Fossil</a></li> |
| 39 | <li><a href="checkin_names.wiki">Check-in And Version Names</a></li> |
| 40 | <li><a href="checkin.wiki">Check-in Checklist</a></li> |
| 41 | <li><a href="checkin.wiki">Checklist — Check-in</a></li> |
| 42 | <li><a href="../test/release-checklist.wiki">Checklist — Pre-Release Testing</a></li> |
| 43 | <li><a href="foss-cklist.wiki">Checklist For Successful Open-Source Projects</a></li> |
| 44 | <li><a href="selfcheck.wiki">Checks — Fossil Repository Integrity Self</a></li> |
| 45 | <li><a href="contribute.wiki">Code or Documentation To The Fossil Project — Contributing</a></li> |
| @@ -54,10 +54,11 @@ | |
| 54 | <li><a href="newrepo.wiki">Create A New Fossil Repository — How To</a></li> |
| 55 | <li><a href="private.wiki">Creating, Syncing, and Deleting Private Branches</a></li> |
| 56 | <li><a href="qandc.wiki">Criticisms — Questions And</a></li> |
| 57 | <li><a href="customskin.md">Customizing The Appearance of Web Pages — Theming:</a></li> |
| 58 | <li><a href="custom_ticket.wiki">Customizing The Ticket System</a></li> |
| 59 | <li><a href="customgraph.md">Customizing the Timeline Graph — Theming:</a></li> |
| 60 | <li><a href="tech_overview.wiki">Databases Used By Fossil — SQLite</a></li> |
| 61 | <li><a href="antibot.wiki">Defense against Spiders and Bots</a></li> |
| 62 | <li><a href="shunning.wiki">Deleting Content From Fossil — Shunning:</a></li> |
| 63 | <li><a href="private.wiki">Deleting Private Branches — Creating, Syncing, and</a></li> |
| 64 | <li><a href="delta_encoder_algorithm.wiki">Delta Encoding Algorithm — Fossil</a></li> |
| @@ -95,10 +96,11 @@ | |
| 96 | <li><a href="inout.wiki">From Git — Import And Export To And</a></li> |
| 97 | <li><a href="quotes.wiki">General — Quotes: What People Are Saying About Fossil, Git, and DVCSes in</a></li> |
| 98 | <li><a href="fossil-v-git.wiki">Git — Fossil Versus</a></li> |
| 99 | <li><a href="inout.wiki">Git — Import And Export To And From</a></li> |
| 100 | <li><a href="quotes.wiki">Git, and DVCSes in General — Quotes: What People Are Saying About Fossil,</a></li> |
| 101 | <li><a href="customgraph.md">Graph — Theming: Customizing the Timeline</a></li> |
| 102 | <li><a href="quickstart.wiki">Guide — Fossil Quick Start</a></li> |
| 103 | <li><a href="style.wiki">Guidelines — Source Code Style</a></li> |
| 104 | <li><a href="hacker-howto.wiki">Hacker How-To</a></li> |
| 105 | <li><a href="adding_code.wiki">Hacking Fossil</a></li> |
| 106 | <li><a href="hints.wiki">Hints — Fossil Tips And Usage</a></li> |
| @@ -176,13 +178,15 @@ | |
| 178 | <li><a href="sync.wiki">The Fossil Sync Protocol</a></li> |
| 179 | <li><a href="tickets.wiki">The Fossil Ticket System</a></li> |
| 180 | <li><a href="webui.wiki">The Fossil Web Interface</a></li> |
| 181 | <li><a href="th1.md">The TH1 Scripting Language</a></li> |
| 182 | <li><a href="customskin.md">Theming: Customizing The Appearance of Web Pages</a></li> |
| 183 | <li><a href="customgraph.md">Theming: Customizing the Timeline Graph</a></li> |
| 184 | <li><a href="theory1.wiki">Thoughts On The Design Of The Fossil DVCS</a></li> |
| 185 | <li><a href="custom_ticket.wiki">Ticket System — Customizing The</a></li> |
| 186 | <li><a href="tickets.wiki">Ticket System — The Fossil</a></li> |
| 187 | <li><a href="customgraph.md">Timeline Graph — Theming: Customizing the</a></li> |
| 188 | <li><a href="hints.wiki">Tips And Usage Hints — Fossil</a></li> |
| 189 | <li><a href="bugtheory.wiki">Tracking In Fossil — Bug</a></li> |
| 190 | <li><a href="fiveminutes.wiki">Update and Running in 5 Minutes as a Single User</a></li> |
| 191 | <li><a href="hints.wiki">Usage Hints — Fossil Tips And</a></li> |
| 192 | <li><a href="fiveminutes.wiki">User — Update and Running in 5 Minutes as a Single</a></li> |
| 193 |
+78
-39
| --- www/th1.md | ||
| +++ www/th1.md | ||
| @@ -166,90 +166,90 @@ | ||
| 166 | 166 | All commands starting with "tcl", with the exception of "tclReady", |
| 167 | 167 | require the Tcl integration subsystem be included at compile-time. |
| 168 | 168 | Additionally, the "tcl" repository setting must be enabled at runtime |
| 169 | 169 | in order to successfully make use of these commands. |
| 170 | 170 | |
| 171 | -TH1 anoncap Command | |
| -------------------- | ||
| 171 | +<a name="anoncap"></a>TH1 anoncap Command | |
| 172 | +----------------------------------------- | |
| 172 | 173 | |
| 173 | 174 | * anoncap STRING... |
| 174 | 175 | |
| 175 | 176 | Returns true if the anonymous user has all of the capabilities listed |
| 176 | 177 | in STRING. |
| 177 | 178 | |
| 178 | -TH1 anycap Command | |
| ------------------- | ||
| 179 | +<a name="anycap"></a>TH1 anycap Command | |
| 180 | +--------------------------------------- | |
| 179 | 181 | |
| 180 | 182 | * anycap STRING |
| 181 | 183 | |
| 182 | 184 | Returns true if the current user user has any one of the capabilities |
| 183 | 185 | listed in STRING. |
| 184 | 186 | |
| 185 | -TH1 artifact Command | |
| --------------------- | ||
| 187 | +<a name="artifact"></a>TH1 artifact Command | |
| 188 | +------------------------------------------- | |
| 186 | 189 | |
| 187 | 190 | * artifact ID ?FILENAME? |
| 188 | 191 | |
| 189 | 192 | Attempts to locate the specified artifact and return its contents. An |
| 190 | 193 | error is generated if the repository is not open or the artifact cannot |
| 191 | 194 | be found. |
| 192 | 195 | |
| 193 | -TH1 checkout Command | |
| --------------------- | ||
| 196 | +<a name="checkout"></a>TH1 checkout Command | |
| 197 | +------------------------------------------- | |
| 194 | 198 | |
| 195 | 199 | * checkout ?BOOLEAN? |
| 196 | 200 | |
| 197 | 201 | Return the fully qualified directory name of the current checkout or an |
| 198 | 202 | empty string if it is not available. Optionally, it will attempt to find |
| 199 | 203 | the current checkout, opening the configuration ("user") database and the |
| 200 | 204 | repository as necessary, if the boolean argument is non-zero. |
| 201 | 205 | |
| 202 | -TH1 combobox Command | |
| --------------------- | ||
| 206 | +<a name="combobox"></a>TH1 combobox Command | |
| 207 | +------------------------------------------- | |
| 203 | 208 | |
| 204 | 209 | * combobox NAME TEXT-LIST NUMLINES |
| 205 | 210 | |
| 206 | 211 | Generates and emits an HTML combobox. NAME is both the name of the |
| 207 | 212 | CGI parameter and the name of a variable that contains the currently |
| 208 | 213 | selected value. TEXT-LIST is a list of possible values for the |
| 209 | 214 | combobox. NUMLINES is 1 for a true combobox. If NUMLINES is greater |
| 210 | 215 | than one then the display is a listbox with the number of lines given. |
| 211 | 216 | |
| 212 | -TH1 date Command | |
| ----------------- | ||
| 217 | +<a name="date"></a>TH1 date Command | |
| 218 | +----------------------------------- | |
| 213 | 219 | |
| 214 | 220 | * date ?-local? |
| 215 | 221 | |
| 216 | 222 | Return a strings which is the current time and date. If the -local |
| 217 | 223 | option is used, the date appears using localtime instead of UTC. |
| 218 | 224 | |
| 219 | -TH1 decorate Command | |
| --------------------- | ||
| 225 | +<a name="decorate"></a>TH1 decorate Command | |
| 226 | +------------------------------------------- | |
| 220 | 227 | |
| 221 | 228 | * decorate STRING |
| 222 | 229 | |
| 223 | 230 | Renders STRING as wiki content; however, only links are handled. No |
| 224 | 231 | other markup is processed. |
| 225 | 232 | |
| 226 | -TH1 enable_output Command | |
| -------------------------- | ||
| 233 | +<a name="enable_output"></a>TH1 enable_output Command | |
| 234 | +----------------------------------------------------- | |
| 227 | 235 | |
| 228 | 236 | * enable_output BOOLEAN |
| 229 | 237 | |
| 230 | 238 | Enable or disable sending output when the combobox, puts, or wiki |
| 231 | 239 | commands are used. |
| 232 | 240 | |
| 233 | -TH1 getParameter Command | |
| ------------------------- | ||
| 241 | +<a name="getParameter"></a>TH1 getParameter Command | |
| 242 | +--------------------------------------------------- | |
| 234 | 243 | |
| 235 | 244 | * getParameter NAME ?DEFAULT? |
| 236 | 245 | |
| 237 | 246 | Returns the value of the specified query parameter or the specified |
| 238 | 247 | default value when there is no matching query parameter. |
| 239 | 248 | |
| 240 | -TH1 globalState Command | |
| ------------------------ | ||
| 249 | +<a name="globalState"></a>TH1 globalState Command | |
| 250 | +------------------------------------------------- | |
| 241 | 251 | |
| 242 | 252 | * globalState NAME ?DEFAULT? |
| 243 | 253 | |
| 244 | 254 | Returns a string containing the value of the specified global state |
| 245 | 255 | variable -OR- the specified default value. The supported items are: |
| @@ -266,20 +266,20 @@ | ||
| 266 | 266 | |
| 267 | 267 | Attempts to query for unsupported global state variables will result |
| 268 | 268 | in a script error. Additional global state variables may be exposed |
| 269 | 269 | in the future. |
| 270 | 270 | |
| 271 | -TH1 hascap Command | |
| ------------------- | ||
| 271 | +<a name="hascap"></a>TH1 hascap Command | |
| 272 | +--------------------------------------- | |
| 272 | 273 | |
| 273 | 274 | * hascap STRING... |
| 274 | 275 | |
| 275 | 276 | Returns true if the current user has all of the capabilities listed |
| 276 | 277 | in STRING. |
| 277 | 278 | |
| 278 | -TH1 hasfeature Command | |
| ----------------------- | ||
| 279 | +<a name="hasfeature"></a>TH1 hasfeature Command | |
| 280 | +----------------------------------------------- | |
| 279 | 281 | |
| 280 | 282 | * hasfeature STRING |
| 281 | 283 | |
| 282 | 284 | Returns true if the binary has the given compile-time feature enabled. |
| 283 | 285 | The possible features are: |
| @@ -294,27 +294,27 @@ | ||
| 294 | 294 | 1. **tclPrivateStubs** -- _Uses Tcl private stubs (i.e. header-only)._ |
| 295 | 295 | 1. **json** -- _Support for the JSON APIs._ |
| 296 | 296 | 1. **markdown** -- _Support for Markdown documentation format._ |
| 297 | 297 | 1. **unicodeCmdLine** -- _The command line arguments are Unicode._ |
| 298 | 298 | |
| 299 | -TH1 html Command | |
| ----------------- | ||
| 299 | +<a name="html"></a>TH1 html Command | |
| 300 | +----------------------------------- | |
| 300 | 301 | |
| 301 | 302 | * html STRING |
| 302 | 303 | |
| 303 | 304 | Outputs the STRING escaped for HTML. |
| 304 | 305 | |
| 305 | -TH1 htmlize Command | |
| -------------------- | ||
| 306 | +<a name="htmlize"></a>TH1 htmlize Command | |
| 307 | +----------------------------------------- | |
| 306 | 308 | |
| 307 | 309 | * htmlize STRING |
| 308 | 310 | |
| 309 | 311 | Escape all characters of STRING which have special meaning in HTML. |
| 310 | 312 | Returns the escaped string. |
| 311 | 313 | |
| 312 | -TH1 http Command | |
| ----------------- | ||
| 314 | +<a name="http"></a>TH1 http Command | |
| 315 | +----------------------------------- | |
| 313 | 316 | |
| 314 | 317 | * http ?-asynchronous? ?--? url ?payload? |
| 315 | 318 | |
| 316 | 319 | Performs an HTTP or HTTPS request for the specified URL. If a |
| 317 | 320 | payload is present, it will be interpreted as text/plain and |
| @@ -322,35 +322,35 @@ | ||
| 322 | 322 | be used. Upon success, if the -asynchronous option is used, an |
| 323 | 323 | empty string is returned as the result; otherwise, the response |
| 324 | 324 | from the server is returned as the result. Synchronous requests |
| 325 | 325 | are not currently implemented. |
| 326 | 326 | |
| 327 | -TH1 httpize Command | |
| -------------------- | ||
| 327 | +<a name="httpize"></a>TH1 httpize Command | |
| 328 | +----------------------------------------- | |
| 328 | 329 | |
| 329 | 330 | * httpize STRING |
| 330 | 331 | |
| 331 | 332 | Escape all characters of STRING which have special meaning in URI |
| 332 | 333 | components. Returns the escaped string. |
| 333 | 334 | |
| 334 | -TH1 linecount Command | |
| ---------------------- | ||
| 335 | +<a name="linecount"></a>TH1 linecount Command | |
| 336 | +--------------------------------------------- | |
| 335 | 337 | |
| 336 | 338 | * linecount STRING MAX MIN |
| 337 | 339 | |
| 338 | 340 | Returns one more than the number of \n characters in STRING. But |
| 339 | 341 | never returns less than MIN or more than MAX. |
| 340 | 342 | |
| 341 | -TH1 puts Command | |
| ----------------- | ||
| 343 | +<a name="puts"></a>TH1 puts Command | |
| 344 | +----------------------------------- | |
| 342 | 345 | |
| 343 | 346 | * puts STRING |
| 344 | 347 | |
| 345 | 348 | Outputs the STRING unchanged. |
| 346 | 349 | |
| 347 | -TH1 query Command | |
| ------------------ | ||
| 350 | +<a name="query"></a>TH1 query Command | |
| 351 | +------------------------------------- | |
| 348 | 352 | |
| 349 | 353 | * query SQL CODE |
| 350 | 354 | |
| 351 | 355 | Runs the SQL query given by the SQL argument. For each row in the result |
| 352 | 356 | set, run CODE. |
| @@ -357,52 +357,52 @@ | ||
| 357 | 357 | |
| 358 | 358 | In SQL, parameters such as $var are filled in using the value of variable |
| 359 | 359 | "var". Result values are stored in variables with the column name prior |
| 360 | 360 | to each invocation of CODE. |
| 361 | 361 | |
| 362 | -TH1 randhex Command | |
| -------------------- | ||
| 362 | +<a name="randhex"></a>TH1 randhex Command | |
| 363 | +----------------------------------------- | |
| 363 | 364 | |
| 364 | 365 | * randhex N |
| 365 | 366 | |
| 366 | 367 | Returns a string of N*2 random hexadecimal digits with N<50. If N is |
| 367 | 368 | omitted, use a value of 10. |
| 368 | 369 | |
| 369 | -TH1 regexp Command | |
| ------------------- | ||
| 370 | +<a name="regexp"></a>TH1 regexp Command | |
| 371 | +--------------------------------------- | |
| 370 | 372 | |
| 371 | 373 | * regexp ?-nocase? ?--? exp string |
| 372 | 374 | |
| 373 | 375 | Checks the string against the specified regular expression and returns |
| 374 | 376 | non-zero if it matches. If the regular expression is invalid or cannot |
| 375 | 377 | be compiled, an error will be generated. |
| 376 | 378 | |
| 377 | -TH1 reinitialize Command | |
| ------------------------- | ||
| 379 | +<a name="reinitialize"></a>TH1 reinitialize Command | |
| 380 | +--------------------------------------------------- | |
| 378 | 381 | |
| 379 | 382 | * reinitialize ?FLAGS? |
| 380 | 383 | |
| 381 | 384 | Reinitializes the TH1 interpreter using the specified flags. |
| 382 | 385 | |
| 383 | -TH1 render Command | |
| ------------------- | ||
| 386 | +<a name="render"></a>TH1 render Command | |
| 387 | +--------------------------------------- | |
| 384 | 388 | |
| 385 | 389 | * render STRING |
| 386 | 390 | |
| 387 | 391 | Renders the TH1 template and writes the results. |
| 388 | 392 | |
| 389 | -TH1 repository Command | |
| ----------------------- | ||
| 393 | +<a name="repository"></a>TH1 repository Command | |
| 394 | +----------------------------------------------- | |
| 390 | 395 | |
| 391 | 396 | * repository ?BOOLEAN? |
| 392 | 397 | |
| 393 | 398 | Returns the fully qualified file name of the open repository or an empty |
| 394 | 399 | string if one is not currently open. Optionally, it will attempt to open |
| 395 | 400 | the repository if the boolean argument is non-zero. |
| 396 | 401 | |
| 397 | -TH1 searchable Command | |
| ----------------------- | ||
| 402 | +<a name="searchable"></a>TH1 searchable Command | |
| 403 | +----------------------------------------------- | |
| 398 | 404 | |
| 399 | 405 | * searchable STRING... |
| 400 | 406 | |
| 401 | 407 | Return true if searching in any of the document classes identified |
| 402 | 408 | by STRING is enabled for the repository and user has the necessary |
| @@ -426,104 +426,104 @@ | ||
| 426 | 426 | if {[searchable cdtw]} {...} |
| 427 | 427 | |
| 428 | 428 | This command is useful for enabling or disabling a "Search" entry on the |
| 429 | 429 | menu bar. |
| 430 | 430 | |
| 431 | -TH1 setParameter Command | |
| ------------------------- | ||
| 431 | +<a name="setParameter"></a>TH1 setParameter Command | |
| 432 | +--------------------------------------------------- | |
| 432 | 433 | |
| 433 | 434 | * setParameter NAME VALUE |
| 434 | 435 | |
| 435 | 436 | Sets the value of the specified query parameter. |
| 436 | 437 | |
| 437 | -TH1 setting Command | |
| -------------------- | ||
| 438 | +<a name="setting"></a>TH1 setting Command | |
| 439 | +----------------------------------------- | |
| 438 | 440 | |
| 439 | 441 | * setting name |
| 440 | 442 | |
| 441 | 443 | Gets and returns the value of the specified setting. |
| 442 | 444 | |
| 443 | -TH1 styleHeader Command | |
| ------------------------ | ||
| 445 | +<a name="styleHeader"></a>TH1 styleHeader Command | |
| 446 | +------------------------------------------------- | |
| 444 | 447 | |
| 445 | 448 | * styleHeader TITLE |
| 446 | 449 | |
| 447 | 450 | Render the configured style header. |
| 448 | 451 | |
| 449 | -TH1 styleFooter Command | |
| ------------------------ | ||
| 452 | +<a name="styleFooter"></a>TH1 styleFooter Command | |
| 453 | +------------------------------------------------- | |
| 450 | 454 | |
| 451 | 455 | * styleFooter |
| 452 | 456 | |
| 453 | 457 | Render the configured style footer. |
| 454 | 458 | |
| 455 | -TH1 tclEval Command | |
| -------------------- | ||
| 459 | +<a name="tclEval"></a>TH1 tclEval Command | |
| 460 | +----------------------------------------- | |
| 456 | 461 | |
| 457 | 462 | **This command requires the Tcl integration feature.** |
| 458 | 463 | |
| 459 | 464 | * tclEval arg ?arg ...? |
| 460 | 465 | |
| 461 | 466 | Evaluates the Tcl script and returns its result verbatim. If a Tcl script |
| 462 | 467 | error is generated, it will be transformed into a TH1 script error. A Tcl |
| 463 | 468 | interpreter will be created automatically if it has not been already. |
| 464 | 469 | |
| 465 | -TH1 tclExpr Command | |
| -------------------- | ||
| 470 | +<a name="tclExpr"></a>TH1 tclExpr Command | |
| 471 | +----------------------------------------- | |
| 466 | 472 | |
| 467 | 473 | **This command requires the Tcl integration feature.** |
| 468 | 474 | |
| 469 | 475 | * tclExpr arg ?arg ...? |
| 470 | 476 | |
| 471 | 477 | Evaluates the Tcl expression and returns its result verbatim. If a Tcl |
| 472 | 478 | script error is generated, it will be transformed into a TH1 script error. |
| 473 | 479 | A Tcl interpreter will be created automatically if it has not been already. |
| 474 | 480 | |
| 475 | -TH1 tclInvoke Command | |
| ---------------------- | ||
| 481 | +<a name="tclInvoke"></a>TH1 tclInvoke Command | |
| 482 | +--------------------------------------------- | |
| 476 | 483 | |
| 477 | 484 | **This command requires the Tcl integration feature.** |
| 478 | 485 | |
| 479 | 486 | * tclInvoke command ?arg ...? |
| 480 | 487 | |
| 481 | 488 | Invokes the Tcl command using the supplied arguments. No additional |
| 482 | 489 | substitutions are performed on the arguments. A Tcl interpreter will |
| 483 | 490 | be created automatically if it has not been already. |
| 484 | 491 | |
| 485 | -TH1 tclReady Command | |
| --------------------- | ||
| 492 | +<a name="tclReady"></a>TH1 tclReady Command | |
| 493 | +------------------------------------------- | |
| 486 | 494 | |
| 487 | 495 | * tclReady |
| 488 | 496 | |
| 489 | 497 | Returns true if the binary has the Tcl integration feature enabled and it |
| 490 | 498 | is currently available for use by TH1 scripts. |
| 491 | 499 | |
| 492 | -TH1 trace Command | |
| ------------------ | ||
| 500 | +<a name="trace"></a>TH1 trace Command | |
| 501 | +------------------------------------- | |
| 493 | 502 | |
| 494 | 503 | * trace STRING |
| 495 | 504 | |
| 496 | 505 | Generates a TH1 trace message if TH1 tracing is enabled. |
| 497 | 506 | |
| 498 | -TH1 stime Command | |
| ------------------ | ||
| 507 | +<a name="stime"></a>TH1 stime Command | |
| 508 | +------------------------------------- | |
| 499 | 509 | |
| 500 | 510 | * stime |
| 501 | 511 | |
| 502 | 512 | Returns the number of microseconds of CPU time consumed by the current |
| 503 | 513 | process in system space. |
| 504 | 514 | |
| 505 | -TH1 utime Command | |
| ------------------ | ||
| 515 | +<a name="utime"></a>TH1 utime Command | |
| 516 | +------------------------------------- | |
| 506 | 517 | |
| 507 | 518 | * utime |
| 508 | 519 | |
| 509 | 520 | Returns the number of microseconds of CPU time consumed by the current |
| 510 | 521 | process in user space. |
| 511 | 522 | |
| 512 | -TH1 wiki Command | |
| ----------------- | ||
| 523 | +<a name="wiki"></a>TH1 wiki Command | |
| 524 | +----------------------------------- | |
| 513 | 525 | |
| 514 | 526 | * wiki STRING |
| 515 | 527 | |
| 516 | 528 | Renders STRING as wiki content. |
| 517 | 529 | |
| @@ -536,22 +536,22 @@ | ||
| 536 | 536 | Tcl commands: |
| 537 | 537 | |
| 538 | 538 | * th1Eval |
| 539 | 539 | * th1Expr |
| 540 | 540 | |
| 541 | -Tcl th1Eval Command | |
| -------------------- | ||
| 541 | +<a name="th1Eval"></a>Tcl th1Eval Command | |
| 542 | +----------------------------------------- | |
| 542 | 543 | |
| 543 | 544 | **This command requires the Tcl integration feature.** |
| 544 | 545 | |
| 545 | 546 | * th1Eval arg |
| 546 | 547 | |
| 547 | 548 | Evaluates the TH1 script and returns its result verbatim. If a TH1 script |
| 548 | 549 | error is generated, it will be transformed into a Tcl script error. |
| 549 | 550 | |
| 550 | -Tcl th1Expr Command | |
| -------------------- | ||
| 551 | +<a name="th1Expr"></a>Tcl th1Expr Command | |
| 552 | +----------------------------------------- | |
| 551 | 553 | |
| 552 | 554 | **This command requires the Tcl integration feature.** |
| 553 | 555 | |
| 554 | 556 | * th1Expr arg |
| 555 | 557 | |
| 556 | 558 |
| --- www/th1.md | |
| +++ www/th1.md | |
| @@ -166,90 +166,90 @@ | |
| 166 | All commands starting with "tcl", with the exception of "tclReady", |
| 167 | require the Tcl integration subsystem be included at compile-time. |
| 168 | Additionally, the "tcl" repository setting must be enabled at runtime |
| 169 | in order to successfully make use of these commands. |
| 170 | |
| 171 | TH1 anoncap Command |
| -------------------- | |
| 172 | |
| 173 | * anoncap STRING... |
| 174 | |
| 175 | Returns true if the anonymous user has all of the capabilities listed |
| 176 | in STRING. |
| 177 | |
| 178 | TH1 anycap Command |
| ------------------- | |
| 179 | |
| 180 | * anycap STRING |
| 181 | |
| 182 | Returns true if the current user user has any one of the capabilities |
| 183 | listed in STRING. |
| 184 | |
| 185 | TH1 artifact Command |
| --------------------- | |
| 186 | |
| 187 | * artifact ID ?FILENAME? |
| 188 | |
| 189 | Attempts to locate the specified artifact and return its contents. An |
| 190 | error is generated if the repository is not open or the artifact cannot |
| 191 | be found. |
| 192 | |
| 193 | TH1 checkout Command |
| --------------------- | |
| 194 | |
| 195 | * checkout ?BOOLEAN? |
| 196 | |
| 197 | Return the fully qualified directory name of the current checkout or an |
| 198 | empty string if it is not available. Optionally, it will attempt to find |
| 199 | the current checkout, opening the configuration ("user") database and the |
| 200 | repository as necessary, if the boolean argument is non-zero. |
| 201 | |
| 202 | TH1 combobox Command |
| --------------------- | |
| 203 | |
| 204 | * combobox NAME TEXT-LIST NUMLINES |
| 205 | |
| 206 | Generates and emits an HTML combobox. NAME is both the name of the |
| 207 | CGI parameter and the name of a variable that contains the currently |
| 208 | selected value. TEXT-LIST is a list of possible values for the |
| 209 | combobox. NUMLINES is 1 for a true combobox. If NUMLINES is greater |
| 210 | than one then the display is a listbox with the number of lines given. |
| 211 | |
| 212 | TH1 date Command |
| ----------------- | |
| 213 | |
| 214 | * date ?-local? |
| 215 | |
| 216 | Return a strings which is the current time and date. If the -local |
| 217 | option is used, the date appears using localtime instead of UTC. |
| 218 | |
| 219 | TH1 decorate Command |
| --------------------- | |
| 220 | |
| 221 | * decorate STRING |
| 222 | |
| 223 | Renders STRING as wiki content; however, only links are handled. No |
| 224 | other markup is processed. |
| 225 | |
| 226 | TH1 enable_output Command |
| -------------------------- | |
| 227 | |
| 228 | * enable_output BOOLEAN |
| 229 | |
| 230 | Enable or disable sending output when the combobox, puts, or wiki |
| 231 | commands are used. |
| 232 | |
| 233 | TH1 getParameter Command |
| ------------------------- | |
| 234 | |
| 235 | * getParameter NAME ?DEFAULT? |
| 236 | |
| 237 | Returns the value of the specified query parameter or the specified |
| 238 | default value when there is no matching query parameter. |
| 239 | |
| 240 | TH1 globalState Command |
| ------------------------ | |
| 241 | |
| 242 | * globalState NAME ?DEFAULT? |
| 243 | |
| 244 | Returns a string containing the value of the specified global state |
| 245 | variable -OR- the specified default value. The supported items are: |
| @@ -266,20 +266,20 @@ | |
| 266 | |
| 267 | Attempts to query for unsupported global state variables will result |
| 268 | in a script error. Additional global state variables may be exposed |
| 269 | in the future. |
| 270 | |
| 271 | TH1 hascap Command |
| ------------------- | |
| 272 | |
| 273 | * hascap STRING... |
| 274 | |
| 275 | Returns true if the current user has all of the capabilities listed |
| 276 | in STRING. |
| 277 | |
| 278 | TH1 hasfeature Command |
| ----------------------- | |
| 279 | |
| 280 | * hasfeature STRING |
| 281 | |
| 282 | Returns true if the binary has the given compile-time feature enabled. |
| 283 | The possible features are: |
| @@ -294,27 +294,27 @@ | |
| 294 | 1. **tclPrivateStubs** -- _Uses Tcl private stubs (i.e. header-only)._ |
| 295 | 1. **json** -- _Support for the JSON APIs._ |
| 296 | 1. **markdown** -- _Support for Markdown documentation format._ |
| 297 | 1. **unicodeCmdLine** -- _The command line arguments are Unicode._ |
| 298 | |
| 299 | TH1 html Command |
| ----------------- | |
| 300 | |
| 301 | * html STRING |
| 302 | |
| 303 | Outputs the STRING escaped for HTML. |
| 304 | |
| 305 | TH1 htmlize Command |
| -------------------- | |
| 306 | |
| 307 | * htmlize STRING |
| 308 | |
| 309 | Escape all characters of STRING which have special meaning in HTML. |
| 310 | Returns the escaped string. |
| 311 | |
| 312 | TH1 http Command |
| ----------------- | |
| 313 | |
| 314 | * http ?-asynchronous? ?--? url ?payload? |
| 315 | |
| 316 | Performs an HTTP or HTTPS request for the specified URL. If a |
| 317 | payload is present, it will be interpreted as text/plain and |
| @@ -322,35 +322,35 @@ | |
| 322 | be used. Upon success, if the -asynchronous option is used, an |
| 323 | empty string is returned as the result; otherwise, the response |
| 324 | from the server is returned as the result. Synchronous requests |
| 325 | are not currently implemented. |
| 326 | |
| 327 | TH1 httpize Command |
| -------------------- | |
| 328 | |
| 329 | * httpize STRING |
| 330 | |
| 331 | Escape all characters of STRING which have special meaning in URI |
| 332 | components. Returns the escaped string. |
| 333 | |
| 334 | TH1 linecount Command |
| ---------------------- | |
| 335 | |
| 336 | * linecount STRING MAX MIN |
| 337 | |
| 338 | Returns one more than the number of \n characters in STRING. But |
| 339 | never returns less than MIN or more than MAX. |
| 340 | |
| 341 | TH1 puts Command |
| ----------------- | |
| 342 | |
| 343 | * puts STRING |
| 344 | |
| 345 | Outputs the STRING unchanged. |
| 346 | |
| 347 | TH1 query Command |
| ------------------ | |
| 348 | |
| 349 | * query SQL CODE |
| 350 | |
| 351 | Runs the SQL query given by the SQL argument. For each row in the result |
| 352 | set, run CODE. |
| @@ -357,52 +357,52 @@ | |
| 357 | |
| 358 | In SQL, parameters such as $var are filled in using the value of variable |
| 359 | "var". Result values are stored in variables with the column name prior |
| 360 | to each invocation of CODE. |
| 361 | |
| 362 | TH1 randhex Command |
| -------------------- | |
| 363 | |
| 364 | * randhex N |
| 365 | |
| 366 | Returns a string of N*2 random hexadecimal digits with N<50. If N is |
| 367 | omitted, use a value of 10. |
| 368 | |
| 369 | TH1 regexp Command |
| ------------------- | |
| 370 | |
| 371 | * regexp ?-nocase? ?--? exp string |
| 372 | |
| 373 | Checks the string against the specified regular expression and returns |
| 374 | non-zero if it matches. If the regular expression is invalid or cannot |
| 375 | be compiled, an error will be generated. |
| 376 | |
| 377 | TH1 reinitialize Command |
| ------------------------- | |
| 378 | |
| 379 | * reinitialize ?FLAGS? |
| 380 | |
| 381 | Reinitializes the TH1 interpreter using the specified flags. |
| 382 | |
| 383 | TH1 render Command |
| ------------------- | |
| 384 | |
| 385 | * render STRING |
| 386 | |
| 387 | Renders the TH1 template and writes the results. |
| 388 | |
| 389 | TH1 repository Command |
| ----------------------- | |
| 390 | |
| 391 | * repository ?BOOLEAN? |
| 392 | |
| 393 | Returns the fully qualified file name of the open repository or an empty |
| 394 | string if one is not currently open. Optionally, it will attempt to open |
| 395 | the repository if the boolean argument is non-zero. |
| 396 | |
| 397 | TH1 searchable Command |
| ----------------------- | |
| 398 | |
| 399 | * searchable STRING... |
| 400 | |
| 401 | Return true if searching in any of the document classes identified |
| 402 | by STRING is enabled for the repository and user has the necessary |
| @@ -426,104 +426,104 @@ | |
| 426 | if {[searchable cdtw]} {...} |
| 427 | |
| 428 | This command is useful for enabling or disabling a "Search" entry on the |
| 429 | menu bar. |
| 430 | |
| 431 | TH1 setParameter Command |
| ------------------------- | |
| 432 | |
| 433 | * setParameter NAME VALUE |
| 434 | |
| 435 | Sets the value of the specified query parameter. |
| 436 | |
| 437 | TH1 setting Command |
| -------------------- | |
| 438 | |
| 439 | * setting name |
| 440 | |
| 441 | Gets and returns the value of the specified setting. |
| 442 | |
| 443 | TH1 styleHeader Command |
| ------------------------ | |
| 444 | |
| 445 | * styleHeader TITLE |
| 446 | |
| 447 | Render the configured style header. |
| 448 | |
| 449 | TH1 styleFooter Command |
| ------------------------ | |
| 450 | |
| 451 | * styleFooter |
| 452 | |
| 453 | Render the configured style footer. |
| 454 | |
| 455 | TH1 tclEval Command |
| -------------------- | |
| 456 | |
| 457 | **This command requires the Tcl integration feature.** |
| 458 | |
| 459 | * tclEval arg ?arg ...? |
| 460 | |
| 461 | Evaluates the Tcl script and returns its result verbatim. If a Tcl script |
| 462 | error is generated, it will be transformed into a TH1 script error. A Tcl |
| 463 | interpreter will be created automatically if it has not been already. |
| 464 | |
| 465 | TH1 tclExpr Command |
| -------------------- | |
| 466 | |
| 467 | **This command requires the Tcl integration feature.** |
| 468 | |
| 469 | * tclExpr arg ?arg ...? |
| 470 | |
| 471 | Evaluates the Tcl expression and returns its result verbatim. If a Tcl |
| 472 | script error is generated, it will be transformed into a TH1 script error. |
| 473 | A Tcl interpreter will be created automatically if it has not been already. |
| 474 | |
| 475 | TH1 tclInvoke Command |
| ---------------------- | |
| 476 | |
| 477 | **This command requires the Tcl integration feature.** |
| 478 | |
| 479 | * tclInvoke command ?arg ...? |
| 480 | |
| 481 | Invokes the Tcl command using the supplied arguments. No additional |
| 482 | substitutions are performed on the arguments. A Tcl interpreter will |
| 483 | be created automatically if it has not been already. |
| 484 | |
| 485 | TH1 tclReady Command |
| --------------------- | |
| 486 | |
| 487 | * tclReady |
| 488 | |
| 489 | Returns true if the binary has the Tcl integration feature enabled and it |
| 490 | is currently available for use by TH1 scripts. |
| 491 | |
| 492 | TH1 trace Command |
| ------------------ | |
| 493 | |
| 494 | * trace STRING |
| 495 | |
| 496 | Generates a TH1 trace message if TH1 tracing is enabled. |
| 497 | |
| 498 | TH1 stime Command |
| ------------------ | |
| 499 | |
| 500 | * stime |
| 501 | |
| 502 | Returns the number of microseconds of CPU time consumed by the current |
| 503 | process in system space. |
| 504 | |
| 505 | TH1 utime Command |
| ------------------ | |
| 506 | |
| 507 | * utime |
| 508 | |
| 509 | Returns the number of microseconds of CPU time consumed by the current |
| 510 | process in user space. |
| 511 | |
| 512 | TH1 wiki Command |
| ----------------- | |
| 513 | |
| 514 | * wiki STRING |
| 515 | |
| 516 | Renders STRING as wiki content. |
| 517 | |
| @@ -536,22 +536,22 @@ | |
| 536 | Tcl commands: |
| 537 | |
| 538 | * th1Eval |
| 539 | * th1Expr |
| 540 | |
| 541 | Tcl th1Eval Command |
| -------------------- | |
| 542 | |
| 543 | **This command requires the Tcl integration feature.** |
| 544 | |
| 545 | * th1Eval arg |
| 546 | |
| 547 | Evaluates the TH1 script and returns its result verbatim. If a TH1 script |
| 548 | error is generated, it will be transformed into a Tcl script error. |
| 549 | |
| 550 | Tcl th1Expr Command |
| -------------------- | |
| 551 | |
| 552 | **This command requires the Tcl integration feature.** |
| 553 | |
| 554 | * th1Expr arg |
| 555 | |
| 556 |
| --- www/th1.md | |
| +++ www/th1.md | |
| @@ -166,90 +166,90 @@ | |
| 166 | All commands starting with "tcl", with the exception of "tclReady", |
| 167 | require the Tcl integration subsystem be included at compile-time. |
| 168 | Additionally, the "tcl" repository setting must be enabled at runtime |
| 169 | in order to successfully make use of these commands. |
| 170 | |
| -------------------- | |
| 171 | <a name="anoncap"></a>TH1 anoncap Command |
| 172 | ----------------------------------------- |
| 173 | |
| 174 | * anoncap STRING... |
| 175 | |
| 176 | Returns true if the anonymous user has all of the capabilities listed |
| 177 | in STRING. |
| 178 | |
| ------------------- | |
| 179 | <a name="anycap"></a>TH1 anycap Command |
| 180 | --------------------------------------- |
| 181 | |
| 182 | * anycap STRING |
| 183 | |
| 184 | Returns true if the current user user has any one of the capabilities |
| 185 | listed in STRING. |
| 186 | |
| --------------------- | |
| 187 | <a name="artifact"></a>TH1 artifact Command |
| 188 | ------------------------------------------- |
| 189 | |
| 190 | * artifact ID ?FILENAME? |
| 191 | |
| 192 | Attempts to locate the specified artifact and return its contents. An |
| 193 | error is generated if the repository is not open or the artifact cannot |
| 194 | be found. |
| 195 | |
| --------------------- | |
| 196 | <a name="checkout"></a>TH1 checkout Command |
| 197 | ------------------------------------------- |
| 198 | |
| 199 | * checkout ?BOOLEAN? |
| 200 | |
| 201 | Return the fully qualified directory name of the current checkout or an |
| 202 | empty string if it is not available. Optionally, it will attempt to find |
| 203 | the current checkout, opening the configuration ("user") database and the |
| 204 | repository as necessary, if the boolean argument is non-zero. |
| 205 | |
| --------------------- | |
| 206 | <a name="combobox"></a>TH1 combobox Command |
| 207 | ------------------------------------------- |
| 208 | |
| 209 | * combobox NAME TEXT-LIST NUMLINES |
| 210 | |
| 211 | Generates and emits an HTML combobox. NAME is both the name of the |
| 212 | CGI parameter and the name of a variable that contains the currently |
| 213 | selected value. TEXT-LIST is a list of possible values for the |
| 214 | combobox. NUMLINES is 1 for a true combobox. If NUMLINES is greater |
| 215 | than one then the display is a listbox with the number of lines given. |
| 216 | |
| ----------------- | |
| 217 | <a name="date"></a>TH1 date Command |
| 218 | ----------------------------------- |
| 219 | |
| 220 | * date ?-local? |
| 221 | |
| 222 | Return a strings which is the current time and date. If the -local |
| 223 | option is used, the date appears using localtime instead of UTC. |
| 224 | |
| --------------------- | |
| 225 | <a name="decorate"></a>TH1 decorate Command |
| 226 | ------------------------------------------- |
| 227 | |
| 228 | * decorate STRING |
| 229 | |
| 230 | Renders STRING as wiki content; however, only links are handled. No |
| 231 | other markup is processed. |
| 232 | |
| -------------------------- | |
| 233 | <a name="enable_output"></a>TH1 enable_output Command |
| 234 | ----------------------------------------------------- |
| 235 | |
| 236 | * enable_output BOOLEAN |
| 237 | |
| 238 | Enable or disable sending output when the combobox, puts, or wiki |
| 239 | commands are used. |
| 240 | |
| ------------------------- | |
| 241 | <a name="getParameter"></a>TH1 getParameter Command |
| 242 | --------------------------------------------------- |
| 243 | |
| 244 | * getParameter NAME ?DEFAULT? |
| 245 | |
| 246 | Returns the value of the specified query parameter or the specified |
| 247 | default value when there is no matching query parameter. |
| 248 | |
| ------------------------ | |
| 249 | <a name="globalState"></a>TH1 globalState Command |
| 250 | ------------------------------------------------- |
| 251 | |
| 252 | * globalState NAME ?DEFAULT? |
| 253 | |
| 254 | Returns a string containing the value of the specified global state |
| 255 | variable -OR- the specified default value. The supported items are: |
| @@ -266,20 +266,20 @@ | |
| 266 | |
| 267 | Attempts to query for unsupported global state variables will result |
| 268 | in a script error. Additional global state variables may be exposed |
| 269 | in the future. |
| 270 | |
| ------------------- | |
| 271 | <a name="hascap"></a>TH1 hascap Command |
| 272 | --------------------------------------- |
| 273 | |
| 274 | * hascap STRING... |
| 275 | |
| 276 | Returns true if the current user has all of the capabilities listed |
| 277 | in STRING. |
| 278 | |
| ----------------------- | |
| 279 | <a name="hasfeature"></a>TH1 hasfeature Command |
| 280 | ----------------------------------------------- |
| 281 | |
| 282 | * hasfeature STRING |
| 283 | |
| 284 | Returns true if the binary has the given compile-time feature enabled. |
| 285 | The possible features are: |
| @@ -294,27 +294,27 @@ | |
| 294 | 1. **tclPrivateStubs** -- _Uses Tcl private stubs (i.e. header-only)._ |
| 295 | 1. **json** -- _Support for the JSON APIs._ |
| 296 | 1. **markdown** -- _Support for Markdown documentation format._ |
| 297 | 1. **unicodeCmdLine** -- _The command line arguments are Unicode._ |
| 298 | |
| ----------------- | |
| 299 | <a name="html"></a>TH1 html Command |
| 300 | ----------------------------------- |
| 301 | |
| 302 | * html STRING |
| 303 | |
| 304 | Outputs the STRING escaped for HTML. |
| 305 | |
| -------------------- | |
| 306 | <a name="htmlize"></a>TH1 htmlize Command |
| 307 | ----------------------------------------- |
| 308 | |
| 309 | * htmlize STRING |
| 310 | |
| 311 | Escape all characters of STRING which have special meaning in HTML. |
| 312 | Returns the escaped string. |
| 313 | |
| ----------------- | |
| 314 | <a name="http"></a>TH1 http Command |
| 315 | ----------------------------------- |
| 316 | |
| 317 | * http ?-asynchronous? ?--? url ?payload? |
| 318 | |
| 319 | Performs an HTTP or HTTPS request for the specified URL. If a |
| 320 | payload is present, it will be interpreted as text/plain and |
| @@ -322,35 +322,35 @@ | |
| 322 | be used. Upon success, if the -asynchronous option is used, an |
| 323 | empty string is returned as the result; otherwise, the response |
| 324 | from the server is returned as the result. Synchronous requests |
| 325 | are not currently implemented. |
| 326 | |
| -------------------- | |
| 327 | <a name="httpize"></a>TH1 httpize Command |
| 328 | ----------------------------------------- |
| 329 | |
| 330 | * httpize STRING |
| 331 | |
| 332 | Escape all characters of STRING which have special meaning in URI |
| 333 | components. Returns the escaped string. |
| 334 | |
| ---------------------- | |
| 335 | <a name="linecount"></a>TH1 linecount Command |
| 336 | --------------------------------------------- |
| 337 | |
| 338 | * linecount STRING MAX MIN |
| 339 | |
| 340 | Returns one more than the number of \n characters in STRING. But |
| 341 | never returns less than MIN or more than MAX. |
| 342 | |
| ----------------- | |
| 343 | <a name="puts"></a>TH1 puts Command |
| 344 | ----------------------------------- |
| 345 | |
| 346 | * puts STRING |
| 347 | |
| 348 | Outputs the STRING unchanged. |
| 349 | |
| ------------------ | |
| 350 | <a name="query"></a>TH1 query Command |
| 351 | ------------------------------------- |
| 352 | |
| 353 | * query SQL CODE |
| 354 | |
| 355 | Runs the SQL query given by the SQL argument. For each row in the result |
| 356 | set, run CODE. |
| @@ -357,52 +357,52 @@ | |
| 357 | |
| 358 | In SQL, parameters such as $var are filled in using the value of variable |
| 359 | "var". Result values are stored in variables with the column name prior |
| 360 | to each invocation of CODE. |
| 361 | |
| -------------------- | |
| 362 | <a name="randhex"></a>TH1 randhex Command |
| 363 | ----------------------------------------- |
| 364 | |
| 365 | * randhex N |
| 366 | |
| 367 | Returns a string of N*2 random hexadecimal digits with N<50. If N is |
| 368 | omitted, use a value of 10. |
| 369 | |
| ------------------- | |
| 370 | <a name="regexp"></a>TH1 regexp Command |
| 371 | --------------------------------------- |
| 372 | |
| 373 | * regexp ?-nocase? ?--? exp string |
| 374 | |
| 375 | Checks the string against the specified regular expression and returns |
| 376 | non-zero if it matches. If the regular expression is invalid or cannot |
| 377 | be compiled, an error will be generated. |
| 378 | |
| ------------------------- | |
| 379 | <a name="reinitialize"></a>TH1 reinitialize Command |
| 380 | --------------------------------------------------- |
| 381 | |
| 382 | * reinitialize ?FLAGS? |
| 383 | |
| 384 | Reinitializes the TH1 interpreter using the specified flags. |
| 385 | |
| ------------------- | |
| 386 | <a name="render"></a>TH1 render Command |
| 387 | --------------------------------------- |
| 388 | |
| 389 | * render STRING |
| 390 | |
| 391 | Renders the TH1 template and writes the results. |
| 392 | |
| ----------------------- | |
| 393 | <a name="repository"></a>TH1 repository Command |
| 394 | ----------------------------------------------- |
| 395 | |
| 396 | * repository ?BOOLEAN? |
| 397 | |
| 398 | Returns the fully qualified file name of the open repository or an empty |
| 399 | string if one is not currently open. Optionally, it will attempt to open |
| 400 | the repository if the boolean argument is non-zero. |
| 401 | |
| ----------------------- | |
| 402 | <a name="searchable"></a>TH1 searchable Command |
| 403 | ----------------------------------------------- |
| 404 | |
| 405 | * searchable STRING... |
| 406 | |
| 407 | Return true if searching in any of the document classes identified |
| 408 | by STRING is enabled for the repository and user has the necessary |
| @@ -426,104 +426,104 @@ | |
| 426 | if {[searchable cdtw]} {...} |
| 427 | |
| 428 | This command is useful for enabling or disabling a "Search" entry on the |
| 429 | menu bar. |
| 430 | |
| ------------------------- | |
| 431 | <a name="setParameter"></a>TH1 setParameter Command |
| 432 | --------------------------------------------------- |
| 433 | |
| 434 | * setParameter NAME VALUE |
| 435 | |
| 436 | Sets the value of the specified query parameter. |
| 437 | |
| -------------------- | |
| 438 | <a name="setting"></a>TH1 setting Command |
| 439 | ----------------------------------------- |
| 440 | |
| 441 | * setting name |
| 442 | |
| 443 | Gets and returns the value of the specified setting. |
| 444 | |
| ------------------------ | |
| 445 | <a name="styleHeader"></a>TH1 styleHeader Command |
| 446 | ------------------------------------------------- |
| 447 | |
| 448 | * styleHeader TITLE |
| 449 | |
| 450 | Render the configured style header. |
| 451 | |
| ------------------------ | |
| 452 | <a name="styleFooter"></a>TH1 styleFooter Command |
| 453 | ------------------------------------------------- |
| 454 | |
| 455 | * styleFooter |
| 456 | |
| 457 | Render the configured style footer. |
| 458 | |
| -------------------- | |
| 459 | <a name="tclEval"></a>TH1 tclEval Command |
| 460 | ----------------------------------------- |
| 461 | |
| 462 | **This command requires the Tcl integration feature.** |
| 463 | |
| 464 | * tclEval arg ?arg ...? |
| 465 | |
| 466 | Evaluates the Tcl script and returns its result verbatim. If a Tcl script |
| 467 | error is generated, it will be transformed into a TH1 script error. A Tcl |
| 468 | interpreter will be created automatically if it has not been already. |
| 469 | |
| -------------------- | |
| 470 | <a name="tclExpr"></a>TH1 tclExpr Command |
| 471 | ----------------------------------------- |
| 472 | |
| 473 | **This command requires the Tcl integration feature.** |
| 474 | |
| 475 | * tclExpr arg ?arg ...? |
| 476 | |
| 477 | Evaluates the Tcl expression and returns its result verbatim. If a Tcl |
| 478 | script error is generated, it will be transformed into a TH1 script error. |
| 479 | A Tcl interpreter will be created automatically if it has not been already. |
| 480 | |
| ---------------------- | |
| 481 | <a name="tclInvoke"></a>TH1 tclInvoke Command |
| 482 | --------------------------------------------- |
| 483 | |
| 484 | **This command requires the Tcl integration feature.** |
| 485 | |
| 486 | * tclInvoke command ?arg ...? |
| 487 | |
| 488 | Invokes the Tcl command using the supplied arguments. No additional |
| 489 | substitutions are performed on the arguments. A Tcl interpreter will |
| 490 | be created automatically if it has not been already. |
| 491 | |
| --------------------- | |
| 492 | <a name="tclReady"></a>TH1 tclReady Command |
| 493 | ------------------------------------------- |
| 494 | |
| 495 | * tclReady |
| 496 | |
| 497 | Returns true if the binary has the Tcl integration feature enabled and it |
| 498 | is currently available for use by TH1 scripts. |
| 499 | |
| ------------------ | |
| 500 | <a name="trace"></a>TH1 trace Command |
| 501 | ------------------------------------- |
| 502 | |
| 503 | * trace STRING |
| 504 | |
| 505 | Generates a TH1 trace message if TH1 tracing is enabled. |
| 506 | |
| ------------------ | |
| 507 | <a name="stime"></a>TH1 stime Command |
| 508 | ------------------------------------- |
| 509 | |
| 510 | * stime |
| 511 | |
| 512 | Returns the number of microseconds of CPU time consumed by the current |
| 513 | process in system space. |
| 514 | |
| ------------------ | |
| 515 | <a name="utime"></a>TH1 utime Command |
| 516 | ------------------------------------- |
| 517 | |
| 518 | * utime |
| 519 | |
| 520 | Returns the number of microseconds of CPU time consumed by the current |
| 521 | process in user space. |
| 522 | |
| ----------------- | |
| 523 | <a name="wiki"></a>TH1 wiki Command |
| 524 | ----------------------------------- |
| 525 | |
| 526 | * wiki STRING |
| 527 | |
| 528 | Renders STRING as wiki content. |
| 529 | |
| @@ -536,22 +536,22 @@ | |
| 536 | Tcl commands: |
| 537 | |
| 538 | * th1Eval |
| 539 | * th1Expr |
| 540 | |
| -------------------- | |
| 541 | <a name="th1Eval"></a>Tcl th1Eval Command |
| 542 | ----------------------------------------- |
| 543 | |
| 544 | **This command requires the Tcl integration feature.** |
| 545 | |
| 546 | * th1Eval arg |
| 547 | |
| 548 | Evaluates the TH1 script and returns its result verbatim. If a TH1 script |
| 549 | error is generated, it will be transformed into a Tcl script error. |
| 550 | |
| -------------------- | |
| 551 | <a name="th1Expr"></a>Tcl th1Expr Command |
| 552 | ----------------------------------------- |
| 553 | |
| 554 | **This command requires the Tcl integration feature.** |
| 555 | |
| 556 | * th1Expr arg |
| 557 | |
| 558 |