Fossil SCM

Merge updates from trunk.

mistachkin 2015-03-23 01:29 mvAndRmFiles merge
Commit 78829b7089ac7a065514382c1c75d3e054216fbd
+6 -6
--- Dockerfile
+++ Dockerfile
@@ -2,26 +2,26 @@
22
# Dockerfile for Fossil
33
###
44
FROM fedora:21
55
66
### Now install some additional parts we will need for the build
7
-RUN yum update -y && yum install -y gcc make zlib-devel openssl-devel tcl tar && yum clean all && groupadd -r fossil -g 433 && useradd -u 431 -r -g fossil -d /opt/fossil -s /sbin/nologin -c "Fossil user" fossil
7
+RUN yum update -y && yum install -y gcc make zlib-devel openssl-devel tar && yum 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 "release", change the next line accordingly.
1010
ENV FOSSIL_INSTALL_VERSION trunk
1111
12
+RUN curl "http://core.tcl.tk/tcl/tarball/tcl-src.tar.gz?name=tcl-src&uuid=release" | tar zx
13
+RUN cd tcl-src/unix && ./configure --prefix=/usr --disable-shared --disable-threads --disable-load && make && make install
1214
RUN curl "http://www.fossil-scm.org/index.html/tarball/fossil-src.tar.gz?name=fossil-src&uuid=${FOSSIL_INSTALL_VERSION}" | tar zx
13
-RUN cd fossil-src && ./configure --disable-lineedit --disable-fusefs --json --with-th1-docs --with-th1-hooks --with-tcl --with-tcl-stubs --with-tcl-private-stubs && make;
14
-RUN cp fossil-src/fossil /usr/bin && rm -rf fossil-src && chmod a+rx /usr/bin/fossil && mkdir -p /opt/fossil && chown fossil:fossil /opt/fossil
15
+RUN cd fossil-src && ./configure --disable-lineedit --disable-fusefs --json --with-th1-docs --with-th1-hooks --with-tcl
16
+RUN cd fossil-src && make && strip fossil && cp fossil /usr/bin && cd .. && rm -rf fossil-src && chmod a+rx /usr/bin/fossil && mkdir -p /opt/fossil && chown fossil:fossil /opt/fossil
1517
1618
### Build is done, remove modules no longer needed
1719
RUN yum remove -y gcc make zlib-devel openssl-devel tar && yum clean all
1820
1921
USER fossil
2022
2123
ENV HOME /opt/fossil
2224
23
-RUN fossil new --docker -A admin /opt/fossil/repository.fossil && fossil user password -R /opt/fossil/repository.fossil admin admin && fossil cache init -R /opt/fossil/repository.fossil
24
-
2525
EXPOSE 8080
2626
27
-CMD ["/usr/bin/fossil", "server", "/opt/fossil/repository.fossil"]
27
+CMD ["/usr/bin/fossil", "server", "--create", "--user", "admin", "/opt/fossil/repository.fossil"]
2828
--- Dockerfile
+++ Dockerfile
@@ -2,26 +2,26 @@
2 # Dockerfile for Fossil
3 ###
4 FROM fedora:21
5
6 ### Now install some additional parts we will need for the build
7 RUN yum update -y && yum install -y gcc make zlib-devel openssl-devel tcl tar && yum 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 "release", change the next line accordingly.
10 ENV FOSSIL_INSTALL_VERSION trunk
11
 
 
12 RUN curl "http://www.fossil-scm.org/index.html/tarball/fossil-src.tar.gz?name=fossil-src&uuid=${FOSSIL_INSTALL_VERSION}" | tar zx
13 RUN cd fossil-src && ./configure --disable-lineedit --disable-fusefs --json --with-th1-docs --with-th1-hooks --with-tcl --with-tcl-stubs --with-tcl-private-stubs && make;
14 RUN cp fossil-src/fossil /usr/bin && rm -rf fossil-src && chmod a+rx /usr/bin/fossil && mkdir -p /opt/fossil && chown fossil:fossil /opt/fossil
15
16 ### Build is done, remove modules no longer needed
17 RUN yum remove -y gcc make zlib-devel openssl-devel tar && yum clean all
18
19 USER fossil
20
21 ENV HOME /opt/fossil
22
23 RUN fossil new --docker -A admin /opt/fossil/repository.fossil && fossil user password -R /opt/fossil/repository.fossil admin admin && fossil cache init -R /opt/fossil/repository.fossil
24
25 EXPOSE 8080
26
27 CMD ["/usr/bin/fossil", "server", "/opt/fossil/repository.fossil"]
28
--- Dockerfile
+++ Dockerfile
@@ -2,26 +2,26 @@
2 # Dockerfile for Fossil
3 ###
4 FROM fedora:21
5
6 ### Now install some additional parts we will need for the build
7 RUN yum update -y && yum install -y gcc make zlib-devel openssl-devel tar && yum 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 "release", change the next line accordingly.
10 ENV FOSSIL_INSTALL_VERSION trunk
11
12 RUN curl "http://core.tcl.tk/tcl/tarball/tcl-src.tar.gz?name=tcl-src&uuid=release" | tar zx
13 RUN cd tcl-src/unix && ./configure --prefix=/usr --disable-shared --disable-threads --disable-load && make && make install
14 RUN curl "http://www.fossil-scm.org/index.html/tarball/fossil-src.tar.gz?name=fossil-src&uuid=${FOSSIL_INSTALL_VERSION}" | tar zx
15 RUN cd fossil-src && ./configure --disable-lineedit --disable-fusefs --json --with-th1-docs --with-th1-hooks --with-tcl
16 RUN cd fossil-src && make && strip fossil && cp fossil /usr/bin && cd .. && rm -rf fossil-src && chmod a+rx /usr/bin/fossil && mkdir -p /opt/fossil && chown fossil:fossil /opt/fossil
17
18 ### Build is done, remove modules no longer needed
19 RUN yum remove -y gcc make zlib-devel openssl-devel tar && yum clean all
20
21 USER fossil
22
23 ENV HOME /opt/fossil
24
 
 
25 EXPOSE 8080
26
27 CMD ["/usr/bin/fossil", "server", "--create", "--user", "admin", "/opt/fossil/repository.fossil"]
28
--- skins/blitz/css.txt
+++ skins/blitz/css.txt
@@ -464,11 +464,11 @@
464464
font-weight: 400;
465465
color: #ccc;
466466
}
467467
468468
pre, code {
469
- font-size: 1.3rem;
469
+ font-size: 1.2rem;
470470
}
471471
472472
body {
473473
font-size: 1.4em; /* currently ems cause chrome bug misinterpreting rems on body element */
474474
line-height: 1.5;
@@ -599,10 +599,11 @@
599599
-moz-appearance: none;
600600
appearance: none;
601601
}
602602
603603
textarea {
604
+ height: inherit;
604605
min-height: 65px;
605606
padding-top: 6px;
606607
padding-bottom: 6px;
607608
}
608609
@@ -857,11 +858,10 @@
857858
858859
.mainmenu li {
859860
outline: 0;
860861
display: block;
861862
float: left;
862
- padding: 10px 15px;
863863
margin: 0;
864864
}
865865
866866
.mainmenu li.active {
867867
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEQAACxEBf2RfkQAAAAd0SU1FB90FDxEXAZ2XRzAAAABJSURBVCjPY2CgBzhz5sx/QmoYiTXAxMSEkWRDsLkAl0GMpHoBm0EoAlu3bmUQFxcnGAboBjEhc4gxAJtLGUmJBVwuYiTXAGSDAIx5IBObnuVxAAAAAElFTkSuQmCC);
@@ -868,12 +868,13 @@
868868
background-repeat: no-repeat;
869869
background-position: center bottom;
870870
}
871871
872872
.mainmenu li a {
873
- color: #3b5c6b;
874
- display: block;
873
+ color: #3b5c6b;
874
+ display: block;
875
+ padding: 10px 15px;
875876
}
876877
877878
.mainmenu li.active a {
878879
font-weight: bold;
879880
}
@@ -890,11 +891,11 @@
890891
padding: 10px 0px;
891892
border-bottom: 1px solid #ddd;
892893
}
893894
894895
.submenu input, .submenu select {
895
- margin: 0;
896
+ margin: 0 0 0 5px;
896897
}
897898
898899
.submenu a {
899900
color: #3b5c6b;
900901
padding: 5px 15px;
@@ -1072,17 +1073,15 @@
10721073
font-weight: bold;
10731074
white-space: nowrap;
10741075
}
10751076
10761077
a.timelineHistLink {
1077
- text-transform: uppercase;
1078
+ text-transform: lowercase;
10781079
}
10791080
10801081
span.timelineComment {
1081
- /* make the span behave like a div */
1082
- /* padding: 10px 20px;*/
1083
- /* display: block;*/
1082
+ padding: 0px 5px;
10841083
}
10851084
10861085
10871086
/* Login/Loguot
10881087
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */
@@ -1097,17 +1096,22 @@
10971096
table.login_out td {
10981097
border: 0;
10991098
}
11001099
11011100
1102
-/* Miscellaneous
1101
+/* Diff displays
11031102
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */
1104
-.udiff, .sbsdiff {
1105
- font-size: .85em !important;
1106
- overflow: auto;
1107
- border: 1px solid #ccc;
1108
- border-radius: 5px;
1103
+pre.udiff, table.sbsdiffcols {
1104
+ width: 100%;
1105
+ overflow: auto;
1106
+ border: 1px solid #ccc;
1107
+ padding: 5px;
1108
+ font-size: 1rem;
1109
+}
1110
+
1111
+pre.udiff:focus, table.sbsdiffcols:focus {
1112
+ outline: none;
11091113
}
11101114
11111115
11121116
/* Ticket Reports
11131117
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */
11141118
--- skins/blitz/css.txt
+++ skins/blitz/css.txt
@@ -464,11 +464,11 @@
464 font-weight: 400;
465 color: #ccc;
466 }
467
468 pre, code {
469 font-size: 1.3rem;
470 }
471
472 body {
473 font-size: 1.4em; /* currently ems cause chrome bug misinterpreting rems on body element */
474 line-height: 1.5;
@@ -599,10 +599,11 @@
599 -moz-appearance: none;
600 appearance: none;
601 }
602
603 textarea {
 
604 min-height: 65px;
605 padding-top: 6px;
606 padding-bottom: 6px;
607 }
608
@@ -857,11 +858,10 @@
857
858 .mainmenu li {
859 outline: 0;
860 display: block;
861 float: left;
862 padding: 10px 15px;
863 margin: 0;
864 }
865
866 .mainmenu li.active {
867 background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEQAACxEBf2RfkQAAAAd0SU1FB90FDxEXAZ2XRzAAAABJSURBVCjPY2CgBzhz5sx/QmoYiTXAxMSEkWRDsLkAl0GMpHoBm0EoAlu3bmUQFxcnGAboBjEhc4gxAJtLGUmJBVwuYiTXAGSDAIx5IBObnuVxAAAAAElFTkSuQmCC);
@@ -868,12 +868,13 @@
868 background-repeat: no-repeat;
869 background-position: center bottom;
870 }
871
872 .mainmenu li a {
873 color: #3b5c6b;
874 display: block;
 
875 }
876
877 .mainmenu li.active a {
878 font-weight: bold;
879 }
@@ -890,11 +891,11 @@
890 padding: 10px 0px;
891 border-bottom: 1px solid #ddd;
892 }
893
894 .submenu input, .submenu select {
895 margin: 0;
896 }
897
898 .submenu a {
899 color: #3b5c6b;
900 padding: 5px 15px;
@@ -1072,17 +1073,15 @@
1072 font-weight: bold;
1073 white-space: nowrap;
1074 }
1075
1076 a.timelineHistLink {
1077 text-transform: uppercase;
1078 }
1079
1080 span.timelineComment {
1081 /* make the span behave like a div */
1082 /* padding: 10px 20px;*/
1083 /* display: block;*/
1084 }
1085
1086
1087 /* Login/Loguot
1088 ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */
@@ -1097,17 +1096,22 @@
1097 table.login_out td {
1098 border: 0;
1099 }
1100
1101
1102 /* Miscellaneous
1103 ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */
1104 .udiff, .sbsdiff {
1105 font-size: .85em !important;
1106 overflow: auto;
1107 border: 1px solid #ccc;
1108 border-radius: 5px;
 
 
 
 
 
1109 }
1110
1111
1112 /* Ticket Reports
1113 ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */
1114
--- skins/blitz/css.txt
+++ skins/blitz/css.txt
@@ -464,11 +464,11 @@
464 font-weight: 400;
465 color: #ccc;
466 }
467
468 pre, code {
469 font-size: 1.2rem;
470 }
471
472 body {
473 font-size: 1.4em; /* currently ems cause chrome bug misinterpreting rems on body element */
474 line-height: 1.5;
@@ -599,10 +599,11 @@
599 -moz-appearance: none;
600 appearance: none;
601 }
602
603 textarea {
604 height: inherit;
605 min-height: 65px;
606 padding-top: 6px;
607 padding-bottom: 6px;
608 }
609
@@ -857,11 +858,10 @@
858
859 .mainmenu li {
860 outline: 0;
861 display: block;
862 float: left;
 
863 margin: 0;
864 }
865
866 .mainmenu li.active {
867 background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEQAACxEBf2RfkQAAAAd0SU1FB90FDxEXAZ2XRzAAAABJSURBVCjPY2CgBzhz5sx/QmoYiTXAxMSEkWRDsLkAl0GMpHoBm0EoAlu3bmUQFxcnGAboBjEhc4gxAJtLGUmJBVwuYiTXAGSDAIx5IBObnuVxAAAAAElFTkSuQmCC);
@@ -868,12 +868,13 @@
868 background-repeat: no-repeat;
869 background-position: center bottom;
870 }
871
872 .mainmenu li a {
873 color: #3b5c6b;
874 display: block;
875 padding: 10px 15px;
876 }
877
878 .mainmenu li.active a {
879 font-weight: bold;
880 }
@@ -890,11 +891,11 @@
891 padding: 10px 0px;
892 border-bottom: 1px solid #ddd;
893 }
894
895 .submenu input, .submenu select {
896 margin: 0 0 0 5px;
897 }
898
899 .submenu a {
900 color: #3b5c6b;
901 padding: 5px 15px;
@@ -1072,17 +1073,15 @@
1073 font-weight: bold;
1074 white-space: nowrap;
1075 }
1076
1077 a.timelineHistLink {
1078 text-transform: lowercase;
1079 }
1080
1081 span.timelineComment {
1082 padding: 0px 5px;
 
 
1083 }
1084
1085
1086 /* Login/Loguot
1087 ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */
@@ -1097,17 +1096,22 @@
1096 table.login_out td {
1097 border: 0;
1098 }
1099
1100
1101 /* Diff displays
1102 ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */
1103 pre.udiff, table.sbsdiffcols {
1104 width: 100%;
1105 overflow: auto;
1106 border: 1px solid #ccc;
1107 padding: 5px;
1108 font-size: 1rem;
1109 }
1110
1111 pre.udiff:focus, table.sbsdiffcols:focus {
1112 outline: none;
1113 }
1114
1115
1116 /* Ticket Reports
1117 ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */
1118
--- skins/blitz_no_logo/css.txt
+++ skins/blitz_no_logo/css.txt
@@ -464,11 +464,11 @@
464464
font-weight: 400;
465465
color: #ccc;
466466
}
467467
468468
pre, code {
469
- font-size: 1.3rem;
469
+ font-size: 1.2rem;
470470
}
471471
472472
body {
473473
font-size: 1.4em; /* currently ems cause chrome bug misinterpreting rems on body element */
474474
line-height: 1.5;
@@ -599,10 +599,11 @@
599599
-moz-appearance: none;
600600
appearance: none;
601601
}
602602
603603
textarea {
604
+ height: inherit;
604605
min-height: 65px;
605606
padding-top: 6px;
606607
padding-bottom: 6px;
607608
}
608609
@@ -857,11 +858,10 @@
857858
858859
.mainmenu li {
859860
outline: 0;
860861
display: block;
861862
float: left;
862
- padding: 10px 15px;
863863
margin: 0;
864864
}
865865
866866
.mainmenu li.active {
867867
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEQAACxEBf2RfkQAAAAd0SU1FB90FDxEXAZ2XRzAAAABJSURBVCjPY2CgBzhz5sx/QmoYiTXAxMSEkWRDsLkAl0GMpHoBm0EoAlu3bmUQFxcnGAboBjEhc4gxAJtLGUmJBVwuYiTXAGSDAIx5IBObnuVxAAAAAElFTkSuQmCC);
@@ -868,12 +868,13 @@
868868
background-repeat: no-repeat;
869869
background-position: center bottom;
870870
}
871871
872872
.mainmenu li a {
873
- color: #3b5c6b;
874
- display: block;
873
+ color: #3b5c6b;
874
+ display: block;
875
+ padding: 10px 15px;
875876
}
876877
877878
.mainmenu li.active a {
878879
font-weight: bold;
879880
}
@@ -890,11 +891,11 @@
890891
padding: 10px 0px;
891892
border-bottom: 1px solid #ddd;
892893
}
893894
894895
.submenu input, .submenu select {
895
- margin: 0;
896
+ margin: 0 0 0 5px;
896897
}
897898
898899
.submenu a {
899900
color: #3b5c6b;
900901
padding: 5px 15px;
@@ -1072,17 +1073,15 @@
10721073
font-weight: bold;
10731074
white-space: nowrap;
10741075
}
10751076
10761077
a.timelineHistLink {
1077
- text-transform: uppercase;
1078
+ text-transform: lowercase;
10781079
}
10791080
10801081
span.timelineComment {
1081
- /* make the span behave like a div */
1082
- /* padding: 10px 20px;*/
1083
- /* display: block;*/
1082
+ padding: 0px 5px;
10841083
}
10851084
10861085
10871086
/* Login/Loguot
10881087
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */
@@ -1097,17 +1096,22 @@
10971096
table.login_out td {
10981097
border: 0;
10991098
}
11001099
11011100
1102
-/* Miscellaneous
1101
+/* Diff displays
11031102
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */
1104
-.udiff, .sbsdiff {
1105
- font-size: .85em !important;
1106
- overflow: auto;
1107
- border: 1px solid #ccc;
1108
- border-radius: 5px;
1103
+pre.udiff, table.sbsdiffcols {
1104
+ width: 100%;
1105
+ overflow: auto;
1106
+ border: 1px solid #ccc;
1107
+ padding: 0px 5px;
1108
+ font-size: 1rem;
1109
+}
1110
+
1111
+pre.udiff:focus, table.sbsdiffcols:focus {
1112
+ outline: none;
11091113
}
11101114
11111115
11121116
/* Ticket Reports
11131117
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */
11141118
--- skins/blitz_no_logo/css.txt
+++ skins/blitz_no_logo/css.txt
@@ -464,11 +464,11 @@
464 font-weight: 400;
465 color: #ccc;
466 }
467
468 pre, code {
469 font-size: 1.3rem;
470 }
471
472 body {
473 font-size: 1.4em; /* currently ems cause chrome bug misinterpreting rems on body element */
474 line-height: 1.5;
@@ -599,10 +599,11 @@
599 -moz-appearance: none;
600 appearance: none;
601 }
602
603 textarea {
 
604 min-height: 65px;
605 padding-top: 6px;
606 padding-bottom: 6px;
607 }
608
@@ -857,11 +858,10 @@
857
858 .mainmenu li {
859 outline: 0;
860 display: block;
861 float: left;
862 padding: 10px 15px;
863 margin: 0;
864 }
865
866 .mainmenu li.active {
867 background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEQAACxEBf2RfkQAAAAd0SU1FB90FDxEXAZ2XRzAAAABJSURBVCjPY2CgBzhz5sx/QmoYiTXAxMSEkWRDsLkAl0GMpHoBm0EoAlu3bmUQFxcnGAboBjEhc4gxAJtLGUmJBVwuYiTXAGSDAIx5IBObnuVxAAAAAElFTkSuQmCC);
@@ -868,12 +868,13 @@
868 background-repeat: no-repeat;
869 background-position: center bottom;
870 }
871
872 .mainmenu li a {
873 color: #3b5c6b;
874 display: block;
 
875 }
876
877 .mainmenu li.active a {
878 font-weight: bold;
879 }
@@ -890,11 +891,11 @@
890 padding: 10px 0px;
891 border-bottom: 1px solid #ddd;
892 }
893
894 .submenu input, .submenu select {
895 margin: 0;
896 }
897
898 .submenu a {
899 color: #3b5c6b;
900 padding: 5px 15px;
@@ -1072,17 +1073,15 @@
1072 font-weight: bold;
1073 white-space: nowrap;
1074 }
1075
1076 a.timelineHistLink {
1077 text-transform: uppercase;
1078 }
1079
1080 span.timelineComment {
1081 /* make the span behave like a div */
1082 /* padding: 10px 20px;*/
1083 /* display: block;*/
1084 }
1085
1086
1087 /* Login/Loguot
1088 ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */
@@ -1097,17 +1096,22 @@
1097 table.login_out td {
1098 border: 0;
1099 }
1100
1101
1102 /* Miscellaneous
1103 ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */
1104 .udiff, .sbsdiff {
1105 font-size: .85em !important;
1106 overflow: auto;
1107 border: 1px solid #ccc;
1108 border-radius: 5px;
 
 
 
 
 
1109 }
1110
1111
1112 /* Ticket Reports
1113 ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */
1114
--- skins/blitz_no_logo/css.txt
+++ skins/blitz_no_logo/css.txt
@@ -464,11 +464,11 @@
464 font-weight: 400;
465 color: #ccc;
466 }
467
468 pre, code {
469 font-size: 1.2rem;
470 }
471
472 body {
473 font-size: 1.4em; /* currently ems cause chrome bug misinterpreting rems on body element */
474 line-height: 1.5;
@@ -599,10 +599,11 @@
599 -moz-appearance: none;
600 appearance: none;
601 }
602
603 textarea {
604 height: inherit;
605 min-height: 65px;
606 padding-top: 6px;
607 padding-bottom: 6px;
608 }
609
@@ -857,11 +858,10 @@
858
859 .mainmenu li {
860 outline: 0;
861 display: block;
862 float: left;
 
863 margin: 0;
864 }
865
866 .mainmenu li.active {
867 background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEQAACxEBf2RfkQAAAAd0SU1FB90FDxEXAZ2XRzAAAABJSURBVCjPY2CgBzhz5sx/QmoYiTXAxMSEkWRDsLkAl0GMpHoBm0EoAlu3bmUQFxcnGAboBjEhc4gxAJtLGUmJBVwuYiTXAGSDAIx5IBObnuVxAAAAAElFTkSuQmCC);
@@ -868,12 +868,13 @@
868 background-repeat: no-repeat;
869 background-position: center bottom;
870 }
871
872 .mainmenu li a {
873 color: #3b5c6b;
874 display: block;
875 padding: 10px 15px;
876 }
877
878 .mainmenu li.active a {
879 font-weight: bold;
880 }
@@ -890,11 +891,11 @@
891 padding: 10px 0px;
892 border-bottom: 1px solid #ddd;
893 }
894
895 .submenu input, .submenu select {
896 margin: 0 0 0 5px;
897 }
898
899 .submenu a {
900 color: #3b5c6b;
901 padding: 5px 15px;
@@ -1072,17 +1073,15 @@
1073 font-weight: bold;
1074 white-space: nowrap;
1075 }
1076
1077 a.timelineHistLink {
1078 text-transform: lowercase;
1079 }
1080
1081 span.timelineComment {
1082 padding: 0px 5px;
 
 
1083 }
1084
1085
1086 /* Login/Loguot
1087 ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */
@@ -1097,17 +1096,22 @@
1096 table.login_out td {
1097 border: 0;
1098 }
1099
1100
1101 /* Diff displays
1102 ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */
1103 pre.udiff, table.sbsdiffcols {
1104 width: 100%;
1105 overflow: auto;
1106 border: 1px solid #ccc;
1107 padding: 0px 5px;
1108 font-size: 1rem;
1109 }
1110
1111 pre.udiff:focus, table.sbsdiffcols:focus {
1112 outline: none;
1113 }
1114
1115
1116 /* Ticket Reports
1117 ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– */
1118
--- skins/eagle/header.txt
+++ skins/eagle/header.txt
@@ -70,15 +70,10 @@
7070
}
7171
set logourl [getLogoUrl $baseurl]
7272
</th1>
7373
<a href="$logourl">
7474
<img src="$logo_image_url" border="0" alt="$project_name">
75
- <th1>
76
- if {[anycap jor]} {
77
- html "<a class='rss' href='$home/timeline.rss'></a>"
78
- }
79
- </th1>
8075
</a>
8176
</div>
8277
<div class="title">$<title></div>
8378
<div class="status"><nobr><th1>
8479
if {[info exists login]} {
8580
--- skins/eagle/header.txt
+++ skins/eagle/header.txt
@@ -70,15 +70,10 @@
70 }
71 set logourl [getLogoUrl $baseurl]
72 </th1>
73 <a href="$logourl">
74 <img src="$logo_image_url" border="0" alt="$project_name">
75 <th1>
76 if {[anycap jor]} {
77 html "<a class='rss' href='$home/timeline.rss'></a>"
78 }
79 </th1>
80 </a>
81 </div>
82 <div class="title">$<title></div>
83 <div class="status"><nobr><th1>
84 if {[info exists login]} {
85
--- skins/eagle/header.txt
+++ skins/eagle/header.txt
@@ -70,15 +70,10 @@
70 }
71 set logourl [getLogoUrl $baseurl]
72 </th1>
73 <a href="$logourl">
74 <img src="$logo_image_url" border="0" alt="$project_name">
 
 
 
 
 
75 </a>
76 </div>
77 <div class="title">$<title></div>
78 <div class="status"><nobr><th1>
79 if {[info exists login]} {
80
--- skins/enhanced1/header.txt
+++ skins/enhanced1/header.txt
@@ -70,15 +70,10 @@
7070
}
7171
set logourl [getLogoUrl $baseurl]
7272
</th1>
7373
<a href="$logourl">
7474
<img src="$logo_image_url" border="0" alt="$project_name">
75
- <th1>
76
- if {[anycap jor]} {
77
- html "<a class='rss' href='$home/timeline.rss'></a>"
78
- }
79
- </th1>
8075
</a>
8176
</div>
8277
<div class="title">$<title></div>
8378
<div class="status"><th1>
8479
if {[info exists login]} {
8580
--- skins/enhanced1/header.txt
+++ skins/enhanced1/header.txt
@@ -70,15 +70,10 @@
70 }
71 set logourl [getLogoUrl $baseurl]
72 </th1>
73 <a href="$logourl">
74 <img src="$logo_image_url" border="0" alt="$project_name">
75 <th1>
76 if {[anycap jor]} {
77 html "<a class='rss' href='$home/timeline.rss'></a>"
78 }
79 </th1>
80 </a>
81 </div>
82 <div class="title">$<title></div>
83 <div class="status"><th1>
84 if {[info exists login]} {
85
--- skins/enhanced1/header.txt
+++ skins/enhanced1/header.txt
@@ -70,15 +70,10 @@
70 }
71 set logourl [getLogoUrl $baseurl]
72 </th1>
73 <a href="$logourl">
74 <img src="$logo_image_url" border="0" alt="$project_name">
 
 
 
 
 
75 </a>
76 </div>
77 <div class="title">$<title></div>
78 <div class="status"><th1>
79 if {[info exists login]} {
80
+2
--- src/add.c
+++ src/add.c
@@ -306,10 +306,11 @@
306306
zCleanFlag = db_get("clean-glob", 0);
307307
}
308308
if( zIgnoreFlag==0 ){
309309
zIgnoreFlag = db_get("ignore-glob", 0);
310310
}
311
+ if( db_get_boolean("dotfiles", 0) ) scanFlags |= SCAN_ALL;
311312
vid = db_lget_int("checkout",0);
312313
db_begin_transaction();
313314
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
314315
filename_collation());
315316
pClean = glob_create(zCleanFlag);
@@ -646,10 +647,11 @@
646647
zCleanFlag = db_get("clean-glob", 0);
647648
}
648649
if( zIgnoreFlag==0 ){
649650
zIgnoreFlag = db_get("ignore-glob", 0);
650651
}
652
+ if( db_get_boolean("dotfiles", 0) ) scanFlags |= SCAN_ALL;
651653
vid = db_lget_int("checkout",0);
652654
db_begin_transaction();
653655
654656
/* step 1:
655657
** Populate the temp table "sfile" with the names of all unmanaged
656658
--- src/add.c
+++ src/add.c
@@ -306,10 +306,11 @@
306 zCleanFlag = db_get("clean-glob", 0);
307 }
308 if( zIgnoreFlag==0 ){
309 zIgnoreFlag = db_get("ignore-glob", 0);
310 }
 
311 vid = db_lget_int("checkout",0);
312 db_begin_transaction();
313 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
314 filename_collation());
315 pClean = glob_create(zCleanFlag);
@@ -646,10 +647,11 @@
646 zCleanFlag = db_get("clean-glob", 0);
647 }
648 if( zIgnoreFlag==0 ){
649 zIgnoreFlag = db_get("ignore-glob", 0);
650 }
 
651 vid = db_lget_int("checkout",0);
652 db_begin_transaction();
653
654 /* step 1:
655 ** Populate the temp table "sfile" with the names of all unmanaged
656
--- src/add.c
+++ src/add.c
@@ -306,10 +306,11 @@
306 zCleanFlag = db_get("clean-glob", 0);
307 }
308 if( zIgnoreFlag==0 ){
309 zIgnoreFlag = db_get("ignore-glob", 0);
310 }
311 if( db_get_boolean("dotfiles", 0) ) scanFlags |= SCAN_ALL;
312 vid = db_lget_int("checkout",0);
313 db_begin_transaction();
314 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
315 filename_collation());
316 pClean = glob_create(zCleanFlag);
@@ -646,10 +647,11 @@
647 zCleanFlag = db_get("clean-glob", 0);
648 }
649 if( zIgnoreFlag==0 ){
650 zIgnoreFlag = db_get("ignore-glob", 0);
651 }
652 if( db_get_boolean("dotfiles", 0) ) scanFlags |= SCAN_ALL;
653 vid = db_lget_int("checkout",0);
654 db_begin_transaction();
655
656 /* step 1:
657 ** Populate the temp table "sfile" with the names of all unmanaged
658
+2
--- src/add.c
+++ src/add.c
@@ -306,10 +306,11 @@
306306
zCleanFlag = db_get("clean-glob", 0);
307307
}
308308
if( zIgnoreFlag==0 ){
309309
zIgnoreFlag = db_get("ignore-glob", 0);
310310
}
311
+ if( db_get_boolean("dotfiles", 0) ) scanFlags |= SCAN_ALL;
311312
vid = db_lget_int("checkout",0);
312313
db_begin_transaction();
313314
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
314315
filename_collation());
315316
pClean = glob_create(zCleanFlag);
@@ -646,10 +647,11 @@
646647
zCleanFlag = db_get("clean-glob", 0);
647648
}
648649
if( zIgnoreFlag==0 ){
649650
zIgnoreFlag = db_get("ignore-glob", 0);
650651
}
652
+ if( db_get_boolean("dotfiles", 0) ) scanFlags |= SCAN_ALL;
651653
vid = db_lget_int("checkout",0);
652654
db_begin_transaction();
653655
654656
/* step 1:
655657
** Populate the temp table "sfile" with the names of all unmanaged
656658
--- src/add.c
+++ src/add.c
@@ -306,10 +306,11 @@
306 zCleanFlag = db_get("clean-glob", 0);
307 }
308 if( zIgnoreFlag==0 ){
309 zIgnoreFlag = db_get("ignore-glob", 0);
310 }
 
311 vid = db_lget_int("checkout",0);
312 db_begin_transaction();
313 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
314 filename_collation());
315 pClean = glob_create(zCleanFlag);
@@ -646,10 +647,11 @@
646 zCleanFlag = db_get("clean-glob", 0);
647 }
648 if( zIgnoreFlag==0 ){
649 zIgnoreFlag = db_get("ignore-glob", 0);
650 }
 
651 vid = db_lget_int("checkout",0);
652 db_begin_transaction();
653
654 /* step 1:
655 ** Populate the temp table "sfile" with the names of all unmanaged
656
--- src/add.c
+++ src/add.c
@@ -306,10 +306,11 @@
306 zCleanFlag = db_get("clean-glob", 0);
307 }
308 if( zIgnoreFlag==0 ){
309 zIgnoreFlag = db_get("ignore-glob", 0);
310 }
311 if( db_get_boolean("dotfiles", 0) ) scanFlags |= SCAN_ALL;
312 vid = db_lget_int("checkout",0);
313 db_begin_transaction();
314 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)",
315 filename_collation());
316 pClean = glob_create(zCleanFlag);
@@ -646,10 +647,11 @@
647 zCleanFlag = db_get("clean-glob", 0);
648 }
649 if( zIgnoreFlag==0 ){
650 zIgnoreFlag = db_get("ignore-glob", 0);
651 }
652 if( db_get_boolean("dotfiles", 0) ) scanFlags |= SCAN_ALL;
653 vid = db_lget_int("checkout",0);
654 db_begin_transaction();
655
656 /* step 1:
657 ** Populate the temp table "sfile" with the names of all unmanaged
658
--- src/cache.c
+++ src/cache.c
@@ -226,10 +226,18 @@
226226
cache_read_done:
227227
sqlite3_exec(db, "COMMIT", 0, 0, 0);
228228
sqlite3_close(db);
229229
return rc;
230230
}
231
+
232
+/*
233
+** Create a cache database for the current repository if no such
234
+** database already exists.
235
+*/
236
+void cache_initialize(void){
237
+ sqlite3_close(cacheOpen(1));
238
+}
231239
232240
/*
233241
** COMMAND: cache*
234242
** Usage: %fossil cache SUBCOMMAND
235243
**
236244
--- src/cache.c
+++ src/cache.c
@@ -226,10 +226,18 @@
226 cache_read_done:
227 sqlite3_exec(db, "COMMIT", 0, 0, 0);
228 sqlite3_close(db);
229 return rc;
230 }
 
 
 
 
 
 
 
 
231
232 /*
233 ** COMMAND: cache*
234 ** Usage: %fossil cache SUBCOMMAND
235 **
236
--- src/cache.c
+++ src/cache.c
@@ -226,10 +226,18 @@
226 cache_read_done:
227 sqlite3_exec(db, "COMMIT", 0, 0, 0);
228 sqlite3_close(db);
229 return rc;
230 }
231
232 /*
233 ** Create a cache database for the current repository if no such
234 ** database already exists.
235 */
236 void cache_initialize(void){
237 sqlite3_close(cacheOpen(1));
238 }
239
240 /*
241 ** COMMAND: cache*
242 ** Usage: %fossil cache SUBCOMMAND
243 **
244
--- src/checkin.c
+++ src/checkin.c
@@ -571,10 +571,12 @@
571571
572572
if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
573573
db_must_be_within_tree();
574574
cwdRelative = determine_cwd_relative_option();
575575
576
+ if( db_get_boolean("dotfiles", 0) ) scanFlags |= SCAN_ALL;
577
+
576578
/* We should be done with options.. */
577579
verify_all_options();
578580
579581
if( zIgnoreFlag==0 ){
580582
zIgnoreFlag = db_get("ignore-glob", 0);
@@ -707,10 +709,11 @@
707709
zKeepFlag = db_get("keep-glob", 0);
708710
}
709711
if( zCleanFlag==0 ){
710712
zCleanFlag = db_get("clean-glob", 0);
711713
}
714
+ if( db_get_boolean("dotfiles", 0) ) scanFlags |= SCAN_ALL;
712715
verify_all_options();
713716
pIgnore = glob_create(zIgnoreFlag);
714717
pKeep = glob_create(zKeepFlag);
715718
pClean = glob_create(zCleanFlag);
716719
nRoot = (int)strlen(g.zLocalRoot);
717720
--- src/checkin.c
+++ src/checkin.c
@@ -571,10 +571,12 @@
571
572 if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
573 db_must_be_within_tree();
574 cwdRelative = determine_cwd_relative_option();
575
 
 
576 /* We should be done with options.. */
577 verify_all_options();
578
579 if( zIgnoreFlag==0 ){
580 zIgnoreFlag = db_get("ignore-glob", 0);
@@ -707,10 +709,11 @@
707 zKeepFlag = db_get("keep-glob", 0);
708 }
709 if( zCleanFlag==0 ){
710 zCleanFlag = db_get("clean-glob", 0);
711 }
 
712 verify_all_options();
713 pIgnore = glob_create(zIgnoreFlag);
714 pKeep = glob_create(zKeepFlag);
715 pClean = glob_create(zCleanFlag);
716 nRoot = (int)strlen(g.zLocalRoot);
717
--- src/checkin.c
+++ src/checkin.c
@@ -571,10 +571,12 @@
571
572 if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
573 db_must_be_within_tree();
574 cwdRelative = determine_cwd_relative_option();
575
576 if( db_get_boolean("dotfiles", 0) ) scanFlags |= SCAN_ALL;
577
578 /* We should be done with options.. */
579 verify_all_options();
580
581 if( zIgnoreFlag==0 ){
582 zIgnoreFlag = db_get("ignore-glob", 0);
@@ -707,10 +709,11 @@
709 zKeepFlag = db_get("keep-glob", 0);
710 }
711 if( zCleanFlag==0 ){
712 zCleanFlag = db_get("clean-glob", 0);
713 }
714 if( db_get_boolean("dotfiles", 0) ) scanFlags |= SCAN_ALL;
715 verify_all_options();
716 pIgnore = glob_create(zIgnoreFlag);
717 pKeep = glob_create(zKeepFlag);
718 pClean = glob_create(zCleanFlag);
719 nRoot = (int)strlen(g.zLocalRoot);
720
+2 -1
--- src/clone.c
+++ src/clone.c
@@ -164,11 +164,11 @@
164164
}else{
165165
db_create_repository(g.argv[3]);
166166
db_open_repository(g.argv[3]);
167167
db_begin_transaction();
168168
db_record_repository_filename(g.argv[3]);
169
- db_initial_setup(0, 0, zDefaultUser, 0);
169
+ db_initial_setup(0, 0, zDefaultUser);
170170
user_select();
171171
db_set("content-schema", CONTENT_SCHEMA, 0);
172172
db_set("aux-schema", AUX_SCHEMA_MAX, 0);
173173
db_set("rebuilt", get_version(), 0);
174174
remember_or_get_http_auth(zHttpAuth, urlFlags & URL_REMEMBER, g.argv[2]);
@@ -182,10 +182,11 @@
182182
blob_reset(&fn);
183183
}
184184
db_multi_exec(
185185
"REPLACE INTO config(name,value,mtime)"
186186
" VALUES('server-code', lower(hex(randomblob(20))), now());"
187
+ "DELETE FROM config WHERE name='project-code';"
187188
);
188189
url_enable_proxy(0);
189190
clone_ssh_db_set_options();
190191
url_get_password_if_needed();
191192
g.xlinkClusterOnly = 1;
192193
--- src/clone.c
+++ src/clone.c
@@ -164,11 +164,11 @@
164 }else{
165 db_create_repository(g.argv[3]);
166 db_open_repository(g.argv[3]);
167 db_begin_transaction();
168 db_record_repository_filename(g.argv[3]);
169 db_initial_setup(0, 0, zDefaultUser, 0);
170 user_select();
171 db_set("content-schema", CONTENT_SCHEMA, 0);
172 db_set("aux-schema", AUX_SCHEMA_MAX, 0);
173 db_set("rebuilt", get_version(), 0);
174 remember_or_get_http_auth(zHttpAuth, urlFlags & URL_REMEMBER, g.argv[2]);
@@ -182,10 +182,11 @@
182 blob_reset(&fn);
183 }
184 db_multi_exec(
185 "REPLACE INTO config(name,value,mtime)"
186 " VALUES('server-code', lower(hex(randomblob(20))), now());"
 
187 );
188 url_enable_proxy(0);
189 clone_ssh_db_set_options();
190 url_get_password_if_needed();
191 g.xlinkClusterOnly = 1;
192
--- src/clone.c
+++ src/clone.c
@@ -164,11 +164,11 @@
164 }else{
165 db_create_repository(g.argv[3]);
166 db_open_repository(g.argv[3]);
167 db_begin_transaction();
168 db_record_repository_filename(g.argv[3]);
169 db_initial_setup(0, 0, zDefaultUser);
170 user_select();
171 db_set("content-schema", CONTENT_SCHEMA, 0);
172 db_set("aux-schema", AUX_SCHEMA_MAX, 0);
173 db_set("rebuilt", get_version(), 0);
174 remember_or_get_http_auth(zHttpAuth, urlFlags & URL_REMEMBER, g.argv[2]);
@@ -182,10 +182,11 @@
182 blob_reset(&fn);
183 }
184 db_multi_exec(
185 "REPLACE INTO config(name,value,mtime)"
186 " VALUES('server-code', lower(hex(randomblob(20))), now());"
187 "DELETE FROM config WHERE name='project-code';"
188 );
189 url_enable_proxy(0);
190 clone_ssh_db_set_options();
191 url_get_password_if_needed();
192 g.xlinkClusterOnly = 1;
193
+3 -1
--- src/configure.c
+++ src/configure.c
@@ -97,10 +97,11 @@
9797
{ "timeline-plaintext", CONFIGSET_SKIN },
9898
{ "adunit", CONFIGSET_SKIN },
9999
{ "adunit-omit-if-admin", CONFIGSET_SKIN },
100100
{ "adunit-omit-if-user", CONFIGSET_SKIN },
101101
{ "white-foreground", CONFIGSET_SKIN },
102
+
102103
#ifdef FOSSIL_ENABLE_TH1_DOCS
103104
{ "th1-docs", CONFIGSET_TH1 },
104105
#endif
105106
#ifdef FOSSIL_ENABLE_TH1_HOOKS
106107
{ "th1-hooks", CONFIGSET_TH1 },
@@ -124,10 +125,11 @@
124125
{ "keep-glob", CONFIGSET_PROJ },
125126
{ "crnl-glob", CONFIGSET_PROJ },
126127
{ "encoding-glob", CONFIGSET_PROJ },
127128
{ "empty-dirs", CONFIGSET_PROJ },
128129
{ "allow-symlinks", CONFIGSET_PROJ },
130
+ { "dotfiles", CONFIGSET_PROJ },
129131
130132
#ifdef FOSSIL_ENABLE_LEGACY_MV_RM
131133
{ "move-files", CONFIGSET_PROJ },
132134
{ "remove-files", CONFIGSET_PROJ },
133135
#endif
@@ -862,11 +864,11 @@
862864
**
863865
** Push the local configuration into the remote server identified
864866
** by URL. Admin privilege is required on the remote server for
865867
** this to work. When the same record exists both locally and on
866868
** the remote end, the one that was most recently changed wins.
867
-** Use the --legacy flag when talking to holder servers.
869
+** Use the --legacy flag when talking to older servers.
868870
**
869871
** %fossil configuration reset AREA
870872
**
871873
** Restore the configuration to the default. AREA as above.
872874
**
873875
--- src/configure.c
+++ src/configure.c
@@ -97,10 +97,11 @@
97 { "timeline-plaintext", CONFIGSET_SKIN },
98 { "adunit", CONFIGSET_SKIN },
99 { "adunit-omit-if-admin", CONFIGSET_SKIN },
100 { "adunit-omit-if-user", CONFIGSET_SKIN },
101 { "white-foreground", CONFIGSET_SKIN },
 
102 #ifdef FOSSIL_ENABLE_TH1_DOCS
103 { "th1-docs", CONFIGSET_TH1 },
104 #endif
105 #ifdef FOSSIL_ENABLE_TH1_HOOKS
106 { "th1-hooks", CONFIGSET_TH1 },
@@ -124,10 +125,11 @@
124 { "keep-glob", CONFIGSET_PROJ },
125 { "crnl-glob", CONFIGSET_PROJ },
126 { "encoding-glob", CONFIGSET_PROJ },
127 { "empty-dirs", CONFIGSET_PROJ },
128 { "allow-symlinks", CONFIGSET_PROJ },
 
129
130 #ifdef FOSSIL_ENABLE_LEGACY_MV_RM
131 { "move-files", CONFIGSET_PROJ },
132 { "remove-files", CONFIGSET_PROJ },
133 #endif
@@ -862,11 +864,11 @@
862 **
863 ** Push the local configuration into the remote server identified
864 ** by URL. Admin privilege is required on the remote server for
865 ** this to work. When the same record exists both locally and on
866 ** the remote end, the one that was most recently changed wins.
867 ** Use the --legacy flag when talking to holder servers.
868 **
869 ** %fossil configuration reset AREA
870 **
871 ** Restore the configuration to the default. AREA as above.
872 **
873
--- src/configure.c
+++ src/configure.c
@@ -97,10 +97,11 @@
97 { "timeline-plaintext", CONFIGSET_SKIN },
98 { "adunit", CONFIGSET_SKIN },
99 { "adunit-omit-if-admin", CONFIGSET_SKIN },
100 { "adunit-omit-if-user", CONFIGSET_SKIN },
101 { "white-foreground", CONFIGSET_SKIN },
102
103 #ifdef FOSSIL_ENABLE_TH1_DOCS
104 { "th1-docs", CONFIGSET_TH1 },
105 #endif
106 #ifdef FOSSIL_ENABLE_TH1_HOOKS
107 { "th1-hooks", CONFIGSET_TH1 },
@@ -124,10 +125,11 @@
125 { "keep-glob", CONFIGSET_PROJ },
126 { "crnl-glob", CONFIGSET_PROJ },
127 { "encoding-glob", CONFIGSET_PROJ },
128 { "empty-dirs", CONFIGSET_PROJ },
129 { "allow-symlinks", CONFIGSET_PROJ },
130 { "dotfiles", CONFIGSET_PROJ },
131
132 #ifdef FOSSIL_ENABLE_LEGACY_MV_RM
133 { "move-files", CONFIGSET_PROJ },
134 { "remove-files", CONFIGSET_PROJ },
135 #endif
@@ -862,11 +864,11 @@
864 **
865 ** Push the local configuration into the remote server identified
866 ** by URL. Admin privilege is required on the remote server for
867 ** this to work. When the same record exists both locally and on
868 ** the remote end, the one that was most recently changed wins.
869 ** Use the --legacy flag when talking to older servers.
870 **
871 ** %fossil configuration reset AREA
872 **
873 ** Restore the configuration to the default. AREA as above.
874 **
875
+3 -1
--- src/configure.c
+++ src/configure.c
@@ -97,10 +97,11 @@
9797
{ "timeline-plaintext", CONFIGSET_SKIN },
9898
{ "adunit", CONFIGSET_SKIN },
9999
{ "adunit-omit-if-admin", CONFIGSET_SKIN },
100100
{ "adunit-omit-if-user", CONFIGSET_SKIN },
101101
{ "white-foreground", CONFIGSET_SKIN },
102
+
102103
#ifdef FOSSIL_ENABLE_TH1_DOCS
103104
{ "th1-docs", CONFIGSET_TH1 },
104105
#endif
105106
#ifdef FOSSIL_ENABLE_TH1_HOOKS
106107
{ "th1-hooks", CONFIGSET_TH1 },
@@ -124,10 +125,11 @@
124125
{ "keep-glob", CONFIGSET_PROJ },
125126
{ "crnl-glob", CONFIGSET_PROJ },
126127
{ "encoding-glob", CONFIGSET_PROJ },
127128
{ "empty-dirs", CONFIGSET_PROJ },
128129
{ "allow-symlinks", CONFIGSET_PROJ },
130
+ { "dotfiles", CONFIGSET_PROJ },
129131
130132
#ifdef FOSSIL_ENABLE_LEGACY_MV_RM
131133
{ "move-files", CONFIGSET_PROJ },
132134
{ "remove-files", CONFIGSET_PROJ },
133135
#endif
@@ -862,11 +864,11 @@
862864
**
863865
** Push the local configuration into the remote server identified
864866
** by URL. Admin privilege is required on the remote server for
865867
** this to work. When the same record exists both locally and on
866868
** the remote end, the one that was most recently changed wins.
867
-** Use the --legacy flag when talking to holder servers.
869
+** Use the --legacy flag when talking to older servers.
868870
**
869871
** %fossil configuration reset AREA
870872
**
871873
** Restore the configuration to the default. AREA as above.
872874
**
873875
--- src/configure.c
+++ src/configure.c
@@ -97,10 +97,11 @@
97 { "timeline-plaintext", CONFIGSET_SKIN },
98 { "adunit", CONFIGSET_SKIN },
99 { "adunit-omit-if-admin", CONFIGSET_SKIN },
100 { "adunit-omit-if-user", CONFIGSET_SKIN },
101 { "white-foreground", CONFIGSET_SKIN },
 
102 #ifdef FOSSIL_ENABLE_TH1_DOCS
103 { "th1-docs", CONFIGSET_TH1 },
104 #endif
105 #ifdef FOSSIL_ENABLE_TH1_HOOKS
106 { "th1-hooks", CONFIGSET_TH1 },
@@ -124,10 +125,11 @@
124 { "keep-glob", CONFIGSET_PROJ },
125 { "crnl-glob", CONFIGSET_PROJ },
126 { "encoding-glob", CONFIGSET_PROJ },
127 { "empty-dirs", CONFIGSET_PROJ },
128 { "allow-symlinks", CONFIGSET_PROJ },
 
129
130 #ifdef FOSSIL_ENABLE_LEGACY_MV_RM
131 { "move-files", CONFIGSET_PROJ },
132 { "remove-files", CONFIGSET_PROJ },
133 #endif
@@ -862,11 +864,11 @@
862 **
863 ** Push the local configuration into the remote server identified
864 ** by URL. Admin privilege is required on the remote server for
865 ** this to work. When the same record exists both locally and on
866 ** the remote end, the one that was most recently changed wins.
867 ** Use the --legacy flag when talking to holder servers.
868 **
869 ** %fossil configuration reset AREA
870 **
871 ** Restore the configuration to the default. AREA as above.
872 **
873
--- src/configure.c
+++ src/configure.c
@@ -97,10 +97,11 @@
97 { "timeline-plaintext", CONFIGSET_SKIN },
98 { "adunit", CONFIGSET_SKIN },
99 { "adunit-omit-if-admin", CONFIGSET_SKIN },
100 { "adunit-omit-if-user", CONFIGSET_SKIN },
101 { "white-foreground", CONFIGSET_SKIN },
102
103 #ifdef FOSSIL_ENABLE_TH1_DOCS
104 { "th1-docs", CONFIGSET_TH1 },
105 #endif
106 #ifdef FOSSIL_ENABLE_TH1_HOOKS
107 { "th1-hooks", CONFIGSET_TH1 },
@@ -124,10 +125,11 @@
125 { "keep-glob", CONFIGSET_PROJ },
126 { "crnl-glob", CONFIGSET_PROJ },
127 { "encoding-glob", CONFIGSET_PROJ },
128 { "empty-dirs", CONFIGSET_PROJ },
129 { "allow-symlinks", CONFIGSET_PROJ },
130 { "dotfiles", CONFIGSET_PROJ },
131
132 #ifdef FOSSIL_ENABLE_LEGACY_MV_RM
133 { "move-files", CONFIGSET_PROJ },
134 { "remove-files", CONFIGSET_PROJ },
135 #endif
@@ -862,11 +864,11 @@
864 **
865 ** Push the local configuration into the remote server identified
866 ** by URL. Admin privilege is required on the remote server for
867 ** this to work. When the same record exists both locally and on
868 ** the remote end, the one that was most recently changed wins.
869 ** Use the --legacy flag when talking to older servers.
870 **
871 ** %fossil configuration reset AREA
872 **
873 ** Restore the configuration to the default. AREA as above.
874 **
875
+11 -38
--- src/db.c
+++ src/db.c
@@ -1475,42 +1475,10 @@
14751475
" VALUES('reader','','kptw','Reader');"
14761476
);
14771477
}
14781478
}
14791479
1480
-/*
1481
-** This function sets the server and project codes if they do not already
1482
-** exist. Currently, it should be called only by the db_initial_setup()
1483
-** or cmd_webserver() functions, the latter being used to facilitate more
1484
-** robust integration with "canned image" environments (e.g. Docker).
1485
-*/
1486
-void db_setup_server_and_project_codes(
1487
- int optional
1488
-){
1489
- if( !optional ){
1490
- db_multi_exec(
1491
- "INSERT INTO config(name,value,mtime)"
1492
- " VALUES('server-code', lower(hex(randomblob(20))),now());"
1493
- "INSERT INTO config(name,value,mtime)"
1494
- " VALUES('project-code', lower(hex(randomblob(20))),now());"
1495
- );
1496
- }else if( db_is_writeable("repository") ){
1497
- if( db_get("server-code", 0)==0 ) {
1498
- db_multi_exec(
1499
- "INSERT INTO config(name,value,mtime)"
1500
- " VALUES('server-code', lower(hex(randomblob(20))),now());"
1501
- );
1502
- }
1503
- if( db_get("project-code", 0)==0 ) {
1504
- db_multi_exec(
1505
- "INSERT INTO config(name,value,mtime)"
1506
- " VALUES('project-code', lower(hex(randomblob(20))),now());"
1507
- );
1508
- }
1509
- }
1510
-}
1511
-
15121480
/*
15131481
** Return a pointer to a string that contains the RHS of an IN operator
15141482
** that will select CONFIG table names that are in the list of control
15151483
** settings.
15161484
*/
@@ -1548,23 +1516,25 @@
15481516
** not server and project codes are invented for this repository.
15491517
*/
15501518
void db_initial_setup(
15511519
const char *zTemplate, /* Repository from which to copy settings. */
15521520
const char *zInitialDate, /* Initial date of repository. (ex: "now") */
1553
- const char *zDefaultUser, /* Default user for the repository */
1554
- int makeServerCodes /* True to make new server & project codes */
1521
+ const char *zDefaultUser /* Default user for the repository */
15551522
){
15561523
char *zDate;
15571524
Blob hash;
15581525
Blob manifest;
15591526
15601527
db_set("content-schema", CONTENT_SCHEMA, 0);
15611528
db_set("aux-schema", AUX_SCHEMA_MAX, 0);
15621529
db_set("rebuilt", get_version(), 0);
1563
- if( makeServerCodes ){
1564
- db_setup_server_and_project_codes(0);
1565
- }
1530
+ db_multi_exec(
1531
+ "INSERT INTO config(name,value,mtime)"
1532
+ " VALUES('server-code', lower(hex(randomblob(20))),now());"
1533
+ "INSERT INTO config(name,value,mtime)"
1534
+ " VALUES('project-code', lower(hex(randomblob(20))),now());"
1535
+ );
15661536
if( !db_is_global("autosync") ) db_set_int("autosync", 1, 0);
15671537
if( !db_is_global("localauth") ) db_set_int("localauth", 0, 0);
15681538
if( !db_is_global("timeline-plaintext") ){
15691539
db_set_int("timeline-plaintext", 1, 0);
15701540
}
@@ -1687,11 +1657,11 @@
16871657
db_open_repository(g.argv[2]);
16881658
db_open_config(0);
16891659
if( zTemplate ) db_attach(zTemplate, "settingSrc");
16901660
db_begin_transaction();
16911661
if( zDate==0 ) zDate = "now";
1692
- db_initial_setup(zTemplate, zDate, zDefaultUser, 1);
1662
+ db_initial_setup(zTemplate, zDate, zDefaultUser);
16931663
db_end_transaction(0);
16941664
if( zTemplate ) db_detach("settingSrc");
16951665
fossil_print("project-id: %s\n", db_get("project-code", 0));
16961666
fossil_print("server-id: %s\n", db_get("server-code", 0));
16971667
zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
@@ -2375,10 +2345,11 @@
23752345
{ "crnl-glob", 0, 40, 1, 0, "" },
23762346
{ "default-perms", 0, 16, 0, 0, "u" },
23772347
{ "diff-binary", 0, 0, 0, 0, "on" },
23782348
{ "diff-command", 0, 40, 0, 0, "" },
23792349
{ "dont-push", 0, 0, 0, 0, "off" },
2350
+ { "dotfiles", 0, 0, 0, 0, "off" },
23802351
{ "editor", 0, 32, 0, 0, "" },
23812352
{ "empty-dirs", 0, 40, 1, 0, "" },
23822353
{ "encoding-glob", 0, 40, 1, 0, "" },
23832354
{ "gdiff-command", 0, 40, 0, 0, "gdiff" },
23842355
{ "gmerge-command", 0, 40, 0, 0, "" },
@@ -2541,10 +2512,12 @@
25412512
** diff-command External command to run when performing a diff.
25422513
** If undefined, the internal text diff will be used.
25432514
**
25442515
** dont-push Prevent this repository from pushing from client to
25452516
** server. Useful when setting up a private branch.
2517
+**
2518
+** dotfiles Include --dotfiles option for all compatible commands.
25462519
**
25472520
** editor Text editor command used for check-in comments.
25482521
**
25492522
** empty-dirs A comma or newline-separated list of pathnames. On
25502523
** (versionable) update and checkout commands, if no file or directory
25512524
--- src/db.c
+++ src/db.c
@@ -1475,42 +1475,10 @@
1475 " VALUES('reader','','kptw','Reader');"
1476 );
1477 }
1478 }
1479
1480 /*
1481 ** This function sets the server and project codes if they do not already
1482 ** exist. Currently, it should be called only by the db_initial_setup()
1483 ** or cmd_webserver() functions, the latter being used to facilitate more
1484 ** robust integration with "canned image" environments (e.g. Docker).
1485 */
1486 void db_setup_server_and_project_codes(
1487 int optional
1488 ){
1489 if( !optional ){
1490 db_multi_exec(
1491 "INSERT INTO config(name,value,mtime)"
1492 " VALUES('server-code', lower(hex(randomblob(20))),now());"
1493 "INSERT INTO config(name,value,mtime)"
1494 " VALUES('project-code', lower(hex(randomblob(20))),now());"
1495 );
1496 }else if( db_is_writeable("repository") ){
1497 if( db_get("server-code", 0)==0 ) {
1498 db_multi_exec(
1499 "INSERT INTO config(name,value,mtime)"
1500 " VALUES('server-code', lower(hex(randomblob(20))),now());"
1501 );
1502 }
1503 if( db_get("project-code", 0)==0 ) {
1504 db_multi_exec(
1505 "INSERT INTO config(name,value,mtime)"
1506 " VALUES('project-code', lower(hex(randomblob(20))),now());"
1507 );
1508 }
1509 }
1510 }
1511
1512 /*
1513 ** Return a pointer to a string that contains the RHS of an IN operator
1514 ** that will select CONFIG table names that are in the list of control
1515 ** settings.
1516 */
@@ -1548,23 +1516,25 @@
1548 ** not server and project codes are invented for this repository.
1549 */
1550 void db_initial_setup(
1551 const char *zTemplate, /* Repository from which to copy settings. */
1552 const char *zInitialDate, /* Initial date of repository. (ex: "now") */
1553 const char *zDefaultUser, /* Default user for the repository */
1554 int makeServerCodes /* True to make new server & project codes */
1555 ){
1556 char *zDate;
1557 Blob hash;
1558 Blob manifest;
1559
1560 db_set("content-schema", CONTENT_SCHEMA, 0);
1561 db_set("aux-schema", AUX_SCHEMA_MAX, 0);
1562 db_set("rebuilt", get_version(), 0);
1563 if( makeServerCodes ){
1564 db_setup_server_and_project_codes(0);
1565 }
 
 
 
1566 if( !db_is_global("autosync") ) db_set_int("autosync", 1, 0);
1567 if( !db_is_global("localauth") ) db_set_int("localauth", 0, 0);
1568 if( !db_is_global("timeline-plaintext") ){
1569 db_set_int("timeline-plaintext", 1, 0);
1570 }
@@ -1687,11 +1657,11 @@
1687 db_open_repository(g.argv[2]);
1688 db_open_config(0);
1689 if( zTemplate ) db_attach(zTemplate, "settingSrc");
1690 db_begin_transaction();
1691 if( zDate==0 ) zDate = "now";
1692 db_initial_setup(zTemplate, zDate, zDefaultUser, 1);
1693 db_end_transaction(0);
1694 if( zTemplate ) db_detach("settingSrc");
1695 fossil_print("project-id: %s\n", db_get("project-code", 0));
1696 fossil_print("server-id: %s\n", db_get("server-code", 0));
1697 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
@@ -2375,10 +2345,11 @@
2375 { "crnl-glob", 0, 40, 1, 0, "" },
2376 { "default-perms", 0, 16, 0, 0, "u" },
2377 { "diff-binary", 0, 0, 0, 0, "on" },
2378 { "diff-command", 0, 40, 0, 0, "" },
2379 { "dont-push", 0, 0, 0, 0, "off" },
 
2380 { "editor", 0, 32, 0, 0, "" },
2381 { "empty-dirs", 0, 40, 1, 0, "" },
2382 { "encoding-glob", 0, 40, 1, 0, "" },
2383 { "gdiff-command", 0, 40, 0, 0, "gdiff" },
2384 { "gmerge-command", 0, 40, 0, 0, "" },
@@ -2541,10 +2512,12 @@
2541 ** diff-command External command to run when performing a diff.
2542 ** If undefined, the internal text diff will be used.
2543 **
2544 ** dont-push Prevent this repository from pushing from client to
2545 ** server. Useful when setting up a private branch.
 
 
2546 **
2547 ** editor Text editor command used for check-in comments.
2548 **
2549 ** empty-dirs A comma or newline-separated list of pathnames. On
2550 ** (versionable) update and checkout commands, if no file or directory
2551
--- src/db.c
+++ src/db.c
@@ -1475,42 +1475,10 @@
1475 " VALUES('reader','','kptw','Reader');"
1476 );
1477 }
1478 }
1479
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1480 /*
1481 ** Return a pointer to a string that contains the RHS of an IN operator
1482 ** that will select CONFIG table names that are in the list of control
1483 ** settings.
1484 */
@@ -1548,23 +1516,25 @@
1516 ** not server and project codes are invented for this repository.
1517 */
1518 void db_initial_setup(
1519 const char *zTemplate, /* Repository from which to copy settings. */
1520 const char *zInitialDate, /* Initial date of repository. (ex: "now") */
1521 const char *zDefaultUser /* Default user for the repository */
 
1522 ){
1523 char *zDate;
1524 Blob hash;
1525 Blob manifest;
1526
1527 db_set("content-schema", CONTENT_SCHEMA, 0);
1528 db_set("aux-schema", AUX_SCHEMA_MAX, 0);
1529 db_set("rebuilt", get_version(), 0);
1530 db_multi_exec(
1531 "INSERT INTO config(name,value,mtime)"
1532 " VALUES('server-code', lower(hex(randomblob(20))),now());"
1533 "INSERT INTO config(name,value,mtime)"
1534 " VALUES('project-code', lower(hex(randomblob(20))),now());"
1535 );
1536 if( !db_is_global("autosync") ) db_set_int("autosync", 1, 0);
1537 if( !db_is_global("localauth") ) db_set_int("localauth", 0, 0);
1538 if( !db_is_global("timeline-plaintext") ){
1539 db_set_int("timeline-plaintext", 1, 0);
1540 }
@@ -1687,11 +1657,11 @@
1657 db_open_repository(g.argv[2]);
1658 db_open_config(0);
1659 if( zTemplate ) db_attach(zTemplate, "settingSrc");
1660 db_begin_transaction();
1661 if( zDate==0 ) zDate = "now";
1662 db_initial_setup(zTemplate, zDate, zDefaultUser);
1663 db_end_transaction(0);
1664 if( zTemplate ) db_detach("settingSrc");
1665 fossil_print("project-id: %s\n", db_get("project-code", 0));
1666 fossil_print("server-id: %s\n", db_get("server-code", 0));
1667 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
@@ -2375,10 +2345,11 @@
2345 { "crnl-glob", 0, 40, 1, 0, "" },
2346 { "default-perms", 0, 16, 0, 0, "u" },
2347 { "diff-binary", 0, 0, 0, 0, "on" },
2348 { "diff-command", 0, 40, 0, 0, "" },
2349 { "dont-push", 0, 0, 0, 0, "off" },
2350 { "dotfiles", 0, 0, 0, 0, "off" },
2351 { "editor", 0, 32, 0, 0, "" },
2352 { "empty-dirs", 0, 40, 1, 0, "" },
2353 { "encoding-glob", 0, 40, 1, 0, "" },
2354 { "gdiff-command", 0, 40, 0, 0, "gdiff" },
2355 { "gmerge-command", 0, 40, 0, 0, "" },
@@ -2541,10 +2512,12 @@
2512 ** diff-command External command to run when performing a diff.
2513 ** If undefined, the internal text diff will be used.
2514 **
2515 ** dont-push Prevent this repository from pushing from client to
2516 ** server. Useful when setting up a private branch.
2517 **
2518 ** dotfiles Include --dotfiles option for all compatible commands.
2519 **
2520 ** editor Text editor command used for check-in comments.
2521 **
2522 ** empty-dirs A comma or newline-separated list of pathnames. On
2523 ** (versionable) update and checkout commands, if no file or directory
2524
+11 -38
--- src/db.c
+++ src/db.c
@@ -1475,42 +1475,10 @@
14751475
" VALUES('reader','','kptw','Reader');"
14761476
);
14771477
}
14781478
}
14791479
1480
-/*
1481
-** This function sets the server and project codes if they do not already
1482
-** exist. Currently, it should be called only by the db_initial_setup()
1483
-** or cmd_webserver() functions, the latter being used to facilitate more
1484
-** robust integration with "canned image" environments (e.g. Docker).
1485
-*/
1486
-void db_setup_server_and_project_codes(
1487
- int optional
1488
-){
1489
- if( !optional ){
1490
- db_multi_exec(
1491
- "INSERT INTO config(name,value,mtime)"
1492
- " VALUES('server-code', lower(hex(randomblob(20))),now());"
1493
- "INSERT INTO config(name,value,mtime)"
1494
- " VALUES('project-code', lower(hex(randomblob(20))),now());"
1495
- );
1496
- }else if( db_is_writeable("repository") ){
1497
- if( db_get("server-code", 0)==0 ) {
1498
- db_multi_exec(
1499
- "INSERT INTO config(name,value,mtime)"
1500
- " VALUES('server-code', lower(hex(randomblob(20))),now());"
1501
- );
1502
- }
1503
- if( db_get("project-code", 0)==0 ) {
1504
- db_multi_exec(
1505
- "INSERT INTO config(name,value,mtime)"
1506
- " VALUES('project-code', lower(hex(randomblob(20))),now());"
1507
- );
1508
- }
1509
- }
1510
-}
1511
-
15121480
/*
15131481
** Return a pointer to a string that contains the RHS of an IN operator
15141482
** that will select CONFIG table names that are in the list of control
15151483
** settings.
15161484
*/
@@ -1548,23 +1516,25 @@
15481516
** not server and project codes are invented for this repository.
15491517
*/
15501518
void db_initial_setup(
15511519
const char *zTemplate, /* Repository from which to copy settings. */
15521520
const char *zInitialDate, /* Initial date of repository. (ex: "now") */
1553
- const char *zDefaultUser, /* Default user for the repository */
1554
- int makeServerCodes /* True to make new server & project codes */
1521
+ const char *zDefaultUser /* Default user for the repository */
15551522
){
15561523
char *zDate;
15571524
Blob hash;
15581525
Blob manifest;
15591526
15601527
db_set("content-schema", CONTENT_SCHEMA, 0);
15611528
db_set("aux-schema", AUX_SCHEMA_MAX, 0);
15621529
db_set("rebuilt", get_version(), 0);
1563
- if( makeServerCodes ){
1564
- db_setup_server_and_project_codes(0);
1565
- }
1530
+ db_multi_exec(
1531
+ "INSERT INTO config(name,value,mtime)"
1532
+ " VALUES('server-code', lower(hex(randomblob(20))),now());"
1533
+ "INSERT INTO config(name,value,mtime)"
1534
+ " VALUES('project-code', lower(hex(randomblob(20))),now());"
1535
+ );
15661536
if( !db_is_global("autosync") ) db_set_int("autosync", 1, 0);
15671537
if( !db_is_global("localauth") ) db_set_int("localauth", 0, 0);
15681538
if( !db_is_global("timeline-plaintext") ){
15691539
db_set_int("timeline-plaintext", 1, 0);
15701540
}
@@ -1687,11 +1657,11 @@
16871657
db_open_repository(g.argv[2]);
16881658
db_open_config(0);
16891659
if( zTemplate ) db_attach(zTemplate, "settingSrc");
16901660
db_begin_transaction();
16911661
if( zDate==0 ) zDate = "now";
1692
- db_initial_setup(zTemplate, zDate, zDefaultUser, 1);
1662
+ db_initial_setup(zTemplate, zDate, zDefaultUser);
16931663
db_end_transaction(0);
16941664
if( zTemplate ) db_detach("settingSrc");
16951665
fossil_print("project-id: %s\n", db_get("project-code", 0));
16961666
fossil_print("server-id: %s\n", db_get("server-code", 0));
16971667
zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
@@ -2375,10 +2345,11 @@
23752345
{ "crnl-glob", 0, 40, 1, 0, "" },
23762346
{ "default-perms", 0, 16, 0, 0, "u" },
23772347
{ "diff-binary", 0, 0, 0, 0, "on" },
23782348
{ "diff-command", 0, 40, 0, 0, "" },
23792349
{ "dont-push", 0, 0, 0, 0, "off" },
2350
+ { "dotfiles", 0, 0, 0, 0, "off" },
23802351
{ "editor", 0, 32, 0, 0, "" },
23812352
{ "empty-dirs", 0, 40, 1, 0, "" },
23822353
{ "encoding-glob", 0, 40, 1, 0, "" },
23832354
{ "gdiff-command", 0, 40, 0, 0, "gdiff" },
23842355
{ "gmerge-command", 0, 40, 0, 0, "" },
@@ -2541,10 +2512,12 @@
25412512
** diff-command External command to run when performing a diff.
25422513
** If undefined, the internal text diff will be used.
25432514
**
25442515
** dont-push Prevent this repository from pushing from client to
25452516
** server. Useful when setting up a private branch.
2517
+**
2518
+** dotfiles Include --dotfiles option for all compatible commands.
25462519
**
25472520
** editor Text editor command used for check-in comments.
25482521
**
25492522
** empty-dirs A comma or newline-separated list of pathnames. On
25502523
** (versionable) update and checkout commands, if no file or directory
25512524
--- src/db.c
+++ src/db.c
@@ -1475,42 +1475,10 @@
1475 " VALUES('reader','','kptw','Reader');"
1476 );
1477 }
1478 }
1479
1480 /*
1481 ** This function sets the server and project codes if they do not already
1482 ** exist. Currently, it should be called only by the db_initial_setup()
1483 ** or cmd_webserver() functions, the latter being used to facilitate more
1484 ** robust integration with "canned image" environments (e.g. Docker).
1485 */
1486 void db_setup_server_and_project_codes(
1487 int optional
1488 ){
1489 if( !optional ){
1490 db_multi_exec(
1491 "INSERT INTO config(name,value,mtime)"
1492 " VALUES('server-code', lower(hex(randomblob(20))),now());"
1493 "INSERT INTO config(name,value,mtime)"
1494 " VALUES('project-code', lower(hex(randomblob(20))),now());"
1495 );
1496 }else if( db_is_writeable("repository") ){
1497 if( db_get("server-code", 0)==0 ) {
1498 db_multi_exec(
1499 "INSERT INTO config(name,value,mtime)"
1500 " VALUES('server-code', lower(hex(randomblob(20))),now());"
1501 );
1502 }
1503 if( db_get("project-code", 0)==0 ) {
1504 db_multi_exec(
1505 "INSERT INTO config(name,value,mtime)"
1506 " VALUES('project-code', lower(hex(randomblob(20))),now());"
1507 );
1508 }
1509 }
1510 }
1511
1512 /*
1513 ** Return a pointer to a string that contains the RHS of an IN operator
1514 ** that will select CONFIG table names that are in the list of control
1515 ** settings.
1516 */
@@ -1548,23 +1516,25 @@
1548 ** not server and project codes are invented for this repository.
1549 */
1550 void db_initial_setup(
1551 const char *zTemplate, /* Repository from which to copy settings. */
1552 const char *zInitialDate, /* Initial date of repository. (ex: "now") */
1553 const char *zDefaultUser, /* Default user for the repository */
1554 int makeServerCodes /* True to make new server & project codes */
1555 ){
1556 char *zDate;
1557 Blob hash;
1558 Blob manifest;
1559
1560 db_set("content-schema", CONTENT_SCHEMA, 0);
1561 db_set("aux-schema", AUX_SCHEMA_MAX, 0);
1562 db_set("rebuilt", get_version(), 0);
1563 if( makeServerCodes ){
1564 db_setup_server_and_project_codes(0);
1565 }
 
 
 
1566 if( !db_is_global("autosync") ) db_set_int("autosync", 1, 0);
1567 if( !db_is_global("localauth") ) db_set_int("localauth", 0, 0);
1568 if( !db_is_global("timeline-plaintext") ){
1569 db_set_int("timeline-plaintext", 1, 0);
1570 }
@@ -1687,11 +1657,11 @@
1687 db_open_repository(g.argv[2]);
1688 db_open_config(0);
1689 if( zTemplate ) db_attach(zTemplate, "settingSrc");
1690 db_begin_transaction();
1691 if( zDate==0 ) zDate = "now";
1692 db_initial_setup(zTemplate, zDate, zDefaultUser, 1);
1693 db_end_transaction(0);
1694 if( zTemplate ) db_detach("settingSrc");
1695 fossil_print("project-id: %s\n", db_get("project-code", 0));
1696 fossil_print("server-id: %s\n", db_get("server-code", 0));
1697 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
@@ -2375,10 +2345,11 @@
2375 { "crnl-glob", 0, 40, 1, 0, "" },
2376 { "default-perms", 0, 16, 0, 0, "u" },
2377 { "diff-binary", 0, 0, 0, 0, "on" },
2378 { "diff-command", 0, 40, 0, 0, "" },
2379 { "dont-push", 0, 0, 0, 0, "off" },
 
2380 { "editor", 0, 32, 0, 0, "" },
2381 { "empty-dirs", 0, 40, 1, 0, "" },
2382 { "encoding-glob", 0, 40, 1, 0, "" },
2383 { "gdiff-command", 0, 40, 0, 0, "gdiff" },
2384 { "gmerge-command", 0, 40, 0, 0, "" },
@@ -2541,10 +2512,12 @@
2541 ** diff-command External command to run when performing a diff.
2542 ** If undefined, the internal text diff will be used.
2543 **
2544 ** dont-push Prevent this repository from pushing from client to
2545 ** server. Useful when setting up a private branch.
 
 
2546 **
2547 ** editor Text editor command used for check-in comments.
2548 **
2549 ** empty-dirs A comma or newline-separated list of pathnames. On
2550 ** (versionable) update and checkout commands, if no file or directory
2551
--- src/db.c
+++ src/db.c
@@ -1475,42 +1475,10 @@
1475 " VALUES('reader','','kptw','Reader');"
1476 );
1477 }
1478 }
1479
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1480 /*
1481 ** Return a pointer to a string that contains the RHS of an IN operator
1482 ** that will select CONFIG table names that are in the list of control
1483 ** settings.
1484 */
@@ -1548,23 +1516,25 @@
1516 ** not server and project codes are invented for this repository.
1517 */
1518 void db_initial_setup(
1519 const char *zTemplate, /* Repository from which to copy settings. */
1520 const char *zInitialDate, /* Initial date of repository. (ex: "now") */
1521 const char *zDefaultUser /* Default user for the repository */
 
1522 ){
1523 char *zDate;
1524 Blob hash;
1525 Blob manifest;
1526
1527 db_set("content-schema", CONTENT_SCHEMA, 0);
1528 db_set("aux-schema", AUX_SCHEMA_MAX, 0);
1529 db_set("rebuilt", get_version(), 0);
1530 db_multi_exec(
1531 "INSERT INTO config(name,value,mtime)"
1532 " VALUES('server-code', lower(hex(randomblob(20))),now());"
1533 "INSERT INTO config(name,value,mtime)"
1534 " VALUES('project-code', lower(hex(randomblob(20))),now());"
1535 );
1536 if( !db_is_global("autosync") ) db_set_int("autosync", 1, 0);
1537 if( !db_is_global("localauth") ) db_set_int("localauth", 0, 0);
1538 if( !db_is_global("timeline-plaintext") ){
1539 db_set_int("timeline-plaintext", 1, 0);
1540 }
@@ -1687,11 +1657,11 @@
1657 db_open_repository(g.argv[2]);
1658 db_open_config(0);
1659 if( zTemplate ) db_attach(zTemplate, "settingSrc");
1660 db_begin_transaction();
1661 if( zDate==0 ) zDate = "now";
1662 db_initial_setup(zTemplate, zDate, zDefaultUser);
1663 db_end_transaction(0);
1664 if( zTemplate ) db_detach("settingSrc");
1665 fossil_print("project-id: %s\n", db_get("project-code", 0));
1666 fossil_print("server-id: %s\n", db_get("server-code", 0));
1667 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
@@ -2375,10 +2345,11 @@
2345 { "crnl-glob", 0, 40, 1, 0, "" },
2346 { "default-perms", 0, 16, 0, 0, "u" },
2347 { "diff-binary", 0, 0, 0, 0, "on" },
2348 { "diff-command", 0, 40, 0, 0, "" },
2349 { "dont-push", 0, 0, 0, 0, "off" },
2350 { "dotfiles", 0, 0, 0, 0, "off" },
2351 { "editor", 0, 32, 0, 0, "" },
2352 { "empty-dirs", 0, 40, 1, 0, "" },
2353 { "encoding-glob", 0, 40, 1, 0, "" },
2354 { "gdiff-command", 0, 40, 0, 0, "gdiff" },
2355 { "gmerge-command", 0, 40, 0, 0, "" },
@@ -2541,10 +2512,12 @@
2512 ** diff-command External command to run when performing a diff.
2513 ** If undefined, the internal text diff will be used.
2514 **
2515 ** dont-push Prevent this repository from pushing from client to
2516 ** server. Useful when setting up a private branch.
2517 **
2518 ** dotfiles Include --dotfiles option for all compatible commands.
2519 **
2520 ** editor Text editor command used for check-in comments.
2521 **
2522 ** empty-dirs A comma or newline-separated list of pathnames. On
2523 ** (versionable) update and checkout commands, if no file or directory
2524
+1 -1
--- src/doc.c
+++ src/doc.c
@@ -640,11 +640,11 @@
640640
if( blob_size(&title)==0 ) blob_append(&title,zName,-1);
641641
style_header("%s", blob_str(&title));
642642
blob_append(cgi_output_blob(), blob_buffer(&filebody),blob_size(&filebody));
643643
style_footer();
644644
#ifdef FOSSIL_ENABLE_TH1_DOCS
645
- }else if( db_get_boolean("th1-docs", 0) &&
645
+ }else if( Th_AreDocsEnabled() &&
646646
fossil_strcmp(zMime, "application/x-th1")==0 ){
647647
style_header("%h", zName);
648648
Th_Render(blob_str(&filebody));
649649
style_footer();
650650
#endif
651651
--- src/doc.c
+++ src/doc.c
@@ -640,11 +640,11 @@
640 if( blob_size(&title)==0 ) blob_append(&title,zName,-1);
641 style_header("%s", blob_str(&title));
642 blob_append(cgi_output_blob(), blob_buffer(&filebody),blob_size(&filebody));
643 style_footer();
644 #ifdef FOSSIL_ENABLE_TH1_DOCS
645 }else if( db_get_boolean("th1-docs", 0) &&
646 fossil_strcmp(zMime, "application/x-th1")==0 ){
647 style_header("%h", zName);
648 Th_Render(blob_str(&filebody));
649 style_footer();
650 #endif
651
--- src/doc.c
+++ src/doc.c
@@ -640,11 +640,11 @@
640 if( blob_size(&title)==0 ) blob_append(&title,zName,-1);
641 style_header("%s", blob_str(&title));
642 blob_append(cgi_output_blob(), blob_buffer(&filebody),blob_size(&filebody));
643 style_footer();
644 #ifdef FOSSIL_ENABLE_TH1_DOCS
645 }else if( Th_AreDocsEnabled() &&
646 fossil_strcmp(zMime, "application/x-th1")==0 ){
647 style_header("%h", zName);
648 Th_Render(blob_str(&filebody));
649 style_footer();
650 #endif
651
+847 -17
--- src/import.c
+++ src/import.c
@@ -12,12 +12,12 @@
1212
** Author contact information:
1313
** [email protected]
1414
**
1515
*******************************************************************************
1616
**
17
-** This file contains code used to import the content of a Git
18
-** repository in the git-fast-import format as a new Fossil
17
+** This file contains code used to import the content of a Git/SVN
18
+** repository in the git-fast-import/svn-dump formats as a new Fossil
1919
** repository.
2020
*/
2121
#include "config.h"
2222
#include "import.h"
2323
#include <assert.h>
@@ -516,12 +516,12 @@
516516
** last commit that holds that tag.
517517
**
518518
** None of the above is explained in the git-fast-export
519519
** documentation. We had to figure it out via trial and error.
520520
*/
521
- for(i=strlen(z)-1; i>=0 && z[i]!='/'; i--){}
522
- gg.tagCommit = strncmp(&z[i-4], "tags", 4)==0; /* True for pattern B */
521
+ for(i=5; i<strlen(z) && z[i]!='/'; i++){}
522
+ gg.tagCommit = strncmp(&z[5], "tags", 4)==0; /* True for pattern B */
523523
if( z[i+1]!=0 ) z += i+1;
524524
if( fossil_strcmp(z, "master")==0 ) z = "trunk";
525525
gg.zBranch = fossil_strdup(z);
526526
gg.fromLoaded = 0;
527527
}else
@@ -716,46 +716,822 @@
716716
malformed_line:
717717
trim_newline(zLine);
718718
fossil_fatal("bad fast-import line: [%s]", zLine);
719719
return;
720720
}
721
+
722
+static struct{
723
+ int rev; /* SVN revision number */
724
+ char *zDate; /* Date/time stamp */
725
+ char *zUser; /* User name */
726
+ char *zComment; /* Comment of a commit */
727
+ const char *zTrunk; /* Name of trunk folder in repo root */
728
+ int lenTrunk; /* String length of zTrunk */
729
+ const char *zBranches; /* Name of branches folder in repo root */
730
+ int lenBranches; /* String length of zBranches */
731
+ const char *zTags; /* Name of tags folder in repo root */
732
+ int lenTags; /* String length of zTags */
733
+ Bag newBranches; /* Branches that were created in this revision */
734
+ int incrFlag; /* Add svn-rev-nn tags on every checkin */
735
+} gsvn;
736
+typedef struct {
737
+ char *zKey;
738
+ char *zVal;
739
+} KeyVal;
740
+typedef struct {
741
+ KeyVal *aHeaders;
742
+ int nHeaders;
743
+ char *pRawProps;
744
+ KeyVal *aProps;
745
+ int nProps;
746
+ Blob content;
747
+ int contentFlag;
748
+} SvnRecord;
749
+
750
+#define svn_find_header(rec, zHeader) \
751
+ svn_find_keyval((rec).aHeaders, (rec).nHeaders, (zHeader))
752
+#define svn_find_prop(rec, zProp) \
753
+ svn_find_keyval((rec).aProps, (rec).nProps, (zProp))
754
+static char *svn_find_keyval(
755
+ KeyVal *aKeyVal,
756
+ int nKeyVal,
757
+ const char *zKey
758
+){
759
+ int i;
760
+ for(i=0; i<nKeyVal; i++){
761
+ if( fossil_strcmp(aKeyVal[i].zKey, zKey)==0 ){
762
+ return aKeyVal[i].zVal;
763
+ }
764
+ }
765
+ return 0;
766
+}
767
+
768
+static void svn_free_rec(SvnRecord *rec){
769
+ int i;
770
+ for(i=0; i<rec->nHeaders; i++){
771
+ fossil_free(rec->aHeaders[i].zKey);
772
+ }
773
+ fossil_free(rec->aHeaders);
774
+ fossil_free(rec->aProps);
775
+ fossil_free(rec->pRawProps);
776
+ blob_reset(&rec->content);
777
+}
778
+
779
+static int svn_read_headers(FILE *pIn, SvnRecord *rec){
780
+ char zLine[1000];
781
+
782
+ rec->aHeaders = 0;
783
+ rec->nHeaders = 0;
784
+ while( fgets(zLine, sizeof(zLine), pIn) ){
785
+ if( zLine[0]!='\n' ) break;
786
+ }
787
+ if( feof(pIn) ) return 0;
788
+ do{
789
+ char *sep;
790
+ if( zLine[0]=='\n' ) break;
791
+ rec->nHeaders += 1;
792
+ rec->aHeaders = fossil_realloc(rec->aHeaders,
793
+ sizeof(rec->aHeaders[0])*rec->nHeaders);
794
+ rec->aHeaders[rec->nHeaders-1].zKey = mprintf("%s", zLine);
795
+ sep = strchr(rec->aHeaders[rec->nHeaders-1].zKey, ':');
796
+ if( !sep ){
797
+ trim_newline(zLine);
798
+ fossil_fatal("bad header line: [%s]", zLine);
799
+ }
800
+ *sep = 0;
801
+ rec->aHeaders[rec->nHeaders-1].zVal = sep+1;
802
+ sep = strchr(rec->aHeaders[rec->nHeaders-1].zVal, '\n');
803
+ *sep = 0;
804
+ while(rec->aHeaders[rec->nHeaders-1].zVal
805
+ && fossil_isspace(*(rec->aHeaders[rec->nHeaders-1].zVal)) )
806
+ {
807
+ rec->aHeaders[rec->nHeaders-1].zVal++;
808
+ }
809
+ }while( fgets(zLine, sizeof(zLine), pIn) );
810
+ if( zLine[0]!='\n' ){
811
+ trim_newline(zLine);
812
+ fossil_fatal("svn-dump data ended unexpectedly");
813
+ }
814
+ return 1;
815
+}
816
+
817
+static void svn_read_props(FILE *pIn, SvnRecord *rec){
818
+ int nRawProps = 0;
819
+ char *pRawProps;
820
+ const char *zLen;
821
+
822
+ rec->pRawProps = 0;
823
+ rec->aProps = 0;
824
+ rec->nProps = 0;
825
+ zLen = svn_find_header(*rec, "Prop-content-length");
826
+ if( zLen ){
827
+ nRawProps = atoi(zLen);
828
+ }
829
+ if( nRawProps ){
830
+ int got;
831
+ char *zLine;
832
+ rec->pRawProps = pRawProps = fossil_malloc( nRawProps );
833
+ got = fread(rec->pRawProps, 1, nRawProps, pIn);
834
+ if( got!=nRawProps ){
835
+ fossil_fatal("short read: got %d of %d bytes", got, nRawProps);
836
+ }
837
+ if( memcmp(&pRawProps[got-10], "PROPS-END\n", 10)!=0 ){
838
+ fossil_fatal("svn-dump data ended unexpectedly");
839
+ }
840
+ zLine = pRawProps;
841
+ while( zLine<(pRawProps+nRawProps-10) ){
842
+ char *eol;
843
+ int propLen;
844
+ if( zLine[0]=='D' ){
845
+ propLen = atoi(&zLine[2]);
846
+ eol = strchr(zLine, '\n');
847
+ zLine = eol+1+propLen+1;
848
+ }else{
849
+ if( zLine[0]!='K' ){
850
+ fossil_fatal("svn-dump data format broken");
851
+ }
852
+ propLen = atoi(&zLine[2]);
853
+ eol = strchr(zLine, '\n');
854
+ zLine = eol+1;
855
+ eol = zLine+propLen;
856
+ if( *eol!='\n' ){
857
+ fossil_fatal("svn-dump data format broken");
858
+ }
859
+ *eol = 0;
860
+ rec->nProps += 1;
861
+ rec->aProps = fossil_realloc(rec->aProps,
862
+ sizeof(rec->aProps[0])*rec->nProps);
863
+ rec->aProps[rec->nProps-1].zKey = zLine;
864
+ zLine = eol+1;
865
+ if( zLine[0]!='V' ){
866
+ fossil_fatal("svn-dump data format broken");
867
+ }
868
+ propLen = atoi(&zLine[2]);
869
+ eol = strchr(zLine, '\n');
870
+ zLine = eol+1;
871
+ eol = zLine+propLen;
872
+ if( *eol!='\n' ){
873
+ fossil_fatal("svn-dump data format broken");
874
+ }
875
+ *eol = 0;
876
+ rec->aProps[rec->nProps-1].zVal = zLine;
877
+ zLine = eol+1;
878
+ }
879
+ }
880
+ }
881
+}
882
+
883
+static int svn_read_rec(FILE *pIn, SvnRecord *rec){
884
+ const char *zLen;
885
+ int nLen = 0;
886
+ if( svn_read_headers(pIn, rec)==0 ) return 0;
887
+ svn_read_props(pIn, rec);
888
+ blob_zero(&rec->content);
889
+ zLen = svn_find_header(*rec, "Text-content-length");
890
+ if( zLen ){
891
+ rec->contentFlag = 1;
892
+ nLen = atoi(zLen);
893
+ blob_read_from_channel(&rec->content, pIn, nLen);
894
+ if( blob_size(&rec->content)!=nLen ){
895
+ fossil_fatal("short read: got %d of %d bytes",
896
+ blob_size(&rec->content), nLen
897
+ );
898
+ }
899
+ }else{
900
+ rec->contentFlag = 0;
901
+ }
902
+ return 1;
903
+}
904
+
905
+/*
906
+** Returns the UUID for the RID, or NULL if not found.
907
+** The returned string is allocated via db_text() and must be
908
+** free()d by the caller.
909
+*/
910
+char * rid_to_uuid(int rid)
911
+{
912
+ return db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
913
+}
914
+
915
+#define SVN_UNKNOWN 0
916
+#define SVN_TRUNK 1
917
+#define SVN_BRANCH 2
918
+#define SVN_TAG 3
919
+
920
+#define MAX_INT_32 (0x7FFFFFFFL)
921
+
922
+static void svn_finish_revision(){
923
+ Blob manifest;
924
+ static Stmt getChanges;
925
+ static Stmt getFiles;
926
+ static Stmt setRid;
927
+ Blob mcksum;
928
+
929
+ blob_zero(&manifest);
930
+ db_static_prepare(&getChanges, "SELECT tid, tname, ttype, tparent"
931
+ " FROM xrevisions, xbranches ON (tbranch=tid)"
932
+ " WHERE trid ISNULL");
933
+ db_static_prepare(&getFiles, "SELECT tpath, tuuid, tperm FROM xfiles"
934
+ " WHERE tbranch=:branch ORDER BY tpath");
935
+ db_prepare(&setRid, "UPDATE xrevisions SET trid=:rid"
936
+ " WHERE trev=%d AND tbranch=:branch", gsvn.rev);
937
+ while( db_step(&getChanges)==SQLITE_ROW ){
938
+ int branchId = db_column_int(&getChanges, 0);
939
+ const char *zBranch = db_column_text(&getChanges, 1);
940
+ int branchType = db_column_int(&getChanges, 2);
941
+ int parentRid = db_column_int(&getChanges, 3);
942
+ int mergeRid = parentRid;
943
+ Manifest *pParentManifest = 0;
944
+ ManifestFile *pParentFile = 0;
945
+ int sameAsParent = 1;
946
+ int parentBranch = 0;
947
+ if( !bag_find(&gsvn.newBranches, branchId) ){
948
+ parentRid = db_int(0, "SELECT trid, max(trev) FROM xrevisions"
949
+ " WHERE trev<%d AND tbranch=%d",
950
+ gsvn.rev, branchId);
951
+ }
952
+ if( parentRid>0 ){
953
+ pParentManifest = manifest_get(parentRid, CFTYPE_MANIFEST, 0);
954
+ pParentFile = manifest_file_next(pParentManifest, 0);
955
+ parentBranch = db_int(0, "SELECT tbranch FROM xrevisions WHERE trid=%d",
956
+ parentRid);
957
+ if( parentBranch!=branchId && branchType!=SVN_TAG ){
958
+ sameAsParent = 0;
959
+ }
960
+ }
961
+ if( mergeRid<MAX_INT_32 ){
962
+ if( gsvn.zComment ){
963
+ blob_appendf(&manifest, "C %F\n", gsvn.zComment);
964
+ }else{
965
+ blob_append(&manifest, "C (no\\scomment)\n", 16);
966
+ }
967
+ blob_appendf(&manifest, "D %s\n", gsvn.zDate);
968
+ db_bind_int(&getFiles, ":branch", branchId);
969
+ while( db_step(&getFiles)==SQLITE_ROW ){
970
+ const char *zFile = db_column_text(&getFiles, 0);
971
+ const char *zUuid = db_column_text(&getFiles, 1);
972
+ const char *zPerm = db_column_text(&getFiles, 2);
973
+ if( zPerm ){
974
+ blob_appendf(&manifest, "F %F %s %s\n", zFile, zUuid, zPerm);
975
+ }else{
976
+ blob_appendf(&manifest, "F %F %s\n", zFile, zUuid);
977
+ }
978
+ if( sameAsParent ){
979
+ if( !pParentFile
980
+ || fossil_strcmp(pParentFile->zName,zFile)!=0
981
+ || fossil_strcmp(pParentFile->zUuid,zUuid)!=0
982
+ || fossil_strcmp(pParentFile->zPerm,zPerm)!=0
983
+ ){
984
+ sameAsParent = 0;
985
+ }else{
986
+ pParentFile = manifest_file_next(pParentManifest, 0);
987
+ }
988
+ }
989
+ }
990
+ if( pParentFile ){
991
+ sameAsParent = 0;
992
+ }
993
+ db_reset(&getFiles);
994
+ if( !sameAsParent ){
995
+ if( parentRid>0 ){
996
+ char *zParentUuid = rid_to_uuid(parentRid);
997
+ if( parentRid==mergeRid || mergeRid==0){
998
+ char *zParentBranch =
999
+ db_text(0, "SELECT tname FROM xbranches WHERE tid=%d",
1000
+ parentBranch
1001
+ );
1002
+ blob_appendf(&manifest, "P %s\n", zParentUuid);
1003
+ blob_appendf(&manifest, "T *branch * %F\n", zBranch);
1004
+ blob_appendf(&manifest, "T *sym-%F *\n", zBranch);
1005
+ if( gsvn.incrFlag ){
1006
+ blob_appendf(&manifest, "T +sym-svn-rev-%d *\n", gsvn.rev);
1007
+ }
1008
+ blob_appendf(&manifest, "T -sym-%F *\n", zParentBranch);
1009
+ fossil_free(zParentBranch);
1010
+ }else{
1011
+ char *zMergeUuid = rid_to_uuid(mergeRid);
1012
+ blob_appendf(&manifest, "P %s %s\n", zParentUuid, zMergeUuid);
1013
+ if( gsvn.incrFlag ){
1014
+ blob_appendf(&manifest, "T +sym-svn-rev-%d *\n", gsvn.rev);
1015
+ }
1016
+ fossil_free(zMergeUuid);
1017
+ }
1018
+ fossil_free(zParentUuid);
1019
+ }else{
1020
+ blob_appendf(&manifest, "T *branch * %F\n", zBranch);
1021
+ blob_appendf(&manifest, "T *sym-%F *\n", zBranch);
1022
+ if( gsvn.incrFlag ){
1023
+ blob_appendf(&manifest, "T +sym-svn-rev-%d *\n", gsvn.rev);
1024
+ }
1025
+ }
1026
+ }else if( branchType==SVN_TAG ){
1027
+ char *zParentUuid = rid_to_uuid(parentRid);
1028
+ blob_reset(&manifest);
1029
+ blob_appendf(&manifest, "D %s\n", gsvn.zDate);
1030
+ blob_appendf(&manifest, "T +sym-%F %s\n", zBranch, zParentUuid);
1031
+ fossil_free(zParentUuid);
1032
+ }
1033
+ }else{
1034
+ char *zParentUuid = rid_to_uuid(parentRid);
1035
+ blob_appendf(&manifest, "D %s\n", gsvn.zDate);
1036
+ if( branchType!=SVN_TAG ){
1037
+ blob_appendf(&manifest, "T +closed %s\n", zParentUuid);
1038
+ }else{
1039
+ blob_appendf(&manifest, "T -sym-%F %s\n", zBranch, zParentUuid);
1040
+ }
1041
+ fossil_free(zParentUuid);
1042
+ }
1043
+ if( gsvn.zUser ){
1044
+ blob_appendf(&manifest, "U %F\n", gsvn.zUser);
1045
+ }else{
1046
+ const char *zUserOvrd = find_option("user-override",0,1);
1047
+ blob_appendf(&manifest, "U %F\n", zUserOvrd ? zUserOvrd : login_name());
1048
+ }
1049
+ md5sum_blob(&manifest, &mcksum);
1050
+ blob_appendf(&manifest, "Z %b\n", &mcksum);
1051
+ blob_reset(&mcksum);
1052
+ if( !sameAsParent ){
1053
+ int rid = content_put(&manifest);
1054
+ db_bind_int(&setRid, ":branch", branchId);
1055
+ db_bind_int(&setRid, ":rid", rid);
1056
+ db_step(&setRid);
1057
+ db_reset(&setRid);
1058
+ }else if( branchType==SVN_TAG ){
1059
+ content_put(&manifest);
1060
+ db_bind_int(&setRid, ":branch", branchId);
1061
+ db_bind_int(&setRid, ":rid", parentRid);
1062
+ db_step(&setRid);
1063
+ db_reset(&setRid);
1064
+ }else if( mergeRid==MAX_INT_32 ){
1065
+ content_put(&manifest);
1066
+ db_multi_exec("DELETE FROM xrevisions WHERE tbranch=%d AND trev=%d",
1067
+ branchId, gsvn.rev);
1068
+ }else{
1069
+ db_multi_exec("DELETE FROM xrevisions WHERE tbranch=%d AND trev=%d",
1070
+ branchId, gsvn.rev);
1071
+ }
1072
+ blob_reset(&manifest);
1073
+ manifest_destroy(pParentManifest);
1074
+ }
1075
+ db_reset(&getChanges);
1076
+ db_finalize(&setRid);
1077
+}
1078
+
1079
+static u64 svn_get_varint(const char **pz){
1080
+ unsigned int v = 0;
1081
+ do{
1082
+ v = (v<<7) | ((*pz)[0]&0x7f);
1083
+ }while( (*pz)++[0]&0x80 );
1084
+ return v;
1085
+}
1086
+
1087
+static void svn_apply_svndiff(Blob *pDiff, Blob *pSrc, Blob *pOut){
1088
+ const char *zDiff = blob_buffer(pDiff);
1089
+ char *zOut;
1090
+ if( blob_size(pDiff)<4 || memcmp(zDiff, "SVN", 4)!=0 ){
1091
+ fossil_fatal("Invalid svndiff0 format");
1092
+ }
1093
+ zDiff += 4;
1094
+ blob_zero(pOut);
1095
+ while( zDiff<(blob_buffer(pDiff)+blob_size(pDiff)) ){
1096
+ u64 lenOut, lenInst, lenData, lenOld;
1097
+ const char *zInst;
1098
+ const char *zData;
1099
+
1100
+ u64 offSrc = svn_get_varint(&zDiff);
1101
+ /*lenSrc =*/ svn_get_varint(&zDiff);
1102
+ lenOut = svn_get_varint(&zDiff);
1103
+ lenInst = svn_get_varint(&zDiff);
1104
+ lenData = svn_get_varint(&zDiff);
1105
+ zInst = zDiff;
1106
+ zData = zInst+lenInst;
1107
+ lenOld = blob_size(pOut);
1108
+ blob_resize(pOut, lenOut+lenOld);
1109
+ zOut = blob_buffer(pOut)+lenOld;
1110
+ while( zDiff<zInst+lenInst ){
1111
+ u64 lenCpy = (*zDiff)&0x3f;
1112
+ const char *zCpy;
1113
+ switch( (*zDiff)&0xC0 ){
1114
+ case 0x00: zCpy = blob_buffer(pSrc)+offSrc; break;
1115
+ case 0x40: zCpy = blob_buffer(pOut); break;
1116
+ case 0x80: zCpy = zData; break;
1117
+ default: fossil_fatal("Invalid svndiff0 instruction");
1118
+ }
1119
+ zDiff++;
1120
+ if( lenCpy==0 ){
1121
+ lenCpy = svn_get_varint(&zDiff);
1122
+ }
1123
+ if( zCpy!=zData ){
1124
+ zCpy += svn_get_varint(&zDiff);
1125
+ }else{
1126
+ zData += lenCpy;
1127
+ }
1128
+ while( lenCpy-- > 0 ){
1129
+ *zOut++ = *zCpy++;
1130
+ }
1131
+ }
1132
+ zDiff += lenData;
1133
+ }
1134
+}
1135
+
1136
+/*
1137
+** Extract the branch or tag that the given path is on. Return the branch ID.
1138
+ */
1139
+static int svn_parse_path(char *zPath, char **zFile, int *type){
1140
+ char *zBranch = 0;
1141
+ int branchId = 0;
1142
+ *type = SVN_UNKNOWN;
1143
+ *zFile = 0;
1144
+ if( gsvn.lenTrunk==0 ){
1145
+ zBranch = "trunk";
1146
+ *zFile = zPath;
1147
+ *type = SVN_TRUNK;
1148
+ }else
1149
+ if( strncmp(zPath, gsvn.zTrunk, gsvn.lenTrunk-1)==0 ){
1150
+ if( zPath[gsvn.lenTrunk-1]=='/' || zPath[gsvn.lenTrunk-1]==0 ){
1151
+ zBranch = "trunk";
1152
+ *zFile = zPath+gsvn.lenTrunk;
1153
+ *type = SVN_TRUNK;
1154
+ }else{
1155
+ zBranch = 0;
1156
+ *type = SVN_UNKNOWN;
1157
+ }
1158
+ }else{
1159
+ if( strncmp(zPath, gsvn.zBranches, gsvn.lenBranches)==0 ){
1160
+ *zFile = zBranch = zPath+gsvn.lenBranches;
1161
+ *type = SVN_BRANCH;
1162
+ }else
1163
+ if( strncmp(zPath, gsvn.zTags, gsvn.lenTags)==0 ){
1164
+ *zFile = zBranch = zPath+gsvn.lenTags;
1165
+ *type = SVN_TAG;
1166
+ }else{ /* Not a branch, tag or trunk */
1167
+ return 0;
1168
+ }
1169
+ while( **zFile && **zFile!='/' ){ (*zFile)++; }
1170
+ if( **zFile ){
1171
+ **zFile = '\0';
1172
+ (*zFile)++;
1173
+ }
1174
+ }
1175
+ if( *type!=SVN_UNKNOWN ){
1176
+ branchId = db_int(0,
1177
+ "SELECT tid FROM xbranches WHERE tname=%Q AND ttype=%d",
1178
+ zBranch, *type);
1179
+ if( branchId==0 ){
1180
+ db_multi_exec("INSERT INTO xbranches (tname, ttype) VALUES(%Q, %d)",
1181
+ zBranch, *type);
1182
+ branchId = db_last_insert_rowid();
1183
+ }
1184
+ }
1185
+ return branchId;
1186
+}
1187
+
1188
+/*
1189
+** Read the svn-dump format from pIn and insert the corresponding
1190
+** content into the database.
1191
+*/
1192
+static void svn_dump_import(FILE *pIn){
1193
+ SvnRecord rec;
1194
+ int ver;
1195
+ char *zTemp;
1196
+ const char *zUuid;
1197
+ Stmt addFile;
1198
+ Stmt delPath;
1199
+ Stmt addRev;
1200
+ Stmt cpyPath;
1201
+ Stmt cpyRoot;
1202
+ Stmt revSrc;
1203
+
1204
+ /* version */
1205
+ if( svn_read_rec(pIn, &rec)
1206
+ && (zTemp = svn_find_header(rec, "SVN-fs-dump-format-version")) ){
1207
+ ver = atoi(zTemp);
1208
+ if( ver!=2 && ver!=3 ){
1209
+ fossil_fatal("Unknown svn-dump format version: %d", ver);
1210
+ }
1211
+ }else{
1212
+ fossil_fatal("Input is not an svn-dump!");
1213
+ }
1214
+ svn_free_rec(&rec);
1215
+ /* UUID */
1216
+ if( !svn_read_rec(pIn, &rec) || !(zUuid = svn_find_header(rec, "UUID")) ){
1217
+ /* Removed the following line since UUID is not actually used
1218
+ fossil_fatal("Missing UUID!"); */
1219
+ }
1220
+ svn_free_rec(&rec);
1221
+
1222
+ /* content */
1223
+ db_prepare(&addFile,
1224
+ "INSERT INTO xfiles (tpath, tbranch, tuuid, tperm)"
1225
+ " VALUES(:path, :branch, (SELECT uuid FROM blob WHERE rid=:rid), :perm)"
1226
+ );
1227
+ db_prepare(&delPath,
1228
+ "DELETE FROM xfiles"
1229
+ " WHERE (tpath=:path OR (tpath>:path||'/' AND tpath<:path||'0'))"
1230
+ " AND tbranch=:branch"
1231
+ );
1232
+ db_prepare(&addRev,
1233
+ "INSERT OR IGNORE INTO xrevisions (trev, tbranch) VALUES(:rev, :branch)"
1234
+ );
1235
+ db_prepare(&cpyPath,
1236
+ "INSERT INTO xfiles (tpath, tbranch, tuuid, tperm)"
1237
+ " SELECT :path||:sep||substr(filename, length(:srcpath)+2), :branch, uuid, perm"
1238
+ " FROM xfoci"
1239
+ " WHERE checkinID=:rid"
1240
+ " AND filename>:srcpath||'/'"
1241
+ " AND filename<:srcpath||'0'"
1242
+ );
1243
+ db_prepare(&cpyRoot,
1244
+ "INSERT INTO xfiles (tpath, tbranch, tuuid, tperm)"
1245
+ " SELECT :path||:sep||filename, :branch, uuid, perm"
1246
+ " FROM xfoci"
1247
+ " WHERE checkinID=:rid"
1248
+ );
1249
+ db_prepare(&revSrc,
1250
+ "UPDATE xrevisions SET tparent=:parent"
1251
+ " WHERE trev=:rev AND tbranch=:branch AND tparent<:parent"
1252
+ );
1253
+ gsvn.rev = -1;
1254
+ bag_init(&gsvn.newBranches);
1255
+ while( svn_read_rec(pIn, &rec) ){
1256
+ if( (zTemp = svn_find_header(rec, "Revision-number")) ){ /* revision node */
1257
+ /* finish previous revision */
1258
+ char *zDate = NULL;
1259
+ if( gsvn.rev>=0 ){
1260
+ svn_finish_revision();
1261
+ fossil_free(gsvn.zUser);
1262
+ fossil_free(gsvn.zComment);
1263
+ fossil_free(gsvn.zDate);
1264
+ bag_clear(&gsvn.newBranches);
1265
+ }
1266
+ /* start new revision */
1267
+ gsvn.rev = atoi(zTemp);
1268
+ gsvn.zUser = mprintf("%s", svn_find_prop(rec, "svn:author"));
1269
+ gsvn.zComment = mprintf("%s", svn_find_prop(rec, "svn:log"));
1270
+ zDate = svn_find_prop(rec, "svn:date");
1271
+ if( zDate ){
1272
+ gsvn.zDate = date_in_standard_format(zDate);
1273
+ }else{
1274
+ gsvn.zDate = date_in_standard_format("now");
1275
+ }
1276
+ db_bind_int(&addRev, ":rev", gsvn.rev);
1277
+ fossil_print("\rImporting SVN revision: %d", gsvn.rev);
1278
+ }else
1279
+ if( (zTemp = svn_find_header(rec, "Node-path")) ){ /* file/dir node */
1280
+ char *zFile;
1281
+ int branchType;
1282
+ int branchId = svn_parse_path(zTemp, &zFile, &branchType);
1283
+ char *zAction = svn_find_header(rec, "Node-action");
1284
+ char *zKind = svn_find_header(rec, "Node-kind");
1285
+ char *zPerm = svn_find_prop(rec, "svn:executable") ? "x" : 0;
1286
+ int deltaFlag = 0;
1287
+ int srcRev = 0;
1288
+ if( branchId==0 ){
1289
+ svn_free_rec(&rec);
1290
+ continue;
1291
+ }
1292
+ if( (zTemp = svn_find_header(rec, "Text-delta")) ){
1293
+ deltaFlag = strncmp(zTemp, "true", 4)==0;
1294
+ }
1295
+ if( strncmp(zAction, "delete", 6)==0
1296
+ || strncmp(zAction, "replace", 7)==0 )
1297
+ {
1298
+ db_bind_int(&addRev, ":branch", branchId);
1299
+ db_step(&addRev);
1300
+ db_reset(&addRev);
1301
+ if( zFile[0]!=0 ){
1302
+ db_bind_text(&delPath, ":path", zFile);
1303
+ db_bind_int(&delPath, ":branch", branchId);
1304
+ db_step(&delPath);
1305
+ db_reset(&delPath);
1306
+ }else{
1307
+ db_multi_exec("DELETE FROM xfiles WHERE tbranch=%d", branchId);
1308
+ db_bind_int(&revSrc, ":parent", MAX_INT_32);
1309
+ db_bind_int(&revSrc, ":rev", gsvn.rev);
1310
+ db_bind_int(&revSrc, ":branch", branchId);
1311
+ db_step(&revSrc);
1312
+ db_reset(&revSrc);
1313
+ }
1314
+ } /* no 'else' here since 'replace' does both a 'delete' and an 'add' */
1315
+ if( strncmp(zAction, "add", 3)==0
1316
+ || strncmp(zAction, "replace", 7)==0 )
1317
+ {
1318
+ char *zSrcPath = svn_find_header(rec, "Node-copyfrom-path");
1319
+ char *zSrcFile;
1320
+ int srcRid = 0;
1321
+ if( zSrcPath ){
1322
+ int srcBranch;
1323
+ zTemp = svn_find_header(rec, "Node-copyfrom-rev");
1324
+ if( zTemp ){
1325
+ srcRev = atoi(zTemp);
1326
+ }else{
1327
+ fossil_fatal("Missing copyfrom-rev");
1328
+ }
1329
+ srcBranch = svn_parse_path(zSrcPath, &zSrcFile, &branchType);
1330
+ if( srcBranch==0 ){
1331
+ fossil_fatal("Copy from path outside the import paths");
1332
+ }
1333
+ srcRid = db_int(0, "SELECT trid, max(trev) FROM xrevisions"
1334
+ " WHERE trev<=%d AND tbranch=%d",
1335
+ srcRev, srcBranch);
1336
+ if( srcRid>0 && srcBranch!=branchId ){
1337
+ db_bind_int(&addRev, ":branch", branchId);
1338
+ db_step(&addRev);
1339
+ db_reset(&addRev);
1340
+ db_bind_int(&revSrc, ":parent", srcRid);
1341
+ db_bind_int(&revSrc, ":rev", gsvn.rev);
1342
+ db_bind_int(&revSrc, ":branch", branchId);
1343
+ db_step(&revSrc);
1344
+ db_reset(&revSrc);
1345
+ }
1346
+ }
1347
+ if( zKind==0 ){
1348
+ fossil_fatal("Missing Node-kind");
1349
+ }else if( strncmp(zKind, "dir", 3)==0 ){
1350
+ if( zSrcPath ){
1351
+ if( srcRid>0 ){
1352
+ if( zSrcFile[0]==0 ){
1353
+ db_bind_text(&cpyRoot, ":path", zFile);
1354
+ if( zFile[0]!=0 ){
1355
+ db_bind_text(&cpyRoot, ":sep", "/");
1356
+ }else{
1357
+ db_bind_text(&cpyRoot, ":sep", "");
1358
+ }
1359
+ db_bind_int(&cpyRoot, ":branch", branchId);
1360
+ db_bind_int(&cpyRoot, ":rid", srcRid);
1361
+ db_step(&cpyRoot);
1362
+ db_reset(&cpyRoot);
1363
+ }else{
1364
+ db_bind_text(&cpyPath, ":path", zFile);
1365
+ if( zFile[0]!=0 ){
1366
+ db_bind_text(&cpyPath, ":sep", "/");
1367
+ }else{
1368
+ db_bind_text(&cpyPath, ":sep", "");
1369
+ }
1370
+ db_bind_int(&cpyPath, ":branch", branchId);
1371
+ db_bind_text(&cpyPath, ":srcpath", zSrcFile);
1372
+ db_bind_int(&cpyPath, ":rid", srcRid);
1373
+ db_step(&cpyPath);
1374
+ db_reset(&cpyPath);
1375
+ }
1376
+ }
1377
+ }
1378
+ if( zFile[0]==0 ){
1379
+ bag_insert(&gsvn.newBranches, branchId);
1380
+ }
1381
+ }else{
1382
+ int rid = 0;
1383
+ if( zSrcPath ){
1384
+ rid = db_int(0, "SELECT rid FROM blob WHERE uuid=("
1385
+ " SELECT uuid FROM xfoci"
1386
+ " WHERE checkinID=%d AND filename=%Q"
1387
+ ")",
1388
+ srcRid, zSrcFile);
1389
+ }
1390
+ if( deltaFlag ){
1391
+ Blob deltaSrc;
1392
+ Blob target;
1393
+ if( rid!=0 ){
1394
+ content_get(rid, &deltaSrc);
1395
+ }else{
1396
+ blob_zero(&deltaSrc);
1397
+ }
1398
+ svn_apply_svndiff(&rec.content, &deltaSrc, &target);
1399
+ rid = content_put(&target);
1400
+ }else if( rec.contentFlag ){
1401
+ rid = content_put(&rec.content);
1402
+ }
1403
+ db_bind_text(&addFile, ":path", zFile);
1404
+ db_bind_int(&addFile, ":branch", branchId);
1405
+ db_bind_int(&addFile, ":rid", rid);
1406
+ db_bind_text(&addFile, ":perm", zPerm);
1407
+ db_step(&addFile);
1408
+ db_reset(&addFile);
1409
+ db_bind_int(&addRev, ":branch", branchId);
1410
+ db_step(&addRev);
1411
+ db_reset(&addRev);
1412
+ }
1413
+ }else
1414
+ if( strncmp(zAction, "change", 6)==0 ){
1415
+ int rid = 0;
1416
+ if( zKind==0 ){
1417
+ fossil_fatal("Missing Node-kind");
1418
+ }
1419
+ if( strncmp(zKind, "dir", 3)!=0 ){
1420
+ if( deltaFlag ){
1421
+ Blob deltaSrc;
1422
+ Blob target;
1423
+ rid = db_int(0, "SELECT rid FROM blob WHERE uuid=("
1424
+ " SELECT uuid FROM xfiles"
1425
+ " WHERE tpath=%Q AND tbranch=%d"
1426
+ ")", zFile, branchId);
1427
+ content_get(rid, &deltaSrc);
1428
+ svn_apply_svndiff(&rec.content, &deltaSrc, &target);
1429
+ rid = content_put(&target);
1430
+ }else{
1431
+ rid = content_put(&rec.content);
1432
+ }
1433
+ db_bind_text(&addFile, ":path", zFile);
1434
+ db_bind_int(&addFile, ":branch", branchId);
1435
+ db_bind_int(&addFile, ":rid", rid);
1436
+ db_bind_text(&addFile, ":perm", zPerm);
1437
+ db_step(&addFile);
1438
+ db_reset(&addFile);
1439
+ db_bind_int(&addRev, ":branch", branchId);
1440
+ db_step(&addRev);
1441
+ db_reset(&addRev);
1442
+ }
1443
+ }else
1444
+ if( strncmp(zAction, "delete", 6)!=0 ){ /* already did this one above */
1445
+ fossil_fatal("Unknown Node-action");
1446
+ }
1447
+ }else{
1448
+ fossil_fatal("Unknown record type");
1449
+ }
1450
+ svn_free_rec(&rec);
1451
+ }
1452
+ svn_finish_revision();
1453
+ fossil_free(gsvn.zUser);
1454
+ fossil_free(gsvn.zComment);
1455
+ fossil_free(gsvn.zDate);
1456
+ db_finalize(&addFile);
1457
+ db_finalize(&delPath);
1458
+ db_finalize(&addRev);
1459
+ db_finalize(&cpyPath);
1460
+ db_finalize(&cpyRoot);
1461
+ db_finalize(&revSrc);
1462
+ fossil_print(" Done!\n");
1463
+}
7211464
7221465
/*
7231466
** COMMAND: import
7241467
**
725
-** Usage: %fossil import ?OPTIONS? NEW-REPOSITORY ?INPUT-FILE?
1468
+** Usage: %fossil import ?--git? ?OPTIONS? NEW-REPOSITORY ?INPUT-FILE?
1469
+** or: %fossil import --svn ?OPTIONS? NEW-REPOSITORY ?INPUT-FILE?
7261470
**
7271471
** Read interchange format generated by another VCS and use it to
7281472
** construct a new Fossil repository named by the NEW-REPOSITORY
7291473
** argument. If no input file is supplied the interchange format
7301474
** data is read from standard input.
7311475
**
732
-** The git-fast-export file format is currently the only VCS interchange
733
-** format that is understood, though other interchange formats may be added
734
-** in the future.
1476
+** The following formats are currently understood by this command
1477
+**
1478
+** --git Import from the git-fast-export file format (default)
1479
+**
1480
+** --svn Import from the svnadmin-dump file format. The default
1481
+** behaviour (unless overridden by --flat) is to treat 3
1482
+** folders in the SVN root as special, following the
1483
+** common layout of SVN repositories. These are (by
1484
+** default) trunk/, branches/ and tags/
1485
+** Options:
1486
+** --trunk FOLDER Name of trunk folder
1487
+** --branches FOLDER Name of branches folder
1488
+** --tags FOLDER Name of tags folder
1489
+** --base PATH Path to project root in repository
1490
+** --flat The whole dump is a single branch
1491
+**
1492
+** Common Options:
1493
+** -i|--incremental allow importing into an existing repository
1494
+** -f|--force overwrite repository if already exist
7351495
**
7361496
** The --incremental option allows an existing repository to be extended
7371497
** with new content.
7381498
**
739
-** Options:
740
-** --git import from the git-fast-export file format (default)
741
-** --incremental allow importing into an existing repository
7421499
**
7431500
** See also: export
7441501
*/
7451502
void import_cmd(void){
7461503
char *zPassword;
7471504
FILE *pIn;
7481505
Stmt q;
7491506
int forceFlag = find_option("force", "f", 0)!=0;
750
- int incrFlag = find_option("incremental", "i", 0)!=0;
7511507
int svnFlag = find_option("svn", 0, 0)!=0;
7521508
753
- find_option("git",0,0); /* Skip the --git option for now */
1509
+ /* Options common to all input formats */
1510
+ int incrFlag = find_option("incremental", "i", 0)!=0;
1511
+
1512
+ /* Options for --svn only */
1513
+ const char *zBase="";
1514
+ int flatFlag=0;
1515
+
1516
+ if( svnFlag ){
1517
+ /* Get --svn related options here, so verify_all_options() fail when svn
1518
+ * only option are specify with --git
1519
+ */
1520
+ zBase = find_option("base", 0, 1);
1521
+ flatFlag = find_option("flat", 0, 0)!=0;
1522
+ gsvn.zTrunk = find_option("trunk", 0, 1);
1523
+ gsvn.zBranches = find_option("branches", 0, 1);
1524
+ gsvn.zTags = find_option("tags", 0, 1);
1525
+ gsvn.incrFlag = incrFlag;
1526
+ }else{
1527
+ find_option("git",0,0); /* Skip the --git option for now */
1528
+ }
7541529
verify_all_options();
755
- if( g.argc!=3 && g.argc!=4 ){
756
- usage("NEW-REPOSITORY ?INPUT-FILE?");
1530
+
1531
+ if( g.argc!=3 && g.argc!=4 ){
1532
+ usage("--git|--svn ?OPTIONS? NEW-REPOSITORY ?INPUT-FILE?");
7571533
}
7581534
if( g.argc==4 ){
7591535
pIn = fossil_fopen(g.argv[3], "rb");
7601536
}else{
7611537
pIn = stdin;
@@ -767,14 +1543,66 @@
7671543
}
7681544
db_open_repository(g.argv[2]);
7691545
db_open_config(0);
7701546
7711547
db_begin_transaction();
772
- if( !incrFlag ) db_initial_setup(0, 0, 0, 1);
1548
+ if( !incrFlag ) db_initial_setup(0, 0, 0);
7731549
7741550
if( svnFlag ){
775
- fossil_fatal("--svn format not implemented yet");
1551
+ db_multi_exec(
1552
+ "CREATE TEMP TABLE xrevisions("
1553
+ " trev INTEGER, tbranch INT, trid INT, tparent INT DEFAULT 0,"
1554
+ " UNIQUE(tbranch, trev)"
1555
+ ");"
1556
+ "CREATE INDEX temp.i_xrevisions ON xrevisions(trid);"
1557
+ "CREATE TEMP TABLE xfiles("
1558
+ " tpath TEXT, tbranch INT, tuuid TEXT, tperm TEXT,"
1559
+ " UNIQUE (tbranch, tpath) ON CONFLICT REPLACE"
1560
+ ");"
1561
+ "CREATE TEMP TABLE xbranches("
1562
+ " tid INTEGER PRIMARY KEY, tname TEXT, ttype INT,"
1563
+ " UNIQUE(tname, ttype)"
1564
+ ");"
1565
+ "CREATE VIRTUAL TABLE temp.xfoci USING files_of_checkin;"
1566
+ );
1567
+ if( zBase==0 ){ zBase = ""; }
1568
+ if( strlen(zBase)>0 ){
1569
+ if( zBase[strlen(zBase)-1]!='/' ){
1570
+ zBase = mprintf("%s/", zBase);
1571
+ }
1572
+ }
1573
+ if( flatFlag ){
1574
+ gsvn.zTrunk = zBase;
1575
+ gsvn.zBranches = 0;
1576
+ gsvn.zTags = 0;
1577
+ gsvn.lenTrunk = strlen(zBase);
1578
+ gsvn.lenBranches = 0;
1579
+ gsvn.lenTags = 0;
1580
+ }else{
1581
+ if( gsvn.zTrunk==0 ){ gsvn.zTrunk = "trunk/"; }
1582
+ if( gsvn.zBranches==0 ){ gsvn.zBranches = "branches/"; }
1583
+ if( gsvn.zTags==0 ){ gsvn.zTags = "tags/"; }
1584
+ gsvn.zTrunk = mprintf("%s%s", zBase, gsvn.zTrunk);
1585
+ gsvn.zBranches = mprintf("%s%s", zBase, gsvn.zBranches);
1586
+ gsvn.zTags = mprintf("%s%s", zBase, gsvn.zTags);
1587
+ gsvn.lenTrunk = strlen(gsvn.zTrunk);
1588
+ gsvn.lenBranches = strlen(gsvn.zBranches);
1589
+ gsvn.lenTags = strlen(gsvn.zTags);
1590
+ if( gsvn.zTrunk[gsvn.lenTrunk-1]!='/' ){
1591
+ gsvn.zTrunk = mprintf("%s/", gsvn.zTrunk);
1592
+ gsvn.lenTrunk++;
1593
+ }
1594
+ if( gsvn.zBranches[gsvn.lenBranches-1]!='/' ){
1595
+ gsvn.zBranches = mprintf("%s/", gsvn.zBranches);
1596
+ gsvn.lenBranches++;
1597
+ }
1598
+ if( gsvn.zTags[gsvn.lenTags-1]!='/' ){
1599
+ gsvn.zTags = mprintf("%s/", gsvn.zTags);
1600
+ gsvn.lenTags++;
1601
+ }
1602
+ }
1603
+ svn_dump_import(pIn);
7761604
}else{
7771605
/* The following temp-tables are used to hold information needed for
7781606
** the import.
7791607
**
7801608
** The XMARK table provides a mapping from fast-import "marks" and symbols
@@ -807,10 +1635,12 @@
8071635
fast_insert_content(&record, 0, 0);
8081636
import_reset(0);
8091637
}
8101638
db_finalize(&q);
8111639
}
1640
+
1641
+ verify_cancel();
8121642
db_end_transaction(0);
8131643
db_begin_transaction();
8141644
fossil_print("Rebuilding repository meta-data...\n");
8151645
rebuild_db(0, 1, !incrFlag);
8161646
verify_cancel();
8171647
--- src/import.c
+++ src/import.c
@@ -12,12 +12,12 @@
12 ** Author contact information:
13 ** [email protected]
14 **
15 *******************************************************************************
16 **
17 ** This file contains code used to import the content of a Git
18 ** repository in the git-fast-import format as a new Fossil
19 ** repository.
20 */
21 #include "config.h"
22 #include "import.h"
23 #include <assert.h>
@@ -516,12 +516,12 @@
516 ** last commit that holds that tag.
517 **
518 ** None of the above is explained in the git-fast-export
519 ** documentation. We had to figure it out via trial and error.
520 */
521 for(i=strlen(z)-1; i>=0 && z[i]!='/'; i--){}
522 gg.tagCommit = strncmp(&z[i-4], "tags", 4)==0; /* True for pattern B */
523 if( z[i+1]!=0 ) z += i+1;
524 if( fossil_strcmp(z, "master")==0 ) z = "trunk";
525 gg.zBranch = fossil_strdup(z);
526 gg.fromLoaded = 0;
527 }else
@@ -716,46 +716,822 @@
716 malformed_line:
717 trim_newline(zLine);
718 fossil_fatal("bad fast-import line: [%s]", zLine);
719 return;
720 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
721
722 /*
723 ** COMMAND: import
724 **
725 ** Usage: %fossil import ?OPTIONS? NEW-REPOSITORY ?INPUT-FILE?
 
726 **
727 ** Read interchange format generated by another VCS and use it to
728 ** construct a new Fossil repository named by the NEW-REPOSITORY
729 ** argument. If no input file is supplied the interchange format
730 ** data is read from standard input.
731 **
732 ** The git-fast-export file format is currently the only VCS interchange
733 ** format that is understood, though other interchange formats may be added
734 ** in the future.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
735 **
736 ** The --incremental option allows an existing repository to be extended
737 ** with new content.
738 **
739 ** Options:
740 ** --git import from the git-fast-export file format (default)
741 ** --incremental allow importing into an existing repository
742 **
743 ** See also: export
744 */
745 void import_cmd(void){
746 char *zPassword;
747 FILE *pIn;
748 Stmt q;
749 int forceFlag = find_option("force", "f", 0)!=0;
750 int incrFlag = find_option("incremental", "i", 0)!=0;
751 int svnFlag = find_option("svn", 0, 0)!=0;
752
753 find_option("git",0,0); /* Skip the --git option for now */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
754 verify_all_options();
755 if( g.argc!=3 && g.argc!=4 ){
756 usage("NEW-REPOSITORY ?INPUT-FILE?");
 
757 }
758 if( g.argc==4 ){
759 pIn = fossil_fopen(g.argv[3], "rb");
760 }else{
761 pIn = stdin;
@@ -767,14 +1543,66 @@
767 }
768 db_open_repository(g.argv[2]);
769 db_open_config(0);
770
771 db_begin_transaction();
772 if( !incrFlag ) db_initial_setup(0, 0, 0, 1);
773
774 if( svnFlag ){
775 fossil_fatal("--svn format not implemented yet");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
776 }else{
777 /* The following temp-tables are used to hold information needed for
778 ** the import.
779 **
780 ** The XMARK table provides a mapping from fast-import "marks" and symbols
@@ -807,10 +1635,12 @@
807 fast_insert_content(&record, 0, 0);
808 import_reset(0);
809 }
810 db_finalize(&q);
811 }
 
 
812 db_end_transaction(0);
813 db_begin_transaction();
814 fossil_print("Rebuilding repository meta-data...\n");
815 rebuild_db(0, 1, !incrFlag);
816 verify_cancel();
817
--- src/import.c
+++ src/import.c
@@ -12,12 +12,12 @@
12 ** Author contact information:
13 ** [email protected]
14 **
15 *******************************************************************************
16 **
17 ** This file contains code used to import the content of a Git/SVN
18 ** repository in the git-fast-import/svn-dump formats as a new Fossil
19 ** repository.
20 */
21 #include "config.h"
22 #include "import.h"
23 #include <assert.h>
@@ -516,12 +516,12 @@
516 ** last commit that holds that tag.
517 **
518 ** None of the above is explained in the git-fast-export
519 ** documentation. We had to figure it out via trial and error.
520 */
521 for(i=5; i<strlen(z) && z[i]!='/'; i++){}
522 gg.tagCommit = strncmp(&z[5], "tags", 4)==0; /* True for pattern B */
523 if( z[i+1]!=0 ) z += i+1;
524 if( fossil_strcmp(z, "master")==0 ) z = "trunk";
525 gg.zBranch = fossil_strdup(z);
526 gg.fromLoaded = 0;
527 }else
@@ -716,46 +716,822 @@
716 malformed_line:
717 trim_newline(zLine);
718 fossil_fatal("bad fast-import line: [%s]", zLine);
719 return;
720 }
721
722 static struct{
723 int rev; /* SVN revision number */
724 char *zDate; /* Date/time stamp */
725 char *zUser; /* User name */
726 char *zComment; /* Comment of a commit */
727 const char *zTrunk; /* Name of trunk folder in repo root */
728 int lenTrunk; /* String length of zTrunk */
729 const char *zBranches; /* Name of branches folder in repo root */
730 int lenBranches; /* String length of zBranches */
731 const char *zTags; /* Name of tags folder in repo root */
732 int lenTags; /* String length of zTags */
733 Bag newBranches; /* Branches that were created in this revision */
734 int incrFlag; /* Add svn-rev-nn tags on every checkin */
735 } gsvn;
736 typedef struct {
737 char *zKey;
738 char *zVal;
739 } KeyVal;
740 typedef struct {
741 KeyVal *aHeaders;
742 int nHeaders;
743 char *pRawProps;
744 KeyVal *aProps;
745 int nProps;
746 Blob content;
747 int contentFlag;
748 } SvnRecord;
749
750 #define svn_find_header(rec, zHeader) \
751 svn_find_keyval((rec).aHeaders, (rec).nHeaders, (zHeader))
752 #define svn_find_prop(rec, zProp) \
753 svn_find_keyval((rec).aProps, (rec).nProps, (zProp))
754 static char *svn_find_keyval(
755 KeyVal *aKeyVal,
756 int nKeyVal,
757 const char *zKey
758 ){
759 int i;
760 for(i=0; i<nKeyVal; i++){
761 if( fossil_strcmp(aKeyVal[i].zKey, zKey)==0 ){
762 return aKeyVal[i].zVal;
763 }
764 }
765 return 0;
766 }
767
768 static void svn_free_rec(SvnRecord *rec){
769 int i;
770 for(i=0; i<rec->nHeaders; i++){
771 fossil_free(rec->aHeaders[i].zKey);
772 }
773 fossil_free(rec->aHeaders);
774 fossil_free(rec->aProps);
775 fossil_free(rec->pRawProps);
776 blob_reset(&rec->content);
777 }
778
779 static int svn_read_headers(FILE *pIn, SvnRecord *rec){
780 char zLine[1000];
781
782 rec->aHeaders = 0;
783 rec->nHeaders = 0;
784 while( fgets(zLine, sizeof(zLine), pIn) ){
785 if( zLine[0]!='\n' ) break;
786 }
787 if( feof(pIn) ) return 0;
788 do{
789 char *sep;
790 if( zLine[0]=='\n' ) break;
791 rec->nHeaders += 1;
792 rec->aHeaders = fossil_realloc(rec->aHeaders,
793 sizeof(rec->aHeaders[0])*rec->nHeaders);
794 rec->aHeaders[rec->nHeaders-1].zKey = mprintf("%s", zLine);
795 sep = strchr(rec->aHeaders[rec->nHeaders-1].zKey, ':');
796 if( !sep ){
797 trim_newline(zLine);
798 fossil_fatal("bad header line: [%s]", zLine);
799 }
800 *sep = 0;
801 rec->aHeaders[rec->nHeaders-1].zVal = sep+1;
802 sep = strchr(rec->aHeaders[rec->nHeaders-1].zVal, '\n');
803 *sep = 0;
804 while(rec->aHeaders[rec->nHeaders-1].zVal
805 && fossil_isspace(*(rec->aHeaders[rec->nHeaders-1].zVal)) )
806 {
807 rec->aHeaders[rec->nHeaders-1].zVal++;
808 }
809 }while( fgets(zLine, sizeof(zLine), pIn) );
810 if( zLine[0]!='\n' ){
811 trim_newline(zLine);
812 fossil_fatal("svn-dump data ended unexpectedly");
813 }
814 return 1;
815 }
816
817 static void svn_read_props(FILE *pIn, SvnRecord *rec){
818 int nRawProps = 0;
819 char *pRawProps;
820 const char *zLen;
821
822 rec->pRawProps = 0;
823 rec->aProps = 0;
824 rec->nProps = 0;
825 zLen = svn_find_header(*rec, "Prop-content-length");
826 if( zLen ){
827 nRawProps = atoi(zLen);
828 }
829 if( nRawProps ){
830 int got;
831 char *zLine;
832 rec->pRawProps = pRawProps = fossil_malloc( nRawProps );
833 got = fread(rec->pRawProps, 1, nRawProps, pIn);
834 if( got!=nRawProps ){
835 fossil_fatal("short read: got %d of %d bytes", got, nRawProps);
836 }
837 if( memcmp(&pRawProps[got-10], "PROPS-END\n", 10)!=0 ){
838 fossil_fatal("svn-dump data ended unexpectedly");
839 }
840 zLine = pRawProps;
841 while( zLine<(pRawProps+nRawProps-10) ){
842 char *eol;
843 int propLen;
844 if( zLine[0]=='D' ){
845 propLen = atoi(&zLine[2]);
846 eol = strchr(zLine, '\n');
847 zLine = eol+1+propLen+1;
848 }else{
849 if( zLine[0]!='K' ){
850 fossil_fatal("svn-dump data format broken");
851 }
852 propLen = atoi(&zLine[2]);
853 eol = strchr(zLine, '\n');
854 zLine = eol+1;
855 eol = zLine+propLen;
856 if( *eol!='\n' ){
857 fossil_fatal("svn-dump data format broken");
858 }
859 *eol = 0;
860 rec->nProps += 1;
861 rec->aProps = fossil_realloc(rec->aProps,
862 sizeof(rec->aProps[0])*rec->nProps);
863 rec->aProps[rec->nProps-1].zKey = zLine;
864 zLine = eol+1;
865 if( zLine[0]!='V' ){
866 fossil_fatal("svn-dump data format broken");
867 }
868 propLen = atoi(&zLine[2]);
869 eol = strchr(zLine, '\n');
870 zLine = eol+1;
871 eol = zLine+propLen;
872 if( *eol!='\n' ){
873 fossil_fatal("svn-dump data format broken");
874 }
875 *eol = 0;
876 rec->aProps[rec->nProps-1].zVal = zLine;
877 zLine = eol+1;
878 }
879 }
880 }
881 }
882
883 static int svn_read_rec(FILE *pIn, SvnRecord *rec){
884 const char *zLen;
885 int nLen = 0;
886 if( svn_read_headers(pIn, rec)==0 ) return 0;
887 svn_read_props(pIn, rec);
888 blob_zero(&rec->content);
889 zLen = svn_find_header(*rec, "Text-content-length");
890 if( zLen ){
891 rec->contentFlag = 1;
892 nLen = atoi(zLen);
893 blob_read_from_channel(&rec->content, pIn, nLen);
894 if( blob_size(&rec->content)!=nLen ){
895 fossil_fatal("short read: got %d of %d bytes",
896 blob_size(&rec->content), nLen
897 );
898 }
899 }else{
900 rec->contentFlag = 0;
901 }
902 return 1;
903 }
904
905 /*
906 ** Returns the UUID for the RID, or NULL if not found.
907 ** The returned string is allocated via db_text() and must be
908 ** free()d by the caller.
909 */
910 char * rid_to_uuid(int rid)
911 {
912 return db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
913 }
914
915 #define SVN_UNKNOWN 0
916 #define SVN_TRUNK 1
917 #define SVN_BRANCH 2
918 #define SVN_TAG 3
919
920 #define MAX_INT_32 (0x7FFFFFFFL)
921
922 static void svn_finish_revision(){
923 Blob manifest;
924 static Stmt getChanges;
925 static Stmt getFiles;
926 static Stmt setRid;
927 Blob mcksum;
928
929 blob_zero(&manifest);
930 db_static_prepare(&getChanges, "SELECT tid, tname, ttype, tparent"
931 " FROM xrevisions, xbranches ON (tbranch=tid)"
932 " WHERE trid ISNULL");
933 db_static_prepare(&getFiles, "SELECT tpath, tuuid, tperm FROM xfiles"
934 " WHERE tbranch=:branch ORDER BY tpath");
935 db_prepare(&setRid, "UPDATE xrevisions SET trid=:rid"
936 " WHERE trev=%d AND tbranch=:branch", gsvn.rev);
937 while( db_step(&getChanges)==SQLITE_ROW ){
938 int branchId = db_column_int(&getChanges, 0);
939 const char *zBranch = db_column_text(&getChanges, 1);
940 int branchType = db_column_int(&getChanges, 2);
941 int parentRid = db_column_int(&getChanges, 3);
942 int mergeRid = parentRid;
943 Manifest *pParentManifest = 0;
944 ManifestFile *pParentFile = 0;
945 int sameAsParent = 1;
946 int parentBranch = 0;
947 if( !bag_find(&gsvn.newBranches, branchId) ){
948 parentRid = db_int(0, "SELECT trid, max(trev) FROM xrevisions"
949 " WHERE trev<%d AND tbranch=%d",
950 gsvn.rev, branchId);
951 }
952 if( parentRid>0 ){
953 pParentManifest = manifest_get(parentRid, CFTYPE_MANIFEST, 0);
954 pParentFile = manifest_file_next(pParentManifest, 0);
955 parentBranch = db_int(0, "SELECT tbranch FROM xrevisions WHERE trid=%d",
956 parentRid);
957 if( parentBranch!=branchId && branchType!=SVN_TAG ){
958 sameAsParent = 0;
959 }
960 }
961 if( mergeRid<MAX_INT_32 ){
962 if( gsvn.zComment ){
963 blob_appendf(&manifest, "C %F\n", gsvn.zComment);
964 }else{
965 blob_append(&manifest, "C (no\\scomment)\n", 16);
966 }
967 blob_appendf(&manifest, "D %s\n", gsvn.zDate);
968 db_bind_int(&getFiles, ":branch", branchId);
969 while( db_step(&getFiles)==SQLITE_ROW ){
970 const char *zFile = db_column_text(&getFiles, 0);
971 const char *zUuid = db_column_text(&getFiles, 1);
972 const char *zPerm = db_column_text(&getFiles, 2);
973 if( zPerm ){
974 blob_appendf(&manifest, "F %F %s %s\n", zFile, zUuid, zPerm);
975 }else{
976 blob_appendf(&manifest, "F %F %s\n", zFile, zUuid);
977 }
978 if( sameAsParent ){
979 if( !pParentFile
980 || fossil_strcmp(pParentFile->zName,zFile)!=0
981 || fossil_strcmp(pParentFile->zUuid,zUuid)!=0
982 || fossil_strcmp(pParentFile->zPerm,zPerm)!=0
983 ){
984 sameAsParent = 0;
985 }else{
986 pParentFile = manifest_file_next(pParentManifest, 0);
987 }
988 }
989 }
990 if( pParentFile ){
991 sameAsParent = 0;
992 }
993 db_reset(&getFiles);
994 if( !sameAsParent ){
995 if( parentRid>0 ){
996 char *zParentUuid = rid_to_uuid(parentRid);
997 if( parentRid==mergeRid || mergeRid==0){
998 char *zParentBranch =
999 db_text(0, "SELECT tname FROM xbranches WHERE tid=%d",
1000 parentBranch
1001 );
1002 blob_appendf(&manifest, "P %s\n", zParentUuid);
1003 blob_appendf(&manifest, "T *branch * %F\n", zBranch);
1004 blob_appendf(&manifest, "T *sym-%F *\n", zBranch);
1005 if( gsvn.incrFlag ){
1006 blob_appendf(&manifest, "T +sym-svn-rev-%d *\n", gsvn.rev);
1007 }
1008 blob_appendf(&manifest, "T -sym-%F *\n", zParentBranch);
1009 fossil_free(zParentBranch);
1010 }else{
1011 char *zMergeUuid = rid_to_uuid(mergeRid);
1012 blob_appendf(&manifest, "P %s %s\n", zParentUuid, zMergeUuid);
1013 if( gsvn.incrFlag ){
1014 blob_appendf(&manifest, "T +sym-svn-rev-%d *\n", gsvn.rev);
1015 }
1016 fossil_free(zMergeUuid);
1017 }
1018 fossil_free(zParentUuid);
1019 }else{
1020 blob_appendf(&manifest, "T *branch * %F\n", zBranch);
1021 blob_appendf(&manifest, "T *sym-%F *\n", zBranch);
1022 if( gsvn.incrFlag ){
1023 blob_appendf(&manifest, "T +sym-svn-rev-%d *\n", gsvn.rev);
1024 }
1025 }
1026 }else if( branchType==SVN_TAG ){
1027 char *zParentUuid = rid_to_uuid(parentRid);
1028 blob_reset(&manifest);
1029 blob_appendf(&manifest, "D %s\n", gsvn.zDate);
1030 blob_appendf(&manifest, "T +sym-%F %s\n", zBranch, zParentUuid);
1031 fossil_free(zParentUuid);
1032 }
1033 }else{
1034 char *zParentUuid = rid_to_uuid(parentRid);
1035 blob_appendf(&manifest, "D %s\n", gsvn.zDate);
1036 if( branchType!=SVN_TAG ){
1037 blob_appendf(&manifest, "T +closed %s\n", zParentUuid);
1038 }else{
1039 blob_appendf(&manifest, "T -sym-%F %s\n", zBranch, zParentUuid);
1040 }
1041 fossil_free(zParentUuid);
1042 }
1043 if( gsvn.zUser ){
1044 blob_appendf(&manifest, "U %F\n", gsvn.zUser);
1045 }else{
1046 const char *zUserOvrd = find_option("user-override",0,1);
1047 blob_appendf(&manifest, "U %F\n", zUserOvrd ? zUserOvrd : login_name());
1048 }
1049 md5sum_blob(&manifest, &mcksum);
1050 blob_appendf(&manifest, "Z %b\n", &mcksum);
1051 blob_reset(&mcksum);
1052 if( !sameAsParent ){
1053 int rid = content_put(&manifest);
1054 db_bind_int(&setRid, ":branch", branchId);
1055 db_bind_int(&setRid, ":rid", rid);
1056 db_step(&setRid);
1057 db_reset(&setRid);
1058 }else if( branchType==SVN_TAG ){
1059 content_put(&manifest);
1060 db_bind_int(&setRid, ":branch", branchId);
1061 db_bind_int(&setRid, ":rid", parentRid);
1062 db_step(&setRid);
1063 db_reset(&setRid);
1064 }else if( mergeRid==MAX_INT_32 ){
1065 content_put(&manifest);
1066 db_multi_exec("DELETE FROM xrevisions WHERE tbranch=%d AND trev=%d",
1067 branchId, gsvn.rev);
1068 }else{
1069 db_multi_exec("DELETE FROM xrevisions WHERE tbranch=%d AND trev=%d",
1070 branchId, gsvn.rev);
1071 }
1072 blob_reset(&manifest);
1073 manifest_destroy(pParentManifest);
1074 }
1075 db_reset(&getChanges);
1076 db_finalize(&setRid);
1077 }
1078
1079 static u64 svn_get_varint(const char **pz){
1080 unsigned int v = 0;
1081 do{
1082 v = (v<<7) | ((*pz)[0]&0x7f);
1083 }while( (*pz)++[0]&0x80 );
1084 return v;
1085 }
1086
1087 static void svn_apply_svndiff(Blob *pDiff, Blob *pSrc, Blob *pOut){
1088 const char *zDiff = blob_buffer(pDiff);
1089 char *zOut;
1090 if( blob_size(pDiff)<4 || memcmp(zDiff, "SVN", 4)!=0 ){
1091 fossil_fatal("Invalid svndiff0 format");
1092 }
1093 zDiff += 4;
1094 blob_zero(pOut);
1095 while( zDiff<(blob_buffer(pDiff)+blob_size(pDiff)) ){
1096 u64 lenOut, lenInst, lenData, lenOld;
1097 const char *zInst;
1098 const char *zData;
1099
1100 u64 offSrc = svn_get_varint(&zDiff);
1101 /*lenSrc =*/ svn_get_varint(&zDiff);
1102 lenOut = svn_get_varint(&zDiff);
1103 lenInst = svn_get_varint(&zDiff);
1104 lenData = svn_get_varint(&zDiff);
1105 zInst = zDiff;
1106 zData = zInst+lenInst;
1107 lenOld = blob_size(pOut);
1108 blob_resize(pOut, lenOut+lenOld);
1109 zOut = blob_buffer(pOut)+lenOld;
1110 while( zDiff<zInst+lenInst ){
1111 u64 lenCpy = (*zDiff)&0x3f;
1112 const char *zCpy;
1113 switch( (*zDiff)&0xC0 ){
1114 case 0x00: zCpy = blob_buffer(pSrc)+offSrc; break;
1115 case 0x40: zCpy = blob_buffer(pOut); break;
1116 case 0x80: zCpy = zData; break;
1117 default: fossil_fatal("Invalid svndiff0 instruction");
1118 }
1119 zDiff++;
1120 if( lenCpy==0 ){
1121 lenCpy = svn_get_varint(&zDiff);
1122 }
1123 if( zCpy!=zData ){
1124 zCpy += svn_get_varint(&zDiff);
1125 }else{
1126 zData += lenCpy;
1127 }
1128 while( lenCpy-- > 0 ){
1129 *zOut++ = *zCpy++;
1130 }
1131 }
1132 zDiff += lenData;
1133 }
1134 }
1135
1136 /*
1137 ** Extract the branch or tag that the given path is on. Return the branch ID.
1138 */
1139 static int svn_parse_path(char *zPath, char **zFile, int *type){
1140 char *zBranch = 0;
1141 int branchId = 0;
1142 *type = SVN_UNKNOWN;
1143 *zFile = 0;
1144 if( gsvn.lenTrunk==0 ){
1145 zBranch = "trunk";
1146 *zFile = zPath;
1147 *type = SVN_TRUNK;
1148 }else
1149 if( strncmp(zPath, gsvn.zTrunk, gsvn.lenTrunk-1)==0 ){
1150 if( zPath[gsvn.lenTrunk-1]=='/' || zPath[gsvn.lenTrunk-1]==0 ){
1151 zBranch = "trunk";
1152 *zFile = zPath+gsvn.lenTrunk;
1153 *type = SVN_TRUNK;
1154 }else{
1155 zBranch = 0;
1156 *type = SVN_UNKNOWN;
1157 }
1158 }else{
1159 if( strncmp(zPath, gsvn.zBranches, gsvn.lenBranches)==0 ){
1160 *zFile = zBranch = zPath+gsvn.lenBranches;
1161 *type = SVN_BRANCH;
1162 }else
1163 if( strncmp(zPath, gsvn.zTags, gsvn.lenTags)==0 ){
1164 *zFile = zBranch = zPath+gsvn.lenTags;
1165 *type = SVN_TAG;
1166 }else{ /* Not a branch, tag or trunk */
1167 return 0;
1168 }
1169 while( **zFile && **zFile!='/' ){ (*zFile)++; }
1170 if( **zFile ){
1171 **zFile = '\0';
1172 (*zFile)++;
1173 }
1174 }
1175 if( *type!=SVN_UNKNOWN ){
1176 branchId = db_int(0,
1177 "SELECT tid FROM xbranches WHERE tname=%Q AND ttype=%d",
1178 zBranch, *type);
1179 if( branchId==0 ){
1180 db_multi_exec("INSERT INTO xbranches (tname, ttype) VALUES(%Q, %d)",
1181 zBranch, *type);
1182 branchId = db_last_insert_rowid();
1183 }
1184 }
1185 return branchId;
1186 }
1187
1188 /*
1189 ** Read the svn-dump format from pIn and insert the corresponding
1190 ** content into the database.
1191 */
1192 static void svn_dump_import(FILE *pIn){
1193 SvnRecord rec;
1194 int ver;
1195 char *zTemp;
1196 const char *zUuid;
1197 Stmt addFile;
1198 Stmt delPath;
1199 Stmt addRev;
1200 Stmt cpyPath;
1201 Stmt cpyRoot;
1202 Stmt revSrc;
1203
1204 /* version */
1205 if( svn_read_rec(pIn, &rec)
1206 && (zTemp = svn_find_header(rec, "SVN-fs-dump-format-version")) ){
1207 ver = atoi(zTemp);
1208 if( ver!=2 && ver!=3 ){
1209 fossil_fatal("Unknown svn-dump format version: %d", ver);
1210 }
1211 }else{
1212 fossil_fatal("Input is not an svn-dump!");
1213 }
1214 svn_free_rec(&rec);
1215 /* UUID */
1216 if( !svn_read_rec(pIn, &rec) || !(zUuid = svn_find_header(rec, "UUID")) ){
1217 /* Removed the following line since UUID is not actually used
1218 fossil_fatal("Missing UUID!"); */
1219 }
1220 svn_free_rec(&rec);
1221
1222 /* content */
1223 db_prepare(&addFile,
1224 "INSERT INTO xfiles (tpath, tbranch, tuuid, tperm)"
1225 " VALUES(:path, :branch, (SELECT uuid FROM blob WHERE rid=:rid), :perm)"
1226 );
1227 db_prepare(&delPath,
1228 "DELETE FROM xfiles"
1229 " WHERE (tpath=:path OR (tpath>:path||'/' AND tpath<:path||'0'))"
1230 " AND tbranch=:branch"
1231 );
1232 db_prepare(&addRev,
1233 "INSERT OR IGNORE INTO xrevisions (trev, tbranch) VALUES(:rev, :branch)"
1234 );
1235 db_prepare(&cpyPath,
1236 "INSERT INTO xfiles (tpath, tbranch, tuuid, tperm)"
1237 " SELECT :path||:sep||substr(filename, length(:srcpath)+2), :branch, uuid, perm"
1238 " FROM xfoci"
1239 " WHERE checkinID=:rid"
1240 " AND filename>:srcpath||'/'"
1241 " AND filename<:srcpath||'0'"
1242 );
1243 db_prepare(&cpyRoot,
1244 "INSERT INTO xfiles (tpath, tbranch, tuuid, tperm)"
1245 " SELECT :path||:sep||filename, :branch, uuid, perm"
1246 " FROM xfoci"
1247 " WHERE checkinID=:rid"
1248 );
1249 db_prepare(&revSrc,
1250 "UPDATE xrevisions SET tparent=:parent"
1251 " WHERE trev=:rev AND tbranch=:branch AND tparent<:parent"
1252 );
1253 gsvn.rev = -1;
1254 bag_init(&gsvn.newBranches);
1255 while( svn_read_rec(pIn, &rec) ){
1256 if( (zTemp = svn_find_header(rec, "Revision-number")) ){ /* revision node */
1257 /* finish previous revision */
1258 char *zDate = NULL;
1259 if( gsvn.rev>=0 ){
1260 svn_finish_revision();
1261 fossil_free(gsvn.zUser);
1262 fossil_free(gsvn.zComment);
1263 fossil_free(gsvn.zDate);
1264 bag_clear(&gsvn.newBranches);
1265 }
1266 /* start new revision */
1267 gsvn.rev = atoi(zTemp);
1268 gsvn.zUser = mprintf("%s", svn_find_prop(rec, "svn:author"));
1269 gsvn.zComment = mprintf("%s", svn_find_prop(rec, "svn:log"));
1270 zDate = svn_find_prop(rec, "svn:date");
1271 if( zDate ){
1272 gsvn.zDate = date_in_standard_format(zDate);
1273 }else{
1274 gsvn.zDate = date_in_standard_format("now");
1275 }
1276 db_bind_int(&addRev, ":rev", gsvn.rev);
1277 fossil_print("\rImporting SVN revision: %d", gsvn.rev);
1278 }else
1279 if( (zTemp = svn_find_header(rec, "Node-path")) ){ /* file/dir node */
1280 char *zFile;
1281 int branchType;
1282 int branchId = svn_parse_path(zTemp, &zFile, &branchType);
1283 char *zAction = svn_find_header(rec, "Node-action");
1284 char *zKind = svn_find_header(rec, "Node-kind");
1285 char *zPerm = svn_find_prop(rec, "svn:executable") ? "x" : 0;
1286 int deltaFlag = 0;
1287 int srcRev = 0;
1288 if( branchId==0 ){
1289 svn_free_rec(&rec);
1290 continue;
1291 }
1292 if( (zTemp = svn_find_header(rec, "Text-delta")) ){
1293 deltaFlag = strncmp(zTemp, "true", 4)==0;
1294 }
1295 if( strncmp(zAction, "delete", 6)==0
1296 || strncmp(zAction, "replace", 7)==0 )
1297 {
1298 db_bind_int(&addRev, ":branch", branchId);
1299 db_step(&addRev);
1300 db_reset(&addRev);
1301 if( zFile[0]!=0 ){
1302 db_bind_text(&delPath, ":path", zFile);
1303 db_bind_int(&delPath, ":branch", branchId);
1304 db_step(&delPath);
1305 db_reset(&delPath);
1306 }else{
1307 db_multi_exec("DELETE FROM xfiles WHERE tbranch=%d", branchId);
1308 db_bind_int(&revSrc, ":parent", MAX_INT_32);
1309 db_bind_int(&revSrc, ":rev", gsvn.rev);
1310 db_bind_int(&revSrc, ":branch", branchId);
1311 db_step(&revSrc);
1312 db_reset(&revSrc);
1313 }
1314 } /* no 'else' here since 'replace' does both a 'delete' and an 'add' */
1315 if( strncmp(zAction, "add", 3)==0
1316 || strncmp(zAction, "replace", 7)==0 )
1317 {
1318 char *zSrcPath = svn_find_header(rec, "Node-copyfrom-path");
1319 char *zSrcFile;
1320 int srcRid = 0;
1321 if( zSrcPath ){
1322 int srcBranch;
1323 zTemp = svn_find_header(rec, "Node-copyfrom-rev");
1324 if( zTemp ){
1325 srcRev = atoi(zTemp);
1326 }else{
1327 fossil_fatal("Missing copyfrom-rev");
1328 }
1329 srcBranch = svn_parse_path(zSrcPath, &zSrcFile, &branchType);
1330 if( srcBranch==0 ){
1331 fossil_fatal("Copy from path outside the import paths");
1332 }
1333 srcRid = db_int(0, "SELECT trid, max(trev) FROM xrevisions"
1334 " WHERE trev<=%d AND tbranch=%d",
1335 srcRev, srcBranch);
1336 if( srcRid>0 && srcBranch!=branchId ){
1337 db_bind_int(&addRev, ":branch", branchId);
1338 db_step(&addRev);
1339 db_reset(&addRev);
1340 db_bind_int(&revSrc, ":parent", srcRid);
1341 db_bind_int(&revSrc, ":rev", gsvn.rev);
1342 db_bind_int(&revSrc, ":branch", branchId);
1343 db_step(&revSrc);
1344 db_reset(&revSrc);
1345 }
1346 }
1347 if( zKind==0 ){
1348 fossil_fatal("Missing Node-kind");
1349 }else if( strncmp(zKind, "dir", 3)==0 ){
1350 if( zSrcPath ){
1351 if( srcRid>0 ){
1352 if( zSrcFile[0]==0 ){
1353 db_bind_text(&cpyRoot, ":path", zFile);
1354 if( zFile[0]!=0 ){
1355 db_bind_text(&cpyRoot, ":sep", "/");
1356 }else{
1357 db_bind_text(&cpyRoot, ":sep", "");
1358 }
1359 db_bind_int(&cpyRoot, ":branch", branchId);
1360 db_bind_int(&cpyRoot, ":rid", srcRid);
1361 db_step(&cpyRoot);
1362 db_reset(&cpyRoot);
1363 }else{
1364 db_bind_text(&cpyPath, ":path", zFile);
1365 if( zFile[0]!=0 ){
1366 db_bind_text(&cpyPath, ":sep", "/");
1367 }else{
1368 db_bind_text(&cpyPath, ":sep", "");
1369 }
1370 db_bind_int(&cpyPath, ":branch", branchId);
1371 db_bind_text(&cpyPath, ":srcpath", zSrcFile);
1372 db_bind_int(&cpyPath, ":rid", srcRid);
1373 db_step(&cpyPath);
1374 db_reset(&cpyPath);
1375 }
1376 }
1377 }
1378 if( zFile[0]==0 ){
1379 bag_insert(&gsvn.newBranches, branchId);
1380 }
1381 }else{
1382 int rid = 0;
1383 if( zSrcPath ){
1384 rid = db_int(0, "SELECT rid FROM blob WHERE uuid=("
1385 " SELECT uuid FROM xfoci"
1386 " WHERE checkinID=%d AND filename=%Q"
1387 ")",
1388 srcRid, zSrcFile);
1389 }
1390 if( deltaFlag ){
1391 Blob deltaSrc;
1392 Blob target;
1393 if( rid!=0 ){
1394 content_get(rid, &deltaSrc);
1395 }else{
1396 blob_zero(&deltaSrc);
1397 }
1398 svn_apply_svndiff(&rec.content, &deltaSrc, &target);
1399 rid = content_put(&target);
1400 }else if( rec.contentFlag ){
1401 rid = content_put(&rec.content);
1402 }
1403 db_bind_text(&addFile, ":path", zFile);
1404 db_bind_int(&addFile, ":branch", branchId);
1405 db_bind_int(&addFile, ":rid", rid);
1406 db_bind_text(&addFile, ":perm", zPerm);
1407 db_step(&addFile);
1408 db_reset(&addFile);
1409 db_bind_int(&addRev, ":branch", branchId);
1410 db_step(&addRev);
1411 db_reset(&addRev);
1412 }
1413 }else
1414 if( strncmp(zAction, "change", 6)==0 ){
1415 int rid = 0;
1416 if( zKind==0 ){
1417 fossil_fatal("Missing Node-kind");
1418 }
1419 if( strncmp(zKind, "dir", 3)!=0 ){
1420 if( deltaFlag ){
1421 Blob deltaSrc;
1422 Blob target;
1423 rid = db_int(0, "SELECT rid FROM blob WHERE uuid=("
1424 " SELECT uuid FROM xfiles"
1425 " WHERE tpath=%Q AND tbranch=%d"
1426 ")", zFile, branchId);
1427 content_get(rid, &deltaSrc);
1428 svn_apply_svndiff(&rec.content, &deltaSrc, &target);
1429 rid = content_put(&target);
1430 }else{
1431 rid = content_put(&rec.content);
1432 }
1433 db_bind_text(&addFile, ":path", zFile);
1434 db_bind_int(&addFile, ":branch", branchId);
1435 db_bind_int(&addFile, ":rid", rid);
1436 db_bind_text(&addFile, ":perm", zPerm);
1437 db_step(&addFile);
1438 db_reset(&addFile);
1439 db_bind_int(&addRev, ":branch", branchId);
1440 db_step(&addRev);
1441 db_reset(&addRev);
1442 }
1443 }else
1444 if( strncmp(zAction, "delete", 6)!=0 ){ /* already did this one above */
1445 fossil_fatal("Unknown Node-action");
1446 }
1447 }else{
1448 fossil_fatal("Unknown record type");
1449 }
1450 svn_free_rec(&rec);
1451 }
1452 svn_finish_revision();
1453 fossil_free(gsvn.zUser);
1454 fossil_free(gsvn.zComment);
1455 fossil_free(gsvn.zDate);
1456 db_finalize(&addFile);
1457 db_finalize(&delPath);
1458 db_finalize(&addRev);
1459 db_finalize(&cpyPath);
1460 db_finalize(&cpyRoot);
1461 db_finalize(&revSrc);
1462 fossil_print(" Done!\n");
1463 }
1464
1465 /*
1466 ** COMMAND: import
1467 **
1468 ** Usage: %fossil import ?--git? ?OPTIONS? NEW-REPOSITORY ?INPUT-FILE?
1469 ** or: %fossil import --svn ?OPTIONS? NEW-REPOSITORY ?INPUT-FILE?
1470 **
1471 ** Read interchange format generated by another VCS and use it to
1472 ** construct a new Fossil repository named by the NEW-REPOSITORY
1473 ** argument. If no input file is supplied the interchange format
1474 ** data is read from standard input.
1475 **
1476 ** The following formats are currently understood by this command
1477 **
1478 ** --git Import from the git-fast-export file format (default)
1479 **
1480 ** --svn Import from the svnadmin-dump file format. The default
1481 ** behaviour (unless overridden by --flat) is to treat 3
1482 ** folders in the SVN root as special, following the
1483 ** common layout of SVN repositories. These are (by
1484 ** default) trunk/, branches/ and tags/
1485 ** Options:
1486 ** --trunk FOLDER Name of trunk folder
1487 ** --branches FOLDER Name of branches folder
1488 ** --tags FOLDER Name of tags folder
1489 ** --base PATH Path to project root in repository
1490 ** --flat The whole dump is a single branch
1491 **
1492 ** Common Options:
1493 ** -i|--incremental allow importing into an existing repository
1494 ** -f|--force overwrite repository if already exist
1495 **
1496 ** The --incremental option allows an existing repository to be extended
1497 ** with new content.
1498 **
 
 
 
1499 **
1500 ** See also: export
1501 */
1502 void import_cmd(void){
1503 char *zPassword;
1504 FILE *pIn;
1505 Stmt q;
1506 int forceFlag = find_option("force", "f", 0)!=0;
 
1507 int svnFlag = find_option("svn", 0, 0)!=0;
1508
1509 /* Options common to all input formats */
1510 int incrFlag = find_option("incremental", "i", 0)!=0;
1511
1512 /* Options for --svn only */
1513 const char *zBase="";
1514 int flatFlag=0;
1515
1516 if( svnFlag ){
1517 /* Get --svn related options here, so verify_all_options() fail when svn
1518 * only option are specify with --git
1519 */
1520 zBase = find_option("base", 0, 1);
1521 flatFlag = find_option("flat", 0, 0)!=0;
1522 gsvn.zTrunk = find_option("trunk", 0, 1);
1523 gsvn.zBranches = find_option("branches", 0, 1);
1524 gsvn.zTags = find_option("tags", 0, 1);
1525 gsvn.incrFlag = incrFlag;
1526 }else{
1527 find_option("git",0,0); /* Skip the --git option for now */
1528 }
1529 verify_all_options();
1530
1531 if( g.argc!=3 && g.argc!=4 ){
1532 usage("--git|--svn ?OPTIONS? NEW-REPOSITORY ?INPUT-FILE?");
1533 }
1534 if( g.argc==4 ){
1535 pIn = fossil_fopen(g.argv[3], "rb");
1536 }else{
1537 pIn = stdin;
@@ -767,14 +1543,66 @@
1543 }
1544 db_open_repository(g.argv[2]);
1545 db_open_config(0);
1546
1547 db_begin_transaction();
1548 if( !incrFlag ) db_initial_setup(0, 0, 0);
1549
1550 if( svnFlag ){
1551 db_multi_exec(
1552 "CREATE TEMP TABLE xrevisions("
1553 " trev INTEGER, tbranch INT, trid INT, tparent INT DEFAULT 0,"
1554 " UNIQUE(tbranch, trev)"
1555 ");"
1556 "CREATE INDEX temp.i_xrevisions ON xrevisions(trid);"
1557 "CREATE TEMP TABLE xfiles("
1558 " tpath TEXT, tbranch INT, tuuid TEXT, tperm TEXT,"
1559 " UNIQUE (tbranch, tpath) ON CONFLICT REPLACE"
1560 ");"
1561 "CREATE TEMP TABLE xbranches("
1562 " tid INTEGER PRIMARY KEY, tname TEXT, ttype INT,"
1563 " UNIQUE(tname, ttype)"
1564 ");"
1565 "CREATE VIRTUAL TABLE temp.xfoci USING files_of_checkin;"
1566 );
1567 if( zBase==0 ){ zBase = ""; }
1568 if( strlen(zBase)>0 ){
1569 if( zBase[strlen(zBase)-1]!='/' ){
1570 zBase = mprintf("%s/", zBase);
1571 }
1572 }
1573 if( flatFlag ){
1574 gsvn.zTrunk = zBase;
1575 gsvn.zBranches = 0;
1576 gsvn.zTags = 0;
1577 gsvn.lenTrunk = strlen(zBase);
1578 gsvn.lenBranches = 0;
1579 gsvn.lenTags = 0;
1580 }else{
1581 if( gsvn.zTrunk==0 ){ gsvn.zTrunk = "trunk/"; }
1582 if( gsvn.zBranches==0 ){ gsvn.zBranches = "branches/"; }
1583 if( gsvn.zTags==0 ){ gsvn.zTags = "tags/"; }
1584 gsvn.zTrunk = mprintf("%s%s", zBase, gsvn.zTrunk);
1585 gsvn.zBranches = mprintf("%s%s", zBase, gsvn.zBranches);
1586 gsvn.zTags = mprintf("%s%s", zBase, gsvn.zTags);
1587 gsvn.lenTrunk = strlen(gsvn.zTrunk);
1588 gsvn.lenBranches = strlen(gsvn.zBranches);
1589 gsvn.lenTags = strlen(gsvn.zTags);
1590 if( gsvn.zTrunk[gsvn.lenTrunk-1]!='/' ){
1591 gsvn.zTrunk = mprintf("%s/", gsvn.zTrunk);
1592 gsvn.lenTrunk++;
1593 }
1594 if( gsvn.zBranches[gsvn.lenBranches-1]!='/' ){
1595 gsvn.zBranches = mprintf("%s/", gsvn.zBranches);
1596 gsvn.lenBranches++;
1597 }
1598 if( gsvn.zTags[gsvn.lenTags-1]!='/' ){
1599 gsvn.zTags = mprintf("%s/", gsvn.zTags);
1600 gsvn.lenTags++;
1601 }
1602 }
1603 svn_dump_import(pIn);
1604 }else{
1605 /* The following temp-tables are used to hold information needed for
1606 ** the import.
1607 **
1608 ** The XMARK table provides a mapping from fast-import "marks" and symbols
@@ -807,10 +1635,12 @@
1635 fast_insert_content(&record, 0, 0);
1636 import_reset(0);
1637 }
1638 db_finalize(&q);
1639 }
1640
1641 verify_cancel();
1642 db_end_transaction(0);
1643 db_begin_transaction();
1644 fossil_print("Rebuilding repository meta-data...\n");
1645 rebuild_db(0, 1, !incrFlag);
1646 verify_cancel();
1647
--- src/json_config.c
+++ src/json_config.c
@@ -81,10 +81,11 @@
8181
{ "keep-glob", CONFIGSET_PROJ },
8282
{ "crnl-glob", CONFIGSET_PROJ },
8383
{ "encoding-glob", CONFIGSET_PROJ },
8484
{ "empty-dirs", CONFIGSET_PROJ },
8585
{ "allow-symlinks", CONFIGSET_PROJ },
86
+{ "dotfiles", CONFIGSET_PROJ },
8687
8788
{ "ticket-table", CONFIGSET_TKT },
8889
{ "ticket-common", CONFIGSET_TKT },
8990
{ "ticket-change", CONFIGSET_TKT },
9091
{ "ticket-newpage", CONFIGSET_TKT },
9192
--- src/json_config.c
+++ src/json_config.c
@@ -81,10 +81,11 @@
81 { "keep-glob", CONFIGSET_PROJ },
82 { "crnl-glob", CONFIGSET_PROJ },
83 { "encoding-glob", CONFIGSET_PROJ },
84 { "empty-dirs", CONFIGSET_PROJ },
85 { "allow-symlinks", CONFIGSET_PROJ },
 
86
87 { "ticket-table", CONFIGSET_TKT },
88 { "ticket-common", CONFIGSET_TKT },
89 { "ticket-change", CONFIGSET_TKT },
90 { "ticket-newpage", CONFIGSET_TKT },
91
--- src/json_config.c
+++ src/json_config.c
@@ -81,10 +81,11 @@
81 { "keep-glob", CONFIGSET_PROJ },
82 { "crnl-glob", CONFIGSET_PROJ },
83 { "encoding-glob", CONFIGSET_PROJ },
84 { "empty-dirs", CONFIGSET_PROJ },
85 { "allow-symlinks", CONFIGSET_PROJ },
86 { "dotfiles", CONFIGSET_PROJ },
87
88 { "ticket-table", CONFIGSET_TKT },
89 { "ticket-common", CONFIGSET_TKT },
90 { "ticket-change", CONFIGSET_TKT },
91 { "ticket-newpage", CONFIGSET_TKT },
92
+39 -14
--- src/main.c
+++ src/main.c
@@ -2034,19 +2034,43 @@
20342034
** Open the repository to be served if it is known. If g.argv[arg] is
20352035
** a directory full of repositories, then set g.zRepositoryName to
20362036
** the name of that directory and the specific repository will be
20372037
** opened later by process_one_web_page() based on the content of
20382038
** the PATH_INFO variable.
2039
+**
2040
+** If the fCreate flag is set, then create the repository if it
2041
+** does not already exist.
20392042
*/
2040
-static void find_server_repository(int arg){
2043
+static void find_server_repository(int arg, int fCreate){
20412044
if( g.argc<=arg ){
20422045
db_must_be_within_tree();
2043
- }else if( file_isdir(g.argv[arg])==1 ){
2044
- g.zRepositoryName = mprintf("%s", g.argv[arg]);
2045
- file_simplify_name(g.zRepositoryName, -1, 0);
20462046
}else{
2047
- db_open_repository(g.argv[arg]);
2047
+ const char *zRepo = g.argv[arg];
2048
+ int isDir = file_isdir(zRepo);
2049
+ if( isDir==1 ){
2050
+ g.zRepositoryName = mprintf("%s", zRepo);
2051
+ file_simplify_name(g.zRepositoryName, -1, 0);
2052
+ }else{
2053
+ if( isDir==0 && fCreate ){
2054
+ const char *zPassword;
2055
+ db_create_repository(zRepo);
2056
+ db_open_repository(zRepo);
2057
+ db_begin_transaction();
2058
+ db_initial_setup(0, "now", g.zLogin);
2059
+ db_end_transaction(0);
2060
+ fossil_print("project-id: %s\n", db_get("project-code", 0));
2061
+ fossil_print("server-id: %s\n", db_get("server-code", 0));
2062
+ zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
2063
+ fossil_print("admin-user: %s (initial password is \"%s\")\n",
2064
+ g.zLogin, zPassword);
2065
+ cache_initialize();
2066
+ g.zLogin = 0;
2067
+ g.userUid = 0;
2068
+ }else{
2069
+ db_open_repository(zRepo);
2070
+ }
2071
+ }
20482072
}
20492073
}
20502074
20512075
/*
20522076
** undocumented format:
@@ -2149,15 +2173,15 @@
21492173
g.fullHttpReply = 1;
21502174
if( g.argc>=5 ){
21512175
g.httpIn = fossil_fopen(g.argv[2], "rb");
21522176
g.httpOut = fossil_fopen(g.argv[3], "wb");
21532177
zIpAddr = g.argv[4];
2154
- find_server_repository(5);
2178
+ find_server_repository(5, 0);
21552179
}else{
21562180
g.httpIn = stdin;
21572181
g.httpOut = stdout;
2158
- find_server_repository(2);
2182
+ find_server_repository(2, 0);
21592183
}
21602184
if( zIpAddr==0 ){
21612185
zIpAddr = cgi_ssh_remote_addr(0);
21622186
if( zIpAddr && zIpAddr[0] ){
21632187
g.fSshClient |= CGI_SSH_CLIENT;
@@ -2200,11 +2224,11 @@
22002224
Th_InitTraceLog();
22012225
login_set_capabilities("sx", 0);
22022226
g.useLocalauth = 1;
22032227
g.httpIn = stdin;
22042228
g.httpOut = stdout;
2205
- find_server_repository(2);
2229
+ find_server_repository(2, 0);
22062230
g.cgiOutput = 1;
22072231
g.fullHttpReply = 1;
22082232
zIpAddr = cgi_ssh_remote_addr(0);
22092233
if( zIpAddr && zIpAddr[0] ){
22102234
g.fSshClient |= CGI_SSH_CLIENT;
@@ -2257,12 +2281,12 @@
22572281
** The "ui" command automatically starts a web browser after initializing
22582282
** the web server. The "ui" command also binds to 127.0.0.1 and so will
22592283
** only process HTTP traffic from the local machine.
22602284
**
22612285
** The REPOSITORY can be a directory (aka folder) that contains one or
2262
-** more repositories with names ending in ".fossil". In this case, the
2263
-** a prefix of the URL pathname is used to search the directory for an
2286
+** more repositories with names ending in ".fossil". In this case, a
2287
+** prefix of the URL pathname is used to search the directory for an
22642288
** appropriate repository. To thwart mischief, the pathname in the URL must
22652289
** contain only alphanumerics, "_", "/", "-", and ".", and no "-" may
22662290
** occur after "/", and every "." must be surrounded on both sides by
22672291
** alphanumerics. Any pathname that does not satisfy these constraints
22682292
** results in a 404 error. Files in REPOSITORY that match the comma-separated
@@ -2279,10 +2303,11 @@
22792303
** connection is from localhost. The "ui" command also enables --repolist
22802304
** by default.
22812305
**
22822306
** Options:
22832307
** --baseurl URL Use URL as the base (useful for reverse proxies)
2308
+** --create Create a new REPOSITORY if it does not already exist
22842309
** --files GLOBLIST Comma-separated list of glob patterns for static files
22852310
** --localauth enable automatic login for requests from localhost
22862311
** --localhost listen on 127.0.0.1 only (always true for "ui")
22872312
** --nojail Drop root privileges but do not enter the chroot jail
22882313
** --notfound URL Redirect
@@ -2308,10 +2333,11 @@
23082333
#endif
23092334
int allowRepoList; /* List repositories on URL "/" */
23102335
const char *zAltBase; /* Argument to the --baseurl option */
23112336
const char *zFileGlob; /* Static content must match this */
23122337
char *zIpAddr = 0; /* Bind to this IP address */
2338
+ int fCreate = 0;
23132339
23142340
#if defined(_WIN32)
23152341
const char *zStopperFile; /* Name of file used to terminate server */
23162342
zStopperFile = find_option("stopper", 0, 1);
23172343
#endif
@@ -2332,10 +2358,11 @@
23322358
Th_InitTraceLog();
23332359
zPort = find_option("port", "P", 1);
23342360
zNotFound = find_option("notfound", 0, 1);
23352361
allowRepoList = find_option("repolist",0,0)!=0;
23362362
zAltBase = find_option("baseurl", 0, 1);
2363
+ fCreate = find_option("create",0,0)!=0;
23372364
if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
23382365
if( zAltBase ){
23392366
set_base_url(zAltBase);
23402367
}
23412368
if( find_option("localhost", 0, 0)!=0 ){
@@ -2350,11 +2377,11 @@
23502377
if( isUiCmd ){
23512378
flags |= HTTP_SERVER_LOCALHOST|HTTP_SERVER_REPOLIST;
23522379
g.useLocalauth = 1;
23532380
allowRepoList = 1;
23542381
}
2355
- find_server_repository(2);
2382
+ find_server_repository(2, fCreate);
23562383
if( zPort ){
23572384
int i;
23582385
for(i=strlen(zPort)-1; i>=0 && zPort[i]!=':'; i--){}
23592386
if( i>0 ){
23602387
zIpAddr = mprintf("%.*s", i, zPort);
@@ -2390,12 +2417,10 @@
23902417
}else{
23912418
zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
23922419
}
23932420
if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
23942421
if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
2395
- }else{
2396
- db_setup_server_and_project_codes(1);
23972422
}
23982423
db_close(1);
23992424
if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
24002425
fossil_fatal("unable to listen on TCP socket %d", iPort);
24012426
}
@@ -2404,11 +2429,11 @@
24042429
g.httpOut = stdout;
24052430
if( g.fHttpTrace || g.fSqlTrace ){
24062431
fprintf(stderr, "====== SERVER pid %d =======\n", getpid());
24072432
}
24082433
g.cgiOutput = 1;
2409
- find_server_repository(2);
2434
+ find_server_repository(2, 0);
24102435
g.zRepositoryName = enter_chroot_jail(g.zRepositoryName, noJail);
24112436
if( flags & HTTP_SERVER_SCGI ){
24122437
cgi_handle_scgi_request();
24132438
}else{
24142439
cgi_handle_http_request(0);
24152440
--- src/main.c
+++ src/main.c
@@ -2034,19 +2034,43 @@
2034 ** Open the repository to be served if it is known. If g.argv[arg] is
2035 ** a directory full of repositories, then set g.zRepositoryName to
2036 ** the name of that directory and the specific repository will be
2037 ** opened later by process_one_web_page() based on the content of
2038 ** the PATH_INFO variable.
 
 
 
2039 */
2040 static void find_server_repository(int arg){
2041 if( g.argc<=arg ){
2042 db_must_be_within_tree();
2043 }else if( file_isdir(g.argv[arg])==1 ){
2044 g.zRepositoryName = mprintf("%s", g.argv[arg]);
2045 file_simplify_name(g.zRepositoryName, -1, 0);
2046 }else{
2047 db_open_repository(g.argv[arg]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2048 }
2049 }
2050
2051 /*
2052 ** undocumented format:
@@ -2149,15 +2173,15 @@
2149 g.fullHttpReply = 1;
2150 if( g.argc>=5 ){
2151 g.httpIn = fossil_fopen(g.argv[2], "rb");
2152 g.httpOut = fossil_fopen(g.argv[3], "wb");
2153 zIpAddr = g.argv[4];
2154 find_server_repository(5);
2155 }else{
2156 g.httpIn = stdin;
2157 g.httpOut = stdout;
2158 find_server_repository(2);
2159 }
2160 if( zIpAddr==0 ){
2161 zIpAddr = cgi_ssh_remote_addr(0);
2162 if( zIpAddr && zIpAddr[0] ){
2163 g.fSshClient |= CGI_SSH_CLIENT;
@@ -2200,11 +2224,11 @@
2200 Th_InitTraceLog();
2201 login_set_capabilities("sx", 0);
2202 g.useLocalauth = 1;
2203 g.httpIn = stdin;
2204 g.httpOut = stdout;
2205 find_server_repository(2);
2206 g.cgiOutput = 1;
2207 g.fullHttpReply = 1;
2208 zIpAddr = cgi_ssh_remote_addr(0);
2209 if( zIpAddr && zIpAddr[0] ){
2210 g.fSshClient |= CGI_SSH_CLIENT;
@@ -2257,12 +2281,12 @@
2257 ** The "ui" command automatically starts a web browser after initializing
2258 ** the web server. The "ui" command also binds to 127.0.0.1 and so will
2259 ** only process HTTP traffic from the local machine.
2260 **
2261 ** The REPOSITORY can be a directory (aka folder) that contains one or
2262 ** more repositories with names ending in ".fossil". In this case, the
2263 ** a prefix of the URL pathname is used to search the directory for an
2264 ** appropriate repository. To thwart mischief, the pathname in the URL must
2265 ** contain only alphanumerics, "_", "/", "-", and ".", and no "-" may
2266 ** occur after "/", and every "." must be surrounded on both sides by
2267 ** alphanumerics. Any pathname that does not satisfy these constraints
2268 ** results in a 404 error. Files in REPOSITORY that match the comma-separated
@@ -2279,10 +2303,11 @@
2279 ** connection is from localhost. The "ui" command also enables --repolist
2280 ** by default.
2281 **
2282 ** Options:
2283 ** --baseurl URL Use URL as the base (useful for reverse proxies)
 
2284 ** --files GLOBLIST Comma-separated list of glob patterns for static files
2285 ** --localauth enable automatic login for requests from localhost
2286 ** --localhost listen on 127.0.0.1 only (always true for "ui")
2287 ** --nojail Drop root privileges but do not enter the chroot jail
2288 ** --notfound URL Redirect
@@ -2308,10 +2333,11 @@
2308 #endif
2309 int allowRepoList; /* List repositories on URL "/" */
2310 const char *zAltBase; /* Argument to the --baseurl option */
2311 const char *zFileGlob; /* Static content must match this */
2312 char *zIpAddr = 0; /* Bind to this IP address */
 
2313
2314 #if defined(_WIN32)
2315 const char *zStopperFile; /* Name of file used to terminate server */
2316 zStopperFile = find_option("stopper", 0, 1);
2317 #endif
@@ -2332,10 +2358,11 @@
2332 Th_InitTraceLog();
2333 zPort = find_option("port", "P", 1);
2334 zNotFound = find_option("notfound", 0, 1);
2335 allowRepoList = find_option("repolist",0,0)!=0;
2336 zAltBase = find_option("baseurl", 0, 1);
 
2337 if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
2338 if( zAltBase ){
2339 set_base_url(zAltBase);
2340 }
2341 if( find_option("localhost", 0, 0)!=0 ){
@@ -2350,11 +2377,11 @@
2350 if( isUiCmd ){
2351 flags |= HTTP_SERVER_LOCALHOST|HTTP_SERVER_REPOLIST;
2352 g.useLocalauth = 1;
2353 allowRepoList = 1;
2354 }
2355 find_server_repository(2);
2356 if( zPort ){
2357 int i;
2358 for(i=strlen(zPort)-1; i>=0 && zPort[i]!=':'; i--){}
2359 if( i>0 ){
2360 zIpAddr = mprintf("%.*s", i, zPort);
@@ -2390,12 +2417,10 @@
2390 }else{
2391 zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
2392 }
2393 if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
2394 if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
2395 }else{
2396 db_setup_server_and_project_codes(1);
2397 }
2398 db_close(1);
2399 if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
2400 fossil_fatal("unable to listen on TCP socket %d", iPort);
2401 }
@@ -2404,11 +2429,11 @@
2404 g.httpOut = stdout;
2405 if( g.fHttpTrace || g.fSqlTrace ){
2406 fprintf(stderr, "====== SERVER pid %d =======\n", getpid());
2407 }
2408 g.cgiOutput = 1;
2409 find_server_repository(2);
2410 g.zRepositoryName = enter_chroot_jail(g.zRepositoryName, noJail);
2411 if( flags & HTTP_SERVER_SCGI ){
2412 cgi_handle_scgi_request();
2413 }else{
2414 cgi_handle_http_request(0);
2415
--- src/main.c
+++ src/main.c
@@ -2034,19 +2034,43 @@
2034 ** Open the repository to be served if it is known. If g.argv[arg] is
2035 ** a directory full of repositories, then set g.zRepositoryName to
2036 ** the name of that directory and the specific repository will be
2037 ** opened later by process_one_web_page() based on the content of
2038 ** the PATH_INFO variable.
2039 **
2040 ** If the fCreate flag is set, then create the repository if it
2041 ** does not already exist.
2042 */
2043 static void find_server_repository(int arg, int fCreate){
2044 if( g.argc<=arg ){
2045 db_must_be_within_tree();
 
 
 
2046 }else{
2047 const char *zRepo = g.argv[arg];
2048 int isDir = file_isdir(zRepo);
2049 if( isDir==1 ){
2050 g.zRepositoryName = mprintf("%s", zRepo);
2051 file_simplify_name(g.zRepositoryName, -1, 0);
2052 }else{
2053 if( isDir==0 && fCreate ){
2054 const char *zPassword;
2055 db_create_repository(zRepo);
2056 db_open_repository(zRepo);
2057 db_begin_transaction();
2058 db_initial_setup(0, "now", g.zLogin);
2059 db_end_transaction(0);
2060 fossil_print("project-id: %s\n", db_get("project-code", 0));
2061 fossil_print("server-id: %s\n", db_get("server-code", 0));
2062 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
2063 fossil_print("admin-user: %s (initial password is \"%s\")\n",
2064 g.zLogin, zPassword);
2065 cache_initialize();
2066 g.zLogin = 0;
2067 g.userUid = 0;
2068 }else{
2069 db_open_repository(zRepo);
2070 }
2071 }
2072 }
2073 }
2074
2075 /*
2076 ** undocumented format:
@@ -2149,15 +2173,15 @@
2173 g.fullHttpReply = 1;
2174 if( g.argc>=5 ){
2175 g.httpIn = fossil_fopen(g.argv[2], "rb");
2176 g.httpOut = fossil_fopen(g.argv[3], "wb");
2177 zIpAddr = g.argv[4];
2178 find_server_repository(5, 0);
2179 }else{
2180 g.httpIn = stdin;
2181 g.httpOut = stdout;
2182 find_server_repository(2, 0);
2183 }
2184 if( zIpAddr==0 ){
2185 zIpAddr = cgi_ssh_remote_addr(0);
2186 if( zIpAddr && zIpAddr[0] ){
2187 g.fSshClient |= CGI_SSH_CLIENT;
@@ -2200,11 +2224,11 @@
2224 Th_InitTraceLog();
2225 login_set_capabilities("sx", 0);
2226 g.useLocalauth = 1;
2227 g.httpIn = stdin;
2228 g.httpOut = stdout;
2229 find_server_repository(2, 0);
2230 g.cgiOutput = 1;
2231 g.fullHttpReply = 1;
2232 zIpAddr = cgi_ssh_remote_addr(0);
2233 if( zIpAddr && zIpAddr[0] ){
2234 g.fSshClient |= CGI_SSH_CLIENT;
@@ -2257,12 +2281,12 @@
2281 ** The "ui" command automatically starts a web browser after initializing
2282 ** the web server. The "ui" command also binds to 127.0.0.1 and so will
2283 ** only process HTTP traffic from the local machine.
2284 **
2285 ** The REPOSITORY can be a directory (aka folder) that contains one or
2286 ** more repositories with names ending in ".fossil". In this case, a
2287 ** prefix of the URL pathname is used to search the directory for an
2288 ** appropriate repository. To thwart mischief, the pathname in the URL must
2289 ** contain only alphanumerics, "_", "/", "-", and ".", and no "-" may
2290 ** occur after "/", and every "." must be surrounded on both sides by
2291 ** alphanumerics. Any pathname that does not satisfy these constraints
2292 ** results in a 404 error. Files in REPOSITORY that match the comma-separated
@@ -2279,10 +2303,11 @@
2303 ** connection is from localhost. The "ui" command also enables --repolist
2304 ** by default.
2305 **
2306 ** Options:
2307 ** --baseurl URL Use URL as the base (useful for reverse proxies)
2308 ** --create Create a new REPOSITORY if it does not already exist
2309 ** --files GLOBLIST Comma-separated list of glob patterns for static files
2310 ** --localauth enable automatic login for requests from localhost
2311 ** --localhost listen on 127.0.0.1 only (always true for "ui")
2312 ** --nojail Drop root privileges but do not enter the chroot jail
2313 ** --notfound URL Redirect
@@ -2308,10 +2333,11 @@
2333 #endif
2334 int allowRepoList; /* List repositories on URL "/" */
2335 const char *zAltBase; /* Argument to the --baseurl option */
2336 const char *zFileGlob; /* Static content must match this */
2337 char *zIpAddr = 0; /* Bind to this IP address */
2338 int fCreate = 0;
2339
2340 #if defined(_WIN32)
2341 const char *zStopperFile; /* Name of file used to terminate server */
2342 zStopperFile = find_option("stopper", 0, 1);
2343 #endif
@@ -2332,10 +2358,11 @@
2358 Th_InitTraceLog();
2359 zPort = find_option("port", "P", 1);
2360 zNotFound = find_option("notfound", 0, 1);
2361 allowRepoList = find_option("repolist",0,0)!=0;
2362 zAltBase = find_option("baseurl", 0, 1);
2363 fCreate = find_option("create",0,0)!=0;
2364 if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
2365 if( zAltBase ){
2366 set_base_url(zAltBase);
2367 }
2368 if( find_option("localhost", 0, 0)!=0 ){
@@ -2350,11 +2377,11 @@
2377 if( isUiCmd ){
2378 flags |= HTTP_SERVER_LOCALHOST|HTTP_SERVER_REPOLIST;
2379 g.useLocalauth = 1;
2380 allowRepoList = 1;
2381 }
2382 find_server_repository(2, fCreate);
2383 if( zPort ){
2384 int i;
2385 for(i=strlen(zPort)-1; i>=0 && zPort[i]!=':'; i--){}
2386 if( i>0 ){
2387 zIpAddr = mprintf("%.*s", i, zPort);
@@ -2390,12 +2417,10 @@
2417 }else{
2418 zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
2419 }
2420 if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
2421 if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
 
 
2422 }
2423 db_close(1);
2424 if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
2425 fossil_fatal("unable to listen on TCP socket %d", iPort);
2426 }
@@ -2404,11 +2429,11 @@
2429 g.httpOut = stdout;
2430 if( g.fHttpTrace || g.fSqlTrace ){
2431 fprintf(stderr, "====== SERVER pid %d =======\n", getpid());
2432 }
2433 g.cgiOutput = 1;
2434 find_server_repository(2, 0);
2435 g.zRepositoryName = enter_chroot_jail(g.zRepositoryName, noJail);
2436 if( flags & HTTP_SERVER_SCGI ){
2437 cgi_handle_scgi_request();
2438 }else{
2439 cgi_handle_http_request(0);
2440
+39 -14
--- src/main.c
+++ src/main.c
@@ -2034,19 +2034,43 @@
20342034
** Open the repository to be served if it is known. If g.argv[arg] is
20352035
** a directory full of repositories, then set g.zRepositoryName to
20362036
** the name of that directory and the specific repository will be
20372037
** opened later by process_one_web_page() based on the content of
20382038
** the PATH_INFO variable.
2039
+**
2040
+** If the fCreate flag is set, then create the repository if it
2041
+** does not already exist.
20392042
*/
2040
-static void find_server_repository(int arg){
2043
+static void find_server_repository(int arg, int fCreate){
20412044
if( g.argc<=arg ){
20422045
db_must_be_within_tree();
2043
- }else if( file_isdir(g.argv[arg])==1 ){
2044
- g.zRepositoryName = mprintf("%s", g.argv[arg]);
2045
- file_simplify_name(g.zRepositoryName, -1, 0);
20462046
}else{
2047
- db_open_repository(g.argv[arg]);
2047
+ const char *zRepo = g.argv[arg];
2048
+ int isDir = file_isdir(zRepo);
2049
+ if( isDir==1 ){
2050
+ g.zRepositoryName = mprintf("%s", zRepo);
2051
+ file_simplify_name(g.zRepositoryName, -1, 0);
2052
+ }else{
2053
+ if( isDir==0 && fCreate ){
2054
+ const char *zPassword;
2055
+ db_create_repository(zRepo);
2056
+ db_open_repository(zRepo);
2057
+ db_begin_transaction();
2058
+ db_initial_setup(0, "now", g.zLogin);
2059
+ db_end_transaction(0);
2060
+ fossil_print("project-id: %s\n", db_get("project-code", 0));
2061
+ fossil_print("server-id: %s\n", db_get("server-code", 0));
2062
+ zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
2063
+ fossil_print("admin-user: %s (initial password is \"%s\")\n",
2064
+ g.zLogin, zPassword);
2065
+ cache_initialize();
2066
+ g.zLogin = 0;
2067
+ g.userUid = 0;
2068
+ }else{
2069
+ db_open_repository(zRepo);
2070
+ }
2071
+ }
20482072
}
20492073
}
20502074
20512075
/*
20522076
** undocumented format:
@@ -2149,15 +2173,15 @@
21492173
g.fullHttpReply = 1;
21502174
if( g.argc>=5 ){
21512175
g.httpIn = fossil_fopen(g.argv[2], "rb");
21522176
g.httpOut = fossil_fopen(g.argv[3], "wb");
21532177
zIpAddr = g.argv[4];
2154
- find_server_repository(5);
2178
+ find_server_repository(5, 0);
21552179
}else{
21562180
g.httpIn = stdin;
21572181
g.httpOut = stdout;
2158
- find_server_repository(2);
2182
+ find_server_repository(2, 0);
21592183
}
21602184
if( zIpAddr==0 ){
21612185
zIpAddr = cgi_ssh_remote_addr(0);
21622186
if( zIpAddr && zIpAddr[0] ){
21632187
g.fSshClient |= CGI_SSH_CLIENT;
@@ -2200,11 +2224,11 @@
22002224
Th_InitTraceLog();
22012225
login_set_capabilities("sx", 0);
22022226
g.useLocalauth = 1;
22032227
g.httpIn = stdin;
22042228
g.httpOut = stdout;
2205
- find_server_repository(2);
2229
+ find_server_repository(2, 0);
22062230
g.cgiOutput = 1;
22072231
g.fullHttpReply = 1;
22082232
zIpAddr = cgi_ssh_remote_addr(0);
22092233
if( zIpAddr && zIpAddr[0] ){
22102234
g.fSshClient |= CGI_SSH_CLIENT;
@@ -2257,12 +2281,12 @@
22572281
** The "ui" command automatically starts a web browser after initializing
22582282
** the web server. The "ui" command also binds to 127.0.0.1 and so will
22592283
** only process HTTP traffic from the local machine.
22602284
**
22612285
** The REPOSITORY can be a directory (aka folder) that contains one or
2262
-** more repositories with names ending in ".fossil". In this case, the
2263
-** a prefix of the URL pathname is used to search the directory for an
2286
+** more repositories with names ending in ".fossil". In this case, a
2287
+** prefix of the URL pathname is used to search the directory for an
22642288
** appropriate repository. To thwart mischief, the pathname in the URL must
22652289
** contain only alphanumerics, "_", "/", "-", and ".", and no "-" may
22662290
** occur after "/", and every "." must be surrounded on both sides by
22672291
** alphanumerics. Any pathname that does not satisfy these constraints
22682292
** results in a 404 error. Files in REPOSITORY that match the comma-separated
@@ -2279,10 +2303,11 @@
22792303
** connection is from localhost. The "ui" command also enables --repolist
22802304
** by default.
22812305
**
22822306
** Options:
22832307
** --baseurl URL Use URL as the base (useful for reverse proxies)
2308
+** --create Create a new REPOSITORY if it does not already exist
22842309
** --files GLOBLIST Comma-separated list of glob patterns for static files
22852310
** --localauth enable automatic login for requests from localhost
22862311
** --localhost listen on 127.0.0.1 only (always true for "ui")
22872312
** --nojail Drop root privileges but do not enter the chroot jail
22882313
** --notfound URL Redirect
@@ -2308,10 +2333,11 @@
23082333
#endif
23092334
int allowRepoList; /* List repositories on URL "/" */
23102335
const char *zAltBase; /* Argument to the --baseurl option */
23112336
const char *zFileGlob; /* Static content must match this */
23122337
char *zIpAddr = 0; /* Bind to this IP address */
2338
+ int fCreate = 0;
23132339
23142340
#if defined(_WIN32)
23152341
const char *zStopperFile; /* Name of file used to terminate server */
23162342
zStopperFile = find_option("stopper", 0, 1);
23172343
#endif
@@ -2332,10 +2358,11 @@
23322358
Th_InitTraceLog();
23332359
zPort = find_option("port", "P", 1);
23342360
zNotFound = find_option("notfound", 0, 1);
23352361
allowRepoList = find_option("repolist",0,0)!=0;
23362362
zAltBase = find_option("baseurl", 0, 1);
2363
+ fCreate = find_option("create",0,0)!=0;
23372364
if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
23382365
if( zAltBase ){
23392366
set_base_url(zAltBase);
23402367
}
23412368
if( find_option("localhost", 0, 0)!=0 ){
@@ -2350,11 +2377,11 @@
23502377
if( isUiCmd ){
23512378
flags |= HTTP_SERVER_LOCALHOST|HTTP_SERVER_REPOLIST;
23522379
g.useLocalauth = 1;
23532380
allowRepoList = 1;
23542381
}
2355
- find_server_repository(2);
2382
+ find_server_repository(2, fCreate);
23562383
if( zPort ){
23572384
int i;
23582385
for(i=strlen(zPort)-1; i>=0 && zPort[i]!=':'; i--){}
23592386
if( i>0 ){
23602387
zIpAddr = mprintf("%.*s", i, zPort);
@@ -2390,12 +2417,10 @@
23902417
}else{
23912418
zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
23922419
}
23932420
if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
23942421
if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
2395
- }else{
2396
- db_setup_server_and_project_codes(1);
23972422
}
23982423
db_close(1);
23992424
if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
24002425
fossil_fatal("unable to listen on TCP socket %d", iPort);
24012426
}
@@ -2404,11 +2429,11 @@
24042429
g.httpOut = stdout;
24052430
if( g.fHttpTrace || g.fSqlTrace ){
24062431
fprintf(stderr, "====== SERVER pid %d =======\n", getpid());
24072432
}
24082433
g.cgiOutput = 1;
2409
- find_server_repository(2);
2434
+ find_server_repository(2, 0);
24102435
g.zRepositoryName = enter_chroot_jail(g.zRepositoryName, noJail);
24112436
if( flags & HTTP_SERVER_SCGI ){
24122437
cgi_handle_scgi_request();
24132438
}else{
24142439
cgi_handle_http_request(0);
24152440
--- src/main.c
+++ src/main.c
@@ -2034,19 +2034,43 @@
2034 ** Open the repository to be served if it is known. If g.argv[arg] is
2035 ** a directory full of repositories, then set g.zRepositoryName to
2036 ** the name of that directory and the specific repository will be
2037 ** opened later by process_one_web_page() based on the content of
2038 ** the PATH_INFO variable.
 
 
 
2039 */
2040 static void find_server_repository(int arg){
2041 if( g.argc<=arg ){
2042 db_must_be_within_tree();
2043 }else if( file_isdir(g.argv[arg])==1 ){
2044 g.zRepositoryName = mprintf("%s", g.argv[arg]);
2045 file_simplify_name(g.zRepositoryName, -1, 0);
2046 }else{
2047 db_open_repository(g.argv[arg]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2048 }
2049 }
2050
2051 /*
2052 ** undocumented format:
@@ -2149,15 +2173,15 @@
2149 g.fullHttpReply = 1;
2150 if( g.argc>=5 ){
2151 g.httpIn = fossil_fopen(g.argv[2], "rb");
2152 g.httpOut = fossil_fopen(g.argv[3], "wb");
2153 zIpAddr = g.argv[4];
2154 find_server_repository(5);
2155 }else{
2156 g.httpIn = stdin;
2157 g.httpOut = stdout;
2158 find_server_repository(2);
2159 }
2160 if( zIpAddr==0 ){
2161 zIpAddr = cgi_ssh_remote_addr(0);
2162 if( zIpAddr && zIpAddr[0] ){
2163 g.fSshClient |= CGI_SSH_CLIENT;
@@ -2200,11 +2224,11 @@
2200 Th_InitTraceLog();
2201 login_set_capabilities("sx", 0);
2202 g.useLocalauth = 1;
2203 g.httpIn = stdin;
2204 g.httpOut = stdout;
2205 find_server_repository(2);
2206 g.cgiOutput = 1;
2207 g.fullHttpReply = 1;
2208 zIpAddr = cgi_ssh_remote_addr(0);
2209 if( zIpAddr && zIpAddr[0] ){
2210 g.fSshClient |= CGI_SSH_CLIENT;
@@ -2257,12 +2281,12 @@
2257 ** The "ui" command automatically starts a web browser after initializing
2258 ** the web server. The "ui" command also binds to 127.0.0.1 and so will
2259 ** only process HTTP traffic from the local machine.
2260 **
2261 ** The REPOSITORY can be a directory (aka folder) that contains one or
2262 ** more repositories with names ending in ".fossil". In this case, the
2263 ** a prefix of the URL pathname is used to search the directory for an
2264 ** appropriate repository. To thwart mischief, the pathname in the URL must
2265 ** contain only alphanumerics, "_", "/", "-", and ".", and no "-" may
2266 ** occur after "/", and every "." must be surrounded on both sides by
2267 ** alphanumerics. Any pathname that does not satisfy these constraints
2268 ** results in a 404 error. Files in REPOSITORY that match the comma-separated
@@ -2279,10 +2303,11 @@
2279 ** connection is from localhost. The "ui" command also enables --repolist
2280 ** by default.
2281 **
2282 ** Options:
2283 ** --baseurl URL Use URL as the base (useful for reverse proxies)
 
2284 ** --files GLOBLIST Comma-separated list of glob patterns for static files
2285 ** --localauth enable automatic login for requests from localhost
2286 ** --localhost listen on 127.0.0.1 only (always true for "ui")
2287 ** --nojail Drop root privileges but do not enter the chroot jail
2288 ** --notfound URL Redirect
@@ -2308,10 +2333,11 @@
2308 #endif
2309 int allowRepoList; /* List repositories on URL "/" */
2310 const char *zAltBase; /* Argument to the --baseurl option */
2311 const char *zFileGlob; /* Static content must match this */
2312 char *zIpAddr = 0; /* Bind to this IP address */
 
2313
2314 #if defined(_WIN32)
2315 const char *zStopperFile; /* Name of file used to terminate server */
2316 zStopperFile = find_option("stopper", 0, 1);
2317 #endif
@@ -2332,10 +2358,11 @@
2332 Th_InitTraceLog();
2333 zPort = find_option("port", "P", 1);
2334 zNotFound = find_option("notfound", 0, 1);
2335 allowRepoList = find_option("repolist",0,0)!=0;
2336 zAltBase = find_option("baseurl", 0, 1);
 
2337 if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
2338 if( zAltBase ){
2339 set_base_url(zAltBase);
2340 }
2341 if( find_option("localhost", 0, 0)!=0 ){
@@ -2350,11 +2377,11 @@
2350 if( isUiCmd ){
2351 flags |= HTTP_SERVER_LOCALHOST|HTTP_SERVER_REPOLIST;
2352 g.useLocalauth = 1;
2353 allowRepoList = 1;
2354 }
2355 find_server_repository(2);
2356 if( zPort ){
2357 int i;
2358 for(i=strlen(zPort)-1; i>=0 && zPort[i]!=':'; i--){}
2359 if( i>0 ){
2360 zIpAddr = mprintf("%.*s", i, zPort);
@@ -2390,12 +2417,10 @@
2390 }else{
2391 zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
2392 }
2393 if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
2394 if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
2395 }else{
2396 db_setup_server_and_project_codes(1);
2397 }
2398 db_close(1);
2399 if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
2400 fossil_fatal("unable to listen on TCP socket %d", iPort);
2401 }
@@ -2404,11 +2429,11 @@
2404 g.httpOut = stdout;
2405 if( g.fHttpTrace || g.fSqlTrace ){
2406 fprintf(stderr, "====== SERVER pid %d =======\n", getpid());
2407 }
2408 g.cgiOutput = 1;
2409 find_server_repository(2);
2410 g.zRepositoryName = enter_chroot_jail(g.zRepositoryName, noJail);
2411 if( flags & HTTP_SERVER_SCGI ){
2412 cgi_handle_scgi_request();
2413 }else{
2414 cgi_handle_http_request(0);
2415
--- src/main.c
+++ src/main.c
@@ -2034,19 +2034,43 @@
2034 ** Open the repository to be served if it is known. If g.argv[arg] is
2035 ** a directory full of repositories, then set g.zRepositoryName to
2036 ** the name of that directory and the specific repository will be
2037 ** opened later by process_one_web_page() based on the content of
2038 ** the PATH_INFO variable.
2039 **
2040 ** If the fCreate flag is set, then create the repository if it
2041 ** does not already exist.
2042 */
2043 static void find_server_repository(int arg, int fCreate){
2044 if( g.argc<=arg ){
2045 db_must_be_within_tree();
 
 
 
2046 }else{
2047 const char *zRepo = g.argv[arg];
2048 int isDir = file_isdir(zRepo);
2049 if( isDir==1 ){
2050 g.zRepositoryName = mprintf("%s", zRepo);
2051 file_simplify_name(g.zRepositoryName, -1, 0);
2052 }else{
2053 if( isDir==0 && fCreate ){
2054 const char *zPassword;
2055 db_create_repository(zRepo);
2056 db_open_repository(zRepo);
2057 db_begin_transaction();
2058 db_initial_setup(0, "now", g.zLogin);
2059 db_end_transaction(0);
2060 fossil_print("project-id: %s\n", db_get("project-code", 0));
2061 fossil_print("server-id: %s\n", db_get("server-code", 0));
2062 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
2063 fossil_print("admin-user: %s (initial password is \"%s\")\n",
2064 g.zLogin, zPassword);
2065 cache_initialize();
2066 g.zLogin = 0;
2067 g.userUid = 0;
2068 }else{
2069 db_open_repository(zRepo);
2070 }
2071 }
2072 }
2073 }
2074
2075 /*
2076 ** undocumented format:
@@ -2149,15 +2173,15 @@
2173 g.fullHttpReply = 1;
2174 if( g.argc>=5 ){
2175 g.httpIn = fossil_fopen(g.argv[2], "rb");
2176 g.httpOut = fossil_fopen(g.argv[3], "wb");
2177 zIpAddr = g.argv[4];
2178 find_server_repository(5, 0);
2179 }else{
2180 g.httpIn = stdin;
2181 g.httpOut = stdout;
2182 find_server_repository(2, 0);
2183 }
2184 if( zIpAddr==0 ){
2185 zIpAddr = cgi_ssh_remote_addr(0);
2186 if( zIpAddr && zIpAddr[0] ){
2187 g.fSshClient |= CGI_SSH_CLIENT;
@@ -2200,11 +2224,11 @@
2224 Th_InitTraceLog();
2225 login_set_capabilities("sx", 0);
2226 g.useLocalauth = 1;
2227 g.httpIn = stdin;
2228 g.httpOut = stdout;
2229 find_server_repository(2, 0);
2230 g.cgiOutput = 1;
2231 g.fullHttpReply = 1;
2232 zIpAddr = cgi_ssh_remote_addr(0);
2233 if( zIpAddr && zIpAddr[0] ){
2234 g.fSshClient |= CGI_SSH_CLIENT;
@@ -2257,12 +2281,12 @@
2281 ** The "ui" command automatically starts a web browser after initializing
2282 ** the web server. The "ui" command also binds to 127.0.0.1 and so will
2283 ** only process HTTP traffic from the local machine.
2284 **
2285 ** The REPOSITORY can be a directory (aka folder) that contains one or
2286 ** more repositories with names ending in ".fossil". In this case, a
2287 ** prefix of the URL pathname is used to search the directory for an
2288 ** appropriate repository. To thwart mischief, the pathname in the URL must
2289 ** contain only alphanumerics, "_", "/", "-", and ".", and no "-" may
2290 ** occur after "/", and every "." must be surrounded on both sides by
2291 ** alphanumerics. Any pathname that does not satisfy these constraints
2292 ** results in a 404 error. Files in REPOSITORY that match the comma-separated
@@ -2279,10 +2303,11 @@
2303 ** connection is from localhost. The "ui" command also enables --repolist
2304 ** by default.
2305 **
2306 ** Options:
2307 ** --baseurl URL Use URL as the base (useful for reverse proxies)
2308 ** --create Create a new REPOSITORY if it does not already exist
2309 ** --files GLOBLIST Comma-separated list of glob patterns for static files
2310 ** --localauth enable automatic login for requests from localhost
2311 ** --localhost listen on 127.0.0.1 only (always true for "ui")
2312 ** --nojail Drop root privileges but do not enter the chroot jail
2313 ** --notfound URL Redirect
@@ -2308,10 +2333,11 @@
2333 #endif
2334 int allowRepoList; /* List repositories on URL "/" */
2335 const char *zAltBase; /* Argument to the --baseurl option */
2336 const char *zFileGlob; /* Static content must match this */
2337 char *zIpAddr = 0; /* Bind to this IP address */
2338 int fCreate = 0;
2339
2340 #if defined(_WIN32)
2341 const char *zStopperFile; /* Name of file used to terminate server */
2342 zStopperFile = find_option("stopper", 0, 1);
2343 #endif
@@ -2332,10 +2358,11 @@
2358 Th_InitTraceLog();
2359 zPort = find_option("port", "P", 1);
2360 zNotFound = find_option("notfound", 0, 1);
2361 allowRepoList = find_option("repolist",0,0)!=0;
2362 zAltBase = find_option("baseurl", 0, 1);
2363 fCreate = find_option("create",0,0)!=0;
2364 if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
2365 if( zAltBase ){
2366 set_base_url(zAltBase);
2367 }
2368 if( find_option("localhost", 0, 0)!=0 ){
@@ -2350,11 +2377,11 @@
2377 if( isUiCmd ){
2378 flags |= HTTP_SERVER_LOCALHOST|HTTP_SERVER_REPOLIST;
2379 g.useLocalauth = 1;
2380 allowRepoList = 1;
2381 }
2382 find_server_repository(2, fCreate);
2383 if( zPort ){
2384 int i;
2385 for(i=strlen(zPort)-1; i>=0 && zPort[i]!=':'; i--){}
2386 if( i>0 ){
2387 zIpAddr = mprintf("%.*s", i, zPort);
@@ -2390,12 +2417,10 @@
2417 }else{
2418 zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
2419 }
2420 if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
2421 if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
 
 
2422 }
2423 db_close(1);
2424 if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
2425 fossil_fatal("unable to listen on TCP socket %d", iPort);
2426 }
@@ -2404,11 +2429,11 @@
2429 g.httpOut = stdout;
2430 if( g.fHttpTrace || g.fSqlTrace ){
2431 fprintf(stderr, "====== SERVER pid %d =======\n", getpid());
2432 }
2433 g.cgiOutput = 1;
2434 find_server_repository(2, 0);
2435 g.zRepositoryName = enter_chroot_jail(g.zRepositoryName, noJail);
2436 if( flags & HTTP_SERVER_SCGI ){
2437 cgi_handle_scgi_request();
2438 }else{
2439 cgi_handle_http_request(0);
2440
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -591,11 +591,11 @@
591591
#### The directories where the OpenSSL include and library files are located.
592592
# The recommended usage here is to use the Sysinternals junction tool
593593
# to create a hard link between an "openssl-1.x" sub-directory of the
594594
# Fossil source code directory and the target OpenSSL source directory.
595595
#
596
-OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2
596
+OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2a
597597
OPENSSLINCDIR = $(OPENSSLDIR)/include
598598
OPENSSLLIBDIR = $(OPENSSLDIR)
599599
600600
#### Either the directory where the Tcl library is installed or the Tcl
601601
# source code directory resides (depending on the value of the macro
@@ -1333,11 +1333,11 @@
13331333
13341334
# Uncomment to enable Tcl support
13351335
# FOSSIL_ENABLE_TCL = 1
13361336
13371337
!ifdef FOSSIL_ENABLE_SSL
1338
-SSLDIR = $(B)\compat\openssl-1.0.2
1338
+SSLDIR = $(B)\compat\openssl-1.0.2a
13391339
SSLINCDIR = $(SSLDIR)\inc32
13401340
SSLLIBDIR = $(SSLDIR)\out32
13411341
SSLLFLAGS = /nologo /opt:ref /debug
13421342
SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
13431343
!if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64"
13441344
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -591,11 +591,11 @@
591 #### The directories where the OpenSSL include and library files are located.
592 # The recommended usage here is to use the Sysinternals junction tool
593 # to create a hard link between an "openssl-1.x" sub-directory of the
594 # Fossil source code directory and the target OpenSSL source directory.
595 #
596 OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2
597 OPENSSLINCDIR = $(OPENSSLDIR)/include
598 OPENSSLLIBDIR = $(OPENSSLDIR)
599
600 #### Either the directory where the Tcl library is installed or the Tcl
601 # source code directory resides (depending on the value of the macro
@@ -1333,11 +1333,11 @@
1333
1334 # Uncomment to enable Tcl support
1335 # FOSSIL_ENABLE_TCL = 1
1336
1337 !ifdef FOSSIL_ENABLE_SSL
1338 SSLDIR = $(B)\compat\openssl-1.0.2
1339 SSLINCDIR = $(SSLDIR)\inc32
1340 SSLLIBDIR = $(SSLDIR)\out32
1341 SSLLFLAGS = /nologo /opt:ref /debug
1342 SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
1343 !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64"
1344
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -591,11 +591,11 @@
591 #### The directories where the OpenSSL include and library files are located.
592 # The recommended usage here is to use the Sysinternals junction tool
593 # to create a hard link between an "openssl-1.x" sub-directory of the
594 # Fossil source code directory and the target OpenSSL source directory.
595 #
596 OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2a
597 OPENSSLINCDIR = $(OPENSSLDIR)/include
598 OPENSSLLIBDIR = $(OPENSSLDIR)
599
600 #### Either the directory where the Tcl library is installed or the Tcl
601 # source code directory resides (depending on the value of the macro
@@ -1333,11 +1333,11 @@
1333
1334 # Uncomment to enable Tcl support
1335 # FOSSIL_ENABLE_TCL = 1
1336
1337 !ifdef FOSSIL_ENABLE_SSL
1338 SSLDIR = $(B)\compat\openssl-1.0.2a
1339 SSLINCDIR = $(SSLDIR)\inc32
1340 SSLLIBDIR = $(SSLDIR)\out32
1341 SSLLFLAGS = /nologo /opt:ref /debug
1342 SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
1343 !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64"
1344
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -591,11 +591,11 @@
591591
#### The directories where the OpenSSL include and library files are located.
592592
# The recommended usage here is to use the Sysinternals junction tool
593593
# to create a hard link between an "openssl-1.x" sub-directory of the
594594
# Fossil source code directory and the target OpenSSL source directory.
595595
#
596
-OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2
596
+OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2a
597597
OPENSSLINCDIR = $(OPENSSLDIR)/include
598598
OPENSSLLIBDIR = $(OPENSSLDIR)
599599
600600
#### Either the directory where the Tcl library is installed or the Tcl
601601
# source code directory resides (depending on the value of the macro
@@ -1333,11 +1333,11 @@
13331333
13341334
# Uncomment to enable Tcl support
13351335
# FOSSIL_ENABLE_TCL = 1
13361336
13371337
!ifdef FOSSIL_ENABLE_SSL
1338
-SSLDIR = $(B)\compat\openssl-1.0.2
1338
+SSLDIR = $(B)\compat\openssl-1.0.2a
13391339
SSLINCDIR = $(SSLDIR)\inc32
13401340
SSLLIBDIR = $(SSLDIR)\out32
13411341
SSLLFLAGS = /nologo /opt:ref /debug
13421342
SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
13431343
!if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64"
13441344
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -591,11 +591,11 @@
591 #### The directories where the OpenSSL include and library files are located.
592 # The recommended usage here is to use the Sysinternals junction tool
593 # to create a hard link between an "openssl-1.x" sub-directory of the
594 # Fossil source code directory and the target OpenSSL source directory.
595 #
596 OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2
597 OPENSSLINCDIR = $(OPENSSLDIR)/include
598 OPENSSLLIBDIR = $(OPENSSLDIR)
599
600 #### Either the directory where the Tcl library is installed or the Tcl
601 # source code directory resides (depending on the value of the macro
@@ -1333,11 +1333,11 @@
1333
1334 # Uncomment to enable Tcl support
1335 # FOSSIL_ENABLE_TCL = 1
1336
1337 !ifdef FOSSIL_ENABLE_SSL
1338 SSLDIR = $(B)\compat\openssl-1.0.2
1339 SSLINCDIR = $(SSLDIR)\inc32
1340 SSLLIBDIR = $(SSLDIR)\out32
1341 SSLLFLAGS = /nologo /opt:ref /debug
1342 SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
1343 !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64"
1344
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -591,11 +591,11 @@
591 #### The directories where the OpenSSL include and library files are located.
592 # The recommended usage here is to use the Sysinternals junction tool
593 # to create a hard link between an "openssl-1.x" sub-directory of the
594 # Fossil source code directory and the target OpenSSL source directory.
595 #
596 OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2a
597 OPENSSLINCDIR = $(OPENSSLDIR)/include
598 OPENSSLLIBDIR = $(OPENSSLDIR)
599
600 #### Either the directory where the Tcl library is installed or the Tcl
601 # source code directory resides (depending on the value of the macro
@@ -1333,11 +1333,11 @@
1333
1334 # Uncomment to enable Tcl support
1335 # FOSSIL_ENABLE_TCL = 1
1336
1337 !ifdef FOSSIL_ENABLE_SSL
1338 SSLDIR = $(B)\compat\openssl-1.0.2a
1339 SSLINCDIR = $(SSLDIR)\inc32
1340 SSLLIBDIR = $(SSLDIR)\out32
1341 SSLLFLAGS = /nologo /opt:ref /debug
1342 SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
1343 !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64"
1344
+1 -1
--- src/rebuild.c
+++ src/rebuild.c
@@ -953,11 +953,11 @@
953953
/* We should be done with options.. */
954954
verify_all_options();
955955
956956
db_open_config(0);
957957
db_begin_transaction();
958
- db_initial_setup(0, 0, 0, 1);
958
+ db_initial_setup(0, 0, 0);
959959
960960
fossil_print("Reading files from directory \"%s\"...\n", g.argv[3]);
961961
recon_read_dir(g.argv[3]);
962962
fossil_print("\nBuilding the Fossil repository...\n");
963963
964964
--- src/rebuild.c
+++ src/rebuild.c
@@ -953,11 +953,11 @@
953 /* We should be done with options.. */
954 verify_all_options();
955
956 db_open_config(0);
957 db_begin_transaction();
958 db_initial_setup(0, 0, 0, 1);
959
960 fossil_print("Reading files from directory \"%s\"...\n", g.argv[3]);
961 recon_read_dir(g.argv[3]);
962 fossil_print("\nBuilding the Fossil repository...\n");
963
964
--- src/rebuild.c
+++ src/rebuild.c
@@ -953,11 +953,11 @@
953 /* We should be done with options.. */
954 verify_all_options();
955
956 db_open_config(0);
957 db_begin_transaction();
958 db_initial_setup(0, 0, 0);
959
960 fossil_print("Reading files from directory \"%s\"...\n", g.argv[3]);
961 recon_read_dir(g.argv[3]);
962 fossil_print("\nBuilding the Fossil repository...\n");
963
964
+46 -19
--- src/shell.c
+++ src/shell.c
@@ -22,10 +22,17 @@
2222
*/
2323
#if defined(INCLUDE_MSVC_H)
2424
#include "msvc.h"
2525
#endif
2626
27
+/*
28
+** No support for loadable extensions in VxWorks.
29
+*/
30
+#if defined(_WRS_KERNEL) && !SQLITE_OMIT_LOAD_EXTENSION
31
+# define SQLITE_OMIT_LOAD_EXTENSION 1
32
+#endif
33
+
2734
/*
2835
** Enable large-file support for fopen() and friends on unix.
2936
*/
3037
#ifndef SQLITE_DISABLE_LFS
3138
# define _LARGE_FILE 1
@@ -105,14 +112,19 @@
105112
#else
106113
/* Make sure isatty() has a prototype.
107114
*/
108115
extern int isatty(int);
109116
110
-/* popen and pclose are not C89 functions and so are sometimes omitted from
111
-** the <stdio.h> header */
112
-extern FILE *popen(const char*,const char*);
113
-extern int pclose(FILE*);
117
+#if !defined(__RTP__) && !defined(_WRS_KERNEL)
118
+ /* popen and pclose are not C89 functions and so are sometimes omitted from
119
+ ** the <stdio.h> header */
120
+ extern FILE *popen(const char*,const char*);
121
+ extern int pclose(FILE*);
122
+#else
123
+# define SQLITE_OMIT_POPEN 1
124
+#endif
125
+
114126
#endif
115127
116128
#if defined(_WIN32_WCE)
117129
/* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty()
118130
* thus we always assume that we have a console. That can be
@@ -163,14 +175,22 @@
163175
t = (sqlite3_int64)(r*86400000.0);
164176
}
165177
return t;
166178
}
167179
168
-#if !defined(_WIN32) && !defined(WIN32) && !defined(_WRS_KERNEL) \
169
- && !defined(__minux)
180
+#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
170181
#include <sys/time.h>
171182
#include <sys/resource.h>
183
+
184
+/* VxWorks does not support getrusage() as far as we can determine */
185
+#if defined(_WRS_KERNEL) || defined(__RTP__)
186
+struct rusage {
187
+ struct timeval ru_utime; /* user CPU time used */
188
+ struct timeval ru_stime; /* system CPU time used */
189
+};
190
+#define getrusage(A,B) memset(B,0,sizeof(*B))
191
+#endif
172192
173193
/* Saved resource information for the beginning of an operation */
174194
static struct rusage sBegin; /* CPU time at start */
175195
static sqlite3_int64 iBegin; /* Wall-clock time at start */
176196
@@ -193,12 +213,12 @@
193213
/*
194214
** Print the timing results.
195215
*/
196216
static void endTimer(void){
197217
if( enableTimer ){
198
- struct rusage sEnd;
199218
sqlite3_int64 iEnd = timeOfDay();
219
+ struct rusage sEnd;
200220
getrusage(RUSAGE_SELF, &sEnd);
201221
printf("Run Time: real %.3f user %f sys %f\n",
202222
(iEnd - iBegin)*0.001,
203223
timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
204224
timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
@@ -2437,11 +2457,13 @@
24372457
/*
24382458
** Change the output file back to stdout
24392459
*/
24402460
static void output_reset(ShellState *p){
24412461
if( p->outfile[0]=='|' ){
2462
+#ifndef SQLITE_OMIT_POPEN
24422463
pclose(p->out);
2464
+#endif
24432465
}else{
24442466
output_file_close(p->out);
24452467
}
24462468
p->outfile[0] = 0;
24472469
p->out = stdout;
@@ -2930,13 +2952,18 @@
29302952
return 1;
29312953
}
29322954
sCtx.zFile = zFile;
29332955
sCtx.nLine = 1;
29342956
if( sCtx.zFile[0]=='|' ){
2957
+#ifdef SQLITE_OMIT_POPEN
2958
+ fprintf(stderr, "Error: pipes are not supporte in this OS\n");
2959
+ return 1;
2960
+#else
29352961
sCtx.in = popen(sCtx.zFile+1, "r");
29362962
sCtx.zFile = "<pipe>";
29372963
xCloser = pclose;
2964
+#endif
29382965
}else{
29392966
sCtx.in = fopen(sCtx.zFile, "rb");
29402967
xCloser = fclose;
29412968
}
29422969
if( p->mode==MODE_Ascii ){
@@ -3255,18 +3282,24 @@
32553282
}else{
32563283
p->outCount = 0;
32573284
}
32583285
output_reset(p);
32593286
if( zFile[0]=='|' ){
3287
+#ifdef SQLITE_OMIT_POPEN
3288
+ fprintf(stderr,"Error: pipes are not supported in this OS\n");
3289
+ rc = 1;
3290
+ p->out = stdout;
3291
+#else
32603292
p->out = popen(zFile + 1, "w");
32613293
if( p->out==0 ){
32623294
fprintf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
32633295
p->out = stdout;
32643296
rc = 1;
32653297
}else{
32663298
sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
32673299
}
3300
+#endif
32683301
}else{
32693302
p->out = output_file_open(zFile);
32703303
if( p->out==0 ){
32713304
if( strcmp(zFile,"off")!=0 ){
32723305
fprintf(stderr,"Error: cannot write to \"%s\"\n", zFile);
@@ -4187,27 +4220,25 @@
41874220
** Read input from the file given by sqliterc_override. Or if that
41884221
** parameter is NULL, take input from ~/.sqliterc
41894222
**
41904223
** Returns the number of errors.
41914224
*/
4192
-static int process_sqliterc(
4225
+static void process_sqliterc(
41934226
ShellState *p, /* Configuration data */
41944227
const char *sqliterc_override /* Name of config file. NULL to use default */
41954228
){
41964229
char *home_dir = NULL;
41974230
const char *sqliterc = sqliterc_override;
41984231
char *zBuf = 0;
41994232
FILE *in = NULL;
4200
- int rc = 0;
42014233
42024234
if (sqliterc == NULL) {
42034235
home_dir = find_home_dir();
42044236
if( home_dir==0 ){
4205
-#if !defined(__RTP__) && !defined(_WRS_KERNEL)
4206
- fprintf(stderr,"%s: Error: cannot locate your home directory\n", Argv0);
4207
-#endif
4208
- return 1;
4237
+ fprintf(stderr, "-- warning: cannot find home directory;"
4238
+ " cannot read ~/.sqliterc\n");
4239
+ return;
42094240
}
42104241
sqlite3_initialize();
42114242
zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
42124243
sqliterc = zBuf;
42134244
}
@@ -4214,15 +4245,14 @@
42144245
in = fopen(sqliterc,"rb");
42154246
if( in ){
42164247
if( stdin_is_interactive ){
42174248
fprintf(stderr,"-- Loading resources from %s\n",sqliterc);
42184249
}
4219
- rc = process_input(p,in);
4250
+ process_input(p,in);
42204251
fclose(in);
42214252
}
42224253
sqlite3_free(zBuf);
4223
- return rc;
42244254
}
42254255
42264256
/*
42274257
** Show available command line options
42284258
*/
@@ -4494,14 +4524,11 @@
44944524
44954525
/* Process the initialization file if there is one. If no -init option
44964526
** is given on the command line, look for a file named ~/.sqliterc and
44974527
** try to process it.
44984528
*/
4499
- rc = process_sqliterc(&data,zInitFile);
4500
- if( rc>0 ){
4501
- return rc;
4502
- }
4529
+ process_sqliterc(&data,zInitFile);
45034530
45044531
/* Make a second pass through the command-line argument and set
45054532
** options. This second pass is delayed until after the initialization
45064533
** file is processed so that the command-line arguments will override
45074534
** settings in the initialization file.
45084535
--- src/shell.c
+++ src/shell.c
@@ -22,10 +22,17 @@
22 */
23 #if defined(INCLUDE_MSVC_H)
24 #include "msvc.h"
25 #endif
26
 
 
 
 
 
 
 
27 /*
28 ** Enable large-file support for fopen() and friends on unix.
29 */
30 #ifndef SQLITE_DISABLE_LFS
31 # define _LARGE_FILE 1
@@ -105,14 +112,19 @@
105 #else
106 /* Make sure isatty() has a prototype.
107 */
108 extern int isatty(int);
109
110 /* popen and pclose are not C89 functions and so are sometimes omitted from
111 ** the <stdio.h> header */
112 extern FILE *popen(const char*,const char*);
113 extern int pclose(FILE*);
 
 
 
 
 
114 #endif
115
116 #if defined(_WIN32_WCE)
117 /* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty()
118 * thus we always assume that we have a console. That can be
@@ -163,14 +175,22 @@
163 t = (sqlite3_int64)(r*86400000.0);
164 }
165 return t;
166 }
167
168 #if !defined(_WIN32) && !defined(WIN32) && !defined(_WRS_KERNEL) \
169 && !defined(__minux)
170 #include <sys/time.h>
171 #include <sys/resource.h>
 
 
 
 
 
 
 
 
 
172
173 /* Saved resource information for the beginning of an operation */
174 static struct rusage sBegin; /* CPU time at start */
175 static sqlite3_int64 iBegin; /* Wall-clock time at start */
176
@@ -193,12 +213,12 @@
193 /*
194 ** Print the timing results.
195 */
196 static void endTimer(void){
197 if( enableTimer ){
198 struct rusage sEnd;
199 sqlite3_int64 iEnd = timeOfDay();
 
200 getrusage(RUSAGE_SELF, &sEnd);
201 printf("Run Time: real %.3f user %f sys %f\n",
202 (iEnd - iBegin)*0.001,
203 timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
204 timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
@@ -2437,11 +2457,13 @@
2437 /*
2438 ** Change the output file back to stdout
2439 */
2440 static void output_reset(ShellState *p){
2441 if( p->outfile[0]=='|' ){
 
2442 pclose(p->out);
 
2443 }else{
2444 output_file_close(p->out);
2445 }
2446 p->outfile[0] = 0;
2447 p->out = stdout;
@@ -2930,13 +2952,18 @@
2930 return 1;
2931 }
2932 sCtx.zFile = zFile;
2933 sCtx.nLine = 1;
2934 if( sCtx.zFile[0]=='|' ){
 
 
 
 
2935 sCtx.in = popen(sCtx.zFile+1, "r");
2936 sCtx.zFile = "<pipe>";
2937 xCloser = pclose;
 
2938 }else{
2939 sCtx.in = fopen(sCtx.zFile, "rb");
2940 xCloser = fclose;
2941 }
2942 if( p->mode==MODE_Ascii ){
@@ -3255,18 +3282,24 @@
3255 }else{
3256 p->outCount = 0;
3257 }
3258 output_reset(p);
3259 if( zFile[0]=='|' ){
 
 
 
 
 
3260 p->out = popen(zFile + 1, "w");
3261 if( p->out==0 ){
3262 fprintf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
3263 p->out = stdout;
3264 rc = 1;
3265 }else{
3266 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
3267 }
 
3268 }else{
3269 p->out = output_file_open(zFile);
3270 if( p->out==0 ){
3271 if( strcmp(zFile,"off")!=0 ){
3272 fprintf(stderr,"Error: cannot write to \"%s\"\n", zFile);
@@ -4187,27 +4220,25 @@
4187 ** Read input from the file given by sqliterc_override. Or if that
4188 ** parameter is NULL, take input from ~/.sqliterc
4189 **
4190 ** Returns the number of errors.
4191 */
4192 static int process_sqliterc(
4193 ShellState *p, /* Configuration data */
4194 const char *sqliterc_override /* Name of config file. NULL to use default */
4195 ){
4196 char *home_dir = NULL;
4197 const char *sqliterc = sqliterc_override;
4198 char *zBuf = 0;
4199 FILE *in = NULL;
4200 int rc = 0;
4201
4202 if (sqliterc == NULL) {
4203 home_dir = find_home_dir();
4204 if( home_dir==0 ){
4205 #if !defined(__RTP__) && !defined(_WRS_KERNEL)
4206 fprintf(stderr,"%s: Error: cannot locate your home directory\n", Argv0);
4207 #endif
4208 return 1;
4209 }
4210 sqlite3_initialize();
4211 zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
4212 sqliterc = zBuf;
4213 }
@@ -4214,15 +4245,14 @@
4214 in = fopen(sqliterc,"rb");
4215 if( in ){
4216 if( stdin_is_interactive ){
4217 fprintf(stderr,"-- Loading resources from %s\n",sqliterc);
4218 }
4219 rc = process_input(p,in);
4220 fclose(in);
4221 }
4222 sqlite3_free(zBuf);
4223 return rc;
4224 }
4225
4226 /*
4227 ** Show available command line options
4228 */
@@ -4494,14 +4524,11 @@
4494
4495 /* Process the initialization file if there is one. If no -init option
4496 ** is given on the command line, look for a file named ~/.sqliterc and
4497 ** try to process it.
4498 */
4499 rc = process_sqliterc(&data,zInitFile);
4500 if( rc>0 ){
4501 return rc;
4502 }
4503
4504 /* Make a second pass through the command-line argument and set
4505 ** options. This second pass is delayed until after the initialization
4506 ** file is processed so that the command-line arguments will override
4507 ** settings in the initialization file.
4508
--- src/shell.c
+++ src/shell.c
@@ -22,10 +22,17 @@
22 */
23 #if defined(INCLUDE_MSVC_H)
24 #include "msvc.h"
25 #endif
26
27 /*
28 ** No support for loadable extensions in VxWorks.
29 */
30 #if defined(_WRS_KERNEL) && !SQLITE_OMIT_LOAD_EXTENSION
31 # define SQLITE_OMIT_LOAD_EXTENSION 1
32 #endif
33
34 /*
35 ** Enable large-file support for fopen() and friends on unix.
36 */
37 #ifndef SQLITE_DISABLE_LFS
38 # define _LARGE_FILE 1
@@ -105,14 +112,19 @@
112 #else
113 /* Make sure isatty() has a prototype.
114 */
115 extern int isatty(int);
116
117 #if !defined(__RTP__) && !defined(_WRS_KERNEL)
118 /* popen and pclose are not C89 functions and so are sometimes omitted from
119 ** the <stdio.h> header */
120 extern FILE *popen(const char*,const char*);
121 extern int pclose(FILE*);
122 #else
123 # define SQLITE_OMIT_POPEN 1
124 #endif
125
126 #endif
127
128 #if defined(_WIN32_WCE)
129 /* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty()
130 * thus we always assume that we have a console. That can be
@@ -163,14 +175,22 @@
175 t = (sqlite3_int64)(r*86400000.0);
176 }
177 return t;
178 }
179
180 #if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
 
181 #include <sys/time.h>
182 #include <sys/resource.h>
183
184 /* VxWorks does not support getrusage() as far as we can determine */
185 #if defined(_WRS_KERNEL) || defined(__RTP__)
186 struct rusage {
187 struct timeval ru_utime; /* user CPU time used */
188 struct timeval ru_stime; /* system CPU time used */
189 };
190 #define getrusage(A,B) memset(B,0,sizeof(*B))
191 #endif
192
193 /* Saved resource information for the beginning of an operation */
194 static struct rusage sBegin; /* CPU time at start */
195 static sqlite3_int64 iBegin; /* Wall-clock time at start */
196
@@ -193,12 +213,12 @@
213 /*
214 ** Print the timing results.
215 */
216 static void endTimer(void){
217 if( enableTimer ){
 
218 sqlite3_int64 iEnd = timeOfDay();
219 struct rusage sEnd;
220 getrusage(RUSAGE_SELF, &sEnd);
221 printf("Run Time: real %.3f user %f sys %f\n",
222 (iEnd - iBegin)*0.001,
223 timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
224 timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
@@ -2437,11 +2457,13 @@
2457 /*
2458 ** Change the output file back to stdout
2459 */
2460 static void output_reset(ShellState *p){
2461 if( p->outfile[0]=='|' ){
2462 #ifndef SQLITE_OMIT_POPEN
2463 pclose(p->out);
2464 #endif
2465 }else{
2466 output_file_close(p->out);
2467 }
2468 p->outfile[0] = 0;
2469 p->out = stdout;
@@ -2930,13 +2952,18 @@
2952 return 1;
2953 }
2954 sCtx.zFile = zFile;
2955 sCtx.nLine = 1;
2956 if( sCtx.zFile[0]=='|' ){
2957 #ifdef SQLITE_OMIT_POPEN
2958 fprintf(stderr, "Error: pipes are not supporte in this OS\n");
2959 return 1;
2960 #else
2961 sCtx.in = popen(sCtx.zFile+1, "r");
2962 sCtx.zFile = "<pipe>";
2963 xCloser = pclose;
2964 #endif
2965 }else{
2966 sCtx.in = fopen(sCtx.zFile, "rb");
2967 xCloser = fclose;
2968 }
2969 if( p->mode==MODE_Ascii ){
@@ -3255,18 +3282,24 @@
3282 }else{
3283 p->outCount = 0;
3284 }
3285 output_reset(p);
3286 if( zFile[0]=='|' ){
3287 #ifdef SQLITE_OMIT_POPEN
3288 fprintf(stderr,"Error: pipes are not supported in this OS\n");
3289 rc = 1;
3290 p->out = stdout;
3291 #else
3292 p->out = popen(zFile + 1, "w");
3293 if( p->out==0 ){
3294 fprintf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
3295 p->out = stdout;
3296 rc = 1;
3297 }else{
3298 sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
3299 }
3300 #endif
3301 }else{
3302 p->out = output_file_open(zFile);
3303 if( p->out==0 ){
3304 if( strcmp(zFile,"off")!=0 ){
3305 fprintf(stderr,"Error: cannot write to \"%s\"\n", zFile);
@@ -4187,27 +4220,25 @@
4220 ** Read input from the file given by sqliterc_override. Or if that
4221 ** parameter is NULL, take input from ~/.sqliterc
4222 **
4223 ** Returns the number of errors.
4224 */
4225 static void process_sqliterc(
4226 ShellState *p, /* Configuration data */
4227 const char *sqliterc_override /* Name of config file. NULL to use default */
4228 ){
4229 char *home_dir = NULL;
4230 const char *sqliterc = sqliterc_override;
4231 char *zBuf = 0;
4232 FILE *in = NULL;
 
4233
4234 if (sqliterc == NULL) {
4235 home_dir = find_home_dir();
4236 if( home_dir==0 ){
4237 fprintf(stderr, "-- warning: cannot find home directory;"
4238 " cannot read ~/.sqliterc\n");
4239 return;
 
4240 }
4241 sqlite3_initialize();
4242 zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
4243 sqliterc = zBuf;
4244 }
@@ -4214,15 +4245,14 @@
4245 in = fopen(sqliterc,"rb");
4246 if( in ){
4247 if( stdin_is_interactive ){
4248 fprintf(stderr,"-- Loading resources from %s\n",sqliterc);
4249 }
4250 process_input(p,in);
4251 fclose(in);
4252 }
4253 sqlite3_free(zBuf);
 
4254 }
4255
4256 /*
4257 ** Show available command line options
4258 */
@@ -4494,14 +4524,11 @@
4524
4525 /* Process the initialization file if there is one. If no -init option
4526 ** is given on the command line, look for a file named ~/.sqliterc and
4527 ** try to process it.
4528 */
4529 process_sqliterc(&data,zInitFile);
 
 
 
4530
4531 /* Make a second pass through the command-line argument and set
4532 ** options. This second pass is delayed until after the initialization
4533 ** file is processed so that the command-line arguments will override
4534 ** settings in the initialization file.
4535
+481 -221
--- 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.8.8. By combining all the individual C code files into this
3
+** version 3.8.9. 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.
@@ -88,10 +88,48 @@
8888
#endif /* _MSVC_H_ */
8989
9090
/************** End of msvc.h ************************************************/
9191
/************** Continuing where we left off in sqliteInt.h ******************/
9292
93
+/*
94
+** Special setup for VxWorks
95
+*/
96
+/************** Include vxworks.h in the middle of sqliteInt.h ***************/
97
+/************** Begin file vxworks.h *****************************************/
98
+/*
99
+** 2015-03-02
100
+**
101
+** The author disclaims copyright to this source code. In place of
102
+** a legal notice, here is a blessing:
103
+**
104
+** May you do good and not evil.
105
+** May you find forgiveness for yourself and forgive others.
106
+** May you share freely, never taking more than you give.
107
+**
108
+******************************************************************************
109
+**
110
+** This file contains code that is specific to Wind River's VxWorks
111
+*/
112
+#if defined(__RTP__) || defined(_WRS_KERNEL)
113
+/* This is VxWorks. Set up things specially for that OS
114
+*/
115
+#include <vxWorks.h>
116
+#include <pthread.h> /* amalgamator: dontcache */
117
+#define OS_VXWORKS 1
118
+#define SQLITE_OS_OTHER 0
119
+#define SQLITE_HOMEGROWN_RECURSIVE_MUTEX 1
120
+#define SQLITE_OMIT_LOAD_EXTENSION 1
121
+#define SQLITE_ENABLE_LOCKING_STYLE 0
122
+#define HAVE_UTIME 1
123
+#else
124
+/* This is not VxWorks. */
125
+#define OS_VXWORKS 0
126
+#endif /* defined(_WRS_KERNEL) */
127
+
128
+/************** End of vxworks.h *********************************************/
129
+/************** Continuing where we left off in sqliteInt.h ******************/
130
+
93131
/*
94132
** These #defines should enable >2GB file support on POSIX if the
95133
** underlying operating system supports it. If the OS lacks
96134
** large file support, or if the OS is windows, these should be no-ops.
97135
**
@@ -276,13 +314,13 @@
276314
**
277315
** See also: [sqlite3_libversion()],
278316
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
279317
** [sqlite_version()] and [sqlite_source_id()].
280318
*/
281
-#define SQLITE_VERSION "3.8.8"
282
-#define SQLITE_VERSION_NUMBER 3008008
283
-#define SQLITE_SOURCE_ID "2015-02-25 14:25:31 6d132e7a224ee68b5cefe9222944aac5760ffc20"
319
+#define SQLITE_VERSION "3.8.9"
320
+#define SQLITE_VERSION_NUMBER 3008009
321
+#define SQLITE_SOURCE_ID "2015-03-09 10:40:48 e5da5e7d5dc5a3438ced23f1ee83e695abc29c45"
284322
285323
/*
286324
** CAPI3REF: Run-Time Library Version Numbers
287325
** KEYWORDS: sqlite3_version, sqlite3_sourceid
288326
**
@@ -925,18 +963,20 @@
925963
**
926964
** These integer constants are opcodes for the xFileControl method
927965
** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
928966
** interface.
929967
**
968
+** <ul>
969
+** <li>[[SQLITE_FCNTL_LOCKSTATE]]
930970
** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This
931971
** opcode causes the xFileControl method to write the current state of
932972
** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED],
933973
** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])
934974
** into an integer that the pArg argument points to. This capability
935
-** is used during testing and only needs to be supported when SQLITE_TEST
936
-** is defined.
937
-** <ul>
975
+** is used during testing and is only available when the SQLITE_TEST
976
+** compile-time option is used.
977
+**
938978
** <li>[[SQLITE_FCNTL_SIZE_HINT]]
939979
** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
940980
** layer a hint of how large the database file will grow to be during the
941981
** current transaction. This hint is not guaranteed to be accurate but it
942982
** is often close. The underlying VFS might choose to preallocate database
@@ -1057,11 +1097,13 @@
10571097
** the error message if the pragma fails. ^If the
10581098
** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal
10591099
** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA]
10601100
** file control returns [SQLITE_OK], then the parser assumes that the
10611101
** VFS has handled the PRAGMA itself and the parser generates a no-op
1062
-** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns
1102
+** prepared statement if result string is NULL, or that returns a copy
1103
+** of the result string if the string is non-NULL.
1104
+** ^If the [SQLITE_FCNTL_PRAGMA] file control returns
10631105
** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
10641106
** that the VFS encountered an error while handling the [PRAGMA] and the
10651107
** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
10661108
** file control occurs at the beginning of pragma statement analysis and so
10671109
** it is able to override built-in [PRAGMA] statements.
@@ -1916,11 +1958,10 @@
19161958
** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE
19171959
** <dd>^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is
19181960
** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro
19191961
** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value
19201962
** that specifies the maximum size of the created heap.
1921
-** </dl>
19221963
**
19231964
** [[SQLITE_CONFIG_PCACHE_HDRSZ]]
19241965
** <dt>SQLITE_CONFIG_PCACHE_HDRSZ
19251966
** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which
19261967
** is a pointer to an integer and writes into that integer the number of extra
@@ -3356,20 +3397,18 @@
33563397
** The second argument, "zSql", is the statement to be compiled, encoded
33573398
** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2()
33583399
** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2()
33593400
** use UTF-16.
33603401
**
3361
-** ^If the nByte argument is less than zero, then zSql is read up to the
3362
-** first zero terminator. ^If nByte is non-negative, then it is the maximum
3363
-** number of bytes read from zSql. ^When nByte is non-negative, the
3364
-** zSql string ends at either the first '\000' or '\u0000' character or
3365
-** the nByte-th byte, whichever comes first. If the caller knows
3366
-** that the supplied string is nul-terminated, then there is a small
3367
-** performance advantage to be gained by passing an nByte parameter that
3368
-** is equal to the number of bytes in the input string <i>including</i>
3369
-** the nul-terminator bytes as this saves SQLite from having to
3370
-** make a copy of the input string.
3402
+** ^If the nByte argument is negative, then zSql is read up to the
3403
+** first zero terminator. ^If nByte is positive, then it is the
3404
+** number of bytes read from zSql. ^If nByte is zero, then no prepared
3405
+** statement is generated.
3406
+** If the caller knows that the supplied string is nul-terminated, then
3407
+** there is a small performance advantage to passing an nByte parameter that
3408
+** is the number of bytes in the input string <i>including</i>
3409
+** the nul-terminator.
33713410
**
33723411
** ^If pzTail is not NULL then *pzTail is made to point to the first byte
33733412
** past the end of the first SQL statement in zSql. These routines only
33743413
** compile the first statement in zSql, so *pzTail is left pointing to
33753414
** what remains uncompiled.
@@ -4394,12 +4433,12 @@
43944433
** DEPRECATED
43954434
**
43964435
** These functions are [deprecated]. In order to maintain
43974436
** backwards compatibility with older code, these functions continue
43984437
** to be supported. However, new applications should avoid
4399
-** the use of these functions. To help encourage people to avoid
4400
-** using these functions, we are not going to tell you what they do.
4438
+** the use of these functions. To encourage programmers to avoid
4439
+** these functions, we will not explain what they do.
44014440
*/
44024441
#ifndef SQLITE_OMIT_DEPRECATED
44034442
SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*);
44044443
SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*);
44054444
SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
@@ -7157,24 +7196,24 @@
71577196
**
71587197
** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step()
71597198
** is not a permanent error and does not affect the return value of
71607199
** sqlite3_backup_finish().
71617200
**
7162
-** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]]
7201
+** [[sqlite3_backup_remaining()]] [[sqlite3_backup_pagecount()]]
71637202
** <b>sqlite3_backup_remaining() and sqlite3_backup_pagecount()</b>
71647203
**
7165
-** ^Each call to sqlite3_backup_step() sets two values inside
7166
-** the [sqlite3_backup] object: the number of pages still to be backed
7167
-** up and the total number of pages in the source database file.
7168
-** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces
7169
-** retrieve these two values, respectively.
7170
-**
7171
-** ^The values returned by these functions are only updated by
7172
-** sqlite3_backup_step(). ^If the source database is modified during a backup
7173
-** operation, then the values are not updated to account for any extra
7174
-** pages that need to be updated or the size of the source database file
7175
-** changing.
7204
+** ^The sqlite3_backup_remaining() routine returns the number of pages still
7205
+** to be backed up at the conclusion of the most recent sqlite3_backup_step().
7206
+** ^The sqlite3_backup_pagecount() routine returns the total number of pages
7207
+** in the source database at the conclusion of the most recent
7208
+** sqlite3_backup_step().
7209
+** ^(The values returned by these functions are only updated by
7210
+** sqlite3_backup_step(). If the source database is modified in a way that
7211
+** changes the size of the source database or the number of pages remaining,
7212
+** those changes are not reflected in the output of sqlite3_backup_pagecount()
7213
+** and sqlite3_backup_remaining() until after the next
7214
+** sqlite3_backup_step().)^
71767215
**
71777216
** <b>Concurrent Usage of Database Handles</b>
71787217
**
71797218
** ^The source [database connection] may be used by the application for other
71807219
** purposes while a backup operation is underway or being initialized.
@@ -8018,19 +8057,21 @@
80188057
#ifndef SQLITE_MAX_FUNCTION_ARG
80198058
# define SQLITE_MAX_FUNCTION_ARG 127
80208059
#endif
80218060
80228061
/*
8023
-** The maximum number of in-memory pages to use for the main database
8024
-** table and for temporary tables. The SQLITE_DEFAULT_CACHE_SIZE
8062
+** The suggested maximum number of in-memory pages to use for
8063
+** the main database table and for temporary tables.
8064
+**
8065
+** IMPLEMENTATION-OF: R-31093-59126 The default suggested cache size
8066
+** is 2000 pages.
8067
+** IMPLEMENTATION-OF: R-48205-43578 The default suggested cache size can be
8068
+** altered using the SQLITE_DEFAULT_CACHE_SIZE compile-time options.
80258069
*/
80268070
#ifndef SQLITE_DEFAULT_CACHE_SIZE
80278071
# define SQLITE_DEFAULT_CACHE_SIZE 2000
80288072
#endif
8029
-#ifndef SQLITE_DEFAULT_TEMP_CACHE_SIZE
8030
-# define SQLITE_DEFAULT_TEMP_CACHE_SIZE 500
8031
-#endif
80328073
80338074
/*
80348075
** The default number of frames to accumulate in the log file before
80358076
** checkpointing the database in WAL mode.
80368077
*/
@@ -9733,27 +9774,29 @@
97339774
#define OP_FkCounter 134 /* synopsis: fkctr[P1]+=P2 */
97349775
#define OP_FkIfZero 135 /* synopsis: if fkctr[P1]==0 goto P2 */
97359776
#define OP_MemMax 136 /* synopsis: r[P1]=max(r[P1],r[P2]) */
97369777
#define OP_IfPos 137 /* synopsis: if r[P1]>0 goto P2 */
97379778
#define OP_IfNeg 138 /* synopsis: r[P1]+=P3, if r[P1]<0 goto P2 */
9738
-#define OP_IfZero 139 /* synopsis: r[P1]+=P3, if r[P1]==0 goto P2 */
9739
-#define OP_AggFinal 140 /* synopsis: accum=r[P1] N=P2 */
9740
-#define OP_IncrVacuum 141
9741
-#define OP_Expire 142
9742
-#define OP_TableLock 143 /* synopsis: iDb=P1 root=P2 write=P3 */
9743
-#define OP_VBegin 144
9744
-#define OP_VCreate 145
9745
-#define OP_VDestroy 146
9746
-#define OP_VOpen 147
9747
-#define OP_VColumn 148 /* synopsis: r[P3]=vcolumn(P2) */
9748
-#define OP_VNext 149
9749
-#define OP_VRename 150
9750
-#define OP_Pagecount 151
9751
-#define OP_MaxPgcnt 152
9752
-#define OP_Init 153 /* synopsis: Start at P2 */
9753
-#define OP_Noop 154
9754
-#define OP_Explain 155
9779
+#define OP_IfNotZero 139 /* synopsis: if r[P1]!=0 then r[P1]+=P3, goto P2 */
9780
+#define OP_DecrJumpZero 140 /* synopsis: if (--r[P1])==0 goto P2 */
9781
+#define OP_JumpZeroIncr 141 /* synopsis: if (r[P1]++)==0 ) goto P2 */
9782
+#define OP_AggFinal 142 /* synopsis: accum=r[P1] N=P2 */
9783
+#define OP_IncrVacuum 143
9784
+#define OP_Expire 144
9785
+#define OP_TableLock 145 /* synopsis: iDb=P1 root=P2 write=P3 */
9786
+#define OP_VBegin 146
9787
+#define OP_VCreate 147
9788
+#define OP_VDestroy 148
9789
+#define OP_VOpen 149
9790
+#define OP_VColumn 150 /* synopsis: r[P3]=vcolumn(P2) */
9791
+#define OP_VNext 151
9792
+#define OP_VRename 152
9793
+#define OP_Pagecount 153
9794
+#define OP_MaxPgcnt 154
9795
+#define OP_Init 155 /* synopsis: Start at P2 */
9796
+#define OP_Noop 156
9797
+#define OP_Explain 157
97559798
97569799
97579800
/* Properties such as "out2" or "jump" that are specified in
97589801
** comments following the "case" for each opcode in the vdbe.c
97599802
** are encoded into bitvectors as follows:
@@ -9781,13 +9824,13 @@
97819824
/* 96 */ 0x24, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,\
97829825
/* 104 */ 0x00, 0x01, 0x01, 0x01, 0x01, 0x08, 0x08, 0x00,\
97839826
/* 112 */ 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00,\
97849827
/* 120 */ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
97859828
/* 128 */ 0x0c, 0x45, 0x15, 0x01, 0x02, 0x02, 0x00, 0x01,\
9786
-/* 136 */ 0x08, 0x05, 0x05, 0x05, 0x00, 0x01, 0x00, 0x00,\
9787
-/* 144 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02,\
9788
-/* 152 */ 0x02, 0x01, 0x00, 0x00,}
9829
+/* 136 */ 0x08, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x01,\
9830
+/* 144 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,\
9831
+/* 152 */ 0x00, 0x02, 0x02, 0x01, 0x00, 0x00,}
97899832
97909833
/************** End of opcodes.h *********************************************/
97919834
/************** Continuing where we left off in vdbe.h ***********************/
97929835
97939836
/*
@@ -12022,11 +12065,11 @@
1202212065
#define WHERE_ONEPASS_DESIRED 0x0004 /* Want to do one-pass UPDATE/DELETE */
1202312066
#define WHERE_DUPLICATES_OK 0x0008 /* Ok to return a row more than once */
1202412067
#define WHERE_OMIT_OPEN_CLOSE 0x0010 /* Table cursors are already open */
1202512068
#define WHERE_FORCE_TABLE 0x0020 /* Do not use an index-only search */
1202612069
#define WHERE_ONETABLE_ONLY 0x0040 /* Only code the 1st table in pTabList */
12027
- /* 0x0080 // not currently used */
12070
+#define WHERE_NO_AUTOINDEX 0x0080 /* Disallow automatic indexes */
1202812071
#define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */
1202912072
#define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */
1203012073
#define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */
1203112074
#define WHERE_SORTBYGROUP 0x0800 /* Support sqlite3WhereIsSorted() */
1203212075
#define WHERE_REOPEN_IDX 0x1000 /* Try to use OP_ReopenIdx */
@@ -24969,27 +25012,29 @@
2496925012
/* 134 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
2497025013
/* 135 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
2497125014
/* 136 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
2497225015
/* 137 */ "IfPos" OpHelp("if r[P1]>0 goto P2"),
2497325016
/* 138 */ "IfNeg" OpHelp("r[P1]+=P3, if r[P1]<0 goto P2"),
24974
- /* 139 */ "IfZero" OpHelp("r[P1]+=P3, if r[P1]==0 goto P2"),
24975
- /* 140 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
24976
- /* 141 */ "IncrVacuum" OpHelp(""),
24977
- /* 142 */ "Expire" OpHelp(""),
24978
- /* 143 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
24979
- /* 144 */ "VBegin" OpHelp(""),
24980
- /* 145 */ "VCreate" OpHelp(""),
24981
- /* 146 */ "VDestroy" OpHelp(""),
24982
- /* 147 */ "VOpen" OpHelp(""),
24983
- /* 148 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
24984
- /* 149 */ "VNext" OpHelp(""),
24985
- /* 150 */ "VRename" OpHelp(""),
24986
- /* 151 */ "Pagecount" OpHelp(""),
24987
- /* 152 */ "MaxPgcnt" OpHelp(""),
24988
- /* 153 */ "Init" OpHelp("Start at P2"),
24989
- /* 154 */ "Noop" OpHelp(""),
24990
- /* 155 */ "Explain" OpHelp(""),
25017
+ /* 139 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]+=P3, goto P2"),
25018
+ /* 140 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
25019
+ /* 141 */ "JumpZeroIncr" OpHelp("if (r[P1]++)==0 ) goto P2"),
25020
+ /* 142 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
25021
+ /* 143 */ "IncrVacuum" OpHelp(""),
25022
+ /* 144 */ "Expire" OpHelp(""),
25023
+ /* 145 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
25024
+ /* 146 */ "VBegin" OpHelp(""),
25025
+ /* 147 */ "VCreate" OpHelp(""),
25026
+ /* 148 */ "VDestroy" OpHelp(""),
25027
+ /* 149 */ "VOpen" OpHelp(""),
25028
+ /* 150 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
25029
+ /* 151 */ "VNext" OpHelp(""),
25030
+ /* 152 */ "VRename" OpHelp(""),
25031
+ /* 153 */ "Pagecount" OpHelp(""),
25032
+ /* 154 */ "MaxPgcnt" OpHelp(""),
25033
+ /* 155 */ "Init" OpHelp("Start at P2"),
25034
+ /* 156 */ "Noop" OpHelp(""),
25035
+ /* 157 */ "Explain" OpHelp(""),
2499125036
};
2499225037
return azName[i];
2499325038
}
2499425039
#endif
2499525040
@@ -25065,22 +25110,10 @@
2506525110
# else
2506625111
# define SQLITE_ENABLE_LOCKING_STYLE 0
2506725112
# endif
2506825113
#endif
2506925114
25070
-/*
25071
-** Define the OS_VXWORKS pre-processor macro to 1 if building on
25072
-** vxworks, or 0 otherwise.
25073
-*/
25074
-#ifndef OS_VXWORKS
25075
-# if defined(__RTP__) || defined(_WRS_KERNEL)
25076
-# define OS_VXWORKS 1
25077
-# else
25078
-# define OS_VXWORKS 0
25079
-# endif
25080
-#endif
25081
-
2508225115
/*
2508325116
** standard include files.
2508425117
*/
2508525118
#include <sys/types.h>
2508625119
#include <sys/stat.h>
@@ -25091,22 +25124,23 @@
2509125124
#include <errno.h>
2509225125
#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
2509325126
# include <sys/mman.h>
2509425127
#endif
2509525128
25096
-#if SQLITE_ENABLE_LOCKING_STYLE || OS_VXWORKS
25129
+#if SQLITE_ENABLE_LOCKING_STYLE
2509725130
# include <sys/ioctl.h>
25098
-# if OS_VXWORKS
25099
-# include <semaphore.h>
25100
-# include <limits.h>
25101
-# else
25102
-# include <sys/file.h>
25103
-# include <sys/param.h>
25104
-# endif
25131
+# include <sys/file.h>
25132
+# include <sys/param.h>
2510525133
#endif /* SQLITE_ENABLE_LOCKING_STYLE */
2510625134
25107
-#if defined(__APPLE__) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
25135
+#if OS_VXWORKS
25136
+/* # include <sys/ioctl.h> */
25137
+# include <semaphore.h>
25138
+# include <limits.h>
25139
+#endif /* OS_VXWORKS */
25140
+
25141
+#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
2510825142
# include <sys/mount.h>
2510925143
#endif
2511025144
2511125145
#ifdef HAVE_UTIME
2511225146
# include <utime.h>
@@ -25142,10 +25176,14 @@
2514225176
2514325177
/*
2514425178
** Maximum supported path-length.
2514525179
*/
2514625180
#define MAX_PATHNAME 512
25181
+
25182
+/* Always cast the getpid() return type for compatibility with
25183
+** kernel modules in VxWorks. */
25184
+#define osGetpid(X) (pid_t)getpid()
2514725185
2514825186
/*
2514925187
** Only set the lastErrno if the error code is a real error and not
2515025188
** a normal expected return code of SQLITE_BUSY or SQLITE_OK
2515125189
*/
@@ -25231,11 +25269,11 @@
2523125269
2523225270
/* This variable holds the process id (pid) from when the xRandomness()
2523325271
** method was called. If xOpen() is called from a different process id,
2523425272
** indicating that a fork() has occurred, the PRNG will be reset.
2523525273
*/
25236
-static int randomnessPid = 0;
25274
+static pid_t randomnessPid = 0;
2523725275
2523825276
/*
2523925277
** Allowed values for the unixFile.ctrlFlags bitmask:
2524025278
*/
2524125279
#define UNIXFILE_EXCL 0x01 /* Connections from one process only */
@@ -25587,11 +25625,11 @@
2558725625
#define osFcntl ((int(*)(int,int,...))aSyscall[7].pCurrent)
2558825626
2558925627
{ "read", (sqlite3_syscall_ptr)read, 0 },
2559025628
#define osRead ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent)
2559125629
25592
-#if defined(USE_PREAD) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
25630
+#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
2559325631
{ "pread", (sqlite3_syscall_ptr)pread, 0 },
2559425632
#else
2559525633
{ "pread", (sqlite3_syscall_ptr)0, 0 },
2559625634
#endif
2559725635
#define osPread ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].pCurrent)
@@ -25604,11 +25642,11 @@
2560425642
#define osPread64 ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[10].pCurrent)
2560525643
2560625644
{ "write", (sqlite3_syscall_ptr)write, 0 },
2560725645
#define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
2560825646
25609
-#if defined(USE_PREAD) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
25647
+#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
2561025648
{ "pwrite", (sqlite3_syscall_ptr)pwrite, 0 },
2561125649
#else
2561225650
{ "pwrite", (sqlite3_syscall_ptr)0, 0 },
2561325651
#endif
2561425652
#define osPwrite ((ssize_t(*)(int,const void*,size_t,off_t))\
@@ -26743,11 +26781,12 @@
2674326781
int tErrno = 0;
2674426782
2674526783
assert( pFile );
2674626784
OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h,
2674726785
azFileLock(eFileLock), azFileLock(pFile->eFileLock),
26748
- azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared , getpid()));
26786
+ azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared,
26787
+ osGetpid()));
2674926788
2675026789
/* If there is already a lock of this type or more restrictive on the
2675126790
** unixFile, do nothing. Don't use the end_lock: exit path, as
2675226791
** unixEnterMutex() hasn't been called yet.
2675326792
*/
@@ -26951,11 +26990,11 @@
2695126990
int rc = SQLITE_OK;
2695226991
2695326992
assert( pFile );
2695426993
OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock,
2695526994
pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
26956
- getpid()));
26995
+ osGetpid()));
2695726996
2695826997
assert( eFileLock<=SHARED_LOCK );
2695926998
if( pFile->eFileLock<=eFileLock ){
2696026999
return SQLITE_OK;
2696127000
}
@@ -27378,11 +27417,11 @@
2737827417
char *zLockFile = (char *)pFile->lockingContext;
2737927418
int rc;
2738027419
2738127420
assert( pFile );
2738227421
OSTRACE(("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock,
27383
- pFile->eFileLock, getpid()));
27422
+ pFile->eFileLock, osGetpid()));
2738427423
assert( eFileLock<=SHARED_LOCK );
2738527424
2738627425
/* no-op if possible */
2738727426
if( pFile->eFileLock==eFileLock ){
2738827427
return SQLITE_OK;
@@ -27441,14 +27480,13 @@
2744127480
** a single exclusive lock. In other words, SHARED, RESERVED, and
2744227481
** PENDING locks are the same thing as an EXCLUSIVE lock. SQLite
2744327482
** still works when you do this, but concurrency is reduced since
2744427483
** only a single process can be reading the database at a time.
2744527484
**
27446
-** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off or if
27447
-** compiling for VXWORKS.
27485
+** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off
2744827486
*/
27449
-#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
27487
+#if SQLITE_ENABLE_LOCKING_STYLE
2745027488
2745127489
/*
2745227490
** Retry flock() calls that fail with EINTR
2745327491
*/
2745427492
#ifdef EINTR
@@ -27597,11 +27635,11 @@
2759727635
static int flockUnlock(sqlite3_file *id, int eFileLock) {
2759827636
unixFile *pFile = (unixFile*)id;
2759927637
2760027638
assert( pFile );
2760127639
OSTRACE(("UNLOCK %d %d was %d pid=%d (flock)\n", pFile->h, eFileLock,
27602
- pFile->eFileLock, getpid()));
27640
+ pFile->eFileLock, osGetpid()));
2760327641
assert( eFileLock<=SHARED_LOCK );
2760427642
2760527643
/* no-op if possible */
2760627644
if( pFile->eFileLock==eFileLock ){
2760727645
return SQLITE_OK;
@@ -27658,11 +27696,11 @@
2765827696
** This routine checks if there is a RESERVED lock held on the specified
2765927697
** file by this or any other process. If such a lock is held, set *pResOut
2766027698
** to a non-zero value otherwise *pResOut is set to zero. The return value
2766127699
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
2766227700
*/
27663
-static int semCheckReservedLock(sqlite3_file *id, int *pResOut) {
27701
+static int semXCheckReservedLock(sqlite3_file *id, int *pResOut) {
2766427702
int rc = SQLITE_OK;
2766527703
int reserved = 0;
2766627704
unixFile *pFile = (unixFile*)id;
2766727705
2766827706
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
@@ -27725,11 +27763,11 @@
2772527763
** access the file.
2772627764
**
2772727765
** This routine will only increase a lock. Use the sqlite3OsUnlock()
2772827766
** routine to lower a locking level.
2772927767
*/
27730
-static int semLock(sqlite3_file *id, int eFileLock) {
27768
+static int semXLock(sqlite3_file *id, int eFileLock) {
2773127769
unixFile *pFile = (unixFile*)id;
2773227770
sem_t *pSem = pFile->pInode->pSem;
2773327771
int rc = SQLITE_OK;
2773427772
2773527773
/* if we already have a lock, it is exclusive.
@@ -27758,18 +27796,18 @@
2775827796
** must be either NO_LOCK or SHARED_LOCK.
2775927797
**
2776027798
** If the locking level of the file descriptor is already at or below
2776127799
** the requested locking level, this routine is a no-op.
2776227800
*/
27763
-static int semUnlock(sqlite3_file *id, int eFileLock) {
27801
+static int semXUnlock(sqlite3_file *id, int eFileLock) {
2776427802
unixFile *pFile = (unixFile*)id;
2776527803
sem_t *pSem = pFile->pInode->pSem;
2776627804
2776727805
assert( pFile );
2776827806
assert( pSem );
2776927807
OSTRACE(("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock,
27770
- pFile->eFileLock, getpid()));
27808
+ pFile->eFileLock, osGetpid()));
2777127809
assert( eFileLock<=SHARED_LOCK );
2777227810
2777327811
/* no-op if possible */
2777427812
if( pFile->eFileLock==eFileLock ){
2777527813
return SQLITE_OK;
@@ -27795,14 +27833,14 @@
2779527833
}
2779627834
2779727835
/*
2779827836
** Close a file.
2779927837
*/
27800
-static int semClose(sqlite3_file *id) {
27838
+static int semXClose(sqlite3_file *id) {
2780127839
if( id ){
2780227840
unixFile *pFile = (unixFile*)id;
27803
- semUnlock(id, NO_LOCK);
27841
+ semXUnlock(id, NO_LOCK);
2780427842
assert( pFile );
2780527843
unixEnterMutex();
2780627844
releaseInodeInfo(pFile);
2780727845
unixLeaveMutex();
2780827846
closeUnixFile(id);
@@ -27979,11 +28017,11 @@
2797928017
afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
2798028018
2798128019
assert( pFile );
2798228020
OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h,
2798328021
azFileLock(eFileLock), azFileLock(pFile->eFileLock),
27984
- azFileLock(pInode->eFileLock), pInode->nShared , getpid()));
28022
+ azFileLock(pInode->eFileLock), pInode->nShared , osGetpid()));
2798528023
2798628024
/* If there is already a lock of this type or more restrictive on the
2798728025
** unixFile, do nothing. Don't use the afp_end_lock: exit path, as
2798828026
** unixEnterMutex() hasn't been called yet.
2798928027
*/
@@ -28165,11 +28203,11 @@
2816528203
#endif
2816628204
2816728205
assert( pFile );
2816828206
OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock,
2816928207
pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
28170
- getpid()));
28208
+ osGetpid()));
2817128209
2817228210
assert( eFileLock<=SHARED_LOCK );
2817328211
if( pFile->eFileLock<=eFileLock ){
2817428212
return SQLITE_OK;
2817528213
}
@@ -29204,11 +29242,13 @@
2920429242
**
2920529243
** This function should not be called directly by other code in this file.
2920629244
** Instead, it should be called via macro osGetpagesize().
2920729245
*/
2920829246
static int unixGetpagesize(void){
29209
-#if defined(_BSD_SOURCE)
29247
+#if OS_VXWORKS
29248
+ return 1024;
29249
+#elif defined(_BSD_SOURCE)
2921029250
return getpagesize();
2921129251
#else
2921229252
return (int)sysconf(_SC_PAGESIZE);
2921329253
#endif
2921429254
}
@@ -29833,11 +29873,11 @@
2983329873
}
2983429874
}
2983529875
}
2983629876
sqlite3_mutex_leave(pShmNode->mutex);
2983729877
OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
29838
- p->id, getpid(), p->sharedMask, p->exclMask));
29878
+ p->id, osGetpid(), p->sharedMask, p->exclMask));
2983929879
return rc;
2984029880
}
2984129881
2984229882
/*
2984329883
** Implement a memory barrier or memory fence on shared memory.
@@ -30236,11 +30276,11 @@
3023630276
dotlockUnlock, /* xUnlock method */
3023730277
dotlockCheckReservedLock, /* xCheckReservedLock method */
3023830278
0 /* xShmMap method */
3023930279
)
3024030280
30241
-#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
30281
+#if SQLITE_ENABLE_LOCKING_STYLE
3024230282
IOMETHODS(
3024330283
flockIoFinder, /* Finder function name */
3024430284
flockIoMethods, /* sqlite3_io_methods object name */
3024530285
1, /* shared memory is disabled */
3024630286
flockClose, /* xClose method */
@@ -30254,14 +30294,14 @@
3025430294
#if OS_VXWORKS
3025530295
IOMETHODS(
3025630296
semIoFinder, /* Finder function name */
3025730297
semIoMethods, /* sqlite3_io_methods object name */
3025830298
1, /* shared memory is disabled */
30259
- semClose, /* xClose method */
30260
- semLock, /* xLock method */
30261
- semUnlock, /* xUnlock method */
30262
- semCheckReservedLock, /* xCheckReservedLock method */
30299
+ semXClose, /* xClose method */
30300
+ semXLock, /* xLock method */
30301
+ semXUnlock, /* xUnlock method */
30302
+ semXCheckReservedLock, /* xCheckReservedLock method */
3026330303
0 /* xShmMap method */
3026430304
)
3026530305
#endif
3026630306
3026730307
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
@@ -30381,19 +30421,17 @@
3038130421
static const sqlite3_io_methods
3038230422
*(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
3038330423
3038430424
#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
3038530425
30386
-#if OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE
30387
-/*
30388
-** This "finder" function attempts to determine the best locking strategy
30389
-** for the database file "filePath". It then returns the sqlite3_io_methods
30390
-** object that implements that strategy.
30391
-**
30392
-** This is for VXWorks only.
30426
+#if OS_VXWORKS
30427
+/*
30428
+** This "finder" function for VxWorks checks to see if posix advisory
30429
+** locking works. If it does, then that is what is used. If it does not
30430
+** work, then fallback to named semaphore locking.
3039330431
*/
30394
-static const sqlite3_io_methods *autolockIoFinderImpl(
30432
+static const sqlite3_io_methods *vxworksIoFinderImpl(
3039530433
const char *filePath, /* name of the database file */
3039630434
unixFile *pNew /* the open file object */
3039730435
){
3039830436
struct flock lockInfo;
3039930437
@@ -30415,13 +30453,13 @@
3041530453
}else{
3041630454
return &semIoMethods;
3041730455
}
3041830456
}
3041930457
static const sqlite3_io_methods
30420
- *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
30458
+ *(*const vxworksIoFinder)(const char*,unixFile*) = vxworksIoFinderImpl;
3042130459
30422
-#endif /* OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE */
30460
+#endif /* OS_VXWORKS */
3042330461
3042430462
/*
3042530463
** An abstract type for a pointer to an IO method finder function:
3042630464
*/
3042730465
typedef const sqlite3_io_methods *(*finder_type)(const char*,unixFile*);
@@ -30930,12 +30968,12 @@
3093030968
/* Detect a pid change and reset the PRNG. There is a race condition
3093130969
** here such that two or more threads all trying to open databases at
3093230970
** the same instant might all reset the PRNG. But multiple resets
3093330971
** are harmless.
3093430972
*/
30935
- if( randomnessPid!=getpid() ){
30936
- randomnessPid = getpid();
30973
+ if( randomnessPid!=osGetpid() ){
30974
+ randomnessPid = osGetpid();
3093730975
sqlite3_randomness(0,0);
3093830976
}
3093930977
3094030978
memset(p, 0, sizeof(unixFile));
3094130979
@@ -31322,11 +31360,11 @@
3132231360
** When testing, initializing zBuf[] to zero is all we do. That means
3132331361
** that we always use the same random number sequence. This makes the
3132431362
** tests repeatable.
3132531363
*/
3132631364
memset(zBuf, 0, nBuf);
31327
- randomnessPid = getpid();
31365
+ randomnessPid = osGetpid();
3132831366
#if !defined(SQLITE_TEST)
3132931367
{
3133031368
int fd, got;
3133131369
fd = robust_open("/dev/urandom", O_RDONLY, 0);
3133231370
if( fd<0 ){
@@ -31643,11 +31681,11 @@
3164331681
#else
3164431682
# ifdef _CS_DARWIN_USER_TEMP_DIR
3164531683
{
3164631684
if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){
3164731685
OSTRACE(("GETLOCKPATH failed %s errno=%d pid=%d\n",
31648
- lPath, errno, getpid()));
31686
+ lPath, errno, osGetpid()));
3164931687
return SQLITE_IOERR_LOCK;
3165031688
}
3165131689
len = strlcat(lPath, "sqliteplocks", maxLen);
3165231690
}
3165331691
# else
@@ -31665,11 +31703,11 @@
3166531703
char c = dbPath[i];
3166631704
lPath[i+len] = (c=='/')?'_':c;
3166731705
}
3166831706
lPath[i+len]='\0';
3166931707
strlcat(lPath, ":auto:", maxLen);
31670
- OSTRACE(("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, getpid()));
31708
+ OSTRACE(("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, osGetpid()));
3167131709
return SQLITE_OK;
3167231710
}
3167331711
3167431712
/*
3167531713
** Creates the lock file and any missing directories in lockPath
@@ -31692,20 +31730,20 @@
3169231730
if( osMkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){
3169331731
int err=errno;
3169431732
if( err!=EEXIST ) {
3169531733
OSTRACE(("CREATELOCKPATH FAILED creating %s, "
3169631734
"'%s' proxy lock path=%s pid=%d\n",
31697
- buf, strerror(err), lockPath, getpid()));
31735
+ buf, strerror(err), lockPath, osGetpid()));
3169831736
return err;
3169931737
}
3170031738
}
3170131739
}
3170231740
start=i+1;
3170331741
}
3170431742
buf[i] = lockPath[i];
3170531743
}
31706
- OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n", lockPath, getpid()));
31744
+ OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n", lockPath, osGetpid()));
3170731745
return 0;
3170831746
}
3170931747
3171031748
/*
3171131749
** Create a new VFS file descriptor (stored in memory obtained from
@@ -32006,11 +32044,12 @@
3200632044
int readLen = 0;
3200732045
int tryOldLockPath = 0;
3200832046
int forceNewLockPath = 0;
3200932047
3201032048
OSTRACE(("TAKECONCH %d for %s pid=%d\n", conchFile->h,
32011
- (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid()));
32049
+ (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
32050
+ osGetpid()));
3201232051
3201332052
rc = proxyGetHostID(myHostID, &pError);
3201432053
if( (rc&0xff)==SQLITE_IOERR ){
3201532054
storeLastErrno(pFile, pError);
3201632055
goto end_takeconch;
@@ -32216,11 +32255,11 @@
3221632255
3221732256
pCtx = (proxyLockingContext *)pFile->lockingContext;
3221832257
conchFile = pCtx->conchFile;
3221932258
OSTRACE(("RELEASECONCH %d for %s pid=%d\n", conchFile->h,
3222032259
(pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
32221
- getpid()));
32260
+ osGetpid()));
3222232261
if( pCtx->conchHeld>0 ){
3222332262
rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
3222432263
}
3222532264
pCtx->conchHeld = 0;
3222632265
OSTRACE(("RELEASECONCH %d %s\n", conchFile->h,
@@ -32358,11 +32397,11 @@
3235832397
}else{
3235932398
lockPath=(char *)path;
3236032399
}
3236132400
3236232401
OSTRACE(("TRANSPROXY %d for %s pid=%d\n", pFile->h,
32363
- (lockPath ? lockPath : ":auto:"), getpid()));
32402
+ (lockPath ? lockPath : ":auto:"), osGetpid()));
3236432403
3236532404
pCtx = sqlite3_malloc( sizeof(*pCtx) );
3236632405
if( pCtx==0 ){
3236732406
return SQLITE_NOMEM;
3236832407
}
@@ -32699,26 +32738,28 @@
3269932738
** Note that the sqlite3_vfs.pNext field of the VFS object is modified
3270032739
** by the SQLite core when the VFS is registered. So the following
3270132740
** array cannot be const.
3270232741
*/
3270332742
static sqlite3_vfs aVfs[] = {
32704
-#if SQLITE_ENABLE_LOCKING_STYLE && (OS_VXWORKS || defined(__APPLE__))
32743
+#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
3270532744
UNIXVFS("unix", autolockIoFinder ),
32745
+#elif OS_VXWORKS
32746
+ UNIXVFS("unix", vxworksIoFinder ),
3270632747
#else
3270732748
UNIXVFS("unix", posixIoFinder ),
3270832749
#endif
3270932750
UNIXVFS("unix-none", nolockIoFinder ),
3271032751
UNIXVFS("unix-dotfile", dotlockIoFinder ),
3271132752
UNIXVFS("unix-excl", posixIoFinder ),
3271232753
#if OS_VXWORKS
3271332754
UNIXVFS("unix-namedsem", semIoFinder ),
3271432755
#endif
32715
-#if SQLITE_ENABLE_LOCKING_STYLE
32756
+#if SQLITE_ENABLE_LOCKING_STYLE || OS_VXWORKS
3271632757
UNIXVFS("unix-posix", posixIoFinder ),
32717
-#if !OS_VXWORKS
32758
+#endif
32759
+#if SQLITE_ENABLE_LOCKING_STYLE
3271832760
UNIXVFS("unix-flock", flockIoFinder ),
32719
-#endif
3272032761
#endif
3272132762
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
3272232763
UNIXVFS("unix-afp", afpIoFinder ),
3272332764
UNIXVFS("unix-nfs", nfsIoFinder ),
3272432765
UNIXVFS("unix-proxy", proxyIoFinder ),
@@ -39072,16 +39113,24 @@
3907239113
sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 0);
3907339114
}
3907439115
}
3907539116
3907639117
/*
39077
-** Compute the number of pages of cache requested.
39118
+** Compute the number of pages of cache requested. p->szCache is the
39119
+** cache size requested by the "PRAGMA cache_size" statement.
39120
+**
39121
+**
3907839122
*/
3907939123
static int numberOfCachePages(PCache *p){
3908039124
if( p->szCache>=0 ){
39125
+ /* IMPLEMENTATION-OF: R-42059-47211 If the argument N is positive then the
39126
+ ** suggested cache size is set to N. */
3908139127
return p->szCache;
3908239128
}else{
39129
+ /* IMPLEMENTATION-OF: R-61436-13639 If the argument N is negative, then
39130
+ ** the number of cache pages is adjusted to use approximately abs(N*1024)
39131
+ ** bytes of memory. */
3908339132
return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra));
3908439133
}
3908539134
}
3908639135
3908739136
/*************************************************** General Interfaces ******
@@ -68615,10 +68664,14 @@
6861568664
}
6861668665
SQLITE_API const void *sqlite3_value_text16le(sqlite3_value *pVal){
6861768666
return sqlite3ValueText(pVal, SQLITE_UTF16LE);
6861868667
}
6861968668
#endif /* SQLITE_OMIT_UTF16 */
68669
+/* EVIDENCE-OF: R-12793-43283 Every value in SQLite has one of five
68670
+** fundamental datatypes: 64-bit signed integer 64-bit IEEE floating
68671
+** point number string BLOB NULL
68672
+*/
6862068673
SQLITE_API int sqlite3_value_type(sqlite3_value* pVal){
6862168674
static const u8 aType[] = {
6862268675
SQLITE_BLOB, /* 0x00 */
6862368676
SQLITE_NULL, /* 0x01 */
6862468677
SQLITE_TEXT, /* 0x02 */
@@ -71290,11 +71343,11 @@
7129071343
7129171344
/* Opcode: String8 * P2 * P4 *
7129271345
** Synopsis: r[P2]='P4'
7129371346
**
7129471347
** P4 points to a nul terminated UTF-8 string. This opcode is transformed
71295
-** into a String before it is executed for the first time. During
71348
+** into a String opcode before it is executed for the first time. During
7129671349
** this transformation, the length of string P4 is computed and stored
7129771350
** as the P1 parameter.
7129871351
*/
7129971352
case OP_String8: { /* same as TK_STRING, out2-prerelease */
7130071353
assert( pOp->p4.z!=0 );
@@ -71322,22 +71375,34 @@
7132271375
goto too_big;
7132371376
}
7132471377
/* Fall through to the next case, OP_String */
7132571378
}
7132671379
71327
-/* Opcode: String P1 P2 * P4 *
71380
+/* Opcode: String P1 P2 P3 P4 P5
7132871381
** Synopsis: r[P2]='P4' (len=P1)
7132971382
**
7133071383
** The string value P4 of length P1 (bytes) is stored in register P2.
71384
+**
71385
+** If P5!=0 and the content of register P3 is greater than zero, then
71386
+** the datatype of the register P2 is converted to BLOB. The content is
71387
+** the same sequence of bytes, it is merely interpreted as a BLOB instead
71388
+** of a string, as if it had been CAST.
7133171389
*/
7133271390
case OP_String: { /* out2-prerelease */
7133371391
assert( pOp->p4.z!=0 );
7133471392
pOut->flags = MEM_Str|MEM_Static|MEM_Term;
7133571393
pOut->z = pOp->p4.z;
7133671394
pOut->n = pOp->p1;
7133771395
pOut->enc = encoding;
7133871396
UPDATE_MAX_BLOBSIZE(pOut);
71397
+ if( pOp->p5 ){
71398
+ assert( pOp->p3>0 );
71399
+ assert( pOp->p3<=(p->nMem-p->nCursor) );
71400
+ pIn3 = &aMem[pOp->p3];
71401
+ assert( pIn3->flags & MEM_Int );
71402
+ if( pIn3->u.i ) pOut->flags = MEM_Blob|MEM_Static|MEM_Term;
71403
+ }
7133971404
break;
7134071405
}
7134171406
7134271407
/* Opcode: Null P1 P2 P3 * *
7134371408
** Synopsis: r[P2..P3]=NULL
@@ -73325,11 +73390,16 @@
7332573390
** the value of this counter needs to be restored too. */
7332673391
p->nStmtDefCons = db->nDeferredCons;
7332773392
p->nStmtDefImmCons = db->nDeferredImmCons;
7332873393
}
7332973394
73330
- /* Gather the schema version number for checking */
73395
+ /* Gather the schema version number for checking:
73396
+ ** IMPLEMENTATION-OF: R-32195-19465 The schema version is used by SQLite
73397
+ ** each time a query is executed to ensure that the internal cache of the
73398
+ ** schema used when compiling the SQL query matches the schema of the
73399
+ ** database against which the compiled query is actually executed.
73400
+ */
7333173401
sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta);
7333273402
iGen = db->aDb[pOp->p1].pSchema->iGeneration;
7333373403
}else{
7333473404
iGen = iMeta = 0;
7333573405
}
@@ -75843,14 +75913,16 @@
7584375913
#endif /* SQLITE_OMIT_AUTOINCREMENT */
7584475914
7584575915
/* Opcode: IfPos P1 P2 * * *
7584675916
** Synopsis: if r[P1]>0 goto P2
7584775917
**
75848
-** If the value of register P1 is 1 or greater, jump to P2.
75918
+** Register P1 must contain an integer.
75919
+** If the value of register P1 is 1 or greater, jump to P2 and
75920
+** add the literal value P3 to register P1.
7584975921
**
75850
-** It is illegal to use this instruction on a register that does
75851
-** not contain an integer. An assertion fault will result if you try.
75922
+** If the initial value of register P1 is less than 1, then the
75923
+** value is unchanged and control passes through to the next instruction.
7585275924
*/
7585375925
case OP_IfPos: { /* jump, in1 */
7585475926
pIn1 = &aMem[pOp->p1];
7585575927
assert( pIn1->flags&MEM_Int );
7585675928
VdbeBranchTaken( pIn1->u.i>0, 2);
@@ -75875,27 +75947,63 @@
7587575947
pc = pOp->p2 - 1;
7587675948
}
7587775949
break;
7587875950
}
7587975951
75880
-/* Opcode: IfZero P1 P2 P3 * *
75881
-** Synopsis: r[P1]+=P3, if r[P1]==0 goto P2
75952
+/* Opcode: IfNotZero P1 P2 P3 * *
75953
+** Synopsis: if r[P1]!=0 then r[P1]+=P3, goto P2
7588275954
**
75883
-** The register P1 must contain an integer. Add literal P3 to the
75884
-** value in register P1. If the result is exactly 0, jump to P2.
75955
+** Register P1 must contain an integer. If the content of register P1 is
75956
+** initially nonzero, then add P3 to P1 and jump to P2. If register P1 is
75957
+** initially zero, leave it unchanged and fall through.
7588575958
*/
75886
-case OP_IfZero: { /* jump, in1 */
75959
+case OP_IfNotZero: { /* jump, in1 */
75960
+ pIn1 = &aMem[pOp->p1];
75961
+ assert( pIn1->flags&MEM_Int );
75962
+ VdbeBranchTaken(pIn1->u.i<0, 2);
75963
+ if( pIn1->u.i ){
75964
+ pIn1->u.i += pOp->p3;
75965
+ pc = pOp->p2 - 1;
75966
+ }
75967
+ break;
75968
+}
75969
+
75970
+/* Opcode: DecrJumpZero P1 P2 * * *
75971
+** Synopsis: if (--r[P1])==0 goto P2
75972
+**
75973
+** Register P1 must hold an integer. Decrement the value in register P1
75974
+** then jump to P2 if the new value is exactly zero.
75975
+*/
75976
+case OP_DecrJumpZero: { /* jump, in1 */
7588775977
pIn1 = &aMem[pOp->p1];
7588875978
assert( pIn1->flags&MEM_Int );
75889
- pIn1->u.i += pOp->p3;
75979
+ pIn1->u.i--;
7589075980
VdbeBranchTaken(pIn1->u.i==0, 2);
7589175981
if( pIn1->u.i==0 ){
7589275982
pc = pOp->p2 - 1;
7589375983
}
7589475984
break;
7589575985
}
7589675986
75987
+
75988
+/* Opcode: JumpZeroIncr P1 P2 * * *
75989
+** Synopsis: if (r[P1]++)==0 ) goto P2
75990
+**
75991
+** The register P1 must contain an integer. If register P1 is initially
75992
+** zero, then jump to P2. Increment register P1 regardless of whether or
75993
+** not the jump is taken.
75994
+*/
75995
+case OP_JumpZeroIncr: { /* jump, in1 */
75996
+ pIn1 = &aMem[pOp->p1];
75997
+ assert( pIn1->flags&MEM_Int );
75998
+ VdbeBranchTaken(pIn1->u.i==0, 2);
75999
+ if( (pIn1->u.i++)==0 ){
76000
+ pc = pOp->p2 - 1;
76001
+ }
76002
+ break;
76003
+}
76004
+
7589776005
/* Opcode: AggStep * P2 P3 P4 P5
7589876006
** Synopsis: accum=r[P3] step(r[P2@P5])
7589976007
**
7590076008
** Execute the step function for an aggregate. The
7590176009
** function has P5 arguments. P4 is a pointer to the FuncDef
@@ -97181,10 +97289,15 @@
9718197289
** pExpr points to an expression which implements a function. If
9718297290
** it is appropriate to apply the LIKE optimization to that function
9718397291
** then set aWc[0] through aWc[2] to the wildcard characters and
9718497292
** return TRUE. If the function is not a LIKE-style function then
9718597293
** return FALSE.
97294
+**
97295
+** *pIsNocase is set to true if uppercase and lowercase are equivalent for
97296
+** the function (default for LIKE). If the function makes the distinction
97297
+** between uppercase and lowercase (as does GLOB) then *pIsNocase is set to
97298
+** false.
9718697299
*/
9718797300
SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
9718897301
FuncDef *pDef;
9718997302
if( pExpr->op!=TK_FUNCTION
9719097303
|| !pExpr->x.pList
@@ -102972,10 +103085,21 @@
102972103085
}
102973103086
102974103087
/* Send an SQLITE_FCNTL_PRAGMA file-control to the underlying VFS
102975103088
** connection. If it returns SQLITE_OK, then assume that the VFS
102976103089
** handled the pragma and generate a no-op prepared statement.
103090
+ **
103091
+ ** IMPLEMENTATION-OF: R-12238-55120 Whenever a PRAGMA statement is parsed,
103092
+ ** an SQLITE_FCNTL_PRAGMA file control is sent to the open sqlite3_file
103093
+ ** object corresponding to the database file to which the pragma
103094
+ ** statement refers.
103095
+ **
103096
+ ** IMPLEMENTATION-OF: R-29875-31678 The argument to the SQLITE_FCNTL_PRAGMA
103097
+ ** file control is an array of pointers to strings (char**) in which the
103098
+ ** second element of the array is the name of the pragma and the third
103099
+ ** element is the argument to the pragma or NULL if the pragma has no
103100
+ ** argument.
102977103101
*/
102978103102
aFcntl[0] = 0;
102979103103
aFcntl[1] = zLeft;
102980103104
aFcntl[2] = zRight;
102981103105
aFcntl[3] = 0;
@@ -103732,34 +103856,46 @@
103732103856
Index *pIdx;
103733103857
Table *pTab;
103734103858
pIdx = sqlite3FindIndex(db, zRight, zDb);
103735103859
if( pIdx ){
103736103860
int i;
103737
- int mx = pPragma->iArg ? pIdx->nColumn : pIdx->nKeyCol;
103861
+ int mx;
103862
+ if( pPragma->iArg ){
103863
+ /* PRAGMA index_xinfo (newer version with more rows and columns) */
103864
+ mx = pIdx->nColumn;
103865
+ pParse->nMem = 6;
103866
+ }else{
103867
+ /* PRAGMA index_info (legacy version) */
103868
+ mx = pIdx->nKeyCol;
103869
+ pParse->nMem = 3;
103870
+ }
103738103871
pTab = pIdx->pTable;
103739
- sqlite3VdbeSetNumCols(v, 6);
103740
- pParse->nMem = 6;
103872
+ sqlite3VdbeSetNumCols(v, pParse->nMem);
103741103873
sqlite3CodeVerifySchema(pParse, iDb);
103742103874
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC);
103743103875
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE_STATIC);
103744103876
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE_STATIC);
103745
- sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "desc", SQLITE_STATIC);
103746
- sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "coll", SQLITE_STATIC);
103747
- sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "key", SQLITE_STATIC);
103877
+ if( pPragma->iArg ){
103878
+ sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "desc", SQLITE_STATIC);
103879
+ sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "coll", SQLITE_STATIC);
103880
+ sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "key", SQLITE_STATIC);
103881
+ }
103748103882
for(i=0; i<mx; i++){
103749103883
i16 cnum = pIdx->aiColumn[i];
103750103884
sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
103751103885
sqlite3VdbeAddOp2(v, OP_Integer, cnum, 2);
103752103886
if( cnum<0 ){
103753103887
sqlite3VdbeAddOp2(v, OP_Null, 0, 3);
103754103888
}else{
103755103889
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pTab->aCol[cnum].zName, 0);
103756103890
}
103757
- sqlite3VdbeAddOp2(v, OP_Integer, pIdx->aSortOrder[i], 4);
103758
- sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, pIdx->azColl[i], 0);
103759
- sqlite3VdbeAddOp2(v, OP_Integer, i<pIdx->nKeyCol, 6);
103760
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
103891
+ if( pPragma->iArg ){
103892
+ sqlite3VdbeAddOp2(v, OP_Integer, pIdx->aSortOrder[i], 4);
103893
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, pIdx->azColl[i], 0);
103894
+ sqlite3VdbeAddOp2(v, OP_Integer, i<pIdx->nKeyCol, 6);
103895
+ }
103896
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, pParse->nMem);
103761103897
}
103762103898
}
103763103899
}
103764103900
break;
103765103901
@@ -104457,12 +104593,13 @@
104457104593
#endif
104458104594
104459104595
/*
104460104596
** PRAGMA shrink_memory
104461104597
**
104462
- ** This pragma attempts to free as much memory as possible from the
104463
- ** current database connection.
104598
+ ** IMPLEMENTATION-OF: R-23445-46109 This pragma causes the database
104599
+ ** connection on which it is invoked to free up as much memory as it
104600
+ ** can, by calling sqlite3_db_release_memory().
104464104601
*/
104465104602
case PragTyp_SHRINK_MEMORY: {
104466104603
sqlite3_db_release_memory(db);
104467104604
break;
104468104605
}
@@ -104487,12 +104624,16 @@
104487104624
104488104625
/*
104489104626
** PRAGMA soft_heap_limit
104490104627
** PRAGMA soft_heap_limit = N
104491104628
**
104492
- ** Call sqlite3_soft_heap_limit64(N). Return the result. If N is omitted,
104493
- ** use -1.
104629
+ ** IMPLEMENTATION-OF: R-26343-45930 This pragma invokes the
104630
+ ** sqlite3_soft_heap_limit64() interface with the argument N, if N is
104631
+ ** specified and is a non-negative integer.
104632
+ ** IMPLEMENTATION-OF: R-64451-07163 The soft_heap_limit pragma always
104633
+ ** returns the same integer that would be returned by the
104634
+ ** sqlite3_soft_heap_limit64(-1) C-language function.
104494104635
*/
104495104636
case PragTyp_SOFT_HEAP_LIMIT: {
104496104637
sqlite3_int64 N;
104497104638
if( zRight && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK ){
104498104639
sqlite3_soft_heap_limit64(N);
@@ -106065,24 +106206,21 @@
106065106206
}else{
106066106207
op = OP_IdxInsert;
106067106208
}
106068106209
sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord);
106069106210
if( pSelect->iLimit ){
106070
- int addr1, addr2;
106211
+ int addr;
106071106212
int iLimit;
106072106213
if( pSelect->iOffset ){
106073106214
iLimit = pSelect->iOffset+1;
106074106215
}else{
106075106216
iLimit = pSelect->iLimit;
106076106217
}
106077
- addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit); VdbeCoverage(v);
106078
- sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1);
106079
- addr2 = sqlite3VdbeAddOp0(v, OP_Goto);
106080
- sqlite3VdbeJumpHere(v, addr1);
106218
+ addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, -1); VdbeCoverage(v);
106081106219
sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor);
106082106220
sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor);
106083
- sqlite3VdbeJumpHere(v, addr2);
106221
+ sqlite3VdbeJumpHere(v, addr);
106084106222
}
106085106223
}
106086106224
106087106225
/*
106088106226
** Add code to implement the OFFSET
@@ -106475,11 +106613,11 @@
106475106613
/* Jump to the end of the loop if the LIMIT is reached. Except, if
106476106614
** there is a sorter, in which case the sorter has already limited
106477106615
** the output for us.
106478106616
*/
106479106617
if( pSort==0 && p->iLimit ){
106480
- sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v);
106618
+ sqlite3VdbeAddOp2(v, OP_DecrJumpZero, p->iLimit, iBreak); VdbeCoverage(v);
106481106619
}
106482106620
}
106483106621
106484106622
/*
106485106623
** Allocate a KeyInfo object sufficient for an index of N key columns and
@@ -107328,11 +107466,11 @@
107328107466
}
107329107467
}else{
107330107468
sqlite3ExprCode(pParse, p->pLimit, iLimit);
107331107469
sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeCoverage(v);
107332107470
VdbeComment((v, "LIMIT counter"));
107333
- sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak); VdbeCoverage(v);
107471
+ sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, iBreak); VdbeCoverage(v);
107334107472
}
107335107473
if( p->pOffset ){
107336107474
p->iOffset = iOffset = ++pParse->nMem;
107337107475
pParse->nMem++; /* Allocate an extra register for limit+offset */
107338107476
sqlite3ExprCode(pParse, p->pOffset, iOffset);
@@ -107547,11 +107685,11 @@
107547107685
addrCont = sqlite3VdbeMakeLabel(v);
107548107686
codeOffset(v, regOffset, addrCont);
107549107687
selectInnerLoop(pParse, p, p->pEList, iCurrent,
107550107688
0, 0, pDest, addrCont, addrBreak);
107551107689
if( regLimit ){
107552
- sqlite3VdbeAddOp3(v, OP_IfZero, regLimit, addrBreak, -1);
107690
+ sqlite3VdbeAddOp2(v, OP_DecrJumpZero, regLimit, addrBreak);
107553107691
VdbeCoverage(v);
107554107692
}
107555107693
sqlite3VdbeResolveLabel(v, addrCont);
107556107694
107557107695
/* Execute the recursive SELECT taking the single row in Current as
@@ -107772,11 +107910,11 @@
107772107910
}
107773107911
p->pPrior = 0;
107774107912
p->iLimit = pPrior->iLimit;
107775107913
p->iOffset = pPrior->iOffset;
107776107914
if( p->iLimit ){
107777
- addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit); VdbeCoverage(v);
107915
+ addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
107778107916
VdbeComment((v, "Jump ahead if LIMIT reached"));
107779107917
}
107780107918
explainSetInteger(iSub2, pParse->iNextSelectId);
107781107919
rc = sqlite3Select(pParse, p, &dest);
107782107920
testcase( rc!=SQLITE_OK );
@@ -108173,11 +108311,11 @@
108173108311
}
108174108312
108175108313
/* Jump to the end of the loop if the LIMIT is reached.
108176108314
*/
108177108315
if( p->iLimit ){
108178
- sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v);
108316
+ sqlite3VdbeAddOp2(v, OP_DecrJumpZero, p->iLimit, iBreak); VdbeCoverage(v);
108179108317
}
108180108318
108181108319
/* Generate the subroutine return
108182108320
*/
108183108321
sqlite3VdbeResolveLabel(v, iContinue);
@@ -114787,10 +114925,12 @@
114787114925
int addrNxt; /* Jump here to start the next IN combination */
114788114926
int addrSkip; /* Jump here for next iteration of skip-scan */
114789114927
int addrCont; /* Jump here to continue with the next loop cycle */
114790114928
int addrFirst; /* First instruction of interior of the loop */
114791114929
int addrBody; /* Beginning of the body of this loop */
114930
+ int iLikeRepCntr; /* LIKE range processing counter register */
114931
+ int addrLikeRep; /* LIKE range processing address */
114792114932
u8 iFrom; /* Which entry in the FROM clause */
114793114933
u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */
114794114934
int p1, p2; /* Operands of the opcode used to ends the loop */
114795114935
union { /* Information that depends on pWLoop->wsFlags */
114796114936
struct {
@@ -114971,11 +115111,11 @@
114971115111
WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
114972115112
WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
114973115113
} u;
114974115114
LogEst truthProb; /* Probability of truth for this expression */
114975115115
u16 eOperator; /* A WO_xx value describing <op> */
114976
- u8 wtFlags; /* TERM_xxx bit flags. See below */
115116
+ u16 wtFlags; /* TERM_xxx bit flags. See below */
114977115117
u8 nChild; /* Number of children that must disable us */
114978115118
WhereClause *pWC; /* The clause this term is part of */
114979115119
Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */
114980115120
Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */
114981115121
};
@@ -114993,10 +115133,13 @@
114993115133
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
114994115134
# define TERM_VNULL 0x80 /* Manufactured x>NULL or x<=NULL term */
114995115135
#else
114996115136
# define TERM_VNULL 0x00 /* Disabled if not using stat3 */
114997115137
#endif
115138
+#define TERM_LIKEOPT 0x100 /* Virtual terms from the LIKE optimization */
115139
+#define TERM_LIKECOND 0x200 /* Conditionally this LIKE operator term */
115140
+#define TERM_LIKE 0x400 /* The original LIKE operator */
114998115141
114999115142
/*
115000115143
** An instance of the WhereScan object is used as an iterator for locating
115001115144
** terms in the WHERE clause that are useful to the query planner.
115002115145
*/
@@ -115368,11 +115511,11 @@
115368115511
** WARNING: This routine might reallocate the space used to store
115369115512
** WhereTerms. All pointers to WhereTerms should be invalidated after
115370115513
** calling this routine. Such pointers may be reinitialized by referencing
115371115514
** the pWC->a[] array.
115372115515
*/
115373
-static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
115516
+static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){
115374115517
WhereTerm *pTerm;
115375115518
int idx;
115376115519
testcase( wtFlags & TERM_VIRTUAL );
115377115520
if( pWC->nTerm>=pWC->nSlot ){
115378115521
WhereTerm *pOld = pWC->a;
@@ -115793,11 +115936,15 @@
115793115936
** Check to see if the given expression is a LIKE or GLOB operator that
115794115937
** can be optimized using inequality constraints. Return TRUE if it is
115795115938
** so and false if not.
115796115939
**
115797115940
** In order for the operator to be optimizible, the RHS must be a string
115798
-** literal that does not begin with a wildcard.
115941
+** literal that does not begin with a wildcard. The LHS must be a column
115942
+** that may only be NULL, a string, or a BLOB, never a number. (This means
115943
+** that virtual tables cannot participate in the LIKE optimization.) If the
115944
+** collating sequence for the column on the LHS must be appropriate for
115945
+** the operator.
115799115946
*/
115800115947
static int isLikeOrGlob(
115801115948
Parse *pParse, /* Parsing and code generating context */
115802115949
Expr *pExpr, /* Test this expression */
115803115950
Expr **ppPrefix, /* Pointer to TK_STRING expression with pattern prefix */
@@ -115822,11 +115969,11 @@
115822115969
#endif
115823115970
pList = pExpr->x.pList;
115824115971
pLeft = pList->a[1].pExpr;
115825115972
if( pLeft->op!=TK_COLUMN
115826115973
|| sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
115827
- || IsVirtual(pLeft->pTab)
115974
+ || IsVirtual(pLeft->pTab) /* Value might be numeric */
115828115975
){
115829115976
/* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must
115830115977
** be the name of an indexed column with TEXT affinity. */
115831115978
return 0;
115832115979
}
@@ -116271,11 +116418,11 @@
116271116418
Bitmask prereqLeft; /* Prerequesites of the pExpr->pLeft */
116272116419
Bitmask prereqAll; /* Prerequesites of pExpr */
116273116420
Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */
116274116421
Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */
116275116422
int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */
116276
- int noCase = 0; /* LIKE/GLOB distinguishes case */
116423
+ int noCase = 0; /* uppercase equivalent to lowercase */
116277116424
int op; /* Top-level operator. pExpr->op */
116278116425
Parse *pParse = pWInfo->pParse; /* Parsing context */
116279116426
sqlite3 *db = pParse->db; /* Database connection */
116280116427
116281116428
if( db->mallocFailed ){
@@ -116409,16 +116556,19 @@
116409116556
116410116557
#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION
116411116558
/* Add constraints to reduce the search space on a LIKE or GLOB
116412116559
** operator.
116413116560
**
116414
- ** A like pattern of the form "x LIKE 'abc%'" is changed into constraints
116561
+ ** A like pattern of the form "x LIKE 'aBc%'" is changed into constraints
116415116562
**
116416
- ** x>='abc' AND x<'abd' AND x LIKE 'abc%'
116563
+ ** x>='ABC' AND x<'abd' AND x LIKE 'aBc%'
116417116564
**
116418116565
** The last character of the prefix "abc" is incremented to form the
116419
- ** termination condition "abd".
116566
+ ** termination condition "abd". If case is not significant (the default
116567
+ ** for LIKE) then the lower-bound is made all uppercase and the upper-
116568
+ ** bound is made all lowercase so that the bounds also work when comparing
116569
+ ** BLOBs.
116420116570
*/
116421116571
if( pWC->op==TK_AND
116422116572
&& isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase)
116423116573
){
116424116574
Expr *pLeft; /* LHS of LIKE/GLOB operator */
@@ -116426,13 +116576,29 @@
116426116576
Expr *pNewExpr1;
116427116577
Expr *pNewExpr2;
116428116578
int idxNew1;
116429116579
int idxNew2;
116430116580
Token sCollSeqName; /* Name of collating sequence */
116581
+ const u16 wtFlags = TERM_LIKEOPT | TERM_VIRTUAL | TERM_DYNAMIC;
116431116582
116432116583
pLeft = pExpr->x.pList->a[1].pExpr;
116433116584
pStr2 = sqlite3ExprDup(db, pStr1, 0);
116585
+
116586
+ /* Convert the lower bound to upper-case and the upper bound to
116587
+ ** lower-case (upper-case is less than lower-case in ASCII) so that
116588
+ ** the range constraints also work for BLOBs
116589
+ */
116590
+ if( noCase && !pParse->db->mallocFailed ){
116591
+ int i;
116592
+ char c;
116593
+ pTerm->wtFlags |= TERM_LIKE;
116594
+ for(i=0; (c = pStr1->u.zToken[i])!=0; i++){
116595
+ pStr1->u.zToken[i] = sqlite3Toupper(c);
116596
+ pStr2->u.zToken[i] = sqlite3Tolower(c);
116597
+ }
116598
+ }
116599
+
116434116600
if( !db->mallocFailed ){
116435116601
u8 c, *pC; /* Last character before the first wildcard */
116436116602
pC = (u8*)&pStr2->u.zToken[sqlite3Strlen30(pStr2->u.zToken)-1];
116437116603
c = *pC;
116438116604
if( noCase ){
@@ -116448,23 +116614,23 @@
116448116614
*pC = c + 1;
116449116615
}
116450116616
sCollSeqName.z = noCase ? "NOCASE" : "BINARY";
116451116617
sCollSeqName.n = 6;
116452116618
pNewExpr1 = sqlite3ExprDup(db, pLeft, 0);
116453
- pNewExpr1 = sqlite3PExpr(pParse, TK_GE,
116619
+ pNewExpr1 = sqlite3PExpr(pParse, TK_GE,
116454116620
sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName),
116455116621
pStr1, 0);
116456116622
transferJoinMarkings(pNewExpr1, pExpr);
116457
- idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
116623
+ idxNew1 = whereClauseInsert(pWC, pNewExpr1, wtFlags);
116458116624
testcase( idxNew1==0 );
116459116625
exprAnalyze(pSrc, pWC, idxNew1);
116460116626
pNewExpr2 = sqlite3ExprDup(db, pLeft, 0);
116461116627
pNewExpr2 = sqlite3PExpr(pParse, TK_LT,
116462116628
sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName),
116463116629
pStr2, 0);
116464116630
transferJoinMarkings(pNewExpr2, pExpr);
116465
- idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
116631
+ idxNew2 = whereClauseInsert(pWC, pNewExpr2, wtFlags);
116466116632
testcase( idxNew2==0 );
116467116633
exprAnalyze(pSrc, pWC, idxNew2);
116468116634
pTerm = &pWC->a[idxTerm];
116469116635
if( isComplete ){
116470116636
markTermAsChild(pWC, idxNew1, idxTerm);
@@ -117635,24 +117801,47 @@
117635117801
** by indices, we disable them to prevent redundant tests in the inner
117636117802
** loop. We would get the correct results if nothing were ever disabled,
117637117803
** but joins might run a little slower. The trick is to disable as much
117638117804
** as we can without disabling too much. If we disabled in (1), we'd get
117639117805
** the wrong answer. See ticket #813.
117806
+**
117807
+** If all the children of a term are disabled, then that term is also
117808
+** automatically disabled. In this way, terms get disabled if derived
117809
+** virtual terms are tested first. For example:
117810
+**
117811
+** x GLOB 'abc*' AND x>='abc' AND x<'acd'
117812
+** \___________/ \______/ \_____/
117813
+** parent child1 child2
117814
+**
117815
+** Only the parent term was in the original WHERE clause. The child1
117816
+** and child2 terms were added by the LIKE optimization. If both of
117817
+** the virtual child terms are valid, then testing of the parent can be
117818
+** skipped.
117819
+**
117820
+** Usually the parent term is marked as TERM_CODED. But if the parent
117821
+** term was originally TERM_LIKE, then the parent gets TERM_LIKECOND instead.
117822
+** The TERM_LIKECOND marking indicates that the term should be coded inside
117823
+** a conditional such that is only evaluated on the second pass of a
117824
+** LIKE-optimization loop, when scanning BLOBs instead of strings.
117640117825
*/
117641117826
static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
117642
- if( pTerm
117827
+ int nLoop = 0;
117828
+ while( pTerm
117643117829
&& (pTerm->wtFlags & TERM_CODED)==0
117644117830
&& (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin))
117645117831
&& (pLevel->notReady & pTerm->prereqAll)==0
117646117832
){
117647
- pTerm->wtFlags |= TERM_CODED;
117648
- if( pTerm->iParent>=0 ){
117649
- WhereTerm *pOther = &pTerm->pWC->a[pTerm->iParent];
117650
- if( (--pOther->nChild)==0 ){
117651
- disableTerm(pLevel, pOther);
117652
- }
117833
+ if( nLoop && (pTerm->wtFlags & TERM_LIKE)!=0 ){
117834
+ pTerm->wtFlags |= TERM_LIKECOND;
117835
+ }else{
117836
+ pTerm->wtFlags |= TERM_CODED;
117653117837
}
117838
+ if( pTerm->iParent<0 ) break;
117839
+ pTerm = &pTerm->pWC->a[pTerm->iParent];
117840
+ pTerm->nChild--;
117841
+ if( pTerm->nChild!=0 ) break;
117842
+ nLoop++;
117654117843
}
117655117844
}
117656117845
117657117846
/*
117658117847
** Code an OP_Affinity opcode to apply the column affinity string zAff
@@ -118132,11 +118321,30 @@
118132118321
}
118133118322
#else
118134118323
# define addScanStatus(a, b, c, d) ((void)d)
118135118324
#endif
118136118325
118137
-
118326
+/*
118327
+** Look at the last instruction coded. If that instruction is OP_String8
118328
+** and if pLoop->iLikeRepCntr is non-zero, then change the P3 to be
118329
+** pLoop->iLikeRepCntr and set P5.
118330
+**
118331
+** The LIKE optimization trys to evaluate "x LIKE 'abc%'" as a range
118332
+** expression: "x>='ABC' AND x<'abd'". But this requires that the range
118333
+** scan loop run twice, once for strings and a second time for BLOBs.
118334
+** The OP_String opcodes on the second pass convert the upper and lower
118335
+** bound string contants to blobs. This routine makes the necessary changes
118336
+** to the OP_String opcodes for that to happen.
118337
+*/
118338
+static void whereLikeOptimizationStringFixup(Vdbe *v, WhereLevel *pLevel){
118339
+ VdbeOp *pOp;
118340
+ pOp = sqlite3VdbeGetOp(v, -1);
118341
+ if( pLevel->iLikeRepCntr && pOp->opcode==OP_String8 ){
118342
+ pOp->p3 = pLevel->iLikeRepCntr;
118343
+ pOp->p5 = 1;
118344
+ }
118345
+}
118138118346
118139118347
/*
118140118348
** Generate code for the start of the iLevel-th loop in the WHERE clause
118141118349
** implementation described by pWInfo.
118142118350
*/
@@ -118466,10 +118674,23 @@
118466118674
nExtraReg = 1;
118467118675
}
118468118676
if( pLoop->wsFlags & WHERE_TOP_LIMIT ){
118469118677
pRangeEnd = pLoop->aLTerm[j++];
118470118678
nExtraReg = 1;
118679
+ if( pRangeStart
118680
+ && (pRangeStart->wtFlags & TERM_LIKEOPT)!=0
118681
+ && (pRangeEnd->wtFlags & TERM_LIKEOPT)!=0
118682
+ ){
118683
+ pLevel->iLikeRepCntr = ++pParse->nMem;
118684
+ testcase( bRev );
118685
+ testcase( pIdx->aSortOrder[nEq]==SQLITE_SO_DESC );
118686
+ sqlite3VdbeAddOp2(v, OP_Integer,
118687
+ bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC),
118688
+ pLevel->iLikeRepCntr);
118689
+ VdbeComment((v, "LIKE loop counter"));
118690
+ pLevel->addrLikeRep = sqlite3VdbeCurrentAddr(v);
118691
+ }
118471118692
if( pRangeStart==0
118472118693
&& (j = pIdx->aiColumn[nEq])>=0
118473118694
&& pIdx->pTable->aCol[j].notNull==0
118474118695
){
118475118696
bSeekPastNull = 1;
@@ -118508,10 +118729,11 @@
118508118729
/* Seek the index cursor to the start of the range. */
118509118730
nConstraint = nEq;
118510118731
if( pRangeStart ){
118511118732
Expr *pRight = pRangeStart->pExpr->pRight;
118512118733
sqlite3ExprCode(pParse, pRight, regBase+nEq);
118734
+ whereLikeOptimizationStringFixup(v, pLevel);
118513118735
if( (pRangeStart->wtFlags & TERM_VNULL)==0
118514118736
&& sqlite3ExprCanBeNull(pRight)
118515118737
){
118516118738
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
118517118739
VdbeCoverage(v);
@@ -118553,10 +118775,11 @@
118553118775
nConstraint = nEq;
118554118776
if( pRangeEnd ){
118555118777
Expr *pRight = pRangeEnd->pExpr->pRight;
118556118778
sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
118557118779
sqlite3ExprCode(pParse, pRight, regBase+nEq);
118780
+ whereLikeOptimizationStringFixup(v, pLevel);
118558118781
if( (pRangeEnd->wtFlags & TERM_VNULL)==0
118559118782
&& sqlite3ExprCanBeNull(pRight)
118560118783
){
118561118784
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
118562118785
VdbeCoverage(v);
@@ -118780,11 +119003,12 @@
118780119003
** eliminating duplicates from other WHERE clauses, the action for each
118781119004
** sub-WHERE clause is to to invoke the main loop body as a subroutine.
118782119005
*/
118783119006
wctrlFlags = WHERE_OMIT_OPEN_CLOSE
118784119007
| WHERE_FORCE_TABLE
118785
- | WHERE_ONETABLE_ONLY;
119008
+ | WHERE_ONETABLE_ONLY
119009
+ | WHERE_NO_AUTOINDEX;
118786119010
for(ii=0; ii<pOrWc->nTerm; ii++){
118787119011
WhereTerm *pOrTerm = &pOrWc->a[ii];
118788119012
if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
118789119013
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
118790119014
Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
@@ -118942,10 +119166,11 @@
118942119166
/* Insert code to test every subexpression that can be completely
118943119167
** computed using the current set of tables.
118944119168
*/
118945119169
for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
118946119170
Expr *pE;
119171
+ int skipLikeAddr = 0;
118947119172
testcase( pTerm->wtFlags & TERM_VIRTUAL );
118948119173
testcase( pTerm->wtFlags & TERM_CODED );
118949119174
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
118950119175
if( (pTerm->prereqAll & pLevel->notReady)!=0 ){
118951119176
testcase( pWInfo->untestedTerms==0
@@ -118955,12 +119180,18 @@
118955119180
}
118956119181
pE = pTerm->pExpr;
118957119182
assert( pE!=0 );
118958119183
if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
118959119184
continue;
119185
+ }
119186
+ if( pTerm->wtFlags & TERM_LIKECOND ){
119187
+ assert( pLevel->iLikeRepCntr>0 );
119188
+ skipLikeAddr = sqlite3VdbeAddOp1(v, OP_IfNot, pLevel->iLikeRepCntr);
119189
+ VdbeCoverage(v);
118960119190
}
118961119191
sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
119192
+ if( skipLikeAddr ) sqlite3VdbeJumpHere(v, skipLikeAddr);
118962119193
pTerm->wtFlags |= TERM_CODED;
118963119194
}
118964119195
118965119196
/* Insert code to test for implied constraints based on transitivity
118966119197
** of the "==" operator.
@@ -119974,10 +120205,11 @@
119974120205
rLogSize = estLog(rSize);
119975120206
119976120207
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
119977120208
/* Automatic indexes */
119978120209
if( !pBuilder->pOrSet
120210
+ && (pWInfo->wctrlFlags & WHERE_NO_AUTOINDEX)==0
119979120211
&& (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0
119980120212
&& pSrc->pIndex==0
119981120213
&& !pSrc->viaCoroutine
119982120214
&& !pSrc->notIndexed
119983120215
&& HasRowid(pTab)
@@ -121758,10 +121990,20 @@
121758121990
if( pLevel->addrSkip ){
121759121991
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrSkip);
121760121992
VdbeComment((v, "next skip-scan on %s", pLoop->u.btree.pIndex->zName));
121761121993
sqlite3VdbeJumpHere(v, pLevel->addrSkip);
121762121994
sqlite3VdbeJumpHere(v, pLevel->addrSkip-2);
121995
+ }
121996
+ if( pLevel->addrLikeRep ){
121997
+ int op;
121998
+ if( sqlite3VdbeGetOp(v, pLevel->addrLikeRep-1)->p1 ){
121999
+ op = OP_DecrJumpZero;
122000
+ }else{
122001
+ op = OP_JumpZeroIncr;
122002
+ }
122003
+ sqlite3VdbeAddOp2(v, op, pLevel->iLikeRepCntr, pLevel->addrLikeRep);
122004
+ VdbeCoverage(v);
121763122005
}
121764122006
if( pLevel->iLeftJoin ){
121765122007
addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
121766122008
assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
121767122009
|| (pLoop->wsFlags & WHERE_INDEXED)!=0 );
@@ -126982,30 +127224,32 @@
126982127224
/* Mutex configuration options are only available in a threadsafe
126983127225
** compile.
126984127226
*/
126985127227
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-54466-46756 */
126986127228
case SQLITE_CONFIG_SINGLETHREAD: {
126987
- /* Disable all mutexing */
126988
- sqlite3GlobalConfig.bCoreMutex = 0;
126989
- sqlite3GlobalConfig.bFullMutex = 0;
127229
+ /* EVIDENCE-OF: R-02748-19096 This option sets the threading mode to
127230
+ ** Single-thread. */
127231
+ sqlite3GlobalConfig.bCoreMutex = 0; /* Disable mutex on core */
127232
+ sqlite3GlobalConfig.bFullMutex = 0; /* Disable mutex on connections */
126990127233
break;
126991127234
}
126992127235
#endif
126993127236
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-20520-54086 */
126994127237
case SQLITE_CONFIG_MULTITHREAD: {
126995
- /* Disable mutexing of database connections */
126996
- /* Enable mutexing of core data structures */
126997
- sqlite3GlobalConfig.bCoreMutex = 1;
126998
- sqlite3GlobalConfig.bFullMutex = 0;
127238
+ /* EVIDENCE-OF: R-14374-42468 This option sets the threading mode to
127239
+ ** Multi-thread. */
127240
+ sqlite3GlobalConfig.bCoreMutex = 1; /* Enable mutex on core */
127241
+ sqlite3GlobalConfig.bFullMutex = 0; /* Disable mutex on connections */
126999127242
break;
127000127243
}
127001127244
#endif
127002127245
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-59593-21810 */
127003127246
case SQLITE_CONFIG_SERIALIZED: {
127004
- /* Enable all mutexing */
127005
- sqlite3GlobalConfig.bCoreMutex = 1;
127006
- sqlite3GlobalConfig.bFullMutex = 1;
127247
+ /* EVIDENCE-OF: R-41220-51800 This option sets the threading mode to
127248
+ ** Serialized. */
127249
+ sqlite3GlobalConfig.bCoreMutex = 1; /* Enable mutex on core */
127250
+ sqlite3GlobalConfig.bFullMutex = 1; /* Enable mutex on connections */
127007127251
break;
127008127252
}
127009127253
#endif
127010127254
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-63666-48755 */
127011127255
case SQLITE_CONFIG_MUTEX: {
@@ -127113,11 +127357,12 @@
127113127357
** SQLITE_ENABLE_MEMSYS5 and returns SQLITE_ERROR if invoked otherwise. */
127114127358
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
127115127359
case SQLITE_CONFIG_HEAP: {
127116127360
/* EVIDENCE-OF: R-19854-42126 There are three arguments to
127117127361
** SQLITE_CONFIG_HEAP: An 8-byte aligned pointer to the memory, the
127118
- ** number of bytes in the memory buffer, and the minimum allocation size. */
127362
+ ** number of bytes in the memory buffer, and the minimum allocation size.
127363
+ */
127119127364
sqlite3GlobalConfig.pHeap = va_arg(ap, void*);
127120127365
sqlite3GlobalConfig.nHeap = va_arg(ap, int);
127121127366
sqlite3GlobalConfig.mnReq = va_arg(ap, int);
127122127367
127123127368
if( sqlite3GlobalConfig.mnReq<1 ){
@@ -127218,11 +127463,13 @@
127218127463
** EVIDENCE-OF: R-34993-45031 The maximum allowed mmap size will be
127219127464
** silently truncated if necessary so that it does not exceed the
127220127465
** compile-time maximum mmap size set by the SQLITE_MAX_MMAP_SIZE
127221127466
** compile-time option.
127222127467
*/
127223
- if( mxMmap<0 || mxMmap>SQLITE_MAX_MMAP_SIZE ) mxMmap = SQLITE_MAX_MMAP_SIZE;
127468
+ if( mxMmap<0 || mxMmap>SQLITE_MAX_MMAP_SIZE ){
127469
+ mxMmap = SQLITE_MAX_MMAP_SIZE;
127470
+ }
127224127471
if( szMmap<0 ) szMmap = SQLITE_DEFAULT_MMAP_SIZE;
127225127472
if( szMmap>mxMmap) szMmap = mxMmap;
127226127473
sqlite3GlobalConfig.mxMmap = mxMmap;
127227127474
sqlite3GlobalConfig.szMmap = szMmap;
127228127475
break;
@@ -129062,11 +129309,23 @@
129062129309
for(iIn=0; iIn<nUri; iIn++) nByte += (zUri[iIn]=='&');
129063129310
zFile = sqlite3_malloc(nByte);
129064129311
if( !zFile ) return SQLITE_NOMEM;
129065129312
129066129313
iIn = 5;
129067
-#ifndef SQLITE_ALLOW_URI_AUTHORITY
129314
+#ifdef SQLITE_ALLOW_URI_AUTHORITY
129315
+ if( strncmp(zUri+5, "///", 3)==0 ){
129316
+ iIn = 7;
129317
+ /* The following condition causes URIs with five leading / characters
129318
+ ** like file://///host/path to be converted into UNCs like //host/path.
129319
+ ** The correct URI for that UNC has only two or four leading / characters
129320
+ ** file://host/path or file:////host/path. But 5 leading slashes is a
129321
+ ** common error, we are told, so we handle it as a special case. */
129322
+ if( strncmp(zUri+7, "///", 3)==0 ){ iIn++; }
129323
+ }else if( strncmp(zUri+5, "//localhost/", 12)==0 ){
129324
+ iIn = 16;
129325
+ }
129326
+#else
129068129327
/* Discard the scheme and authority segments of the URI. */
129069129328
if( zUri[5]=='/' && zUri[6]=='/' ){
129070129329
iIn = 7;
129071129330
while( zUri[iIn] && zUri[iIn]!='/' ) iIn++;
129072129331
if( iIn!=7 && (iIn!=16 || memcmp("localhost", &zUri[7], 9)) ){
@@ -129505,11 +129764,12 @@
129505129764
sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT);
129506129765
129507129766
opendb_out:
129508129767
sqlite3_free(zOpen);
129509129768
if( db ){
129510
- assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 );
129769
+ assert( db->mutex!=0 || isThreadsafe==0
129770
+ || sqlite3GlobalConfig.bFullMutex==0 );
129511129771
sqlite3_mutex_leave(db->mutex);
129512129772
}
129513129773
rc = sqlite3_errcode(db);
129514129774
assert( db!=0 || rc==SQLITE_NOMEM );
129515129775
if( rc==SQLITE_NOMEM ){
@@ -130250,21 +130510,21 @@
130250130510
case SQLITE_TESTCTRL_ISINIT: {
130251130511
if( sqlite3GlobalConfig.isInit==0 ) rc = SQLITE_ERROR;
130252130512
break;
130253130513
}
130254130514
130255
- /* sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, onOff, tnum);
130515
+ /* sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, onOff, tnum);
130256130516
**
130257130517
** This test control is used to create imposter tables. "db" is a pointer
130258130518
** to the database connection. dbName is the database name (ex: "main" or
130259130519
** "temp") which will receive the imposter. "onOff" turns imposter mode on
130260130520
** or off. "tnum" is the root page of the b-tree to which the imposter
130261130521
** table should connect.
130262130522
**
130263130523
** Enable imposter mode only when the schema has already been parsed. Then
130264
- ** run a single CREATE TABLE statement to construct the imposter table in the
130265
- ** parsed schema. Then turn imposter mode back off again.
130524
+ ** run a single CREATE TABLE statement to construct the imposter table in
130525
+ ** the parsed schema. Then turn imposter mode back off again.
130266130526
**
130267130527
** If onOff==0 and tnum>0 then reset the schema for all databases, causing
130268130528
** the schema to be reparsed the next time it is needed. This has the
130269130529
** effect of erasing all imposter tables.
130270130530
*/
130271130531
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
1 /******************************************************************************
2 ** This file is an amalgamation of many separate C source files from SQLite
3 ** version 3.8.8. 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.
@@ -88,10 +88,48 @@
88 #endif /* _MSVC_H_ */
89
90 /************** End of msvc.h ************************************************/
91 /************** Continuing where we left off in sqliteInt.h ******************/
92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93 /*
94 ** These #defines should enable >2GB file support on POSIX if the
95 ** underlying operating system supports it. If the OS lacks
96 ** large file support, or if the OS is windows, these should be no-ops.
97 **
@@ -276,13 +314,13 @@
276 **
277 ** See also: [sqlite3_libversion()],
278 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
279 ** [sqlite_version()] and [sqlite_source_id()].
280 */
281 #define SQLITE_VERSION "3.8.8"
282 #define SQLITE_VERSION_NUMBER 3008008
283 #define SQLITE_SOURCE_ID "2015-02-25 14:25:31 6d132e7a224ee68b5cefe9222944aac5760ffc20"
284
285 /*
286 ** CAPI3REF: Run-Time Library Version Numbers
287 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
288 **
@@ -925,18 +963,20 @@
925 **
926 ** These integer constants are opcodes for the xFileControl method
927 ** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
928 ** interface.
929 **
 
 
930 ** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This
931 ** opcode causes the xFileControl method to write the current state of
932 ** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED],
933 ** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])
934 ** into an integer that the pArg argument points to. This capability
935 ** is used during testing and only needs to be supported when SQLITE_TEST
936 ** is defined.
937 ** <ul>
938 ** <li>[[SQLITE_FCNTL_SIZE_HINT]]
939 ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
940 ** layer a hint of how large the database file will grow to be during the
941 ** current transaction. This hint is not guaranteed to be accurate but it
942 ** is often close. The underlying VFS might choose to preallocate database
@@ -1057,11 +1097,13 @@
1057 ** the error message if the pragma fails. ^If the
1058 ** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal
1059 ** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA]
1060 ** file control returns [SQLITE_OK], then the parser assumes that the
1061 ** VFS has handled the PRAGMA itself and the parser generates a no-op
1062 ** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns
 
 
1063 ** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
1064 ** that the VFS encountered an error while handling the [PRAGMA] and the
1065 ** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
1066 ** file control occurs at the beginning of pragma statement analysis and so
1067 ** it is able to override built-in [PRAGMA] statements.
@@ -1916,11 +1958,10 @@
1916 ** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE
1917 ** <dd>^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is
1918 ** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro
1919 ** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value
1920 ** that specifies the maximum size of the created heap.
1921 ** </dl>
1922 **
1923 ** [[SQLITE_CONFIG_PCACHE_HDRSZ]]
1924 ** <dt>SQLITE_CONFIG_PCACHE_HDRSZ
1925 ** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which
1926 ** is a pointer to an integer and writes into that integer the number of extra
@@ -3356,20 +3397,18 @@
3356 ** The second argument, "zSql", is the statement to be compiled, encoded
3357 ** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2()
3358 ** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2()
3359 ** use UTF-16.
3360 **
3361 ** ^If the nByte argument is less than zero, then zSql is read up to the
3362 ** first zero terminator. ^If nByte is non-negative, then it is the maximum
3363 ** number of bytes read from zSql. ^When nByte is non-negative, the
3364 ** zSql string ends at either the first '\000' or '\u0000' character or
3365 ** the nByte-th byte, whichever comes first. If the caller knows
3366 ** that the supplied string is nul-terminated, then there is a small
3367 ** performance advantage to be gained by passing an nByte parameter that
3368 ** is equal to the number of bytes in the input string <i>including</i>
3369 ** the nul-terminator bytes as this saves SQLite from having to
3370 ** make a copy of the input string.
3371 **
3372 ** ^If pzTail is not NULL then *pzTail is made to point to the first byte
3373 ** past the end of the first SQL statement in zSql. These routines only
3374 ** compile the first statement in zSql, so *pzTail is left pointing to
3375 ** what remains uncompiled.
@@ -4394,12 +4433,12 @@
4394 ** DEPRECATED
4395 **
4396 ** These functions are [deprecated]. In order to maintain
4397 ** backwards compatibility with older code, these functions continue
4398 ** to be supported. However, new applications should avoid
4399 ** the use of these functions. To help encourage people to avoid
4400 ** using these functions, we are not going to tell you what they do.
4401 */
4402 #ifndef SQLITE_OMIT_DEPRECATED
4403 SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*);
4404 SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*);
4405 SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
@@ -7157,24 +7196,24 @@
7157 **
7158 ** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step()
7159 ** is not a permanent error and does not affect the return value of
7160 ** sqlite3_backup_finish().
7161 **
7162 ** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]]
7163 ** <b>sqlite3_backup_remaining() and sqlite3_backup_pagecount()</b>
7164 **
7165 ** ^Each call to sqlite3_backup_step() sets two values inside
7166 ** the [sqlite3_backup] object: the number of pages still to be backed
7167 ** up and the total number of pages in the source database file.
7168 ** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces
7169 ** retrieve these two values, respectively.
7170 **
7171 ** ^The values returned by these functions are only updated by
7172 ** sqlite3_backup_step(). ^If the source database is modified during a backup
7173 ** operation, then the values are not updated to account for any extra
7174 ** pages that need to be updated or the size of the source database file
7175 ** changing.
7176 **
7177 ** <b>Concurrent Usage of Database Handles</b>
7178 **
7179 ** ^The source [database connection] may be used by the application for other
7180 ** purposes while a backup operation is underway or being initialized.
@@ -8018,19 +8057,21 @@
8018 #ifndef SQLITE_MAX_FUNCTION_ARG
8019 # define SQLITE_MAX_FUNCTION_ARG 127
8020 #endif
8021
8022 /*
8023 ** The maximum number of in-memory pages to use for the main database
8024 ** table and for temporary tables. The SQLITE_DEFAULT_CACHE_SIZE
 
 
 
 
 
8025 */
8026 #ifndef SQLITE_DEFAULT_CACHE_SIZE
8027 # define SQLITE_DEFAULT_CACHE_SIZE 2000
8028 #endif
8029 #ifndef SQLITE_DEFAULT_TEMP_CACHE_SIZE
8030 # define SQLITE_DEFAULT_TEMP_CACHE_SIZE 500
8031 #endif
8032
8033 /*
8034 ** The default number of frames to accumulate in the log file before
8035 ** checkpointing the database in WAL mode.
8036 */
@@ -9733,27 +9774,29 @@
9733 #define OP_FkCounter 134 /* synopsis: fkctr[P1]+=P2 */
9734 #define OP_FkIfZero 135 /* synopsis: if fkctr[P1]==0 goto P2 */
9735 #define OP_MemMax 136 /* synopsis: r[P1]=max(r[P1],r[P2]) */
9736 #define OP_IfPos 137 /* synopsis: if r[P1]>0 goto P2 */
9737 #define OP_IfNeg 138 /* synopsis: r[P1]+=P3, if r[P1]<0 goto P2 */
9738 #define OP_IfZero 139 /* synopsis: r[P1]+=P3, if r[P1]==0 goto P2 */
9739 #define OP_AggFinal 140 /* synopsis: accum=r[P1] N=P2 */
9740 #define OP_IncrVacuum 141
9741 #define OP_Expire 142
9742 #define OP_TableLock 143 /* synopsis: iDb=P1 root=P2 write=P3 */
9743 #define OP_VBegin 144
9744 #define OP_VCreate 145
9745 #define OP_VDestroy 146
9746 #define OP_VOpen 147
9747 #define OP_VColumn 148 /* synopsis: r[P3]=vcolumn(P2) */
9748 #define OP_VNext 149
9749 #define OP_VRename 150
9750 #define OP_Pagecount 151
9751 #define OP_MaxPgcnt 152
9752 #define OP_Init 153 /* synopsis: Start at P2 */
9753 #define OP_Noop 154
9754 #define OP_Explain 155
 
 
9755
9756
9757 /* Properties such as "out2" or "jump" that are specified in
9758 ** comments following the "case" for each opcode in the vdbe.c
9759 ** are encoded into bitvectors as follows:
@@ -9781,13 +9824,13 @@
9781 /* 96 */ 0x24, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,\
9782 /* 104 */ 0x00, 0x01, 0x01, 0x01, 0x01, 0x08, 0x08, 0x00,\
9783 /* 112 */ 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00,\
9784 /* 120 */ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
9785 /* 128 */ 0x0c, 0x45, 0x15, 0x01, 0x02, 0x02, 0x00, 0x01,\
9786 /* 136 */ 0x08, 0x05, 0x05, 0x05, 0x00, 0x01, 0x00, 0x00,\
9787 /* 144 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02,\
9788 /* 152 */ 0x02, 0x01, 0x00, 0x00,}
9789
9790 /************** End of opcodes.h *********************************************/
9791 /************** Continuing where we left off in vdbe.h ***********************/
9792
9793 /*
@@ -12022,11 +12065,11 @@
12022 #define WHERE_ONEPASS_DESIRED 0x0004 /* Want to do one-pass UPDATE/DELETE */
12023 #define WHERE_DUPLICATES_OK 0x0008 /* Ok to return a row more than once */
12024 #define WHERE_OMIT_OPEN_CLOSE 0x0010 /* Table cursors are already open */
12025 #define WHERE_FORCE_TABLE 0x0020 /* Do not use an index-only search */
12026 #define WHERE_ONETABLE_ONLY 0x0040 /* Only code the 1st table in pTabList */
12027 /* 0x0080 // not currently used */
12028 #define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */
12029 #define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */
12030 #define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */
12031 #define WHERE_SORTBYGROUP 0x0800 /* Support sqlite3WhereIsSorted() */
12032 #define WHERE_REOPEN_IDX 0x1000 /* Try to use OP_ReopenIdx */
@@ -24969,27 +25012,29 @@
24969 /* 134 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
24970 /* 135 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
24971 /* 136 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
24972 /* 137 */ "IfPos" OpHelp("if r[P1]>0 goto P2"),
24973 /* 138 */ "IfNeg" OpHelp("r[P1]+=P3, if r[P1]<0 goto P2"),
24974 /* 139 */ "IfZero" OpHelp("r[P1]+=P3, if r[P1]==0 goto P2"),
24975 /* 140 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
24976 /* 141 */ "IncrVacuum" OpHelp(""),
24977 /* 142 */ "Expire" OpHelp(""),
24978 /* 143 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
24979 /* 144 */ "VBegin" OpHelp(""),
24980 /* 145 */ "VCreate" OpHelp(""),
24981 /* 146 */ "VDestroy" OpHelp(""),
24982 /* 147 */ "VOpen" OpHelp(""),
24983 /* 148 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
24984 /* 149 */ "VNext" OpHelp(""),
24985 /* 150 */ "VRename" OpHelp(""),
24986 /* 151 */ "Pagecount" OpHelp(""),
24987 /* 152 */ "MaxPgcnt" OpHelp(""),
24988 /* 153 */ "Init" OpHelp("Start at P2"),
24989 /* 154 */ "Noop" OpHelp(""),
24990 /* 155 */ "Explain" OpHelp(""),
 
 
24991 };
24992 return azName[i];
24993 }
24994 #endif
24995
@@ -25065,22 +25110,10 @@
25065 # else
25066 # define SQLITE_ENABLE_LOCKING_STYLE 0
25067 # endif
25068 #endif
25069
25070 /*
25071 ** Define the OS_VXWORKS pre-processor macro to 1 if building on
25072 ** vxworks, or 0 otherwise.
25073 */
25074 #ifndef OS_VXWORKS
25075 # if defined(__RTP__) || defined(_WRS_KERNEL)
25076 # define OS_VXWORKS 1
25077 # else
25078 # define OS_VXWORKS 0
25079 # endif
25080 #endif
25081
25082 /*
25083 ** standard include files.
25084 */
25085 #include <sys/types.h>
25086 #include <sys/stat.h>
@@ -25091,22 +25124,23 @@
25091 #include <errno.h>
25092 #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
25093 # include <sys/mman.h>
25094 #endif
25095
25096 #if SQLITE_ENABLE_LOCKING_STYLE || OS_VXWORKS
25097 # include <sys/ioctl.h>
25098 # if OS_VXWORKS
25099 # include <semaphore.h>
25100 # include <limits.h>
25101 # else
25102 # include <sys/file.h>
25103 # include <sys/param.h>
25104 # endif
25105 #endif /* SQLITE_ENABLE_LOCKING_STYLE */
25106
25107 #if defined(__APPLE__) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
 
 
 
 
 
 
25108 # include <sys/mount.h>
25109 #endif
25110
25111 #ifdef HAVE_UTIME
25112 # include <utime.h>
@@ -25142,10 +25176,14 @@
25142
25143 /*
25144 ** Maximum supported path-length.
25145 */
25146 #define MAX_PATHNAME 512
 
 
 
 
25147
25148 /*
25149 ** Only set the lastErrno if the error code is a real error and not
25150 ** a normal expected return code of SQLITE_BUSY or SQLITE_OK
25151 */
@@ -25231,11 +25269,11 @@
25231
25232 /* This variable holds the process id (pid) from when the xRandomness()
25233 ** method was called. If xOpen() is called from a different process id,
25234 ** indicating that a fork() has occurred, the PRNG will be reset.
25235 */
25236 static int randomnessPid = 0;
25237
25238 /*
25239 ** Allowed values for the unixFile.ctrlFlags bitmask:
25240 */
25241 #define UNIXFILE_EXCL 0x01 /* Connections from one process only */
@@ -25587,11 +25625,11 @@
25587 #define osFcntl ((int(*)(int,int,...))aSyscall[7].pCurrent)
25588
25589 { "read", (sqlite3_syscall_ptr)read, 0 },
25590 #define osRead ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent)
25591
25592 #if defined(USE_PREAD) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
25593 { "pread", (sqlite3_syscall_ptr)pread, 0 },
25594 #else
25595 { "pread", (sqlite3_syscall_ptr)0, 0 },
25596 #endif
25597 #define osPread ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].pCurrent)
@@ -25604,11 +25642,11 @@
25604 #define osPread64 ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[10].pCurrent)
25605
25606 { "write", (sqlite3_syscall_ptr)write, 0 },
25607 #define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
25608
25609 #if defined(USE_PREAD) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
25610 { "pwrite", (sqlite3_syscall_ptr)pwrite, 0 },
25611 #else
25612 { "pwrite", (sqlite3_syscall_ptr)0, 0 },
25613 #endif
25614 #define osPwrite ((ssize_t(*)(int,const void*,size_t,off_t))\
@@ -26743,11 +26781,12 @@
26743 int tErrno = 0;
26744
26745 assert( pFile );
26746 OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h,
26747 azFileLock(eFileLock), azFileLock(pFile->eFileLock),
26748 azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared , getpid()));
 
26749
26750 /* If there is already a lock of this type or more restrictive on the
26751 ** unixFile, do nothing. Don't use the end_lock: exit path, as
26752 ** unixEnterMutex() hasn't been called yet.
26753 */
@@ -26951,11 +26990,11 @@
26951 int rc = SQLITE_OK;
26952
26953 assert( pFile );
26954 OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock,
26955 pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
26956 getpid()));
26957
26958 assert( eFileLock<=SHARED_LOCK );
26959 if( pFile->eFileLock<=eFileLock ){
26960 return SQLITE_OK;
26961 }
@@ -27378,11 +27417,11 @@
27378 char *zLockFile = (char *)pFile->lockingContext;
27379 int rc;
27380
27381 assert( pFile );
27382 OSTRACE(("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock,
27383 pFile->eFileLock, getpid()));
27384 assert( eFileLock<=SHARED_LOCK );
27385
27386 /* no-op if possible */
27387 if( pFile->eFileLock==eFileLock ){
27388 return SQLITE_OK;
@@ -27441,14 +27480,13 @@
27441 ** a single exclusive lock. In other words, SHARED, RESERVED, and
27442 ** PENDING locks are the same thing as an EXCLUSIVE lock. SQLite
27443 ** still works when you do this, but concurrency is reduced since
27444 ** only a single process can be reading the database at a time.
27445 **
27446 ** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off or if
27447 ** compiling for VXWORKS.
27448 */
27449 #if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
27450
27451 /*
27452 ** Retry flock() calls that fail with EINTR
27453 */
27454 #ifdef EINTR
@@ -27597,11 +27635,11 @@
27597 static int flockUnlock(sqlite3_file *id, int eFileLock) {
27598 unixFile *pFile = (unixFile*)id;
27599
27600 assert( pFile );
27601 OSTRACE(("UNLOCK %d %d was %d pid=%d (flock)\n", pFile->h, eFileLock,
27602 pFile->eFileLock, getpid()));
27603 assert( eFileLock<=SHARED_LOCK );
27604
27605 /* no-op if possible */
27606 if( pFile->eFileLock==eFileLock ){
27607 return SQLITE_OK;
@@ -27658,11 +27696,11 @@
27658 ** This routine checks if there is a RESERVED lock held on the specified
27659 ** file by this or any other process. If such a lock is held, set *pResOut
27660 ** to a non-zero value otherwise *pResOut is set to zero. The return value
27661 ** is set to SQLITE_OK unless an I/O error occurs during lock checking.
27662 */
27663 static int semCheckReservedLock(sqlite3_file *id, int *pResOut) {
27664 int rc = SQLITE_OK;
27665 int reserved = 0;
27666 unixFile *pFile = (unixFile*)id;
27667
27668 SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
@@ -27725,11 +27763,11 @@
27725 ** access the file.
27726 **
27727 ** This routine will only increase a lock. Use the sqlite3OsUnlock()
27728 ** routine to lower a locking level.
27729 */
27730 static int semLock(sqlite3_file *id, int eFileLock) {
27731 unixFile *pFile = (unixFile*)id;
27732 sem_t *pSem = pFile->pInode->pSem;
27733 int rc = SQLITE_OK;
27734
27735 /* if we already have a lock, it is exclusive.
@@ -27758,18 +27796,18 @@
27758 ** must be either NO_LOCK or SHARED_LOCK.
27759 **
27760 ** If the locking level of the file descriptor is already at or below
27761 ** the requested locking level, this routine is a no-op.
27762 */
27763 static int semUnlock(sqlite3_file *id, int eFileLock) {
27764 unixFile *pFile = (unixFile*)id;
27765 sem_t *pSem = pFile->pInode->pSem;
27766
27767 assert( pFile );
27768 assert( pSem );
27769 OSTRACE(("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock,
27770 pFile->eFileLock, getpid()));
27771 assert( eFileLock<=SHARED_LOCK );
27772
27773 /* no-op if possible */
27774 if( pFile->eFileLock==eFileLock ){
27775 return SQLITE_OK;
@@ -27795,14 +27833,14 @@
27795 }
27796
27797 /*
27798 ** Close a file.
27799 */
27800 static int semClose(sqlite3_file *id) {
27801 if( id ){
27802 unixFile *pFile = (unixFile*)id;
27803 semUnlock(id, NO_LOCK);
27804 assert( pFile );
27805 unixEnterMutex();
27806 releaseInodeInfo(pFile);
27807 unixLeaveMutex();
27808 closeUnixFile(id);
@@ -27979,11 +28017,11 @@
27979 afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
27980
27981 assert( pFile );
27982 OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h,
27983 azFileLock(eFileLock), azFileLock(pFile->eFileLock),
27984 azFileLock(pInode->eFileLock), pInode->nShared , getpid()));
27985
27986 /* If there is already a lock of this type or more restrictive on the
27987 ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as
27988 ** unixEnterMutex() hasn't been called yet.
27989 */
@@ -28165,11 +28203,11 @@
28165 #endif
28166
28167 assert( pFile );
28168 OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock,
28169 pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
28170 getpid()));
28171
28172 assert( eFileLock<=SHARED_LOCK );
28173 if( pFile->eFileLock<=eFileLock ){
28174 return SQLITE_OK;
28175 }
@@ -29204,11 +29242,13 @@
29204 **
29205 ** This function should not be called directly by other code in this file.
29206 ** Instead, it should be called via macro osGetpagesize().
29207 */
29208 static int unixGetpagesize(void){
29209 #if defined(_BSD_SOURCE)
 
 
29210 return getpagesize();
29211 #else
29212 return (int)sysconf(_SC_PAGESIZE);
29213 #endif
29214 }
@@ -29833,11 +29873,11 @@
29833 }
29834 }
29835 }
29836 sqlite3_mutex_leave(pShmNode->mutex);
29837 OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
29838 p->id, getpid(), p->sharedMask, p->exclMask));
29839 return rc;
29840 }
29841
29842 /*
29843 ** Implement a memory barrier or memory fence on shared memory.
@@ -30236,11 +30276,11 @@
30236 dotlockUnlock, /* xUnlock method */
30237 dotlockCheckReservedLock, /* xCheckReservedLock method */
30238 0 /* xShmMap method */
30239 )
30240
30241 #if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
30242 IOMETHODS(
30243 flockIoFinder, /* Finder function name */
30244 flockIoMethods, /* sqlite3_io_methods object name */
30245 1, /* shared memory is disabled */
30246 flockClose, /* xClose method */
@@ -30254,14 +30294,14 @@
30254 #if OS_VXWORKS
30255 IOMETHODS(
30256 semIoFinder, /* Finder function name */
30257 semIoMethods, /* sqlite3_io_methods object name */
30258 1, /* shared memory is disabled */
30259 semClose, /* xClose method */
30260 semLock, /* xLock method */
30261 semUnlock, /* xUnlock method */
30262 semCheckReservedLock, /* xCheckReservedLock method */
30263 0 /* xShmMap method */
30264 )
30265 #endif
30266
30267 #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
@@ -30381,19 +30421,17 @@
30381 static const sqlite3_io_methods
30382 *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
30383
30384 #endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
30385
30386 #if OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE
30387 /*
30388 ** This "finder" function attempts to determine the best locking strategy
30389 ** for the database file "filePath". It then returns the sqlite3_io_methods
30390 ** object that implements that strategy.
30391 **
30392 ** This is for VXWorks only.
30393 */
30394 static const sqlite3_io_methods *autolockIoFinderImpl(
30395 const char *filePath, /* name of the database file */
30396 unixFile *pNew /* the open file object */
30397 ){
30398 struct flock lockInfo;
30399
@@ -30415,13 +30453,13 @@
30415 }else{
30416 return &semIoMethods;
30417 }
30418 }
30419 static const sqlite3_io_methods
30420 *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
30421
30422 #endif /* OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE */
30423
30424 /*
30425 ** An abstract type for a pointer to an IO method finder function:
30426 */
30427 typedef const sqlite3_io_methods *(*finder_type)(const char*,unixFile*);
@@ -30930,12 +30968,12 @@
30930 /* Detect a pid change and reset the PRNG. There is a race condition
30931 ** here such that two or more threads all trying to open databases at
30932 ** the same instant might all reset the PRNG. But multiple resets
30933 ** are harmless.
30934 */
30935 if( randomnessPid!=getpid() ){
30936 randomnessPid = getpid();
30937 sqlite3_randomness(0,0);
30938 }
30939
30940 memset(p, 0, sizeof(unixFile));
30941
@@ -31322,11 +31360,11 @@
31322 ** When testing, initializing zBuf[] to zero is all we do. That means
31323 ** that we always use the same random number sequence. This makes the
31324 ** tests repeatable.
31325 */
31326 memset(zBuf, 0, nBuf);
31327 randomnessPid = getpid();
31328 #if !defined(SQLITE_TEST)
31329 {
31330 int fd, got;
31331 fd = robust_open("/dev/urandom", O_RDONLY, 0);
31332 if( fd<0 ){
@@ -31643,11 +31681,11 @@
31643 #else
31644 # ifdef _CS_DARWIN_USER_TEMP_DIR
31645 {
31646 if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){
31647 OSTRACE(("GETLOCKPATH failed %s errno=%d pid=%d\n",
31648 lPath, errno, getpid()));
31649 return SQLITE_IOERR_LOCK;
31650 }
31651 len = strlcat(lPath, "sqliteplocks", maxLen);
31652 }
31653 # else
@@ -31665,11 +31703,11 @@
31665 char c = dbPath[i];
31666 lPath[i+len] = (c=='/')?'_':c;
31667 }
31668 lPath[i+len]='\0';
31669 strlcat(lPath, ":auto:", maxLen);
31670 OSTRACE(("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, getpid()));
31671 return SQLITE_OK;
31672 }
31673
31674 /*
31675 ** Creates the lock file and any missing directories in lockPath
@@ -31692,20 +31730,20 @@
31692 if( osMkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){
31693 int err=errno;
31694 if( err!=EEXIST ) {
31695 OSTRACE(("CREATELOCKPATH FAILED creating %s, "
31696 "'%s' proxy lock path=%s pid=%d\n",
31697 buf, strerror(err), lockPath, getpid()));
31698 return err;
31699 }
31700 }
31701 }
31702 start=i+1;
31703 }
31704 buf[i] = lockPath[i];
31705 }
31706 OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n", lockPath, getpid()));
31707 return 0;
31708 }
31709
31710 /*
31711 ** Create a new VFS file descriptor (stored in memory obtained from
@@ -32006,11 +32044,12 @@
32006 int readLen = 0;
32007 int tryOldLockPath = 0;
32008 int forceNewLockPath = 0;
32009
32010 OSTRACE(("TAKECONCH %d for %s pid=%d\n", conchFile->h,
32011 (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid()));
 
32012
32013 rc = proxyGetHostID(myHostID, &pError);
32014 if( (rc&0xff)==SQLITE_IOERR ){
32015 storeLastErrno(pFile, pError);
32016 goto end_takeconch;
@@ -32216,11 +32255,11 @@
32216
32217 pCtx = (proxyLockingContext *)pFile->lockingContext;
32218 conchFile = pCtx->conchFile;
32219 OSTRACE(("RELEASECONCH %d for %s pid=%d\n", conchFile->h,
32220 (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
32221 getpid()));
32222 if( pCtx->conchHeld>0 ){
32223 rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
32224 }
32225 pCtx->conchHeld = 0;
32226 OSTRACE(("RELEASECONCH %d %s\n", conchFile->h,
@@ -32358,11 +32397,11 @@
32358 }else{
32359 lockPath=(char *)path;
32360 }
32361
32362 OSTRACE(("TRANSPROXY %d for %s pid=%d\n", pFile->h,
32363 (lockPath ? lockPath : ":auto:"), getpid()));
32364
32365 pCtx = sqlite3_malloc( sizeof(*pCtx) );
32366 if( pCtx==0 ){
32367 return SQLITE_NOMEM;
32368 }
@@ -32699,26 +32738,28 @@
32699 ** Note that the sqlite3_vfs.pNext field of the VFS object is modified
32700 ** by the SQLite core when the VFS is registered. So the following
32701 ** array cannot be const.
32702 */
32703 static sqlite3_vfs aVfs[] = {
32704 #if SQLITE_ENABLE_LOCKING_STYLE && (OS_VXWORKS || defined(__APPLE__))
32705 UNIXVFS("unix", autolockIoFinder ),
 
 
32706 #else
32707 UNIXVFS("unix", posixIoFinder ),
32708 #endif
32709 UNIXVFS("unix-none", nolockIoFinder ),
32710 UNIXVFS("unix-dotfile", dotlockIoFinder ),
32711 UNIXVFS("unix-excl", posixIoFinder ),
32712 #if OS_VXWORKS
32713 UNIXVFS("unix-namedsem", semIoFinder ),
32714 #endif
32715 #if SQLITE_ENABLE_LOCKING_STYLE
32716 UNIXVFS("unix-posix", posixIoFinder ),
32717 #if !OS_VXWORKS
 
32718 UNIXVFS("unix-flock", flockIoFinder ),
32719 #endif
32720 #endif
32721 #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
32722 UNIXVFS("unix-afp", afpIoFinder ),
32723 UNIXVFS("unix-nfs", nfsIoFinder ),
32724 UNIXVFS("unix-proxy", proxyIoFinder ),
@@ -39072,16 +39113,24 @@
39072 sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 0);
39073 }
39074 }
39075
39076 /*
39077 ** Compute the number of pages of cache requested.
 
 
 
39078 */
39079 static int numberOfCachePages(PCache *p){
39080 if( p->szCache>=0 ){
 
 
39081 return p->szCache;
39082 }else{
 
 
 
39083 return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra));
39084 }
39085 }
39086
39087 /*************************************************** General Interfaces ******
@@ -68615,10 +68664,14 @@
68615 }
68616 SQLITE_API const void *sqlite3_value_text16le(sqlite3_value *pVal){
68617 return sqlite3ValueText(pVal, SQLITE_UTF16LE);
68618 }
68619 #endif /* SQLITE_OMIT_UTF16 */
 
 
 
 
68620 SQLITE_API int sqlite3_value_type(sqlite3_value* pVal){
68621 static const u8 aType[] = {
68622 SQLITE_BLOB, /* 0x00 */
68623 SQLITE_NULL, /* 0x01 */
68624 SQLITE_TEXT, /* 0x02 */
@@ -71290,11 +71343,11 @@
71290
71291 /* Opcode: String8 * P2 * P4 *
71292 ** Synopsis: r[P2]='P4'
71293 **
71294 ** P4 points to a nul terminated UTF-8 string. This opcode is transformed
71295 ** into a String before it is executed for the first time. During
71296 ** this transformation, the length of string P4 is computed and stored
71297 ** as the P1 parameter.
71298 */
71299 case OP_String8: { /* same as TK_STRING, out2-prerelease */
71300 assert( pOp->p4.z!=0 );
@@ -71322,22 +71375,34 @@
71322 goto too_big;
71323 }
71324 /* Fall through to the next case, OP_String */
71325 }
71326
71327 /* Opcode: String P1 P2 * P4 *
71328 ** Synopsis: r[P2]='P4' (len=P1)
71329 **
71330 ** The string value P4 of length P1 (bytes) is stored in register P2.
 
 
 
 
 
71331 */
71332 case OP_String: { /* out2-prerelease */
71333 assert( pOp->p4.z!=0 );
71334 pOut->flags = MEM_Str|MEM_Static|MEM_Term;
71335 pOut->z = pOp->p4.z;
71336 pOut->n = pOp->p1;
71337 pOut->enc = encoding;
71338 UPDATE_MAX_BLOBSIZE(pOut);
 
 
 
 
 
 
 
71339 break;
71340 }
71341
71342 /* Opcode: Null P1 P2 P3 * *
71343 ** Synopsis: r[P2..P3]=NULL
@@ -73325,11 +73390,16 @@
73325 ** the value of this counter needs to be restored too. */
73326 p->nStmtDefCons = db->nDeferredCons;
73327 p->nStmtDefImmCons = db->nDeferredImmCons;
73328 }
73329
73330 /* Gather the schema version number for checking */
 
 
 
 
 
73331 sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta);
73332 iGen = db->aDb[pOp->p1].pSchema->iGeneration;
73333 }else{
73334 iGen = iMeta = 0;
73335 }
@@ -75843,14 +75913,16 @@
75843 #endif /* SQLITE_OMIT_AUTOINCREMENT */
75844
75845 /* Opcode: IfPos P1 P2 * * *
75846 ** Synopsis: if r[P1]>0 goto P2
75847 **
75848 ** If the value of register P1 is 1 or greater, jump to P2.
 
 
75849 **
75850 ** It is illegal to use this instruction on a register that does
75851 ** not contain an integer. An assertion fault will result if you try.
75852 */
75853 case OP_IfPos: { /* jump, in1 */
75854 pIn1 = &aMem[pOp->p1];
75855 assert( pIn1->flags&MEM_Int );
75856 VdbeBranchTaken( pIn1->u.i>0, 2);
@@ -75875,27 +75947,63 @@
75875 pc = pOp->p2 - 1;
75876 }
75877 break;
75878 }
75879
75880 /* Opcode: IfZero P1 P2 P3 * *
75881 ** Synopsis: r[P1]+=P3, if r[P1]==0 goto P2
75882 **
75883 ** The register P1 must contain an integer. Add literal P3 to the
75884 ** value in register P1. If the result is exactly 0, jump to P2.
 
75885 */
75886 case OP_IfZero: { /* jump, in1 */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75887 pIn1 = &aMem[pOp->p1];
75888 assert( pIn1->flags&MEM_Int );
75889 pIn1->u.i += pOp->p3;
75890 VdbeBranchTaken(pIn1->u.i==0, 2);
75891 if( pIn1->u.i==0 ){
75892 pc = pOp->p2 - 1;
75893 }
75894 break;
75895 }
75896
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75897 /* Opcode: AggStep * P2 P3 P4 P5
75898 ** Synopsis: accum=r[P3] step(r[P2@P5])
75899 **
75900 ** Execute the step function for an aggregate. The
75901 ** function has P5 arguments. P4 is a pointer to the FuncDef
@@ -97181,10 +97289,15 @@
97181 ** pExpr points to an expression which implements a function. If
97182 ** it is appropriate to apply the LIKE optimization to that function
97183 ** then set aWc[0] through aWc[2] to the wildcard characters and
97184 ** return TRUE. If the function is not a LIKE-style function then
97185 ** return FALSE.
 
 
 
 
 
97186 */
97187 SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
97188 FuncDef *pDef;
97189 if( pExpr->op!=TK_FUNCTION
97190 || !pExpr->x.pList
@@ -102972,10 +103085,21 @@
102972 }
102973
102974 /* Send an SQLITE_FCNTL_PRAGMA file-control to the underlying VFS
102975 ** connection. If it returns SQLITE_OK, then assume that the VFS
102976 ** handled the pragma and generate a no-op prepared statement.
 
 
 
 
 
 
 
 
 
 
 
102977 */
102978 aFcntl[0] = 0;
102979 aFcntl[1] = zLeft;
102980 aFcntl[2] = zRight;
102981 aFcntl[3] = 0;
@@ -103732,34 +103856,46 @@
103732 Index *pIdx;
103733 Table *pTab;
103734 pIdx = sqlite3FindIndex(db, zRight, zDb);
103735 if( pIdx ){
103736 int i;
103737 int mx = pPragma->iArg ? pIdx->nColumn : pIdx->nKeyCol;
 
 
 
 
 
 
 
 
 
103738 pTab = pIdx->pTable;
103739 sqlite3VdbeSetNumCols(v, 6);
103740 pParse->nMem = 6;
103741 sqlite3CodeVerifySchema(pParse, iDb);
103742 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC);
103743 sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE_STATIC);
103744 sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE_STATIC);
103745 sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "desc", SQLITE_STATIC);
103746 sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "coll", SQLITE_STATIC);
103747 sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "key", SQLITE_STATIC);
 
 
103748 for(i=0; i<mx; i++){
103749 i16 cnum = pIdx->aiColumn[i];
103750 sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
103751 sqlite3VdbeAddOp2(v, OP_Integer, cnum, 2);
103752 if( cnum<0 ){
103753 sqlite3VdbeAddOp2(v, OP_Null, 0, 3);
103754 }else{
103755 sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pTab->aCol[cnum].zName, 0);
103756 }
103757 sqlite3VdbeAddOp2(v, OP_Integer, pIdx->aSortOrder[i], 4);
103758 sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, pIdx->azColl[i], 0);
103759 sqlite3VdbeAddOp2(v, OP_Integer, i<pIdx->nKeyCol, 6);
103760 sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
 
 
103761 }
103762 }
103763 }
103764 break;
103765
@@ -104457,12 +104593,13 @@
104457 #endif
104458
104459 /*
104460 ** PRAGMA shrink_memory
104461 **
104462 ** This pragma attempts to free as much memory as possible from the
104463 ** current database connection.
 
104464 */
104465 case PragTyp_SHRINK_MEMORY: {
104466 sqlite3_db_release_memory(db);
104467 break;
104468 }
@@ -104487,12 +104624,16 @@
104487
104488 /*
104489 ** PRAGMA soft_heap_limit
104490 ** PRAGMA soft_heap_limit = N
104491 **
104492 ** Call sqlite3_soft_heap_limit64(N). Return the result. If N is omitted,
104493 ** use -1.
 
 
 
 
104494 */
104495 case PragTyp_SOFT_HEAP_LIMIT: {
104496 sqlite3_int64 N;
104497 if( zRight && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK ){
104498 sqlite3_soft_heap_limit64(N);
@@ -106065,24 +106206,21 @@
106065 }else{
106066 op = OP_IdxInsert;
106067 }
106068 sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord);
106069 if( pSelect->iLimit ){
106070 int addr1, addr2;
106071 int iLimit;
106072 if( pSelect->iOffset ){
106073 iLimit = pSelect->iOffset+1;
106074 }else{
106075 iLimit = pSelect->iLimit;
106076 }
106077 addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit); VdbeCoverage(v);
106078 sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1);
106079 addr2 = sqlite3VdbeAddOp0(v, OP_Goto);
106080 sqlite3VdbeJumpHere(v, addr1);
106081 sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor);
106082 sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor);
106083 sqlite3VdbeJumpHere(v, addr2);
106084 }
106085 }
106086
106087 /*
106088 ** Add code to implement the OFFSET
@@ -106475,11 +106613,11 @@
106475 /* Jump to the end of the loop if the LIMIT is reached. Except, if
106476 ** there is a sorter, in which case the sorter has already limited
106477 ** the output for us.
106478 */
106479 if( pSort==0 && p->iLimit ){
106480 sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v);
106481 }
106482 }
106483
106484 /*
106485 ** Allocate a KeyInfo object sufficient for an index of N key columns and
@@ -107328,11 +107466,11 @@
107328 }
107329 }else{
107330 sqlite3ExprCode(pParse, p->pLimit, iLimit);
107331 sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeCoverage(v);
107332 VdbeComment((v, "LIMIT counter"));
107333 sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak); VdbeCoverage(v);
107334 }
107335 if( p->pOffset ){
107336 p->iOffset = iOffset = ++pParse->nMem;
107337 pParse->nMem++; /* Allocate an extra register for limit+offset */
107338 sqlite3ExprCode(pParse, p->pOffset, iOffset);
@@ -107547,11 +107685,11 @@
107547 addrCont = sqlite3VdbeMakeLabel(v);
107548 codeOffset(v, regOffset, addrCont);
107549 selectInnerLoop(pParse, p, p->pEList, iCurrent,
107550 0, 0, pDest, addrCont, addrBreak);
107551 if( regLimit ){
107552 sqlite3VdbeAddOp3(v, OP_IfZero, regLimit, addrBreak, -1);
107553 VdbeCoverage(v);
107554 }
107555 sqlite3VdbeResolveLabel(v, addrCont);
107556
107557 /* Execute the recursive SELECT taking the single row in Current as
@@ -107772,11 +107910,11 @@
107772 }
107773 p->pPrior = 0;
107774 p->iLimit = pPrior->iLimit;
107775 p->iOffset = pPrior->iOffset;
107776 if( p->iLimit ){
107777 addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit); VdbeCoverage(v);
107778 VdbeComment((v, "Jump ahead if LIMIT reached"));
107779 }
107780 explainSetInteger(iSub2, pParse->iNextSelectId);
107781 rc = sqlite3Select(pParse, p, &dest);
107782 testcase( rc!=SQLITE_OK );
@@ -108173,11 +108311,11 @@
108173 }
108174
108175 /* Jump to the end of the loop if the LIMIT is reached.
108176 */
108177 if( p->iLimit ){
108178 sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v);
108179 }
108180
108181 /* Generate the subroutine return
108182 */
108183 sqlite3VdbeResolveLabel(v, iContinue);
@@ -114787,10 +114925,12 @@
114787 int addrNxt; /* Jump here to start the next IN combination */
114788 int addrSkip; /* Jump here for next iteration of skip-scan */
114789 int addrCont; /* Jump here to continue with the next loop cycle */
114790 int addrFirst; /* First instruction of interior of the loop */
114791 int addrBody; /* Beginning of the body of this loop */
 
 
114792 u8 iFrom; /* Which entry in the FROM clause */
114793 u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */
114794 int p1, p2; /* Operands of the opcode used to ends the loop */
114795 union { /* Information that depends on pWLoop->wsFlags */
114796 struct {
@@ -114971,11 +115111,11 @@
114971 WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
114972 WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
114973 } u;
114974 LogEst truthProb; /* Probability of truth for this expression */
114975 u16 eOperator; /* A WO_xx value describing <op> */
114976 u8 wtFlags; /* TERM_xxx bit flags. See below */
114977 u8 nChild; /* Number of children that must disable us */
114978 WhereClause *pWC; /* The clause this term is part of */
114979 Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */
114980 Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */
114981 };
@@ -114993,10 +115133,13 @@
114993 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
114994 # define TERM_VNULL 0x80 /* Manufactured x>NULL or x<=NULL term */
114995 #else
114996 # define TERM_VNULL 0x00 /* Disabled if not using stat3 */
114997 #endif
 
 
 
114998
114999 /*
115000 ** An instance of the WhereScan object is used as an iterator for locating
115001 ** terms in the WHERE clause that are useful to the query planner.
115002 */
@@ -115368,11 +115511,11 @@
115368 ** WARNING: This routine might reallocate the space used to store
115369 ** WhereTerms. All pointers to WhereTerms should be invalidated after
115370 ** calling this routine. Such pointers may be reinitialized by referencing
115371 ** the pWC->a[] array.
115372 */
115373 static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
115374 WhereTerm *pTerm;
115375 int idx;
115376 testcase( wtFlags & TERM_VIRTUAL );
115377 if( pWC->nTerm>=pWC->nSlot ){
115378 WhereTerm *pOld = pWC->a;
@@ -115793,11 +115936,15 @@
115793 ** Check to see if the given expression is a LIKE or GLOB operator that
115794 ** can be optimized using inequality constraints. Return TRUE if it is
115795 ** so and false if not.
115796 **
115797 ** In order for the operator to be optimizible, the RHS must be a string
115798 ** literal that does not begin with a wildcard.
 
 
 
 
115799 */
115800 static int isLikeOrGlob(
115801 Parse *pParse, /* Parsing and code generating context */
115802 Expr *pExpr, /* Test this expression */
115803 Expr **ppPrefix, /* Pointer to TK_STRING expression with pattern prefix */
@@ -115822,11 +115969,11 @@
115822 #endif
115823 pList = pExpr->x.pList;
115824 pLeft = pList->a[1].pExpr;
115825 if( pLeft->op!=TK_COLUMN
115826 || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
115827 || IsVirtual(pLeft->pTab)
115828 ){
115829 /* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must
115830 ** be the name of an indexed column with TEXT affinity. */
115831 return 0;
115832 }
@@ -116271,11 +116418,11 @@
116271 Bitmask prereqLeft; /* Prerequesites of the pExpr->pLeft */
116272 Bitmask prereqAll; /* Prerequesites of pExpr */
116273 Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */
116274 Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */
116275 int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */
116276 int noCase = 0; /* LIKE/GLOB distinguishes case */
116277 int op; /* Top-level operator. pExpr->op */
116278 Parse *pParse = pWInfo->pParse; /* Parsing context */
116279 sqlite3 *db = pParse->db; /* Database connection */
116280
116281 if( db->mallocFailed ){
@@ -116409,16 +116556,19 @@
116409
116410 #ifndef SQLITE_OMIT_LIKE_OPTIMIZATION
116411 /* Add constraints to reduce the search space on a LIKE or GLOB
116412 ** operator.
116413 **
116414 ** A like pattern of the form "x LIKE 'abc%'" is changed into constraints
116415 **
116416 ** x>='abc' AND x<'abd' AND x LIKE 'abc%'
116417 **
116418 ** The last character of the prefix "abc" is incremented to form the
116419 ** termination condition "abd".
 
 
 
116420 */
116421 if( pWC->op==TK_AND
116422 && isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase)
116423 ){
116424 Expr *pLeft; /* LHS of LIKE/GLOB operator */
@@ -116426,13 +116576,29 @@
116426 Expr *pNewExpr1;
116427 Expr *pNewExpr2;
116428 int idxNew1;
116429 int idxNew2;
116430 Token sCollSeqName; /* Name of collating sequence */
 
116431
116432 pLeft = pExpr->x.pList->a[1].pExpr;
116433 pStr2 = sqlite3ExprDup(db, pStr1, 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116434 if( !db->mallocFailed ){
116435 u8 c, *pC; /* Last character before the first wildcard */
116436 pC = (u8*)&pStr2->u.zToken[sqlite3Strlen30(pStr2->u.zToken)-1];
116437 c = *pC;
116438 if( noCase ){
@@ -116448,23 +116614,23 @@
116448 *pC = c + 1;
116449 }
116450 sCollSeqName.z = noCase ? "NOCASE" : "BINARY";
116451 sCollSeqName.n = 6;
116452 pNewExpr1 = sqlite3ExprDup(db, pLeft, 0);
116453 pNewExpr1 = sqlite3PExpr(pParse, TK_GE,
116454 sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName),
116455 pStr1, 0);
116456 transferJoinMarkings(pNewExpr1, pExpr);
116457 idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
116458 testcase( idxNew1==0 );
116459 exprAnalyze(pSrc, pWC, idxNew1);
116460 pNewExpr2 = sqlite3ExprDup(db, pLeft, 0);
116461 pNewExpr2 = sqlite3PExpr(pParse, TK_LT,
116462 sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName),
116463 pStr2, 0);
116464 transferJoinMarkings(pNewExpr2, pExpr);
116465 idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
116466 testcase( idxNew2==0 );
116467 exprAnalyze(pSrc, pWC, idxNew2);
116468 pTerm = &pWC->a[idxTerm];
116469 if( isComplete ){
116470 markTermAsChild(pWC, idxNew1, idxTerm);
@@ -117635,24 +117801,47 @@
117635 ** by indices, we disable them to prevent redundant tests in the inner
117636 ** loop. We would get the correct results if nothing were ever disabled,
117637 ** but joins might run a little slower. The trick is to disable as much
117638 ** as we can without disabling too much. If we disabled in (1), we'd get
117639 ** the wrong answer. See ticket #813.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117640 */
117641 static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
117642 if( pTerm
 
117643 && (pTerm->wtFlags & TERM_CODED)==0
117644 && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin))
117645 && (pLevel->notReady & pTerm->prereqAll)==0
117646 ){
117647 pTerm->wtFlags |= TERM_CODED;
117648 if( pTerm->iParent>=0 ){
117649 WhereTerm *pOther = &pTerm->pWC->a[pTerm->iParent];
117650 if( (--pOther->nChild)==0 ){
117651 disableTerm(pLevel, pOther);
117652 }
117653 }
 
 
 
 
 
117654 }
117655 }
117656
117657 /*
117658 ** Code an OP_Affinity opcode to apply the column affinity string zAff
@@ -118132,11 +118321,30 @@
118132 }
118133 #else
118134 # define addScanStatus(a, b, c, d) ((void)d)
118135 #endif
118136
118137
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118138
118139 /*
118140 ** Generate code for the start of the iLevel-th loop in the WHERE clause
118141 ** implementation described by pWInfo.
118142 */
@@ -118466,10 +118674,23 @@
118466 nExtraReg = 1;
118467 }
118468 if( pLoop->wsFlags & WHERE_TOP_LIMIT ){
118469 pRangeEnd = pLoop->aLTerm[j++];
118470 nExtraReg = 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
118471 if( pRangeStart==0
118472 && (j = pIdx->aiColumn[nEq])>=0
118473 && pIdx->pTable->aCol[j].notNull==0
118474 ){
118475 bSeekPastNull = 1;
@@ -118508,10 +118729,11 @@
118508 /* Seek the index cursor to the start of the range. */
118509 nConstraint = nEq;
118510 if( pRangeStart ){
118511 Expr *pRight = pRangeStart->pExpr->pRight;
118512 sqlite3ExprCode(pParse, pRight, regBase+nEq);
 
118513 if( (pRangeStart->wtFlags & TERM_VNULL)==0
118514 && sqlite3ExprCanBeNull(pRight)
118515 ){
118516 sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
118517 VdbeCoverage(v);
@@ -118553,10 +118775,11 @@
118553 nConstraint = nEq;
118554 if( pRangeEnd ){
118555 Expr *pRight = pRangeEnd->pExpr->pRight;
118556 sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
118557 sqlite3ExprCode(pParse, pRight, regBase+nEq);
 
118558 if( (pRangeEnd->wtFlags & TERM_VNULL)==0
118559 && sqlite3ExprCanBeNull(pRight)
118560 ){
118561 sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
118562 VdbeCoverage(v);
@@ -118780,11 +119003,12 @@
118780 ** eliminating duplicates from other WHERE clauses, the action for each
118781 ** sub-WHERE clause is to to invoke the main loop body as a subroutine.
118782 */
118783 wctrlFlags = WHERE_OMIT_OPEN_CLOSE
118784 | WHERE_FORCE_TABLE
118785 | WHERE_ONETABLE_ONLY;
 
118786 for(ii=0; ii<pOrWc->nTerm; ii++){
118787 WhereTerm *pOrTerm = &pOrWc->a[ii];
118788 if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
118789 WhereInfo *pSubWInfo; /* Info for single OR-term scan */
118790 Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
@@ -118942,10 +119166,11 @@
118942 /* Insert code to test every subexpression that can be completely
118943 ** computed using the current set of tables.
118944 */
118945 for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
118946 Expr *pE;
 
118947 testcase( pTerm->wtFlags & TERM_VIRTUAL );
118948 testcase( pTerm->wtFlags & TERM_CODED );
118949 if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
118950 if( (pTerm->prereqAll & pLevel->notReady)!=0 ){
118951 testcase( pWInfo->untestedTerms==0
@@ -118955,12 +119180,18 @@
118955 }
118956 pE = pTerm->pExpr;
118957 assert( pE!=0 );
118958 if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
118959 continue;
 
 
 
 
 
118960 }
118961 sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
 
118962 pTerm->wtFlags |= TERM_CODED;
118963 }
118964
118965 /* Insert code to test for implied constraints based on transitivity
118966 ** of the "==" operator.
@@ -119974,10 +120205,11 @@
119974 rLogSize = estLog(rSize);
119975
119976 #ifndef SQLITE_OMIT_AUTOMATIC_INDEX
119977 /* Automatic indexes */
119978 if( !pBuilder->pOrSet
 
119979 && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0
119980 && pSrc->pIndex==0
119981 && !pSrc->viaCoroutine
119982 && !pSrc->notIndexed
119983 && HasRowid(pTab)
@@ -121758,10 +121990,20 @@
121758 if( pLevel->addrSkip ){
121759 sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrSkip);
121760 VdbeComment((v, "next skip-scan on %s", pLoop->u.btree.pIndex->zName));
121761 sqlite3VdbeJumpHere(v, pLevel->addrSkip);
121762 sqlite3VdbeJumpHere(v, pLevel->addrSkip-2);
 
 
 
 
 
 
 
 
 
 
121763 }
121764 if( pLevel->iLeftJoin ){
121765 addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
121766 assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
121767 || (pLoop->wsFlags & WHERE_INDEXED)!=0 );
@@ -126982,30 +127224,32 @@
126982 /* Mutex configuration options are only available in a threadsafe
126983 ** compile.
126984 */
126985 #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-54466-46756 */
126986 case SQLITE_CONFIG_SINGLETHREAD: {
126987 /* Disable all mutexing */
126988 sqlite3GlobalConfig.bCoreMutex = 0;
126989 sqlite3GlobalConfig.bFullMutex = 0;
 
126990 break;
126991 }
126992 #endif
126993 #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-20520-54086 */
126994 case SQLITE_CONFIG_MULTITHREAD: {
126995 /* Disable mutexing of database connections */
126996 /* Enable mutexing of core data structures */
126997 sqlite3GlobalConfig.bCoreMutex = 1;
126998 sqlite3GlobalConfig.bFullMutex = 0;
126999 break;
127000 }
127001 #endif
127002 #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-59593-21810 */
127003 case SQLITE_CONFIG_SERIALIZED: {
127004 /* Enable all mutexing */
127005 sqlite3GlobalConfig.bCoreMutex = 1;
127006 sqlite3GlobalConfig.bFullMutex = 1;
 
127007 break;
127008 }
127009 #endif
127010 #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-63666-48755 */
127011 case SQLITE_CONFIG_MUTEX: {
@@ -127113,11 +127357,12 @@
127113 ** SQLITE_ENABLE_MEMSYS5 and returns SQLITE_ERROR if invoked otherwise. */
127114 #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
127115 case SQLITE_CONFIG_HEAP: {
127116 /* EVIDENCE-OF: R-19854-42126 There are three arguments to
127117 ** SQLITE_CONFIG_HEAP: An 8-byte aligned pointer to the memory, the
127118 ** number of bytes in the memory buffer, and the minimum allocation size. */
 
127119 sqlite3GlobalConfig.pHeap = va_arg(ap, void*);
127120 sqlite3GlobalConfig.nHeap = va_arg(ap, int);
127121 sqlite3GlobalConfig.mnReq = va_arg(ap, int);
127122
127123 if( sqlite3GlobalConfig.mnReq<1 ){
@@ -127218,11 +127463,13 @@
127218 ** EVIDENCE-OF: R-34993-45031 The maximum allowed mmap size will be
127219 ** silently truncated if necessary so that it does not exceed the
127220 ** compile-time maximum mmap size set by the SQLITE_MAX_MMAP_SIZE
127221 ** compile-time option.
127222 */
127223 if( mxMmap<0 || mxMmap>SQLITE_MAX_MMAP_SIZE ) mxMmap = SQLITE_MAX_MMAP_SIZE;
 
 
127224 if( szMmap<0 ) szMmap = SQLITE_DEFAULT_MMAP_SIZE;
127225 if( szMmap>mxMmap) szMmap = mxMmap;
127226 sqlite3GlobalConfig.mxMmap = mxMmap;
127227 sqlite3GlobalConfig.szMmap = szMmap;
127228 break;
@@ -129062,11 +129309,23 @@
129062 for(iIn=0; iIn<nUri; iIn++) nByte += (zUri[iIn]=='&');
129063 zFile = sqlite3_malloc(nByte);
129064 if( !zFile ) return SQLITE_NOMEM;
129065
129066 iIn = 5;
129067 #ifndef SQLITE_ALLOW_URI_AUTHORITY
 
 
 
 
 
 
 
 
 
 
 
 
129068 /* Discard the scheme and authority segments of the URI. */
129069 if( zUri[5]=='/' && zUri[6]=='/' ){
129070 iIn = 7;
129071 while( zUri[iIn] && zUri[iIn]!='/' ) iIn++;
129072 if( iIn!=7 && (iIn!=16 || memcmp("localhost", &zUri[7], 9)) ){
@@ -129505,11 +129764,12 @@
129505 sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT);
129506
129507 opendb_out:
129508 sqlite3_free(zOpen);
129509 if( db ){
129510 assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 );
 
129511 sqlite3_mutex_leave(db->mutex);
129512 }
129513 rc = sqlite3_errcode(db);
129514 assert( db!=0 || rc==SQLITE_NOMEM );
129515 if( rc==SQLITE_NOMEM ){
@@ -130250,21 +130510,21 @@
130250 case SQLITE_TESTCTRL_ISINIT: {
130251 if( sqlite3GlobalConfig.isInit==0 ) rc = SQLITE_ERROR;
130252 break;
130253 }
130254
130255 /* sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, onOff, tnum);
130256 **
130257 ** This test control is used to create imposter tables. "db" is a pointer
130258 ** to the database connection. dbName is the database name (ex: "main" or
130259 ** "temp") which will receive the imposter. "onOff" turns imposter mode on
130260 ** or off. "tnum" is the root page of the b-tree to which the imposter
130261 ** table should connect.
130262 **
130263 ** Enable imposter mode only when the schema has already been parsed. Then
130264 ** run a single CREATE TABLE statement to construct the imposter table in the
130265 ** parsed schema. Then turn imposter mode back off again.
130266 **
130267 ** If onOff==0 and tnum>0 then reset the schema for all databases, causing
130268 ** the schema to be reparsed the next time it is needed. This has the
130269 ** effect of erasing all imposter tables.
130270 */
130271
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
1 /******************************************************************************
2 ** This file is an amalgamation of many separate C source files from SQLite
3 ** version 3.8.9. 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.
@@ -88,10 +88,48 @@
88 #endif /* _MSVC_H_ */
89
90 /************** End of msvc.h ************************************************/
91 /************** Continuing where we left off in sqliteInt.h ******************/
92
93 /*
94 ** Special setup for VxWorks
95 */
96 /************** Include vxworks.h in the middle of sqliteInt.h ***************/
97 /************** Begin file vxworks.h *****************************************/
98 /*
99 ** 2015-03-02
100 **
101 ** The author disclaims copyright to this source code. In place of
102 ** a legal notice, here is a blessing:
103 **
104 ** May you do good and not evil.
105 ** May you find forgiveness for yourself and forgive others.
106 ** May you share freely, never taking more than you give.
107 **
108 ******************************************************************************
109 **
110 ** This file contains code that is specific to Wind River's VxWorks
111 */
112 #if defined(__RTP__) || defined(_WRS_KERNEL)
113 /* This is VxWorks. Set up things specially for that OS
114 */
115 #include <vxWorks.h>
116 #include <pthread.h> /* amalgamator: dontcache */
117 #define OS_VXWORKS 1
118 #define SQLITE_OS_OTHER 0
119 #define SQLITE_HOMEGROWN_RECURSIVE_MUTEX 1
120 #define SQLITE_OMIT_LOAD_EXTENSION 1
121 #define SQLITE_ENABLE_LOCKING_STYLE 0
122 #define HAVE_UTIME 1
123 #else
124 /* This is not VxWorks. */
125 #define OS_VXWORKS 0
126 #endif /* defined(_WRS_KERNEL) */
127
128 /************** End of vxworks.h *********************************************/
129 /************** Continuing where we left off in sqliteInt.h ******************/
130
131 /*
132 ** These #defines should enable >2GB file support on POSIX if the
133 ** underlying operating system supports it. If the OS lacks
134 ** large file support, or if the OS is windows, these should be no-ops.
135 **
@@ -276,13 +314,13 @@
314 **
315 ** See also: [sqlite3_libversion()],
316 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
317 ** [sqlite_version()] and [sqlite_source_id()].
318 */
319 #define SQLITE_VERSION "3.8.9"
320 #define SQLITE_VERSION_NUMBER 3008009
321 #define SQLITE_SOURCE_ID "2015-03-09 10:40:48 e5da5e7d5dc5a3438ced23f1ee83e695abc29c45"
322
323 /*
324 ** CAPI3REF: Run-Time Library Version Numbers
325 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
326 **
@@ -925,18 +963,20 @@
963 **
964 ** These integer constants are opcodes for the xFileControl method
965 ** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
966 ** interface.
967 **
968 ** <ul>
969 ** <li>[[SQLITE_FCNTL_LOCKSTATE]]
970 ** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This
971 ** opcode causes the xFileControl method to write the current state of
972 ** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED],
973 ** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])
974 ** into an integer that the pArg argument points to. This capability
975 ** is used during testing and is only available when the SQLITE_TEST
976 ** compile-time option is used.
977 **
978 ** <li>[[SQLITE_FCNTL_SIZE_HINT]]
979 ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
980 ** layer a hint of how large the database file will grow to be during the
981 ** current transaction. This hint is not guaranteed to be accurate but it
982 ** is often close. The underlying VFS might choose to preallocate database
@@ -1057,11 +1097,13 @@
1097 ** the error message if the pragma fails. ^If the
1098 ** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal
1099 ** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA]
1100 ** file control returns [SQLITE_OK], then the parser assumes that the
1101 ** VFS has handled the PRAGMA itself and the parser generates a no-op
1102 ** prepared statement if result string is NULL, or that returns a copy
1103 ** of the result string if the string is non-NULL.
1104 ** ^If the [SQLITE_FCNTL_PRAGMA] file control returns
1105 ** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
1106 ** that the VFS encountered an error while handling the [PRAGMA] and the
1107 ** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
1108 ** file control occurs at the beginning of pragma statement analysis and so
1109 ** it is able to override built-in [PRAGMA] statements.
@@ -1916,11 +1958,10 @@
1958 ** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE
1959 ** <dd>^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is
1960 ** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro
1961 ** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value
1962 ** that specifies the maximum size of the created heap.
 
1963 **
1964 ** [[SQLITE_CONFIG_PCACHE_HDRSZ]]
1965 ** <dt>SQLITE_CONFIG_PCACHE_HDRSZ
1966 ** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which
1967 ** is a pointer to an integer and writes into that integer the number of extra
@@ -3356,20 +3397,18 @@
3397 ** The second argument, "zSql", is the statement to be compiled, encoded
3398 ** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2()
3399 ** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2()
3400 ** use UTF-16.
3401 **
3402 ** ^If the nByte argument is negative, then zSql is read up to the
3403 ** first zero terminator. ^If nByte is positive, then it is the
3404 ** number of bytes read from zSql. ^If nByte is zero, then no prepared
3405 ** statement is generated.
3406 ** If the caller knows that the supplied string is nul-terminated, then
3407 ** there is a small performance advantage to passing an nByte parameter that
3408 ** is the number of bytes in the input string <i>including</i>
3409 ** the nul-terminator.
 
 
3410 **
3411 ** ^If pzTail is not NULL then *pzTail is made to point to the first byte
3412 ** past the end of the first SQL statement in zSql. These routines only
3413 ** compile the first statement in zSql, so *pzTail is left pointing to
3414 ** what remains uncompiled.
@@ -4394,12 +4433,12 @@
4433 ** DEPRECATED
4434 **
4435 ** These functions are [deprecated]. In order to maintain
4436 ** backwards compatibility with older code, these functions continue
4437 ** to be supported. However, new applications should avoid
4438 ** the use of these functions. To encourage programmers to avoid
4439 ** these functions, we will not explain what they do.
4440 */
4441 #ifndef SQLITE_OMIT_DEPRECATED
4442 SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*);
4443 SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*);
4444 SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
@@ -7157,24 +7196,24 @@
7196 **
7197 ** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step()
7198 ** is not a permanent error and does not affect the return value of
7199 ** sqlite3_backup_finish().
7200 **
7201 ** [[sqlite3_backup_remaining()]] [[sqlite3_backup_pagecount()]]
7202 ** <b>sqlite3_backup_remaining() and sqlite3_backup_pagecount()</b>
7203 **
7204 ** ^The sqlite3_backup_remaining() routine returns the number of pages still
7205 ** to be backed up at the conclusion of the most recent sqlite3_backup_step().
7206 ** ^The sqlite3_backup_pagecount() routine returns the total number of pages
7207 ** in the source database at the conclusion of the most recent
7208 ** sqlite3_backup_step().
7209 ** ^(The values returned by these functions are only updated by
7210 ** sqlite3_backup_step(). If the source database is modified in a way that
7211 ** changes the size of the source database or the number of pages remaining,
7212 ** those changes are not reflected in the output of sqlite3_backup_pagecount()
7213 ** and sqlite3_backup_remaining() until after the next
7214 ** sqlite3_backup_step().)^
7215 **
7216 ** <b>Concurrent Usage of Database Handles</b>
7217 **
7218 ** ^The source [database connection] may be used by the application for other
7219 ** purposes while a backup operation is underway or being initialized.
@@ -8018,19 +8057,21 @@
8057 #ifndef SQLITE_MAX_FUNCTION_ARG
8058 # define SQLITE_MAX_FUNCTION_ARG 127
8059 #endif
8060
8061 /*
8062 ** The suggested maximum number of in-memory pages to use for
8063 ** the main database table and for temporary tables.
8064 **
8065 ** IMPLEMENTATION-OF: R-31093-59126 The default suggested cache size
8066 ** is 2000 pages.
8067 ** IMPLEMENTATION-OF: R-48205-43578 The default suggested cache size can be
8068 ** altered using the SQLITE_DEFAULT_CACHE_SIZE compile-time options.
8069 */
8070 #ifndef SQLITE_DEFAULT_CACHE_SIZE
8071 # define SQLITE_DEFAULT_CACHE_SIZE 2000
8072 #endif
 
 
 
8073
8074 /*
8075 ** The default number of frames to accumulate in the log file before
8076 ** checkpointing the database in WAL mode.
8077 */
@@ -9733,27 +9774,29 @@
9774 #define OP_FkCounter 134 /* synopsis: fkctr[P1]+=P2 */
9775 #define OP_FkIfZero 135 /* synopsis: if fkctr[P1]==0 goto P2 */
9776 #define OP_MemMax 136 /* synopsis: r[P1]=max(r[P1],r[P2]) */
9777 #define OP_IfPos 137 /* synopsis: if r[P1]>0 goto P2 */
9778 #define OP_IfNeg 138 /* synopsis: r[P1]+=P3, if r[P1]<0 goto P2 */
9779 #define OP_IfNotZero 139 /* synopsis: if r[P1]!=0 then r[P1]+=P3, goto P2 */
9780 #define OP_DecrJumpZero 140 /* synopsis: if (--r[P1])==0 goto P2 */
9781 #define OP_JumpZeroIncr 141 /* synopsis: if (r[P1]++)==0 ) goto P2 */
9782 #define OP_AggFinal 142 /* synopsis: accum=r[P1] N=P2 */
9783 #define OP_IncrVacuum 143
9784 #define OP_Expire 144
9785 #define OP_TableLock 145 /* synopsis: iDb=P1 root=P2 write=P3 */
9786 #define OP_VBegin 146
9787 #define OP_VCreate 147
9788 #define OP_VDestroy 148
9789 #define OP_VOpen 149
9790 #define OP_VColumn 150 /* synopsis: r[P3]=vcolumn(P2) */
9791 #define OP_VNext 151
9792 #define OP_VRename 152
9793 #define OP_Pagecount 153
9794 #define OP_MaxPgcnt 154
9795 #define OP_Init 155 /* synopsis: Start at P2 */
9796 #define OP_Noop 156
9797 #define OP_Explain 157
9798
9799
9800 /* Properties such as "out2" or "jump" that are specified in
9801 ** comments following the "case" for each opcode in the vdbe.c
9802 ** are encoded into bitvectors as follows:
@@ -9781,13 +9824,13 @@
9824 /* 96 */ 0x24, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,\
9825 /* 104 */ 0x00, 0x01, 0x01, 0x01, 0x01, 0x08, 0x08, 0x00,\
9826 /* 112 */ 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00,\
9827 /* 120 */ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
9828 /* 128 */ 0x0c, 0x45, 0x15, 0x01, 0x02, 0x02, 0x00, 0x01,\
9829 /* 136 */ 0x08, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x01,\
9830 /* 144 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,\
9831 /* 152 */ 0x00, 0x02, 0x02, 0x01, 0x00, 0x00,}
9832
9833 /************** End of opcodes.h *********************************************/
9834 /************** Continuing where we left off in vdbe.h ***********************/
9835
9836 /*
@@ -12022,11 +12065,11 @@
12065 #define WHERE_ONEPASS_DESIRED 0x0004 /* Want to do one-pass UPDATE/DELETE */
12066 #define WHERE_DUPLICATES_OK 0x0008 /* Ok to return a row more than once */
12067 #define WHERE_OMIT_OPEN_CLOSE 0x0010 /* Table cursors are already open */
12068 #define WHERE_FORCE_TABLE 0x0020 /* Do not use an index-only search */
12069 #define WHERE_ONETABLE_ONLY 0x0040 /* Only code the 1st table in pTabList */
12070 #define WHERE_NO_AUTOINDEX 0x0080 /* Disallow automatic indexes */
12071 #define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */
12072 #define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */
12073 #define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */
12074 #define WHERE_SORTBYGROUP 0x0800 /* Support sqlite3WhereIsSorted() */
12075 #define WHERE_REOPEN_IDX 0x1000 /* Try to use OP_ReopenIdx */
@@ -24969,27 +25012,29 @@
25012 /* 134 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
25013 /* 135 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
25014 /* 136 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
25015 /* 137 */ "IfPos" OpHelp("if r[P1]>0 goto P2"),
25016 /* 138 */ "IfNeg" OpHelp("r[P1]+=P3, if r[P1]<0 goto P2"),
25017 /* 139 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]+=P3, goto P2"),
25018 /* 140 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
25019 /* 141 */ "JumpZeroIncr" OpHelp("if (r[P1]++)==0 ) goto P2"),
25020 /* 142 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
25021 /* 143 */ "IncrVacuum" OpHelp(""),
25022 /* 144 */ "Expire" OpHelp(""),
25023 /* 145 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
25024 /* 146 */ "VBegin" OpHelp(""),
25025 /* 147 */ "VCreate" OpHelp(""),
25026 /* 148 */ "VDestroy" OpHelp(""),
25027 /* 149 */ "VOpen" OpHelp(""),
25028 /* 150 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
25029 /* 151 */ "VNext" OpHelp(""),
25030 /* 152 */ "VRename" OpHelp(""),
25031 /* 153 */ "Pagecount" OpHelp(""),
25032 /* 154 */ "MaxPgcnt" OpHelp(""),
25033 /* 155 */ "Init" OpHelp("Start at P2"),
25034 /* 156 */ "Noop" OpHelp(""),
25035 /* 157 */ "Explain" OpHelp(""),
25036 };
25037 return azName[i];
25038 }
25039 #endif
25040
@@ -25065,22 +25110,10 @@
25110 # else
25111 # define SQLITE_ENABLE_LOCKING_STYLE 0
25112 # endif
25113 #endif
25114
 
 
 
 
 
 
 
 
 
 
 
 
25115 /*
25116 ** standard include files.
25117 */
25118 #include <sys/types.h>
25119 #include <sys/stat.h>
@@ -25091,22 +25124,23 @@
25124 #include <errno.h>
25125 #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
25126 # include <sys/mman.h>
25127 #endif
25128
25129 #if SQLITE_ENABLE_LOCKING_STYLE
25130 # include <sys/ioctl.h>
25131 # include <sys/file.h>
25132 # include <sys/param.h>
 
 
 
 
 
25133 #endif /* SQLITE_ENABLE_LOCKING_STYLE */
25134
25135 #if OS_VXWORKS
25136 /* # include <sys/ioctl.h> */
25137 # include <semaphore.h>
25138 # include <limits.h>
25139 #endif /* OS_VXWORKS */
25140
25141 #if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
25142 # include <sys/mount.h>
25143 #endif
25144
25145 #ifdef HAVE_UTIME
25146 # include <utime.h>
@@ -25142,10 +25176,14 @@
25176
25177 /*
25178 ** Maximum supported path-length.
25179 */
25180 #define MAX_PATHNAME 512
25181
25182 /* Always cast the getpid() return type for compatibility with
25183 ** kernel modules in VxWorks. */
25184 #define osGetpid(X) (pid_t)getpid()
25185
25186 /*
25187 ** Only set the lastErrno if the error code is a real error and not
25188 ** a normal expected return code of SQLITE_BUSY or SQLITE_OK
25189 */
@@ -25231,11 +25269,11 @@
25269
25270 /* This variable holds the process id (pid) from when the xRandomness()
25271 ** method was called. If xOpen() is called from a different process id,
25272 ** indicating that a fork() has occurred, the PRNG will be reset.
25273 */
25274 static pid_t randomnessPid = 0;
25275
25276 /*
25277 ** Allowed values for the unixFile.ctrlFlags bitmask:
25278 */
25279 #define UNIXFILE_EXCL 0x01 /* Connections from one process only */
@@ -25587,11 +25625,11 @@
25625 #define osFcntl ((int(*)(int,int,...))aSyscall[7].pCurrent)
25626
25627 { "read", (sqlite3_syscall_ptr)read, 0 },
25628 #define osRead ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent)
25629
25630 #if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
25631 { "pread", (sqlite3_syscall_ptr)pread, 0 },
25632 #else
25633 { "pread", (sqlite3_syscall_ptr)0, 0 },
25634 #endif
25635 #define osPread ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].pCurrent)
@@ -25604,11 +25642,11 @@
25642 #define osPread64 ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[10].pCurrent)
25643
25644 { "write", (sqlite3_syscall_ptr)write, 0 },
25645 #define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
25646
25647 #if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
25648 { "pwrite", (sqlite3_syscall_ptr)pwrite, 0 },
25649 #else
25650 { "pwrite", (sqlite3_syscall_ptr)0, 0 },
25651 #endif
25652 #define osPwrite ((ssize_t(*)(int,const void*,size_t,off_t))\
@@ -26743,11 +26781,12 @@
26781 int tErrno = 0;
26782
26783 assert( pFile );
26784 OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h,
26785 azFileLock(eFileLock), azFileLock(pFile->eFileLock),
26786 azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared,
26787 osGetpid()));
26788
26789 /* If there is already a lock of this type or more restrictive on the
26790 ** unixFile, do nothing. Don't use the end_lock: exit path, as
26791 ** unixEnterMutex() hasn't been called yet.
26792 */
@@ -26951,11 +26990,11 @@
26990 int rc = SQLITE_OK;
26991
26992 assert( pFile );
26993 OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock,
26994 pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
26995 osGetpid()));
26996
26997 assert( eFileLock<=SHARED_LOCK );
26998 if( pFile->eFileLock<=eFileLock ){
26999 return SQLITE_OK;
27000 }
@@ -27378,11 +27417,11 @@
27417 char *zLockFile = (char *)pFile->lockingContext;
27418 int rc;
27419
27420 assert( pFile );
27421 OSTRACE(("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock,
27422 pFile->eFileLock, osGetpid()));
27423 assert( eFileLock<=SHARED_LOCK );
27424
27425 /* no-op if possible */
27426 if( pFile->eFileLock==eFileLock ){
27427 return SQLITE_OK;
@@ -27441,14 +27480,13 @@
27480 ** a single exclusive lock. In other words, SHARED, RESERVED, and
27481 ** PENDING locks are the same thing as an EXCLUSIVE lock. SQLite
27482 ** still works when you do this, but concurrency is reduced since
27483 ** only a single process can be reading the database at a time.
27484 **
27485 ** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off
 
27486 */
27487 #if SQLITE_ENABLE_LOCKING_STYLE
27488
27489 /*
27490 ** Retry flock() calls that fail with EINTR
27491 */
27492 #ifdef EINTR
@@ -27597,11 +27635,11 @@
27635 static int flockUnlock(sqlite3_file *id, int eFileLock) {
27636 unixFile *pFile = (unixFile*)id;
27637
27638 assert( pFile );
27639 OSTRACE(("UNLOCK %d %d was %d pid=%d (flock)\n", pFile->h, eFileLock,
27640 pFile->eFileLock, osGetpid()));
27641 assert( eFileLock<=SHARED_LOCK );
27642
27643 /* no-op if possible */
27644 if( pFile->eFileLock==eFileLock ){
27645 return SQLITE_OK;
@@ -27658,11 +27696,11 @@
27696 ** This routine checks if there is a RESERVED lock held on the specified
27697 ** file by this or any other process. If such a lock is held, set *pResOut
27698 ** to a non-zero value otherwise *pResOut is set to zero. The return value
27699 ** is set to SQLITE_OK unless an I/O error occurs during lock checking.
27700 */
27701 static int semXCheckReservedLock(sqlite3_file *id, int *pResOut) {
27702 int rc = SQLITE_OK;
27703 int reserved = 0;
27704 unixFile *pFile = (unixFile*)id;
27705
27706 SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
@@ -27725,11 +27763,11 @@
27763 ** access the file.
27764 **
27765 ** This routine will only increase a lock. Use the sqlite3OsUnlock()
27766 ** routine to lower a locking level.
27767 */
27768 static int semXLock(sqlite3_file *id, int eFileLock) {
27769 unixFile *pFile = (unixFile*)id;
27770 sem_t *pSem = pFile->pInode->pSem;
27771 int rc = SQLITE_OK;
27772
27773 /* if we already have a lock, it is exclusive.
@@ -27758,18 +27796,18 @@
27796 ** must be either NO_LOCK or SHARED_LOCK.
27797 **
27798 ** If the locking level of the file descriptor is already at or below
27799 ** the requested locking level, this routine is a no-op.
27800 */
27801 static int semXUnlock(sqlite3_file *id, int eFileLock) {
27802 unixFile *pFile = (unixFile*)id;
27803 sem_t *pSem = pFile->pInode->pSem;
27804
27805 assert( pFile );
27806 assert( pSem );
27807 OSTRACE(("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock,
27808 pFile->eFileLock, osGetpid()));
27809 assert( eFileLock<=SHARED_LOCK );
27810
27811 /* no-op if possible */
27812 if( pFile->eFileLock==eFileLock ){
27813 return SQLITE_OK;
@@ -27795,14 +27833,14 @@
27833 }
27834
27835 /*
27836 ** Close a file.
27837 */
27838 static int semXClose(sqlite3_file *id) {
27839 if( id ){
27840 unixFile *pFile = (unixFile*)id;
27841 semXUnlock(id, NO_LOCK);
27842 assert( pFile );
27843 unixEnterMutex();
27844 releaseInodeInfo(pFile);
27845 unixLeaveMutex();
27846 closeUnixFile(id);
@@ -27979,11 +28017,11 @@
28017 afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
28018
28019 assert( pFile );
28020 OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h,
28021 azFileLock(eFileLock), azFileLock(pFile->eFileLock),
28022 azFileLock(pInode->eFileLock), pInode->nShared , osGetpid()));
28023
28024 /* If there is already a lock of this type or more restrictive on the
28025 ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as
28026 ** unixEnterMutex() hasn't been called yet.
28027 */
@@ -28165,11 +28203,11 @@
28203 #endif
28204
28205 assert( pFile );
28206 OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock,
28207 pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
28208 osGetpid()));
28209
28210 assert( eFileLock<=SHARED_LOCK );
28211 if( pFile->eFileLock<=eFileLock ){
28212 return SQLITE_OK;
28213 }
@@ -29204,11 +29242,13 @@
29242 **
29243 ** This function should not be called directly by other code in this file.
29244 ** Instead, it should be called via macro osGetpagesize().
29245 */
29246 static int unixGetpagesize(void){
29247 #if OS_VXWORKS
29248 return 1024;
29249 #elif defined(_BSD_SOURCE)
29250 return getpagesize();
29251 #else
29252 return (int)sysconf(_SC_PAGESIZE);
29253 #endif
29254 }
@@ -29833,11 +29873,11 @@
29873 }
29874 }
29875 }
29876 sqlite3_mutex_leave(pShmNode->mutex);
29877 OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
29878 p->id, osGetpid(), p->sharedMask, p->exclMask));
29879 return rc;
29880 }
29881
29882 /*
29883 ** Implement a memory barrier or memory fence on shared memory.
@@ -30236,11 +30276,11 @@
30276 dotlockUnlock, /* xUnlock method */
30277 dotlockCheckReservedLock, /* xCheckReservedLock method */
30278 0 /* xShmMap method */
30279 )
30280
30281 #if SQLITE_ENABLE_LOCKING_STYLE
30282 IOMETHODS(
30283 flockIoFinder, /* Finder function name */
30284 flockIoMethods, /* sqlite3_io_methods object name */
30285 1, /* shared memory is disabled */
30286 flockClose, /* xClose method */
@@ -30254,14 +30294,14 @@
30294 #if OS_VXWORKS
30295 IOMETHODS(
30296 semIoFinder, /* Finder function name */
30297 semIoMethods, /* sqlite3_io_methods object name */
30298 1, /* shared memory is disabled */
30299 semXClose, /* xClose method */
30300 semXLock, /* xLock method */
30301 semXUnlock, /* xUnlock method */
30302 semXCheckReservedLock, /* xCheckReservedLock method */
30303 0 /* xShmMap method */
30304 )
30305 #endif
30306
30307 #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
@@ -30381,19 +30421,17 @@
30421 static const sqlite3_io_methods
30422 *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
30423
30424 #endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
30425
30426 #if OS_VXWORKS
30427 /*
30428 ** This "finder" function for VxWorks checks to see if posix advisory
30429 ** locking works. If it does, then that is what is used. If it does not
30430 ** work, then fallback to named semaphore locking.
 
 
30431 */
30432 static const sqlite3_io_methods *vxworksIoFinderImpl(
30433 const char *filePath, /* name of the database file */
30434 unixFile *pNew /* the open file object */
30435 ){
30436 struct flock lockInfo;
30437
@@ -30415,13 +30453,13 @@
30453 }else{
30454 return &semIoMethods;
30455 }
30456 }
30457 static const sqlite3_io_methods
30458 *(*const vxworksIoFinder)(const char*,unixFile*) = vxworksIoFinderImpl;
30459
30460 #endif /* OS_VXWORKS */
30461
30462 /*
30463 ** An abstract type for a pointer to an IO method finder function:
30464 */
30465 typedef const sqlite3_io_methods *(*finder_type)(const char*,unixFile*);
@@ -30930,12 +30968,12 @@
30968 /* Detect a pid change and reset the PRNG. There is a race condition
30969 ** here such that two or more threads all trying to open databases at
30970 ** the same instant might all reset the PRNG. But multiple resets
30971 ** are harmless.
30972 */
30973 if( randomnessPid!=osGetpid() ){
30974 randomnessPid = osGetpid();
30975 sqlite3_randomness(0,0);
30976 }
30977
30978 memset(p, 0, sizeof(unixFile));
30979
@@ -31322,11 +31360,11 @@
31360 ** When testing, initializing zBuf[] to zero is all we do. That means
31361 ** that we always use the same random number sequence. This makes the
31362 ** tests repeatable.
31363 */
31364 memset(zBuf, 0, nBuf);
31365 randomnessPid = osGetpid();
31366 #if !defined(SQLITE_TEST)
31367 {
31368 int fd, got;
31369 fd = robust_open("/dev/urandom", O_RDONLY, 0);
31370 if( fd<0 ){
@@ -31643,11 +31681,11 @@
31681 #else
31682 # ifdef _CS_DARWIN_USER_TEMP_DIR
31683 {
31684 if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){
31685 OSTRACE(("GETLOCKPATH failed %s errno=%d pid=%d\n",
31686 lPath, errno, osGetpid()));
31687 return SQLITE_IOERR_LOCK;
31688 }
31689 len = strlcat(lPath, "sqliteplocks", maxLen);
31690 }
31691 # else
@@ -31665,11 +31703,11 @@
31703 char c = dbPath[i];
31704 lPath[i+len] = (c=='/')?'_':c;
31705 }
31706 lPath[i+len]='\0';
31707 strlcat(lPath, ":auto:", maxLen);
31708 OSTRACE(("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, osGetpid()));
31709 return SQLITE_OK;
31710 }
31711
31712 /*
31713 ** Creates the lock file and any missing directories in lockPath
@@ -31692,20 +31730,20 @@
31730 if( osMkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){
31731 int err=errno;
31732 if( err!=EEXIST ) {
31733 OSTRACE(("CREATELOCKPATH FAILED creating %s, "
31734 "'%s' proxy lock path=%s pid=%d\n",
31735 buf, strerror(err), lockPath, osGetpid()));
31736 return err;
31737 }
31738 }
31739 }
31740 start=i+1;
31741 }
31742 buf[i] = lockPath[i];
31743 }
31744 OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n", lockPath, osGetpid()));
31745 return 0;
31746 }
31747
31748 /*
31749 ** Create a new VFS file descriptor (stored in memory obtained from
@@ -32006,11 +32044,12 @@
32044 int readLen = 0;
32045 int tryOldLockPath = 0;
32046 int forceNewLockPath = 0;
32047
32048 OSTRACE(("TAKECONCH %d for %s pid=%d\n", conchFile->h,
32049 (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
32050 osGetpid()));
32051
32052 rc = proxyGetHostID(myHostID, &pError);
32053 if( (rc&0xff)==SQLITE_IOERR ){
32054 storeLastErrno(pFile, pError);
32055 goto end_takeconch;
@@ -32216,11 +32255,11 @@
32255
32256 pCtx = (proxyLockingContext *)pFile->lockingContext;
32257 conchFile = pCtx->conchFile;
32258 OSTRACE(("RELEASECONCH %d for %s pid=%d\n", conchFile->h,
32259 (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
32260 osGetpid()));
32261 if( pCtx->conchHeld>0 ){
32262 rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
32263 }
32264 pCtx->conchHeld = 0;
32265 OSTRACE(("RELEASECONCH %d %s\n", conchFile->h,
@@ -32358,11 +32397,11 @@
32397 }else{
32398 lockPath=(char *)path;
32399 }
32400
32401 OSTRACE(("TRANSPROXY %d for %s pid=%d\n", pFile->h,
32402 (lockPath ? lockPath : ":auto:"), osGetpid()));
32403
32404 pCtx = sqlite3_malloc( sizeof(*pCtx) );
32405 if( pCtx==0 ){
32406 return SQLITE_NOMEM;
32407 }
@@ -32699,26 +32738,28 @@
32738 ** Note that the sqlite3_vfs.pNext field of the VFS object is modified
32739 ** by the SQLite core when the VFS is registered. So the following
32740 ** array cannot be const.
32741 */
32742 static sqlite3_vfs aVfs[] = {
32743 #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
32744 UNIXVFS("unix", autolockIoFinder ),
32745 #elif OS_VXWORKS
32746 UNIXVFS("unix", vxworksIoFinder ),
32747 #else
32748 UNIXVFS("unix", posixIoFinder ),
32749 #endif
32750 UNIXVFS("unix-none", nolockIoFinder ),
32751 UNIXVFS("unix-dotfile", dotlockIoFinder ),
32752 UNIXVFS("unix-excl", posixIoFinder ),
32753 #if OS_VXWORKS
32754 UNIXVFS("unix-namedsem", semIoFinder ),
32755 #endif
32756 #if SQLITE_ENABLE_LOCKING_STYLE || OS_VXWORKS
32757 UNIXVFS("unix-posix", posixIoFinder ),
32758 #endif
32759 #if SQLITE_ENABLE_LOCKING_STYLE
32760 UNIXVFS("unix-flock", flockIoFinder ),
 
32761 #endif
32762 #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
32763 UNIXVFS("unix-afp", afpIoFinder ),
32764 UNIXVFS("unix-nfs", nfsIoFinder ),
32765 UNIXVFS("unix-proxy", proxyIoFinder ),
@@ -39072,16 +39113,24 @@
39113 sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 0);
39114 }
39115 }
39116
39117 /*
39118 ** Compute the number of pages of cache requested. p->szCache is the
39119 ** cache size requested by the "PRAGMA cache_size" statement.
39120 **
39121 **
39122 */
39123 static int numberOfCachePages(PCache *p){
39124 if( p->szCache>=0 ){
39125 /* IMPLEMENTATION-OF: R-42059-47211 If the argument N is positive then the
39126 ** suggested cache size is set to N. */
39127 return p->szCache;
39128 }else{
39129 /* IMPLEMENTATION-OF: R-61436-13639 If the argument N is negative, then
39130 ** the number of cache pages is adjusted to use approximately abs(N*1024)
39131 ** bytes of memory. */
39132 return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra));
39133 }
39134 }
39135
39136 /*************************************************** General Interfaces ******
@@ -68615,10 +68664,14 @@
68664 }
68665 SQLITE_API const void *sqlite3_value_text16le(sqlite3_value *pVal){
68666 return sqlite3ValueText(pVal, SQLITE_UTF16LE);
68667 }
68668 #endif /* SQLITE_OMIT_UTF16 */
68669 /* EVIDENCE-OF: R-12793-43283 Every value in SQLite has one of five
68670 ** fundamental datatypes: 64-bit signed integer 64-bit IEEE floating
68671 ** point number string BLOB NULL
68672 */
68673 SQLITE_API int sqlite3_value_type(sqlite3_value* pVal){
68674 static const u8 aType[] = {
68675 SQLITE_BLOB, /* 0x00 */
68676 SQLITE_NULL, /* 0x01 */
68677 SQLITE_TEXT, /* 0x02 */
@@ -71290,11 +71343,11 @@
71343
71344 /* Opcode: String8 * P2 * P4 *
71345 ** Synopsis: r[P2]='P4'
71346 **
71347 ** P4 points to a nul terminated UTF-8 string. This opcode is transformed
71348 ** into a String opcode before it is executed for the first time. During
71349 ** this transformation, the length of string P4 is computed and stored
71350 ** as the P1 parameter.
71351 */
71352 case OP_String8: { /* same as TK_STRING, out2-prerelease */
71353 assert( pOp->p4.z!=0 );
@@ -71322,22 +71375,34 @@
71375 goto too_big;
71376 }
71377 /* Fall through to the next case, OP_String */
71378 }
71379
71380 /* Opcode: String P1 P2 P3 P4 P5
71381 ** Synopsis: r[P2]='P4' (len=P1)
71382 **
71383 ** The string value P4 of length P1 (bytes) is stored in register P2.
71384 **
71385 ** If P5!=0 and the content of register P3 is greater than zero, then
71386 ** the datatype of the register P2 is converted to BLOB. The content is
71387 ** the same sequence of bytes, it is merely interpreted as a BLOB instead
71388 ** of a string, as if it had been CAST.
71389 */
71390 case OP_String: { /* out2-prerelease */
71391 assert( pOp->p4.z!=0 );
71392 pOut->flags = MEM_Str|MEM_Static|MEM_Term;
71393 pOut->z = pOp->p4.z;
71394 pOut->n = pOp->p1;
71395 pOut->enc = encoding;
71396 UPDATE_MAX_BLOBSIZE(pOut);
71397 if( pOp->p5 ){
71398 assert( pOp->p3>0 );
71399 assert( pOp->p3<=(p->nMem-p->nCursor) );
71400 pIn3 = &aMem[pOp->p3];
71401 assert( pIn3->flags & MEM_Int );
71402 if( pIn3->u.i ) pOut->flags = MEM_Blob|MEM_Static|MEM_Term;
71403 }
71404 break;
71405 }
71406
71407 /* Opcode: Null P1 P2 P3 * *
71408 ** Synopsis: r[P2..P3]=NULL
@@ -73325,11 +73390,16 @@
73390 ** the value of this counter needs to be restored too. */
73391 p->nStmtDefCons = db->nDeferredCons;
73392 p->nStmtDefImmCons = db->nDeferredImmCons;
73393 }
73394
73395 /* Gather the schema version number for checking:
73396 ** IMPLEMENTATION-OF: R-32195-19465 The schema version is used by SQLite
73397 ** each time a query is executed to ensure that the internal cache of the
73398 ** schema used when compiling the SQL query matches the schema of the
73399 ** database against which the compiled query is actually executed.
73400 */
73401 sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta);
73402 iGen = db->aDb[pOp->p1].pSchema->iGeneration;
73403 }else{
73404 iGen = iMeta = 0;
73405 }
@@ -75843,14 +75913,16 @@
75913 #endif /* SQLITE_OMIT_AUTOINCREMENT */
75914
75915 /* Opcode: IfPos P1 P2 * * *
75916 ** Synopsis: if r[P1]>0 goto P2
75917 **
75918 ** Register P1 must contain an integer.
75919 ** If the value of register P1 is 1 or greater, jump to P2 and
75920 ** add the literal value P3 to register P1.
75921 **
75922 ** If the initial value of register P1 is less than 1, then the
75923 ** value is unchanged and control passes through to the next instruction.
75924 */
75925 case OP_IfPos: { /* jump, in1 */
75926 pIn1 = &aMem[pOp->p1];
75927 assert( pIn1->flags&MEM_Int );
75928 VdbeBranchTaken( pIn1->u.i>0, 2);
@@ -75875,27 +75947,63 @@
75947 pc = pOp->p2 - 1;
75948 }
75949 break;
75950 }
75951
75952 /* Opcode: IfNotZero P1 P2 P3 * *
75953 ** Synopsis: if r[P1]!=0 then r[P1]+=P3, goto P2
75954 **
75955 ** Register P1 must contain an integer. If the content of register P1 is
75956 ** initially nonzero, then add P3 to P1 and jump to P2. If register P1 is
75957 ** initially zero, leave it unchanged and fall through.
75958 */
75959 case OP_IfNotZero: { /* jump, in1 */
75960 pIn1 = &aMem[pOp->p1];
75961 assert( pIn1->flags&MEM_Int );
75962 VdbeBranchTaken(pIn1->u.i<0, 2);
75963 if( pIn1->u.i ){
75964 pIn1->u.i += pOp->p3;
75965 pc = pOp->p2 - 1;
75966 }
75967 break;
75968 }
75969
75970 /* Opcode: DecrJumpZero P1 P2 * * *
75971 ** Synopsis: if (--r[P1])==0 goto P2
75972 **
75973 ** Register P1 must hold an integer. Decrement the value in register P1
75974 ** then jump to P2 if the new value is exactly zero.
75975 */
75976 case OP_DecrJumpZero: { /* jump, in1 */
75977 pIn1 = &aMem[pOp->p1];
75978 assert( pIn1->flags&MEM_Int );
75979 pIn1->u.i--;
75980 VdbeBranchTaken(pIn1->u.i==0, 2);
75981 if( pIn1->u.i==0 ){
75982 pc = pOp->p2 - 1;
75983 }
75984 break;
75985 }
75986
75987
75988 /* Opcode: JumpZeroIncr P1 P2 * * *
75989 ** Synopsis: if (r[P1]++)==0 ) goto P2
75990 **
75991 ** The register P1 must contain an integer. If register P1 is initially
75992 ** zero, then jump to P2. Increment register P1 regardless of whether or
75993 ** not the jump is taken.
75994 */
75995 case OP_JumpZeroIncr: { /* jump, in1 */
75996 pIn1 = &aMem[pOp->p1];
75997 assert( pIn1->flags&MEM_Int );
75998 VdbeBranchTaken(pIn1->u.i==0, 2);
75999 if( (pIn1->u.i++)==0 ){
76000 pc = pOp->p2 - 1;
76001 }
76002 break;
76003 }
76004
76005 /* Opcode: AggStep * P2 P3 P4 P5
76006 ** Synopsis: accum=r[P3] step(r[P2@P5])
76007 **
76008 ** Execute the step function for an aggregate. The
76009 ** function has P5 arguments. P4 is a pointer to the FuncDef
@@ -97181,10 +97289,15 @@
97289 ** pExpr points to an expression which implements a function. If
97290 ** it is appropriate to apply the LIKE optimization to that function
97291 ** then set aWc[0] through aWc[2] to the wildcard characters and
97292 ** return TRUE. If the function is not a LIKE-style function then
97293 ** return FALSE.
97294 **
97295 ** *pIsNocase is set to true if uppercase and lowercase are equivalent for
97296 ** the function (default for LIKE). If the function makes the distinction
97297 ** between uppercase and lowercase (as does GLOB) then *pIsNocase is set to
97298 ** false.
97299 */
97300 SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
97301 FuncDef *pDef;
97302 if( pExpr->op!=TK_FUNCTION
97303 || !pExpr->x.pList
@@ -102972,10 +103085,21 @@
103085 }
103086
103087 /* Send an SQLITE_FCNTL_PRAGMA file-control to the underlying VFS
103088 ** connection. If it returns SQLITE_OK, then assume that the VFS
103089 ** handled the pragma and generate a no-op prepared statement.
103090 **
103091 ** IMPLEMENTATION-OF: R-12238-55120 Whenever a PRAGMA statement is parsed,
103092 ** an SQLITE_FCNTL_PRAGMA file control is sent to the open sqlite3_file
103093 ** object corresponding to the database file to which the pragma
103094 ** statement refers.
103095 **
103096 ** IMPLEMENTATION-OF: R-29875-31678 The argument to the SQLITE_FCNTL_PRAGMA
103097 ** file control is an array of pointers to strings (char**) in which the
103098 ** second element of the array is the name of the pragma and the third
103099 ** element is the argument to the pragma or NULL if the pragma has no
103100 ** argument.
103101 */
103102 aFcntl[0] = 0;
103103 aFcntl[1] = zLeft;
103104 aFcntl[2] = zRight;
103105 aFcntl[3] = 0;
@@ -103732,34 +103856,46 @@
103856 Index *pIdx;
103857 Table *pTab;
103858 pIdx = sqlite3FindIndex(db, zRight, zDb);
103859 if( pIdx ){
103860 int i;
103861 int mx;
103862 if( pPragma->iArg ){
103863 /* PRAGMA index_xinfo (newer version with more rows and columns) */
103864 mx = pIdx->nColumn;
103865 pParse->nMem = 6;
103866 }else{
103867 /* PRAGMA index_info (legacy version) */
103868 mx = pIdx->nKeyCol;
103869 pParse->nMem = 3;
103870 }
103871 pTab = pIdx->pTable;
103872 sqlite3VdbeSetNumCols(v, pParse->nMem);
 
103873 sqlite3CodeVerifySchema(pParse, iDb);
103874 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC);
103875 sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE_STATIC);
103876 sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE_STATIC);
103877 if( pPragma->iArg ){
103878 sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "desc", SQLITE_STATIC);
103879 sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "coll", SQLITE_STATIC);
103880 sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "key", SQLITE_STATIC);
103881 }
103882 for(i=0; i<mx; i++){
103883 i16 cnum = pIdx->aiColumn[i];
103884 sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
103885 sqlite3VdbeAddOp2(v, OP_Integer, cnum, 2);
103886 if( cnum<0 ){
103887 sqlite3VdbeAddOp2(v, OP_Null, 0, 3);
103888 }else{
103889 sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pTab->aCol[cnum].zName, 0);
103890 }
103891 if( pPragma->iArg ){
103892 sqlite3VdbeAddOp2(v, OP_Integer, pIdx->aSortOrder[i], 4);
103893 sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, pIdx->azColl[i], 0);
103894 sqlite3VdbeAddOp2(v, OP_Integer, i<pIdx->nKeyCol, 6);
103895 }
103896 sqlite3VdbeAddOp2(v, OP_ResultRow, 1, pParse->nMem);
103897 }
103898 }
103899 }
103900 break;
103901
@@ -104457,12 +104593,13 @@
104593 #endif
104594
104595 /*
104596 ** PRAGMA shrink_memory
104597 **
104598 ** IMPLEMENTATION-OF: R-23445-46109 This pragma causes the database
104599 ** connection on which it is invoked to free up as much memory as it
104600 ** can, by calling sqlite3_db_release_memory().
104601 */
104602 case PragTyp_SHRINK_MEMORY: {
104603 sqlite3_db_release_memory(db);
104604 break;
104605 }
@@ -104487,12 +104624,16 @@
104624
104625 /*
104626 ** PRAGMA soft_heap_limit
104627 ** PRAGMA soft_heap_limit = N
104628 **
104629 ** IMPLEMENTATION-OF: R-26343-45930 This pragma invokes the
104630 ** sqlite3_soft_heap_limit64() interface with the argument N, if N is
104631 ** specified and is a non-negative integer.
104632 ** IMPLEMENTATION-OF: R-64451-07163 The soft_heap_limit pragma always
104633 ** returns the same integer that would be returned by the
104634 ** sqlite3_soft_heap_limit64(-1) C-language function.
104635 */
104636 case PragTyp_SOFT_HEAP_LIMIT: {
104637 sqlite3_int64 N;
104638 if( zRight && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK ){
104639 sqlite3_soft_heap_limit64(N);
@@ -106065,24 +106206,21 @@
106206 }else{
106207 op = OP_IdxInsert;
106208 }
106209 sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord);
106210 if( pSelect->iLimit ){
106211 int addr;
106212 int iLimit;
106213 if( pSelect->iOffset ){
106214 iLimit = pSelect->iOffset+1;
106215 }else{
106216 iLimit = pSelect->iLimit;
106217 }
106218 addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, -1); VdbeCoverage(v);
 
 
 
106219 sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor);
106220 sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor);
106221 sqlite3VdbeJumpHere(v, addr);
106222 }
106223 }
106224
106225 /*
106226 ** Add code to implement the OFFSET
@@ -106475,11 +106613,11 @@
106613 /* Jump to the end of the loop if the LIMIT is reached. Except, if
106614 ** there is a sorter, in which case the sorter has already limited
106615 ** the output for us.
106616 */
106617 if( pSort==0 && p->iLimit ){
106618 sqlite3VdbeAddOp2(v, OP_DecrJumpZero, p->iLimit, iBreak); VdbeCoverage(v);
106619 }
106620 }
106621
106622 /*
106623 ** Allocate a KeyInfo object sufficient for an index of N key columns and
@@ -107328,11 +107466,11 @@
107466 }
107467 }else{
107468 sqlite3ExprCode(pParse, p->pLimit, iLimit);
107469 sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeCoverage(v);
107470 VdbeComment((v, "LIMIT counter"));
107471 sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, iBreak); VdbeCoverage(v);
107472 }
107473 if( p->pOffset ){
107474 p->iOffset = iOffset = ++pParse->nMem;
107475 pParse->nMem++; /* Allocate an extra register for limit+offset */
107476 sqlite3ExprCode(pParse, p->pOffset, iOffset);
@@ -107547,11 +107685,11 @@
107685 addrCont = sqlite3VdbeMakeLabel(v);
107686 codeOffset(v, regOffset, addrCont);
107687 selectInnerLoop(pParse, p, p->pEList, iCurrent,
107688 0, 0, pDest, addrCont, addrBreak);
107689 if( regLimit ){
107690 sqlite3VdbeAddOp2(v, OP_DecrJumpZero, regLimit, addrBreak);
107691 VdbeCoverage(v);
107692 }
107693 sqlite3VdbeResolveLabel(v, addrCont);
107694
107695 /* Execute the recursive SELECT taking the single row in Current as
@@ -107772,11 +107910,11 @@
107910 }
107911 p->pPrior = 0;
107912 p->iLimit = pPrior->iLimit;
107913 p->iOffset = pPrior->iOffset;
107914 if( p->iLimit ){
107915 addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
107916 VdbeComment((v, "Jump ahead if LIMIT reached"));
107917 }
107918 explainSetInteger(iSub2, pParse->iNextSelectId);
107919 rc = sqlite3Select(pParse, p, &dest);
107920 testcase( rc!=SQLITE_OK );
@@ -108173,11 +108311,11 @@
108311 }
108312
108313 /* Jump to the end of the loop if the LIMIT is reached.
108314 */
108315 if( p->iLimit ){
108316 sqlite3VdbeAddOp2(v, OP_DecrJumpZero, p->iLimit, iBreak); VdbeCoverage(v);
108317 }
108318
108319 /* Generate the subroutine return
108320 */
108321 sqlite3VdbeResolveLabel(v, iContinue);
@@ -114787,10 +114925,12 @@
114925 int addrNxt; /* Jump here to start the next IN combination */
114926 int addrSkip; /* Jump here for next iteration of skip-scan */
114927 int addrCont; /* Jump here to continue with the next loop cycle */
114928 int addrFirst; /* First instruction of interior of the loop */
114929 int addrBody; /* Beginning of the body of this loop */
114930 int iLikeRepCntr; /* LIKE range processing counter register */
114931 int addrLikeRep; /* LIKE range processing address */
114932 u8 iFrom; /* Which entry in the FROM clause */
114933 u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */
114934 int p1, p2; /* Operands of the opcode used to ends the loop */
114935 union { /* Information that depends on pWLoop->wsFlags */
114936 struct {
@@ -114971,11 +115111,11 @@
115111 WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
115112 WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
115113 } u;
115114 LogEst truthProb; /* Probability of truth for this expression */
115115 u16 eOperator; /* A WO_xx value describing <op> */
115116 u16 wtFlags; /* TERM_xxx bit flags. See below */
115117 u8 nChild; /* Number of children that must disable us */
115118 WhereClause *pWC; /* The clause this term is part of */
115119 Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */
115120 Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */
115121 };
@@ -114993,10 +115133,13 @@
115133 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
115134 # define TERM_VNULL 0x80 /* Manufactured x>NULL or x<=NULL term */
115135 #else
115136 # define TERM_VNULL 0x00 /* Disabled if not using stat3 */
115137 #endif
115138 #define TERM_LIKEOPT 0x100 /* Virtual terms from the LIKE optimization */
115139 #define TERM_LIKECOND 0x200 /* Conditionally this LIKE operator term */
115140 #define TERM_LIKE 0x400 /* The original LIKE operator */
115141
115142 /*
115143 ** An instance of the WhereScan object is used as an iterator for locating
115144 ** terms in the WHERE clause that are useful to the query planner.
115145 */
@@ -115368,11 +115511,11 @@
115511 ** WARNING: This routine might reallocate the space used to store
115512 ** WhereTerms. All pointers to WhereTerms should be invalidated after
115513 ** calling this routine. Such pointers may be reinitialized by referencing
115514 ** the pWC->a[] array.
115515 */
115516 static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){
115517 WhereTerm *pTerm;
115518 int idx;
115519 testcase( wtFlags & TERM_VIRTUAL );
115520 if( pWC->nTerm>=pWC->nSlot ){
115521 WhereTerm *pOld = pWC->a;
@@ -115793,11 +115936,15 @@
115936 ** Check to see if the given expression is a LIKE or GLOB operator that
115937 ** can be optimized using inequality constraints. Return TRUE if it is
115938 ** so and false if not.
115939 **
115940 ** In order for the operator to be optimizible, the RHS must be a string
115941 ** literal that does not begin with a wildcard. The LHS must be a column
115942 ** that may only be NULL, a string, or a BLOB, never a number. (This means
115943 ** that virtual tables cannot participate in the LIKE optimization.) If the
115944 ** collating sequence for the column on the LHS must be appropriate for
115945 ** the operator.
115946 */
115947 static int isLikeOrGlob(
115948 Parse *pParse, /* Parsing and code generating context */
115949 Expr *pExpr, /* Test this expression */
115950 Expr **ppPrefix, /* Pointer to TK_STRING expression with pattern prefix */
@@ -115822,11 +115969,11 @@
115969 #endif
115970 pList = pExpr->x.pList;
115971 pLeft = pList->a[1].pExpr;
115972 if( pLeft->op!=TK_COLUMN
115973 || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
115974 || IsVirtual(pLeft->pTab) /* Value might be numeric */
115975 ){
115976 /* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must
115977 ** be the name of an indexed column with TEXT affinity. */
115978 return 0;
115979 }
@@ -116271,11 +116418,11 @@
116418 Bitmask prereqLeft; /* Prerequesites of the pExpr->pLeft */
116419 Bitmask prereqAll; /* Prerequesites of pExpr */
116420 Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */
116421 Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */
116422 int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */
116423 int noCase = 0; /* uppercase equivalent to lowercase */
116424 int op; /* Top-level operator. pExpr->op */
116425 Parse *pParse = pWInfo->pParse; /* Parsing context */
116426 sqlite3 *db = pParse->db; /* Database connection */
116427
116428 if( db->mallocFailed ){
@@ -116409,16 +116556,19 @@
116556
116557 #ifndef SQLITE_OMIT_LIKE_OPTIMIZATION
116558 /* Add constraints to reduce the search space on a LIKE or GLOB
116559 ** operator.
116560 **
116561 ** A like pattern of the form "x LIKE 'aBc%'" is changed into constraints
116562 **
116563 ** x>='ABC' AND x<'abd' AND x LIKE 'aBc%'
116564 **
116565 ** The last character of the prefix "abc" is incremented to form the
116566 ** termination condition "abd". If case is not significant (the default
116567 ** for LIKE) then the lower-bound is made all uppercase and the upper-
116568 ** bound is made all lowercase so that the bounds also work when comparing
116569 ** BLOBs.
116570 */
116571 if( pWC->op==TK_AND
116572 && isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase)
116573 ){
116574 Expr *pLeft; /* LHS of LIKE/GLOB operator */
@@ -116426,13 +116576,29 @@
116576 Expr *pNewExpr1;
116577 Expr *pNewExpr2;
116578 int idxNew1;
116579 int idxNew2;
116580 Token sCollSeqName; /* Name of collating sequence */
116581 const u16 wtFlags = TERM_LIKEOPT | TERM_VIRTUAL | TERM_DYNAMIC;
116582
116583 pLeft = pExpr->x.pList->a[1].pExpr;
116584 pStr2 = sqlite3ExprDup(db, pStr1, 0);
116585
116586 /* Convert the lower bound to upper-case and the upper bound to
116587 ** lower-case (upper-case is less than lower-case in ASCII) so that
116588 ** the range constraints also work for BLOBs
116589 */
116590 if( noCase && !pParse->db->mallocFailed ){
116591 int i;
116592 char c;
116593 pTerm->wtFlags |= TERM_LIKE;
116594 for(i=0; (c = pStr1->u.zToken[i])!=0; i++){
116595 pStr1->u.zToken[i] = sqlite3Toupper(c);
116596 pStr2->u.zToken[i] = sqlite3Tolower(c);
116597 }
116598 }
116599
116600 if( !db->mallocFailed ){
116601 u8 c, *pC; /* Last character before the first wildcard */
116602 pC = (u8*)&pStr2->u.zToken[sqlite3Strlen30(pStr2->u.zToken)-1];
116603 c = *pC;
116604 if( noCase ){
@@ -116448,23 +116614,23 @@
116614 *pC = c + 1;
116615 }
116616 sCollSeqName.z = noCase ? "NOCASE" : "BINARY";
116617 sCollSeqName.n = 6;
116618 pNewExpr1 = sqlite3ExprDup(db, pLeft, 0);
116619 pNewExpr1 = sqlite3PExpr(pParse, TK_GE,
116620 sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName),
116621 pStr1, 0);
116622 transferJoinMarkings(pNewExpr1, pExpr);
116623 idxNew1 = whereClauseInsert(pWC, pNewExpr1, wtFlags);
116624 testcase( idxNew1==0 );
116625 exprAnalyze(pSrc, pWC, idxNew1);
116626 pNewExpr2 = sqlite3ExprDup(db, pLeft, 0);
116627 pNewExpr2 = sqlite3PExpr(pParse, TK_LT,
116628 sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName),
116629 pStr2, 0);
116630 transferJoinMarkings(pNewExpr2, pExpr);
116631 idxNew2 = whereClauseInsert(pWC, pNewExpr2, wtFlags);
116632 testcase( idxNew2==0 );
116633 exprAnalyze(pSrc, pWC, idxNew2);
116634 pTerm = &pWC->a[idxTerm];
116635 if( isComplete ){
116636 markTermAsChild(pWC, idxNew1, idxTerm);
@@ -117635,24 +117801,47 @@
117801 ** by indices, we disable them to prevent redundant tests in the inner
117802 ** loop. We would get the correct results if nothing were ever disabled,
117803 ** but joins might run a little slower. The trick is to disable as much
117804 ** as we can without disabling too much. If we disabled in (1), we'd get
117805 ** the wrong answer. See ticket #813.
117806 **
117807 ** If all the children of a term are disabled, then that term is also
117808 ** automatically disabled. In this way, terms get disabled if derived
117809 ** virtual terms are tested first. For example:
117810 **
117811 ** x GLOB 'abc*' AND x>='abc' AND x<'acd'
117812 ** \___________/ \______/ \_____/
117813 ** parent child1 child2
117814 **
117815 ** Only the parent term was in the original WHERE clause. The child1
117816 ** and child2 terms were added by the LIKE optimization. If both of
117817 ** the virtual child terms are valid, then testing of the parent can be
117818 ** skipped.
117819 **
117820 ** Usually the parent term is marked as TERM_CODED. But if the parent
117821 ** term was originally TERM_LIKE, then the parent gets TERM_LIKECOND instead.
117822 ** The TERM_LIKECOND marking indicates that the term should be coded inside
117823 ** a conditional such that is only evaluated on the second pass of a
117824 ** LIKE-optimization loop, when scanning BLOBs instead of strings.
117825 */
117826 static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
117827 int nLoop = 0;
117828 while( pTerm
117829 && (pTerm->wtFlags & TERM_CODED)==0
117830 && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin))
117831 && (pLevel->notReady & pTerm->prereqAll)==0
117832 ){
117833 if( nLoop && (pTerm->wtFlags & TERM_LIKE)!=0 ){
117834 pTerm->wtFlags |= TERM_LIKECOND;
117835 }else{
117836 pTerm->wtFlags |= TERM_CODED;
 
 
117837 }
117838 if( pTerm->iParent<0 ) break;
117839 pTerm = &pTerm->pWC->a[pTerm->iParent];
117840 pTerm->nChild--;
117841 if( pTerm->nChild!=0 ) break;
117842 nLoop++;
117843 }
117844 }
117845
117846 /*
117847 ** Code an OP_Affinity opcode to apply the column affinity string zAff
@@ -118132,11 +118321,30 @@
118321 }
118322 #else
118323 # define addScanStatus(a, b, c, d) ((void)d)
118324 #endif
118325
118326 /*
118327 ** Look at the last instruction coded. If that instruction is OP_String8
118328 ** and if pLoop->iLikeRepCntr is non-zero, then change the P3 to be
118329 ** pLoop->iLikeRepCntr and set P5.
118330 **
118331 ** The LIKE optimization trys to evaluate "x LIKE 'abc%'" as a range
118332 ** expression: "x>='ABC' AND x<'abd'". But this requires that the range
118333 ** scan loop run twice, once for strings and a second time for BLOBs.
118334 ** The OP_String opcodes on the second pass convert the upper and lower
118335 ** bound string contants to blobs. This routine makes the necessary changes
118336 ** to the OP_String opcodes for that to happen.
118337 */
118338 static void whereLikeOptimizationStringFixup(Vdbe *v, WhereLevel *pLevel){
118339 VdbeOp *pOp;
118340 pOp = sqlite3VdbeGetOp(v, -1);
118341 if( pLevel->iLikeRepCntr && pOp->opcode==OP_String8 ){
118342 pOp->p3 = pLevel->iLikeRepCntr;
118343 pOp->p5 = 1;
118344 }
118345 }
118346
118347 /*
118348 ** Generate code for the start of the iLevel-th loop in the WHERE clause
118349 ** implementation described by pWInfo.
118350 */
@@ -118466,10 +118674,23 @@
118674 nExtraReg = 1;
118675 }
118676 if( pLoop->wsFlags & WHERE_TOP_LIMIT ){
118677 pRangeEnd = pLoop->aLTerm[j++];
118678 nExtraReg = 1;
118679 if( pRangeStart
118680 && (pRangeStart->wtFlags & TERM_LIKEOPT)!=0
118681 && (pRangeEnd->wtFlags & TERM_LIKEOPT)!=0
118682 ){
118683 pLevel->iLikeRepCntr = ++pParse->nMem;
118684 testcase( bRev );
118685 testcase( pIdx->aSortOrder[nEq]==SQLITE_SO_DESC );
118686 sqlite3VdbeAddOp2(v, OP_Integer,
118687 bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC),
118688 pLevel->iLikeRepCntr);
118689 VdbeComment((v, "LIKE loop counter"));
118690 pLevel->addrLikeRep = sqlite3VdbeCurrentAddr(v);
118691 }
118692 if( pRangeStart==0
118693 && (j = pIdx->aiColumn[nEq])>=0
118694 && pIdx->pTable->aCol[j].notNull==0
118695 ){
118696 bSeekPastNull = 1;
@@ -118508,10 +118729,11 @@
118729 /* Seek the index cursor to the start of the range. */
118730 nConstraint = nEq;
118731 if( pRangeStart ){
118732 Expr *pRight = pRangeStart->pExpr->pRight;
118733 sqlite3ExprCode(pParse, pRight, regBase+nEq);
118734 whereLikeOptimizationStringFixup(v, pLevel);
118735 if( (pRangeStart->wtFlags & TERM_VNULL)==0
118736 && sqlite3ExprCanBeNull(pRight)
118737 ){
118738 sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
118739 VdbeCoverage(v);
@@ -118553,10 +118775,11 @@
118775 nConstraint = nEq;
118776 if( pRangeEnd ){
118777 Expr *pRight = pRangeEnd->pExpr->pRight;
118778 sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
118779 sqlite3ExprCode(pParse, pRight, regBase+nEq);
118780 whereLikeOptimizationStringFixup(v, pLevel);
118781 if( (pRangeEnd->wtFlags & TERM_VNULL)==0
118782 && sqlite3ExprCanBeNull(pRight)
118783 ){
118784 sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
118785 VdbeCoverage(v);
@@ -118780,11 +119003,12 @@
119003 ** eliminating duplicates from other WHERE clauses, the action for each
119004 ** sub-WHERE clause is to to invoke the main loop body as a subroutine.
119005 */
119006 wctrlFlags = WHERE_OMIT_OPEN_CLOSE
119007 | WHERE_FORCE_TABLE
119008 | WHERE_ONETABLE_ONLY
119009 | WHERE_NO_AUTOINDEX;
119010 for(ii=0; ii<pOrWc->nTerm; ii++){
119011 WhereTerm *pOrTerm = &pOrWc->a[ii];
119012 if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
119013 WhereInfo *pSubWInfo; /* Info for single OR-term scan */
119014 Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
@@ -118942,10 +119166,11 @@
119166 /* Insert code to test every subexpression that can be completely
119167 ** computed using the current set of tables.
119168 */
119169 for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
119170 Expr *pE;
119171 int skipLikeAddr = 0;
119172 testcase( pTerm->wtFlags & TERM_VIRTUAL );
119173 testcase( pTerm->wtFlags & TERM_CODED );
119174 if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
119175 if( (pTerm->prereqAll & pLevel->notReady)!=0 ){
119176 testcase( pWInfo->untestedTerms==0
@@ -118955,12 +119180,18 @@
119180 }
119181 pE = pTerm->pExpr;
119182 assert( pE!=0 );
119183 if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
119184 continue;
119185 }
119186 if( pTerm->wtFlags & TERM_LIKECOND ){
119187 assert( pLevel->iLikeRepCntr>0 );
119188 skipLikeAddr = sqlite3VdbeAddOp1(v, OP_IfNot, pLevel->iLikeRepCntr);
119189 VdbeCoverage(v);
119190 }
119191 sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
119192 if( skipLikeAddr ) sqlite3VdbeJumpHere(v, skipLikeAddr);
119193 pTerm->wtFlags |= TERM_CODED;
119194 }
119195
119196 /* Insert code to test for implied constraints based on transitivity
119197 ** of the "==" operator.
@@ -119974,10 +120205,11 @@
120205 rLogSize = estLog(rSize);
120206
120207 #ifndef SQLITE_OMIT_AUTOMATIC_INDEX
120208 /* Automatic indexes */
120209 if( !pBuilder->pOrSet
120210 && (pWInfo->wctrlFlags & WHERE_NO_AUTOINDEX)==0
120211 && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0
120212 && pSrc->pIndex==0
120213 && !pSrc->viaCoroutine
120214 && !pSrc->notIndexed
120215 && HasRowid(pTab)
@@ -121758,10 +121990,20 @@
121990 if( pLevel->addrSkip ){
121991 sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrSkip);
121992 VdbeComment((v, "next skip-scan on %s", pLoop->u.btree.pIndex->zName));
121993 sqlite3VdbeJumpHere(v, pLevel->addrSkip);
121994 sqlite3VdbeJumpHere(v, pLevel->addrSkip-2);
121995 }
121996 if( pLevel->addrLikeRep ){
121997 int op;
121998 if( sqlite3VdbeGetOp(v, pLevel->addrLikeRep-1)->p1 ){
121999 op = OP_DecrJumpZero;
122000 }else{
122001 op = OP_JumpZeroIncr;
122002 }
122003 sqlite3VdbeAddOp2(v, op, pLevel->iLikeRepCntr, pLevel->addrLikeRep);
122004 VdbeCoverage(v);
122005 }
122006 if( pLevel->iLeftJoin ){
122007 addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
122008 assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
122009 || (pLoop->wsFlags & WHERE_INDEXED)!=0 );
@@ -126982,30 +127224,32 @@
127224 /* Mutex configuration options are only available in a threadsafe
127225 ** compile.
127226 */
127227 #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-54466-46756 */
127228 case SQLITE_CONFIG_SINGLETHREAD: {
127229 /* EVIDENCE-OF: R-02748-19096 This option sets the threading mode to
127230 ** Single-thread. */
127231 sqlite3GlobalConfig.bCoreMutex = 0; /* Disable mutex on core */
127232 sqlite3GlobalConfig.bFullMutex = 0; /* Disable mutex on connections */
127233 break;
127234 }
127235 #endif
127236 #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-20520-54086 */
127237 case SQLITE_CONFIG_MULTITHREAD: {
127238 /* EVIDENCE-OF: R-14374-42468 This option sets the threading mode to
127239 ** Multi-thread. */
127240 sqlite3GlobalConfig.bCoreMutex = 1; /* Enable mutex on core */
127241 sqlite3GlobalConfig.bFullMutex = 0; /* Disable mutex on connections */
127242 break;
127243 }
127244 #endif
127245 #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-59593-21810 */
127246 case SQLITE_CONFIG_SERIALIZED: {
127247 /* EVIDENCE-OF: R-41220-51800 This option sets the threading mode to
127248 ** Serialized. */
127249 sqlite3GlobalConfig.bCoreMutex = 1; /* Enable mutex on core */
127250 sqlite3GlobalConfig.bFullMutex = 1; /* Enable mutex on connections */
127251 break;
127252 }
127253 #endif
127254 #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-63666-48755 */
127255 case SQLITE_CONFIG_MUTEX: {
@@ -127113,11 +127357,12 @@
127357 ** SQLITE_ENABLE_MEMSYS5 and returns SQLITE_ERROR if invoked otherwise. */
127358 #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
127359 case SQLITE_CONFIG_HEAP: {
127360 /* EVIDENCE-OF: R-19854-42126 There are three arguments to
127361 ** SQLITE_CONFIG_HEAP: An 8-byte aligned pointer to the memory, the
127362 ** number of bytes in the memory buffer, and the minimum allocation size.
127363 */
127364 sqlite3GlobalConfig.pHeap = va_arg(ap, void*);
127365 sqlite3GlobalConfig.nHeap = va_arg(ap, int);
127366 sqlite3GlobalConfig.mnReq = va_arg(ap, int);
127367
127368 if( sqlite3GlobalConfig.mnReq<1 ){
@@ -127218,11 +127463,13 @@
127463 ** EVIDENCE-OF: R-34993-45031 The maximum allowed mmap size will be
127464 ** silently truncated if necessary so that it does not exceed the
127465 ** compile-time maximum mmap size set by the SQLITE_MAX_MMAP_SIZE
127466 ** compile-time option.
127467 */
127468 if( mxMmap<0 || mxMmap>SQLITE_MAX_MMAP_SIZE ){
127469 mxMmap = SQLITE_MAX_MMAP_SIZE;
127470 }
127471 if( szMmap<0 ) szMmap = SQLITE_DEFAULT_MMAP_SIZE;
127472 if( szMmap>mxMmap) szMmap = mxMmap;
127473 sqlite3GlobalConfig.mxMmap = mxMmap;
127474 sqlite3GlobalConfig.szMmap = szMmap;
127475 break;
@@ -129062,11 +129309,23 @@
129309 for(iIn=0; iIn<nUri; iIn++) nByte += (zUri[iIn]=='&');
129310 zFile = sqlite3_malloc(nByte);
129311 if( !zFile ) return SQLITE_NOMEM;
129312
129313 iIn = 5;
129314 #ifdef SQLITE_ALLOW_URI_AUTHORITY
129315 if( strncmp(zUri+5, "///", 3)==0 ){
129316 iIn = 7;
129317 /* The following condition causes URIs with five leading / characters
129318 ** like file://///host/path to be converted into UNCs like //host/path.
129319 ** The correct URI for that UNC has only two or four leading / characters
129320 ** file://host/path or file:////host/path. But 5 leading slashes is a
129321 ** common error, we are told, so we handle it as a special case. */
129322 if( strncmp(zUri+7, "///", 3)==0 ){ iIn++; }
129323 }else if( strncmp(zUri+5, "//localhost/", 12)==0 ){
129324 iIn = 16;
129325 }
129326 #else
129327 /* Discard the scheme and authority segments of the URI. */
129328 if( zUri[5]=='/' && zUri[6]=='/' ){
129329 iIn = 7;
129330 while( zUri[iIn] && zUri[iIn]!='/' ) iIn++;
129331 if( iIn!=7 && (iIn!=16 || memcmp("localhost", &zUri[7], 9)) ){
@@ -129505,11 +129764,12 @@
129764 sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT);
129765
129766 opendb_out:
129767 sqlite3_free(zOpen);
129768 if( db ){
129769 assert( db->mutex!=0 || isThreadsafe==0
129770 || sqlite3GlobalConfig.bFullMutex==0 );
129771 sqlite3_mutex_leave(db->mutex);
129772 }
129773 rc = sqlite3_errcode(db);
129774 assert( db!=0 || rc==SQLITE_NOMEM );
129775 if( rc==SQLITE_NOMEM ){
@@ -130250,21 +130510,21 @@
130510 case SQLITE_TESTCTRL_ISINIT: {
130511 if( sqlite3GlobalConfig.isInit==0 ) rc = SQLITE_ERROR;
130512 break;
130513 }
130514
130515 /* sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, onOff, tnum);
130516 **
130517 ** This test control is used to create imposter tables. "db" is a pointer
130518 ** to the database connection. dbName is the database name (ex: "main" or
130519 ** "temp") which will receive the imposter. "onOff" turns imposter mode on
130520 ** or off. "tnum" is the root page of the b-tree to which the imposter
130521 ** table should connect.
130522 **
130523 ** Enable imposter mode only when the schema has already been parsed. Then
130524 ** run a single CREATE TABLE statement to construct the imposter table in
130525 ** the parsed schema. Then turn imposter mode back off again.
130526 **
130527 ** If onOff==0 and tnum>0 then reset the schema for all databases, causing
130528 ** the schema to be reparsed the next time it is needed. This has the
130529 ** effect of erasing all imposter tables.
130530 */
130531
+33 -32
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -105,13 +105,13 @@
105105
**
106106
** See also: [sqlite3_libversion()],
107107
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108108
** [sqlite_version()] and [sqlite_source_id()].
109109
*/
110
-#define SQLITE_VERSION "3.8.8"
111
-#define SQLITE_VERSION_NUMBER 3008008
112
-#define SQLITE_SOURCE_ID "2015-02-25 14:25:31 6d132e7a224ee68b5cefe9222944aac5760ffc20"
110
+#define SQLITE_VERSION "3.8.9"
111
+#define SQLITE_VERSION_NUMBER 3008009
112
+#define SQLITE_SOURCE_ID "2015-03-09 10:40:48 e5da5e7d5dc5a3438ced23f1ee83e695abc29c45"
113113
114114
/*
115115
** CAPI3REF: Run-Time Library Version Numbers
116116
** KEYWORDS: sqlite3_version, sqlite3_sourceid
117117
**
@@ -754,18 +754,20 @@
754754
**
755755
** These integer constants are opcodes for the xFileControl method
756756
** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
757757
** interface.
758758
**
759
+** <ul>
760
+** <li>[[SQLITE_FCNTL_LOCKSTATE]]
759761
** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This
760762
** opcode causes the xFileControl method to write the current state of
761763
** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED],
762764
** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])
763765
** into an integer that the pArg argument points to. This capability
764
-** is used during testing and only needs to be supported when SQLITE_TEST
765
-** is defined.
766
-** <ul>
766
+** is used during testing and is only available when the SQLITE_TEST
767
+** compile-time option is used.
768
+**
767769
** <li>[[SQLITE_FCNTL_SIZE_HINT]]
768770
** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
769771
** layer a hint of how large the database file will grow to be during the
770772
** current transaction. This hint is not guaranteed to be accurate but it
771773
** is often close. The underlying VFS might choose to preallocate database
@@ -886,11 +888,13 @@
886888
** the error message if the pragma fails. ^If the
887889
** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal
888890
** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA]
889891
** file control returns [SQLITE_OK], then the parser assumes that the
890892
** VFS has handled the PRAGMA itself and the parser generates a no-op
891
-** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns
893
+** prepared statement if result string is NULL, or that returns a copy
894
+** of the result string if the string is non-NULL.
895
+** ^If the [SQLITE_FCNTL_PRAGMA] file control returns
892896
** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
893897
** that the VFS encountered an error while handling the [PRAGMA] and the
894898
** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
895899
** file control occurs at the beginning of pragma statement analysis and so
896900
** it is able to override built-in [PRAGMA] statements.
@@ -1745,11 +1749,10 @@
17451749
** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE
17461750
** <dd>^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is
17471751
** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro
17481752
** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value
17491753
** that specifies the maximum size of the created heap.
1750
-** </dl>
17511754
**
17521755
** [[SQLITE_CONFIG_PCACHE_HDRSZ]]
17531756
** <dt>SQLITE_CONFIG_PCACHE_HDRSZ
17541757
** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which
17551758
** is a pointer to an integer and writes into that integer the number of extra
@@ -3185,20 +3188,18 @@
31853188
** The second argument, "zSql", is the statement to be compiled, encoded
31863189
** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2()
31873190
** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2()
31883191
** use UTF-16.
31893192
**
3190
-** ^If the nByte argument is less than zero, then zSql is read up to the
3191
-** first zero terminator. ^If nByte is non-negative, then it is the maximum
3192
-** number of bytes read from zSql. ^When nByte is non-negative, the
3193
-** zSql string ends at either the first '\000' or '\u0000' character or
3194
-** the nByte-th byte, whichever comes first. If the caller knows
3195
-** that the supplied string is nul-terminated, then there is a small
3196
-** performance advantage to be gained by passing an nByte parameter that
3197
-** is equal to the number of bytes in the input string <i>including</i>
3198
-** the nul-terminator bytes as this saves SQLite from having to
3199
-** make a copy of the input string.
3193
+** ^If the nByte argument is negative, then zSql is read up to the
3194
+** first zero terminator. ^If nByte is positive, then it is the
3195
+** number of bytes read from zSql. ^If nByte is zero, then no prepared
3196
+** statement is generated.
3197
+** If the caller knows that the supplied string is nul-terminated, then
3198
+** there is a small performance advantage to passing an nByte parameter that
3199
+** is the number of bytes in the input string <i>including</i>
3200
+** the nul-terminator.
32003201
**
32013202
** ^If pzTail is not NULL then *pzTail is made to point to the first byte
32023203
** past the end of the first SQL statement in zSql. These routines only
32033204
** compile the first statement in zSql, so *pzTail is left pointing to
32043205
** what remains uncompiled.
@@ -4223,12 +4224,12 @@
42234224
** DEPRECATED
42244225
**
42254226
** These functions are [deprecated]. In order to maintain
42264227
** backwards compatibility with older code, these functions continue
42274228
** to be supported. However, new applications should avoid
4228
-** the use of these functions. To help encourage people to avoid
4229
-** using these functions, we are not going to tell you what they do.
4229
+** the use of these functions. To encourage programmers to avoid
4230
+** these functions, we will not explain what they do.
42304231
*/
42314232
#ifndef SQLITE_OMIT_DEPRECATED
42324233
SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*);
42334234
SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*);
42344235
SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
@@ -6986,24 +6987,24 @@
69866987
**
69876988
** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step()
69886989
** is not a permanent error and does not affect the return value of
69896990
** sqlite3_backup_finish().
69906991
**
6991
-** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]]
6992
+** [[sqlite3_backup_remaining()]] [[sqlite3_backup_pagecount()]]
69926993
** <b>sqlite3_backup_remaining() and sqlite3_backup_pagecount()</b>
69936994
**
6994
-** ^Each call to sqlite3_backup_step() sets two values inside
6995
-** the [sqlite3_backup] object: the number of pages still to be backed
6996
-** up and the total number of pages in the source database file.
6997
-** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces
6998
-** retrieve these two values, respectively.
6999
-**
7000
-** ^The values returned by these functions are only updated by
7001
-** sqlite3_backup_step(). ^If the source database is modified during a backup
7002
-** operation, then the values are not updated to account for any extra
7003
-** pages that need to be updated or the size of the source database file
7004
-** changing.
6995
+** ^The sqlite3_backup_remaining() routine returns the number of pages still
6996
+** to be backed up at the conclusion of the most recent sqlite3_backup_step().
6997
+** ^The sqlite3_backup_pagecount() routine returns the total number of pages
6998
+** in the source database at the conclusion of the most recent
6999
+** sqlite3_backup_step().
7000
+** ^(The values returned by these functions are only updated by
7001
+** sqlite3_backup_step(). If the source database is modified in a way that
7002
+** changes the size of the source database or the number of pages remaining,
7003
+** those changes are not reflected in the output of sqlite3_backup_pagecount()
7004
+** and sqlite3_backup_remaining() until after the next
7005
+** sqlite3_backup_step().)^
70057006
**
70067007
** <b>Concurrent Usage of Database Handles</b>
70077008
**
70087009
** ^The source [database connection] may be used by the application for other
70097010
** purposes while a backup operation is underway or being initialized.
70107011
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -105,13 +105,13 @@
105 **
106 ** See also: [sqlite3_libversion()],
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.8.8"
111 #define SQLITE_VERSION_NUMBER 3008008
112 #define SQLITE_SOURCE_ID "2015-02-25 14:25:31 6d132e7a224ee68b5cefe9222944aac5760ffc20"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
@@ -754,18 +754,20 @@
754 **
755 ** These integer constants are opcodes for the xFileControl method
756 ** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
757 ** interface.
758 **
 
 
759 ** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This
760 ** opcode causes the xFileControl method to write the current state of
761 ** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED],
762 ** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])
763 ** into an integer that the pArg argument points to. This capability
764 ** is used during testing and only needs to be supported when SQLITE_TEST
765 ** is defined.
766 ** <ul>
767 ** <li>[[SQLITE_FCNTL_SIZE_HINT]]
768 ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
769 ** layer a hint of how large the database file will grow to be during the
770 ** current transaction. This hint is not guaranteed to be accurate but it
771 ** is often close. The underlying VFS might choose to preallocate database
@@ -886,11 +888,13 @@
886 ** the error message if the pragma fails. ^If the
887 ** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal
888 ** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA]
889 ** file control returns [SQLITE_OK], then the parser assumes that the
890 ** VFS has handled the PRAGMA itself and the parser generates a no-op
891 ** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns
 
 
892 ** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
893 ** that the VFS encountered an error while handling the [PRAGMA] and the
894 ** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
895 ** file control occurs at the beginning of pragma statement analysis and so
896 ** it is able to override built-in [PRAGMA] statements.
@@ -1745,11 +1749,10 @@
1745 ** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE
1746 ** <dd>^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is
1747 ** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro
1748 ** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value
1749 ** that specifies the maximum size of the created heap.
1750 ** </dl>
1751 **
1752 ** [[SQLITE_CONFIG_PCACHE_HDRSZ]]
1753 ** <dt>SQLITE_CONFIG_PCACHE_HDRSZ
1754 ** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which
1755 ** is a pointer to an integer and writes into that integer the number of extra
@@ -3185,20 +3188,18 @@
3185 ** The second argument, "zSql", is the statement to be compiled, encoded
3186 ** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2()
3187 ** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2()
3188 ** use UTF-16.
3189 **
3190 ** ^If the nByte argument is less than zero, then zSql is read up to the
3191 ** first zero terminator. ^If nByte is non-negative, then it is the maximum
3192 ** number of bytes read from zSql. ^When nByte is non-negative, the
3193 ** zSql string ends at either the first '\000' or '\u0000' character or
3194 ** the nByte-th byte, whichever comes first. If the caller knows
3195 ** that the supplied string is nul-terminated, then there is a small
3196 ** performance advantage to be gained by passing an nByte parameter that
3197 ** is equal to the number of bytes in the input string <i>including</i>
3198 ** the nul-terminator bytes as this saves SQLite from having to
3199 ** make a copy of the input string.
3200 **
3201 ** ^If pzTail is not NULL then *pzTail is made to point to the first byte
3202 ** past the end of the first SQL statement in zSql. These routines only
3203 ** compile the first statement in zSql, so *pzTail is left pointing to
3204 ** what remains uncompiled.
@@ -4223,12 +4224,12 @@
4223 ** DEPRECATED
4224 **
4225 ** These functions are [deprecated]. In order to maintain
4226 ** backwards compatibility with older code, these functions continue
4227 ** to be supported. However, new applications should avoid
4228 ** the use of these functions. To help encourage people to avoid
4229 ** using these functions, we are not going to tell you what they do.
4230 */
4231 #ifndef SQLITE_OMIT_DEPRECATED
4232 SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*);
4233 SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*);
4234 SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
@@ -6986,24 +6987,24 @@
6986 **
6987 ** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step()
6988 ** is not a permanent error and does not affect the return value of
6989 ** sqlite3_backup_finish().
6990 **
6991 ** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]]
6992 ** <b>sqlite3_backup_remaining() and sqlite3_backup_pagecount()</b>
6993 **
6994 ** ^Each call to sqlite3_backup_step() sets two values inside
6995 ** the [sqlite3_backup] object: the number of pages still to be backed
6996 ** up and the total number of pages in the source database file.
6997 ** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces
6998 ** retrieve these two values, respectively.
6999 **
7000 ** ^The values returned by these functions are only updated by
7001 ** sqlite3_backup_step(). ^If the source database is modified during a backup
7002 ** operation, then the values are not updated to account for any extra
7003 ** pages that need to be updated or the size of the source database file
7004 ** changing.
7005 **
7006 ** <b>Concurrent Usage of Database Handles</b>
7007 **
7008 ** ^The source [database connection] may be used by the application for other
7009 ** purposes while a backup operation is underway or being initialized.
7010
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -105,13 +105,13 @@
105 **
106 ** See also: [sqlite3_libversion()],
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.8.9"
111 #define SQLITE_VERSION_NUMBER 3008009
112 #define SQLITE_SOURCE_ID "2015-03-09 10:40:48 e5da5e7d5dc5a3438ced23f1ee83e695abc29c45"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
@@ -754,18 +754,20 @@
754 **
755 ** These integer constants are opcodes for the xFileControl method
756 ** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
757 ** interface.
758 **
759 ** <ul>
760 ** <li>[[SQLITE_FCNTL_LOCKSTATE]]
761 ** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This
762 ** opcode causes the xFileControl method to write the current state of
763 ** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED],
764 ** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])
765 ** into an integer that the pArg argument points to. This capability
766 ** is used during testing and is only available when the SQLITE_TEST
767 ** compile-time option is used.
768 **
769 ** <li>[[SQLITE_FCNTL_SIZE_HINT]]
770 ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
771 ** layer a hint of how large the database file will grow to be during the
772 ** current transaction. This hint is not guaranteed to be accurate but it
773 ** is often close. The underlying VFS might choose to preallocate database
@@ -886,11 +888,13 @@
888 ** the error message if the pragma fails. ^If the
889 ** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal
890 ** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA]
891 ** file control returns [SQLITE_OK], then the parser assumes that the
892 ** VFS has handled the PRAGMA itself and the parser generates a no-op
893 ** prepared statement if result string is NULL, or that returns a copy
894 ** of the result string if the string is non-NULL.
895 ** ^If the [SQLITE_FCNTL_PRAGMA] file control returns
896 ** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
897 ** that the VFS encountered an error while handling the [PRAGMA] and the
898 ** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
899 ** file control occurs at the beginning of pragma statement analysis and so
900 ** it is able to override built-in [PRAGMA] statements.
@@ -1745,11 +1749,10 @@
1749 ** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE
1750 ** <dd>^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is
1751 ** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro
1752 ** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value
1753 ** that specifies the maximum size of the created heap.
 
1754 **
1755 ** [[SQLITE_CONFIG_PCACHE_HDRSZ]]
1756 ** <dt>SQLITE_CONFIG_PCACHE_HDRSZ
1757 ** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which
1758 ** is a pointer to an integer and writes into that integer the number of extra
@@ -3185,20 +3188,18 @@
3188 ** The second argument, "zSql", is the statement to be compiled, encoded
3189 ** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2()
3190 ** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2()
3191 ** use UTF-16.
3192 **
3193 ** ^If the nByte argument is negative, then zSql is read up to the
3194 ** first zero terminator. ^If nByte is positive, then it is the
3195 ** number of bytes read from zSql. ^If nByte is zero, then no prepared
3196 ** statement is generated.
3197 ** If the caller knows that the supplied string is nul-terminated, then
3198 ** there is a small performance advantage to passing an nByte parameter that
3199 ** is the number of bytes in the input string <i>including</i>
3200 ** the nul-terminator.
 
 
3201 **
3202 ** ^If pzTail is not NULL then *pzTail is made to point to the first byte
3203 ** past the end of the first SQL statement in zSql. These routines only
3204 ** compile the first statement in zSql, so *pzTail is left pointing to
3205 ** what remains uncompiled.
@@ -4223,12 +4224,12 @@
4224 ** DEPRECATED
4225 **
4226 ** These functions are [deprecated]. In order to maintain
4227 ** backwards compatibility with older code, these functions continue
4228 ** to be supported. However, new applications should avoid
4229 ** the use of these functions. To encourage programmers to avoid
4230 ** these functions, we will not explain what they do.
4231 */
4232 #ifndef SQLITE_OMIT_DEPRECATED
4233 SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*);
4234 SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*);
4235 SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
@@ -6986,24 +6987,24 @@
6987 **
6988 ** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step()
6989 ** is not a permanent error and does not affect the return value of
6990 ** sqlite3_backup_finish().
6991 **
6992 ** [[sqlite3_backup_remaining()]] [[sqlite3_backup_pagecount()]]
6993 ** <b>sqlite3_backup_remaining() and sqlite3_backup_pagecount()</b>
6994 **
6995 ** ^The sqlite3_backup_remaining() routine returns the number of pages still
6996 ** to be backed up at the conclusion of the most recent sqlite3_backup_step().
6997 ** ^The sqlite3_backup_pagecount() routine returns the total number of pages
6998 ** in the source database at the conclusion of the most recent
6999 ** sqlite3_backup_step().
7000 ** ^(The values returned by these functions are only updated by
7001 ** sqlite3_backup_step(). If the source database is modified in a way that
7002 ** changes the size of the source database or the number of pages remaining,
7003 ** those changes are not reflected in the output of sqlite3_backup_pagecount()
7004 ** and sqlite3_backup_remaining() until after the next
7005 ** sqlite3_backup_step().)^
7006 **
7007 ** <b>Concurrent Usage of Database Handles</b>
7008 **
7009 ** ^The source [database connection] may be used by the application for other
7010 ** purposes while a backup operation is underway or being initialized.
7011
+28 -2
--- src/th_main.c
+++ src/th_main.c
@@ -1839,10 +1839,16 @@
18391839
** Make sure that the TH1 script error was not caused by a "missing"
18401840
** command hook handler as that is not actually an error condition.
18411841
*/
18421842
if( memcmp(zResult, NO_COMMAND_HOOK_ERROR, nResult)!=0 ){
18431843
sendError(zResult, nResult, 0);
1844
+ }else{
1845
+ /*
1846
+ ** There is no command hook handler "installed". This situation
1847
+ ** is NOT actually an error.
1848
+ */
1849
+ rc = TH_OK;
18441850
}
18451851
}
18461852
/*
18471853
** If the script returned TH_ERROR (e.g. the "command_hook" TH1 command does
18481854
** not exist because commands are not being hooked), return TH_OK because we
@@ -1859,11 +1865,11 @@
18591865
** clean it up now. This is very important because some commands do not
18601866
** expect the repository and/or the configuration ("user") database to be
18611867
** open prior to their own code doing so.
18621868
*/
18631869
if( TH_INIT_HOOK & TH_INIT_NEED_CONFIG ) Th_CloseConfig(1);
1864
- return (rc != TH_ERROR) ? rc : TH_OK;
1870
+ return rc;
18651871
}
18661872
18671873
/*
18681874
** This function is called by Fossil just after dispatching a command.
18691875
** Returning a value other than TH_OK from this function (i.e. via an
@@ -1920,10 +1926,16 @@
19201926
** Make sure that the TH1 script error was not caused by a "missing"
19211927
** webpage hook handler as that is not actually an error condition.
19221928
*/
19231929
if( memcmp(zResult, NO_WEBPAGE_HOOK_ERROR, nResult)!=0 ){
19241930
sendError(zResult, nResult, 1);
1931
+ }else{
1932
+ /*
1933
+ ** There is no webpage hook handler "installed". This situation
1934
+ ** is NOT actually an error.
1935
+ */
1936
+ rc = TH_OK;
19251937
}
19261938
}
19271939
/*
19281940
** If the script returned TH_ERROR (e.g. the "webpage_hook" TH1 command does
19291941
** not exist because commands are not being hooked), return TH_OK because we
@@ -1940,11 +1952,11 @@
19401952
** clean it up now. This is very important because some commands do not
19411953
** expect the repository and/or the configuration ("user") database to be
19421954
** open prior to their own code doing so.
19431955
*/
19441956
if( TH_INIT_HOOK & TH_INIT_NEED_CONFIG ) Th_CloseConfig(1);
1945
- return (rc != TH_ERROR) ? rc : TH_OK;
1957
+ return rc;
19461958
}
19471959
19481960
/*
19491961
** This function is called by Fossil just after processing a web page.
19501962
** Returning a value other than TH_OK from this function (i.e. via an
@@ -1975,10 +1987,24 @@
19751987
*/
19761988
if( TH_INIT_HOOK & TH_INIT_NEED_CONFIG ) Th_CloseConfig(1);
19771989
return rc;
19781990
}
19791991
#endif
1992
+
1993
+
1994
+#ifdef FOSSIL_ENABLE_TH1_DOCS
1995
+/*
1996
+** This function determines if TH1 docs are enabled for the repository.
1997
+*/
1998
+int Th_AreDocsEnabled(void){
1999
+ if( fossil_getenv("TH1_ENABLE_DOCS")!=0 ){
2000
+ return 1;
2001
+ }
2002
+ return db_get_boolean("th1-docs", 0);
2003
+}
2004
+#endif
2005
+
19802006
19812007
/*
19822008
** The z[] input contains text mixed with TH1 scripts.
19832009
** The TH1 scripts are contained within <th1>...</th1>.
19842010
** TH1 variables are $aaa or $<aaa>. The first form of
19852011
--- src/th_main.c
+++ src/th_main.c
@@ -1839,10 +1839,16 @@
1839 ** Make sure that the TH1 script error was not caused by a "missing"
1840 ** command hook handler as that is not actually an error condition.
1841 */
1842 if( memcmp(zResult, NO_COMMAND_HOOK_ERROR, nResult)!=0 ){
1843 sendError(zResult, nResult, 0);
 
 
 
 
 
 
1844 }
1845 }
1846 /*
1847 ** If the script returned TH_ERROR (e.g. the "command_hook" TH1 command does
1848 ** not exist because commands are not being hooked), return TH_OK because we
@@ -1859,11 +1865,11 @@
1859 ** clean it up now. This is very important because some commands do not
1860 ** expect the repository and/or the configuration ("user") database to be
1861 ** open prior to their own code doing so.
1862 */
1863 if( TH_INIT_HOOK & TH_INIT_NEED_CONFIG ) Th_CloseConfig(1);
1864 return (rc != TH_ERROR) ? rc : TH_OK;
1865 }
1866
1867 /*
1868 ** This function is called by Fossil just after dispatching a command.
1869 ** Returning a value other than TH_OK from this function (i.e. via an
@@ -1920,10 +1926,16 @@
1920 ** Make sure that the TH1 script error was not caused by a "missing"
1921 ** webpage hook handler as that is not actually an error condition.
1922 */
1923 if( memcmp(zResult, NO_WEBPAGE_HOOK_ERROR, nResult)!=0 ){
1924 sendError(zResult, nResult, 1);
 
 
 
 
 
 
1925 }
1926 }
1927 /*
1928 ** If the script returned TH_ERROR (e.g. the "webpage_hook" TH1 command does
1929 ** not exist because commands are not being hooked), return TH_OK because we
@@ -1940,11 +1952,11 @@
1940 ** clean it up now. This is very important because some commands do not
1941 ** expect the repository and/or the configuration ("user") database to be
1942 ** open prior to their own code doing so.
1943 */
1944 if( TH_INIT_HOOK & TH_INIT_NEED_CONFIG ) Th_CloseConfig(1);
1945 return (rc != TH_ERROR) ? rc : TH_OK;
1946 }
1947
1948 /*
1949 ** This function is called by Fossil just after processing a web page.
1950 ** Returning a value other than TH_OK from this function (i.e. via an
@@ -1975,10 +1987,24 @@
1975 */
1976 if( TH_INIT_HOOK & TH_INIT_NEED_CONFIG ) Th_CloseConfig(1);
1977 return rc;
1978 }
1979 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1980
1981 /*
1982 ** The z[] input contains text mixed with TH1 scripts.
1983 ** The TH1 scripts are contained within <th1>...</th1>.
1984 ** TH1 variables are $aaa or $<aaa>. The first form of
1985
--- src/th_main.c
+++ src/th_main.c
@@ -1839,10 +1839,16 @@
1839 ** Make sure that the TH1 script error was not caused by a "missing"
1840 ** command hook handler as that is not actually an error condition.
1841 */
1842 if( memcmp(zResult, NO_COMMAND_HOOK_ERROR, nResult)!=0 ){
1843 sendError(zResult, nResult, 0);
1844 }else{
1845 /*
1846 ** There is no command hook handler "installed". This situation
1847 ** is NOT actually an error.
1848 */
1849 rc = TH_OK;
1850 }
1851 }
1852 /*
1853 ** If the script returned TH_ERROR (e.g. the "command_hook" TH1 command does
1854 ** not exist because commands are not being hooked), return TH_OK because we
@@ -1859,11 +1865,11 @@
1865 ** clean it up now. This is very important because some commands do not
1866 ** expect the repository and/or the configuration ("user") database to be
1867 ** open prior to their own code doing so.
1868 */
1869 if( TH_INIT_HOOK & TH_INIT_NEED_CONFIG ) Th_CloseConfig(1);
1870 return rc;
1871 }
1872
1873 /*
1874 ** This function is called by Fossil just after dispatching a command.
1875 ** Returning a value other than TH_OK from this function (i.e. via an
@@ -1920,10 +1926,16 @@
1926 ** Make sure that the TH1 script error was not caused by a "missing"
1927 ** webpage hook handler as that is not actually an error condition.
1928 */
1929 if( memcmp(zResult, NO_WEBPAGE_HOOK_ERROR, nResult)!=0 ){
1930 sendError(zResult, nResult, 1);
1931 }else{
1932 /*
1933 ** There is no webpage hook handler "installed". This situation
1934 ** is NOT actually an error.
1935 */
1936 rc = TH_OK;
1937 }
1938 }
1939 /*
1940 ** If the script returned TH_ERROR (e.g. the "webpage_hook" TH1 command does
1941 ** not exist because commands are not being hooked), return TH_OK because we
@@ -1940,11 +1952,11 @@
1952 ** clean it up now. This is very important because some commands do not
1953 ** expect the repository and/or the configuration ("user") database to be
1954 ** open prior to their own code doing so.
1955 */
1956 if( TH_INIT_HOOK & TH_INIT_NEED_CONFIG ) Th_CloseConfig(1);
1957 return rc;
1958 }
1959
1960 /*
1961 ** This function is called by Fossil just after processing a web page.
1962 ** Returning a value other than TH_OK from this function (i.e. via an
@@ -1975,10 +1987,24 @@
1987 */
1988 if( TH_INIT_HOOK & TH_INIT_NEED_CONFIG ) Th_CloseConfig(1);
1989 return rc;
1990 }
1991 #endif
1992
1993
1994 #ifdef FOSSIL_ENABLE_TH1_DOCS
1995 /*
1996 ** This function determines if TH1 docs are enabled for the repository.
1997 */
1998 int Th_AreDocsEnabled(void){
1999 if( fossil_getenv("TH1_ENABLE_DOCS")!=0 ){
2000 return 1;
2001 }
2002 return db_get_boolean("th1-docs", 0);
2003 }
2004 #endif
2005
2006
2007 /*
2008 ** The z[] input contains text mixed with TH1 scripts.
2009 ** The TH1 scripts are contained within <th1>...</th1>.
2010 ** TH1 variables are $aaa or $<aaa>. The first form of
2011
+28 -2
--- src/th_main.c
+++ src/th_main.c
@@ -1839,10 +1839,16 @@
18391839
** Make sure that the TH1 script error was not caused by a "missing"
18401840
** command hook handler as that is not actually an error condition.
18411841
*/
18421842
if( memcmp(zResult, NO_COMMAND_HOOK_ERROR, nResult)!=0 ){
18431843
sendError(zResult, nResult, 0);
1844
+ }else{
1845
+ /*
1846
+ ** There is no command hook handler "installed". This situation
1847
+ ** is NOT actually an error.
1848
+ */
1849
+ rc = TH_OK;
18441850
}
18451851
}
18461852
/*
18471853
** If the script returned TH_ERROR (e.g. the "command_hook" TH1 command does
18481854
** not exist because commands are not being hooked), return TH_OK because we
@@ -1859,11 +1865,11 @@
18591865
** clean it up now. This is very important because some commands do not
18601866
** expect the repository and/or the configuration ("user") database to be
18611867
** open prior to their own code doing so.
18621868
*/
18631869
if( TH_INIT_HOOK & TH_INIT_NEED_CONFIG ) Th_CloseConfig(1);
1864
- return (rc != TH_ERROR) ? rc : TH_OK;
1870
+ return rc;
18651871
}
18661872
18671873
/*
18681874
** This function is called by Fossil just after dispatching a command.
18691875
** Returning a value other than TH_OK from this function (i.e. via an
@@ -1920,10 +1926,16 @@
19201926
** Make sure that the TH1 script error was not caused by a "missing"
19211927
** webpage hook handler as that is not actually an error condition.
19221928
*/
19231929
if( memcmp(zResult, NO_WEBPAGE_HOOK_ERROR, nResult)!=0 ){
19241930
sendError(zResult, nResult, 1);
1931
+ }else{
1932
+ /*
1933
+ ** There is no webpage hook handler "installed". This situation
1934
+ ** is NOT actually an error.
1935
+ */
1936
+ rc = TH_OK;
19251937
}
19261938
}
19271939
/*
19281940
** If the script returned TH_ERROR (e.g. the "webpage_hook" TH1 command does
19291941
** not exist because commands are not being hooked), return TH_OK because we
@@ -1940,11 +1952,11 @@
19401952
** clean it up now. This is very important because some commands do not
19411953
** expect the repository and/or the configuration ("user") database to be
19421954
** open prior to their own code doing so.
19431955
*/
19441956
if( TH_INIT_HOOK & TH_INIT_NEED_CONFIG ) Th_CloseConfig(1);
1945
- return (rc != TH_ERROR) ? rc : TH_OK;
1957
+ return rc;
19461958
}
19471959
19481960
/*
19491961
** This function is called by Fossil just after processing a web page.
19501962
** Returning a value other than TH_OK from this function (i.e. via an
@@ -1975,10 +1987,24 @@
19751987
*/
19761988
if( TH_INIT_HOOK & TH_INIT_NEED_CONFIG ) Th_CloseConfig(1);
19771989
return rc;
19781990
}
19791991
#endif
1992
+
1993
+
1994
+#ifdef FOSSIL_ENABLE_TH1_DOCS
1995
+/*
1996
+** This function determines if TH1 docs are enabled for the repository.
1997
+*/
1998
+int Th_AreDocsEnabled(void){
1999
+ if( fossil_getenv("TH1_ENABLE_DOCS")!=0 ){
2000
+ return 1;
2001
+ }
2002
+ return db_get_boolean("th1-docs", 0);
2003
+}
2004
+#endif
2005
+
19802006
19812007
/*
19822008
** The z[] input contains text mixed with TH1 scripts.
19832009
** The TH1 scripts are contained within <th1>...</th1>.
19842010
** TH1 variables are $aaa or $<aaa>. The first form of
19852011
--- src/th_main.c
+++ src/th_main.c
@@ -1839,10 +1839,16 @@
1839 ** Make sure that the TH1 script error was not caused by a "missing"
1840 ** command hook handler as that is not actually an error condition.
1841 */
1842 if( memcmp(zResult, NO_COMMAND_HOOK_ERROR, nResult)!=0 ){
1843 sendError(zResult, nResult, 0);
 
 
 
 
 
 
1844 }
1845 }
1846 /*
1847 ** If the script returned TH_ERROR (e.g. the "command_hook" TH1 command does
1848 ** not exist because commands are not being hooked), return TH_OK because we
@@ -1859,11 +1865,11 @@
1859 ** clean it up now. This is very important because some commands do not
1860 ** expect the repository and/or the configuration ("user") database to be
1861 ** open prior to their own code doing so.
1862 */
1863 if( TH_INIT_HOOK & TH_INIT_NEED_CONFIG ) Th_CloseConfig(1);
1864 return (rc != TH_ERROR) ? rc : TH_OK;
1865 }
1866
1867 /*
1868 ** This function is called by Fossil just after dispatching a command.
1869 ** Returning a value other than TH_OK from this function (i.e. via an
@@ -1920,10 +1926,16 @@
1920 ** Make sure that the TH1 script error was not caused by a "missing"
1921 ** webpage hook handler as that is not actually an error condition.
1922 */
1923 if( memcmp(zResult, NO_WEBPAGE_HOOK_ERROR, nResult)!=0 ){
1924 sendError(zResult, nResult, 1);
 
 
 
 
 
 
1925 }
1926 }
1927 /*
1928 ** If the script returned TH_ERROR (e.g. the "webpage_hook" TH1 command does
1929 ** not exist because commands are not being hooked), return TH_OK because we
@@ -1940,11 +1952,11 @@
1940 ** clean it up now. This is very important because some commands do not
1941 ** expect the repository and/or the configuration ("user") database to be
1942 ** open prior to their own code doing so.
1943 */
1944 if( TH_INIT_HOOK & TH_INIT_NEED_CONFIG ) Th_CloseConfig(1);
1945 return (rc != TH_ERROR) ? rc : TH_OK;
1946 }
1947
1948 /*
1949 ** This function is called by Fossil just after processing a web page.
1950 ** Returning a value other than TH_OK from this function (i.e. via an
@@ -1975,10 +1987,24 @@
1975 */
1976 if( TH_INIT_HOOK & TH_INIT_NEED_CONFIG ) Th_CloseConfig(1);
1977 return rc;
1978 }
1979 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1980
1981 /*
1982 ** The z[] input contains text mixed with TH1 scripts.
1983 ** The TH1 scripts are contained within <th1>...</th1>.
1984 ** TH1 variables are $aaa or $<aaa>. The first form of
1985
--- src/th_main.c
+++ src/th_main.c
@@ -1839,10 +1839,16 @@
1839 ** Make sure that the TH1 script error was not caused by a "missing"
1840 ** command hook handler as that is not actually an error condition.
1841 */
1842 if( memcmp(zResult, NO_COMMAND_HOOK_ERROR, nResult)!=0 ){
1843 sendError(zResult, nResult, 0);
1844 }else{
1845 /*
1846 ** There is no command hook handler "installed". This situation
1847 ** is NOT actually an error.
1848 */
1849 rc = TH_OK;
1850 }
1851 }
1852 /*
1853 ** If the script returned TH_ERROR (e.g. the "command_hook" TH1 command does
1854 ** not exist because commands are not being hooked), return TH_OK because we
@@ -1859,11 +1865,11 @@
1865 ** clean it up now. This is very important because some commands do not
1866 ** expect the repository and/or the configuration ("user") database to be
1867 ** open prior to their own code doing so.
1868 */
1869 if( TH_INIT_HOOK & TH_INIT_NEED_CONFIG ) Th_CloseConfig(1);
1870 return rc;
1871 }
1872
1873 /*
1874 ** This function is called by Fossil just after dispatching a command.
1875 ** Returning a value other than TH_OK from this function (i.e. via an
@@ -1920,10 +1926,16 @@
1926 ** Make sure that the TH1 script error was not caused by a "missing"
1927 ** webpage hook handler as that is not actually an error condition.
1928 */
1929 if( memcmp(zResult, NO_WEBPAGE_HOOK_ERROR, nResult)!=0 ){
1930 sendError(zResult, nResult, 1);
1931 }else{
1932 /*
1933 ** There is no webpage hook handler "installed". This situation
1934 ** is NOT actually an error.
1935 */
1936 rc = TH_OK;
1937 }
1938 }
1939 /*
1940 ** If the script returned TH_ERROR (e.g. the "webpage_hook" TH1 command does
1941 ** not exist because commands are not being hooked), return TH_OK because we
@@ -1940,11 +1952,11 @@
1952 ** clean it up now. This is very important because some commands do not
1953 ** expect the repository and/or the configuration ("user") database to be
1954 ** open prior to their own code doing so.
1955 */
1956 if( TH_INIT_HOOK & TH_INIT_NEED_CONFIG ) Th_CloseConfig(1);
1957 return rc;
1958 }
1959
1960 /*
1961 ** This function is called by Fossil just after processing a web page.
1962 ** Returning a value other than TH_OK from this function (i.e. via an
@@ -1975,10 +1987,24 @@
1987 */
1988 if( TH_INIT_HOOK & TH_INIT_NEED_CONFIG ) Th_CloseConfig(1);
1989 return rc;
1990 }
1991 #endif
1992
1993
1994 #ifdef FOSSIL_ENABLE_TH1_DOCS
1995 /*
1996 ** This function determines if TH1 docs are enabled for the repository.
1997 */
1998 int Th_AreDocsEnabled(void){
1999 if( fossil_getenv("TH1_ENABLE_DOCS")!=0 ){
2000 return 1;
2001 }
2002 return db_get_boolean("th1-docs", 0);
2003 }
2004 #endif
2005
2006
2007 /*
2008 ** The z[] input contains text mixed with TH1 scripts.
2009 ** The TH1 scripts are contained within <th1>...</th1>.
2010 ** TH1 variables are $aaa or $<aaa>. The first form of
2011
+35 -18
--- src/timeline.c
+++ src/timeline.c
@@ -752,25 +752,25 @@
752752
@ }while( obj = obj.offsetParent );
753753
@ }
754754
@ return left;
755755
@ }
756756
@ function drawUpArrow(x,y0,y1){
757
- @ drawBox(lineClr,x,y0+5,x+1,y1);
757
+ @ drawBox(lineClr,x,y0+4,x+1,y1);
758758
@ var n = document.createElement("div"),
759759
@ l = x-2,
760760
@ t = y0;
761761
@ n.style.position = "absolute";
762762
@ n.style.left = l+"px";
763763
@ n.style.top = t+"px";
764764
@ n.style.width = 0;
765765
@ n.style.height = 0;
766
+ @ n.style.transform = "scale(.999)";
766767
@ n.style.borderWidth = 0;
767768
@ n.style.borderStyle = "solid";
768769
@ n.style.borderColor = "transparent";
769770
@ n.style.borderRightWidth = "3px";
770
- @ n.style.borderBottomColor = "#000";
771
- @ n.style.borderBottomStyle = "outset";
771
+ @ n.style.borderBottomColor = lineClr;
772772
@ n.style.borderLeftWidth = "3px";
773773
@ if( y0+10>=y1 ){
774774
@ n.style.borderBottomWidth = "5px";
775775
@ } else {
776776
@ n.style.borderBottomWidth = "7px";
@@ -782,27 +782,26 @@
782782
@ t = y-2;
783783
@ n.style.position = "absolute";
784784
@ n.style.top = t+"px";
785785
@ n.style.width = 0;
786786
@ n.style.height = "1px";
787
+ @ n.style.transform = "scale(.999)";
787788
@ n.style.borderWidth = 0;
788789
@ n.style.borderStyle = "solid";
789790
@ n.style.borderColor = "transparent";
790791
@ n.style.borderTopWidth = "2px";
791792
@ n.style.borderBottomWidth = "2px";
792793
@ if( xFrom<xTo ){
793794
@ drawBox(lineClr,xFrom,y,xTo-3,y);
794795
@ n.style.left = xTo-3+"px";
795
- @ n.style.borderLeftStyle = "inset";
796796
@ n.style.borderLeftWidth = "3px";
797
- @ n.style.borderLeftColor = "#000";
797
+ @ n.style.borderLeftColor = lineClr;
798798
@ }else{
799799
@ drawBox(lineClr,xTo+3,y,xFrom,y);
800800
@ n.style.left = xTo+1+"px";
801
- @ n.style.borderRightStyle = "outset";
802801
@ n.style.borderRightWidth = "3px";
803
- @ n.style.borderRightColor = "#000";
802
+ @ n.style.borderRightColor = lineClr;
804803
@ }
805804
@ cDiv.appendChild(n);
806805
@ }
807806
@ function drawThinLine(x0,y0,x1,y1){
808807
@ drawBox(lineClr,x0,y0,x1,y1);
@@ -851,16 +850,16 @@
851850
@ n.style.position = "absolute";
852851
@ n.style.top = t+"px";
853852
@ n.style.left = l+"px";
854853
@ n.style.width = 0;
855854
@ n.style.height = 0;
855
+ @ n.style.transform = "scale(.999)";
856856
@ n.style.borderWidth = 0;
857857
@ n.style.borderStyle = "solid";
858858
@ n.style.borderColor = "transparent";
859859
@ n.style.borderTopWidth = "3px";
860860
@ n.style.borderBottomWidth = "3px";
861
- @ n.style.borderLeftStyle = "inset";
862861
@ n.style.borderLeftWidth = "7px";
863862
@ n.style.borderLeftColor = "#600000";
864863
@ cDiv.appendChild(n);
865864
@ }
866865
@ }
@@ -1421,11 +1420,11 @@
14211420
if( (tmFlags & TIMELINE_UNHIDE)==0 ){
14221421
timeline_submenu(&url, "Unhide", "unhide", "", 0);
14231422
}
14241423
}else{
14251424
/* Otherwise, a timeline based on a span of time */
1426
- int n;
1425
+ int n, nBefore, nAfter;
14271426
const char *zEType = "timeline item";
14281427
char *zDate;
14291428
if( zUses ){
14301429
blob_append_sql(&sql, " AND event.objid IN usesfile ");
14311430
}
@@ -1629,20 +1628,38 @@
16291628
}
16301629
if( zSearch ){
16311630
blob_appendf(&desc, " matching \"%h\"", zSearch);
16321631
}
16331632
if( g.perm.Hyperlink ){
1634
- if( zAfter || n==nEntry ){
1633
+ if( zCirca && rCirca ){
1634
+ nBefore = db_int(0,
1635
+ "SELECT count(*) FROM timeline WHERE etype!='div'"
1636
+ " AND sortby<=%f /*scan*/", rCirca);
1637
+ nAfter = db_int(0,
1638
+ "SELECT count(*) FROM timeline WHERE etype!='div'"
1639
+ " AND sortby>=%f /*scan*/", rCirca);
16351640
zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/");
1636
- timeline_submenu(&url, "Older", "b", zDate, "a");
1637
- zOlderButton = fossil_strdup(url_render(&url, "b", zDate, "a", 0));
1638
- free(zDate);
1639
- }
1640
- if( zBefore || (zAfter && n==nEntry) ){
1641
- zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/");
1642
- timeline_submenu(&url, "Newer", "a", zDate, "b");
1643
- free(zDate);
1641
+ if( nBefore>=nEntry ){
1642
+ timeline_submenu(&url, "Older", "b", zDate, "c");
1643
+ zOlderButton = fossil_strdup(url_render(&url, "b", zDate, "c", 0));
1644
+ }
1645
+ if( nAfter>=nEntry ){
1646
+ timeline_submenu(&url, "Newer", "a", zDate, "c");
1647
+ }
1648
+ free(zDate);
1649
+ }else{
1650
+ if( zAfter || n==nEntry ){
1651
+ zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/");
1652
+ timeline_submenu(&url, "Older", "b", zDate, "a");
1653
+ zOlderButton = fossil_strdup(url_render(&url, "b", zDate, "a", 0));
1654
+ free(zDate);
1655
+ }
1656
+ if( zBefore || (zAfter && n==nEntry) ){
1657
+ zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/");
1658
+ timeline_submenu(&url, "Newer", "a", zDate, "b");
1659
+ free(zDate);
1660
+ }
16441661
}
16451662
if( zType[0]=='a' || zType[0]=='c' ){
16461663
if( (tmFlags & TIMELINE_UNHIDE)==0 ){
16471664
timeline_submenu(&url, "Unhide", "unhide", "", 0);
16481665
}
16491666
--- src/timeline.c
+++ src/timeline.c
@@ -752,25 +752,25 @@
752 @ }while( obj = obj.offsetParent );
753 @ }
754 @ return left;
755 @ }
756 @ function drawUpArrow(x,y0,y1){
757 @ drawBox(lineClr,x,y0+5,x+1,y1);
758 @ var n = document.createElement("div"),
759 @ l = x-2,
760 @ t = y0;
761 @ n.style.position = "absolute";
762 @ n.style.left = l+"px";
763 @ n.style.top = t+"px";
764 @ n.style.width = 0;
765 @ n.style.height = 0;
 
766 @ n.style.borderWidth = 0;
767 @ n.style.borderStyle = "solid";
768 @ n.style.borderColor = "transparent";
769 @ n.style.borderRightWidth = "3px";
770 @ n.style.borderBottomColor = "#000";
771 @ n.style.borderBottomStyle = "outset";
772 @ n.style.borderLeftWidth = "3px";
773 @ if( y0+10>=y1 ){
774 @ n.style.borderBottomWidth = "5px";
775 @ } else {
776 @ n.style.borderBottomWidth = "7px";
@@ -782,27 +782,26 @@
782 @ t = y-2;
783 @ n.style.position = "absolute";
784 @ n.style.top = t+"px";
785 @ n.style.width = 0;
786 @ n.style.height = "1px";
 
787 @ n.style.borderWidth = 0;
788 @ n.style.borderStyle = "solid";
789 @ n.style.borderColor = "transparent";
790 @ n.style.borderTopWidth = "2px";
791 @ n.style.borderBottomWidth = "2px";
792 @ if( xFrom<xTo ){
793 @ drawBox(lineClr,xFrom,y,xTo-3,y);
794 @ n.style.left = xTo-3+"px";
795 @ n.style.borderLeftStyle = "inset";
796 @ n.style.borderLeftWidth = "3px";
797 @ n.style.borderLeftColor = "#000";
798 @ }else{
799 @ drawBox(lineClr,xTo+3,y,xFrom,y);
800 @ n.style.left = xTo+1+"px";
801 @ n.style.borderRightStyle = "outset";
802 @ n.style.borderRightWidth = "3px";
803 @ n.style.borderRightColor = "#000";
804 @ }
805 @ cDiv.appendChild(n);
806 @ }
807 @ function drawThinLine(x0,y0,x1,y1){
808 @ drawBox(lineClr,x0,y0,x1,y1);
@@ -851,16 +850,16 @@
851 @ n.style.position = "absolute";
852 @ n.style.top = t+"px";
853 @ n.style.left = l+"px";
854 @ n.style.width = 0;
855 @ n.style.height = 0;
 
856 @ n.style.borderWidth = 0;
857 @ n.style.borderStyle = "solid";
858 @ n.style.borderColor = "transparent";
859 @ n.style.borderTopWidth = "3px";
860 @ n.style.borderBottomWidth = "3px";
861 @ n.style.borderLeftStyle = "inset";
862 @ n.style.borderLeftWidth = "7px";
863 @ n.style.borderLeftColor = "#600000";
864 @ cDiv.appendChild(n);
865 @ }
866 @ }
@@ -1421,11 +1420,11 @@
1421 if( (tmFlags & TIMELINE_UNHIDE)==0 ){
1422 timeline_submenu(&url, "Unhide", "unhide", "", 0);
1423 }
1424 }else{
1425 /* Otherwise, a timeline based on a span of time */
1426 int n;
1427 const char *zEType = "timeline item";
1428 char *zDate;
1429 if( zUses ){
1430 blob_append_sql(&sql, " AND event.objid IN usesfile ");
1431 }
@@ -1629,20 +1628,38 @@
1629 }
1630 if( zSearch ){
1631 blob_appendf(&desc, " matching \"%h\"", zSearch);
1632 }
1633 if( g.perm.Hyperlink ){
1634 if( zAfter || n==nEntry ){
 
 
 
 
 
 
1635 zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/");
1636 timeline_submenu(&url, "Older", "b", zDate, "a");
1637 zOlderButton = fossil_strdup(url_render(&url, "b", zDate, "a", 0));
1638 free(zDate);
1639 }
1640 if( zBefore || (zAfter && n==nEntry) ){
1641 zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/");
1642 timeline_submenu(&url, "Newer", "a", zDate, "b");
1643 free(zDate);
 
 
 
 
 
 
 
 
 
 
 
 
1644 }
1645 if( zType[0]=='a' || zType[0]=='c' ){
1646 if( (tmFlags & TIMELINE_UNHIDE)==0 ){
1647 timeline_submenu(&url, "Unhide", "unhide", "", 0);
1648 }
1649
--- src/timeline.c
+++ src/timeline.c
@@ -752,25 +752,25 @@
752 @ }while( obj = obj.offsetParent );
753 @ }
754 @ return left;
755 @ }
756 @ function drawUpArrow(x,y0,y1){
757 @ drawBox(lineClr,x,y0+4,x+1,y1);
758 @ var n = document.createElement("div"),
759 @ l = x-2,
760 @ t = y0;
761 @ n.style.position = "absolute";
762 @ n.style.left = l+"px";
763 @ n.style.top = t+"px";
764 @ n.style.width = 0;
765 @ n.style.height = 0;
766 @ n.style.transform = "scale(.999)";
767 @ n.style.borderWidth = 0;
768 @ n.style.borderStyle = "solid";
769 @ n.style.borderColor = "transparent";
770 @ n.style.borderRightWidth = "3px";
771 @ n.style.borderBottomColor = lineClr;
 
772 @ n.style.borderLeftWidth = "3px";
773 @ if( y0+10>=y1 ){
774 @ n.style.borderBottomWidth = "5px";
775 @ } else {
776 @ n.style.borderBottomWidth = "7px";
@@ -782,27 +782,26 @@
782 @ t = y-2;
783 @ n.style.position = "absolute";
784 @ n.style.top = t+"px";
785 @ n.style.width = 0;
786 @ n.style.height = "1px";
787 @ n.style.transform = "scale(.999)";
788 @ n.style.borderWidth = 0;
789 @ n.style.borderStyle = "solid";
790 @ n.style.borderColor = "transparent";
791 @ n.style.borderTopWidth = "2px";
792 @ n.style.borderBottomWidth = "2px";
793 @ if( xFrom<xTo ){
794 @ drawBox(lineClr,xFrom,y,xTo-3,y);
795 @ n.style.left = xTo-3+"px";
 
796 @ n.style.borderLeftWidth = "3px";
797 @ n.style.borderLeftColor = lineClr;
798 @ }else{
799 @ drawBox(lineClr,xTo+3,y,xFrom,y);
800 @ n.style.left = xTo+1+"px";
 
801 @ n.style.borderRightWidth = "3px";
802 @ n.style.borderRightColor = lineClr;
803 @ }
804 @ cDiv.appendChild(n);
805 @ }
806 @ function drawThinLine(x0,y0,x1,y1){
807 @ drawBox(lineClr,x0,y0,x1,y1);
@@ -851,16 +850,16 @@
850 @ n.style.position = "absolute";
851 @ n.style.top = t+"px";
852 @ n.style.left = l+"px";
853 @ n.style.width = 0;
854 @ n.style.height = 0;
855 @ n.style.transform = "scale(.999)";
856 @ n.style.borderWidth = 0;
857 @ n.style.borderStyle = "solid";
858 @ n.style.borderColor = "transparent";
859 @ n.style.borderTopWidth = "3px";
860 @ n.style.borderBottomWidth = "3px";
 
861 @ n.style.borderLeftWidth = "7px";
862 @ n.style.borderLeftColor = "#600000";
863 @ cDiv.appendChild(n);
864 @ }
865 @ }
@@ -1421,11 +1420,11 @@
1420 if( (tmFlags & TIMELINE_UNHIDE)==0 ){
1421 timeline_submenu(&url, "Unhide", "unhide", "", 0);
1422 }
1423 }else{
1424 /* Otherwise, a timeline based on a span of time */
1425 int n, nBefore, nAfter;
1426 const char *zEType = "timeline item";
1427 char *zDate;
1428 if( zUses ){
1429 blob_append_sql(&sql, " AND event.objid IN usesfile ");
1430 }
@@ -1629,20 +1628,38 @@
1628 }
1629 if( zSearch ){
1630 blob_appendf(&desc, " matching \"%h\"", zSearch);
1631 }
1632 if( g.perm.Hyperlink ){
1633 if( zCirca && rCirca ){
1634 nBefore = db_int(0,
1635 "SELECT count(*) FROM timeline WHERE etype!='div'"
1636 " AND sortby<=%f /*scan*/", rCirca);
1637 nAfter = db_int(0,
1638 "SELECT count(*) FROM timeline WHERE etype!='div'"
1639 " AND sortby>=%f /*scan*/", rCirca);
1640 zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/");
1641 if( nBefore>=nEntry ){
1642 timeline_submenu(&url, "Older", "b", zDate, "c");
1643 zOlderButton = fossil_strdup(url_render(&url, "b", zDate, "c", 0));
1644 }
1645 if( nAfter>=nEntry ){
1646 timeline_submenu(&url, "Newer", "a", zDate, "c");
1647 }
1648 free(zDate);
1649 }else{
1650 if( zAfter || n==nEntry ){
1651 zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/");
1652 timeline_submenu(&url, "Older", "b", zDate, "a");
1653 zOlderButton = fossil_strdup(url_render(&url, "b", zDate, "a", 0));
1654 free(zDate);
1655 }
1656 if( zBefore || (zAfter && n==nEntry) ){
1657 zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/");
1658 timeline_submenu(&url, "Newer", "a", zDate, "b");
1659 free(zDate);
1660 }
1661 }
1662 if( zType[0]=='a' || zType[0]=='c' ){
1663 if( (tmFlags & TIMELINE_UNHIDE)==0 ){
1664 timeline_submenu(&url, "Unhide", "unhide", "", 0);
1665 }
1666
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -1250,10 +1250,12 @@
12501250
zTerm = "]</span>";
12511251
}
12521252
}else if( g.perm.Hyperlink ){
12531253
blob_appendf(p->pOut, "%z[",href("%R/info/%s", zTarget));
12541254
zTerm = "]</a>";
1255
+ }else{
1256
+ zTerm = "";
12551257
}
12561258
}else if( strlen(zTarget)>=10 && fossil_isdigit(zTarget[0]) && zTarget[4]=='-'
12571259
&& db_int(0, "SELECT datetime(%Q) NOT NULL", zTarget) ){
12581260
blob_appendf(p->pOut, "<a href=\"%R/timeline?c=%T\">", zTarget);
12591261
}else if( (z = validWikiPageName(p, zTarget))!=0 ){
12601262
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -1250,10 +1250,12 @@
1250 zTerm = "]</span>";
1251 }
1252 }else if( g.perm.Hyperlink ){
1253 blob_appendf(p->pOut, "%z[",href("%R/info/%s", zTarget));
1254 zTerm = "]</a>";
 
 
1255 }
1256 }else if( strlen(zTarget)>=10 && fossil_isdigit(zTarget[0]) && zTarget[4]=='-'
1257 && db_int(0, "SELECT datetime(%Q) NOT NULL", zTarget) ){
1258 blob_appendf(p->pOut, "<a href=\"%R/timeline?c=%T\">", zTarget);
1259 }else if( (z = validWikiPageName(p, zTarget))!=0 ){
1260
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -1250,10 +1250,12 @@
1250 zTerm = "]</span>";
1251 }
1252 }else if( g.perm.Hyperlink ){
1253 blob_appendf(p->pOut, "%z[",href("%R/info/%s", zTarget));
1254 zTerm = "]</a>";
1255 }else{
1256 zTerm = "";
1257 }
1258 }else if( strlen(zTarget)>=10 && fossil_isdigit(zTarget[0]) && zTarget[4]=='-'
1259 && db_int(0, "SELECT datetime(%Q) NOT NULL", zTarget) ){
1260 blob_appendf(p->pOut, "<a href=\"%R/timeline?c=%T\">", zTarget);
1261 }else if( (z = validWikiPageName(p, zTarget))!=0 ){
1262
+18 -17
--- src/xfersetup.c
+++ src/xfersetup.c
@@ -33,11 +33,11 @@
3333
return;
3434
}
3535
3636
style_header("Transfer Setup");
3737
38
- @ <table border="0" cellspacing="20">
38
+ @ <table class="xfersetup">
3939
setup_menu_entry("Common", "xfersetup_com",
4040
"Common TH1 code run before all transfer request processing.");
4141
setup_menu_entry("Push", "xfersetup_push",
4242
"Specific TH1 code to run after \"push\" transfer requests.");
4343
setup_menu_entry("Commit", "xfersetup_commit",
@@ -60,33 +60,33 @@
6060
syncFlags = SYNC_PUSH | SYNC_PULL;
6161
zButton = "Synchronize";
6262
zWarning = mprintf("WARNING: Pushing to \"%s\" is enabled.",
6363
g.url.canonical);
6464
}
65
- if( P("sync") ){
66
- user_select();
67
- url_enable_proxy(0);
68
- client_sync(syncFlags, 0, 0);
69
- }
70
- @ <p>Press the %h(zButton) button below to synchronize with the
71
- @ "%h(g.url.canonical)" repository now. This may be useful when
72
- @ testing the various transfer scripts.</p>
73
- @ <p>You can use the "http -async" command in your scripts, but
74
- @ make sure the "th1-uri-regexp" setting is set first.</p>
65
+ @ <p>Press the <strong>%h(zButton)</strong> button below to
66
+ @ synchronize with the <em>%h(g.url.canonical)</em> repository now.<br/>
67
+ @ This may be useful when testing the various transfer scripts.</p>
68
+ @ <p>You can use the <code>http -async</code> command in your scripts, but
69
+ @ make sure the <code>th1-uri-regexp</code> setting is set first.</p>
7570
if( zWarning ){
7671
@
7772
@ <big><b>%h(zWarning)</b></big>
7873
free(zWarning);
7974
}
8075
@
81
- @ <blockquote>
8276
@ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
8377
login_insert_csrf_secret();
8478
@ <input type="submit" name="sync" value="%h(zButton)" />
8579
@ </div></form>
86
- @ </blockquote>
8780
@
81
+ if( P("sync") ){
82
+ user_select();
83
+ url_enable_proxy(0);
84
+ @ <pre class="xfersetup">
85
+ client_sync(syncFlags, 0, 0);
86
+ @ </pre>
87
+ }
8888
}
8989
9090
style_footer();
9191
}
9292
@@ -137,18 +137,18 @@
137137
}
138138
@ <form action="%s(g.zTop)/%s(g.zPath)" method="post"><div>
139139
login_insert_csrf_secret();
140140
@ <p>%s(zDesc)</p>
141141
@ <textarea name="x" rows="%d(height)" cols="80">%h(z)</textarea>
142
- @ <blockquote><p>
142
+ @ <p>
143143
@ <input type="submit" name="submit" value="Apply Changes" />
144144
@ <input type="submit" name="clear" value="Revert To Default" />
145145
@ <input type="submit" name="setup" value="Cancel" />
146
- @ </p></blockquote>
146
+ @ </p>
147147
@ </div></form>
148
- @ <hr />
149148
if ( zDfltValue ){
149
+ @ <hr />
150150
@ <h2>Default %s(zTitle)</h2>
151151
@ <blockquote><pre>
152152
@ %h(zDfltValue)
153153
@ </pre></blockquote>
154154
}
@@ -181,11 +181,12 @@
181181
/*
182182
** WEBPAGE: xfersetup_push
183183
*/
184184
void xfersetup_push_page(void){
185185
static const char zDesc[] =
186
- @ Enter TH1 script that runs after processing "push" transfer requests.
186
+ @ Enter TH1 script that runs after processing <strong>push</strong>
187
+ @ transfer requests.
187188
;
188189
xfersetup_generic(
189190
"Transfer Push Script",
190191
"xfer-push-script",
191192
zDefaultXferPush,
192193
193194
ADDED test/fileStat.th1
--- src/xfersetup.c
+++ src/xfersetup.c
@@ -33,11 +33,11 @@
33 return;
34 }
35
36 style_header("Transfer Setup");
37
38 @ <table border="0" cellspacing="20">
39 setup_menu_entry("Common", "xfersetup_com",
40 "Common TH1 code run before all transfer request processing.");
41 setup_menu_entry("Push", "xfersetup_push",
42 "Specific TH1 code to run after \"push\" transfer requests.");
43 setup_menu_entry("Commit", "xfersetup_commit",
@@ -60,33 +60,33 @@
60 syncFlags = SYNC_PUSH | SYNC_PULL;
61 zButton = "Synchronize";
62 zWarning = mprintf("WARNING: Pushing to \"%s\" is enabled.",
63 g.url.canonical);
64 }
65 if( P("sync") ){
66 user_select();
67 url_enable_proxy(0);
68 client_sync(syncFlags, 0, 0);
69 }
70 @ <p>Press the %h(zButton) button below to synchronize with the
71 @ "%h(g.url.canonical)" repository now. This may be useful when
72 @ testing the various transfer scripts.</p>
73 @ <p>You can use the "http -async" command in your scripts, but
74 @ make sure the "th1-uri-regexp" setting is set first.</p>
75 if( zWarning ){
76 @
77 @ <big><b>%h(zWarning)</b></big>
78 free(zWarning);
79 }
80 @
81 @ <blockquote>
82 @ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
83 login_insert_csrf_secret();
84 @ <input type="submit" name="sync" value="%h(zButton)" />
85 @ </div></form>
86 @ </blockquote>
87 @
 
 
 
 
 
 
 
88 }
89
90 style_footer();
91 }
92
@@ -137,18 +137,18 @@
137 }
138 @ <form action="%s(g.zTop)/%s(g.zPath)" method="post"><div>
139 login_insert_csrf_secret();
140 @ <p>%s(zDesc)</p>
141 @ <textarea name="x" rows="%d(height)" cols="80">%h(z)</textarea>
142 @ <blockquote><p>
143 @ <input type="submit" name="submit" value="Apply Changes" />
144 @ <input type="submit" name="clear" value="Revert To Default" />
145 @ <input type="submit" name="setup" value="Cancel" />
146 @ </p></blockquote>
147 @ </div></form>
148 @ <hr />
149 if ( zDfltValue ){
 
150 @ <h2>Default %s(zTitle)</h2>
151 @ <blockquote><pre>
152 @ %h(zDfltValue)
153 @ </pre></blockquote>
154 }
@@ -181,11 +181,12 @@
181 /*
182 ** WEBPAGE: xfersetup_push
183 */
184 void xfersetup_push_page(void){
185 static const char zDesc[] =
186 @ Enter TH1 script that runs after processing "push" transfer requests.
 
187 ;
188 xfersetup_generic(
189 "Transfer Push Script",
190 "xfer-push-script",
191 zDefaultXferPush,
192
193 DDED test/fileStat.th1
--- src/xfersetup.c
+++ src/xfersetup.c
@@ -33,11 +33,11 @@
33 return;
34 }
35
36 style_header("Transfer Setup");
37
38 @ <table class="xfersetup">
39 setup_menu_entry("Common", "xfersetup_com",
40 "Common TH1 code run before all transfer request processing.");
41 setup_menu_entry("Push", "xfersetup_push",
42 "Specific TH1 code to run after \"push\" transfer requests.");
43 setup_menu_entry("Commit", "xfersetup_commit",
@@ -60,33 +60,33 @@
60 syncFlags = SYNC_PUSH | SYNC_PULL;
61 zButton = "Synchronize";
62 zWarning = mprintf("WARNING: Pushing to \"%s\" is enabled.",
63 g.url.canonical);
64 }
65 @ <p>Press the <strong>%h(zButton)</strong> button below to
66 @ synchronize with the <em>%h(g.url.canonical)</em> repository now.<br/>
67 @ This may be useful when testing the various transfer scripts.</p>
68 @ <p>You can use the <code>http -async</code> command in your scripts, but
69 @ make sure the <code>th1-uri-regexp</code> setting is set first.</p>
 
 
 
 
 
70 if( zWarning ){
71 @
72 @ <big><b>%h(zWarning)</b></big>
73 free(zWarning);
74 }
75 @
 
76 @ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
77 login_insert_csrf_secret();
78 @ <input type="submit" name="sync" value="%h(zButton)" />
79 @ </div></form>
 
80 @
81 if( P("sync") ){
82 user_select();
83 url_enable_proxy(0);
84 @ <pre class="xfersetup">
85 client_sync(syncFlags, 0, 0);
86 @ </pre>
87 }
88 }
89
90 style_footer();
91 }
92
@@ -137,18 +137,18 @@
137 }
138 @ <form action="%s(g.zTop)/%s(g.zPath)" method="post"><div>
139 login_insert_csrf_secret();
140 @ <p>%s(zDesc)</p>
141 @ <textarea name="x" rows="%d(height)" cols="80">%h(z)</textarea>
142 @ <p>
143 @ <input type="submit" name="submit" value="Apply Changes" />
144 @ <input type="submit" name="clear" value="Revert To Default" />
145 @ <input type="submit" name="setup" value="Cancel" />
146 @ </p>
147 @ </div></form>
 
148 if ( zDfltValue ){
149 @ <hr />
150 @ <h2>Default %s(zTitle)</h2>
151 @ <blockquote><pre>
152 @ %h(zDfltValue)
153 @ </pre></blockquote>
154 }
@@ -181,11 +181,12 @@
181 /*
182 ** WEBPAGE: xfersetup_push
183 */
184 void xfersetup_push_page(void){
185 static const char zDesc[] =
186 @ Enter TH1 script that runs after processing <strong>push</strong>
187 @ transfer requests.
188 ;
189 xfersetup_generic(
190 "Transfer Push Script",
191 "xfer-push-script",
192 zDefaultXferPush,
193
194 DDED test/fileStat.th1
--- a/test/fileStat.th1
+++ b/test/fileStat.th1
@@ -0,0 +1,29 @@
1
+<th1>
2
+ proc doSomeTclSetup {} {
3
+ #
4
+ # NOTE: Copy repository file name to the Tcl interpreter. This is
5
+ # done first (once) because it will be necessary for almost
6
+ # everything else later on.
7
+ #
8
+ tclInvoke set repository [repository]
9
+
10
+ #
11
+ # NOTE: Create some procedures in the Tcl interpreter to perform
12
+ # useful operations. This could also do things like load
13
+ # packages, etc.
14
+ #
15
+ tclEval {
16
+ #
17
+ # NOTE: Returns an [exec] command for Fossil, using the provided
18
+ # sub-command and arguments, suitable for use with [eval]
19
+ # or [catch].
20
+ #
21
+ proc getFossilCommand { repository user args } {
22
+ global env
23
+
24
+ lappend result exec [info nameofexecutable]
25
+
26
+ if {[info exists env(GATEWAY_INTERFACE)]} then {
27
+ #
28
+ # NOTE: This option is required when calling
29
+ # out to
--- a/test/fileStat.th1
+++ b/test/fileStat.th1
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/test/fileStat.th1
+++ b/test/fileStat.th1
@@ -0,0 +1,29 @@
1 <th1>
2 proc doSomeTclSetup {} {
3 #
4 # NOTE: Copy repository file name to the Tcl interpreter. This is
5 # done first (once) because it will be necessary for almost
6 # everything else later on.
7 #
8 tclInvoke set repository [repository]
9
10 #
11 # NOTE: Create some procedures in the Tcl interpreter to perform
12 # useful operations. This could also do things like load
13 # packages, etc.
14 #
15 tclEval {
16 #
17 # NOTE: Returns an [exec] command for Fossil, using the provided
18 # sub-command and arguments, suitable for use with [eval]
19 # or [catch].
20 #
21 proc getFossilCommand { repository user args } {
22 global env
23
24 lappend result exec [info nameofexecutable]
25
26 if {[info exists env(GATEWAY_INTERFACE)]} then {
27 #
28 # NOTE: This option is required when calling
29 # out to
--- test/tester.tcl
+++ test/tester.tcl
@@ -328,10 +328,76 @@
328328
}
329329
append out \n$line
330330
}
331331
return [string range $out 1 end]
332332
}
333
+
334
+# Executes the "fossil http" command. The entire content of the HTTP request
335
+# is read from the data file name, with [subst] being performed on it prior to
336
+# submission. Temporary input and output files are created and deleted. The
337
+# result will be the contents of the temoprary output file.
338
+proc test_fossil_http { repository dataFileName url } {
339
+ set suffix [appendArgs [pid] - [getSeqNo] - [clock seconds] .txt]
340
+ set inFileName [file join $::tempPath [appendArgs test-http-in- $suffix]]
341
+ set outFileName [file join $::tempPath [appendArgs test-http-out- $suffix]]
342
+ set data [subst [read_file $dataFileName]]
343
+
344
+ write_file $inFileName $data
345
+ fossil http $inFileName $outFileName 127.0.0.1 $repository --localauth
346
+ set result [expr {[file exists $outFileName] ? [read_file $outFileName] : ""}]
347
+
348
+ if {1} then {
349
+ catch {file delete $inFileName}
350
+ catch {file delete $outFileName}
351
+ }
352
+
353
+ return $result
354
+}
355
+
356
+# obtains and increments a "sequence number" for this test run.
357
+proc getSeqNo {} {
358
+ upvar #0 seqNo seqNo
359
+ if {![info exists seqNo]} {
360
+ set seqNo 0
361
+ }
362
+ return [incr seqNo]
363
+}
364
+
365
+# fixup the whitespace in the result to make it easier to compare.
366
+proc normalize_result {} {
367
+ return [string map [list \r\n \n] [string trim $::RESULT]]
368
+}
369
+
370
+# returns the first line of the normalized result.
371
+proc first_data_line {} {
372
+ return [lindex [split [normalize_result] \n] 0]
373
+}
374
+
375
+# returns the second line of the normalized result.
376
+proc second_data_line {} {
377
+ return [lindex [split [normalize_result] \n] 1]
378
+}
379
+
380
+# returns the third line of the normalized result.
381
+proc third_data_line {} {
382
+ return [lindex [split [normalize_result] \n] 2]
383
+}
384
+
385
+# returns the last line of the normalized result.
386
+proc last_data_line {} {
387
+ return [lindex [split [normalize_result] \n] end]
388
+}
389
+
390
+# returns the second to last line of the normalized result.
391
+proc next_to_last_data_line {} {
392
+ return [lindex [split [normalize_result] \n] end-1]
393
+}
394
+
395
+# returns the third to last line of the normalized result.
396
+proc third_to_last_data_line {} {
397
+ return [lindex [split [normalize_result] \n] end-2]
398
+}
333399
334400
protInit $fossilexe
335401
foreach testfile $argv {
336402
set dir [file root [file tail $testfile]]
337403
file delete -force $dir
338404
339405
ADDED test/th1-docs-input.txt
340406
ADDED test/th1-docs.test
--- test/tester.tcl
+++ test/tester.tcl
@@ -328,10 +328,76 @@
328 }
329 append out \n$line
330 }
331 return [string range $out 1 end]
332 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
333
334 protInit $fossilexe
335 foreach testfile $argv {
336 set dir [file root [file tail $testfile]]
337 file delete -force $dir
338
339 DDED test/th1-docs-input.txt
340 DDED test/th1-docs.test
--- test/tester.tcl
+++ test/tester.tcl
@@ -328,10 +328,76 @@
328 }
329 append out \n$line
330 }
331 return [string range $out 1 end]
332 }
333
334 # Executes the "fossil http" command. The entire content of the HTTP request
335 # is read from the data file name, with [subst] being performed on it prior to
336 # submission. Temporary input and output files are created and deleted. The
337 # result will be the contents of the temoprary output file.
338 proc test_fossil_http { repository dataFileName url } {
339 set suffix [appendArgs [pid] - [getSeqNo] - [clock seconds] .txt]
340 set inFileName [file join $::tempPath [appendArgs test-http-in- $suffix]]
341 set outFileName [file join $::tempPath [appendArgs test-http-out- $suffix]]
342 set data [subst [read_file $dataFileName]]
343
344 write_file $inFileName $data
345 fossil http $inFileName $outFileName 127.0.0.1 $repository --localauth
346 set result [expr {[file exists $outFileName] ? [read_file $outFileName] : ""}]
347
348 if {1} then {
349 catch {file delete $inFileName}
350 catch {file delete $outFileName}
351 }
352
353 return $result
354 }
355
356 # obtains and increments a "sequence number" for this test run.
357 proc getSeqNo {} {
358 upvar #0 seqNo seqNo
359 if {![info exists seqNo]} {
360 set seqNo 0
361 }
362 return [incr seqNo]
363 }
364
365 # fixup the whitespace in the result to make it easier to compare.
366 proc normalize_result {} {
367 return [string map [list \r\n \n] [string trim $::RESULT]]
368 }
369
370 # returns the first line of the normalized result.
371 proc first_data_line {} {
372 return [lindex [split [normalize_result] \n] 0]
373 }
374
375 # returns the second line of the normalized result.
376 proc second_data_line {} {
377 return [lindex [split [normalize_result] \n] 1]
378 }
379
380 # returns the third line of the normalized result.
381 proc third_data_line {} {
382 return [lindex [split [normalize_result] \n] 2]
383 }
384
385 # returns the last line of the normalized result.
386 proc last_data_line {} {
387 return [lindex [split [normalize_result] \n] end]
388 }
389
390 # returns the second to last line of the normalized result.
391 proc next_to_last_data_line {} {
392 return [lindex [split [normalize_result] \n] end-1]
393 }
394
395 # returns the third to last line of the normalized result.
396 proc third_to_last_data_line {} {
397 return [lindex [split [normalize_result] \n] end-2]
398 }
399
400 protInit $fossilexe
401 foreach testfile $argv {
402 set dir [file root [file tail $testfile]]
403 file delete -force $dir
404
405 DDED test/th1-docs-input.txt
406 DDED test/th1-docs.test
--- a/test/th1-docs-input.txt
+++ b/test/th1-docs-input.txt
@@ -0,0 +1,4 @@
1
+GET ${url} HTTP/1.1
2
+Host: localhost
3
+User-Agent: Fossil
4
+
--- a/test/th1-docs-input.txt
+++ b/test/th1-docs-input.txt
@@ -0,0 +1,4 @@
 
 
 
 
--- a/test/th1-docs-input.txt
+++ b/test/th1-docs-input.txt
@@ -0,0 +1,4 @@
1 GET ${url} HTTP/1.1
2 Host: localhost
3 User-Agent: Fossil
4
--- a/test/th1-docs.test
+++ b/test/th1-docs.test
@@ -0,0 +1 @@
1
+thenthenthenset data [fossil info]
--- a/test/th1-docs.test
+++ b/test/th1-docs.test
@@ -0,0 +1 @@
 
--- a/test/th1-docs.test
+++ b/test/th1-docs.test
@@ -0,0 +1 @@
1 thenthenthenset data [fossil info]
--- test/th1-hooks.test
+++ test/th1-hooks.test
@@ -28,50 +28,10 @@
2828
2929
set env(TH1_ENABLE_HOOKS) 1; # TH1 hooks must be enabled for this test.
3030
3131
###############################################################################
3232
33
-proc fossil_th1_hook_http { repository url } {
34
- set suffix [appendArgs [pid] - [clock seconds] .txt]
35
- set inFileName [file join $::tempPath [appendArgs test-http-in- $suffix]]
36
- set outFileName [file join $::tempPath [appendArgs test-http-out- $suffix]]
37
- set data [subst [read_file [file join $::testdir th1-hooks-input.txt]]]
38
-
39
- write_file $inFileName $data
40
- fossil http $repository $inFileName $outFileName 127.0.0.1
41
- set result [expr {[file exists $outFileName] ? [read_file $outFileName] : ""}]
42
-
43
- if {1} then {
44
- catch {file delete $inFileName}
45
- catch {file delete $outFileName}
46
- }
47
-
48
- return $result
49
-}
50
-
51
-proc first_data_line {} {
52
- return [lindex [split [string trim $::RESULT] \r\n] 0]
53
-}
54
-
55
-proc second_data_line {} {
56
- return [lindex [split [string trim $::RESULT] \r\n] 1]
57
-}
58
-
59
-proc third_data_line {} {
60
- return [lindex [split [string trim $::RESULT] \r\n] 2]
61
-}
62
-
63
-proc last_data_line {} {
64
- return [lindex [split [string trim $::RESULT] \r\n] end]
65
-}
66
-
67
-proc next_to_last_data_line {} {
68
- return [lindex [split [string trim $::RESULT] \r\n] end-1]
69
-}
70
-
71
-###############################################################################
72
-
7333
set testTh1Setup {
7434
proc initialize_hook_log {} {
7535
if {![info exists ::hook_log]} {
7636
set ::hook_log ""
7737
}
@@ -103,13 +63,18 @@
10363
break "TH_BREAK return code"
10464
} elseif {$::cmd_name eq "test4"} {
10565
emit_hook_log
10666
return -code 2 "TH_RETURN return code"
10767
} elseif {$::cmd_name eq "timeline"} {
108
- if {$::cmd_args eq "custom"} {
68
+ set length [llength $::cmd_args]
69
+ set length [expr {$length - 1}]
70
+ if {[lindex $::cmd_args $length] eq "custom"} {
10971
emit_hook_log
11072
return "custom timeline"
73
+ } elseif {[lindex $::cmd_args $length] eq "now"} {
74
+ emit_hook_log
75
+ return "now timeline"
11176
} else {
11277
emit_hook_log
11378
error "unsupported timeline"
11479
}
11580
}
@@ -139,63 +104,89 @@
139104
regexp -line -- {^repository: (.*)$} $data dummy repository
140105
141106
if {[string length $repository] == 0 || ![file exists $repository]} then {
142107
error "unable to locate repository"
143108
}
109
+
110
+set dataFileName [file join $::testdir th1-hooks-input.txt]
144111
145112
###############################################################################
146113
147114
saveTh1SetupFile; writeTh1SetupFile $testTh1Setup
148115
149116
###############################################################################
150117
151118
fossil timeline custom; # NOTE: Bad "WHEN" argument.
152
-test th1-cmd-hooks-1a {[string map [list \r\n \n] [string trim $RESULT]] eq {<h1><b>command_hook timeline</b></h1>
153
-ERROR: unsupported timeline
119
+test th1-cmd-hooks-1a {[normalize_result] eq \
120
+{<h1><b>command_hook timeline</b></h1>
154121
+++ no more data (0) +++
155122
156123
<h1><b>command_hook timeline command_notify timeline</b></h1>}}
157124
158125
###############################################################################
159126
160127
fossil timeline
161
-test th1-cmd-hooks-2a {[first_data_line] eq {<h1><b>command_hook timeline</b></h1>}}
128
+test th1-cmd-hooks-2a {[first_data_line] eq \
129
+ {<h1><b>command_hook timeline</b></h1>}}
130
+
162131
test th1-cmd-hooks-2b {[second_data_line] eq {ERROR: unsupported timeline}}
163
-test th1-cmd-hooks-2c {[regexp -- {=== \d{4}-\d{2}-\d{2} ===} [third_data_line]]}
164
-test th1-cmd-hooks-2d {[last_data_line] eq {<h1><b>command_hook timeline command_notify timeline</b></h1>}}
132
+
133
+###############################################################################
134
+
135
+fossil timeline now
136
+test th1-cmd-hooks-3a {[first_data_line] eq \
137
+ {<h1><b>command_hook timeline</b></h1>}}
138
+
139
+test th1-cmd-hooks-3b \
140
+ {[regexp -- {=== \d{4}-\d{2}-\d{2} ===} [second_data_line]]}
141
+
142
+test th1-cmd-hooks-3c \
143
+ {[regexp -- {--- line limit \(\d+\) reached ---} [third_to_last_data_line]]}
144
+
145
+test th1-cmd-hooks-3d {[last_data_line] eq \
146
+ {<h1><b>command_hook timeline command_notify timeline</b></h1>}}
165147
166148
###############################################################################
167149
168150
fossil test1
169151
test th1-custom-cmd-1a {[next_to_last_data_line] eq $repository}
170
-test th1-custom-cmd-1b {[last_data_line] eq {<h1><b>command_hook test1 command_notify test1</b></h1>}}
152
+
153
+test th1-custom-cmd-1b {[last_data_line] eq \
154
+ {<h1><b>command_hook test1 command_notify test1</b></h1>}}
171155
172156
###############################################################################
173157
174158
fossil test2
175159
test th1-custom-cmd-2a {[first_data_line] eq {ERROR: unsupported command}}
176160
177161
###############################################################################
178162
179163
fossil test3
180
-test th1-custom-cmd-3a {[string trim $RESULT] eq {<h1><b>command_hook test3</b></h1>}}
164
+test th1-custom-cmd-3a {[string trim $RESULT] eq \
165
+ {<h1><b>command_hook test3</b></h1>}}
181166
182167
###############################################################################
183168
184169
fossil test4
185
-test th1-custom-cmd-4a {[string trim $RESULT] eq {<h1><b>command_hook test4</b></h1>}}
170
+test th1-custom-cmd-4a {[string trim $RESULT] eq \
171
+ {<h1><b>command_hook test4</b></h1>}}
186172
187173
###############################################################################
188174
189
-set RESULT [fossil_th1_hook_http $repository /timeline]
175
+set RESULT [test_fossil_http $repository $dataFileName /timeline]
190176
test th1-web-hooks-1a {[regexp {<title>Fossil: Timeline</title>} $RESULT]}
191
-test th1-web-hooks-1b {[regexp {<h1><b>command_hook http webpage_hook timeline webpage_notify timeline</b></h1>} $RESULT]}
177
+
178
+test th1-web-hooks-1b {[regexp [appendArgs \
179
+ {<h1><b>command_hook http webpage_hook timeline} " " \
180
+ {webpage_notify timeline</b></h1>}] $RESULT]}
192181
193182
###############################################################################
194183
195
-set RESULT [fossil_th1_hook_http $repository /test1]
184
+set RESULT [test_fossil_http $repository $dataFileName /test1]
196185
test th1-custom-web-1a {[next_to_last_data_line] eq $repository}
197
-test th1-custom-web-1b {[last_data_line] eq {<h1><b>command_hook http webpage_hook test1 webpage_notify test1</b></h1>}}
186
+
187
+test th1-custom-web-1b {[last_data_line] eq \
188
+ {<h1><b>command_hook http webpage_hook test1 webpage_notify test1</b></h1>}}
198189
199190
###############################################################################
200191
201192
restoreTh1SetupFile
202193
--- test/th1-hooks.test
+++ test/th1-hooks.test
@@ -28,50 +28,10 @@
28
29 set env(TH1_ENABLE_HOOKS) 1; # TH1 hooks must be enabled for this test.
30
31 ###############################################################################
32
33 proc fossil_th1_hook_http { repository url } {
34 set suffix [appendArgs [pid] - [clock seconds] .txt]
35 set inFileName [file join $::tempPath [appendArgs test-http-in- $suffix]]
36 set outFileName [file join $::tempPath [appendArgs test-http-out- $suffix]]
37 set data [subst [read_file [file join $::testdir th1-hooks-input.txt]]]
38
39 write_file $inFileName $data
40 fossil http $repository $inFileName $outFileName 127.0.0.1
41 set result [expr {[file exists $outFileName] ? [read_file $outFileName] : ""}]
42
43 if {1} then {
44 catch {file delete $inFileName}
45 catch {file delete $outFileName}
46 }
47
48 return $result
49 }
50
51 proc first_data_line {} {
52 return [lindex [split [string trim $::RESULT] \r\n] 0]
53 }
54
55 proc second_data_line {} {
56 return [lindex [split [string trim $::RESULT] \r\n] 1]
57 }
58
59 proc third_data_line {} {
60 return [lindex [split [string trim $::RESULT] \r\n] 2]
61 }
62
63 proc last_data_line {} {
64 return [lindex [split [string trim $::RESULT] \r\n] end]
65 }
66
67 proc next_to_last_data_line {} {
68 return [lindex [split [string trim $::RESULT] \r\n] end-1]
69 }
70
71 ###############################################################################
72
73 set testTh1Setup {
74 proc initialize_hook_log {} {
75 if {![info exists ::hook_log]} {
76 set ::hook_log ""
77 }
@@ -103,13 +63,18 @@
103 break "TH_BREAK return code"
104 } elseif {$::cmd_name eq "test4"} {
105 emit_hook_log
106 return -code 2 "TH_RETURN return code"
107 } elseif {$::cmd_name eq "timeline"} {
108 if {$::cmd_args eq "custom"} {
 
 
109 emit_hook_log
110 return "custom timeline"
 
 
 
111 } else {
112 emit_hook_log
113 error "unsupported timeline"
114 }
115 }
@@ -139,63 +104,89 @@
139 regexp -line -- {^repository: (.*)$} $data dummy repository
140
141 if {[string length $repository] == 0 || ![file exists $repository]} then {
142 error "unable to locate repository"
143 }
 
 
144
145 ###############################################################################
146
147 saveTh1SetupFile; writeTh1SetupFile $testTh1Setup
148
149 ###############################################################################
150
151 fossil timeline custom; # NOTE: Bad "WHEN" argument.
152 test th1-cmd-hooks-1a {[string map [list \r\n \n] [string trim $RESULT]] eq {<h1><b>command_hook timeline</b></h1>
153 ERROR: unsupported timeline
154 +++ no more data (0) +++
155
156 <h1><b>command_hook timeline command_notify timeline</b></h1>}}
157
158 ###############################################################################
159
160 fossil timeline
161 test th1-cmd-hooks-2a {[first_data_line] eq {<h1><b>command_hook timeline</b></h1>}}
 
 
162 test th1-cmd-hooks-2b {[second_data_line] eq {ERROR: unsupported timeline}}
163 test th1-cmd-hooks-2c {[regexp -- {=== \d{4}-\d{2}-\d{2} ===} [third_data_line]]}
164 test th1-cmd-hooks-2d {[last_data_line] eq {<h1><b>command_hook timeline command_notify timeline</b></h1>}}
 
 
 
 
 
 
 
 
 
 
 
 
 
165
166 ###############################################################################
167
168 fossil test1
169 test th1-custom-cmd-1a {[next_to_last_data_line] eq $repository}
170 test th1-custom-cmd-1b {[last_data_line] eq {<h1><b>command_hook test1 command_notify test1</b></h1>}}
 
 
171
172 ###############################################################################
173
174 fossil test2
175 test th1-custom-cmd-2a {[first_data_line] eq {ERROR: unsupported command}}
176
177 ###############################################################################
178
179 fossil test3
180 test th1-custom-cmd-3a {[string trim $RESULT] eq {<h1><b>command_hook test3</b></h1>}}
 
181
182 ###############################################################################
183
184 fossil test4
185 test th1-custom-cmd-4a {[string trim $RESULT] eq {<h1><b>command_hook test4</b></h1>}}
 
186
187 ###############################################################################
188
189 set RESULT [fossil_th1_hook_http $repository /timeline]
190 test th1-web-hooks-1a {[regexp {<title>Fossil: Timeline</title>} $RESULT]}
191 test th1-web-hooks-1b {[regexp {<h1><b>command_hook http webpage_hook timeline webpage_notify timeline</b></h1>} $RESULT]}
 
 
 
192
193 ###############################################################################
194
195 set RESULT [fossil_th1_hook_http $repository /test1]
196 test th1-custom-web-1a {[next_to_last_data_line] eq $repository}
197 test th1-custom-web-1b {[last_data_line] eq {<h1><b>command_hook http webpage_hook test1 webpage_notify test1</b></h1>}}
 
 
198
199 ###############################################################################
200
201 restoreTh1SetupFile
202
--- test/th1-hooks.test
+++ test/th1-hooks.test
@@ -28,50 +28,10 @@
28
29 set env(TH1_ENABLE_HOOKS) 1; # TH1 hooks must be enabled for this test.
30
31 ###############################################################################
32
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33 set testTh1Setup {
34 proc initialize_hook_log {} {
35 if {![info exists ::hook_log]} {
36 set ::hook_log ""
37 }
@@ -103,13 +63,18 @@
63 break "TH_BREAK return code"
64 } elseif {$::cmd_name eq "test4"} {
65 emit_hook_log
66 return -code 2 "TH_RETURN return code"
67 } elseif {$::cmd_name eq "timeline"} {
68 set length [llength $::cmd_args]
69 set length [expr {$length - 1}]
70 if {[lindex $::cmd_args $length] eq "custom"} {
71 emit_hook_log
72 return "custom timeline"
73 } elseif {[lindex $::cmd_args $length] eq "now"} {
74 emit_hook_log
75 return "now timeline"
76 } else {
77 emit_hook_log
78 error "unsupported timeline"
79 }
80 }
@@ -139,63 +104,89 @@
104 regexp -line -- {^repository: (.*)$} $data dummy repository
105
106 if {[string length $repository] == 0 || ![file exists $repository]} then {
107 error "unable to locate repository"
108 }
109
110 set dataFileName [file join $::testdir th1-hooks-input.txt]
111
112 ###############################################################################
113
114 saveTh1SetupFile; writeTh1SetupFile $testTh1Setup
115
116 ###############################################################################
117
118 fossil timeline custom; # NOTE: Bad "WHEN" argument.
119 test th1-cmd-hooks-1a {[normalize_result] eq \
120 {<h1><b>command_hook timeline</b></h1>
121 +++ no more data (0) +++
122
123 <h1><b>command_hook timeline command_notify timeline</b></h1>}}
124
125 ###############################################################################
126
127 fossil timeline
128 test th1-cmd-hooks-2a {[first_data_line] eq \
129 {<h1><b>command_hook timeline</b></h1>}}
130
131 test th1-cmd-hooks-2b {[second_data_line] eq {ERROR: unsupported timeline}}
132
133 ###############################################################################
134
135 fossil timeline now
136 test th1-cmd-hooks-3a {[first_data_line] eq \
137 {<h1><b>command_hook timeline</b></h1>}}
138
139 test th1-cmd-hooks-3b \
140 {[regexp -- {=== \d{4}-\d{2}-\d{2} ===} [second_data_line]]}
141
142 test th1-cmd-hooks-3c \
143 {[regexp -- {--- line limit \(\d+\) reached ---} [third_to_last_data_line]]}
144
145 test th1-cmd-hooks-3d {[last_data_line] eq \
146 {<h1><b>command_hook timeline command_notify timeline</b></h1>}}
147
148 ###############################################################################
149
150 fossil test1
151 test th1-custom-cmd-1a {[next_to_last_data_line] eq $repository}
152
153 test th1-custom-cmd-1b {[last_data_line] eq \
154 {<h1><b>command_hook test1 command_notify test1</b></h1>}}
155
156 ###############################################################################
157
158 fossil test2
159 test th1-custom-cmd-2a {[first_data_line] eq {ERROR: unsupported command}}
160
161 ###############################################################################
162
163 fossil test3
164 test th1-custom-cmd-3a {[string trim $RESULT] eq \
165 {<h1><b>command_hook test3</b></h1>}}
166
167 ###############################################################################
168
169 fossil test4
170 test th1-custom-cmd-4a {[string trim $RESULT] eq \
171 {<h1><b>command_hook test4</b></h1>}}
172
173 ###############################################################################
174
175 set RESULT [test_fossil_http $repository $dataFileName /timeline]
176 test th1-web-hooks-1a {[regexp {<title>Fossil: Timeline</title>} $RESULT]}
177
178 test th1-web-hooks-1b {[regexp [appendArgs \
179 {<h1><b>command_hook http webpage_hook timeline} " " \
180 {webpage_notify timeline</b></h1>}] $RESULT]}
181
182 ###############################################################################
183
184 set RESULT [test_fossil_http $repository $dataFileName /test1]
185 test th1-custom-web-1a {[next_to_last_data_line] eq $repository}
186
187 test th1-custom-web-1b {[last_data_line] eq \
188 {<h1><b>command_hook http webpage_hook test1 webpage_notify test1</b></h1>}}
189
190 ###############################################################################
191
192 restoreTh1SetupFile
193
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -150,11 +150,11 @@
150150
#### The directories where the OpenSSL include and library files are located.
151151
# The recommended usage here is to use the Sysinternals junction tool
152152
# to create a hard link between an "openssl-1.x" sub-directory of the
153153
# Fossil source code directory and the target OpenSSL source directory.
154154
#
155
-OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2
155
+OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2a
156156
OPENSSLINCDIR = $(OPENSSLDIR)/include
157157
OPENSSLLIBDIR = $(OPENSSLDIR)
158158
159159
#### Either the directory where the Tcl library is installed or the Tcl
160160
# source code directory resides (depending on the value of the macro
161161
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -150,11 +150,11 @@
150 #### The directories where the OpenSSL include and library files are located.
151 # The recommended usage here is to use the Sysinternals junction tool
152 # to create a hard link between an "openssl-1.x" sub-directory of the
153 # Fossil source code directory and the target OpenSSL source directory.
154 #
155 OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2
156 OPENSSLINCDIR = $(OPENSSLDIR)/include
157 OPENSSLLIBDIR = $(OPENSSLDIR)
158
159 #### Either the directory where the Tcl library is installed or the Tcl
160 # source code directory resides (depending on the value of the macro
161
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -150,11 +150,11 @@
150 #### The directories where the OpenSSL include and library files are located.
151 # The recommended usage here is to use the Sysinternals junction tool
152 # to create a hard link between an "openssl-1.x" sub-directory of the
153 # Fossil source code directory and the target OpenSSL source directory.
154 #
155 OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2a
156 OPENSSLINCDIR = $(OPENSSLDIR)/include
157 OPENSSLLIBDIR = $(OPENSSLDIR)
158
159 #### Either the directory where the Tcl library is installed or the Tcl
160 # source code directory resides (depending on the value of the macro
161
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -150,11 +150,11 @@
150150
#### The directories where the OpenSSL include and library files are located.
151151
# The recommended usage here is to use the Sysinternals junction tool
152152
# to create a hard link between an "openssl-1.x" sub-directory of the
153153
# Fossil source code directory and the target OpenSSL source directory.
154154
#
155
-OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2
155
+OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2a
156156
OPENSSLINCDIR = $(OPENSSLDIR)/include
157157
OPENSSLLIBDIR = $(OPENSSLDIR)
158158
159159
#### Either the directory where the Tcl library is installed or the Tcl
160160
# source code directory resides (depending on the value of the macro
161161
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -150,11 +150,11 @@
150 #### The directories where the OpenSSL include and library files are located.
151 # The recommended usage here is to use the Sysinternals junction tool
152 # to create a hard link between an "openssl-1.x" sub-directory of the
153 # Fossil source code directory and the target OpenSSL source directory.
154 #
155 OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2
156 OPENSSLINCDIR = $(OPENSSLDIR)/include
157 OPENSSLLIBDIR = $(OPENSSLDIR)
158
159 #### Either the directory where the Tcl library is installed or the Tcl
160 # source code directory resides (depending on the value of the macro
161
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -150,11 +150,11 @@
150 #### The directories where the OpenSSL include and library files are located.
151 # The recommended usage here is to use the Sysinternals junction tool
152 # to create a hard link between an "openssl-1.x" sub-directory of the
153 # Fossil source code directory and the target OpenSSL source directory.
154 #
155 OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2a
156 OPENSSLINCDIR = $(OPENSSLDIR)/include
157 OPENSSLLIBDIR = $(OPENSSLDIR)
158
159 #### Either the directory where the Tcl library is installed or the Tcl
160 # source code directory resides (depending on the value of the macro
161
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -59,11 +59,11 @@
5959
#
6060
FOSSIL_ENABLE_LEGACY_MV_RM = 1
6161
6262
#### Enable TH1 scripts in embedded documentation files
6363
#
64
-# FOSSIL_ENABLE_TH1_DOCS = 1
64
+FOSSIL_ENABLE_TH1_DOCS = 1
6565
6666
#### Enable hooks for commands and web pages via TH1
6767
#
6868
FOSSIL_ENABLE_TH1_HOOKS = 1
6969
@@ -150,11 +150,11 @@
150150
#### The directories where the OpenSSL include and library files are located.
151151
# The recommended usage here is to use the Sysinternals junction tool
152152
# to create a hard link between an "openssl-1.x" sub-directory of the
153153
# Fossil source code directory and the target OpenSSL source directory.
154154
#
155
-OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2
155
+OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2a
156156
OPENSSLINCDIR = $(OPENSSLDIR)/include
157157
OPENSSLLIBDIR = $(OPENSSLDIR)
158158
159159
#### Either the directory where the Tcl library is installed or the Tcl
160160
# source code directory resides (depending on the value of the macro
161161
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -59,11 +59,11 @@
59 #
60 FOSSIL_ENABLE_LEGACY_MV_RM = 1
61
62 #### Enable TH1 scripts in embedded documentation files
63 #
64 # FOSSIL_ENABLE_TH1_DOCS = 1
65
66 #### Enable hooks for commands and web pages via TH1
67 #
68 FOSSIL_ENABLE_TH1_HOOKS = 1
69
@@ -150,11 +150,11 @@
150 #### The directories where the OpenSSL include and library files are located.
151 # The recommended usage here is to use the Sysinternals junction tool
152 # to create a hard link between an "openssl-1.x" sub-directory of the
153 # Fossil source code directory and the target OpenSSL source directory.
154 #
155 OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2
156 OPENSSLINCDIR = $(OPENSSLDIR)/include
157 OPENSSLLIBDIR = $(OPENSSLDIR)
158
159 #### Either the directory where the Tcl library is installed or the Tcl
160 # source code directory resides (depending on the value of the macro
161
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -59,11 +59,11 @@
59 #
60 FOSSIL_ENABLE_LEGACY_MV_RM = 1
61
62 #### Enable TH1 scripts in embedded documentation files
63 #
64 FOSSIL_ENABLE_TH1_DOCS = 1
65
66 #### Enable hooks for commands and web pages via TH1
67 #
68 FOSSIL_ENABLE_TH1_HOOKS = 1
69
@@ -150,11 +150,11 @@
150 #### The directories where the OpenSSL include and library files are located.
151 # The recommended usage here is to use the Sysinternals junction tool
152 # to create a hard link between an "openssl-1.x" sub-directory of the
153 # Fossil source code directory and the target OpenSSL source directory.
154 #
155 OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2a
156 OPENSSLINCDIR = $(OPENSSLDIR)/include
157 OPENSSLLIBDIR = $(OPENSSLDIR)
158
159 #### Either the directory where the Tcl library is installed or the Tcl
160 # source code directory resides (depending on the value of the macro
161
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -59,11 +59,11 @@
5959
#
6060
FOSSIL_ENABLE_LEGACY_MV_RM = 1
6161
6262
#### Enable TH1 scripts in embedded documentation files
6363
#
64
-# FOSSIL_ENABLE_TH1_DOCS = 1
64
+FOSSIL_ENABLE_TH1_DOCS = 1
6565
6666
#### Enable hooks for commands and web pages via TH1
6767
#
6868
FOSSIL_ENABLE_TH1_HOOKS = 1
6969
@@ -150,11 +150,11 @@
150150
#### The directories where the OpenSSL include and library files are located.
151151
# The recommended usage here is to use the Sysinternals junction tool
152152
# to create a hard link between an "openssl-1.x" sub-directory of the
153153
# Fossil source code directory and the target OpenSSL source directory.
154154
#
155
-OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2
155
+OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2a
156156
OPENSSLINCDIR = $(OPENSSLDIR)/include
157157
OPENSSLLIBDIR = $(OPENSSLDIR)
158158
159159
#### Either the directory where the Tcl library is installed or the Tcl
160160
# source code directory resides (depending on the value of the macro
161161
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -59,11 +59,11 @@
59 #
60 FOSSIL_ENABLE_LEGACY_MV_RM = 1
61
62 #### Enable TH1 scripts in embedded documentation files
63 #
64 # FOSSIL_ENABLE_TH1_DOCS = 1
65
66 #### Enable hooks for commands and web pages via TH1
67 #
68 FOSSIL_ENABLE_TH1_HOOKS = 1
69
@@ -150,11 +150,11 @@
150 #### The directories where the OpenSSL include and library files are located.
151 # The recommended usage here is to use the Sysinternals junction tool
152 # to create a hard link between an "openssl-1.x" sub-directory of the
153 # Fossil source code directory and the target OpenSSL source directory.
154 #
155 OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2
156 OPENSSLINCDIR = $(OPENSSLDIR)/include
157 OPENSSLLIBDIR = $(OPENSSLDIR)
158
159 #### Either the directory where the Tcl library is installed or the Tcl
160 # source code directory resides (depending on the value of the macro
161
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -59,11 +59,11 @@
59 #
60 FOSSIL_ENABLE_LEGACY_MV_RM = 1
61
62 #### Enable TH1 scripts in embedded documentation files
63 #
64 FOSSIL_ENABLE_TH1_DOCS = 1
65
66 #### Enable hooks for commands and web pages via TH1
67 #
68 FOSSIL_ENABLE_TH1_HOOKS = 1
69
@@ -150,11 +150,11 @@
150 #### The directories where the OpenSSL include and library files are located.
151 # The recommended usage here is to use the Sysinternals junction tool
152 # to create a hard link between an "openssl-1.x" sub-directory of the
153 # Fossil source code directory and the target OpenSSL source directory.
154 #
155 OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2a
156 OPENSSLINCDIR = $(OPENSSLDIR)/include
157 OPENSSLLIBDIR = $(OPENSSLDIR)
158
159 #### Either the directory where the Tcl library is installed or the Tcl
160 # source code directory resides (depending on the value of the macro
161
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -58,11 +58,11 @@
5858
5959
# Uncomment to enable Tcl support
6060
# FOSSIL_ENABLE_TCL = 1
6161
6262
!ifdef FOSSIL_ENABLE_SSL
63
-SSLDIR = $(B)\compat\openssl-1.0.2
63
+SSLDIR = $(B)\compat\openssl-1.0.2a
6464
SSLINCDIR = $(SSLDIR)\inc32
6565
SSLLIBDIR = $(SSLDIR)\out32
6666
SSLLFLAGS = /nologo /opt:ref /debug
6767
SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
6868
!if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64"
6969
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -58,11 +58,11 @@
58
59 # Uncomment to enable Tcl support
60 # FOSSIL_ENABLE_TCL = 1
61
62 !ifdef FOSSIL_ENABLE_SSL
63 SSLDIR = $(B)\compat\openssl-1.0.2
64 SSLINCDIR = $(SSLDIR)\inc32
65 SSLLIBDIR = $(SSLDIR)\out32
66 SSLLFLAGS = /nologo /opt:ref /debug
67 SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
68 !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64"
69
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -58,11 +58,11 @@
58
59 # Uncomment to enable Tcl support
60 # FOSSIL_ENABLE_TCL = 1
61
62 !ifdef FOSSIL_ENABLE_SSL
63 SSLDIR = $(B)\compat\openssl-1.0.2a
64 SSLINCDIR = $(SSLDIR)\inc32
65 SSLLIBDIR = $(SSLDIR)\out32
66 SSLLFLAGS = /nologo /opt:ref /debug
67 SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
68 !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64"
69
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -58,11 +58,11 @@
5858
5959
# Uncomment to enable Tcl support
6060
# FOSSIL_ENABLE_TCL = 1
6161
6262
!ifdef FOSSIL_ENABLE_SSL
63
-SSLDIR = $(B)\compat\openssl-1.0.2
63
+SSLDIR = $(B)\compat\openssl-1.0.2a
6464
SSLINCDIR = $(SSLDIR)\inc32
6565
SSLLIBDIR = $(SSLDIR)\out32
6666
SSLLFLAGS = /nologo /opt:ref /debug
6767
SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
6868
!if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64"
6969
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -58,11 +58,11 @@
58
59 # Uncomment to enable Tcl support
60 # FOSSIL_ENABLE_TCL = 1
61
62 !ifdef FOSSIL_ENABLE_SSL
63 SSLDIR = $(B)\compat\openssl-1.0.2
64 SSLINCDIR = $(SSLDIR)\inc32
65 SSLLIBDIR = $(SSLDIR)\out32
66 SSLLFLAGS = /nologo /opt:ref /debug
67 SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
68 !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64"
69
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -58,11 +58,11 @@
58
59 # Uncomment to enable Tcl support
60 # FOSSIL_ENABLE_TCL = 1
61
62 !ifdef FOSSIL_ENABLE_SSL
63 SSLDIR = $(B)\compat\openssl-1.0.2a
64 SSLINCDIR = $(SSLDIR)\inc32
65 SSLLIBDIR = $(SSLDIR)\out32
66 SSLLFLAGS = /nologo /opt:ref /debug
67 SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib
68 !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64"
69
+1 -1
--- www/build.wiki
+++ www/build.wiki
@@ -125,11 +125,11 @@
125125
the optional <a href="https://www.openssl.org/">OpenSSL</a> support,
126126
first <a href="https://www.openssl.org/source/">download the official
127127
source code for OpenSSL</a> and extract it to an appropriately named
128128
"<b>openssl-X.Y.ZA</b>" subdirectory within the local
129129
[/tree?ci=trunk&name=compat | compat] directory (e.g.
130
-"<b>compat/openssl-1.0.2</b>"), then make sure that some recent
130
+"<b>compat/openssl-1.0.2a</b>"), then make sure that some recent
131131
<a href="http://www.perl.org/">Perl</a> binaries are installed locally,
132132
and finally run one of the following commands:
133133
<blockquote><pre>
134134
nmake /f Makefile.msc FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin
135135
</pre></blockquote>
136136
--- www/build.wiki
+++ www/build.wiki
@@ -125,11 +125,11 @@
125 the optional <a href="https://www.openssl.org/">OpenSSL</a> support,
126 first <a href="https://www.openssl.org/source/">download the official
127 source code for OpenSSL</a> and extract it to an appropriately named
128 "<b>openssl-X.Y.ZA</b>" subdirectory within the local
129 [/tree?ci=trunk&name=compat | compat] directory (e.g.
130 "<b>compat/openssl-1.0.2</b>"), then make sure that some recent
131 <a href="http://www.perl.org/">Perl</a> binaries are installed locally,
132 and finally run one of the following commands:
133 <blockquote><pre>
134 nmake /f Makefile.msc FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin
135 </pre></blockquote>
136
--- www/build.wiki
+++ www/build.wiki
@@ -125,11 +125,11 @@
125 the optional <a href="https://www.openssl.org/">OpenSSL</a> support,
126 first <a href="https://www.openssl.org/source/">download the official
127 source code for OpenSSL</a> and extract it to an appropriately named
128 "<b>openssl-X.Y.ZA</b>" subdirectory within the local
129 [/tree?ci=trunk&name=compat | compat] directory (e.g.
130 "<b>compat/openssl-1.0.2a</b>"), then make sure that some recent
131 <a href="http://www.perl.org/">Perl</a> binaries are installed locally,
132 and finally run one of the following commands:
133 <blockquote><pre>
134 nmake /f Makefile.msc FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin
135 </pre></blockquote>
136
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,7 +1,11 @@
11
<title>Change Log</title>
22
3
+<h2>Changes for Version 1.33 (not released yet)</h2>
4
+ * Add [/help?cmd=import|fossil import --svn], for importing a subversion
5
+ repository into fossil which was exported using "svnadmin dump".
6
+
37
<h2>Changes for Version 1.32 (2015-03-14)</h2>
48
* When creating a new repository using [/help?cmd=init|fossil init], ensure
59
that the new repository is fully compatible with historical versions of
610
Fossil by having a valid manifest as RID 1.
711
* Anti-aliased rendering of arrowheads on timeline graphs.
812
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,7 +1,11 @@
1 <title>Change Log</title>
2
 
 
 
 
3 <h2>Changes for Version 1.32 (2015-03-14)</h2>
4 * When creating a new repository using [/help?cmd=init|fossil init], ensure
5 that the new repository is fully compatible with historical versions of
6 Fossil by having a valid manifest as RID 1.
7 * Anti-aliased rendering of arrowheads on timeline graphs.
8
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,7 +1,11 @@
1 <title>Change Log</title>
2
3 <h2>Changes for Version 1.33 (not released yet)</h2>
4 * Add [/help?cmd=import|fossil import --svn], for importing a subversion
5 repository into fossil which was exported using "svnadmin dump".
6
7 <h2>Changes for Version 1.32 (2015-03-14)</h2>
8 * When creating a new repository using [/help?cmd=init|fossil init], ensure
9 that the new repository is fully compatible with historical versions of
10 Fossil by having a valid manifest as RID 1.
11 * Anti-aliased rendering of arrowheads on timeline graphs.
12
+4 -5
--- www/sync.wiki
+++ www/sync.wiki
@@ -247,13 +247,11 @@
247247
<b>push</b> <i>servercode projectcode</i><br>
248248
<b>pull</b> <i>servercode projectcode</i>
249249
</blockquote>
250250
251251
<p>The <i>servercode</i> argument is the repository ID for the
252
-client. The server will only allow the transaction to proceed
253
-if the servercode is different from its own servercode. This
254
-prevents a sync-loop. The <i>projectcode</i> is the identifier
252
+client. The <i>projectcode</i> is the identifier
255253
of the software project that the client repository contains.
256254
The projectcode for the client and server must match in order
257255
for the transaction to proceed.</p>
258256
259257
<p>The server will also send a push card back to the client
@@ -384,11 +382,11 @@
384382
385383
<blockquote>
386384
<b>reqconfig</b> <i>configuration-name</i>
387385
</blockquote>
388386
389
-<p>As of [/timeline?r=trunk&c=2015-01-24+00%3A17%3A55&n=20|2015-01-24], the configuration-name must be one of the
387
+<p>As of [/timeline?r=trunk&c=2015-03-19+03%3A57%3A46&n=20|2015-03-19], the configuration-name must be one of the
390388
following values:
391389
392390
<center><table border=0>
393391
<tr><td valign="top">
394392
<ul>
@@ -420,16 +418,17 @@
420418
<li> keep-glob
421419
<li> crnl-glob
422420
<li> encoding-glob
423421
<li> empty-dirs
424422
<li> allow-symlinks
423
+<li> dotfiles
425424
<li> ticket-table
426425
<li> ticket-common
427426
<li> ticket-change
428427
<li> ticket-newpage
429
-<li> ticket-viewpage
430428
<ul></td><td valign="top"><ul>
429
+<li> ticket-viewpage
431430
<li> ticket-editpage
432431
<li> ticket-reportlist
433432
<li> ticket-report-template
434433
<li> ticket-key-template
435434
<li> ticket-title-expr
436435
--- www/sync.wiki
+++ www/sync.wiki
@@ -247,13 +247,11 @@
247 <b>push</b> <i>servercode projectcode</i><br>
248 <b>pull</b> <i>servercode projectcode</i>
249 </blockquote>
250
251 <p>The <i>servercode</i> argument is the repository ID for the
252 client. The server will only allow the transaction to proceed
253 if the servercode is different from its own servercode. This
254 prevents a sync-loop. The <i>projectcode</i> is the identifier
255 of the software project that the client repository contains.
256 The projectcode for the client and server must match in order
257 for the transaction to proceed.</p>
258
259 <p>The server will also send a push card back to the client
@@ -384,11 +382,11 @@
384
385 <blockquote>
386 <b>reqconfig</b> <i>configuration-name</i>
387 </blockquote>
388
389 <p>As of [/timeline?r=trunk&c=2015-01-24+00%3A17%3A55&n=20|2015-01-24], the configuration-name must be one of the
390 following values:
391
392 <center><table border=0>
393 <tr><td valign="top">
394 <ul>
@@ -420,16 +418,17 @@
420 <li> keep-glob
421 <li> crnl-glob
422 <li> encoding-glob
423 <li> empty-dirs
424 <li> allow-symlinks
 
425 <li> ticket-table
426 <li> ticket-common
427 <li> ticket-change
428 <li> ticket-newpage
429 <li> ticket-viewpage
430 <ul></td><td valign="top"><ul>
 
431 <li> ticket-editpage
432 <li> ticket-reportlist
433 <li> ticket-report-template
434 <li> ticket-key-template
435 <li> ticket-title-expr
436
--- www/sync.wiki
+++ www/sync.wiki
@@ -247,13 +247,11 @@
247 <b>push</b> <i>servercode projectcode</i><br>
248 <b>pull</b> <i>servercode projectcode</i>
249 </blockquote>
250
251 <p>The <i>servercode</i> argument is the repository ID for the
252 client. The <i>projectcode</i> is the identifier
 
 
253 of the software project that the client repository contains.
254 The projectcode for the client and server must match in order
255 for the transaction to proceed.</p>
256
257 <p>The server will also send a push card back to the client
@@ -384,11 +382,11 @@
382
383 <blockquote>
384 <b>reqconfig</b> <i>configuration-name</i>
385 </blockquote>
386
387 <p>As of [/timeline?r=trunk&c=2015-03-19+03%3A57%3A46&n=20|2015-03-19], the configuration-name must be one of the
388 following values:
389
390 <center><table border=0>
391 <tr><td valign="top">
392 <ul>
@@ -420,16 +418,17 @@
418 <li> keep-glob
419 <li> crnl-glob
420 <li> encoding-glob
421 <li> empty-dirs
422 <li> allow-symlinks
423 <li> dotfiles
424 <li> ticket-table
425 <li> ticket-common
426 <li> ticket-change
427 <li> ticket-newpage
 
428 <ul></td><td valign="top"><ul>
429 <li> ticket-viewpage
430 <li> ticket-editpage
431 <li> ticket-reportlist
432 <li> ticket-report-template
433 <li> ticket-key-template
434 <li> ticket-title-expr
435

Keyboard Shortcuts

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