Fossil SCM

Merge trunk

andygoth 2016-11-05 15:53 andygoth-changes merge
Commit a47d79e910a9c88ba76b31b121bbc38fb8b54743
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 @@
11
###
22
# Dockerfile for Fossil
33
###
4
-FROM fedora:23
4
+FROM fedora:24
55
66
### Now install some additional parts we will need for the build
77
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
88
99
### If you want to build "trunk", change the next line accordingly.
1010
--- 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
--- Makefile.in
+++ Makefile.in
@@ -37,10 +37,11 @@
3737
# care about testing the end result, this can be blank.
3838
#
3939
TCLSH = tclsh
4040
4141
LIB = @LDFLAGS@ @EXTRA_LDFLAGS@ @LIBS@
42
+BCCFLAGS = @CPPFLAGS@ @CFLAGS@
4243
TCCFLAGS = @EXTRA_CFLAGS@ @CPPFLAGS@ @CFLAGS@ -DHAVE_AUTOCONFIG_H -D_HAVE_SQLITE_CONFIG_H
4344
INSTALLDIR = $(DESTDIR)@prefix@/bin
4445
USE_SYSTEM_SQLITE = @USE_SYSTEM_SQLITE@
4546
USE_LINENOISE = @USE_LINENOISE@
4647
USE_SEE = @USE_SEE@
4748
--- 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
+1 -1
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1
-1.36
1
+1.37
22
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1 1.36
2
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1 1.37
2
+1
--- auto.def
+++ auto.def
@@ -479,10 +479,11 @@
479479
cc-check-function-in-lib sin m
480480
481481
# Check for the FuseFS library
482482
if {[opt-bool fusefs]} {
483483
if {[cc-check-function-in-lib fuse_mount fuse]} {
484
+ define-append EXTRA_CFLAGS -DFOSSIL_HAVE_FUSEFS
484485
define FOSSIL_HAVE_FUSEFS 1
485486
define-append LIBS -lfuse
486487
msg-result "FuseFS support enabled"
487488
}
488489
}
489490
--- 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
--- skins/black_and_white/css.txt
+++ skins/black_and_white/css.txt
@@ -106,16 +106,16 @@
106106
border-width:1px 0px;
107107
background-color: #eee;
108108
color: #333;
109109
}
110110
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 {
112112
padding: 3px 10px 3px 10px;
113113
color: #333;
114114
text-decoration: none;
115115
}
116
-div.submenu a:hover, div.sectionmenu>a.button:hover {
116
+div.submenu a:hover, div.sectionmenu>a.button:hover, div.submenu label:hover {
117117
color: #eee;
118118
background-color: #333;
119119
}
120120
121121
/* All page content from the bottom of the menu or submenu down to
122122
--- 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
--- skins/blitz/css.txt
+++ skins/blitz/css.txt
@@ -894,19 +894,19 @@
894894
895895
.submenu input, .submenu select {
896896
margin: 0 0 0 5px;
897897
}
898898
899
-.submenu a {
899
+.submenu a, .submenu label {
900900
color: #3b5c6b;
901901
padding: 5px 15px;
902902
text-decoration: none;
903903
border: 1px solid transparent;
904904
border-radius: 5px;
905905
}
906906
907
-.submenu a:hover {
907
+.submenu a:hover, .submenu label:hover {
908908
border: 1px solid #ccc;
909909
}
910910
911911
912912
/* Section
913913
--- 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
--- skins/blitz_no_logo/css.txt
+++ skins/blitz_no_logo/css.txt
@@ -894,19 +894,19 @@
894894
895895
.submenu input, .submenu select {
896896
margin: 0 0 0 5px;
897897
}
898898
899
-.submenu a {
899
+.submenu a, .submenu label {
900900
color: #3b5c6b;
901901
padding: 5px 15px;
902902
text-decoration: none;
903903
border: 1px solid transparent;
904904
border-radius: 5px;
905905
}
906906
907
-.submenu a:hover {
907
+.submenu a:hover, .submenu label:hover {
908908
border: 1px solid #ccc;
909909
}
910910
911911
912912
/* Section
913913
--- 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
--- skins/default/css.txt
+++ skins/default/css.txt
@@ -104,17 +104,17 @@
104104
margin-top: 10px;
105105
padding: 10px;
106106
border-bottom: 1px solid #ccc;
107107
}
108108
109
-.submenu a {
109
+.submenu a, .submenu label {
110110
padding: 10px 11px;
111111
text-decoration:none;
112112
color: #777;
113113
}
114114
115
-.submenu a:hover {
115
+.submenu a:hover, .submenu label:hover {
116116
padding: 6px 10px;
117117
border: 1px solid #ccc;
118118
border-radius: 5px;
119119
color: #000;
120120
}
121121
--- 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
--- skins/eagle/css.txt
+++ skins/eagle/css.txt
@@ -73,16 +73,18 @@
7373
text-align: center;
7474
background-color: #485D7B;
7575
color: white;
7676
}
7777
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 {
7980
padding: 3px 10px 3px 10px;
8081
color: white;
8182
text-decoration: none;
8283
}
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 {
8486
text-decoration: underline;
8587
}
8688
8789
/* All page content from the bottom of the menu or submenu down to
8890
** the footer */
8991
--- 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
--- skins/enhanced1/css.txt
+++ skins/enhanced1/css.txt
@@ -71,16 +71,18 @@
7171
text-align: center;
7272
background-color: #456878;
7373
color: white;
7474
}
7575
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 {
7778
padding: 3px 10px 3px 10px;
7879
color: white;
7980
text-decoration: none;
8081
}
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 {
8284
color: #558195;
8385
background-color: white;
8486
}
8587
8688
/* All page content from the bottom of the menu or submenu down to
8789
--- 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
--- skins/khaki/css.txt
+++ skins/khaki/css.txt
@@ -69,16 +69,18 @@
6969
text-align: center;
7070
background-color: #c0af58;
7171
color: white;
7272
}
7373
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 {
7576
padding: 3px 10px 3px 10px;
7677
color: white;
7778
text-decoration: none;
7879
}
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 {
8082
color: #a09048;
8183
background-color: white;
8284
}
8385
8486
/* All page content from the bottom of the menu or submenu down to
8587
--- 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
--- skins/original/css.txt
+++ skins/original/css.txt
@@ -71,16 +71,18 @@
7171
text-align: center;
7272
background-color: #456878;
7373
color: white;
7474
}
7575
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 {
7778
padding: 3px 10px 3px 10px;
7879
color: white;
7980
text-decoration: none;
8081
}
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 {
8284
color: #558195;
8385
background-color: white;
8486
}
8587
8688
/* All page content from the bottom of the menu or submenu down to
8789
--- 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
--- skins/plain_gray/css.txt
+++ skins/plain_gray/css.txt
@@ -71,16 +71,18 @@
7171
text-align: center;
7272
background-color: #606060;
7373
color: white;
7474
}
7575
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 {
7778
padding: 3px 10px 3px 10px;
7879
color: white;
7980
text-decoration: none;
8081
}
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 {
8284
color: #404040;
8385
background-color: white;
8486
}
8587
8688
/* All page content from the bottom of the menu or submenu down to
8789
--- 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
--- skins/rounded1/css.txt
+++ skins/rounded1/css.txt
@@ -84,11 +84,11 @@
8484
div.mainmenu a, div.mainmenu a:visited {
8585
padding: 3px 10px 3px 10px;
8686
color: white;
8787
text-decoration: none;
8888
}
89
-div.submenu a, div.submenu a:visited, a.button,
89
+div.submenu a, div.submenu a:visited, a.button, div.submenu label
9090
div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited {
9191
padding: 2px 8px;
9292
color: #000;
9393
font-family: Arial;
9494
text-decoration: none;
@@ -102,11 +102,11 @@
102102
div.mainmenu a:hover {
103103
color: #000;
104104
background-color: white;
105105
}
106106
107
-div.submenu a:hover, div.sectionmenu>a.button:hover {
107
+div.submenu a:hover, div.sectionmenu>a.button:hover, div.submenu label:hover {
108108
background-color: #c0c0c0;
109109
}
110110
111111
/* All page content from the bottom of the menu or submenu down to
112112
** the footer */
113113
--- 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
--- skins/xekri/css.txt
+++ skins/xekri/css.txt
@@ -158,17 +158,17 @@
158158
border-top: 1px solid #0a0;
159159
border-radius: 0;
160160
display: block;
161161
}
162162
163
-div.mainmenu a, div.submenu a {
163
+div.mainmenu a, div.submenu a, div.submenu label {
164164
color: #000;
165165
padding: 0 0.75rem;
166166
text-decoration: none;
167167
}
168168
169
-div.mainmenu a:hover, div.submenu a:hover {
169
+div.mainmenu a:hover, div.submenu a:hover, div.submenu label:hover {
170170
color: #fff;
171171
text-shadow: 0px 0px 6px #0f0;
172172
}
173173
174174
div.submenu * {
175175
--- 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 @@
173173
int useCheckouts = 0;
174174
int quiet = 0;
175175
int dryRunFlag = 0;
176176
int showFile = find_option("showfile",0,0)!=0;
177177
int stopOnError = find_option("dontstop",0,0)==0;
178
- int rc;
179178
int nToDel = 0;
180179
int showLabel = 0;
181180
182181
dryRunFlag = find_option("dry-run","n",0)!=0;
183182
if( !dryRunFlag ){
@@ -378,10 +377,11 @@
378377
);
379378
}
380379
db_multi_exec("CREATE TEMP TABLE toDel(x TEXT)");
381380
db_prepare(&q, "SELECT name, tag FROM repolist ORDER BY 1");
382381
while( db_step(&q)==SQLITE_ROW ){
382
+ int rc;
383383
const char *zFilename = db_column_text(&q, 0);
384384
#if !USE_SEE
385385
if( sqlite3_strglob("*.efossil", zFilename)==0 ) continue;
386386
#endif
387387
if( file_access(zFilename, F_OK)
388388
--- 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 @@
452452
#if 0
453453
/* Shunning here needs to get both the attachment control artifact and
454454
** the object that is attached. */
455455
if( g.perm.Admin ){
456456
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",
458458
g.zTop, zUuid);
459459
}else{
460
- style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
460
+ style_submenu_element("Shun", "%s/shun?shun=%s#addshun",
461461
g.zTop, zUuid);
462462
}
463463
}
464464
#endif
465465
pAttach = manifest_get(rid, CFTYPE_ATTACHMENT, 0);
@@ -475,23 +475,23 @@
475475
&& db_exists("SELECT 1 FROM ticket WHERE tkt_uuid='%q'", zTarget)
476476
){
477477
zTktUuid = zTarget;
478478
if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; }
479479
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);
481481
}
482482
}else if( db_exists("SELECT 1 FROM tag WHERE tagname='wiki-%q'",zTarget) ){
483483
zWikiName = zTarget;
484484
if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
485485
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);
487487
}
488488
}else if( db_exists("SELECT 1 FROM tag WHERE tagname='event-%q'",zTarget) ){
489489
zTNUuid = zTarget;
490490
if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
491491
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);
493493
}
494494
}
495495
zDate = db_text(0, "SELECT datetime(%.12f)", pAttach->rDate);
496496
497497
if( P("confirm")
@@ -551,14 +551,13 @@
551551
if( strcmp(zModAction,"approve")==0 ){
552552
moderation_approve(rid);
553553
}
554554
}
555555
style_header("Attachment Details");
556
- style_submenu_element("Raw", "Raw", "%R/artifact/%s", zUuid);
556
+ style_submenu_element("Raw", "%R/artifact/%s", zUuid);
557557
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,
560559
((zLn&&*zLn) ? "" : "?ln=0"));
561560
}
562561
563562
@ <div class="section">Overview</div>
564563
@ <p><table class="label-value">
@@ -629,11 +628,11 @@
629628
}
630629
}else if( strncmp(zMime, "image/", 6)==0 ){
631630
int sz = db_int(0, "SELECT size FROM blob WHERE rid=%d", ridSrc);
632631
@ <i>(file is %d(sz) bytes of image data)</i><br />
633632
@ <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);
635634
}else{
636635
int sz = db_int(0, "SELECT size FROM blob WHERE rid=%d", ridSrc);
637636
@ <i>(file is %d(sz) bytes of binary data)</i>
638637
}
639638
@ </blockquote>
640639
--- 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 @@
7575
** Return the value of a boolean bisect option.
7676
*/
7777
int bisect_option(const char *zName){
7878
unsigned int i;
7979
int r = -1;
80
- for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
80
+ for(i=0; i<count(aBisectOption); i++){
8181
if( fossil_strcmp(zName, aBisectOption[i].zName)==0 ){
8282
char *zLabel = mprintf("bisect-%s", zName);
8383
char *z = db_lget(zLabel, (char*)aBisectOption[i].zDefault);
8484
if( is_truth(z) ) r = 1;
8585
if( is_false(z) ) r = 0;
@@ -406,21 +406,21 @@
406406
}else if( strncmp(zCmd, "chart", n)==0 ){
407407
bisect_chart(1);
408408
}else if( strncmp(zCmd, "options", n)==0 ){
409409
if( g.argc==3 ){
410410
unsigned int i;
411
- for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
411
+ for(i=0; i<count(aBisectOption); i++){
412412
char *z = mprintf("bisect-%s", aBisectOption[i].zName);
413413
fossil_print(" %-15s %-6s ", aBisectOption[i].zName,
414414
db_lget(z, (char*)aBisectOption[i].zDefault));
415415
fossil_free(z);
416416
comment_print(aBisectOption[i].zDesc, 0, 27, -1, g.comFmtFlags);
417417
}
418418
}else if( g.argc==4 || g.argc==5 ){
419419
unsigned int i;
420420
n = strlen(g.argv[3]);
421
- for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
421
+ for(i=0; i<count(aBisectOption); i++){
422422
if( strncmp(g.argv[3], aBisectOption[i].zName, n)==0 ){
423423
char *z = mprintf("bisect-%s", aBisectOption[i].zName);
424424
if( g.argc==5 ){
425425
db_lset(z, g.argv[4]);
426426
}
@@ -427,11 +427,11 @@
427427
fossil_print("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault));
428428
fossil_free(z);
429429
break;
430430
}
431431
}
432
- if( i>=sizeof(aBisectOption)/sizeof(aBisectOption[0]) ){
432
+ if( i>=count(aBisectOption) ){
433433
fossil_fatal("no such bisect option: %s", g.argv[3]);
434434
}
435435
}else{
436436
usage("options ?NAME? ?VALUE?");
437437
}
438438
--- 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 @@
154154
if( brid==0 ){
155155
fossil_fatal("trouble committing manifest: %s", g.zErrMsg);
156156
}
157157
db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid);
158158
if( manifest_crosslink(brid, &branch, MC_PERMIT_HOOKS)==0 ){
159
- fossil_fatal("%s\n", g.zErrMsg);
159
+ fossil_fatal("%s", g.zErrMsg);
160160
}
161161
assert( blob_is_reset(&branch) );
162162
content_deltify(rootid, brid, 0);
163163
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", brid);
164164
fossil_print("New branch: %s\n", zUuid);
@@ -323,11 +323,12 @@
323323
@ WHERE plink.pid=event.objid
324324
@ AND tagxref.rid=plink.cid
325325
@ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch')
326326
@ AND tagtype>0),
327327
@ count(*),
328
-@ (SELECT uuid FROM blob WHERE rid=tagxref.rid)
328
+@ (SELECT uuid FROM blob WHERE rid=tagxref.rid),
329
+@ event.bgcolor
329330
@ FROM tagxref, tag, event
330331
@ WHERE tagxref.tagid=tag.tagid
331332
@ AND tagxref.tagtype>0
332333
@ AND tag.tagname='branch'
333334
@ AND event.objid=tagxref.rid
@@ -344,14 +345,16 @@
344345
** if there are no query parameters.
345346
*/
346347
static void new_brlist_page(void){
347348
Stmt q;
348349
double rNow;
350
+ int show_colors = PB("colors");
349351
login_check_credentials();
350352
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
351353
style_header("Branches");
352354
style_adunit_config(ADUNIT_RIGHT_OK);
355
+ style_submenu_checkbox("colors", "Use Branch Colors", 0);
353356
login_anonymous_available();
354357
355358
db_prepare(&q, brlistQuery/*works-like:""*/);
356359
rNow = db_double(0.0, "SELECT julianday('now')");
357360
@ <div class="brlist"><table id="branchlisttable">
@@ -367,14 +370,26 @@
367370
double rMtime = db_column_double(&q, 1);
368371
int isClosed = db_column_int(&q, 2);
369372
const char *zMergeTo = db_column_text(&q, 3);
370373
int nCkin = db_column_int(&q, 4);
371374
const char *zLastCkin = db_column_text(&q, 5);
375
+ const char *zBgClr = db_column_text(&q, 6);
372376
char *zAge = human_readable_age(rNow - rMtime);
373377
sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0);
374378
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
+ }
376391
@ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td>
377392
@ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td>
378393
@ <td>%d(nCkin)</td>
379394
fossil_free(zAge);
380395
@ <td>%s(isClosed?"closed":"")</td>
@@ -427,25 +442,25 @@
427442
if( showAll ) brFlags = BRL_BOTH;
428443
if( showClosed ) brFlags = BRL_CLOSED_ONLY;
429444
430445
style_header("%s", showClosed ? "Closed Branches" :
431446
showAll ? "All Branches" : "Open Branches");
432
- style_submenu_element("Timeline", "Timeline", "brtimeline");
447
+ style_submenu_element("Timeline", "brtimeline");
433448
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");
436451
}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");
439454
}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");
442457
}
443458
if( !colorTest ){
444
- style_submenu_element("Color-Test", "Color-Test", "brlist?colortest");
459
+ style_submenu_element("Color-Test", "brlist?colortest");
445460
}else{
446
- style_submenu_element("All", "All", "brlist?all");
461
+ style_submenu_element("All", "brlist?all");
447462
}
448463
login_anonymous_available();
449464
#if 0
450465
style_sidebox_begin("Nomenclature:", "33%");
451466
@ <ol>
@@ -529,11 +544,11 @@
529544
530545
login_check_credentials();
531546
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
532547
533548
style_header("Branches");
534
- style_submenu_element("List", "List", "brlist");
549
+ style_submenu_element("List", "brlist");
535550
login_anonymous_available();
536551
@ <h2>The initial check-in for each branch:</h2>
537552
db_prepare(&q,
538553
"%s AND blob.rid IN (SELECT rid FROM tagxref"
539554
" WHERE tagtype>0 AND tagid=%d AND srcid!=0)"
540555
--- 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 @@
171171
blob_zero(&dirname);
172172
if( zD ){
173173
blob_append(&dirname, "in directory ", -1);
174174
hyperlinked_path(zD, &dirname, zCI, "dir", "");
175175
zPrefix = mprintf("%s/", zD);
176
- style_submenu_element("Top-Level", "Top-Level", "%s",
176
+ style_submenu_element("Top-Level", "%s",
177177
url_render(&sURI, "name", 0, 0, 0));
178178
}else{
179179
blob_append(&dirname, "in the top-level directory", -1);
180180
zPrefix = "";
181181
}
182182
if( linkTrunk ){
183
- style_submenu_element("Trunk", "Trunk", "%s",
183
+ style_submenu_element("Trunk", "%s",
184184
url_render(&sURI, "ci", "trunk", 0, 0));
185185
}
186186
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));
189188
}
190189
if( zCI ){
191190
@ <h2>Files of check-in [%z(href("vinfo?name=%!S",zUuid))%S(zUuid)</a>]
192191
@ %s(blob_str(&dirname))</h2>
193192
zSubdirLink = mprintf("%R/dir?ci=%!S&name=%T", zUuid, zPrefix);
194193
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);
197195
}
198196
}else{
199197
@ <h2>The union of all files from all check-ins
200198
@ %s(blob_str(&dirname))</h2>
201199
zSubdirLink = mprintf("%R/dir?name=%T", zPrefix);
202200
}
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",
206203
url_render(&sURI, "type", "tree", 0, 0));
207204
208205
/* Compute the temporary table "localfiles" containing the names
209206
** of all files and subdirectories in the zD[] directory.
210207
**
@@ -616,35 +613,32 @@
616613
blob_zero(&dirname);
617614
if( zD ){
618615
blob_append(&dirname, "within directory ", -1);
619616
hyperlinked_path(zD, &dirname, zCI, "tree", zREx);
620617
if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE);
621
- style_submenu_element("Top-Level", "Top-Level", "%s",
618
+ style_submenu_element("Top-Level", "%s",
622619
url_render(&sURI, "name", 0, 0, 0));
623620
}else{
624621
if( zRE ){
625622
blob_appendf(&dirname, "matching \"%s\"", zRE);
626623
}
627624
}
628625
style_submenu_binary("mtime","Sort By Time","Sort By Filename", 0);
629626
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));
632628
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);
635630
}
636631
}
637632
if( linkTrunk ){
638
- style_submenu_element("Trunk", "Trunk", "%s",
633
+ style_submenu_element("Trunk", "%s",
639634
url_render(&sURI, "ci", "trunk", 0, 0));
640635
}
641636
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));
644638
}
645
- style_submenu_element("Flat-View", "Flat-View", "%s",
639
+ style_submenu_element("Flat-View", "%s",
646640
url_render(&sURI, "type", "flat", 0, 0));
647641
648642
/* Compute the file hierarchy.
649643
*/
650644
if( zCI ){
@@ -695,17 +689,15 @@
695689
if( showDirOnly ){
696690
for(nFile=0, p=sTree.pFirst; p; p=p->pNext){
697691
if( p->pChild!=0 && p->nFullName>nD ) nFile++;
698692
}
699693
zObjType = "Folders";
700
- style_submenu_element("Files","Files","%s",
701
- url_render(&sURI,"nofiles",0,0,0));
702694
}else{
703695
zObjType = "Files";
704
- style_submenu_element("Folders","Folders","%s",
705
- url_render(&sURI,"nofiles","1",0,0));
706696
}
697
+
698
+ style_submenu_checkbox("nofiles", "Folders Only", 0);
707699
708700
if( zCI ){
709701
@ <h2>%s(zObjType) from
710702
if( sqlite3_strnicmp(zCI, zUuid, (int)strlen(zCI))!=0 ){
711703
@ "%h(zCI)"
@@ -1032,13 +1024,11 @@
10321024
}
10331025
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
10341026
baseTime = db_double(0.0,"SELECT mtime FROM event WHERE objid=%d", rid);
10351027
zNow = db_text("", "SELECT datetime(mtime,toLocal()) FROM event"
10361028
" 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);
10401030
style_header("File Ages");
10411031
zGlob = P("glob");
10421032
compute_fileage(rid,zGlob);
10431033
db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);");
10441034
10451035
--- 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 @@
3333
** Return a pointer to built-in content
3434
*/
3535
const unsigned char *builtin_file(const char *zFilename, int *piSize){
3636
int lwr, upr, i, c;
3737
lwr = 0;
38
- upr = sizeof(aBuiltinFiles)/sizeof(aBuiltinFiles[0]) - 1;
38
+ upr = count(aBuiltinFiles) - 1;
3939
while( upr>=lwr ){
4040
i = (upr+lwr)/2;
4141
c = strcmp(aBuiltinFiles[i].zName,zFilename);
4242
if( c<0 ){
4343
lwr = i+1;
@@ -60,11 +60,11 @@
6060
**
6161
** List the names and sizes of all built-in resources.
6262
*/
6363
void test_builtin_list(void){
6464
int i;
65
- for(i=0; i<sizeof(aBuiltinFiles)/sizeof(aBuiltinFiles[0]); i++){
65
+ for(i=0; i<count(aBuiltinFiles); i++){
6666
fossil_print("%-30s %6d\n", aBuiltinFiles[i].zName,aBuiltinFiles[i].nByte);
6767
}
6868
}
6969
7070
/*
7171
--- 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 @@
2121
** formatting function and its cousins, and routines to encode and
2222
** decode strings in HTML or HTTP.
2323
*/
2424
#include "config.h"
2525
#ifdef _WIN32
26
+# if !defined(_WIN32_WINNT)
27
+# define _WIN32_WINNT 0x0501
28
+# endif
2629
# include <winsock2.h>
2730
# include <ws2tcpip.h>
2831
#else
2932
# include <sys/socket.h>
3033
# include <netinet/in.h>
@@ -716,11 +719,11 @@
716719
}
717720
}
718721
zName = 0;
719722
showBytes = 0;
720723
}else{
721
- nArg = tokenize_line(zLine, sizeof(azArg)/sizeof(azArg[0]), azArg);
724
+ nArg = tokenize_line(zLine, count(azArg), azArg);
722725
for(i=0; i<nArg; i++){
723726
int c = fossil_tolower(azArg[i][0]);
724727
int n = strlen(azArg[i]);
725728
if( c=='c' && sqlite3_strnicmp(azArg[i],"content-disposition:",n)==0 ){
726729
i++;
727730
--- 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 @@
22822282
fossil_fatal("trouble committing manifest: %s", g.zErrMsg);
22832283
}
22842284
db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nvid);
22852285
if( manifest_crosslink(nvid, &manifest,
22862286
dryRunFlag ? MC_NONE : MC_PERMIT_HOOKS)==0 ){
2287
- fossil_fatal("%s\n", g.zErrMsg);
2287
+ fossil_fatal("%s", g.zErrMsg);
22882288
}
22892289
assert( blob_is_reset(&manifest) );
22902290
content_deltify(vid, nvid, 0);
22912291
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid);
22922292
22932293
--- 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 @@
22822282
fossil_fatal("trouble committing manifest: %s", g.zErrMsg);
22832283
}
22842284
db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nvid);
22852285
if( manifest_crosslink(nvid, &manifest,
22862286
dryRunFlag ? MC_NONE : MC_PERMIT_HOOKS)==0 ){
2287
- fossil_fatal("%s\n", g.zErrMsg);
2287
+ fossil_fatal("%s", g.zErrMsg);
22882288
}
22892289
assert( blob_is_reset(&manifest) );
22902290
content_deltify(vid, nvid, 0);
22912291
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid);
22922292
22932293
--- 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
+166 -15
--- src/db.c
+++ src/db.c
@@ -27,11 +27,15 @@
2727
** (3) A local checkout database named "_FOSSIL_" or ".fslckout"
2828
** and located at the root of the local copy of the source tree.
2929
**
3030
*/
3131
#include "config.h"
32
-#if ! defined(_WIN32)
32
+#if defined(_WIN32)
33
+# if USE_SEE
34
+# include <windows.h>
35
+# endif
36
+#else
3337
# include <pwd.h>
3438
#endif
3539
#include <sqlite3.h>
3640
#include <sys/types.h>
3741
#include <sys/stat.h>
@@ -870,31 +874,170 @@
870874
db_tolocal_function, 0, 0);
871875
sqlite3_create_function(db, "fromLocal", 0, SQLITE_UTF8, 0,
872876
db_fromlocal_function, 0, 0);
873877
}
874878
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
+
8751018
/*
8761019
** 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.
8801024
*/
881
-static void db_encryption_key(
1025
+static void db_maybe_obtain_encryption_key(
8821026
const char *zDbFile, /* Name of the database file */
8831027
Blob *pKey /* Put the encryption key here */
8841028
){
885
- blob_init(pKey, 0, 0);
8861029
#if USE_SEE
8871030
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);
8911034
}else{
8921035
char *zPrompt = mprintf("\rencryption key for '%s': ", zDbFile);
8931036
prompt_for_password(zPrompt, pKey, 0);
8941037
fossil_free(zPrompt);
895
- zSavedKey = fossil_strdup(blob_str(pKey));
1038
+ db_set_saved_encryption_key(pKey);
8961039
}
8971040
}
8981041
#endif
8991042
}
9001043
@@ -915,14 +1058,16 @@
9151058
g.zVfsName
9161059
);
9171060
if( rc!=SQLITE_OK ){
9181061
db_err("[%s]: %s", zDbName, sqlite3_errmsg(db));
9191062
}
920
- db_encryption_key(zDbName, &key);
1063
+ blob_init(&key, 0, 0);
1064
+ db_maybe_obtain_encryption_key(zDbName, &key);
9211065
if( blob_size(&key)>0 ){
9221066
char *zCmd = sqlite3_mprintf("PRAGMA key(%Q)", blob_str(&key));
9231067
sqlite3_exec(db, zCmd, 0, 0, 0);
1068
+ fossil_secure_zero(zCmd, strlen(zCmd));
9241069
sqlite3_free(zCmd);
9251070
}
9261071
blob_reset(&key);
9271072
sqlite3_busy_timeout(db, 5000);
9281073
sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
@@ -955,14 +1100,19 @@
9551100
/*
9561101
** zDbName is the name of a database file. Attach zDbName using
9571102
** the name zLabel.
9581103
*/
9591104
void db_attach(const char *zDbName, const char *zLabel){
1105
+ char *zCmd;
9601106
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);
9641114
blob_reset(&key);
9651115
}
9661116
9671117
/*
9681118
** Change the schema name of the "main" database to zLabel.
@@ -1192,10 +1342,11 @@
11921342
}
11931343
if( db_local_table_exists_but_lacks_column("undo_vfile", "islink") ){
11941344
db_multi_exec("ALTER TABLE undo_vfile ADD COLUMN islink BOOL DEFAULT 0");
11951345
}
11961346
}
1347
+ fossil_free(zVFileDef);
11971348
return 1;
11981349
}
11991350
12001351
/*
12011352
** Locate the root directory of the local repository tree. The root
@@ -2648,11 +2799,11 @@
26482799
*/
26492800
const Setting *db_find_setting(const char *zName, int allowPrefix){
26502801
int lwr, mid, upr, c;
26512802
int n = (int)strlen(zName) + !allowPrefix;
26522803
lwr = 0;
2653
- upr = ArraySize(aSetting)-2;
2804
+ upr = count(aSetting)-2;
26542805
while( upr>=lwr ){
26552806
mid = (upr+lwr)/2;
26562807
c = fossil_strncmp(zName, aSetting[mid].name, n);
26572808
if( c<0 ){
26582809
upr = mid - 1;
26592810
--- 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 @@
377377
/* Compute the hash table used to locate matching sections in the
378378
** source file.
379379
*/
380380
nHash = lenSrc/NHASH;
381381
collide = fossil_malloc( nHash*2*sizeof(int) );
382
+ memset(collide, -1, nHash*2*sizeof(int));
382383
landmark = &collide[nHash];
383
- memset(landmark, -1, nHash*sizeof(int));
384
- memset(collide, -1, nHash*sizeof(int));
385384
for(i=0; i<lenSrc-NHASH; i+=NHASH){
386385
int hv = hash_once(&zSrc[i]) % nHash;
387386
collide[i/NHASH] = landmark[hv];
388387
landmark[hv] = i/NHASH;
389388
}
390389
--- 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 @@
5454
Blob orig, target, delta;
5555
if( g.argc!=5 ){
5656
usage("ORIGIN TARGET DELTA");
5757
}
5858
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]);
6060
}
6161
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]);
6363
}
6464
blob_delta_create(&orig, &target, &delta);
6565
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]);
6767
}
6868
blob_reset(&orig);
6969
blob_reset(&target);
7070
blob_reset(&delta);
7171
}
@@ -85,14 +85,14 @@
8585
int sz1, sz2, sz3;
8686
if( g.argc!=4 ){
8787
usage("ORIGIN TARGET");
8888
}
8989
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]);
9191
}
9292
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]);
9494
}
9595
blob_delta_create(&orig, &target, &delta);
9696
delta_analyze(blob_buffer(&delta), blob_size(&delta), &nCopy, &nInsert);
9797
sz1 = blob_size(&orig);
9898
sz2 = blob_size(&target);
@@ -153,18 +153,18 @@
153153
Blob orig, target, delta;
154154
if( g.argc!=5 ){
155155
usage("ORIGIN DELTA TARGET");
156156
}
157157
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]);
159159
}
160160
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]);
162162
}
163163
blob_delta_apply(&orig, &delta, &target);
164164
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]);
166166
}
167167
blob_reset(&orig);
168168
blob_reset(&target);
169169
blob_reset(&delta);
170170
}
171171
--- 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
--- src/descendants.c
+++ src/descendants.c
@@ -455,17 +455,17 @@
455455
456456
login_check_credentials();
457457
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
458458
459459
if( !showAll ){
460
- style_submenu_element("All", "All", "leaves?all");
460
+ style_submenu_element("All", "leaves?all");
461461
}
462462
if( !showClosed ){
463
- style_submenu_element("Closed", "Closed", "leaves?closed");
463
+ style_submenu_element("Closed", "leaves?closed");
464464
}
465465
if( showClosed || showAll ){
466
- style_submenu_element("Open", "Open", "leaves");
466
+ style_submenu_element("Open", "leaves");
467467
}
468468
style_header("Leaves");
469469
login_anonymous_available();
470470
#if 0
471471
style_sidebox_begin("Nomenclature:", "33%");
472472
--- 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 @@
115115
int nFrom; /* Number of lines in aFrom[] */
116116
DLine *aTo; /* File on right side of the diff */
117117
int nTo; /* Number of lines in aTo[] */
118118
int (*same_fn)(const DLine*,const DLine*); /* comparison function */
119119
};
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
+}
120144
121145
/*
122146
** Return an array of DLine objects containing a pointer to the
123147
** start of each line and a hash of that line. The lower
124148
** bits of the hash store the length of each line.
@@ -140,32 +164,26 @@
140164
u64 diffFlags
141165
){
142166
int nLine, i, k, nn, s, x;
143167
unsigned int h, h2;
144168
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' );
157175
a = fossil_malloc( sizeof(a[0])*nLine );
158176
memset(a, 0, sizeof(a[0])*nLine);
159177
if( nLine==0 ){
160178
*pnLine = 0;
161179
return a;
162180
}
163181
i = 0;
164182
do{
165183
zNL = strchr(z,'\n');
166
- if( zNL==0 ) zNL = z+strlen(z);
184
+ if( zNL==0 ) zNL = z+n;
167185
nn = (int)(zNL - z);
168186
if( nn>LENGTH_MASK ){
169187
fossil_free(a);
170188
return 0;
171189
}
@@ -181,14 +199,15 @@
181199
}
182200
if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){
183201
int numws = 0;
184202
while( s<k && fossil_isspace(z[s]) ){ s++; }
185203
for(h=0, x=s; x<k; x++){
186
- if( fossil_isspace(z[x]) ){
204
+ char c = z[x];
205
+ if( fossil_isspace(c) ){
187206
++numws;
188207
}else{
189
- h += z[x];
208
+ h += c;
190209
h *= 0x9e3779b1;
191210
}
192211
}
193212
k -= numws;
194213
}else{
@@ -200,13 +219,13 @@
200219
a[i].indent = s;
201220
a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s);
202221
h2 = h % nLine;
203222
a[i].iNext = a[h2].iHash;
204223
a[h2].iHash = i+1;
205
- z += nn+1;
224
+ z += nn+1; n -= nn+1;
206225
i++;
207
- }while( zNL[0] && zNL[1] );
226
+ }while( zNL[0]!='\0' && zNL[1]!='\0' );
208227
assert( i==nLine );
209228
210229
/* Return results */
211230
*pnLine = nLine;
212231
return a;
@@ -1049,11 +1068,11 @@
10491068
if( nLeft>mnLen ) memset(aM+mnLen, 1, nLeft-mnLen);
10501069
if( nRight>mnLen ) memset(aM+mnLen, 2, nRight-mnLen);
10511070
return aM;
10521071
}
10531072
1054
- if( nRight < (sizeof(aBuf)/sizeof(aBuf[0]))-1 ){
1073
+ if( nRight < count(aBuf)-1 ){
10551074
pToFree = 0;
10561075
a = aBuf;
10571076
}else{
10581077
a = pToFree = fossil_malloc( sizeof(a[0])*(nRight+1) );
10591078
}
@@ -2326,34 +2345,32 @@
23262345
url_add_parameter(&url, "limit", sqlite3_mprintf("%d", iLimit));
23272346
}
23282347
url_add_parameter(&url, "log", showLog ? "1" : "0");
23292348
if( ignoreWs ){
23302349
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));
23332352
}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));
23362355
}
23372356
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));
23402358
}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));
23432360
}
23442361
if( ann.bLimit ){
23452362
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));
23482365
z1 = sqlite3_mprintf("%d Ancestors", iLimit+20);
23492366
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));
23512368
}
23522369
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));
23552372
}
23562373
if( skin_detail_boolean("white-foreground") ){
23572374
clr1 = 0xa04040;
23582375
clr2 = 0x4059a0;
23592376
}else{
23602377
--- 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 @@
412412
" ORDER BY pathname /*scan*/",
413413
vid
414414
);
415415
}
416416
db_prepare(&q, "%s", blob_sql_text(&sql));
417
+ blob_reset(&sql);
417418
while( db_step(&q)==SQLITE_ROW ){
418419
const char *zPathname = db_column_text(&q,0);
419420
int isDeleted = db_column_int(&q, 1);
420421
int isChnged = db_column_int(&q,2);
421422
int isNew = db_column_int(&q,3);
@@ -797,10 +798,11 @@
797798
** Options:
798799
** --binary PATTERN Treat files that match the glob PATTERN as binary
799800
** --branch BRANCH Show diff of all changes on BRANCH
800801
** --brief Show filenames only
801802
** --checkin VERSION Show diff of all changes in VERSION
803
+** --command PROG External diff program - overrides "diff-command"
802804
** --context|-c N Use N lines of context
803805
** --diff-binary BOOL Include binary files when using external commands
804806
** --exec-abs-paths Force absolute path names with external commands.
805807
** --exec-rel-paths Force relative path names with external commands.
806808
** --from|-r VERSION Select VERSION as source for the diff
@@ -868,11 +870,12 @@
868870
fossil_fatal("must use --from if --to is present");
869871
}else{
870872
db_find_and_open_repository(0, 0);
871873
}
872874
if( !isInternDiff ){
873
- zDiffCmd = diff_command_external(isGDiff);
875
+ zDiffCmd = find_option("command", 0, 1);
876
+ if( zDiffCmd==0 ) zDiffCmd = diff_command_external(isGDiff);
874877
}
875878
zBinGlob = diff_get_binary_glob();
876879
fIncludeBinary = diff_include_binary_files();
877880
determine_exec_relative_option(1);
878881
verify_all_options();
879882
--- 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 @@
6969
** The page_index.h file is generated by the mkindex program which scans all
7070
** source code files looking for header comments on the functions that
7171
** implement command and webpages.
7272
*/
7373
#include "page_index.h"
74
-#define MX_COMMAND (sizeof(aCommand)/sizeof(aCommand[0]))
74
+#define MX_COMMAND count(aCommand)
7575
7676
/*
7777
** Given a command or webpage name in zName, find the corresponding CmdOrPage
7878
** object and return a pointer to that object in *ppCmd.
7979
**
@@ -233,16 +233,17 @@
233233
*/
234234
void help_page(void){
235235
const char *zCmd = P("cmd");
236236
237237
if( zCmd==0 ) zCmd = P("name");
238
- style_header("Command-line Help");
239
- if( zCmd ){
238
+ if( zCmd && *zCmd ){
240239
int rc;
241240
const CmdOrPage *pCmd = 0;
242241
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);
244245
if( *zCmd=='/' ){
245246
/* Some of the webpages require query parameters in order to work.
246247
** @ <h1>The "<a href='%R%s(zCmd)'>%s(zCmd)</a>" page:</h1> */
247248
@ <h1>The "%s(zCmd)" page:</h1>
248249
}else{
@@ -262,26 +263,30 @@
262263
@ </blockquote>
263264
}
264265
}
265266
}else{
266267
int i, j, n;
268
+
269
+ style_header("Help");
267270
268271
@ <h1>Available commands:</h1>
269272
@ <table border="0"><tr>
270273
for(i=j=0; i<MX_COMMAND; i++){
271274
const char *z = aCommand[i].zName;
272275
if( '/'==*z || strncmp(z,"test",4)==0 ) continue;
273276
j++;
274277
}
275
- n = (j+6)/7;
278
+ n = (j+5)/6;
276279
for(i=j=0; i<MX_COMMAND; i++){
277280
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>":"";
278283
if( '/'==*z || strncmp(z,"test",4)==0 ) continue;
279284
if( j==0 ){
280285
@ <td valign="top"><ul>
281286
}
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>
283288
j++;
284289
if( j>=n ){
285290
@ </ul></td>
286291
j = 0;
287292
}
@@ -360,11 +365,11 @@
360365
**
361366
** Show all help text on a single page. Useful for proof-reading.
362367
*/
363368
void test_all_help_page(void){
364369
int i;
365
- style_header("Testpage: All Help Text");
370
+ style_header("All Help Text");
366371
for(i=0; i<MX_COMMAND; i++){
367372
if( memcmp(aCommand[i].zName, "test", 4)==0 ) continue;
368373
@ <h2>%s(aCommand[i].zName):</h2>
369374
@ <blockquote>
370375
help_to_html(aCommand[i].zHelp, cgi_output_blob());
@@ -402,11 +407,11 @@
402407
*/
403408
void cmd_test_webpage_list(void){
404409
int i, nCmd;
405410
const char *aCmd[MX_COMMAND];
406411
for(i=nCmd=0; i<MX_COMMAND; i++){
407
- if(0x08 & aCommand[i].eCmdFlags){
412
+ if(CMDFLAG_WEBPAGE & aCommand[i].eCmdFlags){
408413
aCmd[nCmd++] = aCommand[i].zName;
409414
}
410415
}
411416
assert(nCmd && "page list is empty?");
412417
multi_column_list(aCmd, nCmd);
413418
--- 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 @@
5454
if( !looks_like_binary(pBlob) ) {
5555
return 0; /* Plain text */
5656
}
5757
x = (const unsigned char*)blob_buffer(pBlob);
5858
n = blob_size(pBlob);
59
- for(i=0; i<ArraySize(aMime); i++){
59
+ for(i=0; i<count(aMime); i++){
6060
if( n>=aMime[i].size && memcmp(x, aMime[i].zPrefix, aMime[i].size)==0 ){
6161
return aMime[i].zMimetype;
6262
}
6363
}
6464
return "unknown/unknown";
@@ -293,11 +293,11 @@
293293
** Verify that all entries in the aMime[] table are in sorted order.
294294
** Abort with a fatal error if any is out-of-order.
295295
*/
296296
static void mimetype_verify(void){
297297
int i;
298
- for(i=1; i<ArraySize(aMime); i++){
298
+ for(i=1; i<count(aMime); i++){
299299
if( fossil_strcmp(aMime[i-1].zSuffix,aMime[i].zSuffix)>=0 ){
300300
fossil_fatal("mimetypes out of sequence: %s before %s",
301301
aMime[i-1].zSuffix, aMime[i].zSuffix);
302302
}
303303
}
@@ -331,11 +331,11 @@
331331
len = strlen(z);
332332
if( len<sizeof(zSuffix)-1 ){
333333
sqlite3_snprintf(sizeof(zSuffix), zSuffix, "%s", z);
334334
for(i=0; zSuffix[i]; i++) zSuffix[i] = fossil_tolower(zSuffix[i]);
335335
first = 0;
336
- last = ArraySize(aMime) - 1;
336
+ last = count(aMime) - 1;
337337
while( first<=last ){
338338
int c;
339339
i = (first+last)/2;
340340
c = fossil_strcmp(zSuffix, aMime[i].zSuffix);
341341
if( c==0 ) return aMime[i].zMimetype;
@@ -384,11 +384,11 @@
384384
@ <table id='mimeTable' border=1 cellpadding=0 class='mimetypetable'>
385385
@ <thead>
386386
@ <tr><th>Suffix<th>Mimetype
387387
@ </thead>
388388
@ <tbody>
389
- for(i=0; i<ArraySize(aMime); i++){
389
+ for(i=0; i<count(aMime); i++){
390390
@ <tr><td>%h(aMime[i].zSuffix)<td>%h(aMime[i].zMimetype)</tr>
391391
}
392392
@ </tbody></table>
393393
output_table_sorting_javascript("mimeTable","tt",1);
394394
style_footer();
@@ -593,11 +593,11 @@
593593
login_check_credentials();
594594
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
595595
blob_init(&title, 0, 0);
596596
zDfltTitle = isUV ? "" : "Documentation";
597597
db_begin_transaction();
598
- while( rid==0 && (++nMiss)<=ArraySize(azSuffix) ){
598
+ while( rid==0 && (++nMiss)<=count(azSuffix) ){
599599
zName = P("name");
600600
if( isUV ){
601601
if( zName==0 ) zName = "index.wiki";
602602
i = 0;
603603
}else{
@@ -606,14 +606,14 @@
606606
zCheckin = mprintf("%.*s", i, zName);
607607
if( fossil_strcmp(zCheckin,"ckout")==0 && g.localOpen==0 ){
608608
zCheckin = "tip";
609609
}
610610
}
611
- if( nMiss==ArraySize(azSuffix) ){
611
+ if( nMiss==count(azSuffix) ){
612612
zName = "404.md";
613613
}else if( zName[i]==0 ){
614
- assert( nMiss>=0 && nMiss<ArraySize(azSuffix) );
614
+ assert( nMiss>=0 && nMiss<count(azSuffix) );
615615
zName = azSuffix[nMiss];
616616
}else if( !isUV ){
617617
zName += i;
618618
}
619619
while( zName[0]=='/' ){ zName++; }
@@ -623,11 +623,11 @@
623623
g.zPath = mprintf("%s/%s/%s", g.zPath, zCheckin, zName);
624624
}
625625
if( nMiss==0 ) zOrigName = zName;
626626
if( !file_is_simple_pathname(zName, 1) ){
627627
if( sqlite3_strglob("*/", zName)==0 ){
628
- assert( nMiss>=0 && nMiss<ArraySize(azSuffix) );
628
+ assert( nMiss>=0 && nMiss<count(azSuffix) );
629629
zName = mprintf("%s%s", zName, azSuffix[nMiss]);
630630
if( !file_is_simple_pathname(zName, 1) ){
631631
goto doc_not_found;
632632
}
633633
}else{
@@ -686,11 +686,11 @@
686686
Blob tail = BLOB_INITIALIZER;
687687
markdown_to_html(&filebody, &title, &tail);
688688
if( blob_size(&title)>0 ){
689689
style_header("%s", blob_str(&title));
690690
}else{
691
- style_header("%s", nMiss>=ArraySize(azSuffix)?
691
+ style_header("%s", nMiss>=count(azSuffix)?
692692
"Not Found" : zDfltTitle);
693693
}
694694
convert_href_and_output(&tail);
695695
style_footer();
696696
}else if( fossil_strcmp(zMime, "text/plain")==0 ){
@@ -719,11 +719,11 @@
719719
#endif
720720
}else{
721721
cgi_set_content_type(zMime);
722722
cgi_set_content(&filebody);
723723
}
724
- if( nMiss>=ArraySize(azSuffix) ) cgi_set_status(404, "Not Found");
724
+ if( nMiss>=count(azSuffix) ) cgi_set_status(404, "Not Found");
725725
db_end_transaction(0);
726726
return;
727727
728728
/* Jump here when unable to locate the document */
729729
doc_not_found:
730730
--- 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 @@
152152
blob_appendf(&title, "Tech-note %S", zId);
153153
tail = fullbody;
154154
}
155155
style_header("%s", blob_str(&title));
156156
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);
158158
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);
162161
}
163162
}
164163
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);
166165
if( g.perm.Hyperlink ){
167166
if( verboseFlag ){
168
- style_submenu_element("Plain", 0,
167
+ style_submenu_element("Plain",
169168
"%R/technote?name=%!S&aid=%s&mimetype=text/plain",
170169
zId, zUuid);
171170
if( nextRid ){
172171
char *zNext;
173172
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",
175174
zId, zNext);
176175
free(zNext);
177176
}
178177
if( prevRid ){
179178
char *zPrev;
180179
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",
182181
zId, zPrev);
183182
free(zPrev);
184183
}
185184
}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",
187186
zId, zUuid);
188187
}
189188
}
190189
191190
if( verboseFlag && g.perm.Hyperlink ){
192191
--- 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 @@
132132
133133
/*
134134
** create_mark()
135135
** Create a new (mark,rid,uuid) entry for the given rid in the 'xmark' table,
136136
** 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.
137141
** This function returns -1 in the case where 'rid' does not exist, otherwise
138142
** it returns 0.
139143
** mark->name is dynamically allocated and is owned by the caller upon return.
140144
*/
141
-int create_mark(int rid, struct mark_t *mark){
145
+int create_mark(int rid, struct mark_t *mark, unsigned int *unused_mark){
142146
char sid[13];
143147
char *zUuid = rid_to_uuid(rid);
144
- if(!zUuid){
148
+ if( !zUuid ){
145149
fossil_trace("Undefined rid=%d\n", rid);
146150
return -1;
147151
}
148152
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;
150155
mark->name = fossil_strdup(sid);
151156
sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", zUuid);
152157
free(zUuid);
153158
insert_commit_xref(mark->rid, mark->name, mark->uuid);
154159
return 0;
@@ -156,19 +161,22 @@
156161
157162
/*
158163
** mark_name_from_rid()
159164
** Find the mark associated with the given rid. Mark names always start
160165
** 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.
164172
*/
165
-char * mark_name_from_rid(int rid){
173
+char * mark_name_from_rid(int rid, unsigned int *unused_mark){
166174
char *zMark = db_text(0, "SELECT tname FROM xmark WHERE trid=%d", rid);
167
- if(zMark==NULL){
175
+ if( zMark==NULL ){
168176
struct mark_t mark;
169
- if(create_mark(rid, &mark)==0){
177
+ if( create_mark(rid, &mark, unused_mark)==0 ){
170178
zMark = mark.name;
171179
}else{
172180
return NULL;
173181
}
174182
}
@@ -185,43 +193,52 @@
185193
** database. Otherwise, 0 is returned.
186194
** mark->name is dynamically allocated, and owned by the caller.
187195
*/
188196
int parse_mark(char *line, struct mark_t *mark){
189197
char *cur_tok;
198
+ char type_;
190199
cur_tok = strtok(line, " \t");
191
- if(!cur_tok||strlen(cur_tok)<2){
200
+ if( !cur_tok || strlen(cur_tok)<2 ){
192201
return -1;
193202
}
194203
mark->rid = atoi(&cur_tok[1]);
195
- if(cur_tok[0]!='c'){
204
+ type_ = cur_tok[0];
205
+ if( type_!='c' && type_!='b' ){
196206
/* This is probably a blob mark */
197207
mark->name = NULL;
198208
return 0;
199209
}
200210
201211
cur_tok = strtok(NULL, " \t");
202
- if(!cur_tok){
212
+ if( !cur_tok ){
203213
/* This mark was generated by an older version of Fossil and doesn't
204214
** include the mark name and uuid. create_mark() will name the new mark
205215
** exactly as it was when exported to git, so that we should have a
206216
** 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);
208225
}else{
209226
mark->name = fossil_strdup(cur_tok);
210227
}
211228
212229
cur_tok = strtok(NULL, "\n");
213
- if(!cur_tok||strlen(cur_tok)!=40){
230
+ if( !cur_tok || strlen(cur_tok)!=40 ){
214231
free(mark->name);
215232
fossil_trace("Invalid SHA-1 in marks file: %s\n", cur_tok);
216233
return -1;
217234
}else{
218235
sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", cur_tok);
219236
}
220237
221238
/* 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 ){
223240
free(mark->name);
224241
fossil_trace("Non-existent SHA-1 in marks file: %s\n", mark->uuid);
225242
return -1;
226243
}
227244
@@ -233,40 +250,66 @@
233250
/*
234251
** import_marks()
235252
** Import the marks specified in file 'f' into the 'xmark' table.
236253
** If 'blobs' is non-null, insert all blob marks into it.
237254
** 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.
238258
** Each line in the file must be at most 100 characters in length. This
239259
** seems like a reasonable maximum for a 40-character uuid, and 1-13
240260
** character rid.
241261
** The function returns -1 if any of the lines in file 'f' are malformed,
242262
** or the rid/uuid information doesn't match what is in the repository
243263
** database. Otherwise, 0 is returned.
244264
*/
245
-int import_marks(FILE* f, Bag *blobs, Bag *vers){
265
+int import_marks(FILE* f, Bag *blobs, Bag *vers, unsigned int *unused_mark){
246266
char line[101];
247267
while(fgets(line, sizeof(line), f)){
248268
struct mark_t mark;
249
- if(strlen(line)==100&&line[99]!='\n'){
269
+ if( strlen(line)==100 && line[99]!='\n' ){
250270
/* line too long */
251271
return -1;
252272
}
253273
if( parse_mark(line, &mark)<0 ){
254274
return -1;
255275
}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 ){
259277
bag_insert(blobs, mark.rid);
260278
}
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
+ }
263289
}
264290
free(mark.name);
265291
}
266292
return 0;
267293
}
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
+}
268311
269312
/*
270313
** If 'blobs' is non-null, it must point to a Bag of blob rids to be
271314
** written to disk. Blob rids are written as 'b<rid>'.
272315
** If 'vers' is non-null, it must point to a Bag of commit rids to be
@@ -275,32 +318,24 @@
275318
** This function does not fail, but may produce errors if a uuid cannot
276319
** be found for an rid in 'vers'.
277320
*/
278321
void export_marks(FILE* f, Bag *blobs, Bag *vers){
279322
int rid;
323
+
280324
if( blobs!=NULL ){
281325
rid = bag_first(blobs);
282
- if(rid!=0){
326
+ if( rid!=0 ){
283327
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 );
286330
}
287331
}
288332
if( vers!=NULL ){
289333
rid = bag_first(vers);
290334
if( rid!=0 ){
291335
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');
302337
}while( (rid = bag_next(vers, rid))!=0 );
303338
}
304339
}
305340
}
306341
@@ -336,10 +371,11 @@
336371
*/
337372
void export_cmd(void){
338373
Stmt q, q2, q3;
339374
int i;
340375
Bag blobs, vers;
376
+ unsigned int unused_mark = 1;
341377
const char *markfile_in;
342378
const char *markfile_out;
343379
344380
bag_init(&blobs);
345381
bag_init(&vers);
@@ -362,25 +398,25 @@
362398
363399
f = fossil_fopen(markfile_in, "r");
364400
if( f==0 ){
365401
fossil_fatal("cannot open %s for reading", markfile_in);
366402
}
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);
369405
}
370406
db_prepare(&qb, "INSERT OR IGNORE INTO oldblob VALUES (:rid)");
371407
db_prepare(&qc, "INSERT OR IGNORE INTO oldcommit VALUES (:rid)");
372408
rid = bag_first(&blobs);
373
- if(rid!=0){
409
+ if( rid!=0 ){
374410
do{
375411
db_bind_int(&qb, ":rid", rid);
376412
db_step(&qb);
377413
db_reset(&qb);
378414
}while((rid = bag_next(&blobs, rid))!=0);
379415
}
380416
rid = bag_first(&vers);
381
- if(rid!=0){
417
+ if( rid!=0 ){
382418
do{
383419
db_bind_int(&qc, ":rid", rid);
384420
db_step(&qc);
385421
db_reset(&qc);
386422
}while((rid = bag_next(&vers, rid))!=0);
@@ -416,15 +452,18 @@
416452
while( db_step(&q)==SQLITE_ROW ){
417453
int rid = db_column_int(&q, 0);
418454
Blob content;
419455
420456
while( !bag_find(&blobs, rid) ){
457
+ char *zMark;
421458
content_get(rid, &content);
422459
db_bind_int(&q2, ":rid", rid);
423460
db_step(&q2);
424461
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);
426465
bag_insert(&blobs, rid);
427466
fwrite(blob_buffer(&content), 1, blob_size(&content), stdout);
428467
printf("\n");
429468
blob_reset(&content);
430469
@@ -470,11 +509,11 @@
470509
if( zBranch==0 ) zBranch = "trunk";
471510
zBr = mprintf("%s", zBranch);
472511
for(i=0; zBr[i]; i++){
473512
if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_';
474513
}
475
- zMark = mark_name_from_rid(ckinId);
514
+ zMark = mark_name_from_rid(ckinId, &unused_mark);
476515
printf("commit refs/heads/%s\nmark %s\n", zBr, zMark);
477516
free(zMark);
478517
free(zBr);
479518
printf("committer");
480519
print_person(zUser);
@@ -487,21 +526,21 @@
487526
" AND pid IN (SELECT objid FROM event)",
488527
ckinId
489528
);
490529
if( db_step(&q3) == SQLITE_ROW ){
491530
int pid = db_column_int(&q3, 0);
492
- zMark = mark_name_from_rid(pid);
531
+ zMark = mark_name_from_rid(pid, &unused_mark);
493532
printf("from %s\n", zMark);
494533
free(zMark);
495534
db_prepare(&q4,
496535
"SELECT pid FROM plink"
497536
" WHERE cid=%d AND NOT isprim"
498537
" AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)"
499538
" ORDER BY pid",
500539
ckinId);
501540
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);
503542
printf("merge %s\n", zMark);
504543
free(zMark);
505544
}
506545
db_finalize(&q4);
507546
}else{
@@ -516,20 +555,22 @@
516555
);
517556
while( db_step(&q4)==SQLITE_ROW ){
518557
const char *zName = db_column_text(&q4,0);
519558
int zNew = db_column_int(&q4,1);
520559
int mPerm = db_column_int(&q4,2);
521
- if( zNew==0)
560
+ if( zNew==0 ){
522561
printf("D %s\n", zName);
523
- else if( bag_find(&blobs, zNew) ) {
562
+ }else if( bag_find(&blobs, zNew) ){
524563
const char *zPerm;
564
+ zMark = mark_name_from_rid(zNew, &unused_mark);
525565
switch( mPerm ){
526566
case PERM_LNK: zPerm = "120000"; break;
527567
case PERM_EXE: zPerm = "100755"; break;
528568
default: zPerm = "100644"; break;
529569
}
530
- printf("M %s :%d %s\n", zPerm, BLOBMARK(zNew), zName);
570
+ printf("M %s %s %s\n", zPerm, zMark, zName);
571
+ free(zMark);
531572
}
532573
}
533574
db_finalize(&q4);
534575
db_finalize(&q3);
535576
printf("\n");
@@ -547,20 +588,22 @@
547588
);
548589
while( db_step(&q)==SQLITE_ROW ){
549590
const char *zTagname = db_column_text(&q, 0);
550591
char *zEncoded = 0;
551592
int rid = db_column_int(&q, 1);
593
+ char *zMark = mark_name_from_rid(rid, &unused_mark);
552594
const char *zSecSince1970 = db_column_text(&q, 2);
553595
int i;
554596
if( rid==0 || !bag_find(&vers, rid) ) continue;
555597
zTagname += 4;
556598
zEncoded = mprintf("%s", zTagname);
557599
for(i=0; zEncoded[i]; i++){
558600
if( !fossil_isalnum(zEncoded[i]) ) zEncoded[i] = '_';
559601
}
560602
printf("tag %s\n", zEncoded);
561
- printf("from :%d\n", COMMITMARK(rid));
603
+ printf("from %s\n", zMark);
604
+ free(zMark);
562605
printf("tagger <tagger> %s +0000\n", zSecSince1970);
563606
printf("data 0\n");
564607
fossil_free(zEncoded);
565608
}
566609
db_finalize(&q);
@@ -570,12 +613,12 @@
570613
f = fossil_fopen(markfile_out, "w");
571614
if( f == 0 ){
572615
fossil_fatal("cannot open %s for writing", markfile_out);
573616
}
574617
export_marks(f, &blobs, &vers);
575
- if( ferror(f)!=0 || fclose(f)!=0 ) {
618
+ if( ferror(f)!=0 || fclose(f)!=0 ){
576619
fossil_fatal("error while writing %s", markfile_out);
577620
}
578621
}
579622
bag_clear(&blobs);
580623
bag_clear(&vers);
581624
}
582625
--- 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 @@
863863
#ifdef _WIN32
864864
win32_getcwd(zBuf, nBuf);
865865
#else
866866
if( getcwd(zBuf, nBuf-1)==0 ){
867867
if( errno==ERANGE ){
868
- fossil_fatal("pwd too big: max %d\n", nBuf-1);
868
+ fossil_fatal("pwd too big: max %d", nBuf-1);
869869
}else{
870870
fossil_fatal("cannot find current working directory; %s",
871871
strerror(errno));
872872
}
873873
}
@@ -1290,11 +1290,11 @@
12901290
azDirs[1] = fossil_getenv("TEMP");
12911291
azDirs[2] = fossil_getenv("TMP");
12921292
#endif
12931293
12941294
1295
- for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
1295
+ for(i=0; i<count(azDirs); i++){
12961296
if( azDirs[i]==0 ) continue;
12971297
if( !file_isdir(azDirs[i]) ) continue;
12981298
zDir = azDirs[i];
12991299
break;
13001300
}
@@ -1407,11 +1407,11 @@
14071407
const char *file_is_win_reserved(const char *zPath){
14081408
static const char *azRes[] = { "CON", "PRN", "AUX", "NUL", "COM", "LPT" };
14091409
static char zReturn[5];
14101410
int i;
14111411
while( zPath[0] ){
1412
- for(i=0; i<ArraySize(azRes); i++){
1412
+ for(i=0; i<count(azRes); i++){
14131413
if( sqlite3_strnicmp(zPath, azRes[i], 3)==0
14141414
&& ((i>=4 && fossil_isdigit(zPath[3])
14151415
&& (zPath[4]=='/' || zPath[4]=='.' || zPath[4]==0))
14161416
|| (i<4 && (zPath[3]=='/' || zPath[3]=='.' || zPath[3]==0)))
14171417
){
14181418
--- 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 @@
331331
@ No such file: %h(zFilename)
332332
style_footer();
333333
return;
334334
}
335335
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);
337337
}
338338
if( baseCheckin ){
339339
compute_direct_ancestors(baseCheckin);
340340
}
341341
url_add_parameter(&url, "name", zFilename);
@@ -454,11 +454,11 @@
454454
int aParent[GR_MAX_RAIL];
455455
456456
db_bind_int(&qparent, ":fid", frid);
457457
db_bind_int(&qparent, ":mid", fmid);
458458
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) ){
460460
aParent[nParent] = db_column_int(&qparent, 0);
461461
nParent++;
462462
}
463463
db_reset(&qparent);
464464
if( zBr==0 ) zBr = "trunk";
465465
--- 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 @@
2525
** It allows multiple commands to be issued without having to reenter the
2626
** crypto phasephrase for each command.
2727
*/
2828
#include "config.h"
2929
#include "fshell.h"
30
+#include "linenoise.h"
3031
#include <ctype.h>
3132
3233
#ifndef _WIN32
3334
#include <sys/types.h>
3435
#include <sys/wait.h>
@@ -55,16 +56,19 @@
5556
int mxArg = 0;
5657
int n, i;
5758
char **azArg = 0;
5859
int fDebug;
5960
pid_t childPid;
60
- char zLine[10000];
61
+ char *zLine = 0;
6162
fDebug = find_option("debug", 0, 0)!=0;
6263
db_find_and_open_repository(OPEN_ANY_SCHEMA|OPEN_OK_NOT_FOUND, 0);
6364
db_close(0);
6465
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
+
6670
/* Parse the line of input */
6771
n = (int)strlen(zLine);
6872
for(i=0, nArg=1; i<n; i++){
6973
while( fossil_isspace(zLine[i]) ){ i++; }
7074
if( i>=n ) break;
7175
--- 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 @@
2020
**
2121
** This module is a mostly a no-op unless compiled with -DFOSSIL_HAVE_FUSEFS.
2222
** The FOSSIL_HAVE_FUSEFS should be omitted on systems that lack support for
2323
** the Fuse Filesystem, of course.
2424
*/
25
+#ifdef FOSSIL_HAVE_FUSEFS
2526
#include "config.h"
2627
#include <stdio.h>
2728
#include <string.h>
2829
#include <errno.h>
2930
#include <fcntl.h>
3031
#include <stdlib.h>
3132
#include <unistd.h>
3233
#include <sys/types.h>
3334
#include "fusefs.h"
34
-#ifdef FOSSIL_HAVE_FUSEFS
3535
3636
#define FUSE_USE_VERSION 26
3737
#include <fuse.h>
3838
3939
/*
@@ -207,11 +207,12 @@
207207
filler(buf, ".", NULL, 0);
208208
filler(buf, "..", NULL, 0);
209209
manifest_file_rewind(fusefs.pMan);
210210
if( n==2 ){
211211
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;
213214
zPrev = pFile->zName;
214215
for(nPrev=0; zPrev[nPrev] && zPrev[nPrev]!='/'; nPrev++){}
215216
z = mprintf("%.*s", nPrev, zPrev);
216217
filler(buf, z, NULL, 0);
217218
fossil_free(z);
@@ -282,11 +283,10 @@
282283
static struct fuse_operations fusefs_methods = {
283284
.getattr = fusefs_getattr,
284285
.readdir = fusefs_readdir,
285286
.read = fusefs_read,
286287
};
287
-#endif /* FOSSIL_HAVE_FUSEFS */
288288
289289
/*
290290
** COMMAND: fusefs
291291
**
292292
** Usage: %fossil fusefs [--debug] DIRECTORY
@@ -314,13 +314,10 @@
314314
** After stopping the "fossil fusefs" command, it might also be necessary
315315
** to run "fusermount -u DIRECTORY" to reset the FuseFS before using it
316316
** again.
317317
*/
318318
void fusefs_cmd(void){
319
-#ifndef FOSSIL_HAVE_FUSEFS
320
- fossil_fatal("this build of fossil does not support the fuse filesystem");
321
-#else
322319
char *zMountPoint;
323320
char *azNewArgv[5];
324321
int doDebug = find_option("debug","d",0)!=0;
325322
326323
db_find_and_open_repository(0,0);
@@ -338,7 +335,7 @@
338335
azNewArgv[4] = 0;
339336
g.localOpen = 0; /* Prevent tags like "current" and "prev" */
340337
fuse_main(4, azNewArgv, &fusefs_methods, NULL);
341338
fusefs_reset();
342339
fusefs_clear_path();
343
-#endif
344340
}
341
+#endif /* FOSSIL_HAVE_FUSEFS */
345342
--- 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 @@
258258
int iRail = pBottom->iRail;
259259
GraphRow *pCurrent;
260260
GraphRow *pPrior;
261261
u64 mask = ((u64)1)<<iRail;
262262
263
- pBottom->iRail = iRail;
264263
pBottom->railInUse |= mask;
265264
pPrior = pBottom;
266265
for(pCurrent=pBottom->pChild; pCurrent; pCurrent=pCurrent->pChild){
267266
assert( pPrior->idx > pCurrent->idx );
268267
assert( pCurrent->iRail<0 );
@@ -344,14 +343,16 @@
344343
/*
345344
** Compute the complete graph
346345
*/
347346
void graph_finish(GraphContext *p, int omitDescenders){
348347
GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent;
349
- int i;
348
+ int i, j;
350349
u64 mask;
351350
int hasDup = 0; /* True if one or more isDup entries */
352351
const char *zTrunk;
352
+ int railRid[GR_MAX_RAIL]; /* Maps rails to rids for lines
353
+ that enter from bottom of screen */
353354
354355
if( p==0 || p->pFirst==0 || p->nErr ) return;
355356
p->nErr = 1; /* Assume an error until proven otherwise */
356357
357358
/* Initialize all rows */
@@ -366,10 +367,11 @@
366367
pDup->isDup = 1;
367368
}
368369
hashInsert(p, pRow, 1);
369370
}
370371
p->mxRail = -1;
372
+ memset(railRid, 0, sizeof(railRid));
371373
372374
/* Purge merge-parents that are out-of-graph if descenders are not
373375
** drawn.
374376
**
375377
** Each node has one primary parent and zero or more "merge" parents.
@@ -458,10 +460,13 @@
458460
}
459461
if( p->mxRail>=GR_MAX_RAIL ) return;
460462
mask = BIT(pRow->iRail);
461463
if( !omitDescenders ){
462464
pRow->bDescender = pRow->nParent>0;
465
+ if( pRow->bDescender ){
466
+ railRid[pRow->iRail] = pRow->aParent[0];
467
+ }
463468
for(pLoop=pRow; pLoop; pLoop=pLoop->pNext){
464469
pLoop->railInUse |= mask;
465470
}
466471
}
467472
assignChildrenToRail(pRow);
@@ -536,12 +541,22 @@
536541
for(i=1; i<pRow->nParent; i++){
537542
int parentRid = pRow->aParent[i];
538543
pDesc = hashFind(p, parentRid);
539544
if( pDesc==0 ){
540545
/* 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
+ }
543558
mask = BIT(iMrail);
544559
pRow->mergeIn[iMrail] = 1;
545560
pRow->mergeDown |= mask;
546561
for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){
547562
pLoop->railInUse |= mask;
548563
--- 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
--- src/http_socket.c
+++ src/http_socket.c
@@ -23,20 +23,19 @@
2323
** of the server is held in global variables that are set by url_parse().
2424
**
2525
** Low-level sockets are abstracted out into this module because they
2626
** are handled different on Unix and windows.
2727
*/
28
-
28
+#if defined(_WIN32)
29
+# define _WIN32_WINNT 0x501
30
+#endif
2931
#ifndef __EXTENSIONS__
3032
# define __EXTENSIONS__ 1 /* IPv6 won't compile on Solaris without this */
3133
#endif
3234
#include "config.h"
3335
#include "http_socket.h"
3436
#if defined(_WIN32)
35
-# if !defined(_WIN32_WINNT)
36
-# define _WIN32_WINNT 0x0501
37
-# endif
3837
# include <winsock2.h>
3938
# include <ws2tcpip.h>
4039
#else
4140
# include <netinet/in.h>
4241
# include <arpa/inet.h>
4342
--- 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 @@
16121612
{"rename-branch", &gimport.zBranchPre, "", &gimport.zBranchSuf, "", 3},
16131613
{"rename-tag" , &gimport.zTagPre , "", &gimport.zTagSuf , "", 3},
16141614
{"rename-rev" , &gsvn.zRevPre, "svn-rev-", &gsvn.zRevSuf , "", 2},
16151615
}, *renOpt = renOpts;
16161616
int i;
1617
- for( i = 0; i < sizeof(renOpts) / sizeof(*renOpts); ++i, ++renOpt ){
1617
+ for( i = 0; i < count(renOpts); ++i, ++renOpt ){
16181618
if( 1 << svnFlag & renOpt->format ){
16191619
const char *zArgument = find_option(renOpt->zOpt, 0, 1);
16201620
if( zArgument ){
16211621
const char *sep = strchr(zArgument, '%');
16221622
if( !sep ){
@@ -1761,21 +1761,22 @@
17611761
** times but only the last tag should be used. And we do not know which
17621762
** occurrence of the tag is the last until the import finishes.
17631763
*/
17641764
db_multi_exec(
17651765
"CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT);"
1766
+ "CREATE INDEX temp.i_xmark ON xmark(trid);"
17661767
"CREATE TEMP TABLE xbranch(tname TEXT UNIQUE, brnm TEXT);"
17671768
"CREATE TEMP TABLE xtag(tname TEXT UNIQUE, tcontent TEXT);"
17681769
);
17691770
17701771
if( markfile_in ){
17711772
FILE *f = fossil_fopen(markfile_in, "r");
17721773
if( !f ){
1773
- fossil_fatal("cannot open %s for reading\n", markfile_in);
1774
+ fossil_fatal("cannot open %s for reading", markfile_in);
17741775
}
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);
17771778
}
17781779
fclose(f);
17791780
}
17801781
17811782
manifest_crosslink_begin();
@@ -1795,21 +1796,21 @@
17951796
db_prepare(&q_marks, "SELECT DISTINCT trid FROM xmark");
17961797
while( db_step(&q_marks)==SQLITE_ROW ){
17971798
rid = db_column_int(&q_marks, 0);
17981799
if( db_int(0, "SELECT count(objid) FROM event"
17991800
" 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
+ */
18031804
}else{
18041805
bag_insert(&vers, rid);
18051806
}
18061807
}
18071808
db_finalize(&q_marks);
18081809
f = fossil_fopen(markfile_out, "w");
18091810
if( !f ){
1810
- fossil_fatal("cannot open %s for writing\n", markfile_out);
1811
+ fossil_fatal("cannot open %s for writing", markfile_out);
18111812
}
18121813
export_marks(f, &blobs, &vers);
18131814
fclose(f);
18141815
bag_clear(&blobs);
18151816
bag_clear(&vers);
18161817
--- 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 @@
231231
db_int(-1, "SELECT count(*) FROM event WHERE type='ci' /*scan*/"));
232232
}else{
233233
int rid;
234234
rid = name_to_rid(g.argv[2]);
235235
if( rid==0 ){
236
- fossil_fatal("no such object: %s\n", g.argv[2]);
236
+ fossil_fatal("no such object: %s", g.argv[2]);
237237
}
238238
show_common_info(rid, "uuid:", 1, 1);
239239
}
240240
}
241241
@@ -826,15 +826,13 @@
826826
}
827827
}
828828
style_header("Update of \"%h\"", pWiki->zWikiTitle);
829829
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
830830
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);
836834
login_anonymous_available();
837835
@ <div class="section">Overview</div>
838836
@ <p><table class="label-value">
839837
@ <tr><th>Artifact&nbsp;ID:</th>
840838
@ <td>%z(href("%R/artifact/%!S",zUuid))%s(zUuid)</a>
@@ -1053,50 +1051,47 @@
10531051
if(zGlob && !*zGlob){
10541052
zGlob = NULL;
10551053
}
10561054
diffFlags = construct_diff_flags(verboseFlag, sideBySide);
10571055
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);
10601057
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",
10631059
zFrom, zTo,
10641060
zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
10651061
}
10661062
if( !sideBySide ){
1067
- style_submenu_element("Side-by-Side Diff", "sbsdiff",
1063
+ style_submenu_element("Side-by-Side Diff",
10681064
"%R/vdiff?from=%T&to=%T&sbs=1%s%T%s",
10691065
zFrom, zTo,
10701066
zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
10711067
}
10721068
if( sideBySide || !verboseFlag ) {
1073
- style_submenu_element("Unified Diff", "udiff",
1069
+ style_submenu_element("Unified Diff",
10741070
"%R/vdiff?from=%T&to=%T&sbs=0&v%s%T%s",
10751071
zFrom, zTo,
10761072
zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
10771073
}
1078
- style_submenu_element("Invert", "invert",
1074
+ style_submenu_element("Invert",
10791075
"%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T%s", zTo, zFrom,
10801076
sideBySide, (verboseFlag && !sideBySide)?"&v":"",
10811077
zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
10821078
if( zGlob ){
1083
- style_submenu_element("Clear glob", "clearglob",
1079
+ style_submenu_element("Clear glob",
10841080
"%R/vdiff?from=%T&to=%T&sbs=%d%s%s", zFrom, zTo,
10851081
sideBySide, (verboseFlag && !sideBySide)?"&v":"", zW);
10861082
}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);
10891084
}
10901085
if( sideBySide || verboseFlag ){
10911086
if( *zW ){
1092
- style_submenu_element("Show Whitespace Differences", "whitespace",
1087
+ style_submenu_element("Show Whitespace Differences",
10931088
"%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T", zFrom, zTo,
10941089
sideBySide, (verboseFlag && !sideBySide)?"&v":"",
10951090
zGlob ? "&glob=" : "", zGlob ? zGlob : "");
10961091
}else{
1097
- style_submenu_element("Ignore Whitespace", "ignorews",
1092
+ style_submenu_element("Ignore Whitespace",
10981093
"%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T&w", zFrom, zTo,
10991094
sideBySide, (verboseFlag && !sideBySide)?"&v":"",
11001095
zGlob ? "&glob=" : "", zGlob ? zGlob : "");
11011096
}
11021097
}
@@ -1514,26 +1509,26 @@
15141509
diffFlags = construct_diff_flags(1, sideBySide) | DIFF_HTML;
15151510
15161511
style_header("Diff");
15171512
zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
15181513
if( *zW ){
1519
- style_submenu_element("Show Whitespace Changes", "Show Whitespace Changes",
1514
+ style_submenu_element("Show Whitespace Changes",
15201515
"%s/fdiff?v1=%T&v2=%T&sbs=%d",
15211516
g.zTop, P("v1"), P("v2"), sideBySide);
15221517
}else{
1523
- style_submenu_element("Ignore Whitespace", "Ignore Whitespace",
1518
+ style_submenu_element("Ignore Whitespace",
15241519
"%s/fdiff?v1=%T&v2=%T&sbs=%d&w",
15251520
g.zTop, P("v1"), P("v2"), sideBySide);
15261521
}
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",
15281523
g.zTop, P("v1"), P("v2"));
15291524
if( !sideBySide ){
1530
- style_submenu_element("Side-by-Side Diff", "sbsdiff",
1525
+ style_submenu_element("Side-by-Side Diff",
15311526
"%s/fdiff?v1=%T&v2=%T&sbs=1%s",
15321527
g.zTop, P("v1"), P("v2"), zW);
15331528
}else{
1534
- style_submenu_element("Unified Diff", "udiff",
1529
+ style_submenu_element("Unified Diff",
15351530
"%s/fdiff?v1=%T&v2=%T&sbs=0%s",
15361531
g.zTop, P("v1"), P("v2"), zW);
15371532
}
15381533
15391534
if( P("smhdr")!=0 ){
@@ -1672,15 +1667,14 @@
16721667
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
16731668
if( rid==0 ) fossil_redirect_home();
16741669
if( g.perm.Admin ){
16751670
const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
16761671
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",
16781673
g.zTop, zUuid);
16791674
}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);
16821676
}
16831677
}
16841678
style_header("Hex Artifact Content");
16851679
zUuid = db_text("?","SELECT uuid FROM blob WHERE rid=%d", rid);
16861680
if( g.perm.Setup ){
@@ -1689,12 +1683,12 @@
16891683
@ <h2>Artifact %s(zUuid):</h2>
16901684
}
16911685
blob_zero(&downloadName);
16921686
if( P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL;
16931687
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);
16961690
@ <hr />
16971691
content_get(rid, &content);
16981692
@ <blockquote><pre>
16991693
hexdump(&content);
17001694
@ </pre></blockquote>
@@ -1895,15 +1889,14 @@
18951889
/*NOTREACHED*/
18961890
}
18971891
if( g.perm.Admin ){
18981892
const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
18991893
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",
19011895
g.zTop, zUuid);
19021896
}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);
19051898
}
19061899
}
19071900
style_header("%s", descOnly ? "Artifact Description" : "Artifact Content");
19081901
zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid);
19091902
if( g.perm.Setup ){
@@ -1925,48 +1918,42 @@
19251918
const char *zIp = db_column_text(&q,2);
19261919
@ <p>Received on %s(zDate) from %h(zUser) at %h(zIp).</p>
19271920
}
19281921
db_finalize(&q);
19291922
}
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);
19321925
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);
19351927
}
19361928
asText = P("txt")!=0;
19371929
zMime = mimetype_from_name(blob_str(&downloadName));
19381930
if( zMime ){
19391931
if( fossil_strcmp(zMime, "text/html")==0 ){
19401932
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);
19431934
}else{
19441935
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);
19471937
}
19481938
}else if( fossil_strcmp(zMime, "text/x-fossil-wiki")==0
19491939
|| fossil_strcmp(zMime, "text/x-markdown")==0 ){
19501940
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);
19531942
}else{
19541943
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);
19571945
}
19581946
}
19591947
}
19601948
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);
19621950
}
19631951
if( descOnly ){
1964
- style_submenu_element("Content", "Content", "%R/artifact/%s", zUuid);
1952
+ style_submenu_element("Content", "%R/artifact/%s", zUuid);
19651953
}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,
19681955
((zLn&&*zLn) ? "" : "?txt=1&ln=0"));
19691956
@ <hr />
19701957
content_get(rid, &content);
19711958
if( renderAsWiki ){
19721959
wiki_render_by_mimetype(&content, zMime);
@@ -1975,11 +1962,11 @@
19751962
@ width="100%%" frameborder="0" marginwidth="0" marginheight="0"
19761963
@ sandbox="allow-same-origin"
19771964
@ onload="this.height=this.contentDocument.documentElement.scrollHeight;">
19781965
@ </iframe>
19791966
}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);
19811968
blob_to_utf8_no_bom(&content, 0);
19821969
zMime = mimetype_from_content(&content);
19831970
@ <blockquote>
19841971
if( zMime==0 ){
19851972
const char *z;
@@ -1992,12 +1979,11 @@
19921979
@ </pre>
19931980
}
19941981
}else if( strncmp(zMime, "image/", 6)==0 ){
19951982
@ <i>(file is %d(blob_size(&content)) bytes of image data)</i><br />
19961983
@ <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);
19991985
}else{
20001986
@ <i>(file is %d(blob_size(&content)) bytes of binary data)</i>
20011987
}
20021988
@ </blockquote>
20031989
}
@@ -2025,15 +2011,14 @@
20252011
rid = name_to_rid_www("name");
20262012
if( rid==0 ){ fossil_redirect_home(); }
20272013
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
20282014
if( g.perm.Admin ){
20292015
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",
20312017
g.zTop, zUuid);
20322018
}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);
20352020
}
20362021
}
20372022
pTktChng = manifest_get(rid, CFTYPE_TICKET, 0);
20382023
if( pTktChng==0 ) fossil_redirect_home();
20392024
zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate);
@@ -2060,19 +2045,18 @@
20602045
}
20612046
zTktTitle = db_table_has_column("repository", "ticket", "title" )
20622047
? db_text("(No title)", "SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName)
20632048
: 0;
20642049
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);
20692054
if( P("plaintext") ){
2070
- style_submenu_element("Formatted", "Formatted", "%R/info/%s", zUuid);
2055
+ style_submenu_element("Formatted", "%R/info/%s", zUuid);
20712056
}else{
2072
- style_submenu_element("Plaintext", "Plaintext",
2073
- "%R/info/%s?plaintext", zUuid);
2057
+ style_submenu_element("Plaintext", "%R/info/%s?plaintext", zUuid);
20742058
}
20752059
20762060
@ <div class="section">Overview</div>
20772061
@ <p><table class="label-value">
20782062
@ <tr><th>Artifact&nbsp;ID:</th>
@@ -2264,11 +2248,11 @@
22642248
{ "#91d680", 0 },
22652249
22662250
22672251
{ "custom", "##" },
22682252
};
2269
- int nColor = sizeof(aColor)/sizeof(aColor[0])-1;
2253
+ int nColor = count(aColor)-1;
22702254
int stdClrFound = 0;
22712255
int i;
22722256
22732257
if( zIdPropagate ){
22742258
@ <div><label>
22752259
--- 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&nbsp;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&nbsp;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&nbsp;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&nbsp;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
--- src/json_branch.c
+++ src/json_branch.c
@@ -292,11 +292,11 @@
292292
if( brid==0 ){
293293
fossil_fatal("Problem committing manifest: %s", g.zErrMsg);
294294
}
295295
db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid);
296296
if( manifest_crosslink(brid, &branch, MC_PERMIT_HOOKS)==0 ){
297
- fossil_fatal("%s\n", g.zErrMsg);
297
+ fossil_fatal("%s", g.zErrMsg);
298298
}
299299
assert( blob_is_reset(&branch) );
300300
content_deltify(rootid, brid, 0);
301301
if( zNewRid ){
302302
*zNewRid = brid;
303303
--- 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 @@
115115
if( contentFormat>0 ){/*HTML-ize it*/
116116
Blob content = empty_blob;
117117
Blob raw = empty_blob;
118118
zFormat = "html";
119119
if(zBody && *zBody){
120
+ const char *zMimetype = pWiki->zMimetype;
121
+ if( zMimetype==0 ) zMimetype = "text/plain";
122
+ zMimetype = wiki_filter_mimetypes(zMimetype);
120123
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
+ }
122140
len = (unsigned int)blob_size(&content);
123141
}
124142
cson_object_set(pay,"size",json_new_int((cson_int_t)len));
125143
cson_object_set(pay,"content",
126144
cson_value_new_string(blob_buffer(&content),len));
127145
--- 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
--- src/linenoise.c
+++ src/linenoise.c
@@ -105,10 +105,11 @@
105105
*
106106
*/
107107
108108
#include <termios.h>
109109
#include <unistd.h>
110
+#include <stdarg.h>
110111
#include <stdlib.h>
111112
#include <stdio.h>
112113
#include <errno.h>
113114
#include <string.h>
114115
#include <stdlib.h>
@@ -115,10 +116,11 @@
115116
#include <ctype.h>
116117
#include <sys/types.h>
117118
#include <sys/ioctl.h>
118119
#include <unistd.h>
119120
#include "linenoise.h"
121
+#include "sqlite3.h"
120122
121123
#define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100
122124
#define LINENOISE_MAX_LINE 4096
123125
static const char *unsupported_term[] = {"dumb","cons25","emacs",NULL};
124126
static linenoiseCompletionCallback *completionCallback = NULL;
@@ -191,10 +193,42 @@
191193
fflush(lndebug_fp); \
192194
} while (0)
193195
#else
194196
#define lndebug(fmt, arg1)
195197
#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
196230
197231
/* ======================= Low level terminal handling ====================== */
198232
199233
/* Set if to use or not the multi line mode. */
200234
void linenoiseSetMultiLine(int ml) {
201235
--- 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 @@
1818
** This module codes the main() procedure that runs first when the
1919
** program is invoked.
2020
*/
2121
#include "VERSION.h"
2222
#include "config.h"
23
+#if defined(_WIN32)
24
+# include <windows.h>
25
+#endif
2326
#include "main.h"
2427
#include <string.h>
2528
#include <time.h>
2629
#include <fcntl.h>
2730
#include <sys/types.h>
2831
#include <sys/stat.h>
2932
#include <stdlib.h> /* atexit() */
30
-#if defined(_WIN32)
31
-# include <windows.h>
32
-#else
33
+#if !defined(_WIN32)
3334
# include <errno.h> /* errno global */
3435
#endif
3536
#ifdef FOSSIL_ENABLE_SSL
3637
# include "openssl/crypto.h"
3738
#endif
@@ -299,10 +300,22 @@
299300
/*
300301
** atexit() handler which frees up "some" of the resources
301302
** used by fossil.
302303
*/
303304
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
304317
#if defined(_WIN32) && !defined(_WIN64) && defined(FOSSIL_ENABLE_TCL) && \
305318
defined(USE_TCL_STUBS)
306319
/*
307320
** If Tcl is compiled on Windows using the latest MinGW, Fossil can crash
308321
** when exiting while a stubs-enabled Tcl is still loaded. This is due to
@@ -1917,10 +1930,41 @@
19171930
}
19181931
}
19191932
}
19201933
}
19211934
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
+
19221966
/*
19231967
** undocumented format:
19241968
**
19251969
** fossil http INFILE OUTFILE IPADDR ?REPOSITORY?
19261970
**
@@ -1968,10 +2012,12 @@
19682012
** --notfound URL use URL as "HTTP 404, object not found" page.
19692013
** --repolist If REPOSITORY is directory, URL "/" lists all repos
19702014
** --scgi Interpret input as SCGI rather than HTTP
19712015
** --skin LABEL Use override skin LABEL
19722016
** --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.
19732019
**
19742020
** See also: cgi, server, winsrv
19752021
*/
19762022
void cmd_http(void){
19772023
const char *zIpAddr = 0;
@@ -1980,10 +2026,13 @@
19802026
const char *zAltBase;
19812027
const char *zFileGlob;
19822028
int useSCGI;
19832029
int noJail;
19842030
int allowRepoList;
2031
+#if defined(_WIN32) && USE_SEE
2032
+ const char *zPidKey;
2033
+#endif
19852034
19862035
Th_InitTraceLog();
19872036
19882037
/* The winhttp module passes the --files option as --files-urlenc with
19892038
** the argument being URL encoded, to avoid wildcard expansion in the
@@ -2010,10 +2059,21 @@
20102059
zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */
20112060
cgi_replace_parameter("HTTPS","on");
20122061
}
20132062
zHost = find_option("host", 0, 1);
20142063
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
20152075
20162076
/* We should be done with options.. */
20172077
verify_all_options();
20182078
20192079
if( g.argc!=2 && g.argc!=3 && g.argc!=5 && g.argc!=6 ){
@@ -2171,11 +2231,12 @@
21712231
** -P|--port TCPPORT listen to request on port TCPPORT
21722232
** --th-trace trace TH1 execution (for debugging purposes)
21732233
** --repolist If REPOSITORY is dir, URL "/" lists repos.
21742234
** --scgi Accept SCGI rather than HTTP
21752235
** --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.
21772238
**
21782239
** See also: cgi, http, winsrv
21792240
*/
21802241
void cmd_webserver(void){
21812242
int iPort, mxPort; /* Range of TCP ports allowed */
@@ -2192,10 +2253,13 @@
21922253
const char *zAltBase; /* Argument to the --baseurl option */
21932254
const char *zFileGlob; /* Static content must match this */
21942255
char *zIpAddr = 0; /* Bind to this IP address */
21952256
int fCreate = 0; /* The --create flag */
21962257
const char *zInitPage = 0; /* Start on this page. --page option */
2258
+#if defined(_WIN32) && USE_SEE
2259
+ const char *zPidKey;
2260
+#endif
21972261
21982262
#if defined(_WIN32)
21992263
const char *zStopperFile; /* Name of file used to terminate server */
22002264
zStopperFile = find_option("stopper", 0, 1);
22012265
#endif
@@ -2235,10 +2299,21 @@
22352299
g.sslNotAvailable = 1;
22362300
}
22372301
if( find_option("localhost", 0, 0)!=0 ){
22382302
flags |= HTTP_SERVER_LOCALHOST;
22392303
}
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
22402315
22412316
/* We should be done with options.. */
22422317
verify_all_options();
22432318
22442319
if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
@@ -2275,11 +2350,11 @@
22752350
if( zBrowser==0 ){
22762351
static const char *const azBrowserProg[] =
22772352
{ "xdg-open", "gnome-open", "firefox", "google-chrome" };
22782353
int i;
22792354
zBrowser = "echo";
2280
- for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
2355
+ for(i=0; i<count(azBrowserProg); i++){
22812356
if( binaryOnPath(azBrowserProg[i]) ){
22822357
zBrowser = azBrowserProg[i];
22832358
break;
22842359
}
22852360
}
22862361
--- 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 @@
88
# to regenerate this file.
99
#
1010
# This file is included by primary Makefile.
1111
#
1212
13
+XBCC = $(BCC) $(BCCFLAGS) $(CFLAGS)
1314
XTCC = $(TCC) -I. -I$(SRCDIR) -I$(OBJDIR) $(TCCFLAGS) $(CFLAGS)
1415
1516
1617
SRC = \
1718
$(SRCDIR)/add.c \
@@ -451,26 +452,26 @@
451452
452453
$(OBJDIR):
453454
-mkdir $(OBJDIR)
454455
455456
$(OBJDIR)/translate: $(SRCDIR)/translate.c
456
- $(BCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c
457
+ $(XBCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c
457458
458459
$(OBJDIR)/makeheaders: $(SRCDIR)/makeheaders.c
459
- $(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
460
+ $(XBCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
460461
461462
$(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
462
- $(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
463
+ $(XBCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
463464
464465
$(OBJDIR)/mkbuiltin: $(SRCDIR)/mkbuiltin.c
465
- $(BCC) -o $(OBJDIR)/mkbuiltin $(SRCDIR)/mkbuiltin.c
466
+ $(XBCC) -o $(OBJDIR)/mkbuiltin $(SRCDIR)/mkbuiltin.c
466467
467468
$(OBJDIR)/mkversion: $(SRCDIR)/mkversion.c
468
- $(BCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c
469
+ $(XBCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c
469470
470471
$(OBJDIR)/codecheck1: $(SRCDIR)/codecheck1.c
471
- $(BCC) -o $(OBJDIR)/codecheck1 $(SRCDIR)/codecheck1.c
472
+ $(XBCC) -o $(OBJDIR)/codecheck1 $(SRCDIR)/codecheck1.c
472473
473474
# Run the test suite.
474475
# Other flags that can be included in TESTFLAGS are:
475476
#
476477
# -halt Stop testing after the first failed test
477478
--- 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
--- src/makeheaders.html
+++ src/makeheaders.html
@@ -4,11 +4,11 @@
44
<h1 align=center>The Makeheaders Program</h1>
55
66
77
<p>
88
This document describes <em>makeheaders</em>,
9
-a tool that automatically generates ``<code>.h</code>''
9
+a tool that automatically generates &#8220;<code>.h</code>&#8221;
1010
files for a C or C++ programming project.
1111
</p>
1212
1313
1414
<h2>Table Of Contents</h2>
@@ -67,11 +67,11 @@
6767
<ul>
6868
<li> Typedefs.
6969
<li> Structure, union and enumeration declarations.
7070
<li> Function and procedure prototypes.
7171
<li> Preprocessor macros and #defines.
72
-<li> ``extern'' variable declarations.
72
+<li> &#8220;<code>extern</code>&#8221; variable declarations.
7373
</ul>
7474
</p>
7575
7676
<p>
7777
Definitions in C, on the other hand, include these kinds of things:
@@ -89,13 +89,13 @@
8989
is the <em>interface</em> and the definition is the <em>implementation</em>.
9090
</p>
9191
9292
<p>
9393
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 &#8220;<code>.h</code>&#8221; suffix and definitions are
95
+placed in &#8220;<code>.c</code>&#8221; files.
96
+The .c files contain &#8220;<code>#include</code>&#8221; preprocessor statements
9797
that cause the contents of .h files to be included as part of the
9898
source code when the .c file is compiled.
9999
In this way, the .h files define the interface to a subsystem and
100100
the .c files define how the subsystem is implemented.
101101
</p>
@@ -262,11 +262,11 @@
262262
263263
<p>
264264
A similar option is -H. Like the lower-case -h option, big -H
265265
generates a single include file on standard output. But unlike
266266
small -h, the big -H only emits prototypes and declarations that
267
-have been designated as ``exportable''.
267
+have been designated as &#8220;exportable&#8221;.
268268
The idea is that -H will generate an include file that defines
269269
the interface to a library.
270270
More will be said about this in section 3.4.
271271
</p>
272272
@@ -293,13 +293,13 @@
293293
then you can supply an empty header filename, like this:
294294
<pre>
295295
makeheaders alpha.c beta.c gamma.c:
296296
</pre>
297297
In this example, makeheaders will scan the three files named
298
-``alpha.c'',
299
-``beta.c'' and
300
-``gamma.c''
298
+&#8220;<code>alpha.c</code>&#8221;,
299
+&#8220;<code>beta.c</code>&#8221; and
300
+&#8220;<code>gamma.c</code>&#8221;
301301
but because of the colon on the end of third filename
302302
it will only generate headers for the first two files.
303303
Unfortunately,
304304
it is not possible to get makeheaders to process any file whose
305305
name contains a colon.
@@ -309,14 +309,14 @@
309309
In a large project, the length of the command line for makeheaders
310310
can become very long.
311311
If the operating system doesn't support long command lines
312312
(example: DOS and Win32) you may not be able to list all of the
313313
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 &#8220;<code>-f</code>&#8221; option followed
315315
by the name of a file to cause makeheaders to read command line
316316
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 &#8220;<code>mkhdr.dat</code>&#8221;
318318
that contains text like this:
319319
<pre>
320320
src/alpha.c:hdr/alpha.h
321321
src/beta.c:hdr/beta.h
322322
src/gamma.c:hdr/gamma.h
@@ -327,18 +327,18 @@
327327
makeheaders -f mkhdr.dat
328328
</pre>
329329
</p>
330330
331331
<p>
332
-The ``-local'' option causes makeheaders to
333
-generate of prototypes for ``static'' functions and
332
+The &#8220;<code>-local</code>&#8221; option causes makeheaders to
333
+generate of prototypes for &#8220;<code>static</code>&#8221; functions and
334334
procedures.
335335
Such prototypes are normally omitted.
336336
</p>
337337
338338
<p>
339
-Finally, makeheaders also includes a ``-doc'' option.
339
+Finally, makeheaders also includes a &#8220;<code>-doc</code>&#8221; option.
340340
This command line option prevents makeheaders from generating any
341341
headers at all.
342342
Instead, makeheaders will write to standard output
343343
information about every definition and declaration that it encounters
344344
in its scan of source files.
@@ -352,19 +352,21 @@
352352
</p>
353353
354354
<p>
355355
If you forget what command line options are available, or forget
356356
their exact name, you can invoke makeheaders using an unknown
357
-command line option (like ``--help'' or ``-?'')
357
+command line option (like &#8220;<code>--help</code>&#8221; or
358
+&#8220;<code>-?</code>&#8221;)
358359
and it will print a summary of the available options on standard
359360
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
+&#8220;<code>-</code>&#8221;,
363
+you can prepend a &#8220;<code>./</code>&#8221; to its name in order to get it
362364
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 &#8220;<code>--</code>&#8221; on the
366
+command line to cause all subsequent command line arguments to be treated as
367
+filenames even if their names begin with &#8220;<code>-</code>&#8221;.
366368
</p>
367369
368370
<a name="H0006"></a>
369371
<h2>3.0 Preparing Source Files For Use With Makeheaders</h2>
370372
@@ -379,30 +381,31 @@
379381
380382
<a name="H0007"></a>
381383
<h3>3.1 The Basic Setup</h3>
382384
383385
<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
385387
one or more .c files and all structure and type declarations in
386388
separate .h files.
387389
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
389391
.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
+&#8220;<code>alpha.c</code>&#8221;
391394
makeheaders will attempt to generate a corresponding header file
392
-named ``alpha.h''.
395
+named &#8220;<code>alpha.h</code>&#8221;.
393396
For that reason, you don't want to use that name for
394397
any of the .h files you write since that will prevent makeheaders
395398
from generating the .h file automatically.
396399
</p>
397400
398401
<p>
399402
The structure of a .c file intented for use with makeheaders is very
400403
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 &#8220;<code>#include</code>&#8221; 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 &#8220;<code>alpha.c</code>&#8221;
404407
might look something like this:
405408
</p>
406409
407410
<pre>
408411
/*
@@ -415,14 +418,14 @@
415418
416419
<p>
417420
Your manually generated header files require no special attention at all.
418421
Code them as you normally would.
419422
However, makeheaders will work better if you omit the
420
-``#if'' statements people often put around the outside of
423
+&#8220;<code>#if</code>&#8221; statements people often put around the outside of
421424
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 &#8220;<code>beta.h</code>&#8221;,
426
+many people will habitually write the following:
424427
425428
<pre>
426429
#ifndef BETA_H
427430
#define BETA_H
428431
@@ -435,11 +438,11 @@
435438
Remember that the header files you write will never really be
436439
included by any C code.
437440
Instead, makeheaders will scan your header files to extract only
438441
those declarations that are needed by individual .c files and then
439442
copy those declarations to the .h files corresponding to the .c files.
440
-Hence, the ``#if'' wrapper serves no useful purpose.
443
+Hence, the &#8220;<code>#if</code>&#8221; wrapper serves no useful purpose.
441444
But it does make makeheaders work harder, forcing it to put
442445
the statements
443446
444447
<pre>
445448
#if !defined(BETA_H)
@@ -465,11 +468,11 @@
465468
</p>
466469
467470
<p>
468471
Note that
469472
the wildcard expression used in the above example,
470
-``<code>*.[ch]</code>'',
473
+&#8220;<code>*.[ch]</code>&#8221;,
471474
will expand to include all .h files in the current directory, both
472475
those entered manually be the programmer and others generated automatically
473476
by a prior run of makeheaders.
474477
But that is not a problem.
475478
The makeheaders program will recognize and ignore any files it
@@ -489,14 +492,14 @@
489492
<p><li>
490493
When a function is defined in any .c file, a prototype of that function
491494
is placed in the generated .h file of every .c file that
492495
calls the function.</p>
493496
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 &#8220;<code>static</code>&#8221; keyword of C appears at the
498
+beginning of the function definition, the prototype is suppressed.
499
+If you use the &#8220;<code>LOCAL</code>&#8221; keyword where you would normally
500
+say &#8220;<code>static</code>&#8221;, then a prototype is generated, but it
498501
will only appear in the single header file that corresponds to the
499502
source file containing the function. For example, if the file
500503
<code>alpha.c</code> contains the following:
501504
<pre>
502505
LOCAL int testFunc(void){
@@ -509,24 +512,26 @@
509512
LOCAL int testFunc(void);
510513
</pre>
511514
However, no other generated header files will contain a prototype for
512515
<code>testFunc()</code> since the function has only file scope.</p>
513516
514
-<p>When the ``LOCAL'' keyword is used, makeheaders will also
515
-generate a #define for LOCAL, like this:
517
+<p>When the &#8220;<code>LOCAL</code>&#8221; keyword is used, makeheaders will
518
+also generate a #define for LOCAL, like this:
516519
<pre>
517520
#define LOCAL static
518521
</pre>
519522
so that the C compiler will know what it means.</p>
520523
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 &#8220;<code>-local</code>&#8221;
525
+command-line option, then it treats the &#8220;<code>static</code>&#8221;
526
+keyword like &#8220;<code>LOCAL</code>&#8221; and generates prototypes in the
527
+header file that corresponds to the source file containing the function
528
+definition.</p>
525529
526530
<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
+&#8220;<code>extern</code>&#8221;
528533
declaration of that variable is placed in the header of every
529534
.c file that uses the variable.
530535
</p>
531536
532537
<p><li>
@@ -550,12 +555,12 @@
550555
551556
<p><li>
552557
When a structure, union or enumeration declaration appears in a .h
553558
file, makeheaders will automatically
554559
generate a typedef that allows the declaration to be referenced without
555
-the ``struct'', ``union'' or ``enum''
556
-qualifier.
560
+the &#8220;<code>struct</code>&#8221;, &#8220;<code>union</code>&#8221; or
561
+&#8220;<code>enum</code>&#8221; qualifier.
557562
In other words, if makeheaders sees the code:
558563
<pre>
559564
struct Examp { /* ... */ };
560565
</pre>
561566
it will automatically generate a corresponding typedef like this:
@@ -572,13 +577,13 @@
572577
</ul>
573578
574579
<p>
575580
As a final note, we observe that automatically generated declarations
576581
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 &#8220;<code>X</code>&#8221; requires a
583
+prior declaration of another structure &#8220;<code>Y</code>&#8221;, then Y will
584
+appear first in the generated headers.
580585
</p>
581586
582587
<a name="H0009"></a>
583588
<h3>3.3 How To Avoid Having To Write Any Header Files</h3>
584589
@@ -611,18 +616,18 @@
611616
<pre>
612617
#if INTERFACE
613618
#endif
614619
</pre>
615620
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
+&#8220;<code>#if INTERFACE</code>&#8221; but before the corresponding
622
+&#8220;<code>#endif</code>&#8221; are eligable to be copied into the
618623
automatically generated
619624
.h files of other .c files.
620625
</p>
621626
622627
<p>
623
-If you use the ``#if INTERFACE'' mechanism in a .c file,
628
+If you use the &#8220;<code>#if INTERFACE</code>&#8221; mechanism in a .c file,
624629
then the generated header for that .c file will contain a line
625630
like this:
626631
<pre>
627632
#define INTERFACE 0
628633
</pre>
@@ -637,15 +642,15 @@
637642
</p>
638643
639644
<p>
640645
Note that you don't have to use this approach exclusively.
641646
You can put some declarations in .h files and others within the
642
-``#if INTERFACE'' regions of .c files.
647
+&#8220;<code>#if INTERFACE</code>&#8221; regions of .c files.
643648
Makeheaders treats all declarations alike, no matter where they
644649
come from.
645650
You should also note that a single .c file can contain as many
646
-``#if INTERFACE'' regions as desired.
651
+&#8220;<code>#if INTERFACE</code>&#8221; regions as desired.
647652
</p>
648653
649654
<a name="H0010"></a>
650655
<h3>3.4 Designating Declarations For Export</h3>
651656
@@ -664,11 +669,11 @@
664669
like this, but makeheaders does.
665670
</p>
666671
667672
<p>
668673
Using makeheaders, it is possible to designate routines and data
669
-structures as being for ``export''.
674
+structures as being for &#8220;<code>export</code>&#8221;.
670675
Exported objects are visible not only to other files within the
671676
same library or subassembly but also to other
672677
libraries and subassemblies in the larger program.
673678
By default, makeheaders only makes objects visible to other members
674679
of the same library.
@@ -690,14 +695,14 @@
690695
691696
<p>
692697
But trouble quickly arises when we attempt to devise a mechanism for
693698
telling makeheaders which prototypes it should export and which it should
694699
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 &#8220;<code>static</code>&#8221; keyword of C works well for
701
+prohibiting prototypes from leaving a single source file, but because C doesn't
697702
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: &#8220;<code>EXPORT</code>&#8221;
699704
</p>
700705
701706
<p>
702707
Makeheaders allows the EXPORT keyword to precede any function or
703708
procedure definition.
@@ -726,15 +731,15 @@
726731
<pre>
727732
#if EXPORT_INTERFACE
728733
#endif
729734
</pre>
730735
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 &#8220;<code>#if EXPORT_INTERFACE</code>&#8221; mechanism can be used in
737
+either .c or .h files.
738
+(The &#8220;<code>#if INTERFACE</code>&#8221; 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.)
736741
</p>
737742
738743
<a name="H0011"></a>
739744
<h3>3.5 Local declarations processed by makeheaders</h3>
740745
@@ -742,11 +747,11 @@
742747
Structure declarations and typedefs that appear in .c files are normally
743748
ignored by makeheaders.
744749
Such declarations are only intended for use by the source file in which
745750
they appear and so makeheaders doesn't need to copy them into any
746751
generated header files.
747
-We call such declarations ``private''.
752
+We call such declarations &#8220;<code>private</code>&#8221;.
748753
</p>
749754
750755
<p>
751756
Sometimes it is convenient to have makeheaders sort a sequence
752757
of private declarations into the correct order for us automatically.
@@ -764,12 +769,13 @@
764769
within
765770
<pre>
766771
#if LOCAL_INTERFACE
767772
#endif
768773
</pre>
769
-A ``LOCAL_INTERFACE'' block works very much like the
770
-``INTERFACE'' and ``EXPORT_INTERFACE''
774
+A &#8220;<code>LOCAL_INTERFACE</code>&#8221; block works very much like the
775
+&#8220;<code>INTERFACE</code>&#8221; and
776
+&#8220;<code>EXPORT_INTERFACE</code>&#8221;
771777
blocks described above, except that makeheaders insures that the
772778
objects declared in a LOCAL_INTERFACE are only visible to the
773779
file containing the LOCAL_INTERFACE.
774780
</p>
775781
@@ -777,11 +783,12 @@
777783
<h3>3.6 Using Makeheaders With C++ Code</h3>
778784
779785
<p>
780786
You can use makeheaders to generate header files for C++ code, in
781787
addition to C.
782
-Makeheaders will recognize and copy both ``class'' declarations
788
+Makeheaders will recognize and copy both &#8220;<code>class</code>&#8221;
789
+declarations
783790
and inline function definitions, and it knows not to try to generate
784791
prototypes for methods.
785792
</p>
786793
787794
<p>
@@ -805,20 +812,20 @@
805812
C++ input. Makeheaders will recognize that its source code is C++
806813
by the suffix on the source code filename. Simple ".c" or ".h" suffixes
807814
are assumed to be ANSI-C. Anything else, including ".cc", ".C" and
808815
".cpp" is assumed to be C++.
809816
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
811818
every "C" to "H" in the suffix of the filename.
812819
Thus the C++ source
813
-file ``alpha.cpp'' will induce makeheaders to
814
-generate a header file named ``alpha.hpp''.
820
+file &#8220;<code>alpha.cpp</code>&#8221; will induce makeheaders to
821
+generate a header file named &#8220;<code>alpha.hpp</code>&#8221;.
815822
</p>
816823
817824
<p>
818825
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
820827
of the special keywords <b>PUBLIC</b>, <b>PROTECTED</b>, or
821828
<b>PRIVATE</b> (in upper-case to distinguish them from the regular
822829
C++ keywords with the same meaning) then a prototype for that
823830
method will be inserted into the class definition. If none of
824831
these keywords appear, then the prototype is not inserted. For
@@ -867,11 +874,11 @@
867874
<h4>3.6.1 C++ Limitations</h4>
868875
869876
<p>
870877
Makeheaders does not understand more recent
871878
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.
873880
</p>
874881
875882
<a name="H0013"></a>
876883
<h3>3.7 Conditional Compilation</h3>
877884
@@ -879,13 +886,13 @@
879886
The makeheaders program understands and tracks the conditional
880887
compilation constructs in the source code files it scans.
881888
Hence, if the following code appears in a source file
882889
<pre>
883890
#ifdef UNIX
884
- # define WORKS_WELL 1
891
+ # define WORKS_WELL 1
885892
#else
886
- # define WORKS_WELL 0
893
+ # define WORKS_WELL 0
887894
#endif
888895
</pre>
889896
then the next patch of code will appear in the generated header for
890897
every .c file that uses the WORKS_WELL constant:
891898
<pre>
@@ -918,12 +925,12 @@
918925
<p>
919926
Makeheaders does not understand the old K&amp;R style of function
920927
and procedure definitions.
921928
It only understands the modern ANSI-C style, and will probably
922929
become very confused if it encounters an old K&amp;R function.
923
-You should take care to avoid putting K&amp;R function defintions
924
-in your code, therefore.
930
+Therefore you should take care to avoid putting K&amp;R function definitions
931
+in your code.
925932
</p>
926933
927934
<p>
928935
Makeheaders does not understand when you define more than one
929936
global variable with the same type separated by a comma.
@@ -993,35 +1000,35 @@
9931000
in the code, it is not necessary to make a corresponding change
9941001
in a separate document. Just rerun the documentation generator.
9951002
</ul>
9961003
The makeheaders program does not generate program documentation itself.
9971004
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
9991006
information to another tool to do the actual documentation preparation.
10001007
</p>
10011008
10021009
<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 &#8220;<code>-doc</code>&#8221; option, it
1011
+emits no header files at all.
10051012
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.
10071014
This output can then be used by another program (the implementation
10081015
of which is left as an exercise to the reader) that will use the
10091016
information to prepare suitable documentation.
10101017
</p>
10111018
10121019
<p>
1013
-The ``-doc'' option causes makeheaders to print information
1014
-to standard output about all of the following objects:
1020
+The &#8220;<code>-doc</code>&#8221; option causes makeheaders to print
1021
+information to standard output about all of the following objects:
10151022
<ul>
1016
-<li> C++ Class declarations
1023
+<li> C++ class declarations
10171024
<li> Structure and union declarations
10181025
<li> Enumerations
10191026
<li> Typedefs
10201027
<li> Procedure and function definitions
10211028
<li> Global variables
1022
-<li> Preprocessor macros (ex: ``#define'')
1029
+<li> Preprocessor macros (ex: &#8220;<code>#define</code>&#8221;)
10231030
</ul>
10241031
For each of these objects, the following information is output:
10251032
<ul>
10261033
<li> The name of the object.
10271034
<li> The type of the object. (Structure, typedef, macro, etc.)
@@ -1029,11 +1036,12 @@
10291036
an EXPORT_INTERFACE block) or local (contained with LOCAL_INTERFACE).
10301037
<li> A flag to indicate if the object is declared in a C++ file.
10311038
<li> The name of the file in which the object was declared.
10321039
<li> The complete text of any block comment that preceeds the declarations.
10331040
<li> If the declaration occurred inside a preprocessor conditional
1034
- (``#if'') then the text of that conditional is provided.
1041
+ (&#8220;<code>#if</code>&#8221;) then the text of that conditional is
1042
+ provided.
10351043
<li> The complete text of a declaration for the object.
10361044
</ul>
10371045
The exact output format will not be described here.
10381046
It is simple to understand and parse and should be obvious to
10391047
anyone who inspects some sample output.
@@ -1042,11 +1050,11 @@
10421050
<a name="H0016"></a>
10431051
<h2>5.0 Compiling The Makeheaders Program</h2>
10441052
10451053
<p>
10461054
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.
10481056
The program makes only modest demands of the system and C library
10491057
and should compile without alteration on most ANSI C compilers
10501058
and on most operating systems.
10511059
It is known to compile using several variations of GCC for Unix
10521060
as well as Cygwin32 and MSVC 5.0 for Win32.
10531061
--- 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&amp;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&amp;R function.
923 You should take care to avoid putting K&amp;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 &#8220;<code>.h</code>&#8221;
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> &#8220;<code>extern</code>&#8221; 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 &#8220;<code>.h</code>&#8221; suffix and definitions are
95 placed in &#8220;<code>.c</code>&#8221; files.
96 The .c files contain &#8220;<code>#include</code>&#8221; 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 &#8220;exportable&#8221;.
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 &#8220;<code>alpha.c</code>&#8221;,
299 &#8220;<code>beta.c</code>&#8221; and
300 &#8220;<code>gamma.c</code>&#8221;
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 &#8220;<code>-f</code>&#8221; 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 &#8220;<code>mkhdr.dat</code>&#8221;
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 &#8220;<code>-local</code>&#8221; option causes makeheaders to
333 generate of prototypes for &#8220;<code>static</code>&#8221; functions and
334 procedures.
335 Such prototypes are normally omitted.
336 </p>
337
338 <p>
339 Finally, makeheaders also includes a &#8220;<code>-doc</code>&#8221; 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 &#8220;<code>--help</code>&#8221; or
358 &#8220;<code>-?</code>&#8221;)
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 &#8220;<code>-</code>&#8221;,
363 you can prepend a &#8220;<code>./</code>&#8221; to its name in order to get it
364 accepted by the command line parser.
365 Or, you can insert the special option &#8220;<code>--</code>&#8221; on the
366 command line to cause all subsequent command line arguments to be treated as
367 filenames even if their names begin with &#8220;<code>-</code>&#8221;.
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 &#8220;<code>alpha.c</code>&#8221;
394 makeheaders will attempt to generate a corresponding header file
395 named &#8220;<code>alpha.h</code>&#8221;.
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 &#8220;<code>#include</code>&#8221; 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 &#8220;<code>alpha.c</code>&#8221;
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 &#8220;<code>#if</code>&#8221; 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 &#8220;<code>beta.h</code>&#8221;,
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 &#8220;<code>#if</code>&#8221; 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 &#8220;<code>*.[ch]</code>&#8221;,
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 &#8220;<code>static</code>&#8221; keyword of C appears at the
498 beginning of the function definition, the prototype is suppressed.
499 If you use the &#8220;<code>LOCAL</code>&#8221; keyword where you would normally
500 say &#8220;<code>static</code>&#8221;, 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 &#8220;<code>LOCAL</code>&#8221; 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 &#8220;<code>-local</code>&#8221;
525 command-line option, then it treats the &#8220;<code>static</code>&#8221;
526 keyword like &#8220;<code>LOCAL</code>&#8221; 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 &#8220;<code>extern</code>&#8221;
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 &#8220;<code>struct</code>&#8221;, &#8220;<code>union</code>&#8221; or
561 &#8220;<code>enum</code>&#8221; 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 &#8220;<code>X</code>&#8221; requires a
583 prior declaration of another structure &#8220;<code>Y</code>&#8221;, 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 &#8220;<code>#if INTERFACE</code>&#8221; but before the corresponding
622 &#8220;<code>#endif</code>&#8221; 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 &#8220;<code>#if INTERFACE</code>&#8221; 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 &#8220;<code>#if INTERFACE</code>&#8221; 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 &#8220;<code>#if INTERFACE</code>&#8221; 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 &#8220;<code>export</code>&#8221;.
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 &#8220;<code>static</code>&#8221; 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: &#8220;<code>EXPORT</code>&#8221;
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 &#8220;<code>#if EXPORT_INTERFACE</code>&#8221; mechanism can be used in
737 either .c or .h files.
738 (The &#8220;<code>#if INTERFACE</code>&#8221; 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 &#8220;<code>private</code>&#8221;.
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 &#8220;<code>LOCAL_INTERFACE</code>&#8221; block works very much like the
775 &#8220;<code>INTERFACE</code>&#8221; and
776 &#8220;<code>EXPORT_INTERFACE</code>&#8221;
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 &#8220;<code>class</code>&#8221;
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 &#8220;<code>alpha.cpp</code>&#8221; will induce makeheaders to
821 generate a header file named &#8220;<code>alpha.hpp</code>&#8221;.
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&amp;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&amp;R function.
930 Therefore you should take care to avoid putting K&amp;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 &#8220;<code>-doc</code>&#8221; 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 &#8220;<code>-doc</code>&#8221; 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: &#8220;<code>#define</code>&#8221;)
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 (&#8220;<code>#if</code>&#8221;) 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 @@
255255
# to regenerate this file.
256256
#
257257
# This file is included by primary Makefile.
258258
#
259259
260
+XBCC = $(BCC) $(BCCFLAGS) $(CFLAGS)
260261
XTCC = $(TCC) -I. -I$(SRCDIR) -I$(OBJDIR) $(TCCFLAGS) $(CFLAGS)
261262
262263
}
263264
writeln -nonewline "SRC ="
264265
foreach s [lsort $src] {
@@ -298,26 +299,26 @@
298299
299300
$(OBJDIR):
300301
-mkdir $(OBJDIR)
301302
302303
$(OBJDIR)/translate: $(SRCDIR)/translate.c
303
- $(BCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c
304
+ $(XBCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c
304305
305306
$(OBJDIR)/makeheaders: $(SRCDIR)/makeheaders.c
306
- $(BCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
307
+ $(XBCC) -o $(OBJDIR)/makeheaders $(SRCDIR)/makeheaders.c
307308
308309
$(OBJDIR)/mkindex: $(SRCDIR)/mkindex.c
309
- $(BCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
310
+ $(XBCC) -o $(OBJDIR)/mkindex $(SRCDIR)/mkindex.c
310311
311312
$(OBJDIR)/mkbuiltin: $(SRCDIR)/mkbuiltin.c
312
- $(BCC) -o $(OBJDIR)/mkbuiltin $(SRCDIR)/mkbuiltin.c
313
+ $(XBCC) -o $(OBJDIR)/mkbuiltin $(SRCDIR)/mkbuiltin.c
313314
314315
$(OBJDIR)/mkversion: $(SRCDIR)/mkversion.c
315
- $(BCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c
316
+ $(XBCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c
316317
317318
$(OBJDIR)/codecheck1: $(SRCDIR)/codecheck1.c
318
- $(BCC) -o $(OBJDIR)/codecheck1 $(SRCDIR)/codecheck1.c
319
+ $(XBCC) -o $(OBJDIR)/codecheck1 $(SRCDIR)/codecheck1.c
319320
320321
# Run the test suite.
321322
# Other flags that can be included in TESTFLAGS are:
322323
#
323324
# -halt Stop testing after the first failed test
@@ -917,10 +918,11 @@
917918
-include config.w32
918919
919920
# STOP HERE
920921
# You should not need to change anything below this line
921922
#--------------------------------------------------------
923
+XBCC = $(BCC) $(CFLAGS)
922924
XTCC = $(TCC) $(CFLAGS) -I. -I$(SRCDIR)
923925
}
924926
writeln -nonewline "SRC ="
925927
foreach s [lsort $src] {
926928
writeln -nonewline " \\\n \$(SRCDIR)/$s.c"
@@ -1013,26 +1015,26 @@
10131015
else
10141016
$(MKDIR) $(OBJDIR)
10151017
endif
10161018
10171019
$(TRANSLATE): $(SRCDIR)/translate.c
1018
- $(BCC) -o $@ $(SRCDIR)/translate.c
1020
+ $(XBCC) -o $@ $(SRCDIR)/translate.c
10191021
10201022
$(MAKEHEADERS): $(SRCDIR)/makeheaders.c
1021
- $(BCC) -o $@ $(SRCDIR)/makeheaders.c
1023
+ $(XBCC) -o $@ $(SRCDIR)/makeheaders.c
10221024
10231025
$(MKINDEX): $(SRCDIR)/mkindex.c
1024
- $(BCC) -o $@ $(SRCDIR)/mkindex.c
1026
+ $(XBCC) -o $@ $(SRCDIR)/mkindex.c
10251027
10261028
$(MKBUILTIN): $(SRCDIR)/mkbuiltin.c
1027
- $(BCC) -o $@ $(SRCDIR)/mkbuiltin.c
1029
+ $(XBCC) -o $@ $(SRCDIR)/mkbuiltin.c
10281030
10291031
$(MKVERSION): $(SRCDIR)/mkversion.c
1030
- $(BCC) -o $@ $(SRCDIR)/mkversion.c
1032
+ $(XBCC) -o $@ $(SRCDIR)/mkversion.c
10311033
10321034
$(CODECHECK1): $(SRCDIR)/codecheck1.c
1033
- $(BCC) -o $@ $(SRCDIR)/codecheck1.c
1035
+ $(XBCC) -o $@ $(SRCDIR)/codecheck1.c
10341036
10351037
# WARNING. DANGER. Running the test suite modifies the repository the
10361038
# build is done from, i.e. the checkout belongs to. Do not sync/push
10371039
# the repository after running the tests.
10381040
test: $(OBJDIR) $(APPNAME)
@@ -1305,26 +1307,26 @@
13051307
writeln "\t+echo. >> \$@"
13061308
writeln "\t+echo fossil >> \$@"
13071309
13081310
writeln {
13091311
translate$E: $(SRCDIR)\translate.c
1310
- $(BCC) -o$@ $**
1312
+ $(XBCC) -o$@ $**
13111313
13121314
makeheaders$E: $(SRCDIR)\makeheaders.c
1313
- $(BCC) -o$@ $**
1315
+ $(XBCC) -o$@ $**
13141316
13151317
mkindex$E: $(SRCDIR)\mkindex.c
1316
- $(BCC) -o$@ $**
1318
+ $(XBCC) -o$@ $**
13171319
13181320
mkbuiltin$E: $(SRCDIR)\mkbuiltin.c
1319
- $(BCC) -o$@ $**
1321
+ $(XBCC) -o$@ $**
13201322
13211323
mkversion$E: $(SRCDIR)\mkversion.c
1322
- $(BCC) -o$@ $**
1324
+ $(XBCC) -o$@ $**
13231325
13241326
codecheck1$E: $(SRCDIR)\codecheck1.c
1325
- $(BCC) -o$@ $**
1327
+ $(XBCC) -o$@ $**
13261328
13271329
$(OBJDIR)\shell$O : $(SRCDIR)\shell.c
13281330
$(TCC) -o$@ -c $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) $**
13291331
13301332
$(OBJDIR)\sqlite3$O : $(SRCDIR)\sqlite3.c
@@ -1827,26 +1829,26 @@
18271829
writeln {
18281830
$(OX):
18291831
@-mkdir $@
18301832
18311833
translate$E: $(SRCDIR)\translate.c
1832
- $(BCC) $**
1834
+ $(XBCC) $**
18331835
18341836
makeheaders$E: $(SRCDIR)\makeheaders.c
1835
- $(BCC) $**
1837
+ $(XBCC) $**
18361838
18371839
mkindex$E: $(SRCDIR)\mkindex.c
1838
- $(BCC) $**
1840
+ $(XBCC) $**
18391841
18401842
mkbuiltin$E: $(SRCDIR)\mkbuiltin.c
1841
- $(BCC) $**
1843
+ $(XBCC) $**
18421844
18431845
mkversion$E: $(SRCDIR)\mkversion.c
1844
- $(BCC) $**
1846
+ $(XBCC) $**
18451847
18461848
codecheck1$E: $(SRCDIR)\codecheck1.c
1847
- $(BCC) $**
1849
+ $(XBCC) $**
18481850
18491851
!if $(USE_SEE)!=0
18501852
SQLITE3_SHELL_SRC = $(SRCDIR)\shell-see.c
18511853
!else
18521854
SQLITE3_SHELL_SRC = $(SRCDIR)\shell.c
18531855
--- 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 @@
295295
/* binary search of the tag */
296296
key.text = data;
297297
key.size = i;
298298
return bsearch(&key,
299299
block_tags,
300
- (sizeof block_tags)/(sizeof block_tags[0]),
300
+ count(block_tags),
301301
sizeof block_tags[0],
302302
cmp_html_tag);
303303
}
304304
305305
306306
--- 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 @@
316316
const char *z = blob_buffer(p);
317317
int n = blob_size(p) - len + 1;
318318
assert( len==(int)strlen(mergeMarker[1]) );
319319
assert( len==(int)strlen(mergeMarker[2]) );
320320
assert( len==(int)strlen(mergeMarker[3]) );
321
- assert( sizeof(mergeMarker)/sizeof(mergeMarker[0])==4 );
321
+ assert( count(mergeMarker)==4 );
322322
for(i=0; i<n; ){
323323
for(j=0; j<4; j++){
324324
if( memcmp(&z[i], mergeMarker[j], len)==0 ) return 1;
325325
}
326326
while( i<n && z[i]!='\n' ){ i++; }
@@ -376,21 +376,21 @@
376376
377377
if( g.argc!=6 ){
378378
usage("PIVOT V1 V2 MERGED");
379379
}
380380
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]);
382382
}
383383
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]);
385385
}
386386
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]);
388388
}
389389
blob_merge(&pivot, &v1, &v2, &merged);
390390
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]);
392392
}
393393
blob_reset(&pivot);
394394
blob_reset(&v1);
395395
blob_reset(&v2);
396396
blob_reset(&merged);
397397
--- 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 @@
202202
/* Otherwise, this is a first-tier command */
203203
aEntry[nUsed].eType |= CMDFLAG_1ST_TIER;
204204
}
205205
}
206206
207
- /* Processing additional flags that might following the command name */
207
+ /* Process additional flags that might follow the command name */
208208
while( zLine[i+j]!=0 ){
209209
i += j;
210210
while( fossil_isspace(zLine[i]) ){ i++; }
211211
if( zLine[i]==0 ) break;
212212
for(j=0; zLine[i+j] && !fossil_isspace(zLine[i+j]); j++){}
@@ -223,11 +223,11 @@
223223
fprintf(stderr, "%s:%d: unknown option: '%.*s'\n",
224224
zFile, nLine, j, &zLine[i]);
225225
nErr++;
226226
}
227227
}
228
-
228
+
229229
nUsed++;
230230
}
231231
232232
/*
233233
** Check to see if the current line is an #if and if it is, add it to
234234
--- 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
--- src/mkversion.c
+++ src/mkversion.c
@@ -64,10 +64,14 @@
6464
printf("#define RELEASE_VERSION_NUMBER %s\n", z);
6565
memset(vx,0,sizeof(vx));
6666
strcpy(vx,b);
6767
d = 0;
6868
for(z=vx; z[0]; z++){
69
+ if( z[0]=='-' ){
70
+ z[0] = 0;
71
+ break;
72
+ }
6973
if( z[0]!='.' ) continue;
7074
if ( d<3 ){
7175
z[0] = ',';
7276
d++;
7377
}else{
7478
--- 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 @@
6767
"mlink", "fid",
6868
"tagxref", "srcid",
6969
"tagxref", "rid",
7070
};
7171
int i;
72
- for(i=0; i<sizeof(aTabField)/sizeof(aTabField[0]); i+=2){
72
+ for(i=0; i<count(aTabField); i+=2){
7373
if( db_exists("SELECT 1 FROM \"%w\" WHERE \"%w\"=%d",
7474
aTabField[i], aTabField[i+1], rid) ) return 1;
7575
}
7676
return 0;
7777
}
7878
--- 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 @@
10061006
char *zRange;
10071007
10081008
login_check_credentials();
10091009
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
10101010
style_header("List Of Artifacts");
1011
- style_submenu_element("250 Largest", 0, "bigbloblist");
1011
+ style_submenu_element("250 Largest", "bigbloblist");
10121012
if( !unpubOnly && mx>n && P("s")==0 ){
10131013
int i;
10141014
@ <p>Select a range of artifacts to view:</p>
10151015
@ <ul>
10161016
for(i=1; i<=mx; i+=n){
@@ -1020,11 +1020,11 @@
10201020
@ </ul>
10211021
style_footer();
10221022
return;
10231023
}
10241024
if( !unpubOnly && mx>n ){
1025
- style_submenu_element("Index", "Index", "bloblist");
1025
+ style_submenu_element("Index", "bloblist");
10261026
}
10271027
if( unpubOnly ){
10281028
zRange = mprintf("IN private");
10291029
}else{
10301030
zRange = mprintf("BETWEEN %d AND %d", s, s+n-1);
@@ -1204,11 +1204,11 @@
12041204
char *zId = aCollide[i].azHit[j];
12051205
if( zId==0 ) continue;
12061206
@ %z(href("%R/whatis/%s",zId))%h(zId)</a>
12071207
}
12081208
}
1209
- for(i=4; i<ArraySize(aCollide); i++){
1209
+ for(i=4; i<count(aCollide); i++){
12101210
for(j=0; j<aCollide[i].cnt && j<MAX_COLLIDE; j++){
12111211
fossil_free(aCollide[i].azHit[j]);
12121212
}
12131213
}
12141214
}
@@ -1220,15 +1220,15 @@
12201220
*/
12211221
void hash_collisions_webpage(void){
12221222
login_check_credentials();
12231223
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
12241224
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");
12271227
@ <h1>Hash Prefix Collisions on Check-ins</h1>
12281228
collision_report("SELECT (SELECT uuid FROM blob WHERE rid=objid)"
12291229
" FROM event WHERE event.type='ci'"
12301230
" ORDER BY 1");
12311231
@ <h1>Hash Prefix Collisions on All Artifacts</h1>
12321232
collision_report("SELECT uuid FROM blob ORDER BY 1");
12331233
style_footer();
12341234
}
12351235
--- 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 @@
158158
{ 'n', 0, 0, etSIZE, 0, 0 },
159159
{ '%', 0, 0, etPERCENT, 0, 0 },
160160
{ 'p', 16, 0, etPOINTER, 0, 1 },
161161
{ '/', 0, 0, etPATH, 0, 0 },
162162
};
163
-#define etNINFO (sizeof(fmtinfo)/sizeof(fmtinfo[0]))
163
+#define etNINFO count(fmtinfo)
164164
165165
/*
166166
** "*val" is a double such that 0.1 <= *val < 10.0
167167
** Return the ascii code for the leading digit of *val, then
168168
** multiply "*val" by 10.0 to renormalize.
@@ -875,24 +875,33 @@
875875
/*
876876
** Write to standard output or standard error.
877877
**
878878
** On windows, transform the output into the current terminal encoding
879879
** 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.
881884
*/
882885
void fossil_puts(const char *z, int toStdErr){
886
+ FILE* out = (toStdErr ? stderr : stdout);
883887
int n = (int)strlen(z);
884888
if( n==0 ) return;
889
+ assert( toStdErr==0 || toStdErr==1 );
885890
if( toStdErr==0 ) stdoutAtBOL = (z[n-1]=='\n');
886891
#if defined(_WIN32)
887892
if( fossil_utf8_to_console(z, n, toStdErr) >= 0 ){
888893
return;
889894
}
895
+ fflush(out);
896
+ _setmode(_fileno(out), _O_BINARY);
890897
#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
894903
}
895904
896905
/*
897906
** Force the standard output cursor to move to the beginning
898907
** of a line, if it is not there already.
@@ -970,11 +979,11 @@
970979
pNow->tm_hour, pNow->tm_min, pNow->tm_sec);
971980
va_start(ap, zFormat);
972981
vfprintf(out, zFormat, ap);
973982
fprintf(out, "\n");
974983
va_end(ap);
975
- for(i=0; i<sizeof(azEnv)/sizeof(azEnv[0]); i++){
984
+ for(i=0; i<count(azEnv); i++){
976985
char *p;
977986
if( (p = fossil_getenv(azEnv[i]))!=0 ){
978987
fprintf(out, "%s=%s\n", azEnv[i], p);
979988
fossil_path_free(p);
980989
}else if( (z = P(azEnv[i]))!=0 ){
981990
--- 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 @@
205205
in.i++;
206206
}
207207
if( in.i+pRe->nInit>in.mx ) return 0;
208208
}
209209
210
- if( pRe->nState<=(sizeof(aSpace)/(sizeof(aSpace[0])*2)) ){
210
+ if( pRe->nState<=count(aSpace)*2 ){
211211
pToFree = 0;
212212
aStateSet[0].aState = aSpace;
213213
}else{
214214
pToFree = fossil_malloc( sizeof(ReStateNumber)*2*pRe->nState );
215215
if( pToFree==0 ) return -1;
216216
--- 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 @@
198198
};
199199
int i;
200200
if( fossil_strncmp(zArg1, "fx_", 3)==0 ){
201201
break;
202202
}
203
- for(i=0; i<sizeof(azAllowed)/sizeof(azAllowed[0]); i++){
203
+ for(i=0; i<count(azAllowed); i++){
204204
if( fossil_stricmp(zArg1, azAllowed[i])==0 ) break;
205205
}
206
- if( i>=sizeof(azAllowed)/sizeof(azAllowed[0]) ){
206
+ if( i>=count(azAllowed) ){
207207
*(char**)pError = mprintf("access to table \"%s\" is restricted",zArg1);
208208
rc = SQLITE_DENY;
209209
}else if( !g.perm.RdAddr && strncmp(zArg2, "private_", 8)==0 ){
210210
rc = SQLITE_IGNORE;
211211
}
@@ -450,13 +450,13 @@
450450
zTitle = mprintf("Copy Of %s", zTitle);
451451
zOwner = g.zLogin;
452452
}
453453
}
454454
if( zOwner==0 ) zOwner = g.zLogin;
455
- style_submenu_element("Cancel", "Cancel", "reportlist");
455
+ style_submenu_element("Cancel", "reportlist");
456456
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);
458458
}
459459
style_header("%s", rn>0 ? "Edit Report Format":"Create New Report Format");
460460
if( zErr ){
461461
@ <blockquote class="reportError">%h(zErr)</blockquote>
462462
}
@@ -700,15 +700,14 @@
700700
pState->zWikiEnd = "";
701701
if( P("plaintext") ){
702702
pState->wikiFlags |= WIKI_LINKSONLY;
703703
pState->zWikiStart = "<pre class='verbatim'>";
704704
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);
707706
}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);
710709
}
711710
}else{
712711
pState->nCol++;
713712
}
714713
}
@@ -1197,22 +1196,20 @@
11971196
count = 0;
11981197
if( !tabs ){
11991198
struct GenerateHTML sState = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12001199
12011200
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",""));
12041202
if( g.perm.Admin
12051203
|| (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);
12071205
}
12081206
if( g.perm.TktFmt ){
1209
- style_submenu_element("SQL", "SQL", "rptsql?rn=%d",rn);
1207
+ style_submenu_element("SQL", "rptsql?rn=%d",rn);
12101208
}
12111209
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);
12141211
}
12151212
style_header("%s", zTitle);
12161213
output_color_key(zClrKey, 1,
12171214
"border=\"0\" cellpadding=\"3\" cellspacing=\"0\" class=\"report\"");
12181215
@ <table border="1" cellpadding="2" cellspacing="0" class="report"
12191216
--- 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 @@
216216
free( zFreeProjectName );
217217
}
218218
}
219219
220220
/*
221
-** COMMAND: rss
221
+** COMMAND: rss*
222222
**
223223
** Usage: %fossil rss ?OPTIONS?
224224
**
225225
** The CLI variant of the /timeline.rss page, this produces an RSS
226226
** feed of the timeline to stdout. Options:
227227
--- 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 @@
407407
408408
/* search_match(TEXT, TEXT, ....)
409409
**
410410
** Using the full-scan search engine created by the most recent call
411411
** 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.
413413
** Return non-zero on a match and zero on a miss.
414414
*/
415415
static void search_match_sqlfunc(
416416
sqlite3_context *context,
417417
int argc,
@@ -418,11 +418,11 @@
418418
sqlite3_value **argv
419419
){
420420
const char *azDoc[5];
421421
int nDoc;
422422
int rc;
423
- for(nDoc=0; nDoc<ArraySize(azDoc) && nDoc<argc; nDoc++){
423
+ for(nDoc=0; nDoc<count(azDoc) && nDoc<argc; nDoc++){
424424
azDoc[nDoc] = (const char*)sqlite3_value_text(argv[nDoc]);
425425
if( azDoc[nDoc]==0 ) azDoc[nDoc] = "";
426426
}
427427
rc = search_match(&gSearch, nDoc, azDoc);
428428
sqlite3_result_int(context, rc);
@@ -657,11 +657,11 @@
657657
};
658658
int i;
659659
if( g.perm.Read==0 ) srchFlags &= ~(SRCH_CKIN|SRCH_DOC);
660660
if( g.perm.RdTkt==0 ) srchFlags &= ~(SRCH_TKT);
661661
if( g.perm.RdWiki==0 ) srchFlags &= ~(SRCH_WIKI);
662
- for(i=0; i<ArraySize(aSetng); i++){
662
+ for(i=0; i<count(aSetng); i++){
663663
unsigned int m = aSetng[i].m;
664664
if( (srchFlags & m)==0 ) continue;
665665
if( ((knownGood|knownBad) & m)!=0 ) continue;
666666
if( db_get_boolean(aSetng[i].zKey,0) ){
667667
knownGood |= m;
@@ -892,11 +892,11 @@
892892
{ SRCH_DOC, 'd' },
893893
{ SRCH_TKT, 't' },
894894
{ SRCH_WIKI, 'w' },
895895
};
896896
int i;
897
- for(i=0; i<ArraySize(aMask); i++){
897
+ for(i=0; i<count(aMask); i++){
898898
if( srchFlags & aMask[i].m ){
899899
blob_appendf(&sql, "%sftsdocs.type='%c'", zSep, aMask[i].c);
900900
zSep = " OR ";
901901
}
902902
}
@@ -1070,11 +1070,11 @@
10701070
};
10711071
const char *zY = PD("y","all");
10721072
unsigned newFlags = srchFlags;
10731073
int i;
10741074
@ <select size='1' name='y'>
1075
- for(i=0; i<ArraySize(aY); i++){
1075
+ for(i=0; i<count(aY); i++){
10761076
if( (aY[i].m & srchFlags)==0 ) continue;
10771077
cgi_printf("<option value='%s'", aY[i].z);
10781078
if( fossil_strcmp(zY,aY[i].z)==0 ){
10791079
newFlags &= aY[i].m;
10801080
cgi_printf(" selected");
@@ -1727,17 +1727,17 @@
17271727
int iAction = 0;
17281728
db_find_and_open_repository(0, 0);
17291729
if( g.argc>2 ){
17301730
zSubCmd = g.argv[2];
17311731
n = (int)strlen(zSubCmd);
1732
- for(i=0; i<ArraySize(aCmd); i++){
1732
+ for(i=0; i<count(aCmd); i++){
17331733
if( fossil_strncmp(aCmd[i].z, zSubCmd, n)==0 ) break;
17341734
}
1735
- if( i>=ArraySize(aCmd) ){
1735
+ if( i>=count(aCmd) ){
17361736
Blob all;
17371737
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);
17391739
fossil_fatal("unknown \"%s\" - should be on of:%s",
17401740
zSubCmd, blob_str(&all));
17411741
return;
17421742
}
17431743
iCmd = aCmd[i].iCmd;
@@ -1757,11 +1757,11 @@
17571757
/* Adjust search settings */
17581758
if( iCmd==3 || iCmd==4 ){
17591759
const char *zCtrl;
17601760
if( g.argc<4 ) usage(mprintf("%s STRING",zSubCmd));
17611761
zCtrl = g.argv[3];
1762
- for(j=0; j<ArraySize(aSetng); j++){
1762
+ for(j=0; j<count(aSetng); j++){
17631763
if( strchr(zCtrl, aSetng[j].zSw[0])!=0 ){
17641764
db_set_int(aSetng[j].zSetting, iCmd-3, 0);
17651765
}
17661766
}
17671767
}
@@ -1778,11 +1778,11 @@
17781778
if( iAction>=2 ){
17791779
search_rebuild_index();
17801780
}
17811781
17821782
/* Always show the status before ending */
1783
- for(i=0; i<ArraySize(aSetng); i++){
1783
+ for(i=0; i<count(aSetng); i++){
17841784
fossil_print("%-16s %s\n", aSetng[i].zName,
17851785
db_get_boolean(aSetng[i].zSetting,0) ? "on" : "off");
17861786
}
17871787
fossil_print("%-16s %s\n", "Porter stemmer:",
17881788
db_get_boolean("search-stemmer",0) ? "on" : "off");
17891789
--- 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 @@
1919
*/
2020
#include "config.h"
2121
#include <assert.h>
2222
#include "setup.h"
2323
24
-#if INTERFACE
25
-#define ArraySize(x) (sizeof(x)/sizeof(x[0]))
26
-#endif
27
-
2824
/*
2925
** Output a single entry for a menu generated using an HTML table.
3026
** If zLink is not NULL or an empty string, then it is the page that
3127
** the menu entry will hyperlink to. If zLink is NULL or "", then
3228
** the menu entry has no hyperlink - it is disabled.
@@ -149,13 +145,13 @@
149145
if( !g.perm.Admin ){
150146
login_needed(0);
151147
return;
152148
}
153149
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");
157153
style_header("User List");
158154
@ <table border=1 cellpadding=2 cellspacing=0 class='userTable'>
159155
@ <thead><tr>
160156
@ <th>UID <th>Category
161157
@ <th>Capabilities (<a href='%R/setup_ucap_list'>key</a>)
@@ -557,11 +553,11 @@
557553
free(z2);
558554
}
559555
560556
/* Begin generating the page
561557
*/
562
- style_submenu_element("Cancel", "Cancel", "setup_ulist");
558
+ style_submenu_element("Cancel", "setup_ulist");
563559
if( uid ){
564560
style_header("Edit User %h", zLogin);
565561
}else{
566562
style_header("Add A New User");
567563
}
@@ -944,18 +940,18 @@
944940
admin_log("Set option [%q] to [%q].",
945941
zVar, iQ ? "on" : "off");
946942
iVal = iQ;
947943
}
948944
}
949
- @ <input type="checkbox" name="%s(zQParm)"
945
+ @ <label><input type="checkbox" name="%s(zQParm)"
950946
if( iVal ){
951947
@ checked="checked"
952948
}
953949
if( disabled ){
954950
@ disabled="disabled"
955951
}
956
- @ /> <b>%s(zLabel)</b>
952
+ @ /> <b>%s(zLabel)</b></label>
957953
}
958954
959955
/*
960956
** Generate an entry box for an attribute.
961957
*/
@@ -1431,11 +1427,11 @@
14311427
@ %s(zTmDiff) hours ahead of UTC.</p>
14321428
}
14331429
14341430
@ <hr />
14351431
multiple_choice_attribute("Per-Item Time Format", "timeline-date-format",
1436
- "tdf", "0", ArraySize(azTimeFormats)/2, azTimeFormats);
1432
+ "tdf", "0", count(azTimeFormats)/2, azTimeFormats);
14371433
@ <p>If the "HH:MM" or "HH:MM:SS" format is selected, then the date is shown
14381434
@ in a separate box (using CSS class "timelineDate") whenever the date changes.
14391435
@ With the "YYYY-MM-DD&nbsp;HH:MM" and "YYMMDD ..." formats, the complete date
14401436
@ and time is shown on every timeline entry (using the CSS class "timelineTime").</p>
14411437
@@ -1537,11 +1533,11 @@
15371533
@ <p>Settings marked with (v) are 'versionable' and will be overridden
15381534
@ by the contents of files named <tt>.fossil-settings/PROPERTY</tt>
15391535
@ in the check-out root.
15401536
@ If such a file is present, the corresponding field above is not
15411537
@ editable.</p><hr /><p>
1542
- @ These settings work the same as the
1538
+ @ These settings work the same as the
15431539
@ <a href='%R/help?cmd=settings'>fossil set</a> command.
15441540
db_end_transaction(0);
15451541
style_footer();
15461542
}
15471543
15481544
--- 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&nbsp;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&nbsp;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 @@
666666
#define MODE_Column 1 /* One record per line in neat columns */
667667
#define MODE_List 2 /* One record per line with a separator */
668668
#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
669669
#define MODE_Html 4 /* Generate an XHTML table */
670670
#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 */
676677
677678
static const char *modeDescr[] = {
678679
"line",
679680
"column",
680681
"list",
681682
"semi",
682683
"html",
683684
"insert",
685
+ "quote",
684686
"tcl",
685687
"csv",
686688
"explain",
687689
"ascii",
688690
"prettyprint",
@@ -1196,23 +1198,26 @@
11961198
utf8_printf(p->out, "%s", p->rowSeparator);
11971199
}
11981200
setTextMode(p->out, 1);
11991201
break;
12001202
}
1203
+ case MODE_Quote:
12011204
case MODE_Insert: {
12021205
p->cnt++;
12031206
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
+ }
12141219
for(i=0; i<nArg; i++){
12151220
char *zSep = i>0 ? ",": "";
12161221
if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
12171222
utf8_printf(p->out,"%sNULL",zSep);
12181223
}else if( aiType && aiType[i]==SQLITE_TEXT ){
@@ -1231,11 +1236,11 @@
12311236
}else{
12321237
if( zSep[0] ) utf8_printf(p->out,"%s",zSep);
12331238
output_quoted_string(p->out, azArg[i]);
12341239
}
12351240
}
1236
- raw_printf(p->out,");\n");
1241
+ raw_printf(p->out,p->cMode==MODE_Quote?"\n":");\n");
12371242
break;
12381243
}
12391244
case MODE_Ascii: {
12401245
if( p->cnt++==0 && p->showHeader ){
12411246
for(i=0; i<nArg; i++){
@@ -2175,10 +2180,11 @@
21752180
" column Left-aligned columns. (See .width)\n"
21762181
" html HTML <table> code\n"
21772182
" insert SQL insert statements for TABLE\n"
21782183
" line One value per line\n"
21792184
" list Values delimited by .separator strings\n"
2185
+ " quote Escape answers as for SQL\n"
21802186
" tabs Tab-separated values\n"
21812187
" tcl TCL list elements\n"
21822188
".nullvalue STRING Use STRING in place of NULL values\n"
21832189
".once FILENAME Output for the next SQL command only to FILENAME\n"
21842190
".open ?--new? ?FILE? Close existing database and reopen FILE\n"
@@ -3975,10 +3981,12 @@
39753981
p->mode = MODE_List;
39763982
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
39773983
}else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
39783984
p->mode = MODE_Insert;
39793985
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;
39803988
}else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
39813989
p->mode = MODE_Ascii;
39823990
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
39833991
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
39843992
}else {
39853993
--- 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 @@
317317
}
318318
style_header("Artifact Receipts");
319319
if( showAll ){
320320
ofst = 0;
321321
}else{
322
- style_submenu_element("All", "All", "rcvfromlist?all=1");
322
+ style_submenu_element("All", "rcvfromlist?all=1");
323323
}
324324
if( ofst>0 ){
325
- style_submenu_element("Newer", "Newer", "rcvfromlist?ofst=%d",
325
+ style_submenu_element("Newer", "rcvfromlist?ofst=%d",
326326
ofst>30 ? ofst-30 : 0);
327327
}
328328
db_multi_exec(
329329
"CREATE TEMP TABLE rcvidUsed(x INTEGER PRIMARY KEY);"
330330
"INSERT OR IGNORE INTO rcvidUsed(x) SELECT rcvid FROM blob;"
@@ -363,12 +363,11 @@
363363
int rcvid = db_column_int(&q, 0);
364364
const char *zUser = db_column_text(&q, 1);
365365
const char *zDate = db_column_text(&q, 2);
366366
const char *zIpAddr = db_column_text(&q, 3);
367367
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);
370369
}else{
371370
cnt++;
372371
@ <tr>
373372
if( db_column_int(&q,4) ){
374373
@ <td style="padding-right: 15px;text-align: right;">
@@ -406,19 +405,17 @@
406405
style_header("Artifact Receipt %d", rcvid);
407406
if( db_exists(
408407
"SELECT 1 FROM blob WHERE rcvid=%d AND"
409408
" NOT EXISTS (SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)", rcvid)
410409
){
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);
413411
}
414412
if( db_exists(
415413
"SELECT 1 FROM blob WHERE rcvid=%d AND"
416414
" EXISTS (SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)", rcvid)
417415
){
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);
420417
}
421418
db_prepare(&q,
422419
"SELECT login, datetime(rcvfrom.mtime), rcvfrom.ipaddr"
423420
" FROM rcvfrom LEFT JOIN user USING(uid)"
424421
" WHERE rcvid=%d",
425422
--- 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 @@
100100
Blob err = BLOB_INITIALIZER;
101101
if( strchr(zName, '/')!=0 ){
102102
zAltSkinDir = fossil_strdup(zName);
103103
return 0;
104104
}
105
- for(i=0; i<ArraySize(aBuiltinSkin); i++){
105
+ for(i=0; i<count(aBuiltinSkin); i++){
106106
if( fossil_strcmp(aBuiltinSkin[i].zLabel, zName)==0 ){
107107
pAltSkin = &aBuiltinSkin[i];
108108
return 0;
109109
}
110110
}
111111
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++){
113113
blob_append(&err, " ", 1);
114114
blob_append(&err, aBuiltinSkin[i].zLabel, -1);
115115
}
116116
return blob_str(&err);
117117
}
@@ -163,11 +163,11 @@
163163
/*
164164
** Return a pointer to a SkinDetail element. Return 0 if not found.
165165
*/
166166
static struct SkinDetail *skin_detail_find(const char *zName){
167167
int lwr = 0;
168
- int upr = ArraySize(aSkinDetail);
168
+ int upr = count(aSkinDetail);
169169
while( upr>=lwr ){
170170
int mid = (upr+lwr)/2;
171171
int c = fossil_strcmp(aSkinDetail[mid].zName, zName);
172172
if( c==0 ) return &aSkinDetail[mid];
173173
if( c<0 ){
@@ -283,11 +283,11 @@
283283
** Return true if there exists a skin name "zSkinName".
284284
*/
285285
static int skinExists(const char *zSkinName){
286286
int i;
287287
if( zSkinName==0 ) return 0;
288
- for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){
288
+ for(i=0; i<count(aBuiltinSkin); i++){
289289
if( fossil_strcmp(zSkinName, aBuiltinSkin[i].zDesc)==0 ) return 1;
290290
}
291291
return db_exists("SELECT 1 FROM config WHERE name='skin:%q'", zSkinName);
292292
}
293293
@@ -304,11 +304,11 @@
304304
char *zLabel;
305305
static const char *azType[] = { "css", "header", "footer", "details" };
306306
int i;
307307
Blob val;
308308
blob_zero(&val);
309
- for(i=0; i<sizeof(azType)/sizeof(azType[0]); i++){
309
+ for(i=0; i<count(azType); i++){
310310
if( zName ){
311311
zLabel = mprintf("skins/%s/%s.txt", zName, azType[i]);
312312
z = builtin_text(zLabel);
313313
fossil_free(zLabel);
314314
}else{
@@ -427,11 +427,11 @@
427427
login_needed(0);
428428
return;
429429
}
430430
db_begin_transaction();
431431
zCurrent = getSkin(0);
432
- for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){
432
+ for(i=0; i<count(aBuiltinSkin); i++){
433433
aBuiltinSkin[i].zSQL = getSkin(aBuiltinSkin[i].zLabel);
434434
}
435435
436436
/* Process requests to delete a user-defined skin */
437437
if( P("del1") && (zName = skinVarName(P("sn"), 1))!=0 ){
@@ -458,11 +458,11 @@
458458
int seen = 0;
459459
460460
/* Check to see if the current skin is already saved. If it is, there
461461
** is no need to create a backup */
462462
zCurrent = getSkin(0);
463
- for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){
463
+ for(i=0; i<count(aBuiltinSkin); i++){
464464
if( fossil_strcmp(aBuiltinSkin[i].zSQL, zCurrent)==0 ){
465465
seen = 1;
466466
break;
467467
}
468468
}
@@ -476,11 +476,11 @@
476476
" %Q,now())", zCurrent
477477
);
478478
}
479479
}
480480
seen = 0;
481
- for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){
481
+ for(i=0; i<count(aBuiltinSkin); i++){
482482
if( fossil_strcmp(aBuiltinSkin[i].zDesc, z)==0 ){
483483
seen = 1;
484484
zCurrent = aBuiltinSkin[i].zSQL;
485485
db_multi_exec("%s", zCurrent/*safe-for-%s*/);
486486
break;
@@ -513,11 +513,11 @@
513513
@ is restarted without the override.</p>
514514
@
515515
}
516516
@ <h2>Available Skins:</h2>
517517
@ <table border="0">
518
- for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){
518
+ for(i=0; i<count(aBuiltinSkin); i++){
519519
z = aBuiltinSkin[i].zDesc;
520520
@ <tr><td>%d(i+1).<td>%h(z)<td>&nbsp;&nbsp;<td>
521521
if( fossil_strcmp(aBuiltinSkin[i].zSQL, zCurrent)==0 ){
522522
@ (Currently In Use)
523523
seenCurrent = 1;
@@ -597,25 +597,25 @@
597597
if( !g.perm.Setup ){
598598
login_needed(0);
599599
return;
600600
}
601601
ii = atoi(PD("w","0"));
602
- if( ii<0 || ii>ArraySize(aSkinAttr) ) ii = 0;
602
+ if( ii<0 || ii>count(aSkinAttr) ) ii = 0;
603603
zBasis = PD("basis","default");
604604
zDflt = mprintf("skins/%s/%s.txt", zBasis, aSkinAttr[ii].zFile);
605605
db_begin_transaction();
606606
if( P("revert")!=0 ){
607607
db_multi_exec("DELETE FROM config WHERE name=%Q", aSkinAttr[ii].zFile);
608608
cgi_replace_parameter(aSkinAttr[ii].zFile, builtin_text(zDflt));
609609
}
610610
style_header("%s", aSkinAttr[ii].zTitle);
611
- for(j=0; j<ArraySize(aSkinAttr); j++){
611
+ for(j=0; j<count(aSkinAttr); j++){
612612
if( j==ii ) continue;
613
- style_submenu_element(aSkinAttr[j].zSubmenu, 0,
613
+ style_submenu_element(aSkinAttr[j].zSubmenu,
614614
"%R/setup_skinedit?w=%d&basis=%h",j,zBasis);
615615
}
616
- style_submenu_element("Skins", 0, "%R/setup_skin");
616
+ style_submenu_element("Skins", "%R/setup_skin");
617617
@ <form action="%s(g.zTop)/setup_skinedit" method="post"><div>
618618
login_insert_csrf_secret();
619619
@ <input type='hidden' name='w' value='%d(ii)'>
620620
@ <h2>Edit %s(aSkinAttr[ii].zTitle):</h2>
621621
zContent = textarea_attribute("", 10, 80, aSkinAttr[ii].zFile,
@@ -622,11 +622,11 @@
622622
aSkinAttr[ii].zFile, builtin_text(zDflt), 0);
623623
@ <br />
624624
@ <input type="submit" name="submit" value="Apply Changes" />
625625
@ <hr />
626626
@ Baseline: <select size='1' name='basis'>
627
- for(j=0; j<ArraySize(aBuiltinSkin); j++){
627
+ for(j=0; j<count(aBuiltinSkin); j++){
628628
cgi_printf("<option value='%h'%s>%h</option>\n",
629629
aBuiltinSkin[j].zLabel,
630630
fossil_strcmp(zBasis,aBuiltinSkin[j].zLabel)==0 ? " selected" : "",
631631
aBuiltinSkin[j].zDesc
632632
);
633633
--- 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>&nbsp;&nbsp;<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>&nbsp;&nbsp;<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 @@
11
/******************************************************************************
22
** 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
44
** single large file, the entire code can be compiled as a single translation
55
** unit. This allows many compilers to do optimizations that would not be
66
** possible if the files were compiled separately. Performance improvements
77
** of 5% or more are commonly seen when SQLite is compiled as a single
88
** translation unit.
@@ -379,13 +379,13 @@
379379
**
380380
** See also: [sqlite3_libversion()],
381381
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
382382
** [sqlite_version()] and [sqlite_source_id()].
383383
*/
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"
387387
388388
/*
389389
** CAPI3REF: Run-Time Library Version Numbers
390390
** KEYWORDS: sqlite3_version, sqlite3_sourceid
391391
**
@@ -1235,10 +1235,16 @@
12351235
** <li>[[SQLITE_FCNTL_HAS_MOVED]]
12361236
** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a
12371237
** pointer to an integer and it writes a boolean into that integer depending
12381238
** on whether or not the file has been renamed, moved, or deleted since it
12391239
** 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.
12401246
**
12411247
** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]]
12421248
** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This
12431249
** opcode causes the xFileControl method to swap the file handle with the one
12441250
** pointed to by the pArg argument. This capability is used during testing
@@ -1286,10 +1292,12 @@
12861292
#define SQLITE_FCNTL_WAL_BLOCK 24
12871293
#define SQLITE_FCNTL_ZIPVFS 25
12881294
#define SQLITE_FCNTL_RBU 26
12891295
#define SQLITE_FCNTL_VFS_POINTER 27
12901296
#define SQLITE_FCNTL_JOURNAL_POINTER 28
1297
+#define SQLITE_FCNTL_WIN32_GET_HANDLE 29
1298
+#define SQLITE_FCNTL_PDB 30
12911299
12921300
/* deprecated names */
12931301
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
12941302
#define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
12951303
#define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
@@ -2238,18 +2246,31 @@
22382246
** does not make a copy of the new main schema name string, so the application
22392247
** must ensure that the argument passed into this DBCONFIG option is unchanged
22402248
** until after the database connection closes.
22412249
** </dd>
22422250
**
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
+**
22432263
** </dl>
22442264
*/
22452265
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
22462266
#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
22472267
#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */
22482268
#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
22492269
#define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */
22502270
#define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */
2271
+#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */
22512272
22522273
22532274
/*
22542275
** CAPI3REF: Enable Or Disable Extended Result Codes
22552276
** METHOD: sqlite3
@@ -12675,11 +12696,11 @@
1267512696
#define OP_SorterData 120 /* synopsis: r[P2]=data */
1267612697
#define OP_RowKey 121 /* synopsis: r[P2]=key */
1267712698
#define OP_RowData 122 /* synopsis: r[P2]=data */
1267812699
#define OP_Rowid 123 /* synopsis: r[P2]=rowid */
1267912700
#define OP_NullRow 124
12680
-#define OP_SorterInsert 125
12701
+#define OP_SorterInsert 125 /* synopsis: key=r[P2] */
1268112702
#define OP_IdxInsert 126 /* synopsis: key=r[P2] */
1268212703
#define OP_IdxDelete 127 /* synopsis: key=r[P2@P3] */
1268312704
#define OP_Seek 128 /* synopsis: Move P3 to P1.rowid */
1268412705
#define OP_IdxRowid 129 /* synopsis: r[P2]=rowid */
1268512706
#define OP_Destroy 130
@@ -13030,11 +13051,11 @@
1303013051
int,
1303113052
int,
1303213053
int,
1303313054
void(*)(DbPage*)
1303413055
);
13035
-SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager);
13056
+SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*);
1303613057
SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
1303713058
1303813059
/* Functions used to configure a Pager object. */
1303913060
SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *);
1304013061
SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int);
@@ -13081,19 +13102,22 @@
1308113102
SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
1308213103
SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
1308313104
SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager);
1308413105
1308513106
#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*);
1308713108
SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager);
1308813109
SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager);
1308913110
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);
1309113113
# ifdef SQLITE_ENABLE_SNAPSHOT
1309213114
SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot);
1309313115
SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot);
1309413116
# endif
13117
+#else
13118
+# define sqlite3PagerUseWal(x) 0
1309513119
#endif
1309613120
1309713121
#ifdef SQLITE_ENABLE_ZIPVFS
1309813122
SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager);
1309913123
#endif
@@ -14060,10 +14084,11 @@
1406014084
#define SQLITE_QueryOnly 0x04000000 /* Disable database changes */
1406114085
#define SQLITE_VdbeEQP 0x08000000 /* Debug EXPLAIN QUERY PLAN */
1406214086
#define SQLITE_Vacuum 0x10000000 /* Currently in a VACUUM */
1406314087
#define SQLITE_CellSizeCk 0x20000000 /* Check btree cell sizes on load */
1406414088
#define SQLITE_Fts3Tokenizer 0x40000000 /* Enable fts3_tokenizer(2) */
14089
+#define SQLITE_NoCkptOnClose 0x80000000 /* No checkpoint on close()/DETACH */
1406514090
1406614091
1406714092
/*
1406814093
** Bits of the sqlite3.dbOptFlags field that are used by the
1406914094
** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
@@ -17268,10 +17293,13 @@
1726817293
#if SQLITE_DEFAULT_LOCKING_MODE
1726917294
"DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
1727017295
#endif
1727117296
#if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc)
1727217297
"DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
17298
+#endif
17299
+#if SQLITE_DIRECT_OVERFLOW_READ
17300
+ "DIRECT_OVERFLOW_READ",
1727317301
#endif
1727417302
#if SQLITE_DISABLE_DIRSYNC
1727517303
"DISABLE_DIRSYNC",
1727617304
#endif
1727717305
#if SQLITE_DISABLE_LFS
@@ -17354,10 +17382,13 @@
1735417382
#if SQLITE_ENABLE_UNLOCK_NOTIFY
1735517383
"ENABLE_UNLOCK_NOTIFY",
1735617384
#endif
1735717385
#if SQLITE_ENABLE_UPDATE_DELETE_LIMIT
1735817386
"ENABLE_UPDATE_DELETE_LIMIT",
17387
+#endif
17388
+#if defined(SQLITE_ENABLE_URI_00_ERROR)
17389
+ "ENABLE_URI_00_ERROR",
1735917390
#endif
1736017391
#if SQLITE_HAS_CODEC
1736117392
"HAS_CODEC",
1736217393
#endif
1736317394
#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
@@ -18105,12 +18136,12 @@
1810518136
UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */
1810618137
UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */
1810718138
int iNewReg; /* Register for new.* values */
1810818139
i64 iKey1; /* First key value passed to hook */
1810918140
i64 iKey2; /* Second key value passed to hook */
18110
- int iPKey; /* If not negative index of IPK column */
1811118141
Mem *aNew; /* Array of new.* values */
18142
+ Table *pTab; /* Schema object being upated */
1811218143
};
1811318144
1811418145
/*
1811518146
** Function prototypes
1811618147
*/
@@ -24598,13 +24629,12 @@
2459824629
char *zNew;
2459924630
size_t n;
2460024631
if( z==0 ){
2460124632
return 0;
2460224633
}
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);
2460624636
if( zNew ){
2460724637
memcpy(zNew, z, n);
2460824638
}
2460924639
return zNew;
2461024640
}
@@ -29127,11 +29157,11 @@
2912729157
/* 120 */ "SorterData" OpHelp("r[P2]=data"),
2912829158
/* 121 */ "RowKey" OpHelp("r[P2]=key"),
2912929159
/* 122 */ "RowData" OpHelp("r[P2]=data"),
2913029160
/* 123 */ "Rowid" OpHelp("r[P2]=rowid"),
2913129161
/* 124 */ "NullRow" OpHelp(""),
29132
- /* 125 */ "SorterInsert" OpHelp(""),
29162
+ /* 125 */ "SorterInsert" OpHelp("key=r[P2]"),
2913329163
/* 126 */ "IdxInsert" OpHelp("key=r[P2]"),
2913429164
/* 127 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
2913529165
/* 128 */ "Seek" OpHelp("Move P3 to P1.rowid"),
2913629166
/* 129 */ "IdxRowid" OpHelp("r[P2]=rowid"),
2913729167
/* 130 */ "Destroy" OpHelp(""),
@@ -40674,10 +40704,16 @@
4067440704
a[1] = winIoerrRetryDelay;
4067540705
}
4067640706
OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
4067740707
return SQLITE_OK;
4067840708
}
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
+ }
4067940715
#ifdef SQLITE_TEST
4068040716
case SQLITE_FCNTL_WIN32_SET_HANDLE: {
4068140717
LPHANDLE phFile = (LPHANDLE)pArg;
4068240718
HANDLE hOldFile = pFile->h;
4068340719
pFile->h = *phFile;
@@ -44715,11 +44751,11 @@
4471544751
szBulk = pCache->szAlloc * (i64)pcache1.nInitPage;
4471644752
}else{
4471744753
szBulk = -1024 * (i64)pcache1.nInitPage;
4471844754
}
4471944755
if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){
44720
- szBulk = pCache->szAlloc*pCache->nMax;
44756
+ szBulk = pCache->szAlloc*(i64)pCache->nMax;
4472144757
}
4472244758
zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
4472344759
sqlite3EndBenignMalloc();
4472444760
if( zBulk ){
4472544761
int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
@@ -46249,21 +46285,21 @@
4624946285
#define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */
4625046286
4625146287
#ifdef SQLITE_OMIT_WAL
4625246288
# define sqlite3WalOpen(x,y,z) 0
4625346289
# define sqlite3WalLimit(x,y)
46254
-# define sqlite3WalClose(w,x,y,z) 0
46290
+# define sqlite3WalClose(v,w,x,y,z) 0
4625546291
# define sqlite3WalBeginReadTransaction(y,z) 0
4625646292
# define sqlite3WalEndReadTransaction(z)
4625746293
# define sqlite3WalDbsize(y) 0
4625846294
# define sqlite3WalBeginWriteTransaction(y) 0
4625946295
# define sqlite3WalEndWriteTransaction(x) 0
4626046296
# define sqlite3WalUndo(x,y,z) 0
4626146297
# define sqlite3WalSavepoint(y,z)
4626246298
# define sqlite3WalSavepointUndo(y,z) 0
4626346299
# 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
4626546301
# define sqlite3WalCallback(z) 0
4626646302
# define sqlite3WalExclusiveMode(y,z) 0
4626746303
# define sqlite3WalHeapMemory(z) 0
4626846304
# define sqlite3WalFramesize(z) 0
4626946305
# define sqlite3WalFindFrame(x,y,z) 0
@@ -46277,11 +46313,11 @@
4627746313
*/
4627846314
typedef struct Wal Wal;
4627946315
4628046316
/* Open and close a connection to a write-ahead log. */
4628146317
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 *);
4628346319
4628446320
/* Set the limiting size of a WAL file. */
4628546321
SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64);
4628646322
4628746323
/* Used by readers to open (lock) and close (unlock) a snapshot. A
@@ -46320,10 +46356,11 @@
4632046356
SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int);
4632146357
4632246358
/* Copy pages from the log to the database file */
4632346359
SQLITE_PRIVATE int sqlite3WalCheckpoint(
4632446360
Wal *pWal, /* Write-ahead log connection */
46361
+ sqlite3 *db, /* Check this handle's interrupt flag */
4632546362
int eMode, /* One of PASSIVE, FULL and RESTART */
4632646363
int (*xBusy)(void*), /* Function to call when busy */
4632746364
void *pBusyArg, /* Context argument for xBusyHandler */
4632846365
int sync_flags, /* Flags to sync db file with (or 0) */
4632946366
int nBuf, /* Size of buffer nBuf */
@@ -47164,13 +47201,14 @@
4716447201
/*
4716547202
** Return true if this pager uses a write-ahead log instead of the usual
4716647203
** rollback journal. Otherwise false.
4716747204
*/
4716847205
#ifndef SQLITE_OMIT_WAL
47169
-static int pagerUseWal(Pager *pPager){
47206
+SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager){
4717047207
return (pPager->pWal!=0);
4717147208
}
47209
+# define pagerUseWal(x) sqlite3PagerUseWal(x)
4717247210
#else
4717347211
# define pagerUseWal(x) 0
4717447212
# define pagerRollbackWal(x) 0
4717547213
# define pagerWalFrames(v,w,x,y) 0
4717647214
# define pagerOpenWalIfPresent(z) SQLITE_OK
@@ -50368,21 +50406,22 @@
5036850406
** This function always succeeds. If a transaction is active an attempt
5036950407
** is made to roll it back. If an error occurs during the rollback
5037050408
** a hot journal may be left in the filesystem but no error is returned
5037150409
** to the caller.
5037250410
*/
50373
-SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
50411
+SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){
5037450412
u8 *pTmp = (u8 *)pPager->pTmpSpace;
5037550413
50414
+ assert( db || pagerUseWal(pPager)==0 );
5037650415
assert( assert_pager_state(pPager) );
5037750416
disable_simulated_io_errors();
5037850417
sqlite3BeginBenignMalloc();
5037950418
pagerFreeMapHdrs(pPager);
5038050419
/* pPager->errCode = 0; */
5038150420
pPager->exclusiveMode = 0;
5038250421
#ifndef SQLITE_OMIT_WAL
50383
- sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp);
50422
+ sqlite3WalClose(pPager->pWal,db,pPager->ckptSyncFlags,pPager->pageSize,pTmp);
5038450423
pPager->pWal = 0;
5038550424
#endif
5038650425
pager_reset(pPager);
5038750426
if( MEMDB ){
5038850427
pager_unlock(pPager);
@@ -53541,14 +53580,20 @@
5354153580
** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint()
5354253581
** or wal_blocking_checkpoint() API functions.
5354353582
**
5354453583
** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
5354553584
*/
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
+){
5354753592
int rc = SQLITE_OK;
5354853593
if( pPager->pWal ){
53549
- rc = sqlite3WalCheckpoint(pPager->pWal, eMode,
53594
+ rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode,
5355053595
(eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
5355153596
pPager->pBusyHandlerArg,
5355253597
pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
5355353598
pnLog, pnCkpt
5355453599
);
@@ -53676,11 +53721,11 @@
5367653721
** Before closing the log file, this function attempts to take an
5367753722
** EXCLUSIVE lock on the database file. If this cannot be obtained, an
5367853723
** error (SQLITE_BUSY) is returned and the log connection is not closed.
5367953724
** If successful, the EXCLUSIVE lock is not released before returning.
5368053725
*/
53681
-SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){
53726
+SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){
5368253727
int rc = SQLITE_OK;
5368353728
5368453729
assert( pPager->journalMode==PAGER_JOURNALMODE_WAL );
5368553730
5368653731
/* If the log file is not already open, but does exist in the file-system,
@@ -53704,11 +53749,11 @@
5370453749
** the database file, the log and log-summary files will be deleted.
5370553750
*/
5370653751
if( rc==SQLITE_OK && pPager->pWal ){
5370753752
rc = pagerExclusiveLock(pPager);
5370853753
if( rc==SQLITE_OK ){
53709
- rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags,
53754
+ rc = sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags,
5371053755
pPager->pageSize, (u8*)pPager->pTmpSpace);
5371153756
pPager->pWal = 0;
5371253757
pagerFixMaplimit(pPager);
5371353758
if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK);
5371453759
}
@@ -55487,10 +55532,11 @@
5548755532
** checkpoint is running (in any other thread or process) at the same
5548855533
** time.
5548955534
*/
5549055535
static int walCheckpoint(
5549155536
Wal *pWal, /* Wal connection */
55537
+ sqlite3 *db, /* Check for interrupts on this handle */
5549255538
int eMode, /* One of PASSIVE, FULL or RESTART */
5549355539
int (*xBusy)(void*), /* Function to call when busy */
5549455540
void *pBusyArg, /* Context argument for xBusyHandler */
5549555541
int sync_flags, /* Flags for OsSync() (or 0) */
5549655542
u8 *zBuf /* Temporary buffer to use */
@@ -55581,10 +55627,14 @@
5558155627
5558255628
/* Iterate through the contents of the WAL, copying data to the db file */
5558355629
while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
5558455630
i64 iOffset;
5558555631
assert( walFramePgno(pWal, iFrame)==iDbpage );
55632
+ if( db->u1.isInterrupted ){
55633
+ rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
55634
+ break;
55635
+ }
5558655636
if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){
5558755637
continue;
5558855638
}
5558955639
iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE;
5559055640
/* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */
@@ -55685,10 +55735,11 @@
5568555735
/*
5568655736
** Close a connection to a log file.
5568755737
*/
5568855738
SQLITE_PRIVATE int sqlite3WalClose(
5568955739
Wal *pWal, /* Wal to close */
55740
+ sqlite3 *db, /* For interrupt flag */
5569055741
int sync_flags, /* Flags to pass to OsSync() (or 0) */
5569155742
int nBuf,
5569255743
u8 *zBuf /* Buffer of at least nBuf bytes */
5569355744
){
5569455745
int rc = SQLITE_OK;
@@ -55701,17 +55752,18 @@
5570155752
** the database. In this case checkpoint the database and unlink both
5570255753
** the wal and wal-index files.
5570355754
**
5570455755
** The EXCLUSIVE lock is not released before returning.
5570555756
*/
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
+ ){
5570855760
if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
5570955761
pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
5571055762
}
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
5571355765
);
5571455766
if( rc==SQLITE_OK ){
5571555767
int bPersist = -1;
5571655768
sqlite3OsFileControlHint(
5571755769
pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersist
@@ -56955,10 +57007,11 @@
5695557007
** If parameter xBusy is not NULL, it is a pointer to a busy-handler
5695657008
** callback. In this case this function runs a blocking checkpoint.
5695757009
*/
5695857010
SQLITE_PRIVATE int sqlite3WalCheckpoint(
5695957011
Wal *pWal, /* Wal connection */
57012
+ sqlite3 *db, /* Check this handle's interrupt flag */
5696057013
int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */
5696157014
int (*xBusy)(void*), /* Function to call when busy */
5696257015
void *pBusyArg, /* Context argument for xBusyHandler */
5696357016
int sync_flags, /* Flags to sync db file with (or 0) */
5696457017
int nBuf, /* Size of temporary buffer */
@@ -57029,11 +57082,11 @@
5702957082
if( rc==SQLITE_OK ){
5703057083
5703157084
if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
5703257085
rc = SQLITE_CORRUPT_BKPT;
5703357086
}else{
57034
- rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf);
57087
+ rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf);
5703557088
}
5703657089
5703757090
/* If no error occurred, set the output variables. */
5703857091
if( rc==SQLITE_OK || rc==SQLITE_BUSY ){
5703957092
if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame;
@@ -60619,23 +60672,30 @@
6061960672
*ppBtree = p;
6062060673
6062160674
btree_open_out:
6062260675
if( rc!=SQLITE_OK ){
6062360676
if( pBt && pBt->pPager ){
60624
- sqlite3PagerClose(pBt->pPager);
60677
+ sqlite3PagerClose(pBt->pPager, 0);
6062560678
}
6062660679
sqlite3_free(pBt);
6062760680
sqlite3_free(p);
6062860681
*ppBtree = 0;
6062960682
}else{
60683
+ sqlite3_file *pFile;
60684
+
6063060685
/* If the B-Tree was successfully opened, set the pager-cache size to the
6063160686
** default value. Except, when opening on an existing shared pager-cache,
6063260687
** do not change the pager-cache size.
6063360688
*/
6063460689
if( sqlite3BtreeSchema(p, 0, 0)==0 ){
6063560690
sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE);
6063660691
}
60692
+
60693
+ pFile = sqlite3PagerFile(pBt->pPager);
60694
+ if( pFile->pMethods ){
60695
+ sqlite3OsFileControlHint(pFile, SQLITE_FCNTL_PDB, (void*)&pBt->db);
60696
+ }
6063760697
}
6063860698
if( mutexOpen ){
6063960699
assert( sqlite3_mutex_held(mutexOpen) );
6064060700
sqlite3_mutex_leave(mutexOpen);
6064160701
}
@@ -60761,11 +60821,11 @@
6076160821
** it without having to hold the mutex.
6076260822
**
6076360823
** Clean out and delete the BtShared object.
6076460824
*/
6076560825
assert( !pBt->pCursor );
60766
- sqlite3PagerClose(pBt->pPager);
60826
+ sqlite3PagerClose(pBt->pPager, p->db);
6076760827
if( pBt->xFreeSchema && pBt->pSchema ){
6076860828
pBt->xFreeSchema(pBt->pSchema);
6076960829
}
6077060830
sqlite3DbFree(0, pBt->pSchema);
6077160831
freeTempSpace(pBt);
@@ -62825,11 +62885,11 @@
6282562885
if( (eOp&0x01)==0 /* (1) */
6282662886
&& offset==0 /* (2) */
6282762887
&& (bEnd || a==ovflSize) /* (6) */
6282862888
&& pBt->inTransaction==TRANS_READ /* (4) */
6282962889
&& (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */
62830
- && pBt->pPage1->aData[19]==0x01 /* (5) */
62890
+ && 0==sqlite3PagerUseWal(pBt->pPager) /* (5) */
6283162891
&& &pBuf[-4]>=pBufStart /* (7) */
6283262892
){
6283362893
u8 aSave[4];
6283462894
u8 *aWrite = &pBuf[-4];
6283562895
assert( aWrite>=pBufStart ); /* hence (7) */
@@ -63081,13 +63141,16 @@
6308163141
}
6308263142
sqlite3BtreeClearCursor(pCur);
6308363143
}
6308463144
6308563145
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;
6308963152
}
6309063153
}else if( pCur->pgnoRoot==0 ){
6309163154
pCur->eState = CURSOR_INVALID;
6309263155
return SQLITE_OK;
6309363156
}else{
@@ -63094,11 +63157,11 @@
6309463157
assert( pCur->iPage==(-1) );
6309563158
rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0],
6309663159
0, pCur->curPagerFlags);
6309763160
if( rc!=SQLITE_OK ){
6309863161
pCur->eState = CURSOR_INVALID;
63099
- return rc;
63162
+ return rc;
6310063163
}
6310163164
pCur->iPage = 0;
6310263165
pCur->curIntKey = pCur->apPage[0]->intKey;
6310363166
}
6310463167
pRoot = pCur->apPage[0];
@@ -63117,14 +63180,16 @@
6311763180
assert( pRoot->intKey==1 || pRoot->intKey==0 );
6311863181
if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){
6311963182
return SQLITE_CORRUPT_BKPT;
6312063183
}
6312163184
63185
+skip_init:
6312263186
pCur->aiIdx[0] = 0;
6312363187
pCur->info.nSize = 0;
6312463188
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl);
6312563189
63190
+ pRoot = pCur->apPage[0];
6312663191
if( pRoot->nCell>0 ){
6312763192
pCur->eState = CURSOR_VALID;
6312863193
}else if( !pRoot->leaf ){
6312963194
Pgno subpage;
6313063195
if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT;
@@ -67701,11 +67766,11 @@
6770167766
BtShared *pBt = p->pBt;
6770267767
sqlite3BtreeEnter(p);
6770367768
if( pBt->inTransaction!=TRANS_NONE ){
6770467769
rc = SQLITE_LOCKED;
6770567770
}else{
67706
- rc = sqlite3PagerCheckpoint(pBt->pPager, eMode, pnLog, pnCkpt);
67771
+ rc = sqlite3PagerCheckpoint(pBt->pPager, p->db, eMode, pnLog, pnCkpt);
6770767772
}
6770867773
sqlite3BtreeLeave(p);
6770967774
}
6771067775
return rc;
6771167776
}
@@ -69336,11 +69401,11 @@
6933669401
switch( aff ){
6933769402
case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */
6933869403
if( (pMem->flags & MEM_Blob)==0 ){
6933969404
sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding);
6934069405
assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
69341
- MemSetTypeFlag(pMem, MEM_Blob);
69406
+ if( pMem->flags & MEM_Str ) MemSetTypeFlag(pMem, MEM_Blob);
6934269407
}else{
6934369408
pMem->flags &= ~(MEM_TypeMask&~MEM_Blob);
6934469409
}
6934569410
break;
6934669411
}
@@ -75076,11 +75141,11 @@
7507675141
preupdate.keyinfo.enc = ENC(db);
7507775142
preupdate.keyinfo.nField = pTab->nCol;
7507875143
preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder;
7507975144
preupdate.iKey1 = iKey1;
7508075145
preupdate.iKey2 = iKey2;
75081
- preupdate.iPKey = pTab->iPKey;
75146
+ preupdate.pTab = pTab;
7508275147
7508375148
db->pPreUpdate = &preupdate;
7508475149
db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2);
7508575150
db->pPreUpdate = 0;
7508675151
sqlite3DbFree(db, preupdate.aRecord);
@@ -76808,13 +76873,18 @@
7680876873
}
7680976874
7681076875
if( iIdx>=p->pUnpacked->nField ){
7681176876
*ppValue = (sqlite3_value *)columnNullValue();
7681276877
}else{
76878
+ Mem *pMem = *ppValue = &p->pUnpacked->aMem[iIdx];
7681376879
*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
+ }
7681676886
}
7681776887
}
7681876888
7681976889
preupdate_old_out:
7682076890
sqlite3Error(db, rc);
@@ -76887,11 +76957,11 @@
7688776957
}
7688876958
if( iIdx>=pUnpack->nField ){
7688976959
pMem = (sqlite3_value *)columnNullValue();
7689076960
}else{
7689176961
pMem = &pUnpack->aMem[iIdx];
76892
- if( iIdx==p->iPKey ){
76962
+ if( iIdx==p->pTab->iPKey ){
7689376963
sqlite3VdbeMemSetInt64(pMem, p->iKey2);
7689476964
}
7689576965
}
7689676966
}else{
7689776967
/* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required
@@ -76908,11 +76978,11 @@
7690876978
}
7690976979
}
7691076980
assert( iIdx>=0 && iIdx<p->pCsr->nField );
7691176981
pMem = &p->aNew[iIdx];
7691276982
if( pMem->flags==0 ){
76913
- if( iIdx==p->iPKey ){
76983
+ if( iIdx==p->pTab->iPKey ){
7691476984
sqlite3VdbeMemSetInt64(pMem, p->iKey2);
7691576985
}else{
7691676986
rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]);
7691776987
if( rc!=SQLITE_OK ) goto preupdate_new_out;
7691876988
}
@@ -79286,12 +79356,11 @@
7928679356
** or not both operands are null.
7928779357
*/
7928879358
assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
7928979359
assert( (flags1 & MEM_Cleared)==0 );
7929079360
assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 );
79291
- if( (flags1&MEM_Null)!=0
79292
- && (flags3&MEM_Null)!=0
79361
+ if( (flags1&flags3&MEM_Null)!=0
7929379362
&& (flags3&MEM_Cleared)==0
7929479363
){
7929579364
res = 0; /* Operands are equal */
7929679365
}else{
7929779366
res = 1; /* Operands are not equal */
@@ -81554,11 +81623,11 @@
8155481623
8155581624
REGISTER_TRACE(pOp->p3, pMem);
8155681625
sqlite3VdbeMemIntegerify(pMem);
8155781626
assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */
8155881627
if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){
81559
- rc = SQLITE_FULL; /* IMP: R-12275-61338 */
81628
+ rc = SQLITE_FULL; /* IMP: R-17817-00630 */
8156081629
goto abort_due_to_error;
8156181630
}
8156281631
if( v<pMem->u.i+1 ){
8156381632
v = pMem->u.i + 1;
8156481633
}
@@ -82321,10 +82390,17 @@
8232182390
** This flag avoids doing an extra seek.
8232282391
**
8232382392
** This instruction only works for indices. The equivalent instruction
8232482393
** for tables is OP_Insert.
8232582394
*/
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
+*/
8232682402
case OP_SorterInsert: /* in2 */
8232782403
case OP_IdxInsert: { /* in2 */
8232882404
VdbeCursor *pC;
8232982405
BtreePayload x;
8233082406
@@ -83549,11 +83625,11 @@
8354983625
/* If leaving WAL mode, close the log file. If successful, the call
8355083626
** to PagerCloseWal() checkpoints and deletes the write-ahead-log
8355183627
** file. An EXCLUSIVE lock may still be held on the database file
8355283628
** after a successful return.
8355383629
*/
83554
- rc = sqlite3PagerCloseWal(pPager);
83630
+ rc = sqlite3PagerCloseWal(pPager, db);
8355583631
if( rc==SQLITE_OK ){
8355683632
sqlite3PagerSetJournalMode(pPager, eNew);
8355783633
}
8355883634
}else if( eOld==PAGER_JOURNALMODE_MEMORY ){
8355983635
/* Cannot transition directly from MEMORY to WAL. Use mode OFF
@@ -88812,11 +88888,10 @@
8881288888
const char *zId; /* The function name. */
8881388889
FuncDef *pDef; /* Information about the function */
8881488890
u8 enc = ENC(pParse->db); /* The database encoding */
8881588891
8881688892
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
88817
-// notValid(pParse, pNC, "functions", NC_PartIdx);
8881888893
zId = pExpr->u.zToken;
8881988894
nId = sqlite3Strlen30(zId);
8882088895
pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0);
8882188896
if( pDef==0 ){
8882288897
pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0);
@@ -94293,15 +94368,14 @@
9429394368
&& (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab)
9429494369
|| sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) )
9429594370
){
9429694371
return 1;
9429794372
}
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;
9430394377
}
9430494378
return 0;
9430594379
}
9430694380
9430794381
/*
@@ -122355,11 +122429,11 @@
122355122429
}
122356122430
#endif
122357122431
122358122432
sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size);
122359122433
sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0));
122360
- sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF);
122434
+ sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF|PAGER_CACHESPILL);
122361122435
122362122436
/* Begin a transaction and take an exclusive lock on the main database
122363122437
** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below,
122364122438
** to ensure that we do not try to change the page-size on a WAL database.
122365122439
*/
@@ -124663,11 +124737,10 @@
124663124737
**
124664124738
** * the comparison will be performed with no affinity, or
124665124739
** * the affinity change in zAff is guaranteed not to change the value.
124666124740
*/
124667124741
static void updateRangeAffinityStr(
124668
- Parse *pParse, /* Parse context */
124669124742
Expr *pRight, /* RHS of comparison */
124670124743
int n, /* Number of vector elements in comparison */
124671124744
char *zAff /* Affinity string to modify */
124672124745
){
124673124746
int i;
@@ -125749,15 +125822,15 @@
125749125822
assert( (bRev & ~1)==0 );
125750125823
pLevel->iLikeRepCntr <<=1;
125751125824
pLevel->iLikeRepCntr |= bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC);
125752125825
}
125753125826
#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
+ }
125759125832
}
125760125833
}
125761125834
assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 );
125762125835
125763125836
/* If we are doing a reverse order scan on an ascending index, or
@@ -125803,11 +125876,11 @@
125803125876
){
125804125877
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
125805125878
VdbeCoverage(v);
125806125879
}
125807125880
if( zStartAff ){
125808
- updateRangeAffinityStr(pParse, pRight, nBtm, &zStartAff[nEq]);
125881
+ updateRangeAffinityStr(pRight, nBtm, &zStartAff[nEq]);
125809125882
}
125810125883
nConstraint += nBtm;
125811125884
testcase( pRangeStart->wtFlags & TERM_VIRTUAL );
125812125885
if( sqlite3ExprIsVector(pRight)==0 ){
125813125886
disableTerm(pLevel, pRangeStart);
@@ -125853,11 +125926,11 @@
125853125926
){
125854125927
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
125855125928
VdbeCoverage(v);
125856125929
}
125857125930
if( zEndAff ){
125858
- updateRangeAffinityStr(pParse, pRight, nTop, zEndAff);
125931
+ updateRangeAffinityStr(pRight, nTop, zEndAff);
125859125932
codeApplyAffinity(pParse, regBase+nEq, nTop, zEndAff);
125860125933
}else{
125861125934
assert( pParse->db->mallocFailed );
125862125935
}
125863125936
nConstraint += nTop;
@@ -127539,10 +127612,11 @@
127539127612
Expr *pNew;
127540127613
Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i);
127541127614
Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i);
127542127615
127543127616
pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight, 0);
127617
+ transferJoinMarkings(pNew, pExpr);
127544127618
idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC);
127545127619
exprAnalyze(pSrc, pWC, idxNew);
127546127620
}
127547127621
pTerm = &pWC->a[idxTerm];
127548127622
pTerm->wtFlags = TERM_CODED|TERM_VIRTUAL; /* Disable the original */
@@ -127980,15 +128054,17 @@
127980128054
Expr *pX; /* An expression being tested */
127981128055
WhereClause *pWC; /* Shorthand for pScan->pWC */
127982128056
WhereTerm *pTerm; /* The term being tested */
127983128057
int k = pScan->k; /* Where to start scanning */
127984128058
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){
127987128062
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{
127990128066
for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
127991128067
if( pTerm->leftCursor==iCur
127992128068
&& pTerm->u.leftColumn==iColumn
127993128069
&& (iColumn!=XN_EXPR
127994128070
|| sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0)
@@ -128034,19 +128110,21 @@
128034128110
&& pX->iColumn==pScan->aiColumn[0]
128035128111
){
128036128112
testcase( pTerm->eOperator & WO_IS );
128037128113
continue;
128038128114
}
128115
+ pScan->pWC = pWC;
128039128116
pScan->k = k+1;
128040128117
return pTerm;
128041128118
}
128042128119
}
128043128120
}
128044
- pScan->pWC = pScan->pWC->pOuter;
128121
+ pWC = pWC->pOuter;
128045128122
k = 0;
128046
- }
128047
- pScan->pWC = pScan->pOrigWC;
128123
+ }while( pWC!=0 );
128124
+ if( pScan->iEquiv>=pScan->nEquiv ) break;
128125
+ pWC = pScan->pOrigWC;
128048128126
k = 0;
128049128127
pScan->iEquiv++;
128050128128
}
128051128129
return 0;
128052128130
}
@@ -128076,28 +128154,28 @@
128076128154
int iCur, /* Cursor to scan for */
128077128155
int iColumn, /* Column to scan for */
128078128156
u32 opMask, /* Operator(s) to scan for */
128079128157
Index *pIdx /* Must be compatible with this index */
128080128158
){
128081
- int j = 0;
128082
-
128083
- /* memset(pScan, 0, sizeof(*pScan)); */
128084128159
pScan->pOrigWC = pWC;
128085128160
pScan->pWC = pWC;
128086128161
pScan->pIdxExpr = 0;
128162
+ pScan->idxaff = 0;
128163
+ pScan->zCollName = 0;
128087128164
if( pIdx ){
128088
- j = iColumn;
128165
+ int j = iColumn;
128089128166
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;
128099128177
}
128100128178
pScan->opMask = opMask;
128101128179
pScan->k = 0;
128102128180
pScan->aiCur[0] = iCur;
128103128181
pScan->aiColumn[0] = iColumn;
@@ -130005,11 +130083,11 @@
130005130083
** CREATE INDEX ... ON (a, b, c, d, e)
130006130084
**
130007130085
** then this function would be invoked with nEq=1. The value returned in
130008130086
** this case is 3.
130009130087
*/
130010
-int whereRangeVectorLen(
130088
+static int whereRangeVectorLen(
130011130089
Parse *pParse, /* Parsing context */
130012130090
int iCur, /* Cursor open on pIdx */
130013130091
Index *pIdx, /* The index to be used for a inequality constraint */
130014130092
int nEq, /* Number of prior equality constraints on same index */
130015130093
WhereTerm *pTerm /* The vector inequality constraint */
@@ -131451,11 +131529,11 @@
131451131529
if( rev ) *pRevMask |= MASKBIT(iLoop);
131452131530
revSet = 1;
131453131531
}
131454131532
}
131455131533
if( isMatch ){
131456
- if( iColumn<0 ){
131534
+ if( iColumn==XN_ROWID ){
131457131535
testcase( distinctColumns==0 );
131458131536
distinctColumns = 1;
131459131537
}
131460131538
obSat |= MASKBIT(i);
131461131539
}else{
@@ -131906,17 +131984,24 @@
131906131984
}else{
131907131985
pWInfo->nOBSat = pFrom->isOrdered;
131908131986
pWInfo->revMask = pFrom->revLoop;
131909131987
if( pWInfo->nOBSat<=0 ){
131910131988
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,
131914131996
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
+ }
131918132003
}
131919132004
}
131920132005
}
131921132006
}
131922132007
if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP)
@@ -132635,17 +132720,19 @@
132635132720
pLevel->addrLikeRep);
132636132721
VdbeCoverage(v);
132637132722
}
132638132723
#endif
132639132724
if( pLevel->iLeftJoin ){
132725
+ int ws = pLoop->wsFlags;
132640132726
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 ){
132644132729
sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor);
132645132730
}
132646
- if( pLoop->wsFlags & WHERE_INDEXED ){
132731
+ if( (ws & WHERE_INDEXED)
132732
+ || ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx)
132733
+ ){
132647132734
sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
132648132735
}
132649132736
if( pLevel->op==OP_Return ){
132650132737
sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst);
132651132738
}else{
@@ -138607,10 +138694,11 @@
138607138694
} aFlagOp[] = {
138608138695
{ SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys },
138609138696
{ SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger },
138610138697
{ SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer },
138611138698
{ SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension },
138699
+ { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose },
138612138700
};
138613138701
unsigned int i;
138614138702
rc = SQLITE_ERROR; /* IMP: R-42790-23372 */
138615138703
for(i=0; i<ArraySize(aFlagOp); i++){
138616138704
if( aFlagOp[i].op==op ){
@@ -139903,10 +139991,17 @@
139903139991
db->busyHandler.nBusy = 0;
139904139992
rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt);
139905139993
sqlite3Error(db, rc);
139906139994
}
139907139995
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
+
139908140003
sqlite3_mutex_leave(db->mutex);
139909140004
return rc;
139910140005
#endif
139911140006
}
139912140007
@@ -140405,10 +140500,11 @@
140405140500
int octet = (sqlite3HexToInt(zUri[iIn++]) << 4);
140406140501
octet += sqlite3HexToInt(zUri[iIn++]);
140407140502
140408140503
assert( octet>=0 && octet<256 );
140409140504
if( octet==0 ){
140505
+#ifndef SQLITE_ENABLE_URI_00_ERROR
140410140506
/* This branch is taken when "%00" appears within the URI. In this
140411140507
** case we ignore all text in the remainder of the path, name or
140412140508
** value currently being parsed. So ignore the current character
140413140509
** and skip to the next "?", "=" or "&", as appropriate. */
140414140510
while( (c = zUri[iIn])!=0 && c!='#'
@@ -140417,10 +140513,16 @@
140417140513
&& (eState!=2 || c!='&')
140418140514
){
140419140515
iIn++;
140420140516
}
140421140517
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
140422140524
}
140423140525
c = octet;
140424140526
}else if( eState==1 && (c=='&' || c=='=') ){
140425140527
if( zFile[iOut-1]==0 ){
140426140528
/* An empty option name. Ignore this option altogether. */
@@ -164296,14 +164398,16 @@
164296164398
char *zSql;
164297164399
sqlite3_stmt *p;
164298164400
int rc;
164299164401
i64 nRow = 0;
164300164402
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 ){
164303164407
pRtree->nRowEst = RTREE_DEFAULT_ROWEST;
164304
- return SQLITE_OK;
164408
+ return rc==SQLITE_ERROR ? SQLITE_OK : rc;
164305164409
}
164306164410
zSql = sqlite3_mprintf(zFmt, pRtree->zDb, pRtree->zName);
164307164411
if( zSql==0 ){
164308164412
rc = SQLITE_NOMEM;
164309164413
}else{
@@ -165200,11 +165304,11 @@
165200165304
** of the locale to use. Passing an empty string ("") or SQL NULL value
165201165305
** as the second argument is the same as invoking the 1 argument version
165202165306
** of upper() or lower().
165203165307
**
165204165308
** lower('I', 'en_us') -> 'i'
165205
-** lower('I', 'tr_tr') -> 'ı' (small dotless i)
165309
+** lower('I', 'tr_tr') -> '\u131' (small dotless i)
165206165310
**
165207165311
** http://www.icu-project.org/userguide/posix.html#case_mappings
165208165312
*/
165209165313
static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
165210165314
const UChar *zInput; /* Pointer to input string */
@@ -181496,10 +181600,13 @@
181496181600
int nToken, /* Size of token in bytes */
181497181601
int iStartOff, /* Start offset of token */
181498181602
int iEndOff /* End offset of token */
181499181603
){
181500181604
int rc = SQLITE_OK;
181605
+
181606
+ UNUSED_PARAM2(pToken, nToken);
181607
+ UNUSED_PARAM(iEndOff);
181501181608
181502181609
if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){
181503181610
Fts5SFinder *p = (Fts5SFinder*)pContext;
181504181611
if( p->iPos>0 ){
181505181612
int i;
@@ -181652,11 +181759,10 @@
181652181759
for(jj=0; jj<(sFinder.nFirst-1); jj++){
181653181760
if( sFinder.aFirst[jj+1]>io ) break;
181654181761
}
181655181762
181656181763
if( sFinder.aFirst[jj]<io ){
181657
- int nScore;
181658181764
memset(aSeen, 0, nPhrase);
181659181765
rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i,
181660181766
sFinder.aFirst[jj], nToken, &nScore, 0
181661181767
);
181662181768
@@ -195587,11 +195693,11 @@
195587195693
int nArg, /* Number of args */
195588195694
sqlite3_value **apUnused /* Function arguments */
195589195695
){
195590195696
assert( nArg==0 );
195591195697
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);
195593195699
}
195594195700
195595195701
static int fts5Init(sqlite3 *db){
195596195702
static const sqlite3_module fts5Mod = {
195597195703
/* iVersion */ 2,
195598195704
--- 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 @@
119119
**
120120
** See also: [sqlite3_libversion()],
121121
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
122122
** [sqlite_version()] and [sqlite_source_id()].
123123
*/
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"
127127
128128
/*
129129
** CAPI3REF: Run-Time Library Version Numbers
130130
** KEYWORDS: sqlite3_version, sqlite3_sourceid
131131
**
@@ -975,10 +975,16 @@
975975
** <li>[[SQLITE_FCNTL_HAS_MOVED]]
976976
** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a
977977
** pointer to an integer and it writes a boolean into that integer depending
978978
** on whether or not the file has been renamed, moved, or deleted since it
979979
** 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.
980986
**
981987
** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]]
982988
** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This
983989
** opcode causes the xFileControl method to swap the file handle with the one
984990
** pointed to by the pArg argument. This capability is used during testing
@@ -1026,10 +1032,12 @@
10261032
#define SQLITE_FCNTL_WAL_BLOCK 24
10271033
#define SQLITE_FCNTL_ZIPVFS 25
10281034
#define SQLITE_FCNTL_RBU 26
10291035
#define SQLITE_FCNTL_VFS_POINTER 27
10301036
#define SQLITE_FCNTL_JOURNAL_POINTER 28
1037
+#define SQLITE_FCNTL_WIN32_GET_HANDLE 29
1038
+#define SQLITE_FCNTL_PDB 30
10311039
10321040
/* deprecated names */
10331041
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
10341042
#define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
10351043
#define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
@@ -1978,18 +1986,31 @@
19781986
** does not make a copy of the new main schema name string, so the application
19791987
** must ensure that the argument passed into this DBCONFIG option is unchanged
19801988
** until after the database connection closes.
19811989
** </dd>
19821990
**
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
+**
19832003
** </dl>
19842004
*/
19852005
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
19862006
#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
19872007
#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */
19882008
#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
19892009
#define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */
19902010
#define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */
2011
+#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */
19912012
19922013
19932014
/*
19942015
** CAPI3REF: Enable Or Disable Extended Result Codes
19952016
** METHOD: sqlite3
19962017
--- 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 @@
2525
** SQL code to implement the tables needed by the stash.
2626
*/
2727
static const char zStashInit[] =
2828
@ CREATE TABLE IF NOT EXISTS localdb.stash(
2929
@ 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
3131
@ comment TEXT, -- Comment for this stash. Or NULL
3232
@ ctime TIMESTAMP -- When the stash was created
3333
@ );
3434
@ CREATE TABLE IF NOT EXISTS localdb.stashfile(
3535
@ stashid INTEGER REFERENCES stash, -- Stash that contains this file
@@ -39,11 +39,11 @@
3939
@ isExec BOOLEAN, -- True if file is executable
4040
@ isLink BOOLEAN, -- True if file is a symlink
4141
@ origname TEXT, -- Original filename
4242
@ newname TEXT, -- New name for file at next check-in
4343
@ delta BLOB, -- Delta from baseline. Content if rid=0
44
-@ PRIMARY KEY(origname, stashid)
44
+@ PRIMARY KEY(newname, stashid)
4545
@ );
4646
@ INSERT OR IGNORE INTO vvar(name, value) VALUES('stash-next', 1);
4747
;
4848
4949
/*
@@ -196,11 +196,11 @@
196196
}
197197
return stashid;
198198
}
199199
200200
/*
201
-** Apply a stash to the current check-out.
201
+** Apply a stash to the current checkout.
202202
*/
203203
static void stash_apply(int stashid, int nConflict){
204204
int vid;
205205
Stmt q;
206206
db_prepare(&q,
@@ -278,10 +278,15 @@
278278
}
279279
blob_reset(&delta);
280280
if( fossil_strcmp(zOrig,zNew)!=0 ){
281281
undo_save(zOrig);
282282
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
+ );
283288
}
284289
}
285290
stash_add_files_in_sfile(vid);
286291
db_finalize(&q);
287292
if( nConflict ){
@@ -393,18 +398,18 @@
393398
** return that number. Or throw a fatal error if it is not a valid
394399
** stash number. If it is NULL, return the most recent stash or
395400
** throw an error if the stash is empty.
396401
*/
397402
static int stash_get_id(const char *zStashId){
398
- int stashid = 0;
403
+ int stashid;
399404
if( zStashId==0 ){
400405
stashid = db_int(0, "SELECT max(stashid) FROM stash");
401406
if( stashid==0 ) fossil_fatal("empty stash");
402407
}else{
403408
stashid = atoi(zStashId);
404409
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);
406411
}
407412
}
408413
return stashid;
409414
}
410415
@@ -420,70 +425,83 @@
420425
** Save the current changes in the working tree as a new stash.
421426
** Then revert the changes back to the last check-in. If FILES
422427
** are listed, then only stash and revert the named files. The
423428
** "save" verb can be omitted if and only if there are no other
424429
** 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.
426431
**
427
-** fossil stash list ?-v|--verbose?
428
-** fossil stash ls ?-v|--verbose?
432
+** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>?
429433
**
430434
** List all changes sets currently stashed. Show information about
431435
** individual files in each changeset if -v or --verbose is used.
432436
**
433
-** fossil stash show|cat ?STASHID? ?DIFF-FLAGS?
437
+** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS?
434438
**
435
-** Show the content of a stash
439
+** Show the contents of a stash.
436440
**
437441
** fossil stash pop
438442
** fossil stash apply ?STASHID?
439443
**
440444
** 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
442446
** the stash after applying it but the "apply" command retains the
443447
** changeset.
444448
**
445449
** fossil stash goto ?STASHID?
446450
**
447451
** Update to the baseline checkout for STASHID then apply the
448452
** changes of STASHID. Keep STASHID so that it can be reused
449453
** This command is undoable.
450454
**
451
-** fossil stash drop ?STASHID? ?-a|--all?
452
-** fossil stash rm ?STASHID? ?-a|--all?
455
+** fossil stash drop|rm ?STASHID? ?-a|--all?
453456
**
454457
** Forget everything about STASHID. Forget the whole stash if the
455458
** -a|--all flag is used. Individual drops are undoable but -a|--all
456459
** is not.
457460
**
458
-** fossil stash diff ?STASHID?
459
-** fossil stash gdiff ?STASHID?
461
+** fossil stash diff ?STASHID? ?DIFF-OPTIONS?
462
+** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS?
460463
**
461464
** Show diffs of the current working directory and what that
462465
** directory would be if STASHID were applied.
463466
**
464467
** SUMMARY:
465468
** fossil stash
466469
** fossil stash save ?-m|--comment COMMENT? ?FILES...?
467470
** 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>?
469472
** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS?
470473
** 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?
475478
*/
476479
void stash_cmd(void){
477480
const char *zCmd;
478481
int nCmd;
479482
int stashid = 0;
483
+ int rc;
480484
undo_capture_command_line();
481485
db_must_be_within_tree();
482486
db_open_config(0, 0);
483487
db_begin_transaction();
484488
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
+ }
485503
if( g.argc<=2 ){
486504
zCmd = "save";
487505
}else{
488506
zCmd = g.argv[2];
489507
}
@@ -641,37 +659,30 @@
641659
|| memcmp(zCmd, "cat", nCmd)==0
642660
){
643661
const char *zDiffCmd = 0;
644662
const char *zBinGlob = 0;
645663
int fIncludeBinary = 0;
664
+ int fBaseline = zCmd[0]=='s' || zCmd[0]=='c';
646665
u64 diffFlags;
647666
648667
if( find_option("tk",0,0)!=0 ){
649668
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);
659670
return;
660671
}
661672
if( find_option("internal","i",0)==0 ){
662673
zDiffCmd = diff_command_external(memcmp(zCmd, "gdiff", nCmd)==0);
663674
}
664675
diffFlags = diff_options();
665676
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));
667678
if( zDiffCmd ){
668679
zBinGlob = diff_get_binary_glob();
669680
fIncludeBinary = diff_include_binary_files();
670681
}
671682
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,
673684
diffFlags);
674685
}else
675686
if( memcmp(zCmd, "help", nCmd)==0 ){
676687
g.argv[1] = "help";
677688
g.argv[2] = "stash";
678689
--- 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 @@
7171
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
7272
brief = P("brief")!=0;
7373
style_header("Repository Statistics");
7474
style_adunit_config(ADUNIT_RIGHT_OK);
7575
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");
7979
}
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");
8282
if( sqlite3_compileoption_used("ENABLE_DBSTAT_VTAB") ){
83
- style_submenu_element("Table Sizes", 0, "repo-tabsize");
83
+ style_submenu_element("Table Sizes", "repo-tabsize");
8484
}
8585
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");
8787
}
8888
@ <table class="label-value">
8989
@ <tr><th>Repository&nbsp;Size:</th><td>
9090
fsize = file_size(g.zRepositoryName);
9191
bigSizeName(sizeof(zBuf), zBuf, fsize);
@@ -340,12 +340,12 @@
340340
login_check_credentials();
341341
if( !g.perm.Admin ){ login_needed(0); return; }
342342
343343
style_header("URLs and Checkouts");
344344
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");
347347
@ <div class="section">URLs</div>
348348
@ <table border="0" width='100%%'>
349349
db_prepare(&q, "SELECT substr(name,9), datetime(mtime,'unixepoch')"
350350
" FROM config WHERE name GLOB 'baseurl:*' ORDER BY 2 DESC");
351351
cnt = 0;
@@ -387,14 +387,14 @@
387387
login_check_credentials();
388388
if( !g.perm.Admin ){ login_needed(0); return; }
389389
390390
style_header("Repository Schema");
391391
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");
394394
if( sqlite3_compileoption_used("ENABLE_DBSTAT_VTAB") ){
395
- style_submenu_element("Table Sizes", 0, "repo-tabsize");
395
+ style_submenu_element("Table Sizes", "repo-tabsize");
396396
}
397397
db_prepare(&q,
398398
"SELECT sql FROM repository.sqlite_master WHERE sql IS NOT NULL");
399399
@ <pre>
400400
while( db_step(&q)==SQLITE_ROW ){
@@ -417,13 +417,13 @@
417417
418418
login_check_credentials();
419419
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
420420
style_header("Repository Table Sizes");
421421
style_adunit_config(ADUNIT_RIGHT_OK);
422
- style_submenu_element("Stat", "Repository Stats", "stat");
422
+ style_submenu_element("Stat", "stat");
423423
if( g.perm.Admin ){
424
- style_submenu_element("Schema", "Repository Schema", "repo_schema");
424
+ style_submenu_element("Schema", "repo_schema");
425425
}
426426
db_multi_exec(
427427
"CREATE TEMP TABLE trans(name TEXT PRIMARY KEY,tabname TEXT)WITHOUT ROWID;"
428428
"INSERT INTO trans(name,tabname)"
429429
" SELECT name, tbl_name FROM repository.sqlite_master;"
430430
--- 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&nbsp;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&nbsp;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 @@
706706
if( zUserName && zUserName[0]==0 ) zUserName = 0;
707707
if( zView==0 ){
708708
zView = "byuser";
709709
cgi_replace_query_parameter("view","byuser");
710710
}
711
- for(i=0; i<ArraySize(aViewType); i++){
711
+ for(i=0; i<count(aViewType); i++){
712712
if( fossil_strcmp(zView, aViewType[i].zVal)==0 ){
713713
eType = aViewType[i].eType;
714714
break;
715715
}
716716
}
717717
if( eType!=RPT_NONE ){
718718
int nView = 0; /* Slots used in azView[] */
719
- for(i=0; i<ArraySize(aViewType); i++){
719
+ for(i=0; i<count(aViewType); i++){
720720
azView[nView++] = aViewType[i].zVal;
721721
azView[nView++] = aViewType[i].zName;
722722
}
723723
if( eType!=RPT_BYFILE ){
724
- style_submenu_multichoice("type", ArraySize(azType)/2, azType, 0);
724
+ style_submenu_multichoice("type", count(azType)/2, azType, 0);
725725
}
726726
style_submenu_multichoice("view", nView/2, azView, 0);
727727
if( eType!=RPT_BYUSER ){
728728
style_submenu_sql("user","User:",
729729
"SELECT '', 'All Users' UNION ALL "
@@ -732,11 +732,11 @@
732732
" ORDER BY 1 COLLATE nocase) WHERE x!=''",
733733
eType==RPT_BYFILE ? "WHERE type='ci'" : ""
734734
);
735735
}
736736
}
737
- style_submenu_element("Stats", "Stats", "%R/stat");
737
+ style_submenu_element("Stats", "%R/stat");
738738
style_header("Activity Reports");
739739
switch( eType ){
740740
case RPT_BYYEAR:
741741
stats_report_by_month_year(0, 0, zUserName);
742742
break;
743743
--- 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 @@
3030
** Populate these structure with calls to
3131
**
3232
** style_submenu_element()
3333
** style_submenu_entry()
3434
** style_submenu_checkbox()
35
+** style_submenu_binary()
3536
** style_submenu_multichoice()
37
+** style_submenu_sql()
3638
**
3739
** prior to calling style_footer(). The style_footer() routine
3840
** will generate the appropriate HTML text just below the main
3941
** menu.
4042
*/
4143
static struct Submenu {
4244
const char *zLabel; /* Button label */
43
- const char *zTitle;
4445
const char *zLink; /* Jump to this link when button is pressed */
4546
} aSubmenu[30];
4647
static int nSubmenu = 0; /* Number of buttons */
4748
static struct SubmenuCtrl {
4849
const char *zName; /* Form query parameter */
@@ -52,13 +53,14 @@
5253
short int iSize; /* Width for FF_ENTRY. Count for FF_MULTI */
5354
const char *const *azChoice;/* value/display pairs for FF_MULTI */
5455
const char *zFalse; /* FF_BINARY label when false */
5556
} aSubmenuCtrl[20];
5657
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
6062
6163
/*
6264
** Remember that the header has been generated. The footer is omitted
6365
** if an error occurs before the header.
6466
*/
@@ -230,18 +232,16 @@
230232
/*
231233
** Add a new element to the submenu
232234
*/
233235
void style_submenu_element(
234236
const char *zLabel,
235
- const char *zTitle,
236237
const char *zLink,
237238
...
238239
){
239240
va_list ap;
240
- assert( nSubmenu < sizeof(aSubmenu)/sizeof(aSubmenu[0]) );
241
+ assert( nSubmenu < count(aSubmenu) );
241242
aSubmenu[nSubmenu].zLabel = zLabel;
242
- aSubmenu[nSubmenu].zTitle = zTitle ? zTitle : zLabel;
243243
va_start(ap, zLink);
244244
aSubmenu[nSubmenu].zLink = vmprintf(zLink, ap);
245245
va_end(ap);
246246
nSubmenu++;
247247
}
@@ -249,25 +249,37 @@
249249
const char *zName, /* Query parameter name */
250250
const char *zLabel, /* Label before the entry box */
251251
int iSize, /* Size of the entry box */
252252
int isDisabled /* True if disabled */
253253
){
254
- assert( nSubmenuCtrl < ArraySize(aSubmenuCtrl) );
254
+ assert( nSubmenuCtrl < count(aSubmenuCtrl) );
255255
aSubmenuCtrl[nSubmenuCtrl].zName = zName;
256256
aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
257257
aSubmenuCtrl[nSubmenuCtrl].iSize = iSize;
258258
aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled;
259259
aSubmenuCtrl[nSubmenuCtrl].eType = FF_ENTRY;
260260
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++;
261273
}
262274
void style_submenu_binary(
263275
const char *zName, /* Query parameter name */
264276
const char *zTrue, /* Label to show when parameter is true */
265277
const char *zFalse, /* Label to show when the parameter is false */
266278
int isDisabled /* True if this control is disabled */
267279
){
268
- assert( nSubmenuCtrl < ArraySize(aSubmenuCtrl) );
280
+ assert( nSubmenuCtrl < count(aSubmenuCtrl) );
269281
aSubmenuCtrl[nSubmenuCtrl].zName = zName;
270282
aSubmenuCtrl[nSubmenuCtrl].zLabel = zTrue;
271283
aSubmenuCtrl[nSubmenuCtrl].zFalse = zFalse;
272284
aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled;
273285
aSubmenuCtrl[nSubmenuCtrl].eType = FF_BINARY;
@@ -277,11 +289,11 @@
277289
const char *zName, /* Query parameter name */
278290
int nChoice, /* Number of options */
279291
const char *const *azChoice,/* value/display pairs. 2*nChoice entries */
280292
int isDisabled /* True if this control is disabled */
281293
){
282
- assert( nSubmenuCtrl < ArraySize(aSubmenuCtrl) );
294
+ assert( nSubmenuCtrl < count(aSubmenuCtrl) );
283295
aSubmenuCtrl[nSubmenuCtrl].zName = zName;
284296
aSubmenuCtrl[nSubmenuCtrl].iSize = nChoice;
285297
aSubmenuCtrl[nSubmenuCtrl].azChoice = azChoice;
286298
aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled;
287299
aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI;
@@ -400,10 +412,11 @@
400412
401413
if( g.thTrace ) Th_Trace("BEGIN_HEADER<br />\n", -1);
402414
403415
/* Generate the header up through the main menu */
404416
Th_Store("project_name", db_get("project-name","Unnamed Fossil Project"));
417
+ Th_Store("project_description", db_get("project-description",""));
405418
Th_Store("title", zTitle);
406419
Th_Store("baseurl", g.zBaseURL);
407420
Th_Store("secureurl", login_wants_https_redirect()? g.zHttpsURL: g.zBaseURL);
408421
Th_Store("home", g.zTop);
409422
Th_Store("index_page", db_get("index-page","/home"));
@@ -523,74 +536,75 @@
523536
}else{
524537
@ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a>
525538
}
526539
}
527540
}
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
- "&nbsp;%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("&nbsp;%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
+ @ &nbsp;%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
+ @ &nbsp;%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;
592606
}
593607
}
594608
@ </div>
595609
if( nSubmenuCtrl ){
596610
cgi_query_parameters_to_hidden();
@@ -703,14 +717,15 @@
703717
{ "td.timelineTableCell",
704718
"the format for the timeline data cells",
705719
@ vertical-align: top;
706720
@ text-align: left;
707721
},
708
- { "tr.timelineCurrent td.timelineTableCell",
722
+ { "tr.timelineCurrent",
709723
"the format for the timeline data cell of the current checkout",
710724
@ padding: .1em .2em;
711725
@ border: 1px dashed #446979;
726
+ @ box-shadow: 1px 1px 4px #888;
712727
},
713728
{ "tr.timelineSelected",
714729
"The row in the timeline table that contains the entry of interest",
715730
@ padding: .1em .2em;
716731
@ border: 2px solid lightgray;
@@ -1574,17 +1589,13 @@
15741589
login_needed(0);
15751590
return;
15761591
}
15771592
for(i=0; i<count(azCgiVars); i++) (void)P(azCgiVars[i]);
15781593
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");
15861597
15871598
#if !defined(_WIN32)
15881599
@ uid=%d(getuid()), gid=%d(getgid())<br />
15891600
#endif
15901601
@ g.zBaseURL = %h(g.zBaseURL)<br />
15911602
--- 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 "&nbsp;%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("&nbsp;%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 @ &nbsp;%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 @ &nbsp;%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 @@
654654
login_needed(g.anon.Read);
655655
}
656656
login_anonymous_available();
657657
style_header("Tags");
658658
style_adunit_config(ADUNIT_RIGHT_OK);
659
- style_submenu_element("Timeline", "Timeline", "tagtimeline");
659
+ style_submenu_element("Timeline", "tagtimeline");
660660
@ <h2>Non-propagating tags:</h2>
661661
db_prepare(&q,
662662
"SELECT substr(tagname,5)"
663663
" FROM tag"
664664
" WHERE EXISTS(SELECT 1 FROM tagxref"
@@ -693,11 +693,11 @@
693693
694694
login_check_credentials();
695695
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
696696
697697
style_header("Tagged Check-ins");
698
- style_submenu_element("List", "List", "taglist");
698
+ style_submenu_element("List", "taglist");
699699
login_anonymous_available();
700700
@ <h2>Check-ins with non-propagating tags:</h2>
701701
db_prepare(&q,
702702
"%s AND blob.rid IN (SELECT rid FROM tagxref"
703703
" WHERE tagtype=1 AND srcid>0"
704704
--- 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 @@
13171317
}else{
13181318
Th_SetResult(interp, "repository unavailable", -1);
13191319
return TH_ERROR;
13201320
}
13211321
}
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
+}
13221404
13231405
#ifdef _WIN32
13241406
# include <windows.h>
13251407
#else
13261408
# include <sys/time.h>
@@ -1886,10 +1968,11 @@
18861968
{"styleHeader", styleHeaderCmd, 0},
18871969
{"styleFooter", styleFooterCmd, 0},
18881970
{"tclReady", tclReadyCmd, 0},
18891971
{"trace", traceCmd, 0},
18901972
{"stime", stimeCmd, 0},
1973
+ {"unversioned", unversionedCmd, 0},
18911974
{"utime", utimeCmd, 0},
18921975
{"verifyCsrf", verifyCsrfCmd, 0},
18931976
{"wiki", wikiCmd, (void*)&aFlags[0]},
18941977
{0, 0, 0}
18951978
};
@@ -1922,11 +2005,11 @@
19222005
g.tcl.setup = db_get("tcl-setup", 0); /* Grab Tcl setup script. */
19232006
}
19242007
th_register_tcl(g.interp, &g.tcl); /* Tcl integration commands. */
19252008
}
19262009
#endif
1927
- for(i=0; i<sizeof(aCommand)/sizeof(aCommand[0]); i++){
2010
+ for(i=0; i<count(aCommand); i++){
19282011
if ( !aCommand[i].zName || !aCommand[i].xProc ) continue;
19292012
Th_CreateCommand(g.interp, aCommand[i].zName, aCommand[i].xProc,
19302013
aCommand[i].pContext, 0);
19312014
}
19322015
}else{
@@ -2593,11 +2676,11 @@
25932676
}else if( fossil_stricmp(g.argv[2], "webhook")==0 ){
25942677
rc = Th_WebpageHook(g.argv[3], (unsigned int)atoi(g.argv[4]));
25952678
}else if( fossil_stricmp(g.argv[2], "webnotify")==0 ){
25962679
rc = Th_WebpageNotify(g.argv[3], (unsigned int)atoi(g.argv[4]));
25972680
}else{
2598
- fossil_fatal("Unknown TH1 hook %s\n", g.argv[2]);
2681
+ fossil_fatal("Unknown TH1 hook %s", g.argv[2]);
25992682
}
26002683
if( g.interp ){
26012684
zResult = (char*)Th_GetResult(g.interp, &nResult);
26022685
}
26032686
sendText("RESULT (", -1, 0);
26042687
--- 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 @@
833833
int i;
834834
Th_Interp *th1Interp = (Th_Interp *)clientData;
835835
836836
if( !th1Interp ) return;
837837
/* Remove the Tcl integration commands. */
838
- for(i=0; i<(sizeof(aCommand)/sizeof(aCommand[0])); i++){
838
+ for(i=0; i<count(aCommand); i++){
839839
Th_RenameCommand(th1Interp, aCommand[i].zName, -1, NULL, 0);
840840
}
841841
}
842842
843843
/*
@@ -1261,11 +1261,11 @@
12611261
void *pContext
12621262
){
12631263
int i;
12641264
12651265
/* 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++){
12671267
void *ctx;
12681268
if( !aCommand[i].zName || !aCommand[i].xProc ) continue;
12691269
ctx = aCommand[i].pContext;
12701270
/* Use Tcl interpreter for context? */
12711271
if( !ctx ) ctx = pContext;
12721272
--- 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 @@
390390
"SELECT pid FROM plink"
391391
" WHERE cid=:rid AND pid NOT IN phantom"
392392
" ORDER BY isprim DESC /*sort*/"
393393
);
394394
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) ){
396396
aParent[nParent++] = db_column_int(&qparent, 0);
397397
}
398398
db_reset(&qparent);
399399
gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr,
400400
zUuid, isLeaf);
@@ -737,11 +737,11 @@
737737
pRow->mergeOut, /* mo */
738738
pRow->mergeUpto, /* mu */
739739
pRow->aiRiser[pRow->iRail], /* u */
740740
pRow->isLeaf ? 1 : 0 /* f */
741741
);
742
- /* u */
742
+ /* au */
743743
cSep = '[';
744744
for(i=0; i<GR_MAX_RAIL; i++){
745745
if( i==pRow->iRail ) continue;
746746
if( pRow->aiRiser[i]>0 ){
747747
cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]);
@@ -757,11 +757,11 @@
757757
cgi_printf("mi:");
758758
cSep = '[';
759759
for(i=0; i<GR_MAX_RAIL; i++){
760760
if( pRow->mergeIn[i] ){
761761
int mi = i;
762
- if( pRow->mergeDown & (1<<i) ) mi = -mi;
762
+ if( (pRow->mergeDown >> i) & 1 ) mi = -mi;
763763
cgi_printf("%c%d", cSep, mi);
764764
cSep = ',';
765765
}
766766
}
767767
if( cSep=='[' ) cgi_printf("[");
@@ -1083,11 +1083,11 @@
10831083
const char *zMenuName, /* Submenu name */
10841084
const char *zParam, /* Parameter value to add or change */
10851085
const char *zValue, /* Value of the new parameter */
10861086
const char *zRemove /* Parameter to omit */
10871087
){
1088
- style_submenu_element(zMenuName, zMenuName, "%s",
1088
+ style_submenu_element(zMenuName, "%s",
10891089
url_render(pUrl, zParam, zValue, zRemove, 0));
10901090
}
10911091
10921092
10931093
/*
@@ -1186,11 +1186,11 @@
11861186
}
11871187
if( g.perm.RdWiki ){
11881188
az[i++] = "w";
11891189
az[i++] = "Wiki";
11901190
}
1191
- assert( i<=ArraySize(az) );
1191
+ assert( i<=count(az) );
11921192
}
11931193
if( i>2 ){
11941194
style_submenu_multichoice("y", i/2, az, isDisabled);
11951195
}
11961196
}
@@ -1224,21 +1224,22 @@
12241224
/*
12251225
** WEBPAGE: timeline
12261226
**
12271227
** Query parameters:
12281228
**
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
12361236
** 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
12401241
** y=TYPE 'ci', 'w', 't', 'e', or (default) 'all'
12411242
** ng No Graph.
12421243
** nd Do not highlight the focus check-in
12431244
** v Show details of files changed
12441245
** f=CHECKIN Show family (immediate parents and children) of CHECKIN
@@ -1245,20 +1246,22 @@
12451246
** from=CHECKIN Path from...
12461247
** to=CHECKIN ... to this
12471248
** shortest ... show only the shortest path
12481249
** uf=FILE_SHA1 Show only check-ins that contain the given file version
12491250
** 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
12511252
** brbg Background color from branch name
12521253
** ubg Background color from user
12531254
** namechng Show only check-ins that have filename changes
12541255
** 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
12561257
** yw=YYYY-WW Show only events for the given week of the given year
12571258
** ymd=YYYY-MM-DD Show only events on the given day
12581259
** datefmt=N Override the date format
12591260
** bisect Show the check-ins that are in the current bisect
1261
+** showid Show RIDs
1262
+** showsql Show the SQL text
12601263
**
12611264
** p= and d= can appear individually or together. If either p= or d=
12621265
** appear, then u=, y=, a=, and b= are ignored.
12631266
**
12641267
** If both a= and b= appear then both upper and lower bounds are honored.
@@ -1342,17 +1345,15 @@
13421345
url_initialize(&url, "timeline");
13431346
cgi_query_parameters_to_url(&url);
13441347
if( zTagName && g.perm.Read ){
13451348
tagid = db_int(-1,"SELECT tagid FROM tag WHERE tagname='sym-%q'",zTagName);
13461349
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");
13491351
}else if( zBrName && g.perm.Read ){
13501352
tagid = db_int(-1,"SELECT tagid FROM tag WHERE tagname='sym-%q'",zBrName);
13511353
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");
13541355
}else{
13551356
tagid = 0;
13561357
}
13571358
if( zMark && zMark[0]==0 ){
13581359
if( zAfter ) zMark = zAfter;
@@ -1478,12 +1479,11 @@
14781479
blob_append(&sql, ")", -1);
14791480
path_reset();
14801481
addFileGlobExclusion(zChng, &sql);
14811482
tmFlags |= TIMELINE_DISJOINT;
14821483
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');
14851485
blob_appendf(&desc, "%d check-ins going from ",
14861486
db_int(0, "SELECT count(*) FROM timeline"));
14871487
blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h", zFrom), zFrom);
14881488
blob_append(&desc, " to ", -1);
14891489
blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h",zTo), zTo);
@@ -1529,14 +1529,13 @@
15291529
if( p_rid ){
15301530
/* If both p= and d= are set, we don't have the uuid of d yet. */
15311531
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", d_rid);
15321532
}
15331533
}
1534
+ style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c');
15341535
style_submenu_entry("n","Max:",4,0);
15351536
timeline_y_submenu(1);
1536
- style_submenu_binary("v","With Files","Without Files",
1537
- zType[0]!='a' && zType[0]!='c');
15381537
}else if( f_rid && g.perm.Read ){
15391538
/* If f= is present, ignore all other parameters other than n= */
15401539
char *zUuid;
15411540
db_multi_exec(
15421541
"CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
@@ -1550,15 +1549,12 @@
15501549
if( useDividers ) selectedRid = f_rid;
15511550
blob_appendf(&desc, "Parents and children of check-in ");
15521551
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid);
15531552
blob_appendf(&desc, "%z[%S]</a>", href("%R/info/%!S", zUuid), zUuid);
15541553
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');
15601556
}else{
15611557
/* Otherwise, a timeline based on a span of time */
15621558
int n;
15631559
const char *zEType = "timeline item";
15641560
char *zDate;
@@ -1823,26 +1819,23 @@
18231819
timeline_submenu(&url, "Newer", "a", zDate, "b");
18241820
}
18251821
free(zDate);
18261822
}
18271823
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);
18311825
}
1826
+ style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c');
18321827
style_submenu_entry("n","Max:",4,0);
18331828
timeline_y_submenu(disableY);
1834
- style_submenu_binary("v","With Files","Without Files",
1835
- zType[0]!='a' && zType[0]!='c');
18361829
}
18371830
blob_zero(&cond);
18381831
}
18391832
if( PB("showsql") ){
18401833
@ <pre>%h(blob_sql_text(&sql))</pre>
18411834
}
18421835
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");
18441837
}
18451838
if( PB("showid") ) tmFlags |= TIMELINE_SHOWRID;
18461839
if( useDividers && zMark && zMark[0] ){
18471840
double r = symbolic_name_to_mtime(zMark);
18481841
if( r>0.0 ) selectedRid = timeline_add_divider(r);
18491842
--- 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 @@
216216
const char *zBaseName = zName[0]=='+' ? zName+1 : zName;
217217
j = fieldId(zBaseName);
218218
if( j<0 ) continue;
219219
aUsed[j] = 1;
220220
if( aField[j].mUsed & USEDBY_TICKET ){
221
- if( zName[0]=='+' ){
222
- zName++;
221
+ const char *zUsedByName = zName;
222
+ if( zUsedByName[0]=='+' ){
223
+ zUsedByName++;
223224
blob_append_sql(&sql1,", \"%w\"=coalesce(\"%w\",'') || %Q",
224
- zName, zName, p->aField[i].zValue);
225
+ zUsedByName, zUsedByName, p->aField[i].zValue);
225226
}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);
227228
}
228229
}
229230
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);
231236
blob_append_sql(&sql3, ",%Q", p->aField[i].zValue);
232237
}
233238
if( rid>0 ){
234239
wiki_extract_links(p->aField[i].zValue, rid, 1, p->rDate, i==0, 0);
235240
}
@@ -451,35 +456,28 @@
451456
const char *zUuid = PD("name","");
452457
453458
login_check_credentials();
454459
if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; }
455460
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",""));
458462
}
459463
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);
466467
}
467468
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);
470470
}
471471
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",
474473
g.zTop, zUuid, g.zTop, zUuid);
475474
}
476475
if( P("plaintext") ){
477
- style_submenu_element("Formatted", "Formatted", "%R/tktview/%s", zUuid);
476
+ style_submenu_element("Formatted", "%R/tktview/%s", zUuid);
478477
}else{
479
- style_submenu_element("Plaintext", "Plaintext",
480
- "%R/tktview/%s?plaintext", zUuid);
478
+ style_submenu_element("Plaintext", "%R/tktview/%s?plaintext", zUuid);
481479
}
482480
style_header("View Ticket");
483481
if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br />\n", -1);
484482
ticket_init();
485483
initializeVariablesFromCGI();
@@ -546,11 +544,13 @@
546544
Blob *pTicket, /* The text of the ticket change record */
547545
const char *zTktId, /* The ticket to which this change is applied */
548546
int needMod /* True if moderation is needed */
549547
){
550548
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);
552552
if( rid==0 ){
553553
fossil_fatal("trouble committing ticket: %s", g.zErrMsg);
554554
}
555555
if( needMod ){
556556
moderation_table_create();
@@ -560,11 +560,10 @@
560560
);
561561
}else{
562562
db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d);", rid);
563563
db_multi_exec("INSERT OR IGNORE INTO unclustered VALUES(%d);", rid);
564564
}
565
- manifest_crosslink_begin();
566565
result = (manifest_crosslink(rid, pTicket, MC_NONE)==0);
567566
assert( blob_is_reset(pTicket) );
568567
if( !result ){
569568
result = manifest_crosslink_end(MC_PERMIT_HOOKS);
570569
}else{
@@ -850,20 +849,17 @@
850849
return;
851850
}
852851
zUuid = PD("name","");
853852
zType = PD("y","a");
854853
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);
857856
}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);
860858
}
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);
865861
if( zType[0]=='c' ){
866862
zTitle = mprintf("Check-ins Associated With Ticket %h", zUuid);
867863
}else{
868864
zTitle = mprintf("Timeline Of Ticket %h", zUuid);
869865
}
@@ -925,22 +921,18 @@
925921
login_needed(g.anon.Hyperlink && g.anon.RdTkt);
926922
return;
927923
}
928924
zUuid = PD("name","");
929925
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);
936930
if( P("plaintext")!=0 ){
937
- style_submenu_element("Formatted", "Formatted",
938
- "%R/tkthistory/%s", zUuid);
931
+ style_submenu_element("Formatted", "%R/tkthistory/%s", zUuid);
939932
}else{
940
- style_submenu_element("Plaintext", "Plaintext",
941
- "%R/tkthistory/%s?plaintext", zUuid);
933
+ style_submenu_element("Plaintext", "%R/tkthistory/%s?plaintext", zUuid);
942934
}
943935
style_header("%z", zTitle);
944936
945937
tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid);
946938
if( tagid==0 ){
@@ -1386,11 +1378,11 @@
13861378
blob_appendf(&tktchng, "K %s\n", zTktUuid);
13871379
blob_appendf(&tktchng, "U %F\n", zUser);
13881380
md5sum_blob(&tktchng, &cksum);
13891381
blob_appendf(&tktchng, "Z %b\n", &cksum);
13901382
if( ticket_put(&tktchng, zTktUuid, ticket_need_moderation(1)) ){
1391
- fossil_fatal("%s\n", g.zErrMsg);
1383
+ fossil_fatal("%s", g.zErrMsg);
13921384
}else{
13931385
fossil_print("ticket %s succeeded for %s\n",
13941386
(eCmd==set?"set":"add"),zTktUuid);
13951387
}
13961388
}
@@ -1410,17 +1402,17 @@
14101402
/*
14111403
** Add some standard submenu elements for ticket screens.
14121404
*/
14131405
void ticket_standard_submenu(unsigned int ok){
14141406
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");
14161408
}
14171409
if( (ok & T_REPLIST)!=0 ){
1418
- style_submenu_element("Reports","Reports","%R/reportlist");
1410
+ style_submenu_element("Reports", "%R/reportlist");
14191411
}
14201412
if( (ok & T_NEW)!=0 && g.anon.NewTkt ){
1421
- style_submenu_element("New","New","%R/tktnew");
1413
+ style_submenu_element("New", "%R/tktnew");
14221414
}
14231415
}
14241416
14251417
/*
14261418
** WEBPAGE: ticket
14271419
--- 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 @@
4646
** cause CC to become a comment character for the @-substitution.
4747
** Typical values for CC are "--" (for SQL text) or "#" (for Tcl script)
4848
** or "//" (for C++ code). Lines of subsequent @-blocks that begin with
4949
** CC are omitted from the output.
5050
**
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.
5156
*/
5257
#include <stdio.h>
5358
#include <ctype.h>
5459
#include <stdlib.h>
5560
#include <string.h>
@@ -141,17 +146,23 @@
141146
** a cgi_printf() statement whose format is the text following the '@'.
142147
** Substrings of the form "%C(...)" (where C is any sequence of
143148
** characters other than \000 and '(') will put "%C" in the
144149
** format and add the "(...)" as an argument to the cgi_printf call.
145150
*/
151
+ const char *zNewline = "\\n";
146152
int indent;
147153
int nC;
148154
char c;
149155
i++;
150156
if( isspace(zLine[i]) ){ i++; }
151157
indent = i;
152158
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
+ }
153164
if( zLine[i]=='"' || zLine[i]=='\\' ){ zOut[j++] = '\\'; }
154165
zOut[j++] = zLine[i];
155166
if( zLine[i]!='%' || zLine[i+1]=='%' || zLine[i+1]==0 ) continue;
156167
for(nC=1; zLine[i+nC] && zLine[i+nC]!='('; nC++){}
157168
if( zLine[i+nC]!='(' || !isalpha(zLine[i+nC-1]) ) continue;
@@ -169,14 +180,14 @@
169180
i++;
170181
}
171182
}
172183
zOut[j] = 0;
173184
if( !inPrint ){
174
- fprintf(out,"%*scgi_printf(\"%s\\n\"",indent-2,"", zOut);
185
+ fprintf(out,"%*scgi_printf(\"%s%s\"",indent-2,"", zOut, zNewline);
175186
inPrint = 1;
176187
}else{
177
- fprintf(out,"\n%*s\"%s\\n\"",indent+5, "", zOut);
188
+ fprintf(out,"\n%*s\"%s%s\"",indent+5, "", zOut, zNewline);
178189
}
179190
}
180191
}
181192
}
182193
183194
--- 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 @@
144144
if( (unsigned int)c<128 ){
145145
return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
146146
}else if( (unsigned int)c<(1<<22) ){
147147
unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
148148
int iRes = 0;
149
- int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
149
+ int iHi = count(aEntry) - 1;
150150
int iLo = 0;
151151
while( iHi>=iLo ){
152152
int iTest = (iHi + iLo) / 2;
153153
if( key >= aEntry[iTest] ){
154154
iRes = iTest;
@@ -201,11 +201,11 @@
201201
'e', 'i', 'o', 'u', 'y',
202202
};
203203
204204
unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
205205
int iRes = 0;
206
- int iHi = sizeof(aDia)/sizeof(aDia[0]) - 1;
206
+ int iHi = count(aDia) - 1;
207207
int iLo = 0;
208208
while( iHi>=iLo ){
209209
int iTest = (iHi + iLo) / 2;
210210
if( key >= aDia[iTest] ){
211211
iRes = iTest;
@@ -348,11 +348,11 @@
348348
349349
if( c<128 ){
350350
if( c>='A' && c<='Z' ) ret = c + ('a' - 'A');
351351
}else if( c<65536 ){
352352
const struct TableEntry *p;
353
- int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
353
+ int iHi = count(aEntry) - 1;
354354
int iLo = 0;
355355
int iRes = -1;
356356
357357
assert( c>aEntry[0].iCode );
358358
while( iHi>=iLo ){
359359
--- 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
--- src/unversioned.c
+++ src/unversioned.c
@@ -452,18 +452,20 @@
452452
**
453453
** Display a list of all unversioned files in the repository.
454454
** Query parameters:
455455
**
456456
** byage=1 Order the initial display be decreasing age
457
+** showdel=0 Show deleted files
457458
*/
458459
void uvstat_page(void){
459460
Stmt q;
460461
sqlite3_int64 iNow;
461462
sqlite3_int64 iTotalSz = 0;
462463
int cnt = 0;
463464
int n = 0;
464465
const char *zOrderBy = "name";
466
+ int showDel = 0;
465467
char zSzName[100];
466468
467469
login_check_credentials();
468470
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
469471
style_header("Unversioned Files");
@@ -471,20 +473,22 @@
471473
@ No unversioned files on this server
472474
style_footer();
473475
return;
474476
}
475477
if( PB("byage") ) zOrderBy = "mtime DESC";
478
+ if( PB("showdel") ) showDel = 1;
476479
db_prepare(&q,
477480
"SELECT"
478481
" name,"
479482
" mtime,"
480483
" hash,"
481484
" sz,"
482485
" (SELECT login FROM rcvfrom, user"
483486
" WHERE user.uid=rcvfrom.uid AND rcvfrom.rcvid=unversioned.rcvid),"
484487
" rcvid"
485
- " FROM unversioned ORDER BY %s",
488
+ " FROM unversioned %s ORDER BY %s",
489
+ showDel ? "" : "WHERE hash IS NOT NULL" /*safe-for-%s*/,
486490
zOrderBy/*safe-for-%s*/
487491
);
488492
iNow = db_int64(0, "SELECT strftime('%%s','now');");
489493
while( db_step(&q)==SQLITE_ROW ){
490494
const char *zName = db_column_text(&q, 0);
491495
--- 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 @@
1919
** querying information about users.
2020
*/
2121
#include "config.h"
2222
#include "user.h"
2323
24
-#if defined(_WIN32)
25
-#include <conio.h>
26
-#endif
27
-
2824
/*
2925
** Strip leading and trailing space from a string and add the string
3026
** onto the end of a blob.
3127
*/
3228
static void strip_string(Blob *pBlob, char *z){
@@ -43,53 +39,74 @@
4339
}
4440
blob_append(pBlob, z, -1);
4541
}
4642
4743
#if defined(_WIN32) || defined(__BIONIC__)
48
-#ifdef __MINGW32__
44
+#ifdef _WIN32
4945
#include <conio.h>
5046
#endif
47
+
5148
/*
52
-** getpass for Windows and Android
49
+** getpass() for Windows and Android.
5350
*/
51
+static char *zPwdBuffer = 0;
52
+static size_t nPwdBuffer = 0;
53
+
5454
static char *getpass(const char *prompt){
55
- static char pwd[64];
55
+ char *zPwd;
56
+ size_t nPwd;
5657
size_t i;
5758
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;
5867
fputs(prompt,stderr);
5968
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){
6172
#if defined(_WIN32)
62
- pwd[i] = _getch();
73
+ zPwd[i] = _getch();
6374
#else
64
- pwd[i] = getc(stdin);
75
+ zPwd[i] = getc(stdin);
6576
#endif
66
- if(pwd[i]=='\r' || pwd[i]=='\n'){
77
+ if(zPwd[i]=='\r' || zPwd[i]=='\n'){
6778
break;
6879
}
6980
/* 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)){
7182
i -= 2;
7283
continue;
7384
}
7485
/* CTRL-C */
75
- else if(pwd[i]==3) {
86
+ else if(zPwd[i]==3) {
7687
i=0;
7788
break;
7889
}
7990
/* ESC */
80
- else if(pwd[i]==27){
91
+ else if(zPwd[i]==27){
8192
i=0;
8293
break;
8394
}
8495
else{
8596
fputc('*',stderr);
8697
}
8798
}
88
- pwd[i]='\0';
99
+ zPwd[i]='\0';
89100
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);
91108
}
92109
#endif
93110
94111
#if defined(_WIN32) || defined(WIN32)
95112
# include <io.h>
@@ -553,10 +570,25 @@
553570
db_multi_exec(
554571
"UPDATE user SET pw=shared_secret(pw,login), mtime=now()"
555572
" WHERE length(pw)>0 AND length(pw)!=40"
556573
);
557574
}
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
+}
558590
559591
/*
560592
** WEBPAGE: access_log
561593
**
562594
** Show login attempts, including timestamp and IP address.
@@ -616,13 +648,12 @@
616648
}else if( y==2 ){
617649
blob_append(&sql, " WHERE NOT success", -1);
618650
}
619651
blob_append_sql(&sql," ORDER BY rowid DESC LIMIT %d OFFSET %d", n+1, skip);
620652
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);
624655
}
625656
rc = db_prepare_ignore_error(&q, "%s", blob_sql_text(&sql));
626657
fLogEnabled = db_get_boolean("access-log", 0);
627658
@ <div align="center">Access logging is %s(fLogEnabled?"on":"off").
628659
@ (Change this on the <a href="setup_settings">settings</a> page.)</div>
@@ -634,12 +665,12 @@
634665
const char *zIP = db_column_text(&q, 1);
635666
const char *zDate = db_column_text(&q, 2);
636667
int bSuccess = db_column_int(&q, 3);
637668
cnt++;
638669
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);
641672
break;
642673
}
643674
if( bSuccess ){
644675
@ <tr>
645676
}else{
@@ -646,12 +677,11 @@
646677
@ <tr bgcolor="#ffacc0">
647678
}
648679
@ <td>%s(zDate)</td><td>%h(zName)</td><td>%h(zIP)</td></tr>
649680
}
650681
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);
653683
}
654684
@ </tbody></table>
655685
db_finalize(&q);
656686
@ <hr />
657687
@ <form method="post" action="%s(g.zTop)/access_log">
658688
--- 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 @@
317317
wchar_t *zUnicode; /* Unicode version of zUtf8 */
318318
DWORD dummy;
319319
Blob blob;
320320
321321
static int istty[2] = { -1, -1 };
322
+ assert( toStdErr==0 || toStdErr==1 );
322323
if( istty[toStdErr]==-1 ){
323324
istty[toStdErr] = _isatty(toStdErr + 1) != 0;
324325
}
325326
if( !istty[toStdErr] ){
326327
/* stdout/stderr is not a console. */
327328
--- 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 @@
5555
}
5656
void *fossil_realloc(void *p, size_t n){
5757
p = realloc(p, n);
5858
if( p==0 ) fossil_panic("out of memory");
5959
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
60117
}
61118
62119
/*
63120
** This function implements a cross-platform "system()" interface.
64121
*/
65122
--- 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 @@
350350
}
351351
}
352352
if( verbose ) fossil_print("%s\n", &zName[nRepos]);
353353
if( file_wd_isdir(zName)==1 ){
354354
/*TODO(dchest): remove directories? */
355
- fossil_fatal("%s is directory, cannot overwrite\n", zName);
355
+ fossil_fatal("%s is directory, cannot overwrite", zName);
356356
}
357357
if( file_wd_size(zName)>=0 && (isLink || file_wd_islink(0)) ){
358358
file_delete(zName);
359359
}
360360
if( isLink ){
@@ -435,11 +435,11 @@
435435
for(; zName[0]!=0; zName++){
436436
if( zName[0]=='/' && sqlite3_strglob("/ci-comment-????????????.txt", zName)==0 ){
437437
return 1;
438438
}
439439
if( zName[0]!='-' ) continue;
440
- for(i=0; i<sizeof(azTemp)/sizeof(azTemp[0]); i++){
440
+ for(i=0; i<count(azTemp); i++){
441441
n = (int)strlen(azTemp[i]);
442442
if( memcmp(azTemp[i], zName+1, n) ) continue;
443443
if( zName[n+1]==0 ) return 1;
444444
if( zName[n+1]=='-' ){
445445
for(j=n+2; zName[j] && fossil_isdigit(zName[j]); j++){}
@@ -918,11 +918,11 @@
918918
blob_zero(pManOut);
919919
}
920920
db_must_be_within_tree();
921921
pManifest = manifest_get(vid, CFTYPE_MANIFEST, &err);
922922
if( pManifest==0 ){
923
- fossil_fatal("manifest file (%d) is malformed:\n%s\n",
923
+ fossil_fatal("manifest file (%d) is malformed:\n%s",
924924
vid, blob_str(&err));
925925
}
926926
manifest_file_rewind(pManifest);
927927
while( (pFile = manifest_file_next(pManifest,0))!=0 ){
928928
if( pFile->zUuid==0 ) continue;
929929
--- 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 @@
138138
** All others become "text/x-fossil-wiki"
139139
*/
140140
const char *wiki_filter_mimetypes(const char *zMimetype){
141141
if( zMimetype!=0 ){
142142
int i;
143
- for(i=0; i<sizeof(azStyles)/sizeof(azStyles[0]); i+=3){
143
+ for(i=0; i<count(azStyles); i+=3){
144144
if( fossil_strcmp(zMimetype,azStyles[i+2])==0 ){
145145
return azStyles[i];
146146
}
147147
}
148148
if( fossil_strcmp(zMimetype, "text/x-markdown")==0
@@ -183,13 +183,13 @@
183183
void markdown_rules_page(void){
184184
Blob x;
185185
int fTxt = P("txt")!=0;
186186
style_header("Markdown Formatting Rules");
187187
if( fTxt ){
188
- style_submenu_element("Formatted", "Formatted", "%R/md_rules");
188
+ style_submenu_element("Formatted", "%R/md_rules");
189189
}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");
191191
}
192192
blob_init(&x, builtin_text("markdown.md"), -1);
193193
wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-markdown");
194194
blob_reset(&x);
195195
style_footer();
@@ -231,26 +231,26 @@
231231
/*
232232
** Add some standard submenu elements for wiki screens.
233233
*/
234234
static void wiki_standard_submenu(unsigned int ok){
235235
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");
237237
}
238238
if( (ok & W_LIST)!=0 ){
239
- style_submenu_element("List","List","%R/wcontent");
239
+ style_submenu_element("List", "%R/wcontent");
240240
}
241241
if( (ok & W_HELP)!=0 ){
242
- style_submenu_element("Help","Help","%R/wikihelp");
242
+ style_submenu_element("Help", "%R/wikihelp");
243243
}
244244
if( (ok & W_NEW)!=0 && g.anon.NewWiki ){
245
- style_submenu_element("New","New","%R/wikinew");
245
+ style_submenu_element("New", "%R/wikinew");
246246
}
247247
#if 0
248248
if( (ok & W_BLOG)!=0
249249
#endif
250250
if( (ok & W_SANDBOX)!=0 ){
251
- style_submenu_element("Sandbox", "Sandbox", "%R/wiki?name=Sandbox");
251
+ style_submenu_element("Sandbox", "%R/wiki?name=Sandbox");
252252
}
253253
}
254254
255255
/*
256256
** WEBPAGE: wikihelp
@@ -366,39 +366,33 @@
366366
}
367367
}
368368
zMimetype = wiki_filter_mimetypes(zMimetype);
369369
if( !g.isHome ){
370370
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);
373372
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);
376374
}
377375
if( (rid && g.anon.WrWiki) || (!rid && g.anon.NewWiki) ){
378376
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",
381378
g.zTop, zPageName);
382379
}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);
386381
}
387382
}
388383
if( rid && g.anon.ApndWiki && g.anon.Attach ){
389
- style_submenu_element("Attach", "Add An Attachment",
384
+ style_submenu_element("Attach",
390385
"%s/attachadd?page=%T&from=%s/wiki%%3fname=%T",
391386
g.zTop, zPageName, g.zTop, zPageName);
392387
}
393388
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",
396390
g.zTop, zPageName, zMimetype);
397391
}
398392
if( g.perm.Hyperlink ){
399
- style_submenu_element("History", "History", "%s/whistory?name=%T",
393
+ style_submenu_element("History", "%s/whistory?name=%T",
400394
g.zTop, zPageName);
401395
}
402396
}
403397
style_set_current_page("%T?name=%T", g.zPath, zPageName);
404398
style_header("%s", zPageName);
@@ -434,11 +428,11 @@
434428
** wiki mimetype.
435429
*/
436430
void mimetype_option_menu(const char *zMimetype){
437431
unsigned i;
438432
@ <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){
440434
if( fossil_strcmp(zMimetype,azStyles[i])==0 ){
441435
@ <option value="%s(azStyles[i])" selected>%s(azStyles[i+1])</option>
442436
}else{
443437
@ <option value="%s(azStyles[i])">%s(azStyles[i+1])</option>
444438
}
@@ -951,13 +945,13 @@
951945
952946
login_check_credentials();
953947
if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
954948
style_header("Available Wiki Pages");
955949
if( showAll ){
956
- style_submenu_element("Active", "Only Active Pages", "%s/wcontent", g.zTop);
950
+ style_submenu_element("Active", "%s/wcontent", g.zTop);
957951
}else{
958
- style_submenu_element("All", "All", "%s/wcontent?all=1", g.zTop);
952
+ style_submenu_element("All", "%s/wcontent?all=1", g.zTop);
959953
}
960954
wiki_standard_submenu(W_ALL_BUT(W_LIST));
961955
@ <ul>
962956
wiki_prepare_page_list(&q);
963957
while( db_step(&q)==SQLITE_ROW ){
964958
--- 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
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -145,11 +145,11 @@
145145
** Use binary search to locate a tag in the aAttribute[] table.
146146
*/
147147
static int findAttr(const char *z){
148148
int i, c, first, last;
149149
first = 1;
150
- last = sizeof(aAttribute)/sizeof(aAttribute[0]) - 1;
150
+ last = count(aAttribute) - 1;
151151
while( first<=last ){
152152
i = (first+last)/2;
153153
c = fossil_strcmp(aAttribute[i].zName, z);
154154
if( c==0 ){
155155
return i;
@@ -372,11 +372,11 @@
372372
AMSK_ID|AMSK_TYPE },
373373
};
374374
375375
void show_allowed_wiki_markup( void ){
376376
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++ ){
378378
@ &lt;%s(aMarkup[i].zName)&gt;
379379
}
380380
}
381381
382382
/*
@@ -383,11 +383,11 @@
383383
** Use binary search to locate a tag in the aMarkup[] table.
384384
*/
385385
static int findTag(const char *z){
386386
int i, c, first, last;
387387
first = 1;
388
- last = sizeof(aMarkup)/sizeof(aMarkup[0]) - 1;
388
+ last = count(aMarkup) - 1;
389389
while( first<=last ){
390390
i = (first+last)/2;
391391
c = fossil_strcmp(aMarkup[i].zName, z);
392392
if( c==0 ){
393393
assert( aMarkup[i].iCode==i );
@@ -947,11 +947,11 @@
947947
for(j=*pN; fossil_isspace(z[j]); j++){}
948948
zTag = mprintf("%.*s", i-j, &z[j]);
949949
j = (int)strlen(zTag);
950950
while( j>0 && fossil_isspace(zTag[j-1]) ){ j--; }
951951
if( j==0 ) return 0;
952
- style_submenu_element(zTag, zTag, "%s", zHref);
952
+ style_submenu_element(zTag, "%s", zHref);
953953
*pN = i+4;
954954
return 1;
955955
}
956956
957957
/*
@@ -2187,11 +2187,11 @@
21872187
{ 4, '<', "&lt;" },
21882188
{ 4, '>', "&gt;" },
21892189
{ 6, ' ', "&nbsp;" },
21902190
};
21912191
int jj;
2192
- for(jj=0; jj<ArraySize(aEntity); jj++){
2192
+ for(jj=0; jj<count(aEntity); jj++){
21932193
if( aEntity[jj].n==n && strncmp(aEntity[jj].z,zIn,n)==0 ){
21942194
c = aEntity[jj].c;
21952195
break;
21962196
}
21972197
}
21982198
--- 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 @ &lt;%s(aMarkup[i].zName)&gt;
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, '<', "&lt;" },
2188 { 4, '>', "&gt;" },
2189 { 6, ' ', "&nbsp;" },
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 @ &lt;%s(aMarkup[i].zName)&gt;
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, '<', "&lt;" },
2188 { 4, '>', "&gt;" },
2189 { 6, ' ', "&nbsp;" },
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 @@
306306
SOCKADDR_IN addr;
307307
int idCnt = 0;
308308
int iPort = mnPort;
309309
Blob options;
310310
wchar_t zTmpPath[MAX_PATH];
311
+#if USE_SEE
312
+ const char *zSavedKey = 0;
313
+ size_t savedKeySize = 0;
314
+#endif
311315
312316
blob_zero(&options);
313317
if( zBaseUrl ){
314318
blob_appendf(&options, " --baseurl %s", zBaseUrl);
315319
}
@@ -326,10 +330,18 @@
326330
blob_appendf(&options, " --th-trace");
327331
}
328332
if( flags & HTTP_SERVER_REPOLIST ){
329333
blob_appendf(&options, " --repolist");
330334
}
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
331343
if( WSAStartup(MAKEWORD(1,1), &wd) ){
332344
fossil_fatal("unable to initialize winsock");
333345
}
334346
while( iPort<=mxPort ){
335347
s = socket(AF_INET, SOCK_STREAM, 0);
@@ -654,11 +666,13 @@
654666
}
655667
}
656668
return 0;
657669
}
658670
659
-/* dupe ifdef needed for mkindex
671
+/* Duplicate #ifdef needed for mkindex */
672
+#ifdef _WIN32
673
+/*
660674
** COMMAND: winsrv*
661675
**
662676
** Usage: %fossil winsrv METHOD ?SERVICE-NAME? ?OPTIONS?
663677
**
664678
** Where METHOD is one of: create delete show start stop.
@@ -1103,6 +1117,7 @@
11031117
fossil_fatal("METHOD should be one of:"
11041118
" create delete show start stop");
11051119
}
11061120
return;
11071121
}
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 */
11091124
--- 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 @@
21402140
}
21412141
if( syncFlags & (SYNC_UV_TRACE|SYNC_UV_DRYRUN) ){
21422142
const char *zMsg = 0;
21432143
switch( iStatus ){
21442144
case 0:
2145
- case 1: zMsg = "UV-PULL"; break;
2145
+ case 1: zMsg = "UV-PULL"; break;
21462146
case 2: zMsg = "UV-PULL-MTIME-ONLY"; break;
21472147
case 4: zMsg = "UV-PUSH-MTIME-ONLY"; break;
21482148
case 5: zMsg = "UV-PUSH"; break;
21492149
}
21502150
if( zMsg ) fossil_print("\r%s: %s\n", zMsg, zName);
21512151
21522152
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
--- 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 @@
6666
* <a href="../../../timeline?c=20015206bc"
6767
target="testwindow">
6868
This timeline has a hidden commit.</a> Click Unhide to reveal.
6969
* <a href="../../../timeline?y=ci&n=15&b=2a4e4cf03e"
7070
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>
7174
7275
External:
7376
7477
* <a href="http://www.sqlite.org/src/timeline?c=2010-09-29&nd"
7578
target="testwindow">Timewarp due to a mis-configured system clock.</a>
7679
--- 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 @@
185185
ADDED f0
186186
} -changes {
187187
ADDED f0
188188
MISSING f1
189189
EDITED f2
190
- MISSING f3
190
+ RENAMED f3n
191191
} -addremove {
192
- ADDED f3n
193192
DELETED f1
194
- DELETED f3
195193
} -exists {f0 f2 f3n} -notexists {f1 f3}
196194
197195
# Confirm there is no longer a stash saved
198196
fossil stash list
199197
test stash-2-list {[first_data_line] eq "empty stash"}
@@ -311,13 +309,11 @@
311309
UPDATE f1
312310
UPDATE f2n
313311
} -changes {
314312
RENAMED f2n
315313
} -addremove {
316
- ADDED f2n
317
- DELETED f2
318
-} -exists {f1 f2n} -notexists {f2} -knownbugs {-changes}
314
+} -exists {f1 f2n} -notexists {f2}
319315
320316
321317
322318
########
323319
# fossil stash snapshot ?-m|--comment COMMENT? ?FILES...?
324320
--- 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 @@
749749
}
750750
return [string range $out 1 end]
751751
}
752752
753753
# 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
755756
# where the "stop argument" is to be stored. This value must eventually be
756757
# passed to the [test_stop_server] procedure.
757758
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]
760761
if {[string length $varName] > 0} {
761762
upvar 1 $varName stopArg
762763
}
763764
if {$::tcl_platform(platform) eq "windows"} {
764765
set stopArg [file join [getTemporaryPath] [appendArgs \
765766
[string trim [clock seconds] -] _ [getSeqNo] .stopper]]
766767
lappend command --stopper $stopArg
767768
}
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 &
769773
set pid [eval $command]
770774
if {$::tcl_platform(platform) ne "windows"} {
771775
set stopArg $pid
772776
}
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]
774784
}
775785
776786
# This procedure stops a Fossil server instance that was previously started
777787
# by the [test_start_server] procedure. The value of the "stop argument"
778788
# 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 } {
780791
if {$::tcl_platform(platform) eq "windows"} {
781792
#
782793
# NOTE: On Windows, the "stop argument" must be the name of a file
783794
# that does NOT already exist.
784795
#
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} {
787799
while {1} {
788800
if {[catch {
789801
#
790802
# NOTE: Using the TaskList utility requires Windows XP or
791803
# later.
792804
#
793805
exec tasklist.exe /FI "PID eq $pid"
794
- } result] != 0 || ![regexp -- " $pid " $result]} then {
806
+ } result] != 0 || ![regexp -- " $pid " $result]} {
795807
break
796808
}
797809
after 1000; # wait a bit...
798810
}
799811
file delete $stopArg
812
+ if {[string length $fileName] > 0} {
813
+ file delete $fileName
814
+ }
800815
return true
801816
}
802817
} else {
803818
#
804819
# NOTE: On Unix, the "stop argument" must be an integer identifier
805820
# that refers to an existing process.
806821
#
807822
if {[regexp {^(?:-)?\d+$} $stopArg] && \
808
- [catch {exec kill -TERM $stopArg}] == 0} then {
823
+ [catch {exec kill -TERM $stopArg}] == 0} {
809824
while {1} {
810825
if {[catch {
811826
#
812827
# TODO: Is this portable to all the supported variants of
813828
# Unix? It should be, it's POSIX.
814829
#
815830
exec ps -p $pid
816
- } result] != 0 || ![regexp -- "(?:^$pid| $pid) " $result]} then {
831
+ } result] != 0 || ![regexp -- "(?:^$pid| $pid) " $result]} {
817832
break
818833
}
819834
after 1000; # wait a bit...
835
+ }
836
+ if {[string length $fileName] > 0} {
837
+ file delete $fileName
820838
}
821839
return true
822840
}
823841
}
824842
return false
825843
--- 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 @@
10381038
error expr for getParameter glob_match globalState hascap hasfeature\
10391039
html htmlize http httpize if info insertCsrf lindex linecount list\
10401040
llength lsearch markdown proc puts query randhex redirect regexp\
10411041
reinitialize rename render repository return searchable set\
10421042
setParameter setting stime string styleFooter styleHeader tclReady\
1043
- trace unset uplevel upvar utime verifyCsrf wiki}
1043
+ trace unset unversioned uplevel upvar utime verifyCsrf wiki}
10441044
set tcl_commands {tclEval tclExpr tclInvoke tclIsSafe tclMakeSafe}
10451045
if {$th1Tcl} {
10461046
test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands $tcl_commands"]}
10471047
} else {
10481048
test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands"]}
@@ -1562,9 +1562,45 @@
15621562
}
15631563
15641564
fossil test-th-source $th1FileName
15651565
test th1-source-1 {$RESULT eq {TH_RETURN: 0 1 2 3 4 5 6 7 8 9}}
15661566
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}}
15671603
15681604
###############################################################################
15691605
15701606
test_cleanup
15711607
--- 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
--- test/unversioned.test
+++ test/unversioned.test
@@ -305,19 +305,19 @@
305305
unversioned5\.txt$} [normalize_result]]}
306306
307307
###############################################################################
308308
309309
set password [string trim [clock seconds] -]
310
-set remote [appendArgs http://uvtester: $password @localhost:8080/]
311310
312311
fossil user new uvtester "Unversioned Test User" $password
313312
fossil user capabilities uvtester oy
314313
315314
###############################################################################
316315
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 /]
319319
320320
###############################################################################
321321
322322
set clientDir [file join $tempPath [appendArgs \
323323
uvtest_ [string trim [clock seconds] -] _ [getSeqNo]]]
@@ -427,11 +427,11 @@
427427
file delete -force $clientDir
428428
puts [appendArgs "Now in server directory \"" [pwd] \".]
429429
430430
###############################################################################
431431
432
-set stopped [test_stop_server $stopArg $pid]
432
+set stopped [test_stop_server $stopArg $pid $outTmpFile]
433433
434434
puts [appendArgs \
435435
[expr {$stopped ? "Stopped" : "Could not stop"}] \
436436
" Fossil server, pid \"" $pid "\", using argument \"" \
437437
$stopArg \".]
438438
--- 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 @@
6666
<p>
6767
In addition to setting various CGI environment variables, if the HTTP
6868
request contains POST content, then the web server relays the POST content
6969
to standard input of the CGI script.
7070
<p>
71
-In summary, the task of the
71
+In summary, the task of the
7272
CGI script is to read the various CGI environment variables and
7373
the POST content on standard input (if any), figure out an appropriate
7474
reply, then write that reply on standard output.
7575
The web server will read the output from the CGI script, reformat it
7676
into an appropriate HTTP reply, and relay the result back to the
@@ -89,31 +89,31 @@
8989
like the following:
9090
<blockquote><pre>
9191
#!/usr/bin/fossil
9292
repository: /home/www/repos/project.fossil
9393
</pre></blockquote>
94
-The first line of the script is a
94
+The first line of the script is a
9595
"[https://en.wikipedia.org/wiki/Shebang_%28Unix%29|shebang]"
9696
that tells the operating system what program to use as the interpreter
9797
for this script. On unix, when you execute a script that starts with
9898
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
100100
itself.
101101
In our example, the interpreter is Fossil, and the argument might
102102
be something like "/var/www/cgi-bin/one/two" (depending on how your
103103
particular web server is configured).
104104
<p>
105105
The Fossil program that is run as the script interpreter
106106
is the same Fossil that runs when
107107
you type ordinary Fossil commands like "fossil sync" or "fossil commit".
108108
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
110110
set to "CGI/1.0" and it therefore knows that it is being used as
111111
CGI rather than as an ordinary command-line tool, and behaves accordingly.
112112
<p>
113113
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
115115
<code>argv&#91;1&#93;</code>). In our example, the second line of that file
116116
tells Fossil the location of the repository it will be serving.
117117
Fossil then starts looking at the CGI environment variables to figure
118118
out what web page is being requested, generates that one web page,
119119
then exits.
@@ -130,11 +130,11 @@
130130
<ol type='A'>
131131
<li> [https://www.fossil-scm.org/fossil/info/c14ecc43]
132132
<li> [https://www.fossil-scm.org/fossil/info?name=c14ecc43]
133133
</ol>
134134
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
136136
"[/help?cmd=/info|/info]" webpage will be generated and the suffix of
137137
PATH_INFO will be converted into the "name" query parameter, which
138138
identifies the artifact about which information is requested.
139139
In case (B), the PATH_INFO is just "info", but the same "name"
140140
query parameter is set explicitly by the URL itself.
@@ -164,11 +164,11 @@
164164
<blockquote>
165165
<b>http://example.com/cgis/example2/subdir/three/timeline</b>
166166
</blockquote>
167167
Here is what happens:
168168
<ol>
169
-<li> The input URI on the HTTP request is
169
+<li> The input URI on the HTTP request is
170170
<b>/cgis/example2/subdir/three/timeline</b>
171171
<li> The web server searches prefixes of the input URI until it finds
172172
the "cgis/example2" script. The web server then sets
173173
PATH_INFO to the "subdir/three/timeline" suffix and invokes the
174174
"cgis/example2" script.
@@ -175,11 +175,11 @@
175175
<li> Fossil runs and sees the "directory:" line pointing to
176176
"/home/www/repos". Fossil then starts pulling terms off the
177177
front of the PATH_INFO looking for a repository. It first looks
178178
at "/home/www/resps/subdir.fossil" but there is no such repository.
179179
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
181181
"subdir/three/" leaving it at just "timeline".
182182
<li> Fossil looks at the rest of PATH_INFO to see that the webpage
183183
requested is "timeline".
184184
</ol>
185185
</blockquote>
@@ -201,14 +201,14 @@
201201
and has a value.
202202
<li><p>
203203
The "[/help?cmd=ui|fossil ui]" and "[/help?cmd=server|fossil server]" commands
204204
are implemented using a simple built-in web server that accepts incoming HTTP
205205
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
207207
is used internally to implement "fossil ui/server".
208208
<p>
209209
SCGI is processed using the same built-in web server, just modified
210210
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
212212
process to handle each CGI request.
213213
</ol>
214214
</blockquote>
215215
--- 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&#91;1&#93;</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&#91;1&#93;</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/adding_code.wiki
+++ www/adding_code.wiki
@@ -22,11 +22,11 @@
2222
2323
2. The <b>makeheaders</b> preprocessor generates all the ".h" files
2424
automatically. Fossil programmers write ".c" files only and let the
2525
makeheaders preprocessor create the ".h" files.
2626
27
- 3. The <b>translate</b> preprocessor converts source code lines that
27
+ 3. The <b>translate</b> preprocessor converts source code lines that
2828
begin with "@" into string literals, or into print statements that
2929
generate web page output, depending on context.
3030
3131
The [./makefile.wiki|Makefile] for Fossil takes care of running these
3232
preprocessors with all the right arguments and in the right order. So it is
@@ -39,13 +39,13 @@
3939
<h2>3.0 Adding New Source Code Files</h2>
4040
4141
New source code files are added in the "src/" subdirectory of the Fossil
4242
source tree. Suppose one wants to add a new source code file named
4343
"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
4545
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
4747
interpreter. The command to run the makemake.tcl script is:
4848
4949
<b>tclsh makemake.tcl</b>
5050
5151
The working directory must be src/ when the command above is run.
@@ -60,11 +60,11 @@
6060
6161
<blockquote><verbatim>
6262
/*
6363
** Copyright boilerplate goes here.
6464
*****************************************************
65
-** High-level description of what this module goes
65
+** High-level description of what this module goes
6666
** here.
6767
*/
6868
#include "config.h"
6969
#include "xyzzy.h"
7070
@@ -83,11 +83,11 @@
8383
exceptions to this rule. Don't worry about those exceptions. The
8484
files you write will require this #include line.)
8585
8686
The "#if INTERFACE ... #endif" section is optional and is only needed
8787
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
8989
uses definitions in the INTERFACE section to help it generate header
9090
files. See [../src/makeheaders.html | makeheaders.html] for additional
9191
information.
9292
9393
After creating a template file such as shown above, and after updating
9494
--- 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 @@
11
<title>Defense Against Spiders</title>
22
33
The website presented by a Fossil server has many hyperlinks.
44
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
66
and ZIP archive of older check-ins) can be expensive to compute.
77
If a spider or bot tries to walk a website implemented by
88
Fossil, it can present a crippling bandwidth and CPU load.
99
1010
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
1212
describes the techniques used by Fossil to try to welcome human
1313
users while keeping out spiders.
1414
1515
<h2>The "hyperlink" user capability</h2>
1616
1717
Every Fossil web session has a "user". For random passers-by on the internet
1818
(and for spiders) that user is "nobody". The "anonymous" user is also
1919
available for humans who do not wish to identify themselves. The difference
2020
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
2323
passwords for specific individuals.
2424
2525
The "h" or "hyperlink" capability is a permission that can be granted
2626
to users that enables the display of hyperlinks. Most of the hyperlinks
2727
generated by Fossil are suppressed if this capability is missing. So
@@ -37,11 +37,11 @@
3737
page inviting the user to log in as anonymous in order to activate hyperlinks.
3838
3939
Removing the "h" capability from user "nobody" is an effective means
4040
of preventing spiders from walking a Fossil-generated website. But
4141
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
4343
are less cumbersome to humans.
4444
4545
<h2>Automatic hyperlinks based on UserAgent</h2>
4646
4747
Fossil has the ability to selectively enable hyperlinks for users
@@ -94,25 +94,25 @@
9494
web browsers implement javascript, so hyperlinks will appears
9595
normally for human users.
9696
9797
<h2>Further defenses</h2>
9898
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
100100
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
102102
like normal web browsers and which interpret javascript. We do not
103103
believe these attacks to be nefarious since SQLite is public domain
104104
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
106106
believe these "attacks" are coming from "script kiddies". But regardless
107107
of whether or not malice is involved, these attacks do present
108108
an unnecessary load on the server which reduces the responsiveness of
109109
the SQLite website for well-behaved and socially responsible users.
110110
For this reason, additional defenses against
111111
spiders have been put in place.
112112
113
-On the Admin/Access page of Fossil, just below the
113
+On the Admin/Access page of Fossil, just below the
114114
"<b>Enable hyperlinks for "nobody" based on User-Agent and Javascript</b>"
115115
setting, there are now two additional subsettings that can be optionally
116116
enabled to control hyperlinks.
117117
118118
The first subsetting waits to run the
@@ -137,11 +137,11 @@
137137
Fossil currently does a very good job of providing easy access to humans
138138
while keeping out troublesome robots and spiders. However, spiders and
139139
bots continue to grow more sophisticated, requiring ever more advanced
140140
defenses. This "arms race" is unlikely to ever end. The developers of
141141
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.
143143
144144
Readers of this page who have suggestions on how to improve the spider
145145
defenses in Fossil are invited to submit your ideas to the Fossil Users
146
-mailing list:
146
+mailing list:
147147
[mailto:[email protected] | [email protected]].
148148
--- 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 @@
1818
<li>Locate the check-in that contains the file that is to be
1919
annotated. Call this check-in C0.
2020
<li>Find all direct ancestors of C0. A direct ancestor is the closure
2121
of the primary parent of C0. Merged in branches are not part of
2222
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
2424
check-in in which the file to be annotated was modified.
2525
<li>Load the complete text of the file to be annotated from check-in C0.
2626
Call this version of the file F0.
2727
<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),
2929
beginning with the most
3030
recent ancestor and moving toward the oldest ancestor, do the
3131
following steps:
3232
<ol type='a'>
3333
<li>Load the text for the file to be annotated as it existed in check-in CX.
@@ -44,19 +44,19 @@
4444
<h2>3.0 Discussion and Notes</h2>
4545
4646
The time-consuming part of this algorithm is step 6b - computing the
4747
diff from all historical versions of the file to the version of the file
4848
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
5050
[/help?cmd=/annotate|/annotate] webpage only shows those lines that where
5151
changed by the 20 most recent modifications to the file. This allows
5252
the loop on step 6 to terminate after only 19 diffs instead of the hundreds
5353
or thousands of diffs that might be required for a frequently modified file.
5454
5555
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
5757
available in the database, and so the algorithm could be enhanced to follow
5858
files across name changes by modifications to step 3.
5959
6060
Step 2 is interesting in that it is
6161
[/artifact/6cb824a0417?ln=196-201 | implemented] using a
6262
[https://www.sqlite.org/lang_with.html#recursivecte|recursive common table expression].
6363
--- 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
--- www/bugtheory.wiki
+++ www/bugtheory.wiki
@@ -27,11 +27,11 @@
2727
Recall that a fossil repository consists of an
2828
unordered collection of <i>artifacts</i>. (See the
2929
<a href="fileformat.wiki">file format document</a> for details.)
3030
Some artifacts have a special format, and among those are
3131
<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
3333
ticket. A ticket is created by a ticket change artifact.
3434
Each subsequent modification of the ticket is a separate artifact.
3535
3636
The "push", "pull", and "sync" algorithms share ticket change artifacts
3737
between repositories in the same way as every other artifact. In fact,
3838
--- 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 @@
11
<title>Change Log</title>
22
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>
423
524
* Add support for [./unvers.wiki|unversioned content],
625
the [/help?cmd=unversioned|fossil unversioned] command and the
726
[/help?cmd=/uv|/uv] and [/uvlist] web pages.
827
* The [/uv/download.html|download page] is moved into
928
[./unvers.wiki|unversioned content] so that the self-hosting Fossil
1029
websites no longer uses any external content.
1130
* Added the "Search" button to the graphical diff generated by
1231
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
1433
[/help?cmd=diff|diff] command.
1534
* Various performance enhancements to the [/help?cmd=diff|diff] command.
1635
* Update internal Unicode character tables, used in regular expression
1736
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
1938
the SQLITE_DBCONFIG_MAINDBNAME interface of SQLite which is only available
2039
in SQLite version 3.15 and later and so Fossil will not work with
2140
earlier SQLite versions.
2241
* Fix [https://www.mail-archive.com/[email protected]/msg23618.html|multi-line timeline bug]
2342
* Enhance the [/help?cmd=purge|fossil purge] command.
@@ -28,10 +47,11 @@
2847
able to pull from their parent but not push.
2948
* Added the -nocomplain option to the TH1 "query" command.
3049
* Added support for the chng=GLOBLIST query parameter on the
3150
[/help?cmd=/timeline|/timeline] webpage.
3251
52
+<a name='v1_35'></a>
3353
<h2>Changes for Version 1.35 (2016-06-14)</h2>
3454
3555
* Enable symlinks by default on all non-Windows platforms.
3656
* Enhance the [/md_rules|Markdown formatting] so that hyperlinks that begin
3757
with "/" are relative to the root of the Fossil repository.
@@ -71,10 +91,11 @@
7191
names in place of getpass() to read passwords and passphrases
7292
* Option --baseurl now works on Windows.
7393
* Numerious documentation improvements.
7494
* Update the built-in SQLite to version 3.13.0.
7595
96
+<a name='v1_34'></a>
7697
<h2>Changes for Version 1.34 (2015-11-02)</h2>
7798
7899
* Make the [/help?cmd=clean|fossil clean] command undoable for files less
79100
than 10MiB.
80101
* Update internal Unicode character tables, used in regular expression
@@ -106,10 +127,11 @@
106127
* Change the mimetype for ".n" and ".man" files to text/plain.
107128
* Display improvements in the [/help?cmd=bisect|fossil bisect chart] command.
108129
* Updated the built-in SQLite to version 3.9.1 and activated JSON1 and FTS5
109130
support (both currently unused within Fossil).
110131
132
+<a name='v1_33'></a>
111133
<h2>Changes for Version 1.33 (2015-05-23)</h2>
112134
* Improved fork detection on [/help?cmd=update|fossil update],
113135
[/help?cmd=status|fossil status] and related commands.
114136
* Change the default skin to what used to be called "San Francisco Modern".
115137
* Add the [/repo-tabsize] web page
@@ -155,10 +177,11 @@
155177
field for direct entry of the user name to each applicable report.
156178
* Create parent directories of [/help?cmd=settings|empty-dirs] if they don't
157179
already exist.
158180
* Inhibit timeline links to wiki pages that have been deleted.
159181
182
+<a name='v1_33'></a>
160183
<h2>Changes for Version 1.32 (2015-03-14)</h2>
161184
* When creating a new repository using [/help?cmd=init|fossil init], ensure
162185
that the new repository is fully compatible with historical versions of
163186
Fossil by having a valid manifest as RID 1.
164187
* Anti-aliased rendering of arrowheads on timeline graphs.
@@ -171,10 +194,11 @@
171194
* Enhance the "ln=" query parameter on artifact displays to accept multiple
172195
ranges, separate by spaces (or "+" when URL-encoded).
173196
* Added [/help?cmd=forget|fossil forget] as an alias for
174197
[/help?cmd=rm|fossil rm].
175198
199
+<a name='v1_31'></a>
176200
<h2>Changes For Version 1.31 (2015-02-23)</h2>
177201
* Change the auxiliary schema by adding columns MLINK.ISAUX and MLINK.PMID
178202
columns to the schema, to support better drawing of file change graphs.
179203
A [/help?cmd=rebuild|fossil rebuild] is recommended but is not required.
180204
so that the new graph drawing logic can work effectively.
@@ -222,10 +246,11 @@
222246
* Allow the user of Common Table Expressions in the SQL that defaults
223247
ticket reports.
224248
* Break out the components (css, footer, and header) for the
225249
various built-in skins into separate files in the source tree.
226250
251
+<a name='v1_30'></a>
227252
<h2>Changes For Version 1.30 (2015-01-19)</h2>
228253
* Added the [/help?cmd=bundle|fossil bundle] command.
229254
* Added the [/help?cmd=purge|fossil purge] command.
230255
* Added the [/help?cmd=publish|fossil publish] command.
231256
* Added the [/help?cmd=unpublished|fossil unpublished] command.
@@ -292,10 +317,11 @@
292317
the correctness of printf-style formatting strings.
293318
* Fix CVE-2014-3566, also known as the POODLE SSL 3.0 vulnerability.
294319
* Numerous documentation fixes and improvements.
295320
* Other obscure and minor bug fixes - see the timeline for details.
296321
322
+<a name='v1_29'></a>
297323
<h2>Changes For Version 1.29 (2014-06-12)</h2>
298324
* Add the ability to display content, diffs and annotations for UTF16
299325
text files in the web interface.
300326
* Add the "SaveAs..." and "Invert" buttons
301327
to the graphical diff display that results
302328
--- 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
--- www/checkin_names.wiki
+++ www/checkin_names.wiki
@@ -55,20 +55,20 @@
5555
</pre></blockquote>
5656
5757
The full 40-character SHA1 hash is unwieldy to remember and type, though,
5858
so Fossil also accepts a unique prefix of the hash, using any combination
5959
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
6161
accomplish the same thing as the above:
6262
6363
<blockquote><pre>
6464
fossil info e5a734a19a9
6565
fossil info E5a734A
6666
fossil info e5a7
6767
</blockquote>
6868
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
7070
prefix of canonical name.
7171
7272
<h2>Tags And Branch Names</h2>
7373
7474
Using a tag or branch name where a check-in name is expected causes
@@ -112,11 +112,11 @@
112112
113113
<blockquote><tt>
114114
fossil info tag:deed2
115115
</tt></blockquote>
116116
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
118118
tagged with "deed2" not to the
119119
check-in whose canonical name begins with "deed2".
120120
121121
<h2>Whole Branches</h2>
122122
@@ -147,11 +147,11 @@
147147
* <i>YYYY-MM-DD</i>
148148
* <i>YYYY-MM-DD HH:MM</i>
149149
* <i>YYYY-MM-DD HH:MM:SS</i>
150150
* <i>YYYY-MM-DD HH:MM:SS.SSS</i>
151151
152
-The space between the day and the year can optionally be
152
+The space between the day and the year can optionally be
153153
replaced by an uppercase <b>T</b> and the entire timestamp can
154154
optionally be followed by "<b>z</b>" or "<b>Z</b>". In the fourth
155155
form with fractional seconds, any number of digits may follow the
156156
decimal point, though due to precision limits only the first three
157157
digits will be significant.
@@ -158,17 +158,17 @@
158158
159159
In its default configuration, Fossil interprets and displays all dates
160160
in Universal Coordinated Time (UTC). This tends to work the best for
161161
distributed projects where participants are scattered around the globe.
162162
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
164164
name is meaningless if Fossil is in the default mode of using UTC for
165165
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
167167
UTC instead of local time.
168168
169
-For an example of how timestamps are useful,
169
+For an example of how timestamps are useful,
170170
consider the homepage for the Fossil website itself:
171171
172172
<blockquote>
173173
http://www.fossil-scm.org/fossil/doc/<b>trunk</b>/www/index.wiki
174174
</blockquote>
@@ -191,11 +191,11 @@
191191
<blockquote>
192192
fossil update trunk:2010-07-01T14:30
193193
</blockquote>
194194
195195
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
197197
July 1, 2010.
198198
199199
<h2>Root Of A Branch</h2>
200200
201201
A branch name that begins with the "<tt>root:</tt>" prefix refers to the
@@ -220,11 +220,11 @@
220220
current check-out. And the "previous" or "prev" tag means the primary
221221
(non-merge) parent of the current check-out.
222222
223223
For embedded documentation, the tag "ckout" means the version as present in
224224
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
226226
used to preview local changes to documentation before committing them. It does
227227
not apply to CLI commands.
228228
229229
<h2>Additional Examples</h2>
230230
231231
--- 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
--- www/childprojects.wiki
+++ www/childprojects.wiki
@@ -37,21 +37,21 @@
3737
VALUES('project-code',lower(hex(randomblob(20))));
3838
INSERT INTO config(name,value)
3939
VALUES('project-name','CHILD-PROJECT-NAME');
4040
</verbatim></blockquote>
4141
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
4343
the child project, of course.
4444
4545
The repository is now a separate project, independent from its parent.
4646
Clone the new project to the developers as needed.
4747
4848
The child project and the parent project will not normally be able to sync
4949
with one another, since they are now separate projects with distinct
5050
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
5353
parent repository is also provided on the command-line, then updates to
5454
the parent project that occurred after the child was created will be added
5555
to the child repository. Thus, by periodically doing a
5656
pull --from-parent-project, the child project is able to stay up to date
5757
with all the latest changes in the parent.
5858
--- 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
--- www/concepts.wiki
+++ www/concepts.wiki
@@ -131,11 +131,11 @@
131131
<h3>2.2 Manifests</h3>
132132
133133
Associated with every check-in is a special file called the
134134
[./fileformat.wiki#manifest| "manifest"]. The manifest is a
135135
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
137137
of the file and the name of the file as it appears on disk,
138138
and thus serves as a mapping from artifact ID to disk name. The artifact ID
139139
of the manifest is the identifier for the entire check-in. When
140140
you look at a "timeline" of changes in Fossil, the ID associated
141141
with each check-in or commit is really just the artifact ID of the
@@ -147,11 +147,11 @@
147147
manifest file to be materialized to disk, if desired. Both Fossil
148148
itself, and SQLite cause the manifest file to be materialized to disk
149149
so that the makefiles for these project can read the manifest and
150150
embed version information in generated binaries.
151151
152
-<p>Fossil automatically generates a manifest whenever you "commit"
152
+<p>Fossil automatically generates a manifest whenever you "commit"
153153
a new check-in. So this is not something that you, the developer,
154154
need to worry with. The format of a manifest is intentionally
155155
designed to be simple to parse, so that if
156156
you want to read and interpret a manifest, either by hand or
157157
with a script, that is easy to do. But you will probably never
@@ -200,11 +200,11 @@
200200
Fossil effectively. You will want to have some kind of text editor
201201
for entering check-in comments. Fossil will use whatever text editor
202202
is identified by your VISUAL environment variable. Fossil will also
203203
use GPG to clearsign your manifests if you happen to have it installed,
204204
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,
206206
though Fossil has an excellent built-in "diff" algorithm that works
207207
fine for most people. If you happen to have Tcl/Tk installed on your
208208
system, Fossil will use it to generate a graphical "diff" display when
209209
you use the --tk option to the "diff" command, but this too is entirely
210210
optional.
@@ -211,11 +211,11 @@
211211
212212
213213
To uninstall Fossil, simply delete the executable.
214214
215215
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
217217
run "<b>fossil all rebuild</b>" to restructure your repositories after
218218
an upgrade. Running "all rebuild" never hurts, so when upgrading it
219219
is a good policy to run it even if it is not strictly necessary.
220220
221221
To use Fossil, simply type the name of the executable in your
@@ -266,11 +266,11 @@
266266
267267
<ol>
268268
<li>
269269
Establish a local repository using either the <b>new</b> command
270270
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.
272272
</li>
273273
274274
<li>
275275
Establish one or more source trees using
276276
the <b>open</b> command with the name of the repository file as its
@@ -279,11 +279,11 @@
279279
280280
<li>
281281
The <b>open</b> command in the previous step populates your local source
282282
tree with a copy of the latest check-in. Usually this is what you want.
283283
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.
285285
Use the <b>timeline</b> or <b>leaves</b> commands
286286
to identify alternative check-ins to switch to.
287287
</li>
288288
289289
<li>
@@ -302,17 +302,17 @@
302302
you cloned from or whatever server you most recently synced with.
303303
</li>
304304
305305
<li>
306306
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.
308308
In autosync mode, <b>update</b> will first go back to the server you
309309
cloned from or with which you most recently synced, and pull down all
310310
recent changes into your local repository. Then it will merge recent
311311
changes into your local source tree. If you do an <b>update</b> and
312312
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
314314
to back out the changes.
315315
</li>
316316
317317
<li>
318318
Repeat all of the above until you have generated great software.
319319
--- 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
--- www/contribute.wiki
+++ www/contribute.wiki
@@ -10,11 +10,11 @@
1010
[./copyright-release.pdf | Contributor Agreement (PDF)]
1111
(or [./copyright-release.html | as HTML]) on file for you. We require
1212
this in order to maintain clear title to the Fossil code and prevent
1313
the introduction of code with incompatible licenses or other entanglements
1414
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
1616
Fossil.
1717
1818
If you do not wish to submit a Contributor Agreement, we would still
1919
welcome your suggestions and example code, but we will not use your code
2020
directly - we will be forced to re-implement your changes from scratch which
@@ -21,14 +21,14 @@
2121
might take longer.
2222
2323
<h2>2.0 Submitting Patches</h2>
2424
2525
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
2828
describe in detail what the patch does and which version of Fossil
29
-it is written against.
29
+it is written against.
3030
3131
A contributor agreement is not strictly necessary to submit a patch.
3232
However, without a contributor agreement on file, your patch will be
3333
used for reference only - it will not be applied to the code. This
3434
may delay acceptance of your patch.
@@ -53,23 +53,23 @@
5353
Fossil Architect (Richard Hipp) will merge changes onto the trunk.</p>
5454
5555
Contributors are required to following the
5656
[./checkin.wiki | pre-checkin checklist] prior to every check-in to
5757
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
5959
should print out a copy of the pre-checkin checklist and keep
6060
it on a notecard beside their workstations, for quick reference.
6161
6262
Contributors should review the
6363
[./style.wiki | Coding Style Guidelines] and mimic the coding style
6464
used through the rest of the Fossil source code. Your code should
6565
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.
6767
6868
<h2>4.0 Testing</h2>
6969
70
-Fossil has the beginnings of a
70
+Fossil has the beginnings of a
7171
[../test/release-checklist.wiki | release checklist] but this is an
7272
area that needs further work. (Your contributions here are welcomed!)
7373
Contributors with check-in privileges are expected to run the release
7474
checklist on any major changes they contribute, and if appropriate expand
7575
the checklist and/or the automated test scripts to cover their additions.
7676
--- 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
--- www/custom_ticket.wiki
+++ www/custom_ticket.wiki
@@ -65,11 +65,11 @@
6565
&lt;/tr>
6666
&lt;th1>enable_output 1&lt;/th1>
6767
</pre>
6868
This bit of code will get rid of the "email" field entry for logged-in users.
6969
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.
7171
</p>
7272
</blockquote>
7373
7474
<h2>Modify the 'view ticket' page</h2><blockquote>
7575
<p>
@@ -83,11 +83,11 @@
8383
&lt;td align="right">Opened by:&lt;/td>&lt;td bgcolor="#d0d0d0">
8484
$&lt;opened_by>
8585
&lt;/td>
8686
</pre>
8787
This will add a row which displays these two fields, in the event the user has
88
-"edit" capability.
88
+"edit" capability.
8989
</p>
9090
</blockquote>
9191
9292
<h2>Modify the 'edit ticket' page</h2><blockquote>
9393
<p>
9494
--- www/custom_ticket.wiki
+++ www/custom_ticket.wiki
@@ -65,11 +65,11 @@
65 &lt;/tr>
66 &lt;th1>enable_output 1&lt;/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 &lt;td align="right">Opened by:&lt;/td>&lt;td bgcolor="#d0d0d0">
84 $&lt;opened_by>
85 &lt;/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 &lt;/tr>
66 &lt;th1>enable_output 1&lt;/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 &lt;td align="right">Opened by:&lt;/td>&lt;td bgcolor="#d0d0d0">
84 $&lt;opened_by>
85 &lt;/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/customskin.md
+++ www/customskin.md
@@ -144,10 +144,14 @@
144144
respository settings and the specific page being generated.
145145
146146
* **project_name** - The project_name variable is filled with the
147147
name of the project as configured under the Admin/Configuration
148148
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.
149153
150154
* **title** - The title variable holds the title of the page being
151155
generated.
152156
153157
The title variable is special in that it is deleted after
154158
--- 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
--- www/delta_encoder_algorithm.wiki
+++ www/delta_encoder_algorithm.wiki
@@ -153,11 +153,11 @@
153153
byte forward. The "base" is left unchanged in that case.</p>
154154
155155
<p>The processing loop stops at one of two conditions:
156156
<ol>
157157
<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".
159159
</li>
160160
<li>After the emission of instructions the new "base" location is
161161
within NHASH bytes of end of the "target", i.e. there are no more than
162162
at most NHASH bytes left.
163163
</li>
164164
--- 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
--- www/delta_format.wiki
+++ www/delta_format.wiki
@@ -161,49 +161,49 @@
161161
</table>
162162
163163
<p>The unified diff behind the above delta is</p>
164164
165165
<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
167167
--- ../DELTA/old 2007-08-23 21:14:40.000000000 -0700
168168
+++ ../DELTA/new 2007-08-23 21:14:33.000000000 -0700
169169
@@ -5,7 +5,7 @@
170
-
170
+
171171
* 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
173173
- it is thus unable to update database because it cannot create
174174
+ it is thus unable to update the database because it cannot create
175175
a rollback journal) then it currently fails silently on a push.
176176
It needs to return a helpful error.
177
-
177
+
178178
@@ -27,8 +27,8 @@
179179
* Additional information displayed for the "vinfo" page:
180
-
180
+
181181
+ All leaves of this version that are not included in the
182182
- descendant list. With date, user, comment, and hyperlink.
183183
- Leaves in the descendant table should be marked as such.
184184
+ descendant list. With date, user, comment, and hyperlink.
185185
+ Leaves in the descendant table should be marked as such.
186186
See the compute_leaves() function to see how to find all
187187
leaves.
188188
+ Add file diff links to the file change list.
189189
@@ -37,7 +37,7 @@
190
-
190
+
191191
* The /xfer handler (for push, pull, and clone) does not do
192192
delta compression. This results in excess bandwidth usage.
193193
- There are some code in xfer.c that are sketches of ideas on
194194
+ There are some pieces in xfer.c that are sketches of ideas on
195195
how to do delta compression, but nothing has been implemented.
196
-
196
+
197197
* Enhancements to the diff and tkdiff commands in the cli.
198198
@@ -45,7 +45,7 @@
199199
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
201201
configuration options to replace tkdiff with some other
202202
- visual differ of the users choice.
203203
+ visual differ of the users choice. Example: eskil.
204
-
204
+
205205
* Ticketing interface (expand this bullet)
206206
207207
</pre></td></tr></table>
208208
209209
210210
--- 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
--- www/embeddeddoc.wiki
+++ www/embeddeddoc.wiki
@@ -42,13 +42,13 @@
4242
<b>http://www.hwaci.com/cgi-bin/fossil</b>.
4343
If you launch the web server using the "<b>fossil server</b>" command line,
4444
then the <i>&lt;baseurl&gt;</i> is usually
4545
<b>http://localhost:8080/</b>.
4646
47
-The <i>&lt;version&gt;</i> is any unique prefix of the check-in ID for
47
+The <i>&lt;version&gt;</i> is any unique prefix of the check-in ID for
4848
the check-in containing the documentation you want to access.
49
-Or <i>&lt;version&gt;</i> can be the name of a
49
+Or <i>&lt;version&gt;</i> can be the name of a
5050
[./branching.wiki | branch] in order to show
5151
the documentation for the latest version of that branch.
5252
Or <i>&lt;version&gt;</i> can be one of the keywords "<b>tip</b>" or
5353
"<b>ckout</b>". The "<b>tip</b>" keyword means to use the most recent
5454
check-in. This is useful if you want to see the very latest
@@ -62,30 +62,30 @@
6262
6363
Finally, the <i>&lt;filename&gt;</i> element of the URL is the
6464
pathname of the documentation file relative to the root of the source
6565
tree.
6666
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
6969
[/mimetype_list|many different file suffixes],
7070
including all the popular ones such as ".css", ".gif", ".htm",
7171
".html", ".jpg", ".jpeg", ".png", and ".txt".
7272
73
-Documentation files whose names end in ".wiki" use the
73
+Documentation files whose names end in ".wiki" use the
7474
[/wiki_rules | fossil wiki markup] -
7575
a safe subset of HTML together with some wiki rules for paragraph
76
-breaks, lists, and hyperlinks.
76
+breaks, lists, and hyperlinks.
7777
Documentation files ending in ".md" or ".markdown" use the
7878
[/md_rules | Markdown markup langauge].
7979
Documentation files ending in ".txt" are plain text.
8080
Wiki, markdown, and plain text documentation files
8181
are rendered with the standard fossil header and footer added.
8282
Most other mimetypes are delivered directly to the requesting
8383
web browser without interpretation, additions, or changes.
8484
8585
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.
8787
However, if the file begins with a &lt;div&gt; element like this:
8888
8989
<b>&lt;div class='fossil-doc' data-title='<i>Title Text</i>'&gt;</b>
9090
9191
Then the standard Fossil header and footer are added to the document
@@ -117,11 +117,11 @@
117117
<blockquote><pre>
118118
#!/usr/bin/fossil
119119
repository: /fossil/fossil.fossil
120120
</pre></blockquote>
121121
122
-This is one of four ways to set up a
122
+This is one of four ways to set up a
123123
<a href="./server.wiki">fossil web server</a>.
124124
125125
The "<b>/trunk/</b>" part of the URL tells fossil to use
126126
the documentation files from the most recent trunk check-in.
127127
If you wanted to see an historical version of this document,
@@ -138,11 +138,11 @@
138138
<li> <i>YYYY-MM-DD</i>
139139
<li> <i>YYYY-MM-DD</i><b>T</b><i>HH:MM</i>
140140
<li> <i>YYYY-MM-DD</i><b>T</b><i>HH:MM:SS</i>
141141
</ul>
142142
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
144144
of the document that was most recently checked in as of the date
145145
and time specified. So, for example, to see what the fossil website
146146
looked like at the beginning of 2010, enter:
147147
148148
<blockquote>
149149
--- 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>&lt;baseurl&gt;</i> is usually
45 <b>http://localhost:8080/</b>.
46
47 The <i>&lt;version&gt;</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>&lt;version&gt;</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>&lt;version&gt;</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>&lt;filename&gt;</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 &lt;div&gt; element like this:
88
89 <b>&lt;div class='fossil-doc' data-title='<i>Title Text</i>'&gt;</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>&lt;baseurl&gt;</i> is usually
45 <b>http://localhost:8080/</b>.
46
47 The <i>&lt;version&gt;</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>&lt;version&gt;</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>&lt;version&gt;</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>&lt;filename&gt;</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 &lt;div&gt; element like this:
88
89 <b>&lt;div class='fossil-doc' data-title='<i>Title Text</i>'&gt;</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/encryptedrepos.wiki
+++ www/encryptedrepos.wiki
@@ -3,11 +3,11 @@
33
Fossil can be compiled so that it works with encrypted repositories using
44
the [https://www.sqlite.org/see/doc/trunk/www/readme.wiki|SQLite Encryption Extension].
55
This technical note explains the process.
66
</blockquote>
77
<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
99
[http://www.hwaci.com/cgi-bin/see-step1|purchasing a license].
1010
<p>
1111
Assuming you have an SEE license, the first step of compiling Fossil to
1212
use SEE is to create an SEE-enabled version of the SQLite database source code.
1313
This alternative SQLite database source file should be called "sqlite3-see.c"
1414
--- 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 @@
8888
`--sqlstats`: (Sets `g.fSqlStats`.) Print a number of performance
8989
statistics about each SQLite database used when it is closed.
9090
9191
`--sshtrace`: (Sets `g.fSshTrace`.)
9292
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.
9498
9599
`--systemtrace`: (Sets `g.fSystemTrace`.) Trace all commands launched
96100
as sub processes.
97101
98102
`--user LOGIN`: (Sets `g.zLogin`) Also `-U LOGIN`. Set the user name
99103
--- 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 @@
2323
can be something simple like "Version 1.2.3" perhaps with a bright
2424
color background to draw attention to the entry and the wiki content
2525
can contain release notes, for example.
2626
2727
* <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
2929
roadmaps for future development, can be entered as technotes.
3030
3131
* <b>Process Checkpoints</b>. For projects that have a formal process,
3232
technotes can be used to record the completion or the initiation of
3333
various process steps. For example, a technote can be used to record
@@ -49,11 +49,11 @@
4949
stay better organized and provide a better historical record of the
5050
development progress.
5151
5252
<h2>Viewing Technotes</h2>
5353
54
-Because technotes are considered a special kind of wiki,
54
+Because technotes are considered a special kind of wiki,
5555
users must have permission to read wiki in order read technotes.
5656
Enable the "j" permission under the /Setup/Users menu in order
5757
to give specific users or user classes the ability to view wiki
5858
and technotes.
5959
@@ -64,12 +64,12 @@
6464
6565
There is a hyperlink under the /wikihelp menu that can be used to create
6666
new technotes. And there is a submenu hyperlink on technote displays for
6767
editing existing technotes.
6868
69
-Users must have check-in privileges (permission "i") in order to
69
+Users must have check-in privileges (permission "i") in order to
7070
create or edit technotes. In addition, users must have create-wiki
7171
privilege (permission "f") to create new technotes and edit-wiki
7272
privilege (permission "k") in order to edit existing technotes.
7373
7474
Technote content may be formatted as [/wiki_rules | Fossil wiki],
7575
[/md_rules | Markdown], or a plain text.
7676
--- 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 @@
6262
If you already have a fork in your check-in tree and you want to convert
6363
that fork to a branch, you can do this from the web interface.
6464
First locate the check-in that you want to be
6565
the initial check-in of your branch on the timeline and click on its
6666
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
6969
the name of your new branch to the right and press the "Apply Changes"
7070
button.</blockquote></li>
7171
7272
<a name="q4"></a>
7373
<p><b>(4) How do I tag a check-in?</b></p>
@@ -89,11 +89,11 @@
8989
9090
The CHECK-IN in the previous line can be any
9191
[./checkin_names.wiki | valid check-in name format].
9292
9393
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
9595
what to tag on the timeline, then click on the link to go the detailed
9696
information page for that check-in. Then find the "<b>edit</b>"
9797
link (near the "Commands:" label) and click on that. There are
9898
controls on the edit page that allow new tags to be added and existing
9999
tags to be removed.</blockquote></li>
@@ -100,13 +100,13 @@
100100
101101
<a name="q5"></a>
102102
<p><b>(5) How do I create a private branch that won't get pushed back to the
103103
main repository.</b></p>
104104
105
-<blockquote>Use the <b>--private</b> command-line option on the
105
+<blockquote>Use the <b>--private</b> command-line option on the
106106
<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.
108108
All descendants of a private check-in are also private.
109109
110110
Unless you specify something different using the <b>--branch</b> and/or
111111
<b>--bgcolor</b> options, the new private check-in will be put on a branch
112112
named "private" with an orange background color.
113113
--- 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
--- www/fileformat.wiki
+++ www/fileformat.wiki
@@ -2,11 +2,11 @@
22
<h1 align="center">
33
Fossil File Formats
44
</h1>
55
66
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.
88
A fossil repository is intended to be readable,
99
searchable, and extensible by people not yet born.
1010
1111
The global state of a fossil repository is an unordered
1212
set of <i>artifacts</i>.
@@ -14,11 +14,11 @@
1414
part of a trouble ticket, or one of several special control artifacts
1515
used to show the relationships between other artifacts within the
1616
project. Each artifact is normally represented on disk as a separate
1717
file. Artifacts can be text or binary.
1818
19
-In addition to the global state,
19
+In addition to the global state,
2020
each fossil repository also contains local state.
2121
The local state consists of web-page formatting
2222
preferences, authorized users, ticket display and reporting formats,
2323
and so forth. The global state is shared in common among all
2424
repositories for the same project, whereas the local state is often
@@ -30,11 +30,11 @@
3030
mentioned here in order to distinguish it from global state.
3131
3232
Each artifact in the repository is named by its SHA1 hash.
3333
No prefixes or meta information is added to an artifact before
3434
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
3636
on the file as it exists in your source tree.</p>
3737
3838
Some artifacts have a particular format which gives them special
3939
meaning to fossil. Fossil recognizes:
4040
@@ -84,11 +84,11 @@
8484
Each card begins with a single
8585
character "card type". Zero or more arguments may follow
8686
the card type. All arguments are separated from each other
8787
and from the card-type character by a single space
8888
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
9090
character that acts as the card separator.
9191
9292
All cards of the manifest occur in strict sorted lexicographical order.
9393
No card may be duplicated.
9494
The entire manifest may be PGP clear-signed, but otherwise it
@@ -114,18 +114,18 @@
114114
another manifest that serves as the "baseline" for this manifest. A
115115
manifest that has a B-card is called a delta-manifest and a manifest
116116
that omits the B-card is a baseline-manifest. The other manifest
117117
identified by the argument of the B-card must be a baseline-manifest.
118118
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.
120120
121121
A manifest must have exactly one C-card. The sole argument to
122122
the C-card is a check-in comment that describes the check-in that
123123
the manifest defines. The check-in comment is text. The following
124124
escape sequences are applied to the text:
125125
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
127127
(ASCII 0x5C) is represented as two backslashes "\\". Apart from
128128
space and newline, no other whitespace characters are allowed in
129129
the check-in comment. Nor are any unprintable characters allowed
130130
in the comment.
131131
@@ -167,11 +167,11 @@
167167
is used.
168168
169169
A manifest has zero or one P-cards. Most manifests have one P-card.
170170
The P-card has a varying number of arguments that
171171
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
173173
hexadecimal SHA1 of a predecessor manifest. All arguments
174174
to the P-card must be unique within that card.
175175
The first argument is the SHA1 of the direct ancestor of the manifest.
176176
Other arguments define manifests with which the first was
177177
merged to yield the current manifest. Most manifests have
@@ -184,28 +184,28 @@
184184
whereas a P-card defines the immediate ancestor or a merge
185185
ancestor, the Q-card is used to identify a single check-in or a small
186186
range of check-ins which were cherry-picked for inclusion in or
187187
exclusion from the current manifest. The first argument of
188188
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.
190190
The target is preceded by "+" or "-" to show inclusion or
191191
exclusion, respectively. The optional second argument to the
192192
Q-card is another manifest artifact ID which is the "baseline"
193193
for the cherry-pick. If omitted, the baseline is the primary
194194
parent of the target. The
195195
changes included or excluded consist of all changes moving from
196
-the baseline to the target.
196
+the baseline to the target.
197197
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.
199199
Older versions of Fossil will reject manifests that contain Q-cards.
200200
201201
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
203203
the check-in except the manifest itself. The checksum is expressed
204204
as 32 characters of lowercase hexadecimal. The checksum is
205205
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,
207207
take the pathname of the file relative to the root of the
208208
repository, append a single space (ASCII 0x20), the
209209
size of the file in ASCII decimal, a single newline
210210
character (ASCII 0x0A), and the complete text of the file.
211211
Compute the MD5 checksum of the result.
@@ -228,12 +228,12 @@
228228
is encoded using the same character escapes as is used for the
229229
check-in comment argument to the C-card.
230230
231231
A manifest must have a single Z-card as its last line. The argument
232232
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
235235
a sanity check to prove that the manifest is well-formed and
236236
consistent.
237237
238238
A sample manifest from Fossil itself can be seen
239239
[/artifact/28987096ac | here].
@@ -240,11 +240,11 @@
240240
241241
<a name="cluster"></a>
242242
<h2>2.0 Clusters</h2>
243243
244244
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
246246
reduce network traffic. As such, clusters are an optimization and
247247
may be removed from a repository without loss or damage to the
248248
underlying project code.
249249
250250
Clusters follow a syntax that is very similar to manifests.
@@ -252,15 +252,15 @@
252252
(ASCII 0x0a) separate the artifact into cards. Each card begins with a single
253253
character "card type". Zero or more arguments may follow
254254
the card type. All arguments are separated from each other
255255
and from the card-type character by a single space
256256
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
258258
character that acts as the card separator.
259259
All cards of a cluster occur in strict sorted lexicographical order.
260260
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
262262
what is described here.
263263
Unlike manifests, clusters are never PGP signed.
264264
265265
Allowed cards in the cluster are as follows:
266266
@@ -268,11 +268,11 @@
268268
<b>M</b> <i>artifact-id</i><br />
269269
<b>Z</b> <i>checksum</i>
270270
</blockquote>
271271
272272
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
274274
another artifact in the repository. The Z card works exactly like
275275
the Z card of a manifest. The argument to the Z card is the
276276
lower-case hexadecimal representation of the MD5 checksum of all
277277
prior cards in the cluster. The Z-card is required.
278278
@@ -315,11 +315,11 @@
315315
first value is the tag name. The first character of the tag
316316
is either "+", "-", or "*". The "+" means the tag should be added
317317
to the artifact. The "-" means the tag should be removed.
318318
The "*" character means the tag should be added to the artifact
319319
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
321321
more recent "-", "*", or "+" tag with the same name.
322322
The optional third argument is the value of the tag. A tag
323323
without a value is a Boolean.
324324
325325
When two or more tags with the same name are applied to the
@@ -331,11 +331,11 @@
331331
for display purposes. The "user" tag overrides the name of the
332332
check-in user. The "date" tag overrides the check-in date.
333333
The "branch" tag sets the name of the branch that at check-in
334334
belongs to. Symbolic tags begin with the "sym-" prefix.
335335
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
337337
artifact. The Z card is the usual required artifact checksum.
338338
339339
An example control artifacts can be seen [/info/9d302ccda8 | here].
340340
341341
@@ -360,11 +360,11 @@
360360
361361
The D card is the date and time when the wiki page was edited.
362362
The P card specifies the parent wiki pages, if any. The L card
363363
gives the name of the wiki page. The optional N card specifies
364364
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.
366366
The U card specifies the login
367367
of the user who made this edit to the wiki page. The Z card is
368368
the usual checksum over the entire artifact and is required.
369369
370370
The W card is used to specify the text of the wiki page. The
@@ -405,11 +405,11 @@
405405
If the <i>value</i> parameter of the J card is omitted, then the
406406
field is set to an empty string.
407407
Each fossil server has a ticket configuration which specifies the fields its
408408
understands. The ticket configuration is part of the local state for
409409
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
411411
local ticket configuration. If a J card specifies a <i>field</i> that
412412
is not in the local configuration, then that J card
413413
is simply ignored.
414414
415415
The first argument of the J card is the field name. The second
@@ -424,11 +424,11 @@
424424
425425
<a name="attachment"></a>
426426
<h2>6.0 Attachments</h2>
427427
428428
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
430430
technical note to which
431431
the attachment is connected (the target artifact).
432432
The following cards are allowed on an attachment artifact:
433433
434434
<blockquote>
@@ -441,11 +441,11 @@
441441
</blockquote>
442442
443443
The A card specifies a filename for the attachment in its first argument.
444444
The second argument to the A card is the name of the wiki page or
445445
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
447447
ID of the attachment itself. A missing third argument means that the
448448
attachment should be deleted.
449449
450450
The C card is an optional comment describing what the attachment is about.
451451
The C card is optional, but there can only be one.
@@ -487,11 +487,11 @@
487487
</blockquote>
488488
489489
The C card contains text that is displayed on the timeline for the
490490
technote. The C card is optional, but there can only be one.
491491
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
493493
technote artifact was created. This is different from the time at which
494494
the technote appears on the timeline.
495495
496496
A single E card gives the time of the technote (the point on the timeline
497497
where the technote is displayed) and a unique identifier for the technote.
@@ -525,11 +525,11 @@
525525
display color for timelines.
526526
527527
The optional U card gives name of the user who entered the technote.
528528
529529
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
531531
[#wikichng | wiki artifact].
532532
533533
The Z card is the required checksum over the rest of the artifact.
534534
535535
536536
--- 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
--- www/fiveminutes.wiki
+++ www/fiveminutes.wiki
@@ -4,65 +4,65 @@
44
The following document was contributed by Gilles Ganault on 2013-01-08.
55
</i></b>
66
</p><hr>
77
88
<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
1111
repository, and no need for branching/forking.</p>
1212
1313
<h2>Create a new repository</h2>
1414
<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
1818
after they've been checked out of the repository.</p>
1919
2020
<h2>Open the repository</h2>
2121
<p>cd c:\temp\test.fossil</p>
2222
<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
2525
file _FOSSIL_ to keep track of changes (on non-Windows systems it is called
2626
<tt>.fslckout</tt>).</p>
2727
2828
<h2>Add new files</h2>
2929
<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 &quot;commit&quot;. When using &quot;.&quot;, 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 &quot;commit&quot;. When using &quot;.&quot;, it tells Fossil
32
+to add all the files in the current directory recursively, i.e. including all
3333
the files in all the subdirectories.</p>
3434
<p>Note: To tell Fossil to ignore some extensions:</p>
3535
<p>fossil settings ignore-glob &quot;*.o,*.obj,*.exe&quot; --global</p>
3636
3737
<h2>Remove files that haven't been committed yet</h2>
3838
<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
4040
added through &quot;fossil add&quot;.</p>
4141
4242
<h2>Check current status</h2>
4343
<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 &quot;fossil commit&quot;. 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 &quot;fossil commit&quot;. It's a useful command to run before
4646
running &quot;fossil commit&quot; just to check that things are OK before proceeding.</p>
4747
4848
<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,
5151
etc.</p>
5252
5353
<p>fossil commit -m "Added stuff"</p>
5454
5555
If no file names are provided on the command-line then all changes will be checked in,
5656
otherwise just the listed file(s) will be checked in.
5757
5858
<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
6060
in your work directory:</p>
6161
<p>fossil gdiff myfile.c</p>
6262
<p>If you wish to compare two different revisions of a file in the repository:</p>
63
-<p>fossil finfo myfile: Note the first hash, which is the UUID of the commit
63
+<p>fossil finfo myfile: Note the first hash, which is the UUID of the commit
6464
when the file was committed</p>
6565
<p>fossil gdiff --from UUID#1 --to UUID#2 myfile.c</p>
6666
<h2>Cancel changes and go back to previous revision</h2>
6767
<p>fossil revert myfile.c</p>
6868
<p>Fossil does not prompt when reverting a file. It simply reminds the user about the
@@ -69,8 +69,8 @@
6969
"undo" command, just in case the revert was a mistake.</p>
7070
7171
7272
<h2>Close the repository</h2>
7373
<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 &quot;fossil&quot;
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 &quot;fossil&quot;
7676
will trigger an error since there is no longer any connection.</p>
7777
--- 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 &quot;commit&quot;. When using &quot;.&quot;, 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 &quot;*.o,*.obj,*.exe&quot; --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 &quot;fossil add&quot;.</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 &quot;fossil commit&quot;. It's a useful command to run before
46 running &quot;fossil commit&quot; 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 &quot;fossil&quot;
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 &quot;commit&quot;. When using &quot;.&quot;, 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 &quot;*.o,*.obj,*.exe&quot; --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 &quot;fossil add&quot;.</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 &quot;fossil commit&quot;. It's a useful command to run before
46 running &quot;fossil commit&quot; 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 &quot;fossil&quot;
76 will trigger an error since there is no longer any connection.</p>
77
--- www/foss-cklist.wiki
+++ www/foss-cklist.wiki
@@ -89,11 +89,11 @@
8989
9090
<li><p>The project has a website.
9191
9292
<li><p>Release version numbers are in the traditional X.Y or X.Y.Z format.
9393
94
-<li><p>Releases can be downloaded as tarball using
94
+<li><p>Releases can be downloaded as tarball using
9595
gzip or bzip2 compression.
9696
9797
<li><p>Releases unpack into a versioned top-level directory.
9898
(ex: "projectname-1.2.3/").
9999
@@ -102,12 +102,12 @@
102102
tarball.
103103
104104
<li><p>There are no incompatible licenses in the code.
105105
106106
<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
108108
in the public domain.
109109
110110
<li><p>There is an accurate change log in the code and on the website.
111111
112112
<li><p>There is documentation in the code and on the website.
113113
</ol>
114114
--- 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
--- www/fossil-from-msvc.wiki
+++ www/fossil-from-msvc.wiki
@@ -11,41 +11,41 @@
1111
<li>Tools &gt; External Tools, where the items in this list map
1212
to "External Tool X" that we'll add to our own Fossil
1313
menu later: </li>
1414
<ol type="1">
1515
<li>Rename the default "&#91;New Tool 1&#93;" to eg.
16
- "Commit"&nbsp;&nbsp;&nbsp;2.
16
+ "Commit"&nbsp;&nbsp;&nbsp;2.
1717
</li>
1818
<li>Change Command to where Fossil is located eg.
1919
"c:\fossil.exe"</li>
2020
<li>Change Arguments to the required command, eg.
21
- "commit -m".
21
+ "commit -m".
2222
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
2424
where the source files are currently checked out
2525
by Fossil (eg. c:\Workspace). It's also possible to use system
2626
variables such as "$(ProjectDir)" instead of hard-coding the path</li>
2727
<li>Check "Prompt for arguments", since Commit
2828
requires typing a comment. Useless for commands like Changes
2929
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
3333
opening a DOS box</li>
3434
<li>Click on OK</li>
3535
</ol>
3636
<li>Tools &gt; Customize &gt; Commands</li>
3737
<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
3939
New Menu". A new "Fossil" menu is displayed in the
4040
IDE's menu bar</li>
4141
<li>Click on "Modify Selection" to rename it
4242
"Fossil", and...</li>
4343
<li>Use the "Move Down" button to move it lower in
4444
the list</li>
4545
</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
5050
maps to "External Command X".</li>
5151
</ol>
5252
--- www/fossil-from-msvc.wiki
+++ www/fossil-from-msvc.wiki
@@ -11,41 +11,41 @@
11 <li>Tools &gt; 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 "&#91;New Tool 1&#93;" to eg.
16 "Commit"&nbsp;&nbsp;&nbsp;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 &gt; Customize &gt; 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 &gt; 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 "&#91;New Tool 1&#93;" to eg.
16 "Commit"&nbsp;&nbsp;&nbsp;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 &gt; Customize &gt; 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 @@
22
33
<h3>What Is Fossil?</h3>
44
55
<div style='width:200px;float:right;border:2px solid #446979;padding:10px;margin:0px 10px;'>
66
<ul>
7
-<li> [http://www.fossil-scm.org/download.html | Download]
7
+<li> [/uv/download.html | Download]
88
<li> [./quickstart.wiki | Quick Start]
99
<li> [./build.wiki | Install]
1010
<li> [../COPYRIGHT-BSD2.txt | License]
1111
<li> [./faq.wiki | FAQ]
1212
<li> [./changes.wiki | Change Log]
@@ -38,11 +38,11 @@
3838
([./webpage-ex.md|examples]) designed to promote situational awareness.
3939
4040
This entire website is just a running instance of Fossil.
4141
The pages you see here are all [./wikitheory.wiki | wiki] or
4242
[./embeddeddoc.wiki | embedded documentation] or (in the case of
43
- the [/uv/download.html|download] page)
43
+ the [/uv/download.html|download] page)
4444
[./unvers.wiki | unversioned files].
4545
When you clone Fossil from one of its
4646
[./selfhost.wiki | self-hosting repositories],
4747
you get more than just source code - you get this entire website.
4848
4949
--- 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 @@
11
<title>Import And Export</title>
22
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
44
[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
66
import/export a Fossil repository to most version control systems using
77
Git as an intermediary.
88
99
<h2>Git → Fossil</h2>
1010
@@ -20,11 +20,11 @@
2020
command is the name of a new Fossil repository that is created to hold the Git
2121
content.
2222
2323
The --git option is not actually required. The git-fast-export file format
2424
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
2626
interchange formats, and so for compatibility, use of the
2727
--git option is recommended.
2828
2929
<h2>Fossil → Git</h2>
3030
@@ -43,21 +43,60 @@
4343
Note that the "fossil export --git" command only exports the versioned files.
4444
Tickets and wiki and events are not exported, since Git does not understand
4545
those concepts.
4646
4747
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
4949
format that Fossil will generate. However,
5050
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
5252
option recommended.
5353
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>
64103
--- 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 @@
22
33
<h1>1.0 Introduction</h1>
44
55
The build process for Fossil is tricky in that the source code
66
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
88
[http://www.fossil-scm.org/download.html | precompiled binary]
99
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].
1212
So must people do not need to be concerned with the
1313
build complexities of Fossil. But hard-core developers who desire
1414
a deep understanding of how Fossil is put together can benefit
1515
from reviewing this article.
1616
1717
<a name="srctour"></a>
1818
<h1>2.0 Source Code Tour</h1>
1919
20
-The source code for Fossil is found in the
20
+The source code for Fossil is found in the
2121
[/dir?ci=trunk&name=src | src/] subdirectory of the
2222
source tree. The src/ subdirectory contains all code, including
2323
the code for the separate preprocessor programs.
2424
2525
Each preprocessor program is a separate C program implemented in
@@ -50,11 +50,11 @@
5050
The TH1 script engine is implemented using files:
5151
5252
7. th.c
5353
8. th.h
5454
55
-These two files are imports like the SQLite source files,
55
+These two files are imports like the SQLite source files,
5656
and so are not preprocessed.
5757
5858
The VERSION.h header file is generated from other information sources
5959
using a small program called:
6060
@@ -86,11 +86,11 @@
8686
8787
13. main.mk
8888
8989
The main.mk makefile is invoked from the Makefile in the top-level
9090
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
9292
other subdirectories (currently all in the win/ subdirectory).
9393
9494
All the other files in the src/ subdirectory (79 files at the time of
9595
this writing) are C source code files that are subject to the
9696
preprocessing steps described below. In the sequel, we will call these
@@ -109,11 +109,11 @@
109109
(The "manifest" and "manifest.uuid" files are automatically generated and
110110
updated by Fossil itself. See the [/help/setting | fossil set manifest]
111111
command for additional information.)
112112
113113
The VERSION.h header file is generated by
114
-a C program: src/mkversion.c.
114
+a C program: src/mkversion.c.
115115
To run the VERSION.h generator, first compile the src/mkversion.c
116116
source file into a command-line program (named "mkversion.exe")
117117
then run:
118118
119119
<blockquote><pre>
@@ -126,11 +126,11 @@
126126
in the root of the source tree are the three arguments and
127127
the generated VERSION.h file appears on standard output.
128128
129129
The builtin_data.h header file is generated by a C program: src/mkbuiltin.c.
130130
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
132132
builtin_data.h file, first compile the mkbuiltin.c program, then run:
133133
134134
<blockquote><pre>
135135
mkbuiltin.exe diff.tcl <i>OtherFiles...</i> &gt;builtin_data.h
136136
</pre></blockquote>
@@ -163,11 +163,11 @@
163163
Note that "src.c" in the above is a stand-in for the (79) regular source
164164
files of Fossil - all source files except for the exceptions described in
165165
section 2.0 above.
166166
167167
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.
169169
170170
<h2>4.2 The translate preprocessor</h2>
171171
172172
The translate preprocessor looks for lines of source code that begin
173173
with "@" and converts those lines into string constants or (depending on
@@ -181,11 +181,11 @@
181181
</pre></blockquote>
182182
183183
In this case, the "src.c" file represents any single source file from the
184184
set of ordinary source files as described in section 2.0 above. Note that
185185
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
187187
single "_" character at the end. But a new makefile can use any naming
188188
convention it wants - the "_" is not critical to the build process.
189189
190190
After being translated, the output files (the "src_.c" files) should be
191191
used for all subsequent preprocessing and compilation steps.
@@ -209,16 +209,16 @@
209209
<blockquote><pre>
210210
makeheaders src_.c:src.h sqlite3.h th.h VERSION.h
211211
</pre></blockquote>
212212
213213
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.
215215
216216
<h1>5.0 Compilation</h1>
217217
218218
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
220220
combined into a single executable using a C compiler. This can be done
221221
all at once, or each preprocessed source file can be compiled into a
222222
separate object code file and the resulting object code files linked
223223
together in a final step.
224224
@@ -247,11 +247,11 @@
247247
* -Dmain=sqlite3_main
248248
* -DSQLITE_OMIT_LOAD_EXTENSION=1
249249
250250
The "main()" routine in the shell must be changed into sqlite3_main()
251251
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
253253
[/help/sqlite3 | fossil sql] command is invoked.
254254
255255
All the other source code files can be compiled without any special
256256
options.
257257
258258
--- 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> &gt;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> &gt;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 @@
11
#!/usr/bin/tclsh
22
#
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.
57
#
68
#
79
set out [open download.html w]
810
fconfigure $out -encoding utf-8 -translation lf
911
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'>
3713
3814
<center><font size=4>}
3915
puts $out \
4016
"<b>To install Fossil &rarr;</b> download the stand-alone executable"
4117
puts $out \
@@ -45,46 +21,57 @@
4521
<a href="http://download.opensuse.org/repositories/home:/rmax:/fossil/">
4622
here.</a>
4723
Cryptographic checksums for download files are
4824
<a href="http://www.hwaci.com/fossil_download_checksums.html">here</a>.
4925
</small></p>
50
-</center>
51
-
5226
<table cellpadding="10">
5327
}
5428
55
-# Find all all unique timestamps.
29
+# Find all unique timestamps.
5630
#
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]
5937
set avers($version) 1
6038
}
6139
}
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
6245
6346
# Do all versions from newest to oldest
6447
#
6548
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"
6752
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&amp;y=ci"
56
+ puts $out " (<a href='$hr2'>$vdate($vers)</a>)"
57
+ }
58
+ puts $out "</b></center>"
6959
puts $out "</td></tr>"
7060
puts $out "<tr>"
7161
7262
foreach {prefix img desc} {
7363
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}
7565
fossil-openbsd-x86 openbsd.gif {OpenBSD 5.x x86}
7666
fossil-w32 win32.gif {Windows}
7767
fossil-src src.gif {Source Tarball}
7868
} {
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)]
8673
set units bytes
8774
if {$size>1024*1024} {
8875
set size [format %.2f [expr {$size/(1024.0*1024.0)}]]
8976
set units MiB
9077
} elseif {$size>1024} {
@@ -97,26 +84,23 @@
9784
} else {
9885
puts $out "<td>&nbsp;</td>"
9986
}
10087
}
10188
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
+# }
11098
}
11199
puts $out "<tr><td colspan=5><hr></td></tr>"
112100
113
-puts $out {</table></div>
114
-</body>
115
-</html>
116
-}
117
-
101
+puts $out {</table></center></div>}
118102
close $out
119103
120104
# Generate the checksum page
121105
#
122106
set out [open fossil_download_checksums.html w]
@@ -128,11 +112,15 @@
128112
<p>The following table shows the SHA1 checksums for the precompiled
129113
binaries available on the
130114
<a href="/download.html">Fossil website</a>.</p>
131115
<pre>}
132116
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"
136124
}
137125
puts $out {</pre></body></html>}
138126
close $out
139127
--- 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 &rarr;</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>&nbsp;</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 &rarr;</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&amp;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>&nbsp;</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
22
#
33
# Run this TCL script to generate a WIKI page that contains a
44
# permuted index of the various documentation files.
55
#
66
# tclsh mkindex.tcl
@@ -78,21 +78,24 @@
7878
wikitheory.wiki {Wiki In Fossil}
7979
/wiki_rules {Wiki Formatting Rules}
8080
}
8181
8282
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
+}
8487
foreach {file title} $doclist {
8588
set n [llength $title]
8689
regsub -all {\s+} $title { } title
87
- lappend permindex [list $title $file]
90
+ lappend permindex [list $title $file 1]
8891
for {set i 0} {$i<$n-1} {incr i} {
8992
set prefix [lrange $title 0 $i]
9093
set suffix [lrange $title [expr {$i+1}] end]
9194
set firstword [string tolower [lindex $suffix 0]]
9295
if {[lsearch $stopwords $firstword]<0} {
93
- lappend permindex [list "$suffix &mdash; $prefix" $file]
96
+ lappend permindex [list "$suffix &mdash; $prefix" $file 0]
9497
}
9598
}
9699
}
97100
set permindex [lsort -dict -index 0 $permindex]
98101
set out [open permutedindex.html w]
@@ -118,10 +121,11 @@
118121
</ul>
119122
<a name="pindex"></a>
120123
<h2>Permuted Index:</h2>
121124
<ul>}
122125
foreach entry $permindex {
123
- foreach {title file} $entry break
126
+ foreach {title file bold} $entry break
127
+ if {$bold} {set title <b>$title</b>}
124128
if {[string match /* $file]} {set file ../../..$file}
125129
puts $out "<li><a href=\"$file\">$title</a></li>"
126130
}
127131
puts $out "</ul></div>"
128132
--- 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 &mdash; $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 &mdash; $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
--- www/newrepo.wiki
+++ www/newrepo.wiki
@@ -53,11 +53,11 @@
5353
5454
<verbatim>
5555
stephan@ludo:~/fossil$ mkdir demo
5656
stephan@ludo:~/fossil$ cd demo
5757
stephan@ludo:~/fossil/demo$ fossil open ../demo.fossil
58
-stephan@ludo:~/fossil/demo$
58
+stephan@ludo:~/fossil/demo$
5959
</verbatim>
6060
6161
That creates a file called <tt>_FOSSIL_</tt> in the current
6262
directory, and this file contains all kinds of fossil-related
6363
information about your local repository. You can ignore it
6464
--- 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
--- www/permutedindex.html
+++ www/permutedindex.html
@@ -19,55 +19,53 @@
1919
<a name="pindex"></a>
2020
<h2>Permuted Index:</h2>
2121
<ul>
2222
<li><a href="fiveminutes.wiki">5 Minutes as a Single User &mdash; Update and Running in</a></li>
2323
<li><a href="fossil-from-msvc.wiki">2010 IDE &mdash; 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 &mdash; 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>
2726
<li><a href="copyright-release.html">Agreement &mdash; Contributor License</a></li>
2827
<li><a href="delta_encoder_algorithm.wiki">Algorithm &mdash; Fossil Delta Encoding</a></li>
2928
<li><a href="blame.wiki">Algorithm Of Fossil &mdash; The Annotate/Blame</a></li>
3029
<li><a href="blame.wiki">Annotate/Blame Algorithm Of Fossil &mdash; The</a></li>
3130
<li><a href="customskin.md">Appearance of Web Pages &mdash; Theming: Customizing The</a></li>
32
-<li><a href="fiveminutes.wiki">as a Single User &mdash; Update and Running in 5 Minutes</a></li>
3331
<li><a href="faq.wiki">Asked Questions &mdash; Frequently</a></li>
3432
<li><a href="password.wiki">Authentication &mdash; 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>
3634
<li><a href="antibot.wiki">Bots &mdash; Defense against Spiders and</a></li>
3735
<li><a href="private.wiki">Branches &mdash; 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>
4038
<li><a href="makefile.wiki">Build Process &mdash; The Fossil</a></li>
4139
<li><a href="aboutcgi.wiki">CGI Works In Fossil &mdash; How</a></li>
4240
<li><a href="changes.wiki">Changelog &mdash; 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>
4543
<li><a href="checkin.wiki">Checklist &mdash; Check-in</a></li>
4644
<li><a href="../test/release-checklist.wiki">Checklist &mdash; 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>
4846
<li><a href="selfcheck.wiki">Checks &mdash; 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>
5048
<li><a href="contribute.wiki">Code or Documentation To The Fossil Project &mdash; Contributing</a></li>
5149
<li><a href="style.wiki">Code Style Guidelines &mdash; Source</a></li>
5250
<li><a href="../../../help">Commands and Webpages &mdash; 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>
5452
<li><a href="concepts.wiki">Concepts &mdash; Fossil Core</a></li>
5553
<li><a href="server.wiki">Configure A Fossil Server &mdash; How To</a></li>
5654
<li><a href="shunning.wiki">Content From Fossil &mdash; 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>
5957
<li><a href="whyusefossil.wiki">Control &mdash; Benefits Of Version</a></li>
6058
<li><a href="concepts.wiki">Core Concepts &mdash; Fossil</a></li>
6159
<li><a href="newrepo.wiki">Create A New Fossil Repository &mdash; 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>
6361
<li><a href="qandc.wiki">Criticisms &mdash; Questions And</a></li>
6462
<li><a href="customskin.md">Customizing The Appearance of Web Pages &mdash; 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>
6664
<li><a href="customgraph.md">Customizing the Timeline Graph &mdash; Theming:</a></li>
6765
<li><a href="tech_overview.wiki">Databases Used By Fossil &mdash; 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>
6967
<li><a href="shunning.wiki">Deleting Content From Fossil &mdash; Shunning:</a></li>
7068
<li><a href="private.wiki">Deleting Private Branches &mdash; Creating, Syncing, and</a></li>
7169
<li><a href="delta_encoder_algorithm.wiki">Delta Encoding Algorithm &mdash; Fossil</a></li>
7270
<li><a href="delta_format.wiki">Delta Format &mdash; Fossil</a></li>
7371
<li><a href="tech_overview.wiki">Design And Implementation Of Fossil &mdash; A Technical Overview Of The</a></li>
@@ -74,15 +72,15 @@
7472
<li><a href="theory1.wiki">Design Of The Fossil DVCS &mdash; Thoughts On The</a></li>
7573
<li><a href="embeddeddoc.wiki">Documentation &mdash; Embedded Project</a></li>
7674
<li><a href="contribute.wiki">Documentation To The Fossil Project &mdash; Contributing Code or</a></li>
7775
<li><a href="theory1.wiki">DVCS &mdash; Thoughts On The Design Of The Fossil</a></li>
7876
<li><a href="quotes.wiki">DVCSes in General &mdash; 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>
8078
<li><a href="delta_encoder_algorithm.wiki">Encoding Algorithm &mdash; Fossil Delta</a></li>
8179
<li><a href="encryptedrepos.wiki">Encrypted Repositories &mdash; 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>
8482
<li><a href="webpage-ex.md">Examples &mdash; Webpage</a></li>
8583
<li><a href="inout.wiki">Export To And From Git &mdash; Import And</a></li>
8684
<li><a href="fossil-from-msvc.wiki">Express 2010 IDE &mdash; Integrating Fossil in the Microsoft</a></li>
8785
<li><a href="adding_code.wiki">Features To Fossil &mdash; Adding New</a></li>
8886
<li><a href="fileformat.wiki">File Format &mdash; Fossil</a></li>
@@ -90,56 +88,54 @@
9088
<li><a href="branching.wiki">Forking, Merging, and Tagging &mdash; Branching,</a></li>
9189
<li><a href="delta_format.wiki">Format &mdash; Fossil Delta</a></li>
9290
<li><a href="fileformat.wiki">Format &mdash; Fossil File</a></li>
9391
<li><a href="../../../md_rules">Formatting Rules &mdash; Markdown</a></li>
9492
<li><a href="../../../wiki_rules">Formatting Rules &mdash; 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>
106104
<li><a href="quotes.wiki">Fossil, Git, and DVCSes in General &mdash; 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 &mdash; Shunning: Deleting Content</a></li>
109
-<li><a href="inout.wiki">From Git &mdash; Import And Export To And</a></li>
105
+<li><a href="faq.wiki"><b>Frequently Asked Questions</b></a></li>
110106
<li><a href="quotes.wiki">General &mdash; Quotes: What People Are Saying About Fossil, Git, and DVCSes in</a></li>
111107
<li><a href="fossil-v-git.wiki">Git &mdash; Fossil Versus</a></li>
112108
<li><a href="inout.wiki">Git &mdash; Import And Export To And From</a></li>
113109
<li><a href="quotes.wiki">Git, and DVCSes in General &mdash; Quotes: What People Are Saying About Fossil,</a></li>
114110
<li><a href="env-opts.md">Global Options &mdash; Environment Variables and</a></li>
115111
<li><a href="customgraph.md">Graph &mdash; Theming: Customizing the Timeline</a></li>
116112
<li><a href="quickstart.wiki">Guide &mdash; Fossil Quick Start</a></li>
117113
<li><a href="style.wiki">Guidelines &mdash; 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>
120116
<li><a href="hints.wiki">Hints &mdash; 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>
122118
<li><a href="selfhost.wiki">Hosting Repositories &mdash; 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>
127123
<li><a href="hacker-howto.wiki">How-To &mdash; Hacker</a></li>
128124
<li><a href="fossil-from-msvc.wiki">IDE &mdash; Integrating Fossil in the Microsoft Express 2010</a></li>
129125
<li><a href="tech_overview.wiki">Implementation Of Fossil &mdash; 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>
131127
<li><a href="build.wiki">Installing Fossil &mdash; 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>
133129
<li><a href="selfcheck.wiki">Integrity Self Checks &mdash; Fossil Repository</a></li>
134130
<li><a href="webui.wiki">Interface &mdash; The Fossil Web</a></li>
135131
<li><a href="th1.md">Language &mdash; The TH1 Scripting</a></li>
136132
<li><a href="copyright-release.html">License Agreement &mdash; 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>
138134
<li><a href="password.wiki">Management And Authentication &mdash; Password</a></li>
139135
<li><a href="../../../sitemap">Map &mdash; 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>
141137
<li><a href="branching.wiki">Merging, and Tagging &mdash; Branching, Forking,</a></li>
142138
<li><a href="fossil-from-msvc.wiki">Microsoft Express 2010 IDE &mdash; Integrating Fossil in the</a></li>
143139
<li><a href="fiveminutes.wiki">Minutes as a Single User &mdash; Update and Running in 5</a></li>
144140
<li><a href="checkin_names.wiki">Names &mdash; Check-in And Version</a></li>
145141
<li><a href="adding_code.wiki">New Features To Fossil &mdash; Adding</a></li>
@@ -148,47 +144,46 @@
148144
<li><a href="pop.wiki">Operations &mdash; Principles Of</a></li>
149145
<li><a href="env-opts.md">Options &mdash; Environment Variables and Global</a></li>
150146
<li><a href="tech_overview.wiki">Overview Of The Design And Implementation Of Fossil &mdash; A Technical</a></li>
151147
<li><a href="index.wiki">Page &mdash; Home</a></li>
152148
<li><a href="customskin.md">Pages &mdash; 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>
154150
<li><a href="quotes.wiki">People Are Saying About Fossil, Git, and DVCSes in General &mdash; 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>
158154
<li><a href="private.wiki">Private Branches &mdash; Creating, Syncing, and Deleting</a></li>
159155
<li><a href="makefile.wiki">Process &mdash; The Fossil Build</a></li>
160156
<li><a href="contribute.wiki">Project &mdash; Contributing Code or Documentation To The Fossil</a></li>
161157
<li><a href="embeddeddoc.wiki">Project Documentation &mdash; Embedded</a></li>
162158
<li><a href="foss-cklist.wiki">Projects &mdash; Checklist For Successful Open-Source</a></li>
163159
<li><a href="childprojects.wiki">Projects &mdash; Child</a></li>
164160
<li><a href="sync.wiki">Protocol &mdash; The Fossil Sync</a></li>
165161
<li><a href="faq.wiki">Questions &mdash; 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>
167163
<li><a href="quickstart.wiki">Quick Start Guide &mdash; 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>
169165
<li><a href="selfhost.wiki">Repositories &mdash; Fossil Self Hosting</a></li>
170166
<li><a href="encryptedrepos.wiki">Repositories &mdash; How To Use Encrypted</a></li>
171167
<li><a href="newrepo.wiki">Repository &mdash; How To Create A New Fossil</a></li>
172168
<li><a href="selfcheck.wiki">Repository Integrity Self Checks &mdash; Fossil</a></li>
173
-<li><a href="reviews.wiki">Reviews</a></li>
169
+<li><a href="reviews.wiki"><b>Reviews</b></a></li>
174170
<li><a href="../../../md_rules">Rules &mdash; Markdown Formatting</a></li>
175171
<li><a href="../../../wiki_rules">Rules &mdash; Wiki Formatting</a></li>
176172
<li><a href="fiveminutes.wiki">Running in 5 Minutes as a Single User &mdash; Update and</a></li>
177173
<li><a href="quotes.wiki">Saying About Fossil, Git, and DVCSes in General &mdash; Quotes: What People Are</a></li>
178174
<li><a href="th1.md">Scripting Language &mdash; The TH1</a></li>
179175
<li><a href="selfcheck.wiki">Self Checks &mdash; Fossil Repository Integrity</a></li>
180176
<li><a href="selfhost.wiki">Self Hosting Repositories &mdash; Fossil</a></li>
181177
<li><a href="server.wiki">Server &mdash; How To Configure A Fossil</a></li>
182178
<li><a href="settings.wiki">Settings &mdash; Fossil</a></li>
183
-<li><a href="whyusefossil.wiki">Should Use Fossil &mdash; 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>
185180
<li><a href="fiveminutes.wiki">Single User &mdash; 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>
188183
<li><a href="antibot.wiki">Spiders and Bots &mdash; 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>
190185
<li><a href="ssl.wiki">SSL with Fossil &mdash; Using</a></li>
191186
<li><a href="quickstart.wiki">Start Guide &mdash; Fossil Quick</a></li>
192187
<li><a href="stats.wiki">Statistics &mdash; Performance</a></li>
193188
<li><a href="style.wiki">Style Guidelines &mdash; Source Code</a></li>
194189
<li><a href="foss-cklist.wiki">Successful Open-Source Projects &mdash; Checklist For</a></li>
@@ -198,42 +193,39 @@
198193
<li><a href="tickets.wiki">System &mdash; The Fossil Ticket</a></li>
199194
<li><a href="branching.wiki">Tagging &mdash; Branching, Forking, Merging, and</a></li>
200195
<li><a href="tech_overview.wiki">Technical Overview Of The Design And Implementation Of Fossil &mdash; A</a></li>
201196
<li><a href="../test/release-checklist.wiki">Testing Checklist &mdash; Pre-Release</a></li>
202197
<li><a href="th1.md">TH1 Scripting Language &mdash; 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>
212207
<li><a href="custom_ticket.wiki">Ticket System &mdash; Customizing The</a></li>
213208
<li><a href="tickets.wiki">Ticket System &mdash; The Fossil</a></li>
214209
<li><a href="customgraph.md">Timeline Graph &mdash; Theming: Customizing the</a></li>
215210
<li><a href="hints.wiki">Tips And Usage Hints &mdash; Fossil</a></li>
216211
<li><a href="bugtheory.wiki">Tracking In Fossil &mdash; 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>
219214
<li><a href="hints.wiki">Usage Hints &mdash; Fossil Tips And</a></li>
220
-<li><a href="encryptedrepos.wiki">Use Encrypted Repositories &mdash; How To</a></li>
221
-<li><a href="whyusefossil.wiki">Use Fossil &mdash; Why You Should</a></li>
222215
<li><a href="fiveminutes.wiki">User &mdash; 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>
224217
<li><a href="env-opts.md">Variables and Global Options &mdash; Environment</a></li>
225218
<li><a href="whyusefossil.wiki">Version Control &mdash; Benefits Of</a></li>
226219
<li><a href="checkin_names.wiki">Version Names &mdash; Check-in And</a></li>
227220
<li><a href="fossil-v-git.wiki">Versus Git &mdash; Fossil</a></li>
228221
<li><a href="webui.wiki">Web Interface &mdash; The Fossil</a></li>
229222
<li><a href="customskin.md">Web Pages &mdash; 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>
231224
<li><a href="../../../help">Webpages &mdash; Lists of Commands and</a></li>
232225
<li><a href="quotes.wiki">What People Are Saying About Fossil, Git, and DVCSes in General &mdash; 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 &mdash; 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>
237229
<li><a href="aboutcgi.wiki">Works In Fossil &mdash; How CGI</a></li>
238230
<li><a href="whyusefossil.wiki">You Should Use Fossil &mdash; Why</a></li>
239231
</ul></div>
240232
--- 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 &mdash; Update and Running in</a></li>
23 <li><a href="fossil-from-msvc.wiki">2010 IDE &mdash; 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 &mdash; Defense</a></li>
27 <li><a href="copyright-release.html">Agreement &mdash; Contributor License</a></li>
28 <li><a href="delta_encoder_algorithm.wiki">Algorithm &mdash; Fossil Delta Encoding</a></li>
29 <li><a href="blame.wiki">Algorithm Of Fossil &mdash; The Annotate/Blame</a></li>
30 <li><a href="blame.wiki">Annotate/Blame Algorithm Of Fossil &mdash; The</a></li>
31 <li><a href="customskin.md">Appearance of Web Pages &mdash; Theming: Customizing The</a></li>
32 <li><a href="fiveminutes.wiki">as a Single User &mdash; Update and Running in 5 Minutes</a></li>
33 <li><a href="faq.wiki">Asked Questions &mdash; Frequently</a></li>
34 <li><a href="password.wiki">Authentication &mdash; Password Management And</a></li>
35 <li><a href="whyusefossil.wiki">Benefits Of Version Control</a></li>
36 <li><a href="antibot.wiki">Bots &mdash; Defense against Spiders and</a></li>
37 <li><a href="private.wiki">Branches &mdash; 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 &mdash; The Fossil</a></li>
41 <li><a href="aboutcgi.wiki">CGI Works In Fossil &mdash; How</a></li>
42 <li><a href="changes.wiki">Changelog &mdash; 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 &mdash; Check-in</a></li>
46 <li><a href="../test/release-checklist.wiki">Checklist &mdash; 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 &mdash; 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 &mdash; Contributing</a></li>
51 <li><a href="style.wiki">Code Style Guidelines &mdash; Source</a></li>
52 <li><a href="../../../help">Commands and Webpages &mdash; Lists of</a></li>
53 <li><a href="build.wiki">Compiling and Installing Fossil</a></li>
54 <li><a href="concepts.wiki">Concepts &mdash; Fossil Core</a></li>
55 <li><a href="server.wiki">Configure A Fossil Server &mdash; How To</a></li>
56 <li><a href="shunning.wiki">Content From Fossil &mdash; 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 &mdash; Benefits Of Version</a></li>
60 <li><a href="concepts.wiki">Core Concepts &mdash; Fossil</a></li>
61 <li><a href="newrepo.wiki">Create A New Fossil Repository &mdash; 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 &mdash; Questions And</a></li>
64 <li><a href="customskin.md">Customizing The Appearance of Web Pages &mdash; 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 &mdash; Theming:</a></li>
67 <li><a href="tech_overview.wiki">Databases Used By Fossil &mdash; 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 &mdash; Shunning:</a></li>
70 <li><a href="private.wiki">Deleting Private Branches &mdash; Creating, Syncing, and</a></li>
71 <li><a href="delta_encoder_algorithm.wiki">Delta Encoding Algorithm &mdash; Fossil</a></li>
72 <li><a href="delta_format.wiki">Delta Format &mdash; Fossil</a></li>
73 <li><a href="tech_overview.wiki">Design And Implementation Of Fossil &mdash; A Technical Overview Of The</a></li>
@@ -74,15 +72,15 @@
74 <li><a href="theory1.wiki">Design Of The Fossil DVCS &mdash; Thoughts On The</a></li>
75 <li><a href="embeddeddoc.wiki">Documentation &mdash; Embedded Project</a></li>
76 <li><a href="contribute.wiki">Documentation To The Fossil Project &mdash; Contributing Code or</a></li>
77 <li><a href="theory1.wiki">DVCS &mdash; Thoughts On The Design Of The Fossil</a></li>
78 <li><a href="quotes.wiki">DVCSes in General &mdash; 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 &mdash; Fossil Delta</a></li>
81 <li><a href="encryptedrepos.wiki">Encrypted Repositories &mdash; 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 &mdash; Webpage</a></li>
85 <li><a href="inout.wiki">Export To And From Git &mdash; Import And</a></li>
86 <li><a href="fossil-from-msvc.wiki">Express 2010 IDE &mdash; Integrating Fossil in the Microsoft</a></li>
87 <li><a href="adding_code.wiki">Features To Fossil &mdash; Adding New</a></li>
88 <li><a href="fileformat.wiki">File Format &mdash; Fossil</a></li>
@@ -90,56 +88,54 @@
90 <li><a href="branching.wiki">Forking, Merging, and Tagging &mdash; Branching,</a></li>
91 <li><a href="delta_format.wiki">Format &mdash; Fossil Delta</a></li>
92 <li><a href="fileformat.wiki">Format &mdash; Fossil File</a></li>
93 <li><a href="../../../md_rules">Formatting Rules &mdash; Markdown</a></li>
94 <li><a href="../../../wiki_rules">Formatting Rules &mdash; 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 &mdash; 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 &mdash; Shunning: Deleting Content</a></li>
109 <li><a href="inout.wiki">From Git &mdash; Import And Export To And</a></li>
110 <li><a href="quotes.wiki">General &mdash; Quotes: What People Are Saying About Fossil, Git, and DVCSes in</a></li>
111 <li><a href="fossil-v-git.wiki">Git &mdash; Fossil Versus</a></li>
112 <li><a href="inout.wiki">Git &mdash; Import And Export To And From</a></li>
113 <li><a href="quotes.wiki">Git, and DVCSes in General &mdash; Quotes: What People Are Saying About Fossil,</a></li>
114 <li><a href="env-opts.md">Global Options &mdash; Environment Variables and</a></li>
115 <li><a href="customgraph.md">Graph &mdash; Theming: Customizing the Timeline</a></li>
116 <li><a href="quickstart.wiki">Guide &mdash; Fossil Quick Start</a></li>
117 <li><a href="style.wiki">Guidelines &mdash; 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 &mdash; Fossil Tips And Usage</a></li>
121 <li><a href="index.wiki">Home Page</a></li>
122 <li><a href="selfhost.wiki">Hosting Repositories &mdash; 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 &mdash; Hacker</a></li>
128 <li><a href="fossil-from-msvc.wiki">IDE &mdash; Integrating Fossil in the Microsoft Express 2010</a></li>
129 <li><a href="tech_overview.wiki">Implementation Of Fossil &mdash; 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 &mdash; 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 &mdash; Fossil Repository</a></li>
134 <li><a href="webui.wiki">Interface &mdash; The Fossil Web</a></li>
135 <li><a href="th1.md">Language &mdash; The TH1 Scripting</a></li>
136 <li><a href="copyright-release.html">License Agreement &mdash; Contributor</a></li>
137 <li><a href="../../../help">Lists of Commands and Webpages</a></li>
138 <li><a href="password.wiki">Management And Authentication &mdash; Password</a></li>
139 <li><a href="../../../sitemap">Map &mdash; Site</a></li>
140 <li><a href="../../../md_rules">Markdown Formatting Rules</a></li>
141 <li><a href="branching.wiki">Merging, and Tagging &mdash; Branching, Forking,</a></li>
142 <li><a href="fossil-from-msvc.wiki">Microsoft Express 2010 IDE &mdash; Integrating Fossil in the</a></li>
143 <li><a href="fiveminutes.wiki">Minutes as a Single User &mdash; Update and Running in 5</a></li>
144 <li><a href="checkin_names.wiki">Names &mdash; Check-in And Version</a></li>
145 <li><a href="adding_code.wiki">New Features To Fossil &mdash; Adding</a></li>
@@ -148,47 +144,46 @@
148 <li><a href="pop.wiki">Operations &mdash; Principles Of</a></li>
149 <li><a href="env-opts.md">Options &mdash; Environment Variables and Global</a></li>
150 <li><a href="tech_overview.wiki">Overview Of The Design And Implementation Of Fossil &mdash; A Technical</a></li>
151 <li><a href="index.wiki">Page &mdash; Home</a></li>
152 <li><a href="customskin.md">Pages &mdash; 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 &mdash; 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 &mdash; Creating, Syncing, and Deleting</a></li>
159 <li><a href="makefile.wiki">Process &mdash; The Fossil Build</a></li>
160 <li><a href="contribute.wiki">Project &mdash; Contributing Code or Documentation To The Fossil</a></li>
161 <li><a href="embeddeddoc.wiki">Project Documentation &mdash; Embedded</a></li>
162 <li><a href="foss-cklist.wiki">Projects &mdash; Checklist For Successful Open-Source</a></li>
163 <li><a href="childprojects.wiki">Projects &mdash; Child</a></li>
164 <li><a href="sync.wiki">Protocol &mdash; The Fossil Sync</a></li>
165 <li><a href="faq.wiki">Questions &mdash; Frequently Asked</a></li>
166 <li><a href="qandc.wiki">Questions And Criticisms</a></li>
167 <li><a href="quickstart.wiki">Quick Start Guide &mdash; 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 &mdash; Fossil Self Hosting</a></li>
170 <li><a href="encryptedrepos.wiki">Repositories &mdash; How To Use Encrypted</a></li>
171 <li><a href="newrepo.wiki">Repository &mdash; How To Create A New Fossil</a></li>
172 <li><a href="selfcheck.wiki">Repository Integrity Self Checks &mdash; Fossil</a></li>
173 <li><a href="reviews.wiki">Reviews</a></li>
174 <li><a href="../../../md_rules">Rules &mdash; Markdown Formatting</a></li>
175 <li><a href="../../../wiki_rules">Rules &mdash; Wiki Formatting</a></li>
176 <li><a href="fiveminutes.wiki">Running in 5 Minutes as a Single User &mdash; Update and</a></li>
177 <li><a href="quotes.wiki">Saying About Fossil, Git, and DVCSes in General &mdash; Quotes: What People Are</a></li>
178 <li><a href="th1.md">Scripting Language &mdash; The TH1</a></li>
179 <li><a href="selfcheck.wiki">Self Checks &mdash; Fossil Repository Integrity</a></li>
180 <li><a href="selfhost.wiki">Self Hosting Repositories &mdash; Fossil</a></li>
181 <li><a href="server.wiki">Server &mdash; How To Configure A Fossil</a></li>
182 <li><a href="settings.wiki">Settings &mdash; Fossil</a></li>
183 <li><a href="whyusefossil.wiki">Should Use Fossil &mdash; 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 &mdash; 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 &mdash; 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 &mdash; Using</a></li>
191 <li><a href="quickstart.wiki">Start Guide &mdash; Fossil Quick</a></li>
192 <li><a href="stats.wiki">Statistics &mdash; Performance</a></li>
193 <li><a href="style.wiki">Style Guidelines &mdash; Source Code</a></li>
194 <li><a href="foss-cklist.wiki">Successful Open-Source Projects &mdash; Checklist For</a></li>
@@ -198,42 +193,39 @@
198 <li><a href="tickets.wiki">System &mdash; The Fossil Ticket</a></li>
199 <li><a href="branching.wiki">Tagging &mdash; Branching, Forking, Merging, and</a></li>
200 <li><a href="tech_overview.wiki">Technical Overview Of The Design And Implementation Of Fossil &mdash; A</a></li>
201 <li><a href="../test/release-checklist.wiki">Testing Checklist &mdash; Pre-Release</a></li>
202 <li><a href="th1.md">TH1 Scripting Language &mdash; 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 &mdash; Customizing The</a></li>
213 <li><a href="tickets.wiki">Ticket System &mdash; The Fossil</a></li>
214 <li><a href="customgraph.md">Timeline Graph &mdash; Theming: Customizing the</a></li>
215 <li><a href="hints.wiki">Tips And Usage Hints &mdash; Fossil</a></li>
216 <li><a href="bugtheory.wiki">Tracking In Fossil &mdash; 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 &mdash; Fossil Tips And</a></li>
220 <li><a href="encryptedrepos.wiki">Use Encrypted Repositories &mdash; How To</a></li>
221 <li><a href="whyusefossil.wiki">Use Fossil &mdash; Why You Should</a></li>
222 <li><a href="fiveminutes.wiki">User &mdash; 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 &mdash; Environment</a></li>
225 <li><a href="whyusefossil.wiki">Version Control &mdash; Benefits Of</a></li>
226 <li><a href="checkin_names.wiki">Version Names &mdash; Check-in And</a></li>
227 <li><a href="fossil-v-git.wiki">Versus Git &mdash; Fossil</a></li>
228 <li><a href="webui.wiki">Web Interface &mdash; The Fossil</a></li>
229 <li><a href="customskin.md">Web Pages &mdash; Theming: Customizing The Appearance of</a></li>
230 <li><a href="webpage-ex.md">Webpage Examples</a></li>
231 <li><a href="../../../help">Webpages &mdash; Lists of Commands and</a></li>
232 <li><a href="quotes.wiki">What People Are Saying About Fossil, Git, and DVCSes in General &mdash; 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 &mdash; Using SSL</a></li>
237 <li><a href="aboutcgi.wiki">Works In Fossil &mdash; How CGI</a></li>
238 <li><a href="whyusefossil.wiki">You Should Use Fossil &mdash; 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 &mdash; Update and Running in</a></li>
23 <li><a href="fossil-from-msvc.wiki">2010 IDE &mdash; 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 &mdash; Contributor License</a></li>
27 <li><a href="delta_encoder_algorithm.wiki">Algorithm &mdash; Fossil Delta Encoding</a></li>
28 <li><a href="blame.wiki">Algorithm Of Fossil &mdash; The Annotate/Blame</a></li>
29 <li><a href="blame.wiki">Annotate/Blame Algorithm Of Fossil &mdash; The</a></li>
30 <li><a href="customskin.md">Appearance of Web Pages &mdash; Theming: Customizing The</a></li>
 
31 <li><a href="faq.wiki">Asked Questions &mdash; Frequently</a></li>
32 <li><a href="password.wiki">Authentication &mdash; 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 &mdash; Defense against Spiders and</a></li>
35 <li><a href="private.wiki">Branches &mdash; 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 &mdash; The Fossil</a></li>
39 <li><a href="aboutcgi.wiki">CGI Works In Fossil &mdash; How</a></li>
40 <li><a href="changes.wiki">Changelog &mdash; 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 &mdash; Check-in</a></li>
44 <li><a href="../test/release-checklist.wiki">Checklist &mdash; 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 &mdash; 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 &mdash; Contributing</a></li>
49 <li><a href="style.wiki">Code Style Guidelines &mdash; Source</a></li>
50 <li><a href="../../../help">Commands and Webpages &mdash; 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 &mdash; Fossil Core</a></li>
53 <li><a href="server.wiki">Configure A Fossil Server &mdash; How To</a></li>
54 <li><a href="shunning.wiki">Content From Fossil &mdash; 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 &mdash; Benefits Of Version</a></li>
58 <li><a href="concepts.wiki">Core Concepts &mdash; Fossil</a></li>
59 <li><a href="newrepo.wiki">Create A New Fossil Repository &mdash; 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 &mdash; Questions And</a></li>
62 <li><a href="customskin.md">Customizing The Appearance of Web Pages &mdash; 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 &mdash; Theming:</a></li>
65 <li><a href="tech_overview.wiki">Databases Used By Fossil &mdash; 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 &mdash; Shunning:</a></li>
68 <li><a href="private.wiki">Deleting Private Branches &mdash; Creating, Syncing, and</a></li>
69 <li><a href="delta_encoder_algorithm.wiki">Delta Encoding Algorithm &mdash; Fossil</a></li>
70 <li><a href="delta_format.wiki">Delta Format &mdash; Fossil</a></li>
71 <li><a href="tech_overview.wiki">Design And Implementation Of Fossil &mdash; A Technical Overview Of The</a></li>
@@ -74,15 +72,15 @@
72 <li><a href="theory1.wiki">Design Of The Fossil DVCS &mdash; Thoughts On The</a></li>
73 <li><a href="embeddeddoc.wiki">Documentation &mdash; Embedded Project</a></li>
74 <li><a href="contribute.wiki">Documentation To The Fossil Project &mdash; Contributing Code or</a></li>
75 <li><a href="theory1.wiki">DVCS &mdash; Thoughts On The Design Of The Fossil</a></li>
76 <li><a href="quotes.wiki">DVCSes in General &mdash; 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 &mdash; Fossil Delta</a></li>
79 <li><a href="encryptedrepos.wiki">Encrypted Repositories &mdash; 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 &mdash; Webpage</a></li>
83 <li><a href="inout.wiki">Export To And From Git &mdash; Import And</a></li>
84 <li><a href="fossil-from-msvc.wiki">Express 2010 IDE &mdash; Integrating Fossil in the Microsoft</a></li>
85 <li><a href="adding_code.wiki">Features To Fossil &mdash; Adding New</a></li>
86 <li><a href="fileformat.wiki">File Format &mdash; Fossil</a></li>
@@ -90,56 +88,54 @@
88 <li><a href="branching.wiki">Forking, Merging, and Tagging &mdash; Branching,</a></li>
89 <li><a href="delta_format.wiki">Format &mdash; Fossil Delta</a></li>
90 <li><a href="fileformat.wiki">Format &mdash; Fossil File</a></li>
91 <li><a href="../../../md_rules">Formatting Rules &mdash; Markdown</a></li>
92 <li><a href="../../../wiki_rules">Formatting Rules &mdash; 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 &mdash; 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 &mdash; Quotes: What People Are Saying About Fossil, Git, and DVCSes in</a></li>
107 <li><a href="fossil-v-git.wiki">Git &mdash; Fossil Versus</a></li>
108 <li><a href="inout.wiki">Git &mdash; Import And Export To And From</a></li>
109 <li><a href="quotes.wiki">Git, and DVCSes in General &mdash; Quotes: What People Are Saying About Fossil,</a></li>
110 <li><a href="env-opts.md">Global Options &mdash; Environment Variables and</a></li>
111 <li><a href="customgraph.md">Graph &mdash; Theming: Customizing the Timeline</a></li>
112 <li><a href="quickstart.wiki">Guide &mdash; Fossil Quick Start</a></li>
113 <li><a href="style.wiki">Guidelines &mdash; 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 &mdash; 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 &mdash; 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 &mdash; Hacker</a></li>
124 <li><a href="fossil-from-msvc.wiki">IDE &mdash; Integrating Fossil in the Microsoft Express 2010</a></li>
125 <li><a href="tech_overview.wiki">Implementation Of Fossil &mdash; 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 &mdash; 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 &mdash; Fossil Repository</a></li>
130 <li><a href="webui.wiki">Interface &mdash; The Fossil Web</a></li>
131 <li><a href="th1.md">Language &mdash; The TH1 Scripting</a></li>
132 <li><a href="copyright-release.html">License Agreement &mdash; 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 &mdash; Password</a></li>
135 <li><a href="../../../sitemap">Map &mdash; 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 &mdash; Branching, Forking,</a></li>
138 <li><a href="fossil-from-msvc.wiki">Microsoft Express 2010 IDE &mdash; Integrating Fossil in the</a></li>
139 <li><a href="fiveminutes.wiki">Minutes as a Single User &mdash; Update and Running in 5</a></li>
140 <li><a href="checkin_names.wiki">Names &mdash; Check-in And Version</a></li>
141 <li><a href="adding_code.wiki">New Features To Fossil &mdash; Adding</a></li>
@@ -148,47 +144,46 @@
144 <li><a href="pop.wiki">Operations &mdash; Principles Of</a></li>
145 <li><a href="env-opts.md">Options &mdash; Environment Variables and Global</a></li>
146 <li><a href="tech_overview.wiki">Overview Of The Design And Implementation Of Fossil &mdash; A Technical</a></li>
147 <li><a href="index.wiki">Page &mdash; Home</a></li>
148 <li><a href="customskin.md">Pages &mdash; 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 &mdash; 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 &mdash; Creating, Syncing, and Deleting</a></li>
155 <li><a href="makefile.wiki">Process &mdash; The Fossil Build</a></li>
156 <li><a href="contribute.wiki">Project &mdash; Contributing Code or Documentation To The Fossil</a></li>
157 <li><a href="embeddeddoc.wiki">Project Documentation &mdash; Embedded</a></li>
158 <li><a href="foss-cklist.wiki">Projects &mdash; Checklist For Successful Open-Source</a></li>
159 <li><a href="childprojects.wiki">Projects &mdash; Child</a></li>
160 <li><a href="sync.wiki">Protocol &mdash; The Fossil Sync</a></li>
161 <li><a href="faq.wiki">Questions &mdash; 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 &mdash; 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 &mdash; Fossil Self Hosting</a></li>
166 <li><a href="encryptedrepos.wiki">Repositories &mdash; How To Use Encrypted</a></li>
167 <li><a href="newrepo.wiki">Repository &mdash; How To Create A New Fossil</a></li>
168 <li><a href="selfcheck.wiki">Repository Integrity Self Checks &mdash; Fossil</a></li>
169 <li><a href="reviews.wiki"><b>Reviews</b></a></li>
170 <li><a href="../../../md_rules">Rules &mdash; Markdown Formatting</a></li>
171 <li><a href="../../../wiki_rules">Rules &mdash; Wiki Formatting</a></li>
172 <li><a href="fiveminutes.wiki">Running in 5 Minutes as a Single User &mdash; Update and</a></li>
173 <li><a href="quotes.wiki">Saying About Fossil, Git, and DVCSes in General &mdash; Quotes: What People Are</a></li>
174 <li><a href="th1.md">Scripting Language &mdash; The TH1</a></li>
175 <li><a href="selfcheck.wiki">Self Checks &mdash; Fossil Repository Integrity</a></li>
176 <li><a href="selfhost.wiki">Self Hosting Repositories &mdash; Fossil</a></li>
177 <li><a href="server.wiki">Server &mdash; How To Configure A Fossil</a></li>
178 <li><a href="settings.wiki">Settings &mdash; 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 &mdash; 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 &mdash; 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 &mdash; Using</a></li>
186 <li><a href="quickstart.wiki">Start Guide &mdash; Fossil Quick</a></li>
187 <li><a href="stats.wiki">Statistics &mdash; Performance</a></li>
188 <li><a href="style.wiki">Style Guidelines &mdash; Source Code</a></li>
189 <li><a href="foss-cklist.wiki">Successful Open-Source Projects &mdash; Checklist For</a></li>
@@ -198,42 +193,39 @@
193 <li><a href="tickets.wiki">System &mdash; The Fossil Ticket</a></li>
194 <li><a href="branching.wiki">Tagging &mdash; Branching, Forking, Merging, and</a></li>
195 <li><a href="tech_overview.wiki">Technical Overview Of The Design And Implementation Of Fossil &mdash; A</a></li>
196 <li><a href="../test/release-checklist.wiki">Testing Checklist &mdash; Pre-Release</a></li>
197 <li><a href="th1.md">TH1 Scripting Language &mdash; 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 &mdash; Customizing The</a></li>
208 <li><a href="tickets.wiki">Ticket System &mdash; The Fossil</a></li>
209 <li><a href="customgraph.md">Timeline Graph &mdash; Theming: Customizing the</a></li>
210 <li><a href="hints.wiki">Tips And Usage Hints &mdash; Fossil</a></li>
211 <li><a href="bugtheory.wiki">Tracking In Fossil &mdash; 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 &mdash; Fossil Tips And</a></li>
 
 
215 <li><a href="fiveminutes.wiki">User &mdash; 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 &mdash; Environment</a></li>
218 <li><a href="whyusefossil.wiki">Version Control &mdash; Benefits Of</a></li>
219 <li><a href="checkin_names.wiki">Version Names &mdash; Check-in And</a></li>
220 <li><a href="fossil-v-git.wiki">Versus Git &mdash; Fossil</a></li>
221 <li><a href="webui.wiki">Web Interface &mdash; The Fossil</a></li>
222 <li><a href="customskin.md">Web Pages &mdash; 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 &mdash; Lists of Commands and</a></li>
225 <li><a href="quotes.wiki">What People Are Saying About Fossil, Git, and DVCSes in General &mdash; 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 &mdash; How CGI</a></li>
230 <li><a href="whyusefossil.wiki">You Should Use Fossil &mdash; Why</a></li>
231 </ul></div>
232
+5 -5
--- www/pop.wiki
+++ www/pop.wiki
@@ -4,18 +4,18 @@
44
This page attempts to define the foundational principals upon
55
which Fossil is built.
66
</p>
77
88
<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
1010
trouble tickets, and control files (collectively "artifacts").
1111
All historical copies of all artifacts
1212
are saved. The project maintains an audit
1313
trail.</p></li>
1414
1515
<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
1717
of the others.</p></li>
1818
1919
<li><p>Each repository has both global and local state. The
2020
global state is common to all repositories (or at least
2121
has the potential to be shared in common when the
@@ -24,28 +24,28 @@
2424
The global state represents the content of the project.
2525
The local state identifies the authorized users and
2626
access policies for a particular repository.</p></li>
2727
2828
<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
3030
its SHA1 hash encoded in lowercase hexadecimal.
3131
In many contexts, the name can be
3232
abbreviated to a unique prefix. A five- or six-character
3333
prefix usually suffices to uniquely identify a file.</p></li>
3434
3535
<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
3737
changes the hash that forms the artifacts name, thus
3838
creating a new artifact. Both the old original version of the
3939
artifact and the new change are preserved under different names.</p></li>
4040
4141
<li><p>It is theoretically possible for two artifacts with different
4242
content to share the same hash. But finding two such
4343
artifacts is so incredibly difficult and unlikely that we
4444
consider it to be an impossibility.</p></li>
4545
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
4747
artifact itself, exactly as it would appear in a disk file. No prefix
4848
or meta-information about the artifact is added before computing
4949
the hash. So you can
5050
always find the SHA1 signature of a file by using the
5151
"sha1sum" command-line utility.</p></li>
5252
--- 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
--- www/private.wiki
+++ www/private.wiki
@@ -41,11 +41,11 @@
4141
<h2>Syncing Private Branches</h2>
4242
4343
A private branch normally stays on the one repository where it was
4444
originally created. But sometimes you want to share private branches
4545
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,
4747
your Linux desktop, and your iMac. You can transfer private branches
4848
between these machines by using the --private option on the "sync",
4949
"push", "pull", and "clone" commands. For example, if you are running
5050
"fossil server" on your Linux box and you want to clone that repository
5151
to your Mac, including all private branches, use:
@@ -67,11 +67,11 @@
6767
only enable "x" for local repositories when you need to share private
6868
branches.
6969
7070
Private branch sync only works if you use the --private command-line option.
7171
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
7373
push private branches beyond their intended audience.
7474
7575
<h2>Purging Private Branches</h2>
7676
7777
You can remove all private branches from a repository using this command:
@@ -85,10 +85,10 @@
8585
removed, they cannot be retrieved (unless you have synced them to another
8686
repository.) So be careful with the command.
8787
8888
<h2>Additional Notes</h2>
8989
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
9191
single repository at once. There is no mechanism in Fossil (currently)
9292
that allows you to push, pull, clone, sync, or scrub and individual
9393
private branch within a repository that contains multiple private
9494
branches.
9595
--- 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 @@
2222
<li> Integrated <a href="wikitheory.wiki">wiki</a>. </li>
2323
<li> Integrated <a href="bugtheory.wiki">bug tracking</a> </li>
2424
<li> Immutable artifacts </li>
2525
<li> Self-contained, stand-alone executable that can be run in
2626
a <a href="http://en.wikipedia.org/wiki/Chroot">chroot jail</a> </li>
27
- <li> Simple, well-defined,
27
+ <li> Simple, well-defined,
2828
<a href="fileformat.wiki">enduring file format</a> </li>
2929
<li> Integrated <a href="webui.wiki">web interface</a> </li>
3030
</ol>
3131
</blockquote>
3232
@@ -36,11 +36,11 @@
3636
<ol>
3737
<li> Fossil is distributed. You can view and/or edit tickets, wiki, and
3838
code while off network, then sync your changes later. With Trac, you
3939
can only view and edit tickets and wiki while you are connected to
4040
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
4242
to setup on a low-resource machine. Fossil does not require an
4343
administrator.</li>
4444
<li> Fossil integrates code versioning into the same repository with
4545
wiki and tickets. There is nothing extra to add or install.
4646
Fossil is an all-in-one turnkey solution. </li>
@@ -48,25 +48,25 @@
4848
</blockquote>
4949
5050
<b>Love the concept here. Anyone using this for real work yet?</b>
5151
5252
<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>.
5454
In fact, this page was probably delivered
5555
to your web-browser via a working fossil instance. The same virtual
5656
machine that hosts http://www.fossil-scm.org/
5757
(a <a href="http://www.linode.com/">Linode 720</a>)
5858
also hosts 24 other fossil repositories for various small projects.
59
-The documentation files for
59
+The documentation files for
6060
<a href="http://www.sqlite.org/">SQLite</a> are hosted in a
6161
fossil repository <a href="http://www.sqlite.org/docsrc/">here</a>,
6262
for example.
6363
Other projects are also adopting fossil. But fossil does not yet have
6464
the massive user base of git or mercurial.
6565
</blockquote>
6666
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
6868
Linksys Router's administration screen.</b>
6969
7070
<blockquote>
7171
<p>I take a pragmatic approach to software: form follows function.
7272
To me, it is more important to have a reliable, fast, efficient,
@@ -83,11 +83,11 @@
8383
keeps the bug-tracking database in a versioned file. That file can
8484
then be pushed and pulled along with the rest repository.</b>
8585
8686
<blockquote>
8787
<p>Fossil already <u>does</u> push and pull bugs along with the files
88
-in your repository.
88
+in your repository.
8989
But fossil does <u>not</u> track bugs as files in the source tree.
9090
That approach to bug tracking was rejected for three reasons:</p>
9191
9292
<ol>
9393
<li> Check-ins in fossil are immutable. So if
@@ -108,11 +108,11 @@
108108
109109
<p>These points are reiterated in the opening paragraphs of
110110
the <a href="bugtheory.wiki">Bug-Tracking In Fossil</a> document.</p>
111111
</blockquote>
112112
113
-<b>Fossil is already the name of a plan9 versioned
113
+<b>Fossil is already the name of a plan9 versioned
114114
append-only filesystem.</b>
115115
116116
<blockquote>
117117
I did not know that. Perhaps they selected the name for the same reason that
118118
I did: because a repository with immutable artifacts preserves
@@ -137,22 +137,22 @@
137137
Subversion or Bazaar.</b>
138138
139139
<blockquote>
140140
<p>I have no doubt that Trac has many features that fossil lacks. But that
141141
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
143143
fossil supports disconnected operation.</p>
144144
145145
<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
147147
(diff, patch, merge, cvs, svn, rcs, git, python, perl, tcl, apache,
148148
sqlite, and so forth)
149149
in order to run fossil. Fossil runs just fine in a chroot jail all
150150
by itself. And the self-contained fossil
151151
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
153153
much less than 2MB according to "size" when compiled using -Os on x64 Linux.)
154154
Fossil is the very opposite of bloat.</p>
155155
</blockquote>
156156
157157
158158
</nowiki>
159159
--- 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
--- www/quickstart.wiki
+++ www/quickstart.wiki
@@ -5,16 +5,16 @@
55
and painlessly.</p>
66
77
<h2>Installing</h2>
88
99
<p>Fossil is a single self-contained C program. You need to
10
- either download a
10
+ either download a
1111
<a href="http://www.fossil-scm.org/download.html">precompiled binary</a>
1212
or <a href="build.wiki">compile it yourself</a> from sources.
1313
Install fossil by putting the fossil binary
1414
someplace on your $PATH.</p>
15
-
15
+
1616
<a name="fslclone"></a>
1717
<h2>General Work Flow</h2>
1818
1919
<p>Fossil works with repository files (a database with the project's
2020
complete history) and with checked-out local trees (the working directory
@@ -34,11 +34,11 @@
3434
3535
<h2>Starting A New Project</h2>
3636
3737
<p>To start a new project with fossil, create a new empty repository
3838
this way: ([/help/init | more info]) </p>
39
-
39
+
4040
<blockquote>
4141
<b>fossil init </b><i> repository-filename</i>
4242
</blockquote>
4343
4444
<h2>Cloning An Existing Repository</h2>
@@ -46,36 +46,36 @@
4646
<p>Most fossil operations interact with a repository that is on the
4747
local disk drive, not on a remote system. Hence, before accessing
4848
a remote repository it is necessary to make a local copy of that
4949
repository. Making a local copy of a remote repository is called
5050
"cloning".</p>
51
-
51
+
5252
<p>Clone a remote repository as follows: ([/help/clone | more info])</p>
53
-
53
+
5454
<blockquote>
5555
<b>fossil clone</b> <i>URL repository-filename</i>
5656
</blockquote>
57
-
57
+
5858
<p>The <i>URL</i> specifies the fossil repository
5959
you want to clone. The <i>repository-filename</i> is the new local
6060
filename into which the cloned repository will be written. For
6161
example:
62
-
62
+
6363
<blockquote>
6464
<b>fossil clone http://www.fossil-scm.org/ myclone.fossil</b>
6565
</blockquote>
6666
67
- <p>If the remote repository requires a login, include a
67
+ <p>If the remote repository requires a login, include a
6868
userid in the URL like this:
6969
7070
<blockquote>
7171
<b>fossil clone http://</b><i>userid</i><b>@www.fossil-scm.org/ myclone.fossil</b>
7272
</blockquote>
73
-
73
+
7474
7575
<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.
7777
Examples: "%40" in place of "@" and "%2F" in place of "/".
7878
7979
<p>If you are behind a restrictive firewall, you might need
8080
to <a href="#proxy">specify an HTTP proxy</a>.</p>
8181
@@ -85,31 +85,31 @@
8585
information above and beyond the versioned files, including some
8686
sensitive information such as password hashes and email addresses. If you
8787
want to share Fossil repositories directly, consider running the
8888
[/help/scrub|fossil scrub] command to remove sensitive information
8989
before transmitting the file.
90
-
90
+
9191
<h2>Importing From Another Version Control System</h2>
9292
9393
<p>Rather than start a new project, or clone an existing Fossil project,
94
- you might prefer to
94
+ you might prefer to
9595
<a href="./inout.wiki">import an existing Git project</a>
9696
into Fossil using the [/help/import | fossil import] command.
9797
9898
<h2>Checking Out A Local Tree</h2>
9999
100100
<p>To work on a project in fossil, you need to check out a local
101101
copy of the source tree. Create the directory you want to be
102102
the root of your tree and cd into that directory. Then
103103
do this: ([/help/open | more info])</p>
104
-
104
+
105105
<blockquote>
106106
<b>fossil open </b><i> repository-filename</i>
107107
</blockquote>
108
-
108
+
109109
<p>This leaves you with the newest version of the tree
110
- checked out.
110
+ checked out.
111111
From anywhere underneath the root of your local tree, you
112112
can type commands like the following to find out the status of
113113
your local tree:</p>
114114
115115
<blockquote>
@@ -122,11 +122,11 @@
122122
<b>[/help/branch | fossil branch]</b><br>
123123
</blockquote>
124124
125125
<p>Note that Fossil allows you to make multiple check-outs in
126126
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
128128
the same time without having to generate extra clones.</p>
129129
130130
<p>To switch a checkout between different versions and branches,
131131
use:</p>
132132
@@ -140,17 +140,17 @@
140140
version, whereas [/help/checkout | checkout] does not
141141
automatically sync and does a "hard" switch, overwriting local
142142
changes if told to do so.</p>
143143
144144
<h2>Configuring Your Local Repository</h2>
145
-
145
+
146146
<p>When you create a new repository, either by cloning an existing
147147
project or create a new project of your own, you usually want to do some
148148
local configuration. This is easily accomplished using the web-server
149149
that is built into fossil. Start the fossil webserver like this:
150150
([/help/ui | more info])</p>
151
-
151
+
152152
<blockquote>
153153
<b>fossil ui </b><i> repository-filename</i>
154154
</blockquote>
155155
156156
<p>You can omit the <i>repository-filename</i> from the command above
@@ -163,15 +163,15 @@
163163
where to find your web browser using a command like this:</p>
164164
165165
<blockquote>
166166
<b>fossil setting web-browser </b><i> path-to-web-browser</i>
167167
</blockquote>
168
-
168
+
169169
<p>By default, fossil does not require a login for HTTP connections
170170
coming in from the IP loopback address 127.0.0.1. You can, and perhaps
171171
should, change this after you create a few users.</p>
172
-
172
+
173173
<p>When you are finished configuring, just press Control-C or use
174174
the <b>kill</b> command to shut down the mini-server.</p>
175175
176176
<h2>Making Changes</h2>
177177
@@ -194,18 +194,18 @@
194194
<p>You will be prompted for check-in comments using whatever editor
195195
is specified by your VISUAL or EDITOR environment variable.</p>
196196
197197
In the default configuration, the [/help/commit|commit]
198198
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
200200
[./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
202202
commit and push them.</p>
203203
204204
<h2>Sharing Changes</h2>
205205
206
- <p>When [./concepts.wiki#workflow|autosync] is turned off,
206
+ <p>When [./concepts.wiki#workflow|autosync] is turned off,
207207
the changes you [/help/commit | commit] are only
208208
on your local repository.
209209
To share those changes with other repositories, do:</p>
210210
211211
<blockquote>
@@ -241,11 +241,11 @@
241241
the <i>VERSION</i>, then fossil moves you to the
242242
latest version of the branch your are currently on.</p>
243243
244244
<p>The default behavior is for [./concepts.wiki#workflow|autosync] to
245245
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
247247
automatically after you [/help/commit|commit]. So in normal practice,
248248
the push, pull, and sync commands are rarely used. But it is important
249249
to know about them, all the same.</p>
250250
251251
<blockquote>
@@ -342,11 +342,11 @@
342342
<li>[./server.wiki#cgi|CGI]
343343
<li>[./server.wiki#scgi|SCGI]
344344
</ul>
345345
346346
<p>The [./selfhost.wiki | self-hosting fossil repositories] use
347
- CGI.
347
+ CGI.
348348
349349
<a name="proxy"></a>
350350
<h2>HTTP Proxies</h2>
351351
352352
<p>If you are behind a restrictive firewall that requires you to use
@@ -382,11 +382,11 @@
382382
<p>Or unset the environment variable. The fossil setting for the
383383
HTTP proxy takes precedence over the environment variable and the
384384
command-line option overrides both. If you have an persistent
385385
proxy setting that you want to override for a one-time sync, that
386386
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>
388388
389389
<blockquote>
390390
<b>fossil sync http://192.168.1.36:8080/ --proxy off</b>
391391
</blockquote>
392392
393393
--- 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 @@
55
by the creator of Fossil, so of course there is selection bias...
66
77
<h2>On The Usability Of Git:</h2>
88
99
<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
1111
unusable unless you have the manpage tattooed on you arm.
1212
1313
<blockquote>
1414
<i>by mml at [http://news.ycombinator.com/item?id=1433387]</i>
1515
</blockquote>
1616
1717
<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
1919
represented as n-dimensional membranes, mapping the spatial loci of
2020
successive commits onto the projected manifold of each cloned
2121
repository.</nowiki>
2222
2323
<blockquote>
@@ -25,11 +25,11 @@
2525
</blockquote>
2626
2727
<li>Git is not a Prius. Git is a Model T.
2828
Its plumbing and wiring sticks out all over the place.
2929
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.
3131
And it <b>will</b> break down.
3232
3333
<blockquote>
3434
<i>Nick Farina at [http://nfarina.com/post/9868516270/git-is-simpler]</i>
3535
</blockquote>
@@ -39,11 +39,11 @@
3939
<blockquote>
4040
<i>Linus Torvalds - 2005-04-07 22:13:13<br>
4141
Commit comment on the very first source-code check-in for git
4242
</blockquote>
4343
44
-<li>I've been experimenting a lot with git at work.
44
+<li>I've been experimenting a lot with git at work.
4545
Damn, it's complicated.
4646
It has things to trip you up with that sane people just wouldn't ever both with
4747
including the ability to allow you to commit stuff in such a way that you can't find
4848
it again afterwards (!!!)
4949
Demented workflow complexity on acid?
@@ -104,19 +104,19 @@
104104
105105
<blockquote>
106106
<i>Joe Prostko at [http://www.mail-archive.com/[email protected]/msg16716.html]
107107
</blockquote>
108108
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,
110110
such simplicity and flexibility!!!
111111
112112
<blockquote>
113113
<i>zengr at [http://stackoverflow.com/questions/138621/best-version-control-for-lone-developer]</i>
114114
</blockquote>
115115
116116
<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
118118
the entire program in a single file!
119119
120120
<blockquote>
121121
<i>thunderbong commenting on hacker news: [https://news.ycombinator.com/item?id=9131619]</i>
122122
</blockquote>
@@ -127,30 +127,30 @@
127127
128128
<h2>On Git Versus Fossil</h2>
129129
130130
<ol>
131131
<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....
133133
Also <nowiki>[for]</nowiki> not having a misanthropic command line interface.
134134
135135
<blockquote>
136136
<i>Joshua Paine at [http://www.mail-archive.com/[email protected]/msg02736.html]</i>
137137
</blockquote>
138138
139139
<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
144144
been a smoother ride than Git was.
145145
146146
<blockquote>
147147
<i>viablepanic at [http://www.reddit.com/r/programming/comments/bxcto/why_not_fossil_scm/]</i>
148148
</blockquote>
149149
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
152152
reflect the unchanging nature of things in that history.
153153
154154
<p>In git (or rather, the git community), the development history is part of
155155
the published aspect of the project, so it provides tools for rearranging
156156
that history so you can present what you "should" have done rather
157157
--- 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 @@
11
<title>Reviews</title>
22
<b>External links:</b>
3
-
3
+
44
* [http://nixtu.blogspot.com/2010/03/fossil-dvcs-on-go-first-impressions.html |
55
Fossil DVCS on the Go - First Impressions]
66
* [http://blog.mired.org/2011/02/fossil-sweet-spot-in-vcs-space.html |
77
Fossil - a sweet spot in the VCS space] by Mike Meyer.
88
* [http://blog.s11n.net/?p=72|Four reasons to take a closer look at the Fossil SCM] by Stephan Beal
@@ -22,27 +22,27 @@
2222
2323
2424
<b>Joshua Paine on 2010-10-22:</b>
2525
2626
<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
3737
features. Also not having a misanthropic command line interface.
3838
</blockquote>
3939
4040
<b>Stephan Beal writes on 2009-01-11:</b>
4141
4242
<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
4444
<a href="http://www.sqlite.org/">sqlite.org</a>. It
4545
was a good thing I bookmarked it, because I was never able to find the
4646
link again (it might have been in a bug report or something). The
4747
reasons I first took a close look at it were (A) it stemmed from the
4848
sqlite project, which I've held in high regards for years (e.g. I
4949
--- 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
--- www/selfcheck.wiki
+++ www/selfcheck.wiki
@@ -14,11 +14,11 @@
1414
lost. The integrity checks are doing their job well.</p>
1515
1616
<h2>Atomic Check-ins With Rollback</h2>
1717
1818
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.
2020
([./tech_overview.wiki | Addition information] about the repository
2121
file format.)
2222
SQLite is very mature and stable and has been in wide-spread use for many
2323
years, so we are confident it will not cause repository
2424
corruption. SQLite
@@ -61,11 +61,11 @@
6161
message is printed and the transaction rolls back.
6262
6363
So, in other words, fossil always checks to make sure it can
6464
re-extract a file before it commits a change to that file.
6565
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
6767
files.
6868
6969
<h2>Checksum Over All Files In A Check-in</h2>
7070
7171
Manifest artifacts that define a check-in have two fields (the
@@ -102,7 +102,7 @@
102102
<a href="http://en.wikipedia.org/wiki/The_Tortoise_and_the_Hare">tortoise</a>:
103103
reliability is more important than raw speed. The developers of
104104
fossil see no merit in getting the wrong answer quickly.
105105
106106
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.
108108
Most operations complete in under a second.
109109
--- 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
--- www/selfhost.wiki
+++ www/selfhost.wiki
@@ -7,23 +7,23 @@
77
2. [http://www2.fossil-scm.org/]
88
3. [http://www3.fossil-scm.org/site.cgi]
99
1010
1111
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
1313
<a href="http://en.wikipedia.org/wiki/Cron">cron job</a> that invokes
1414
"fossil sync" at regular intervals.
1515
1616
Note that the two secondary repositories are more than just read-only mirrors.
1717
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
1919
on any of the three servers and those changes automatically propagate to the
2020
other two servers.
2121
2222
Server (1) runs as a CGI script on a
2323
<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
2525
hosts <a href="http://www.sqlite.org/">SQLite</a> and over a
2626
dozen other smaller projects. This demonstrates that Fossil can run on
2727
a low-power host processor.
2828
Multiple fossil-based projects can easily be hosted on the same machine,
2929
even if that machine is itself one of several dozen virtual machines on
@@ -34,17 +34,17 @@
3434
#!/usr/bin/fossil
3535
repository: /fossil/fossil.fossil
3636
</pre></blockquote>
3737
3838
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.
4040
This server demonstrates the ability of
4141
Fossil to run on an economical shared-host web account with no
4242
privileges beyond port 80 HTTP access and CGI. It is not necessary
4343
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
4646
that can run in
4747
such a restricted environment. The CGI script that runs on the
4848
Hurricane Electric server is the same as the CGI script shown above,
4949
except that the pathnames are modified to suit the environment:
5050
5151
--- 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 @@
22
<h2>Introduction</h2><blockquote>
33
<p>A server is not necessary to use Fossil, but a server does help in collaborating with
44
peers. A Fossil server also works well as a complete website for a project.
55
For example, the complete [https://www.fossil-scm.org/] website, including the
66
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
88
self-hosting repository for Fossil.</p>
99
<p>This article is a guide for setting up your own Fossil server.
1010
<p>See "[./aboutcgi.wiki|How CGI Works In Fossil]" for background
1111
information on the underlying CGI technology.
1212
See "[./sync.wiki|The Fossil Sync Protocol]" for information on the
@@ -18,11 +18,11 @@
1818
<li>A stand-alone server
1919
<li>Using inetd or xinetd or stunnel
2020
<li>CGI
2121
<li>SCGI (a.k.a. SimpleCGI)
2222
</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
2424
containing many repositories with names ending in ".fossil".
2525
</blockquote>
2626
<a name="standalone"></a>
2727
<h2>Standalone server</h2><blockquote>
2828
The easiest way to set up a Fossil server is to use either the
@@ -34,11 +34,11 @@
3434
<p>
3535
The <i>REPOSITORY</i> argument is either the name of the repository file, or
3636
a directory containing many repositories.
3737
Both of these commands start a Fossil server, usually on TCP port 8080, though
3838
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
4040
<i>REPOSITORY</i> is a directory, URLs of the form
4141
<b>http://localhost:8080/</b><i>repo</i><b>/</b> where <i>repo</i> is the base
4242
name of the repository file without the ".fossil" suffix.
4343
The difference between "ui" and "server" is that "ui" will
4444
also start a web browser and point it
@@ -75,23 +75,23 @@
7575
need to modify the pathnames for your particular setup.
7676
The final argument is either the name of the fossil repository to be served,
7777
or a directory containing multiple repositories.
7878
</p>
7979
<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
8282
numeric, add the desired name and port to /etc/services. For example, if
8383
you want your Fossil server running on TCP port 12345 instead of 80, you
8484
will need to add:
8585
<blockquote>
8686
<pre>
8787
fossil 12345/tcp #fossil server
8888
</pre>
8989
</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
9393
case you use FreeBSD.
9494
</p>
9595
<p>
9696
If your system is running xinetd, then the configuration is likely to be
9797
in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d".
@@ -119,11 +119,11 @@
119119
jail for the user who owns the fossil repository before reading any information
120120
off of the wire.
121121
</p>
122122
<p>
123123
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.
125125
</p>
126126
<p>
127127
[https://www.stunnel.org/ | Stunnel version 5] is an inetd-like process that
128128
accepts and decodes SSL-encrypted connections. Fossil can be run directly from
129129
stunnel in a manner similar to inetd and xinetd. This can be used to provide
@@ -137,15 +137,15 @@
137137
TIMEOUTclose = 0
138138
exec = /usr/bin/fossil
139139
execargs = /usr/bin/fossil http /home/fossil/ubercool.fossil --https
140140
</nowiki></pre></blockquote>
141141
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
143143
the --https option to let Fossil know to use "https" instead of "http" as the scheme
144144
on generated hyperlinks.
145145
<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
147147
than the "standalone" server, but it has the
148148
advantage of only using system resources when an actual connection is
149149
attempted. If no-one ever connects to that port, a Fossil server will
150150
not (automatically) run. It has the disadvantage of requiring "root" access
151151
and therefore may not normally be available to lower-priced "shared" servers
@@ -155,11 +155,11 @@
155155
<a name="cgi"></a>
156156
<h2>Fossil as CGI</h2><blockquote>
157157
<p>
158158
A Fossil server can also be run from an ordinary web server as a CGI program.
159159
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
161161
implemented.
162162
</p>
163163
<p>
164164
To run Fossil as CGI, create a CGI script (here called "repo") in the CGI directory
165165
of your web server and having content like this:
@@ -184,12 +184,12 @@
184184
script itself must be executable for the user under which it will run (which often differs
185185
from the one running the web server - consult your site's documentation or administrator).</li>
186186
<li>The repository file AND the directory containing it must be writable by the same account
187187
which executes the Fossil binary (again, this might differ from the WWW user). The directory
188188
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
191191
a chroot, ensure that this directory exists and is readable/writeable
192192
by the user who executes the Fossil binary.</li>
193193
</ul>
194194
</p>
195195
@@ -219,11 +219,11 @@
219219
220220
<a name="scgi"></a>
221221
<h2>Fossil as SCGI</h2><blockquote>
222222
223223
<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
225225
starting a stand-alone web server, can also be used for SCGI. Simply add
226226
the --scgi command-line option and the stand-alone server will interpret
227227
and respond to the SimpleCGI or SCGI protocol rather than raw HTTP. This can
228228
be used in combination with a webserver (such as [http://nginx.org|Nginx])
229229
that does not support CGI. A typical Nginx configuration to support SCGI
@@ -284,27 +284,27 @@
284284
</blockquote>
285285
286286
<a name="loadmgmt"></a>
287287
<h2>Managing Server Load</h2><blockquote>
288288
<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
290290
load on the server.
291291
The Fossil [./selfhost.wiki | self-hosting server] is a 1/24th slice VM at
292292
[http://www.linode.com | Linode.com] hosting 65 other repositories in
293293
addition to Fossil (and including some very high-traffic sites such
294294
as [http://www.sqlite.org] and [http://system.data.sqlite.org]) and
295295
it has a typical load of 0.05 to 0.1. A single HTTP request to Fossil
296296
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
298298
and the CPU can still be mostly idle.
299299
<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
301301
amounts of CPU time, especially on repositories with a large number
302302
of files or with long revision histories. High CPU usage pages include
303303
[/help?cmd=/zip | /zip], [/help?cmd=/tarball | /tarball],
304304
[/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.
306306
If these kinds of requests arrive too quickly, the load average on the
307307
server can grow dramatically, making the server unresponsive.
308308
<p>
309309
Fossil provides two capabilities to help avoid server overload problems
310310
due to excessive requests to expensive pages:
@@ -312,11 +312,11 @@
312312
<li><p>An optional cache is available that remembers the 10 most recently
313313
requested /zip or /tarball pages and returns the precomputed answer
314314
if the same page is requested again.
315315
<li><p>Page requests can be configured to fail with a
316316
[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
318318
average is too high.
319319
</ol>
320320
Both of these load-control mechanisms are turned off by default, but they
321321
are recommended for high-traffic sites.
322322
<p>
323323
--- 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
--- www/settings.wiki
+++ www/settings.wiki
@@ -4,11 +4,11 @@
44
55
Settings control the behaviour of fossil. They are set with the
66
<tt>fossil settings</tt> command, or through the web interface in
77
the Settings page in the Admin section.
88
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
1010
<tt>fossil help settings</tt> from the command line.
1111
1212
1313
<h3>Repository settings</h3>
1414
@@ -16,17 +16,17 @@
1616
a subset of settings are copied to your local repository.
1717
1818
If you make a change to a setting on your local repository, it is not
1919
synced back to the server when you <tt>push</tt> or <tt>sync</tt>. If
2020
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.
2222
2323
You can also set a setting globally on your local machine. The value
2424
will be used for all repositories cloned to your machine, unless
2525
overridden explicitly in a particular repository. Global settings can be
2626
set by using the <tt>-global</tt> option on the <tt>fossil settings</tt>
27
-command.
27
+command.
2828
2929
<h3>"Versionable" settings</h3>
3030
3131
Most of the settings control the behaviour of fossil on your local
3232
machine, largely acting to reflect your preference on how you want to
3333
--- 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 @@
22
<h1 align="center">Deleting Content From Fossil</h1>
33
44
Fossil is designed to keep all historical content forever. Users
55
of Fossil are discouraged from "deleting" content simply because it
66
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.
88
Such is the design intent of Fossil.
99
1010
Nevertheless, there may occasionally arise legitimate reasons for
1111
deleting content. Such reasons might include:
1212
@@ -21,35 +21,35 @@
2121
disrupting the operation of Fossil.
2222
2323
<h2>Shunning</h2>
2424
2525
Fossil provides a mechanism called "shunning" for removing content from
26
-a repository.
26
+a repository.
2727
2828
Every Fossil repository maintains a list of the SHA1 hash names of
2929
"shunned" artifacts.
30
-Fossil will refuse to push or pull any shunned artifact.
30
+Fossil will refuse to push or pull any shunned artifact.
3131
Furthermore, all shunned artifacts (but not the shunning list
3232
itself) are removed from the
3333
repository whenever the repository is reconstructed using the
3434
"rebuild" command.
3535
3636
<h3>Shunning lists are local state</h3>
3737
3838
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
4040
using the normal "sync" mechanism. An artifact can be
4141
shunned from one repository but be allowed to exist in another. The fact that
4242
the shunning list does not propagate is a security feature. If the
4343
shunning list propagated then a malicious user (or
4444
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
4646
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
4848
information from your personal repositories without your permission.
4949
50
-The shunning list does not propagate to a remote repository
50
+The shunning list does not propagate to a remote repository
5151
by the normal "sync" mechanism,
5252
but it is still possible to copy shuns from one repository to another
5353
using the "configuration" command:
5454
5555
<b>fossil configuration pull shun</b> <i>remote-url</i><br>
@@ -56,12 +56,12 @@
5656
<b>fossil configuration push shun</b> <i>remote-url</i>
5757
5858
The two command above will pull or push shunning lists from or to
5959
the <i>remote-url</i> indicated and merge the lists on the receiving
6060
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
6363
disabled by the "<tt>auto-shun</tt>" setting.
6464
6565
Note that the shunning list remains in the repository even after the
6666
shunned artifact has been removed. This is to prevent the artifact
6767
from being reintroduced into the repository the next time it syncs with
@@ -68,11 +68,11 @@
6868
another repository that has not shunned the artifact.
6969
7070
<h3>Managing the shunning list</h3>
7171
7272
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.
7474
That URL is accessible under the "Admin" button on the default menu
7575
bar. Items can be added to or removed from the shunning list. "Sync"
7676
operations are inhibited as soon as the artifact is added to the
7777
shunning list, but the content of the artifact is not actually removed
7878
from the repository until the next time the repository is rebuilt.
7979
--- 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 @@
11
<title>Fossil Performance</title>
22
<h1 align="center">Performance Statistics</h1>
33
4
-The questions will inevitably arise: How does Fossil perform?
4
+The questions will inevitably arise: How does Fossil perform?
55
Does it use a lot of disk space or bandwidth? Is it scalable?
66
77
In an attempt to answers these questions, this report looks at several
88
projects that use fossil for configuration management and examines how
99
well they are working. The following table is a summary of the results.
@@ -96,21 +96,21 @@
9696
every ticket, and every check-in is a separate "artifact". One way to
9797
think of a Fossil project is as a bag of artifacts. Of course, there is
9898
a lot more than this going on in Fossil. Many of the artifacts have meaning
9999
and are related to other artifacts. But at a low level (for example when
100100
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
102102
characteristics of Fossil is that the entire project history can be
103103
reconstructed simply by scanning the artifacts in an arbitrary order.
104104
105105
The number of check-ins is the number of times that the "commit" command
106106
has been run. A single check-in might change a 3 or 4 files, or it might
107107
change dozens or hundreds of files. Regardless of the number of files
108108
changed, it still only counts as one check-in.
109109
110110
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
112112
separately on the disk. Fossil makes use of delta compression between related
113113
versions of the same file, and then uses zlib compression on the resulting
114114
deltas. The total resulting repository size is shown after the uncompressed
115115
size.
116116
117117
--- 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 @@
11
<title>The Fossil Sync Protocol</title>
22
3
-<p>This document describes the wire protocol used to synchronize
3
+<p>This document describes the wire protocol used to synchronize
44
content between two Fossil repositories.</p>
55
66
<h2>1.0 Overview</h2>
77
88
<p>The global state of a fossil repository consists of an unordered
@@ -22,11 +22,11 @@
2222
shared to a few hundred.</p>
2323
2424
<p>Each repository also has local state. The local state determines
2525
the web-page formatting preferences, authorized users, ticket formats,
2626
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,
2828
some local state is transferred during a [/help?cmd=clone|clone]
2929
in order to initialize the local state of the new repository. And
3030
the [/help?cmd=configuration|config push] and
3131
[/help?cmd=configuration|config pull]
3232
commands can be an administrator to sync local state.</p>
@@ -40,15 +40,15 @@
4040
request.</p>
4141
4242
<p>The server might be running as an independent server
4343
using the <b>server</b> command, or it might be launched from
4444
inetd or xinetd using the <b>http</b> command. Or the server might
45
-be launched from CGI.
45
+be launched from CGI.
4646
(See "[./server.wiki|How To Configure A Fossil Server]" for details.)
4747
The specifics of how the server listens
4848
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
5050
the client is the issuer of the requests.</p>
5151
5252
<p>A single push, pull, or sync might involve multiple HTTP requests.
5353
The client maintains state between all requests. But on the server
5454
side, each request is independent. The server does not preserve
@@ -55,11 +55,11 @@
5555
any information about the client from one request to the next.</p>
5656
5757
<h4>2.0.1 Encrypted Transport</h4>
5858
5959
<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
6161
clear-text HTTP requests or encrypted HTTPS requests. But when
6262
HTTPS requests are sent, they first must be decrypted by a webserver
6363
or proxy before being passed to the Fossil server. This limitation
6464
may be relaxed in a future release.</p>
6565
@@ -408,11 +408,11 @@
408408
<b>uvigot</b> <i>name mtime hash size</i>
409409
</blockquote>
410410
411411
<p>The <i>name</i> argument is the name of an unversioned file.
412412
The <i>mtime</i> is the last modification time of the unversioned file
413
-in seconds since 1970.
413
+in seconds since 1970.
414414
The <i>hash</i> is the SHA1 hash of the unversioned file content, or
415415
"<b>-</b>" if the file has been deleted.
416416
The <i>size</i> is the uncompressed size of the file in bytes.
417417
418418
<p>When the server sees a "pragma uv-hash" card for which the hash
419419
--- 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 @@
174174
* tclInvoke
175175
* tclIsSafe
176176
* tclMakeSafe
177177
* tclReady
178178
* trace
179
+ * unversioned content
180
+ * unversioned list
179181
* utime
180182
* verifyCsrf
181183
* wiki
182184
183185
Each of the commands above is documented by a block comment above their
@@ -610,10 +612,27 @@
610612
-------------------------------------
611613
612614
* trace STRING
613615
614616
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.
615634
616635
<a name="utime"></a>TH1 utime Command
617636
-------------------------------------
618637
619638
* utime
620639
--- 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
--- www/theory1.wiki
+++ www/theory1.wiki
@@ -16,18 +16,18 @@
1616
1717
<h2>Fossil Is A NoSQL Database</h2>
1818
1919
We begin with the first question: Fossil is not based on a distributed
2020
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.
2222
The current implementation of Fossil uses
2323
SQLite as a local store for the content of the distributed database and as
2424
a cache for meta-information about the distributed database that is precomputed
2525
for quick and easy presentation. But the use of SQLite in this role is an
2626
implementation detail and is not fundamental to the design. Some future
2727
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.
2929
(Actually, that is very unlikely
3030
to happen since SQLite works amazingly well in its current role, but the point
3131
is that omitting SQLite from Fossil is a theoretical possibility.)
3232
3333
The underlying database that Fossil implements has nothing to do with
@@ -64,11 +64,11 @@
6464
a NoSQL database) and there is the local relational database. The
6565
bag-of-artifacts database has a fixed format and is what defines a Fossil
6666
repository. Fossil will never modify the file format of the bag-of-artifacts
6767
database in an incompatible way because to do so would be to make something
6868
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.
7070
The schema of the local relational database changes from time to time as
7171
the Fossil implementation is enhanced, and the content is recomputed from
7272
the unchanging bag of artifacts. The local relational database is an
7373
implementation detail which currently happens to use SQLite.
7474
@@ -89,11 +89,11 @@
8989
the first question.
9090
9191
<h2>SQL Is A High-Level Scripting Language</h2>
9292
9393
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)
9595
as its scripting language.
9696
9797
This misunderstanding likely arises because people fail
9898
to appreciate that SQL is a programming language. People are taught that SQL
9999
is a "query language" as if that were somehow different from a
@@ -125,11 +125,11 @@
125125
out using SQL statements. It is true that these SQL statements are glued
126126
together with C code, but it turns out that C works surprisingly well in
127127
that role. Several early prototypes of Fossil were written in a scripting
128128
language (TCL). We normally find that TCL programs are shorter than the
129129
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
131131
understand.
132132
And so in the final design, we switched from TCL to C in order to make
133133
the code easier to implement and debug.
134134
135135
Without the advantages of having SQLite built in, the design might well
136136
--- 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 @@
2525
There are no extra programs to install or setup.
2626
Everything you need is already pre-configured and built into the
2727
self-contained, stand-alone Fossil executable.
2828
2929
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],
3231
including the document you are now reading,
3332
is rendered using the Fossil web interface, with no enhancements,
3433
and little customization.
3534
3635
<blockquote>
3736
--- 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
--- www/wikitheory.wiki
+++ www/wikitheory.wiki
@@ -34,26 +34,26 @@
3434
the wiki page will fork. The web interface will display whichever edit
3535
was checked in last. The other edit can be found in the history. The
3636
file format will support merging the branches back together, but there
3737
is no mechanism in the user interface (yet) to perform the merge.
3838
39
-Every change to a wiki page is a separate
39
+Every change to a wiki page is a separate
4040
[./fileformat.wiki | control artifact]
4141
of type [./fileformat.wiki#wikichng | "Wiki Page"].
4242
4343
<h2>Embedded Documentation</h2>
4444
4545
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.
4747
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
4949
online. (Details are described [./embeddeddoc.wiki | separately].)
5050
5151
Some projects prefer to store their documentation in wiki. There is nothing
5252
wrong with that. But other projects prefer to keep documentation as part
5353
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.
5555
Embedded documentation serves this latter purpose. Both forms of documentation
5656
use the exact same markup. Some projects may choose to
5757
use both forms of documentation at the same time. Because the same
5858
format is used, it is trivial to move a file from wiki to embedded documentation
5959
or back again as the project evolves.
6060
--- 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

Keyboard Shortcuts

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