Fossil SCM
Merge trunk
Commit
a47d79e910a9c88ba76b31b121bbc38fb8b54743
Parent
b18735fc4aca792…
139 files changed
+1
-1
+1
+1
-1
+1
+2
-2
+2
-2
+2
-2
+2
-2
+4
-2
+4
-2
+4
-2
+4
-2
+4
-2
+2
-2
+2
-2
+1
-1
+8
-9
+4
-4
+28
-13
+15
-25
+2
-2
+4
-1
+1
-1
+1
-1
+166
-15
+1
-2
+8
-8
+3
-3
+48
-31
+4
-1
+13
-8
+10
-10
+8
-9
+91
-48
+3
-3
+2
-2
+6
-2
+4
-7
+19
-4
+3
-4
+9
-8
+45
-61
+1
-1
+19
-1
+34
+80
-5
+7
-6
+93
-85
+26
-24
+1
-1
+5
-5
+2
-2
+4
+1
-1
+5
-5
+15
-6
+1
-1
+11
-14
+1
-1
+10
-10
+8
-12
+24
-16
+5
-8
+14
-14
+206
-100
+24
-3
+42
-31
+14
-14
+4
-4
+93
-82
+2
-2
+85
-2
+2
-2
+29
-36
+36
-44
+13
-2
+3
-3
+5
-1
+53
-23
+1
+57
+3
-3
+18
-24
+5
-5
+17
-2
+1
-1
+31
+3
+2
-6
+29
-11
+37
-1
+4
-4
+10
-10
+5
-5
+11
-11
+4
-4
+1
-1
+29
-3
+9
-9
+3
-3
+8
-8
+7
-7
+2
-2
+4
+1
-1
+9
-9
+9
-9
+1
-1
+5
-1
+3
-3
+5
-5
+26
-26
+19
-19
+2
-2
+11
-11
+2
-2
+54
-15
+13
-13
+48
-60
+9
-5
+1
-1
+68
-76
+5
-5
+3
-3
+10
-10
+26
-26
+13
-13
+12
-12
+3
-3
+6
-6
+20
-20
+3
-3
+10
-10
+3
-3
+6
-6
+19
+5
-5
+1
-2
+4
-4
~
Dockerfile
~
Makefile.in
~
VERSION
~
auto.def
~
skins/black_and_white/css.txt
~
skins/blitz/css.txt
~
skins/blitz_no_logo/css.txt
~
skins/default/css.txt
~
skins/eagle/css.txt
~
skins/enhanced1/css.txt
~
skins/khaki/css.txt
~
skins/original/css.txt
~
skins/plain_gray/css.txt
~
skins/rounded1/css.txt
~
skins/xekri/css.txt
~
src/allrepo.c
~
src/attach.c
~
src/bisect.c
~
src/branch.c
~
src/browse.c
~
src/builtin.c
~
src/cgi.c
~
src/checkin.c
~
src/checkin.c
~
src/db.c
~
src/delta.c
~
src/deltacmd.c
~
src/descendants.c
~
src/diff.c
~
src/diffcmd.c
~
src/dispatch.c
~
src/doc.c
~
src/event.c
~
src/export.c
~
src/file.c
~
src/finfo.c
~
src/fshell.c
~
src/fusefs.c
~
src/graph.c
~
src/http_socket.c
~
src/import.c
~
src/info.c
~
src/json_branch.c
~
src/json_wiki.c
~
src/linenoise.c
~
src/main.c
~
src/main.mk
~
src/makeheaders.html
~
src/makemake.tcl
~
src/markdown.c
~
src/merge3.c
~
src/mkindex.c
~
src/mkversion.c
~
src/moderate.c
~
src/name.c
~
src/printf.c
~
src/regexp.c
~
src/report.c
~
src/rss.c
~
src/search.c
~
src/setup.c
~
src/shell.c
~
src/shun.c
~
src/skins.c
~
src/sqlite3.c
~
src/sqlite3.h
~
src/stash.c
~
src/stat.c
~
src/statrep.c
~
src/style.c
~
src/tag.c
~
src/th_main.c
~
src/th_tcl.c
~
src/timeline.c
~
src/tkt.c
~
src/translate.c
~
src/unicode.c
~
src/unversioned.c
~
src/user.c
~
src/utf8.c
~
src/util.c
~
src/vfile.c
~
src/wiki.c
~
src/wikiformat.c
~
src/winhttp.c
~
src/xfer.c
~
test/diff.test
~
test/graph-test-1.wiki
~
test/stash.test
~
test/tester.tcl
~
test/th1.test
~
test/unversioned.test
~
www/aboutcgi.wiki
~
www/adding_code.wiki
~
www/antibot.wiki
~
www/blame.wiki
~
www/bugtheory.wiki
~
www/changes.wiki
~
www/checkin_names.wiki
~
www/childprojects.wiki
~
www/concepts.wiki
~
www/contribute.wiki
~
www/custom_ticket.wiki
~
www/customskin.md
~
www/delta_encoder_algorithm.wiki
~
www/delta_format.wiki
~
www/embeddeddoc.wiki
~
www/encryptedrepos.wiki
~
www/env-opts.md
~
www/event.wiki
~
www/faq.wiki
~
www/fileformat.wiki
~
www/fiveminutes.wiki
~
www/foss-cklist.wiki
~
www/fossil-from-msvc.wiki
~
www/index.wiki
~
www/inout.wiki
~
www/makefile.wiki
~
www/mkdownload.tcl
~
www/mkindex.tcl
~
www/newrepo.wiki
~
www/permutedindex.html
~
www/pop.wiki
~
www/private.wiki
~
www/qandc.wiki
~
www/quickstart.wiki
~
www/quotes.wiki
~
www/reviews.wiki
~
www/selfcheck.wiki
~
www/selfhost.wiki
~
www/server.wiki
~
www/settings.wiki
~
www/shunning.wiki
~
www/stats.wiki
~
www/sync.wiki
~
www/th1.md
~
www/theory1.wiki
~
www/webui.wiki
~
www/wikitheory.wiki
+1
-1
| --- Dockerfile | ||
| +++ Dockerfile | ||
| @@ -1,9 +1,9 @@ | ||
| 1 | 1 | ### |
| 2 | 2 | # Dockerfile for Fossil |
| 3 | 3 | ### |
| 4 | -FROM fedora:23 | |
| 4 | +FROM fedora:24 | |
| 5 | 5 | |
| 6 | 6 | ### Now install some additional parts we will need for the build |
| 7 | 7 | RUN dnf update -y && dnf install -y gcc make zlib-devel openssl-devel tar && dnf clean all && groupadd -r fossil -g 433 && useradd -u 431 -r -g fossil -d /opt/fossil -s /sbin/nologin -c "Fossil user" fossil |
| 8 | 8 | |
| 9 | 9 | ### If you want to build "trunk", change the next line accordingly. |
| 10 | 10 |
| --- Dockerfile | |
| +++ Dockerfile | |
| @@ -1,9 +1,9 @@ | |
| 1 | ### |
| 2 | # Dockerfile for Fossil |
| 3 | ### |
| 4 | FROM fedora:23 |
| 5 | |
| 6 | ### Now install some additional parts we will need for the build |
| 7 | RUN dnf update -y && dnf install -y gcc make zlib-devel openssl-devel tar && dnf clean all && groupadd -r fossil -g 433 && useradd -u 431 -r -g fossil -d /opt/fossil -s /sbin/nologin -c "Fossil user" fossil |
| 8 | |
| 9 | ### If you want to build "trunk", change the next line accordingly. |
| 10 |
| --- Dockerfile | |
| +++ Dockerfile | |
| @@ -1,9 +1,9 @@ | |
| 1 | ### |
| 2 | # Dockerfile for Fossil |
| 3 | ### |
| 4 | FROM fedora:24 |
| 5 | |
| 6 | ### Now install some additional parts we will need for the build |
| 7 | RUN dnf update -y && dnf install -y gcc make zlib-devel openssl-devel tar && dnf clean all && groupadd -r fossil -g 433 && useradd -u 431 -r -g fossil -d /opt/fossil -s /sbin/nologin -c "Fossil user" fossil |
| 8 | |
| 9 | ### If you want to build "trunk", change the next line accordingly. |
| 10 |
+1
| --- Makefile.in | ||
| +++ Makefile.in | ||
| @@ -37,10 +37,11 @@ | ||
| 37 | 37 | # care about testing the end result, this can be blank. |
| 38 | 38 | # |
| 39 | 39 | TCLSH = tclsh |
| 40 | 40 | |
| 41 | 41 | LIB = @LDFLAGS@ @EXTRA_LDFLAGS@ @LIBS@ |
| 42 | +BCCFLAGS = @CPPFLAGS@ @CFLAGS@ | |
| 42 | 43 | TCCFLAGS = @EXTRA_CFLAGS@ @CPPFLAGS@ @CFLAGS@ -DHAVE_AUTOCONFIG_H -D_HAVE_SQLITE_CONFIG_H |
| 43 | 44 | INSTALLDIR = $(DESTDIR)@prefix@/bin |
| 44 | 45 | USE_SYSTEM_SQLITE = @USE_SYSTEM_SQLITE@ |
| 45 | 46 | USE_LINENOISE = @USE_LINENOISE@ |
| 46 | 47 | USE_SEE = @USE_SEE@ |
| 47 | 48 |
| --- Makefile.in | |
| +++ Makefile.in | |
| @@ -37,10 +37,11 @@ | |
| 37 | # care about testing the end result, this can be blank. |
| 38 | # |
| 39 | TCLSH = tclsh |
| 40 | |
| 41 | LIB = @LDFLAGS@ @EXTRA_LDFLAGS@ @LIBS@ |
| 42 | TCCFLAGS = @EXTRA_CFLAGS@ @CPPFLAGS@ @CFLAGS@ -DHAVE_AUTOCONFIG_H -D_HAVE_SQLITE_CONFIG_H |
| 43 | INSTALLDIR = $(DESTDIR)@prefix@/bin |
| 44 | USE_SYSTEM_SQLITE = @USE_SYSTEM_SQLITE@ |
| 45 | USE_LINENOISE = @USE_LINENOISE@ |
| 46 | USE_SEE = @USE_SEE@ |
| 47 |
| --- Makefile.in | |
| +++ Makefile.in | |
| @@ -37,10 +37,11 @@ | |
| 37 | # care about testing the end result, this can be blank. |
| 38 | # |
| 39 | TCLSH = tclsh |
| 40 | |
| 41 | LIB = @LDFLAGS@ @EXTRA_LDFLAGS@ @LIBS@ |
| 42 | BCCFLAGS = @CPPFLAGS@ @CFLAGS@ |
| 43 | TCCFLAGS = @EXTRA_CFLAGS@ @CPPFLAGS@ @CFLAGS@ -DHAVE_AUTOCONFIG_H -D_HAVE_SQLITE_CONFIG_H |
| 44 | INSTALLDIR = $(DESTDIR)@prefix@/bin |
| 45 | USE_SYSTEM_SQLITE = @USE_SYSTEM_SQLITE@ |
| 46 | USE_LINENOISE = @USE_LINENOISE@ |
| 47 | USE_SEE = @USE_SEE@ |
| 48 |
M
VERSION
+1
-1
| --- VERSION | ||
| +++ VERSION | ||
| @@ -1,1 +1,1 @@ | ||
| 1 | -1.36 | |
| 1 | +1.37 | |
| 2 | 2 |
| --- VERSION | |
| +++ VERSION | |
| @@ -1,1 +1,1 @@ | |
| 1 | 1.36 |
| 2 |
| --- VERSION | |
| +++ VERSION | |
| @@ -1,1 +1,1 @@ | |
| 1 | 1.37 |
| 2 |
M
auto.def
+1
| --- auto.def | ||
| +++ auto.def | ||
| @@ -479,10 +479,11 @@ | ||
| 479 | 479 | cc-check-function-in-lib sin m |
| 480 | 480 | |
| 481 | 481 | # Check for the FuseFS library |
| 482 | 482 | if {[opt-bool fusefs]} { |
| 483 | 483 | if {[cc-check-function-in-lib fuse_mount fuse]} { |
| 484 | + define-append EXTRA_CFLAGS -DFOSSIL_HAVE_FUSEFS | |
| 484 | 485 | define FOSSIL_HAVE_FUSEFS 1 |
| 485 | 486 | define-append LIBS -lfuse |
| 486 | 487 | msg-result "FuseFS support enabled" |
| 487 | 488 | } |
| 488 | 489 | } |
| 489 | 490 |
| --- auto.def | |
| +++ auto.def | |
| @@ -479,10 +479,11 @@ | |
| 479 | cc-check-function-in-lib sin m |
| 480 | |
| 481 | # Check for the FuseFS library |
| 482 | if {[opt-bool fusefs]} { |
| 483 | if {[cc-check-function-in-lib fuse_mount fuse]} { |
| 484 | define FOSSIL_HAVE_FUSEFS 1 |
| 485 | define-append LIBS -lfuse |
| 486 | msg-result "FuseFS support enabled" |
| 487 | } |
| 488 | } |
| 489 |
| --- auto.def | |
| +++ auto.def | |
| @@ -479,10 +479,11 @@ | |
| 479 | cc-check-function-in-lib sin m |
| 480 | |
| 481 | # Check for the FuseFS library |
| 482 | if {[opt-bool fusefs]} { |
| 483 | if {[cc-check-function-in-lib fuse_mount fuse]} { |
| 484 | define-append EXTRA_CFLAGS -DFOSSIL_HAVE_FUSEFS |
| 485 | define FOSSIL_HAVE_FUSEFS 1 |
| 486 | define-append LIBS -lfuse |
| 487 | msg-result "FuseFS support enabled" |
| 488 | } |
| 489 | } |
| 490 |
+2
-2
| --- skins/black_and_white/css.txt | ||
| +++ skins/black_and_white/css.txt | ||
| @@ -106,16 +106,16 @@ | ||
| 106 | 106 | border-width:1px 0px; |
| 107 | 107 | background-color: #eee; |
| 108 | 108 | color: #333; |
| 109 | 109 | } |
| 110 | 110 | div.submenu a, div.submenu a:visited, div.sectionmenu>a.button:link, |
| 111 | -div.sectionmenu>a.button:visited { | |
| 111 | +div.sectionmenu>a.button:visited, div.submenu label { | |
| 112 | 112 | padding: 3px 10px 3px 10px; |
| 113 | 113 | color: #333; |
| 114 | 114 | text-decoration: none; |
| 115 | 115 | } |
| 116 | -div.submenu a:hover, div.sectionmenu>a.button:hover { | |
| 116 | +div.submenu a:hover, div.sectionmenu>a.button:hover, div.submenu label:hover { | |
| 117 | 117 | color: #eee; |
| 118 | 118 | background-color: #333; |
| 119 | 119 | } |
| 120 | 120 | |
| 121 | 121 | /* All page content from the bottom of the menu or submenu down to |
| 122 | 122 |
| --- skins/black_and_white/css.txt | |
| +++ skins/black_and_white/css.txt | |
| @@ -106,16 +106,16 @@ | |
| 106 | border-width:1px 0px; |
| 107 | background-color: #eee; |
| 108 | color: #333; |
| 109 | } |
| 110 | div.submenu a, div.submenu a:visited, div.sectionmenu>a.button:link, |
| 111 | div.sectionmenu>a.button:visited { |
| 112 | padding: 3px 10px 3px 10px; |
| 113 | color: #333; |
| 114 | text-decoration: none; |
| 115 | } |
| 116 | div.submenu a:hover, div.sectionmenu>a.button:hover { |
| 117 | color: #eee; |
| 118 | background-color: #333; |
| 119 | } |
| 120 | |
| 121 | /* All page content from the bottom of the menu or submenu down to |
| 122 |
| --- skins/black_and_white/css.txt | |
| +++ skins/black_and_white/css.txt | |
| @@ -106,16 +106,16 @@ | |
| 106 | border-width:1px 0px; |
| 107 | background-color: #eee; |
| 108 | color: #333; |
| 109 | } |
| 110 | div.submenu a, div.submenu a:visited, div.sectionmenu>a.button:link, |
| 111 | div.sectionmenu>a.button:visited, div.submenu label { |
| 112 | padding: 3px 10px 3px 10px; |
| 113 | color: #333; |
| 114 | text-decoration: none; |
| 115 | } |
| 116 | div.submenu a:hover, div.sectionmenu>a.button:hover, div.submenu label:hover { |
| 117 | color: #eee; |
| 118 | background-color: #333; |
| 119 | } |
| 120 | |
| 121 | /* All page content from the bottom of the menu or submenu down to |
| 122 |
+2
-2
| --- skins/blitz/css.txt | ||
| +++ skins/blitz/css.txt | ||
| @@ -894,19 +894,19 @@ | ||
| 894 | 894 | |
| 895 | 895 | .submenu input, .submenu select { |
| 896 | 896 | margin: 0 0 0 5px; |
| 897 | 897 | } |
| 898 | 898 | |
| 899 | -.submenu a { | |
| 899 | +.submenu a, .submenu label { | |
| 900 | 900 | color: #3b5c6b; |
| 901 | 901 | padding: 5px 15px; |
| 902 | 902 | text-decoration: none; |
| 903 | 903 | border: 1px solid transparent; |
| 904 | 904 | border-radius: 5px; |
| 905 | 905 | } |
| 906 | 906 | |
| 907 | -.submenu a:hover { | |
| 907 | +.submenu a:hover, .submenu label:hover { | |
| 908 | 908 | border: 1px solid #ccc; |
| 909 | 909 | } |
| 910 | 910 | |
| 911 | 911 | |
| 912 | 912 | /* Section |
| 913 | 913 |
| --- skins/blitz/css.txt | |
| +++ skins/blitz/css.txt | |
| @@ -894,19 +894,19 @@ | |
| 894 | |
| 895 | .submenu input, .submenu select { |
| 896 | margin: 0 0 0 5px; |
| 897 | } |
| 898 | |
| 899 | .submenu a { |
| 900 | color: #3b5c6b; |
| 901 | padding: 5px 15px; |
| 902 | text-decoration: none; |
| 903 | border: 1px solid transparent; |
| 904 | border-radius: 5px; |
| 905 | } |
| 906 | |
| 907 | .submenu a:hover { |
| 908 | border: 1px solid #ccc; |
| 909 | } |
| 910 | |
| 911 | |
| 912 | /* Section |
| 913 |
| --- skins/blitz/css.txt | |
| +++ skins/blitz/css.txt | |
| @@ -894,19 +894,19 @@ | |
| 894 | |
| 895 | .submenu input, .submenu select { |
| 896 | margin: 0 0 0 5px; |
| 897 | } |
| 898 | |
| 899 | .submenu a, .submenu label { |
| 900 | color: #3b5c6b; |
| 901 | padding: 5px 15px; |
| 902 | text-decoration: none; |
| 903 | border: 1px solid transparent; |
| 904 | border-radius: 5px; |
| 905 | } |
| 906 | |
| 907 | .submenu a:hover, .submenu label:hover { |
| 908 | border: 1px solid #ccc; |
| 909 | } |
| 910 | |
| 911 | |
| 912 | /* Section |
| 913 |
+2
-2
| --- skins/blitz_no_logo/css.txt | ||
| +++ skins/blitz_no_logo/css.txt | ||
| @@ -894,19 +894,19 @@ | ||
| 894 | 894 | |
| 895 | 895 | .submenu input, .submenu select { |
| 896 | 896 | margin: 0 0 0 5px; |
| 897 | 897 | } |
| 898 | 898 | |
| 899 | -.submenu a { | |
| 899 | +.submenu a, .submenu label { | |
| 900 | 900 | color: #3b5c6b; |
| 901 | 901 | padding: 5px 15px; |
| 902 | 902 | text-decoration: none; |
| 903 | 903 | border: 1px solid transparent; |
| 904 | 904 | border-radius: 5px; |
| 905 | 905 | } |
| 906 | 906 | |
| 907 | -.submenu a:hover { | |
| 907 | +.submenu a:hover, .submenu label:hover { | |
| 908 | 908 | border: 1px solid #ccc; |
| 909 | 909 | } |
| 910 | 910 | |
| 911 | 911 | |
| 912 | 912 | /* Section |
| 913 | 913 |
| --- skins/blitz_no_logo/css.txt | |
| +++ skins/blitz_no_logo/css.txt | |
| @@ -894,19 +894,19 @@ | |
| 894 | |
| 895 | .submenu input, .submenu select { |
| 896 | margin: 0 0 0 5px; |
| 897 | } |
| 898 | |
| 899 | .submenu a { |
| 900 | color: #3b5c6b; |
| 901 | padding: 5px 15px; |
| 902 | text-decoration: none; |
| 903 | border: 1px solid transparent; |
| 904 | border-radius: 5px; |
| 905 | } |
| 906 | |
| 907 | .submenu a:hover { |
| 908 | border: 1px solid #ccc; |
| 909 | } |
| 910 | |
| 911 | |
| 912 | /* Section |
| 913 |
| --- skins/blitz_no_logo/css.txt | |
| +++ skins/blitz_no_logo/css.txt | |
| @@ -894,19 +894,19 @@ | |
| 894 | |
| 895 | .submenu input, .submenu select { |
| 896 | margin: 0 0 0 5px; |
| 897 | } |
| 898 | |
| 899 | .submenu a, .submenu label { |
| 900 | color: #3b5c6b; |
| 901 | padding: 5px 15px; |
| 902 | text-decoration: none; |
| 903 | border: 1px solid transparent; |
| 904 | border-radius: 5px; |
| 905 | } |
| 906 | |
| 907 | .submenu a:hover, .submenu label:hover { |
| 908 | border: 1px solid #ccc; |
| 909 | } |
| 910 | |
| 911 | |
| 912 | /* Section |
| 913 |
+2
-2
| --- skins/default/css.txt | ||
| +++ skins/default/css.txt | ||
| @@ -104,17 +104,17 @@ | ||
| 104 | 104 | margin-top: 10px; |
| 105 | 105 | padding: 10px; |
| 106 | 106 | border-bottom: 1px solid #ccc; |
| 107 | 107 | } |
| 108 | 108 | |
| 109 | -.submenu a { | |
| 109 | +.submenu a, .submenu label { | |
| 110 | 110 | padding: 10px 11px; |
| 111 | 111 | text-decoration:none; |
| 112 | 112 | color: #777; |
| 113 | 113 | } |
| 114 | 114 | |
| 115 | -.submenu a:hover { | |
| 115 | +.submenu a:hover, .submenu label:hover { | |
| 116 | 116 | padding: 6px 10px; |
| 117 | 117 | border: 1px solid #ccc; |
| 118 | 118 | border-radius: 5px; |
| 119 | 119 | color: #000; |
| 120 | 120 | } |
| 121 | 121 |
| --- skins/default/css.txt | |
| +++ skins/default/css.txt | |
| @@ -104,17 +104,17 @@ | |
| 104 | margin-top: 10px; |
| 105 | padding: 10px; |
| 106 | border-bottom: 1px solid #ccc; |
| 107 | } |
| 108 | |
| 109 | .submenu a { |
| 110 | padding: 10px 11px; |
| 111 | text-decoration:none; |
| 112 | color: #777; |
| 113 | } |
| 114 | |
| 115 | .submenu a:hover { |
| 116 | padding: 6px 10px; |
| 117 | border: 1px solid #ccc; |
| 118 | border-radius: 5px; |
| 119 | color: #000; |
| 120 | } |
| 121 |
| --- skins/default/css.txt | |
| +++ skins/default/css.txt | |
| @@ -104,17 +104,17 @@ | |
| 104 | margin-top: 10px; |
| 105 | padding: 10px; |
| 106 | border-bottom: 1px solid #ccc; |
| 107 | } |
| 108 | |
| 109 | .submenu a, .submenu label { |
| 110 | padding: 10px 11px; |
| 111 | text-decoration:none; |
| 112 | color: #777; |
| 113 | } |
| 114 | |
| 115 | .submenu a:hover, .submenu label:hover { |
| 116 | padding: 6px 10px; |
| 117 | border: 1px solid #ccc; |
| 118 | border-radius: 5px; |
| 119 | color: #000; |
| 120 | } |
| 121 |
+4
-2
| --- skins/eagle/css.txt | ||
| +++ skins/eagle/css.txt | ||
| @@ -73,16 +73,18 @@ | ||
| 73 | 73 | text-align: center; |
| 74 | 74 | background-color: #485D7B; |
| 75 | 75 | color: white; |
| 76 | 76 | } |
| 77 | 77 | div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited, |
| 78 | -div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { | |
| 78 | +div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited, | |
| 79 | +div.submenu label { | |
| 79 | 80 | padding: 3px 10px 3px 10px; |
| 80 | 81 | color: white; |
| 81 | 82 | text-decoration: none; |
| 82 | 83 | } |
| 83 | -div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover { | |
| 84 | +div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover, | |
| 85 | +div.submenu label:hover { | |
| 84 | 86 | text-decoration: underline; |
| 85 | 87 | } |
| 86 | 88 | |
| 87 | 89 | /* All page content from the bottom of the menu or submenu down to |
| 88 | 90 | ** the footer */ |
| 89 | 91 |
| --- skins/eagle/css.txt | |
| +++ skins/eagle/css.txt | |
| @@ -73,16 +73,18 @@ | |
| 73 | text-align: center; |
| 74 | background-color: #485D7B; |
| 75 | color: white; |
| 76 | } |
| 77 | div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited, |
| 78 | div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { |
| 79 | padding: 3px 10px 3px 10px; |
| 80 | color: white; |
| 81 | text-decoration: none; |
| 82 | } |
| 83 | div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover { |
| 84 | text-decoration: underline; |
| 85 | } |
| 86 | |
| 87 | /* All page content from the bottom of the menu or submenu down to |
| 88 | ** the footer */ |
| 89 |
| --- skins/eagle/css.txt | |
| +++ skins/eagle/css.txt | |
| @@ -73,16 +73,18 @@ | |
| 73 | text-align: center; |
| 74 | background-color: #485D7B; |
| 75 | color: white; |
| 76 | } |
| 77 | div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited, |
| 78 | div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited, |
| 79 | div.submenu label { |
| 80 | padding: 3px 10px 3px 10px; |
| 81 | color: white; |
| 82 | text-decoration: none; |
| 83 | } |
| 84 | div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover, |
| 85 | div.submenu label:hover { |
| 86 | text-decoration: underline; |
| 87 | } |
| 88 | |
| 89 | /* All page content from the bottom of the menu or submenu down to |
| 90 | ** the footer */ |
| 91 |
+4
-2
| --- skins/enhanced1/css.txt | ||
| +++ skins/enhanced1/css.txt | ||
| @@ -71,16 +71,18 @@ | ||
| 71 | 71 | text-align: center; |
| 72 | 72 | background-color: #456878; |
| 73 | 73 | color: white; |
| 74 | 74 | } |
| 75 | 75 | div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited, |
| 76 | -div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { | |
| 76 | +div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited, | |
| 77 | +div.submenu label { | |
| 77 | 78 | padding: 3px 10px 3px 10px; |
| 78 | 79 | color: white; |
| 79 | 80 | text-decoration: none; |
| 80 | 81 | } |
| 81 | -div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover { | |
| 82 | +div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover, | |
| 83 | +div.submenu label:hover { | |
| 82 | 84 | color: #558195; |
| 83 | 85 | background-color: white; |
| 84 | 86 | } |
| 85 | 87 | |
| 86 | 88 | /* All page content from the bottom of the menu or submenu down to |
| 87 | 89 |
| --- skins/enhanced1/css.txt | |
| +++ skins/enhanced1/css.txt | |
| @@ -71,16 +71,18 @@ | |
| 71 | text-align: center; |
| 72 | background-color: #456878; |
| 73 | color: white; |
| 74 | } |
| 75 | div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited, |
| 76 | div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { |
| 77 | padding: 3px 10px 3px 10px; |
| 78 | color: white; |
| 79 | text-decoration: none; |
| 80 | } |
| 81 | div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover { |
| 82 | color: #558195; |
| 83 | background-color: white; |
| 84 | } |
| 85 | |
| 86 | /* All page content from the bottom of the menu or submenu down to |
| 87 |
| --- skins/enhanced1/css.txt | |
| +++ skins/enhanced1/css.txt | |
| @@ -71,16 +71,18 @@ | |
| 71 | text-align: center; |
| 72 | background-color: #456878; |
| 73 | color: white; |
| 74 | } |
| 75 | div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited, |
| 76 | div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited, |
| 77 | div.submenu label { |
| 78 | padding: 3px 10px 3px 10px; |
| 79 | color: white; |
| 80 | text-decoration: none; |
| 81 | } |
| 82 | div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover, |
| 83 | div.submenu label:hover { |
| 84 | color: #558195; |
| 85 | background-color: white; |
| 86 | } |
| 87 | |
| 88 | /* All page content from the bottom of the menu or submenu down to |
| 89 |
+4
-2
| --- skins/khaki/css.txt | ||
| +++ skins/khaki/css.txt | ||
| @@ -69,16 +69,18 @@ | ||
| 69 | 69 | text-align: center; |
| 70 | 70 | background-color: #c0af58; |
| 71 | 71 | color: white; |
| 72 | 72 | } |
| 73 | 73 | div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited, |
| 74 | -div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { | |
| 74 | +div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited, | |
| 75 | +div.submenu label { | |
| 75 | 76 | padding: 3px 10px 3px 10px; |
| 76 | 77 | color: white; |
| 77 | 78 | text-decoration: none; |
| 78 | 79 | } |
| 79 | -div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover { | |
| 80 | +div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover | |
| 81 | +div.submenu label:hover { | |
| 80 | 82 | color: #a09048; |
| 81 | 83 | background-color: white; |
| 82 | 84 | } |
| 83 | 85 | |
| 84 | 86 | /* All page content from the bottom of the menu or submenu down to |
| 85 | 87 |
| --- skins/khaki/css.txt | |
| +++ skins/khaki/css.txt | |
| @@ -69,16 +69,18 @@ | |
| 69 | text-align: center; |
| 70 | background-color: #c0af58; |
| 71 | color: white; |
| 72 | } |
| 73 | div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited, |
| 74 | div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { |
| 75 | padding: 3px 10px 3px 10px; |
| 76 | color: white; |
| 77 | text-decoration: none; |
| 78 | } |
| 79 | div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover { |
| 80 | color: #a09048; |
| 81 | background-color: white; |
| 82 | } |
| 83 | |
| 84 | /* All page content from the bottom of the menu or submenu down to |
| 85 |
| --- skins/khaki/css.txt | |
| +++ skins/khaki/css.txt | |
| @@ -69,16 +69,18 @@ | |
| 69 | text-align: center; |
| 70 | background-color: #c0af58; |
| 71 | color: white; |
| 72 | } |
| 73 | div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited, |
| 74 | div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited, |
| 75 | div.submenu label { |
| 76 | padding: 3px 10px 3px 10px; |
| 77 | color: white; |
| 78 | text-decoration: none; |
| 79 | } |
| 80 | div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover |
| 81 | div.submenu label:hover { |
| 82 | color: #a09048; |
| 83 | background-color: white; |
| 84 | } |
| 85 | |
| 86 | /* All page content from the bottom of the menu or submenu down to |
| 87 |
+4
-2
| --- skins/original/css.txt | ||
| +++ skins/original/css.txt | ||
| @@ -71,16 +71,18 @@ | ||
| 71 | 71 | text-align: center; |
| 72 | 72 | background-color: #456878; |
| 73 | 73 | color: white; |
| 74 | 74 | } |
| 75 | 75 | div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited, |
| 76 | -div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { | |
| 76 | +div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited, | |
| 77 | +div.submenu label { | |
| 77 | 78 | padding: 3px 10px 3px 10px; |
| 78 | 79 | color: white; |
| 79 | 80 | text-decoration: none; |
| 80 | 81 | } |
| 81 | -div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover { | |
| 82 | +div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover, | |
| 83 | +div.submenu label:hover { | |
| 82 | 84 | color: #558195; |
| 83 | 85 | background-color: white; |
| 84 | 86 | } |
| 85 | 87 | |
| 86 | 88 | /* All page content from the bottom of the menu or submenu down to |
| 87 | 89 |
| --- skins/original/css.txt | |
| +++ skins/original/css.txt | |
| @@ -71,16 +71,18 @@ | |
| 71 | text-align: center; |
| 72 | background-color: #456878; |
| 73 | color: white; |
| 74 | } |
| 75 | div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited, |
| 76 | div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { |
| 77 | padding: 3px 10px 3px 10px; |
| 78 | color: white; |
| 79 | text-decoration: none; |
| 80 | } |
| 81 | div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover { |
| 82 | color: #558195; |
| 83 | background-color: white; |
| 84 | } |
| 85 | |
| 86 | /* All page content from the bottom of the menu or submenu down to |
| 87 |
| --- skins/original/css.txt | |
| +++ skins/original/css.txt | |
| @@ -71,16 +71,18 @@ | |
| 71 | text-align: center; |
| 72 | background-color: #456878; |
| 73 | color: white; |
| 74 | } |
| 75 | div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited, |
| 76 | div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited, |
| 77 | div.submenu label { |
| 78 | padding: 3px 10px 3px 10px; |
| 79 | color: white; |
| 80 | text-decoration: none; |
| 81 | } |
| 82 | div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover, |
| 83 | div.submenu label:hover { |
| 84 | color: #558195; |
| 85 | background-color: white; |
| 86 | } |
| 87 | |
| 88 | /* All page content from the bottom of the menu or submenu down to |
| 89 |
+4
-2
| --- skins/plain_gray/css.txt | ||
| +++ skins/plain_gray/css.txt | ||
| @@ -71,16 +71,18 @@ | ||
| 71 | 71 | text-align: center; |
| 72 | 72 | background-color: #606060; |
| 73 | 73 | color: white; |
| 74 | 74 | } |
| 75 | 75 | div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited, |
| 76 | -div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { | |
| 76 | +div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited, | |
| 77 | +div.submenu label { | |
| 77 | 78 | padding: 3px 10px 3px 10px; |
| 78 | 79 | color: white; |
| 79 | 80 | text-decoration: none; |
| 80 | 81 | } |
| 81 | -div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover { | |
| 82 | +div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover, | |
| 83 | +div.submenu label:hover { | |
| 82 | 84 | color: #404040; |
| 83 | 85 | background-color: white; |
| 84 | 86 | } |
| 85 | 87 | |
| 86 | 88 | /* All page content from the bottom of the menu or submenu down to |
| 87 | 89 |
| --- skins/plain_gray/css.txt | |
| +++ skins/plain_gray/css.txt | |
| @@ -71,16 +71,18 @@ | |
| 71 | text-align: center; |
| 72 | background-color: #606060; |
| 73 | color: white; |
| 74 | } |
| 75 | div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited, |
| 76 | div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { |
| 77 | padding: 3px 10px 3px 10px; |
| 78 | color: white; |
| 79 | text-decoration: none; |
| 80 | } |
| 81 | div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover { |
| 82 | color: #404040; |
| 83 | background-color: white; |
| 84 | } |
| 85 | |
| 86 | /* All page content from the bottom of the menu or submenu down to |
| 87 |
| --- skins/plain_gray/css.txt | |
| +++ skins/plain_gray/css.txt | |
| @@ -71,16 +71,18 @@ | |
| 71 | text-align: center; |
| 72 | background-color: #606060; |
| 73 | color: white; |
| 74 | } |
| 75 | div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited, |
| 76 | div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited, |
| 77 | div.submenu label { |
| 78 | padding: 3px 10px 3px 10px; |
| 79 | color: white; |
| 80 | text-decoration: none; |
| 81 | } |
| 82 | div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover, |
| 83 | div.submenu label:hover { |
| 84 | color: #404040; |
| 85 | background-color: white; |
| 86 | } |
| 87 | |
| 88 | /* All page content from the bottom of the menu or submenu down to |
| 89 |
+2
-2
| --- skins/rounded1/css.txt | ||
| +++ skins/rounded1/css.txt | ||
| @@ -84,11 +84,11 @@ | ||
| 84 | 84 | div.mainmenu a, div.mainmenu a:visited { |
| 85 | 85 | padding: 3px 10px 3px 10px; |
| 86 | 86 | color: white; |
| 87 | 87 | text-decoration: none; |
| 88 | 88 | } |
| 89 | -div.submenu a, div.submenu a:visited, a.button, | |
| 89 | +div.submenu a, div.submenu a:visited, a.button, div.submenu label | |
| 90 | 90 | div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { |
| 91 | 91 | padding: 2px 8px; |
| 92 | 92 | color: #000; |
| 93 | 93 | font-family: Arial; |
| 94 | 94 | text-decoration: none; |
| @@ -102,11 +102,11 @@ | ||
| 102 | 102 | div.mainmenu a:hover { |
| 103 | 103 | color: #000; |
| 104 | 104 | background-color: white; |
| 105 | 105 | } |
| 106 | 106 | |
| 107 | -div.submenu a:hover, div.sectionmenu>a.button:hover { | |
| 107 | +div.submenu a:hover, div.sectionmenu>a.button:hover, div.submenu label:hover { | |
| 108 | 108 | background-color: #c0c0c0; |
| 109 | 109 | } |
| 110 | 110 | |
| 111 | 111 | /* All page content from the bottom of the menu or submenu down to |
| 112 | 112 | ** the footer */ |
| 113 | 113 |
| --- skins/rounded1/css.txt | |
| +++ skins/rounded1/css.txt | |
| @@ -84,11 +84,11 @@ | |
| 84 | div.mainmenu a, div.mainmenu a:visited { |
| 85 | padding: 3px 10px 3px 10px; |
| 86 | color: white; |
| 87 | text-decoration: none; |
| 88 | } |
| 89 | div.submenu a, div.submenu a:visited, a.button, |
| 90 | div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { |
| 91 | padding: 2px 8px; |
| 92 | color: #000; |
| 93 | font-family: Arial; |
| 94 | text-decoration: none; |
| @@ -102,11 +102,11 @@ | |
| 102 | div.mainmenu a:hover { |
| 103 | color: #000; |
| 104 | background-color: white; |
| 105 | } |
| 106 | |
| 107 | div.submenu a:hover, div.sectionmenu>a.button:hover { |
| 108 | background-color: #c0c0c0; |
| 109 | } |
| 110 | |
| 111 | /* All page content from the bottom of the menu or submenu down to |
| 112 | ** the footer */ |
| 113 |
| --- skins/rounded1/css.txt | |
| +++ skins/rounded1/css.txt | |
| @@ -84,11 +84,11 @@ | |
| 84 | div.mainmenu a, div.mainmenu a:visited { |
| 85 | padding: 3px 10px 3px 10px; |
| 86 | color: white; |
| 87 | text-decoration: none; |
| 88 | } |
| 89 | div.submenu a, div.submenu a:visited, a.button, div.submenu label |
| 90 | div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited { |
| 91 | padding: 2px 8px; |
| 92 | color: #000; |
| 93 | font-family: Arial; |
| 94 | text-decoration: none; |
| @@ -102,11 +102,11 @@ | |
| 102 | div.mainmenu a:hover { |
| 103 | color: #000; |
| 104 | background-color: white; |
| 105 | } |
| 106 | |
| 107 | div.submenu a:hover, div.sectionmenu>a.button:hover, div.submenu label:hover { |
| 108 | background-color: #c0c0c0; |
| 109 | } |
| 110 | |
| 111 | /* All page content from the bottom of the menu or submenu down to |
| 112 | ** the footer */ |
| 113 |
+2
-2
| --- skins/xekri/css.txt | ||
| +++ skins/xekri/css.txt | ||
| @@ -158,17 +158,17 @@ | ||
| 158 | 158 | border-top: 1px solid #0a0; |
| 159 | 159 | border-radius: 0; |
| 160 | 160 | display: block; |
| 161 | 161 | } |
| 162 | 162 | |
| 163 | -div.mainmenu a, div.submenu a { | |
| 163 | +div.mainmenu a, div.submenu a, div.submenu label { | |
| 164 | 164 | color: #000; |
| 165 | 165 | padding: 0 0.75rem; |
| 166 | 166 | text-decoration: none; |
| 167 | 167 | } |
| 168 | 168 | |
| 169 | -div.mainmenu a:hover, div.submenu a:hover { | |
| 169 | +div.mainmenu a:hover, div.submenu a:hover, div.submenu label:hover { | |
| 170 | 170 | color: #fff; |
| 171 | 171 | text-shadow: 0px 0px 6px #0f0; |
| 172 | 172 | } |
| 173 | 173 | |
| 174 | 174 | div.submenu * { |
| 175 | 175 |
| --- skins/xekri/css.txt | |
| +++ skins/xekri/css.txt | |
| @@ -158,17 +158,17 @@ | |
| 158 | border-top: 1px solid #0a0; |
| 159 | border-radius: 0; |
| 160 | display: block; |
| 161 | } |
| 162 | |
| 163 | div.mainmenu a, div.submenu a { |
| 164 | color: #000; |
| 165 | padding: 0 0.75rem; |
| 166 | text-decoration: none; |
| 167 | } |
| 168 | |
| 169 | div.mainmenu a:hover, div.submenu a:hover { |
| 170 | color: #fff; |
| 171 | text-shadow: 0px 0px 6px #0f0; |
| 172 | } |
| 173 | |
| 174 | div.submenu * { |
| 175 |
| --- skins/xekri/css.txt | |
| +++ skins/xekri/css.txt | |
| @@ -158,17 +158,17 @@ | |
| 158 | border-top: 1px solid #0a0; |
| 159 | border-radius: 0; |
| 160 | display: block; |
| 161 | } |
| 162 | |
| 163 | div.mainmenu a, div.submenu a, div.submenu label { |
| 164 | color: #000; |
| 165 | padding: 0 0.75rem; |
| 166 | text-decoration: none; |
| 167 | } |
| 168 | |
| 169 | div.mainmenu a:hover, div.submenu a:hover, div.submenu label:hover { |
| 170 | color: #fff; |
| 171 | text-shadow: 0px 0px 6px #0f0; |
| 172 | } |
| 173 | |
| 174 | div.submenu * { |
| 175 |
+1
-1
| --- src/allrepo.c | ||
| +++ src/allrepo.c | ||
| @@ -173,11 +173,10 @@ | ||
| 173 | 173 | int useCheckouts = 0; |
| 174 | 174 | int quiet = 0; |
| 175 | 175 | int dryRunFlag = 0; |
| 176 | 176 | int showFile = find_option("showfile",0,0)!=0; |
| 177 | 177 | int stopOnError = find_option("dontstop",0,0)==0; |
| 178 | - int rc; | |
| 179 | 178 | int nToDel = 0; |
| 180 | 179 | int showLabel = 0; |
| 181 | 180 | |
| 182 | 181 | dryRunFlag = find_option("dry-run","n",0)!=0; |
| 183 | 182 | if( !dryRunFlag ){ |
| @@ -378,10 +377,11 @@ | ||
| 378 | 377 | ); |
| 379 | 378 | } |
| 380 | 379 | db_multi_exec("CREATE TEMP TABLE toDel(x TEXT)"); |
| 381 | 380 | db_prepare(&q, "SELECT name, tag FROM repolist ORDER BY 1"); |
| 382 | 381 | while( db_step(&q)==SQLITE_ROW ){ |
| 382 | + int rc; | |
| 383 | 383 | const char *zFilename = db_column_text(&q, 0); |
| 384 | 384 | #if !USE_SEE |
| 385 | 385 | if( sqlite3_strglob("*.efossil", zFilename)==0 ) continue; |
| 386 | 386 | #endif |
| 387 | 387 | if( file_access(zFilename, F_OK) |
| 388 | 388 |
| --- src/allrepo.c | |
| +++ src/allrepo.c | |
| @@ -173,11 +173,10 @@ | |
| 173 | int useCheckouts = 0; |
| 174 | int quiet = 0; |
| 175 | int dryRunFlag = 0; |
| 176 | int showFile = find_option("showfile",0,0)!=0; |
| 177 | int stopOnError = find_option("dontstop",0,0)==0; |
| 178 | int rc; |
| 179 | int nToDel = 0; |
| 180 | int showLabel = 0; |
| 181 | |
| 182 | dryRunFlag = find_option("dry-run","n",0)!=0; |
| 183 | if( !dryRunFlag ){ |
| @@ -378,10 +377,11 @@ | |
| 378 | ); |
| 379 | } |
| 380 | db_multi_exec("CREATE TEMP TABLE toDel(x TEXT)"); |
| 381 | db_prepare(&q, "SELECT name, tag FROM repolist ORDER BY 1"); |
| 382 | while( db_step(&q)==SQLITE_ROW ){ |
| 383 | const char *zFilename = db_column_text(&q, 0); |
| 384 | #if !USE_SEE |
| 385 | if( sqlite3_strglob("*.efossil", zFilename)==0 ) continue; |
| 386 | #endif |
| 387 | if( file_access(zFilename, F_OK) |
| 388 |
| --- src/allrepo.c | |
| +++ src/allrepo.c | |
| @@ -173,11 +173,10 @@ | |
| 173 | int useCheckouts = 0; |
| 174 | int quiet = 0; |
| 175 | int dryRunFlag = 0; |
| 176 | int showFile = find_option("showfile",0,0)!=0; |
| 177 | int stopOnError = find_option("dontstop",0,0)==0; |
| 178 | int nToDel = 0; |
| 179 | int showLabel = 0; |
| 180 | |
| 181 | dryRunFlag = find_option("dry-run","n",0)!=0; |
| 182 | if( !dryRunFlag ){ |
| @@ -378,10 +377,11 @@ | |
| 377 | ); |
| 378 | } |
| 379 | db_multi_exec("CREATE TEMP TABLE toDel(x TEXT)"); |
| 380 | db_prepare(&q, "SELECT name, tag FROM repolist ORDER BY 1"); |
| 381 | while( db_step(&q)==SQLITE_ROW ){ |
| 382 | int rc; |
| 383 | const char *zFilename = db_column_text(&q, 0); |
| 384 | #if !USE_SEE |
| 385 | if( sqlite3_strglob("*.efossil", zFilename)==0 ) continue; |
| 386 | #endif |
| 387 | if( file_access(zFilename, F_OK) |
| 388 |
+8
-9
| --- src/attach.c | ||
| +++ src/attach.c | ||
| @@ -452,14 +452,14 @@ | ||
| 452 | 452 | #if 0 |
| 453 | 453 | /* Shunning here needs to get both the attachment control artifact and |
| 454 | 454 | ** the object that is attached. */ |
| 455 | 455 | if( g.perm.Admin ){ |
| 456 | 456 | if( db_exists("SELECT 1 FROM shun WHERE uuid='%q'", zUuid) ){ |
| 457 | - style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", | |
| 457 | + style_submenu_element("Unshun", "%s/shun?uuid=%s&sub=1", | |
| 458 | 458 | g.zTop, zUuid); |
| 459 | 459 | }else{ |
| 460 | - style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", | |
| 460 | + style_submenu_element("Shun", "%s/shun?shun=%s#addshun", | |
| 461 | 461 | g.zTop, zUuid); |
| 462 | 462 | } |
| 463 | 463 | } |
| 464 | 464 | #endif |
| 465 | 465 | pAttach = manifest_get(rid, CFTYPE_ATTACHMENT, 0); |
| @@ -475,23 +475,23 @@ | ||
| 475 | 475 | && db_exists("SELECT 1 FROM ticket WHERE tkt_uuid='%q'", zTarget) |
| 476 | 476 | ){ |
| 477 | 477 | zTktUuid = zTarget; |
| 478 | 478 | if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; } |
| 479 | 479 | if( g.perm.WrTkt ){ |
| 480 | - style_submenu_element("Delete","Delete","%R/ainfo/%s?del", zUuid); | |
| 480 | + style_submenu_element("Delete", "%R/ainfo/%s?del", zUuid); | |
| 481 | 481 | } |
| 482 | 482 | }else if( db_exists("SELECT 1 FROM tag WHERE tagname='wiki-%q'",zTarget) ){ |
| 483 | 483 | zWikiName = zTarget; |
| 484 | 484 | if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; } |
| 485 | 485 | if( g.perm.WrWiki ){ |
| 486 | - style_submenu_element("Delete","Delete","%R/ainfo/%s?del", zUuid); | |
| 486 | + style_submenu_element("Delete", "%R/ainfo/%s?del", zUuid); | |
| 487 | 487 | } |
| 488 | 488 | }else if( db_exists("SELECT 1 FROM tag WHERE tagname='event-%q'",zTarget) ){ |
| 489 | 489 | zTNUuid = zTarget; |
| 490 | 490 | if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; } |
| 491 | 491 | if( g.perm.Write && g.perm.WrWiki ){ |
| 492 | - style_submenu_element("Delete","Delete","%R/ainfo/%s?del", zUuid); | |
| 492 | + style_submenu_element("Delete", "%R/ainfo/%s?del", zUuid); | |
| 493 | 493 | } |
| 494 | 494 | } |
| 495 | 495 | zDate = db_text(0, "SELECT datetime(%.12f)", pAttach->rDate); |
| 496 | 496 | |
| 497 | 497 | if( P("confirm") |
| @@ -551,14 +551,13 @@ | ||
| 551 | 551 | if( strcmp(zModAction,"approve")==0 ){ |
| 552 | 552 | moderation_approve(rid); |
| 553 | 553 | } |
| 554 | 554 | } |
| 555 | 555 | style_header("Attachment Details"); |
| 556 | - style_submenu_element("Raw", "Raw", "%R/artifact/%s", zUuid); | |
| 556 | + style_submenu_element("Raw", "%R/artifact/%s", zUuid); | |
| 557 | 557 | if(fShowContent){ |
| 558 | - style_submenu_element("Line Numbers", "Line Numbers", | |
| 559 | - "%R/ainfo/%s%s",zUuid, | |
| 558 | + style_submenu_element("Line Numbers", "%R/ainfo/%s%s", zUuid, | |
| 560 | 559 | ((zLn&&*zLn) ? "" : "?ln=0")); |
| 561 | 560 | } |
| 562 | 561 | |
| 563 | 562 | @ <div class="section">Overview</div> |
| 564 | 563 | @ <p><table class="label-value"> |
| @@ -629,11 +628,11 @@ | ||
| 629 | 628 | } |
| 630 | 629 | }else if( strncmp(zMime, "image/", 6)==0 ){ |
| 631 | 630 | int sz = db_int(0, "SELECT size FROM blob WHERE rid=%d", ridSrc); |
| 632 | 631 | @ <i>(file is %d(sz) bytes of image data)</i><br /> |
| 633 | 632 | @ <img src="%R/raw/%s(zSrc)?m=%s(zMime)"></img> |
| 634 | - style_submenu_element("Image", "Image", "%R/raw/%s?m=%s", zSrc, zMime); | |
| 633 | + style_submenu_element("Image", "%R/raw/%s?m=%s", zSrc, zMime); | |
| 635 | 634 | }else{ |
| 636 | 635 | int sz = db_int(0, "SELECT size FROM blob WHERE rid=%d", ridSrc); |
| 637 | 636 | @ <i>(file is %d(sz) bytes of binary data)</i> |
| 638 | 637 | } |
| 639 | 638 | @ </blockquote> |
| 640 | 639 |
| --- src/attach.c | |
| +++ src/attach.c | |
| @@ -452,14 +452,14 @@ | |
| 452 | #if 0 |
| 453 | /* Shunning here needs to get both the attachment control artifact and |
| 454 | ** the object that is attached. */ |
| 455 | if( g.perm.Admin ){ |
| 456 | if( db_exists("SELECT 1 FROM shun WHERE uuid='%q'", zUuid) ){ |
| 457 | style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", |
| 458 | g.zTop, zUuid); |
| 459 | }else{ |
| 460 | style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", |
| 461 | g.zTop, zUuid); |
| 462 | } |
| 463 | } |
| 464 | #endif |
| 465 | pAttach = manifest_get(rid, CFTYPE_ATTACHMENT, 0); |
| @@ -475,23 +475,23 @@ | |
| 475 | && db_exists("SELECT 1 FROM ticket WHERE tkt_uuid='%q'", zTarget) |
| 476 | ){ |
| 477 | zTktUuid = zTarget; |
| 478 | if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; } |
| 479 | if( g.perm.WrTkt ){ |
| 480 | style_submenu_element("Delete","Delete","%R/ainfo/%s?del", zUuid); |
| 481 | } |
| 482 | }else if( db_exists("SELECT 1 FROM tag WHERE tagname='wiki-%q'",zTarget) ){ |
| 483 | zWikiName = zTarget; |
| 484 | if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; } |
| 485 | if( g.perm.WrWiki ){ |
| 486 | style_submenu_element("Delete","Delete","%R/ainfo/%s?del", zUuid); |
| 487 | } |
| 488 | }else if( db_exists("SELECT 1 FROM tag WHERE tagname='event-%q'",zTarget) ){ |
| 489 | zTNUuid = zTarget; |
| 490 | if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; } |
| 491 | if( g.perm.Write && g.perm.WrWiki ){ |
| 492 | style_submenu_element("Delete","Delete","%R/ainfo/%s?del", zUuid); |
| 493 | } |
| 494 | } |
| 495 | zDate = db_text(0, "SELECT datetime(%.12f)", pAttach->rDate); |
| 496 | |
| 497 | if( P("confirm") |
| @@ -551,14 +551,13 @@ | |
| 551 | if( strcmp(zModAction,"approve")==0 ){ |
| 552 | moderation_approve(rid); |
| 553 | } |
| 554 | } |
| 555 | style_header("Attachment Details"); |
| 556 | style_submenu_element("Raw", "Raw", "%R/artifact/%s", zUuid); |
| 557 | if(fShowContent){ |
| 558 | style_submenu_element("Line Numbers", "Line Numbers", |
| 559 | "%R/ainfo/%s%s",zUuid, |
| 560 | ((zLn&&*zLn) ? "" : "?ln=0")); |
| 561 | } |
| 562 | |
| 563 | @ <div class="section">Overview</div> |
| 564 | @ <p><table class="label-value"> |
| @@ -629,11 +628,11 @@ | |
| 629 | } |
| 630 | }else if( strncmp(zMime, "image/", 6)==0 ){ |
| 631 | int sz = db_int(0, "SELECT size FROM blob WHERE rid=%d", ridSrc); |
| 632 | @ <i>(file is %d(sz) bytes of image data)</i><br /> |
| 633 | @ <img src="%R/raw/%s(zSrc)?m=%s(zMime)"></img> |
| 634 | style_submenu_element("Image", "Image", "%R/raw/%s?m=%s", zSrc, zMime); |
| 635 | }else{ |
| 636 | int sz = db_int(0, "SELECT size FROM blob WHERE rid=%d", ridSrc); |
| 637 | @ <i>(file is %d(sz) bytes of binary data)</i> |
| 638 | } |
| 639 | @ </blockquote> |
| 640 |
| --- src/attach.c | |
| +++ src/attach.c | |
| @@ -452,14 +452,14 @@ | |
| 452 | #if 0 |
| 453 | /* Shunning here needs to get both the attachment control artifact and |
| 454 | ** the object that is attached. */ |
| 455 | if( g.perm.Admin ){ |
| 456 | if( db_exists("SELECT 1 FROM shun WHERE uuid='%q'", zUuid) ){ |
| 457 | style_submenu_element("Unshun", "%s/shun?uuid=%s&sub=1", |
| 458 | g.zTop, zUuid); |
| 459 | }else{ |
| 460 | style_submenu_element("Shun", "%s/shun?shun=%s#addshun", |
| 461 | g.zTop, zUuid); |
| 462 | } |
| 463 | } |
| 464 | #endif |
| 465 | pAttach = manifest_get(rid, CFTYPE_ATTACHMENT, 0); |
| @@ -475,23 +475,23 @@ | |
| 475 | && db_exists("SELECT 1 FROM ticket WHERE tkt_uuid='%q'", zTarget) |
| 476 | ){ |
| 477 | zTktUuid = zTarget; |
| 478 | if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; } |
| 479 | if( g.perm.WrTkt ){ |
| 480 | style_submenu_element("Delete", "%R/ainfo/%s?del", zUuid); |
| 481 | } |
| 482 | }else if( db_exists("SELECT 1 FROM tag WHERE tagname='wiki-%q'",zTarget) ){ |
| 483 | zWikiName = zTarget; |
| 484 | if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; } |
| 485 | if( g.perm.WrWiki ){ |
| 486 | style_submenu_element("Delete", "%R/ainfo/%s?del", zUuid); |
| 487 | } |
| 488 | }else if( db_exists("SELECT 1 FROM tag WHERE tagname='event-%q'",zTarget) ){ |
| 489 | zTNUuid = zTarget; |
| 490 | if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; } |
| 491 | if( g.perm.Write && g.perm.WrWiki ){ |
| 492 | style_submenu_element("Delete", "%R/ainfo/%s?del", zUuid); |
| 493 | } |
| 494 | } |
| 495 | zDate = db_text(0, "SELECT datetime(%.12f)", pAttach->rDate); |
| 496 | |
| 497 | if( P("confirm") |
| @@ -551,14 +551,13 @@ | |
| 551 | if( strcmp(zModAction,"approve")==0 ){ |
| 552 | moderation_approve(rid); |
| 553 | } |
| 554 | } |
| 555 | style_header("Attachment Details"); |
| 556 | style_submenu_element("Raw", "%R/artifact/%s", zUuid); |
| 557 | if(fShowContent){ |
| 558 | style_submenu_element("Line Numbers", "%R/ainfo/%s%s", zUuid, |
| 559 | ((zLn&&*zLn) ? "" : "?ln=0")); |
| 560 | } |
| 561 | |
| 562 | @ <div class="section">Overview</div> |
| 563 | @ <p><table class="label-value"> |
| @@ -629,11 +628,11 @@ | |
| 628 | } |
| 629 | }else if( strncmp(zMime, "image/", 6)==0 ){ |
| 630 | int sz = db_int(0, "SELECT size FROM blob WHERE rid=%d", ridSrc); |
| 631 | @ <i>(file is %d(sz) bytes of image data)</i><br /> |
| 632 | @ <img src="%R/raw/%s(zSrc)?m=%s(zMime)"></img> |
| 633 | style_submenu_element("Image", "%R/raw/%s?m=%s", zSrc, zMime); |
| 634 | }else{ |
| 635 | int sz = db_int(0, "SELECT size FROM blob WHERE rid=%d", ridSrc); |
| 636 | @ <i>(file is %d(sz) bytes of binary data)</i> |
| 637 | } |
| 638 | @ </blockquote> |
| 639 |
+4
-4
| --- src/bisect.c | ||
| +++ src/bisect.c | ||
| @@ -75,11 +75,11 @@ | ||
| 75 | 75 | ** Return the value of a boolean bisect option. |
| 76 | 76 | */ |
| 77 | 77 | int bisect_option(const char *zName){ |
| 78 | 78 | unsigned int i; |
| 79 | 79 | int r = -1; |
| 80 | - for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){ | |
| 80 | + for(i=0; i<count(aBisectOption); i++){ | |
| 81 | 81 | if( fossil_strcmp(zName, aBisectOption[i].zName)==0 ){ |
| 82 | 82 | char *zLabel = mprintf("bisect-%s", zName); |
| 83 | 83 | char *z = db_lget(zLabel, (char*)aBisectOption[i].zDefault); |
| 84 | 84 | if( is_truth(z) ) r = 1; |
| 85 | 85 | if( is_false(z) ) r = 0; |
| @@ -406,21 +406,21 @@ | ||
| 406 | 406 | }else if( strncmp(zCmd, "chart", n)==0 ){ |
| 407 | 407 | bisect_chart(1); |
| 408 | 408 | }else if( strncmp(zCmd, "options", n)==0 ){ |
| 409 | 409 | if( g.argc==3 ){ |
| 410 | 410 | unsigned int i; |
| 411 | - for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){ | |
| 411 | + for(i=0; i<count(aBisectOption); i++){ | |
| 412 | 412 | char *z = mprintf("bisect-%s", aBisectOption[i].zName); |
| 413 | 413 | fossil_print(" %-15s %-6s ", aBisectOption[i].zName, |
| 414 | 414 | db_lget(z, (char*)aBisectOption[i].zDefault)); |
| 415 | 415 | fossil_free(z); |
| 416 | 416 | comment_print(aBisectOption[i].zDesc, 0, 27, -1, g.comFmtFlags); |
| 417 | 417 | } |
| 418 | 418 | }else if( g.argc==4 || g.argc==5 ){ |
| 419 | 419 | unsigned int i; |
| 420 | 420 | n = strlen(g.argv[3]); |
| 421 | - for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){ | |
| 421 | + for(i=0; i<count(aBisectOption); i++){ | |
| 422 | 422 | if( strncmp(g.argv[3], aBisectOption[i].zName, n)==0 ){ |
| 423 | 423 | char *z = mprintf("bisect-%s", aBisectOption[i].zName); |
| 424 | 424 | if( g.argc==5 ){ |
| 425 | 425 | db_lset(z, g.argv[4]); |
| 426 | 426 | } |
| @@ -427,11 +427,11 @@ | ||
| 427 | 427 | fossil_print("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault)); |
| 428 | 428 | fossil_free(z); |
| 429 | 429 | break; |
| 430 | 430 | } |
| 431 | 431 | } |
| 432 | - if( i>=sizeof(aBisectOption)/sizeof(aBisectOption[0]) ){ | |
| 432 | + if( i>=count(aBisectOption) ){ | |
| 433 | 433 | fossil_fatal("no such bisect option: %s", g.argv[3]); |
| 434 | 434 | } |
| 435 | 435 | }else{ |
| 436 | 436 | usage("options ?NAME? ?VALUE?"); |
| 437 | 437 | } |
| 438 | 438 |
| --- src/bisect.c | |
| +++ src/bisect.c | |
| @@ -75,11 +75,11 @@ | |
| 75 | ** Return the value of a boolean bisect option. |
| 76 | */ |
| 77 | int bisect_option(const char *zName){ |
| 78 | unsigned int i; |
| 79 | int r = -1; |
| 80 | for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){ |
| 81 | if( fossil_strcmp(zName, aBisectOption[i].zName)==0 ){ |
| 82 | char *zLabel = mprintf("bisect-%s", zName); |
| 83 | char *z = db_lget(zLabel, (char*)aBisectOption[i].zDefault); |
| 84 | if( is_truth(z) ) r = 1; |
| 85 | if( is_false(z) ) r = 0; |
| @@ -406,21 +406,21 @@ | |
| 406 | }else if( strncmp(zCmd, "chart", n)==0 ){ |
| 407 | bisect_chart(1); |
| 408 | }else if( strncmp(zCmd, "options", n)==0 ){ |
| 409 | if( g.argc==3 ){ |
| 410 | unsigned int i; |
| 411 | for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){ |
| 412 | char *z = mprintf("bisect-%s", aBisectOption[i].zName); |
| 413 | fossil_print(" %-15s %-6s ", aBisectOption[i].zName, |
| 414 | db_lget(z, (char*)aBisectOption[i].zDefault)); |
| 415 | fossil_free(z); |
| 416 | comment_print(aBisectOption[i].zDesc, 0, 27, -1, g.comFmtFlags); |
| 417 | } |
| 418 | }else if( g.argc==4 || g.argc==5 ){ |
| 419 | unsigned int i; |
| 420 | n = strlen(g.argv[3]); |
| 421 | for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){ |
| 422 | if( strncmp(g.argv[3], aBisectOption[i].zName, n)==0 ){ |
| 423 | char *z = mprintf("bisect-%s", aBisectOption[i].zName); |
| 424 | if( g.argc==5 ){ |
| 425 | db_lset(z, g.argv[4]); |
| 426 | } |
| @@ -427,11 +427,11 @@ | |
| 427 | fossil_print("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault)); |
| 428 | fossil_free(z); |
| 429 | break; |
| 430 | } |
| 431 | } |
| 432 | if( i>=sizeof(aBisectOption)/sizeof(aBisectOption[0]) ){ |
| 433 | fossil_fatal("no such bisect option: %s", g.argv[3]); |
| 434 | } |
| 435 | }else{ |
| 436 | usage("options ?NAME? ?VALUE?"); |
| 437 | } |
| 438 |
| --- src/bisect.c | |
| +++ src/bisect.c | |
| @@ -75,11 +75,11 @@ | |
| 75 | ** Return the value of a boolean bisect option. |
| 76 | */ |
| 77 | int bisect_option(const char *zName){ |
| 78 | unsigned int i; |
| 79 | int r = -1; |
| 80 | for(i=0; i<count(aBisectOption); i++){ |
| 81 | if( fossil_strcmp(zName, aBisectOption[i].zName)==0 ){ |
| 82 | char *zLabel = mprintf("bisect-%s", zName); |
| 83 | char *z = db_lget(zLabel, (char*)aBisectOption[i].zDefault); |
| 84 | if( is_truth(z) ) r = 1; |
| 85 | if( is_false(z) ) r = 0; |
| @@ -406,21 +406,21 @@ | |
| 406 | }else if( strncmp(zCmd, "chart", n)==0 ){ |
| 407 | bisect_chart(1); |
| 408 | }else if( strncmp(zCmd, "options", n)==0 ){ |
| 409 | if( g.argc==3 ){ |
| 410 | unsigned int i; |
| 411 | for(i=0; i<count(aBisectOption); i++){ |
| 412 | char *z = mprintf("bisect-%s", aBisectOption[i].zName); |
| 413 | fossil_print(" %-15s %-6s ", aBisectOption[i].zName, |
| 414 | db_lget(z, (char*)aBisectOption[i].zDefault)); |
| 415 | fossil_free(z); |
| 416 | comment_print(aBisectOption[i].zDesc, 0, 27, -1, g.comFmtFlags); |
| 417 | } |
| 418 | }else if( g.argc==4 || g.argc==5 ){ |
| 419 | unsigned int i; |
| 420 | n = strlen(g.argv[3]); |
| 421 | for(i=0; i<count(aBisectOption); i++){ |
| 422 | if( strncmp(g.argv[3], aBisectOption[i].zName, n)==0 ){ |
| 423 | char *z = mprintf("bisect-%s", aBisectOption[i].zName); |
| 424 | if( g.argc==5 ){ |
| 425 | db_lset(z, g.argv[4]); |
| 426 | } |
| @@ -427,11 +427,11 @@ | |
| 427 | fossil_print("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault)); |
| 428 | fossil_free(z); |
| 429 | break; |
| 430 | } |
| 431 | } |
| 432 | if( i>=count(aBisectOption) ){ |
| 433 | fossil_fatal("no such bisect option: %s", g.argv[3]); |
| 434 | } |
| 435 | }else{ |
| 436 | usage("options ?NAME? ?VALUE?"); |
| 437 | } |
| 438 |
+28
-13
| --- src/branch.c | ||
| +++ src/branch.c | ||
| @@ -154,11 +154,11 @@ | ||
| 154 | 154 | if( brid==0 ){ |
| 155 | 155 | fossil_fatal("trouble committing manifest: %s", g.zErrMsg); |
| 156 | 156 | } |
| 157 | 157 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid); |
| 158 | 158 | if( manifest_crosslink(brid, &branch, MC_PERMIT_HOOKS)==0 ){ |
| 159 | - fossil_fatal("%s\n", g.zErrMsg); | |
| 159 | + fossil_fatal("%s", g.zErrMsg); | |
| 160 | 160 | } |
| 161 | 161 | assert( blob_is_reset(&branch) ); |
| 162 | 162 | content_deltify(rootid, brid, 0); |
| 163 | 163 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", brid); |
| 164 | 164 | fossil_print("New branch: %s\n", zUuid); |
| @@ -323,11 +323,12 @@ | ||
| 323 | 323 | @ WHERE plink.pid=event.objid |
| 324 | 324 | @ AND tagxref.rid=plink.cid |
| 325 | 325 | @ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch') |
| 326 | 326 | @ AND tagtype>0), |
| 327 | 327 | @ count(*), |
| 328 | -@ (SELECT uuid FROM blob WHERE rid=tagxref.rid) | |
| 328 | +@ (SELECT uuid FROM blob WHERE rid=tagxref.rid), | |
| 329 | +@ event.bgcolor | |
| 329 | 330 | @ FROM tagxref, tag, event |
| 330 | 331 | @ WHERE tagxref.tagid=tag.tagid |
| 331 | 332 | @ AND tagxref.tagtype>0 |
| 332 | 333 | @ AND tag.tagname='branch' |
| 333 | 334 | @ AND event.objid=tagxref.rid |
| @@ -344,14 +345,16 @@ | ||
| 344 | 345 | ** if there are no query parameters. |
| 345 | 346 | */ |
| 346 | 347 | static void new_brlist_page(void){ |
| 347 | 348 | Stmt q; |
| 348 | 349 | double rNow; |
| 350 | + int show_colors = PB("colors"); | |
| 349 | 351 | login_check_credentials(); |
| 350 | 352 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 351 | 353 | style_header("Branches"); |
| 352 | 354 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 355 | + style_submenu_checkbox("colors", "Use Branch Colors", 0); | |
| 353 | 356 | login_anonymous_available(); |
| 354 | 357 | |
| 355 | 358 | db_prepare(&q, brlistQuery/*works-like:""*/); |
| 356 | 359 | rNow = db_double(0.0, "SELECT julianday('now')"); |
| 357 | 360 | @ <div class="brlist"><table id="branchlisttable"> |
| @@ -367,14 +370,26 @@ | ||
| 367 | 370 | double rMtime = db_column_double(&q, 1); |
| 368 | 371 | int isClosed = db_column_int(&q, 2); |
| 369 | 372 | const char *zMergeTo = db_column_text(&q, 3); |
| 370 | 373 | int nCkin = db_column_int(&q, 4); |
| 371 | 374 | const char *zLastCkin = db_column_text(&q, 5); |
| 375 | + const char *zBgClr = db_column_text(&q, 6); | |
| 372 | 376 | char *zAge = human_readable_age(rNow - rMtime); |
| 373 | 377 | sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0); |
| 374 | 378 | if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0; |
| 375 | - @ <tr> | |
| 379 | + if( zBgClr == 0 ){ | |
| 380 | + if( zBranch==0 || strcmp(zBranch,"trunk")==0 ){ | |
| 381 | + zBgClr = 0; | |
| 382 | + }else{ | |
| 383 | + zBgClr = hash_color(zBranch); | |
| 384 | + } | |
| 385 | + } | |
| 386 | + if( zBgClr && zBgClr[0] && show_colors ){ | |
| 387 | + @ <tr style="background-color:%s(zBgClr)"> | |
| 388 | + }else{ | |
| 389 | + @ <tr> | |
| 390 | + } | |
| 376 | 391 | @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td> |
| 377 | 392 | @ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td> |
| 378 | 393 | @ <td>%d(nCkin)</td> |
| 379 | 394 | fossil_free(zAge); |
| 380 | 395 | @ <td>%s(isClosed?"closed":"")</td> |
| @@ -427,25 +442,25 @@ | ||
| 427 | 442 | if( showAll ) brFlags = BRL_BOTH; |
| 428 | 443 | if( showClosed ) brFlags = BRL_CLOSED_ONLY; |
| 429 | 444 | |
| 430 | 445 | style_header("%s", showClosed ? "Closed Branches" : |
| 431 | 446 | showAll ? "All Branches" : "Open Branches"); |
| 432 | - style_submenu_element("Timeline", "Timeline", "brtimeline"); | |
| 447 | + style_submenu_element("Timeline", "brtimeline"); | |
| 433 | 448 | if( showClosed ){ |
| 434 | - style_submenu_element("All", "All", "brlist?all"); | |
| 435 | - style_submenu_element("Open","Open","brlist?open"); | |
| 449 | + style_submenu_element("All", "brlist?all"); | |
| 450 | + style_submenu_element("Open", "brlist?open"); | |
| 436 | 451 | }else if( showAll ){ |
| 437 | - style_submenu_element("Closed", "Closed", "brlist?closed"); | |
| 438 | - style_submenu_element("Open","Open","brlist"); | |
| 452 | + style_submenu_element("Closed", "brlist?closed"); | |
| 453 | + style_submenu_element("Open", "brlist"); | |
| 439 | 454 | }else{ |
| 440 | - style_submenu_element("All", "All", "brlist?all"); | |
| 441 | - style_submenu_element("Closed","Closed","brlist?closed"); | |
| 455 | + style_submenu_element("All", "brlist?all"); | |
| 456 | + style_submenu_element("Closed", "brlist?closed"); | |
| 442 | 457 | } |
| 443 | 458 | if( !colorTest ){ |
| 444 | - style_submenu_element("Color-Test", "Color-Test", "brlist?colortest"); | |
| 459 | + style_submenu_element("Color-Test", "brlist?colortest"); | |
| 445 | 460 | }else{ |
| 446 | - style_submenu_element("All", "All", "brlist?all"); | |
| 461 | + style_submenu_element("All", "brlist?all"); | |
| 447 | 462 | } |
| 448 | 463 | login_anonymous_available(); |
| 449 | 464 | #if 0 |
| 450 | 465 | style_sidebox_begin("Nomenclature:", "33%"); |
| 451 | 466 | @ <ol> |
| @@ -529,11 +544,11 @@ | ||
| 529 | 544 | |
| 530 | 545 | login_check_credentials(); |
| 531 | 546 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 532 | 547 | |
| 533 | 548 | style_header("Branches"); |
| 534 | - style_submenu_element("List", "List", "brlist"); | |
| 549 | + style_submenu_element("List", "brlist"); | |
| 535 | 550 | login_anonymous_available(); |
| 536 | 551 | @ <h2>The initial check-in for each branch:</h2> |
| 537 | 552 | db_prepare(&q, |
| 538 | 553 | "%s AND blob.rid IN (SELECT rid FROM tagxref" |
| 539 | 554 | " WHERE tagtype>0 AND tagid=%d AND srcid!=0)" |
| 540 | 555 |
| --- src/branch.c | |
| +++ src/branch.c | |
| @@ -154,11 +154,11 @@ | |
| 154 | if( brid==0 ){ |
| 155 | fossil_fatal("trouble committing manifest: %s", g.zErrMsg); |
| 156 | } |
| 157 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid); |
| 158 | if( manifest_crosslink(brid, &branch, MC_PERMIT_HOOKS)==0 ){ |
| 159 | fossil_fatal("%s\n", g.zErrMsg); |
| 160 | } |
| 161 | assert( blob_is_reset(&branch) ); |
| 162 | content_deltify(rootid, brid, 0); |
| 163 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", brid); |
| 164 | fossil_print("New branch: %s\n", zUuid); |
| @@ -323,11 +323,12 @@ | |
| 323 | @ WHERE plink.pid=event.objid |
| 324 | @ AND tagxref.rid=plink.cid |
| 325 | @ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch') |
| 326 | @ AND tagtype>0), |
| 327 | @ count(*), |
| 328 | @ (SELECT uuid FROM blob WHERE rid=tagxref.rid) |
| 329 | @ FROM tagxref, tag, event |
| 330 | @ WHERE tagxref.tagid=tag.tagid |
| 331 | @ AND tagxref.tagtype>0 |
| 332 | @ AND tag.tagname='branch' |
| 333 | @ AND event.objid=tagxref.rid |
| @@ -344,14 +345,16 @@ | |
| 344 | ** if there are no query parameters. |
| 345 | */ |
| 346 | static void new_brlist_page(void){ |
| 347 | Stmt q; |
| 348 | double rNow; |
| 349 | login_check_credentials(); |
| 350 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 351 | style_header("Branches"); |
| 352 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 353 | login_anonymous_available(); |
| 354 | |
| 355 | db_prepare(&q, brlistQuery/*works-like:""*/); |
| 356 | rNow = db_double(0.0, "SELECT julianday('now')"); |
| 357 | @ <div class="brlist"><table id="branchlisttable"> |
| @@ -367,14 +370,26 @@ | |
| 367 | double rMtime = db_column_double(&q, 1); |
| 368 | int isClosed = db_column_int(&q, 2); |
| 369 | const char *zMergeTo = db_column_text(&q, 3); |
| 370 | int nCkin = db_column_int(&q, 4); |
| 371 | const char *zLastCkin = db_column_text(&q, 5); |
| 372 | char *zAge = human_readable_age(rNow - rMtime); |
| 373 | sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0); |
| 374 | if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0; |
| 375 | @ <tr> |
| 376 | @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td> |
| 377 | @ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td> |
| 378 | @ <td>%d(nCkin)</td> |
| 379 | fossil_free(zAge); |
| 380 | @ <td>%s(isClosed?"closed":"")</td> |
| @@ -427,25 +442,25 @@ | |
| 427 | if( showAll ) brFlags = BRL_BOTH; |
| 428 | if( showClosed ) brFlags = BRL_CLOSED_ONLY; |
| 429 | |
| 430 | style_header("%s", showClosed ? "Closed Branches" : |
| 431 | showAll ? "All Branches" : "Open Branches"); |
| 432 | style_submenu_element("Timeline", "Timeline", "brtimeline"); |
| 433 | if( showClosed ){ |
| 434 | style_submenu_element("All", "All", "brlist?all"); |
| 435 | style_submenu_element("Open","Open","brlist?open"); |
| 436 | }else if( showAll ){ |
| 437 | style_submenu_element("Closed", "Closed", "brlist?closed"); |
| 438 | style_submenu_element("Open","Open","brlist"); |
| 439 | }else{ |
| 440 | style_submenu_element("All", "All", "brlist?all"); |
| 441 | style_submenu_element("Closed","Closed","brlist?closed"); |
| 442 | } |
| 443 | if( !colorTest ){ |
| 444 | style_submenu_element("Color-Test", "Color-Test", "brlist?colortest"); |
| 445 | }else{ |
| 446 | style_submenu_element("All", "All", "brlist?all"); |
| 447 | } |
| 448 | login_anonymous_available(); |
| 449 | #if 0 |
| 450 | style_sidebox_begin("Nomenclature:", "33%"); |
| 451 | @ <ol> |
| @@ -529,11 +544,11 @@ | |
| 529 | |
| 530 | login_check_credentials(); |
| 531 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 532 | |
| 533 | style_header("Branches"); |
| 534 | style_submenu_element("List", "List", "brlist"); |
| 535 | login_anonymous_available(); |
| 536 | @ <h2>The initial check-in for each branch:</h2> |
| 537 | db_prepare(&q, |
| 538 | "%s AND blob.rid IN (SELECT rid FROM tagxref" |
| 539 | " WHERE tagtype>0 AND tagid=%d AND srcid!=0)" |
| 540 |
| --- src/branch.c | |
| +++ src/branch.c | |
| @@ -154,11 +154,11 @@ | |
| 154 | if( brid==0 ){ |
| 155 | fossil_fatal("trouble committing manifest: %s", g.zErrMsg); |
| 156 | } |
| 157 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid); |
| 158 | if( manifest_crosslink(brid, &branch, MC_PERMIT_HOOKS)==0 ){ |
| 159 | fossil_fatal("%s", g.zErrMsg); |
| 160 | } |
| 161 | assert( blob_is_reset(&branch) ); |
| 162 | content_deltify(rootid, brid, 0); |
| 163 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", brid); |
| 164 | fossil_print("New branch: %s\n", zUuid); |
| @@ -323,11 +323,12 @@ | |
| 323 | @ WHERE plink.pid=event.objid |
| 324 | @ AND tagxref.rid=plink.cid |
| 325 | @ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch') |
| 326 | @ AND tagtype>0), |
| 327 | @ count(*), |
| 328 | @ (SELECT uuid FROM blob WHERE rid=tagxref.rid), |
| 329 | @ event.bgcolor |
| 330 | @ FROM tagxref, tag, event |
| 331 | @ WHERE tagxref.tagid=tag.tagid |
| 332 | @ AND tagxref.tagtype>0 |
| 333 | @ AND tag.tagname='branch' |
| 334 | @ AND event.objid=tagxref.rid |
| @@ -344,14 +345,16 @@ | |
| 345 | ** if there are no query parameters. |
| 346 | */ |
| 347 | static void new_brlist_page(void){ |
| 348 | Stmt q; |
| 349 | double rNow; |
| 350 | int show_colors = PB("colors"); |
| 351 | login_check_credentials(); |
| 352 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 353 | style_header("Branches"); |
| 354 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 355 | style_submenu_checkbox("colors", "Use Branch Colors", 0); |
| 356 | login_anonymous_available(); |
| 357 | |
| 358 | db_prepare(&q, brlistQuery/*works-like:""*/); |
| 359 | rNow = db_double(0.0, "SELECT julianday('now')"); |
| 360 | @ <div class="brlist"><table id="branchlisttable"> |
| @@ -367,14 +370,26 @@ | |
| 370 | double rMtime = db_column_double(&q, 1); |
| 371 | int isClosed = db_column_int(&q, 2); |
| 372 | const char *zMergeTo = db_column_text(&q, 3); |
| 373 | int nCkin = db_column_int(&q, 4); |
| 374 | const char *zLastCkin = db_column_text(&q, 5); |
| 375 | const char *zBgClr = db_column_text(&q, 6); |
| 376 | char *zAge = human_readable_age(rNow - rMtime); |
| 377 | sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0); |
| 378 | if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0; |
| 379 | if( zBgClr == 0 ){ |
| 380 | if( zBranch==0 || strcmp(zBranch,"trunk")==0 ){ |
| 381 | zBgClr = 0; |
| 382 | }else{ |
| 383 | zBgClr = hash_color(zBranch); |
| 384 | } |
| 385 | } |
| 386 | if( zBgClr && zBgClr[0] && show_colors ){ |
| 387 | @ <tr style="background-color:%s(zBgClr)"> |
| 388 | }else{ |
| 389 | @ <tr> |
| 390 | } |
| 391 | @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td> |
| 392 | @ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td> |
| 393 | @ <td>%d(nCkin)</td> |
| 394 | fossil_free(zAge); |
| 395 | @ <td>%s(isClosed?"closed":"")</td> |
| @@ -427,25 +442,25 @@ | |
| 442 | if( showAll ) brFlags = BRL_BOTH; |
| 443 | if( showClosed ) brFlags = BRL_CLOSED_ONLY; |
| 444 | |
| 445 | style_header("%s", showClosed ? "Closed Branches" : |
| 446 | showAll ? "All Branches" : "Open Branches"); |
| 447 | style_submenu_element("Timeline", "brtimeline"); |
| 448 | if( showClosed ){ |
| 449 | style_submenu_element("All", "brlist?all"); |
| 450 | style_submenu_element("Open", "brlist?open"); |
| 451 | }else if( showAll ){ |
| 452 | style_submenu_element("Closed", "brlist?closed"); |
| 453 | style_submenu_element("Open", "brlist"); |
| 454 | }else{ |
| 455 | style_submenu_element("All", "brlist?all"); |
| 456 | style_submenu_element("Closed", "brlist?closed"); |
| 457 | } |
| 458 | if( !colorTest ){ |
| 459 | style_submenu_element("Color-Test", "brlist?colortest"); |
| 460 | }else{ |
| 461 | style_submenu_element("All", "brlist?all"); |
| 462 | } |
| 463 | login_anonymous_available(); |
| 464 | #if 0 |
| 465 | style_sidebox_begin("Nomenclature:", "33%"); |
| 466 | @ <ol> |
| @@ -529,11 +544,11 @@ | |
| 544 | |
| 545 | login_check_credentials(); |
| 546 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 547 | |
| 548 | style_header("Branches"); |
| 549 | style_submenu_element("List", "brlist"); |
| 550 | login_anonymous_available(); |
| 551 | @ <h2>The initial check-in for each branch:</h2> |
| 552 | db_prepare(&q, |
| 553 | "%s AND blob.rid IN (SELECT rid FROM tagxref" |
| 554 | " WHERE tagtype>0 AND tagid=%d AND srcid!=0)" |
| 555 |
+15
-25
| --- src/browse.c | ||
| +++ src/browse.c | ||
| @@ -171,40 +171,37 @@ | ||
| 171 | 171 | blob_zero(&dirname); |
| 172 | 172 | if( zD ){ |
| 173 | 173 | blob_append(&dirname, "in directory ", -1); |
| 174 | 174 | hyperlinked_path(zD, &dirname, zCI, "dir", ""); |
| 175 | 175 | zPrefix = mprintf("%s/", zD); |
| 176 | - style_submenu_element("Top-Level", "Top-Level", "%s", | |
| 176 | + style_submenu_element("Top-Level", "%s", | |
| 177 | 177 | url_render(&sURI, "name", 0, 0, 0)); |
| 178 | 178 | }else{ |
| 179 | 179 | blob_append(&dirname, "in the top-level directory", -1); |
| 180 | 180 | zPrefix = ""; |
| 181 | 181 | } |
| 182 | 182 | if( linkTrunk ){ |
| 183 | - style_submenu_element("Trunk", "Trunk", "%s", | |
| 183 | + style_submenu_element("Trunk", "%s", | |
| 184 | 184 | url_render(&sURI, "ci", "trunk", 0, 0)); |
| 185 | 185 | } |
| 186 | 186 | if( linkTip ){ |
| 187 | - style_submenu_element("Tip", "Tip", "%s", | |
| 188 | - url_render(&sURI, "ci", "tip", 0, 0)); | |
| 187 | + style_submenu_element("Tip", "%s", url_render(&sURI, "ci", "tip", 0, 0)); | |
| 189 | 188 | } |
| 190 | 189 | if( zCI ){ |
| 191 | 190 | @ <h2>Files of check-in [%z(href("vinfo?name=%!S",zUuid))%S(zUuid)</a>] |
| 192 | 191 | @ %s(blob_str(&dirname))</h2> |
| 193 | 192 | zSubdirLink = mprintf("%R/dir?ci=%!S&name=%T", zUuid, zPrefix); |
| 194 | 193 | if( nD==0 ){ |
| 195 | - style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%!S", | |
| 196 | - zUuid); | |
| 194 | + style_submenu_element("File Ages", "%R/fileage?name=%!S", zUuid); | |
| 197 | 195 | } |
| 198 | 196 | }else{ |
| 199 | 197 | @ <h2>The union of all files from all check-ins |
| 200 | 198 | @ %s(blob_str(&dirname))</h2> |
| 201 | 199 | zSubdirLink = mprintf("%R/dir?name=%T", zPrefix); |
| 202 | 200 | } |
| 203 | - style_submenu_element("All", "All", "%s", | |
| 204 | - url_render(&sURI, "ci", 0, 0, 0)); | |
| 205 | - style_submenu_element("Tree-View", "Tree-View", "%s", | |
| 201 | + style_submenu_element("All", "%s", url_render(&sURI, "ci", 0, 0, 0)); | |
| 202 | + style_submenu_element("Tree-View", "%s", | |
| 206 | 203 | url_render(&sURI, "type", "tree", 0, 0)); |
| 207 | 204 | |
| 208 | 205 | /* Compute the temporary table "localfiles" containing the names |
| 209 | 206 | ** of all files and subdirectories in the zD[] directory. |
| 210 | 207 | ** |
| @@ -616,35 +613,32 @@ | ||
| 616 | 613 | blob_zero(&dirname); |
| 617 | 614 | if( zD ){ |
| 618 | 615 | blob_append(&dirname, "within directory ", -1); |
| 619 | 616 | hyperlinked_path(zD, &dirname, zCI, "tree", zREx); |
| 620 | 617 | if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE); |
| 621 | - style_submenu_element("Top-Level", "Top-Level", "%s", | |
| 618 | + style_submenu_element("Top-Level", "%s", | |
| 622 | 619 | url_render(&sURI, "name", 0, 0, 0)); |
| 623 | 620 | }else{ |
| 624 | 621 | if( zRE ){ |
| 625 | 622 | blob_appendf(&dirname, "matching \"%s\"", zRE); |
| 626 | 623 | } |
| 627 | 624 | } |
| 628 | 625 | style_submenu_binary("mtime","Sort By Time","Sort By Filename", 0); |
| 629 | 626 | if( zCI ){ |
| 630 | - style_submenu_element("All", "All", "%s", | |
| 631 | - url_render(&sURI, "ci", 0, 0, 0)); | |
| 627 | + style_submenu_element("All", "%s", url_render(&sURI, "ci", 0, 0, 0)); | |
| 632 | 628 | if( nD==0 && !showDirOnly ){ |
| 633 | - style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%s", | |
| 634 | - zUuid); | |
| 629 | + style_submenu_element("File Ages", "%R/fileage?name=%s", zUuid); | |
| 635 | 630 | } |
| 636 | 631 | } |
| 637 | 632 | if( linkTrunk ){ |
| 638 | - style_submenu_element("Trunk", "Trunk", "%s", | |
| 633 | + style_submenu_element("Trunk", "%s", | |
| 639 | 634 | url_render(&sURI, "ci", "trunk", 0, 0)); |
| 640 | 635 | } |
| 641 | 636 | if( linkTip ){ |
| 642 | - style_submenu_element("Tip", "Tip", "%s", | |
| 643 | - url_render(&sURI, "ci", "tip", 0, 0)); | |
| 637 | + style_submenu_element("Tip", "%s", url_render(&sURI, "ci", "tip", 0, 0)); | |
| 644 | 638 | } |
| 645 | - style_submenu_element("Flat-View", "Flat-View", "%s", | |
| 639 | + style_submenu_element("Flat-View", "%s", | |
| 646 | 640 | url_render(&sURI, "type", "flat", 0, 0)); |
| 647 | 641 | |
| 648 | 642 | /* Compute the file hierarchy. |
| 649 | 643 | */ |
| 650 | 644 | if( zCI ){ |
| @@ -695,17 +689,15 @@ | ||
| 695 | 689 | if( showDirOnly ){ |
| 696 | 690 | for(nFile=0, p=sTree.pFirst; p; p=p->pNext){ |
| 697 | 691 | if( p->pChild!=0 && p->nFullName>nD ) nFile++; |
| 698 | 692 | } |
| 699 | 693 | zObjType = "Folders"; |
| 700 | - style_submenu_element("Files","Files","%s", | |
| 701 | - url_render(&sURI,"nofiles",0,0,0)); | |
| 702 | 694 | }else{ |
| 703 | 695 | zObjType = "Files"; |
| 704 | - style_submenu_element("Folders","Folders","%s", | |
| 705 | - url_render(&sURI,"nofiles","1",0,0)); | |
| 706 | 696 | } |
| 697 | + | |
| 698 | + style_submenu_checkbox("nofiles", "Folders Only", 0); | |
| 707 | 699 | |
| 708 | 700 | if( zCI ){ |
| 709 | 701 | @ <h2>%s(zObjType) from |
| 710 | 702 | if( sqlite3_strnicmp(zCI, zUuid, (int)strlen(zCI))!=0 ){ |
| 711 | 703 | @ "%h(zCI)" |
| @@ -1032,13 +1024,11 @@ | ||
| 1032 | 1024 | } |
| 1033 | 1025 | zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1034 | 1026 | baseTime = db_double(0.0,"SELECT mtime FROM event WHERE objid=%d", rid); |
| 1035 | 1027 | zNow = db_text("", "SELECT datetime(mtime,toLocal()) FROM event" |
| 1036 | 1028 | " WHERE objid=%d", rid); |
| 1037 | - style_submenu_element("Tree-View", "Tree-View", | |
| 1038 | - "%R/tree?ci=%T&mtime=1&type=tree", | |
| 1039 | - zName); | |
| 1029 | + style_submenu_element("Tree-View", "%R/tree?ci=%T&mtime=1&type=tree", zName); | |
| 1040 | 1030 | style_header("File Ages"); |
| 1041 | 1031 | zGlob = P("glob"); |
| 1042 | 1032 | compute_fileage(rid,zGlob); |
| 1043 | 1033 | db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);"); |
| 1044 | 1034 | |
| 1045 | 1035 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -171,40 +171,37 @@ | |
| 171 | blob_zero(&dirname); |
| 172 | if( zD ){ |
| 173 | blob_append(&dirname, "in directory ", -1); |
| 174 | hyperlinked_path(zD, &dirname, zCI, "dir", ""); |
| 175 | zPrefix = mprintf("%s/", zD); |
| 176 | style_submenu_element("Top-Level", "Top-Level", "%s", |
| 177 | url_render(&sURI, "name", 0, 0, 0)); |
| 178 | }else{ |
| 179 | blob_append(&dirname, "in the top-level directory", -1); |
| 180 | zPrefix = ""; |
| 181 | } |
| 182 | if( linkTrunk ){ |
| 183 | style_submenu_element("Trunk", "Trunk", "%s", |
| 184 | url_render(&sURI, "ci", "trunk", 0, 0)); |
| 185 | } |
| 186 | if( linkTip ){ |
| 187 | style_submenu_element("Tip", "Tip", "%s", |
| 188 | url_render(&sURI, "ci", "tip", 0, 0)); |
| 189 | } |
| 190 | if( zCI ){ |
| 191 | @ <h2>Files of check-in [%z(href("vinfo?name=%!S",zUuid))%S(zUuid)</a>] |
| 192 | @ %s(blob_str(&dirname))</h2> |
| 193 | zSubdirLink = mprintf("%R/dir?ci=%!S&name=%T", zUuid, zPrefix); |
| 194 | if( nD==0 ){ |
| 195 | style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%!S", |
| 196 | zUuid); |
| 197 | } |
| 198 | }else{ |
| 199 | @ <h2>The union of all files from all check-ins |
| 200 | @ %s(blob_str(&dirname))</h2> |
| 201 | zSubdirLink = mprintf("%R/dir?name=%T", zPrefix); |
| 202 | } |
| 203 | style_submenu_element("All", "All", "%s", |
| 204 | url_render(&sURI, "ci", 0, 0, 0)); |
| 205 | style_submenu_element("Tree-View", "Tree-View", "%s", |
| 206 | url_render(&sURI, "type", "tree", 0, 0)); |
| 207 | |
| 208 | /* Compute the temporary table "localfiles" containing the names |
| 209 | ** of all files and subdirectories in the zD[] directory. |
| 210 | ** |
| @@ -616,35 +613,32 @@ | |
| 616 | blob_zero(&dirname); |
| 617 | if( zD ){ |
| 618 | blob_append(&dirname, "within directory ", -1); |
| 619 | hyperlinked_path(zD, &dirname, zCI, "tree", zREx); |
| 620 | if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE); |
| 621 | style_submenu_element("Top-Level", "Top-Level", "%s", |
| 622 | url_render(&sURI, "name", 0, 0, 0)); |
| 623 | }else{ |
| 624 | if( zRE ){ |
| 625 | blob_appendf(&dirname, "matching \"%s\"", zRE); |
| 626 | } |
| 627 | } |
| 628 | style_submenu_binary("mtime","Sort By Time","Sort By Filename", 0); |
| 629 | if( zCI ){ |
| 630 | style_submenu_element("All", "All", "%s", |
| 631 | url_render(&sURI, "ci", 0, 0, 0)); |
| 632 | if( nD==0 && !showDirOnly ){ |
| 633 | style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%s", |
| 634 | zUuid); |
| 635 | } |
| 636 | } |
| 637 | if( linkTrunk ){ |
| 638 | style_submenu_element("Trunk", "Trunk", "%s", |
| 639 | url_render(&sURI, "ci", "trunk", 0, 0)); |
| 640 | } |
| 641 | if( linkTip ){ |
| 642 | style_submenu_element("Tip", "Tip", "%s", |
| 643 | url_render(&sURI, "ci", "tip", 0, 0)); |
| 644 | } |
| 645 | style_submenu_element("Flat-View", "Flat-View", "%s", |
| 646 | url_render(&sURI, "type", "flat", 0, 0)); |
| 647 | |
| 648 | /* Compute the file hierarchy. |
| 649 | */ |
| 650 | if( zCI ){ |
| @@ -695,17 +689,15 @@ | |
| 695 | if( showDirOnly ){ |
| 696 | for(nFile=0, p=sTree.pFirst; p; p=p->pNext){ |
| 697 | if( p->pChild!=0 && p->nFullName>nD ) nFile++; |
| 698 | } |
| 699 | zObjType = "Folders"; |
| 700 | style_submenu_element("Files","Files","%s", |
| 701 | url_render(&sURI,"nofiles",0,0,0)); |
| 702 | }else{ |
| 703 | zObjType = "Files"; |
| 704 | style_submenu_element("Folders","Folders","%s", |
| 705 | url_render(&sURI,"nofiles","1",0,0)); |
| 706 | } |
| 707 | |
| 708 | if( zCI ){ |
| 709 | @ <h2>%s(zObjType) from |
| 710 | if( sqlite3_strnicmp(zCI, zUuid, (int)strlen(zCI))!=0 ){ |
| 711 | @ "%h(zCI)" |
| @@ -1032,13 +1024,11 @@ | |
| 1032 | } |
| 1033 | zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1034 | baseTime = db_double(0.0,"SELECT mtime FROM event WHERE objid=%d", rid); |
| 1035 | zNow = db_text("", "SELECT datetime(mtime,toLocal()) FROM event" |
| 1036 | " WHERE objid=%d", rid); |
| 1037 | style_submenu_element("Tree-View", "Tree-View", |
| 1038 | "%R/tree?ci=%T&mtime=1&type=tree", |
| 1039 | zName); |
| 1040 | style_header("File Ages"); |
| 1041 | zGlob = P("glob"); |
| 1042 | compute_fileage(rid,zGlob); |
| 1043 | db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);"); |
| 1044 | |
| 1045 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -171,40 +171,37 @@ | |
| 171 | blob_zero(&dirname); |
| 172 | if( zD ){ |
| 173 | blob_append(&dirname, "in directory ", -1); |
| 174 | hyperlinked_path(zD, &dirname, zCI, "dir", ""); |
| 175 | zPrefix = mprintf("%s/", zD); |
| 176 | style_submenu_element("Top-Level", "%s", |
| 177 | url_render(&sURI, "name", 0, 0, 0)); |
| 178 | }else{ |
| 179 | blob_append(&dirname, "in the top-level directory", -1); |
| 180 | zPrefix = ""; |
| 181 | } |
| 182 | if( linkTrunk ){ |
| 183 | style_submenu_element("Trunk", "%s", |
| 184 | url_render(&sURI, "ci", "trunk", 0, 0)); |
| 185 | } |
| 186 | if( linkTip ){ |
| 187 | style_submenu_element("Tip", "%s", url_render(&sURI, "ci", "tip", 0, 0)); |
| 188 | } |
| 189 | if( zCI ){ |
| 190 | @ <h2>Files of check-in [%z(href("vinfo?name=%!S",zUuid))%S(zUuid)</a>] |
| 191 | @ %s(blob_str(&dirname))</h2> |
| 192 | zSubdirLink = mprintf("%R/dir?ci=%!S&name=%T", zUuid, zPrefix); |
| 193 | if( nD==0 ){ |
| 194 | style_submenu_element("File Ages", "%R/fileage?name=%!S", zUuid); |
| 195 | } |
| 196 | }else{ |
| 197 | @ <h2>The union of all files from all check-ins |
| 198 | @ %s(blob_str(&dirname))</h2> |
| 199 | zSubdirLink = mprintf("%R/dir?name=%T", zPrefix); |
| 200 | } |
| 201 | style_submenu_element("All", "%s", url_render(&sURI, "ci", 0, 0, 0)); |
| 202 | style_submenu_element("Tree-View", "%s", |
| 203 | url_render(&sURI, "type", "tree", 0, 0)); |
| 204 | |
| 205 | /* Compute the temporary table "localfiles" containing the names |
| 206 | ** of all files and subdirectories in the zD[] directory. |
| 207 | ** |
| @@ -616,35 +613,32 @@ | |
| 613 | blob_zero(&dirname); |
| 614 | if( zD ){ |
| 615 | blob_append(&dirname, "within directory ", -1); |
| 616 | hyperlinked_path(zD, &dirname, zCI, "tree", zREx); |
| 617 | if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE); |
| 618 | style_submenu_element("Top-Level", "%s", |
| 619 | url_render(&sURI, "name", 0, 0, 0)); |
| 620 | }else{ |
| 621 | if( zRE ){ |
| 622 | blob_appendf(&dirname, "matching \"%s\"", zRE); |
| 623 | } |
| 624 | } |
| 625 | style_submenu_binary("mtime","Sort By Time","Sort By Filename", 0); |
| 626 | if( zCI ){ |
| 627 | style_submenu_element("All", "%s", url_render(&sURI, "ci", 0, 0, 0)); |
| 628 | if( nD==0 && !showDirOnly ){ |
| 629 | style_submenu_element("File Ages", "%R/fileage?name=%s", zUuid); |
| 630 | } |
| 631 | } |
| 632 | if( linkTrunk ){ |
| 633 | style_submenu_element("Trunk", "%s", |
| 634 | url_render(&sURI, "ci", "trunk", 0, 0)); |
| 635 | } |
| 636 | if( linkTip ){ |
| 637 | style_submenu_element("Tip", "%s", url_render(&sURI, "ci", "tip", 0, 0)); |
| 638 | } |
| 639 | style_submenu_element("Flat-View", "%s", |
| 640 | url_render(&sURI, "type", "flat", 0, 0)); |
| 641 | |
| 642 | /* Compute the file hierarchy. |
| 643 | */ |
| 644 | if( zCI ){ |
| @@ -695,17 +689,15 @@ | |
| 689 | if( showDirOnly ){ |
| 690 | for(nFile=0, p=sTree.pFirst; p; p=p->pNext){ |
| 691 | if( p->pChild!=0 && p->nFullName>nD ) nFile++; |
| 692 | } |
| 693 | zObjType = "Folders"; |
| 694 | }else{ |
| 695 | zObjType = "Files"; |
| 696 | } |
| 697 | |
| 698 | style_submenu_checkbox("nofiles", "Folders Only", 0); |
| 699 | |
| 700 | if( zCI ){ |
| 701 | @ <h2>%s(zObjType) from |
| 702 | if( sqlite3_strnicmp(zCI, zUuid, (int)strlen(zCI))!=0 ){ |
| 703 | @ "%h(zCI)" |
| @@ -1032,13 +1024,11 @@ | |
| 1024 | } |
| 1025 | zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1026 | baseTime = db_double(0.0,"SELECT mtime FROM event WHERE objid=%d", rid); |
| 1027 | zNow = db_text("", "SELECT datetime(mtime,toLocal()) FROM event" |
| 1028 | " WHERE objid=%d", rid); |
| 1029 | style_submenu_element("Tree-View", "%R/tree?ci=%T&mtime=1&type=tree", zName); |
| 1030 | style_header("File Ages"); |
| 1031 | zGlob = P("glob"); |
| 1032 | compute_fileage(rid,zGlob); |
| 1033 | db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);"); |
| 1034 | |
| 1035 |
+2
-2
| --- src/builtin.c | ||
| +++ src/builtin.c | ||
| @@ -33,11 +33,11 @@ | ||
| 33 | 33 | ** Return a pointer to built-in content |
| 34 | 34 | */ |
| 35 | 35 | const unsigned char *builtin_file(const char *zFilename, int *piSize){ |
| 36 | 36 | int lwr, upr, i, c; |
| 37 | 37 | lwr = 0; |
| 38 | - upr = sizeof(aBuiltinFiles)/sizeof(aBuiltinFiles[0]) - 1; | |
| 38 | + upr = count(aBuiltinFiles) - 1; | |
| 39 | 39 | while( upr>=lwr ){ |
| 40 | 40 | i = (upr+lwr)/2; |
| 41 | 41 | c = strcmp(aBuiltinFiles[i].zName,zFilename); |
| 42 | 42 | if( c<0 ){ |
| 43 | 43 | lwr = i+1; |
| @@ -60,11 +60,11 @@ | ||
| 60 | 60 | ** |
| 61 | 61 | ** List the names and sizes of all built-in resources. |
| 62 | 62 | */ |
| 63 | 63 | void test_builtin_list(void){ |
| 64 | 64 | int i; |
| 65 | - for(i=0; i<sizeof(aBuiltinFiles)/sizeof(aBuiltinFiles[0]); i++){ | |
| 65 | + for(i=0; i<count(aBuiltinFiles); i++){ | |
| 66 | 66 | fossil_print("%-30s %6d\n", aBuiltinFiles[i].zName,aBuiltinFiles[i].nByte); |
| 67 | 67 | } |
| 68 | 68 | } |
| 69 | 69 | |
| 70 | 70 | /* |
| 71 | 71 |
| --- src/builtin.c | |
| +++ src/builtin.c | |
| @@ -33,11 +33,11 @@ | |
| 33 | ** Return a pointer to built-in content |
| 34 | */ |
| 35 | const unsigned char *builtin_file(const char *zFilename, int *piSize){ |
| 36 | int lwr, upr, i, c; |
| 37 | lwr = 0; |
| 38 | upr = sizeof(aBuiltinFiles)/sizeof(aBuiltinFiles[0]) - 1; |
| 39 | while( upr>=lwr ){ |
| 40 | i = (upr+lwr)/2; |
| 41 | c = strcmp(aBuiltinFiles[i].zName,zFilename); |
| 42 | if( c<0 ){ |
| 43 | lwr = i+1; |
| @@ -60,11 +60,11 @@ | |
| 60 | ** |
| 61 | ** List the names and sizes of all built-in resources. |
| 62 | */ |
| 63 | void test_builtin_list(void){ |
| 64 | int i; |
| 65 | for(i=0; i<sizeof(aBuiltinFiles)/sizeof(aBuiltinFiles[0]); i++){ |
| 66 | fossil_print("%-30s %6d\n", aBuiltinFiles[i].zName,aBuiltinFiles[i].nByte); |
| 67 | } |
| 68 | } |
| 69 | |
| 70 | /* |
| 71 |
| --- src/builtin.c | |
| +++ src/builtin.c | |
| @@ -33,11 +33,11 @@ | |
| 33 | ** Return a pointer to built-in content |
| 34 | */ |
| 35 | const unsigned char *builtin_file(const char *zFilename, int *piSize){ |
| 36 | int lwr, upr, i, c; |
| 37 | lwr = 0; |
| 38 | upr = count(aBuiltinFiles) - 1; |
| 39 | while( upr>=lwr ){ |
| 40 | i = (upr+lwr)/2; |
| 41 | c = strcmp(aBuiltinFiles[i].zName,zFilename); |
| 42 | if( c<0 ){ |
| 43 | lwr = i+1; |
| @@ -60,11 +60,11 @@ | |
| 60 | ** |
| 61 | ** List the names and sizes of all built-in resources. |
| 62 | */ |
| 63 | void test_builtin_list(void){ |
| 64 | int i; |
| 65 | for(i=0; i<count(aBuiltinFiles); i++){ |
| 66 | fossil_print("%-30s %6d\n", aBuiltinFiles[i].zName,aBuiltinFiles[i].nByte); |
| 67 | } |
| 68 | } |
| 69 | |
| 70 | /* |
| 71 |
+4
-1
| --- src/cgi.c | ||
| +++ src/cgi.c | ||
| @@ -21,10 +21,13 @@ | ||
| 21 | 21 | ** formatting function and its cousins, and routines to encode and |
| 22 | 22 | ** decode strings in HTML or HTTP. |
| 23 | 23 | */ |
| 24 | 24 | #include "config.h" |
| 25 | 25 | #ifdef _WIN32 |
| 26 | +# if !defined(_WIN32_WINNT) | |
| 27 | +# define _WIN32_WINNT 0x0501 | |
| 28 | +# endif | |
| 26 | 29 | # include <winsock2.h> |
| 27 | 30 | # include <ws2tcpip.h> |
| 28 | 31 | #else |
| 29 | 32 | # include <sys/socket.h> |
| 30 | 33 | # include <netinet/in.h> |
| @@ -716,11 +719,11 @@ | ||
| 716 | 719 | } |
| 717 | 720 | } |
| 718 | 721 | zName = 0; |
| 719 | 722 | showBytes = 0; |
| 720 | 723 | }else{ |
| 721 | - nArg = tokenize_line(zLine, sizeof(azArg)/sizeof(azArg[0]), azArg); | |
| 724 | + nArg = tokenize_line(zLine, count(azArg), azArg); | |
| 722 | 725 | for(i=0; i<nArg; i++){ |
| 723 | 726 | int c = fossil_tolower(azArg[i][0]); |
| 724 | 727 | int n = strlen(azArg[i]); |
| 725 | 728 | if( c=='c' && sqlite3_strnicmp(azArg[i],"content-disposition:",n)==0 ){ |
| 726 | 729 | i++; |
| 727 | 730 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -21,10 +21,13 @@ | |
| 21 | ** formatting function and its cousins, and routines to encode and |
| 22 | ** decode strings in HTML or HTTP. |
| 23 | */ |
| 24 | #include "config.h" |
| 25 | #ifdef _WIN32 |
| 26 | # include <winsock2.h> |
| 27 | # include <ws2tcpip.h> |
| 28 | #else |
| 29 | # include <sys/socket.h> |
| 30 | # include <netinet/in.h> |
| @@ -716,11 +719,11 @@ | |
| 716 | } |
| 717 | } |
| 718 | zName = 0; |
| 719 | showBytes = 0; |
| 720 | }else{ |
| 721 | nArg = tokenize_line(zLine, sizeof(azArg)/sizeof(azArg[0]), azArg); |
| 722 | for(i=0; i<nArg; i++){ |
| 723 | int c = fossil_tolower(azArg[i][0]); |
| 724 | int n = strlen(azArg[i]); |
| 725 | if( c=='c' && sqlite3_strnicmp(azArg[i],"content-disposition:",n)==0 ){ |
| 726 | i++; |
| 727 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -21,10 +21,13 @@ | |
| 21 | ** formatting function and its cousins, and routines to encode and |
| 22 | ** decode strings in HTML or HTTP. |
| 23 | */ |
| 24 | #include "config.h" |
| 25 | #ifdef _WIN32 |
| 26 | # if !defined(_WIN32_WINNT) |
| 27 | # define _WIN32_WINNT 0x0501 |
| 28 | # endif |
| 29 | # include <winsock2.h> |
| 30 | # include <ws2tcpip.h> |
| 31 | #else |
| 32 | # include <sys/socket.h> |
| 33 | # include <netinet/in.h> |
| @@ -716,11 +719,11 @@ | |
| 719 | } |
| 720 | } |
| 721 | zName = 0; |
| 722 | showBytes = 0; |
| 723 | }else{ |
| 724 | nArg = tokenize_line(zLine, count(azArg), azArg); |
| 725 | for(i=0; i<nArg; i++){ |
| 726 | int c = fossil_tolower(azArg[i][0]); |
| 727 | int n = strlen(azArg[i]); |
| 728 | if( c=='c' && sqlite3_strnicmp(azArg[i],"content-disposition:",n)==0 ){ |
| 729 | i++; |
| 730 |
+1
-1
| --- src/checkin.c | ||
| +++ src/checkin.c | ||
| @@ -2282,11 +2282,11 @@ | ||
| 2282 | 2282 | fossil_fatal("trouble committing manifest: %s", g.zErrMsg); |
| 2283 | 2283 | } |
| 2284 | 2284 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nvid); |
| 2285 | 2285 | if( manifest_crosslink(nvid, &manifest, |
| 2286 | 2286 | dryRunFlag ? MC_NONE : MC_PERMIT_HOOKS)==0 ){ |
| 2287 | - fossil_fatal("%s\n", g.zErrMsg); | |
| 2287 | + fossil_fatal("%s", g.zErrMsg); | |
| 2288 | 2288 | } |
| 2289 | 2289 | assert( blob_is_reset(&manifest) ); |
| 2290 | 2290 | content_deltify(vid, nvid, 0); |
| 2291 | 2291 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid); |
| 2292 | 2292 | |
| 2293 | 2293 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -2282,11 +2282,11 @@ | |
| 2282 | fossil_fatal("trouble committing manifest: %s", g.zErrMsg); |
| 2283 | } |
| 2284 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nvid); |
| 2285 | if( manifest_crosslink(nvid, &manifest, |
| 2286 | dryRunFlag ? MC_NONE : MC_PERMIT_HOOKS)==0 ){ |
| 2287 | fossil_fatal("%s\n", g.zErrMsg); |
| 2288 | } |
| 2289 | assert( blob_is_reset(&manifest) ); |
| 2290 | content_deltify(vid, nvid, 0); |
| 2291 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid); |
| 2292 | |
| 2293 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -2282,11 +2282,11 @@ | |
| 2282 | fossil_fatal("trouble committing manifest: %s", g.zErrMsg); |
| 2283 | } |
| 2284 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nvid); |
| 2285 | if( manifest_crosslink(nvid, &manifest, |
| 2286 | dryRunFlag ? MC_NONE : MC_PERMIT_HOOKS)==0 ){ |
| 2287 | fossil_fatal("%s", g.zErrMsg); |
| 2288 | } |
| 2289 | assert( blob_is_reset(&manifest) ); |
| 2290 | content_deltify(vid, nvid, 0); |
| 2291 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid); |
| 2292 | |
| 2293 |
+1
-1
| --- src/checkin.c | ||
| +++ src/checkin.c | ||
| @@ -2282,11 +2282,11 @@ | ||
| 2282 | 2282 | fossil_fatal("trouble committing manifest: %s", g.zErrMsg); |
| 2283 | 2283 | } |
| 2284 | 2284 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nvid); |
| 2285 | 2285 | if( manifest_crosslink(nvid, &manifest, |
| 2286 | 2286 | dryRunFlag ? MC_NONE : MC_PERMIT_HOOKS)==0 ){ |
| 2287 | - fossil_fatal("%s\n", g.zErrMsg); | |
| 2287 | + fossil_fatal("%s", g.zErrMsg); | |
| 2288 | 2288 | } |
| 2289 | 2289 | assert( blob_is_reset(&manifest) ); |
| 2290 | 2290 | content_deltify(vid, nvid, 0); |
| 2291 | 2291 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid); |
| 2292 | 2292 | |
| 2293 | 2293 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -2282,11 +2282,11 @@ | |
| 2282 | fossil_fatal("trouble committing manifest: %s", g.zErrMsg); |
| 2283 | } |
| 2284 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nvid); |
| 2285 | if( manifest_crosslink(nvid, &manifest, |
| 2286 | dryRunFlag ? MC_NONE : MC_PERMIT_HOOKS)==0 ){ |
| 2287 | fossil_fatal("%s\n", g.zErrMsg); |
| 2288 | } |
| 2289 | assert( blob_is_reset(&manifest) ); |
| 2290 | content_deltify(vid, nvid, 0); |
| 2291 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid); |
| 2292 | |
| 2293 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -2282,11 +2282,11 @@ | |
| 2282 | fossil_fatal("trouble committing manifest: %s", g.zErrMsg); |
| 2283 | } |
| 2284 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nvid); |
| 2285 | if( manifest_crosslink(nvid, &manifest, |
| 2286 | dryRunFlag ? MC_NONE : MC_PERMIT_HOOKS)==0 ){ |
| 2287 | fossil_fatal("%s", g.zErrMsg); |
| 2288 | } |
| 2289 | assert( blob_is_reset(&manifest) ); |
| 2290 | content_deltify(vid, nvid, 0); |
| 2291 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid); |
| 2292 | |
| 2293 |
M
src/db.c
+166
-15
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -27,11 +27,15 @@ | ||
| 27 | 27 | ** (3) A local checkout database named "_FOSSIL_" or ".fslckout" |
| 28 | 28 | ** and located at the root of the local copy of the source tree. |
| 29 | 29 | ** |
| 30 | 30 | */ |
| 31 | 31 | #include "config.h" |
| 32 | -#if ! defined(_WIN32) | |
| 32 | +#if defined(_WIN32) | |
| 33 | +# if USE_SEE | |
| 34 | +# include <windows.h> | |
| 35 | +# endif | |
| 36 | +#else | |
| 33 | 37 | # include <pwd.h> |
| 34 | 38 | #endif |
| 35 | 39 | #include <sqlite3.h> |
| 36 | 40 | #include <sys/types.h> |
| 37 | 41 | #include <sys/stat.h> |
| @@ -870,31 +874,170 @@ | ||
| 870 | 874 | db_tolocal_function, 0, 0); |
| 871 | 875 | sqlite3_create_function(db, "fromLocal", 0, SQLITE_UTF8, 0, |
| 872 | 876 | db_fromlocal_function, 0, 0); |
| 873 | 877 | } |
| 874 | 878 | |
| 879 | +#if USE_SEE | |
| 880 | +/* | |
| 881 | +** This is a pointer to the saved database encryption key string. | |
| 882 | +*/ | |
| 883 | +static char *zSavedKey = 0; | |
| 884 | + | |
| 885 | +/* | |
| 886 | +** This is the size of the saved database encryption key, in bytes. | |
| 887 | +*/ | |
| 888 | +size_t savedKeySize = 0; | |
| 889 | + | |
| 890 | +/* | |
| 891 | +** This function returns the saved database encryption key -OR- zero if | |
| 892 | +** no database encryption key is saved. | |
| 893 | +*/ | |
| 894 | +char *db_get_saved_encryption_key(){ | |
| 895 | + return zSavedKey; | |
| 896 | +} | |
| 897 | + | |
| 898 | +/* | |
| 899 | +** This function returns the size of the saved database encryption key | |
| 900 | +** -OR- zero if no database encryption key is saved. | |
| 901 | +*/ | |
| 902 | +size_t db_get_saved_encryption_key_size(){ | |
| 903 | + return savedKeySize; | |
| 904 | +} | |
| 905 | + | |
| 906 | +/* | |
| 907 | +** This function arranges for the database encryption key to be securely | |
| 908 | +** saved in non-pagable memory (on platforms where this is possible). | |
| 909 | +*/ | |
| 910 | +static void db_save_encryption_key( | |
| 911 | + Blob *pKey | |
| 912 | +){ | |
| 913 | + void *p = NULL; | |
| 914 | + size_t n = 0; | |
| 915 | + size_t pageSize = 0; | |
| 916 | + size_t blobSize = 0; | |
| 917 | + | |
| 918 | + blobSize = blob_size(pKey); | |
| 919 | + if( blobSize==0 ) return; | |
| 920 | + fossil_get_page_size(&pageSize); | |
| 921 | + assert( pageSize>0 ); | |
| 922 | + if( blobSize>pageSize ){ | |
| 923 | + fossil_fatal("key blob too large: %u versus %u", blobSize, pageSize); | |
| 924 | + } | |
| 925 | + p = fossil_secure_alloc_page(&n); | |
| 926 | + assert( p!=NULL ); | |
| 927 | + assert( n==pageSize ); | |
| 928 | + assert( n>=blobSize ); | |
| 929 | + memcpy(p, blob_str(pKey), blobSize); | |
| 930 | + zSavedKey = p; | |
| 931 | + savedKeySize = n; | |
| 932 | +} | |
| 933 | + | |
| 934 | +/* | |
| 935 | +** This function arranges for the saved database encryption key to be | |
| 936 | +** securely zeroed, unlocked (if necessary), and freed. | |
| 937 | +*/ | |
| 938 | +void db_unsave_encryption_key(){ | |
| 939 | + fossil_secure_free_page(zSavedKey, savedKeySize); | |
| 940 | + zSavedKey = NULL; | |
| 941 | + savedKeySize = 0; | |
| 942 | +} | |
| 943 | + | |
| 944 | +/* | |
| 945 | +** This function sets the saved database encryption key to the specified | |
| 946 | +** string value, allocating or freeing the underlying memory if needed. | |
| 947 | +*/ | |
| 948 | +void db_set_saved_encryption_key( | |
| 949 | + Blob *pKey | |
| 950 | +){ | |
| 951 | + if( zSavedKey!=NULL ){ | |
| 952 | + size_t blobSize = blob_size(pKey); | |
| 953 | + if( blobSize==0 ){ | |
| 954 | + db_unsave_encryption_key(); | |
| 955 | + }else{ | |
| 956 | + if( blobSize>savedKeySize ){ | |
| 957 | + fossil_fatal("key blob too large: %u versus %u", | |
| 958 | + blobSize, savedKeySize); | |
| 959 | + } | |
| 960 | + fossil_secure_zero(zSavedKey, savedKeySize); | |
| 961 | + memcpy(zSavedKey, blob_str(pKey), blobSize); | |
| 962 | + } | |
| 963 | + }else{ | |
| 964 | + db_save_encryption_key(pKey); | |
| 965 | + } | |
| 966 | +} | |
| 967 | + | |
| 968 | +#if defined(_WIN32) | |
| 969 | +/* | |
| 970 | +** This function sets the saved database encryption key to one that gets | |
| 971 | +** read from the specified Fossil parent process. This is only necessary | |
| 972 | +** (or functional) on Windows. | |
| 973 | +*/ | |
| 974 | +void db_read_saved_encryption_key_from_process( | |
| 975 | + DWORD processId, /* Identifier for Fossil parent process. */ | |
| 976 | + LPVOID pAddress, /* Pointer to saved key buffer in the parent process. */ | |
| 977 | + SIZE_T nSize /* Size of saved key buffer in the parent process. */ | |
| 978 | +){ | |
| 979 | + void *p = NULL; | |
| 980 | + size_t n = 0; | |
| 981 | + size_t pageSize = 0; | |
| 982 | + HANDLE hProcess = NULL; | |
| 983 | + | |
| 984 | + fossil_get_page_size(&pageSize); | |
| 985 | + assert( pageSize>0 ); | |
| 986 | + if( nSize>pageSize ){ | |
| 987 | + fossil_fatal("key too large: %u versus %u", nSize, pageSize); | |
| 988 | + } | |
| 989 | + p = fossil_secure_alloc_page(&n); | |
| 990 | + assert( p!=NULL ); | |
| 991 | + assert( n==pageSize ); | |
| 992 | + assert( n>=nSize ); | |
| 993 | + hProcess = OpenProcess(PROCESS_VM_READ, FALSE, processId); | |
| 994 | + if( hProcess!=NULL ){ | |
| 995 | + SIZE_T nRead = 0; | |
| 996 | + if( ReadProcessMemory(hProcess, pAddress, p, nSize, &nRead) ){ | |
| 997 | + CloseHandle(hProcess); | |
| 998 | + if( nRead==nSize ){ | |
| 999 | + db_unsave_encryption_key(); | |
| 1000 | + zSavedKey = p; | |
| 1001 | + savedKeySize = n; | |
| 1002 | + }else{ | |
| 1003 | + fossil_fatal("bad size read, %u out of %u bytes at %p from pid %lu", | |
| 1004 | + nRead, nSize, pAddress, processId); | |
| 1005 | + } | |
| 1006 | + }else{ | |
| 1007 | + CloseHandle(hProcess); | |
| 1008 | + fossil_fatal("failed read, %u bytes at %p from pid %lu: %lu", nSize, | |
| 1009 | + pAddress, processId, GetLastError()); | |
| 1010 | + } | |
| 1011 | + }else{ | |
| 1012 | + fossil_fatal("failed to open pid %lu: %lu", processId, GetLastError()); | |
| 1013 | + } | |
| 1014 | +} | |
| 1015 | +#endif /* defined(_WIN32) */ | |
| 1016 | +#endif /* USE_SEE */ | |
| 1017 | + | |
| 875 | 1018 | /* |
| 876 | 1019 | ** If the database file zDbFile has a name that suggests that it is |
| 877 | -** encrypted, then prompt for the encryption key and return it in the | |
| 878 | -** blob *pKey. Or, if the encryption key has previously been requested, | |
| 879 | -** just return a copy of the previous result. | |
| 1020 | +** encrypted, then prompt for the database encryption key and return it | |
| 1021 | +** in the blob *pKey. Or, if the encryption key has previously been | |
| 1022 | +** requested, just return a copy of the previous result. The blob in | |
| 1023 | +** *pKey must be initialized. | |
| 880 | 1024 | */ |
| 881 | -static void db_encryption_key( | |
| 1025 | +static void db_maybe_obtain_encryption_key( | |
| 882 | 1026 | const char *zDbFile, /* Name of the database file */ |
| 883 | 1027 | Blob *pKey /* Put the encryption key here */ |
| 884 | 1028 | ){ |
| 885 | - blob_init(pKey, 0, 0); | |
| 886 | 1029 | #if USE_SEE |
| 887 | 1030 | if( sqlite3_strglob("*.efossil", zDbFile)==0 ){ |
| 888 | - static char *zSavedKey = 0; | |
| 889 | - if( zSavedKey ){ | |
| 890 | - blob_set(pKey, zSavedKey); | |
| 1031 | + char *zKey = db_get_saved_encryption_key(); | |
| 1032 | + if( zKey ){ | |
| 1033 | + blob_set(pKey, zKey); | |
| 891 | 1034 | }else{ |
| 892 | 1035 | char *zPrompt = mprintf("\rencryption key for '%s': ", zDbFile); |
| 893 | 1036 | prompt_for_password(zPrompt, pKey, 0); |
| 894 | 1037 | fossil_free(zPrompt); |
| 895 | - zSavedKey = fossil_strdup(blob_str(pKey)); | |
| 1038 | + db_set_saved_encryption_key(pKey); | |
| 896 | 1039 | } |
| 897 | 1040 | } |
| 898 | 1041 | #endif |
| 899 | 1042 | } |
| 900 | 1043 | |
| @@ -915,14 +1058,16 @@ | ||
| 915 | 1058 | g.zVfsName |
| 916 | 1059 | ); |
| 917 | 1060 | if( rc!=SQLITE_OK ){ |
| 918 | 1061 | db_err("[%s]: %s", zDbName, sqlite3_errmsg(db)); |
| 919 | 1062 | } |
| 920 | - db_encryption_key(zDbName, &key); | |
| 1063 | + blob_init(&key, 0, 0); | |
| 1064 | + db_maybe_obtain_encryption_key(zDbName, &key); | |
| 921 | 1065 | if( blob_size(&key)>0 ){ |
| 922 | 1066 | char *zCmd = sqlite3_mprintf("PRAGMA key(%Q)", blob_str(&key)); |
| 923 | 1067 | sqlite3_exec(db, zCmd, 0, 0, 0); |
| 1068 | + fossil_secure_zero(zCmd, strlen(zCmd)); | |
| 924 | 1069 | sqlite3_free(zCmd); |
| 925 | 1070 | } |
| 926 | 1071 | blob_reset(&key); |
| 927 | 1072 | sqlite3_busy_timeout(db, 5000); |
| 928 | 1073 | sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */ |
| @@ -955,14 +1100,19 @@ | ||
| 955 | 1100 | /* |
| 956 | 1101 | ** zDbName is the name of a database file. Attach zDbName using |
| 957 | 1102 | ** the name zLabel. |
| 958 | 1103 | */ |
| 959 | 1104 | void db_attach(const char *zDbName, const char *zLabel){ |
| 1105 | + char *zCmd; | |
| 960 | 1106 | Blob key; |
| 961 | - db_encryption_key(zDbName, &key); | |
| 962 | - db_multi_exec("ATTACH DATABASE %Q AS %Q KEY %Q", | |
| 963 | - zDbName, zLabel, blob_str(&key)); | |
| 1107 | + blob_init(&key, 0, 0); | |
| 1108 | + db_maybe_obtain_encryption_key(zDbName, &key); | |
| 1109 | + zCmd = sqlite3_mprintf("ATTACH DATABASE %Q AS %Q KEY %Q", | |
| 1110 | + zDbName, zLabel, blob_str(&key)); | |
| 1111 | + db_multi_exec(zCmd /*works-like:""*/); | |
| 1112 | + fossil_secure_zero(zCmd, strlen(zCmd)); | |
| 1113 | + sqlite3_free(zCmd); | |
| 964 | 1114 | blob_reset(&key); |
| 965 | 1115 | } |
| 966 | 1116 | |
| 967 | 1117 | /* |
| 968 | 1118 | ** Change the schema name of the "main" database to zLabel. |
| @@ -1192,10 +1342,11 @@ | ||
| 1192 | 1342 | } |
| 1193 | 1343 | if( db_local_table_exists_but_lacks_column("undo_vfile", "islink") ){ |
| 1194 | 1344 | db_multi_exec("ALTER TABLE undo_vfile ADD COLUMN islink BOOL DEFAULT 0"); |
| 1195 | 1345 | } |
| 1196 | 1346 | } |
| 1347 | + fossil_free(zVFileDef); | |
| 1197 | 1348 | return 1; |
| 1198 | 1349 | } |
| 1199 | 1350 | |
| 1200 | 1351 | /* |
| 1201 | 1352 | ** Locate the root directory of the local repository tree. The root |
| @@ -2648,11 +2799,11 @@ | ||
| 2648 | 2799 | */ |
| 2649 | 2800 | const Setting *db_find_setting(const char *zName, int allowPrefix){ |
| 2650 | 2801 | int lwr, mid, upr, c; |
| 2651 | 2802 | int n = (int)strlen(zName) + !allowPrefix; |
| 2652 | 2803 | lwr = 0; |
| 2653 | - upr = ArraySize(aSetting)-2; | |
| 2804 | + upr = count(aSetting)-2; | |
| 2654 | 2805 | while( upr>=lwr ){ |
| 2655 | 2806 | mid = (upr+lwr)/2; |
| 2656 | 2807 | c = fossil_strncmp(zName, aSetting[mid].name, n); |
| 2657 | 2808 | if( c<0 ){ |
| 2658 | 2809 | upr = mid - 1; |
| 2659 | 2810 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -27,11 +27,15 @@ | |
| 27 | ** (3) A local checkout database named "_FOSSIL_" or ".fslckout" |
| 28 | ** and located at the root of the local copy of the source tree. |
| 29 | ** |
| 30 | */ |
| 31 | #include "config.h" |
| 32 | #if ! defined(_WIN32) |
| 33 | # include <pwd.h> |
| 34 | #endif |
| 35 | #include <sqlite3.h> |
| 36 | #include <sys/types.h> |
| 37 | #include <sys/stat.h> |
| @@ -870,31 +874,170 @@ | |
| 870 | db_tolocal_function, 0, 0); |
| 871 | sqlite3_create_function(db, "fromLocal", 0, SQLITE_UTF8, 0, |
| 872 | db_fromlocal_function, 0, 0); |
| 873 | } |
| 874 | |
| 875 | /* |
| 876 | ** If the database file zDbFile has a name that suggests that it is |
| 877 | ** encrypted, then prompt for the encryption key and return it in the |
| 878 | ** blob *pKey. Or, if the encryption key has previously been requested, |
| 879 | ** just return a copy of the previous result. |
| 880 | */ |
| 881 | static void db_encryption_key( |
| 882 | const char *zDbFile, /* Name of the database file */ |
| 883 | Blob *pKey /* Put the encryption key here */ |
| 884 | ){ |
| 885 | blob_init(pKey, 0, 0); |
| 886 | #if USE_SEE |
| 887 | if( sqlite3_strglob("*.efossil", zDbFile)==0 ){ |
| 888 | static char *zSavedKey = 0; |
| 889 | if( zSavedKey ){ |
| 890 | blob_set(pKey, zSavedKey); |
| 891 | }else{ |
| 892 | char *zPrompt = mprintf("\rencryption key for '%s': ", zDbFile); |
| 893 | prompt_for_password(zPrompt, pKey, 0); |
| 894 | fossil_free(zPrompt); |
| 895 | zSavedKey = fossil_strdup(blob_str(pKey)); |
| 896 | } |
| 897 | } |
| 898 | #endif |
| 899 | } |
| 900 | |
| @@ -915,14 +1058,16 @@ | |
| 915 | g.zVfsName |
| 916 | ); |
| 917 | if( rc!=SQLITE_OK ){ |
| 918 | db_err("[%s]: %s", zDbName, sqlite3_errmsg(db)); |
| 919 | } |
| 920 | db_encryption_key(zDbName, &key); |
| 921 | if( blob_size(&key)>0 ){ |
| 922 | char *zCmd = sqlite3_mprintf("PRAGMA key(%Q)", blob_str(&key)); |
| 923 | sqlite3_exec(db, zCmd, 0, 0, 0); |
| 924 | sqlite3_free(zCmd); |
| 925 | } |
| 926 | blob_reset(&key); |
| 927 | sqlite3_busy_timeout(db, 5000); |
| 928 | sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */ |
| @@ -955,14 +1100,19 @@ | |
| 955 | /* |
| 956 | ** zDbName is the name of a database file. Attach zDbName using |
| 957 | ** the name zLabel. |
| 958 | */ |
| 959 | void db_attach(const char *zDbName, const char *zLabel){ |
| 960 | Blob key; |
| 961 | db_encryption_key(zDbName, &key); |
| 962 | db_multi_exec("ATTACH DATABASE %Q AS %Q KEY %Q", |
| 963 | zDbName, zLabel, blob_str(&key)); |
| 964 | blob_reset(&key); |
| 965 | } |
| 966 | |
| 967 | /* |
| 968 | ** Change the schema name of the "main" database to zLabel. |
| @@ -1192,10 +1342,11 @@ | |
| 1192 | } |
| 1193 | if( db_local_table_exists_but_lacks_column("undo_vfile", "islink") ){ |
| 1194 | db_multi_exec("ALTER TABLE undo_vfile ADD COLUMN islink BOOL DEFAULT 0"); |
| 1195 | } |
| 1196 | } |
| 1197 | return 1; |
| 1198 | } |
| 1199 | |
| 1200 | /* |
| 1201 | ** Locate the root directory of the local repository tree. The root |
| @@ -2648,11 +2799,11 @@ | |
| 2648 | */ |
| 2649 | const Setting *db_find_setting(const char *zName, int allowPrefix){ |
| 2650 | int lwr, mid, upr, c; |
| 2651 | int n = (int)strlen(zName) + !allowPrefix; |
| 2652 | lwr = 0; |
| 2653 | upr = ArraySize(aSetting)-2; |
| 2654 | while( upr>=lwr ){ |
| 2655 | mid = (upr+lwr)/2; |
| 2656 | c = fossil_strncmp(zName, aSetting[mid].name, n); |
| 2657 | if( c<0 ){ |
| 2658 | upr = mid - 1; |
| 2659 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -27,11 +27,15 @@ | |
| 27 | ** (3) A local checkout database named "_FOSSIL_" or ".fslckout" |
| 28 | ** and located at the root of the local copy of the source tree. |
| 29 | ** |
| 30 | */ |
| 31 | #include "config.h" |
| 32 | #if defined(_WIN32) |
| 33 | # if USE_SEE |
| 34 | # include <windows.h> |
| 35 | # endif |
| 36 | #else |
| 37 | # include <pwd.h> |
| 38 | #endif |
| 39 | #include <sqlite3.h> |
| 40 | #include <sys/types.h> |
| 41 | #include <sys/stat.h> |
| @@ -870,31 +874,170 @@ | |
| 874 | db_tolocal_function, 0, 0); |
| 875 | sqlite3_create_function(db, "fromLocal", 0, SQLITE_UTF8, 0, |
| 876 | db_fromlocal_function, 0, 0); |
| 877 | } |
| 878 | |
| 879 | #if USE_SEE |
| 880 | /* |
| 881 | ** This is a pointer to the saved database encryption key string. |
| 882 | */ |
| 883 | static char *zSavedKey = 0; |
| 884 | |
| 885 | /* |
| 886 | ** This is the size of the saved database encryption key, in bytes. |
| 887 | */ |
| 888 | size_t savedKeySize = 0; |
| 889 | |
| 890 | /* |
| 891 | ** This function returns the saved database encryption key -OR- zero if |
| 892 | ** no database encryption key is saved. |
| 893 | */ |
| 894 | char *db_get_saved_encryption_key(){ |
| 895 | return zSavedKey; |
| 896 | } |
| 897 | |
| 898 | /* |
| 899 | ** This function returns the size of the saved database encryption key |
| 900 | ** -OR- zero if no database encryption key is saved. |
| 901 | */ |
| 902 | size_t db_get_saved_encryption_key_size(){ |
| 903 | return savedKeySize; |
| 904 | } |
| 905 | |
| 906 | /* |
| 907 | ** This function arranges for the database encryption key to be securely |
| 908 | ** saved in non-pagable memory (on platforms where this is possible). |
| 909 | */ |
| 910 | static void db_save_encryption_key( |
| 911 | Blob *pKey |
| 912 | ){ |
| 913 | void *p = NULL; |
| 914 | size_t n = 0; |
| 915 | size_t pageSize = 0; |
| 916 | size_t blobSize = 0; |
| 917 | |
| 918 | blobSize = blob_size(pKey); |
| 919 | if( blobSize==0 ) return; |
| 920 | fossil_get_page_size(&pageSize); |
| 921 | assert( pageSize>0 ); |
| 922 | if( blobSize>pageSize ){ |
| 923 | fossil_fatal("key blob too large: %u versus %u", blobSize, pageSize); |
| 924 | } |
| 925 | p = fossil_secure_alloc_page(&n); |
| 926 | assert( p!=NULL ); |
| 927 | assert( n==pageSize ); |
| 928 | assert( n>=blobSize ); |
| 929 | memcpy(p, blob_str(pKey), blobSize); |
| 930 | zSavedKey = p; |
| 931 | savedKeySize = n; |
| 932 | } |
| 933 | |
| 934 | /* |
| 935 | ** This function arranges for the saved database encryption key to be |
| 936 | ** securely zeroed, unlocked (if necessary), and freed. |
| 937 | */ |
| 938 | void db_unsave_encryption_key(){ |
| 939 | fossil_secure_free_page(zSavedKey, savedKeySize); |
| 940 | zSavedKey = NULL; |
| 941 | savedKeySize = 0; |
| 942 | } |
| 943 | |
| 944 | /* |
| 945 | ** This function sets the saved database encryption key to the specified |
| 946 | ** string value, allocating or freeing the underlying memory if needed. |
| 947 | */ |
| 948 | void db_set_saved_encryption_key( |
| 949 | Blob *pKey |
| 950 | ){ |
| 951 | if( zSavedKey!=NULL ){ |
| 952 | size_t blobSize = blob_size(pKey); |
| 953 | if( blobSize==0 ){ |
| 954 | db_unsave_encryption_key(); |
| 955 | }else{ |
| 956 | if( blobSize>savedKeySize ){ |
| 957 | fossil_fatal("key blob too large: %u versus %u", |
| 958 | blobSize, savedKeySize); |
| 959 | } |
| 960 | fossil_secure_zero(zSavedKey, savedKeySize); |
| 961 | memcpy(zSavedKey, blob_str(pKey), blobSize); |
| 962 | } |
| 963 | }else{ |
| 964 | db_save_encryption_key(pKey); |
| 965 | } |
| 966 | } |
| 967 | |
| 968 | #if defined(_WIN32) |
| 969 | /* |
| 970 | ** This function sets the saved database encryption key to one that gets |
| 971 | ** read from the specified Fossil parent process. This is only necessary |
| 972 | ** (or functional) on Windows. |
| 973 | */ |
| 974 | void db_read_saved_encryption_key_from_process( |
| 975 | DWORD processId, /* Identifier for Fossil parent process. */ |
| 976 | LPVOID pAddress, /* Pointer to saved key buffer in the parent process. */ |
| 977 | SIZE_T nSize /* Size of saved key buffer in the parent process. */ |
| 978 | ){ |
| 979 | void *p = NULL; |
| 980 | size_t n = 0; |
| 981 | size_t pageSize = 0; |
| 982 | HANDLE hProcess = NULL; |
| 983 | |
| 984 | fossil_get_page_size(&pageSize); |
| 985 | assert( pageSize>0 ); |
| 986 | if( nSize>pageSize ){ |
| 987 | fossil_fatal("key too large: %u versus %u", nSize, pageSize); |
| 988 | } |
| 989 | p = fossil_secure_alloc_page(&n); |
| 990 | assert( p!=NULL ); |
| 991 | assert( n==pageSize ); |
| 992 | assert( n>=nSize ); |
| 993 | hProcess = OpenProcess(PROCESS_VM_READ, FALSE, processId); |
| 994 | if( hProcess!=NULL ){ |
| 995 | SIZE_T nRead = 0; |
| 996 | if( ReadProcessMemory(hProcess, pAddress, p, nSize, &nRead) ){ |
| 997 | CloseHandle(hProcess); |
| 998 | if( nRead==nSize ){ |
| 999 | db_unsave_encryption_key(); |
| 1000 | zSavedKey = p; |
| 1001 | savedKeySize = n; |
| 1002 | }else{ |
| 1003 | fossil_fatal("bad size read, %u out of %u bytes at %p from pid %lu", |
| 1004 | nRead, nSize, pAddress, processId); |
| 1005 | } |
| 1006 | }else{ |
| 1007 | CloseHandle(hProcess); |
| 1008 | fossil_fatal("failed read, %u bytes at %p from pid %lu: %lu", nSize, |
| 1009 | pAddress, processId, GetLastError()); |
| 1010 | } |
| 1011 | }else{ |
| 1012 | fossil_fatal("failed to open pid %lu: %lu", processId, GetLastError()); |
| 1013 | } |
| 1014 | } |
| 1015 | #endif /* defined(_WIN32) */ |
| 1016 | #endif /* USE_SEE */ |
| 1017 | |
| 1018 | /* |
| 1019 | ** If the database file zDbFile has a name that suggests that it is |
| 1020 | ** encrypted, then prompt for the database encryption key and return it |
| 1021 | ** in the blob *pKey. Or, if the encryption key has previously been |
| 1022 | ** requested, just return a copy of the previous result. The blob in |
| 1023 | ** *pKey must be initialized. |
| 1024 | */ |
| 1025 | static void db_maybe_obtain_encryption_key( |
| 1026 | const char *zDbFile, /* Name of the database file */ |
| 1027 | Blob *pKey /* Put the encryption key here */ |
| 1028 | ){ |
| 1029 | #if USE_SEE |
| 1030 | if( sqlite3_strglob("*.efossil", zDbFile)==0 ){ |
| 1031 | char *zKey = db_get_saved_encryption_key(); |
| 1032 | if( zKey ){ |
| 1033 | blob_set(pKey, zKey); |
| 1034 | }else{ |
| 1035 | char *zPrompt = mprintf("\rencryption key for '%s': ", zDbFile); |
| 1036 | prompt_for_password(zPrompt, pKey, 0); |
| 1037 | fossil_free(zPrompt); |
| 1038 | db_set_saved_encryption_key(pKey); |
| 1039 | } |
| 1040 | } |
| 1041 | #endif |
| 1042 | } |
| 1043 | |
| @@ -915,14 +1058,16 @@ | |
| 1058 | g.zVfsName |
| 1059 | ); |
| 1060 | if( rc!=SQLITE_OK ){ |
| 1061 | db_err("[%s]: %s", zDbName, sqlite3_errmsg(db)); |
| 1062 | } |
| 1063 | blob_init(&key, 0, 0); |
| 1064 | db_maybe_obtain_encryption_key(zDbName, &key); |
| 1065 | if( blob_size(&key)>0 ){ |
| 1066 | char *zCmd = sqlite3_mprintf("PRAGMA key(%Q)", blob_str(&key)); |
| 1067 | sqlite3_exec(db, zCmd, 0, 0, 0); |
| 1068 | fossil_secure_zero(zCmd, strlen(zCmd)); |
| 1069 | sqlite3_free(zCmd); |
| 1070 | } |
| 1071 | blob_reset(&key); |
| 1072 | sqlite3_busy_timeout(db, 5000); |
| 1073 | sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */ |
| @@ -955,14 +1100,19 @@ | |
| 1100 | /* |
| 1101 | ** zDbName is the name of a database file. Attach zDbName using |
| 1102 | ** the name zLabel. |
| 1103 | */ |
| 1104 | void db_attach(const char *zDbName, const char *zLabel){ |
| 1105 | char *zCmd; |
| 1106 | Blob key; |
| 1107 | blob_init(&key, 0, 0); |
| 1108 | db_maybe_obtain_encryption_key(zDbName, &key); |
| 1109 | zCmd = sqlite3_mprintf("ATTACH DATABASE %Q AS %Q KEY %Q", |
| 1110 | zDbName, zLabel, blob_str(&key)); |
| 1111 | db_multi_exec(zCmd /*works-like:""*/); |
| 1112 | fossil_secure_zero(zCmd, strlen(zCmd)); |
| 1113 | sqlite3_free(zCmd); |
| 1114 | blob_reset(&key); |
| 1115 | } |
| 1116 | |
| 1117 | /* |
| 1118 | ** Change the schema name of the "main" database to zLabel. |
| @@ -1192,10 +1342,11 @@ | |
| 1342 | } |
| 1343 | if( db_local_table_exists_but_lacks_column("undo_vfile", "islink") ){ |
| 1344 | db_multi_exec("ALTER TABLE undo_vfile ADD COLUMN islink BOOL DEFAULT 0"); |
| 1345 | } |
| 1346 | } |
| 1347 | fossil_free(zVFileDef); |
| 1348 | return 1; |
| 1349 | } |
| 1350 | |
| 1351 | /* |
| 1352 | ** Locate the root directory of the local repository tree. The root |
| @@ -2648,11 +2799,11 @@ | |
| 2799 | */ |
| 2800 | const Setting *db_find_setting(const char *zName, int allowPrefix){ |
| 2801 | int lwr, mid, upr, c; |
| 2802 | int n = (int)strlen(zName) + !allowPrefix; |
| 2803 | lwr = 0; |
| 2804 | upr = count(aSetting)-2; |
| 2805 | while( upr>=lwr ){ |
| 2806 | mid = (upr+lwr)/2; |
| 2807 | c = fossil_strncmp(zName, aSetting[mid].name, n); |
| 2808 | if( c<0 ){ |
| 2809 | upr = mid - 1; |
| 2810 |
+1
-2
| --- src/delta.c | ||
| +++ src/delta.c | ||
| @@ -377,13 +377,12 @@ | ||
| 377 | 377 | /* Compute the hash table used to locate matching sections in the |
| 378 | 378 | ** source file. |
| 379 | 379 | */ |
| 380 | 380 | nHash = lenSrc/NHASH; |
| 381 | 381 | collide = fossil_malloc( nHash*2*sizeof(int) ); |
| 382 | + memset(collide, -1, nHash*2*sizeof(int)); | |
| 382 | 383 | landmark = &collide[nHash]; |
| 383 | - memset(landmark, -1, nHash*sizeof(int)); | |
| 384 | - memset(collide, -1, nHash*sizeof(int)); | |
| 385 | 384 | for(i=0; i<lenSrc-NHASH; i+=NHASH){ |
| 386 | 385 | int hv = hash_once(&zSrc[i]) % nHash; |
| 387 | 386 | collide[i/NHASH] = landmark[hv]; |
| 388 | 387 | landmark[hv] = i/NHASH; |
| 389 | 388 | } |
| 390 | 389 |
| --- src/delta.c | |
| +++ src/delta.c | |
| @@ -377,13 +377,12 @@ | |
| 377 | /* Compute the hash table used to locate matching sections in the |
| 378 | ** source file. |
| 379 | */ |
| 380 | nHash = lenSrc/NHASH; |
| 381 | collide = fossil_malloc( nHash*2*sizeof(int) ); |
| 382 | landmark = &collide[nHash]; |
| 383 | memset(landmark, -1, nHash*sizeof(int)); |
| 384 | memset(collide, -1, nHash*sizeof(int)); |
| 385 | for(i=0; i<lenSrc-NHASH; i+=NHASH){ |
| 386 | int hv = hash_once(&zSrc[i]) % nHash; |
| 387 | collide[i/NHASH] = landmark[hv]; |
| 388 | landmark[hv] = i/NHASH; |
| 389 | } |
| 390 |
| --- src/delta.c | |
| +++ src/delta.c | |
| @@ -377,13 +377,12 @@ | |
| 377 | /* Compute the hash table used to locate matching sections in the |
| 378 | ** source file. |
| 379 | */ |
| 380 | nHash = lenSrc/NHASH; |
| 381 | collide = fossil_malloc( nHash*2*sizeof(int) ); |
| 382 | memset(collide, -1, nHash*2*sizeof(int)); |
| 383 | landmark = &collide[nHash]; |
| 384 | for(i=0; i<lenSrc-NHASH; i+=NHASH){ |
| 385 | int hv = hash_once(&zSrc[i]) % nHash; |
| 386 | collide[i/NHASH] = landmark[hv]; |
| 387 | landmark[hv] = i/NHASH; |
| 388 | } |
| 389 |
+8
-8
| --- src/deltacmd.c | ||
| +++ src/deltacmd.c | ||
| @@ -54,18 +54,18 @@ | ||
| 54 | 54 | Blob orig, target, delta; |
| 55 | 55 | if( g.argc!=5 ){ |
| 56 | 56 | usage("ORIGIN TARGET DELTA"); |
| 57 | 57 | } |
| 58 | 58 | if( blob_read_from_file(&orig, g.argv[2])<0 ){ |
| 59 | - fossil_fatal("cannot read %s\n", g.argv[2]); | |
| 59 | + fossil_fatal("cannot read %s", g.argv[2]); | |
| 60 | 60 | } |
| 61 | 61 | if( blob_read_from_file(&target, g.argv[3])<0 ){ |
| 62 | - fossil_fatal("cannot read %s\n", g.argv[3]); | |
| 62 | + fossil_fatal("cannot read %s", g.argv[3]); | |
| 63 | 63 | } |
| 64 | 64 | blob_delta_create(&orig, &target, &delta); |
| 65 | 65 | if( blob_write_to_file(&delta, g.argv[4])<blob_size(&delta) ){ |
| 66 | - fossil_fatal("cannot write %s\n", g.argv[4]); | |
| 66 | + fossil_fatal("cannot write %s", g.argv[4]); | |
| 67 | 67 | } |
| 68 | 68 | blob_reset(&orig); |
| 69 | 69 | blob_reset(&target); |
| 70 | 70 | blob_reset(&delta); |
| 71 | 71 | } |
| @@ -85,14 +85,14 @@ | ||
| 85 | 85 | int sz1, sz2, sz3; |
| 86 | 86 | if( g.argc!=4 ){ |
| 87 | 87 | usage("ORIGIN TARGET"); |
| 88 | 88 | } |
| 89 | 89 | if( blob_read_from_file(&orig, g.argv[2])<0 ){ |
| 90 | - fossil_fatal("cannot read %s\n", g.argv[2]); | |
| 90 | + fossil_fatal("cannot read %s", g.argv[2]); | |
| 91 | 91 | } |
| 92 | 92 | if( blob_read_from_file(&target, g.argv[3])<0 ){ |
| 93 | - fossil_fatal("cannot read %s\n", g.argv[3]); | |
| 93 | + fossil_fatal("cannot read %s", g.argv[3]); | |
| 94 | 94 | } |
| 95 | 95 | blob_delta_create(&orig, &target, &delta); |
| 96 | 96 | delta_analyze(blob_buffer(&delta), blob_size(&delta), &nCopy, &nInsert); |
| 97 | 97 | sz1 = blob_size(&orig); |
| 98 | 98 | sz2 = blob_size(&target); |
| @@ -153,18 +153,18 @@ | ||
| 153 | 153 | Blob orig, target, delta; |
| 154 | 154 | if( g.argc!=5 ){ |
| 155 | 155 | usage("ORIGIN DELTA TARGET"); |
| 156 | 156 | } |
| 157 | 157 | if( blob_read_from_file(&orig, g.argv[2])<0 ){ |
| 158 | - fossil_fatal("cannot read %s\n", g.argv[2]); | |
| 158 | + fossil_fatal("cannot read %s", g.argv[2]); | |
| 159 | 159 | } |
| 160 | 160 | if( blob_read_from_file(&delta, g.argv[3])<0 ){ |
| 161 | - fossil_fatal("cannot read %s\n", g.argv[3]); | |
| 161 | + fossil_fatal("cannot read %s", g.argv[3]); | |
| 162 | 162 | } |
| 163 | 163 | blob_delta_apply(&orig, &delta, &target); |
| 164 | 164 | if( blob_write_to_file(&target, g.argv[4])<blob_size(&target) ){ |
| 165 | - fossil_fatal("cannot write %s\n", g.argv[4]); | |
| 165 | + fossil_fatal("cannot write %s", g.argv[4]); | |
| 166 | 166 | } |
| 167 | 167 | blob_reset(&orig); |
| 168 | 168 | blob_reset(&target); |
| 169 | 169 | blob_reset(&delta); |
| 170 | 170 | } |
| 171 | 171 |
| --- src/deltacmd.c | |
| +++ src/deltacmd.c | |
| @@ -54,18 +54,18 @@ | |
| 54 | Blob orig, target, delta; |
| 55 | if( g.argc!=5 ){ |
| 56 | usage("ORIGIN TARGET DELTA"); |
| 57 | } |
| 58 | if( blob_read_from_file(&orig, g.argv[2])<0 ){ |
| 59 | fossil_fatal("cannot read %s\n", g.argv[2]); |
| 60 | } |
| 61 | if( blob_read_from_file(&target, g.argv[3])<0 ){ |
| 62 | fossil_fatal("cannot read %s\n", g.argv[3]); |
| 63 | } |
| 64 | blob_delta_create(&orig, &target, &delta); |
| 65 | if( blob_write_to_file(&delta, g.argv[4])<blob_size(&delta) ){ |
| 66 | fossil_fatal("cannot write %s\n", g.argv[4]); |
| 67 | } |
| 68 | blob_reset(&orig); |
| 69 | blob_reset(&target); |
| 70 | blob_reset(&delta); |
| 71 | } |
| @@ -85,14 +85,14 @@ | |
| 85 | int sz1, sz2, sz3; |
| 86 | if( g.argc!=4 ){ |
| 87 | usage("ORIGIN TARGET"); |
| 88 | } |
| 89 | if( blob_read_from_file(&orig, g.argv[2])<0 ){ |
| 90 | fossil_fatal("cannot read %s\n", g.argv[2]); |
| 91 | } |
| 92 | if( blob_read_from_file(&target, g.argv[3])<0 ){ |
| 93 | fossil_fatal("cannot read %s\n", g.argv[3]); |
| 94 | } |
| 95 | blob_delta_create(&orig, &target, &delta); |
| 96 | delta_analyze(blob_buffer(&delta), blob_size(&delta), &nCopy, &nInsert); |
| 97 | sz1 = blob_size(&orig); |
| 98 | sz2 = blob_size(&target); |
| @@ -153,18 +153,18 @@ | |
| 153 | Blob orig, target, delta; |
| 154 | if( g.argc!=5 ){ |
| 155 | usage("ORIGIN DELTA TARGET"); |
| 156 | } |
| 157 | if( blob_read_from_file(&orig, g.argv[2])<0 ){ |
| 158 | fossil_fatal("cannot read %s\n", g.argv[2]); |
| 159 | } |
| 160 | if( blob_read_from_file(&delta, g.argv[3])<0 ){ |
| 161 | fossil_fatal("cannot read %s\n", g.argv[3]); |
| 162 | } |
| 163 | blob_delta_apply(&orig, &delta, &target); |
| 164 | if( blob_write_to_file(&target, g.argv[4])<blob_size(&target) ){ |
| 165 | fossil_fatal("cannot write %s\n", g.argv[4]); |
| 166 | } |
| 167 | blob_reset(&orig); |
| 168 | blob_reset(&target); |
| 169 | blob_reset(&delta); |
| 170 | } |
| 171 |
| --- src/deltacmd.c | |
| +++ src/deltacmd.c | |
| @@ -54,18 +54,18 @@ | |
| 54 | Blob orig, target, delta; |
| 55 | if( g.argc!=5 ){ |
| 56 | usage("ORIGIN TARGET DELTA"); |
| 57 | } |
| 58 | if( blob_read_from_file(&orig, g.argv[2])<0 ){ |
| 59 | fossil_fatal("cannot read %s", g.argv[2]); |
| 60 | } |
| 61 | if( blob_read_from_file(&target, g.argv[3])<0 ){ |
| 62 | fossil_fatal("cannot read %s", g.argv[3]); |
| 63 | } |
| 64 | blob_delta_create(&orig, &target, &delta); |
| 65 | if( blob_write_to_file(&delta, g.argv[4])<blob_size(&delta) ){ |
| 66 | fossil_fatal("cannot write %s", g.argv[4]); |
| 67 | } |
| 68 | blob_reset(&orig); |
| 69 | blob_reset(&target); |
| 70 | blob_reset(&delta); |
| 71 | } |
| @@ -85,14 +85,14 @@ | |
| 85 | int sz1, sz2, sz3; |
| 86 | if( g.argc!=4 ){ |
| 87 | usage("ORIGIN TARGET"); |
| 88 | } |
| 89 | if( blob_read_from_file(&orig, g.argv[2])<0 ){ |
| 90 | fossil_fatal("cannot read %s", g.argv[2]); |
| 91 | } |
| 92 | if( blob_read_from_file(&target, g.argv[3])<0 ){ |
| 93 | fossil_fatal("cannot read %s", g.argv[3]); |
| 94 | } |
| 95 | blob_delta_create(&orig, &target, &delta); |
| 96 | delta_analyze(blob_buffer(&delta), blob_size(&delta), &nCopy, &nInsert); |
| 97 | sz1 = blob_size(&orig); |
| 98 | sz2 = blob_size(&target); |
| @@ -153,18 +153,18 @@ | |
| 153 | Blob orig, target, delta; |
| 154 | if( g.argc!=5 ){ |
| 155 | usage("ORIGIN DELTA TARGET"); |
| 156 | } |
| 157 | if( blob_read_from_file(&orig, g.argv[2])<0 ){ |
| 158 | fossil_fatal("cannot read %s", g.argv[2]); |
| 159 | } |
| 160 | if( blob_read_from_file(&delta, g.argv[3])<0 ){ |
| 161 | fossil_fatal("cannot read %s", g.argv[3]); |
| 162 | } |
| 163 | blob_delta_apply(&orig, &delta, &target); |
| 164 | if( blob_write_to_file(&target, g.argv[4])<blob_size(&target) ){ |
| 165 | fossil_fatal("cannot write %s", g.argv[4]); |
| 166 | } |
| 167 | blob_reset(&orig); |
| 168 | blob_reset(&target); |
| 169 | blob_reset(&delta); |
| 170 | } |
| 171 |
+3
-3
| --- src/descendants.c | ||
| +++ src/descendants.c | ||
| @@ -455,17 +455,17 @@ | ||
| 455 | 455 | |
| 456 | 456 | login_check_credentials(); |
| 457 | 457 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 458 | 458 | |
| 459 | 459 | if( !showAll ){ |
| 460 | - style_submenu_element("All", "All", "leaves?all"); | |
| 460 | + style_submenu_element("All", "leaves?all"); | |
| 461 | 461 | } |
| 462 | 462 | if( !showClosed ){ |
| 463 | - style_submenu_element("Closed", "Closed", "leaves?closed"); | |
| 463 | + style_submenu_element("Closed", "leaves?closed"); | |
| 464 | 464 | } |
| 465 | 465 | if( showClosed || showAll ){ |
| 466 | - style_submenu_element("Open", "Open", "leaves"); | |
| 466 | + style_submenu_element("Open", "leaves"); | |
| 467 | 467 | } |
| 468 | 468 | style_header("Leaves"); |
| 469 | 469 | login_anonymous_available(); |
| 470 | 470 | #if 0 |
| 471 | 471 | style_sidebox_begin("Nomenclature:", "33%"); |
| 472 | 472 |
| --- src/descendants.c | |
| +++ src/descendants.c | |
| @@ -455,17 +455,17 @@ | |
| 455 | |
| 456 | login_check_credentials(); |
| 457 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 458 | |
| 459 | if( !showAll ){ |
| 460 | style_submenu_element("All", "All", "leaves?all"); |
| 461 | } |
| 462 | if( !showClosed ){ |
| 463 | style_submenu_element("Closed", "Closed", "leaves?closed"); |
| 464 | } |
| 465 | if( showClosed || showAll ){ |
| 466 | style_submenu_element("Open", "Open", "leaves"); |
| 467 | } |
| 468 | style_header("Leaves"); |
| 469 | login_anonymous_available(); |
| 470 | #if 0 |
| 471 | style_sidebox_begin("Nomenclature:", "33%"); |
| 472 |
| --- src/descendants.c | |
| +++ src/descendants.c | |
| @@ -455,17 +455,17 @@ | |
| 455 | |
| 456 | login_check_credentials(); |
| 457 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 458 | |
| 459 | if( !showAll ){ |
| 460 | style_submenu_element("All", "leaves?all"); |
| 461 | } |
| 462 | if( !showClosed ){ |
| 463 | style_submenu_element("Closed", "leaves?closed"); |
| 464 | } |
| 465 | if( showClosed || showAll ){ |
| 466 | style_submenu_element("Open", "leaves"); |
| 467 | } |
| 468 | style_header("Leaves"); |
| 469 | login_anonymous_available(); |
| 470 | #if 0 |
| 471 | style_sidebox_begin("Nomenclature:", "33%"); |
| 472 |
+48
-31
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -115,10 +115,34 @@ | ||
| 115 | 115 | int nFrom; /* Number of lines in aFrom[] */ |
| 116 | 116 | DLine *aTo; /* File on right side of the diff */ |
| 117 | 117 | int nTo; /* Number of lines in aTo[] */ |
| 118 | 118 | int (*same_fn)(const DLine*,const DLine*); /* comparison function */ |
| 119 | 119 | }; |
| 120 | + | |
| 121 | +/* | |
| 122 | +** Count the number of lines in the input string. Include the last line | |
| 123 | +** in the count even if it lacks the \n terminator. If an empty string | |
| 124 | +** is specified, the number of lines is zero. For the purposes of this | |
| 125 | +** function, a string is considered empty if it contains no characters | |
| 126 | +** -OR- it contains only NUL characters. | |
| 127 | +*/ | |
| 128 | +static int count_lines( | |
| 129 | + const char *z, | |
| 130 | + int n, | |
| 131 | + int *pnLine | |
| 132 | +){ | |
| 133 | + int nLine; | |
| 134 | + const char *zNL, *z2; | |
| 135 | + for(nLine=0, z2=z; (zNL = strchr(z2,'\n'))!=0; z2=zNL+1, nLine++){} | |
| 136 | + if( z2[0]!='\0' ){ | |
| 137 | + nLine++; | |
| 138 | + do{ z2++; }while( z2[0]!='\0' ); | |
| 139 | + } | |
| 140 | + if( n!=(int)(z2-z) ) return 0; | |
| 141 | + if( pnLine ) *pnLine = nLine; | |
| 142 | + return 1; | |
| 143 | +} | |
| 120 | 144 | |
| 121 | 145 | /* |
| 122 | 146 | ** Return an array of DLine objects containing a pointer to the |
| 123 | 147 | ** start of each line and a hash of that line. The lower |
| 124 | 148 | ** bits of the hash store the length of each line. |
| @@ -140,32 +164,26 @@ | ||
| 140 | 164 | u64 diffFlags |
| 141 | 165 | ){ |
| 142 | 166 | int nLine, i, k, nn, s, x; |
| 143 | 167 | unsigned int h, h2; |
| 144 | 168 | DLine *a; |
| 145 | - const char *zNL, *z2; | |
| 146 | - | |
| 147 | - /* Count the number of lines in the input file. Include the last line | |
| 148 | - ** in the count even if it lacks the \n terminator | |
| 149 | - */ | |
| 150 | - for(nLine=0, z2=z; (zNL = strchr(z2,'\n'))!=0; z2=zNL+1, nLine++){} | |
| 151 | - if( z2[0]!=0 ){ | |
| 152 | - nLine++; | |
| 153 | - do{ z2++; }while( z2[0] ); | |
| 154 | - } | |
| 155 | - if( n!=(int)(z2-z) ) return 0; | |
| 156 | - | |
| 169 | + const char *zNL; | |
| 170 | + | |
| 171 | + if( count_lines(z, n, &nLine)==0 ){ | |
| 172 | + return 0; | |
| 173 | + } | |
| 174 | + assert( nLine>0 || z[0]=='\0' ); | |
| 157 | 175 | a = fossil_malloc( sizeof(a[0])*nLine ); |
| 158 | 176 | memset(a, 0, sizeof(a[0])*nLine); |
| 159 | 177 | if( nLine==0 ){ |
| 160 | 178 | *pnLine = 0; |
| 161 | 179 | return a; |
| 162 | 180 | } |
| 163 | 181 | i = 0; |
| 164 | 182 | do{ |
| 165 | 183 | zNL = strchr(z,'\n'); |
| 166 | - if( zNL==0 ) zNL = z+strlen(z); | |
| 184 | + if( zNL==0 ) zNL = z+n; | |
| 167 | 185 | nn = (int)(zNL - z); |
| 168 | 186 | if( nn>LENGTH_MASK ){ |
| 169 | 187 | fossil_free(a); |
| 170 | 188 | return 0; |
| 171 | 189 | } |
| @@ -181,14 +199,15 @@ | ||
| 181 | 199 | } |
| 182 | 200 | if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){ |
| 183 | 201 | int numws = 0; |
| 184 | 202 | while( s<k && fossil_isspace(z[s]) ){ s++; } |
| 185 | 203 | for(h=0, x=s; x<k; x++){ |
| 186 | - if( fossil_isspace(z[x]) ){ | |
| 204 | + char c = z[x]; | |
| 205 | + if( fossil_isspace(c) ){ | |
| 187 | 206 | ++numws; |
| 188 | 207 | }else{ |
| 189 | - h += z[x]; | |
| 208 | + h += c; | |
| 190 | 209 | h *= 0x9e3779b1; |
| 191 | 210 | } |
| 192 | 211 | } |
| 193 | 212 | k -= numws; |
| 194 | 213 | }else{ |
| @@ -200,13 +219,13 @@ | ||
| 200 | 219 | a[i].indent = s; |
| 201 | 220 | a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s); |
| 202 | 221 | h2 = h % nLine; |
| 203 | 222 | a[i].iNext = a[h2].iHash; |
| 204 | 223 | a[h2].iHash = i+1; |
| 205 | - z += nn+1; | |
| 224 | + z += nn+1; n -= nn+1; | |
| 206 | 225 | i++; |
| 207 | - }while( zNL[0] && zNL[1] ); | |
| 226 | + }while( zNL[0]!='\0' && zNL[1]!='\0' ); | |
| 208 | 227 | assert( i==nLine ); |
| 209 | 228 | |
| 210 | 229 | /* Return results */ |
| 211 | 230 | *pnLine = nLine; |
| 212 | 231 | return a; |
| @@ -1049,11 +1068,11 @@ | ||
| 1049 | 1068 | if( nLeft>mnLen ) memset(aM+mnLen, 1, nLeft-mnLen); |
| 1050 | 1069 | if( nRight>mnLen ) memset(aM+mnLen, 2, nRight-mnLen); |
| 1051 | 1070 | return aM; |
| 1052 | 1071 | } |
| 1053 | 1072 | |
| 1054 | - if( nRight < (sizeof(aBuf)/sizeof(aBuf[0]))-1 ){ | |
| 1073 | + if( nRight < count(aBuf)-1 ){ | |
| 1055 | 1074 | pToFree = 0; |
| 1056 | 1075 | a = aBuf; |
| 1057 | 1076 | }else{ |
| 1058 | 1077 | a = pToFree = fossil_malloc( sizeof(a[0])*(nRight+1) ); |
| 1059 | 1078 | } |
| @@ -2326,34 +2345,32 @@ | ||
| 2326 | 2345 | url_add_parameter(&url, "limit", sqlite3_mprintf("%d", iLimit)); |
| 2327 | 2346 | } |
| 2328 | 2347 | url_add_parameter(&url, "log", showLog ? "1" : "0"); |
| 2329 | 2348 | if( ignoreWs ){ |
| 2330 | 2349 | url_add_parameter(&url, "w", ""); |
| 2331 | - style_submenu_element("Show Whitespace Changes", "Show Whitespace Changes", | |
| 2332 | - "%s", url_render(&url, "w", 0, 0, 0)); | |
| 2350 | + style_submenu_element("Show Whitespace Changes", "%s", | |
| 2351 | + url_render(&url, "w", 0, 0, 0)); | |
| 2333 | 2352 | }else{ |
| 2334 | - style_submenu_element("Ignore Whitespace", "Ignore Whitespace", | |
| 2335 | - "%s", url_render(&url, "w", "", 0, 0)); | |
| 2353 | + style_submenu_element("Ignore Whitespace", "%s", | |
| 2354 | + url_render(&url, "w", "", 0, 0)); | |
| 2336 | 2355 | } |
| 2337 | 2356 | if( showLog ){ |
| 2338 | - style_submenu_element("Hide Log", "Hide Log", | |
| 2339 | - "%s", url_render(&url, "log", "0", 0, 0)); | |
| 2357 | + style_submenu_element("Hide Log", "%s", url_render(&url, "log", "0", 0, 0)); | |
| 2340 | 2358 | }else{ |
| 2341 | - style_submenu_element("Show Log", "Show Log", | |
| 2342 | - "%s", url_render(&url, "log", "1", 0, 0)); | |
| 2359 | + style_submenu_element("Show Log", "%s", url_render(&url, "log", "1", 0, 0)); | |
| 2343 | 2360 | } |
| 2344 | 2361 | if( ann.bLimit ){ |
| 2345 | 2362 | char *z1, *z2; |
| 2346 | - style_submenu_element("All Ancestors", "All Ancestors", | |
| 2347 | - "%s", url_render(&url, "limit", "-1", 0, 0)); | |
| 2363 | + style_submenu_element("All Ancestors", "%s", | |
| 2364 | + url_render(&url, "limit", "-1", 0, 0)); | |
| 2348 | 2365 | z1 = sqlite3_mprintf("%d Ancestors", iLimit+20); |
| 2349 | 2366 | z2 = sqlite3_mprintf("%d", iLimit+20); |
| 2350 | - style_submenu_element(z1, z1, "%s", url_render(&url, "limit", z2, 0, 0)); | |
| 2367 | + style_submenu_element(z1, "%s", url_render(&url, "limit", z2, 0, 0)); | |
| 2351 | 2368 | } |
| 2352 | 2369 | if( iLimit>20 ){ |
| 2353 | - style_submenu_element("20 Ancestors", "20 Ancestors", | |
| 2354 | - "%s", url_render(&url, "limit", "20", 0, 0)); | |
| 2370 | + style_submenu_element("20 Ancestors", "%s", | |
| 2371 | + url_render(&url, "limit", "20", 0, 0)); | |
| 2355 | 2372 | } |
| 2356 | 2373 | if( skin_detail_boolean("white-foreground") ){ |
| 2357 | 2374 | clr1 = 0xa04040; |
| 2358 | 2375 | clr2 = 0x4059a0; |
| 2359 | 2376 | }else{ |
| 2360 | 2377 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -115,10 +115,34 @@ | |
| 115 | int nFrom; /* Number of lines in aFrom[] */ |
| 116 | DLine *aTo; /* File on right side of the diff */ |
| 117 | int nTo; /* Number of lines in aTo[] */ |
| 118 | int (*same_fn)(const DLine*,const DLine*); /* comparison function */ |
| 119 | }; |
| 120 | |
| 121 | /* |
| 122 | ** Return an array of DLine objects containing a pointer to the |
| 123 | ** start of each line and a hash of that line. The lower |
| 124 | ** bits of the hash store the length of each line. |
| @@ -140,32 +164,26 @@ | |
| 140 | u64 diffFlags |
| 141 | ){ |
| 142 | int nLine, i, k, nn, s, x; |
| 143 | unsigned int h, h2; |
| 144 | DLine *a; |
| 145 | const char *zNL, *z2; |
| 146 | |
| 147 | /* Count the number of lines in the input file. Include the last line |
| 148 | ** in the count even if it lacks the \n terminator |
| 149 | */ |
| 150 | for(nLine=0, z2=z; (zNL = strchr(z2,'\n'))!=0; z2=zNL+1, nLine++){} |
| 151 | if( z2[0]!=0 ){ |
| 152 | nLine++; |
| 153 | do{ z2++; }while( z2[0] ); |
| 154 | } |
| 155 | if( n!=(int)(z2-z) ) return 0; |
| 156 | |
| 157 | a = fossil_malloc( sizeof(a[0])*nLine ); |
| 158 | memset(a, 0, sizeof(a[0])*nLine); |
| 159 | if( nLine==0 ){ |
| 160 | *pnLine = 0; |
| 161 | return a; |
| 162 | } |
| 163 | i = 0; |
| 164 | do{ |
| 165 | zNL = strchr(z,'\n'); |
| 166 | if( zNL==0 ) zNL = z+strlen(z); |
| 167 | nn = (int)(zNL - z); |
| 168 | if( nn>LENGTH_MASK ){ |
| 169 | fossil_free(a); |
| 170 | return 0; |
| 171 | } |
| @@ -181,14 +199,15 @@ | |
| 181 | } |
| 182 | if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){ |
| 183 | int numws = 0; |
| 184 | while( s<k && fossil_isspace(z[s]) ){ s++; } |
| 185 | for(h=0, x=s; x<k; x++){ |
| 186 | if( fossil_isspace(z[x]) ){ |
| 187 | ++numws; |
| 188 | }else{ |
| 189 | h += z[x]; |
| 190 | h *= 0x9e3779b1; |
| 191 | } |
| 192 | } |
| 193 | k -= numws; |
| 194 | }else{ |
| @@ -200,13 +219,13 @@ | |
| 200 | a[i].indent = s; |
| 201 | a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s); |
| 202 | h2 = h % nLine; |
| 203 | a[i].iNext = a[h2].iHash; |
| 204 | a[h2].iHash = i+1; |
| 205 | z += nn+1; |
| 206 | i++; |
| 207 | }while( zNL[0] && zNL[1] ); |
| 208 | assert( i==nLine ); |
| 209 | |
| 210 | /* Return results */ |
| 211 | *pnLine = nLine; |
| 212 | return a; |
| @@ -1049,11 +1068,11 @@ | |
| 1049 | if( nLeft>mnLen ) memset(aM+mnLen, 1, nLeft-mnLen); |
| 1050 | if( nRight>mnLen ) memset(aM+mnLen, 2, nRight-mnLen); |
| 1051 | return aM; |
| 1052 | } |
| 1053 | |
| 1054 | if( nRight < (sizeof(aBuf)/sizeof(aBuf[0]))-1 ){ |
| 1055 | pToFree = 0; |
| 1056 | a = aBuf; |
| 1057 | }else{ |
| 1058 | a = pToFree = fossil_malloc( sizeof(a[0])*(nRight+1) ); |
| 1059 | } |
| @@ -2326,34 +2345,32 @@ | |
| 2326 | url_add_parameter(&url, "limit", sqlite3_mprintf("%d", iLimit)); |
| 2327 | } |
| 2328 | url_add_parameter(&url, "log", showLog ? "1" : "0"); |
| 2329 | if( ignoreWs ){ |
| 2330 | url_add_parameter(&url, "w", ""); |
| 2331 | style_submenu_element("Show Whitespace Changes", "Show Whitespace Changes", |
| 2332 | "%s", url_render(&url, "w", 0, 0, 0)); |
| 2333 | }else{ |
| 2334 | style_submenu_element("Ignore Whitespace", "Ignore Whitespace", |
| 2335 | "%s", url_render(&url, "w", "", 0, 0)); |
| 2336 | } |
| 2337 | if( showLog ){ |
| 2338 | style_submenu_element("Hide Log", "Hide Log", |
| 2339 | "%s", url_render(&url, "log", "0", 0, 0)); |
| 2340 | }else{ |
| 2341 | style_submenu_element("Show Log", "Show Log", |
| 2342 | "%s", url_render(&url, "log", "1", 0, 0)); |
| 2343 | } |
| 2344 | if( ann.bLimit ){ |
| 2345 | char *z1, *z2; |
| 2346 | style_submenu_element("All Ancestors", "All Ancestors", |
| 2347 | "%s", url_render(&url, "limit", "-1", 0, 0)); |
| 2348 | z1 = sqlite3_mprintf("%d Ancestors", iLimit+20); |
| 2349 | z2 = sqlite3_mprintf("%d", iLimit+20); |
| 2350 | style_submenu_element(z1, z1, "%s", url_render(&url, "limit", z2, 0, 0)); |
| 2351 | } |
| 2352 | if( iLimit>20 ){ |
| 2353 | style_submenu_element("20 Ancestors", "20 Ancestors", |
| 2354 | "%s", url_render(&url, "limit", "20", 0, 0)); |
| 2355 | } |
| 2356 | if( skin_detail_boolean("white-foreground") ){ |
| 2357 | clr1 = 0xa04040; |
| 2358 | clr2 = 0x4059a0; |
| 2359 | }else{ |
| 2360 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -115,10 +115,34 @@ | |
| 115 | int nFrom; /* Number of lines in aFrom[] */ |
| 116 | DLine *aTo; /* File on right side of the diff */ |
| 117 | int nTo; /* Number of lines in aTo[] */ |
| 118 | int (*same_fn)(const DLine*,const DLine*); /* comparison function */ |
| 119 | }; |
| 120 | |
| 121 | /* |
| 122 | ** Count the number of lines in the input string. Include the last line |
| 123 | ** in the count even if it lacks the \n terminator. If an empty string |
| 124 | ** is specified, the number of lines is zero. For the purposes of this |
| 125 | ** function, a string is considered empty if it contains no characters |
| 126 | ** -OR- it contains only NUL characters. |
| 127 | */ |
| 128 | static int count_lines( |
| 129 | const char *z, |
| 130 | int n, |
| 131 | int *pnLine |
| 132 | ){ |
| 133 | int nLine; |
| 134 | const char *zNL, *z2; |
| 135 | for(nLine=0, z2=z; (zNL = strchr(z2,'\n'))!=0; z2=zNL+1, nLine++){} |
| 136 | if( z2[0]!='\0' ){ |
| 137 | nLine++; |
| 138 | do{ z2++; }while( z2[0]!='\0' ); |
| 139 | } |
| 140 | if( n!=(int)(z2-z) ) return 0; |
| 141 | if( pnLine ) *pnLine = nLine; |
| 142 | return 1; |
| 143 | } |
| 144 | |
| 145 | /* |
| 146 | ** Return an array of DLine objects containing a pointer to the |
| 147 | ** start of each line and a hash of that line. The lower |
| 148 | ** bits of the hash store the length of each line. |
| @@ -140,32 +164,26 @@ | |
| 164 | u64 diffFlags |
| 165 | ){ |
| 166 | int nLine, i, k, nn, s, x; |
| 167 | unsigned int h, h2; |
| 168 | DLine *a; |
| 169 | const char *zNL; |
| 170 | |
| 171 | if( count_lines(z, n, &nLine)==0 ){ |
| 172 | return 0; |
| 173 | } |
| 174 | assert( nLine>0 || z[0]=='\0' ); |
| 175 | a = fossil_malloc( sizeof(a[0])*nLine ); |
| 176 | memset(a, 0, sizeof(a[0])*nLine); |
| 177 | if( nLine==0 ){ |
| 178 | *pnLine = 0; |
| 179 | return a; |
| 180 | } |
| 181 | i = 0; |
| 182 | do{ |
| 183 | zNL = strchr(z,'\n'); |
| 184 | if( zNL==0 ) zNL = z+n; |
| 185 | nn = (int)(zNL - z); |
| 186 | if( nn>LENGTH_MASK ){ |
| 187 | fossil_free(a); |
| 188 | return 0; |
| 189 | } |
| @@ -181,14 +199,15 @@ | |
| 199 | } |
| 200 | if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){ |
| 201 | int numws = 0; |
| 202 | while( s<k && fossil_isspace(z[s]) ){ s++; } |
| 203 | for(h=0, x=s; x<k; x++){ |
| 204 | char c = z[x]; |
| 205 | if( fossil_isspace(c) ){ |
| 206 | ++numws; |
| 207 | }else{ |
| 208 | h += c; |
| 209 | h *= 0x9e3779b1; |
| 210 | } |
| 211 | } |
| 212 | k -= numws; |
| 213 | }else{ |
| @@ -200,13 +219,13 @@ | |
| 219 | a[i].indent = s; |
| 220 | a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s); |
| 221 | h2 = h % nLine; |
| 222 | a[i].iNext = a[h2].iHash; |
| 223 | a[h2].iHash = i+1; |
| 224 | z += nn+1; n -= nn+1; |
| 225 | i++; |
| 226 | }while( zNL[0]!='\0' && zNL[1]!='\0' ); |
| 227 | assert( i==nLine ); |
| 228 | |
| 229 | /* Return results */ |
| 230 | *pnLine = nLine; |
| 231 | return a; |
| @@ -1049,11 +1068,11 @@ | |
| 1068 | if( nLeft>mnLen ) memset(aM+mnLen, 1, nLeft-mnLen); |
| 1069 | if( nRight>mnLen ) memset(aM+mnLen, 2, nRight-mnLen); |
| 1070 | return aM; |
| 1071 | } |
| 1072 | |
| 1073 | if( nRight < count(aBuf)-1 ){ |
| 1074 | pToFree = 0; |
| 1075 | a = aBuf; |
| 1076 | }else{ |
| 1077 | a = pToFree = fossil_malloc( sizeof(a[0])*(nRight+1) ); |
| 1078 | } |
| @@ -2326,34 +2345,32 @@ | |
| 2345 | url_add_parameter(&url, "limit", sqlite3_mprintf("%d", iLimit)); |
| 2346 | } |
| 2347 | url_add_parameter(&url, "log", showLog ? "1" : "0"); |
| 2348 | if( ignoreWs ){ |
| 2349 | url_add_parameter(&url, "w", ""); |
| 2350 | style_submenu_element("Show Whitespace Changes", "%s", |
| 2351 | url_render(&url, "w", 0, 0, 0)); |
| 2352 | }else{ |
| 2353 | style_submenu_element("Ignore Whitespace", "%s", |
| 2354 | url_render(&url, "w", "", 0, 0)); |
| 2355 | } |
| 2356 | if( showLog ){ |
| 2357 | style_submenu_element("Hide Log", "%s", url_render(&url, "log", "0", 0, 0)); |
| 2358 | }else{ |
| 2359 | style_submenu_element("Show Log", "%s", url_render(&url, "log", "1", 0, 0)); |
| 2360 | } |
| 2361 | if( ann.bLimit ){ |
| 2362 | char *z1, *z2; |
| 2363 | style_submenu_element("All Ancestors", "%s", |
| 2364 | url_render(&url, "limit", "-1", 0, 0)); |
| 2365 | z1 = sqlite3_mprintf("%d Ancestors", iLimit+20); |
| 2366 | z2 = sqlite3_mprintf("%d", iLimit+20); |
| 2367 | style_submenu_element(z1, "%s", url_render(&url, "limit", z2, 0, 0)); |
| 2368 | } |
| 2369 | if( iLimit>20 ){ |
| 2370 | style_submenu_element("20 Ancestors", "%s", |
| 2371 | url_render(&url, "limit", "20", 0, 0)); |
| 2372 | } |
| 2373 | if( skin_detail_boolean("white-foreground") ){ |
| 2374 | clr1 = 0xa04040; |
| 2375 | clr2 = 0x4059a0; |
| 2376 | }else{ |
| 2377 |
+4
-1
| --- src/diffcmd.c | ||
| +++ src/diffcmd.c | ||
| @@ -412,10 +412,11 @@ | ||
| 412 | 412 | " ORDER BY pathname /*scan*/", |
| 413 | 413 | vid |
| 414 | 414 | ); |
| 415 | 415 | } |
| 416 | 416 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 417 | + blob_reset(&sql); | |
| 417 | 418 | while( db_step(&q)==SQLITE_ROW ){ |
| 418 | 419 | const char *zPathname = db_column_text(&q,0); |
| 419 | 420 | int isDeleted = db_column_int(&q, 1); |
| 420 | 421 | int isChnged = db_column_int(&q,2); |
| 421 | 422 | int isNew = db_column_int(&q,3); |
| @@ -797,10 +798,11 @@ | ||
| 797 | 798 | ** Options: |
| 798 | 799 | ** --binary PATTERN Treat files that match the glob PATTERN as binary |
| 799 | 800 | ** --branch BRANCH Show diff of all changes on BRANCH |
| 800 | 801 | ** --brief Show filenames only |
| 801 | 802 | ** --checkin VERSION Show diff of all changes in VERSION |
| 803 | +** --command PROG External diff program - overrides "diff-command" | |
| 802 | 804 | ** --context|-c N Use N lines of context |
| 803 | 805 | ** --diff-binary BOOL Include binary files when using external commands |
| 804 | 806 | ** --exec-abs-paths Force absolute path names with external commands. |
| 805 | 807 | ** --exec-rel-paths Force relative path names with external commands. |
| 806 | 808 | ** --from|-r VERSION Select VERSION as source for the diff |
| @@ -868,11 +870,12 @@ | ||
| 868 | 870 | fossil_fatal("must use --from if --to is present"); |
| 869 | 871 | }else{ |
| 870 | 872 | db_find_and_open_repository(0, 0); |
| 871 | 873 | } |
| 872 | 874 | if( !isInternDiff ){ |
| 873 | - zDiffCmd = diff_command_external(isGDiff); | |
| 875 | + zDiffCmd = find_option("command", 0, 1); | |
| 876 | + if( zDiffCmd==0 ) zDiffCmd = diff_command_external(isGDiff); | |
| 874 | 877 | } |
| 875 | 878 | zBinGlob = diff_get_binary_glob(); |
| 876 | 879 | fIncludeBinary = diff_include_binary_files(); |
| 877 | 880 | determine_exec_relative_option(1); |
| 878 | 881 | verify_all_options(); |
| 879 | 882 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -412,10 +412,11 @@ | |
| 412 | " ORDER BY pathname /*scan*/", |
| 413 | vid |
| 414 | ); |
| 415 | } |
| 416 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 417 | while( db_step(&q)==SQLITE_ROW ){ |
| 418 | const char *zPathname = db_column_text(&q,0); |
| 419 | int isDeleted = db_column_int(&q, 1); |
| 420 | int isChnged = db_column_int(&q,2); |
| 421 | int isNew = db_column_int(&q,3); |
| @@ -797,10 +798,11 @@ | |
| 797 | ** Options: |
| 798 | ** --binary PATTERN Treat files that match the glob PATTERN as binary |
| 799 | ** --branch BRANCH Show diff of all changes on BRANCH |
| 800 | ** --brief Show filenames only |
| 801 | ** --checkin VERSION Show diff of all changes in VERSION |
| 802 | ** --context|-c N Use N lines of context |
| 803 | ** --diff-binary BOOL Include binary files when using external commands |
| 804 | ** --exec-abs-paths Force absolute path names with external commands. |
| 805 | ** --exec-rel-paths Force relative path names with external commands. |
| 806 | ** --from|-r VERSION Select VERSION as source for the diff |
| @@ -868,11 +870,12 @@ | |
| 868 | fossil_fatal("must use --from if --to is present"); |
| 869 | }else{ |
| 870 | db_find_and_open_repository(0, 0); |
| 871 | } |
| 872 | if( !isInternDiff ){ |
| 873 | zDiffCmd = diff_command_external(isGDiff); |
| 874 | } |
| 875 | zBinGlob = diff_get_binary_glob(); |
| 876 | fIncludeBinary = diff_include_binary_files(); |
| 877 | determine_exec_relative_option(1); |
| 878 | verify_all_options(); |
| 879 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -412,10 +412,11 @@ | |
| 412 | " ORDER BY pathname /*scan*/", |
| 413 | vid |
| 414 | ); |
| 415 | } |
| 416 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 417 | blob_reset(&sql); |
| 418 | while( db_step(&q)==SQLITE_ROW ){ |
| 419 | const char *zPathname = db_column_text(&q,0); |
| 420 | int isDeleted = db_column_int(&q, 1); |
| 421 | int isChnged = db_column_int(&q,2); |
| 422 | int isNew = db_column_int(&q,3); |
| @@ -797,10 +798,11 @@ | |
| 798 | ** Options: |
| 799 | ** --binary PATTERN Treat files that match the glob PATTERN as binary |
| 800 | ** --branch BRANCH Show diff of all changes on BRANCH |
| 801 | ** --brief Show filenames only |
| 802 | ** --checkin VERSION Show diff of all changes in VERSION |
| 803 | ** --command PROG External diff program - overrides "diff-command" |
| 804 | ** --context|-c N Use N lines of context |
| 805 | ** --diff-binary BOOL Include binary files when using external commands |
| 806 | ** --exec-abs-paths Force absolute path names with external commands. |
| 807 | ** --exec-rel-paths Force relative path names with external commands. |
| 808 | ** --from|-r VERSION Select VERSION as source for the diff |
| @@ -868,11 +870,12 @@ | |
| 870 | fossil_fatal("must use --from if --to is present"); |
| 871 | }else{ |
| 872 | db_find_and_open_repository(0, 0); |
| 873 | } |
| 874 | if( !isInternDiff ){ |
| 875 | zDiffCmd = find_option("command", 0, 1); |
| 876 | if( zDiffCmd==0 ) zDiffCmd = diff_command_external(isGDiff); |
| 877 | } |
| 878 | zBinGlob = diff_get_binary_glob(); |
| 879 | fIncludeBinary = diff_include_binary_files(); |
| 880 | determine_exec_relative_option(1); |
| 881 | verify_all_options(); |
| 882 |
+13
-8
| --- src/dispatch.c | ||
| +++ src/dispatch.c | ||
| @@ -69,11 +69,11 @@ | ||
| 69 | 69 | ** The page_index.h file is generated by the mkindex program which scans all |
| 70 | 70 | ** source code files looking for header comments on the functions that |
| 71 | 71 | ** implement command and webpages. |
| 72 | 72 | */ |
| 73 | 73 | #include "page_index.h" |
| 74 | -#define MX_COMMAND (sizeof(aCommand)/sizeof(aCommand[0])) | |
| 74 | +#define MX_COMMAND count(aCommand) | |
| 75 | 75 | |
| 76 | 76 | /* |
| 77 | 77 | ** Given a command or webpage name in zName, find the corresponding CmdOrPage |
| 78 | 78 | ** object and return a pointer to that object in *ppCmd. |
| 79 | 79 | ** |
| @@ -233,16 +233,17 @@ | ||
| 233 | 233 | */ |
| 234 | 234 | void help_page(void){ |
| 235 | 235 | const char *zCmd = P("cmd"); |
| 236 | 236 | |
| 237 | 237 | if( zCmd==0 ) zCmd = P("name"); |
| 238 | - style_header("Command-line Help"); | |
| 239 | - if( zCmd ){ | |
| 238 | + if( zCmd && *zCmd ){ | |
| 240 | 239 | int rc; |
| 241 | 240 | const CmdOrPage *pCmd = 0; |
| 242 | 241 | |
| 243 | - style_submenu_element("Command-List", "Command-List", "%s/help", g.zTop); | |
| 242 | + style_header("Help: %s", zCmd); | |
| 243 | + | |
| 244 | + style_submenu_element("Command-List", "%s/help", g.zTop); | |
| 244 | 245 | if( *zCmd=='/' ){ |
| 245 | 246 | /* Some of the webpages require query parameters in order to work. |
| 246 | 247 | ** @ <h1>The "<a href='%R%s(zCmd)'>%s(zCmd)</a>" page:</h1> */ |
| 247 | 248 | @ <h1>The "%s(zCmd)" page:</h1> |
| 248 | 249 | }else{ |
| @@ -262,26 +263,30 @@ | ||
| 262 | 263 | @ </blockquote> |
| 263 | 264 | } |
| 264 | 265 | } |
| 265 | 266 | }else{ |
| 266 | 267 | int i, j, n; |
| 268 | + | |
| 269 | + style_header("Help"); | |
| 267 | 270 | |
| 268 | 271 | @ <h1>Available commands:</h1> |
| 269 | 272 | @ <table border="0"><tr> |
| 270 | 273 | for(i=j=0; i<MX_COMMAND; i++){ |
| 271 | 274 | const char *z = aCommand[i].zName; |
| 272 | 275 | if( '/'==*z || strncmp(z,"test",4)==0 ) continue; |
| 273 | 276 | j++; |
| 274 | 277 | } |
| 275 | - n = (j+6)/7; | |
| 278 | + n = (j+5)/6; | |
| 276 | 279 | for(i=j=0; i<MX_COMMAND; i++){ |
| 277 | 280 | const char *z = aCommand[i].zName; |
| 281 | + const char *zBoldOn = aCommand[i].eCmdFlags&CMDFLAG_1ST_TIER?"<b>" :""; | |
| 282 | + const char *zBoldOff = aCommand[i].eCmdFlags&CMDFLAG_1ST_TIER?"</b>":""; | |
| 278 | 283 | if( '/'==*z || strncmp(z,"test",4)==0 ) continue; |
| 279 | 284 | if( j==0 ){ |
| 280 | 285 | @ <td valign="top"><ul> |
| 281 | 286 | } |
| 282 | - @ <li><a href="%R/help?cmd=%s(z)">%s(z)</a></li> | |
| 287 | + @ <li><a href="%R/help?cmd=%s(z)">%s(zBoldOn)%s(z)%s(zBoldOff)</a></li> | |
| 283 | 288 | j++; |
| 284 | 289 | if( j>=n ){ |
| 285 | 290 | @ </ul></td> |
| 286 | 291 | j = 0; |
| 287 | 292 | } |
| @@ -360,11 +365,11 @@ | ||
| 360 | 365 | ** |
| 361 | 366 | ** Show all help text on a single page. Useful for proof-reading. |
| 362 | 367 | */ |
| 363 | 368 | void test_all_help_page(void){ |
| 364 | 369 | int i; |
| 365 | - style_header("Testpage: All Help Text"); | |
| 370 | + style_header("All Help Text"); | |
| 366 | 371 | for(i=0; i<MX_COMMAND; i++){ |
| 367 | 372 | if( memcmp(aCommand[i].zName, "test", 4)==0 ) continue; |
| 368 | 373 | @ <h2>%s(aCommand[i].zName):</h2> |
| 369 | 374 | @ <blockquote> |
| 370 | 375 | help_to_html(aCommand[i].zHelp, cgi_output_blob()); |
| @@ -402,11 +407,11 @@ | ||
| 402 | 407 | */ |
| 403 | 408 | void cmd_test_webpage_list(void){ |
| 404 | 409 | int i, nCmd; |
| 405 | 410 | const char *aCmd[MX_COMMAND]; |
| 406 | 411 | for(i=nCmd=0; i<MX_COMMAND; i++){ |
| 407 | - if(0x08 & aCommand[i].eCmdFlags){ | |
| 412 | + if(CMDFLAG_WEBPAGE & aCommand[i].eCmdFlags){ | |
| 408 | 413 | aCmd[nCmd++] = aCommand[i].zName; |
| 409 | 414 | } |
| 410 | 415 | } |
| 411 | 416 | assert(nCmd && "page list is empty?"); |
| 412 | 417 | multi_column_list(aCmd, nCmd); |
| 413 | 418 |
| --- src/dispatch.c | |
| +++ src/dispatch.c | |
| @@ -69,11 +69,11 @@ | |
| 69 | ** The page_index.h file is generated by the mkindex program which scans all |
| 70 | ** source code files looking for header comments on the functions that |
| 71 | ** implement command and webpages. |
| 72 | */ |
| 73 | #include "page_index.h" |
| 74 | #define MX_COMMAND (sizeof(aCommand)/sizeof(aCommand[0])) |
| 75 | |
| 76 | /* |
| 77 | ** Given a command or webpage name in zName, find the corresponding CmdOrPage |
| 78 | ** object and return a pointer to that object in *ppCmd. |
| 79 | ** |
| @@ -233,16 +233,17 @@ | |
| 233 | */ |
| 234 | void help_page(void){ |
| 235 | const char *zCmd = P("cmd"); |
| 236 | |
| 237 | if( zCmd==0 ) zCmd = P("name"); |
| 238 | style_header("Command-line Help"); |
| 239 | if( zCmd ){ |
| 240 | int rc; |
| 241 | const CmdOrPage *pCmd = 0; |
| 242 | |
| 243 | style_submenu_element("Command-List", "Command-List", "%s/help", g.zTop); |
| 244 | if( *zCmd=='/' ){ |
| 245 | /* Some of the webpages require query parameters in order to work. |
| 246 | ** @ <h1>The "<a href='%R%s(zCmd)'>%s(zCmd)</a>" page:</h1> */ |
| 247 | @ <h1>The "%s(zCmd)" page:</h1> |
| 248 | }else{ |
| @@ -262,26 +263,30 @@ | |
| 262 | @ </blockquote> |
| 263 | } |
| 264 | } |
| 265 | }else{ |
| 266 | int i, j, n; |
| 267 | |
| 268 | @ <h1>Available commands:</h1> |
| 269 | @ <table border="0"><tr> |
| 270 | for(i=j=0; i<MX_COMMAND; i++){ |
| 271 | const char *z = aCommand[i].zName; |
| 272 | if( '/'==*z || strncmp(z,"test",4)==0 ) continue; |
| 273 | j++; |
| 274 | } |
| 275 | n = (j+6)/7; |
| 276 | for(i=j=0; i<MX_COMMAND; i++){ |
| 277 | const char *z = aCommand[i].zName; |
| 278 | if( '/'==*z || strncmp(z,"test",4)==0 ) continue; |
| 279 | if( j==0 ){ |
| 280 | @ <td valign="top"><ul> |
| 281 | } |
| 282 | @ <li><a href="%R/help?cmd=%s(z)">%s(z)</a></li> |
| 283 | j++; |
| 284 | if( j>=n ){ |
| 285 | @ </ul></td> |
| 286 | j = 0; |
| 287 | } |
| @@ -360,11 +365,11 @@ | |
| 360 | ** |
| 361 | ** Show all help text on a single page. Useful for proof-reading. |
| 362 | */ |
| 363 | void test_all_help_page(void){ |
| 364 | int i; |
| 365 | style_header("Testpage: All Help Text"); |
| 366 | for(i=0; i<MX_COMMAND; i++){ |
| 367 | if( memcmp(aCommand[i].zName, "test", 4)==0 ) continue; |
| 368 | @ <h2>%s(aCommand[i].zName):</h2> |
| 369 | @ <blockquote> |
| 370 | help_to_html(aCommand[i].zHelp, cgi_output_blob()); |
| @@ -402,11 +407,11 @@ | |
| 402 | */ |
| 403 | void cmd_test_webpage_list(void){ |
| 404 | int i, nCmd; |
| 405 | const char *aCmd[MX_COMMAND]; |
| 406 | for(i=nCmd=0; i<MX_COMMAND; i++){ |
| 407 | if(0x08 & aCommand[i].eCmdFlags){ |
| 408 | aCmd[nCmd++] = aCommand[i].zName; |
| 409 | } |
| 410 | } |
| 411 | assert(nCmd && "page list is empty?"); |
| 412 | multi_column_list(aCmd, nCmd); |
| 413 |
| --- src/dispatch.c | |
| +++ src/dispatch.c | |
| @@ -69,11 +69,11 @@ | |
| 69 | ** The page_index.h file is generated by the mkindex program which scans all |
| 70 | ** source code files looking for header comments on the functions that |
| 71 | ** implement command and webpages. |
| 72 | */ |
| 73 | #include "page_index.h" |
| 74 | #define MX_COMMAND count(aCommand) |
| 75 | |
| 76 | /* |
| 77 | ** Given a command or webpage name in zName, find the corresponding CmdOrPage |
| 78 | ** object and return a pointer to that object in *ppCmd. |
| 79 | ** |
| @@ -233,16 +233,17 @@ | |
| 233 | */ |
| 234 | void help_page(void){ |
| 235 | const char *zCmd = P("cmd"); |
| 236 | |
| 237 | if( zCmd==0 ) zCmd = P("name"); |
| 238 | if( zCmd && *zCmd ){ |
| 239 | int rc; |
| 240 | const CmdOrPage *pCmd = 0; |
| 241 | |
| 242 | style_header("Help: %s", zCmd); |
| 243 | |
| 244 | style_submenu_element("Command-List", "%s/help", g.zTop); |
| 245 | if( *zCmd=='/' ){ |
| 246 | /* Some of the webpages require query parameters in order to work. |
| 247 | ** @ <h1>The "<a href='%R%s(zCmd)'>%s(zCmd)</a>" page:</h1> */ |
| 248 | @ <h1>The "%s(zCmd)" page:</h1> |
| 249 | }else{ |
| @@ -262,26 +263,30 @@ | |
| 263 | @ </blockquote> |
| 264 | } |
| 265 | } |
| 266 | }else{ |
| 267 | int i, j, n; |
| 268 | |
| 269 | style_header("Help"); |
| 270 | |
| 271 | @ <h1>Available commands:</h1> |
| 272 | @ <table border="0"><tr> |
| 273 | for(i=j=0; i<MX_COMMAND; i++){ |
| 274 | const char *z = aCommand[i].zName; |
| 275 | if( '/'==*z || strncmp(z,"test",4)==0 ) continue; |
| 276 | j++; |
| 277 | } |
| 278 | n = (j+5)/6; |
| 279 | for(i=j=0; i<MX_COMMAND; i++){ |
| 280 | const char *z = aCommand[i].zName; |
| 281 | const char *zBoldOn = aCommand[i].eCmdFlags&CMDFLAG_1ST_TIER?"<b>" :""; |
| 282 | const char *zBoldOff = aCommand[i].eCmdFlags&CMDFLAG_1ST_TIER?"</b>":""; |
| 283 | if( '/'==*z || strncmp(z,"test",4)==0 ) continue; |
| 284 | if( j==0 ){ |
| 285 | @ <td valign="top"><ul> |
| 286 | } |
| 287 | @ <li><a href="%R/help?cmd=%s(z)">%s(zBoldOn)%s(z)%s(zBoldOff)</a></li> |
| 288 | j++; |
| 289 | if( j>=n ){ |
| 290 | @ </ul></td> |
| 291 | j = 0; |
| 292 | } |
| @@ -360,11 +365,11 @@ | |
| 365 | ** |
| 366 | ** Show all help text on a single page. Useful for proof-reading. |
| 367 | */ |
| 368 | void test_all_help_page(void){ |
| 369 | int i; |
| 370 | style_header("All Help Text"); |
| 371 | for(i=0; i<MX_COMMAND; i++){ |
| 372 | if( memcmp(aCommand[i].zName, "test", 4)==0 ) continue; |
| 373 | @ <h2>%s(aCommand[i].zName):</h2> |
| 374 | @ <blockquote> |
| 375 | help_to_html(aCommand[i].zHelp, cgi_output_blob()); |
| @@ -402,11 +407,11 @@ | |
| 407 | */ |
| 408 | void cmd_test_webpage_list(void){ |
| 409 | int i, nCmd; |
| 410 | const char *aCmd[MX_COMMAND]; |
| 411 | for(i=nCmd=0; i<MX_COMMAND; i++){ |
| 412 | if(CMDFLAG_WEBPAGE & aCommand[i].eCmdFlags){ |
| 413 | aCmd[nCmd++] = aCommand[i].zName; |
| 414 | } |
| 415 | } |
| 416 | assert(nCmd && "page list is empty?"); |
| 417 | multi_column_list(aCmd, nCmd); |
| 418 |
+10
-10
| --- src/doc.c | ||
| +++ src/doc.c | ||
| @@ -54,11 +54,11 @@ | ||
| 54 | 54 | if( !looks_like_binary(pBlob) ) { |
| 55 | 55 | return 0; /* Plain text */ |
| 56 | 56 | } |
| 57 | 57 | x = (const unsigned char*)blob_buffer(pBlob); |
| 58 | 58 | n = blob_size(pBlob); |
| 59 | - for(i=0; i<ArraySize(aMime); i++){ | |
| 59 | + for(i=0; i<count(aMime); i++){ | |
| 60 | 60 | if( n>=aMime[i].size && memcmp(x, aMime[i].zPrefix, aMime[i].size)==0 ){ |
| 61 | 61 | return aMime[i].zMimetype; |
| 62 | 62 | } |
| 63 | 63 | } |
| 64 | 64 | return "unknown/unknown"; |
| @@ -293,11 +293,11 @@ | ||
| 293 | 293 | ** Verify that all entries in the aMime[] table are in sorted order. |
| 294 | 294 | ** Abort with a fatal error if any is out-of-order. |
| 295 | 295 | */ |
| 296 | 296 | static void mimetype_verify(void){ |
| 297 | 297 | int i; |
| 298 | - for(i=1; i<ArraySize(aMime); i++){ | |
| 298 | + for(i=1; i<count(aMime); i++){ | |
| 299 | 299 | if( fossil_strcmp(aMime[i-1].zSuffix,aMime[i].zSuffix)>=0 ){ |
| 300 | 300 | fossil_fatal("mimetypes out of sequence: %s before %s", |
| 301 | 301 | aMime[i-1].zSuffix, aMime[i].zSuffix); |
| 302 | 302 | } |
| 303 | 303 | } |
| @@ -331,11 +331,11 @@ | ||
| 331 | 331 | len = strlen(z); |
| 332 | 332 | if( len<sizeof(zSuffix)-1 ){ |
| 333 | 333 | sqlite3_snprintf(sizeof(zSuffix), zSuffix, "%s", z); |
| 334 | 334 | for(i=0; zSuffix[i]; i++) zSuffix[i] = fossil_tolower(zSuffix[i]); |
| 335 | 335 | first = 0; |
| 336 | - last = ArraySize(aMime) - 1; | |
| 336 | + last = count(aMime) - 1; | |
| 337 | 337 | while( first<=last ){ |
| 338 | 338 | int c; |
| 339 | 339 | i = (first+last)/2; |
| 340 | 340 | c = fossil_strcmp(zSuffix, aMime[i].zSuffix); |
| 341 | 341 | if( c==0 ) return aMime[i].zMimetype; |
| @@ -384,11 +384,11 @@ | ||
| 384 | 384 | @ <table id='mimeTable' border=1 cellpadding=0 class='mimetypetable'> |
| 385 | 385 | @ <thead> |
| 386 | 386 | @ <tr><th>Suffix<th>Mimetype |
| 387 | 387 | @ </thead> |
| 388 | 388 | @ <tbody> |
| 389 | - for(i=0; i<ArraySize(aMime); i++){ | |
| 389 | + for(i=0; i<count(aMime); i++){ | |
| 390 | 390 | @ <tr><td>%h(aMime[i].zSuffix)<td>%h(aMime[i].zMimetype)</tr> |
| 391 | 391 | } |
| 392 | 392 | @ </tbody></table> |
| 393 | 393 | output_table_sorting_javascript("mimeTable","tt",1); |
| 394 | 394 | style_footer(); |
| @@ -593,11 +593,11 @@ | ||
| 593 | 593 | login_check_credentials(); |
| 594 | 594 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 595 | 595 | blob_init(&title, 0, 0); |
| 596 | 596 | zDfltTitle = isUV ? "" : "Documentation"; |
| 597 | 597 | db_begin_transaction(); |
| 598 | - while( rid==0 && (++nMiss)<=ArraySize(azSuffix) ){ | |
| 598 | + while( rid==0 && (++nMiss)<=count(azSuffix) ){ | |
| 599 | 599 | zName = P("name"); |
| 600 | 600 | if( isUV ){ |
| 601 | 601 | if( zName==0 ) zName = "index.wiki"; |
| 602 | 602 | i = 0; |
| 603 | 603 | }else{ |
| @@ -606,14 +606,14 @@ | ||
| 606 | 606 | zCheckin = mprintf("%.*s", i, zName); |
| 607 | 607 | if( fossil_strcmp(zCheckin,"ckout")==0 && g.localOpen==0 ){ |
| 608 | 608 | zCheckin = "tip"; |
| 609 | 609 | } |
| 610 | 610 | } |
| 611 | - if( nMiss==ArraySize(azSuffix) ){ | |
| 611 | + if( nMiss==count(azSuffix) ){ | |
| 612 | 612 | zName = "404.md"; |
| 613 | 613 | }else if( zName[i]==0 ){ |
| 614 | - assert( nMiss>=0 && nMiss<ArraySize(azSuffix) ); | |
| 614 | + assert( nMiss>=0 && nMiss<count(azSuffix) ); | |
| 615 | 615 | zName = azSuffix[nMiss]; |
| 616 | 616 | }else if( !isUV ){ |
| 617 | 617 | zName += i; |
| 618 | 618 | } |
| 619 | 619 | while( zName[0]=='/' ){ zName++; } |
| @@ -623,11 +623,11 @@ | ||
| 623 | 623 | g.zPath = mprintf("%s/%s/%s", g.zPath, zCheckin, zName); |
| 624 | 624 | } |
| 625 | 625 | if( nMiss==0 ) zOrigName = zName; |
| 626 | 626 | if( !file_is_simple_pathname(zName, 1) ){ |
| 627 | 627 | if( sqlite3_strglob("*/", zName)==0 ){ |
| 628 | - assert( nMiss>=0 && nMiss<ArraySize(azSuffix) ); | |
| 628 | + assert( nMiss>=0 && nMiss<count(azSuffix) ); | |
| 629 | 629 | zName = mprintf("%s%s", zName, azSuffix[nMiss]); |
| 630 | 630 | if( !file_is_simple_pathname(zName, 1) ){ |
| 631 | 631 | goto doc_not_found; |
| 632 | 632 | } |
| 633 | 633 | }else{ |
| @@ -686,11 +686,11 @@ | ||
| 686 | 686 | Blob tail = BLOB_INITIALIZER; |
| 687 | 687 | markdown_to_html(&filebody, &title, &tail); |
| 688 | 688 | if( blob_size(&title)>0 ){ |
| 689 | 689 | style_header("%s", blob_str(&title)); |
| 690 | 690 | }else{ |
| 691 | - style_header("%s", nMiss>=ArraySize(azSuffix)? | |
| 691 | + style_header("%s", nMiss>=count(azSuffix)? | |
| 692 | 692 | "Not Found" : zDfltTitle); |
| 693 | 693 | } |
| 694 | 694 | convert_href_and_output(&tail); |
| 695 | 695 | style_footer(); |
| 696 | 696 | }else if( fossil_strcmp(zMime, "text/plain")==0 ){ |
| @@ -719,11 +719,11 @@ | ||
| 719 | 719 | #endif |
| 720 | 720 | }else{ |
| 721 | 721 | cgi_set_content_type(zMime); |
| 722 | 722 | cgi_set_content(&filebody); |
| 723 | 723 | } |
| 724 | - if( nMiss>=ArraySize(azSuffix) ) cgi_set_status(404, "Not Found"); | |
| 724 | + if( nMiss>=count(azSuffix) ) cgi_set_status(404, "Not Found"); | |
| 725 | 725 | db_end_transaction(0); |
| 726 | 726 | return; |
| 727 | 727 | |
| 728 | 728 | /* Jump here when unable to locate the document */ |
| 729 | 729 | doc_not_found: |
| 730 | 730 |
| --- src/doc.c | |
| +++ src/doc.c | |
| @@ -54,11 +54,11 @@ | |
| 54 | if( !looks_like_binary(pBlob) ) { |
| 55 | return 0; /* Plain text */ |
| 56 | } |
| 57 | x = (const unsigned char*)blob_buffer(pBlob); |
| 58 | n = blob_size(pBlob); |
| 59 | for(i=0; i<ArraySize(aMime); i++){ |
| 60 | if( n>=aMime[i].size && memcmp(x, aMime[i].zPrefix, aMime[i].size)==0 ){ |
| 61 | return aMime[i].zMimetype; |
| 62 | } |
| 63 | } |
| 64 | return "unknown/unknown"; |
| @@ -293,11 +293,11 @@ | |
| 293 | ** Verify that all entries in the aMime[] table are in sorted order. |
| 294 | ** Abort with a fatal error if any is out-of-order. |
| 295 | */ |
| 296 | static void mimetype_verify(void){ |
| 297 | int i; |
| 298 | for(i=1; i<ArraySize(aMime); i++){ |
| 299 | if( fossil_strcmp(aMime[i-1].zSuffix,aMime[i].zSuffix)>=0 ){ |
| 300 | fossil_fatal("mimetypes out of sequence: %s before %s", |
| 301 | aMime[i-1].zSuffix, aMime[i].zSuffix); |
| 302 | } |
| 303 | } |
| @@ -331,11 +331,11 @@ | |
| 331 | len = strlen(z); |
| 332 | if( len<sizeof(zSuffix)-1 ){ |
| 333 | sqlite3_snprintf(sizeof(zSuffix), zSuffix, "%s", z); |
| 334 | for(i=0; zSuffix[i]; i++) zSuffix[i] = fossil_tolower(zSuffix[i]); |
| 335 | first = 0; |
| 336 | last = ArraySize(aMime) - 1; |
| 337 | while( first<=last ){ |
| 338 | int c; |
| 339 | i = (first+last)/2; |
| 340 | c = fossil_strcmp(zSuffix, aMime[i].zSuffix); |
| 341 | if( c==0 ) return aMime[i].zMimetype; |
| @@ -384,11 +384,11 @@ | |
| 384 | @ <table id='mimeTable' border=1 cellpadding=0 class='mimetypetable'> |
| 385 | @ <thead> |
| 386 | @ <tr><th>Suffix<th>Mimetype |
| 387 | @ </thead> |
| 388 | @ <tbody> |
| 389 | for(i=0; i<ArraySize(aMime); i++){ |
| 390 | @ <tr><td>%h(aMime[i].zSuffix)<td>%h(aMime[i].zMimetype)</tr> |
| 391 | } |
| 392 | @ </tbody></table> |
| 393 | output_table_sorting_javascript("mimeTable","tt",1); |
| 394 | style_footer(); |
| @@ -593,11 +593,11 @@ | |
| 593 | login_check_credentials(); |
| 594 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 595 | blob_init(&title, 0, 0); |
| 596 | zDfltTitle = isUV ? "" : "Documentation"; |
| 597 | db_begin_transaction(); |
| 598 | while( rid==0 && (++nMiss)<=ArraySize(azSuffix) ){ |
| 599 | zName = P("name"); |
| 600 | if( isUV ){ |
| 601 | if( zName==0 ) zName = "index.wiki"; |
| 602 | i = 0; |
| 603 | }else{ |
| @@ -606,14 +606,14 @@ | |
| 606 | zCheckin = mprintf("%.*s", i, zName); |
| 607 | if( fossil_strcmp(zCheckin,"ckout")==0 && g.localOpen==0 ){ |
| 608 | zCheckin = "tip"; |
| 609 | } |
| 610 | } |
| 611 | if( nMiss==ArraySize(azSuffix) ){ |
| 612 | zName = "404.md"; |
| 613 | }else if( zName[i]==0 ){ |
| 614 | assert( nMiss>=0 && nMiss<ArraySize(azSuffix) ); |
| 615 | zName = azSuffix[nMiss]; |
| 616 | }else if( !isUV ){ |
| 617 | zName += i; |
| 618 | } |
| 619 | while( zName[0]=='/' ){ zName++; } |
| @@ -623,11 +623,11 @@ | |
| 623 | g.zPath = mprintf("%s/%s/%s", g.zPath, zCheckin, zName); |
| 624 | } |
| 625 | if( nMiss==0 ) zOrigName = zName; |
| 626 | if( !file_is_simple_pathname(zName, 1) ){ |
| 627 | if( sqlite3_strglob("*/", zName)==0 ){ |
| 628 | assert( nMiss>=0 && nMiss<ArraySize(azSuffix) ); |
| 629 | zName = mprintf("%s%s", zName, azSuffix[nMiss]); |
| 630 | if( !file_is_simple_pathname(zName, 1) ){ |
| 631 | goto doc_not_found; |
| 632 | } |
| 633 | }else{ |
| @@ -686,11 +686,11 @@ | |
| 686 | Blob tail = BLOB_INITIALIZER; |
| 687 | markdown_to_html(&filebody, &title, &tail); |
| 688 | if( blob_size(&title)>0 ){ |
| 689 | style_header("%s", blob_str(&title)); |
| 690 | }else{ |
| 691 | style_header("%s", nMiss>=ArraySize(azSuffix)? |
| 692 | "Not Found" : zDfltTitle); |
| 693 | } |
| 694 | convert_href_and_output(&tail); |
| 695 | style_footer(); |
| 696 | }else if( fossil_strcmp(zMime, "text/plain")==0 ){ |
| @@ -719,11 +719,11 @@ | |
| 719 | #endif |
| 720 | }else{ |
| 721 | cgi_set_content_type(zMime); |
| 722 | cgi_set_content(&filebody); |
| 723 | } |
| 724 | if( nMiss>=ArraySize(azSuffix) ) cgi_set_status(404, "Not Found"); |
| 725 | db_end_transaction(0); |
| 726 | return; |
| 727 | |
| 728 | /* Jump here when unable to locate the document */ |
| 729 | doc_not_found: |
| 730 |
| --- src/doc.c | |
| +++ src/doc.c | |
| @@ -54,11 +54,11 @@ | |
| 54 | if( !looks_like_binary(pBlob) ) { |
| 55 | return 0; /* Plain text */ |
| 56 | } |
| 57 | x = (const unsigned char*)blob_buffer(pBlob); |
| 58 | n = blob_size(pBlob); |
| 59 | for(i=0; i<count(aMime); i++){ |
| 60 | if( n>=aMime[i].size && memcmp(x, aMime[i].zPrefix, aMime[i].size)==0 ){ |
| 61 | return aMime[i].zMimetype; |
| 62 | } |
| 63 | } |
| 64 | return "unknown/unknown"; |
| @@ -293,11 +293,11 @@ | |
| 293 | ** Verify that all entries in the aMime[] table are in sorted order. |
| 294 | ** Abort with a fatal error if any is out-of-order. |
| 295 | */ |
| 296 | static void mimetype_verify(void){ |
| 297 | int i; |
| 298 | for(i=1; i<count(aMime); i++){ |
| 299 | if( fossil_strcmp(aMime[i-1].zSuffix,aMime[i].zSuffix)>=0 ){ |
| 300 | fossil_fatal("mimetypes out of sequence: %s before %s", |
| 301 | aMime[i-1].zSuffix, aMime[i].zSuffix); |
| 302 | } |
| 303 | } |
| @@ -331,11 +331,11 @@ | |
| 331 | len = strlen(z); |
| 332 | if( len<sizeof(zSuffix)-1 ){ |
| 333 | sqlite3_snprintf(sizeof(zSuffix), zSuffix, "%s", z); |
| 334 | for(i=0; zSuffix[i]; i++) zSuffix[i] = fossil_tolower(zSuffix[i]); |
| 335 | first = 0; |
| 336 | last = count(aMime) - 1; |
| 337 | while( first<=last ){ |
| 338 | int c; |
| 339 | i = (first+last)/2; |
| 340 | c = fossil_strcmp(zSuffix, aMime[i].zSuffix); |
| 341 | if( c==0 ) return aMime[i].zMimetype; |
| @@ -384,11 +384,11 @@ | |
| 384 | @ <table id='mimeTable' border=1 cellpadding=0 class='mimetypetable'> |
| 385 | @ <thead> |
| 386 | @ <tr><th>Suffix<th>Mimetype |
| 387 | @ </thead> |
| 388 | @ <tbody> |
| 389 | for(i=0; i<count(aMime); i++){ |
| 390 | @ <tr><td>%h(aMime[i].zSuffix)<td>%h(aMime[i].zMimetype)</tr> |
| 391 | } |
| 392 | @ </tbody></table> |
| 393 | output_table_sorting_javascript("mimeTable","tt",1); |
| 394 | style_footer(); |
| @@ -593,11 +593,11 @@ | |
| 593 | login_check_credentials(); |
| 594 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 595 | blob_init(&title, 0, 0); |
| 596 | zDfltTitle = isUV ? "" : "Documentation"; |
| 597 | db_begin_transaction(); |
| 598 | while( rid==0 && (++nMiss)<=count(azSuffix) ){ |
| 599 | zName = P("name"); |
| 600 | if( isUV ){ |
| 601 | if( zName==0 ) zName = "index.wiki"; |
| 602 | i = 0; |
| 603 | }else{ |
| @@ -606,14 +606,14 @@ | |
| 606 | zCheckin = mprintf("%.*s", i, zName); |
| 607 | if( fossil_strcmp(zCheckin,"ckout")==0 && g.localOpen==0 ){ |
| 608 | zCheckin = "tip"; |
| 609 | } |
| 610 | } |
| 611 | if( nMiss==count(azSuffix) ){ |
| 612 | zName = "404.md"; |
| 613 | }else if( zName[i]==0 ){ |
| 614 | assert( nMiss>=0 && nMiss<count(azSuffix) ); |
| 615 | zName = azSuffix[nMiss]; |
| 616 | }else if( !isUV ){ |
| 617 | zName += i; |
| 618 | } |
| 619 | while( zName[0]=='/' ){ zName++; } |
| @@ -623,11 +623,11 @@ | |
| 623 | g.zPath = mprintf("%s/%s/%s", g.zPath, zCheckin, zName); |
| 624 | } |
| 625 | if( nMiss==0 ) zOrigName = zName; |
| 626 | if( !file_is_simple_pathname(zName, 1) ){ |
| 627 | if( sqlite3_strglob("*/", zName)==0 ){ |
| 628 | assert( nMiss>=0 && nMiss<count(azSuffix) ); |
| 629 | zName = mprintf("%s%s", zName, azSuffix[nMiss]); |
| 630 | if( !file_is_simple_pathname(zName, 1) ){ |
| 631 | goto doc_not_found; |
| 632 | } |
| 633 | }else{ |
| @@ -686,11 +686,11 @@ | |
| 686 | Blob tail = BLOB_INITIALIZER; |
| 687 | markdown_to_html(&filebody, &title, &tail); |
| 688 | if( blob_size(&title)>0 ){ |
| 689 | style_header("%s", blob_str(&title)); |
| 690 | }else{ |
| 691 | style_header("%s", nMiss>=count(azSuffix)? |
| 692 | "Not Found" : zDfltTitle); |
| 693 | } |
| 694 | convert_href_and_output(&tail); |
| 695 | style_footer(); |
| 696 | }else if( fossil_strcmp(zMime, "text/plain")==0 ){ |
| @@ -719,11 +719,11 @@ | |
| 719 | #endif |
| 720 | }else{ |
| 721 | cgi_set_content_type(zMime); |
| 722 | cgi_set_content(&filebody); |
| 723 | } |
| 724 | if( nMiss>=count(azSuffix) ) cgi_set_status(404, "Not Found"); |
| 725 | db_end_transaction(0); |
| 726 | return; |
| 727 | |
| 728 | /* Jump here when unable to locate the document */ |
| 729 | doc_not_found: |
| 730 |
+8
-9
| --- src/event.c | ||
| +++ src/event.c | ||
| @@ -152,40 +152,39 @@ | ||
| 152 | 152 | blob_appendf(&title, "Tech-note %S", zId); |
| 153 | 153 | tail = fullbody; |
| 154 | 154 | } |
| 155 | 155 | style_header("%s", blob_str(&title)); |
| 156 | 156 | if( g.perm.WrWiki && g.perm.Write && nextRid==0 ){ |
| 157 | - style_submenu_element("Edit", 0, "%R/technoteedit?name=%!S", zId); | |
| 157 | + style_submenu_element("Edit", "%R/technoteedit?name=%!S", zId); | |
| 158 | 158 | if( g.perm.Attach ){ |
| 159 | - style_submenu_element("Attach", "Add an attachment", | |
| 160 | - "%R/attachadd?technote=%!S&from=%R/technote/%!S", | |
| 161 | - zId, zId); | |
| 159 | + style_submenu_element("Attach", | |
| 160 | + "%R/attachadd?technote=%!S&from=%R/technote/%!S", zId, zId); | |
| 162 | 161 | } |
| 163 | 162 | } |
| 164 | 163 | zETime = db_text(0, "SELECT datetime(%.17g)", pTNote->rEventDate); |
| 165 | - style_submenu_element("Context", 0, "%R/timeline?c=%.20s", zId); | |
| 164 | + style_submenu_element("Context", "%R/timeline?c=%.20s", zId); | |
| 166 | 165 | if( g.perm.Hyperlink ){ |
| 167 | 166 | if( verboseFlag ){ |
| 168 | - style_submenu_element("Plain", 0, | |
| 167 | + style_submenu_element("Plain", | |
| 169 | 168 | "%R/technote?name=%!S&aid=%s&mimetype=text/plain", |
| 170 | 169 | zId, zUuid); |
| 171 | 170 | if( nextRid ){ |
| 172 | 171 | char *zNext; |
| 173 | 172 | zNext = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nextRid); |
| 174 | - style_submenu_element("Next", 0,"%R/technote?name=%!S&aid=%s&v", | |
| 173 | + style_submenu_element("Next", "%R/technote?name=%!S&aid=%s&v", | |
| 175 | 174 | zId, zNext); |
| 176 | 175 | free(zNext); |
| 177 | 176 | } |
| 178 | 177 | if( prevRid ){ |
| 179 | 178 | char *zPrev; |
| 180 | 179 | zPrev = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", prevRid); |
| 181 | - style_submenu_element("Prev", 0, "%R/technote?name=%!S&aid=%s&v", | |
| 180 | + style_submenu_element("Prev", "%R/technote?name=%!S&aid=%s&v", | |
| 182 | 181 | zId, zPrev); |
| 183 | 182 | free(zPrev); |
| 184 | 183 | } |
| 185 | 184 | }else{ |
| 186 | - style_submenu_element("Detail", 0, "%R/technote?name=%!S&aid=%s&v", | |
| 185 | + style_submenu_element("Detail", "%R/technote?name=%!S&aid=%s&v", | |
| 187 | 186 | zId, zUuid); |
| 188 | 187 | } |
| 189 | 188 | } |
| 190 | 189 | |
| 191 | 190 | if( verboseFlag && g.perm.Hyperlink ){ |
| 192 | 191 |
| --- src/event.c | |
| +++ src/event.c | |
| @@ -152,40 +152,39 @@ | |
| 152 | blob_appendf(&title, "Tech-note %S", zId); |
| 153 | tail = fullbody; |
| 154 | } |
| 155 | style_header("%s", blob_str(&title)); |
| 156 | if( g.perm.WrWiki && g.perm.Write && nextRid==0 ){ |
| 157 | style_submenu_element("Edit", 0, "%R/technoteedit?name=%!S", zId); |
| 158 | if( g.perm.Attach ){ |
| 159 | style_submenu_element("Attach", "Add an attachment", |
| 160 | "%R/attachadd?technote=%!S&from=%R/technote/%!S", |
| 161 | zId, zId); |
| 162 | } |
| 163 | } |
| 164 | zETime = db_text(0, "SELECT datetime(%.17g)", pTNote->rEventDate); |
| 165 | style_submenu_element("Context", 0, "%R/timeline?c=%.20s", zId); |
| 166 | if( g.perm.Hyperlink ){ |
| 167 | if( verboseFlag ){ |
| 168 | style_submenu_element("Plain", 0, |
| 169 | "%R/technote?name=%!S&aid=%s&mimetype=text/plain", |
| 170 | zId, zUuid); |
| 171 | if( nextRid ){ |
| 172 | char *zNext; |
| 173 | zNext = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nextRid); |
| 174 | style_submenu_element("Next", 0,"%R/technote?name=%!S&aid=%s&v", |
| 175 | zId, zNext); |
| 176 | free(zNext); |
| 177 | } |
| 178 | if( prevRid ){ |
| 179 | char *zPrev; |
| 180 | zPrev = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", prevRid); |
| 181 | style_submenu_element("Prev", 0, "%R/technote?name=%!S&aid=%s&v", |
| 182 | zId, zPrev); |
| 183 | free(zPrev); |
| 184 | } |
| 185 | }else{ |
| 186 | style_submenu_element("Detail", 0, "%R/technote?name=%!S&aid=%s&v", |
| 187 | zId, zUuid); |
| 188 | } |
| 189 | } |
| 190 | |
| 191 | if( verboseFlag && g.perm.Hyperlink ){ |
| 192 |
| --- src/event.c | |
| +++ src/event.c | |
| @@ -152,40 +152,39 @@ | |
| 152 | blob_appendf(&title, "Tech-note %S", zId); |
| 153 | tail = fullbody; |
| 154 | } |
| 155 | style_header("%s", blob_str(&title)); |
| 156 | if( g.perm.WrWiki && g.perm.Write && nextRid==0 ){ |
| 157 | style_submenu_element("Edit", "%R/technoteedit?name=%!S", zId); |
| 158 | if( g.perm.Attach ){ |
| 159 | style_submenu_element("Attach", |
| 160 | "%R/attachadd?technote=%!S&from=%R/technote/%!S", zId, zId); |
| 161 | } |
| 162 | } |
| 163 | zETime = db_text(0, "SELECT datetime(%.17g)", pTNote->rEventDate); |
| 164 | style_submenu_element("Context", "%R/timeline?c=%.20s", zId); |
| 165 | if( g.perm.Hyperlink ){ |
| 166 | if( verboseFlag ){ |
| 167 | style_submenu_element("Plain", |
| 168 | "%R/technote?name=%!S&aid=%s&mimetype=text/plain", |
| 169 | zId, zUuid); |
| 170 | if( nextRid ){ |
| 171 | char *zNext; |
| 172 | zNext = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nextRid); |
| 173 | style_submenu_element("Next", "%R/technote?name=%!S&aid=%s&v", |
| 174 | zId, zNext); |
| 175 | free(zNext); |
| 176 | } |
| 177 | if( prevRid ){ |
| 178 | char *zPrev; |
| 179 | zPrev = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", prevRid); |
| 180 | style_submenu_element("Prev", "%R/technote?name=%!S&aid=%s&v", |
| 181 | zId, zPrev); |
| 182 | free(zPrev); |
| 183 | } |
| 184 | }else{ |
| 185 | style_submenu_element("Detail", "%R/technote?name=%!S&aid=%s&v", |
| 186 | zId, zUuid); |
| 187 | } |
| 188 | } |
| 189 | |
| 190 | if( verboseFlag && g.perm.Hyperlink ){ |
| 191 |
+91
-48
| --- src/export.c | ||
| +++ src/export.c | ||
| @@ -132,23 +132,28 @@ | ||
| 132 | 132 | |
| 133 | 133 | /* |
| 134 | 134 | ** create_mark() |
| 135 | 135 | ** Create a new (mark,rid,uuid) entry for the given rid in the 'xmark' table, |
| 136 | 136 | ** and return that information as a struct mark_t in *mark. |
| 137 | +** *unused_mark is a value representing a mark that is free for use--that is, | |
| 138 | +** it does not appear in the marks file, and has not been used during this | |
| 139 | +** export run. Specifically, it is the supremum of the set of used marks | |
| 140 | +** plus one. | |
| 137 | 141 | ** This function returns -1 in the case where 'rid' does not exist, otherwise |
| 138 | 142 | ** it returns 0. |
| 139 | 143 | ** mark->name is dynamically allocated and is owned by the caller upon return. |
| 140 | 144 | */ |
| 141 | -int create_mark(int rid, struct mark_t *mark){ | |
| 145 | +int create_mark(int rid, struct mark_t *mark, unsigned int *unused_mark){ | |
| 142 | 146 | char sid[13]; |
| 143 | 147 | char *zUuid = rid_to_uuid(rid); |
| 144 | - if(!zUuid){ | |
| 148 | + if( !zUuid ){ | |
| 145 | 149 | fossil_trace("Undefined rid=%d\n", rid); |
| 146 | 150 | return -1; |
| 147 | 151 | } |
| 148 | 152 | mark->rid = rid; |
| 149 | - sqlite3_snprintf(sizeof(sid), sid, ":%d", COMMITMARK(rid)); | |
| 153 | + sqlite3_snprintf(sizeof(sid), sid, ":%d", *unused_mark); | |
| 154 | + *unused_mark += 1; | |
| 150 | 155 | mark->name = fossil_strdup(sid); |
| 151 | 156 | sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", zUuid); |
| 152 | 157 | free(zUuid); |
| 153 | 158 | insert_commit_xref(mark->rid, mark->name, mark->uuid); |
| 154 | 159 | return 0; |
| @@ -156,19 +161,22 @@ | ||
| 156 | 161 | |
| 157 | 162 | /* |
| 158 | 163 | ** mark_name_from_rid() |
| 159 | 164 | ** Find the mark associated with the given rid. Mark names always start |
| 160 | 165 | ** with ':', and are pulled from the 'xmark' temporary table. |
| 161 | -** This function returns NULL if the rid does not exist in the 'xmark' table. | |
| 162 | -** Otherwise, it returns the name of the mark, which is dynamically allocated | |
| 163 | -** and is owned by the caller of this function. | |
| 166 | +** If the given rid doesn't have a mark associated with it yet, one is | |
| 167 | +** created with a value of *unused_mark. | |
| 168 | +** *unused_mark functions exactly as in create_mark(). | |
| 169 | +** This function returns NULL if the rid does not have an associated UUID, | |
| 170 | +** (i.e. is not valid). Otherwise, it returns the name of the mark, which is | |
| 171 | +** dynamically allocated and is owned by the caller of this function. | |
| 164 | 172 | */ |
| 165 | -char * mark_name_from_rid(int rid){ | |
| 173 | +char * mark_name_from_rid(int rid, unsigned int *unused_mark){ | |
| 166 | 174 | char *zMark = db_text(0, "SELECT tname FROM xmark WHERE trid=%d", rid); |
| 167 | - if(zMark==NULL){ | |
| 175 | + if( zMark==NULL ){ | |
| 168 | 176 | struct mark_t mark; |
| 169 | - if(create_mark(rid, &mark)==0){ | |
| 177 | + if( create_mark(rid, &mark, unused_mark)==0 ){ | |
| 170 | 178 | zMark = mark.name; |
| 171 | 179 | }else{ |
| 172 | 180 | return NULL; |
| 173 | 181 | } |
| 174 | 182 | } |
| @@ -185,43 +193,52 @@ | ||
| 185 | 193 | ** database. Otherwise, 0 is returned. |
| 186 | 194 | ** mark->name is dynamically allocated, and owned by the caller. |
| 187 | 195 | */ |
| 188 | 196 | int parse_mark(char *line, struct mark_t *mark){ |
| 189 | 197 | char *cur_tok; |
| 198 | + char type_; | |
| 190 | 199 | cur_tok = strtok(line, " \t"); |
| 191 | - if(!cur_tok||strlen(cur_tok)<2){ | |
| 200 | + if( !cur_tok || strlen(cur_tok)<2 ){ | |
| 192 | 201 | return -1; |
| 193 | 202 | } |
| 194 | 203 | mark->rid = atoi(&cur_tok[1]); |
| 195 | - if(cur_tok[0]!='c'){ | |
| 204 | + type_ = cur_tok[0]; | |
| 205 | + if( type_!='c' && type_!='b' ){ | |
| 196 | 206 | /* This is probably a blob mark */ |
| 197 | 207 | mark->name = NULL; |
| 198 | 208 | return 0; |
| 199 | 209 | } |
| 200 | 210 | |
| 201 | 211 | cur_tok = strtok(NULL, " \t"); |
| 202 | - if(!cur_tok){ | |
| 212 | + if( !cur_tok ){ | |
| 203 | 213 | /* This mark was generated by an older version of Fossil and doesn't |
| 204 | 214 | ** include the mark name and uuid. create_mark() will name the new mark |
| 205 | 215 | ** exactly as it was when exported to git, so that we should have a |
| 206 | 216 | ** valid mapping from git sha1<->mark name<->fossil sha1. */ |
| 207 | - return create_mark(mark->rid, mark); | |
| 217 | + unsigned int mid; | |
| 218 | + if( type_=='c' ){ | |
| 219 | + mid = COMMITMARK(mark->rid); | |
| 220 | + } | |
| 221 | + else{ | |
| 222 | + mid = BLOBMARK(mark->rid); | |
| 223 | + } | |
| 224 | + return create_mark(mark->rid, mark, &mid); | |
| 208 | 225 | }else{ |
| 209 | 226 | mark->name = fossil_strdup(cur_tok); |
| 210 | 227 | } |
| 211 | 228 | |
| 212 | 229 | cur_tok = strtok(NULL, "\n"); |
| 213 | - if(!cur_tok||strlen(cur_tok)!=40){ | |
| 230 | + if( !cur_tok || strlen(cur_tok)!=40 ){ | |
| 214 | 231 | free(mark->name); |
| 215 | 232 | fossil_trace("Invalid SHA-1 in marks file: %s\n", cur_tok); |
| 216 | 233 | return -1; |
| 217 | 234 | }else{ |
| 218 | 235 | sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", cur_tok); |
| 219 | 236 | } |
| 220 | 237 | |
| 221 | 238 | /* make sure that rid corresponds to UUID */ |
| 222 | - if(fast_uuid_to_rid(mark->uuid)!=mark->rid){ | |
| 239 | + if( fast_uuid_to_rid(mark->uuid)!=mark->rid ){ | |
| 223 | 240 | free(mark->name); |
| 224 | 241 | fossil_trace("Non-existent SHA-1 in marks file: %s\n", mark->uuid); |
| 225 | 242 | return -1; |
| 226 | 243 | } |
| 227 | 244 | |
| @@ -233,40 +250,66 @@ | ||
| 233 | 250 | /* |
| 234 | 251 | ** import_marks() |
| 235 | 252 | ** Import the marks specified in file 'f' into the 'xmark' table. |
| 236 | 253 | ** If 'blobs' is non-null, insert all blob marks into it. |
| 237 | 254 | ** If 'vers' is non-null, insert all commit marks into it. |
| 255 | +** If 'unused_marks' is non-null, upon return of this function, all values | |
| 256 | +** x >= *unused_marks are free to use as marks, i.e. they do not clash with | |
| 257 | +** any marks appearing in the marks file. | |
| 238 | 258 | ** Each line in the file must be at most 100 characters in length. This |
| 239 | 259 | ** seems like a reasonable maximum for a 40-character uuid, and 1-13 |
| 240 | 260 | ** character rid. |
| 241 | 261 | ** The function returns -1 if any of the lines in file 'f' are malformed, |
| 242 | 262 | ** or the rid/uuid information doesn't match what is in the repository |
| 243 | 263 | ** database. Otherwise, 0 is returned. |
| 244 | 264 | */ |
| 245 | -int import_marks(FILE* f, Bag *blobs, Bag *vers){ | |
| 265 | +int import_marks(FILE* f, Bag *blobs, Bag *vers, unsigned int *unused_mark){ | |
| 246 | 266 | char line[101]; |
| 247 | 267 | while(fgets(line, sizeof(line), f)){ |
| 248 | 268 | struct mark_t mark; |
| 249 | - if(strlen(line)==100&&line[99]!='\n'){ | |
| 269 | + if( strlen(line)==100 && line[99]!='\n' ){ | |
| 250 | 270 | /* line too long */ |
| 251 | 271 | return -1; |
| 252 | 272 | } |
| 253 | 273 | if( parse_mark(line, &mark)<0 ){ |
| 254 | 274 | return -1; |
| 255 | 275 | }else if( line[0]=='b' ){ |
| 256 | - /* Don't import blob marks into 'xmark' table--git doesn't use them, | |
| 257 | - ** so they need to be left free for git to reuse. */ | |
| 258 | - if(blobs!=NULL){ | |
| 276 | + if( blobs!=NULL ){ | |
| 259 | 277 | bag_insert(blobs, mark.rid); |
| 260 | 278 | } |
| 261 | - }else if( vers!=NULL ){ | |
| 262 | - bag_insert(vers, mark.rid); | |
| 279 | + }else{ | |
| 280 | + if( vers!=NULL ){ | |
| 281 | + bag_insert(vers, mark.rid); | |
| 282 | + } | |
| 283 | + } | |
| 284 | + if( unused_mark!=NULL ){ | |
| 285 | + unsigned int mid = atoi(mark.name + 1); | |
| 286 | + if( mid>=*unused_mark ){ | |
| 287 | + *unused_mark = mid + 1; | |
| 288 | + } | |
| 263 | 289 | } |
| 264 | 290 | free(mark.name); |
| 265 | 291 | } |
| 266 | 292 | return 0; |
| 267 | 293 | } |
| 294 | + | |
| 295 | +void export_mark(FILE* f, int rid, char obj_type) | |
| 296 | +{ | |
| 297 | + unsigned int z = 0; | |
| 298 | + char *zUuid = rid_to_uuid(rid); | |
| 299 | + char *zMark; | |
| 300 | + if( zUuid==NULL ){ | |
| 301 | + fossil_trace("No uuid matching rid=%d when exporting marks\n", rid); | |
| 302 | + return; | |
| 303 | + } | |
| 304 | + /* Since rid is already in the 'xmark' table, the value of z won't be | |
| 305 | + ** used, but pass in a valid pointer just to be safe. */ | |
| 306 | + zMark = mark_name_from_rid(rid, &z); | |
| 307 | + fprintf(f, "%c%d %s %s\n", obj_type, rid, zMark, zUuid); | |
| 308 | + free(zMark); | |
| 309 | + free(zUuid); | |
| 310 | +} | |
| 268 | 311 | |
| 269 | 312 | /* |
| 270 | 313 | ** If 'blobs' is non-null, it must point to a Bag of blob rids to be |
| 271 | 314 | ** written to disk. Blob rids are written as 'b<rid>'. |
| 272 | 315 | ** If 'vers' is non-null, it must point to a Bag of commit rids to be |
| @@ -275,32 +318,24 @@ | ||
| 275 | 318 | ** This function does not fail, but may produce errors if a uuid cannot |
| 276 | 319 | ** be found for an rid in 'vers'. |
| 277 | 320 | */ |
| 278 | 321 | void export_marks(FILE* f, Bag *blobs, Bag *vers){ |
| 279 | 322 | int rid; |
| 323 | + | |
| 280 | 324 | if( blobs!=NULL ){ |
| 281 | 325 | rid = bag_first(blobs); |
| 282 | - if(rid!=0){ | |
| 326 | + if( rid!=0 ){ | |
| 283 | 327 | do{ |
| 284 | - fprintf(f, "b%d\n", rid); | |
| 285 | - }while((rid = bag_next(blobs, rid))!=0); | |
| 328 | + export_mark(f, rid, 'b'); | |
| 329 | + }while( (rid = bag_next(blobs, rid))!=0 ); | |
| 286 | 330 | } |
| 287 | 331 | } |
| 288 | 332 | if( vers!=NULL ){ |
| 289 | 333 | rid = bag_first(vers); |
| 290 | 334 | if( rid!=0 ){ |
| 291 | 335 | do{ |
| 292 | - char *zUuid = rid_to_uuid(rid); | |
| 293 | - char *zMark; | |
| 294 | - if(zUuid==NULL){ | |
| 295 | - fossil_trace("No uuid matching rid=%d when exporting marks\n", rid); | |
| 296 | - continue; | |
| 297 | - } | |
| 298 | - zMark = mark_name_from_rid(rid); | |
| 299 | - fprintf(f, "c%d %s %s\n", rid, zMark, zUuid); | |
| 300 | - free(zMark); | |
| 301 | - free(zUuid); | |
| 336 | + export_mark(f, rid, 'c'); | |
| 302 | 337 | }while( (rid = bag_next(vers, rid))!=0 ); |
| 303 | 338 | } |
| 304 | 339 | } |
| 305 | 340 | } |
| 306 | 341 | |
| @@ -336,10 +371,11 @@ | ||
| 336 | 371 | */ |
| 337 | 372 | void export_cmd(void){ |
| 338 | 373 | Stmt q, q2, q3; |
| 339 | 374 | int i; |
| 340 | 375 | Bag blobs, vers; |
| 376 | + unsigned int unused_mark = 1; | |
| 341 | 377 | const char *markfile_in; |
| 342 | 378 | const char *markfile_out; |
| 343 | 379 | |
| 344 | 380 | bag_init(&blobs); |
| 345 | 381 | bag_init(&vers); |
| @@ -362,25 +398,25 @@ | ||
| 362 | 398 | |
| 363 | 399 | f = fossil_fopen(markfile_in, "r"); |
| 364 | 400 | if( f==0 ){ |
| 365 | 401 | fossil_fatal("cannot open %s for reading", markfile_in); |
| 366 | 402 | } |
| 367 | - if(import_marks(f, &blobs, &vers)<0){ | |
| 368 | - fossil_fatal("error importing marks from file: %s\n", markfile_in); | |
| 403 | + if( import_marks(f, &blobs, &vers, &unused_mark)<0 ){ | |
| 404 | + fossil_fatal("error importing marks from file: %s", markfile_in); | |
| 369 | 405 | } |
| 370 | 406 | db_prepare(&qb, "INSERT OR IGNORE INTO oldblob VALUES (:rid)"); |
| 371 | 407 | db_prepare(&qc, "INSERT OR IGNORE INTO oldcommit VALUES (:rid)"); |
| 372 | 408 | rid = bag_first(&blobs); |
| 373 | - if(rid!=0){ | |
| 409 | + if( rid!=0 ){ | |
| 374 | 410 | do{ |
| 375 | 411 | db_bind_int(&qb, ":rid", rid); |
| 376 | 412 | db_step(&qb); |
| 377 | 413 | db_reset(&qb); |
| 378 | 414 | }while((rid = bag_next(&blobs, rid))!=0); |
| 379 | 415 | } |
| 380 | 416 | rid = bag_first(&vers); |
| 381 | - if(rid!=0){ | |
| 417 | + if( rid!=0 ){ | |
| 382 | 418 | do{ |
| 383 | 419 | db_bind_int(&qc, ":rid", rid); |
| 384 | 420 | db_step(&qc); |
| 385 | 421 | db_reset(&qc); |
| 386 | 422 | }while((rid = bag_next(&vers, rid))!=0); |
| @@ -416,15 +452,18 @@ | ||
| 416 | 452 | while( db_step(&q)==SQLITE_ROW ){ |
| 417 | 453 | int rid = db_column_int(&q, 0); |
| 418 | 454 | Blob content; |
| 419 | 455 | |
| 420 | 456 | while( !bag_find(&blobs, rid) ){ |
| 457 | + char *zMark; | |
| 421 | 458 | content_get(rid, &content); |
| 422 | 459 | db_bind_int(&q2, ":rid", rid); |
| 423 | 460 | db_step(&q2); |
| 424 | 461 | db_reset(&q2); |
| 425 | - printf("blob\nmark :%d\ndata %d\n", BLOBMARK(rid), blob_size(&content)); | |
| 462 | + zMark = mark_name_from_rid(rid, &unused_mark); | |
| 463 | + printf("blob\nmark %s\ndata %d\n", zMark, blob_size(&content)); | |
| 464 | + free(zMark); | |
| 426 | 465 | bag_insert(&blobs, rid); |
| 427 | 466 | fwrite(blob_buffer(&content), 1, blob_size(&content), stdout); |
| 428 | 467 | printf("\n"); |
| 429 | 468 | blob_reset(&content); |
| 430 | 469 | |
| @@ -470,11 +509,11 @@ | ||
| 470 | 509 | if( zBranch==0 ) zBranch = "trunk"; |
| 471 | 510 | zBr = mprintf("%s", zBranch); |
| 472 | 511 | for(i=0; zBr[i]; i++){ |
| 473 | 512 | if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_'; |
| 474 | 513 | } |
| 475 | - zMark = mark_name_from_rid(ckinId); | |
| 514 | + zMark = mark_name_from_rid(ckinId, &unused_mark); | |
| 476 | 515 | printf("commit refs/heads/%s\nmark %s\n", zBr, zMark); |
| 477 | 516 | free(zMark); |
| 478 | 517 | free(zBr); |
| 479 | 518 | printf("committer"); |
| 480 | 519 | print_person(zUser); |
| @@ -487,21 +526,21 @@ | ||
| 487 | 526 | " AND pid IN (SELECT objid FROM event)", |
| 488 | 527 | ckinId |
| 489 | 528 | ); |
| 490 | 529 | if( db_step(&q3) == SQLITE_ROW ){ |
| 491 | 530 | int pid = db_column_int(&q3, 0); |
| 492 | - zMark = mark_name_from_rid(pid); | |
| 531 | + zMark = mark_name_from_rid(pid, &unused_mark); | |
| 493 | 532 | printf("from %s\n", zMark); |
| 494 | 533 | free(zMark); |
| 495 | 534 | db_prepare(&q4, |
| 496 | 535 | "SELECT pid FROM plink" |
| 497 | 536 | " WHERE cid=%d AND NOT isprim" |
| 498 | 537 | " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)" |
| 499 | 538 | " ORDER BY pid", |
| 500 | 539 | ckinId); |
| 501 | 540 | while( db_step(&q4)==SQLITE_ROW ){ |
| 502 | - zMark = mark_name_from_rid(db_column_int(&q4, 0)); | |
| 541 | + zMark = mark_name_from_rid(db_column_int(&q4, 0), &unused_mark); | |
| 503 | 542 | printf("merge %s\n", zMark); |
| 504 | 543 | free(zMark); |
| 505 | 544 | } |
| 506 | 545 | db_finalize(&q4); |
| 507 | 546 | }else{ |
| @@ -516,20 +555,22 @@ | ||
| 516 | 555 | ); |
| 517 | 556 | while( db_step(&q4)==SQLITE_ROW ){ |
| 518 | 557 | const char *zName = db_column_text(&q4,0); |
| 519 | 558 | int zNew = db_column_int(&q4,1); |
| 520 | 559 | int mPerm = db_column_int(&q4,2); |
| 521 | - if( zNew==0) | |
| 560 | + if( zNew==0 ){ | |
| 522 | 561 | printf("D %s\n", zName); |
| 523 | - else if( bag_find(&blobs, zNew) ) { | |
| 562 | + }else if( bag_find(&blobs, zNew) ){ | |
| 524 | 563 | const char *zPerm; |
| 564 | + zMark = mark_name_from_rid(zNew, &unused_mark); | |
| 525 | 565 | switch( mPerm ){ |
| 526 | 566 | case PERM_LNK: zPerm = "120000"; break; |
| 527 | 567 | case PERM_EXE: zPerm = "100755"; break; |
| 528 | 568 | default: zPerm = "100644"; break; |
| 529 | 569 | } |
| 530 | - printf("M %s :%d %s\n", zPerm, BLOBMARK(zNew), zName); | |
| 570 | + printf("M %s %s %s\n", zPerm, zMark, zName); | |
| 571 | + free(zMark); | |
| 531 | 572 | } |
| 532 | 573 | } |
| 533 | 574 | db_finalize(&q4); |
| 534 | 575 | db_finalize(&q3); |
| 535 | 576 | printf("\n"); |
| @@ -547,20 +588,22 @@ | ||
| 547 | 588 | ); |
| 548 | 589 | while( db_step(&q)==SQLITE_ROW ){ |
| 549 | 590 | const char *zTagname = db_column_text(&q, 0); |
| 550 | 591 | char *zEncoded = 0; |
| 551 | 592 | int rid = db_column_int(&q, 1); |
| 593 | + char *zMark = mark_name_from_rid(rid, &unused_mark); | |
| 552 | 594 | const char *zSecSince1970 = db_column_text(&q, 2); |
| 553 | 595 | int i; |
| 554 | 596 | if( rid==0 || !bag_find(&vers, rid) ) continue; |
| 555 | 597 | zTagname += 4; |
| 556 | 598 | zEncoded = mprintf("%s", zTagname); |
| 557 | 599 | for(i=0; zEncoded[i]; i++){ |
| 558 | 600 | if( !fossil_isalnum(zEncoded[i]) ) zEncoded[i] = '_'; |
| 559 | 601 | } |
| 560 | 602 | printf("tag %s\n", zEncoded); |
| 561 | - printf("from :%d\n", COMMITMARK(rid)); | |
| 603 | + printf("from %s\n", zMark); | |
| 604 | + free(zMark); | |
| 562 | 605 | printf("tagger <tagger> %s +0000\n", zSecSince1970); |
| 563 | 606 | printf("data 0\n"); |
| 564 | 607 | fossil_free(zEncoded); |
| 565 | 608 | } |
| 566 | 609 | db_finalize(&q); |
| @@ -570,12 +613,12 @@ | ||
| 570 | 613 | f = fossil_fopen(markfile_out, "w"); |
| 571 | 614 | if( f == 0 ){ |
| 572 | 615 | fossil_fatal("cannot open %s for writing", markfile_out); |
| 573 | 616 | } |
| 574 | 617 | export_marks(f, &blobs, &vers); |
| 575 | - if( ferror(f)!=0 || fclose(f)!=0 ) { | |
| 618 | + if( ferror(f)!=0 || fclose(f)!=0 ){ | |
| 576 | 619 | fossil_fatal("error while writing %s", markfile_out); |
| 577 | 620 | } |
| 578 | 621 | } |
| 579 | 622 | bag_clear(&blobs); |
| 580 | 623 | bag_clear(&vers); |
| 581 | 624 | } |
| 582 | 625 |
| --- src/export.c | |
| +++ src/export.c | |
| @@ -132,23 +132,28 @@ | |
| 132 | |
| 133 | /* |
| 134 | ** create_mark() |
| 135 | ** Create a new (mark,rid,uuid) entry for the given rid in the 'xmark' table, |
| 136 | ** and return that information as a struct mark_t in *mark. |
| 137 | ** This function returns -1 in the case where 'rid' does not exist, otherwise |
| 138 | ** it returns 0. |
| 139 | ** mark->name is dynamically allocated and is owned by the caller upon return. |
| 140 | */ |
| 141 | int create_mark(int rid, struct mark_t *mark){ |
| 142 | char sid[13]; |
| 143 | char *zUuid = rid_to_uuid(rid); |
| 144 | if(!zUuid){ |
| 145 | fossil_trace("Undefined rid=%d\n", rid); |
| 146 | return -1; |
| 147 | } |
| 148 | mark->rid = rid; |
| 149 | sqlite3_snprintf(sizeof(sid), sid, ":%d", COMMITMARK(rid)); |
| 150 | mark->name = fossil_strdup(sid); |
| 151 | sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", zUuid); |
| 152 | free(zUuid); |
| 153 | insert_commit_xref(mark->rid, mark->name, mark->uuid); |
| 154 | return 0; |
| @@ -156,19 +161,22 @@ | |
| 156 | |
| 157 | /* |
| 158 | ** mark_name_from_rid() |
| 159 | ** Find the mark associated with the given rid. Mark names always start |
| 160 | ** with ':', and are pulled from the 'xmark' temporary table. |
| 161 | ** This function returns NULL if the rid does not exist in the 'xmark' table. |
| 162 | ** Otherwise, it returns the name of the mark, which is dynamically allocated |
| 163 | ** and is owned by the caller of this function. |
| 164 | */ |
| 165 | char * mark_name_from_rid(int rid){ |
| 166 | char *zMark = db_text(0, "SELECT tname FROM xmark WHERE trid=%d", rid); |
| 167 | if(zMark==NULL){ |
| 168 | struct mark_t mark; |
| 169 | if(create_mark(rid, &mark)==0){ |
| 170 | zMark = mark.name; |
| 171 | }else{ |
| 172 | return NULL; |
| 173 | } |
| 174 | } |
| @@ -185,43 +193,52 @@ | |
| 185 | ** database. Otherwise, 0 is returned. |
| 186 | ** mark->name is dynamically allocated, and owned by the caller. |
| 187 | */ |
| 188 | int parse_mark(char *line, struct mark_t *mark){ |
| 189 | char *cur_tok; |
| 190 | cur_tok = strtok(line, " \t"); |
| 191 | if(!cur_tok||strlen(cur_tok)<2){ |
| 192 | return -1; |
| 193 | } |
| 194 | mark->rid = atoi(&cur_tok[1]); |
| 195 | if(cur_tok[0]!='c'){ |
| 196 | /* This is probably a blob mark */ |
| 197 | mark->name = NULL; |
| 198 | return 0; |
| 199 | } |
| 200 | |
| 201 | cur_tok = strtok(NULL, " \t"); |
| 202 | if(!cur_tok){ |
| 203 | /* This mark was generated by an older version of Fossil and doesn't |
| 204 | ** include the mark name and uuid. create_mark() will name the new mark |
| 205 | ** exactly as it was when exported to git, so that we should have a |
| 206 | ** valid mapping from git sha1<->mark name<->fossil sha1. */ |
| 207 | return create_mark(mark->rid, mark); |
| 208 | }else{ |
| 209 | mark->name = fossil_strdup(cur_tok); |
| 210 | } |
| 211 | |
| 212 | cur_tok = strtok(NULL, "\n"); |
| 213 | if(!cur_tok||strlen(cur_tok)!=40){ |
| 214 | free(mark->name); |
| 215 | fossil_trace("Invalid SHA-1 in marks file: %s\n", cur_tok); |
| 216 | return -1; |
| 217 | }else{ |
| 218 | sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", cur_tok); |
| 219 | } |
| 220 | |
| 221 | /* make sure that rid corresponds to UUID */ |
| 222 | if(fast_uuid_to_rid(mark->uuid)!=mark->rid){ |
| 223 | free(mark->name); |
| 224 | fossil_trace("Non-existent SHA-1 in marks file: %s\n", mark->uuid); |
| 225 | return -1; |
| 226 | } |
| 227 | |
| @@ -233,40 +250,66 @@ | |
| 233 | /* |
| 234 | ** import_marks() |
| 235 | ** Import the marks specified in file 'f' into the 'xmark' table. |
| 236 | ** If 'blobs' is non-null, insert all blob marks into it. |
| 237 | ** If 'vers' is non-null, insert all commit marks into it. |
| 238 | ** Each line in the file must be at most 100 characters in length. This |
| 239 | ** seems like a reasonable maximum for a 40-character uuid, and 1-13 |
| 240 | ** character rid. |
| 241 | ** The function returns -1 if any of the lines in file 'f' are malformed, |
| 242 | ** or the rid/uuid information doesn't match what is in the repository |
| 243 | ** database. Otherwise, 0 is returned. |
| 244 | */ |
| 245 | int import_marks(FILE* f, Bag *blobs, Bag *vers){ |
| 246 | char line[101]; |
| 247 | while(fgets(line, sizeof(line), f)){ |
| 248 | struct mark_t mark; |
| 249 | if(strlen(line)==100&&line[99]!='\n'){ |
| 250 | /* line too long */ |
| 251 | return -1; |
| 252 | } |
| 253 | if( parse_mark(line, &mark)<0 ){ |
| 254 | return -1; |
| 255 | }else if( line[0]=='b' ){ |
| 256 | /* Don't import blob marks into 'xmark' table--git doesn't use them, |
| 257 | ** so they need to be left free for git to reuse. */ |
| 258 | if(blobs!=NULL){ |
| 259 | bag_insert(blobs, mark.rid); |
| 260 | } |
| 261 | }else if( vers!=NULL ){ |
| 262 | bag_insert(vers, mark.rid); |
| 263 | } |
| 264 | free(mark.name); |
| 265 | } |
| 266 | return 0; |
| 267 | } |
| 268 | |
| 269 | /* |
| 270 | ** If 'blobs' is non-null, it must point to a Bag of blob rids to be |
| 271 | ** written to disk. Blob rids are written as 'b<rid>'. |
| 272 | ** If 'vers' is non-null, it must point to a Bag of commit rids to be |
| @@ -275,32 +318,24 @@ | |
| 275 | ** This function does not fail, but may produce errors if a uuid cannot |
| 276 | ** be found for an rid in 'vers'. |
| 277 | */ |
| 278 | void export_marks(FILE* f, Bag *blobs, Bag *vers){ |
| 279 | int rid; |
| 280 | if( blobs!=NULL ){ |
| 281 | rid = bag_first(blobs); |
| 282 | if(rid!=0){ |
| 283 | do{ |
| 284 | fprintf(f, "b%d\n", rid); |
| 285 | }while((rid = bag_next(blobs, rid))!=0); |
| 286 | } |
| 287 | } |
| 288 | if( vers!=NULL ){ |
| 289 | rid = bag_first(vers); |
| 290 | if( rid!=0 ){ |
| 291 | do{ |
| 292 | char *zUuid = rid_to_uuid(rid); |
| 293 | char *zMark; |
| 294 | if(zUuid==NULL){ |
| 295 | fossil_trace("No uuid matching rid=%d when exporting marks\n", rid); |
| 296 | continue; |
| 297 | } |
| 298 | zMark = mark_name_from_rid(rid); |
| 299 | fprintf(f, "c%d %s %s\n", rid, zMark, zUuid); |
| 300 | free(zMark); |
| 301 | free(zUuid); |
| 302 | }while( (rid = bag_next(vers, rid))!=0 ); |
| 303 | } |
| 304 | } |
| 305 | } |
| 306 | |
| @@ -336,10 +371,11 @@ | |
| 336 | */ |
| 337 | void export_cmd(void){ |
| 338 | Stmt q, q2, q3; |
| 339 | int i; |
| 340 | Bag blobs, vers; |
| 341 | const char *markfile_in; |
| 342 | const char *markfile_out; |
| 343 | |
| 344 | bag_init(&blobs); |
| 345 | bag_init(&vers); |
| @@ -362,25 +398,25 @@ | |
| 362 | |
| 363 | f = fossil_fopen(markfile_in, "r"); |
| 364 | if( f==0 ){ |
| 365 | fossil_fatal("cannot open %s for reading", markfile_in); |
| 366 | } |
| 367 | if(import_marks(f, &blobs, &vers)<0){ |
| 368 | fossil_fatal("error importing marks from file: %s\n", markfile_in); |
| 369 | } |
| 370 | db_prepare(&qb, "INSERT OR IGNORE INTO oldblob VALUES (:rid)"); |
| 371 | db_prepare(&qc, "INSERT OR IGNORE INTO oldcommit VALUES (:rid)"); |
| 372 | rid = bag_first(&blobs); |
| 373 | if(rid!=0){ |
| 374 | do{ |
| 375 | db_bind_int(&qb, ":rid", rid); |
| 376 | db_step(&qb); |
| 377 | db_reset(&qb); |
| 378 | }while((rid = bag_next(&blobs, rid))!=0); |
| 379 | } |
| 380 | rid = bag_first(&vers); |
| 381 | if(rid!=0){ |
| 382 | do{ |
| 383 | db_bind_int(&qc, ":rid", rid); |
| 384 | db_step(&qc); |
| 385 | db_reset(&qc); |
| 386 | }while((rid = bag_next(&vers, rid))!=0); |
| @@ -416,15 +452,18 @@ | |
| 416 | while( db_step(&q)==SQLITE_ROW ){ |
| 417 | int rid = db_column_int(&q, 0); |
| 418 | Blob content; |
| 419 | |
| 420 | while( !bag_find(&blobs, rid) ){ |
| 421 | content_get(rid, &content); |
| 422 | db_bind_int(&q2, ":rid", rid); |
| 423 | db_step(&q2); |
| 424 | db_reset(&q2); |
| 425 | printf("blob\nmark :%d\ndata %d\n", BLOBMARK(rid), blob_size(&content)); |
| 426 | bag_insert(&blobs, rid); |
| 427 | fwrite(blob_buffer(&content), 1, blob_size(&content), stdout); |
| 428 | printf("\n"); |
| 429 | blob_reset(&content); |
| 430 | |
| @@ -470,11 +509,11 @@ | |
| 470 | if( zBranch==0 ) zBranch = "trunk"; |
| 471 | zBr = mprintf("%s", zBranch); |
| 472 | for(i=0; zBr[i]; i++){ |
| 473 | if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_'; |
| 474 | } |
| 475 | zMark = mark_name_from_rid(ckinId); |
| 476 | printf("commit refs/heads/%s\nmark %s\n", zBr, zMark); |
| 477 | free(zMark); |
| 478 | free(zBr); |
| 479 | printf("committer"); |
| 480 | print_person(zUser); |
| @@ -487,21 +526,21 @@ | |
| 487 | " AND pid IN (SELECT objid FROM event)", |
| 488 | ckinId |
| 489 | ); |
| 490 | if( db_step(&q3) == SQLITE_ROW ){ |
| 491 | int pid = db_column_int(&q3, 0); |
| 492 | zMark = mark_name_from_rid(pid); |
| 493 | printf("from %s\n", zMark); |
| 494 | free(zMark); |
| 495 | db_prepare(&q4, |
| 496 | "SELECT pid FROM plink" |
| 497 | " WHERE cid=%d AND NOT isprim" |
| 498 | " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)" |
| 499 | " ORDER BY pid", |
| 500 | ckinId); |
| 501 | while( db_step(&q4)==SQLITE_ROW ){ |
| 502 | zMark = mark_name_from_rid(db_column_int(&q4, 0)); |
| 503 | printf("merge %s\n", zMark); |
| 504 | free(zMark); |
| 505 | } |
| 506 | db_finalize(&q4); |
| 507 | }else{ |
| @@ -516,20 +555,22 @@ | |
| 516 | ); |
| 517 | while( db_step(&q4)==SQLITE_ROW ){ |
| 518 | const char *zName = db_column_text(&q4,0); |
| 519 | int zNew = db_column_int(&q4,1); |
| 520 | int mPerm = db_column_int(&q4,2); |
| 521 | if( zNew==0) |
| 522 | printf("D %s\n", zName); |
| 523 | else if( bag_find(&blobs, zNew) ) { |
| 524 | const char *zPerm; |
| 525 | switch( mPerm ){ |
| 526 | case PERM_LNK: zPerm = "120000"; break; |
| 527 | case PERM_EXE: zPerm = "100755"; break; |
| 528 | default: zPerm = "100644"; break; |
| 529 | } |
| 530 | printf("M %s :%d %s\n", zPerm, BLOBMARK(zNew), zName); |
| 531 | } |
| 532 | } |
| 533 | db_finalize(&q4); |
| 534 | db_finalize(&q3); |
| 535 | printf("\n"); |
| @@ -547,20 +588,22 @@ | |
| 547 | ); |
| 548 | while( db_step(&q)==SQLITE_ROW ){ |
| 549 | const char *zTagname = db_column_text(&q, 0); |
| 550 | char *zEncoded = 0; |
| 551 | int rid = db_column_int(&q, 1); |
| 552 | const char *zSecSince1970 = db_column_text(&q, 2); |
| 553 | int i; |
| 554 | if( rid==0 || !bag_find(&vers, rid) ) continue; |
| 555 | zTagname += 4; |
| 556 | zEncoded = mprintf("%s", zTagname); |
| 557 | for(i=0; zEncoded[i]; i++){ |
| 558 | if( !fossil_isalnum(zEncoded[i]) ) zEncoded[i] = '_'; |
| 559 | } |
| 560 | printf("tag %s\n", zEncoded); |
| 561 | printf("from :%d\n", COMMITMARK(rid)); |
| 562 | printf("tagger <tagger> %s +0000\n", zSecSince1970); |
| 563 | printf("data 0\n"); |
| 564 | fossil_free(zEncoded); |
| 565 | } |
| 566 | db_finalize(&q); |
| @@ -570,12 +613,12 @@ | |
| 570 | f = fossil_fopen(markfile_out, "w"); |
| 571 | if( f == 0 ){ |
| 572 | fossil_fatal("cannot open %s for writing", markfile_out); |
| 573 | } |
| 574 | export_marks(f, &blobs, &vers); |
| 575 | if( ferror(f)!=0 || fclose(f)!=0 ) { |
| 576 | fossil_fatal("error while writing %s", markfile_out); |
| 577 | } |
| 578 | } |
| 579 | bag_clear(&blobs); |
| 580 | bag_clear(&vers); |
| 581 | } |
| 582 |
| --- src/export.c | |
| +++ src/export.c | |
| @@ -132,23 +132,28 @@ | |
| 132 | |
| 133 | /* |
| 134 | ** create_mark() |
| 135 | ** Create a new (mark,rid,uuid) entry for the given rid in the 'xmark' table, |
| 136 | ** and return that information as a struct mark_t in *mark. |
| 137 | ** *unused_mark is a value representing a mark that is free for use--that is, |
| 138 | ** it does not appear in the marks file, and has not been used during this |
| 139 | ** export run. Specifically, it is the supremum of the set of used marks |
| 140 | ** plus one. |
| 141 | ** This function returns -1 in the case where 'rid' does not exist, otherwise |
| 142 | ** it returns 0. |
| 143 | ** mark->name is dynamically allocated and is owned by the caller upon return. |
| 144 | */ |
| 145 | int create_mark(int rid, struct mark_t *mark, unsigned int *unused_mark){ |
| 146 | char sid[13]; |
| 147 | char *zUuid = rid_to_uuid(rid); |
| 148 | if( !zUuid ){ |
| 149 | fossil_trace("Undefined rid=%d\n", rid); |
| 150 | return -1; |
| 151 | } |
| 152 | mark->rid = rid; |
| 153 | sqlite3_snprintf(sizeof(sid), sid, ":%d", *unused_mark); |
| 154 | *unused_mark += 1; |
| 155 | mark->name = fossil_strdup(sid); |
| 156 | sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", zUuid); |
| 157 | free(zUuid); |
| 158 | insert_commit_xref(mark->rid, mark->name, mark->uuid); |
| 159 | return 0; |
| @@ -156,19 +161,22 @@ | |
| 161 | |
| 162 | /* |
| 163 | ** mark_name_from_rid() |
| 164 | ** Find the mark associated with the given rid. Mark names always start |
| 165 | ** with ':', and are pulled from the 'xmark' temporary table. |
| 166 | ** If the given rid doesn't have a mark associated with it yet, one is |
| 167 | ** created with a value of *unused_mark. |
| 168 | ** *unused_mark functions exactly as in create_mark(). |
| 169 | ** This function returns NULL if the rid does not have an associated UUID, |
| 170 | ** (i.e. is not valid). Otherwise, it returns the name of the mark, which is |
| 171 | ** dynamically allocated and is owned by the caller of this function. |
| 172 | */ |
| 173 | char * mark_name_from_rid(int rid, unsigned int *unused_mark){ |
| 174 | char *zMark = db_text(0, "SELECT tname FROM xmark WHERE trid=%d", rid); |
| 175 | if( zMark==NULL ){ |
| 176 | struct mark_t mark; |
| 177 | if( create_mark(rid, &mark, unused_mark)==0 ){ |
| 178 | zMark = mark.name; |
| 179 | }else{ |
| 180 | return NULL; |
| 181 | } |
| 182 | } |
| @@ -185,43 +193,52 @@ | |
| 193 | ** database. Otherwise, 0 is returned. |
| 194 | ** mark->name is dynamically allocated, and owned by the caller. |
| 195 | */ |
| 196 | int parse_mark(char *line, struct mark_t *mark){ |
| 197 | char *cur_tok; |
| 198 | char type_; |
| 199 | cur_tok = strtok(line, " \t"); |
| 200 | if( !cur_tok || strlen(cur_tok)<2 ){ |
| 201 | return -1; |
| 202 | } |
| 203 | mark->rid = atoi(&cur_tok[1]); |
| 204 | type_ = cur_tok[0]; |
| 205 | if( type_!='c' && type_!='b' ){ |
| 206 | /* This is probably a blob mark */ |
| 207 | mark->name = NULL; |
| 208 | return 0; |
| 209 | } |
| 210 | |
| 211 | cur_tok = strtok(NULL, " \t"); |
| 212 | if( !cur_tok ){ |
| 213 | /* This mark was generated by an older version of Fossil and doesn't |
| 214 | ** include the mark name and uuid. create_mark() will name the new mark |
| 215 | ** exactly as it was when exported to git, so that we should have a |
| 216 | ** valid mapping from git sha1<->mark name<->fossil sha1. */ |
| 217 | unsigned int mid; |
| 218 | if( type_=='c' ){ |
| 219 | mid = COMMITMARK(mark->rid); |
| 220 | } |
| 221 | else{ |
| 222 | mid = BLOBMARK(mark->rid); |
| 223 | } |
| 224 | return create_mark(mark->rid, mark, &mid); |
| 225 | }else{ |
| 226 | mark->name = fossil_strdup(cur_tok); |
| 227 | } |
| 228 | |
| 229 | cur_tok = strtok(NULL, "\n"); |
| 230 | if( !cur_tok || strlen(cur_tok)!=40 ){ |
| 231 | free(mark->name); |
| 232 | fossil_trace("Invalid SHA-1 in marks file: %s\n", cur_tok); |
| 233 | return -1; |
| 234 | }else{ |
| 235 | sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", cur_tok); |
| 236 | } |
| 237 | |
| 238 | /* make sure that rid corresponds to UUID */ |
| 239 | if( fast_uuid_to_rid(mark->uuid)!=mark->rid ){ |
| 240 | free(mark->name); |
| 241 | fossil_trace("Non-existent SHA-1 in marks file: %s\n", mark->uuid); |
| 242 | return -1; |
| 243 | } |
| 244 | |
| @@ -233,40 +250,66 @@ | |
| 250 | /* |
| 251 | ** import_marks() |
| 252 | ** Import the marks specified in file 'f' into the 'xmark' table. |
| 253 | ** If 'blobs' is non-null, insert all blob marks into it. |
| 254 | ** If 'vers' is non-null, insert all commit marks into it. |
| 255 | ** If 'unused_marks' is non-null, upon return of this function, all values |
| 256 | ** x >= *unused_marks are free to use as marks, i.e. they do not clash with |
| 257 | ** any marks appearing in the marks file. |
| 258 | ** Each line in the file must be at most 100 characters in length. This |
| 259 | ** seems like a reasonable maximum for a 40-character uuid, and 1-13 |
| 260 | ** character rid. |
| 261 | ** The function returns -1 if any of the lines in file 'f' are malformed, |
| 262 | ** or the rid/uuid information doesn't match what is in the repository |
| 263 | ** database. Otherwise, 0 is returned. |
| 264 | */ |
| 265 | int import_marks(FILE* f, Bag *blobs, Bag *vers, unsigned int *unused_mark){ |
| 266 | char line[101]; |
| 267 | while(fgets(line, sizeof(line), f)){ |
| 268 | struct mark_t mark; |
| 269 | if( strlen(line)==100 && line[99]!='\n' ){ |
| 270 | /* line too long */ |
| 271 | return -1; |
| 272 | } |
| 273 | if( parse_mark(line, &mark)<0 ){ |
| 274 | return -1; |
| 275 | }else if( line[0]=='b' ){ |
| 276 | if( blobs!=NULL ){ |
| 277 | bag_insert(blobs, mark.rid); |
| 278 | } |
| 279 | }else{ |
| 280 | if( vers!=NULL ){ |
| 281 | bag_insert(vers, mark.rid); |
| 282 | } |
| 283 | } |
| 284 | if( unused_mark!=NULL ){ |
| 285 | unsigned int mid = atoi(mark.name + 1); |
| 286 | if( mid>=*unused_mark ){ |
| 287 | *unused_mark = mid + 1; |
| 288 | } |
| 289 | } |
| 290 | free(mark.name); |
| 291 | } |
| 292 | return 0; |
| 293 | } |
| 294 | |
| 295 | void export_mark(FILE* f, int rid, char obj_type) |
| 296 | { |
| 297 | unsigned int z = 0; |
| 298 | char *zUuid = rid_to_uuid(rid); |
| 299 | char *zMark; |
| 300 | if( zUuid==NULL ){ |
| 301 | fossil_trace("No uuid matching rid=%d when exporting marks\n", rid); |
| 302 | return; |
| 303 | } |
| 304 | /* Since rid is already in the 'xmark' table, the value of z won't be |
| 305 | ** used, but pass in a valid pointer just to be safe. */ |
| 306 | zMark = mark_name_from_rid(rid, &z); |
| 307 | fprintf(f, "%c%d %s %s\n", obj_type, rid, zMark, zUuid); |
| 308 | free(zMark); |
| 309 | free(zUuid); |
| 310 | } |
| 311 | |
| 312 | /* |
| 313 | ** If 'blobs' is non-null, it must point to a Bag of blob rids to be |
| 314 | ** written to disk. Blob rids are written as 'b<rid>'. |
| 315 | ** If 'vers' is non-null, it must point to a Bag of commit rids to be |
| @@ -275,32 +318,24 @@ | |
| 318 | ** This function does not fail, but may produce errors if a uuid cannot |
| 319 | ** be found for an rid in 'vers'. |
| 320 | */ |
| 321 | void export_marks(FILE* f, Bag *blobs, Bag *vers){ |
| 322 | int rid; |
| 323 | |
| 324 | if( blobs!=NULL ){ |
| 325 | rid = bag_first(blobs); |
| 326 | if( rid!=0 ){ |
| 327 | do{ |
| 328 | export_mark(f, rid, 'b'); |
| 329 | }while( (rid = bag_next(blobs, rid))!=0 ); |
| 330 | } |
| 331 | } |
| 332 | if( vers!=NULL ){ |
| 333 | rid = bag_first(vers); |
| 334 | if( rid!=0 ){ |
| 335 | do{ |
| 336 | export_mark(f, rid, 'c'); |
| 337 | }while( (rid = bag_next(vers, rid))!=0 ); |
| 338 | } |
| 339 | } |
| 340 | } |
| 341 | |
| @@ -336,10 +371,11 @@ | |
| 371 | */ |
| 372 | void export_cmd(void){ |
| 373 | Stmt q, q2, q3; |
| 374 | int i; |
| 375 | Bag blobs, vers; |
| 376 | unsigned int unused_mark = 1; |
| 377 | const char *markfile_in; |
| 378 | const char *markfile_out; |
| 379 | |
| 380 | bag_init(&blobs); |
| 381 | bag_init(&vers); |
| @@ -362,25 +398,25 @@ | |
| 398 | |
| 399 | f = fossil_fopen(markfile_in, "r"); |
| 400 | if( f==0 ){ |
| 401 | fossil_fatal("cannot open %s for reading", markfile_in); |
| 402 | } |
| 403 | if( import_marks(f, &blobs, &vers, &unused_mark)<0 ){ |
| 404 | fossil_fatal("error importing marks from file: %s", markfile_in); |
| 405 | } |
| 406 | db_prepare(&qb, "INSERT OR IGNORE INTO oldblob VALUES (:rid)"); |
| 407 | db_prepare(&qc, "INSERT OR IGNORE INTO oldcommit VALUES (:rid)"); |
| 408 | rid = bag_first(&blobs); |
| 409 | if( rid!=0 ){ |
| 410 | do{ |
| 411 | db_bind_int(&qb, ":rid", rid); |
| 412 | db_step(&qb); |
| 413 | db_reset(&qb); |
| 414 | }while((rid = bag_next(&blobs, rid))!=0); |
| 415 | } |
| 416 | rid = bag_first(&vers); |
| 417 | if( rid!=0 ){ |
| 418 | do{ |
| 419 | db_bind_int(&qc, ":rid", rid); |
| 420 | db_step(&qc); |
| 421 | db_reset(&qc); |
| 422 | }while((rid = bag_next(&vers, rid))!=0); |
| @@ -416,15 +452,18 @@ | |
| 452 | while( db_step(&q)==SQLITE_ROW ){ |
| 453 | int rid = db_column_int(&q, 0); |
| 454 | Blob content; |
| 455 | |
| 456 | while( !bag_find(&blobs, rid) ){ |
| 457 | char *zMark; |
| 458 | content_get(rid, &content); |
| 459 | db_bind_int(&q2, ":rid", rid); |
| 460 | db_step(&q2); |
| 461 | db_reset(&q2); |
| 462 | zMark = mark_name_from_rid(rid, &unused_mark); |
| 463 | printf("blob\nmark %s\ndata %d\n", zMark, blob_size(&content)); |
| 464 | free(zMark); |
| 465 | bag_insert(&blobs, rid); |
| 466 | fwrite(blob_buffer(&content), 1, blob_size(&content), stdout); |
| 467 | printf("\n"); |
| 468 | blob_reset(&content); |
| 469 | |
| @@ -470,11 +509,11 @@ | |
| 509 | if( zBranch==0 ) zBranch = "trunk"; |
| 510 | zBr = mprintf("%s", zBranch); |
| 511 | for(i=0; zBr[i]; i++){ |
| 512 | if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_'; |
| 513 | } |
| 514 | zMark = mark_name_from_rid(ckinId, &unused_mark); |
| 515 | printf("commit refs/heads/%s\nmark %s\n", zBr, zMark); |
| 516 | free(zMark); |
| 517 | free(zBr); |
| 518 | printf("committer"); |
| 519 | print_person(zUser); |
| @@ -487,21 +526,21 @@ | |
| 526 | " AND pid IN (SELECT objid FROM event)", |
| 527 | ckinId |
| 528 | ); |
| 529 | if( db_step(&q3) == SQLITE_ROW ){ |
| 530 | int pid = db_column_int(&q3, 0); |
| 531 | zMark = mark_name_from_rid(pid, &unused_mark); |
| 532 | printf("from %s\n", zMark); |
| 533 | free(zMark); |
| 534 | db_prepare(&q4, |
| 535 | "SELECT pid FROM plink" |
| 536 | " WHERE cid=%d AND NOT isprim" |
| 537 | " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)" |
| 538 | " ORDER BY pid", |
| 539 | ckinId); |
| 540 | while( db_step(&q4)==SQLITE_ROW ){ |
| 541 | zMark = mark_name_from_rid(db_column_int(&q4, 0), &unused_mark); |
| 542 | printf("merge %s\n", zMark); |
| 543 | free(zMark); |
| 544 | } |
| 545 | db_finalize(&q4); |
| 546 | }else{ |
| @@ -516,20 +555,22 @@ | |
| 555 | ); |
| 556 | while( db_step(&q4)==SQLITE_ROW ){ |
| 557 | const char *zName = db_column_text(&q4,0); |
| 558 | int zNew = db_column_int(&q4,1); |
| 559 | int mPerm = db_column_int(&q4,2); |
| 560 | if( zNew==0 ){ |
| 561 | printf("D %s\n", zName); |
| 562 | }else if( bag_find(&blobs, zNew) ){ |
| 563 | const char *zPerm; |
| 564 | zMark = mark_name_from_rid(zNew, &unused_mark); |
| 565 | switch( mPerm ){ |
| 566 | case PERM_LNK: zPerm = "120000"; break; |
| 567 | case PERM_EXE: zPerm = "100755"; break; |
| 568 | default: zPerm = "100644"; break; |
| 569 | } |
| 570 | printf("M %s %s %s\n", zPerm, zMark, zName); |
| 571 | free(zMark); |
| 572 | } |
| 573 | } |
| 574 | db_finalize(&q4); |
| 575 | db_finalize(&q3); |
| 576 | printf("\n"); |
| @@ -547,20 +588,22 @@ | |
| 588 | ); |
| 589 | while( db_step(&q)==SQLITE_ROW ){ |
| 590 | const char *zTagname = db_column_text(&q, 0); |
| 591 | char *zEncoded = 0; |
| 592 | int rid = db_column_int(&q, 1); |
| 593 | char *zMark = mark_name_from_rid(rid, &unused_mark); |
| 594 | const char *zSecSince1970 = db_column_text(&q, 2); |
| 595 | int i; |
| 596 | if( rid==0 || !bag_find(&vers, rid) ) continue; |
| 597 | zTagname += 4; |
| 598 | zEncoded = mprintf("%s", zTagname); |
| 599 | for(i=0; zEncoded[i]; i++){ |
| 600 | if( !fossil_isalnum(zEncoded[i]) ) zEncoded[i] = '_'; |
| 601 | } |
| 602 | printf("tag %s\n", zEncoded); |
| 603 | printf("from %s\n", zMark); |
| 604 | free(zMark); |
| 605 | printf("tagger <tagger> %s +0000\n", zSecSince1970); |
| 606 | printf("data 0\n"); |
| 607 | fossil_free(zEncoded); |
| 608 | } |
| 609 | db_finalize(&q); |
| @@ -570,12 +613,12 @@ | |
| 613 | f = fossil_fopen(markfile_out, "w"); |
| 614 | if( f == 0 ){ |
| 615 | fossil_fatal("cannot open %s for writing", markfile_out); |
| 616 | } |
| 617 | export_marks(f, &blobs, &vers); |
| 618 | if( ferror(f)!=0 || fclose(f)!=0 ){ |
| 619 | fossil_fatal("error while writing %s", markfile_out); |
| 620 | } |
| 621 | } |
| 622 | bag_clear(&blobs); |
| 623 | bag_clear(&vers); |
| 624 | } |
| 625 |
+3
-3
| --- src/file.c | ||
| +++ src/file.c | ||
| @@ -863,11 +863,11 @@ | ||
| 863 | 863 | #ifdef _WIN32 |
| 864 | 864 | win32_getcwd(zBuf, nBuf); |
| 865 | 865 | #else |
| 866 | 866 | if( getcwd(zBuf, nBuf-1)==0 ){ |
| 867 | 867 | if( errno==ERANGE ){ |
| 868 | - fossil_fatal("pwd too big: max %d\n", nBuf-1); | |
| 868 | + fossil_fatal("pwd too big: max %d", nBuf-1); | |
| 869 | 869 | }else{ |
| 870 | 870 | fossil_fatal("cannot find current working directory; %s", |
| 871 | 871 | strerror(errno)); |
| 872 | 872 | } |
| 873 | 873 | } |
| @@ -1290,11 +1290,11 @@ | ||
| 1290 | 1290 | azDirs[1] = fossil_getenv("TEMP"); |
| 1291 | 1291 | azDirs[2] = fossil_getenv("TMP"); |
| 1292 | 1292 | #endif |
| 1293 | 1293 | |
| 1294 | 1294 | |
| 1295 | - for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){ | |
| 1295 | + for(i=0; i<count(azDirs); i++){ | |
| 1296 | 1296 | if( azDirs[i]==0 ) continue; |
| 1297 | 1297 | if( !file_isdir(azDirs[i]) ) continue; |
| 1298 | 1298 | zDir = azDirs[i]; |
| 1299 | 1299 | break; |
| 1300 | 1300 | } |
| @@ -1407,11 +1407,11 @@ | ||
| 1407 | 1407 | const char *file_is_win_reserved(const char *zPath){ |
| 1408 | 1408 | static const char *azRes[] = { "CON", "PRN", "AUX", "NUL", "COM", "LPT" }; |
| 1409 | 1409 | static char zReturn[5]; |
| 1410 | 1410 | int i; |
| 1411 | 1411 | while( zPath[0] ){ |
| 1412 | - for(i=0; i<ArraySize(azRes); i++){ | |
| 1412 | + for(i=0; i<count(azRes); i++){ | |
| 1413 | 1413 | if( sqlite3_strnicmp(zPath, azRes[i], 3)==0 |
| 1414 | 1414 | && ((i>=4 && fossil_isdigit(zPath[3]) |
| 1415 | 1415 | && (zPath[4]=='/' || zPath[4]=='.' || zPath[4]==0)) |
| 1416 | 1416 | || (i<4 && (zPath[3]=='/' || zPath[3]=='.' || zPath[3]==0))) |
| 1417 | 1417 | ){ |
| 1418 | 1418 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -863,11 +863,11 @@ | |
| 863 | #ifdef _WIN32 |
| 864 | win32_getcwd(zBuf, nBuf); |
| 865 | #else |
| 866 | if( getcwd(zBuf, nBuf-1)==0 ){ |
| 867 | if( errno==ERANGE ){ |
| 868 | fossil_fatal("pwd too big: max %d\n", nBuf-1); |
| 869 | }else{ |
| 870 | fossil_fatal("cannot find current working directory; %s", |
| 871 | strerror(errno)); |
| 872 | } |
| 873 | } |
| @@ -1290,11 +1290,11 @@ | |
| 1290 | azDirs[1] = fossil_getenv("TEMP"); |
| 1291 | azDirs[2] = fossil_getenv("TMP"); |
| 1292 | #endif |
| 1293 | |
| 1294 | |
| 1295 | for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){ |
| 1296 | if( azDirs[i]==0 ) continue; |
| 1297 | if( !file_isdir(azDirs[i]) ) continue; |
| 1298 | zDir = azDirs[i]; |
| 1299 | break; |
| 1300 | } |
| @@ -1407,11 +1407,11 @@ | |
| 1407 | const char *file_is_win_reserved(const char *zPath){ |
| 1408 | static const char *azRes[] = { "CON", "PRN", "AUX", "NUL", "COM", "LPT" }; |
| 1409 | static char zReturn[5]; |
| 1410 | int i; |
| 1411 | while( zPath[0] ){ |
| 1412 | for(i=0; i<ArraySize(azRes); i++){ |
| 1413 | if( sqlite3_strnicmp(zPath, azRes[i], 3)==0 |
| 1414 | && ((i>=4 && fossil_isdigit(zPath[3]) |
| 1415 | && (zPath[4]=='/' || zPath[4]=='.' || zPath[4]==0)) |
| 1416 | || (i<4 && (zPath[3]=='/' || zPath[3]=='.' || zPath[3]==0))) |
| 1417 | ){ |
| 1418 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -863,11 +863,11 @@ | |
| 863 | #ifdef _WIN32 |
| 864 | win32_getcwd(zBuf, nBuf); |
| 865 | #else |
| 866 | if( getcwd(zBuf, nBuf-1)==0 ){ |
| 867 | if( errno==ERANGE ){ |
| 868 | fossil_fatal("pwd too big: max %d", nBuf-1); |
| 869 | }else{ |
| 870 | fossil_fatal("cannot find current working directory; %s", |
| 871 | strerror(errno)); |
| 872 | } |
| 873 | } |
| @@ -1290,11 +1290,11 @@ | |
| 1290 | azDirs[1] = fossil_getenv("TEMP"); |
| 1291 | azDirs[2] = fossil_getenv("TMP"); |
| 1292 | #endif |
| 1293 | |
| 1294 | |
| 1295 | for(i=0; i<count(azDirs); i++){ |
| 1296 | if( azDirs[i]==0 ) continue; |
| 1297 | if( !file_isdir(azDirs[i]) ) continue; |
| 1298 | zDir = azDirs[i]; |
| 1299 | break; |
| 1300 | } |
| @@ -1407,11 +1407,11 @@ | |
| 1407 | const char *file_is_win_reserved(const char *zPath){ |
| 1408 | static const char *azRes[] = { "CON", "PRN", "AUX", "NUL", "COM", "LPT" }; |
| 1409 | static char zReturn[5]; |
| 1410 | int i; |
| 1411 | while( zPath[0] ){ |
| 1412 | for(i=0; i<count(azRes); i++){ |
| 1413 | if( sqlite3_strnicmp(zPath, azRes[i], 3)==0 |
| 1414 | && ((i>=4 && fossil_isdigit(zPath[3]) |
| 1415 | && (zPath[4]=='/' || zPath[4]=='.' || zPath[4]==0)) |
| 1416 | || (i<4 && (zPath[3]=='/' || zPath[3]=='.' || zPath[3]==0))) |
| 1417 | ){ |
| 1418 |
+2
-2
| --- src/finfo.c | ||
| +++ src/finfo.c | ||
| @@ -331,11 +331,11 @@ | ||
| 331 | 331 | @ No such file: %h(zFilename) |
| 332 | 332 | style_footer(); |
| 333 | 333 | return; |
| 334 | 334 | } |
| 335 | 335 | if( g.perm.Admin ){ |
| 336 | - style_submenu_element("MLink Table", "mtab", "%R/mlink?name=%t", zFilename); | |
| 336 | + style_submenu_element("MLink Table", "%R/mlink?name=%t", zFilename); | |
| 337 | 337 | } |
| 338 | 338 | if( baseCheckin ){ |
| 339 | 339 | compute_direct_ancestors(baseCheckin); |
| 340 | 340 | } |
| 341 | 341 | url_add_parameter(&url, "name", zFilename); |
| @@ -454,11 +454,11 @@ | ||
| 454 | 454 | int aParent[GR_MAX_RAIL]; |
| 455 | 455 | |
| 456 | 456 | db_bind_int(&qparent, ":fid", frid); |
| 457 | 457 | db_bind_int(&qparent, ":mid", fmid); |
| 458 | 458 | db_bind_int(&qparent, ":fnid", fnid); |
| 459 | - while( db_step(&qparent)==SQLITE_ROW && nParent<ArraySize(aParent) ){ | |
| 459 | + while( db_step(&qparent)==SQLITE_ROW && nParent<count(aParent) ){ | |
| 460 | 460 | aParent[nParent] = db_column_int(&qparent, 0); |
| 461 | 461 | nParent++; |
| 462 | 462 | } |
| 463 | 463 | db_reset(&qparent); |
| 464 | 464 | if( zBr==0 ) zBr = "trunk"; |
| 465 | 465 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -331,11 +331,11 @@ | |
| 331 | @ No such file: %h(zFilename) |
| 332 | style_footer(); |
| 333 | return; |
| 334 | } |
| 335 | if( g.perm.Admin ){ |
| 336 | style_submenu_element("MLink Table", "mtab", "%R/mlink?name=%t", zFilename); |
| 337 | } |
| 338 | if( baseCheckin ){ |
| 339 | compute_direct_ancestors(baseCheckin); |
| 340 | } |
| 341 | url_add_parameter(&url, "name", zFilename); |
| @@ -454,11 +454,11 @@ | |
| 454 | int aParent[GR_MAX_RAIL]; |
| 455 | |
| 456 | db_bind_int(&qparent, ":fid", frid); |
| 457 | db_bind_int(&qparent, ":mid", fmid); |
| 458 | db_bind_int(&qparent, ":fnid", fnid); |
| 459 | while( db_step(&qparent)==SQLITE_ROW && nParent<ArraySize(aParent) ){ |
| 460 | aParent[nParent] = db_column_int(&qparent, 0); |
| 461 | nParent++; |
| 462 | } |
| 463 | db_reset(&qparent); |
| 464 | if( zBr==0 ) zBr = "trunk"; |
| 465 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -331,11 +331,11 @@ | |
| 331 | @ No such file: %h(zFilename) |
| 332 | style_footer(); |
| 333 | return; |
| 334 | } |
| 335 | if( g.perm.Admin ){ |
| 336 | style_submenu_element("MLink Table", "%R/mlink?name=%t", zFilename); |
| 337 | } |
| 338 | if( baseCheckin ){ |
| 339 | compute_direct_ancestors(baseCheckin); |
| 340 | } |
| 341 | url_add_parameter(&url, "name", zFilename); |
| @@ -454,11 +454,11 @@ | |
| 454 | int aParent[GR_MAX_RAIL]; |
| 455 | |
| 456 | db_bind_int(&qparent, ":fid", frid); |
| 457 | db_bind_int(&qparent, ":mid", fmid); |
| 458 | db_bind_int(&qparent, ":fnid", fnid); |
| 459 | while( db_step(&qparent)==SQLITE_ROW && nParent<count(aParent) ){ |
| 460 | aParent[nParent] = db_column_int(&qparent, 0); |
| 461 | nParent++; |
| 462 | } |
| 463 | db_reset(&qparent); |
| 464 | if( zBr==0 ) zBr = "trunk"; |
| 465 |
+6
-2
| --- src/fshell.c | ||
| +++ src/fshell.c | ||
| @@ -25,10 +25,11 @@ | ||
| 25 | 25 | ** It allows multiple commands to be issued without having to reenter the |
| 26 | 26 | ** crypto phasephrase for each command. |
| 27 | 27 | */ |
| 28 | 28 | #include "config.h" |
| 29 | 29 | #include "fshell.h" |
| 30 | +#include "linenoise.h" | |
| 30 | 31 | #include <ctype.h> |
| 31 | 32 | |
| 32 | 33 | #ifndef _WIN32 |
| 33 | 34 | #include <sys/types.h> |
| 34 | 35 | #include <sys/wait.h> |
| @@ -55,16 +56,19 @@ | ||
| 55 | 56 | int mxArg = 0; |
| 56 | 57 | int n, i; |
| 57 | 58 | char **azArg = 0; |
| 58 | 59 | int fDebug; |
| 59 | 60 | pid_t childPid; |
| 60 | - char zLine[10000]; | |
| 61 | + char *zLine = 0; | |
| 61 | 62 | fDebug = find_option("debug", 0, 0)!=0; |
| 62 | 63 | db_find_and_open_repository(OPEN_ANY_SCHEMA|OPEN_OK_NOT_FOUND, 0); |
| 63 | 64 | db_close(0); |
| 64 | 65 | sqlite3_shutdown(); |
| 65 | - while( printf("fossil> "),fflush(stdout),fgets(zLine, sizeof(zLine), stdin) ){ | |
| 66 | + while( (free(zLine), zLine = linenoise("fossil> ")) ){ | |
| 67 | + /* Remember shell history within the current session */ | |
| 68 | + linenoiseHistoryAdd(zLine); | |
| 69 | + | |
| 66 | 70 | /* Parse the line of input */ |
| 67 | 71 | n = (int)strlen(zLine); |
| 68 | 72 | for(i=0, nArg=1; i<n; i++){ |
| 69 | 73 | while( fossil_isspace(zLine[i]) ){ i++; } |
| 70 | 74 | if( i>=n ) break; |
| 71 | 75 |
| --- src/fshell.c | |
| +++ src/fshell.c | |
| @@ -25,10 +25,11 @@ | |
| 25 | ** It allows multiple commands to be issued without having to reenter the |
| 26 | ** crypto phasephrase for each command. |
| 27 | */ |
| 28 | #include "config.h" |
| 29 | #include "fshell.h" |
| 30 | #include <ctype.h> |
| 31 | |
| 32 | #ifndef _WIN32 |
| 33 | #include <sys/types.h> |
| 34 | #include <sys/wait.h> |
| @@ -55,16 +56,19 @@ | |
| 55 | int mxArg = 0; |
| 56 | int n, i; |
| 57 | char **azArg = 0; |
| 58 | int fDebug; |
| 59 | pid_t childPid; |
| 60 | char zLine[10000]; |
| 61 | fDebug = find_option("debug", 0, 0)!=0; |
| 62 | db_find_and_open_repository(OPEN_ANY_SCHEMA|OPEN_OK_NOT_FOUND, 0); |
| 63 | db_close(0); |
| 64 | sqlite3_shutdown(); |
| 65 | while( printf("fossil> "),fflush(stdout),fgets(zLine, sizeof(zLine), stdin) ){ |
| 66 | /* Parse the line of input */ |
| 67 | n = (int)strlen(zLine); |
| 68 | for(i=0, nArg=1; i<n; i++){ |
| 69 | while( fossil_isspace(zLine[i]) ){ i++; } |
| 70 | if( i>=n ) break; |
| 71 |
| --- src/fshell.c | |
| +++ src/fshell.c | |
| @@ -25,10 +25,11 @@ | |
| 25 | ** It allows multiple commands to be issued without having to reenter the |
| 26 | ** crypto phasephrase for each command. |
| 27 | */ |
| 28 | #include "config.h" |
| 29 | #include "fshell.h" |
| 30 | #include "linenoise.h" |
| 31 | #include <ctype.h> |
| 32 | |
| 33 | #ifndef _WIN32 |
| 34 | #include <sys/types.h> |
| 35 | #include <sys/wait.h> |
| @@ -55,16 +56,19 @@ | |
| 56 | int mxArg = 0; |
| 57 | int n, i; |
| 58 | char **azArg = 0; |
| 59 | int fDebug; |
| 60 | pid_t childPid; |
| 61 | char *zLine = 0; |
| 62 | fDebug = find_option("debug", 0, 0)!=0; |
| 63 | db_find_and_open_repository(OPEN_ANY_SCHEMA|OPEN_OK_NOT_FOUND, 0); |
| 64 | db_close(0); |
| 65 | sqlite3_shutdown(); |
| 66 | while( (free(zLine), zLine = linenoise("fossil> ")) ){ |
| 67 | /* Remember shell history within the current session */ |
| 68 | linenoiseHistoryAdd(zLine); |
| 69 | |
| 70 | /* Parse the line of input */ |
| 71 | n = (int)strlen(zLine); |
| 72 | for(i=0, nArg=1; i<n; i++){ |
| 73 | while( fossil_isspace(zLine[i]) ){ i++; } |
| 74 | if( i>=n ) break; |
| 75 |
+4
-7
| --- src/fusefs.c | ||
| +++ src/fusefs.c | ||
| @@ -20,20 +20,20 @@ | ||
| 20 | 20 | ** |
| 21 | 21 | ** This module is a mostly a no-op unless compiled with -DFOSSIL_HAVE_FUSEFS. |
| 22 | 22 | ** The FOSSIL_HAVE_FUSEFS should be omitted on systems that lack support for |
| 23 | 23 | ** the Fuse Filesystem, of course. |
| 24 | 24 | */ |
| 25 | +#ifdef FOSSIL_HAVE_FUSEFS | |
| 25 | 26 | #include "config.h" |
| 26 | 27 | #include <stdio.h> |
| 27 | 28 | #include <string.h> |
| 28 | 29 | #include <errno.h> |
| 29 | 30 | #include <fcntl.h> |
| 30 | 31 | #include <stdlib.h> |
| 31 | 32 | #include <unistd.h> |
| 32 | 33 | #include <sys/types.h> |
| 33 | 34 | #include "fusefs.h" |
| 34 | -#ifdef FOSSIL_HAVE_FUSEFS | |
| 35 | 35 | |
| 36 | 36 | #define FUSE_USE_VERSION 26 |
| 37 | 37 | #include <fuse.h> |
| 38 | 38 | |
| 39 | 39 | /* |
| @@ -207,11 +207,12 @@ | ||
| 207 | 207 | filler(buf, ".", NULL, 0); |
| 208 | 208 | filler(buf, "..", NULL, 0); |
| 209 | 209 | manifest_file_rewind(fusefs.pMan); |
| 210 | 210 | if( n==2 ){ |
| 211 | 211 | while( (pFile = manifest_file_next(fusefs.pMan, 0))!=0 ){ |
| 212 | - if( nPrev>0 && strncmp(pFile->zName, zPrev, nPrev)==0 ) continue; | |
| 212 | + if( nPrev>0 && strncmp(pFile->zName, zPrev, nPrev)==0 | |
| 213 | + && pFile->zName[nPrev]=='/' ) continue; | |
| 213 | 214 | zPrev = pFile->zName; |
| 214 | 215 | for(nPrev=0; zPrev[nPrev] && zPrev[nPrev]!='/'; nPrev++){} |
| 215 | 216 | z = mprintf("%.*s", nPrev, zPrev); |
| 216 | 217 | filler(buf, z, NULL, 0); |
| 217 | 218 | fossil_free(z); |
| @@ -282,11 +283,10 @@ | ||
| 282 | 283 | static struct fuse_operations fusefs_methods = { |
| 283 | 284 | .getattr = fusefs_getattr, |
| 284 | 285 | .readdir = fusefs_readdir, |
| 285 | 286 | .read = fusefs_read, |
| 286 | 287 | }; |
| 287 | -#endif /* FOSSIL_HAVE_FUSEFS */ | |
| 288 | 288 | |
| 289 | 289 | /* |
| 290 | 290 | ** COMMAND: fusefs |
| 291 | 291 | ** |
| 292 | 292 | ** Usage: %fossil fusefs [--debug] DIRECTORY |
| @@ -314,13 +314,10 @@ | ||
| 314 | 314 | ** After stopping the "fossil fusefs" command, it might also be necessary |
| 315 | 315 | ** to run "fusermount -u DIRECTORY" to reset the FuseFS before using it |
| 316 | 316 | ** again. |
| 317 | 317 | */ |
| 318 | 318 | void fusefs_cmd(void){ |
| 319 | -#ifndef FOSSIL_HAVE_FUSEFS | |
| 320 | - fossil_fatal("this build of fossil does not support the fuse filesystem"); | |
| 321 | -#else | |
| 322 | 319 | char *zMountPoint; |
| 323 | 320 | char *azNewArgv[5]; |
| 324 | 321 | int doDebug = find_option("debug","d",0)!=0; |
| 325 | 322 | |
| 326 | 323 | db_find_and_open_repository(0,0); |
| @@ -338,7 +335,7 @@ | ||
| 338 | 335 | azNewArgv[4] = 0; |
| 339 | 336 | g.localOpen = 0; /* Prevent tags like "current" and "prev" */ |
| 340 | 337 | fuse_main(4, azNewArgv, &fusefs_methods, NULL); |
| 341 | 338 | fusefs_reset(); |
| 342 | 339 | fusefs_clear_path(); |
| 343 | -#endif | |
| 344 | 340 | } |
| 341 | +#endif /* FOSSIL_HAVE_FUSEFS */ | |
| 345 | 342 |
| --- src/fusefs.c | |
| +++ src/fusefs.c | |
| @@ -20,20 +20,20 @@ | |
| 20 | ** |
| 21 | ** This module is a mostly a no-op unless compiled with -DFOSSIL_HAVE_FUSEFS. |
| 22 | ** The FOSSIL_HAVE_FUSEFS should be omitted on systems that lack support for |
| 23 | ** the Fuse Filesystem, of course. |
| 24 | */ |
| 25 | #include "config.h" |
| 26 | #include <stdio.h> |
| 27 | #include <string.h> |
| 28 | #include <errno.h> |
| 29 | #include <fcntl.h> |
| 30 | #include <stdlib.h> |
| 31 | #include <unistd.h> |
| 32 | #include <sys/types.h> |
| 33 | #include "fusefs.h" |
| 34 | #ifdef FOSSIL_HAVE_FUSEFS |
| 35 | |
| 36 | #define FUSE_USE_VERSION 26 |
| 37 | #include <fuse.h> |
| 38 | |
| 39 | /* |
| @@ -207,11 +207,12 @@ | |
| 207 | filler(buf, ".", NULL, 0); |
| 208 | filler(buf, "..", NULL, 0); |
| 209 | manifest_file_rewind(fusefs.pMan); |
| 210 | if( n==2 ){ |
| 211 | while( (pFile = manifest_file_next(fusefs.pMan, 0))!=0 ){ |
| 212 | if( nPrev>0 && strncmp(pFile->zName, zPrev, nPrev)==0 ) continue; |
| 213 | zPrev = pFile->zName; |
| 214 | for(nPrev=0; zPrev[nPrev] && zPrev[nPrev]!='/'; nPrev++){} |
| 215 | z = mprintf("%.*s", nPrev, zPrev); |
| 216 | filler(buf, z, NULL, 0); |
| 217 | fossil_free(z); |
| @@ -282,11 +283,10 @@ | |
| 282 | static struct fuse_operations fusefs_methods = { |
| 283 | .getattr = fusefs_getattr, |
| 284 | .readdir = fusefs_readdir, |
| 285 | .read = fusefs_read, |
| 286 | }; |
| 287 | #endif /* FOSSIL_HAVE_FUSEFS */ |
| 288 | |
| 289 | /* |
| 290 | ** COMMAND: fusefs |
| 291 | ** |
| 292 | ** Usage: %fossil fusefs [--debug] DIRECTORY |
| @@ -314,13 +314,10 @@ | |
| 314 | ** After stopping the "fossil fusefs" command, it might also be necessary |
| 315 | ** to run "fusermount -u DIRECTORY" to reset the FuseFS before using it |
| 316 | ** again. |
| 317 | */ |
| 318 | void fusefs_cmd(void){ |
| 319 | #ifndef FOSSIL_HAVE_FUSEFS |
| 320 | fossil_fatal("this build of fossil does not support the fuse filesystem"); |
| 321 | #else |
| 322 | char *zMountPoint; |
| 323 | char *azNewArgv[5]; |
| 324 | int doDebug = find_option("debug","d",0)!=0; |
| 325 | |
| 326 | db_find_and_open_repository(0,0); |
| @@ -338,7 +335,7 @@ | |
| 338 | azNewArgv[4] = 0; |
| 339 | g.localOpen = 0; /* Prevent tags like "current" and "prev" */ |
| 340 | fuse_main(4, azNewArgv, &fusefs_methods, NULL); |
| 341 | fusefs_reset(); |
| 342 | fusefs_clear_path(); |
| 343 | #endif |
| 344 | } |
| 345 |
| --- src/fusefs.c | |
| +++ src/fusefs.c | |
| @@ -20,20 +20,20 @@ | |
| 20 | ** |
| 21 | ** This module is a mostly a no-op unless compiled with -DFOSSIL_HAVE_FUSEFS. |
| 22 | ** The FOSSIL_HAVE_FUSEFS should be omitted on systems that lack support for |
| 23 | ** the Fuse Filesystem, of course. |
| 24 | */ |
| 25 | #ifdef FOSSIL_HAVE_FUSEFS |
| 26 | #include "config.h" |
| 27 | #include <stdio.h> |
| 28 | #include <string.h> |
| 29 | #include <errno.h> |
| 30 | #include <fcntl.h> |
| 31 | #include <stdlib.h> |
| 32 | #include <unistd.h> |
| 33 | #include <sys/types.h> |
| 34 | #include "fusefs.h" |
| 35 | |
| 36 | #define FUSE_USE_VERSION 26 |
| 37 | #include <fuse.h> |
| 38 | |
| 39 | /* |
| @@ -207,11 +207,12 @@ | |
| 207 | filler(buf, ".", NULL, 0); |
| 208 | filler(buf, "..", NULL, 0); |
| 209 | manifest_file_rewind(fusefs.pMan); |
| 210 | if( n==2 ){ |
| 211 | while( (pFile = manifest_file_next(fusefs.pMan, 0))!=0 ){ |
| 212 | if( nPrev>0 && strncmp(pFile->zName, zPrev, nPrev)==0 |
| 213 | && pFile->zName[nPrev]=='/' ) continue; |
| 214 | zPrev = pFile->zName; |
| 215 | for(nPrev=0; zPrev[nPrev] && zPrev[nPrev]!='/'; nPrev++){} |
| 216 | z = mprintf("%.*s", nPrev, zPrev); |
| 217 | filler(buf, z, NULL, 0); |
| 218 | fossil_free(z); |
| @@ -282,11 +283,10 @@ | |
| 283 | static struct fuse_operations fusefs_methods = { |
| 284 | .getattr = fusefs_getattr, |
| 285 | .readdir = fusefs_readdir, |
| 286 | .read = fusefs_read, |
| 287 | }; |
| 288 | |
| 289 | /* |
| 290 | ** COMMAND: fusefs |
| 291 | ** |
| 292 | ** Usage: %fossil fusefs [--debug] DIRECTORY |
| @@ -314,13 +314,10 @@ | |
| 314 | ** After stopping the "fossil fusefs" command, it might also be necessary |
| 315 | ** to run "fusermount -u DIRECTORY" to reset the FuseFS before using it |
| 316 | ** again. |
| 317 | */ |
| 318 | void fusefs_cmd(void){ |
| 319 | char *zMountPoint; |
| 320 | char *azNewArgv[5]; |
| 321 | int doDebug = find_option("debug","d",0)!=0; |
| 322 | |
| 323 | db_find_and_open_repository(0,0); |
| @@ -338,7 +335,7 @@ | |
| 335 | azNewArgv[4] = 0; |
| 336 | g.localOpen = 0; /* Prevent tags like "current" and "prev" */ |
| 337 | fuse_main(4, azNewArgv, &fusefs_methods, NULL); |
| 338 | fusefs_reset(); |
| 339 | fusefs_clear_path(); |
| 340 | } |
| 341 | #endif /* FOSSIL_HAVE_FUSEFS */ |
| 342 |
+19
-4
| --- src/graph.c | ||
| +++ src/graph.c | ||
| @@ -258,11 +258,10 @@ | ||
| 258 | 258 | int iRail = pBottom->iRail; |
| 259 | 259 | GraphRow *pCurrent; |
| 260 | 260 | GraphRow *pPrior; |
| 261 | 261 | u64 mask = ((u64)1)<<iRail; |
| 262 | 262 | |
| 263 | - pBottom->iRail = iRail; | |
| 264 | 263 | pBottom->railInUse |= mask; |
| 265 | 264 | pPrior = pBottom; |
| 266 | 265 | for(pCurrent=pBottom->pChild; pCurrent; pCurrent=pCurrent->pChild){ |
| 267 | 266 | assert( pPrior->idx > pCurrent->idx ); |
| 268 | 267 | assert( pCurrent->iRail<0 ); |
| @@ -344,14 +343,16 @@ | ||
| 344 | 343 | /* |
| 345 | 344 | ** Compute the complete graph |
| 346 | 345 | */ |
| 347 | 346 | void graph_finish(GraphContext *p, int omitDescenders){ |
| 348 | 347 | GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent; |
| 349 | - int i; | |
| 348 | + int i, j; | |
| 350 | 349 | u64 mask; |
| 351 | 350 | int hasDup = 0; /* True if one or more isDup entries */ |
| 352 | 351 | const char *zTrunk; |
| 352 | + int railRid[GR_MAX_RAIL]; /* Maps rails to rids for lines | |
| 353 | + that enter from bottom of screen */ | |
| 353 | 354 | |
| 354 | 355 | if( p==0 || p->pFirst==0 || p->nErr ) return; |
| 355 | 356 | p->nErr = 1; /* Assume an error until proven otherwise */ |
| 356 | 357 | |
| 357 | 358 | /* Initialize all rows */ |
| @@ -366,10 +367,11 @@ | ||
| 366 | 367 | pDup->isDup = 1; |
| 367 | 368 | } |
| 368 | 369 | hashInsert(p, pRow, 1); |
| 369 | 370 | } |
| 370 | 371 | p->mxRail = -1; |
| 372 | + memset(railRid, 0, sizeof(railRid)); | |
| 371 | 373 | |
| 372 | 374 | /* Purge merge-parents that are out-of-graph if descenders are not |
| 373 | 375 | ** drawn. |
| 374 | 376 | ** |
| 375 | 377 | ** Each node has one primary parent and zero or more "merge" parents. |
| @@ -458,10 +460,13 @@ | ||
| 458 | 460 | } |
| 459 | 461 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 460 | 462 | mask = BIT(pRow->iRail); |
| 461 | 463 | if( !omitDescenders ){ |
| 462 | 464 | pRow->bDescender = pRow->nParent>0; |
| 465 | + if( pRow->bDescender ){ | |
| 466 | + railRid[pRow->iRail] = pRow->aParent[0]; | |
| 467 | + } | |
| 463 | 468 | for(pLoop=pRow; pLoop; pLoop=pLoop->pNext){ |
| 464 | 469 | pLoop->railInUse |= mask; |
| 465 | 470 | } |
| 466 | 471 | } |
| 467 | 472 | assignChildrenToRail(pRow); |
| @@ -536,12 +541,22 @@ | ||
| 536 | 541 | for(i=1; i<pRow->nParent; i++){ |
| 537 | 542 | int parentRid = pRow->aParent[i]; |
| 538 | 543 | pDesc = hashFind(p, parentRid); |
| 539 | 544 | if( pDesc==0 ){ |
| 540 | 545 | /* Merge from a node that is off-screen */ |
| 541 | - int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0); | |
| 542 | - if( p->mxRail>=GR_MAX_RAIL ) return; | |
| 546 | + int iMrail = -1; | |
| 547 | + for(j=0; j<GR_MAX_RAIL; j++){ | |
| 548 | + if( railRid[j]==parentRid ){ | |
| 549 | + iMrail = j; | |
| 550 | + break; | |
| 551 | + } | |
| 552 | + } | |
| 553 | + if( iMrail==-1 ){ | |
| 554 | + iMrail = findFreeRail(p, pRow->idx, p->nRow, 0); | |
| 555 | + if( p->mxRail>=GR_MAX_RAIL ) return; | |
| 556 | + railRid[iMrail] = parentRid; | |
| 557 | + } | |
| 543 | 558 | mask = BIT(iMrail); |
| 544 | 559 | pRow->mergeIn[iMrail] = 1; |
| 545 | 560 | pRow->mergeDown |= mask; |
| 546 | 561 | for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){ |
| 547 | 562 | pLoop->railInUse |= mask; |
| 548 | 563 |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -258,11 +258,10 @@ | |
| 258 | int iRail = pBottom->iRail; |
| 259 | GraphRow *pCurrent; |
| 260 | GraphRow *pPrior; |
| 261 | u64 mask = ((u64)1)<<iRail; |
| 262 | |
| 263 | pBottom->iRail = iRail; |
| 264 | pBottom->railInUse |= mask; |
| 265 | pPrior = pBottom; |
| 266 | for(pCurrent=pBottom->pChild; pCurrent; pCurrent=pCurrent->pChild){ |
| 267 | assert( pPrior->idx > pCurrent->idx ); |
| 268 | assert( pCurrent->iRail<0 ); |
| @@ -344,14 +343,16 @@ | |
| 344 | /* |
| 345 | ** Compute the complete graph |
| 346 | */ |
| 347 | void graph_finish(GraphContext *p, int omitDescenders){ |
| 348 | GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent; |
| 349 | int i; |
| 350 | u64 mask; |
| 351 | int hasDup = 0; /* True if one or more isDup entries */ |
| 352 | const char *zTrunk; |
| 353 | |
| 354 | if( p==0 || p->pFirst==0 || p->nErr ) return; |
| 355 | p->nErr = 1; /* Assume an error until proven otherwise */ |
| 356 | |
| 357 | /* Initialize all rows */ |
| @@ -366,10 +367,11 @@ | |
| 366 | pDup->isDup = 1; |
| 367 | } |
| 368 | hashInsert(p, pRow, 1); |
| 369 | } |
| 370 | p->mxRail = -1; |
| 371 | |
| 372 | /* Purge merge-parents that are out-of-graph if descenders are not |
| 373 | ** drawn. |
| 374 | ** |
| 375 | ** Each node has one primary parent and zero or more "merge" parents. |
| @@ -458,10 +460,13 @@ | |
| 458 | } |
| 459 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 460 | mask = BIT(pRow->iRail); |
| 461 | if( !omitDescenders ){ |
| 462 | pRow->bDescender = pRow->nParent>0; |
| 463 | for(pLoop=pRow; pLoop; pLoop=pLoop->pNext){ |
| 464 | pLoop->railInUse |= mask; |
| 465 | } |
| 466 | } |
| 467 | assignChildrenToRail(pRow); |
| @@ -536,12 +541,22 @@ | |
| 536 | for(i=1; i<pRow->nParent; i++){ |
| 537 | int parentRid = pRow->aParent[i]; |
| 538 | pDesc = hashFind(p, parentRid); |
| 539 | if( pDesc==0 ){ |
| 540 | /* Merge from a node that is off-screen */ |
| 541 | int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0); |
| 542 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 543 | mask = BIT(iMrail); |
| 544 | pRow->mergeIn[iMrail] = 1; |
| 545 | pRow->mergeDown |= mask; |
| 546 | for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){ |
| 547 | pLoop->railInUse |= mask; |
| 548 |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -258,11 +258,10 @@ | |
| 258 | int iRail = pBottom->iRail; |
| 259 | GraphRow *pCurrent; |
| 260 | GraphRow *pPrior; |
| 261 | u64 mask = ((u64)1)<<iRail; |
| 262 | |
| 263 | pBottom->railInUse |= mask; |
| 264 | pPrior = pBottom; |
| 265 | for(pCurrent=pBottom->pChild; pCurrent; pCurrent=pCurrent->pChild){ |
| 266 | assert( pPrior->idx > pCurrent->idx ); |
| 267 | assert( pCurrent->iRail<0 ); |
| @@ -344,14 +343,16 @@ | |
| 343 | /* |
| 344 | ** Compute the complete graph |
| 345 | */ |
| 346 | void graph_finish(GraphContext *p, int omitDescenders){ |
| 347 | GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent; |
| 348 | int i, j; |
| 349 | u64 mask; |
| 350 | int hasDup = 0; /* True if one or more isDup entries */ |
| 351 | const char *zTrunk; |
| 352 | int railRid[GR_MAX_RAIL]; /* Maps rails to rids for lines |
| 353 | that enter from bottom of screen */ |
| 354 | |
| 355 | if( p==0 || p->pFirst==0 || p->nErr ) return; |
| 356 | p->nErr = 1; /* Assume an error until proven otherwise */ |
| 357 | |
| 358 | /* Initialize all rows */ |
| @@ -366,10 +367,11 @@ | |
| 367 | pDup->isDup = 1; |
| 368 | } |
| 369 | hashInsert(p, pRow, 1); |
| 370 | } |
| 371 | p->mxRail = -1; |
| 372 | memset(railRid, 0, sizeof(railRid)); |
| 373 | |
| 374 | /* Purge merge-parents that are out-of-graph if descenders are not |
| 375 | ** drawn. |
| 376 | ** |
| 377 | ** Each node has one primary parent and zero or more "merge" parents. |
| @@ -458,10 +460,13 @@ | |
| 460 | } |
| 461 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 462 | mask = BIT(pRow->iRail); |
| 463 | if( !omitDescenders ){ |
| 464 | pRow->bDescender = pRow->nParent>0; |
| 465 | if( pRow->bDescender ){ |
| 466 | railRid[pRow->iRail] = pRow->aParent[0]; |
| 467 | } |
| 468 | for(pLoop=pRow; pLoop; pLoop=pLoop->pNext){ |
| 469 | pLoop->railInUse |= mask; |
| 470 | } |
| 471 | } |
| 472 | assignChildrenToRail(pRow); |
| @@ -536,12 +541,22 @@ | |
| 541 | for(i=1; i<pRow->nParent; i++){ |
| 542 | int parentRid = pRow->aParent[i]; |
| 543 | pDesc = hashFind(p, parentRid); |
| 544 | if( pDesc==0 ){ |
| 545 | /* Merge from a node that is off-screen */ |
| 546 | int iMrail = -1; |
| 547 | for(j=0; j<GR_MAX_RAIL; j++){ |
| 548 | if( railRid[j]==parentRid ){ |
| 549 | iMrail = j; |
| 550 | break; |
| 551 | } |
| 552 | } |
| 553 | if( iMrail==-1 ){ |
| 554 | iMrail = findFreeRail(p, pRow->idx, p->nRow, 0); |
| 555 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 556 | railRid[iMrail] = parentRid; |
| 557 | } |
| 558 | mask = BIT(iMrail); |
| 559 | pRow->mergeIn[iMrail] = 1; |
| 560 | pRow->mergeDown |= mask; |
| 561 | for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){ |
| 562 | pLoop->railInUse |= mask; |
| 563 |
+3
-4
| --- src/http_socket.c | ||
| +++ src/http_socket.c | ||
| @@ -23,20 +23,19 @@ | ||
| 23 | 23 | ** of the server is held in global variables that are set by url_parse(). |
| 24 | 24 | ** |
| 25 | 25 | ** Low-level sockets are abstracted out into this module because they |
| 26 | 26 | ** are handled different on Unix and windows. |
| 27 | 27 | */ |
| 28 | - | |
| 28 | +#if defined(_WIN32) | |
| 29 | +# define _WIN32_WINNT 0x501 | |
| 30 | +#endif | |
| 29 | 31 | #ifndef __EXTENSIONS__ |
| 30 | 32 | # define __EXTENSIONS__ 1 /* IPv6 won't compile on Solaris without this */ |
| 31 | 33 | #endif |
| 32 | 34 | #include "config.h" |
| 33 | 35 | #include "http_socket.h" |
| 34 | 36 | #if defined(_WIN32) |
| 35 | -# if !defined(_WIN32_WINNT) | |
| 36 | -# define _WIN32_WINNT 0x0501 | |
| 37 | -# endif | |
| 38 | 37 | # include <winsock2.h> |
| 39 | 38 | # include <ws2tcpip.h> |
| 40 | 39 | #else |
| 41 | 40 | # include <netinet/in.h> |
| 42 | 41 | # include <arpa/inet.h> |
| 43 | 42 |
| --- src/http_socket.c | |
| +++ src/http_socket.c | |
| @@ -23,20 +23,19 @@ | |
| 23 | ** of the server is held in global variables that are set by url_parse(). |
| 24 | ** |
| 25 | ** Low-level sockets are abstracted out into this module because they |
| 26 | ** are handled different on Unix and windows. |
| 27 | */ |
| 28 | |
| 29 | #ifndef __EXTENSIONS__ |
| 30 | # define __EXTENSIONS__ 1 /* IPv6 won't compile on Solaris without this */ |
| 31 | #endif |
| 32 | #include "config.h" |
| 33 | #include "http_socket.h" |
| 34 | #if defined(_WIN32) |
| 35 | # if !defined(_WIN32_WINNT) |
| 36 | # define _WIN32_WINNT 0x0501 |
| 37 | # endif |
| 38 | # include <winsock2.h> |
| 39 | # include <ws2tcpip.h> |
| 40 | #else |
| 41 | # include <netinet/in.h> |
| 42 | # include <arpa/inet.h> |
| 43 |
| --- src/http_socket.c | |
| +++ src/http_socket.c | |
| @@ -23,20 +23,19 @@ | |
| 23 | ** of the server is held in global variables that are set by url_parse(). |
| 24 | ** |
| 25 | ** Low-level sockets are abstracted out into this module because they |
| 26 | ** are handled different on Unix and windows. |
| 27 | */ |
| 28 | #if defined(_WIN32) |
| 29 | # define _WIN32_WINNT 0x501 |
| 30 | #endif |
| 31 | #ifndef __EXTENSIONS__ |
| 32 | # define __EXTENSIONS__ 1 /* IPv6 won't compile on Solaris without this */ |
| 33 | #endif |
| 34 | #include "config.h" |
| 35 | #include "http_socket.h" |
| 36 | #if defined(_WIN32) |
| 37 | # include <winsock2.h> |
| 38 | # include <ws2tcpip.h> |
| 39 | #else |
| 40 | # include <netinet/in.h> |
| 41 | # include <arpa/inet.h> |
| 42 |
+9
-8
| --- src/import.c | ||
| +++ src/import.c | ||
| @@ -1612,11 +1612,11 @@ | ||
| 1612 | 1612 | {"rename-branch", &gimport.zBranchPre, "", &gimport.zBranchSuf, "", 3}, |
| 1613 | 1613 | {"rename-tag" , &gimport.zTagPre , "", &gimport.zTagSuf , "", 3}, |
| 1614 | 1614 | {"rename-rev" , &gsvn.zRevPre, "svn-rev-", &gsvn.zRevSuf , "", 2}, |
| 1615 | 1615 | }, *renOpt = renOpts; |
| 1616 | 1616 | int i; |
| 1617 | - for( i = 0; i < sizeof(renOpts) / sizeof(*renOpts); ++i, ++renOpt ){ | |
| 1617 | + for( i = 0; i < count(renOpts); ++i, ++renOpt ){ | |
| 1618 | 1618 | if( 1 << svnFlag & renOpt->format ){ |
| 1619 | 1619 | const char *zArgument = find_option(renOpt->zOpt, 0, 1); |
| 1620 | 1620 | if( zArgument ){ |
| 1621 | 1621 | const char *sep = strchr(zArgument, '%'); |
| 1622 | 1622 | if( !sep ){ |
| @@ -1761,21 +1761,22 @@ | ||
| 1761 | 1761 | ** times but only the last tag should be used. And we do not know which |
| 1762 | 1762 | ** occurrence of the tag is the last until the import finishes. |
| 1763 | 1763 | */ |
| 1764 | 1764 | db_multi_exec( |
| 1765 | 1765 | "CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT);" |
| 1766 | + "CREATE INDEX temp.i_xmark ON xmark(trid);" | |
| 1766 | 1767 | "CREATE TEMP TABLE xbranch(tname TEXT UNIQUE, brnm TEXT);" |
| 1767 | 1768 | "CREATE TEMP TABLE xtag(tname TEXT UNIQUE, tcontent TEXT);" |
| 1768 | 1769 | ); |
| 1769 | 1770 | |
| 1770 | 1771 | if( markfile_in ){ |
| 1771 | 1772 | FILE *f = fossil_fopen(markfile_in, "r"); |
| 1772 | 1773 | if( !f ){ |
| 1773 | - fossil_fatal("cannot open %s for reading\n", markfile_in); | |
| 1774 | + fossil_fatal("cannot open %s for reading", markfile_in); | |
| 1774 | 1775 | } |
| 1775 | - if(import_marks(f, &blobs, NULL)<0){ | |
| 1776 | - fossil_fatal("error importing marks from file: %s\n", markfile_in); | |
| 1776 | + if( import_marks(f, &blobs, NULL, NULL)<0 ){ | |
| 1777 | + fossil_fatal("error importing marks from file: %s", markfile_in); | |
| 1777 | 1778 | } |
| 1778 | 1779 | fclose(f); |
| 1779 | 1780 | } |
| 1780 | 1781 | |
| 1781 | 1782 | manifest_crosslink_begin(); |
| @@ -1795,21 +1796,21 @@ | ||
| 1795 | 1796 | db_prepare(&q_marks, "SELECT DISTINCT trid FROM xmark"); |
| 1796 | 1797 | while( db_step(&q_marks)==SQLITE_ROW ){ |
| 1797 | 1798 | rid = db_column_int(&q_marks, 0); |
| 1798 | 1799 | if( db_int(0, "SELECT count(objid) FROM event" |
| 1799 | 1800 | " WHERE objid=%d AND type='ci'", rid)==0 ){ |
| 1800 | - if( bag_find(&blobs, rid)==0 ){ | |
| 1801 | - bag_insert(&blobs, rid); | |
| 1802 | - } | |
| 1801 | + /* Blob marks exported by git aren't saved between runs, so they need | |
| 1802 | + ** to be left free for git to re-use in the future. | |
| 1803 | + */ | |
| 1803 | 1804 | }else{ |
| 1804 | 1805 | bag_insert(&vers, rid); |
| 1805 | 1806 | } |
| 1806 | 1807 | } |
| 1807 | 1808 | db_finalize(&q_marks); |
| 1808 | 1809 | f = fossil_fopen(markfile_out, "w"); |
| 1809 | 1810 | if( !f ){ |
| 1810 | - fossil_fatal("cannot open %s for writing\n", markfile_out); | |
| 1811 | + fossil_fatal("cannot open %s for writing", markfile_out); | |
| 1811 | 1812 | } |
| 1812 | 1813 | export_marks(f, &blobs, &vers); |
| 1813 | 1814 | fclose(f); |
| 1814 | 1815 | bag_clear(&blobs); |
| 1815 | 1816 | bag_clear(&vers); |
| 1816 | 1817 |
| --- src/import.c | |
| +++ src/import.c | |
| @@ -1612,11 +1612,11 @@ | |
| 1612 | {"rename-branch", &gimport.zBranchPre, "", &gimport.zBranchSuf, "", 3}, |
| 1613 | {"rename-tag" , &gimport.zTagPre , "", &gimport.zTagSuf , "", 3}, |
| 1614 | {"rename-rev" , &gsvn.zRevPre, "svn-rev-", &gsvn.zRevSuf , "", 2}, |
| 1615 | }, *renOpt = renOpts; |
| 1616 | int i; |
| 1617 | for( i = 0; i < sizeof(renOpts) / sizeof(*renOpts); ++i, ++renOpt ){ |
| 1618 | if( 1 << svnFlag & renOpt->format ){ |
| 1619 | const char *zArgument = find_option(renOpt->zOpt, 0, 1); |
| 1620 | if( zArgument ){ |
| 1621 | const char *sep = strchr(zArgument, '%'); |
| 1622 | if( !sep ){ |
| @@ -1761,21 +1761,22 @@ | |
| 1761 | ** times but only the last tag should be used. And we do not know which |
| 1762 | ** occurrence of the tag is the last until the import finishes. |
| 1763 | */ |
| 1764 | db_multi_exec( |
| 1765 | "CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT);" |
| 1766 | "CREATE TEMP TABLE xbranch(tname TEXT UNIQUE, brnm TEXT);" |
| 1767 | "CREATE TEMP TABLE xtag(tname TEXT UNIQUE, tcontent TEXT);" |
| 1768 | ); |
| 1769 | |
| 1770 | if( markfile_in ){ |
| 1771 | FILE *f = fossil_fopen(markfile_in, "r"); |
| 1772 | if( !f ){ |
| 1773 | fossil_fatal("cannot open %s for reading\n", markfile_in); |
| 1774 | } |
| 1775 | if(import_marks(f, &blobs, NULL)<0){ |
| 1776 | fossil_fatal("error importing marks from file: %s\n", markfile_in); |
| 1777 | } |
| 1778 | fclose(f); |
| 1779 | } |
| 1780 | |
| 1781 | manifest_crosslink_begin(); |
| @@ -1795,21 +1796,21 @@ | |
| 1795 | db_prepare(&q_marks, "SELECT DISTINCT trid FROM xmark"); |
| 1796 | while( db_step(&q_marks)==SQLITE_ROW ){ |
| 1797 | rid = db_column_int(&q_marks, 0); |
| 1798 | if( db_int(0, "SELECT count(objid) FROM event" |
| 1799 | " WHERE objid=%d AND type='ci'", rid)==0 ){ |
| 1800 | if( bag_find(&blobs, rid)==0 ){ |
| 1801 | bag_insert(&blobs, rid); |
| 1802 | } |
| 1803 | }else{ |
| 1804 | bag_insert(&vers, rid); |
| 1805 | } |
| 1806 | } |
| 1807 | db_finalize(&q_marks); |
| 1808 | f = fossil_fopen(markfile_out, "w"); |
| 1809 | if( !f ){ |
| 1810 | fossil_fatal("cannot open %s for writing\n", markfile_out); |
| 1811 | } |
| 1812 | export_marks(f, &blobs, &vers); |
| 1813 | fclose(f); |
| 1814 | bag_clear(&blobs); |
| 1815 | bag_clear(&vers); |
| 1816 |
| --- src/import.c | |
| +++ src/import.c | |
| @@ -1612,11 +1612,11 @@ | |
| 1612 | {"rename-branch", &gimport.zBranchPre, "", &gimport.zBranchSuf, "", 3}, |
| 1613 | {"rename-tag" , &gimport.zTagPre , "", &gimport.zTagSuf , "", 3}, |
| 1614 | {"rename-rev" , &gsvn.zRevPre, "svn-rev-", &gsvn.zRevSuf , "", 2}, |
| 1615 | }, *renOpt = renOpts; |
| 1616 | int i; |
| 1617 | for( i = 0; i < count(renOpts); ++i, ++renOpt ){ |
| 1618 | if( 1 << svnFlag & renOpt->format ){ |
| 1619 | const char *zArgument = find_option(renOpt->zOpt, 0, 1); |
| 1620 | if( zArgument ){ |
| 1621 | const char *sep = strchr(zArgument, '%'); |
| 1622 | if( !sep ){ |
| @@ -1761,21 +1761,22 @@ | |
| 1761 | ** times but only the last tag should be used. And we do not know which |
| 1762 | ** occurrence of the tag is the last until the import finishes. |
| 1763 | */ |
| 1764 | db_multi_exec( |
| 1765 | "CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT);" |
| 1766 | "CREATE INDEX temp.i_xmark ON xmark(trid);" |
| 1767 | "CREATE TEMP TABLE xbranch(tname TEXT UNIQUE, brnm TEXT);" |
| 1768 | "CREATE TEMP TABLE xtag(tname TEXT UNIQUE, tcontent TEXT);" |
| 1769 | ); |
| 1770 | |
| 1771 | if( markfile_in ){ |
| 1772 | FILE *f = fossil_fopen(markfile_in, "r"); |
| 1773 | if( !f ){ |
| 1774 | fossil_fatal("cannot open %s for reading", markfile_in); |
| 1775 | } |
| 1776 | if( import_marks(f, &blobs, NULL, NULL)<0 ){ |
| 1777 | fossil_fatal("error importing marks from file: %s", markfile_in); |
| 1778 | } |
| 1779 | fclose(f); |
| 1780 | } |
| 1781 | |
| 1782 | manifest_crosslink_begin(); |
| @@ -1795,21 +1796,21 @@ | |
| 1796 | db_prepare(&q_marks, "SELECT DISTINCT trid FROM xmark"); |
| 1797 | while( db_step(&q_marks)==SQLITE_ROW ){ |
| 1798 | rid = db_column_int(&q_marks, 0); |
| 1799 | if( db_int(0, "SELECT count(objid) FROM event" |
| 1800 | " WHERE objid=%d AND type='ci'", rid)==0 ){ |
| 1801 | /* Blob marks exported by git aren't saved between runs, so they need |
| 1802 | ** to be left free for git to re-use in the future. |
| 1803 | */ |
| 1804 | }else{ |
| 1805 | bag_insert(&vers, rid); |
| 1806 | } |
| 1807 | } |
| 1808 | db_finalize(&q_marks); |
| 1809 | f = fossil_fopen(markfile_out, "w"); |
| 1810 | if( !f ){ |
| 1811 | fossil_fatal("cannot open %s for writing", markfile_out); |
| 1812 | } |
| 1813 | export_marks(f, &blobs, &vers); |
| 1814 | fclose(f); |
| 1815 | bag_clear(&blobs); |
| 1816 | bag_clear(&vers); |
| 1817 |
+45
-61
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -231,11 +231,11 @@ | ||
| 231 | 231 | db_int(-1, "SELECT count(*) FROM event WHERE type='ci' /*scan*/")); |
| 232 | 232 | }else{ |
| 233 | 233 | int rid; |
| 234 | 234 | rid = name_to_rid(g.argv[2]); |
| 235 | 235 | if( rid==0 ){ |
| 236 | - fossil_fatal("no such object: %s\n", g.argv[2]); | |
| 236 | + fossil_fatal("no such object: %s", g.argv[2]); | |
| 237 | 237 | } |
| 238 | 238 | show_common_info(rid, "uuid:", 1, 1); |
| 239 | 239 | } |
| 240 | 240 | } |
| 241 | 241 | |
| @@ -826,15 +826,13 @@ | ||
| 826 | 826 | } |
| 827 | 827 | } |
| 828 | 828 | style_header("Update of \"%h\"", pWiki->zWikiTitle); |
| 829 | 829 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 830 | 830 | zDate = db_text(0, "SELECT datetime(%.17g)", pWiki->rDate); |
| 831 | - style_submenu_element("Raw", "Raw", "artifact/%s", zUuid); | |
| 832 | - style_submenu_element("History", "History", "whistory?name=%t", | |
| 833 | - pWiki->zWikiTitle); | |
| 834 | - style_submenu_element("Page", "Page", "wiki?name=%t", | |
| 835 | - pWiki->zWikiTitle); | |
| 831 | + style_submenu_element("Raw", "artifact/%s", zUuid); | |
| 832 | + style_submenu_element("History", "whistory?name=%t", pWiki->zWikiTitle); | |
| 833 | + style_submenu_element("Page", "wiki?name=%t", pWiki->zWikiTitle); | |
| 836 | 834 | login_anonymous_available(); |
| 837 | 835 | @ <div class="section">Overview</div> |
| 838 | 836 | @ <p><table class="label-value"> |
| 839 | 837 | @ <tr><th>Artifact ID:</th> |
| 840 | 838 | @ <td>%z(href("%R/artifact/%!S",zUuid))%s(zUuid)</a> |
| @@ -1053,50 +1051,47 @@ | ||
| 1053 | 1051 | if(zGlob && !*zGlob){ |
| 1054 | 1052 | zGlob = NULL; |
| 1055 | 1053 | } |
| 1056 | 1054 | diffFlags = construct_diff_flags(verboseFlag, sideBySide); |
| 1057 | 1055 | zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; |
| 1058 | - style_submenu_element("Path","path", | |
| 1059 | - "%R/timeline?me=%T&you=%T", zFrom, zTo); | |
| 1056 | + style_submenu_element("Path", "%R/timeline?me=%T&you=%T", zFrom, zTo); | |
| 1060 | 1057 | if( sideBySide || verboseFlag ){ |
| 1061 | - style_submenu_element("Hide Diff", "hidediff", | |
| 1062 | - "%R/vdiff?from=%T&to=%T&sbs=0%s%T%s", | |
| 1058 | + style_submenu_element("Hide Diff", "%R/vdiff?from=%T&to=%T&sbs=0%s%T%s", | |
| 1063 | 1059 | zFrom, zTo, |
| 1064 | 1060 | zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); |
| 1065 | 1061 | } |
| 1066 | 1062 | if( !sideBySide ){ |
| 1067 | - style_submenu_element("Side-by-Side Diff", "sbsdiff", | |
| 1063 | + style_submenu_element("Side-by-Side Diff", | |
| 1068 | 1064 | "%R/vdiff?from=%T&to=%T&sbs=1%s%T%s", |
| 1069 | 1065 | zFrom, zTo, |
| 1070 | 1066 | zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); |
| 1071 | 1067 | } |
| 1072 | 1068 | if( sideBySide || !verboseFlag ) { |
| 1073 | - style_submenu_element("Unified Diff", "udiff", | |
| 1069 | + style_submenu_element("Unified Diff", | |
| 1074 | 1070 | "%R/vdiff?from=%T&to=%T&sbs=0&v%s%T%s", |
| 1075 | 1071 | zFrom, zTo, |
| 1076 | 1072 | zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); |
| 1077 | 1073 | } |
| 1078 | - style_submenu_element("Invert", "invert", | |
| 1074 | + style_submenu_element("Invert", | |
| 1079 | 1075 | "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T%s", zTo, zFrom, |
| 1080 | 1076 | sideBySide, (verboseFlag && !sideBySide)?"&v":"", |
| 1081 | 1077 | zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); |
| 1082 | 1078 | if( zGlob ){ |
| 1083 | - style_submenu_element("Clear glob", "clearglob", | |
| 1079 | + style_submenu_element("Clear glob", | |
| 1084 | 1080 | "%R/vdiff?from=%T&to=%T&sbs=%d%s%s", zFrom, zTo, |
| 1085 | 1081 | sideBySide, (verboseFlag && !sideBySide)?"&v":"", zW); |
| 1086 | 1082 | }else{ |
| 1087 | - style_submenu_element("Patch", "patch", | |
| 1088 | - "%R/vpatch?from=%T&to=%T%s", zFrom, zTo, zW); | |
| 1083 | + style_submenu_element("Patch", "%R/vpatch?from=%T&to=%T%s", zFrom, zTo, zW); | |
| 1089 | 1084 | } |
| 1090 | 1085 | if( sideBySide || verboseFlag ){ |
| 1091 | 1086 | if( *zW ){ |
| 1092 | - style_submenu_element("Show Whitespace Differences", "whitespace", | |
| 1087 | + style_submenu_element("Show Whitespace Differences", | |
| 1093 | 1088 | "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T", zFrom, zTo, |
| 1094 | 1089 | sideBySide, (verboseFlag && !sideBySide)?"&v":"", |
| 1095 | 1090 | zGlob ? "&glob=" : "", zGlob ? zGlob : ""); |
| 1096 | 1091 | }else{ |
| 1097 | - style_submenu_element("Ignore Whitespace", "ignorews", | |
| 1092 | + style_submenu_element("Ignore Whitespace", | |
| 1098 | 1093 | "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T&w", zFrom, zTo, |
| 1099 | 1094 | sideBySide, (verboseFlag && !sideBySide)?"&v":"", |
| 1100 | 1095 | zGlob ? "&glob=" : "", zGlob ? zGlob : ""); |
| 1101 | 1096 | } |
| 1102 | 1097 | } |
| @@ -1514,26 +1509,26 @@ | ||
| 1514 | 1509 | diffFlags = construct_diff_flags(1, sideBySide) | DIFF_HTML; |
| 1515 | 1510 | |
| 1516 | 1511 | style_header("Diff"); |
| 1517 | 1512 | zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; |
| 1518 | 1513 | if( *zW ){ |
| 1519 | - style_submenu_element("Show Whitespace Changes", "Show Whitespace Changes", | |
| 1514 | + style_submenu_element("Show Whitespace Changes", | |
| 1520 | 1515 | "%s/fdiff?v1=%T&v2=%T&sbs=%d", |
| 1521 | 1516 | g.zTop, P("v1"), P("v2"), sideBySide); |
| 1522 | 1517 | }else{ |
| 1523 | - style_submenu_element("Ignore Whitespace", "Ignore Whitespace", | |
| 1518 | + style_submenu_element("Ignore Whitespace", | |
| 1524 | 1519 | "%s/fdiff?v1=%T&v2=%T&sbs=%d&w", |
| 1525 | 1520 | g.zTop, P("v1"), P("v2"), sideBySide); |
| 1526 | 1521 | } |
| 1527 | - style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch", | |
| 1522 | + style_submenu_element("Patch", "%s/fdiff?v1=%T&v2=%T&patch", | |
| 1528 | 1523 | g.zTop, P("v1"), P("v2")); |
| 1529 | 1524 | if( !sideBySide ){ |
| 1530 | - style_submenu_element("Side-by-Side Diff", "sbsdiff", | |
| 1525 | + style_submenu_element("Side-by-Side Diff", | |
| 1531 | 1526 | "%s/fdiff?v1=%T&v2=%T&sbs=1%s", |
| 1532 | 1527 | g.zTop, P("v1"), P("v2"), zW); |
| 1533 | 1528 | }else{ |
| 1534 | - style_submenu_element("Unified Diff", "udiff", | |
| 1529 | + style_submenu_element("Unified Diff", | |
| 1535 | 1530 | "%s/fdiff?v1=%T&v2=%T&sbs=0%s", |
| 1536 | 1531 | g.zTop, P("v1"), P("v2"), zW); |
| 1537 | 1532 | } |
| 1538 | 1533 | |
| 1539 | 1534 | if( P("smhdr")!=0 ){ |
| @@ -1672,15 +1667,14 @@ | ||
| 1672 | 1667 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1673 | 1668 | if( rid==0 ) fossil_redirect_home(); |
| 1674 | 1669 | if( g.perm.Admin ){ |
| 1675 | 1670 | const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1676 | 1671 | if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){ |
| 1677 | - style_submenu_element("Unshun","Unshun","%s/shun?accept=%s&sub=1#delshun", | |
| 1672 | + style_submenu_element("Unshun", "%s/shun?accept=%s&sub=1#delshun", | |
| 1678 | 1673 | g.zTop, zUuid); |
| 1679 | 1674 | }else{ |
| 1680 | - style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", | |
| 1681 | - g.zTop, zUuid); | |
| 1675 | + style_submenu_element("Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid); | |
| 1682 | 1676 | } |
| 1683 | 1677 | } |
| 1684 | 1678 | style_header("Hex Artifact Content"); |
| 1685 | 1679 | zUuid = db_text("?","SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1686 | 1680 | if( g.perm.Setup ){ |
| @@ -1689,12 +1683,12 @@ | ||
| 1689 | 1683 | @ <h2>Artifact %s(zUuid):</h2> |
| 1690 | 1684 | } |
| 1691 | 1685 | blob_zero(&downloadName); |
| 1692 | 1686 | if( P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL; |
| 1693 | 1687 | object_description(rid, objdescFlags, &downloadName); |
| 1694 | - style_submenu_element("Download", "Download", | |
| 1695 | - "%s/raw/%T?name=%s", g.zTop, blob_str(&downloadName), zUuid); | |
| 1688 | + style_submenu_element("Download", "%s/raw/%T?name=%s", | |
| 1689 | + g.zTop, blob_str(&downloadName), zUuid); | |
| 1696 | 1690 | @ <hr /> |
| 1697 | 1691 | content_get(rid, &content); |
| 1698 | 1692 | @ <blockquote><pre> |
| 1699 | 1693 | hexdump(&content); |
| 1700 | 1694 | @ </pre></blockquote> |
| @@ -1895,15 +1889,14 @@ | ||
| 1895 | 1889 | /*NOTREACHED*/ |
| 1896 | 1890 | } |
| 1897 | 1891 | if( g.perm.Admin ){ |
| 1898 | 1892 | const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1899 | 1893 | if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){ |
| 1900 | - style_submenu_element("Unshun","Unshun","%s/shun?accept=%s&sub=1#accshun", | |
| 1894 | + style_submenu_element("Unshun", "%s/shun?accept=%s&sub=1#accshun", | |
| 1901 | 1895 | g.zTop, zUuid); |
| 1902 | 1896 | }else{ |
| 1903 | - style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", | |
| 1904 | - g.zTop, zUuid); | |
| 1897 | + style_submenu_element("Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid); | |
| 1905 | 1898 | } |
| 1906 | 1899 | } |
| 1907 | 1900 | style_header("%s", descOnly ? "Artifact Description" : "Artifact Content"); |
| 1908 | 1901 | zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1909 | 1902 | if( g.perm.Setup ){ |
| @@ -1925,48 +1918,42 @@ | ||
| 1925 | 1918 | const char *zIp = db_column_text(&q,2); |
| 1926 | 1919 | @ <p>Received on %s(zDate) from %h(zUser) at %h(zIp).</p> |
| 1927 | 1920 | } |
| 1928 | 1921 | db_finalize(&q); |
| 1929 | 1922 | } |
| 1930 | - style_submenu_element("Download", "Download", | |
| 1931 | - "%R/raw/%T?name=%s", blob_str(&downloadName), zUuid); | |
| 1923 | + style_submenu_element("Download", "%R/raw/%T?name=%s", | |
| 1924 | + blob_str(&downloadName), zUuid); | |
| 1932 | 1925 | if( db_exists("SELECT 1 FROM mlink WHERE fid=%d", rid) ){ |
| 1933 | - style_submenu_element("Check-ins Using", "Check-ins Using", | |
| 1934 | - "%R/timeline?n=200&uf=%s",zUuid); | |
| 1926 | + style_submenu_element("Check-ins Using", "%R/timeline?n=200&uf=%s", zUuid); | |
| 1935 | 1927 | } |
| 1936 | 1928 | asText = P("txt")!=0; |
| 1937 | 1929 | zMime = mimetype_from_name(blob_str(&downloadName)); |
| 1938 | 1930 | if( zMime ){ |
| 1939 | 1931 | if( fossil_strcmp(zMime, "text/html")==0 ){ |
| 1940 | 1932 | if( asText ){ |
| 1941 | - style_submenu_element("Html", "Html", | |
| 1942 | - "%s/artifact/%s", g.zTop, zUuid); | |
| 1933 | + style_submenu_element("Html", "%s/artifact/%s", g.zTop, zUuid); | |
| 1943 | 1934 | }else{ |
| 1944 | 1935 | renderAsHtml = 1; |
| 1945 | - style_submenu_element("Text", "Text", | |
| 1946 | - "%s/artifact/%s?txt=1", g.zTop, zUuid); | |
| 1936 | + style_submenu_element("Text", "%s/artifact/%s?txt=1", g.zTop, zUuid); | |
| 1947 | 1937 | } |
| 1948 | 1938 | }else if( fossil_strcmp(zMime, "text/x-fossil-wiki")==0 |
| 1949 | 1939 | || fossil_strcmp(zMime, "text/x-markdown")==0 ){ |
| 1950 | 1940 | if( asText ){ |
| 1951 | - style_submenu_element("Wiki", "Wiki", | |
| 1952 | - "%s/artifact/%s", g.zTop, zUuid); | |
| 1941 | + style_submenu_element("Wiki", "%s/artifact/%s", g.zTop, zUuid); | |
| 1953 | 1942 | }else{ |
| 1954 | 1943 | renderAsWiki = 1; |
| 1955 | - style_submenu_element("Text", "Text", | |
| 1956 | - "%s/artifact/%s?txt=1", g.zTop, zUuid); | |
| 1944 | + style_submenu_element("Text", "%s/artifact/%s?txt=1", g.zTop, zUuid); | |
| 1957 | 1945 | } |
| 1958 | 1946 | } |
| 1959 | 1947 | } |
| 1960 | 1948 | if( (objType & (OBJTYPE_WIKI|OBJTYPE_TICKET))!=0 ){ |
| 1961 | - style_submenu_element("Parsed", "Parsed", "%R/info/%s", zUuid); | |
| 1949 | + style_submenu_element("Parsed", "%R/info/%s", zUuid); | |
| 1962 | 1950 | } |
| 1963 | 1951 | if( descOnly ){ |
| 1964 | - style_submenu_element("Content", "Content", "%R/artifact/%s", zUuid); | |
| 1952 | + style_submenu_element("Content", "%R/artifact/%s", zUuid); | |
| 1965 | 1953 | }else{ |
| 1966 | - style_submenu_element("Line Numbers", "Line Numbers", | |
| 1967 | - "%R/artifact/%s%s",zUuid, | |
| 1954 | + style_submenu_element("Line Numbers", "%R/artifact/%s%s", zUuid, | |
| 1968 | 1955 | ((zLn&&*zLn) ? "" : "?txt=1&ln=0")); |
| 1969 | 1956 | @ <hr /> |
| 1970 | 1957 | content_get(rid, &content); |
| 1971 | 1958 | if( renderAsWiki ){ |
| 1972 | 1959 | wiki_render_by_mimetype(&content, zMime); |
| @@ -1975,11 +1962,11 @@ | ||
| 1975 | 1962 | @ width="100%%" frameborder="0" marginwidth="0" marginheight="0" |
| 1976 | 1963 | @ sandbox="allow-same-origin" |
| 1977 | 1964 | @ onload="this.height=this.contentDocument.documentElement.scrollHeight;"> |
| 1978 | 1965 | @ </iframe> |
| 1979 | 1966 | }else{ |
| 1980 | - style_submenu_element("Hex","Hex", "%s/hexdump?name=%s", g.zTop, zUuid); | |
| 1967 | + style_submenu_element("Hex", "%s/hexdump?name=%s", g.zTop, zUuid); | |
| 1981 | 1968 | blob_to_utf8_no_bom(&content, 0); |
| 1982 | 1969 | zMime = mimetype_from_content(&content); |
| 1983 | 1970 | @ <blockquote> |
| 1984 | 1971 | if( zMime==0 ){ |
| 1985 | 1972 | const char *z; |
| @@ -1992,12 +1979,11 @@ | ||
| 1992 | 1979 | @ </pre> |
| 1993 | 1980 | } |
| 1994 | 1981 | }else if( strncmp(zMime, "image/", 6)==0 ){ |
| 1995 | 1982 | @ <i>(file is %d(blob_size(&content)) bytes of image data)</i><br /> |
| 1996 | 1983 | @ <img src="%R/raw/%s(zUuid)?m=%s(zMime)" /> |
| 1997 | - style_submenu_element("Image", "Image", | |
| 1998 | - "%R/raw/%s?m=%s", zUuid, zMime); | |
| 1984 | + style_submenu_element("Image", "%R/raw/%s?m=%s", zUuid, zMime); | |
| 1999 | 1985 | }else{ |
| 2000 | 1986 | @ <i>(file is %d(blob_size(&content)) bytes of binary data)</i> |
| 2001 | 1987 | } |
| 2002 | 1988 | @ </blockquote> |
| 2003 | 1989 | } |
| @@ -2025,15 +2011,14 @@ | ||
| 2025 | 2011 | rid = name_to_rid_www("name"); |
| 2026 | 2012 | if( rid==0 ){ fossil_redirect_home(); } |
| 2027 | 2013 | zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 2028 | 2014 | if( g.perm.Admin ){ |
| 2029 | 2015 | if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){ |
| 2030 | - style_submenu_element("Unshun","Unshun", "%s/shun?accept=%s&sub=1#accshun", | |
| 2016 | + style_submenu_element("Unshun", "%s/shun?accept=%s&sub=1#accshun", | |
| 2031 | 2017 | g.zTop, zUuid); |
| 2032 | 2018 | }else{ |
| 2033 | - style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", | |
| 2034 | - g.zTop, zUuid); | |
| 2019 | + style_submenu_element("Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid); | |
| 2035 | 2020 | } |
| 2036 | 2021 | } |
| 2037 | 2022 | pTktChng = manifest_get(rid, CFTYPE_TICKET, 0); |
| 2038 | 2023 | if( pTktChng==0 ) fossil_redirect_home(); |
| 2039 | 2024 | zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate); |
| @@ -2060,19 +2045,18 @@ | ||
| 2060 | 2045 | } |
| 2061 | 2046 | zTktTitle = db_table_has_column("repository", "ticket", "title" ) |
| 2062 | 2047 | ? db_text("(No title)", "SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName) |
| 2063 | 2048 | : 0; |
| 2064 | 2049 | style_header("Ticket Change Details"); |
| 2065 | - style_submenu_element("Raw", "Raw", "%R/artifact/%s", zUuid); | |
| 2066 | - style_submenu_element("History", "History", "%R/tkthistory/%s", zTktName); | |
| 2067 | - style_submenu_element("Page", "Page", "%R/tktview/%t", zTktName); | |
| 2068 | - style_submenu_element("Timeline", "Timeline", "%R/tkttimeline/%t", zTktName); | |
| 2050 | + style_submenu_element("Raw", "%R/artifact/%s", zUuid); | |
| 2051 | + style_submenu_element("History", "%R/tkthistory/%s", zTktName); | |
| 2052 | + style_submenu_element("Page", "%R/tktview/%t", zTktName); | |
| 2053 | + style_submenu_element("Timeline", "%R/tkttimeline/%t", zTktName); | |
| 2069 | 2054 | if( P("plaintext") ){ |
| 2070 | - style_submenu_element("Formatted", "Formatted", "%R/info/%s", zUuid); | |
| 2055 | + style_submenu_element("Formatted", "%R/info/%s", zUuid); | |
| 2071 | 2056 | }else{ |
| 2072 | - style_submenu_element("Plaintext", "Plaintext", | |
| 2073 | - "%R/info/%s?plaintext", zUuid); | |
| 2057 | + style_submenu_element("Plaintext", "%R/info/%s?plaintext", zUuid); | |
| 2074 | 2058 | } |
| 2075 | 2059 | |
| 2076 | 2060 | @ <div class="section">Overview</div> |
| 2077 | 2061 | @ <p><table class="label-value"> |
| 2078 | 2062 | @ <tr><th>Artifact ID:</th> |
| @@ -2264,11 +2248,11 @@ | ||
| 2264 | 2248 | { "#91d680", 0 }, |
| 2265 | 2249 | |
| 2266 | 2250 | |
| 2267 | 2251 | { "custom", "##" }, |
| 2268 | 2252 | }; |
| 2269 | - int nColor = sizeof(aColor)/sizeof(aColor[0])-1; | |
| 2253 | + int nColor = count(aColor)-1; | |
| 2270 | 2254 | int stdClrFound = 0; |
| 2271 | 2255 | int i; |
| 2272 | 2256 | |
| 2273 | 2257 | if( zIdPropagate ){ |
| 2274 | 2258 | @ <div><label> |
| 2275 | 2259 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -231,11 +231,11 @@ | |
| 231 | db_int(-1, "SELECT count(*) FROM event WHERE type='ci' /*scan*/")); |
| 232 | }else{ |
| 233 | int rid; |
| 234 | rid = name_to_rid(g.argv[2]); |
| 235 | if( rid==0 ){ |
| 236 | fossil_fatal("no such object: %s\n", g.argv[2]); |
| 237 | } |
| 238 | show_common_info(rid, "uuid:", 1, 1); |
| 239 | } |
| 240 | } |
| 241 | |
| @@ -826,15 +826,13 @@ | |
| 826 | } |
| 827 | } |
| 828 | style_header("Update of \"%h\"", pWiki->zWikiTitle); |
| 829 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 830 | zDate = db_text(0, "SELECT datetime(%.17g)", pWiki->rDate); |
| 831 | style_submenu_element("Raw", "Raw", "artifact/%s", zUuid); |
| 832 | style_submenu_element("History", "History", "whistory?name=%t", |
| 833 | pWiki->zWikiTitle); |
| 834 | style_submenu_element("Page", "Page", "wiki?name=%t", |
| 835 | pWiki->zWikiTitle); |
| 836 | login_anonymous_available(); |
| 837 | @ <div class="section">Overview</div> |
| 838 | @ <p><table class="label-value"> |
| 839 | @ <tr><th>Artifact ID:</th> |
| 840 | @ <td>%z(href("%R/artifact/%!S",zUuid))%s(zUuid)</a> |
| @@ -1053,50 +1051,47 @@ | |
| 1053 | if(zGlob && !*zGlob){ |
| 1054 | zGlob = NULL; |
| 1055 | } |
| 1056 | diffFlags = construct_diff_flags(verboseFlag, sideBySide); |
| 1057 | zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; |
| 1058 | style_submenu_element("Path","path", |
| 1059 | "%R/timeline?me=%T&you=%T", zFrom, zTo); |
| 1060 | if( sideBySide || verboseFlag ){ |
| 1061 | style_submenu_element("Hide Diff", "hidediff", |
| 1062 | "%R/vdiff?from=%T&to=%T&sbs=0%s%T%s", |
| 1063 | zFrom, zTo, |
| 1064 | zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); |
| 1065 | } |
| 1066 | if( !sideBySide ){ |
| 1067 | style_submenu_element("Side-by-Side Diff", "sbsdiff", |
| 1068 | "%R/vdiff?from=%T&to=%T&sbs=1%s%T%s", |
| 1069 | zFrom, zTo, |
| 1070 | zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); |
| 1071 | } |
| 1072 | if( sideBySide || !verboseFlag ) { |
| 1073 | style_submenu_element("Unified Diff", "udiff", |
| 1074 | "%R/vdiff?from=%T&to=%T&sbs=0&v%s%T%s", |
| 1075 | zFrom, zTo, |
| 1076 | zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); |
| 1077 | } |
| 1078 | style_submenu_element("Invert", "invert", |
| 1079 | "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T%s", zTo, zFrom, |
| 1080 | sideBySide, (verboseFlag && !sideBySide)?"&v":"", |
| 1081 | zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); |
| 1082 | if( zGlob ){ |
| 1083 | style_submenu_element("Clear glob", "clearglob", |
| 1084 | "%R/vdiff?from=%T&to=%T&sbs=%d%s%s", zFrom, zTo, |
| 1085 | sideBySide, (verboseFlag && !sideBySide)?"&v":"", zW); |
| 1086 | }else{ |
| 1087 | style_submenu_element("Patch", "patch", |
| 1088 | "%R/vpatch?from=%T&to=%T%s", zFrom, zTo, zW); |
| 1089 | } |
| 1090 | if( sideBySide || verboseFlag ){ |
| 1091 | if( *zW ){ |
| 1092 | style_submenu_element("Show Whitespace Differences", "whitespace", |
| 1093 | "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T", zFrom, zTo, |
| 1094 | sideBySide, (verboseFlag && !sideBySide)?"&v":"", |
| 1095 | zGlob ? "&glob=" : "", zGlob ? zGlob : ""); |
| 1096 | }else{ |
| 1097 | style_submenu_element("Ignore Whitespace", "ignorews", |
| 1098 | "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T&w", zFrom, zTo, |
| 1099 | sideBySide, (verboseFlag && !sideBySide)?"&v":"", |
| 1100 | zGlob ? "&glob=" : "", zGlob ? zGlob : ""); |
| 1101 | } |
| 1102 | } |
| @@ -1514,26 +1509,26 @@ | |
| 1514 | diffFlags = construct_diff_flags(1, sideBySide) | DIFF_HTML; |
| 1515 | |
| 1516 | style_header("Diff"); |
| 1517 | zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; |
| 1518 | if( *zW ){ |
| 1519 | style_submenu_element("Show Whitespace Changes", "Show Whitespace Changes", |
| 1520 | "%s/fdiff?v1=%T&v2=%T&sbs=%d", |
| 1521 | g.zTop, P("v1"), P("v2"), sideBySide); |
| 1522 | }else{ |
| 1523 | style_submenu_element("Ignore Whitespace", "Ignore Whitespace", |
| 1524 | "%s/fdiff?v1=%T&v2=%T&sbs=%d&w", |
| 1525 | g.zTop, P("v1"), P("v2"), sideBySide); |
| 1526 | } |
| 1527 | style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch", |
| 1528 | g.zTop, P("v1"), P("v2")); |
| 1529 | if( !sideBySide ){ |
| 1530 | style_submenu_element("Side-by-Side Diff", "sbsdiff", |
| 1531 | "%s/fdiff?v1=%T&v2=%T&sbs=1%s", |
| 1532 | g.zTop, P("v1"), P("v2"), zW); |
| 1533 | }else{ |
| 1534 | style_submenu_element("Unified Diff", "udiff", |
| 1535 | "%s/fdiff?v1=%T&v2=%T&sbs=0%s", |
| 1536 | g.zTop, P("v1"), P("v2"), zW); |
| 1537 | } |
| 1538 | |
| 1539 | if( P("smhdr")!=0 ){ |
| @@ -1672,15 +1667,14 @@ | |
| 1672 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1673 | if( rid==0 ) fossil_redirect_home(); |
| 1674 | if( g.perm.Admin ){ |
| 1675 | const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1676 | if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){ |
| 1677 | style_submenu_element("Unshun","Unshun","%s/shun?accept=%s&sub=1#delshun", |
| 1678 | g.zTop, zUuid); |
| 1679 | }else{ |
| 1680 | style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", |
| 1681 | g.zTop, zUuid); |
| 1682 | } |
| 1683 | } |
| 1684 | style_header("Hex Artifact Content"); |
| 1685 | zUuid = db_text("?","SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1686 | if( g.perm.Setup ){ |
| @@ -1689,12 +1683,12 @@ | |
| 1689 | @ <h2>Artifact %s(zUuid):</h2> |
| 1690 | } |
| 1691 | blob_zero(&downloadName); |
| 1692 | if( P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL; |
| 1693 | object_description(rid, objdescFlags, &downloadName); |
| 1694 | style_submenu_element("Download", "Download", |
| 1695 | "%s/raw/%T?name=%s", g.zTop, blob_str(&downloadName), zUuid); |
| 1696 | @ <hr /> |
| 1697 | content_get(rid, &content); |
| 1698 | @ <blockquote><pre> |
| 1699 | hexdump(&content); |
| 1700 | @ </pre></blockquote> |
| @@ -1895,15 +1889,14 @@ | |
| 1895 | /*NOTREACHED*/ |
| 1896 | } |
| 1897 | if( g.perm.Admin ){ |
| 1898 | const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1899 | if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){ |
| 1900 | style_submenu_element("Unshun","Unshun","%s/shun?accept=%s&sub=1#accshun", |
| 1901 | g.zTop, zUuid); |
| 1902 | }else{ |
| 1903 | style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", |
| 1904 | g.zTop, zUuid); |
| 1905 | } |
| 1906 | } |
| 1907 | style_header("%s", descOnly ? "Artifact Description" : "Artifact Content"); |
| 1908 | zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1909 | if( g.perm.Setup ){ |
| @@ -1925,48 +1918,42 @@ | |
| 1925 | const char *zIp = db_column_text(&q,2); |
| 1926 | @ <p>Received on %s(zDate) from %h(zUser) at %h(zIp).</p> |
| 1927 | } |
| 1928 | db_finalize(&q); |
| 1929 | } |
| 1930 | style_submenu_element("Download", "Download", |
| 1931 | "%R/raw/%T?name=%s", blob_str(&downloadName), zUuid); |
| 1932 | if( db_exists("SELECT 1 FROM mlink WHERE fid=%d", rid) ){ |
| 1933 | style_submenu_element("Check-ins Using", "Check-ins Using", |
| 1934 | "%R/timeline?n=200&uf=%s",zUuid); |
| 1935 | } |
| 1936 | asText = P("txt")!=0; |
| 1937 | zMime = mimetype_from_name(blob_str(&downloadName)); |
| 1938 | if( zMime ){ |
| 1939 | if( fossil_strcmp(zMime, "text/html")==0 ){ |
| 1940 | if( asText ){ |
| 1941 | style_submenu_element("Html", "Html", |
| 1942 | "%s/artifact/%s", g.zTop, zUuid); |
| 1943 | }else{ |
| 1944 | renderAsHtml = 1; |
| 1945 | style_submenu_element("Text", "Text", |
| 1946 | "%s/artifact/%s?txt=1", g.zTop, zUuid); |
| 1947 | } |
| 1948 | }else if( fossil_strcmp(zMime, "text/x-fossil-wiki")==0 |
| 1949 | || fossil_strcmp(zMime, "text/x-markdown")==0 ){ |
| 1950 | if( asText ){ |
| 1951 | style_submenu_element("Wiki", "Wiki", |
| 1952 | "%s/artifact/%s", g.zTop, zUuid); |
| 1953 | }else{ |
| 1954 | renderAsWiki = 1; |
| 1955 | style_submenu_element("Text", "Text", |
| 1956 | "%s/artifact/%s?txt=1", g.zTop, zUuid); |
| 1957 | } |
| 1958 | } |
| 1959 | } |
| 1960 | if( (objType & (OBJTYPE_WIKI|OBJTYPE_TICKET))!=0 ){ |
| 1961 | style_submenu_element("Parsed", "Parsed", "%R/info/%s", zUuid); |
| 1962 | } |
| 1963 | if( descOnly ){ |
| 1964 | style_submenu_element("Content", "Content", "%R/artifact/%s", zUuid); |
| 1965 | }else{ |
| 1966 | style_submenu_element("Line Numbers", "Line Numbers", |
| 1967 | "%R/artifact/%s%s",zUuid, |
| 1968 | ((zLn&&*zLn) ? "" : "?txt=1&ln=0")); |
| 1969 | @ <hr /> |
| 1970 | content_get(rid, &content); |
| 1971 | if( renderAsWiki ){ |
| 1972 | wiki_render_by_mimetype(&content, zMime); |
| @@ -1975,11 +1962,11 @@ | |
| 1975 | @ width="100%%" frameborder="0" marginwidth="0" marginheight="0" |
| 1976 | @ sandbox="allow-same-origin" |
| 1977 | @ onload="this.height=this.contentDocument.documentElement.scrollHeight;"> |
| 1978 | @ </iframe> |
| 1979 | }else{ |
| 1980 | style_submenu_element("Hex","Hex", "%s/hexdump?name=%s", g.zTop, zUuid); |
| 1981 | blob_to_utf8_no_bom(&content, 0); |
| 1982 | zMime = mimetype_from_content(&content); |
| 1983 | @ <blockquote> |
| 1984 | if( zMime==0 ){ |
| 1985 | const char *z; |
| @@ -1992,12 +1979,11 @@ | |
| 1992 | @ </pre> |
| 1993 | } |
| 1994 | }else if( strncmp(zMime, "image/", 6)==0 ){ |
| 1995 | @ <i>(file is %d(blob_size(&content)) bytes of image data)</i><br /> |
| 1996 | @ <img src="%R/raw/%s(zUuid)?m=%s(zMime)" /> |
| 1997 | style_submenu_element("Image", "Image", |
| 1998 | "%R/raw/%s?m=%s", zUuid, zMime); |
| 1999 | }else{ |
| 2000 | @ <i>(file is %d(blob_size(&content)) bytes of binary data)</i> |
| 2001 | } |
| 2002 | @ </blockquote> |
| 2003 | } |
| @@ -2025,15 +2011,14 @@ | |
| 2025 | rid = name_to_rid_www("name"); |
| 2026 | if( rid==0 ){ fossil_redirect_home(); } |
| 2027 | zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 2028 | if( g.perm.Admin ){ |
| 2029 | if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){ |
| 2030 | style_submenu_element("Unshun","Unshun", "%s/shun?accept=%s&sub=1#accshun", |
| 2031 | g.zTop, zUuid); |
| 2032 | }else{ |
| 2033 | style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", |
| 2034 | g.zTop, zUuid); |
| 2035 | } |
| 2036 | } |
| 2037 | pTktChng = manifest_get(rid, CFTYPE_TICKET, 0); |
| 2038 | if( pTktChng==0 ) fossil_redirect_home(); |
| 2039 | zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate); |
| @@ -2060,19 +2045,18 @@ | |
| 2060 | } |
| 2061 | zTktTitle = db_table_has_column("repository", "ticket", "title" ) |
| 2062 | ? db_text("(No title)", "SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName) |
| 2063 | : 0; |
| 2064 | style_header("Ticket Change Details"); |
| 2065 | style_submenu_element("Raw", "Raw", "%R/artifact/%s", zUuid); |
| 2066 | style_submenu_element("History", "History", "%R/tkthistory/%s", zTktName); |
| 2067 | style_submenu_element("Page", "Page", "%R/tktview/%t", zTktName); |
| 2068 | style_submenu_element("Timeline", "Timeline", "%R/tkttimeline/%t", zTktName); |
| 2069 | if( P("plaintext") ){ |
| 2070 | style_submenu_element("Formatted", "Formatted", "%R/info/%s", zUuid); |
| 2071 | }else{ |
| 2072 | style_submenu_element("Plaintext", "Plaintext", |
| 2073 | "%R/info/%s?plaintext", zUuid); |
| 2074 | } |
| 2075 | |
| 2076 | @ <div class="section">Overview</div> |
| 2077 | @ <p><table class="label-value"> |
| 2078 | @ <tr><th>Artifact ID:</th> |
| @@ -2264,11 +2248,11 @@ | |
| 2264 | { "#91d680", 0 }, |
| 2265 | |
| 2266 | |
| 2267 | { "custom", "##" }, |
| 2268 | }; |
| 2269 | int nColor = sizeof(aColor)/sizeof(aColor[0])-1; |
| 2270 | int stdClrFound = 0; |
| 2271 | int i; |
| 2272 | |
| 2273 | if( zIdPropagate ){ |
| 2274 | @ <div><label> |
| 2275 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -231,11 +231,11 @@ | |
| 231 | db_int(-1, "SELECT count(*) FROM event WHERE type='ci' /*scan*/")); |
| 232 | }else{ |
| 233 | int rid; |
| 234 | rid = name_to_rid(g.argv[2]); |
| 235 | if( rid==0 ){ |
| 236 | fossil_fatal("no such object: %s", g.argv[2]); |
| 237 | } |
| 238 | show_common_info(rid, "uuid:", 1, 1); |
| 239 | } |
| 240 | } |
| 241 | |
| @@ -826,15 +826,13 @@ | |
| 826 | } |
| 827 | } |
| 828 | style_header("Update of \"%h\"", pWiki->zWikiTitle); |
| 829 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 830 | zDate = db_text(0, "SELECT datetime(%.17g)", pWiki->rDate); |
| 831 | style_submenu_element("Raw", "artifact/%s", zUuid); |
| 832 | style_submenu_element("History", "whistory?name=%t", pWiki->zWikiTitle); |
| 833 | style_submenu_element("Page", "wiki?name=%t", pWiki->zWikiTitle); |
| 834 | login_anonymous_available(); |
| 835 | @ <div class="section">Overview</div> |
| 836 | @ <p><table class="label-value"> |
| 837 | @ <tr><th>Artifact ID:</th> |
| 838 | @ <td>%z(href("%R/artifact/%!S",zUuid))%s(zUuid)</a> |
| @@ -1053,50 +1051,47 @@ | |
| 1051 | if(zGlob && !*zGlob){ |
| 1052 | zGlob = NULL; |
| 1053 | } |
| 1054 | diffFlags = construct_diff_flags(verboseFlag, sideBySide); |
| 1055 | zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; |
| 1056 | style_submenu_element("Path", "%R/timeline?me=%T&you=%T", zFrom, zTo); |
| 1057 | if( sideBySide || verboseFlag ){ |
| 1058 | style_submenu_element("Hide Diff", "%R/vdiff?from=%T&to=%T&sbs=0%s%T%s", |
| 1059 | zFrom, zTo, |
| 1060 | zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); |
| 1061 | } |
| 1062 | if( !sideBySide ){ |
| 1063 | style_submenu_element("Side-by-Side Diff", |
| 1064 | "%R/vdiff?from=%T&to=%T&sbs=1%s%T%s", |
| 1065 | zFrom, zTo, |
| 1066 | zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); |
| 1067 | } |
| 1068 | if( sideBySide || !verboseFlag ) { |
| 1069 | style_submenu_element("Unified Diff", |
| 1070 | "%R/vdiff?from=%T&to=%T&sbs=0&v%s%T%s", |
| 1071 | zFrom, zTo, |
| 1072 | zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); |
| 1073 | } |
| 1074 | style_submenu_element("Invert", |
| 1075 | "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T%s", zTo, zFrom, |
| 1076 | sideBySide, (verboseFlag && !sideBySide)?"&v":"", |
| 1077 | zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); |
| 1078 | if( zGlob ){ |
| 1079 | style_submenu_element("Clear glob", |
| 1080 | "%R/vdiff?from=%T&to=%T&sbs=%d%s%s", zFrom, zTo, |
| 1081 | sideBySide, (verboseFlag && !sideBySide)?"&v":"", zW); |
| 1082 | }else{ |
| 1083 | style_submenu_element("Patch", "%R/vpatch?from=%T&to=%T%s", zFrom, zTo, zW); |
| 1084 | } |
| 1085 | if( sideBySide || verboseFlag ){ |
| 1086 | if( *zW ){ |
| 1087 | style_submenu_element("Show Whitespace Differences", |
| 1088 | "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T", zFrom, zTo, |
| 1089 | sideBySide, (verboseFlag && !sideBySide)?"&v":"", |
| 1090 | zGlob ? "&glob=" : "", zGlob ? zGlob : ""); |
| 1091 | }else{ |
| 1092 | style_submenu_element("Ignore Whitespace", |
| 1093 | "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T&w", zFrom, zTo, |
| 1094 | sideBySide, (verboseFlag && !sideBySide)?"&v":"", |
| 1095 | zGlob ? "&glob=" : "", zGlob ? zGlob : ""); |
| 1096 | } |
| 1097 | } |
| @@ -1514,26 +1509,26 @@ | |
| 1509 | diffFlags = construct_diff_flags(1, sideBySide) | DIFF_HTML; |
| 1510 | |
| 1511 | style_header("Diff"); |
| 1512 | zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; |
| 1513 | if( *zW ){ |
| 1514 | style_submenu_element("Show Whitespace Changes", |
| 1515 | "%s/fdiff?v1=%T&v2=%T&sbs=%d", |
| 1516 | g.zTop, P("v1"), P("v2"), sideBySide); |
| 1517 | }else{ |
| 1518 | style_submenu_element("Ignore Whitespace", |
| 1519 | "%s/fdiff?v1=%T&v2=%T&sbs=%d&w", |
| 1520 | g.zTop, P("v1"), P("v2"), sideBySide); |
| 1521 | } |
| 1522 | style_submenu_element("Patch", "%s/fdiff?v1=%T&v2=%T&patch", |
| 1523 | g.zTop, P("v1"), P("v2")); |
| 1524 | if( !sideBySide ){ |
| 1525 | style_submenu_element("Side-by-Side Diff", |
| 1526 | "%s/fdiff?v1=%T&v2=%T&sbs=1%s", |
| 1527 | g.zTop, P("v1"), P("v2"), zW); |
| 1528 | }else{ |
| 1529 | style_submenu_element("Unified Diff", |
| 1530 | "%s/fdiff?v1=%T&v2=%T&sbs=0%s", |
| 1531 | g.zTop, P("v1"), P("v2"), zW); |
| 1532 | } |
| 1533 | |
| 1534 | if( P("smhdr")!=0 ){ |
| @@ -1672,15 +1667,14 @@ | |
| 1667 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1668 | if( rid==0 ) fossil_redirect_home(); |
| 1669 | if( g.perm.Admin ){ |
| 1670 | const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1671 | if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){ |
| 1672 | style_submenu_element("Unshun", "%s/shun?accept=%s&sub=1#delshun", |
| 1673 | g.zTop, zUuid); |
| 1674 | }else{ |
| 1675 | style_submenu_element("Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid); |
| 1676 | } |
| 1677 | } |
| 1678 | style_header("Hex Artifact Content"); |
| 1679 | zUuid = db_text("?","SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1680 | if( g.perm.Setup ){ |
| @@ -1689,12 +1683,12 @@ | |
| 1683 | @ <h2>Artifact %s(zUuid):</h2> |
| 1684 | } |
| 1685 | blob_zero(&downloadName); |
| 1686 | if( P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL; |
| 1687 | object_description(rid, objdescFlags, &downloadName); |
| 1688 | style_submenu_element("Download", "%s/raw/%T?name=%s", |
| 1689 | g.zTop, blob_str(&downloadName), zUuid); |
| 1690 | @ <hr /> |
| 1691 | content_get(rid, &content); |
| 1692 | @ <blockquote><pre> |
| 1693 | hexdump(&content); |
| 1694 | @ </pre></blockquote> |
| @@ -1895,15 +1889,14 @@ | |
| 1889 | /*NOTREACHED*/ |
| 1890 | } |
| 1891 | if( g.perm.Admin ){ |
| 1892 | const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1893 | if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){ |
| 1894 | style_submenu_element("Unshun", "%s/shun?accept=%s&sub=1#accshun", |
| 1895 | g.zTop, zUuid); |
| 1896 | }else{ |
| 1897 | style_submenu_element("Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid); |
| 1898 | } |
| 1899 | } |
| 1900 | style_header("%s", descOnly ? "Artifact Description" : "Artifact Content"); |
| 1901 | zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1902 | if( g.perm.Setup ){ |
| @@ -1925,48 +1918,42 @@ | |
| 1918 | const char *zIp = db_column_text(&q,2); |
| 1919 | @ <p>Received on %s(zDate) from %h(zUser) at %h(zIp).</p> |
| 1920 | } |
| 1921 | db_finalize(&q); |
| 1922 | } |
| 1923 | style_submenu_element("Download", "%R/raw/%T?name=%s", |
| 1924 | blob_str(&downloadName), zUuid); |
| 1925 | if( db_exists("SELECT 1 FROM mlink WHERE fid=%d", rid) ){ |
| 1926 | style_submenu_element("Check-ins Using", "%R/timeline?n=200&uf=%s", zUuid); |
| 1927 | } |
| 1928 | asText = P("txt")!=0; |
| 1929 | zMime = mimetype_from_name(blob_str(&downloadName)); |
| 1930 | if( zMime ){ |
| 1931 | if( fossil_strcmp(zMime, "text/html")==0 ){ |
| 1932 | if( asText ){ |
| 1933 | style_submenu_element("Html", "%s/artifact/%s", g.zTop, zUuid); |
| 1934 | }else{ |
| 1935 | renderAsHtml = 1; |
| 1936 | style_submenu_element("Text", "%s/artifact/%s?txt=1", g.zTop, zUuid); |
| 1937 | } |
| 1938 | }else if( fossil_strcmp(zMime, "text/x-fossil-wiki")==0 |
| 1939 | || fossil_strcmp(zMime, "text/x-markdown")==0 ){ |
| 1940 | if( asText ){ |
| 1941 | style_submenu_element("Wiki", "%s/artifact/%s", g.zTop, zUuid); |
| 1942 | }else{ |
| 1943 | renderAsWiki = 1; |
| 1944 | style_submenu_element("Text", "%s/artifact/%s?txt=1", g.zTop, zUuid); |
| 1945 | } |
| 1946 | } |
| 1947 | } |
| 1948 | if( (objType & (OBJTYPE_WIKI|OBJTYPE_TICKET))!=0 ){ |
| 1949 | style_submenu_element("Parsed", "%R/info/%s", zUuid); |
| 1950 | } |
| 1951 | if( descOnly ){ |
| 1952 | style_submenu_element("Content", "%R/artifact/%s", zUuid); |
| 1953 | }else{ |
| 1954 | style_submenu_element("Line Numbers", "%R/artifact/%s%s", zUuid, |
| 1955 | ((zLn&&*zLn) ? "" : "?txt=1&ln=0")); |
| 1956 | @ <hr /> |
| 1957 | content_get(rid, &content); |
| 1958 | if( renderAsWiki ){ |
| 1959 | wiki_render_by_mimetype(&content, zMime); |
| @@ -1975,11 +1962,11 @@ | |
| 1962 | @ width="100%%" frameborder="0" marginwidth="0" marginheight="0" |
| 1963 | @ sandbox="allow-same-origin" |
| 1964 | @ onload="this.height=this.contentDocument.documentElement.scrollHeight;"> |
| 1965 | @ </iframe> |
| 1966 | }else{ |
| 1967 | style_submenu_element("Hex", "%s/hexdump?name=%s", g.zTop, zUuid); |
| 1968 | blob_to_utf8_no_bom(&content, 0); |
| 1969 | zMime = mimetype_from_content(&content); |
| 1970 | @ <blockquote> |
| 1971 | if( zMime==0 ){ |
| 1972 | const char *z; |
| @@ -1992,12 +1979,11 @@ | |
| 1979 | @ </pre> |
| 1980 | } |
| 1981 | }else if( strncmp(zMime, "image/", 6)==0 ){ |
| 1982 | @ <i>(file is %d(blob_size(&content)) bytes of image data)</i><br /> |
| 1983 | @ <img src="%R/raw/%s(zUuid)?m=%s(zMime)" /> |
| 1984 | style_submenu_element("Image", "%R/raw/%s?m=%s", zUuid, zMime); |
| 1985 | }else{ |
| 1986 | @ <i>(file is %d(blob_size(&content)) bytes of binary data)</i> |
| 1987 | } |
| 1988 | @ </blockquote> |
| 1989 | } |
| @@ -2025,15 +2011,14 @@ | |
| 2011 | rid = name_to_rid_www("name"); |
| 2012 | if( rid==0 ){ fossil_redirect_home(); } |
| 2013 | zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 2014 | if( g.perm.Admin ){ |
| 2015 | if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){ |
| 2016 | style_submenu_element("Unshun", "%s/shun?accept=%s&sub=1#accshun", |
| 2017 | g.zTop, zUuid); |
| 2018 | }else{ |
| 2019 | style_submenu_element("Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid); |
| 2020 | } |
| 2021 | } |
| 2022 | pTktChng = manifest_get(rid, CFTYPE_TICKET, 0); |
| 2023 | if( pTktChng==0 ) fossil_redirect_home(); |
| 2024 | zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate); |
| @@ -2060,19 +2045,18 @@ | |
| 2045 | } |
| 2046 | zTktTitle = db_table_has_column("repository", "ticket", "title" ) |
| 2047 | ? db_text("(No title)", "SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName) |
| 2048 | : 0; |
| 2049 | style_header("Ticket Change Details"); |
| 2050 | style_submenu_element("Raw", "%R/artifact/%s", zUuid); |
| 2051 | style_submenu_element("History", "%R/tkthistory/%s", zTktName); |
| 2052 | style_submenu_element("Page", "%R/tktview/%t", zTktName); |
| 2053 | style_submenu_element("Timeline", "%R/tkttimeline/%t", zTktName); |
| 2054 | if( P("plaintext") ){ |
| 2055 | style_submenu_element("Formatted", "%R/info/%s", zUuid); |
| 2056 | }else{ |
| 2057 | style_submenu_element("Plaintext", "%R/info/%s?plaintext", zUuid); |
| 2058 | } |
| 2059 | |
| 2060 | @ <div class="section">Overview</div> |
| 2061 | @ <p><table class="label-value"> |
| 2062 | @ <tr><th>Artifact ID:</th> |
| @@ -2264,11 +2248,11 @@ | |
| 2248 | { "#91d680", 0 }, |
| 2249 | |
| 2250 | |
| 2251 | { "custom", "##" }, |
| 2252 | }; |
| 2253 | int nColor = count(aColor)-1; |
| 2254 | int stdClrFound = 0; |
| 2255 | int i; |
| 2256 | |
| 2257 | if( zIdPropagate ){ |
| 2258 | @ <div><label> |
| 2259 |
+1
-1
| --- src/json_branch.c | ||
| +++ src/json_branch.c | ||
| @@ -292,11 +292,11 @@ | ||
| 292 | 292 | if( brid==0 ){ |
| 293 | 293 | fossil_fatal("Problem committing manifest: %s", g.zErrMsg); |
| 294 | 294 | } |
| 295 | 295 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid); |
| 296 | 296 | if( manifest_crosslink(brid, &branch, MC_PERMIT_HOOKS)==0 ){ |
| 297 | - fossil_fatal("%s\n", g.zErrMsg); | |
| 297 | + fossil_fatal("%s", g.zErrMsg); | |
| 298 | 298 | } |
| 299 | 299 | assert( blob_is_reset(&branch) ); |
| 300 | 300 | content_deltify(rootid, brid, 0); |
| 301 | 301 | if( zNewRid ){ |
| 302 | 302 | *zNewRid = brid; |
| 303 | 303 |
| --- src/json_branch.c | |
| +++ src/json_branch.c | |
| @@ -292,11 +292,11 @@ | |
| 292 | if( brid==0 ){ |
| 293 | fossil_fatal("Problem committing manifest: %s", g.zErrMsg); |
| 294 | } |
| 295 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid); |
| 296 | if( manifest_crosslink(brid, &branch, MC_PERMIT_HOOKS)==0 ){ |
| 297 | fossil_fatal("%s\n", g.zErrMsg); |
| 298 | } |
| 299 | assert( blob_is_reset(&branch) ); |
| 300 | content_deltify(rootid, brid, 0); |
| 301 | if( zNewRid ){ |
| 302 | *zNewRid = brid; |
| 303 |
| --- src/json_branch.c | |
| +++ src/json_branch.c | |
| @@ -292,11 +292,11 @@ | |
| 292 | if( brid==0 ){ |
| 293 | fossil_fatal("Problem committing manifest: %s", g.zErrMsg); |
| 294 | } |
| 295 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid); |
| 296 | if( manifest_crosslink(brid, &branch, MC_PERMIT_HOOKS)==0 ){ |
| 297 | fossil_fatal("%s", g.zErrMsg); |
| 298 | } |
| 299 | assert( blob_is_reset(&branch) ); |
| 300 | content_deltify(rootid, brid, 0); |
| 301 | if( zNewRid ){ |
| 302 | *zNewRid = brid; |
| 303 |
+19
-1
| --- src/json_wiki.c | ||
| +++ src/json_wiki.c | ||
| @@ -115,12 +115,30 @@ | ||
| 115 | 115 | if( contentFormat>0 ){/*HTML-ize it*/ |
| 116 | 116 | Blob content = empty_blob; |
| 117 | 117 | Blob raw = empty_blob; |
| 118 | 118 | zFormat = "html"; |
| 119 | 119 | if(zBody && *zBody){ |
| 120 | + const char *zMimetype = pWiki->zMimetype; | |
| 121 | + if( zMimetype==0 ) zMimetype = "text/plain"; | |
| 122 | + zMimetype = wiki_filter_mimetypes(zMimetype); | |
| 120 | 123 | blob_append(&raw,zBody,-1); |
| 121 | - wiki_convert(&raw,&content,0); | |
| 124 | + if( fossil_strcmp(zMimetype, "text/x-fossil-wiki")==0 ){ | |
| 125 | + wiki_convert(&raw,&content,0); | |
| 126 | + }else if( fossil_strcmp(zMimetype, "text/x-markdown")==0 ){ | |
| 127 | + markdown_to_html(&raw,0,&content); | |
| 128 | + }else if( fossil_strcmp(zMimetype, "text/plain")==0 ){ | |
| 129 | + htmlize_to_blob(&content,blob_str(&raw),blob_size(&raw)); | |
| 130 | + }else{ | |
| 131 | + json_set_err( FSL_JSON_E_UNKNOWN, | |
| 132 | + "Unsupported MIME type '%s' for wiki page '%s'.", | |
| 133 | + zMimetype, pWiki->zWikiTitle ); | |
| 134 | + blob_reset(&content); | |
| 135 | + blob_reset(&raw); | |
| 136 | + cson_free_object(pay); | |
| 137 | + manifest_destroy(pWiki); | |
| 138 | + return NULL; | |
| 139 | + } | |
| 122 | 140 | len = (unsigned int)blob_size(&content); |
| 123 | 141 | } |
| 124 | 142 | cson_object_set(pay,"size",json_new_int((cson_int_t)len)); |
| 125 | 143 | cson_object_set(pay,"content", |
| 126 | 144 | cson_value_new_string(blob_buffer(&content),len)); |
| 127 | 145 |
| --- src/json_wiki.c | |
| +++ src/json_wiki.c | |
| @@ -115,12 +115,30 @@ | |
| 115 | if( contentFormat>0 ){/*HTML-ize it*/ |
| 116 | Blob content = empty_blob; |
| 117 | Blob raw = empty_blob; |
| 118 | zFormat = "html"; |
| 119 | if(zBody && *zBody){ |
| 120 | blob_append(&raw,zBody,-1); |
| 121 | wiki_convert(&raw,&content,0); |
| 122 | len = (unsigned int)blob_size(&content); |
| 123 | } |
| 124 | cson_object_set(pay,"size",json_new_int((cson_int_t)len)); |
| 125 | cson_object_set(pay,"content", |
| 126 | cson_value_new_string(blob_buffer(&content),len)); |
| 127 |
| --- src/json_wiki.c | |
| +++ src/json_wiki.c | |
| @@ -115,12 +115,30 @@ | |
| 115 | if( contentFormat>0 ){/*HTML-ize it*/ |
| 116 | Blob content = empty_blob; |
| 117 | Blob raw = empty_blob; |
| 118 | zFormat = "html"; |
| 119 | if(zBody && *zBody){ |
| 120 | const char *zMimetype = pWiki->zMimetype; |
| 121 | if( zMimetype==0 ) zMimetype = "text/plain"; |
| 122 | zMimetype = wiki_filter_mimetypes(zMimetype); |
| 123 | blob_append(&raw,zBody,-1); |
| 124 | if( fossil_strcmp(zMimetype, "text/x-fossil-wiki")==0 ){ |
| 125 | wiki_convert(&raw,&content,0); |
| 126 | }else if( fossil_strcmp(zMimetype, "text/x-markdown")==0 ){ |
| 127 | markdown_to_html(&raw,0,&content); |
| 128 | }else if( fossil_strcmp(zMimetype, "text/plain")==0 ){ |
| 129 | htmlize_to_blob(&content,blob_str(&raw),blob_size(&raw)); |
| 130 | }else{ |
| 131 | json_set_err( FSL_JSON_E_UNKNOWN, |
| 132 | "Unsupported MIME type '%s' for wiki page '%s'.", |
| 133 | zMimetype, pWiki->zWikiTitle ); |
| 134 | blob_reset(&content); |
| 135 | blob_reset(&raw); |
| 136 | cson_free_object(pay); |
| 137 | manifest_destroy(pWiki); |
| 138 | return NULL; |
| 139 | } |
| 140 | len = (unsigned int)blob_size(&content); |
| 141 | } |
| 142 | cson_object_set(pay,"size",json_new_int((cson_int_t)len)); |
| 143 | cson_object_set(pay,"content", |
| 144 | cson_value_new_string(blob_buffer(&content),len)); |
| 145 |
+34
| --- src/linenoise.c | ||
| +++ src/linenoise.c | ||
| @@ -105,10 +105,11 @@ | ||
| 105 | 105 | * |
| 106 | 106 | */ |
| 107 | 107 | |
| 108 | 108 | #include <termios.h> |
| 109 | 109 | #include <unistd.h> |
| 110 | +#include <stdarg.h> | |
| 110 | 111 | #include <stdlib.h> |
| 111 | 112 | #include <stdio.h> |
| 112 | 113 | #include <errno.h> |
| 113 | 114 | #include <string.h> |
| 114 | 115 | #include <stdlib.h> |
| @@ -115,10 +116,11 @@ | ||
| 115 | 116 | #include <ctype.h> |
| 116 | 117 | #include <sys/types.h> |
| 117 | 118 | #include <sys/ioctl.h> |
| 118 | 119 | #include <unistd.h> |
| 119 | 120 | #include "linenoise.h" |
| 121 | +#include "sqlite3.h" | |
| 120 | 122 | |
| 121 | 123 | #define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100 |
| 122 | 124 | #define LINENOISE_MAX_LINE 4096 |
| 123 | 125 | static const char *unsupported_term[] = {"dumb","cons25","emacs",NULL}; |
| 124 | 126 | static linenoiseCompletionCallback *completionCallback = NULL; |
| @@ -191,10 +193,42 @@ | ||
| 191 | 193 | fflush(lndebug_fp); \ |
| 192 | 194 | } while (0) |
| 193 | 195 | #else |
| 194 | 196 | #define lndebug(fmt, arg1) |
| 195 | 197 | #endif |
| 198 | + | |
| 199 | +/* =========================== C89 compatibility ============================ */ | |
| 200 | + | |
| 201 | +/* snprintf() is not C89, but sqlite3_vsnprintf() can be adapted. */ | |
| 202 | +static int linenoiseSnprintf(char *str, size_t size, const char *format, ...) { | |
| 203 | + va_list ap; | |
| 204 | + int result; | |
| 205 | + | |
| 206 | + va_start(ap,format); | |
| 207 | + result = (int)strlen(sqlite3_vsnprintf((int)size,str,format,ap)); | |
| 208 | + va_end(ap); | |
| 209 | + | |
| 210 | + return result; | |
| 211 | +} | |
| 212 | +#undef snprintf | |
| 213 | +#define snprintf linenoiseSnprintf | |
| 214 | + | |
| 215 | +/* strdup() is technically not standard C89 despite being in POSIX. */ | |
| 216 | +static char *linenoiseStrdup(const char *s) { | |
| 217 | + size_t size = strlen(s)+1; | |
| 218 | + char *result = malloc(size); | |
| 219 | + | |
| 220 | + if (result) memcpy(result,s,size); | |
| 221 | + | |
| 222 | + return result; | |
| 223 | +} | |
| 224 | +#undef strdup | |
| 225 | +#define strdup linenoiseStrdup | |
| 226 | + | |
| 227 | +/* strcasecmp() is not standard C89. SQLite offers a direct replacement. */ | |
| 228 | +#undef strcasecmp | |
| 229 | +#define strcasecmp sqlite3_stricmp | |
| 196 | 230 | |
| 197 | 231 | /* ======================= Low level terminal handling ====================== */ |
| 198 | 232 | |
| 199 | 233 | /* Set if to use or not the multi line mode. */ |
| 200 | 234 | void linenoiseSetMultiLine(int ml) { |
| 201 | 235 |
| --- src/linenoise.c | |
| +++ src/linenoise.c | |
| @@ -105,10 +105,11 @@ | |
| 105 | * |
| 106 | */ |
| 107 | |
| 108 | #include <termios.h> |
| 109 | #include <unistd.h> |
| 110 | #include <stdlib.h> |
| 111 | #include <stdio.h> |
| 112 | #include <errno.h> |
| 113 | #include <string.h> |
| 114 | #include <stdlib.h> |
| @@ -115,10 +116,11 @@ | |
| 115 | #include <ctype.h> |
| 116 | #include <sys/types.h> |
| 117 | #include <sys/ioctl.h> |
| 118 | #include <unistd.h> |
| 119 | #include "linenoise.h" |
| 120 | |
| 121 | #define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100 |
| 122 | #define LINENOISE_MAX_LINE 4096 |
| 123 | static const char *unsupported_term[] = {"dumb","cons25","emacs",NULL}; |
| 124 | static linenoiseCompletionCallback *completionCallback = NULL; |
| @@ -191,10 +193,42 @@ | |
| 191 | fflush(lndebug_fp); \ |
| 192 | } while (0) |
| 193 | #else |
| 194 | #define lndebug(fmt, arg1) |
| 195 | #endif |
| 196 | |
| 197 | /* ======================= Low level terminal handling ====================== */ |
| 198 | |
| 199 | /* Set if to use or not the multi line mode. */ |
| 200 | void linenoiseSetMultiLine(int ml) { |
| 201 |
| --- src/linenoise.c | |
| +++ src/linenoise.c | |
| @@ -105,10 +105,11 @@ | |
| 105 | * |
| 106 | */ |
| 107 | |
| 108 | #include <termios.h> |
| 109 | #include <unistd.h> |
| 110 | #include <stdarg.h> |
| 111 | #include <stdlib.h> |
| 112 | #include <stdio.h> |
| 113 | #include <errno.h> |
| 114 | #include <string.h> |
| 115 | #include <stdlib.h> |
| @@ -115,10 +116,11 @@ | |
| 116 | #include <ctype.h> |
| 117 | #include <sys/types.h> |
| 118 | #include <sys/ioctl.h> |
| 119 | #include <unistd.h> |
| 120 | #include "linenoise.h" |
| 121 | #include "sqlite3.h" |
| 122 | |
| 123 | #define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100 |
| 124 | #define LINENOISE_MAX_LINE 4096 |
| 125 | static const char *unsupported_term[] = {"dumb","cons25","emacs",NULL}; |
| 126 | static linenoiseCompletionCallback *completionCallback = NULL; |
| @@ -191,10 +193,42 @@ | |
| 193 | fflush(lndebug_fp); \ |
| 194 | } while (0) |
| 195 | #else |
| 196 | #define lndebug(fmt, arg1) |
| 197 | #endif |
| 198 | |
| 199 | /* =========================== C89 compatibility ============================ */ |
| 200 | |
| 201 | /* snprintf() is not C89, but sqlite3_vsnprintf() can be adapted. */ |
| 202 | static int linenoiseSnprintf(char *str, size_t size, const char *format, ...) { |
| 203 | va_list ap; |
| 204 | int result; |
| 205 | |
| 206 | va_start(ap,format); |
| 207 | result = (int)strlen(sqlite3_vsnprintf((int)size,str,format,ap)); |
| 208 | va_end(ap); |
| 209 | |
| 210 | return result; |
| 211 | } |
| 212 | #undef snprintf |
| 213 | #define snprintf linenoiseSnprintf |
| 214 | |
| 215 | /* strdup() is technically not standard C89 despite being in POSIX. */ |
| 216 | static char *linenoiseStrdup(const char *s) { |
| 217 | size_t size = strlen(s)+1; |
| 218 | char *result = malloc(size); |
| 219 | |
| 220 | if (result) memcpy(result,s,size); |
| 221 | |
| 222 | return result; |
| 223 | } |
| 224 | #undef strdup |
| 225 | #define strdup linenoiseStrdup |
| 226 | |
| 227 | /* strcasecmp() is not standard C89. SQLite offers a direct replacement. */ |
| 228 | #undef strcasecmp |
| 229 | #define strcasecmp sqlite3_stricmp |
| 230 | |
| 231 | /* ======================= Low level terminal handling ====================== */ |
| 232 | |
| 233 | /* Set if to use or not the multi line mode. */ |
| 234 | void linenoiseSetMultiLine(int ml) { |
| 235 |
+80
-5
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -18,20 +18,21 @@ | ||
| 18 | 18 | ** This module codes the main() procedure that runs first when the |
| 19 | 19 | ** program is invoked. |
| 20 | 20 | */ |
| 21 | 21 | #include "VERSION.h" |
| 22 | 22 | #include "config.h" |
| 23 | +#if defined(_WIN32) | |
| 24 | +# include <windows.h> | |
| 25 | +#endif | |
| 23 | 26 | #include "main.h" |
| 24 | 27 | #include <string.h> |
| 25 | 28 | #include <time.h> |
| 26 | 29 | #include <fcntl.h> |
| 27 | 30 | #include <sys/types.h> |
| 28 | 31 | #include <sys/stat.h> |
| 29 | 32 | #include <stdlib.h> /* atexit() */ |
| 30 | -#if defined(_WIN32) | |
| 31 | -# include <windows.h> | |
| 32 | -#else | |
| 33 | +#if !defined(_WIN32) | |
| 33 | 34 | # include <errno.h> /* errno global */ |
| 34 | 35 | #endif |
| 35 | 36 | #ifdef FOSSIL_ENABLE_SSL |
| 36 | 37 | # include "openssl/crypto.h" |
| 37 | 38 | #endif |
| @@ -299,10 +300,22 @@ | ||
| 299 | 300 | /* |
| 300 | 301 | ** atexit() handler which frees up "some" of the resources |
| 301 | 302 | ** used by fossil. |
| 302 | 303 | */ |
| 303 | 304 | static void fossil_atexit(void) { |
| 305 | +#if USE_SEE | |
| 306 | + /* | |
| 307 | + ** Zero, unlock, and free the saved database encryption key now. | |
| 308 | + */ | |
| 309 | + db_unsave_encryption_key(); | |
| 310 | +#endif | |
| 311 | +#if defined(_WIN32) || defined(__BIONIC__) | |
| 312 | + /* | |
| 313 | + ** Free the secure getpass() buffer now. | |
| 314 | + */ | |
| 315 | + freepass(); | |
| 316 | +#endif | |
| 304 | 317 | #if defined(_WIN32) && !defined(_WIN64) && defined(FOSSIL_ENABLE_TCL) && \ |
| 305 | 318 | defined(USE_TCL_STUBS) |
| 306 | 319 | /* |
| 307 | 320 | ** If Tcl is compiled on Windows using the latest MinGW, Fossil can crash |
| 308 | 321 | ** when exiting while a stubs-enabled Tcl is still loaded. This is due to |
| @@ -1917,10 +1930,41 @@ | ||
| 1917 | 1930 | } |
| 1918 | 1931 | } |
| 1919 | 1932 | } |
| 1920 | 1933 | } |
| 1921 | 1934 | |
| 1935 | +#if defined(_WIN32) && USE_SEE | |
| 1936 | +/* | |
| 1937 | +** This function attempts to parse a string value in the following | |
| 1938 | +** format: | |
| 1939 | +** | |
| 1940 | +** "%lu:%p:%u" | |
| 1941 | +** | |
| 1942 | +** There are three parts, which must be delimited by colons. The | |
| 1943 | +** first part is an unsigned long integer in base-10 (decimal) format. | |
| 1944 | +** The second part is a numerical representation of a native pointer, | |
| 1945 | +** in the appropriate implementation defined format. The third part | |
| 1946 | +** is an unsigned integer in base-10 (decimal) format. | |
| 1947 | +** | |
| 1948 | +** If the specified value cannot be parsed, for any reason, a fatal | |
| 1949 | +** error will be raised and the process will be terminated. | |
| 1950 | +*/ | |
| 1951 | +void parse_pid_key_value( | |
| 1952 | + const char *zPidKey, /* The value to be parsed. */ | |
| 1953 | + DWORD *pProcessId, /* The extracted process identifier. */ | |
| 1954 | + LPVOID *ppAddress, /* The extracted pointer value. */ | |
| 1955 | + SIZE_T *pnSize /* The extracted size value. */ | |
| 1956 | +){ | |
| 1957 | + unsigned int nSize = 0; | |
| 1958 | + if( sscanf(zPidKey, "%lu:%p:%u", pProcessId, ppAddress, &nSize)==3 ){ | |
| 1959 | + *pnSize = (SIZE_T)nSize; | |
| 1960 | + }else{ | |
| 1961 | + fossil_fatal("failed to parse pid key"); | |
| 1962 | + } | |
| 1963 | +} | |
| 1964 | +#endif | |
| 1965 | + | |
| 1922 | 1966 | /* |
| 1923 | 1967 | ** undocumented format: |
| 1924 | 1968 | ** |
| 1925 | 1969 | ** fossil http INFILE OUTFILE IPADDR ?REPOSITORY? |
| 1926 | 1970 | ** |
| @@ -1968,10 +2012,12 @@ | ||
| 1968 | 2012 | ** --notfound URL use URL as "HTTP 404, object not found" page. |
| 1969 | 2013 | ** --repolist If REPOSITORY is directory, URL "/" lists all repos |
| 1970 | 2014 | ** --scgi Interpret input as SCGI rather than HTTP |
| 1971 | 2015 | ** --skin LABEL Use override skin LABEL |
| 1972 | 2016 | ** --th-trace trace TH1 execution (for debugging purposes) |
| 2017 | +** --usepidkey Use saved encryption key from parent process. This is | |
| 2018 | +** only necessary when using SEE on Windows. | |
| 1973 | 2019 | ** |
| 1974 | 2020 | ** See also: cgi, server, winsrv |
| 1975 | 2021 | */ |
| 1976 | 2022 | void cmd_http(void){ |
| 1977 | 2023 | const char *zIpAddr = 0; |
| @@ -1980,10 +2026,13 @@ | ||
| 1980 | 2026 | const char *zAltBase; |
| 1981 | 2027 | const char *zFileGlob; |
| 1982 | 2028 | int useSCGI; |
| 1983 | 2029 | int noJail; |
| 1984 | 2030 | int allowRepoList; |
| 2031 | +#if defined(_WIN32) && USE_SEE | |
| 2032 | + const char *zPidKey; | |
| 2033 | +#endif | |
| 1985 | 2034 | |
| 1986 | 2035 | Th_InitTraceLog(); |
| 1987 | 2036 | |
| 1988 | 2037 | /* The winhttp module passes the --files option as --files-urlenc with |
| 1989 | 2038 | ** the argument being URL encoded, to avoid wildcard expansion in the |
| @@ -2010,10 +2059,21 @@ | ||
| 2010 | 2059 | zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */ |
| 2011 | 2060 | cgi_replace_parameter("HTTPS","on"); |
| 2012 | 2061 | } |
| 2013 | 2062 | zHost = find_option("host", 0, 1); |
| 2014 | 2063 | if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost); |
| 2064 | + | |
| 2065 | +#if defined(_WIN32) && USE_SEE | |
| 2066 | + zPidKey = find_option("usepidkey", 0, 1); | |
| 2067 | + if( zPidKey ){ | |
| 2068 | + DWORD processId = 0; | |
| 2069 | + LPVOID pAddress = NULL; | |
| 2070 | + SIZE_T nSize = 0; | |
| 2071 | + parse_pid_key_value(zPidKey, &processId, &pAddress, &nSize); | |
| 2072 | + db_read_saved_encryption_key_from_process(processId, pAddress, nSize); | |
| 2073 | + } | |
| 2074 | +#endif | |
| 2015 | 2075 | |
| 2016 | 2076 | /* We should be done with options.. */ |
| 2017 | 2077 | verify_all_options(); |
| 2018 | 2078 | |
| 2019 | 2079 | if( g.argc!=2 && g.argc!=3 && g.argc!=5 && g.argc!=6 ){ |
| @@ -2171,11 +2231,12 @@ | ||
| 2171 | 2231 | ** -P|--port TCPPORT listen to request on port TCPPORT |
| 2172 | 2232 | ** --th-trace trace TH1 execution (for debugging purposes) |
| 2173 | 2233 | ** --repolist If REPOSITORY is dir, URL "/" lists repos. |
| 2174 | 2234 | ** --scgi Accept SCGI rather than HTTP |
| 2175 | 2235 | ** --skin LABEL Use override skin LABEL |
| 2176 | - | |
| 2236 | +** --usepidkey Use saved encryption key from parent process. This is | |
| 2237 | +** only necessary when using SEE on Windows. | |
| 2177 | 2238 | ** |
| 2178 | 2239 | ** See also: cgi, http, winsrv |
| 2179 | 2240 | */ |
| 2180 | 2241 | void cmd_webserver(void){ |
| 2181 | 2242 | int iPort, mxPort; /* Range of TCP ports allowed */ |
| @@ -2192,10 +2253,13 @@ | ||
| 2192 | 2253 | const char *zAltBase; /* Argument to the --baseurl option */ |
| 2193 | 2254 | const char *zFileGlob; /* Static content must match this */ |
| 2194 | 2255 | char *zIpAddr = 0; /* Bind to this IP address */ |
| 2195 | 2256 | int fCreate = 0; /* The --create flag */ |
| 2196 | 2257 | const char *zInitPage = 0; /* Start on this page. --page option */ |
| 2258 | +#if defined(_WIN32) && USE_SEE | |
| 2259 | + const char *zPidKey; | |
| 2260 | +#endif | |
| 2197 | 2261 | |
| 2198 | 2262 | #if defined(_WIN32) |
| 2199 | 2263 | const char *zStopperFile; /* Name of file used to terminate server */ |
| 2200 | 2264 | zStopperFile = find_option("stopper", 0, 1); |
| 2201 | 2265 | #endif |
| @@ -2235,10 +2299,21 @@ | ||
| 2235 | 2299 | g.sslNotAvailable = 1; |
| 2236 | 2300 | } |
| 2237 | 2301 | if( find_option("localhost", 0, 0)!=0 ){ |
| 2238 | 2302 | flags |= HTTP_SERVER_LOCALHOST; |
| 2239 | 2303 | } |
| 2304 | + | |
| 2305 | +#if defined(_WIN32) && USE_SEE | |
| 2306 | + zPidKey = find_option("usepidkey", 0, 1); | |
| 2307 | + if( zPidKey ){ | |
| 2308 | + DWORD processId = 0; | |
| 2309 | + LPVOID pAddress = NULL; | |
| 2310 | + SIZE_T nSize = 0; | |
| 2311 | + parse_pid_key_value(zPidKey, &processId, &pAddress, &nSize); | |
| 2312 | + db_read_saved_encryption_key_from_process(processId, pAddress, nSize); | |
| 2313 | + } | |
| 2314 | +#endif | |
| 2240 | 2315 | |
| 2241 | 2316 | /* We should be done with options.. */ |
| 2242 | 2317 | verify_all_options(); |
| 2243 | 2318 | |
| 2244 | 2319 | if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?"); |
| @@ -2275,11 +2350,11 @@ | ||
| 2275 | 2350 | if( zBrowser==0 ){ |
| 2276 | 2351 | static const char *const azBrowserProg[] = |
| 2277 | 2352 | { "xdg-open", "gnome-open", "firefox", "google-chrome" }; |
| 2278 | 2353 | int i; |
| 2279 | 2354 | zBrowser = "echo"; |
| 2280 | - for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){ | |
| 2355 | + for(i=0; i<count(azBrowserProg); i++){ | |
| 2281 | 2356 | if( binaryOnPath(azBrowserProg[i]) ){ |
| 2282 | 2357 | zBrowser = azBrowserProg[i]; |
| 2283 | 2358 | break; |
| 2284 | 2359 | } |
| 2285 | 2360 | } |
| 2286 | 2361 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -18,20 +18,21 @@ | |
| 18 | ** This module codes the main() procedure that runs first when the |
| 19 | ** program is invoked. |
| 20 | */ |
| 21 | #include "VERSION.h" |
| 22 | #include "config.h" |
| 23 | #include "main.h" |
| 24 | #include <string.h> |
| 25 | #include <time.h> |
| 26 | #include <fcntl.h> |
| 27 | #include <sys/types.h> |
| 28 | #include <sys/stat.h> |
| 29 | #include <stdlib.h> /* atexit() */ |
| 30 | #if defined(_WIN32) |
| 31 | # include <windows.h> |
| 32 | #else |
| 33 | # include <errno.h> /* errno global */ |
| 34 | #endif |
| 35 | #ifdef FOSSIL_ENABLE_SSL |
| 36 | # include "openssl/crypto.h" |
| 37 | #endif |
| @@ -299,10 +300,22 @@ | |
| 299 | /* |
| 300 | ** atexit() handler which frees up "some" of the resources |
| 301 | ** used by fossil. |
| 302 | */ |
| 303 | static void fossil_atexit(void) { |
| 304 | #if defined(_WIN32) && !defined(_WIN64) && defined(FOSSIL_ENABLE_TCL) && \ |
| 305 | defined(USE_TCL_STUBS) |
| 306 | /* |
| 307 | ** If Tcl is compiled on Windows using the latest MinGW, Fossil can crash |
| 308 | ** when exiting while a stubs-enabled Tcl is still loaded. This is due to |
| @@ -1917,10 +1930,41 @@ | |
| 1917 | } |
| 1918 | } |
| 1919 | } |
| 1920 | } |
| 1921 | |
| 1922 | /* |
| 1923 | ** undocumented format: |
| 1924 | ** |
| 1925 | ** fossil http INFILE OUTFILE IPADDR ?REPOSITORY? |
| 1926 | ** |
| @@ -1968,10 +2012,12 @@ | |
| 1968 | ** --notfound URL use URL as "HTTP 404, object not found" page. |
| 1969 | ** --repolist If REPOSITORY is directory, URL "/" lists all repos |
| 1970 | ** --scgi Interpret input as SCGI rather than HTTP |
| 1971 | ** --skin LABEL Use override skin LABEL |
| 1972 | ** --th-trace trace TH1 execution (for debugging purposes) |
| 1973 | ** |
| 1974 | ** See also: cgi, server, winsrv |
| 1975 | */ |
| 1976 | void cmd_http(void){ |
| 1977 | const char *zIpAddr = 0; |
| @@ -1980,10 +2026,13 @@ | |
| 1980 | const char *zAltBase; |
| 1981 | const char *zFileGlob; |
| 1982 | int useSCGI; |
| 1983 | int noJail; |
| 1984 | int allowRepoList; |
| 1985 | |
| 1986 | Th_InitTraceLog(); |
| 1987 | |
| 1988 | /* The winhttp module passes the --files option as --files-urlenc with |
| 1989 | ** the argument being URL encoded, to avoid wildcard expansion in the |
| @@ -2010,10 +2059,21 @@ | |
| 2010 | zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */ |
| 2011 | cgi_replace_parameter("HTTPS","on"); |
| 2012 | } |
| 2013 | zHost = find_option("host", 0, 1); |
| 2014 | if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost); |
| 2015 | |
| 2016 | /* We should be done with options.. */ |
| 2017 | verify_all_options(); |
| 2018 | |
| 2019 | if( g.argc!=2 && g.argc!=3 && g.argc!=5 && g.argc!=6 ){ |
| @@ -2171,11 +2231,12 @@ | |
| 2171 | ** -P|--port TCPPORT listen to request on port TCPPORT |
| 2172 | ** --th-trace trace TH1 execution (for debugging purposes) |
| 2173 | ** --repolist If REPOSITORY is dir, URL "/" lists repos. |
| 2174 | ** --scgi Accept SCGI rather than HTTP |
| 2175 | ** --skin LABEL Use override skin LABEL |
| 2176 | |
| 2177 | ** |
| 2178 | ** See also: cgi, http, winsrv |
| 2179 | */ |
| 2180 | void cmd_webserver(void){ |
| 2181 | int iPort, mxPort; /* Range of TCP ports allowed */ |
| @@ -2192,10 +2253,13 @@ | |
| 2192 | const char *zAltBase; /* Argument to the --baseurl option */ |
| 2193 | const char *zFileGlob; /* Static content must match this */ |
| 2194 | char *zIpAddr = 0; /* Bind to this IP address */ |
| 2195 | int fCreate = 0; /* The --create flag */ |
| 2196 | const char *zInitPage = 0; /* Start on this page. --page option */ |
| 2197 | |
| 2198 | #if defined(_WIN32) |
| 2199 | const char *zStopperFile; /* Name of file used to terminate server */ |
| 2200 | zStopperFile = find_option("stopper", 0, 1); |
| 2201 | #endif |
| @@ -2235,10 +2299,21 @@ | |
| 2235 | g.sslNotAvailable = 1; |
| 2236 | } |
| 2237 | if( find_option("localhost", 0, 0)!=0 ){ |
| 2238 | flags |= HTTP_SERVER_LOCALHOST; |
| 2239 | } |
| 2240 | |
| 2241 | /* We should be done with options.. */ |
| 2242 | verify_all_options(); |
| 2243 | |
| 2244 | if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?"); |
| @@ -2275,11 +2350,11 @@ | |
| 2275 | if( zBrowser==0 ){ |
| 2276 | static const char *const azBrowserProg[] = |
| 2277 | { "xdg-open", "gnome-open", "firefox", "google-chrome" }; |
| 2278 | int i; |
| 2279 | zBrowser = "echo"; |
| 2280 | for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){ |
| 2281 | if( binaryOnPath(azBrowserProg[i]) ){ |
| 2282 | zBrowser = azBrowserProg[i]; |
| 2283 | break; |
| 2284 | } |
| 2285 | } |
| 2286 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -18,20 +18,21 @@ | |
| 18 | ** This module codes the main() procedure that runs first when the |
| 19 | ** program is invoked. |
| 20 | */ |
| 21 | #include "VERSION.h" |
| 22 | #include "config.h" |
| 23 | #if defined(_WIN32) |
| 24 | # include <windows.h> |
| 25 | #endif |
| 26 | #include "main.h" |
| 27 | #include <string.h> |
| 28 | #include <time.h> |
| 29 | #include <fcntl.h> |
| 30 | #include <sys/types.h> |
| 31 | #include <sys/stat.h> |
| 32 | #include <stdlib.h> /* atexit() */ |
| 33 | #if !defined(_WIN32) |
| 34 | # include <errno.h> /* errno global */ |
| 35 | #endif |
| 36 | #ifdef FOSSIL_ENABLE_SSL |
| 37 | # include "openssl/crypto.h" |
| 38 | #endif |
| @@ -299,10 +300,22 @@ | |
| 300 | /* |
| 301 | ** atexit() handler which frees up "some" of the resources |
| 302 | ** used by fossil. |
| 303 | */ |
| 304 | static void fossil_atexit(void) { |
| 305 | #if USE_SEE |
| 306 | /* |
| 307 | ** Zero, unlock, and free the saved database encryption key now. |
| 308 | */ |
| 309 | db_unsave_encryption_key(); |
| 310 | #endif |
| 311 | #if defined(_WIN32) || defined(__BIONIC__) |
| 312 | /* |
| 313 | ** Free the secure getpass() buffer now. |
| 314 | */ |
| 315 | freepass(); |
| 316 | #endif |
| 317 | #if defined(_WIN32) && !defined(_WIN64) && defined(FOSSIL_ENABLE_TCL) && \ |
| 318 | defined(USE_TCL_STUBS) |
| 319 | /* |
| 320 | ** If Tcl is compiled on Windows using the latest MinGW, Fossil can crash |
| 321 | ** when exiting while a stubs-enabled Tcl is still loaded. This is due to |
| @@ -1917,10 +1930,41 @@ | |
| 1930 | } |
| 1931 | } |
| 1932 | } |
| 1933 | } |
| 1934 | |
| 1935 | #if defined(_WIN32) && USE_SEE |
| 1936 | /* |
| 1937 | ** This function attempts to parse a string value in the following |
| 1938 | ** format: |
| 1939 | ** |
| 1940 | ** "%lu:%p:%u" |
| 1941 | ** |
| 1942 | ** There are three parts, which must be delimited by colons. The |
| 1943 | ** first part is an unsigned long integer in base-10 (decimal) format. |
| 1944 | ** The second part is a numerical representation of a native pointer, |
| 1945 | ** in the appropriate implementation defined format. The third part |
| 1946 | ** is an unsigned integer in base-10 (decimal) format. |
| 1947 | ** |
| 1948 | ** If the specified value cannot be parsed, for any reason, a fatal |
| 1949 | ** error will be raised and the process will be terminated. |
| 1950 | */ |
| 1951 | void parse_pid_key_value( |
| 1952 | const char *zPidKey, /* The value to be parsed. */ |
| 1953 | DWORD *pProcessId, /* The extracted process identifier. */ |
| 1954 | LPVOID *ppAddress, /* The extracted pointer value. */ |
| 1955 | SIZE_T *pnSize /* The extracted size value. */ |
| 1956 | ){ |
| 1957 | unsigned int nSize = 0; |
| 1958 | if( sscanf(zPidKey, "%lu:%p:%u", pProcessId, ppAddress, &nSize)==3 ){ |
| 1959 | *pnSize = (SIZE_T)nSize; |
| 1960 | }else{ |
| 1961 | fossil_fatal("failed to parse pid key"); |
| 1962 | } |
| 1963 | } |
| 1964 | #endif |
| 1965 | |
| 1966 | /* |
| 1967 | ** undocumented format: |
| 1968 | ** |
| 1969 | ** fossil http INFILE OUTFILE IPADDR ?REPOSITORY? |
| 1970 | ** |
| @@ -1968,10 +2012,12 @@ | |
| 2012 | ** --notfound URL use URL as "HTTP 404, object not found" page. |
| 2013 | ** --repolist If REPOSITORY is directory, URL "/" lists all repos |
| 2014 | ** --scgi Interpret input as SCGI rather than HTTP |
| 2015 | ** --skin LABEL Use override skin LABEL |
| 2016 | ** --th-trace trace TH1 execution (for debugging purposes) |
| 2017 | ** --usepidkey Use saved encryption key from parent process. This is |
| 2018 | ** only necessary when using SEE on Windows. |
| 2019 | ** |
| 2020 | ** See also: cgi, server, winsrv |
| 2021 | */ |
| 2022 | void cmd_http(void){ |
| 2023 | const char *zIpAddr = 0; |
| @@ -1980,10 +2026,13 @@ | |
| 2026 | const char *zAltBase; |
| 2027 | const char *zFileGlob; |
| 2028 | int useSCGI; |
| 2029 | int noJail; |
| 2030 | int allowRepoList; |
| 2031 | #if defined(_WIN32) && USE_SEE |
| 2032 | const char *zPidKey; |
| 2033 | #endif |
| 2034 | |
| 2035 | Th_InitTraceLog(); |
| 2036 | |
| 2037 | /* The winhttp module passes the --files option as --files-urlenc with |
| 2038 | ** the argument being URL encoded, to avoid wildcard expansion in the |
| @@ -2010,10 +2059,21 @@ | |
| 2059 | zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */ |
| 2060 | cgi_replace_parameter("HTTPS","on"); |
| 2061 | } |
| 2062 | zHost = find_option("host", 0, 1); |
| 2063 | if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost); |
| 2064 | |
| 2065 | #if defined(_WIN32) && USE_SEE |
| 2066 | zPidKey = find_option("usepidkey", 0, 1); |
| 2067 | if( zPidKey ){ |
| 2068 | DWORD processId = 0; |
| 2069 | LPVOID pAddress = NULL; |
| 2070 | SIZE_T nSize = 0; |
| 2071 | parse_pid_key_value(zPidKey, &processId, &pAddress, &nSize); |
| 2072 | db_read_saved_encryption_key_from_process(processId, pAddress, nSize); |
| 2073 | } |
| 2074 | #endif |
| 2075 | |
| 2076 | /* We should be done with options.. */ |
| 2077 | verify_all_options(); |
| 2078 | |
| 2079 | if( g.argc!=2 && g.argc!=3 && g.argc!=5 && g.argc!=6 ){ |
| @@ -2171,11 +2231,12 @@ | |
| 2231 | ** -P|--port TCPPORT listen to request on port TCPPORT |
| 2232 | ** --th-trace trace TH1 execution (for debugging purposes) |
| 2233 | ** --repolist If REPOSITORY is dir, URL "/" lists repos. |
| 2234 | ** --scgi Accept SCGI rather than HTTP |
| 2235 | ** --skin LABEL Use override skin LABEL |
| 2236 | ** --usepidkey Use saved encryption key from parent process. This is |
| 2237 | ** only necessary when using SEE on Windows. |
| 2238 | ** |
| 2239 | ** See also: cgi, http, winsrv |
| 2240 | */ |
| 2241 | void cmd_webserver(void){ |
| 2242 | int iPort, mxPort; /* Range of TCP ports allowed */ |
| @@ -2192,10 +2253,13 @@ | |
| 2253 | const char *zAltBase; /* Argument to the --baseurl option */ |
| 2254 | const char *zFileGlob; /* Static content must match this */ |
| 2255 | char *zIpAddr = 0; /* Bind to this IP address */ |
| 2256 | int fCreate = 0; /* The --create flag */ |
| 2257 | const char *zInitPage = 0; /* Start on this page. --page option */ |
| 2258 | #if defined(_WIN32) && USE_SEE |
| 2259 | const char *zPidKey; |
| 2260 | #endif |
| 2261 | |
| 2262 | #if defined(_WIN32) |
| 2263 | const char *zStopperFile; /* Name of file used to terminate server */ |
| 2264 | zStopperFile = find_option("stopper", 0, 1); |
| 2265 | #endif |
| @@ -2235,10 +2299,21 @@ | |
| 2299 | g.sslNotAvailable = 1; |
| 2300 | } |
| 2301 | if( find_option("localhost", 0, 0)!=0 ){ |
| 2302 | flags |= HTTP_SERVER_LOCALHOST; |
| 2303 | } |
| 2304 | |
| 2305 | #if defined(_WIN32) && USE_SEE |
| 2306 | zPidKey = find_option("usepidkey", 0, 1); |
| 2307 | if( zPidKey ){ |
| 2308 | DWORD processId = 0; |
| 2309 | LPVOID pAddress = NULL; |
| 2310 | SIZE_T nSize = 0; |
| 2311 | parse_pid_key_value(zPidKey, &processId, &pAddress, &nSize); |
| 2312 | db_read_saved_encryption_key_from_process(processId, pAddress, nSize); |
| 2313 | } |
| 2314 | #endif |
| 2315 | |
| 2316 | /* We should be done with options.. */ |
| 2317 | verify_all_options(); |
| 2318 | |
| 2319 | if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?"); |
| @@ -2275,11 +2350,11 @@ | |
| 2350 | if( zBrowser==0 ){ |
| 2351 | static const char *const azBrowserProg[] = |
| 2352 | { "xdg-open", "gnome-open", "firefox", "google-chrome" }; |
| 2353 | int i; |
| 2354 | zBrowser = "echo"; |
| 2355 | for(i=0; i<count(azBrowserProg); i++){ |
| 2356 | if( binaryOnPath(azBrowserProg[i]) ){ |
| 2357 | zBrowser = azBrowserProg[i]; |
| 2358 | break; |
| 2359 | } |
| 2360 | } |
| 2361 |
+7
-6
| --- src/main.mk | ||
| +++ src/main.mk | ||
| @@ -8,10 +8,11 @@ | ||
| 8 | 8 | # to regenerate this file. |
| 9 | 9 | # |
| 10 | 10 | # This file is included by primary Makefile. |
| 11 | 11 | # |
| 12 | 12 | |
| 13 | +XBCC = $(BCC) $(BCCFLAGS) $(CFLAGS) | |
| 13 | 14 | XTCC = $(TCC) -I. -I$(SRCDIR) -I$(OBJDIR) $(TCCFLAGS) $(CFLAGS) |
| 14 | 15 | |
| 15 | 16 | |
| 16 | 17 | SRC = \ |
| 17 | 18 | $(SRCDIR)/add.c \ |
| @@ -451,26 +452,26 @@ | ||
| 451 | 452 | |
| 452 | 453 | $(OBJDIR): |
| 453 | 454 | -mkdir $(OBJDIR) |
| 454 | 455 | |
| 455 | 456 | $(OBJDIR)/translate: $(SRCDIR)/translate.c |
| 456 | - $(BCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c | |
| 457 | + $(XBCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c | |
| 457 | 458 | |
| 458 | 459 | $(OBJDIR)/makeheaders: $(SRCDIR)/makeheaders.c |
| 459 | - $(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c | |
| 460 | + $(XBCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c | |
| 460 | 461 | |
| 461 | 462 | $(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c |
| 462 | - $(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c | |
| 463 | + $(XBCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c | |
| 463 | 464 | |
| 464 | 465 | $(OBJDIR)/mkbuiltin: $(SRCDIR)/mkbuiltin.c |
| 465 | - $(BCC) -o $(OBJDIR)/mkbuiltin $(SRCDIR)/mkbuiltin.c | |
| 466 | + $(XBCC) -o $(OBJDIR)/mkbuiltin $(SRCDIR)/mkbuiltin.c | |
| 466 | 467 | |
| 467 | 468 | $(OBJDIR)/mkversion: $(SRCDIR)/mkversion.c |
| 468 | - $(BCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c | |
| 469 | + $(XBCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c | |
| 469 | 470 | |
| 470 | 471 | $(OBJDIR)/codecheck1: $(SRCDIR)/codecheck1.c |
| 471 | - $(BCC) -o $(OBJDIR)/codecheck1 $(SRCDIR)/codecheck1.c | |
| 472 | + $(XBCC) -o $(OBJDIR)/codecheck1 $(SRCDIR)/codecheck1.c | |
| 472 | 473 | |
| 473 | 474 | # Run the test suite. |
| 474 | 475 | # Other flags that can be included in TESTFLAGS are: |
| 475 | 476 | # |
| 476 | 477 | # -halt Stop testing after the first failed test |
| 477 | 478 |
| --- src/main.mk | |
| +++ src/main.mk | |
| @@ -8,10 +8,11 @@ | |
| 8 | # to regenerate this file. |
| 9 | # |
| 10 | # This file is included by primary Makefile. |
| 11 | # |
| 12 | |
| 13 | XTCC = $(TCC) -I. -I$(SRCDIR) -I$(OBJDIR) $(TCCFLAGS) $(CFLAGS) |
| 14 | |
| 15 | |
| 16 | SRC = \ |
| 17 | $(SRCDIR)/add.c \ |
| @@ -451,26 +452,26 @@ | |
| 451 | |
| 452 | $(OBJDIR): |
| 453 | -mkdir $(OBJDIR) |
| 454 | |
| 455 | $(OBJDIR)/translate: $(SRCDIR)/translate.c |
| 456 | $(BCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c |
| 457 | |
| 458 | $(OBJDIR)/makeheaders: $(SRCDIR)/makeheaders.c |
| 459 | $(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c |
| 460 | |
| 461 | $(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c |
| 462 | $(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c |
| 463 | |
| 464 | $(OBJDIR)/mkbuiltin: $(SRCDIR)/mkbuiltin.c |
| 465 | $(BCC) -o $(OBJDIR)/mkbuiltin $(SRCDIR)/mkbuiltin.c |
| 466 | |
| 467 | $(OBJDIR)/mkversion: $(SRCDIR)/mkversion.c |
| 468 | $(BCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c |
| 469 | |
| 470 | $(OBJDIR)/codecheck1: $(SRCDIR)/codecheck1.c |
| 471 | $(BCC) -o $(OBJDIR)/codecheck1 $(SRCDIR)/codecheck1.c |
| 472 | |
| 473 | # Run the test suite. |
| 474 | # Other flags that can be included in TESTFLAGS are: |
| 475 | # |
| 476 | # -halt Stop testing after the first failed test |
| 477 |
| --- src/main.mk | |
| +++ src/main.mk | |
| @@ -8,10 +8,11 @@ | |
| 8 | # to regenerate this file. |
| 9 | # |
| 10 | # This file is included by primary Makefile. |
| 11 | # |
| 12 | |
| 13 | XBCC = $(BCC) $(BCCFLAGS) $(CFLAGS) |
| 14 | XTCC = $(TCC) -I. -I$(SRCDIR) -I$(OBJDIR) $(TCCFLAGS) $(CFLAGS) |
| 15 | |
| 16 | |
| 17 | SRC = \ |
| 18 | $(SRCDIR)/add.c \ |
| @@ -451,26 +452,26 @@ | |
| 452 | |
| 453 | $(OBJDIR): |
| 454 | -mkdir $(OBJDIR) |
| 455 | |
| 456 | $(OBJDIR)/translate: $(SRCDIR)/translate.c |
| 457 | $(XBCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c |
| 458 | |
| 459 | $(OBJDIR)/makeheaders: $(SRCDIR)/makeheaders.c |
| 460 | $(XBCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c |
| 461 | |
| 462 | $(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c |
| 463 | $(XBCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c |
| 464 | |
| 465 | $(OBJDIR)/mkbuiltin: $(SRCDIR)/mkbuiltin.c |
| 466 | $(XBCC) -o $(OBJDIR)/mkbuiltin $(SRCDIR)/mkbuiltin.c |
| 467 | |
| 468 | $(OBJDIR)/mkversion: $(SRCDIR)/mkversion.c |
| 469 | $(XBCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c |
| 470 | |
| 471 | $(OBJDIR)/codecheck1: $(SRCDIR)/codecheck1.c |
| 472 | $(XBCC) -o $(OBJDIR)/codecheck1 $(SRCDIR)/codecheck1.c |
| 473 | |
| 474 | # Run the test suite. |
| 475 | # Other flags that can be included in TESTFLAGS are: |
| 476 | # |
| 477 | # -halt Stop testing after the first failed test |
| 478 |
+93
-85
| --- src/makeheaders.html | ||
| +++ src/makeheaders.html | ||
| @@ -4,11 +4,11 @@ | ||
| 4 | 4 | <h1 align=center>The Makeheaders Program</h1> |
| 5 | 5 | |
| 6 | 6 | |
| 7 | 7 | <p> |
| 8 | 8 | This document describes <em>makeheaders</em>, |
| 9 | -a tool that automatically generates ``<code>.h</code>'' | |
| 9 | +a tool that automatically generates “<code>.h</code>” | |
| 10 | 10 | files for a C or C++ programming project. |
| 11 | 11 | </p> |
| 12 | 12 | |
| 13 | 13 | |
| 14 | 14 | <h2>Table Of Contents</h2> |
| @@ -67,11 +67,11 @@ | ||
| 67 | 67 | <ul> |
| 68 | 68 | <li> Typedefs. |
| 69 | 69 | <li> Structure, union and enumeration declarations. |
| 70 | 70 | <li> Function and procedure prototypes. |
| 71 | 71 | <li> Preprocessor macros and #defines. |
| 72 | -<li> ``extern'' variable declarations. | |
| 72 | +<li> “<code>extern</code>” variable declarations. | |
| 73 | 73 | </ul> |
| 74 | 74 | </p> |
| 75 | 75 | |
| 76 | 76 | <p> |
| 77 | 77 | Definitions in C, on the other hand, include these kinds of things: |
| @@ -89,13 +89,13 @@ | ||
| 89 | 89 | is the <em>interface</em> and the definition is the <em>implementation</em>. |
| 90 | 90 | </p> |
| 91 | 91 | |
| 92 | 92 | <p> |
| 93 | 93 | In C programs, it has always been the tradition that declarations are |
| 94 | -put in files with the ``<code>.h</code>'' suffix and definitions are | |
| 95 | -placed in ``<code>.c</code>'' files. | |
| 96 | -The .c files contain ``<code>#include</code>'' preprocessor statements | |
| 94 | +put in files with the “<code>.h</code>” suffix and definitions are | |
| 95 | +placed in “<code>.c</code>” files. | |
| 96 | +The .c files contain “<code>#include</code>” preprocessor statements | |
| 97 | 97 | that cause the contents of .h files to be included as part of the |
| 98 | 98 | source code when the .c file is compiled. |
| 99 | 99 | In this way, the .h files define the interface to a subsystem and |
| 100 | 100 | the .c files define how the subsystem is implemented. |
| 101 | 101 | </p> |
| @@ -262,11 +262,11 @@ | ||
| 262 | 262 | |
| 263 | 263 | <p> |
| 264 | 264 | A similar option is -H. Like the lower-case -h option, big -H |
| 265 | 265 | generates a single include file on standard output. But unlike |
| 266 | 266 | small -h, the big -H only emits prototypes and declarations that |
| 267 | -have been designated as ``exportable''. | |
| 267 | +have been designated as “exportable”. | |
| 268 | 268 | The idea is that -H will generate an include file that defines |
| 269 | 269 | the interface to a library. |
| 270 | 270 | More will be said about this in section 3.4. |
| 271 | 271 | </p> |
| 272 | 272 | |
| @@ -293,13 +293,13 @@ | ||
| 293 | 293 | then you can supply an empty header filename, like this: |
| 294 | 294 | <pre> |
| 295 | 295 | makeheaders alpha.c beta.c gamma.c: |
| 296 | 296 | </pre> |
| 297 | 297 | In this example, makeheaders will scan the three files named |
| 298 | -``alpha.c'', | |
| 299 | -``beta.c'' and | |
| 300 | -``gamma.c'' | |
| 298 | +“<code>alpha.c</code>”, | |
| 299 | +“<code>beta.c</code>” and | |
| 300 | +“<code>gamma.c</code>” | |
| 301 | 301 | but because of the colon on the end of third filename |
| 302 | 302 | it will only generate headers for the first two files. |
| 303 | 303 | Unfortunately, |
| 304 | 304 | it is not possible to get makeheaders to process any file whose |
| 305 | 305 | name contains a colon. |
| @@ -309,14 +309,14 @@ | ||
| 309 | 309 | In a large project, the length of the command line for makeheaders |
| 310 | 310 | can become very long. |
| 311 | 311 | If the operating system doesn't support long command lines |
| 312 | 312 | (example: DOS and Win32) you may not be able to list all of the |
| 313 | 313 | input files in the space available. |
| 314 | -In that case, you can use the ``-f'' option followed | |
| 314 | +In that case, you can use the “<code>-f</code>” option followed | |
| 315 | 315 | by the name of a file to cause makeheaders to read command line |
| 316 | 316 | options and filename from the file instead of from the command line. |
| 317 | -For example, you might prepare a file named ``mkhdr.dat'' | |
| 317 | +For example, you might prepare a file named “<code>mkhdr.dat</code>” | |
| 318 | 318 | that contains text like this: |
| 319 | 319 | <pre> |
| 320 | 320 | src/alpha.c:hdr/alpha.h |
| 321 | 321 | src/beta.c:hdr/beta.h |
| 322 | 322 | src/gamma.c:hdr/gamma.h |
| @@ -327,18 +327,18 @@ | ||
| 327 | 327 | makeheaders -f mkhdr.dat |
| 328 | 328 | </pre> |
| 329 | 329 | </p> |
| 330 | 330 | |
| 331 | 331 | <p> |
| 332 | -The ``-local'' option causes makeheaders to | |
| 333 | -generate of prototypes for ``static'' functions and | |
| 332 | +The “<code>-local</code>” option causes makeheaders to | |
| 333 | +generate of prototypes for “<code>static</code>” functions and | |
| 334 | 334 | procedures. |
| 335 | 335 | Such prototypes are normally omitted. |
| 336 | 336 | </p> |
| 337 | 337 | |
| 338 | 338 | <p> |
| 339 | -Finally, makeheaders also includes a ``-doc'' option. | |
| 339 | +Finally, makeheaders also includes a “<code>-doc</code>” option. | |
| 340 | 340 | This command line option prevents makeheaders from generating any |
| 341 | 341 | headers at all. |
| 342 | 342 | Instead, makeheaders will write to standard output |
| 343 | 343 | information about every definition and declaration that it encounters |
| 344 | 344 | in its scan of source files. |
| @@ -352,19 +352,21 @@ | ||
| 352 | 352 | </p> |
| 353 | 353 | |
| 354 | 354 | <p> |
| 355 | 355 | If you forget what command line options are available, or forget |
| 356 | 356 | their exact name, you can invoke makeheaders using an unknown |
| 357 | -command line option (like ``--help'' or ``-?'') | |
| 357 | +command line option (like “<code>--help</code>” or | |
| 358 | +“<code>-?</code>”) | |
| 358 | 359 | and it will print a summary of the available options on standard |
| 359 | 360 | error. |
| 360 | -If you need to process a file whose name begins with ``-'', | |
| 361 | -you can prepend a ``./'' to its name in order to get it | |
| 361 | +If you need to process a file whose name begins with | |
| 362 | +“<code>-</code>”, | |
| 363 | +you can prepend a “<code>./</code>” to its name in order to get it | |
| 362 | 364 | accepted by the command line parser. |
| 363 | -Or, you can insert the special option ``--'' on the command | |
| 364 | -line to cause all subsequent command line arguments to be treated as | |
| 365 | -filenames even if their names beginn with ``-''. | |
| 365 | +Or, you can insert the special option “<code>--</code>” on the | |
| 366 | +command line to cause all subsequent command line arguments to be treated as | |
| 367 | +filenames even if their names begin with “<code>-</code>”. | |
| 366 | 368 | </p> |
| 367 | 369 | |
| 368 | 370 | <a name="H0006"></a> |
| 369 | 371 | <h2>3.0 Preparing Source Files For Use With Makeheaders</h2> |
| 370 | 372 | |
| @@ -379,30 +381,31 @@ | ||
| 379 | 381 | |
| 380 | 382 | <a name="H0007"></a> |
| 381 | 383 | <h3>3.1 The Basic Setup</h3> |
| 382 | 384 | |
| 383 | 385 | <p> |
| 384 | -The simpliest way to use makeheaders is to put all definitions in | |
| 386 | +The simplest way to use makeheaders is to put all definitions in | |
| 385 | 387 | one or more .c files and all structure and type declarations in |
| 386 | 388 | separate .h files. |
| 387 | 389 | The only restriction is that you should take care to chose basenames |
| 388 | -for your .h files that are different from the basenames for you | |
| 390 | +for your .h files that are different from the basenames for your | |
| 389 | 391 | .c files. |
| 390 | -Recall that if your .c file is named (for example) ``alpha.c'' | |
| 392 | +Recall that if your .c file is named (for example) | |
| 393 | +“<code>alpha.c</code>” | |
| 391 | 394 | makeheaders will attempt to generate a corresponding header file |
| 392 | -named ``alpha.h''. | |
| 395 | +named “<code>alpha.h</code>”. | |
| 393 | 396 | For that reason, you don't want to use that name for |
| 394 | 397 | any of the .h files you write since that will prevent makeheaders |
| 395 | 398 | from generating the .h file automatically. |
| 396 | 399 | </p> |
| 397 | 400 | |
| 398 | 401 | <p> |
| 399 | 402 | The structure of a .c file intented for use with makeheaders is very |
| 400 | 403 | simple. |
| 401 | -All you have to do is add a single ``#include'' to the top | |
| 402 | -of the file that sources the header file that makeheaders will generate. | |
| 403 | -Hence, the beginning of a source file named ``alpha.c'' | |
| 404 | +All you have to do is add a single “<code>#include</code>” to the | |
| 405 | +top of the file that sources the header file that makeheaders will generate. | |
| 406 | +Hence, the beginning of a source file named “<code>alpha.c</code>” | |
| 404 | 407 | might look something like this: |
| 405 | 408 | </p> |
| 406 | 409 | |
| 407 | 410 | <pre> |
| 408 | 411 | /* |
| @@ -415,14 +418,14 @@ | ||
| 415 | 418 | |
| 416 | 419 | <p> |
| 417 | 420 | Your manually generated header files require no special attention at all. |
| 418 | 421 | Code them as you normally would. |
| 419 | 422 | However, makeheaders will work better if you omit the |
| 420 | -``#if'' statements people often put around the outside of | |
| 423 | +“<code>#if</code>” statements people often put around the outside of | |
| 421 | 424 | header files that prevent the files from being included more than once. |
| 422 | -For example, to create a header file named ``beta.h'', many | |
| 423 | -people will habitually write the following: | |
| 425 | +For example, to create a header file named “<code>beta.h</code>”, | |
| 426 | +many people will habitually write the following: | |
| 424 | 427 | |
| 425 | 428 | <pre> |
| 426 | 429 | #ifndef BETA_H |
| 427 | 430 | #define BETA_H |
| 428 | 431 | |
| @@ -435,11 +438,11 @@ | ||
| 435 | 438 | Remember that the header files you write will never really be |
| 436 | 439 | included by any C code. |
| 437 | 440 | Instead, makeheaders will scan your header files to extract only |
| 438 | 441 | those declarations that are needed by individual .c files and then |
| 439 | 442 | copy those declarations to the .h files corresponding to the .c files. |
| 440 | -Hence, the ``#if'' wrapper serves no useful purpose. | |
| 443 | +Hence, the “<code>#if</code>” wrapper serves no useful purpose. | |
| 441 | 444 | But it does make makeheaders work harder, forcing it to put |
| 442 | 445 | the statements |
| 443 | 446 | |
| 444 | 447 | <pre> |
| 445 | 448 | #if !defined(BETA_H) |
| @@ -465,11 +468,11 @@ | ||
| 465 | 468 | </p> |
| 466 | 469 | |
| 467 | 470 | <p> |
| 468 | 471 | Note that |
| 469 | 472 | the wildcard expression used in the above example, |
| 470 | -``<code>*.[ch]</code>'', | |
| 473 | +“<code>*.[ch]</code>”, | |
| 471 | 474 | will expand to include all .h files in the current directory, both |
| 472 | 475 | those entered manually be the programmer and others generated automatically |
| 473 | 476 | by a prior run of makeheaders. |
| 474 | 477 | But that is not a problem. |
| 475 | 478 | The makeheaders program will recognize and ignore any files it |
| @@ -489,14 +492,14 @@ | ||
| 489 | 492 | <p><li> |
| 490 | 493 | When a function is defined in any .c file, a prototype of that function |
| 491 | 494 | is placed in the generated .h file of every .c file that |
| 492 | 495 | calls the function.</p> |
| 493 | 496 | |
| 494 | -<P>If the ``static'' keyword of C appears at the beginning | |
| 495 | -of the function definition, the prototype is suppressed. | |
| 496 | -If you use the ``LOCAL'' keyword where you would normally | |
| 497 | -say ``static'', then a prototype is generated, but it | |
| 497 | +<P>If the “<code>static</code>” keyword of C appears at the | |
| 498 | +beginning of the function definition, the prototype is suppressed. | |
| 499 | +If you use the “<code>LOCAL</code>” keyword where you would normally | |
| 500 | +say “<code>static</code>”, then a prototype is generated, but it | |
| 498 | 501 | will only appear in the single header file that corresponds to the |
| 499 | 502 | source file containing the function. For example, if the file |
| 500 | 503 | <code>alpha.c</code> contains the following: |
| 501 | 504 | <pre> |
| 502 | 505 | LOCAL int testFunc(void){ |
| @@ -509,24 +512,26 @@ | ||
| 509 | 512 | LOCAL int testFunc(void); |
| 510 | 513 | </pre> |
| 511 | 514 | However, no other generated header files will contain a prototype for |
| 512 | 515 | <code>testFunc()</code> since the function has only file scope.</p> |
| 513 | 516 | |
| 514 | -<p>When the ``LOCAL'' keyword is used, makeheaders will also | |
| 515 | -generate a #define for LOCAL, like this: | |
| 517 | +<p>When the “<code>LOCAL</code>” keyword is used, makeheaders will | |
| 518 | +also generate a #define for LOCAL, like this: | |
| 516 | 519 | <pre> |
| 517 | 520 | #define LOCAL static |
| 518 | 521 | </pre> |
| 519 | 522 | so that the C compiler will know what it means.</p> |
| 520 | 523 | |
| 521 | -<p>If you invoke makeheaders with a ``-local'' command-line | |
| 522 | -option, then it treats the ``static'' keyword like | |
| 523 | -``LOCAL'' and generates prototypes in the header file | |
| 524 | -that corresponds to the source file containing the function defintiion.</p> | |
| 524 | +<p>If you invoke makeheaders with a “<code>-local</code>” | |
| 525 | +command-line option, then it treats the “<code>static</code>” | |
| 526 | +keyword like “<code>LOCAL</code>” and generates prototypes in the | |
| 527 | +header file that corresponds to the source file containing the function | |
| 528 | +definition.</p> | |
| 525 | 529 | |
| 526 | 530 | <p><li> |
| 527 | -When a global variable is defined in a .c file, an ``extern'' | |
| 531 | +When a global variable is defined in a .c file, an | |
| 532 | +“<code>extern</code>” | |
| 528 | 533 | declaration of that variable is placed in the header of every |
| 529 | 534 | .c file that uses the variable. |
| 530 | 535 | </p> |
| 531 | 536 | |
| 532 | 537 | <p><li> |
| @@ -550,12 +555,12 @@ | ||
| 550 | 555 | |
| 551 | 556 | <p><li> |
| 552 | 557 | When a structure, union or enumeration declaration appears in a .h |
| 553 | 558 | file, makeheaders will automatically |
| 554 | 559 | generate a typedef that allows the declaration to be referenced without |
| 555 | -the ``struct'', ``union'' or ``enum'' | |
| 556 | -qualifier. | |
| 560 | +the “<code>struct</code>”, “<code>union</code>” or | |
| 561 | +“<code>enum</code>” qualifier. | |
| 557 | 562 | In other words, if makeheaders sees the code: |
| 558 | 563 | <pre> |
| 559 | 564 | struct Examp { /* ... */ }; |
| 560 | 565 | </pre> |
| 561 | 566 | it will automatically generate a corresponding typedef like this: |
| @@ -572,13 +577,13 @@ | ||
| 572 | 577 | </ul> |
| 573 | 578 | |
| 574 | 579 | <p> |
| 575 | 580 | As a final note, we observe that automatically generated declarations |
| 576 | 581 | are ordered as required by the ANSI-C programming language. |
| 577 | -If the declaration of some structure ``X'' requires a prior | |
| 578 | -declaration of another structure ``Y'', then Y will appear | |
| 579 | -first in the generated headers. | |
| 582 | +If the declaration of some structure “<code>X</code>” requires a | |
| 583 | +prior declaration of another structure “<code>Y</code>”, then Y will | |
| 584 | +appear first in the generated headers. | |
| 580 | 585 | </p> |
| 581 | 586 | |
| 582 | 587 | <a name="H0009"></a> |
| 583 | 588 | <h3>3.3 How To Avoid Having To Write Any Header Files</h3> |
| 584 | 589 | |
| @@ -611,18 +616,18 @@ | ||
| 611 | 616 | <pre> |
| 612 | 617 | #if INTERFACE |
| 613 | 618 | #endif |
| 614 | 619 | </pre> |
| 615 | 620 | Thus any structure definitions that appear after the |
| 616 | -``#if INTERFACE'' but before the corresponding | |
| 617 | -``#endif'' are eligable to be copied into the | |
| 621 | +“<code>#if INTERFACE</code>” but before the corresponding | |
| 622 | +“<code>#endif</code>” are eligable to be copied into the | |
| 618 | 623 | automatically generated |
| 619 | 624 | .h files of other .c files. |
| 620 | 625 | </p> |
| 621 | 626 | |
| 622 | 627 | <p> |
| 623 | -If you use the ``#if INTERFACE'' mechanism in a .c file, | |
| 628 | +If you use the “<code>#if INTERFACE</code>” mechanism in a .c file, | |
| 624 | 629 | then the generated header for that .c file will contain a line |
| 625 | 630 | like this: |
| 626 | 631 | <pre> |
| 627 | 632 | #define INTERFACE 0 |
| 628 | 633 | </pre> |
| @@ -637,15 +642,15 @@ | ||
| 637 | 642 | </p> |
| 638 | 643 | |
| 639 | 644 | <p> |
| 640 | 645 | Note that you don't have to use this approach exclusively. |
| 641 | 646 | You can put some declarations in .h files and others within the |
| 642 | -``#if INTERFACE'' regions of .c files. | |
| 647 | +“<code>#if INTERFACE</code>” regions of .c files. | |
| 643 | 648 | Makeheaders treats all declarations alike, no matter where they |
| 644 | 649 | come from. |
| 645 | 650 | You should also note that a single .c file can contain as many |
| 646 | -``#if INTERFACE'' regions as desired. | |
| 651 | +“<code>#if INTERFACE</code>” regions as desired. | |
| 647 | 652 | </p> |
| 648 | 653 | |
| 649 | 654 | <a name="H0010"></a> |
| 650 | 655 | <h3>3.4 Designating Declarations For Export</h3> |
| 651 | 656 | |
| @@ -664,11 +669,11 @@ | ||
| 664 | 669 | like this, but makeheaders does. |
| 665 | 670 | </p> |
| 666 | 671 | |
| 667 | 672 | <p> |
| 668 | 673 | Using makeheaders, it is possible to designate routines and data |
| 669 | -structures as being for ``export''. | |
| 674 | +structures as being for “<code>export</code>”. | |
| 670 | 675 | Exported objects are visible not only to other files within the |
| 671 | 676 | same library or subassembly but also to other |
| 672 | 677 | libraries and subassemblies in the larger program. |
| 673 | 678 | By default, makeheaders only makes objects visible to other members |
| 674 | 679 | of the same library. |
| @@ -690,14 +695,14 @@ | ||
| 690 | 695 | |
| 691 | 696 | <p> |
| 692 | 697 | But trouble quickly arises when we attempt to devise a mechanism for |
| 693 | 698 | telling makeheaders which prototypes it should export and which it should |
| 694 | 699 | keep local. |
| 695 | -The built-in ``static'' keyword of C works well for prohibiting | |
| 696 | -prototypes from leaving a single source file, but because C doesn't | |
| 700 | +The built-in “<code>static</code>” keyword of C works well for | |
| 701 | +prohibiting prototypes from leaving a single source file, but because C doesn't | |
| 697 | 702 | support a linkage hierarchy, there is nothing in the C language to help us. |
| 698 | -We'll have to invite our own keyword: ``EXPORT'' | |
| 703 | +We'll have to invite our own keyword: “<code>EXPORT</code>” | |
| 699 | 704 | </p> |
| 700 | 705 | |
| 701 | 706 | <p> |
| 702 | 707 | Makeheaders allows the EXPORT keyword to precede any function or |
| 703 | 708 | procedure definition. |
| @@ -726,15 +731,15 @@ | ||
| 726 | 731 | <pre> |
| 727 | 732 | #if EXPORT_INTERFACE |
| 728 | 733 | #endif |
| 729 | 734 | </pre> |
| 730 | 735 | will become part of the exported interface. |
| 731 | -The ``#if EXPORT_INTERFACE'' mechanism can be used in either | |
| 732 | -.c or .h files. | |
| 733 | -(The ``#if INTERFACE'' can also be used in both .h and .c files, | |
| 734 | -but since it's use in a .h file would be redundant, we haven't mentioned | |
| 735 | -it before.) | |
| 736 | +The “<code>#if EXPORT_INTERFACE</code>” mechanism can be used in | |
| 737 | +either .c or .h files. | |
| 738 | +(The “<code>#if INTERFACE</code>” can also be used in both .h and | |
| 739 | +.c files, but since it's use in a .h file would be redundant, we haven't | |
| 740 | +mentioned it before.) | |
| 736 | 741 | </p> |
| 737 | 742 | |
| 738 | 743 | <a name="H0011"></a> |
| 739 | 744 | <h3>3.5 Local declarations processed by makeheaders</h3> |
| 740 | 745 | |
| @@ -742,11 +747,11 @@ | ||
| 742 | 747 | Structure declarations and typedefs that appear in .c files are normally |
| 743 | 748 | ignored by makeheaders. |
| 744 | 749 | Such declarations are only intended for use by the source file in which |
| 745 | 750 | they appear and so makeheaders doesn't need to copy them into any |
| 746 | 751 | generated header files. |
| 747 | -We call such declarations ``private''. | |
| 752 | +We call such declarations “<code>private</code>”. | |
| 748 | 753 | </p> |
| 749 | 754 | |
| 750 | 755 | <p> |
| 751 | 756 | Sometimes it is convenient to have makeheaders sort a sequence |
| 752 | 757 | of private declarations into the correct order for us automatically. |
| @@ -764,12 +769,13 @@ | ||
| 764 | 769 | within |
| 765 | 770 | <pre> |
| 766 | 771 | #if LOCAL_INTERFACE |
| 767 | 772 | #endif |
| 768 | 773 | </pre> |
| 769 | -A ``LOCAL_INTERFACE'' block works very much like the | |
| 770 | -``INTERFACE'' and ``EXPORT_INTERFACE'' | |
| 774 | +A “<code>LOCAL_INTERFACE</code>” block works very much like the | |
| 775 | +“<code>INTERFACE</code>” and | |
| 776 | +“<code>EXPORT_INTERFACE</code>” | |
| 771 | 777 | blocks described above, except that makeheaders insures that the |
| 772 | 778 | objects declared in a LOCAL_INTERFACE are only visible to the |
| 773 | 779 | file containing the LOCAL_INTERFACE. |
| 774 | 780 | </p> |
| 775 | 781 | |
| @@ -777,11 +783,12 @@ | ||
| 777 | 783 | <h3>3.6 Using Makeheaders With C++ Code</h3> |
| 778 | 784 | |
| 779 | 785 | <p> |
| 780 | 786 | You can use makeheaders to generate header files for C++ code, in |
| 781 | 787 | addition to C. |
| 782 | -Makeheaders will recognize and copy both ``class'' declarations | |
| 788 | +Makeheaders will recognize and copy both “<code>class</code>” | |
| 789 | +declarations | |
| 783 | 790 | and inline function definitions, and it knows not to try to generate |
| 784 | 791 | prototypes for methods. |
| 785 | 792 | </p> |
| 786 | 793 | |
| 787 | 794 | <p> |
| @@ -805,20 +812,20 @@ | ||
| 805 | 812 | C++ input. Makeheaders will recognize that its source code is C++ |
| 806 | 813 | by the suffix on the source code filename. Simple ".c" or ".h" suffixes |
| 807 | 814 | are assumed to be ANSI-C. Anything else, including ".cc", ".C" and |
| 808 | 815 | ".cpp" is assumed to be C++. |
| 809 | 816 | The name of the header file generated by makeheaders is derived from |
| 810 | -by the name of the source file by converting every "c" to "h" and | |
| 817 | +the name of the source file by converting every "c" to "h" and | |
| 811 | 818 | every "C" to "H" in the suffix of the filename. |
| 812 | 819 | Thus the C++ source |
| 813 | -file ``alpha.cpp'' will induce makeheaders to | |
| 814 | -generate a header file named ``alpha.hpp''. | |
| 820 | +file “<code>alpha.cpp</code>” will induce makeheaders to | |
| 821 | +generate a header file named “<code>alpha.hpp</code>”. | |
| 815 | 822 | </p> |
| 816 | 823 | |
| 817 | 824 | <p> |
| 818 | 825 | Makeheaders augments class definitions by inserting prototypes to |
| 819 | -methods were appropriate. If a method definition begins with one | |
| 826 | +methods where appropriate. If a method definition begins with one | |
| 820 | 827 | of the special keywords <b>PUBLIC</b>, <b>PROTECTED</b>, or |
| 821 | 828 | <b>PRIVATE</b> (in upper-case to distinguish them from the regular |
| 822 | 829 | C++ keywords with the same meaning) then a prototype for that |
| 823 | 830 | method will be inserted into the class definition. If none of |
| 824 | 831 | these keywords appear, then the prototype is not inserted. For |
| @@ -867,11 +874,11 @@ | ||
| 867 | 874 | <h4>3.6.1 C++ Limitations</h4> |
| 868 | 875 | |
| 869 | 876 | <p> |
| 870 | 877 | Makeheaders does not understand more recent |
| 871 | 878 | C++ syntax such as templates and namespaces. |
| 872 | -Perhaps these issued will be addressed in future revisions. | |
| 879 | +Perhaps these issues will be addressed in future revisions. | |
| 873 | 880 | </p> |
| 874 | 881 | |
| 875 | 882 | <a name="H0013"></a> |
| 876 | 883 | <h3>3.7 Conditional Compilation</h3> |
| 877 | 884 | |
| @@ -879,13 +886,13 @@ | ||
| 879 | 886 | The makeheaders program understands and tracks the conditional |
| 880 | 887 | compilation constructs in the source code files it scans. |
| 881 | 888 | Hence, if the following code appears in a source file |
| 882 | 889 | <pre> |
| 883 | 890 | #ifdef UNIX |
| 884 | - # define WORKS_WELL 1 | |
| 891 | + # define WORKS_WELL 1 | |
| 885 | 892 | #else |
| 886 | - # define WORKS_WELL 0 | |
| 893 | + # define WORKS_WELL 0 | |
| 887 | 894 | #endif |
| 888 | 895 | </pre> |
| 889 | 896 | then the next patch of code will appear in the generated header for |
| 890 | 897 | every .c file that uses the WORKS_WELL constant: |
| 891 | 898 | <pre> |
| @@ -918,12 +925,12 @@ | ||
| 918 | 925 | <p> |
| 919 | 926 | Makeheaders does not understand the old K&R style of function |
| 920 | 927 | and procedure definitions. |
| 921 | 928 | It only understands the modern ANSI-C style, and will probably |
| 922 | 929 | become very confused if it encounters an old K&R function. |
| 923 | -You should take care to avoid putting K&R function defintions | |
| 924 | -in your code, therefore. | |
| 930 | +Therefore you should take care to avoid putting K&R function definitions | |
| 931 | +in your code. | |
| 925 | 932 | </p> |
| 926 | 933 | |
| 927 | 934 | <p> |
| 928 | 935 | Makeheaders does not understand when you define more than one |
| 929 | 936 | global variable with the same type separated by a comma. |
| @@ -993,35 +1000,35 @@ | ||
| 993 | 1000 | in the code, it is not necessary to make a corresponding change |
| 994 | 1001 | in a separate document. Just rerun the documentation generator. |
| 995 | 1002 | </ul> |
| 996 | 1003 | The makeheaders program does not generate program documentation itself. |
| 997 | 1004 | But you can use makeheaders to parse the program source code, extract |
| 998 | -the information that is relavant to the documentation and to pass this | |
| 1005 | +the information that is relevant to the documentation and to pass this | |
| 999 | 1006 | information to another tool to do the actual documentation preparation. |
| 1000 | 1007 | </p> |
| 1001 | 1008 | |
| 1002 | 1009 | <p> |
| 1003 | -When makeheaders is run with the ``-doc'' option, it emits | |
| 1004 | -no header files at all. | |
| 1010 | +When makeheaders is run with the “<code>-doc</code>” option, it | |
| 1011 | +emits no header files at all. | |
| 1005 | 1012 | Instead, it does a complete dump of its internal tables to standard |
| 1006 | -outputs in a form that is easily parsed. | |
| 1013 | +output in a form that is easily parsed. | |
| 1007 | 1014 | This output can then be used by another program (the implementation |
| 1008 | 1015 | of which is left as an exercise to the reader) that will use the |
| 1009 | 1016 | information to prepare suitable documentation. |
| 1010 | 1017 | </p> |
| 1011 | 1018 | |
| 1012 | 1019 | <p> |
| 1013 | -The ``-doc'' option causes makeheaders to print information | |
| 1014 | -to standard output about all of the following objects: | |
| 1020 | +The “<code>-doc</code>” option causes makeheaders to print | |
| 1021 | +information to standard output about all of the following objects: | |
| 1015 | 1022 | <ul> |
| 1016 | -<li> C++ Class declarations | |
| 1023 | +<li> C++ class declarations | |
| 1017 | 1024 | <li> Structure and union declarations |
| 1018 | 1025 | <li> Enumerations |
| 1019 | 1026 | <li> Typedefs |
| 1020 | 1027 | <li> Procedure and function definitions |
| 1021 | 1028 | <li> Global variables |
| 1022 | -<li> Preprocessor macros (ex: ``#define'') | |
| 1029 | +<li> Preprocessor macros (ex: “<code>#define</code>”) | |
| 1023 | 1030 | </ul> |
| 1024 | 1031 | For each of these objects, the following information is output: |
| 1025 | 1032 | <ul> |
| 1026 | 1033 | <li> The name of the object. |
| 1027 | 1034 | <li> The type of the object. (Structure, typedef, macro, etc.) |
| @@ -1029,11 +1036,12 @@ | ||
| 1029 | 1036 | an EXPORT_INTERFACE block) or local (contained with LOCAL_INTERFACE). |
| 1030 | 1037 | <li> A flag to indicate if the object is declared in a C++ file. |
| 1031 | 1038 | <li> The name of the file in which the object was declared. |
| 1032 | 1039 | <li> The complete text of any block comment that preceeds the declarations. |
| 1033 | 1040 | <li> If the declaration occurred inside a preprocessor conditional |
| 1034 | - (``#if'') then the text of that conditional is provided. | |
| 1041 | + (“<code>#if</code>”) then the text of that conditional is | |
| 1042 | + provided. | |
| 1035 | 1043 | <li> The complete text of a declaration for the object. |
| 1036 | 1044 | </ul> |
| 1037 | 1045 | The exact output format will not be described here. |
| 1038 | 1046 | It is simple to understand and parse and should be obvious to |
| 1039 | 1047 | anyone who inspects some sample output. |
| @@ -1042,11 +1050,11 @@ | ||
| 1042 | 1050 | <a name="H0016"></a> |
| 1043 | 1051 | <h2>5.0 Compiling The Makeheaders Program</h2> |
| 1044 | 1052 | |
| 1045 | 1053 | <p> |
| 1046 | 1054 | The source code for makeheaders is a single file of ANSI-C code, |
| 1047 | -less than 3000 lines in length. | |
| 1055 | +approximately 3000 lines in length. | |
| 1048 | 1056 | The program makes only modest demands of the system and C library |
| 1049 | 1057 | and should compile without alteration on most ANSI C compilers |
| 1050 | 1058 | and on most operating systems. |
| 1051 | 1059 | It is known to compile using several variations of GCC for Unix |
| 1052 | 1060 | as well as Cygwin32 and MSVC 5.0 for Win32. |
| 1053 | 1061 |
| --- src/makeheaders.html | |
| +++ src/makeheaders.html | |
| @@ -4,11 +4,11 @@ | |
| 4 | <h1 align=center>The Makeheaders Program</h1> |
| 5 | |
| 6 | |
| 7 | <p> |
| 8 | This document describes <em>makeheaders</em>, |
| 9 | a tool that automatically generates ``<code>.h</code>'' |
| 10 | files for a C or C++ programming project. |
| 11 | </p> |
| 12 | |
| 13 | |
| 14 | <h2>Table Of Contents</h2> |
| @@ -67,11 +67,11 @@ | |
| 67 | <ul> |
| 68 | <li> Typedefs. |
| 69 | <li> Structure, union and enumeration declarations. |
| 70 | <li> Function and procedure prototypes. |
| 71 | <li> Preprocessor macros and #defines. |
| 72 | <li> ``extern'' variable declarations. |
| 73 | </ul> |
| 74 | </p> |
| 75 | |
| 76 | <p> |
| 77 | Definitions in C, on the other hand, include these kinds of things: |
| @@ -89,13 +89,13 @@ | |
| 89 | is the <em>interface</em> and the definition is the <em>implementation</em>. |
| 90 | </p> |
| 91 | |
| 92 | <p> |
| 93 | In C programs, it has always been the tradition that declarations are |
| 94 | put in files with the ``<code>.h</code>'' suffix and definitions are |
| 95 | placed in ``<code>.c</code>'' files. |
| 96 | The .c files contain ``<code>#include</code>'' preprocessor statements |
| 97 | that cause the contents of .h files to be included as part of the |
| 98 | source code when the .c file is compiled. |
| 99 | In this way, the .h files define the interface to a subsystem and |
| 100 | the .c files define how the subsystem is implemented. |
| 101 | </p> |
| @@ -262,11 +262,11 @@ | |
| 262 | |
| 263 | <p> |
| 264 | A similar option is -H. Like the lower-case -h option, big -H |
| 265 | generates a single include file on standard output. But unlike |
| 266 | small -h, the big -H only emits prototypes and declarations that |
| 267 | have been designated as ``exportable''. |
| 268 | The idea is that -H will generate an include file that defines |
| 269 | the interface to a library. |
| 270 | More will be said about this in section 3.4. |
| 271 | </p> |
| 272 | |
| @@ -293,13 +293,13 @@ | |
| 293 | then you can supply an empty header filename, like this: |
| 294 | <pre> |
| 295 | makeheaders alpha.c beta.c gamma.c: |
| 296 | </pre> |
| 297 | In this example, makeheaders will scan the three files named |
| 298 | ``alpha.c'', |
| 299 | ``beta.c'' and |
| 300 | ``gamma.c'' |
| 301 | but because of the colon on the end of third filename |
| 302 | it will only generate headers for the first two files. |
| 303 | Unfortunately, |
| 304 | it is not possible to get makeheaders to process any file whose |
| 305 | name contains a colon. |
| @@ -309,14 +309,14 @@ | |
| 309 | In a large project, the length of the command line for makeheaders |
| 310 | can become very long. |
| 311 | If the operating system doesn't support long command lines |
| 312 | (example: DOS and Win32) you may not be able to list all of the |
| 313 | input files in the space available. |
| 314 | In that case, you can use the ``-f'' option followed |
| 315 | by the name of a file to cause makeheaders to read command line |
| 316 | options and filename from the file instead of from the command line. |
| 317 | For example, you might prepare a file named ``mkhdr.dat'' |
| 318 | that contains text like this: |
| 319 | <pre> |
| 320 | src/alpha.c:hdr/alpha.h |
| 321 | src/beta.c:hdr/beta.h |
| 322 | src/gamma.c:hdr/gamma.h |
| @@ -327,18 +327,18 @@ | |
| 327 | makeheaders -f mkhdr.dat |
| 328 | </pre> |
| 329 | </p> |
| 330 | |
| 331 | <p> |
| 332 | The ``-local'' option causes makeheaders to |
| 333 | generate of prototypes for ``static'' functions and |
| 334 | procedures. |
| 335 | Such prototypes are normally omitted. |
| 336 | </p> |
| 337 | |
| 338 | <p> |
| 339 | Finally, makeheaders also includes a ``-doc'' option. |
| 340 | This command line option prevents makeheaders from generating any |
| 341 | headers at all. |
| 342 | Instead, makeheaders will write to standard output |
| 343 | information about every definition and declaration that it encounters |
| 344 | in its scan of source files. |
| @@ -352,19 +352,21 @@ | |
| 352 | </p> |
| 353 | |
| 354 | <p> |
| 355 | If you forget what command line options are available, or forget |
| 356 | their exact name, you can invoke makeheaders using an unknown |
| 357 | command line option (like ``--help'' or ``-?'') |
| 358 | and it will print a summary of the available options on standard |
| 359 | error. |
| 360 | If you need to process a file whose name begins with ``-'', |
| 361 | you can prepend a ``./'' to its name in order to get it |
| 362 | accepted by the command line parser. |
| 363 | Or, you can insert the special option ``--'' on the command |
| 364 | line to cause all subsequent command line arguments to be treated as |
| 365 | filenames even if their names beginn with ``-''. |
| 366 | </p> |
| 367 | |
| 368 | <a name="H0006"></a> |
| 369 | <h2>3.0 Preparing Source Files For Use With Makeheaders</h2> |
| 370 | |
| @@ -379,30 +381,31 @@ | |
| 379 | |
| 380 | <a name="H0007"></a> |
| 381 | <h3>3.1 The Basic Setup</h3> |
| 382 | |
| 383 | <p> |
| 384 | The simpliest way to use makeheaders is to put all definitions in |
| 385 | one or more .c files and all structure and type declarations in |
| 386 | separate .h files. |
| 387 | The only restriction is that you should take care to chose basenames |
| 388 | for your .h files that are different from the basenames for you |
| 389 | .c files. |
| 390 | Recall that if your .c file is named (for example) ``alpha.c'' |
| 391 | makeheaders will attempt to generate a corresponding header file |
| 392 | named ``alpha.h''. |
| 393 | For that reason, you don't want to use that name for |
| 394 | any of the .h files you write since that will prevent makeheaders |
| 395 | from generating the .h file automatically. |
| 396 | </p> |
| 397 | |
| 398 | <p> |
| 399 | The structure of a .c file intented for use with makeheaders is very |
| 400 | simple. |
| 401 | All you have to do is add a single ``#include'' to the top |
| 402 | of the file that sources the header file that makeheaders will generate. |
| 403 | Hence, the beginning of a source file named ``alpha.c'' |
| 404 | might look something like this: |
| 405 | </p> |
| 406 | |
| 407 | <pre> |
| 408 | /* |
| @@ -415,14 +418,14 @@ | |
| 415 | |
| 416 | <p> |
| 417 | Your manually generated header files require no special attention at all. |
| 418 | Code them as you normally would. |
| 419 | However, makeheaders will work better if you omit the |
| 420 | ``#if'' statements people often put around the outside of |
| 421 | header files that prevent the files from being included more than once. |
| 422 | For example, to create a header file named ``beta.h'', many |
| 423 | people will habitually write the following: |
| 424 | |
| 425 | <pre> |
| 426 | #ifndef BETA_H |
| 427 | #define BETA_H |
| 428 | |
| @@ -435,11 +438,11 @@ | |
| 435 | Remember that the header files you write will never really be |
| 436 | included by any C code. |
| 437 | Instead, makeheaders will scan your header files to extract only |
| 438 | those declarations that are needed by individual .c files and then |
| 439 | copy those declarations to the .h files corresponding to the .c files. |
| 440 | Hence, the ``#if'' wrapper serves no useful purpose. |
| 441 | But it does make makeheaders work harder, forcing it to put |
| 442 | the statements |
| 443 | |
| 444 | <pre> |
| 445 | #if !defined(BETA_H) |
| @@ -465,11 +468,11 @@ | |
| 465 | </p> |
| 466 | |
| 467 | <p> |
| 468 | Note that |
| 469 | the wildcard expression used in the above example, |
| 470 | ``<code>*.[ch]</code>'', |
| 471 | will expand to include all .h files in the current directory, both |
| 472 | those entered manually be the programmer and others generated automatically |
| 473 | by a prior run of makeheaders. |
| 474 | But that is not a problem. |
| 475 | The makeheaders program will recognize and ignore any files it |
| @@ -489,14 +492,14 @@ | |
| 489 | <p><li> |
| 490 | When a function is defined in any .c file, a prototype of that function |
| 491 | is placed in the generated .h file of every .c file that |
| 492 | calls the function.</p> |
| 493 | |
| 494 | <P>If the ``static'' keyword of C appears at the beginning |
| 495 | of the function definition, the prototype is suppressed. |
| 496 | If you use the ``LOCAL'' keyword where you would normally |
| 497 | say ``static'', then a prototype is generated, but it |
| 498 | will only appear in the single header file that corresponds to the |
| 499 | source file containing the function. For example, if the file |
| 500 | <code>alpha.c</code> contains the following: |
| 501 | <pre> |
| 502 | LOCAL int testFunc(void){ |
| @@ -509,24 +512,26 @@ | |
| 509 | LOCAL int testFunc(void); |
| 510 | </pre> |
| 511 | However, no other generated header files will contain a prototype for |
| 512 | <code>testFunc()</code> since the function has only file scope.</p> |
| 513 | |
| 514 | <p>When the ``LOCAL'' keyword is used, makeheaders will also |
| 515 | generate a #define for LOCAL, like this: |
| 516 | <pre> |
| 517 | #define LOCAL static |
| 518 | </pre> |
| 519 | so that the C compiler will know what it means.</p> |
| 520 | |
| 521 | <p>If you invoke makeheaders with a ``-local'' command-line |
| 522 | option, then it treats the ``static'' keyword like |
| 523 | ``LOCAL'' and generates prototypes in the header file |
| 524 | that corresponds to the source file containing the function defintiion.</p> |
| 525 | |
| 526 | <p><li> |
| 527 | When a global variable is defined in a .c file, an ``extern'' |
| 528 | declaration of that variable is placed in the header of every |
| 529 | .c file that uses the variable. |
| 530 | </p> |
| 531 | |
| 532 | <p><li> |
| @@ -550,12 +555,12 @@ | |
| 550 | |
| 551 | <p><li> |
| 552 | When a structure, union or enumeration declaration appears in a .h |
| 553 | file, makeheaders will automatically |
| 554 | generate a typedef that allows the declaration to be referenced without |
| 555 | the ``struct'', ``union'' or ``enum'' |
| 556 | qualifier. |
| 557 | In other words, if makeheaders sees the code: |
| 558 | <pre> |
| 559 | struct Examp { /* ... */ }; |
| 560 | </pre> |
| 561 | it will automatically generate a corresponding typedef like this: |
| @@ -572,13 +577,13 @@ | |
| 572 | </ul> |
| 573 | |
| 574 | <p> |
| 575 | As a final note, we observe that automatically generated declarations |
| 576 | are ordered as required by the ANSI-C programming language. |
| 577 | If the declaration of some structure ``X'' requires a prior |
| 578 | declaration of another structure ``Y'', then Y will appear |
| 579 | first in the generated headers. |
| 580 | </p> |
| 581 | |
| 582 | <a name="H0009"></a> |
| 583 | <h3>3.3 How To Avoid Having To Write Any Header Files</h3> |
| 584 | |
| @@ -611,18 +616,18 @@ | |
| 611 | <pre> |
| 612 | #if INTERFACE |
| 613 | #endif |
| 614 | </pre> |
| 615 | Thus any structure definitions that appear after the |
| 616 | ``#if INTERFACE'' but before the corresponding |
| 617 | ``#endif'' are eligable to be copied into the |
| 618 | automatically generated |
| 619 | .h files of other .c files. |
| 620 | </p> |
| 621 | |
| 622 | <p> |
| 623 | If you use the ``#if INTERFACE'' mechanism in a .c file, |
| 624 | then the generated header for that .c file will contain a line |
| 625 | like this: |
| 626 | <pre> |
| 627 | #define INTERFACE 0 |
| 628 | </pre> |
| @@ -637,15 +642,15 @@ | |
| 637 | </p> |
| 638 | |
| 639 | <p> |
| 640 | Note that you don't have to use this approach exclusively. |
| 641 | You can put some declarations in .h files and others within the |
| 642 | ``#if INTERFACE'' regions of .c files. |
| 643 | Makeheaders treats all declarations alike, no matter where they |
| 644 | come from. |
| 645 | You should also note that a single .c file can contain as many |
| 646 | ``#if INTERFACE'' regions as desired. |
| 647 | </p> |
| 648 | |
| 649 | <a name="H0010"></a> |
| 650 | <h3>3.4 Designating Declarations For Export</h3> |
| 651 | |
| @@ -664,11 +669,11 @@ | |
| 664 | like this, but makeheaders does. |
| 665 | </p> |
| 666 | |
| 667 | <p> |
| 668 | Using makeheaders, it is possible to designate routines and data |
| 669 | structures as being for ``export''. |
| 670 | Exported objects are visible not only to other files within the |
| 671 | same library or subassembly but also to other |
| 672 | libraries and subassemblies in the larger program. |
| 673 | By default, makeheaders only makes objects visible to other members |
| 674 | of the same library. |
| @@ -690,14 +695,14 @@ | |
| 690 | |
| 691 | <p> |
| 692 | But trouble quickly arises when we attempt to devise a mechanism for |
| 693 | telling makeheaders which prototypes it should export and which it should |
| 694 | keep local. |
| 695 | The built-in ``static'' keyword of C works well for prohibiting |
| 696 | prototypes from leaving a single source file, but because C doesn't |
| 697 | support a linkage hierarchy, there is nothing in the C language to help us. |
| 698 | We'll have to invite our own keyword: ``EXPORT'' |
| 699 | </p> |
| 700 | |
| 701 | <p> |
| 702 | Makeheaders allows the EXPORT keyword to precede any function or |
| 703 | procedure definition. |
| @@ -726,15 +731,15 @@ | |
| 726 | <pre> |
| 727 | #if EXPORT_INTERFACE |
| 728 | #endif |
| 729 | </pre> |
| 730 | will become part of the exported interface. |
| 731 | The ``#if EXPORT_INTERFACE'' mechanism can be used in either |
| 732 | .c or .h files. |
| 733 | (The ``#if INTERFACE'' can also be used in both .h and .c files, |
| 734 | but since it's use in a .h file would be redundant, we haven't mentioned |
| 735 | it before.) |
| 736 | </p> |
| 737 | |
| 738 | <a name="H0011"></a> |
| 739 | <h3>3.5 Local declarations processed by makeheaders</h3> |
| 740 | |
| @@ -742,11 +747,11 @@ | |
| 742 | Structure declarations and typedefs that appear in .c files are normally |
| 743 | ignored by makeheaders. |
| 744 | Such declarations are only intended for use by the source file in which |
| 745 | they appear and so makeheaders doesn't need to copy them into any |
| 746 | generated header files. |
| 747 | We call such declarations ``private''. |
| 748 | </p> |
| 749 | |
| 750 | <p> |
| 751 | Sometimes it is convenient to have makeheaders sort a sequence |
| 752 | of private declarations into the correct order for us automatically. |
| @@ -764,12 +769,13 @@ | |
| 764 | within |
| 765 | <pre> |
| 766 | #if LOCAL_INTERFACE |
| 767 | #endif |
| 768 | </pre> |
| 769 | A ``LOCAL_INTERFACE'' block works very much like the |
| 770 | ``INTERFACE'' and ``EXPORT_INTERFACE'' |
| 771 | blocks described above, except that makeheaders insures that the |
| 772 | objects declared in a LOCAL_INTERFACE are only visible to the |
| 773 | file containing the LOCAL_INTERFACE. |
| 774 | </p> |
| 775 | |
| @@ -777,11 +783,12 @@ | |
| 777 | <h3>3.6 Using Makeheaders With C++ Code</h3> |
| 778 | |
| 779 | <p> |
| 780 | You can use makeheaders to generate header files for C++ code, in |
| 781 | addition to C. |
| 782 | Makeheaders will recognize and copy both ``class'' declarations |
| 783 | and inline function definitions, and it knows not to try to generate |
| 784 | prototypes for methods. |
| 785 | </p> |
| 786 | |
| 787 | <p> |
| @@ -805,20 +812,20 @@ | |
| 805 | C++ input. Makeheaders will recognize that its source code is C++ |
| 806 | by the suffix on the source code filename. Simple ".c" or ".h" suffixes |
| 807 | are assumed to be ANSI-C. Anything else, including ".cc", ".C" and |
| 808 | ".cpp" is assumed to be C++. |
| 809 | The name of the header file generated by makeheaders is derived from |
| 810 | by the name of the source file by converting every "c" to "h" and |
| 811 | every "C" to "H" in the suffix of the filename. |
| 812 | Thus the C++ source |
| 813 | file ``alpha.cpp'' will induce makeheaders to |
| 814 | generate a header file named ``alpha.hpp''. |
| 815 | </p> |
| 816 | |
| 817 | <p> |
| 818 | Makeheaders augments class definitions by inserting prototypes to |
| 819 | methods were appropriate. If a method definition begins with one |
| 820 | of the special keywords <b>PUBLIC</b>, <b>PROTECTED</b>, or |
| 821 | <b>PRIVATE</b> (in upper-case to distinguish them from the regular |
| 822 | C++ keywords with the same meaning) then a prototype for that |
| 823 | method will be inserted into the class definition. If none of |
| 824 | these keywords appear, then the prototype is not inserted. For |
| @@ -867,11 +874,11 @@ | |
| 867 | <h4>3.6.1 C++ Limitations</h4> |
| 868 | |
| 869 | <p> |
| 870 | Makeheaders does not understand more recent |
| 871 | C++ syntax such as templates and namespaces. |
| 872 | Perhaps these issued will be addressed in future revisions. |
| 873 | </p> |
| 874 | |
| 875 | <a name="H0013"></a> |
| 876 | <h3>3.7 Conditional Compilation</h3> |
| 877 | |
| @@ -879,13 +886,13 @@ | |
| 879 | The makeheaders program understands and tracks the conditional |
| 880 | compilation constructs in the source code files it scans. |
| 881 | Hence, if the following code appears in a source file |
| 882 | <pre> |
| 883 | #ifdef UNIX |
| 884 | # define WORKS_WELL 1 |
| 885 | #else |
| 886 | # define WORKS_WELL 0 |
| 887 | #endif |
| 888 | </pre> |
| 889 | then the next patch of code will appear in the generated header for |
| 890 | every .c file that uses the WORKS_WELL constant: |
| 891 | <pre> |
| @@ -918,12 +925,12 @@ | |
| 918 | <p> |
| 919 | Makeheaders does not understand the old K&R style of function |
| 920 | and procedure definitions. |
| 921 | It only understands the modern ANSI-C style, and will probably |
| 922 | become very confused if it encounters an old K&R function. |
| 923 | You should take care to avoid putting K&R function defintions |
| 924 | in your code, therefore. |
| 925 | </p> |
| 926 | |
| 927 | <p> |
| 928 | Makeheaders does not understand when you define more than one |
| 929 | global variable with the same type separated by a comma. |
| @@ -993,35 +1000,35 @@ | |
| 993 | in the code, it is not necessary to make a corresponding change |
| 994 | in a separate document. Just rerun the documentation generator. |
| 995 | </ul> |
| 996 | The makeheaders program does not generate program documentation itself. |
| 997 | But you can use makeheaders to parse the program source code, extract |
| 998 | the information that is relavant to the documentation and to pass this |
| 999 | information to another tool to do the actual documentation preparation. |
| 1000 | </p> |
| 1001 | |
| 1002 | <p> |
| 1003 | When makeheaders is run with the ``-doc'' option, it emits |
| 1004 | no header files at all. |
| 1005 | Instead, it does a complete dump of its internal tables to standard |
| 1006 | outputs in a form that is easily parsed. |
| 1007 | This output can then be used by another program (the implementation |
| 1008 | of which is left as an exercise to the reader) that will use the |
| 1009 | information to prepare suitable documentation. |
| 1010 | </p> |
| 1011 | |
| 1012 | <p> |
| 1013 | The ``-doc'' option causes makeheaders to print information |
| 1014 | to standard output about all of the following objects: |
| 1015 | <ul> |
| 1016 | <li> C++ Class declarations |
| 1017 | <li> Structure and union declarations |
| 1018 | <li> Enumerations |
| 1019 | <li> Typedefs |
| 1020 | <li> Procedure and function definitions |
| 1021 | <li> Global variables |
| 1022 | <li> Preprocessor macros (ex: ``#define'') |
| 1023 | </ul> |
| 1024 | For each of these objects, the following information is output: |
| 1025 | <ul> |
| 1026 | <li> The name of the object. |
| 1027 | <li> The type of the object. (Structure, typedef, macro, etc.) |
| @@ -1029,11 +1036,12 @@ | |
| 1029 | an EXPORT_INTERFACE block) or local (contained with LOCAL_INTERFACE). |
| 1030 | <li> A flag to indicate if the object is declared in a C++ file. |
| 1031 | <li> The name of the file in which the object was declared. |
| 1032 | <li> The complete text of any block comment that preceeds the declarations. |
| 1033 | <li> If the declaration occurred inside a preprocessor conditional |
| 1034 | (``#if'') then the text of that conditional is provided. |
| 1035 | <li> The complete text of a declaration for the object. |
| 1036 | </ul> |
| 1037 | The exact output format will not be described here. |
| 1038 | It is simple to understand and parse and should be obvious to |
| 1039 | anyone who inspects some sample output. |
| @@ -1042,11 +1050,11 @@ | |
| 1042 | <a name="H0016"></a> |
| 1043 | <h2>5.0 Compiling The Makeheaders Program</h2> |
| 1044 | |
| 1045 | <p> |
| 1046 | The source code for makeheaders is a single file of ANSI-C code, |
| 1047 | less than 3000 lines in length. |
| 1048 | The program makes only modest demands of the system and C library |
| 1049 | and should compile without alteration on most ANSI C compilers |
| 1050 | and on most operating systems. |
| 1051 | It is known to compile using several variations of GCC for Unix |
| 1052 | as well as Cygwin32 and MSVC 5.0 for Win32. |
| 1053 |
| --- src/makeheaders.html | |
| +++ src/makeheaders.html | |
| @@ -4,11 +4,11 @@ | |
| 4 | <h1 align=center>The Makeheaders Program</h1> |
| 5 | |
| 6 | |
| 7 | <p> |
| 8 | This document describes <em>makeheaders</em>, |
| 9 | a tool that automatically generates “<code>.h</code>” |
| 10 | files for a C or C++ programming project. |
| 11 | </p> |
| 12 | |
| 13 | |
| 14 | <h2>Table Of Contents</h2> |
| @@ -67,11 +67,11 @@ | |
| 67 | <ul> |
| 68 | <li> Typedefs. |
| 69 | <li> Structure, union and enumeration declarations. |
| 70 | <li> Function and procedure prototypes. |
| 71 | <li> Preprocessor macros and #defines. |
| 72 | <li> “<code>extern</code>” variable declarations. |
| 73 | </ul> |
| 74 | </p> |
| 75 | |
| 76 | <p> |
| 77 | Definitions in C, on the other hand, include these kinds of things: |
| @@ -89,13 +89,13 @@ | |
| 89 | is the <em>interface</em> and the definition is the <em>implementation</em>. |
| 90 | </p> |
| 91 | |
| 92 | <p> |
| 93 | In C programs, it has always been the tradition that declarations are |
| 94 | put in files with the “<code>.h</code>” suffix and definitions are |
| 95 | placed in “<code>.c</code>” files. |
| 96 | The .c files contain “<code>#include</code>” preprocessor statements |
| 97 | that cause the contents of .h files to be included as part of the |
| 98 | source code when the .c file is compiled. |
| 99 | In this way, the .h files define the interface to a subsystem and |
| 100 | the .c files define how the subsystem is implemented. |
| 101 | </p> |
| @@ -262,11 +262,11 @@ | |
| 262 | |
| 263 | <p> |
| 264 | A similar option is -H. Like the lower-case -h option, big -H |
| 265 | generates a single include file on standard output. But unlike |
| 266 | small -h, the big -H only emits prototypes and declarations that |
| 267 | have been designated as “exportable”. |
| 268 | The idea is that -H will generate an include file that defines |
| 269 | the interface to a library. |
| 270 | More will be said about this in section 3.4. |
| 271 | </p> |
| 272 | |
| @@ -293,13 +293,13 @@ | |
| 293 | then you can supply an empty header filename, like this: |
| 294 | <pre> |
| 295 | makeheaders alpha.c beta.c gamma.c: |
| 296 | </pre> |
| 297 | In this example, makeheaders will scan the three files named |
| 298 | “<code>alpha.c</code>”, |
| 299 | “<code>beta.c</code>” and |
| 300 | “<code>gamma.c</code>” |
| 301 | but because of the colon on the end of third filename |
| 302 | it will only generate headers for the first two files. |
| 303 | Unfortunately, |
| 304 | it is not possible to get makeheaders to process any file whose |
| 305 | name contains a colon. |
| @@ -309,14 +309,14 @@ | |
| 309 | In a large project, the length of the command line for makeheaders |
| 310 | can become very long. |
| 311 | If the operating system doesn't support long command lines |
| 312 | (example: DOS and Win32) you may not be able to list all of the |
| 313 | input files in the space available. |
| 314 | In that case, you can use the “<code>-f</code>” option followed |
| 315 | by the name of a file to cause makeheaders to read command line |
| 316 | options and filename from the file instead of from the command line. |
| 317 | For example, you might prepare a file named “<code>mkhdr.dat</code>” |
| 318 | that contains text like this: |
| 319 | <pre> |
| 320 | src/alpha.c:hdr/alpha.h |
| 321 | src/beta.c:hdr/beta.h |
| 322 | src/gamma.c:hdr/gamma.h |
| @@ -327,18 +327,18 @@ | |
| 327 | makeheaders -f mkhdr.dat |
| 328 | </pre> |
| 329 | </p> |
| 330 | |
| 331 | <p> |
| 332 | The “<code>-local</code>” option causes makeheaders to |
| 333 | generate of prototypes for “<code>static</code>” functions and |
| 334 | procedures. |
| 335 | Such prototypes are normally omitted. |
| 336 | </p> |
| 337 | |
| 338 | <p> |
| 339 | Finally, makeheaders also includes a “<code>-doc</code>” option. |
| 340 | This command line option prevents makeheaders from generating any |
| 341 | headers at all. |
| 342 | Instead, makeheaders will write to standard output |
| 343 | information about every definition and declaration that it encounters |
| 344 | in its scan of source files. |
| @@ -352,19 +352,21 @@ | |
| 352 | </p> |
| 353 | |
| 354 | <p> |
| 355 | If you forget what command line options are available, or forget |
| 356 | their exact name, you can invoke makeheaders using an unknown |
| 357 | command line option (like “<code>--help</code>” or |
| 358 | “<code>-?</code>”) |
| 359 | and it will print a summary of the available options on standard |
| 360 | error. |
| 361 | If you need to process a file whose name begins with |
| 362 | “<code>-</code>”, |
| 363 | you can prepend a “<code>./</code>” to its name in order to get it |
| 364 | accepted by the command line parser. |
| 365 | Or, you can insert the special option “<code>--</code>” on the |
| 366 | command line to cause all subsequent command line arguments to be treated as |
| 367 | filenames even if their names begin with “<code>-</code>”. |
| 368 | </p> |
| 369 | |
| 370 | <a name="H0006"></a> |
| 371 | <h2>3.0 Preparing Source Files For Use With Makeheaders</h2> |
| 372 | |
| @@ -379,30 +381,31 @@ | |
| 381 | |
| 382 | <a name="H0007"></a> |
| 383 | <h3>3.1 The Basic Setup</h3> |
| 384 | |
| 385 | <p> |
| 386 | The simplest way to use makeheaders is to put all definitions in |
| 387 | one or more .c files and all structure and type declarations in |
| 388 | separate .h files. |
| 389 | The only restriction is that you should take care to chose basenames |
| 390 | for your .h files that are different from the basenames for your |
| 391 | .c files. |
| 392 | Recall that if your .c file is named (for example) |
| 393 | “<code>alpha.c</code>” |
| 394 | makeheaders will attempt to generate a corresponding header file |
| 395 | named “<code>alpha.h</code>”. |
| 396 | For that reason, you don't want to use that name for |
| 397 | any of the .h files you write since that will prevent makeheaders |
| 398 | from generating the .h file automatically. |
| 399 | </p> |
| 400 | |
| 401 | <p> |
| 402 | The structure of a .c file intented for use with makeheaders is very |
| 403 | simple. |
| 404 | All you have to do is add a single “<code>#include</code>” to the |
| 405 | top of the file that sources the header file that makeheaders will generate. |
| 406 | Hence, the beginning of a source file named “<code>alpha.c</code>” |
| 407 | might look something like this: |
| 408 | </p> |
| 409 | |
| 410 | <pre> |
| 411 | /* |
| @@ -415,14 +418,14 @@ | |
| 418 | |
| 419 | <p> |
| 420 | Your manually generated header files require no special attention at all. |
| 421 | Code them as you normally would. |
| 422 | However, makeheaders will work better if you omit the |
| 423 | “<code>#if</code>” statements people often put around the outside of |
| 424 | header files that prevent the files from being included more than once. |
| 425 | For example, to create a header file named “<code>beta.h</code>”, |
| 426 | many people will habitually write the following: |
| 427 | |
| 428 | <pre> |
| 429 | #ifndef BETA_H |
| 430 | #define BETA_H |
| 431 | |
| @@ -435,11 +438,11 @@ | |
| 438 | Remember that the header files you write will never really be |
| 439 | included by any C code. |
| 440 | Instead, makeheaders will scan your header files to extract only |
| 441 | those declarations that are needed by individual .c files and then |
| 442 | copy those declarations to the .h files corresponding to the .c files. |
| 443 | Hence, the “<code>#if</code>” wrapper serves no useful purpose. |
| 444 | But it does make makeheaders work harder, forcing it to put |
| 445 | the statements |
| 446 | |
| 447 | <pre> |
| 448 | #if !defined(BETA_H) |
| @@ -465,11 +468,11 @@ | |
| 468 | </p> |
| 469 | |
| 470 | <p> |
| 471 | Note that |
| 472 | the wildcard expression used in the above example, |
| 473 | “<code>*.[ch]</code>”, |
| 474 | will expand to include all .h files in the current directory, both |
| 475 | those entered manually be the programmer and others generated automatically |
| 476 | by a prior run of makeheaders. |
| 477 | But that is not a problem. |
| 478 | The makeheaders program will recognize and ignore any files it |
| @@ -489,14 +492,14 @@ | |
| 492 | <p><li> |
| 493 | When a function is defined in any .c file, a prototype of that function |
| 494 | is placed in the generated .h file of every .c file that |
| 495 | calls the function.</p> |
| 496 | |
| 497 | <P>If the “<code>static</code>” keyword of C appears at the |
| 498 | beginning of the function definition, the prototype is suppressed. |
| 499 | If you use the “<code>LOCAL</code>” keyword where you would normally |
| 500 | say “<code>static</code>”, then a prototype is generated, but it |
| 501 | will only appear in the single header file that corresponds to the |
| 502 | source file containing the function. For example, if the file |
| 503 | <code>alpha.c</code> contains the following: |
| 504 | <pre> |
| 505 | LOCAL int testFunc(void){ |
| @@ -509,24 +512,26 @@ | |
| 512 | LOCAL int testFunc(void); |
| 513 | </pre> |
| 514 | However, no other generated header files will contain a prototype for |
| 515 | <code>testFunc()</code> since the function has only file scope.</p> |
| 516 | |
| 517 | <p>When the “<code>LOCAL</code>” keyword is used, makeheaders will |
| 518 | also generate a #define for LOCAL, like this: |
| 519 | <pre> |
| 520 | #define LOCAL static |
| 521 | </pre> |
| 522 | so that the C compiler will know what it means.</p> |
| 523 | |
| 524 | <p>If you invoke makeheaders with a “<code>-local</code>” |
| 525 | command-line option, then it treats the “<code>static</code>” |
| 526 | keyword like “<code>LOCAL</code>” and generates prototypes in the |
| 527 | header file that corresponds to the source file containing the function |
| 528 | definition.</p> |
| 529 | |
| 530 | <p><li> |
| 531 | When a global variable is defined in a .c file, an |
| 532 | “<code>extern</code>” |
| 533 | declaration of that variable is placed in the header of every |
| 534 | .c file that uses the variable. |
| 535 | </p> |
| 536 | |
| 537 | <p><li> |
| @@ -550,12 +555,12 @@ | |
| 555 | |
| 556 | <p><li> |
| 557 | When a structure, union or enumeration declaration appears in a .h |
| 558 | file, makeheaders will automatically |
| 559 | generate a typedef that allows the declaration to be referenced without |
| 560 | the “<code>struct</code>”, “<code>union</code>” or |
| 561 | “<code>enum</code>” qualifier. |
| 562 | In other words, if makeheaders sees the code: |
| 563 | <pre> |
| 564 | struct Examp { /* ... */ }; |
| 565 | </pre> |
| 566 | it will automatically generate a corresponding typedef like this: |
| @@ -572,13 +577,13 @@ | |
| 577 | </ul> |
| 578 | |
| 579 | <p> |
| 580 | As a final note, we observe that automatically generated declarations |
| 581 | are ordered as required by the ANSI-C programming language. |
| 582 | If the declaration of some structure “<code>X</code>” requires a |
| 583 | prior declaration of another structure “<code>Y</code>”, then Y will |
| 584 | appear first in the generated headers. |
| 585 | </p> |
| 586 | |
| 587 | <a name="H0009"></a> |
| 588 | <h3>3.3 How To Avoid Having To Write Any Header Files</h3> |
| 589 | |
| @@ -611,18 +616,18 @@ | |
| 616 | <pre> |
| 617 | #if INTERFACE |
| 618 | #endif |
| 619 | </pre> |
| 620 | Thus any structure definitions that appear after the |
| 621 | “<code>#if INTERFACE</code>” but before the corresponding |
| 622 | “<code>#endif</code>” are eligable to be copied into the |
| 623 | automatically generated |
| 624 | .h files of other .c files. |
| 625 | </p> |
| 626 | |
| 627 | <p> |
| 628 | If you use the “<code>#if INTERFACE</code>” mechanism in a .c file, |
| 629 | then the generated header for that .c file will contain a line |
| 630 | like this: |
| 631 | <pre> |
| 632 | #define INTERFACE 0 |
| 633 | </pre> |
| @@ -637,15 +642,15 @@ | |
| 642 | </p> |
| 643 | |
| 644 | <p> |
| 645 | Note that you don't have to use this approach exclusively. |
| 646 | You can put some declarations in .h files and others within the |
| 647 | “<code>#if INTERFACE</code>” regions of .c files. |
| 648 | Makeheaders treats all declarations alike, no matter where they |
| 649 | come from. |
| 650 | You should also note that a single .c file can contain as many |
| 651 | “<code>#if INTERFACE</code>” regions as desired. |
| 652 | </p> |
| 653 | |
| 654 | <a name="H0010"></a> |
| 655 | <h3>3.4 Designating Declarations For Export</h3> |
| 656 | |
| @@ -664,11 +669,11 @@ | |
| 669 | like this, but makeheaders does. |
| 670 | </p> |
| 671 | |
| 672 | <p> |
| 673 | Using makeheaders, it is possible to designate routines and data |
| 674 | structures as being for “<code>export</code>”. |
| 675 | Exported objects are visible not only to other files within the |
| 676 | same library or subassembly but also to other |
| 677 | libraries and subassemblies in the larger program. |
| 678 | By default, makeheaders only makes objects visible to other members |
| 679 | of the same library. |
| @@ -690,14 +695,14 @@ | |
| 695 | |
| 696 | <p> |
| 697 | But trouble quickly arises when we attempt to devise a mechanism for |
| 698 | telling makeheaders which prototypes it should export and which it should |
| 699 | keep local. |
| 700 | The built-in “<code>static</code>” keyword of C works well for |
| 701 | prohibiting prototypes from leaving a single source file, but because C doesn't |
| 702 | support a linkage hierarchy, there is nothing in the C language to help us. |
| 703 | We'll have to invite our own keyword: “<code>EXPORT</code>” |
| 704 | </p> |
| 705 | |
| 706 | <p> |
| 707 | Makeheaders allows the EXPORT keyword to precede any function or |
| 708 | procedure definition. |
| @@ -726,15 +731,15 @@ | |
| 731 | <pre> |
| 732 | #if EXPORT_INTERFACE |
| 733 | #endif |
| 734 | </pre> |
| 735 | will become part of the exported interface. |
| 736 | The “<code>#if EXPORT_INTERFACE</code>” mechanism can be used in |
| 737 | either .c or .h files. |
| 738 | (The “<code>#if INTERFACE</code>” can also be used in both .h and |
| 739 | .c files, but since it's use in a .h file would be redundant, we haven't |
| 740 | mentioned it before.) |
| 741 | </p> |
| 742 | |
| 743 | <a name="H0011"></a> |
| 744 | <h3>3.5 Local declarations processed by makeheaders</h3> |
| 745 | |
| @@ -742,11 +747,11 @@ | |
| 747 | Structure declarations and typedefs that appear in .c files are normally |
| 748 | ignored by makeheaders. |
| 749 | Such declarations are only intended for use by the source file in which |
| 750 | they appear and so makeheaders doesn't need to copy them into any |
| 751 | generated header files. |
| 752 | We call such declarations “<code>private</code>”. |
| 753 | </p> |
| 754 | |
| 755 | <p> |
| 756 | Sometimes it is convenient to have makeheaders sort a sequence |
| 757 | of private declarations into the correct order for us automatically. |
| @@ -764,12 +769,13 @@ | |
| 769 | within |
| 770 | <pre> |
| 771 | #if LOCAL_INTERFACE |
| 772 | #endif |
| 773 | </pre> |
| 774 | A “<code>LOCAL_INTERFACE</code>” block works very much like the |
| 775 | “<code>INTERFACE</code>” and |
| 776 | “<code>EXPORT_INTERFACE</code>” |
| 777 | blocks described above, except that makeheaders insures that the |
| 778 | objects declared in a LOCAL_INTERFACE are only visible to the |
| 779 | file containing the LOCAL_INTERFACE. |
| 780 | </p> |
| 781 | |
| @@ -777,11 +783,12 @@ | |
| 783 | <h3>3.6 Using Makeheaders With C++ Code</h3> |
| 784 | |
| 785 | <p> |
| 786 | You can use makeheaders to generate header files for C++ code, in |
| 787 | addition to C. |
| 788 | Makeheaders will recognize and copy both “<code>class</code>” |
| 789 | declarations |
| 790 | and inline function definitions, and it knows not to try to generate |
| 791 | prototypes for methods. |
| 792 | </p> |
| 793 | |
| 794 | <p> |
| @@ -805,20 +812,20 @@ | |
| 812 | C++ input. Makeheaders will recognize that its source code is C++ |
| 813 | by the suffix on the source code filename. Simple ".c" or ".h" suffixes |
| 814 | are assumed to be ANSI-C. Anything else, including ".cc", ".C" and |
| 815 | ".cpp" is assumed to be C++. |
| 816 | The name of the header file generated by makeheaders is derived from |
| 817 | the name of the source file by converting every "c" to "h" and |
| 818 | every "C" to "H" in the suffix of the filename. |
| 819 | Thus the C++ source |
| 820 | file “<code>alpha.cpp</code>” will induce makeheaders to |
| 821 | generate a header file named “<code>alpha.hpp</code>”. |
| 822 | </p> |
| 823 | |
| 824 | <p> |
| 825 | Makeheaders augments class definitions by inserting prototypes to |
| 826 | methods where appropriate. If a method definition begins with one |
| 827 | of the special keywords <b>PUBLIC</b>, <b>PROTECTED</b>, or |
| 828 | <b>PRIVATE</b> (in upper-case to distinguish them from the regular |
| 829 | C++ keywords with the same meaning) then a prototype for that |
| 830 | method will be inserted into the class definition. If none of |
| 831 | these keywords appear, then the prototype is not inserted. For |
| @@ -867,11 +874,11 @@ | |
| 874 | <h4>3.6.1 C++ Limitations</h4> |
| 875 | |
| 876 | <p> |
| 877 | Makeheaders does not understand more recent |
| 878 | C++ syntax such as templates and namespaces. |
| 879 | Perhaps these issues will be addressed in future revisions. |
| 880 | </p> |
| 881 | |
| 882 | <a name="H0013"></a> |
| 883 | <h3>3.7 Conditional Compilation</h3> |
| 884 | |
| @@ -879,13 +886,13 @@ | |
| 886 | The makeheaders program understands and tracks the conditional |
| 887 | compilation constructs in the source code files it scans. |
| 888 | Hence, if the following code appears in a source file |
| 889 | <pre> |
| 890 | #ifdef UNIX |
| 891 | # define WORKS_WELL 1 |
| 892 | #else |
| 893 | # define WORKS_WELL 0 |
| 894 | #endif |
| 895 | </pre> |
| 896 | then the next patch of code will appear in the generated header for |
| 897 | every .c file that uses the WORKS_WELL constant: |
| 898 | <pre> |
| @@ -918,12 +925,12 @@ | |
| 925 | <p> |
| 926 | Makeheaders does not understand the old K&R style of function |
| 927 | and procedure definitions. |
| 928 | It only understands the modern ANSI-C style, and will probably |
| 929 | become very confused if it encounters an old K&R function. |
| 930 | Therefore you should take care to avoid putting K&R function definitions |
| 931 | in your code. |
| 932 | </p> |
| 933 | |
| 934 | <p> |
| 935 | Makeheaders does not understand when you define more than one |
| 936 | global variable with the same type separated by a comma. |
| @@ -993,35 +1000,35 @@ | |
| 1000 | in the code, it is not necessary to make a corresponding change |
| 1001 | in a separate document. Just rerun the documentation generator. |
| 1002 | </ul> |
| 1003 | The makeheaders program does not generate program documentation itself. |
| 1004 | But you can use makeheaders to parse the program source code, extract |
| 1005 | the information that is relevant to the documentation and to pass this |
| 1006 | information to another tool to do the actual documentation preparation. |
| 1007 | </p> |
| 1008 | |
| 1009 | <p> |
| 1010 | When makeheaders is run with the “<code>-doc</code>” option, it |
| 1011 | emits no header files at all. |
| 1012 | Instead, it does a complete dump of its internal tables to standard |
| 1013 | output in a form that is easily parsed. |
| 1014 | This output can then be used by another program (the implementation |
| 1015 | of which is left as an exercise to the reader) that will use the |
| 1016 | information to prepare suitable documentation. |
| 1017 | </p> |
| 1018 | |
| 1019 | <p> |
| 1020 | The “<code>-doc</code>” option causes makeheaders to print |
| 1021 | information to standard output about all of the following objects: |
| 1022 | <ul> |
| 1023 | <li> C++ class declarations |
| 1024 | <li> Structure and union declarations |
| 1025 | <li> Enumerations |
| 1026 | <li> Typedefs |
| 1027 | <li> Procedure and function definitions |
| 1028 | <li> Global variables |
| 1029 | <li> Preprocessor macros (ex: “<code>#define</code>”) |
| 1030 | </ul> |
| 1031 | For each of these objects, the following information is output: |
| 1032 | <ul> |
| 1033 | <li> The name of the object. |
| 1034 | <li> The type of the object. (Structure, typedef, macro, etc.) |
| @@ -1029,11 +1036,12 @@ | |
| 1036 | an EXPORT_INTERFACE block) or local (contained with LOCAL_INTERFACE). |
| 1037 | <li> A flag to indicate if the object is declared in a C++ file. |
| 1038 | <li> The name of the file in which the object was declared. |
| 1039 | <li> The complete text of any block comment that preceeds the declarations. |
| 1040 | <li> If the declaration occurred inside a preprocessor conditional |
| 1041 | (“<code>#if</code>”) then the text of that conditional is |
| 1042 | provided. |
| 1043 | <li> The complete text of a declaration for the object. |
| 1044 | </ul> |
| 1045 | The exact output format will not be described here. |
| 1046 | It is simple to understand and parse and should be obvious to |
| 1047 | anyone who inspects some sample output. |
| @@ -1042,11 +1050,11 @@ | |
| 1050 | <a name="H0016"></a> |
| 1051 | <h2>5.0 Compiling The Makeheaders Program</h2> |
| 1052 | |
| 1053 | <p> |
| 1054 | The source code for makeheaders is a single file of ANSI-C code, |
| 1055 | approximately 3000 lines in length. |
| 1056 | The program makes only modest demands of the system and C library |
| 1057 | and should compile without alteration on most ANSI C compilers |
| 1058 | and on most operating systems. |
| 1059 | It is known to compile using several variations of GCC for Unix |
| 1060 | as well as Cygwin32 and MSVC 5.0 for Win32. |
| 1061 |
+26
-24
| --- src/makemake.tcl | ||
| +++ src/makemake.tcl | ||
| @@ -255,10 +255,11 @@ | ||
| 255 | 255 | # to regenerate this file. |
| 256 | 256 | # |
| 257 | 257 | # This file is included by primary Makefile. |
| 258 | 258 | # |
| 259 | 259 | |
| 260 | +XBCC = $(BCC) $(BCCFLAGS) $(CFLAGS) | |
| 260 | 261 | XTCC = $(TCC) -I. -I$(SRCDIR) -I$(OBJDIR) $(TCCFLAGS) $(CFLAGS) |
| 261 | 262 | |
| 262 | 263 | } |
| 263 | 264 | writeln -nonewline "SRC =" |
| 264 | 265 | foreach s [lsort $src] { |
| @@ -298,26 +299,26 @@ | ||
| 298 | 299 | |
| 299 | 300 | $(OBJDIR): |
| 300 | 301 | -mkdir $(OBJDIR) |
| 301 | 302 | |
| 302 | 303 | $(OBJDIR)/translate: $(SRCDIR)/translate.c |
| 303 | - $(BCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c | |
| 304 | + $(XBCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c | |
| 304 | 305 | |
| 305 | 306 | $(OBJDIR)/makeheaders: $(SRCDIR)/makeheaders.c |
| 306 | - $(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c | |
| 307 | + $(XBCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c | |
| 307 | 308 | |
| 308 | 309 | $(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c |
| 309 | - $(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c | |
| 310 | + $(XBCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c | |
| 310 | 311 | |
| 311 | 312 | $(OBJDIR)/mkbuiltin: $(SRCDIR)/mkbuiltin.c |
| 312 | - $(BCC) -o $(OBJDIR)/mkbuiltin $(SRCDIR)/mkbuiltin.c | |
| 313 | + $(XBCC) -o $(OBJDIR)/mkbuiltin $(SRCDIR)/mkbuiltin.c | |
| 313 | 314 | |
| 314 | 315 | $(OBJDIR)/mkversion: $(SRCDIR)/mkversion.c |
| 315 | - $(BCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c | |
| 316 | + $(XBCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c | |
| 316 | 317 | |
| 317 | 318 | $(OBJDIR)/codecheck1: $(SRCDIR)/codecheck1.c |
| 318 | - $(BCC) -o $(OBJDIR)/codecheck1 $(SRCDIR)/codecheck1.c | |
| 319 | + $(XBCC) -o $(OBJDIR)/codecheck1 $(SRCDIR)/codecheck1.c | |
| 319 | 320 | |
| 320 | 321 | # Run the test suite. |
| 321 | 322 | # Other flags that can be included in TESTFLAGS are: |
| 322 | 323 | # |
| 323 | 324 | # -halt Stop testing after the first failed test |
| @@ -917,10 +918,11 @@ | ||
| 917 | 918 | -include config.w32 |
| 918 | 919 | |
| 919 | 920 | # STOP HERE |
| 920 | 921 | # You should not need to change anything below this line |
| 921 | 922 | #-------------------------------------------------------- |
| 923 | +XBCC = $(BCC) $(CFLAGS) | |
| 922 | 924 | XTCC = $(TCC) $(CFLAGS) -I. -I$(SRCDIR) |
| 923 | 925 | } |
| 924 | 926 | writeln -nonewline "SRC =" |
| 925 | 927 | foreach s [lsort $src] { |
| 926 | 928 | writeln -nonewline " \\\n \$(SRCDIR)/$s.c" |
| @@ -1013,26 +1015,26 @@ | ||
| 1013 | 1015 | else |
| 1014 | 1016 | $(MKDIR) $(OBJDIR) |
| 1015 | 1017 | endif |
| 1016 | 1018 | |
| 1017 | 1019 | $(TRANSLATE): $(SRCDIR)/translate.c |
| 1018 | - $(BCC) -o $@ $(SRCDIR)/translate.c | |
| 1020 | + $(XBCC) -o $@ $(SRCDIR)/translate.c | |
| 1019 | 1021 | |
| 1020 | 1022 | $(MAKEHEADERS): $(SRCDIR)/makeheaders.c |
| 1021 | - $(BCC) -o $@ $(SRCDIR)/makeheaders.c | |
| 1023 | + $(XBCC) -o $@ $(SRCDIR)/makeheaders.c | |
| 1022 | 1024 | |
| 1023 | 1025 | $(MKINDEX): $(SRCDIR)/mkindex.c |
| 1024 | - $(BCC) -o $@ $(SRCDIR)/mkindex.c | |
| 1026 | + $(XBCC) -o $@ $(SRCDIR)/mkindex.c | |
| 1025 | 1027 | |
| 1026 | 1028 | $(MKBUILTIN): $(SRCDIR)/mkbuiltin.c |
| 1027 | - $(BCC) -o $@ $(SRCDIR)/mkbuiltin.c | |
| 1029 | + $(XBCC) -o $@ $(SRCDIR)/mkbuiltin.c | |
| 1028 | 1030 | |
| 1029 | 1031 | $(MKVERSION): $(SRCDIR)/mkversion.c |
| 1030 | - $(BCC) -o $@ $(SRCDIR)/mkversion.c | |
| 1032 | + $(XBCC) -o $@ $(SRCDIR)/mkversion.c | |
| 1031 | 1033 | |
| 1032 | 1034 | $(CODECHECK1): $(SRCDIR)/codecheck1.c |
| 1033 | - $(BCC) -o $@ $(SRCDIR)/codecheck1.c | |
| 1035 | + $(XBCC) -o $@ $(SRCDIR)/codecheck1.c | |
| 1034 | 1036 | |
| 1035 | 1037 | # WARNING. DANGER. Running the test suite modifies the repository the |
| 1036 | 1038 | # build is done from, i.e. the checkout belongs to. Do not sync/push |
| 1037 | 1039 | # the repository after running the tests. |
| 1038 | 1040 | test: $(OBJDIR) $(APPNAME) |
| @@ -1305,26 +1307,26 @@ | ||
| 1305 | 1307 | writeln "\t+echo. >> \$@" |
| 1306 | 1308 | writeln "\t+echo fossil >> \$@" |
| 1307 | 1309 | |
| 1308 | 1310 | writeln { |
| 1309 | 1311 | translate$E: $(SRCDIR)\translate.c |
| 1310 | - $(BCC) -o$@ $** | |
| 1312 | + $(XBCC) -o$@ $** | |
| 1311 | 1313 | |
| 1312 | 1314 | makeheaders$E: $(SRCDIR)\makeheaders.c |
| 1313 | - $(BCC) -o$@ $** | |
| 1315 | + $(XBCC) -o$@ $** | |
| 1314 | 1316 | |
| 1315 | 1317 | mkindex$E: $(SRCDIR)\mkindex.c |
| 1316 | - $(BCC) -o$@ $** | |
| 1318 | + $(XBCC) -o$@ $** | |
| 1317 | 1319 | |
| 1318 | 1320 | mkbuiltin$E: $(SRCDIR)\mkbuiltin.c |
| 1319 | - $(BCC) -o$@ $** | |
| 1321 | + $(XBCC) -o$@ $** | |
| 1320 | 1322 | |
| 1321 | 1323 | mkversion$E: $(SRCDIR)\mkversion.c |
| 1322 | - $(BCC) -o$@ $** | |
| 1324 | + $(XBCC) -o$@ $** | |
| 1323 | 1325 | |
| 1324 | 1326 | codecheck1$E: $(SRCDIR)\codecheck1.c |
| 1325 | - $(BCC) -o$@ $** | |
| 1327 | + $(XBCC) -o$@ $** | |
| 1326 | 1328 | |
| 1327 | 1329 | $(OBJDIR)\shell$O : $(SRCDIR)\shell.c |
| 1328 | 1330 | $(TCC) -o$@ -c $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) $** |
| 1329 | 1331 | |
| 1330 | 1332 | $(OBJDIR)\sqlite3$O : $(SRCDIR)\sqlite3.c |
| @@ -1827,26 +1829,26 @@ | ||
| 1827 | 1829 | writeln { |
| 1828 | 1830 | $(OX): |
| 1829 | 1831 | @-mkdir $@ |
| 1830 | 1832 | |
| 1831 | 1833 | translate$E: $(SRCDIR)\translate.c |
| 1832 | - $(BCC) $** | |
| 1834 | + $(XBCC) $** | |
| 1833 | 1835 | |
| 1834 | 1836 | makeheaders$E: $(SRCDIR)\makeheaders.c |
| 1835 | - $(BCC) $** | |
| 1837 | + $(XBCC) $** | |
| 1836 | 1838 | |
| 1837 | 1839 | mkindex$E: $(SRCDIR)\mkindex.c |
| 1838 | - $(BCC) $** | |
| 1840 | + $(XBCC) $** | |
| 1839 | 1841 | |
| 1840 | 1842 | mkbuiltin$E: $(SRCDIR)\mkbuiltin.c |
| 1841 | - $(BCC) $** | |
| 1843 | + $(XBCC) $** | |
| 1842 | 1844 | |
| 1843 | 1845 | mkversion$E: $(SRCDIR)\mkversion.c |
| 1844 | - $(BCC) $** | |
| 1846 | + $(XBCC) $** | |
| 1845 | 1847 | |
| 1846 | 1848 | codecheck1$E: $(SRCDIR)\codecheck1.c |
| 1847 | - $(BCC) $** | |
| 1849 | + $(XBCC) $** | |
| 1848 | 1850 | |
| 1849 | 1851 | !if $(USE_SEE)!=0 |
| 1850 | 1852 | SQLITE3_SHELL_SRC = $(SRCDIR)\shell-see.c |
| 1851 | 1853 | !else |
| 1852 | 1854 | SQLITE3_SHELL_SRC = $(SRCDIR)\shell.c |
| 1853 | 1855 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -255,10 +255,11 @@ | |
| 255 | # to regenerate this file. |
| 256 | # |
| 257 | # This file is included by primary Makefile. |
| 258 | # |
| 259 | |
| 260 | XTCC = $(TCC) -I. -I$(SRCDIR) -I$(OBJDIR) $(TCCFLAGS) $(CFLAGS) |
| 261 | |
| 262 | } |
| 263 | writeln -nonewline "SRC =" |
| 264 | foreach s [lsort $src] { |
| @@ -298,26 +299,26 @@ | |
| 298 | |
| 299 | $(OBJDIR): |
| 300 | -mkdir $(OBJDIR) |
| 301 | |
| 302 | $(OBJDIR)/translate: $(SRCDIR)/translate.c |
| 303 | $(BCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c |
| 304 | |
| 305 | $(OBJDIR)/makeheaders: $(SRCDIR)/makeheaders.c |
| 306 | $(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c |
| 307 | |
| 308 | $(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c |
| 309 | $(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c |
| 310 | |
| 311 | $(OBJDIR)/mkbuiltin: $(SRCDIR)/mkbuiltin.c |
| 312 | $(BCC) -o $(OBJDIR)/mkbuiltin $(SRCDIR)/mkbuiltin.c |
| 313 | |
| 314 | $(OBJDIR)/mkversion: $(SRCDIR)/mkversion.c |
| 315 | $(BCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c |
| 316 | |
| 317 | $(OBJDIR)/codecheck1: $(SRCDIR)/codecheck1.c |
| 318 | $(BCC) -o $(OBJDIR)/codecheck1 $(SRCDIR)/codecheck1.c |
| 319 | |
| 320 | # Run the test suite. |
| 321 | # Other flags that can be included in TESTFLAGS are: |
| 322 | # |
| 323 | # -halt Stop testing after the first failed test |
| @@ -917,10 +918,11 @@ | |
| 917 | -include config.w32 |
| 918 | |
| 919 | # STOP HERE |
| 920 | # You should not need to change anything below this line |
| 921 | #-------------------------------------------------------- |
| 922 | XTCC = $(TCC) $(CFLAGS) -I. -I$(SRCDIR) |
| 923 | } |
| 924 | writeln -nonewline "SRC =" |
| 925 | foreach s [lsort $src] { |
| 926 | writeln -nonewline " \\\n \$(SRCDIR)/$s.c" |
| @@ -1013,26 +1015,26 @@ | |
| 1013 | else |
| 1014 | $(MKDIR) $(OBJDIR) |
| 1015 | endif |
| 1016 | |
| 1017 | $(TRANSLATE): $(SRCDIR)/translate.c |
| 1018 | $(BCC) -o $@ $(SRCDIR)/translate.c |
| 1019 | |
| 1020 | $(MAKEHEADERS): $(SRCDIR)/makeheaders.c |
| 1021 | $(BCC) -o $@ $(SRCDIR)/makeheaders.c |
| 1022 | |
| 1023 | $(MKINDEX): $(SRCDIR)/mkindex.c |
| 1024 | $(BCC) -o $@ $(SRCDIR)/mkindex.c |
| 1025 | |
| 1026 | $(MKBUILTIN): $(SRCDIR)/mkbuiltin.c |
| 1027 | $(BCC) -o $@ $(SRCDIR)/mkbuiltin.c |
| 1028 | |
| 1029 | $(MKVERSION): $(SRCDIR)/mkversion.c |
| 1030 | $(BCC) -o $@ $(SRCDIR)/mkversion.c |
| 1031 | |
| 1032 | $(CODECHECK1): $(SRCDIR)/codecheck1.c |
| 1033 | $(BCC) -o $@ $(SRCDIR)/codecheck1.c |
| 1034 | |
| 1035 | # WARNING. DANGER. Running the test suite modifies the repository the |
| 1036 | # build is done from, i.e. the checkout belongs to. Do not sync/push |
| 1037 | # the repository after running the tests. |
| 1038 | test: $(OBJDIR) $(APPNAME) |
| @@ -1305,26 +1307,26 @@ | |
| 1305 | writeln "\t+echo. >> \$@" |
| 1306 | writeln "\t+echo fossil >> \$@" |
| 1307 | |
| 1308 | writeln { |
| 1309 | translate$E: $(SRCDIR)\translate.c |
| 1310 | $(BCC) -o$@ $** |
| 1311 | |
| 1312 | makeheaders$E: $(SRCDIR)\makeheaders.c |
| 1313 | $(BCC) -o$@ $** |
| 1314 | |
| 1315 | mkindex$E: $(SRCDIR)\mkindex.c |
| 1316 | $(BCC) -o$@ $** |
| 1317 | |
| 1318 | mkbuiltin$E: $(SRCDIR)\mkbuiltin.c |
| 1319 | $(BCC) -o$@ $** |
| 1320 | |
| 1321 | mkversion$E: $(SRCDIR)\mkversion.c |
| 1322 | $(BCC) -o$@ $** |
| 1323 | |
| 1324 | codecheck1$E: $(SRCDIR)\codecheck1.c |
| 1325 | $(BCC) -o$@ $** |
| 1326 | |
| 1327 | $(OBJDIR)\shell$O : $(SRCDIR)\shell.c |
| 1328 | $(TCC) -o$@ -c $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) $** |
| 1329 | |
| 1330 | $(OBJDIR)\sqlite3$O : $(SRCDIR)\sqlite3.c |
| @@ -1827,26 +1829,26 @@ | |
| 1827 | writeln { |
| 1828 | $(OX): |
| 1829 | @-mkdir $@ |
| 1830 | |
| 1831 | translate$E: $(SRCDIR)\translate.c |
| 1832 | $(BCC) $** |
| 1833 | |
| 1834 | makeheaders$E: $(SRCDIR)\makeheaders.c |
| 1835 | $(BCC) $** |
| 1836 | |
| 1837 | mkindex$E: $(SRCDIR)\mkindex.c |
| 1838 | $(BCC) $** |
| 1839 | |
| 1840 | mkbuiltin$E: $(SRCDIR)\mkbuiltin.c |
| 1841 | $(BCC) $** |
| 1842 | |
| 1843 | mkversion$E: $(SRCDIR)\mkversion.c |
| 1844 | $(BCC) $** |
| 1845 | |
| 1846 | codecheck1$E: $(SRCDIR)\codecheck1.c |
| 1847 | $(BCC) $** |
| 1848 | |
| 1849 | !if $(USE_SEE)!=0 |
| 1850 | SQLITE3_SHELL_SRC = $(SRCDIR)\shell-see.c |
| 1851 | !else |
| 1852 | SQLITE3_SHELL_SRC = $(SRCDIR)\shell.c |
| 1853 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -255,10 +255,11 @@ | |
| 255 | # to regenerate this file. |
| 256 | # |
| 257 | # This file is included by primary Makefile. |
| 258 | # |
| 259 | |
| 260 | XBCC = $(BCC) $(BCCFLAGS) $(CFLAGS) |
| 261 | XTCC = $(TCC) -I. -I$(SRCDIR) -I$(OBJDIR) $(TCCFLAGS) $(CFLAGS) |
| 262 | |
| 263 | } |
| 264 | writeln -nonewline "SRC =" |
| 265 | foreach s [lsort $src] { |
| @@ -298,26 +299,26 @@ | |
| 299 | |
| 300 | $(OBJDIR): |
| 301 | -mkdir $(OBJDIR) |
| 302 | |
| 303 | $(OBJDIR)/translate: $(SRCDIR)/translate.c |
| 304 | $(XBCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c |
| 305 | |
| 306 | $(OBJDIR)/makeheaders: $(SRCDIR)/makeheaders.c |
| 307 | $(XBCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c |
| 308 | |
| 309 | $(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c |
| 310 | $(XBCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c |
| 311 | |
| 312 | $(OBJDIR)/mkbuiltin: $(SRCDIR)/mkbuiltin.c |
| 313 | $(XBCC) -o $(OBJDIR)/mkbuiltin $(SRCDIR)/mkbuiltin.c |
| 314 | |
| 315 | $(OBJDIR)/mkversion: $(SRCDIR)/mkversion.c |
| 316 | $(XBCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c |
| 317 | |
| 318 | $(OBJDIR)/codecheck1: $(SRCDIR)/codecheck1.c |
| 319 | $(XBCC) -o $(OBJDIR)/codecheck1 $(SRCDIR)/codecheck1.c |
| 320 | |
| 321 | # Run the test suite. |
| 322 | # Other flags that can be included in TESTFLAGS are: |
| 323 | # |
| 324 | # -halt Stop testing after the first failed test |
| @@ -917,10 +918,11 @@ | |
| 918 | -include config.w32 |
| 919 | |
| 920 | # STOP HERE |
| 921 | # You should not need to change anything below this line |
| 922 | #-------------------------------------------------------- |
| 923 | XBCC = $(BCC) $(CFLAGS) |
| 924 | XTCC = $(TCC) $(CFLAGS) -I. -I$(SRCDIR) |
| 925 | } |
| 926 | writeln -nonewline "SRC =" |
| 927 | foreach s [lsort $src] { |
| 928 | writeln -nonewline " \\\n \$(SRCDIR)/$s.c" |
| @@ -1013,26 +1015,26 @@ | |
| 1015 | else |
| 1016 | $(MKDIR) $(OBJDIR) |
| 1017 | endif |
| 1018 | |
| 1019 | $(TRANSLATE): $(SRCDIR)/translate.c |
| 1020 | $(XBCC) -o $@ $(SRCDIR)/translate.c |
| 1021 | |
| 1022 | $(MAKEHEADERS): $(SRCDIR)/makeheaders.c |
| 1023 | $(XBCC) -o $@ $(SRCDIR)/makeheaders.c |
| 1024 | |
| 1025 | $(MKINDEX): $(SRCDIR)/mkindex.c |
| 1026 | $(XBCC) -o $@ $(SRCDIR)/mkindex.c |
| 1027 | |
| 1028 | $(MKBUILTIN): $(SRCDIR)/mkbuiltin.c |
| 1029 | $(XBCC) -o $@ $(SRCDIR)/mkbuiltin.c |
| 1030 | |
| 1031 | $(MKVERSION): $(SRCDIR)/mkversion.c |
| 1032 | $(XBCC) -o $@ $(SRCDIR)/mkversion.c |
| 1033 | |
| 1034 | $(CODECHECK1): $(SRCDIR)/codecheck1.c |
| 1035 | $(XBCC) -o $@ $(SRCDIR)/codecheck1.c |
| 1036 | |
| 1037 | # WARNING. DANGER. Running the test suite modifies the repository the |
| 1038 | # build is done from, i.e. the checkout belongs to. Do not sync/push |
| 1039 | # the repository after running the tests. |
| 1040 | test: $(OBJDIR) $(APPNAME) |
| @@ -1305,26 +1307,26 @@ | |
| 1307 | writeln "\t+echo. >> \$@" |
| 1308 | writeln "\t+echo fossil >> \$@" |
| 1309 | |
| 1310 | writeln { |
| 1311 | translate$E: $(SRCDIR)\translate.c |
| 1312 | $(XBCC) -o$@ $** |
| 1313 | |
| 1314 | makeheaders$E: $(SRCDIR)\makeheaders.c |
| 1315 | $(XBCC) -o$@ $** |
| 1316 | |
| 1317 | mkindex$E: $(SRCDIR)\mkindex.c |
| 1318 | $(XBCC) -o$@ $** |
| 1319 | |
| 1320 | mkbuiltin$E: $(SRCDIR)\mkbuiltin.c |
| 1321 | $(XBCC) -o$@ $** |
| 1322 | |
| 1323 | mkversion$E: $(SRCDIR)\mkversion.c |
| 1324 | $(XBCC) -o$@ $** |
| 1325 | |
| 1326 | codecheck1$E: $(SRCDIR)\codecheck1.c |
| 1327 | $(XBCC) -o$@ $** |
| 1328 | |
| 1329 | $(OBJDIR)\shell$O : $(SRCDIR)\shell.c |
| 1330 | $(TCC) -o$@ -c $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) $** |
| 1331 | |
| 1332 | $(OBJDIR)\sqlite3$O : $(SRCDIR)\sqlite3.c |
| @@ -1827,26 +1829,26 @@ | |
| 1829 | writeln { |
| 1830 | $(OX): |
| 1831 | @-mkdir $@ |
| 1832 | |
| 1833 | translate$E: $(SRCDIR)\translate.c |
| 1834 | $(XBCC) $** |
| 1835 | |
| 1836 | makeheaders$E: $(SRCDIR)\makeheaders.c |
| 1837 | $(XBCC) $** |
| 1838 | |
| 1839 | mkindex$E: $(SRCDIR)\mkindex.c |
| 1840 | $(XBCC) $** |
| 1841 | |
| 1842 | mkbuiltin$E: $(SRCDIR)\mkbuiltin.c |
| 1843 | $(XBCC) $** |
| 1844 | |
| 1845 | mkversion$E: $(SRCDIR)\mkversion.c |
| 1846 | $(XBCC) $** |
| 1847 | |
| 1848 | codecheck1$E: $(SRCDIR)\codecheck1.c |
| 1849 | $(XBCC) $** |
| 1850 | |
| 1851 | !if $(USE_SEE)!=0 |
| 1852 | SQLITE3_SHELL_SRC = $(SRCDIR)\shell-see.c |
| 1853 | !else |
| 1854 | SQLITE3_SHELL_SRC = $(SRCDIR)\shell.c |
| 1855 |
+1
-1
| --- src/markdown.c | ||
| +++ src/markdown.c | ||
| @@ -295,11 +295,11 @@ | ||
| 295 | 295 | /* binary search of the tag */ |
| 296 | 296 | key.text = data; |
| 297 | 297 | key.size = i; |
| 298 | 298 | return bsearch(&key, |
| 299 | 299 | block_tags, |
| 300 | - (sizeof block_tags)/(sizeof block_tags[0]), | |
| 300 | + count(block_tags), | |
| 301 | 301 | sizeof block_tags[0], |
| 302 | 302 | cmp_html_tag); |
| 303 | 303 | } |
| 304 | 304 | |
| 305 | 305 | |
| 306 | 306 |
| --- src/markdown.c | |
| +++ src/markdown.c | |
| @@ -295,11 +295,11 @@ | |
| 295 | /* binary search of the tag */ |
| 296 | key.text = data; |
| 297 | key.size = i; |
| 298 | return bsearch(&key, |
| 299 | block_tags, |
| 300 | (sizeof block_tags)/(sizeof block_tags[0]), |
| 301 | sizeof block_tags[0], |
| 302 | cmp_html_tag); |
| 303 | } |
| 304 | |
| 305 | |
| 306 |
| --- src/markdown.c | |
| +++ src/markdown.c | |
| @@ -295,11 +295,11 @@ | |
| 295 | /* binary search of the tag */ |
| 296 | key.text = data; |
| 297 | key.size = i; |
| 298 | return bsearch(&key, |
| 299 | block_tags, |
| 300 | count(block_tags), |
| 301 | sizeof block_tags[0], |
| 302 | cmp_html_tag); |
| 303 | } |
| 304 | |
| 305 | |
| 306 |
+5
-5
| --- src/merge3.c | ||
| +++ src/merge3.c | ||
| @@ -316,11 +316,11 @@ | ||
| 316 | 316 | const char *z = blob_buffer(p); |
| 317 | 317 | int n = blob_size(p) - len + 1; |
| 318 | 318 | assert( len==(int)strlen(mergeMarker[1]) ); |
| 319 | 319 | assert( len==(int)strlen(mergeMarker[2]) ); |
| 320 | 320 | assert( len==(int)strlen(mergeMarker[3]) ); |
| 321 | - assert( sizeof(mergeMarker)/sizeof(mergeMarker[0])==4 ); | |
| 321 | + assert( count(mergeMarker)==4 ); | |
| 322 | 322 | for(i=0; i<n; ){ |
| 323 | 323 | for(j=0; j<4; j++){ |
| 324 | 324 | if( memcmp(&z[i], mergeMarker[j], len)==0 ) return 1; |
| 325 | 325 | } |
| 326 | 326 | while( i<n && z[i]!='\n' ){ i++; } |
| @@ -376,21 +376,21 @@ | ||
| 376 | 376 | |
| 377 | 377 | if( g.argc!=6 ){ |
| 378 | 378 | usage("PIVOT V1 V2 MERGED"); |
| 379 | 379 | } |
| 380 | 380 | if( blob_read_from_file(&pivot, g.argv[2])<0 ){ |
| 381 | - fossil_fatal("cannot read %s\n", g.argv[2]); | |
| 381 | + fossil_fatal("cannot read %s", g.argv[2]); | |
| 382 | 382 | } |
| 383 | 383 | if( blob_read_from_file(&v1, g.argv[3])<0 ){ |
| 384 | - fossil_fatal("cannot read %s\n", g.argv[3]); | |
| 384 | + fossil_fatal("cannot read %s", g.argv[3]); | |
| 385 | 385 | } |
| 386 | 386 | if( blob_read_from_file(&v2, g.argv[4])<0 ){ |
| 387 | - fossil_fatal("cannot read %s\n", g.argv[4]); | |
| 387 | + fossil_fatal("cannot read %s", g.argv[4]); | |
| 388 | 388 | } |
| 389 | 389 | blob_merge(&pivot, &v1, &v2, &merged); |
| 390 | 390 | if( blob_write_to_file(&merged, g.argv[5])<blob_size(&merged) ){ |
| 391 | - fossil_fatal("cannot write %s\n", g.argv[4]); | |
| 391 | + fossil_fatal("cannot write %s", g.argv[4]); | |
| 392 | 392 | } |
| 393 | 393 | blob_reset(&pivot); |
| 394 | 394 | blob_reset(&v1); |
| 395 | 395 | blob_reset(&v2); |
| 396 | 396 | blob_reset(&merged); |
| 397 | 397 |
| --- src/merge3.c | |
| +++ src/merge3.c | |
| @@ -316,11 +316,11 @@ | |
| 316 | const char *z = blob_buffer(p); |
| 317 | int n = blob_size(p) - len + 1; |
| 318 | assert( len==(int)strlen(mergeMarker[1]) ); |
| 319 | assert( len==(int)strlen(mergeMarker[2]) ); |
| 320 | assert( len==(int)strlen(mergeMarker[3]) ); |
| 321 | assert( sizeof(mergeMarker)/sizeof(mergeMarker[0])==4 ); |
| 322 | for(i=0; i<n; ){ |
| 323 | for(j=0; j<4; j++){ |
| 324 | if( memcmp(&z[i], mergeMarker[j], len)==0 ) return 1; |
| 325 | } |
| 326 | while( i<n && z[i]!='\n' ){ i++; } |
| @@ -376,21 +376,21 @@ | |
| 376 | |
| 377 | if( g.argc!=6 ){ |
| 378 | usage("PIVOT V1 V2 MERGED"); |
| 379 | } |
| 380 | if( blob_read_from_file(&pivot, g.argv[2])<0 ){ |
| 381 | fossil_fatal("cannot read %s\n", g.argv[2]); |
| 382 | } |
| 383 | if( blob_read_from_file(&v1, g.argv[3])<0 ){ |
| 384 | fossil_fatal("cannot read %s\n", g.argv[3]); |
| 385 | } |
| 386 | if( blob_read_from_file(&v2, g.argv[4])<0 ){ |
| 387 | fossil_fatal("cannot read %s\n", g.argv[4]); |
| 388 | } |
| 389 | blob_merge(&pivot, &v1, &v2, &merged); |
| 390 | if( blob_write_to_file(&merged, g.argv[5])<blob_size(&merged) ){ |
| 391 | fossil_fatal("cannot write %s\n", g.argv[4]); |
| 392 | } |
| 393 | blob_reset(&pivot); |
| 394 | blob_reset(&v1); |
| 395 | blob_reset(&v2); |
| 396 | blob_reset(&merged); |
| 397 |
| --- src/merge3.c | |
| +++ src/merge3.c | |
| @@ -316,11 +316,11 @@ | |
| 316 | const char *z = blob_buffer(p); |
| 317 | int n = blob_size(p) - len + 1; |
| 318 | assert( len==(int)strlen(mergeMarker[1]) ); |
| 319 | assert( len==(int)strlen(mergeMarker[2]) ); |
| 320 | assert( len==(int)strlen(mergeMarker[3]) ); |
| 321 | assert( count(mergeMarker)==4 ); |
| 322 | for(i=0; i<n; ){ |
| 323 | for(j=0; j<4; j++){ |
| 324 | if( memcmp(&z[i], mergeMarker[j], len)==0 ) return 1; |
| 325 | } |
| 326 | while( i<n && z[i]!='\n' ){ i++; } |
| @@ -376,21 +376,21 @@ | |
| 376 | |
| 377 | if( g.argc!=6 ){ |
| 378 | usage("PIVOT V1 V2 MERGED"); |
| 379 | } |
| 380 | if( blob_read_from_file(&pivot, g.argv[2])<0 ){ |
| 381 | fossil_fatal("cannot read %s", g.argv[2]); |
| 382 | } |
| 383 | if( blob_read_from_file(&v1, g.argv[3])<0 ){ |
| 384 | fossil_fatal("cannot read %s", g.argv[3]); |
| 385 | } |
| 386 | if( blob_read_from_file(&v2, g.argv[4])<0 ){ |
| 387 | fossil_fatal("cannot read %s", g.argv[4]); |
| 388 | } |
| 389 | blob_merge(&pivot, &v1, &v2, &merged); |
| 390 | if( blob_write_to_file(&merged, g.argv[5])<blob_size(&merged) ){ |
| 391 | fossil_fatal("cannot write %s", g.argv[4]); |
| 392 | } |
| 393 | blob_reset(&pivot); |
| 394 | blob_reset(&v1); |
| 395 | blob_reset(&v2); |
| 396 | blob_reset(&merged); |
| 397 |
+2
-2
| --- src/mkindex.c | ||
| +++ src/mkindex.c | ||
| @@ -202,11 +202,11 @@ | ||
| 202 | 202 | /* Otherwise, this is a first-tier command */ |
| 203 | 203 | aEntry[nUsed].eType |= CMDFLAG_1ST_TIER; |
| 204 | 204 | } |
| 205 | 205 | } |
| 206 | 206 | |
| 207 | - /* Processing additional flags that might following the command name */ | |
| 207 | + /* Process additional flags that might follow the command name */ | |
| 208 | 208 | while( zLine[i+j]!=0 ){ |
| 209 | 209 | i += j; |
| 210 | 210 | while( fossil_isspace(zLine[i]) ){ i++; } |
| 211 | 211 | if( zLine[i]==0 ) break; |
| 212 | 212 | for(j=0; zLine[i+j] && !fossil_isspace(zLine[i+j]); j++){} |
| @@ -223,11 +223,11 @@ | ||
| 223 | 223 | fprintf(stderr, "%s:%d: unknown option: '%.*s'\n", |
| 224 | 224 | zFile, nLine, j, &zLine[i]); |
| 225 | 225 | nErr++; |
| 226 | 226 | } |
| 227 | 227 | } |
| 228 | - | |
| 228 | + | |
| 229 | 229 | nUsed++; |
| 230 | 230 | } |
| 231 | 231 | |
| 232 | 232 | /* |
| 233 | 233 | ** Check to see if the current line is an #if and if it is, add it to |
| 234 | 234 |
| --- src/mkindex.c | |
| +++ src/mkindex.c | |
| @@ -202,11 +202,11 @@ | |
| 202 | /* Otherwise, this is a first-tier command */ |
| 203 | aEntry[nUsed].eType |= CMDFLAG_1ST_TIER; |
| 204 | } |
| 205 | } |
| 206 | |
| 207 | /* Processing additional flags that might following the command name */ |
| 208 | while( zLine[i+j]!=0 ){ |
| 209 | i += j; |
| 210 | while( fossil_isspace(zLine[i]) ){ i++; } |
| 211 | if( zLine[i]==0 ) break; |
| 212 | for(j=0; zLine[i+j] && !fossil_isspace(zLine[i+j]); j++){} |
| @@ -223,11 +223,11 @@ | |
| 223 | fprintf(stderr, "%s:%d: unknown option: '%.*s'\n", |
| 224 | zFile, nLine, j, &zLine[i]); |
| 225 | nErr++; |
| 226 | } |
| 227 | } |
| 228 | |
| 229 | nUsed++; |
| 230 | } |
| 231 | |
| 232 | /* |
| 233 | ** Check to see if the current line is an #if and if it is, add it to |
| 234 |
| --- src/mkindex.c | |
| +++ src/mkindex.c | |
| @@ -202,11 +202,11 @@ | |
| 202 | /* Otherwise, this is a first-tier command */ |
| 203 | aEntry[nUsed].eType |= CMDFLAG_1ST_TIER; |
| 204 | } |
| 205 | } |
| 206 | |
| 207 | /* Process additional flags that might follow the command name */ |
| 208 | while( zLine[i+j]!=0 ){ |
| 209 | i += j; |
| 210 | while( fossil_isspace(zLine[i]) ){ i++; } |
| 211 | if( zLine[i]==0 ) break; |
| 212 | for(j=0; zLine[i+j] && !fossil_isspace(zLine[i+j]); j++){} |
| @@ -223,11 +223,11 @@ | |
| 223 | fprintf(stderr, "%s:%d: unknown option: '%.*s'\n", |
| 224 | zFile, nLine, j, &zLine[i]); |
| 225 | nErr++; |
| 226 | } |
| 227 | } |
| 228 | |
| 229 | nUsed++; |
| 230 | } |
| 231 | |
| 232 | /* |
| 233 | ** Check to see if the current line is an #if and if it is, add it to |
| 234 |
+4
| --- src/mkversion.c | ||
| +++ src/mkversion.c | ||
| @@ -64,10 +64,14 @@ | ||
| 64 | 64 | printf("#define RELEASE_VERSION_NUMBER %s\n", z); |
| 65 | 65 | memset(vx,0,sizeof(vx)); |
| 66 | 66 | strcpy(vx,b); |
| 67 | 67 | d = 0; |
| 68 | 68 | for(z=vx; z[0]; z++){ |
| 69 | + if( z[0]=='-' ){ | |
| 70 | + z[0] = 0; | |
| 71 | + break; | |
| 72 | + } | |
| 69 | 73 | if( z[0]!='.' ) continue; |
| 70 | 74 | if ( d<3 ){ |
| 71 | 75 | z[0] = ','; |
| 72 | 76 | d++; |
| 73 | 77 | }else{ |
| 74 | 78 |
| --- src/mkversion.c | |
| +++ src/mkversion.c | |
| @@ -64,10 +64,14 @@ | |
| 64 | printf("#define RELEASE_VERSION_NUMBER %s\n", z); |
| 65 | memset(vx,0,sizeof(vx)); |
| 66 | strcpy(vx,b); |
| 67 | d = 0; |
| 68 | for(z=vx; z[0]; z++){ |
| 69 | if( z[0]!='.' ) continue; |
| 70 | if ( d<3 ){ |
| 71 | z[0] = ','; |
| 72 | d++; |
| 73 | }else{ |
| 74 |
| --- src/mkversion.c | |
| +++ src/mkversion.c | |
| @@ -64,10 +64,14 @@ | |
| 64 | printf("#define RELEASE_VERSION_NUMBER %s\n", z); |
| 65 | memset(vx,0,sizeof(vx)); |
| 66 | strcpy(vx,b); |
| 67 | d = 0; |
| 68 | for(z=vx; z[0]; z++){ |
| 69 | if( z[0]=='-' ){ |
| 70 | z[0] = 0; |
| 71 | break; |
| 72 | } |
| 73 | if( z[0]!='.' ) continue; |
| 74 | if ( d<3 ){ |
| 75 | z[0] = ','; |
| 76 | d++; |
| 77 | }else{ |
| 78 |
+1
-1
| --- src/moderate.c | ||
| +++ src/moderate.c | ||
| @@ -67,11 +67,11 @@ | ||
| 67 | 67 | "mlink", "fid", |
| 68 | 68 | "tagxref", "srcid", |
| 69 | 69 | "tagxref", "rid", |
| 70 | 70 | }; |
| 71 | 71 | int i; |
| 72 | - for(i=0; i<sizeof(aTabField)/sizeof(aTabField[0]); i+=2){ | |
| 72 | + for(i=0; i<count(aTabField); i+=2){ | |
| 73 | 73 | if( db_exists("SELECT 1 FROM \"%w\" WHERE \"%w\"=%d", |
| 74 | 74 | aTabField[i], aTabField[i+1], rid) ) return 1; |
| 75 | 75 | } |
| 76 | 76 | return 0; |
| 77 | 77 | } |
| 78 | 78 |
| --- src/moderate.c | |
| +++ src/moderate.c | |
| @@ -67,11 +67,11 @@ | |
| 67 | "mlink", "fid", |
| 68 | "tagxref", "srcid", |
| 69 | "tagxref", "rid", |
| 70 | }; |
| 71 | int i; |
| 72 | for(i=0; i<sizeof(aTabField)/sizeof(aTabField[0]); i+=2){ |
| 73 | if( db_exists("SELECT 1 FROM \"%w\" WHERE \"%w\"=%d", |
| 74 | aTabField[i], aTabField[i+1], rid) ) return 1; |
| 75 | } |
| 76 | return 0; |
| 77 | } |
| 78 |
| --- src/moderate.c | |
| +++ src/moderate.c | |
| @@ -67,11 +67,11 @@ | |
| 67 | "mlink", "fid", |
| 68 | "tagxref", "srcid", |
| 69 | "tagxref", "rid", |
| 70 | }; |
| 71 | int i; |
| 72 | for(i=0; i<count(aTabField); i+=2){ |
| 73 | if( db_exists("SELECT 1 FROM \"%w\" WHERE \"%w\"=%d", |
| 74 | aTabField[i], aTabField[i+1], rid) ) return 1; |
| 75 | } |
| 76 | return 0; |
| 77 | } |
| 78 |
+5
-5
| --- src/name.c | ||
| +++ src/name.c | ||
| @@ -1006,11 +1006,11 @@ | ||
| 1006 | 1006 | char *zRange; |
| 1007 | 1007 | |
| 1008 | 1008 | login_check_credentials(); |
| 1009 | 1009 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1010 | 1010 | style_header("List Of Artifacts"); |
| 1011 | - style_submenu_element("250 Largest", 0, "bigbloblist"); | |
| 1011 | + style_submenu_element("250 Largest", "bigbloblist"); | |
| 1012 | 1012 | if( !unpubOnly && mx>n && P("s")==0 ){ |
| 1013 | 1013 | int i; |
| 1014 | 1014 | @ <p>Select a range of artifacts to view:</p> |
| 1015 | 1015 | @ <ul> |
| 1016 | 1016 | for(i=1; i<=mx; i+=n){ |
| @@ -1020,11 +1020,11 @@ | ||
| 1020 | 1020 | @ </ul> |
| 1021 | 1021 | style_footer(); |
| 1022 | 1022 | return; |
| 1023 | 1023 | } |
| 1024 | 1024 | if( !unpubOnly && mx>n ){ |
| 1025 | - style_submenu_element("Index", "Index", "bloblist"); | |
| 1025 | + style_submenu_element("Index", "bloblist"); | |
| 1026 | 1026 | } |
| 1027 | 1027 | if( unpubOnly ){ |
| 1028 | 1028 | zRange = mprintf("IN private"); |
| 1029 | 1029 | }else{ |
| 1030 | 1030 | zRange = mprintf("BETWEEN %d AND %d", s, s+n-1); |
| @@ -1204,11 +1204,11 @@ | ||
| 1204 | 1204 | char *zId = aCollide[i].azHit[j]; |
| 1205 | 1205 | if( zId==0 ) continue; |
| 1206 | 1206 | @ %z(href("%R/whatis/%s",zId))%h(zId)</a> |
| 1207 | 1207 | } |
| 1208 | 1208 | } |
| 1209 | - for(i=4; i<ArraySize(aCollide); i++){ | |
| 1209 | + for(i=4; i<count(aCollide); i++){ | |
| 1210 | 1210 | for(j=0; j<aCollide[i].cnt && j<MAX_COLLIDE; j++){ |
| 1211 | 1211 | fossil_free(aCollide[i].azHit[j]); |
| 1212 | 1212 | } |
| 1213 | 1213 | } |
| 1214 | 1214 | } |
| @@ -1220,15 +1220,15 @@ | ||
| 1220 | 1220 | */ |
| 1221 | 1221 | void hash_collisions_webpage(void){ |
| 1222 | 1222 | login_check_credentials(); |
| 1223 | 1223 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1224 | 1224 | style_header("SHA1 Prefix Collisions"); |
| 1225 | - style_submenu_element("Activity Reports", 0, "reports"); | |
| 1226 | - style_submenu_element("Stats", 0, "stat"); | |
| 1225 | + style_submenu_element("Activity Reports", "reports"); | |
| 1226 | + style_submenu_element("Stats", "stat"); | |
| 1227 | 1227 | @ <h1>Hash Prefix Collisions on Check-ins</h1> |
| 1228 | 1228 | collision_report("SELECT (SELECT uuid FROM blob WHERE rid=objid)" |
| 1229 | 1229 | " FROM event WHERE event.type='ci'" |
| 1230 | 1230 | " ORDER BY 1"); |
| 1231 | 1231 | @ <h1>Hash Prefix Collisions on All Artifacts</h1> |
| 1232 | 1232 | collision_report("SELECT uuid FROM blob ORDER BY 1"); |
| 1233 | 1233 | style_footer(); |
| 1234 | 1234 | } |
| 1235 | 1235 |
| --- src/name.c | |
| +++ src/name.c | |
| @@ -1006,11 +1006,11 @@ | |
| 1006 | char *zRange; |
| 1007 | |
| 1008 | login_check_credentials(); |
| 1009 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1010 | style_header("List Of Artifacts"); |
| 1011 | style_submenu_element("250 Largest", 0, "bigbloblist"); |
| 1012 | if( !unpubOnly && mx>n && P("s")==0 ){ |
| 1013 | int i; |
| 1014 | @ <p>Select a range of artifacts to view:</p> |
| 1015 | @ <ul> |
| 1016 | for(i=1; i<=mx; i+=n){ |
| @@ -1020,11 +1020,11 @@ | |
| 1020 | @ </ul> |
| 1021 | style_footer(); |
| 1022 | return; |
| 1023 | } |
| 1024 | if( !unpubOnly && mx>n ){ |
| 1025 | style_submenu_element("Index", "Index", "bloblist"); |
| 1026 | } |
| 1027 | if( unpubOnly ){ |
| 1028 | zRange = mprintf("IN private"); |
| 1029 | }else{ |
| 1030 | zRange = mprintf("BETWEEN %d AND %d", s, s+n-1); |
| @@ -1204,11 +1204,11 @@ | |
| 1204 | char *zId = aCollide[i].azHit[j]; |
| 1205 | if( zId==0 ) continue; |
| 1206 | @ %z(href("%R/whatis/%s",zId))%h(zId)</a> |
| 1207 | } |
| 1208 | } |
| 1209 | for(i=4; i<ArraySize(aCollide); i++){ |
| 1210 | for(j=0; j<aCollide[i].cnt && j<MAX_COLLIDE; j++){ |
| 1211 | fossil_free(aCollide[i].azHit[j]); |
| 1212 | } |
| 1213 | } |
| 1214 | } |
| @@ -1220,15 +1220,15 @@ | |
| 1220 | */ |
| 1221 | void hash_collisions_webpage(void){ |
| 1222 | login_check_credentials(); |
| 1223 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1224 | style_header("SHA1 Prefix Collisions"); |
| 1225 | style_submenu_element("Activity Reports", 0, "reports"); |
| 1226 | style_submenu_element("Stats", 0, "stat"); |
| 1227 | @ <h1>Hash Prefix Collisions on Check-ins</h1> |
| 1228 | collision_report("SELECT (SELECT uuid FROM blob WHERE rid=objid)" |
| 1229 | " FROM event WHERE event.type='ci'" |
| 1230 | " ORDER BY 1"); |
| 1231 | @ <h1>Hash Prefix Collisions on All Artifacts</h1> |
| 1232 | collision_report("SELECT uuid FROM blob ORDER BY 1"); |
| 1233 | style_footer(); |
| 1234 | } |
| 1235 |
| --- src/name.c | |
| +++ src/name.c | |
| @@ -1006,11 +1006,11 @@ | |
| 1006 | char *zRange; |
| 1007 | |
| 1008 | login_check_credentials(); |
| 1009 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1010 | style_header("List Of Artifacts"); |
| 1011 | style_submenu_element("250 Largest", "bigbloblist"); |
| 1012 | if( !unpubOnly && mx>n && P("s")==0 ){ |
| 1013 | int i; |
| 1014 | @ <p>Select a range of artifacts to view:</p> |
| 1015 | @ <ul> |
| 1016 | for(i=1; i<=mx; i+=n){ |
| @@ -1020,11 +1020,11 @@ | |
| 1020 | @ </ul> |
| 1021 | style_footer(); |
| 1022 | return; |
| 1023 | } |
| 1024 | if( !unpubOnly && mx>n ){ |
| 1025 | style_submenu_element("Index", "bloblist"); |
| 1026 | } |
| 1027 | if( unpubOnly ){ |
| 1028 | zRange = mprintf("IN private"); |
| 1029 | }else{ |
| 1030 | zRange = mprintf("BETWEEN %d AND %d", s, s+n-1); |
| @@ -1204,11 +1204,11 @@ | |
| 1204 | char *zId = aCollide[i].azHit[j]; |
| 1205 | if( zId==0 ) continue; |
| 1206 | @ %z(href("%R/whatis/%s",zId))%h(zId)</a> |
| 1207 | } |
| 1208 | } |
| 1209 | for(i=4; i<count(aCollide); i++){ |
| 1210 | for(j=0; j<aCollide[i].cnt && j<MAX_COLLIDE; j++){ |
| 1211 | fossil_free(aCollide[i].azHit[j]); |
| 1212 | } |
| 1213 | } |
| 1214 | } |
| @@ -1220,15 +1220,15 @@ | |
| 1220 | */ |
| 1221 | void hash_collisions_webpage(void){ |
| 1222 | login_check_credentials(); |
| 1223 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1224 | style_header("SHA1 Prefix Collisions"); |
| 1225 | style_submenu_element("Activity Reports", "reports"); |
| 1226 | style_submenu_element("Stats", "stat"); |
| 1227 | @ <h1>Hash Prefix Collisions on Check-ins</h1> |
| 1228 | collision_report("SELECT (SELECT uuid FROM blob WHERE rid=objid)" |
| 1229 | " FROM event WHERE event.type='ci'" |
| 1230 | " ORDER BY 1"); |
| 1231 | @ <h1>Hash Prefix Collisions on All Artifacts</h1> |
| 1232 | collision_report("SELECT uuid FROM blob ORDER BY 1"); |
| 1233 | style_footer(); |
| 1234 | } |
| 1235 |
+15
-6
| --- src/printf.c | ||
| +++ src/printf.c | ||
| @@ -158,11 +158,11 @@ | ||
| 158 | 158 | { 'n', 0, 0, etSIZE, 0, 0 }, |
| 159 | 159 | { '%', 0, 0, etPERCENT, 0, 0 }, |
| 160 | 160 | { 'p', 16, 0, etPOINTER, 0, 1 }, |
| 161 | 161 | { '/', 0, 0, etPATH, 0, 0 }, |
| 162 | 162 | }; |
| 163 | -#define etNINFO (sizeof(fmtinfo)/sizeof(fmtinfo[0])) | |
| 163 | +#define etNINFO count(fmtinfo) | |
| 164 | 164 | |
| 165 | 165 | /* |
| 166 | 166 | ** "*val" is a double such that 0.1 <= *val < 10.0 |
| 167 | 167 | ** Return the ascii code for the leading digit of *val, then |
| 168 | 168 | ** multiply "*val" by 10.0 to renormalize. |
| @@ -875,24 +875,33 @@ | ||
| 875 | 875 | /* |
| 876 | 876 | ** Write to standard output or standard error. |
| 877 | 877 | ** |
| 878 | 878 | ** On windows, transform the output into the current terminal encoding |
| 879 | 879 | ** if the output is going to the screen. If output is redirected into |
| 880 | -** a file, no translation occurs. No translation ever occurs on unix. | |
| 880 | +** a file, no translation occurs. Switch output mode to binary to | |
| 881 | +** properly process line-endings, make sure to switch the mode back to | |
| 882 | +** text when done. | |
| 883 | +** No translation ever occurs on unix. | |
| 881 | 884 | */ |
| 882 | 885 | void fossil_puts(const char *z, int toStdErr){ |
| 886 | + FILE* out = (toStdErr ? stderr : stdout); | |
| 883 | 887 | int n = (int)strlen(z); |
| 884 | 888 | if( n==0 ) return; |
| 889 | + assert( toStdErr==0 || toStdErr==1 ); | |
| 885 | 890 | if( toStdErr==0 ) stdoutAtBOL = (z[n-1]=='\n'); |
| 886 | 891 | #if defined(_WIN32) |
| 887 | 892 | if( fossil_utf8_to_console(z, n, toStdErr) >= 0 ){ |
| 888 | 893 | return; |
| 889 | 894 | } |
| 895 | + fflush(out); | |
| 896 | + _setmode(_fileno(out), _O_BINARY); | |
| 890 | 897 | #endif |
| 891 | - assert( toStdErr==0 || toStdErr==1 ); | |
| 892 | - fwrite(z, 1, n, toStdErr ? stderr : stdout); | |
| 893 | - fflush(toStdErr ? stderr : stdout); | |
| 898 | + fwrite(z, 1, n, out); | |
| 899 | +#if defined(_WIN32) | |
| 900 | + fflush(out); | |
| 901 | + _setmode(_fileno(out), _O_TEXT); | |
| 902 | +#endif | |
| 894 | 903 | } |
| 895 | 904 | |
| 896 | 905 | /* |
| 897 | 906 | ** Force the standard output cursor to move to the beginning |
| 898 | 907 | ** of a line, if it is not there already. |
| @@ -970,11 +979,11 @@ | ||
| 970 | 979 | pNow->tm_hour, pNow->tm_min, pNow->tm_sec); |
| 971 | 980 | va_start(ap, zFormat); |
| 972 | 981 | vfprintf(out, zFormat, ap); |
| 973 | 982 | fprintf(out, "\n"); |
| 974 | 983 | va_end(ap); |
| 975 | - for(i=0; i<sizeof(azEnv)/sizeof(azEnv[0]); i++){ | |
| 984 | + for(i=0; i<count(azEnv); i++){ | |
| 976 | 985 | char *p; |
| 977 | 986 | if( (p = fossil_getenv(azEnv[i]))!=0 ){ |
| 978 | 987 | fprintf(out, "%s=%s\n", azEnv[i], p); |
| 979 | 988 | fossil_path_free(p); |
| 980 | 989 | }else if( (z = P(azEnv[i]))!=0 ){ |
| 981 | 990 |
| --- src/printf.c | |
| +++ src/printf.c | |
| @@ -158,11 +158,11 @@ | |
| 158 | { 'n', 0, 0, etSIZE, 0, 0 }, |
| 159 | { '%', 0, 0, etPERCENT, 0, 0 }, |
| 160 | { 'p', 16, 0, etPOINTER, 0, 1 }, |
| 161 | { '/', 0, 0, etPATH, 0, 0 }, |
| 162 | }; |
| 163 | #define etNINFO (sizeof(fmtinfo)/sizeof(fmtinfo[0])) |
| 164 | |
| 165 | /* |
| 166 | ** "*val" is a double such that 0.1 <= *val < 10.0 |
| 167 | ** Return the ascii code for the leading digit of *val, then |
| 168 | ** multiply "*val" by 10.0 to renormalize. |
| @@ -875,24 +875,33 @@ | |
| 875 | /* |
| 876 | ** Write to standard output or standard error. |
| 877 | ** |
| 878 | ** On windows, transform the output into the current terminal encoding |
| 879 | ** if the output is going to the screen. If output is redirected into |
| 880 | ** a file, no translation occurs. No translation ever occurs on unix. |
| 881 | */ |
| 882 | void fossil_puts(const char *z, int toStdErr){ |
| 883 | int n = (int)strlen(z); |
| 884 | if( n==0 ) return; |
| 885 | if( toStdErr==0 ) stdoutAtBOL = (z[n-1]=='\n'); |
| 886 | #if defined(_WIN32) |
| 887 | if( fossil_utf8_to_console(z, n, toStdErr) >= 0 ){ |
| 888 | return; |
| 889 | } |
| 890 | #endif |
| 891 | assert( toStdErr==0 || toStdErr==1 ); |
| 892 | fwrite(z, 1, n, toStdErr ? stderr : stdout); |
| 893 | fflush(toStdErr ? stderr : stdout); |
| 894 | } |
| 895 | |
| 896 | /* |
| 897 | ** Force the standard output cursor to move to the beginning |
| 898 | ** of a line, if it is not there already. |
| @@ -970,11 +979,11 @@ | |
| 970 | pNow->tm_hour, pNow->tm_min, pNow->tm_sec); |
| 971 | va_start(ap, zFormat); |
| 972 | vfprintf(out, zFormat, ap); |
| 973 | fprintf(out, "\n"); |
| 974 | va_end(ap); |
| 975 | for(i=0; i<sizeof(azEnv)/sizeof(azEnv[0]); i++){ |
| 976 | char *p; |
| 977 | if( (p = fossil_getenv(azEnv[i]))!=0 ){ |
| 978 | fprintf(out, "%s=%s\n", azEnv[i], p); |
| 979 | fossil_path_free(p); |
| 980 | }else if( (z = P(azEnv[i]))!=0 ){ |
| 981 |
| --- src/printf.c | |
| +++ src/printf.c | |
| @@ -158,11 +158,11 @@ | |
| 158 | { 'n', 0, 0, etSIZE, 0, 0 }, |
| 159 | { '%', 0, 0, etPERCENT, 0, 0 }, |
| 160 | { 'p', 16, 0, etPOINTER, 0, 1 }, |
| 161 | { '/', 0, 0, etPATH, 0, 0 }, |
| 162 | }; |
| 163 | #define etNINFO count(fmtinfo) |
| 164 | |
| 165 | /* |
| 166 | ** "*val" is a double such that 0.1 <= *val < 10.0 |
| 167 | ** Return the ascii code for the leading digit of *val, then |
| 168 | ** multiply "*val" by 10.0 to renormalize. |
| @@ -875,24 +875,33 @@ | |
| 875 | /* |
| 876 | ** Write to standard output or standard error. |
| 877 | ** |
| 878 | ** On windows, transform the output into the current terminal encoding |
| 879 | ** if the output is going to the screen. If output is redirected into |
| 880 | ** a file, no translation occurs. Switch output mode to binary to |
| 881 | ** properly process line-endings, make sure to switch the mode back to |
| 882 | ** text when done. |
| 883 | ** No translation ever occurs on unix. |
| 884 | */ |
| 885 | void fossil_puts(const char *z, int toStdErr){ |
| 886 | FILE* out = (toStdErr ? stderr : stdout); |
| 887 | int n = (int)strlen(z); |
| 888 | if( n==0 ) return; |
| 889 | assert( toStdErr==0 || toStdErr==1 ); |
| 890 | if( toStdErr==0 ) stdoutAtBOL = (z[n-1]=='\n'); |
| 891 | #if defined(_WIN32) |
| 892 | if( fossil_utf8_to_console(z, n, toStdErr) >= 0 ){ |
| 893 | return; |
| 894 | } |
| 895 | fflush(out); |
| 896 | _setmode(_fileno(out), _O_BINARY); |
| 897 | #endif |
| 898 | fwrite(z, 1, n, out); |
| 899 | #if defined(_WIN32) |
| 900 | fflush(out); |
| 901 | _setmode(_fileno(out), _O_TEXT); |
| 902 | #endif |
| 903 | } |
| 904 | |
| 905 | /* |
| 906 | ** Force the standard output cursor to move to the beginning |
| 907 | ** of a line, if it is not there already. |
| @@ -970,11 +979,11 @@ | |
| 979 | pNow->tm_hour, pNow->tm_min, pNow->tm_sec); |
| 980 | va_start(ap, zFormat); |
| 981 | vfprintf(out, zFormat, ap); |
| 982 | fprintf(out, "\n"); |
| 983 | va_end(ap); |
| 984 | for(i=0; i<count(azEnv); i++){ |
| 985 | char *p; |
| 986 | if( (p = fossil_getenv(azEnv[i]))!=0 ){ |
| 987 | fprintf(out, "%s=%s\n", azEnv[i], p); |
| 988 | fossil_path_free(p); |
| 989 | }else if( (z = P(azEnv[i]))!=0 ){ |
| 990 |
+1
-1
| --- src/regexp.c | ||
| +++ src/regexp.c | ||
| @@ -205,11 +205,11 @@ | ||
| 205 | 205 | in.i++; |
| 206 | 206 | } |
| 207 | 207 | if( in.i+pRe->nInit>in.mx ) return 0; |
| 208 | 208 | } |
| 209 | 209 | |
| 210 | - if( pRe->nState<=(sizeof(aSpace)/(sizeof(aSpace[0])*2)) ){ | |
| 210 | + if( pRe->nState<=count(aSpace)*2 ){ | |
| 211 | 211 | pToFree = 0; |
| 212 | 212 | aStateSet[0].aState = aSpace; |
| 213 | 213 | }else{ |
| 214 | 214 | pToFree = fossil_malloc( sizeof(ReStateNumber)*2*pRe->nState ); |
| 215 | 215 | if( pToFree==0 ) return -1; |
| 216 | 216 |
| --- src/regexp.c | |
| +++ src/regexp.c | |
| @@ -205,11 +205,11 @@ | |
| 205 | in.i++; |
| 206 | } |
| 207 | if( in.i+pRe->nInit>in.mx ) return 0; |
| 208 | } |
| 209 | |
| 210 | if( pRe->nState<=(sizeof(aSpace)/(sizeof(aSpace[0])*2)) ){ |
| 211 | pToFree = 0; |
| 212 | aStateSet[0].aState = aSpace; |
| 213 | }else{ |
| 214 | pToFree = fossil_malloc( sizeof(ReStateNumber)*2*pRe->nState ); |
| 215 | if( pToFree==0 ) return -1; |
| 216 |
| --- src/regexp.c | |
| +++ src/regexp.c | |
| @@ -205,11 +205,11 @@ | |
| 205 | in.i++; |
| 206 | } |
| 207 | if( in.i+pRe->nInit>in.mx ) return 0; |
| 208 | } |
| 209 | |
| 210 | if( pRe->nState<=count(aSpace)*2 ){ |
| 211 | pToFree = 0; |
| 212 | aStateSet[0].aState = aSpace; |
| 213 | }else{ |
| 214 | pToFree = fossil_malloc( sizeof(ReStateNumber)*2*pRe->nState ); |
| 215 | if( pToFree==0 ) return -1; |
| 216 |
+11
-14
| --- src/report.c | ||
| +++ src/report.c | ||
| @@ -198,14 +198,14 @@ | ||
| 198 | 198 | }; |
| 199 | 199 | int i; |
| 200 | 200 | if( fossil_strncmp(zArg1, "fx_", 3)==0 ){ |
| 201 | 201 | break; |
| 202 | 202 | } |
| 203 | - for(i=0; i<sizeof(azAllowed)/sizeof(azAllowed[0]); i++){ | |
| 203 | + for(i=0; i<count(azAllowed); i++){ | |
| 204 | 204 | if( fossil_stricmp(zArg1, azAllowed[i])==0 ) break; |
| 205 | 205 | } |
| 206 | - if( i>=sizeof(azAllowed)/sizeof(azAllowed[0]) ){ | |
| 206 | + if( i>=count(azAllowed) ){ | |
| 207 | 207 | *(char**)pError = mprintf("access to table \"%s\" is restricted",zArg1); |
| 208 | 208 | rc = SQLITE_DENY; |
| 209 | 209 | }else if( !g.perm.RdAddr && strncmp(zArg2, "private_", 8)==0 ){ |
| 210 | 210 | rc = SQLITE_IGNORE; |
| 211 | 211 | } |
| @@ -450,13 +450,13 @@ | ||
| 450 | 450 | zTitle = mprintf("Copy Of %s", zTitle); |
| 451 | 451 | zOwner = g.zLogin; |
| 452 | 452 | } |
| 453 | 453 | } |
| 454 | 454 | if( zOwner==0 ) zOwner = g.zLogin; |
| 455 | - style_submenu_element("Cancel", "Cancel", "reportlist"); | |
| 455 | + style_submenu_element("Cancel", "reportlist"); | |
| 456 | 456 | if( rn>0 ){ |
| 457 | - style_submenu_element("Delete", "Delete", "rptedit?rn=%d&del1=1", rn); | |
| 457 | + style_submenu_element("Delete", "rptedit?rn=%d&del1=1", rn); | |
| 458 | 458 | } |
| 459 | 459 | style_header("%s", rn>0 ? "Edit Report Format":"Create New Report Format"); |
| 460 | 460 | if( zErr ){ |
| 461 | 461 | @ <blockquote class="reportError">%h(zErr)</blockquote> |
| 462 | 462 | } |
| @@ -700,15 +700,14 @@ | ||
| 700 | 700 | pState->zWikiEnd = ""; |
| 701 | 701 | if( P("plaintext") ){ |
| 702 | 702 | pState->wikiFlags |= WIKI_LINKSONLY; |
| 703 | 703 | pState->zWikiStart = "<pre class='verbatim'>"; |
| 704 | 704 | pState->zWikiEnd = "</pre>"; |
| 705 | - style_submenu_element("Formatted", "Formatted", | |
| 706 | - "%R/rptview?rn=%d", pState->rn); | |
| 705 | + style_submenu_element("Formatted", "%R/rptview?rn=%d", pState->rn); | |
| 707 | 706 | }else{ |
| 708 | - style_submenu_element("Plaintext", "Plaintext", | |
| 709 | - "%R/rptview?rn=%d&plaintext", pState->rn); | |
| 707 | + style_submenu_element("Plaintext", "%R/rptview?rn=%d&plaintext", | |
| 708 | + pState->rn); | |
| 710 | 709 | } |
| 711 | 710 | }else{ |
| 712 | 711 | pState->nCol++; |
| 713 | 712 | } |
| 714 | 713 | } |
| @@ -1197,22 +1196,20 @@ | ||
| 1197 | 1196 | count = 0; |
| 1198 | 1197 | if( !tabs ){ |
| 1199 | 1198 | struct GenerateHTML sState = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
| 1200 | 1199 | |
| 1201 | 1200 | db_multi_exec("PRAGMA empty_result_callbacks=ON"); |
| 1202 | - style_submenu_element("Raw", "Raw", | |
| 1203 | - "rptview?tablist=1&%h", PD("QUERY_STRING","")); | |
| 1201 | + style_submenu_element("Raw", "rptview?tablist=1&%h", PD("QUERY_STRING","")); | |
| 1204 | 1202 | if( g.perm.Admin |
| 1205 | 1203 | || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){ |
| 1206 | - style_submenu_element("Edit", "Edit", "rptedit?rn=%d", rn); | |
| 1204 | + style_submenu_element("Edit", "rptedit?rn=%d", rn); | |
| 1207 | 1205 | } |
| 1208 | 1206 | if( g.perm.TktFmt ){ |
| 1209 | - style_submenu_element("SQL", "SQL", "rptsql?rn=%d",rn); | |
| 1207 | + style_submenu_element("SQL", "rptsql?rn=%d",rn); | |
| 1210 | 1208 | } |
| 1211 | 1209 | if( g.perm.NewTkt ){ |
| 1212 | - style_submenu_element("New Ticket", "Create a new ticket", | |
| 1213 | - "%s/tktnew", g.zTop); | |
| 1210 | + style_submenu_element("New Ticket", "%s/tktnew", g.zTop); | |
| 1214 | 1211 | } |
| 1215 | 1212 | style_header("%s", zTitle); |
| 1216 | 1213 | output_color_key(zClrKey, 1, |
| 1217 | 1214 | "border=\"0\" cellpadding=\"3\" cellspacing=\"0\" class=\"report\""); |
| 1218 | 1215 | @ <table border="1" cellpadding="2" cellspacing="0" class="report" |
| 1219 | 1216 |
| --- src/report.c | |
| +++ src/report.c | |
| @@ -198,14 +198,14 @@ | |
| 198 | }; |
| 199 | int i; |
| 200 | if( fossil_strncmp(zArg1, "fx_", 3)==0 ){ |
| 201 | break; |
| 202 | } |
| 203 | for(i=0; i<sizeof(azAllowed)/sizeof(azAllowed[0]); i++){ |
| 204 | if( fossil_stricmp(zArg1, azAllowed[i])==0 ) break; |
| 205 | } |
| 206 | if( i>=sizeof(azAllowed)/sizeof(azAllowed[0]) ){ |
| 207 | *(char**)pError = mprintf("access to table \"%s\" is restricted",zArg1); |
| 208 | rc = SQLITE_DENY; |
| 209 | }else if( !g.perm.RdAddr && strncmp(zArg2, "private_", 8)==0 ){ |
| 210 | rc = SQLITE_IGNORE; |
| 211 | } |
| @@ -450,13 +450,13 @@ | |
| 450 | zTitle = mprintf("Copy Of %s", zTitle); |
| 451 | zOwner = g.zLogin; |
| 452 | } |
| 453 | } |
| 454 | if( zOwner==0 ) zOwner = g.zLogin; |
| 455 | style_submenu_element("Cancel", "Cancel", "reportlist"); |
| 456 | if( rn>0 ){ |
| 457 | style_submenu_element("Delete", "Delete", "rptedit?rn=%d&del1=1", rn); |
| 458 | } |
| 459 | style_header("%s", rn>0 ? "Edit Report Format":"Create New Report Format"); |
| 460 | if( zErr ){ |
| 461 | @ <blockquote class="reportError">%h(zErr)</blockquote> |
| 462 | } |
| @@ -700,15 +700,14 @@ | |
| 700 | pState->zWikiEnd = ""; |
| 701 | if( P("plaintext") ){ |
| 702 | pState->wikiFlags |= WIKI_LINKSONLY; |
| 703 | pState->zWikiStart = "<pre class='verbatim'>"; |
| 704 | pState->zWikiEnd = "</pre>"; |
| 705 | style_submenu_element("Formatted", "Formatted", |
| 706 | "%R/rptview?rn=%d", pState->rn); |
| 707 | }else{ |
| 708 | style_submenu_element("Plaintext", "Plaintext", |
| 709 | "%R/rptview?rn=%d&plaintext", pState->rn); |
| 710 | } |
| 711 | }else{ |
| 712 | pState->nCol++; |
| 713 | } |
| 714 | } |
| @@ -1197,22 +1196,20 @@ | |
| 1197 | count = 0; |
| 1198 | if( !tabs ){ |
| 1199 | struct GenerateHTML sState = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
| 1200 | |
| 1201 | db_multi_exec("PRAGMA empty_result_callbacks=ON"); |
| 1202 | style_submenu_element("Raw", "Raw", |
| 1203 | "rptview?tablist=1&%h", PD("QUERY_STRING","")); |
| 1204 | if( g.perm.Admin |
| 1205 | || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){ |
| 1206 | style_submenu_element("Edit", "Edit", "rptedit?rn=%d", rn); |
| 1207 | } |
| 1208 | if( g.perm.TktFmt ){ |
| 1209 | style_submenu_element("SQL", "SQL", "rptsql?rn=%d",rn); |
| 1210 | } |
| 1211 | if( g.perm.NewTkt ){ |
| 1212 | style_submenu_element("New Ticket", "Create a new ticket", |
| 1213 | "%s/tktnew", g.zTop); |
| 1214 | } |
| 1215 | style_header("%s", zTitle); |
| 1216 | output_color_key(zClrKey, 1, |
| 1217 | "border=\"0\" cellpadding=\"3\" cellspacing=\"0\" class=\"report\""); |
| 1218 | @ <table border="1" cellpadding="2" cellspacing="0" class="report" |
| 1219 |
| --- src/report.c | |
| +++ src/report.c | |
| @@ -198,14 +198,14 @@ | |
| 198 | }; |
| 199 | int i; |
| 200 | if( fossil_strncmp(zArg1, "fx_", 3)==0 ){ |
| 201 | break; |
| 202 | } |
| 203 | for(i=0; i<count(azAllowed); i++){ |
| 204 | if( fossil_stricmp(zArg1, azAllowed[i])==0 ) break; |
| 205 | } |
| 206 | if( i>=count(azAllowed) ){ |
| 207 | *(char**)pError = mprintf("access to table \"%s\" is restricted",zArg1); |
| 208 | rc = SQLITE_DENY; |
| 209 | }else if( !g.perm.RdAddr && strncmp(zArg2, "private_", 8)==0 ){ |
| 210 | rc = SQLITE_IGNORE; |
| 211 | } |
| @@ -450,13 +450,13 @@ | |
| 450 | zTitle = mprintf("Copy Of %s", zTitle); |
| 451 | zOwner = g.zLogin; |
| 452 | } |
| 453 | } |
| 454 | if( zOwner==0 ) zOwner = g.zLogin; |
| 455 | style_submenu_element("Cancel", "reportlist"); |
| 456 | if( rn>0 ){ |
| 457 | style_submenu_element("Delete", "rptedit?rn=%d&del1=1", rn); |
| 458 | } |
| 459 | style_header("%s", rn>0 ? "Edit Report Format":"Create New Report Format"); |
| 460 | if( zErr ){ |
| 461 | @ <blockquote class="reportError">%h(zErr)</blockquote> |
| 462 | } |
| @@ -700,15 +700,14 @@ | |
| 700 | pState->zWikiEnd = ""; |
| 701 | if( P("plaintext") ){ |
| 702 | pState->wikiFlags |= WIKI_LINKSONLY; |
| 703 | pState->zWikiStart = "<pre class='verbatim'>"; |
| 704 | pState->zWikiEnd = "</pre>"; |
| 705 | style_submenu_element("Formatted", "%R/rptview?rn=%d", pState->rn); |
| 706 | }else{ |
| 707 | style_submenu_element("Plaintext", "%R/rptview?rn=%d&plaintext", |
| 708 | pState->rn); |
| 709 | } |
| 710 | }else{ |
| 711 | pState->nCol++; |
| 712 | } |
| 713 | } |
| @@ -1197,22 +1196,20 @@ | |
| 1196 | count = 0; |
| 1197 | if( !tabs ){ |
| 1198 | struct GenerateHTML sState = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
| 1199 | |
| 1200 | db_multi_exec("PRAGMA empty_result_callbacks=ON"); |
| 1201 | style_submenu_element("Raw", "rptview?tablist=1&%h", PD("QUERY_STRING","")); |
| 1202 | if( g.perm.Admin |
| 1203 | || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){ |
| 1204 | style_submenu_element("Edit", "rptedit?rn=%d", rn); |
| 1205 | } |
| 1206 | if( g.perm.TktFmt ){ |
| 1207 | style_submenu_element("SQL", "rptsql?rn=%d",rn); |
| 1208 | } |
| 1209 | if( g.perm.NewTkt ){ |
| 1210 | style_submenu_element("New Ticket", "%s/tktnew", g.zTop); |
| 1211 | } |
| 1212 | style_header("%s", zTitle); |
| 1213 | output_color_key(zClrKey, 1, |
| 1214 | "border=\"0\" cellpadding=\"3\" cellspacing=\"0\" class=\"report\""); |
| 1215 | @ <table border="1" cellpadding="2" cellspacing="0" class="report" |
| 1216 |
+1
-1
| --- src/rss.c | ||
| +++ src/rss.c | ||
| @@ -216,11 +216,11 @@ | ||
| 216 | 216 | free( zFreeProjectName ); |
| 217 | 217 | } |
| 218 | 218 | } |
| 219 | 219 | |
| 220 | 220 | /* |
| 221 | -** COMMAND: rss | |
| 221 | +** COMMAND: rss* | |
| 222 | 222 | ** |
| 223 | 223 | ** Usage: %fossil rss ?OPTIONS? |
| 224 | 224 | ** |
| 225 | 225 | ** The CLI variant of the /timeline.rss page, this produces an RSS |
| 226 | 226 | ** feed of the timeline to stdout. Options: |
| 227 | 227 |
| --- src/rss.c | |
| +++ src/rss.c | |
| @@ -216,11 +216,11 @@ | |
| 216 | free( zFreeProjectName ); |
| 217 | } |
| 218 | } |
| 219 | |
| 220 | /* |
| 221 | ** COMMAND: rss |
| 222 | ** |
| 223 | ** Usage: %fossil rss ?OPTIONS? |
| 224 | ** |
| 225 | ** The CLI variant of the /timeline.rss page, this produces an RSS |
| 226 | ** feed of the timeline to stdout. Options: |
| 227 |
| --- src/rss.c | |
| +++ src/rss.c | |
| @@ -216,11 +216,11 @@ | |
| 216 | free( zFreeProjectName ); |
| 217 | } |
| 218 | } |
| 219 | |
| 220 | /* |
| 221 | ** COMMAND: rss* |
| 222 | ** |
| 223 | ** Usage: %fossil rss ?OPTIONS? |
| 224 | ** |
| 225 | ** The CLI variant of the /timeline.rss page, this produces an RSS |
| 226 | ** feed of the timeline to stdout. Options: |
| 227 |
+10
-10
| --- src/search.c | ||
| +++ src/search.c | ||
| @@ -407,11 +407,11 @@ | ||
| 407 | 407 | |
| 408 | 408 | /* search_match(TEXT, TEXT, ....) |
| 409 | 409 | ** |
| 410 | 410 | ** Using the full-scan search engine created by the most recent call |
| 411 | 411 | ** to search_init(), match the input the TEXT arguments. |
| 412 | -** Remember the results global full-scan search object. | |
| 412 | +** Remember the results global full-scan search object. | |
| 413 | 413 | ** Return non-zero on a match and zero on a miss. |
| 414 | 414 | */ |
| 415 | 415 | static void search_match_sqlfunc( |
| 416 | 416 | sqlite3_context *context, |
| 417 | 417 | int argc, |
| @@ -418,11 +418,11 @@ | ||
| 418 | 418 | sqlite3_value **argv |
| 419 | 419 | ){ |
| 420 | 420 | const char *azDoc[5]; |
| 421 | 421 | int nDoc; |
| 422 | 422 | int rc; |
| 423 | - for(nDoc=0; nDoc<ArraySize(azDoc) && nDoc<argc; nDoc++){ | |
| 423 | + for(nDoc=0; nDoc<count(azDoc) && nDoc<argc; nDoc++){ | |
| 424 | 424 | azDoc[nDoc] = (const char*)sqlite3_value_text(argv[nDoc]); |
| 425 | 425 | if( azDoc[nDoc]==0 ) azDoc[nDoc] = ""; |
| 426 | 426 | } |
| 427 | 427 | rc = search_match(&gSearch, nDoc, azDoc); |
| 428 | 428 | sqlite3_result_int(context, rc); |
| @@ -657,11 +657,11 @@ | ||
| 657 | 657 | }; |
| 658 | 658 | int i; |
| 659 | 659 | if( g.perm.Read==0 ) srchFlags &= ~(SRCH_CKIN|SRCH_DOC); |
| 660 | 660 | if( g.perm.RdTkt==0 ) srchFlags &= ~(SRCH_TKT); |
| 661 | 661 | if( g.perm.RdWiki==0 ) srchFlags &= ~(SRCH_WIKI); |
| 662 | - for(i=0; i<ArraySize(aSetng); i++){ | |
| 662 | + for(i=0; i<count(aSetng); i++){ | |
| 663 | 663 | unsigned int m = aSetng[i].m; |
| 664 | 664 | if( (srchFlags & m)==0 ) continue; |
| 665 | 665 | if( ((knownGood|knownBad) & m)!=0 ) continue; |
| 666 | 666 | if( db_get_boolean(aSetng[i].zKey,0) ){ |
| 667 | 667 | knownGood |= m; |
| @@ -892,11 +892,11 @@ | ||
| 892 | 892 | { SRCH_DOC, 'd' }, |
| 893 | 893 | { SRCH_TKT, 't' }, |
| 894 | 894 | { SRCH_WIKI, 'w' }, |
| 895 | 895 | }; |
| 896 | 896 | int i; |
| 897 | - for(i=0; i<ArraySize(aMask); i++){ | |
| 897 | + for(i=0; i<count(aMask); i++){ | |
| 898 | 898 | if( srchFlags & aMask[i].m ){ |
| 899 | 899 | blob_appendf(&sql, "%sftsdocs.type='%c'", zSep, aMask[i].c); |
| 900 | 900 | zSep = " OR "; |
| 901 | 901 | } |
| 902 | 902 | } |
| @@ -1070,11 +1070,11 @@ | ||
| 1070 | 1070 | }; |
| 1071 | 1071 | const char *zY = PD("y","all"); |
| 1072 | 1072 | unsigned newFlags = srchFlags; |
| 1073 | 1073 | int i; |
| 1074 | 1074 | @ <select size='1' name='y'> |
| 1075 | - for(i=0; i<ArraySize(aY); i++){ | |
| 1075 | + for(i=0; i<count(aY); i++){ | |
| 1076 | 1076 | if( (aY[i].m & srchFlags)==0 ) continue; |
| 1077 | 1077 | cgi_printf("<option value='%s'", aY[i].z); |
| 1078 | 1078 | if( fossil_strcmp(zY,aY[i].z)==0 ){ |
| 1079 | 1079 | newFlags &= aY[i].m; |
| 1080 | 1080 | cgi_printf(" selected"); |
| @@ -1727,17 +1727,17 @@ | ||
| 1727 | 1727 | int iAction = 0; |
| 1728 | 1728 | db_find_and_open_repository(0, 0); |
| 1729 | 1729 | if( g.argc>2 ){ |
| 1730 | 1730 | zSubCmd = g.argv[2]; |
| 1731 | 1731 | n = (int)strlen(zSubCmd); |
| 1732 | - for(i=0; i<ArraySize(aCmd); i++){ | |
| 1732 | + for(i=0; i<count(aCmd); i++){ | |
| 1733 | 1733 | if( fossil_strncmp(aCmd[i].z, zSubCmd, n)==0 ) break; |
| 1734 | 1734 | } |
| 1735 | - if( i>=ArraySize(aCmd) ){ | |
| 1735 | + if( i>=count(aCmd) ){ | |
| 1736 | 1736 | Blob all; |
| 1737 | 1737 | blob_init(&all,0,0); |
| 1738 | - for(i=0; i<ArraySize(aCmd); i++) blob_appendf(&all, " %s", aCmd[i].z); | |
| 1738 | + for(i=0; i<count(aCmd); i++) blob_appendf(&all, " %s", aCmd[i].z); | |
| 1739 | 1739 | fossil_fatal("unknown \"%s\" - should be on of:%s", |
| 1740 | 1740 | zSubCmd, blob_str(&all)); |
| 1741 | 1741 | return; |
| 1742 | 1742 | } |
| 1743 | 1743 | iCmd = aCmd[i].iCmd; |
| @@ -1757,11 +1757,11 @@ | ||
| 1757 | 1757 | /* Adjust search settings */ |
| 1758 | 1758 | if( iCmd==3 || iCmd==4 ){ |
| 1759 | 1759 | const char *zCtrl; |
| 1760 | 1760 | if( g.argc<4 ) usage(mprintf("%s STRING",zSubCmd)); |
| 1761 | 1761 | zCtrl = g.argv[3]; |
| 1762 | - for(j=0; j<ArraySize(aSetng); j++){ | |
| 1762 | + for(j=0; j<count(aSetng); j++){ | |
| 1763 | 1763 | if( strchr(zCtrl, aSetng[j].zSw[0])!=0 ){ |
| 1764 | 1764 | db_set_int(aSetng[j].zSetting, iCmd-3, 0); |
| 1765 | 1765 | } |
| 1766 | 1766 | } |
| 1767 | 1767 | } |
| @@ -1778,11 +1778,11 @@ | ||
| 1778 | 1778 | if( iAction>=2 ){ |
| 1779 | 1779 | search_rebuild_index(); |
| 1780 | 1780 | } |
| 1781 | 1781 | |
| 1782 | 1782 | /* Always show the status before ending */ |
| 1783 | - for(i=0; i<ArraySize(aSetng); i++){ | |
| 1783 | + for(i=0; i<count(aSetng); i++){ | |
| 1784 | 1784 | fossil_print("%-16s %s\n", aSetng[i].zName, |
| 1785 | 1785 | db_get_boolean(aSetng[i].zSetting,0) ? "on" : "off"); |
| 1786 | 1786 | } |
| 1787 | 1787 | fossil_print("%-16s %s\n", "Porter stemmer:", |
| 1788 | 1788 | db_get_boolean("search-stemmer",0) ? "on" : "off"); |
| 1789 | 1789 |
| --- src/search.c | |
| +++ src/search.c | |
| @@ -407,11 +407,11 @@ | |
| 407 | |
| 408 | /* search_match(TEXT, TEXT, ....) |
| 409 | ** |
| 410 | ** Using the full-scan search engine created by the most recent call |
| 411 | ** to search_init(), match the input the TEXT arguments. |
| 412 | ** Remember the results global full-scan search object. |
| 413 | ** Return non-zero on a match and zero on a miss. |
| 414 | */ |
| 415 | static void search_match_sqlfunc( |
| 416 | sqlite3_context *context, |
| 417 | int argc, |
| @@ -418,11 +418,11 @@ | |
| 418 | sqlite3_value **argv |
| 419 | ){ |
| 420 | const char *azDoc[5]; |
| 421 | int nDoc; |
| 422 | int rc; |
| 423 | for(nDoc=0; nDoc<ArraySize(azDoc) && nDoc<argc; nDoc++){ |
| 424 | azDoc[nDoc] = (const char*)sqlite3_value_text(argv[nDoc]); |
| 425 | if( azDoc[nDoc]==0 ) azDoc[nDoc] = ""; |
| 426 | } |
| 427 | rc = search_match(&gSearch, nDoc, azDoc); |
| 428 | sqlite3_result_int(context, rc); |
| @@ -657,11 +657,11 @@ | |
| 657 | }; |
| 658 | int i; |
| 659 | if( g.perm.Read==0 ) srchFlags &= ~(SRCH_CKIN|SRCH_DOC); |
| 660 | if( g.perm.RdTkt==0 ) srchFlags &= ~(SRCH_TKT); |
| 661 | if( g.perm.RdWiki==0 ) srchFlags &= ~(SRCH_WIKI); |
| 662 | for(i=0; i<ArraySize(aSetng); i++){ |
| 663 | unsigned int m = aSetng[i].m; |
| 664 | if( (srchFlags & m)==0 ) continue; |
| 665 | if( ((knownGood|knownBad) & m)!=0 ) continue; |
| 666 | if( db_get_boolean(aSetng[i].zKey,0) ){ |
| 667 | knownGood |= m; |
| @@ -892,11 +892,11 @@ | |
| 892 | { SRCH_DOC, 'd' }, |
| 893 | { SRCH_TKT, 't' }, |
| 894 | { SRCH_WIKI, 'w' }, |
| 895 | }; |
| 896 | int i; |
| 897 | for(i=0; i<ArraySize(aMask); i++){ |
| 898 | if( srchFlags & aMask[i].m ){ |
| 899 | blob_appendf(&sql, "%sftsdocs.type='%c'", zSep, aMask[i].c); |
| 900 | zSep = " OR "; |
| 901 | } |
| 902 | } |
| @@ -1070,11 +1070,11 @@ | |
| 1070 | }; |
| 1071 | const char *zY = PD("y","all"); |
| 1072 | unsigned newFlags = srchFlags; |
| 1073 | int i; |
| 1074 | @ <select size='1' name='y'> |
| 1075 | for(i=0; i<ArraySize(aY); i++){ |
| 1076 | if( (aY[i].m & srchFlags)==0 ) continue; |
| 1077 | cgi_printf("<option value='%s'", aY[i].z); |
| 1078 | if( fossil_strcmp(zY,aY[i].z)==0 ){ |
| 1079 | newFlags &= aY[i].m; |
| 1080 | cgi_printf(" selected"); |
| @@ -1727,17 +1727,17 @@ | |
| 1727 | int iAction = 0; |
| 1728 | db_find_and_open_repository(0, 0); |
| 1729 | if( g.argc>2 ){ |
| 1730 | zSubCmd = g.argv[2]; |
| 1731 | n = (int)strlen(zSubCmd); |
| 1732 | for(i=0; i<ArraySize(aCmd); i++){ |
| 1733 | if( fossil_strncmp(aCmd[i].z, zSubCmd, n)==0 ) break; |
| 1734 | } |
| 1735 | if( i>=ArraySize(aCmd) ){ |
| 1736 | Blob all; |
| 1737 | blob_init(&all,0,0); |
| 1738 | for(i=0; i<ArraySize(aCmd); i++) blob_appendf(&all, " %s", aCmd[i].z); |
| 1739 | fossil_fatal("unknown \"%s\" - should be on of:%s", |
| 1740 | zSubCmd, blob_str(&all)); |
| 1741 | return; |
| 1742 | } |
| 1743 | iCmd = aCmd[i].iCmd; |
| @@ -1757,11 +1757,11 @@ | |
| 1757 | /* Adjust search settings */ |
| 1758 | if( iCmd==3 || iCmd==4 ){ |
| 1759 | const char *zCtrl; |
| 1760 | if( g.argc<4 ) usage(mprintf("%s STRING",zSubCmd)); |
| 1761 | zCtrl = g.argv[3]; |
| 1762 | for(j=0; j<ArraySize(aSetng); j++){ |
| 1763 | if( strchr(zCtrl, aSetng[j].zSw[0])!=0 ){ |
| 1764 | db_set_int(aSetng[j].zSetting, iCmd-3, 0); |
| 1765 | } |
| 1766 | } |
| 1767 | } |
| @@ -1778,11 +1778,11 @@ | |
| 1778 | if( iAction>=2 ){ |
| 1779 | search_rebuild_index(); |
| 1780 | } |
| 1781 | |
| 1782 | /* Always show the status before ending */ |
| 1783 | for(i=0; i<ArraySize(aSetng); i++){ |
| 1784 | fossil_print("%-16s %s\n", aSetng[i].zName, |
| 1785 | db_get_boolean(aSetng[i].zSetting,0) ? "on" : "off"); |
| 1786 | } |
| 1787 | fossil_print("%-16s %s\n", "Porter stemmer:", |
| 1788 | db_get_boolean("search-stemmer",0) ? "on" : "off"); |
| 1789 |
| --- src/search.c | |
| +++ src/search.c | |
| @@ -407,11 +407,11 @@ | |
| 407 | |
| 408 | /* search_match(TEXT, TEXT, ....) |
| 409 | ** |
| 410 | ** Using the full-scan search engine created by the most recent call |
| 411 | ** to search_init(), match the input the TEXT arguments. |
| 412 | ** Remember the results global full-scan search object. |
| 413 | ** Return non-zero on a match and zero on a miss. |
| 414 | */ |
| 415 | static void search_match_sqlfunc( |
| 416 | sqlite3_context *context, |
| 417 | int argc, |
| @@ -418,11 +418,11 @@ | |
| 418 | sqlite3_value **argv |
| 419 | ){ |
| 420 | const char *azDoc[5]; |
| 421 | int nDoc; |
| 422 | int rc; |
| 423 | for(nDoc=0; nDoc<count(azDoc) && nDoc<argc; nDoc++){ |
| 424 | azDoc[nDoc] = (const char*)sqlite3_value_text(argv[nDoc]); |
| 425 | if( azDoc[nDoc]==0 ) azDoc[nDoc] = ""; |
| 426 | } |
| 427 | rc = search_match(&gSearch, nDoc, azDoc); |
| 428 | sqlite3_result_int(context, rc); |
| @@ -657,11 +657,11 @@ | |
| 657 | }; |
| 658 | int i; |
| 659 | if( g.perm.Read==0 ) srchFlags &= ~(SRCH_CKIN|SRCH_DOC); |
| 660 | if( g.perm.RdTkt==0 ) srchFlags &= ~(SRCH_TKT); |
| 661 | if( g.perm.RdWiki==0 ) srchFlags &= ~(SRCH_WIKI); |
| 662 | for(i=0; i<count(aSetng); i++){ |
| 663 | unsigned int m = aSetng[i].m; |
| 664 | if( (srchFlags & m)==0 ) continue; |
| 665 | if( ((knownGood|knownBad) & m)!=0 ) continue; |
| 666 | if( db_get_boolean(aSetng[i].zKey,0) ){ |
| 667 | knownGood |= m; |
| @@ -892,11 +892,11 @@ | |
| 892 | { SRCH_DOC, 'd' }, |
| 893 | { SRCH_TKT, 't' }, |
| 894 | { SRCH_WIKI, 'w' }, |
| 895 | }; |
| 896 | int i; |
| 897 | for(i=0; i<count(aMask); i++){ |
| 898 | if( srchFlags & aMask[i].m ){ |
| 899 | blob_appendf(&sql, "%sftsdocs.type='%c'", zSep, aMask[i].c); |
| 900 | zSep = " OR "; |
| 901 | } |
| 902 | } |
| @@ -1070,11 +1070,11 @@ | |
| 1070 | }; |
| 1071 | const char *zY = PD("y","all"); |
| 1072 | unsigned newFlags = srchFlags; |
| 1073 | int i; |
| 1074 | @ <select size='1' name='y'> |
| 1075 | for(i=0; i<count(aY); i++){ |
| 1076 | if( (aY[i].m & srchFlags)==0 ) continue; |
| 1077 | cgi_printf("<option value='%s'", aY[i].z); |
| 1078 | if( fossil_strcmp(zY,aY[i].z)==0 ){ |
| 1079 | newFlags &= aY[i].m; |
| 1080 | cgi_printf(" selected"); |
| @@ -1727,17 +1727,17 @@ | |
| 1727 | int iAction = 0; |
| 1728 | db_find_and_open_repository(0, 0); |
| 1729 | if( g.argc>2 ){ |
| 1730 | zSubCmd = g.argv[2]; |
| 1731 | n = (int)strlen(zSubCmd); |
| 1732 | for(i=0; i<count(aCmd); i++){ |
| 1733 | if( fossil_strncmp(aCmd[i].z, zSubCmd, n)==0 ) break; |
| 1734 | } |
| 1735 | if( i>=count(aCmd) ){ |
| 1736 | Blob all; |
| 1737 | blob_init(&all,0,0); |
| 1738 | for(i=0; i<count(aCmd); i++) blob_appendf(&all, " %s", aCmd[i].z); |
| 1739 | fossil_fatal("unknown \"%s\" - should be on of:%s", |
| 1740 | zSubCmd, blob_str(&all)); |
| 1741 | return; |
| 1742 | } |
| 1743 | iCmd = aCmd[i].iCmd; |
| @@ -1757,11 +1757,11 @@ | |
| 1757 | /* Adjust search settings */ |
| 1758 | if( iCmd==3 || iCmd==4 ){ |
| 1759 | const char *zCtrl; |
| 1760 | if( g.argc<4 ) usage(mprintf("%s STRING",zSubCmd)); |
| 1761 | zCtrl = g.argv[3]; |
| 1762 | for(j=0; j<count(aSetng); j++){ |
| 1763 | if( strchr(zCtrl, aSetng[j].zSw[0])!=0 ){ |
| 1764 | db_set_int(aSetng[j].zSetting, iCmd-3, 0); |
| 1765 | } |
| 1766 | } |
| 1767 | } |
| @@ -1778,11 +1778,11 @@ | |
| 1778 | if( iAction>=2 ){ |
| 1779 | search_rebuild_index(); |
| 1780 | } |
| 1781 | |
| 1782 | /* Always show the status before ending */ |
| 1783 | for(i=0; i<count(aSetng); i++){ |
| 1784 | fossil_print("%-16s %s\n", aSetng[i].zName, |
| 1785 | db_get_boolean(aSetng[i].zSetting,0) ? "on" : "off"); |
| 1786 | } |
| 1787 | fossil_print("%-16s %s\n", "Porter stemmer:", |
| 1788 | db_get_boolean("search-stemmer",0) ? "on" : "off"); |
| 1789 |
+8
-12
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -19,14 +19,10 @@ | ||
| 19 | 19 | */ |
| 20 | 20 | #include "config.h" |
| 21 | 21 | #include <assert.h> |
| 22 | 22 | #include "setup.h" |
| 23 | 23 | |
| 24 | -#if INTERFACE | |
| 25 | -#define ArraySize(x) (sizeof(x)/sizeof(x[0])) | |
| 26 | -#endif | |
| 27 | - | |
| 28 | 24 | /* |
| 29 | 25 | ** Output a single entry for a menu generated using an HTML table. |
| 30 | 26 | ** If zLink is not NULL or an empty string, then it is the page that |
| 31 | 27 | ** the menu entry will hyperlink to. If zLink is NULL or "", then |
| 32 | 28 | ** the menu entry has no hyperlink - it is disabled. |
| @@ -149,13 +145,13 @@ | ||
| 149 | 145 | if( !g.perm.Admin ){ |
| 150 | 146 | login_needed(0); |
| 151 | 147 | return; |
| 152 | 148 | } |
| 153 | 149 | |
| 154 | - style_submenu_element("Add", "Add User", "setup_uedit"); | |
| 155 | - style_submenu_element("Log", "Access Log", "access_log"); | |
| 156 | - style_submenu_element("Help", "Help", "setup_ulist_notes"); | |
| 150 | + style_submenu_element("Add", "setup_uedit"); | |
| 151 | + style_submenu_element("Log", "access_log"); | |
| 152 | + style_submenu_element("Help", "setup_ulist_notes"); | |
| 157 | 153 | style_header("User List"); |
| 158 | 154 | @ <table border=1 cellpadding=2 cellspacing=0 class='userTable'> |
| 159 | 155 | @ <thead><tr> |
| 160 | 156 | @ <th>UID <th>Category |
| 161 | 157 | @ <th>Capabilities (<a href='%R/setup_ucap_list'>key</a>) |
| @@ -557,11 +553,11 @@ | ||
| 557 | 553 | free(z2); |
| 558 | 554 | } |
| 559 | 555 | |
| 560 | 556 | /* Begin generating the page |
| 561 | 557 | */ |
| 562 | - style_submenu_element("Cancel", "Cancel", "setup_ulist"); | |
| 558 | + style_submenu_element("Cancel", "setup_ulist"); | |
| 563 | 559 | if( uid ){ |
| 564 | 560 | style_header("Edit User %h", zLogin); |
| 565 | 561 | }else{ |
| 566 | 562 | style_header("Add A New User"); |
| 567 | 563 | } |
| @@ -944,18 +940,18 @@ | ||
| 944 | 940 | admin_log("Set option [%q] to [%q].", |
| 945 | 941 | zVar, iQ ? "on" : "off"); |
| 946 | 942 | iVal = iQ; |
| 947 | 943 | } |
| 948 | 944 | } |
| 949 | - @ <input type="checkbox" name="%s(zQParm)" | |
| 945 | + @ <label><input type="checkbox" name="%s(zQParm)" | |
| 950 | 946 | if( iVal ){ |
| 951 | 947 | @ checked="checked" |
| 952 | 948 | } |
| 953 | 949 | if( disabled ){ |
| 954 | 950 | @ disabled="disabled" |
| 955 | 951 | } |
| 956 | - @ /> <b>%s(zLabel)</b> | |
| 952 | + @ /> <b>%s(zLabel)</b></label> | |
| 957 | 953 | } |
| 958 | 954 | |
| 959 | 955 | /* |
| 960 | 956 | ** Generate an entry box for an attribute. |
| 961 | 957 | */ |
| @@ -1431,11 +1427,11 @@ | ||
| 1431 | 1427 | @ %s(zTmDiff) hours ahead of UTC.</p> |
| 1432 | 1428 | } |
| 1433 | 1429 | |
| 1434 | 1430 | @ <hr /> |
| 1435 | 1431 | multiple_choice_attribute("Per-Item Time Format", "timeline-date-format", |
| 1436 | - "tdf", "0", ArraySize(azTimeFormats)/2, azTimeFormats); | |
| 1432 | + "tdf", "0", count(azTimeFormats)/2, azTimeFormats); | |
| 1437 | 1433 | @ <p>If the "HH:MM" or "HH:MM:SS" format is selected, then the date is shown |
| 1438 | 1434 | @ in a separate box (using CSS class "timelineDate") whenever the date changes. |
| 1439 | 1435 | @ With the "YYYY-MM-DD HH:MM" and "YYMMDD ..." formats, the complete date |
| 1440 | 1436 | @ and time is shown on every timeline entry (using the CSS class "timelineTime").</p> |
| 1441 | 1437 | |
| @@ -1537,11 +1533,11 @@ | ||
| 1537 | 1533 | @ <p>Settings marked with (v) are 'versionable' and will be overridden |
| 1538 | 1534 | @ by the contents of files named <tt>.fossil-settings/PROPERTY</tt> |
| 1539 | 1535 | @ in the check-out root. |
| 1540 | 1536 | @ If such a file is present, the corresponding field above is not |
| 1541 | 1537 | @ editable.</p><hr /><p> |
| 1542 | - @ These settings work the same as the | |
| 1538 | + @ These settings work the same as the | |
| 1543 | 1539 | @ <a href='%R/help?cmd=settings'>fossil set</a> command. |
| 1544 | 1540 | db_end_transaction(0); |
| 1545 | 1541 | style_footer(); |
| 1546 | 1542 | } |
| 1547 | 1543 | |
| 1548 | 1544 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -19,14 +19,10 @@ | |
| 19 | */ |
| 20 | #include "config.h" |
| 21 | #include <assert.h> |
| 22 | #include "setup.h" |
| 23 | |
| 24 | #if INTERFACE |
| 25 | #define ArraySize(x) (sizeof(x)/sizeof(x[0])) |
| 26 | #endif |
| 27 | |
| 28 | /* |
| 29 | ** Output a single entry for a menu generated using an HTML table. |
| 30 | ** If zLink is not NULL or an empty string, then it is the page that |
| 31 | ** the menu entry will hyperlink to. If zLink is NULL or "", then |
| 32 | ** the menu entry has no hyperlink - it is disabled. |
| @@ -149,13 +145,13 @@ | |
| 149 | if( !g.perm.Admin ){ |
| 150 | login_needed(0); |
| 151 | return; |
| 152 | } |
| 153 | |
| 154 | style_submenu_element("Add", "Add User", "setup_uedit"); |
| 155 | style_submenu_element("Log", "Access Log", "access_log"); |
| 156 | style_submenu_element("Help", "Help", "setup_ulist_notes"); |
| 157 | style_header("User List"); |
| 158 | @ <table border=1 cellpadding=2 cellspacing=0 class='userTable'> |
| 159 | @ <thead><tr> |
| 160 | @ <th>UID <th>Category |
| 161 | @ <th>Capabilities (<a href='%R/setup_ucap_list'>key</a>) |
| @@ -557,11 +553,11 @@ | |
| 557 | free(z2); |
| 558 | } |
| 559 | |
| 560 | /* Begin generating the page |
| 561 | */ |
| 562 | style_submenu_element("Cancel", "Cancel", "setup_ulist"); |
| 563 | if( uid ){ |
| 564 | style_header("Edit User %h", zLogin); |
| 565 | }else{ |
| 566 | style_header("Add A New User"); |
| 567 | } |
| @@ -944,18 +940,18 @@ | |
| 944 | admin_log("Set option [%q] to [%q].", |
| 945 | zVar, iQ ? "on" : "off"); |
| 946 | iVal = iQ; |
| 947 | } |
| 948 | } |
| 949 | @ <input type="checkbox" name="%s(zQParm)" |
| 950 | if( iVal ){ |
| 951 | @ checked="checked" |
| 952 | } |
| 953 | if( disabled ){ |
| 954 | @ disabled="disabled" |
| 955 | } |
| 956 | @ /> <b>%s(zLabel)</b> |
| 957 | } |
| 958 | |
| 959 | /* |
| 960 | ** Generate an entry box for an attribute. |
| 961 | */ |
| @@ -1431,11 +1427,11 @@ | |
| 1431 | @ %s(zTmDiff) hours ahead of UTC.</p> |
| 1432 | } |
| 1433 | |
| 1434 | @ <hr /> |
| 1435 | multiple_choice_attribute("Per-Item Time Format", "timeline-date-format", |
| 1436 | "tdf", "0", ArraySize(azTimeFormats)/2, azTimeFormats); |
| 1437 | @ <p>If the "HH:MM" or "HH:MM:SS" format is selected, then the date is shown |
| 1438 | @ in a separate box (using CSS class "timelineDate") whenever the date changes. |
| 1439 | @ With the "YYYY-MM-DD HH:MM" and "YYMMDD ..." formats, the complete date |
| 1440 | @ and time is shown on every timeline entry (using the CSS class "timelineTime").</p> |
| 1441 | |
| @@ -1537,11 +1533,11 @@ | |
| 1537 | @ <p>Settings marked with (v) are 'versionable' and will be overridden |
| 1538 | @ by the contents of files named <tt>.fossil-settings/PROPERTY</tt> |
| 1539 | @ in the check-out root. |
| 1540 | @ If such a file is present, the corresponding field above is not |
| 1541 | @ editable.</p><hr /><p> |
| 1542 | @ These settings work the same as the |
| 1543 | @ <a href='%R/help?cmd=settings'>fossil set</a> command. |
| 1544 | db_end_transaction(0); |
| 1545 | style_footer(); |
| 1546 | } |
| 1547 | |
| 1548 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -19,14 +19,10 @@ | |
| 19 | */ |
| 20 | #include "config.h" |
| 21 | #include <assert.h> |
| 22 | #include "setup.h" |
| 23 | |
| 24 | /* |
| 25 | ** Output a single entry for a menu generated using an HTML table. |
| 26 | ** If zLink is not NULL or an empty string, then it is the page that |
| 27 | ** the menu entry will hyperlink to. If zLink is NULL or "", then |
| 28 | ** the menu entry has no hyperlink - it is disabled. |
| @@ -149,13 +145,13 @@ | |
| 145 | if( !g.perm.Admin ){ |
| 146 | login_needed(0); |
| 147 | return; |
| 148 | } |
| 149 | |
| 150 | style_submenu_element("Add", "setup_uedit"); |
| 151 | style_submenu_element("Log", "access_log"); |
| 152 | style_submenu_element("Help", "setup_ulist_notes"); |
| 153 | style_header("User List"); |
| 154 | @ <table border=1 cellpadding=2 cellspacing=0 class='userTable'> |
| 155 | @ <thead><tr> |
| 156 | @ <th>UID <th>Category |
| 157 | @ <th>Capabilities (<a href='%R/setup_ucap_list'>key</a>) |
| @@ -557,11 +553,11 @@ | |
| 553 | free(z2); |
| 554 | } |
| 555 | |
| 556 | /* Begin generating the page |
| 557 | */ |
| 558 | style_submenu_element("Cancel", "setup_ulist"); |
| 559 | if( uid ){ |
| 560 | style_header("Edit User %h", zLogin); |
| 561 | }else{ |
| 562 | style_header("Add A New User"); |
| 563 | } |
| @@ -944,18 +940,18 @@ | |
| 940 | admin_log("Set option [%q] to [%q].", |
| 941 | zVar, iQ ? "on" : "off"); |
| 942 | iVal = iQ; |
| 943 | } |
| 944 | } |
| 945 | @ <label><input type="checkbox" name="%s(zQParm)" |
| 946 | if( iVal ){ |
| 947 | @ checked="checked" |
| 948 | } |
| 949 | if( disabled ){ |
| 950 | @ disabled="disabled" |
| 951 | } |
| 952 | @ /> <b>%s(zLabel)</b></label> |
| 953 | } |
| 954 | |
| 955 | /* |
| 956 | ** Generate an entry box for an attribute. |
| 957 | */ |
| @@ -1431,11 +1427,11 @@ | |
| 1427 | @ %s(zTmDiff) hours ahead of UTC.</p> |
| 1428 | } |
| 1429 | |
| 1430 | @ <hr /> |
| 1431 | multiple_choice_attribute("Per-Item Time Format", "timeline-date-format", |
| 1432 | "tdf", "0", count(azTimeFormats)/2, azTimeFormats); |
| 1433 | @ <p>If the "HH:MM" or "HH:MM:SS" format is selected, then the date is shown |
| 1434 | @ in a separate box (using CSS class "timelineDate") whenever the date changes. |
| 1435 | @ With the "YYYY-MM-DD HH:MM" and "YYMMDD ..." formats, the complete date |
| 1436 | @ and time is shown on every timeline entry (using the CSS class "timelineTime").</p> |
| 1437 | |
| @@ -1537,11 +1533,11 @@ | |
| 1533 | @ <p>Settings marked with (v) are 'versionable' and will be overridden |
| 1534 | @ by the contents of files named <tt>.fossil-settings/PROPERTY</tt> |
| 1535 | @ in the check-out root. |
| 1536 | @ If such a file is present, the corresponding field above is not |
| 1537 | @ editable.</p><hr /><p> |
| 1538 | @ These settings work the same as the |
| 1539 | @ <a href='%R/help?cmd=settings'>fossil set</a> command. |
| 1540 | db_end_transaction(0); |
| 1541 | style_footer(); |
| 1542 | } |
| 1543 | |
| 1544 |
+24
-16
| --- src/shell.c | ||
| +++ src/shell.c | ||
| @@ -666,23 +666,25 @@ | ||
| 666 | 666 | #define MODE_Column 1 /* One record per line in neat columns */ |
| 667 | 667 | #define MODE_List 2 /* One record per line with a separator */ |
| 668 | 668 | #define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */ |
| 669 | 669 | #define MODE_Html 4 /* Generate an XHTML table */ |
| 670 | 670 | #define MODE_Insert 5 /* Generate SQL "insert" statements */ |
| 671 | -#define MODE_Tcl 6 /* Generate ANSI-C or TCL quoted elements */ | |
| 672 | -#define MODE_Csv 7 /* Quote strings, numbers are plain */ | |
| 673 | -#define MODE_Explain 8 /* Like MODE_Column, but do not truncate data */ | |
| 674 | -#define MODE_Ascii 9 /* Use ASCII unit and record separators (0x1F/0x1E) */ | |
| 675 | -#define MODE_Pretty 10 /* Pretty-print schemas */ | |
| 671 | +#define MODE_Quote 6 /* Quote values as for SQL */ | |
| 672 | +#define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */ | |
| 673 | +#define MODE_Csv 8 /* Quote strings, numbers are plain */ | |
| 674 | +#define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */ | |
| 675 | +#define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */ | |
| 676 | +#define MODE_Pretty 11 /* Pretty-print schemas */ | |
| 676 | 677 | |
| 677 | 678 | static const char *modeDescr[] = { |
| 678 | 679 | "line", |
| 679 | 680 | "column", |
| 680 | 681 | "list", |
| 681 | 682 | "semi", |
| 682 | 683 | "html", |
| 683 | 684 | "insert", |
| 685 | + "quote", | |
| 684 | 686 | "tcl", |
| 685 | 687 | "csv", |
| 686 | 688 | "explain", |
| 687 | 689 | "ascii", |
| 688 | 690 | "prettyprint", |
| @@ -1196,23 +1198,26 @@ | ||
| 1196 | 1198 | utf8_printf(p->out, "%s", p->rowSeparator); |
| 1197 | 1199 | } |
| 1198 | 1200 | setTextMode(p->out, 1); |
| 1199 | 1201 | break; |
| 1200 | 1202 | } |
| 1203 | + case MODE_Quote: | |
| 1201 | 1204 | case MODE_Insert: { |
| 1202 | 1205 | p->cnt++; |
| 1203 | 1206 | if( azArg==0 ) break; |
| 1204 | - utf8_printf(p->out,"INSERT INTO %s",p->zDestTable); | |
| 1205 | - if( p->showHeader ){ | |
| 1206 | - raw_printf(p->out,"("); | |
| 1207 | - for(i=0; i<nArg; i++){ | |
| 1208 | - char *zSep = i>0 ? ",": ""; | |
| 1209 | - utf8_printf(p->out, "%s%s", zSep, azCol[i]); | |
| 1210 | - } | |
| 1211 | - raw_printf(p->out,")"); | |
| 1212 | - } | |
| 1213 | - raw_printf(p->out," VALUES("); | |
| 1207 | + if( p->cMode==MODE_Insert ){ | |
| 1208 | + utf8_printf(p->out,"INSERT INTO %s",p->zDestTable); | |
| 1209 | + if( p->showHeader ){ | |
| 1210 | + raw_printf(p->out,"("); | |
| 1211 | + for(i=0; i<nArg; i++){ | |
| 1212 | + char *zSep = i>0 ? ",": ""; | |
| 1213 | + utf8_printf(p->out, "%s%s", zSep, azCol[i]); | |
| 1214 | + } | |
| 1215 | + raw_printf(p->out,")"); | |
| 1216 | + } | |
| 1217 | + raw_printf(p->out," VALUES("); | |
| 1218 | + } | |
| 1214 | 1219 | for(i=0; i<nArg; i++){ |
| 1215 | 1220 | char *zSep = i>0 ? ",": ""; |
| 1216 | 1221 | if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ |
| 1217 | 1222 | utf8_printf(p->out,"%sNULL",zSep); |
| 1218 | 1223 | }else if( aiType && aiType[i]==SQLITE_TEXT ){ |
| @@ -1231,11 +1236,11 @@ | ||
| 1231 | 1236 | }else{ |
| 1232 | 1237 | if( zSep[0] ) utf8_printf(p->out,"%s",zSep); |
| 1233 | 1238 | output_quoted_string(p->out, azArg[i]); |
| 1234 | 1239 | } |
| 1235 | 1240 | } |
| 1236 | - raw_printf(p->out,");\n"); | |
| 1241 | + raw_printf(p->out,p->cMode==MODE_Quote?"\n":");\n"); | |
| 1237 | 1242 | break; |
| 1238 | 1243 | } |
| 1239 | 1244 | case MODE_Ascii: { |
| 1240 | 1245 | if( p->cnt++==0 && p->showHeader ){ |
| 1241 | 1246 | for(i=0; i<nArg; i++){ |
| @@ -2175,10 +2180,11 @@ | ||
| 2175 | 2180 | " column Left-aligned columns. (See .width)\n" |
| 2176 | 2181 | " html HTML <table> code\n" |
| 2177 | 2182 | " insert SQL insert statements for TABLE\n" |
| 2178 | 2183 | " line One value per line\n" |
| 2179 | 2184 | " list Values delimited by .separator strings\n" |
| 2185 | + " quote Escape answers as for SQL\n" | |
| 2180 | 2186 | " tabs Tab-separated values\n" |
| 2181 | 2187 | " tcl TCL list elements\n" |
| 2182 | 2188 | ".nullvalue STRING Use STRING in place of NULL values\n" |
| 2183 | 2189 | ".once FILENAME Output for the next SQL command only to FILENAME\n" |
| 2184 | 2190 | ".open ?--new? ?FILE? Close existing database and reopen FILE\n" |
| @@ -3975,10 +3981,12 @@ | ||
| 3975 | 3981 | p->mode = MODE_List; |
| 3976 | 3982 | sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab); |
| 3977 | 3983 | }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){ |
| 3978 | 3984 | p->mode = MODE_Insert; |
| 3979 | 3985 | set_table_name(p, nArg>=3 ? azArg[2] : "table"); |
| 3986 | + }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){ | |
| 3987 | + p->mode = MODE_Quote; | |
| 3980 | 3988 | }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){ |
| 3981 | 3989 | p->mode = MODE_Ascii; |
| 3982 | 3990 | sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit); |
| 3983 | 3991 | sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record); |
| 3984 | 3992 | }else { |
| 3985 | 3993 |
| --- src/shell.c | |
| +++ src/shell.c | |
| @@ -666,23 +666,25 @@ | |
| 666 | #define MODE_Column 1 /* One record per line in neat columns */ |
| 667 | #define MODE_List 2 /* One record per line with a separator */ |
| 668 | #define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */ |
| 669 | #define MODE_Html 4 /* Generate an XHTML table */ |
| 670 | #define MODE_Insert 5 /* Generate SQL "insert" statements */ |
| 671 | #define MODE_Tcl 6 /* Generate ANSI-C or TCL quoted elements */ |
| 672 | #define MODE_Csv 7 /* Quote strings, numbers are plain */ |
| 673 | #define MODE_Explain 8 /* Like MODE_Column, but do not truncate data */ |
| 674 | #define MODE_Ascii 9 /* Use ASCII unit and record separators (0x1F/0x1E) */ |
| 675 | #define MODE_Pretty 10 /* Pretty-print schemas */ |
| 676 | |
| 677 | static const char *modeDescr[] = { |
| 678 | "line", |
| 679 | "column", |
| 680 | "list", |
| 681 | "semi", |
| 682 | "html", |
| 683 | "insert", |
| 684 | "tcl", |
| 685 | "csv", |
| 686 | "explain", |
| 687 | "ascii", |
| 688 | "prettyprint", |
| @@ -1196,23 +1198,26 @@ | |
| 1196 | utf8_printf(p->out, "%s", p->rowSeparator); |
| 1197 | } |
| 1198 | setTextMode(p->out, 1); |
| 1199 | break; |
| 1200 | } |
| 1201 | case MODE_Insert: { |
| 1202 | p->cnt++; |
| 1203 | if( azArg==0 ) break; |
| 1204 | utf8_printf(p->out,"INSERT INTO %s",p->zDestTable); |
| 1205 | if( p->showHeader ){ |
| 1206 | raw_printf(p->out,"("); |
| 1207 | for(i=0; i<nArg; i++){ |
| 1208 | char *zSep = i>0 ? ",": ""; |
| 1209 | utf8_printf(p->out, "%s%s", zSep, azCol[i]); |
| 1210 | } |
| 1211 | raw_printf(p->out,")"); |
| 1212 | } |
| 1213 | raw_printf(p->out," VALUES("); |
| 1214 | for(i=0; i<nArg; i++){ |
| 1215 | char *zSep = i>0 ? ",": ""; |
| 1216 | if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ |
| 1217 | utf8_printf(p->out,"%sNULL",zSep); |
| 1218 | }else if( aiType && aiType[i]==SQLITE_TEXT ){ |
| @@ -1231,11 +1236,11 @@ | |
| 1231 | }else{ |
| 1232 | if( zSep[0] ) utf8_printf(p->out,"%s",zSep); |
| 1233 | output_quoted_string(p->out, azArg[i]); |
| 1234 | } |
| 1235 | } |
| 1236 | raw_printf(p->out,");\n"); |
| 1237 | break; |
| 1238 | } |
| 1239 | case MODE_Ascii: { |
| 1240 | if( p->cnt++==0 && p->showHeader ){ |
| 1241 | for(i=0; i<nArg; i++){ |
| @@ -2175,10 +2180,11 @@ | |
| 2175 | " column Left-aligned columns. (See .width)\n" |
| 2176 | " html HTML <table> code\n" |
| 2177 | " insert SQL insert statements for TABLE\n" |
| 2178 | " line One value per line\n" |
| 2179 | " list Values delimited by .separator strings\n" |
| 2180 | " tabs Tab-separated values\n" |
| 2181 | " tcl TCL list elements\n" |
| 2182 | ".nullvalue STRING Use STRING in place of NULL values\n" |
| 2183 | ".once FILENAME Output for the next SQL command only to FILENAME\n" |
| 2184 | ".open ?--new? ?FILE? Close existing database and reopen FILE\n" |
| @@ -3975,10 +3981,12 @@ | |
| 3975 | p->mode = MODE_List; |
| 3976 | sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab); |
| 3977 | }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){ |
| 3978 | p->mode = MODE_Insert; |
| 3979 | set_table_name(p, nArg>=3 ? azArg[2] : "table"); |
| 3980 | }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){ |
| 3981 | p->mode = MODE_Ascii; |
| 3982 | sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit); |
| 3983 | sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record); |
| 3984 | }else { |
| 3985 |
| --- src/shell.c | |
| +++ src/shell.c | |
| @@ -666,23 +666,25 @@ | |
| 666 | #define MODE_Column 1 /* One record per line in neat columns */ |
| 667 | #define MODE_List 2 /* One record per line with a separator */ |
| 668 | #define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */ |
| 669 | #define MODE_Html 4 /* Generate an XHTML table */ |
| 670 | #define MODE_Insert 5 /* Generate SQL "insert" statements */ |
| 671 | #define MODE_Quote 6 /* Quote values as for SQL */ |
| 672 | #define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */ |
| 673 | #define MODE_Csv 8 /* Quote strings, numbers are plain */ |
| 674 | #define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */ |
| 675 | #define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */ |
| 676 | #define MODE_Pretty 11 /* Pretty-print schemas */ |
| 677 | |
| 678 | static const char *modeDescr[] = { |
| 679 | "line", |
| 680 | "column", |
| 681 | "list", |
| 682 | "semi", |
| 683 | "html", |
| 684 | "insert", |
| 685 | "quote", |
| 686 | "tcl", |
| 687 | "csv", |
| 688 | "explain", |
| 689 | "ascii", |
| 690 | "prettyprint", |
| @@ -1196,23 +1198,26 @@ | |
| 1198 | utf8_printf(p->out, "%s", p->rowSeparator); |
| 1199 | } |
| 1200 | setTextMode(p->out, 1); |
| 1201 | break; |
| 1202 | } |
| 1203 | case MODE_Quote: |
| 1204 | case MODE_Insert: { |
| 1205 | p->cnt++; |
| 1206 | if( azArg==0 ) break; |
| 1207 | if( p->cMode==MODE_Insert ){ |
| 1208 | utf8_printf(p->out,"INSERT INTO %s",p->zDestTable); |
| 1209 | if( p->showHeader ){ |
| 1210 | raw_printf(p->out,"("); |
| 1211 | for(i=0; i<nArg; i++){ |
| 1212 | char *zSep = i>0 ? ",": ""; |
| 1213 | utf8_printf(p->out, "%s%s", zSep, azCol[i]); |
| 1214 | } |
| 1215 | raw_printf(p->out,")"); |
| 1216 | } |
| 1217 | raw_printf(p->out," VALUES("); |
| 1218 | } |
| 1219 | for(i=0; i<nArg; i++){ |
| 1220 | char *zSep = i>0 ? ",": ""; |
| 1221 | if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ |
| 1222 | utf8_printf(p->out,"%sNULL",zSep); |
| 1223 | }else if( aiType && aiType[i]==SQLITE_TEXT ){ |
| @@ -1231,11 +1236,11 @@ | |
| 1236 | }else{ |
| 1237 | if( zSep[0] ) utf8_printf(p->out,"%s",zSep); |
| 1238 | output_quoted_string(p->out, azArg[i]); |
| 1239 | } |
| 1240 | } |
| 1241 | raw_printf(p->out,p->cMode==MODE_Quote?"\n":");\n"); |
| 1242 | break; |
| 1243 | } |
| 1244 | case MODE_Ascii: { |
| 1245 | if( p->cnt++==0 && p->showHeader ){ |
| 1246 | for(i=0; i<nArg; i++){ |
| @@ -2175,10 +2180,11 @@ | |
| 2180 | " column Left-aligned columns. (See .width)\n" |
| 2181 | " html HTML <table> code\n" |
| 2182 | " insert SQL insert statements for TABLE\n" |
| 2183 | " line One value per line\n" |
| 2184 | " list Values delimited by .separator strings\n" |
| 2185 | " quote Escape answers as for SQL\n" |
| 2186 | " tabs Tab-separated values\n" |
| 2187 | " tcl TCL list elements\n" |
| 2188 | ".nullvalue STRING Use STRING in place of NULL values\n" |
| 2189 | ".once FILENAME Output for the next SQL command only to FILENAME\n" |
| 2190 | ".open ?--new? ?FILE? Close existing database and reopen FILE\n" |
| @@ -3975,10 +3981,12 @@ | |
| 3981 | p->mode = MODE_List; |
| 3982 | sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab); |
| 3983 | }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){ |
| 3984 | p->mode = MODE_Insert; |
| 3985 | set_table_name(p, nArg>=3 ? azArg[2] : "table"); |
| 3986 | }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){ |
| 3987 | p->mode = MODE_Quote; |
| 3988 | }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){ |
| 3989 | p->mode = MODE_Ascii; |
| 3990 | sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit); |
| 3991 | sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record); |
| 3992 | }else { |
| 3993 |
+5
-8
| --- src/shun.c | ||
| +++ src/shun.c | ||
| @@ -317,14 +317,14 @@ | ||
| 317 | 317 | } |
| 318 | 318 | style_header("Artifact Receipts"); |
| 319 | 319 | if( showAll ){ |
| 320 | 320 | ofst = 0; |
| 321 | 321 | }else{ |
| 322 | - style_submenu_element("All", "All", "rcvfromlist?all=1"); | |
| 322 | + style_submenu_element("All", "rcvfromlist?all=1"); | |
| 323 | 323 | } |
| 324 | 324 | if( ofst>0 ){ |
| 325 | - style_submenu_element("Newer", "Newer", "rcvfromlist?ofst=%d", | |
| 325 | + style_submenu_element("Newer", "rcvfromlist?ofst=%d", | |
| 326 | 326 | ofst>30 ? ofst-30 : 0); |
| 327 | 327 | } |
| 328 | 328 | db_multi_exec( |
| 329 | 329 | "CREATE TEMP TABLE rcvidUsed(x INTEGER PRIMARY KEY);" |
| 330 | 330 | "INSERT OR IGNORE INTO rcvidUsed(x) SELECT rcvid FROM blob;" |
| @@ -363,12 +363,11 @@ | ||
| 363 | 363 | int rcvid = db_column_int(&q, 0); |
| 364 | 364 | const char *zUser = db_column_text(&q, 1); |
| 365 | 365 | const char *zDate = db_column_text(&q, 2); |
| 366 | 366 | const char *zIpAddr = db_column_text(&q, 3); |
| 367 | 367 | if( cnt==30 && !showAll ){ |
| 368 | - style_submenu_element("Older", "Older", | |
| 369 | - "rcvfromlist?ofst=%d", ofst+30); | |
| 368 | + style_submenu_element("Older", "rcvfromlist?ofst=%d", ofst+30); | |
| 370 | 369 | }else{ |
| 371 | 370 | cnt++; |
| 372 | 371 | @ <tr> |
| 373 | 372 | if( db_column_int(&q,4) ){ |
| 374 | 373 | @ <td style="padding-right: 15px;text-align: right;"> |
| @@ -406,19 +405,17 @@ | ||
| 406 | 405 | style_header("Artifact Receipt %d", rcvid); |
| 407 | 406 | if( db_exists( |
| 408 | 407 | "SELECT 1 FROM blob WHERE rcvid=%d AND" |
| 409 | 408 | " NOT EXISTS (SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)", rcvid) |
| 410 | 409 | ){ |
| 411 | - style_submenu_element("Shun All", "Shun All", | |
| 412 | - "shun?shun&rcvid=%d#addshun", rcvid); | |
| 410 | + style_submenu_element("Shun All", "shun?shun&rcvid=%d#addshun", rcvid); | |
| 413 | 411 | } |
| 414 | 412 | if( db_exists( |
| 415 | 413 | "SELECT 1 FROM blob WHERE rcvid=%d AND" |
| 416 | 414 | " EXISTS (SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)", rcvid) |
| 417 | 415 | ){ |
| 418 | - style_submenu_element("Unshun All", "Unshun All", | |
| 419 | - "shun?accept&rcvid=%d#delshun", rcvid); | |
| 416 | + style_submenu_element("Unshun All", "shun?accept&rcvid=%d#delshun", rcvid); | |
| 420 | 417 | } |
| 421 | 418 | db_prepare(&q, |
| 422 | 419 | "SELECT login, datetime(rcvfrom.mtime), rcvfrom.ipaddr" |
| 423 | 420 | " FROM rcvfrom LEFT JOIN user USING(uid)" |
| 424 | 421 | " WHERE rcvid=%d", |
| 425 | 422 |
| --- src/shun.c | |
| +++ src/shun.c | |
| @@ -317,14 +317,14 @@ | |
| 317 | } |
| 318 | style_header("Artifact Receipts"); |
| 319 | if( showAll ){ |
| 320 | ofst = 0; |
| 321 | }else{ |
| 322 | style_submenu_element("All", "All", "rcvfromlist?all=1"); |
| 323 | } |
| 324 | if( ofst>0 ){ |
| 325 | style_submenu_element("Newer", "Newer", "rcvfromlist?ofst=%d", |
| 326 | ofst>30 ? ofst-30 : 0); |
| 327 | } |
| 328 | db_multi_exec( |
| 329 | "CREATE TEMP TABLE rcvidUsed(x INTEGER PRIMARY KEY);" |
| 330 | "INSERT OR IGNORE INTO rcvidUsed(x) SELECT rcvid FROM blob;" |
| @@ -363,12 +363,11 @@ | |
| 363 | int rcvid = db_column_int(&q, 0); |
| 364 | const char *zUser = db_column_text(&q, 1); |
| 365 | const char *zDate = db_column_text(&q, 2); |
| 366 | const char *zIpAddr = db_column_text(&q, 3); |
| 367 | if( cnt==30 && !showAll ){ |
| 368 | style_submenu_element("Older", "Older", |
| 369 | "rcvfromlist?ofst=%d", ofst+30); |
| 370 | }else{ |
| 371 | cnt++; |
| 372 | @ <tr> |
| 373 | if( db_column_int(&q,4) ){ |
| 374 | @ <td style="padding-right: 15px;text-align: right;"> |
| @@ -406,19 +405,17 @@ | |
| 406 | style_header("Artifact Receipt %d", rcvid); |
| 407 | if( db_exists( |
| 408 | "SELECT 1 FROM blob WHERE rcvid=%d AND" |
| 409 | " NOT EXISTS (SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)", rcvid) |
| 410 | ){ |
| 411 | style_submenu_element("Shun All", "Shun All", |
| 412 | "shun?shun&rcvid=%d#addshun", rcvid); |
| 413 | } |
| 414 | if( db_exists( |
| 415 | "SELECT 1 FROM blob WHERE rcvid=%d AND" |
| 416 | " EXISTS (SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)", rcvid) |
| 417 | ){ |
| 418 | style_submenu_element("Unshun All", "Unshun All", |
| 419 | "shun?accept&rcvid=%d#delshun", rcvid); |
| 420 | } |
| 421 | db_prepare(&q, |
| 422 | "SELECT login, datetime(rcvfrom.mtime), rcvfrom.ipaddr" |
| 423 | " FROM rcvfrom LEFT JOIN user USING(uid)" |
| 424 | " WHERE rcvid=%d", |
| 425 |
| --- src/shun.c | |
| +++ src/shun.c | |
| @@ -317,14 +317,14 @@ | |
| 317 | } |
| 318 | style_header("Artifact Receipts"); |
| 319 | if( showAll ){ |
| 320 | ofst = 0; |
| 321 | }else{ |
| 322 | style_submenu_element("All", "rcvfromlist?all=1"); |
| 323 | } |
| 324 | if( ofst>0 ){ |
| 325 | style_submenu_element("Newer", "rcvfromlist?ofst=%d", |
| 326 | ofst>30 ? ofst-30 : 0); |
| 327 | } |
| 328 | db_multi_exec( |
| 329 | "CREATE TEMP TABLE rcvidUsed(x INTEGER PRIMARY KEY);" |
| 330 | "INSERT OR IGNORE INTO rcvidUsed(x) SELECT rcvid FROM blob;" |
| @@ -363,12 +363,11 @@ | |
| 363 | int rcvid = db_column_int(&q, 0); |
| 364 | const char *zUser = db_column_text(&q, 1); |
| 365 | const char *zDate = db_column_text(&q, 2); |
| 366 | const char *zIpAddr = db_column_text(&q, 3); |
| 367 | if( cnt==30 && !showAll ){ |
| 368 | style_submenu_element("Older", "rcvfromlist?ofst=%d", ofst+30); |
| 369 | }else{ |
| 370 | cnt++; |
| 371 | @ <tr> |
| 372 | if( db_column_int(&q,4) ){ |
| 373 | @ <td style="padding-right: 15px;text-align: right;"> |
| @@ -406,19 +405,17 @@ | |
| 405 | style_header("Artifact Receipt %d", rcvid); |
| 406 | if( db_exists( |
| 407 | "SELECT 1 FROM blob WHERE rcvid=%d AND" |
| 408 | " NOT EXISTS (SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)", rcvid) |
| 409 | ){ |
| 410 | style_submenu_element("Shun All", "shun?shun&rcvid=%d#addshun", rcvid); |
| 411 | } |
| 412 | if( db_exists( |
| 413 | "SELECT 1 FROM blob WHERE rcvid=%d AND" |
| 414 | " EXISTS (SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)", rcvid) |
| 415 | ){ |
| 416 | style_submenu_element("Unshun All", "shun?accept&rcvid=%d#delshun", rcvid); |
| 417 | } |
| 418 | db_prepare(&q, |
| 419 | "SELECT login, datetime(rcvfrom.mtime), rcvfrom.ipaddr" |
| 420 | " FROM rcvfrom LEFT JOIN user USING(uid)" |
| 421 | " WHERE rcvid=%d", |
| 422 |
+14
-14
| --- src/skins.c | ||
| +++ src/skins.c | ||
| @@ -100,18 +100,18 @@ | ||
| 100 | 100 | Blob err = BLOB_INITIALIZER; |
| 101 | 101 | if( strchr(zName, '/')!=0 ){ |
| 102 | 102 | zAltSkinDir = fossil_strdup(zName); |
| 103 | 103 | return 0; |
| 104 | 104 | } |
| 105 | - for(i=0; i<ArraySize(aBuiltinSkin); i++){ | |
| 105 | + for(i=0; i<count(aBuiltinSkin); i++){ | |
| 106 | 106 | if( fossil_strcmp(aBuiltinSkin[i].zLabel, zName)==0 ){ |
| 107 | 107 | pAltSkin = &aBuiltinSkin[i]; |
| 108 | 108 | return 0; |
| 109 | 109 | } |
| 110 | 110 | } |
| 111 | 111 | blob_appendf(&err, "available skins: %s", aBuiltinSkin[0].zLabel); |
| 112 | - for(i=1; i<ArraySize(aBuiltinSkin); i++){ | |
| 112 | + for(i=1; i<count(aBuiltinSkin); i++){ | |
| 113 | 113 | blob_append(&err, " ", 1); |
| 114 | 114 | blob_append(&err, aBuiltinSkin[i].zLabel, -1); |
| 115 | 115 | } |
| 116 | 116 | return blob_str(&err); |
| 117 | 117 | } |
| @@ -163,11 +163,11 @@ | ||
| 163 | 163 | /* |
| 164 | 164 | ** Return a pointer to a SkinDetail element. Return 0 if not found. |
| 165 | 165 | */ |
| 166 | 166 | static struct SkinDetail *skin_detail_find(const char *zName){ |
| 167 | 167 | int lwr = 0; |
| 168 | - int upr = ArraySize(aSkinDetail); | |
| 168 | + int upr = count(aSkinDetail); | |
| 169 | 169 | while( upr>=lwr ){ |
| 170 | 170 | int mid = (upr+lwr)/2; |
| 171 | 171 | int c = fossil_strcmp(aSkinDetail[mid].zName, zName); |
| 172 | 172 | if( c==0 ) return &aSkinDetail[mid]; |
| 173 | 173 | if( c<0 ){ |
| @@ -283,11 +283,11 @@ | ||
| 283 | 283 | ** Return true if there exists a skin name "zSkinName". |
| 284 | 284 | */ |
| 285 | 285 | static int skinExists(const char *zSkinName){ |
| 286 | 286 | int i; |
| 287 | 287 | if( zSkinName==0 ) return 0; |
| 288 | - for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ | |
| 288 | + for(i=0; i<count(aBuiltinSkin); i++){ | |
| 289 | 289 | if( fossil_strcmp(zSkinName, aBuiltinSkin[i].zDesc)==0 ) return 1; |
| 290 | 290 | } |
| 291 | 291 | return db_exists("SELECT 1 FROM config WHERE name='skin:%q'", zSkinName); |
| 292 | 292 | } |
| 293 | 293 | |
| @@ -304,11 +304,11 @@ | ||
| 304 | 304 | char *zLabel; |
| 305 | 305 | static const char *azType[] = { "css", "header", "footer", "details" }; |
| 306 | 306 | int i; |
| 307 | 307 | Blob val; |
| 308 | 308 | blob_zero(&val); |
| 309 | - for(i=0; i<sizeof(azType)/sizeof(azType[0]); i++){ | |
| 309 | + for(i=0; i<count(azType); i++){ | |
| 310 | 310 | if( zName ){ |
| 311 | 311 | zLabel = mprintf("skins/%s/%s.txt", zName, azType[i]); |
| 312 | 312 | z = builtin_text(zLabel); |
| 313 | 313 | fossil_free(zLabel); |
| 314 | 314 | }else{ |
| @@ -427,11 +427,11 @@ | ||
| 427 | 427 | login_needed(0); |
| 428 | 428 | return; |
| 429 | 429 | } |
| 430 | 430 | db_begin_transaction(); |
| 431 | 431 | zCurrent = getSkin(0); |
| 432 | - for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ | |
| 432 | + for(i=0; i<count(aBuiltinSkin); i++){ | |
| 433 | 433 | aBuiltinSkin[i].zSQL = getSkin(aBuiltinSkin[i].zLabel); |
| 434 | 434 | } |
| 435 | 435 | |
| 436 | 436 | /* Process requests to delete a user-defined skin */ |
| 437 | 437 | if( P("del1") && (zName = skinVarName(P("sn"), 1))!=0 ){ |
| @@ -458,11 +458,11 @@ | ||
| 458 | 458 | int seen = 0; |
| 459 | 459 | |
| 460 | 460 | /* Check to see if the current skin is already saved. If it is, there |
| 461 | 461 | ** is no need to create a backup */ |
| 462 | 462 | zCurrent = getSkin(0); |
| 463 | - for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ | |
| 463 | + for(i=0; i<count(aBuiltinSkin); i++){ | |
| 464 | 464 | if( fossil_strcmp(aBuiltinSkin[i].zSQL, zCurrent)==0 ){ |
| 465 | 465 | seen = 1; |
| 466 | 466 | break; |
| 467 | 467 | } |
| 468 | 468 | } |
| @@ -476,11 +476,11 @@ | ||
| 476 | 476 | " %Q,now())", zCurrent |
| 477 | 477 | ); |
| 478 | 478 | } |
| 479 | 479 | } |
| 480 | 480 | seen = 0; |
| 481 | - for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ | |
| 481 | + for(i=0; i<count(aBuiltinSkin); i++){ | |
| 482 | 482 | if( fossil_strcmp(aBuiltinSkin[i].zDesc, z)==0 ){ |
| 483 | 483 | seen = 1; |
| 484 | 484 | zCurrent = aBuiltinSkin[i].zSQL; |
| 485 | 485 | db_multi_exec("%s", zCurrent/*safe-for-%s*/); |
| 486 | 486 | break; |
| @@ -513,11 +513,11 @@ | ||
| 513 | 513 | @ is restarted without the override.</p> |
| 514 | 514 | @ |
| 515 | 515 | } |
| 516 | 516 | @ <h2>Available Skins:</h2> |
| 517 | 517 | @ <table border="0"> |
| 518 | - for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ | |
| 518 | + for(i=0; i<count(aBuiltinSkin); i++){ | |
| 519 | 519 | z = aBuiltinSkin[i].zDesc; |
| 520 | 520 | @ <tr><td>%d(i+1).<td>%h(z)<td> <td> |
| 521 | 521 | if( fossil_strcmp(aBuiltinSkin[i].zSQL, zCurrent)==0 ){ |
| 522 | 522 | @ (Currently In Use) |
| 523 | 523 | seenCurrent = 1; |
| @@ -597,25 +597,25 @@ | ||
| 597 | 597 | if( !g.perm.Setup ){ |
| 598 | 598 | login_needed(0); |
| 599 | 599 | return; |
| 600 | 600 | } |
| 601 | 601 | ii = atoi(PD("w","0")); |
| 602 | - if( ii<0 || ii>ArraySize(aSkinAttr) ) ii = 0; | |
| 602 | + if( ii<0 || ii>count(aSkinAttr) ) ii = 0; | |
| 603 | 603 | zBasis = PD("basis","default"); |
| 604 | 604 | zDflt = mprintf("skins/%s/%s.txt", zBasis, aSkinAttr[ii].zFile); |
| 605 | 605 | db_begin_transaction(); |
| 606 | 606 | if( P("revert")!=0 ){ |
| 607 | 607 | db_multi_exec("DELETE FROM config WHERE name=%Q", aSkinAttr[ii].zFile); |
| 608 | 608 | cgi_replace_parameter(aSkinAttr[ii].zFile, builtin_text(zDflt)); |
| 609 | 609 | } |
| 610 | 610 | style_header("%s", aSkinAttr[ii].zTitle); |
| 611 | - for(j=0; j<ArraySize(aSkinAttr); j++){ | |
| 611 | + for(j=0; j<count(aSkinAttr); j++){ | |
| 612 | 612 | if( j==ii ) continue; |
| 613 | - style_submenu_element(aSkinAttr[j].zSubmenu, 0, | |
| 613 | + style_submenu_element(aSkinAttr[j].zSubmenu, | |
| 614 | 614 | "%R/setup_skinedit?w=%d&basis=%h",j,zBasis); |
| 615 | 615 | } |
| 616 | - style_submenu_element("Skins", 0, "%R/setup_skin"); | |
| 616 | + style_submenu_element("Skins", "%R/setup_skin"); | |
| 617 | 617 | @ <form action="%s(g.zTop)/setup_skinedit" method="post"><div> |
| 618 | 618 | login_insert_csrf_secret(); |
| 619 | 619 | @ <input type='hidden' name='w' value='%d(ii)'> |
| 620 | 620 | @ <h2>Edit %s(aSkinAttr[ii].zTitle):</h2> |
| 621 | 621 | zContent = textarea_attribute("", 10, 80, aSkinAttr[ii].zFile, |
| @@ -622,11 +622,11 @@ | ||
| 622 | 622 | aSkinAttr[ii].zFile, builtin_text(zDflt), 0); |
| 623 | 623 | @ <br /> |
| 624 | 624 | @ <input type="submit" name="submit" value="Apply Changes" /> |
| 625 | 625 | @ <hr /> |
| 626 | 626 | @ Baseline: <select size='1' name='basis'> |
| 627 | - for(j=0; j<ArraySize(aBuiltinSkin); j++){ | |
| 627 | + for(j=0; j<count(aBuiltinSkin); j++){ | |
| 628 | 628 | cgi_printf("<option value='%h'%s>%h</option>\n", |
| 629 | 629 | aBuiltinSkin[j].zLabel, |
| 630 | 630 | fossil_strcmp(zBasis,aBuiltinSkin[j].zLabel)==0 ? " selected" : "", |
| 631 | 631 | aBuiltinSkin[j].zDesc |
| 632 | 632 | ); |
| 633 | 633 |
| --- src/skins.c | |
| +++ src/skins.c | |
| @@ -100,18 +100,18 @@ | |
| 100 | Blob err = BLOB_INITIALIZER; |
| 101 | if( strchr(zName, '/')!=0 ){ |
| 102 | zAltSkinDir = fossil_strdup(zName); |
| 103 | return 0; |
| 104 | } |
| 105 | for(i=0; i<ArraySize(aBuiltinSkin); i++){ |
| 106 | if( fossil_strcmp(aBuiltinSkin[i].zLabel, zName)==0 ){ |
| 107 | pAltSkin = &aBuiltinSkin[i]; |
| 108 | return 0; |
| 109 | } |
| 110 | } |
| 111 | blob_appendf(&err, "available skins: %s", aBuiltinSkin[0].zLabel); |
| 112 | for(i=1; i<ArraySize(aBuiltinSkin); i++){ |
| 113 | blob_append(&err, " ", 1); |
| 114 | blob_append(&err, aBuiltinSkin[i].zLabel, -1); |
| 115 | } |
| 116 | return blob_str(&err); |
| 117 | } |
| @@ -163,11 +163,11 @@ | |
| 163 | /* |
| 164 | ** Return a pointer to a SkinDetail element. Return 0 if not found. |
| 165 | */ |
| 166 | static struct SkinDetail *skin_detail_find(const char *zName){ |
| 167 | int lwr = 0; |
| 168 | int upr = ArraySize(aSkinDetail); |
| 169 | while( upr>=lwr ){ |
| 170 | int mid = (upr+lwr)/2; |
| 171 | int c = fossil_strcmp(aSkinDetail[mid].zName, zName); |
| 172 | if( c==0 ) return &aSkinDetail[mid]; |
| 173 | if( c<0 ){ |
| @@ -283,11 +283,11 @@ | |
| 283 | ** Return true if there exists a skin name "zSkinName". |
| 284 | */ |
| 285 | static int skinExists(const char *zSkinName){ |
| 286 | int i; |
| 287 | if( zSkinName==0 ) return 0; |
| 288 | for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ |
| 289 | if( fossil_strcmp(zSkinName, aBuiltinSkin[i].zDesc)==0 ) return 1; |
| 290 | } |
| 291 | return db_exists("SELECT 1 FROM config WHERE name='skin:%q'", zSkinName); |
| 292 | } |
| 293 | |
| @@ -304,11 +304,11 @@ | |
| 304 | char *zLabel; |
| 305 | static const char *azType[] = { "css", "header", "footer", "details" }; |
| 306 | int i; |
| 307 | Blob val; |
| 308 | blob_zero(&val); |
| 309 | for(i=0; i<sizeof(azType)/sizeof(azType[0]); i++){ |
| 310 | if( zName ){ |
| 311 | zLabel = mprintf("skins/%s/%s.txt", zName, azType[i]); |
| 312 | z = builtin_text(zLabel); |
| 313 | fossil_free(zLabel); |
| 314 | }else{ |
| @@ -427,11 +427,11 @@ | |
| 427 | login_needed(0); |
| 428 | return; |
| 429 | } |
| 430 | db_begin_transaction(); |
| 431 | zCurrent = getSkin(0); |
| 432 | for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ |
| 433 | aBuiltinSkin[i].zSQL = getSkin(aBuiltinSkin[i].zLabel); |
| 434 | } |
| 435 | |
| 436 | /* Process requests to delete a user-defined skin */ |
| 437 | if( P("del1") && (zName = skinVarName(P("sn"), 1))!=0 ){ |
| @@ -458,11 +458,11 @@ | |
| 458 | int seen = 0; |
| 459 | |
| 460 | /* Check to see if the current skin is already saved. If it is, there |
| 461 | ** is no need to create a backup */ |
| 462 | zCurrent = getSkin(0); |
| 463 | for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ |
| 464 | if( fossil_strcmp(aBuiltinSkin[i].zSQL, zCurrent)==0 ){ |
| 465 | seen = 1; |
| 466 | break; |
| 467 | } |
| 468 | } |
| @@ -476,11 +476,11 @@ | |
| 476 | " %Q,now())", zCurrent |
| 477 | ); |
| 478 | } |
| 479 | } |
| 480 | seen = 0; |
| 481 | for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ |
| 482 | if( fossil_strcmp(aBuiltinSkin[i].zDesc, z)==0 ){ |
| 483 | seen = 1; |
| 484 | zCurrent = aBuiltinSkin[i].zSQL; |
| 485 | db_multi_exec("%s", zCurrent/*safe-for-%s*/); |
| 486 | break; |
| @@ -513,11 +513,11 @@ | |
| 513 | @ is restarted without the override.</p> |
| 514 | @ |
| 515 | } |
| 516 | @ <h2>Available Skins:</h2> |
| 517 | @ <table border="0"> |
| 518 | for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ |
| 519 | z = aBuiltinSkin[i].zDesc; |
| 520 | @ <tr><td>%d(i+1).<td>%h(z)<td> <td> |
| 521 | if( fossil_strcmp(aBuiltinSkin[i].zSQL, zCurrent)==0 ){ |
| 522 | @ (Currently In Use) |
| 523 | seenCurrent = 1; |
| @@ -597,25 +597,25 @@ | |
| 597 | if( !g.perm.Setup ){ |
| 598 | login_needed(0); |
| 599 | return; |
| 600 | } |
| 601 | ii = atoi(PD("w","0")); |
| 602 | if( ii<0 || ii>ArraySize(aSkinAttr) ) ii = 0; |
| 603 | zBasis = PD("basis","default"); |
| 604 | zDflt = mprintf("skins/%s/%s.txt", zBasis, aSkinAttr[ii].zFile); |
| 605 | db_begin_transaction(); |
| 606 | if( P("revert")!=0 ){ |
| 607 | db_multi_exec("DELETE FROM config WHERE name=%Q", aSkinAttr[ii].zFile); |
| 608 | cgi_replace_parameter(aSkinAttr[ii].zFile, builtin_text(zDflt)); |
| 609 | } |
| 610 | style_header("%s", aSkinAttr[ii].zTitle); |
| 611 | for(j=0; j<ArraySize(aSkinAttr); j++){ |
| 612 | if( j==ii ) continue; |
| 613 | style_submenu_element(aSkinAttr[j].zSubmenu, 0, |
| 614 | "%R/setup_skinedit?w=%d&basis=%h",j,zBasis); |
| 615 | } |
| 616 | style_submenu_element("Skins", 0, "%R/setup_skin"); |
| 617 | @ <form action="%s(g.zTop)/setup_skinedit" method="post"><div> |
| 618 | login_insert_csrf_secret(); |
| 619 | @ <input type='hidden' name='w' value='%d(ii)'> |
| 620 | @ <h2>Edit %s(aSkinAttr[ii].zTitle):</h2> |
| 621 | zContent = textarea_attribute("", 10, 80, aSkinAttr[ii].zFile, |
| @@ -622,11 +622,11 @@ | |
| 622 | aSkinAttr[ii].zFile, builtin_text(zDflt), 0); |
| 623 | @ <br /> |
| 624 | @ <input type="submit" name="submit" value="Apply Changes" /> |
| 625 | @ <hr /> |
| 626 | @ Baseline: <select size='1' name='basis'> |
| 627 | for(j=0; j<ArraySize(aBuiltinSkin); j++){ |
| 628 | cgi_printf("<option value='%h'%s>%h</option>\n", |
| 629 | aBuiltinSkin[j].zLabel, |
| 630 | fossil_strcmp(zBasis,aBuiltinSkin[j].zLabel)==0 ? " selected" : "", |
| 631 | aBuiltinSkin[j].zDesc |
| 632 | ); |
| 633 |
| --- src/skins.c | |
| +++ src/skins.c | |
| @@ -100,18 +100,18 @@ | |
| 100 | Blob err = BLOB_INITIALIZER; |
| 101 | if( strchr(zName, '/')!=0 ){ |
| 102 | zAltSkinDir = fossil_strdup(zName); |
| 103 | return 0; |
| 104 | } |
| 105 | for(i=0; i<count(aBuiltinSkin); i++){ |
| 106 | if( fossil_strcmp(aBuiltinSkin[i].zLabel, zName)==0 ){ |
| 107 | pAltSkin = &aBuiltinSkin[i]; |
| 108 | return 0; |
| 109 | } |
| 110 | } |
| 111 | blob_appendf(&err, "available skins: %s", aBuiltinSkin[0].zLabel); |
| 112 | for(i=1; i<count(aBuiltinSkin); i++){ |
| 113 | blob_append(&err, " ", 1); |
| 114 | blob_append(&err, aBuiltinSkin[i].zLabel, -1); |
| 115 | } |
| 116 | return blob_str(&err); |
| 117 | } |
| @@ -163,11 +163,11 @@ | |
| 163 | /* |
| 164 | ** Return a pointer to a SkinDetail element. Return 0 if not found. |
| 165 | */ |
| 166 | static struct SkinDetail *skin_detail_find(const char *zName){ |
| 167 | int lwr = 0; |
| 168 | int upr = count(aSkinDetail); |
| 169 | while( upr>=lwr ){ |
| 170 | int mid = (upr+lwr)/2; |
| 171 | int c = fossil_strcmp(aSkinDetail[mid].zName, zName); |
| 172 | if( c==0 ) return &aSkinDetail[mid]; |
| 173 | if( c<0 ){ |
| @@ -283,11 +283,11 @@ | |
| 283 | ** Return true if there exists a skin name "zSkinName". |
| 284 | */ |
| 285 | static int skinExists(const char *zSkinName){ |
| 286 | int i; |
| 287 | if( zSkinName==0 ) return 0; |
| 288 | for(i=0; i<count(aBuiltinSkin); i++){ |
| 289 | if( fossil_strcmp(zSkinName, aBuiltinSkin[i].zDesc)==0 ) return 1; |
| 290 | } |
| 291 | return db_exists("SELECT 1 FROM config WHERE name='skin:%q'", zSkinName); |
| 292 | } |
| 293 | |
| @@ -304,11 +304,11 @@ | |
| 304 | char *zLabel; |
| 305 | static const char *azType[] = { "css", "header", "footer", "details" }; |
| 306 | int i; |
| 307 | Blob val; |
| 308 | blob_zero(&val); |
| 309 | for(i=0; i<count(azType); i++){ |
| 310 | if( zName ){ |
| 311 | zLabel = mprintf("skins/%s/%s.txt", zName, azType[i]); |
| 312 | z = builtin_text(zLabel); |
| 313 | fossil_free(zLabel); |
| 314 | }else{ |
| @@ -427,11 +427,11 @@ | |
| 427 | login_needed(0); |
| 428 | return; |
| 429 | } |
| 430 | db_begin_transaction(); |
| 431 | zCurrent = getSkin(0); |
| 432 | for(i=0; i<count(aBuiltinSkin); i++){ |
| 433 | aBuiltinSkin[i].zSQL = getSkin(aBuiltinSkin[i].zLabel); |
| 434 | } |
| 435 | |
| 436 | /* Process requests to delete a user-defined skin */ |
| 437 | if( P("del1") && (zName = skinVarName(P("sn"), 1))!=0 ){ |
| @@ -458,11 +458,11 @@ | |
| 458 | int seen = 0; |
| 459 | |
| 460 | /* Check to see if the current skin is already saved. If it is, there |
| 461 | ** is no need to create a backup */ |
| 462 | zCurrent = getSkin(0); |
| 463 | for(i=0; i<count(aBuiltinSkin); i++){ |
| 464 | if( fossil_strcmp(aBuiltinSkin[i].zSQL, zCurrent)==0 ){ |
| 465 | seen = 1; |
| 466 | break; |
| 467 | } |
| 468 | } |
| @@ -476,11 +476,11 @@ | |
| 476 | " %Q,now())", zCurrent |
| 477 | ); |
| 478 | } |
| 479 | } |
| 480 | seen = 0; |
| 481 | for(i=0; i<count(aBuiltinSkin); i++){ |
| 482 | if( fossil_strcmp(aBuiltinSkin[i].zDesc, z)==0 ){ |
| 483 | seen = 1; |
| 484 | zCurrent = aBuiltinSkin[i].zSQL; |
| 485 | db_multi_exec("%s", zCurrent/*safe-for-%s*/); |
| 486 | break; |
| @@ -513,11 +513,11 @@ | |
| 513 | @ is restarted without the override.</p> |
| 514 | @ |
| 515 | } |
| 516 | @ <h2>Available Skins:</h2> |
| 517 | @ <table border="0"> |
| 518 | for(i=0; i<count(aBuiltinSkin); i++){ |
| 519 | z = aBuiltinSkin[i].zDesc; |
| 520 | @ <tr><td>%d(i+1).<td>%h(z)<td> <td> |
| 521 | if( fossil_strcmp(aBuiltinSkin[i].zSQL, zCurrent)==0 ){ |
| 522 | @ (Currently In Use) |
| 523 | seenCurrent = 1; |
| @@ -597,25 +597,25 @@ | |
| 597 | if( !g.perm.Setup ){ |
| 598 | login_needed(0); |
| 599 | return; |
| 600 | } |
| 601 | ii = atoi(PD("w","0")); |
| 602 | if( ii<0 || ii>count(aSkinAttr) ) ii = 0; |
| 603 | zBasis = PD("basis","default"); |
| 604 | zDflt = mprintf("skins/%s/%s.txt", zBasis, aSkinAttr[ii].zFile); |
| 605 | db_begin_transaction(); |
| 606 | if( P("revert")!=0 ){ |
| 607 | db_multi_exec("DELETE FROM config WHERE name=%Q", aSkinAttr[ii].zFile); |
| 608 | cgi_replace_parameter(aSkinAttr[ii].zFile, builtin_text(zDflt)); |
| 609 | } |
| 610 | style_header("%s", aSkinAttr[ii].zTitle); |
| 611 | for(j=0; j<count(aSkinAttr); j++){ |
| 612 | if( j==ii ) continue; |
| 613 | style_submenu_element(aSkinAttr[j].zSubmenu, |
| 614 | "%R/setup_skinedit?w=%d&basis=%h",j,zBasis); |
| 615 | } |
| 616 | style_submenu_element("Skins", "%R/setup_skin"); |
| 617 | @ <form action="%s(g.zTop)/setup_skinedit" method="post"><div> |
| 618 | login_insert_csrf_secret(); |
| 619 | @ <input type='hidden' name='w' value='%d(ii)'> |
| 620 | @ <h2>Edit %s(aSkinAttr[ii].zTitle):</h2> |
| 621 | zContent = textarea_attribute("", 10, 80, aSkinAttr[ii].zFile, |
| @@ -622,11 +622,11 @@ | |
| 622 | aSkinAttr[ii].zFile, builtin_text(zDflt), 0); |
| 623 | @ <br /> |
| 624 | @ <input type="submit" name="submit" value="Apply Changes" /> |
| 625 | @ <hr /> |
| 626 | @ Baseline: <select size='1' name='basis'> |
| 627 | for(j=0; j<count(aBuiltinSkin); j++){ |
| 628 | cgi_printf("<option value='%h'%s>%h</option>\n", |
| 629 | aBuiltinSkin[j].zLabel, |
| 630 | fossil_strcmp(zBasis,aBuiltinSkin[j].zLabel)==0 ? " selected" : "", |
| 631 | aBuiltinSkin[j].zDesc |
| 632 | ); |
| 633 |
+206
-100
| --- src/sqlite3.c | ||
| +++ src/sqlite3.c | ||
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | /****************************************************************************** |
| 2 | 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | -** version 3.15.0. By combining all the individual C code files into this | |
| 3 | +** version 3.16.0. By combining all the individual C code files into this | |
| 4 | 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | 8 | ** translation unit. |
| @@ -379,13 +379,13 @@ | ||
| 379 | 379 | ** |
| 380 | 380 | ** See also: [sqlite3_libversion()], |
| 381 | 381 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 382 | 382 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 383 | 383 | */ |
| 384 | -#define SQLITE_VERSION "3.15.0" | |
| 385 | -#define SQLITE_VERSION_NUMBER 3015000 | |
| 386 | -#define SQLITE_SOURCE_ID "2016-10-04 12:20:12 3a9d802fda10585654332b314d317250dc5d894e" | |
| 384 | +#define SQLITE_VERSION "3.16.0" | |
| 385 | +#define SQLITE_VERSION_NUMBER 3016000 | |
| 386 | +#define SQLITE_SOURCE_ID "2016-11-02 14:50:19 3028845329c9b7acdec2ec8b01d00d782347454c" | |
| 387 | 387 | |
| 388 | 388 | /* |
| 389 | 389 | ** CAPI3REF: Run-Time Library Version Numbers |
| 390 | 390 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 391 | 391 | ** |
| @@ -1235,10 +1235,16 @@ | ||
| 1235 | 1235 | ** <li>[[SQLITE_FCNTL_HAS_MOVED]] |
| 1236 | 1236 | ** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a |
| 1237 | 1237 | ** pointer to an integer and it writes a boolean into that integer depending |
| 1238 | 1238 | ** on whether or not the file has been renamed, moved, or deleted since it |
| 1239 | 1239 | ** was first opened. |
| 1240 | +** | |
| 1241 | +** <li>[[SQLITE_FCNTL_WIN32_GET_HANDLE]] | |
| 1242 | +** The [SQLITE_FCNTL_WIN32_GET_HANDLE] opcode can be used to obtain the | |
| 1243 | +** underlying native file handle associated with a file handle. This file | |
| 1244 | +** control interprets its argument as a pointer to a native file handle and | |
| 1245 | +** writes the resulting value there. | |
| 1240 | 1246 | ** |
| 1241 | 1247 | ** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]] |
| 1242 | 1248 | ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This |
| 1243 | 1249 | ** opcode causes the xFileControl method to swap the file handle with the one |
| 1244 | 1250 | ** pointed to by the pArg argument. This capability is used during testing |
| @@ -1286,10 +1292,12 @@ | ||
| 1286 | 1292 | #define SQLITE_FCNTL_WAL_BLOCK 24 |
| 1287 | 1293 | #define SQLITE_FCNTL_ZIPVFS 25 |
| 1288 | 1294 | #define SQLITE_FCNTL_RBU 26 |
| 1289 | 1295 | #define SQLITE_FCNTL_VFS_POINTER 27 |
| 1290 | 1296 | #define SQLITE_FCNTL_JOURNAL_POINTER 28 |
| 1297 | +#define SQLITE_FCNTL_WIN32_GET_HANDLE 29 | |
| 1298 | +#define SQLITE_FCNTL_PDB 30 | |
| 1291 | 1299 | |
| 1292 | 1300 | /* deprecated names */ |
| 1293 | 1301 | #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE |
| 1294 | 1302 | #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE |
| 1295 | 1303 | #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| @@ -2238,18 +2246,31 @@ | ||
| 2238 | 2246 | ** does not make a copy of the new main schema name string, so the application |
| 2239 | 2247 | ** must ensure that the argument passed into this DBCONFIG option is unchanged |
| 2240 | 2248 | ** until after the database connection closes. |
| 2241 | 2249 | ** </dd> |
| 2242 | 2250 | ** |
| 2251 | +** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt> | |
| 2252 | +** <dd> Usually, when a database in wal mode is closed or detached from a | |
| 2253 | +** database handle, SQLite checks if this will mean that there are now no | |
| 2254 | +** connections at all to the database. If so, it performs a checkpoint | |
| 2255 | +** operation before closing the connection. This option may be used to | |
| 2256 | +** override this behaviour. The first parameter passed to this operation | |
| 2257 | +** is an integer - non-zero to disable checkpoints-on-close, or zero (the | |
| 2258 | +** default) to enable them. The second parameter is a pointer to an integer | |
| 2259 | +** into which is written 0 or 1 to indicate whether checkpoints-on-close | |
| 2260 | +** have been disabled - 0 if they are not disabled, 1 if they are. | |
| 2261 | +** </dd> | |
| 2262 | +** | |
| 2243 | 2263 | ** </dl> |
| 2244 | 2264 | */ |
| 2245 | 2265 | #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ |
| 2246 | 2266 | #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ |
| 2247 | 2267 | #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ |
| 2248 | 2268 | #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ |
| 2249 | 2269 | #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ |
| 2250 | 2270 | #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ |
| 2271 | +#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */ | |
| 2251 | 2272 | |
| 2252 | 2273 | |
| 2253 | 2274 | /* |
| 2254 | 2275 | ** CAPI3REF: Enable Or Disable Extended Result Codes |
| 2255 | 2276 | ** METHOD: sqlite3 |
| @@ -12675,11 +12696,11 @@ | ||
| 12675 | 12696 | #define OP_SorterData 120 /* synopsis: r[P2]=data */ |
| 12676 | 12697 | #define OP_RowKey 121 /* synopsis: r[P2]=key */ |
| 12677 | 12698 | #define OP_RowData 122 /* synopsis: r[P2]=data */ |
| 12678 | 12699 | #define OP_Rowid 123 /* synopsis: r[P2]=rowid */ |
| 12679 | 12700 | #define OP_NullRow 124 |
| 12680 | -#define OP_SorterInsert 125 | |
| 12701 | +#define OP_SorterInsert 125 /* synopsis: key=r[P2] */ | |
| 12681 | 12702 | #define OP_IdxInsert 126 /* synopsis: key=r[P2] */ |
| 12682 | 12703 | #define OP_IdxDelete 127 /* synopsis: key=r[P2@P3] */ |
| 12683 | 12704 | #define OP_Seek 128 /* synopsis: Move P3 to P1.rowid */ |
| 12684 | 12705 | #define OP_IdxRowid 129 /* synopsis: r[P2]=rowid */ |
| 12685 | 12706 | #define OP_Destroy 130 |
| @@ -13030,11 +13051,11 @@ | ||
| 13030 | 13051 | int, |
| 13031 | 13052 | int, |
| 13032 | 13053 | int, |
| 13033 | 13054 | void(*)(DbPage*) |
| 13034 | 13055 | ); |
| 13035 | -SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager); | |
| 13056 | +SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*); | |
| 13036 | 13057 | SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); |
| 13037 | 13058 | |
| 13038 | 13059 | /* Functions used to configure a Pager object. */ |
| 13039 | 13060 | SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); |
| 13040 | 13061 | SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); |
| @@ -13081,19 +13102,22 @@ | ||
| 13081 | 13102 | SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n); |
| 13082 | 13103 | SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); |
| 13083 | 13104 | SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager); |
| 13084 | 13105 | |
| 13085 | 13106 | #ifndef SQLITE_OMIT_WAL |
| 13086 | -SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*); | |
| 13107 | +SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, sqlite3*, int, int*, int*); | |
| 13087 | 13108 | SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager); |
| 13088 | 13109 | SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); |
| 13089 | 13110 | SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); |
| 13090 | -SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager); | |
| 13111 | +SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3*); | |
| 13112 | +SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager); | |
| 13091 | 13113 | # ifdef SQLITE_ENABLE_SNAPSHOT |
| 13092 | 13114 | SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot); |
| 13093 | 13115 | SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot); |
| 13094 | 13116 | # endif |
| 13117 | +#else | |
| 13118 | +# define sqlite3PagerUseWal(x) 0 | |
| 13095 | 13119 | #endif |
| 13096 | 13120 | |
| 13097 | 13121 | #ifdef SQLITE_ENABLE_ZIPVFS |
| 13098 | 13122 | SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); |
| 13099 | 13123 | #endif |
| @@ -14060,10 +14084,11 @@ | ||
| 14060 | 14084 | #define SQLITE_QueryOnly 0x04000000 /* Disable database changes */ |
| 14061 | 14085 | #define SQLITE_VdbeEQP 0x08000000 /* Debug EXPLAIN QUERY PLAN */ |
| 14062 | 14086 | #define SQLITE_Vacuum 0x10000000 /* Currently in a VACUUM */ |
| 14063 | 14087 | #define SQLITE_CellSizeCk 0x20000000 /* Check btree cell sizes on load */ |
| 14064 | 14088 | #define SQLITE_Fts3Tokenizer 0x40000000 /* Enable fts3_tokenizer(2) */ |
| 14089 | +#define SQLITE_NoCkptOnClose 0x80000000 /* No checkpoint on close()/DETACH */ | |
| 14065 | 14090 | |
| 14066 | 14091 | |
| 14067 | 14092 | /* |
| 14068 | 14093 | ** Bits of the sqlite3.dbOptFlags field that are used by the |
| 14069 | 14094 | ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to |
| @@ -17268,10 +17293,13 @@ | ||
| 17268 | 17293 | #if SQLITE_DEFAULT_LOCKING_MODE |
| 17269 | 17294 | "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), |
| 17270 | 17295 | #endif |
| 17271 | 17296 | #if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc) |
| 17272 | 17297 | "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE), |
| 17298 | +#endif | |
| 17299 | +#if SQLITE_DIRECT_OVERFLOW_READ | |
| 17300 | + "DIRECT_OVERFLOW_READ", | |
| 17273 | 17301 | #endif |
| 17274 | 17302 | #if SQLITE_DISABLE_DIRSYNC |
| 17275 | 17303 | "DISABLE_DIRSYNC", |
| 17276 | 17304 | #endif |
| 17277 | 17305 | #if SQLITE_DISABLE_LFS |
| @@ -17354,10 +17382,13 @@ | ||
| 17354 | 17382 | #if SQLITE_ENABLE_UNLOCK_NOTIFY |
| 17355 | 17383 | "ENABLE_UNLOCK_NOTIFY", |
| 17356 | 17384 | #endif |
| 17357 | 17385 | #if SQLITE_ENABLE_UPDATE_DELETE_LIMIT |
| 17358 | 17386 | "ENABLE_UPDATE_DELETE_LIMIT", |
| 17387 | +#endif | |
| 17388 | +#if defined(SQLITE_ENABLE_URI_00_ERROR) | |
| 17389 | + "ENABLE_URI_00_ERROR", | |
| 17359 | 17390 | #endif |
| 17360 | 17391 | #if SQLITE_HAS_CODEC |
| 17361 | 17392 | "HAS_CODEC", |
| 17362 | 17393 | #endif |
| 17363 | 17394 | #if HAVE_ISNAN || SQLITE_HAVE_ISNAN |
| @@ -18105,12 +18136,12 @@ | ||
| 18105 | 18136 | UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */ |
| 18106 | 18137 | UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */ |
| 18107 | 18138 | int iNewReg; /* Register for new.* values */ |
| 18108 | 18139 | i64 iKey1; /* First key value passed to hook */ |
| 18109 | 18140 | i64 iKey2; /* Second key value passed to hook */ |
| 18110 | - int iPKey; /* If not negative index of IPK column */ | |
| 18111 | 18141 | Mem *aNew; /* Array of new.* values */ |
| 18142 | + Table *pTab; /* Schema object being upated */ | |
| 18112 | 18143 | }; |
| 18113 | 18144 | |
| 18114 | 18145 | /* |
| 18115 | 18146 | ** Function prototypes |
| 18116 | 18147 | */ |
| @@ -24598,13 +24629,12 @@ | ||
| 24598 | 24629 | char *zNew; |
| 24599 | 24630 | size_t n; |
| 24600 | 24631 | if( z==0 ){ |
| 24601 | 24632 | return 0; |
| 24602 | 24633 | } |
| 24603 | - n = sqlite3Strlen30(z) + 1; | |
| 24604 | - assert( (n&0x7fffffff)==n ); | |
| 24605 | - zNew = sqlite3DbMallocRaw(db, (int)n); | |
| 24634 | + n = strlen(z) + 1; | |
| 24635 | + zNew = sqlite3DbMallocRaw(db, n); | |
| 24606 | 24636 | if( zNew ){ |
| 24607 | 24637 | memcpy(zNew, z, n); |
| 24608 | 24638 | } |
| 24609 | 24639 | return zNew; |
| 24610 | 24640 | } |
| @@ -29127,11 +29157,11 @@ | ||
| 29127 | 29157 | /* 120 */ "SorterData" OpHelp("r[P2]=data"), |
| 29128 | 29158 | /* 121 */ "RowKey" OpHelp("r[P2]=key"), |
| 29129 | 29159 | /* 122 */ "RowData" OpHelp("r[P2]=data"), |
| 29130 | 29160 | /* 123 */ "Rowid" OpHelp("r[P2]=rowid"), |
| 29131 | 29161 | /* 124 */ "NullRow" OpHelp(""), |
| 29132 | - /* 125 */ "SorterInsert" OpHelp(""), | |
| 29162 | + /* 125 */ "SorterInsert" OpHelp("key=r[P2]"), | |
| 29133 | 29163 | /* 126 */ "IdxInsert" OpHelp("key=r[P2]"), |
| 29134 | 29164 | /* 127 */ "IdxDelete" OpHelp("key=r[P2@P3]"), |
| 29135 | 29165 | /* 128 */ "Seek" OpHelp("Move P3 to P1.rowid"), |
| 29136 | 29166 | /* 129 */ "IdxRowid" OpHelp("r[P2]=rowid"), |
| 29137 | 29167 | /* 130 */ "Destroy" OpHelp(""), |
| @@ -40674,10 +40704,16 @@ | ||
| 40674 | 40704 | a[1] = winIoerrRetryDelay; |
| 40675 | 40705 | } |
| 40676 | 40706 | OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); |
| 40677 | 40707 | return SQLITE_OK; |
| 40678 | 40708 | } |
| 40709 | + case SQLITE_FCNTL_WIN32_GET_HANDLE: { | |
| 40710 | + LPHANDLE phFile = (LPHANDLE)pArg; | |
| 40711 | + *phFile = pFile->h; | |
| 40712 | + OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); | |
| 40713 | + return SQLITE_OK; | |
| 40714 | + } | |
| 40679 | 40715 | #ifdef SQLITE_TEST |
| 40680 | 40716 | case SQLITE_FCNTL_WIN32_SET_HANDLE: { |
| 40681 | 40717 | LPHANDLE phFile = (LPHANDLE)pArg; |
| 40682 | 40718 | HANDLE hOldFile = pFile->h; |
| 40683 | 40719 | pFile->h = *phFile; |
| @@ -44715,11 +44751,11 @@ | ||
| 44715 | 44751 | szBulk = pCache->szAlloc * (i64)pcache1.nInitPage; |
| 44716 | 44752 | }else{ |
| 44717 | 44753 | szBulk = -1024 * (i64)pcache1.nInitPage; |
| 44718 | 44754 | } |
| 44719 | 44755 | if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){ |
| 44720 | - szBulk = pCache->szAlloc*pCache->nMax; | |
| 44756 | + szBulk = pCache->szAlloc*(i64)pCache->nMax; | |
| 44721 | 44757 | } |
| 44722 | 44758 | zBulk = pCache->pBulk = sqlite3Malloc( szBulk ); |
| 44723 | 44759 | sqlite3EndBenignMalloc(); |
| 44724 | 44760 | if( zBulk ){ |
| 44725 | 44761 | int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc; |
| @@ -46249,21 +46285,21 @@ | ||
| 46249 | 46285 | #define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */ |
| 46250 | 46286 | |
| 46251 | 46287 | #ifdef SQLITE_OMIT_WAL |
| 46252 | 46288 | # define sqlite3WalOpen(x,y,z) 0 |
| 46253 | 46289 | # define sqlite3WalLimit(x,y) |
| 46254 | -# define sqlite3WalClose(w,x,y,z) 0 | |
| 46290 | +# define sqlite3WalClose(v,w,x,y,z) 0 | |
| 46255 | 46291 | # define sqlite3WalBeginReadTransaction(y,z) 0 |
| 46256 | 46292 | # define sqlite3WalEndReadTransaction(z) |
| 46257 | 46293 | # define sqlite3WalDbsize(y) 0 |
| 46258 | 46294 | # define sqlite3WalBeginWriteTransaction(y) 0 |
| 46259 | 46295 | # define sqlite3WalEndWriteTransaction(x) 0 |
| 46260 | 46296 | # define sqlite3WalUndo(x,y,z) 0 |
| 46261 | 46297 | # define sqlite3WalSavepoint(y,z) |
| 46262 | 46298 | # define sqlite3WalSavepointUndo(y,z) 0 |
| 46263 | 46299 | # define sqlite3WalFrames(u,v,w,x,y,z) 0 |
| 46264 | -# define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0 | |
| 46300 | +# define sqlite3WalCheckpoint(q,r,s,t,u,v,w,x,y,z) 0 | |
| 46265 | 46301 | # define sqlite3WalCallback(z) 0 |
| 46266 | 46302 | # define sqlite3WalExclusiveMode(y,z) 0 |
| 46267 | 46303 | # define sqlite3WalHeapMemory(z) 0 |
| 46268 | 46304 | # define sqlite3WalFramesize(z) 0 |
| 46269 | 46305 | # define sqlite3WalFindFrame(x,y,z) 0 |
| @@ -46277,11 +46313,11 @@ | ||
| 46277 | 46313 | */ |
| 46278 | 46314 | typedef struct Wal Wal; |
| 46279 | 46315 | |
| 46280 | 46316 | /* Open and close a connection to a write-ahead log. */ |
| 46281 | 46317 | SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**); |
| 46282 | -SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *); | |
| 46318 | +SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, sqlite3*, int sync_flags, int, u8 *); | |
| 46283 | 46319 | |
| 46284 | 46320 | /* Set the limiting size of a WAL file. */ |
| 46285 | 46321 | SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64); |
| 46286 | 46322 | |
| 46287 | 46323 | /* Used by readers to open (lock) and close (unlock) a snapshot. A |
| @@ -46320,10 +46356,11 @@ | ||
| 46320 | 46356 | SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int); |
| 46321 | 46357 | |
| 46322 | 46358 | /* Copy pages from the log to the database file */ |
| 46323 | 46359 | SQLITE_PRIVATE int sqlite3WalCheckpoint( |
| 46324 | 46360 | Wal *pWal, /* Write-ahead log connection */ |
| 46361 | + sqlite3 *db, /* Check this handle's interrupt flag */ | |
| 46325 | 46362 | int eMode, /* One of PASSIVE, FULL and RESTART */ |
| 46326 | 46363 | int (*xBusy)(void*), /* Function to call when busy */ |
| 46327 | 46364 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 46328 | 46365 | int sync_flags, /* Flags to sync db file with (or 0) */ |
| 46329 | 46366 | int nBuf, /* Size of buffer nBuf */ |
| @@ -47164,13 +47201,14 @@ | ||
| 47164 | 47201 | /* |
| 47165 | 47202 | ** Return true if this pager uses a write-ahead log instead of the usual |
| 47166 | 47203 | ** rollback journal. Otherwise false. |
| 47167 | 47204 | */ |
| 47168 | 47205 | #ifndef SQLITE_OMIT_WAL |
| 47169 | -static int pagerUseWal(Pager *pPager){ | |
| 47206 | +SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager){ | |
| 47170 | 47207 | return (pPager->pWal!=0); |
| 47171 | 47208 | } |
| 47209 | +# define pagerUseWal(x) sqlite3PagerUseWal(x) | |
| 47172 | 47210 | #else |
| 47173 | 47211 | # define pagerUseWal(x) 0 |
| 47174 | 47212 | # define pagerRollbackWal(x) 0 |
| 47175 | 47213 | # define pagerWalFrames(v,w,x,y) 0 |
| 47176 | 47214 | # define pagerOpenWalIfPresent(z) SQLITE_OK |
| @@ -50368,21 +50406,22 @@ | ||
| 50368 | 50406 | ** This function always succeeds. If a transaction is active an attempt |
| 50369 | 50407 | ** is made to roll it back. If an error occurs during the rollback |
| 50370 | 50408 | ** a hot journal may be left in the filesystem but no error is returned |
| 50371 | 50409 | ** to the caller. |
| 50372 | 50410 | */ |
| 50373 | -SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){ | |
| 50411 | +SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){ | |
| 50374 | 50412 | u8 *pTmp = (u8 *)pPager->pTmpSpace; |
| 50375 | 50413 | |
| 50414 | + assert( db || pagerUseWal(pPager)==0 ); | |
| 50376 | 50415 | assert( assert_pager_state(pPager) ); |
| 50377 | 50416 | disable_simulated_io_errors(); |
| 50378 | 50417 | sqlite3BeginBenignMalloc(); |
| 50379 | 50418 | pagerFreeMapHdrs(pPager); |
| 50380 | 50419 | /* pPager->errCode = 0; */ |
| 50381 | 50420 | pPager->exclusiveMode = 0; |
| 50382 | 50421 | #ifndef SQLITE_OMIT_WAL |
| 50383 | - sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp); | |
| 50422 | + sqlite3WalClose(pPager->pWal,db,pPager->ckptSyncFlags,pPager->pageSize,pTmp); | |
| 50384 | 50423 | pPager->pWal = 0; |
| 50385 | 50424 | #endif |
| 50386 | 50425 | pager_reset(pPager); |
| 50387 | 50426 | if( MEMDB ){ |
| 50388 | 50427 | pager_unlock(pPager); |
| @@ -53541,14 +53580,20 @@ | ||
| 53541 | 53580 | ** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint() |
| 53542 | 53581 | ** or wal_blocking_checkpoint() API functions. |
| 53543 | 53582 | ** |
| 53544 | 53583 | ** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. |
| 53545 | 53584 | */ |
| 53546 | -SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){ | |
| 53585 | +SQLITE_PRIVATE int sqlite3PagerCheckpoint( | |
| 53586 | + Pager *pPager, /* Checkpoint on this pager */ | |
| 53587 | + sqlite3 *db, /* Db handle used to check for interrupts */ | |
| 53588 | + int eMode, /* Type of checkpoint */ | |
| 53589 | + int *pnLog, /* OUT: Final number of frames in log */ | |
| 53590 | + int *pnCkpt /* OUT: Final number of checkpointed frames */ | |
| 53591 | +){ | |
| 53547 | 53592 | int rc = SQLITE_OK; |
| 53548 | 53593 | if( pPager->pWal ){ |
| 53549 | - rc = sqlite3WalCheckpoint(pPager->pWal, eMode, | |
| 53594 | + rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode, | |
| 53550 | 53595 | (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), |
| 53551 | 53596 | pPager->pBusyHandlerArg, |
| 53552 | 53597 | pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, |
| 53553 | 53598 | pnLog, pnCkpt |
| 53554 | 53599 | ); |
| @@ -53676,11 +53721,11 @@ | ||
| 53676 | 53721 | ** Before closing the log file, this function attempts to take an |
| 53677 | 53722 | ** EXCLUSIVE lock on the database file. If this cannot be obtained, an |
| 53678 | 53723 | ** error (SQLITE_BUSY) is returned and the log connection is not closed. |
| 53679 | 53724 | ** If successful, the EXCLUSIVE lock is not released before returning. |
| 53680 | 53725 | */ |
| 53681 | -SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){ | |
| 53726 | +SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){ | |
| 53682 | 53727 | int rc = SQLITE_OK; |
| 53683 | 53728 | |
| 53684 | 53729 | assert( pPager->journalMode==PAGER_JOURNALMODE_WAL ); |
| 53685 | 53730 | |
| 53686 | 53731 | /* If the log file is not already open, but does exist in the file-system, |
| @@ -53704,11 +53749,11 @@ | ||
| 53704 | 53749 | ** the database file, the log and log-summary files will be deleted. |
| 53705 | 53750 | */ |
| 53706 | 53751 | if( rc==SQLITE_OK && pPager->pWal ){ |
| 53707 | 53752 | rc = pagerExclusiveLock(pPager); |
| 53708 | 53753 | if( rc==SQLITE_OK ){ |
| 53709 | - rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, | |
| 53754 | + rc = sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags, | |
| 53710 | 53755 | pPager->pageSize, (u8*)pPager->pTmpSpace); |
| 53711 | 53756 | pPager->pWal = 0; |
| 53712 | 53757 | pagerFixMaplimit(pPager); |
| 53713 | 53758 | if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK); |
| 53714 | 53759 | } |
| @@ -55487,10 +55532,11 @@ | ||
| 55487 | 55532 | ** checkpoint is running (in any other thread or process) at the same |
| 55488 | 55533 | ** time. |
| 55489 | 55534 | */ |
| 55490 | 55535 | static int walCheckpoint( |
| 55491 | 55536 | Wal *pWal, /* Wal connection */ |
| 55537 | + sqlite3 *db, /* Check for interrupts on this handle */ | |
| 55492 | 55538 | int eMode, /* One of PASSIVE, FULL or RESTART */ |
| 55493 | 55539 | int (*xBusy)(void*), /* Function to call when busy */ |
| 55494 | 55540 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 55495 | 55541 | int sync_flags, /* Flags for OsSync() (or 0) */ |
| 55496 | 55542 | u8 *zBuf /* Temporary buffer to use */ |
| @@ -55581,10 +55627,14 @@ | ||
| 55581 | 55627 | |
| 55582 | 55628 | /* Iterate through the contents of the WAL, copying data to the db file */ |
| 55583 | 55629 | while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ |
| 55584 | 55630 | i64 iOffset; |
| 55585 | 55631 | assert( walFramePgno(pWal, iFrame)==iDbpage ); |
| 55632 | + if( db->u1.isInterrupted ){ | |
| 55633 | + rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT; | |
| 55634 | + break; | |
| 55635 | + } | |
| 55586 | 55636 | if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){ |
| 55587 | 55637 | continue; |
| 55588 | 55638 | } |
| 55589 | 55639 | iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE; |
| 55590 | 55640 | /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */ |
| @@ -55685,10 +55735,11 @@ | ||
| 55685 | 55735 | /* |
| 55686 | 55736 | ** Close a connection to a log file. |
| 55687 | 55737 | */ |
| 55688 | 55738 | SQLITE_PRIVATE int sqlite3WalClose( |
| 55689 | 55739 | Wal *pWal, /* Wal to close */ |
| 55740 | + sqlite3 *db, /* For interrupt flag */ | |
| 55690 | 55741 | int sync_flags, /* Flags to pass to OsSync() (or 0) */ |
| 55691 | 55742 | int nBuf, |
| 55692 | 55743 | u8 *zBuf /* Buffer of at least nBuf bytes */ |
| 55693 | 55744 | ){ |
| 55694 | 55745 | int rc = SQLITE_OK; |
| @@ -55701,17 +55752,18 @@ | ||
| 55701 | 55752 | ** the database. In this case checkpoint the database and unlink both |
| 55702 | 55753 | ** the wal and wal-index files. |
| 55703 | 55754 | ** |
| 55704 | 55755 | ** The EXCLUSIVE lock is not released before returning. |
| 55705 | 55756 | */ |
| 55706 | - rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE); | |
| 55707 | - if( rc==SQLITE_OK ){ | |
| 55757 | + if( (db->flags & SQLITE_NoCkptOnClose)==0 | |
| 55758 | + && SQLITE_OK==(rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE)) | |
| 55759 | + ){ | |
| 55708 | 55760 | if( pWal->exclusiveMode==WAL_NORMAL_MODE ){ |
| 55709 | 55761 | pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; |
| 55710 | 55762 | } |
| 55711 | - rc = sqlite3WalCheckpoint( | |
| 55712 | - pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0 | |
| 55763 | + rc = sqlite3WalCheckpoint(pWal, db, | |
| 55764 | + SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0 | |
| 55713 | 55765 | ); |
| 55714 | 55766 | if( rc==SQLITE_OK ){ |
| 55715 | 55767 | int bPersist = -1; |
| 55716 | 55768 | sqlite3OsFileControlHint( |
| 55717 | 55769 | pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersist |
| @@ -56955,10 +57007,11 @@ | ||
| 56955 | 57007 | ** If parameter xBusy is not NULL, it is a pointer to a busy-handler |
| 56956 | 57008 | ** callback. In this case this function runs a blocking checkpoint. |
| 56957 | 57009 | */ |
| 56958 | 57010 | SQLITE_PRIVATE int sqlite3WalCheckpoint( |
| 56959 | 57011 | Wal *pWal, /* Wal connection */ |
| 57012 | + sqlite3 *db, /* Check this handle's interrupt flag */ | |
| 56960 | 57013 | int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */ |
| 56961 | 57014 | int (*xBusy)(void*), /* Function to call when busy */ |
| 56962 | 57015 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 56963 | 57016 | int sync_flags, /* Flags to sync db file with (or 0) */ |
| 56964 | 57017 | int nBuf, /* Size of temporary buffer */ |
| @@ -57029,11 +57082,11 @@ | ||
| 57029 | 57082 | if( rc==SQLITE_OK ){ |
| 57030 | 57083 | |
| 57031 | 57084 | if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ |
| 57032 | 57085 | rc = SQLITE_CORRUPT_BKPT; |
| 57033 | 57086 | }else{ |
| 57034 | - rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); | |
| 57087 | + rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); | |
| 57035 | 57088 | } |
| 57036 | 57089 | |
| 57037 | 57090 | /* If no error occurred, set the output variables. */ |
| 57038 | 57091 | if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ |
| 57039 | 57092 | if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; |
| @@ -60619,23 +60672,30 @@ | ||
| 60619 | 60672 | *ppBtree = p; |
| 60620 | 60673 | |
| 60621 | 60674 | btree_open_out: |
| 60622 | 60675 | if( rc!=SQLITE_OK ){ |
| 60623 | 60676 | if( pBt && pBt->pPager ){ |
| 60624 | - sqlite3PagerClose(pBt->pPager); | |
| 60677 | + sqlite3PagerClose(pBt->pPager, 0); | |
| 60625 | 60678 | } |
| 60626 | 60679 | sqlite3_free(pBt); |
| 60627 | 60680 | sqlite3_free(p); |
| 60628 | 60681 | *ppBtree = 0; |
| 60629 | 60682 | }else{ |
| 60683 | + sqlite3_file *pFile; | |
| 60684 | + | |
| 60630 | 60685 | /* If the B-Tree was successfully opened, set the pager-cache size to the |
| 60631 | 60686 | ** default value. Except, when opening on an existing shared pager-cache, |
| 60632 | 60687 | ** do not change the pager-cache size. |
| 60633 | 60688 | */ |
| 60634 | 60689 | if( sqlite3BtreeSchema(p, 0, 0)==0 ){ |
| 60635 | 60690 | sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE); |
| 60636 | 60691 | } |
| 60692 | + | |
| 60693 | + pFile = sqlite3PagerFile(pBt->pPager); | |
| 60694 | + if( pFile->pMethods ){ | |
| 60695 | + sqlite3OsFileControlHint(pFile, SQLITE_FCNTL_PDB, (void*)&pBt->db); | |
| 60696 | + } | |
| 60637 | 60697 | } |
| 60638 | 60698 | if( mutexOpen ){ |
| 60639 | 60699 | assert( sqlite3_mutex_held(mutexOpen) ); |
| 60640 | 60700 | sqlite3_mutex_leave(mutexOpen); |
| 60641 | 60701 | } |
| @@ -60761,11 +60821,11 @@ | ||
| 60761 | 60821 | ** it without having to hold the mutex. |
| 60762 | 60822 | ** |
| 60763 | 60823 | ** Clean out and delete the BtShared object. |
| 60764 | 60824 | */ |
| 60765 | 60825 | assert( !pBt->pCursor ); |
| 60766 | - sqlite3PagerClose(pBt->pPager); | |
| 60826 | + sqlite3PagerClose(pBt->pPager, p->db); | |
| 60767 | 60827 | if( pBt->xFreeSchema && pBt->pSchema ){ |
| 60768 | 60828 | pBt->xFreeSchema(pBt->pSchema); |
| 60769 | 60829 | } |
| 60770 | 60830 | sqlite3DbFree(0, pBt->pSchema); |
| 60771 | 60831 | freeTempSpace(pBt); |
| @@ -62825,11 +62885,11 @@ | ||
| 62825 | 62885 | if( (eOp&0x01)==0 /* (1) */ |
| 62826 | 62886 | && offset==0 /* (2) */ |
| 62827 | 62887 | && (bEnd || a==ovflSize) /* (6) */ |
| 62828 | 62888 | && pBt->inTransaction==TRANS_READ /* (4) */ |
| 62829 | 62889 | && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */ |
| 62830 | - && pBt->pPage1->aData[19]==0x01 /* (5) */ | |
| 62890 | + && 0==sqlite3PagerUseWal(pBt->pPager) /* (5) */ | |
| 62831 | 62891 | && &pBuf[-4]>=pBufStart /* (7) */ |
| 62832 | 62892 | ){ |
| 62833 | 62893 | u8 aSave[4]; |
| 62834 | 62894 | u8 *aWrite = &pBuf[-4]; |
| 62835 | 62895 | assert( aWrite>=pBufStart ); /* hence (7) */ |
| @@ -63081,13 +63141,16 @@ | ||
| 63081 | 63141 | } |
| 63082 | 63142 | sqlite3BtreeClearCursor(pCur); |
| 63083 | 63143 | } |
| 63084 | 63144 | |
| 63085 | 63145 | if( pCur->iPage>=0 ){ |
| 63086 | - while( pCur->iPage ){ | |
| 63087 | - assert( pCur->apPage[pCur->iPage]!=0 ); | |
| 63088 | - releasePageNotNull(pCur->apPage[pCur->iPage--]); | |
| 63146 | + if( pCur->iPage ){ | |
| 63147 | + do{ | |
| 63148 | + assert( pCur->apPage[pCur->iPage]!=0 ); | |
| 63149 | + releasePageNotNull(pCur->apPage[pCur->iPage--]); | |
| 63150 | + }while( pCur->iPage); | |
| 63151 | + goto skip_init; | |
| 63089 | 63152 | } |
| 63090 | 63153 | }else if( pCur->pgnoRoot==0 ){ |
| 63091 | 63154 | pCur->eState = CURSOR_INVALID; |
| 63092 | 63155 | return SQLITE_OK; |
| 63093 | 63156 | }else{ |
| @@ -63094,11 +63157,11 @@ | ||
| 63094 | 63157 | assert( pCur->iPage==(-1) ); |
| 63095 | 63158 | rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0], |
| 63096 | 63159 | 0, pCur->curPagerFlags); |
| 63097 | 63160 | if( rc!=SQLITE_OK ){ |
| 63098 | 63161 | pCur->eState = CURSOR_INVALID; |
| 63099 | - return rc; | |
| 63162 | + return rc; | |
| 63100 | 63163 | } |
| 63101 | 63164 | pCur->iPage = 0; |
| 63102 | 63165 | pCur->curIntKey = pCur->apPage[0]->intKey; |
| 63103 | 63166 | } |
| 63104 | 63167 | pRoot = pCur->apPage[0]; |
| @@ -63117,14 +63180,16 @@ | ||
| 63117 | 63180 | assert( pRoot->intKey==1 || pRoot->intKey==0 ); |
| 63118 | 63181 | if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){ |
| 63119 | 63182 | return SQLITE_CORRUPT_BKPT; |
| 63120 | 63183 | } |
| 63121 | 63184 | |
| 63185 | +skip_init: | |
| 63122 | 63186 | pCur->aiIdx[0] = 0; |
| 63123 | 63187 | pCur->info.nSize = 0; |
| 63124 | 63188 | pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl); |
| 63125 | 63189 | |
| 63190 | + pRoot = pCur->apPage[0]; | |
| 63126 | 63191 | if( pRoot->nCell>0 ){ |
| 63127 | 63192 | pCur->eState = CURSOR_VALID; |
| 63128 | 63193 | }else if( !pRoot->leaf ){ |
| 63129 | 63194 | Pgno subpage; |
| 63130 | 63195 | if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT; |
| @@ -67701,11 +67766,11 @@ | ||
| 67701 | 67766 | BtShared *pBt = p->pBt; |
| 67702 | 67767 | sqlite3BtreeEnter(p); |
| 67703 | 67768 | if( pBt->inTransaction!=TRANS_NONE ){ |
| 67704 | 67769 | rc = SQLITE_LOCKED; |
| 67705 | 67770 | }else{ |
| 67706 | - rc = sqlite3PagerCheckpoint(pBt->pPager, eMode, pnLog, pnCkpt); | |
| 67771 | + rc = sqlite3PagerCheckpoint(pBt->pPager, p->db, eMode, pnLog, pnCkpt); | |
| 67707 | 67772 | } |
| 67708 | 67773 | sqlite3BtreeLeave(p); |
| 67709 | 67774 | } |
| 67710 | 67775 | return rc; |
| 67711 | 67776 | } |
| @@ -69336,11 +69401,11 @@ | ||
| 69336 | 69401 | switch( aff ){ |
| 69337 | 69402 | case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */ |
| 69338 | 69403 | if( (pMem->flags & MEM_Blob)==0 ){ |
| 69339 | 69404 | sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding); |
| 69340 | 69405 | assert( pMem->flags & MEM_Str || pMem->db->mallocFailed ); |
| 69341 | - MemSetTypeFlag(pMem, MEM_Blob); | |
| 69406 | + if( pMem->flags & MEM_Str ) MemSetTypeFlag(pMem, MEM_Blob); | |
| 69342 | 69407 | }else{ |
| 69343 | 69408 | pMem->flags &= ~(MEM_TypeMask&~MEM_Blob); |
| 69344 | 69409 | } |
| 69345 | 69410 | break; |
| 69346 | 69411 | } |
| @@ -75076,11 +75141,11 @@ | ||
| 75076 | 75141 | preupdate.keyinfo.enc = ENC(db); |
| 75077 | 75142 | preupdate.keyinfo.nField = pTab->nCol; |
| 75078 | 75143 | preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder; |
| 75079 | 75144 | preupdate.iKey1 = iKey1; |
| 75080 | 75145 | preupdate.iKey2 = iKey2; |
| 75081 | - preupdate.iPKey = pTab->iPKey; | |
| 75146 | + preupdate.pTab = pTab; | |
| 75082 | 75147 | |
| 75083 | 75148 | db->pPreUpdate = &preupdate; |
| 75084 | 75149 | db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2); |
| 75085 | 75150 | db->pPreUpdate = 0; |
| 75086 | 75151 | sqlite3DbFree(db, preupdate.aRecord); |
| @@ -76808,13 +76873,18 @@ | ||
| 76808 | 76873 | } |
| 76809 | 76874 | |
| 76810 | 76875 | if( iIdx>=p->pUnpacked->nField ){ |
| 76811 | 76876 | *ppValue = (sqlite3_value *)columnNullValue(); |
| 76812 | 76877 | }else{ |
| 76878 | + Mem *pMem = *ppValue = &p->pUnpacked->aMem[iIdx]; | |
| 76813 | 76879 | *ppValue = &p->pUnpacked->aMem[iIdx]; |
| 76814 | - if( iIdx==p->iPKey ){ | |
| 76815 | - sqlite3VdbeMemSetInt64(*ppValue, p->iKey1); | |
| 76880 | + if( iIdx==p->pTab->iPKey ){ | |
| 76881 | + sqlite3VdbeMemSetInt64(pMem, p->iKey1); | |
| 76882 | + }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){ | |
| 76883 | + if( pMem->flags & MEM_Int ){ | |
| 76884 | + sqlite3VdbeMemRealify(pMem); | |
| 76885 | + } | |
| 76816 | 76886 | } |
| 76817 | 76887 | } |
| 76818 | 76888 | |
| 76819 | 76889 | preupdate_old_out: |
| 76820 | 76890 | sqlite3Error(db, rc); |
| @@ -76887,11 +76957,11 @@ | ||
| 76887 | 76957 | } |
| 76888 | 76958 | if( iIdx>=pUnpack->nField ){ |
| 76889 | 76959 | pMem = (sqlite3_value *)columnNullValue(); |
| 76890 | 76960 | }else{ |
| 76891 | 76961 | pMem = &pUnpack->aMem[iIdx]; |
| 76892 | - if( iIdx==p->iPKey ){ | |
| 76962 | + if( iIdx==p->pTab->iPKey ){ | |
| 76893 | 76963 | sqlite3VdbeMemSetInt64(pMem, p->iKey2); |
| 76894 | 76964 | } |
| 76895 | 76965 | } |
| 76896 | 76966 | }else{ |
| 76897 | 76967 | /* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required |
| @@ -76908,11 +76978,11 @@ | ||
| 76908 | 76978 | } |
| 76909 | 76979 | } |
| 76910 | 76980 | assert( iIdx>=0 && iIdx<p->pCsr->nField ); |
| 76911 | 76981 | pMem = &p->aNew[iIdx]; |
| 76912 | 76982 | if( pMem->flags==0 ){ |
| 76913 | - if( iIdx==p->iPKey ){ | |
| 76983 | + if( iIdx==p->pTab->iPKey ){ | |
| 76914 | 76984 | sqlite3VdbeMemSetInt64(pMem, p->iKey2); |
| 76915 | 76985 | }else{ |
| 76916 | 76986 | rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]); |
| 76917 | 76987 | if( rc!=SQLITE_OK ) goto preupdate_new_out; |
| 76918 | 76988 | } |
| @@ -79286,12 +79356,11 @@ | ||
| 79286 | 79356 | ** or not both operands are null. |
| 79287 | 79357 | */ |
| 79288 | 79358 | assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne ); |
| 79289 | 79359 | assert( (flags1 & MEM_Cleared)==0 ); |
| 79290 | 79360 | assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 ); |
| 79291 | - if( (flags1&MEM_Null)!=0 | |
| 79292 | - && (flags3&MEM_Null)!=0 | |
| 79361 | + if( (flags1&flags3&MEM_Null)!=0 | |
| 79293 | 79362 | && (flags3&MEM_Cleared)==0 |
| 79294 | 79363 | ){ |
| 79295 | 79364 | res = 0; /* Operands are equal */ |
| 79296 | 79365 | }else{ |
| 79297 | 79366 | res = 1; /* Operands are not equal */ |
| @@ -81554,11 +81623,11 @@ | ||
| 81554 | 81623 | |
| 81555 | 81624 | REGISTER_TRACE(pOp->p3, pMem); |
| 81556 | 81625 | sqlite3VdbeMemIntegerify(pMem); |
| 81557 | 81626 | assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ |
| 81558 | 81627 | if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){ |
| 81559 | - rc = SQLITE_FULL; /* IMP: R-12275-61338 */ | |
| 81628 | + rc = SQLITE_FULL; /* IMP: R-17817-00630 */ | |
| 81560 | 81629 | goto abort_due_to_error; |
| 81561 | 81630 | } |
| 81562 | 81631 | if( v<pMem->u.i+1 ){ |
| 81563 | 81632 | v = pMem->u.i + 1; |
| 81564 | 81633 | } |
| @@ -82321,10 +82390,17 @@ | ||
| 82321 | 82390 | ** This flag avoids doing an extra seek. |
| 82322 | 82391 | ** |
| 82323 | 82392 | ** This instruction only works for indices. The equivalent instruction |
| 82324 | 82393 | ** for tables is OP_Insert. |
| 82325 | 82394 | */ |
| 82395 | +/* Opcode: SorterInsert P1 P2 * * * | |
| 82396 | +** Synopsis: key=r[P2] | |
| 82397 | +** | |
| 82398 | +** Register P2 holds an SQL index key made using the | |
| 82399 | +** MakeRecord instructions. This opcode writes that key | |
| 82400 | +** into the sorter P1. Data for the entry is nil. | |
| 82401 | +*/ | |
| 82326 | 82402 | case OP_SorterInsert: /* in2 */ |
| 82327 | 82403 | case OP_IdxInsert: { /* in2 */ |
| 82328 | 82404 | VdbeCursor *pC; |
| 82329 | 82405 | BtreePayload x; |
| 82330 | 82406 | |
| @@ -83549,11 +83625,11 @@ | ||
| 83549 | 83625 | /* If leaving WAL mode, close the log file. If successful, the call |
| 83550 | 83626 | ** to PagerCloseWal() checkpoints and deletes the write-ahead-log |
| 83551 | 83627 | ** file. An EXCLUSIVE lock may still be held on the database file |
| 83552 | 83628 | ** after a successful return. |
| 83553 | 83629 | */ |
| 83554 | - rc = sqlite3PagerCloseWal(pPager); | |
| 83630 | + rc = sqlite3PagerCloseWal(pPager, db); | |
| 83555 | 83631 | if( rc==SQLITE_OK ){ |
| 83556 | 83632 | sqlite3PagerSetJournalMode(pPager, eNew); |
| 83557 | 83633 | } |
| 83558 | 83634 | }else if( eOld==PAGER_JOURNALMODE_MEMORY ){ |
| 83559 | 83635 | /* Cannot transition directly from MEMORY to WAL. Use mode OFF |
| @@ -88812,11 +88888,10 @@ | ||
| 88812 | 88888 | const char *zId; /* The function name. */ |
| 88813 | 88889 | FuncDef *pDef; /* Information about the function */ |
| 88814 | 88890 | u8 enc = ENC(pParse->db); /* The database encoding */ |
| 88815 | 88891 | |
| 88816 | 88892 | assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); |
| 88817 | -// notValid(pParse, pNC, "functions", NC_PartIdx); | |
| 88818 | 88893 | zId = pExpr->u.zToken; |
| 88819 | 88894 | nId = sqlite3Strlen30(zId); |
| 88820 | 88895 | pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0); |
| 88821 | 88896 | if( pDef==0 ){ |
| 88822 | 88897 | pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0); |
| @@ -94293,15 +94368,14 @@ | ||
| 94293 | 94368 | && (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab) |
| 94294 | 94369 | || sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) ) |
| 94295 | 94370 | ){ |
| 94296 | 94371 | return 1; |
| 94297 | 94372 | } |
| 94298 | - if( pE2->op==TK_NOTNULL | |
| 94299 | - && sqlite3ExprCompare(pE1->pLeft, pE2->pLeft, iTab)==0 | |
| 94300 | - && (pE1->op!=TK_ISNULL && pE1->op!=TK_IS) | |
| 94301 | - ){ | |
| 94302 | - return 1; | |
| 94373 | + if( pE2->op==TK_NOTNULL && pE1->op!=TK_ISNULL && pE1->op!=TK_IS ){ | |
| 94374 | + Expr *pX = sqlite3ExprSkipCollate(pE1->pLeft); | |
| 94375 | + testcase( pX!=pE1->pLeft ); | |
| 94376 | + if( sqlite3ExprCompare(pX, pE2->pLeft, iTab)==0 ) return 1; | |
| 94303 | 94377 | } |
| 94304 | 94378 | return 0; |
| 94305 | 94379 | } |
| 94306 | 94380 | |
| 94307 | 94381 | /* |
| @@ -122355,11 +122429,11 @@ | ||
| 122355 | 122429 | } |
| 122356 | 122430 | #endif |
| 122357 | 122431 | |
| 122358 | 122432 | sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size); |
| 122359 | 122433 | sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0)); |
| 122360 | - sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF); | |
| 122434 | + sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF|PAGER_CACHESPILL); | |
| 122361 | 122435 | |
| 122362 | 122436 | /* Begin a transaction and take an exclusive lock on the main database |
| 122363 | 122437 | ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below, |
| 122364 | 122438 | ** to ensure that we do not try to change the page-size on a WAL database. |
| 122365 | 122439 | */ |
| @@ -124663,11 +124737,10 @@ | ||
| 124663 | 124737 | ** |
| 124664 | 124738 | ** * the comparison will be performed with no affinity, or |
| 124665 | 124739 | ** * the affinity change in zAff is guaranteed not to change the value. |
| 124666 | 124740 | */ |
| 124667 | 124741 | static void updateRangeAffinityStr( |
| 124668 | - Parse *pParse, /* Parse context */ | |
| 124669 | 124742 | Expr *pRight, /* RHS of comparison */ |
| 124670 | 124743 | int n, /* Number of vector elements in comparison */ |
| 124671 | 124744 | char *zAff /* Affinity string to modify */ |
| 124672 | 124745 | ){ |
| 124673 | 124746 | int i; |
| @@ -125749,15 +125822,15 @@ | ||
| 125749 | 125822 | assert( (bRev & ~1)==0 ); |
| 125750 | 125823 | pLevel->iLikeRepCntr <<=1; |
| 125751 | 125824 | pLevel->iLikeRepCntr |= bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC); |
| 125752 | 125825 | } |
| 125753 | 125826 | #endif |
| 125754 | - if( pRangeStart==0 | |
| 125755 | - && (j = pIdx->aiColumn[nEq])>=0 | |
| 125756 | - && pIdx->pTable->aCol[j].notNull==0 | |
| 125757 | - ){ | |
| 125758 | - bSeekPastNull = 1; | |
| 125827 | + if( pRangeStart==0 ){ | |
| 125828 | + j = pIdx->aiColumn[nEq]; | |
| 125829 | + if( (j>=0 && pIdx->pTable->aCol[j].notNull==0) || j==XN_EXPR ){ | |
| 125830 | + bSeekPastNull = 1; | |
| 125831 | + } | |
| 125759 | 125832 | } |
| 125760 | 125833 | } |
| 125761 | 125834 | assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 ); |
| 125762 | 125835 | |
| 125763 | 125836 | /* If we are doing a reverse order scan on an ascending index, or |
| @@ -125803,11 +125876,11 @@ | ||
| 125803 | 125876 | ){ |
| 125804 | 125877 | sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); |
| 125805 | 125878 | VdbeCoverage(v); |
| 125806 | 125879 | } |
| 125807 | 125880 | if( zStartAff ){ |
| 125808 | - updateRangeAffinityStr(pParse, pRight, nBtm, &zStartAff[nEq]); | |
| 125881 | + updateRangeAffinityStr(pRight, nBtm, &zStartAff[nEq]); | |
| 125809 | 125882 | } |
| 125810 | 125883 | nConstraint += nBtm; |
| 125811 | 125884 | testcase( pRangeStart->wtFlags & TERM_VIRTUAL ); |
| 125812 | 125885 | if( sqlite3ExprIsVector(pRight)==0 ){ |
| 125813 | 125886 | disableTerm(pLevel, pRangeStart); |
| @@ -125853,11 +125926,11 @@ | ||
| 125853 | 125926 | ){ |
| 125854 | 125927 | sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); |
| 125855 | 125928 | VdbeCoverage(v); |
| 125856 | 125929 | } |
| 125857 | 125930 | if( zEndAff ){ |
| 125858 | - updateRangeAffinityStr(pParse, pRight, nTop, zEndAff); | |
| 125931 | + updateRangeAffinityStr(pRight, nTop, zEndAff); | |
| 125859 | 125932 | codeApplyAffinity(pParse, regBase+nEq, nTop, zEndAff); |
| 125860 | 125933 | }else{ |
| 125861 | 125934 | assert( pParse->db->mallocFailed ); |
| 125862 | 125935 | } |
| 125863 | 125936 | nConstraint += nTop; |
| @@ -127539,10 +127612,11 @@ | ||
| 127539 | 127612 | Expr *pNew; |
| 127540 | 127613 | Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i); |
| 127541 | 127614 | Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i); |
| 127542 | 127615 | |
| 127543 | 127616 | pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight, 0); |
| 127617 | + transferJoinMarkings(pNew, pExpr); | |
| 127544 | 127618 | idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC); |
| 127545 | 127619 | exprAnalyze(pSrc, pWC, idxNew); |
| 127546 | 127620 | } |
| 127547 | 127621 | pTerm = &pWC->a[idxTerm]; |
| 127548 | 127622 | pTerm->wtFlags = TERM_CODED|TERM_VIRTUAL; /* Disable the original */ |
| @@ -127980,15 +128054,17 @@ | ||
| 127980 | 128054 | Expr *pX; /* An expression being tested */ |
| 127981 | 128055 | WhereClause *pWC; /* Shorthand for pScan->pWC */ |
| 127982 | 128056 | WhereTerm *pTerm; /* The term being tested */ |
| 127983 | 128057 | int k = pScan->k; /* Where to start scanning */ |
| 127984 | 128058 | |
| 127985 | - while( pScan->iEquiv<=pScan->nEquiv ){ | |
| 127986 | - iCur = pScan->aiCur[pScan->iEquiv-1]; | |
| 128059 | + assert( pScan->iEquiv<=pScan->nEquiv ); | |
| 128060 | + pWC = pScan->pWC; | |
| 128061 | + while(1){ | |
| 127987 | 128062 | iColumn = pScan->aiColumn[pScan->iEquiv-1]; |
| 127988 | - if( iColumn==XN_EXPR && pScan->pIdxExpr==0 ) return 0; | |
| 127989 | - while( (pWC = pScan->pWC)!=0 ){ | |
| 128063 | + iCur = pScan->aiCur[pScan->iEquiv-1]; | |
| 128064 | + assert( pWC!=0 ); | |
| 128065 | + do{ | |
| 127990 | 128066 | for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){ |
| 127991 | 128067 | if( pTerm->leftCursor==iCur |
| 127992 | 128068 | && pTerm->u.leftColumn==iColumn |
| 127993 | 128069 | && (iColumn!=XN_EXPR |
| 127994 | 128070 | || sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0) |
| @@ -128034,19 +128110,21 @@ | ||
| 128034 | 128110 | && pX->iColumn==pScan->aiColumn[0] |
| 128035 | 128111 | ){ |
| 128036 | 128112 | testcase( pTerm->eOperator & WO_IS ); |
| 128037 | 128113 | continue; |
| 128038 | 128114 | } |
| 128115 | + pScan->pWC = pWC; | |
| 128039 | 128116 | pScan->k = k+1; |
| 128040 | 128117 | return pTerm; |
| 128041 | 128118 | } |
| 128042 | 128119 | } |
| 128043 | 128120 | } |
| 128044 | - pScan->pWC = pScan->pWC->pOuter; | |
| 128121 | + pWC = pWC->pOuter; | |
| 128045 | 128122 | k = 0; |
| 128046 | - } | |
| 128047 | - pScan->pWC = pScan->pOrigWC; | |
| 128123 | + }while( pWC!=0 ); | |
| 128124 | + if( pScan->iEquiv>=pScan->nEquiv ) break; | |
| 128125 | + pWC = pScan->pOrigWC; | |
| 128048 | 128126 | k = 0; |
| 128049 | 128127 | pScan->iEquiv++; |
| 128050 | 128128 | } |
| 128051 | 128129 | return 0; |
| 128052 | 128130 | } |
| @@ -128076,28 +128154,28 @@ | ||
| 128076 | 128154 | int iCur, /* Cursor to scan for */ |
| 128077 | 128155 | int iColumn, /* Column to scan for */ |
| 128078 | 128156 | u32 opMask, /* Operator(s) to scan for */ |
| 128079 | 128157 | Index *pIdx /* Must be compatible with this index */ |
| 128080 | 128158 | ){ |
| 128081 | - int j = 0; | |
| 128082 | - | |
| 128083 | - /* memset(pScan, 0, sizeof(*pScan)); */ | |
| 128084 | 128159 | pScan->pOrigWC = pWC; |
| 128085 | 128160 | pScan->pWC = pWC; |
| 128086 | 128161 | pScan->pIdxExpr = 0; |
| 128162 | + pScan->idxaff = 0; | |
| 128163 | + pScan->zCollName = 0; | |
| 128087 | 128164 | if( pIdx ){ |
| 128088 | - j = iColumn; | |
| 128165 | + int j = iColumn; | |
| 128089 | 128166 | iColumn = pIdx->aiColumn[j]; |
| 128090 | - if( iColumn==XN_EXPR ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; | |
| 128091 | - if( iColumn==pIdx->pTable->iPKey ) iColumn = XN_ROWID; | |
| 128092 | - } | |
| 128093 | - if( pIdx && iColumn>=0 ){ | |
| 128094 | - pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; | |
| 128095 | - pScan->zCollName = pIdx->azColl[j]; | |
| 128096 | - }else{ | |
| 128097 | - pScan->idxaff = 0; | |
| 128098 | - pScan->zCollName = 0; | |
| 128167 | + if( iColumn==XN_EXPR ){ | |
| 128168 | + pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; | |
| 128169 | + }else if( iColumn==pIdx->pTable->iPKey ){ | |
| 128170 | + iColumn = XN_ROWID; | |
| 128171 | + }else if( iColumn>=0 ){ | |
| 128172 | + pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; | |
| 128173 | + pScan->zCollName = pIdx->azColl[j]; | |
| 128174 | + } | |
| 128175 | + }else if( iColumn==XN_EXPR ){ | |
| 128176 | + return 0; | |
| 128099 | 128177 | } |
| 128100 | 128178 | pScan->opMask = opMask; |
| 128101 | 128179 | pScan->k = 0; |
| 128102 | 128180 | pScan->aiCur[0] = iCur; |
| 128103 | 128181 | pScan->aiColumn[0] = iColumn; |
| @@ -130005,11 +130083,11 @@ | ||
| 130005 | 130083 | ** CREATE INDEX ... ON (a, b, c, d, e) |
| 130006 | 130084 | ** |
| 130007 | 130085 | ** then this function would be invoked with nEq=1. The value returned in |
| 130008 | 130086 | ** this case is 3. |
| 130009 | 130087 | */ |
| 130010 | -int whereRangeVectorLen( | |
| 130088 | +static int whereRangeVectorLen( | |
| 130011 | 130089 | Parse *pParse, /* Parsing context */ |
| 130012 | 130090 | int iCur, /* Cursor open on pIdx */ |
| 130013 | 130091 | Index *pIdx, /* The index to be used for a inequality constraint */ |
| 130014 | 130092 | int nEq, /* Number of prior equality constraints on same index */ |
| 130015 | 130093 | WhereTerm *pTerm /* The vector inequality constraint */ |
| @@ -131451,11 +131529,11 @@ | ||
| 131451 | 131529 | if( rev ) *pRevMask |= MASKBIT(iLoop); |
| 131452 | 131530 | revSet = 1; |
| 131453 | 131531 | } |
| 131454 | 131532 | } |
| 131455 | 131533 | if( isMatch ){ |
| 131456 | - if( iColumn<0 ){ | |
| 131534 | + if( iColumn==XN_ROWID ){ | |
| 131457 | 131535 | testcase( distinctColumns==0 ); |
| 131458 | 131536 | distinctColumns = 1; |
| 131459 | 131537 | } |
| 131460 | 131538 | obSat |= MASKBIT(i); |
| 131461 | 131539 | }else{ |
| @@ -131906,17 +131984,24 @@ | ||
| 131906 | 131984 | }else{ |
| 131907 | 131985 | pWInfo->nOBSat = pFrom->isOrdered; |
| 131908 | 131986 | pWInfo->revMask = pFrom->revLoop; |
| 131909 | 131987 | if( pWInfo->nOBSat<=0 ){ |
| 131910 | 131988 | pWInfo->nOBSat = 0; |
| 131911 | - if( nLoop>0 && (pFrom->aLoop[nLoop-1]->wsFlags & WHERE_ONEROW)==0 ){ | |
| 131912 | - Bitmask m = 0; | |
| 131913 | - int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom, | |
| 131989 | + if( nLoop>0 ){ | |
| 131990 | + u32 wsFlags = pFrom->aLoop[nLoop-1]->wsFlags; | |
| 131991 | + if( (wsFlags & WHERE_ONEROW)==0 | |
| 131992 | + && (wsFlags&(WHERE_IPK|WHERE_COLUMN_IN))!=(WHERE_IPK|WHERE_COLUMN_IN) | |
| 131993 | + ){ | |
| 131994 | + Bitmask m = 0; | |
| 131995 | + int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom, | |
| 131914 | 131996 | WHERE_ORDERBY_LIMIT, nLoop-1, pFrom->aLoop[nLoop-1], &m); |
| 131915 | - if( rc==pWInfo->pOrderBy->nExpr ){ | |
| 131916 | - pWInfo->bOrderedInnerLoop = 1; | |
| 131917 | - pWInfo->revMask = m; | |
| 131997 | + testcase( wsFlags & WHERE_IPK ); | |
| 131998 | + testcase( wsFlags & WHERE_COLUMN_IN ); | |
| 131999 | + if( rc==pWInfo->pOrderBy->nExpr ){ | |
| 132000 | + pWInfo->bOrderedInnerLoop = 1; | |
| 132001 | + pWInfo->revMask = m; | |
| 132002 | + } | |
| 131918 | 132003 | } |
| 131919 | 132004 | } |
| 131920 | 132005 | } |
| 131921 | 132006 | } |
| 131922 | 132007 | if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP) |
| @@ -132635,17 +132720,19 @@ | ||
| 132635 | 132720 | pLevel->addrLikeRep); |
| 132636 | 132721 | VdbeCoverage(v); |
| 132637 | 132722 | } |
| 132638 | 132723 | #endif |
| 132639 | 132724 | if( pLevel->iLeftJoin ){ |
| 132725 | + int ws = pLoop->wsFlags; | |
| 132640 | 132726 | addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v); |
| 132641 | - assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 | |
| 132642 | - || (pLoop->wsFlags & WHERE_INDEXED)!=0 ); | |
| 132643 | - if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 ){ | |
| 132727 | + assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 ); | |
| 132728 | + if( (ws & WHERE_IDX_ONLY)==0 ){ | |
| 132644 | 132729 | sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor); |
| 132645 | 132730 | } |
| 132646 | - if( pLoop->wsFlags & WHERE_INDEXED ){ | |
| 132731 | + if( (ws & WHERE_INDEXED) | |
| 132732 | + || ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx) | |
| 132733 | + ){ | |
| 132647 | 132734 | sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur); |
| 132648 | 132735 | } |
| 132649 | 132736 | if( pLevel->op==OP_Return ){ |
| 132650 | 132737 | sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst); |
| 132651 | 132738 | }else{ |
| @@ -138607,10 +138694,11 @@ | ||
| 138607 | 138694 | } aFlagOp[] = { |
| 138608 | 138695 | { SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys }, |
| 138609 | 138696 | { SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger }, |
| 138610 | 138697 | { SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer }, |
| 138611 | 138698 | { SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension }, |
| 138699 | + { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose }, | |
| 138612 | 138700 | }; |
| 138613 | 138701 | unsigned int i; |
| 138614 | 138702 | rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ |
| 138615 | 138703 | for(i=0; i<ArraySize(aFlagOp); i++){ |
| 138616 | 138704 | if( aFlagOp[i].op==op ){ |
| @@ -139903,10 +139991,17 @@ | ||
| 139903 | 139991 | db->busyHandler.nBusy = 0; |
| 139904 | 139992 | rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt); |
| 139905 | 139993 | sqlite3Error(db, rc); |
| 139906 | 139994 | } |
| 139907 | 139995 | rc = sqlite3ApiExit(db, rc); |
| 139996 | + | |
| 139997 | + /* If there are no active statements, clear the interrupt flag at this | |
| 139998 | + ** point. */ | |
| 139999 | + if( db->nVdbeActive==0 ){ | |
| 140000 | + db->u1.isInterrupted = 0; | |
| 140001 | + } | |
| 140002 | + | |
| 139908 | 140003 | sqlite3_mutex_leave(db->mutex); |
| 139909 | 140004 | return rc; |
| 139910 | 140005 | #endif |
| 139911 | 140006 | } |
| 139912 | 140007 | |
| @@ -140405,10 +140500,11 @@ | ||
| 140405 | 140500 | int octet = (sqlite3HexToInt(zUri[iIn++]) << 4); |
| 140406 | 140501 | octet += sqlite3HexToInt(zUri[iIn++]); |
| 140407 | 140502 | |
| 140408 | 140503 | assert( octet>=0 && octet<256 ); |
| 140409 | 140504 | if( octet==0 ){ |
| 140505 | +#ifndef SQLITE_ENABLE_URI_00_ERROR | |
| 140410 | 140506 | /* This branch is taken when "%00" appears within the URI. In this |
| 140411 | 140507 | ** case we ignore all text in the remainder of the path, name or |
| 140412 | 140508 | ** value currently being parsed. So ignore the current character |
| 140413 | 140509 | ** and skip to the next "?", "=" or "&", as appropriate. */ |
| 140414 | 140510 | while( (c = zUri[iIn])!=0 && c!='#' |
| @@ -140417,10 +140513,16 @@ | ||
| 140417 | 140513 | && (eState!=2 || c!='&') |
| 140418 | 140514 | ){ |
| 140419 | 140515 | iIn++; |
| 140420 | 140516 | } |
| 140421 | 140517 | continue; |
| 140518 | +#else | |
| 140519 | + /* If ENABLE_URI_00_ERROR is defined, "%00" in a URI is an error. */ | |
| 140520 | + *pzErrMsg = sqlite3_mprintf("unexpected %%00 in uri"); | |
| 140521 | + rc = SQLITE_ERROR; | |
| 140522 | + goto parse_uri_out; | |
| 140523 | +#endif | |
| 140422 | 140524 | } |
| 140423 | 140525 | c = octet; |
| 140424 | 140526 | }else if( eState==1 && (c=='&' || c=='=') ){ |
| 140425 | 140527 | if( zFile[iOut-1]==0 ){ |
| 140426 | 140528 | /* An empty option name. Ignore this option altogether. */ |
| @@ -164296,14 +164398,16 @@ | ||
| 164296 | 164398 | char *zSql; |
| 164297 | 164399 | sqlite3_stmt *p; |
| 164298 | 164400 | int rc; |
| 164299 | 164401 | i64 nRow = 0; |
| 164300 | 164402 | |
| 164301 | - if( sqlite3_table_column_metadata(db,pRtree->zDb,"sqlite_stat1", | |
| 164302 | - 0,0,0,0,0,0)==SQLITE_ERROR ){ | |
| 164403 | + rc = sqlite3_table_column_metadata( | |
| 164404 | + db, pRtree->zDb, "sqlite_stat1",0,0,0,0,0,0 | |
| 164405 | + ); | |
| 164406 | + if( rc!=SQLITE_OK ){ | |
| 164303 | 164407 | pRtree->nRowEst = RTREE_DEFAULT_ROWEST; |
| 164304 | - return SQLITE_OK; | |
| 164408 | + return rc==SQLITE_ERROR ? SQLITE_OK : rc; | |
| 164305 | 164409 | } |
| 164306 | 164410 | zSql = sqlite3_mprintf(zFmt, pRtree->zDb, pRtree->zName); |
| 164307 | 164411 | if( zSql==0 ){ |
| 164308 | 164412 | rc = SQLITE_NOMEM; |
| 164309 | 164413 | }else{ |
| @@ -165200,11 +165304,11 @@ | ||
| 165200 | 165304 | ** of the locale to use. Passing an empty string ("") or SQL NULL value |
| 165201 | 165305 | ** as the second argument is the same as invoking the 1 argument version |
| 165202 | 165306 | ** of upper() or lower(). |
| 165203 | 165307 | ** |
| 165204 | 165308 | ** lower('I', 'en_us') -> 'i' |
| 165205 | -** lower('I', 'tr_tr') -> 'ı' (small dotless i) | |
| 165309 | +** lower('I', 'tr_tr') -> '\u131' (small dotless i) | |
| 165206 | 165310 | ** |
| 165207 | 165311 | ** http://www.icu-project.org/userguide/posix.html#case_mappings |
| 165208 | 165312 | */ |
| 165209 | 165313 | static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){ |
| 165210 | 165314 | const UChar *zInput; /* Pointer to input string */ |
| @@ -181496,10 +181600,13 @@ | ||
| 181496 | 181600 | int nToken, /* Size of token in bytes */ |
| 181497 | 181601 | int iStartOff, /* Start offset of token */ |
| 181498 | 181602 | int iEndOff /* End offset of token */ |
| 181499 | 181603 | ){ |
| 181500 | 181604 | int rc = SQLITE_OK; |
| 181605 | + | |
| 181606 | + UNUSED_PARAM2(pToken, nToken); | |
| 181607 | + UNUSED_PARAM(iEndOff); | |
| 181501 | 181608 | |
| 181502 | 181609 | if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){ |
| 181503 | 181610 | Fts5SFinder *p = (Fts5SFinder*)pContext; |
| 181504 | 181611 | if( p->iPos>0 ){ |
| 181505 | 181612 | int i; |
| @@ -181652,11 +181759,10 @@ | ||
| 181652 | 181759 | for(jj=0; jj<(sFinder.nFirst-1); jj++){ |
| 181653 | 181760 | if( sFinder.aFirst[jj+1]>io ) break; |
| 181654 | 181761 | } |
| 181655 | 181762 | |
| 181656 | 181763 | if( sFinder.aFirst[jj]<io ){ |
| 181657 | - int nScore; | |
| 181658 | 181764 | memset(aSeen, 0, nPhrase); |
| 181659 | 181765 | rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i, |
| 181660 | 181766 | sFinder.aFirst[jj], nToken, &nScore, 0 |
| 181661 | 181767 | ); |
| 181662 | 181768 | |
| @@ -195587,11 +195693,11 @@ | ||
| 195587 | 195693 | int nArg, /* Number of args */ |
| 195588 | 195694 | sqlite3_value **apUnused /* Function arguments */ |
| 195589 | 195695 | ){ |
| 195590 | 195696 | assert( nArg==0 ); |
| 195591 | 195697 | UNUSED_PARAM2(nArg, apUnused); |
| 195592 | - sqlite3_result_text(pCtx, "fts5: 2016-10-04 00:47:26 b10d0f939c82c4de3faa90b86de9ec4a89992856", -1, SQLITE_TRANSIENT); | |
| 195698 | + sqlite3_result_text(pCtx, "fts5: 2016-10-26 16:05:10 ec9dab8054c71d112c68f58a45821b38c2a45677", -1, SQLITE_TRANSIENT); | |
| 195593 | 195699 | } |
| 195594 | 195700 | |
| 195595 | 195701 | static int fts5Init(sqlite3 *db){ |
| 195596 | 195702 | static const sqlite3_module fts5Mod = { |
| 195597 | 195703 | /* iVersion */ 2, |
| 195598 | 195704 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -1,8 +1,8 @@ | |
| 1 | /****************************************************************************** |
| 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | ** version 3.15.0. By combining all the individual C code files into this |
| 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | ** translation unit. |
| @@ -379,13 +379,13 @@ | |
| 379 | ** |
| 380 | ** See also: [sqlite3_libversion()], |
| 381 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 382 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 383 | */ |
| 384 | #define SQLITE_VERSION "3.15.0" |
| 385 | #define SQLITE_VERSION_NUMBER 3015000 |
| 386 | #define SQLITE_SOURCE_ID "2016-10-04 12:20:12 3a9d802fda10585654332b314d317250dc5d894e" |
| 387 | |
| 388 | /* |
| 389 | ** CAPI3REF: Run-Time Library Version Numbers |
| 390 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 391 | ** |
| @@ -1235,10 +1235,16 @@ | |
| 1235 | ** <li>[[SQLITE_FCNTL_HAS_MOVED]] |
| 1236 | ** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a |
| 1237 | ** pointer to an integer and it writes a boolean into that integer depending |
| 1238 | ** on whether or not the file has been renamed, moved, or deleted since it |
| 1239 | ** was first opened. |
| 1240 | ** |
| 1241 | ** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]] |
| 1242 | ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This |
| 1243 | ** opcode causes the xFileControl method to swap the file handle with the one |
| 1244 | ** pointed to by the pArg argument. This capability is used during testing |
| @@ -1286,10 +1292,12 @@ | |
| 1286 | #define SQLITE_FCNTL_WAL_BLOCK 24 |
| 1287 | #define SQLITE_FCNTL_ZIPVFS 25 |
| 1288 | #define SQLITE_FCNTL_RBU 26 |
| 1289 | #define SQLITE_FCNTL_VFS_POINTER 27 |
| 1290 | #define SQLITE_FCNTL_JOURNAL_POINTER 28 |
| 1291 | |
| 1292 | /* deprecated names */ |
| 1293 | #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE |
| 1294 | #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE |
| 1295 | #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| @@ -2238,18 +2246,31 @@ | |
| 2238 | ** does not make a copy of the new main schema name string, so the application |
| 2239 | ** must ensure that the argument passed into this DBCONFIG option is unchanged |
| 2240 | ** until after the database connection closes. |
| 2241 | ** </dd> |
| 2242 | ** |
| 2243 | ** </dl> |
| 2244 | */ |
| 2245 | #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ |
| 2246 | #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ |
| 2247 | #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ |
| 2248 | #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ |
| 2249 | #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ |
| 2250 | #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ |
| 2251 | |
| 2252 | |
| 2253 | /* |
| 2254 | ** CAPI3REF: Enable Or Disable Extended Result Codes |
| 2255 | ** METHOD: sqlite3 |
| @@ -12675,11 +12696,11 @@ | |
| 12675 | #define OP_SorterData 120 /* synopsis: r[P2]=data */ |
| 12676 | #define OP_RowKey 121 /* synopsis: r[P2]=key */ |
| 12677 | #define OP_RowData 122 /* synopsis: r[P2]=data */ |
| 12678 | #define OP_Rowid 123 /* synopsis: r[P2]=rowid */ |
| 12679 | #define OP_NullRow 124 |
| 12680 | #define OP_SorterInsert 125 |
| 12681 | #define OP_IdxInsert 126 /* synopsis: key=r[P2] */ |
| 12682 | #define OP_IdxDelete 127 /* synopsis: key=r[P2@P3] */ |
| 12683 | #define OP_Seek 128 /* synopsis: Move P3 to P1.rowid */ |
| 12684 | #define OP_IdxRowid 129 /* synopsis: r[P2]=rowid */ |
| 12685 | #define OP_Destroy 130 |
| @@ -13030,11 +13051,11 @@ | |
| 13030 | int, |
| 13031 | int, |
| 13032 | int, |
| 13033 | void(*)(DbPage*) |
| 13034 | ); |
| 13035 | SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager); |
| 13036 | SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); |
| 13037 | |
| 13038 | /* Functions used to configure a Pager object. */ |
| 13039 | SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); |
| 13040 | SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); |
| @@ -13081,19 +13102,22 @@ | |
| 13081 | SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n); |
| 13082 | SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); |
| 13083 | SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager); |
| 13084 | |
| 13085 | #ifndef SQLITE_OMIT_WAL |
| 13086 | SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*); |
| 13087 | SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager); |
| 13088 | SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); |
| 13089 | SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); |
| 13090 | SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager); |
| 13091 | # ifdef SQLITE_ENABLE_SNAPSHOT |
| 13092 | SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot); |
| 13093 | SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot); |
| 13094 | # endif |
| 13095 | #endif |
| 13096 | |
| 13097 | #ifdef SQLITE_ENABLE_ZIPVFS |
| 13098 | SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); |
| 13099 | #endif |
| @@ -14060,10 +14084,11 @@ | |
| 14060 | #define SQLITE_QueryOnly 0x04000000 /* Disable database changes */ |
| 14061 | #define SQLITE_VdbeEQP 0x08000000 /* Debug EXPLAIN QUERY PLAN */ |
| 14062 | #define SQLITE_Vacuum 0x10000000 /* Currently in a VACUUM */ |
| 14063 | #define SQLITE_CellSizeCk 0x20000000 /* Check btree cell sizes on load */ |
| 14064 | #define SQLITE_Fts3Tokenizer 0x40000000 /* Enable fts3_tokenizer(2) */ |
| 14065 | |
| 14066 | |
| 14067 | /* |
| 14068 | ** Bits of the sqlite3.dbOptFlags field that are used by the |
| 14069 | ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to |
| @@ -17268,10 +17293,13 @@ | |
| 17268 | #if SQLITE_DEFAULT_LOCKING_MODE |
| 17269 | "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), |
| 17270 | #endif |
| 17271 | #if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc) |
| 17272 | "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE), |
| 17273 | #endif |
| 17274 | #if SQLITE_DISABLE_DIRSYNC |
| 17275 | "DISABLE_DIRSYNC", |
| 17276 | #endif |
| 17277 | #if SQLITE_DISABLE_LFS |
| @@ -17354,10 +17382,13 @@ | |
| 17354 | #if SQLITE_ENABLE_UNLOCK_NOTIFY |
| 17355 | "ENABLE_UNLOCK_NOTIFY", |
| 17356 | #endif |
| 17357 | #if SQLITE_ENABLE_UPDATE_DELETE_LIMIT |
| 17358 | "ENABLE_UPDATE_DELETE_LIMIT", |
| 17359 | #endif |
| 17360 | #if SQLITE_HAS_CODEC |
| 17361 | "HAS_CODEC", |
| 17362 | #endif |
| 17363 | #if HAVE_ISNAN || SQLITE_HAVE_ISNAN |
| @@ -18105,12 +18136,12 @@ | |
| 18105 | UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */ |
| 18106 | UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */ |
| 18107 | int iNewReg; /* Register for new.* values */ |
| 18108 | i64 iKey1; /* First key value passed to hook */ |
| 18109 | i64 iKey2; /* Second key value passed to hook */ |
| 18110 | int iPKey; /* If not negative index of IPK column */ |
| 18111 | Mem *aNew; /* Array of new.* values */ |
| 18112 | }; |
| 18113 | |
| 18114 | /* |
| 18115 | ** Function prototypes |
| 18116 | */ |
| @@ -24598,13 +24629,12 @@ | |
| 24598 | char *zNew; |
| 24599 | size_t n; |
| 24600 | if( z==0 ){ |
| 24601 | return 0; |
| 24602 | } |
| 24603 | n = sqlite3Strlen30(z) + 1; |
| 24604 | assert( (n&0x7fffffff)==n ); |
| 24605 | zNew = sqlite3DbMallocRaw(db, (int)n); |
| 24606 | if( zNew ){ |
| 24607 | memcpy(zNew, z, n); |
| 24608 | } |
| 24609 | return zNew; |
| 24610 | } |
| @@ -29127,11 +29157,11 @@ | |
| 29127 | /* 120 */ "SorterData" OpHelp("r[P2]=data"), |
| 29128 | /* 121 */ "RowKey" OpHelp("r[P2]=key"), |
| 29129 | /* 122 */ "RowData" OpHelp("r[P2]=data"), |
| 29130 | /* 123 */ "Rowid" OpHelp("r[P2]=rowid"), |
| 29131 | /* 124 */ "NullRow" OpHelp(""), |
| 29132 | /* 125 */ "SorterInsert" OpHelp(""), |
| 29133 | /* 126 */ "IdxInsert" OpHelp("key=r[P2]"), |
| 29134 | /* 127 */ "IdxDelete" OpHelp("key=r[P2@P3]"), |
| 29135 | /* 128 */ "Seek" OpHelp("Move P3 to P1.rowid"), |
| 29136 | /* 129 */ "IdxRowid" OpHelp("r[P2]=rowid"), |
| 29137 | /* 130 */ "Destroy" OpHelp(""), |
| @@ -40674,10 +40704,16 @@ | |
| 40674 | a[1] = winIoerrRetryDelay; |
| 40675 | } |
| 40676 | OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); |
| 40677 | return SQLITE_OK; |
| 40678 | } |
| 40679 | #ifdef SQLITE_TEST |
| 40680 | case SQLITE_FCNTL_WIN32_SET_HANDLE: { |
| 40681 | LPHANDLE phFile = (LPHANDLE)pArg; |
| 40682 | HANDLE hOldFile = pFile->h; |
| 40683 | pFile->h = *phFile; |
| @@ -44715,11 +44751,11 @@ | |
| 44715 | szBulk = pCache->szAlloc * (i64)pcache1.nInitPage; |
| 44716 | }else{ |
| 44717 | szBulk = -1024 * (i64)pcache1.nInitPage; |
| 44718 | } |
| 44719 | if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){ |
| 44720 | szBulk = pCache->szAlloc*pCache->nMax; |
| 44721 | } |
| 44722 | zBulk = pCache->pBulk = sqlite3Malloc( szBulk ); |
| 44723 | sqlite3EndBenignMalloc(); |
| 44724 | if( zBulk ){ |
| 44725 | int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc; |
| @@ -46249,21 +46285,21 @@ | |
| 46249 | #define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */ |
| 46250 | |
| 46251 | #ifdef SQLITE_OMIT_WAL |
| 46252 | # define sqlite3WalOpen(x,y,z) 0 |
| 46253 | # define sqlite3WalLimit(x,y) |
| 46254 | # define sqlite3WalClose(w,x,y,z) 0 |
| 46255 | # define sqlite3WalBeginReadTransaction(y,z) 0 |
| 46256 | # define sqlite3WalEndReadTransaction(z) |
| 46257 | # define sqlite3WalDbsize(y) 0 |
| 46258 | # define sqlite3WalBeginWriteTransaction(y) 0 |
| 46259 | # define sqlite3WalEndWriteTransaction(x) 0 |
| 46260 | # define sqlite3WalUndo(x,y,z) 0 |
| 46261 | # define sqlite3WalSavepoint(y,z) |
| 46262 | # define sqlite3WalSavepointUndo(y,z) 0 |
| 46263 | # define sqlite3WalFrames(u,v,w,x,y,z) 0 |
| 46264 | # define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0 |
| 46265 | # define sqlite3WalCallback(z) 0 |
| 46266 | # define sqlite3WalExclusiveMode(y,z) 0 |
| 46267 | # define sqlite3WalHeapMemory(z) 0 |
| 46268 | # define sqlite3WalFramesize(z) 0 |
| 46269 | # define sqlite3WalFindFrame(x,y,z) 0 |
| @@ -46277,11 +46313,11 @@ | |
| 46277 | */ |
| 46278 | typedef struct Wal Wal; |
| 46279 | |
| 46280 | /* Open and close a connection to a write-ahead log. */ |
| 46281 | SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**); |
| 46282 | SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *); |
| 46283 | |
| 46284 | /* Set the limiting size of a WAL file. */ |
| 46285 | SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64); |
| 46286 | |
| 46287 | /* Used by readers to open (lock) and close (unlock) a snapshot. A |
| @@ -46320,10 +46356,11 @@ | |
| 46320 | SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int); |
| 46321 | |
| 46322 | /* Copy pages from the log to the database file */ |
| 46323 | SQLITE_PRIVATE int sqlite3WalCheckpoint( |
| 46324 | Wal *pWal, /* Write-ahead log connection */ |
| 46325 | int eMode, /* One of PASSIVE, FULL and RESTART */ |
| 46326 | int (*xBusy)(void*), /* Function to call when busy */ |
| 46327 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 46328 | int sync_flags, /* Flags to sync db file with (or 0) */ |
| 46329 | int nBuf, /* Size of buffer nBuf */ |
| @@ -47164,13 +47201,14 @@ | |
| 47164 | /* |
| 47165 | ** Return true if this pager uses a write-ahead log instead of the usual |
| 47166 | ** rollback journal. Otherwise false. |
| 47167 | */ |
| 47168 | #ifndef SQLITE_OMIT_WAL |
| 47169 | static int pagerUseWal(Pager *pPager){ |
| 47170 | return (pPager->pWal!=0); |
| 47171 | } |
| 47172 | #else |
| 47173 | # define pagerUseWal(x) 0 |
| 47174 | # define pagerRollbackWal(x) 0 |
| 47175 | # define pagerWalFrames(v,w,x,y) 0 |
| 47176 | # define pagerOpenWalIfPresent(z) SQLITE_OK |
| @@ -50368,21 +50406,22 @@ | |
| 50368 | ** This function always succeeds. If a transaction is active an attempt |
| 50369 | ** is made to roll it back. If an error occurs during the rollback |
| 50370 | ** a hot journal may be left in the filesystem but no error is returned |
| 50371 | ** to the caller. |
| 50372 | */ |
| 50373 | SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){ |
| 50374 | u8 *pTmp = (u8 *)pPager->pTmpSpace; |
| 50375 | |
| 50376 | assert( assert_pager_state(pPager) ); |
| 50377 | disable_simulated_io_errors(); |
| 50378 | sqlite3BeginBenignMalloc(); |
| 50379 | pagerFreeMapHdrs(pPager); |
| 50380 | /* pPager->errCode = 0; */ |
| 50381 | pPager->exclusiveMode = 0; |
| 50382 | #ifndef SQLITE_OMIT_WAL |
| 50383 | sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp); |
| 50384 | pPager->pWal = 0; |
| 50385 | #endif |
| 50386 | pager_reset(pPager); |
| 50387 | if( MEMDB ){ |
| 50388 | pager_unlock(pPager); |
| @@ -53541,14 +53580,20 @@ | |
| 53541 | ** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint() |
| 53542 | ** or wal_blocking_checkpoint() API functions. |
| 53543 | ** |
| 53544 | ** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. |
| 53545 | */ |
| 53546 | SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){ |
| 53547 | int rc = SQLITE_OK; |
| 53548 | if( pPager->pWal ){ |
| 53549 | rc = sqlite3WalCheckpoint(pPager->pWal, eMode, |
| 53550 | (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), |
| 53551 | pPager->pBusyHandlerArg, |
| 53552 | pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, |
| 53553 | pnLog, pnCkpt |
| 53554 | ); |
| @@ -53676,11 +53721,11 @@ | |
| 53676 | ** Before closing the log file, this function attempts to take an |
| 53677 | ** EXCLUSIVE lock on the database file. If this cannot be obtained, an |
| 53678 | ** error (SQLITE_BUSY) is returned and the log connection is not closed. |
| 53679 | ** If successful, the EXCLUSIVE lock is not released before returning. |
| 53680 | */ |
| 53681 | SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){ |
| 53682 | int rc = SQLITE_OK; |
| 53683 | |
| 53684 | assert( pPager->journalMode==PAGER_JOURNALMODE_WAL ); |
| 53685 | |
| 53686 | /* If the log file is not already open, but does exist in the file-system, |
| @@ -53704,11 +53749,11 @@ | |
| 53704 | ** the database file, the log and log-summary files will be deleted. |
| 53705 | */ |
| 53706 | if( rc==SQLITE_OK && pPager->pWal ){ |
| 53707 | rc = pagerExclusiveLock(pPager); |
| 53708 | if( rc==SQLITE_OK ){ |
| 53709 | rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, |
| 53710 | pPager->pageSize, (u8*)pPager->pTmpSpace); |
| 53711 | pPager->pWal = 0; |
| 53712 | pagerFixMaplimit(pPager); |
| 53713 | if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK); |
| 53714 | } |
| @@ -55487,10 +55532,11 @@ | |
| 55487 | ** checkpoint is running (in any other thread or process) at the same |
| 55488 | ** time. |
| 55489 | */ |
| 55490 | static int walCheckpoint( |
| 55491 | Wal *pWal, /* Wal connection */ |
| 55492 | int eMode, /* One of PASSIVE, FULL or RESTART */ |
| 55493 | int (*xBusy)(void*), /* Function to call when busy */ |
| 55494 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 55495 | int sync_flags, /* Flags for OsSync() (or 0) */ |
| 55496 | u8 *zBuf /* Temporary buffer to use */ |
| @@ -55581,10 +55627,14 @@ | |
| 55581 | |
| 55582 | /* Iterate through the contents of the WAL, copying data to the db file */ |
| 55583 | while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ |
| 55584 | i64 iOffset; |
| 55585 | assert( walFramePgno(pWal, iFrame)==iDbpage ); |
| 55586 | if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){ |
| 55587 | continue; |
| 55588 | } |
| 55589 | iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE; |
| 55590 | /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */ |
| @@ -55685,10 +55735,11 @@ | |
| 55685 | /* |
| 55686 | ** Close a connection to a log file. |
| 55687 | */ |
| 55688 | SQLITE_PRIVATE int sqlite3WalClose( |
| 55689 | Wal *pWal, /* Wal to close */ |
| 55690 | int sync_flags, /* Flags to pass to OsSync() (or 0) */ |
| 55691 | int nBuf, |
| 55692 | u8 *zBuf /* Buffer of at least nBuf bytes */ |
| 55693 | ){ |
| 55694 | int rc = SQLITE_OK; |
| @@ -55701,17 +55752,18 @@ | |
| 55701 | ** the database. In this case checkpoint the database and unlink both |
| 55702 | ** the wal and wal-index files. |
| 55703 | ** |
| 55704 | ** The EXCLUSIVE lock is not released before returning. |
| 55705 | */ |
| 55706 | rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE); |
| 55707 | if( rc==SQLITE_OK ){ |
| 55708 | if( pWal->exclusiveMode==WAL_NORMAL_MODE ){ |
| 55709 | pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; |
| 55710 | } |
| 55711 | rc = sqlite3WalCheckpoint( |
| 55712 | pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0 |
| 55713 | ); |
| 55714 | if( rc==SQLITE_OK ){ |
| 55715 | int bPersist = -1; |
| 55716 | sqlite3OsFileControlHint( |
| 55717 | pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersist |
| @@ -56955,10 +57007,11 @@ | |
| 56955 | ** If parameter xBusy is not NULL, it is a pointer to a busy-handler |
| 56956 | ** callback. In this case this function runs a blocking checkpoint. |
| 56957 | */ |
| 56958 | SQLITE_PRIVATE int sqlite3WalCheckpoint( |
| 56959 | Wal *pWal, /* Wal connection */ |
| 56960 | int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */ |
| 56961 | int (*xBusy)(void*), /* Function to call when busy */ |
| 56962 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 56963 | int sync_flags, /* Flags to sync db file with (or 0) */ |
| 56964 | int nBuf, /* Size of temporary buffer */ |
| @@ -57029,11 +57082,11 @@ | |
| 57029 | if( rc==SQLITE_OK ){ |
| 57030 | |
| 57031 | if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ |
| 57032 | rc = SQLITE_CORRUPT_BKPT; |
| 57033 | }else{ |
| 57034 | rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); |
| 57035 | } |
| 57036 | |
| 57037 | /* If no error occurred, set the output variables. */ |
| 57038 | if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ |
| 57039 | if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; |
| @@ -60619,23 +60672,30 @@ | |
| 60619 | *ppBtree = p; |
| 60620 | |
| 60621 | btree_open_out: |
| 60622 | if( rc!=SQLITE_OK ){ |
| 60623 | if( pBt && pBt->pPager ){ |
| 60624 | sqlite3PagerClose(pBt->pPager); |
| 60625 | } |
| 60626 | sqlite3_free(pBt); |
| 60627 | sqlite3_free(p); |
| 60628 | *ppBtree = 0; |
| 60629 | }else{ |
| 60630 | /* If the B-Tree was successfully opened, set the pager-cache size to the |
| 60631 | ** default value. Except, when opening on an existing shared pager-cache, |
| 60632 | ** do not change the pager-cache size. |
| 60633 | */ |
| 60634 | if( sqlite3BtreeSchema(p, 0, 0)==0 ){ |
| 60635 | sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE); |
| 60636 | } |
| 60637 | } |
| 60638 | if( mutexOpen ){ |
| 60639 | assert( sqlite3_mutex_held(mutexOpen) ); |
| 60640 | sqlite3_mutex_leave(mutexOpen); |
| 60641 | } |
| @@ -60761,11 +60821,11 @@ | |
| 60761 | ** it without having to hold the mutex. |
| 60762 | ** |
| 60763 | ** Clean out and delete the BtShared object. |
| 60764 | */ |
| 60765 | assert( !pBt->pCursor ); |
| 60766 | sqlite3PagerClose(pBt->pPager); |
| 60767 | if( pBt->xFreeSchema && pBt->pSchema ){ |
| 60768 | pBt->xFreeSchema(pBt->pSchema); |
| 60769 | } |
| 60770 | sqlite3DbFree(0, pBt->pSchema); |
| 60771 | freeTempSpace(pBt); |
| @@ -62825,11 +62885,11 @@ | |
| 62825 | if( (eOp&0x01)==0 /* (1) */ |
| 62826 | && offset==0 /* (2) */ |
| 62827 | && (bEnd || a==ovflSize) /* (6) */ |
| 62828 | && pBt->inTransaction==TRANS_READ /* (4) */ |
| 62829 | && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */ |
| 62830 | && pBt->pPage1->aData[19]==0x01 /* (5) */ |
| 62831 | && &pBuf[-4]>=pBufStart /* (7) */ |
| 62832 | ){ |
| 62833 | u8 aSave[4]; |
| 62834 | u8 *aWrite = &pBuf[-4]; |
| 62835 | assert( aWrite>=pBufStart ); /* hence (7) */ |
| @@ -63081,13 +63141,16 @@ | |
| 63081 | } |
| 63082 | sqlite3BtreeClearCursor(pCur); |
| 63083 | } |
| 63084 | |
| 63085 | if( pCur->iPage>=0 ){ |
| 63086 | while( pCur->iPage ){ |
| 63087 | assert( pCur->apPage[pCur->iPage]!=0 ); |
| 63088 | releasePageNotNull(pCur->apPage[pCur->iPage--]); |
| 63089 | } |
| 63090 | }else if( pCur->pgnoRoot==0 ){ |
| 63091 | pCur->eState = CURSOR_INVALID; |
| 63092 | return SQLITE_OK; |
| 63093 | }else{ |
| @@ -63094,11 +63157,11 @@ | |
| 63094 | assert( pCur->iPage==(-1) ); |
| 63095 | rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0], |
| 63096 | 0, pCur->curPagerFlags); |
| 63097 | if( rc!=SQLITE_OK ){ |
| 63098 | pCur->eState = CURSOR_INVALID; |
| 63099 | return rc; |
| 63100 | } |
| 63101 | pCur->iPage = 0; |
| 63102 | pCur->curIntKey = pCur->apPage[0]->intKey; |
| 63103 | } |
| 63104 | pRoot = pCur->apPage[0]; |
| @@ -63117,14 +63180,16 @@ | |
| 63117 | assert( pRoot->intKey==1 || pRoot->intKey==0 ); |
| 63118 | if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){ |
| 63119 | return SQLITE_CORRUPT_BKPT; |
| 63120 | } |
| 63121 | |
| 63122 | pCur->aiIdx[0] = 0; |
| 63123 | pCur->info.nSize = 0; |
| 63124 | pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl); |
| 63125 | |
| 63126 | if( pRoot->nCell>0 ){ |
| 63127 | pCur->eState = CURSOR_VALID; |
| 63128 | }else if( !pRoot->leaf ){ |
| 63129 | Pgno subpage; |
| 63130 | if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT; |
| @@ -67701,11 +67766,11 @@ | |
| 67701 | BtShared *pBt = p->pBt; |
| 67702 | sqlite3BtreeEnter(p); |
| 67703 | if( pBt->inTransaction!=TRANS_NONE ){ |
| 67704 | rc = SQLITE_LOCKED; |
| 67705 | }else{ |
| 67706 | rc = sqlite3PagerCheckpoint(pBt->pPager, eMode, pnLog, pnCkpt); |
| 67707 | } |
| 67708 | sqlite3BtreeLeave(p); |
| 67709 | } |
| 67710 | return rc; |
| 67711 | } |
| @@ -69336,11 +69401,11 @@ | |
| 69336 | switch( aff ){ |
| 69337 | case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */ |
| 69338 | if( (pMem->flags & MEM_Blob)==0 ){ |
| 69339 | sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding); |
| 69340 | assert( pMem->flags & MEM_Str || pMem->db->mallocFailed ); |
| 69341 | MemSetTypeFlag(pMem, MEM_Blob); |
| 69342 | }else{ |
| 69343 | pMem->flags &= ~(MEM_TypeMask&~MEM_Blob); |
| 69344 | } |
| 69345 | break; |
| 69346 | } |
| @@ -75076,11 +75141,11 @@ | |
| 75076 | preupdate.keyinfo.enc = ENC(db); |
| 75077 | preupdate.keyinfo.nField = pTab->nCol; |
| 75078 | preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder; |
| 75079 | preupdate.iKey1 = iKey1; |
| 75080 | preupdate.iKey2 = iKey2; |
| 75081 | preupdate.iPKey = pTab->iPKey; |
| 75082 | |
| 75083 | db->pPreUpdate = &preupdate; |
| 75084 | db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2); |
| 75085 | db->pPreUpdate = 0; |
| 75086 | sqlite3DbFree(db, preupdate.aRecord); |
| @@ -76808,13 +76873,18 @@ | |
| 76808 | } |
| 76809 | |
| 76810 | if( iIdx>=p->pUnpacked->nField ){ |
| 76811 | *ppValue = (sqlite3_value *)columnNullValue(); |
| 76812 | }else{ |
| 76813 | *ppValue = &p->pUnpacked->aMem[iIdx]; |
| 76814 | if( iIdx==p->iPKey ){ |
| 76815 | sqlite3VdbeMemSetInt64(*ppValue, p->iKey1); |
| 76816 | } |
| 76817 | } |
| 76818 | |
| 76819 | preupdate_old_out: |
| 76820 | sqlite3Error(db, rc); |
| @@ -76887,11 +76957,11 @@ | |
| 76887 | } |
| 76888 | if( iIdx>=pUnpack->nField ){ |
| 76889 | pMem = (sqlite3_value *)columnNullValue(); |
| 76890 | }else{ |
| 76891 | pMem = &pUnpack->aMem[iIdx]; |
| 76892 | if( iIdx==p->iPKey ){ |
| 76893 | sqlite3VdbeMemSetInt64(pMem, p->iKey2); |
| 76894 | } |
| 76895 | } |
| 76896 | }else{ |
| 76897 | /* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required |
| @@ -76908,11 +76978,11 @@ | |
| 76908 | } |
| 76909 | } |
| 76910 | assert( iIdx>=0 && iIdx<p->pCsr->nField ); |
| 76911 | pMem = &p->aNew[iIdx]; |
| 76912 | if( pMem->flags==0 ){ |
| 76913 | if( iIdx==p->iPKey ){ |
| 76914 | sqlite3VdbeMemSetInt64(pMem, p->iKey2); |
| 76915 | }else{ |
| 76916 | rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]); |
| 76917 | if( rc!=SQLITE_OK ) goto preupdate_new_out; |
| 76918 | } |
| @@ -79286,12 +79356,11 @@ | |
| 79286 | ** or not both operands are null. |
| 79287 | */ |
| 79288 | assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne ); |
| 79289 | assert( (flags1 & MEM_Cleared)==0 ); |
| 79290 | assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 ); |
| 79291 | if( (flags1&MEM_Null)!=0 |
| 79292 | && (flags3&MEM_Null)!=0 |
| 79293 | && (flags3&MEM_Cleared)==0 |
| 79294 | ){ |
| 79295 | res = 0; /* Operands are equal */ |
| 79296 | }else{ |
| 79297 | res = 1; /* Operands are not equal */ |
| @@ -81554,11 +81623,11 @@ | |
| 81554 | |
| 81555 | REGISTER_TRACE(pOp->p3, pMem); |
| 81556 | sqlite3VdbeMemIntegerify(pMem); |
| 81557 | assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ |
| 81558 | if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){ |
| 81559 | rc = SQLITE_FULL; /* IMP: R-12275-61338 */ |
| 81560 | goto abort_due_to_error; |
| 81561 | } |
| 81562 | if( v<pMem->u.i+1 ){ |
| 81563 | v = pMem->u.i + 1; |
| 81564 | } |
| @@ -82321,10 +82390,17 @@ | |
| 82321 | ** This flag avoids doing an extra seek. |
| 82322 | ** |
| 82323 | ** This instruction only works for indices. The equivalent instruction |
| 82324 | ** for tables is OP_Insert. |
| 82325 | */ |
| 82326 | case OP_SorterInsert: /* in2 */ |
| 82327 | case OP_IdxInsert: { /* in2 */ |
| 82328 | VdbeCursor *pC; |
| 82329 | BtreePayload x; |
| 82330 | |
| @@ -83549,11 +83625,11 @@ | |
| 83549 | /* If leaving WAL mode, close the log file. If successful, the call |
| 83550 | ** to PagerCloseWal() checkpoints and deletes the write-ahead-log |
| 83551 | ** file. An EXCLUSIVE lock may still be held on the database file |
| 83552 | ** after a successful return. |
| 83553 | */ |
| 83554 | rc = sqlite3PagerCloseWal(pPager); |
| 83555 | if( rc==SQLITE_OK ){ |
| 83556 | sqlite3PagerSetJournalMode(pPager, eNew); |
| 83557 | } |
| 83558 | }else if( eOld==PAGER_JOURNALMODE_MEMORY ){ |
| 83559 | /* Cannot transition directly from MEMORY to WAL. Use mode OFF |
| @@ -88812,11 +88888,10 @@ | |
| 88812 | const char *zId; /* The function name. */ |
| 88813 | FuncDef *pDef; /* Information about the function */ |
| 88814 | u8 enc = ENC(pParse->db); /* The database encoding */ |
| 88815 | |
| 88816 | assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); |
| 88817 | // notValid(pParse, pNC, "functions", NC_PartIdx); |
| 88818 | zId = pExpr->u.zToken; |
| 88819 | nId = sqlite3Strlen30(zId); |
| 88820 | pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0); |
| 88821 | if( pDef==0 ){ |
| 88822 | pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0); |
| @@ -94293,15 +94368,14 @@ | |
| 94293 | && (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab) |
| 94294 | || sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) ) |
| 94295 | ){ |
| 94296 | return 1; |
| 94297 | } |
| 94298 | if( pE2->op==TK_NOTNULL |
| 94299 | && sqlite3ExprCompare(pE1->pLeft, pE2->pLeft, iTab)==0 |
| 94300 | && (pE1->op!=TK_ISNULL && pE1->op!=TK_IS) |
| 94301 | ){ |
| 94302 | return 1; |
| 94303 | } |
| 94304 | return 0; |
| 94305 | } |
| 94306 | |
| 94307 | /* |
| @@ -122355,11 +122429,11 @@ | |
| 122355 | } |
| 122356 | #endif |
| 122357 | |
| 122358 | sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size); |
| 122359 | sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0)); |
| 122360 | sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF); |
| 122361 | |
| 122362 | /* Begin a transaction and take an exclusive lock on the main database |
| 122363 | ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below, |
| 122364 | ** to ensure that we do not try to change the page-size on a WAL database. |
| 122365 | */ |
| @@ -124663,11 +124737,10 @@ | |
| 124663 | ** |
| 124664 | ** * the comparison will be performed with no affinity, or |
| 124665 | ** * the affinity change in zAff is guaranteed not to change the value. |
| 124666 | */ |
| 124667 | static void updateRangeAffinityStr( |
| 124668 | Parse *pParse, /* Parse context */ |
| 124669 | Expr *pRight, /* RHS of comparison */ |
| 124670 | int n, /* Number of vector elements in comparison */ |
| 124671 | char *zAff /* Affinity string to modify */ |
| 124672 | ){ |
| 124673 | int i; |
| @@ -125749,15 +125822,15 @@ | |
| 125749 | assert( (bRev & ~1)==0 ); |
| 125750 | pLevel->iLikeRepCntr <<=1; |
| 125751 | pLevel->iLikeRepCntr |= bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC); |
| 125752 | } |
| 125753 | #endif |
| 125754 | if( pRangeStart==0 |
| 125755 | && (j = pIdx->aiColumn[nEq])>=0 |
| 125756 | && pIdx->pTable->aCol[j].notNull==0 |
| 125757 | ){ |
| 125758 | bSeekPastNull = 1; |
| 125759 | } |
| 125760 | } |
| 125761 | assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 ); |
| 125762 | |
| 125763 | /* If we are doing a reverse order scan on an ascending index, or |
| @@ -125803,11 +125876,11 @@ | |
| 125803 | ){ |
| 125804 | sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); |
| 125805 | VdbeCoverage(v); |
| 125806 | } |
| 125807 | if( zStartAff ){ |
| 125808 | updateRangeAffinityStr(pParse, pRight, nBtm, &zStartAff[nEq]); |
| 125809 | } |
| 125810 | nConstraint += nBtm; |
| 125811 | testcase( pRangeStart->wtFlags & TERM_VIRTUAL ); |
| 125812 | if( sqlite3ExprIsVector(pRight)==0 ){ |
| 125813 | disableTerm(pLevel, pRangeStart); |
| @@ -125853,11 +125926,11 @@ | |
| 125853 | ){ |
| 125854 | sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); |
| 125855 | VdbeCoverage(v); |
| 125856 | } |
| 125857 | if( zEndAff ){ |
| 125858 | updateRangeAffinityStr(pParse, pRight, nTop, zEndAff); |
| 125859 | codeApplyAffinity(pParse, regBase+nEq, nTop, zEndAff); |
| 125860 | }else{ |
| 125861 | assert( pParse->db->mallocFailed ); |
| 125862 | } |
| 125863 | nConstraint += nTop; |
| @@ -127539,10 +127612,11 @@ | |
| 127539 | Expr *pNew; |
| 127540 | Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i); |
| 127541 | Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i); |
| 127542 | |
| 127543 | pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight, 0); |
| 127544 | idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC); |
| 127545 | exprAnalyze(pSrc, pWC, idxNew); |
| 127546 | } |
| 127547 | pTerm = &pWC->a[idxTerm]; |
| 127548 | pTerm->wtFlags = TERM_CODED|TERM_VIRTUAL; /* Disable the original */ |
| @@ -127980,15 +128054,17 @@ | |
| 127980 | Expr *pX; /* An expression being tested */ |
| 127981 | WhereClause *pWC; /* Shorthand for pScan->pWC */ |
| 127982 | WhereTerm *pTerm; /* The term being tested */ |
| 127983 | int k = pScan->k; /* Where to start scanning */ |
| 127984 | |
| 127985 | while( pScan->iEquiv<=pScan->nEquiv ){ |
| 127986 | iCur = pScan->aiCur[pScan->iEquiv-1]; |
| 127987 | iColumn = pScan->aiColumn[pScan->iEquiv-1]; |
| 127988 | if( iColumn==XN_EXPR && pScan->pIdxExpr==0 ) return 0; |
| 127989 | while( (pWC = pScan->pWC)!=0 ){ |
| 127990 | for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){ |
| 127991 | if( pTerm->leftCursor==iCur |
| 127992 | && pTerm->u.leftColumn==iColumn |
| 127993 | && (iColumn!=XN_EXPR |
| 127994 | || sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0) |
| @@ -128034,19 +128110,21 @@ | |
| 128034 | && pX->iColumn==pScan->aiColumn[0] |
| 128035 | ){ |
| 128036 | testcase( pTerm->eOperator & WO_IS ); |
| 128037 | continue; |
| 128038 | } |
| 128039 | pScan->k = k+1; |
| 128040 | return pTerm; |
| 128041 | } |
| 128042 | } |
| 128043 | } |
| 128044 | pScan->pWC = pScan->pWC->pOuter; |
| 128045 | k = 0; |
| 128046 | } |
| 128047 | pScan->pWC = pScan->pOrigWC; |
| 128048 | k = 0; |
| 128049 | pScan->iEquiv++; |
| 128050 | } |
| 128051 | return 0; |
| 128052 | } |
| @@ -128076,28 +128154,28 @@ | |
| 128076 | int iCur, /* Cursor to scan for */ |
| 128077 | int iColumn, /* Column to scan for */ |
| 128078 | u32 opMask, /* Operator(s) to scan for */ |
| 128079 | Index *pIdx /* Must be compatible with this index */ |
| 128080 | ){ |
| 128081 | int j = 0; |
| 128082 | |
| 128083 | /* memset(pScan, 0, sizeof(*pScan)); */ |
| 128084 | pScan->pOrigWC = pWC; |
| 128085 | pScan->pWC = pWC; |
| 128086 | pScan->pIdxExpr = 0; |
| 128087 | if( pIdx ){ |
| 128088 | j = iColumn; |
| 128089 | iColumn = pIdx->aiColumn[j]; |
| 128090 | if( iColumn==XN_EXPR ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; |
| 128091 | if( iColumn==pIdx->pTable->iPKey ) iColumn = XN_ROWID; |
| 128092 | } |
| 128093 | if( pIdx && iColumn>=0 ){ |
| 128094 | pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; |
| 128095 | pScan->zCollName = pIdx->azColl[j]; |
| 128096 | }else{ |
| 128097 | pScan->idxaff = 0; |
| 128098 | pScan->zCollName = 0; |
| 128099 | } |
| 128100 | pScan->opMask = opMask; |
| 128101 | pScan->k = 0; |
| 128102 | pScan->aiCur[0] = iCur; |
| 128103 | pScan->aiColumn[0] = iColumn; |
| @@ -130005,11 +130083,11 @@ | |
| 130005 | ** CREATE INDEX ... ON (a, b, c, d, e) |
| 130006 | ** |
| 130007 | ** then this function would be invoked with nEq=1. The value returned in |
| 130008 | ** this case is 3. |
| 130009 | */ |
| 130010 | int whereRangeVectorLen( |
| 130011 | Parse *pParse, /* Parsing context */ |
| 130012 | int iCur, /* Cursor open on pIdx */ |
| 130013 | Index *pIdx, /* The index to be used for a inequality constraint */ |
| 130014 | int nEq, /* Number of prior equality constraints on same index */ |
| 130015 | WhereTerm *pTerm /* The vector inequality constraint */ |
| @@ -131451,11 +131529,11 @@ | |
| 131451 | if( rev ) *pRevMask |= MASKBIT(iLoop); |
| 131452 | revSet = 1; |
| 131453 | } |
| 131454 | } |
| 131455 | if( isMatch ){ |
| 131456 | if( iColumn<0 ){ |
| 131457 | testcase( distinctColumns==0 ); |
| 131458 | distinctColumns = 1; |
| 131459 | } |
| 131460 | obSat |= MASKBIT(i); |
| 131461 | }else{ |
| @@ -131906,17 +131984,24 @@ | |
| 131906 | }else{ |
| 131907 | pWInfo->nOBSat = pFrom->isOrdered; |
| 131908 | pWInfo->revMask = pFrom->revLoop; |
| 131909 | if( pWInfo->nOBSat<=0 ){ |
| 131910 | pWInfo->nOBSat = 0; |
| 131911 | if( nLoop>0 && (pFrom->aLoop[nLoop-1]->wsFlags & WHERE_ONEROW)==0 ){ |
| 131912 | Bitmask m = 0; |
| 131913 | int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom, |
| 131914 | WHERE_ORDERBY_LIMIT, nLoop-1, pFrom->aLoop[nLoop-1], &m); |
| 131915 | if( rc==pWInfo->pOrderBy->nExpr ){ |
| 131916 | pWInfo->bOrderedInnerLoop = 1; |
| 131917 | pWInfo->revMask = m; |
| 131918 | } |
| 131919 | } |
| 131920 | } |
| 131921 | } |
| 131922 | if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP) |
| @@ -132635,17 +132720,19 @@ | |
| 132635 | pLevel->addrLikeRep); |
| 132636 | VdbeCoverage(v); |
| 132637 | } |
| 132638 | #endif |
| 132639 | if( pLevel->iLeftJoin ){ |
| 132640 | addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v); |
| 132641 | assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 |
| 132642 | || (pLoop->wsFlags & WHERE_INDEXED)!=0 ); |
| 132643 | if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 ){ |
| 132644 | sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor); |
| 132645 | } |
| 132646 | if( pLoop->wsFlags & WHERE_INDEXED ){ |
| 132647 | sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur); |
| 132648 | } |
| 132649 | if( pLevel->op==OP_Return ){ |
| 132650 | sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst); |
| 132651 | }else{ |
| @@ -138607,10 +138694,11 @@ | |
| 138607 | } aFlagOp[] = { |
| 138608 | { SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys }, |
| 138609 | { SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger }, |
| 138610 | { SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer }, |
| 138611 | { SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension }, |
| 138612 | }; |
| 138613 | unsigned int i; |
| 138614 | rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ |
| 138615 | for(i=0; i<ArraySize(aFlagOp); i++){ |
| 138616 | if( aFlagOp[i].op==op ){ |
| @@ -139903,10 +139991,17 @@ | |
| 139903 | db->busyHandler.nBusy = 0; |
| 139904 | rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt); |
| 139905 | sqlite3Error(db, rc); |
| 139906 | } |
| 139907 | rc = sqlite3ApiExit(db, rc); |
| 139908 | sqlite3_mutex_leave(db->mutex); |
| 139909 | return rc; |
| 139910 | #endif |
| 139911 | } |
| 139912 | |
| @@ -140405,10 +140500,11 @@ | |
| 140405 | int octet = (sqlite3HexToInt(zUri[iIn++]) << 4); |
| 140406 | octet += sqlite3HexToInt(zUri[iIn++]); |
| 140407 | |
| 140408 | assert( octet>=0 && octet<256 ); |
| 140409 | if( octet==0 ){ |
| 140410 | /* This branch is taken when "%00" appears within the URI. In this |
| 140411 | ** case we ignore all text in the remainder of the path, name or |
| 140412 | ** value currently being parsed. So ignore the current character |
| 140413 | ** and skip to the next "?", "=" or "&", as appropriate. */ |
| 140414 | while( (c = zUri[iIn])!=0 && c!='#' |
| @@ -140417,10 +140513,16 @@ | |
| 140417 | && (eState!=2 || c!='&') |
| 140418 | ){ |
| 140419 | iIn++; |
| 140420 | } |
| 140421 | continue; |
| 140422 | } |
| 140423 | c = octet; |
| 140424 | }else if( eState==1 && (c=='&' || c=='=') ){ |
| 140425 | if( zFile[iOut-1]==0 ){ |
| 140426 | /* An empty option name. Ignore this option altogether. */ |
| @@ -164296,14 +164398,16 @@ | |
| 164296 | char *zSql; |
| 164297 | sqlite3_stmt *p; |
| 164298 | int rc; |
| 164299 | i64 nRow = 0; |
| 164300 | |
| 164301 | if( sqlite3_table_column_metadata(db,pRtree->zDb,"sqlite_stat1", |
| 164302 | 0,0,0,0,0,0)==SQLITE_ERROR ){ |
| 164303 | pRtree->nRowEst = RTREE_DEFAULT_ROWEST; |
| 164304 | return SQLITE_OK; |
| 164305 | } |
| 164306 | zSql = sqlite3_mprintf(zFmt, pRtree->zDb, pRtree->zName); |
| 164307 | if( zSql==0 ){ |
| 164308 | rc = SQLITE_NOMEM; |
| 164309 | }else{ |
| @@ -165200,11 +165304,11 @@ | |
| 165200 | ** of the locale to use. Passing an empty string ("") or SQL NULL value |
| 165201 | ** as the second argument is the same as invoking the 1 argument version |
| 165202 | ** of upper() or lower(). |
| 165203 | ** |
| 165204 | ** lower('I', 'en_us') -> 'i' |
| 165205 | ** lower('I', 'tr_tr') -> 'ı' (small dotless i) |
| 165206 | ** |
| 165207 | ** http://www.icu-project.org/userguide/posix.html#case_mappings |
| 165208 | */ |
| 165209 | static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){ |
| 165210 | const UChar *zInput; /* Pointer to input string */ |
| @@ -181496,10 +181600,13 @@ | |
| 181496 | int nToken, /* Size of token in bytes */ |
| 181497 | int iStartOff, /* Start offset of token */ |
| 181498 | int iEndOff /* End offset of token */ |
| 181499 | ){ |
| 181500 | int rc = SQLITE_OK; |
| 181501 | |
| 181502 | if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){ |
| 181503 | Fts5SFinder *p = (Fts5SFinder*)pContext; |
| 181504 | if( p->iPos>0 ){ |
| 181505 | int i; |
| @@ -181652,11 +181759,10 @@ | |
| 181652 | for(jj=0; jj<(sFinder.nFirst-1); jj++){ |
| 181653 | if( sFinder.aFirst[jj+1]>io ) break; |
| 181654 | } |
| 181655 | |
| 181656 | if( sFinder.aFirst[jj]<io ){ |
| 181657 | int nScore; |
| 181658 | memset(aSeen, 0, nPhrase); |
| 181659 | rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i, |
| 181660 | sFinder.aFirst[jj], nToken, &nScore, 0 |
| 181661 | ); |
| 181662 | |
| @@ -195587,11 +195693,11 @@ | |
| 195587 | int nArg, /* Number of args */ |
| 195588 | sqlite3_value **apUnused /* Function arguments */ |
| 195589 | ){ |
| 195590 | assert( nArg==0 ); |
| 195591 | UNUSED_PARAM2(nArg, apUnused); |
| 195592 | sqlite3_result_text(pCtx, "fts5: 2016-10-04 00:47:26 b10d0f939c82c4de3faa90b86de9ec4a89992856", -1, SQLITE_TRANSIENT); |
| 195593 | } |
| 195594 | |
| 195595 | static int fts5Init(sqlite3 *db){ |
| 195596 | static const sqlite3_module fts5Mod = { |
| 195597 | /* iVersion */ 2, |
| 195598 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -1,8 +1,8 @@ | |
| 1 | /****************************************************************************** |
| 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | ** version 3.16.0. By combining all the individual C code files into this |
| 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | ** translation unit. |
| @@ -379,13 +379,13 @@ | |
| 379 | ** |
| 380 | ** See also: [sqlite3_libversion()], |
| 381 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 382 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 383 | */ |
| 384 | #define SQLITE_VERSION "3.16.0" |
| 385 | #define SQLITE_VERSION_NUMBER 3016000 |
| 386 | #define SQLITE_SOURCE_ID "2016-11-02 14:50:19 3028845329c9b7acdec2ec8b01d00d782347454c" |
| 387 | |
| 388 | /* |
| 389 | ** CAPI3REF: Run-Time Library Version Numbers |
| 390 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 391 | ** |
| @@ -1235,10 +1235,16 @@ | |
| 1235 | ** <li>[[SQLITE_FCNTL_HAS_MOVED]] |
| 1236 | ** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a |
| 1237 | ** pointer to an integer and it writes a boolean into that integer depending |
| 1238 | ** on whether or not the file has been renamed, moved, or deleted since it |
| 1239 | ** was first opened. |
| 1240 | ** |
| 1241 | ** <li>[[SQLITE_FCNTL_WIN32_GET_HANDLE]] |
| 1242 | ** The [SQLITE_FCNTL_WIN32_GET_HANDLE] opcode can be used to obtain the |
| 1243 | ** underlying native file handle associated with a file handle. This file |
| 1244 | ** control interprets its argument as a pointer to a native file handle and |
| 1245 | ** writes the resulting value there. |
| 1246 | ** |
| 1247 | ** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]] |
| 1248 | ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This |
| 1249 | ** opcode causes the xFileControl method to swap the file handle with the one |
| 1250 | ** pointed to by the pArg argument. This capability is used during testing |
| @@ -1286,10 +1292,12 @@ | |
| 1292 | #define SQLITE_FCNTL_WAL_BLOCK 24 |
| 1293 | #define SQLITE_FCNTL_ZIPVFS 25 |
| 1294 | #define SQLITE_FCNTL_RBU 26 |
| 1295 | #define SQLITE_FCNTL_VFS_POINTER 27 |
| 1296 | #define SQLITE_FCNTL_JOURNAL_POINTER 28 |
| 1297 | #define SQLITE_FCNTL_WIN32_GET_HANDLE 29 |
| 1298 | #define SQLITE_FCNTL_PDB 30 |
| 1299 | |
| 1300 | /* deprecated names */ |
| 1301 | #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE |
| 1302 | #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE |
| 1303 | #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| @@ -2238,18 +2246,31 @@ | |
| 2246 | ** does not make a copy of the new main schema name string, so the application |
| 2247 | ** must ensure that the argument passed into this DBCONFIG option is unchanged |
| 2248 | ** until after the database connection closes. |
| 2249 | ** </dd> |
| 2250 | ** |
| 2251 | ** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt> |
| 2252 | ** <dd> Usually, when a database in wal mode is closed or detached from a |
| 2253 | ** database handle, SQLite checks if this will mean that there are now no |
| 2254 | ** connections at all to the database. If so, it performs a checkpoint |
| 2255 | ** operation before closing the connection. This option may be used to |
| 2256 | ** override this behaviour. The first parameter passed to this operation |
| 2257 | ** is an integer - non-zero to disable checkpoints-on-close, or zero (the |
| 2258 | ** default) to enable them. The second parameter is a pointer to an integer |
| 2259 | ** into which is written 0 or 1 to indicate whether checkpoints-on-close |
| 2260 | ** have been disabled - 0 if they are not disabled, 1 if they are. |
| 2261 | ** </dd> |
| 2262 | ** |
| 2263 | ** </dl> |
| 2264 | */ |
| 2265 | #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ |
| 2266 | #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ |
| 2267 | #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ |
| 2268 | #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ |
| 2269 | #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ |
| 2270 | #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ |
| 2271 | #define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */ |
| 2272 | |
| 2273 | |
| 2274 | /* |
| 2275 | ** CAPI3REF: Enable Or Disable Extended Result Codes |
| 2276 | ** METHOD: sqlite3 |
| @@ -12675,11 +12696,11 @@ | |
| 12696 | #define OP_SorterData 120 /* synopsis: r[P2]=data */ |
| 12697 | #define OP_RowKey 121 /* synopsis: r[P2]=key */ |
| 12698 | #define OP_RowData 122 /* synopsis: r[P2]=data */ |
| 12699 | #define OP_Rowid 123 /* synopsis: r[P2]=rowid */ |
| 12700 | #define OP_NullRow 124 |
| 12701 | #define OP_SorterInsert 125 /* synopsis: key=r[P2] */ |
| 12702 | #define OP_IdxInsert 126 /* synopsis: key=r[P2] */ |
| 12703 | #define OP_IdxDelete 127 /* synopsis: key=r[P2@P3] */ |
| 12704 | #define OP_Seek 128 /* synopsis: Move P3 to P1.rowid */ |
| 12705 | #define OP_IdxRowid 129 /* synopsis: r[P2]=rowid */ |
| 12706 | #define OP_Destroy 130 |
| @@ -13030,11 +13051,11 @@ | |
| 13051 | int, |
| 13052 | int, |
| 13053 | int, |
| 13054 | void(*)(DbPage*) |
| 13055 | ); |
| 13056 | SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*); |
| 13057 | SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); |
| 13058 | |
| 13059 | /* Functions used to configure a Pager object. */ |
| 13060 | SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); |
| 13061 | SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); |
| @@ -13081,19 +13102,22 @@ | |
| 13102 | SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n); |
| 13103 | SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); |
| 13104 | SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager); |
| 13105 | |
| 13106 | #ifndef SQLITE_OMIT_WAL |
| 13107 | SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, sqlite3*, int, int*, int*); |
| 13108 | SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager); |
| 13109 | SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); |
| 13110 | SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); |
| 13111 | SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3*); |
| 13112 | SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager); |
| 13113 | # ifdef SQLITE_ENABLE_SNAPSHOT |
| 13114 | SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot); |
| 13115 | SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot); |
| 13116 | # endif |
| 13117 | #else |
| 13118 | # define sqlite3PagerUseWal(x) 0 |
| 13119 | #endif |
| 13120 | |
| 13121 | #ifdef SQLITE_ENABLE_ZIPVFS |
| 13122 | SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); |
| 13123 | #endif |
| @@ -14060,10 +14084,11 @@ | |
| 14084 | #define SQLITE_QueryOnly 0x04000000 /* Disable database changes */ |
| 14085 | #define SQLITE_VdbeEQP 0x08000000 /* Debug EXPLAIN QUERY PLAN */ |
| 14086 | #define SQLITE_Vacuum 0x10000000 /* Currently in a VACUUM */ |
| 14087 | #define SQLITE_CellSizeCk 0x20000000 /* Check btree cell sizes on load */ |
| 14088 | #define SQLITE_Fts3Tokenizer 0x40000000 /* Enable fts3_tokenizer(2) */ |
| 14089 | #define SQLITE_NoCkptOnClose 0x80000000 /* No checkpoint on close()/DETACH */ |
| 14090 | |
| 14091 | |
| 14092 | /* |
| 14093 | ** Bits of the sqlite3.dbOptFlags field that are used by the |
| 14094 | ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to |
| @@ -17268,10 +17293,13 @@ | |
| 17293 | #if SQLITE_DEFAULT_LOCKING_MODE |
| 17294 | "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), |
| 17295 | #endif |
| 17296 | #if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc) |
| 17297 | "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE), |
| 17298 | #endif |
| 17299 | #if SQLITE_DIRECT_OVERFLOW_READ |
| 17300 | "DIRECT_OVERFLOW_READ", |
| 17301 | #endif |
| 17302 | #if SQLITE_DISABLE_DIRSYNC |
| 17303 | "DISABLE_DIRSYNC", |
| 17304 | #endif |
| 17305 | #if SQLITE_DISABLE_LFS |
| @@ -17354,10 +17382,13 @@ | |
| 17382 | #if SQLITE_ENABLE_UNLOCK_NOTIFY |
| 17383 | "ENABLE_UNLOCK_NOTIFY", |
| 17384 | #endif |
| 17385 | #if SQLITE_ENABLE_UPDATE_DELETE_LIMIT |
| 17386 | "ENABLE_UPDATE_DELETE_LIMIT", |
| 17387 | #endif |
| 17388 | #if defined(SQLITE_ENABLE_URI_00_ERROR) |
| 17389 | "ENABLE_URI_00_ERROR", |
| 17390 | #endif |
| 17391 | #if SQLITE_HAS_CODEC |
| 17392 | "HAS_CODEC", |
| 17393 | #endif |
| 17394 | #if HAVE_ISNAN || SQLITE_HAVE_ISNAN |
| @@ -18105,12 +18136,12 @@ | |
| 18136 | UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */ |
| 18137 | UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */ |
| 18138 | int iNewReg; /* Register for new.* values */ |
| 18139 | i64 iKey1; /* First key value passed to hook */ |
| 18140 | i64 iKey2; /* Second key value passed to hook */ |
| 18141 | Mem *aNew; /* Array of new.* values */ |
| 18142 | Table *pTab; /* Schema object being upated */ |
| 18143 | }; |
| 18144 | |
| 18145 | /* |
| 18146 | ** Function prototypes |
| 18147 | */ |
| @@ -24598,13 +24629,12 @@ | |
| 24629 | char *zNew; |
| 24630 | size_t n; |
| 24631 | if( z==0 ){ |
| 24632 | return 0; |
| 24633 | } |
| 24634 | n = strlen(z) + 1; |
| 24635 | zNew = sqlite3DbMallocRaw(db, n); |
| 24636 | if( zNew ){ |
| 24637 | memcpy(zNew, z, n); |
| 24638 | } |
| 24639 | return zNew; |
| 24640 | } |
| @@ -29127,11 +29157,11 @@ | |
| 29157 | /* 120 */ "SorterData" OpHelp("r[P2]=data"), |
| 29158 | /* 121 */ "RowKey" OpHelp("r[P2]=key"), |
| 29159 | /* 122 */ "RowData" OpHelp("r[P2]=data"), |
| 29160 | /* 123 */ "Rowid" OpHelp("r[P2]=rowid"), |
| 29161 | /* 124 */ "NullRow" OpHelp(""), |
| 29162 | /* 125 */ "SorterInsert" OpHelp("key=r[P2]"), |
| 29163 | /* 126 */ "IdxInsert" OpHelp("key=r[P2]"), |
| 29164 | /* 127 */ "IdxDelete" OpHelp("key=r[P2@P3]"), |
| 29165 | /* 128 */ "Seek" OpHelp("Move P3 to P1.rowid"), |
| 29166 | /* 129 */ "IdxRowid" OpHelp("r[P2]=rowid"), |
| 29167 | /* 130 */ "Destroy" OpHelp(""), |
| @@ -40674,10 +40704,16 @@ | |
| 40704 | a[1] = winIoerrRetryDelay; |
| 40705 | } |
| 40706 | OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); |
| 40707 | return SQLITE_OK; |
| 40708 | } |
| 40709 | case SQLITE_FCNTL_WIN32_GET_HANDLE: { |
| 40710 | LPHANDLE phFile = (LPHANDLE)pArg; |
| 40711 | *phFile = pFile->h; |
| 40712 | OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); |
| 40713 | return SQLITE_OK; |
| 40714 | } |
| 40715 | #ifdef SQLITE_TEST |
| 40716 | case SQLITE_FCNTL_WIN32_SET_HANDLE: { |
| 40717 | LPHANDLE phFile = (LPHANDLE)pArg; |
| 40718 | HANDLE hOldFile = pFile->h; |
| 40719 | pFile->h = *phFile; |
| @@ -44715,11 +44751,11 @@ | |
| 44751 | szBulk = pCache->szAlloc * (i64)pcache1.nInitPage; |
| 44752 | }else{ |
| 44753 | szBulk = -1024 * (i64)pcache1.nInitPage; |
| 44754 | } |
| 44755 | if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){ |
| 44756 | szBulk = pCache->szAlloc*(i64)pCache->nMax; |
| 44757 | } |
| 44758 | zBulk = pCache->pBulk = sqlite3Malloc( szBulk ); |
| 44759 | sqlite3EndBenignMalloc(); |
| 44760 | if( zBulk ){ |
| 44761 | int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc; |
| @@ -46249,21 +46285,21 @@ | |
| 46285 | #define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */ |
| 46286 | |
| 46287 | #ifdef SQLITE_OMIT_WAL |
| 46288 | # define sqlite3WalOpen(x,y,z) 0 |
| 46289 | # define sqlite3WalLimit(x,y) |
| 46290 | # define sqlite3WalClose(v,w,x,y,z) 0 |
| 46291 | # define sqlite3WalBeginReadTransaction(y,z) 0 |
| 46292 | # define sqlite3WalEndReadTransaction(z) |
| 46293 | # define sqlite3WalDbsize(y) 0 |
| 46294 | # define sqlite3WalBeginWriteTransaction(y) 0 |
| 46295 | # define sqlite3WalEndWriteTransaction(x) 0 |
| 46296 | # define sqlite3WalUndo(x,y,z) 0 |
| 46297 | # define sqlite3WalSavepoint(y,z) |
| 46298 | # define sqlite3WalSavepointUndo(y,z) 0 |
| 46299 | # define sqlite3WalFrames(u,v,w,x,y,z) 0 |
| 46300 | # define sqlite3WalCheckpoint(q,r,s,t,u,v,w,x,y,z) 0 |
| 46301 | # define sqlite3WalCallback(z) 0 |
| 46302 | # define sqlite3WalExclusiveMode(y,z) 0 |
| 46303 | # define sqlite3WalHeapMemory(z) 0 |
| 46304 | # define sqlite3WalFramesize(z) 0 |
| 46305 | # define sqlite3WalFindFrame(x,y,z) 0 |
| @@ -46277,11 +46313,11 @@ | |
| 46313 | */ |
| 46314 | typedef struct Wal Wal; |
| 46315 | |
| 46316 | /* Open and close a connection to a write-ahead log. */ |
| 46317 | SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**); |
| 46318 | SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, sqlite3*, int sync_flags, int, u8 *); |
| 46319 | |
| 46320 | /* Set the limiting size of a WAL file. */ |
| 46321 | SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64); |
| 46322 | |
| 46323 | /* Used by readers to open (lock) and close (unlock) a snapshot. A |
| @@ -46320,10 +46356,11 @@ | |
| 46356 | SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int); |
| 46357 | |
| 46358 | /* Copy pages from the log to the database file */ |
| 46359 | SQLITE_PRIVATE int sqlite3WalCheckpoint( |
| 46360 | Wal *pWal, /* Write-ahead log connection */ |
| 46361 | sqlite3 *db, /* Check this handle's interrupt flag */ |
| 46362 | int eMode, /* One of PASSIVE, FULL and RESTART */ |
| 46363 | int (*xBusy)(void*), /* Function to call when busy */ |
| 46364 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 46365 | int sync_flags, /* Flags to sync db file with (or 0) */ |
| 46366 | int nBuf, /* Size of buffer nBuf */ |
| @@ -47164,13 +47201,14 @@ | |
| 47201 | /* |
| 47202 | ** Return true if this pager uses a write-ahead log instead of the usual |
| 47203 | ** rollback journal. Otherwise false. |
| 47204 | */ |
| 47205 | #ifndef SQLITE_OMIT_WAL |
| 47206 | SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager){ |
| 47207 | return (pPager->pWal!=0); |
| 47208 | } |
| 47209 | # define pagerUseWal(x) sqlite3PagerUseWal(x) |
| 47210 | #else |
| 47211 | # define pagerUseWal(x) 0 |
| 47212 | # define pagerRollbackWal(x) 0 |
| 47213 | # define pagerWalFrames(v,w,x,y) 0 |
| 47214 | # define pagerOpenWalIfPresent(z) SQLITE_OK |
| @@ -50368,21 +50406,22 @@ | |
| 50406 | ** This function always succeeds. If a transaction is active an attempt |
| 50407 | ** is made to roll it back. If an error occurs during the rollback |
| 50408 | ** a hot journal may be left in the filesystem but no error is returned |
| 50409 | ** to the caller. |
| 50410 | */ |
| 50411 | SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){ |
| 50412 | u8 *pTmp = (u8 *)pPager->pTmpSpace; |
| 50413 | |
| 50414 | assert( db || pagerUseWal(pPager)==0 ); |
| 50415 | assert( assert_pager_state(pPager) ); |
| 50416 | disable_simulated_io_errors(); |
| 50417 | sqlite3BeginBenignMalloc(); |
| 50418 | pagerFreeMapHdrs(pPager); |
| 50419 | /* pPager->errCode = 0; */ |
| 50420 | pPager->exclusiveMode = 0; |
| 50421 | #ifndef SQLITE_OMIT_WAL |
| 50422 | sqlite3WalClose(pPager->pWal,db,pPager->ckptSyncFlags,pPager->pageSize,pTmp); |
| 50423 | pPager->pWal = 0; |
| 50424 | #endif |
| 50425 | pager_reset(pPager); |
| 50426 | if( MEMDB ){ |
| 50427 | pager_unlock(pPager); |
| @@ -53541,14 +53580,20 @@ | |
| 53580 | ** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint() |
| 53581 | ** or wal_blocking_checkpoint() API functions. |
| 53582 | ** |
| 53583 | ** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. |
| 53584 | */ |
| 53585 | SQLITE_PRIVATE int sqlite3PagerCheckpoint( |
| 53586 | Pager *pPager, /* Checkpoint on this pager */ |
| 53587 | sqlite3 *db, /* Db handle used to check for interrupts */ |
| 53588 | int eMode, /* Type of checkpoint */ |
| 53589 | int *pnLog, /* OUT: Final number of frames in log */ |
| 53590 | int *pnCkpt /* OUT: Final number of checkpointed frames */ |
| 53591 | ){ |
| 53592 | int rc = SQLITE_OK; |
| 53593 | if( pPager->pWal ){ |
| 53594 | rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode, |
| 53595 | (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), |
| 53596 | pPager->pBusyHandlerArg, |
| 53597 | pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, |
| 53598 | pnLog, pnCkpt |
| 53599 | ); |
| @@ -53676,11 +53721,11 @@ | |
| 53721 | ** Before closing the log file, this function attempts to take an |
| 53722 | ** EXCLUSIVE lock on the database file. If this cannot be obtained, an |
| 53723 | ** error (SQLITE_BUSY) is returned and the log connection is not closed. |
| 53724 | ** If successful, the EXCLUSIVE lock is not released before returning. |
| 53725 | */ |
| 53726 | SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){ |
| 53727 | int rc = SQLITE_OK; |
| 53728 | |
| 53729 | assert( pPager->journalMode==PAGER_JOURNALMODE_WAL ); |
| 53730 | |
| 53731 | /* If the log file is not already open, but does exist in the file-system, |
| @@ -53704,11 +53749,11 @@ | |
| 53749 | ** the database file, the log and log-summary files will be deleted. |
| 53750 | */ |
| 53751 | if( rc==SQLITE_OK && pPager->pWal ){ |
| 53752 | rc = pagerExclusiveLock(pPager); |
| 53753 | if( rc==SQLITE_OK ){ |
| 53754 | rc = sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags, |
| 53755 | pPager->pageSize, (u8*)pPager->pTmpSpace); |
| 53756 | pPager->pWal = 0; |
| 53757 | pagerFixMaplimit(pPager); |
| 53758 | if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK); |
| 53759 | } |
| @@ -55487,10 +55532,11 @@ | |
| 55532 | ** checkpoint is running (in any other thread or process) at the same |
| 55533 | ** time. |
| 55534 | */ |
| 55535 | static int walCheckpoint( |
| 55536 | Wal *pWal, /* Wal connection */ |
| 55537 | sqlite3 *db, /* Check for interrupts on this handle */ |
| 55538 | int eMode, /* One of PASSIVE, FULL or RESTART */ |
| 55539 | int (*xBusy)(void*), /* Function to call when busy */ |
| 55540 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 55541 | int sync_flags, /* Flags for OsSync() (or 0) */ |
| 55542 | u8 *zBuf /* Temporary buffer to use */ |
| @@ -55581,10 +55627,14 @@ | |
| 55627 | |
| 55628 | /* Iterate through the contents of the WAL, copying data to the db file */ |
| 55629 | while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ |
| 55630 | i64 iOffset; |
| 55631 | assert( walFramePgno(pWal, iFrame)==iDbpage ); |
| 55632 | if( db->u1.isInterrupted ){ |
| 55633 | rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT; |
| 55634 | break; |
| 55635 | } |
| 55636 | if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){ |
| 55637 | continue; |
| 55638 | } |
| 55639 | iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE; |
| 55640 | /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */ |
| @@ -55685,10 +55735,11 @@ | |
| 55735 | /* |
| 55736 | ** Close a connection to a log file. |
| 55737 | */ |
| 55738 | SQLITE_PRIVATE int sqlite3WalClose( |
| 55739 | Wal *pWal, /* Wal to close */ |
| 55740 | sqlite3 *db, /* For interrupt flag */ |
| 55741 | int sync_flags, /* Flags to pass to OsSync() (or 0) */ |
| 55742 | int nBuf, |
| 55743 | u8 *zBuf /* Buffer of at least nBuf bytes */ |
| 55744 | ){ |
| 55745 | int rc = SQLITE_OK; |
| @@ -55701,17 +55752,18 @@ | |
| 55752 | ** the database. In this case checkpoint the database and unlink both |
| 55753 | ** the wal and wal-index files. |
| 55754 | ** |
| 55755 | ** The EXCLUSIVE lock is not released before returning. |
| 55756 | */ |
| 55757 | if( (db->flags & SQLITE_NoCkptOnClose)==0 |
| 55758 | && SQLITE_OK==(rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE)) |
| 55759 | ){ |
| 55760 | if( pWal->exclusiveMode==WAL_NORMAL_MODE ){ |
| 55761 | pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; |
| 55762 | } |
| 55763 | rc = sqlite3WalCheckpoint(pWal, db, |
| 55764 | SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0 |
| 55765 | ); |
| 55766 | if( rc==SQLITE_OK ){ |
| 55767 | int bPersist = -1; |
| 55768 | sqlite3OsFileControlHint( |
| 55769 | pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersist |
| @@ -56955,10 +57007,11 @@ | |
| 57007 | ** If parameter xBusy is not NULL, it is a pointer to a busy-handler |
| 57008 | ** callback. In this case this function runs a blocking checkpoint. |
| 57009 | */ |
| 57010 | SQLITE_PRIVATE int sqlite3WalCheckpoint( |
| 57011 | Wal *pWal, /* Wal connection */ |
| 57012 | sqlite3 *db, /* Check this handle's interrupt flag */ |
| 57013 | int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */ |
| 57014 | int (*xBusy)(void*), /* Function to call when busy */ |
| 57015 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 57016 | int sync_flags, /* Flags to sync db file with (or 0) */ |
| 57017 | int nBuf, /* Size of temporary buffer */ |
| @@ -57029,11 +57082,11 @@ | |
| 57082 | if( rc==SQLITE_OK ){ |
| 57083 | |
| 57084 | if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ |
| 57085 | rc = SQLITE_CORRUPT_BKPT; |
| 57086 | }else{ |
| 57087 | rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); |
| 57088 | } |
| 57089 | |
| 57090 | /* If no error occurred, set the output variables. */ |
| 57091 | if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ |
| 57092 | if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; |
| @@ -60619,23 +60672,30 @@ | |
| 60672 | *ppBtree = p; |
| 60673 | |
| 60674 | btree_open_out: |
| 60675 | if( rc!=SQLITE_OK ){ |
| 60676 | if( pBt && pBt->pPager ){ |
| 60677 | sqlite3PagerClose(pBt->pPager, 0); |
| 60678 | } |
| 60679 | sqlite3_free(pBt); |
| 60680 | sqlite3_free(p); |
| 60681 | *ppBtree = 0; |
| 60682 | }else{ |
| 60683 | sqlite3_file *pFile; |
| 60684 | |
| 60685 | /* If the B-Tree was successfully opened, set the pager-cache size to the |
| 60686 | ** default value. Except, when opening on an existing shared pager-cache, |
| 60687 | ** do not change the pager-cache size. |
| 60688 | */ |
| 60689 | if( sqlite3BtreeSchema(p, 0, 0)==0 ){ |
| 60690 | sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE); |
| 60691 | } |
| 60692 | |
| 60693 | pFile = sqlite3PagerFile(pBt->pPager); |
| 60694 | if( pFile->pMethods ){ |
| 60695 | sqlite3OsFileControlHint(pFile, SQLITE_FCNTL_PDB, (void*)&pBt->db); |
| 60696 | } |
| 60697 | } |
| 60698 | if( mutexOpen ){ |
| 60699 | assert( sqlite3_mutex_held(mutexOpen) ); |
| 60700 | sqlite3_mutex_leave(mutexOpen); |
| 60701 | } |
| @@ -60761,11 +60821,11 @@ | |
| 60821 | ** it without having to hold the mutex. |
| 60822 | ** |
| 60823 | ** Clean out and delete the BtShared object. |
| 60824 | */ |
| 60825 | assert( !pBt->pCursor ); |
| 60826 | sqlite3PagerClose(pBt->pPager, p->db); |
| 60827 | if( pBt->xFreeSchema && pBt->pSchema ){ |
| 60828 | pBt->xFreeSchema(pBt->pSchema); |
| 60829 | } |
| 60830 | sqlite3DbFree(0, pBt->pSchema); |
| 60831 | freeTempSpace(pBt); |
| @@ -62825,11 +62885,11 @@ | |
| 62885 | if( (eOp&0x01)==0 /* (1) */ |
| 62886 | && offset==0 /* (2) */ |
| 62887 | && (bEnd || a==ovflSize) /* (6) */ |
| 62888 | && pBt->inTransaction==TRANS_READ /* (4) */ |
| 62889 | && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */ |
| 62890 | && 0==sqlite3PagerUseWal(pBt->pPager) /* (5) */ |
| 62891 | && &pBuf[-4]>=pBufStart /* (7) */ |
| 62892 | ){ |
| 62893 | u8 aSave[4]; |
| 62894 | u8 *aWrite = &pBuf[-4]; |
| 62895 | assert( aWrite>=pBufStart ); /* hence (7) */ |
| @@ -63081,13 +63141,16 @@ | |
| 63141 | } |
| 63142 | sqlite3BtreeClearCursor(pCur); |
| 63143 | } |
| 63144 | |
| 63145 | if( pCur->iPage>=0 ){ |
| 63146 | if( pCur->iPage ){ |
| 63147 | do{ |
| 63148 | assert( pCur->apPage[pCur->iPage]!=0 ); |
| 63149 | releasePageNotNull(pCur->apPage[pCur->iPage--]); |
| 63150 | }while( pCur->iPage); |
| 63151 | goto skip_init; |
| 63152 | } |
| 63153 | }else if( pCur->pgnoRoot==0 ){ |
| 63154 | pCur->eState = CURSOR_INVALID; |
| 63155 | return SQLITE_OK; |
| 63156 | }else{ |
| @@ -63094,11 +63157,11 @@ | |
| 63157 | assert( pCur->iPage==(-1) ); |
| 63158 | rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0], |
| 63159 | 0, pCur->curPagerFlags); |
| 63160 | if( rc!=SQLITE_OK ){ |
| 63161 | pCur->eState = CURSOR_INVALID; |
| 63162 | return rc; |
| 63163 | } |
| 63164 | pCur->iPage = 0; |
| 63165 | pCur->curIntKey = pCur->apPage[0]->intKey; |
| 63166 | } |
| 63167 | pRoot = pCur->apPage[0]; |
| @@ -63117,14 +63180,16 @@ | |
| 63180 | assert( pRoot->intKey==1 || pRoot->intKey==0 ); |
| 63181 | if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){ |
| 63182 | return SQLITE_CORRUPT_BKPT; |
| 63183 | } |
| 63184 | |
| 63185 | skip_init: |
| 63186 | pCur->aiIdx[0] = 0; |
| 63187 | pCur->info.nSize = 0; |
| 63188 | pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl); |
| 63189 | |
| 63190 | pRoot = pCur->apPage[0]; |
| 63191 | if( pRoot->nCell>0 ){ |
| 63192 | pCur->eState = CURSOR_VALID; |
| 63193 | }else if( !pRoot->leaf ){ |
| 63194 | Pgno subpage; |
| 63195 | if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT; |
| @@ -67701,11 +67766,11 @@ | |
| 67766 | BtShared *pBt = p->pBt; |
| 67767 | sqlite3BtreeEnter(p); |
| 67768 | if( pBt->inTransaction!=TRANS_NONE ){ |
| 67769 | rc = SQLITE_LOCKED; |
| 67770 | }else{ |
| 67771 | rc = sqlite3PagerCheckpoint(pBt->pPager, p->db, eMode, pnLog, pnCkpt); |
| 67772 | } |
| 67773 | sqlite3BtreeLeave(p); |
| 67774 | } |
| 67775 | return rc; |
| 67776 | } |
| @@ -69336,11 +69401,11 @@ | |
| 69401 | switch( aff ){ |
| 69402 | case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */ |
| 69403 | if( (pMem->flags & MEM_Blob)==0 ){ |
| 69404 | sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding); |
| 69405 | assert( pMem->flags & MEM_Str || pMem->db->mallocFailed ); |
| 69406 | if( pMem->flags & MEM_Str ) MemSetTypeFlag(pMem, MEM_Blob); |
| 69407 | }else{ |
| 69408 | pMem->flags &= ~(MEM_TypeMask&~MEM_Blob); |
| 69409 | } |
| 69410 | break; |
| 69411 | } |
| @@ -75076,11 +75141,11 @@ | |
| 75141 | preupdate.keyinfo.enc = ENC(db); |
| 75142 | preupdate.keyinfo.nField = pTab->nCol; |
| 75143 | preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder; |
| 75144 | preupdate.iKey1 = iKey1; |
| 75145 | preupdate.iKey2 = iKey2; |
| 75146 | preupdate.pTab = pTab; |
| 75147 | |
| 75148 | db->pPreUpdate = &preupdate; |
| 75149 | db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2); |
| 75150 | db->pPreUpdate = 0; |
| 75151 | sqlite3DbFree(db, preupdate.aRecord); |
| @@ -76808,13 +76873,18 @@ | |
| 76873 | } |
| 76874 | |
| 76875 | if( iIdx>=p->pUnpacked->nField ){ |
| 76876 | *ppValue = (sqlite3_value *)columnNullValue(); |
| 76877 | }else{ |
| 76878 | Mem *pMem = *ppValue = &p->pUnpacked->aMem[iIdx]; |
| 76879 | *ppValue = &p->pUnpacked->aMem[iIdx]; |
| 76880 | if( iIdx==p->pTab->iPKey ){ |
| 76881 | sqlite3VdbeMemSetInt64(pMem, p->iKey1); |
| 76882 | }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){ |
| 76883 | if( pMem->flags & MEM_Int ){ |
| 76884 | sqlite3VdbeMemRealify(pMem); |
| 76885 | } |
| 76886 | } |
| 76887 | } |
| 76888 | |
| 76889 | preupdate_old_out: |
| 76890 | sqlite3Error(db, rc); |
| @@ -76887,11 +76957,11 @@ | |
| 76957 | } |
| 76958 | if( iIdx>=pUnpack->nField ){ |
| 76959 | pMem = (sqlite3_value *)columnNullValue(); |
| 76960 | }else{ |
| 76961 | pMem = &pUnpack->aMem[iIdx]; |
| 76962 | if( iIdx==p->pTab->iPKey ){ |
| 76963 | sqlite3VdbeMemSetInt64(pMem, p->iKey2); |
| 76964 | } |
| 76965 | } |
| 76966 | }else{ |
| 76967 | /* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required |
| @@ -76908,11 +76978,11 @@ | |
| 76978 | } |
| 76979 | } |
| 76980 | assert( iIdx>=0 && iIdx<p->pCsr->nField ); |
| 76981 | pMem = &p->aNew[iIdx]; |
| 76982 | if( pMem->flags==0 ){ |
| 76983 | if( iIdx==p->pTab->iPKey ){ |
| 76984 | sqlite3VdbeMemSetInt64(pMem, p->iKey2); |
| 76985 | }else{ |
| 76986 | rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]); |
| 76987 | if( rc!=SQLITE_OK ) goto preupdate_new_out; |
| 76988 | } |
| @@ -79286,12 +79356,11 @@ | |
| 79356 | ** or not both operands are null. |
| 79357 | */ |
| 79358 | assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne ); |
| 79359 | assert( (flags1 & MEM_Cleared)==0 ); |
| 79360 | assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 ); |
| 79361 | if( (flags1&flags3&MEM_Null)!=0 |
| 79362 | && (flags3&MEM_Cleared)==0 |
| 79363 | ){ |
| 79364 | res = 0; /* Operands are equal */ |
| 79365 | }else{ |
| 79366 | res = 1; /* Operands are not equal */ |
| @@ -81554,11 +81623,11 @@ | |
| 81623 | |
| 81624 | REGISTER_TRACE(pOp->p3, pMem); |
| 81625 | sqlite3VdbeMemIntegerify(pMem); |
| 81626 | assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ |
| 81627 | if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){ |
| 81628 | rc = SQLITE_FULL; /* IMP: R-17817-00630 */ |
| 81629 | goto abort_due_to_error; |
| 81630 | } |
| 81631 | if( v<pMem->u.i+1 ){ |
| 81632 | v = pMem->u.i + 1; |
| 81633 | } |
| @@ -82321,10 +82390,17 @@ | |
| 82390 | ** This flag avoids doing an extra seek. |
| 82391 | ** |
| 82392 | ** This instruction only works for indices. The equivalent instruction |
| 82393 | ** for tables is OP_Insert. |
| 82394 | */ |
| 82395 | /* Opcode: SorterInsert P1 P2 * * * |
| 82396 | ** Synopsis: key=r[P2] |
| 82397 | ** |
| 82398 | ** Register P2 holds an SQL index key made using the |
| 82399 | ** MakeRecord instructions. This opcode writes that key |
| 82400 | ** into the sorter P1. Data for the entry is nil. |
| 82401 | */ |
| 82402 | case OP_SorterInsert: /* in2 */ |
| 82403 | case OP_IdxInsert: { /* in2 */ |
| 82404 | VdbeCursor *pC; |
| 82405 | BtreePayload x; |
| 82406 | |
| @@ -83549,11 +83625,11 @@ | |
| 83625 | /* If leaving WAL mode, close the log file. If successful, the call |
| 83626 | ** to PagerCloseWal() checkpoints and deletes the write-ahead-log |
| 83627 | ** file. An EXCLUSIVE lock may still be held on the database file |
| 83628 | ** after a successful return. |
| 83629 | */ |
| 83630 | rc = sqlite3PagerCloseWal(pPager, db); |
| 83631 | if( rc==SQLITE_OK ){ |
| 83632 | sqlite3PagerSetJournalMode(pPager, eNew); |
| 83633 | } |
| 83634 | }else if( eOld==PAGER_JOURNALMODE_MEMORY ){ |
| 83635 | /* Cannot transition directly from MEMORY to WAL. Use mode OFF |
| @@ -88812,11 +88888,10 @@ | |
| 88888 | const char *zId; /* The function name. */ |
| 88889 | FuncDef *pDef; /* Information about the function */ |
| 88890 | u8 enc = ENC(pParse->db); /* The database encoding */ |
| 88891 | |
| 88892 | assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); |
| 88893 | zId = pExpr->u.zToken; |
| 88894 | nId = sqlite3Strlen30(zId); |
| 88895 | pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0); |
| 88896 | if( pDef==0 ){ |
| 88897 | pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0); |
| @@ -94293,15 +94368,14 @@ | |
| 94368 | && (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab) |
| 94369 | || sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) ) |
| 94370 | ){ |
| 94371 | return 1; |
| 94372 | } |
| 94373 | if( pE2->op==TK_NOTNULL && pE1->op!=TK_ISNULL && pE1->op!=TK_IS ){ |
| 94374 | Expr *pX = sqlite3ExprSkipCollate(pE1->pLeft); |
| 94375 | testcase( pX!=pE1->pLeft ); |
| 94376 | if( sqlite3ExprCompare(pX, pE2->pLeft, iTab)==0 ) return 1; |
| 94377 | } |
| 94378 | return 0; |
| 94379 | } |
| 94380 | |
| 94381 | /* |
| @@ -122355,11 +122429,11 @@ | |
| 122429 | } |
| 122430 | #endif |
| 122431 | |
| 122432 | sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size); |
| 122433 | sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0)); |
| 122434 | sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF|PAGER_CACHESPILL); |
| 122435 | |
| 122436 | /* Begin a transaction and take an exclusive lock on the main database |
| 122437 | ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below, |
| 122438 | ** to ensure that we do not try to change the page-size on a WAL database. |
| 122439 | */ |
| @@ -124663,11 +124737,10 @@ | |
| 124737 | ** |
| 124738 | ** * the comparison will be performed with no affinity, or |
| 124739 | ** * the affinity change in zAff is guaranteed not to change the value. |
| 124740 | */ |
| 124741 | static void updateRangeAffinityStr( |
| 124742 | Expr *pRight, /* RHS of comparison */ |
| 124743 | int n, /* Number of vector elements in comparison */ |
| 124744 | char *zAff /* Affinity string to modify */ |
| 124745 | ){ |
| 124746 | int i; |
| @@ -125749,15 +125822,15 @@ | |
| 125822 | assert( (bRev & ~1)==0 ); |
| 125823 | pLevel->iLikeRepCntr <<=1; |
| 125824 | pLevel->iLikeRepCntr |= bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC); |
| 125825 | } |
| 125826 | #endif |
| 125827 | if( pRangeStart==0 ){ |
| 125828 | j = pIdx->aiColumn[nEq]; |
| 125829 | if( (j>=0 && pIdx->pTable->aCol[j].notNull==0) || j==XN_EXPR ){ |
| 125830 | bSeekPastNull = 1; |
| 125831 | } |
| 125832 | } |
| 125833 | } |
| 125834 | assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 ); |
| 125835 | |
| 125836 | /* If we are doing a reverse order scan on an ascending index, or |
| @@ -125803,11 +125876,11 @@ | |
| 125876 | ){ |
| 125877 | sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); |
| 125878 | VdbeCoverage(v); |
| 125879 | } |
| 125880 | if( zStartAff ){ |
| 125881 | updateRangeAffinityStr(pRight, nBtm, &zStartAff[nEq]); |
| 125882 | } |
| 125883 | nConstraint += nBtm; |
| 125884 | testcase( pRangeStart->wtFlags & TERM_VIRTUAL ); |
| 125885 | if( sqlite3ExprIsVector(pRight)==0 ){ |
| 125886 | disableTerm(pLevel, pRangeStart); |
| @@ -125853,11 +125926,11 @@ | |
| 125926 | ){ |
| 125927 | sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); |
| 125928 | VdbeCoverage(v); |
| 125929 | } |
| 125930 | if( zEndAff ){ |
| 125931 | updateRangeAffinityStr(pRight, nTop, zEndAff); |
| 125932 | codeApplyAffinity(pParse, regBase+nEq, nTop, zEndAff); |
| 125933 | }else{ |
| 125934 | assert( pParse->db->mallocFailed ); |
| 125935 | } |
| 125936 | nConstraint += nTop; |
| @@ -127539,10 +127612,11 @@ | |
| 127612 | Expr *pNew; |
| 127613 | Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i); |
| 127614 | Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i); |
| 127615 | |
| 127616 | pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight, 0); |
| 127617 | transferJoinMarkings(pNew, pExpr); |
| 127618 | idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC); |
| 127619 | exprAnalyze(pSrc, pWC, idxNew); |
| 127620 | } |
| 127621 | pTerm = &pWC->a[idxTerm]; |
| 127622 | pTerm->wtFlags = TERM_CODED|TERM_VIRTUAL; /* Disable the original */ |
| @@ -127980,15 +128054,17 @@ | |
| 128054 | Expr *pX; /* An expression being tested */ |
| 128055 | WhereClause *pWC; /* Shorthand for pScan->pWC */ |
| 128056 | WhereTerm *pTerm; /* The term being tested */ |
| 128057 | int k = pScan->k; /* Where to start scanning */ |
| 128058 | |
| 128059 | assert( pScan->iEquiv<=pScan->nEquiv ); |
| 128060 | pWC = pScan->pWC; |
| 128061 | while(1){ |
| 128062 | iColumn = pScan->aiColumn[pScan->iEquiv-1]; |
| 128063 | iCur = pScan->aiCur[pScan->iEquiv-1]; |
| 128064 | assert( pWC!=0 ); |
| 128065 | do{ |
| 128066 | for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){ |
| 128067 | if( pTerm->leftCursor==iCur |
| 128068 | && pTerm->u.leftColumn==iColumn |
| 128069 | && (iColumn!=XN_EXPR |
| 128070 | || sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0) |
| @@ -128034,19 +128110,21 @@ | |
| 128110 | && pX->iColumn==pScan->aiColumn[0] |
| 128111 | ){ |
| 128112 | testcase( pTerm->eOperator & WO_IS ); |
| 128113 | continue; |
| 128114 | } |
| 128115 | pScan->pWC = pWC; |
| 128116 | pScan->k = k+1; |
| 128117 | return pTerm; |
| 128118 | } |
| 128119 | } |
| 128120 | } |
| 128121 | pWC = pWC->pOuter; |
| 128122 | k = 0; |
| 128123 | }while( pWC!=0 ); |
| 128124 | if( pScan->iEquiv>=pScan->nEquiv ) break; |
| 128125 | pWC = pScan->pOrigWC; |
| 128126 | k = 0; |
| 128127 | pScan->iEquiv++; |
| 128128 | } |
| 128129 | return 0; |
| 128130 | } |
| @@ -128076,28 +128154,28 @@ | |
| 128154 | int iCur, /* Cursor to scan for */ |
| 128155 | int iColumn, /* Column to scan for */ |
| 128156 | u32 opMask, /* Operator(s) to scan for */ |
| 128157 | Index *pIdx /* Must be compatible with this index */ |
| 128158 | ){ |
| 128159 | pScan->pOrigWC = pWC; |
| 128160 | pScan->pWC = pWC; |
| 128161 | pScan->pIdxExpr = 0; |
| 128162 | pScan->idxaff = 0; |
| 128163 | pScan->zCollName = 0; |
| 128164 | if( pIdx ){ |
| 128165 | int j = iColumn; |
| 128166 | iColumn = pIdx->aiColumn[j]; |
| 128167 | if( iColumn==XN_EXPR ){ |
| 128168 | pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; |
| 128169 | }else if( iColumn==pIdx->pTable->iPKey ){ |
| 128170 | iColumn = XN_ROWID; |
| 128171 | }else if( iColumn>=0 ){ |
| 128172 | pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; |
| 128173 | pScan->zCollName = pIdx->azColl[j]; |
| 128174 | } |
| 128175 | }else if( iColumn==XN_EXPR ){ |
| 128176 | return 0; |
| 128177 | } |
| 128178 | pScan->opMask = opMask; |
| 128179 | pScan->k = 0; |
| 128180 | pScan->aiCur[0] = iCur; |
| 128181 | pScan->aiColumn[0] = iColumn; |
| @@ -130005,11 +130083,11 @@ | |
| 130083 | ** CREATE INDEX ... ON (a, b, c, d, e) |
| 130084 | ** |
| 130085 | ** then this function would be invoked with nEq=1. The value returned in |
| 130086 | ** this case is 3. |
| 130087 | */ |
| 130088 | static int whereRangeVectorLen( |
| 130089 | Parse *pParse, /* Parsing context */ |
| 130090 | int iCur, /* Cursor open on pIdx */ |
| 130091 | Index *pIdx, /* The index to be used for a inequality constraint */ |
| 130092 | int nEq, /* Number of prior equality constraints on same index */ |
| 130093 | WhereTerm *pTerm /* The vector inequality constraint */ |
| @@ -131451,11 +131529,11 @@ | |
| 131529 | if( rev ) *pRevMask |= MASKBIT(iLoop); |
| 131530 | revSet = 1; |
| 131531 | } |
| 131532 | } |
| 131533 | if( isMatch ){ |
| 131534 | if( iColumn==XN_ROWID ){ |
| 131535 | testcase( distinctColumns==0 ); |
| 131536 | distinctColumns = 1; |
| 131537 | } |
| 131538 | obSat |= MASKBIT(i); |
| 131539 | }else{ |
| @@ -131906,17 +131984,24 @@ | |
| 131984 | }else{ |
| 131985 | pWInfo->nOBSat = pFrom->isOrdered; |
| 131986 | pWInfo->revMask = pFrom->revLoop; |
| 131987 | if( pWInfo->nOBSat<=0 ){ |
| 131988 | pWInfo->nOBSat = 0; |
| 131989 | if( nLoop>0 ){ |
| 131990 | u32 wsFlags = pFrom->aLoop[nLoop-1]->wsFlags; |
| 131991 | if( (wsFlags & WHERE_ONEROW)==0 |
| 131992 | && (wsFlags&(WHERE_IPK|WHERE_COLUMN_IN))!=(WHERE_IPK|WHERE_COLUMN_IN) |
| 131993 | ){ |
| 131994 | Bitmask m = 0; |
| 131995 | int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom, |
| 131996 | WHERE_ORDERBY_LIMIT, nLoop-1, pFrom->aLoop[nLoop-1], &m); |
| 131997 | testcase( wsFlags & WHERE_IPK ); |
| 131998 | testcase( wsFlags & WHERE_COLUMN_IN ); |
| 131999 | if( rc==pWInfo->pOrderBy->nExpr ){ |
| 132000 | pWInfo->bOrderedInnerLoop = 1; |
| 132001 | pWInfo->revMask = m; |
| 132002 | } |
| 132003 | } |
| 132004 | } |
| 132005 | } |
| 132006 | } |
| 132007 | if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP) |
| @@ -132635,17 +132720,19 @@ | |
| 132720 | pLevel->addrLikeRep); |
| 132721 | VdbeCoverage(v); |
| 132722 | } |
| 132723 | #endif |
| 132724 | if( pLevel->iLeftJoin ){ |
| 132725 | int ws = pLoop->wsFlags; |
| 132726 | addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v); |
| 132727 | assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 ); |
| 132728 | if( (ws & WHERE_IDX_ONLY)==0 ){ |
| 132729 | sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor); |
| 132730 | } |
| 132731 | if( (ws & WHERE_INDEXED) |
| 132732 | || ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx) |
| 132733 | ){ |
| 132734 | sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur); |
| 132735 | } |
| 132736 | if( pLevel->op==OP_Return ){ |
| 132737 | sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst); |
| 132738 | }else{ |
| @@ -138607,10 +138694,11 @@ | |
| 138694 | } aFlagOp[] = { |
| 138695 | { SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys }, |
| 138696 | { SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger }, |
| 138697 | { SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer }, |
| 138698 | { SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension }, |
| 138699 | { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose }, |
| 138700 | }; |
| 138701 | unsigned int i; |
| 138702 | rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ |
| 138703 | for(i=0; i<ArraySize(aFlagOp); i++){ |
| 138704 | if( aFlagOp[i].op==op ){ |
| @@ -139903,10 +139991,17 @@ | |
| 139991 | db->busyHandler.nBusy = 0; |
| 139992 | rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt); |
| 139993 | sqlite3Error(db, rc); |
| 139994 | } |
| 139995 | rc = sqlite3ApiExit(db, rc); |
| 139996 | |
| 139997 | /* If there are no active statements, clear the interrupt flag at this |
| 139998 | ** point. */ |
| 139999 | if( db->nVdbeActive==0 ){ |
| 140000 | db->u1.isInterrupted = 0; |
| 140001 | } |
| 140002 | |
| 140003 | sqlite3_mutex_leave(db->mutex); |
| 140004 | return rc; |
| 140005 | #endif |
| 140006 | } |
| 140007 | |
| @@ -140405,10 +140500,11 @@ | |
| 140500 | int octet = (sqlite3HexToInt(zUri[iIn++]) << 4); |
| 140501 | octet += sqlite3HexToInt(zUri[iIn++]); |
| 140502 | |
| 140503 | assert( octet>=0 && octet<256 ); |
| 140504 | if( octet==0 ){ |
| 140505 | #ifndef SQLITE_ENABLE_URI_00_ERROR |
| 140506 | /* This branch is taken when "%00" appears within the URI. In this |
| 140507 | ** case we ignore all text in the remainder of the path, name or |
| 140508 | ** value currently being parsed. So ignore the current character |
| 140509 | ** and skip to the next "?", "=" or "&", as appropriate. */ |
| 140510 | while( (c = zUri[iIn])!=0 && c!='#' |
| @@ -140417,10 +140513,16 @@ | |
| 140513 | && (eState!=2 || c!='&') |
| 140514 | ){ |
| 140515 | iIn++; |
| 140516 | } |
| 140517 | continue; |
| 140518 | #else |
| 140519 | /* If ENABLE_URI_00_ERROR is defined, "%00" in a URI is an error. */ |
| 140520 | *pzErrMsg = sqlite3_mprintf("unexpected %%00 in uri"); |
| 140521 | rc = SQLITE_ERROR; |
| 140522 | goto parse_uri_out; |
| 140523 | #endif |
| 140524 | } |
| 140525 | c = octet; |
| 140526 | }else if( eState==1 && (c=='&' || c=='=') ){ |
| 140527 | if( zFile[iOut-1]==0 ){ |
| 140528 | /* An empty option name. Ignore this option altogether. */ |
| @@ -164296,14 +164398,16 @@ | |
| 164398 | char *zSql; |
| 164399 | sqlite3_stmt *p; |
| 164400 | int rc; |
| 164401 | i64 nRow = 0; |
| 164402 | |
| 164403 | rc = sqlite3_table_column_metadata( |
| 164404 | db, pRtree->zDb, "sqlite_stat1",0,0,0,0,0,0 |
| 164405 | ); |
| 164406 | if( rc!=SQLITE_OK ){ |
| 164407 | pRtree->nRowEst = RTREE_DEFAULT_ROWEST; |
| 164408 | return rc==SQLITE_ERROR ? SQLITE_OK : rc; |
| 164409 | } |
| 164410 | zSql = sqlite3_mprintf(zFmt, pRtree->zDb, pRtree->zName); |
| 164411 | if( zSql==0 ){ |
| 164412 | rc = SQLITE_NOMEM; |
| 164413 | }else{ |
| @@ -165200,11 +165304,11 @@ | |
| 165304 | ** of the locale to use. Passing an empty string ("") or SQL NULL value |
| 165305 | ** as the second argument is the same as invoking the 1 argument version |
| 165306 | ** of upper() or lower(). |
| 165307 | ** |
| 165308 | ** lower('I', 'en_us') -> 'i' |
| 165309 | ** lower('I', 'tr_tr') -> '\u131' (small dotless i) |
| 165310 | ** |
| 165311 | ** http://www.icu-project.org/userguide/posix.html#case_mappings |
| 165312 | */ |
| 165313 | static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){ |
| 165314 | const UChar *zInput; /* Pointer to input string */ |
| @@ -181496,10 +181600,13 @@ | |
| 181600 | int nToken, /* Size of token in bytes */ |
| 181601 | int iStartOff, /* Start offset of token */ |
| 181602 | int iEndOff /* End offset of token */ |
| 181603 | ){ |
| 181604 | int rc = SQLITE_OK; |
| 181605 | |
| 181606 | UNUSED_PARAM2(pToken, nToken); |
| 181607 | UNUSED_PARAM(iEndOff); |
| 181608 | |
| 181609 | if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){ |
| 181610 | Fts5SFinder *p = (Fts5SFinder*)pContext; |
| 181611 | if( p->iPos>0 ){ |
| 181612 | int i; |
| @@ -181652,11 +181759,10 @@ | |
| 181759 | for(jj=0; jj<(sFinder.nFirst-1); jj++){ |
| 181760 | if( sFinder.aFirst[jj+1]>io ) break; |
| 181761 | } |
| 181762 | |
| 181763 | if( sFinder.aFirst[jj]<io ){ |
| 181764 | memset(aSeen, 0, nPhrase); |
| 181765 | rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i, |
| 181766 | sFinder.aFirst[jj], nToken, &nScore, 0 |
| 181767 | ); |
| 181768 | |
| @@ -195587,11 +195693,11 @@ | |
| 195693 | int nArg, /* Number of args */ |
| 195694 | sqlite3_value **apUnused /* Function arguments */ |
| 195695 | ){ |
| 195696 | assert( nArg==0 ); |
| 195697 | UNUSED_PARAM2(nArg, apUnused); |
| 195698 | sqlite3_result_text(pCtx, "fts5: 2016-10-26 16:05:10 ec9dab8054c71d112c68f58a45821b38c2a45677", -1, SQLITE_TRANSIENT); |
| 195699 | } |
| 195700 | |
| 195701 | static int fts5Init(sqlite3 *db){ |
| 195702 | static const sqlite3_module fts5Mod = { |
| 195703 | /* iVersion */ 2, |
| 195704 |
+24
-3
| --- src/sqlite3.h | ||
| +++ src/sqlite3.h | ||
| @@ -119,13 +119,13 @@ | ||
| 119 | 119 | ** |
| 120 | 120 | ** See also: [sqlite3_libversion()], |
| 121 | 121 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 122 | 122 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 123 | 123 | */ |
| 124 | -#define SQLITE_VERSION "3.15.0" | |
| 125 | -#define SQLITE_VERSION_NUMBER 3015000 | |
| 126 | -#define SQLITE_SOURCE_ID "2016-10-04 12:20:12 3a9d802fda10585654332b314d317250dc5d894e" | |
| 124 | +#define SQLITE_VERSION "3.16.0" | |
| 125 | +#define SQLITE_VERSION_NUMBER 3016000 | |
| 126 | +#define SQLITE_SOURCE_ID "2016-11-02 14:50:19 3028845329c9b7acdec2ec8b01d00d782347454c" | |
| 127 | 127 | |
| 128 | 128 | /* |
| 129 | 129 | ** CAPI3REF: Run-Time Library Version Numbers |
| 130 | 130 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 131 | 131 | ** |
| @@ -975,10 +975,16 @@ | ||
| 975 | 975 | ** <li>[[SQLITE_FCNTL_HAS_MOVED]] |
| 976 | 976 | ** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a |
| 977 | 977 | ** pointer to an integer and it writes a boolean into that integer depending |
| 978 | 978 | ** on whether or not the file has been renamed, moved, or deleted since it |
| 979 | 979 | ** was first opened. |
| 980 | +** | |
| 981 | +** <li>[[SQLITE_FCNTL_WIN32_GET_HANDLE]] | |
| 982 | +** The [SQLITE_FCNTL_WIN32_GET_HANDLE] opcode can be used to obtain the | |
| 983 | +** underlying native file handle associated with a file handle. This file | |
| 984 | +** control interprets its argument as a pointer to a native file handle and | |
| 985 | +** writes the resulting value there. | |
| 980 | 986 | ** |
| 981 | 987 | ** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]] |
| 982 | 988 | ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This |
| 983 | 989 | ** opcode causes the xFileControl method to swap the file handle with the one |
| 984 | 990 | ** pointed to by the pArg argument. This capability is used during testing |
| @@ -1026,10 +1032,12 @@ | ||
| 1026 | 1032 | #define SQLITE_FCNTL_WAL_BLOCK 24 |
| 1027 | 1033 | #define SQLITE_FCNTL_ZIPVFS 25 |
| 1028 | 1034 | #define SQLITE_FCNTL_RBU 26 |
| 1029 | 1035 | #define SQLITE_FCNTL_VFS_POINTER 27 |
| 1030 | 1036 | #define SQLITE_FCNTL_JOURNAL_POINTER 28 |
| 1037 | +#define SQLITE_FCNTL_WIN32_GET_HANDLE 29 | |
| 1038 | +#define SQLITE_FCNTL_PDB 30 | |
| 1031 | 1039 | |
| 1032 | 1040 | /* deprecated names */ |
| 1033 | 1041 | #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE |
| 1034 | 1042 | #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE |
| 1035 | 1043 | #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| @@ -1978,18 +1986,31 @@ | ||
| 1978 | 1986 | ** does not make a copy of the new main schema name string, so the application |
| 1979 | 1987 | ** must ensure that the argument passed into this DBCONFIG option is unchanged |
| 1980 | 1988 | ** until after the database connection closes. |
| 1981 | 1989 | ** </dd> |
| 1982 | 1990 | ** |
| 1991 | +** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt> | |
| 1992 | +** <dd> Usually, when a database in wal mode is closed or detached from a | |
| 1993 | +** database handle, SQLite checks if this will mean that there are now no | |
| 1994 | +** connections at all to the database. If so, it performs a checkpoint | |
| 1995 | +** operation before closing the connection. This option may be used to | |
| 1996 | +** override this behaviour. The first parameter passed to this operation | |
| 1997 | +** is an integer - non-zero to disable checkpoints-on-close, or zero (the | |
| 1998 | +** default) to enable them. The second parameter is a pointer to an integer | |
| 1999 | +** into which is written 0 or 1 to indicate whether checkpoints-on-close | |
| 2000 | +** have been disabled - 0 if they are not disabled, 1 if they are. | |
| 2001 | +** </dd> | |
| 2002 | +** | |
| 1983 | 2003 | ** </dl> |
| 1984 | 2004 | */ |
| 1985 | 2005 | #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ |
| 1986 | 2006 | #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ |
| 1987 | 2007 | #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ |
| 1988 | 2008 | #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ |
| 1989 | 2009 | #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ |
| 1990 | 2010 | #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ |
| 2011 | +#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */ | |
| 1991 | 2012 | |
| 1992 | 2013 | |
| 1993 | 2014 | /* |
| 1994 | 2015 | ** CAPI3REF: Enable Or Disable Extended Result Codes |
| 1995 | 2016 | ** METHOD: sqlite3 |
| 1996 | 2017 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -119,13 +119,13 @@ | |
| 119 | ** |
| 120 | ** See also: [sqlite3_libversion()], |
| 121 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 122 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 123 | */ |
| 124 | #define SQLITE_VERSION "3.15.0" |
| 125 | #define SQLITE_VERSION_NUMBER 3015000 |
| 126 | #define SQLITE_SOURCE_ID "2016-10-04 12:20:12 3a9d802fda10585654332b314d317250dc5d894e" |
| 127 | |
| 128 | /* |
| 129 | ** CAPI3REF: Run-Time Library Version Numbers |
| 130 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 131 | ** |
| @@ -975,10 +975,16 @@ | |
| 975 | ** <li>[[SQLITE_FCNTL_HAS_MOVED]] |
| 976 | ** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a |
| 977 | ** pointer to an integer and it writes a boolean into that integer depending |
| 978 | ** on whether or not the file has been renamed, moved, or deleted since it |
| 979 | ** was first opened. |
| 980 | ** |
| 981 | ** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]] |
| 982 | ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This |
| 983 | ** opcode causes the xFileControl method to swap the file handle with the one |
| 984 | ** pointed to by the pArg argument. This capability is used during testing |
| @@ -1026,10 +1032,12 @@ | |
| 1026 | #define SQLITE_FCNTL_WAL_BLOCK 24 |
| 1027 | #define SQLITE_FCNTL_ZIPVFS 25 |
| 1028 | #define SQLITE_FCNTL_RBU 26 |
| 1029 | #define SQLITE_FCNTL_VFS_POINTER 27 |
| 1030 | #define SQLITE_FCNTL_JOURNAL_POINTER 28 |
| 1031 | |
| 1032 | /* deprecated names */ |
| 1033 | #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE |
| 1034 | #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE |
| 1035 | #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| @@ -1978,18 +1986,31 @@ | |
| 1978 | ** does not make a copy of the new main schema name string, so the application |
| 1979 | ** must ensure that the argument passed into this DBCONFIG option is unchanged |
| 1980 | ** until after the database connection closes. |
| 1981 | ** </dd> |
| 1982 | ** |
| 1983 | ** </dl> |
| 1984 | */ |
| 1985 | #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ |
| 1986 | #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ |
| 1987 | #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ |
| 1988 | #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ |
| 1989 | #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ |
| 1990 | #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ |
| 1991 | |
| 1992 | |
| 1993 | /* |
| 1994 | ** CAPI3REF: Enable Or Disable Extended Result Codes |
| 1995 | ** METHOD: sqlite3 |
| 1996 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -119,13 +119,13 @@ | |
| 119 | ** |
| 120 | ** See also: [sqlite3_libversion()], |
| 121 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 122 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 123 | */ |
| 124 | #define SQLITE_VERSION "3.16.0" |
| 125 | #define SQLITE_VERSION_NUMBER 3016000 |
| 126 | #define SQLITE_SOURCE_ID "2016-11-02 14:50:19 3028845329c9b7acdec2ec8b01d00d782347454c" |
| 127 | |
| 128 | /* |
| 129 | ** CAPI3REF: Run-Time Library Version Numbers |
| 130 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 131 | ** |
| @@ -975,10 +975,16 @@ | |
| 975 | ** <li>[[SQLITE_FCNTL_HAS_MOVED]] |
| 976 | ** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a |
| 977 | ** pointer to an integer and it writes a boolean into that integer depending |
| 978 | ** on whether or not the file has been renamed, moved, or deleted since it |
| 979 | ** was first opened. |
| 980 | ** |
| 981 | ** <li>[[SQLITE_FCNTL_WIN32_GET_HANDLE]] |
| 982 | ** The [SQLITE_FCNTL_WIN32_GET_HANDLE] opcode can be used to obtain the |
| 983 | ** underlying native file handle associated with a file handle. This file |
| 984 | ** control interprets its argument as a pointer to a native file handle and |
| 985 | ** writes the resulting value there. |
| 986 | ** |
| 987 | ** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]] |
| 988 | ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This |
| 989 | ** opcode causes the xFileControl method to swap the file handle with the one |
| 990 | ** pointed to by the pArg argument. This capability is used during testing |
| @@ -1026,10 +1032,12 @@ | |
| 1032 | #define SQLITE_FCNTL_WAL_BLOCK 24 |
| 1033 | #define SQLITE_FCNTL_ZIPVFS 25 |
| 1034 | #define SQLITE_FCNTL_RBU 26 |
| 1035 | #define SQLITE_FCNTL_VFS_POINTER 27 |
| 1036 | #define SQLITE_FCNTL_JOURNAL_POINTER 28 |
| 1037 | #define SQLITE_FCNTL_WIN32_GET_HANDLE 29 |
| 1038 | #define SQLITE_FCNTL_PDB 30 |
| 1039 | |
| 1040 | /* deprecated names */ |
| 1041 | #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE |
| 1042 | #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE |
| 1043 | #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| @@ -1978,18 +1986,31 @@ | |
| 1986 | ** does not make a copy of the new main schema name string, so the application |
| 1987 | ** must ensure that the argument passed into this DBCONFIG option is unchanged |
| 1988 | ** until after the database connection closes. |
| 1989 | ** </dd> |
| 1990 | ** |
| 1991 | ** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt> |
| 1992 | ** <dd> Usually, when a database in wal mode is closed or detached from a |
| 1993 | ** database handle, SQLite checks if this will mean that there are now no |
| 1994 | ** connections at all to the database. If so, it performs a checkpoint |
| 1995 | ** operation before closing the connection. This option may be used to |
| 1996 | ** override this behaviour. The first parameter passed to this operation |
| 1997 | ** is an integer - non-zero to disable checkpoints-on-close, or zero (the |
| 1998 | ** default) to enable them. The second parameter is a pointer to an integer |
| 1999 | ** into which is written 0 or 1 to indicate whether checkpoints-on-close |
| 2000 | ** have been disabled - 0 if they are not disabled, 1 if they are. |
| 2001 | ** </dd> |
| 2002 | ** |
| 2003 | ** </dl> |
| 2004 | */ |
| 2005 | #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ |
| 2006 | #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ |
| 2007 | #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ |
| 2008 | #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ |
| 2009 | #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ |
| 2010 | #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ |
| 2011 | #define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */ |
| 2012 | |
| 2013 | |
| 2014 | /* |
| 2015 | ** CAPI3REF: Enable Or Disable Extended Result Codes |
| 2016 | ** METHOD: sqlite3 |
| 2017 |
+42
-31
| --- src/stash.c | ||
| +++ src/stash.c | ||
| @@ -25,11 +25,11 @@ | ||
| 25 | 25 | ** SQL code to implement the tables needed by the stash. |
| 26 | 26 | */ |
| 27 | 27 | static const char zStashInit[] = |
| 28 | 28 | @ CREATE TABLE IF NOT EXISTS localdb.stash( |
| 29 | 29 | @ stashid INTEGER PRIMARY KEY, -- Unique stash identifier |
| 30 | -@ vid INTEGER, -- The baseline check-out for this stash | |
| 30 | +@ vid INTEGER, -- The baseline checkout for this stash | |
| 31 | 31 | @ comment TEXT, -- Comment for this stash. Or NULL |
| 32 | 32 | @ ctime TIMESTAMP -- When the stash was created |
| 33 | 33 | @ ); |
| 34 | 34 | @ CREATE TABLE IF NOT EXISTS localdb.stashfile( |
| 35 | 35 | @ stashid INTEGER REFERENCES stash, -- Stash that contains this file |
| @@ -39,11 +39,11 @@ | ||
| 39 | 39 | @ isExec BOOLEAN, -- True if file is executable |
| 40 | 40 | @ isLink BOOLEAN, -- True if file is a symlink |
| 41 | 41 | @ origname TEXT, -- Original filename |
| 42 | 42 | @ newname TEXT, -- New name for file at next check-in |
| 43 | 43 | @ delta BLOB, -- Delta from baseline. Content if rid=0 |
| 44 | -@ PRIMARY KEY(origname, stashid) | |
| 44 | +@ PRIMARY KEY(newname, stashid) | |
| 45 | 45 | @ ); |
| 46 | 46 | @ INSERT OR IGNORE INTO vvar(name, value) VALUES('stash-next', 1); |
| 47 | 47 | ; |
| 48 | 48 | |
| 49 | 49 | /* |
| @@ -196,11 +196,11 @@ | ||
| 196 | 196 | } |
| 197 | 197 | return stashid; |
| 198 | 198 | } |
| 199 | 199 | |
| 200 | 200 | /* |
| 201 | -** Apply a stash to the current check-out. | |
| 201 | +** Apply a stash to the current checkout. | |
| 202 | 202 | */ |
| 203 | 203 | static void stash_apply(int stashid, int nConflict){ |
| 204 | 204 | int vid; |
| 205 | 205 | Stmt q; |
| 206 | 206 | db_prepare(&q, |
| @@ -278,10 +278,15 @@ | ||
| 278 | 278 | } |
| 279 | 279 | blob_reset(&delta); |
| 280 | 280 | if( fossil_strcmp(zOrig,zNew)!=0 ){ |
| 281 | 281 | undo_save(zOrig); |
| 282 | 282 | file_delete(zOPath); |
| 283 | + db_multi_exec( | |
| 284 | + "UPDATE vfile SET pathname='%q', origname='%q'" | |
| 285 | + " WHERE pathname='%q' %s AND vid=%d", | |
| 286 | + zNew, zOrig, zOrig, filename_collation(), vid | |
| 287 | + ); | |
| 283 | 288 | } |
| 284 | 289 | } |
| 285 | 290 | stash_add_files_in_sfile(vid); |
| 286 | 291 | db_finalize(&q); |
| 287 | 292 | if( nConflict ){ |
| @@ -393,18 +398,18 @@ | ||
| 393 | 398 | ** return that number. Or throw a fatal error if it is not a valid |
| 394 | 399 | ** stash number. If it is NULL, return the most recent stash or |
| 395 | 400 | ** throw an error if the stash is empty. |
| 396 | 401 | */ |
| 397 | 402 | static int stash_get_id(const char *zStashId){ |
| 398 | - int stashid = 0; | |
| 403 | + int stashid; | |
| 399 | 404 | if( zStashId==0 ){ |
| 400 | 405 | stashid = db_int(0, "SELECT max(stashid) FROM stash"); |
| 401 | 406 | if( stashid==0 ) fossil_fatal("empty stash"); |
| 402 | 407 | }else{ |
| 403 | 408 | stashid = atoi(zStashId); |
| 404 | 409 | if( !db_exists("SELECT 1 FROM stash WHERE stashid=%d", stashid) ){ |
| 405 | - fossil_fatal("no such stash: %d\n", stashid); | |
| 410 | + fossil_fatal("no such stash: %s", zStashId); | |
| 406 | 411 | } |
| 407 | 412 | } |
| 408 | 413 | return stashid; |
| 409 | 414 | } |
| 410 | 415 | |
| @@ -420,70 +425,83 @@ | ||
| 420 | 425 | ** Save the current changes in the working tree as a new stash. |
| 421 | 426 | ** Then revert the changes back to the last check-in. If FILES |
| 422 | 427 | ** are listed, then only stash and revert the named files. The |
| 423 | 428 | ** "save" verb can be omitted if and only if there are no other |
| 424 | 429 | ** arguments. The "snapshot" verb works the same as "save" but |
| 425 | -** omits the revert, keeping the check-out unchanged. | |
| 430 | +** omits the revert, keeping the checkout unchanged. | |
| 426 | 431 | ** |
| 427 | -** fossil stash list ?-v|--verbose? | |
| 428 | -** fossil stash ls ?-v|--verbose? | |
| 432 | +** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>? | |
| 429 | 433 | ** |
| 430 | 434 | ** List all changes sets currently stashed. Show information about |
| 431 | 435 | ** individual files in each changeset if -v or --verbose is used. |
| 432 | 436 | ** |
| 433 | -** fossil stash show|cat ?STASHID? ?DIFF-FLAGS? | |
| 437 | +** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS? | |
| 434 | 438 | ** |
| 435 | -** Show the content of a stash | |
| 439 | +** Show the contents of a stash. | |
| 436 | 440 | ** |
| 437 | 441 | ** fossil stash pop |
| 438 | 442 | ** fossil stash apply ?STASHID? |
| 439 | 443 | ** |
| 440 | 444 | ** Apply STASHID or the most recently create stash to the current |
| 441 | -** working check-out. The "pop" command deletes that changeset from | |
| 445 | +** working checkout. The "pop" command deletes that changeset from | |
| 442 | 446 | ** the stash after applying it but the "apply" command retains the |
| 443 | 447 | ** changeset. |
| 444 | 448 | ** |
| 445 | 449 | ** fossil stash goto ?STASHID? |
| 446 | 450 | ** |
| 447 | 451 | ** Update to the baseline checkout for STASHID then apply the |
| 448 | 452 | ** changes of STASHID. Keep STASHID so that it can be reused |
| 449 | 453 | ** This command is undoable. |
| 450 | 454 | ** |
| 451 | -** fossil stash drop ?STASHID? ?-a|--all? | |
| 452 | -** fossil stash rm ?STASHID? ?-a|--all? | |
| 455 | +** fossil stash drop|rm ?STASHID? ?-a|--all? | |
| 453 | 456 | ** |
| 454 | 457 | ** Forget everything about STASHID. Forget the whole stash if the |
| 455 | 458 | ** -a|--all flag is used. Individual drops are undoable but -a|--all |
| 456 | 459 | ** is not. |
| 457 | 460 | ** |
| 458 | -** fossil stash diff ?STASHID? | |
| 459 | -** fossil stash gdiff ?STASHID? | |
| 461 | +** fossil stash diff ?STASHID? ?DIFF-OPTIONS? | |
| 462 | +** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS? | |
| 460 | 463 | ** |
| 461 | 464 | ** Show diffs of the current working directory and what that |
| 462 | 465 | ** directory would be if STASHID were applied. |
| 463 | 466 | ** |
| 464 | 467 | ** SUMMARY: |
| 465 | 468 | ** fossil stash |
| 466 | 469 | ** fossil stash save ?-m|--comment COMMENT? ?FILES...? |
| 467 | 470 | ** fossil stash snapshot ?-m|--comment COMMENT? ?FILES...? |
| 468 | -** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>? | |
| 471 | +** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>? | |
| 469 | 472 | ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS? |
| 470 | 473 | ** fossil stash pop |
| 471 | -** fossil stash apply ?STASHID? | |
| 472 | -** fossil stash goto ?STASHID? | |
| 473 | -** fossil stash rm|drop ?STASHID? ?-a|--all? | |
| 474 | -** fossil stash [g]diff ?STASHID? ?DIFF-OPTIONS? | |
| 474 | +** fossil stash apply|goto ?STASHID? | |
| 475 | +** fossil stash drop|rm ?STASHID? ?-a|--all? | |
| 476 | +** fossil stash diff ?STASHID? ?DIFF-OPTIONS? | |
| 477 | +** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS? | |
| 475 | 478 | */ |
| 476 | 479 | void stash_cmd(void){ |
| 477 | 480 | const char *zCmd; |
| 478 | 481 | int nCmd; |
| 479 | 482 | int stashid = 0; |
| 483 | + int rc; | |
| 480 | 484 | undo_capture_command_line(); |
| 481 | 485 | db_must_be_within_tree(); |
| 482 | 486 | db_open_config(0, 0); |
| 483 | 487 | db_begin_transaction(); |
| 484 | 488 | db_multi_exec(zStashInit /*works-like:""*/); |
| 489 | + rc = db_exists("SELECT 1 FROM sqlite_master" | |
| 490 | + " WHERE name='stashfile'" | |
| 491 | + " AND sql GLOB '* PRIMARY KEY(origname, stashid)*'"); | |
| 492 | + if( rc!=0 ){ | |
| 493 | + db_multi_exec( | |
| 494 | + "CREATE TABLE localdb.stashfile_tmp AS SELECT * FROM stashfile;" | |
| 495 | + "DROP TABLE stashfile;" | |
| 496 | + ); | |
| 497 | + db_multi_exec(zStashInit /*works-like:""*/); | |
| 498 | + db_multi_exec( | |
| 499 | + "INSERT INTO stashfile SELECT * FROM stashfile_tmp;" | |
| 500 | + "DROP TABLE stashfile_tmp;" | |
| 501 | + ); | |
| 502 | + } | |
| 485 | 503 | if( g.argc<=2 ){ |
| 486 | 504 | zCmd = "save"; |
| 487 | 505 | }else{ |
| 488 | 506 | zCmd = g.argv[2]; |
| 489 | 507 | } |
| @@ -641,37 +659,30 @@ | ||
| 641 | 659 | || memcmp(zCmd, "cat", nCmd)==0 |
| 642 | 660 | ){ |
| 643 | 661 | const char *zDiffCmd = 0; |
| 644 | 662 | const char *zBinGlob = 0; |
| 645 | 663 | int fIncludeBinary = 0; |
| 664 | + int fBaseline = zCmd[0]=='s' || zCmd[0]=='c'; | |
| 646 | 665 | u64 diffFlags; |
| 647 | 666 | |
| 648 | 667 | if( find_option("tk",0,0)!=0 ){ |
| 649 | 668 | db_close(0); |
| 650 | - switch (zCmd[0]) { | |
| 651 | - case 's': | |
| 652 | - case 'c': | |
| 653 | - diff_tk("stash show", 3); | |
| 654 | - break; | |
| 655 | - | |
| 656 | - default: | |
| 657 | - diff_tk("stash diff", 3); | |
| 658 | - } | |
| 669 | + diff_tk(fBaseline ? "stash show" : "stash diff", 3); | |
| 659 | 670 | return; |
| 660 | 671 | } |
| 661 | 672 | if( find_option("internal","i",0)==0 ){ |
| 662 | 673 | zDiffCmd = diff_command_external(memcmp(zCmd, "gdiff", nCmd)==0); |
| 663 | 674 | } |
| 664 | 675 | diffFlags = diff_options(); |
| 665 | 676 | if( find_option("verbose","v",0)!=0 ) diffFlags |= DIFF_VERBOSE; |
| 666 | - if( g.argc>4 ) usage(mprintf("%s STASHID", zCmd)); | |
| 677 | + if( g.argc>4 ) usage(mprintf("%s ?STASHID? ?DIFF-OPTIONS?", zCmd)); | |
| 667 | 678 | if( zDiffCmd ){ |
| 668 | 679 | zBinGlob = diff_get_binary_glob(); |
| 669 | 680 | fIncludeBinary = diff_include_binary_files(); |
| 670 | 681 | } |
| 671 | 682 | stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0); |
| 672 | - stash_diff(stashid, zDiffCmd, zBinGlob, zCmd[0]=='s', fIncludeBinary, | |
| 683 | + stash_diff(stashid, zDiffCmd, zBinGlob, fBaseline, fIncludeBinary, | |
| 673 | 684 | diffFlags); |
| 674 | 685 | }else |
| 675 | 686 | if( memcmp(zCmd, "help", nCmd)==0 ){ |
| 676 | 687 | g.argv[1] = "help"; |
| 677 | 688 | g.argv[2] = "stash"; |
| 678 | 689 |
| --- src/stash.c | |
| +++ src/stash.c | |
| @@ -25,11 +25,11 @@ | |
| 25 | ** SQL code to implement the tables needed by the stash. |
| 26 | */ |
| 27 | static const char zStashInit[] = |
| 28 | @ CREATE TABLE IF NOT EXISTS localdb.stash( |
| 29 | @ stashid INTEGER PRIMARY KEY, -- Unique stash identifier |
| 30 | @ vid INTEGER, -- The baseline check-out for this stash |
| 31 | @ comment TEXT, -- Comment for this stash. Or NULL |
| 32 | @ ctime TIMESTAMP -- When the stash was created |
| 33 | @ ); |
| 34 | @ CREATE TABLE IF NOT EXISTS localdb.stashfile( |
| 35 | @ stashid INTEGER REFERENCES stash, -- Stash that contains this file |
| @@ -39,11 +39,11 @@ | |
| 39 | @ isExec BOOLEAN, -- True if file is executable |
| 40 | @ isLink BOOLEAN, -- True if file is a symlink |
| 41 | @ origname TEXT, -- Original filename |
| 42 | @ newname TEXT, -- New name for file at next check-in |
| 43 | @ delta BLOB, -- Delta from baseline. Content if rid=0 |
| 44 | @ PRIMARY KEY(origname, stashid) |
| 45 | @ ); |
| 46 | @ INSERT OR IGNORE INTO vvar(name, value) VALUES('stash-next', 1); |
| 47 | ; |
| 48 | |
| 49 | /* |
| @@ -196,11 +196,11 @@ | |
| 196 | } |
| 197 | return stashid; |
| 198 | } |
| 199 | |
| 200 | /* |
| 201 | ** Apply a stash to the current check-out. |
| 202 | */ |
| 203 | static void stash_apply(int stashid, int nConflict){ |
| 204 | int vid; |
| 205 | Stmt q; |
| 206 | db_prepare(&q, |
| @@ -278,10 +278,15 @@ | |
| 278 | } |
| 279 | blob_reset(&delta); |
| 280 | if( fossil_strcmp(zOrig,zNew)!=0 ){ |
| 281 | undo_save(zOrig); |
| 282 | file_delete(zOPath); |
| 283 | } |
| 284 | } |
| 285 | stash_add_files_in_sfile(vid); |
| 286 | db_finalize(&q); |
| 287 | if( nConflict ){ |
| @@ -393,18 +398,18 @@ | |
| 393 | ** return that number. Or throw a fatal error if it is not a valid |
| 394 | ** stash number. If it is NULL, return the most recent stash or |
| 395 | ** throw an error if the stash is empty. |
| 396 | */ |
| 397 | static int stash_get_id(const char *zStashId){ |
| 398 | int stashid = 0; |
| 399 | if( zStashId==0 ){ |
| 400 | stashid = db_int(0, "SELECT max(stashid) FROM stash"); |
| 401 | if( stashid==0 ) fossil_fatal("empty stash"); |
| 402 | }else{ |
| 403 | stashid = atoi(zStashId); |
| 404 | if( !db_exists("SELECT 1 FROM stash WHERE stashid=%d", stashid) ){ |
| 405 | fossil_fatal("no such stash: %d\n", stashid); |
| 406 | } |
| 407 | } |
| 408 | return stashid; |
| 409 | } |
| 410 | |
| @@ -420,70 +425,83 @@ | |
| 420 | ** Save the current changes in the working tree as a new stash. |
| 421 | ** Then revert the changes back to the last check-in. If FILES |
| 422 | ** are listed, then only stash and revert the named files. The |
| 423 | ** "save" verb can be omitted if and only if there are no other |
| 424 | ** arguments. The "snapshot" verb works the same as "save" but |
| 425 | ** omits the revert, keeping the check-out unchanged. |
| 426 | ** |
| 427 | ** fossil stash list ?-v|--verbose? |
| 428 | ** fossil stash ls ?-v|--verbose? |
| 429 | ** |
| 430 | ** List all changes sets currently stashed. Show information about |
| 431 | ** individual files in each changeset if -v or --verbose is used. |
| 432 | ** |
| 433 | ** fossil stash show|cat ?STASHID? ?DIFF-FLAGS? |
| 434 | ** |
| 435 | ** Show the content of a stash |
| 436 | ** |
| 437 | ** fossil stash pop |
| 438 | ** fossil stash apply ?STASHID? |
| 439 | ** |
| 440 | ** Apply STASHID or the most recently create stash to the current |
| 441 | ** working check-out. The "pop" command deletes that changeset from |
| 442 | ** the stash after applying it but the "apply" command retains the |
| 443 | ** changeset. |
| 444 | ** |
| 445 | ** fossil stash goto ?STASHID? |
| 446 | ** |
| 447 | ** Update to the baseline checkout for STASHID then apply the |
| 448 | ** changes of STASHID. Keep STASHID so that it can be reused |
| 449 | ** This command is undoable. |
| 450 | ** |
| 451 | ** fossil stash drop ?STASHID? ?-a|--all? |
| 452 | ** fossil stash rm ?STASHID? ?-a|--all? |
| 453 | ** |
| 454 | ** Forget everything about STASHID. Forget the whole stash if the |
| 455 | ** -a|--all flag is used. Individual drops are undoable but -a|--all |
| 456 | ** is not. |
| 457 | ** |
| 458 | ** fossil stash diff ?STASHID? |
| 459 | ** fossil stash gdiff ?STASHID? |
| 460 | ** |
| 461 | ** Show diffs of the current working directory and what that |
| 462 | ** directory would be if STASHID were applied. |
| 463 | ** |
| 464 | ** SUMMARY: |
| 465 | ** fossil stash |
| 466 | ** fossil stash save ?-m|--comment COMMENT? ?FILES...? |
| 467 | ** fossil stash snapshot ?-m|--comment COMMENT? ?FILES...? |
| 468 | ** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>? |
| 469 | ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS? |
| 470 | ** fossil stash pop |
| 471 | ** fossil stash apply ?STASHID? |
| 472 | ** fossil stash goto ?STASHID? |
| 473 | ** fossil stash rm|drop ?STASHID? ?-a|--all? |
| 474 | ** fossil stash [g]diff ?STASHID? ?DIFF-OPTIONS? |
| 475 | */ |
| 476 | void stash_cmd(void){ |
| 477 | const char *zCmd; |
| 478 | int nCmd; |
| 479 | int stashid = 0; |
| 480 | undo_capture_command_line(); |
| 481 | db_must_be_within_tree(); |
| 482 | db_open_config(0, 0); |
| 483 | db_begin_transaction(); |
| 484 | db_multi_exec(zStashInit /*works-like:""*/); |
| 485 | if( g.argc<=2 ){ |
| 486 | zCmd = "save"; |
| 487 | }else{ |
| 488 | zCmd = g.argv[2]; |
| 489 | } |
| @@ -641,37 +659,30 @@ | |
| 641 | || memcmp(zCmd, "cat", nCmd)==0 |
| 642 | ){ |
| 643 | const char *zDiffCmd = 0; |
| 644 | const char *zBinGlob = 0; |
| 645 | int fIncludeBinary = 0; |
| 646 | u64 diffFlags; |
| 647 | |
| 648 | if( find_option("tk",0,0)!=0 ){ |
| 649 | db_close(0); |
| 650 | switch (zCmd[0]) { |
| 651 | case 's': |
| 652 | case 'c': |
| 653 | diff_tk("stash show", 3); |
| 654 | break; |
| 655 | |
| 656 | default: |
| 657 | diff_tk("stash diff", 3); |
| 658 | } |
| 659 | return; |
| 660 | } |
| 661 | if( find_option("internal","i",0)==0 ){ |
| 662 | zDiffCmd = diff_command_external(memcmp(zCmd, "gdiff", nCmd)==0); |
| 663 | } |
| 664 | diffFlags = diff_options(); |
| 665 | if( find_option("verbose","v",0)!=0 ) diffFlags |= DIFF_VERBOSE; |
| 666 | if( g.argc>4 ) usage(mprintf("%s STASHID", zCmd)); |
| 667 | if( zDiffCmd ){ |
| 668 | zBinGlob = diff_get_binary_glob(); |
| 669 | fIncludeBinary = diff_include_binary_files(); |
| 670 | } |
| 671 | stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0); |
| 672 | stash_diff(stashid, zDiffCmd, zBinGlob, zCmd[0]=='s', fIncludeBinary, |
| 673 | diffFlags); |
| 674 | }else |
| 675 | if( memcmp(zCmd, "help", nCmd)==0 ){ |
| 676 | g.argv[1] = "help"; |
| 677 | g.argv[2] = "stash"; |
| 678 |
| --- src/stash.c | |
| +++ src/stash.c | |
| @@ -25,11 +25,11 @@ | |
| 25 | ** SQL code to implement the tables needed by the stash. |
| 26 | */ |
| 27 | static const char zStashInit[] = |
| 28 | @ CREATE TABLE IF NOT EXISTS localdb.stash( |
| 29 | @ stashid INTEGER PRIMARY KEY, -- Unique stash identifier |
| 30 | @ vid INTEGER, -- The baseline checkout for this stash |
| 31 | @ comment TEXT, -- Comment for this stash. Or NULL |
| 32 | @ ctime TIMESTAMP -- When the stash was created |
| 33 | @ ); |
| 34 | @ CREATE TABLE IF NOT EXISTS localdb.stashfile( |
| 35 | @ stashid INTEGER REFERENCES stash, -- Stash that contains this file |
| @@ -39,11 +39,11 @@ | |
| 39 | @ isExec BOOLEAN, -- True if file is executable |
| 40 | @ isLink BOOLEAN, -- True if file is a symlink |
| 41 | @ origname TEXT, -- Original filename |
| 42 | @ newname TEXT, -- New name for file at next check-in |
| 43 | @ delta BLOB, -- Delta from baseline. Content if rid=0 |
| 44 | @ PRIMARY KEY(newname, stashid) |
| 45 | @ ); |
| 46 | @ INSERT OR IGNORE INTO vvar(name, value) VALUES('stash-next', 1); |
| 47 | ; |
| 48 | |
| 49 | /* |
| @@ -196,11 +196,11 @@ | |
| 196 | } |
| 197 | return stashid; |
| 198 | } |
| 199 | |
| 200 | /* |
| 201 | ** Apply a stash to the current checkout. |
| 202 | */ |
| 203 | static void stash_apply(int stashid, int nConflict){ |
| 204 | int vid; |
| 205 | Stmt q; |
| 206 | db_prepare(&q, |
| @@ -278,10 +278,15 @@ | |
| 278 | } |
| 279 | blob_reset(&delta); |
| 280 | if( fossil_strcmp(zOrig,zNew)!=0 ){ |
| 281 | undo_save(zOrig); |
| 282 | file_delete(zOPath); |
| 283 | db_multi_exec( |
| 284 | "UPDATE vfile SET pathname='%q', origname='%q'" |
| 285 | " WHERE pathname='%q' %s AND vid=%d", |
| 286 | zNew, zOrig, zOrig, filename_collation(), vid |
| 287 | ); |
| 288 | } |
| 289 | } |
| 290 | stash_add_files_in_sfile(vid); |
| 291 | db_finalize(&q); |
| 292 | if( nConflict ){ |
| @@ -393,18 +398,18 @@ | |
| 398 | ** return that number. Or throw a fatal error if it is not a valid |
| 399 | ** stash number. If it is NULL, return the most recent stash or |
| 400 | ** throw an error if the stash is empty. |
| 401 | */ |
| 402 | static int stash_get_id(const char *zStashId){ |
| 403 | int stashid; |
| 404 | if( zStashId==0 ){ |
| 405 | stashid = db_int(0, "SELECT max(stashid) FROM stash"); |
| 406 | if( stashid==0 ) fossil_fatal("empty stash"); |
| 407 | }else{ |
| 408 | stashid = atoi(zStashId); |
| 409 | if( !db_exists("SELECT 1 FROM stash WHERE stashid=%d", stashid) ){ |
| 410 | fossil_fatal("no such stash: %s", zStashId); |
| 411 | } |
| 412 | } |
| 413 | return stashid; |
| 414 | } |
| 415 | |
| @@ -420,70 +425,83 @@ | |
| 425 | ** Save the current changes in the working tree as a new stash. |
| 426 | ** Then revert the changes back to the last check-in. If FILES |
| 427 | ** are listed, then only stash and revert the named files. The |
| 428 | ** "save" verb can be omitted if and only if there are no other |
| 429 | ** arguments. The "snapshot" verb works the same as "save" but |
| 430 | ** omits the revert, keeping the checkout unchanged. |
| 431 | ** |
| 432 | ** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>? |
| 433 | ** |
| 434 | ** List all changes sets currently stashed. Show information about |
| 435 | ** individual files in each changeset if -v or --verbose is used. |
| 436 | ** |
| 437 | ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS? |
| 438 | ** |
| 439 | ** Show the contents of a stash. |
| 440 | ** |
| 441 | ** fossil stash pop |
| 442 | ** fossil stash apply ?STASHID? |
| 443 | ** |
| 444 | ** Apply STASHID or the most recently create stash to the current |
| 445 | ** working checkout. The "pop" command deletes that changeset from |
| 446 | ** the stash after applying it but the "apply" command retains the |
| 447 | ** changeset. |
| 448 | ** |
| 449 | ** fossil stash goto ?STASHID? |
| 450 | ** |
| 451 | ** Update to the baseline checkout for STASHID then apply the |
| 452 | ** changes of STASHID. Keep STASHID so that it can be reused |
| 453 | ** This command is undoable. |
| 454 | ** |
| 455 | ** fossil stash drop|rm ?STASHID? ?-a|--all? |
| 456 | ** |
| 457 | ** Forget everything about STASHID. Forget the whole stash if the |
| 458 | ** -a|--all flag is used. Individual drops are undoable but -a|--all |
| 459 | ** is not. |
| 460 | ** |
| 461 | ** fossil stash diff ?STASHID? ?DIFF-OPTIONS? |
| 462 | ** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS? |
| 463 | ** |
| 464 | ** Show diffs of the current working directory and what that |
| 465 | ** directory would be if STASHID were applied. |
| 466 | ** |
| 467 | ** SUMMARY: |
| 468 | ** fossil stash |
| 469 | ** fossil stash save ?-m|--comment COMMENT? ?FILES...? |
| 470 | ** fossil stash snapshot ?-m|--comment COMMENT? ?FILES...? |
| 471 | ** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>? |
| 472 | ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS? |
| 473 | ** fossil stash pop |
| 474 | ** fossil stash apply|goto ?STASHID? |
| 475 | ** fossil stash drop|rm ?STASHID? ?-a|--all? |
| 476 | ** fossil stash diff ?STASHID? ?DIFF-OPTIONS? |
| 477 | ** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS? |
| 478 | */ |
| 479 | void stash_cmd(void){ |
| 480 | const char *zCmd; |
| 481 | int nCmd; |
| 482 | int stashid = 0; |
| 483 | int rc; |
| 484 | undo_capture_command_line(); |
| 485 | db_must_be_within_tree(); |
| 486 | db_open_config(0, 0); |
| 487 | db_begin_transaction(); |
| 488 | db_multi_exec(zStashInit /*works-like:""*/); |
| 489 | rc = db_exists("SELECT 1 FROM sqlite_master" |
| 490 | " WHERE name='stashfile'" |
| 491 | " AND sql GLOB '* PRIMARY KEY(origname, stashid)*'"); |
| 492 | if( rc!=0 ){ |
| 493 | db_multi_exec( |
| 494 | "CREATE TABLE localdb.stashfile_tmp AS SELECT * FROM stashfile;" |
| 495 | "DROP TABLE stashfile;" |
| 496 | ); |
| 497 | db_multi_exec(zStashInit /*works-like:""*/); |
| 498 | db_multi_exec( |
| 499 | "INSERT INTO stashfile SELECT * FROM stashfile_tmp;" |
| 500 | "DROP TABLE stashfile_tmp;" |
| 501 | ); |
| 502 | } |
| 503 | if( g.argc<=2 ){ |
| 504 | zCmd = "save"; |
| 505 | }else{ |
| 506 | zCmd = g.argv[2]; |
| 507 | } |
| @@ -641,37 +659,30 @@ | |
| 659 | || memcmp(zCmd, "cat", nCmd)==0 |
| 660 | ){ |
| 661 | const char *zDiffCmd = 0; |
| 662 | const char *zBinGlob = 0; |
| 663 | int fIncludeBinary = 0; |
| 664 | int fBaseline = zCmd[0]=='s' || zCmd[0]=='c'; |
| 665 | u64 diffFlags; |
| 666 | |
| 667 | if( find_option("tk",0,0)!=0 ){ |
| 668 | db_close(0); |
| 669 | diff_tk(fBaseline ? "stash show" : "stash diff", 3); |
| 670 | return; |
| 671 | } |
| 672 | if( find_option("internal","i",0)==0 ){ |
| 673 | zDiffCmd = diff_command_external(memcmp(zCmd, "gdiff", nCmd)==0); |
| 674 | } |
| 675 | diffFlags = diff_options(); |
| 676 | if( find_option("verbose","v",0)!=0 ) diffFlags |= DIFF_VERBOSE; |
| 677 | if( g.argc>4 ) usage(mprintf("%s ?STASHID? ?DIFF-OPTIONS?", zCmd)); |
| 678 | if( zDiffCmd ){ |
| 679 | zBinGlob = diff_get_binary_glob(); |
| 680 | fIncludeBinary = diff_include_binary_files(); |
| 681 | } |
| 682 | stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0); |
| 683 | stash_diff(stashid, zDiffCmd, zBinGlob, fBaseline, fIncludeBinary, |
| 684 | diffFlags); |
| 685 | }else |
| 686 | if( memcmp(zCmd, "help", nCmd)==0 ){ |
| 687 | g.argv[1] = "help"; |
| 688 | g.argv[2] = "stash"; |
| 689 |
+14
-14
| --- src/stat.c | ||
| +++ src/stat.c | ||
| @@ -71,21 +71,21 @@ | ||
| 71 | 71 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 72 | 72 | brief = P("brief")!=0; |
| 73 | 73 | style_header("Repository Statistics"); |
| 74 | 74 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 75 | 75 | if( g.perm.Admin ){ |
| 76 | - style_submenu_element("URLs", "URLs and Checkouts", "urllist"); | |
| 77 | - style_submenu_element("Schema", "Repository Schema", "repo_schema"); | |
| 78 | - style_submenu_element("Web-Cache", "Web-Cache Stats", "cachestat"); | |
| 76 | + style_submenu_element("URLs", "urllist"); | |
| 77 | + style_submenu_element("Schema", "repo_schema"); | |
| 78 | + style_submenu_element("Web-Cache", "cachestat"); | |
| 79 | 79 | } |
| 80 | - style_submenu_element("Activity Reports", 0, "reports"); | |
| 81 | - style_submenu_element("SHA1 Collisions", 0, "hash-collisions"); | |
| 80 | + style_submenu_element("Activity Reports", "reports"); | |
| 81 | + style_submenu_element("SHA1 Collisions", "hash-collisions"); | |
| 82 | 82 | if( sqlite3_compileoption_used("ENABLE_DBSTAT_VTAB") ){ |
| 83 | - style_submenu_element("Table Sizes", 0, "repo-tabsize"); | |
| 83 | + style_submenu_element("Table Sizes", "repo-tabsize"); | |
| 84 | 84 | } |
| 85 | 85 | if( g.perm.Admin || g.perm.Setup || db_get_boolean("test_env_enable",0) ){ |
| 86 | - style_submenu_element("Environment", 0, "test_env"); | |
| 86 | + style_submenu_element("Environment", "test_env"); | |
| 87 | 87 | } |
| 88 | 88 | @ <table class="label-value"> |
| 89 | 89 | @ <tr><th>Repository Size:</th><td> |
| 90 | 90 | fsize = file_size(g.zRepositoryName); |
| 91 | 91 | bigSizeName(sizeof(zBuf), zBuf, fsize); |
| @@ -340,12 +340,12 @@ | ||
| 340 | 340 | login_check_credentials(); |
| 341 | 341 | if( !g.perm.Admin ){ login_needed(0); return; } |
| 342 | 342 | |
| 343 | 343 | style_header("URLs and Checkouts"); |
| 344 | 344 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 345 | - style_submenu_element("Stat", "Repository Stats", "stat"); | |
| 346 | - style_submenu_element("Schema", "Repository Schema", "repo_schema"); | |
| 345 | + style_submenu_element("Stat", "stat"); | |
| 346 | + style_submenu_element("Schema", "repo_schema"); | |
| 347 | 347 | @ <div class="section">URLs</div> |
| 348 | 348 | @ <table border="0" width='100%%'> |
| 349 | 349 | db_prepare(&q, "SELECT substr(name,9), datetime(mtime,'unixepoch')" |
| 350 | 350 | " FROM config WHERE name GLOB 'baseurl:*' ORDER BY 2 DESC"); |
| 351 | 351 | cnt = 0; |
| @@ -387,14 +387,14 @@ | ||
| 387 | 387 | login_check_credentials(); |
| 388 | 388 | if( !g.perm.Admin ){ login_needed(0); return; } |
| 389 | 389 | |
| 390 | 390 | style_header("Repository Schema"); |
| 391 | 391 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 392 | - style_submenu_element("Stat", "Repository Stats", "stat"); | |
| 393 | - style_submenu_element("URLs", "URLs and Checkouts", "urllist"); | |
| 392 | + style_submenu_element("Stat", "stat"); | |
| 393 | + style_submenu_element("URLs", "urllist"); | |
| 394 | 394 | if( sqlite3_compileoption_used("ENABLE_DBSTAT_VTAB") ){ |
| 395 | - style_submenu_element("Table Sizes", 0, "repo-tabsize"); | |
| 395 | + style_submenu_element("Table Sizes", "repo-tabsize"); | |
| 396 | 396 | } |
| 397 | 397 | db_prepare(&q, |
| 398 | 398 | "SELECT sql FROM repository.sqlite_master WHERE sql IS NOT NULL"); |
| 399 | 399 | @ <pre> |
| 400 | 400 | while( db_step(&q)==SQLITE_ROW ){ |
| @@ -417,13 +417,13 @@ | ||
| 417 | 417 | |
| 418 | 418 | login_check_credentials(); |
| 419 | 419 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 420 | 420 | style_header("Repository Table Sizes"); |
| 421 | 421 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 422 | - style_submenu_element("Stat", "Repository Stats", "stat"); | |
| 422 | + style_submenu_element("Stat", "stat"); | |
| 423 | 423 | if( g.perm.Admin ){ |
| 424 | - style_submenu_element("Schema", "Repository Schema", "repo_schema"); | |
| 424 | + style_submenu_element("Schema", "repo_schema"); | |
| 425 | 425 | } |
| 426 | 426 | db_multi_exec( |
| 427 | 427 | "CREATE TEMP TABLE trans(name TEXT PRIMARY KEY,tabname TEXT)WITHOUT ROWID;" |
| 428 | 428 | "INSERT INTO trans(name,tabname)" |
| 429 | 429 | " SELECT name, tbl_name FROM repository.sqlite_master;" |
| 430 | 430 |
| --- src/stat.c | |
| +++ src/stat.c | |
| @@ -71,21 +71,21 @@ | |
| 71 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 72 | brief = P("brief")!=0; |
| 73 | style_header("Repository Statistics"); |
| 74 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 75 | if( g.perm.Admin ){ |
| 76 | style_submenu_element("URLs", "URLs and Checkouts", "urllist"); |
| 77 | style_submenu_element("Schema", "Repository Schema", "repo_schema"); |
| 78 | style_submenu_element("Web-Cache", "Web-Cache Stats", "cachestat"); |
| 79 | } |
| 80 | style_submenu_element("Activity Reports", 0, "reports"); |
| 81 | style_submenu_element("SHA1 Collisions", 0, "hash-collisions"); |
| 82 | if( sqlite3_compileoption_used("ENABLE_DBSTAT_VTAB") ){ |
| 83 | style_submenu_element("Table Sizes", 0, "repo-tabsize"); |
| 84 | } |
| 85 | if( g.perm.Admin || g.perm.Setup || db_get_boolean("test_env_enable",0) ){ |
| 86 | style_submenu_element("Environment", 0, "test_env"); |
| 87 | } |
| 88 | @ <table class="label-value"> |
| 89 | @ <tr><th>Repository Size:</th><td> |
| 90 | fsize = file_size(g.zRepositoryName); |
| 91 | bigSizeName(sizeof(zBuf), zBuf, fsize); |
| @@ -340,12 +340,12 @@ | |
| 340 | login_check_credentials(); |
| 341 | if( !g.perm.Admin ){ login_needed(0); return; } |
| 342 | |
| 343 | style_header("URLs and Checkouts"); |
| 344 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 345 | style_submenu_element("Stat", "Repository Stats", "stat"); |
| 346 | style_submenu_element("Schema", "Repository Schema", "repo_schema"); |
| 347 | @ <div class="section">URLs</div> |
| 348 | @ <table border="0" width='100%%'> |
| 349 | db_prepare(&q, "SELECT substr(name,9), datetime(mtime,'unixepoch')" |
| 350 | " FROM config WHERE name GLOB 'baseurl:*' ORDER BY 2 DESC"); |
| 351 | cnt = 0; |
| @@ -387,14 +387,14 @@ | |
| 387 | login_check_credentials(); |
| 388 | if( !g.perm.Admin ){ login_needed(0); return; } |
| 389 | |
| 390 | style_header("Repository Schema"); |
| 391 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 392 | style_submenu_element("Stat", "Repository Stats", "stat"); |
| 393 | style_submenu_element("URLs", "URLs and Checkouts", "urllist"); |
| 394 | if( sqlite3_compileoption_used("ENABLE_DBSTAT_VTAB") ){ |
| 395 | style_submenu_element("Table Sizes", 0, "repo-tabsize"); |
| 396 | } |
| 397 | db_prepare(&q, |
| 398 | "SELECT sql FROM repository.sqlite_master WHERE sql IS NOT NULL"); |
| 399 | @ <pre> |
| 400 | while( db_step(&q)==SQLITE_ROW ){ |
| @@ -417,13 +417,13 @@ | |
| 417 | |
| 418 | login_check_credentials(); |
| 419 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 420 | style_header("Repository Table Sizes"); |
| 421 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 422 | style_submenu_element("Stat", "Repository Stats", "stat"); |
| 423 | if( g.perm.Admin ){ |
| 424 | style_submenu_element("Schema", "Repository Schema", "repo_schema"); |
| 425 | } |
| 426 | db_multi_exec( |
| 427 | "CREATE TEMP TABLE trans(name TEXT PRIMARY KEY,tabname TEXT)WITHOUT ROWID;" |
| 428 | "INSERT INTO trans(name,tabname)" |
| 429 | " SELECT name, tbl_name FROM repository.sqlite_master;" |
| 430 |
| --- src/stat.c | |
| +++ src/stat.c | |
| @@ -71,21 +71,21 @@ | |
| 71 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 72 | brief = P("brief")!=0; |
| 73 | style_header("Repository Statistics"); |
| 74 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 75 | if( g.perm.Admin ){ |
| 76 | style_submenu_element("URLs", "urllist"); |
| 77 | style_submenu_element("Schema", "repo_schema"); |
| 78 | style_submenu_element("Web-Cache", "cachestat"); |
| 79 | } |
| 80 | style_submenu_element("Activity Reports", "reports"); |
| 81 | style_submenu_element("SHA1 Collisions", "hash-collisions"); |
| 82 | if( sqlite3_compileoption_used("ENABLE_DBSTAT_VTAB") ){ |
| 83 | style_submenu_element("Table Sizes", "repo-tabsize"); |
| 84 | } |
| 85 | if( g.perm.Admin || g.perm.Setup || db_get_boolean("test_env_enable",0) ){ |
| 86 | style_submenu_element("Environment", "test_env"); |
| 87 | } |
| 88 | @ <table class="label-value"> |
| 89 | @ <tr><th>Repository Size:</th><td> |
| 90 | fsize = file_size(g.zRepositoryName); |
| 91 | bigSizeName(sizeof(zBuf), zBuf, fsize); |
| @@ -340,12 +340,12 @@ | |
| 340 | login_check_credentials(); |
| 341 | if( !g.perm.Admin ){ login_needed(0); return; } |
| 342 | |
| 343 | style_header("URLs and Checkouts"); |
| 344 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 345 | style_submenu_element("Stat", "stat"); |
| 346 | style_submenu_element("Schema", "repo_schema"); |
| 347 | @ <div class="section">URLs</div> |
| 348 | @ <table border="0" width='100%%'> |
| 349 | db_prepare(&q, "SELECT substr(name,9), datetime(mtime,'unixepoch')" |
| 350 | " FROM config WHERE name GLOB 'baseurl:*' ORDER BY 2 DESC"); |
| 351 | cnt = 0; |
| @@ -387,14 +387,14 @@ | |
| 387 | login_check_credentials(); |
| 388 | if( !g.perm.Admin ){ login_needed(0); return; } |
| 389 | |
| 390 | style_header("Repository Schema"); |
| 391 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 392 | style_submenu_element("Stat", "stat"); |
| 393 | style_submenu_element("URLs", "urllist"); |
| 394 | if( sqlite3_compileoption_used("ENABLE_DBSTAT_VTAB") ){ |
| 395 | style_submenu_element("Table Sizes", "repo-tabsize"); |
| 396 | } |
| 397 | db_prepare(&q, |
| 398 | "SELECT sql FROM repository.sqlite_master WHERE sql IS NOT NULL"); |
| 399 | @ <pre> |
| 400 | while( db_step(&q)==SQLITE_ROW ){ |
| @@ -417,13 +417,13 @@ | |
| 417 | |
| 418 | login_check_credentials(); |
| 419 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 420 | style_header("Repository Table Sizes"); |
| 421 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 422 | style_submenu_element("Stat", "stat"); |
| 423 | if( g.perm.Admin ){ |
| 424 | style_submenu_element("Schema", "repo_schema"); |
| 425 | } |
| 426 | db_multi_exec( |
| 427 | "CREATE TEMP TABLE trans(name TEXT PRIMARY KEY,tabname TEXT)WITHOUT ROWID;" |
| 428 | "INSERT INTO trans(name,tabname)" |
| 429 | " SELECT name, tbl_name FROM repository.sqlite_master;" |
| 430 |
+4
-4
| --- src/statrep.c | ||
| +++ src/statrep.c | ||
| @@ -706,24 +706,24 @@ | ||
| 706 | 706 | if( zUserName && zUserName[0]==0 ) zUserName = 0; |
| 707 | 707 | if( zView==0 ){ |
| 708 | 708 | zView = "byuser"; |
| 709 | 709 | cgi_replace_query_parameter("view","byuser"); |
| 710 | 710 | } |
| 711 | - for(i=0; i<ArraySize(aViewType); i++){ | |
| 711 | + for(i=0; i<count(aViewType); i++){ | |
| 712 | 712 | if( fossil_strcmp(zView, aViewType[i].zVal)==0 ){ |
| 713 | 713 | eType = aViewType[i].eType; |
| 714 | 714 | break; |
| 715 | 715 | } |
| 716 | 716 | } |
| 717 | 717 | if( eType!=RPT_NONE ){ |
| 718 | 718 | int nView = 0; /* Slots used in azView[] */ |
| 719 | - for(i=0; i<ArraySize(aViewType); i++){ | |
| 719 | + for(i=0; i<count(aViewType); i++){ | |
| 720 | 720 | azView[nView++] = aViewType[i].zVal; |
| 721 | 721 | azView[nView++] = aViewType[i].zName; |
| 722 | 722 | } |
| 723 | 723 | if( eType!=RPT_BYFILE ){ |
| 724 | - style_submenu_multichoice("type", ArraySize(azType)/2, azType, 0); | |
| 724 | + style_submenu_multichoice("type", count(azType)/2, azType, 0); | |
| 725 | 725 | } |
| 726 | 726 | style_submenu_multichoice("view", nView/2, azView, 0); |
| 727 | 727 | if( eType!=RPT_BYUSER ){ |
| 728 | 728 | style_submenu_sql("user","User:", |
| 729 | 729 | "SELECT '', 'All Users' UNION ALL " |
| @@ -732,11 +732,11 @@ | ||
| 732 | 732 | " ORDER BY 1 COLLATE nocase) WHERE x!=''", |
| 733 | 733 | eType==RPT_BYFILE ? "WHERE type='ci'" : "" |
| 734 | 734 | ); |
| 735 | 735 | } |
| 736 | 736 | } |
| 737 | - style_submenu_element("Stats", "Stats", "%R/stat"); | |
| 737 | + style_submenu_element("Stats", "%R/stat"); | |
| 738 | 738 | style_header("Activity Reports"); |
| 739 | 739 | switch( eType ){ |
| 740 | 740 | case RPT_BYYEAR: |
| 741 | 741 | stats_report_by_month_year(0, 0, zUserName); |
| 742 | 742 | break; |
| 743 | 743 |
| --- src/statrep.c | |
| +++ src/statrep.c | |
| @@ -706,24 +706,24 @@ | |
| 706 | if( zUserName && zUserName[0]==0 ) zUserName = 0; |
| 707 | if( zView==0 ){ |
| 708 | zView = "byuser"; |
| 709 | cgi_replace_query_parameter("view","byuser"); |
| 710 | } |
| 711 | for(i=0; i<ArraySize(aViewType); i++){ |
| 712 | if( fossil_strcmp(zView, aViewType[i].zVal)==0 ){ |
| 713 | eType = aViewType[i].eType; |
| 714 | break; |
| 715 | } |
| 716 | } |
| 717 | if( eType!=RPT_NONE ){ |
| 718 | int nView = 0; /* Slots used in azView[] */ |
| 719 | for(i=0; i<ArraySize(aViewType); i++){ |
| 720 | azView[nView++] = aViewType[i].zVal; |
| 721 | azView[nView++] = aViewType[i].zName; |
| 722 | } |
| 723 | if( eType!=RPT_BYFILE ){ |
| 724 | style_submenu_multichoice("type", ArraySize(azType)/2, azType, 0); |
| 725 | } |
| 726 | style_submenu_multichoice("view", nView/2, azView, 0); |
| 727 | if( eType!=RPT_BYUSER ){ |
| 728 | style_submenu_sql("user","User:", |
| 729 | "SELECT '', 'All Users' UNION ALL " |
| @@ -732,11 +732,11 @@ | |
| 732 | " ORDER BY 1 COLLATE nocase) WHERE x!=''", |
| 733 | eType==RPT_BYFILE ? "WHERE type='ci'" : "" |
| 734 | ); |
| 735 | } |
| 736 | } |
| 737 | style_submenu_element("Stats", "Stats", "%R/stat"); |
| 738 | style_header("Activity Reports"); |
| 739 | switch( eType ){ |
| 740 | case RPT_BYYEAR: |
| 741 | stats_report_by_month_year(0, 0, zUserName); |
| 742 | break; |
| 743 |
| --- src/statrep.c | |
| +++ src/statrep.c | |
| @@ -706,24 +706,24 @@ | |
| 706 | if( zUserName && zUserName[0]==0 ) zUserName = 0; |
| 707 | if( zView==0 ){ |
| 708 | zView = "byuser"; |
| 709 | cgi_replace_query_parameter("view","byuser"); |
| 710 | } |
| 711 | for(i=0; i<count(aViewType); i++){ |
| 712 | if( fossil_strcmp(zView, aViewType[i].zVal)==0 ){ |
| 713 | eType = aViewType[i].eType; |
| 714 | break; |
| 715 | } |
| 716 | } |
| 717 | if( eType!=RPT_NONE ){ |
| 718 | int nView = 0; /* Slots used in azView[] */ |
| 719 | for(i=0; i<count(aViewType); i++){ |
| 720 | azView[nView++] = aViewType[i].zVal; |
| 721 | azView[nView++] = aViewType[i].zName; |
| 722 | } |
| 723 | if( eType!=RPT_BYFILE ){ |
| 724 | style_submenu_multichoice("type", count(azType)/2, azType, 0); |
| 725 | } |
| 726 | style_submenu_multichoice("view", nView/2, azView, 0); |
| 727 | if( eType!=RPT_BYUSER ){ |
| 728 | style_submenu_sql("user","User:", |
| 729 | "SELECT '', 'All Users' UNION ALL " |
| @@ -732,11 +732,11 @@ | |
| 732 | " ORDER BY 1 COLLATE nocase) WHERE x!=''", |
| 733 | eType==RPT_BYFILE ? "WHERE type='ci'" : "" |
| 734 | ); |
| 735 | } |
| 736 | } |
| 737 | style_submenu_element("Stats", "%R/stat"); |
| 738 | style_header("Activity Reports"); |
| 739 | switch( eType ){ |
| 740 | case RPT_BYYEAR: |
| 741 | stats_report_by_month_year(0, 0, zUserName); |
| 742 | break; |
| 743 |
+93
-82
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -30,19 +30,20 @@ | ||
| 30 | 30 | ** Populate these structure with calls to |
| 31 | 31 | ** |
| 32 | 32 | ** style_submenu_element() |
| 33 | 33 | ** style_submenu_entry() |
| 34 | 34 | ** style_submenu_checkbox() |
| 35 | +** style_submenu_binary() | |
| 35 | 36 | ** style_submenu_multichoice() |
| 37 | +** style_submenu_sql() | |
| 36 | 38 | ** |
| 37 | 39 | ** prior to calling style_footer(). The style_footer() routine |
| 38 | 40 | ** will generate the appropriate HTML text just below the main |
| 39 | 41 | ** menu. |
| 40 | 42 | */ |
| 41 | 43 | static struct Submenu { |
| 42 | 44 | const char *zLabel; /* Button label */ |
| 43 | - const char *zTitle; | |
| 44 | 45 | const char *zLink; /* Jump to this link when button is pressed */ |
| 45 | 46 | } aSubmenu[30]; |
| 46 | 47 | static int nSubmenu = 0; /* Number of buttons */ |
| 47 | 48 | static struct SubmenuCtrl { |
| 48 | 49 | const char *zName; /* Form query parameter */ |
| @@ -52,13 +53,14 @@ | ||
| 52 | 53 | short int iSize; /* Width for FF_ENTRY. Count for FF_MULTI */ |
| 53 | 54 | const char *const *azChoice;/* value/display pairs for FF_MULTI */ |
| 54 | 55 | const char *zFalse; /* FF_BINARY label when false */ |
| 55 | 56 | } aSubmenuCtrl[20]; |
| 56 | 57 | static int nSubmenuCtrl = 0; |
| 57 | -#define FF_ENTRY 1 | |
| 58 | -#define FF_MULTI 2 | |
| 59 | -#define FF_BINARY 3 | |
| 58 | +#define FF_ENTRY 1 | |
| 59 | +#define FF_MULTI 2 | |
| 60 | +#define FF_BINARY 3 | |
| 61 | +#define FF_CHECKBOX 4 | |
| 60 | 62 | |
| 61 | 63 | /* |
| 62 | 64 | ** Remember that the header has been generated. The footer is omitted |
| 63 | 65 | ** if an error occurs before the header. |
| 64 | 66 | */ |
| @@ -230,18 +232,16 @@ | ||
| 230 | 232 | /* |
| 231 | 233 | ** Add a new element to the submenu |
| 232 | 234 | */ |
| 233 | 235 | void style_submenu_element( |
| 234 | 236 | const char *zLabel, |
| 235 | - const char *zTitle, | |
| 236 | 237 | const char *zLink, |
| 237 | 238 | ... |
| 238 | 239 | ){ |
| 239 | 240 | va_list ap; |
| 240 | - assert( nSubmenu < sizeof(aSubmenu)/sizeof(aSubmenu[0]) ); | |
| 241 | + assert( nSubmenu < count(aSubmenu) ); | |
| 241 | 242 | aSubmenu[nSubmenu].zLabel = zLabel; |
| 242 | - aSubmenu[nSubmenu].zTitle = zTitle ? zTitle : zLabel; | |
| 243 | 243 | va_start(ap, zLink); |
| 244 | 244 | aSubmenu[nSubmenu].zLink = vmprintf(zLink, ap); |
| 245 | 245 | va_end(ap); |
| 246 | 246 | nSubmenu++; |
| 247 | 247 | } |
| @@ -249,25 +249,37 @@ | ||
| 249 | 249 | const char *zName, /* Query parameter name */ |
| 250 | 250 | const char *zLabel, /* Label before the entry box */ |
| 251 | 251 | int iSize, /* Size of the entry box */ |
| 252 | 252 | int isDisabled /* True if disabled */ |
| 253 | 253 | ){ |
| 254 | - assert( nSubmenuCtrl < ArraySize(aSubmenuCtrl) ); | |
| 254 | + assert( nSubmenuCtrl < count(aSubmenuCtrl) ); | |
| 255 | 255 | aSubmenuCtrl[nSubmenuCtrl].zName = zName; |
| 256 | 256 | aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel; |
| 257 | 257 | aSubmenuCtrl[nSubmenuCtrl].iSize = iSize; |
| 258 | 258 | aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled; |
| 259 | 259 | aSubmenuCtrl[nSubmenuCtrl].eType = FF_ENTRY; |
| 260 | 260 | nSubmenuCtrl++; |
| 261 | +} | |
| 262 | +void style_submenu_checkbox( | |
| 263 | + const char *zName, /* Query parameter name */ | |
| 264 | + const char *zLabel, /* Label to display after the checkbox */ | |
| 265 | + int isDisabled /* True if disabled */ | |
| 266 | +){ | |
| 267 | + assert( nSubmenuCtrl < count(aSubmenuCtrl) ); | |
| 268 | + aSubmenuCtrl[nSubmenuCtrl].zName = zName; | |
| 269 | + aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel; | |
| 270 | + aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled; | |
| 271 | + aSubmenuCtrl[nSubmenuCtrl].eType = FF_CHECKBOX; | |
| 272 | + nSubmenuCtrl++; | |
| 261 | 273 | } |
| 262 | 274 | void style_submenu_binary( |
| 263 | 275 | const char *zName, /* Query parameter name */ |
| 264 | 276 | const char *zTrue, /* Label to show when parameter is true */ |
| 265 | 277 | const char *zFalse, /* Label to show when the parameter is false */ |
| 266 | 278 | int isDisabled /* True if this control is disabled */ |
| 267 | 279 | ){ |
| 268 | - assert( nSubmenuCtrl < ArraySize(aSubmenuCtrl) ); | |
| 280 | + assert( nSubmenuCtrl < count(aSubmenuCtrl) ); | |
| 269 | 281 | aSubmenuCtrl[nSubmenuCtrl].zName = zName; |
| 270 | 282 | aSubmenuCtrl[nSubmenuCtrl].zLabel = zTrue; |
| 271 | 283 | aSubmenuCtrl[nSubmenuCtrl].zFalse = zFalse; |
| 272 | 284 | aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled; |
| 273 | 285 | aSubmenuCtrl[nSubmenuCtrl].eType = FF_BINARY; |
| @@ -277,11 +289,11 @@ | ||
| 277 | 289 | const char *zName, /* Query parameter name */ |
| 278 | 290 | int nChoice, /* Number of options */ |
| 279 | 291 | const char *const *azChoice,/* value/display pairs. 2*nChoice entries */ |
| 280 | 292 | int isDisabled /* True if this control is disabled */ |
| 281 | 293 | ){ |
| 282 | - assert( nSubmenuCtrl < ArraySize(aSubmenuCtrl) ); | |
| 294 | + assert( nSubmenuCtrl < count(aSubmenuCtrl) ); | |
| 283 | 295 | aSubmenuCtrl[nSubmenuCtrl].zName = zName; |
| 284 | 296 | aSubmenuCtrl[nSubmenuCtrl].iSize = nChoice; |
| 285 | 297 | aSubmenuCtrl[nSubmenuCtrl].azChoice = azChoice; |
| 286 | 298 | aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled; |
| 287 | 299 | aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI; |
| @@ -400,10 +412,11 @@ | ||
| 400 | 412 | |
| 401 | 413 | if( g.thTrace ) Th_Trace("BEGIN_HEADER<br />\n", -1); |
| 402 | 414 | |
| 403 | 415 | /* Generate the header up through the main menu */ |
| 404 | 416 | Th_Store("project_name", db_get("project-name","Unnamed Fossil Project")); |
| 417 | + Th_Store("project_description", db_get("project-description","")); | |
| 405 | 418 | Th_Store("title", zTitle); |
| 406 | 419 | Th_Store("baseurl", g.zBaseURL); |
| 407 | 420 | Th_Store("secureurl", login_wants_https_redirect()? g.zHttpsURL: g.zBaseURL); |
| 408 | 421 | Th_Store("home", g.zTop); |
| 409 | 422 | Th_Store("index_page", db_get("index-page","/home")); |
| @@ -523,74 +536,75 @@ | ||
| 523 | 536 | }else{ |
| 524 | 537 | @ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a> |
| 525 | 538 | } |
| 526 | 539 | } |
| 527 | 540 | } |
| 528 | - if( nSubmenuCtrl>0 ){ | |
| 529 | - for(i=0; i<nSubmenuCtrl; i++){ | |
| 530 | - const char *zQPN = aSubmenuCtrl[i].zName; | |
| 531 | - const char *zDisabled = " disabled"; | |
| 532 | - if( !aSubmenuCtrl[i].isDisabled ){ | |
| 533 | - zDisabled = ""; | |
| 534 | - cgi_tag_query_parameter(zQPN); | |
| 535 | - } | |
| 536 | - switch( aSubmenuCtrl[i].eType ){ | |
| 537 | - case FF_ENTRY: { | |
| 538 | - cgi_printf( | |
| 539 | - "<span class='submenuctrl'>" | |
| 540 | - " %h<input type='text' name='%s' size='%d' maxlength='%d'" | |
| 541 | - " value='%h'%s></span>\n", | |
| 542 | - aSubmenuCtrl[i].zLabel, | |
| 543 | - zQPN, | |
| 544 | - aSubmenuCtrl[i].iSize, aSubmenuCtrl[i].iSize, | |
| 545 | - PD(zQPN,""), | |
| 546 | - zDisabled | |
| 547 | - ); | |
| 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 | - ); | |
| 561 | - for(j=0; j<aSubmenuCtrl[i].iSize*2; j+=2){ | |
| 562 | - const char *zQPV = aSubmenuCtrl[i].azChoice[j]; | |
| 563 | - cgi_printf( | |
| 564 | - "<option value='%h'%s>%h</option>\n", | |
| 565 | - zQPV, | |
| 566 | - fossil_strcmp(zVal,zQPV)==0 ? " selected" : "", | |
| 567 | - aSubmenuCtrl[i].azChoice[j+1] | |
| 568 | - ); | |
| 569 | - } | |
| 570 | - @ </select> | |
| 571 | - break; | |
| 572 | - } | |
| 573 | - case FF_BINARY: { | |
| 574 | - int isTrue = PB(zQPN); | |
| 575 | - cgi_printf( | |
| 576 | - "<select class='submenuctrl' size='1' name='%s'%s " | |
| 577 | - "onchange='gebi(\"f01\").submit();'>\n", | |
| 578 | - zQPN, zDisabled | |
| 579 | - ); | |
| 580 | - cgi_printf( | |
| 581 | - "<option value='1'%s>%h</option>\n", | |
| 582 | - isTrue ? " selected":"", aSubmenuCtrl[i].zLabel | |
| 583 | - ); | |
| 584 | - cgi_printf( | |
| 585 | - "<option value='0'%s>%h</option>\n", | |
| 586 | - (!isTrue) ? " selected":"", aSubmenuCtrl[i].zFalse | |
| 587 | - ); | |
| 588 | - @ </select> | |
| 589 | - break; | |
| 590 | - } | |
| 591 | - } | |
| 541 | + for(i=0; i<nSubmenuCtrl; i++){ | |
| 542 | + const char *zQPN = aSubmenuCtrl[i].zName; | |
| 543 | + const char *zDisabled = " disabled"; | |
| 544 | + if( !aSubmenuCtrl[i].isDisabled ){ | |
| 545 | + zDisabled = ""; | |
| 546 | + cgi_tag_query_parameter(zQPN); | |
| 547 | + } | |
| 548 | + switch( aSubmenuCtrl[i].eType ){ | |
| 549 | + case FF_ENTRY: | |
| 550 | + @ <span class='submenuctrl'>\ | |
| 551 | + @ %h(aSubmenuCtrl[i].zLabel)\ | |
| 552 | + @ <input type='text' name='%s(zQPN)' value='%h(PD(zQPN, ""))' \ | |
| 553 | + if( aSubmenuCtrl[i].iSize<0 ){ | |
| 554 | + @ size='%d(-aSubmenuCtrl[i].iSize)' \ | |
| 555 | + }else if( aSubmenuCtrl[i].iSize>0 ){ | |
| 556 | + @ size='%d(aSubmenuCtrl[i].iSize)' \ | |
| 557 | + @ maxlength='%d(aSubmenuCtrl[i].iSize)' \ | |
| 558 | + } | |
| 559 | + @ onchange='gebi("f01").submit();'%s(zDisabled)></span> | |
| 560 | + break; | |
| 561 | + case FF_MULTI: { | |
| 562 | + int j; | |
| 563 | + const char *zVal = P(zQPN); | |
| 564 | + if( aSubmenuCtrl[i].zLabel ){ | |
| 565 | + @ %h(aSubmenuCtrl[i].zLabel)\ | |
| 566 | + } | |
| 567 | + @ <select class='submenuctrl' size='1' name='%s(zQPN)' \ | |
| 568 | + @ onchange='gebi("f01").submit();'%s(zDisabled)> | |
| 569 | + for(j=0; j<aSubmenuCtrl[i].iSize*2; j+=2){ | |
| 570 | + const char *zQPV = aSubmenuCtrl[i].azChoice[j]; | |
| 571 | + @ <option value='%h(zQPV)'\ | |
| 572 | + if( fossil_strcmp(zVal, zQPV)==0 ){ | |
| 573 | + @ selected\ | |
| 574 | + } | |
| 575 | + @ >%h(aSubmenuCtrl[i].azChoice[j+1])</option> | |
| 576 | + } | |
| 577 | + @ </select> | |
| 578 | + break; | |
| 579 | + } | |
| 580 | + case FF_BINARY: { | |
| 581 | + int isTrue = PB(zQPN); | |
| 582 | + @ <select class='submenuctrl' size='1' name='%s(zQPN)' \ | |
| 583 | + @ onchange='gebi("f01").submit();'%s(zDisabled)> | |
| 584 | + @ <option value='1'\ | |
| 585 | + if( isTrue ){ | |
| 586 | + @ selected\ | |
| 587 | + } | |
| 588 | + @ >%h(aSubmenuCtrl[i].zLabel)</option> | |
| 589 | + @ <option value='0'\ | |
| 590 | + if( !isTrue ){ | |
| 591 | + @ selected\ | |
| 592 | + } | |
| 593 | + @ >%h(aSubmenuCtrl[i].zFalse)</option> | |
| 594 | + @ </select> | |
| 595 | + break; | |
| 596 | + } | |
| 597 | + case FF_CHECKBOX: | |
| 598 | + @ <label class='submenuctrl'>\ | |
| 599 | + @ <input type='checkbox' name='%s(zQPN)' value='1' \ | |
| 600 | + if( PB(zQPN) ){ | |
| 601 | + @ checked \ | |
| 602 | + } | |
| 603 | + @ onchange='gebi("f01").submit();'%s(zDisabled)>\ | |
| 604 | + @ %h(aSubmenuCtrl[i].zLabel)</label> | |
| 605 | + break; | |
| 592 | 606 | } |
| 593 | 607 | } |
| 594 | 608 | @ </div> |
| 595 | 609 | if( nSubmenuCtrl ){ |
| 596 | 610 | cgi_query_parameters_to_hidden(); |
| @@ -703,14 +717,15 @@ | ||
| 703 | 717 | { "td.timelineTableCell", |
| 704 | 718 | "the format for the timeline data cells", |
| 705 | 719 | @ vertical-align: top; |
| 706 | 720 | @ text-align: left; |
| 707 | 721 | }, |
| 708 | - { "tr.timelineCurrent td.timelineTableCell", | |
| 722 | + { "tr.timelineCurrent", | |
| 709 | 723 | "the format for the timeline data cell of the current checkout", |
| 710 | 724 | @ padding: .1em .2em; |
| 711 | 725 | @ border: 1px dashed #446979; |
| 726 | + @ box-shadow: 1px 1px 4px #888; | |
| 712 | 727 | }, |
| 713 | 728 | { "tr.timelineSelected", |
| 714 | 729 | "The row in the timeline table that contains the entry of interest", |
| 715 | 730 | @ padding: .1em .2em; |
| 716 | 731 | @ border: 2px solid lightgray; |
| @@ -1574,17 +1589,13 @@ | ||
| 1574 | 1589 | login_needed(0); |
| 1575 | 1590 | return; |
| 1576 | 1591 | } |
| 1577 | 1592 | for(i=0; i<count(azCgiVars); i++) (void)P(azCgiVars[i]); |
| 1578 | 1593 | style_header("Environment Test"); |
| 1579 | - showAll = atoi(PD("showall","0")); | |
| 1580 | - if( !showAll ){ | |
| 1581 | - style_submenu_element("Show Cookies", 0, "%R/test_env?showall=1"); | |
| 1582 | - }else{ | |
| 1583 | - style_submenu_element("Hide Cookies", 0, "%R/test_env"); | |
| 1584 | - } | |
| 1585 | - style_submenu_element("Stats", 0, "%R/stat"); | |
| 1594 | + showAll = PB("showall"); | |
| 1595 | + style_submenu_checkbox("showall", "Cookies", 0); | |
| 1596 | + style_submenu_element("Stats", "%R/stat"); | |
| 1586 | 1597 | |
| 1587 | 1598 | #if !defined(_WIN32) |
| 1588 | 1599 | @ uid=%d(getuid()), gid=%d(getgid())<br /> |
| 1589 | 1600 | #endif |
| 1590 | 1601 | @ g.zBaseURL = %h(g.zBaseURL)<br /> |
| 1591 | 1602 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -30,19 +30,20 @@ | |
| 30 | ** Populate these structure with calls to |
| 31 | ** |
| 32 | ** style_submenu_element() |
| 33 | ** style_submenu_entry() |
| 34 | ** style_submenu_checkbox() |
| 35 | ** style_submenu_multichoice() |
| 36 | ** |
| 37 | ** prior to calling style_footer(). The style_footer() routine |
| 38 | ** will generate the appropriate HTML text just below the main |
| 39 | ** menu. |
| 40 | */ |
| 41 | static struct Submenu { |
| 42 | const char *zLabel; /* Button label */ |
| 43 | const char *zTitle; |
| 44 | const char *zLink; /* Jump to this link when button is pressed */ |
| 45 | } aSubmenu[30]; |
| 46 | static int nSubmenu = 0; /* Number of buttons */ |
| 47 | static struct SubmenuCtrl { |
| 48 | const char *zName; /* Form query parameter */ |
| @@ -52,13 +53,14 @@ | |
| 52 | short int iSize; /* Width for FF_ENTRY. Count for FF_MULTI */ |
| 53 | const char *const *azChoice;/* value/display pairs for FF_MULTI */ |
| 54 | const char *zFalse; /* FF_BINARY label when false */ |
| 55 | } aSubmenuCtrl[20]; |
| 56 | static int nSubmenuCtrl = 0; |
| 57 | #define FF_ENTRY 1 |
| 58 | #define FF_MULTI 2 |
| 59 | #define FF_BINARY 3 |
| 60 | |
| 61 | /* |
| 62 | ** Remember that the header has been generated. The footer is omitted |
| 63 | ** if an error occurs before the header. |
| 64 | */ |
| @@ -230,18 +232,16 @@ | |
| 230 | /* |
| 231 | ** Add a new element to the submenu |
| 232 | */ |
| 233 | void style_submenu_element( |
| 234 | const char *zLabel, |
| 235 | const char *zTitle, |
| 236 | const char *zLink, |
| 237 | ... |
| 238 | ){ |
| 239 | va_list ap; |
| 240 | assert( nSubmenu < sizeof(aSubmenu)/sizeof(aSubmenu[0]) ); |
| 241 | aSubmenu[nSubmenu].zLabel = zLabel; |
| 242 | aSubmenu[nSubmenu].zTitle = zTitle ? zTitle : zLabel; |
| 243 | va_start(ap, zLink); |
| 244 | aSubmenu[nSubmenu].zLink = vmprintf(zLink, ap); |
| 245 | va_end(ap); |
| 246 | nSubmenu++; |
| 247 | } |
| @@ -249,25 +249,37 @@ | |
| 249 | const char *zName, /* Query parameter name */ |
| 250 | const char *zLabel, /* Label before the entry box */ |
| 251 | int iSize, /* Size of the entry box */ |
| 252 | int isDisabled /* True if disabled */ |
| 253 | ){ |
| 254 | assert( nSubmenuCtrl < ArraySize(aSubmenuCtrl) ); |
| 255 | aSubmenuCtrl[nSubmenuCtrl].zName = zName; |
| 256 | aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel; |
| 257 | aSubmenuCtrl[nSubmenuCtrl].iSize = iSize; |
| 258 | aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled; |
| 259 | aSubmenuCtrl[nSubmenuCtrl].eType = FF_ENTRY; |
| 260 | nSubmenuCtrl++; |
| 261 | } |
| 262 | void style_submenu_binary( |
| 263 | const char *zName, /* Query parameter name */ |
| 264 | const char *zTrue, /* Label to show when parameter is true */ |
| 265 | const char *zFalse, /* Label to show when the parameter is false */ |
| 266 | int isDisabled /* True if this control is disabled */ |
| 267 | ){ |
| 268 | assert( nSubmenuCtrl < ArraySize(aSubmenuCtrl) ); |
| 269 | aSubmenuCtrl[nSubmenuCtrl].zName = zName; |
| 270 | aSubmenuCtrl[nSubmenuCtrl].zLabel = zTrue; |
| 271 | aSubmenuCtrl[nSubmenuCtrl].zFalse = zFalse; |
| 272 | aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled; |
| 273 | aSubmenuCtrl[nSubmenuCtrl].eType = FF_BINARY; |
| @@ -277,11 +289,11 @@ | |
| 277 | const char *zName, /* Query parameter name */ |
| 278 | int nChoice, /* Number of options */ |
| 279 | const char *const *azChoice,/* value/display pairs. 2*nChoice entries */ |
| 280 | int isDisabled /* True if this control is disabled */ |
| 281 | ){ |
| 282 | assert( nSubmenuCtrl < ArraySize(aSubmenuCtrl) ); |
| 283 | aSubmenuCtrl[nSubmenuCtrl].zName = zName; |
| 284 | aSubmenuCtrl[nSubmenuCtrl].iSize = nChoice; |
| 285 | aSubmenuCtrl[nSubmenuCtrl].azChoice = azChoice; |
| 286 | aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled; |
| 287 | aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI; |
| @@ -400,10 +412,11 @@ | |
| 400 | |
| 401 | if( g.thTrace ) Th_Trace("BEGIN_HEADER<br />\n", -1); |
| 402 | |
| 403 | /* Generate the header up through the main menu */ |
| 404 | Th_Store("project_name", db_get("project-name","Unnamed Fossil Project")); |
| 405 | Th_Store("title", zTitle); |
| 406 | Th_Store("baseurl", g.zBaseURL); |
| 407 | Th_Store("secureurl", login_wants_https_redirect()? g.zHttpsURL: g.zBaseURL); |
| 408 | Th_Store("home", g.zTop); |
| 409 | Th_Store("index_page", db_get("index-page","/home")); |
| @@ -523,74 +536,75 @@ | |
| 523 | }else{ |
| 524 | @ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a> |
| 525 | } |
| 526 | } |
| 527 | } |
| 528 | if( nSubmenuCtrl>0 ){ |
| 529 | for(i=0; i<nSubmenuCtrl; i++){ |
| 530 | const char *zQPN = aSubmenuCtrl[i].zName; |
| 531 | const char *zDisabled = " disabled"; |
| 532 | if( !aSubmenuCtrl[i].isDisabled ){ |
| 533 | zDisabled = ""; |
| 534 | cgi_tag_query_parameter(zQPN); |
| 535 | } |
| 536 | switch( aSubmenuCtrl[i].eType ){ |
| 537 | case FF_ENTRY: { |
| 538 | cgi_printf( |
| 539 | "<span class='submenuctrl'>" |
| 540 | " %h<input type='text' name='%s' size='%d' maxlength='%d'" |
| 541 | " value='%h'%s></span>\n", |
| 542 | aSubmenuCtrl[i].zLabel, |
| 543 | zQPN, |
| 544 | aSubmenuCtrl[i].iSize, aSubmenuCtrl[i].iSize, |
| 545 | PD(zQPN,""), |
| 546 | zDisabled |
| 547 | ); |
| 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 | ); |
| 561 | for(j=0; j<aSubmenuCtrl[i].iSize*2; j+=2){ |
| 562 | const char *zQPV = aSubmenuCtrl[i].azChoice[j]; |
| 563 | cgi_printf( |
| 564 | "<option value='%h'%s>%h</option>\n", |
| 565 | zQPV, |
| 566 | fossil_strcmp(zVal,zQPV)==0 ? " selected" : "", |
| 567 | aSubmenuCtrl[i].azChoice[j+1] |
| 568 | ); |
| 569 | } |
| 570 | @ </select> |
| 571 | break; |
| 572 | } |
| 573 | case FF_BINARY: { |
| 574 | int isTrue = PB(zQPN); |
| 575 | cgi_printf( |
| 576 | "<select class='submenuctrl' size='1' name='%s'%s " |
| 577 | "onchange='gebi(\"f01\").submit();'>\n", |
| 578 | zQPN, zDisabled |
| 579 | ); |
| 580 | cgi_printf( |
| 581 | "<option value='1'%s>%h</option>\n", |
| 582 | isTrue ? " selected":"", aSubmenuCtrl[i].zLabel |
| 583 | ); |
| 584 | cgi_printf( |
| 585 | "<option value='0'%s>%h</option>\n", |
| 586 | (!isTrue) ? " selected":"", aSubmenuCtrl[i].zFalse |
| 587 | ); |
| 588 | @ </select> |
| 589 | break; |
| 590 | } |
| 591 | } |
| 592 | } |
| 593 | } |
| 594 | @ </div> |
| 595 | if( nSubmenuCtrl ){ |
| 596 | cgi_query_parameters_to_hidden(); |
| @@ -703,14 +717,15 @@ | |
| 703 | { "td.timelineTableCell", |
| 704 | "the format for the timeline data cells", |
| 705 | @ vertical-align: top; |
| 706 | @ text-align: left; |
| 707 | }, |
| 708 | { "tr.timelineCurrent td.timelineTableCell", |
| 709 | "the format for the timeline data cell of the current checkout", |
| 710 | @ padding: .1em .2em; |
| 711 | @ border: 1px dashed #446979; |
| 712 | }, |
| 713 | { "tr.timelineSelected", |
| 714 | "The row in the timeline table that contains the entry of interest", |
| 715 | @ padding: .1em .2em; |
| 716 | @ border: 2px solid lightgray; |
| @@ -1574,17 +1589,13 @@ | |
| 1574 | login_needed(0); |
| 1575 | return; |
| 1576 | } |
| 1577 | for(i=0; i<count(azCgiVars); i++) (void)P(azCgiVars[i]); |
| 1578 | style_header("Environment Test"); |
| 1579 | showAll = atoi(PD("showall","0")); |
| 1580 | if( !showAll ){ |
| 1581 | style_submenu_element("Show Cookies", 0, "%R/test_env?showall=1"); |
| 1582 | }else{ |
| 1583 | style_submenu_element("Hide Cookies", 0, "%R/test_env"); |
| 1584 | } |
| 1585 | style_submenu_element("Stats", 0, "%R/stat"); |
| 1586 | |
| 1587 | #if !defined(_WIN32) |
| 1588 | @ uid=%d(getuid()), gid=%d(getgid())<br /> |
| 1589 | #endif |
| 1590 | @ g.zBaseURL = %h(g.zBaseURL)<br /> |
| 1591 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -30,19 +30,20 @@ | |
| 30 | ** Populate these structure with calls to |
| 31 | ** |
| 32 | ** style_submenu_element() |
| 33 | ** style_submenu_entry() |
| 34 | ** style_submenu_checkbox() |
| 35 | ** style_submenu_binary() |
| 36 | ** style_submenu_multichoice() |
| 37 | ** style_submenu_sql() |
| 38 | ** |
| 39 | ** prior to calling style_footer(). The style_footer() routine |
| 40 | ** will generate the appropriate HTML text just below the main |
| 41 | ** menu. |
| 42 | */ |
| 43 | static struct Submenu { |
| 44 | const char *zLabel; /* Button label */ |
| 45 | const char *zLink; /* Jump to this link when button is pressed */ |
| 46 | } aSubmenu[30]; |
| 47 | static int nSubmenu = 0; /* Number of buttons */ |
| 48 | static struct SubmenuCtrl { |
| 49 | const char *zName; /* Form query parameter */ |
| @@ -52,13 +53,14 @@ | |
| 53 | short int iSize; /* Width for FF_ENTRY. Count for FF_MULTI */ |
| 54 | const char *const *azChoice;/* value/display pairs for FF_MULTI */ |
| 55 | const char *zFalse; /* FF_BINARY label when false */ |
| 56 | } aSubmenuCtrl[20]; |
| 57 | static int nSubmenuCtrl = 0; |
| 58 | #define FF_ENTRY 1 |
| 59 | #define FF_MULTI 2 |
| 60 | #define FF_BINARY 3 |
| 61 | #define FF_CHECKBOX 4 |
| 62 | |
| 63 | /* |
| 64 | ** Remember that the header has been generated. The footer is omitted |
| 65 | ** if an error occurs before the header. |
| 66 | */ |
| @@ -230,18 +232,16 @@ | |
| 232 | /* |
| 233 | ** Add a new element to the submenu |
| 234 | */ |
| 235 | void style_submenu_element( |
| 236 | const char *zLabel, |
| 237 | const char *zLink, |
| 238 | ... |
| 239 | ){ |
| 240 | va_list ap; |
| 241 | assert( nSubmenu < count(aSubmenu) ); |
| 242 | aSubmenu[nSubmenu].zLabel = zLabel; |
| 243 | va_start(ap, zLink); |
| 244 | aSubmenu[nSubmenu].zLink = vmprintf(zLink, ap); |
| 245 | va_end(ap); |
| 246 | nSubmenu++; |
| 247 | } |
| @@ -249,25 +249,37 @@ | |
| 249 | const char *zName, /* Query parameter name */ |
| 250 | const char *zLabel, /* Label before the entry box */ |
| 251 | int iSize, /* Size of the entry box */ |
| 252 | int isDisabled /* True if disabled */ |
| 253 | ){ |
| 254 | assert( nSubmenuCtrl < count(aSubmenuCtrl) ); |
| 255 | aSubmenuCtrl[nSubmenuCtrl].zName = zName; |
| 256 | aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel; |
| 257 | aSubmenuCtrl[nSubmenuCtrl].iSize = iSize; |
| 258 | aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled; |
| 259 | aSubmenuCtrl[nSubmenuCtrl].eType = FF_ENTRY; |
| 260 | nSubmenuCtrl++; |
| 261 | } |
| 262 | void style_submenu_checkbox( |
| 263 | const char *zName, /* Query parameter name */ |
| 264 | const char *zLabel, /* Label to display after the checkbox */ |
| 265 | int isDisabled /* True if disabled */ |
| 266 | ){ |
| 267 | assert( nSubmenuCtrl < count(aSubmenuCtrl) ); |
| 268 | aSubmenuCtrl[nSubmenuCtrl].zName = zName; |
| 269 | aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel; |
| 270 | aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled; |
| 271 | aSubmenuCtrl[nSubmenuCtrl].eType = FF_CHECKBOX; |
| 272 | nSubmenuCtrl++; |
| 273 | } |
| 274 | void style_submenu_binary( |
| 275 | const char *zName, /* Query parameter name */ |
| 276 | const char *zTrue, /* Label to show when parameter is true */ |
| 277 | const char *zFalse, /* Label to show when the parameter is false */ |
| 278 | int isDisabled /* True if this control is disabled */ |
| 279 | ){ |
| 280 | assert( nSubmenuCtrl < count(aSubmenuCtrl) ); |
| 281 | aSubmenuCtrl[nSubmenuCtrl].zName = zName; |
| 282 | aSubmenuCtrl[nSubmenuCtrl].zLabel = zTrue; |
| 283 | aSubmenuCtrl[nSubmenuCtrl].zFalse = zFalse; |
| 284 | aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled; |
| 285 | aSubmenuCtrl[nSubmenuCtrl].eType = FF_BINARY; |
| @@ -277,11 +289,11 @@ | |
| 289 | const char *zName, /* Query parameter name */ |
| 290 | int nChoice, /* Number of options */ |
| 291 | const char *const *azChoice,/* value/display pairs. 2*nChoice entries */ |
| 292 | int isDisabled /* True if this control is disabled */ |
| 293 | ){ |
| 294 | assert( nSubmenuCtrl < count(aSubmenuCtrl) ); |
| 295 | aSubmenuCtrl[nSubmenuCtrl].zName = zName; |
| 296 | aSubmenuCtrl[nSubmenuCtrl].iSize = nChoice; |
| 297 | aSubmenuCtrl[nSubmenuCtrl].azChoice = azChoice; |
| 298 | aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled; |
| 299 | aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI; |
| @@ -400,10 +412,11 @@ | |
| 412 | |
| 413 | if( g.thTrace ) Th_Trace("BEGIN_HEADER<br />\n", -1); |
| 414 | |
| 415 | /* Generate the header up through the main menu */ |
| 416 | Th_Store("project_name", db_get("project-name","Unnamed Fossil Project")); |
| 417 | Th_Store("project_description", db_get("project-description","")); |
| 418 | Th_Store("title", zTitle); |
| 419 | Th_Store("baseurl", g.zBaseURL); |
| 420 | Th_Store("secureurl", login_wants_https_redirect()? g.zHttpsURL: g.zBaseURL); |
| 421 | Th_Store("home", g.zTop); |
| 422 | Th_Store("index_page", db_get("index-page","/home")); |
| @@ -523,74 +536,75 @@ | |
| 536 | }else{ |
| 537 | @ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a> |
| 538 | } |
| 539 | } |
| 540 | } |
| 541 | for(i=0; i<nSubmenuCtrl; i++){ |
| 542 | const char *zQPN = aSubmenuCtrl[i].zName; |
| 543 | const char *zDisabled = " disabled"; |
| 544 | if( !aSubmenuCtrl[i].isDisabled ){ |
| 545 | zDisabled = ""; |
| 546 | cgi_tag_query_parameter(zQPN); |
| 547 | } |
| 548 | switch( aSubmenuCtrl[i].eType ){ |
| 549 | case FF_ENTRY: |
| 550 | @ <span class='submenuctrl'>\ |
| 551 | @ %h(aSubmenuCtrl[i].zLabel)\ |
| 552 | @ <input type='text' name='%s(zQPN)' value='%h(PD(zQPN, ""))' \ |
| 553 | if( aSubmenuCtrl[i].iSize<0 ){ |
| 554 | @ size='%d(-aSubmenuCtrl[i].iSize)' \ |
| 555 | }else if( aSubmenuCtrl[i].iSize>0 ){ |
| 556 | @ size='%d(aSubmenuCtrl[i].iSize)' \ |
| 557 | @ maxlength='%d(aSubmenuCtrl[i].iSize)' \ |
| 558 | } |
| 559 | @ onchange='gebi("f01").submit();'%s(zDisabled)></span> |
| 560 | break; |
| 561 | case FF_MULTI: { |
| 562 | int j; |
| 563 | const char *zVal = P(zQPN); |
| 564 | if( aSubmenuCtrl[i].zLabel ){ |
| 565 | @ %h(aSubmenuCtrl[i].zLabel)\ |
| 566 | } |
| 567 | @ <select class='submenuctrl' size='1' name='%s(zQPN)' \ |
| 568 | @ onchange='gebi("f01").submit();'%s(zDisabled)> |
| 569 | for(j=0; j<aSubmenuCtrl[i].iSize*2; j+=2){ |
| 570 | const char *zQPV = aSubmenuCtrl[i].azChoice[j]; |
| 571 | @ <option value='%h(zQPV)'\ |
| 572 | if( fossil_strcmp(zVal, zQPV)==0 ){ |
| 573 | @ selected\ |
| 574 | } |
| 575 | @ >%h(aSubmenuCtrl[i].azChoice[j+1])</option> |
| 576 | } |
| 577 | @ </select> |
| 578 | break; |
| 579 | } |
| 580 | case FF_BINARY: { |
| 581 | int isTrue = PB(zQPN); |
| 582 | @ <select class='submenuctrl' size='1' name='%s(zQPN)' \ |
| 583 | @ onchange='gebi("f01").submit();'%s(zDisabled)> |
| 584 | @ <option value='1'\ |
| 585 | if( isTrue ){ |
| 586 | @ selected\ |
| 587 | } |
| 588 | @ >%h(aSubmenuCtrl[i].zLabel)</option> |
| 589 | @ <option value='0'\ |
| 590 | if( !isTrue ){ |
| 591 | @ selected\ |
| 592 | } |
| 593 | @ >%h(aSubmenuCtrl[i].zFalse)</option> |
| 594 | @ </select> |
| 595 | break; |
| 596 | } |
| 597 | case FF_CHECKBOX: |
| 598 | @ <label class='submenuctrl'>\ |
| 599 | @ <input type='checkbox' name='%s(zQPN)' value='1' \ |
| 600 | if( PB(zQPN) ){ |
| 601 | @ checked \ |
| 602 | } |
| 603 | @ onchange='gebi("f01").submit();'%s(zDisabled)>\ |
| 604 | @ %h(aSubmenuCtrl[i].zLabel)</label> |
| 605 | break; |
| 606 | } |
| 607 | } |
| 608 | @ </div> |
| 609 | if( nSubmenuCtrl ){ |
| 610 | cgi_query_parameters_to_hidden(); |
| @@ -703,14 +717,15 @@ | |
| 717 | { "td.timelineTableCell", |
| 718 | "the format for the timeline data cells", |
| 719 | @ vertical-align: top; |
| 720 | @ text-align: left; |
| 721 | }, |
| 722 | { "tr.timelineCurrent", |
| 723 | "the format for the timeline data cell of the current checkout", |
| 724 | @ padding: .1em .2em; |
| 725 | @ border: 1px dashed #446979; |
| 726 | @ box-shadow: 1px 1px 4px #888; |
| 727 | }, |
| 728 | { "tr.timelineSelected", |
| 729 | "The row in the timeline table that contains the entry of interest", |
| 730 | @ padding: .1em .2em; |
| 731 | @ border: 2px solid lightgray; |
| @@ -1574,17 +1589,13 @@ | |
| 1589 | login_needed(0); |
| 1590 | return; |
| 1591 | } |
| 1592 | for(i=0; i<count(azCgiVars); i++) (void)P(azCgiVars[i]); |
| 1593 | style_header("Environment Test"); |
| 1594 | showAll = PB("showall"); |
| 1595 | style_submenu_checkbox("showall", "Cookies", 0); |
| 1596 | style_submenu_element("Stats", "%R/stat"); |
| 1597 | |
| 1598 | #if !defined(_WIN32) |
| 1599 | @ uid=%d(getuid()), gid=%d(getgid())<br /> |
| 1600 | #endif |
| 1601 | @ g.zBaseURL = %h(g.zBaseURL)<br /> |
| 1602 |
+2
-2
| --- src/tag.c | ||
| +++ src/tag.c | ||
| @@ -654,11 +654,11 @@ | ||
| 654 | 654 | login_needed(g.anon.Read); |
| 655 | 655 | } |
| 656 | 656 | login_anonymous_available(); |
| 657 | 657 | style_header("Tags"); |
| 658 | 658 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 659 | - style_submenu_element("Timeline", "Timeline", "tagtimeline"); | |
| 659 | + style_submenu_element("Timeline", "tagtimeline"); | |
| 660 | 660 | @ <h2>Non-propagating tags:</h2> |
| 661 | 661 | db_prepare(&q, |
| 662 | 662 | "SELECT substr(tagname,5)" |
| 663 | 663 | " FROM tag" |
| 664 | 664 | " WHERE EXISTS(SELECT 1 FROM tagxref" |
| @@ -693,11 +693,11 @@ | ||
| 693 | 693 | |
| 694 | 694 | login_check_credentials(); |
| 695 | 695 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 696 | 696 | |
| 697 | 697 | style_header("Tagged Check-ins"); |
| 698 | - style_submenu_element("List", "List", "taglist"); | |
| 698 | + style_submenu_element("List", "taglist"); | |
| 699 | 699 | login_anonymous_available(); |
| 700 | 700 | @ <h2>Check-ins with non-propagating tags:</h2> |
| 701 | 701 | db_prepare(&q, |
| 702 | 702 | "%s AND blob.rid IN (SELECT rid FROM tagxref" |
| 703 | 703 | " WHERE tagtype=1 AND srcid>0" |
| 704 | 704 |
| --- src/tag.c | |
| +++ src/tag.c | |
| @@ -654,11 +654,11 @@ | |
| 654 | login_needed(g.anon.Read); |
| 655 | } |
| 656 | login_anonymous_available(); |
| 657 | style_header("Tags"); |
| 658 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 659 | style_submenu_element("Timeline", "Timeline", "tagtimeline"); |
| 660 | @ <h2>Non-propagating tags:</h2> |
| 661 | db_prepare(&q, |
| 662 | "SELECT substr(tagname,5)" |
| 663 | " FROM tag" |
| 664 | " WHERE EXISTS(SELECT 1 FROM tagxref" |
| @@ -693,11 +693,11 @@ | |
| 693 | |
| 694 | login_check_credentials(); |
| 695 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 696 | |
| 697 | style_header("Tagged Check-ins"); |
| 698 | style_submenu_element("List", "List", "taglist"); |
| 699 | login_anonymous_available(); |
| 700 | @ <h2>Check-ins with non-propagating tags:</h2> |
| 701 | db_prepare(&q, |
| 702 | "%s AND blob.rid IN (SELECT rid FROM tagxref" |
| 703 | " WHERE tagtype=1 AND srcid>0" |
| 704 |
| --- src/tag.c | |
| +++ src/tag.c | |
| @@ -654,11 +654,11 @@ | |
| 654 | login_needed(g.anon.Read); |
| 655 | } |
| 656 | login_anonymous_available(); |
| 657 | style_header("Tags"); |
| 658 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 659 | style_submenu_element("Timeline", "tagtimeline"); |
| 660 | @ <h2>Non-propagating tags:</h2> |
| 661 | db_prepare(&q, |
| 662 | "SELECT substr(tagname,5)" |
| 663 | " FROM tag" |
| 664 | " WHERE EXISTS(SELECT 1 FROM tagxref" |
| @@ -693,11 +693,11 @@ | |
| 693 | |
| 694 | login_check_credentials(); |
| 695 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 696 | |
| 697 | style_header("Tagged Check-ins"); |
| 698 | style_submenu_element("List", "taglist"); |
| 699 | login_anonymous_available(); |
| 700 | @ <h2>Check-ins with non-propagating tags:</h2> |
| 701 | db_prepare(&q, |
| 702 | "%s AND blob.rid IN (SELECT rid FROM tagxref" |
| 703 | " WHERE tagtype=1 AND srcid>0" |
| 704 |
+85
-2
| --- src/th_main.c | ||
| +++ src/th_main.c | ||
| @@ -1317,10 +1317,92 @@ | ||
| 1317 | 1317 | }else{ |
| 1318 | 1318 | Th_SetResult(interp, "repository unavailable", -1); |
| 1319 | 1319 | return TH_ERROR; |
| 1320 | 1320 | } |
| 1321 | 1321 | } |
| 1322 | + | |
| 1323 | +/* | |
| 1324 | +** TH1 command: unversioned content FILENAME | |
| 1325 | +** | |
| 1326 | +** Attempts to locate the specified unversioned file and return its contents. | |
| 1327 | +** An error is generated if the repository is not open or the unversioned file | |
| 1328 | +** cannot be found. | |
| 1329 | +*/ | |
| 1330 | +static int unversionedContentCmd( | |
| 1331 | + Th_Interp *interp, | |
| 1332 | + void *p, | |
| 1333 | + int argc, | |
| 1334 | + const char **argv, | |
| 1335 | + int *argl | |
| 1336 | +){ | |
| 1337 | + if( argc!=3 ){ | |
| 1338 | + return Th_WrongNumArgs(interp, "unversioned content FILENAME"); | |
| 1339 | + } | |
| 1340 | + if( Th_IsRepositoryOpen() ){ | |
| 1341 | + Blob content; | |
| 1342 | + if( unversioned_content(argv[2], &content)==0 ){ | |
| 1343 | + Th_SetResult(interp, blob_str(&content), blob_size(&content)); | |
| 1344 | + blob_reset(&content); | |
| 1345 | + return TH_OK; | |
| 1346 | + }else{ | |
| 1347 | + return TH_ERROR; | |
| 1348 | + } | |
| 1349 | + }else{ | |
| 1350 | + Th_SetResult(interp, "repository unavailable", -1); | |
| 1351 | + return TH_ERROR; | |
| 1352 | + } | |
| 1353 | +} | |
| 1354 | + | |
| 1355 | +/* | |
| 1356 | +** TH1 command: unversioned list | |
| 1357 | +** | |
| 1358 | +** Returns a list of the names of all unversioned files held in the local | |
| 1359 | +** repository. An error is generated if the repository is not open. | |
| 1360 | +*/ | |
| 1361 | +static int unversionedListCmd( | |
| 1362 | + Th_Interp *interp, | |
| 1363 | + void *p, | |
| 1364 | + int argc, | |
| 1365 | + const char **argv, | |
| 1366 | + int *argl | |
| 1367 | +){ | |
| 1368 | + if( argc!=2 ){ | |
| 1369 | + return Th_WrongNumArgs(interp, "unversioned list"); | |
| 1370 | + } | |
| 1371 | + if( Th_IsRepositoryOpen() ){ | |
| 1372 | + Stmt q; | |
| 1373 | + char *zList = 0; | |
| 1374 | + int nList = 0; | |
| 1375 | + db_prepare(&q, "SELECT name FROM unversioned WHERE hash IS NOT NULL" | |
| 1376 | + " ORDER BY name"); | |
| 1377 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 1378 | + Th_ListAppend(interp, &zList, &nList, db_column_text(&q,0), -1); | |
| 1379 | + } | |
| 1380 | + db_finalize(&q); | |
| 1381 | + Th_SetResult(interp, zList, nList); | |
| 1382 | + Th_Free(interp, zList); | |
| 1383 | + return TH_OK; | |
| 1384 | + }else{ | |
| 1385 | + Th_SetResult(interp, "repository unavailable", -1); | |
| 1386 | + return TH_ERROR; | |
| 1387 | + } | |
| 1388 | +} | |
| 1389 | + | |
| 1390 | +static int unversionedCmd( | |
| 1391 | + Th_Interp *interp, | |
| 1392 | + void *p, | |
| 1393 | + int argc, | |
| 1394 | + const char **argv, | |
| 1395 | + int *argl | |
| 1396 | +){ | |
| 1397 | + static const Th_SubCommand aSub[] = { | |
| 1398 | + { "content", unversionedContentCmd }, | |
| 1399 | + { "list", unversionedListCmd }, | |
| 1400 | + { 0, 0 } | |
| 1401 | + }; | |
| 1402 | + return Th_CallSubCommand(interp, p, argc, argv, argl, aSub); | |
| 1403 | +} | |
| 1322 | 1404 | |
| 1323 | 1405 | #ifdef _WIN32 |
| 1324 | 1406 | # include <windows.h> |
| 1325 | 1407 | #else |
| 1326 | 1408 | # include <sys/time.h> |
| @@ -1886,10 +1968,11 @@ | ||
| 1886 | 1968 | {"styleHeader", styleHeaderCmd, 0}, |
| 1887 | 1969 | {"styleFooter", styleFooterCmd, 0}, |
| 1888 | 1970 | {"tclReady", tclReadyCmd, 0}, |
| 1889 | 1971 | {"trace", traceCmd, 0}, |
| 1890 | 1972 | {"stime", stimeCmd, 0}, |
| 1973 | + {"unversioned", unversionedCmd, 0}, | |
| 1891 | 1974 | {"utime", utimeCmd, 0}, |
| 1892 | 1975 | {"verifyCsrf", verifyCsrfCmd, 0}, |
| 1893 | 1976 | {"wiki", wikiCmd, (void*)&aFlags[0]}, |
| 1894 | 1977 | {0, 0, 0} |
| 1895 | 1978 | }; |
| @@ -1922,11 +2005,11 @@ | ||
| 1922 | 2005 | g.tcl.setup = db_get("tcl-setup", 0); /* Grab Tcl setup script. */ |
| 1923 | 2006 | } |
| 1924 | 2007 | th_register_tcl(g.interp, &g.tcl); /* Tcl integration commands. */ |
| 1925 | 2008 | } |
| 1926 | 2009 | #endif |
| 1927 | - for(i=0; i<sizeof(aCommand)/sizeof(aCommand[0]); i++){ | |
| 2010 | + for(i=0; i<count(aCommand); i++){ | |
| 1928 | 2011 | if ( !aCommand[i].zName || !aCommand[i].xProc ) continue; |
| 1929 | 2012 | Th_CreateCommand(g.interp, aCommand[i].zName, aCommand[i].xProc, |
| 1930 | 2013 | aCommand[i].pContext, 0); |
| 1931 | 2014 | } |
| 1932 | 2015 | }else{ |
| @@ -2593,11 +2676,11 @@ | ||
| 2593 | 2676 | }else if( fossil_stricmp(g.argv[2], "webhook")==0 ){ |
| 2594 | 2677 | rc = Th_WebpageHook(g.argv[3], (unsigned int)atoi(g.argv[4])); |
| 2595 | 2678 | }else if( fossil_stricmp(g.argv[2], "webnotify")==0 ){ |
| 2596 | 2679 | rc = Th_WebpageNotify(g.argv[3], (unsigned int)atoi(g.argv[4])); |
| 2597 | 2680 | }else{ |
| 2598 | - fossil_fatal("Unknown TH1 hook %s\n", g.argv[2]); | |
| 2681 | + fossil_fatal("Unknown TH1 hook %s", g.argv[2]); | |
| 2599 | 2682 | } |
| 2600 | 2683 | if( g.interp ){ |
| 2601 | 2684 | zResult = (char*)Th_GetResult(g.interp, &nResult); |
| 2602 | 2685 | } |
| 2603 | 2686 | sendText("RESULT (", -1, 0); |
| 2604 | 2687 |
| --- src/th_main.c | |
| +++ src/th_main.c | |
| @@ -1317,10 +1317,92 @@ | |
| 1317 | }else{ |
| 1318 | Th_SetResult(interp, "repository unavailable", -1); |
| 1319 | return TH_ERROR; |
| 1320 | } |
| 1321 | } |
| 1322 | |
| 1323 | #ifdef _WIN32 |
| 1324 | # include <windows.h> |
| 1325 | #else |
| 1326 | # include <sys/time.h> |
| @@ -1886,10 +1968,11 @@ | |
| 1886 | {"styleHeader", styleHeaderCmd, 0}, |
| 1887 | {"styleFooter", styleFooterCmd, 0}, |
| 1888 | {"tclReady", tclReadyCmd, 0}, |
| 1889 | {"trace", traceCmd, 0}, |
| 1890 | {"stime", stimeCmd, 0}, |
| 1891 | {"utime", utimeCmd, 0}, |
| 1892 | {"verifyCsrf", verifyCsrfCmd, 0}, |
| 1893 | {"wiki", wikiCmd, (void*)&aFlags[0]}, |
| 1894 | {0, 0, 0} |
| 1895 | }; |
| @@ -1922,11 +2005,11 @@ | |
| 1922 | g.tcl.setup = db_get("tcl-setup", 0); /* Grab Tcl setup script. */ |
| 1923 | } |
| 1924 | th_register_tcl(g.interp, &g.tcl); /* Tcl integration commands. */ |
| 1925 | } |
| 1926 | #endif |
| 1927 | for(i=0; i<sizeof(aCommand)/sizeof(aCommand[0]); i++){ |
| 1928 | if ( !aCommand[i].zName || !aCommand[i].xProc ) continue; |
| 1929 | Th_CreateCommand(g.interp, aCommand[i].zName, aCommand[i].xProc, |
| 1930 | aCommand[i].pContext, 0); |
| 1931 | } |
| 1932 | }else{ |
| @@ -2593,11 +2676,11 @@ | |
| 2593 | }else if( fossil_stricmp(g.argv[2], "webhook")==0 ){ |
| 2594 | rc = Th_WebpageHook(g.argv[3], (unsigned int)atoi(g.argv[4])); |
| 2595 | }else if( fossil_stricmp(g.argv[2], "webnotify")==0 ){ |
| 2596 | rc = Th_WebpageNotify(g.argv[3], (unsigned int)atoi(g.argv[4])); |
| 2597 | }else{ |
| 2598 | fossil_fatal("Unknown TH1 hook %s\n", g.argv[2]); |
| 2599 | } |
| 2600 | if( g.interp ){ |
| 2601 | zResult = (char*)Th_GetResult(g.interp, &nResult); |
| 2602 | } |
| 2603 | sendText("RESULT (", -1, 0); |
| 2604 |
| --- src/th_main.c | |
| +++ src/th_main.c | |
| @@ -1317,10 +1317,92 @@ | |
| 1317 | }else{ |
| 1318 | Th_SetResult(interp, "repository unavailable", -1); |
| 1319 | return TH_ERROR; |
| 1320 | } |
| 1321 | } |
| 1322 | |
| 1323 | /* |
| 1324 | ** TH1 command: unversioned content FILENAME |
| 1325 | ** |
| 1326 | ** Attempts to locate the specified unversioned file and return its contents. |
| 1327 | ** An error is generated if the repository is not open or the unversioned file |
| 1328 | ** cannot be found. |
| 1329 | */ |
| 1330 | static int unversionedContentCmd( |
| 1331 | Th_Interp *interp, |
| 1332 | void *p, |
| 1333 | int argc, |
| 1334 | const char **argv, |
| 1335 | int *argl |
| 1336 | ){ |
| 1337 | if( argc!=3 ){ |
| 1338 | return Th_WrongNumArgs(interp, "unversioned content FILENAME"); |
| 1339 | } |
| 1340 | if( Th_IsRepositoryOpen() ){ |
| 1341 | Blob content; |
| 1342 | if( unversioned_content(argv[2], &content)==0 ){ |
| 1343 | Th_SetResult(interp, blob_str(&content), blob_size(&content)); |
| 1344 | blob_reset(&content); |
| 1345 | return TH_OK; |
| 1346 | }else{ |
| 1347 | return TH_ERROR; |
| 1348 | } |
| 1349 | }else{ |
| 1350 | Th_SetResult(interp, "repository unavailable", -1); |
| 1351 | return TH_ERROR; |
| 1352 | } |
| 1353 | } |
| 1354 | |
| 1355 | /* |
| 1356 | ** TH1 command: unversioned list |
| 1357 | ** |
| 1358 | ** Returns a list of the names of all unversioned files held in the local |
| 1359 | ** repository. An error is generated if the repository is not open. |
| 1360 | */ |
| 1361 | static int unversionedListCmd( |
| 1362 | Th_Interp *interp, |
| 1363 | void *p, |
| 1364 | int argc, |
| 1365 | const char **argv, |
| 1366 | int *argl |
| 1367 | ){ |
| 1368 | if( argc!=2 ){ |
| 1369 | return Th_WrongNumArgs(interp, "unversioned list"); |
| 1370 | } |
| 1371 | if( Th_IsRepositoryOpen() ){ |
| 1372 | Stmt q; |
| 1373 | char *zList = 0; |
| 1374 | int nList = 0; |
| 1375 | db_prepare(&q, "SELECT name FROM unversioned WHERE hash IS NOT NULL" |
| 1376 | " ORDER BY name"); |
| 1377 | while( db_step(&q)==SQLITE_ROW ){ |
| 1378 | Th_ListAppend(interp, &zList, &nList, db_column_text(&q,0), -1); |
| 1379 | } |
| 1380 | db_finalize(&q); |
| 1381 | Th_SetResult(interp, zList, nList); |
| 1382 | Th_Free(interp, zList); |
| 1383 | return TH_OK; |
| 1384 | }else{ |
| 1385 | Th_SetResult(interp, "repository unavailable", -1); |
| 1386 | return TH_ERROR; |
| 1387 | } |
| 1388 | } |
| 1389 | |
| 1390 | static int unversionedCmd( |
| 1391 | Th_Interp *interp, |
| 1392 | void *p, |
| 1393 | int argc, |
| 1394 | const char **argv, |
| 1395 | int *argl |
| 1396 | ){ |
| 1397 | static const Th_SubCommand aSub[] = { |
| 1398 | { "content", unversionedContentCmd }, |
| 1399 | { "list", unversionedListCmd }, |
| 1400 | { 0, 0 } |
| 1401 | }; |
| 1402 | return Th_CallSubCommand(interp, p, argc, argv, argl, aSub); |
| 1403 | } |
| 1404 | |
| 1405 | #ifdef _WIN32 |
| 1406 | # include <windows.h> |
| 1407 | #else |
| 1408 | # include <sys/time.h> |
| @@ -1886,10 +1968,11 @@ | |
| 1968 | {"styleHeader", styleHeaderCmd, 0}, |
| 1969 | {"styleFooter", styleFooterCmd, 0}, |
| 1970 | {"tclReady", tclReadyCmd, 0}, |
| 1971 | {"trace", traceCmd, 0}, |
| 1972 | {"stime", stimeCmd, 0}, |
| 1973 | {"unversioned", unversionedCmd, 0}, |
| 1974 | {"utime", utimeCmd, 0}, |
| 1975 | {"verifyCsrf", verifyCsrfCmd, 0}, |
| 1976 | {"wiki", wikiCmd, (void*)&aFlags[0]}, |
| 1977 | {0, 0, 0} |
| 1978 | }; |
| @@ -1922,11 +2005,11 @@ | |
| 2005 | g.tcl.setup = db_get("tcl-setup", 0); /* Grab Tcl setup script. */ |
| 2006 | } |
| 2007 | th_register_tcl(g.interp, &g.tcl); /* Tcl integration commands. */ |
| 2008 | } |
| 2009 | #endif |
| 2010 | for(i=0; i<count(aCommand); i++){ |
| 2011 | if ( !aCommand[i].zName || !aCommand[i].xProc ) continue; |
| 2012 | Th_CreateCommand(g.interp, aCommand[i].zName, aCommand[i].xProc, |
| 2013 | aCommand[i].pContext, 0); |
| 2014 | } |
| 2015 | }else{ |
| @@ -2593,11 +2676,11 @@ | |
| 2676 | }else if( fossil_stricmp(g.argv[2], "webhook")==0 ){ |
| 2677 | rc = Th_WebpageHook(g.argv[3], (unsigned int)atoi(g.argv[4])); |
| 2678 | }else if( fossil_stricmp(g.argv[2], "webnotify")==0 ){ |
| 2679 | rc = Th_WebpageNotify(g.argv[3], (unsigned int)atoi(g.argv[4])); |
| 2680 | }else{ |
| 2681 | fossil_fatal("Unknown TH1 hook %s", g.argv[2]); |
| 2682 | } |
| 2683 | if( g.interp ){ |
| 2684 | zResult = (char*)Th_GetResult(g.interp, &nResult); |
| 2685 | } |
| 2686 | sendText("RESULT (", -1, 0); |
| 2687 |
+2
-2
| --- src/th_tcl.c | ||
| +++ src/th_tcl.c | ||
| @@ -833,11 +833,11 @@ | ||
| 833 | 833 | int i; |
| 834 | 834 | Th_Interp *th1Interp = (Th_Interp *)clientData; |
| 835 | 835 | |
| 836 | 836 | if( !th1Interp ) return; |
| 837 | 837 | /* Remove the Tcl integration commands. */ |
| 838 | - for(i=0; i<(sizeof(aCommand)/sizeof(aCommand[0])); i++){ | |
| 838 | + for(i=0; i<count(aCommand); i++){ | |
| 839 | 839 | Th_RenameCommand(th1Interp, aCommand[i].zName, -1, NULL, 0); |
| 840 | 840 | } |
| 841 | 841 | } |
| 842 | 842 | |
| 843 | 843 | /* |
| @@ -1261,11 +1261,11 @@ | ||
| 1261 | 1261 | void *pContext |
| 1262 | 1262 | ){ |
| 1263 | 1263 | int i; |
| 1264 | 1264 | |
| 1265 | 1265 | /* Add the Tcl integration commands to TH1. */ |
| 1266 | - for(i=0; i<(sizeof(aCommand)/sizeof(aCommand[0])); i++){ | |
| 1266 | + for(i=0; i<count(aCommand); i++){ | |
| 1267 | 1267 | void *ctx; |
| 1268 | 1268 | if( !aCommand[i].zName || !aCommand[i].xProc ) continue; |
| 1269 | 1269 | ctx = aCommand[i].pContext; |
| 1270 | 1270 | /* Use Tcl interpreter for context? */ |
| 1271 | 1271 | if( !ctx ) ctx = pContext; |
| 1272 | 1272 |
| --- src/th_tcl.c | |
| +++ src/th_tcl.c | |
| @@ -833,11 +833,11 @@ | |
| 833 | int i; |
| 834 | Th_Interp *th1Interp = (Th_Interp *)clientData; |
| 835 | |
| 836 | if( !th1Interp ) return; |
| 837 | /* Remove the Tcl integration commands. */ |
| 838 | for(i=0; i<(sizeof(aCommand)/sizeof(aCommand[0])); i++){ |
| 839 | Th_RenameCommand(th1Interp, aCommand[i].zName, -1, NULL, 0); |
| 840 | } |
| 841 | } |
| 842 | |
| 843 | /* |
| @@ -1261,11 +1261,11 @@ | |
| 1261 | void *pContext |
| 1262 | ){ |
| 1263 | int i; |
| 1264 | |
| 1265 | /* Add the Tcl integration commands to TH1. */ |
| 1266 | for(i=0; i<(sizeof(aCommand)/sizeof(aCommand[0])); i++){ |
| 1267 | void *ctx; |
| 1268 | if( !aCommand[i].zName || !aCommand[i].xProc ) continue; |
| 1269 | ctx = aCommand[i].pContext; |
| 1270 | /* Use Tcl interpreter for context? */ |
| 1271 | if( !ctx ) ctx = pContext; |
| 1272 |
| --- src/th_tcl.c | |
| +++ src/th_tcl.c | |
| @@ -833,11 +833,11 @@ | |
| 833 | int i; |
| 834 | Th_Interp *th1Interp = (Th_Interp *)clientData; |
| 835 | |
| 836 | if( !th1Interp ) return; |
| 837 | /* Remove the Tcl integration commands. */ |
| 838 | for(i=0; i<count(aCommand); i++){ |
| 839 | Th_RenameCommand(th1Interp, aCommand[i].zName, -1, NULL, 0); |
| 840 | } |
| 841 | } |
| 842 | |
| 843 | /* |
| @@ -1261,11 +1261,11 @@ | |
| 1261 | void *pContext |
| 1262 | ){ |
| 1263 | int i; |
| 1264 | |
| 1265 | /* Add the Tcl integration commands to TH1. */ |
| 1266 | for(i=0; i<count(aCommand); i++){ |
| 1267 | void *ctx; |
| 1268 | if( !aCommand[i].zName || !aCommand[i].xProc ) continue; |
| 1269 | ctx = aCommand[i].pContext; |
| 1270 | /* Use Tcl interpreter for context? */ |
| 1271 | if( !ctx ) ctx = pContext; |
| 1272 |
+29
-36
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -390,11 +390,11 @@ | ||
| 390 | 390 | "SELECT pid FROM plink" |
| 391 | 391 | " WHERE cid=:rid AND pid NOT IN phantom" |
| 392 | 392 | " ORDER BY isprim DESC /*sort*/" |
| 393 | 393 | ); |
| 394 | 394 | db_bind_int(&qparent, ":rid", rid); |
| 395 | - while( db_step(&qparent)==SQLITE_ROW && nParent<ArraySize(aParent) ){ | |
| 395 | + while( db_step(&qparent)==SQLITE_ROW && nParent<count(aParent) ){ | |
| 396 | 396 | aParent[nParent++] = db_column_int(&qparent, 0); |
| 397 | 397 | } |
| 398 | 398 | db_reset(&qparent); |
| 399 | 399 | gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr, |
| 400 | 400 | zUuid, isLeaf); |
| @@ -737,11 +737,11 @@ | ||
| 737 | 737 | pRow->mergeOut, /* mo */ |
| 738 | 738 | pRow->mergeUpto, /* mu */ |
| 739 | 739 | pRow->aiRiser[pRow->iRail], /* u */ |
| 740 | 740 | pRow->isLeaf ? 1 : 0 /* f */ |
| 741 | 741 | ); |
| 742 | - /* u */ | |
| 742 | + /* au */ | |
| 743 | 743 | cSep = '['; |
| 744 | 744 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 745 | 745 | if( i==pRow->iRail ) continue; |
| 746 | 746 | if( pRow->aiRiser[i]>0 ){ |
| 747 | 747 | cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]); |
| @@ -757,11 +757,11 @@ | ||
| 757 | 757 | cgi_printf("mi:"); |
| 758 | 758 | cSep = '['; |
| 759 | 759 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 760 | 760 | if( pRow->mergeIn[i] ){ |
| 761 | 761 | int mi = i; |
| 762 | - if( pRow->mergeDown & (1<<i) ) mi = -mi; | |
| 762 | + if( (pRow->mergeDown >> i) & 1 ) mi = -mi; | |
| 763 | 763 | cgi_printf("%c%d", cSep, mi); |
| 764 | 764 | cSep = ','; |
| 765 | 765 | } |
| 766 | 766 | } |
| 767 | 767 | if( cSep=='[' ) cgi_printf("["); |
| @@ -1083,11 +1083,11 @@ | ||
| 1083 | 1083 | const char *zMenuName, /* Submenu name */ |
| 1084 | 1084 | const char *zParam, /* Parameter value to add or change */ |
| 1085 | 1085 | const char *zValue, /* Value of the new parameter */ |
| 1086 | 1086 | const char *zRemove /* Parameter to omit */ |
| 1087 | 1087 | ){ |
| 1088 | - style_submenu_element(zMenuName, zMenuName, "%s", | |
| 1088 | + style_submenu_element(zMenuName, "%s", | |
| 1089 | 1089 | url_render(pUrl, zParam, zValue, zRemove, 0)); |
| 1090 | 1090 | } |
| 1091 | 1091 | |
| 1092 | 1092 | |
| 1093 | 1093 | /* |
| @@ -1186,11 +1186,11 @@ | ||
| 1186 | 1186 | } |
| 1187 | 1187 | if( g.perm.RdWiki ){ |
| 1188 | 1188 | az[i++] = "w"; |
| 1189 | 1189 | az[i++] = "Wiki"; |
| 1190 | 1190 | } |
| 1191 | - assert( i<=ArraySize(az) ); | |
| 1191 | + assert( i<=count(az) ); | |
| 1192 | 1192 | } |
| 1193 | 1193 | if( i>2 ){ |
| 1194 | 1194 | style_submenu_multichoice("y", i/2, az, isDisabled); |
| 1195 | 1195 | } |
| 1196 | 1196 | } |
| @@ -1224,21 +1224,22 @@ | ||
| 1224 | 1224 | /* |
| 1225 | 1225 | ** WEBPAGE: timeline |
| 1226 | 1226 | ** |
| 1227 | 1227 | ** Query parameters: |
| 1228 | 1228 | ** |
| 1229 | -** a=TIMEORTAG after this event | |
| 1230 | -** b=TIMEORTAG before this event | |
| 1231 | -** c=TIMEORTAG "circa" this event | |
| 1232 | -** m=TIMEORTAG mark this event | |
| 1233 | -** n=COUNT suggested number of events in output | |
| 1234 | -** p=CHECKIN parents and ancestors of CHECKIN | |
| 1235 | -** d=CHECKIN descendants of CHECIN | |
| 1229 | +** a=TIMEORTAG After this event | |
| 1230 | +** b=TIMEORTAG Before this event | |
| 1231 | +** c=TIMEORTAG "Circa" this event | |
| 1232 | +** m=TIMEORTAG Mark this event | |
| 1233 | +** n=COUNT Suggested number of events in output | |
| 1234 | +** p=CHECKIN Parents and ancestors of CHECKIN | |
| 1235 | +** d=CHECKIN Descendants of CHECIN | |
| 1236 | 1236 | ** dp=CHECKIN The same as d=CHECKIN&p=CHECKIN |
| 1237 | -** t=TAG show only check-ins with the given TAG | |
| 1238 | -** r=TAG show check-ins related to TAG | |
| 1239 | -** u=USER only show items associated with USER | |
| 1237 | +** t=TAG Show only check-ins with the given TAG | |
| 1238 | +** r=TAG Show check-ins related to TAG | |
| 1239 | +** mionly Limit r=TAG to show ancestors but not descendants | |
| 1240 | +** u=USER Only show items associated with USER | |
| 1240 | 1241 | ** y=TYPE 'ci', 'w', 't', 'e', or (default) 'all' |
| 1241 | 1242 | ** ng No Graph. |
| 1242 | 1243 | ** nd Do not highlight the focus check-in |
| 1243 | 1244 | ** v Show details of files changed |
| 1244 | 1245 | ** f=CHECKIN Show family (immediate parents and children) of CHECKIN |
| @@ -1245,20 +1246,22 @@ | ||
| 1245 | 1246 | ** from=CHECKIN Path from... |
| 1246 | 1247 | ** to=CHECKIN ... to this |
| 1247 | 1248 | ** shortest ... show only the shortest path |
| 1248 | 1249 | ** uf=FILE_SHA1 Show only check-ins that contain the given file version |
| 1249 | 1250 | ** chng=GLOBLIST Show only check-ins that involve changes to a file whose |
| 1250 | -** name matches one of the comma-separate GLOBLIST. | |
| 1251 | +** name matches one of the comma-separate GLOBLIST | |
| 1251 | 1252 | ** brbg Background color from branch name |
| 1252 | 1253 | ** ubg Background color from user |
| 1253 | 1254 | ** namechng Show only check-ins that have filename changes |
| 1254 | 1255 | ** forks Show only forks and their children |
| 1255 | -** ym=YYYY-MM Show only events for the given year/month. | |
| 1256 | +** ym=YYYY-MM Show only events for the given year/month | |
| 1256 | 1257 | ** yw=YYYY-WW Show only events for the given week of the given year |
| 1257 | 1258 | ** ymd=YYYY-MM-DD Show only events on the given day |
| 1258 | 1259 | ** datefmt=N Override the date format |
| 1259 | 1260 | ** bisect Show the check-ins that are in the current bisect |
| 1261 | +** showid Show RIDs | |
| 1262 | +** showsql Show the SQL text | |
| 1260 | 1263 | ** |
| 1261 | 1264 | ** p= and d= can appear individually or together. If either p= or d= |
| 1262 | 1265 | ** appear, then u=, y=, a=, and b= are ignored. |
| 1263 | 1266 | ** |
| 1264 | 1267 | ** If both a= and b= appear then both upper and lower bounds are honored. |
| @@ -1342,17 +1345,15 @@ | ||
| 1342 | 1345 | url_initialize(&url, "timeline"); |
| 1343 | 1346 | cgi_query_parameters_to_url(&url); |
| 1344 | 1347 | if( zTagName && g.perm.Read ){ |
| 1345 | 1348 | tagid = db_int(-1,"SELECT tagid FROM tag WHERE tagname='sym-%q'",zTagName); |
| 1346 | 1349 | zThisTag = zTagName; |
| 1347 | - style_submenu_element("Related", "Related", "%s", | |
| 1348 | - url_render(&url, "r", zTagName, "t", 0)); | |
| 1350 | + timeline_submenu(&url, "Related", "r", zTagName, "t"); | |
| 1349 | 1351 | }else if( zBrName && g.perm.Read ){ |
| 1350 | 1352 | tagid = db_int(-1,"SELECT tagid FROM tag WHERE tagname='sym-%q'",zBrName); |
| 1351 | 1353 | zThisTag = zBrName; |
| 1352 | - style_submenu_element("Branch Only", "only", "%s", | |
| 1353 | - url_render(&url, "t", zBrName, "r", 0)); | |
| 1354 | + timeline_submenu(&url, "Branch Only", "t", zBrName, "r"); | |
| 1354 | 1355 | }else{ |
| 1355 | 1356 | tagid = 0; |
| 1356 | 1357 | } |
| 1357 | 1358 | if( zMark && zMark[0]==0 ){ |
| 1358 | 1359 | if( zAfter ) zMark = zAfter; |
| @@ -1478,12 +1479,11 @@ | ||
| 1478 | 1479 | blob_append(&sql, ")", -1); |
| 1479 | 1480 | path_reset(); |
| 1480 | 1481 | addFileGlobExclusion(zChng, &sql); |
| 1481 | 1482 | tmFlags |= TIMELINE_DISJOINT; |
| 1482 | 1483 | db_multi_exec("%s", blob_sql_text(&sql)); |
| 1483 | - style_submenu_binary("v","With Files","Without Files", | |
| 1484 | - zType[0]!='a' && zType[0]!='c'); | |
| 1484 | + style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c'); | |
| 1485 | 1485 | blob_appendf(&desc, "%d check-ins going from ", |
| 1486 | 1486 | db_int(0, "SELECT count(*) FROM timeline")); |
| 1487 | 1487 | blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h", zFrom), zFrom); |
| 1488 | 1488 | blob_append(&desc, " to ", -1); |
| 1489 | 1489 | blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h",zTo), zTo); |
| @@ -1529,14 +1529,13 @@ | ||
| 1529 | 1529 | if( p_rid ){ |
| 1530 | 1530 | /* If both p= and d= are set, we don't have the uuid of d yet. */ |
| 1531 | 1531 | zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", d_rid); |
| 1532 | 1532 | } |
| 1533 | 1533 | } |
| 1534 | + style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c'); | |
| 1534 | 1535 | style_submenu_entry("n","Max:",4,0); |
| 1535 | 1536 | timeline_y_submenu(1); |
| 1536 | - style_submenu_binary("v","With Files","Without Files", | |
| 1537 | - zType[0]!='a' && zType[0]!='c'); | |
| 1538 | 1537 | }else if( f_rid && g.perm.Read ){ |
| 1539 | 1538 | /* If f= is present, ignore all other parameters other than n= */ |
| 1540 | 1539 | char *zUuid; |
| 1541 | 1540 | db_multi_exec( |
| 1542 | 1541 | "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);" |
| @@ -1550,15 +1549,12 @@ | ||
| 1550 | 1549 | if( useDividers ) selectedRid = f_rid; |
| 1551 | 1550 | blob_appendf(&desc, "Parents and children of check-in "); |
| 1552 | 1551 | zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid); |
| 1553 | 1552 | blob_appendf(&desc, "%z[%S]</a>", href("%R/info/%!S", zUuid), zUuid); |
| 1554 | 1553 | tmFlags |= TIMELINE_DISJOINT; |
| 1555 | - style_submenu_binary("v","With Files","Without Files", | |
| 1556 | - zType[0]!='a' && zType[0]!='c'); | |
| 1557 | - if( (tmFlags & TIMELINE_UNHIDE)==0 ){ | |
| 1558 | - timeline_submenu(&url, "Unhide", "unhide", "", 0); | |
| 1559 | - } | |
| 1554 | + style_submenu_checkbox("unhide", "Unhide", 0); | |
| 1555 | + style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c'); | |
| 1560 | 1556 | }else{ |
| 1561 | 1557 | /* Otherwise, a timeline based on a span of time */ |
| 1562 | 1558 | int n; |
| 1563 | 1559 | const char *zEType = "timeline item"; |
| 1564 | 1560 | char *zDate; |
| @@ -1823,26 +1819,23 @@ | ||
| 1823 | 1819 | timeline_submenu(&url, "Newer", "a", zDate, "b"); |
| 1824 | 1820 | } |
| 1825 | 1821 | free(zDate); |
| 1826 | 1822 | } |
| 1827 | 1823 | if( zType[0]=='a' || zType[0]=='c' ){ |
| 1828 | - if( (tmFlags & TIMELINE_UNHIDE)==0 ){ | |
| 1829 | - timeline_submenu(&url, "Unhide", "unhide", "", 0); | |
| 1830 | - } | |
| 1824 | + style_submenu_checkbox("unhide", "Unhide", 0); | |
| 1831 | 1825 | } |
| 1826 | + style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c'); | |
| 1832 | 1827 | style_submenu_entry("n","Max:",4,0); |
| 1833 | 1828 | timeline_y_submenu(disableY); |
| 1834 | - style_submenu_binary("v","With Files","Without Files", | |
| 1835 | - zType[0]!='a' && zType[0]!='c'); | |
| 1836 | 1829 | } |
| 1837 | 1830 | blob_zero(&cond); |
| 1838 | 1831 | } |
| 1839 | 1832 | if( PB("showsql") ){ |
| 1840 | 1833 | @ <pre>%h(blob_sql_text(&sql))</pre> |
| 1841 | 1834 | } |
| 1842 | 1835 | if( search_restrict(SRCH_CKIN)!=0 ){ |
| 1843 | - style_submenu_element("Search", 0, "%R/search?y=c"); | |
| 1836 | + style_submenu_element("Search", "%R/search?y=c"); | |
| 1844 | 1837 | } |
| 1845 | 1838 | if( PB("showid") ) tmFlags |= TIMELINE_SHOWRID; |
| 1846 | 1839 | if( useDividers && zMark && zMark[0] ){ |
| 1847 | 1840 | double r = symbolic_name_to_mtime(zMark); |
| 1848 | 1841 | if( r>0.0 ) selectedRid = timeline_add_divider(r); |
| 1849 | 1842 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -390,11 +390,11 @@ | |
| 390 | "SELECT pid FROM plink" |
| 391 | " WHERE cid=:rid AND pid NOT IN phantom" |
| 392 | " ORDER BY isprim DESC /*sort*/" |
| 393 | ); |
| 394 | db_bind_int(&qparent, ":rid", rid); |
| 395 | while( db_step(&qparent)==SQLITE_ROW && nParent<ArraySize(aParent) ){ |
| 396 | aParent[nParent++] = db_column_int(&qparent, 0); |
| 397 | } |
| 398 | db_reset(&qparent); |
| 399 | gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr, |
| 400 | zUuid, isLeaf); |
| @@ -737,11 +737,11 @@ | |
| 737 | pRow->mergeOut, /* mo */ |
| 738 | pRow->mergeUpto, /* mu */ |
| 739 | pRow->aiRiser[pRow->iRail], /* u */ |
| 740 | pRow->isLeaf ? 1 : 0 /* f */ |
| 741 | ); |
| 742 | /* u */ |
| 743 | cSep = '['; |
| 744 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 745 | if( i==pRow->iRail ) continue; |
| 746 | if( pRow->aiRiser[i]>0 ){ |
| 747 | cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]); |
| @@ -757,11 +757,11 @@ | |
| 757 | cgi_printf("mi:"); |
| 758 | cSep = '['; |
| 759 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 760 | if( pRow->mergeIn[i] ){ |
| 761 | int mi = i; |
| 762 | if( pRow->mergeDown & (1<<i) ) mi = -mi; |
| 763 | cgi_printf("%c%d", cSep, mi); |
| 764 | cSep = ','; |
| 765 | } |
| 766 | } |
| 767 | if( cSep=='[' ) cgi_printf("["); |
| @@ -1083,11 +1083,11 @@ | |
| 1083 | const char *zMenuName, /* Submenu name */ |
| 1084 | const char *zParam, /* Parameter value to add or change */ |
| 1085 | const char *zValue, /* Value of the new parameter */ |
| 1086 | const char *zRemove /* Parameter to omit */ |
| 1087 | ){ |
| 1088 | style_submenu_element(zMenuName, zMenuName, "%s", |
| 1089 | url_render(pUrl, zParam, zValue, zRemove, 0)); |
| 1090 | } |
| 1091 | |
| 1092 | |
| 1093 | /* |
| @@ -1186,11 +1186,11 @@ | |
| 1186 | } |
| 1187 | if( g.perm.RdWiki ){ |
| 1188 | az[i++] = "w"; |
| 1189 | az[i++] = "Wiki"; |
| 1190 | } |
| 1191 | assert( i<=ArraySize(az) ); |
| 1192 | } |
| 1193 | if( i>2 ){ |
| 1194 | style_submenu_multichoice("y", i/2, az, isDisabled); |
| 1195 | } |
| 1196 | } |
| @@ -1224,21 +1224,22 @@ | |
| 1224 | /* |
| 1225 | ** WEBPAGE: timeline |
| 1226 | ** |
| 1227 | ** Query parameters: |
| 1228 | ** |
| 1229 | ** a=TIMEORTAG after this event |
| 1230 | ** b=TIMEORTAG before this event |
| 1231 | ** c=TIMEORTAG "circa" this event |
| 1232 | ** m=TIMEORTAG mark this event |
| 1233 | ** n=COUNT suggested number of events in output |
| 1234 | ** p=CHECKIN parents and ancestors of CHECKIN |
| 1235 | ** d=CHECKIN descendants of CHECIN |
| 1236 | ** dp=CHECKIN The same as d=CHECKIN&p=CHECKIN |
| 1237 | ** t=TAG show only check-ins with the given TAG |
| 1238 | ** r=TAG show check-ins related to TAG |
| 1239 | ** u=USER only show items associated with USER |
| 1240 | ** y=TYPE 'ci', 'w', 't', 'e', or (default) 'all' |
| 1241 | ** ng No Graph. |
| 1242 | ** nd Do not highlight the focus check-in |
| 1243 | ** v Show details of files changed |
| 1244 | ** f=CHECKIN Show family (immediate parents and children) of CHECKIN |
| @@ -1245,20 +1246,22 @@ | |
| 1245 | ** from=CHECKIN Path from... |
| 1246 | ** to=CHECKIN ... to this |
| 1247 | ** shortest ... show only the shortest path |
| 1248 | ** uf=FILE_SHA1 Show only check-ins that contain the given file version |
| 1249 | ** chng=GLOBLIST Show only check-ins that involve changes to a file whose |
| 1250 | ** name matches one of the comma-separate GLOBLIST. |
| 1251 | ** brbg Background color from branch name |
| 1252 | ** ubg Background color from user |
| 1253 | ** namechng Show only check-ins that have filename changes |
| 1254 | ** forks Show only forks and their children |
| 1255 | ** ym=YYYY-MM Show only events for the given year/month. |
| 1256 | ** yw=YYYY-WW Show only events for the given week of the given year |
| 1257 | ** ymd=YYYY-MM-DD Show only events on the given day |
| 1258 | ** datefmt=N Override the date format |
| 1259 | ** bisect Show the check-ins that are in the current bisect |
| 1260 | ** |
| 1261 | ** p= and d= can appear individually or together. If either p= or d= |
| 1262 | ** appear, then u=, y=, a=, and b= are ignored. |
| 1263 | ** |
| 1264 | ** If both a= and b= appear then both upper and lower bounds are honored. |
| @@ -1342,17 +1345,15 @@ | |
| 1342 | url_initialize(&url, "timeline"); |
| 1343 | cgi_query_parameters_to_url(&url); |
| 1344 | if( zTagName && g.perm.Read ){ |
| 1345 | tagid = db_int(-1,"SELECT tagid FROM tag WHERE tagname='sym-%q'",zTagName); |
| 1346 | zThisTag = zTagName; |
| 1347 | style_submenu_element("Related", "Related", "%s", |
| 1348 | url_render(&url, "r", zTagName, "t", 0)); |
| 1349 | }else if( zBrName && g.perm.Read ){ |
| 1350 | tagid = db_int(-1,"SELECT tagid FROM tag WHERE tagname='sym-%q'",zBrName); |
| 1351 | zThisTag = zBrName; |
| 1352 | style_submenu_element("Branch Only", "only", "%s", |
| 1353 | url_render(&url, "t", zBrName, "r", 0)); |
| 1354 | }else{ |
| 1355 | tagid = 0; |
| 1356 | } |
| 1357 | if( zMark && zMark[0]==0 ){ |
| 1358 | if( zAfter ) zMark = zAfter; |
| @@ -1478,12 +1479,11 @@ | |
| 1478 | blob_append(&sql, ")", -1); |
| 1479 | path_reset(); |
| 1480 | addFileGlobExclusion(zChng, &sql); |
| 1481 | tmFlags |= TIMELINE_DISJOINT; |
| 1482 | db_multi_exec("%s", blob_sql_text(&sql)); |
| 1483 | style_submenu_binary("v","With Files","Without Files", |
| 1484 | zType[0]!='a' && zType[0]!='c'); |
| 1485 | blob_appendf(&desc, "%d check-ins going from ", |
| 1486 | db_int(0, "SELECT count(*) FROM timeline")); |
| 1487 | blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h", zFrom), zFrom); |
| 1488 | blob_append(&desc, " to ", -1); |
| 1489 | blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h",zTo), zTo); |
| @@ -1529,14 +1529,13 @@ | |
| 1529 | if( p_rid ){ |
| 1530 | /* If both p= and d= are set, we don't have the uuid of d yet. */ |
| 1531 | zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", d_rid); |
| 1532 | } |
| 1533 | } |
| 1534 | style_submenu_entry("n","Max:",4,0); |
| 1535 | timeline_y_submenu(1); |
| 1536 | style_submenu_binary("v","With Files","Without Files", |
| 1537 | zType[0]!='a' && zType[0]!='c'); |
| 1538 | }else if( f_rid && g.perm.Read ){ |
| 1539 | /* If f= is present, ignore all other parameters other than n= */ |
| 1540 | char *zUuid; |
| 1541 | db_multi_exec( |
| 1542 | "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);" |
| @@ -1550,15 +1549,12 @@ | |
| 1550 | if( useDividers ) selectedRid = f_rid; |
| 1551 | blob_appendf(&desc, "Parents and children of check-in "); |
| 1552 | zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid); |
| 1553 | blob_appendf(&desc, "%z[%S]</a>", href("%R/info/%!S", zUuid), zUuid); |
| 1554 | tmFlags |= TIMELINE_DISJOINT; |
| 1555 | style_submenu_binary("v","With Files","Without Files", |
| 1556 | zType[0]!='a' && zType[0]!='c'); |
| 1557 | if( (tmFlags & TIMELINE_UNHIDE)==0 ){ |
| 1558 | timeline_submenu(&url, "Unhide", "unhide", "", 0); |
| 1559 | } |
| 1560 | }else{ |
| 1561 | /* Otherwise, a timeline based on a span of time */ |
| 1562 | int n; |
| 1563 | const char *zEType = "timeline item"; |
| 1564 | char *zDate; |
| @@ -1823,26 +1819,23 @@ | |
| 1823 | timeline_submenu(&url, "Newer", "a", zDate, "b"); |
| 1824 | } |
| 1825 | free(zDate); |
| 1826 | } |
| 1827 | if( zType[0]=='a' || zType[0]=='c' ){ |
| 1828 | if( (tmFlags & TIMELINE_UNHIDE)==0 ){ |
| 1829 | timeline_submenu(&url, "Unhide", "unhide", "", 0); |
| 1830 | } |
| 1831 | } |
| 1832 | style_submenu_entry("n","Max:",4,0); |
| 1833 | timeline_y_submenu(disableY); |
| 1834 | style_submenu_binary("v","With Files","Without Files", |
| 1835 | zType[0]!='a' && zType[0]!='c'); |
| 1836 | } |
| 1837 | blob_zero(&cond); |
| 1838 | } |
| 1839 | if( PB("showsql") ){ |
| 1840 | @ <pre>%h(blob_sql_text(&sql))</pre> |
| 1841 | } |
| 1842 | if( search_restrict(SRCH_CKIN)!=0 ){ |
| 1843 | style_submenu_element("Search", 0, "%R/search?y=c"); |
| 1844 | } |
| 1845 | if( PB("showid") ) tmFlags |= TIMELINE_SHOWRID; |
| 1846 | if( useDividers && zMark && zMark[0] ){ |
| 1847 | double r = symbolic_name_to_mtime(zMark); |
| 1848 | if( r>0.0 ) selectedRid = timeline_add_divider(r); |
| 1849 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -390,11 +390,11 @@ | |
| 390 | "SELECT pid FROM plink" |
| 391 | " WHERE cid=:rid AND pid NOT IN phantom" |
| 392 | " ORDER BY isprim DESC /*sort*/" |
| 393 | ); |
| 394 | db_bind_int(&qparent, ":rid", rid); |
| 395 | while( db_step(&qparent)==SQLITE_ROW && nParent<count(aParent) ){ |
| 396 | aParent[nParent++] = db_column_int(&qparent, 0); |
| 397 | } |
| 398 | db_reset(&qparent); |
| 399 | gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr, |
| 400 | zUuid, isLeaf); |
| @@ -737,11 +737,11 @@ | |
| 737 | pRow->mergeOut, /* mo */ |
| 738 | pRow->mergeUpto, /* mu */ |
| 739 | pRow->aiRiser[pRow->iRail], /* u */ |
| 740 | pRow->isLeaf ? 1 : 0 /* f */ |
| 741 | ); |
| 742 | /* au */ |
| 743 | cSep = '['; |
| 744 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 745 | if( i==pRow->iRail ) continue; |
| 746 | if( pRow->aiRiser[i]>0 ){ |
| 747 | cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]); |
| @@ -757,11 +757,11 @@ | |
| 757 | cgi_printf("mi:"); |
| 758 | cSep = '['; |
| 759 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 760 | if( pRow->mergeIn[i] ){ |
| 761 | int mi = i; |
| 762 | if( (pRow->mergeDown >> i) & 1 ) mi = -mi; |
| 763 | cgi_printf("%c%d", cSep, mi); |
| 764 | cSep = ','; |
| 765 | } |
| 766 | } |
| 767 | if( cSep=='[' ) cgi_printf("["); |
| @@ -1083,11 +1083,11 @@ | |
| 1083 | const char *zMenuName, /* Submenu name */ |
| 1084 | const char *zParam, /* Parameter value to add or change */ |
| 1085 | const char *zValue, /* Value of the new parameter */ |
| 1086 | const char *zRemove /* Parameter to omit */ |
| 1087 | ){ |
| 1088 | style_submenu_element(zMenuName, "%s", |
| 1089 | url_render(pUrl, zParam, zValue, zRemove, 0)); |
| 1090 | } |
| 1091 | |
| 1092 | |
| 1093 | /* |
| @@ -1186,11 +1186,11 @@ | |
| 1186 | } |
| 1187 | if( g.perm.RdWiki ){ |
| 1188 | az[i++] = "w"; |
| 1189 | az[i++] = "Wiki"; |
| 1190 | } |
| 1191 | assert( i<=count(az) ); |
| 1192 | } |
| 1193 | if( i>2 ){ |
| 1194 | style_submenu_multichoice("y", i/2, az, isDisabled); |
| 1195 | } |
| 1196 | } |
| @@ -1224,21 +1224,22 @@ | |
| 1224 | /* |
| 1225 | ** WEBPAGE: timeline |
| 1226 | ** |
| 1227 | ** Query parameters: |
| 1228 | ** |
| 1229 | ** a=TIMEORTAG After this event |
| 1230 | ** b=TIMEORTAG Before this event |
| 1231 | ** c=TIMEORTAG "Circa" this event |
| 1232 | ** m=TIMEORTAG Mark this event |
| 1233 | ** n=COUNT Suggested number of events in output |
| 1234 | ** p=CHECKIN Parents and ancestors of CHECKIN |
| 1235 | ** d=CHECKIN Descendants of CHECIN |
| 1236 | ** dp=CHECKIN The same as d=CHECKIN&p=CHECKIN |
| 1237 | ** t=TAG Show only check-ins with the given TAG |
| 1238 | ** r=TAG Show check-ins related to TAG |
| 1239 | ** mionly Limit r=TAG to show ancestors but not descendants |
| 1240 | ** u=USER Only show items associated with USER |
| 1241 | ** y=TYPE 'ci', 'w', 't', 'e', or (default) 'all' |
| 1242 | ** ng No Graph. |
| 1243 | ** nd Do not highlight the focus check-in |
| 1244 | ** v Show details of files changed |
| 1245 | ** f=CHECKIN Show family (immediate parents and children) of CHECKIN |
| @@ -1245,20 +1246,22 @@ | |
| 1246 | ** from=CHECKIN Path from... |
| 1247 | ** to=CHECKIN ... to this |
| 1248 | ** shortest ... show only the shortest path |
| 1249 | ** uf=FILE_SHA1 Show only check-ins that contain the given file version |
| 1250 | ** chng=GLOBLIST Show only check-ins that involve changes to a file whose |
| 1251 | ** name matches one of the comma-separate GLOBLIST |
| 1252 | ** brbg Background color from branch name |
| 1253 | ** ubg Background color from user |
| 1254 | ** namechng Show only check-ins that have filename changes |
| 1255 | ** forks Show only forks and their children |
| 1256 | ** ym=YYYY-MM Show only events for the given year/month |
| 1257 | ** yw=YYYY-WW Show only events for the given week of the given year |
| 1258 | ** ymd=YYYY-MM-DD Show only events on the given day |
| 1259 | ** datefmt=N Override the date format |
| 1260 | ** bisect Show the check-ins that are in the current bisect |
| 1261 | ** showid Show RIDs |
| 1262 | ** showsql Show the SQL text |
| 1263 | ** |
| 1264 | ** p= and d= can appear individually or together. If either p= or d= |
| 1265 | ** appear, then u=, y=, a=, and b= are ignored. |
| 1266 | ** |
| 1267 | ** If both a= and b= appear then both upper and lower bounds are honored. |
| @@ -1342,17 +1345,15 @@ | |
| 1345 | url_initialize(&url, "timeline"); |
| 1346 | cgi_query_parameters_to_url(&url); |
| 1347 | if( zTagName && g.perm.Read ){ |
| 1348 | tagid = db_int(-1,"SELECT tagid FROM tag WHERE tagname='sym-%q'",zTagName); |
| 1349 | zThisTag = zTagName; |
| 1350 | timeline_submenu(&url, "Related", "r", zTagName, "t"); |
| 1351 | }else if( zBrName && g.perm.Read ){ |
| 1352 | tagid = db_int(-1,"SELECT tagid FROM tag WHERE tagname='sym-%q'",zBrName); |
| 1353 | zThisTag = zBrName; |
| 1354 | timeline_submenu(&url, "Branch Only", "t", zBrName, "r"); |
| 1355 | }else{ |
| 1356 | tagid = 0; |
| 1357 | } |
| 1358 | if( zMark && zMark[0]==0 ){ |
| 1359 | if( zAfter ) zMark = zAfter; |
| @@ -1478,12 +1479,11 @@ | |
| 1479 | blob_append(&sql, ")", -1); |
| 1480 | path_reset(); |
| 1481 | addFileGlobExclusion(zChng, &sql); |
| 1482 | tmFlags |= TIMELINE_DISJOINT; |
| 1483 | db_multi_exec("%s", blob_sql_text(&sql)); |
| 1484 | style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c'); |
| 1485 | blob_appendf(&desc, "%d check-ins going from ", |
| 1486 | db_int(0, "SELECT count(*) FROM timeline")); |
| 1487 | blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h", zFrom), zFrom); |
| 1488 | blob_append(&desc, " to ", -1); |
| 1489 | blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h",zTo), zTo); |
| @@ -1529,14 +1529,13 @@ | |
| 1529 | if( p_rid ){ |
| 1530 | /* If both p= and d= are set, we don't have the uuid of d yet. */ |
| 1531 | zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", d_rid); |
| 1532 | } |
| 1533 | } |
| 1534 | style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c'); |
| 1535 | style_submenu_entry("n","Max:",4,0); |
| 1536 | timeline_y_submenu(1); |
| 1537 | }else if( f_rid && g.perm.Read ){ |
| 1538 | /* If f= is present, ignore all other parameters other than n= */ |
| 1539 | char *zUuid; |
| 1540 | db_multi_exec( |
| 1541 | "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);" |
| @@ -1550,15 +1549,12 @@ | |
| 1549 | if( useDividers ) selectedRid = f_rid; |
| 1550 | blob_appendf(&desc, "Parents and children of check-in "); |
| 1551 | zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid); |
| 1552 | blob_appendf(&desc, "%z[%S]</a>", href("%R/info/%!S", zUuid), zUuid); |
| 1553 | tmFlags |= TIMELINE_DISJOINT; |
| 1554 | style_submenu_checkbox("unhide", "Unhide", 0); |
| 1555 | style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c'); |
| 1556 | }else{ |
| 1557 | /* Otherwise, a timeline based on a span of time */ |
| 1558 | int n; |
| 1559 | const char *zEType = "timeline item"; |
| 1560 | char *zDate; |
| @@ -1823,26 +1819,23 @@ | |
| 1819 | timeline_submenu(&url, "Newer", "a", zDate, "b"); |
| 1820 | } |
| 1821 | free(zDate); |
| 1822 | } |
| 1823 | if( zType[0]=='a' || zType[0]=='c' ){ |
| 1824 | style_submenu_checkbox("unhide", "Unhide", 0); |
| 1825 | } |
| 1826 | style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c'); |
| 1827 | style_submenu_entry("n","Max:",4,0); |
| 1828 | timeline_y_submenu(disableY); |
| 1829 | } |
| 1830 | blob_zero(&cond); |
| 1831 | } |
| 1832 | if( PB("showsql") ){ |
| 1833 | @ <pre>%h(blob_sql_text(&sql))</pre> |
| 1834 | } |
| 1835 | if( search_restrict(SRCH_CKIN)!=0 ){ |
| 1836 | style_submenu_element("Search", "%R/search?y=c"); |
| 1837 | } |
| 1838 | if( PB("showid") ) tmFlags |= TIMELINE_SHOWRID; |
| 1839 | if( useDividers && zMark && zMark[0] ){ |
| 1840 | double r = symbolic_name_to_mtime(zMark); |
| 1841 | if( r>0.0 ) selectedRid = timeline_add_divider(r); |
| 1842 |
+36
-44
| --- src/tkt.c | ||
| +++ src/tkt.c | ||
| @@ -216,20 +216,25 @@ | ||
| 216 | 216 | const char *zBaseName = zName[0]=='+' ? zName+1 : zName; |
| 217 | 217 | j = fieldId(zBaseName); |
| 218 | 218 | if( j<0 ) continue; |
| 219 | 219 | aUsed[j] = 1; |
| 220 | 220 | if( aField[j].mUsed & USEDBY_TICKET ){ |
| 221 | - if( zName[0]=='+' ){ | |
| 222 | - zName++; | |
| 221 | + const char *zUsedByName = zName; | |
| 222 | + if( zUsedByName[0]=='+' ){ | |
| 223 | + zUsedByName++; | |
| 223 | 224 | blob_append_sql(&sql1,", \"%w\"=coalesce(\"%w\",'') || %Q", |
| 224 | - zName, zName, p->aField[i].zValue); | |
| 225 | + zUsedByName, zUsedByName, p->aField[i].zValue); | |
| 225 | 226 | }else{ |
| 226 | - blob_append_sql(&sql1,", \"%w\"=%Q", zName, p->aField[i].zValue); | |
| 227 | + blob_append_sql(&sql1,", \"%w\"=%Q", zUsedByName, p->aField[i].zValue); | |
| 227 | 228 | } |
| 228 | 229 | } |
| 229 | 230 | if( aField[j].mUsed & USEDBY_TICKETCHNG ){ |
| 230 | - blob_append_sql(&sql2, ",\"%w\"", zName); | |
| 231 | + const char *zUsedByName = zName; | |
| 232 | + if( zUsedByName[0]=='+' ){ | |
| 233 | + zUsedByName++; | |
| 234 | + } | |
| 235 | + blob_append_sql(&sql2, ",\"%w\"", zUsedByName); | |
| 231 | 236 | blob_append_sql(&sql3, ",%Q", p->aField[i].zValue); |
| 232 | 237 | } |
| 233 | 238 | if( rid>0 ){ |
| 234 | 239 | wiki_extract_links(p->aField[i].zValue, rid, 1, p->rDate, i==0, 0); |
| 235 | 240 | } |
| @@ -451,35 +456,28 @@ | ||
| 451 | 456 | const char *zUuid = PD("name",""); |
| 452 | 457 | |
| 453 | 458 | login_check_credentials(); |
| 454 | 459 | if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; } |
| 455 | 460 | if( g.anon.WrTkt || g.anon.ApndTkt ){ |
| 456 | - style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T", | |
| 457 | - g.zTop, PD("name","")); | |
| 461 | + style_submenu_element("Edit", "%s/tktedit?name=%T", g.zTop, PD("name","")); | |
| 458 | 462 | } |
| 459 | 463 | if( g.perm.Hyperlink ){ |
| 460 | - style_submenu_element("History", "History Of This Ticket", | |
| 461 | - "%s/tkthistory/%T", g.zTop, zUuid); | |
| 462 | - style_submenu_element("Timeline", "Timeline Of This Ticket", | |
| 463 | - "%s/tkttimeline/%T", g.zTop, zUuid); | |
| 464 | - style_submenu_element("Check-ins", "Check-ins Of This Ticket", | |
| 465 | - "%s/tkttimeline/%T?y=ci", g.zTop, zUuid); | |
| 464 | + style_submenu_element("History", "%s/tkthistory/%T", g.zTop, zUuid); | |
| 465 | + style_submenu_element("Timeline", "%s/tkttimeline/%T", g.zTop, zUuid); | |
| 466 | + style_submenu_element("Check-ins", "%s/tkttimeline/%T?y=ci", g.zTop, zUuid); | |
| 466 | 467 | } |
| 467 | 468 | if( g.anon.NewTkt ){ |
| 468 | - style_submenu_element("New Ticket", "Create a new ticket", | |
| 469 | - "%s/tktnew", g.zTop); | |
| 469 | + style_submenu_element("New Ticket", "%s/tktnew", g.zTop); | |
| 470 | 470 | } |
| 471 | 471 | if( g.anon.ApndTkt && g.anon.Attach ){ |
| 472 | - style_submenu_element("Attach", "Add An Attachment", | |
| 473 | - "%s/attachadd?tkt=%T&from=%s/tktview/%t", | |
| 472 | + style_submenu_element("Attach", "%s/attachadd?tkt=%T&from=%s/tktview/%t", | |
| 474 | 473 | g.zTop, zUuid, g.zTop, zUuid); |
| 475 | 474 | } |
| 476 | 475 | if( P("plaintext") ){ |
| 477 | - style_submenu_element("Formatted", "Formatted", "%R/tktview/%s", zUuid); | |
| 476 | + style_submenu_element("Formatted", "%R/tktview/%s", zUuid); | |
| 478 | 477 | }else{ |
| 479 | - style_submenu_element("Plaintext", "Plaintext", | |
| 480 | - "%R/tktview/%s?plaintext", zUuid); | |
| 478 | + style_submenu_element("Plaintext", "%R/tktview/%s?plaintext", zUuid); | |
| 481 | 479 | } |
| 482 | 480 | style_header("View Ticket"); |
| 483 | 481 | if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br />\n", -1); |
| 484 | 482 | ticket_init(); |
| 485 | 483 | initializeVariablesFromCGI(); |
| @@ -546,11 +544,13 @@ | ||
| 546 | 544 | Blob *pTicket, /* The text of the ticket change record */ |
| 547 | 545 | const char *zTktId, /* The ticket to which this change is applied */ |
| 548 | 546 | int needMod /* True if moderation is needed */ |
| 549 | 547 | ){ |
| 550 | 548 | int result; |
| 551 | - int rid = content_put_ex(pTicket, 0, 0, 0, needMod); | |
| 549 | + int rid; | |
| 550 | + manifest_crosslink_begin(); | |
| 551 | + rid = content_put_ex(pTicket, 0, 0, 0, needMod); | |
| 552 | 552 | if( rid==0 ){ |
| 553 | 553 | fossil_fatal("trouble committing ticket: %s", g.zErrMsg); |
| 554 | 554 | } |
| 555 | 555 | if( needMod ){ |
| 556 | 556 | moderation_table_create(); |
| @@ -560,11 +560,10 @@ | ||
| 560 | 560 | ); |
| 561 | 561 | }else{ |
| 562 | 562 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d);", rid); |
| 563 | 563 | db_multi_exec("INSERT OR IGNORE INTO unclustered VALUES(%d);", rid); |
| 564 | 564 | } |
| 565 | - manifest_crosslink_begin(); | |
| 566 | 565 | result = (manifest_crosslink(rid, pTicket, MC_NONE)==0); |
| 567 | 566 | assert( blob_is_reset(pTicket) ); |
| 568 | 567 | if( !result ){ |
| 569 | 568 | result = manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 570 | 569 | }else{ |
| @@ -850,20 +849,17 @@ | ||
| 850 | 849 | return; |
| 851 | 850 | } |
| 852 | 851 | zUuid = PD("name",""); |
| 853 | 852 | zType = PD("y","a"); |
| 854 | 853 | if( zType[0]!='c' ){ |
| 855 | - style_submenu_element("Check-ins", "Check-ins", | |
| 856 | - "%s/tkttimeline?name=%T&y=ci", g.zTop, zUuid); | |
| 854 | + style_submenu_element("Check-ins", "%s/tkttimeline?name=%T&y=ci", | |
| 855 | + g.zTop, zUuid); | |
| 857 | 856 | }else{ |
| 858 | - style_submenu_element("Timeline", "Timeline", | |
| 859 | - "%s/tkttimeline?name=%T", g.zTop, zUuid); | |
| 857 | + style_submenu_element("Timeline", "%s/tkttimeline?name=%T", g.zTop, zUuid); | |
| 860 | 858 | } |
| 861 | - style_submenu_element("History", "History", | |
| 862 | - "%s/tkthistory/%s", g.zTop, zUuid); | |
| 863 | - style_submenu_element("Status", "Status", | |
| 864 | - "%s/info/%s", g.zTop, zUuid); | |
| 859 | + style_submenu_element("History", "%s/tkthistory/%s", g.zTop, zUuid); | |
| 860 | + style_submenu_element("Status", "%s/info/%s", g.zTop, zUuid); | |
| 865 | 861 | if( zType[0]=='c' ){ |
| 866 | 862 | zTitle = mprintf("Check-ins Associated With Ticket %h", zUuid); |
| 867 | 863 | }else{ |
| 868 | 864 | zTitle = mprintf("Timeline Of Ticket %h", zUuid); |
| 869 | 865 | } |
| @@ -925,22 +921,18 @@ | ||
| 925 | 921 | login_needed(g.anon.Hyperlink && g.anon.RdTkt); |
| 926 | 922 | return; |
| 927 | 923 | } |
| 928 | 924 | zUuid = PD("name",""); |
| 929 | 925 | zTitle = mprintf("History Of Ticket %h", zUuid); |
| 930 | - style_submenu_element("Status", "Status", | |
| 931 | - "%s/info/%s", g.zTop, zUuid); | |
| 932 | - style_submenu_element("Check-ins", "Check-ins", | |
| 933 | - "%s/tkttimeline?name=%s&y=ci", g.zTop, zUuid); | |
| 934 | - style_submenu_element("Timeline", "Timeline", | |
| 935 | - "%s/tkttimeline?name=%s", g.zTop, zUuid); | |
| 926 | + style_submenu_element("Status", "%s/info/%s", g.zTop, zUuid); | |
| 927 | + style_submenu_element("Check-ins", "%s/tkttimeline?name=%s&y=ci", | |
| 928 | + g.zTop, zUuid); | |
| 929 | + style_submenu_element("Timeline", "%s/tkttimeline?name=%s", g.zTop, zUuid); | |
| 936 | 930 | if( P("plaintext")!=0 ){ |
| 937 | - style_submenu_element("Formatted", "Formatted", | |
| 938 | - "%R/tkthistory/%s", zUuid); | |
| 931 | + style_submenu_element("Formatted", "%R/tkthistory/%s", zUuid); | |
| 939 | 932 | }else{ |
| 940 | - style_submenu_element("Plaintext", "Plaintext", | |
| 941 | - "%R/tkthistory/%s?plaintext", zUuid); | |
| 933 | + style_submenu_element("Plaintext", "%R/tkthistory/%s?plaintext", zUuid); | |
| 942 | 934 | } |
| 943 | 935 | style_header("%z", zTitle); |
| 944 | 936 | |
| 945 | 937 | tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid); |
| 946 | 938 | if( tagid==0 ){ |
| @@ -1386,11 +1378,11 @@ | ||
| 1386 | 1378 | blob_appendf(&tktchng, "K %s\n", zTktUuid); |
| 1387 | 1379 | blob_appendf(&tktchng, "U %F\n", zUser); |
| 1388 | 1380 | md5sum_blob(&tktchng, &cksum); |
| 1389 | 1381 | blob_appendf(&tktchng, "Z %b\n", &cksum); |
| 1390 | 1382 | if( ticket_put(&tktchng, zTktUuid, ticket_need_moderation(1)) ){ |
| 1391 | - fossil_fatal("%s\n", g.zErrMsg); | |
| 1383 | + fossil_fatal("%s", g.zErrMsg); | |
| 1392 | 1384 | }else{ |
| 1393 | 1385 | fossil_print("ticket %s succeeded for %s\n", |
| 1394 | 1386 | (eCmd==set?"set":"add"),zTktUuid); |
| 1395 | 1387 | } |
| 1396 | 1388 | } |
| @@ -1410,17 +1402,17 @@ | ||
| 1410 | 1402 | /* |
| 1411 | 1403 | ** Add some standard submenu elements for ticket screens. |
| 1412 | 1404 | */ |
| 1413 | 1405 | void ticket_standard_submenu(unsigned int ok){ |
| 1414 | 1406 | if( (ok & T_SRCH)!=0 && search_restrict(SRCH_TKT)!=0 ){ |
| 1415 | - style_submenu_element("Search","Search","%R/tktsrch"); | |
| 1407 | + style_submenu_element("Search", "%R/tktsrch"); | |
| 1416 | 1408 | } |
| 1417 | 1409 | if( (ok & T_REPLIST)!=0 ){ |
| 1418 | - style_submenu_element("Reports","Reports","%R/reportlist"); | |
| 1410 | + style_submenu_element("Reports", "%R/reportlist"); | |
| 1419 | 1411 | } |
| 1420 | 1412 | if( (ok & T_NEW)!=0 && g.anon.NewTkt ){ |
| 1421 | - style_submenu_element("New","New","%R/tktnew"); | |
| 1413 | + style_submenu_element("New", "%R/tktnew"); | |
| 1422 | 1414 | } |
| 1423 | 1415 | } |
| 1424 | 1416 | |
| 1425 | 1417 | /* |
| 1426 | 1418 | ** WEBPAGE: ticket |
| 1427 | 1419 |
| --- src/tkt.c | |
| +++ src/tkt.c | |
| @@ -216,20 +216,25 @@ | |
| 216 | const char *zBaseName = zName[0]=='+' ? zName+1 : zName; |
| 217 | j = fieldId(zBaseName); |
| 218 | if( j<0 ) continue; |
| 219 | aUsed[j] = 1; |
| 220 | if( aField[j].mUsed & USEDBY_TICKET ){ |
| 221 | if( zName[0]=='+' ){ |
| 222 | zName++; |
| 223 | blob_append_sql(&sql1,", \"%w\"=coalesce(\"%w\",'') || %Q", |
| 224 | zName, zName, p->aField[i].zValue); |
| 225 | }else{ |
| 226 | blob_append_sql(&sql1,", \"%w\"=%Q", zName, p->aField[i].zValue); |
| 227 | } |
| 228 | } |
| 229 | if( aField[j].mUsed & USEDBY_TICKETCHNG ){ |
| 230 | blob_append_sql(&sql2, ",\"%w\"", zName); |
| 231 | blob_append_sql(&sql3, ",%Q", p->aField[i].zValue); |
| 232 | } |
| 233 | if( rid>0 ){ |
| 234 | wiki_extract_links(p->aField[i].zValue, rid, 1, p->rDate, i==0, 0); |
| 235 | } |
| @@ -451,35 +456,28 @@ | |
| 451 | const char *zUuid = PD("name",""); |
| 452 | |
| 453 | login_check_credentials(); |
| 454 | if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; } |
| 455 | if( g.anon.WrTkt || g.anon.ApndTkt ){ |
| 456 | style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T", |
| 457 | g.zTop, PD("name","")); |
| 458 | } |
| 459 | if( g.perm.Hyperlink ){ |
| 460 | style_submenu_element("History", "History Of This Ticket", |
| 461 | "%s/tkthistory/%T", g.zTop, zUuid); |
| 462 | style_submenu_element("Timeline", "Timeline Of This Ticket", |
| 463 | "%s/tkttimeline/%T", g.zTop, zUuid); |
| 464 | style_submenu_element("Check-ins", "Check-ins Of This Ticket", |
| 465 | "%s/tkttimeline/%T?y=ci", g.zTop, zUuid); |
| 466 | } |
| 467 | if( g.anon.NewTkt ){ |
| 468 | style_submenu_element("New Ticket", "Create a new ticket", |
| 469 | "%s/tktnew", g.zTop); |
| 470 | } |
| 471 | if( g.anon.ApndTkt && g.anon.Attach ){ |
| 472 | style_submenu_element("Attach", "Add An Attachment", |
| 473 | "%s/attachadd?tkt=%T&from=%s/tktview/%t", |
| 474 | g.zTop, zUuid, g.zTop, zUuid); |
| 475 | } |
| 476 | if( P("plaintext") ){ |
| 477 | style_submenu_element("Formatted", "Formatted", "%R/tktview/%s", zUuid); |
| 478 | }else{ |
| 479 | style_submenu_element("Plaintext", "Plaintext", |
| 480 | "%R/tktview/%s?plaintext", zUuid); |
| 481 | } |
| 482 | style_header("View Ticket"); |
| 483 | if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br />\n", -1); |
| 484 | ticket_init(); |
| 485 | initializeVariablesFromCGI(); |
| @@ -546,11 +544,13 @@ | |
| 546 | Blob *pTicket, /* The text of the ticket change record */ |
| 547 | const char *zTktId, /* The ticket to which this change is applied */ |
| 548 | int needMod /* True if moderation is needed */ |
| 549 | ){ |
| 550 | int result; |
| 551 | int rid = content_put_ex(pTicket, 0, 0, 0, needMod); |
| 552 | if( rid==0 ){ |
| 553 | fossil_fatal("trouble committing ticket: %s", g.zErrMsg); |
| 554 | } |
| 555 | if( needMod ){ |
| 556 | moderation_table_create(); |
| @@ -560,11 +560,10 @@ | |
| 560 | ); |
| 561 | }else{ |
| 562 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d);", rid); |
| 563 | db_multi_exec("INSERT OR IGNORE INTO unclustered VALUES(%d);", rid); |
| 564 | } |
| 565 | manifest_crosslink_begin(); |
| 566 | result = (manifest_crosslink(rid, pTicket, MC_NONE)==0); |
| 567 | assert( blob_is_reset(pTicket) ); |
| 568 | if( !result ){ |
| 569 | result = manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 570 | }else{ |
| @@ -850,20 +849,17 @@ | |
| 850 | return; |
| 851 | } |
| 852 | zUuid = PD("name",""); |
| 853 | zType = PD("y","a"); |
| 854 | if( zType[0]!='c' ){ |
| 855 | style_submenu_element("Check-ins", "Check-ins", |
| 856 | "%s/tkttimeline?name=%T&y=ci", g.zTop, zUuid); |
| 857 | }else{ |
| 858 | style_submenu_element("Timeline", "Timeline", |
| 859 | "%s/tkttimeline?name=%T", g.zTop, zUuid); |
| 860 | } |
| 861 | style_submenu_element("History", "History", |
| 862 | "%s/tkthistory/%s", g.zTop, zUuid); |
| 863 | style_submenu_element("Status", "Status", |
| 864 | "%s/info/%s", g.zTop, zUuid); |
| 865 | if( zType[0]=='c' ){ |
| 866 | zTitle = mprintf("Check-ins Associated With Ticket %h", zUuid); |
| 867 | }else{ |
| 868 | zTitle = mprintf("Timeline Of Ticket %h", zUuid); |
| 869 | } |
| @@ -925,22 +921,18 @@ | |
| 925 | login_needed(g.anon.Hyperlink && g.anon.RdTkt); |
| 926 | return; |
| 927 | } |
| 928 | zUuid = PD("name",""); |
| 929 | zTitle = mprintf("History Of Ticket %h", zUuid); |
| 930 | style_submenu_element("Status", "Status", |
| 931 | "%s/info/%s", g.zTop, zUuid); |
| 932 | style_submenu_element("Check-ins", "Check-ins", |
| 933 | "%s/tkttimeline?name=%s&y=ci", g.zTop, zUuid); |
| 934 | style_submenu_element("Timeline", "Timeline", |
| 935 | "%s/tkttimeline?name=%s", g.zTop, zUuid); |
| 936 | if( P("plaintext")!=0 ){ |
| 937 | style_submenu_element("Formatted", "Formatted", |
| 938 | "%R/tkthistory/%s", zUuid); |
| 939 | }else{ |
| 940 | style_submenu_element("Plaintext", "Plaintext", |
| 941 | "%R/tkthistory/%s?plaintext", zUuid); |
| 942 | } |
| 943 | style_header("%z", zTitle); |
| 944 | |
| 945 | tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid); |
| 946 | if( tagid==0 ){ |
| @@ -1386,11 +1378,11 @@ | |
| 1386 | blob_appendf(&tktchng, "K %s\n", zTktUuid); |
| 1387 | blob_appendf(&tktchng, "U %F\n", zUser); |
| 1388 | md5sum_blob(&tktchng, &cksum); |
| 1389 | blob_appendf(&tktchng, "Z %b\n", &cksum); |
| 1390 | if( ticket_put(&tktchng, zTktUuid, ticket_need_moderation(1)) ){ |
| 1391 | fossil_fatal("%s\n", g.zErrMsg); |
| 1392 | }else{ |
| 1393 | fossil_print("ticket %s succeeded for %s\n", |
| 1394 | (eCmd==set?"set":"add"),zTktUuid); |
| 1395 | } |
| 1396 | } |
| @@ -1410,17 +1402,17 @@ | |
| 1410 | /* |
| 1411 | ** Add some standard submenu elements for ticket screens. |
| 1412 | */ |
| 1413 | void ticket_standard_submenu(unsigned int ok){ |
| 1414 | if( (ok & T_SRCH)!=0 && search_restrict(SRCH_TKT)!=0 ){ |
| 1415 | style_submenu_element("Search","Search","%R/tktsrch"); |
| 1416 | } |
| 1417 | if( (ok & T_REPLIST)!=0 ){ |
| 1418 | style_submenu_element("Reports","Reports","%R/reportlist"); |
| 1419 | } |
| 1420 | if( (ok & T_NEW)!=0 && g.anon.NewTkt ){ |
| 1421 | style_submenu_element("New","New","%R/tktnew"); |
| 1422 | } |
| 1423 | } |
| 1424 | |
| 1425 | /* |
| 1426 | ** WEBPAGE: ticket |
| 1427 |
| --- src/tkt.c | |
| +++ src/tkt.c | |
| @@ -216,20 +216,25 @@ | |
| 216 | const char *zBaseName = zName[0]=='+' ? zName+1 : zName; |
| 217 | j = fieldId(zBaseName); |
| 218 | if( j<0 ) continue; |
| 219 | aUsed[j] = 1; |
| 220 | if( aField[j].mUsed & USEDBY_TICKET ){ |
| 221 | const char *zUsedByName = zName; |
| 222 | if( zUsedByName[0]=='+' ){ |
| 223 | zUsedByName++; |
| 224 | blob_append_sql(&sql1,", \"%w\"=coalesce(\"%w\",'') || %Q", |
| 225 | zUsedByName, zUsedByName, p->aField[i].zValue); |
| 226 | }else{ |
| 227 | blob_append_sql(&sql1,", \"%w\"=%Q", zUsedByName, p->aField[i].zValue); |
| 228 | } |
| 229 | } |
| 230 | if( aField[j].mUsed & USEDBY_TICKETCHNG ){ |
| 231 | const char *zUsedByName = zName; |
| 232 | if( zUsedByName[0]=='+' ){ |
| 233 | zUsedByName++; |
| 234 | } |
| 235 | blob_append_sql(&sql2, ",\"%w\"", zUsedByName); |
| 236 | blob_append_sql(&sql3, ",%Q", p->aField[i].zValue); |
| 237 | } |
| 238 | if( rid>0 ){ |
| 239 | wiki_extract_links(p->aField[i].zValue, rid, 1, p->rDate, i==0, 0); |
| 240 | } |
| @@ -451,35 +456,28 @@ | |
| 456 | const char *zUuid = PD("name",""); |
| 457 | |
| 458 | login_check_credentials(); |
| 459 | if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; } |
| 460 | if( g.anon.WrTkt || g.anon.ApndTkt ){ |
| 461 | style_submenu_element("Edit", "%s/tktedit?name=%T", g.zTop, PD("name","")); |
| 462 | } |
| 463 | if( g.perm.Hyperlink ){ |
| 464 | style_submenu_element("History", "%s/tkthistory/%T", g.zTop, zUuid); |
| 465 | style_submenu_element("Timeline", "%s/tkttimeline/%T", g.zTop, zUuid); |
| 466 | style_submenu_element("Check-ins", "%s/tkttimeline/%T?y=ci", g.zTop, zUuid); |
| 467 | } |
| 468 | if( g.anon.NewTkt ){ |
| 469 | style_submenu_element("New Ticket", "%s/tktnew", g.zTop); |
| 470 | } |
| 471 | if( g.anon.ApndTkt && g.anon.Attach ){ |
| 472 | style_submenu_element("Attach", "%s/attachadd?tkt=%T&from=%s/tktview/%t", |
| 473 | g.zTop, zUuid, g.zTop, zUuid); |
| 474 | } |
| 475 | if( P("plaintext") ){ |
| 476 | style_submenu_element("Formatted", "%R/tktview/%s", zUuid); |
| 477 | }else{ |
| 478 | style_submenu_element("Plaintext", "%R/tktview/%s?plaintext", zUuid); |
| 479 | } |
| 480 | style_header("View Ticket"); |
| 481 | if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br />\n", -1); |
| 482 | ticket_init(); |
| 483 | initializeVariablesFromCGI(); |
| @@ -546,11 +544,13 @@ | |
| 544 | Blob *pTicket, /* The text of the ticket change record */ |
| 545 | const char *zTktId, /* The ticket to which this change is applied */ |
| 546 | int needMod /* True if moderation is needed */ |
| 547 | ){ |
| 548 | int result; |
| 549 | int rid; |
| 550 | manifest_crosslink_begin(); |
| 551 | rid = content_put_ex(pTicket, 0, 0, 0, needMod); |
| 552 | if( rid==0 ){ |
| 553 | fossil_fatal("trouble committing ticket: %s", g.zErrMsg); |
| 554 | } |
| 555 | if( needMod ){ |
| 556 | moderation_table_create(); |
| @@ -560,11 +560,10 @@ | |
| 560 | ); |
| 561 | }else{ |
| 562 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d);", rid); |
| 563 | db_multi_exec("INSERT OR IGNORE INTO unclustered VALUES(%d);", rid); |
| 564 | } |
| 565 | result = (manifest_crosslink(rid, pTicket, MC_NONE)==0); |
| 566 | assert( blob_is_reset(pTicket) ); |
| 567 | if( !result ){ |
| 568 | result = manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 569 | }else{ |
| @@ -850,20 +849,17 @@ | |
| 849 | return; |
| 850 | } |
| 851 | zUuid = PD("name",""); |
| 852 | zType = PD("y","a"); |
| 853 | if( zType[0]!='c' ){ |
| 854 | style_submenu_element("Check-ins", "%s/tkttimeline?name=%T&y=ci", |
| 855 | g.zTop, zUuid); |
| 856 | }else{ |
| 857 | style_submenu_element("Timeline", "%s/tkttimeline?name=%T", g.zTop, zUuid); |
| 858 | } |
| 859 | style_submenu_element("History", "%s/tkthistory/%s", g.zTop, zUuid); |
| 860 | style_submenu_element("Status", "%s/info/%s", g.zTop, zUuid); |
| 861 | if( zType[0]=='c' ){ |
| 862 | zTitle = mprintf("Check-ins Associated With Ticket %h", zUuid); |
| 863 | }else{ |
| 864 | zTitle = mprintf("Timeline Of Ticket %h", zUuid); |
| 865 | } |
| @@ -925,22 +921,18 @@ | |
| 921 | login_needed(g.anon.Hyperlink && g.anon.RdTkt); |
| 922 | return; |
| 923 | } |
| 924 | zUuid = PD("name",""); |
| 925 | zTitle = mprintf("History Of Ticket %h", zUuid); |
| 926 | style_submenu_element("Status", "%s/info/%s", g.zTop, zUuid); |
| 927 | style_submenu_element("Check-ins", "%s/tkttimeline?name=%s&y=ci", |
| 928 | g.zTop, zUuid); |
| 929 | style_submenu_element("Timeline", "%s/tkttimeline?name=%s", g.zTop, zUuid); |
| 930 | if( P("plaintext")!=0 ){ |
| 931 | style_submenu_element("Formatted", "%R/tkthistory/%s", zUuid); |
| 932 | }else{ |
| 933 | style_submenu_element("Plaintext", "%R/tkthistory/%s?plaintext", zUuid); |
| 934 | } |
| 935 | style_header("%z", zTitle); |
| 936 | |
| 937 | tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid); |
| 938 | if( tagid==0 ){ |
| @@ -1386,11 +1378,11 @@ | |
| 1378 | blob_appendf(&tktchng, "K %s\n", zTktUuid); |
| 1379 | blob_appendf(&tktchng, "U %F\n", zUser); |
| 1380 | md5sum_blob(&tktchng, &cksum); |
| 1381 | blob_appendf(&tktchng, "Z %b\n", &cksum); |
| 1382 | if( ticket_put(&tktchng, zTktUuid, ticket_need_moderation(1)) ){ |
| 1383 | fossil_fatal("%s", g.zErrMsg); |
| 1384 | }else{ |
| 1385 | fossil_print("ticket %s succeeded for %s\n", |
| 1386 | (eCmd==set?"set":"add"),zTktUuid); |
| 1387 | } |
| 1388 | } |
| @@ -1410,17 +1402,17 @@ | |
| 1402 | /* |
| 1403 | ** Add some standard submenu elements for ticket screens. |
| 1404 | */ |
| 1405 | void ticket_standard_submenu(unsigned int ok){ |
| 1406 | if( (ok & T_SRCH)!=0 && search_restrict(SRCH_TKT)!=0 ){ |
| 1407 | style_submenu_element("Search", "%R/tktsrch"); |
| 1408 | } |
| 1409 | if( (ok & T_REPLIST)!=0 ){ |
| 1410 | style_submenu_element("Reports", "%R/reportlist"); |
| 1411 | } |
| 1412 | if( (ok & T_NEW)!=0 && g.anon.NewTkt ){ |
| 1413 | style_submenu_element("New", "%R/tktnew"); |
| 1414 | } |
| 1415 | } |
| 1416 | |
| 1417 | /* |
| 1418 | ** WEBPAGE: ticket |
| 1419 |
+13
-2
| --- src/translate.c | ||
| +++ src/translate.c | ||
| @@ -46,10 +46,15 @@ | ||
| 46 | 46 | ** cause CC to become a comment character for the @-substitution. |
| 47 | 47 | ** Typical values for CC are "--" (for SQL text) or "#" (for Tcl script) |
| 48 | 48 | ** or "//" (for C++ code). Lines of subsequent @-blocks that begin with |
| 49 | 49 | ** CC are omitted from the output. |
| 50 | 50 | ** |
| 51 | +** Enhancement #3: | |
| 52 | +** | |
| 53 | +** If a non-enhancement #1 line ends in backslash, the backslash and the | |
| 54 | +** newline (\n) are not included in the argument to cgi_printf(). This | |
| 55 | +** is used to split one long output line across multiple source lines. | |
| 51 | 56 | */ |
| 52 | 57 | #include <stdio.h> |
| 53 | 58 | #include <ctype.h> |
| 54 | 59 | #include <stdlib.h> |
| 55 | 60 | #include <string.h> |
| @@ -141,17 +146,23 @@ | ||
| 141 | 146 | ** a cgi_printf() statement whose format is the text following the '@'. |
| 142 | 147 | ** Substrings of the form "%C(...)" (where C is any sequence of |
| 143 | 148 | ** characters other than \000 and '(') will put "%C" in the |
| 144 | 149 | ** format and add the "(...)" as an argument to the cgi_printf call. |
| 145 | 150 | */ |
| 151 | + const char *zNewline = "\\n"; | |
| 146 | 152 | int indent; |
| 147 | 153 | int nC; |
| 148 | 154 | char c; |
| 149 | 155 | i++; |
| 150 | 156 | if( isspace(zLine[i]) ){ i++; } |
| 151 | 157 | indent = i; |
| 152 | 158 | for(j=0; zLine[i] && zLine[i]!='\r' && zLine[i]!='\n'; i++){ |
| 159 | + if( zLine[i]=='\\' && (!zLine[i+1] || zLine[i+1]=='\r' | |
| 160 | + || zLine[i+1]=='\n') ){ | |
| 161 | + zNewline = ""; | |
| 162 | + break; | |
| 163 | + } | |
| 153 | 164 | if( zLine[i]=='"' || zLine[i]=='\\' ){ zOut[j++] = '\\'; } |
| 154 | 165 | zOut[j++] = zLine[i]; |
| 155 | 166 | if( zLine[i]!='%' || zLine[i+1]=='%' || zLine[i+1]==0 ) continue; |
| 156 | 167 | for(nC=1; zLine[i+nC] && zLine[i+nC]!='('; nC++){} |
| 157 | 168 | if( zLine[i+nC]!='(' || !isalpha(zLine[i+nC-1]) ) continue; |
| @@ -169,14 +180,14 @@ | ||
| 169 | 180 | i++; |
| 170 | 181 | } |
| 171 | 182 | } |
| 172 | 183 | zOut[j] = 0; |
| 173 | 184 | if( !inPrint ){ |
| 174 | - fprintf(out,"%*scgi_printf(\"%s\\n\"",indent-2,"", zOut); | |
| 185 | + fprintf(out,"%*scgi_printf(\"%s%s\"",indent-2,"", zOut, zNewline); | |
| 175 | 186 | inPrint = 1; |
| 176 | 187 | }else{ |
| 177 | - fprintf(out,"\n%*s\"%s\\n\"",indent+5, "", zOut); | |
| 188 | + fprintf(out,"\n%*s\"%s%s\"",indent+5, "", zOut, zNewline); | |
| 178 | 189 | } |
| 179 | 190 | } |
| 180 | 191 | } |
| 181 | 192 | } |
| 182 | 193 | |
| 183 | 194 |
| --- src/translate.c | |
| +++ src/translate.c | |
| @@ -46,10 +46,15 @@ | |
| 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 | #include <string.h> |
| @@ -141,17 +146,23 @@ | |
| 141 | ** a cgi_printf() statement whose format is the text following the '@'. |
| 142 | ** Substrings of the form "%C(...)" (where C is any sequence of |
| 143 | ** characters other than \000 and '(') will put "%C" in the |
| 144 | ** format and add the "(...)" as an argument to the cgi_printf call. |
| 145 | */ |
| 146 | int indent; |
| 147 | int nC; |
| 148 | char c; |
| 149 | i++; |
| 150 | if( isspace(zLine[i]) ){ i++; } |
| 151 | indent = i; |
| 152 | for(j=0; zLine[i] && zLine[i]!='\r' && zLine[i]!='\n'; i++){ |
| 153 | if( zLine[i]=='"' || zLine[i]=='\\' ){ zOut[j++] = '\\'; } |
| 154 | zOut[j++] = zLine[i]; |
| 155 | if( zLine[i]!='%' || zLine[i+1]=='%' || zLine[i+1]==0 ) continue; |
| 156 | for(nC=1; zLine[i+nC] && zLine[i+nC]!='('; nC++){} |
| 157 | if( zLine[i+nC]!='(' || !isalpha(zLine[i+nC-1]) ) continue; |
| @@ -169,14 +180,14 @@ | |
| 169 | i++; |
| 170 | } |
| 171 | } |
| 172 | zOut[j] = 0; |
| 173 | if( !inPrint ){ |
| 174 | fprintf(out,"%*scgi_printf(\"%s\\n\"",indent-2,"", zOut); |
| 175 | inPrint = 1; |
| 176 | }else{ |
| 177 | fprintf(out,"\n%*s\"%s\\n\"",indent+5, "", zOut); |
| 178 | } |
| 179 | } |
| 180 | } |
| 181 | } |
| 182 | |
| 183 |
| --- src/translate.c | |
| +++ src/translate.c | |
| @@ -46,10 +46,15 @@ | |
| 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 | ** Enhancement #3: |
| 52 | ** |
| 53 | ** If a non-enhancement #1 line ends in backslash, the backslash and the |
| 54 | ** newline (\n) are not included in the argument to cgi_printf(). This |
| 55 | ** is used to split one long output line across multiple source lines. |
| 56 | */ |
| 57 | #include <stdio.h> |
| 58 | #include <ctype.h> |
| 59 | #include <stdlib.h> |
| 60 | #include <string.h> |
| @@ -141,17 +146,23 @@ | |
| 146 | ** a cgi_printf() statement whose format is the text following the '@'. |
| 147 | ** Substrings of the form "%C(...)" (where C is any sequence of |
| 148 | ** characters other than \000 and '(') will put "%C" in the |
| 149 | ** format and add the "(...)" as an argument to the cgi_printf call. |
| 150 | */ |
| 151 | const char *zNewline = "\\n"; |
| 152 | int indent; |
| 153 | int nC; |
| 154 | char c; |
| 155 | i++; |
| 156 | if( isspace(zLine[i]) ){ i++; } |
| 157 | indent = i; |
| 158 | for(j=0; zLine[i] && zLine[i]!='\r' && zLine[i]!='\n'; i++){ |
| 159 | if( zLine[i]=='\\' && (!zLine[i+1] || zLine[i+1]=='\r' |
| 160 | || zLine[i+1]=='\n') ){ |
| 161 | zNewline = ""; |
| 162 | break; |
| 163 | } |
| 164 | if( zLine[i]=='"' || zLine[i]=='\\' ){ zOut[j++] = '\\'; } |
| 165 | zOut[j++] = zLine[i]; |
| 166 | if( zLine[i]!='%' || zLine[i+1]=='%' || zLine[i+1]==0 ) continue; |
| 167 | for(nC=1; zLine[i+nC] && zLine[i+nC]!='('; nC++){} |
| 168 | if( zLine[i+nC]!='(' || !isalpha(zLine[i+nC-1]) ) continue; |
| @@ -169,14 +180,14 @@ | |
| 180 | i++; |
| 181 | } |
| 182 | } |
| 183 | zOut[j] = 0; |
| 184 | if( !inPrint ){ |
| 185 | fprintf(out,"%*scgi_printf(\"%s%s\"",indent-2,"", zOut, zNewline); |
| 186 | inPrint = 1; |
| 187 | }else{ |
| 188 | fprintf(out,"\n%*s\"%s%s\"",indent+5, "", zOut, zNewline); |
| 189 | } |
| 190 | } |
| 191 | } |
| 192 | } |
| 193 | |
| 194 |
+3
-3
| --- src/unicode.c | ||
| +++ src/unicode.c | ||
| @@ -144,11 +144,11 @@ | ||
| 144 | 144 | if( (unsigned int)c<128 ){ |
| 145 | 145 | return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 ); |
| 146 | 146 | }else if( (unsigned int)c<(1<<22) ){ |
| 147 | 147 | unsigned int key = (((unsigned int)c)<<10) | 0x000003FF; |
| 148 | 148 | int iRes = 0; |
| 149 | - int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; | |
| 149 | + int iHi = count(aEntry) - 1; | |
| 150 | 150 | int iLo = 0; |
| 151 | 151 | while( iHi>=iLo ){ |
| 152 | 152 | int iTest = (iHi + iLo) / 2; |
| 153 | 153 | if( key >= aEntry[iTest] ){ |
| 154 | 154 | iRes = iTest; |
| @@ -201,11 +201,11 @@ | ||
| 201 | 201 | 'e', 'i', 'o', 'u', 'y', |
| 202 | 202 | }; |
| 203 | 203 | |
| 204 | 204 | unsigned int key = (((unsigned int)c)<<3) | 0x00000007; |
| 205 | 205 | int iRes = 0; |
| 206 | - int iHi = sizeof(aDia)/sizeof(aDia[0]) - 1; | |
| 206 | + int iHi = count(aDia) - 1; | |
| 207 | 207 | int iLo = 0; |
| 208 | 208 | while( iHi>=iLo ){ |
| 209 | 209 | int iTest = (iHi + iLo) / 2; |
| 210 | 210 | if( key >= aDia[iTest] ){ |
| 211 | 211 | iRes = iTest; |
| @@ -348,11 +348,11 @@ | ||
| 348 | 348 | |
| 349 | 349 | if( c<128 ){ |
| 350 | 350 | if( c>='A' && c<='Z' ) ret = c + ('a' - 'A'); |
| 351 | 351 | }else if( c<65536 ){ |
| 352 | 352 | const struct TableEntry *p; |
| 353 | - int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; | |
| 353 | + int iHi = count(aEntry) - 1; | |
| 354 | 354 | int iLo = 0; |
| 355 | 355 | int iRes = -1; |
| 356 | 356 | |
| 357 | 357 | assert( c>aEntry[0].iCode ); |
| 358 | 358 | while( iHi>=iLo ){ |
| 359 | 359 |
| --- src/unicode.c | |
| +++ src/unicode.c | |
| @@ -144,11 +144,11 @@ | |
| 144 | if( (unsigned int)c<128 ){ |
| 145 | return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 ); |
| 146 | }else if( (unsigned int)c<(1<<22) ){ |
| 147 | unsigned int key = (((unsigned int)c)<<10) | 0x000003FF; |
| 148 | int iRes = 0; |
| 149 | int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; |
| 150 | int iLo = 0; |
| 151 | while( iHi>=iLo ){ |
| 152 | int iTest = (iHi + iLo) / 2; |
| 153 | if( key >= aEntry[iTest] ){ |
| 154 | iRes = iTest; |
| @@ -201,11 +201,11 @@ | |
| 201 | 'e', 'i', 'o', 'u', 'y', |
| 202 | }; |
| 203 | |
| 204 | unsigned int key = (((unsigned int)c)<<3) | 0x00000007; |
| 205 | int iRes = 0; |
| 206 | int iHi = sizeof(aDia)/sizeof(aDia[0]) - 1; |
| 207 | int iLo = 0; |
| 208 | while( iHi>=iLo ){ |
| 209 | int iTest = (iHi + iLo) / 2; |
| 210 | if( key >= aDia[iTest] ){ |
| 211 | iRes = iTest; |
| @@ -348,11 +348,11 @@ | |
| 348 | |
| 349 | if( c<128 ){ |
| 350 | if( c>='A' && c<='Z' ) ret = c + ('a' - 'A'); |
| 351 | }else if( c<65536 ){ |
| 352 | const struct TableEntry *p; |
| 353 | int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; |
| 354 | int iLo = 0; |
| 355 | int iRes = -1; |
| 356 | |
| 357 | assert( c>aEntry[0].iCode ); |
| 358 | while( iHi>=iLo ){ |
| 359 |
| --- src/unicode.c | |
| +++ src/unicode.c | |
| @@ -144,11 +144,11 @@ | |
| 144 | if( (unsigned int)c<128 ){ |
| 145 | return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 ); |
| 146 | }else if( (unsigned int)c<(1<<22) ){ |
| 147 | unsigned int key = (((unsigned int)c)<<10) | 0x000003FF; |
| 148 | int iRes = 0; |
| 149 | int iHi = count(aEntry) - 1; |
| 150 | int iLo = 0; |
| 151 | while( iHi>=iLo ){ |
| 152 | int iTest = (iHi + iLo) / 2; |
| 153 | if( key >= aEntry[iTest] ){ |
| 154 | iRes = iTest; |
| @@ -201,11 +201,11 @@ | |
| 201 | 'e', 'i', 'o', 'u', 'y', |
| 202 | }; |
| 203 | |
| 204 | unsigned int key = (((unsigned int)c)<<3) | 0x00000007; |
| 205 | int iRes = 0; |
| 206 | int iHi = count(aDia) - 1; |
| 207 | int iLo = 0; |
| 208 | while( iHi>=iLo ){ |
| 209 | int iTest = (iHi + iLo) / 2; |
| 210 | if( key >= aDia[iTest] ){ |
| 211 | iRes = iTest; |
| @@ -348,11 +348,11 @@ | |
| 348 | |
| 349 | if( c<128 ){ |
| 350 | if( c>='A' && c<='Z' ) ret = c + ('a' - 'A'); |
| 351 | }else if( c<65536 ){ |
| 352 | const struct TableEntry *p; |
| 353 | int iHi = count(aEntry) - 1; |
| 354 | int iLo = 0; |
| 355 | int iRes = -1; |
| 356 | |
| 357 | assert( c>aEntry[0].iCode ); |
| 358 | while( iHi>=iLo ){ |
| 359 |
+5
-1
| --- src/unversioned.c | ||
| +++ src/unversioned.c | ||
| @@ -452,18 +452,20 @@ | ||
| 452 | 452 | ** |
| 453 | 453 | ** Display a list of all unversioned files in the repository. |
| 454 | 454 | ** Query parameters: |
| 455 | 455 | ** |
| 456 | 456 | ** byage=1 Order the initial display be decreasing age |
| 457 | +** showdel=0 Show deleted files | |
| 457 | 458 | */ |
| 458 | 459 | void uvstat_page(void){ |
| 459 | 460 | Stmt q; |
| 460 | 461 | sqlite3_int64 iNow; |
| 461 | 462 | sqlite3_int64 iTotalSz = 0; |
| 462 | 463 | int cnt = 0; |
| 463 | 464 | int n = 0; |
| 464 | 465 | const char *zOrderBy = "name"; |
| 466 | + int showDel = 0; | |
| 465 | 467 | char zSzName[100]; |
| 466 | 468 | |
| 467 | 469 | login_check_credentials(); |
| 468 | 470 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 469 | 471 | style_header("Unversioned Files"); |
| @@ -471,20 +473,22 @@ | ||
| 471 | 473 | @ No unversioned files on this server |
| 472 | 474 | style_footer(); |
| 473 | 475 | return; |
| 474 | 476 | } |
| 475 | 477 | if( PB("byage") ) zOrderBy = "mtime DESC"; |
| 478 | + if( PB("showdel") ) showDel = 1; | |
| 476 | 479 | db_prepare(&q, |
| 477 | 480 | "SELECT" |
| 478 | 481 | " name," |
| 479 | 482 | " mtime," |
| 480 | 483 | " hash," |
| 481 | 484 | " sz," |
| 482 | 485 | " (SELECT login FROM rcvfrom, user" |
| 483 | 486 | " WHERE user.uid=rcvfrom.uid AND rcvfrom.rcvid=unversioned.rcvid)," |
| 484 | 487 | " rcvid" |
| 485 | - " FROM unversioned ORDER BY %s", | |
| 488 | + " FROM unversioned %s ORDER BY %s", | |
| 489 | + showDel ? "" : "WHERE hash IS NOT NULL" /*safe-for-%s*/, | |
| 486 | 490 | zOrderBy/*safe-for-%s*/ |
| 487 | 491 | ); |
| 488 | 492 | iNow = db_int64(0, "SELECT strftime('%%s','now');"); |
| 489 | 493 | while( db_step(&q)==SQLITE_ROW ){ |
| 490 | 494 | const char *zName = db_column_text(&q, 0); |
| 491 | 495 |
| --- src/unversioned.c | |
| +++ src/unversioned.c | |
| @@ -452,18 +452,20 @@ | |
| 452 | ** |
| 453 | ** Display a list of all unversioned files in the repository. |
| 454 | ** Query parameters: |
| 455 | ** |
| 456 | ** byage=1 Order the initial display be decreasing age |
| 457 | */ |
| 458 | void uvstat_page(void){ |
| 459 | Stmt q; |
| 460 | sqlite3_int64 iNow; |
| 461 | sqlite3_int64 iTotalSz = 0; |
| 462 | int cnt = 0; |
| 463 | int n = 0; |
| 464 | const char *zOrderBy = "name"; |
| 465 | char zSzName[100]; |
| 466 | |
| 467 | login_check_credentials(); |
| 468 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 469 | style_header("Unversioned Files"); |
| @@ -471,20 +473,22 @@ | |
| 471 | @ No unversioned files on this server |
| 472 | style_footer(); |
| 473 | return; |
| 474 | } |
| 475 | if( PB("byage") ) zOrderBy = "mtime DESC"; |
| 476 | db_prepare(&q, |
| 477 | "SELECT" |
| 478 | " name," |
| 479 | " mtime," |
| 480 | " hash," |
| 481 | " sz," |
| 482 | " (SELECT login FROM rcvfrom, user" |
| 483 | " WHERE user.uid=rcvfrom.uid AND rcvfrom.rcvid=unversioned.rcvid)," |
| 484 | " rcvid" |
| 485 | " FROM unversioned ORDER BY %s", |
| 486 | zOrderBy/*safe-for-%s*/ |
| 487 | ); |
| 488 | iNow = db_int64(0, "SELECT strftime('%%s','now');"); |
| 489 | while( db_step(&q)==SQLITE_ROW ){ |
| 490 | const char *zName = db_column_text(&q, 0); |
| 491 |
| --- src/unversioned.c | |
| +++ src/unversioned.c | |
| @@ -452,18 +452,20 @@ | |
| 452 | ** |
| 453 | ** Display a list of all unversioned files in the repository. |
| 454 | ** Query parameters: |
| 455 | ** |
| 456 | ** byage=1 Order the initial display be decreasing age |
| 457 | ** showdel=0 Show deleted files |
| 458 | */ |
| 459 | void uvstat_page(void){ |
| 460 | Stmt q; |
| 461 | sqlite3_int64 iNow; |
| 462 | sqlite3_int64 iTotalSz = 0; |
| 463 | int cnt = 0; |
| 464 | int n = 0; |
| 465 | const char *zOrderBy = "name"; |
| 466 | int showDel = 0; |
| 467 | char zSzName[100]; |
| 468 | |
| 469 | login_check_credentials(); |
| 470 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 471 | style_header("Unversioned Files"); |
| @@ -471,20 +473,22 @@ | |
| 473 | @ No unversioned files on this server |
| 474 | style_footer(); |
| 475 | return; |
| 476 | } |
| 477 | if( PB("byage") ) zOrderBy = "mtime DESC"; |
| 478 | if( PB("showdel") ) showDel = 1; |
| 479 | db_prepare(&q, |
| 480 | "SELECT" |
| 481 | " name," |
| 482 | " mtime," |
| 483 | " hash," |
| 484 | " sz," |
| 485 | " (SELECT login FROM rcvfrom, user" |
| 486 | " WHERE user.uid=rcvfrom.uid AND rcvfrom.rcvid=unversioned.rcvid)," |
| 487 | " rcvid" |
| 488 | " FROM unversioned %s ORDER BY %s", |
| 489 | showDel ? "" : "WHERE hash IS NOT NULL" /*safe-for-%s*/, |
| 490 | zOrderBy/*safe-for-%s*/ |
| 491 | ); |
| 492 | iNow = db_int64(0, "SELECT strftime('%%s','now');"); |
| 493 | while( db_step(&q)==SQLITE_ROW ){ |
| 494 | const char *zName = db_column_text(&q, 0); |
| 495 |
+53
-23
| --- src/user.c | ||
| +++ src/user.c | ||
| @@ -19,14 +19,10 @@ | ||
| 19 | 19 | ** querying information about users. |
| 20 | 20 | */ |
| 21 | 21 | #include "config.h" |
| 22 | 22 | #include "user.h" |
| 23 | 23 | |
| 24 | -#if defined(_WIN32) | |
| 25 | -#include <conio.h> | |
| 26 | -#endif | |
| 27 | - | |
| 28 | 24 | /* |
| 29 | 25 | ** Strip leading and trailing space from a string and add the string |
| 30 | 26 | ** onto the end of a blob. |
| 31 | 27 | */ |
| 32 | 28 | static void strip_string(Blob *pBlob, char *z){ |
| @@ -43,53 +39,74 @@ | ||
| 43 | 39 | } |
| 44 | 40 | blob_append(pBlob, z, -1); |
| 45 | 41 | } |
| 46 | 42 | |
| 47 | 43 | #if defined(_WIN32) || defined(__BIONIC__) |
| 48 | -#ifdef __MINGW32__ | |
| 44 | +#ifdef _WIN32 | |
| 49 | 45 | #include <conio.h> |
| 50 | 46 | #endif |
| 47 | + | |
| 51 | 48 | /* |
| 52 | -** getpass for Windows and Android | |
| 49 | +** getpass() for Windows and Android. | |
| 53 | 50 | */ |
| 51 | +static char *zPwdBuffer = 0; | |
| 52 | +static size_t nPwdBuffer = 0; | |
| 53 | + | |
| 54 | 54 | static char *getpass(const char *prompt){ |
| 55 | - static char pwd[64]; | |
| 55 | + char *zPwd; | |
| 56 | + size_t nPwd; | |
| 56 | 57 | size_t i; |
| 57 | 58 | |
| 59 | + if( zPwdBuffer==0 ){ | |
| 60 | + zPwdBuffer = fossil_secure_alloc_page(&nPwdBuffer); | |
| 61 | + assert( zPwdBuffer ); | |
| 62 | + }else{ | |
| 63 | + fossil_secure_zero(zPwdBuffer, nPwdBuffer); | |
| 64 | + } | |
| 65 | + zPwd = zPwdBuffer; | |
| 66 | + nPwd = nPwdBuffer; | |
| 58 | 67 | fputs(prompt,stderr); |
| 59 | 68 | fflush(stderr); |
| 60 | - for(i=0; i<sizeof(pwd)-1; ++i){ | |
| 69 | + assert( zPwd!=0 ); | |
| 70 | + assert( nPwd>0 ); | |
| 71 | + for(i=0; i<nPwd-1; ++i){ | |
| 61 | 72 | #if defined(_WIN32) |
| 62 | - pwd[i] = _getch(); | |
| 73 | + zPwd[i] = _getch(); | |
| 63 | 74 | #else |
| 64 | - pwd[i] = getc(stdin); | |
| 75 | + zPwd[i] = getc(stdin); | |
| 65 | 76 | #endif |
| 66 | - if(pwd[i]=='\r' || pwd[i]=='\n'){ | |
| 77 | + if(zPwd[i]=='\r' || zPwd[i]=='\n'){ | |
| 67 | 78 | break; |
| 68 | 79 | } |
| 69 | 80 | /* BS or DEL */ |
| 70 | - else if(i>0 && (pwd[i]==8 || pwd[i]==127)){ | |
| 81 | + else if(i>0 && (zPwd[i]==8 || zPwd[i]==127)){ | |
| 71 | 82 | i -= 2; |
| 72 | 83 | continue; |
| 73 | 84 | } |
| 74 | 85 | /* CTRL-C */ |
| 75 | - else if(pwd[i]==3) { | |
| 86 | + else if(zPwd[i]==3) { | |
| 76 | 87 | i=0; |
| 77 | 88 | break; |
| 78 | 89 | } |
| 79 | 90 | /* ESC */ |
| 80 | - else if(pwd[i]==27){ | |
| 91 | + else if(zPwd[i]==27){ | |
| 81 | 92 | i=0; |
| 82 | 93 | break; |
| 83 | 94 | } |
| 84 | 95 | else{ |
| 85 | 96 | fputc('*',stderr); |
| 86 | 97 | } |
| 87 | 98 | } |
| 88 | - pwd[i]='\0'; | |
| 99 | + zPwd[i]='\0'; | |
| 89 | 100 | fputs("\n", stderr); |
| 90 | - return pwd; | |
| 101 | + assert( zPwd==zPwdBuffer ); | |
| 102 | + return zPwd; | |
| 103 | +} | |
| 104 | +void freepass(){ | |
| 105 | + if( !zPwdBuffer ) return; | |
| 106 | + assert( nPwdBuffer>0 ); | |
| 107 | + fossil_secure_free_page(zPwdBuffer, nPwdBuffer); | |
| 91 | 108 | } |
| 92 | 109 | #endif |
| 93 | 110 | |
| 94 | 111 | #if defined(_WIN32) || defined(WIN32) |
| 95 | 112 | # include <io.h> |
| @@ -553,10 +570,25 @@ | ||
| 553 | 570 | db_multi_exec( |
| 554 | 571 | "UPDATE user SET pw=shared_secret(pw,login), mtime=now()" |
| 555 | 572 | " WHERE length(pw)>0 AND length(pw)!=40" |
| 556 | 573 | ); |
| 557 | 574 | } |
| 575 | + | |
| 576 | +/* | |
| 577 | +** COMMAND: test-prompt-user | |
| 578 | +** | |
| 579 | +** Usage: %fossil test-prompt-user PROMPT | |
| 580 | +** | |
| 581 | +** Prompts the user for input and then prints it verbatim (i.e. without | |
| 582 | +** a trailing line terminator). | |
| 583 | +*/ | |
| 584 | +void test_prompt_user_cmd(void){ | |
| 585 | + Blob answer; | |
| 586 | + if( g.argc!=3 ) usage("PROMPT"); | |
| 587 | + prompt_user(g.argv[2], &answer); | |
| 588 | + fossil_print("%s", blob_str(&answer)); | |
| 589 | +} | |
| 558 | 590 | |
| 559 | 591 | /* |
| 560 | 592 | ** WEBPAGE: access_log |
| 561 | 593 | ** |
| 562 | 594 | ** Show login attempts, including timestamp and IP address. |
| @@ -616,13 +648,12 @@ | ||
| 616 | 648 | }else if( y==2 ){ |
| 617 | 649 | blob_append(&sql, " WHERE NOT success", -1); |
| 618 | 650 | } |
| 619 | 651 | blob_append_sql(&sql," ORDER BY rowid DESC LIMIT %d OFFSET %d", n+1, skip); |
| 620 | 652 | if( skip ){ |
| 621 | - style_submenu_element("Newer", "Newer entries", | |
| 622 | - "%s/access_log?o=%d&n=%d&y=%d", g.zTop, skip>=n ? skip-n : 0, | |
| 623 | - n, y); | |
| 653 | + style_submenu_element("Newer", "%s/access_log?o=%d&n=%d&y=%d", | |
| 654 | + g.zTop, skip>=n ? skip-n : 0, n, y); | |
| 624 | 655 | } |
| 625 | 656 | rc = db_prepare_ignore_error(&q, "%s", blob_sql_text(&sql)); |
| 626 | 657 | fLogEnabled = db_get_boolean("access-log", 0); |
| 627 | 658 | @ <div align="center">Access logging is %s(fLogEnabled?"on":"off"). |
| 628 | 659 | @ (Change this on the <a href="setup_settings">settings</a> page.)</div> |
| @@ -634,12 +665,12 @@ | ||
| 634 | 665 | const char *zIP = db_column_text(&q, 1); |
| 635 | 666 | const char *zDate = db_column_text(&q, 2); |
| 636 | 667 | int bSuccess = db_column_int(&q, 3); |
| 637 | 668 | cnt++; |
| 638 | 669 | if( cnt>n ){ |
| 639 | - style_submenu_element("Older", "Older entries", | |
| 640 | - "%s/access_log?o=%d&n=%d&y=%d", g.zTop, skip+n, n, y); | |
| 670 | + style_submenu_element("Older", "%s/access_log?o=%d&n=%d&y=%d", | |
| 671 | + g.zTop, skip+n, n, y); | |
| 641 | 672 | break; |
| 642 | 673 | } |
| 643 | 674 | if( bSuccess ){ |
| 644 | 675 | @ <tr> |
| 645 | 676 | }else{ |
| @@ -646,12 +677,11 @@ | ||
| 646 | 677 | @ <tr bgcolor="#ffacc0"> |
| 647 | 678 | } |
| 648 | 679 | @ <td>%s(zDate)</td><td>%h(zName)</td><td>%h(zIP)</td></tr> |
| 649 | 680 | } |
| 650 | 681 | if( skip>0 || cnt>n ){ |
| 651 | - style_submenu_element("All", "All entries", | |
| 652 | - "%s/access_log?n=10000000", g.zTop); | |
| 682 | + style_submenu_element("All", "%s/access_log?n=10000000", g.zTop); | |
| 653 | 683 | } |
| 654 | 684 | @ </tbody></table> |
| 655 | 685 | db_finalize(&q); |
| 656 | 686 | @ <hr /> |
| 657 | 687 | @ <form method="post" action="%s(g.zTop)/access_log"> |
| 658 | 688 |
| --- src/user.c | |
| +++ src/user.c | |
| @@ -19,14 +19,10 @@ | |
| 19 | ** querying information about users. |
| 20 | */ |
| 21 | #include "config.h" |
| 22 | #include "user.h" |
| 23 | |
| 24 | #if defined(_WIN32) |
| 25 | #include <conio.h> |
| 26 | #endif |
| 27 | |
| 28 | /* |
| 29 | ** Strip leading and trailing space from a string and add the string |
| 30 | ** onto the end of a blob. |
| 31 | */ |
| 32 | static void strip_string(Blob *pBlob, char *z){ |
| @@ -43,53 +39,74 @@ | |
| 43 | } |
| 44 | blob_append(pBlob, z, -1); |
| 45 | } |
| 46 | |
| 47 | #if defined(_WIN32) || defined(__BIONIC__) |
| 48 | #ifdef __MINGW32__ |
| 49 | #include <conio.h> |
| 50 | #endif |
| 51 | /* |
| 52 | ** getpass for Windows and Android |
| 53 | */ |
| 54 | static char *getpass(const char *prompt){ |
| 55 | static char pwd[64]; |
| 56 | size_t i; |
| 57 | |
| 58 | fputs(prompt,stderr); |
| 59 | fflush(stderr); |
| 60 | for(i=0; i<sizeof(pwd)-1; ++i){ |
| 61 | #if defined(_WIN32) |
| 62 | pwd[i] = _getch(); |
| 63 | #else |
| 64 | pwd[i] = getc(stdin); |
| 65 | #endif |
| 66 | if(pwd[i]=='\r' || pwd[i]=='\n'){ |
| 67 | break; |
| 68 | } |
| 69 | /* BS or DEL */ |
| 70 | else if(i>0 && (pwd[i]==8 || pwd[i]==127)){ |
| 71 | i -= 2; |
| 72 | continue; |
| 73 | } |
| 74 | /* CTRL-C */ |
| 75 | else if(pwd[i]==3) { |
| 76 | i=0; |
| 77 | break; |
| 78 | } |
| 79 | /* ESC */ |
| 80 | else if(pwd[i]==27){ |
| 81 | i=0; |
| 82 | break; |
| 83 | } |
| 84 | else{ |
| 85 | fputc('*',stderr); |
| 86 | } |
| 87 | } |
| 88 | pwd[i]='\0'; |
| 89 | fputs("\n", stderr); |
| 90 | return pwd; |
| 91 | } |
| 92 | #endif |
| 93 | |
| 94 | #if defined(_WIN32) || defined(WIN32) |
| 95 | # include <io.h> |
| @@ -553,10 +570,25 @@ | |
| 553 | db_multi_exec( |
| 554 | "UPDATE user SET pw=shared_secret(pw,login), mtime=now()" |
| 555 | " WHERE length(pw)>0 AND length(pw)!=40" |
| 556 | ); |
| 557 | } |
| 558 | |
| 559 | /* |
| 560 | ** WEBPAGE: access_log |
| 561 | ** |
| 562 | ** Show login attempts, including timestamp and IP address. |
| @@ -616,13 +648,12 @@ | |
| 616 | }else if( y==2 ){ |
| 617 | blob_append(&sql, " WHERE NOT success", -1); |
| 618 | } |
| 619 | blob_append_sql(&sql," ORDER BY rowid DESC LIMIT %d OFFSET %d", n+1, skip); |
| 620 | if( skip ){ |
| 621 | style_submenu_element("Newer", "Newer entries", |
| 622 | "%s/access_log?o=%d&n=%d&y=%d", g.zTop, skip>=n ? skip-n : 0, |
| 623 | n, y); |
| 624 | } |
| 625 | rc = db_prepare_ignore_error(&q, "%s", blob_sql_text(&sql)); |
| 626 | fLogEnabled = db_get_boolean("access-log", 0); |
| 627 | @ <div align="center">Access logging is %s(fLogEnabled?"on":"off"). |
| 628 | @ (Change this on the <a href="setup_settings">settings</a> page.)</div> |
| @@ -634,12 +665,12 @@ | |
| 634 | const char *zIP = db_column_text(&q, 1); |
| 635 | const char *zDate = db_column_text(&q, 2); |
| 636 | int bSuccess = db_column_int(&q, 3); |
| 637 | cnt++; |
| 638 | if( cnt>n ){ |
| 639 | style_submenu_element("Older", "Older entries", |
| 640 | "%s/access_log?o=%d&n=%d&y=%d", g.zTop, skip+n, n, y); |
| 641 | break; |
| 642 | } |
| 643 | if( bSuccess ){ |
| 644 | @ <tr> |
| 645 | }else{ |
| @@ -646,12 +677,11 @@ | |
| 646 | @ <tr bgcolor="#ffacc0"> |
| 647 | } |
| 648 | @ <td>%s(zDate)</td><td>%h(zName)</td><td>%h(zIP)</td></tr> |
| 649 | } |
| 650 | if( skip>0 || cnt>n ){ |
| 651 | style_submenu_element("All", "All entries", |
| 652 | "%s/access_log?n=10000000", g.zTop); |
| 653 | } |
| 654 | @ </tbody></table> |
| 655 | db_finalize(&q); |
| 656 | @ <hr /> |
| 657 | @ <form method="post" action="%s(g.zTop)/access_log"> |
| 658 |
| --- src/user.c | |
| +++ src/user.c | |
| @@ -19,14 +19,10 @@ | |
| 19 | ** querying information about users. |
| 20 | */ |
| 21 | #include "config.h" |
| 22 | #include "user.h" |
| 23 | |
| 24 | /* |
| 25 | ** Strip leading and trailing space from a string and add the string |
| 26 | ** onto the end of a blob. |
| 27 | */ |
| 28 | static void strip_string(Blob *pBlob, char *z){ |
| @@ -43,53 +39,74 @@ | |
| 39 | } |
| 40 | blob_append(pBlob, z, -1); |
| 41 | } |
| 42 | |
| 43 | #if defined(_WIN32) || defined(__BIONIC__) |
| 44 | #ifdef _WIN32 |
| 45 | #include <conio.h> |
| 46 | #endif |
| 47 | |
| 48 | /* |
| 49 | ** getpass() for Windows and Android. |
| 50 | */ |
| 51 | static char *zPwdBuffer = 0; |
| 52 | static size_t nPwdBuffer = 0; |
| 53 | |
| 54 | static char *getpass(const char *prompt){ |
| 55 | char *zPwd; |
| 56 | size_t nPwd; |
| 57 | size_t i; |
| 58 | |
| 59 | if( zPwdBuffer==0 ){ |
| 60 | zPwdBuffer = fossil_secure_alloc_page(&nPwdBuffer); |
| 61 | assert( zPwdBuffer ); |
| 62 | }else{ |
| 63 | fossil_secure_zero(zPwdBuffer, nPwdBuffer); |
| 64 | } |
| 65 | zPwd = zPwdBuffer; |
| 66 | nPwd = nPwdBuffer; |
| 67 | fputs(prompt,stderr); |
| 68 | fflush(stderr); |
| 69 | assert( zPwd!=0 ); |
| 70 | assert( nPwd>0 ); |
| 71 | for(i=0; i<nPwd-1; ++i){ |
| 72 | #if defined(_WIN32) |
| 73 | zPwd[i] = _getch(); |
| 74 | #else |
| 75 | zPwd[i] = getc(stdin); |
| 76 | #endif |
| 77 | if(zPwd[i]=='\r' || zPwd[i]=='\n'){ |
| 78 | break; |
| 79 | } |
| 80 | /* BS or DEL */ |
| 81 | else if(i>0 && (zPwd[i]==8 || zPwd[i]==127)){ |
| 82 | i -= 2; |
| 83 | continue; |
| 84 | } |
| 85 | /* CTRL-C */ |
| 86 | else if(zPwd[i]==3) { |
| 87 | i=0; |
| 88 | break; |
| 89 | } |
| 90 | /* ESC */ |
| 91 | else if(zPwd[i]==27){ |
| 92 | i=0; |
| 93 | break; |
| 94 | } |
| 95 | else{ |
| 96 | fputc('*',stderr); |
| 97 | } |
| 98 | } |
| 99 | zPwd[i]='\0'; |
| 100 | fputs("\n", stderr); |
| 101 | assert( zPwd==zPwdBuffer ); |
| 102 | return zPwd; |
| 103 | } |
| 104 | void freepass(){ |
| 105 | if( !zPwdBuffer ) return; |
| 106 | assert( nPwdBuffer>0 ); |
| 107 | fossil_secure_free_page(zPwdBuffer, nPwdBuffer); |
| 108 | } |
| 109 | #endif |
| 110 | |
| 111 | #if defined(_WIN32) || defined(WIN32) |
| 112 | # include <io.h> |
| @@ -553,10 +570,25 @@ | |
| 570 | db_multi_exec( |
| 571 | "UPDATE user SET pw=shared_secret(pw,login), mtime=now()" |
| 572 | " WHERE length(pw)>0 AND length(pw)!=40" |
| 573 | ); |
| 574 | } |
| 575 | |
| 576 | /* |
| 577 | ** COMMAND: test-prompt-user |
| 578 | ** |
| 579 | ** Usage: %fossil test-prompt-user PROMPT |
| 580 | ** |
| 581 | ** Prompts the user for input and then prints it verbatim (i.e. without |
| 582 | ** a trailing line terminator). |
| 583 | */ |
| 584 | void test_prompt_user_cmd(void){ |
| 585 | Blob answer; |
| 586 | if( g.argc!=3 ) usage("PROMPT"); |
| 587 | prompt_user(g.argv[2], &answer); |
| 588 | fossil_print("%s", blob_str(&answer)); |
| 589 | } |
| 590 | |
| 591 | /* |
| 592 | ** WEBPAGE: access_log |
| 593 | ** |
| 594 | ** Show login attempts, including timestamp and IP address. |
| @@ -616,13 +648,12 @@ | |
| 648 | }else if( y==2 ){ |
| 649 | blob_append(&sql, " WHERE NOT success", -1); |
| 650 | } |
| 651 | blob_append_sql(&sql," ORDER BY rowid DESC LIMIT %d OFFSET %d", n+1, skip); |
| 652 | if( skip ){ |
| 653 | style_submenu_element("Newer", "%s/access_log?o=%d&n=%d&y=%d", |
| 654 | g.zTop, skip>=n ? skip-n : 0, n, y); |
| 655 | } |
| 656 | rc = db_prepare_ignore_error(&q, "%s", blob_sql_text(&sql)); |
| 657 | fLogEnabled = db_get_boolean("access-log", 0); |
| 658 | @ <div align="center">Access logging is %s(fLogEnabled?"on":"off"). |
| 659 | @ (Change this on the <a href="setup_settings">settings</a> page.)</div> |
| @@ -634,12 +665,12 @@ | |
| 665 | const char *zIP = db_column_text(&q, 1); |
| 666 | const char *zDate = db_column_text(&q, 2); |
| 667 | int bSuccess = db_column_int(&q, 3); |
| 668 | cnt++; |
| 669 | if( cnt>n ){ |
| 670 | style_submenu_element("Older", "%s/access_log?o=%d&n=%d&y=%d", |
| 671 | g.zTop, skip+n, n, y); |
| 672 | break; |
| 673 | } |
| 674 | if( bSuccess ){ |
| 675 | @ <tr> |
| 676 | }else{ |
| @@ -646,12 +677,11 @@ | |
| 677 | @ <tr bgcolor="#ffacc0"> |
| 678 | } |
| 679 | @ <td>%s(zDate)</td><td>%h(zName)</td><td>%h(zIP)</td></tr> |
| 680 | } |
| 681 | if( skip>0 || cnt>n ){ |
| 682 | style_submenu_element("All", "%s/access_log?n=10000000", g.zTop); |
| 683 | } |
| 684 | @ </tbody></table> |
| 685 | db_finalize(&q); |
| 686 | @ <hr /> |
| 687 | @ <form method="post" action="%s(g.zTop)/access_log"> |
| 688 |
+1
| --- src/utf8.c | ||
| +++ src/utf8.c | ||
| @@ -317,10 +317,11 @@ | ||
| 317 | 317 | wchar_t *zUnicode; /* Unicode version of zUtf8 */ |
| 318 | 318 | DWORD dummy; |
| 319 | 319 | Blob blob; |
| 320 | 320 | |
| 321 | 321 | static int istty[2] = { -1, -1 }; |
| 322 | + assert( toStdErr==0 || toStdErr==1 ); | |
| 322 | 323 | if( istty[toStdErr]==-1 ){ |
| 323 | 324 | istty[toStdErr] = _isatty(toStdErr + 1) != 0; |
| 324 | 325 | } |
| 325 | 326 | if( !istty[toStdErr] ){ |
| 326 | 327 | /* stdout/stderr is not a console. */ |
| 327 | 328 |
| --- src/utf8.c | |
| +++ src/utf8.c | |
| @@ -317,10 +317,11 @@ | |
| 317 | wchar_t *zUnicode; /* Unicode version of zUtf8 */ |
| 318 | DWORD dummy; |
| 319 | Blob blob; |
| 320 | |
| 321 | static int istty[2] = { -1, -1 }; |
| 322 | if( istty[toStdErr]==-1 ){ |
| 323 | istty[toStdErr] = _isatty(toStdErr + 1) != 0; |
| 324 | } |
| 325 | if( !istty[toStdErr] ){ |
| 326 | /* stdout/stderr is not a console. */ |
| 327 |
| --- src/utf8.c | |
| +++ src/utf8.c | |
| @@ -317,10 +317,11 @@ | |
| 317 | wchar_t *zUnicode; /* Unicode version of zUtf8 */ |
| 318 | DWORD dummy; |
| 319 | Blob blob; |
| 320 | |
| 321 | static int istty[2] = { -1, -1 }; |
| 322 | assert( toStdErr==0 || toStdErr==1 ); |
| 323 | if( istty[toStdErr]==-1 ){ |
| 324 | istty[toStdErr] = _isatty(toStdErr + 1) != 0; |
| 325 | } |
| 326 | if( !istty[toStdErr] ){ |
| 327 | /* stdout/stderr is not a console. */ |
| 328 |
+57
| --- src/util.c | ||
| +++ src/util.c | ||
| @@ -55,10 +55,67 @@ | ||
| 55 | 55 | } |
| 56 | 56 | void *fossil_realloc(void *p, size_t n){ |
| 57 | 57 | p = realloc(p, n); |
| 58 | 58 | if( p==0 ) fossil_panic("out of memory"); |
| 59 | 59 | return p; |
| 60 | +} | |
| 61 | +void fossil_secure_zero(void *p, size_t n){ | |
| 62 | + volatile unsigned char *vp = (volatile unsigned char *)p; | |
| 63 | + size_t i; | |
| 64 | + | |
| 65 | + if( p==0 ) return; | |
| 66 | + assert( n>0 ); | |
| 67 | + if( n==0 ) return; | |
| 68 | + for(i=0; i<n; i++){ vp[i] ^= 0xFF; } | |
| 69 | + for(i=0; i<n; i++){ vp[i] ^= vp[i]; } | |
| 70 | +} | |
| 71 | +void fossil_get_page_size(size_t *piPageSize){ | |
| 72 | +#if defined(_WIN32) | |
| 73 | + SYSTEM_INFO sysInfo; | |
| 74 | + memset(&sysInfo, 0, sizeof(SYSTEM_INFO)); | |
| 75 | + GetSystemInfo(&sysInfo); | |
| 76 | + *piPageSize = (size_t)sysInfo.dwPageSize; | |
| 77 | +#else | |
| 78 | + *piPageSize = 4096; /* FIXME: What for POSIX? */ | |
| 79 | +#endif | |
| 80 | +} | |
| 81 | +void *fossil_secure_alloc_page(size_t *pN){ | |
| 82 | + void *p; | |
| 83 | + size_t pageSize; | |
| 84 | + | |
| 85 | + fossil_get_page_size(&pageSize); | |
| 86 | + assert( pageSize>0 ); | |
| 87 | + assert( pageSize%2==0 ); | |
| 88 | +#if defined(_WIN32) | |
| 89 | + p = VirtualAlloc(NULL, pageSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); | |
| 90 | + if( p==NULL ){ | |
| 91 | + fossil_fatal("VirtualAlloc failed: %lu\n", GetLastError()); | |
| 92 | + } | |
| 93 | + if( !VirtualLock(p, pageSize) ){ | |
| 94 | + fossil_fatal("VirtualLock failed: %lu\n", GetLastError()); | |
| 95 | + } | |
| 96 | +#else | |
| 97 | + p = fossil_malloc(pageSize); | |
| 98 | +#endif | |
| 99 | + fossil_secure_zero(p, pageSize); | |
| 100 | + if( pN ) *pN = pageSize; | |
| 101 | + return p; | |
| 102 | +} | |
| 103 | +void fossil_secure_free_page(void *p, size_t n){ | |
| 104 | + if( !p ) return; | |
| 105 | + assert( n>0 ); | |
| 106 | + fossil_secure_zero(p, n); | |
| 107 | +#if defined(_WIN32) | |
| 108 | + if( !VirtualUnlock(p, n) ){ | |
| 109 | + fossil_fatal("VirtualUnlock failed: %lu\n", GetLastError()); | |
| 110 | + } | |
| 111 | + if( !VirtualFree(p, 0, MEM_RELEASE) ){ | |
| 112 | + fossil_fatal("VirtualFree failed: %lu\n", GetLastError()); | |
| 113 | + } | |
| 114 | +#else | |
| 115 | + fossil_free(p); | |
| 116 | +#endif | |
| 60 | 117 | } |
| 61 | 118 | |
| 62 | 119 | /* |
| 63 | 120 | ** This function implements a cross-platform "system()" interface. |
| 64 | 121 | */ |
| 65 | 122 |
| --- src/util.c | |
| +++ src/util.c | |
| @@ -55,10 +55,67 @@ | |
| 55 | } |
| 56 | void *fossil_realloc(void *p, size_t n){ |
| 57 | p = realloc(p, n); |
| 58 | if( p==0 ) fossil_panic("out of memory"); |
| 59 | return p; |
| 60 | } |
| 61 | |
| 62 | /* |
| 63 | ** This function implements a cross-platform "system()" interface. |
| 64 | */ |
| 65 |
| --- src/util.c | |
| +++ src/util.c | |
| @@ -55,10 +55,67 @@ | |
| 55 | } |
| 56 | void *fossil_realloc(void *p, size_t n){ |
| 57 | p = realloc(p, n); |
| 58 | if( p==0 ) fossil_panic("out of memory"); |
| 59 | return p; |
| 60 | } |
| 61 | void fossil_secure_zero(void *p, size_t n){ |
| 62 | volatile unsigned char *vp = (volatile unsigned char *)p; |
| 63 | size_t i; |
| 64 | |
| 65 | if( p==0 ) return; |
| 66 | assert( n>0 ); |
| 67 | if( n==0 ) return; |
| 68 | for(i=0; i<n; i++){ vp[i] ^= 0xFF; } |
| 69 | for(i=0; i<n; i++){ vp[i] ^= vp[i]; } |
| 70 | } |
| 71 | void fossil_get_page_size(size_t *piPageSize){ |
| 72 | #if defined(_WIN32) |
| 73 | SYSTEM_INFO sysInfo; |
| 74 | memset(&sysInfo, 0, sizeof(SYSTEM_INFO)); |
| 75 | GetSystemInfo(&sysInfo); |
| 76 | *piPageSize = (size_t)sysInfo.dwPageSize; |
| 77 | #else |
| 78 | *piPageSize = 4096; /* FIXME: What for POSIX? */ |
| 79 | #endif |
| 80 | } |
| 81 | void *fossil_secure_alloc_page(size_t *pN){ |
| 82 | void *p; |
| 83 | size_t pageSize; |
| 84 | |
| 85 | fossil_get_page_size(&pageSize); |
| 86 | assert( pageSize>0 ); |
| 87 | assert( pageSize%2==0 ); |
| 88 | #if defined(_WIN32) |
| 89 | p = VirtualAlloc(NULL, pageSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); |
| 90 | if( p==NULL ){ |
| 91 | fossil_fatal("VirtualAlloc failed: %lu\n", GetLastError()); |
| 92 | } |
| 93 | if( !VirtualLock(p, pageSize) ){ |
| 94 | fossil_fatal("VirtualLock failed: %lu\n", GetLastError()); |
| 95 | } |
| 96 | #else |
| 97 | p = fossil_malloc(pageSize); |
| 98 | #endif |
| 99 | fossil_secure_zero(p, pageSize); |
| 100 | if( pN ) *pN = pageSize; |
| 101 | return p; |
| 102 | } |
| 103 | void fossil_secure_free_page(void *p, size_t n){ |
| 104 | if( !p ) return; |
| 105 | assert( n>0 ); |
| 106 | fossil_secure_zero(p, n); |
| 107 | #if defined(_WIN32) |
| 108 | if( !VirtualUnlock(p, n) ){ |
| 109 | fossil_fatal("VirtualUnlock failed: %lu\n", GetLastError()); |
| 110 | } |
| 111 | if( !VirtualFree(p, 0, MEM_RELEASE) ){ |
| 112 | fossil_fatal("VirtualFree failed: %lu\n", GetLastError()); |
| 113 | } |
| 114 | #else |
| 115 | fossil_free(p); |
| 116 | #endif |
| 117 | } |
| 118 | |
| 119 | /* |
| 120 | ** This function implements a cross-platform "system()" interface. |
| 121 | */ |
| 122 |
+3
-3
| --- src/vfile.c | ||
| +++ src/vfile.c | ||
| @@ -350,11 +350,11 @@ | ||
| 350 | 350 | } |
| 351 | 351 | } |
| 352 | 352 | if( verbose ) fossil_print("%s\n", &zName[nRepos]); |
| 353 | 353 | if( file_wd_isdir(zName)==1 ){ |
| 354 | 354 | /*TODO(dchest): remove directories? */ |
| 355 | - fossil_fatal("%s is directory, cannot overwrite\n", zName); | |
| 355 | + fossil_fatal("%s is directory, cannot overwrite", zName); | |
| 356 | 356 | } |
| 357 | 357 | if( file_wd_size(zName)>=0 && (isLink || file_wd_islink(0)) ){ |
| 358 | 358 | file_delete(zName); |
| 359 | 359 | } |
| 360 | 360 | if( isLink ){ |
| @@ -435,11 +435,11 @@ | ||
| 435 | 435 | for(; zName[0]!=0; zName++){ |
| 436 | 436 | if( zName[0]=='/' && sqlite3_strglob("/ci-comment-????????????.txt", zName)==0 ){ |
| 437 | 437 | return 1; |
| 438 | 438 | } |
| 439 | 439 | if( zName[0]!='-' ) continue; |
| 440 | - for(i=0; i<sizeof(azTemp)/sizeof(azTemp[0]); i++){ | |
| 440 | + for(i=0; i<count(azTemp); i++){ | |
| 441 | 441 | n = (int)strlen(azTemp[i]); |
| 442 | 442 | if( memcmp(azTemp[i], zName+1, n) ) continue; |
| 443 | 443 | if( zName[n+1]==0 ) return 1; |
| 444 | 444 | if( zName[n+1]=='-' ){ |
| 445 | 445 | for(j=n+2; zName[j] && fossil_isdigit(zName[j]); j++){} |
| @@ -918,11 +918,11 @@ | ||
| 918 | 918 | blob_zero(pManOut); |
| 919 | 919 | } |
| 920 | 920 | db_must_be_within_tree(); |
| 921 | 921 | pManifest = manifest_get(vid, CFTYPE_MANIFEST, &err); |
| 922 | 922 | if( pManifest==0 ){ |
| 923 | - fossil_fatal("manifest file (%d) is malformed:\n%s\n", | |
| 923 | + fossil_fatal("manifest file (%d) is malformed:\n%s", | |
| 924 | 924 | vid, blob_str(&err)); |
| 925 | 925 | } |
| 926 | 926 | manifest_file_rewind(pManifest); |
| 927 | 927 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 928 | 928 | if( pFile->zUuid==0 ) continue; |
| 929 | 929 |
| --- src/vfile.c | |
| +++ src/vfile.c | |
| @@ -350,11 +350,11 @@ | |
| 350 | } |
| 351 | } |
| 352 | if( verbose ) fossil_print("%s\n", &zName[nRepos]); |
| 353 | if( file_wd_isdir(zName)==1 ){ |
| 354 | /*TODO(dchest): remove directories? */ |
| 355 | fossil_fatal("%s is directory, cannot overwrite\n", zName); |
| 356 | } |
| 357 | if( file_wd_size(zName)>=0 && (isLink || file_wd_islink(0)) ){ |
| 358 | file_delete(zName); |
| 359 | } |
| 360 | if( isLink ){ |
| @@ -435,11 +435,11 @@ | |
| 435 | for(; zName[0]!=0; zName++){ |
| 436 | if( zName[0]=='/' && sqlite3_strglob("/ci-comment-????????????.txt", zName)==0 ){ |
| 437 | return 1; |
| 438 | } |
| 439 | if( zName[0]!='-' ) continue; |
| 440 | for(i=0; i<sizeof(azTemp)/sizeof(azTemp[0]); i++){ |
| 441 | n = (int)strlen(azTemp[i]); |
| 442 | if( memcmp(azTemp[i], zName+1, n) ) continue; |
| 443 | if( zName[n+1]==0 ) return 1; |
| 444 | if( zName[n+1]=='-' ){ |
| 445 | for(j=n+2; zName[j] && fossil_isdigit(zName[j]); j++){} |
| @@ -918,11 +918,11 @@ | |
| 918 | blob_zero(pManOut); |
| 919 | } |
| 920 | db_must_be_within_tree(); |
| 921 | pManifest = manifest_get(vid, CFTYPE_MANIFEST, &err); |
| 922 | if( pManifest==0 ){ |
| 923 | fossil_fatal("manifest file (%d) is malformed:\n%s\n", |
| 924 | vid, blob_str(&err)); |
| 925 | } |
| 926 | manifest_file_rewind(pManifest); |
| 927 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 928 | if( pFile->zUuid==0 ) continue; |
| 929 |
| --- src/vfile.c | |
| +++ src/vfile.c | |
| @@ -350,11 +350,11 @@ | |
| 350 | } |
| 351 | } |
| 352 | if( verbose ) fossil_print("%s\n", &zName[nRepos]); |
| 353 | if( file_wd_isdir(zName)==1 ){ |
| 354 | /*TODO(dchest): remove directories? */ |
| 355 | fossil_fatal("%s is directory, cannot overwrite", zName); |
| 356 | } |
| 357 | if( file_wd_size(zName)>=0 && (isLink || file_wd_islink(0)) ){ |
| 358 | file_delete(zName); |
| 359 | } |
| 360 | if( isLink ){ |
| @@ -435,11 +435,11 @@ | |
| 435 | for(; zName[0]!=0; zName++){ |
| 436 | if( zName[0]=='/' && sqlite3_strglob("/ci-comment-????????????.txt", zName)==0 ){ |
| 437 | return 1; |
| 438 | } |
| 439 | if( zName[0]!='-' ) continue; |
| 440 | for(i=0; i<count(azTemp); i++){ |
| 441 | n = (int)strlen(azTemp[i]); |
| 442 | if( memcmp(azTemp[i], zName+1, n) ) continue; |
| 443 | if( zName[n+1]==0 ) return 1; |
| 444 | if( zName[n+1]=='-' ){ |
| 445 | for(j=n+2; zName[j] && fossil_isdigit(zName[j]); j++){} |
| @@ -918,11 +918,11 @@ | |
| 918 | blob_zero(pManOut); |
| 919 | } |
| 920 | db_must_be_within_tree(); |
| 921 | pManifest = manifest_get(vid, CFTYPE_MANIFEST, &err); |
| 922 | if( pManifest==0 ){ |
| 923 | fossil_fatal("manifest file (%d) is malformed:\n%s", |
| 924 | vid, blob_str(&err)); |
| 925 | } |
| 926 | manifest_file_rewind(pManifest); |
| 927 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 928 | if( pFile->zUuid==0 ) continue; |
| 929 |
+18
-24
| --- src/wiki.c | ||
| +++ src/wiki.c | ||
| @@ -138,11 +138,11 @@ | ||
| 138 | 138 | ** All others become "text/x-fossil-wiki" |
| 139 | 139 | */ |
| 140 | 140 | const char *wiki_filter_mimetypes(const char *zMimetype){ |
| 141 | 141 | if( zMimetype!=0 ){ |
| 142 | 142 | int i; |
| 143 | - for(i=0; i<sizeof(azStyles)/sizeof(azStyles[0]); i+=3){ | |
| 143 | + for(i=0; i<count(azStyles); i+=3){ | |
| 144 | 144 | if( fossil_strcmp(zMimetype,azStyles[i+2])==0 ){ |
| 145 | 145 | return azStyles[i]; |
| 146 | 146 | } |
| 147 | 147 | } |
| 148 | 148 | if( fossil_strcmp(zMimetype, "text/x-markdown")==0 |
| @@ -183,13 +183,13 @@ | ||
| 183 | 183 | void markdown_rules_page(void){ |
| 184 | 184 | Blob x; |
| 185 | 185 | int fTxt = P("txt")!=0; |
| 186 | 186 | style_header("Markdown Formatting Rules"); |
| 187 | 187 | if( fTxt ){ |
| 188 | - style_submenu_element("Formatted", "Formatted", "%R/md_rules"); | |
| 188 | + style_submenu_element("Formatted", "%R/md_rules"); | |
| 189 | 189 | }else{ |
| 190 | - style_submenu_element("Plain-Text", "Plain-Text", "%R/md_rules?txt=1"); | |
| 190 | + style_submenu_element("Plain-Text", "%R/md_rules?txt=1"); | |
| 191 | 191 | } |
| 192 | 192 | blob_init(&x, builtin_text("markdown.md"), -1); |
| 193 | 193 | wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-markdown"); |
| 194 | 194 | blob_reset(&x); |
| 195 | 195 | style_footer(); |
| @@ -231,26 +231,26 @@ | ||
| 231 | 231 | /* |
| 232 | 232 | ** Add some standard submenu elements for wiki screens. |
| 233 | 233 | */ |
| 234 | 234 | static void wiki_standard_submenu(unsigned int ok){ |
| 235 | 235 | if( (ok & W_SRCH)!=0 && search_restrict(SRCH_WIKI)!=0 ){ |
| 236 | - style_submenu_element("Search","Search","%R/wikisrch"); | |
| 236 | + style_submenu_element("Search", "%R/wikisrch"); | |
| 237 | 237 | } |
| 238 | 238 | if( (ok & W_LIST)!=0 ){ |
| 239 | - style_submenu_element("List","List","%R/wcontent"); | |
| 239 | + style_submenu_element("List", "%R/wcontent"); | |
| 240 | 240 | } |
| 241 | 241 | if( (ok & W_HELP)!=0 ){ |
| 242 | - style_submenu_element("Help","Help","%R/wikihelp"); | |
| 242 | + style_submenu_element("Help", "%R/wikihelp"); | |
| 243 | 243 | } |
| 244 | 244 | if( (ok & W_NEW)!=0 && g.anon.NewWiki ){ |
| 245 | - style_submenu_element("New","New","%R/wikinew"); | |
| 245 | + style_submenu_element("New", "%R/wikinew"); | |
| 246 | 246 | } |
| 247 | 247 | #if 0 |
| 248 | 248 | if( (ok & W_BLOG)!=0 |
| 249 | 249 | #endif |
| 250 | 250 | if( (ok & W_SANDBOX)!=0 ){ |
| 251 | - style_submenu_element("Sandbox", "Sandbox", "%R/wiki?name=Sandbox"); | |
| 251 | + style_submenu_element("Sandbox", "%R/wiki?name=Sandbox"); | |
| 252 | 252 | } |
| 253 | 253 | } |
| 254 | 254 | |
| 255 | 255 | /* |
| 256 | 256 | ** WEBPAGE: wikihelp |
| @@ -366,39 +366,33 @@ | ||
| 366 | 366 | } |
| 367 | 367 | } |
| 368 | 368 | zMimetype = wiki_filter_mimetypes(zMimetype); |
| 369 | 369 | if( !g.isHome ){ |
| 370 | 370 | if( rid ){ |
| 371 | - style_submenu_element("Diff", "Last change", | |
| 372 | - "%R/wdiff?name=%T&a=%d", zPageName, rid); | |
| 371 | + style_submenu_element("Diff", "%R/wdiff?name=%T&a=%d", zPageName, rid); | |
| 373 | 372 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 374 | - style_submenu_element("Details", "Details", | |
| 375 | - "%R/info/%s", zUuid); | |
| 373 | + style_submenu_element("Details", "%R/info/%s", zUuid); | |
| 376 | 374 | } |
| 377 | 375 | if( (rid && g.anon.WrWiki) || (!rid && g.anon.NewWiki) ){ |
| 378 | 376 | if( db_get_boolean("wysiwyg-wiki", 0) ){ |
| 379 | - style_submenu_element("Edit", "Edit Wiki Page", | |
| 380 | - "%s/wikiedit?name=%T&wysiwyg=1", | |
| 377 | + style_submenu_element("Edit", "%s/wikiedit?name=%T&wysiwyg=1", | |
| 381 | 378 | g.zTop, zPageName); |
| 382 | 379 | }else{ |
| 383 | - style_submenu_element("Edit", "Edit Wiki Page", | |
| 384 | - "%s/wikiedit?name=%T", | |
| 385 | - g.zTop, zPageName); | |
| 380 | + style_submenu_element("Edit", "%s/wikiedit?name=%T", g.zTop, zPageName); | |
| 386 | 381 | } |
| 387 | 382 | } |
| 388 | 383 | if( rid && g.anon.ApndWiki && g.anon.Attach ){ |
| 389 | - style_submenu_element("Attach", "Add An Attachment", | |
| 384 | + style_submenu_element("Attach", | |
| 390 | 385 | "%s/attachadd?page=%T&from=%s/wiki%%3fname=%T", |
| 391 | 386 | g.zTop, zPageName, g.zTop, zPageName); |
| 392 | 387 | } |
| 393 | 388 | if( rid && g.anon.ApndWiki ){ |
| 394 | - style_submenu_element("Append", "Add A Comment", | |
| 395 | - "%s/wikiappend?name=%T&mimetype=%s", | |
| 389 | + style_submenu_element("Append", "%s/wikiappend?name=%T&mimetype=%s", | |
| 396 | 390 | g.zTop, zPageName, zMimetype); |
| 397 | 391 | } |
| 398 | 392 | if( g.perm.Hyperlink ){ |
| 399 | - style_submenu_element("History", "History", "%s/whistory?name=%T", | |
| 393 | + style_submenu_element("History", "%s/whistory?name=%T", | |
| 400 | 394 | g.zTop, zPageName); |
| 401 | 395 | } |
| 402 | 396 | } |
| 403 | 397 | style_set_current_page("%T?name=%T", g.zPath, zPageName); |
| 404 | 398 | style_header("%s", zPageName); |
| @@ -434,11 +428,11 @@ | ||
| 434 | 428 | ** wiki mimetype. |
| 435 | 429 | */ |
| 436 | 430 | void mimetype_option_menu(const char *zMimetype){ |
| 437 | 431 | unsigned i; |
| 438 | 432 | @ <select name="mimetype" size="1"> |
| 439 | - for(i=0; i<sizeof(azStyles)/sizeof(azStyles[0]); i+=3){ | |
| 433 | + for(i=0; i<count(azStyles); i+=3){ | |
| 440 | 434 | if( fossil_strcmp(zMimetype,azStyles[i])==0 ){ |
| 441 | 435 | @ <option value="%s(azStyles[i])" selected>%s(azStyles[i+1])</option> |
| 442 | 436 | }else{ |
| 443 | 437 | @ <option value="%s(azStyles[i])">%s(azStyles[i+1])</option> |
| 444 | 438 | } |
| @@ -951,13 +945,13 @@ | ||
| 951 | 945 | |
| 952 | 946 | login_check_credentials(); |
| 953 | 947 | if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; } |
| 954 | 948 | style_header("Available Wiki Pages"); |
| 955 | 949 | if( showAll ){ |
| 956 | - style_submenu_element("Active", "Only Active Pages", "%s/wcontent", g.zTop); | |
| 950 | + style_submenu_element("Active", "%s/wcontent", g.zTop); | |
| 957 | 951 | }else{ |
| 958 | - style_submenu_element("All", "All", "%s/wcontent?all=1", g.zTop); | |
| 952 | + style_submenu_element("All", "%s/wcontent?all=1", g.zTop); | |
| 959 | 953 | } |
| 960 | 954 | wiki_standard_submenu(W_ALL_BUT(W_LIST)); |
| 961 | 955 | @ <ul> |
| 962 | 956 | wiki_prepare_page_list(&q); |
| 963 | 957 | while( db_step(&q)==SQLITE_ROW ){ |
| 964 | 958 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -138,11 +138,11 @@ | |
| 138 | ** All others become "text/x-fossil-wiki" |
| 139 | */ |
| 140 | const char *wiki_filter_mimetypes(const char *zMimetype){ |
| 141 | if( zMimetype!=0 ){ |
| 142 | int i; |
| 143 | for(i=0; i<sizeof(azStyles)/sizeof(azStyles[0]); i+=3){ |
| 144 | if( fossil_strcmp(zMimetype,azStyles[i+2])==0 ){ |
| 145 | return azStyles[i]; |
| 146 | } |
| 147 | } |
| 148 | if( fossil_strcmp(zMimetype, "text/x-markdown")==0 |
| @@ -183,13 +183,13 @@ | |
| 183 | void markdown_rules_page(void){ |
| 184 | Blob x; |
| 185 | int fTxt = P("txt")!=0; |
| 186 | style_header("Markdown Formatting Rules"); |
| 187 | if( fTxt ){ |
| 188 | style_submenu_element("Formatted", "Formatted", "%R/md_rules"); |
| 189 | }else{ |
| 190 | style_submenu_element("Plain-Text", "Plain-Text", "%R/md_rules?txt=1"); |
| 191 | } |
| 192 | blob_init(&x, builtin_text("markdown.md"), -1); |
| 193 | wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-markdown"); |
| 194 | blob_reset(&x); |
| 195 | style_footer(); |
| @@ -231,26 +231,26 @@ | |
| 231 | /* |
| 232 | ** Add some standard submenu elements for wiki screens. |
| 233 | */ |
| 234 | static void wiki_standard_submenu(unsigned int ok){ |
| 235 | if( (ok & W_SRCH)!=0 && search_restrict(SRCH_WIKI)!=0 ){ |
| 236 | style_submenu_element("Search","Search","%R/wikisrch"); |
| 237 | } |
| 238 | if( (ok & W_LIST)!=0 ){ |
| 239 | style_submenu_element("List","List","%R/wcontent"); |
| 240 | } |
| 241 | if( (ok & W_HELP)!=0 ){ |
| 242 | style_submenu_element("Help","Help","%R/wikihelp"); |
| 243 | } |
| 244 | if( (ok & W_NEW)!=0 && g.anon.NewWiki ){ |
| 245 | style_submenu_element("New","New","%R/wikinew"); |
| 246 | } |
| 247 | #if 0 |
| 248 | if( (ok & W_BLOG)!=0 |
| 249 | #endif |
| 250 | if( (ok & W_SANDBOX)!=0 ){ |
| 251 | style_submenu_element("Sandbox", "Sandbox", "%R/wiki?name=Sandbox"); |
| 252 | } |
| 253 | } |
| 254 | |
| 255 | /* |
| 256 | ** WEBPAGE: wikihelp |
| @@ -366,39 +366,33 @@ | |
| 366 | } |
| 367 | } |
| 368 | zMimetype = wiki_filter_mimetypes(zMimetype); |
| 369 | if( !g.isHome ){ |
| 370 | if( rid ){ |
| 371 | style_submenu_element("Diff", "Last change", |
| 372 | "%R/wdiff?name=%T&a=%d", zPageName, rid); |
| 373 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 374 | style_submenu_element("Details", "Details", |
| 375 | "%R/info/%s", zUuid); |
| 376 | } |
| 377 | if( (rid && g.anon.WrWiki) || (!rid && g.anon.NewWiki) ){ |
| 378 | if( db_get_boolean("wysiwyg-wiki", 0) ){ |
| 379 | style_submenu_element("Edit", "Edit Wiki Page", |
| 380 | "%s/wikiedit?name=%T&wysiwyg=1", |
| 381 | g.zTop, zPageName); |
| 382 | }else{ |
| 383 | style_submenu_element("Edit", "Edit Wiki Page", |
| 384 | "%s/wikiedit?name=%T", |
| 385 | g.zTop, zPageName); |
| 386 | } |
| 387 | } |
| 388 | if( rid && g.anon.ApndWiki && g.anon.Attach ){ |
| 389 | style_submenu_element("Attach", "Add An Attachment", |
| 390 | "%s/attachadd?page=%T&from=%s/wiki%%3fname=%T", |
| 391 | g.zTop, zPageName, g.zTop, zPageName); |
| 392 | } |
| 393 | if( rid && g.anon.ApndWiki ){ |
| 394 | style_submenu_element("Append", "Add A Comment", |
| 395 | "%s/wikiappend?name=%T&mimetype=%s", |
| 396 | g.zTop, zPageName, zMimetype); |
| 397 | } |
| 398 | if( g.perm.Hyperlink ){ |
| 399 | style_submenu_element("History", "History", "%s/whistory?name=%T", |
| 400 | g.zTop, zPageName); |
| 401 | } |
| 402 | } |
| 403 | style_set_current_page("%T?name=%T", g.zPath, zPageName); |
| 404 | style_header("%s", zPageName); |
| @@ -434,11 +428,11 @@ | |
| 434 | ** wiki mimetype. |
| 435 | */ |
| 436 | void mimetype_option_menu(const char *zMimetype){ |
| 437 | unsigned i; |
| 438 | @ <select name="mimetype" size="1"> |
| 439 | for(i=0; i<sizeof(azStyles)/sizeof(azStyles[0]); i+=3){ |
| 440 | if( fossil_strcmp(zMimetype,azStyles[i])==0 ){ |
| 441 | @ <option value="%s(azStyles[i])" selected>%s(azStyles[i+1])</option> |
| 442 | }else{ |
| 443 | @ <option value="%s(azStyles[i])">%s(azStyles[i+1])</option> |
| 444 | } |
| @@ -951,13 +945,13 @@ | |
| 951 | |
| 952 | login_check_credentials(); |
| 953 | if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; } |
| 954 | style_header("Available Wiki Pages"); |
| 955 | if( showAll ){ |
| 956 | style_submenu_element("Active", "Only Active Pages", "%s/wcontent", g.zTop); |
| 957 | }else{ |
| 958 | style_submenu_element("All", "All", "%s/wcontent?all=1", g.zTop); |
| 959 | } |
| 960 | wiki_standard_submenu(W_ALL_BUT(W_LIST)); |
| 961 | @ <ul> |
| 962 | wiki_prepare_page_list(&q); |
| 963 | while( db_step(&q)==SQLITE_ROW ){ |
| 964 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -138,11 +138,11 @@ | |
| 138 | ** All others become "text/x-fossil-wiki" |
| 139 | */ |
| 140 | const char *wiki_filter_mimetypes(const char *zMimetype){ |
| 141 | if( zMimetype!=0 ){ |
| 142 | int i; |
| 143 | for(i=0; i<count(azStyles); i+=3){ |
| 144 | if( fossil_strcmp(zMimetype,azStyles[i+2])==0 ){ |
| 145 | return azStyles[i]; |
| 146 | } |
| 147 | } |
| 148 | if( fossil_strcmp(zMimetype, "text/x-markdown")==0 |
| @@ -183,13 +183,13 @@ | |
| 183 | void markdown_rules_page(void){ |
| 184 | Blob x; |
| 185 | int fTxt = P("txt")!=0; |
| 186 | style_header("Markdown Formatting Rules"); |
| 187 | if( fTxt ){ |
| 188 | style_submenu_element("Formatted", "%R/md_rules"); |
| 189 | }else{ |
| 190 | style_submenu_element("Plain-Text", "%R/md_rules?txt=1"); |
| 191 | } |
| 192 | blob_init(&x, builtin_text("markdown.md"), -1); |
| 193 | wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-markdown"); |
| 194 | blob_reset(&x); |
| 195 | style_footer(); |
| @@ -231,26 +231,26 @@ | |
| 231 | /* |
| 232 | ** Add some standard submenu elements for wiki screens. |
| 233 | */ |
| 234 | static void wiki_standard_submenu(unsigned int ok){ |
| 235 | if( (ok & W_SRCH)!=0 && search_restrict(SRCH_WIKI)!=0 ){ |
| 236 | style_submenu_element("Search", "%R/wikisrch"); |
| 237 | } |
| 238 | if( (ok & W_LIST)!=0 ){ |
| 239 | style_submenu_element("List", "%R/wcontent"); |
| 240 | } |
| 241 | if( (ok & W_HELP)!=0 ){ |
| 242 | style_submenu_element("Help", "%R/wikihelp"); |
| 243 | } |
| 244 | if( (ok & W_NEW)!=0 && g.anon.NewWiki ){ |
| 245 | style_submenu_element("New", "%R/wikinew"); |
| 246 | } |
| 247 | #if 0 |
| 248 | if( (ok & W_BLOG)!=0 |
| 249 | #endif |
| 250 | if( (ok & W_SANDBOX)!=0 ){ |
| 251 | style_submenu_element("Sandbox", "%R/wiki?name=Sandbox"); |
| 252 | } |
| 253 | } |
| 254 | |
| 255 | /* |
| 256 | ** WEBPAGE: wikihelp |
| @@ -366,39 +366,33 @@ | |
| 366 | } |
| 367 | } |
| 368 | zMimetype = wiki_filter_mimetypes(zMimetype); |
| 369 | if( !g.isHome ){ |
| 370 | if( rid ){ |
| 371 | style_submenu_element("Diff", "%R/wdiff?name=%T&a=%d", zPageName, rid); |
| 372 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 373 | style_submenu_element("Details", "%R/info/%s", zUuid); |
| 374 | } |
| 375 | if( (rid && g.anon.WrWiki) || (!rid && g.anon.NewWiki) ){ |
| 376 | if( db_get_boolean("wysiwyg-wiki", 0) ){ |
| 377 | style_submenu_element("Edit", "%s/wikiedit?name=%T&wysiwyg=1", |
| 378 | g.zTop, zPageName); |
| 379 | }else{ |
| 380 | style_submenu_element("Edit", "%s/wikiedit?name=%T", g.zTop, zPageName); |
| 381 | } |
| 382 | } |
| 383 | if( rid && g.anon.ApndWiki && g.anon.Attach ){ |
| 384 | style_submenu_element("Attach", |
| 385 | "%s/attachadd?page=%T&from=%s/wiki%%3fname=%T", |
| 386 | g.zTop, zPageName, g.zTop, zPageName); |
| 387 | } |
| 388 | if( rid && g.anon.ApndWiki ){ |
| 389 | style_submenu_element("Append", "%s/wikiappend?name=%T&mimetype=%s", |
| 390 | g.zTop, zPageName, zMimetype); |
| 391 | } |
| 392 | if( g.perm.Hyperlink ){ |
| 393 | style_submenu_element("History", "%s/whistory?name=%T", |
| 394 | g.zTop, zPageName); |
| 395 | } |
| 396 | } |
| 397 | style_set_current_page("%T?name=%T", g.zPath, zPageName); |
| 398 | style_header("%s", zPageName); |
| @@ -434,11 +428,11 @@ | |
| 428 | ** wiki mimetype. |
| 429 | */ |
| 430 | void mimetype_option_menu(const char *zMimetype){ |
| 431 | unsigned i; |
| 432 | @ <select name="mimetype" size="1"> |
| 433 | for(i=0; i<count(azStyles); i+=3){ |
| 434 | if( fossil_strcmp(zMimetype,azStyles[i])==0 ){ |
| 435 | @ <option value="%s(azStyles[i])" selected>%s(azStyles[i+1])</option> |
| 436 | }else{ |
| 437 | @ <option value="%s(azStyles[i])">%s(azStyles[i+1])</option> |
| 438 | } |
| @@ -951,13 +945,13 @@ | |
| 945 | |
| 946 | login_check_credentials(); |
| 947 | if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; } |
| 948 | style_header("Available Wiki Pages"); |
| 949 | if( showAll ){ |
| 950 | style_submenu_element("Active", "%s/wcontent", g.zTop); |
| 951 | }else{ |
| 952 | style_submenu_element("All", "%s/wcontent?all=1", g.zTop); |
| 953 | } |
| 954 | wiki_standard_submenu(W_ALL_BUT(W_LIST)); |
| 955 | @ <ul> |
| 956 | wiki_prepare_page_list(&q); |
| 957 | while( db_step(&q)==SQLITE_ROW ){ |
| 958 |
+5
-5
| --- src/wikiformat.c | ||
| +++ src/wikiformat.c | ||
| @@ -145,11 +145,11 @@ | ||
| 145 | 145 | ** Use binary search to locate a tag in the aAttribute[] table. |
| 146 | 146 | */ |
| 147 | 147 | static int findAttr(const char *z){ |
| 148 | 148 | int i, c, first, last; |
| 149 | 149 | first = 1; |
| 150 | - last = sizeof(aAttribute)/sizeof(aAttribute[0]) - 1; | |
| 150 | + last = count(aAttribute) - 1; | |
| 151 | 151 | while( first<=last ){ |
| 152 | 152 | i = (first+last)/2; |
| 153 | 153 | c = fossil_strcmp(aAttribute[i].zName, z); |
| 154 | 154 | if( c==0 ){ |
| 155 | 155 | return i; |
| @@ -372,11 +372,11 @@ | ||
| 372 | 372 | AMSK_ID|AMSK_TYPE }, |
| 373 | 373 | }; |
| 374 | 374 | |
| 375 | 375 | void show_allowed_wiki_markup( void ){ |
| 376 | 376 | int i; /* loop over allowedAttr */ |
| 377 | - for( i=1 ; i<=sizeof(aMarkup)/sizeof(aMarkup[0]) - 1 ; i++ ){ | |
| 377 | + for( i=1 ; i<=count(aMarkup) - 1 ; i++ ){ | |
| 378 | 378 | @ <%s(aMarkup[i].zName)> |
| 379 | 379 | } |
| 380 | 380 | } |
| 381 | 381 | |
| 382 | 382 | /* |
| @@ -383,11 +383,11 @@ | ||
| 383 | 383 | ** Use binary search to locate a tag in the aMarkup[] table. |
| 384 | 384 | */ |
| 385 | 385 | static int findTag(const char *z){ |
| 386 | 386 | int i, c, first, last; |
| 387 | 387 | first = 1; |
| 388 | - last = sizeof(aMarkup)/sizeof(aMarkup[0]) - 1; | |
| 388 | + last = count(aMarkup) - 1; | |
| 389 | 389 | while( first<=last ){ |
| 390 | 390 | i = (first+last)/2; |
| 391 | 391 | c = fossil_strcmp(aMarkup[i].zName, z); |
| 392 | 392 | if( c==0 ){ |
| 393 | 393 | assert( aMarkup[i].iCode==i ); |
| @@ -947,11 +947,11 @@ | ||
| 947 | 947 | for(j=*pN; fossil_isspace(z[j]); j++){} |
| 948 | 948 | zTag = mprintf("%.*s", i-j, &z[j]); |
| 949 | 949 | j = (int)strlen(zTag); |
| 950 | 950 | while( j>0 && fossil_isspace(zTag[j-1]) ){ j--; } |
| 951 | 951 | if( j==0 ) return 0; |
| 952 | - style_submenu_element(zTag, zTag, "%s", zHref); | |
| 952 | + style_submenu_element(zTag, "%s", zHref); | |
| 953 | 953 | *pN = i+4; |
| 954 | 954 | return 1; |
| 955 | 955 | } |
| 956 | 956 | |
| 957 | 957 | /* |
| @@ -2187,11 +2187,11 @@ | ||
| 2187 | 2187 | { 4, '<', "<" }, |
| 2188 | 2188 | { 4, '>', ">" }, |
| 2189 | 2189 | { 6, ' ', " " }, |
| 2190 | 2190 | }; |
| 2191 | 2191 | int jj; |
| 2192 | - for(jj=0; jj<ArraySize(aEntity); jj++){ | |
| 2192 | + for(jj=0; jj<count(aEntity); jj++){ | |
| 2193 | 2193 | if( aEntity[jj].n==n && strncmp(aEntity[jj].z,zIn,n)==0 ){ |
| 2194 | 2194 | c = aEntity[jj].c; |
| 2195 | 2195 | break; |
| 2196 | 2196 | } |
| 2197 | 2197 | } |
| 2198 | 2198 |
| --- src/wikiformat.c | |
| +++ src/wikiformat.c | |
| @@ -145,11 +145,11 @@ | |
| 145 | ** Use binary search to locate a tag in the aAttribute[] table. |
| 146 | */ |
| 147 | static int findAttr(const char *z){ |
| 148 | int i, c, first, last; |
| 149 | first = 1; |
| 150 | last = sizeof(aAttribute)/sizeof(aAttribute[0]) - 1; |
| 151 | while( first<=last ){ |
| 152 | i = (first+last)/2; |
| 153 | c = fossil_strcmp(aAttribute[i].zName, z); |
| 154 | if( c==0 ){ |
| 155 | return i; |
| @@ -372,11 +372,11 @@ | |
| 372 | AMSK_ID|AMSK_TYPE }, |
| 373 | }; |
| 374 | |
| 375 | void show_allowed_wiki_markup( void ){ |
| 376 | int i; /* loop over allowedAttr */ |
| 377 | for( i=1 ; i<=sizeof(aMarkup)/sizeof(aMarkup[0]) - 1 ; i++ ){ |
| 378 | @ <%s(aMarkup[i].zName)> |
| 379 | } |
| 380 | } |
| 381 | |
| 382 | /* |
| @@ -383,11 +383,11 @@ | |
| 383 | ** Use binary search to locate a tag in the aMarkup[] table. |
| 384 | */ |
| 385 | static int findTag(const char *z){ |
| 386 | int i, c, first, last; |
| 387 | first = 1; |
| 388 | last = sizeof(aMarkup)/sizeof(aMarkup[0]) - 1; |
| 389 | while( first<=last ){ |
| 390 | i = (first+last)/2; |
| 391 | c = fossil_strcmp(aMarkup[i].zName, z); |
| 392 | if( c==0 ){ |
| 393 | assert( aMarkup[i].iCode==i ); |
| @@ -947,11 +947,11 @@ | |
| 947 | for(j=*pN; fossil_isspace(z[j]); j++){} |
| 948 | zTag = mprintf("%.*s", i-j, &z[j]); |
| 949 | j = (int)strlen(zTag); |
| 950 | while( j>0 && fossil_isspace(zTag[j-1]) ){ j--; } |
| 951 | if( j==0 ) return 0; |
| 952 | style_submenu_element(zTag, zTag, "%s", zHref); |
| 953 | *pN = i+4; |
| 954 | return 1; |
| 955 | } |
| 956 | |
| 957 | /* |
| @@ -2187,11 +2187,11 @@ | |
| 2187 | { 4, '<', "<" }, |
| 2188 | { 4, '>', ">" }, |
| 2189 | { 6, ' ', " " }, |
| 2190 | }; |
| 2191 | int jj; |
| 2192 | for(jj=0; jj<ArraySize(aEntity); jj++){ |
| 2193 | if( aEntity[jj].n==n && strncmp(aEntity[jj].z,zIn,n)==0 ){ |
| 2194 | c = aEntity[jj].c; |
| 2195 | break; |
| 2196 | } |
| 2197 | } |
| 2198 |
| --- src/wikiformat.c | |
| +++ src/wikiformat.c | |
| @@ -145,11 +145,11 @@ | |
| 145 | ** Use binary search to locate a tag in the aAttribute[] table. |
| 146 | */ |
| 147 | static int findAttr(const char *z){ |
| 148 | int i, c, first, last; |
| 149 | first = 1; |
| 150 | last = count(aAttribute) - 1; |
| 151 | while( first<=last ){ |
| 152 | i = (first+last)/2; |
| 153 | c = fossil_strcmp(aAttribute[i].zName, z); |
| 154 | if( c==0 ){ |
| 155 | return i; |
| @@ -372,11 +372,11 @@ | |
| 372 | AMSK_ID|AMSK_TYPE }, |
| 373 | }; |
| 374 | |
| 375 | void show_allowed_wiki_markup( void ){ |
| 376 | int i; /* loop over allowedAttr */ |
| 377 | for( i=1 ; i<=count(aMarkup) - 1 ; i++ ){ |
| 378 | @ <%s(aMarkup[i].zName)> |
| 379 | } |
| 380 | } |
| 381 | |
| 382 | /* |
| @@ -383,11 +383,11 @@ | |
| 383 | ** Use binary search to locate a tag in the aMarkup[] table. |
| 384 | */ |
| 385 | static int findTag(const char *z){ |
| 386 | int i, c, first, last; |
| 387 | first = 1; |
| 388 | last = count(aMarkup) - 1; |
| 389 | while( first<=last ){ |
| 390 | i = (first+last)/2; |
| 391 | c = fossil_strcmp(aMarkup[i].zName, z); |
| 392 | if( c==0 ){ |
| 393 | assert( aMarkup[i].iCode==i ); |
| @@ -947,11 +947,11 @@ | |
| 947 | for(j=*pN; fossil_isspace(z[j]); j++){} |
| 948 | zTag = mprintf("%.*s", i-j, &z[j]); |
| 949 | j = (int)strlen(zTag); |
| 950 | while( j>0 && fossil_isspace(zTag[j-1]) ){ j--; } |
| 951 | if( j==0 ) return 0; |
| 952 | style_submenu_element(zTag, "%s", zHref); |
| 953 | *pN = i+4; |
| 954 | return 1; |
| 955 | } |
| 956 | |
| 957 | /* |
| @@ -2187,11 +2187,11 @@ | |
| 2187 | { 4, '<', "<" }, |
| 2188 | { 4, '>', ">" }, |
| 2189 | { 6, ' ', " " }, |
| 2190 | }; |
| 2191 | int jj; |
| 2192 | for(jj=0; jj<count(aEntity); jj++){ |
| 2193 | if( aEntity[jj].n==n && strncmp(aEntity[jj].z,zIn,n)==0 ){ |
| 2194 | c = aEntity[jj].c; |
| 2195 | break; |
| 2196 | } |
| 2197 | } |
| 2198 |
+17
-2
| --- src/winhttp.c | ||
| +++ src/winhttp.c | ||
| @@ -306,10 +306,14 @@ | ||
| 306 | 306 | SOCKADDR_IN addr; |
| 307 | 307 | int idCnt = 0; |
| 308 | 308 | int iPort = mnPort; |
| 309 | 309 | Blob options; |
| 310 | 310 | wchar_t zTmpPath[MAX_PATH]; |
| 311 | +#if USE_SEE | |
| 312 | + const char *zSavedKey = 0; | |
| 313 | + size_t savedKeySize = 0; | |
| 314 | +#endif | |
| 311 | 315 | |
| 312 | 316 | blob_zero(&options); |
| 313 | 317 | if( zBaseUrl ){ |
| 314 | 318 | blob_appendf(&options, " --baseurl %s", zBaseUrl); |
| 315 | 319 | } |
| @@ -326,10 +330,18 @@ | ||
| 326 | 330 | blob_appendf(&options, " --th-trace"); |
| 327 | 331 | } |
| 328 | 332 | if( flags & HTTP_SERVER_REPOLIST ){ |
| 329 | 333 | blob_appendf(&options, " --repolist"); |
| 330 | 334 | } |
| 335 | +#if USE_SEE | |
| 336 | + zSavedKey = db_get_saved_encryption_key(); | |
| 337 | + savedKeySize = db_get_saved_encryption_key_size(); | |
| 338 | + if( zSavedKey!=0 && savedKeySize>0 ){ | |
| 339 | + blob_appendf(&options, " --usepidkey %lu:%p:%u", GetCurrentProcessId(), | |
| 340 | + zSavedKey, savedKeySize); | |
| 341 | + } | |
| 342 | +#endif | |
| 331 | 343 | if( WSAStartup(MAKEWORD(1,1), &wd) ){ |
| 332 | 344 | fossil_fatal("unable to initialize winsock"); |
| 333 | 345 | } |
| 334 | 346 | while( iPort<=mxPort ){ |
| 335 | 347 | s = socket(AF_INET, SOCK_STREAM, 0); |
| @@ -654,11 +666,13 @@ | ||
| 654 | 666 | } |
| 655 | 667 | } |
| 656 | 668 | return 0; |
| 657 | 669 | } |
| 658 | 670 | |
| 659 | -/* dupe ifdef needed for mkindex | |
| 671 | +/* Duplicate #ifdef needed for mkindex */ | |
| 672 | +#ifdef _WIN32 | |
| 673 | +/* | |
| 660 | 674 | ** COMMAND: winsrv* |
| 661 | 675 | ** |
| 662 | 676 | ** Usage: %fossil winsrv METHOD ?SERVICE-NAME? ?OPTIONS? |
| 663 | 677 | ** |
| 664 | 678 | ** Where METHOD is one of: create delete show start stop. |
| @@ -1103,6 +1117,7 @@ | ||
| 1103 | 1117 | fossil_fatal("METHOD should be one of:" |
| 1104 | 1118 | " create delete show start stop"); |
| 1105 | 1119 | } |
| 1106 | 1120 | return; |
| 1107 | 1121 | } |
| 1108 | -#endif /* _WIN32 -- This code is for win32 only */ | |
| 1122 | +#endif /* _WIN32 -- dupe needed for mkindex */ | |
| 1123 | +#endif /* _WIN32 -- This code is for win32 only */ | |
| 1109 | 1124 |
| --- src/winhttp.c | |
| +++ src/winhttp.c | |
| @@ -306,10 +306,14 @@ | |
| 306 | SOCKADDR_IN addr; |
| 307 | int idCnt = 0; |
| 308 | int iPort = mnPort; |
| 309 | Blob options; |
| 310 | wchar_t zTmpPath[MAX_PATH]; |
| 311 | |
| 312 | blob_zero(&options); |
| 313 | if( zBaseUrl ){ |
| 314 | blob_appendf(&options, " --baseurl %s", zBaseUrl); |
| 315 | } |
| @@ -326,10 +330,18 @@ | |
| 326 | blob_appendf(&options, " --th-trace"); |
| 327 | } |
| 328 | if( flags & HTTP_SERVER_REPOLIST ){ |
| 329 | blob_appendf(&options, " --repolist"); |
| 330 | } |
| 331 | if( WSAStartup(MAKEWORD(1,1), &wd) ){ |
| 332 | fossil_fatal("unable to initialize winsock"); |
| 333 | } |
| 334 | while( iPort<=mxPort ){ |
| 335 | s = socket(AF_INET, SOCK_STREAM, 0); |
| @@ -654,11 +666,13 @@ | |
| 654 | } |
| 655 | } |
| 656 | return 0; |
| 657 | } |
| 658 | |
| 659 | /* dupe ifdef needed for mkindex |
| 660 | ** COMMAND: winsrv* |
| 661 | ** |
| 662 | ** Usage: %fossil winsrv METHOD ?SERVICE-NAME? ?OPTIONS? |
| 663 | ** |
| 664 | ** Where METHOD is one of: create delete show start stop. |
| @@ -1103,6 +1117,7 @@ | |
| 1103 | fossil_fatal("METHOD should be one of:" |
| 1104 | " create delete show start stop"); |
| 1105 | } |
| 1106 | return; |
| 1107 | } |
| 1108 | #endif /* _WIN32 -- This code is for win32 only */ |
| 1109 |
| --- src/winhttp.c | |
| +++ src/winhttp.c | |
| @@ -306,10 +306,14 @@ | |
| 306 | SOCKADDR_IN addr; |
| 307 | int idCnt = 0; |
| 308 | int iPort = mnPort; |
| 309 | Blob options; |
| 310 | wchar_t zTmpPath[MAX_PATH]; |
| 311 | #if USE_SEE |
| 312 | const char *zSavedKey = 0; |
| 313 | size_t savedKeySize = 0; |
| 314 | #endif |
| 315 | |
| 316 | blob_zero(&options); |
| 317 | if( zBaseUrl ){ |
| 318 | blob_appendf(&options, " --baseurl %s", zBaseUrl); |
| 319 | } |
| @@ -326,10 +330,18 @@ | |
| 330 | blob_appendf(&options, " --th-trace"); |
| 331 | } |
| 332 | if( flags & HTTP_SERVER_REPOLIST ){ |
| 333 | blob_appendf(&options, " --repolist"); |
| 334 | } |
| 335 | #if USE_SEE |
| 336 | zSavedKey = db_get_saved_encryption_key(); |
| 337 | savedKeySize = db_get_saved_encryption_key_size(); |
| 338 | if( zSavedKey!=0 && savedKeySize>0 ){ |
| 339 | blob_appendf(&options, " --usepidkey %lu:%p:%u", GetCurrentProcessId(), |
| 340 | zSavedKey, savedKeySize); |
| 341 | } |
| 342 | #endif |
| 343 | if( WSAStartup(MAKEWORD(1,1), &wd) ){ |
| 344 | fossil_fatal("unable to initialize winsock"); |
| 345 | } |
| 346 | while( iPort<=mxPort ){ |
| 347 | s = socket(AF_INET, SOCK_STREAM, 0); |
| @@ -654,11 +666,13 @@ | |
| 666 | } |
| 667 | } |
| 668 | return 0; |
| 669 | } |
| 670 | |
| 671 | /* Duplicate #ifdef needed for mkindex */ |
| 672 | #ifdef _WIN32 |
| 673 | /* |
| 674 | ** COMMAND: winsrv* |
| 675 | ** |
| 676 | ** Usage: %fossil winsrv METHOD ?SERVICE-NAME? ?OPTIONS? |
| 677 | ** |
| 678 | ** Where METHOD is one of: create delete show start stop. |
| @@ -1103,6 +1117,7 @@ | |
| 1117 | fossil_fatal("METHOD should be one of:" |
| 1118 | " create delete show start stop"); |
| 1119 | } |
| 1120 | return; |
| 1121 | } |
| 1122 | #endif /* _WIN32 -- dupe needed for mkindex */ |
| 1123 | #endif /* _WIN32 -- This code is for win32 only */ |
| 1124 |
+1
-1
| --- src/xfer.c | ||
| +++ src/xfer.c | ||
| @@ -2140,11 +2140,11 @@ | ||
| 2140 | 2140 | } |
| 2141 | 2141 | if( syncFlags & (SYNC_UV_TRACE|SYNC_UV_DRYRUN) ){ |
| 2142 | 2142 | const char *zMsg = 0; |
| 2143 | 2143 | switch( iStatus ){ |
| 2144 | 2144 | case 0: |
| 2145 | - case 1: zMsg = "UV-PULL"; break; | |
| 2145 | + case 1: zMsg = "UV-PULL"; break; | |
| 2146 | 2146 | case 2: zMsg = "UV-PULL-MTIME-ONLY"; break; |
| 2147 | 2147 | case 4: zMsg = "UV-PUSH-MTIME-ONLY"; break; |
| 2148 | 2148 | case 5: zMsg = "UV-PUSH"; break; |
| 2149 | 2149 | } |
| 2150 | 2150 | if( zMsg ) fossil_print("\r%s: %s\n", zMsg, zName); |
| 2151 | 2151 | |
| 2152 | 2152 | ADDED test/diff.test |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -2140,11 +2140,11 @@ | |
| 2140 | } |
| 2141 | if( syncFlags & (SYNC_UV_TRACE|SYNC_UV_DRYRUN) ){ |
| 2142 | const char *zMsg = 0; |
| 2143 | switch( iStatus ){ |
| 2144 | case 0: |
| 2145 | case 1: zMsg = "UV-PULL"; break; |
| 2146 | case 2: zMsg = "UV-PULL-MTIME-ONLY"; break; |
| 2147 | case 4: zMsg = "UV-PUSH-MTIME-ONLY"; break; |
| 2148 | case 5: zMsg = "UV-PUSH"; break; |
| 2149 | } |
| 2150 | if( zMsg ) fossil_print("\r%s: %s\n", zMsg, zName); |
| 2151 | |
| 2152 | DDED test/diff.test |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -2140,11 +2140,11 @@ | |
| 2140 | } |
| 2141 | if( syncFlags & (SYNC_UV_TRACE|SYNC_UV_DRYRUN) ){ |
| 2142 | const char *zMsg = 0; |
| 2143 | switch( iStatus ){ |
| 2144 | case 0: |
| 2145 | case 1: zMsg = "UV-PULL"; break; |
| 2146 | case 2: zMsg = "UV-PULL-MTIME-ONLY"; break; |
| 2147 | case 4: zMsg = "UV-PUSH-MTIME-ONLY"; break; |
| 2148 | case 5: zMsg = "UV-PUSH"; break; |
| 2149 | } |
| 2150 | if( zMsg ) fossil_print("\r%s: %s\n", zMsg, zName); |
| 2151 | |
| 2152 | DDED test/diff.test |
+31
| --- a/test/diff.test | ||
| +++ b/test/diff.test | ||
| @@ -0,0 +1,31 @@ | ||
| 1 | +16384]" | |
| 2 | +write_file file4_file file4.dat "test file 4 (l16384]\ntwo" | |
| 3 | +write_file f163842016 D. Richard Hipp | |
| 4 | +# | |
| 5 | +# This program is free software; you can redistribute it and/or | |
| 6 | +# modify it under the terms of the Simplified BSD License (also | |
| 7 | +# known as the "2-Clause License" or "FreeBSD License".) | |
| 8 | +# | |
| 9 | +# This program is distributed in the hope that it will be useful, | |
| 10 | +# but without any warranty; without even the implied warranty of | |
| 11 | +# merchantability or fitness for a particular purpose. | |
| 12 | +# | |
| 13 | +# Author contact information: | |
| 14 | +# [email protected] | |
| 15 | +# http://www.hwaci.com/drh/ | |
| 16 | +# | |
| 17 | +############################################################################ | |
| 18 | +# | |
| 19 | +# Tests for the diff command. | |
| 20 | +# | |
| 21 | + | |
| 22 | +require_no_open_checkout | |
| 23 | + | |
| 24 | +test_setup; set rootDir [file normalize [pwd]] | |
| 25 | + | |
| 26 | +################################### | |
| 27 | +# Tests of binary file det# | |
| 28 | +# Coite_file file1.dat z 32768] | |
| 29 | +fossil diff file1.dat | |
| 30 | + | |
| 31 | +test diff-file1-1 {[normalize_restest_cleanup |
| --- a/test/diff.test | |
| +++ b/test/diff.test | |
| @@ -0,0 +1,31 @@ | |
| --- a/test/diff.test | |
| +++ b/test/diff.test | |
| @@ -0,0 +1,31 @@ | |
| 1 | 16384]" |
| 2 | write_file file4_file file4.dat "test file 4 (l16384]\ntwo" |
| 3 | write_file f163842016 D. Richard Hipp |
| 4 | # |
| 5 | # This program is free software; you can redistribute it and/or |
| 6 | # modify it under the terms of the Simplified BSD License (also |
| 7 | # known as the "2-Clause License" or "FreeBSD License".) |
| 8 | # |
| 9 | # This program is distributed in the hope that it will be useful, |
| 10 | # but without any warranty; without even the implied warranty of |
| 11 | # merchantability or fitness for a particular purpose. |
| 12 | # |
| 13 | # Author contact information: |
| 14 | # [email protected] |
| 15 | # http://www.hwaci.com/drh/ |
| 16 | # |
| 17 | ############################################################################ |
| 18 | # |
| 19 | # Tests for the diff command. |
| 20 | # |
| 21 | |
| 22 | require_no_open_checkout |
| 23 | |
| 24 | test_setup; set rootDir [file normalize [pwd]] |
| 25 | |
| 26 | ################################### |
| 27 | # Tests of binary file det# |
| 28 | # Coite_file file1.dat z 32768] |
| 29 | fossil diff file1.dat |
| 30 | |
| 31 | test diff-file1-1 {[normalize_restest_cleanup |
| --- test/graph-test-1.wiki | ||
| +++ test/graph-test-1.wiki | ||
| @@ -66,10 +66,13 @@ | ||
| 66 | 66 | * <a href="../../../timeline?c=20015206bc" |
| 67 | 67 | target="testwindow"> |
| 68 | 68 | This timeline has a hidden commit.</a> Click Unhide to reveal. |
| 69 | 69 | * <a href="../../../timeline?y=ci&n=15&b=2a4e4cf03e" |
| 70 | 70 | target="testwindow">Isolated check-ins.</a> |
| 71 | + * <a href="../../../timeline?b=0fa60142&n=50" | |
| 72 | + target="testwindow">Single branch raiser from bottom of page | |
| 73 | + up to checkins 057e4b and d3cc6d</a> | |
| 71 | 74 | |
| 72 | 75 | External: |
| 73 | 76 | |
| 74 | 77 | * <a href="http://www.sqlite.org/src/timeline?c=2010-09-29&nd" |
| 75 | 78 | target="testwindow">Timewarp due to a mis-configured system clock.</a> |
| 76 | 79 |
| --- test/graph-test-1.wiki | |
| +++ test/graph-test-1.wiki | |
| @@ -66,10 +66,13 @@ | |
| 66 | * <a href="../../../timeline?c=20015206bc" |
| 67 | target="testwindow"> |
| 68 | This timeline has a hidden commit.</a> Click Unhide to reveal. |
| 69 | * <a href="../../../timeline?y=ci&n=15&b=2a4e4cf03e" |
| 70 | target="testwindow">Isolated check-ins.</a> |
| 71 | |
| 72 | External: |
| 73 | |
| 74 | * <a href="http://www.sqlite.org/src/timeline?c=2010-09-29&nd" |
| 75 | target="testwindow">Timewarp due to a mis-configured system clock.</a> |
| 76 |
| --- test/graph-test-1.wiki | |
| +++ test/graph-test-1.wiki | |
| @@ -66,10 +66,13 @@ | |
| 66 | * <a href="../../../timeline?c=20015206bc" |
| 67 | target="testwindow"> |
| 68 | This timeline has a hidden commit.</a> Click Unhide to reveal. |
| 69 | * <a href="../../../timeline?y=ci&n=15&b=2a4e4cf03e" |
| 70 | target="testwindow">Isolated check-ins.</a> |
| 71 | * <a href="../../../timeline?b=0fa60142&n=50" |
| 72 | target="testwindow">Single branch raiser from bottom of page |
| 73 | up to checkins 057e4b and d3cc6d</a> |
| 74 | |
| 75 | External: |
| 76 | |
| 77 | * <a href="http://www.sqlite.org/src/timeline?c=2010-09-29&nd" |
| 78 | target="testwindow">Timewarp due to a mis-configured system clock.</a> |
| 79 |
+2
-6
| --- test/stash.test | ||
| +++ test/stash.test | ||
| @@ -185,15 +185,13 @@ | ||
| 185 | 185 | ADDED f0 |
| 186 | 186 | } -changes { |
| 187 | 187 | ADDED f0 |
| 188 | 188 | MISSING f1 |
| 189 | 189 | EDITED f2 |
| 190 | - MISSING f3 | |
| 190 | + RENAMED f3n | |
| 191 | 191 | } -addremove { |
| 192 | - ADDED f3n | |
| 193 | 192 | DELETED f1 |
| 194 | - DELETED f3 | |
| 195 | 193 | } -exists {f0 f2 f3n} -notexists {f1 f3} |
| 196 | 194 | |
| 197 | 195 | # Confirm there is no longer a stash saved |
| 198 | 196 | fossil stash list |
| 199 | 197 | test stash-2-list {[first_data_line] eq "empty stash"} |
| @@ -311,13 +309,11 @@ | ||
| 311 | 309 | UPDATE f1 |
| 312 | 310 | UPDATE f2n |
| 313 | 311 | } -changes { |
| 314 | 312 | RENAMED f2n |
| 315 | 313 | } -addremove { |
| 316 | - ADDED f2n | |
| 317 | - DELETED f2 | |
| 318 | -} -exists {f1 f2n} -notexists {f2} -knownbugs {-changes} | |
| 314 | +} -exists {f1 f2n} -notexists {f2} | |
| 319 | 315 | |
| 320 | 316 | |
| 321 | 317 | |
| 322 | 318 | ######## |
| 323 | 319 | # fossil stash snapshot ?-m|--comment COMMENT? ?FILES...? |
| 324 | 320 |
| --- test/stash.test | |
| +++ test/stash.test | |
| @@ -185,15 +185,13 @@ | |
| 185 | ADDED f0 |
| 186 | } -changes { |
| 187 | ADDED f0 |
| 188 | MISSING f1 |
| 189 | EDITED f2 |
| 190 | MISSING f3 |
| 191 | } -addremove { |
| 192 | ADDED f3n |
| 193 | DELETED f1 |
| 194 | DELETED f3 |
| 195 | } -exists {f0 f2 f3n} -notexists {f1 f3} |
| 196 | |
| 197 | # Confirm there is no longer a stash saved |
| 198 | fossil stash list |
| 199 | test stash-2-list {[first_data_line] eq "empty stash"} |
| @@ -311,13 +309,11 @@ | |
| 311 | UPDATE f1 |
| 312 | UPDATE f2n |
| 313 | } -changes { |
| 314 | RENAMED f2n |
| 315 | } -addremove { |
| 316 | ADDED f2n |
| 317 | DELETED f2 |
| 318 | } -exists {f1 f2n} -notexists {f2} -knownbugs {-changes} |
| 319 | |
| 320 | |
| 321 | |
| 322 | ######## |
| 323 | # fossil stash snapshot ?-m|--comment COMMENT? ?FILES...? |
| 324 |
| --- test/stash.test | |
| +++ test/stash.test | |
| @@ -185,15 +185,13 @@ | |
| 185 | ADDED f0 |
| 186 | } -changes { |
| 187 | ADDED f0 |
| 188 | MISSING f1 |
| 189 | EDITED f2 |
| 190 | RENAMED f3n |
| 191 | } -addremove { |
| 192 | DELETED f1 |
| 193 | } -exists {f0 f2 f3n} -notexists {f1 f3} |
| 194 | |
| 195 | # Confirm there is no longer a stash saved |
| 196 | fossil stash list |
| 197 | test stash-2-list {[first_data_line] eq "empty stash"} |
| @@ -311,13 +309,11 @@ | |
| 309 | UPDATE f1 |
| 310 | UPDATE f2n |
| 311 | } -changes { |
| 312 | RENAMED f2n |
| 313 | } -addremove { |
| 314 | } -exists {f1 f2n} -notexists {f2} |
| 315 | |
| 316 | |
| 317 | |
| 318 | ######## |
| 319 | # fossil stash snapshot ?-m|--comment COMMENT? ?FILES...? |
| 320 |
+29
-11
| --- test/tester.tcl | ||
| +++ test/tester.tcl | ||
| @@ -749,76 +749,94 @@ | ||
| 749 | 749 | } |
| 750 | 750 | return [string range $out 1 end] |
| 751 | 751 | } |
| 752 | 752 | |
| 753 | 753 | # This procedure executes the "fossil server" command. The return value |
| 754 | -# is the new process identifier. The varName argument refers to a variable | |
| 754 | +# is a list comprised of the new process identifier and the port on which | |
| 755 | +# the server started. The varName argument refers to a variable | |
| 755 | 756 | # where the "stop argument" is to be stored. This value must eventually be |
| 756 | 757 | # passed to the [test_stop_server] procedure. |
| 757 | 758 | proc test_start_server { repository {varName ""} } { |
| 758 | - global fossilexe | |
| 759 | - set command [list exec $fossilexe server] | |
| 759 | + global fossilexe tempPath | |
| 760 | + set command [list exec $fossilexe server --localhost] | |
| 760 | 761 | if {[string length $varName] > 0} { |
| 761 | 762 | upvar 1 $varName stopArg |
| 762 | 763 | } |
| 763 | 764 | if {$::tcl_platform(platform) eq "windows"} { |
| 764 | 765 | set stopArg [file join [getTemporaryPath] [appendArgs \ |
| 765 | 766 | [string trim [clock seconds] -] _ [getSeqNo] .stopper]] |
| 766 | 767 | lappend command --stopper $stopArg |
| 767 | 768 | } |
| 768 | - lappend command $repository & | |
| 769 | + set outFileName [file join $tempPath [appendArgs \ | |
| 770 | + fossil_server_ [string trim [clock seconds] -] _ \ | |
| 771 | + [getSeqNo]]].out | |
| 772 | + lappend command $repository >&$outFileName & | |
| 769 | 773 | set pid [eval $command] |
| 770 | 774 | if {$::tcl_platform(platform) ne "windows"} { |
| 771 | 775 | set stopArg $pid |
| 772 | 776 | } |
| 773 | - return $pid | |
| 777 | + after 1000; # output might not be there yet | |
| 778 | + set output [read_file $outFileName] | |
| 779 | + if {![regexp {Listening.*TCP port (\d+)} $output dummy port]} { | |
| 780 | + puts stdout "Could not detect Fossil server port, using default..." | |
| 781 | + set port 8080; # return the default port just in case | |
| 782 | + } | |
| 783 | + return [list $pid $port $outFileName] | |
| 774 | 784 | } |
| 775 | 785 | |
| 776 | 786 | # This procedure stops a Fossil server instance that was previously started |
| 777 | 787 | # by the [test_start_server] procedure. The value of the "stop argument" |
| 778 | 788 | # will vary by platform as will the exact method used to stop the server. |
| 779 | -proc test_stop_server { stopArg pid } { | |
| 789 | +# The fileName argument is the name of a temporary output file to delete. | |
| 790 | +proc test_stop_server { stopArg pid fileName } { | |
| 780 | 791 | if {$::tcl_platform(platform) eq "windows"} { |
| 781 | 792 | # |
| 782 | 793 | # NOTE: On Windows, the "stop argument" must be the name of a file |
| 783 | 794 | # that does NOT already exist. |
| 784 | 795 | # |
| 785 | - if {![file exists $stopArg] && \ | |
| 786 | - [catch {write_file $stopArg [clock seconds]}] == 0} then { | |
| 796 | + if {[string length $stopArg] > 0 && \ | |
| 797 | + ![file exists $stopArg] && \ | |
| 798 | + [catch {write_file $stopArg [clock seconds]}] == 0} { | |
| 787 | 799 | while {1} { |
| 788 | 800 | if {[catch { |
| 789 | 801 | # |
| 790 | 802 | # NOTE: Using the TaskList utility requires Windows XP or |
| 791 | 803 | # later. |
| 792 | 804 | # |
| 793 | 805 | exec tasklist.exe /FI "PID eq $pid" |
| 794 | - } result] != 0 || ![regexp -- " $pid " $result]} then { | |
| 806 | + } result] != 0 || ![regexp -- " $pid " $result]} { | |
| 795 | 807 | break |
| 796 | 808 | } |
| 797 | 809 | after 1000; # wait a bit... |
| 798 | 810 | } |
| 799 | 811 | file delete $stopArg |
| 812 | + if {[string length $fileName] > 0} { | |
| 813 | + file delete $fileName | |
| 814 | + } | |
| 800 | 815 | return true |
| 801 | 816 | } |
| 802 | 817 | } else { |
| 803 | 818 | # |
| 804 | 819 | # NOTE: On Unix, the "stop argument" must be an integer identifier |
| 805 | 820 | # that refers to an existing process. |
| 806 | 821 | # |
| 807 | 822 | if {[regexp {^(?:-)?\d+$} $stopArg] && \ |
| 808 | - [catch {exec kill -TERM $stopArg}] == 0} then { | |
| 823 | + [catch {exec kill -TERM $stopArg}] == 0} { | |
| 809 | 824 | while {1} { |
| 810 | 825 | if {[catch { |
| 811 | 826 | # |
| 812 | 827 | # TODO: Is this portable to all the supported variants of |
| 813 | 828 | # Unix? It should be, it's POSIX. |
| 814 | 829 | # |
| 815 | 830 | exec ps -p $pid |
| 816 | - } result] != 0 || ![regexp -- "(?:^$pid| $pid) " $result]} then { | |
| 831 | + } result] != 0 || ![regexp -- "(?:^$pid| $pid) " $result]} { | |
| 817 | 832 | break |
| 818 | 833 | } |
| 819 | 834 | after 1000; # wait a bit... |
| 835 | + } | |
| 836 | + if {[string length $fileName] > 0} { | |
| 837 | + file delete $fileName | |
| 820 | 838 | } |
| 821 | 839 | return true |
| 822 | 840 | } |
| 823 | 841 | } |
| 824 | 842 | return false |
| 825 | 843 |
| --- test/tester.tcl | |
| +++ test/tester.tcl | |
| @@ -749,76 +749,94 @@ | |
| 749 | } |
| 750 | return [string range $out 1 end] |
| 751 | } |
| 752 | |
| 753 | # This procedure executes the "fossil server" command. The return value |
| 754 | # is the new process identifier. The varName argument refers to a variable |
| 755 | # where the "stop argument" is to be stored. This value must eventually be |
| 756 | # passed to the [test_stop_server] procedure. |
| 757 | proc test_start_server { repository {varName ""} } { |
| 758 | global fossilexe |
| 759 | set command [list exec $fossilexe server] |
| 760 | if {[string length $varName] > 0} { |
| 761 | upvar 1 $varName stopArg |
| 762 | } |
| 763 | if {$::tcl_platform(platform) eq "windows"} { |
| 764 | set stopArg [file join [getTemporaryPath] [appendArgs \ |
| 765 | [string trim [clock seconds] -] _ [getSeqNo] .stopper]] |
| 766 | lappend command --stopper $stopArg |
| 767 | } |
| 768 | lappend command $repository & |
| 769 | set pid [eval $command] |
| 770 | if {$::tcl_platform(platform) ne "windows"} { |
| 771 | set stopArg $pid |
| 772 | } |
| 773 | return $pid |
| 774 | } |
| 775 | |
| 776 | # This procedure stops a Fossil server instance that was previously started |
| 777 | # by the [test_start_server] procedure. The value of the "stop argument" |
| 778 | # will vary by platform as will the exact method used to stop the server. |
| 779 | proc test_stop_server { stopArg pid } { |
| 780 | if {$::tcl_platform(platform) eq "windows"} { |
| 781 | # |
| 782 | # NOTE: On Windows, the "stop argument" must be the name of a file |
| 783 | # that does NOT already exist. |
| 784 | # |
| 785 | if {![file exists $stopArg] && \ |
| 786 | [catch {write_file $stopArg [clock seconds]}] == 0} then { |
| 787 | while {1} { |
| 788 | if {[catch { |
| 789 | # |
| 790 | # NOTE: Using the TaskList utility requires Windows XP or |
| 791 | # later. |
| 792 | # |
| 793 | exec tasklist.exe /FI "PID eq $pid" |
| 794 | } result] != 0 || ![regexp -- " $pid " $result]} then { |
| 795 | break |
| 796 | } |
| 797 | after 1000; # wait a bit... |
| 798 | } |
| 799 | file delete $stopArg |
| 800 | return true |
| 801 | } |
| 802 | } else { |
| 803 | # |
| 804 | # NOTE: On Unix, the "stop argument" must be an integer identifier |
| 805 | # that refers to an existing process. |
| 806 | # |
| 807 | if {[regexp {^(?:-)?\d+$} $stopArg] && \ |
| 808 | [catch {exec kill -TERM $stopArg}] == 0} then { |
| 809 | while {1} { |
| 810 | if {[catch { |
| 811 | # |
| 812 | # TODO: Is this portable to all the supported variants of |
| 813 | # Unix? It should be, it's POSIX. |
| 814 | # |
| 815 | exec ps -p $pid |
| 816 | } result] != 0 || ![regexp -- "(?:^$pid| $pid) " $result]} then { |
| 817 | break |
| 818 | } |
| 819 | after 1000; # wait a bit... |
| 820 | } |
| 821 | return true |
| 822 | } |
| 823 | } |
| 824 | return false |
| 825 |
| --- test/tester.tcl | |
| +++ test/tester.tcl | |
| @@ -749,76 +749,94 @@ | |
| 749 | } |
| 750 | return [string range $out 1 end] |
| 751 | } |
| 752 | |
| 753 | # This procedure executes the "fossil server" command. The return value |
| 754 | # is a list comprised of the new process identifier and the port on which |
| 755 | # the server started. The varName argument refers to a variable |
| 756 | # where the "stop argument" is to be stored. This value must eventually be |
| 757 | # passed to the [test_stop_server] procedure. |
| 758 | proc test_start_server { repository {varName ""} } { |
| 759 | global fossilexe tempPath |
| 760 | set command [list exec $fossilexe server --localhost] |
| 761 | if {[string length $varName] > 0} { |
| 762 | upvar 1 $varName stopArg |
| 763 | } |
| 764 | if {$::tcl_platform(platform) eq "windows"} { |
| 765 | set stopArg [file join [getTemporaryPath] [appendArgs \ |
| 766 | [string trim [clock seconds] -] _ [getSeqNo] .stopper]] |
| 767 | lappend command --stopper $stopArg |
| 768 | } |
| 769 | set outFileName [file join $tempPath [appendArgs \ |
| 770 | fossil_server_ [string trim [clock seconds] -] _ \ |
| 771 | [getSeqNo]]].out |
| 772 | lappend command $repository >&$outFileName & |
| 773 | set pid [eval $command] |
| 774 | if {$::tcl_platform(platform) ne "windows"} { |
| 775 | set stopArg $pid |
| 776 | } |
| 777 | after 1000; # output might not be there yet |
| 778 | set output [read_file $outFileName] |
| 779 | if {![regexp {Listening.*TCP port (\d+)} $output dummy port]} { |
| 780 | puts stdout "Could not detect Fossil server port, using default..." |
| 781 | set port 8080; # return the default port just in case |
| 782 | } |
| 783 | return [list $pid $port $outFileName] |
| 784 | } |
| 785 | |
| 786 | # This procedure stops a Fossil server instance that was previously started |
| 787 | # by the [test_start_server] procedure. The value of the "stop argument" |
| 788 | # will vary by platform as will the exact method used to stop the server. |
| 789 | # The fileName argument is the name of a temporary output file to delete. |
| 790 | proc test_stop_server { stopArg pid fileName } { |
| 791 | if {$::tcl_platform(platform) eq "windows"} { |
| 792 | # |
| 793 | # NOTE: On Windows, the "stop argument" must be the name of a file |
| 794 | # that does NOT already exist. |
| 795 | # |
| 796 | if {[string length $stopArg] > 0 && \ |
| 797 | ![file exists $stopArg] && \ |
| 798 | [catch {write_file $stopArg [clock seconds]}] == 0} { |
| 799 | while {1} { |
| 800 | if {[catch { |
| 801 | # |
| 802 | # NOTE: Using the TaskList utility requires Windows XP or |
| 803 | # later. |
| 804 | # |
| 805 | exec tasklist.exe /FI "PID eq $pid" |
| 806 | } result] != 0 || ![regexp -- " $pid " $result]} { |
| 807 | break |
| 808 | } |
| 809 | after 1000; # wait a bit... |
| 810 | } |
| 811 | file delete $stopArg |
| 812 | if {[string length $fileName] > 0} { |
| 813 | file delete $fileName |
| 814 | } |
| 815 | return true |
| 816 | } |
| 817 | } else { |
| 818 | # |
| 819 | # NOTE: On Unix, the "stop argument" must be an integer identifier |
| 820 | # that refers to an existing process. |
| 821 | # |
| 822 | if {[regexp {^(?:-)?\d+$} $stopArg] && \ |
| 823 | [catch {exec kill -TERM $stopArg}] == 0} { |
| 824 | while {1} { |
| 825 | if {[catch { |
| 826 | # |
| 827 | # TODO: Is this portable to all the supported variants of |
| 828 | # Unix? It should be, it's POSIX. |
| 829 | # |
| 830 | exec ps -p $pid |
| 831 | } result] != 0 || ![regexp -- "(?:^$pid| $pid) " $result]} { |
| 832 | break |
| 833 | } |
| 834 | after 1000; # wait a bit... |
| 835 | } |
| 836 | if {[string length $fileName] > 0} { |
| 837 | file delete $fileName |
| 838 | } |
| 839 | return true |
| 840 | } |
| 841 | } |
| 842 | return false |
| 843 |
+37
-1
| --- test/th1.test | ||
| +++ test/th1.test | ||
| @@ -1038,11 +1038,11 @@ | ||
| 1038 | 1038 | error expr for getParameter glob_match globalState hascap hasfeature\ |
| 1039 | 1039 | html htmlize http httpize if info insertCsrf lindex linecount list\ |
| 1040 | 1040 | llength lsearch markdown proc puts query randhex redirect regexp\ |
| 1041 | 1041 | reinitialize rename render repository return searchable set\ |
| 1042 | 1042 | setParameter setting stime string styleFooter styleHeader tclReady\ |
| 1043 | - trace unset uplevel upvar utime verifyCsrf wiki} | |
| 1043 | + trace unset unversioned uplevel upvar utime verifyCsrf wiki} | |
| 1044 | 1044 | set tcl_commands {tclEval tclExpr tclInvoke tclIsSafe tclMakeSafe} |
| 1045 | 1045 | if {$th1Tcl} { |
| 1046 | 1046 | test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands $tcl_commands"]} |
| 1047 | 1047 | } else { |
| 1048 | 1048 | test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands"]} |
| @@ -1562,9 +1562,45 @@ | ||
| 1562 | 1562 | } |
| 1563 | 1563 | |
| 1564 | 1564 | fossil test-th-source $th1FileName |
| 1565 | 1565 | test th1-source-1 {$RESULT eq {TH_RETURN: 0 1 2 3 4 5 6 7 8 9}} |
| 1566 | 1566 | file delete $th1FileName |
| 1567 | + | |
| 1568 | +############################################################################### | |
| 1569 | + | |
| 1570 | +# | |
| 1571 | +# TODO: Modify the result of this test if the list of unversioned files | |
| 1572 | +# changes. | |
| 1573 | +# | |
| 1574 | +run_in_checkout { | |
| 1575 | + fossil test-th-eval --open-config "unversioned list" | |
| 1576 | +} | |
| 1577 | + | |
| 1578 | +test th1-unversioned-1 {[normalize_result] eq \ | |
| 1579 | +{build-icons/linux.gif build-icons/linux64.gif build-icons/mac.gif\ | |
| 1580 | +build-icons/openbsd.gif build-icons/src.gif build-icons/win32.gif\ | |
| 1581 | +download.html download/fossil-linux-x86-1.32.zip\ | |
| 1582 | +download/fossil-linux-x86-1.33.zip download/fossil-linux-x86-1.34.zip\ | |
| 1583 | +download/fossil-linux-x86-1.35.zip download/fossil-macosx-x86-1.32.zip\ | |
| 1584 | +download/fossil-macosx-x86-1.33.zip download/fossil-macosx-x86-1.34.zip\ | |
| 1585 | +download/fossil-macosx-x86-1.35.zip download/fossil-openbsd-x86-1.32.zip\ | |
| 1586 | +download/fossil-openbsd-x86-1.33.zip download/fossil-openbsd-x86-1.34.tar.gz\ | |
| 1587 | +download/fossil-openbsd-x86-1.35.tar.gz download/fossil-src-1.32.tar.gz\ | |
| 1588 | +download/fossil-src-1.33.tar.gz download/fossil-src-1.34.tar.gz\ | |
| 1589 | +download/fossil-src-1.35.tar.gz download/fossil-w32-1.32.zip\ | |
| 1590 | +download/fossil-w32-1.33.zip download/fossil-w32-1.34.zip\ | |
| 1591 | +download/fossil-w32-1.35.zip download/releasenotes-1.32.html\ | |
| 1592 | +download/releasenotes-1.33.html download/releasenotes-1.34.html\ | |
| 1593 | +download/releasenotes-1.35.html index.wiki}} | |
| 1594 | + | |
| 1595 | +############################################################################### | |
| 1596 | + | |
| 1597 | +run_in_checkout { | |
| 1598 | + fossil test-th-eval --open-config \ | |
| 1599 | + {string length [unversioned content build-icons/src.gif]} | |
| 1600 | +} | |
| 1601 | + | |
| 1602 | +test th1-unversioned-2 {$RESULT eq {4592}} | |
| 1567 | 1603 | |
| 1568 | 1604 | ############################################################################### |
| 1569 | 1605 | |
| 1570 | 1606 | test_cleanup |
| 1571 | 1607 |
| --- test/th1.test | |
| +++ test/th1.test | |
| @@ -1038,11 +1038,11 @@ | |
| 1038 | error expr for getParameter glob_match globalState hascap hasfeature\ |
| 1039 | html htmlize http httpize if info insertCsrf lindex linecount list\ |
| 1040 | llength lsearch markdown proc puts query randhex redirect regexp\ |
| 1041 | reinitialize rename render repository return searchable set\ |
| 1042 | setParameter setting stime string styleFooter styleHeader tclReady\ |
| 1043 | trace unset uplevel upvar utime verifyCsrf wiki} |
| 1044 | set tcl_commands {tclEval tclExpr tclInvoke tclIsSafe tclMakeSafe} |
| 1045 | if {$th1Tcl} { |
| 1046 | test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands $tcl_commands"]} |
| 1047 | } else { |
| 1048 | test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands"]} |
| @@ -1562,9 +1562,45 @@ | |
| 1562 | } |
| 1563 | |
| 1564 | fossil test-th-source $th1FileName |
| 1565 | test th1-source-1 {$RESULT eq {TH_RETURN: 0 1 2 3 4 5 6 7 8 9}} |
| 1566 | file delete $th1FileName |
| 1567 | |
| 1568 | ############################################################################### |
| 1569 | |
| 1570 | test_cleanup |
| 1571 |
| --- test/th1.test | |
| +++ test/th1.test | |
| @@ -1038,11 +1038,11 @@ | |
| 1038 | error expr for getParameter glob_match globalState hascap hasfeature\ |
| 1039 | html htmlize http httpize if info insertCsrf lindex linecount list\ |
| 1040 | llength lsearch markdown proc puts query randhex redirect regexp\ |
| 1041 | reinitialize rename render repository return searchable set\ |
| 1042 | setParameter setting stime string styleFooter styleHeader tclReady\ |
| 1043 | trace unset unversioned uplevel upvar utime verifyCsrf wiki} |
| 1044 | set tcl_commands {tclEval tclExpr tclInvoke tclIsSafe tclMakeSafe} |
| 1045 | if {$th1Tcl} { |
| 1046 | test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands $tcl_commands"]} |
| 1047 | } else { |
| 1048 | test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands"]} |
| @@ -1562,9 +1562,45 @@ | |
| 1562 | } |
| 1563 | |
| 1564 | fossil test-th-source $th1FileName |
| 1565 | test th1-source-1 {$RESULT eq {TH_RETURN: 0 1 2 3 4 5 6 7 8 9}} |
| 1566 | file delete $th1FileName |
| 1567 | |
| 1568 | ############################################################################### |
| 1569 | |
| 1570 | # |
| 1571 | # TODO: Modify the result of this test if the list of unversioned files |
| 1572 | # changes. |
| 1573 | # |
| 1574 | run_in_checkout { |
| 1575 | fossil test-th-eval --open-config "unversioned list" |
| 1576 | } |
| 1577 | |
| 1578 | test th1-unversioned-1 {[normalize_result] eq \ |
| 1579 | {build-icons/linux.gif build-icons/linux64.gif build-icons/mac.gif\ |
| 1580 | build-icons/openbsd.gif build-icons/src.gif build-icons/win32.gif\ |
| 1581 | download.html download/fossil-linux-x86-1.32.zip\ |
| 1582 | download/fossil-linux-x86-1.33.zip download/fossil-linux-x86-1.34.zip\ |
| 1583 | download/fossil-linux-x86-1.35.zip download/fossil-macosx-x86-1.32.zip\ |
| 1584 | download/fossil-macosx-x86-1.33.zip download/fossil-macosx-x86-1.34.zip\ |
| 1585 | download/fossil-macosx-x86-1.35.zip download/fossil-openbsd-x86-1.32.zip\ |
| 1586 | download/fossil-openbsd-x86-1.33.zip download/fossil-openbsd-x86-1.34.tar.gz\ |
| 1587 | download/fossil-openbsd-x86-1.35.tar.gz download/fossil-src-1.32.tar.gz\ |
| 1588 | download/fossil-src-1.33.tar.gz download/fossil-src-1.34.tar.gz\ |
| 1589 | download/fossil-src-1.35.tar.gz download/fossil-w32-1.32.zip\ |
| 1590 | download/fossil-w32-1.33.zip download/fossil-w32-1.34.zip\ |
| 1591 | download/fossil-w32-1.35.zip download/releasenotes-1.32.html\ |
| 1592 | download/releasenotes-1.33.html download/releasenotes-1.34.html\ |
| 1593 | download/releasenotes-1.35.html index.wiki}} |
| 1594 | |
| 1595 | ############################################################################### |
| 1596 | |
| 1597 | run_in_checkout { |
| 1598 | fossil test-th-eval --open-config \ |
| 1599 | {string length [unversioned content build-icons/src.gif]} |
| 1600 | } |
| 1601 | |
| 1602 | test th1-unversioned-2 {$RESULT eq {4592}} |
| 1603 | |
| 1604 | ############################################################################### |
| 1605 | |
| 1606 | test_cleanup |
| 1607 |
+4
-4
| --- test/unversioned.test | ||
| +++ test/unversioned.test | ||
| @@ -305,19 +305,19 @@ | ||
| 305 | 305 | unversioned5\.txt$} [normalize_result]]} |
| 306 | 306 | |
| 307 | 307 | ############################################################################### |
| 308 | 308 | |
| 309 | 309 | set password [string trim [clock seconds] -] |
| 310 | -set remote [appendArgs http://uvtester: $password @localhost:8080/] | |
| 311 | 310 | |
| 312 | 311 | fossil user new uvtester "Unversioned Test User" $password |
| 313 | 312 | fossil user capabilities uvtester oy |
| 314 | 313 | |
| 315 | 314 | ############################################################################### |
| 316 | 315 | |
| 317 | -set pid [test_start_server $repository stopArg] | |
| 318 | -puts [appendArgs "Started Fossil server, pid \"" $pid \".] | |
| 316 | +foreach {pid port outTmpFile} [test_start_server $repository stopArg] {} | |
| 317 | +puts [appendArgs "Started Fossil server, pid \"" $pid \" ", port \"" $port \".] | |
| 318 | +set remote [appendArgs http://uvtester: $password @localhost: $port /] | |
| 319 | 319 | |
| 320 | 320 | ############################################################################### |
| 321 | 321 | |
| 322 | 322 | set clientDir [file join $tempPath [appendArgs \ |
| 323 | 323 | uvtest_ [string trim [clock seconds] -] _ [getSeqNo]]] |
| @@ -427,11 +427,11 @@ | ||
| 427 | 427 | file delete -force $clientDir |
| 428 | 428 | puts [appendArgs "Now in server directory \"" [pwd] \".] |
| 429 | 429 | |
| 430 | 430 | ############################################################################### |
| 431 | 431 | |
| 432 | -set stopped [test_stop_server $stopArg $pid] | |
| 432 | +set stopped [test_stop_server $stopArg $pid $outTmpFile] | |
| 433 | 433 | |
| 434 | 434 | puts [appendArgs \ |
| 435 | 435 | [expr {$stopped ? "Stopped" : "Could not stop"}] \ |
| 436 | 436 | " Fossil server, pid \"" $pid "\", using argument \"" \ |
| 437 | 437 | $stopArg \".] |
| 438 | 438 |
| --- test/unversioned.test | |
| +++ test/unversioned.test | |
| @@ -305,19 +305,19 @@ | |
| 305 | unversioned5\.txt$} [normalize_result]]} |
| 306 | |
| 307 | ############################################################################### |
| 308 | |
| 309 | set password [string trim [clock seconds] -] |
| 310 | set remote [appendArgs http://uvtester: $password @localhost:8080/] |
| 311 | |
| 312 | fossil user new uvtester "Unversioned Test User" $password |
| 313 | fossil user capabilities uvtester oy |
| 314 | |
| 315 | ############################################################################### |
| 316 | |
| 317 | set pid [test_start_server $repository stopArg] |
| 318 | puts [appendArgs "Started Fossil server, pid \"" $pid \".] |
| 319 | |
| 320 | ############################################################################### |
| 321 | |
| 322 | set clientDir [file join $tempPath [appendArgs \ |
| 323 | uvtest_ [string trim [clock seconds] -] _ [getSeqNo]]] |
| @@ -427,11 +427,11 @@ | |
| 427 | file delete -force $clientDir |
| 428 | puts [appendArgs "Now in server directory \"" [pwd] \".] |
| 429 | |
| 430 | ############################################################################### |
| 431 | |
| 432 | set stopped [test_stop_server $stopArg $pid] |
| 433 | |
| 434 | puts [appendArgs \ |
| 435 | [expr {$stopped ? "Stopped" : "Could not stop"}] \ |
| 436 | " Fossil server, pid \"" $pid "\", using argument \"" \ |
| 437 | $stopArg \".] |
| 438 |
| --- test/unversioned.test | |
| +++ test/unversioned.test | |
| @@ -305,19 +305,19 @@ | |
| 305 | unversioned5\.txt$} [normalize_result]]} |
| 306 | |
| 307 | ############################################################################### |
| 308 | |
| 309 | set password [string trim [clock seconds] -] |
| 310 | |
| 311 | fossil user new uvtester "Unversioned Test User" $password |
| 312 | fossil user capabilities uvtester oy |
| 313 | |
| 314 | ############################################################################### |
| 315 | |
| 316 | foreach {pid port outTmpFile} [test_start_server $repository stopArg] {} |
| 317 | puts [appendArgs "Started Fossil server, pid \"" $pid \" ", port \"" $port \".] |
| 318 | set remote [appendArgs http://uvtester: $password @localhost: $port /] |
| 319 | |
| 320 | ############################################################################### |
| 321 | |
| 322 | set clientDir [file join $tempPath [appendArgs \ |
| 323 | uvtest_ [string trim [clock seconds] -] _ [getSeqNo]]] |
| @@ -427,11 +427,11 @@ | |
| 427 | file delete -force $clientDir |
| 428 | puts [appendArgs "Now in server directory \"" [pwd] \".] |
| 429 | |
| 430 | ############################################################################### |
| 431 | |
| 432 | set stopped [test_stop_server $stopArg $pid $outTmpFile] |
| 433 | |
| 434 | puts [appendArgs \ |
| 435 | [expr {$stopped ? "Stopped" : "Could not stop"}] \ |
| 436 | " Fossil server, pid \"" $pid "\", using argument \"" \ |
| 437 | $stopArg \".] |
| 438 |
+10
-10
| --- www/aboutcgi.wiki | ||
| +++ www/aboutcgi.wiki | ||
| @@ -66,11 +66,11 @@ | ||
| 66 | 66 | <p> |
| 67 | 67 | In addition to setting various CGI environment variables, if the HTTP |
| 68 | 68 | request contains POST content, then the web server relays the POST content |
| 69 | 69 | to standard input of the CGI script. |
| 70 | 70 | <p> |
| 71 | -In summary, the task of the | |
| 71 | +In summary, the task of the | |
| 72 | 72 | CGI script is to read the various CGI environment variables and |
| 73 | 73 | the POST content on standard input (if any), figure out an appropriate |
| 74 | 74 | reply, then write that reply on standard output. |
| 75 | 75 | The web server will read the output from the CGI script, reformat it |
| 76 | 76 | into an appropriate HTTP reply, and relay the result back to the |
| @@ -89,31 +89,31 @@ | ||
| 89 | 89 | like the following: |
| 90 | 90 | <blockquote><pre> |
| 91 | 91 | #!/usr/bin/fossil |
| 92 | 92 | repository: /home/www/repos/project.fossil |
| 93 | 93 | </pre></blockquote> |
| 94 | -The first line of the script is a | |
| 94 | +The first line of the script is a | |
| 95 | 95 | "[https://en.wikipedia.org/wiki/Shebang_%28Unix%29|shebang]" |
| 96 | 96 | that tells the operating system what program to use as the interpreter |
| 97 | 97 | for this script. On unix, when you execute a script that starts with |
| 98 | 98 | a shebang, the operating system runs the program identified by the |
| 99 | -shebang with a single argument that is the full pathname of the script | |
| 99 | +shebang with a single argument that is the full pathname of the script | |
| 100 | 100 | itself. |
| 101 | 101 | In our example, the interpreter is Fossil, and the argument might |
| 102 | 102 | be something like "/var/www/cgi-bin/one/two" (depending on how your |
| 103 | 103 | particular web server is configured). |
| 104 | 104 | <p> |
| 105 | 105 | The Fossil program that is run as the script interpreter |
| 106 | 106 | is the same Fossil that runs when |
| 107 | 107 | you type ordinary Fossil commands like "fossil sync" or "fossil commit". |
| 108 | 108 | But in this case, as soon as it launches, the Fossil program |
| 109 | -recognizes that the GATEWAY_INTERFACE environment variable is | |
| 109 | +recognizes that the GATEWAY_INTERFACE environment variable is | |
| 110 | 110 | set to "CGI/1.0" and it therefore knows that it is being used as |
| 111 | 111 | CGI rather than as an ordinary command-line tool, and behaves accordingly. |
| 112 | 112 | <p> |
| 113 | 113 | When Fossil recognizes that it is being run as CGI, it opens and reads |
| 114 | -the file identified by its sole argument (the file named by | |
| 114 | +the file identified by its sole argument (the file named by | |
| 115 | 115 | <code>argv[1]</code>). In our example, the second line of that file |
| 116 | 116 | tells Fossil the location of the repository it will be serving. |
| 117 | 117 | Fossil then starts looking at the CGI environment variables to figure |
| 118 | 118 | out what web page is being requested, generates that one web page, |
| 119 | 119 | then exits. |
| @@ -130,11 +130,11 @@ | ||
| 130 | 130 | <ol type='A'> |
| 131 | 131 | <li> [https://www.fossil-scm.org/fossil/info/c14ecc43] |
| 132 | 132 | <li> [https://www.fossil-scm.org/fossil/info?name=c14ecc43] |
| 133 | 133 | </ol> |
| 134 | 134 | In both cases, the CGI script is called "/fossil". For case (A), |
| 135 | -the PATH_INFO variable will be "info/c14ecc43" and so the | |
| 135 | +the PATH_INFO variable will be "info/c14ecc43" and so the | |
| 136 | 136 | "[/help?cmd=/info|/info]" webpage will be generated and the suffix of |
| 137 | 137 | PATH_INFO will be converted into the "name" query parameter, which |
| 138 | 138 | identifies the artifact about which information is requested. |
| 139 | 139 | In case (B), the PATH_INFO is just "info", but the same "name" |
| 140 | 140 | query parameter is set explicitly by the URL itself. |
| @@ -164,11 +164,11 @@ | ||
| 164 | 164 | <blockquote> |
| 165 | 165 | <b>http://example.com/cgis/example2/subdir/three/timeline</b> |
| 166 | 166 | </blockquote> |
| 167 | 167 | Here is what happens: |
| 168 | 168 | <ol> |
| 169 | -<li> The input URI on the HTTP request is | |
| 169 | +<li> The input URI on the HTTP request is | |
| 170 | 170 | <b>/cgis/example2/subdir/three/timeline</b> |
| 171 | 171 | <li> The web server searches prefixes of the input URI until it finds |
| 172 | 172 | the "cgis/example2" script. The web server then sets |
| 173 | 173 | PATH_INFO to the "subdir/three/timeline" suffix and invokes the |
| 174 | 174 | "cgis/example2" script. |
| @@ -175,11 +175,11 @@ | ||
| 175 | 175 | <li> Fossil runs and sees the "directory:" line pointing to |
| 176 | 176 | "/home/www/repos". Fossil then starts pulling terms off the |
| 177 | 177 | front of the PATH_INFO looking for a repository. It first looks |
| 178 | 178 | at "/home/www/resps/subdir.fossil" but there is no such repository. |
| 179 | 179 | So then it looks at "/home/www/repos/subdir/three.fossil" and finds |
| 180 | - a repository. The PATH_INFO is shortened by removing | |
| 180 | + a repository. The PATH_INFO is shortened by removing | |
| 181 | 181 | "subdir/three/" leaving it at just "timeline". |
| 182 | 182 | <li> Fossil looks at the rest of PATH_INFO to see that the webpage |
| 183 | 183 | requested is "timeline". |
| 184 | 184 | </ol> |
| 185 | 185 | </blockquote> |
| @@ -201,14 +201,14 @@ | ||
| 201 | 201 | and has a value. |
| 202 | 202 | <li><p> |
| 203 | 203 | The "[/help?cmd=ui|fossil ui]" and "[/help?cmd=server|fossil server]" commands |
| 204 | 204 | are implemented using a simple built-in web server that accepts incoming HTTP |
| 205 | 205 | requests, translates each request into a CGI invocation, then creates a |
| 206 | -separate child Fossil process to handle each request. In other words, CGI | |
| 206 | +separate child Fossil process to handle each request. In other words, CGI | |
| 207 | 207 | is used internally to implement "fossil ui/server". |
| 208 | 208 | <p> |
| 209 | 209 | SCGI is processed using the same built-in web server, just modified |
| 210 | 210 | to parse SCGI requests instead of HTTP requests. Each SCGI request is |
| 211 | -converted into CGI, then Fossil creates a separate child Fossil | |
| 211 | +converted into CGI, then Fossil creates a separate child Fossil | |
| 212 | 212 | process to handle each CGI request. |
| 213 | 213 | </ol> |
| 214 | 214 | </blockquote> |
| 215 | 215 |
| --- www/aboutcgi.wiki | |
| +++ www/aboutcgi.wiki | |
| @@ -66,11 +66,11 @@ | |
| 66 | <p> |
| 67 | In addition to setting various CGI environment variables, if the HTTP |
| 68 | request contains POST content, then the web server relays the POST content |
| 69 | to standard input of the CGI script. |
| 70 | <p> |
| 71 | In summary, the task of the |
| 72 | CGI script is to read the various CGI environment variables and |
| 73 | the POST content on standard input (if any), figure out an appropriate |
| 74 | reply, then write that reply on standard output. |
| 75 | The web server will read the output from the CGI script, reformat it |
| 76 | into an appropriate HTTP reply, and relay the result back to the |
| @@ -89,31 +89,31 @@ | |
| 89 | like the following: |
| 90 | <blockquote><pre> |
| 91 | #!/usr/bin/fossil |
| 92 | repository: /home/www/repos/project.fossil |
| 93 | </pre></blockquote> |
| 94 | The first line of the script is a |
| 95 | "[https://en.wikipedia.org/wiki/Shebang_%28Unix%29|shebang]" |
| 96 | that tells the operating system what program to use as the interpreter |
| 97 | for this script. On unix, when you execute a script that starts with |
| 98 | a shebang, the operating system runs the program identified by the |
| 99 | shebang with a single argument that is the full pathname of the script |
| 100 | itself. |
| 101 | In our example, the interpreter is Fossil, and the argument might |
| 102 | be something like "/var/www/cgi-bin/one/two" (depending on how your |
| 103 | particular web server is configured). |
| 104 | <p> |
| 105 | The Fossil program that is run as the script interpreter |
| 106 | is the same Fossil that runs when |
| 107 | you type ordinary Fossil commands like "fossil sync" or "fossil commit". |
| 108 | But in this case, as soon as it launches, the Fossil program |
| 109 | recognizes that the GATEWAY_INTERFACE environment variable is |
| 110 | set to "CGI/1.0" and it therefore knows that it is being used as |
| 111 | CGI rather than as an ordinary command-line tool, and behaves accordingly. |
| 112 | <p> |
| 113 | When Fossil recognizes that it is being run as CGI, it opens and reads |
| 114 | the file identified by its sole argument (the file named by |
| 115 | <code>argv[1]</code>). In our example, the second line of that file |
| 116 | tells Fossil the location of the repository it will be serving. |
| 117 | Fossil then starts looking at the CGI environment variables to figure |
| 118 | out what web page is being requested, generates that one web page, |
| 119 | then exits. |
| @@ -130,11 +130,11 @@ | |
| 130 | <ol type='A'> |
| 131 | <li> [https://www.fossil-scm.org/fossil/info/c14ecc43] |
| 132 | <li> [https://www.fossil-scm.org/fossil/info?name=c14ecc43] |
| 133 | </ol> |
| 134 | In both cases, the CGI script is called "/fossil". For case (A), |
| 135 | the PATH_INFO variable will be "info/c14ecc43" and so the |
| 136 | "[/help?cmd=/info|/info]" webpage will be generated and the suffix of |
| 137 | PATH_INFO will be converted into the "name" query parameter, which |
| 138 | identifies the artifact about which information is requested. |
| 139 | In case (B), the PATH_INFO is just "info", but the same "name" |
| 140 | query parameter is set explicitly by the URL itself. |
| @@ -164,11 +164,11 @@ | |
| 164 | <blockquote> |
| 165 | <b>http://example.com/cgis/example2/subdir/three/timeline</b> |
| 166 | </blockquote> |
| 167 | Here is what happens: |
| 168 | <ol> |
| 169 | <li> The input URI on the HTTP request is |
| 170 | <b>/cgis/example2/subdir/three/timeline</b> |
| 171 | <li> The web server searches prefixes of the input URI until it finds |
| 172 | the "cgis/example2" script. The web server then sets |
| 173 | PATH_INFO to the "subdir/three/timeline" suffix and invokes the |
| 174 | "cgis/example2" script. |
| @@ -175,11 +175,11 @@ | |
| 175 | <li> Fossil runs and sees the "directory:" line pointing to |
| 176 | "/home/www/repos". Fossil then starts pulling terms off the |
| 177 | front of the PATH_INFO looking for a repository. It first looks |
| 178 | at "/home/www/resps/subdir.fossil" but there is no such repository. |
| 179 | So then it looks at "/home/www/repos/subdir/three.fossil" and finds |
| 180 | a repository. The PATH_INFO is shortened by removing |
| 181 | "subdir/three/" leaving it at just "timeline". |
| 182 | <li> Fossil looks at the rest of PATH_INFO to see that the webpage |
| 183 | requested is "timeline". |
| 184 | </ol> |
| 185 | </blockquote> |
| @@ -201,14 +201,14 @@ | |
| 201 | and has a value. |
| 202 | <li><p> |
| 203 | The "[/help?cmd=ui|fossil ui]" and "[/help?cmd=server|fossil server]" commands |
| 204 | are implemented using a simple built-in web server that accepts incoming HTTP |
| 205 | requests, translates each request into a CGI invocation, then creates a |
| 206 | separate child Fossil process to handle each request. In other words, CGI |
| 207 | is used internally to implement "fossil ui/server". |
| 208 | <p> |
| 209 | SCGI is processed using the same built-in web server, just modified |
| 210 | to parse SCGI requests instead of HTTP requests. Each SCGI request is |
| 211 | converted into CGI, then Fossil creates a separate child Fossil |
| 212 | process to handle each CGI request. |
| 213 | </ol> |
| 214 | </blockquote> |
| 215 |
| --- www/aboutcgi.wiki | |
| +++ www/aboutcgi.wiki | |
| @@ -66,11 +66,11 @@ | |
| 66 | <p> |
| 67 | In addition to setting various CGI environment variables, if the HTTP |
| 68 | request contains POST content, then the web server relays the POST content |
| 69 | to standard input of the CGI script. |
| 70 | <p> |
| 71 | In summary, the task of the |
| 72 | CGI script is to read the various CGI environment variables and |
| 73 | the POST content on standard input (if any), figure out an appropriate |
| 74 | reply, then write that reply on standard output. |
| 75 | The web server will read the output from the CGI script, reformat it |
| 76 | into an appropriate HTTP reply, and relay the result back to the |
| @@ -89,31 +89,31 @@ | |
| 89 | like the following: |
| 90 | <blockquote><pre> |
| 91 | #!/usr/bin/fossil |
| 92 | repository: /home/www/repos/project.fossil |
| 93 | </pre></blockquote> |
| 94 | The first line of the script is a |
| 95 | "[https://en.wikipedia.org/wiki/Shebang_%28Unix%29|shebang]" |
| 96 | that tells the operating system what program to use as the interpreter |
| 97 | for this script. On unix, when you execute a script that starts with |
| 98 | a shebang, the operating system runs the program identified by the |
| 99 | shebang with a single argument that is the full pathname of the script |
| 100 | itself. |
| 101 | In our example, the interpreter is Fossil, and the argument might |
| 102 | be something like "/var/www/cgi-bin/one/two" (depending on how your |
| 103 | particular web server is configured). |
| 104 | <p> |
| 105 | The Fossil program that is run as the script interpreter |
| 106 | is the same Fossil that runs when |
| 107 | you type ordinary Fossil commands like "fossil sync" or "fossil commit". |
| 108 | But in this case, as soon as it launches, the Fossil program |
| 109 | recognizes that the GATEWAY_INTERFACE environment variable is |
| 110 | set to "CGI/1.0" and it therefore knows that it is being used as |
| 111 | CGI rather than as an ordinary command-line tool, and behaves accordingly. |
| 112 | <p> |
| 113 | When Fossil recognizes that it is being run as CGI, it opens and reads |
| 114 | the file identified by its sole argument (the file named by |
| 115 | <code>argv[1]</code>). In our example, the second line of that file |
| 116 | tells Fossil the location of the repository it will be serving. |
| 117 | Fossil then starts looking at the CGI environment variables to figure |
| 118 | out what web page is being requested, generates that one web page, |
| 119 | then exits. |
| @@ -130,11 +130,11 @@ | |
| 130 | <ol type='A'> |
| 131 | <li> [https://www.fossil-scm.org/fossil/info/c14ecc43] |
| 132 | <li> [https://www.fossil-scm.org/fossil/info?name=c14ecc43] |
| 133 | </ol> |
| 134 | In both cases, the CGI script is called "/fossil". For case (A), |
| 135 | the PATH_INFO variable will be "info/c14ecc43" and so the |
| 136 | "[/help?cmd=/info|/info]" webpage will be generated and the suffix of |
| 137 | PATH_INFO will be converted into the "name" query parameter, which |
| 138 | identifies the artifact about which information is requested. |
| 139 | In case (B), the PATH_INFO is just "info", but the same "name" |
| 140 | query parameter is set explicitly by the URL itself. |
| @@ -164,11 +164,11 @@ | |
| 164 | <blockquote> |
| 165 | <b>http://example.com/cgis/example2/subdir/three/timeline</b> |
| 166 | </blockquote> |
| 167 | Here is what happens: |
| 168 | <ol> |
| 169 | <li> The input URI on the HTTP request is |
| 170 | <b>/cgis/example2/subdir/three/timeline</b> |
| 171 | <li> The web server searches prefixes of the input URI until it finds |
| 172 | the "cgis/example2" script. The web server then sets |
| 173 | PATH_INFO to the "subdir/three/timeline" suffix and invokes the |
| 174 | "cgis/example2" script. |
| @@ -175,11 +175,11 @@ | |
| 175 | <li> Fossil runs and sees the "directory:" line pointing to |
| 176 | "/home/www/repos". Fossil then starts pulling terms off the |
| 177 | front of the PATH_INFO looking for a repository. It first looks |
| 178 | at "/home/www/resps/subdir.fossil" but there is no such repository. |
| 179 | So then it looks at "/home/www/repos/subdir/three.fossil" and finds |
| 180 | a repository. The PATH_INFO is shortened by removing |
| 181 | "subdir/three/" leaving it at just "timeline". |
| 182 | <li> Fossil looks at the rest of PATH_INFO to see that the webpage |
| 183 | requested is "timeline". |
| 184 | </ol> |
| 185 | </blockquote> |
| @@ -201,14 +201,14 @@ | |
| 201 | and has a value. |
| 202 | <li><p> |
| 203 | The "[/help?cmd=ui|fossil ui]" and "[/help?cmd=server|fossil server]" commands |
| 204 | are implemented using a simple built-in web server that accepts incoming HTTP |
| 205 | requests, translates each request into a CGI invocation, then creates a |
| 206 | separate child Fossil process to handle each request. In other words, CGI |
| 207 | is used internally to implement "fossil ui/server". |
| 208 | <p> |
| 209 | SCGI is processed using the same built-in web server, just modified |
| 210 | to parse SCGI requests instead of HTTP requests. Each SCGI request is |
| 211 | converted into CGI, then Fossil creates a separate child Fossil |
| 212 | process to handle each CGI request. |
| 213 | </ol> |
| 214 | </blockquote> |
| 215 |
+5
-5
| --- www/adding_code.wiki | ||
| +++ www/adding_code.wiki | ||
| @@ -22,11 +22,11 @@ | ||
| 22 | 22 | |
| 23 | 23 | 2. The <b>makeheaders</b> preprocessor generates all the ".h" files |
| 24 | 24 | automatically. Fossil programmers write ".c" files only and let the |
| 25 | 25 | makeheaders preprocessor create the ".h" files. |
| 26 | 26 | |
| 27 | - 3. The <b>translate</b> preprocessor converts source code lines that | |
| 27 | + 3. The <b>translate</b> preprocessor converts source code lines that | |
| 28 | 28 | begin with "@" into string literals, or into print statements that |
| 29 | 29 | generate web page output, depending on context. |
| 30 | 30 | |
| 31 | 31 | The [./makefile.wiki|Makefile] for Fossil takes care of running these |
| 32 | 32 | preprocessors with all the right arguments and in the right order. So it is |
| @@ -39,13 +39,13 @@ | ||
| 39 | 39 | <h2>3.0 Adding New Source Code Files</h2> |
| 40 | 40 | |
| 41 | 41 | New source code files are added in the "src/" subdirectory of the Fossil |
| 42 | 42 | source tree. Suppose one wants to add a new source code file named |
| 43 | 43 | "xyzzy.c". The first step is to add this file to the various makefiles. |
| 44 | -Do so by editing the file src/makemake.tcl and adding "xyzzy" (without | |
| 44 | +Do so by editing the file src/makemake.tcl and adding "xyzzy" (without | |
| 45 | 45 | the final ".c") to the list of source modules at the top of that script. |
| 46 | -Save the result and then run the makemake.tcl script using a TCL | |
| 46 | +Save the result and then run the makemake.tcl script using a TCL | |
| 47 | 47 | interpreter. The command to run the makemake.tcl script is: |
| 48 | 48 | |
| 49 | 49 | <b>tclsh makemake.tcl</b> |
| 50 | 50 | |
| 51 | 51 | The working directory must be src/ when the command above is run. |
| @@ -60,11 +60,11 @@ | ||
| 60 | 60 | |
| 61 | 61 | <blockquote><verbatim> |
| 62 | 62 | /* |
| 63 | 63 | ** Copyright boilerplate goes here. |
| 64 | 64 | ***************************************************** |
| 65 | -** High-level description of what this module goes | |
| 65 | +** High-level description of what this module goes | |
| 66 | 66 | ** here. |
| 67 | 67 | */ |
| 68 | 68 | #include "config.h" |
| 69 | 69 | #include "xyzzy.h" |
| 70 | 70 | |
| @@ -83,11 +83,11 @@ | ||
| 83 | 83 | exceptions to this rule. Don't worry about those exceptions. The |
| 84 | 84 | files you write will require this #include line.) |
| 85 | 85 | |
| 86 | 86 | The "#if INTERFACE ... #endif" section is optional and is only needed |
| 87 | 87 | if there are structure definitions or typedefs or macros that need to |
| 88 | -be used by other source code files. The makeheaders preprocessor | |
| 88 | +be used by other source code files. The makeheaders preprocessor | |
| 89 | 89 | uses definitions in the INTERFACE section to help it generate header |
| 90 | 90 | files. See [../src/makeheaders.html | makeheaders.html] for additional |
| 91 | 91 | information. |
| 92 | 92 | |
| 93 | 93 | After creating a template file such as shown above, and after updating |
| 94 | 94 |
| --- www/adding_code.wiki | |
| +++ www/adding_code.wiki | |
| @@ -22,11 +22,11 @@ | |
| 22 | |
| 23 | 2. The <b>makeheaders</b> preprocessor generates all the ".h" files |
| 24 | automatically. Fossil programmers write ".c" files only and let the |
| 25 | makeheaders preprocessor create the ".h" files. |
| 26 | |
| 27 | 3. The <b>translate</b> preprocessor converts source code lines that |
| 28 | begin with "@" into string literals, or into print statements that |
| 29 | generate web page output, depending on context. |
| 30 | |
| 31 | The [./makefile.wiki|Makefile] for Fossil takes care of running these |
| 32 | preprocessors with all the right arguments and in the right order. So it is |
| @@ -39,13 +39,13 @@ | |
| 39 | <h2>3.0 Adding New Source Code Files</h2> |
| 40 | |
| 41 | New source code files are added in the "src/" subdirectory of the Fossil |
| 42 | source tree. Suppose one wants to add a new source code file named |
| 43 | "xyzzy.c". The first step is to add this file to the various makefiles. |
| 44 | Do so by editing the file src/makemake.tcl and adding "xyzzy" (without |
| 45 | the final ".c") to the list of source modules at the top of that script. |
| 46 | Save the result and then run the makemake.tcl script using a TCL |
| 47 | interpreter. The command to run the makemake.tcl script is: |
| 48 | |
| 49 | <b>tclsh makemake.tcl</b> |
| 50 | |
| 51 | The working directory must be src/ when the command above is run. |
| @@ -60,11 +60,11 @@ | |
| 60 | |
| 61 | <blockquote><verbatim> |
| 62 | /* |
| 63 | ** Copyright boilerplate goes here. |
| 64 | ***************************************************** |
| 65 | ** High-level description of what this module goes |
| 66 | ** here. |
| 67 | */ |
| 68 | #include "config.h" |
| 69 | #include "xyzzy.h" |
| 70 | |
| @@ -83,11 +83,11 @@ | |
| 83 | exceptions to this rule. Don't worry about those exceptions. The |
| 84 | files you write will require this #include line.) |
| 85 | |
| 86 | The "#if INTERFACE ... #endif" section is optional and is only needed |
| 87 | if there are structure definitions or typedefs or macros that need to |
| 88 | be used by other source code files. The makeheaders preprocessor |
| 89 | uses definitions in the INTERFACE section to help it generate header |
| 90 | files. See [../src/makeheaders.html | makeheaders.html] for additional |
| 91 | information. |
| 92 | |
| 93 | After creating a template file such as shown above, and after updating |
| 94 |
| --- www/adding_code.wiki | |
| +++ www/adding_code.wiki | |
| @@ -22,11 +22,11 @@ | |
| 22 | |
| 23 | 2. The <b>makeheaders</b> preprocessor generates all the ".h" files |
| 24 | automatically. Fossil programmers write ".c" files only and let the |
| 25 | makeheaders preprocessor create the ".h" files. |
| 26 | |
| 27 | 3. The <b>translate</b> preprocessor converts source code lines that |
| 28 | begin with "@" into string literals, or into print statements that |
| 29 | generate web page output, depending on context. |
| 30 | |
| 31 | The [./makefile.wiki|Makefile] for Fossil takes care of running these |
| 32 | preprocessors with all the right arguments and in the right order. So it is |
| @@ -39,13 +39,13 @@ | |
| 39 | <h2>3.0 Adding New Source Code Files</h2> |
| 40 | |
| 41 | New source code files are added in the "src/" subdirectory of the Fossil |
| 42 | source tree. Suppose one wants to add a new source code file named |
| 43 | "xyzzy.c". The first step is to add this file to the various makefiles. |
| 44 | Do so by editing the file src/makemake.tcl and adding "xyzzy" (without |
| 45 | the final ".c") to the list of source modules at the top of that script. |
| 46 | Save the result and then run the makemake.tcl script using a TCL |
| 47 | interpreter. The command to run the makemake.tcl script is: |
| 48 | |
| 49 | <b>tclsh makemake.tcl</b> |
| 50 | |
| 51 | The working directory must be src/ when the command above is run. |
| @@ -60,11 +60,11 @@ | |
| 60 | |
| 61 | <blockquote><verbatim> |
| 62 | /* |
| 63 | ** Copyright boilerplate goes here. |
| 64 | ***************************************************** |
| 65 | ** High-level description of what this module goes |
| 66 | ** here. |
| 67 | */ |
| 68 | #include "config.h" |
| 69 | #include "xyzzy.h" |
| 70 | |
| @@ -83,11 +83,11 @@ | |
| 83 | exceptions to this rule. Don't worry about those exceptions. The |
| 84 | files you write will require this #include line.) |
| 85 | |
| 86 | The "#if INTERFACE ... #endif" section is optional and is only needed |
| 87 | if there are structure definitions or typedefs or macros that need to |
| 88 | be used by other source code files. The makeheaders preprocessor |
| 89 | uses definitions in the INTERFACE section to help it generate header |
| 90 | files. See [../src/makeheaders.html | makeheaders.html] for additional |
| 91 | information. |
| 92 | |
| 93 | After creating a template file such as shown above, and after updating |
| 94 |
+11
-11
| --- www/antibot.wiki | ||
| +++ www/antibot.wiki | ||
| @@ -1,27 +1,27 @@ | ||
| 1 | 1 | <title>Defense Against Spiders</title> |
| 2 | 2 | |
| 3 | 3 | The website presented by a Fossil server has many hyperlinks. |
| 4 | 4 | Even a modest project can have millions of pages in its |
| 5 | -tree, and many of those pages (for example diffs and annotations | |
| 5 | +tree, and many of those pages (for example diffs and annotations | |
| 6 | 6 | and ZIP archive of older check-ins) can be expensive to compute. |
| 7 | 7 | If a spider or bot tries to walk a website implemented by |
| 8 | 8 | Fossil, it can present a crippling bandwidth and CPU load. |
| 9 | 9 | |
| 10 | 10 | The website presented by a Fossil server is intended to be used |
| 11 | -interactively by humans, not walked by spiders. This article | |
| 11 | +interactively by humans, not walked by spiders. This article | |
| 12 | 12 | describes the techniques used by Fossil to try to welcome human |
| 13 | 13 | users while keeping out spiders. |
| 14 | 14 | |
| 15 | 15 | <h2>The "hyperlink" user capability</h2> |
| 16 | 16 | |
| 17 | 17 | Every Fossil web session has a "user". For random passers-by on the internet |
| 18 | 18 | (and for spiders) that user is "nobody". The "anonymous" user is also |
| 19 | 19 | available for humans who do not wish to identify themselves. The difference |
| 20 | 20 | is that "anonymous" requires a login (using a password supplied via |
| 21 | -a CAPTCHA) whereas "nobody" does not require a login. | |
| 22 | -The site administrator can also create logins with | |
| 21 | +a CAPTCHA) whereas "nobody" does not require a login. | |
| 22 | +The site administrator can also create logins with | |
| 23 | 23 | passwords for specific individuals. |
| 24 | 24 | |
| 25 | 25 | The "h" or "hyperlink" capability is a permission that can be granted |
| 26 | 26 | to users that enables the display of hyperlinks. Most of the hyperlinks |
| 27 | 27 | generated by Fossil are suppressed if this capability is missing. So |
| @@ -37,11 +37,11 @@ | ||
| 37 | 37 | page inviting the user to log in as anonymous in order to activate hyperlinks. |
| 38 | 38 | |
| 39 | 39 | Removing the "h" capability from user "nobody" is an effective means |
| 40 | 40 | of preventing spiders from walking a Fossil-generated website. But |
| 41 | 41 | it can also be annoying to humans, since it requires them to log in. |
| 42 | -Hence, Fossil provides other techniques for blocking spiders which | |
| 42 | +Hence, Fossil provides other techniques for blocking spiders which | |
| 43 | 43 | are less cumbersome to humans. |
| 44 | 44 | |
| 45 | 45 | <h2>Automatic hyperlinks based on UserAgent</h2> |
| 46 | 46 | |
| 47 | 47 | Fossil has the ability to selectively enable hyperlinks for users |
| @@ -94,25 +94,25 @@ | ||
| 94 | 94 | web browsers implement javascript, so hyperlinks will appears |
| 95 | 95 | normally for human users. |
| 96 | 96 | |
| 97 | 97 | <h2>Further defenses</h2> |
| 98 | 98 | |
| 99 | -Recently (as of this writing, in the spring of 2013) the Fossil server | |
| 99 | +Recently (as of this writing, in the spring of 2013) the Fossil server | |
| 100 | 100 | on the SQLite website ([http://www.sqlite.org/src/]) has been hit repeatedly |
| 101 | -by Chinese spiders that use forged UserAgent strings to make them look | |
| 101 | +by Chinese spiders that use forged UserAgent strings to make them look | |
| 102 | 102 | like normal web browsers and which interpret javascript. We do not |
| 103 | 103 | believe these attacks to be nefarious since SQLite is public domain |
| 104 | 104 | and the attackers could obtain all information they ever wanted to |
| 105 | -know about SQLite simply by cloning the repository. Instead, we | |
| 105 | +know about SQLite simply by cloning the repository. Instead, we | |
| 106 | 106 | believe these "attacks" are coming from "script kiddies". But regardless |
| 107 | 107 | of whether or not malice is involved, these attacks do present |
| 108 | 108 | an unnecessary load on the server which reduces the responsiveness of |
| 109 | 109 | the SQLite website for well-behaved and socially responsible users. |
| 110 | 110 | For this reason, additional defenses against |
| 111 | 111 | spiders have been put in place. |
| 112 | 112 | |
| 113 | -On the Admin/Access page of Fossil, just below the | |
| 113 | +On the Admin/Access page of Fossil, just below the | |
| 114 | 114 | "<b>Enable hyperlinks for "nobody" based on User-Agent and Javascript</b>" |
| 115 | 115 | setting, there are now two additional subsettings that can be optionally |
| 116 | 116 | enabled to control hyperlinks. |
| 117 | 117 | |
| 118 | 118 | The first subsetting waits to run the |
| @@ -137,11 +137,11 @@ | ||
| 137 | 137 | Fossil currently does a very good job of providing easy access to humans |
| 138 | 138 | while keeping out troublesome robots and spiders. However, spiders and |
| 139 | 139 | bots continue to grow more sophisticated, requiring ever more advanced |
| 140 | 140 | defenses. This "arms race" is unlikely to ever end. The developers of |
| 141 | 141 | Fossil will continue to try improve the spider defenses of Fossil so |
| 142 | -check back from time to time for the latest releases and updates. | |
| 142 | +check back from time to time for the latest releases and updates. | |
| 143 | 143 | |
| 144 | 144 | Readers of this page who have suggestions on how to improve the spider |
| 145 | 145 | defenses in Fossil are invited to submit your ideas to the Fossil Users |
| 146 | -mailing list: | |
| 146 | +mailing list: | |
| 147 | 147 | [mailto:[email protected] | [email protected]]. |
| 148 | 148 |
| --- www/antibot.wiki | |
| +++ www/antibot.wiki | |
| @@ -1,27 +1,27 @@ | |
| 1 | <title>Defense Against Spiders</title> |
| 2 | |
| 3 | The website presented by a Fossil server has many hyperlinks. |
| 4 | Even a modest project can have millions of pages in its |
| 5 | tree, and many of those pages (for example diffs and annotations |
| 6 | and ZIP archive of older check-ins) can be expensive to compute. |
| 7 | If a spider or bot tries to walk a website implemented by |
| 8 | Fossil, it can present a crippling bandwidth and CPU load. |
| 9 | |
| 10 | The website presented by a Fossil server is intended to be used |
| 11 | interactively by humans, not walked by spiders. This article |
| 12 | describes the techniques used by Fossil to try to welcome human |
| 13 | users while keeping out spiders. |
| 14 | |
| 15 | <h2>The "hyperlink" user capability</h2> |
| 16 | |
| 17 | Every Fossil web session has a "user". For random passers-by on the internet |
| 18 | (and for spiders) that user is "nobody". The "anonymous" user is also |
| 19 | available for humans who do not wish to identify themselves. The difference |
| 20 | is that "anonymous" requires a login (using a password supplied via |
| 21 | a CAPTCHA) whereas "nobody" does not require a login. |
| 22 | The site administrator can also create logins with |
| 23 | passwords for specific individuals. |
| 24 | |
| 25 | The "h" or "hyperlink" capability is a permission that can be granted |
| 26 | to users that enables the display of hyperlinks. Most of the hyperlinks |
| 27 | generated by Fossil are suppressed if this capability is missing. So |
| @@ -37,11 +37,11 @@ | |
| 37 | page inviting the user to log in as anonymous in order to activate hyperlinks. |
| 38 | |
| 39 | Removing the "h" capability from user "nobody" is an effective means |
| 40 | of preventing spiders from walking a Fossil-generated website. But |
| 41 | it can also be annoying to humans, since it requires them to log in. |
| 42 | Hence, Fossil provides other techniques for blocking spiders which |
| 43 | are less cumbersome to humans. |
| 44 | |
| 45 | <h2>Automatic hyperlinks based on UserAgent</h2> |
| 46 | |
| 47 | Fossil has the ability to selectively enable hyperlinks for users |
| @@ -94,25 +94,25 @@ | |
| 94 | web browsers implement javascript, so hyperlinks will appears |
| 95 | normally for human users. |
| 96 | |
| 97 | <h2>Further defenses</h2> |
| 98 | |
| 99 | Recently (as of this writing, in the spring of 2013) the Fossil server |
| 100 | on the SQLite website ([http://www.sqlite.org/src/]) has been hit repeatedly |
| 101 | by Chinese spiders that use forged UserAgent strings to make them look |
| 102 | like normal web browsers and which interpret javascript. We do not |
| 103 | believe these attacks to be nefarious since SQLite is public domain |
| 104 | and the attackers could obtain all information they ever wanted to |
| 105 | know about SQLite simply by cloning the repository. Instead, we |
| 106 | believe these "attacks" are coming from "script kiddies". But regardless |
| 107 | of whether or not malice is involved, these attacks do present |
| 108 | an unnecessary load on the server which reduces the responsiveness of |
| 109 | the SQLite website for well-behaved and socially responsible users. |
| 110 | For this reason, additional defenses against |
| 111 | spiders have been put in place. |
| 112 | |
| 113 | On the Admin/Access page of Fossil, just below the |
| 114 | "<b>Enable hyperlinks for "nobody" based on User-Agent and Javascript</b>" |
| 115 | setting, there are now two additional subsettings that can be optionally |
| 116 | enabled to control hyperlinks. |
| 117 | |
| 118 | The first subsetting waits to run the |
| @@ -137,11 +137,11 @@ | |
| 137 | Fossil currently does a very good job of providing easy access to humans |
| 138 | while keeping out troublesome robots and spiders. However, spiders and |
| 139 | bots continue to grow more sophisticated, requiring ever more advanced |
| 140 | defenses. This "arms race" is unlikely to ever end. The developers of |
| 141 | Fossil will continue to try improve the spider defenses of Fossil so |
| 142 | check back from time to time for the latest releases and updates. |
| 143 | |
| 144 | Readers of this page who have suggestions on how to improve the spider |
| 145 | defenses in Fossil are invited to submit your ideas to the Fossil Users |
| 146 | mailing list: |
| 147 | [mailto:[email protected] | [email protected]]. |
| 148 |
| --- www/antibot.wiki | |
| +++ www/antibot.wiki | |
| @@ -1,27 +1,27 @@ | |
| 1 | <title>Defense Against Spiders</title> |
| 2 | |
| 3 | The website presented by a Fossil server has many hyperlinks. |
| 4 | Even a modest project can have millions of pages in its |
| 5 | tree, and many of those pages (for example diffs and annotations |
| 6 | and ZIP archive of older check-ins) can be expensive to compute. |
| 7 | If a spider or bot tries to walk a website implemented by |
| 8 | Fossil, it can present a crippling bandwidth and CPU load. |
| 9 | |
| 10 | The website presented by a Fossil server is intended to be used |
| 11 | interactively by humans, not walked by spiders. This article |
| 12 | describes the techniques used by Fossil to try to welcome human |
| 13 | users while keeping out spiders. |
| 14 | |
| 15 | <h2>The "hyperlink" user capability</h2> |
| 16 | |
| 17 | Every Fossil web session has a "user". For random passers-by on the internet |
| 18 | (and for spiders) that user is "nobody". The "anonymous" user is also |
| 19 | available for humans who do not wish to identify themselves. The difference |
| 20 | is that "anonymous" requires a login (using a password supplied via |
| 21 | a CAPTCHA) whereas "nobody" does not require a login. |
| 22 | The site administrator can also create logins with |
| 23 | passwords for specific individuals. |
| 24 | |
| 25 | The "h" or "hyperlink" capability is a permission that can be granted |
| 26 | to users that enables the display of hyperlinks. Most of the hyperlinks |
| 27 | generated by Fossil are suppressed if this capability is missing. So |
| @@ -37,11 +37,11 @@ | |
| 37 | page inviting the user to log in as anonymous in order to activate hyperlinks. |
| 38 | |
| 39 | Removing the "h" capability from user "nobody" is an effective means |
| 40 | of preventing spiders from walking a Fossil-generated website. But |
| 41 | it can also be annoying to humans, since it requires them to log in. |
| 42 | Hence, Fossil provides other techniques for blocking spiders which |
| 43 | are less cumbersome to humans. |
| 44 | |
| 45 | <h2>Automatic hyperlinks based on UserAgent</h2> |
| 46 | |
| 47 | Fossil has the ability to selectively enable hyperlinks for users |
| @@ -94,25 +94,25 @@ | |
| 94 | web browsers implement javascript, so hyperlinks will appears |
| 95 | normally for human users. |
| 96 | |
| 97 | <h2>Further defenses</h2> |
| 98 | |
| 99 | Recently (as of this writing, in the spring of 2013) the Fossil server |
| 100 | on the SQLite website ([http://www.sqlite.org/src/]) has been hit repeatedly |
| 101 | by Chinese spiders that use forged UserAgent strings to make them look |
| 102 | like normal web browsers and which interpret javascript. We do not |
| 103 | believe these attacks to be nefarious since SQLite is public domain |
| 104 | and the attackers could obtain all information they ever wanted to |
| 105 | know about SQLite simply by cloning the repository. Instead, we |
| 106 | believe these "attacks" are coming from "script kiddies". But regardless |
| 107 | of whether or not malice is involved, these attacks do present |
| 108 | an unnecessary load on the server which reduces the responsiveness of |
| 109 | the SQLite website for well-behaved and socially responsible users. |
| 110 | For this reason, additional defenses against |
| 111 | spiders have been put in place. |
| 112 | |
| 113 | On the Admin/Access page of Fossil, just below the |
| 114 | "<b>Enable hyperlinks for "nobody" based on User-Agent and Javascript</b>" |
| 115 | setting, there are now two additional subsettings that can be optionally |
| 116 | enabled to control hyperlinks. |
| 117 | |
| 118 | The first subsetting waits to run the |
| @@ -137,11 +137,11 @@ | |
| 137 | Fossil currently does a very good job of providing easy access to humans |
| 138 | while keeping out troublesome robots and spiders. However, spiders and |
| 139 | bots continue to grow more sophisticated, requiring ever more advanced |
| 140 | defenses. This "arms race" is unlikely to ever end. The developers of |
| 141 | Fossil will continue to try improve the spider defenses of Fossil so |
| 142 | check back from time to time for the latest releases and updates. |
| 143 | |
| 144 | Readers of this page who have suggestions on how to improve the spider |
| 145 | defenses in Fossil are invited to submit your ideas to the Fossil Users |
| 146 | mailing list: |
| 147 | [mailto:[email protected] | [email protected]]. |
| 148 |
+4
-4
| --- www/blame.wiki | ||
| +++ www/blame.wiki | ||
| @@ -18,16 +18,16 @@ | ||
| 18 | 18 | <li>Locate the check-in that contains the file that is to be |
| 19 | 19 | annotated. Call this check-in C0. |
| 20 | 20 | <li>Find all direct ancestors of C0. A direct ancestor is the closure |
| 21 | 21 | of the primary parent of C0. Merged in branches are not part of |
| 22 | 22 | the direct ancestors of C0. |
| 23 | -<li>Prune the list of ancestors of C0 so that it contains only | |
| 23 | +<li>Prune the list of ancestors of C0 so that it contains only | |
| 24 | 24 | check-in in which the file to be annotated was modified. |
| 25 | 25 | <li>Load the complete text of the file to be annotated from check-in C0. |
| 26 | 26 | Call this version of the file F0. |
| 27 | 27 | <li>Parse F0 into lines. Mark each line as "unchanged". |
| 28 | -<li>For each ancestor of C0 on the pruned list (call the ancestor CX), | |
| 28 | +<li>For each ancestor of C0 on the pruned list (call the ancestor CX), | |
| 29 | 29 | beginning with the most |
| 30 | 30 | recent ancestor and moving toward the oldest ancestor, do the |
| 31 | 31 | following steps: |
| 32 | 32 | <ol type='a'> |
| 33 | 33 | <li>Load the text for the file to be annotated as it existed in check-in CX. |
| @@ -44,19 +44,19 @@ | ||
| 44 | 44 | <h2>3.0 Discussion and Notes</h2> |
| 45 | 45 | |
| 46 | 46 | The time-consuming part of this algorithm is step 6b - computing the |
| 47 | 47 | diff from all historical versions of the file to the version of the file |
| 48 | 48 | under analysis. For a large file that has many historical changes, this |
| 49 | -can take several seconds. For this reason, the default | |
| 49 | +can take several seconds. For this reason, the default | |
| 50 | 50 | [/help?cmd=/annotate|/annotate] webpage only shows those lines that where |
| 51 | 51 | changed by the 20 most recent modifications to the file. This allows |
| 52 | 52 | the loop on step 6 to terminate after only 19 diffs instead of the hundreds |
| 53 | 53 | or thousands of diffs that might be required for a frequently modified file. |
| 54 | 54 | |
| 55 | 55 | As currently implemented (as of 2015-12-12) the annotate algorithm does not |
| 56 | -follow files across name changes. File name change information is | |
| 56 | +follow files across name changes. File name change information is | |
| 57 | 57 | available in the database, and so the algorithm could be enhanced to follow |
| 58 | 58 | files across name changes by modifications to step 3. |
| 59 | 59 | |
| 60 | 60 | Step 2 is interesting in that it is |
| 61 | 61 | [/artifact/6cb824a0417?ln=196-201 | implemented] using a |
| 62 | 62 | [https://www.sqlite.org/lang_with.html#recursivecte|recursive common table expression]. |
| 63 | 63 |
| --- www/blame.wiki | |
| +++ www/blame.wiki | |
| @@ -18,16 +18,16 @@ | |
| 18 | <li>Locate the check-in that contains the file that is to be |
| 19 | annotated. Call this check-in C0. |
| 20 | <li>Find all direct ancestors of C0. A direct ancestor is the closure |
| 21 | of the primary parent of C0. Merged in branches are not part of |
| 22 | the direct ancestors of C0. |
| 23 | <li>Prune the list of ancestors of C0 so that it contains only |
| 24 | check-in in which the file to be annotated was modified. |
| 25 | <li>Load the complete text of the file to be annotated from check-in C0. |
| 26 | Call this version of the file F0. |
| 27 | <li>Parse F0 into lines. Mark each line as "unchanged". |
| 28 | <li>For each ancestor of C0 on the pruned list (call the ancestor CX), |
| 29 | beginning with the most |
| 30 | recent ancestor and moving toward the oldest ancestor, do the |
| 31 | following steps: |
| 32 | <ol type='a'> |
| 33 | <li>Load the text for the file to be annotated as it existed in check-in CX. |
| @@ -44,19 +44,19 @@ | |
| 44 | <h2>3.0 Discussion and Notes</h2> |
| 45 | |
| 46 | The time-consuming part of this algorithm is step 6b - computing the |
| 47 | diff from all historical versions of the file to the version of the file |
| 48 | under analysis. For a large file that has many historical changes, this |
| 49 | can take several seconds. For this reason, the default |
| 50 | [/help?cmd=/annotate|/annotate] webpage only shows those lines that where |
| 51 | changed by the 20 most recent modifications to the file. This allows |
| 52 | the loop on step 6 to terminate after only 19 diffs instead of the hundreds |
| 53 | or thousands of diffs that might be required for a frequently modified file. |
| 54 | |
| 55 | As currently implemented (as of 2015-12-12) the annotate algorithm does not |
| 56 | follow files across name changes. File name change information is |
| 57 | available in the database, and so the algorithm could be enhanced to follow |
| 58 | files across name changes by modifications to step 3. |
| 59 | |
| 60 | Step 2 is interesting in that it is |
| 61 | [/artifact/6cb824a0417?ln=196-201 | implemented] using a |
| 62 | [https://www.sqlite.org/lang_with.html#recursivecte|recursive common table expression]. |
| 63 |
| --- www/blame.wiki | |
| +++ www/blame.wiki | |
| @@ -18,16 +18,16 @@ | |
| 18 | <li>Locate the check-in that contains the file that is to be |
| 19 | annotated. Call this check-in C0. |
| 20 | <li>Find all direct ancestors of C0. A direct ancestor is the closure |
| 21 | of the primary parent of C0. Merged in branches are not part of |
| 22 | the direct ancestors of C0. |
| 23 | <li>Prune the list of ancestors of C0 so that it contains only |
| 24 | check-in in which the file to be annotated was modified. |
| 25 | <li>Load the complete text of the file to be annotated from check-in C0. |
| 26 | Call this version of the file F0. |
| 27 | <li>Parse F0 into lines. Mark each line as "unchanged". |
| 28 | <li>For each ancestor of C0 on the pruned list (call the ancestor CX), |
| 29 | beginning with the most |
| 30 | recent ancestor and moving toward the oldest ancestor, do the |
| 31 | following steps: |
| 32 | <ol type='a'> |
| 33 | <li>Load the text for the file to be annotated as it existed in check-in CX. |
| @@ -44,19 +44,19 @@ | |
| 44 | <h2>3.0 Discussion and Notes</h2> |
| 45 | |
| 46 | The time-consuming part of this algorithm is step 6b - computing the |
| 47 | diff from all historical versions of the file to the version of the file |
| 48 | under analysis. For a large file that has many historical changes, this |
| 49 | can take several seconds. For this reason, the default |
| 50 | [/help?cmd=/annotate|/annotate] webpage only shows those lines that where |
| 51 | changed by the 20 most recent modifications to the file. This allows |
| 52 | the loop on step 6 to terminate after only 19 diffs instead of the hundreds |
| 53 | or thousands of diffs that might be required for a frequently modified file. |
| 54 | |
| 55 | As currently implemented (as of 2015-12-12) the annotate algorithm does not |
| 56 | follow files across name changes. File name change information is |
| 57 | available in the database, and so the algorithm could be enhanced to follow |
| 58 | files across name changes by modifications to step 3. |
| 59 | |
| 60 | Step 2 is interesting in that it is |
| 61 | [/artifact/6cb824a0417?ln=196-201 | implemented] using a |
| 62 | [https://www.sqlite.org/lang_with.html#recursivecte|recursive common table expression]. |
| 63 |
+1
-1
| --- www/bugtheory.wiki | ||
| +++ www/bugtheory.wiki | ||
| @@ -27,11 +27,11 @@ | ||
| 27 | 27 | Recall that a fossil repository consists of an |
| 28 | 28 | unordered collection of <i>artifacts</i>. (See the |
| 29 | 29 | <a href="fileformat.wiki">file format document</a> for details.) |
| 30 | 30 | Some artifacts have a special format, and among those are |
| 31 | 31 | <a href="fileformat.wiki#tktchng">Ticket Change Artifacts</a>. |
| 32 | -One or more ticket change artifacts are associated with each | |
| 32 | +One or more ticket change artifacts are associated with each | |
| 33 | 33 | ticket. A ticket is created by a ticket change artifact. |
| 34 | 34 | Each subsequent modification of the ticket is a separate artifact. |
| 35 | 35 | |
| 36 | 36 | The "push", "pull", and "sync" algorithms share ticket change artifacts |
| 37 | 37 | between repositories in the same way as every other artifact. In fact, |
| 38 | 38 |
| --- www/bugtheory.wiki | |
| +++ www/bugtheory.wiki | |
| @@ -27,11 +27,11 @@ | |
| 27 | Recall that a fossil repository consists of an |
| 28 | unordered collection of <i>artifacts</i>. (See the |
| 29 | <a href="fileformat.wiki">file format document</a> for details.) |
| 30 | Some artifacts have a special format, and among those are |
| 31 | <a href="fileformat.wiki#tktchng">Ticket Change Artifacts</a>. |
| 32 | One or more ticket change artifacts are associated with each |
| 33 | ticket. A ticket is created by a ticket change artifact. |
| 34 | Each subsequent modification of the ticket is a separate artifact. |
| 35 | |
| 36 | The "push", "pull", and "sync" algorithms share ticket change artifacts |
| 37 | between repositories in the same way as every other artifact. In fact, |
| 38 |
| --- www/bugtheory.wiki | |
| +++ www/bugtheory.wiki | |
| @@ -27,11 +27,11 @@ | |
| 27 | Recall that a fossil repository consists of an |
| 28 | unordered collection of <i>artifacts</i>. (See the |
| 29 | <a href="fileformat.wiki">file format document</a> for details.) |
| 30 | Some artifacts have a special format, and among those are |
| 31 | <a href="fileformat.wiki#tktchng">Ticket Change Artifacts</a>. |
| 32 | One or more ticket change artifacts are associated with each |
| 33 | ticket. A ticket is created by a ticket change artifact. |
| 34 | Each subsequent modification of the ticket is a separate artifact. |
| 35 | |
| 36 | The "push", "pull", and "sync" algorithms share ticket change artifacts |
| 37 | between repositories in the same way as every other artifact. In fact, |
| 38 |
+29
-3
| --- www/changes.wiki | ||
| +++ www/changes.wiki | ||
| @@ -1,23 +1,42 @@ | ||
| 1 | 1 | <title>Change Log</title> |
| 2 | 2 | |
| 3 | -<h2>Changes for Version 1.36 (2016-00-00)</h2> | |
| 3 | +<a name='v1_37'></a> | |
| 4 | +<h2>Changes for Version 1.37 (2017-XX-YY)</h2> | |
| 5 | + | |
| 6 | + * Fix a C99-ism that prevents the 1.36 release from building with MSVC. | |
| 7 | + * Fix [/help?cmd=ticket|ticket set] when using the "+" prefix with fields | |
| 8 | + from the "ticketchng" table. | |
| 9 | + * Enhance the "brlist" page to make use of branch colors. | |
| 10 | + * Remove the "fusefs" command from builds that do not have the underlying | |
| 11 | + support enabled. | |
| 12 | + * Fixes for incremental git import/export. | |
| 13 | + * Minor security enhancements to | |
| 14 | + [./encryptedrepos.wiki|encrypted repositories]. | |
| 15 | + * TH1 enhancements: | |
| 16 | + <ul><li>Add <nowiki>[unversioned content]</nowiki> command.</li> | |
| 17 | + <li>Add <nowiki>[unversioned list]</nowiki> command.</li> | |
| 18 | + <li>Add project_description variable.</li> | |
| 19 | + </ul> | |
| 20 | + | |
| 21 | +<a name='v1_36'></a> | |
| 22 | +<h2>Changes for Version 1.36 (2016-10-24)</h2> | |
| 4 | 23 | |
| 5 | 24 | * Add support for [./unvers.wiki|unversioned content], |
| 6 | 25 | the [/help?cmd=unversioned|fossil unversioned] command and the |
| 7 | 26 | [/help?cmd=/uv|/uv] and [/uvlist] web pages. |
| 8 | 27 | * The [/uv/download.html|download page] is moved into |
| 9 | 28 | [./unvers.wiki|unversioned content] so that the self-hosting Fossil |
| 10 | 29 | websites no longer uses any external content. |
| 11 | 30 | * Added the "Search" button to the graphical diff generated by |
| 12 | 31 | the --tk option on the [/help?cmd=diff|diff] command. |
| 13 | - * Added the "--checkin VERSION" option to the | |
| 32 | + * Added the "--checkin VERSION" option to the | |
| 14 | 33 | [/help?cmd=diff|diff] command. |
| 15 | 34 | * Various performance enhancements to the [/help?cmd=diff|diff] command. |
| 16 | 35 | * Update internal Unicode character tables, used in regular expression |
| 17 | 36 | handling, from version 8.0 to 9.0. |
| 18 | - * Update the built-in SQLite to version 3.15 (beta). Fossil now requires | |
| 37 | + * Update the built-in SQLite to version 3.15. Fossil now requires | |
| 19 | 38 | the SQLITE_DBCONFIG_MAINDBNAME interface of SQLite which is only available |
| 20 | 39 | in SQLite version 3.15 and later and so Fossil will not work with |
| 21 | 40 | earlier SQLite versions. |
| 22 | 41 | * Fix [https://www.mail-archive.com/[email protected]/msg23618.html|multi-line timeline bug] |
| 23 | 42 | * Enhance the [/help?cmd=purge|fossil purge] command. |
| @@ -28,10 +47,11 @@ | ||
| 28 | 47 | able to pull from their parent but not push. |
| 29 | 48 | * Added the -nocomplain option to the TH1 "query" command. |
| 30 | 49 | * Added support for the chng=GLOBLIST query parameter on the |
| 31 | 50 | [/help?cmd=/timeline|/timeline] webpage. |
| 32 | 51 | |
| 52 | +<a name='v1_35'></a> | |
| 33 | 53 | <h2>Changes for Version 1.35 (2016-06-14)</h2> |
| 34 | 54 | |
| 35 | 55 | * Enable symlinks by default on all non-Windows platforms. |
| 36 | 56 | * Enhance the [/md_rules|Markdown formatting] so that hyperlinks that begin |
| 37 | 57 | with "/" are relative to the root of the Fossil repository. |
| @@ -71,10 +91,11 @@ | ||
| 71 | 91 | names in place of getpass() to read passwords and passphrases |
| 72 | 92 | * Option --baseurl now works on Windows. |
| 73 | 93 | * Numerious documentation improvements. |
| 74 | 94 | * Update the built-in SQLite to version 3.13.0. |
| 75 | 95 | |
| 96 | +<a name='v1_34'></a> | |
| 76 | 97 | <h2>Changes for Version 1.34 (2015-11-02)</h2> |
| 77 | 98 | |
| 78 | 99 | * Make the [/help?cmd=clean|fossil clean] command undoable for files less |
| 79 | 100 | than 10MiB. |
| 80 | 101 | * Update internal Unicode character tables, used in regular expression |
| @@ -106,10 +127,11 @@ | ||
| 106 | 127 | * Change the mimetype for ".n" and ".man" files to text/plain. |
| 107 | 128 | * Display improvements in the [/help?cmd=bisect|fossil bisect chart] command. |
| 108 | 129 | * Updated the built-in SQLite to version 3.9.1 and activated JSON1 and FTS5 |
| 109 | 130 | support (both currently unused within Fossil). |
| 110 | 131 | |
| 132 | +<a name='v1_33'></a> | |
| 111 | 133 | <h2>Changes for Version 1.33 (2015-05-23)</h2> |
| 112 | 134 | * Improved fork detection on [/help?cmd=update|fossil update], |
| 113 | 135 | [/help?cmd=status|fossil status] and related commands. |
| 114 | 136 | * Change the default skin to what used to be called "San Francisco Modern". |
| 115 | 137 | * Add the [/repo-tabsize] web page |
| @@ -155,10 +177,11 @@ | ||
| 155 | 177 | field for direct entry of the user name to each applicable report. |
| 156 | 178 | * Create parent directories of [/help?cmd=settings|empty-dirs] if they don't |
| 157 | 179 | already exist. |
| 158 | 180 | * Inhibit timeline links to wiki pages that have been deleted. |
| 159 | 181 | |
| 182 | +<a name='v1_33'></a> | |
| 160 | 183 | <h2>Changes for Version 1.32 (2015-03-14)</h2> |
| 161 | 184 | * When creating a new repository using [/help?cmd=init|fossil init], ensure |
| 162 | 185 | that the new repository is fully compatible with historical versions of |
| 163 | 186 | Fossil by having a valid manifest as RID 1. |
| 164 | 187 | * Anti-aliased rendering of arrowheads on timeline graphs. |
| @@ -171,10 +194,11 @@ | ||
| 171 | 194 | * Enhance the "ln=" query parameter on artifact displays to accept multiple |
| 172 | 195 | ranges, separate by spaces (or "+" when URL-encoded). |
| 173 | 196 | * Added [/help?cmd=forget|fossil forget] as an alias for |
| 174 | 197 | [/help?cmd=rm|fossil rm]. |
| 175 | 198 | |
| 199 | +<a name='v1_31'></a> | |
| 176 | 200 | <h2>Changes For Version 1.31 (2015-02-23)</h2> |
| 177 | 201 | * Change the auxiliary schema by adding columns MLINK.ISAUX and MLINK.PMID |
| 178 | 202 | columns to the schema, to support better drawing of file change graphs. |
| 179 | 203 | A [/help?cmd=rebuild|fossil rebuild] is recommended but is not required. |
| 180 | 204 | so that the new graph drawing logic can work effectively. |
| @@ -222,10 +246,11 @@ | ||
| 222 | 246 | * Allow the user of Common Table Expressions in the SQL that defaults |
| 223 | 247 | ticket reports. |
| 224 | 248 | * Break out the components (css, footer, and header) for the |
| 225 | 249 | various built-in skins into separate files in the source tree. |
| 226 | 250 | |
| 251 | +<a name='v1_30'></a> | |
| 227 | 252 | <h2>Changes For Version 1.30 (2015-01-19)</h2> |
| 228 | 253 | * Added the [/help?cmd=bundle|fossil bundle] command. |
| 229 | 254 | * Added the [/help?cmd=purge|fossil purge] command. |
| 230 | 255 | * Added the [/help?cmd=publish|fossil publish] command. |
| 231 | 256 | * Added the [/help?cmd=unpublished|fossil unpublished] command. |
| @@ -292,10 +317,11 @@ | ||
| 292 | 317 | the correctness of printf-style formatting strings. |
| 293 | 318 | * Fix CVE-2014-3566, also known as the POODLE SSL 3.0 vulnerability. |
| 294 | 319 | * Numerous documentation fixes and improvements. |
| 295 | 320 | * Other obscure and minor bug fixes - see the timeline for details. |
| 296 | 321 | |
| 322 | +<a name='v1_29'></a> | |
| 297 | 323 | <h2>Changes For Version 1.29 (2014-06-12)</h2> |
| 298 | 324 | * Add the ability to display content, diffs and annotations for UTF16 |
| 299 | 325 | text files in the web interface. |
| 300 | 326 | * Add the "SaveAs..." and "Invert" buttons |
| 301 | 327 | to the graphical diff display that results |
| 302 | 328 |
| --- www/changes.wiki | |
| +++ www/changes.wiki | |
| @@ -1,23 +1,42 @@ | |
| 1 | <title>Change Log</title> |
| 2 | |
| 3 | <h2>Changes for Version 1.36 (2016-00-00)</h2> |
| 4 | |
| 5 | * Add support for [./unvers.wiki|unversioned content], |
| 6 | the [/help?cmd=unversioned|fossil unversioned] command and the |
| 7 | [/help?cmd=/uv|/uv] and [/uvlist] web pages. |
| 8 | * The [/uv/download.html|download page] is moved into |
| 9 | [./unvers.wiki|unversioned content] so that the self-hosting Fossil |
| 10 | websites no longer uses any external content. |
| 11 | * Added the "Search" button to the graphical diff generated by |
| 12 | the --tk option on the [/help?cmd=diff|diff] command. |
| 13 | * Added the "--checkin VERSION" option to the |
| 14 | [/help?cmd=diff|diff] command. |
| 15 | * Various performance enhancements to the [/help?cmd=diff|diff] command. |
| 16 | * Update internal Unicode character tables, used in regular expression |
| 17 | handling, from version 8.0 to 9.0. |
| 18 | * Update the built-in SQLite to version 3.15 (beta). Fossil now requires |
| 19 | the SQLITE_DBCONFIG_MAINDBNAME interface of SQLite which is only available |
| 20 | in SQLite version 3.15 and later and so Fossil will not work with |
| 21 | earlier SQLite versions. |
| 22 | * Fix [https://www.mail-archive.com/[email protected]/msg23618.html|multi-line timeline bug] |
| 23 | * Enhance the [/help?cmd=purge|fossil purge] command. |
| @@ -28,10 +47,11 @@ | |
| 28 | able to pull from their parent but not push. |
| 29 | * Added the -nocomplain option to the TH1 "query" command. |
| 30 | * Added support for the chng=GLOBLIST query parameter on the |
| 31 | [/help?cmd=/timeline|/timeline] webpage. |
| 32 | |
| 33 | <h2>Changes for Version 1.35 (2016-06-14)</h2> |
| 34 | |
| 35 | * Enable symlinks by default on all non-Windows platforms. |
| 36 | * Enhance the [/md_rules|Markdown formatting] so that hyperlinks that begin |
| 37 | with "/" are relative to the root of the Fossil repository. |
| @@ -71,10 +91,11 @@ | |
| 71 | names in place of getpass() to read passwords and passphrases |
| 72 | * Option --baseurl now works on Windows. |
| 73 | * Numerious documentation improvements. |
| 74 | * Update the built-in SQLite to version 3.13.0. |
| 75 | |
| 76 | <h2>Changes for Version 1.34 (2015-11-02)</h2> |
| 77 | |
| 78 | * Make the [/help?cmd=clean|fossil clean] command undoable for files less |
| 79 | than 10MiB. |
| 80 | * Update internal Unicode character tables, used in regular expression |
| @@ -106,10 +127,11 @@ | |
| 106 | * Change the mimetype for ".n" and ".man" files to text/plain. |
| 107 | * Display improvements in the [/help?cmd=bisect|fossil bisect chart] command. |
| 108 | * Updated the built-in SQLite to version 3.9.1 and activated JSON1 and FTS5 |
| 109 | support (both currently unused within Fossil). |
| 110 | |
| 111 | <h2>Changes for Version 1.33 (2015-05-23)</h2> |
| 112 | * Improved fork detection on [/help?cmd=update|fossil update], |
| 113 | [/help?cmd=status|fossil status] and related commands. |
| 114 | * Change the default skin to what used to be called "San Francisco Modern". |
| 115 | * Add the [/repo-tabsize] web page |
| @@ -155,10 +177,11 @@ | |
| 155 | field for direct entry of the user name to each applicable report. |
| 156 | * Create parent directories of [/help?cmd=settings|empty-dirs] if they don't |
| 157 | already exist. |
| 158 | * Inhibit timeline links to wiki pages that have been deleted. |
| 159 | |
| 160 | <h2>Changes for Version 1.32 (2015-03-14)</h2> |
| 161 | * When creating a new repository using [/help?cmd=init|fossil init], ensure |
| 162 | that the new repository is fully compatible with historical versions of |
| 163 | Fossil by having a valid manifest as RID 1. |
| 164 | * Anti-aliased rendering of arrowheads on timeline graphs. |
| @@ -171,10 +194,11 @@ | |
| 171 | * Enhance the "ln=" query parameter on artifact displays to accept multiple |
| 172 | ranges, separate by spaces (or "+" when URL-encoded). |
| 173 | * Added [/help?cmd=forget|fossil forget] as an alias for |
| 174 | [/help?cmd=rm|fossil rm]. |
| 175 | |
| 176 | <h2>Changes For Version 1.31 (2015-02-23)</h2> |
| 177 | * Change the auxiliary schema by adding columns MLINK.ISAUX and MLINK.PMID |
| 178 | columns to the schema, to support better drawing of file change graphs. |
| 179 | A [/help?cmd=rebuild|fossil rebuild] is recommended but is not required. |
| 180 | so that the new graph drawing logic can work effectively. |
| @@ -222,10 +246,11 @@ | |
| 222 | * Allow the user of Common Table Expressions in the SQL that defaults |
| 223 | ticket reports. |
| 224 | * Break out the components (css, footer, and header) for the |
| 225 | various built-in skins into separate files in the source tree. |
| 226 | |
| 227 | <h2>Changes For Version 1.30 (2015-01-19)</h2> |
| 228 | * Added the [/help?cmd=bundle|fossil bundle] command. |
| 229 | * Added the [/help?cmd=purge|fossil purge] command. |
| 230 | * Added the [/help?cmd=publish|fossil publish] command. |
| 231 | * Added the [/help?cmd=unpublished|fossil unpublished] command. |
| @@ -292,10 +317,11 @@ | |
| 292 | the correctness of printf-style formatting strings. |
| 293 | * Fix CVE-2014-3566, also known as the POODLE SSL 3.0 vulnerability. |
| 294 | * Numerous documentation fixes and improvements. |
| 295 | * Other obscure and minor bug fixes - see the timeline for details. |
| 296 | |
| 297 | <h2>Changes For Version 1.29 (2014-06-12)</h2> |
| 298 | * Add the ability to display content, diffs and annotations for UTF16 |
| 299 | text files in the web interface. |
| 300 | * Add the "SaveAs..." and "Invert" buttons |
| 301 | to the graphical diff display that results |
| 302 |
| --- www/changes.wiki | |
| +++ www/changes.wiki | |
| @@ -1,23 +1,42 @@ | |
| 1 | <title>Change Log</title> |
| 2 | |
| 3 | <a name='v1_37'></a> |
| 4 | <h2>Changes for Version 1.37 (2017-XX-YY)</h2> |
| 5 | |
| 6 | * Fix a C99-ism that prevents the 1.36 release from building with MSVC. |
| 7 | * Fix [/help?cmd=ticket|ticket set] when using the "+" prefix with fields |
| 8 | from the "ticketchng" table. |
| 9 | * Enhance the "brlist" page to make use of branch colors. |
| 10 | * Remove the "fusefs" command from builds that do not have the underlying |
| 11 | support enabled. |
| 12 | * Fixes for incremental git import/export. |
| 13 | * Minor security enhancements to |
| 14 | [./encryptedrepos.wiki|encrypted repositories]. |
| 15 | * TH1 enhancements: |
| 16 | <ul><li>Add <nowiki>[unversioned content]</nowiki> command.</li> |
| 17 | <li>Add <nowiki>[unversioned list]</nowiki> command.</li> |
| 18 | <li>Add project_description variable.</li> |
| 19 | </ul> |
| 20 | |
| 21 | <a name='v1_36'></a> |
| 22 | <h2>Changes for Version 1.36 (2016-10-24)</h2> |
| 23 | |
| 24 | * Add support for [./unvers.wiki|unversioned content], |
| 25 | the [/help?cmd=unversioned|fossil unversioned] command and the |
| 26 | [/help?cmd=/uv|/uv] and [/uvlist] web pages. |
| 27 | * The [/uv/download.html|download page] is moved into |
| 28 | [./unvers.wiki|unversioned content] so that the self-hosting Fossil |
| 29 | websites no longer uses any external content. |
| 30 | * Added the "Search" button to the graphical diff generated by |
| 31 | the --tk option on the [/help?cmd=diff|diff] command. |
| 32 | * Added the "--checkin VERSION" option to the |
| 33 | [/help?cmd=diff|diff] command. |
| 34 | * Various performance enhancements to the [/help?cmd=diff|diff] command. |
| 35 | * Update internal Unicode character tables, used in regular expression |
| 36 | handling, from version 8.0 to 9.0. |
| 37 | * Update the built-in SQLite to version 3.15. Fossil now requires |
| 38 | the SQLITE_DBCONFIG_MAINDBNAME interface of SQLite which is only available |
| 39 | in SQLite version 3.15 and later and so Fossil will not work with |
| 40 | earlier SQLite versions. |
| 41 | * Fix [https://www.mail-archive.com/[email protected]/msg23618.html|multi-line timeline bug] |
| 42 | * Enhance the [/help?cmd=purge|fossil purge] command. |
| @@ -28,10 +47,11 @@ | |
| 47 | able to pull from their parent but not push. |
| 48 | * Added the -nocomplain option to the TH1 "query" command. |
| 49 | * Added support for the chng=GLOBLIST query parameter on the |
| 50 | [/help?cmd=/timeline|/timeline] webpage. |
| 51 | |
| 52 | <a name='v1_35'></a> |
| 53 | <h2>Changes for Version 1.35 (2016-06-14)</h2> |
| 54 | |
| 55 | * Enable symlinks by default on all non-Windows platforms. |
| 56 | * Enhance the [/md_rules|Markdown formatting] so that hyperlinks that begin |
| 57 | with "/" are relative to the root of the Fossil repository. |
| @@ -71,10 +91,11 @@ | |
| 91 | names in place of getpass() to read passwords and passphrases |
| 92 | * Option --baseurl now works on Windows. |
| 93 | * Numerious documentation improvements. |
| 94 | * Update the built-in SQLite to version 3.13.0. |
| 95 | |
| 96 | <a name='v1_34'></a> |
| 97 | <h2>Changes for Version 1.34 (2015-11-02)</h2> |
| 98 | |
| 99 | * Make the [/help?cmd=clean|fossil clean] command undoable for files less |
| 100 | than 10MiB. |
| 101 | * Update internal Unicode character tables, used in regular expression |
| @@ -106,10 +127,11 @@ | |
| 127 | * Change the mimetype for ".n" and ".man" files to text/plain. |
| 128 | * Display improvements in the [/help?cmd=bisect|fossil bisect chart] command. |
| 129 | * Updated the built-in SQLite to version 3.9.1 and activated JSON1 and FTS5 |
| 130 | support (both currently unused within Fossil). |
| 131 | |
| 132 | <a name='v1_33'></a> |
| 133 | <h2>Changes for Version 1.33 (2015-05-23)</h2> |
| 134 | * Improved fork detection on [/help?cmd=update|fossil update], |
| 135 | [/help?cmd=status|fossil status] and related commands. |
| 136 | * Change the default skin to what used to be called "San Francisco Modern". |
| 137 | * Add the [/repo-tabsize] web page |
| @@ -155,10 +177,11 @@ | |
| 177 | field for direct entry of the user name to each applicable report. |
| 178 | * Create parent directories of [/help?cmd=settings|empty-dirs] if they don't |
| 179 | already exist. |
| 180 | * Inhibit timeline links to wiki pages that have been deleted. |
| 181 | |
| 182 | <a name='v1_33'></a> |
| 183 | <h2>Changes for Version 1.32 (2015-03-14)</h2> |
| 184 | * When creating a new repository using [/help?cmd=init|fossil init], ensure |
| 185 | that the new repository is fully compatible with historical versions of |
| 186 | Fossil by having a valid manifest as RID 1. |
| 187 | * Anti-aliased rendering of arrowheads on timeline graphs. |
| @@ -171,10 +194,11 @@ | |
| 194 | * Enhance the "ln=" query parameter on artifact displays to accept multiple |
| 195 | ranges, separate by spaces (or "+" when URL-encoded). |
| 196 | * Added [/help?cmd=forget|fossil forget] as an alias for |
| 197 | [/help?cmd=rm|fossil rm]. |
| 198 | |
| 199 | <a name='v1_31'></a> |
| 200 | <h2>Changes For Version 1.31 (2015-02-23)</h2> |
| 201 | * Change the auxiliary schema by adding columns MLINK.ISAUX and MLINK.PMID |
| 202 | columns to the schema, to support better drawing of file change graphs. |
| 203 | A [/help?cmd=rebuild|fossil rebuild] is recommended but is not required. |
| 204 | so that the new graph drawing logic can work effectively. |
| @@ -222,10 +246,11 @@ | |
| 246 | * Allow the user of Common Table Expressions in the SQL that defaults |
| 247 | ticket reports. |
| 248 | * Break out the components (css, footer, and header) for the |
| 249 | various built-in skins into separate files in the source tree. |
| 250 | |
| 251 | <a name='v1_30'></a> |
| 252 | <h2>Changes For Version 1.30 (2015-01-19)</h2> |
| 253 | * Added the [/help?cmd=bundle|fossil bundle] command. |
| 254 | * Added the [/help?cmd=purge|fossil purge] command. |
| 255 | * Added the [/help?cmd=publish|fossil publish] command. |
| 256 | * Added the [/help?cmd=unpublished|fossil unpublished] command. |
| @@ -292,10 +317,11 @@ | |
| 317 | the correctness of printf-style formatting strings. |
| 318 | * Fix CVE-2014-3566, also known as the POODLE SSL 3.0 vulnerability. |
| 319 | * Numerous documentation fixes and improvements. |
| 320 | * Other obscure and minor bug fixes - see the timeline for details. |
| 321 | |
| 322 | <a name='v1_29'></a> |
| 323 | <h2>Changes For Version 1.29 (2014-06-12)</h2> |
| 324 | * Add the ability to display content, diffs and annotations for UTF16 |
| 325 | text files in the web interface. |
| 326 | * Add the "SaveAs..." and "Invert" buttons |
| 327 | to the graphical diff display that results |
| 328 |
+9
-9
| --- www/checkin_names.wiki | ||
| +++ www/checkin_names.wiki | ||
| @@ -55,20 +55,20 @@ | ||
| 55 | 55 | </pre></blockquote> |
| 56 | 56 | |
| 57 | 57 | The full 40-character SHA1 hash is unwieldy to remember and type, though, |
| 58 | 58 | so Fossil also accepts a unique prefix of the hash, using any combination |
| 59 | 59 | of upper and lower case letters, as long as the prefix is at least 4 |
| 60 | -characters long. Hence the following commands all | |
| 60 | +characters long. Hence the following commands all | |
| 61 | 61 | accomplish the same thing as the above: |
| 62 | 62 | |
| 63 | 63 | <blockquote><pre> |
| 64 | 64 | fossil info e5a734a19a9 |
| 65 | 65 | fossil info E5a734A |
| 66 | 66 | fossil info e5a7 |
| 67 | 67 | </blockquote> |
| 68 | 68 | |
| 69 | -Many web-interface screens identify check-ins by 10- or 16-character | |
| 69 | +Many web-interface screens identify check-ins by 10- or 16-character | |
| 70 | 70 | prefix of canonical name. |
| 71 | 71 | |
| 72 | 72 | <h2>Tags And Branch Names</h2> |
| 73 | 73 | |
| 74 | 74 | Using a tag or branch name where a check-in name is expected causes |
| @@ -112,11 +112,11 @@ | ||
| 112 | 112 | |
| 113 | 113 | <blockquote><tt> |
| 114 | 114 | fossil info tag:deed2 |
| 115 | 115 | </tt></blockquote> |
| 116 | 116 | |
| 117 | -The "tag:deed2" name will refer to the most recent check-in | |
| 117 | +The "tag:deed2" name will refer to the most recent check-in | |
| 118 | 118 | tagged with "deed2" not to the |
| 119 | 119 | check-in whose canonical name begins with "deed2". |
| 120 | 120 | |
| 121 | 121 | <h2>Whole Branches</h2> |
| 122 | 122 | |
| @@ -147,11 +147,11 @@ | ||
| 147 | 147 | * <i>YYYY-MM-DD</i> |
| 148 | 148 | * <i>YYYY-MM-DD HH:MM</i> |
| 149 | 149 | * <i>YYYY-MM-DD HH:MM:SS</i> |
| 150 | 150 | * <i>YYYY-MM-DD HH:MM:SS.SSS</i> |
| 151 | 151 | |
| 152 | -The space between the day and the year can optionally be | |
| 152 | +The space between the day and the year can optionally be | |
| 153 | 153 | replaced by an uppercase <b>T</b> and the entire timestamp can |
| 154 | 154 | optionally be followed by "<b>z</b>" or "<b>Z</b>". In the fourth |
| 155 | 155 | form with fractional seconds, any number of digits may follow the |
| 156 | 156 | decimal point, though due to precision limits only the first three |
| 157 | 157 | digits will be significant. |
| @@ -158,17 +158,17 @@ | ||
| 158 | 158 | |
| 159 | 159 | In its default configuration, Fossil interprets and displays all dates |
| 160 | 160 | in Universal Coordinated Time (UTC). This tends to work the best for |
| 161 | 161 | distributed projects where participants are scattered around the globe. |
| 162 | 162 | But there is an option on the Admin/Timeline page of the web-interface to |
| 163 | -switch to local time. The "<b>Z</b>" suffix on an timestamp check-in | |
| 163 | +switch to local time. The "<b>Z</b>" suffix on a timestamp check-in | |
| 164 | 164 | name is meaningless if Fossil is in the default mode of using UTC for |
| 165 | 165 | everything, but if Fossil has been switched to local time mode, then the |
| 166 | -"<b>Z</b>" suffix means to interpret that particular timestamp using | |
| 166 | +"<b>Z</b>" suffix means to interpret that particular timestamp using | |
| 167 | 167 | UTC instead of local time. |
| 168 | 168 | |
| 169 | -For an example of how timestamps are useful, | |
| 169 | +For an example of how timestamps are useful, | |
| 170 | 170 | consider the homepage for the Fossil website itself: |
| 171 | 171 | |
| 172 | 172 | <blockquote> |
| 173 | 173 | http://www.fossil-scm.org/fossil/doc/<b>trunk</b>/www/index.wiki |
| 174 | 174 | </blockquote> |
| @@ -191,11 +191,11 @@ | ||
| 191 | 191 | <blockquote> |
| 192 | 192 | fossil update trunk:2010-07-01T14:30 |
| 193 | 193 | </blockquote> |
| 194 | 194 | |
| 195 | 195 | Would cause Fossil to update the working check-out to be the most recent |
| 196 | -check-in on the trunk that is not more recent that 14:30 (UTC) on | |
| 196 | +check-in on the trunk that is not more recent that 14:30 (UTC) on | |
| 197 | 197 | July 1, 2010. |
| 198 | 198 | |
| 199 | 199 | <h2>Root Of A Branch</h2> |
| 200 | 200 | |
| 201 | 201 | A branch name that begins with the "<tt>root:</tt>" prefix refers to the |
| @@ -220,11 +220,11 @@ | ||
| 220 | 220 | current check-out. And the "previous" or "prev" tag means the primary |
| 221 | 221 | (non-merge) parent of the current check-out. |
| 222 | 222 | |
| 223 | 223 | For embedded documentation, the tag "ckout" means the version as present in |
| 224 | 224 | the local source tree on disk, provided that the web server is started using |
| 225 | -"fossil ui" or "fossil server" from within the source tree. This tag can be | |
| 225 | +"fossil ui" or "fossil server" from within the source tree. This tag can be | |
| 226 | 226 | used to preview local changes to documentation before committing them. It does |
| 227 | 227 | not apply to CLI commands. |
| 228 | 228 | |
| 229 | 229 | <h2>Additional Examples</h2> |
| 230 | 230 | |
| 231 | 231 |
| --- www/checkin_names.wiki | |
| +++ www/checkin_names.wiki | |
| @@ -55,20 +55,20 @@ | |
| 55 | </pre></blockquote> |
| 56 | |
| 57 | The full 40-character SHA1 hash is unwieldy to remember and type, though, |
| 58 | so Fossil also accepts a unique prefix of the hash, using any combination |
| 59 | of upper and lower case letters, as long as the prefix is at least 4 |
| 60 | characters long. Hence the following commands all |
| 61 | accomplish the same thing as the above: |
| 62 | |
| 63 | <blockquote><pre> |
| 64 | fossil info e5a734a19a9 |
| 65 | fossil info E5a734A |
| 66 | fossil info e5a7 |
| 67 | </blockquote> |
| 68 | |
| 69 | Many web-interface screens identify check-ins by 10- or 16-character |
| 70 | prefix of canonical name. |
| 71 | |
| 72 | <h2>Tags And Branch Names</h2> |
| 73 | |
| 74 | Using a tag or branch name where a check-in name is expected causes |
| @@ -112,11 +112,11 @@ | |
| 112 | |
| 113 | <blockquote><tt> |
| 114 | fossil info tag:deed2 |
| 115 | </tt></blockquote> |
| 116 | |
| 117 | The "tag:deed2" name will refer to the most recent check-in |
| 118 | tagged with "deed2" not to the |
| 119 | check-in whose canonical name begins with "deed2". |
| 120 | |
| 121 | <h2>Whole Branches</h2> |
| 122 | |
| @@ -147,11 +147,11 @@ | |
| 147 | * <i>YYYY-MM-DD</i> |
| 148 | * <i>YYYY-MM-DD HH:MM</i> |
| 149 | * <i>YYYY-MM-DD HH:MM:SS</i> |
| 150 | * <i>YYYY-MM-DD HH:MM:SS.SSS</i> |
| 151 | |
| 152 | The space between the day and the year can optionally be |
| 153 | replaced by an uppercase <b>T</b> and the entire timestamp can |
| 154 | optionally be followed by "<b>z</b>" or "<b>Z</b>". In the fourth |
| 155 | form with fractional seconds, any number of digits may follow the |
| 156 | decimal point, though due to precision limits only the first three |
| 157 | digits will be significant. |
| @@ -158,17 +158,17 @@ | |
| 158 | |
| 159 | In its default configuration, Fossil interprets and displays all dates |
| 160 | in Universal Coordinated Time (UTC). This tends to work the best for |
| 161 | distributed projects where participants are scattered around the globe. |
| 162 | But there is an option on the Admin/Timeline page of the web-interface to |
| 163 | switch to local time. The "<b>Z</b>" suffix on an timestamp check-in |
| 164 | name is meaningless if Fossil is in the default mode of using UTC for |
| 165 | everything, but if Fossil has been switched to local time mode, then the |
| 166 | "<b>Z</b>" suffix means to interpret that particular timestamp using |
| 167 | UTC instead of local time. |
| 168 | |
| 169 | For an example of how timestamps are useful, |
| 170 | consider the homepage for the Fossil website itself: |
| 171 | |
| 172 | <blockquote> |
| 173 | http://www.fossil-scm.org/fossil/doc/<b>trunk</b>/www/index.wiki |
| 174 | </blockquote> |
| @@ -191,11 +191,11 @@ | |
| 191 | <blockquote> |
| 192 | fossil update trunk:2010-07-01T14:30 |
| 193 | </blockquote> |
| 194 | |
| 195 | Would cause Fossil to update the working check-out to be the most recent |
| 196 | check-in on the trunk that is not more recent that 14:30 (UTC) on |
| 197 | July 1, 2010. |
| 198 | |
| 199 | <h2>Root Of A Branch</h2> |
| 200 | |
| 201 | A branch name that begins with the "<tt>root:</tt>" prefix refers to the |
| @@ -220,11 +220,11 @@ | |
| 220 | current check-out. And the "previous" or "prev" tag means the primary |
| 221 | (non-merge) parent of the current check-out. |
| 222 | |
| 223 | For embedded documentation, the tag "ckout" means the version as present in |
| 224 | the local source tree on disk, provided that the web server is started using |
| 225 | "fossil ui" or "fossil server" from within the source tree. This tag can be |
| 226 | used to preview local changes to documentation before committing them. It does |
| 227 | not apply to CLI commands. |
| 228 | |
| 229 | <h2>Additional Examples</h2> |
| 230 | |
| 231 |
| --- www/checkin_names.wiki | |
| +++ www/checkin_names.wiki | |
| @@ -55,20 +55,20 @@ | |
| 55 | </pre></blockquote> |
| 56 | |
| 57 | The full 40-character SHA1 hash is unwieldy to remember and type, though, |
| 58 | so Fossil also accepts a unique prefix of the hash, using any combination |
| 59 | of upper and lower case letters, as long as the prefix is at least 4 |
| 60 | characters long. Hence the following commands all |
| 61 | accomplish the same thing as the above: |
| 62 | |
| 63 | <blockquote><pre> |
| 64 | fossil info e5a734a19a9 |
| 65 | fossil info E5a734A |
| 66 | fossil info e5a7 |
| 67 | </blockquote> |
| 68 | |
| 69 | Many web-interface screens identify check-ins by 10- or 16-character |
| 70 | prefix of canonical name. |
| 71 | |
| 72 | <h2>Tags And Branch Names</h2> |
| 73 | |
| 74 | Using a tag or branch name where a check-in name is expected causes |
| @@ -112,11 +112,11 @@ | |
| 112 | |
| 113 | <blockquote><tt> |
| 114 | fossil info tag:deed2 |
| 115 | </tt></blockquote> |
| 116 | |
| 117 | The "tag:deed2" name will refer to the most recent check-in |
| 118 | tagged with "deed2" not to the |
| 119 | check-in whose canonical name begins with "deed2". |
| 120 | |
| 121 | <h2>Whole Branches</h2> |
| 122 | |
| @@ -147,11 +147,11 @@ | |
| 147 | * <i>YYYY-MM-DD</i> |
| 148 | * <i>YYYY-MM-DD HH:MM</i> |
| 149 | * <i>YYYY-MM-DD HH:MM:SS</i> |
| 150 | * <i>YYYY-MM-DD HH:MM:SS.SSS</i> |
| 151 | |
| 152 | The space between the day and the year can optionally be |
| 153 | replaced by an uppercase <b>T</b> and the entire timestamp can |
| 154 | optionally be followed by "<b>z</b>" or "<b>Z</b>". In the fourth |
| 155 | form with fractional seconds, any number of digits may follow the |
| 156 | decimal point, though due to precision limits only the first three |
| 157 | digits will be significant. |
| @@ -158,17 +158,17 @@ | |
| 158 | |
| 159 | In its default configuration, Fossil interprets and displays all dates |
| 160 | in Universal Coordinated Time (UTC). This tends to work the best for |
| 161 | distributed projects where participants are scattered around the globe. |
| 162 | But there is an option on the Admin/Timeline page of the web-interface to |
| 163 | switch to local time. The "<b>Z</b>" suffix on a timestamp check-in |
| 164 | name is meaningless if Fossil is in the default mode of using UTC for |
| 165 | everything, but if Fossil has been switched to local time mode, then the |
| 166 | "<b>Z</b>" suffix means to interpret that particular timestamp using |
| 167 | UTC instead of local time. |
| 168 | |
| 169 | For an example of how timestamps are useful, |
| 170 | consider the homepage for the Fossil website itself: |
| 171 | |
| 172 | <blockquote> |
| 173 | http://www.fossil-scm.org/fossil/doc/<b>trunk</b>/www/index.wiki |
| 174 | </blockquote> |
| @@ -191,11 +191,11 @@ | |
| 191 | <blockquote> |
| 192 | fossil update trunk:2010-07-01T14:30 |
| 193 | </blockquote> |
| 194 | |
| 195 | Would cause Fossil to update the working check-out to be the most recent |
| 196 | check-in on the trunk that is not more recent that 14:30 (UTC) on |
| 197 | July 1, 2010. |
| 198 | |
| 199 | <h2>Root Of A Branch</h2> |
| 200 | |
| 201 | A branch name that begins with the "<tt>root:</tt>" prefix refers to the |
| @@ -220,11 +220,11 @@ | |
| 220 | current check-out. And the "previous" or "prev" tag means the primary |
| 221 | (non-merge) parent of the current check-out. |
| 222 | |
| 223 | For embedded documentation, the tag "ckout" means the version as present in |
| 224 | the local source tree on disk, provided that the web server is started using |
| 225 | "fossil ui" or "fossil server" from within the source tree. This tag can be |
| 226 | used to preview local changes to documentation before committing them. It does |
| 227 | not apply to CLI commands. |
| 228 | |
| 229 | <h2>Additional Examples</h2> |
| 230 | |
| 231 |
+3
-3
| --- www/childprojects.wiki | ||
| +++ www/childprojects.wiki | ||
| @@ -37,21 +37,21 @@ | ||
| 37 | 37 | VALUES('project-code',lower(hex(randomblob(20)))); |
| 38 | 38 | INSERT INTO config(name,value) |
| 39 | 39 | VALUES('project-name','CHILD-PROJECT-NAME'); |
| 40 | 40 | </verbatim></blockquote> |
| 41 | 41 | |
| 42 | -Modify the CHILD-PROJECT-NAME in the last statement to be the name of | |
| 42 | +Modify the CHILD-PROJECT-NAME in the last statement to be the name of | |
| 43 | 43 | the child project, of course. |
| 44 | 44 | |
| 45 | 45 | The repository is now a separate project, independent from its parent. |
| 46 | 46 | Clone the new project to the developers as needed. |
| 47 | 47 | |
| 48 | 48 | The child project and the parent project will not normally be able to sync |
| 49 | 49 | with one another, since they are now separate projects with distinct |
| 50 | 50 | project codes. However, if the |
| 51 | -"--from-parent-project" command-line option is provided to the | |
| 52 | -"[/help?cmd=pull|fossil pull]" command in the child, and the URL of | |
| 51 | +"--from-parent-project" command-line option is provided to the | |
| 52 | +"[/help?cmd=pull|fossil pull]" command in the child, and the URL of | |
| 53 | 53 | parent repository is also provided on the command-line, then updates to |
| 54 | 54 | the parent project that occurred after the child was created will be added |
| 55 | 55 | to the child repository. Thus, by periodically doing a |
| 56 | 56 | pull --from-parent-project, the child project is able to stay up to date |
| 57 | 57 | with all the latest changes in the parent. |
| 58 | 58 |
| --- www/childprojects.wiki | |
| +++ www/childprojects.wiki | |
| @@ -37,21 +37,21 @@ | |
| 37 | VALUES('project-code',lower(hex(randomblob(20)))); |
| 38 | INSERT INTO config(name,value) |
| 39 | VALUES('project-name','CHILD-PROJECT-NAME'); |
| 40 | </verbatim></blockquote> |
| 41 | |
| 42 | Modify the CHILD-PROJECT-NAME in the last statement to be the name of |
| 43 | the child project, of course. |
| 44 | |
| 45 | The repository is now a separate project, independent from its parent. |
| 46 | Clone the new project to the developers as needed. |
| 47 | |
| 48 | The child project and the parent project will not normally be able to sync |
| 49 | with one another, since they are now separate projects with distinct |
| 50 | project codes. However, if the |
| 51 | "--from-parent-project" command-line option is provided to the |
| 52 | "[/help?cmd=pull|fossil pull]" command in the child, and the URL of |
| 53 | parent repository is also provided on the command-line, then updates to |
| 54 | the parent project that occurred after the child was created will be added |
| 55 | to the child repository. Thus, by periodically doing a |
| 56 | pull --from-parent-project, the child project is able to stay up to date |
| 57 | with all the latest changes in the parent. |
| 58 |
| --- www/childprojects.wiki | |
| +++ www/childprojects.wiki | |
| @@ -37,21 +37,21 @@ | |
| 37 | VALUES('project-code',lower(hex(randomblob(20)))); |
| 38 | INSERT INTO config(name,value) |
| 39 | VALUES('project-name','CHILD-PROJECT-NAME'); |
| 40 | </verbatim></blockquote> |
| 41 | |
| 42 | Modify the CHILD-PROJECT-NAME in the last statement to be the name of |
| 43 | the child project, of course. |
| 44 | |
| 45 | The repository is now a separate project, independent from its parent. |
| 46 | Clone the new project to the developers as needed. |
| 47 | |
| 48 | The child project and the parent project will not normally be able to sync |
| 49 | with one another, since they are now separate projects with distinct |
| 50 | project codes. However, if the |
| 51 | "--from-parent-project" command-line option is provided to the |
| 52 | "[/help?cmd=pull|fossil pull]" command in the child, and the URL of |
| 53 | parent repository is also provided on the command-line, then updates to |
| 54 | the parent project that occurred after the child was created will be added |
| 55 | to the child repository. Thus, by periodically doing a |
| 56 | pull --from-parent-project, the child project is able to stay up to date |
| 57 | with all the latest changes in the parent. |
| 58 |
+8
-8
| --- www/concepts.wiki | ||
| +++ www/concepts.wiki | ||
| @@ -131,11 +131,11 @@ | ||
| 131 | 131 | <h3>2.2 Manifests</h3> |
| 132 | 132 | |
| 133 | 133 | Associated with every check-in is a special file called the |
| 134 | 134 | [./fileformat.wiki#manifest| "manifest"]. The manifest is a |
| 135 | 135 | listing of all other files in |
| 136 | -that source tree. The manifest contains the (complete) artifact ID | |
| 136 | +that source tree. The manifest contains the (complete) artifact ID | |
| 137 | 137 | of the file and the name of the file as it appears on disk, |
| 138 | 138 | and thus serves as a mapping from artifact ID to disk name. The artifact ID |
| 139 | 139 | of the manifest is the identifier for the entire check-in. When |
| 140 | 140 | you look at a "timeline" of changes in Fossil, the ID associated |
| 141 | 141 | with each check-in or commit is really just the artifact ID of the |
| @@ -147,11 +147,11 @@ | ||
| 147 | 147 | manifest file to be materialized to disk, if desired. Both Fossil |
| 148 | 148 | itself, and SQLite cause the manifest file to be materialized to disk |
| 149 | 149 | so that the makefiles for these project can read the manifest and |
| 150 | 150 | embed version information in generated binaries. |
| 151 | 151 | |
| 152 | -<p>Fossil automatically generates a manifest whenever you "commit" | |
| 152 | +<p>Fossil automatically generates a manifest whenever you "commit" | |
| 153 | 153 | a new check-in. So this is not something that you, the developer, |
| 154 | 154 | need to worry with. The format of a manifest is intentionally |
| 155 | 155 | designed to be simple to parse, so that if |
| 156 | 156 | you want to read and interpret a manifest, either by hand or |
| 157 | 157 | with a script, that is easy to do. But you will probably never |
| @@ -200,11 +200,11 @@ | ||
| 200 | 200 | Fossil effectively. You will want to have some kind of text editor |
| 201 | 201 | for entering check-in comments. Fossil will use whatever text editor |
| 202 | 202 | is identified by your VISUAL environment variable. Fossil will also |
| 203 | 203 | use GPG to clearsign your manifests if you happen to have it installed, |
| 204 | 204 | but Fossil will skip that step if GPG missing from your system. |
| 205 | -You can optionally set up Fossil to use external "diff" programs, | |
| 205 | +You can optionally set up Fossil to use external "diff" programs, | |
| 206 | 206 | though Fossil has an excellent built-in "diff" algorithm that works |
| 207 | 207 | fine for most people. If you happen to have Tcl/Tk installed on your |
| 208 | 208 | system, Fossil will use it to generate a graphical "diff" display when |
| 209 | 209 | you use the --tk option to the "diff" command, but this too is entirely |
| 210 | 210 | optional. |
| @@ -211,11 +211,11 @@ | ||
| 211 | 211 | |
| 212 | 212 | |
| 213 | 213 | To uninstall Fossil, simply delete the executable. |
| 214 | 214 | |
| 215 | 215 | To upgrade an older version of Fossil to a newer version, just |
| 216 | -replace the old executable with the new one. You might need to | |
| 216 | +replace the old executable with the new one. You might need to | |
| 217 | 217 | run "<b>fossil all rebuild</b>" to restructure your repositories after |
| 218 | 218 | an upgrade. Running "all rebuild" never hurts, so when upgrading it |
| 219 | 219 | is a good policy to run it even if it is not strictly necessary. |
| 220 | 220 | |
| 221 | 221 | To use Fossil, simply type the name of the executable in your |
| @@ -266,11 +266,11 @@ | ||
| 266 | 266 | |
| 267 | 267 | <ol> |
| 268 | 268 | <li> |
| 269 | 269 | Establish a local repository using either the <b>new</b> command |
| 270 | 270 | to start a new project, or the <b>clone</b> command to make a clone |
| 271 | -of a repository for an existing project. | |
| 271 | +of a repository for an existing project. | |
| 272 | 272 | </li> |
| 273 | 273 | |
| 274 | 274 | <li> |
| 275 | 275 | Establish one or more source trees using |
| 276 | 276 | the <b>open</b> command with the name of the repository file as its |
| @@ -279,11 +279,11 @@ | ||
| 279 | 279 | |
| 280 | 280 | <li> |
| 281 | 281 | The <b>open</b> command in the previous step populates your local source |
| 282 | 282 | tree with a copy of the latest check-in. Usually this is what you want. |
| 283 | 283 | In the rare cases where it is not, use the <b>update</b> command to |
| 284 | -switch to a different check-in. | |
| 284 | +switch to a different check-in. | |
| 285 | 285 | Use the <b>timeline</b> or <b>leaves</b> commands |
| 286 | 286 | to identify alternative check-ins to switch to. |
| 287 | 287 | </li> |
| 288 | 288 | |
| 289 | 289 | <li> |
| @@ -302,17 +302,17 @@ | ||
| 302 | 302 | you cloned from or whatever server you most recently synced with. |
| 303 | 303 | </li> |
| 304 | 304 | |
| 305 | 305 | <li> |
| 306 | 306 | When your coworkers make their own changes, you can merge those changes |
| 307 | -into your local local source tree using the <b>update</b> command. | |
| 307 | +into your local local source tree using the <b>update</b> command. | |
| 308 | 308 | In autosync mode, <b>update</b> will first go back to the server you |
| 309 | 309 | cloned from or with which you most recently synced, and pull down all |
| 310 | 310 | recent changes into your local repository. Then it will merge recent |
| 311 | 311 | changes into your local source tree. If you do an <b>update</b> and |
| 312 | 312 | find that it messes something up in your source tree (perhaps a co-worker |
| 313 | -checked in incompatible changes) you can use the <b>undo</b> command | |
| 313 | +checked in incompatible changes) you can use the <b>undo</b> command | |
| 314 | 314 | to back out the changes. |
| 315 | 315 | </li> |
| 316 | 316 | |
| 317 | 317 | <li> |
| 318 | 318 | Repeat all of the above until you have generated great software. |
| 319 | 319 |
| --- www/concepts.wiki | |
| +++ www/concepts.wiki | |
| @@ -131,11 +131,11 @@ | |
| 131 | <h3>2.2 Manifests</h3> |
| 132 | |
| 133 | Associated with every check-in is a special file called the |
| 134 | [./fileformat.wiki#manifest| "manifest"]. The manifest is a |
| 135 | listing of all other files in |
| 136 | that source tree. The manifest contains the (complete) artifact ID |
| 137 | of the file and the name of the file as it appears on disk, |
| 138 | and thus serves as a mapping from artifact ID to disk name. The artifact ID |
| 139 | of the manifest is the identifier for the entire check-in. When |
| 140 | you look at a "timeline" of changes in Fossil, the ID associated |
| 141 | with each check-in or commit is really just the artifact ID of the |
| @@ -147,11 +147,11 @@ | |
| 147 | manifest file to be materialized to disk, if desired. Both Fossil |
| 148 | itself, and SQLite cause the manifest file to be materialized to disk |
| 149 | so that the makefiles for these project can read the manifest and |
| 150 | embed version information in generated binaries. |
| 151 | |
| 152 | <p>Fossil automatically generates a manifest whenever you "commit" |
| 153 | a new check-in. So this is not something that you, the developer, |
| 154 | need to worry with. The format of a manifest is intentionally |
| 155 | designed to be simple to parse, so that if |
| 156 | you want to read and interpret a manifest, either by hand or |
| 157 | with a script, that is easy to do. But you will probably never |
| @@ -200,11 +200,11 @@ | |
| 200 | Fossil effectively. You will want to have some kind of text editor |
| 201 | for entering check-in comments. Fossil will use whatever text editor |
| 202 | is identified by your VISUAL environment variable. Fossil will also |
| 203 | use GPG to clearsign your manifests if you happen to have it installed, |
| 204 | but Fossil will skip that step if GPG missing from your system. |
| 205 | You can optionally set up Fossil to use external "diff" programs, |
| 206 | though Fossil has an excellent built-in "diff" algorithm that works |
| 207 | fine for most people. If you happen to have Tcl/Tk installed on your |
| 208 | system, Fossil will use it to generate a graphical "diff" display when |
| 209 | you use the --tk option to the "diff" command, but this too is entirely |
| 210 | optional. |
| @@ -211,11 +211,11 @@ | |
| 211 | |
| 212 | |
| 213 | To uninstall Fossil, simply delete the executable. |
| 214 | |
| 215 | To upgrade an older version of Fossil to a newer version, just |
| 216 | replace the old executable with the new one. You might need to |
| 217 | run "<b>fossil all rebuild</b>" to restructure your repositories after |
| 218 | an upgrade. Running "all rebuild" never hurts, so when upgrading it |
| 219 | is a good policy to run it even if it is not strictly necessary. |
| 220 | |
| 221 | To use Fossil, simply type the name of the executable in your |
| @@ -266,11 +266,11 @@ | |
| 266 | |
| 267 | <ol> |
| 268 | <li> |
| 269 | Establish a local repository using either the <b>new</b> command |
| 270 | to start a new project, or the <b>clone</b> command to make a clone |
| 271 | of a repository for an existing project. |
| 272 | </li> |
| 273 | |
| 274 | <li> |
| 275 | Establish one or more source trees using |
| 276 | the <b>open</b> command with the name of the repository file as its |
| @@ -279,11 +279,11 @@ | |
| 279 | |
| 280 | <li> |
| 281 | The <b>open</b> command in the previous step populates your local source |
| 282 | tree with a copy of the latest check-in. Usually this is what you want. |
| 283 | In the rare cases where it is not, use the <b>update</b> command to |
| 284 | switch to a different check-in. |
| 285 | Use the <b>timeline</b> or <b>leaves</b> commands |
| 286 | to identify alternative check-ins to switch to. |
| 287 | </li> |
| 288 | |
| 289 | <li> |
| @@ -302,17 +302,17 @@ | |
| 302 | you cloned from or whatever server you most recently synced with. |
| 303 | </li> |
| 304 | |
| 305 | <li> |
| 306 | When your coworkers make their own changes, you can merge those changes |
| 307 | into your local local source tree using the <b>update</b> command. |
| 308 | In autosync mode, <b>update</b> will first go back to the server you |
| 309 | cloned from or with which you most recently synced, and pull down all |
| 310 | recent changes into your local repository. Then it will merge recent |
| 311 | changes into your local source tree. If you do an <b>update</b> and |
| 312 | find that it messes something up in your source tree (perhaps a co-worker |
| 313 | checked in incompatible changes) you can use the <b>undo</b> command |
| 314 | to back out the changes. |
| 315 | </li> |
| 316 | |
| 317 | <li> |
| 318 | Repeat all of the above until you have generated great software. |
| 319 |
| --- www/concepts.wiki | |
| +++ www/concepts.wiki | |
| @@ -131,11 +131,11 @@ | |
| 131 | <h3>2.2 Manifests</h3> |
| 132 | |
| 133 | Associated with every check-in is a special file called the |
| 134 | [./fileformat.wiki#manifest| "manifest"]. The manifest is a |
| 135 | listing of all other files in |
| 136 | that source tree. The manifest contains the (complete) artifact ID |
| 137 | of the file and the name of the file as it appears on disk, |
| 138 | and thus serves as a mapping from artifact ID to disk name. The artifact ID |
| 139 | of the manifest is the identifier for the entire check-in. When |
| 140 | you look at a "timeline" of changes in Fossil, the ID associated |
| 141 | with each check-in or commit is really just the artifact ID of the |
| @@ -147,11 +147,11 @@ | |
| 147 | manifest file to be materialized to disk, if desired. Both Fossil |
| 148 | itself, and SQLite cause the manifest file to be materialized to disk |
| 149 | so that the makefiles for these project can read the manifest and |
| 150 | embed version information in generated binaries. |
| 151 | |
| 152 | <p>Fossil automatically generates a manifest whenever you "commit" |
| 153 | a new check-in. So this is not something that you, the developer, |
| 154 | need to worry with. The format of a manifest is intentionally |
| 155 | designed to be simple to parse, so that if |
| 156 | you want to read and interpret a manifest, either by hand or |
| 157 | with a script, that is easy to do. But you will probably never |
| @@ -200,11 +200,11 @@ | |
| 200 | Fossil effectively. You will want to have some kind of text editor |
| 201 | for entering check-in comments. Fossil will use whatever text editor |
| 202 | is identified by your VISUAL environment variable. Fossil will also |
| 203 | use GPG to clearsign your manifests if you happen to have it installed, |
| 204 | but Fossil will skip that step if GPG missing from your system. |
| 205 | You can optionally set up Fossil to use external "diff" programs, |
| 206 | though Fossil has an excellent built-in "diff" algorithm that works |
| 207 | fine for most people. If you happen to have Tcl/Tk installed on your |
| 208 | system, Fossil will use it to generate a graphical "diff" display when |
| 209 | you use the --tk option to the "diff" command, but this too is entirely |
| 210 | optional. |
| @@ -211,11 +211,11 @@ | |
| 211 | |
| 212 | |
| 213 | To uninstall Fossil, simply delete the executable. |
| 214 | |
| 215 | To upgrade an older version of Fossil to a newer version, just |
| 216 | replace the old executable with the new one. You might need to |
| 217 | run "<b>fossil all rebuild</b>" to restructure your repositories after |
| 218 | an upgrade. Running "all rebuild" never hurts, so when upgrading it |
| 219 | is a good policy to run it even if it is not strictly necessary. |
| 220 | |
| 221 | To use Fossil, simply type the name of the executable in your |
| @@ -266,11 +266,11 @@ | |
| 266 | |
| 267 | <ol> |
| 268 | <li> |
| 269 | Establish a local repository using either the <b>new</b> command |
| 270 | to start a new project, or the <b>clone</b> command to make a clone |
| 271 | of a repository for an existing project. |
| 272 | </li> |
| 273 | |
| 274 | <li> |
| 275 | Establish one or more source trees using |
| 276 | the <b>open</b> command with the name of the repository file as its |
| @@ -279,11 +279,11 @@ | |
| 279 | |
| 280 | <li> |
| 281 | The <b>open</b> command in the previous step populates your local source |
| 282 | tree with a copy of the latest check-in. Usually this is what you want. |
| 283 | In the rare cases where it is not, use the <b>update</b> command to |
| 284 | switch to a different check-in. |
| 285 | Use the <b>timeline</b> or <b>leaves</b> commands |
| 286 | to identify alternative check-ins to switch to. |
| 287 | </li> |
| 288 | |
| 289 | <li> |
| @@ -302,17 +302,17 @@ | |
| 302 | you cloned from or whatever server you most recently synced with. |
| 303 | </li> |
| 304 | |
| 305 | <li> |
| 306 | When your coworkers make their own changes, you can merge those changes |
| 307 | into your local local source tree using the <b>update</b> command. |
| 308 | In autosync mode, <b>update</b> will first go back to the server you |
| 309 | cloned from or with which you most recently synced, and pull down all |
| 310 | recent changes into your local repository. Then it will merge recent |
| 311 | changes into your local source tree. If you do an <b>update</b> and |
| 312 | find that it messes something up in your source tree (perhaps a co-worker |
| 313 | checked in incompatible changes) you can use the <b>undo</b> command |
| 314 | to back out the changes. |
| 315 | </li> |
| 316 | |
| 317 | <li> |
| 318 | Repeat all of the above until you have generated great software. |
| 319 |
+7
-7
| --- www/contribute.wiki | ||
| +++ www/contribute.wiki | ||
| @@ -10,11 +10,11 @@ | ||
| 10 | 10 | [./copyright-release.pdf | Contributor Agreement (PDF)] |
| 11 | 11 | (or [./copyright-release.html | as HTML]) on file for you. We require |
| 12 | 12 | this in order to maintain clear title to the Fossil code and prevent |
| 13 | 13 | the introduction of code with incompatible licenses or other entanglements |
| 14 | 14 | that might cause legal problems for Fossil users. Many larger companies |
| 15 | -and other lawyer-rich organizations require this as a precondition to using | |
| 15 | +and other lawyer-rich organizations require this as a precondition to using | |
| 16 | 16 | Fossil. |
| 17 | 17 | |
| 18 | 18 | If you do not wish to submit a Contributor Agreement, we would still |
| 19 | 19 | welcome your suggestions and example code, but we will not use your code |
| 20 | 20 | directly - we will be forced to re-implement your changes from scratch which |
| @@ -21,14 +21,14 @@ | ||
| 21 | 21 | might take longer. |
| 22 | 22 | |
| 23 | 23 | <h2>2.0 Submitting Patches</h2> |
| 24 | 24 | |
| 25 | 25 | Suggested changes or bug fixes can be submitted by creating a patch |
| 26 | -against the current source tree. Email patches to | |
| 27 | -<a href="mailto:[email protected]">[email protected]</a>. Be sure to | |
| 26 | +against the current source tree. Email patches to | |
| 27 | +<a href="mailto:[email protected]">[email protected]</a>. Be sure to | |
| 28 | 28 | describe in detail what the patch does and which version of Fossil |
| 29 | -it is written against. | |
| 29 | +it is written against. | |
| 30 | 30 | |
| 31 | 31 | A contributor agreement is not strictly necessary to submit a patch. |
| 32 | 32 | However, without a contributor agreement on file, your patch will be |
| 33 | 33 | used for reference only - it will not be applied to the code. This |
| 34 | 34 | may delay acceptance of your patch. |
| @@ -53,23 +53,23 @@ | ||
| 53 | 53 | Fossil Architect (Richard Hipp) will merge changes onto the trunk.</p> |
| 54 | 54 | |
| 55 | 55 | Contributors are required to following the |
| 56 | 56 | [./checkin.wiki | pre-checkin checklist] prior to every check-in to |
| 57 | 57 | the Fossil self-hosting repository. This checklist is short and succinct |
| 58 | -and should only require a few seconds to follow. Contributors | |
| 58 | +and should only require a few seconds to follow. Contributors | |
| 59 | 59 | should print out a copy of the pre-checkin checklist and keep |
| 60 | 60 | it on a notecard beside their workstations, for quick reference. |
| 61 | 61 | |
| 62 | 62 | Contributors should review the |
| 63 | 63 | [./style.wiki | Coding Style Guidelines] and mimic the coding style |
| 64 | 64 | used through the rest of the Fossil source code. Your code should |
| 65 | 65 | blend in. A third-party reader should be unable to distinguish your |
| 66 | -code from any other code in the source corpus. | |
| 66 | +code from any other code in the source corpus. | |
| 67 | 67 | |
| 68 | 68 | <h2>4.0 Testing</h2> |
| 69 | 69 | |
| 70 | -Fossil has the beginnings of a | |
| 70 | +Fossil has the beginnings of a | |
| 71 | 71 | [../test/release-checklist.wiki | release checklist] but this is an |
| 72 | 72 | area that needs further work. (Your contributions here are welcomed!) |
| 73 | 73 | Contributors with check-in privileges are expected to run the release |
| 74 | 74 | checklist on any major changes they contribute, and if appropriate expand |
| 75 | 75 | the checklist and/or the automated test scripts to cover their additions. |
| 76 | 76 |
| --- www/contribute.wiki | |
| +++ www/contribute.wiki | |
| @@ -10,11 +10,11 @@ | |
| 10 | [./copyright-release.pdf | Contributor Agreement (PDF)] |
| 11 | (or [./copyright-release.html | as HTML]) on file for you. We require |
| 12 | this in order to maintain clear title to the Fossil code and prevent |
| 13 | the introduction of code with incompatible licenses or other entanglements |
| 14 | that might cause legal problems for Fossil users. Many larger companies |
| 15 | and other lawyer-rich organizations require this as a precondition to using |
| 16 | Fossil. |
| 17 | |
| 18 | If you do not wish to submit a Contributor Agreement, we would still |
| 19 | welcome your suggestions and example code, but we will not use your code |
| 20 | directly - we will be forced to re-implement your changes from scratch which |
| @@ -21,14 +21,14 @@ | |
| 21 | might take longer. |
| 22 | |
| 23 | <h2>2.0 Submitting Patches</h2> |
| 24 | |
| 25 | Suggested changes or bug fixes can be submitted by creating a patch |
| 26 | against the current source tree. Email patches to |
| 27 | <a href="mailto:[email protected]">[email protected]</a>. Be sure to |
| 28 | describe in detail what the patch does and which version of Fossil |
| 29 | it is written against. |
| 30 | |
| 31 | A contributor agreement is not strictly necessary to submit a patch. |
| 32 | However, without a contributor agreement on file, your patch will be |
| 33 | used for reference only - it will not be applied to the code. This |
| 34 | may delay acceptance of your patch. |
| @@ -53,23 +53,23 @@ | |
| 53 | Fossil Architect (Richard Hipp) will merge changes onto the trunk.</p> |
| 54 | |
| 55 | Contributors are required to following the |
| 56 | [./checkin.wiki | pre-checkin checklist] prior to every check-in to |
| 57 | the Fossil self-hosting repository. This checklist is short and succinct |
| 58 | and should only require a few seconds to follow. Contributors |
| 59 | should print out a copy of the pre-checkin checklist and keep |
| 60 | it on a notecard beside their workstations, for quick reference. |
| 61 | |
| 62 | Contributors should review the |
| 63 | [./style.wiki | Coding Style Guidelines] and mimic the coding style |
| 64 | used through the rest of the Fossil source code. Your code should |
| 65 | blend in. A third-party reader should be unable to distinguish your |
| 66 | code from any other code in the source corpus. |
| 67 | |
| 68 | <h2>4.0 Testing</h2> |
| 69 | |
| 70 | Fossil has the beginnings of a |
| 71 | [../test/release-checklist.wiki | release checklist] but this is an |
| 72 | area that needs further work. (Your contributions here are welcomed!) |
| 73 | Contributors with check-in privileges are expected to run the release |
| 74 | checklist on any major changes they contribute, and if appropriate expand |
| 75 | the checklist and/or the automated test scripts to cover their additions. |
| 76 |
| --- www/contribute.wiki | |
| +++ www/contribute.wiki | |
| @@ -10,11 +10,11 @@ | |
| 10 | [./copyright-release.pdf | Contributor Agreement (PDF)] |
| 11 | (or [./copyright-release.html | as HTML]) on file for you. We require |
| 12 | this in order to maintain clear title to the Fossil code and prevent |
| 13 | the introduction of code with incompatible licenses or other entanglements |
| 14 | that might cause legal problems for Fossil users. Many larger companies |
| 15 | and other lawyer-rich organizations require this as a precondition to using |
| 16 | Fossil. |
| 17 | |
| 18 | If you do not wish to submit a Contributor Agreement, we would still |
| 19 | welcome your suggestions and example code, but we will not use your code |
| 20 | directly - we will be forced to re-implement your changes from scratch which |
| @@ -21,14 +21,14 @@ | |
| 21 | might take longer. |
| 22 | |
| 23 | <h2>2.0 Submitting Patches</h2> |
| 24 | |
| 25 | Suggested changes or bug fixes can be submitted by creating a patch |
| 26 | against the current source tree. Email patches to |
| 27 | <a href="mailto:[email protected]">[email protected]</a>. Be sure to |
| 28 | describe in detail what the patch does and which version of Fossil |
| 29 | it is written against. |
| 30 | |
| 31 | A contributor agreement is not strictly necessary to submit a patch. |
| 32 | However, without a contributor agreement on file, your patch will be |
| 33 | used for reference only - it will not be applied to the code. This |
| 34 | may delay acceptance of your patch. |
| @@ -53,23 +53,23 @@ | |
| 53 | Fossil Architect (Richard Hipp) will merge changes onto the trunk.</p> |
| 54 | |
| 55 | Contributors are required to following the |
| 56 | [./checkin.wiki | pre-checkin checklist] prior to every check-in to |
| 57 | the Fossil self-hosting repository. This checklist is short and succinct |
| 58 | and should only require a few seconds to follow. Contributors |
| 59 | should print out a copy of the pre-checkin checklist and keep |
| 60 | it on a notecard beside their workstations, for quick reference. |
| 61 | |
| 62 | Contributors should review the |
| 63 | [./style.wiki | Coding Style Guidelines] and mimic the coding style |
| 64 | used through the rest of the Fossil source code. Your code should |
| 65 | blend in. A third-party reader should be unable to distinguish your |
| 66 | code from any other code in the source corpus. |
| 67 | |
| 68 | <h2>4.0 Testing</h2> |
| 69 | |
| 70 | Fossil has the beginnings of a |
| 71 | [../test/release-checklist.wiki | release checklist] but this is an |
| 72 | area that needs further work. (Your contributions here are welcomed!) |
| 73 | Contributors with check-in privileges are expected to run the release |
| 74 | checklist on any major changes they contribute, and if appropriate expand |
| 75 | the checklist and/or the automated test scripts to cover their additions. |
| 76 |
+2
-2
| --- www/custom_ticket.wiki | ||
| +++ www/custom_ticket.wiki | ||
| @@ -65,11 +65,11 @@ | ||
| 65 | 65 | </tr> |
| 66 | 66 | <th1>enable_output 1</th1> |
| 67 | 67 | </pre> |
| 68 | 68 | This bit of code will get rid of the "email" field entry for logged-in users. |
| 69 | 69 | Since we know the user's information, we don't have to ask for it. NOTE: it |
| 70 | -might be good to automatically scoop up the user's email and put it here. | |
| 70 | +might be good to automatically scoop up the user's email and put it here. | |
| 71 | 71 | </p> |
| 72 | 72 | </blockquote> |
| 73 | 73 | |
| 74 | 74 | <h2>Modify the 'view ticket' page</h2><blockquote> |
| 75 | 75 | <p> |
| @@ -83,11 +83,11 @@ | ||
| 83 | 83 | <td align="right">Opened by:</td><td bgcolor="#d0d0d0"> |
| 84 | 84 | $<opened_by> |
| 85 | 85 | </td> |
| 86 | 86 | </pre> |
| 87 | 87 | This will add a row which displays these two fields, in the event the user has |
| 88 | -"edit" capability. | |
| 88 | +"edit" capability. | |
| 89 | 89 | </p> |
| 90 | 90 | </blockquote> |
| 91 | 91 | |
| 92 | 92 | <h2>Modify the 'edit ticket' page</h2><blockquote> |
| 93 | 93 | <p> |
| 94 | 94 |
| --- www/custom_ticket.wiki | |
| +++ www/custom_ticket.wiki | |
| @@ -65,11 +65,11 @@ | |
| 65 | </tr> |
| 66 | <th1>enable_output 1</th1> |
| 67 | </pre> |
| 68 | This bit of code will get rid of the "email" field entry for logged-in users. |
| 69 | Since we know the user's information, we don't have to ask for it. NOTE: it |
| 70 | might be good to automatically scoop up the user's email and put it here. |
| 71 | </p> |
| 72 | </blockquote> |
| 73 | |
| 74 | <h2>Modify the 'view ticket' page</h2><blockquote> |
| 75 | <p> |
| @@ -83,11 +83,11 @@ | |
| 83 | <td align="right">Opened by:</td><td bgcolor="#d0d0d0"> |
| 84 | $<opened_by> |
| 85 | </td> |
| 86 | </pre> |
| 87 | This will add a row which displays these two fields, in the event the user has |
| 88 | "edit" capability. |
| 89 | </p> |
| 90 | </blockquote> |
| 91 | |
| 92 | <h2>Modify the 'edit ticket' page</h2><blockquote> |
| 93 | <p> |
| 94 |
| --- www/custom_ticket.wiki | |
| +++ www/custom_ticket.wiki | |
| @@ -65,11 +65,11 @@ | |
| 65 | </tr> |
| 66 | <th1>enable_output 1</th1> |
| 67 | </pre> |
| 68 | This bit of code will get rid of the "email" field entry for logged-in users. |
| 69 | Since we know the user's information, we don't have to ask for it. NOTE: it |
| 70 | might be good to automatically scoop up the user's email and put it here. |
| 71 | </p> |
| 72 | </blockquote> |
| 73 | |
| 74 | <h2>Modify the 'view ticket' page</h2><blockquote> |
| 75 | <p> |
| @@ -83,11 +83,11 @@ | |
| 83 | <td align="right">Opened by:</td><td bgcolor="#d0d0d0"> |
| 84 | $<opened_by> |
| 85 | </td> |
| 86 | </pre> |
| 87 | This will add a row which displays these two fields, in the event the user has |
| 88 | "edit" capability. |
| 89 | </p> |
| 90 | </blockquote> |
| 91 | |
| 92 | <h2>Modify the 'edit ticket' page</h2><blockquote> |
| 93 | <p> |
| 94 |
+4
| --- www/customskin.md | ||
| +++ www/customskin.md | ||
| @@ -144,10 +144,14 @@ | ||
| 144 | 144 | respository settings and the specific page being generated. |
| 145 | 145 | |
| 146 | 146 | * **project_name** - The project_name variable is filled with the |
| 147 | 147 | name of the project as configured under the Admin/Configuration |
| 148 | 148 | menu. |
| 149 | + | |
| 150 | + * **project_description** - The project_description variable is | |
| 151 | + filled with the description of the project as configured under | |
| 152 | + the Admin/Configuration menu. | |
| 149 | 153 | |
| 150 | 154 | * **title** - The title variable holds the title of the page being |
| 151 | 155 | generated. |
| 152 | 156 | |
| 153 | 157 | The title variable is special in that it is deleted after |
| 154 | 158 |
| --- www/customskin.md | |
| +++ www/customskin.md | |
| @@ -144,10 +144,14 @@ | |
| 144 | respository settings and the specific page being generated. |
| 145 | |
| 146 | * **project_name** - The project_name variable is filled with the |
| 147 | name of the project as configured under the Admin/Configuration |
| 148 | menu. |
| 149 | |
| 150 | * **title** - The title variable holds the title of the page being |
| 151 | generated. |
| 152 | |
| 153 | The title variable is special in that it is deleted after |
| 154 |
| --- www/customskin.md | |
| +++ www/customskin.md | |
| @@ -144,10 +144,14 @@ | |
| 144 | respository settings and the specific page being generated. |
| 145 | |
| 146 | * **project_name** - The project_name variable is filled with the |
| 147 | name of the project as configured under the Admin/Configuration |
| 148 | menu. |
| 149 | |
| 150 | * **project_description** - The project_description variable is |
| 151 | filled with the description of the project as configured under |
| 152 | the Admin/Configuration menu. |
| 153 | |
| 154 | * **title** - The title variable holds the title of the page being |
| 155 | generated. |
| 156 | |
| 157 | The title variable is special in that it is deleted after |
| 158 |
+1
-1
| --- www/delta_encoder_algorithm.wiki | ||
| +++ www/delta_encoder_algorithm.wiki | ||
| @@ -153,11 +153,11 @@ | ||
| 153 | 153 | byte forward. The "base" is left unchanged in that case.</p> |
| 154 | 154 | |
| 155 | 155 | <p>The processing loop stops at one of two conditions: |
| 156 | 156 | <ol> |
| 157 | 157 | <li>The encoder decided to move the window forward, but the end of the |
| 158 | -window reached the end of the "target". | |
| 158 | +window reached the end of the "target". | |
| 159 | 159 | </li> |
| 160 | 160 | <li>After the emission of instructions the new "base" location is |
| 161 | 161 | within NHASH bytes of end of the "target", i.e. there are no more than |
| 162 | 162 | at most NHASH bytes left. |
| 163 | 163 | </li> |
| 164 | 164 |
| --- www/delta_encoder_algorithm.wiki | |
| +++ www/delta_encoder_algorithm.wiki | |
| @@ -153,11 +153,11 @@ | |
| 153 | byte forward. The "base" is left unchanged in that case.</p> |
| 154 | |
| 155 | <p>The processing loop stops at one of two conditions: |
| 156 | <ol> |
| 157 | <li>The encoder decided to move the window forward, but the end of the |
| 158 | window reached the end of the "target". |
| 159 | </li> |
| 160 | <li>After the emission of instructions the new "base" location is |
| 161 | within NHASH bytes of end of the "target", i.e. there are no more than |
| 162 | at most NHASH bytes left. |
| 163 | </li> |
| 164 |
| --- www/delta_encoder_algorithm.wiki | |
| +++ www/delta_encoder_algorithm.wiki | |
| @@ -153,11 +153,11 @@ | |
| 153 | byte forward. The "base" is left unchanged in that case.</p> |
| 154 | |
| 155 | <p>The processing loop stops at one of two conditions: |
| 156 | <ol> |
| 157 | <li>The encoder decided to move the window forward, but the end of the |
| 158 | window reached the end of the "target". |
| 159 | </li> |
| 160 | <li>After the emission of instructions the new "base" location is |
| 161 | within NHASH bytes of end of the "target", i.e. there are no more than |
| 162 | at most NHASH bytes left. |
| 163 | </li> |
| 164 |
+9
-9
| --- www/delta_format.wiki | ||
| +++ www/delta_format.wiki | ||
| @@ -161,49 +161,49 @@ | ||
| 161 | 161 | </table> |
| 162 | 162 | |
| 163 | 163 | <p>The unified diff behind the above delta is</p> |
| 164 | 164 | |
| 165 | 165 | <table border=1><tr><td><pre> |
| 166 | -bluepeak:(761) ~/Projects/Tcl/Fossil/Devel/devel > diff -u ../DELTA/old ../DELTA/new | |
| 166 | +bluepeak:(761) ~/Projects/Tcl/Fossil/Devel/devel > diff -u ../DELTA/old ../DELTA/new | |
| 167 | 167 | --- ../DELTA/old 2007-08-23 21:14:40.000000000 -0700 |
| 168 | 168 | +++ ../DELTA/new 2007-08-23 21:14:33.000000000 -0700 |
| 169 | 169 | @@ -5,7 +5,7 @@ |
| 170 | - | |
| 170 | + | |
| 171 | 171 | * If the server does not have write permission on the database |
| 172 | - file, or on the directory containing the database file (and | |
| 172 | + file, or on the directory containing the database file (and | |
| 173 | 173 | - it is thus unable to update database because it cannot create |
| 174 | 174 | + it is thus unable to update the database because it cannot create |
| 175 | 175 | a rollback journal) then it currently fails silently on a push. |
| 176 | 176 | It needs to return a helpful error. |
| 177 | - | |
| 177 | + | |
| 178 | 178 | @@ -27,8 +27,8 @@ |
| 179 | 179 | * Additional information displayed for the "vinfo" page: |
| 180 | - | |
| 180 | + | |
| 181 | 181 | + All leaves of this version that are not included in the |
| 182 | 182 | - descendant list. With date, user, comment, and hyperlink. |
| 183 | 183 | - Leaves in the descendant table should be marked as such. |
| 184 | 184 | + descendant list. With date, user, comment, and hyperlink. |
| 185 | 185 | + Leaves in the descendant table should be marked as such. |
| 186 | 186 | See the compute_leaves() function to see how to find all |
| 187 | 187 | leaves. |
| 188 | 188 | + Add file diff links to the file change list. |
| 189 | 189 | @@ -37,7 +37,7 @@ |
| 190 | - | |
| 190 | + | |
| 191 | 191 | * The /xfer handler (for push, pull, and clone) does not do |
| 192 | 192 | delta compression. This results in excess bandwidth usage. |
| 193 | 193 | - There are some code in xfer.c that are sketches of ideas on |
| 194 | 194 | + There are some pieces in xfer.c that are sketches of ideas on |
| 195 | 195 | how to do delta compression, but nothing has been implemented. |
| 196 | - | |
| 196 | + | |
| 197 | 197 | * Enhancements to the diff and tkdiff commands in the cli. |
| 198 | 198 | @@ -45,7 +45,7 @@ |
| 199 | 199 | single file. Allow diffs against any two arbitrary versions, |
| 200 | - not just diffs against the current check-out. Allow | |
| 200 | + not just diffs against the current check-out. Allow | |
| 201 | 201 | configuration options to replace tkdiff with some other |
| 202 | 202 | - visual differ of the users choice. |
| 203 | 203 | + visual differ of the users choice. Example: eskil. |
| 204 | - | |
| 204 | + | |
| 205 | 205 | * Ticketing interface (expand this bullet) |
| 206 | 206 | |
| 207 | 207 | </pre></td></tr></table> |
| 208 | 208 | |
| 209 | 209 | |
| 210 | 210 |
| --- www/delta_format.wiki | |
| +++ www/delta_format.wiki | |
| @@ -161,49 +161,49 @@ | |
| 161 | </table> |
| 162 | |
| 163 | <p>The unified diff behind the above delta is</p> |
| 164 | |
| 165 | <table border=1><tr><td><pre> |
| 166 | bluepeak:(761) ~/Projects/Tcl/Fossil/Devel/devel > diff -u ../DELTA/old ../DELTA/new |
| 167 | --- ../DELTA/old 2007-08-23 21:14:40.000000000 -0700 |
| 168 | +++ ../DELTA/new 2007-08-23 21:14:33.000000000 -0700 |
| 169 | @@ -5,7 +5,7 @@ |
| 170 | |
| 171 | * If the server does not have write permission on the database |
| 172 | file, or on the directory containing the database file (and |
| 173 | - it is thus unable to update database because it cannot create |
| 174 | + it is thus unable to update the database because it cannot create |
| 175 | a rollback journal) then it currently fails silently on a push. |
| 176 | It needs to return a helpful error. |
| 177 | |
| 178 | @@ -27,8 +27,8 @@ |
| 179 | * Additional information displayed for the "vinfo" page: |
| 180 | |
| 181 | + All leaves of this version that are not included in the |
| 182 | - descendant list. With date, user, comment, and hyperlink. |
| 183 | - Leaves in the descendant table should be marked as such. |
| 184 | + descendant list. With date, user, comment, and hyperlink. |
| 185 | + Leaves in the descendant table should be marked as such. |
| 186 | See the compute_leaves() function to see how to find all |
| 187 | leaves. |
| 188 | + Add file diff links to the file change list. |
| 189 | @@ -37,7 +37,7 @@ |
| 190 | |
| 191 | * The /xfer handler (for push, pull, and clone) does not do |
| 192 | delta compression. This results in excess bandwidth usage. |
| 193 | - There are some code in xfer.c that are sketches of ideas on |
| 194 | + There are some pieces in xfer.c that are sketches of ideas on |
| 195 | how to do delta compression, but nothing has been implemented. |
| 196 | |
| 197 | * Enhancements to the diff and tkdiff commands in the cli. |
| 198 | @@ -45,7 +45,7 @@ |
| 199 | single file. Allow diffs against any two arbitrary versions, |
| 200 | not just diffs against the current check-out. Allow |
| 201 | configuration options to replace tkdiff with some other |
| 202 | - visual differ of the users choice. |
| 203 | + visual differ of the users choice. Example: eskil. |
| 204 | |
| 205 | * Ticketing interface (expand this bullet) |
| 206 | |
| 207 | </pre></td></tr></table> |
| 208 | |
| 209 | |
| 210 |
| --- www/delta_format.wiki | |
| +++ www/delta_format.wiki | |
| @@ -161,49 +161,49 @@ | |
| 161 | </table> |
| 162 | |
| 163 | <p>The unified diff behind the above delta is</p> |
| 164 | |
| 165 | <table border=1><tr><td><pre> |
| 166 | bluepeak:(761) ~/Projects/Tcl/Fossil/Devel/devel > diff -u ../DELTA/old ../DELTA/new |
| 167 | --- ../DELTA/old 2007-08-23 21:14:40.000000000 -0700 |
| 168 | +++ ../DELTA/new 2007-08-23 21:14:33.000000000 -0700 |
| 169 | @@ -5,7 +5,7 @@ |
| 170 | |
| 171 | * If the server does not have write permission on the database |
| 172 | file, or on the directory containing the database file (and |
| 173 | - it is thus unable to update database because it cannot create |
| 174 | + it is thus unable to update the database because it cannot create |
| 175 | a rollback journal) then it currently fails silently on a push. |
| 176 | It needs to return a helpful error. |
| 177 | |
| 178 | @@ -27,8 +27,8 @@ |
| 179 | * Additional information displayed for the "vinfo" page: |
| 180 | |
| 181 | + All leaves of this version that are not included in the |
| 182 | - descendant list. With date, user, comment, and hyperlink. |
| 183 | - Leaves in the descendant table should be marked as such. |
| 184 | + descendant list. With date, user, comment, and hyperlink. |
| 185 | + Leaves in the descendant table should be marked as such. |
| 186 | See the compute_leaves() function to see how to find all |
| 187 | leaves. |
| 188 | + Add file diff links to the file change list. |
| 189 | @@ -37,7 +37,7 @@ |
| 190 | |
| 191 | * The /xfer handler (for push, pull, and clone) does not do |
| 192 | delta compression. This results in excess bandwidth usage. |
| 193 | - There are some code in xfer.c that are sketches of ideas on |
| 194 | + There are some pieces in xfer.c that are sketches of ideas on |
| 195 | how to do delta compression, but nothing has been implemented. |
| 196 | |
| 197 | * Enhancements to the diff and tkdiff commands in the cli. |
| 198 | @@ -45,7 +45,7 @@ |
| 199 | single file. Allow diffs against any two arbitrary versions, |
| 200 | not just diffs against the current check-out. Allow |
| 201 | configuration options to replace tkdiff with some other |
| 202 | - visual differ of the users choice. |
| 203 | + visual differ of the users choice. Example: eskil. |
| 204 | |
| 205 | * Ticketing interface (expand this bullet) |
| 206 | |
| 207 | </pre></td></tr></table> |
| 208 | |
| 209 | |
| 210 |
+9
-9
| --- www/embeddeddoc.wiki | ||
| +++ www/embeddeddoc.wiki | ||
| @@ -42,13 +42,13 @@ | ||
| 42 | 42 | <b>http://www.hwaci.com/cgi-bin/fossil</b>. |
| 43 | 43 | If you launch the web server using the "<b>fossil server</b>" command line, |
| 44 | 44 | then the <i><baseurl></i> is usually |
| 45 | 45 | <b>http://localhost:8080/</b>. |
| 46 | 46 | |
| 47 | -The <i><version></i> is any unique prefix of the check-in ID for | |
| 47 | +The <i><version></i> is any unique prefix of the check-in ID for | |
| 48 | 48 | the check-in containing the documentation you want to access. |
| 49 | -Or <i><version></i> can be the name of a | |
| 49 | +Or <i><version></i> can be the name of a | |
| 50 | 50 | [./branching.wiki | branch] in order to show |
| 51 | 51 | the documentation for the latest version of that branch. |
| 52 | 52 | Or <i><version></i> can be one of the keywords "<b>tip</b>" or |
| 53 | 53 | "<b>ckout</b>". The "<b>tip</b>" keyword means to use the most recent |
| 54 | 54 | check-in. This is useful if you want to see the very latest |
| @@ -62,30 +62,30 @@ | ||
| 62 | 62 | |
| 63 | 63 | Finally, the <i><filename></i> element of the URL is the |
| 64 | 64 | pathname of the documentation file relative to the root of the source |
| 65 | 65 | tree. |
| 66 | 66 | |
| 67 | -The mimetype (and thus the rendering) of documentation files is | |
| 68 | -determined by the file suffix. Fossil currently understands | |
| 67 | +The mimetype (and thus the rendering) of documentation files is | |
| 68 | +determined by the file suffix. Fossil currently understands | |
| 69 | 69 | [/mimetype_list|many different file suffixes], |
| 70 | 70 | including all the popular ones such as ".css", ".gif", ".htm", |
| 71 | 71 | ".html", ".jpg", ".jpeg", ".png", and ".txt". |
| 72 | 72 | |
| 73 | -Documentation files whose names end in ".wiki" use the | |
| 73 | +Documentation files whose names end in ".wiki" use the | |
| 74 | 74 | [/wiki_rules | fossil wiki markup] - |
| 75 | 75 | a safe subset of HTML together with some wiki rules for paragraph |
| 76 | -breaks, lists, and hyperlinks. | |
| 76 | +breaks, lists, and hyperlinks. | |
| 77 | 77 | Documentation files ending in ".md" or ".markdown" use the |
| 78 | 78 | [/md_rules | Markdown markup langauge]. |
| 79 | 79 | Documentation files ending in ".txt" are plain text. |
| 80 | 80 | Wiki, markdown, and plain text documentation files |
| 81 | 81 | are rendered with the standard fossil header and footer added. |
| 82 | 82 | Most other mimetypes are delivered directly to the requesting |
| 83 | 83 | web browser without interpretation, additions, or changes. |
| 84 | 84 | |
| 85 | 85 | Files with the mimetype "text/html" (the .html or .htm suffix) are |
| 86 | -usually rendered directly to the browser without interpretation. | |
| 86 | +usually rendered directly to the browser without interpretation. | |
| 87 | 87 | However, if the file begins with a <div> element like this: |
| 88 | 88 | |
| 89 | 89 | <b><div class='fossil-doc' data-title='<i>Title Text</i>'></b> |
| 90 | 90 | |
| 91 | 91 | Then the standard Fossil header and footer are added to the document |
| @@ -117,11 +117,11 @@ | ||
| 117 | 117 | <blockquote><pre> |
| 118 | 118 | #!/usr/bin/fossil |
| 119 | 119 | repository: /fossil/fossil.fossil |
| 120 | 120 | </pre></blockquote> |
| 121 | 121 | |
| 122 | -This is one of four ways to set up a | |
| 122 | +This is one of four ways to set up a | |
| 123 | 123 | <a href="./server.wiki">fossil web server</a>. |
| 124 | 124 | |
| 125 | 125 | The "<b>/trunk/</b>" part of the URL tells fossil to use |
| 126 | 126 | the documentation files from the most recent trunk check-in. |
| 127 | 127 | If you wanted to see an historical version of this document, |
| @@ -138,11 +138,11 @@ | ||
| 138 | 138 | <li> <i>YYYY-MM-DD</i> |
| 139 | 139 | <li> <i>YYYY-MM-DD</i><b>T</b><i>HH:MM</i> |
| 140 | 140 | <li> <i>YYYY-MM-DD</i><b>T</b><i>HH:MM:SS</i> |
| 141 | 141 | </ul> |
| 142 | 142 | |
| 143 | -When the symbolic name is a date and time, fossil shows the version | |
| 143 | +When the symbolic name is a date and time, fossil shows the version | |
| 144 | 144 | of the document that was most recently checked in as of the date |
| 145 | 145 | and time specified. So, for example, to see what the fossil website |
| 146 | 146 | looked like at the beginning of 2010, enter: |
| 147 | 147 | |
| 148 | 148 | <blockquote> |
| 149 | 149 |
| --- www/embeddeddoc.wiki | |
| +++ www/embeddeddoc.wiki | |
| @@ -42,13 +42,13 @@ | |
| 42 | <b>http://www.hwaci.com/cgi-bin/fossil</b>. |
| 43 | If you launch the web server using the "<b>fossil server</b>" command line, |
| 44 | then the <i><baseurl></i> is usually |
| 45 | <b>http://localhost:8080/</b>. |
| 46 | |
| 47 | The <i><version></i> is any unique prefix of the check-in ID for |
| 48 | the check-in containing the documentation you want to access. |
| 49 | Or <i><version></i> can be the name of a |
| 50 | [./branching.wiki | branch] in order to show |
| 51 | the documentation for the latest version of that branch. |
| 52 | Or <i><version></i> can be one of the keywords "<b>tip</b>" or |
| 53 | "<b>ckout</b>". The "<b>tip</b>" keyword means to use the most recent |
| 54 | check-in. This is useful if you want to see the very latest |
| @@ -62,30 +62,30 @@ | |
| 62 | |
| 63 | Finally, the <i><filename></i> element of the URL is the |
| 64 | pathname of the documentation file relative to the root of the source |
| 65 | tree. |
| 66 | |
| 67 | The mimetype (and thus the rendering) of documentation files is |
| 68 | determined by the file suffix. Fossil currently understands |
| 69 | [/mimetype_list|many different file suffixes], |
| 70 | including all the popular ones such as ".css", ".gif", ".htm", |
| 71 | ".html", ".jpg", ".jpeg", ".png", and ".txt". |
| 72 | |
| 73 | Documentation files whose names end in ".wiki" use the |
| 74 | [/wiki_rules | fossil wiki markup] - |
| 75 | a safe subset of HTML together with some wiki rules for paragraph |
| 76 | breaks, lists, and hyperlinks. |
| 77 | Documentation files ending in ".md" or ".markdown" use the |
| 78 | [/md_rules | Markdown markup langauge]. |
| 79 | Documentation files ending in ".txt" are plain text. |
| 80 | Wiki, markdown, and plain text documentation files |
| 81 | are rendered with the standard fossil header and footer added. |
| 82 | Most other mimetypes are delivered directly to the requesting |
| 83 | web browser without interpretation, additions, or changes. |
| 84 | |
| 85 | Files with the mimetype "text/html" (the .html or .htm suffix) are |
| 86 | usually rendered directly to the browser without interpretation. |
| 87 | However, if the file begins with a <div> element like this: |
| 88 | |
| 89 | <b><div class='fossil-doc' data-title='<i>Title Text</i>'></b> |
| 90 | |
| 91 | Then the standard Fossil header and footer are added to the document |
| @@ -117,11 +117,11 @@ | |
| 117 | <blockquote><pre> |
| 118 | #!/usr/bin/fossil |
| 119 | repository: /fossil/fossil.fossil |
| 120 | </pre></blockquote> |
| 121 | |
| 122 | This is one of four ways to set up a |
| 123 | <a href="./server.wiki">fossil web server</a>. |
| 124 | |
| 125 | The "<b>/trunk/</b>" part of the URL tells fossil to use |
| 126 | the documentation files from the most recent trunk check-in. |
| 127 | If you wanted to see an historical version of this document, |
| @@ -138,11 +138,11 @@ | |
| 138 | <li> <i>YYYY-MM-DD</i> |
| 139 | <li> <i>YYYY-MM-DD</i><b>T</b><i>HH:MM</i> |
| 140 | <li> <i>YYYY-MM-DD</i><b>T</b><i>HH:MM:SS</i> |
| 141 | </ul> |
| 142 | |
| 143 | When the symbolic name is a date and time, fossil shows the version |
| 144 | of the document that was most recently checked in as of the date |
| 145 | and time specified. So, for example, to see what the fossil website |
| 146 | looked like at the beginning of 2010, enter: |
| 147 | |
| 148 | <blockquote> |
| 149 |
| --- www/embeddeddoc.wiki | |
| +++ www/embeddeddoc.wiki | |
| @@ -42,13 +42,13 @@ | |
| 42 | <b>http://www.hwaci.com/cgi-bin/fossil</b>. |
| 43 | If you launch the web server using the "<b>fossil server</b>" command line, |
| 44 | then the <i><baseurl></i> is usually |
| 45 | <b>http://localhost:8080/</b>. |
| 46 | |
| 47 | The <i><version></i> is any unique prefix of the check-in ID for |
| 48 | the check-in containing the documentation you want to access. |
| 49 | Or <i><version></i> can be the name of a |
| 50 | [./branching.wiki | branch] in order to show |
| 51 | the documentation for the latest version of that branch. |
| 52 | Or <i><version></i> can be one of the keywords "<b>tip</b>" or |
| 53 | "<b>ckout</b>". The "<b>tip</b>" keyword means to use the most recent |
| 54 | check-in. This is useful if you want to see the very latest |
| @@ -62,30 +62,30 @@ | |
| 62 | |
| 63 | Finally, the <i><filename></i> element of the URL is the |
| 64 | pathname of the documentation file relative to the root of the source |
| 65 | tree. |
| 66 | |
| 67 | The mimetype (and thus the rendering) of documentation files is |
| 68 | determined by the file suffix. Fossil currently understands |
| 69 | [/mimetype_list|many different file suffixes], |
| 70 | including all the popular ones such as ".css", ".gif", ".htm", |
| 71 | ".html", ".jpg", ".jpeg", ".png", and ".txt". |
| 72 | |
| 73 | Documentation files whose names end in ".wiki" use the |
| 74 | [/wiki_rules | fossil wiki markup] - |
| 75 | a safe subset of HTML together with some wiki rules for paragraph |
| 76 | breaks, lists, and hyperlinks. |
| 77 | Documentation files ending in ".md" or ".markdown" use the |
| 78 | [/md_rules | Markdown markup langauge]. |
| 79 | Documentation files ending in ".txt" are plain text. |
| 80 | Wiki, markdown, and plain text documentation files |
| 81 | are rendered with the standard fossil header and footer added. |
| 82 | Most other mimetypes are delivered directly to the requesting |
| 83 | web browser without interpretation, additions, or changes. |
| 84 | |
| 85 | Files with the mimetype "text/html" (the .html or .htm suffix) are |
| 86 | usually rendered directly to the browser without interpretation. |
| 87 | However, if the file begins with a <div> element like this: |
| 88 | |
| 89 | <b><div class='fossil-doc' data-title='<i>Title Text</i>'></b> |
| 90 | |
| 91 | Then the standard Fossil header and footer are added to the document |
| @@ -117,11 +117,11 @@ | |
| 117 | <blockquote><pre> |
| 118 | #!/usr/bin/fossil |
| 119 | repository: /fossil/fossil.fossil |
| 120 | </pre></blockquote> |
| 121 | |
| 122 | This is one of four ways to set up a |
| 123 | <a href="./server.wiki">fossil web server</a>. |
| 124 | |
| 125 | The "<b>/trunk/</b>" part of the URL tells fossil to use |
| 126 | the documentation files from the most recent trunk check-in. |
| 127 | If you wanted to see an historical version of this document, |
| @@ -138,11 +138,11 @@ | |
| 138 | <li> <i>YYYY-MM-DD</i> |
| 139 | <li> <i>YYYY-MM-DD</i><b>T</b><i>HH:MM</i> |
| 140 | <li> <i>YYYY-MM-DD</i><b>T</b><i>HH:MM:SS</i> |
| 141 | </ul> |
| 142 | |
| 143 | When the symbolic name is a date and time, fossil shows the version |
| 144 | of the document that was most recently checked in as of the date |
| 145 | and time specified. So, for example, to see what the fossil website |
| 146 | looked like at the beginning of 2010, enter: |
| 147 | |
| 148 | <blockquote> |
| 149 |
+1
-1
| --- www/encryptedrepos.wiki | ||
| +++ www/encryptedrepos.wiki | ||
| @@ -3,11 +3,11 @@ | ||
| 3 | 3 | Fossil can be compiled so that it works with encrypted repositories using |
| 4 | 4 | the [https://www.sqlite.org/see/doc/trunk/www/readme.wiki|SQLite Encryption Extension]. |
| 5 | 5 | This technical note explains the process. |
| 6 | 6 | </blockquote> |
| 7 | 7 | <h2>Building An Encryption-Enabled Fossil</h2><blockquote> |
| 8 | -The SQLite Encryption Extension (SEE) is proprietary software and requires | |
| 8 | +The SQLite Encryption Extension (SEE) is proprietary software and requires | |
| 9 | 9 | [http://www.hwaci.com/cgi-bin/see-step1|purchasing a license]. |
| 10 | 10 | <p> |
| 11 | 11 | Assuming you have an SEE license, the first step of compiling Fossil to |
| 12 | 12 | use SEE is to create an SEE-enabled version of the SQLite database source code. |
| 13 | 13 | This alternative SQLite database source file should be called "sqlite3-see.c" |
| 14 | 14 |
| --- www/encryptedrepos.wiki | |
| +++ www/encryptedrepos.wiki | |
| @@ -3,11 +3,11 @@ | |
| 3 | Fossil can be compiled so that it works with encrypted repositories using |
| 4 | the [https://www.sqlite.org/see/doc/trunk/www/readme.wiki|SQLite Encryption Extension]. |
| 5 | This technical note explains the process. |
| 6 | </blockquote> |
| 7 | <h2>Building An Encryption-Enabled Fossil</h2><blockquote> |
| 8 | The SQLite Encryption Extension (SEE) is proprietary software and requires |
| 9 | [http://www.hwaci.com/cgi-bin/see-step1|purchasing a license]. |
| 10 | <p> |
| 11 | Assuming you have an SEE license, the first step of compiling Fossil to |
| 12 | use SEE is to create an SEE-enabled version of the SQLite database source code. |
| 13 | This alternative SQLite database source file should be called "sqlite3-see.c" |
| 14 |
| --- www/encryptedrepos.wiki | |
| +++ www/encryptedrepos.wiki | |
| @@ -3,11 +3,11 @@ | |
| 3 | Fossil can be compiled so that it works with encrypted repositories using |
| 4 | the [https://www.sqlite.org/see/doc/trunk/www/readme.wiki|SQLite Encryption Extension]. |
| 5 | This technical note explains the process. |
| 6 | </blockquote> |
| 7 | <h2>Building An Encryption-Enabled Fossil</h2><blockquote> |
| 8 | The SQLite Encryption Extension (SEE) is proprietary software and requires |
| 9 | [http://www.hwaci.com/cgi-bin/see-step1|purchasing a license]. |
| 10 | <p> |
| 11 | Assuming you have an SEE license, the first step of compiling Fossil to |
| 12 | use SEE is to create an SEE-enabled version of the SQLite database source code. |
| 13 | This alternative SQLite database source file should be called "sqlite3-see.c" |
| 14 |
+5
-1
| --- www/env-opts.md | ||
| +++ www/env-opts.md | ||
| @@ -88,11 +88,15 @@ | ||
| 88 | 88 | `--sqlstats`: (Sets `g.fSqlStats`.) Print a number of performance |
| 89 | 89 | statistics about each SQLite database used when it is closed. |
| 90 | 90 | |
| 91 | 91 | `--sshtrace`: (Sets `g.fSshTrace`.) |
| 92 | 92 | |
| 93 | -`--ssl-identity SSLIDENTITY`: | |
| 93 | +`--ssl-identity`: The fully qualified name of the file containing the client | |
| 94 | +certificate and private key to use, in PEM format. It can be created by | |
| 95 | +concatenating the client certificate and private key files. This identity will | |
| 96 | +be presented to SSL servers to authenticate the client, in addition to the | |
| 97 | +normal password authentication. | |
| 94 | 98 | |
| 95 | 99 | `--systemtrace`: (Sets `g.fSystemTrace`.) Trace all commands launched |
| 96 | 100 | as sub processes. |
| 97 | 101 | |
| 98 | 102 | `--user LOGIN`: (Sets `g.zLogin`) Also `-U LOGIN`. Set the user name |
| 99 | 103 |
| --- www/env-opts.md | |
| +++ www/env-opts.md | |
| @@ -88,11 +88,15 @@ | |
| 88 | `--sqlstats`: (Sets `g.fSqlStats`.) Print a number of performance |
| 89 | statistics about each SQLite database used when it is closed. |
| 90 | |
| 91 | `--sshtrace`: (Sets `g.fSshTrace`.) |
| 92 | |
| 93 | `--ssl-identity SSLIDENTITY`: |
| 94 | |
| 95 | `--systemtrace`: (Sets `g.fSystemTrace`.) Trace all commands launched |
| 96 | as sub processes. |
| 97 | |
| 98 | `--user LOGIN`: (Sets `g.zLogin`) Also `-U LOGIN`. Set the user name |
| 99 |
| --- www/env-opts.md | |
| +++ www/env-opts.md | |
| @@ -88,11 +88,15 @@ | |
| 88 | `--sqlstats`: (Sets `g.fSqlStats`.) Print a number of performance |
| 89 | statistics about each SQLite database used when it is closed. |
| 90 | |
| 91 | `--sshtrace`: (Sets `g.fSshTrace`.) |
| 92 | |
| 93 | `--ssl-identity`: The fully qualified name of the file containing the client |
| 94 | certificate and private key to use, in PEM format. It can be created by |
| 95 | concatenating the client certificate and private key files. This identity will |
| 96 | be presented to SSL servers to authenticate the client, in addition to the |
| 97 | normal password authentication. |
| 98 | |
| 99 | `--systemtrace`: (Sets `g.fSystemTrace`.) Trace all commands launched |
| 100 | as sub processes. |
| 101 | |
| 102 | `--user LOGIN`: (Sets `g.zLogin`) Also `-U LOGIN`. Set the user name |
| 103 |
+3
-3
| --- www/event.wiki | ||
| +++ www/event.wiki | ||
| @@ -23,11 +23,11 @@ | ||
| 23 | 23 | can be something simple like "Version 1.2.3" perhaps with a bright |
| 24 | 24 | color background to draw attention to the entry and the wiki content |
| 25 | 25 | can contain release notes, for example. |
| 26 | 26 | |
| 27 | 27 | * <b>Blog Entries</b>. Blog entries from developers describing the current |
| 28 | - state of a project, or rational for various design decisions, or | |
| 28 | + state of a project, or rational for various design decisions, or | |
| 29 | 29 | roadmaps for future development, can be entered as technotes. |
| 30 | 30 | |
| 31 | 31 | * <b>Process Checkpoints</b>. For projects that have a formal process, |
| 32 | 32 | technotes can be used to record the completion or the initiation of |
| 33 | 33 | various process steps. For example, a technote can be used to record |
| @@ -49,11 +49,11 @@ | ||
| 49 | 49 | stay better organized and provide a better historical record of the |
| 50 | 50 | development progress. |
| 51 | 51 | |
| 52 | 52 | <h2>Viewing Technotes</h2> |
| 53 | 53 | |
| 54 | -Because technotes are considered a special kind of wiki, | |
| 54 | +Because technotes are considered a special kind of wiki, | |
| 55 | 55 | users must have permission to read wiki in order read technotes. |
| 56 | 56 | Enable the "j" permission under the /Setup/Users menu in order |
| 57 | 57 | to give specific users or user classes the ability to view wiki |
| 58 | 58 | and technotes. |
| 59 | 59 | |
| @@ -64,12 +64,12 @@ | ||
| 64 | 64 | |
| 65 | 65 | There is a hyperlink under the /wikihelp menu that can be used to create |
| 66 | 66 | new technotes. And there is a submenu hyperlink on technote displays for |
| 67 | 67 | editing existing technotes. |
| 68 | 68 | |
| 69 | -Users must have check-in privileges (permission "i") in order to | |
| 69 | +Users must have check-in privileges (permission "i") in order to | |
| 70 | 70 | create or edit technotes. In addition, users must have create-wiki |
| 71 | 71 | privilege (permission "f") to create new technotes and edit-wiki |
| 72 | 72 | privilege (permission "k") in order to edit existing technotes. |
| 73 | 73 | |
| 74 | 74 | Technote content may be formatted as [/wiki_rules | Fossil wiki], |
| 75 | 75 | [/md_rules | Markdown], or a plain text. |
| 76 | 76 |
| --- www/event.wiki | |
| +++ www/event.wiki | |
| @@ -23,11 +23,11 @@ | |
| 23 | can be something simple like "Version 1.2.3" perhaps with a bright |
| 24 | color background to draw attention to the entry and the wiki content |
| 25 | can contain release notes, for example. |
| 26 | |
| 27 | * <b>Blog Entries</b>. Blog entries from developers describing the current |
| 28 | state of a project, or rational for various design decisions, or |
| 29 | roadmaps for future development, can be entered as technotes. |
| 30 | |
| 31 | * <b>Process Checkpoints</b>. For projects that have a formal process, |
| 32 | technotes can be used to record the completion or the initiation of |
| 33 | various process steps. For example, a technote can be used to record |
| @@ -49,11 +49,11 @@ | |
| 49 | stay better organized and provide a better historical record of the |
| 50 | development progress. |
| 51 | |
| 52 | <h2>Viewing Technotes</h2> |
| 53 | |
| 54 | Because technotes are considered a special kind of wiki, |
| 55 | users must have permission to read wiki in order read technotes. |
| 56 | Enable the "j" permission under the /Setup/Users menu in order |
| 57 | to give specific users or user classes the ability to view wiki |
| 58 | and technotes. |
| 59 | |
| @@ -64,12 +64,12 @@ | |
| 64 | |
| 65 | There is a hyperlink under the /wikihelp menu that can be used to create |
| 66 | new technotes. And there is a submenu hyperlink on technote displays for |
| 67 | editing existing technotes. |
| 68 | |
| 69 | Users must have check-in privileges (permission "i") in order to |
| 70 | create or edit technotes. In addition, users must have create-wiki |
| 71 | privilege (permission "f") to create new technotes and edit-wiki |
| 72 | privilege (permission "k") in order to edit existing technotes. |
| 73 | |
| 74 | Technote content may be formatted as [/wiki_rules | Fossil wiki], |
| 75 | [/md_rules | Markdown], or a plain text. |
| 76 |
| --- www/event.wiki | |
| +++ www/event.wiki | |
| @@ -23,11 +23,11 @@ | |
| 23 | can be something simple like "Version 1.2.3" perhaps with a bright |
| 24 | color background to draw attention to the entry and the wiki content |
| 25 | can contain release notes, for example. |
| 26 | |
| 27 | * <b>Blog Entries</b>. Blog entries from developers describing the current |
| 28 | state of a project, or rational for various design decisions, or |
| 29 | roadmaps for future development, can be entered as technotes. |
| 30 | |
| 31 | * <b>Process Checkpoints</b>. For projects that have a formal process, |
| 32 | technotes can be used to record the completion or the initiation of |
| 33 | various process steps. For example, a technote can be used to record |
| @@ -49,11 +49,11 @@ | |
| 49 | stay better organized and provide a better historical record of the |
| 50 | development progress. |
| 51 | |
| 52 | <h2>Viewing Technotes</h2> |
| 53 | |
| 54 | Because technotes are considered a special kind of wiki, |
| 55 | users must have permission to read wiki in order read technotes. |
| 56 | Enable the "j" permission under the /Setup/Users menu in order |
| 57 | to give specific users or user classes the ability to view wiki |
| 58 | and technotes. |
| 59 | |
| @@ -64,12 +64,12 @@ | |
| 64 | |
| 65 | There is a hyperlink under the /wikihelp menu that can be used to create |
| 66 | new technotes. And there is a submenu hyperlink on technote displays for |
| 67 | editing existing technotes. |
| 68 | |
| 69 | Users must have check-in privileges (permission "i") in order to |
| 70 | create or edit technotes. In addition, users must have create-wiki |
| 71 | privilege (permission "f") to create new technotes and edit-wiki |
| 72 | privilege (permission "k") in order to edit existing technotes. |
| 73 | |
| 74 | Technote content may be formatted as [/wiki_rules | Fossil wiki], |
| 75 | [/md_rules | Markdown], or a plain text. |
| 76 |
+5
-5
| --- www/faq.wiki | ||
| +++ www/faq.wiki | ||
| @@ -62,12 +62,12 @@ | ||
| 62 | 62 | If you already have a fork in your check-in tree and you want to convert |
| 63 | 63 | that fork to a branch, you can do this from the web interface. |
| 64 | 64 | First locate the check-in that you want to be |
| 65 | 65 | the initial check-in of your branch on the timeline and click on its |
| 66 | 66 | link so that you are on the <b>ci</b> page. Then find the "<b>edit</b>" |
| 67 | -link (near the "Commands:" label) and click on that. On the | |
| 68 | -"Edit Check-in" page, check the box beside "Branching:" and fill in | |
| 67 | +link (near the "Commands:" label) and click on that. On the | |
| 68 | +"Edit Check-in" page, check the box beside "Branching:" and fill in | |
| 69 | 69 | the name of your new branch to the right and press the "Apply Changes" |
| 70 | 70 | button.</blockquote></li> |
| 71 | 71 | |
| 72 | 72 | <a name="q4"></a> |
| 73 | 73 | <p><b>(4) How do I tag a check-in?</b></p> |
| @@ -89,11 +89,11 @@ | ||
| 89 | 89 | |
| 90 | 90 | The CHECK-IN in the previous line can be any |
| 91 | 91 | [./checkin_names.wiki | valid check-in name format]. |
| 92 | 92 | |
| 93 | 93 | You can also add (and remove) tags from a check-in using the |
| 94 | -[./webui.wiki | web interface]. First locate the check-in that you | |
| 94 | +[./webui.wiki | web interface]. First locate the check-in that you | |
| 95 | 95 | what to tag on the timeline, then click on the link to go the detailed |
| 96 | 96 | information page for that check-in. Then find the "<b>edit</b>" |
| 97 | 97 | link (near the "Commands:" label) and click on that. There are |
| 98 | 98 | controls on the edit page that allow new tags to be added and existing |
| 99 | 99 | tags to be removed.</blockquote></li> |
| @@ -100,13 +100,13 @@ | ||
| 100 | 100 | |
| 101 | 101 | <a name="q5"></a> |
| 102 | 102 | <p><b>(5) How do I create a private branch that won't get pushed back to the |
| 103 | 103 | main repository.</b></p> |
| 104 | 104 | |
| 105 | -<blockquote>Use the <b>--private</b> command-line option on the | |
| 105 | +<blockquote>Use the <b>--private</b> command-line option on the | |
| 106 | 106 | <b>commit</b> command. The result will be a check-in which exists on |
| 107 | -your local repository only and is never pushed to other repositories. | |
| 107 | +your local repository only and is never pushed to other repositories. | |
| 108 | 108 | All descendants of a private check-in are also private. |
| 109 | 109 | |
| 110 | 110 | Unless you specify something different using the <b>--branch</b> and/or |
| 111 | 111 | <b>--bgcolor</b> options, the new private check-in will be put on a branch |
| 112 | 112 | named "private" with an orange background color. |
| 113 | 113 |
| --- www/faq.wiki | |
| +++ www/faq.wiki | |
| @@ -62,12 +62,12 @@ | |
| 62 | If you already have a fork in your check-in tree and you want to convert |
| 63 | that fork to a branch, you can do this from the web interface. |
| 64 | First locate the check-in that you want to be |
| 65 | the initial check-in of your branch on the timeline and click on its |
| 66 | link so that you are on the <b>ci</b> page. Then find the "<b>edit</b>" |
| 67 | link (near the "Commands:" label) and click on that. On the |
| 68 | "Edit Check-in" page, check the box beside "Branching:" and fill in |
| 69 | the name of your new branch to the right and press the "Apply Changes" |
| 70 | button.</blockquote></li> |
| 71 | |
| 72 | <a name="q4"></a> |
| 73 | <p><b>(4) How do I tag a check-in?</b></p> |
| @@ -89,11 +89,11 @@ | |
| 89 | |
| 90 | The CHECK-IN in the previous line can be any |
| 91 | [./checkin_names.wiki | valid check-in name format]. |
| 92 | |
| 93 | You can also add (and remove) tags from a check-in using the |
| 94 | [./webui.wiki | web interface]. First locate the check-in that you |
| 95 | what to tag on the timeline, then click on the link to go the detailed |
| 96 | information page for that check-in. Then find the "<b>edit</b>" |
| 97 | link (near the "Commands:" label) and click on that. There are |
| 98 | controls on the edit page that allow new tags to be added and existing |
| 99 | tags to be removed.</blockquote></li> |
| @@ -100,13 +100,13 @@ | |
| 100 | |
| 101 | <a name="q5"></a> |
| 102 | <p><b>(5) How do I create a private branch that won't get pushed back to the |
| 103 | main repository.</b></p> |
| 104 | |
| 105 | <blockquote>Use the <b>--private</b> command-line option on the |
| 106 | <b>commit</b> command. The result will be a check-in which exists on |
| 107 | your local repository only and is never pushed to other repositories. |
| 108 | All descendants of a private check-in are also private. |
| 109 | |
| 110 | Unless you specify something different using the <b>--branch</b> and/or |
| 111 | <b>--bgcolor</b> options, the new private check-in will be put on a branch |
| 112 | named "private" with an orange background color. |
| 113 |
| --- www/faq.wiki | |
| +++ www/faq.wiki | |
| @@ -62,12 +62,12 @@ | |
| 62 | If you already have a fork in your check-in tree and you want to convert |
| 63 | that fork to a branch, you can do this from the web interface. |
| 64 | First locate the check-in that you want to be |
| 65 | the initial check-in of your branch on the timeline and click on its |
| 66 | link so that you are on the <b>ci</b> page. Then find the "<b>edit</b>" |
| 67 | link (near the "Commands:" label) and click on that. On the |
| 68 | "Edit Check-in" page, check the box beside "Branching:" and fill in |
| 69 | the name of your new branch to the right and press the "Apply Changes" |
| 70 | button.</blockquote></li> |
| 71 | |
| 72 | <a name="q4"></a> |
| 73 | <p><b>(4) How do I tag a check-in?</b></p> |
| @@ -89,11 +89,11 @@ | |
| 89 | |
| 90 | The CHECK-IN in the previous line can be any |
| 91 | [./checkin_names.wiki | valid check-in name format]. |
| 92 | |
| 93 | You can also add (and remove) tags from a check-in using the |
| 94 | [./webui.wiki | web interface]. First locate the check-in that you |
| 95 | what to tag on the timeline, then click on the link to go the detailed |
| 96 | information page for that check-in. Then find the "<b>edit</b>" |
| 97 | link (near the "Commands:" label) and click on that. There are |
| 98 | controls on the edit page that allow new tags to be added and existing |
| 99 | tags to be removed.</blockquote></li> |
| @@ -100,13 +100,13 @@ | |
| 100 | |
| 101 | <a name="q5"></a> |
| 102 | <p><b>(5) How do I create a private branch that won't get pushed back to the |
| 103 | main repository.</b></p> |
| 104 | |
| 105 | <blockquote>Use the <b>--private</b> command-line option on the |
| 106 | <b>commit</b> command. The result will be a check-in which exists on |
| 107 | your local repository only and is never pushed to other repositories. |
| 108 | All descendants of a private check-in are also private. |
| 109 | |
| 110 | Unless you specify something different using the <b>--branch</b> and/or |
| 111 | <b>--bgcolor</b> options, the new private check-in will be put on a branch |
| 112 | named "private" with an orange background color. |
| 113 |
+26
-26
| --- www/fileformat.wiki | ||
| +++ www/fileformat.wiki | ||
| @@ -2,11 +2,11 @@ | ||
| 2 | 2 | <h1 align="center"> |
| 3 | 3 | Fossil File Formats |
| 4 | 4 | </h1> |
| 5 | 5 | |
| 6 | 6 | The global state of a fossil repository is kept simple so that it can |
| 7 | -endure in useful form for decades or centuries. | |
| 7 | +endure in useful form for decades or centuries. | |
| 8 | 8 | A fossil repository is intended to be readable, |
| 9 | 9 | searchable, and extensible by people not yet born. |
| 10 | 10 | |
| 11 | 11 | The global state of a fossil repository is an unordered |
| 12 | 12 | set of <i>artifacts</i>. |
| @@ -14,11 +14,11 @@ | ||
| 14 | 14 | part of a trouble ticket, or one of several special control artifacts |
| 15 | 15 | used to show the relationships between other artifacts within the |
| 16 | 16 | project. Each artifact is normally represented on disk as a separate |
| 17 | 17 | file. Artifacts can be text or binary. |
| 18 | 18 | |
| 19 | -In addition to the global state, | |
| 19 | +In addition to the global state, | |
| 20 | 20 | each fossil repository also contains local state. |
| 21 | 21 | The local state consists of web-page formatting |
| 22 | 22 | preferences, authorized users, ticket display and reporting formats, |
| 23 | 23 | and so forth. The global state is shared in common among all |
| 24 | 24 | repositories for the same project, whereas the local state is often |
| @@ -30,11 +30,11 @@ | ||
| 30 | 30 | mentioned here in order to distinguish it from global state. |
| 31 | 31 | |
| 32 | 32 | Each artifact in the repository is named by its SHA1 hash. |
| 33 | 33 | No prefixes or meta information is added to an artifact before |
| 34 | 34 | its hash is computed. The name of an artifact in the repository |
| 35 | -is exactly the same SHA1 hash that is computed by sha1sum | |
| 35 | +is exactly the same SHA1 hash that is computed by sha1sum | |
| 36 | 36 | on the file as it exists in your source tree.</p> |
| 37 | 37 | |
| 38 | 38 | Some artifacts have a particular format which gives them special |
| 39 | 39 | meaning to fossil. Fossil recognizes: |
| 40 | 40 | |
| @@ -84,11 +84,11 @@ | ||
| 84 | 84 | Each card begins with a single |
| 85 | 85 | character "card type". Zero or more arguments may follow |
| 86 | 86 | the card type. All arguments are separated from each other |
| 87 | 87 | and from the card-type character by a single space |
| 88 | 88 | character. There is no surplus white space between arguments |
| 89 | -and no leading or trailing whitespace except for the newline | |
| 89 | +and no leading or trailing whitespace except for the newline | |
| 90 | 90 | character that acts as the card separator. |
| 91 | 91 | |
| 92 | 92 | All cards of the manifest occur in strict sorted lexicographical order. |
| 93 | 93 | No card may be duplicated. |
| 94 | 94 | The entire manifest may be PGP clear-signed, but otherwise it |
| @@ -114,18 +114,18 @@ | ||
| 114 | 114 | another manifest that serves as the "baseline" for this manifest. A |
| 115 | 115 | manifest that has a B-card is called a delta-manifest and a manifest |
| 116 | 116 | that omits the B-card is a baseline-manifest. The other manifest |
| 117 | 117 | identified by the argument of the B-card must be a baseline-manifest. |
| 118 | 118 | A baseline-manifest records the complete contents of a check-in. |
| 119 | -A delta-manifest records only changes from its baseline. | |
| 119 | +A delta-manifest records only changes from its baseline. | |
| 120 | 120 | |
| 121 | 121 | A manifest must have exactly one C-card. The sole argument to |
| 122 | 122 | the C-card is a check-in comment that describes the check-in that |
| 123 | 123 | the manifest defines. The check-in comment is text. The following |
| 124 | 124 | escape sequences are applied to the text: |
| 125 | 125 | A space (ASCII 0x20) is represented as "\s" (ASCII 0x5C, 0x73). A |
| 126 | -newline (ASCII 0x0a) is "\n" (ASCII 0x5C, x6E). A backslash | |
| 126 | +newline (ASCII 0x0a) is "\n" (ASCII 0x5C, x6E). A backslash | |
| 127 | 127 | (ASCII 0x5C) is represented as two backslashes "\\". Apart from |
| 128 | 128 | space and newline, no other whitespace characters are allowed in |
| 129 | 129 | the check-in comment. Nor are any unprintable characters allowed |
| 130 | 130 | in the comment. |
| 131 | 131 | |
| @@ -167,11 +167,11 @@ | ||
| 167 | 167 | is used. |
| 168 | 168 | |
| 169 | 169 | A manifest has zero or one P-cards. Most manifests have one P-card. |
| 170 | 170 | The P-card has a varying number of arguments that |
| 171 | 171 | define other manifests from which the current manifest |
| 172 | -is derived. Each argument is a 40-character lowercase | |
| 172 | +is derived. Each argument is a 40-character lowercase | |
| 173 | 173 | hexadecimal SHA1 of a predecessor manifest. All arguments |
| 174 | 174 | to the P-card must be unique within that card. |
| 175 | 175 | The first argument is the SHA1 of the direct ancestor of the manifest. |
| 176 | 176 | Other arguments define manifests with which the first was |
| 177 | 177 | merged to yield the current manifest. Most manifests have |
| @@ -184,28 +184,28 @@ | ||
| 184 | 184 | whereas a P-card defines the immediate ancestor or a merge |
| 185 | 185 | ancestor, the Q-card is used to identify a single check-in or a small |
| 186 | 186 | range of check-ins which were cherry-picked for inclusion in or |
| 187 | 187 | exclusion from the current manifest. The first argument of |
| 188 | 188 | the Q-card is the artifact ID of another manifest (the "target") |
| 189 | -which has had its changes included or excluded in the current manifest. | |
| 189 | +which has had its changes included or excluded in the current manifest. | |
| 190 | 190 | The target is preceded by "+" or "-" to show inclusion or |
| 191 | 191 | exclusion, respectively. The optional second argument to the |
| 192 | 192 | Q-card is another manifest artifact ID which is the "baseline" |
| 193 | 193 | for the cherry-pick. If omitted, the baseline is the primary |
| 194 | 194 | parent of the target. The |
| 195 | 195 | changes included or excluded consist of all changes moving from |
| 196 | -the baseline to the target. | |
| 196 | +the baseline to the target. | |
| 197 | 197 | |
| 198 | -The Q-card was added to the interface specification on 2011-02-26. | |
| 198 | +The Q-card was added to the interface specification on 2011-02-26. | |
| 199 | 199 | Older versions of Fossil will reject manifests that contain Q-cards. |
| 200 | 200 | |
| 201 | 201 | A manifest may optionally have a single R-card. The R-card has |
| 202 | -a single argument which is the MD5 checksum of all files in | |
| 202 | +a single argument which is the MD5 checksum of all files in | |
| 203 | 203 | the check-in except the manifest itself. The checksum is expressed |
| 204 | 204 | as 32 characters of lowercase hexadecimal. The checksum is |
| 205 | 205 | computed as follows: For each file in the check-in (except for |
| 206 | -the manifest itself) in strict sorted lexicographical order, | |
| 206 | +the manifest itself) in strict sorted lexicographical order, | |
| 207 | 207 | take the pathname of the file relative to the root of the |
| 208 | 208 | repository, append a single space (ASCII 0x20), the |
| 209 | 209 | size of the file in ASCII decimal, a single newline |
| 210 | 210 | character (ASCII 0x0A), and the complete text of the file. |
| 211 | 211 | Compute the MD5 checksum of the result. |
| @@ -228,12 +228,12 @@ | ||
| 228 | 228 | is encoded using the same character escapes as is used for the |
| 229 | 229 | check-in comment argument to the C-card. |
| 230 | 230 | |
| 231 | 231 | A manifest must have a single Z-card as its last line. The argument |
| 232 | 232 | to the Z-card is a 32-character lowercase hexadecimal MD5 hash |
| 233 | -of all prior lines of the manifest up to and including the newline | |
| 234 | -character that immediately precedes the "Z". The Z-card is | |
| 233 | +of all prior lines of the manifest up to and including the newline | |
| 234 | +character that immediately precedes the "Z". The Z-card is | |
| 235 | 235 | a sanity check to prove that the manifest is well-formed and |
| 236 | 236 | consistent. |
| 237 | 237 | |
| 238 | 238 | A sample manifest from Fossil itself can be seen |
| 239 | 239 | [/artifact/28987096ac | here]. |
| @@ -240,11 +240,11 @@ | ||
| 240 | 240 | |
| 241 | 241 | <a name="cluster"></a> |
| 242 | 242 | <h2>2.0 Clusters</h2> |
| 243 | 243 | |
| 244 | 244 | A cluster is an artifact that declares the existence of other artifacts. |
| 245 | -Clusters are used during repository synchronization to help | |
| 245 | +Clusters are used during repository synchronization to help | |
| 246 | 246 | reduce network traffic. As such, clusters are an optimization and |
| 247 | 247 | may be removed from a repository without loss or damage to the |
| 248 | 248 | underlying project code. |
| 249 | 249 | |
| 250 | 250 | Clusters follow a syntax that is very similar to manifests. |
| @@ -252,15 +252,15 @@ | ||
| 252 | 252 | (ASCII 0x0a) separate the artifact into cards. Each card begins with a single |
| 253 | 253 | character "card type". Zero or more arguments may follow |
| 254 | 254 | the card type. All arguments are separated from each other |
| 255 | 255 | and from the card-type character by a single space |
| 256 | 256 | character. There is no surplus white space between arguments |
| 257 | -and no leading or trailing whitespace except for the newline | |
| 257 | +and no leading or trailing whitespace except for the newline | |
| 258 | 258 | character that acts as the card separator. |
| 259 | 259 | All cards of a cluster occur in strict sorted lexicographical order. |
| 260 | 260 | No card may be duplicated. |
| 261 | -The cluster may not contain additional text or data beyond | |
| 261 | +The cluster may not contain additional text or data beyond | |
| 262 | 262 | what is described here. |
| 263 | 263 | Unlike manifests, clusters are never PGP signed. |
| 264 | 264 | |
| 265 | 265 | Allowed cards in the cluster are as follows: |
| 266 | 266 | |
| @@ -268,11 +268,11 @@ | ||
| 268 | 268 | <b>M</b> <i>artifact-id</i><br /> |
| 269 | 269 | <b>Z</b> <i>checksum</i> |
| 270 | 270 | </blockquote> |
| 271 | 271 | |
| 272 | 272 | A cluster contains one or more "M" cards followed by a single "Z" |
| 273 | -card. Each M card has a single argument which is the artifact ID of | |
| 273 | +card. Each M card has a single argument which is the artifact ID of | |
| 274 | 274 | another artifact in the repository. The Z card works exactly like |
| 275 | 275 | the Z card of a manifest. The argument to the Z card is the |
| 276 | 276 | lower-case hexadecimal representation of the MD5 checksum of all |
| 277 | 277 | prior cards in the cluster. The Z-card is required. |
| 278 | 278 | |
| @@ -315,11 +315,11 @@ | ||
| 315 | 315 | first value is the tag name. The first character of the tag |
| 316 | 316 | is either "+", "-", or "*". The "+" means the tag should be added |
| 317 | 317 | to the artifact. The "-" means the tag should be removed. |
| 318 | 318 | The "*" character means the tag should be added to the artifact |
| 319 | 319 | and all direct descendants (but not descendants through a merge) down |
| 320 | -to but not including the first descendant that contains a | |
| 320 | +to but not including the first descendant that contains a | |
| 321 | 321 | more recent "-", "*", or "+" tag with the same name. |
| 322 | 322 | The optional third argument is the value of the tag. A tag |
| 323 | 323 | without a value is a Boolean. |
| 324 | 324 | |
| 325 | 325 | When two or more tags with the same name are applied to the |
| @@ -331,11 +331,11 @@ | ||
| 331 | 331 | for display purposes. The "user" tag overrides the name of the |
| 332 | 332 | check-in user. The "date" tag overrides the check-in date. |
| 333 | 333 | The "branch" tag sets the name of the branch that at check-in |
| 334 | 334 | belongs to. Symbolic tags begin with the "sym-" prefix. |
| 335 | 335 | |
| 336 | -The U card is the name of the user that created the control | |
| 336 | +The U card is the name of the user that created the control | |
| 337 | 337 | artifact. The Z card is the usual required artifact checksum. |
| 338 | 338 | |
| 339 | 339 | An example control artifacts can be seen [/info/9d302ccda8 | here]. |
| 340 | 340 | |
| 341 | 341 | |
| @@ -360,11 +360,11 @@ | ||
| 360 | 360 | |
| 361 | 361 | The D card is the date and time when the wiki page was edited. |
| 362 | 362 | The P card specifies the parent wiki pages, if any. The L card |
| 363 | 363 | gives the name of the wiki page. The optional N card specifies |
| 364 | 364 | the mimetype of the wiki text. If the N card is omitted, the |
| 365 | -mimetype is assumed to be text/x-fossil-wiki. | |
| 365 | +mimetype is assumed to be text/x-fossil-wiki. | |
| 366 | 366 | The U card specifies the login |
| 367 | 367 | of the user who made this edit to the wiki page. The Z card is |
| 368 | 368 | the usual checksum over the entire artifact and is required. |
| 369 | 369 | |
| 370 | 370 | The W card is used to specify the text of the wiki page. The |
| @@ -405,11 +405,11 @@ | ||
| 405 | 405 | If the <i>value</i> parameter of the J card is omitted, then the |
| 406 | 406 | field is set to an empty string. |
| 407 | 407 | Each fossil server has a ticket configuration which specifies the fields its |
| 408 | 408 | understands. The ticket configuration is part of the local state for |
| 409 | 409 | the repository and thus can vary from one repository to another. |
| 410 | -Hence a J card might specify a <i>field</i> that do not exist in the | |
| 410 | +Hence a J card might specify a <i>field</i> that do not exist in the | |
| 411 | 411 | local ticket configuration. If a J card specifies a <i>field</i> that |
| 412 | 412 | is not in the local configuration, then that J card |
| 413 | 413 | is simply ignored. |
| 414 | 414 | |
| 415 | 415 | The first argument of the J card is the field name. The second |
| @@ -424,11 +424,11 @@ | ||
| 424 | 424 | |
| 425 | 425 | <a name="attachment"></a> |
| 426 | 426 | <h2>6.0 Attachments</h2> |
| 427 | 427 | |
| 428 | 428 | An attachment artifact associates some other artifact that is the |
| 429 | -attachment (the source artifact) with a ticket or wiki page or | |
| 429 | +attachment (the source artifact) with a ticket or wiki page or | |
| 430 | 430 | technical note to which |
| 431 | 431 | the attachment is connected (the target artifact). |
| 432 | 432 | The following cards are allowed on an attachment artifact: |
| 433 | 433 | |
| 434 | 434 | <blockquote> |
| @@ -441,11 +441,11 @@ | ||
| 441 | 441 | </blockquote> |
| 442 | 442 | |
| 443 | 443 | The A card specifies a filename for the attachment in its first argument. |
| 444 | 444 | The second argument to the A card is the name of the wiki page or |
| 445 | 445 | ticket or technical note to which the attachment is connected. The |
| 446 | -third argument is either missing or else it is the 40-character artifact | |
| 446 | +third argument is either missing or else it is the 40-character artifact | |
| 447 | 447 | ID of the attachment itself. A missing third argument means that the |
| 448 | 448 | attachment should be deleted. |
| 449 | 449 | |
| 450 | 450 | The C card is an optional comment describing what the attachment is about. |
| 451 | 451 | The C card is optional, but there can only be one. |
| @@ -487,11 +487,11 @@ | ||
| 487 | 487 | </blockquote> |
| 488 | 488 | |
| 489 | 489 | The C card contains text that is displayed on the timeline for the |
| 490 | 490 | technote. The C card is optional, but there can only be one. |
| 491 | 491 | |
| 492 | -A single D card is required to give the date and time when the | |
| 492 | +A single D card is required to give the date and time when the | |
| 493 | 493 | technote artifact was created. This is different from the time at which |
| 494 | 494 | the technote appears on the timeline. |
| 495 | 495 | |
| 496 | 496 | A single E card gives the time of the technote (the point on the timeline |
| 497 | 497 | where the technote is displayed) and a unique identifier for the technote. |
| @@ -525,11 +525,11 @@ | ||
| 525 | 525 | display color for timelines. |
| 526 | 526 | |
| 527 | 527 | The optional U card gives name of the user who entered the technote. |
| 528 | 528 | |
| 529 | 529 | A single W card provides wiki text for the document associated with the |
| 530 | -technote. The format of the W card is exactly the same as for a | |
| 530 | +technote. The format of the W card is exactly the same as for a | |
| 531 | 531 | [#wikichng | wiki artifact]. |
| 532 | 532 | |
| 533 | 533 | The Z card is the required checksum over the rest of the artifact. |
| 534 | 534 | |
| 535 | 535 | |
| 536 | 536 |
| --- www/fileformat.wiki | |
| +++ www/fileformat.wiki | |
| @@ -2,11 +2,11 @@ | |
| 2 | <h1 align="center"> |
| 3 | Fossil File Formats |
| 4 | </h1> |
| 5 | |
| 6 | The global state of a fossil repository is kept simple so that it can |
| 7 | endure in useful form for decades or centuries. |
| 8 | A fossil repository is intended to be readable, |
| 9 | searchable, and extensible by people not yet born. |
| 10 | |
| 11 | The global state of a fossil repository is an unordered |
| 12 | set of <i>artifacts</i>. |
| @@ -14,11 +14,11 @@ | |
| 14 | part of a trouble ticket, or one of several special control artifacts |
| 15 | used to show the relationships between other artifacts within the |
| 16 | project. Each artifact is normally represented on disk as a separate |
| 17 | file. Artifacts can be text or binary. |
| 18 | |
| 19 | In addition to the global state, |
| 20 | each fossil repository also contains local state. |
| 21 | The local state consists of web-page formatting |
| 22 | preferences, authorized users, ticket display and reporting formats, |
| 23 | and so forth. The global state is shared in common among all |
| 24 | repositories for the same project, whereas the local state is often |
| @@ -30,11 +30,11 @@ | |
| 30 | mentioned here in order to distinguish it from global state. |
| 31 | |
| 32 | Each artifact in the repository is named by its SHA1 hash. |
| 33 | No prefixes or meta information is added to an artifact before |
| 34 | its hash is computed. The name of an artifact in the repository |
| 35 | is exactly the same SHA1 hash that is computed by sha1sum |
| 36 | on the file as it exists in your source tree.</p> |
| 37 | |
| 38 | Some artifacts have a particular format which gives them special |
| 39 | meaning to fossil. Fossil recognizes: |
| 40 | |
| @@ -84,11 +84,11 @@ | |
| 84 | Each card begins with a single |
| 85 | character "card type". Zero or more arguments may follow |
| 86 | the card type. All arguments are separated from each other |
| 87 | and from the card-type character by a single space |
| 88 | character. There is no surplus white space between arguments |
| 89 | and no leading or trailing whitespace except for the newline |
| 90 | character that acts as the card separator. |
| 91 | |
| 92 | All cards of the manifest occur in strict sorted lexicographical order. |
| 93 | No card may be duplicated. |
| 94 | The entire manifest may be PGP clear-signed, but otherwise it |
| @@ -114,18 +114,18 @@ | |
| 114 | another manifest that serves as the "baseline" for this manifest. A |
| 115 | manifest that has a B-card is called a delta-manifest and a manifest |
| 116 | that omits the B-card is a baseline-manifest. The other manifest |
| 117 | identified by the argument of the B-card must be a baseline-manifest. |
| 118 | A baseline-manifest records the complete contents of a check-in. |
| 119 | A delta-manifest records only changes from its baseline. |
| 120 | |
| 121 | A manifest must have exactly one C-card. The sole argument to |
| 122 | the C-card is a check-in comment that describes the check-in that |
| 123 | the manifest defines. The check-in comment is text. The following |
| 124 | escape sequences are applied to the text: |
| 125 | A space (ASCII 0x20) is represented as "\s" (ASCII 0x5C, 0x73). A |
| 126 | newline (ASCII 0x0a) is "\n" (ASCII 0x5C, x6E). A backslash |
| 127 | (ASCII 0x5C) is represented as two backslashes "\\". Apart from |
| 128 | space and newline, no other whitespace characters are allowed in |
| 129 | the check-in comment. Nor are any unprintable characters allowed |
| 130 | in the comment. |
| 131 | |
| @@ -167,11 +167,11 @@ | |
| 167 | is used. |
| 168 | |
| 169 | A manifest has zero or one P-cards. Most manifests have one P-card. |
| 170 | The P-card has a varying number of arguments that |
| 171 | define other manifests from which the current manifest |
| 172 | is derived. Each argument is a 40-character lowercase |
| 173 | hexadecimal SHA1 of a predecessor manifest. All arguments |
| 174 | to the P-card must be unique within that card. |
| 175 | The first argument is the SHA1 of the direct ancestor of the manifest. |
| 176 | Other arguments define manifests with which the first was |
| 177 | merged to yield the current manifest. Most manifests have |
| @@ -184,28 +184,28 @@ | |
| 184 | whereas a P-card defines the immediate ancestor or a merge |
| 185 | ancestor, the Q-card is used to identify a single check-in or a small |
| 186 | range of check-ins which were cherry-picked for inclusion in or |
| 187 | exclusion from the current manifest. The first argument of |
| 188 | the Q-card is the artifact ID of another manifest (the "target") |
| 189 | which has had its changes included or excluded in the current manifest. |
| 190 | The target is preceded by "+" or "-" to show inclusion or |
| 191 | exclusion, respectively. The optional second argument to the |
| 192 | Q-card is another manifest artifact ID which is the "baseline" |
| 193 | for the cherry-pick. If omitted, the baseline is the primary |
| 194 | parent of the target. The |
| 195 | changes included or excluded consist of all changes moving from |
| 196 | the baseline to the target. |
| 197 | |
| 198 | The Q-card was added to the interface specification on 2011-02-26. |
| 199 | Older versions of Fossil will reject manifests that contain Q-cards. |
| 200 | |
| 201 | A manifest may optionally have a single R-card. The R-card has |
| 202 | a single argument which is the MD5 checksum of all files in |
| 203 | the check-in except the manifest itself. The checksum is expressed |
| 204 | as 32 characters of lowercase hexadecimal. The checksum is |
| 205 | computed as follows: For each file in the check-in (except for |
| 206 | the manifest itself) in strict sorted lexicographical order, |
| 207 | take the pathname of the file relative to the root of the |
| 208 | repository, append a single space (ASCII 0x20), the |
| 209 | size of the file in ASCII decimal, a single newline |
| 210 | character (ASCII 0x0A), and the complete text of the file. |
| 211 | Compute the MD5 checksum of the result. |
| @@ -228,12 +228,12 @@ | |
| 228 | is encoded using the same character escapes as is used for the |
| 229 | check-in comment argument to the C-card. |
| 230 | |
| 231 | A manifest must have a single Z-card as its last line. The argument |
| 232 | to the Z-card is a 32-character lowercase hexadecimal MD5 hash |
| 233 | of all prior lines of the manifest up to and including the newline |
| 234 | character that immediately precedes the "Z". The Z-card is |
| 235 | a sanity check to prove that the manifest is well-formed and |
| 236 | consistent. |
| 237 | |
| 238 | A sample manifest from Fossil itself can be seen |
| 239 | [/artifact/28987096ac | here]. |
| @@ -240,11 +240,11 @@ | |
| 240 | |
| 241 | <a name="cluster"></a> |
| 242 | <h2>2.0 Clusters</h2> |
| 243 | |
| 244 | A cluster is an artifact that declares the existence of other artifacts. |
| 245 | Clusters are used during repository synchronization to help |
| 246 | reduce network traffic. As such, clusters are an optimization and |
| 247 | may be removed from a repository without loss or damage to the |
| 248 | underlying project code. |
| 249 | |
| 250 | Clusters follow a syntax that is very similar to manifests. |
| @@ -252,15 +252,15 @@ | |
| 252 | (ASCII 0x0a) separate the artifact into cards. Each card begins with a single |
| 253 | character "card type". Zero or more arguments may follow |
| 254 | the card type. All arguments are separated from each other |
| 255 | and from the card-type character by a single space |
| 256 | character. There is no surplus white space between arguments |
| 257 | and no leading or trailing whitespace except for the newline |
| 258 | character that acts as the card separator. |
| 259 | All cards of a cluster occur in strict sorted lexicographical order. |
| 260 | No card may be duplicated. |
| 261 | The cluster may not contain additional text or data beyond |
| 262 | what is described here. |
| 263 | Unlike manifests, clusters are never PGP signed. |
| 264 | |
| 265 | Allowed cards in the cluster are as follows: |
| 266 | |
| @@ -268,11 +268,11 @@ | |
| 268 | <b>M</b> <i>artifact-id</i><br /> |
| 269 | <b>Z</b> <i>checksum</i> |
| 270 | </blockquote> |
| 271 | |
| 272 | A cluster contains one or more "M" cards followed by a single "Z" |
| 273 | card. Each M card has a single argument which is the artifact ID of |
| 274 | another artifact in the repository. The Z card works exactly like |
| 275 | the Z card of a manifest. The argument to the Z card is the |
| 276 | lower-case hexadecimal representation of the MD5 checksum of all |
| 277 | prior cards in the cluster. The Z-card is required. |
| 278 | |
| @@ -315,11 +315,11 @@ | |
| 315 | first value is the tag name. The first character of the tag |
| 316 | is either "+", "-", or "*". The "+" means the tag should be added |
| 317 | to the artifact. The "-" means the tag should be removed. |
| 318 | The "*" character means the tag should be added to the artifact |
| 319 | and all direct descendants (but not descendants through a merge) down |
| 320 | to but not including the first descendant that contains a |
| 321 | more recent "-", "*", or "+" tag with the same name. |
| 322 | The optional third argument is the value of the tag. A tag |
| 323 | without a value is a Boolean. |
| 324 | |
| 325 | When two or more tags with the same name are applied to the |
| @@ -331,11 +331,11 @@ | |
| 331 | for display purposes. The "user" tag overrides the name of the |
| 332 | check-in user. The "date" tag overrides the check-in date. |
| 333 | The "branch" tag sets the name of the branch that at check-in |
| 334 | belongs to. Symbolic tags begin with the "sym-" prefix. |
| 335 | |
| 336 | The U card is the name of the user that created the control |
| 337 | artifact. The Z card is the usual required artifact checksum. |
| 338 | |
| 339 | An example control artifacts can be seen [/info/9d302ccda8 | here]. |
| 340 | |
| 341 | |
| @@ -360,11 +360,11 @@ | |
| 360 | |
| 361 | The D card is the date and time when the wiki page was edited. |
| 362 | The P card specifies the parent wiki pages, if any. The L card |
| 363 | gives the name of the wiki page. The optional N card specifies |
| 364 | the mimetype of the wiki text. If the N card is omitted, the |
| 365 | mimetype is assumed to be text/x-fossil-wiki. |
| 366 | The U card specifies the login |
| 367 | of the user who made this edit to the wiki page. The Z card is |
| 368 | the usual checksum over the entire artifact and is required. |
| 369 | |
| 370 | The W card is used to specify the text of the wiki page. The |
| @@ -405,11 +405,11 @@ | |
| 405 | If the <i>value</i> parameter of the J card is omitted, then the |
| 406 | field is set to an empty string. |
| 407 | Each fossil server has a ticket configuration which specifies the fields its |
| 408 | understands. The ticket configuration is part of the local state for |
| 409 | the repository and thus can vary from one repository to another. |
| 410 | Hence a J card might specify a <i>field</i> that do not exist in the |
| 411 | local ticket configuration. If a J card specifies a <i>field</i> that |
| 412 | is not in the local configuration, then that J card |
| 413 | is simply ignored. |
| 414 | |
| 415 | The first argument of the J card is the field name. The second |
| @@ -424,11 +424,11 @@ | |
| 424 | |
| 425 | <a name="attachment"></a> |
| 426 | <h2>6.0 Attachments</h2> |
| 427 | |
| 428 | An attachment artifact associates some other artifact that is the |
| 429 | attachment (the source artifact) with a ticket or wiki page or |
| 430 | technical note to which |
| 431 | the attachment is connected (the target artifact). |
| 432 | The following cards are allowed on an attachment artifact: |
| 433 | |
| 434 | <blockquote> |
| @@ -441,11 +441,11 @@ | |
| 441 | </blockquote> |
| 442 | |
| 443 | The A card specifies a filename for the attachment in its first argument. |
| 444 | The second argument to the A card is the name of the wiki page or |
| 445 | ticket or technical note to which the attachment is connected. The |
| 446 | third argument is either missing or else it is the 40-character artifact |
| 447 | ID of the attachment itself. A missing third argument means that the |
| 448 | attachment should be deleted. |
| 449 | |
| 450 | The C card is an optional comment describing what the attachment is about. |
| 451 | The C card is optional, but there can only be one. |
| @@ -487,11 +487,11 @@ | |
| 487 | </blockquote> |
| 488 | |
| 489 | The C card contains text that is displayed on the timeline for the |
| 490 | technote. The C card is optional, but there can only be one. |
| 491 | |
| 492 | A single D card is required to give the date and time when the |
| 493 | technote artifact was created. This is different from the time at which |
| 494 | the technote appears on the timeline. |
| 495 | |
| 496 | A single E card gives the time of the technote (the point on the timeline |
| 497 | where the technote is displayed) and a unique identifier for the technote. |
| @@ -525,11 +525,11 @@ | |
| 525 | display color for timelines. |
| 526 | |
| 527 | The optional U card gives name of the user who entered the technote. |
| 528 | |
| 529 | A single W card provides wiki text for the document associated with the |
| 530 | technote. The format of the W card is exactly the same as for a |
| 531 | [#wikichng | wiki artifact]. |
| 532 | |
| 533 | The Z card is the required checksum over the rest of the artifact. |
| 534 | |
| 535 | |
| 536 |
| --- www/fileformat.wiki | |
| +++ www/fileformat.wiki | |
| @@ -2,11 +2,11 @@ | |
| 2 | <h1 align="center"> |
| 3 | Fossil File Formats |
| 4 | </h1> |
| 5 | |
| 6 | The global state of a fossil repository is kept simple so that it can |
| 7 | endure in useful form for decades or centuries. |
| 8 | A fossil repository is intended to be readable, |
| 9 | searchable, and extensible by people not yet born. |
| 10 | |
| 11 | The global state of a fossil repository is an unordered |
| 12 | set of <i>artifacts</i>. |
| @@ -14,11 +14,11 @@ | |
| 14 | part of a trouble ticket, or one of several special control artifacts |
| 15 | used to show the relationships between other artifacts within the |
| 16 | project. Each artifact is normally represented on disk as a separate |
| 17 | file. Artifacts can be text or binary. |
| 18 | |
| 19 | In addition to the global state, |
| 20 | each fossil repository also contains local state. |
| 21 | The local state consists of web-page formatting |
| 22 | preferences, authorized users, ticket display and reporting formats, |
| 23 | and so forth. The global state is shared in common among all |
| 24 | repositories for the same project, whereas the local state is often |
| @@ -30,11 +30,11 @@ | |
| 30 | mentioned here in order to distinguish it from global state. |
| 31 | |
| 32 | Each artifact in the repository is named by its SHA1 hash. |
| 33 | No prefixes or meta information is added to an artifact before |
| 34 | its hash is computed. The name of an artifact in the repository |
| 35 | is exactly the same SHA1 hash that is computed by sha1sum |
| 36 | on the file as it exists in your source tree.</p> |
| 37 | |
| 38 | Some artifacts have a particular format which gives them special |
| 39 | meaning to fossil. Fossil recognizes: |
| 40 | |
| @@ -84,11 +84,11 @@ | |
| 84 | Each card begins with a single |
| 85 | character "card type". Zero or more arguments may follow |
| 86 | the card type. All arguments are separated from each other |
| 87 | and from the card-type character by a single space |
| 88 | character. There is no surplus white space between arguments |
| 89 | and no leading or trailing whitespace except for the newline |
| 90 | character that acts as the card separator. |
| 91 | |
| 92 | All cards of the manifest occur in strict sorted lexicographical order. |
| 93 | No card may be duplicated. |
| 94 | The entire manifest may be PGP clear-signed, but otherwise it |
| @@ -114,18 +114,18 @@ | |
| 114 | another manifest that serves as the "baseline" for this manifest. A |
| 115 | manifest that has a B-card is called a delta-manifest and a manifest |
| 116 | that omits the B-card is a baseline-manifest. The other manifest |
| 117 | identified by the argument of the B-card must be a baseline-manifest. |
| 118 | A baseline-manifest records the complete contents of a check-in. |
| 119 | A delta-manifest records only changes from its baseline. |
| 120 | |
| 121 | A manifest must have exactly one C-card. The sole argument to |
| 122 | the C-card is a check-in comment that describes the check-in that |
| 123 | the manifest defines. The check-in comment is text. The following |
| 124 | escape sequences are applied to the text: |
| 125 | A space (ASCII 0x20) is represented as "\s" (ASCII 0x5C, 0x73). A |
| 126 | newline (ASCII 0x0a) is "\n" (ASCII 0x5C, x6E). A backslash |
| 127 | (ASCII 0x5C) is represented as two backslashes "\\". Apart from |
| 128 | space and newline, no other whitespace characters are allowed in |
| 129 | the check-in comment. Nor are any unprintable characters allowed |
| 130 | in the comment. |
| 131 | |
| @@ -167,11 +167,11 @@ | |
| 167 | is used. |
| 168 | |
| 169 | A manifest has zero or one P-cards. Most manifests have one P-card. |
| 170 | The P-card has a varying number of arguments that |
| 171 | define other manifests from which the current manifest |
| 172 | is derived. Each argument is a 40-character lowercase |
| 173 | hexadecimal SHA1 of a predecessor manifest. All arguments |
| 174 | to the P-card must be unique within that card. |
| 175 | The first argument is the SHA1 of the direct ancestor of the manifest. |
| 176 | Other arguments define manifests with which the first was |
| 177 | merged to yield the current manifest. Most manifests have |
| @@ -184,28 +184,28 @@ | |
| 184 | whereas a P-card defines the immediate ancestor or a merge |
| 185 | ancestor, the Q-card is used to identify a single check-in or a small |
| 186 | range of check-ins which were cherry-picked for inclusion in or |
| 187 | exclusion from the current manifest. The first argument of |
| 188 | the Q-card is the artifact ID of another manifest (the "target") |
| 189 | which has had its changes included or excluded in the current manifest. |
| 190 | The target is preceded by "+" or "-" to show inclusion or |
| 191 | exclusion, respectively. The optional second argument to the |
| 192 | Q-card is another manifest artifact ID which is the "baseline" |
| 193 | for the cherry-pick. If omitted, the baseline is the primary |
| 194 | parent of the target. The |
| 195 | changes included or excluded consist of all changes moving from |
| 196 | the baseline to the target. |
| 197 | |
| 198 | The Q-card was added to the interface specification on 2011-02-26. |
| 199 | Older versions of Fossil will reject manifests that contain Q-cards. |
| 200 | |
| 201 | A manifest may optionally have a single R-card. The R-card has |
| 202 | a single argument which is the MD5 checksum of all files in |
| 203 | the check-in except the manifest itself. The checksum is expressed |
| 204 | as 32 characters of lowercase hexadecimal. The checksum is |
| 205 | computed as follows: For each file in the check-in (except for |
| 206 | the manifest itself) in strict sorted lexicographical order, |
| 207 | take the pathname of the file relative to the root of the |
| 208 | repository, append a single space (ASCII 0x20), the |
| 209 | size of the file in ASCII decimal, a single newline |
| 210 | character (ASCII 0x0A), and the complete text of the file. |
| 211 | Compute the MD5 checksum of the result. |
| @@ -228,12 +228,12 @@ | |
| 228 | is encoded using the same character escapes as is used for the |
| 229 | check-in comment argument to the C-card. |
| 230 | |
| 231 | A manifest must have a single Z-card as its last line. The argument |
| 232 | to the Z-card is a 32-character lowercase hexadecimal MD5 hash |
| 233 | of all prior lines of the manifest up to and including the newline |
| 234 | character that immediately precedes the "Z". The Z-card is |
| 235 | a sanity check to prove that the manifest is well-formed and |
| 236 | consistent. |
| 237 | |
| 238 | A sample manifest from Fossil itself can be seen |
| 239 | [/artifact/28987096ac | here]. |
| @@ -240,11 +240,11 @@ | |
| 240 | |
| 241 | <a name="cluster"></a> |
| 242 | <h2>2.0 Clusters</h2> |
| 243 | |
| 244 | A cluster is an artifact that declares the existence of other artifacts. |
| 245 | Clusters are used during repository synchronization to help |
| 246 | reduce network traffic. As such, clusters are an optimization and |
| 247 | may be removed from a repository without loss or damage to the |
| 248 | underlying project code. |
| 249 | |
| 250 | Clusters follow a syntax that is very similar to manifests. |
| @@ -252,15 +252,15 @@ | |
| 252 | (ASCII 0x0a) separate the artifact into cards. Each card begins with a single |
| 253 | character "card type". Zero or more arguments may follow |
| 254 | the card type. All arguments are separated from each other |
| 255 | and from the card-type character by a single space |
| 256 | character. There is no surplus white space between arguments |
| 257 | and no leading or trailing whitespace except for the newline |
| 258 | character that acts as the card separator. |
| 259 | All cards of a cluster occur in strict sorted lexicographical order. |
| 260 | No card may be duplicated. |
| 261 | The cluster may not contain additional text or data beyond |
| 262 | what is described here. |
| 263 | Unlike manifests, clusters are never PGP signed. |
| 264 | |
| 265 | Allowed cards in the cluster are as follows: |
| 266 | |
| @@ -268,11 +268,11 @@ | |
| 268 | <b>M</b> <i>artifact-id</i><br /> |
| 269 | <b>Z</b> <i>checksum</i> |
| 270 | </blockquote> |
| 271 | |
| 272 | A cluster contains one or more "M" cards followed by a single "Z" |
| 273 | card. Each M card has a single argument which is the artifact ID of |
| 274 | another artifact in the repository. The Z card works exactly like |
| 275 | the Z card of a manifest. The argument to the Z card is the |
| 276 | lower-case hexadecimal representation of the MD5 checksum of all |
| 277 | prior cards in the cluster. The Z-card is required. |
| 278 | |
| @@ -315,11 +315,11 @@ | |
| 315 | first value is the tag name. The first character of the tag |
| 316 | is either "+", "-", or "*". The "+" means the tag should be added |
| 317 | to the artifact. The "-" means the tag should be removed. |
| 318 | The "*" character means the tag should be added to the artifact |
| 319 | and all direct descendants (but not descendants through a merge) down |
| 320 | to but not including the first descendant that contains a |
| 321 | more recent "-", "*", or "+" tag with the same name. |
| 322 | The optional third argument is the value of the tag. A tag |
| 323 | without a value is a Boolean. |
| 324 | |
| 325 | When two or more tags with the same name are applied to the |
| @@ -331,11 +331,11 @@ | |
| 331 | for display purposes. The "user" tag overrides the name of the |
| 332 | check-in user. The "date" tag overrides the check-in date. |
| 333 | The "branch" tag sets the name of the branch that at check-in |
| 334 | belongs to. Symbolic tags begin with the "sym-" prefix. |
| 335 | |
| 336 | The U card is the name of the user that created the control |
| 337 | artifact. The Z card is the usual required artifact checksum. |
| 338 | |
| 339 | An example control artifacts can be seen [/info/9d302ccda8 | here]. |
| 340 | |
| 341 | |
| @@ -360,11 +360,11 @@ | |
| 360 | |
| 361 | The D card is the date and time when the wiki page was edited. |
| 362 | The P card specifies the parent wiki pages, if any. The L card |
| 363 | gives the name of the wiki page. The optional N card specifies |
| 364 | the mimetype of the wiki text. If the N card is omitted, the |
| 365 | mimetype is assumed to be text/x-fossil-wiki. |
| 366 | The U card specifies the login |
| 367 | of the user who made this edit to the wiki page. The Z card is |
| 368 | the usual checksum over the entire artifact and is required. |
| 369 | |
| 370 | The W card is used to specify the text of the wiki page. The |
| @@ -405,11 +405,11 @@ | |
| 405 | If the <i>value</i> parameter of the J card is omitted, then the |
| 406 | field is set to an empty string. |
| 407 | Each fossil server has a ticket configuration which specifies the fields its |
| 408 | understands. The ticket configuration is part of the local state for |
| 409 | the repository and thus can vary from one repository to another. |
| 410 | Hence a J card might specify a <i>field</i> that do not exist in the |
| 411 | local ticket configuration. If a J card specifies a <i>field</i> that |
| 412 | is not in the local configuration, then that J card |
| 413 | is simply ignored. |
| 414 | |
| 415 | The first argument of the J card is the field name. The second |
| @@ -424,11 +424,11 @@ | |
| 424 | |
| 425 | <a name="attachment"></a> |
| 426 | <h2>6.0 Attachments</h2> |
| 427 | |
| 428 | An attachment artifact associates some other artifact that is the |
| 429 | attachment (the source artifact) with a ticket or wiki page or |
| 430 | technical note to which |
| 431 | the attachment is connected (the target artifact). |
| 432 | The following cards are allowed on an attachment artifact: |
| 433 | |
| 434 | <blockquote> |
| @@ -441,11 +441,11 @@ | |
| 441 | </blockquote> |
| 442 | |
| 443 | The A card specifies a filename for the attachment in its first argument. |
| 444 | The second argument to the A card is the name of the wiki page or |
| 445 | ticket or technical note to which the attachment is connected. The |
| 446 | third argument is either missing or else it is the 40-character artifact |
| 447 | ID of the attachment itself. A missing third argument means that the |
| 448 | attachment should be deleted. |
| 449 | |
| 450 | The C card is an optional comment describing what the attachment is about. |
| 451 | The C card is optional, but there can only be one. |
| @@ -487,11 +487,11 @@ | |
| 487 | </blockquote> |
| 488 | |
| 489 | The C card contains text that is displayed on the timeline for the |
| 490 | technote. The C card is optional, but there can only be one. |
| 491 | |
| 492 | A single D card is required to give the date and time when the |
| 493 | technote artifact was created. This is different from the time at which |
| 494 | the technote appears on the timeline. |
| 495 | |
| 496 | A single E card gives the time of the technote (the point on the timeline |
| 497 | where the technote is displayed) and a unique identifier for the technote. |
| @@ -525,11 +525,11 @@ | |
| 525 | display color for timelines. |
| 526 | |
| 527 | The optional U card gives name of the user who entered the technote. |
| 528 | |
| 529 | A single W card provides wiki text for the document associated with the |
| 530 | technote. The format of the W card is exactly the same as for a |
| 531 | [#wikichng | wiki artifact]. |
| 532 | |
| 533 | The Z card is the required checksum over the rest of the artifact. |
| 534 | |
| 535 | |
| 536 |
+19
-19
| --- www/fiveminutes.wiki | ||
| +++ www/fiveminutes.wiki | ||
| @@ -4,65 +4,65 @@ | ||
| 4 | 4 | The following document was contributed by Gilles Ganault on 2013-01-08. |
| 5 | 5 | </i></b> |
| 6 | 6 | </p><hr> |
| 7 | 7 | |
| 8 | 8 | <h1>Up and running in 5 minutes as a single user</h1> |
| 9 | -<p>This short document explains the main basic Fossil commands for a single | |
| 10 | -user, i.e. with no additional users, with no need to synchronize with some remote | |
| 9 | +<p>This short document explains the main basic Fossil commands for a single | |
| 10 | +user, i.e. with no additional users, with no need to synchronize with some remote | |
| 11 | 11 | repository, and no need for branching/forking.</p> |
| 12 | 12 | |
| 13 | 13 | <h2>Create a new repository</h2> |
| 14 | 14 | <p>fossil new c:\test.repo</p> |
| 15 | -<p>This will create the new SQLite binary file that holds the repository, i.e. | |
| 16 | -files, tickets, wiki, etc. It can be located anywhere, although it's considered | |
| 17 | -best practice to keep it outside the work directory where you will work on files | |
| 15 | +<p>This will create the new SQLite binary file that holds the repository, i.e. | |
| 16 | +files, tickets, wiki, etc. It can be located anywhere, although it's considered | |
| 17 | +best practice to keep it outside the work directory where you will work on files | |
| 18 | 18 | after they've been checked out of the repository.</p> |
| 19 | 19 | |
| 20 | 20 | <h2>Open the repository</h2> |
| 21 | 21 | <p>cd c:\temp\test.fossil</p> |
| 22 | 22 | <p>fossil open c:\test.repo</p> |
| 23 | -<p>This will check out the last revision of all the files in the repository, | |
| 24 | -if any, into the current work directory. In addition, it will create a binary | |
| 23 | +<p>This will check out the last revision of all the files in the repository, | |
| 24 | +if any, into the current work directory. In addition, it will create a binary | |
| 25 | 25 | file _FOSSIL_ to keep track of changes (on non-Windows systems it is called |
| 26 | 26 | <tt>.fslckout</tt>).</p> |
| 27 | 27 | |
| 28 | 28 | <h2>Add new files</h2> |
| 29 | 29 | <p>fossil add .</p> |
| 30 | -<p>To tell Fossil to add new files to the repository. The files aren't actually | |
| 31 | -added until you run "commit". When using ".", it tells Fossil | |
| 32 | -to add all the files in the current directory recursively, i.e. including all | |
| 30 | +<p>To tell Fossil to add new files to the repository. The files aren't actually | |
| 31 | +added until you run "commit". When using ".", it tells Fossil | |
| 32 | +to add all the files in the current directory recursively, i.e. including all | |
| 33 | 33 | the files in all the subdirectories.</p> |
| 34 | 34 | <p>Note: To tell Fossil to ignore some extensions:</p> |
| 35 | 35 | <p>fossil settings ignore-glob "*.o,*.obj,*.exe" --global</p> |
| 36 | 36 | |
| 37 | 37 | <h2>Remove files that haven't been committed yet</h2> |
| 38 | 38 | <p>fossil delete myfile.c</p> |
| 39 | -<p>This will simply remove the item from the list of files that were previously | |
| 39 | +<p>This will simply remove the item from the list of files that were previously | |
| 40 | 40 | added through "fossil add".</p> |
| 41 | 41 | |
| 42 | 42 | <h2>Check current status</h2> |
| 43 | 43 | <p>fossil changes</p> |
| 44 | -<p>This shows the list of changes that have been done and will be committed the | |
| 45 | -next time you run "fossil commit". It's a useful command to run before | |
| 44 | +<p>This shows the list of changes that have been done and will be committed the | |
| 45 | +next time you run "fossil commit". It's a useful command to run before | |
| 46 | 46 | running "fossil commit" just to check that things are OK before proceeding.</p> |
| 47 | 47 | |
| 48 | 48 | <h2>Commit changes</h2> |
| 49 | -<p>To actually apply the pending changes to the repository, e.g. new files marked | |
| 50 | -for addition, checked-out files that have been edited and must be checked-in, | |
| 49 | +<p>To actually apply the pending changes to the repository, e.g. new files marked | |
| 50 | +for addition, checked-out files that have been edited and must be checked-in, | |
| 51 | 51 | etc.</p> |
| 52 | 52 | |
| 53 | 53 | <p>fossil commit -m "Added stuff"</p> |
| 54 | 54 | |
| 55 | 55 | If no file names are provided on the command-line then all changes will be checked in, |
| 56 | 56 | otherwise just the listed file(s) will be checked in. |
| 57 | 57 | |
| 58 | 58 | <h2>Compare two revisions of a file</h2> |
| 59 | -<p>If you wish to compare the last revision of a file and its checked out version | |
| 59 | +<p>If you wish to compare the last revision of a file and its checked out version | |
| 60 | 60 | in your work directory:</p> |
| 61 | 61 | <p>fossil gdiff myfile.c</p> |
| 62 | 62 | <p>If you wish to compare two different revisions of a file in the repository:</p> |
| 63 | -<p>fossil finfo myfile: Note the first hash, which is the UUID of the commit | |
| 63 | +<p>fossil finfo myfile: Note the first hash, which is the UUID of the commit | |
| 64 | 64 | when the file was committed</p> |
| 65 | 65 | <p>fossil gdiff --from UUID#1 --to UUID#2 myfile.c</p> |
| 66 | 66 | <h2>Cancel changes and go back to previous revision</h2> |
| 67 | 67 | <p>fossil revert myfile.c</p> |
| 68 | 68 | <p>Fossil does not prompt when reverting a file. It simply reminds the user about the |
| @@ -69,8 +69,8 @@ | ||
| 69 | 69 | "undo" command, just in case the revert was a mistake.</p> |
| 70 | 70 | |
| 71 | 71 | |
| 72 | 72 | <h2>Close the repository</h2> |
| 73 | 73 | <p>fossil close</p> |
| 74 | -<p>This will simply remove the _FOSSIL_ at the root of the work directory but | |
| 75 | -will not delete the files in the work directory. From then on, any use of "fossil" | |
| 74 | +<p>This will simply remove the _FOSSIL_ at the root of the work directory but | |
| 75 | +will not delete the files in the work directory. From then on, any use of "fossil" | |
| 76 | 76 | will trigger an error since there is no longer any connection.</p> |
| 77 | 77 |
| --- www/fiveminutes.wiki | |
| +++ www/fiveminutes.wiki | |
| @@ -4,65 +4,65 @@ | |
| 4 | The following document was contributed by Gilles Ganault on 2013-01-08. |
| 5 | </i></b> |
| 6 | </p><hr> |
| 7 | |
| 8 | <h1>Up and running in 5 minutes as a single user</h1> |
| 9 | <p>This short document explains the main basic Fossil commands for a single |
| 10 | user, i.e. with no additional users, with no need to synchronize with some remote |
| 11 | repository, and no need for branching/forking.</p> |
| 12 | |
| 13 | <h2>Create a new repository</h2> |
| 14 | <p>fossil new c:\test.repo</p> |
| 15 | <p>This will create the new SQLite binary file that holds the repository, i.e. |
| 16 | files, tickets, wiki, etc. It can be located anywhere, although it's considered |
| 17 | best practice to keep it outside the work directory where you will work on files |
| 18 | after they've been checked out of the repository.</p> |
| 19 | |
| 20 | <h2>Open the repository</h2> |
| 21 | <p>cd c:\temp\test.fossil</p> |
| 22 | <p>fossil open c:\test.repo</p> |
| 23 | <p>This will check out the last revision of all the files in the repository, |
| 24 | if any, into the current work directory. In addition, it will create a binary |
| 25 | file _FOSSIL_ to keep track of changes (on non-Windows systems it is called |
| 26 | <tt>.fslckout</tt>).</p> |
| 27 | |
| 28 | <h2>Add new files</h2> |
| 29 | <p>fossil add .</p> |
| 30 | <p>To tell Fossil to add new files to the repository. The files aren't actually |
| 31 | added until you run "commit". When using ".", it tells Fossil |
| 32 | to add all the files in the current directory recursively, i.e. including all |
| 33 | the files in all the subdirectories.</p> |
| 34 | <p>Note: To tell Fossil to ignore some extensions:</p> |
| 35 | <p>fossil settings ignore-glob "*.o,*.obj,*.exe" --global</p> |
| 36 | |
| 37 | <h2>Remove files that haven't been committed yet</h2> |
| 38 | <p>fossil delete myfile.c</p> |
| 39 | <p>This will simply remove the item from the list of files that were previously |
| 40 | added through "fossil add".</p> |
| 41 | |
| 42 | <h2>Check current status</h2> |
| 43 | <p>fossil changes</p> |
| 44 | <p>This shows the list of changes that have been done and will be committed the |
| 45 | next time you run "fossil commit". It's a useful command to run before |
| 46 | running "fossil commit" just to check that things are OK before proceeding.</p> |
| 47 | |
| 48 | <h2>Commit changes</h2> |
| 49 | <p>To actually apply the pending changes to the repository, e.g. new files marked |
| 50 | for addition, checked-out files that have been edited and must be checked-in, |
| 51 | etc.</p> |
| 52 | |
| 53 | <p>fossil commit -m "Added stuff"</p> |
| 54 | |
| 55 | If no file names are provided on the command-line then all changes will be checked in, |
| 56 | otherwise just the listed file(s) will be checked in. |
| 57 | |
| 58 | <h2>Compare two revisions of a file</h2> |
| 59 | <p>If you wish to compare the last revision of a file and its checked out version |
| 60 | in your work directory:</p> |
| 61 | <p>fossil gdiff myfile.c</p> |
| 62 | <p>If you wish to compare two different revisions of a file in the repository:</p> |
| 63 | <p>fossil finfo myfile: Note the first hash, which is the UUID of the commit |
| 64 | when the file was committed</p> |
| 65 | <p>fossil gdiff --from UUID#1 --to UUID#2 myfile.c</p> |
| 66 | <h2>Cancel changes and go back to previous revision</h2> |
| 67 | <p>fossil revert myfile.c</p> |
| 68 | <p>Fossil does not prompt when reverting a file. It simply reminds the user about the |
| @@ -69,8 +69,8 @@ | |
| 69 | "undo" command, just in case the revert was a mistake.</p> |
| 70 | |
| 71 | |
| 72 | <h2>Close the repository</h2> |
| 73 | <p>fossil close</p> |
| 74 | <p>This will simply remove the _FOSSIL_ at the root of the work directory but |
| 75 | will not delete the files in the work directory. From then on, any use of "fossil" |
| 76 | will trigger an error since there is no longer any connection.</p> |
| 77 |
| --- www/fiveminutes.wiki | |
| +++ www/fiveminutes.wiki | |
| @@ -4,65 +4,65 @@ | |
| 4 | The following document was contributed by Gilles Ganault on 2013-01-08. |
| 5 | </i></b> |
| 6 | </p><hr> |
| 7 | |
| 8 | <h1>Up and running in 5 minutes as a single user</h1> |
| 9 | <p>This short document explains the main basic Fossil commands for a single |
| 10 | user, i.e. with no additional users, with no need to synchronize with some remote |
| 11 | repository, and no need for branching/forking.</p> |
| 12 | |
| 13 | <h2>Create a new repository</h2> |
| 14 | <p>fossil new c:\test.repo</p> |
| 15 | <p>This will create the new SQLite binary file that holds the repository, i.e. |
| 16 | files, tickets, wiki, etc. It can be located anywhere, although it's considered |
| 17 | best practice to keep it outside the work directory where you will work on files |
| 18 | after they've been checked out of the repository.</p> |
| 19 | |
| 20 | <h2>Open the repository</h2> |
| 21 | <p>cd c:\temp\test.fossil</p> |
| 22 | <p>fossil open c:\test.repo</p> |
| 23 | <p>This will check out the last revision of all the files in the repository, |
| 24 | if any, into the current work directory. In addition, it will create a binary |
| 25 | file _FOSSIL_ to keep track of changes (on non-Windows systems it is called |
| 26 | <tt>.fslckout</tt>).</p> |
| 27 | |
| 28 | <h2>Add new files</h2> |
| 29 | <p>fossil add .</p> |
| 30 | <p>To tell Fossil to add new files to the repository. The files aren't actually |
| 31 | added until you run "commit". When using ".", it tells Fossil |
| 32 | to add all the files in the current directory recursively, i.e. including all |
| 33 | the files in all the subdirectories.</p> |
| 34 | <p>Note: To tell Fossil to ignore some extensions:</p> |
| 35 | <p>fossil settings ignore-glob "*.o,*.obj,*.exe" --global</p> |
| 36 | |
| 37 | <h2>Remove files that haven't been committed yet</h2> |
| 38 | <p>fossil delete myfile.c</p> |
| 39 | <p>This will simply remove the item from the list of files that were previously |
| 40 | added through "fossil add".</p> |
| 41 | |
| 42 | <h2>Check current status</h2> |
| 43 | <p>fossil changes</p> |
| 44 | <p>This shows the list of changes that have been done and will be committed the |
| 45 | next time you run "fossil commit". It's a useful command to run before |
| 46 | running "fossil commit" just to check that things are OK before proceeding.</p> |
| 47 | |
| 48 | <h2>Commit changes</h2> |
| 49 | <p>To actually apply the pending changes to the repository, e.g. new files marked |
| 50 | for addition, checked-out files that have been edited and must be checked-in, |
| 51 | etc.</p> |
| 52 | |
| 53 | <p>fossil commit -m "Added stuff"</p> |
| 54 | |
| 55 | If no file names are provided on the command-line then all changes will be checked in, |
| 56 | otherwise just the listed file(s) will be checked in. |
| 57 | |
| 58 | <h2>Compare two revisions of a file</h2> |
| 59 | <p>If you wish to compare the last revision of a file and its checked out version |
| 60 | in your work directory:</p> |
| 61 | <p>fossil gdiff myfile.c</p> |
| 62 | <p>If you wish to compare two different revisions of a file in the repository:</p> |
| 63 | <p>fossil finfo myfile: Note the first hash, which is the UUID of the commit |
| 64 | when the file was committed</p> |
| 65 | <p>fossil gdiff --from UUID#1 --to UUID#2 myfile.c</p> |
| 66 | <h2>Cancel changes and go back to previous revision</h2> |
| 67 | <p>fossil revert myfile.c</p> |
| 68 | <p>Fossil does not prompt when reverting a file. It simply reminds the user about the |
| @@ -69,8 +69,8 @@ | |
| 69 | "undo" command, just in case the revert was a mistake.</p> |
| 70 | |
| 71 | |
| 72 | <h2>Close the repository</h2> |
| 73 | <p>fossil close</p> |
| 74 | <p>This will simply remove the _FOSSIL_ at the root of the work directory but |
| 75 | will not delete the files in the work directory. From then on, any use of "fossil" |
| 76 | will trigger an error since there is no longer any connection.</p> |
| 77 |
+2
-2
| --- www/foss-cklist.wiki | ||
| +++ www/foss-cklist.wiki | ||
| @@ -89,11 +89,11 @@ | ||
| 89 | 89 | |
| 90 | 90 | <li><p>The project has a website. |
| 91 | 91 | |
| 92 | 92 | <li><p>Release version numbers are in the traditional X.Y or X.Y.Z format. |
| 93 | 93 | |
| 94 | -<li><p>Releases can be downloaded as tarball using | |
| 94 | +<li><p>Releases can be downloaded as tarball using | |
| 95 | 95 | gzip or bzip2 compression. |
| 96 | 96 | |
| 97 | 97 | <li><p>Releases unpack into a versioned top-level directory. |
| 98 | 98 | (ex: "projectname-1.2.3/"). |
| 99 | 99 | |
| @@ -102,12 +102,12 @@ | ||
| 102 | 102 | tarball. |
| 103 | 103 | |
| 104 | 104 | <li><p>There are no incompatible licenses in the code. |
| 105 | 105 | |
| 106 | 106 | <li><p>The project has not been blithely proclaimed "public domain" without |
| 107 | -having gone through the tedious and exacting legal steps to actually put it | |
| 107 | +having gone through the tedious and exacting legal steps to actually put it | |
| 108 | 108 | in the public domain. |
| 109 | 109 | |
| 110 | 110 | <li><p>There is an accurate change log in the code and on the website. |
| 111 | 111 | |
| 112 | 112 | <li><p>There is documentation in the code and on the website. |
| 113 | 113 | </ol> |
| 114 | 114 |
| --- www/foss-cklist.wiki | |
| +++ www/foss-cklist.wiki | |
| @@ -89,11 +89,11 @@ | |
| 89 | |
| 90 | <li><p>The project has a website. |
| 91 | |
| 92 | <li><p>Release version numbers are in the traditional X.Y or X.Y.Z format. |
| 93 | |
| 94 | <li><p>Releases can be downloaded as tarball using |
| 95 | gzip or bzip2 compression. |
| 96 | |
| 97 | <li><p>Releases unpack into a versioned top-level directory. |
| 98 | (ex: "projectname-1.2.3/"). |
| 99 | |
| @@ -102,12 +102,12 @@ | |
| 102 | tarball. |
| 103 | |
| 104 | <li><p>There are no incompatible licenses in the code. |
| 105 | |
| 106 | <li><p>The project has not been blithely proclaimed "public domain" without |
| 107 | having gone through the tedious and exacting legal steps to actually put it |
| 108 | in the public domain. |
| 109 | |
| 110 | <li><p>There is an accurate change log in the code and on the website. |
| 111 | |
| 112 | <li><p>There is documentation in the code and on the website. |
| 113 | </ol> |
| 114 |
| --- www/foss-cklist.wiki | |
| +++ www/foss-cklist.wiki | |
| @@ -89,11 +89,11 @@ | |
| 89 | |
| 90 | <li><p>The project has a website. |
| 91 | |
| 92 | <li><p>Release version numbers are in the traditional X.Y or X.Y.Z format. |
| 93 | |
| 94 | <li><p>Releases can be downloaded as tarball using |
| 95 | gzip or bzip2 compression. |
| 96 | |
| 97 | <li><p>Releases unpack into a versioned top-level directory. |
| 98 | (ex: "projectname-1.2.3/"). |
| 99 | |
| @@ -102,12 +102,12 @@ | |
| 102 | tarball. |
| 103 | |
| 104 | <li><p>There are no incompatible licenses in the code. |
| 105 | |
| 106 | <li><p>The project has not been blithely proclaimed "public domain" without |
| 107 | having gone through the tedious and exacting legal steps to actually put it |
| 108 | in the public domain. |
| 109 | |
| 110 | <li><p>There is an accurate change log in the code and on the website. |
| 111 | |
| 112 | <li><p>There is documentation in the code and on the website. |
| 113 | </ol> |
| 114 |
+11
-11
| --- www/fossil-from-msvc.wiki | ||
| +++ www/fossil-from-msvc.wiki | ||
| @@ -11,41 +11,41 @@ | ||
| 11 | 11 | <li>Tools > External Tools, where the items in this list map |
| 12 | 12 | to "External Tool X" that we'll add to our own Fossil |
| 13 | 13 | menu later: </li> |
| 14 | 14 | <ol type="1"> |
| 15 | 15 | <li>Rename the default "[New Tool 1]" to eg. |
| 16 | - "Commit" 2. | |
| 16 | + "Commit" 2. | |
| 17 | 17 | </li> |
| 18 | 18 | <li>Change Command to where Fossil is located eg. |
| 19 | 19 | "c:\fossil.exe"</li> |
| 20 | 20 | <li>Change Arguments to the required command, eg. |
| 21 | - "commit -m". | |
| 21 | + "commit -m". | |
| 22 | 22 | The user will be prompted to type the comment that Commit expects</li> |
| 23 | - <li>Set "Initial Directory" to point it to the work directory | |
| 23 | + <li>Set "Initial Directory" to point it to the work directory | |
| 24 | 24 | where the source files are currently checked out |
| 25 | 25 | by Fossil (eg. c:\Workspace). It's also possible to use system |
| 26 | 26 | variables such as "$(ProjectDir)" instead of hard-coding the path</li> |
| 27 | 27 | <li>Check "Prompt for arguments", since Commit |
| 28 | 28 | requires typing a comment. Useless for commands like Changes |
| 29 | 29 | that don't require arguments</li> |
| 30 | - <li>Uncheck "Close on Exit", so we can see what Fossil says | |
| 31 | - before closing the DOS box. Note that "Use Output Window" | |
| 32 | - will display the output in a child window within the IDE instead of | |
| 30 | + <li>Uncheck "Close on Exit", so we can see what Fossil says | |
| 31 | + before closing the DOS box. Note that "Use Output Window" | |
| 32 | + will display the output in a child window within the IDE instead of | |
| 33 | 33 | opening a DOS box</li> |
| 34 | 34 | <li>Click on OK</li> |
| 35 | 35 | </ol> |
| 36 | 36 | <li>Tools > Customize > Commands</li> |
| 37 | 37 | <ol type="1"> |
| 38 | - <li>With "Menu bar = Menu Bar" selected, click on "Add | |
| 38 | + <li>With "Menu bar = Menu Bar" selected, click on "Add | |
| 39 | 39 | New Menu". A new "Fossil" menu is displayed in the |
| 40 | 40 | IDE's menu bar</li> |
| 41 | 41 | <li>Click on "Modify Selection" to rename it |
| 42 | 42 | "Fossil", and...</li> |
| 43 | 43 | <li>Use the "Move Down" button to move it lower in |
| 44 | 44 | the list</li> |
| 45 | 45 | </ol> |
| 46 | - <li>Still in Customize dialog: In the "Menu bar" combo, select | |
| 47 | - the new Fossil menu you just created, and Click on "Add Command...": | |
| 48 | - From Categories, select Tools, and select "External Command 1". | |
| 49 | - Click on Close. It's unfortunate that the IDE doesn't say which command | |
| 46 | + <li>Still in Customize dialog: In the "Menu bar" combo, select | |
| 47 | + the new Fossil menu you just created, and Click on "Add Command...": | |
| 48 | + From Categories, select Tools, and select "External Command 1". | |
| 49 | + Click on Close. It's unfortunate that the IDE doesn't say which command | |
| 50 | 50 | maps to "External Command X".</li> |
| 51 | 51 | </ol> |
| 52 | 52 |
| --- www/fossil-from-msvc.wiki | |
| +++ www/fossil-from-msvc.wiki | |
| @@ -11,41 +11,41 @@ | |
| 11 | <li>Tools > External Tools, where the items in this list map |
| 12 | to "External Tool X" that we'll add to our own Fossil |
| 13 | menu later: </li> |
| 14 | <ol type="1"> |
| 15 | <li>Rename the default "[New Tool 1]" to eg. |
| 16 | "Commit" 2. |
| 17 | </li> |
| 18 | <li>Change Command to where Fossil is located eg. |
| 19 | "c:\fossil.exe"</li> |
| 20 | <li>Change Arguments to the required command, eg. |
| 21 | "commit -m". |
| 22 | The user will be prompted to type the comment that Commit expects</li> |
| 23 | <li>Set "Initial Directory" to point it to the work directory |
| 24 | where the source files are currently checked out |
| 25 | by Fossil (eg. c:\Workspace). It's also possible to use system |
| 26 | variables such as "$(ProjectDir)" instead of hard-coding the path</li> |
| 27 | <li>Check "Prompt for arguments", since Commit |
| 28 | requires typing a comment. Useless for commands like Changes |
| 29 | that don't require arguments</li> |
| 30 | <li>Uncheck "Close on Exit", so we can see what Fossil says |
| 31 | before closing the DOS box. Note that "Use Output Window" |
| 32 | will display the output in a child window within the IDE instead of |
| 33 | opening a DOS box</li> |
| 34 | <li>Click on OK</li> |
| 35 | </ol> |
| 36 | <li>Tools > Customize > Commands</li> |
| 37 | <ol type="1"> |
| 38 | <li>With "Menu bar = Menu Bar" selected, click on "Add |
| 39 | New Menu". A new "Fossil" menu is displayed in the |
| 40 | IDE's menu bar</li> |
| 41 | <li>Click on "Modify Selection" to rename it |
| 42 | "Fossil", and...</li> |
| 43 | <li>Use the "Move Down" button to move it lower in |
| 44 | the list</li> |
| 45 | </ol> |
| 46 | <li>Still in Customize dialog: In the "Menu bar" combo, select |
| 47 | the new Fossil menu you just created, and Click on "Add Command...": |
| 48 | From Categories, select Tools, and select "External Command 1". |
| 49 | Click on Close. It's unfortunate that the IDE doesn't say which command |
| 50 | maps to "External Command X".</li> |
| 51 | </ol> |
| 52 |
| --- www/fossil-from-msvc.wiki | |
| +++ www/fossil-from-msvc.wiki | |
| @@ -11,41 +11,41 @@ | |
| 11 | <li>Tools > External Tools, where the items in this list map |
| 12 | to "External Tool X" that we'll add to our own Fossil |
| 13 | menu later: </li> |
| 14 | <ol type="1"> |
| 15 | <li>Rename the default "[New Tool 1]" to eg. |
| 16 | "Commit" 2. |
| 17 | </li> |
| 18 | <li>Change Command to where Fossil is located eg. |
| 19 | "c:\fossil.exe"</li> |
| 20 | <li>Change Arguments to the required command, eg. |
| 21 | "commit -m". |
| 22 | The user will be prompted to type the comment that Commit expects</li> |
| 23 | <li>Set "Initial Directory" to point it to the work directory |
| 24 | where the source files are currently checked out |
| 25 | by Fossil (eg. c:\Workspace). It's also possible to use system |
| 26 | variables such as "$(ProjectDir)" instead of hard-coding the path</li> |
| 27 | <li>Check "Prompt for arguments", since Commit |
| 28 | requires typing a comment. Useless for commands like Changes |
| 29 | that don't require arguments</li> |
| 30 | <li>Uncheck "Close on Exit", so we can see what Fossil says |
| 31 | before closing the DOS box. Note that "Use Output Window" |
| 32 | will display the output in a child window within the IDE instead of |
| 33 | opening a DOS box</li> |
| 34 | <li>Click on OK</li> |
| 35 | </ol> |
| 36 | <li>Tools > Customize > Commands</li> |
| 37 | <ol type="1"> |
| 38 | <li>With "Menu bar = Menu Bar" selected, click on "Add |
| 39 | New Menu". A new "Fossil" menu is displayed in the |
| 40 | IDE's menu bar</li> |
| 41 | <li>Click on "Modify Selection" to rename it |
| 42 | "Fossil", and...</li> |
| 43 | <li>Use the "Move Down" button to move it lower in |
| 44 | the list</li> |
| 45 | </ol> |
| 46 | <li>Still in Customize dialog: In the "Menu bar" combo, select |
| 47 | the new Fossil menu you just created, and Click on "Add Command...": |
| 48 | From Categories, select Tools, and select "External Command 1". |
| 49 | Click on Close. It's unfortunate that the IDE doesn't say which command |
| 50 | maps to "External Command X".</li> |
| 51 | </ol> |
| 52 |
+2
-2
| --- www/index.wiki | ||
| +++ www/index.wiki | ||
| @@ -2,11 +2,11 @@ | ||
| 2 | 2 | |
| 3 | 3 | <h3>What Is Fossil?</h3> |
| 4 | 4 | |
| 5 | 5 | <div style='width:200px;float:right;border:2px solid #446979;padding:10px;margin:0px 10px;'> |
| 6 | 6 | <ul> |
| 7 | -<li> [http://www.fossil-scm.org/download.html | Download] | |
| 7 | +<li> [/uv/download.html | Download] | |
| 8 | 8 | <li> [./quickstart.wiki | Quick Start] |
| 9 | 9 | <li> [./build.wiki | Install] |
| 10 | 10 | <li> [../COPYRIGHT-BSD2.txt | License] |
| 11 | 11 | <li> [./faq.wiki | FAQ] |
| 12 | 12 | <li> [./changes.wiki | Change Log] |
| @@ -38,11 +38,11 @@ | ||
| 38 | 38 | ([./webpage-ex.md|examples]) designed to promote situational awareness. |
| 39 | 39 | |
| 40 | 40 | This entire website is just a running instance of Fossil. |
| 41 | 41 | The pages you see here are all [./wikitheory.wiki | wiki] or |
| 42 | 42 | [./embeddeddoc.wiki | embedded documentation] or (in the case of |
| 43 | - the [/uv/download.html|download] page) | |
| 43 | + the [/uv/download.html|download] page) | |
| 44 | 44 | [./unvers.wiki | unversioned files]. |
| 45 | 45 | When you clone Fossil from one of its |
| 46 | 46 | [./selfhost.wiki | self-hosting repositories], |
| 47 | 47 | you get more than just source code - you get this entire website. |
| 48 | 48 | |
| 49 | 49 |
| --- www/index.wiki | |
| +++ www/index.wiki | |
| @@ -2,11 +2,11 @@ | |
| 2 | |
| 3 | <h3>What Is Fossil?</h3> |
| 4 | |
| 5 | <div style='width:200px;float:right;border:2px solid #446979;padding:10px;margin:0px 10px;'> |
| 6 | <ul> |
| 7 | <li> [http://www.fossil-scm.org/download.html | Download] |
| 8 | <li> [./quickstart.wiki | Quick Start] |
| 9 | <li> [./build.wiki | Install] |
| 10 | <li> [../COPYRIGHT-BSD2.txt | License] |
| 11 | <li> [./faq.wiki | FAQ] |
| 12 | <li> [./changes.wiki | Change Log] |
| @@ -38,11 +38,11 @@ | |
| 38 | ([./webpage-ex.md|examples]) designed to promote situational awareness. |
| 39 | |
| 40 | This entire website is just a running instance of Fossil. |
| 41 | The pages you see here are all [./wikitheory.wiki | wiki] or |
| 42 | [./embeddeddoc.wiki | embedded documentation] or (in the case of |
| 43 | the [/uv/download.html|download] page) |
| 44 | [./unvers.wiki | unversioned files]. |
| 45 | When you clone Fossil from one of its |
| 46 | [./selfhost.wiki | self-hosting repositories], |
| 47 | you get more than just source code - you get this entire website. |
| 48 | |
| 49 |
| --- www/index.wiki | |
| +++ www/index.wiki | |
| @@ -2,11 +2,11 @@ | |
| 2 | |
| 3 | <h3>What Is Fossil?</h3> |
| 4 | |
| 5 | <div style='width:200px;float:right;border:2px solid #446979;padding:10px;margin:0px 10px;'> |
| 6 | <ul> |
| 7 | <li> [/uv/download.html | Download] |
| 8 | <li> [./quickstart.wiki | Quick Start] |
| 9 | <li> [./build.wiki | Install] |
| 10 | <li> [../COPYRIGHT-BSD2.txt | License] |
| 11 | <li> [./faq.wiki | FAQ] |
| 12 | <li> [./changes.wiki | Change Log] |
| @@ -38,11 +38,11 @@ | |
| 38 | ([./webpage-ex.md|examples]) designed to promote situational awareness. |
| 39 | |
| 40 | This entire website is just a running instance of Fossil. |
| 41 | The pages you see here are all [./wikitheory.wiki | wiki] or |
| 42 | [./embeddeddoc.wiki | embedded documentation] or (in the case of |
| 43 | the [/uv/download.html|download] page) |
| 44 | [./unvers.wiki | unversioned files]. |
| 45 | When you clone Fossil from one of its |
| 46 | [./selfhost.wiki | self-hosting repositories], |
| 47 | you get more than just source code - you get this entire website. |
| 48 | |
| 49 |
+54
-15
| --- www/inout.wiki | ||
| +++ www/inout.wiki | ||
| @@ -1,10 +1,10 @@ | ||
| 1 | 1 | <title>Import And Export</title> |
| 2 | 2 | |
| 3 | -Fossil has the ability to import and export repositories from and to | |
| 3 | +Fossil has the ability to import and export repositories from and to | |
| 4 | 4 | [http://git-scm.com/ | Git]. And since most other version control |
| 5 | -systems will also import/export from Git, that means that you can | |
| 5 | +systems will also import/export from Git, that means that you can | |
| 6 | 6 | import/export a Fossil repository to most version control systems using |
| 7 | 7 | Git as an intermediary. |
| 8 | 8 | |
| 9 | 9 | <h2>Git → Fossil</h2> |
| 10 | 10 | |
| @@ -20,11 +20,11 @@ | ||
| 20 | 20 | command is the name of a new Fossil repository that is created to hold the Git |
| 21 | 21 | content. |
| 22 | 22 | |
| 23 | 23 | The --git option is not actually required. The git-fast-export file format |
| 24 | 24 | is currently the only VCS interchange format that Fossil understands. But |
| 25 | -future versions of Fossil might be enhanced to understand other VCS | |
| 25 | +future versions of Fossil might be enhanced to understand other VCS | |
| 26 | 26 | interchange formats, and so for compatibility, use of the |
| 27 | 27 | --git option is recommended. |
| 28 | 28 | |
| 29 | 29 | <h2>Fossil → Git</h2> |
| 30 | 30 | |
| @@ -43,21 +43,60 @@ | ||
| 43 | 43 | Note that the "fossil export --git" command only exports the versioned files. |
| 44 | 44 | Tickets and wiki and events are not exported, since Git does not understand |
| 45 | 45 | those concepts. |
| 46 | 46 | |
| 47 | 47 | As with the "import" command, the --git option is not required |
| 48 | -since the git-fast-export file format is currently the only VCS interchange | |
| 48 | +since the git-fast-export file format is currently the only VCS interchange | |
| 49 | 49 | format that Fossil will generate. However, |
| 50 | 50 | future versions of Fossil might add the ability to generate other |
| 51 | -VCS interchange formats, and so for compatibility, the use of the --git | |
| 51 | +VCS interchange formats, and so for compatibility, the use of the --git | |
| 52 | 52 | option recommended. |
| 53 | 53 | |
| 54 | -An anonymous user sends this comment: | |
| 55 | - | |
| 56 | -<blockquote> | |
| 57 | -The main Fossil branch is called "trunk", while the main git branch is | |
| 58 | -called "master". After you've exported your FOSSIL repo to git, you won't | |
| 59 | -see any files and gitk will complain about a missing "HEAD". You can | |
| 60 | -resolve this problem by merging "trunk" with "master" | |
| 61 | -(first verify using git status that you are on the "master" branch): | |
| 62 | -<tt>git merge trunk</tt> | |
| 63 | -</blockquote> | |
| 54 | +<h2>Bidirectional Synchronization</h2> | |
| 55 | +Fossil also has the ability to synchronize with a Git repository via repeated | |
| 56 | +imports and/or exports. To do this, it uses marks files to store a record of | |
| 57 | +artifacts which are known by both Git and Fossil to exist at a given point in | |
| 58 | +time. | |
| 59 | + | |
| 60 | +To illustrate, consider the example of a remote Fossil repository that a | |
| 61 | +user wants to import into a local Git repository. First, the user would clone | |
| 62 | +the remote repository and import it into a new Git repository: | |
| 63 | + | |
| 64 | +<blockquote><pre> | |
| 65 | +fossil clone /path/to/remote/repo.fossil repo.fossil | |
| 66 | +mkdir repo | |
| 67 | +cd repo | |
| 68 | +fossil open ../repo.fossil | |
| 69 | +mkdir ../repo.git | |
| 70 | +cd ../repo.git | |
| 71 | +git init . | |
| 72 | +fossil export --git --export-marks ../repo/fossil.marks \ | |
| 73 | + ../repo.fossil | git fast-import \ | |
| 74 | + --export-marks=../repo/git.marks | |
| 75 | +</pre></blockquote> | |
| 76 | + | |
| 77 | +Once the import has completed, the user would need to <tt>git checkout | |
| 78 | +trunk</tt>. At any point after this, new changes can be imported from the | |
| 79 | +remote Fossil repository: | |
| 80 | + | |
| 81 | +<blockquote><pre> | |
| 82 | +cd ../repo | |
| 83 | +fossil pull | |
| 84 | +cd ../repo.git | |
| 85 | +fossil export --git --import-marks ../repo/fossil.marks \ | |
| 86 | + --export-marks ../repo/fossil.marks \ | |
| 87 | + ../repo.fossil | git fast-import \ | |
| 88 | + --import-marks=../repo/git.marks \ | |
| 89 | + --export-marks=../repo/git.marks | |
| 90 | +</pre></blockquote> | |
| 91 | + | |
| 92 | +Changes in the Git repository can be exported to the Fossil repository and then | |
| 93 | +pushed to the remote: | |
| 94 | + | |
| 95 | +<blockquote><pre> | |
| 96 | +git fast-export --import-marks=../repo/git.marks \ | |
| 97 | + --export-marks=../repo/git.marks --all | fossil import --git \ | |
| 98 | + --incremental --import-marks ../repo/fossil.marks \ | |
| 99 | + --export-marks ../repo/fossil.marks ../repo.fossil | |
| 100 | +cd ../repo | |
| 101 | +fossil push | |
| 102 | +</pre></blockquote> | |
| 64 | 103 |
| --- www/inout.wiki | |
| +++ www/inout.wiki | |
| @@ -1,10 +1,10 @@ | |
| 1 | <title>Import And Export</title> |
| 2 | |
| 3 | Fossil has the ability to import and export repositories from and to |
| 4 | [http://git-scm.com/ | Git]. And since most other version control |
| 5 | systems will also import/export from Git, that means that you can |
| 6 | import/export a Fossil repository to most version control systems using |
| 7 | Git as an intermediary. |
| 8 | |
| 9 | <h2>Git → Fossil</h2> |
| 10 | |
| @@ -20,11 +20,11 @@ | |
| 20 | command is the name of a new Fossil repository that is created to hold the Git |
| 21 | content. |
| 22 | |
| 23 | The --git option is not actually required. The git-fast-export file format |
| 24 | is currently the only VCS interchange format that Fossil understands. But |
| 25 | future versions of Fossil might be enhanced to understand other VCS |
| 26 | interchange formats, and so for compatibility, use of the |
| 27 | --git option is recommended. |
| 28 | |
| 29 | <h2>Fossil → Git</h2> |
| 30 | |
| @@ -43,21 +43,60 @@ | |
| 43 | Note that the "fossil export --git" command only exports the versioned files. |
| 44 | Tickets and wiki and events are not exported, since Git does not understand |
| 45 | those concepts. |
| 46 | |
| 47 | As with the "import" command, the --git option is not required |
| 48 | since the git-fast-export file format is currently the only VCS interchange |
| 49 | format that Fossil will generate. However, |
| 50 | future versions of Fossil might add the ability to generate other |
| 51 | VCS interchange formats, and so for compatibility, the use of the --git |
| 52 | option recommended. |
| 53 | |
| 54 | An anonymous user sends this comment: |
| 55 | |
| 56 | <blockquote> |
| 57 | The main Fossil branch is called "trunk", while the main git branch is |
| 58 | called "master". After you've exported your FOSSIL repo to git, you won't |
| 59 | see any files and gitk will complain about a missing "HEAD". You can |
| 60 | resolve this problem by merging "trunk" with "master" |
| 61 | (first verify using git status that you are on the "master" branch): |
| 62 | <tt>git merge trunk</tt> |
| 63 | </blockquote> |
| 64 |
| --- www/inout.wiki | |
| +++ www/inout.wiki | |
| @@ -1,10 +1,10 @@ | |
| 1 | <title>Import And Export</title> |
| 2 | |
| 3 | Fossil has the ability to import and export repositories from and to |
| 4 | [http://git-scm.com/ | Git]. And since most other version control |
| 5 | systems will also import/export from Git, that means that you can |
| 6 | import/export a Fossil repository to most version control systems using |
| 7 | Git as an intermediary. |
| 8 | |
| 9 | <h2>Git → Fossil</h2> |
| 10 | |
| @@ -20,11 +20,11 @@ | |
| 20 | command is the name of a new Fossil repository that is created to hold the Git |
| 21 | content. |
| 22 | |
| 23 | The --git option is not actually required. The git-fast-export file format |
| 24 | is currently the only VCS interchange format that Fossil understands. But |
| 25 | future versions of Fossil might be enhanced to understand other VCS |
| 26 | interchange formats, and so for compatibility, use of the |
| 27 | --git option is recommended. |
| 28 | |
| 29 | <h2>Fossil → Git</h2> |
| 30 | |
| @@ -43,21 +43,60 @@ | |
| 43 | Note that the "fossil export --git" command only exports the versioned files. |
| 44 | Tickets and wiki and events are not exported, since Git does not understand |
| 45 | those concepts. |
| 46 | |
| 47 | As with the "import" command, the --git option is not required |
| 48 | since the git-fast-export file format is currently the only VCS interchange |
| 49 | format that Fossil will generate. However, |
| 50 | future versions of Fossil might add the ability to generate other |
| 51 | VCS interchange formats, and so for compatibility, the use of the --git |
| 52 | option recommended. |
| 53 | |
| 54 | <h2>Bidirectional Synchronization</h2> |
| 55 | Fossil also has the ability to synchronize with a Git repository via repeated |
| 56 | imports and/or exports. To do this, it uses marks files to store a record of |
| 57 | artifacts which are known by both Git and Fossil to exist at a given point in |
| 58 | time. |
| 59 | |
| 60 | To illustrate, consider the example of a remote Fossil repository that a |
| 61 | user wants to import into a local Git repository. First, the user would clone |
| 62 | the remote repository and import it into a new Git repository: |
| 63 | |
| 64 | <blockquote><pre> |
| 65 | fossil clone /path/to/remote/repo.fossil repo.fossil |
| 66 | mkdir repo |
| 67 | cd repo |
| 68 | fossil open ../repo.fossil |
| 69 | mkdir ../repo.git |
| 70 | cd ../repo.git |
| 71 | git init . |
| 72 | fossil export --git --export-marks ../repo/fossil.marks \ |
| 73 | ../repo.fossil | git fast-import \ |
| 74 | --export-marks=../repo/git.marks |
| 75 | </pre></blockquote> |
| 76 | |
| 77 | Once the import has completed, the user would need to <tt>git checkout |
| 78 | trunk</tt>. At any point after this, new changes can be imported from the |
| 79 | remote Fossil repository: |
| 80 | |
| 81 | <blockquote><pre> |
| 82 | cd ../repo |
| 83 | fossil pull |
| 84 | cd ../repo.git |
| 85 | fossil export --git --import-marks ../repo/fossil.marks \ |
| 86 | --export-marks ../repo/fossil.marks \ |
| 87 | ../repo.fossil | git fast-import \ |
| 88 | --import-marks=../repo/git.marks \ |
| 89 | --export-marks=../repo/git.marks |
| 90 | </pre></blockquote> |
| 91 | |
| 92 | Changes in the Git repository can be exported to the Fossil repository and then |
| 93 | pushed to the remote: |
| 94 | |
| 95 | <blockquote><pre> |
| 96 | git fast-export --import-marks=../repo/git.marks \ |
| 97 | --export-marks=../repo/git.marks --all | fossil import --git \ |
| 98 | --incremental --import-marks ../repo/fossil.marks \ |
| 99 | --export-marks ../repo/fossil.marks ../repo.fossil |
| 100 | cd ../repo |
| 101 | fossil push |
| 102 | </pre></blockquote> |
| 103 |
+13
-13
| --- www/makefile.wiki | ||
| +++ www/makefile.wiki | ||
| @@ -2,24 +2,24 @@ | ||
| 2 | 2 | |
| 3 | 3 | <h1>1.0 Introduction</h1> |
| 4 | 4 | |
| 5 | 5 | The build process for Fossil is tricky in that the source code |
| 6 | 6 | needs to be processed by three different preprocessor programs |
| 7 | -before it is compiled. Most users will download a | |
| 7 | +before it is compiled. Most users will download a | |
| 8 | 8 | [http://www.fossil-scm.org/download.html | precompiled binary] |
| 9 | 9 | so this is of no consequence to them, and even those who |
| 10 | -want to compile the code themselves can use one of the | |
| 11 | -[./build.wiki | existing makefiles]. | |
| 10 | +want to compile the code themselves can use one of the | |
| 11 | +[./build.wiki | existing makefiles]. | |
| 12 | 12 | So must people do not need to be concerned with the |
| 13 | 13 | build complexities of Fossil. But hard-core developers who desire |
| 14 | 14 | a deep understanding of how Fossil is put together can benefit |
| 15 | 15 | from reviewing this article. |
| 16 | 16 | |
| 17 | 17 | <a name="srctour"></a> |
| 18 | 18 | <h1>2.0 Source Code Tour</h1> |
| 19 | 19 | |
| 20 | -The source code for Fossil is found in the | |
| 20 | +The source code for Fossil is found in the | |
| 21 | 21 | [/dir?ci=trunk&name=src | src/] subdirectory of the |
| 22 | 22 | source tree. The src/ subdirectory contains all code, including |
| 23 | 23 | the code for the separate preprocessor programs. |
| 24 | 24 | |
| 25 | 25 | Each preprocessor program is a separate C program implemented in |
| @@ -50,11 +50,11 @@ | ||
| 50 | 50 | The TH1 script engine is implemented using files: |
| 51 | 51 | |
| 52 | 52 | 7. th.c |
| 53 | 53 | 8. th.h |
| 54 | 54 | |
| 55 | -These two files are imports like the SQLite source files, | |
| 55 | +These two files are imports like the SQLite source files, | |
| 56 | 56 | and so are not preprocessed. |
| 57 | 57 | |
| 58 | 58 | The VERSION.h header file is generated from other information sources |
| 59 | 59 | using a small program called: |
| 60 | 60 | |
| @@ -86,11 +86,11 @@ | ||
| 86 | 86 | |
| 87 | 87 | 13. main.mk |
| 88 | 88 | |
| 89 | 89 | The main.mk makefile is invoked from the Makefile in the top-level |
| 90 | 90 | directory. The main.mk is generated by makemake.tcl and should not |
| 91 | -be hand edited. Other makefiles generated by makemake.tcl are in | |
| 91 | +be hand edited. Other makefiles generated by makemake.tcl are in | |
| 92 | 92 | other subdirectories (currently all in the win/ subdirectory). |
| 93 | 93 | |
| 94 | 94 | All the other files in the src/ subdirectory (79 files at the time of |
| 95 | 95 | this writing) are C source code files that are subject to the |
| 96 | 96 | preprocessing steps described below. In the sequel, we will call these |
| @@ -109,11 +109,11 @@ | ||
| 109 | 109 | (The "manifest" and "manifest.uuid" files are automatically generated and |
| 110 | 110 | updated by Fossil itself. See the [/help/setting | fossil set manifest] |
| 111 | 111 | command for additional information.) |
| 112 | 112 | |
| 113 | 113 | The VERSION.h header file is generated by |
| 114 | -a C program: src/mkversion.c. | |
| 114 | +a C program: src/mkversion.c. | |
| 115 | 115 | To run the VERSION.h generator, first compile the src/mkversion.c |
| 116 | 116 | source file into a command-line program (named "mkversion.exe") |
| 117 | 117 | then run: |
| 118 | 118 | |
| 119 | 119 | <blockquote><pre> |
| @@ -126,11 +126,11 @@ | ||
| 126 | 126 | in the root of the source tree are the three arguments and |
| 127 | 127 | the generated VERSION.h file appears on standard output. |
| 128 | 128 | |
| 129 | 129 | The builtin_data.h header file is generated by a C program: src/mkbuiltin.c. |
| 130 | 130 | The builtin_data.h file contains C-langauge byte-array definitions for |
| 131 | -the content of resource files used by Fossil. To generate the | |
| 131 | +the content of resource files used by Fossil. To generate the | |
| 132 | 132 | builtin_data.h file, first compile the mkbuiltin.c program, then run: |
| 133 | 133 | |
| 134 | 134 | <blockquote><pre> |
| 135 | 135 | mkbuiltin.exe diff.tcl <i>OtherFiles...</i> >builtin_data.h |
| 136 | 136 | </pre></blockquote> |
| @@ -163,11 +163,11 @@ | ||
| 163 | 163 | Note that "src.c" in the above is a stand-in for the (79) regular source |
| 164 | 164 | files of Fossil - all source files except for the exceptions described in |
| 165 | 165 | section 2.0 above. |
| 166 | 166 | |
| 167 | 167 | The output of the mkindex program is a header file that is #include-ed by |
| 168 | -the main.c source file during the final compilation step. | |
| 168 | +the main.c source file during the final compilation step. | |
| 169 | 169 | |
| 170 | 170 | <h2>4.2 The translate preprocessor</h2> |
| 171 | 171 | |
| 172 | 172 | The translate preprocessor looks for lines of source code that begin |
| 173 | 173 | with "@" and converts those lines into string constants or (depending on |
| @@ -181,11 +181,11 @@ | ||
| 181 | 181 | </pre></blockquote> |
| 182 | 182 | |
| 183 | 183 | In this case, the "src.c" file represents any single source file from the |
| 184 | 184 | set of ordinary source files as described in section 2.0 above. Note that |
| 185 | 185 | each source file is translated separately. By convention, the names of |
| 186 | -the translated source files are the names of the input sources with a | |
| 186 | +the translated source files are the names of the input sources with a | |
| 187 | 187 | single "_" character at the end. But a new makefile can use any naming |
| 188 | 188 | convention it wants - the "_" is not critical to the build process. |
| 189 | 189 | |
| 190 | 190 | After being translated, the output files (the "src_.c" files) should be |
| 191 | 191 | used for all subsequent preprocessing and compilation steps. |
| @@ -209,16 +209,16 @@ | ||
| 209 | 209 | <blockquote><pre> |
| 210 | 210 | makeheaders src_.c:src.h sqlite3.h th.h VERSION.h |
| 211 | 211 | </pre></blockquote> |
| 212 | 212 | |
| 213 | 213 | In the example above the "src_.c" and "src.h" names represent all of the |
| 214 | -(79) ordinary C source files, each as a separate argument. | |
| 214 | +(79) ordinary C source files, each as a separate argument. | |
| 215 | 215 | |
| 216 | 216 | <h1>5.0 Compilation</h1> |
| 217 | 217 | |
| 218 | 218 | After all generated files have been created and all ordinary source files |
| 219 | -have been preprocessed, the generated and preprocessed files can be | |
| 219 | +have been preprocessed, the generated and preprocessed files can be | |
| 220 | 220 | combined into a single executable using a C compiler. This can be done |
| 221 | 221 | all at once, or each preprocessed source file can be compiled into a |
| 222 | 222 | separate object code file and the resulting object code files linked |
| 223 | 223 | together in a final step. |
| 224 | 224 | |
| @@ -247,11 +247,11 @@ | ||
| 247 | 247 | * -Dmain=sqlite3_main |
| 248 | 248 | * -DSQLITE_OMIT_LOAD_EXTENSION=1 |
| 249 | 249 | |
| 250 | 250 | The "main()" routine in the shell must be changed into sqlite3_main() |
| 251 | 251 | to prevent it from colliding with the real main() in Fossil, and to give |
| 252 | -Fossil an entry point to jump to when the | |
| 252 | +Fossil an entry point to jump to when the | |
| 253 | 253 | [/help/sqlite3 | fossil sql] command is invoked. |
| 254 | 254 | |
| 255 | 255 | All the other source code files can be compiled without any special |
| 256 | 256 | options. |
| 257 | 257 | |
| 258 | 258 |
| --- www/makefile.wiki | |
| +++ www/makefile.wiki | |
| @@ -2,24 +2,24 @@ | |
| 2 | |
| 3 | <h1>1.0 Introduction</h1> |
| 4 | |
| 5 | The build process for Fossil is tricky in that the source code |
| 6 | needs to be processed by three different preprocessor programs |
| 7 | before it is compiled. Most users will download a |
| 8 | [http://www.fossil-scm.org/download.html | precompiled binary] |
| 9 | so this is of no consequence to them, and even those who |
| 10 | want to compile the code themselves can use one of the |
| 11 | [./build.wiki | existing makefiles]. |
| 12 | So must people do not need to be concerned with the |
| 13 | build complexities of Fossil. But hard-core developers who desire |
| 14 | a deep understanding of how Fossil is put together can benefit |
| 15 | from reviewing this article. |
| 16 | |
| 17 | <a name="srctour"></a> |
| 18 | <h1>2.0 Source Code Tour</h1> |
| 19 | |
| 20 | The source code for Fossil is found in the |
| 21 | [/dir?ci=trunk&name=src | src/] subdirectory of the |
| 22 | source tree. The src/ subdirectory contains all code, including |
| 23 | the code for the separate preprocessor programs. |
| 24 | |
| 25 | Each preprocessor program is a separate C program implemented in |
| @@ -50,11 +50,11 @@ | |
| 50 | The TH1 script engine is implemented using files: |
| 51 | |
| 52 | 7. th.c |
| 53 | 8. th.h |
| 54 | |
| 55 | These two files are imports like the SQLite source files, |
| 56 | and so are not preprocessed. |
| 57 | |
| 58 | The VERSION.h header file is generated from other information sources |
| 59 | using a small program called: |
| 60 | |
| @@ -86,11 +86,11 @@ | |
| 86 | |
| 87 | 13. main.mk |
| 88 | |
| 89 | The main.mk makefile is invoked from the Makefile in the top-level |
| 90 | directory. The main.mk is generated by makemake.tcl and should not |
| 91 | be hand edited. Other makefiles generated by makemake.tcl are in |
| 92 | other subdirectories (currently all in the win/ subdirectory). |
| 93 | |
| 94 | All the other files in the src/ subdirectory (79 files at the time of |
| 95 | this writing) are C source code files that are subject to the |
| 96 | preprocessing steps described below. In the sequel, we will call these |
| @@ -109,11 +109,11 @@ | |
| 109 | (The "manifest" and "manifest.uuid" files are automatically generated and |
| 110 | updated by Fossil itself. See the [/help/setting | fossil set manifest] |
| 111 | command for additional information.) |
| 112 | |
| 113 | The VERSION.h header file is generated by |
| 114 | a C program: src/mkversion.c. |
| 115 | To run the VERSION.h generator, first compile the src/mkversion.c |
| 116 | source file into a command-line program (named "mkversion.exe") |
| 117 | then run: |
| 118 | |
| 119 | <blockquote><pre> |
| @@ -126,11 +126,11 @@ | |
| 126 | in the root of the source tree are the three arguments and |
| 127 | the generated VERSION.h file appears on standard output. |
| 128 | |
| 129 | The builtin_data.h header file is generated by a C program: src/mkbuiltin.c. |
| 130 | The builtin_data.h file contains C-langauge byte-array definitions for |
| 131 | the content of resource files used by Fossil. To generate the |
| 132 | builtin_data.h file, first compile the mkbuiltin.c program, then run: |
| 133 | |
| 134 | <blockquote><pre> |
| 135 | mkbuiltin.exe diff.tcl <i>OtherFiles...</i> >builtin_data.h |
| 136 | </pre></blockquote> |
| @@ -163,11 +163,11 @@ | |
| 163 | Note that "src.c" in the above is a stand-in for the (79) regular source |
| 164 | files of Fossil - all source files except for the exceptions described in |
| 165 | section 2.0 above. |
| 166 | |
| 167 | The output of the mkindex program is a header file that is #include-ed by |
| 168 | the main.c source file during the final compilation step. |
| 169 | |
| 170 | <h2>4.2 The translate preprocessor</h2> |
| 171 | |
| 172 | The translate preprocessor looks for lines of source code that begin |
| 173 | with "@" and converts those lines into string constants or (depending on |
| @@ -181,11 +181,11 @@ | |
| 181 | </pre></blockquote> |
| 182 | |
| 183 | In this case, the "src.c" file represents any single source file from the |
| 184 | set of ordinary source files as described in section 2.0 above. Note that |
| 185 | each source file is translated separately. By convention, the names of |
| 186 | the translated source files are the names of the input sources with a |
| 187 | single "_" character at the end. But a new makefile can use any naming |
| 188 | convention it wants - the "_" is not critical to the build process. |
| 189 | |
| 190 | After being translated, the output files (the "src_.c" files) should be |
| 191 | used for all subsequent preprocessing and compilation steps. |
| @@ -209,16 +209,16 @@ | |
| 209 | <blockquote><pre> |
| 210 | makeheaders src_.c:src.h sqlite3.h th.h VERSION.h |
| 211 | </pre></blockquote> |
| 212 | |
| 213 | In the example above the "src_.c" and "src.h" names represent all of the |
| 214 | (79) ordinary C source files, each as a separate argument. |
| 215 | |
| 216 | <h1>5.0 Compilation</h1> |
| 217 | |
| 218 | After all generated files have been created and all ordinary source files |
| 219 | have been preprocessed, the generated and preprocessed files can be |
| 220 | combined into a single executable using a C compiler. This can be done |
| 221 | all at once, or each preprocessed source file can be compiled into a |
| 222 | separate object code file and the resulting object code files linked |
| 223 | together in a final step. |
| 224 | |
| @@ -247,11 +247,11 @@ | |
| 247 | * -Dmain=sqlite3_main |
| 248 | * -DSQLITE_OMIT_LOAD_EXTENSION=1 |
| 249 | |
| 250 | The "main()" routine in the shell must be changed into sqlite3_main() |
| 251 | to prevent it from colliding with the real main() in Fossil, and to give |
| 252 | Fossil an entry point to jump to when the |
| 253 | [/help/sqlite3 | fossil sql] command is invoked. |
| 254 | |
| 255 | All the other source code files can be compiled without any special |
| 256 | options. |
| 257 | |
| 258 |
| --- www/makefile.wiki | |
| +++ www/makefile.wiki | |
| @@ -2,24 +2,24 @@ | |
| 2 | |
| 3 | <h1>1.0 Introduction</h1> |
| 4 | |
| 5 | The build process for Fossil is tricky in that the source code |
| 6 | needs to be processed by three different preprocessor programs |
| 7 | before it is compiled. Most users will download a |
| 8 | [http://www.fossil-scm.org/download.html | precompiled binary] |
| 9 | so this is of no consequence to them, and even those who |
| 10 | want to compile the code themselves can use one of the |
| 11 | [./build.wiki | existing makefiles]. |
| 12 | So must people do not need to be concerned with the |
| 13 | build complexities of Fossil. But hard-core developers who desire |
| 14 | a deep understanding of how Fossil is put together can benefit |
| 15 | from reviewing this article. |
| 16 | |
| 17 | <a name="srctour"></a> |
| 18 | <h1>2.0 Source Code Tour</h1> |
| 19 | |
| 20 | The source code for Fossil is found in the |
| 21 | [/dir?ci=trunk&name=src | src/] subdirectory of the |
| 22 | source tree. The src/ subdirectory contains all code, including |
| 23 | the code for the separate preprocessor programs. |
| 24 | |
| 25 | Each preprocessor program is a separate C program implemented in |
| @@ -50,11 +50,11 @@ | |
| 50 | The TH1 script engine is implemented using files: |
| 51 | |
| 52 | 7. th.c |
| 53 | 8. th.h |
| 54 | |
| 55 | These two files are imports like the SQLite source files, |
| 56 | and so are not preprocessed. |
| 57 | |
| 58 | The VERSION.h header file is generated from other information sources |
| 59 | using a small program called: |
| 60 | |
| @@ -86,11 +86,11 @@ | |
| 86 | |
| 87 | 13. main.mk |
| 88 | |
| 89 | The main.mk makefile is invoked from the Makefile in the top-level |
| 90 | directory. The main.mk is generated by makemake.tcl and should not |
| 91 | be hand edited. Other makefiles generated by makemake.tcl are in |
| 92 | other subdirectories (currently all in the win/ subdirectory). |
| 93 | |
| 94 | All the other files in the src/ subdirectory (79 files at the time of |
| 95 | this writing) are C source code files that are subject to the |
| 96 | preprocessing steps described below. In the sequel, we will call these |
| @@ -109,11 +109,11 @@ | |
| 109 | (The "manifest" and "manifest.uuid" files are automatically generated and |
| 110 | updated by Fossil itself. See the [/help/setting | fossil set manifest] |
| 111 | command for additional information.) |
| 112 | |
| 113 | The VERSION.h header file is generated by |
| 114 | a C program: src/mkversion.c. |
| 115 | To run the VERSION.h generator, first compile the src/mkversion.c |
| 116 | source file into a command-line program (named "mkversion.exe") |
| 117 | then run: |
| 118 | |
| 119 | <blockquote><pre> |
| @@ -126,11 +126,11 @@ | |
| 126 | in the root of the source tree are the three arguments and |
| 127 | the generated VERSION.h file appears on standard output. |
| 128 | |
| 129 | The builtin_data.h header file is generated by a C program: src/mkbuiltin.c. |
| 130 | The builtin_data.h file contains C-langauge byte-array definitions for |
| 131 | the content of resource files used by Fossil. To generate the |
| 132 | builtin_data.h file, first compile the mkbuiltin.c program, then run: |
| 133 | |
| 134 | <blockquote><pre> |
| 135 | mkbuiltin.exe diff.tcl <i>OtherFiles...</i> >builtin_data.h |
| 136 | </pre></blockquote> |
| @@ -163,11 +163,11 @@ | |
| 163 | Note that "src.c" in the above is a stand-in for the (79) regular source |
| 164 | files of Fossil - all source files except for the exceptions described in |
| 165 | section 2.0 above. |
| 166 | |
| 167 | The output of the mkindex program is a header file that is #include-ed by |
| 168 | the main.c source file during the final compilation step. |
| 169 | |
| 170 | <h2>4.2 The translate preprocessor</h2> |
| 171 | |
| 172 | The translate preprocessor looks for lines of source code that begin |
| 173 | with "@" and converts those lines into string constants or (depending on |
| @@ -181,11 +181,11 @@ | |
| 181 | </pre></blockquote> |
| 182 | |
| 183 | In this case, the "src.c" file represents any single source file from the |
| 184 | set of ordinary source files as described in section 2.0 above. Note that |
| 185 | each source file is translated separately. By convention, the names of |
| 186 | the translated source files are the names of the input sources with a |
| 187 | single "_" character at the end. But a new makefile can use any naming |
| 188 | convention it wants - the "_" is not critical to the build process. |
| 189 | |
| 190 | After being translated, the output files (the "src_.c" files) should be |
| 191 | used for all subsequent preprocessing and compilation steps. |
| @@ -209,16 +209,16 @@ | |
| 209 | <blockquote><pre> |
| 210 | makeheaders src_.c:src.h sqlite3.h th.h VERSION.h |
| 211 | </pre></blockquote> |
| 212 | |
| 213 | In the example above the "src_.c" and "src.h" names represent all of the |
| 214 | (79) ordinary C source files, each as a separate argument. |
| 215 | |
| 216 | <h1>5.0 Compilation</h1> |
| 217 | |
| 218 | After all generated files have been created and all ordinary source files |
| 219 | have been preprocessed, the generated and preprocessed files can be |
| 220 | combined into a single executable using a C compiler. This can be done |
| 221 | all at once, or each preprocessed source file can be compiled into a |
| 222 | separate object code file and the resulting object code files linked |
| 223 | together in a final step. |
| 224 | |
| @@ -247,11 +247,11 @@ | |
| 247 | * -Dmain=sqlite3_main |
| 248 | * -DSQLITE_OMIT_LOAD_EXTENSION=1 |
| 249 | |
| 250 | The "main()" routine in the shell must be changed into sqlite3_main() |
| 251 | to prevent it from colliding with the real main() in Fossil, and to give |
| 252 | Fossil an entry point to jump to when the |
| 253 | [/help/sqlite3 | fossil sql] command is invoked. |
| 254 | |
| 255 | All the other source code files can be compiled without any special |
| 256 | options. |
| 257 | |
| 258 |
+48
-60
| --- www/mkdownload.tcl | ||
| +++ www/mkdownload.tcl | ||
| @@ -1,41 +1,17 @@ | ||
| 1 | 1 | #!/usr/bin/tclsh |
| 2 | 2 | # |
| 3 | -# Run this script to build the "download.html" page. Also generate | |
| 4 | -# the fossil_download_checksums.html page. | |
| 3 | +# Run this script to build and install the "download.html" page of | |
| 4 | +# unversioned comment. | |
| 5 | +# | |
| 6 | +# Also generate the fossil_download_checksums.html page. | |
| 5 | 7 | # |
| 6 | 8 | # |
| 7 | 9 | set out [open download.html w] |
| 8 | 10 | fconfigure $out -encoding utf-8 -translation lf |
| 9 | 11 | puts $out \ |
| 10 | -{<!DOCTYPE html> | |
| 11 | -<html> | |
| 12 | - <head> | |
| 13 | - <base href="https://www.fossil-scm.org/download.html" /> | |
| 14 | - <title>Fossil: Download</title> | |
| 15 | - <link rel="alternate" type="application/rss+xml" title="RSS Feed" | |
| 16 | - href="/fossil/timeline.rss" /> | |
| 17 | - <link rel="stylesheet" href="/fossil/style.css?default" type="text/css" | |
| 18 | - media="screen" /> | |
| 19 | - </head> | |
| 20 | - | |
| 21 | - <body> | |
| 22 | - <div class="header"> | |
| 23 | - <div class="title"><h1>Fossil</h1>Download</div> | |
| 24 | - </div> | |
| 25 | - <div class="mainmenu"> | |
| 26 | -<a href='/fossil/doc/trunk/www/index.wiki'>Home</a> | |
| 27 | -<a href='/fossil/timeline?y=ci'>Timeline</a> | |
| 28 | -<a href='/fossil/dir?ci=tip'>Code</a> | |
| 29 | -<a href='/fossil/doc/trunk/www/permutedindex.html'>Docs</a> | |
| 30 | -<a href='/fossil/brlist'>Branches</a> | |
| 31 | -<a href='/fossil/ticket'>Tickets</a> | |
| 32 | -<a href='/fossil/wiki'>Wiki</a> | |
| 33 | -<a href='/download.html' class='active'>Download</a> | |
| 34 | -</div> | |
| 35 | -<div class="content"> | |
| 36 | -<p> | |
| 12 | +{<div class='fossil-doc' data-title='Download Page'> | |
| 37 | 13 | |
| 38 | 14 | <center><font size=4>} |
| 39 | 15 | puts $out \ |
| 40 | 16 | "<b>To install Fossil →</b> download the stand-alone executable" |
| 41 | 17 | puts $out \ |
| @@ -45,46 +21,57 @@ | ||
| 45 | 21 | <a href="http://download.opensuse.org/repositories/home:/rmax:/fossil/"> |
| 46 | 22 | here.</a> |
| 47 | 23 | Cryptographic checksums for download files are |
| 48 | 24 | <a href="http://www.hwaci.com/fossil_download_checksums.html">here</a>. |
| 49 | 25 | </small></p> |
| 50 | -</center> | |
| 51 | - | |
| 52 | 26 | <table cellpadding="10"> |
| 53 | 27 | } |
| 54 | 28 | |
| 55 | -# Find all all unique timestamps. | |
| 29 | +# Find all unique timestamps. | |
| 56 | 30 | # |
| 57 | -foreach file [glob -nocomplain download/fossil-*.zip] { | |
| 58 | - if {[regexp -- {-(\d\.\d+).zip$} $file all version]} { | |
| 31 | +set in [open {|fossil uv list} rb] | |
| 32 | +while {[gets $in line]>0} { | |
| 33 | + set fn [lindex $line 5] | |
| 34 | + set filesize($fn) [lindex $line 3] | |
| 35 | + if {[regexp -- {-(\d\.\d+)\.(tar\.gz|zip)$} $fn all version]} { | |
| 36 | + set filehash($fn) [lindex $line 1] | |
| 59 | 37 | set avers($version) 1 |
| 60 | 38 | } |
| 61 | 39 | } |
| 40 | +close $in | |
| 41 | + | |
| 42 | +set vdate(1.36) 2016-10-24 | |
| 43 | +set vdate(1.35) 2016-06-14 | |
| 44 | +set vdate(1.34) 2016-11-02 | |
| 62 | 45 | |
| 63 | 46 | # Do all versions from newest to oldest |
| 64 | 47 | # |
| 65 | 48 | foreach vers [lsort -decr -real [array names avers]] { |
| 66 | - set hr "/fossil/timeline?c=version-$vers;y=ci" | |
| 49 | + # set hr "../timeline?c=version-$vers;y=ci" | |
| 50 | + set v2 v[string map {. _} $vers] | |
| 51 | + set hr "../doc/trunk/www/changes.wiki#$v2" | |
| 67 | 52 | puts $out "<tr><td colspan=6 align=left><hr>" |
| 68 | - puts $out "<center><b><a href=\"$hr\">Version $vers</a></b></center>" | |
| 53 | + puts $out "<center><b><a href=\"$hr\">Version $vers</a>" | |
| 54 | + if {[info exists vdate($vers)]} { | |
| 55 | + set hr2 "../timeline?c=version-$vers&y=ci" | |
| 56 | + puts $out " (<a href='$hr2'>$vdate($vers)</a>)" | |
| 57 | + } | |
| 58 | + puts $out "</b></center>" | |
| 69 | 59 | puts $out "</td></tr>" |
| 70 | 60 | puts $out "<tr>" |
| 71 | 61 | |
| 72 | 62 | foreach {prefix img desc} { |
| 73 | 63 | fossil-linux-x86 linux.gif {Linux 3.x x86} |
| 74 | - fossil-macosx-x86 mac.gif {Mac 10.x x86} | |
| 64 | + fossil-macosx mac.gif {Mac 10.x x86} | |
| 75 | 65 | fossil-openbsd-x86 openbsd.gif {OpenBSD 5.x x86} |
| 76 | 66 | fossil-w32 win32.gif {Windows} |
| 77 | 67 | fossil-src src.gif {Source Tarball} |
| 78 | 68 | } { |
| 79 | - set basename download/$prefix-$vers | |
| 80 | - set filename $basename.tar.gz | |
| 81 | - if {![file exists $basename.tar.gz]} { | |
| 82 | - set filename $basename.zip | |
| 83 | - } | |
| 84 | - if {[file exists $filename]} { | |
| 85 | - set size [file size $filename] | |
| 69 | + set glob download/$prefix*-$vers* | |
| 70 | + set filename [array names filesize $glob] | |
| 71 | + if {[info exists filesize($filename)]} { | |
| 72 | + set size [set filesize($filename)] | |
| 86 | 73 | set units bytes |
| 87 | 74 | if {$size>1024*1024} { |
| 88 | 75 | set size [format %.2f [expr {$size/(1024.0*1024.0)}]] |
| 89 | 76 | set units MiB |
| 90 | 77 | } elseif {$size>1024} { |
| @@ -97,26 +84,23 @@ | ||
| 97 | 84 | } else { |
| 98 | 85 | puts $out "<td> </td>" |
| 99 | 86 | } |
| 100 | 87 | } |
| 101 | 88 | puts $out "</tr>" |
| 102 | - if {[file exists download/releasenotes-$vers.html]} { | |
| 103 | - puts $out "<tr><td colspan=6 align=left>" | |
| 104 | - set rn [open download/releasenotes-$vers.html] | |
| 105 | - fconfigure $rn -encoding utf-8 | |
| 106 | - puts $out "[read $rn]" | |
| 107 | - close $rn | |
| 108 | - puts $out "</td></tr>" | |
| 109 | - } | |
| 89 | +# | |
| 90 | +# if {[info exists filesize(download/releasenotes-$vers.html)]} { | |
| 91 | +# puts $out "<tr><td colspan=6 align=left>" | |
| 92 | +# set rn [|open uv cat download/releasenotes-$vers.html] | |
| 93 | +# fconfigure $rn -encoding utf-8 | |
| 94 | +# puts $out "[read $rn]" | |
| 95 | +# close $rn | |
| 96 | +# puts $out "</td></tr>" | |
| 97 | +# } | |
| 110 | 98 | } |
| 111 | 99 | puts $out "<tr><td colspan=5><hr></td></tr>" |
| 112 | 100 | |
| 113 | -puts $out {</table></div> | |
| 114 | -</body> | |
| 115 | -</html> | |
| 116 | -} | |
| 117 | - | |
| 101 | +puts $out {</table></center></div>} | |
| 118 | 102 | close $out |
| 119 | 103 | |
| 120 | 104 | # Generate the checksum page |
| 121 | 105 | # |
| 122 | 106 | set out [open fossil_download_checksums.html w] |
| @@ -128,11 +112,15 @@ | ||
| 128 | 112 | <p>The following table shows the SHA1 checksums for the precompiled |
| 129 | 113 | binaries available on the |
| 130 | 114 | <a href="/download.html">Fossil website</a>.</p> |
| 131 | 115 | <pre>} |
| 132 | 116 | |
| 133 | -foreach file [lsort [glob -nocomplain download/fossil-*.zip]] { | |
| 134 | - set sha1sum [lindex [exec sha1sum $file] 0] | |
| 135 | - puts $out "$sha1sum [file tail $file]" | |
| 117 | +foreach {line} [split [exec fossil sql "SELECT hash, name FROM unversioned\ | |
| 118 | + WHERE name GLOB '*.tar.gz' OR\ | |
| 119 | + name GLOB '*.zip'"] \n] { | |
| 120 | + set x [split $line |] | |
| 121 | + set hash [lindex $x 0] | |
| 122 | + set nm [file tail [lindex $x 1]] | |
| 123 | + puts $out "$hash $nm" | |
| 136 | 124 | } |
| 137 | 125 | puts $out {</pre></body></html>} |
| 138 | 126 | close $out |
| 139 | 127 |
| --- www/mkdownload.tcl | |
| +++ www/mkdownload.tcl | |
| @@ -1,41 +1,17 @@ | |
| 1 | #!/usr/bin/tclsh |
| 2 | # |
| 3 | # Run this script to build the "download.html" page. Also generate |
| 4 | # the fossil_download_checksums.html page. |
| 5 | # |
| 6 | # |
| 7 | set out [open download.html w] |
| 8 | fconfigure $out -encoding utf-8 -translation lf |
| 9 | puts $out \ |
| 10 | {<!DOCTYPE html> |
| 11 | <html> |
| 12 | <head> |
| 13 | <base href="https://www.fossil-scm.org/download.html" /> |
| 14 | <title>Fossil: Download</title> |
| 15 | <link rel="alternate" type="application/rss+xml" title="RSS Feed" |
| 16 | href="/fossil/timeline.rss" /> |
| 17 | <link rel="stylesheet" href="/fossil/style.css?default" type="text/css" |
| 18 | media="screen" /> |
| 19 | </head> |
| 20 | |
| 21 | <body> |
| 22 | <div class="header"> |
| 23 | <div class="title"><h1>Fossil</h1>Download</div> |
| 24 | </div> |
| 25 | <div class="mainmenu"> |
| 26 | <a href='/fossil/doc/trunk/www/index.wiki'>Home</a> |
| 27 | <a href='/fossil/timeline?y=ci'>Timeline</a> |
| 28 | <a href='/fossil/dir?ci=tip'>Code</a> |
| 29 | <a href='/fossil/doc/trunk/www/permutedindex.html'>Docs</a> |
| 30 | <a href='/fossil/brlist'>Branches</a> |
| 31 | <a href='/fossil/ticket'>Tickets</a> |
| 32 | <a href='/fossil/wiki'>Wiki</a> |
| 33 | <a href='/download.html' class='active'>Download</a> |
| 34 | </div> |
| 35 | <div class="content"> |
| 36 | <p> |
| 37 | |
| 38 | <center><font size=4>} |
| 39 | puts $out \ |
| 40 | "<b>To install Fossil →</b> download the stand-alone executable" |
| 41 | puts $out \ |
| @@ -45,46 +21,57 @@ | |
| 45 | <a href="http://download.opensuse.org/repositories/home:/rmax:/fossil/"> |
| 46 | here.</a> |
| 47 | Cryptographic checksums for download files are |
| 48 | <a href="http://www.hwaci.com/fossil_download_checksums.html">here</a>. |
| 49 | </small></p> |
| 50 | </center> |
| 51 | |
| 52 | <table cellpadding="10"> |
| 53 | } |
| 54 | |
| 55 | # Find all all unique timestamps. |
| 56 | # |
| 57 | foreach file [glob -nocomplain download/fossil-*.zip] { |
| 58 | if {[regexp -- {-(\d\.\d+).zip$} $file all version]} { |
| 59 | set avers($version) 1 |
| 60 | } |
| 61 | } |
| 62 | |
| 63 | # Do all versions from newest to oldest |
| 64 | # |
| 65 | foreach vers [lsort -decr -real [array names avers]] { |
| 66 | set hr "/fossil/timeline?c=version-$vers;y=ci" |
| 67 | puts $out "<tr><td colspan=6 align=left><hr>" |
| 68 | puts $out "<center><b><a href=\"$hr\">Version $vers</a></b></center>" |
| 69 | puts $out "</td></tr>" |
| 70 | puts $out "<tr>" |
| 71 | |
| 72 | foreach {prefix img desc} { |
| 73 | fossil-linux-x86 linux.gif {Linux 3.x x86} |
| 74 | fossil-macosx-x86 mac.gif {Mac 10.x x86} |
| 75 | fossil-openbsd-x86 openbsd.gif {OpenBSD 5.x x86} |
| 76 | fossil-w32 win32.gif {Windows} |
| 77 | fossil-src src.gif {Source Tarball} |
| 78 | } { |
| 79 | set basename download/$prefix-$vers |
| 80 | set filename $basename.tar.gz |
| 81 | if {![file exists $basename.tar.gz]} { |
| 82 | set filename $basename.zip |
| 83 | } |
| 84 | if {[file exists $filename]} { |
| 85 | set size [file size $filename] |
| 86 | set units bytes |
| 87 | if {$size>1024*1024} { |
| 88 | set size [format %.2f [expr {$size/(1024.0*1024.0)}]] |
| 89 | set units MiB |
| 90 | } elseif {$size>1024} { |
| @@ -97,26 +84,23 @@ | |
| 97 | } else { |
| 98 | puts $out "<td> </td>" |
| 99 | } |
| 100 | } |
| 101 | puts $out "</tr>" |
| 102 | if {[file exists download/releasenotes-$vers.html]} { |
| 103 | puts $out "<tr><td colspan=6 align=left>" |
| 104 | set rn [open download/releasenotes-$vers.html] |
| 105 | fconfigure $rn -encoding utf-8 |
| 106 | puts $out "[read $rn]" |
| 107 | close $rn |
| 108 | puts $out "</td></tr>" |
| 109 | } |
| 110 | } |
| 111 | puts $out "<tr><td colspan=5><hr></td></tr>" |
| 112 | |
| 113 | puts $out {</table></div> |
| 114 | </body> |
| 115 | </html> |
| 116 | } |
| 117 | |
| 118 | close $out |
| 119 | |
| 120 | # Generate the checksum page |
| 121 | # |
| 122 | set out [open fossil_download_checksums.html w] |
| @@ -128,11 +112,15 @@ | |
| 128 | <p>The following table shows the SHA1 checksums for the precompiled |
| 129 | binaries available on the |
| 130 | <a href="/download.html">Fossil website</a>.</p> |
| 131 | <pre>} |
| 132 | |
| 133 | foreach file [lsort [glob -nocomplain download/fossil-*.zip]] { |
| 134 | set sha1sum [lindex [exec sha1sum $file] 0] |
| 135 | puts $out "$sha1sum [file tail $file]" |
| 136 | } |
| 137 | puts $out {</pre></body></html>} |
| 138 | close $out |
| 139 |
| --- www/mkdownload.tcl | |
| +++ www/mkdownload.tcl | |
| @@ -1,41 +1,17 @@ | |
| 1 | #!/usr/bin/tclsh |
| 2 | # |
| 3 | # Run this script to build and install the "download.html" page of |
| 4 | # unversioned comment. |
| 5 | # |
| 6 | # Also generate the fossil_download_checksums.html page. |
| 7 | # |
| 8 | # |
| 9 | set out [open download.html w] |
| 10 | fconfigure $out -encoding utf-8 -translation lf |
| 11 | puts $out \ |
| 12 | {<div class='fossil-doc' data-title='Download Page'> |
| 13 | |
| 14 | <center><font size=4>} |
| 15 | puts $out \ |
| 16 | "<b>To install Fossil →</b> download the stand-alone executable" |
| 17 | puts $out \ |
| @@ -45,46 +21,57 @@ | |
| 21 | <a href="http://download.opensuse.org/repositories/home:/rmax:/fossil/"> |
| 22 | here.</a> |
| 23 | Cryptographic checksums for download files are |
| 24 | <a href="http://www.hwaci.com/fossil_download_checksums.html">here</a>. |
| 25 | </small></p> |
| 26 | <table cellpadding="10"> |
| 27 | } |
| 28 | |
| 29 | # Find all unique timestamps. |
| 30 | # |
| 31 | set in [open {|fossil uv list} rb] |
| 32 | while {[gets $in line]>0} { |
| 33 | set fn [lindex $line 5] |
| 34 | set filesize($fn) [lindex $line 3] |
| 35 | if {[regexp -- {-(\d\.\d+)\.(tar\.gz|zip)$} $fn all version]} { |
| 36 | set filehash($fn) [lindex $line 1] |
| 37 | set avers($version) 1 |
| 38 | } |
| 39 | } |
| 40 | close $in |
| 41 | |
| 42 | set vdate(1.36) 2016-10-24 |
| 43 | set vdate(1.35) 2016-06-14 |
| 44 | set vdate(1.34) 2016-11-02 |
| 45 | |
| 46 | # Do all versions from newest to oldest |
| 47 | # |
| 48 | foreach vers [lsort -decr -real [array names avers]] { |
| 49 | # set hr "../timeline?c=version-$vers;y=ci" |
| 50 | set v2 v[string map {. _} $vers] |
| 51 | set hr "../doc/trunk/www/changes.wiki#$v2" |
| 52 | puts $out "<tr><td colspan=6 align=left><hr>" |
| 53 | puts $out "<center><b><a href=\"$hr\">Version $vers</a>" |
| 54 | if {[info exists vdate($vers)]} { |
| 55 | set hr2 "../timeline?c=version-$vers&y=ci" |
| 56 | puts $out " (<a href='$hr2'>$vdate($vers)</a>)" |
| 57 | } |
| 58 | puts $out "</b></center>" |
| 59 | puts $out "</td></tr>" |
| 60 | puts $out "<tr>" |
| 61 | |
| 62 | foreach {prefix img desc} { |
| 63 | fossil-linux-x86 linux.gif {Linux 3.x x86} |
| 64 | fossil-macosx mac.gif {Mac 10.x x86} |
| 65 | fossil-openbsd-x86 openbsd.gif {OpenBSD 5.x x86} |
| 66 | fossil-w32 win32.gif {Windows} |
| 67 | fossil-src src.gif {Source Tarball} |
| 68 | } { |
| 69 | set glob download/$prefix*-$vers* |
| 70 | set filename [array names filesize $glob] |
| 71 | if {[info exists filesize($filename)]} { |
| 72 | set size [set filesize($filename)] |
| 73 | set units bytes |
| 74 | if {$size>1024*1024} { |
| 75 | set size [format %.2f [expr {$size/(1024.0*1024.0)}]] |
| 76 | set units MiB |
| 77 | } elseif {$size>1024} { |
| @@ -97,26 +84,23 @@ | |
| 84 | } else { |
| 85 | puts $out "<td> </td>" |
| 86 | } |
| 87 | } |
| 88 | puts $out "</tr>" |
| 89 | # |
| 90 | # if {[info exists filesize(download/releasenotes-$vers.html)]} { |
| 91 | # puts $out "<tr><td colspan=6 align=left>" |
| 92 | # set rn [|open uv cat download/releasenotes-$vers.html] |
| 93 | # fconfigure $rn -encoding utf-8 |
| 94 | # puts $out "[read $rn]" |
| 95 | # close $rn |
| 96 | # puts $out "</td></tr>" |
| 97 | # } |
| 98 | } |
| 99 | puts $out "<tr><td colspan=5><hr></td></tr>" |
| 100 | |
| 101 | puts $out {</table></center></div>} |
| 102 | close $out |
| 103 | |
| 104 | # Generate the checksum page |
| 105 | # |
| 106 | set out [open fossil_download_checksums.html w] |
| @@ -128,11 +112,15 @@ | |
| 112 | <p>The following table shows the SHA1 checksums for the precompiled |
| 113 | binaries available on the |
| 114 | <a href="/download.html">Fossil website</a>.</p> |
| 115 | <pre>} |
| 116 | |
| 117 | foreach {line} [split [exec fossil sql "SELECT hash, name FROM unversioned\ |
| 118 | WHERE name GLOB '*.tar.gz' OR\ |
| 119 | name GLOB '*.zip'"] \n] { |
| 120 | set x [split $line |] |
| 121 | set hash [lindex $x 0] |
| 122 | set nm [file tail [lindex $x 1]] |
| 123 | puts $out "$hash $nm" |
| 124 | } |
| 125 | puts $out {</pre></body></html>} |
| 126 | close $out |
| 127 |
+9
-5
| --- www/mkindex.tcl | ||
| +++ www/mkindex.tcl | ||
| @@ -1,6 +1,6 @@ | ||
| 1 | -#!/bin/sh | |
| 1 | +#!/usr/bin/env tclsh | |
| 2 | 2 | # |
| 3 | 3 | # Run this TCL script to generate a WIKI page that contains a |
| 4 | 4 | # permuted index of the various documentation files. |
| 5 | 5 | # |
| 6 | 6 | # tclsh mkindex.tcl |
| @@ -78,21 +78,24 @@ | ||
| 78 | 78 | wikitheory.wiki {Wiki In Fossil} |
| 79 | 79 | /wiki_rules {Wiki Formatting Rules} |
| 80 | 80 | } |
| 81 | 81 | |
| 82 | 82 | set permindex {} |
| 83 | -set stopwords {fossil and a in of on the to are about used by for or} | |
| 83 | +set stopwords { | |
| 84 | + a about against and are as by for fossil from in of on or should the to use | |
| 85 | + used with | |
| 86 | +} | |
| 84 | 87 | foreach {file title} $doclist { |
| 85 | 88 | set n [llength $title] |
| 86 | 89 | regsub -all {\s+} $title { } title |
| 87 | - lappend permindex [list $title $file] | |
| 90 | + lappend permindex [list $title $file 1] | |
| 88 | 91 | for {set i 0} {$i<$n-1} {incr i} { |
| 89 | 92 | set prefix [lrange $title 0 $i] |
| 90 | 93 | set suffix [lrange $title [expr {$i+1}] end] |
| 91 | 94 | set firstword [string tolower [lindex $suffix 0]] |
| 92 | 95 | if {[lsearch $stopwords $firstword]<0} { |
| 93 | - lappend permindex [list "$suffix — $prefix" $file] | |
| 96 | + lappend permindex [list "$suffix — $prefix" $file 0] | |
| 94 | 97 | } |
| 95 | 98 | } |
| 96 | 99 | } |
| 97 | 100 | set permindex [lsort -dict -index 0 $permindex] |
| 98 | 101 | set out [open permutedindex.html w] |
| @@ -118,10 +121,11 @@ | ||
| 118 | 121 | </ul> |
| 119 | 122 | <a name="pindex"></a> |
| 120 | 123 | <h2>Permuted Index:</h2> |
| 121 | 124 | <ul>} |
| 122 | 125 | foreach entry $permindex { |
| 123 | - foreach {title file} $entry break | |
| 126 | + foreach {title file bold} $entry break | |
| 127 | + if {$bold} {set title <b>$title</b>} | |
| 124 | 128 | if {[string match /* $file]} {set file ../../..$file} |
| 125 | 129 | puts $out "<li><a href=\"$file\">$title</a></li>" |
| 126 | 130 | } |
| 127 | 131 | puts $out "</ul></div>" |
| 128 | 132 |
| --- www/mkindex.tcl | |
| +++ www/mkindex.tcl | |
| @@ -1,6 +1,6 @@ | |
| 1 | #!/bin/sh |
| 2 | # |
| 3 | # Run this TCL script to generate a WIKI page that contains a |
| 4 | # permuted index of the various documentation files. |
| 5 | # |
| 6 | # tclsh mkindex.tcl |
| @@ -78,21 +78,24 @@ | |
| 78 | wikitheory.wiki {Wiki In Fossil} |
| 79 | /wiki_rules {Wiki Formatting Rules} |
| 80 | } |
| 81 | |
| 82 | set permindex {} |
| 83 | set stopwords {fossil and a in of on the to are about used by for or} |
| 84 | foreach {file title} $doclist { |
| 85 | set n [llength $title] |
| 86 | regsub -all {\s+} $title { } title |
| 87 | lappend permindex [list $title $file] |
| 88 | for {set i 0} {$i<$n-1} {incr i} { |
| 89 | set prefix [lrange $title 0 $i] |
| 90 | set suffix [lrange $title [expr {$i+1}] end] |
| 91 | set firstword [string tolower [lindex $suffix 0]] |
| 92 | if {[lsearch $stopwords $firstword]<0} { |
| 93 | lappend permindex [list "$suffix — $prefix" $file] |
| 94 | } |
| 95 | } |
| 96 | } |
| 97 | set permindex [lsort -dict -index 0 $permindex] |
| 98 | set out [open permutedindex.html w] |
| @@ -118,10 +121,11 @@ | |
| 118 | </ul> |
| 119 | <a name="pindex"></a> |
| 120 | <h2>Permuted Index:</h2> |
| 121 | <ul>} |
| 122 | foreach entry $permindex { |
| 123 | foreach {title file} $entry break |
| 124 | if {[string match /* $file]} {set file ../../..$file} |
| 125 | puts $out "<li><a href=\"$file\">$title</a></li>" |
| 126 | } |
| 127 | puts $out "</ul></div>" |
| 128 |
| --- www/mkindex.tcl | |
| +++ www/mkindex.tcl | |
| @@ -1,6 +1,6 @@ | |
| 1 | #!/usr/bin/env tclsh |
| 2 | # |
| 3 | # Run this TCL script to generate a WIKI page that contains a |
| 4 | # permuted index of the various documentation files. |
| 5 | # |
| 6 | # tclsh mkindex.tcl |
| @@ -78,21 +78,24 @@ | |
| 78 | wikitheory.wiki {Wiki In Fossil} |
| 79 | /wiki_rules {Wiki Formatting Rules} |
| 80 | } |
| 81 | |
| 82 | set permindex {} |
| 83 | set stopwords { |
| 84 | a about against and are as by for fossil from in of on or should the to use |
| 85 | used with |
| 86 | } |
| 87 | foreach {file title} $doclist { |
| 88 | set n [llength $title] |
| 89 | regsub -all {\s+} $title { } title |
| 90 | lappend permindex [list $title $file 1] |
| 91 | for {set i 0} {$i<$n-1} {incr i} { |
| 92 | set prefix [lrange $title 0 $i] |
| 93 | set suffix [lrange $title [expr {$i+1}] end] |
| 94 | set firstword [string tolower [lindex $suffix 0]] |
| 95 | if {[lsearch $stopwords $firstword]<0} { |
| 96 | lappend permindex [list "$suffix — $prefix" $file 0] |
| 97 | } |
| 98 | } |
| 99 | } |
| 100 | set permindex [lsort -dict -index 0 $permindex] |
| 101 | set out [open permutedindex.html w] |
| @@ -118,10 +121,11 @@ | |
| 121 | </ul> |
| 122 | <a name="pindex"></a> |
| 123 | <h2>Permuted Index:</h2> |
| 124 | <ul>} |
| 125 | foreach entry $permindex { |
| 126 | foreach {title file bold} $entry break |
| 127 | if {$bold} {set title <b>$title</b>} |
| 128 | if {[string match /* $file]} {set file ../../..$file} |
| 129 | puts $out "<li><a href=\"$file\">$title</a></li>" |
| 130 | } |
| 131 | puts $out "</ul></div>" |
| 132 |
+1
-1
| --- www/newrepo.wiki | ||
| +++ www/newrepo.wiki | ||
| @@ -53,11 +53,11 @@ | ||
| 53 | 53 | |
| 54 | 54 | <verbatim> |
| 55 | 55 | stephan@ludo:~/fossil$ mkdir demo |
| 56 | 56 | stephan@ludo:~/fossil$ cd demo |
| 57 | 57 | stephan@ludo:~/fossil/demo$ fossil open ../demo.fossil |
| 58 | -stephan@ludo:~/fossil/demo$ | |
| 58 | +stephan@ludo:~/fossil/demo$ | |
| 59 | 59 | </verbatim> |
| 60 | 60 | |
| 61 | 61 | That creates a file called <tt>_FOSSIL_</tt> in the current |
| 62 | 62 | directory, and this file contains all kinds of fossil-related |
| 63 | 63 | information about your local repository. You can ignore it |
| 64 | 64 |
| --- www/newrepo.wiki | |
| +++ www/newrepo.wiki | |
| @@ -53,11 +53,11 @@ | |
| 53 | |
| 54 | <verbatim> |
| 55 | stephan@ludo:~/fossil$ mkdir demo |
| 56 | stephan@ludo:~/fossil$ cd demo |
| 57 | stephan@ludo:~/fossil/demo$ fossil open ../demo.fossil |
| 58 | stephan@ludo:~/fossil/demo$ |
| 59 | </verbatim> |
| 60 | |
| 61 | That creates a file called <tt>_FOSSIL_</tt> in the current |
| 62 | directory, and this file contains all kinds of fossil-related |
| 63 | information about your local repository. You can ignore it |
| 64 |
| --- www/newrepo.wiki | |
| +++ www/newrepo.wiki | |
| @@ -53,11 +53,11 @@ | |
| 53 | |
| 54 | <verbatim> |
| 55 | stephan@ludo:~/fossil$ mkdir demo |
| 56 | stephan@ludo:~/fossil$ cd demo |
| 57 | stephan@ludo:~/fossil/demo$ fossil open ../demo.fossil |
| 58 | stephan@ludo:~/fossil/demo$ |
| 59 | </verbatim> |
| 60 | |
| 61 | That creates a file called <tt>_FOSSIL_</tt> in the current |
| 62 | directory, and this file contains all kinds of fossil-related |
| 63 | information about your local repository. You can ignore it |
| 64 |
+68
-76
| --- www/permutedindex.html | ||
| +++ www/permutedindex.html | ||
| @@ -19,55 +19,53 @@ | ||
| 19 | 19 | <a name="pindex"></a> |
| 20 | 20 | <h2>Permuted Index:</h2> |
| 21 | 21 | <ul> |
| 22 | 22 | <li><a href="fiveminutes.wiki">5 Minutes as a Single User — Update and Running in</a></li> |
| 23 | 23 | <li><a href="fossil-from-msvc.wiki">2010 IDE — Integrating Fossil in the Microsoft Express</a></li> |
| 24 | -<li><a href="tech_overview.wiki">A Technical Overview Of The Design And Implementation Of Fossil</a></li> | |
| 25 | -<li><a href="adding_code.wiki">Adding New Features To Fossil</a></li> | |
| 26 | -<li><a href="antibot.wiki">against Spiders and Bots — Defense</a></li> | |
| 24 | +<li><a href="tech_overview.wiki"><b>A Technical Overview Of The Design And Implementation Of Fossil</b></a></li> | |
| 25 | +<li><a href="adding_code.wiki"><b>Adding New Features To Fossil</b></a></li> | |
| 27 | 26 | <li><a href="copyright-release.html">Agreement — Contributor License</a></li> |
| 28 | 27 | <li><a href="delta_encoder_algorithm.wiki">Algorithm — Fossil Delta Encoding</a></li> |
| 29 | 28 | <li><a href="blame.wiki">Algorithm Of Fossil — The Annotate/Blame</a></li> |
| 30 | 29 | <li><a href="blame.wiki">Annotate/Blame Algorithm Of Fossil — The</a></li> |
| 31 | 30 | <li><a href="customskin.md">Appearance of Web Pages — Theming: Customizing The</a></li> |
| 32 | -<li><a href="fiveminutes.wiki">as a Single User — Update and Running in 5 Minutes</a></li> | |
| 33 | 31 | <li><a href="faq.wiki">Asked Questions — Frequently</a></li> |
| 34 | 32 | <li><a href="password.wiki">Authentication — Password Management And</a></li> |
| 35 | -<li><a href="whyusefossil.wiki">Benefits Of Version Control</a></li> | |
| 33 | +<li><a href="whyusefossil.wiki"><b>Benefits Of Version Control</b></a></li> | |
| 36 | 34 | <li><a href="antibot.wiki">Bots — Defense against Spiders and</a></li> |
| 37 | 35 | <li><a href="private.wiki">Branches — Creating, Syncing, and Deleting Private</a></li> |
| 38 | -<li><a href="branching.wiki">Branching, Forking, Merging, and Tagging</a></li> | |
| 39 | -<li><a href="bugtheory.wiki">Bug Tracking In Fossil</a></li> | |
| 36 | +<li><a href="branching.wiki"><b>Branching, Forking, Merging, and Tagging</b></a></li> | |
| 37 | +<li><a href="bugtheory.wiki"><b>Bug Tracking In Fossil</b></a></li> | |
| 40 | 38 | <li><a href="makefile.wiki">Build Process — The Fossil</a></li> |
| 41 | 39 | <li><a href="aboutcgi.wiki">CGI Works In Fossil — How</a></li> |
| 42 | 40 | <li><a href="changes.wiki">Changelog — Fossil</a></li> |
| 43 | -<li><a href="checkin_names.wiki">Check-in And Version Names</a></li> | |
| 44 | -<li><a href="checkin.wiki">Check-in Checklist</a></li> | |
| 41 | +<li><a href="checkin_names.wiki"><b>Check-in And Version Names</b></a></li> | |
| 42 | +<li><a href="checkin.wiki"><b>Check-in Checklist</b></a></li> | |
| 45 | 43 | <li><a href="checkin.wiki">Checklist — Check-in</a></li> |
| 46 | 44 | <li><a href="../test/release-checklist.wiki">Checklist — Pre-Release Testing</a></li> |
| 47 | -<li><a href="foss-cklist.wiki">Checklist For Successful Open-Source Projects</a></li> | |
| 45 | +<li><a href="foss-cklist.wiki"><b>Checklist For Successful Open-Source Projects</b></a></li> | |
| 48 | 46 | <li><a href="selfcheck.wiki">Checks — Fossil Repository Integrity Self</a></li> |
| 49 | -<li><a href="childprojects.wiki">Child Projects</a></li> | |
| 47 | +<li><a href="childprojects.wiki"><b>Child Projects</b></a></li> | |
| 50 | 48 | <li><a href="contribute.wiki">Code or Documentation To The Fossil Project — Contributing</a></li> |
| 51 | 49 | <li><a href="style.wiki">Code Style Guidelines — Source</a></li> |
| 52 | 50 | <li><a href="../../../help">Commands and Webpages — Lists of</a></li> |
| 53 | -<li><a href="build.wiki">Compiling and Installing Fossil</a></li> | |
| 51 | +<li><a href="build.wiki"><b>Compiling and Installing Fossil</b></a></li> | |
| 54 | 52 | <li><a href="concepts.wiki">Concepts — Fossil Core</a></li> |
| 55 | 53 | <li><a href="server.wiki">Configure A Fossil Server — How To</a></li> |
| 56 | 54 | <li><a href="shunning.wiki">Content From Fossil — Shunning: Deleting</a></li> |
| 57 | -<li><a href="contribute.wiki">Contributing Code or Documentation To The Fossil Project</a></li> | |
| 58 | -<li><a href="copyright-release.html">Contributor License Agreement</a></li> | |
| 55 | +<li><a href="contribute.wiki"><b>Contributing Code or Documentation To The Fossil Project</b></a></li> | |
| 56 | +<li><a href="copyright-release.html"><b>Contributor License Agreement</b></a></li> | |
| 59 | 57 | <li><a href="whyusefossil.wiki">Control — Benefits Of Version</a></li> |
| 60 | 58 | <li><a href="concepts.wiki">Core Concepts — Fossil</a></li> |
| 61 | 59 | <li><a href="newrepo.wiki">Create A New Fossil Repository — How To</a></li> |
| 62 | -<li><a href="private.wiki">Creating, Syncing, and Deleting Private Branches</a></li> | |
| 60 | +<li><a href="private.wiki"><b>Creating, Syncing, and Deleting Private Branches</b></a></li> | |
| 63 | 61 | <li><a href="qandc.wiki">Criticisms — Questions And</a></li> |
| 64 | 62 | <li><a href="customskin.md">Customizing The Appearance of Web Pages — Theming:</a></li> |
| 65 | -<li><a href="custom_ticket.wiki">Customizing The Ticket System</a></li> | |
| 63 | +<li><a href="custom_ticket.wiki"><b>Customizing The Ticket System</b></a></li> | |
| 66 | 64 | <li><a href="customgraph.md">Customizing the Timeline Graph — Theming:</a></li> |
| 67 | 65 | <li><a href="tech_overview.wiki">Databases Used By Fossil — SQLite</a></li> |
| 68 | -<li><a href="antibot.wiki">Defense against Spiders and Bots</a></li> | |
| 66 | +<li><a href="antibot.wiki"><b>Defense against Spiders and Bots</b></a></li> | |
| 69 | 67 | <li><a href="shunning.wiki">Deleting Content From Fossil — Shunning:</a></li> |
| 70 | 68 | <li><a href="private.wiki">Deleting Private Branches — Creating, Syncing, and</a></li> |
| 71 | 69 | <li><a href="delta_encoder_algorithm.wiki">Delta Encoding Algorithm — Fossil</a></li> |
| 72 | 70 | <li><a href="delta_format.wiki">Delta Format — Fossil</a></li> |
| 73 | 71 | <li><a href="tech_overview.wiki">Design And Implementation Of Fossil — A Technical Overview Of The</a></li> |
| @@ -74,15 +72,15 @@ | ||
| 74 | 72 | <li><a href="theory1.wiki">Design Of The Fossil DVCS — Thoughts On The</a></li> |
| 75 | 73 | <li><a href="embeddeddoc.wiki">Documentation — Embedded Project</a></li> |
| 76 | 74 | <li><a href="contribute.wiki">Documentation To The Fossil Project — Contributing Code or</a></li> |
| 77 | 75 | <li><a href="theory1.wiki">DVCS — Thoughts On The Design Of The Fossil</a></li> |
| 78 | 76 | <li><a href="quotes.wiki">DVCSes in General — Quotes: What People Are Saying About Fossil, Git, and</a></li> |
| 79 | -<li><a href="embeddeddoc.wiki">Embedded Project Documentation</a></li> | |
| 77 | +<li><a href="embeddeddoc.wiki"><b>Embedded Project Documentation</b></a></li> | |
| 80 | 78 | <li><a href="delta_encoder_algorithm.wiki">Encoding Algorithm — Fossil Delta</a></li> |
| 81 | 79 | <li><a href="encryptedrepos.wiki">Encrypted Repositories — How To Use</a></li> |
| 82 | -<li><a href="env-opts.md">Environment Variables and Global Options</a></li> | |
| 83 | -<li><a href="event.wiki">Events</a></li> | |
| 80 | +<li><a href="env-opts.md"><b>Environment Variables and Global Options</b></a></li> | |
| 81 | +<li><a href="event.wiki"><b>Events</b></a></li> | |
| 84 | 82 | <li><a href="webpage-ex.md">Examples — Webpage</a></li> |
| 85 | 83 | <li><a href="inout.wiki">Export To And From Git — Import And</a></li> |
| 86 | 84 | <li><a href="fossil-from-msvc.wiki">Express 2010 IDE — Integrating Fossil in the Microsoft</a></li> |
| 87 | 85 | <li><a href="adding_code.wiki">Features To Fossil — Adding New</a></li> |
| 88 | 86 | <li><a href="fileformat.wiki">File Format — Fossil</a></li> |
| @@ -90,56 +88,54 @@ | ||
| 90 | 88 | <li><a href="branching.wiki">Forking, Merging, and Tagging — Branching,</a></li> |
| 91 | 89 | <li><a href="delta_format.wiki">Format — Fossil Delta</a></li> |
| 92 | 90 | <li><a href="fileformat.wiki">Format — Fossil File</a></li> |
| 93 | 91 | <li><a href="../../../md_rules">Formatting Rules — Markdown</a></li> |
| 94 | 92 | <li><a href="../../../wiki_rules">Formatting Rules — Wiki</a></li> |
| 95 | -<li><a href="changes.wiki">Fossil Changelog</a></li> | |
| 96 | -<li><a href="concepts.wiki">Fossil Core Concepts</a></li> | |
| 97 | -<li><a href="delta_encoder_algorithm.wiki">Fossil Delta Encoding Algorithm</a></li> | |
| 98 | -<li><a href="delta_format.wiki">Fossil Delta Format</a></li> | |
| 99 | -<li><a href="fileformat.wiki">Fossil File Format</a></li> | |
| 100 | -<li><a href="quickstart.wiki">Fossil Quick Start Guide</a></li> | |
| 101 | -<li><a href="selfcheck.wiki">Fossil Repository Integrity Self Checks</a></li> | |
| 102 | -<li><a href="selfhost.wiki">Fossil Self Hosting Repositories</a></li> | |
| 103 | -<li><a href="settings.wiki">Fossil Settings</a></li> | |
| 104 | -<li><a href="hints.wiki">Fossil Tips And Usage Hints</a></li> | |
| 105 | -<li><a href="fossil-v-git.wiki">Fossil Versus Git</a></li> | |
| 93 | +<li><a href="changes.wiki"><b>Fossil Changelog</b></a></li> | |
| 94 | +<li><a href="concepts.wiki"><b>Fossil Core Concepts</b></a></li> | |
| 95 | +<li><a href="delta_encoder_algorithm.wiki"><b>Fossil Delta Encoding Algorithm</b></a></li> | |
| 96 | +<li><a href="delta_format.wiki"><b>Fossil Delta Format</b></a></li> | |
| 97 | +<li><a href="fileformat.wiki"><b>Fossil File Format</b></a></li> | |
| 98 | +<li><a href="quickstart.wiki"><b>Fossil Quick Start Guide</b></a></li> | |
| 99 | +<li><a href="selfcheck.wiki"><b>Fossil Repository Integrity Self Checks</b></a></li> | |
| 100 | +<li><a href="selfhost.wiki"><b>Fossil Self Hosting Repositories</b></a></li> | |
| 101 | +<li><a href="settings.wiki"><b>Fossil Settings</b></a></li> | |
| 102 | +<li><a href="hints.wiki"><b>Fossil Tips And Usage Hints</b></a></li> | |
| 103 | +<li><a href="fossil-v-git.wiki"><b>Fossil Versus Git</b></a></li> | |
| 106 | 104 | <li><a href="quotes.wiki">Fossil, Git, and DVCSes in General — Quotes: What People Are Saying About</a></li> |
| 107 | -<li><a href="faq.wiki">Frequently Asked Questions</a></li> | |
| 108 | -<li><a href="shunning.wiki">From Fossil — Shunning: Deleting Content</a></li> | |
| 109 | -<li><a href="inout.wiki">From Git — Import And Export To And</a></li> | |
| 105 | +<li><a href="faq.wiki"><b>Frequently Asked Questions</b></a></li> | |
| 110 | 106 | <li><a href="quotes.wiki">General — Quotes: What People Are Saying About Fossil, Git, and DVCSes in</a></li> |
| 111 | 107 | <li><a href="fossil-v-git.wiki">Git — Fossil Versus</a></li> |
| 112 | 108 | <li><a href="inout.wiki">Git — Import And Export To And From</a></li> |
| 113 | 109 | <li><a href="quotes.wiki">Git, and DVCSes in General — Quotes: What People Are Saying About Fossil,</a></li> |
| 114 | 110 | <li><a href="env-opts.md">Global Options — Environment Variables and</a></li> |
| 115 | 111 | <li><a href="customgraph.md">Graph — Theming: Customizing the Timeline</a></li> |
| 116 | 112 | <li><a href="quickstart.wiki">Guide — Fossil Quick Start</a></li> |
| 117 | 113 | <li><a href="style.wiki">Guidelines — Source Code Style</a></li> |
| 118 | -<li><a href="hacker-howto.wiki">Hacker How-To</a></li> | |
| 119 | -<li><a href="adding_code.wiki">Hacking Fossil</a></li> | |
| 114 | +<li><a href="hacker-howto.wiki"><b>Hacker How-To</b></a></li> | |
| 115 | +<li><a href="adding_code.wiki"><b>Hacking Fossil</b></a></li> | |
| 120 | 116 | <li><a href="hints.wiki">Hints — Fossil Tips And Usage</a></li> |
| 121 | -<li><a href="index.wiki">Home Page</a></li> | |
| 117 | +<li><a href="index.wiki"><b>Home Page</b></a></li> | |
| 122 | 118 | <li><a href="selfhost.wiki">Hosting Repositories — Fossil Self</a></li> |
| 123 | -<li><a href="aboutcgi.wiki">How CGI Works In Fossil</a></li> | |
| 124 | -<li><a href="server.wiki">How To Configure A Fossil Server</a></li> | |
| 125 | -<li><a href="newrepo.wiki">How To Create A New Fossil Repository</a></li> | |
| 126 | -<li><a href="encryptedrepos.wiki">How To Use Encrypted Repositories</a></li> | |
| 119 | +<li><a href="aboutcgi.wiki"><b>How CGI Works In Fossil</b></a></li> | |
| 120 | +<li><a href="server.wiki"><b>How To Configure A Fossil Server</b></a></li> | |
| 121 | +<li><a href="newrepo.wiki"><b>How To Create A New Fossil Repository</b></a></li> | |
| 122 | +<li><a href="encryptedrepos.wiki"><b>How To Use Encrypted Repositories</b></a></li> | |
| 127 | 123 | <li><a href="hacker-howto.wiki">How-To — Hacker</a></li> |
| 128 | 124 | <li><a href="fossil-from-msvc.wiki">IDE — Integrating Fossil in the Microsoft Express 2010</a></li> |
| 129 | 125 | <li><a href="tech_overview.wiki">Implementation Of Fossil — A Technical Overview Of The Design And</a></li> |
| 130 | -<li><a href="inout.wiki">Import And Export To And From Git</a></li> | |
| 126 | +<li><a href="inout.wiki"><b>Import And Export To And From Git</b></a></li> | |
| 131 | 127 | <li><a href="build.wiki">Installing Fossil — Compiling and</a></li> |
| 132 | -<li><a href="fossil-from-msvc.wiki">Integrating Fossil in the Microsoft Express 2010 IDE</a></li> | |
| 128 | +<li><a href="fossil-from-msvc.wiki"><b>Integrating Fossil in the Microsoft Express 2010 IDE</b></a></li> | |
| 133 | 129 | <li><a href="selfcheck.wiki">Integrity Self Checks — Fossil Repository</a></li> |
| 134 | 130 | <li><a href="webui.wiki">Interface — The Fossil Web</a></li> |
| 135 | 131 | <li><a href="th1.md">Language — The TH1 Scripting</a></li> |
| 136 | 132 | <li><a href="copyright-release.html">License Agreement — Contributor</a></li> |
| 137 | -<li><a href="../../../help">Lists of Commands and Webpages</a></li> | |
| 133 | +<li><a href="../../../help"><b>Lists of Commands and Webpages</b></a></li> | |
| 138 | 134 | <li><a href="password.wiki">Management And Authentication — Password</a></li> |
| 139 | 135 | <li><a href="../../../sitemap">Map — Site</a></li> |
| 140 | -<li><a href="../../../md_rules">Markdown Formatting Rules</a></li> | |
| 136 | +<li><a href="../../../md_rules"><b>Markdown Formatting Rules</b></a></li> | |
| 141 | 137 | <li><a href="branching.wiki">Merging, and Tagging — Branching, Forking,</a></li> |
| 142 | 138 | <li><a href="fossil-from-msvc.wiki">Microsoft Express 2010 IDE — Integrating Fossil in the</a></li> |
| 143 | 139 | <li><a href="fiveminutes.wiki">Minutes as a Single User — Update and Running in 5</a></li> |
| 144 | 140 | <li><a href="checkin_names.wiki">Names — Check-in And Version</a></li> |
| 145 | 141 | <li><a href="adding_code.wiki">New Features To Fossil — Adding</a></li> |
| @@ -148,47 +144,46 @@ | ||
| 148 | 144 | <li><a href="pop.wiki">Operations — Principles Of</a></li> |
| 149 | 145 | <li><a href="env-opts.md">Options — Environment Variables and Global</a></li> |
| 150 | 146 | <li><a href="tech_overview.wiki">Overview Of The Design And Implementation Of Fossil — A Technical</a></li> |
| 151 | 147 | <li><a href="index.wiki">Page — Home</a></li> |
| 152 | 148 | <li><a href="customskin.md">Pages — Theming: Customizing The Appearance of Web</a></li> |
| 153 | -<li><a href="password.wiki">Password Management And Authentication</a></li> | |
| 149 | +<li><a href="password.wiki"><b>Password Management And Authentication</b></a></li> | |
| 154 | 150 | <li><a href="quotes.wiki">People Are Saying About Fossil, Git, and DVCSes in General — Quotes: What</a></li> |
| 155 | -<li><a href="stats.wiki">Performance Statistics</a></li> | |
| 156 | -<li><a href="../test/release-checklist.wiki">Pre-Release Testing Checklist</a></li> | |
| 157 | -<li><a href="pop.wiki">Principles Of Operations</a></li> | |
| 151 | +<li><a href="stats.wiki"><b>Performance Statistics</b></a></li> | |
| 152 | +<li><a href="../test/release-checklist.wiki"><b>Pre-Release Testing Checklist</b></a></li> | |
| 153 | +<li><a href="pop.wiki"><b>Principles Of Operations</b></a></li> | |
| 158 | 154 | <li><a href="private.wiki">Private Branches — Creating, Syncing, and Deleting</a></li> |
| 159 | 155 | <li><a href="makefile.wiki">Process — The Fossil Build</a></li> |
| 160 | 156 | <li><a href="contribute.wiki">Project — Contributing Code or Documentation To The Fossil</a></li> |
| 161 | 157 | <li><a href="embeddeddoc.wiki">Project Documentation — Embedded</a></li> |
| 162 | 158 | <li><a href="foss-cklist.wiki">Projects — Checklist For Successful Open-Source</a></li> |
| 163 | 159 | <li><a href="childprojects.wiki">Projects — Child</a></li> |
| 164 | 160 | <li><a href="sync.wiki">Protocol — The Fossil Sync</a></li> |
| 165 | 161 | <li><a href="faq.wiki">Questions — Frequently Asked</a></li> |
| 166 | -<li><a href="qandc.wiki">Questions And Criticisms</a></li> | |
| 162 | +<li><a href="qandc.wiki"><b>Questions And Criticisms</b></a></li> | |
| 167 | 163 | <li><a href="quickstart.wiki">Quick Start Guide — Fossil</a></li> |
| 168 | -<li><a href="quotes.wiki">Quotes: What People Are Saying About Fossil, Git, and DVCSes in General</a></li> | |
| 164 | +<li><a href="quotes.wiki"><b>Quotes: What People Are Saying About Fossil, Git, and DVCSes in General</b></a></li> | |
| 169 | 165 | <li><a href="selfhost.wiki">Repositories — Fossil Self Hosting</a></li> |
| 170 | 166 | <li><a href="encryptedrepos.wiki">Repositories — How To Use Encrypted</a></li> |
| 171 | 167 | <li><a href="newrepo.wiki">Repository — How To Create A New Fossil</a></li> |
| 172 | 168 | <li><a href="selfcheck.wiki">Repository Integrity Self Checks — Fossil</a></li> |
| 173 | -<li><a href="reviews.wiki">Reviews</a></li> | |
| 169 | +<li><a href="reviews.wiki"><b>Reviews</b></a></li> | |
| 174 | 170 | <li><a href="../../../md_rules">Rules — Markdown Formatting</a></li> |
| 175 | 171 | <li><a href="../../../wiki_rules">Rules — Wiki Formatting</a></li> |
| 176 | 172 | <li><a href="fiveminutes.wiki">Running in 5 Minutes as a Single User — Update and</a></li> |
| 177 | 173 | <li><a href="quotes.wiki">Saying About Fossil, Git, and DVCSes in General — Quotes: What People Are</a></li> |
| 178 | 174 | <li><a href="th1.md">Scripting Language — The TH1</a></li> |
| 179 | 175 | <li><a href="selfcheck.wiki">Self Checks — Fossil Repository Integrity</a></li> |
| 180 | 176 | <li><a href="selfhost.wiki">Self Hosting Repositories — Fossil</a></li> |
| 181 | 177 | <li><a href="server.wiki">Server — How To Configure A Fossil</a></li> |
| 182 | 178 | <li><a href="settings.wiki">Settings — Fossil</a></li> |
| 183 | -<li><a href="whyusefossil.wiki">Should Use Fossil — Why You</a></li> | |
| 184 | -<li><a href="shunning.wiki">Shunning: Deleting Content From Fossil</a></li> | |
| 179 | +<li><a href="shunning.wiki"><b>Shunning: Deleting Content From Fossil</b></a></li> | |
| 185 | 180 | <li><a href="fiveminutes.wiki">Single User — Update and Running in 5 Minutes as a</a></li> |
| 186 | -<li><a href="../../../sitemap">Site Map</a></li> | |
| 187 | -<li><a href="style.wiki">Source Code Style Guidelines</a></li> | |
| 181 | +<li><a href="../../../sitemap"><b>Site Map</b></a></li> | |
| 182 | +<li><a href="style.wiki"><b>Source Code Style Guidelines</b></a></li> | |
| 188 | 183 | <li><a href="antibot.wiki">Spiders and Bots — Defense against</a></li> |
| 189 | -<li><a href="tech_overview.wiki">SQLite Databases Used By Fossil</a></li> | |
| 184 | +<li><a href="tech_overview.wiki"><b>SQLite Databases Used By Fossil</b></a></li> | |
| 190 | 185 | <li><a href="ssl.wiki">SSL with Fossil — Using</a></li> |
| 191 | 186 | <li><a href="quickstart.wiki">Start Guide — Fossil Quick</a></li> |
| 192 | 187 | <li><a href="stats.wiki">Statistics — Performance</a></li> |
| 193 | 188 | <li><a href="style.wiki">Style Guidelines — Source Code</a></li> |
| 194 | 189 | <li><a href="foss-cklist.wiki">Successful Open-Source Projects — Checklist For</a></li> |
| @@ -198,42 +193,39 @@ | ||
| 198 | 193 | <li><a href="tickets.wiki">System — The Fossil Ticket</a></li> |
| 199 | 194 | <li><a href="branching.wiki">Tagging — Branching, Forking, Merging, and</a></li> |
| 200 | 195 | <li><a href="tech_overview.wiki">Technical Overview Of The Design And Implementation Of Fossil — A</a></li> |
| 201 | 196 | <li><a href="../test/release-checklist.wiki">Testing Checklist — Pre-Release</a></li> |
| 202 | 197 | <li><a href="th1.md">TH1 Scripting Language — The</a></li> |
| 203 | -<li><a href="blame.wiki">The Annotate/Blame Algorithm Of Fossil</a></li> | |
| 204 | -<li><a href="makefile.wiki">The Fossil Build Process</a></li> | |
| 205 | -<li><a href="sync.wiki">The Fossil Sync Protocol</a></li> | |
| 206 | -<li><a href="tickets.wiki">The Fossil Ticket System</a></li> | |
| 207 | -<li><a href="webui.wiki">The Fossil Web Interface</a></li> | |
| 208 | -<li><a href="th1.md">The TH1 Scripting Language</a></li> | |
| 209 | -<li><a href="customskin.md">Theming: Customizing The Appearance of Web Pages</a></li> | |
| 210 | -<li><a href="customgraph.md">Theming: Customizing the Timeline Graph</a></li> | |
| 211 | -<li><a href="theory1.wiki">Thoughts On The Design Of The Fossil DVCS</a></li> | |
| 198 | +<li><a href="blame.wiki"><b>The Annotate/Blame Algorithm Of Fossil</b></a></li> | |
| 199 | +<li><a href="makefile.wiki"><b>The Fossil Build Process</b></a></li> | |
| 200 | +<li><a href="sync.wiki"><b>The Fossil Sync Protocol</b></a></li> | |
| 201 | +<li><a href="tickets.wiki"><b>The Fossil Ticket System</b></a></li> | |
| 202 | +<li><a href="webui.wiki"><b>The Fossil Web Interface</b></a></li> | |
| 203 | +<li><a href="th1.md"><b>The TH1 Scripting Language</b></a></li> | |
| 204 | +<li><a href="customskin.md"><b>Theming: Customizing The Appearance of Web Pages</b></a></li> | |
| 205 | +<li><a href="customgraph.md"><b>Theming: Customizing the Timeline Graph</b></a></li> | |
| 206 | +<li><a href="theory1.wiki"><b>Thoughts On The Design Of The Fossil DVCS</b></a></li> | |
| 212 | 207 | <li><a href="custom_ticket.wiki">Ticket System — Customizing The</a></li> |
| 213 | 208 | <li><a href="tickets.wiki">Ticket System — The Fossil</a></li> |
| 214 | 209 | <li><a href="customgraph.md">Timeline Graph — Theming: Customizing the</a></li> |
| 215 | 210 | <li><a href="hints.wiki">Tips And Usage Hints — Fossil</a></li> |
| 216 | 211 | <li><a href="bugtheory.wiki">Tracking In Fossil — Bug</a></li> |
| 217 | -<li><a href="unvers.wiki">Unversioned Files</a></li> | |
| 218 | -<li><a href="fiveminutes.wiki">Update and Running in 5 Minutes as a Single User</a></li> | |
| 212 | +<li><a href="unvers.wiki"><b>Unversioned Files</b></a></li> | |
| 213 | +<li><a href="fiveminutes.wiki"><b>Update and Running in 5 Minutes as a Single User</b></a></li> | |
| 219 | 214 | <li><a href="hints.wiki">Usage Hints — Fossil Tips And</a></li> |
| 220 | -<li><a href="encryptedrepos.wiki">Use Encrypted Repositories — How To</a></li> | |
| 221 | -<li><a href="whyusefossil.wiki">Use Fossil — Why You Should</a></li> | |
| 222 | 215 | <li><a href="fiveminutes.wiki">User — Update and Running in 5 Minutes as a Single</a></li> |
| 223 | -<li><a href="ssl.wiki">Using SSL with Fossil</a></li> | |
| 216 | +<li><a href="ssl.wiki"><b>Using SSL with Fossil</b></a></li> | |
| 224 | 217 | <li><a href="env-opts.md">Variables and Global Options — Environment</a></li> |
| 225 | 218 | <li><a href="whyusefossil.wiki">Version Control — Benefits Of</a></li> |
| 226 | 219 | <li><a href="checkin_names.wiki">Version Names — Check-in And</a></li> |
| 227 | 220 | <li><a href="fossil-v-git.wiki">Versus Git — Fossil</a></li> |
| 228 | 221 | <li><a href="webui.wiki">Web Interface — The Fossil</a></li> |
| 229 | 222 | <li><a href="customskin.md">Web Pages — Theming: Customizing The Appearance of</a></li> |
| 230 | -<li><a href="webpage-ex.md">Webpage Examples</a></li> | |
| 223 | +<li><a href="webpage-ex.md"><b>Webpage Examples</b></a></li> | |
| 231 | 224 | <li><a href="../../../help">Webpages — Lists of Commands and</a></li> |
| 232 | 225 | <li><a href="quotes.wiki">What People Are Saying About Fossil, Git, and DVCSes in General — Quotes:</a></li> |
| 233 | -<li><a href="whyusefossil.wiki">Why You Should Use Fossil</a></li> | |
| 234 | -<li><a href="../../../wiki_rules">Wiki Formatting Rules</a></li> | |
| 235 | -<li><a href="wikitheory.wiki">Wiki In Fossil</a></li> | |
| 236 | -<li><a href="ssl.wiki">with Fossil — Using SSL</a></li> | |
| 226 | +<li><a href="whyusefossil.wiki"><b>Why You Should Use Fossil</b></a></li> | |
| 227 | +<li><a href="../../../wiki_rules"><b>Wiki Formatting Rules</b></a></li> | |
| 228 | +<li><a href="wikitheory.wiki"><b>Wiki In Fossil</b></a></li> | |
| 237 | 229 | <li><a href="aboutcgi.wiki">Works In Fossil — How CGI</a></li> |
| 238 | 230 | <li><a href="whyusefossil.wiki">You Should Use Fossil — Why</a></li> |
| 239 | 231 | </ul></div> |
| 240 | 232 |
| --- www/permutedindex.html | |
| +++ www/permutedindex.html | |
| @@ -19,55 +19,53 @@ | |
| 19 | <a name="pindex"></a> |
| 20 | <h2>Permuted Index:</h2> |
| 21 | <ul> |
| 22 | <li><a href="fiveminutes.wiki">5 Minutes as a Single User — Update and Running in</a></li> |
| 23 | <li><a href="fossil-from-msvc.wiki">2010 IDE — Integrating Fossil in the Microsoft Express</a></li> |
| 24 | <li><a href="tech_overview.wiki">A Technical Overview Of The Design And Implementation Of Fossil</a></li> |
| 25 | <li><a href="adding_code.wiki">Adding New Features To Fossil</a></li> |
| 26 | <li><a href="antibot.wiki">against Spiders and Bots — Defense</a></li> |
| 27 | <li><a href="copyright-release.html">Agreement — Contributor License</a></li> |
| 28 | <li><a href="delta_encoder_algorithm.wiki">Algorithm — Fossil Delta Encoding</a></li> |
| 29 | <li><a href="blame.wiki">Algorithm Of Fossil — The Annotate/Blame</a></li> |
| 30 | <li><a href="blame.wiki">Annotate/Blame Algorithm Of Fossil — The</a></li> |
| 31 | <li><a href="customskin.md">Appearance of Web Pages — Theming: Customizing The</a></li> |
| 32 | <li><a href="fiveminutes.wiki">as a Single User — Update and Running in 5 Minutes</a></li> |
| 33 | <li><a href="faq.wiki">Asked Questions — Frequently</a></li> |
| 34 | <li><a href="password.wiki">Authentication — Password Management And</a></li> |
| 35 | <li><a href="whyusefossil.wiki">Benefits Of Version Control</a></li> |
| 36 | <li><a href="antibot.wiki">Bots — Defense against Spiders and</a></li> |
| 37 | <li><a href="private.wiki">Branches — Creating, Syncing, and Deleting Private</a></li> |
| 38 | <li><a href="branching.wiki">Branching, Forking, Merging, and Tagging</a></li> |
| 39 | <li><a href="bugtheory.wiki">Bug Tracking In Fossil</a></li> |
| 40 | <li><a href="makefile.wiki">Build Process — The Fossil</a></li> |
| 41 | <li><a href="aboutcgi.wiki">CGI Works In Fossil — How</a></li> |
| 42 | <li><a href="changes.wiki">Changelog — Fossil</a></li> |
| 43 | <li><a href="checkin_names.wiki">Check-in And Version Names</a></li> |
| 44 | <li><a href="checkin.wiki">Check-in Checklist</a></li> |
| 45 | <li><a href="checkin.wiki">Checklist — Check-in</a></li> |
| 46 | <li><a href="../test/release-checklist.wiki">Checklist — Pre-Release Testing</a></li> |
| 47 | <li><a href="foss-cklist.wiki">Checklist For Successful Open-Source Projects</a></li> |
| 48 | <li><a href="selfcheck.wiki">Checks — Fossil Repository Integrity Self</a></li> |
| 49 | <li><a href="childprojects.wiki">Child Projects</a></li> |
| 50 | <li><a href="contribute.wiki">Code or Documentation To The Fossil Project — Contributing</a></li> |
| 51 | <li><a href="style.wiki">Code Style Guidelines — Source</a></li> |
| 52 | <li><a href="../../../help">Commands and Webpages — Lists of</a></li> |
| 53 | <li><a href="build.wiki">Compiling and Installing Fossil</a></li> |
| 54 | <li><a href="concepts.wiki">Concepts — Fossil Core</a></li> |
| 55 | <li><a href="server.wiki">Configure A Fossil Server — How To</a></li> |
| 56 | <li><a href="shunning.wiki">Content From Fossil — Shunning: Deleting</a></li> |
| 57 | <li><a href="contribute.wiki">Contributing Code or Documentation To The Fossil Project</a></li> |
| 58 | <li><a href="copyright-release.html">Contributor License Agreement</a></li> |
| 59 | <li><a href="whyusefossil.wiki">Control — Benefits Of Version</a></li> |
| 60 | <li><a href="concepts.wiki">Core Concepts — Fossil</a></li> |
| 61 | <li><a href="newrepo.wiki">Create A New Fossil Repository — How To</a></li> |
| 62 | <li><a href="private.wiki">Creating, Syncing, and Deleting Private Branches</a></li> |
| 63 | <li><a href="qandc.wiki">Criticisms — Questions And</a></li> |
| 64 | <li><a href="customskin.md">Customizing The Appearance of Web Pages — Theming:</a></li> |
| 65 | <li><a href="custom_ticket.wiki">Customizing The Ticket System</a></li> |
| 66 | <li><a href="customgraph.md">Customizing the Timeline Graph — Theming:</a></li> |
| 67 | <li><a href="tech_overview.wiki">Databases Used By Fossil — SQLite</a></li> |
| 68 | <li><a href="antibot.wiki">Defense against Spiders and Bots</a></li> |
| 69 | <li><a href="shunning.wiki">Deleting Content From Fossil — Shunning:</a></li> |
| 70 | <li><a href="private.wiki">Deleting Private Branches — Creating, Syncing, and</a></li> |
| 71 | <li><a href="delta_encoder_algorithm.wiki">Delta Encoding Algorithm — Fossil</a></li> |
| 72 | <li><a href="delta_format.wiki">Delta Format — Fossil</a></li> |
| 73 | <li><a href="tech_overview.wiki">Design And Implementation Of Fossil — A Technical Overview Of The</a></li> |
| @@ -74,15 +72,15 @@ | |
| 74 | <li><a href="theory1.wiki">Design Of The Fossil DVCS — Thoughts On The</a></li> |
| 75 | <li><a href="embeddeddoc.wiki">Documentation — Embedded Project</a></li> |
| 76 | <li><a href="contribute.wiki">Documentation To The Fossil Project — Contributing Code or</a></li> |
| 77 | <li><a href="theory1.wiki">DVCS — Thoughts On The Design Of The Fossil</a></li> |
| 78 | <li><a href="quotes.wiki">DVCSes in General — Quotes: What People Are Saying About Fossil, Git, and</a></li> |
| 79 | <li><a href="embeddeddoc.wiki">Embedded Project Documentation</a></li> |
| 80 | <li><a href="delta_encoder_algorithm.wiki">Encoding Algorithm — Fossil Delta</a></li> |
| 81 | <li><a href="encryptedrepos.wiki">Encrypted Repositories — How To Use</a></li> |
| 82 | <li><a href="env-opts.md">Environment Variables and Global Options</a></li> |
| 83 | <li><a href="event.wiki">Events</a></li> |
| 84 | <li><a href="webpage-ex.md">Examples — Webpage</a></li> |
| 85 | <li><a href="inout.wiki">Export To And From Git — Import And</a></li> |
| 86 | <li><a href="fossil-from-msvc.wiki">Express 2010 IDE — Integrating Fossil in the Microsoft</a></li> |
| 87 | <li><a href="adding_code.wiki">Features To Fossil — Adding New</a></li> |
| 88 | <li><a href="fileformat.wiki">File Format — Fossil</a></li> |
| @@ -90,56 +88,54 @@ | |
| 90 | <li><a href="branching.wiki">Forking, Merging, and Tagging — Branching,</a></li> |
| 91 | <li><a href="delta_format.wiki">Format — Fossil Delta</a></li> |
| 92 | <li><a href="fileformat.wiki">Format — Fossil File</a></li> |
| 93 | <li><a href="../../../md_rules">Formatting Rules — Markdown</a></li> |
| 94 | <li><a href="../../../wiki_rules">Formatting Rules — Wiki</a></li> |
| 95 | <li><a href="changes.wiki">Fossil Changelog</a></li> |
| 96 | <li><a href="concepts.wiki">Fossil Core Concepts</a></li> |
| 97 | <li><a href="delta_encoder_algorithm.wiki">Fossil Delta Encoding Algorithm</a></li> |
| 98 | <li><a href="delta_format.wiki">Fossil Delta Format</a></li> |
| 99 | <li><a href="fileformat.wiki">Fossil File Format</a></li> |
| 100 | <li><a href="quickstart.wiki">Fossil Quick Start Guide</a></li> |
| 101 | <li><a href="selfcheck.wiki">Fossil Repository Integrity Self Checks</a></li> |
| 102 | <li><a href="selfhost.wiki">Fossil Self Hosting Repositories</a></li> |
| 103 | <li><a href="settings.wiki">Fossil Settings</a></li> |
| 104 | <li><a href="hints.wiki">Fossil Tips And Usage Hints</a></li> |
| 105 | <li><a href="fossil-v-git.wiki">Fossil Versus Git</a></li> |
| 106 | <li><a href="quotes.wiki">Fossil, Git, and DVCSes in General — Quotes: What People Are Saying About</a></li> |
| 107 | <li><a href="faq.wiki">Frequently Asked Questions</a></li> |
| 108 | <li><a href="shunning.wiki">From Fossil — Shunning: Deleting Content</a></li> |
| 109 | <li><a href="inout.wiki">From Git — Import And Export To And</a></li> |
| 110 | <li><a href="quotes.wiki">General — Quotes: What People Are Saying About Fossil, Git, and DVCSes in</a></li> |
| 111 | <li><a href="fossil-v-git.wiki">Git — Fossil Versus</a></li> |
| 112 | <li><a href="inout.wiki">Git — Import And Export To And From</a></li> |
| 113 | <li><a href="quotes.wiki">Git, and DVCSes in General — Quotes: What People Are Saying About Fossil,</a></li> |
| 114 | <li><a href="env-opts.md">Global Options — Environment Variables and</a></li> |
| 115 | <li><a href="customgraph.md">Graph — Theming: Customizing the Timeline</a></li> |
| 116 | <li><a href="quickstart.wiki">Guide — Fossil Quick Start</a></li> |
| 117 | <li><a href="style.wiki">Guidelines — Source Code Style</a></li> |
| 118 | <li><a href="hacker-howto.wiki">Hacker How-To</a></li> |
| 119 | <li><a href="adding_code.wiki">Hacking Fossil</a></li> |
| 120 | <li><a href="hints.wiki">Hints — Fossil Tips And Usage</a></li> |
| 121 | <li><a href="index.wiki">Home Page</a></li> |
| 122 | <li><a href="selfhost.wiki">Hosting Repositories — Fossil Self</a></li> |
| 123 | <li><a href="aboutcgi.wiki">How CGI Works In Fossil</a></li> |
| 124 | <li><a href="server.wiki">How To Configure A Fossil Server</a></li> |
| 125 | <li><a href="newrepo.wiki">How To Create A New Fossil Repository</a></li> |
| 126 | <li><a href="encryptedrepos.wiki">How To Use Encrypted Repositories</a></li> |
| 127 | <li><a href="hacker-howto.wiki">How-To — Hacker</a></li> |
| 128 | <li><a href="fossil-from-msvc.wiki">IDE — Integrating Fossil in the Microsoft Express 2010</a></li> |
| 129 | <li><a href="tech_overview.wiki">Implementation Of Fossil — A Technical Overview Of The Design And</a></li> |
| 130 | <li><a href="inout.wiki">Import And Export To And From Git</a></li> |
| 131 | <li><a href="build.wiki">Installing Fossil — Compiling and</a></li> |
| 132 | <li><a href="fossil-from-msvc.wiki">Integrating Fossil in the Microsoft Express 2010 IDE</a></li> |
| 133 | <li><a href="selfcheck.wiki">Integrity Self Checks — Fossil Repository</a></li> |
| 134 | <li><a href="webui.wiki">Interface — The Fossil Web</a></li> |
| 135 | <li><a href="th1.md">Language — The TH1 Scripting</a></li> |
| 136 | <li><a href="copyright-release.html">License Agreement — Contributor</a></li> |
| 137 | <li><a href="../../../help">Lists of Commands and Webpages</a></li> |
| 138 | <li><a href="password.wiki">Management And Authentication — Password</a></li> |
| 139 | <li><a href="../../../sitemap">Map — Site</a></li> |
| 140 | <li><a href="../../../md_rules">Markdown Formatting Rules</a></li> |
| 141 | <li><a href="branching.wiki">Merging, and Tagging — Branching, Forking,</a></li> |
| 142 | <li><a href="fossil-from-msvc.wiki">Microsoft Express 2010 IDE — Integrating Fossil in the</a></li> |
| 143 | <li><a href="fiveminutes.wiki">Minutes as a Single User — Update and Running in 5</a></li> |
| 144 | <li><a href="checkin_names.wiki">Names — Check-in And Version</a></li> |
| 145 | <li><a href="adding_code.wiki">New Features To Fossil — Adding</a></li> |
| @@ -148,47 +144,46 @@ | |
| 148 | <li><a href="pop.wiki">Operations — Principles Of</a></li> |
| 149 | <li><a href="env-opts.md">Options — Environment Variables and Global</a></li> |
| 150 | <li><a href="tech_overview.wiki">Overview Of The Design And Implementation Of Fossil — A Technical</a></li> |
| 151 | <li><a href="index.wiki">Page — Home</a></li> |
| 152 | <li><a href="customskin.md">Pages — Theming: Customizing The Appearance of Web</a></li> |
| 153 | <li><a href="password.wiki">Password Management And Authentication</a></li> |
| 154 | <li><a href="quotes.wiki">People Are Saying About Fossil, Git, and DVCSes in General — Quotes: What</a></li> |
| 155 | <li><a href="stats.wiki">Performance Statistics</a></li> |
| 156 | <li><a href="../test/release-checklist.wiki">Pre-Release Testing Checklist</a></li> |
| 157 | <li><a href="pop.wiki">Principles Of Operations</a></li> |
| 158 | <li><a href="private.wiki">Private Branches — Creating, Syncing, and Deleting</a></li> |
| 159 | <li><a href="makefile.wiki">Process — The Fossil Build</a></li> |
| 160 | <li><a href="contribute.wiki">Project — Contributing Code or Documentation To The Fossil</a></li> |
| 161 | <li><a href="embeddeddoc.wiki">Project Documentation — Embedded</a></li> |
| 162 | <li><a href="foss-cklist.wiki">Projects — Checklist For Successful Open-Source</a></li> |
| 163 | <li><a href="childprojects.wiki">Projects — Child</a></li> |
| 164 | <li><a href="sync.wiki">Protocol — The Fossil Sync</a></li> |
| 165 | <li><a href="faq.wiki">Questions — Frequently Asked</a></li> |
| 166 | <li><a href="qandc.wiki">Questions And Criticisms</a></li> |
| 167 | <li><a href="quickstart.wiki">Quick Start Guide — Fossil</a></li> |
| 168 | <li><a href="quotes.wiki">Quotes: What People Are Saying About Fossil, Git, and DVCSes in General</a></li> |
| 169 | <li><a href="selfhost.wiki">Repositories — Fossil Self Hosting</a></li> |
| 170 | <li><a href="encryptedrepos.wiki">Repositories — How To Use Encrypted</a></li> |
| 171 | <li><a href="newrepo.wiki">Repository — How To Create A New Fossil</a></li> |
| 172 | <li><a href="selfcheck.wiki">Repository Integrity Self Checks — Fossil</a></li> |
| 173 | <li><a href="reviews.wiki">Reviews</a></li> |
| 174 | <li><a href="../../../md_rules">Rules — Markdown Formatting</a></li> |
| 175 | <li><a href="../../../wiki_rules">Rules — Wiki Formatting</a></li> |
| 176 | <li><a href="fiveminutes.wiki">Running in 5 Minutes as a Single User — Update and</a></li> |
| 177 | <li><a href="quotes.wiki">Saying About Fossil, Git, and DVCSes in General — Quotes: What People Are</a></li> |
| 178 | <li><a href="th1.md">Scripting Language — The TH1</a></li> |
| 179 | <li><a href="selfcheck.wiki">Self Checks — Fossil Repository Integrity</a></li> |
| 180 | <li><a href="selfhost.wiki">Self Hosting Repositories — Fossil</a></li> |
| 181 | <li><a href="server.wiki">Server — How To Configure A Fossil</a></li> |
| 182 | <li><a href="settings.wiki">Settings — Fossil</a></li> |
| 183 | <li><a href="whyusefossil.wiki">Should Use Fossil — Why You</a></li> |
| 184 | <li><a href="shunning.wiki">Shunning: Deleting Content From Fossil</a></li> |
| 185 | <li><a href="fiveminutes.wiki">Single User — Update and Running in 5 Minutes as a</a></li> |
| 186 | <li><a href="../../../sitemap">Site Map</a></li> |
| 187 | <li><a href="style.wiki">Source Code Style Guidelines</a></li> |
| 188 | <li><a href="antibot.wiki">Spiders and Bots — Defense against</a></li> |
| 189 | <li><a href="tech_overview.wiki">SQLite Databases Used By Fossil</a></li> |
| 190 | <li><a href="ssl.wiki">SSL with Fossil — Using</a></li> |
| 191 | <li><a href="quickstart.wiki">Start Guide — Fossil Quick</a></li> |
| 192 | <li><a href="stats.wiki">Statistics — Performance</a></li> |
| 193 | <li><a href="style.wiki">Style Guidelines — Source Code</a></li> |
| 194 | <li><a href="foss-cklist.wiki">Successful Open-Source Projects — Checklist For</a></li> |
| @@ -198,42 +193,39 @@ | |
| 198 | <li><a href="tickets.wiki">System — The Fossil Ticket</a></li> |
| 199 | <li><a href="branching.wiki">Tagging — Branching, Forking, Merging, and</a></li> |
| 200 | <li><a href="tech_overview.wiki">Technical Overview Of The Design And Implementation Of Fossil — A</a></li> |
| 201 | <li><a href="../test/release-checklist.wiki">Testing Checklist — Pre-Release</a></li> |
| 202 | <li><a href="th1.md">TH1 Scripting Language — The</a></li> |
| 203 | <li><a href="blame.wiki">The Annotate/Blame Algorithm Of Fossil</a></li> |
| 204 | <li><a href="makefile.wiki">The Fossil Build Process</a></li> |
| 205 | <li><a href="sync.wiki">The Fossil Sync Protocol</a></li> |
| 206 | <li><a href="tickets.wiki">The Fossil Ticket System</a></li> |
| 207 | <li><a href="webui.wiki">The Fossil Web Interface</a></li> |
| 208 | <li><a href="th1.md">The TH1 Scripting Language</a></li> |
| 209 | <li><a href="customskin.md">Theming: Customizing The Appearance of Web Pages</a></li> |
| 210 | <li><a href="customgraph.md">Theming: Customizing the Timeline Graph</a></li> |
| 211 | <li><a href="theory1.wiki">Thoughts On The Design Of The Fossil DVCS</a></li> |
| 212 | <li><a href="custom_ticket.wiki">Ticket System — Customizing The</a></li> |
| 213 | <li><a href="tickets.wiki">Ticket System — The Fossil</a></li> |
| 214 | <li><a href="customgraph.md">Timeline Graph — Theming: Customizing the</a></li> |
| 215 | <li><a href="hints.wiki">Tips And Usage Hints — Fossil</a></li> |
| 216 | <li><a href="bugtheory.wiki">Tracking In Fossil — Bug</a></li> |
| 217 | <li><a href="unvers.wiki">Unversioned Files</a></li> |
| 218 | <li><a href="fiveminutes.wiki">Update and Running in 5 Minutes as a Single User</a></li> |
| 219 | <li><a href="hints.wiki">Usage Hints — Fossil Tips And</a></li> |
| 220 | <li><a href="encryptedrepos.wiki">Use Encrypted Repositories — How To</a></li> |
| 221 | <li><a href="whyusefossil.wiki">Use Fossil — Why You Should</a></li> |
| 222 | <li><a href="fiveminutes.wiki">User — Update and Running in 5 Minutes as a Single</a></li> |
| 223 | <li><a href="ssl.wiki">Using SSL with Fossil</a></li> |
| 224 | <li><a href="env-opts.md">Variables and Global Options — Environment</a></li> |
| 225 | <li><a href="whyusefossil.wiki">Version Control — Benefits Of</a></li> |
| 226 | <li><a href="checkin_names.wiki">Version Names — Check-in And</a></li> |
| 227 | <li><a href="fossil-v-git.wiki">Versus Git — Fossil</a></li> |
| 228 | <li><a href="webui.wiki">Web Interface — The Fossil</a></li> |
| 229 | <li><a href="customskin.md">Web Pages — Theming: Customizing The Appearance of</a></li> |
| 230 | <li><a href="webpage-ex.md">Webpage Examples</a></li> |
| 231 | <li><a href="../../../help">Webpages — Lists of Commands and</a></li> |
| 232 | <li><a href="quotes.wiki">What People Are Saying About Fossil, Git, and DVCSes in General — Quotes:</a></li> |
| 233 | <li><a href="whyusefossil.wiki">Why You Should Use Fossil</a></li> |
| 234 | <li><a href="../../../wiki_rules">Wiki Formatting Rules</a></li> |
| 235 | <li><a href="wikitheory.wiki">Wiki In Fossil</a></li> |
| 236 | <li><a href="ssl.wiki">with Fossil — Using SSL</a></li> |
| 237 | <li><a href="aboutcgi.wiki">Works In Fossil — How CGI</a></li> |
| 238 | <li><a href="whyusefossil.wiki">You Should Use Fossil — Why</a></li> |
| 239 | </ul></div> |
| 240 |
| --- www/permutedindex.html | |
| +++ www/permutedindex.html | |
| @@ -19,55 +19,53 @@ | |
| 19 | <a name="pindex"></a> |
| 20 | <h2>Permuted Index:</h2> |
| 21 | <ul> |
| 22 | <li><a href="fiveminutes.wiki">5 Minutes as a Single User — Update and Running in</a></li> |
| 23 | <li><a href="fossil-from-msvc.wiki">2010 IDE — Integrating Fossil in the Microsoft Express</a></li> |
| 24 | <li><a href="tech_overview.wiki"><b>A Technical Overview Of The Design And Implementation Of Fossil</b></a></li> |
| 25 | <li><a href="adding_code.wiki"><b>Adding New Features To Fossil</b></a></li> |
| 26 | <li><a href="copyright-release.html">Agreement — Contributor License</a></li> |
| 27 | <li><a href="delta_encoder_algorithm.wiki">Algorithm — Fossil Delta Encoding</a></li> |
| 28 | <li><a href="blame.wiki">Algorithm Of Fossil — The Annotate/Blame</a></li> |
| 29 | <li><a href="blame.wiki">Annotate/Blame Algorithm Of Fossil — The</a></li> |
| 30 | <li><a href="customskin.md">Appearance of Web Pages — Theming: Customizing The</a></li> |
| 31 | <li><a href="faq.wiki">Asked Questions — Frequently</a></li> |
| 32 | <li><a href="password.wiki">Authentication — Password Management And</a></li> |
| 33 | <li><a href="whyusefossil.wiki"><b>Benefits Of Version Control</b></a></li> |
| 34 | <li><a href="antibot.wiki">Bots — Defense against Spiders and</a></li> |
| 35 | <li><a href="private.wiki">Branches — Creating, Syncing, and Deleting Private</a></li> |
| 36 | <li><a href="branching.wiki"><b>Branching, Forking, Merging, and Tagging</b></a></li> |
| 37 | <li><a href="bugtheory.wiki"><b>Bug Tracking In Fossil</b></a></li> |
| 38 | <li><a href="makefile.wiki">Build Process — The Fossil</a></li> |
| 39 | <li><a href="aboutcgi.wiki">CGI Works In Fossil — How</a></li> |
| 40 | <li><a href="changes.wiki">Changelog — Fossil</a></li> |
| 41 | <li><a href="checkin_names.wiki"><b>Check-in And Version Names</b></a></li> |
| 42 | <li><a href="checkin.wiki"><b>Check-in Checklist</b></a></li> |
| 43 | <li><a href="checkin.wiki">Checklist — Check-in</a></li> |
| 44 | <li><a href="../test/release-checklist.wiki">Checklist — Pre-Release Testing</a></li> |
| 45 | <li><a href="foss-cklist.wiki"><b>Checklist For Successful Open-Source Projects</b></a></li> |
| 46 | <li><a href="selfcheck.wiki">Checks — Fossil Repository Integrity Self</a></li> |
| 47 | <li><a href="childprojects.wiki"><b>Child Projects</b></a></li> |
| 48 | <li><a href="contribute.wiki">Code or Documentation To The Fossil Project — Contributing</a></li> |
| 49 | <li><a href="style.wiki">Code Style Guidelines — Source</a></li> |
| 50 | <li><a href="../../../help">Commands and Webpages — Lists of</a></li> |
| 51 | <li><a href="build.wiki"><b>Compiling and Installing Fossil</b></a></li> |
| 52 | <li><a href="concepts.wiki">Concepts — Fossil Core</a></li> |
| 53 | <li><a href="server.wiki">Configure A Fossil Server — How To</a></li> |
| 54 | <li><a href="shunning.wiki">Content From Fossil — Shunning: Deleting</a></li> |
| 55 | <li><a href="contribute.wiki"><b>Contributing Code or Documentation To The Fossil Project</b></a></li> |
| 56 | <li><a href="copyright-release.html"><b>Contributor License Agreement</b></a></li> |
| 57 | <li><a href="whyusefossil.wiki">Control — Benefits Of Version</a></li> |
| 58 | <li><a href="concepts.wiki">Core Concepts — Fossil</a></li> |
| 59 | <li><a href="newrepo.wiki">Create A New Fossil Repository — How To</a></li> |
| 60 | <li><a href="private.wiki"><b>Creating, Syncing, and Deleting Private Branches</b></a></li> |
| 61 | <li><a href="qandc.wiki">Criticisms — Questions And</a></li> |
| 62 | <li><a href="customskin.md">Customizing The Appearance of Web Pages — Theming:</a></li> |
| 63 | <li><a href="custom_ticket.wiki"><b>Customizing The Ticket System</b></a></li> |
| 64 | <li><a href="customgraph.md">Customizing the Timeline Graph — Theming:</a></li> |
| 65 | <li><a href="tech_overview.wiki">Databases Used By Fossil — SQLite</a></li> |
| 66 | <li><a href="antibot.wiki"><b>Defense against Spiders and Bots</b></a></li> |
| 67 | <li><a href="shunning.wiki">Deleting Content From Fossil — Shunning:</a></li> |
| 68 | <li><a href="private.wiki">Deleting Private Branches — Creating, Syncing, and</a></li> |
| 69 | <li><a href="delta_encoder_algorithm.wiki">Delta Encoding Algorithm — Fossil</a></li> |
| 70 | <li><a href="delta_format.wiki">Delta Format — Fossil</a></li> |
| 71 | <li><a href="tech_overview.wiki">Design And Implementation Of Fossil — A Technical Overview Of The</a></li> |
| @@ -74,15 +72,15 @@ | |
| 72 | <li><a href="theory1.wiki">Design Of The Fossil DVCS — Thoughts On The</a></li> |
| 73 | <li><a href="embeddeddoc.wiki">Documentation — Embedded Project</a></li> |
| 74 | <li><a href="contribute.wiki">Documentation To The Fossil Project — Contributing Code or</a></li> |
| 75 | <li><a href="theory1.wiki">DVCS — Thoughts On The Design Of The Fossil</a></li> |
| 76 | <li><a href="quotes.wiki">DVCSes in General — Quotes: What People Are Saying About Fossil, Git, and</a></li> |
| 77 | <li><a href="embeddeddoc.wiki"><b>Embedded Project Documentation</b></a></li> |
| 78 | <li><a href="delta_encoder_algorithm.wiki">Encoding Algorithm — Fossil Delta</a></li> |
| 79 | <li><a href="encryptedrepos.wiki">Encrypted Repositories — How To Use</a></li> |
| 80 | <li><a href="env-opts.md"><b>Environment Variables and Global Options</b></a></li> |
| 81 | <li><a href="event.wiki"><b>Events</b></a></li> |
| 82 | <li><a href="webpage-ex.md">Examples — Webpage</a></li> |
| 83 | <li><a href="inout.wiki">Export To And From Git — Import And</a></li> |
| 84 | <li><a href="fossil-from-msvc.wiki">Express 2010 IDE — Integrating Fossil in the Microsoft</a></li> |
| 85 | <li><a href="adding_code.wiki">Features To Fossil — Adding New</a></li> |
| 86 | <li><a href="fileformat.wiki">File Format — Fossil</a></li> |
| @@ -90,56 +88,54 @@ | |
| 88 | <li><a href="branching.wiki">Forking, Merging, and Tagging — Branching,</a></li> |
| 89 | <li><a href="delta_format.wiki">Format — Fossil Delta</a></li> |
| 90 | <li><a href="fileformat.wiki">Format — Fossil File</a></li> |
| 91 | <li><a href="../../../md_rules">Formatting Rules — Markdown</a></li> |
| 92 | <li><a href="../../../wiki_rules">Formatting Rules — Wiki</a></li> |
| 93 | <li><a href="changes.wiki"><b>Fossil Changelog</b></a></li> |
| 94 | <li><a href="concepts.wiki"><b>Fossil Core Concepts</b></a></li> |
| 95 | <li><a href="delta_encoder_algorithm.wiki"><b>Fossil Delta Encoding Algorithm</b></a></li> |
| 96 | <li><a href="delta_format.wiki"><b>Fossil Delta Format</b></a></li> |
| 97 | <li><a href="fileformat.wiki"><b>Fossil File Format</b></a></li> |
| 98 | <li><a href="quickstart.wiki"><b>Fossil Quick Start Guide</b></a></li> |
| 99 | <li><a href="selfcheck.wiki"><b>Fossil Repository Integrity Self Checks</b></a></li> |
| 100 | <li><a href="selfhost.wiki"><b>Fossil Self Hosting Repositories</b></a></li> |
| 101 | <li><a href="settings.wiki"><b>Fossil Settings</b></a></li> |
| 102 | <li><a href="hints.wiki"><b>Fossil Tips And Usage Hints</b></a></li> |
| 103 | <li><a href="fossil-v-git.wiki"><b>Fossil Versus Git</b></a></li> |
| 104 | <li><a href="quotes.wiki">Fossil, Git, and DVCSes in General — Quotes: What People Are Saying About</a></li> |
| 105 | <li><a href="faq.wiki"><b>Frequently Asked Questions</b></a></li> |
| 106 | <li><a href="quotes.wiki">General — Quotes: What People Are Saying About Fossil, Git, and DVCSes in</a></li> |
| 107 | <li><a href="fossil-v-git.wiki">Git — Fossil Versus</a></li> |
| 108 | <li><a href="inout.wiki">Git — Import And Export To And From</a></li> |
| 109 | <li><a href="quotes.wiki">Git, and DVCSes in General — Quotes: What People Are Saying About Fossil,</a></li> |
| 110 | <li><a href="env-opts.md">Global Options — Environment Variables and</a></li> |
| 111 | <li><a href="customgraph.md">Graph — Theming: Customizing the Timeline</a></li> |
| 112 | <li><a href="quickstart.wiki">Guide — Fossil Quick Start</a></li> |
| 113 | <li><a href="style.wiki">Guidelines — Source Code Style</a></li> |
| 114 | <li><a href="hacker-howto.wiki"><b>Hacker How-To</b></a></li> |
| 115 | <li><a href="adding_code.wiki"><b>Hacking Fossil</b></a></li> |
| 116 | <li><a href="hints.wiki">Hints — Fossil Tips And Usage</a></li> |
| 117 | <li><a href="index.wiki"><b>Home Page</b></a></li> |
| 118 | <li><a href="selfhost.wiki">Hosting Repositories — Fossil Self</a></li> |
| 119 | <li><a href="aboutcgi.wiki"><b>How CGI Works In Fossil</b></a></li> |
| 120 | <li><a href="server.wiki"><b>How To Configure A Fossil Server</b></a></li> |
| 121 | <li><a href="newrepo.wiki"><b>How To Create A New Fossil Repository</b></a></li> |
| 122 | <li><a href="encryptedrepos.wiki"><b>How To Use Encrypted Repositories</b></a></li> |
| 123 | <li><a href="hacker-howto.wiki">How-To — Hacker</a></li> |
| 124 | <li><a href="fossil-from-msvc.wiki">IDE — Integrating Fossil in the Microsoft Express 2010</a></li> |
| 125 | <li><a href="tech_overview.wiki">Implementation Of Fossil — A Technical Overview Of The Design And</a></li> |
| 126 | <li><a href="inout.wiki"><b>Import And Export To And From Git</b></a></li> |
| 127 | <li><a href="build.wiki">Installing Fossil — Compiling and</a></li> |
| 128 | <li><a href="fossil-from-msvc.wiki"><b>Integrating Fossil in the Microsoft Express 2010 IDE</b></a></li> |
| 129 | <li><a href="selfcheck.wiki">Integrity Self Checks — Fossil Repository</a></li> |
| 130 | <li><a href="webui.wiki">Interface — The Fossil Web</a></li> |
| 131 | <li><a href="th1.md">Language — The TH1 Scripting</a></li> |
| 132 | <li><a href="copyright-release.html">License Agreement — Contributor</a></li> |
| 133 | <li><a href="../../../help"><b>Lists of Commands and Webpages</b></a></li> |
| 134 | <li><a href="password.wiki">Management And Authentication — Password</a></li> |
| 135 | <li><a href="../../../sitemap">Map — Site</a></li> |
| 136 | <li><a href="../../../md_rules"><b>Markdown Formatting Rules</b></a></li> |
| 137 | <li><a href="branching.wiki">Merging, and Tagging — Branching, Forking,</a></li> |
| 138 | <li><a href="fossil-from-msvc.wiki">Microsoft Express 2010 IDE — Integrating Fossil in the</a></li> |
| 139 | <li><a href="fiveminutes.wiki">Minutes as a Single User — Update and Running in 5</a></li> |
| 140 | <li><a href="checkin_names.wiki">Names — Check-in And Version</a></li> |
| 141 | <li><a href="adding_code.wiki">New Features To Fossil — Adding</a></li> |
| @@ -148,47 +144,46 @@ | |
| 144 | <li><a href="pop.wiki">Operations — Principles Of</a></li> |
| 145 | <li><a href="env-opts.md">Options — Environment Variables and Global</a></li> |
| 146 | <li><a href="tech_overview.wiki">Overview Of The Design And Implementation Of Fossil — A Technical</a></li> |
| 147 | <li><a href="index.wiki">Page — Home</a></li> |
| 148 | <li><a href="customskin.md">Pages — Theming: Customizing The Appearance of Web</a></li> |
| 149 | <li><a href="password.wiki"><b>Password Management And Authentication</b></a></li> |
| 150 | <li><a href="quotes.wiki">People Are Saying About Fossil, Git, and DVCSes in General — Quotes: What</a></li> |
| 151 | <li><a href="stats.wiki"><b>Performance Statistics</b></a></li> |
| 152 | <li><a href="../test/release-checklist.wiki"><b>Pre-Release Testing Checklist</b></a></li> |
| 153 | <li><a href="pop.wiki"><b>Principles Of Operations</b></a></li> |
| 154 | <li><a href="private.wiki">Private Branches — Creating, Syncing, and Deleting</a></li> |
| 155 | <li><a href="makefile.wiki">Process — The Fossil Build</a></li> |
| 156 | <li><a href="contribute.wiki">Project — Contributing Code or Documentation To The Fossil</a></li> |
| 157 | <li><a href="embeddeddoc.wiki">Project Documentation — Embedded</a></li> |
| 158 | <li><a href="foss-cklist.wiki">Projects — Checklist For Successful Open-Source</a></li> |
| 159 | <li><a href="childprojects.wiki">Projects — Child</a></li> |
| 160 | <li><a href="sync.wiki">Protocol — The Fossil Sync</a></li> |
| 161 | <li><a href="faq.wiki">Questions — Frequently Asked</a></li> |
| 162 | <li><a href="qandc.wiki"><b>Questions And Criticisms</b></a></li> |
| 163 | <li><a href="quickstart.wiki">Quick Start Guide — Fossil</a></li> |
| 164 | <li><a href="quotes.wiki"><b>Quotes: What People Are Saying About Fossil, Git, and DVCSes in General</b></a></li> |
| 165 | <li><a href="selfhost.wiki">Repositories — Fossil Self Hosting</a></li> |
| 166 | <li><a href="encryptedrepos.wiki">Repositories — How To Use Encrypted</a></li> |
| 167 | <li><a href="newrepo.wiki">Repository — How To Create A New Fossil</a></li> |
| 168 | <li><a href="selfcheck.wiki">Repository Integrity Self Checks — Fossil</a></li> |
| 169 | <li><a href="reviews.wiki"><b>Reviews</b></a></li> |
| 170 | <li><a href="../../../md_rules">Rules — Markdown Formatting</a></li> |
| 171 | <li><a href="../../../wiki_rules">Rules — Wiki Formatting</a></li> |
| 172 | <li><a href="fiveminutes.wiki">Running in 5 Minutes as a Single User — Update and</a></li> |
| 173 | <li><a href="quotes.wiki">Saying About Fossil, Git, and DVCSes in General — Quotes: What People Are</a></li> |
| 174 | <li><a href="th1.md">Scripting Language — The TH1</a></li> |
| 175 | <li><a href="selfcheck.wiki">Self Checks — Fossil Repository Integrity</a></li> |
| 176 | <li><a href="selfhost.wiki">Self Hosting Repositories — Fossil</a></li> |
| 177 | <li><a href="server.wiki">Server — How To Configure A Fossil</a></li> |
| 178 | <li><a href="settings.wiki">Settings — Fossil</a></li> |
| 179 | <li><a href="shunning.wiki"><b>Shunning: Deleting Content From Fossil</b></a></li> |
| 180 | <li><a href="fiveminutes.wiki">Single User — Update and Running in 5 Minutes as a</a></li> |
| 181 | <li><a href="../../../sitemap"><b>Site Map</b></a></li> |
| 182 | <li><a href="style.wiki"><b>Source Code Style Guidelines</b></a></li> |
| 183 | <li><a href="antibot.wiki">Spiders and Bots — Defense against</a></li> |
| 184 | <li><a href="tech_overview.wiki"><b>SQLite Databases Used By Fossil</b></a></li> |
| 185 | <li><a href="ssl.wiki">SSL with Fossil — Using</a></li> |
| 186 | <li><a href="quickstart.wiki">Start Guide — Fossil Quick</a></li> |
| 187 | <li><a href="stats.wiki">Statistics — Performance</a></li> |
| 188 | <li><a href="style.wiki">Style Guidelines — Source Code</a></li> |
| 189 | <li><a href="foss-cklist.wiki">Successful Open-Source Projects — Checklist For</a></li> |
| @@ -198,42 +193,39 @@ | |
| 193 | <li><a href="tickets.wiki">System — The Fossil Ticket</a></li> |
| 194 | <li><a href="branching.wiki">Tagging — Branching, Forking, Merging, and</a></li> |
| 195 | <li><a href="tech_overview.wiki">Technical Overview Of The Design And Implementation Of Fossil — A</a></li> |
| 196 | <li><a href="../test/release-checklist.wiki">Testing Checklist — Pre-Release</a></li> |
| 197 | <li><a href="th1.md">TH1 Scripting Language — The</a></li> |
| 198 | <li><a href="blame.wiki"><b>The Annotate/Blame Algorithm Of Fossil</b></a></li> |
| 199 | <li><a href="makefile.wiki"><b>The Fossil Build Process</b></a></li> |
| 200 | <li><a href="sync.wiki"><b>The Fossil Sync Protocol</b></a></li> |
| 201 | <li><a href="tickets.wiki"><b>The Fossil Ticket System</b></a></li> |
| 202 | <li><a href="webui.wiki"><b>The Fossil Web Interface</b></a></li> |
| 203 | <li><a href="th1.md"><b>The TH1 Scripting Language</b></a></li> |
| 204 | <li><a href="customskin.md"><b>Theming: Customizing The Appearance of Web Pages</b></a></li> |
| 205 | <li><a href="customgraph.md"><b>Theming: Customizing the Timeline Graph</b></a></li> |
| 206 | <li><a href="theory1.wiki"><b>Thoughts On The Design Of The Fossil DVCS</b></a></li> |
| 207 | <li><a href="custom_ticket.wiki">Ticket System — Customizing The</a></li> |
| 208 | <li><a href="tickets.wiki">Ticket System — The Fossil</a></li> |
| 209 | <li><a href="customgraph.md">Timeline Graph — Theming: Customizing the</a></li> |
| 210 | <li><a href="hints.wiki">Tips And Usage Hints — Fossil</a></li> |
| 211 | <li><a href="bugtheory.wiki">Tracking In Fossil — Bug</a></li> |
| 212 | <li><a href="unvers.wiki"><b>Unversioned Files</b></a></li> |
| 213 | <li><a href="fiveminutes.wiki"><b>Update and Running in 5 Minutes as a Single User</b></a></li> |
| 214 | <li><a href="hints.wiki">Usage Hints — Fossil Tips And</a></li> |
| 215 | <li><a href="fiveminutes.wiki">User — Update and Running in 5 Minutes as a Single</a></li> |
| 216 | <li><a href="ssl.wiki"><b>Using SSL with Fossil</b></a></li> |
| 217 | <li><a href="env-opts.md">Variables and Global Options — Environment</a></li> |
| 218 | <li><a href="whyusefossil.wiki">Version Control — Benefits Of</a></li> |
| 219 | <li><a href="checkin_names.wiki">Version Names — Check-in And</a></li> |
| 220 | <li><a href="fossil-v-git.wiki">Versus Git — Fossil</a></li> |
| 221 | <li><a href="webui.wiki">Web Interface — The Fossil</a></li> |
| 222 | <li><a href="customskin.md">Web Pages — Theming: Customizing The Appearance of</a></li> |
| 223 | <li><a href="webpage-ex.md"><b>Webpage Examples</b></a></li> |
| 224 | <li><a href="../../../help">Webpages — Lists of Commands and</a></li> |
| 225 | <li><a href="quotes.wiki">What People Are Saying About Fossil, Git, and DVCSes in General — Quotes:</a></li> |
| 226 | <li><a href="whyusefossil.wiki"><b>Why You Should Use Fossil</b></a></li> |
| 227 | <li><a href="../../../wiki_rules"><b>Wiki Formatting Rules</b></a></li> |
| 228 | <li><a href="wikitheory.wiki"><b>Wiki In Fossil</b></a></li> |
| 229 | <li><a href="aboutcgi.wiki">Works In Fossil — How CGI</a></li> |
| 230 | <li><a href="whyusefossil.wiki">You Should Use Fossil — Why</a></li> |
| 231 | </ul></div> |
| 232 |
+5
-5
| --- www/pop.wiki | ||
| +++ www/pop.wiki | ||
| @@ -4,18 +4,18 @@ | ||
| 4 | 4 | This page attempts to define the foundational principals upon |
| 5 | 5 | which Fossil is built. |
| 6 | 6 | </p> |
| 7 | 7 | |
| 8 | 8 | <ul> |
| 9 | -<li><p>A project consists of source files, wiki pages, and | |
| 9 | +<li><p>A project consists of source files, wiki pages, and | |
| 10 | 10 | trouble tickets, and control files (collectively "artifacts"). |
| 11 | 11 | All historical copies of all artifacts |
| 12 | 12 | are saved. The project maintains an audit |
| 13 | 13 | trail.</p></li> |
| 14 | 14 | |
| 15 | 15 | <li><p>A project resides in one or more repositories. Each |
| 16 | -repository is administered and operates independently | |
| 16 | +repository is administered and operates independently | |
| 17 | 17 | of the others.</p></li> |
| 18 | 18 | |
| 19 | 19 | <li><p>Each repository has both global and local state. The |
| 20 | 20 | global state is common to all repositories (or at least |
| 21 | 21 | has the potential to be shared in common when the |
| @@ -24,28 +24,28 @@ | ||
| 24 | 24 | The global state represents the content of the project. |
| 25 | 25 | The local state identifies the authorized users and |
| 26 | 26 | access policies for a particular repository.</p></li> |
| 27 | 27 | |
| 28 | 28 | <li><p>The global state of a repository is an unordered |
| 29 | -collection of artifacts. Each artifact is named by | |
| 29 | +collection of artifacts. Each artifact is named by | |
| 30 | 30 | its SHA1 hash encoded in lowercase hexadecimal. |
| 31 | 31 | In many contexts, the name can be |
| 32 | 32 | abbreviated to a unique prefix. A five- or six-character |
| 33 | 33 | prefix usually suffices to uniquely identify a file.</p></li> |
| 34 | 34 | |
| 35 | 35 | <li><p>Because artifacts are named by their SHA1 hash, all artifacts |
| 36 | -are immutable. Any change to the content of an artifact also | |
| 36 | +are immutable. Any change to the content of an artifact also | |
| 37 | 37 | changes the hash that forms the artifacts name, thus |
| 38 | 38 | creating a new artifact. Both the old original version of the |
| 39 | 39 | artifact and the new change are preserved under different names.</p></li> |
| 40 | 40 | |
| 41 | 41 | <li><p>It is theoretically possible for two artifacts with different |
| 42 | 42 | content to share the same hash. But finding two such |
| 43 | 43 | artifacts is so incredibly difficult and unlikely that we |
| 44 | 44 | consider it to be an impossibility.</p></li> |
| 45 | 45 | |
| 46 | -<li><p>The signature of an artifact is the SHA1 hash of the | |
| 46 | +<li><p>The signature of an artifact is the SHA1 hash of the | |
| 47 | 47 | artifact itself, exactly as it would appear in a disk file. No prefix |
| 48 | 48 | or meta-information about the artifact is added before computing |
| 49 | 49 | the hash. So you can |
| 50 | 50 | always find the SHA1 signature of a file by using the |
| 51 | 51 | "sha1sum" command-line utility.</p></li> |
| 52 | 52 |
| --- www/pop.wiki | |
| +++ www/pop.wiki | |
| @@ -4,18 +4,18 @@ | |
| 4 | This page attempts to define the foundational principals upon |
| 5 | which Fossil is built. |
| 6 | </p> |
| 7 | |
| 8 | <ul> |
| 9 | <li><p>A project consists of source files, wiki pages, and |
| 10 | trouble tickets, and control files (collectively "artifacts"). |
| 11 | All historical copies of all artifacts |
| 12 | are saved. The project maintains an audit |
| 13 | trail.</p></li> |
| 14 | |
| 15 | <li><p>A project resides in one or more repositories. Each |
| 16 | repository is administered and operates independently |
| 17 | of the others.</p></li> |
| 18 | |
| 19 | <li><p>Each repository has both global and local state. The |
| 20 | global state is common to all repositories (or at least |
| 21 | has the potential to be shared in common when the |
| @@ -24,28 +24,28 @@ | |
| 24 | The global state represents the content of the project. |
| 25 | The local state identifies the authorized users and |
| 26 | access policies for a particular repository.</p></li> |
| 27 | |
| 28 | <li><p>The global state of a repository is an unordered |
| 29 | collection of artifacts. Each artifact is named by |
| 30 | its SHA1 hash encoded in lowercase hexadecimal. |
| 31 | In many contexts, the name can be |
| 32 | abbreviated to a unique prefix. A five- or six-character |
| 33 | prefix usually suffices to uniquely identify a file.</p></li> |
| 34 | |
| 35 | <li><p>Because artifacts are named by their SHA1 hash, all artifacts |
| 36 | are immutable. Any change to the content of an artifact also |
| 37 | changes the hash that forms the artifacts name, thus |
| 38 | creating a new artifact. Both the old original version of the |
| 39 | artifact and the new change are preserved under different names.</p></li> |
| 40 | |
| 41 | <li><p>It is theoretically possible for two artifacts with different |
| 42 | content to share the same hash. But finding two such |
| 43 | artifacts is so incredibly difficult and unlikely that we |
| 44 | consider it to be an impossibility.</p></li> |
| 45 | |
| 46 | <li><p>The signature of an artifact is the SHA1 hash of the |
| 47 | artifact itself, exactly as it would appear in a disk file. No prefix |
| 48 | or meta-information about the artifact is added before computing |
| 49 | the hash. So you can |
| 50 | always find the SHA1 signature of a file by using the |
| 51 | "sha1sum" command-line utility.</p></li> |
| 52 |
| --- www/pop.wiki | |
| +++ www/pop.wiki | |
| @@ -4,18 +4,18 @@ | |
| 4 | This page attempts to define the foundational principals upon |
| 5 | which Fossil is built. |
| 6 | </p> |
| 7 | |
| 8 | <ul> |
| 9 | <li><p>A project consists of source files, wiki pages, and |
| 10 | trouble tickets, and control files (collectively "artifacts"). |
| 11 | All historical copies of all artifacts |
| 12 | are saved. The project maintains an audit |
| 13 | trail.</p></li> |
| 14 | |
| 15 | <li><p>A project resides in one or more repositories. Each |
| 16 | repository is administered and operates independently |
| 17 | of the others.</p></li> |
| 18 | |
| 19 | <li><p>Each repository has both global and local state. The |
| 20 | global state is common to all repositories (or at least |
| 21 | has the potential to be shared in common when the |
| @@ -24,28 +24,28 @@ | |
| 24 | The global state represents the content of the project. |
| 25 | The local state identifies the authorized users and |
| 26 | access policies for a particular repository.</p></li> |
| 27 | |
| 28 | <li><p>The global state of a repository is an unordered |
| 29 | collection of artifacts. Each artifact is named by |
| 30 | its SHA1 hash encoded in lowercase hexadecimal. |
| 31 | In many contexts, the name can be |
| 32 | abbreviated to a unique prefix. A five- or six-character |
| 33 | prefix usually suffices to uniquely identify a file.</p></li> |
| 34 | |
| 35 | <li><p>Because artifacts are named by their SHA1 hash, all artifacts |
| 36 | are immutable. Any change to the content of an artifact also |
| 37 | changes the hash that forms the artifacts name, thus |
| 38 | creating a new artifact. Both the old original version of the |
| 39 | artifact and the new change are preserved under different names.</p></li> |
| 40 | |
| 41 | <li><p>It is theoretically possible for two artifacts with different |
| 42 | content to share the same hash. But finding two such |
| 43 | artifacts is so incredibly difficult and unlikely that we |
| 44 | consider it to be an impossibility.</p></li> |
| 45 | |
| 46 | <li><p>The signature of an artifact is the SHA1 hash of the |
| 47 | artifact itself, exactly as it would appear in a disk file. No prefix |
| 48 | or meta-information about the artifact is added before computing |
| 49 | the hash. So you can |
| 50 | always find the SHA1 signature of a file by using the |
| 51 | "sha1sum" command-line utility.</p></li> |
| 52 |
+3
-3
| --- www/private.wiki | ||
| +++ www/private.wiki | ||
| @@ -41,11 +41,11 @@ | ||
| 41 | 41 | <h2>Syncing Private Branches</h2> |
| 42 | 42 | |
| 43 | 43 | A private branch normally stays on the one repository where it was |
| 44 | 44 | originally created. But sometimes you want to share private branches |
| 45 | 45 | with another repository. For example, you might be building a cross-platform |
| 46 | -application and have separate repositories on your Windows laptop, | |
| 46 | +application and have separate repositories on your Windows laptop, | |
| 47 | 47 | your Linux desktop, and your iMac. You can transfer private branches |
| 48 | 48 | between these machines by using the --private option on the "sync", |
| 49 | 49 | "push", "pull", and "clone" commands. For example, if you are running |
| 50 | 50 | "fossil server" on your Linux box and you want to clone that repository |
| 51 | 51 | to your Mac, including all private branches, use: |
| @@ -67,11 +67,11 @@ | ||
| 67 | 67 | only enable "x" for local repositories when you need to share private |
| 68 | 68 | branches. |
| 69 | 69 | |
| 70 | 70 | Private branch sync only works if you use the --private command-line option. |
| 71 | 71 | Private branches are never synced via the auto-sync mechanism. Once |
| 72 | -again, this restriction is designed to make it hard to accidently | |
| 72 | +again, this restriction is designed to make it hard to accidently | |
| 73 | 73 | push private branches beyond their intended audience. |
| 74 | 74 | |
| 75 | 75 | <h2>Purging Private Branches</h2> |
| 76 | 76 | |
| 77 | 77 | You can remove all private branches from a repository using this command: |
| @@ -85,10 +85,10 @@ | ||
| 85 | 85 | removed, they cannot be retrieved (unless you have synced them to another |
| 86 | 86 | repository.) So be careful with the command. |
| 87 | 87 | |
| 88 | 88 | <h2>Additional Notes</h2> |
| 89 | 89 | |
| 90 | -All of the features above apply to <u>all</u> private branches in a | |
| 90 | +All of the features above apply to <u>all</u> private branches in a | |
| 91 | 91 | single repository at once. There is no mechanism in Fossil (currently) |
| 92 | 92 | that allows you to push, pull, clone, sync, or scrub and individual |
| 93 | 93 | private branch within a repository that contains multiple private |
| 94 | 94 | branches. |
| 95 | 95 |
| --- www/private.wiki | |
| +++ www/private.wiki | |
| @@ -41,11 +41,11 @@ | |
| 41 | <h2>Syncing Private Branches</h2> |
| 42 | |
| 43 | A private branch normally stays on the one repository where it was |
| 44 | originally created. But sometimes you want to share private branches |
| 45 | with another repository. For example, you might be building a cross-platform |
| 46 | application and have separate repositories on your Windows laptop, |
| 47 | your Linux desktop, and your iMac. You can transfer private branches |
| 48 | between these machines by using the --private option on the "sync", |
| 49 | "push", "pull", and "clone" commands. For example, if you are running |
| 50 | "fossil server" on your Linux box and you want to clone that repository |
| 51 | to your Mac, including all private branches, use: |
| @@ -67,11 +67,11 @@ | |
| 67 | only enable "x" for local repositories when you need to share private |
| 68 | branches. |
| 69 | |
| 70 | Private branch sync only works if you use the --private command-line option. |
| 71 | Private branches are never synced via the auto-sync mechanism. Once |
| 72 | again, this restriction is designed to make it hard to accidently |
| 73 | push private branches beyond their intended audience. |
| 74 | |
| 75 | <h2>Purging Private Branches</h2> |
| 76 | |
| 77 | You can remove all private branches from a repository using this command: |
| @@ -85,10 +85,10 @@ | |
| 85 | removed, they cannot be retrieved (unless you have synced them to another |
| 86 | repository.) So be careful with the command. |
| 87 | |
| 88 | <h2>Additional Notes</h2> |
| 89 | |
| 90 | All of the features above apply to <u>all</u> private branches in a |
| 91 | single repository at once. There is no mechanism in Fossil (currently) |
| 92 | that allows you to push, pull, clone, sync, or scrub and individual |
| 93 | private branch within a repository that contains multiple private |
| 94 | branches. |
| 95 |
| --- www/private.wiki | |
| +++ www/private.wiki | |
| @@ -41,11 +41,11 @@ | |
| 41 | <h2>Syncing Private Branches</h2> |
| 42 | |
| 43 | A private branch normally stays on the one repository where it was |
| 44 | originally created. But sometimes you want to share private branches |
| 45 | with another repository. For example, you might be building a cross-platform |
| 46 | application and have separate repositories on your Windows laptop, |
| 47 | your Linux desktop, and your iMac. You can transfer private branches |
| 48 | between these machines by using the --private option on the "sync", |
| 49 | "push", "pull", and "clone" commands. For example, if you are running |
| 50 | "fossil server" on your Linux box and you want to clone that repository |
| 51 | to your Mac, including all private branches, use: |
| @@ -67,11 +67,11 @@ | |
| 67 | only enable "x" for local repositories when you need to share private |
| 68 | branches. |
| 69 | |
| 70 | Private branch sync only works if you use the --private command-line option. |
| 71 | Private branches are never synced via the auto-sync mechanism. Once |
| 72 | again, this restriction is designed to make it hard to accidently |
| 73 | push private branches beyond their intended audience. |
| 74 | |
| 75 | <h2>Purging Private Branches</h2> |
| 76 | |
| 77 | You can remove all private branches from a repository using this command: |
| @@ -85,10 +85,10 @@ | |
| 85 | removed, they cannot be retrieved (unless you have synced them to another |
| 86 | repository.) So be careful with the command. |
| 87 | |
| 88 | <h2>Additional Notes</h2> |
| 89 | |
| 90 | All of the features above apply to <u>all</u> private branches in a |
| 91 | single repository at once. There is no mechanism in Fossil (currently) |
| 92 | that allows you to push, pull, clone, sync, or scrub and individual |
| 93 | private branch within a repository that contains multiple private |
| 94 | branches. |
| 95 |
+10
-10
| --- www/qandc.wiki | ||
| +++ www/qandc.wiki | ||
| @@ -22,11 +22,11 @@ | ||
| 22 | 22 | <li> Integrated <a href="wikitheory.wiki">wiki</a>. </li> |
| 23 | 23 | <li> Integrated <a href="bugtheory.wiki">bug tracking</a> </li> |
| 24 | 24 | <li> Immutable artifacts </li> |
| 25 | 25 | <li> Self-contained, stand-alone executable that can be run in |
| 26 | 26 | a <a href="http://en.wikipedia.org/wiki/Chroot">chroot jail</a> </li> |
| 27 | - <li> Simple, well-defined, | |
| 27 | + <li> Simple, well-defined, | |
| 28 | 28 | <a href="fileformat.wiki">enduring file format</a> </li> |
| 29 | 29 | <li> Integrated <a href="webui.wiki">web interface</a> </li> |
| 30 | 30 | </ol> |
| 31 | 31 | </blockquote> |
| 32 | 32 | |
| @@ -36,11 +36,11 @@ | ||
| 36 | 36 | <ol> |
| 37 | 37 | <li> Fossil is distributed. You can view and/or edit tickets, wiki, and |
| 38 | 38 | code while off network, then sync your changes later. With Trac, you |
| 39 | 39 | can only view and edit tickets and wiki while you are connected to |
| 40 | 40 | the server. </li> |
| 41 | - <li> Fossil is lightweight and fully self-contained. It is very easy | |
| 41 | + <li> Fossil is lightweight and fully self-contained. It is very easy | |
| 42 | 42 | to setup on a low-resource machine. Fossil does not require an |
| 43 | 43 | administrator.</li> |
| 44 | 44 | <li> Fossil integrates code versioning into the same repository with |
| 45 | 45 | wiki and tickets. There is nothing extra to add or install. |
| 46 | 46 | Fossil is an all-in-one turnkey solution. </li> |
| @@ -48,25 +48,25 @@ | ||
| 48 | 48 | </blockquote> |
| 49 | 49 | |
| 50 | 50 | <b>Love the concept here. Anyone using this for real work yet?</b> |
| 51 | 51 | |
| 52 | 52 | <blockquote> |
| 53 | -Fossil is <a href="http://www.fossil-scm.org/">self-hosting</a>. | |
| 53 | +Fossil is <a href="http://www.fossil-scm.org/">self-hosting</a>. | |
| 54 | 54 | In fact, this page was probably delivered |
| 55 | 55 | to your web-browser via a working fossil instance. The same virtual |
| 56 | 56 | machine that hosts http://www.fossil-scm.org/ |
| 57 | 57 | (a <a href="http://www.linode.com/">Linode 720</a>) |
| 58 | 58 | also hosts 24 other fossil repositories for various small projects. |
| 59 | -The documentation files for | |
| 59 | +The documentation files for | |
| 60 | 60 | <a href="http://www.sqlite.org/">SQLite</a> are hosted in a |
| 61 | 61 | fossil repository <a href="http://www.sqlite.org/docsrc/">here</a>, |
| 62 | 62 | for example. |
| 63 | 63 | Other projects are also adopting fossil. But fossil does not yet have |
| 64 | 64 | the massive user base of git or mercurial. |
| 65 | 65 | </blockquote> |
| 66 | 66 | |
| 67 | -<b>Fossil looks like the bug tracker that would be in your | |
| 67 | +<b>Fossil looks like the bug tracker that would be in your | |
| 68 | 68 | Linksys Router's administration screen.</b> |
| 69 | 69 | |
| 70 | 70 | <blockquote> |
| 71 | 71 | <p>I take a pragmatic approach to software: form follows function. |
| 72 | 72 | To me, it is more important to have a reliable, fast, efficient, |
| @@ -83,11 +83,11 @@ | ||
| 83 | 83 | keeps the bug-tracking database in a versioned file. That file can |
| 84 | 84 | then be pushed and pulled along with the rest repository.</b> |
| 85 | 85 | |
| 86 | 86 | <blockquote> |
| 87 | 87 | <p>Fossil already <u>does</u> push and pull bugs along with the files |
| 88 | -in your repository. | |
| 88 | +in your repository. | |
| 89 | 89 | But fossil does <u>not</u> track bugs as files in the source tree. |
| 90 | 90 | That approach to bug tracking was rejected for three reasons:</p> |
| 91 | 91 | |
| 92 | 92 | <ol> |
| 93 | 93 | <li> Check-ins in fossil are immutable. So if |
| @@ -108,11 +108,11 @@ | ||
| 108 | 108 | |
| 109 | 109 | <p>These points are reiterated in the opening paragraphs of |
| 110 | 110 | the <a href="bugtheory.wiki">Bug-Tracking In Fossil</a> document.</p> |
| 111 | 111 | </blockquote> |
| 112 | 112 | |
| 113 | -<b>Fossil is already the name of a plan9 versioned | |
| 113 | +<b>Fossil is already the name of a plan9 versioned | |
| 114 | 114 | append-only filesystem.</b> |
| 115 | 115 | |
| 116 | 116 | <blockquote> |
| 117 | 117 | I did not know that. Perhaps they selected the name for the same reason that |
| 118 | 118 | I did: because a repository with immutable artifacts preserves |
| @@ -137,22 +137,22 @@ | ||
| 137 | 137 | Subversion or Bazaar.</b> |
| 138 | 138 | |
| 139 | 139 | <blockquote> |
| 140 | 140 | <p>I have no doubt that Trac has many features that fossil lacks. But that |
| 141 | 141 | is not the point. Fossil has several key features that Trac lacks and that |
| 142 | -I need: most notably the fact that | |
| 142 | +I need: most notably the fact that | |
| 143 | 143 | fossil supports disconnected operation.</p> |
| 144 | 144 | |
| 145 | 145 | <p>As for bloat: Fossil is a single self-contained executable. |
| 146 | -You do not need any other packages | |
| 146 | +You do not need any other packages | |
| 147 | 147 | (diff, patch, merge, cvs, svn, rcs, git, python, perl, tcl, apache, |
| 148 | 148 | sqlite, and so forth) |
| 149 | 149 | in order to run fossil. Fossil runs just fine in a chroot jail all |
| 150 | 150 | by itself. And the self-contained fossil |
| 151 | 151 | executable is much less than 1MB in size. (Update 2015-01-12: Fossil has |
| 152 | -grown in the years since the previous sentence was written but is still | |
| 152 | +grown in the years since the previous sentence was written but is still | |
| 153 | 153 | much less than 2MB according to "size" when compiled using -Os on x64 Linux.) |
| 154 | 154 | Fossil is the very opposite of bloat.</p> |
| 155 | 155 | </blockquote> |
| 156 | 156 | |
| 157 | 157 | |
| 158 | 158 | </nowiki> |
| 159 | 159 |
| --- www/qandc.wiki | |
| +++ www/qandc.wiki | |
| @@ -22,11 +22,11 @@ | |
| 22 | <li> Integrated <a href="wikitheory.wiki">wiki</a>. </li> |
| 23 | <li> Integrated <a href="bugtheory.wiki">bug tracking</a> </li> |
| 24 | <li> Immutable artifacts </li> |
| 25 | <li> Self-contained, stand-alone executable that can be run in |
| 26 | a <a href="http://en.wikipedia.org/wiki/Chroot">chroot jail</a> </li> |
| 27 | <li> Simple, well-defined, |
| 28 | <a href="fileformat.wiki">enduring file format</a> </li> |
| 29 | <li> Integrated <a href="webui.wiki">web interface</a> </li> |
| 30 | </ol> |
| 31 | </blockquote> |
| 32 | |
| @@ -36,11 +36,11 @@ | |
| 36 | <ol> |
| 37 | <li> Fossil is distributed. You can view and/or edit tickets, wiki, and |
| 38 | code while off network, then sync your changes later. With Trac, you |
| 39 | can only view and edit tickets and wiki while you are connected to |
| 40 | the server. </li> |
| 41 | <li> Fossil is lightweight and fully self-contained. It is very easy |
| 42 | to setup on a low-resource machine. Fossil does not require an |
| 43 | administrator.</li> |
| 44 | <li> Fossil integrates code versioning into the same repository with |
| 45 | wiki and tickets. There is nothing extra to add or install. |
| 46 | Fossil is an all-in-one turnkey solution. </li> |
| @@ -48,25 +48,25 @@ | |
| 48 | </blockquote> |
| 49 | |
| 50 | <b>Love the concept here. Anyone using this for real work yet?</b> |
| 51 | |
| 52 | <blockquote> |
| 53 | Fossil is <a href="http://www.fossil-scm.org/">self-hosting</a>. |
| 54 | In fact, this page was probably delivered |
| 55 | to your web-browser via a working fossil instance. The same virtual |
| 56 | machine that hosts http://www.fossil-scm.org/ |
| 57 | (a <a href="http://www.linode.com/">Linode 720</a>) |
| 58 | also hosts 24 other fossil repositories for various small projects. |
| 59 | The documentation files for |
| 60 | <a href="http://www.sqlite.org/">SQLite</a> are hosted in a |
| 61 | fossil repository <a href="http://www.sqlite.org/docsrc/">here</a>, |
| 62 | for example. |
| 63 | Other projects are also adopting fossil. But fossil does not yet have |
| 64 | the massive user base of git or mercurial. |
| 65 | </blockquote> |
| 66 | |
| 67 | <b>Fossil looks like the bug tracker that would be in your |
| 68 | Linksys Router's administration screen.</b> |
| 69 | |
| 70 | <blockquote> |
| 71 | <p>I take a pragmatic approach to software: form follows function. |
| 72 | To me, it is more important to have a reliable, fast, efficient, |
| @@ -83,11 +83,11 @@ | |
| 83 | keeps the bug-tracking database in a versioned file. That file can |
| 84 | then be pushed and pulled along with the rest repository.</b> |
| 85 | |
| 86 | <blockquote> |
| 87 | <p>Fossil already <u>does</u> push and pull bugs along with the files |
| 88 | in your repository. |
| 89 | But fossil does <u>not</u> track bugs as files in the source tree. |
| 90 | That approach to bug tracking was rejected for three reasons:</p> |
| 91 | |
| 92 | <ol> |
| 93 | <li> Check-ins in fossil are immutable. So if |
| @@ -108,11 +108,11 @@ | |
| 108 | |
| 109 | <p>These points are reiterated in the opening paragraphs of |
| 110 | the <a href="bugtheory.wiki">Bug-Tracking In Fossil</a> document.</p> |
| 111 | </blockquote> |
| 112 | |
| 113 | <b>Fossil is already the name of a plan9 versioned |
| 114 | append-only filesystem.</b> |
| 115 | |
| 116 | <blockquote> |
| 117 | I did not know that. Perhaps they selected the name for the same reason that |
| 118 | I did: because a repository with immutable artifacts preserves |
| @@ -137,22 +137,22 @@ | |
| 137 | Subversion or Bazaar.</b> |
| 138 | |
| 139 | <blockquote> |
| 140 | <p>I have no doubt that Trac has many features that fossil lacks. But that |
| 141 | is not the point. Fossil has several key features that Trac lacks and that |
| 142 | I need: most notably the fact that |
| 143 | fossil supports disconnected operation.</p> |
| 144 | |
| 145 | <p>As for bloat: Fossil is a single self-contained executable. |
| 146 | You do not need any other packages |
| 147 | (diff, patch, merge, cvs, svn, rcs, git, python, perl, tcl, apache, |
| 148 | sqlite, and so forth) |
| 149 | in order to run fossil. Fossil runs just fine in a chroot jail all |
| 150 | by itself. And the self-contained fossil |
| 151 | executable is much less than 1MB in size. (Update 2015-01-12: Fossil has |
| 152 | grown in the years since the previous sentence was written but is still |
| 153 | much less than 2MB according to "size" when compiled using -Os on x64 Linux.) |
| 154 | Fossil is the very opposite of bloat.</p> |
| 155 | </blockquote> |
| 156 | |
| 157 | |
| 158 | </nowiki> |
| 159 |
| --- www/qandc.wiki | |
| +++ www/qandc.wiki | |
| @@ -22,11 +22,11 @@ | |
| 22 | <li> Integrated <a href="wikitheory.wiki">wiki</a>. </li> |
| 23 | <li> Integrated <a href="bugtheory.wiki">bug tracking</a> </li> |
| 24 | <li> Immutable artifacts </li> |
| 25 | <li> Self-contained, stand-alone executable that can be run in |
| 26 | a <a href="http://en.wikipedia.org/wiki/Chroot">chroot jail</a> </li> |
| 27 | <li> Simple, well-defined, |
| 28 | <a href="fileformat.wiki">enduring file format</a> </li> |
| 29 | <li> Integrated <a href="webui.wiki">web interface</a> </li> |
| 30 | </ol> |
| 31 | </blockquote> |
| 32 | |
| @@ -36,11 +36,11 @@ | |
| 36 | <ol> |
| 37 | <li> Fossil is distributed. You can view and/or edit tickets, wiki, and |
| 38 | code while off network, then sync your changes later. With Trac, you |
| 39 | can only view and edit tickets and wiki while you are connected to |
| 40 | the server. </li> |
| 41 | <li> Fossil is lightweight and fully self-contained. It is very easy |
| 42 | to setup on a low-resource machine. Fossil does not require an |
| 43 | administrator.</li> |
| 44 | <li> Fossil integrates code versioning into the same repository with |
| 45 | wiki and tickets. There is nothing extra to add or install. |
| 46 | Fossil is an all-in-one turnkey solution. </li> |
| @@ -48,25 +48,25 @@ | |
| 48 | </blockquote> |
| 49 | |
| 50 | <b>Love the concept here. Anyone using this for real work yet?</b> |
| 51 | |
| 52 | <blockquote> |
| 53 | Fossil is <a href="http://www.fossil-scm.org/">self-hosting</a>. |
| 54 | In fact, this page was probably delivered |
| 55 | to your web-browser via a working fossil instance. The same virtual |
| 56 | machine that hosts http://www.fossil-scm.org/ |
| 57 | (a <a href="http://www.linode.com/">Linode 720</a>) |
| 58 | also hosts 24 other fossil repositories for various small projects. |
| 59 | The documentation files for |
| 60 | <a href="http://www.sqlite.org/">SQLite</a> are hosted in a |
| 61 | fossil repository <a href="http://www.sqlite.org/docsrc/">here</a>, |
| 62 | for example. |
| 63 | Other projects are also adopting fossil. But fossil does not yet have |
| 64 | the massive user base of git or mercurial. |
| 65 | </blockquote> |
| 66 | |
| 67 | <b>Fossil looks like the bug tracker that would be in your |
| 68 | Linksys Router's administration screen.</b> |
| 69 | |
| 70 | <blockquote> |
| 71 | <p>I take a pragmatic approach to software: form follows function. |
| 72 | To me, it is more important to have a reliable, fast, efficient, |
| @@ -83,11 +83,11 @@ | |
| 83 | keeps the bug-tracking database in a versioned file. That file can |
| 84 | then be pushed and pulled along with the rest repository.</b> |
| 85 | |
| 86 | <blockquote> |
| 87 | <p>Fossil already <u>does</u> push and pull bugs along with the files |
| 88 | in your repository. |
| 89 | But fossil does <u>not</u> track bugs as files in the source tree. |
| 90 | That approach to bug tracking was rejected for three reasons:</p> |
| 91 | |
| 92 | <ol> |
| 93 | <li> Check-ins in fossil are immutable. So if |
| @@ -108,11 +108,11 @@ | |
| 108 | |
| 109 | <p>These points are reiterated in the opening paragraphs of |
| 110 | the <a href="bugtheory.wiki">Bug-Tracking In Fossil</a> document.</p> |
| 111 | </blockquote> |
| 112 | |
| 113 | <b>Fossil is already the name of a plan9 versioned |
| 114 | append-only filesystem.</b> |
| 115 | |
| 116 | <blockquote> |
| 117 | I did not know that. Perhaps they selected the name for the same reason that |
| 118 | I did: because a repository with immutable artifacts preserves |
| @@ -137,22 +137,22 @@ | |
| 137 | Subversion or Bazaar.</b> |
| 138 | |
| 139 | <blockquote> |
| 140 | <p>I have no doubt that Trac has many features that fossil lacks. But that |
| 141 | is not the point. Fossil has several key features that Trac lacks and that |
| 142 | I need: most notably the fact that |
| 143 | fossil supports disconnected operation.</p> |
| 144 | |
| 145 | <p>As for bloat: Fossil is a single self-contained executable. |
| 146 | You do not need any other packages |
| 147 | (diff, patch, merge, cvs, svn, rcs, git, python, perl, tcl, apache, |
| 148 | sqlite, and so forth) |
| 149 | in order to run fossil. Fossil runs just fine in a chroot jail all |
| 150 | by itself. And the self-contained fossil |
| 151 | executable is much less than 1MB in size. (Update 2015-01-12: Fossil has |
| 152 | grown in the years since the previous sentence was written but is still |
| 153 | much less than 2MB according to "size" when compiled using -Os on x64 Linux.) |
| 154 | Fossil is the very opposite of bloat.</p> |
| 155 | </blockquote> |
| 156 | |
| 157 | |
| 158 | </nowiki> |
| 159 |
+26
-26
| --- www/quickstart.wiki | ||
| +++ www/quickstart.wiki | ||
| @@ -5,16 +5,16 @@ | ||
| 5 | 5 | and painlessly.</p> |
| 6 | 6 | |
| 7 | 7 | <h2>Installing</h2> |
| 8 | 8 | |
| 9 | 9 | <p>Fossil is a single self-contained C program. You need to |
| 10 | - either download a | |
| 10 | + either download a | |
| 11 | 11 | <a href="http://www.fossil-scm.org/download.html">precompiled binary</a> |
| 12 | 12 | or <a href="build.wiki">compile it yourself</a> from sources. |
| 13 | 13 | Install fossil by putting the fossil binary |
| 14 | 14 | someplace on your $PATH.</p> |
| 15 | - | |
| 15 | + | |
| 16 | 16 | <a name="fslclone"></a> |
| 17 | 17 | <h2>General Work Flow</h2> |
| 18 | 18 | |
| 19 | 19 | <p>Fossil works with repository files (a database with the project's |
| 20 | 20 | complete history) and with checked-out local trees (the working directory |
| @@ -34,11 +34,11 @@ | ||
| 34 | 34 | |
| 35 | 35 | <h2>Starting A New Project</h2> |
| 36 | 36 | |
| 37 | 37 | <p>To start a new project with fossil, create a new empty repository |
| 38 | 38 | this way: ([/help/init | more info]) </p> |
| 39 | - | |
| 39 | + | |
| 40 | 40 | <blockquote> |
| 41 | 41 | <b>fossil init </b><i> repository-filename</i> |
| 42 | 42 | </blockquote> |
| 43 | 43 | |
| 44 | 44 | <h2>Cloning An Existing Repository</h2> |
| @@ -46,36 +46,36 @@ | ||
| 46 | 46 | <p>Most fossil operations interact with a repository that is on the |
| 47 | 47 | local disk drive, not on a remote system. Hence, before accessing |
| 48 | 48 | a remote repository it is necessary to make a local copy of that |
| 49 | 49 | repository. Making a local copy of a remote repository is called |
| 50 | 50 | "cloning".</p> |
| 51 | - | |
| 51 | + | |
| 52 | 52 | <p>Clone a remote repository as follows: ([/help/clone | more info])</p> |
| 53 | - | |
| 53 | + | |
| 54 | 54 | <blockquote> |
| 55 | 55 | <b>fossil clone</b> <i>URL repository-filename</i> |
| 56 | 56 | </blockquote> |
| 57 | - | |
| 57 | + | |
| 58 | 58 | <p>The <i>URL</i> specifies the fossil repository |
| 59 | 59 | you want to clone. The <i>repository-filename</i> is the new local |
| 60 | 60 | filename into which the cloned repository will be written. For |
| 61 | 61 | example: |
| 62 | - | |
| 62 | + | |
| 63 | 63 | <blockquote> |
| 64 | 64 | <b>fossil clone http://www.fossil-scm.org/ myclone.fossil</b> |
| 65 | 65 | </blockquote> |
| 66 | 66 | |
| 67 | - <p>If the remote repository requires a login, include a | |
| 67 | + <p>If the remote repository requires a login, include a | |
| 68 | 68 | userid in the URL like this: |
| 69 | 69 | |
| 70 | 70 | <blockquote> |
| 71 | 71 | <b>fossil clone http://</b><i>userid</i><b>@www.fossil-scm.org/ myclone.fossil</b> |
| 72 | 72 | </blockquote> |
| 73 | - | |
| 73 | + | |
| 74 | 74 | |
| 75 | 75 | <p>You will be prompted separately for the password. |
| 76 | - Use "%HH" escapes for special characters in the userid. | |
| 76 | + Use "%HH" escapes for special characters in the userid. | |
| 77 | 77 | Examples: "%40" in place of "@" and "%2F" in place of "/". |
| 78 | 78 | |
| 79 | 79 | <p>If you are behind a restrictive firewall, you might need |
| 80 | 80 | to <a href="#proxy">specify an HTTP proxy</a>.</p> |
| 81 | 81 | |
| @@ -85,31 +85,31 @@ | ||
| 85 | 85 | information above and beyond the versioned files, including some |
| 86 | 86 | sensitive information such as password hashes and email addresses. If you |
| 87 | 87 | want to share Fossil repositories directly, consider running the |
| 88 | 88 | [/help/scrub|fossil scrub] command to remove sensitive information |
| 89 | 89 | before transmitting the file. |
| 90 | - | |
| 90 | + | |
| 91 | 91 | <h2>Importing From Another Version Control System</h2> |
| 92 | 92 | |
| 93 | 93 | <p>Rather than start a new project, or clone an existing Fossil project, |
| 94 | - you might prefer to | |
| 94 | + you might prefer to | |
| 95 | 95 | <a href="./inout.wiki">import an existing Git project</a> |
| 96 | 96 | into Fossil using the [/help/import | fossil import] command. |
| 97 | 97 | |
| 98 | 98 | <h2>Checking Out A Local Tree</h2> |
| 99 | 99 | |
| 100 | 100 | <p>To work on a project in fossil, you need to check out a local |
| 101 | 101 | copy of the source tree. Create the directory you want to be |
| 102 | 102 | the root of your tree and cd into that directory. Then |
| 103 | 103 | do this: ([/help/open | more info])</p> |
| 104 | - | |
| 104 | + | |
| 105 | 105 | <blockquote> |
| 106 | 106 | <b>fossil open </b><i> repository-filename</i> |
| 107 | 107 | </blockquote> |
| 108 | - | |
| 108 | + | |
| 109 | 109 | <p>This leaves you with the newest version of the tree |
| 110 | - checked out. | |
| 110 | + checked out. | |
| 111 | 111 | From anywhere underneath the root of your local tree, you |
| 112 | 112 | can type commands like the following to find out the status of |
| 113 | 113 | your local tree:</p> |
| 114 | 114 | |
| 115 | 115 | <blockquote> |
| @@ -122,11 +122,11 @@ | ||
| 122 | 122 | <b>[/help/branch | fossil branch]</b><br> |
| 123 | 123 | </blockquote> |
| 124 | 124 | |
| 125 | 125 | <p>Note that Fossil allows you to make multiple check-outs in |
| 126 | 126 | separate directories from the same repository. This enables you, |
| 127 | - for example, to do builds from multiple branches or versions at | |
| 127 | + for example, to do builds from multiple branches or versions at | |
| 128 | 128 | the same time without having to generate extra clones.</p> |
| 129 | 129 | |
| 130 | 130 | <p>To switch a checkout between different versions and branches, |
| 131 | 131 | use:</p> |
| 132 | 132 | |
| @@ -140,17 +140,17 @@ | ||
| 140 | 140 | version, whereas [/help/checkout | checkout] does not |
| 141 | 141 | automatically sync and does a "hard" switch, overwriting local |
| 142 | 142 | changes if told to do so.</p> |
| 143 | 143 | |
| 144 | 144 | <h2>Configuring Your Local Repository</h2> |
| 145 | - | |
| 145 | + | |
| 146 | 146 | <p>When you create a new repository, either by cloning an existing |
| 147 | 147 | project or create a new project of your own, you usually want to do some |
| 148 | 148 | local configuration. This is easily accomplished using the web-server |
| 149 | 149 | that is built into fossil. Start the fossil webserver like this: |
| 150 | 150 | ([/help/ui | more info])</p> |
| 151 | - | |
| 151 | + | |
| 152 | 152 | <blockquote> |
| 153 | 153 | <b>fossil ui </b><i> repository-filename</i> |
| 154 | 154 | </blockquote> |
| 155 | 155 | |
| 156 | 156 | <p>You can omit the <i>repository-filename</i> from the command above |
| @@ -163,15 +163,15 @@ | ||
| 163 | 163 | where to find your web browser using a command like this:</p> |
| 164 | 164 | |
| 165 | 165 | <blockquote> |
| 166 | 166 | <b>fossil setting web-browser </b><i> path-to-web-browser</i> |
| 167 | 167 | </blockquote> |
| 168 | - | |
| 168 | + | |
| 169 | 169 | <p>By default, fossil does not require a login for HTTP connections |
| 170 | 170 | coming in from the IP loopback address 127.0.0.1. You can, and perhaps |
| 171 | 171 | should, change this after you create a few users.</p> |
| 172 | - | |
| 172 | + | |
| 173 | 173 | <p>When you are finished configuring, just press Control-C or use |
| 174 | 174 | the <b>kill</b> command to shut down the mini-server.</p> |
| 175 | 175 | |
| 176 | 176 | <h2>Making Changes</h2> |
| 177 | 177 | |
| @@ -194,18 +194,18 @@ | ||
| 194 | 194 | <p>You will be prompted for check-in comments using whatever editor |
| 195 | 195 | is specified by your VISUAL or EDITOR environment variable.</p> |
| 196 | 196 | |
| 197 | 197 | In the default configuration, the [/help/commit|commit] |
| 198 | 198 | command will also automatically [/help/push|push] your changes, but that |
| 199 | - feature can be disabled. (More information about | |
| 199 | + feature can be disabled. (More information about | |
| 200 | 200 | [./concepts.wiki#workflow|autosync] and how to disable it.) |
| 201 | - Remember that your coworkers can not see your changes until you | |
| 201 | + Remember that your coworkers can not see your changes until you | |
| 202 | 202 | commit and push them.</p> |
| 203 | 203 | |
| 204 | 204 | <h2>Sharing Changes</h2> |
| 205 | 205 | |
| 206 | - <p>When [./concepts.wiki#workflow|autosync] is turned off, | |
| 206 | + <p>When [./concepts.wiki#workflow|autosync] is turned off, | |
| 207 | 207 | the changes you [/help/commit | commit] are only |
| 208 | 208 | on your local repository. |
| 209 | 209 | To share those changes with other repositories, do:</p> |
| 210 | 210 | |
| 211 | 211 | <blockquote> |
| @@ -241,11 +241,11 @@ | ||
| 241 | 241 | the <i>VERSION</i>, then fossil moves you to the |
| 242 | 242 | latest version of the branch your are currently on.</p> |
| 243 | 243 | |
| 244 | 244 | <p>The default behavior is for [./concepts.wiki#workflow|autosync] to |
| 245 | 245 | be turned on. That means that a [/help/pull|pull] automatically occurs |
| 246 | - when you run [/help/update|update] and a [/help/push|push] happens | |
| 246 | + when you run [/help/update|update] and a [/help/push|push] happens | |
| 247 | 247 | automatically after you [/help/commit|commit]. So in normal practice, |
| 248 | 248 | the push, pull, and sync commands are rarely used. But it is important |
| 249 | 249 | to know about them, all the same.</p> |
| 250 | 250 | |
| 251 | 251 | <blockquote> |
| @@ -342,11 +342,11 @@ | ||
| 342 | 342 | <li>[./server.wiki#cgi|CGI] |
| 343 | 343 | <li>[./server.wiki#scgi|SCGI] |
| 344 | 344 | </ul> |
| 345 | 345 | |
| 346 | 346 | <p>The [./selfhost.wiki | self-hosting fossil repositories] use |
| 347 | - CGI. | |
| 347 | + CGI. | |
| 348 | 348 | |
| 349 | 349 | <a name="proxy"></a> |
| 350 | 350 | <h2>HTTP Proxies</h2> |
| 351 | 351 | |
| 352 | 352 | <p>If you are behind a restrictive firewall that requires you to use |
| @@ -382,11 +382,11 @@ | ||
| 382 | 382 | <p>Or unset the environment variable. The fossil setting for the |
| 383 | 383 | HTTP proxy takes precedence over the environment variable and the |
| 384 | 384 | command-line option overrides both. If you have an persistent |
| 385 | 385 | proxy setting that you want to override for a one-time sync, that |
| 386 | 386 | is easily done on the command-line. For example, to sync with |
| 387 | - a co-workers repository on your LAN, you might type:</p> | |
| 387 | + a co-workers repository on your LAN, you might type:</p> | |
| 388 | 388 | |
| 389 | 389 | <blockquote> |
| 390 | 390 | <b>fossil sync http://192.168.1.36:8080/ --proxy off</b> |
| 391 | 391 | </blockquote> |
| 392 | 392 | |
| 393 | 393 |
| --- www/quickstart.wiki | |
| +++ www/quickstart.wiki | |
| @@ -5,16 +5,16 @@ | |
| 5 | and painlessly.</p> |
| 6 | |
| 7 | <h2>Installing</h2> |
| 8 | |
| 9 | <p>Fossil is a single self-contained C program. You need to |
| 10 | either download a |
| 11 | <a href="http://www.fossil-scm.org/download.html">precompiled binary</a> |
| 12 | or <a href="build.wiki">compile it yourself</a> from sources. |
| 13 | Install fossil by putting the fossil binary |
| 14 | someplace on your $PATH.</p> |
| 15 | |
| 16 | <a name="fslclone"></a> |
| 17 | <h2>General Work Flow</h2> |
| 18 | |
| 19 | <p>Fossil works with repository files (a database with the project's |
| 20 | complete history) and with checked-out local trees (the working directory |
| @@ -34,11 +34,11 @@ | |
| 34 | |
| 35 | <h2>Starting A New Project</h2> |
| 36 | |
| 37 | <p>To start a new project with fossil, create a new empty repository |
| 38 | this way: ([/help/init | more info]) </p> |
| 39 | |
| 40 | <blockquote> |
| 41 | <b>fossil init </b><i> repository-filename</i> |
| 42 | </blockquote> |
| 43 | |
| 44 | <h2>Cloning An Existing Repository</h2> |
| @@ -46,36 +46,36 @@ | |
| 46 | <p>Most fossil operations interact with a repository that is on the |
| 47 | local disk drive, not on a remote system. Hence, before accessing |
| 48 | a remote repository it is necessary to make a local copy of that |
| 49 | repository. Making a local copy of a remote repository is called |
| 50 | "cloning".</p> |
| 51 | |
| 52 | <p>Clone a remote repository as follows: ([/help/clone | more info])</p> |
| 53 | |
| 54 | <blockquote> |
| 55 | <b>fossil clone</b> <i>URL repository-filename</i> |
| 56 | </blockquote> |
| 57 | |
| 58 | <p>The <i>URL</i> specifies the fossil repository |
| 59 | you want to clone. The <i>repository-filename</i> is the new local |
| 60 | filename into which the cloned repository will be written. For |
| 61 | example: |
| 62 | |
| 63 | <blockquote> |
| 64 | <b>fossil clone http://www.fossil-scm.org/ myclone.fossil</b> |
| 65 | </blockquote> |
| 66 | |
| 67 | <p>If the remote repository requires a login, include a |
| 68 | userid in the URL like this: |
| 69 | |
| 70 | <blockquote> |
| 71 | <b>fossil clone http://</b><i>userid</i><b>@www.fossil-scm.org/ myclone.fossil</b> |
| 72 | </blockquote> |
| 73 | |
| 74 | |
| 75 | <p>You will be prompted separately for the password. |
| 76 | Use "%HH" escapes for special characters in the userid. |
| 77 | Examples: "%40" in place of "@" and "%2F" in place of "/". |
| 78 | |
| 79 | <p>If you are behind a restrictive firewall, you might need |
| 80 | to <a href="#proxy">specify an HTTP proxy</a>.</p> |
| 81 | |
| @@ -85,31 +85,31 @@ | |
| 85 | information above and beyond the versioned files, including some |
| 86 | sensitive information such as password hashes and email addresses. If you |
| 87 | want to share Fossil repositories directly, consider running the |
| 88 | [/help/scrub|fossil scrub] command to remove sensitive information |
| 89 | before transmitting the file. |
| 90 | |
| 91 | <h2>Importing From Another Version Control System</h2> |
| 92 | |
| 93 | <p>Rather than start a new project, or clone an existing Fossil project, |
| 94 | you might prefer to |
| 95 | <a href="./inout.wiki">import an existing Git project</a> |
| 96 | into Fossil using the [/help/import | fossil import] command. |
| 97 | |
| 98 | <h2>Checking Out A Local Tree</h2> |
| 99 | |
| 100 | <p>To work on a project in fossil, you need to check out a local |
| 101 | copy of the source tree. Create the directory you want to be |
| 102 | the root of your tree and cd into that directory. Then |
| 103 | do this: ([/help/open | more info])</p> |
| 104 | |
| 105 | <blockquote> |
| 106 | <b>fossil open </b><i> repository-filename</i> |
| 107 | </blockquote> |
| 108 | |
| 109 | <p>This leaves you with the newest version of the tree |
| 110 | checked out. |
| 111 | From anywhere underneath the root of your local tree, you |
| 112 | can type commands like the following to find out the status of |
| 113 | your local tree:</p> |
| 114 | |
| 115 | <blockquote> |
| @@ -122,11 +122,11 @@ | |
| 122 | <b>[/help/branch | fossil branch]</b><br> |
| 123 | </blockquote> |
| 124 | |
| 125 | <p>Note that Fossil allows you to make multiple check-outs in |
| 126 | separate directories from the same repository. This enables you, |
| 127 | for example, to do builds from multiple branches or versions at |
| 128 | the same time without having to generate extra clones.</p> |
| 129 | |
| 130 | <p>To switch a checkout between different versions and branches, |
| 131 | use:</p> |
| 132 | |
| @@ -140,17 +140,17 @@ | |
| 140 | version, whereas [/help/checkout | checkout] does not |
| 141 | automatically sync and does a "hard" switch, overwriting local |
| 142 | changes if told to do so.</p> |
| 143 | |
| 144 | <h2>Configuring Your Local Repository</h2> |
| 145 | |
| 146 | <p>When you create a new repository, either by cloning an existing |
| 147 | project or create a new project of your own, you usually want to do some |
| 148 | local configuration. This is easily accomplished using the web-server |
| 149 | that is built into fossil. Start the fossil webserver like this: |
| 150 | ([/help/ui | more info])</p> |
| 151 | |
| 152 | <blockquote> |
| 153 | <b>fossil ui </b><i> repository-filename</i> |
| 154 | </blockquote> |
| 155 | |
| 156 | <p>You can omit the <i>repository-filename</i> from the command above |
| @@ -163,15 +163,15 @@ | |
| 163 | where to find your web browser using a command like this:</p> |
| 164 | |
| 165 | <blockquote> |
| 166 | <b>fossil setting web-browser </b><i> path-to-web-browser</i> |
| 167 | </blockquote> |
| 168 | |
| 169 | <p>By default, fossil does not require a login for HTTP connections |
| 170 | coming in from the IP loopback address 127.0.0.1. You can, and perhaps |
| 171 | should, change this after you create a few users.</p> |
| 172 | |
| 173 | <p>When you are finished configuring, just press Control-C or use |
| 174 | the <b>kill</b> command to shut down the mini-server.</p> |
| 175 | |
| 176 | <h2>Making Changes</h2> |
| 177 | |
| @@ -194,18 +194,18 @@ | |
| 194 | <p>You will be prompted for check-in comments using whatever editor |
| 195 | is specified by your VISUAL or EDITOR environment variable.</p> |
| 196 | |
| 197 | In the default configuration, the [/help/commit|commit] |
| 198 | command will also automatically [/help/push|push] your changes, but that |
| 199 | feature can be disabled. (More information about |
| 200 | [./concepts.wiki#workflow|autosync] and how to disable it.) |
| 201 | Remember that your coworkers can not see your changes until you |
| 202 | commit and push them.</p> |
| 203 | |
| 204 | <h2>Sharing Changes</h2> |
| 205 | |
| 206 | <p>When [./concepts.wiki#workflow|autosync] is turned off, |
| 207 | the changes you [/help/commit | commit] are only |
| 208 | on your local repository. |
| 209 | To share those changes with other repositories, do:</p> |
| 210 | |
| 211 | <blockquote> |
| @@ -241,11 +241,11 @@ | |
| 241 | the <i>VERSION</i>, then fossil moves you to the |
| 242 | latest version of the branch your are currently on.</p> |
| 243 | |
| 244 | <p>The default behavior is for [./concepts.wiki#workflow|autosync] to |
| 245 | be turned on. That means that a [/help/pull|pull] automatically occurs |
| 246 | when you run [/help/update|update] and a [/help/push|push] happens |
| 247 | automatically after you [/help/commit|commit]. So in normal practice, |
| 248 | the push, pull, and sync commands are rarely used. But it is important |
| 249 | to know about them, all the same.</p> |
| 250 | |
| 251 | <blockquote> |
| @@ -342,11 +342,11 @@ | |
| 342 | <li>[./server.wiki#cgi|CGI] |
| 343 | <li>[./server.wiki#scgi|SCGI] |
| 344 | </ul> |
| 345 | |
| 346 | <p>The [./selfhost.wiki | self-hosting fossil repositories] use |
| 347 | CGI. |
| 348 | |
| 349 | <a name="proxy"></a> |
| 350 | <h2>HTTP Proxies</h2> |
| 351 | |
| 352 | <p>If you are behind a restrictive firewall that requires you to use |
| @@ -382,11 +382,11 @@ | |
| 382 | <p>Or unset the environment variable. The fossil setting for the |
| 383 | HTTP proxy takes precedence over the environment variable and the |
| 384 | command-line option overrides both. If you have an persistent |
| 385 | proxy setting that you want to override for a one-time sync, that |
| 386 | is easily done on the command-line. For example, to sync with |
| 387 | a co-workers repository on your LAN, you might type:</p> |
| 388 | |
| 389 | <blockquote> |
| 390 | <b>fossil sync http://192.168.1.36:8080/ --proxy off</b> |
| 391 | </blockquote> |
| 392 | |
| 393 |
| --- www/quickstart.wiki | |
| +++ www/quickstart.wiki | |
| @@ -5,16 +5,16 @@ | |
| 5 | and painlessly.</p> |
| 6 | |
| 7 | <h2>Installing</h2> |
| 8 | |
| 9 | <p>Fossil is a single self-contained C program. You need to |
| 10 | either download a |
| 11 | <a href="http://www.fossil-scm.org/download.html">precompiled binary</a> |
| 12 | or <a href="build.wiki">compile it yourself</a> from sources. |
| 13 | Install fossil by putting the fossil binary |
| 14 | someplace on your $PATH.</p> |
| 15 | |
| 16 | <a name="fslclone"></a> |
| 17 | <h2>General Work Flow</h2> |
| 18 | |
| 19 | <p>Fossil works with repository files (a database with the project's |
| 20 | complete history) and with checked-out local trees (the working directory |
| @@ -34,11 +34,11 @@ | |
| 34 | |
| 35 | <h2>Starting A New Project</h2> |
| 36 | |
| 37 | <p>To start a new project with fossil, create a new empty repository |
| 38 | this way: ([/help/init | more info]) </p> |
| 39 | |
| 40 | <blockquote> |
| 41 | <b>fossil init </b><i> repository-filename</i> |
| 42 | </blockquote> |
| 43 | |
| 44 | <h2>Cloning An Existing Repository</h2> |
| @@ -46,36 +46,36 @@ | |
| 46 | <p>Most fossil operations interact with a repository that is on the |
| 47 | local disk drive, not on a remote system. Hence, before accessing |
| 48 | a remote repository it is necessary to make a local copy of that |
| 49 | repository. Making a local copy of a remote repository is called |
| 50 | "cloning".</p> |
| 51 | |
| 52 | <p>Clone a remote repository as follows: ([/help/clone | more info])</p> |
| 53 | |
| 54 | <blockquote> |
| 55 | <b>fossil clone</b> <i>URL repository-filename</i> |
| 56 | </blockquote> |
| 57 | |
| 58 | <p>The <i>URL</i> specifies the fossil repository |
| 59 | you want to clone. The <i>repository-filename</i> is the new local |
| 60 | filename into which the cloned repository will be written. For |
| 61 | example: |
| 62 | |
| 63 | <blockquote> |
| 64 | <b>fossil clone http://www.fossil-scm.org/ myclone.fossil</b> |
| 65 | </blockquote> |
| 66 | |
| 67 | <p>If the remote repository requires a login, include a |
| 68 | userid in the URL like this: |
| 69 | |
| 70 | <blockquote> |
| 71 | <b>fossil clone http://</b><i>userid</i><b>@www.fossil-scm.org/ myclone.fossil</b> |
| 72 | </blockquote> |
| 73 | |
| 74 | |
| 75 | <p>You will be prompted separately for the password. |
| 76 | Use "%HH" escapes for special characters in the userid. |
| 77 | Examples: "%40" in place of "@" and "%2F" in place of "/". |
| 78 | |
| 79 | <p>If you are behind a restrictive firewall, you might need |
| 80 | to <a href="#proxy">specify an HTTP proxy</a>.</p> |
| 81 | |
| @@ -85,31 +85,31 @@ | |
| 85 | information above and beyond the versioned files, including some |
| 86 | sensitive information such as password hashes and email addresses. If you |
| 87 | want to share Fossil repositories directly, consider running the |
| 88 | [/help/scrub|fossil scrub] command to remove sensitive information |
| 89 | before transmitting the file. |
| 90 | |
| 91 | <h2>Importing From Another Version Control System</h2> |
| 92 | |
| 93 | <p>Rather than start a new project, or clone an existing Fossil project, |
| 94 | you might prefer to |
| 95 | <a href="./inout.wiki">import an existing Git project</a> |
| 96 | into Fossil using the [/help/import | fossil import] command. |
| 97 | |
| 98 | <h2>Checking Out A Local Tree</h2> |
| 99 | |
| 100 | <p>To work on a project in fossil, you need to check out a local |
| 101 | copy of the source tree. Create the directory you want to be |
| 102 | the root of your tree and cd into that directory. Then |
| 103 | do this: ([/help/open | more info])</p> |
| 104 | |
| 105 | <blockquote> |
| 106 | <b>fossil open </b><i> repository-filename</i> |
| 107 | </blockquote> |
| 108 | |
| 109 | <p>This leaves you with the newest version of the tree |
| 110 | checked out. |
| 111 | From anywhere underneath the root of your local tree, you |
| 112 | can type commands like the following to find out the status of |
| 113 | your local tree:</p> |
| 114 | |
| 115 | <blockquote> |
| @@ -122,11 +122,11 @@ | |
| 122 | <b>[/help/branch | fossil branch]</b><br> |
| 123 | </blockquote> |
| 124 | |
| 125 | <p>Note that Fossil allows you to make multiple check-outs in |
| 126 | separate directories from the same repository. This enables you, |
| 127 | for example, to do builds from multiple branches or versions at |
| 128 | the same time without having to generate extra clones.</p> |
| 129 | |
| 130 | <p>To switch a checkout between different versions and branches, |
| 131 | use:</p> |
| 132 | |
| @@ -140,17 +140,17 @@ | |
| 140 | version, whereas [/help/checkout | checkout] does not |
| 141 | automatically sync and does a "hard" switch, overwriting local |
| 142 | changes if told to do so.</p> |
| 143 | |
| 144 | <h2>Configuring Your Local Repository</h2> |
| 145 | |
| 146 | <p>When you create a new repository, either by cloning an existing |
| 147 | project or create a new project of your own, you usually want to do some |
| 148 | local configuration. This is easily accomplished using the web-server |
| 149 | that is built into fossil. Start the fossil webserver like this: |
| 150 | ([/help/ui | more info])</p> |
| 151 | |
| 152 | <blockquote> |
| 153 | <b>fossil ui </b><i> repository-filename</i> |
| 154 | </blockquote> |
| 155 | |
| 156 | <p>You can omit the <i>repository-filename</i> from the command above |
| @@ -163,15 +163,15 @@ | |
| 163 | where to find your web browser using a command like this:</p> |
| 164 | |
| 165 | <blockquote> |
| 166 | <b>fossil setting web-browser </b><i> path-to-web-browser</i> |
| 167 | </blockquote> |
| 168 | |
| 169 | <p>By default, fossil does not require a login for HTTP connections |
| 170 | coming in from the IP loopback address 127.0.0.1. You can, and perhaps |
| 171 | should, change this after you create a few users.</p> |
| 172 | |
| 173 | <p>When you are finished configuring, just press Control-C or use |
| 174 | the <b>kill</b> command to shut down the mini-server.</p> |
| 175 | |
| 176 | <h2>Making Changes</h2> |
| 177 | |
| @@ -194,18 +194,18 @@ | |
| 194 | <p>You will be prompted for check-in comments using whatever editor |
| 195 | is specified by your VISUAL or EDITOR environment variable.</p> |
| 196 | |
| 197 | In the default configuration, the [/help/commit|commit] |
| 198 | command will also automatically [/help/push|push] your changes, but that |
| 199 | feature can be disabled. (More information about |
| 200 | [./concepts.wiki#workflow|autosync] and how to disable it.) |
| 201 | Remember that your coworkers can not see your changes until you |
| 202 | commit and push them.</p> |
| 203 | |
| 204 | <h2>Sharing Changes</h2> |
| 205 | |
| 206 | <p>When [./concepts.wiki#workflow|autosync] is turned off, |
| 207 | the changes you [/help/commit | commit] are only |
| 208 | on your local repository. |
| 209 | To share those changes with other repositories, do:</p> |
| 210 | |
| 211 | <blockquote> |
| @@ -241,11 +241,11 @@ | |
| 241 | the <i>VERSION</i>, then fossil moves you to the |
| 242 | latest version of the branch your are currently on.</p> |
| 243 | |
| 244 | <p>The default behavior is for [./concepts.wiki#workflow|autosync] to |
| 245 | be turned on. That means that a [/help/pull|pull] automatically occurs |
| 246 | when you run [/help/update|update] and a [/help/push|push] happens |
| 247 | automatically after you [/help/commit|commit]. So in normal practice, |
| 248 | the push, pull, and sync commands are rarely used. But it is important |
| 249 | to know about them, all the same.</p> |
| 250 | |
| 251 | <blockquote> |
| @@ -342,11 +342,11 @@ | |
| 342 | <li>[./server.wiki#cgi|CGI] |
| 343 | <li>[./server.wiki#scgi|SCGI] |
| 344 | </ul> |
| 345 | |
| 346 | <p>The [./selfhost.wiki | self-hosting fossil repositories] use |
| 347 | CGI. |
| 348 | |
| 349 | <a name="proxy"></a> |
| 350 | <h2>HTTP Proxies</h2> |
| 351 | |
| 352 | <p>If you are behind a restrictive firewall that requires you to use |
| @@ -382,11 +382,11 @@ | |
| 382 | <p>Or unset the environment variable. The fossil setting for the |
| 383 | HTTP proxy takes precedence over the environment variable and the |
| 384 | command-line option overrides both. If you have an persistent |
| 385 | proxy setting that you want to override for a one-time sync, that |
| 386 | is easily done on the command-line. For example, to sync with |
| 387 | a co-workers repository on your LAN, you might type:</p> |
| 388 | |
| 389 | <blockquote> |
| 390 | <b>fossil sync http://192.168.1.36:8080/ --proxy off</b> |
| 391 | </blockquote> |
| 392 | |
| 393 |
+13
-13
| --- www/quotes.wiki | ||
| +++ www/quotes.wiki | ||
| @@ -5,19 +5,19 @@ | ||
| 5 | 5 | by the creator of Fossil, so of course there is selection bias... |
| 6 | 6 | |
| 7 | 7 | <h2>On The Usability Of Git:</h2> |
| 8 | 8 | |
| 9 | 9 | <ol> |
| 10 | -<li>Git approaches the usability of iptables, which is to say, utterly | |
| 10 | +<li>Git approaches the usability of iptables, which is to say, utterly | |
| 11 | 11 | unusable unless you have the manpage tattooed on you arm. |
| 12 | 12 | |
| 13 | 13 | <blockquote> |
| 14 | 14 | <i>by mml at [http://news.ycombinator.com/item?id=1433387]</i> |
| 15 | 15 | </blockquote> |
| 16 | 16 | |
| 17 | 17 | <li><nowiki>It's simplest to think of the state of your [git] repository |
| 18 | -as a point in a high-dimensional "code-space", in which branches are | |
| 18 | +as a point in a high-dimensional "code-space", in which branches are | |
| 19 | 19 | represented as n-dimensional membranes, mapping the spatial loci of |
| 20 | 20 | successive commits onto the projected manifold of each cloned |
| 21 | 21 | repository.</nowiki> |
| 22 | 22 | |
| 23 | 23 | <blockquote> |
| @@ -25,11 +25,11 @@ | ||
| 25 | 25 | </blockquote> |
| 26 | 26 | |
| 27 | 27 | <li>Git is not a Prius. Git is a Model T. |
| 28 | 28 | Its plumbing and wiring sticks out all over the place. |
| 29 | 29 | You have to be a mechanic to operate it successfully or you'll be |
| 30 | -stuck on the side of the road when it breaks down. | |
| 30 | +stuck on the side of the road when it breaks down. | |
| 31 | 31 | And it <b>will</b> break down. |
| 32 | 32 | |
| 33 | 33 | <blockquote> |
| 34 | 34 | <i>Nick Farina at [http://nfarina.com/post/9868516270/git-is-simpler]</i> |
| 35 | 35 | </blockquote> |
| @@ -39,11 +39,11 @@ | ||
| 39 | 39 | <blockquote> |
| 40 | 40 | <i>Linus Torvalds - 2005-04-07 22:13:13<br> |
| 41 | 41 | Commit comment on the very first source-code check-in for git |
| 42 | 42 | </blockquote> |
| 43 | 43 | |
| 44 | -<li>I've been experimenting a lot with git at work. | |
| 44 | +<li>I've been experimenting a lot with git at work. | |
| 45 | 45 | Damn, it's complicated. |
| 46 | 46 | It has things to trip you up with that sane people just wouldn't ever both with |
| 47 | 47 | including the ability to allow you to commit stuff in such a way that you can't find |
| 48 | 48 | it again afterwards (!!!) |
| 49 | 49 | Demented workflow complexity on acid? |
| @@ -104,19 +104,19 @@ | ||
| 104 | 104 | |
| 105 | 105 | <blockquote> |
| 106 | 106 | <i>Joe Prostko at [http://www.mail-archive.com/[email protected]/msg16716.html] |
| 107 | 107 | </blockquote> |
| 108 | 108 | |
| 109 | -<li>Fossil is awesome!!! I have never seen an app like that before, | |
| 109 | +<li>Fossil is awesome!!! I have never seen an app like that before, | |
| 110 | 110 | such simplicity and flexibility!!! |
| 111 | 111 | |
| 112 | 112 | <blockquote> |
| 113 | 113 | <i>zengr at [http://stackoverflow.com/questions/138621/best-version-control-for-lone-developer]</i> |
| 114 | 114 | </blockquote> |
| 115 | 115 | |
| 116 | 116 | <li>This is my favourite VCS. I can carry it on a USB. And it's a complete system, with it's own |
| 117 | -server, ticketing system, Wiki pages, and a very, very helpful timeline visualization. And | |
| 117 | +server, ticketing system, Wiki pages, and a very, very helpful timeline visualization. And | |
| 118 | 118 | the entire program in a single file! |
| 119 | 119 | |
| 120 | 120 | <blockquote> |
| 121 | 121 | <i>thunderbong commenting on hacker news: [https://news.ycombinator.com/item?id=9131619]</i> |
| 122 | 122 | </blockquote> |
| @@ -127,30 +127,30 @@ | ||
| 127 | 127 | |
| 128 | 128 | <h2>On Git Versus Fossil</h2> |
| 129 | 129 | |
| 130 | 130 | <ol> |
| 131 | 131 | <li value=15> |
| 132 | -Just want to say thanks for fossil making my life easier.... | |
| 132 | +Just want to say thanks for fossil making my life easier.... | |
| 133 | 133 | Also <nowiki>[for]</nowiki> not having a misanthropic command line interface. |
| 134 | 134 | |
| 135 | 135 | <blockquote> |
| 136 | 136 | <i>Joshua Paine at [http://www.mail-archive.com/[email protected]/msg02736.html]</i> |
| 137 | 137 | </blockquote> |
| 138 | 138 | |
| 139 | 139 | <li>We use it at a large university to manage code that small teams write. |
| 140 | -The runs everywhere, ease of installation and portability is something that | |
| 141 | -seems to be a good fit with the environment we have (highly ditrobuted, | |
| 142 | -sometimes very restrictive firewalls, OSX/Win/Linux). We are happy with it | |
| 143 | -and teaching a Msc/Phd student (read complete novice) fossil has just | |
| 140 | +The runs everywhere, ease of installation and portability is something that | |
| 141 | +seems to be a good fit with the environment we have (highly ditrobuted, | |
| 142 | +sometimes very restrictive firewalls, OSX/Win/Linux). We are happy with it | |
| 143 | +and teaching a Msc/Phd student (read complete novice) fossil has just | |
| 144 | 144 | been a smoother ride than Git was. |
| 145 | 145 | |
| 146 | 146 | <blockquote> |
| 147 | 147 | <i>viablepanic at [http://www.reddit.com/r/programming/comments/bxcto/why_not_fossil_scm/]</i> |
| 148 | 148 | </blockquote> |
| 149 | 149 | |
| 150 | -<li>In the fossil community - and hence in fossil itself - development history | |
| 151 | -is pretty much sacrosanct. The very name "fossil" was to chosen to | |
| 150 | +<li>In the fossil community - and hence in fossil itself - development history | |
| 151 | +is pretty much sacrosanct. The very name "fossil" was to chosen to | |
| 152 | 152 | reflect the unchanging nature of things in that history. |
| 153 | 153 | |
| 154 | 154 | <p>In git (or rather, the git community), the development history is part of |
| 155 | 155 | the published aspect of the project, so it provides tools for rearranging |
| 156 | 156 | that history so you can present what you "should" have done rather |
| 157 | 157 |
| --- www/quotes.wiki | |
| +++ www/quotes.wiki | |
| @@ -5,19 +5,19 @@ | |
| 5 | by the creator of Fossil, so of course there is selection bias... |
| 6 | |
| 7 | <h2>On The Usability Of Git:</h2> |
| 8 | |
| 9 | <ol> |
| 10 | <li>Git approaches the usability of iptables, which is to say, utterly |
| 11 | unusable unless you have the manpage tattooed on you arm. |
| 12 | |
| 13 | <blockquote> |
| 14 | <i>by mml at [http://news.ycombinator.com/item?id=1433387]</i> |
| 15 | </blockquote> |
| 16 | |
| 17 | <li><nowiki>It's simplest to think of the state of your [git] repository |
| 18 | as a point in a high-dimensional "code-space", in which branches are |
| 19 | represented as n-dimensional membranes, mapping the spatial loci of |
| 20 | successive commits onto the projected manifold of each cloned |
| 21 | repository.</nowiki> |
| 22 | |
| 23 | <blockquote> |
| @@ -25,11 +25,11 @@ | |
| 25 | </blockquote> |
| 26 | |
| 27 | <li>Git is not a Prius. Git is a Model T. |
| 28 | Its plumbing and wiring sticks out all over the place. |
| 29 | You have to be a mechanic to operate it successfully or you'll be |
| 30 | stuck on the side of the road when it breaks down. |
| 31 | And it <b>will</b> break down. |
| 32 | |
| 33 | <blockquote> |
| 34 | <i>Nick Farina at [http://nfarina.com/post/9868516270/git-is-simpler]</i> |
| 35 | </blockquote> |
| @@ -39,11 +39,11 @@ | |
| 39 | <blockquote> |
| 40 | <i>Linus Torvalds - 2005-04-07 22:13:13<br> |
| 41 | Commit comment on the very first source-code check-in for git |
| 42 | </blockquote> |
| 43 | |
| 44 | <li>I've been experimenting a lot with git at work. |
| 45 | Damn, it's complicated. |
| 46 | It has things to trip you up with that sane people just wouldn't ever both with |
| 47 | including the ability to allow you to commit stuff in such a way that you can't find |
| 48 | it again afterwards (!!!) |
| 49 | Demented workflow complexity on acid? |
| @@ -104,19 +104,19 @@ | |
| 104 | |
| 105 | <blockquote> |
| 106 | <i>Joe Prostko at [http://www.mail-archive.com/[email protected]/msg16716.html] |
| 107 | </blockquote> |
| 108 | |
| 109 | <li>Fossil is awesome!!! I have never seen an app like that before, |
| 110 | such simplicity and flexibility!!! |
| 111 | |
| 112 | <blockquote> |
| 113 | <i>zengr at [http://stackoverflow.com/questions/138621/best-version-control-for-lone-developer]</i> |
| 114 | </blockquote> |
| 115 | |
| 116 | <li>This is my favourite VCS. I can carry it on a USB. And it's a complete system, with it's own |
| 117 | server, ticketing system, Wiki pages, and a very, very helpful timeline visualization. And |
| 118 | the entire program in a single file! |
| 119 | |
| 120 | <blockquote> |
| 121 | <i>thunderbong commenting on hacker news: [https://news.ycombinator.com/item?id=9131619]</i> |
| 122 | </blockquote> |
| @@ -127,30 +127,30 @@ | |
| 127 | |
| 128 | <h2>On Git Versus Fossil</h2> |
| 129 | |
| 130 | <ol> |
| 131 | <li value=15> |
| 132 | Just want to say thanks for fossil making my life easier.... |
| 133 | Also <nowiki>[for]</nowiki> not having a misanthropic command line interface. |
| 134 | |
| 135 | <blockquote> |
| 136 | <i>Joshua Paine at [http://www.mail-archive.com/[email protected]/msg02736.html]</i> |
| 137 | </blockquote> |
| 138 | |
| 139 | <li>We use it at a large university to manage code that small teams write. |
| 140 | The runs everywhere, ease of installation and portability is something that |
| 141 | seems to be a good fit with the environment we have (highly ditrobuted, |
| 142 | sometimes very restrictive firewalls, OSX/Win/Linux). We are happy with it |
| 143 | and teaching a Msc/Phd student (read complete novice) fossil has just |
| 144 | been a smoother ride than Git was. |
| 145 | |
| 146 | <blockquote> |
| 147 | <i>viablepanic at [http://www.reddit.com/r/programming/comments/bxcto/why_not_fossil_scm/]</i> |
| 148 | </blockquote> |
| 149 | |
| 150 | <li>In the fossil community - and hence in fossil itself - development history |
| 151 | is pretty much sacrosanct. The very name "fossil" was to chosen to |
| 152 | reflect the unchanging nature of things in that history. |
| 153 | |
| 154 | <p>In git (or rather, the git community), the development history is part of |
| 155 | the published aspect of the project, so it provides tools for rearranging |
| 156 | that history so you can present what you "should" have done rather |
| 157 |
| --- www/quotes.wiki | |
| +++ www/quotes.wiki | |
| @@ -5,19 +5,19 @@ | |
| 5 | by the creator of Fossil, so of course there is selection bias... |
| 6 | |
| 7 | <h2>On The Usability Of Git:</h2> |
| 8 | |
| 9 | <ol> |
| 10 | <li>Git approaches the usability of iptables, which is to say, utterly |
| 11 | unusable unless you have the manpage tattooed on you arm. |
| 12 | |
| 13 | <blockquote> |
| 14 | <i>by mml at [http://news.ycombinator.com/item?id=1433387]</i> |
| 15 | </blockquote> |
| 16 | |
| 17 | <li><nowiki>It's simplest to think of the state of your [git] repository |
| 18 | as a point in a high-dimensional "code-space", in which branches are |
| 19 | represented as n-dimensional membranes, mapping the spatial loci of |
| 20 | successive commits onto the projected manifold of each cloned |
| 21 | repository.</nowiki> |
| 22 | |
| 23 | <blockquote> |
| @@ -25,11 +25,11 @@ | |
| 25 | </blockquote> |
| 26 | |
| 27 | <li>Git is not a Prius. Git is a Model T. |
| 28 | Its plumbing and wiring sticks out all over the place. |
| 29 | You have to be a mechanic to operate it successfully or you'll be |
| 30 | stuck on the side of the road when it breaks down. |
| 31 | And it <b>will</b> break down. |
| 32 | |
| 33 | <blockquote> |
| 34 | <i>Nick Farina at [http://nfarina.com/post/9868516270/git-is-simpler]</i> |
| 35 | </blockquote> |
| @@ -39,11 +39,11 @@ | |
| 39 | <blockquote> |
| 40 | <i>Linus Torvalds - 2005-04-07 22:13:13<br> |
| 41 | Commit comment on the very first source-code check-in for git |
| 42 | </blockquote> |
| 43 | |
| 44 | <li>I've been experimenting a lot with git at work. |
| 45 | Damn, it's complicated. |
| 46 | It has things to trip you up with that sane people just wouldn't ever both with |
| 47 | including the ability to allow you to commit stuff in such a way that you can't find |
| 48 | it again afterwards (!!!) |
| 49 | Demented workflow complexity on acid? |
| @@ -104,19 +104,19 @@ | |
| 104 | |
| 105 | <blockquote> |
| 106 | <i>Joe Prostko at [http://www.mail-archive.com/[email protected]/msg16716.html] |
| 107 | </blockquote> |
| 108 | |
| 109 | <li>Fossil is awesome!!! I have never seen an app like that before, |
| 110 | such simplicity and flexibility!!! |
| 111 | |
| 112 | <blockquote> |
| 113 | <i>zengr at [http://stackoverflow.com/questions/138621/best-version-control-for-lone-developer]</i> |
| 114 | </blockquote> |
| 115 | |
| 116 | <li>This is my favourite VCS. I can carry it on a USB. And it's a complete system, with it's own |
| 117 | server, ticketing system, Wiki pages, and a very, very helpful timeline visualization. And |
| 118 | the entire program in a single file! |
| 119 | |
| 120 | <blockquote> |
| 121 | <i>thunderbong commenting on hacker news: [https://news.ycombinator.com/item?id=9131619]</i> |
| 122 | </blockquote> |
| @@ -127,30 +127,30 @@ | |
| 127 | |
| 128 | <h2>On Git Versus Fossil</h2> |
| 129 | |
| 130 | <ol> |
| 131 | <li value=15> |
| 132 | Just want to say thanks for fossil making my life easier.... |
| 133 | Also <nowiki>[for]</nowiki> not having a misanthropic command line interface. |
| 134 | |
| 135 | <blockquote> |
| 136 | <i>Joshua Paine at [http://www.mail-archive.com/[email protected]/msg02736.html]</i> |
| 137 | </blockquote> |
| 138 | |
| 139 | <li>We use it at a large university to manage code that small teams write. |
| 140 | The runs everywhere, ease of installation and portability is something that |
| 141 | seems to be a good fit with the environment we have (highly ditrobuted, |
| 142 | sometimes very restrictive firewalls, OSX/Win/Linux). We are happy with it |
| 143 | and teaching a Msc/Phd student (read complete novice) fossil has just |
| 144 | been a smoother ride than Git was. |
| 145 | |
| 146 | <blockquote> |
| 147 | <i>viablepanic at [http://www.reddit.com/r/programming/comments/bxcto/why_not_fossil_scm/]</i> |
| 148 | </blockquote> |
| 149 | |
| 150 | <li>In the fossil community - and hence in fossil itself - development history |
| 151 | is pretty much sacrosanct. The very name "fossil" was to chosen to |
| 152 | reflect the unchanging nature of things in that history. |
| 153 | |
| 154 | <p>In git (or rather, the git community), the development history is part of |
| 155 | the published aspect of the project, so it provides tools for rearranging |
| 156 | that history so you can present what you "should" have done rather |
| 157 |
+12
-12
| --- www/reviews.wiki | ||
| +++ www/reviews.wiki | ||
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | <title>Reviews</title> |
| 2 | 2 | <b>External links:</b> |
| 3 | - | |
| 3 | + | |
| 4 | 4 | * [http://nixtu.blogspot.com/2010/03/fossil-dvcs-on-go-first-impressions.html | |
| 5 | 5 | Fossil DVCS on the Go - First Impressions] |
| 6 | 6 | * [http://blog.mired.org/2011/02/fossil-sweet-spot-in-vcs-space.html | |
| 7 | 7 | Fossil - a sweet spot in the VCS space] by Mike Meyer. |
| 8 | 8 | * [http://blog.s11n.net/?p=72|Four reasons to take a closer look at the Fossil SCM] by Stephan Beal |
| @@ -22,27 +22,27 @@ | ||
| 22 | 22 | |
| 23 | 23 | |
| 24 | 24 | <b>Joshua Paine on 2010-10-22:</b> |
| 25 | 25 | |
| 26 | 26 | <blockquote> |
| 27 | -With one of my several hats on, I'm in a small team using git. Another | |
| 28 | -team member just checked some stuff into trunk that should have been on | |
| 29 | -a branch. Nothing else had happened since, so in fossil I would have | |
| 30 | -just edited that commit and put it on a new branch. In git that can't | |
| 31 | -actually be done without danger once other people have pulled, so I had | |
| 32 | -to create a new commit rolling back the changes, then branch and cherry | |
| 33 | -pick the earlier changes, then figure out how to make my new branch | |
| 34 | -shared instead of private. Just want to say thanks for fossil making my | |
| 35 | -life easier on most of my projects, and being able to move commits to | |
| 36 | -another branch after the fact and shared-by-default branches are good | |
| 27 | +With one of my several hats on, I'm in a small team using git. Another | |
| 28 | +team member just checked some stuff into trunk that should have been on | |
| 29 | +a branch. Nothing else had happened since, so in fossil I would have | |
| 30 | +just edited that commit and put it on a new branch. In git that can't | |
| 31 | +actually be done without danger once other people have pulled, so I had | |
| 32 | +to create a new commit rolling back the changes, then branch and cherry | |
| 33 | +pick the earlier changes, then figure out how to make my new branch | |
| 34 | +shared instead of private. Just want to say thanks for fossil making my | |
| 35 | +life easier on most of my projects, and being able to move commits to | |
| 36 | +another branch after the fact and shared-by-default branches are good | |
| 37 | 37 | features. Also not having a misanthropic command line interface. |
| 38 | 38 | </blockquote> |
| 39 | 39 | |
| 40 | 40 | <b>Stephan Beal writes on 2009-01-11:</b> |
| 41 | 41 | |
| 42 | 42 | <blockquote> |
| 43 | -Sometime in late 2007 I came across a link to fossil on | |
| 43 | +Sometime in late 2007 I came across a link to fossil on | |
| 44 | 44 | <a href="http://www.sqlite.org/">sqlite.org</a>. It |
| 45 | 45 | was a good thing I bookmarked it, because I was never able to find the |
| 46 | 46 | link again (it might have been in a bug report or something). The |
| 47 | 47 | reasons I first took a close look at it were (A) it stemmed from the |
| 48 | 48 | sqlite project, which I've held in high regards for years (e.g. I |
| 49 | 49 |
| --- www/reviews.wiki | |
| +++ www/reviews.wiki | |
| @@ -1,8 +1,8 @@ | |
| 1 | <title>Reviews</title> |
| 2 | <b>External links:</b> |
| 3 | |
| 4 | * [http://nixtu.blogspot.com/2010/03/fossil-dvcs-on-go-first-impressions.html | |
| 5 | Fossil DVCS on the Go - First Impressions] |
| 6 | * [http://blog.mired.org/2011/02/fossil-sweet-spot-in-vcs-space.html | |
| 7 | Fossil - a sweet spot in the VCS space] by Mike Meyer. |
| 8 | * [http://blog.s11n.net/?p=72|Four reasons to take a closer look at the Fossil SCM] by Stephan Beal |
| @@ -22,27 +22,27 @@ | |
| 22 | |
| 23 | |
| 24 | <b>Joshua Paine on 2010-10-22:</b> |
| 25 | |
| 26 | <blockquote> |
| 27 | With one of my several hats on, I'm in a small team using git. Another |
| 28 | team member just checked some stuff into trunk that should have been on |
| 29 | a branch. Nothing else had happened since, so in fossil I would have |
| 30 | just edited that commit and put it on a new branch. In git that can't |
| 31 | actually be done without danger once other people have pulled, so I had |
| 32 | to create a new commit rolling back the changes, then branch and cherry |
| 33 | pick the earlier changes, then figure out how to make my new branch |
| 34 | shared instead of private. Just want to say thanks for fossil making my |
| 35 | life easier on most of my projects, and being able to move commits to |
| 36 | another branch after the fact and shared-by-default branches are good |
| 37 | features. Also not having a misanthropic command line interface. |
| 38 | </blockquote> |
| 39 | |
| 40 | <b>Stephan Beal writes on 2009-01-11:</b> |
| 41 | |
| 42 | <blockquote> |
| 43 | Sometime in late 2007 I came across a link to fossil on |
| 44 | <a href="http://www.sqlite.org/">sqlite.org</a>. It |
| 45 | was a good thing I bookmarked it, because I was never able to find the |
| 46 | link again (it might have been in a bug report or something). The |
| 47 | reasons I first took a close look at it were (A) it stemmed from the |
| 48 | sqlite project, which I've held in high regards for years (e.g. I |
| 49 |
| --- www/reviews.wiki | |
| +++ www/reviews.wiki | |
| @@ -1,8 +1,8 @@ | |
| 1 | <title>Reviews</title> |
| 2 | <b>External links:</b> |
| 3 | |
| 4 | * [http://nixtu.blogspot.com/2010/03/fossil-dvcs-on-go-first-impressions.html | |
| 5 | Fossil DVCS on the Go - First Impressions] |
| 6 | * [http://blog.mired.org/2011/02/fossil-sweet-spot-in-vcs-space.html | |
| 7 | Fossil - a sweet spot in the VCS space] by Mike Meyer. |
| 8 | * [http://blog.s11n.net/?p=72|Four reasons to take a closer look at the Fossil SCM] by Stephan Beal |
| @@ -22,27 +22,27 @@ | |
| 22 | |
| 23 | |
| 24 | <b>Joshua Paine on 2010-10-22:</b> |
| 25 | |
| 26 | <blockquote> |
| 27 | With one of my several hats on, I'm in a small team using git. Another |
| 28 | team member just checked some stuff into trunk that should have been on |
| 29 | a branch. Nothing else had happened since, so in fossil I would have |
| 30 | just edited that commit and put it on a new branch. In git that can't |
| 31 | actually be done without danger once other people have pulled, so I had |
| 32 | to create a new commit rolling back the changes, then branch and cherry |
| 33 | pick the earlier changes, then figure out how to make my new branch |
| 34 | shared instead of private. Just want to say thanks for fossil making my |
| 35 | life easier on most of my projects, and being able to move commits to |
| 36 | another branch after the fact and shared-by-default branches are good |
| 37 | features. Also not having a misanthropic command line interface. |
| 38 | </blockquote> |
| 39 | |
| 40 | <b>Stephan Beal writes on 2009-01-11:</b> |
| 41 | |
| 42 | <blockquote> |
| 43 | Sometime in late 2007 I came across a link to fossil on |
| 44 | <a href="http://www.sqlite.org/">sqlite.org</a>. It |
| 45 | was a good thing I bookmarked it, because I was never able to find the |
| 46 | link again (it might have been in a bug report or something). The |
| 47 | reasons I first took a close look at it were (A) it stemmed from the |
| 48 | sqlite project, which I've held in high regards for years (e.g. I |
| 49 |
+3
-3
| --- www/selfcheck.wiki | ||
| +++ www/selfcheck.wiki | ||
| @@ -14,11 +14,11 @@ | ||
| 14 | 14 | lost. The integrity checks are doing their job well.</p> |
| 15 | 15 | |
| 16 | 16 | <h2>Atomic Check-ins With Rollback</h2> |
| 17 | 17 | |
| 18 | 18 | The fossil repository is stored in an |
| 19 | -<a href="http://www.sqlite.org/">SQLite</a> database file. | |
| 19 | +<a href="http://www.sqlite.org/">SQLite</a> database file. | |
| 20 | 20 | ([./tech_overview.wiki | Addition information] about the repository |
| 21 | 21 | file format.) |
| 22 | 22 | SQLite is very mature and stable and has been in wide-spread use for many |
| 23 | 23 | years, so we are confident it will not cause repository |
| 24 | 24 | corruption. SQLite |
| @@ -61,11 +61,11 @@ | ||
| 61 | 61 | message is printed and the transaction rolls back. |
| 62 | 62 | |
| 63 | 63 | So, in other words, fossil always checks to make sure it can |
| 64 | 64 | re-extract a file before it commits a change to that file. |
| 65 | 65 | Hence bugs in fossil are unlikely to corrupt the repository in |
| 66 | -a way that prevents us from extracting historical versions of | |
| 66 | +a way that prevents us from extracting historical versions of | |
| 67 | 67 | files. |
| 68 | 68 | |
| 69 | 69 | <h2>Checksum Over All Files In A Check-in</h2> |
| 70 | 70 | |
| 71 | 71 | Manifest artifacts that define a check-in have two fields (the |
| @@ -102,7 +102,7 @@ | ||
| 102 | 102 | <a href="http://en.wikipedia.org/wiki/The_Tortoise_and_the_Hare">tortoise</a>: |
| 103 | 103 | reliability is more important than raw speed. The developers of |
| 104 | 104 | fossil see no merit in getting the wrong answer quickly. |
| 105 | 105 | |
| 106 | 106 | Fossil may not be the fastest versioning system, but it is "fast enough". |
| 107 | -Fossil runs quickly enough to stay out of the developers way. | |
| 107 | +Fossil runs quickly enough to stay out of the developers way. | |
| 108 | 108 | Most operations complete in under a second. |
| 109 | 109 |
| --- www/selfcheck.wiki | |
| +++ www/selfcheck.wiki | |
| @@ -14,11 +14,11 @@ | |
| 14 | lost. The integrity checks are doing their job well.</p> |
| 15 | |
| 16 | <h2>Atomic Check-ins With Rollback</h2> |
| 17 | |
| 18 | The fossil repository is stored in an |
| 19 | <a href="http://www.sqlite.org/">SQLite</a> database file. |
| 20 | ([./tech_overview.wiki | Addition information] about the repository |
| 21 | file format.) |
| 22 | SQLite is very mature and stable and has been in wide-spread use for many |
| 23 | years, so we are confident it will not cause repository |
| 24 | corruption. SQLite |
| @@ -61,11 +61,11 @@ | |
| 61 | message is printed and the transaction rolls back. |
| 62 | |
| 63 | So, in other words, fossil always checks to make sure it can |
| 64 | re-extract a file before it commits a change to that file. |
| 65 | Hence bugs in fossil are unlikely to corrupt the repository in |
| 66 | a way that prevents us from extracting historical versions of |
| 67 | files. |
| 68 | |
| 69 | <h2>Checksum Over All Files In A Check-in</h2> |
| 70 | |
| 71 | Manifest artifacts that define a check-in have two fields (the |
| @@ -102,7 +102,7 @@ | |
| 102 | <a href="http://en.wikipedia.org/wiki/The_Tortoise_and_the_Hare">tortoise</a>: |
| 103 | reliability is more important than raw speed. The developers of |
| 104 | fossil see no merit in getting the wrong answer quickly. |
| 105 | |
| 106 | Fossil may not be the fastest versioning system, but it is "fast enough". |
| 107 | Fossil runs quickly enough to stay out of the developers way. |
| 108 | Most operations complete in under a second. |
| 109 |
| --- www/selfcheck.wiki | |
| +++ www/selfcheck.wiki | |
| @@ -14,11 +14,11 @@ | |
| 14 | lost. The integrity checks are doing their job well.</p> |
| 15 | |
| 16 | <h2>Atomic Check-ins With Rollback</h2> |
| 17 | |
| 18 | The fossil repository is stored in an |
| 19 | <a href="http://www.sqlite.org/">SQLite</a> database file. |
| 20 | ([./tech_overview.wiki | Addition information] about the repository |
| 21 | file format.) |
| 22 | SQLite is very mature and stable and has been in wide-spread use for many |
| 23 | years, so we are confident it will not cause repository |
| 24 | corruption. SQLite |
| @@ -61,11 +61,11 @@ | |
| 61 | message is printed and the transaction rolls back. |
| 62 | |
| 63 | So, in other words, fossil always checks to make sure it can |
| 64 | re-extract a file before it commits a change to that file. |
| 65 | Hence bugs in fossil are unlikely to corrupt the repository in |
| 66 | a way that prevents us from extracting historical versions of |
| 67 | files. |
| 68 | |
| 69 | <h2>Checksum Over All Files In A Check-in</h2> |
| 70 | |
| 71 | Manifest artifacts that define a check-in have two fields (the |
| @@ -102,7 +102,7 @@ | |
| 102 | <a href="http://en.wikipedia.org/wiki/The_Tortoise_and_the_Hare">tortoise</a>: |
| 103 | reliability is more important than raw speed. The developers of |
| 104 | fossil see no merit in getting the wrong answer quickly. |
| 105 | |
| 106 | Fossil may not be the fastest versioning system, but it is "fast enough". |
| 107 | Fossil runs quickly enough to stay out of the developers way. |
| 108 | Most operations complete in under a second. |
| 109 |
+6
-6
| --- www/selfhost.wiki | ||
| +++ www/selfhost.wiki | ||
| @@ -7,23 +7,23 @@ | ||
| 7 | 7 | 2. [http://www2.fossil-scm.org/] |
| 8 | 8 | 3. [http://www3.fossil-scm.org/site.cgi] |
| 9 | 9 | |
| 10 | 10 | |
| 11 | 11 | The canonical repository is (1). Repositories (2) and (3) automatically |
| 12 | -stay in synchronization with (1) via a | |
| 12 | +stay in synchronization with (1) via a | |
| 13 | 13 | <a href="http://en.wikipedia.org/wiki/Cron">cron job</a> that invokes |
| 14 | 14 | "fossil sync" at regular intervals. |
| 15 | 15 | |
| 16 | 16 | Note that the two secondary repositories are more than just read-only mirrors. |
| 17 | 17 | All three servers support full read/write capabilities. |
| 18 | -Changes (such as new tickets or wiki or check-ins) can be implemented | |
| 18 | +Changes (such as new tickets or wiki or check-ins) can be implemented | |
| 19 | 19 | on any of the three servers and those changes automatically propagate to the |
| 20 | 20 | other two servers. |
| 21 | 21 | |
| 22 | 22 | Server (1) runs as a CGI script on a |
| 23 | 23 | <a href="http://www.linode.com/">Linode 1024</a> located in Dallas, TX |
| 24 | -- on the same virtual machine that | |
| 24 | +- on the same virtual machine that | |
| 25 | 25 | hosts <a href="http://www.sqlite.org/">SQLite</a> and over a |
| 26 | 26 | dozen other smaller projects. This demonstrates that Fossil can run on |
| 27 | 27 | a low-power host processor. |
| 28 | 28 | Multiple fossil-based projects can easily be hosted on the same machine, |
| 29 | 29 | even if that machine is itself one of several dozen virtual machines on |
| @@ -34,17 +34,17 @@ | ||
| 34 | 34 | #!/usr/bin/fossil |
| 35 | 35 | repository: /fossil/fossil.fossil |
| 36 | 36 | </pre></blockquote> |
| 37 | 37 | |
| 38 | 38 | Server (3) runs as a CGI script on a shared hosting account at |
| 39 | -<a href="http://www.he.net/">Hurricane Electric</a> in Fremont, CA. | |
| 39 | +<a href="http://www.he.net/">Hurricane Electric</a> in Fremont, CA. | |
| 40 | 40 | This server demonstrates the ability of |
| 41 | 41 | Fossil to run on an economical shared-host web account with no |
| 42 | 42 | privileges beyond port 80 HTTP access and CGI. It is not necessary |
| 43 | 43 | to have a dedicated computer with administrator privileges to run Fossil. |
| 44 | -As far as we are aware, | |
| 45 | -Fossil is the only full-featured configuration management system | |
| 44 | +As far as we are aware, | |
| 45 | +Fossil is the only full-featured configuration management system | |
| 46 | 46 | that can run in |
| 47 | 47 | such a restricted environment. The CGI script that runs on the |
| 48 | 48 | Hurricane Electric server is the same as the CGI script shown above, |
| 49 | 49 | except that the pathnames are modified to suit the environment: |
| 50 | 50 | |
| 51 | 51 |
| --- www/selfhost.wiki | |
| +++ www/selfhost.wiki | |
| @@ -7,23 +7,23 @@ | |
| 7 | 2. [http://www2.fossil-scm.org/] |
| 8 | 3. [http://www3.fossil-scm.org/site.cgi] |
| 9 | |
| 10 | |
| 11 | The canonical repository is (1). Repositories (2) and (3) automatically |
| 12 | stay in synchronization with (1) via a |
| 13 | <a href="http://en.wikipedia.org/wiki/Cron">cron job</a> that invokes |
| 14 | "fossil sync" at regular intervals. |
| 15 | |
| 16 | Note that the two secondary repositories are more than just read-only mirrors. |
| 17 | All three servers support full read/write capabilities. |
| 18 | Changes (such as new tickets or wiki or check-ins) can be implemented |
| 19 | on any of the three servers and those changes automatically propagate to the |
| 20 | other two servers. |
| 21 | |
| 22 | Server (1) runs as a CGI script on a |
| 23 | <a href="http://www.linode.com/">Linode 1024</a> located in Dallas, TX |
| 24 | - on the same virtual machine that |
| 25 | hosts <a href="http://www.sqlite.org/">SQLite</a> and over a |
| 26 | dozen other smaller projects. This demonstrates that Fossil can run on |
| 27 | a low-power host processor. |
| 28 | Multiple fossil-based projects can easily be hosted on the same machine, |
| 29 | even if that machine is itself one of several dozen virtual machines on |
| @@ -34,17 +34,17 @@ | |
| 34 | #!/usr/bin/fossil |
| 35 | repository: /fossil/fossil.fossil |
| 36 | </pre></blockquote> |
| 37 | |
| 38 | Server (3) runs as a CGI script on a shared hosting account at |
| 39 | <a href="http://www.he.net/">Hurricane Electric</a> in Fremont, CA. |
| 40 | This server demonstrates the ability of |
| 41 | Fossil to run on an economical shared-host web account with no |
| 42 | privileges beyond port 80 HTTP access and CGI. It is not necessary |
| 43 | to have a dedicated computer with administrator privileges to run Fossil. |
| 44 | As far as we are aware, |
| 45 | Fossil is the only full-featured configuration management system |
| 46 | that can run in |
| 47 | such a restricted environment. The CGI script that runs on the |
| 48 | Hurricane Electric server is the same as the CGI script shown above, |
| 49 | except that the pathnames are modified to suit the environment: |
| 50 | |
| 51 |
| --- www/selfhost.wiki | |
| +++ www/selfhost.wiki | |
| @@ -7,23 +7,23 @@ | |
| 7 | 2. [http://www2.fossil-scm.org/] |
| 8 | 3. [http://www3.fossil-scm.org/site.cgi] |
| 9 | |
| 10 | |
| 11 | The canonical repository is (1). Repositories (2) and (3) automatically |
| 12 | stay in synchronization with (1) via a |
| 13 | <a href="http://en.wikipedia.org/wiki/Cron">cron job</a> that invokes |
| 14 | "fossil sync" at regular intervals. |
| 15 | |
| 16 | Note that the two secondary repositories are more than just read-only mirrors. |
| 17 | All three servers support full read/write capabilities. |
| 18 | Changes (such as new tickets or wiki or check-ins) can be implemented |
| 19 | on any of the three servers and those changes automatically propagate to the |
| 20 | other two servers. |
| 21 | |
| 22 | Server (1) runs as a CGI script on a |
| 23 | <a href="http://www.linode.com/">Linode 1024</a> located in Dallas, TX |
| 24 | - on the same virtual machine that |
| 25 | hosts <a href="http://www.sqlite.org/">SQLite</a> and over a |
| 26 | dozen other smaller projects. This demonstrates that Fossil can run on |
| 27 | a low-power host processor. |
| 28 | Multiple fossil-based projects can easily be hosted on the same machine, |
| 29 | even if that machine is itself one of several dozen virtual machines on |
| @@ -34,17 +34,17 @@ | |
| 34 | #!/usr/bin/fossil |
| 35 | repository: /fossil/fossil.fossil |
| 36 | </pre></blockquote> |
| 37 | |
| 38 | Server (3) runs as a CGI script on a shared hosting account at |
| 39 | <a href="http://www.he.net/">Hurricane Electric</a> in Fremont, CA. |
| 40 | This server demonstrates the ability of |
| 41 | Fossil to run on an economical shared-host web account with no |
| 42 | privileges beyond port 80 HTTP access and CGI. It is not necessary |
| 43 | to have a dedicated computer with administrator privileges to run Fossil. |
| 44 | As far as we are aware, |
| 45 | Fossil is the only full-featured configuration management system |
| 46 | that can run in |
| 47 | such a restricted environment. The CGI script that runs on the |
| 48 | Hurricane Electric server is the same as the CGI script shown above, |
| 49 | except that the pathnames are modified to suit the environment: |
| 50 | |
| 51 |
+20
-20
| --- www/server.wiki | ||
| +++ www/server.wiki | ||
| @@ -2,11 +2,11 @@ | ||
| 2 | 2 | <h2>Introduction</h2><blockquote> |
| 3 | 3 | <p>A server is not necessary to use Fossil, but a server does help in collaborating with |
| 4 | 4 | peers. A Fossil server also works well as a complete website for a project. |
| 5 | 5 | For example, the complete [https://www.fossil-scm.org/] website, including the |
| 6 | 6 | page you are now reading, |
| 7 | -is just a Fossil server displaying the content of the | |
| 7 | +is just a Fossil server displaying the content of the | |
| 8 | 8 | self-hosting repository for Fossil.</p> |
| 9 | 9 | <p>This article is a guide for setting up your own Fossil server. |
| 10 | 10 | <p>See "[./aboutcgi.wiki|How CGI Works In Fossil]" for background |
| 11 | 11 | information on the underlying CGI technology. |
| 12 | 12 | See "[./sync.wiki|The Fossil Sync Protocol]" for information on the |
| @@ -18,11 +18,11 @@ | ||
| 18 | 18 | <li>A stand-alone server |
| 19 | 19 | <li>Using inetd or xinetd or stunnel |
| 20 | 20 | <li>CGI |
| 21 | 21 | <li>SCGI (a.k.a. SimpleCGI) |
| 22 | 22 | </ol> |
| 23 | -Each of these can serve either a single repository, or a directory hierarchy | |
| 23 | +Each of these can serve either a single repository, or a directory hierarchy | |
| 24 | 24 | containing many repositories with names ending in ".fossil". |
| 25 | 25 | </blockquote> |
| 26 | 26 | <a name="standalone"></a> |
| 27 | 27 | <h2>Standalone server</h2><blockquote> |
| 28 | 28 | The easiest way to set up a Fossil server is to use either the |
| @@ -34,11 +34,11 @@ | ||
| 34 | 34 | <p> |
| 35 | 35 | The <i>REPOSITORY</i> argument is either the name of the repository file, or |
| 36 | 36 | a directory containing many repositories. |
| 37 | 37 | Both of these commands start a Fossil server, usually on TCP port 8080, though |
| 38 | 38 | a higher numbered port might also be used if 8080 is already occupied. You can |
| 39 | -access these using URLs of the form <b>http://localhost:8080/</b>, or if | |
| 39 | +access these using URLs of the form <b>http://localhost:8080/</b>, or if | |
| 40 | 40 | <i>REPOSITORY</i> is a directory, URLs of the form |
| 41 | 41 | <b>http://localhost:8080/</b><i>repo</i><b>/</b> where <i>repo</i> is the base |
| 42 | 42 | name of the repository file without the ".fossil" suffix. |
| 43 | 43 | The difference between "ui" and "server" is that "ui" will |
| 44 | 44 | also start a web browser and point it |
| @@ -75,23 +75,23 @@ | ||
| 75 | 75 | need to modify the pathnames for your particular setup. |
| 76 | 76 | The final argument is either the name of the fossil repository to be served, |
| 77 | 77 | or a directory containing multiple repositories. |
| 78 | 78 | </p> |
| 79 | 79 | <p> |
| 80 | -If you use a non-standard TCP port on | |
| 81 | -systems where the port-specification must be a symbolic name and cannot be | |
| 80 | +If you use a non-standard TCP port on | |
| 81 | +systems where the port-specification must be a symbolic name and cannot be | |
| 82 | 82 | numeric, add the desired name and port to /etc/services. For example, if |
| 83 | 83 | you want your Fossil server running on TCP port 12345 instead of 80, you |
| 84 | 84 | will need to add: |
| 85 | 85 | <blockquote> |
| 86 | 86 | <pre> |
| 87 | 87 | fossil 12345/tcp #fossil server |
| 88 | 88 | </pre> |
| 89 | 89 | </blockquote> |
| 90 | -and use the symbolic name ('fossil' in this example) instead of the numeral ('12345') | |
| 91 | -in inetd.conf. For details, see the relevant section in your system's documentation, e.g. | |
| 92 | -the [https://www.freebsd.org/doc/en/books/handbook/network-inetd.html|FreeBSD Handbook] in | |
| 90 | +and use the symbolic name ('fossil' in this example) instead of the numeral ('12345') | |
| 91 | +in inetd.conf. For details, see the relevant section in your system's documentation, e.g. | |
| 92 | +the [https://www.freebsd.org/doc/en/books/handbook/network-inetd.html|FreeBSD Handbook] in | |
| 93 | 93 | case you use FreeBSD. |
| 94 | 94 | </p> |
| 95 | 95 | <p> |
| 96 | 96 | If your system is running xinetd, then the configuration is likely to be |
| 97 | 97 | in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d". |
| @@ -119,11 +119,11 @@ | ||
| 119 | 119 | jail for the user who owns the fossil repository before reading any information |
| 120 | 120 | off of the wire. |
| 121 | 121 | </p> |
| 122 | 122 | <p> |
| 123 | 123 | Inetd or xinetd must be enabled, and must be (re)started whenever their configuration |
| 124 | -changes - consult your system's documentation for details. | |
| 124 | +changes - consult your system's documentation for details. | |
| 125 | 125 | </p> |
| 126 | 126 | <p> |
| 127 | 127 | [https://www.stunnel.org/ | Stunnel version 5] is an inetd-like process that |
| 128 | 128 | accepts and decodes SSL-encrypted connections. Fossil can be run directly from |
| 129 | 129 | stunnel in a manner similar to inetd and xinetd. This can be used to provide |
| @@ -137,15 +137,15 @@ | ||
| 137 | 137 | TIMEOUTclose = 0 |
| 138 | 138 | exec = /usr/bin/fossil |
| 139 | 139 | execargs = /usr/bin/fossil http /home/fossil/ubercool.fossil --https |
| 140 | 140 | </nowiki></pre></blockquote> |
| 141 | 141 | See the stunnel5 documentation for further details about the /etc/stunnel/stunnel.conf |
| 142 | -configuration file. Note that the [/help/http|fossil http] command should include | |
| 142 | +configuration file. Note that the [/help/http|fossil http] command should include | |
| 143 | 143 | the --https option to let Fossil know to use "https" instead of "http" as the scheme |
| 144 | 144 | on generated hyperlinks. |
| 145 | 145 | <p> |
| 146 | -Using inetd or xinetd or stunnel is a more complex setup | |
| 146 | +Using inetd or xinetd or stunnel is a more complex setup | |
| 147 | 147 | than the "standalone" server, but it has the |
| 148 | 148 | advantage of only using system resources when an actual connection is |
| 149 | 149 | attempted. If no-one ever connects to that port, a Fossil server will |
| 150 | 150 | not (automatically) run. It has the disadvantage of requiring "root" access |
| 151 | 151 | and therefore may not normally be available to lower-priced "shared" servers |
| @@ -155,11 +155,11 @@ | ||
| 155 | 155 | <a name="cgi"></a> |
| 156 | 156 | <h2>Fossil as CGI</h2><blockquote> |
| 157 | 157 | <p> |
| 158 | 158 | A Fossil server can also be run from an ordinary web server as a CGI program. |
| 159 | 159 | This feature allows Fossil to be seamlessly integrated into a larger website. |
| 160 | -CGI is how the [./selfhost.wiki | self-hosting fossil repositories] are | |
| 160 | +CGI is how the [./selfhost.wiki | self-hosting fossil repositories] are | |
| 161 | 161 | implemented. |
| 162 | 162 | </p> |
| 163 | 163 | <p> |
| 164 | 164 | To run Fossil as CGI, create a CGI script (here called "repo") in the CGI directory |
| 165 | 165 | of your web server and having content like this: |
| @@ -184,12 +184,12 @@ | ||
| 184 | 184 | script itself must be executable for the user under which it will run (which often differs |
| 185 | 185 | from the one running the web server - consult your site's documentation or administrator).</li> |
| 186 | 186 | <li>The repository file AND the directory containing it must be writable by the same account |
| 187 | 187 | which executes the Fossil binary (again, this might differ from the WWW user). The directory |
| 188 | 188 | needs to be writable so that sqlite can write its journal files.</li> |
| 189 | -<li>Fossil must be able to create temporary files, the default directory | |
| 190 | -for which depends on the OS. When the CGI process is operating within | |
| 189 | +<li>Fossil must be able to create temporary files, the default directory | |
| 190 | +for which depends on the OS. When the CGI process is operating within | |
| 191 | 191 | a chroot, ensure that this directory exists and is readable/writeable |
| 192 | 192 | by the user who executes the Fossil binary.</li> |
| 193 | 193 | </ul> |
| 194 | 194 | </p> |
| 195 | 195 | |
| @@ -219,11 +219,11 @@ | ||
| 219 | 219 | |
| 220 | 220 | <a name="scgi"></a> |
| 221 | 221 | <h2>Fossil as SCGI</h2><blockquote> |
| 222 | 222 | |
| 223 | 223 | <p> |
| 224 | -The [/help/server|fossil server] command, described above as a way of | |
| 224 | +The [/help/server|fossil server] command, described above as a way of | |
| 225 | 225 | starting a stand-alone web server, can also be used for SCGI. Simply add |
| 226 | 226 | the --scgi command-line option and the stand-alone server will interpret |
| 227 | 227 | and respond to the SimpleCGI or SCGI protocol rather than raw HTTP. This can |
| 228 | 228 | be used in combination with a webserver (such as [http://nginx.org|Nginx]) |
| 229 | 229 | that does not support CGI. A typical Nginx configuration to support SCGI |
| @@ -284,27 +284,27 @@ | ||
| 284 | 284 | </blockquote> |
| 285 | 285 | |
| 286 | 286 | <a name="loadmgmt"></a> |
| 287 | 287 | <h2>Managing Server Load</h2><blockquote> |
| 288 | 288 | <p> |
| 289 | -A Fossil server is very efficient and normally presents a very light | |
| 289 | +A Fossil server is very efficient and normally presents a very light | |
| 290 | 290 | load on the server. |
| 291 | 291 | The Fossil [./selfhost.wiki | self-hosting server] is a 1/24th slice VM at |
| 292 | 292 | [http://www.linode.com | Linode.com] hosting 65 other repositories in |
| 293 | 293 | addition to Fossil (and including some very high-traffic sites such |
| 294 | 294 | as [http://www.sqlite.org] and [http://system.data.sqlite.org]) and |
| 295 | 295 | it has a typical load of 0.05 to 0.1. A single HTTP request to Fossil |
| 296 | 296 | normally takes less than 10 milliseconds of CPU time to complete. So |
| 297 | -requests can be arriving at a continuous rate of 20 or more per second | |
| 297 | +requests can be arriving at a continuous rate of 20 or more per second | |
| 298 | 298 | and the CPU can still be mostly idle. |
| 299 | 299 | <p> |
| 300 | -However, there are some Fossil web pages that can consume large | |
| 300 | +However, there are some Fossil web pages that can consume large | |
| 301 | 301 | amounts of CPU time, especially on repositories with a large number |
| 302 | 302 | of files or with long revision histories. High CPU usage pages include |
| 303 | 303 | [/help?cmd=/zip | /zip], [/help?cmd=/tarball | /tarball], |
| 304 | 304 | [/help?cmd=/annotate | /annotate] and others. On very large repositories, |
| 305 | -these commands can take 15 seconds or more of CPU time. | |
| 305 | +these commands can take 15 seconds or more of CPU time. | |
| 306 | 306 | If these kinds of requests arrive too quickly, the load average on the |
| 307 | 307 | server can grow dramatically, making the server unresponsive. |
| 308 | 308 | <p> |
| 309 | 309 | Fossil provides two capabilities to help avoid server overload problems |
| 310 | 310 | due to excessive requests to expensive pages: |
| @@ -312,11 +312,11 @@ | ||
| 312 | 312 | <li><p>An optional cache is available that remembers the 10 most recently |
| 313 | 313 | requested /zip or /tarball pages and returns the precomputed answer |
| 314 | 314 | if the same page is requested again. |
| 315 | 315 | <li><p>Page requests can be configured to fail with a |
| 316 | 316 | [http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.3 | "503 Server Overload"] |
| 317 | - HTTP error if an expensive request is received while the host load | |
| 317 | + HTTP error if an expensive request is received while the host load | |
| 318 | 318 | average is too high. |
| 319 | 319 | </ol> |
| 320 | 320 | Both of these load-control mechanisms are turned off by default, but they |
| 321 | 321 | are recommended for high-traffic sites. |
| 322 | 322 | <p> |
| 323 | 323 |
| --- www/server.wiki | |
| +++ www/server.wiki | |
| @@ -2,11 +2,11 @@ | |
| 2 | <h2>Introduction</h2><blockquote> |
| 3 | <p>A server is not necessary to use Fossil, but a server does help in collaborating with |
| 4 | peers. A Fossil server also works well as a complete website for a project. |
| 5 | For example, the complete [https://www.fossil-scm.org/] website, including the |
| 6 | page you are now reading, |
| 7 | is just a Fossil server displaying the content of the |
| 8 | self-hosting repository for Fossil.</p> |
| 9 | <p>This article is a guide for setting up your own Fossil server. |
| 10 | <p>See "[./aboutcgi.wiki|How CGI Works In Fossil]" for background |
| 11 | information on the underlying CGI technology. |
| 12 | See "[./sync.wiki|The Fossil Sync Protocol]" for information on the |
| @@ -18,11 +18,11 @@ | |
| 18 | <li>A stand-alone server |
| 19 | <li>Using inetd or xinetd or stunnel |
| 20 | <li>CGI |
| 21 | <li>SCGI (a.k.a. SimpleCGI) |
| 22 | </ol> |
| 23 | Each of these can serve either a single repository, or a directory hierarchy |
| 24 | containing many repositories with names ending in ".fossil". |
| 25 | </blockquote> |
| 26 | <a name="standalone"></a> |
| 27 | <h2>Standalone server</h2><blockquote> |
| 28 | The easiest way to set up a Fossil server is to use either the |
| @@ -34,11 +34,11 @@ | |
| 34 | <p> |
| 35 | The <i>REPOSITORY</i> argument is either the name of the repository file, or |
| 36 | a directory containing many repositories. |
| 37 | Both of these commands start a Fossil server, usually on TCP port 8080, though |
| 38 | a higher numbered port might also be used if 8080 is already occupied. You can |
| 39 | access these using URLs of the form <b>http://localhost:8080/</b>, or if |
| 40 | <i>REPOSITORY</i> is a directory, URLs of the form |
| 41 | <b>http://localhost:8080/</b><i>repo</i><b>/</b> where <i>repo</i> is the base |
| 42 | name of the repository file without the ".fossil" suffix. |
| 43 | The difference between "ui" and "server" is that "ui" will |
| 44 | also start a web browser and point it |
| @@ -75,23 +75,23 @@ | |
| 75 | need to modify the pathnames for your particular setup. |
| 76 | The final argument is either the name of the fossil repository to be served, |
| 77 | or a directory containing multiple repositories. |
| 78 | </p> |
| 79 | <p> |
| 80 | If you use a non-standard TCP port on |
| 81 | systems where the port-specification must be a symbolic name and cannot be |
| 82 | numeric, add the desired name and port to /etc/services. For example, if |
| 83 | you want your Fossil server running on TCP port 12345 instead of 80, you |
| 84 | will need to add: |
| 85 | <blockquote> |
| 86 | <pre> |
| 87 | fossil 12345/tcp #fossil server |
| 88 | </pre> |
| 89 | </blockquote> |
| 90 | and use the symbolic name ('fossil' in this example) instead of the numeral ('12345') |
| 91 | in inetd.conf. For details, see the relevant section in your system's documentation, e.g. |
| 92 | the [https://www.freebsd.org/doc/en/books/handbook/network-inetd.html|FreeBSD Handbook] in |
| 93 | case you use FreeBSD. |
| 94 | </p> |
| 95 | <p> |
| 96 | If your system is running xinetd, then the configuration is likely to be |
| 97 | in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d". |
| @@ -119,11 +119,11 @@ | |
| 119 | jail for the user who owns the fossil repository before reading any information |
| 120 | off of the wire. |
| 121 | </p> |
| 122 | <p> |
| 123 | Inetd or xinetd must be enabled, and must be (re)started whenever their configuration |
| 124 | changes - consult your system's documentation for details. |
| 125 | </p> |
| 126 | <p> |
| 127 | [https://www.stunnel.org/ | Stunnel version 5] is an inetd-like process that |
| 128 | accepts and decodes SSL-encrypted connections. Fossil can be run directly from |
| 129 | stunnel in a manner similar to inetd and xinetd. This can be used to provide |
| @@ -137,15 +137,15 @@ | |
| 137 | TIMEOUTclose = 0 |
| 138 | exec = /usr/bin/fossil |
| 139 | execargs = /usr/bin/fossil http /home/fossil/ubercool.fossil --https |
| 140 | </nowiki></pre></blockquote> |
| 141 | See the stunnel5 documentation for further details about the /etc/stunnel/stunnel.conf |
| 142 | configuration file. Note that the [/help/http|fossil http] command should include |
| 143 | the --https option to let Fossil know to use "https" instead of "http" as the scheme |
| 144 | on generated hyperlinks. |
| 145 | <p> |
| 146 | Using inetd or xinetd or stunnel is a more complex setup |
| 147 | than the "standalone" server, but it has the |
| 148 | advantage of only using system resources when an actual connection is |
| 149 | attempted. If no-one ever connects to that port, a Fossil server will |
| 150 | not (automatically) run. It has the disadvantage of requiring "root" access |
| 151 | and therefore may not normally be available to lower-priced "shared" servers |
| @@ -155,11 +155,11 @@ | |
| 155 | <a name="cgi"></a> |
| 156 | <h2>Fossil as CGI</h2><blockquote> |
| 157 | <p> |
| 158 | A Fossil server can also be run from an ordinary web server as a CGI program. |
| 159 | This feature allows Fossil to be seamlessly integrated into a larger website. |
| 160 | CGI is how the [./selfhost.wiki | self-hosting fossil repositories] are |
| 161 | implemented. |
| 162 | </p> |
| 163 | <p> |
| 164 | To run Fossil as CGI, create a CGI script (here called "repo") in the CGI directory |
| 165 | of your web server and having content like this: |
| @@ -184,12 +184,12 @@ | |
| 184 | script itself must be executable for the user under which it will run (which often differs |
| 185 | from the one running the web server - consult your site's documentation or administrator).</li> |
| 186 | <li>The repository file AND the directory containing it must be writable by the same account |
| 187 | which executes the Fossil binary (again, this might differ from the WWW user). The directory |
| 188 | needs to be writable so that sqlite can write its journal files.</li> |
| 189 | <li>Fossil must be able to create temporary files, the default directory |
| 190 | for which depends on the OS. When the CGI process is operating within |
| 191 | a chroot, ensure that this directory exists and is readable/writeable |
| 192 | by the user who executes the Fossil binary.</li> |
| 193 | </ul> |
| 194 | </p> |
| 195 | |
| @@ -219,11 +219,11 @@ | |
| 219 | |
| 220 | <a name="scgi"></a> |
| 221 | <h2>Fossil as SCGI</h2><blockquote> |
| 222 | |
| 223 | <p> |
| 224 | The [/help/server|fossil server] command, described above as a way of |
| 225 | starting a stand-alone web server, can also be used for SCGI. Simply add |
| 226 | the --scgi command-line option and the stand-alone server will interpret |
| 227 | and respond to the SimpleCGI or SCGI protocol rather than raw HTTP. This can |
| 228 | be used in combination with a webserver (such as [http://nginx.org|Nginx]) |
| 229 | that does not support CGI. A typical Nginx configuration to support SCGI |
| @@ -284,27 +284,27 @@ | |
| 284 | </blockquote> |
| 285 | |
| 286 | <a name="loadmgmt"></a> |
| 287 | <h2>Managing Server Load</h2><blockquote> |
| 288 | <p> |
| 289 | A Fossil server is very efficient and normally presents a very light |
| 290 | load on the server. |
| 291 | The Fossil [./selfhost.wiki | self-hosting server] is a 1/24th slice VM at |
| 292 | [http://www.linode.com | Linode.com] hosting 65 other repositories in |
| 293 | addition to Fossil (and including some very high-traffic sites such |
| 294 | as [http://www.sqlite.org] and [http://system.data.sqlite.org]) and |
| 295 | it has a typical load of 0.05 to 0.1. A single HTTP request to Fossil |
| 296 | normally takes less than 10 milliseconds of CPU time to complete. So |
| 297 | requests can be arriving at a continuous rate of 20 or more per second |
| 298 | and the CPU can still be mostly idle. |
| 299 | <p> |
| 300 | However, there are some Fossil web pages that can consume large |
| 301 | amounts of CPU time, especially on repositories with a large number |
| 302 | of files or with long revision histories. High CPU usage pages include |
| 303 | [/help?cmd=/zip | /zip], [/help?cmd=/tarball | /tarball], |
| 304 | [/help?cmd=/annotate | /annotate] and others. On very large repositories, |
| 305 | these commands can take 15 seconds or more of CPU time. |
| 306 | If these kinds of requests arrive too quickly, the load average on the |
| 307 | server can grow dramatically, making the server unresponsive. |
| 308 | <p> |
| 309 | Fossil provides two capabilities to help avoid server overload problems |
| 310 | due to excessive requests to expensive pages: |
| @@ -312,11 +312,11 @@ | |
| 312 | <li><p>An optional cache is available that remembers the 10 most recently |
| 313 | requested /zip or /tarball pages and returns the precomputed answer |
| 314 | if the same page is requested again. |
| 315 | <li><p>Page requests can be configured to fail with a |
| 316 | [http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.3 | "503 Server Overload"] |
| 317 | HTTP error if an expensive request is received while the host load |
| 318 | average is too high. |
| 319 | </ol> |
| 320 | Both of these load-control mechanisms are turned off by default, but they |
| 321 | are recommended for high-traffic sites. |
| 322 | <p> |
| 323 |
| --- www/server.wiki | |
| +++ www/server.wiki | |
| @@ -2,11 +2,11 @@ | |
| 2 | <h2>Introduction</h2><blockquote> |
| 3 | <p>A server is not necessary to use Fossil, but a server does help in collaborating with |
| 4 | peers. A Fossil server also works well as a complete website for a project. |
| 5 | For example, the complete [https://www.fossil-scm.org/] website, including the |
| 6 | page you are now reading, |
| 7 | is just a Fossil server displaying the content of the |
| 8 | self-hosting repository for Fossil.</p> |
| 9 | <p>This article is a guide for setting up your own Fossil server. |
| 10 | <p>See "[./aboutcgi.wiki|How CGI Works In Fossil]" for background |
| 11 | information on the underlying CGI technology. |
| 12 | See "[./sync.wiki|The Fossil Sync Protocol]" for information on the |
| @@ -18,11 +18,11 @@ | |
| 18 | <li>A stand-alone server |
| 19 | <li>Using inetd or xinetd or stunnel |
| 20 | <li>CGI |
| 21 | <li>SCGI (a.k.a. SimpleCGI) |
| 22 | </ol> |
| 23 | Each of these can serve either a single repository, or a directory hierarchy |
| 24 | containing many repositories with names ending in ".fossil". |
| 25 | </blockquote> |
| 26 | <a name="standalone"></a> |
| 27 | <h2>Standalone server</h2><blockquote> |
| 28 | The easiest way to set up a Fossil server is to use either the |
| @@ -34,11 +34,11 @@ | |
| 34 | <p> |
| 35 | The <i>REPOSITORY</i> argument is either the name of the repository file, or |
| 36 | a directory containing many repositories. |
| 37 | Both of these commands start a Fossil server, usually on TCP port 8080, though |
| 38 | a higher numbered port might also be used if 8080 is already occupied. You can |
| 39 | access these using URLs of the form <b>http://localhost:8080/</b>, or if |
| 40 | <i>REPOSITORY</i> is a directory, URLs of the form |
| 41 | <b>http://localhost:8080/</b><i>repo</i><b>/</b> where <i>repo</i> is the base |
| 42 | name of the repository file without the ".fossil" suffix. |
| 43 | The difference between "ui" and "server" is that "ui" will |
| 44 | also start a web browser and point it |
| @@ -75,23 +75,23 @@ | |
| 75 | need to modify the pathnames for your particular setup. |
| 76 | The final argument is either the name of the fossil repository to be served, |
| 77 | or a directory containing multiple repositories. |
| 78 | </p> |
| 79 | <p> |
| 80 | If you use a non-standard TCP port on |
| 81 | systems where the port-specification must be a symbolic name and cannot be |
| 82 | numeric, add the desired name and port to /etc/services. For example, if |
| 83 | you want your Fossil server running on TCP port 12345 instead of 80, you |
| 84 | will need to add: |
| 85 | <blockquote> |
| 86 | <pre> |
| 87 | fossil 12345/tcp #fossil server |
| 88 | </pre> |
| 89 | </blockquote> |
| 90 | and use the symbolic name ('fossil' in this example) instead of the numeral ('12345') |
| 91 | in inetd.conf. For details, see the relevant section in your system's documentation, e.g. |
| 92 | the [https://www.freebsd.org/doc/en/books/handbook/network-inetd.html|FreeBSD Handbook] in |
| 93 | case you use FreeBSD. |
| 94 | </p> |
| 95 | <p> |
| 96 | If your system is running xinetd, then the configuration is likely to be |
| 97 | in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d". |
| @@ -119,11 +119,11 @@ | |
| 119 | jail for the user who owns the fossil repository before reading any information |
| 120 | off of the wire. |
| 121 | </p> |
| 122 | <p> |
| 123 | Inetd or xinetd must be enabled, and must be (re)started whenever their configuration |
| 124 | changes - consult your system's documentation for details. |
| 125 | </p> |
| 126 | <p> |
| 127 | [https://www.stunnel.org/ | Stunnel version 5] is an inetd-like process that |
| 128 | accepts and decodes SSL-encrypted connections. Fossil can be run directly from |
| 129 | stunnel in a manner similar to inetd and xinetd. This can be used to provide |
| @@ -137,15 +137,15 @@ | |
| 137 | TIMEOUTclose = 0 |
| 138 | exec = /usr/bin/fossil |
| 139 | execargs = /usr/bin/fossil http /home/fossil/ubercool.fossil --https |
| 140 | </nowiki></pre></blockquote> |
| 141 | See the stunnel5 documentation for further details about the /etc/stunnel/stunnel.conf |
| 142 | configuration file. Note that the [/help/http|fossil http] command should include |
| 143 | the --https option to let Fossil know to use "https" instead of "http" as the scheme |
| 144 | on generated hyperlinks. |
| 145 | <p> |
| 146 | Using inetd or xinetd or stunnel is a more complex setup |
| 147 | than the "standalone" server, but it has the |
| 148 | advantage of only using system resources when an actual connection is |
| 149 | attempted. If no-one ever connects to that port, a Fossil server will |
| 150 | not (automatically) run. It has the disadvantage of requiring "root" access |
| 151 | and therefore may not normally be available to lower-priced "shared" servers |
| @@ -155,11 +155,11 @@ | |
| 155 | <a name="cgi"></a> |
| 156 | <h2>Fossil as CGI</h2><blockquote> |
| 157 | <p> |
| 158 | A Fossil server can also be run from an ordinary web server as a CGI program. |
| 159 | This feature allows Fossil to be seamlessly integrated into a larger website. |
| 160 | CGI is how the [./selfhost.wiki | self-hosting fossil repositories] are |
| 161 | implemented. |
| 162 | </p> |
| 163 | <p> |
| 164 | To run Fossil as CGI, create a CGI script (here called "repo") in the CGI directory |
| 165 | of your web server and having content like this: |
| @@ -184,12 +184,12 @@ | |
| 184 | script itself must be executable for the user under which it will run (which often differs |
| 185 | from the one running the web server - consult your site's documentation or administrator).</li> |
| 186 | <li>The repository file AND the directory containing it must be writable by the same account |
| 187 | which executes the Fossil binary (again, this might differ from the WWW user). The directory |
| 188 | needs to be writable so that sqlite can write its journal files.</li> |
| 189 | <li>Fossil must be able to create temporary files, the default directory |
| 190 | for which depends on the OS. When the CGI process is operating within |
| 191 | a chroot, ensure that this directory exists and is readable/writeable |
| 192 | by the user who executes the Fossil binary.</li> |
| 193 | </ul> |
| 194 | </p> |
| 195 | |
| @@ -219,11 +219,11 @@ | |
| 219 | |
| 220 | <a name="scgi"></a> |
| 221 | <h2>Fossil as SCGI</h2><blockquote> |
| 222 | |
| 223 | <p> |
| 224 | The [/help/server|fossil server] command, described above as a way of |
| 225 | starting a stand-alone web server, can also be used for SCGI. Simply add |
| 226 | the --scgi command-line option and the stand-alone server will interpret |
| 227 | and respond to the SimpleCGI or SCGI protocol rather than raw HTTP. This can |
| 228 | be used in combination with a webserver (such as [http://nginx.org|Nginx]) |
| 229 | that does not support CGI. A typical Nginx configuration to support SCGI |
| @@ -284,27 +284,27 @@ | |
| 284 | </blockquote> |
| 285 | |
| 286 | <a name="loadmgmt"></a> |
| 287 | <h2>Managing Server Load</h2><blockquote> |
| 288 | <p> |
| 289 | A Fossil server is very efficient and normally presents a very light |
| 290 | load on the server. |
| 291 | The Fossil [./selfhost.wiki | self-hosting server] is a 1/24th slice VM at |
| 292 | [http://www.linode.com | Linode.com] hosting 65 other repositories in |
| 293 | addition to Fossil (and including some very high-traffic sites such |
| 294 | as [http://www.sqlite.org] and [http://system.data.sqlite.org]) and |
| 295 | it has a typical load of 0.05 to 0.1. A single HTTP request to Fossil |
| 296 | normally takes less than 10 milliseconds of CPU time to complete. So |
| 297 | requests can be arriving at a continuous rate of 20 or more per second |
| 298 | and the CPU can still be mostly idle. |
| 299 | <p> |
| 300 | However, there are some Fossil web pages that can consume large |
| 301 | amounts of CPU time, especially on repositories with a large number |
| 302 | of files or with long revision histories. High CPU usage pages include |
| 303 | [/help?cmd=/zip | /zip], [/help?cmd=/tarball | /tarball], |
| 304 | [/help?cmd=/annotate | /annotate] and others. On very large repositories, |
| 305 | these commands can take 15 seconds or more of CPU time. |
| 306 | If these kinds of requests arrive too quickly, the load average on the |
| 307 | server can grow dramatically, making the server unresponsive. |
| 308 | <p> |
| 309 | Fossil provides two capabilities to help avoid server overload problems |
| 310 | due to excessive requests to expensive pages: |
| @@ -312,11 +312,11 @@ | |
| 312 | <li><p>An optional cache is available that remembers the 10 most recently |
| 313 | requested /zip or /tarball pages and returns the precomputed answer |
| 314 | if the same page is requested again. |
| 315 | <li><p>Page requests can be configured to fail with a |
| 316 | [http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.3 | "503 Server Overload"] |
| 317 | HTTP error if an expensive request is received while the host load |
| 318 | average is too high. |
| 319 | </ol> |
| 320 | Both of these load-control mechanisms are turned off by default, but they |
| 321 | are recommended for high-traffic sites. |
| 322 | <p> |
| 323 |
+3
-3
| --- www/settings.wiki | ||
| +++ www/settings.wiki | ||
| @@ -4,11 +4,11 @@ | ||
| 4 | 4 | |
| 5 | 5 | Settings control the behaviour of fossil. They are set with the |
| 6 | 6 | <tt>fossil settings</tt> command, or through the web interface in |
| 7 | 7 | the Settings page in the Admin section. |
| 8 | 8 | |
| 9 | -For a list of all settings, view the Settings page, or type | |
| 9 | +For a list of all settings, view the Settings page, or type | |
| 10 | 10 | <tt>fossil help settings</tt> from the command line. |
| 11 | 11 | |
| 12 | 12 | |
| 13 | 13 | <h3>Repository settings</h3> |
| 14 | 14 | |
| @@ -16,17 +16,17 @@ | ||
| 16 | 16 | a subset of settings are copied to your local repository. |
| 17 | 17 | |
| 18 | 18 | If you make a change to a setting on your local repository, it is not |
| 19 | 19 | synced back to the server when you <tt>push</tt> or <tt>sync</tt>. If |
| 20 | 20 | you make a change on the server, you need to manually make the change on |
| 21 | -all repositories which are cloned from this repository. | |
| 21 | +all repositories which are cloned from this repository. | |
| 22 | 22 | |
| 23 | 23 | You can also set a setting globally on your local machine. The value |
| 24 | 24 | will be used for all repositories cloned to your machine, unless |
| 25 | 25 | overridden explicitly in a particular repository. Global settings can be |
| 26 | 26 | set by using the <tt>-global</tt> option on the <tt>fossil settings</tt> |
| 27 | -command. | |
| 27 | +command. | |
| 28 | 28 | |
| 29 | 29 | <h3>"Versionable" settings</h3> |
| 30 | 30 | |
| 31 | 31 | Most of the settings control the behaviour of fossil on your local |
| 32 | 32 | machine, largely acting to reflect your preference on how you want to |
| 33 | 33 |
| --- www/settings.wiki | |
| +++ www/settings.wiki | |
| @@ -4,11 +4,11 @@ | |
| 4 | |
| 5 | Settings control the behaviour of fossil. They are set with the |
| 6 | <tt>fossil settings</tt> command, or through the web interface in |
| 7 | the Settings page in the Admin section. |
| 8 | |
| 9 | For a list of all settings, view the Settings page, or type |
| 10 | <tt>fossil help settings</tt> from the command line. |
| 11 | |
| 12 | |
| 13 | <h3>Repository settings</h3> |
| 14 | |
| @@ -16,17 +16,17 @@ | |
| 16 | a subset of settings are copied to your local repository. |
| 17 | |
| 18 | If you make a change to a setting on your local repository, it is not |
| 19 | synced back to the server when you <tt>push</tt> or <tt>sync</tt>. If |
| 20 | you make a change on the server, you need to manually make the change on |
| 21 | all repositories which are cloned from this repository. |
| 22 | |
| 23 | You can also set a setting globally on your local machine. The value |
| 24 | will be used for all repositories cloned to your machine, unless |
| 25 | overridden explicitly in a particular repository. Global settings can be |
| 26 | set by using the <tt>-global</tt> option on the <tt>fossil settings</tt> |
| 27 | command. |
| 28 | |
| 29 | <h3>"Versionable" settings</h3> |
| 30 | |
| 31 | Most of the settings control the behaviour of fossil on your local |
| 32 | machine, largely acting to reflect your preference on how you want to |
| 33 |
| --- www/settings.wiki | |
| +++ www/settings.wiki | |
| @@ -4,11 +4,11 @@ | |
| 4 | |
| 5 | Settings control the behaviour of fossil. They are set with the |
| 6 | <tt>fossil settings</tt> command, or through the web interface in |
| 7 | the Settings page in the Admin section. |
| 8 | |
| 9 | For a list of all settings, view the Settings page, or type |
| 10 | <tt>fossil help settings</tt> from the command line. |
| 11 | |
| 12 | |
| 13 | <h3>Repository settings</h3> |
| 14 | |
| @@ -16,17 +16,17 @@ | |
| 16 | a subset of settings are copied to your local repository. |
| 17 | |
| 18 | If you make a change to a setting on your local repository, it is not |
| 19 | synced back to the server when you <tt>push</tt> or <tt>sync</tt>. If |
| 20 | you make a change on the server, you need to manually make the change on |
| 21 | all repositories which are cloned from this repository. |
| 22 | |
| 23 | You can also set a setting globally on your local machine. The value |
| 24 | will be used for all repositories cloned to your machine, unless |
| 25 | overridden explicitly in a particular repository. Global settings can be |
| 26 | set by using the <tt>-global</tt> option on the <tt>fossil settings</tt> |
| 27 | command. |
| 28 | |
| 29 | <h3>"Versionable" settings</h3> |
| 30 | |
| 31 | Most of the settings control the behaviour of fossil on your local |
| 32 | machine, largely acting to reflect your preference on how you want to |
| 33 |
+10
-10
| --- www/shunning.wiki | ||
| +++ www/shunning.wiki | ||
| @@ -2,11 +2,11 @@ | ||
| 2 | 2 | <h1 align="center">Deleting Content From Fossil</h1> |
| 3 | 3 | |
| 4 | 4 | Fossil is designed to keep all historical content forever. Users |
| 5 | 5 | of Fossil are discouraged from "deleting" content simply because it |
| 6 | 6 | has become obsolete. Old content is part of the historical record |
| 7 | -(part of the "fossil record") and should be maintained indefinitely. | |
| 7 | +(part of the "fossil record") and should be maintained indefinitely. | |
| 8 | 8 | Such is the design intent of Fossil. |
| 9 | 9 | |
| 10 | 10 | Nevertheless, there may occasionally arise legitimate reasons for |
| 11 | 11 | deleting content. Such reasons might include: |
| 12 | 12 | |
| @@ -21,35 +21,35 @@ | ||
| 21 | 21 | disrupting the operation of Fossil. |
| 22 | 22 | |
| 23 | 23 | <h2>Shunning</h2> |
| 24 | 24 | |
| 25 | 25 | Fossil provides a mechanism called "shunning" for removing content from |
| 26 | -a repository. | |
| 26 | +a repository. | |
| 27 | 27 | |
| 28 | 28 | Every Fossil repository maintains a list of the SHA1 hash names of |
| 29 | 29 | "shunned" artifacts. |
| 30 | -Fossil will refuse to push or pull any shunned artifact. | |
| 30 | +Fossil will refuse to push or pull any shunned artifact. | |
| 31 | 31 | Furthermore, all shunned artifacts (but not the shunning list |
| 32 | 32 | itself) are removed from the |
| 33 | 33 | repository whenever the repository is reconstructed using the |
| 34 | 34 | "rebuild" command. |
| 35 | 35 | |
| 36 | 36 | <h3>Shunning lists are local state</h3> |
| 37 | 37 | |
| 38 | 38 | The shunning list is part of the local state of a Fossil repository. |
| 39 | -In other words, shunning does not propagate to a remote repository | |
| 39 | +In other words, shunning does not propagate to a remote repository | |
| 40 | 40 | using the normal "sync" mechanism. An artifact can be |
| 41 | 41 | shunned from one repository but be allowed to exist in another. The fact that |
| 42 | 42 | the shunning list does not propagate is a security feature. If the |
| 43 | 43 | shunning list propagated then a malicious user (or |
| 44 | 44 | a bug in the fossil code) might introduce a shun record that would |
| 45 | -propagate through all repositories in a network and permanently | |
| 45 | +propagate through all repositories in a network and permanently | |
| 46 | 46 | destroy vital information. By refusing to propagate the shunning list, |
| 47 | -Fossil ensures that no remote user will ever be able to remove | |
| 47 | +Fossil ensures that no remote user will ever be able to remove | |
| 48 | 48 | information from your personal repositories without your permission. |
| 49 | 49 | |
| 50 | -The shunning list does not propagate to a remote repository | |
| 50 | +The shunning list does not propagate to a remote repository | |
| 51 | 51 | by the normal "sync" mechanism, |
| 52 | 52 | but it is still possible to copy shuns from one repository to another |
| 53 | 53 | using the "configuration" command: |
| 54 | 54 | |
| 55 | 55 | <b>fossil configuration pull shun</b> <i>remote-url</i><br> |
| @@ -56,12 +56,12 @@ | ||
| 56 | 56 | <b>fossil configuration push shun</b> <i>remote-url</i> |
| 57 | 57 | |
| 58 | 58 | The two command above will pull or push shunning lists from or to |
| 59 | 59 | the <i>remote-url</i> indicated and merge the lists on the receiving |
| 60 | 60 | end. "Admin" privilege on the remote server is required in order to |
| 61 | -push a shun list. In contrast, the shunning list will be automatically | |
| 62 | -received by default as part of a normal client "pull" operation unless | |
| 61 | +push a shun list. In contrast, the shunning list will be automatically | |
| 62 | +received by default as part of a normal client "pull" operation unless | |
| 63 | 63 | disabled by the "<tt>auto-shun</tt>" setting. |
| 64 | 64 | |
| 65 | 65 | Note that the shunning list remains in the repository even after the |
| 66 | 66 | shunned artifact has been removed. This is to prevent the artifact |
| 67 | 67 | from being reintroduced into the repository the next time it syncs with |
| @@ -68,11 +68,11 @@ | ||
| 68 | 68 | another repository that has not shunned the artifact. |
| 69 | 69 | |
| 70 | 70 | <h3>Managing the shunning list</h3> |
| 71 | 71 | |
| 72 | 72 | The complete shunning list for a repository can be viewed by a user |
| 73 | -with "admin" privilege on the "/shun" URL of the web interface to Fossil. | |
| 73 | +with "admin" privilege on the "/shun" URL of the web interface to Fossil. | |
| 74 | 74 | That URL is accessible under the "Admin" button on the default menu |
| 75 | 75 | bar. Items can be added to or removed from the shunning list. "Sync" |
| 76 | 76 | operations are inhibited as soon as the artifact is added to the |
| 77 | 77 | shunning list, but the content of the artifact is not actually removed |
| 78 | 78 | from the repository until the next time the repository is rebuilt. |
| 79 | 79 |
| --- www/shunning.wiki | |
| +++ www/shunning.wiki | |
| @@ -2,11 +2,11 @@ | |
| 2 | <h1 align="center">Deleting Content From Fossil</h1> |
| 3 | |
| 4 | Fossil is designed to keep all historical content forever. Users |
| 5 | of Fossil are discouraged from "deleting" content simply because it |
| 6 | has become obsolete. Old content is part of the historical record |
| 7 | (part of the "fossil record") and should be maintained indefinitely. |
| 8 | Such is the design intent of Fossil. |
| 9 | |
| 10 | Nevertheless, there may occasionally arise legitimate reasons for |
| 11 | deleting content. Such reasons might include: |
| 12 | |
| @@ -21,35 +21,35 @@ | |
| 21 | disrupting the operation of Fossil. |
| 22 | |
| 23 | <h2>Shunning</h2> |
| 24 | |
| 25 | Fossil provides a mechanism called "shunning" for removing content from |
| 26 | a repository. |
| 27 | |
| 28 | Every Fossil repository maintains a list of the SHA1 hash names of |
| 29 | "shunned" artifacts. |
| 30 | Fossil will refuse to push or pull any shunned artifact. |
| 31 | Furthermore, all shunned artifacts (but not the shunning list |
| 32 | itself) are removed from the |
| 33 | repository whenever the repository is reconstructed using the |
| 34 | "rebuild" command. |
| 35 | |
| 36 | <h3>Shunning lists are local state</h3> |
| 37 | |
| 38 | The shunning list is part of the local state of a Fossil repository. |
| 39 | In other words, shunning does not propagate to a remote repository |
| 40 | using the normal "sync" mechanism. An artifact can be |
| 41 | shunned from one repository but be allowed to exist in another. The fact that |
| 42 | the shunning list does not propagate is a security feature. If the |
| 43 | shunning list propagated then a malicious user (or |
| 44 | a bug in the fossil code) might introduce a shun record that would |
| 45 | propagate through all repositories in a network and permanently |
| 46 | destroy vital information. By refusing to propagate the shunning list, |
| 47 | Fossil ensures that no remote user will ever be able to remove |
| 48 | information from your personal repositories without your permission. |
| 49 | |
| 50 | The shunning list does not propagate to a remote repository |
| 51 | by the normal "sync" mechanism, |
| 52 | but it is still possible to copy shuns from one repository to another |
| 53 | using the "configuration" command: |
| 54 | |
| 55 | <b>fossil configuration pull shun</b> <i>remote-url</i><br> |
| @@ -56,12 +56,12 @@ | |
| 56 | <b>fossil configuration push shun</b> <i>remote-url</i> |
| 57 | |
| 58 | The two command above will pull or push shunning lists from or to |
| 59 | the <i>remote-url</i> indicated and merge the lists on the receiving |
| 60 | end. "Admin" privilege on the remote server is required in order to |
| 61 | push a shun list. In contrast, the shunning list will be automatically |
| 62 | received by default as part of a normal client "pull" operation unless |
| 63 | disabled by the "<tt>auto-shun</tt>" setting. |
| 64 | |
| 65 | Note that the shunning list remains in the repository even after the |
| 66 | shunned artifact has been removed. This is to prevent the artifact |
| 67 | from being reintroduced into the repository the next time it syncs with |
| @@ -68,11 +68,11 @@ | |
| 68 | another repository that has not shunned the artifact. |
| 69 | |
| 70 | <h3>Managing the shunning list</h3> |
| 71 | |
| 72 | The complete shunning list for a repository can be viewed by a user |
| 73 | with "admin" privilege on the "/shun" URL of the web interface to Fossil. |
| 74 | That URL is accessible under the "Admin" button on the default menu |
| 75 | bar. Items can be added to or removed from the shunning list. "Sync" |
| 76 | operations are inhibited as soon as the artifact is added to the |
| 77 | shunning list, but the content of the artifact is not actually removed |
| 78 | from the repository until the next time the repository is rebuilt. |
| 79 |
| --- www/shunning.wiki | |
| +++ www/shunning.wiki | |
| @@ -2,11 +2,11 @@ | |
| 2 | <h1 align="center">Deleting Content From Fossil</h1> |
| 3 | |
| 4 | Fossil is designed to keep all historical content forever. Users |
| 5 | of Fossil are discouraged from "deleting" content simply because it |
| 6 | has become obsolete. Old content is part of the historical record |
| 7 | (part of the "fossil record") and should be maintained indefinitely. |
| 8 | Such is the design intent of Fossil. |
| 9 | |
| 10 | Nevertheless, there may occasionally arise legitimate reasons for |
| 11 | deleting content. Such reasons might include: |
| 12 | |
| @@ -21,35 +21,35 @@ | |
| 21 | disrupting the operation of Fossil. |
| 22 | |
| 23 | <h2>Shunning</h2> |
| 24 | |
| 25 | Fossil provides a mechanism called "shunning" for removing content from |
| 26 | a repository. |
| 27 | |
| 28 | Every Fossil repository maintains a list of the SHA1 hash names of |
| 29 | "shunned" artifacts. |
| 30 | Fossil will refuse to push or pull any shunned artifact. |
| 31 | Furthermore, all shunned artifacts (but not the shunning list |
| 32 | itself) are removed from the |
| 33 | repository whenever the repository is reconstructed using the |
| 34 | "rebuild" command. |
| 35 | |
| 36 | <h3>Shunning lists are local state</h3> |
| 37 | |
| 38 | The shunning list is part of the local state of a Fossil repository. |
| 39 | In other words, shunning does not propagate to a remote repository |
| 40 | using the normal "sync" mechanism. An artifact can be |
| 41 | shunned from one repository but be allowed to exist in another. The fact that |
| 42 | the shunning list does not propagate is a security feature. If the |
| 43 | shunning list propagated then a malicious user (or |
| 44 | a bug in the fossil code) might introduce a shun record that would |
| 45 | propagate through all repositories in a network and permanently |
| 46 | destroy vital information. By refusing to propagate the shunning list, |
| 47 | Fossil ensures that no remote user will ever be able to remove |
| 48 | information from your personal repositories without your permission. |
| 49 | |
| 50 | The shunning list does not propagate to a remote repository |
| 51 | by the normal "sync" mechanism, |
| 52 | but it is still possible to copy shuns from one repository to another |
| 53 | using the "configuration" command: |
| 54 | |
| 55 | <b>fossil configuration pull shun</b> <i>remote-url</i><br> |
| @@ -56,12 +56,12 @@ | |
| 56 | <b>fossil configuration push shun</b> <i>remote-url</i> |
| 57 | |
| 58 | The two command above will pull or push shunning lists from or to |
| 59 | the <i>remote-url</i> indicated and merge the lists on the receiving |
| 60 | end. "Admin" privilege on the remote server is required in order to |
| 61 | push a shun list. In contrast, the shunning list will be automatically |
| 62 | received by default as part of a normal client "pull" operation unless |
| 63 | disabled by the "<tt>auto-shun</tt>" setting. |
| 64 | |
| 65 | Note that the shunning list remains in the repository even after the |
| 66 | shunned artifact has been removed. This is to prevent the artifact |
| 67 | from being reintroduced into the repository the next time it syncs with |
| @@ -68,11 +68,11 @@ | |
| 68 | another repository that has not shunned the artifact. |
| 69 | |
| 70 | <h3>Managing the shunning list</h3> |
| 71 | |
| 72 | The complete shunning list for a repository can be viewed by a user |
| 73 | with "admin" privilege on the "/shun" URL of the web interface to Fossil. |
| 74 | That URL is accessible under the "Admin" button on the default menu |
| 75 | bar. Items can be added to or removed from the shunning list. "Sync" |
| 76 | operations are inhibited as soon as the artifact is added to the |
| 77 | shunning list, but the content of the artifact is not actually removed |
| 78 | from the repository until the next time the repository is rebuilt. |
| 79 |
+3
-3
| --- www/stats.wiki | ||
| +++ www/stats.wiki | ||
| @@ -1,9 +1,9 @@ | ||
| 1 | 1 | <title>Fossil Performance</title> |
| 2 | 2 | <h1 align="center">Performance Statistics</h1> |
| 3 | 3 | |
| 4 | -The questions will inevitably arise: How does Fossil perform? | |
| 4 | +The questions will inevitably arise: How does Fossil perform? | |
| 5 | 5 | Does it use a lot of disk space or bandwidth? Is it scalable? |
| 6 | 6 | |
| 7 | 7 | In an attempt to answers these questions, this report looks at several |
| 8 | 8 | projects that use fossil for configuration management and examines how |
| 9 | 9 | well they are working. The following table is a summary of the results. |
| @@ -96,21 +96,21 @@ | ||
| 96 | 96 | every ticket, and every check-in is a separate "artifact". One way to |
| 97 | 97 | think of a Fossil project is as a bag of artifacts. Of course, there is |
| 98 | 98 | a lot more than this going on in Fossil. Many of the artifacts have meaning |
| 99 | 99 | and are related to other artifacts. But at a low level (for example when |
| 100 | 100 | synchronizing two instances of the same project) the only thing that matters |
| 101 | -is the unordered collection of artifacts. In fact, one of the key | |
| 101 | +is the unordered collection of artifacts. In fact, one of the key | |
| 102 | 102 | characteristics of Fossil is that the entire project history can be |
| 103 | 103 | reconstructed simply by scanning the artifacts in an arbitrary order. |
| 104 | 104 | |
| 105 | 105 | The number of check-ins is the number of times that the "commit" command |
| 106 | 106 | has been run. A single check-in might change a 3 or 4 files, or it might |
| 107 | 107 | change dozens or hundreds of files. Regardless of the number of files |
| 108 | 108 | changed, it still only counts as one check-in. |
| 109 | 109 | |
| 110 | 110 | The "Uncompressed Size" is the total size of all the artifacts within |
| 111 | -the repository assuming they were all uncompressed and stored | |
| 111 | +the repository assuming they were all uncompressed and stored | |
| 112 | 112 | separately on the disk. Fossil makes use of delta compression between related |
| 113 | 113 | versions of the same file, and then uses zlib compression on the resulting |
| 114 | 114 | deltas. The total resulting repository size is shown after the uncompressed |
| 115 | 115 | size. |
| 116 | 116 | |
| 117 | 117 |
| --- www/stats.wiki | |
| +++ www/stats.wiki | |
| @@ -1,9 +1,9 @@ | |
| 1 | <title>Fossil Performance</title> |
| 2 | <h1 align="center">Performance Statistics</h1> |
| 3 | |
| 4 | The questions will inevitably arise: How does Fossil perform? |
| 5 | Does it use a lot of disk space or bandwidth? Is it scalable? |
| 6 | |
| 7 | In an attempt to answers these questions, this report looks at several |
| 8 | projects that use fossil for configuration management and examines how |
| 9 | well they are working. The following table is a summary of the results. |
| @@ -96,21 +96,21 @@ | |
| 96 | every ticket, and every check-in is a separate "artifact". One way to |
| 97 | think of a Fossil project is as a bag of artifacts. Of course, there is |
| 98 | a lot more than this going on in Fossil. Many of the artifacts have meaning |
| 99 | and are related to other artifacts. But at a low level (for example when |
| 100 | synchronizing two instances of the same project) the only thing that matters |
| 101 | is the unordered collection of artifacts. In fact, one of the key |
| 102 | characteristics of Fossil is that the entire project history can be |
| 103 | reconstructed simply by scanning the artifacts in an arbitrary order. |
| 104 | |
| 105 | The number of check-ins is the number of times that the "commit" command |
| 106 | has been run. A single check-in might change a 3 or 4 files, or it might |
| 107 | change dozens or hundreds of files. Regardless of the number of files |
| 108 | changed, it still only counts as one check-in. |
| 109 | |
| 110 | The "Uncompressed Size" is the total size of all the artifacts within |
| 111 | the repository assuming they were all uncompressed and stored |
| 112 | separately on the disk. Fossil makes use of delta compression between related |
| 113 | versions of the same file, and then uses zlib compression on the resulting |
| 114 | deltas. The total resulting repository size is shown after the uncompressed |
| 115 | size. |
| 116 | |
| 117 |
| --- www/stats.wiki | |
| +++ www/stats.wiki | |
| @@ -1,9 +1,9 @@ | |
| 1 | <title>Fossil Performance</title> |
| 2 | <h1 align="center">Performance Statistics</h1> |
| 3 | |
| 4 | The questions will inevitably arise: How does Fossil perform? |
| 5 | Does it use a lot of disk space or bandwidth? Is it scalable? |
| 6 | |
| 7 | In an attempt to answers these questions, this report looks at several |
| 8 | projects that use fossil for configuration management and examines how |
| 9 | well they are working. The following table is a summary of the results. |
| @@ -96,21 +96,21 @@ | |
| 96 | every ticket, and every check-in is a separate "artifact". One way to |
| 97 | think of a Fossil project is as a bag of artifacts. Of course, there is |
| 98 | a lot more than this going on in Fossil. Many of the artifacts have meaning |
| 99 | and are related to other artifacts. But at a low level (for example when |
| 100 | synchronizing two instances of the same project) the only thing that matters |
| 101 | is the unordered collection of artifacts. In fact, one of the key |
| 102 | characteristics of Fossil is that the entire project history can be |
| 103 | reconstructed simply by scanning the artifacts in an arbitrary order. |
| 104 | |
| 105 | The number of check-ins is the number of times that the "commit" command |
| 106 | has been run. A single check-in might change a 3 or 4 files, or it might |
| 107 | change dozens or hundreds of files. Regardless of the number of files |
| 108 | changed, it still only counts as one check-in. |
| 109 | |
| 110 | The "Uncompressed Size" is the total size of all the artifacts within |
| 111 | the repository assuming they were all uncompressed and stored |
| 112 | separately on the disk. Fossil makes use of delta compression between related |
| 113 | versions of the same file, and then uses zlib compression on the resulting |
| 114 | deltas. The total resulting repository size is shown after the uncompressed |
| 115 | size. |
| 116 | |
| 117 |
+6
-6
| --- www/sync.wiki | ||
| +++ www/sync.wiki | ||
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | <title>The Fossil Sync Protocol</title> |
| 2 | 2 | |
| 3 | -<p>This document describes the wire protocol used to synchronize | |
| 3 | +<p>This document describes the wire protocol used to synchronize | |
| 4 | 4 | content between two Fossil repositories.</p> |
| 5 | 5 | |
| 6 | 6 | <h2>1.0 Overview</h2> |
| 7 | 7 | |
| 8 | 8 | <p>The global state of a fossil repository consists of an unordered |
| @@ -22,11 +22,11 @@ | ||
| 22 | 22 | shared to a few hundred.</p> |
| 23 | 23 | |
| 24 | 24 | <p>Each repository also has local state. The local state determines |
| 25 | 25 | the web-page formatting preferences, authorized users, ticket formats, |
| 26 | 26 | and similar information that varies from one repository to another. |
| 27 | -The local state is not using transferred during a sync. Except, | |
| 27 | +The local state is not using transferred during a sync. Except, | |
| 28 | 28 | some local state is transferred during a [/help?cmd=clone|clone] |
| 29 | 29 | in order to initialize the local state of the new repository. And |
| 30 | 30 | the [/help?cmd=configuration|config push] and |
| 31 | 31 | [/help?cmd=configuration|config pull] |
| 32 | 32 | commands can be an administrator to sync local state.</p> |
| @@ -40,15 +40,15 @@ | ||
| 40 | 40 | request.</p> |
| 41 | 41 | |
| 42 | 42 | <p>The server might be running as an independent server |
| 43 | 43 | using the <b>server</b> command, or it might be launched from |
| 44 | 44 | inetd or xinetd using the <b>http</b> command. Or the server might |
| 45 | -be launched from CGI. | |
| 45 | +be launched from CGI. | |
| 46 | 46 | (See "[./server.wiki|How To Configure A Fossil Server]" for details.) |
| 47 | 47 | The specifics of how the server listens |
| 48 | 48 | for incoming HTTP requests is immaterial to this protocol. |
| 49 | -The important point is that the server is listening for requests and | |
| 49 | +The important point is that the server is listening for requests and | |
| 50 | 50 | the client is the issuer of the requests.</p> |
| 51 | 51 | |
| 52 | 52 | <p>A single push, pull, or sync might involve multiple HTTP requests. |
| 53 | 53 | The client maintains state between all requests. But on the server |
| 54 | 54 | side, each request is independent. The server does not preserve |
| @@ -55,11 +55,11 @@ | ||
| 55 | 55 | any information about the client from one request to the next.</p> |
| 56 | 56 | |
| 57 | 57 | <h4>2.0.1 Encrypted Transport</h4> |
| 58 | 58 | |
| 59 | 59 | <p>In the current implementation of Fossil, the server only |
| 60 | -understands HTTP requests. The client can send either | |
| 60 | +understands HTTP requests. The client can send either | |
| 61 | 61 | clear-text HTTP requests or encrypted HTTPS requests. But when |
| 62 | 62 | HTTPS requests are sent, they first must be decrypted by a webserver |
| 63 | 63 | or proxy before being passed to the Fossil server. This limitation |
| 64 | 64 | may be relaxed in a future release.</p> |
| 65 | 65 | |
| @@ -408,11 +408,11 @@ | ||
| 408 | 408 | <b>uvigot</b> <i>name mtime hash size</i> |
| 409 | 409 | </blockquote> |
| 410 | 410 | |
| 411 | 411 | <p>The <i>name</i> argument is the name of an unversioned file. |
| 412 | 412 | The <i>mtime</i> is the last modification time of the unversioned file |
| 413 | -in seconds since 1970. | |
| 413 | +in seconds since 1970. | |
| 414 | 414 | The <i>hash</i> is the SHA1 hash of the unversioned file content, or |
| 415 | 415 | "<b>-</b>" if the file has been deleted. |
| 416 | 416 | The <i>size</i> is the uncompressed size of the file in bytes. |
| 417 | 417 | |
| 418 | 418 | <p>When the server sees a "pragma uv-hash" card for which the hash |
| 419 | 419 |
| --- www/sync.wiki | |
| +++ www/sync.wiki | |
| @@ -1,8 +1,8 @@ | |
| 1 | <title>The Fossil Sync Protocol</title> |
| 2 | |
| 3 | <p>This document describes the wire protocol used to synchronize |
| 4 | content between two Fossil repositories.</p> |
| 5 | |
| 6 | <h2>1.0 Overview</h2> |
| 7 | |
| 8 | <p>The global state of a fossil repository consists of an unordered |
| @@ -22,11 +22,11 @@ | |
| 22 | shared to a few hundred.</p> |
| 23 | |
| 24 | <p>Each repository also has local state. The local state determines |
| 25 | the web-page formatting preferences, authorized users, ticket formats, |
| 26 | and similar information that varies from one repository to another. |
| 27 | The local state is not using transferred during a sync. Except, |
| 28 | some local state is transferred during a [/help?cmd=clone|clone] |
| 29 | in order to initialize the local state of the new repository. And |
| 30 | the [/help?cmd=configuration|config push] and |
| 31 | [/help?cmd=configuration|config pull] |
| 32 | commands can be an administrator to sync local state.</p> |
| @@ -40,15 +40,15 @@ | |
| 40 | request.</p> |
| 41 | |
| 42 | <p>The server might be running as an independent server |
| 43 | using the <b>server</b> command, or it might be launched from |
| 44 | inetd or xinetd using the <b>http</b> command. Or the server might |
| 45 | be launched from CGI. |
| 46 | (See "[./server.wiki|How To Configure A Fossil Server]" for details.) |
| 47 | The specifics of how the server listens |
| 48 | for incoming HTTP requests is immaterial to this protocol. |
| 49 | The important point is that the server is listening for requests and |
| 50 | the client is the issuer of the requests.</p> |
| 51 | |
| 52 | <p>A single push, pull, or sync might involve multiple HTTP requests. |
| 53 | The client maintains state between all requests. But on the server |
| 54 | side, each request is independent. The server does not preserve |
| @@ -55,11 +55,11 @@ | |
| 55 | any information about the client from one request to the next.</p> |
| 56 | |
| 57 | <h4>2.0.1 Encrypted Transport</h4> |
| 58 | |
| 59 | <p>In the current implementation of Fossil, the server only |
| 60 | understands HTTP requests. The client can send either |
| 61 | clear-text HTTP requests or encrypted HTTPS requests. But when |
| 62 | HTTPS requests are sent, they first must be decrypted by a webserver |
| 63 | or proxy before being passed to the Fossil server. This limitation |
| 64 | may be relaxed in a future release.</p> |
| 65 | |
| @@ -408,11 +408,11 @@ | |
| 408 | <b>uvigot</b> <i>name mtime hash size</i> |
| 409 | </blockquote> |
| 410 | |
| 411 | <p>The <i>name</i> argument is the name of an unversioned file. |
| 412 | The <i>mtime</i> is the last modification time of the unversioned file |
| 413 | in seconds since 1970. |
| 414 | The <i>hash</i> is the SHA1 hash of the unversioned file content, or |
| 415 | "<b>-</b>" if the file has been deleted. |
| 416 | The <i>size</i> is the uncompressed size of the file in bytes. |
| 417 | |
| 418 | <p>When the server sees a "pragma uv-hash" card for which the hash |
| 419 |
| --- www/sync.wiki | |
| +++ www/sync.wiki | |
| @@ -1,8 +1,8 @@ | |
| 1 | <title>The Fossil Sync Protocol</title> |
| 2 | |
| 3 | <p>This document describes the wire protocol used to synchronize |
| 4 | content between two Fossil repositories.</p> |
| 5 | |
| 6 | <h2>1.0 Overview</h2> |
| 7 | |
| 8 | <p>The global state of a fossil repository consists of an unordered |
| @@ -22,11 +22,11 @@ | |
| 22 | shared to a few hundred.</p> |
| 23 | |
| 24 | <p>Each repository also has local state. The local state determines |
| 25 | the web-page formatting preferences, authorized users, ticket formats, |
| 26 | and similar information that varies from one repository to another. |
| 27 | The local state is not using transferred during a sync. Except, |
| 28 | some local state is transferred during a [/help?cmd=clone|clone] |
| 29 | in order to initialize the local state of the new repository. And |
| 30 | the [/help?cmd=configuration|config push] and |
| 31 | [/help?cmd=configuration|config pull] |
| 32 | commands can be an administrator to sync local state.</p> |
| @@ -40,15 +40,15 @@ | |
| 40 | request.</p> |
| 41 | |
| 42 | <p>The server might be running as an independent server |
| 43 | using the <b>server</b> command, or it might be launched from |
| 44 | inetd or xinetd using the <b>http</b> command. Or the server might |
| 45 | be launched from CGI. |
| 46 | (See "[./server.wiki|How To Configure A Fossil Server]" for details.) |
| 47 | The specifics of how the server listens |
| 48 | for incoming HTTP requests is immaterial to this protocol. |
| 49 | The important point is that the server is listening for requests and |
| 50 | the client is the issuer of the requests.</p> |
| 51 | |
| 52 | <p>A single push, pull, or sync might involve multiple HTTP requests. |
| 53 | The client maintains state between all requests. But on the server |
| 54 | side, each request is independent. The server does not preserve |
| @@ -55,11 +55,11 @@ | |
| 55 | any information about the client from one request to the next.</p> |
| 56 | |
| 57 | <h4>2.0.1 Encrypted Transport</h4> |
| 58 | |
| 59 | <p>In the current implementation of Fossil, the server only |
| 60 | understands HTTP requests. The client can send either |
| 61 | clear-text HTTP requests or encrypted HTTPS requests. But when |
| 62 | HTTPS requests are sent, they first must be decrypted by a webserver |
| 63 | or proxy before being passed to the Fossil server. This limitation |
| 64 | may be relaxed in a future release.</p> |
| 65 | |
| @@ -408,11 +408,11 @@ | |
| 408 | <b>uvigot</b> <i>name mtime hash size</i> |
| 409 | </blockquote> |
| 410 | |
| 411 | <p>The <i>name</i> argument is the name of an unversioned file. |
| 412 | The <i>mtime</i> is the last modification time of the unversioned file |
| 413 | in seconds since 1970. |
| 414 | The <i>hash</i> is the SHA1 hash of the unversioned file content, or |
| 415 | "<b>-</b>" if the file has been deleted. |
| 416 | The <i>size</i> is the uncompressed size of the file in bytes. |
| 417 | |
| 418 | <p>When the server sees a "pragma uv-hash" card for which the hash |
| 419 |
+19
| --- www/th1.md | ||
| +++ www/th1.md | ||
| @@ -174,10 +174,12 @@ | ||
| 174 | 174 | * tclInvoke |
| 175 | 175 | * tclIsSafe |
| 176 | 176 | * tclMakeSafe |
| 177 | 177 | * tclReady |
| 178 | 178 | * trace |
| 179 | + * unversioned content | |
| 180 | + * unversioned list | |
| 179 | 181 | * utime |
| 180 | 182 | * verifyCsrf |
| 181 | 183 | * wiki |
| 182 | 184 | |
| 183 | 185 | Each of the commands above is documented by a block comment above their |
| @@ -610,10 +612,27 @@ | ||
| 610 | 612 | ------------------------------------- |
| 611 | 613 | |
| 612 | 614 | * trace STRING |
| 613 | 615 | |
| 614 | 616 | Generates a TH1 trace message if TH1 tracing is enabled. |
| 617 | + | |
| 618 | +<a name="unversioned_content"></a>TH1 unversioned content Command | |
| 619 | +----------------------------------------------------------------- | |
| 620 | + | |
| 621 | + * unversioned content FILENAME | |
| 622 | + | |
| 623 | +Attempts to locate the specified unversioned file and return its contents. | |
| 624 | +An error is generated if the repository is not open or the unversioned file | |
| 625 | +cannot be found. | |
| 626 | + | |
| 627 | +<a name="unversioned_list"></a>TH1 unversioned list Command | |
| 628 | +----------------------------------------------------------- | |
| 629 | + | |
| 630 | + * unversioned list | |
| 631 | + | |
| 632 | +Returns a list of the names of all unversioned files held in the local | |
| 633 | +repository. An error is generated if the repository is not open. | |
| 615 | 634 | |
| 616 | 635 | <a name="utime"></a>TH1 utime Command |
| 617 | 636 | ------------------------------------- |
| 618 | 637 | |
| 619 | 638 | * utime |
| 620 | 639 |
| --- www/th1.md | |
| +++ www/th1.md | |
| @@ -174,10 +174,12 @@ | |
| 174 | * tclInvoke |
| 175 | * tclIsSafe |
| 176 | * tclMakeSafe |
| 177 | * tclReady |
| 178 | * trace |
| 179 | * utime |
| 180 | * verifyCsrf |
| 181 | * wiki |
| 182 | |
| 183 | Each of the commands above is documented by a block comment above their |
| @@ -610,10 +612,27 @@ | |
| 610 | ------------------------------------- |
| 611 | |
| 612 | * trace STRING |
| 613 | |
| 614 | Generates a TH1 trace message if TH1 tracing is enabled. |
| 615 | |
| 616 | <a name="utime"></a>TH1 utime Command |
| 617 | ------------------------------------- |
| 618 | |
| 619 | * utime |
| 620 |
| --- www/th1.md | |
| +++ www/th1.md | |
| @@ -174,10 +174,12 @@ | |
| 174 | * tclInvoke |
| 175 | * tclIsSafe |
| 176 | * tclMakeSafe |
| 177 | * tclReady |
| 178 | * trace |
| 179 | * unversioned content |
| 180 | * unversioned list |
| 181 | * utime |
| 182 | * verifyCsrf |
| 183 | * wiki |
| 184 | |
| 185 | Each of the commands above is documented by a block comment above their |
| @@ -610,10 +612,27 @@ | |
| 612 | ------------------------------------- |
| 613 | |
| 614 | * trace STRING |
| 615 | |
| 616 | Generates a TH1 trace message if TH1 tracing is enabled. |
| 617 | |
| 618 | <a name="unversioned_content"></a>TH1 unversioned content Command |
| 619 | ----------------------------------------------------------------- |
| 620 | |
| 621 | * unversioned content FILENAME |
| 622 | |
| 623 | Attempts to locate the specified unversioned file and return its contents. |
| 624 | An error is generated if the repository is not open or the unversioned file |
| 625 | cannot be found. |
| 626 | |
| 627 | <a name="unversioned_list"></a>TH1 unversioned list Command |
| 628 | ----------------------------------------------------------- |
| 629 | |
| 630 | * unversioned list |
| 631 | |
| 632 | Returns a list of the names of all unversioned files held in the local |
| 633 | repository. An error is generated if the repository is not open. |
| 634 | |
| 635 | <a name="utime"></a>TH1 utime Command |
| 636 | ------------------------------------- |
| 637 | |
| 638 | * utime |
| 639 |
+5
-5
| --- www/theory1.wiki | ||
| +++ www/theory1.wiki | ||
| @@ -16,18 +16,18 @@ | ||
| 16 | 16 | |
| 17 | 17 | <h2>Fossil Is A NoSQL Database</h2> |
| 18 | 18 | |
| 19 | 19 | We begin with the first question: Fossil is not based on a distributed |
| 20 | 20 | NoSQL database because Fossil <u><i>is</i></u> a distributed NoSQL database. |
| 21 | -Fossil is <u>not</u> based on SQLite. | |
| 21 | +Fossil is <u>not</u> based on SQLite. | |
| 22 | 22 | The current implementation of Fossil uses |
| 23 | 23 | SQLite as a local store for the content of the distributed database and as |
| 24 | 24 | a cache for meta-information about the distributed database that is precomputed |
| 25 | 25 | for quick and easy presentation. But the use of SQLite in this role is an |
| 26 | 26 | implementation detail and is not fundamental to the design. Some future |
| 27 | 27 | version of Fossil might do away with SQLite and substitute a pile-of-files or |
| 28 | -a key/value database in place of SQLite. | |
| 28 | +a key/value database in place of SQLite. | |
| 29 | 29 | (Actually, that is very unlikely |
| 30 | 30 | to happen since SQLite works amazingly well in its current role, but the point |
| 31 | 31 | is that omitting SQLite from Fossil is a theoretical possibility.) |
| 32 | 32 | |
| 33 | 33 | The underlying database that Fossil implements has nothing to do with |
| @@ -64,11 +64,11 @@ | ||
| 64 | 64 | a NoSQL database) and there is the local relational database. The |
| 65 | 65 | bag-of-artifacts database has a fixed format and is what defines a Fossil |
| 66 | 66 | repository. Fossil will never modify the file format of the bag-of-artifacts |
| 67 | 67 | database in an incompatible way because to do so would be to make something |
| 68 | 68 | that is no longer "Fossil". The local relational database, on the other hand, |
| 69 | -is a cache that contains information derived from the bag-of-artifacts. | |
| 69 | +is a cache that contains information derived from the bag-of-artifacts. | |
| 70 | 70 | The schema of the local relational database changes from time to time as |
| 71 | 71 | the Fossil implementation is enhanced, and the content is recomputed from |
| 72 | 72 | the unchanging bag of artifacts. The local relational database is an |
| 73 | 73 | implementation detail which currently happens to use SQLite. |
| 74 | 74 | |
| @@ -89,11 +89,11 @@ | ||
| 89 | 89 | the first question. |
| 90 | 90 | |
| 91 | 91 | <h2>SQL Is A High-Level Scripting Language</h2> |
| 92 | 92 | |
| 93 | 93 | The second concern states that Fossil does not use a high-level scripting |
| 94 | -language. But that is not true. Fossil uses SQL (as implemented by SQLite) | |
| 94 | +language. But that is not true. Fossil uses SQL (as implemented by SQLite) | |
| 95 | 95 | as its scripting language. |
| 96 | 96 | |
| 97 | 97 | This misunderstanding likely arises because people fail |
| 98 | 98 | to appreciate that SQL is a programming language. People are taught that SQL |
| 99 | 99 | is a "query language" as if that were somehow different from a |
| @@ -125,11 +125,11 @@ | ||
| 125 | 125 | out using SQL statements. It is true that these SQL statements are glued |
| 126 | 126 | together with C code, but it turns out that C works surprisingly well in |
| 127 | 127 | that role. Several early prototypes of Fossil were written in a scripting |
| 128 | 128 | language (TCL). We normally find that TCL programs are shorter than the |
| 129 | 129 | equivalent C code by a factor of 10 or more. But in the case of Fossil, |
| 130 | -the use of TCL was actually making the code longer and more difficult to | |
| 130 | +the use of TCL was actually making the code longer and more difficult to | |
| 131 | 131 | understand. |
| 132 | 132 | And so in the final design, we switched from TCL to C in order to make |
| 133 | 133 | the code easier to implement and debug. |
| 134 | 134 | |
| 135 | 135 | Without the advantages of having SQLite built in, the design might well |
| 136 | 136 |
| --- www/theory1.wiki | |
| +++ www/theory1.wiki | |
| @@ -16,18 +16,18 @@ | |
| 16 | |
| 17 | <h2>Fossil Is A NoSQL Database</h2> |
| 18 | |
| 19 | We begin with the first question: Fossil is not based on a distributed |
| 20 | NoSQL database because Fossil <u><i>is</i></u> a distributed NoSQL database. |
| 21 | Fossil is <u>not</u> based on SQLite. |
| 22 | The current implementation of Fossil uses |
| 23 | SQLite as a local store for the content of the distributed database and as |
| 24 | a cache for meta-information about the distributed database that is precomputed |
| 25 | for quick and easy presentation. But the use of SQLite in this role is an |
| 26 | implementation detail and is not fundamental to the design. Some future |
| 27 | version of Fossil might do away with SQLite and substitute a pile-of-files or |
| 28 | a key/value database in place of SQLite. |
| 29 | (Actually, that is very unlikely |
| 30 | to happen since SQLite works amazingly well in its current role, but the point |
| 31 | is that omitting SQLite from Fossil is a theoretical possibility.) |
| 32 | |
| 33 | The underlying database that Fossil implements has nothing to do with |
| @@ -64,11 +64,11 @@ | |
| 64 | a NoSQL database) and there is the local relational database. The |
| 65 | bag-of-artifacts database has a fixed format and is what defines a Fossil |
| 66 | repository. Fossil will never modify the file format of the bag-of-artifacts |
| 67 | database in an incompatible way because to do so would be to make something |
| 68 | that is no longer "Fossil". The local relational database, on the other hand, |
| 69 | is a cache that contains information derived from the bag-of-artifacts. |
| 70 | The schema of the local relational database changes from time to time as |
| 71 | the Fossil implementation is enhanced, and the content is recomputed from |
| 72 | the unchanging bag of artifacts. The local relational database is an |
| 73 | implementation detail which currently happens to use SQLite. |
| 74 | |
| @@ -89,11 +89,11 @@ | |
| 89 | the first question. |
| 90 | |
| 91 | <h2>SQL Is A High-Level Scripting Language</h2> |
| 92 | |
| 93 | The second concern states that Fossil does not use a high-level scripting |
| 94 | language. But that is not true. Fossil uses SQL (as implemented by SQLite) |
| 95 | as its scripting language. |
| 96 | |
| 97 | This misunderstanding likely arises because people fail |
| 98 | to appreciate that SQL is a programming language. People are taught that SQL |
| 99 | is a "query language" as if that were somehow different from a |
| @@ -125,11 +125,11 @@ | |
| 125 | out using SQL statements. It is true that these SQL statements are glued |
| 126 | together with C code, but it turns out that C works surprisingly well in |
| 127 | that role. Several early prototypes of Fossil were written in a scripting |
| 128 | language (TCL). We normally find that TCL programs are shorter than the |
| 129 | equivalent C code by a factor of 10 or more. But in the case of Fossil, |
| 130 | the use of TCL was actually making the code longer and more difficult to |
| 131 | understand. |
| 132 | And so in the final design, we switched from TCL to C in order to make |
| 133 | the code easier to implement and debug. |
| 134 | |
| 135 | Without the advantages of having SQLite built in, the design might well |
| 136 |
| --- www/theory1.wiki | |
| +++ www/theory1.wiki | |
| @@ -16,18 +16,18 @@ | |
| 16 | |
| 17 | <h2>Fossil Is A NoSQL Database</h2> |
| 18 | |
| 19 | We begin with the first question: Fossil is not based on a distributed |
| 20 | NoSQL database because Fossil <u><i>is</i></u> a distributed NoSQL database. |
| 21 | Fossil is <u>not</u> based on SQLite. |
| 22 | The current implementation of Fossil uses |
| 23 | SQLite as a local store for the content of the distributed database and as |
| 24 | a cache for meta-information about the distributed database that is precomputed |
| 25 | for quick and easy presentation. But the use of SQLite in this role is an |
| 26 | implementation detail and is not fundamental to the design. Some future |
| 27 | version of Fossil might do away with SQLite and substitute a pile-of-files or |
| 28 | a key/value database in place of SQLite. |
| 29 | (Actually, that is very unlikely |
| 30 | to happen since SQLite works amazingly well in its current role, but the point |
| 31 | is that omitting SQLite from Fossil is a theoretical possibility.) |
| 32 | |
| 33 | The underlying database that Fossil implements has nothing to do with |
| @@ -64,11 +64,11 @@ | |
| 64 | a NoSQL database) and there is the local relational database. The |
| 65 | bag-of-artifacts database has a fixed format and is what defines a Fossil |
| 66 | repository. Fossil will never modify the file format of the bag-of-artifacts |
| 67 | database in an incompatible way because to do so would be to make something |
| 68 | that is no longer "Fossil". The local relational database, on the other hand, |
| 69 | is a cache that contains information derived from the bag-of-artifacts. |
| 70 | The schema of the local relational database changes from time to time as |
| 71 | the Fossil implementation is enhanced, and the content is recomputed from |
| 72 | the unchanging bag of artifacts. The local relational database is an |
| 73 | implementation detail which currently happens to use SQLite. |
| 74 | |
| @@ -89,11 +89,11 @@ | |
| 89 | the first question. |
| 90 | |
| 91 | <h2>SQL Is A High-Level Scripting Language</h2> |
| 92 | |
| 93 | The second concern states that Fossil does not use a high-level scripting |
| 94 | language. But that is not true. Fossil uses SQL (as implemented by SQLite) |
| 95 | as its scripting language. |
| 96 | |
| 97 | This misunderstanding likely arises because people fail |
| 98 | to appreciate that SQL is a programming language. People are taught that SQL |
| 99 | is a "query language" as if that were somehow different from a |
| @@ -125,11 +125,11 @@ | |
| 125 | out using SQL statements. It is true that these SQL statements are glued |
| 126 | together with C code, but it turns out that C works surprisingly well in |
| 127 | that role. Several early prototypes of Fossil were written in a scripting |
| 128 | language (TCL). We normally find that TCL programs are shorter than the |
| 129 | equivalent C code by a factor of 10 or more. But in the case of Fossil, |
| 130 | the use of TCL was actually making the code longer and more difficult to |
| 131 | understand. |
| 132 | And so in the final design, we switched from TCL to C in order to make |
| 133 | the code easier to implement and debug. |
| 134 | |
| 135 | Without the advantages of having SQLite built in, the design might well |
| 136 |
+1
-2
| --- www/webui.wiki | ||
| +++ www/webui.wiki | ||
| @@ -25,12 +25,11 @@ | ||
| 25 | 25 | There are no extra programs to install or setup. |
| 26 | 26 | Everything you need is already pre-configured and built into the |
| 27 | 27 | self-contained, stand-alone Fossil executable. |
| 28 | 28 | |
| 29 | 29 | As an example of how useful this web interface can be, |
| 30 | -the entire [./index.wiki | Fossil website] (except for the | |
| 31 | -[http://www.fossil-scm.org/download.html | download page]), | |
| 30 | +the entire [./index.wiki | Fossil website], | |
| 32 | 31 | including the document you are now reading, |
| 33 | 32 | is rendered using the Fossil web interface, with no enhancements, |
| 34 | 33 | and little customization. |
| 35 | 34 | |
| 36 | 35 | <blockquote> |
| 37 | 36 |
| --- www/webui.wiki | |
| +++ www/webui.wiki | |
| @@ -25,12 +25,11 @@ | |
| 25 | There are no extra programs to install or setup. |
| 26 | Everything you need is already pre-configured and built into the |
| 27 | self-contained, stand-alone Fossil executable. |
| 28 | |
| 29 | As an example of how useful this web interface can be, |
| 30 | the entire [./index.wiki | Fossil website] (except for the |
| 31 | [http://www.fossil-scm.org/download.html | download page]), |
| 32 | including the document you are now reading, |
| 33 | is rendered using the Fossil web interface, with no enhancements, |
| 34 | and little customization. |
| 35 | |
| 36 | <blockquote> |
| 37 |
| --- www/webui.wiki | |
| +++ www/webui.wiki | |
| @@ -25,12 +25,11 @@ | |
| 25 | There are no extra programs to install or setup. |
| 26 | Everything you need is already pre-configured and built into the |
| 27 | self-contained, stand-alone Fossil executable. |
| 28 | |
| 29 | As an example of how useful this web interface can be, |
| 30 | the entire [./index.wiki | Fossil website], |
| 31 | including the document you are now reading, |
| 32 | is rendered using the Fossil web interface, with no enhancements, |
| 33 | and little customization. |
| 34 | |
| 35 | <blockquote> |
| 36 |
+4
-4
| --- www/wikitheory.wiki | ||
| +++ www/wikitheory.wiki | ||
| @@ -34,26 +34,26 @@ | ||
| 34 | 34 | the wiki page will fork. The web interface will display whichever edit |
| 35 | 35 | was checked in last. The other edit can be found in the history. The |
| 36 | 36 | file format will support merging the branches back together, but there |
| 37 | 37 | is no mechanism in the user interface (yet) to perform the merge. |
| 38 | 38 | |
| 39 | -Every change to a wiki page is a separate | |
| 39 | +Every change to a wiki page is a separate | |
| 40 | 40 | [./fileformat.wiki | control artifact] |
| 41 | 41 | of type [./fileformat.wiki#wikichng | "Wiki Page"]. |
| 42 | 42 | |
| 43 | 43 | <h2>Embedded Documentation</h2> |
| 44 | 44 | |
| 45 | 45 | Files in the source tree that use the ".wiki", ".md", or ".markdown" suffixes |
| 46 | -can be accessed and displayed using special URLs to the fossil server. | |
| 46 | +can be accessed and displayed using special URLs to the fossil server. | |
| 47 | 47 | This allows |
| 48 | -project documentation to be stored in the source tree and accessed | |
| 48 | +project documentation to be stored in the source tree and accessed | |
| 49 | 49 | online. (Details are described [./embeddeddoc.wiki | separately].) |
| 50 | 50 | |
| 51 | 51 | Some projects prefer to store their documentation in wiki. There is nothing |
| 52 | 52 | wrong with that. But other projects prefer to keep documentation as part |
| 53 | 53 | of the source tree, so that it is versioned along with the source tree and |
| 54 | -so that only developers with check-in privileges can change it. | |
| 54 | +so that only developers with check-in privileges can change it. | |
| 55 | 55 | Embedded documentation serves this latter purpose. Both forms of documentation |
| 56 | 56 | use the exact same markup. Some projects may choose to |
| 57 | 57 | use both forms of documentation at the same time. Because the same |
| 58 | 58 | format is used, it is trivial to move a file from wiki to embedded documentation |
| 59 | 59 | or back again as the project evolves. |
| 60 | 60 |
| --- www/wikitheory.wiki | |
| +++ www/wikitheory.wiki | |
| @@ -34,26 +34,26 @@ | |
| 34 | the wiki page will fork. The web interface will display whichever edit |
| 35 | was checked in last. The other edit can be found in the history. The |
| 36 | file format will support merging the branches back together, but there |
| 37 | is no mechanism in the user interface (yet) to perform the merge. |
| 38 | |
| 39 | Every change to a wiki page is a separate |
| 40 | [./fileformat.wiki | control artifact] |
| 41 | of type [./fileformat.wiki#wikichng | "Wiki Page"]. |
| 42 | |
| 43 | <h2>Embedded Documentation</h2> |
| 44 | |
| 45 | Files in the source tree that use the ".wiki", ".md", or ".markdown" suffixes |
| 46 | can be accessed and displayed using special URLs to the fossil server. |
| 47 | This allows |
| 48 | project documentation to be stored in the source tree and accessed |
| 49 | online. (Details are described [./embeddeddoc.wiki | separately].) |
| 50 | |
| 51 | Some projects prefer to store their documentation in wiki. There is nothing |
| 52 | wrong with that. But other projects prefer to keep documentation as part |
| 53 | of the source tree, so that it is versioned along with the source tree and |
| 54 | so that only developers with check-in privileges can change it. |
| 55 | Embedded documentation serves this latter purpose. Both forms of documentation |
| 56 | use the exact same markup. Some projects may choose to |
| 57 | use both forms of documentation at the same time. Because the same |
| 58 | format is used, it is trivial to move a file from wiki to embedded documentation |
| 59 | or back again as the project evolves. |
| 60 |
| --- www/wikitheory.wiki | |
| +++ www/wikitheory.wiki | |
| @@ -34,26 +34,26 @@ | |
| 34 | the wiki page will fork. The web interface will display whichever edit |
| 35 | was checked in last. The other edit can be found in the history. The |
| 36 | file format will support merging the branches back together, but there |
| 37 | is no mechanism in the user interface (yet) to perform the merge. |
| 38 | |
| 39 | Every change to a wiki page is a separate |
| 40 | [./fileformat.wiki | control artifact] |
| 41 | of type [./fileformat.wiki#wikichng | "Wiki Page"]. |
| 42 | |
| 43 | <h2>Embedded Documentation</h2> |
| 44 | |
| 45 | Files in the source tree that use the ".wiki", ".md", or ".markdown" suffixes |
| 46 | can be accessed and displayed using special URLs to the fossil server. |
| 47 | This allows |
| 48 | project documentation to be stored in the source tree and accessed |
| 49 | online. (Details are described [./embeddeddoc.wiki | separately].) |
| 50 | |
| 51 | Some projects prefer to store their documentation in wiki. There is nothing |
| 52 | wrong with that. But other projects prefer to keep documentation as part |
| 53 | of the source tree, so that it is versioned along with the source tree and |
| 54 | so that only developers with check-in privileges can change it. |
| 55 | Embedded documentation serves this latter purpose. Both forms of documentation |
| 56 | use the exact same markup. Some projects may choose to |
| 57 | use both forms of documentation at the same time. Because the same |
| 58 | format is used, it is trivial to move a file from wiki to embedded documentation |
| 59 | or back again as the project evolves. |
| 60 |