Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Merge from trunk |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | wcontent-subsets |
| Files: | files | file ages | folders |
| SHA3-256: |
5c0515e20cc464b8362658c0258b75a4 |
| User & Date: | george 2022-01-21 20:13:07.087 |
Context
|
2022-02-10
| ||
| 00:17 | Merge from trunk check-in: 88ff4e5dea user: george tags: wcontent-subsets | |
|
2022-01-21
| ||
| 20:13 | Merge from trunk check-in: 5c0515e20c user: george tags: wcontent-subsets | |
| 11:38 | Fix the previous check-in to list environment variables used by the CGI Server Extensions feature in the correct place. check-in: 6eeb7ec10e user: florian tags: trunk | |
|
2021-10-09
| ||
| 19:50 | Merge in trunk (release 2.17) check-in: 315351f4ac user: george tags: wcontent-subsets | |
Changes
Changes to BUILD.txt.
| ︙ | ︙ | |||
53 54 55 56 57 58 59 | * The configure script (if used) examines the options given and runs various tests with the C compiler to create Makefile from the Makefile.in template as well as autoconfig.h * The Makefile just sets up a few macros and then invokes the real makefile in src/main.mk. The src/main.mk makefile is | | | | | | | | | 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | * The configure script (if used) examines the options given and runs various tests with the C compiler to create Makefile from the Makefile.in template as well as autoconfig.h * The Makefile just sets up a few macros and then invokes the real makefile in src/main.mk. The src/main.mk makefile is automatically generated by a TCL script found at tools/makemake.tcl. Do not edit src/main.mk directly. Update tools/makemake.tcl and then rerun it. * The *.h header files are automatically generated using a program called "makeheaders". Source code to the makeheaders program is found in tools/makeheaders.c. Documentation is found in tools/makeheaders.html. * Most *.c source files are preprocessed using a program called "translate". The sources to translate are found in tools/translate.c. A header comment in tools/translate.c explains in detail what it does. * The tools/mkindex.c program generates some C code that implements static lookup tables. See the header comment in the source code for details on what it does. Additional information on the build process is available from http://fossil-scm.org/home/doc/trunk/www/makefile.wiki |
Changes to Makefile.classic.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #!/usr/bin/make # # This is the top-level makefile for Fossil when the build is occurring # on a unix platform. This works out-of-the-box on most unix platforms. # But you are free to vary some of the definitions if desired. # #### The toplevel directory of the source tree. Fossil can be built # in a directory that is separate from the source tree. Just change # the following to point from the build directory to the src/ folder. # SRCDIR = ./src #### The directory into which object code files should be written. # # OBJDIR = ./bld #### C Compiler and options for use in building executables that | > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #!/usr/bin/make # # This is the top-level makefile for Fossil when the build is occurring # on a unix platform. This works out-of-the-box on most unix platforms. # But you are free to vary some of the definitions if desired. # #### The toplevel directory of the source tree. Fossil can be built # in a directory that is separate from the source tree. Just change # the following to point from the build directory to the src/ folder. # SRCDIR = ./src #### Upstream source files included directly in this repository. # SRCDIR_extsrc = ./extsrc #### In-tree tools such as code generators and translators: # SRCDIR_tools = ./tools #### The directory into which object code files should be written. # # OBJDIR = ./bld #### C Compiler and options for use in building executables that |
| ︙ | ︙ | |||
34 35 36 37 38 39 40 | # the finished binary for fossil. The BCC compiler above is used # for building intermediate code-generator tools. # #TCC = gcc -O6 #TCC = gcc -g -O0 -Wall -fprofile-arcs -ftest-coverage TCC = gcc -g -Os -Wall | < < < < | < | < | < | > > > > > > > > | | 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | # the finished binary for fossil. The BCC compiler above is used # for building intermediate code-generator tools. # #TCC = gcc -O6 #TCC = gcc -g -O0 -Wall -fprofile-arcs -ftest-coverage TCC = gcc -g -Os -Wall # To add support for HTTPS TCC += -DFOSSIL_ENABLE_SSL #### We sometimes add the -static option here so that we can build a # static executable that will run in a chroot jail. #LIB = -static TCC += -DFOSSIL_DYNAMIC_BUILD=1 TCCFLAGS = $(CFLAGS) # We don't attempt to use libedit or libreadline in this simplified # build system (contrast auto.def and Makefile.in) so use the included # copy of linenoise. MinGW can't make use of this, but linenoise is # ifdef'd out elsewhere for that platform. Note that this is a make # flag handled in src/main.mk, not a C preprocessor flag. USE_LINENOISE := 1 #### Extra arguments for linking the finished binary. Fossil needs # to link against the Z-Lib compression library. There are no # other required dependencies. ZLIB_LIB = -lz # If using zlib: LIB += $(ZLIB_LIB) $(LDFLAGS) # If using HTTPS: LIB += -lcrypto -lssl # Many platforms put cos() needed by src/piechart.c in libm, rather than # in libc. We cannot enable this by default because libm doesn't exist # everywhere. #LIB += -lm #### Tcl shell for use in running the fossil testsuite. If you do not # care about testing the end result, this can be blank. # TCLSH = tclsh CFLAGS += -fPIE CPPFLAGS += -I. -I$(SRCDIR_extsrc) -I$(SRCDIR) LIB = -lm -lz -lssl INSTALLDIR = $(DESTDIR)$(prefix)/bin SQLITE3_ORIGINAL = 0 USE_LINENOISE = 1 # You should not need to change anything below this line ############################################################################### # # Automatic platform-specific options. HOST_OS_CMD = uname -s HOST_OS = $(HOST_OS_CMD:sh) LIB.SunOS= -lsocket -lnsl LIB += $(LIB.$(HOST_OS)) TCC.DragonFly += -DUSE_PREAD TCC.FreeBSD += -DUSE_PREAD TCC.NetBSD += -DUSE_PREAD TCC.OpenBSD += -DUSE_PREAD TCC += $(TCC.$(HOST_OS)) APPNAME = fossil$(E) .PHONY: all tags include $(SRCDIR)/main.mk |
Changes to Makefile.in.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #!/usr/bin/make # # This is the top-level makefile for Fossil when the build is occurring # on a unix platform. This works out-of-the-box on most unix platforms. # But you are free to vary some of the definitions if desired. # #### The toplevel directory of the source tree. Fossil can be built # in a directory that is separate from the source tree. Just change # the following to point from the build directory to the src/ folder. # SRCDIR = @srcdir@/src #### The directory into which object code files should be written. # Having a "./" prefix in the value of this variable breaks our use of the # "makeheaders" tool when running make on the MinGW platform, apparently # due to some command line argument manipulation performed automatically # by the shell. # | > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #!/usr/bin/make # # This is the top-level makefile for Fossil when the build is occurring # on a unix platform. This works out-of-the-box on most unix platforms. # But you are free to vary some of the definitions if desired. # #### The toplevel directory of the source tree. Fossil can be built # in a directory that is separate from the source tree. Just change # the following to point from the build directory to the src/ folder. # SRCDIR = @srcdir@/src #### Upstream source files included directly in this repository. # SRCDIR_extsrc = @srcdir@/extsrc #### In-tree tools such as code generators and translators: # SRCDIR_tools = @srcdir@/tools #### The directory into which object code files should be written. # Having a "./" prefix in the value of this variable breaks our use of the # "makeheaders" tool when running make on the MinGW platform, apparently # due to some command line argument manipulation performed automatically # by the shell. # |
| ︙ | ︙ | |||
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | #### Tcl shell for use in running the fossil testsuite. If you do not # care about testing the end result, this can be blank. # TCLSH = @TCLSH@ CFLAGS = @CFLAGS@ LIB = @LDFLAGS@ @EXTRA_LDFLAGS@ @LIBS@ BCCFLAGS = @CPPFLAGS@ $(CFLAGS) TCCFLAGS = @EXTRA_CFLAGS@ @CPPFLAGS@ $(CFLAGS) -DHAVE_AUTOCONFIG_H -D_HAVE_SQLITE_CONFIG_H INSTALLDIR = $(DESTDIR)@prefix@/bin USE_SYSTEM_SQLITE = @USE_SYSTEM_SQLITE@ USE_LINENOISE = @USE_LINENOISE@ USE_MMAN_H = @USE_MMAN_H@ USE_SEE = @USE_SEE@ | > > > > > > > > > > < | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | #### Tcl shell for use in running the fossil testsuite. If you do not # care about testing the end result, this can be blank. # TCLSH = @TCLSH@ CFLAGS = @CFLAGS@ CFLAGS_INCLUDE = @CFLAGS_INCLUDE@ LIB = @LDFLAGS@ @EXTRA_LDFLAGS@ @LIBS@ BCCFLAGS = @CPPFLAGS@ $(CFLAGS) TCCFLAGS = @EXTRA_CFLAGS@ @CPPFLAGS@ $(CFLAGS) -DHAVE_AUTOCONFIG_H -D_HAVE_SQLITE_CONFIG_H INSTALLDIR = $(DESTDIR)@prefix@/bin USE_SYSTEM_SQLITE = @USE_SYSTEM_SQLITE@ SQLITE3_SRC.2 = @SQLITE3_SRC.2@ SQLITE3_OBJ.2 = @SQLITE3_OBJ.2@ SQLITE3_SHELL_SRC.2 = @SQLITE3_SHELL_SRC.2@ SQLITE3_ORIGIN = @SQLITE3_ORIGIN@ # SQLITE3_ORIGIN changes... # SQLITE3_SRC: # 0=src/sqlite3.c, 1=src/sqlite3-see.c, 2=$(SQLITE3_SRC.2) # SQLITE3_SHELL_SRC: # 0=src/shell.c, 1=src/shell-see.c, 2=$(SQLITE3_SHELL_SRC.2) USE_LINENOISE = @USE_LINENOISE@ USE_MMAN_H = @USE_MMAN_H@ USE_SEE = @USE_SEE@ APPNAME = fossil .PHONY: all tags include $(SRCDIR)/main.mk distclean: clean |
| ︙ | ︙ |
Changes to Makefile.osx-jaguar.
| ︙ | ︙ | |||
60 61 62 63 64 65 66 | TCC += -Dsocklen_t=int TCC += -DSQLITE_MAX_MMAP_SIZE=0 INSTALLDIR = $(DESTDIR)/usr/local/bin USE_SYSTEM_SQLITE = USE_LINENOISE = 1 # FOSSIL_ENABLE_TCL = @FOSSIL_ENABLE_TCL@ FOSSIL_ENABLE_TCL = 0 | < | 60 61 62 63 64 65 66 67 68 69 70 71 | TCC += -Dsocklen_t=int TCC += -DSQLITE_MAX_MMAP_SIZE=0 INSTALLDIR = $(DESTDIR)/usr/local/bin USE_SYSTEM_SQLITE = USE_LINENOISE = 1 # FOSSIL_ENABLE_TCL = @FOSSIL_ENABLE_TCL@ FOSSIL_ENABLE_TCL = 0 include $(SRCDIR)/main.mk distclean: clean rm -f autoconfig.h config.log Makefile |
Changes to VERSION.
|
| | | 1 | 2.18 |
Deleted ajax/README.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted ajax/cgi-bin/fossil-json.cgi.example.
|
| < < |
Deleted ajax/i-test/rhino-shell.js.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted ajax/i-test/rhino-test.js.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted ajax/index.html.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted ajax/js/fossil-ajaj.js.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted ajax/js/json2.js.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted ajax/js/whajaj.js.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted ajax/wiki-editor.html.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted art/encode1.tex.
|
| < < |
Deleted art/encode2.tex.
|
| < |
Deleted art/encode3.tex.
|
| < |
Deleted art/encode4.tex.
|
| < |
Deleted art/encode5.tex.
|
| < |
Deleted art/encode6.tex.
|
| < |
Deleted art/encode7.tex.
|
| < |
Deleted art/encode8.tex.
|
| < |
Deleted art/encode9.tex.
|
| < |
Changes to auto.def.
1 2 3 4 5 6 7 8 9 |
# System autoconfiguration. Try: ./configure --help
# This must be above "options" below because it implicitly brings in the
# default Autosetup options, things like --prefix.
use cc cc-lib
options {
with-openssl:path|auto|tree|none
=> {Look for OpenSSL in the given path, automatically, in the source tree, or none}
| < > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# System autoconfiguration. Try: ./configure --help
# This must be above "options" below because it implicitly brings in the
# default Autosetup options, things like --prefix.
use cc cc-lib
options {
with-openssl:path|auto|tree|none
=> {Look for OpenSSL in the given path, automatically, in the source tree, or none}
with-zlib:path|auto|tree
=> {Look for zlib in the given path, automatically, or in the source tree}
with-sqlite:path|auto|tree
=> {Look for sqlite in the given path, automatically, or in the source tree.}
with-exec-rel-paths=0
=> {Enable relative paths for external diff/gdiff}
with-sanitizer: => {Build with C compiler's -fsanitize=LIST; e.g. address,enum,null,undefined}
with-th1-docs=0 => {Enable TH1 for embedded documentation pages}
with-th1-hooks=0 => {Enable TH1 hooks for commands and web pages}
with-tcl:path => {Enable Tcl integration, with Tcl in the specified path}
with-tcl-stubs=0 => {Enable Tcl integration via stubs library mechanism}
|
| ︙ | ︙ | |||
30 31 32 33 34 35 36 |
no-opt=0 => {Build without optimization}
json=0 => {Build with fossil JSON API enabled}
}
# Update the minimum required SQLite version number here, and also
# in src/main.c near the sqlite3_libversion_number() call. Take care
# that both places agree!
| | | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
no-opt=0 => {Build without optimization}
json=0 => {Build with fossil JSON API enabled}
}
# Update the minimum required SQLite version number here, and also
# in src/main.c near the sqlite3_libversion_number() call. Take care
# that both places agree!
define MINIMUM_SQLITE_VERSION "3.38.0"
# This is useful for people wanting Fossil to use an external SQLite library
# to compare the one they have against the minimum required
if {[opt-bool print-minimum-sqlite-version]} {
puts [get-define MINIMUM_SQLITE_VERSION]
exit 0
}
|
| ︙ | ︙ | |||
96 97 98 99 100 101 102 |
}
}
define EXTRA_CFLAGS "-Wall"
define EXTRA_LDFLAGS ""
define USE_SYSTEM_SQLITE 0
define USE_LINENOISE 0
| < | > | 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
}
}
define EXTRA_CFLAGS "-Wall"
define EXTRA_LDFLAGS ""
define USE_SYSTEM_SQLITE 0
define USE_LINENOISE 0
define USE_MMAN_H 0
define USE_SEE 0
define SQLITE3_ORIGIN 0
# SQLITE3_ORIGIN 0 = src/sqlite3, 1=src/sqlite3-see.c, 2=client-provided
# Maintain the C89/C90-style order of variable declarations before statements.
# Check if the compiler supports the respective warning flag.
if {[cctest -cflags -Wdeclaration-after-statement]} {
define-append EXTRA_CFLAGS -Wdeclaration-after-statement
}
|
| ︙ | ︙ | |||
181 182 183 184 185 186 187 |
# Check compatibility of the system SQLite library by running the sqlcompttest.c
# program in the source tree
# passes MINIMUM_SQLITE_VERSION set at the top of this file to sqlcompttest.c
#
set cmdline {}
lappend cmdline {*}[get-define CCACHE]
lappend cmdline {*}[get-define CC] {*}[get-define CFLAGS]
| | | 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# Check compatibility of the system SQLite library by running the sqlcompttest.c
# program in the source tree
# passes MINIMUM_SQLITE_VERSION set at the top of this file to sqlcompttest.c
#
set cmdline {}
lappend cmdline {*}[get-define CCACHE]
lappend cmdline {*}[get-define CC] {*}[get-define CFLAGS]
lappend cmdline $::autosetup(dir)/../tools/sqlcompattest.c -o conftest__
lappend cmdline {*}[get-define LDFLAGS]
lappend cmdline {*}[get-define LIBS]
set sqlite-version [string cat "-D MINIMUM_SQLITE_VERSION=" [get-define MINIMUM_SQLITE_VERSION]]
lappend cmdline {*}[set sqlite-version]
set ok 1
set err [catch {exec-with-stderr {*}$cmdline} result errinfo]
if {$err} {
|
| ︙ | ︙ | |||
229 230 231 232 233 234 235 |
# NOTE: All platforms except MinGW should use the linenoise
# package. It is currently unsupported on Win32.
#
define USE_LINENOISE 1
}
if {[string match *-solaris* [get-define host]]} {
| | | 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 |
# NOTE: All platforms except MinGW should use the linenoise
# package. It is currently unsupported on Win32.
#
define USE_LINENOISE 1
}
if {[string match *-solaris* [get-define host]]} {
define-append EXTRA_CFLAGS {-D__EXTENSIONS__}
}
if {[opt-bool fossil-debug]} {
define CFLAGS {-g -O0 -Wall}
define-append CFLAGS -DFOSSIL_DEBUG
msg-result "Debugging support enabled"
}
|
| ︙ | ︙ | |||
255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
define USE_MMAN_H 1
msg-result "Enabling \"sys/mman.h\" support"
}
if {[opt-bool with-see]} {
define-append EXTRA_CFLAGS -DUSE_SEE
define USE_SEE 1
msg-result "Enabling encryption support"
}
if {[opt-bool json]} {
# Reminder/FIXME (stephan): FOSSIL_ENABLE_JSON
# is required in the CFLAGS because json*.c
# have #ifdef guards around the whole file without
| > | 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 |
define USE_MMAN_H 1
msg-result "Enabling \"sys/mman.h\" support"
}
if {[opt-bool with-see]} {
define-append EXTRA_CFLAGS -DUSE_SEE
define USE_SEE 1
define SQLITE3_ORIGIN 1
msg-result "Enabling encryption support"
}
if {[opt-bool json]} {
# Reminder/FIXME (stephan): FOSSIL_ENABLE_JSON
# is required in the CFLAGS because json*.c
# have #ifdef guards around the whole file without
|
| ︙ | ︙ | |||
338 339 340 341 342 343 344 |
return 1
} else {
msg-result "no"
return 0
}
}
| < < < < | | | | | | | | | | | | | | | | | | | | | | | | | < < < < | 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
return 1
} else {
msg-result "no"
return 0
}
}
# Check for zlib, using the given location if specified
set zlibpath [opt-val with-zlib]
if {$zlibpath eq "tree"} {
set zlibdir [file dirname $autosetup(dir)]/compat/zlib
if {![file isdirectory $zlibdir]} {
user-error "The zlib in source tree directory does not exist"
}
cc-with [list -cflags "-I$zlibdir -L$zlibdir"]
define-append EXTRA_CFLAGS -I$zlibdir
define-append LIBS $zlibdir/libz.a
set ::zlib_lib $zlibdir/libz.a
msg-result "Using zlib in source tree"
} else {
if {$zlibpath ni {auto ""}} {
cc-with [list -cflags "-I$zlibpath -L$zlibpath"]
define-append EXTRA_CFLAGS -I$zlibpath
define-append EXTRA_LDFLAGS -L$zlibpath
msg-result "Using zlib from $zlibpath"
}
if {![cc-check-includes zlib.h] || ![check-function-in-lib inflateEnd z]} {
user-error "zlib not found please install it or specify the location with --with-zlib"
}
set ::zlib_lib -lz
}
set ssldirs [opt-val with-openssl]
if {$ssldirs ne "none"} {
set found 0
if {$ssldirs eq "tree"} {
set ssldir [file dirname $autosetup(dir)]/compat/openssl
if {![file isdirectory $ssldir]} {
user-error "The OpenSSL in source tree directory does not exist"
}
set msg "ssl in $ssldir"
|
| ︙ | ︙ | |||
447 448 449 450 451 452 453 454 455 456 457 458 459 460 |
}
} else {
if {[info exists ::zlib_lib]} {
define-append LIBS $::zlib_lib
}
}
set tclpath [opt-val with-tcl]
if {$tclpath ne ""} {
set tclprivatestubs [opt-bool with-tcl-private-stubs]
# Note parse-tclconfig-sh is in autosetup/local.tcl
if {$tclpath eq "1"} {
set tcldir [file dirname $autosetup(dir)]/compat/tcl-8.6
if {$tclprivatestubs} {
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 |
}
} else {
if {[info exists ::zlib_lib]} {
define-append LIBS $::zlib_lib
}
}
########################################################################
# --with-sqlite=PATH checks for the first it finds of the following...
# - PATH/sqlite3.c and PATH/sqlite3.h
# - PATH/sqlite3.o (and assumes sqlite3.h is with it)
# - PATH/lib/libsqlite3* and PATH/include/sqlite3.h
define CFLAGS_INCLUDE {}
# ^^^ CFLAGS_INCLUDE is ONLY for -I... flags and their order is
# significant so that --with-sqlite=PATH's header can shadow our
# own. One caveat with this is that we cannot point --with-sqlite=PATH
# to the root of sqlite3's own build tree because that dir has a
# config.h which ends up shadowing src/config.h, breaking our build.
set sq3path [opt-val with-sqlite]
define SQLITE3_SRC.2 {}
define SQLITE3_OBJ.2 {}
define SQLITE3_SHELL_SRC.2 {$(SQLITE3_SHELL_SRC.0)}
if {$sq3path in {tree ""}} {
msg-result "Using sqlite3.c from this source tree."
} else {
# SQLITE3_ORIGIN:
# 0 = local source tree
# 1 = use external lib or sqlite3.o
# 2 = use external sqlite3.c and (if found) shell.c
define USE_SYSTEM_SQLITE 1
define SQLITE3_ORIGIN 2
if {$sq3path != "auto"} {
if {([file exists $sq3path/sqlite3.c]) && \
([file exists $sq3path/sqlite3.h]) } {
# Prefer sqlite3.[ch] if found.
define SQLITE3_SRC.2 $sq3path/sqlite3.c
define SQLITE3_OBJ.2 {$(SQLITE3_OBJ.0)}
define USE_SYSTEM_SQLITE 2
define SQLITE3_ORIGIN 2
if {[file exists $sq3path/shell.c]} {
define SQLITE3_SHELL_SRC.2 $sq3path/shell.c
}
define-append CFLAGS_INCLUDE -I$sq3path
define-append EXTRA_LDFLAGS -lpthread
# ^^^ additional -lXXX flags are conservative estimates
msg-result "Using sqlite3.c and sqlite3.h from $sq3path"
} elseif {[file exists $sq3path/sqlite3.o]} {
# Use sqlite3.o if found.
define SQLITE3_OBJ.2 $sq3path/sqlite3.o
define-append CFLAGS_INCLUDE -I$sq3path
define-append EXTRA_LDFLAGS $sq3path/sqlite3.o -lpthread
# ^^^ additional -lXXX flags are conservative estimates
msg-result "Using sqlite3.o from $sq3path"
} elseif { ([llength [glob -nocomplain -directory $sq3path/lib libsqlite3*]] != 0) \
&& ([file exists $sq3path/include/sqlite3.h]) } {
# e.g. --with-sqlite=/usr/local. Try $sq3path/lib/libsqlite3*
# and $sq3path/include/sqlite3.h
define-append CFLAGS_INCLUDE -I$sq3path/include
define-append EXTRA_LDFLAGS -L$sq3path/lib -lsqlite3 -lpthread
# ^^^ additional -lXXX flags are conservative estimates
msg-result "Using -lsqlite3 from $sq3path"
} else {
# Assume $sq3path holds both the lib and header
cc-with [list -cflags "-I$sq3path -L$sq3path"]
define-append CFLAGS_INCLUDE -I$sq3path
define-append EXTRA_LDFLAGS -L$sq3path -lsqlite3 -lpthread
# ^^^ additional -lXXX flags are conservative estimates
msg-result "Using -lsqlite3 from $sq3path"
}
} elseif {![cc-check-includes sqlite3.h] || ![check-function-in-lib sqlite3_open_v2 sqlite3]} {
user-error "libsqlite3 not found please install it or specify the location with --with-sqlite"
}
}
define-append CFLAGS_INCLUDE {-I. -I$(SRCDIR) -I$(SRCDIR_extsrc)}
set tclpath [opt-val with-tcl]
if {$tclpath ne ""} {
set tclprivatestubs [opt-bool with-tcl-private-stubs]
# Note parse-tclconfig-sh is in autosetup/local.tcl
if {$tclpath eq "1"} {
set tcldir [file dirname $autosetup(dir)]/compat/tcl-8.6
if {$tclprivatestubs} {
|
| ︙ | ︙ |
Name change from src/cson_amalgamation.c to extsrc/cson_amalgamation.c.
| ︙ | ︙ |
Name change from src/cson_amalgamation.h to extsrc/cson_amalgamation.h.
| ︙ | ︙ |
Name change from src/linenoise.c to extsrc/linenoise.c.
| ︙ | ︙ |
Name change from src/linenoise.h to extsrc/linenoise.h.
| ︙ | ︙ |
Name change from src/pikchr.c to extsrc/pikchr.c.
| ︙ | ︙ | |||
5026 5027 5028 5029 5030 5031 5032 |
}else{
z = t->z;
nz = t->n;
}
while( nz>0 ){
int j;
for(j=0; j<nz && z[j]!='\\'; j++){}
| | | 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 |
}else{
z = t->z;
nz = t->n;
}
while( nz>0 ){
int j;
for(j=0; j<nz && z[j]!='\\'; j++){}
if( j ) pik_append_text(p, z, j, 0x3);
if( j<nz && (j+1==nz || z[j+1]=='\\') ){
pik_append(p, "\", -1);
j++;
}
nz -= j+1;
z += j+1;
}
|
| ︙ | ︙ | |||
6270 6271 6272 6273 6274 6275 6276 |
}
/*
** Round a PNum into the nearest integer
*/
static int pik_round(PNum v){
if( isnan(v) ) return 0;
| | | 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 |
}
/*
** Round a PNum into the nearest integer
*/
static int pik_round(PNum v){
if( isnan(v) ) return 0;
if( v < -2147483647 ) return (-2147483647-1);
if( v >= 2147483647 ) return 2147483647;
return (int)v;
}
/*
** Search for the variable named z[0..n-1] in:
**
|
| ︙ | ︙ |
Name change from src/shell.c to extsrc/shell.c.
| ︙ | ︙ | |||
441 442 443 444 445 446 447 | static sqlite3 *globalDb = 0; /* ** True if an interrupt (Control-C) has been received. */ static volatile int seenInterrupt = 0; | < < < < < < < < < | 441 442 443 444 445 446 447 448 449 450 451 452 453 454 | static sqlite3 *globalDb = 0; /* ** True if an interrupt (Control-C) has been received. */ static volatile int seenInterrupt = 0; /* ** This is the name of our program. It is set in main(), used ** in a number of other places, mostly for error messages. */ static char *Argv0; /* |
| ︙ | ︙ | |||
501 502 503 504 505 506 507 |
/* Indicate out-of-memory and exit. */
static void shell_out_of_memory(void){
raw_printf(stderr,"Error: out of memory\n");
exit(1);
}
| < < < < < < < < < < < < < | < < | | < < < < < < < < < < < | < < < < < < < < < < | 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 |
/* Indicate out-of-memory and exit. */
static void shell_out_of_memory(void){
raw_printf(stderr,"Error: out of memory\n");
exit(1);
}
/* Check a pointer to see if it is NULL. If it is NULL, exit with an
** out-of-memory error.
*/
static void shell_check_oom(void *p){
if( p==0 ) shell_out_of_memory();
}
/*
** Write I/O traces to the following stream.
*/
#ifdef SQLITE_ENABLE_IOTRACE
static FILE *iotrace = 0;
#endif
|
| ︙ | ︙ | |||
699 700 701 702 703 704 705 |
int nLine = zLine==0 ? 0 : 100;
int n = 0;
while( 1 ){
if( n+100>nLine ){
nLine = nLine*2 + 100;
zLine = realloc(zLine, nLine);
| | | 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 |
int nLine = zLine==0 ? 0 : 100;
int n = 0;
while( 1 ){
if( n+100>nLine ){
nLine = nLine*2 + 100;
zLine = realloc(zLine, nLine);
shell_check_oom(zLine);
}
if( fgets(&zLine[n], nLine - n, in)==0 ){
if( n==0 ){
free(zLine);
return 0;
}
zLine[n] = 0;
|
| ︙ | ︙ | |||
726 727 728 729 730 731 732 |
** multi-byte characterset characters into UTF-8. */
if( stdin_is_interactive && in==stdin ){
char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0);
if( zTrans ){
int nTrans = strlen30(zTrans)+1;
if( nTrans>nLine ){
zLine = realloc(zLine, nTrans);
| | | 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 |
** multi-byte characterset characters into UTF-8. */
if( stdin_is_interactive && in==stdin ){
char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0);
if( zTrans ){
int nTrans = strlen30(zTrans)+1;
if( nTrans>nLine ){
zLine = realloc(zLine, nTrans);
shell_check_oom(zLine);
}
memcpy(zLine, zTrans, nTrans);
sqlite3_free(zTrans);
}
}
#endif /* defined(_WIN32) || defined(WIN32) */
return zLine;
|
| ︙ | ︙ | |||
873 874 875 876 877 878 879 |
if( zAppend[i]==quote ) len++;
}
}
if( p->z==0 || p->n+len>=p->nAlloc ){
p->nAlloc = p->nAlloc*2 + len + 20;
p->z = realloc(p->z, p->nAlloc);
| | | 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 |
if( zAppend[i]==quote ) len++;
}
}
if( p->z==0 || p->n+len>=p->nAlloc ){
p->nAlloc = p->nAlloc*2 + len + 20;
p->z = realloc(p->z, p->nAlloc);
shell_check_oom(p->z);
}
if( quote ){
char *zCsr = p->z+p->n;
*zCsr++ = quote;
for(i=0; i<nAppend; i++){
*zCsr++ = zAppend[i];
|
| ︙ | ︙ | |||
928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 |
ShellText s;
char cQuote;
char *zDiv = "(";
int nRow = 0;
zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;",
zSchema ? zSchema : "main", zName);
sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
initText(&s);
if( zSchema ){
cQuote = quoteChar(zSchema);
if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0;
appendText(&s, zSchema, cQuote);
appendText(&s, ".", 0);
}
cQuote = quoteChar(zName);
appendText(&s, zName, cQuote);
while( sqlite3_step(pStmt)==SQLITE_ROW ){
const char *zCol = (const char*)sqlite3_column_text(pStmt, 1);
nRow++;
appendText(&s, zDiv, 0);
zDiv = ",";
cQuote = quoteChar(zCol);
appendText(&s, zCol, cQuote);
}
appendText(&s, ")", 0);
sqlite3_finalize(pStmt);
if( nRow==0 ){
freeText(&s);
| > > | 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 |
ShellText s;
char cQuote;
char *zDiv = "(";
int nRow = 0;
zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;",
zSchema ? zSchema : "main", zName);
shell_check_oom(zSql);
sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
initText(&s);
if( zSchema ){
cQuote = quoteChar(zSchema);
if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0;
appendText(&s, zSchema, cQuote);
appendText(&s, ".", 0);
}
cQuote = quoteChar(zName);
appendText(&s, zName, cQuote);
while( sqlite3_step(pStmt)==SQLITE_ROW ){
const char *zCol = (const char*)sqlite3_column_text(pStmt, 1);
nRow++;
appendText(&s, zDiv, 0);
zDiv = ",";
if( zCol==0 ) zCol = "";
cQuote = quoteChar(zCol);
appendText(&s, zCol, cQuote);
}
appendText(&s, ")", 0);
sqlite3_finalize(pStmt);
if( nRow==0 ){
freeText(&s);
|
| ︙ | ︙ | |||
967 968 969 970 971 972 973 |
** table X.
*/
static void shellModuleSchema(
sqlite3_context *pCtx,
int nVal,
sqlite3_value **apVal
){
| | | > > | 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 |
** table X.
*/
static void shellModuleSchema(
sqlite3_context *pCtx,
int nVal,
sqlite3_value **apVal
){
const char *zName;
char *zFake;
UNUSED_PARAMETER(nVal);
zName = (const char*)sqlite3_value_text(apVal[0]);
zFake = zName ? shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName) : 0;
if( zFake ){
sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
-1, sqlite3_free);
free(zFake);
}
}
|
| ︙ | ︙ | |||
1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 |
*/
static void SHA3Update(
SHA3Context *p,
const unsigned char *aData,
unsigned int nData
){
unsigned int i = 0;
#if SHA3_BYTEORDER==1234
if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){
for(; i+7<nData; i+=8){
p->u.s[p->nLoaded/8] ^= *(u64*)&aData[i];
p->nLoaded += 8;
if( p->nLoaded>=p->nRate ){
KeccakF1600Step(p);
| > | 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 |
*/
static void SHA3Update(
SHA3Context *p,
const unsigned char *aData,
unsigned int nData
){
unsigned int i = 0;
if( aData==0 ) return;
#if SHA3_BYTEORDER==1234
if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){
for(; i+7<nData; i+=8){
p->u.s[p->nLoaded/8] ^= *(u64*)&aData[i];
p->nLoaded += 8;
if( p->nLoaded>=p->nRate ){
KeccakF1600Step(p);
|
| ︙ | ︙ | |||
2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 |
static int writeFile(
sqlite3_context *pCtx, /* Context to return bytes written in */
const char *zFile, /* File to write */
sqlite3_value *pData, /* Data to write */
mode_t mode, /* MODE parameter passed to writefile() */
sqlite3_int64 mtime /* MTIME parameter (or -1 to not set time) */
){
#if !defined(_WIN32) && !defined(WIN32)
if( S_ISLNK(mode) ){
const char *zTo = (const char*)sqlite3_value_text(pData);
| > | | 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 |
static int writeFile(
sqlite3_context *pCtx, /* Context to return bytes written in */
const char *zFile, /* File to write */
sqlite3_value *pData, /* Data to write */
mode_t mode, /* MODE parameter passed to writefile() */
sqlite3_int64 mtime /* MTIME parameter (or -1 to not set time) */
){
if( zFile==0 ) return 1;
#if !defined(_WIN32) && !defined(WIN32)
if( S_ISLNK(mode) ){
const char *zTo = (const char*)sqlite3_value_text(pData);
if( zTo==0 || symlink(zTo, zFile)<0 ) return 1;
}else
#endif
{
if( S_ISDIR(mode) ){
if( mkdir(zFile, mode) ){
/* The mkdir() call to create the directory failed. This might not
** be an error though - if there is already a directory at the same
|
| ︙ | ︙ | |||
5884 5885 5886 5887 5888 5889 5890 |
return SQLITE_CONSTRAINT;
}
if( (idxNum & 3)==3 ){
/* Both start= and stop= boundaries are available. This is the
** the preferred case */
pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
pIdxInfo->estimatedRows = 1000;
| | | 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 |
return SQLITE_CONSTRAINT;
}
if( (idxNum & 3)==3 ){
/* Both start= and stop= boundaries are available. This is the
** the preferred case */
pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
pIdxInfo->estimatedRows = 1000;
if( pIdxInfo->nOrderBy>=1 && pIdxInfo->aOrderBy[0].iColumn==0 ){
if( pIdxInfo->aOrderBy[0].desc ){
idxNum |= 8;
}else{
idxNum |= 16;
}
pIdxInfo->orderByConsumed = 1;
}
|
| ︙ | ︙ | |||
6719 6720 6721 6722 6723 6724 6725 |
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
(void)pzErrMsg; /* Unused */
| | > | | > | | 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 |
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
(void)pzErrMsg; /* Unused */
rc = sqlite3_create_function(db, "regexp", 2,
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
0, re_sql_func, 0, 0);
if( rc==SQLITE_OK ){
/* The regexpi(PATTERN,STRING) function is a case-insensitive version
** of regexp(PATTERN,STRING). */
rc = sqlite3_create_function(db, "regexpi", 2,
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
(void*)db, re_sql_func, 0, 0);
}
return rc;
}
/************************* End ../ext/misc/regexp.c ********************/
#ifdef SQLITE_HAVE_ZLIB
/************************* Begin ../ext/misc/zipfile.c ******************/
|
| ︙ | ︙ | |||
8673 8674 8675 8676 8677 8678 8679 | ** xStep() callback for the zipfile() aggregate. This can be called in ** any of the following ways: ** ** SELECT zipfile(name,data) ... ** SELECT zipfile(name,mode,mtime,data) ... ** SELECT zipfile(name,mode,mtime,data,method) ... */ | | | 8636 8637 8638 8639 8640 8641 8642 8643 8644 8645 8646 8647 8648 8649 8650 |
** xStep() callback for the zipfile() aggregate. This can be called in
** any of the following ways:
**
** SELECT zipfile(name,data) ...
** SELECT zipfile(name,mode,mtime,data) ...
** SELECT zipfile(name,mode,mtime,data,method) ...
*/
static void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
ZipfileCtx *p; /* Aggregate function context */
ZipfileEntry e; /* New entry to add to zip archive */
sqlite3_value *pName = 0;
sqlite3_value *pMode = 0;
sqlite3_value *pMtime = 0;
sqlite3_value *pData = 0;
|
| ︙ | ︙ | |||
8848 8849 8850 8851 8852 8853 8854 | } sqlite3_free(zErr); } /* ** xFinalize() callback for zipfile aggregate function. */ | | | 8811 8812 8813 8814 8815 8816 8817 8818 8819 8820 8821 8822 8823 8824 8825 |
}
sqlite3_free(zErr);
}
/*
** xFinalize() callback for zipfile aggregate function.
*/
static void zipfileFinal(sqlite3_context *pCtx){
ZipfileCtx *p;
ZipfileEOCD eocd;
sqlite3_int64 nZip;
u8 *aZip;
p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
if( p==0 ) return;
|
| ︙ | ︙ | |||
9937 9938 9939 9940 9941 9942 9943 |
sqlite3 *db, /* Database connection to read details from */
const char *zTab, /* Table name */
IdxTable **ppOut, /* OUT: New object (if successful) */
char **pzErrmsg /* OUT: Error message (if not) */
){
sqlite3_stmt *p1 = 0;
int nCol = 0;
| | | > > > > > > > > | 9900 9901 9902 9903 9904 9905 9906 9907 9908 9909 9910 9911 9912 9913 9914 9915 9916 9917 9918 9919 9920 9921 9922 9923 9924 9925 9926 9927 9928 9929 9930 9931 9932 |
sqlite3 *db, /* Database connection to read details from */
const char *zTab, /* Table name */
IdxTable **ppOut, /* OUT: New object (if successful) */
char **pzErrmsg /* OUT: Error message (if not) */
){
sqlite3_stmt *p1 = 0;
int nCol = 0;
int nTab;
int nByte;
IdxTable *pNew = 0;
int rc, rc2;
char *pCsr = 0;
int nPk = 0;
*ppOut = 0;
if( zTab==0 ) return SQLITE_ERROR;
nTab = STRLEN(zTab);
nByte = sizeof(IdxTable) + nTab + 1;
rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_xinfo=%Q", zTab);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
const char *zCol = (const char*)sqlite3_column_text(p1, 1);
const char *zColSeq = 0;
if( zCol==0 ){
rc = SQLITE_ERROR;
break;
}
nByte += 1 + STRLEN(zCol);
rc = sqlite3_table_column_metadata(
db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0
);
if( zColSeq==0 ) zColSeq = "binary";
nByte += 1 + STRLEN(zColSeq);
nCol++;
|
| ︙ | ︙ | |||
9974 9975 9976 9977 9978 9979 9980 |
pCsr = (char*)&pNew->aCol[nCol];
}
nCol = 0;
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
const char *zCol = (const char*)sqlite3_column_text(p1, 1);
const char *zColSeq = 0;
| > > | | 9945 9946 9947 9948 9949 9950 9951 9952 9953 9954 9955 9956 9957 9958 9959 9960 9961 |
pCsr = (char*)&pNew->aCol[nCol];
}
nCol = 0;
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
const char *zCol = (const char*)sqlite3_column_text(p1, 1);
const char *zColSeq = 0;
int nCopy;
if( zCol==0 ) continue;
nCopy = STRLEN(zCol) + 1;
pNew->aCol[nCol].zName = pCsr;
pNew->aCol[nCol].iPk = (sqlite3_column_int(p1, 5)==1 && nPk==1);
memcpy(pCsr, zCol, nCopy);
pCsr += nCopy;
rc = sqlite3_table_column_metadata(
db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0
|
| ︙ | ︙ | |||
10126 10127 10128 10129 10130 10131 10132 10133 10134 10135 10136 10137 10138 10139 |
rc = idxPrintfPrepareStmt(dbm, &pIdxList, 0, "PRAGMA index_list=%Q", zTbl);
while( rc==SQLITE_OK && sqlite3_step(pIdxList)==SQLITE_ROW ){
int bMatch = 1;
IdxConstraint *pT = pTail;
sqlite3_stmt *pInfo = 0;
const char *zIdx = (const char*)sqlite3_column_text(pIdxList, 1);
/* Zero the IdxConstraint.bFlag values in the pEq list */
for(pIter=pEq; pIter; pIter=pIter->pLink) pIter->bFlag = 0;
rc = idxPrintfPrepareStmt(dbm, &pInfo, 0, "PRAGMA index_xInfo=%Q", zIdx);
while( rc==SQLITE_OK && sqlite3_step(pInfo)==SQLITE_ROW ){
int iIdx = sqlite3_column_int(pInfo, 0);
| > | 10099 10100 10101 10102 10103 10104 10105 10106 10107 10108 10109 10110 10111 10112 10113 |
rc = idxPrintfPrepareStmt(dbm, &pIdxList, 0, "PRAGMA index_list=%Q", zTbl);
while( rc==SQLITE_OK && sqlite3_step(pIdxList)==SQLITE_ROW ){
int bMatch = 1;
IdxConstraint *pT = pTail;
sqlite3_stmt *pInfo = 0;
const char *zIdx = (const char*)sqlite3_column_text(pIdxList, 1);
if( zIdx==0 ) continue;
/* Zero the IdxConstraint.bFlag values in the pEq list */
for(pIter=pEq; pIter; pIter=pIter->pLink) pIter->bFlag = 0;
rc = idxPrintfPrepareStmt(dbm, &pInfo, 0, "PRAGMA index_xInfo=%Q", zIdx);
while( rc==SQLITE_OK && sqlite3_step(pInfo)==SQLITE_ROW ){
int iIdx = sqlite3_column_int(pInfo, 0);
|
| ︙ | ︙ | |||
10408 10409 10410 10411 10412 10413 10414 | /* ** This function is called after candidate indexes have been created. It ** runs all the queries to see which indexes they prefer, and populates ** IdxStatement.zIdx and IdxStatement.zEQP with the results. */ | | | 10382 10383 10384 10385 10386 10387 10388 10389 10390 10391 10392 10393 10394 10395 10396 |
/*
** This function is called after candidate indexes have been created. It
** runs all the queries to see which indexes they prefer, and populates
** IdxStatement.zIdx and IdxStatement.zEQP with the results.
*/
static int idxFindIndexes(
sqlite3expert *p,
char **pzErr /* OUT: Error message (sqlite3_malloc) */
){
IdxStatement *pStmt;
sqlite3 *dbm = p->dbm;
int rc = SQLITE_OK;
|
| ︙ | ︙ | |||
10537 10538 10539 10540 10541 10542 10543 10544 10545 10546 10547 10548 10549 10550 |
int rc = SQLITE_OK;
char *zWrite = 0;
/* Create the table and its triggers in the temp schema */
rc = idxPrintfPrepareStmt(p->db, &pSelect, pzErr, zSql, zTab, zTab);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSelect) ){
const char *zCreate = (const char*)sqlite3_column_text(pSelect, 0);
rc = sqlite3_exec(p->dbv, zCreate, 0, 0, pzErr);
}
idxFinalize(&rc, pSelect);
/* Rename the table in the temp schema to zInt */
if( rc==SQLITE_OK ){
char *z = sqlite3_mprintf("ALTER TABLE temp.%Q RENAME TO %Q", zTab, zInt);
| > | 10511 10512 10513 10514 10515 10516 10517 10518 10519 10520 10521 10522 10523 10524 10525 |
int rc = SQLITE_OK;
char *zWrite = 0;
/* Create the table and its triggers in the temp schema */
rc = idxPrintfPrepareStmt(p->db, &pSelect, pzErr, zSql, zTab, zTab);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSelect) ){
const char *zCreate = (const char*)sqlite3_column_text(pSelect, 0);
if( zCreate==0 ) continue;
rc = sqlite3_exec(p->dbv, zCreate, 0, 0, pzErr);
}
idxFinalize(&rc, pSelect);
/* Rename the table in the temp schema to zInt */
if( rc==SQLITE_OK ){
char *z = sqlite3_mprintf("ALTER TABLE temp.%Q RENAME TO %Q", zTab, zInt);
|
| ︙ | ︙ | |||
10639 10640 10641 10642 10643 10644 10645 10646 |
"ORDER BY 4, 1"
);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSchema) ){
const char *zType = (const char*)sqlite3_column_text(pSchema, 0);
const char *zName = (const char*)sqlite3_column_text(pSchema, 1);
const char *zSql = (const char*)sqlite3_column_text(pSchema, 2);
if( zType[0]=='v' || zType[1]=='r' ){
| > | | 10614 10615 10616 10617 10618 10619 10620 10621 10622 10623 10624 10625 10626 10627 10628 10629 10630 |
"ORDER BY 4, 1"
);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSchema) ){
const char *zType = (const char*)sqlite3_column_text(pSchema, 0);
const char *zName = (const char*)sqlite3_column_text(pSchema, 1);
const char *zSql = (const char*)sqlite3_column_text(pSchema, 2);
if( zType==0 || zName==0 ) continue;
if( zType[0]=='v' || zType[1]=='r' ){
if( zSql ) rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg);
}else{
IdxTable *pTab;
rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg);
if( rc==SQLITE_OK ){
int i;
char *zInner = 0;
char *zOuter = 0;
|
| ︙ | ︙ | |||
10777 10778 10779 10780 10781 10782 10783 10784 10785 10786 10787 10788 10789 10790 10791 10792 10793 10794 |
case SQLITE_FLOAT:
pSlot->rVal = sqlite3_value_double(argv[1]);
break;
case SQLITE_BLOB:
case SQLITE_TEXT: {
int nByte = sqlite3_value_bytes(argv[1]);
if( nByte>pSlot->nByte ){
char *zNew = (char*)sqlite3_realloc(pSlot->z, nByte*2);
if( zNew==0 ){
sqlite3_result_error_nomem(pCtx);
return;
}
pSlot->nByte = nByte*2;
pSlot->z = zNew;
}
pSlot->n = nByte;
if( pSlot->eType==SQLITE_BLOB ){
| > | > | > | 10753 10754 10755 10756 10757 10758 10759 10760 10761 10762 10763 10764 10765 10766 10767 10768 10769 10770 10771 10772 10773 10774 10775 10776 10777 10778 10779 10780 10781 10782 10783 |
case SQLITE_FLOAT:
pSlot->rVal = sqlite3_value_double(argv[1]);
break;
case SQLITE_BLOB:
case SQLITE_TEXT: {
int nByte = sqlite3_value_bytes(argv[1]);
const void *pData = 0;
if( nByte>pSlot->nByte ){
char *zNew = (char*)sqlite3_realloc(pSlot->z, nByte*2);
if( zNew==0 ){
sqlite3_result_error_nomem(pCtx);
return;
}
pSlot->nByte = nByte*2;
pSlot->z = zNew;
}
pSlot->n = nByte;
if( pSlot->eType==SQLITE_BLOB ){
pData = sqlite3_value_blob(argv[1]);
if( pData ) memcpy(pSlot->z, pData, nByte);
}else{
pData = sqlite3_value_text(argv[1]);
memcpy(pSlot->z, pData, nByte);
}
break;
}
}
}
static int idxLargestIndex(sqlite3 *db, int *pnMax, char **pzErr){
|
| ︙ | ︙ | |||
11001 11002 11003 11004 11005 11006 11007 11008 11009 11010 11011 11012 11013 11014 |
rc = idxPrepareStmt(p->dbm, &pWrite, pzErr, zWrite);
}
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pAllIndex) ){
i64 iRowid = sqlite3_column_int64(pAllIndex, 0);
const char *zTab = (const char*)sqlite3_column_text(pAllIndex, 1);
const char *zIdx = (const char*)sqlite3_column_text(pAllIndex, 2);
if( p->iSample<100 && iPrev!=iRowid ){
samplectx.target = (double)p->iSample / 100.0;
samplectx.iTarget = p->iSample;
samplectx.nRow = 0.0;
samplectx.nRet = 0.0;
rc = idxBuildSampleTable(p, zTab);
if( rc!=SQLITE_OK ) break;
| > | 10980 10981 10982 10983 10984 10985 10986 10987 10988 10989 10990 10991 10992 10993 10994 |
rc = idxPrepareStmt(p->dbm, &pWrite, pzErr, zWrite);
}
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pAllIndex) ){
i64 iRowid = sqlite3_column_int64(pAllIndex, 0);
const char *zTab = (const char*)sqlite3_column_text(pAllIndex, 1);
const char *zIdx = (const char*)sqlite3_column_text(pAllIndex, 2);
if( zTab==0 || zIdx==0 ) continue;
if( p->iSample<100 && iPrev!=iRowid ){
samplectx.target = (double)p->iSample / 100.0;
samplectx.iTarget = p->iSample;
samplectx.nRow = 0.0;
samplectx.nRet = 0.0;
rc = idxBuildSampleTable(p, zTab);
if( rc!=SQLITE_OK ) break;
|
| ︙ | ︙ | |||
11067 11068 11069 11070 11071 11072 11073 |
sqlite3_db_config(pNew->dbm, SQLITE_DBCONFIG_TRIGGER_EQP, 1, (int*)0);
}
}
/* Copy the entire schema of database [db] into [dbm]. */
if( rc==SQLITE_OK ){
| | | | 11047 11048 11049 11050 11051 11052 11053 11054 11055 11056 11057 11058 11059 11060 11061 11062 11063 11064 11065 11066 11067 11068 |
sqlite3_db_config(pNew->dbm, SQLITE_DBCONFIG_TRIGGER_EQP, 1, (int*)0);
}
}
/* Copy the entire schema of database [db] into [dbm]. */
if( rc==SQLITE_OK ){
sqlite3_stmt *pSql = 0;
rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg,
"SELECT sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'"
" AND sql NOT LIKE 'CREATE VIRTUAL %%'"
);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
if( zSql ) rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg);
}
idxFinalize(&rc, pSql);
}
/* Create the vtab schema */
if( rc==SQLITE_OK ){
rc = idxCreateVtabSchema(pNew, pzErrmsg);
|
| ︙ | ︙ | |||
12307 12308 12309 12310 12311 12312 12313 12314 12315 12316 12317 12318 12319 12320 12321 12322 12323 12324 12325 12326 12327 12328 12329 12330 12331 |
#define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */
#define MODE_Pretty 11 /* Pretty-print schemas */
#define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */
#define MODE_Json 13 /* Output JSON */
#define MODE_Markdown 14 /* Markdown formatting */
#define MODE_Table 15 /* MySQL-style table formatting */
#define MODE_Box 16 /* Unicode box-drawing characters */
static const char *modeDescr[] = {
"line",
"column",
"list",
"semi",
"html",
"insert",
"quote",
"tcl",
"csv",
"explain",
"ascii",
"prettyprint",
"eqp",
"json",
"markdown",
"table",
| > > | > > | 12287 12288 12289 12290 12291 12292 12293 12294 12295 12296 12297 12298 12299 12300 12301 12302 12303 12304 12305 12306 12307 12308 12309 12310 12311 12312 12313 12314 12315 12316 12317 12318 12319 12320 12321 12322 12323 |
#define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */
#define MODE_Pretty 11 /* Pretty-print schemas */
#define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */
#define MODE_Json 13 /* Output JSON */
#define MODE_Markdown 14 /* Markdown formatting */
#define MODE_Table 15 /* MySQL-style table formatting */
#define MODE_Box 16 /* Unicode box-drawing characters */
#define MODE_Count 17 /* Output only a count of the rows of output */
#define MODE_Off 18 /* No query output shown */
static const char *modeDescr[] = {
"line",
"column",
"list",
"semi",
"html",
"insert",
"quote",
"tcl",
"csv",
"explain",
"ascii",
"prettyprint",
"eqp",
"json",
"markdown",
"table",
"box",
"count",
"off"
};
/*
** These are the column/row/line separators used by the various
** import/export modes.
*/
#define SEP_Column "|"
|
| ︙ | ︙ | |||
12816 12817 12818 12819 12820 12821 12822 |
** is only issued if bSep is true.
*/
static void output_csv(ShellState *p, const char *z, int bSep){
FILE *out = p->out;
if( z==0 ){
utf8_printf(out,"%s",p->nullValue);
}else{
| | < | < < | > | 12800 12801 12802 12803 12804 12805 12806 12807 12808 12809 12810 12811 12812 12813 12814 12815 12816 12817 12818 12819 12820 12821 12822 12823 |
** is only issued if bSep is true.
*/
static void output_csv(ShellState *p, const char *z, int bSep){
FILE *out = p->out;
if( z==0 ){
utf8_printf(out,"%s",p->nullValue);
}else{
unsigned i;
for(i=0; z[i]; i++){
if( needCsvQuote[((unsigned char*)z)[i]] ){
i = 0;
break;
}
}
if( i==0 || strstr(z, p->colSeparator)!=0 ){
char *zQuoted = sqlite3_mprintf("\"%w\"", z);
shell_check_oom(zQuoted);
utf8_printf(out, "%s", zQuoted);
sqlite3_free(zQuoted);
}else{
utf8_printf(out, "%s", z);
}
}
if( bSep ){
|
| ︙ | ︙ | |||
13002 13003 13004 13005 13006 13007 13008 |
static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){
EQPGraphRow *pNew;
int nText = strlen30(zText);
if( p->autoEQPtest ){
utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
}
pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
| | | 12984 12985 12986 12987 12988 12989 12990 12991 12992 12993 12994 12995 12996 12997 12998 |
static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){
EQPGraphRow *pNew;
int nText = strlen30(zText);
if( p->autoEQPtest ){
utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
}
pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
shell_check_oom(pNew);
pNew->iEqpId = iEqpId;
pNew->iParentId = p2;
memcpy(pNew->zText, zText, nText+1);
pNew->pNext = 0;
if( p->sGraph.pLast ){
p->sGraph.pLast->pNext = pNew;
}else{
|
| ︙ | ︙ | |||
13150 13151 13152 13153 13154 13155 13156 13157 13158 13159 13160 13161 13162 13163 |
int *aiType /* Column types. Might be NULL */
){
int i;
ShellState *p = (ShellState*)pArg;
if( azArg==0 ) return 0;
switch( p->cMode ){
case MODE_Line: {
int w = 5;
if( azArg==0 ) break;
for(i=0; i<nArg; i++){
int len = strlen30(azCol[i] ? azCol[i] : "");
if( len>w ) w = len;
}
| > > > > | 13132 13133 13134 13135 13136 13137 13138 13139 13140 13141 13142 13143 13144 13145 13146 13147 13148 13149 |
int *aiType /* Column types. Might be NULL */
){
int i;
ShellState *p = (ShellState*)pArg;
if( azArg==0 ) return 0;
switch( p->cMode ){
case MODE_Count:
case MODE_Off: {
break;
}
case MODE_Line: {
int w = 5;
if( azArg==0 ) break;
for(i=0; i<nArg; i++){
int len = strlen30(azCol[i] ? azCol[i] : "");
if( len>w ) w = len;
}
|
| ︙ | ︙ | |||
13219 13220 13221 13222 13223 13224 13225 13226 13227 13228 13229 13230 13231 13232 |
if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
|| sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0
){
utf8_printf(p->out, "%s;\n", azArg[0]);
break;
}
z = sqlite3_mprintf("%s", azArg[0]);
j = 0;
for(i=0; IsSpace(z[i]); i++){}
for(; (c = z[i])!=0; i++){
if( IsSpace(c) ){
if( z[j-1]=='\r' ) z[j-1] = '\n';
if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue;
}else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){
| > | 13205 13206 13207 13208 13209 13210 13211 13212 13213 13214 13215 13216 13217 13218 13219 |
if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
|| sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0
){
utf8_printf(p->out, "%s;\n", azArg[0]);
break;
}
z = sqlite3_mprintf("%s", azArg[0]);
shell_check_oom(z);
j = 0;
for(i=0; IsSpace(z[i]); i++){}
for(; (c = z[i])!=0; i++){
if( IsSpace(c) ){
if( z[j-1]=='\r' ) z[j-1] = '\n';
if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue;
}else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){
|
| ︙ | ︙ | |||
13350 13351 13352 13353 13354 13355 13356 13357 13358 13359 13360 13361 13362 13363 |
utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
if( p->showHeader ){
raw_printf(p->out,"(");
for(i=0; i<nArg; i++){
if( i>0 ) raw_printf(p->out, ",");
if( quoteChar(azCol[i]) ){
char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
utf8_printf(p->out, "%s", z);
sqlite3_free(z);
}else{
raw_printf(p->out, "%s", azCol[i]);
}
}
raw_printf(p->out,")");
| > | 13337 13338 13339 13340 13341 13342 13343 13344 13345 13346 13347 13348 13349 13350 13351 |
utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
if( p->showHeader ){
raw_printf(p->out,"(");
for(i=0; i<nArg; i++){
if( i>0 ) raw_printf(p->out, ",");
if( quoteChar(azCol[i]) ){
char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
shell_check_oom(z);
utf8_printf(p->out, "%s", z);
sqlite3_free(z);
}else{
raw_printf(p->out, "%s", azCol[i]);
}
}
raw_printf(p->out,")");
|
| ︙ | ︙ | |||
13595 13596 13597 13598 13599 13600 13601 |
p->zDestTable = 0;
}
if( zName==0 ) return;
cQuote = quoteChar(zName);
n = strlen30(zName);
if( cQuote ) n += n+2;
z = p->zDestTable = malloc( n+1 );
| | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 13583 13584 13585 13586 13587 13588 13589 13590 13591 13592 13593 13594 13595 13596 13597 13598 13599 13600 13601 13602 13603 13604 13605 13606 13607 13608 13609 13610 13611 13612 13613 13614 13615 13616 13617 13618 13619 13620 13621 13622 13623 13624 13625 13626 13627 13628 13629 13630 13631 13632 13633 13634 13635 13636 13637 13638 13639 13640 13641 13642 13643 13644 13645 13646 13647 |
p->zDestTable = 0;
}
if( zName==0 ) return;
cQuote = quoteChar(zName);
n = strlen30(zName);
if( cQuote ) n += n+2;
z = p->zDestTable = malloc( n+1 );
shell_check_oom(z);
n = 0;
if( cQuote ) z[n++] = cQuote;
for(i=0; zName[i]; i++){
z[n++] = zName[i];
if( zName[i]==cQuote ) z[n++] = cQuote;
}
if( cQuote ) z[n++] = cQuote;
z[n] = 0;
}
/*
** Maybe construct two lines of text that point out the position of a
** syntax error. Return a pointer to the text, in memory obtained from
** sqlite3_malloc(). Or, if the most recent error does not involve a
** specific token that we can point to, return an empty string.
**
** In all cases, the memory returned is obtained from sqlite3_malloc64()
** and should be released by the caller invoking sqlite3_free().
*/
static char *shell_error_context(const char *zSql, sqlite3 *db){
int iOffset;
size_t len;
char *zCode;
char *zMsg;
int i;
if( db==0
|| zSql==0
|| (iOffset = sqlite3_error_offset(db))<0
){
return sqlite3_mprintf("");
}
while( iOffset>50 ){
iOffset--;
zSql++;
while( (zSql[0]&0xc0)==0x80 ){ zSql++; iOffset--; }
}
len = strlen(zSql);
if( len>78 ){
len = 78;
while( (zSql[len]&0xc0)==0x80 ) len--;
}
zCode = sqlite3_mprintf("%.*s", len, zSql);
for(i=0; zCode[i]; i++){ if( IsSpace(zSql[i]) ) zCode[i] = ' '; }
if( iOffset<25 ){
zMsg = sqlite3_mprintf("\n %z\n %*s^--- error here", zCode, iOffset, "");
}else{
zMsg = sqlite3_mprintf("\n %z\n %*serror here ---^", zCode, iOffset-14, "");
}
return zMsg;
}
/*
** Execute a query statement that will generate SQL output. Print
** the result columns, comma-separated, on a line and then add a
** semicolon terminator to the end of that line.
**
|
| ︙ | ︙ | |||
13628 13629 13630 13631 13632 13633 13634 |
sqlite3_stmt *pSelect;
int rc;
int nResult;
int i;
const char *z;
rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
if( rc!=SQLITE_OK || !pSelect ){
| > | | > | 13657 13658 13659 13660 13661 13662 13663 13664 13665 13666 13667 13668 13669 13670 13671 13672 13673 13674 |
sqlite3_stmt *pSelect;
int rc;
int nResult;
int i;
const char *z;
rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
if( rc!=SQLITE_OK || !pSelect ){
char *zContext = shell_error_context(zSelect, p->db);
utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n%s", rc,
sqlite3_errmsg(p->db), zContext);
sqlite3_free(zContext);
if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
return rc;
}
rc = sqlite3_step(pSelect);
nResult = sqlite3_column_count(pSelect);
while( rc==SQLITE_ROW ){
z = (const char*)sqlite3_column_text(pSelect, 0);
|
| ︙ | ︙ | |||
13660 13661 13662 13663 13664 13665 13666 |
sqlite3_errmsg(p->db));
if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
}
return rc;
}
/*
| | | > > > < | > | > | < > > | | 13691 13692 13693 13694 13695 13696 13697 13698 13699 13700 13701 13702 13703 13704 13705 13706 13707 13708 13709 13710 13711 13712 13713 13714 13715 13716 13717 13718 13719 13720 |
sqlite3_errmsg(p->db));
if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
}
return rc;
}
/*
** Allocate space and save off string indicating current error.
*/
static char *save_err_msg(
sqlite3 *db, /* Database to query */
const char *zWhen, /* Qualifier (format) wrapper */
int rc, /* Error code returned from API */
const char *zSql /* SQL string, or NULL */
){
char *zErr;
char *zContext;
if( zWhen==0 ) zWhen = "%s (%d)%s";
zContext = shell_error_context(zSql, db);
zErr = sqlite3_mprintf(zWhen, sqlite3_errmsg(db), rc, zContext);
shell_check_oom(zErr);
sqlite3_free(zContext);
return zErr;
}
#ifdef __linux__
/*
** Attempt to display I/O stats on Linux using /proc/PID/io
*/
static void displayLinuxIoStats(FILE *out){
|
| ︙ | ︙ | |||
13848 13849 13850 13851 13852 13853 13854 13855 13856 13857 13858 13859 13860 13861 13862 13863 13864 13865 13866 13867 13868 |
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",
iCur);
}
if( pArg->pStmt ){
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
bReset);
raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
raw_printf(pArg->out, "Sort Operations: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
raw_printf(pArg->out, "Reprepare operations: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
raw_printf(pArg->out, "Number of times run: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
| > > > > > > > | 13884 13885 13886 13887 13888 13889 13890 13891 13892 13893 13894 13895 13896 13897 13898 13899 13900 13901 13902 13903 13904 13905 13906 13907 13908 13909 13910 13911 |
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",
iCur);
}
if( pArg->pStmt ){
int iHit, iMiss;
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
bReset);
raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
raw_printf(pArg->out, "Sort Operations: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur);
iHit = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_HIT, bReset);
iMiss = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_MISS, bReset);
if( iHit || iMiss ){
raw_printf(pArg->out, "Bloom filter bypass taken: %d/%d\n",
iHit, iHit+iMiss);
}
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
raw_printf(pArg->out, "Reprepare operations: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
raw_printf(pArg->out, "Number of times run: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
|
| ︙ | ︙ | |||
14011 14012 14013 14014 14015 14016 14017 |
sqlite3_reset(pSql);
return;
}
}
}
nAlloc += 100;
p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
| | | | 14054 14055 14056 14057 14058 14059 14060 14061 14062 14063 14064 14065 14066 14067 14068 14069 14070 |
sqlite3_reset(pSql);
return;
}
}
}
nAlloc += 100;
p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
shell_check_oom(p->aiIndent);
abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
shell_check_oom(abYield);
}
abYield[iOp] = str_in_array(zOp, azYield);
p->aiIndent[iOp] = 0;
p->nIndent = iOp+1;
if( str_in_array(zOp, azNext) ){
for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
|
| ︙ | ︙ | |||
14222 14223 14224 14225 14226 14227 14228 | rc = sqlite3_step(pStmt); if( rc!=SQLITE_ROW ) return; nColumn = sqlite3_column_count(pStmt); nAlloc = nColumn*4; if( nAlloc<=0 ) nAlloc = 1; azData = sqlite3_malloc64( nAlloc*sizeof(char*) ); | | | | | 14265 14266 14267 14268 14269 14270 14271 14272 14273 14274 14275 14276 14277 14278 14279 14280 14281 14282 14283 14284 14285 14286 14287 14288 14289 14290 14291 14292 14293 14294 14295 14296 14297 |
rc = sqlite3_step(pStmt);
if( rc!=SQLITE_ROW ) return;
nColumn = sqlite3_column_count(pStmt);
nAlloc = nColumn*4;
if( nAlloc<=0 ) nAlloc = 1;
azData = sqlite3_malloc64( nAlloc*sizeof(char*) );
shell_check_oom(azData);
for(i=0; i<nColumn; i++){
azData[i] = strdup(sqlite3_column_name(pStmt,i));
}
do{
if( (nRow+2)*nColumn >= nAlloc ){
nAlloc *= 2;
azData = sqlite3_realloc64(azData, nAlloc*sizeof(char*));
shell_check_oom(azData);
}
nRow++;
for(i=0; i<nColumn; i++){
z = (const char*)sqlite3_column_text(pStmt,i);
azData[nRow*nColumn + i] = z ? strdup(z) : 0;
}
}while( sqlite3_step(pStmt)==SQLITE_ROW );
if( nColumn>p->nWidth ){
p->colWidth = realloc(p->colWidth, (nColumn+1)*2*sizeof(int));
shell_check_oom(p->colWidth);
for(i=p->nWidth; i<nColumn; i++) p->colWidth[i] = 0;
p->nWidth = nColumn;
p->actualWidth = &p->colWidth[nColumn];
}
memset(p->actualWidth, 0, nColumn*sizeof(int));
for(i=0; i<nColumn; i++){
w = p->colWidth[i];
|
| ︙ | ︙ | |||
14361 14362 14363 14364 14365 14366 14367 14368 14369 14370 14371 14372 14373 14374 |
** Run a prepared statement
*/
static void exec_prepared_stmt(
ShellState *pArg, /* Pointer to ShellState */
sqlite3_stmt *pStmt /* Statment to run */
){
int rc;
if( pArg->cMode==MODE_Column
|| pArg->cMode==MODE_Table
|| pArg->cMode==MODE_Box
|| pArg->cMode==MODE_Markdown
){
exec_prepared_stmt_columnar(pArg, pStmt);
| > | 14404 14405 14406 14407 14408 14409 14410 14411 14412 14413 14414 14415 14416 14417 14418 |
** Run a prepared statement
*/
static void exec_prepared_stmt(
ShellState *pArg, /* Pointer to ShellState */
sqlite3_stmt *pStmt /* Statment to run */
){
int rc;
sqlite3_uint64 nRow = 0;
if( pArg->cMode==MODE_Column
|| pArg->cMode==MODE_Table
|| pArg->cMode==MODE_Box
|| pArg->cMode==MODE_Markdown
){
exec_prepared_stmt_columnar(pArg, pStmt);
|
| ︙ | ︙ | |||
14393 14394 14395 14396 14397 14398 14399 14400 14401 14402 |
int i, x;
assert(sizeof(int) <= sizeof(char *));
/* save off ptrs to column names */
for(i=0; i<nCol; i++){
azCols[i] = (char *)sqlite3_column_name(pStmt, i);
}
do{
/* extract the data and data types */
for(i=0; i<nCol; i++){
aiTypes[i] = x = sqlite3_column_type(pStmt, i);
| > | > > > | 14437 14438 14439 14440 14441 14442 14443 14444 14445 14446 14447 14448 14449 14450 14451 14452 14453 14454 14455 14456 14457 14458 |
int i, x;
assert(sizeof(int) <= sizeof(char *));
/* save off ptrs to column names */
for(i=0; i<nCol; i++){
azCols[i] = (char *)sqlite3_column_name(pStmt, i);
}
do{
nRow++;
/* extract the data and data types */
for(i=0; i<nCol; i++){
aiTypes[i] = x = sqlite3_column_type(pStmt, i);
if( x==SQLITE_BLOB
&& pArg
&& (pArg->cMode==MODE_Insert || pArg->cMode==MODE_Quote)
){
azVals[i] = "";
}else{
azVals[i] = (char*)sqlite3_column_text(pStmt, i);
}
if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
rc = SQLITE_NOMEM;
break; /* from for */
|
| ︙ | ︙ | |||
14420 14421 14422 14423 14424 14425 14426 14427 14428 14429 14430 14431 14432 14433 |
rc = sqlite3_step(pStmt);
}
}
} while( SQLITE_ROW == rc );
sqlite3_free(pData);
if( pArg->cMode==MODE_Json ){
fputs("]\n", pArg->out);
}
}
}
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
| > > > > > | 14468 14469 14470 14471 14472 14473 14474 14475 14476 14477 14478 14479 14480 14481 14482 14483 14484 14485 14486 |
rc = sqlite3_step(pStmt);
}
}
} while( SQLITE_ROW == rc );
sqlite3_free(pData);
if( pArg->cMode==MODE_Json ){
fputs("]\n", pArg->out);
}else if( pArg->cMode==MODE_Count ){
char zBuf[200];
sqlite3_snprintf(sizeof(zBuf), zBuf, "%llu row%s\n",
nRow, nRow!=1 ? "s" : "");
printf("%s", zBuf);
}
}
}
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
|
| ︙ | ︙ | |||
14543 14544 14545 14546 14547 14548 14549 |
rc = SQLITE_ERROR;
}
}
if( rc==SQLITE_OK ){
pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
if( pState->expert.pExpert==0 ){
| | > | 14596 14597 14598 14599 14600 14601 14602 14603 14604 14605 14606 14607 14608 14609 14610 14611 14612 14613 14614 14615 14616 14617 14618 |
rc = SQLITE_ERROR;
}
}
if( rc==SQLITE_OK ){
pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
if( pState->expert.pExpert==0 ){
raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr ? zErr : "out of memory");
rc = SQLITE_ERROR;
}else{
sqlite3_expert_config(
pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample
);
}
}
sqlite3_free(zErr);
return rc;
}
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
/*
** Execute a statement or set of statements. Print
|
| ︙ | ︙ | |||
14592 14593 14594 14595 14596 14597 14598 |
#endif
while( zSql[0] && (SQLITE_OK == rc) ){
static const char *zStmtSql;
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
if( SQLITE_OK != rc ){
if( pzErrMsg ){
| | | 14646 14647 14648 14649 14650 14651 14652 14653 14654 14655 14656 14657 14658 14659 14660 |
#endif
while( zSql[0] && (SQLITE_OK == rc) ){
static const char *zStmtSql;
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
if( SQLITE_OK != rc ){
if( pzErrMsg ){
*pzErrMsg = save_err_msg(db, "in prepare, %s (%d)%s", rc, zSql);
}
}else{
if( !pStmt ){
/* this happens for a comment or white-space */
zSql = zLeftover;
while( IsSpace(zSql[0]) ) zSql++;
continue;
|
| ︙ | ︙ | |||
14627 14628 14629 14630 14631 14632 14633 14634 14635 14636 14637 14638 14639 14640 14641 14642 14643 14644 14645 14646 14647 14648 14649 14650 14651 14652 14653 14654 14655 14656 14657 |
int triggerEQP = 0;
disable_debug_trace_modes();
sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
if( pArg->autoEQP>=AUTOEQP_trigger ){
sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
}
zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
if( rc==SQLITE_OK ){
while( sqlite3_step(pExplain)==SQLITE_ROW ){
const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
int iEqpId = sqlite3_column_int(pExplain, 0);
int iParentId = sqlite3_column_int(pExplain, 1);
if( zEQPLine==0 ) zEQPLine = "";
if( zEQPLine[0]=='-' ) eqp_render(pArg);
eqp_append(pArg, iEqpId, iParentId, zEQPLine);
}
eqp_render(pArg);
}
sqlite3_finalize(pExplain);
sqlite3_free(zEQP);
if( pArg->autoEQP>=AUTOEQP_full ){
/* Also do an EXPLAIN for ".eqp full" mode */
zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);
rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
if( rc==SQLITE_OK ){
pArg->cMode = MODE_Explain;
explain_data_prepare(pArg, pExplain);
exec_prepared_stmt(pArg, pExplain);
explain_data_delete(pArg);
}
| > > | 14681 14682 14683 14684 14685 14686 14687 14688 14689 14690 14691 14692 14693 14694 14695 14696 14697 14698 14699 14700 14701 14702 14703 14704 14705 14706 14707 14708 14709 14710 14711 14712 14713 |
int triggerEQP = 0;
disable_debug_trace_modes();
sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
if( pArg->autoEQP>=AUTOEQP_trigger ){
sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
}
zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
shell_check_oom(zEQP);
rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
if( rc==SQLITE_OK ){
while( sqlite3_step(pExplain)==SQLITE_ROW ){
const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
int iEqpId = sqlite3_column_int(pExplain, 0);
int iParentId = sqlite3_column_int(pExplain, 1);
if( zEQPLine==0 ) zEQPLine = "";
if( zEQPLine[0]=='-' ) eqp_render(pArg);
eqp_append(pArg, iEqpId, iParentId, zEQPLine);
}
eqp_render(pArg);
}
sqlite3_finalize(pExplain);
sqlite3_free(zEQP);
if( pArg->autoEQP>=AUTOEQP_full ){
/* Also do an EXPLAIN for ".eqp full" mode */
zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);
shell_check_oom(zEQP);
rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
if( rc==SQLITE_OK ){
pArg->cMode = MODE_Explain;
explain_data_prepare(pArg, pExplain);
exec_prepared_stmt(pArg, pExplain);
explain_data_delete(pArg);
}
|
| ︙ | ︙ | |||
14706 14707 14708 14709 14710 14711 14712 |
** next statement to execute. */
rc2 = sqlite3_finalize(pStmt);
if( rc!=SQLITE_NOMEM ) rc = rc2;
if( rc==SQLITE_OK ){
zSql = zLeftover;
while( IsSpace(zSql[0]) ) zSql++;
}else if( pzErrMsg ){
| | | 14762 14763 14764 14765 14766 14767 14768 14769 14770 14771 14772 14773 14774 14775 14776 |
** next statement to execute. */
rc2 = sqlite3_finalize(pStmt);
if( rc!=SQLITE_NOMEM ) rc = rc2;
if( rc==SQLITE_OK ){
zSql = zLeftover;
while( IsSpace(zSql[0]) ) zSql++;
}else if( pzErrMsg ){
*pzErrMsg = save_err_msg(db, "stepping, %s (%d)", rc, 0);
}
/* clear saved stmt handle */
if( pArg ){
pArg->pStmt = NULL;
}
}
|
| ︙ | ︙ | |||
14756 14757 14758 14759 14760 14761 14762 14763 14764 14765 14766 14767 14768 14769 |
int nAlloc = 0;
int nPK = 0; /* Number of PRIMARY KEY columns seen */
int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */
int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid);
int rc;
zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
if( rc ) return 0;
while( sqlite3_step(pStmt)==SQLITE_ROW ){
if( nCol>=nAlloc-2 ){
nAlloc = nAlloc*2 + nCol + 10;
azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
| > | > | 14812 14813 14814 14815 14816 14817 14818 14819 14820 14821 14822 14823 14824 14825 14826 14827 14828 14829 14830 14831 14832 14833 14834 14835 14836 14837 |
int nAlloc = 0;
int nPK = 0; /* Number of PRIMARY KEY columns seen */
int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */
int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid);
int rc;
zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
shell_check_oom(zSql);
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
if( rc ) return 0;
while( sqlite3_step(pStmt)==SQLITE_ROW ){
if( nCol>=nAlloc-2 ){
nAlloc = nAlloc*2 + nCol + 10;
azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
shell_check_oom(azCol);
}
azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
shell_check_oom(azCol[nCol]);
if( sqlite3_column_int(pStmt, 5) ){
nPK++;
if( nPK==1
&& sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
"INTEGER")==0
){
isIPK = 1;
|
| ︙ | ︙ | |||
14799 14800 14801 14802 14803 14804 14805 14806 14807 14808 14809 14810 14811 14812 |
** table or a INTEGER PRIMARY KEY DESC column, neither of which are
** ROWID aliases. To distinguish these cases, check to see if
** there is a "pk" entry in "PRAGMA index_list". There will be
** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
*/
zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
" WHERE origin='pk'", zTab);
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
if( rc ){
freeColumnList(azCol);
return 0;
}
rc = sqlite3_step(pStmt);
| > | 14857 14858 14859 14860 14861 14862 14863 14864 14865 14866 14867 14868 14869 14870 14871 |
** table or a INTEGER PRIMARY KEY DESC column, neither of which are
** ROWID aliases. To distinguish these cases, check to see if
** there is a "pk" entry in "PRAGMA index_list". There will be
** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
*/
zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
" WHERE origin='pk'", zTab);
shell_check_oom(zSql);
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
if( rc ){
freeColumnList(azCol);
return 0;
}
rc = sqlite3_step(pStmt);
|
| ︙ | ︙ | |||
14890 14891 14892 14893 14894 14895 14896 14897 14898 14899 14900 14901 14902 14903 |
raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
p->writableSchema = 1;
}
zIns = sqlite3_mprintf(
"INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)"
"VALUES('table','%q','%q',0,'%q');",
zTable, zTable, zSql);
utf8_printf(p->out, "%s\n", zIns);
sqlite3_free(zIns);
return 0;
}else{
printSchemaLine(p->out, zSql, ";\n");
}
| > | 14949 14950 14951 14952 14953 14954 14955 14956 14957 14958 14959 14960 14961 14962 14963 |
raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
p->writableSchema = 1;
}
zIns = sqlite3_mprintf(
"INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)"
"VALUES('table','%q','%q',0,'%q');",
zTable, zTable, zSql);
shell_check_oom(zIns);
utf8_printf(p->out, "%s\n", zIns);
sqlite3_free(zIns);
return 0;
}else{
printSchemaLine(p->out, zSql, ";\n");
}
|
| ︙ | ︙ | |||
15020 15021 15022 15023 15024 15025 15026 15027 15028 15029 15030 15031 15032 15033 15034 15035 15036 15037 15038 15039 15040 |
static const char *(azHelp[]) = {
#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
".archive ... Manage SQL archives",
" Each command must have exactly one of the following options:",
" -c, --create Create a new archive",
" -u, --update Add or update files with changed mtime",
" -i, --insert Like -u but always add even if unchanged",
" -t, --list List contents of archive",
" -x, --extract Extract files from archive",
" Optional arguments:",
" -v, --verbose Print each filename as it is processed",
" -f FILE, --file FILE Use archive FILE (default is current db)",
" -a FILE, --append FILE Open FILE using the apndvfs VFS",
" -C DIR, --directory DIR Read/extract files from directory DIR",
" -n, --dryrun Show the SQL that would have occurred",
" Examples:",
" .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar",
" .ar -tf ARCHIVE # List members of ARCHIVE",
" .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE",
" See also:",
" http://sqlite.org/cli.html#sqlite_archive_support",
| > > | 15080 15081 15082 15083 15084 15085 15086 15087 15088 15089 15090 15091 15092 15093 15094 15095 15096 15097 15098 15099 15100 15101 15102 |
static const char *(azHelp[]) = {
#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
".archive ... Manage SQL archives",
" Each command must have exactly one of the following options:",
" -c, --create Create a new archive",
" -u, --update Add or update files with changed mtime",
" -i, --insert Like -u but always add even if unchanged",
" -r, --remove Remove files from archive",
" -t, --list List contents of archive",
" -x, --extract Extract files from archive",
" Optional arguments:",
" -v, --verbose Print each filename as it is processed",
" -f FILE, --file FILE Use archive FILE (default is current db)",
" -a FILE, --append FILE Open FILE using the apndvfs VFS",
" -C DIR, --directory DIR Read/extract files from directory DIR",
" -g, --glob Use glob matching for names in archive",
" -n, --dryrun Show the SQL that would have occurred",
" Examples:",
" .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar",
" .ar -tf ARCHIVE # List members of ARCHIVE",
" .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE",
" See also:",
" http://sqlite.org/cli.html#sqlite_archive_support",
|
| ︙ | ︙ | |||
15131 15132 15133 15134 15135 15136 15137 | ".nonce STRING Disable safe mode for one command if the nonce matches", ".nullvalue STRING Use STRING in place of NULL values", ".once ?OPTIONS? ?FILE? Output for the next SQL command only to FILE", " If FILE begins with '|' then open as a pipe", " --bom Put a UTF8 byte-order mark at the beginning", " -e Send output to the system text editor", " -x Send output as CSV to a spreadsheet (same as \".excel\")", | < < < | 15193 15194 15195 15196 15197 15198 15199 15200 15201 15202 15203 15204 15205 15206 | ".nonce STRING Disable safe mode for one command if the nonce matches", ".nullvalue STRING Use STRING in place of NULL values", ".once ?OPTIONS? ?FILE? Output for the next SQL command only to FILE", " If FILE begins with '|' then open as a pipe", " --bom Put a UTF8 byte-order mark at the beginning", " -e Send output to the system text editor", " -x Send output as CSV to a spreadsheet (same as \".excel\")", ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE", " Options:", " --append Use appendvfs to append database to the end of FILE", #ifndef SQLITE_OMIT_DESERIALIZE " --deserialize Load into memory using sqlite3_deserialize()", " --hexdb Load the output of \"dbtotxt\" as an in-memory db", " --maxsize N Maximum size for --hexdb or --deserialized database", |
| ︙ | ︙ | |||
15169 15170 15171 15172 15173 15174 15175 | " --limit N Interrupt after N progress callbacks", " --once Do no more than one progress interrupt", " --quiet|-q No output except at interrupts", " --reset Reset the count for each input and interrupt", #endif ".prompt MAIN CONTINUE Replace the standard prompts", ".quit Exit this program", | | > | 15228 15229 15230 15231 15232 15233 15234 15235 15236 15237 15238 15239 15240 15241 15242 15243 | " --limit N Interrupt after N progress callbacks", " --once Do no more than one progress interrupt", " --quiet|-q No output except at interrupts", " --reset Reset the count for each input and interrupt", #endif ".prompt MAIN CONTINUE Replace the standard prompts", ".quit Exit this program", ".read FILE Read input from FILE or command output", " If FILE begins with \"|\", it is a command that generates the input.", #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) ".recover Recover as much data as possible from corrupt db.", " --freelist-corrupt Assume the freelist is corrupt", " --recovery-db NAME Store recovery metadata in database file NAME", " --lost-and-found TABLE Alternative name for the lost-and-found table", " --no-rowids Do not attempt to recover rowid values", " that are not also INTEGER PRIMARY KEYs", |
| ︙ | ︙ | |||
15289 15290 15291 15292 15293 15294 15295 15296 15297 15298 15299 15300 15301 15302 |
utf8_printf(out, "%s\n", azHelp[i]);
n++;
}
}
}else{
/* Look for commands that for which zPattern is an exact prefix */
zPat = sqlite3_mprintf(".%s*", zPattern);
for(i=0; i<ArraySize(azHelp); i++){
if( sqlite3_strglob(zPat, azHelp[i])==0 ){
utf8_printf(out, "%s\n", azHelp[i]);
j = i+1;
n++;
}
}
| > | 15349 15350 15351 15352 15353 15354 15355 15356 15357 15358 15359 15360 15361 15362 15363 |
utf8_printf(out, "%s\n", azHelp[i]);
n++;
}
}
}else{
/* Look for commands that for which zPattern is an exact prefix */
zPat = sqlite3_mprintf(".%s*", zPattern);
shell_check_oom(zPat);
for(i=0; i<ArraySize(azHelp); i++){
if( sqlite3_strglob(zPat, azHelp[i])==0 ){
utf8_printf(out, "%s\n", azHelp[i]);
j = i+1;
n++;
}
}
|
| ︙ | ︙ | |||
15311 15312 15313 15314 15315 15316 15317 15318 15319 15320 15321 15322 15323 15324 |
}
}
return n;
}
/* Look for commands that contain zPattern anywhere. Show the complete
** text of all commands that match. */
zPat = sqlite3_mprintf("%%%s%%", zPattern);
for(i=0; i<ArraySize(azHelp); i++){
if( azHelp[i][0]=='.' ) j = i;
if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
utf8_printf(out, "%s\n", azHelp[j]);
while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){
j++;
utf8_printf(out, "%s\n", azHelp[j]);
| > | 15372 15373 15374 15375 15376 15377 15378 15379 15380 15381 15382 15383 15384 15385 15386 |
}
}
return n;
}
/* Look for commands that contain zPattern anywhere. Show the complete
** text of all commands that match. */
zPat = sqlite3_mprintf("%%%s%%", zPattern);
shell_check_oom(zPat);
for(i=0; i<ArraySize(azHelp); i++){
if( azHelp[i][0]=='.' ) j = i;
if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
utf8_printf(out, "%s\n", azHelp[j]);
while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){
j++;
utf8_printf(out, "%s\n", azHelp[j]);
|
| ︙ | ︙ | |||
15499 15500 15501 15502 15503 15504 15505 | if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error; rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz); if( rc!=2 ) goto readHexDb_error; if( n<0 ) goto readHexDb_error; if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error; n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */ a = sqlite3_malloc( n ? n : 1 ); | | < < < | 15561 15562 15563 15564 15565 15566 15567 15568 15569 15570 15571 15572 15573 15574 15575 |
if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
if( rc!=2 ) goto readHexDb_error;
if( n<0 ) goto readHexDb_error;
if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error;
n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */
a = sqlite3_malloc( n ? n : 1 );
shell_check_oom(a);
memset(a, 0, n);
if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
utf8_printf(stderr, "invalid pagesize\n");
goto readHexDb_error;
}
for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){
rc = sscanf(zLine, "| page %d offset %d", &j, &k);
|
| ︙ | ︙ | |||
15633 15634 15635 15636 15637 15638 15639 |
static void shellEscapeCrnl(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const char *zText = (const char*)sqlite3_value_text(argv[0]);
UNUSED_PARAMETER(argc);
| | | 15692 15693 15694 15695 15696 15697 15698 15699 15700 15701 15702 15703 15704 15705 15706 |
static void shellEscapeCrnl(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const char *zText = (const char*)sqlite3_value_text(argv[0]);
UNUSED_PARAMETER(argc);
if( zText && zText[0]=='\'' ){
int nText = sqlite3_value_bytes(argv[0]);
int i;
char zBuf1[20];
char zBuf2[20];
const char *zNL = 0;
const char *zCR = 0;
int nCR = 0;
|
| ︙ | ︙ | |||
15810 15811 15812 15813 15814 15815 15816 15817 15818 15819 15820 15821 15822 15823 |
editFunc, 0, 0);
sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
editFunc, 0, 0);
#endif
if( p->openMode==SHELL_OPEN_ZIPFILE ){
char *zSql = sqlite3_mprintf(
"CREATE VIRTUAL TABLE zip USING zipfile(%Q);", zDbFilename);
sqlite3_exec(p->db, zSql, 0, 0, 0);
sqlite3_free(zSql);
}
#ifndef SQLITE_OMIT_DESERIALIZE
else
if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
int rc;
| > | 15869 15870 15871 15872 15873 15874 15875 15876 15877 15878 15879 15880 15881 15882 15883 |
editFunc, 0, 0);
sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
editFunc, 0, 0);
#endif
if( p->openMode==SHELL_OPEN_ZIPFILE ){
char *zSql = sqlite3_mprintf(
"CREATE VIRTUAL TABLE zip USING zipfile(%Q);", zDbFilename);
shell_check_oom(zSql);
sqlite3_exec(p->db, zSql, 0, 0, 0);
sqlite3_free(zSql);
}
#ifndef SQLITE_OMIT_DESERIALIZE
else
if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
int rc;
|
| ︙ | ︙ | |||
15867 15868 15869 15870 15871 15872 15873 15874 15875 15876 15877 |
static sqlite3_stmt *pStmt = 0;
char *zRet;
if( state==0 ){
char *zSql;
sqlite3_finalize(pStmt);
zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
" FROM completion(%Q) ORDER BY 1", text);
sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
}
if( sqlite3_step(pStmt)==SQLITE_ROW ){
| > | > | 15927 15928 15929 15930 15931 15932 15933 15934 15935 15936 15937 15938 15939 15940 15941 15942 15943 15944 15945 15946 15947 |
static sqlite3_stmt *pStmt = 0;
char *zRet;
if( state==0 ){
char *zSql;
sqlite3_finalize(pStmt);
zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
" FROM completion(%Q) ORDER BY 1", text);
shell_check_oom(zSql);
sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
}
if( sqlite3_step(pStmt)==SQLITE_ROW ){
const char *z = (const char*)sqlite3_column_text(pStmt,0);
zRet = z ? strdup(z) : 0;
}else{
sqlite3_finalize(pStmt);
pStmt = 0;
zRet = 0;
}
return zRet;
}
|
| ︙ | ︙ | |||
15904 15905 15906 15907 15908 15909 15910 15911 15912 15913 15914 15915 15916 |
for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
if( i==nLine-1 ) return;
iStart = i+1;
memcpy(zBuf, zLine, iStart);
zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
" FROM completion(%Q,%Q) ORDER BY 1",
&zLine[iStart], zLine);
sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */
while( sqlite3_step(pStmt)==SQLITE_ROW ){
const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0);
int nCompletion = sqlite3_column_bytes(pStmt, 0);
| > | | 15966 15967 15968 15969 15970 15971 15972 15973 15974 15975 15976 15977 15978 15979 15980 15981 15982 15983 15984 15985 15986 15987 |
for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
if( i==nLine-1 ) return;
iStart = i+1;
memcpy(zBuf, zLine, iStart);
zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
" FROM completion(%Q,%Q) ORDER BY 1",
&zLine[iStart], zLine);
shell_check_oom(zSql);
sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */
while( sqlite3_step(pStmt)==SQLITE_ROW ){
const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0);
int nCompletion = sqlite3_column_bytes(pStmt, 0);
if( iStart+nCompletion < sizeof(zBuf)-1 && zCompletion ){
memcpy(zBuf+iStart, zCompletion, nCompletion+1);
linenoiseAddCompletion(lc, zBuf);
}
}
sqlite3_finalize(pStmt);
}
#endif
|
| ︙ | ︙ | |||
16145 16146 16147 16148 16149 16150 16151 |
}
/* Append a single byte to z[] */
static void import_append_char(ImportCtx *p, int c){
if( p->n+1>=p->nAlloc ){
p->nAlloc += p->nAlloc + 100;
p->z = sqlite3_realloc64(p->z, p->nAlloc);
| | | 16208 16209 16210 16211 16212 16213 16214 16215 16216 16217 16218 16219 16220 16221 16222 |
}
/* Append a single byte to z[] */
static void import_append_char(ImportCtx *p, int c){
if( p->n+1>=p->nAlloc ){
p->nAlloc += p->nAlloc + 100;
p->z = sqlite3_realloc64(p->z, p->nAlloc);
shell_check_oom(p->z);
}
p->z[p->n++] = (char)c;
}
/* Read a single field of CSV text. Compatible with rfc4180 and extended
** with the option of having a separator other than ",".
**
|
| ︙ | ︙ | |||
16297 16298 16299 16300 16301 16302 16303 16304 16305 16306 16307 16308 16309 16310 16311 16312 |
int i, j, n;
int nTable = strlen30(zTable);
int k = 0;
int cnt = 0;
const int spinRate = 10000;
zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
if( rc ){
utf8_printf(stderr, "Error %d: %s on [%s]\n",
sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
zQuery);
goto end_data_xfer;
}
n = sqlite3_column_count(pQuery);
zInsert = sqlite3_malloc64(200 + nTable + n*3);
| > | | 16360 16361 16362 16363 16364 16365 16366 16367 16368 16369 16370 16371 16372 16373 16374 16375 16376 16377 16378 16379 16380 16381 16382 16383 16384 |
int i, j, n;
int nTable = strlen30(zTable);
int k = 0;
int cnt = 0;
const int spinRate = 10000;
zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
shell_check_oom(zQuery);
rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
if( rc ){
utf8_printf(stderr, "Error %d: %s on [%s]\n",
sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
zQuery);
goto end_data_xfer;
}
n = sqlite3_column_count(pQuery);
zInsert = sqlite3_malloc64(200 + nTable + n*3);
shell_check_oom(zInsert);
sqlite3_snprintf(200+nTable,zInsert,
"INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
i = strlen30(zInsert);
for(j=1; j<n; j++){
memcpy(zInsert+i, ",?", 2);
i += 2;
}
|
| ︙ | ︙ | |||
16369 16370 16371 16372 16373 16374 16375 16376 16377 16378 16379 16380 16381 16382 |
}
} /* End while */
if( rc==SQLITE_DONE ) break;
sqlite3_finalize(pQuery);
sqlite3_free(zQuery);
zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
zTable);
rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
if( rc ){
utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
break;
}
} /* End for(k=0...) */
| > | 16433 16434 16435 16436 16437 16438 16439 16440 16441 16442 16443 16444 16445 16446 16447 |
}
} /* End while */
if( rc==SQLITE_DONE ) break;
sqlite3_finalize(pQuery);
sqlite3_free(zQuery);
zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
zTable);
shell_check_oom(zQuery);
rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
if( rc ){
utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
break;
}
} /* End for(k=0...) */
|
| ︙ | ︙ | |||
16405 16406 16407 16408 16409 16410 16411 16412 16413 16414 16415 16416 16417 16418 16419 16420 16421 16422 16423 16424 16425 16426 16427 16428 16429 16430 16431 16432 16433 16434 16435 16436 16437 16438 16439 16440 16441 16442 16443 16444 16445 16446 16447 16448 16449 16450 16451 16452 16453 16454 16455 |
int rc;
const unsigned char *zName;
const unsigned char *zSql;
char *zErrMsg = 0;
zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
" WHERE %s", zWhere);
rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
if( rc ){
utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
zQuery);
goto end_schema_xfer;
}
while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
zName = sqlite3_column_text(pQuery, 0);
zSql = sqlite3_column_text(pQuery, 1);
printf("%s... ", zName); fflush(stdout);
sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
if( zErrMsg ){
utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
sqlite3_free(zErrMsg);
zErrMsg = 0;
}
if( xForEach ){
xForEach(p, newDb, (const char*)zName);
}
printf("done\n");
}
if( rc!=SQLITE_DONE ){
sqlite3_finalize(pQuery);
sqlite3_free(zQuery);
zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
" WHERE %s ORDER BY rowid DESC", zWhere);
rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
if( rc ){
utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
zQuery);
goto end_schema_xfer;
}
while( sqlite3_step(pQuery)==SQLITE_ROW ){
zName = sqlite3_column_text(pQuery, 0);
zSql = sqlite3_column_text(pQuery, 1);
printf("%s... ", zName); fflush(stdout);
sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
if( zErrMsg ){
utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
sqlite3_free(zErrMsg);
zErrMsg = 0;
}
| > > > > | 16470 16471 16472 16473 16474 16475 16476 16477 16478 16479 16480 16481 16482 16483 16484 16485 16486 16487 16488 16489 16490 16491 16492 16493 16494 16495 16496 16497 16498 16499 16500 16501 16502 16503 16504 16505 16506 16507 16508 16509 16510 16511 16512 16513 16514 16515 16516 16517 16518 16519 16520 16521 16522 16523 16524 |
int rc;
const unsigned char *zName;
const unsigned char *zSql;
char *zErrMsg = 0;
zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
" WHERE %s", zWhere);
shell_check_oom(zQuery);
rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
if( rc ){
utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
zQuery);
goto end_schema_xfer;
}
while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
zName = sqlite3_column_text(pQuery, 0);
zSql = sqlite3_column_text(pQuery, 1);
if( zName==0 || zSql==0 ) continue;
printf("%s... ", zName); fflush(stdout);
sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
if( zErrMsg ){
utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
sqlite3_free(zErrMsg);
zErrMsg = 0;
}
if( xForEach ){
xForEach(p, newDb, (const char*)zName);
}
printf("done\n");
}
if( rc!=SQLITE_DONE ){
sqlite3_finalize(pQuery);
sqlite3_free(zQuery);
zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
" WHERE %s ORDER BY rowid DESC", zWhere);
shell_check_oom(zQuery);
rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
if( rc ){
utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
zQuery);
goto end_schema_xfer;
}
while( sqlite3_step(pQuery)==SQLITE_ROW ){
zName = sqlite3_column_text(pQuery, 0);
zSql = sqlite3_column_text(pQuery, 1);
if( zName==0 || zSql==0 ) continue;
printf("%s... ", zName); fflush(stdout);
sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
if( zErrMsg ){
utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
sqlite3_free(zErrMsg);
zErrMsg = 0;
}
|
| ︙ | ︙ | |||
16826 16827 16828 16829 16830 16831 16832 |
zTemp = "/tmp";
#endif
}
p->zTempFile = sqlite3_mprintf("%s/temp%llx.%s", zTemp, r, zSuffix);
}else{
p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
}
| | < < | 16895 16896 16897 16898 16899 16900 16901 16902 16903 16904 16905 16906 16907 16908 16909 |
zTemp = "/tmp";
#endif
}
p->zTempFile = sqlite3_mprintf("%s/temp%llx.%s", zTemp, r, zSuffix);
}else{
p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
}
shell_check_oom(p->zTempFile);
}
/*
** The implementation of SQL scalar function fkey_collate_clause(), used
** by the ".lint fkey-indexes" command. This scalar function is always
** called with four arguments - the parent table name, the parent column name,
|
| ︙ | ︙ | |||
17009 17010 17011 17012 17013 17014 17015 17016 17017 17018 17019 |
const char *zEQP = (const char*)sqlite3_column_text(pSql, 0);
const char *zGlob = (const char*)sqlite3_column_text(pSql, 1);
const char *zFrom = (const char*)sqlite3_column_text(pSql, 2);
const char *zTarget = (const char*)sqlite3_column_text(pSql, 3);
const char *zCI = (const char*)sqlite3_column_text(pSql, 4);
const char *zParent = (const char*)sqlite3_column_text(pSql, 5);
rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
if( rc!=SQLITE_OK ) break;
if( SQLITE_ROW==sqlite3_step(pExplain) ){
const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3);
| > > < | | < | 17076 17077 17078 17079 17080 17081 17082 17083 17084 17085 17086 17087 17088 17089 17090 17091 17092 17093 17094 17095 17096 17097 |
const char *zEQP = (const char*)sqlite3_column_text(pSql, 0);
const char *zGlob = (const char*)sqlite3_column_text(pSql, 1);
const char *zFrom = (const char*)sqlite3_column_text(pSql, 2);
const char *zTarget = (const char*)sqlite3_column_text(pSql, 3);
const char *zCI = (const char*)sqlite3_column_text(pSql, 4);
const char *zParent = (const char*)sqlite3_column_text(pSql, 5);
if( zEQP==0 ) continue;
if( zGlob==0 ) continue;
rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
if( rc!=SQLITE_OK ) break;
if( SQLITE_ROW==sqlite3_step(pExplain) ){
const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3);
res = zPlan!=0 && ( 0==sqlite3_strglob(zGlob, zPlan)
|| 0==sqlite3_strglob(zGlobIPK, zPlan));
}
rc = sqlite3_finalize(pExplain);
if( rc!=SQLITE_OK ) break;
if( res<0 ){
raw_printf(stderr, "Error: internal error");
break;
|
| ︙ | ︙ | |||
17187 17188 17189 17190 17191 17192 17193 17194 17195 17196 17197 17198 17199 17200 |
typedef struct ArCommand ArCommand;
struct ArCommand {
u8 eCmd; /* An AR_CMD_* value */
u8 bVerbose; /* True if --verbose */
u8 bZip; /* True if the archive is a ZIP */
u8 bDryRun; /* True if --dry-run */
u8 bAppend; /* True if --append */
u8 fromCmdLine; /* Run from -A instead of .archive */
int nArg; /* Number of command arguments */
char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
const char *zFile; /* --file argument, or NULL */
const char *zDir; /* --directory argument, or NULL */
char **azArg; /* Array of command arguments */
ShellState *p; /* Shell state */
| > | 17254 17255 17256 17257 17258 17259 17260 17261 17262 17263 17264 17265 17266 17267 17268 |
typedef struct ArCommand ArCommand;
struct ArCommand {
u8 eCmd; /* An AR_CMD_* value */
u8 bVerbose; /* True if --verbose */
u8 bZip; /* True if the archive is a ZIP */
u8 bDryRun; /* True if --dry-run */
u8 bAppend; /* True if --append */
u8 bGlob; /* True if --glob */
u8 fromCmdLine; /* Run from -A instead of .archive */
int nArg; /* Number of command arguments */
char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
const char *zFile; /* --file argument, or NULL */
const char *zDir; /* --directory argument, or NULL */
char **azArg; /* Array of command arguments */
ShellState *p; /* Shell state */
|
| ︙ | ︙ | |||
17234 17235 17236 17237 17238 17239 17240 17241 17242 17243 17244 | */ #define AR_CMD_CREATE 1 #define AR_CMD_UPDATE 2 #define AR_CMD_INSERT 3 #define AR_CMD_EXTRACT 4 #define AR_CMD_LIST 5 #define AR_CMD_HELP 6 /* ** Other (non-command) switches. */ | > | | | | | > > > > > | 17302 17303 17304 17305 17306 17307 17308 17309 17310 17311 17312 17313 17314 17315 17316 17317 17318 17319 17320 17321 17322 17323 17324 17325 17326 17327 17328 17329 17330 17331 17332 17333 17334 17335 17336 17337 17338 17339 17340 17341 17342 17343 17344 17345 17346 17347 |
*/
#define AR_CMD_CREATE 1
#define AR_CMD_UPDATE 2
#define AR_CMD_INSERT 3
#define AR_CMD_EXTRACT 4
#define AR_CMD_LIST 5
#define AR_CMD_HELP 6
#define AR_CMD_REMOVE 7
/*
** Other (non-command) switches.
*/
#define AR_SWITCH_VERBOSE 8
#define AR_SWITCH_FILE 9
#define AR_SWITCH_DIRECTORY 10
#define AR_SWITCH_APPEND 11
#define AR_SWITCH_DRYRUN 12
#define AR_SWITCH_GLOB 13
static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
switch( eSwitch ){
case AR_CMD_CREATE:
case AR_CMD_EXTRACT:
case AR_CMD_LIST:
case AR_CMD_REMOVE:
case AR_CMD_UPDATE:
case AR_CMD_INSERT:
case AR_CMD_HELP:
if( pAr->eCmd ){
return arErrorMsg(pAr, "multiple command options");
}
pAr->eCmd = eSwitch;
break;
case AR_SWITCH_DRYRUN:
pAr->bDryRun = 1;
break;
case AR_SWITCH_GLOB:
pAr->bGlob = 1;
break;
case AR_SWITCH_VERBOSE:
pAr->bVerbose = 1;
break;
case AR_SWITCH_APPEND:
pAr->bAppend = 1;
/* Fall thru into --file */
|
| ︙ | ︙ | |||
17299 17300 17301 17302 17303 17304 17305 17306 17307 17308 17309 17310 17311 17312 17313 17314 17315 17316 17317 17318 17319 |
u8 eSwitch;
u8 bArg;
} aSwitch[] = {
{ "create", 'c', AR_CMD_CREATE, 0 },
{ "extract", 'x', AR_CMD_EXTRACT, 0 },
{ "insert", 'i', AR_CMD_INSERT, 0 },
{ "list", 't', AR_CMD_LIST, 0 },
{ "update", 'u', AR_CMD_UPDATE, 0 },
{ "help", 'h', AR_CMD_HELP, 0 },
{ "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
{ "file", 'f', AR_SWITCH_FILE, 1 },
{ "append", 'a', AR_SWITCH_APPEND, 1 },
{ "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
{ "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
};
int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
struct ArSwitch *pEnd = &aSwitch[nSwitch];
if( nArg<=1 ){
utf8_printf(stderr, "Wrong number of arguments. Usage:\n");
return arUsage(stderr);
| > > | 17373 17374 17375 17376 17377 17378 17379 17380 17381 17382 17383 17384 17385 17386 17387 17388 17389 17390 17391 17392 17393 17394 17395 |
u8 eSwitch;
u8 bArg;
} aSwitch[] = {
{ "create", 'c', AR_CMD_CREATE, 0 },
{ "extract", 'x', AR_CMD_EXTRACT, 0 },
{ "insert", 'i', AR_CMD_INSERT, 0 },
{ "list", 't', AR_CMD_LIST, 0 },
{ "remove", 'r', AR_CMD_REMOVE, 0 },
{ "update", 'u', AR_CMD_UPDATE, 0 },
{ "help", 'h', AR_CMD_HELP, 0 },
{ "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
{ "file", 'f', AR_SWITCH_FILE, 1 },
{ "append", 'a', AR_SWITCH_APPEND, 1 },
{ "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
{ "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
{ "glob", 'g', AR_SWITCH_GLOB, 0 },
};
int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
struct ArSwitch *pEnd = &aSwitch[nSwitch];
if( nArg<=1 ){
utf8_printf(stderr, "Wrong number of arguments. Usage:\n");
return arUsage(stderr);
|
| ︙ | ︙ | |||
17422 17423 17424 17425 17426 17427 17428 | } return SQLITE_OK; } /* ** This function assumes that all arguments within the ArCommand.azArg[] | | | | | | > > > > > | < < < | 17498 17499 17500 17501 17502 17503 17504 17505 17506 17507 17508 17509 17510 17511 17512 17513 17514 17515 17516 17517 17518 17519 17520 17521 17522 17523 17524 17525 17526 17527 17528 17529 17530 17531 17532 17533 |
}
return SQLITE_OK;
}
/*
** This function assumes that all arguments within the ArCommand.azArg[]
** array refer to archive members, as for the --extract, --list or --remove
** commands. It checks that each of them are "present". If any specified
** file is not present in the archive, an error is printed to stderr and an
** error code returned. Otherwise, if all specified arguments are present
** in the archive, SQLITE_OK is returned. Here, "present" means either an
** exact equality when pAr->bGlob is false or a "name GLOB pattern" match
** when pAr->bGlob is true.
**
** This function strips any trailing '/' characters from each argument.
** This is consistent with the way the [tar] command seems to work on
** Linux.
*/
static int arCheckEntries(ArCommand *pAr){
int rc = SQLITE_OK;
if( pAr->nArg ){
int i, j;
sqlite3_stmt *pTest = 0;
const char *zSel = (pAr->bGlob)
? "SELECT name FROM %s WHERE glob($name,name)"
: "SELECT name FROM %s WHERE name=$name";
shellPreparePrintf(pAr->db, &rc, &pTest, zSel, pAr->zSrcTable);
j = sqlite3_bind_parameter_index(pTest, "$name");
for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
char *z = pAr->azArg[i];
int n = strlen30(z);
int bOk = 0;
while( n>0 && z[n-1]=='/' ) n--;
z[n] = '\0';
|
| ︙ | ︙ | |||
17469 17470 17471 17472 17473 17474 17475 | } /* ** Format a WHERE clause that can be used against the "sqlar" table to ** identify all archive members that match the command arguments held ** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning. ** The caller is responsible for eventually calling sqlite3_free() on | | > | > | | | 17547 17548 17549 17550 17551 17552 17553 17554 17555 17556 17557 17558 17559 17560 17561 17562 17563 17564 17565 17566 17567 17568 17569 17570 17571 17572 17573 17574 17575 17576 17577 17578 17579 17580 17581 |
}
/*
** Format a WHERE clause that can be used against the "sqlar" table to
** identify all archive members that match the command arguments held
** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning.
** The caller is responsible for eventually calling sqlite3_free() on
** any non-NULL (*pzWhere) value. Here, "match" means strict equality
** when pAr->bGlob is false and GLOB match when pAr->bGlob is true.
*/
static void arWhereClause(
int *pRc,
ArCommand *pAr,
char **pzWhere /* OUT: New WHERE clause */
){
char *zWhere = 0;
const char *zSameOp = (pAr->bGlob)? "GLOB" : "=";
if( *pRc==SQLITE_OK ){
if( pAr->nArg==0 ){
zWhere = sqlite3_mprintf("1");
}else{
int i;
const char *zSep = "";
for(i=0; i<pAr->nArg; i++){
const char *z = pAr->azArg[i];
zWhere = sqlite3_mprintf(
"%z%s name %s '%q' OR substr(name,1,%d) %s '%q/'",
zWhere, zSep, zSameOp, z, strlen30(z)+1, zSameOp, z
);
if( zWhere==0 ){
*pRc = SQLITE_NOMEM;
break;
}
zSep = " OR ";
}
|
| ︙ | ︙ | |||
17540 17541 17542 17543 17544 17545 17546 17547 17548 17549 17550 17551 17552 17553 |
}
}
shellFinalize(&rc, pSql);
sqlite3_free(zWhere);
return rc;
}
/*
** Implementation of .ar "eXtract" command.
*/
static int arExtractCommand(ArCommand *pAr){
const char *zSql1 =
"SELECT "
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 17620 17621 17622 17623 17624 17625 17626 17627 17628 17629 17630 17631 17632 17633 17634 17635 17636 17637 17638 17639 17640 17641 17642 17643 17644 17645 17646 17647 17648 17649 17650 17651 17652 17653 17654 17655 17656 17657 17658 17659 17660 17661 17662 17663 17664 17665 17666 17667 17668 17669 17670 17671 17672 17673 17674 |
}
}
shellFinalize(&rc, pSql);
sqlite3_free(zWhere);
return rc;
}
/*
** Implementation of .ar "Remove" command.
*/
static int arRemoveCommand(ArCommand *pAr){
int rc = 0;
char *zSql = 0;
char *zWhere = 0;
if( pAr->nArg ){
/* Verify that args actually exist within the archive before proceeding.
** And formulate a WHERE clause to match them. */
rc = arCheckEntries(pAr);
arWhereClause(&rc, pAr, &zWhere);
}
if( rc==SQLITE_OK ){
zSql = sqlite3_mprintf("DELETE FROM %s WHERE %s;",
pAr->zSrcTable, zWhere);
if( pAr->bDryRun ){
utf8_printf(pAr->p->out, "%s\n", zSql);
}else{
char *zErr = 0;
rc = sqlite3_exec(pAr->db, "SAVEPOINT ar;", 0, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
if( rc!=SQLITE_OK ){
sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
}else{
rc = sqlite3_exec(pAr->db, "RELEASE ar;", 0, 0, 0);
}
}
if( zErr ){
utf8_printf(stdout, "ERROR: %s\n", zErr);
sqlite3_free(zErr);
}
}
}
sqlite3_free(zWhere);
sqlite3_free(zSql);
return rc;
}
/*
** Implementation of .ar "eXtract" command.
*/
static int arExtractCommand(ArCommand *pAr){
const char *zSql1 =
"SELECT "
|
| ︙ | ︙ | |||
17793 17794 17795 17796 17797 17798 17799 |
}
}
cmd.bZip = 1;
}else if( cmd.zFile ){
int flags;
if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
| | | 17914 17915 17916 17917 17918 17919 17920 17921 17922 17923 17924 17925 17926 17927 17928 |
}
}
cmd.bZip = 1;
}else if( cmd.zFile ){
int flags;
if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
|| cmd.eCmd==AR_CMD_REMOVE || cmd.eCmd==AR_CMD_UPDATE ){
flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
}else{
flags = SQLITE_OPEN_READONLY;
}
cmd.db = 0;
if( cmd.bDryRun ){
utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
|
| ︙ | ︙ | |||
17848 17849 17850 17851 17852 17853 17854 17855 17856 17857 17858 17859 17860 17861 |
case AR_CMD_HELP:
arUsage(pState->out);
break;
case AR_CMD_INSERT:
rc = arCreateOrUpdateCommand(&cmd, 1, 0);
break;
default:
assert( cmd.eCmd==AR_CMD_UPDATE );
rc = arCreateOrUpdateCommand(&cmd, 1, 1);
break;
}
}
| > > > > | 17969 17970 17971 17972 17973 17974 17975 17976 17977 17978 17979 17980 17981 17982 17983 17984 17985 17986 |
case AR_CMD_HELP:
arUsage(pState->out);
break;
case AR_CMD_INSERT:
rc = arCreateOrUpdateCommand(&cmd, 1, 0);
break;
case AR_CMD_REMOVE:
rc = arRemoveCommand(&cmd);
break;
default:
assert( cmd.eCmd==AR_CMD_UPDATE );
rc = arCreateOrUpdateCommand(&cmd, 1, 1);
break;
}
}
|
| ︙ | ︙ | |||
18063 18064 18065 18066 18067 18068 18069 18070 18071 18072 18073 18074 18075 18076 |
" WHERE pk=1 AND type='integer' COLLATE nocase"
" AND NOT EXISTS (SELECT cid FROM pragma_table_info(%Q) WHERE pk=2)"
, zName, zName
);
if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPkFinder) ){
pTab->iPk = sqlite3_column_int(pPkFinder, 0);
zPk = (const char*)sqlite3_column_text(pPkFinder, 1);
}
}
pTab->zQuoted = shellMPrintf(&rc, "\"%w\"", zName);
pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1));
pTab->nCol = nSqlCol;
| > | 18188 18189 18190 18191 18192 18193 18194 18195 18196 18197 18198 18199 18200 18201 18202 |
" WHERE pk=1 AND type='integer' COLLATE nocase"
" AND NOT EXISTS (SELECT cid FROM pragma_table_info(%Q) WHERE pk=2)"
, zName, zName
);
if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPkFinder) ){
pTab->iPk = sqlite3_column_int(pPkFinder, 0);
zPk = (const char*)sqlite3_column_text(pPkFinder, 1);
if( zPk==0 ){ zPk = "_"; /* Defensive. Should never happen */ }
}
}
pTab->zQuoted = shellMPrintf(&rc, "\"%w\"", zName);
pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1));
pTab->nCol = nSqlCol;
|
| ︙ | ︙ | |||
18147 18148 18149 18150 18151 18152 18153 |
if( bIntkey==0 && sqlite3_stricmp(zType, "index")==0 ){
bNoop = 1;
break;
}
if( sqlite3_stricmp(zType, "table")==0 ){
zName = (const char*)sqlite3_column_text(pStmt, 1);
zSql = (const char*)sqlite3_column_text(pStmt, 2);
| > | | > | 18273 18274 18275 18276 18277 18278 18279 18280 18281 18282 18283 18284 18285 18286 18287 18288 18289 18290 |
if( bIntkey==0 && sqlite3_stricmp(zType, "index")==0 ){
bNoop = 1;
break;
}
if( sqlite3_stricmp(zType, "table")==0 ){
zName = (const char*)sqlite3_column_text(pStmt, 1);
zSql = (const char*)sqlite3_column_text(pStmt, 2);
if( zName!=0 && zSql!=0 ){
pRet = recoverNewTable(pRc, zName, zSql, bIntkey, nCol);
break;
}
}
}
shellFinalize(pRc, pStmt);
*pbNoop = bNoop;
return pRet;
}
|
| ︙ | ︙ | |||
18842 18843 18844 18845 18846 18847 18848 18849 |
if( rc ){
utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
rc = 1;
}else{
while( sqlite3_step(pStmt)==SQLITE_ROW ){
const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*));
| > | | 18970 18971 18972 18973 18974 18975 18976 18977 18978 18979 18980 18981 18982 18983 18984 18985 18986 |
if( rc ){
utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
rc = 1;
}else{
while( sqlite3_step(pStmt)==SQLITE_ROW ){
const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
if( zSchema==0 || zFile==0 ) continue;
azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*));
shell_check_oom(azName);
azName[nName*2] = strdup(zSchema);
azName[nName*2+1] = strdup(zFile);
nName++;
}
}
sqlite3_finalize(pStmt);
for(i=0; i<nName; i++){
|
| ︙ | ︙ | |||
19099 19100 19101 19102 19103 19104 19105 |
if( p->mode==MODE_Explain ) p->mode = p->normalMode;
p->autoExplain = 1;
}
}else
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){
| > > > > > > | | > | 19228 19229 19230 19231 19232 19233 19234 19235 19236 19237 19238 19239 19240 19241 19242 19243 19244 19245 19246 19247 19248 19249 19250 |
if( p->mode==MODE_Explain ) p->mode = p->normalMode;
p->autoExplain = 1;
}
}else
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){
if( p->bSafeMode ){
raw_printf(stderr,
"Cannot run experimental commands such as \"%s\" in safe mode\n",
azArg[0]);
rc = 1;
}else{
open_db(p, 0);
expertDotCommand(p, azArg, nArg);
}
}else
#endif
if( c=='f' && strncmp(azArg[0], "filectrl", n)==0 ){
static const struct {
const char *zCtrlName; /* Name of a test-control option */
int ctrlCode; /* Integer code for that option */
|
| ︙ | ︙ | |||
19337 19338 19339 19340 19341 19342 19343 19344 19345 19346 19347 19348 19349 19350 |
char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
int eVerbose = 0; /* Larger for more console output */
int nSkip = 0; /* Initial lines to skip */
int useOutputMode = 1; /* Use output mode to determine separators */
failIfSafeMode(p, "cannot run .import in safe mode");
memset(&sCtx, 0, sizeof(sCtx));
if( p->mode==MODE_Ascii ){
xRead = ascii_read_one_field;
}else{
xRead = csv_read_one_field;
}
for(i=1; i<nArg; i++){
char *z = azArg[i];
| > > > > > | 19473 19474 19475 19476 19477 19478 19479 19480 19481 19482 19483 19484 19485 19486 19487 19488 19489 19490 19491 |
char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
int eVerbose = 0; /* Larger for more console output */
int nSkip = 0; /* Initial lines to skip */
int useOutputMode = 1; /* Use output mode to determine separators */
failIfSafeMode(p, "cannot run .import in safe mode");
memset(&sCtx, 0, sizeof(sCtx));
sCtx.z = sqlite3_malloc64(120);
if( sCtx.z==0 ){
import_cleanup(&sCtx);
shell_out_of_memory();
}
if( p->mode==MODE_Ascii ){
xRead = ascii_read_one_field;
}else{
xRead = csv_read_one_field;
}
for(i=1; i<nArg; i++){
char *z = azArg[i];
|
| ︙ | ︙ | |||
19446 19447 19448 19449 19450 19451 19452 19453 19454 19455 19456 19457 19458 19459 |
}else{
sCtx.in = fopen(sCtx.zFile, "rb");
sCtx.xCloser = fclose;
}
if( sCtx.in==0 ){
utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
rc = 1;
goto meta_command_exit;
}
if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
char zSep[2];
zSep[1] = 0;
zSep[0] = sCtx.cColSep;
utf8_printf(p->out, "Column separator ");
| > | 19587 19588 19589 19590 19591 19592 19593 19594 19595 19596 19597 19598 19599 19600 19601 |
}else{
sCtx.in = fopen(sCtx.zFile, "rb");
sCtx.xCloser = fclose;
}
if( sCtx.in==0 ){
utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
rc = 1;
import_cleanup(&sCtx);
goto meta_command_exit;
}
if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
char zSep[2];
zSep[1] = 0;
zSep[0] = sCtx.cColSep;
utf8_printf(p->out, "Column separator ");
|
| ︙ | ︙ | |||
19864 19865 19866 19867 19868 19869 19870 19871 19872 19873 19874 19875 19876 19877 19878 19879 19880 19881 19882 19883 19884 19885 19886 19887 19888 |
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
}else if( c2=='m' && strncmp(azArg[1],"markdown",n2)==0 ){
p->mode = MODE_Markdown;
}else if( c2=='t' && strncmp(azArg[1],"table",n2)==0 ){
p->mode = MODE_Table;
}else if( c2=='b' && strncmp(azArg[1],"box",n2)==0 ){
p->mode = MODE_Box;
}else if( c2=='j' && strncmp(azArg[1],"json",n2)==0 ){
p->mode = MODE_Json;
}else if( nArg==1 ){
raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
}else{
raw_printf(stderr, "Error: mode should be one of: "
"ascii box column csv html insert json line list markdown "
"quote table tabs tcl\n");
rc = 1;
}
p->cMode = p->mode;
}else
if( c=='n' && strcmp(azArg[0], "nonce")==0 ){
if( nArg!=2 ){
raw_printf(stderr, "Usage: .nonce NONCE\n");
rc = 1;
}else if( p->zNonce==0 || strcmp(azArg[1],p->zNonce)!=0 ){
| > > > > | > < < < < < < < < < < < < < < < < < < < < < < < < < < < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < | | | | > > > > > > | 20006 20007 20008 20009 20010 20011 20012 20013 20014 20015 20016 20017 20018 20019 20020 20021 20022 20023 20024 20025 20026 20027 20028 20029 20030 20031 20032 20033 20034 20035 20036 20037 20038 20039 20040 20041 20042 20043 20044 20045 20046 20047 20048 20049 20050 20051 20052 20053 20054 20055 20056 20057 20058 20059 20060 20061 20062 20063 20064 20065 20066 20067 20068 20069 20070 20071 20072 20073 20074 20075 20076 20077 20078 20079 20080 20081 20082 20083 20084 20085 20086 20087 20088 20089 20090 20091 20092 20093 20094 20095 20096 20097 20098 20099 20100 20101 20102 20103 20104 20105 20106 20107 20108 20109 20110 20111 20112 20113 20114 20115 20116 20117 20118 20119 20120 20121 20122 20123 20124 20125 20126 20127 20128 20129 20130 20131 |
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
}else if( c2=='m' && strncmp(azArg[1],"markdown",n2)==0 ){
p->mode = MODE_Markdown;
}else if( c2=='t' && strncmp(azArg[1],"table",n2)==0 ){
p->mode = MODE_Table;
}else if( c2=='b' && strncmp(azArg[1],"box",n2)==0 ){
p->mode = MODE_Box;
}else if( c2=='c' && strncmp(azArg[1],"count",n2)==0 ){
p->mode = MODE_Count;
}else if( c2=='o' && strncmp(azArg[1],"off",n2)==0 ){
p->mode = MODE_Off;
}else if( c2=='j' && strncmp(azArg[1],"json",n2)==0 ){
p->mode = MODE_Json;
}else if( nArg==1 ){
raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
}else{
raw_printf(stderr, "Error: mode should be one of: "
"ascii box column csv html insert json line list markdown "
"quote table tabs tcl\n");
rc = 1;
}
p->cMode = p->mode;
}else
if( c=='n' && strcmp(azArg[0], "nonce")==0 ){
if( nArg!=2 ){
raw_printf(stderr, "Usage: .nonce NONCE\n");
rc = 1;
}else if( p->zNonce==0 || strcmp(azArg[1],p->zNonce)!=0 ){
raw_printf(stderr, "line %d: incorrect nonce: \"%s\"\n",
p->lineno, azArg[1]);
exit(1);
}else{
p->bSafeMode = 0;
return 0; /* Return immediately to bypass the safe mode reset
** at the end of this procedure */
}
}else
if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
if( nArg==2 ){
sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
"%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
}else{
raw_printf(stderr, "Usage: .nullvalue STRING\n");
rc = 1;
}
}else
if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
const char *zFN = 0; /* Pointer to constant filename */
char *zNewFilename = 0; /* Name of the database file to open */
int iName = 1; /* Index in azArg[] of the filename */
int newFlag = 0; /* True to delete file before opening */
int openMode = SHELL_OPEN_UNSPEC;
/* Check for command-line arguments */
for(iName=1; iName<nArg; iName++){
const char *z = azArg[iName];
if( optionMatch(z,"new") ){
newFlag = 1;
#ifdef SQLITE_HAVE_ZLIB
}else if( optionMatch(z, "zip") ){
openMode = SHELL_OPEN_ZIPFILE;
#endif
}else if( optionMatch(z, "append") ){
openMode = SHELL_OPEN_APPENDVFS;
}else if( optionMatch(z, "readonly") ){
openMode = SHELL_OPEN_READONLY;
}else if( optionMatch(z, "nofollow") ){
p->openFlags |= SQLITE_OPEN_NOFOLLOW;
#ifndef SQLITE_OMIT_DESERIALIZE
}else if( optionMatch(z, "deserialize") ){
openMode = SHELL_OPEN_DESERIALIZE;
}else if( optionMatch(z, "hexdb") ){
openMode = SHELL_OPEN_HEXDB;
}else if( optionMatch(z, "maxsize") && iName+1<nArg ){
p->szMax = integerValue(azArg[++iName]);
#endif /* SQLITE_OMIT_DESERIALIZE */
}else if( z[0]=='-' ){
utf8_printf(stderr, "unknown option: %s\n", z);
rc = 1;
goto meta_command_exit;
}else if( zFN ){
utf8_printf(stderr, "extra argument: \"%s\"\n", z);
rc = 1;
goto meta_command_exit;
}else{
zFN = z;
}
}
/* Close the existing database */
session_close_all(p, -1);
close_db(p->db);
p->db = 0;
p->pAuxDb->zDbFilename = 0;
sqlite3_free(p->pAuxDb->zFreeOnClose);
p->pAuxDb->zFreeOnClose = 0;
p->openMode = openMode;
p->openFlags = 0;
p->szMax = 0;
/* If a filename is specified, try to open it first */
if( zFN || p->openMode==SHELL_OPEN_HEXDB ){
if( newFlag && zFN && !p->bSafeMode ) shellDeleteFile(zFN);
if( p->bSafeMode
&& p->openMode!=SHELL_OPEN_HEXDB
&& zFN
&& strcmp(zFN,":memory:")!=0
){
failIfSafeMode(p, "cannot open disk-based database files in safe mode");
}
if( zFN ){
zNewFilename = sqlite3_mprintf("%s", zFN);
shell_check_oom(zNewFilename);
}else{
zNewFilename = 0;
}
p->pAuxDb->zDbFilename = zNewFilename;
open_db(p, OPEN_DB_KEEPALIVE);
if( p->db==0 ){
utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
sqlite3_free(zNewFilename);
}else{
p->pAuxDb->zFreeOnClose = zNewFilename;
|
| ︙ | ︙ | |||
20043 20044 20045 20046 20047 20048 20049 |
azArg[i]);
showHelp(p->out, azArg[0]);
rc = 1;
goto meta_command_exit;
}
}else if( zFile==0 && eMode!='e' && eMode!='x' ){
zFile = sqlite3_mprintf("%s", z);
| | > | > | 20171 20172 20173 20174 20175 20176 20177 20178 20179 20180 20181 20182 20183 20184 20185 20186 20187 20188 20189 20190 20191 20192 20193 20194 20195 20196 20197 20198 20199 20200 |
azArg[i]);
showHelp(p->out, azArg[0]);
rc = 1;
goto meta_command_exit;
}
}else if( zFile==0 && eMode!='e' && eMode!='x' ){
zFile = sqlite3_mprintf("%s", z);
if( zFile && zFile[0]=='|' ){
while( i+1<nArg ) zFile = sqlite3_mprintf("%z %s", zFile, azArg[++i]);
break;
}
}else{
utf8_printf(p->out,"ERROR: extra parameter: \"%s\". Usage:\n",
azArg[i]);
showHelp(p->out, azArg[0]);
rc = 1;
sqlite3_free(zFile);
goto meta_command_exit;
}
}
if( zFile==0 ){
zFile = sqlite3_mprintf("stdout");
}
if( bOnce ){
p->outCount = 2;
}else{
p->outCount = 0;
}
output_reset(p);
#ifndef SQLITE_NOHAVE_SYSTEM
|
| ︙ | ︙ | |||
20083 20084 20085 20086 20087 20088 20089 20090 20091 20092 20093 20094 20095 20096 |
newTempFile(p, "txt");
bTxtMode = 1;
}
sqlite3_free(zFile);
zFile = sqlite3_mprintf("%s", p->zTempFile);
}
#endif /* SQLITE_NOHAVE_SYSTEM */
if( zFile[0]=='|' ){
#ifdef SQLITE_OMIT_POPEN
raw_printf(stderr, "Error: pipes are not supported in this OS\n");
rc = 1;
p->out = stdout;
#else
p->out = popen(zFile + 1, "w");
| > | 20213 20214 20215 20216 20217 20218 20219 20220 20221 20222 20223 20224 20225 20226 20227 |
newTempFile(p, "txt");
bTxtMode = 1;
}
sqlite3_free(zFile);
zFile = sqlite3_mprintf("%s", p->zTempFile);
}
#endif /* SQLITE_NOHAVE_SYSTEM */
shell_check_oom(zFile);
if( zFile[0]=='|' ){
#ifdef SQLITE_OMIT_POPEN
raw_printf(stderr, "Error: pipes are not supported in this OS\n");
rc = 1;
p->out = stdout;
#else
p->out = popen(zFile + 1, "w");
|
| ︙ | ︙ | |||
20179 20180 20181 20182 20183 20184 20185 |
sqlite3_stmt *pStmt;
const char *zKey = azArg[2];
const char *zValue = azArg[3];
bind_table_init(p);
zSql = sqlite3_mprintf(
"REPLACE INTO temp.sqlite_parameters(key,value)"
"VALUES(%Q,%s);", zKey, zValue);
| | | | | 20310 20311 20312 20313 20314 20315 20316 20317 20318 20319 20320 20321 20322 20323 20324 20325 20326 20327 20328 20329 20330 20331 20332 20333 20334 20335 20336 20337 20338 20339 20340 20341 20342 20343 20344 20345 20346 20347 20348 20349 20350 20351 20352 20353 20354 20355 |
sqlite3_stmt *pStmt;
const char *zKey = azArg[2];
const char *zValue = azArg[3];
bind_table_init(p);
zSql = sqlite3_mprintf(
"REPLACE INTO temp.sqlite_parameters(key,value)"
"VALUES(%Q,%s);", zKey, zValue);
shell_check_oom(zSql);
pStmt = 0;
rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
if( rx!=SQLITE_OK ){
sqlite3_finalize(pStmt);
pStmt = 0;
zSql = sqlite3_mprintf(
"REPLACE INTO temp.sqlite_parameters(key,value)"
"VALUES(%Q,%Q);", zKey, zValue);
shell_check_oom(zSql);
rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
if( rx!=SQLITE_OK ){
utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
sqlite3_finalize(pStmt);
pStmt = 0;
rc = 1;
}
}
sqlite3_step(pStmt);
sqlite3_finalize(pStmt);
}else
/* .parameter unset NAME
** Remove the NAME binding from the parameter binding table, if it
** exists.
*/
if( nArg==3 && strcmp(azArg[1],"unset")==0 ){
char *zSql = sqlite3_mprintf(
"DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]);
shell_check_oom(zSql);
sqlite3_exec(p->db, zSql, 0, 0, 0);
sqlite3_free(zSql);
}else
/* If no command name matches, show a syntax error */
parameter_syntax_error:
showHelp(p->out, "parameter");
}else
|
| ︙ | ︙ | |||
20436 20437 20438 20439 20440 20441 20442 20443 20444 20445 20446 20447 20448 20449 |
"CREATE TABLE %s (\n"
" type text,\n"
" name text,\n"
" tbl_name text,\n"
" rootpage integer,\n"
" sql text\n"
")", zName);
new_argv[1] = 0;
new_colv[0] = "sql";
new_colv[1] = 0;
callback(&data, 1, new_argv, new_colv);
sqlite3_free(new_argv[0]);
}
}
| > | 20567 20568 20569 20570 20571 20572 20573 20574 20575 20576 20577 20578 20579 20580 20581 |
"CREATE TABLE %s (\n"
" type text,\n"
" name text,\n"
" tbl_name text,\n"
" rootpage integer,\n"
" sql text\n"
")", zName);
shell_check_oom(new_argv[0]);
new_argv[1] = 0;
new_colv[0] = "sql";
new_colv[1] = 0;
callback(&data, 1, new_argv, new_colv);
sqlite3_free(new_argv[0]);
}
}
|
| ︙ | ︙ | |||
20487 20488 20489 20490 20491 20492 20493 |
" 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list",
0);
}
#endif
appendText(&sSelect, ") WHERE ", 0);
if( zName ){
char *zQarg = sqlite3_mprintf("%Q", zName);
| > > | | | 20619 20620 20621 20622 20623 20624 20625 20626 20627 20628 20629 20630 20631 20632 20633 20634 20635 20636 |
" 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list",
0);
}
#endif
appendText(&sSelect, ") WHERE ", 0);
if( zName ){
char *zQarg = sqlite3_mprintf("%Q", zName);
int bGlob;
shell_check_oom(zQarg);
bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 ||
strchr(zName, '[') != 0;
if( strchr(zName, '.') ){
appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0);
}else{
appendText(&sSelect, "lower(tbl_name)", 0);
}
appendText(&sSelect, bGlob ? " GLOB " : " LIKE ", 0);
appendText(&sSelect, zQarg, 0);
|
| ︙ | ︙ | |||
20651 20652 20653 20654 20655 20656 20657 |
nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
pSession->azFilter = sqlite3_malloc( nByte );
if( pSession->azFilter==0 ){
raw_printf(stderr, "Error: out or memory\n");
exit(1);
}
for(ii=1; ii<nCmd; ii++){
| | > | 20785 20786 20787 20788 20789 20790 20791 20792 20793 20794 20795 20796 20797 20798 20799 20800 |
nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
pSession->azFilter = sqlite3_malloc( nByte );
if( pSession->azFilter==0 ){
raw_printf(stderr, "Error: out or memory\n");
exit(1);
}
for(ii=1; ii<nCmd; ii++){
char *x = pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
shell_check_oom(x);
}
pSession->nFilter = ii-1;
}
}else
/* .session indirect ?BOOLEAN?
** Query or set the indirect flag
|
| ︙ | ︙ | |||
20723 20724 20725 20726 20727 20728 20729 20730 20731 20732 20733 20734 20735 20736 |
rc = 0;
goto meta_command_exit;
}
pSession->nFilter = 0;
sqlite3session_table_filter(pSession->p, session_filter, pSession);
pAuxDb->nSession++;
pSession->zName = sqlite3_mprintf("%s", zName);
}else
/* If no command name matches, show a syntax error */
session_syntax_error:
showHelp(p->out, "session");
}else
#endif
| > | 20858 20859 20860 20861 20862 20863 20864 20865 20866 20867 20868 20869 20870 20871 20872 |
rc = 0;
goto meta_command_exit;
}
pSession->nFilter = 0;
sqlite3session_table_filter(pSession->p, session_filter, pSession);
pAuxDb->nSession++;
pSession->zName = sqlite3_mprintf("%s", zName);
shell_check_oom(pSession->zName);
}else
/* If no command name matches, show a syntax error */
session_syntax_error:
showHelp(p->out, "session");
}else
#endif
|
| ︙ | ︙ | |||
20816 20817 20818 20819 20820 20821 20822 20823 20824 |
}
for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){
int tno = sqlite3_column_int(pStmt, 0);
const char *zOp = (const char*)sqlite3_column_text(pStmt, 1);
const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);
k = 0;
if( bVerbose>0 ){
| > > > < < | 20952 20953 20954 20955 20956 20957 20958 20959 20960 20961 20962 20963 20964 20965 20966 20967 20968 20969 20970 20971 |
}
for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){
int tno = sqlite3_column_int(pStmt, 0);
const char *zOp = (const char*)sqlite3_column_text(pStmt, 1);
const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);
if( zOp==0 ) continue;
if( zSql==0 ) continue;
if( zAns==0 ) continue;
k = 0;
if( bVerbose>0 ){
printf("%d: %s %s\n", tno, zOp, zSql);
}
if( strcmp(zOp,"memo")==0 ){
utf8_printf(p->out, "%s\n", zSql);
}else
if( strcmp(zOp,"run")==0 ){
char *zErrMsg = 0;
str.n = 0;
|
| ︙ | ︙ | |||
20938 20939 20940 20941 20942 20943 20944 20945 20946 20947 20948 20949 20950 20951 |
sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
initText(&sQuery);
initText(&sSql);
appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0);
zSep = "VALUES(";
while( SQLITE_ROW==sqlite3_step(pStmt) ){
const char *zTab = (const char*)sqlite3_column_text(pStmt,0);
if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue;
if( strncmp(zTab, "sqlite_",7)!=0 ){
appendText(&sQuery,"SELECT * FROM ", 0);
appendText(&sQuery,zTab,'"');
appendText(&sQuery," NOT INDEXED;", 0);
}else if( strcmp(zTab, "sqlite_schema")==0 ){
appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_schema"
| > | 21075 21076 21077 21078 21079 21080 21081 21082 21083 21084 21085 21086 21087 21088 21089 |
sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
initText(&sQuery);
initText(&sSql);
appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0);
zSep = "VALUES(";
while( SQLITE_ROW==sqlite3_step(pStmt) ){
const char *zTab = (const char*)sqlite3_column_text(pStmt,0);
if( zTab==0 ) continue;
if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue;
if( strncmp(zTab, "sqlite_",7)!=0 ){
appendText(&sQuery,"SELECT * FROM ", 0);
appendText(&sQuery,zTab,'"');
appendText(&sQuery," NOT INDEXED;", 0);
}else if( strcmp(zTab, "sqlite_schema")==0 ){
appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_schema"
|
| ︙ | ︙ | |||
20978 20979 20980 20981 20982 20983 20984 20985 20986 20987 20988 20989 20990 20991 |
}else{
zSql = sqlite3_mprintf(
"%s))"
" SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash"
" FROM [sha3sum$query]",
sSql.z, iSize);
}
freeText(&sQuery);
freeText(&sSql);
if( bDebug ){
utf8_printf(p->out, "%s\n", zSql);
}else{
shell_exec(p, zSql, 0);
}
| > | 21116 21117 21118 21119 21120 21121 21122 21123 21124 21125 21126 21127 21128 21129 21130 |
}else{
zSql = sqlite3_mprintf(
"%s))"
" SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash"
" FROM [sha3sum$query]",
sSql.z, iSize);
}
shell_check_oom(zSql);
freeText(&sQuery);
freeText(&sSql);
if( bDebug ){
utf8_printf(p->out, "%s\n", zSql);
}else{
shell_exec(p, zSql, 0);
}
|
| ︙ | ︙ | |||
21001 21002 21003 21004 21005 21006 21007 |
failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
if( nArg<2 ){
raw_printf(stderr, "Usage: .system COMMAND\n");
rc = 1;
goto meta_command_exit;
}
zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
| | | | 21140 21141 21142 21143 21144 21145 21146 21147 21148 21149 21150 21151 21152 21153 21154 21155 21156 21157 21158 |
failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
if( nArg<2 ){
raw_printf(stderr, "Usage: .system COMMAND\n");
rc = 1;
goto meta_command_exit;
}
zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
for(i=2; i<nArg && zCmd!=0; i++){
zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
zCmd, azArg[i]);
}
x = zCmd!=0 ? system(zCmd) : 1;
sqlite3_free(zCmd);
if( x ) raw_printf(stderr, "System command returns %d\n", x);
}else
#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
static const char *azBool[] = { "off", "on", "trigger", "full"};
|
| ︙ | ︙ | |||
21141 21142 21143 21144 21145 21146 21147 |
sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
}
while( sqlite3_step(pStmt)==SQLITE_ROW ){
if( nRow>=nAlloc ){
char **azNew;
int n2 = nAlloc*2 + 10;
azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
| | | | 21280 21281 21282 21283 21284 21285 21286 21287 21288 21289 21290 21291 21292 21293 21294 21295 21296 21297 21298 21299 |
sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
}
while( sqlite3_step(pStmt)==SQLITE_ROW ){
if( nRow>=nAlloc ){
char **azNew;
int n2 = nAlloc*2 + 10;
azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
shell_check_oom(azNew);
nAlloc = n2;
azResult = azNew;
}
azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
shell_check_oom(azResult[nRow]);
nRow++;
}
if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
rc = shellDatabaseError(p->db);
}
/* Pretty-print the contents of array azResult[] to the output */
|
| ︙ | ︙ | |||
21198 21199 21200 21201 21202 21203 21204 21205 21206 |
}else
#ifndef SQLITE_UNTESTABLE
if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
static const struct {
const char *zCtrlName; /* Name of a test-control option */
int ctrlCode; /* Integer code for that option */
const char *zUsage; /* Usage notes */
} aCtrl[] = {
| > | | | | | | | | | | | | | | | | | | | | | 21337 21338 21339 21340 21341 21342 21343 21344 21345 21346 21347 21348 21349 21350 21351 21352 21353 21354 21355 21356 21357 21358 21359 21360 21361 21362 21363 21364 21365 21366 21367 21368 21369 21370 21371 21372 21373 21374 21375 |
}else
#ifndef SQLITE_UNTESTABLE
if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
static const struct {
const char *zCtrlName; /* Name of a test-control option */
int ctrlCode; /* Integer code for that option */
int unSafe; /* Not valid for --safe mode */
const char *zUsage; /* Usage notes */
} aCtrl[] = {
{ "always", SQLITE_TESTCTRL_ALWAYS, 1, "BOOLEAN" },
{ "assert", SQLITE_TESTCTRL_ASSERT, 1, "BOOLEAN" },
/*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,1, "" },*/
/*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, 1, "" },*/
{ "byteorder", SQLITE_TESTCTRL_BYTEORDER, 0, "" },
{ "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,0,"BOOLEAN" },
/*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, 1,"" },*/
{ "imposter", SQLITE_TESTCTRL_IMPOSTER,1,"SCHEMA ON/OFF ROOTPAGE"},
{ "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS,0,"" },
{ "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,0,"BOOLEAN" },
{ "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN" },
{ "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK" },
#ifdef YYCOVERAGE
{ "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE,0,"" },
#endif
{ "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE,0, "OFFSET " },
{ "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE,0, "" },
{ "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, 0, "" },
{ "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, 0, "SEED ?db?" },
{ "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, 0, "" },
{ "sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" },
{ "tune", SQLITE_TESTCTRL_TUNE, 1, "ID VALUE" },
};
int testctrl = -1;
int iCtrl = -1;
int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */
int isOk = 0;
int i, n2;
const char *zCmd = 0;
|
| ︙ | ︙ | |||
21269 21270 21271 21272 21273 21274 21275 21276 21277 21278 21279 21280 21281 21282 |
goto meta_command_exit;
}
}
}
if( testctrl<0 ){
utf8_printf(stderr,"Error: unknown test-control: %s\n"
"Use \".testctrl --help\" for help\n", zCmd);
}else{
switch(testctrl){
/* sqlite3_test_control(int, db, int) */
case SQLITE_TESTCTRL_OPTIMIZATIONS:
if( nArg==3 ){
unsigned int opt = (unsigned int)strtol(azArg[2], 0, 0);
| > > > > > | 21409 21410 21411 21412 21413 21414 21415 21416 21417 21418 21419 21420 21421 21422 21423 21424 21425 21426 21427 |
goto meta_command_exit;
}
}
}
if( testctrl<0 ){
utf8_printf(stderr,"Error: unknown test-control: %s\n"
"Use \".testctrl --help\" for help\n", zCmd);
}else if( aCtrl[iCtrl].unSafe && p->bSafeMode ){
utf8_printf(stderr,
"line %d: \".testctrl %s\" may not be used in safe mode\n",
p->lineno, aCtrl[iCtrl].zCtrlName);
exit(1);
}else{
switch(testctrl){
/* sqlite3_test_control(int, db, int) */
case SQLITE_TESTCTRL_OPTIMIZATIONS:
if( nArg==3 ){
unsigned int opt = (unsigned int)strtol(azArg[2], 0, 0);
|
| ︙ | ︙ | |||
21909 21910 21911 21912 21913 21914 21915 |
}
/* No single-line dispositions remain; accumulate line(s). */
nLine = strlen30(zLine);
if( nSql+nLine+2>=nAlloc ){
/* Grow buffer by half-again increments when big. */
nAlloc = nSql+(nSql>>1)+nLine+100;
zSql = realloc(zSql, nAlloc);
| | | 22054 22055 22056 22057 22058 22059 22060 22061 22062 22063 22064 22065 22066 22067 22068 |
}
/* No single-line dispositions remain; accumulate line(s). */
nLine = strlen30(zLine);
if( nSql+nLine+2>=nAlloc ){
/* Grow buffer by half-again increments when big. */
nAlloc = nSql+(nSql>>1)+nLine+100;
zSql = realloc(zSql, nAlloc);
shell_check_oom(zSql);
}
if( nSql==0 ){
int i;
for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
assert( nAlloc>0 && zSql!=0 );
memcpy(zSql, zLine+i, nLine+1-i);
startline = p->lineno;
|
| ︙ | ︙ | |||
22041 22042 22043 22044 22045 22046 22047 22048 22049 22050 22051 22052 22053 22054 |
home_dir = find_home_dir(0);
if( home_dir==0 ){
raw_printf(stderr, "-- warning: cannot find home directory;"
" cannot read ~/.sqliterc\n");
return;
}
zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
sqliterc = zBuf;
}
p->in = fopen(sqliterc,"rb");
if( p->in ){
if( stdin_is_interactive ){
utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
}
| > | 22186 22187 22188 22189 22190 22191 22192 22193 22194 22195 22196 22197 22198 22199 22200 |
home_dir = find_home_dir(0);
if( home_dir==0 ){
raw_printf(stderr, "-- warning: cannot find home directory;"
" cannot read ~/.sqliterc\n");
return;
}
zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
shell_check_oom(zBuf);
sqliterc = zBuf;
}
p->in = fopen(sqliterc,"rb");
if( p->in ){
if( stdin_is_interactive ){
utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
}
|
| ︙ | ︙ | |||
22239 22240 22241 22242 22243 22244 22245 | #endif setBinaryMode(stdin, 0); setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */ stdin_is_interactive = isatty(0); stdout_is_console = isatty(1); | < < < < | 22385 22386 22387 22388 22389 22390 22391 22392 22393 22394 22395 22396 22397 22398 |
#endif
setBinaryMode(stdin, 0);
setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
stdin_is_interactive = isatty(0);
stdout_is_console = isatty(1);
#if !defined(_WIN32_WCE)
if( getenv("SQLITE_DEBUG_BREAK") ){
if( isatty(0) && isatty(2) ){
fprintf(stderr,
"attach debugger to process %d and press any key to continue.\n",
GETPID());
fgetc(stdin);
|
| ︙ | ︙ | |||
22282 22283 22284 22285 22286 22287 22288 22289 22290 | ** do this. But we want to run an sqlite3_shutdown() afterwards so that ** subsequent sqlite3_config() calls will work. So copy all results into ** memory that does not come from the SQLite memory allocator. */ #if !SQLITE_SHELL_IS_UTF8 sqlite3_initialize(); argvToFree = malloc(sizeof(argv[0])*argc*2); argcToFree = argc; argv = argvToFree + argc; | > < | | | 22424 22425 22426 22427 22428 22429 22430 22431 22432 22433 22434 22435 22436 22437 22438 22439 22440 22441 22442 22443 22444 22445 22446 22447 |
** do this. But we want to run an sqlite3_shutdown() afterwards so that
** subsequent sqlite3_config() calls will work. So copy all results into
** memory that does not come from the SQLite memory allocator.
*/
#if !SQLITE_SHELL_IS_UTF8
sqlite3_initialize();
argvToFree = malloc(sizeof(argv[0])*argc*2);
shell_check_oom(argvToFree);
argcToFree = argc;
argv = argvToFree + argc;
for(i=0; i<argc; i++){
char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
int n;
shell_check_oom(z);
n = (int)strlen(z);
argv[i] = malloc( n+1 );
shell_check_oom(argv[i]);
memcpy(argv[i], z, n+1);
argvToFree[i] = argv[i];
sqlite3_free(z);
}
sqlite3_shutdown();
#endif
|
| ︙ | ︙ | |||
22341 22342 22343 22344 22345 22346 22347 |
data.aAuxDb->zDbFilename = z;
}else{
/* Excesss arguments are interpreted as SQL (or dot-commands) and
** mean that nothing is read from stdin */
readStdin = 0;
nCmd++;
azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
| | | 22483 22484 22485 22486 22487 22488 22489 22490 22491 22492 22493 22494 22495 22496 22497 |
data.aAuxDb->zDbFilename = z;
}else{
/* Excesss arguments are interpreted as SQL (or dot-commands) and
** mean that nothing is read from stdin */
readStdin = 0;
nCmd++;
azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
shell_check_oom(azCmd);
azCmd[nCmd-1] = z;
}
}
if( z[1]=='-' ) z++;
if( strcmp(z,"-separator")==0
|| strcmp(z,"-nullvalue")==0
|| strcmp(z,"-newline")==0
|
| ︙ | ︙ |
Name change from src/sqlite3.c to extsrc/sqlite3.c.
more than 10,000 changes
Name change from src/sqlite3.h to extsrc/sqlite3.h.
| ︙ | ︙ | |||
142 143 144 145 146 147 148 | ** been edited in any way since it was last checked in, then the last ** four hexadecimal digits of the hash may be modified. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ | | | | | 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | ** been edited in any way since it was last checked in, then the last ** four hexadecimal digits of the hash may be modified. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.38.0" #define SQLITE_VERSION_NUMBER 3038000 #define SQLITE_SOURCE_ID "2022-01-12 00:28:12 adebb9d7478d092f16fb0ef7d5246ce152b166479d6f949110b5878b89ea2cec" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
| ︙ | ︙ | |||
535 536 537 538 539 540 541 | #define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) #define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */ #define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8)) | < | 535 536 537 538 539 540 541 542 543 544 545 546 547 548 | #define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) #define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */ #define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8)) #define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) #define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8)) |
| ︙ | ︙ | |||
571 572 573 574 575 576 577 578 579 580 581 582 583 584 | /* ** CAPI3REF: Flags For File Open Operations ** ** These bit values are intended for use in the ** 3rd parameter to the [sqlite3_open_v2()] interface and ** in the 4th parameter to the [sqlite3_vfs.xOpen] method. */ #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ #define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */ | > > > > > > > > > > > > > | 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 | /* ** CAPI3REF: Flags For File Open Operations ** ** These bit values are intended for use in the ** 3rd parameter to the [sqlite3_open_v2()] interface and ** in the 4th parameter to the [sqlite3_vfs.xOpen] method. ** ** Only those flags marked as "Ok for sqlite3_open_v2()" may be ** used as the third argument to the [sqlite3_open_v2()] interface. ** The other flags have historically been ignored by sqlite3_open_v2(), ** though future versions of SQLite might change so that an error is ** raised if any of the disallowed bits are passed into sqlite3_open_v2(). ** Applications should not depend on the historical behavior. ** ** Note in particular that passing the SQLITE_OPEN_EXCLUSIVE flag into ** [sqlite3_open_v2()] does *not* cause the underlying database file ** to be opened using O_EXCL. Passing SQLITE_OPEN_EXCLUSIVE into ** [sqlite3_open_v2()] has historically be a no-op and might become an ** error in future versions of SQLite. */ #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ #define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */ |
| ︙ | ︙ | |||
593 594 595 596 597 598 599 600 601 602 603 604 605 606 | #define SQLITE_OPEN_SUPER_JOURNAL 0x00004000 /* VFS only */ #define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_WAL 0x00080000 /* VFS only */ #define SQLITE_OPEN_NOFOLLOW 0x01000000 /* Ok for sqlite3_open_v2() */ /* Reserved: 0x00F00000 */ /* Legacy compatibility: */ #define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ /* | > | 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 | #define SQLITE_OPEN_SUPER_JOURNAL 0x00004000 /* VFS only */ #define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_WAL 0x00080000 /* VFS only */ #define SQLITE_OPEN_NOFOLLOW 0x01000000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_EXRESCODE 0x02000000 /* Extended result codes */ /* Reserved: 0x00F00000 */ /* Legacy compatibility: */ #define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ /* |
| ︙ | ︙ | |||
3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 | ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^ ** ** ^(<dt>[SQLITE_OPEN_PRIVATECACHE]</dt> ** <dd>The database is opened [shared cache] disabled, overriding ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^ ** ** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt> ** <dd>The database filename is not allowed to be a symbolic link</dd> | > > > > > > > > < < < < < < | > > > > > > > > | 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 | ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^ ** ** ^(<dt>[SQLITE_OPEN_PRIVATECACHE]</dt> ** <dd>The database is opened [shared cache] disabled, overriding ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^ ** ** [[OPEN_EXRESCODE]] ^(<dt>[SQLITE_OPEN_EXRESCODE]</dt> ** <dd>The database connection comes up in "extended result code mode". ** In other words, the database behaves has if ** [sqlite3_extended_result_codes(db,1)] where called on the database ** connection as soon as the connection is created. In addition to setting ** the extended result code mode, this flag also causes [sqlite3_open_v2()] ** to return an extended result code.</dd> ** ** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt> ** <dd>The database filename is not allowed to be a symbolic link</dd> ** </dl>)^ ** ** If the 3rd parameter to sqlite3_open_v2() is not one of the ** required combinations shown above optionally combined with other ** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits] ** then the behavior is undefined. Historic versions of SQLite ** have silently ignored surplus bits in the flags parameter to ** sqlite3_open_v2(), however that behavior might not be carried through ** into future versions of SQLite and so applications should not rely ** upon it. Note in particular that the SQLITE_OPEN_EXCLUSIVE flag is a no-op ** for sqlite3_open_v2(). The SQLITE_OPEN_EXCLUSIVE does *not* cause ** the open to fail if the database already exists. The SQLITE_OPEN_EXCLUSIVE ** flag is intended for use by the [sqlite3_vfs|VFS interface] only, and not ** by sqlite3_open_v2(). ** ** ^The fourth parameter to sqlite3_open_v2() is the name of the ** [sqlite3_vfs] object that defines the operating system interface that ** the new database connection should use. ^If the fourth parameter is ** a NULL pointer then the default [sqlite3_vfs] object is used. ** ** ^If the filename is ":memory:", then a private, temporary in-memory database |
| ︙ | ︙ | |||
3797 3798 3799 3800 3801 3802 3803 | ** [extended result code] even when extended result codes are ** disabled. ** ** The values returned by sqlite3_errcode() and/or ** sqlite3_extended_errcode() might change with each API call. ** Except, there are some interfaces that are guaranteed to never ** change the value of the error code. The error-code preserving | | > > > > > > > > > | 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 |
** [extended result code] even when extended result codes are
** disabled.
**
** The values returned by sqlite3_errcode() and/or
** sqlite3_extended_errcode() might change with each API call.
** Except, there are some interfaces that are guaranteed to never
** change the value of the error code. The error-code preserving
** interfaces include the following:
**
** <ul>
** <li> sqlite3_errcode()
** <li> sqlite3_extended_errcode()
** <li> sqlite3_errmsg()
** <li> sqlite3_errmsg16()
** <li> sqlite3_error_offset()
** </ul>
**
** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language
** text that describes the error, as either UTF-8 or UTF-16 respectively.
** ^(Memory to hold the error message string is managed internally.
** The application does not need to worry about freeing the result.
** However, the error string might be overwritten or deallocated by
** subsequent calls to other SQLite interface functions.)^
**
** ^The sqlite3_errstr() interface returns the English-language text
** that describes the [result code], as UTF-8.
** ^(Memory to hold the error message string is managed internally
** and must not be freed by the application)^.
**
** ^If the most recent error references a specific token in the input
** SQL, the sqlite3_error_offset() interface returns the byte offset
** of the start of that token. ^The byte offset returned by
** sqlite3_error_offset() assumes that the input SQL is UTF8.
** ^If the most error does not reference a specific token in the input
** SQL, then the sqlite3_error_offset() function returns -1.
**
** When the serialized [threading mode] is in use, it might be the
** case that a second error occurs on a separate thread in between
** the time of the first error and the call to these interfaces.
** When that happens, the second error will be reported since these
** interfaces always report the most recent result. To avoid
** this, each thread can obtain exclusive use of the [database connection] D
** by invoking [sqlite3_mutex_enter]([sqlite3_db_mutex](D)) before beginning
** to use D and invoking [sqlite3_mutex_leave]([sqlite3_db_mutex](D)) after
** all calls to the interfaces listed here are completed.
**
** If an interface fails with SQLITE_MISUSE, that means the interface
** was invoked incorrectly by the application. In that case, the
** error code and message may or may not be set.
*/
SQLITE_API int sqlite3_errcode(sqlite3 *db);
SQLITE_API int sqlite3_extended_errcode(sqlite3 *db);
SQLITE_API const char *sqlite3_errmsg(sqlite3*);
SQLITE_API const void *sqlite3_errmsg16(sqlite3*);
SQLITE_API const char *sqlite3_errstr(int);
SQLITE_API int sqlite3_error_offset(sqlite3 *db);
/*
** CAPI3REF: Prepared Statement Object
** KEYWORDS: {prepared statement} {prepared statements}
**
** An instance of this object represents a single SQL statement that
** has been compiled into binary form and is ready to be evaluated.
|
| ︙ | ︙ | |||
6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 | ** ^The rollback callback is not invoked if a transaction is ** automatically rolled back because the database connection is closed. ** ** See also the [sqlite3_update_hook()] interface. */ SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); /* ** CAPI3REF: Data Change Notification Callbacks ** METHOD: sqlite3 ** ** ^The sqlite3_update_hook() interface registers a callback function ** with the [database connection] identified by the first argument | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 |
** ^The rollback callback is not invoked if a transaction is
** automatically rolled back because the database connection is closed.
**
** See also the [sqlite3_update_hook()] interface.
*/
SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
/*
** CAPI3REF: Autovacuum Compaction Amount Callback
** METHOD: sqlite3
**
** ^The sqlite3_autovacuum_pages(D,C,P,X) interface registers a callback
** function C that is invoked prior to each autovacuum of the database
** file. ^The callback is passed a copy of the generic data pointer (P),
** the schema-name of the attached database that is being autovacuumed,
** the the size of the database file in pages, the number of free pages,
** and the number of bytes per page, respectively. The callback should
** return the number of free pages that should be removed by the
** autovacuum. ^If the callback returns zero, then no autovacuum happens.
** ^If the value returned is greater than or equal to the number of
** free pages, then a complete autovacuum happens.
**
** <p>^If there are multiple ATTACH-ed database files that are being
** modified as part of a transaction commit, then the autovacuum pages
** callback is invoked separately for each file.
**
** <p><b>The callback is not reentrant.</b> The callback function should
** not attempt to invoke any other SQLite interface. If it does, bad
** things may happen, including segmentation faults and corrupt database
** files. The callback function should be a simple function that
** does some arithmetic on its input parameters and returns a result.
**
** ^The X parameter to sqlite3_autovacuum_pages(D,C,P,X) is an optional
** destructor for the P parameter. ^If X is not NULL, then X(P) is
** invoked whenever the database connection closes or when the callback
** is overwritten by another invocation of sqlite3_autovacuum_pages().
**
** <p>^There is only one autovacuum pages callback per database connection.
** ^Each call to the sqlite3_autovacuum_pages() interface overrides all
** previous invocations for that database connection. ^If the callback
** argument (C) to sqlite3_autovacuum_pages(D,C,P,X) is a NULL pointer,
** then the autovacuum steps callback is cancelled. The return value
** from sqlite3_autovacuum_pages() is normally SQLITE_OK, but might
** be some other error code if something goes wrong. The current
** implementation will only return SQLITE_OK or SQLITE_MISUSE, but other
** return codes might be added in future releases.
**
** <p>If no autovacuum pages callback is specified (the usual case) or
** a NULL pointer is provided for the callback,
** then the default behavior is to vacuum all free pages. So, in other
** words, the default behavior is the same as if the callback function
** were something like this:
**
** <blockquote><pre>
** unsigned int demonstration_autovac_pages_callback(
** void *pClientData,
** const char *zSchema,
** unsigned int nDbPage,
** unsigned int nFreePage,
** unsigned int nBytePerPage
** ){
** return nFreePage;
** }
** </pre></blockquote>
*/
SQLITE_API int sqlite3_autovacuum_pages(
sqlite3 *db,
unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
void*,
void(*)(void*)
);
/*
** CAPI3REF: Data Change Notification Callbacks
** METHOD: sqlite3
**
** ^The sqlite3_update_hook() interface registers a callback function
** with the [database connection] identified by the first argument
|
| ︙ | ︙ | |||
7851 7852 7853 7854 7855 7856 7857 | #define SQLITE_TESTCTRL_PARSER_COVERAGE 26 #define SQLITE_TESTCTRL_RESULT_INTREAL 27 #define SQLITE_TESTCTRL_PRNG_SEED 28 #define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29 #define SQLITE_TESTCTRL_SEEK_COUNT 30 #define SQLITE_TESTCTRL_TRACEFLAGS 31 #define SQLITE_TESTCTRL_TUNE 32 | > | | 7949 7950 7951 7952 7953 7954 7955 7956 7957 7958 7959 7960 7961 7962 7963 7964 | #define SQLITE_TESTCTRL_PARSER_COVERAGE 26 #define SQLITE_TESTCTRL_RESULT_INTREAL 27 #define SQLITE_TESTCTRL_PRNG_SEED 28 #define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29 #define SQLITE_TESTCTRL_SEEK_COUNT 30 #define SQLITE_TESTCTRL_TRACEFLAGS 31 #define SQLITE_TESTCTRL_TUNE 32 #define SQLITE_TESTCTRL_LOGEST 33 #define SQLITE_TESTCTRL_LAST 33 /* Largest TESTCTRL */ /* ** CAPI3REF: SQL Keyword Checking ** ** These routines provide access to the set of SQL language keywords ** recognized by SQLite. Applications can uses these routines to determine ** whether or not a specific identifier needs to be escaped (for example, |
| ︙ | ︙ | |||
8373 8374 8375 8376 8377 8378 8379 8380 8381 8382 8383 8384 8385 8386 8387 8388 8389 8390 8391 8392 8393 8394 8395 8396 8397 8398 8399 8400 8401 | ** ** [[SQLITE_STMTSTATUS_RUN]] <dt>SQLITE_STMTSTATUS_RUN</dt> ** <dd>^This is the number of times that the prepared statement has ** been run. A single "run" for the purposes of this counter is one ** or more calls to [sqlite3_step()] followed by a call to [sqlite3_reset()]. ** The counter is incremented on the first [sqlite3_step()] call of each ** cycle. ** ** [[SQLITE_STMTSTATUS_MEMUSED]] <dt>SQLITE_STMTSTATUS_MEMUSED</dt> ** <dd>^This is the approximate number of bytes of heap memory ** used to store the prepared statement. ^This value is not actually ** a counter, and so the resetFlg parameter to sqlite3_stmt_status() ** is ignored when the opcode is SQLITE_STMTSTATUS_MEMUSED. ** </dd> ** </dl> */ #define SQLITE_STMTSTATUS_FULLSCAN_STEP 1 #define SQLITE_STMTSTATUS_SORT 2 #define SQLITE_STMTSTATUS_AUTOINDEX 3 #define SQLITE_STMTSTATUS_VM_STEP 4 #define SQLITE_STMTSTATUS_REPREPARE 5 #define SQLITE_STMTSTATUS_RUN 6 #define SQLITE_STMTSTATUS_MEMUSED 99 /* ** CAPI3REF: Custom Page Cache Object ** ** The sqlite3_pcache type is opaque. It is implemented by ** the pluggable module. The SQLite core has no knowledge of | > > > > > > > > > > > > | 8472 8473 8474 8475 8476 8477 8478 8479 8480 8481 8482 8483 8484 8485 8486 8487 8488 8489 8490 8491 8492 8493 8494 8495 8496 8497 8498 8499 8500 8501 8502 8503 8504 8505 8506 8507 8508 8509 8510 8511 8512 | ** ** [[SQLITE_STMTSTATUS_RUN]] <dt>SQLITE_STMTSTATUS_RUN</dt> ** <dd>^This is the number of times that the prepared statement has ** been run. A single "run" for the purposes of this counter is one ** or more calls to [sqlite3_step()] followed by a call to [sqlite3_reset()]. ** The counter is incremented on the first [sqlite3_step()] call of each ** cycle. ** ** [[SQLITE_STMTSTATUS_FILTER_MISS]] ** [[SQLITE_STMTSTATUS_FILTER HIT]] ** <dt>SQLITE_STMTSTATUS_FILTER_HIT<br> ** SQLITE_STMTSTATUS_FILTER_MISS</dt> ** <dd>^SQLITE_STMTSTATUS_FILTER_HIT is the number of times that a join ** step was bypassed because a Bloom filter returned not-found. The ** corresponding SQLITE_STMTSTATUS_FILTER_MISS value is the number of ** times that the Bloom filter returned a find, and thus the join step ** had to be processed as normal. ** ** [[SQLITE_STMTSTATUS_MEMUSED]] <dt>SQLITE_STMTSTATUS_MEMUSED</dt> ** <dd>^This is the approximate number of bytes of heap memory ** used to store the prepared statement. ^This value is not actually ** a counter, and so the resetFlg parameter to sqlite3_stmt_status() ** is ignored when the opcode is SQLITE_STMTSTATUS_MEMUSED. ** </dd> ** </dl> */ #define SQLITE_STMTSTATUS_FULLSCAN_STEP 1 #define SQLITE_STMTSTATUS_SORT 2 #define SQLITE_STMTSTATUS_AUTOINDEX 3 #define SQLITE_STMTSTATUS_VM_STEP 4 #define SQLITE_STMTSTATUS_REPREPARE 5 #define SQLITE_STMTSTATUS_RUN 6 #define SQLITE_STMTSTATUS_FILTER_MISS 7 #define SQLITE_STMTSTATUS_FILTER_HIT 8 #define SQLITE_STMTSTATUS_MEMUSED 99 /* ** CAPI3REF: Custom Page Cache Object ** ** The sqlite3_pcache type is opaque. It is implemented by ** the pluggable module. The SQLite core has no knowledge of |
| ︙ | ︙ | |||
9358 9359 9360 9361 9362 9363 9364 | */ SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*); /* ** CAPI3REF: Determine The Collation For a Virtual Table Constraint ** ** This function may only be called from within a call to the [xBestIndex] | | > > | | | | > > > > > > > > > > | > > > > > > > | | 9469 9470 9471 9472 9473 9474 9475 9476 9477 9478 9479 9480 9481 9482 9483 9484 9485 9486 9487 9488 9489 9490 9491 9492 9493 9494 9495 9496 9497 9498 9499 9500 9501 9502 9503 9504 9505 9506 9507 9508 9509 |
*/
SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*);
/*
** CAPI3REF: Determine The Collation For a Virtual Table Constraint
**
** This function may only be called from within a call to the [xBestIndex]
** method of a [virtual table]. This function returns a pointer to a string
** that is the name of the appropriate collation sequence to use for text
** comparisons on the constraint identified by its arguments.
**
** The first argument must be the pointer to the sqlite3_index_info object
** that is the first parameter to the xBestIndex() method. The second argument
** must be an index into the aConstraint[] array belonging to the
** sqlite3_index_info structure passed to xBestIndex.
**
** Important:
** The first parameter must be the same pointer that is passed into the
** xBestMethod() method. The first parameter may not be a pointer to a
** different sqlite3_index_info object, even an exact copy.
**
** The return value is computed as follows:
**
** <ol>
** <li><p> If the constraint comes from a WHERE clause expression that contains
** a [COLLATE operator], then the name of the collation specified by
** that COLLATE operator is returned.
** <li><p> If there is no COLLATE operator, but the column that is the subject
** of the constraint specifies an alternative collating sequence via
** a [COLLATE clause] on the column definition within the CREATE TABLE
** statement that was passed into [sqlite3_declare_vtab()], then the
** name of that alternative collating sequence is returned.
** <li><p> Otherwise, "BINARY" is returned.
** </ol>
*/
SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
/*
** CAPI3REF: Conflict resolution modes
** KEYWORDS: {conflict resolution mode}
**
|
| ︙ | ︙ |
Changes to skins/ardoise/css.txt.
| ︙ | ︙ | |||
570 571 572 573 574 575 576 577 578 579 580 581 582 583 |
background: #000;
border: 2px solid #bbb;
border-radius: 5px
}
table.numbered-lines td.file-content > pre {
margin-top: -2px/*offset CODE tag border*/;
}
pre > code {
padding: 1rem 1.5rem;
white-space: pre
}
td,
th {
padding: 1px 5px;
| > > > > > > | 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 |
background: #000;
border: 2px solid #bbb;
border-radius: 5px
}
table.numbered-lines td.file-content > pre {
margin-top: -2px/*offset CODE tag border*/;
}
table.numbered-lines {
font-family: monospace;
}
table.numbered-lines pre {
font-family: inherit;
}
pre > code {
padding: 1rem 1.5rem;
white-space: pre
}
td,
th {
padding: 1px 5px;
|
| ︙ | ︙ | |||
1125 1126 1127 1128 1129 1130 1131 |
border-radius: 5px;
}
table.diff pre {
font-size: 1.15rem;
scrollbar-color: black #999;
}
table.udiff pre {
| | | 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 |
border-radius: 5px;
}
table.diff pre {
font-size: 1.15rem;
scrollbar-color: black #999;
}
table.udiff pre {
padding: 0 0
}
td.difftxt {
width: 52rem;
}
td.diffln ins {
background-color: #559855;
color: #000;
|
| ︙ | ︙ |
Changes to skins/eagle/header.txt.
| ︙ | ︙ | |||
101 102 103 104 105 106 107 |
html "<a id='hbbtn' href='$home/sitemap' aria-label='Site Map'>☰</a>\n"
builtin_request_js hbmenu.js
foreach {name url expr class} $mainmenu {
if {![capexpr $expr]} continue
if {[string match /* $url]} {set url $home$url}
html "<a href='$url' class='$class'>$name</a>\n"
}
| < < < < < | 101 102 103 104 105 106 107 108 109 |
html "<a id='hbbtn' href='$home/sitemap' aria-label='Site Map'>☰</a>\n"
builtin_request_js hbmenu.js
foreach {name url expr class} $mainmenu {
if {![capexpr $expr]} continue
if {[string match /* $url]} {set url $home$url}
html "<a href='$url' class='$class'>$name</a>\n"
}
</th1></div>
<div id="hbdrop"></div>
|
Changes to src/alerts.c.
| ︙ | ︙ | |||
946 947 948 949 950 951 952 |
fossil_print("%s", blob_str(&all));
}
blob_reset(&all);
}
/*
** SETTING: email-url width=40
| > > | | > > | 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 |
fossil_print("%s", blob_str(&all));
}
blob_reset(&all);
}
/*
** SETTING: email-url width=40
** This is the main URL used to access the repository for cloning or
** syncing or for operating the web interface. It is also
** the basename for hyperlinks included in email alert text.
** Omit the trailing "/". If the repository is not intended to be
** a long-running server and will not be sending email notifications,
** then leave this setting blank.
*/
/*
** SETTING: email-admin width=40
** This is the email address for the human administrator for the system.
** Abuse and trouble reports and password reset requests are send here.
*/
/*
|
| ︙ | ︙ | |||
1525 1526 1527 1528 1529 1530 1531 |
cgi_set_parameter_nocopy("sa","1",1);
if( g.perm.Read ) cgi_set_parameter_nocopy("sc","1",1);
if( g.perm.RdForum ) cgi_set_parameter_nocopy("sf","1",1);
if( g.perm.RdTkt ) cgi_set_parameter_nocopy("st","1",1);
if( g.perm.RdWiki ) cgi_set_parameter_nocopy("sw","1",1);
}
@ <p>To receive email notifications for changes to this
| | | 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 |
cgi_set_parameter_nocopy("sa","1",1);
if( g.perm.Read ) cgi_set_parameter_nocopy("sc","1",1);
if( g.perm.RdForum ) cgi_set_parameter_nocopy("sf","1",1);
if( g.perm.RdTkt ) cgi_set_parameter_nocopy("st","1",1);
if( g.perm.RdWiki ) cgi_set_parameter_nocopy("sw","1",1);
}
@ <p>To receive email notifications for changes to this
@ repository, fill out the form below and press the "Submit" button.</p>
form_begin(0, "%R/subscribe");
@ <table class="subscribe">
@ <tr>
@ <td class="form_label">Email Address:</td>
@ <td><input type="text" name="e" value="%h(PD("e",""))" size="30"></td>
@ <tr>
if( eErr==1 ){
|
| ︙ | ︙ |
Changes to src/allrepo.c.
| ︙ | ︙ | |||
96 97 98 99 100 101 102 | ** git CMD Do the "git export" or "git status" command (which every ** is specified by CMD) on all repositories for which ** a Git mirror has been previously established. ** ** info Run the "info" command on all repositories. ** ** pull Run a "pull" operation on all repositories. Only the | | | | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | ** git CMD Do the "git export" or "git status" command (which every ** is specified by CMD) on all repositories for which ** a Git mirror has been previously established. ** ** info Run the "info" command on all repositories. ** ** pull Run a "pull" operation on all repositories. Only the ** --verbose and --share-links options are supported. ** ** push Run a "push" on all repositories. Only the --verbose ** option is supported. ** ** rebuild Rebuild on all repositories. The command line options ** supported by the rebuild command itself, if any are ** present, are passed along verbatim. The --force and ** --randomize options are not supported. ** ** sync Run a "sync" on all repositories. Only the --verbose ** and --unversioned and --share-links options are supported. ** ** set Run the "setting" or "set" commands on all ** repositories. These command are particularly useful in ** conjunction with the "max-loadavg" setting which cannot ** otherwise be set globally. ** ** unset Run the "unset" command on all repositories |
| ︙ | ︙ | |||
265 266 267 268 269 270 271 272 273 274 275 276 277 278 |
}
}else if( strncmp(zCmd, "push", n)==0 ){
zCmd = "push -autourl -R";
collect_argument(&extra, "verbose","v");
}else if( strncmp(zCmd, "pull", n)==0 ){
zCmd = "pull -autourl -R";
collect_argument(&extra, "verbose","v");
}else if( strncmp(zCmd, "rebuild", n)==0 ){
zCmd = "rebuild";
collect_argument(&extra, "cluster",0);
collect_argument(&extra, "compress",0);
collect_argument(&extra, "compress-only",0);
collect_argument(&extra, "noverify",0);
collect_argument_value(&extra, "pagesize");
| > | 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
}
}else if( strncmp(zCmd, "push", n)==0 ){
zCmd = "push -autourl -R";
collect_argument(&extra, "verbose","v");
}else if( strncmp(zCmd, "pull", n)==0 ){
zCmd = "pull -autourl -R";
collect_argument(&extra, "verbose","v");
collect_argument(&extra, "share-links",0);
}else if( strncmp(zCmd, "rebuild", n)==0 ){
zCmd = "rebuild";
collect_argument(&extra, "cluster",0);
collect_argument(&extra, "compress",0);
collect_argument(&extra, "compress-only",0);
collect_argument(&extra, "noverify",0);
collect_argument_value(&extra, "pagesize");
|
| ︙ | ︙ | |||
291 292 293 294 295 296 297 298 299 300 301 302 303 304 |
zCmd = "unset -R";
collect_argv(&extra, 3);
}else if( strncmp(zCmd, "fts-config", n)==0 ){
zCmd = "fts-config -R";
collect_argv(&extra, 3);
}else if( strncmp(zCmd, "sync", n)==0 ){
zCmd = "sync -autourl -R";
collect_argument(&extra, "verbose","v");
collect_argument(&extra, "unversioned","u");
}else if( strncmp(zCmd, "test-integrity", n)==0 ){
collect_argument(&extra, "db-only", "d");
collect_argument(&extra, "parse", 0);
collect_argument(&extra, "quick", "q");
zCmd = "test-integrity";
| > | 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 |
zCmd = "unset -R";
collect_argv(&extra, 3);
}else if( strncmp(zCmd, "fts-config", n)==0 ){
zCmd = "fts-config -R";
collect_argv(&extra, 3);
}else if( strncmp(zCmd, "sync", n)==0 ){
zCmd = "sync -autourl -R";
collect_argument(&extra, "share-links",0);
collect_argument(&extra, "verbose","v");
collect_argument(&extra, "unversioned","u");
}else if( strncmp(zCmd, "test-integrity", n)==0 ){
collect_argument(&extra, "db-only", "d");
collect_argument(&extra, "parse", 0);
collect_argument(&extra, "quick", "q");
zCmd = "test-integrity";
|
| ︙ | ︙ |
Changes to src/blob.c.
| ︙ | ︙ | |||
15 16 17 18 19 20 21 | ** ******************************************************************************* ** ** A Blob is a variable-length containers for arbitrary string ** or binary data. */ #include "config.h" | < < < < | < | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | ** ******************************************************************************* ** ** A Blob is a variable-length containers for arbitrary string ** or binary data. */ #include "config.h" #include <zlib.h> #include "blob.h" #if defined(_WIN32) #include <fcntl.h> #include <io.h> #endif #if INTERFACE |
| ︙ | ︙ | |||
970 971 972 973 974 975 976 977 978 979 980 981 982 983 |
blob_append(pBlob, zBuf, n);
}
}
}else{
blob_resize(pBlob, nToRead);
n = fread(blob_buffer(pBlob), 1, nToRead, in);
blob_resize(pBlob, n);
}
return blob_size(pBlob);
}
/*
** Initialize a blob to be the content of a file. If the filename
** is blank or "-" then read from standard input.
| > > > > > > > > > > > > > > > > > > > > > > > > | 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 |
blob_append(pBlob, zBuf, n);
}
}
}else{
blob_resize(pBlob, nToRead);
n = fread(blob_buffer(pBlob), 1, nToRead, in);
blob_resize(pBlob, n);
}
return blob_size(pBlob);
}
/*
** Initialize a blob to the data read from HTTP input. Return
** the number of bytes read into the blob. Any prior content
** of the blob is discarded, not freed.
*/
int blob_read_from_cgi(Blob *pBlob, int nToRead){
size_t n;
blob_zero(pBlob);
if( nToRead<0 ){
char zBuf[10000];
while( !cgi_feof() ){
n = cgi_fread(zBuf, sizeof(zBuf));
if( n>0 ){
blob_append(pBlob, zBuf, n);
}
}
}else{
blob_resize(pBlob, nToRead);
n = cgi_fread(blob_buffer(pBlob), nToRead);
blob_resize(pBlob, n);
}
return blob_size(pBlob);
}
/*
** Initialize a blob to be the content of a file. If the filename
** is blank or "-" then read from standard input.
|
| ︙ | ︙ |
Changes to src/cgi.c.
| ︙ | ︙ | |||
11 12 13 14 15 16 17 | ** ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** | | | > > > > > > > > > > > > > > > > > > | > | > > > > > > > > > > > > > | > > > > | > | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | ** ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This file began as a set of C functions and procedures used intepret ** CGI environment variables for Fossil web pages that were invoked by ** CGI. That's where the file name comes from. But over the years it ** has grown to incorporate lots of related functionality, including: ** ** * Interpreting CGI environment variables when Fossil is run as ** CGI (the original purpose). ** ** * Interpreting HTTP requests received directly or via an SSH tunnel. ** ** * Interpreting SCGI requests ** ** * Generating appropriate replies to CGI, SCGI, and HTTP requests. ** ** * Listening for incoming HTTP requests and dispatching them. ** (Used by "fossil ui" and "fossil server", for example). ** ** So, even though the name of this file implies that it only deals with ** CGI, in fact, the code in this file is used to interpret webpage requests ** received by a variety of means, and to generate well-formatted replies ** to those requests. ** ** The code in this file abstracts the web-request so that downstream ** modules that generate the body of the reply (based on the requested page) ** do not need to know if the request is coming from CGI, direct HTTP, ** SCGI, or some other means. ** ** This module gathers information about web page request into a key/value ** store. Keys and values come from: ** ** * Query parameters ** * POST parameter ** * Cookies ** * Environment variables ** ** The parameters are accessed using cgi_parameter() and similar functions ** or their convenience macros P() and similar. ** ** Environment variable parameters are set as if the request were coming ** in over CGI even if the request arrived via SCGI or direct HTTP. Thus ** the downstream modules that are trying to interpret the request do not ** need to know the request protocol - they can just request the values ** of environment variables and everything will always work. ** ** This file contains routines used by Fossil when it is acting as a ** CGI client. For the code used by Fossil when it is acting as a ** CGI server (for the /ext webpage) see the "extcgi.c" source file. */ #include "config.h" #ifdef _WIN32 |
| ︙ | ︙ | |||
45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
#ifdef __EMX__
typedef int socklen_t;
#endif
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "cgi.h"
#include "cygsup.h"
#if INTERFACE
/*
** Shortcuts for cgi_parameter. P("x") returns the value of query parameter
** or cookie "x", or NULL if there is no such parameter or cookie. PD("x","y")
| > | 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
#ifdef __EMX__
typedef int socklen_t;
#endif
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include "cgi.h"
#include "cygsup.h"
#if INTERFACE
/*
** Shortcuts for cgi_parameter. P("x") returns the value of query parameter
** or cookie "x", or NULL if there is no such parameter or cookie. PD("x","y")
|
| ︙ | ︙ | |||
90 91 92 93 94 95 96 | #define CGI_SSH_CLIENT 0x0001 /* Client is SSH */ #define CGI_SSH_COMPAT 0x0002 /* Compat for old SSH transport */ #define CGI_SSH_FOSSIL 0x0004 /* Use new Fossil SSH transport */ #endif /* INTERFACE */ /* | | > > > > > > > > > > > | 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
#define CGI_SSH_CLIENT 0x0001 /* Client is SSH */
#define CGI_SSH_COMPAT 0x0002 /* Compat for old SSH transport */
#define CGI_SSH_FOSSIL 0x0004 /* Use new Fossil SSH transport */
#endif /* INTERFACE */
/*
** The reply content is generated in two pieces: the header and the body.
** These pieces are generated separately because they are not necessarily
** produced in order. Parts of the header might be built after all or
** part of the body. The header and body are accumulated in separate
** Blob structures then output sequentially once everything has been
** built.
**
** Do not confuse the content header with the HTTP header. The content header
** is generated by downstream code. The HTTP header is generated by the
** cgi_reply() routine below.
**
** The content header and contenty body are *approximately* the <head>
** element and the <body> elements for HTML replies. However this is only
** approximate. The content header also includes parts of <body> that
** show the banner and menu bar at the top of each page. Also note that
** not all replies are HTML, but there can still be separate header and
** body sections of the content.
**
** The cgi_destination() interface switches between the buffers.
*/
static Blob cgiContent[2] = { BLOB_INITIALIZER, BLOB_INITIALIZER };
static Blob *pContent = &cgiContent[0];
/*
|
| ︙ | ︙ | |||
122 123 124 125 126 127 128 |
default: {
cgi_panic("bad destination");
}
}
}
/*
| | | | | | | | > > | | > > > > > > > | | | 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 |
default: {
cgi_panic("bad destination");
}
}
}
/*
** Check to see if the content header or body contains the zNeedle string.
** Return true if it does and false if it does not.
*/
int cgi_header_contains(const char *zNeedle){
return strstr(blob_str(&cgiContent[0]), zNeedle)!=0;
}
int cgi_body_contains(const char *zNeedle){
return strstr(blob_str(&cgiContent[1]), zNeedle)!=0;
}
/*
** Append new reply content to what already exists.
*/
void cgi_append_content(const char *zData, int nAmt){
blob_append(pContent, zData, nAmt);
}
/*
** Reset both reply content buffers to be empty.
*/
void cgi_reset_content(void){
blob_reset(&cgiContent[0]);
blob_reset(&cgiContent[1]);
}
/*
** Return a pointer to Blob that is currently accumulating reply content.
*/
Blob *cgi_output_blob(void){
return pContent;
}
/*
** Return the content header as a text string
*/
const char *cgi_header(void){
return blob_str(&cgiContent[0]);
}
/*
** Combine the header and body content all into the header buffer.
** In other words, append the body content to the end of the header
** content.
*/
static void cgi_combine_header_and_body(void){
int size = blob_size(&cgiContent[1]);
if( size>0 ){
blob_append(&cgiContent[0], blob_buffer(&cgiContent[1]), size);
blob_reset(&cgiContent[1]);
}
}
/*
** Return a pointer to the combined header+body content.
*/
char *cgi_extract_content(void){
cgi_combine_header_and_body();
return blob_buffer(&cgiContent[0]);
}
/*
** Additional information used to form the HTTP reply
*/
static const char *zContentType = "text/html"; /* Content type of the reply */
static const char *zReplyStatus = "OK"; /* Reply status description */
static int iReplyStatus = 200; /* Reply status code */
static Blob extraHeader = BLOB_INITIALIZER; /* Extra header text */
static int rangeStart = 0; /* Start of Range: */
static int rangeEnd = 0; /* End of Range: plus 1 */
/*
** Set the reply content type.
**
** The reply content type defaults to "text/html". It only needs to be
** changed (by calling this routine) in the exceptional case where some
** other content type is being returned.
*/
void cgi_set_content_type(const char *zType){
zContentType = fossil_strdup(zType);
}
/*
** Erase any existing reply content. Replace is with a pNewContent.
**
** This routine erases pNewContent. In other words, it move pNewContent
** into the content buffer.
*/
void cgi_set_content(Blob *pNewContent){
cgi_reset_content();
cgi_destination(CGI_HEADER);
cgiContent[0] = *pNewContent;
blob_zero(pNewContent);
}
/*
** Set the reply status code
*/
void cgi_set_status(int iStat, const char *zStat){
zReplyStatus = fossil_strdup(zStat);
iReplyStatus = iStat;
}
/*
** Append text to the content header buffer.
*/
void cgi_append_header(const char *zLine){
blob_append(&extraHeader, zLine, -1);
}
void cgi_printf_header(const char *zLine, ...){
va_list ap;
va_start(ap, zLine);
|
| ︙ | ︙ | |||
274 275 276 277 278 279 280 281 282 |
static int is_gzippable(void){
if( g.fNoHttpCompress ) return 0;
if( strstr(PD("HTTP_ACCEPT_ENCODING", ""), "gzip")==0 ) return 0;
return strncmp(zContentType, "text/", 5)==0
|| sqlite3_strglob("application/*xml", zContentType)==0
|| sqlite3_strglob("application/*javascript", zContentType)==0;
}
/*
| > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | | | | | | | | | | | | | | > > | | > | | 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 |
static int is_gzippable(void){
if( g.fNoHttpCompress ) return 0;
if( strstr(PD("HTTP_ACCEPT_ENCODING", ""), "gzip")==0 ) return 0;
return strncmp(zContentType, "text/", 5)==0
|| sqlite3_strglob("application/*xml", zContentType)==0
|| sqlite3_strglob("application/*javascript", zContentType)==0;
}
/*
** The following routines read or write content from/to the wire for
** an HTTP request. Depending on settings the content might be coming
** from or going to a socket, or a file, or it might come from or go
** to an SSL decoder/encoder.
*/
/*
** Works like fgets():
**
** Read a single line of input into s[]. Ensure that s[] is zero-terminated.
** The s[] buffer is size bytes and so at most size-1 bytes will be read.
**
** Return a pointer to s[] on success, or NULL at end-of-input.
*/
static char *cgi_fgets(char *s, int size){
if( !g.httpUseSSL ){
return fgets(s, size, g.httpIn);
}
#ifdef FOSSIL_ENABLE_SSL
return ssl_gets(g.httpSSLConn, s, size);
#else
fossil_fatal("SSL not available");
#endif
}
/* Works like fread():
**
** Read as many as bytes of content as we can, up to a maximum of nmemb
** bytes. Return the number of bytes read. Return -1 if there is no
** further input or if an I/O error occurs.
*/
size_t cgi_fread(void *ptr, size_t nmemb){
if( !g.httpUseSSL ){
return fread(ptr, 1, nmemb, g.httpIn);
}
#ifdef FOSSIL_ENABLE_SSL
return ssl_read_server(g.httpSSLConn, ptr, nmemb);
#else
fossil_fatal("SSL not available");
#endif
}
/* Works like feof():
**
** Return true if end-of-input has been reached.
*/
int cgi_feof(void){
if( !g.httpUseSSL ){
return feof(g.httpIn);
}
#ifdef FOSSIL_ENABLE_SSL
return ssl_eof(g.httpSSLConn);
#else
return 1;
#endif
}
/* Works like fwrite():
**
** Try to output nmemb bytes of content. Return the number of
** bytes actually written.
*/
static size_t cgi_fwrite(void *ptr, size_t nmemb){
if( !g.httpUseSSL ){
return fwrite(ptr, 1, nmemb, g.httpOut);
}
#ifdef FOSSIL_ENABLE_SSL
return ssl_write_server(g.httpSSLConn, ptr, nmemb);
#else
fossil_fatal("SSL not available");
#endif
}
/* Works like fflush():
**
** Make sure I/O has completed.
*/
static void cgi_fflush(void){
if( !g.httpUseSSL ){
fflush(g.httpOut);
}
}
/*
** Generate the reply to a web request. The output might be an
** full HTTP response, or a CGI response, depending on how things have
** be set up.
**
** The reply consists of a response header (an HTTP or CGI response header)
** followed by the concatenation of the content header and content body.
*/
void cgi_reply(void){
Blob hdr = BLOB_INITIALIZER;
int total_size;
if( iReplyStatus<=0 ){
iReplyStatus = 200;
zReplyStatus = "OK";
}
if( g.fullHttpReply ){
if( rangeEnd>0
&& iReplyStatus==200
&& fossil_strcmp(P("REQUEST_METHOD"),"GET")==0
){
iReplyStatus = 206;
zReplyStatus = "Partial Content";
}
blob_appendf(&hdr, "HTTP/1.0 %d %s\r\n", iReplyStatus, zReplyStatus);
blob_appendf(&hdr, "Date: %s\r\n", cgi_rfc822_datestamp(time(0)));
blob_appendf(&hdr, "Connection: close\r\n");
blob_appendf(&hdr, "X-UA-Compatible: IE=edge\r\n");
}else{
assert( rangeEnd==0 );
blob_appendf(&hdr, "Status: %d %s\r\n", iReplyStatus, zReplyStatus);
}
if( etag_tag()[0]!=0 ){
blob_appendf(&hdr, "ETag: %s\r\n", etag_tag());
blob_appendf(&hdr, "Cache-Control: max-age=%d\r\n", etag_maxage());
if( etag_mtime()>0 ){
blob_appendf(&hdr, "Last-Modified: %s\r\n",
cgi_rfc822_datestamp(etag_mtime()));
}
}else if( g.isConst ){
/* isConst means that the reply is guaranteed to be invariant, even
** after configuration changes and/or Fossil binary recompiles. */
blob_appendf(&hdr, "Cache-Control: max-age=315360000, immutable\r\n");
}else{
blob_appendf(&hdr, "Cache-control: no-cache\r\n");
}
if( blob_size(&extraHeader)>0 ){
blob_appendf(&hdr, "%s", blob_buffer(&extraHeader));
}
/* Add headers to turn on useful security options in browsers. */
blob_appendf(&hdr, "X-Frame-Options: SAMEORIGIN\r\n");
/* This stops fossil pages appearing in frames or iframes, preventing
** click-jacking attacks on supporting browsers.
**
** Other good headers would be
** Strict-Transport-Security: max-age=62208000
** if we're using https. However, this would break sites which serve different
** content on http and https protocols. Also,
** X-Content-Security-Policy: allow 'self'
** would help mitigate some XSS and data injection attacks, but will break
** deliberate inclusion of external resources, such as JavaScript syntax
** highlighter scripts.
**
** These headers are probably best added by the web server hosting fossil as
** a CGI script.
*/
/* Content intended for logged in users should only be cached in
** the browser, not some shared location.
*/
if( iReplyStatus!=304 ) {
blob_appendf(&hdr, "Content-Type: %s; charset=utf-8\r\n", zContentType);
if( fossil_strcmp(zContentType,"application/x-fossil")==0 ){
cgi_combine_header_and_body();
blob_compress(&cgiContent[0], &cgiContent[0]);
}
if( is_gzippable() && iReplyStatus!=206 ){
int i;
gzip_begin(0);
for( i=0; i<2; i++ ){
int size = blob_size(&cgiContent[i]);
if( size>0 ) gzip_step(blob_buffer(&cgiContent[i]), size);
blob_reset(&cgiContent[i]);
}
gzip_finish(&cgiContent[0]);
blob_appendf(&hdr, "Content-Encoding: gzip\r\n");
blob_appendf(&hdr, "Vary: Accept-Encoding\r\n");
}
total_size = blob_size(&cgiContent[0]) + blob_size(&cgiContent[1]);
if( iReplyStatus==206 ){
blob_appendf(&hdr, "Content-Range: bytes %d-%d/%d\r\n",
rangeStart, rangeEnd-1, total_size);
total_size = rangeEnd - rangeStart;
}
blob_appendf(&hdr, "Content-Length: %d\r\n", total_size);
}else{
total_size = 0;
}
blob_appendf(&hdr, "\r\n");
cgi_fwrite(blob_buffer(&hdr), blob_size(&hdr));
blob_reset(&hdr);
if( total_size>0
&& iReplyStatus!=304
&& fossil_strcmp(P("REQUEST_METHOD"),"HEAD")!=0
){
int i, size;
for(i=0; i<2; i++){
size = blob_size(&cgiContent[i]);
if( size<=rangeStart ){
rangeStart -= size;
}else{
int n = size - rangeStart;
if( n>total_size ){
n = total_size;
}
cgi_fwrite(blob_buffer(&cgiContent[i])+rangeStart, n);
rangeStart = 0;
total_size -= n;
}
}
}
cgi_fflush();
CGIDEBUG(("-------- END cgi ---------\n"));
/* After the webpage has been sent, do any useful background
** processing.
*/
g.cgiOutput = 2;
if( g.db!=0 && iReplyStatus==200 ){
backoffice_check_if_needed();
}
}
/*
** Generate an HTTP or CGI redirect response that causes a redirect
** to the URL given in the argument.
**
** The URL must be relative to the base of the fossil server.
*/
NORETURN void cgi_redirect_with_status(
const char *zURL,
int iStat,
const char *zStat
|
| ︙ | ︙ | |||
469 470 471 472 473 474 475 | } cgi_append_header(z); fossil_free(z); } /* ** Return the URL for the caller. This is obtained from either the | | | 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 |
}
cgi_append_header(z);
fossil_free(z);
}
/*
** Return the URL for the caller. This is obtained from either the
** "referer" CGI parameter, if it exists, or the HTTP_REFERER HTTP parameter.
** If neither exist, return zDefault.
*/
const char *cgi_referer(const char *zDefault){
const char *zRef = P("referer");
if( zRef==0 ){
zRef = P("HTTP_REFERER");
if( zRef==0 ) zRef = zDefault;
|
| ︙ | ︙ | |||
505 506 507 508 509 510 511 | nBase = (int)strlen(g.zBaseURL); if( strncmp(g.zBaseURL,zRef,nBase)!=0 ) return 0; if( zRef[nBase]!=0 && zRef[nBase]!='/' ) return 0; return 1; } /* | | | | 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 |
nBase = (int)strlen(g.zBaseURL);
if( strncmp(g.zBaseURL,zRef,nBase)!=0 ) return 0;
if( zRef[nBase]!=0 && zRef[nBase]!='/' ) return 0;
return 1;
}
/*
** Information about all query parameters, post parameter, cookies and
** CGI environment variables are stored in a hash table as follows:
*/
static int nAllocQP = 0; /* Space allocated for aParamQP[] */
static int nUsedQP = 0; /* Space actually used in aParamQP[] */
static int sortQP = 0; /* True if aParamQP[] needs sorting */
static int seqQP = 0; /* Sequence numbers */
static struct QParam { /* One entry for each query parameter or cookie */
const char *zName; /* Parameter or cookie name */
|
| ︙ | ︙ | |||
644 645 646 647 648 649 650 |
}
return;
}
}
}
/*
| | | | 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 |
}
return;
}
}
}
/*
** Add an environment varaible value to the parameter set. The zName
** portion is fixed but a copy is be made of zValue.
*/
void cgi_setenv(const char *zName, const char *zValue){
cgi_set_parameter_nocopy(zName, fossil_strdup(zValue), 0);
}
/*
** Add a list of query parameters or cookies to the parameter set.
|
| ︙ | ︙ | |||
1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 |
}
}
fputs(z, pLog);
}
/* Forward declaration */
static NORETURN void malformed_request(const char *zMsg);
/*
** Initialize the query parameter database. Information is pulled from
** the QUERY_STRING environment variable (if it exists), from standard
** input if there is POST data, and from HTTP_COOKIE.
**
** REQUEST_URI, PATH_INFO, and SCRIPT_NAME are related as follows:
| > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 |
}
}
fputs(z, pLog);
}
/* Forward declaration */
static NORETURN void malformed_request(const char *zMsg);
/*
** Checks the QUERY_STRING environment variable, sets it up
** via add_param_list() and, if found, applies its "skin"
** setting. Returns 0 if no QUERY_STRING is set, 1 if it is,
** and 2 if it sets the skin (in which case the cookie may
** still need flushing by the page, via cookie_render()).
*/
int cgi_setup_query_string(void){
int rc = 0;
char * z = (char*)P("QUERY_STRING");
if( z ){
++rc;
z = fossil_strdup(z);
add_param_list(z, '&');
z = (char*)P("skin");
if(z){
char *zErr = skin_use_alternative(z, 2);
++rc;
if(!zErr && !P("once")){
cookie_write_parameter("skin","skin",z);
}
fossil_free(zErr);
}
}
return rc;
}
/*
** Initialize the query parameter database. Information is pulled from
** the QUERY_STRING environment variable (if it exists), from standard
** input if there is POST data, and from HTTP_COOKIE.
**
** REQUEST_URI, PATH_INFO, and SCRIPT_NAME are related as follows:
|
| ︙ | ︙ | |||
1163 1164 1165 1166 1167 1168 1169 |
add_param_list(z, ';');
z = (char*)cookie_value("skin",0);
if(z){
skin_use_alternative(z, 2);
}
}
| | < < < < < < < < < < < < | > > | > | | 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 |
add_param_list(z, ';');
z = (char*)cookie_value("skin",0);
if(z){
skin_use_alternative(z, 2);
}
}
cgi_setup_query_string();
z = (char*)P("REMOTE_ADDR");
if( z ){
g.zIpAddr = fossil_strdup(z);
}
len = atoi(PD("CONTENT_LENGTH", "0"));
zType = P("CONTENT_TYPE");
zSemi = zType ? strchr(zType, ';') : 0;
if( zSemi ){
g.zContentType = fossil_strndup(zType, (int)(zSemi-zType));
zType = g.zContentType;
}else{
g.zContentType = zType;
}
blob_zero(&g.cgiIn);
if( len>0 && zType ){
if( fossil_strcmp(zType, "application/x-fossil")==0 ){
if( blob_read_from_cgi(&g.cgiIn, len)!=len ){
malformed_request("CGI content-length mismatch");
}
blob_uncompress(&g.cgiIn, &g.cgiIn);
}
#ifdef FOSSIL_ENABLE_JSON
else if( noJson==0 && g.json.isJsonMode!=0
&& json_can_consume_content_type(zType)!=0 ){
assert( !g.httpUseSSL );
cgi_parse_POST_JSON(g.httpIn, (unsigned int)len);
/*
Potential TODOs:
1) If parsing fails, immediately return an error response
without dispatching the ostensibly-upcoming JSON API.
*/
cgi_set_content_type(json_guess_content_type());
}
#endif /* FOSSIL_ENABLE_JSON */
else{
blob_read_from_cgi(&g.cgiIn, len);
}
}
}
/*
** Decode POST parameter information in the cgiIn content, if any.
*/
|
| ︙ | ︙ | |||
1729 1730 1731 1732 1733 1734 1735 |
*/
void cgi_handle_http_request(const char *zIpAddr){
char *z, *zToken;
int i;
const char *zScheme = "http";
char zLine[2000]; /* A single line of input. */
g.fullHttpReply = 1;
| | | | > > | 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 |
*/
void cgi_handle_http_request(const char *zIpAddr){
char *z, *zToken;
int i;
const char *zScheme = "http";
char zLine[2000]; /* A single line of input. */
g.fullHttpReply = 1;
if( cgi_fgets(zLine, sizeof(zLine))==0 ){
malformed_request("missing HTTP header");
}
blob_append(&g.httpHeader, zLine, -1);
cgi_trace(zLine);
zToken = extract_token(zLine, &z);
if( zToken==0 ){
malformed_request("malformed HTTP header");
}
if( fossil_strcmp(zToken,"GET")!=0
&& fossil_strcmp(zToken,"POST")!=0
&& fossil_strcmp(zToken,"HEAD")!=0
){
malformed_request("unsupported HTTP method");
}
cgi_setenv("GATEWAY_INTERFACE","CGI/1.0");
cgi_setenv("REQUEST_METHOD",zToken);
zToken = extract_token(z, &z);
if( zToken==0 ){
malformed_request("malformed URL in HTTP header");
|
| ︙ | ︙ | |||
1765 1766 1767 1768 1769 1770 1771 |
cgi_setenv("REMOTE_ADDR", zIpAddr);
g.zIpAddr = fossil_strdup(zIpAddr);
}
/* Get all the optional fields that follow the first line.
*/
| | | 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 |
cgi_setenv("REMOTE_ADDR", zIpAddr);
g.zIpAddr = fossil_strdup(zIpAddr);
}
/* Get all the optional fields that follow the first line.
*/
while( cgi_fgets(zLine,sizeof(zLine)) ){
char *zFieldName;
char *zVal;
cgi_trace(zLine);
blob_append(&g.httpHeader, zLine, -1);
zFieldName = extract_token(zLine,&zVal);
if( zFieldName==0 || *zFieldName==0 ) break;
|
| ︙ | ︙ | |||
1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 |
static int nCycles = 0;
static char *zCmd = 0;
char *z, *zToken;
const char *zType = 0;
int i, content_length = 0;
char zLine[2000]; /* A single line of input. */
#ifdef FOSSIL_ENABLE_JSON
if( nCycles==0 ){ json_bootstrap_early(); }
#endif
if( zIpAddr ){
if( nCycles==0 ){
cgi_setenv("REMOTE_ADDR", zIpAddr);
g.zIpAddr = fossil_strdup(zIpAddr);
| > | 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 |
static int nCycles = 0;
static char *zCmd = 0;
char *z, *zToken;
const char *zType = 0;
int i, content_length = 0;
char zLine[2000]; /* A single line of input. */
assert( !g.httpUseSSL );
#ifdef FOSSIL_ENABLE_JSON
if( nCycles==0 ){ json_bootstrap_early(); }
#endif
if( zIpAddr ){
if( nCycles==0 ){
cgi_setenv("REMOTE_ADDR", zIpAddr);
g.zIpAddr = fossil_strdup(zIpAddr);
|
| ︙ | ︙ | |||
1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 |
}
/*
** This routine handles the old fossil SSH probes
*/
char *cgi_handle_ssh_probes(char *zLine, int zSize, char *z, char *zToken){
/* Start looking for probes */
while( fossil_strcmp(zToken, "echo")==0 ){
zToken = extract_token(z, &z);
if( zToken==0 ){
malformed_request("malformed probe");
}
if( fossil_strncmp(zToken, "test", 4)==0 ||
fossil_strncmp(zToken, "probe-", 6)==0 ){
| > | 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 |
}
/*
** This routine handles the old fossil SSH probes
*/
char *cgi_handle_ssh_probes(char *zLine, int zSize, char *z, char *zToken){
/* Start looking for probes */
assert( !g.httpUseSSL );
while( fossil_strcmp(zToken, "echo")==0 ){
zToken = extract_token(z, &z);
if( zToken==0 ){
malformed_request("malformed probe");
}
if( fossil_strncmp(zToken, "test", 4)==0 ||
fossil_strncmp(zToken, "probe-", 6)==0 ){
|
| ︙ | ︙ | |||
2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 |
** This routine handles the old fossil SSH transport_flip
** and transport_open communications if detected.
*/
void cgi_handle_ssh_transport(const char *zCmd){
char *z, *zToken;
char zLine[2000]; /* A single line of input. */
/* look for second newline of transport_flip */
if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
malformed_request("incorrect transport_flip");
}
cgi_trace(zLine);
zToken = extract_token(zLine, &z);
if( zToken && strlen(zToken)==0 ){
| > | 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 |
** This routine handles the old fossil SSH transport_flip
** and transport_open communications if detected.
*/
void cgi_handle_ssh_transport(const char *zCmd){
char *z, *zToken;
char zLine[2000]; /* A single line of input. */
assert( !g.httpUseSSL );
/* look for second newline of transport_flip */
if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
malformed_request("incorrect transport_flip");
}
cgi_trace(zLine);
zToken = extract_token(zLine, &z);
if( zToken && strlen(zToken)==0 ){
|
| ︙ | ︙ | |||
2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 |
void cgi_handle_scgi_request(void){
char *zHdr;
char *zToFree;
int nHdr = 0;
int nRead;
int c, n, m;
while( (c = fgetc(g.httpIn))!=EOF && fossil_isdigit((char)c) ){
nHdr = nHdr*10 + (char)c - '0';
}
if( nHdr<16 ) malformed_request("SCGI header too short");
zToFree = zHdr = fossil_malloc(nHdr);
nRead = (int)fread(zHdr, 1, nHdr, g.httpIn);
if( nRead<nHdr ) malformed_request("cannot read entire SCGI header");
| > | 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 |
void cgi_handle_scgi_request(void){
char *zHdr;
char *zToFree;
int nHdr = 0;
int nRead;
int c, n, m;
assert( !g.httpUseSSL );
while( (c = fgetc(g.httpIn))!=EOF && fossil_isdigit((char)c) ){
nHdr = nHdr*10 + (char)c - '0';
}
if( nHdr<16 ) malformed_request("SCGI header too short");
zToFree = zHdr = fossil_malloc(nHdr);
nRead = (int)fread(zHdr, 1, nHdr, g.httpIn);
if( nRead<nHdr ) malformed_request("cannot read entire SCGI header");
|
| ︙ | ︙ | |||
2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 | ** Bitmap values for the flags parameter to cgi_http_server(). */ #define HTTP_SERVER_LOCALHOST 0x0001 /* Bind to 127.0.0.1 only */ #define HTTP_SERVER_SCGI 0x0002 /* SCGI instead of HTTP */ #define HTTP_SERVER_HAD_REPOSITORY 0x0004 /* Was the repository open? */ #define HTTP_SERVER_HAD_CHECKOUT 0x0008 /* Was a checkout open? */ #define HTTP_SERVER_REPOLIST 0x0010 /* Allow repo listing */ #endif /* INTERFACE */ /* ** Maximum number of child processes that we can have running ** at one time. Set this to 0 for "no limit". */ | > | 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 | ** Bitmap values for the flags parameter to cgi_http_server(). */ #define HTTP_SERVER_LOCALHOST 0x0001 /* Bind to 127.0.0.1 only */ #define HTTP_SERVER_SCGI 0x0002 /* SCGI instead of HTTP */ #define HTTP_SERVER_HAD_REPOSITORY 0x0004 /* Was the repository open? */ #define HTTP_SERVER_HAD_CHECKOUT 0x0008 /* Was a checkout open? */ #define HTTP_SERVER_REPOLIST 0x0010 /* Allow repo listing */ #define HTTP_SERVER_NOFORK 0x0020 /* Do not call fork() */ #endif /* INTERFACE */ /* ** Maximum number of child processes that we can have running ** at one time. Set this to 0 for "no limit". */ |
| ︙ | ︙ | |||
2186 2187 2188 2189 2190 2191 2192 |
fossil_fatal("unable to open listening socket on any"
" port in the range %d..%d", mnPort, mxPort);
}
}
if( iPort>mxPort ) return 1;
listen(listener,10);
fossil_print("Listening for %s requests on TCP port %d\n",
| | > | 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 |
fossil_fatal("unable to open listening socket on any"
" port in the range %d..%d", mnPort, mxPort);
}
}
if( iPort>mxPort ) return 1;
listen(listener,10);
fossil_print("Listening for %s requests on TCP port %d\n",
(flags & HTTP_SERVER_SCGI)!=0 ? "SCGI" :
g.httpUseSSL?"TLS-encrypted HTTPS":"HTTP", iPort);
fflush(stdout);
if( zBrowser ){
assert( strstr(zBrowser,"%d")!=0 );
zBrowser = mprintf(zBrowser /*works-like:"%d"*/, iPort);
#if defined(__CYGWIN__)
/* On Cygwin, we can do better than "echo" */
if( strncmp(zBrowser, "echo ", 5)==0 ){
|
| ︙ | ︙ | |||
2221 2222 2223 2224 2225 2226 2227 |
assert( listener>=0 );
FD_SET( listener, &readfds);
select( listener+1, &readfds, 0, 0, &delay);
if( FD_ISSET(listener, &readfds) ){
lenaddr = sizeof(inaddr);
connection = accept(listener, (struct sockaddr*)&inaddr, &lenaddr);
if( connection>=0 ){
| > > > | > | 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 |
assert( listener>=0 );
FD_SET( listener, &readfds);
select( listener+1, &readfds, 0, 0, &delay);
if( FD_ISSET(listener, &readfds) ){
lenaddr = sizeof(inaddr);
connection = accept(listener, (struct sockaddr*)&inaddr, &lenaddr);
if( connection>=0 ){
if( flags & HTTP_SERVER_NOFORK ){
child = 0;
}else{
child = fork();
}
if( child!=0 ){
if( child>0 ){
nchildren++;
nRequest++;
}
close(connection);
}else{
|
| ︙ | ︙ | |||
2316 2317 2318 2319 2320 2321 2322 |
struct tm *pTm;
time_t now = time(0);
pTm = gmtime(&now);
if( pTm==0 ){
return mprintf("");
}else{
return mprintf("%04d-%02d-%02d %02d:%02d:%02d",
| | > > > > > > > > > > | 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 |
struct tm *pTm;
time_t now = time(0);
pTm = gmtime(&now);
if( pTm==0 ){
return mprintf("");
}else{
return mprintf("%04d-%02d-%02d %02d:%02d:%02d",
pTm->tm_year+1900, pTm->tm_mon+1, pTm->tm_mday,
pTm->tm_hour, pTm->tm_min, pTm->tm_sec);
}
}
/*
** COMMAND: test-date
**
** Show the current date and time in both RFC822 and ISO8601.
*/
void test_date(void){
fossil_print("%z = ", cgi_iso8601_datestamp());
fossil_print("%z\n", cgi_rfc822_datestamp(time(0)));
}
/*
** Parse an RFC822-formatted timestamp as we'd expect from HTTP and return
** a Unix epoch time. <= zero is returned on failure.
**
** Note that this won't handle all the _allowed_ HTTP formats, just the
** most popular one (the one generated by cgi_rfc822_datestamp(), actually).
|
| ︙ | ︙ |
Changes to src/chat.c.
| ︙ | ︙ | |||
172 173 174 175 176 177 178 |
db_get("chat-alert-sound","alerts/plunk.wav"));
zProjectName = db_get("project-name","Unnamed project");
zInputPlaceholder0 =
mprintf("Type markdown-formatted message for %h.", zProjectName);
style_set_current_feature("chat");
style_header("Chat");
@ <div id='chat-input-area'>
| | > > > > > > > > | | | 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
db_get("chat-alert-sound","alerts/plunk.wav"));
zProjectName = db_get("project-name","Unnamed project");
zInputPlaceholder0 =
mprintf("Type markdown-formatted message for %h.", zProjectName);
style_set_current_feature("chat");
style_header("Chat");
@ <div id='chat-input-area'>
@ <div id='chat-input-line-wrapper' class='compact'>
@ <input type="text" id="chat-input-field-single" \
@ data-placeholder0="%h(zInputPlaceholder0)" \
@ data-placeholder="%h(zInputPlaceholder0)" \
@ class="chat-input-field"></input>
@ <textarea id="chat-input-field-multi" \
@ data-placeholder0="%h(zInputPlaceholder0)" \
@ data-placeholder="%h(zInputPlaceholder0)" \
@ class="chat-input-field hidden"></textarea>
@ <div contenteditable id="chat-input-field-x" \
@ data-placeholder0="%h(zInputPlaceholder0)" \
@ data-placeholder="%h(zInputPlaceholder0)" \
@ class="chat-input-field hidden"></div>
@ <div id='chat-buttons-wrapper'>
@ <span class='cbutton' id="chat-button-preview" \
@ title="Preview message (Shift-Enter)">👁</span>
@ <span class='cbutton' id="chat-button-attach" \
@ title="Attach file to message">%s(zPaperclip)</span>
@ <span class='cbutton' id="chat-button-settings" \
@ title="Configure chat">⚙</span>
|
| ︙ | ︙ | |||
342 343 344 345 346 347 348 349 350 351 352 353 354 |
** to be entered into the chat history.
**
** On success it responds with an empty response: the new message
** should be fetched via /chat-poll. On error, e.g. login expiry,
** it emits a JSON response in the same form as described for
** /chat-poll errors, but as a standalone object instead of a
** list of objects.
*/
void chat_send_webpage(void){
int nByte;
const char *zMsg;
const char *zUserName;
login_check_credentials();
| > > > > > > > > > > > > | | 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 |
** to be entered into the chat history.
**
** On success it responds with an empty response: the new message
** should be fetched via /chat-poll. On error, e.g. login expiry,
** it emits a JSON response in the same form as described for
** /chat-poll errors, but as a standalone object instead of a
** list of objects.
**
** Requests to this page should be POST, not GET. POST parameters
** include:
**
** msg The (Markdown) text of the message to be sent
**
** file The content of the file attachment
**
** lmtime ISO-8601 formatted date-time string showing the local time
** of the sender.
**
** At least one of the "msg" or "file" POST parameters must be provided.
*/
void chat_send_webpage(void){
int nByte;
const char *zMsg;
const char *zUserName;
login_check_credentials();
if( 0==g.perm.Chat ) {
chat_emit_permissions_error(0);
return;
}
chat_create_tables();
zUserName = (g.zLogin && g.zLogin[0]) ? g.zLogin : "nobody";
nByte = atoi(PD("file:bytes","0"));
zMsg = PD("msg","");
|
| ︙ | ︙ | |||
755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 |
** Invoking fetch("chat-delete/"+msgid) from javascript in the client
** will delete a chat entry from the CHAT table.
**
** This routine both deletes the identified chat entry and also inserts
** a new entry with the current timestamp and with:
**
** * xmsg = NULL
** * file = NULL
** * mdel = The msgid of the row that was deleted
**
** This new entry will then be propagated to all listeners so that they
** will know to delete their copies of the message too.
*/
void chat_delete_webpage(void){
int mdel;
| > > | 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 |
** Invoking fetch("chat-delete/"+msgid) from javascript in the client
** will delete a chat entry from the CHAT table.
**
** This routine both deletes the identified chat entry and also inserts
** a new entry with the current timestamp and with:
**
** * xmsg = NULL
**
** * file = NULL
**
** * mdel = The msgid of the row that was deleted
**
** This new entry will then be propagated to all listeners so that they
** will know to delete their copies of the message too.
*/
void chat_delete_webpage(void){
int mdel;
|
| ︙ | ︙ | |||
794 795 796 797 798 799 800 | ** This command performs actions associated with the /chat instance ** on the default remote Fossil repository (the Fossil repository whose ** URL shows when you run the "fossil remote" command) or to the URL ** specified by the --remote option. If there is no default remote ** Fossil repository and the --remote option is omitted, then this ** command fails with an error. ** | > > > > | | | | | < < > > > > > > > | 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 |
** This command performs actions associated with the /chat instance
** on the default remote Fossil repository (the Fossil repository whose
** URL shows when you run the "fossil remote" command) or to the URL
** specified by the --remote option. If there is no default remote
** Fossil repository and the --remote option is omitted, then this
** command fails with an error.
**
** Subcommands:
**
** > fossil chat
**
** When there is no SUBCOMMAND (when this command is simply "fossil chat")
** the response is to bring up a web-browser window to the chatroom
** on the default system web-browser. You can accomplish the same by
** typing the appropriate URL into the web-browser yourself. This
** command is merely a convenience for command-line oriented people.
**
** > fossil chat send [ARGUMENTS]
**
** This command sends a new message to the chatroom. The message
** to be sent is determined by arguments as follows:
**
** -f|--file FILENAME File to attach to the message
** --as FILENAME2 Causes --file FILENAME to be sent with
** the attachment name FILENAME2
** -m|--message TEXT Text of the chat message
** --remote URL Send to this remote URL
** --unsafe Allow the use of unencrypted http://
**
** > fossil chat url
**
** Show the default URL used to access the chat server.
**
** Additional subcommands may be added in the future.
*/
void chat_command(void){
const char *zUrl = find_option("remote",0,1);
int urlFlags = 0;
int isDefaultUrl = 0;
int i;
|
| ︙ | ︙ | |||
860 861 862 863 864 865 866 867 868 869 870 871 872 873 |
zCmd = mprintf("%s %s/chat?cli &", zBrowser, zUrl);
#else
zCmd = mprintf("%s \"%s/chat?cli\" &", zBrowser, zUrl);
#endif
fossil_system(zCmd);
}else if( strcmp(g.argv[2],"send")==0 ){
const char *zFilename = find_option("file","r",1);
const char *zMsg = find_option("message","m",1);
int allowUnsafe = find_option("unsafe",0,0)!=0;
const int mFlags = HTTP_GENERIC | HTTP_QUIET | HTTP_NOCOMPRESS;
int i;
const char *zPw;
char *zLMTime;
Blob up, down, fcontent;
| > | 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 |
zCmd = mprintf("%s %s/chat?cli &", zBrowser, zUrl);
#else
zCmd = mprintf("%s \"%s/chat?cli\" &", zBrowser, zUrl);
#endif
fossil_system(zCmd);
}else if( strcmp(g.argv[2],"send")==0 ){
const char *zFilename = find_option("file","r",1);
const char *zAs = find_option("as",0,1);
const char *zMsg = find_option("message","m",1);
int allowUnsafe = find_option("unsafe",0,0)!=0;
const int mFlags = HTTP_GENERIC | HTTP_QUIET | HTTP_NOCOMPRESS;
int i;
const char *zPw;
char *zLMTime;
Blob up, down, fcontent;
|
| ︙ | ︙ | |||
909 910 911 912 913 914 915 |
"\r\n%z\r\n%s", obscure(zPw), zBoundary);
}
if( zMsg && zMsg[0] ){
blob_appendf(&up,"\r\nContent-Disposition: form-data; name=\"msg\"\r\n"
"\r\n%s\r\n%s", zMsg, zBoundary);
}
if( zFilename && blob_read_from_file(&fcontent, zFilename, ExtFILE)>0 ){
| | | | 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 |
"\r\n%z\r\n%s", obscure(zPw), zBoundary);
}
if( zMsg && zMsg[0] ){
blob_appendf(&up,"\r\nContent-Disposition: form-data; name=\"msg\"\r\n"
"\r\n%s\r\n%s", zMsg, zBoundary);
}
if( zFilename && blob_read_from_file(&fcontent, zFilename, ExtFILE)>0 ){
char *zFN = mprintf("%s", file_tail(zAs ? zAs : zFilename));
int i;
const char *zMime = mimetype_from_name(zFN);
for(i=0; zFN[i]; i++){
char c = zFN[i];
if( fossil_isalnum(c) ) continue;
if( c=='.' ) continue;
if( c=='-' ) continue;
zFN[i] = '_';
}
|
| ︙ | ︙ | |||
938 939 940 941 942 943 944 |
}else{
fossil_print("ERROR: %s\n", blob_str(&down));
}
fossil_fatal("unable to send the chat message");
}
blob_reset(&down);
}else if( strcmp(g.argv[2],"url")==0 ){
| | | 970 971 972 973 974 975 976 977 978 979 980 981 982 |
}else{
fossil_print("ERROR: %s\n", blob_str(&down));
}
fossil_fatal("unable to send the chat message");
}
blob_reset(&down);
}else if( strcmp(g.argv[2],"url")==0 ){
/* Show the URL to access chat. */
fossil_print("%s/chat\n", zUrl);
}else{
fossil_fatal("no such subcommand \"%s\". Use --help for help", g.argv[2]);
}
}
|
Changes to src/checkin.c.
| ︙ | ︙ | |||
1347 1348 1349 1350 1351 1352 1353 |
'#'
);
diff_options(&DCfg, 0, 1);
DCfg.diffFlags |= DIFF_VERBOSE;
if( g.aCommitFile ){
FileDirList *diffFiles;
int i;
| > | | | | 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 |
'#'
);
diff_options(&DCfg, 0, 1);
DCfg.diffFlags |= DIFF_VERBOSE;
if( g.aCommitFile ){
FileDirList *diffFiles;
int i;
for(i=0; g.aCommitFile[i]!=0; ++i){}
diffFiles = fossil_malloc_zero((i+1) * sizeof(*diffFiles));
for(i=0; g.aCommitFile[i]!=0; ++i){
diffFiles[i].zName = db_text(0,
"SELECT pathname FROM vfile WHERE id=%d", g.aCommitFile[i]);
if( fossil_strcmp(diffFiles[i].zName, "." )==0 ){
diffFiles[0].zName[0] = '.';
diffFiles[0].zName[1] = 0;
break;
}
diffFiles[i].nName = strlen(diffFiles[i].zName);
diffFiles[i].nUsed = 0;
}
diff_against_disk(0, &DCfg, diffFiles, &prompt);
for( i=0; diffFiles[i].zName; ++i ){
fossil_free(diffFiles[i].zName);
}
fossil_free(diffFiles);
}else{
diff_against_disk(0, &DCfg, 0, &prompt);
}
|
| ︙ | ︙ | |||
1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 |
** and the original file will have been renamed to "<filename>-original".
*/
static int commit_warning(
Blob *pContent, /* The content of the file being committed. */
int crlfOk, /* Non-zero if CR/LF warnings should be disabled. */
int binOk, /* Non-zero if binary warnings should be disabled. */
int encodingOk, /* Non-zero if encoding warnings should be disabled. */
int noPrompt, /* 0 to always prompt, 1 for 'N', 2 for 'Y'. */
const char *zFilename, /* The full name of the file being committed. */
Blob *pReason /* Reason for warning, if any (non-fatal only). */
){
int bReverse; /* UTF-16 byte order is reversed? */
int fUnicode; /* return value of could_be_utf16() */
int fBinary; /* does the blob content appear to be binary? */
int lookFlags; /* output flags from looks_like_utf8/utf16() */
int fHasAnyCr; /* the blob contains one or more CR chars */
int fHasLoneCrOnly; /* all detected line endings are CR only */
int fHasCrLfOnly; /* all detected line endings are CR/LF pairs */
int fHasInvalidUtf8 = 0;/* contains invalid UTF-8 */
char *zMsg; /* Warning message */
Blob fname; /* Relative pathname of the file */
static int allOk = 0; /* Set to true to disable this routine */
if( allOk ) return 0;
| > > | | | | | | | | | | | | | > > > > | | | > | 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 |
** and the original file will have been renamed to "<filename>-original".
*/
static int commit_warning(
Blob *pContent, /* The content of the file being committed. */
int crlfOk, /* Non-zero if CR/LF warnings should be disabled. */
int binOk, /* Non-zero if binary warnings should be disabled. */
int encodingOk, /* Non-zero if encoding warnings should be disabled. */
int sizeOk, /* Non-zero if oversize warnings are disabled */
int noPrompt, /* 0 to always prompt, 1 for 'N', 2 for 'Y'. */
const char *zFilename, /* The full name of the file being committed. */
Blob *pReason /* Reason for warning, if any (non-fatal only). */
){
int bReverse; /* UTF-16 byte order is reversed? */
int fUnicode; /* return value of could_be_utf16() */
int fBinary; /* does the blob content appear to be binary? */
int lookFlags; /* output flags from looks_like_utf8/utf16() */
int fHasAnyCr; /* the blob contains one or more CR chars */
int fHasLoneCrOnly; /* all detected line endings are CR only */
int fHasCrLfOnly; /* all detected line endings are CR/LF pairs */
int fHasInvalidUtf8 = 0;/* contains invalid UTF-8 */
char *zMsg; /* Warning message */
Blob fname; /* Relative pathname of the file */
static int allOk = 0; /* Set to true to disable this routine */
if( allOk ) return 0;
if( sizeOk ){
fUnicode = could_be_utf16(pContent, &bReverse);
if( fUnicode ){
lookFlags = looks_like_utf16(pContent, bReverse, LOOK_NUL);
}else{
lookFlags = looks_like_utf8(pContent, LOOK_NUL);
if( !(lookFlags & LOOK_BINARY) && invalid_utf8(pContent) ){
fHasInvalidUtf8 = 1;
}
}
fHasAnyCr = (lookFlags & LOOK_CR);
fBinary = (lookFlags & LOOK_BINARY);
fHasLoneCrOnly = ((lookFlags & LOOK_EOL) == LOOK_LONE_CR);
fHasCrLfOnly = ((lookFlags & LOOK_EOL) == LOOK_CRLF);
}else{
fUnicode = fHasAnyCr = fBinary = fHasInvalidUtf8 = 0;
fHasLoneCrOnly = fHasCrLfOnly = 0;
}
if( !sizeOk || fUnicode || fHasAnyCr || fBinary || fHasInvalidUtf8 ){
const char *zWarning = 0;
const char *zDisable = 0;
const char *zConvert = "c=convert/";
const char *zIn = "in";
Blob ans;
char cReply;
if( fBinary ){
int fHasNul = (lookFlags & LOOK_NUL); /* contains NUL chars? */
int fHasLong = (lookFlags & LOOK_LONG); /* overly long line? */
if( binOk ){
|
| ︙ | ︙ | |||
1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 |
zWarning = "CR line endings";
}else if( fHasCrLfOnly ){
zWarning = "CR/LF line endings";
}else{
zWarning = "mixed line endings";
}
zDisable = "\"crlf-glob\" setting";
}else{
if( encodingOk ){
return 0; /* We don't want encoding warnings for this file. */
}
zWarning = "Unicode";
zDisable = "\"encoding-glob\" setting";
}
file_relative_name(zFilename, &fname, 0);
| > > > > | > > > > > | | | | > | 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 |
zWarning = "CR line endings";
}else if( fHasCrLfOnly ){
zWarning = "CR/LF line endings";
}else{
zWarning = "mixed line endings";
}
zDisable = "\"crlf-glob\" setting";
}else if( !sizeOk ){
zWarning = "oversize";
zIn = "file";
}else{
if( encodingOk ){
return 0; /* We don't want encoding warnings for this file. */
}
zWarning = "Unicode";
zDisable = "\"encoding-glob\" setting";
}
file_relative_name(zFilename, &fname, 0);
if( !sizeOk ){
zMsg = mprintf(
"%s is more than %,lld bytes in size.\n"
"Commit anyhow (a=all/y/N)? ",
blob_str(&fname), db_large_file_size());
}else{
zMsg = mprintf(
"%s contains %s. Use --no-warnings or the %s to"
" disable this warning.\n"
"Commit anyhow (a=all/%sy/N)? ",
blob_str(&fname), zWarning, zDisable, zConvert);
}
if( noPrompt==0 ){
prompt_user(zMsg, &ans);
cReply = blob_str(&ans)[0];
blob_reset(&ans);
}else if( noPrompt==2 ){
cReply = 'Y';
}else{
|
| ︙ | ︙ | |||
1975 1976 1977 1978 1979 1980 1981 |
blob_to_lf_only(pContent);
}
fwrite(blob_buffer(pContent), 1, blob_size(pContent), f);
fclose(f);
}
return 1;
}else if( cReply!='y' && cReply!='Y' ){
| | | | 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 |
blob_to_lf_only(pContent);
}
fwrite(blob_buffer(pContent), 1, blob_size(pContent), f);
fclose(f);
}
return 1;
}else if( cReply!='y' && cReply!='Y' ){
fossil_fatal("Abandoning commit due to %s %s %s",
zWarning, zIn, blob_str(&fname));
}else if( noPrompt==2 ){
if( pReason ){
blob_append(pReason, zWarning, -1);
}
return 1;
}
blob_reset(&fname);
|
| ︙ | ︙ | |||
2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 |
**
** See also: commit, extras
*/
void test_commit_warning(void){
int rc = 0;
int noSettings;
int verboseFlag;
Stmt q;
noSettings = find_option("no-settings",0,0)!=0;
verboseFlag = find_option("verbose","v",0)!=0;
verify_all_options();
db_must_be_within_tree();
db_prepare(&q,
"SELECT %Q || pathname, pathname, %s, %s, %s FROM vfile"
" WHERE NOT deleted",
g.zLocalRoot,
glob_expr("pathname", noSettings ? 0 : db_get("crlf-glob",
db_get("crnl-glob",""))),
glob_expr("pathname", noSettings ? 0 : db_get("binary-glob","")),
glob_expr("pathname", noSettings ? 0 : db_get("encoding-glob",""))
);
while( db_step(&q)==SQLITE_ROW ){
const char *zFullname;
const char *zName;
Blob content;
Blob reason;
| > > | > | | 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 |
**
** See also: commit, extras
*/
void test_commit_warning(void){
int rc = 0;
int noSettings;
int verboseFlag;
i64 mxSize;
Stmt q;
noSettings = find_option("no-settings",0,0)!=0;
verboseFlag = find_option("verbose","v",0)!=0;
verify_all_options();
db_must_be_within_tree();
mxSize = db_large_file_size();
db_prepare(&q,
"SELECT %Q || pathname, pathname, %s, %s, %s FROM vfile"
" WHERE NOT deleted",
g.zLocalRoot,
glob_expr("pathname", noSettings ? 0 : db_get("crlf-glob",
db_get("crnl-glob",""))),
glob_expr("pathname", noSettings ? 0 : db_get("binary-glob","")),
glob_expr("pathname", noSettings ? 0 : db_get("encoding-glob",""))
);
while( db_step(&q)==SQLITE_ROW ){
const char *zFullname;
const char *zName;
Blob content;
Blob reason;
int crlfOk, binOk, encodingOk, sizeOk;
int fileRc;
zFullname = db_column_text(&q, 0);
zName = db_column_text(&q, 1);
crlfOk = db_column_int(&q, 2);
binOk = db_column_int(&q, 3);
encodingOk = db_column_int(&q, 4);
sizeOk = mxSize<=0 || file_size(zFullname, ExtFILE)<=mxSize;
blob_zero(&content);
blob_read_from_file(&content, zFullname, RepoFILE);
blob_zero(&reason);
fileRc = commit_warning(&content, crlfOk, binOk, encodingOk, sizeOk, 2,
zFullname, &reason);
if( fileRc || verboseFlag ){
fossil_print("%d\t%s\t%s\n", fileRc, zName, blob_str(&reason));
}
blob_reset(&reason);
rc |= fileRc;
}
|
| ︙ | ︙ | |||
2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 |
** ("auto" lets Fossil choose it automatically,
** even for private branches)
** --close close the branch being committed
** --date-override DATETIME DATE to use instead of 'now'
** --delta use a delta manifest in the commit process
** --hash verify file status using hashing rather
** than relying on file mtimes
** --integrate close all merged-in branches
** -m|--comment COMMENT-TEXT use COMMENT-TEXT as commit comment
** -M|--message-file FILE read the commit comment from given file
** --mimetype MIMETYPE mimetype of check-in comment
** -n|--dry-run If given, display instead of run actions
** -v|--verbose Show a diff in the commit message prompt
** --no-prompt This option disables prompting the user for
| > > > > > | 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 |
** ("auto" lets Fossil choose it automatically,
** even for private branches)
** --close close the branch being committed
** --date-override DATETIME DATE to use instead of 'now'
** --delta use a delta manifest in the commit process
** --hash verify file status using hashing rather
** than relying on file mtimes
** --ignore-clock-skew If a clock skew is detected, ignore it and
** behave as if the user had entered 'yes' to
** the question of whether to proceed despite
** the skew.
** --ignore-oversize Do not warning the user about oversized files
** --integrate close all merged-in branches
** -m|--comment COMMENT-TEXT use COMMENT-TEXT as commit comment
** -M|--message-file FILE read the commit comment from given file
** --mimetype MIMETYPE mimetype of check-in comment
** -n|--dry-run If given, display instead of run actions
** -v|--verbose Show a diff in the commit message prompt
** --no-prompt This option disables prompting the user for
|
| ︙ | ︙ | |||
2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 |
int szB; /* Size of the baseline manifest */
int nConflict = 0; /* Number of unresolved merge conflicts */
int abortCommit = 0; /* Abort the commit due to text format conversions */
Blob ans; /* Answer to continuation prompts */
char cReply; /* First character of ans */
int bRecheck = 0; /* Repeat fork and closed-branch checks*/
int bAutoBrClr = 0; /* Value of "--branchcolor" is "auto" */
memset(&sCiInfo, 0, sizeof(sCiInfo));
url_proxy_options();
/* --sha1sum is an undocumented alias for --hash for backwards compatiblity */
useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0;
noSign = find_option("nosign",0,0)!=0;
privateFlag = find_option("private",0,0)!=0;
| > > | 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 |
int szB; /* Size of the baseline manifest */
int nConflict = 0; /* Number of unresolved merge conflicts */
int abortCommit = 0; /* Abort the commit due to text format conversions */
Blob ans; /* Answer to continuation prompts */
char cReply; /* First character of ans */
int bRecheck = 0; /* Repeat fork and closed-branch checks*/
int bAutoBrClr = 0; /* Value of "--branchcolor" is "auto" */
int bIgnoreSkew = 0; /* --ignore-clock-skew flag */
int mxSize;
memset(&sCiInfo, 0, sizeof(sCiInfo));
url_proxy_options();
/* --sha1sum is an undocumented alias for --hash for backwards compatiblity */
useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0;
noSign = find_option("nosign",0,0)!=0;
privateFlag = find_option("private",0,0)!=0;
|
| ︙ | ︙ | |||
2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 |
zComFile = find_option("message-file", "M", 1);
sCiInfo.zDateOvrd = find_option("date-override",0,1);
sCiInfo.zUserOvrd = find_option("user-override",0,1);
db_must_be_within_tree();
noSign = db_get_boolean("omitsign", 0)|noSign;
if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
useCksum = db_get_boolean("repo-cksum", 1);
outputManifest = db_get_manifest_setting();
verify_all_options();
/* Get the ID of the parent manifest artifact */
vid = db_lget_int("checkout", 0);
if( vid==0 ){
useCksum = 1;
if( privateFlag==0 && sCiInfo.zBranch==0 ) {
| > > > | 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 |
zComFile = find_option("message-file", "M", 1);
sCiInfo.zDateOvrd = find_option("date-override",0,1);
sCiInfo.zUserOvrd = find_option("user-override",0,1);
db_must_be_within_tree();
noSign = db_get_boolean("omitsign", 0)|noSign;
if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
useCksum = db_get_boolean("repo-cksum", 1);
bIgnoreSkew = find_option("ignore-clock-skew",0,0)!=0;
outputManifest = db_get_manifest_setting();
mxSize = db_large_file_size();
if( find_option("ignore-oversize",0,0)!=0 ) mxSize = 0;
verify_all_options();
/* Get the ID of the parent manifest artifact */
vid = db_lget_int("checkout", 0);
if( vid==0 ){
useCksum = 1;
if( privateFlag==0 && sCiInfo.zBranch==0 ) {
|
| ︙ | ︙ | |||
2344 2345 2346 2347 2348 2349 2350 |
}
/* Require confirmation to continue with the check-in if there is
** clock skew
*/
if( g.clockSkewSeen ){
| > > > | | 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 |
}
/* Require confirmation to continue with the check-in if there is
** clock skew
*/
if( g.clockSkewSeen ){
if( bIgnoreSkew!=0 ){
cReply = 'y';
fossil_warning("Clock skew ignored due to --ignore-clock-skew.");
}else if( !noPrompt ){
prompt_user("continue in spite of time skew (y/N)? ", &ans);
cReply = blob_str(&ans)[0];
blob_reset(&ans);
}else{
fossil_print("Abandoning commit due to time skew\n");
cReply = 'N';
}
|
| ︙ | ︙ | |||
2580 2581 2582 2583 2584 2585 2586 |
glob_expr("pathname", db_get("binary-glob","")),
glob_expr("pathname", db_get("encoding-glob",""))
);
while( db_step(&q)==SQLITE_ROW ){
int id, rid;
const char *zFullname;
Blob content;
| | > | | 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 |
glob_expr("pathname", db_get("binary-glob","")),
glob_expr("pathname", db_get("encoding-glob",""))
);
while( db_step(&q)==SQLITE_ROW ){
int id, rid;
const char *zFullname;
Blob content;
int crlfOk, binOk, encodingOk, sizeOk;
id = db_column_int(&q, 0);
zFullname = db_column_text(&q, 1);
rid = db_column_int(&q, 2);
crlfOk = db_column_int(&q, 3);
binOk = db_column_int(&q, 4);
encodingOk = db_column_int(&q, 5);
sizeOk = mxSize<=0 || file_size(zFullname, ExtFILE)<=mxSize;
blob_zero(&content);
blob_read_from_file(&content, zFullname, RepoFILE);
/* Do not emit any warnings when they are disabled. */
if( !noWarningFlag ){
abortCommit |= commit_warning(&content, crlfOk, binOk,
encodingOk, sizeOk, noPrompt,
zFullname, 0);
}
if( contains_merge_marker(&content) ){
Blob fname; /* Relative pathname of the file */
nConflict++;
file_relative_name(zFullname, &fname, 0);
|
| ︙ | ︙ |
Changes to src/clone.c.
| ︙ | ︙ | |||
130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
** --nocompress Omit extra delta compression
** --no-open Clone only. Do not open a check-out.
** --once Don't remember the URI.
** --private Also clone private branches
** --save-http-password Remember the HTTP password without asking
** --ssh-command|-c SSH Use SSH as the "ssh" command
** --ssl-identity FILENAME Use the SSL identity if requested by the server
** -u|--unversioned Also sync unversioned content
** -v|--verbose Show more statistics in output
** --workdir DIR Also open a checkout in DIR
**
** See also: [[init]], [[open]]
*/
void clone_cmd(void){
| > | 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
** --nocompress Omit extra delta compression
** --no-open Clone only. Do not open a check-out.
** --once Don't remember the URI.
** --private Also clone private branches
** --save-http-password Remember the HTTP password without asking
** --ssh-command|-c SSH Use SSH as the "ssh" command
** --ssl-identity FILENAME Use the SSL identity if requested by the server
** --transport-command CMD Use CMD to move messages to the server and back
** -u|--unversioned Also sync unversioned content
** -v|--verbose Show more statistics in output
** --workdir DIR Also open a checkout in DIR
**
** See also: [[init]], [[open]]
*/
void clone_cmd(void){
|
| ︙ | ︙ | |||
164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
if( find_option("verbose","v",0)!=0) syncFlags |= SYNC_VERBOSE;
if( find_option("unversioned","u",0)!=0 ) syncFlags |= SYNC_UNVERSIONED;
zHttpAuth = find_option("httpauth","B",1);
zDefaultUser = find_option("admin-user","A",1);
zWorkDir = find_option("workdir", 0, 1);
clone_ssh_find_options();
url_proxy_options();
/* We should be done with options.. */
verify_all_options();
if( g.argc < 3 ){
usage("?OPTIONS? FILE-OR-URL ?NEW-REPOSITORY?");
}
| > | 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
if( find_option("verbose","v",0)!=0) syncFlags |= SYNC_VERBOSE;
if( find_option("unversioned","u",0)!=0 ) syncFlags |= SYNC_UNVERSIONED;
zHttpAuth = find_option("httpauth","B",1);
zDefaultUser = find_option("admin-user","A",1);
zWorkDir = find_option("workdir", 0, 1);
clone_ssh_find_options();
url_proxy_options();
g.zHttpCmd = find_option("transport-command",0,1);
/* We should be done with options.. */
verify_all_options();
if( g.argc < 3 ){
usage("?OPTIONS? FILE-OR-URL ?NEW-REPOSITORY?");
}
|
| ︙ | ︙ | |||
268 269 270 271 272 273 274 |
}
db_begin_transaction();
if( db_exists("SELECT 1 FROM delta WHERE srcId IN phantom") ){
fossil_fatal("there are unresolved deltas -"
" the clone is probably incomplete and unusable.");
}
fossil_print("Rebuilding repository meta-data...\n");
| | | 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 |
}
db_begin_transaction();
if( db_exists("SELECT 1 FROM delta WHERE srcId IN phantom") ){
fossil_fatal("there are unresolved deltas -"
" the clone is probably incomplete and unusable.");
}
fossil_print("Rebuilding repository meta-data...\n");
rebuild_db(1, 0);
if( !noCompress ){
fossil_print("Extra delta compression... "); fflush(stdout);
extra_deltification();
fossil_print("\n");
}
db_end_transaction(0);
fossil_print("Vacuuming the database... "); fflush(stdout);
|
| ︙ | ︙ | |||
295 296 297 298 299 300 301 |
Blob cmd;
fossil_print("opening the new %s repository in directory %s...\n",
zRepo, zWorkDir);
blob_init(&cmd, 0, 0);
blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
blob_append(&cmd, " open ", -1);
blob_append_escaped_arg(&cmd, zRepo, 1);
| | | 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 |
Blob cmd;
fossil_print("opening the new %s repository in directory %s...\n",
zRepo, zWorkDir);
blob_init(&cmd, 0, 0);
blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
blob_append(&cmd, " open ", -1);
blob_append_escaped_arg(&cmd, zRepo, 1);
blob_append(&cmd, " --nosync --workdir ", -1);
blob_append_escaped_arg(&cmd, zWorkDir, 1);
if( allowNested ){
blob_append(&cmd, " --nested", -1);
}
fossil_system(blob_str(&cmd));
blob_reset(&cmd);
}
|
| ︙ | ︙ |
Changes to src/configure.c.
| ︙ | ︙ | |||
721 722 723 724 725 726 727 | /* ** COMMAND: configuration* ** ** Usage: %fossil configuration METHOD ... ?OPTIONS? ** | | < | 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 | /* ** COMMAND: configuration* ** ** Usage: %fossil configuration METHOD ... ?OPTIONS? ** ** Where METHOD is one of: export import merge pull push reset. ** ** > fossil configuration export AREA FILENAME ** ** Write to FILENAME exported configuration information for AREA. ** AREA can be one of: ** ** all email interwiki project shun skin |
| ︙ | ︙ | |||
767 768 769 770 771 772 773 | ** ** > fossil configuration sync AREA ?URL? ** ** Synchronize configuration changes in the local repository with ** the remote repository at URL. ** ** Options: | | | 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 |
**
** > fossil configuration sync AREA ?URL?
**
** Synchronize configuration changes in the local repository with
** the remote repository at URL.
**
** Options:
** -R|--repository REPO Affect repository REPO with changes
**
** See also: [[settings]], [[unset]]
*/
void configuration_cmd(void){
int n;
const char *zMethod;
db_find_and_open_repository(0, 0);
|
| ︙ | ︙ | |||
835 836 837 838 839 840 841 |
if( g.argc!=4 && g.argc!=5 ){
usage(mprintf("%s AREA ?URL?", zMethod));
}
mask = configure_name_to_mask(g.argv[3], 1);
if( g.argc==5 ){
zServer = g.argv[4];
}
| | | 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 |
if( g.argc!=4 && g.argc!=5 ){
usage(mprintf("%s AREA ?URL?", zMethod));
}
mask = configure_name_to_mask(g.argv[3], 1);
if( g.argc==5 ){
zServer = g.argv[4];
}
url_parse(zServer, URL_PROMPT_PW|URL_USE_CONFIG);
if( g.url.protocol==0 ) fossil_fatal("no server URL specified");
user_select();
url_enable_proxy("via proxy: ");
if( overwriteFlag ) mask |= CONFIGSET_OVERWRITE;
if( strncmp(zMethod, "push", n)==0 ){
client_sync(0,0,(unsigned)mask,0);
}else if( strncmp(zMethod, "pull", n)==0 ){
|
| ︙ | ︙ |
Changes to src/db.c.
| ︙ | ︙ | |||
1407 1408 1409 1410 1411 1412 1413 |
sqlite3_create_function(db, "display_name", 1, SQLITE_UTF8, 0,
alert_display_name_func, 0, 0);
sqlite3_create_function(db, "obscure", 1, SQLITE_UTF8, 0,
db_obscure, 0, 0);
sqlite3_create_function(db, "protected_setting", 1, SQLITE_UTF8, 0,
db_protected_setting_func, 0, 0);
sqlite3_create_function(db, "win_reserved", 1, SQLITE_UTF8, 0,
| | > | | 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 |
sqlite3_create_function(db, "display_name", 1, SQLITE_UTF8, 0,
alert_display_name_func, 0, 0);
sqlite3_create_function(db, "obscure", 1, SQLITE_UTF8, 0,
db_obscure, 0, 0);
sqlite3_create_function(db, "protected_setting", 1, SQLITE_UTF8, 0,
db_protected_setting_func, 0, 0);
sqlite3_create_function(db, "win_reserved", 1, SQLITE_UTF8, 0,
db_win_reserved_func,0,0);
sqlite3_create_function(db, "url_nouser", 1, SQLITE_UTF8, 0,
url_nouser_func,0,0);
}
#if USE_SEE
/*
** This is a pointer to the saved database encryption key string.
*/
static char *zSavedKey = 0;
|
| ︙ | ︙ | |||
2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 |
/*
** Returns non-zero if support for symlinks is currently enabled.
*/
int db_allow_symlinks(void){
return g.allowSymlinks;
}
/*
** Open the repository database given by zDbName. If zDbName==NULL then
** get the name from the already open local database.
*/
void db_open_repository(const char *zDbName){
if( g.repositoryOpen ) return;
if( zDbName==0 ){
if( g.localOpen ){
zDbName = db_repository_filename();
}
if( zDbName==0 ){
db_err("unable to find the name of a repository database");
}
}
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > | 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 |
/*
** Returns non-zero if support for symlinks is currently enabled.
*/
int db_allow_symlinks(void){
return g.allowSymlinks;
}
/*
** Return TRUE if the file in the argument seems like it might be an
** SQLite database file that contains a Fossil repository schema.
*/
int db_looks_like_a_repository(const char *zDbName){
sqlite3 *db = 0;
i64 sz;
int rc;
int res = 0;
sqlite3_stmt *pStmt = 0;
sz = file_size(zDbName, ExtFILE);
if( sz<16834 ) return 0;
if( sz & 0x1ff ) return 0;
rc = sqlite3_open(zDbName, &db);
if( rc ) goto is_repo_end;
rc = sqlite3_prepare_v2(db,
"SELECT count(*) FROM sqlite_schema"
" WHERE name COLLATE nocase IN"
"('blob','delta','rcvfrom','user','config','mlink','plink');",
-1, &pStmt, 0);
if( rc ) goto is_repo_end;
rc = sqlite3_step(pStmt);
if( rc!=SQLITE_ROW ) goto is_repo_end;
if( sqlite3_column_int(pStmt, 0)!=7 ) goto is_repo_end;
res = 1;
is_repo_end:
sqlite3_finalize(pStmt);
sqlite3_close(db);
return res;
}
/*
** COMMAND: test-is-repo
*/
void test_is_repo(void){
int i;
for(i=2; i<g.argc; i++){
fossil_print("%s: %s\n",
db_looks_like_a_repository(g.argv[i]) ? "yes" : " no",
g.argv[i]
);
}
}
/*
** Open the repository database given by zDbName. If zDbName==NULL then
** get the name from the already open local database.
*/
void db_open_repository(const char *zDbName){
i64 sz;
if( g.repositoryOpen ) return;
if( zDbName==0 ){
if( g.localOpen ){
zDbName = db_repository_filename();
}
if( zDbName==0 ){
db_err("unable to find the name of a repository database");
}
}
if( file_access(zDbName, R_OK)
|| (sz = file_size(zDbName, ExtFILE))<16384
|| (sz&0x1ff)!=0
){
if( file_access(zDbName, F_OK) ){
#ifdef FOSSIL_ENABLE_JSON
g.json.resultCode = FSL_JSON_E_DB_NOT_FOUND;
#endif
fossil_fatal("repository does not exist or"
" is in an unreadable directory: %s", zDbName);
}else if( file_access(zDbName, R_OK) ){
|
| ︙ | ︙ | |||
2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 |
** associated permissions will be copied.
**
** Options:
** --template FILE Copy settings from repository file
** -A|--admin-user USERNAME Select given USERNAME as admin user
** --date-override DATETIME Use DATETIME as time of the initial check-in
** --sha1 Use an initial hash policy of "sha1"
**
** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
** year-month-day form, it may be truncated, the "T" may be replaced by
** a space, and it may also name a timezone offset from UTC as "-HH:MM"
** (westward) or "+HH:MM" (eastward). Either no timezone suffix or "Z"
** means UTC.
**
** See also: [[clone]]
*/
void create_repository_cmd(void){
char *zPassword;
const char *zTemplate; /* Repository from which to copy settings */
const char *zDate; /* Date of the initial check-in */
const char *zDefaultUser; /* Optional name of the default user */
int bUseSha1 = 0; /* True to set the hash-policy to sha1 */
zTemplate = find_option("template",0,1);
zDate = find_option("date-override",0,1);
zDefaultUser = find_option("admin-user","A",1);
bUseSha1 = find_option("sha1",0,0)!=0;
/* We should be done with options.. */
verify_all_options();
if( g.argc!=3 ){
usage("REPOSITORY-NAME");
}
if( -1 != file_size(g.argv[2], ExtFILE) ){
fossil_fatal("file already exists: %s", g.argv[2]);
}
db_create_repository(g.argv[2]);
db_open_repository(g.argv[2]);
db_open_config(0, 0);
if( zTemplate ) db_attach(zTemplate, "settingSrc");
db_begin_transaction();
if( bUseSha1 ){
g.eHashPolicy = HPOLICY_SHA1;
db_set_int("hash-policy", HPOLICY_SHA1, 0);
}
if( zDate==0 ) zDate = "now";
db_initial_setup(zTemplate, zDate, zDefaultUser);
db_end_transaction(0);
if( zTemplate ) db_detach("settingSrc");
fossil_print("project-id: %s\n", db_get("project-code", 0));
fossil_print("server-id: %s\n", db_get("server-code", 0));
zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
fossil_print("admin-user: %s (initial password is \"%s\")\n",
g.zLogin, zPassword);
}
| > > > > > > > > > > | 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 |
** associated permissions will be copied.
**
** Options:
** --template FILE Copy settings from repository file
** -A|--admin-user USERNAME Select given USERNAME as admin user
** --date-override DATETIME Use DATETIME as time of the initial check-in
** --sha1 Use an initial hash policy of "sha1"
** --project-name STRING The name of the project "project name in quotes"
** --project-desc STRING The descritption of the project "project description in quotes"
**
** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
** year-month-day form, it may be truncated, the "T" may be replaced by
** a space, and it may also name a timezone offset from UTC as "-HH:MM"
** (westward) or "+HH:MM" (eastward). Either no timezone suffix or "Z"
** means UTC.
**
** See also: [[clone]]
*/
void create_repository_cmd(void){
char *zPassword;
const char *zTemplate; /* Repository from which to copy settings */
const char *zDate; /* Date of the initial check-in */
const char *zDefaultUser; /* Optional name of the default user */
const char *zProjectName; /* Optional project name of the repo */
const char *zProjectDesc; /* Optional project description "description of project in quotes" */
int bUseSha1 = 0; /* True to set the hash-policy to sha1 */
zTemplate = find_option("template",0,1);
zDate = find_option("date-override",0,1);
zDefaultUser = find_option("admin-user","A",1);
bUseSha1 = find_option("sha1",0,0)!=0;
zProjectName = find_option("project-name", 0, 1);
zProjectDesc = find_option("project-desc", 0, 1);
/* We should be done with options.. */
verify_all_options();
if( g.argc!=3 ){
usage("REPOSITORY-NAME");
}
if( -1 != file_size(g.argv[2], ExtFILE) ){
fossil_fatal("file already exists: %s", g.argv[2]);
}
db_create_repository(g.argv[2]);
db_open_repository(g.argv[2]);
db_open_config(0, 0);
if( zTemplate ) db_attach(zTemplate, "settingSrc");
db_begin_transaction();
if( bUseSha1 ){
g.eHashPolicy = HPOLICY_SHA1;
db_set_int("hash-policy", HPOLICY_SHA1, 0);
}
if( zProjectName ) db_set("project-name", zProjectName, 0);
if( zProjectDesc ) db_set("project-description", zProjectDesc, 0);
if( zDate==0 ) zDate = "now";
db_initial_setup(zTemplate, zDate, zDefaultUser);
db_end_transaction(0);
if( zTemplate ) db_detach("settingSrc");
if( zProjectName ) fossil_print("project-name: %s\n", zProjectName);
if( zProjectDesc ) fossil_print("project-description: %s\n", zProjectDesc);
fossil_print("project-id: %s\n", db_get("project-code", 0));
fossil_print("server-id: %s\n", db_get("server-code", 0));
zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
fossil_print("admin-user: %s (initial password is \"%s\")\n",
g.zLogin, zPassword);
}
|
| ︙ | ︙ | |||
3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 |
if( db_step(&q2)==SQLITE_ROW ){
v = db_column_int(&q2, 0);
}
db_reset(&q2);
}
return v;
}
void db_set_int(const char *zName, int value, int globalFlag){
db_assert_protection_off_or_not_sensitive(zName);
db_unprotect(PROTECT_CONFIG);
if( globalFlag ){
db_swap_connections();
db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%d)",
zName, value);
| > > > > | 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 |
if( db_step(&q2)==SQLITE_ROW ){
v = db_column_int(&q2, 0);
}
db_reset(&q2);
}
return v;
}
i64 db_large_file_size(void){
/* Return size of the largest file that is not considered oversized */
return strtoll(db_get("large-file-size","20000000"),0,0);
}
void db_set_int(const char *zName, int value, int globalFlag){
db_assert_protection_off_or_not_sensitive(zName);
db_unprotect(PROTECT_CONFIG);
if( globalFlag ){
db_swap_connections();
db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%d)",
zName, value);
|
| ︙ | ︙ | |||
3499 3500 3501 3502 3503 3504 3505 | ** Options: ** --empty Initialize checkout as being empty, but still connected ** with the local repository. If you commit this checkout, ** it will become a new "initial" commit in the repository. ** -f|--force Continue with the open even if the working directory is ** not empty. ** --force-missing Force opening a repository with missing content | | > > > | > | 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 |
** Options:
** --empty Initialize checkout as being empty, but still connected
** with the local repository. If you commit this checkout,
** it will become a new "initial" commit in the repository.
** -f|--force Continue with the open even if the working directory is
** not empty.
** --force-missing Force opening a repository with missing content
** -k|--keep Only modify the manifest and manifest.uuid files
** --nested Allow opening a repository inside an opened checkout
** --nosync Do not auto-sync the repository prior to opening
** --repodir DIR If REPOSITORY is a URI that will be cloned, store
** the clone in DIR rather than in "."
** --setmtime Set timestamps of all files to match their SCM-side
** times (the timestamp of the last checkin which modified
** them).
** --verbose If passed a URI then this flag is passed on to the clone
** operation, otherwise it has no effect.
** --workdir DIR Use DIR as the working directory instead of ".". The DIR
** directory is created if it does not exist.
**
** See also: [[close]], [[clone]]
*/
void cmd_open(void){
int emptyFlag;
int keepFlag;
int forceMissingFlag;
int allowNested;
int setmtimeFlag; /* --setmtime. Set mtimes on files */
int bForce = 0; /* --force. Open even if non-empty dir */
static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0, 0 };
const char *zWorkDir; /* --workdir value */
const char *zRepo = 0; /* Name of the repository file */
const char *zRepoDir = 0; /* --repodir value */
char *zPwd; /* Initial working directory */
int isUri = 0; /* True if REPOSITORY is a URI */
int nLocal; /* Number of preexisting files in cwd */
int bNosync = 0; /* --nosync. Omit auto-sync */
int bVerbose = 0; /* --verbose option for clone */
url_proxy_options();
emptyFlag = find_option("empty",0,0)!=0;
keepFlag = find_option("keep","k",0)!=0;
forceMissingFlag = find_option("force-missing",0,0)!=0;
allowNested = find_option("nested",0,0)!=0;
setmtimeFlag = find_option("setmtime",0,0)!=0;
zWorkDir = find_option("workdir",0,1);
zRepoDir = find_option("repodir",0,1);
bForce = find_option("force","f",0)!=0;
bNosync = find_option("nosync",0,0)!=0;
bVerbose = find_option("verbose",0,0)!=0;
zPwd = file_getcwd(0,0);
/* We should be done with options.. */
verify_all_options();
if( g.argc!=3 && g.argc!=4 ){
|
| ︙ | ︙ | |||
3580 3581 3582 3583 3584 3585 3586 |
}
if( keepFlag==0
&& bForce==0
&& (nLocal = file_directory_size(".", 0, 1))>0
&& (nLocal>1 || isUri || !file_in_cwd(zRepo))
){
fossil_fatal("directory %s is not empty\n"
| > > | | 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 |
}
if( keepFlag==0
&& bForce==0
&& (nLocal = file_directory_size(".", 0, 1))>0
&& (nLocal>1 || isUri || !file_in_cwd(zRepo))
){
fossil_fatal("directory %s is not empty\n"
"use the -f (--force) option to override\n"
"or the -k (--keep) option to keep local files unchanged",
file_getcwd(0,0));
}
if( db_open_local_v2(0, allowNested) ){
fossil_fatal("there is already an open tree at %s", g.zLocalRoot);
}
/* If REPOSITORY looks like a URI, then try to clone it first */
|
| ︙ | ︙ | |||
3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 |
}
if( zRepoDir==0 ) zRepoDir = zPwd;
zRepo = mprintf("%s/%s.fossil", zRepoDir, zNewBase);
fossil_free(zNewBase);
blob_init(&cmd, 0, 0);
blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
blob_append(&cmd, " clone", -1);
blob_append_escaped_arg(&cmd, zUri, 1);
blob_append_escaped_arg(&cmd, zRepo, 1);
zCmd = blob_str(&cmd);
fossil_print("%s\n", zCmd);
if( zWorkDir ) file_chdir(zPwd, 0);
rc = fossil_system(zCmd);
if( rc ){
| > > > | 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 |
}
if( zRepoDir==0 ) zRepoDir = zPwd;
zRepo = mprintf("%s/%s.fossil", zRepoDir, zNewBase);
fossil_free(zNewBase);
blob_init(&cmd, 0, 0);
blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
blob_append(&cmd, " clone", -1);
if(0!=bVerbose){
blob_append(&cmd, " --verbose", -1);
}
blob_append_escaped_arg(&cmd, zUri, 1);
blob_append_escaped_arg(&cmd, zRepo, 1);
zCmd = blob_str(&cmd);
fossil_print("%s\n", zCmd);
if( zWorkDir ) file_chdir(zPwd, 0);
rc = fossil_system(zCmd);
if( rc ){
|
| ︙ | ︙ | |||
3805 3806 3807 3808 3809 3810 3811 | /* ** SETTING: auto-shun boolean default=on ** If enabled, automatically pull the shunning list ** from a server to which the client autosyncs. */ /* ** SETTING: autosync width=16 default=on | > | > | | | > > > | 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 | /* ** SETTING: auto-shun boolean default=on ** If enabled, automatically pull the shunning list ** from a server to which the client autosyncs. */ /* ** SETTING: autosync width=16 default=on ** This setting can be a boolean value (0, 1, on, off, true, false) ** or "pullonly" or "all". ** ** If not false, automatically pull prior to commit ** or update and automatically push after commit or ** tag or branch creation. Except, if the value is ** "pullonly" then only pull operations occur automatically. ** Normally, only the default remote is used, but if the ** value is "all" then push/pull operations occur on all ** remotes. */ /* ** SETTING: autosync-tries width=16 default=1 ** If autosync is enabled setting this to a value greater ** than zero will cause autosync to try no more than this ** number of attempts if there is a sync failure. */ |
| ︙ | ︙ | |||
4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 | ** "Anonymous" in e.g. ticketing system. On the other hand ** users can not be deleted. */ /* ** SETTING: ssh-command width=40 sensitive ** The command used to talk to a remote machine with the "ssh://" protocol. */ /* ** SETTING: ssl-ca-location width=40 sensitive ** The full pathname to a file containing PEM encoded ** CA root certificates, or a directory of certificates ** with filenames formed from the certificate hashes as ** required by OpenSSL. ** ** If set, this will override the OS default list of ** OpenSSL CAs. If unset, the default list will be used. ** Some platforms may add additional certificates. ** Checking your platform behaviour is required if the ** exact contents of the CA root is critical for your ** application. */ /* ** SETTING: ssl-identity width=40 sensitive ** The full pathname to a file containing a certificate ** and private key in PEM format. Create by concatenating ** the certificate and private key files. ** | > > > > | 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 | ** "Anonymous" in e.g. ticketing system. On the other hand ** users can not be deleted. */ /* ** SETTING: ssh-command width=40 sensitive ** The command used to talk to a remote machine with the "ssh://" protocol. */ /* ** SETTING: ssl-ca-location width=40 sensitive ** The full pathname to a file containing PEM encoded ** CA root certificates, or a directory of certificates ** with filenames formed from the certificate hashes as ** required by OpenSSL. ** ** If set, this will override the OS default list of ** OpenSSL CAs. If unset, the default list will be used. ** Some platforms may add additional certificates. ** Checking your platform behaviour is required if the ** exact contents of the CA root is critical for your ** application. ** ** This setting is overridden by environment variables ** SSL_CERT_FILE and SSL_CERT_DIR. */ /* ** SETTING: ssl-identity width=40 sensitive ** The full pathname to a file containing a certificate ** and private key in PEM format. Create by concatenating ** the certificate and private key files. ** |
| ︙ | ︙ | |||
4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 | /* ** SETTING: web-browser width=30 sensitive ** A shell command used to launch your preferred ** web browser when given a URL as an argument. ** Defaults to "start" on windows, "open" on Mac, ** and "firefox" on Unix. */ /* ** SETTING: wiki-classes width=40 block-text ** Defines classes for wiki pages that are recognized by the list ** of available wiki pages (displayed by /wcontent web page). ** ** Each line defines a single rule for a class using a triplet: ** Visibility Label Pattern | > > > > > > > | 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 | /* ** SETTING: web-browser width=30 sensitive ** A shell command used to launch your preferred ** web browser when given a URL as an argument. ** Defaults to "start" on windows, "open" on Mac, ** and "firefox" on Unix. */ /* ** SETTING: large-file-size width=10 default=200000000 ** Fossil considers any file whose size is greater than this value ** to be a "large file". Fossil might issue warnings if you try to ** "add" or "commit" a "large file". Set this value to 0 or less ** to disable all such warnings. */ /* ** SETTING: wiki-classes width=40 block-text ** Defines classes for wiki pages that are recognized by the list ** of available wiki pages (displayed by /wcontent web page). ** ** Each line defines a single rule for a class using a triplet: ** Visibility Label Pattern |
| ︙ | ︙ |
Changes to src/diff.c.
| ︙ | ︙ | |||
578 579 580 581 582 583 584 585 586 587 588 589 590 591 |
p->a[0].isMin = 0;
while( p->n<MX_CSN-1 ){
int mxi = -1;
int mxLen = -1;
int x, i;
int aLCS[4];
struct Span *a, *b;
for(i=0; i<p->n; i++){
if( p->a[i].isMin ) continue;
x = p->a[i].iLen1;
if( p->a[i].iLen2<x ) x = p->a[i].iLen2;
if( x>mxLen ){
mxLen = x;
mxi = i;
| > | 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 |
p->a[0].isMin = 0;
while( p->n<MX_CSN-1 ){
int mxi = -1;
int mxLen = -1;
int x, i;
int aLCS[4];
struct Span *a, *b;
memset(aLCS, 0, sizeof(aLCS));
for(i=0; i<p->n; i++){
if( p->a[i].isMin ) continue;
x = p->a[i].iLen1;
if( p->a[i].iLen2<x ) x = p->a[i].iLen2;
if( x>mxLen ){
mxLen = x;
mxi = i;
|
| ︙ | ︙ | |||
1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 |
}
static void dfjsonEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){
int i, x;
LineChange chng;
blob_append(p->pOut, "5,[", 3);
oneLineChange(pX, pY, &chng);
for(i=x=0; i<chng.n; i++){
blob_append_json_literal(p->pOut, pX->z + x, chng.a[i].iStart1 - x);
x = chng.a[i].iStart1;
blob_append_char(p->pOut, ',');
blob_append_json_literal(p->pOut, pX->z + x, chng.a[i].iLen1);
x += chng.a[i].iLen1;
blob_append_char(p->pOut, ',');
blob_append_json_literal(p->pOut,
| > > > | 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 |
}
static void dfjsonEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){
int i, x;
LineChange chng;
blob_append(p->pOut, "5,[", 3);
oneLineChange(pX, pY, &chng);
for(i=x=0; i<chng.n; i++){
if(i>0){
blob_append_char(p->pOut, ',');
}
blob_append_json_literal(p->pOut, pX->z + x, chng.a[i].iStart1 - x);
x = chng.a[i].iStart1;
blob_append_char(p->pOut, ',');
blob_append_json_literal(p->pOut, pX->z + x, chng.a[i].iLen1);
x += chng.a[i].iLen1;
blob_append_char(p->pOut, ',');
blob_append_json_literal(p->pOut,
|
| ︙ | ︙ | |||
2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 | int dist = 0; /* Distance of match from center */ int mid; /* Center of the chng */ int iSXb, iSYb, iEXb, iEYb; /* Best match so far */ int iSXp, iSYp, iEXp, iEYp; /* Previous match */ sqlite3_int64 bestScore; /* Best score so far */ sqlite3_int64 score; /* Score for current candidate LCS */ int span; /* combined width of the input sequences */ span = (iE1 - iS1) + (iE2 - iS2); bestScore = -10000; score = 0; iSXb = iSXp = iS1; iEXb = iEXp = iS1; iSYb = iSYp = iS2; iEYb = iEYp = iS2; mid = (iE1 + iS1)/2; | > > > > | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | | 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 |
int dist = 0; /* Distance of match from center */
int mid; /* Center of the chng */
int iSXb, iSYb, iEXb, iEYb; /* Best match so far */
int iSXp, iSYp, iEXp, iEYp; /* Previous match */
sqlite3_int64 bestScore; /* Best score so far */
sqlite3_int64 score; /* Score for current candidate LCS */
int span; /* combined width of the input sequences */
int cutoff = 4; /* Max hash chain entries to follow */
int nextCutoff = -1; /* Value of cutoff for next iteration */
span = (iE1 - iS1) + (iE2 - iS2);
bestScore = -10000;
score = 0;
iSXb = iSXp = iS1;
iEXb = iEXp = iS1;
iSYb = iSYp = iS2;
iEYb = iEYp = iS2;
mid = (iE1 + iS1)/2;
do{
nextCutoff = 0;
for(i=iS1; i<iE1; i++){
int limit = 0;
j = p->aTo[p->aFrom[i].h % p->nTo].iHash;
while( j>0
&& (j-1<iS2 || j>=iE2 || p->xDiffer(&p->aFrom[i], &p->aTo[j-1]))
){
if( limit++ > cutoff ){
j = 0;
nextCutoff = cutoff*4;
break;
}
j = p->aTo[j-1].iNext;
}
if( j==0 ) continue;
assert( i>=iSXb && i>=iSXp );
if( i<iEXb && j>=iSYb && j<iEYb ) continue;
if( i<iEXp && j>=iSYp && j<iEYp ) continue;
iSX = i;
iSY = j-1;
pA = &p->aFrom[iSX-1];
pB = &p->aTo[iSY-1];
n = minInt(iSX-iS1, iSY-iS2);
for(k=0; k<n && p->xDiffer(pA,pB)==0; k++, pA--, pB--){}
iSX -= k;
iSY -= k;
iEX = i+1;
iEY = j;
pA = &p->aFrom[iEX];
pB = &p->aTo[iEY];
n = minInt(iE1-iEX, iE2-iEY);
for(k=0; k<n && p->xDiffer(pA,pB)==0; k++, pA++, pB++){}
iEX += k;
iEY += k;
skew = (iSX-iS1) - (iSY-iS2);
if( skew<0 ) skew = -skew;
dist = (iSX+iEX)/2 - mid;
if( dist<0 ) dist = -dist;
score = (iEX - iSX)*(sqlite3_int64)span - (skew + dist);
if( score>bestScore ){
bestScore = score;
iSXb = iSX;
iSYb = iSY;
iEXb = iEX;
iEYb = iEY;
}else if( iEX>iEXp ){
iSXp = iSX;
iSYp = iSY;
iEXp = iEX;
iEYp = iEY;
}
}
}while( iSXb==iEXb && nextCutoff && (cutoff=nextCutoff)<=64 );
if( iSXb==iEXb && (sqlite3_int64)(iE1-iS1)*(iE2-iS2)<2500 ){
/* If no common sequence is found using the hashing heuristic and
** the input is not too big, use the expensive exact solution */
optimalLCS(p, iS1, iE1, iS2, iE2, piSX, piEX, piSY, piEY);
}else{
*piSX = iSXb;
*piSY = iSYb;
*piEX = iEXb;
|
| ︙ | ︙ |
Changes to src/diffcmd.c.
| ︙ | ︙ | |||
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
*/
static const char zWebpageHdr[] =
@ <!DOCTYPE html>
@ <html>
@ <head>
@ <meta charset="UTF-8">
@ <style>
@ h1 {
@ font-size: 150%;
@ }
@
@ table.diff {
@ width: 100%;
@ border-spacing: 0;
@ border: 1px solid black;
@ }
@ table.diff td {
@ vertical-align: top;
@ }
@ table.diff pre {
@ margin: 0 0 0 0;
@ }
@ td.diffln {
@ width: 1px;
@ text-align: right;
@ padding: 0 1em 0 0;
@ }
@ td.difflne {
@ padding-bottom: 0.4em;
@ }
@ td.diffsep {
@ width: 1px;
@ padding: 0 0.3em 0 1em;
@ }
@ td.difftxt pre {
@ overflow-x: auto;
@ }
@ td.diffln ins {
@ background-color: #a0e4b2;
@ text-decoration: none;
@ }
@ td.diffln del {
@ background-color: #ffc0c0;
@ text-decoration: none;
@ }
@ td.difftxt del {
@ background-color: #ffe8e8;
@ text-decoration: none;
@ }
@ td.difftxt del > del {
@ background-color: #ffc0c0;
@ text-decoration: none;
@ font-weight: bold;
@ }
@ td.difftxt del > del.edit {
@ background-color: #c0c0ff;
@ text-decoration: none;
@ font-weight: bold;
@ }
@ td.difftxt ins {
@ background-color: #dafbe1;
@ text-decoration: none;
@ }
@ td.difftxt ins > ins {
@ background-color: #a0e4b2;
@ text-decoration: none;
@ font-weight: bold;
@ }
@ td.difftxt ins > ins.edit {
| > > > > > > > > > > > > > > > > > > > > > > > | 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
*/
static const char zWebpageHdr[] =
@ <!DOCTYPE html>
@ <html>
@ <head>
@ <meta charset="UTF-8">
@ <style>
@ body {
@ background-color: white;
@ }
@ h1 {
@ font-size: 150%;
@ }
@
@ table.diff {
@ width: 100%;
@ border-spacing: 0;
@ border: 1px solid black;
@ line-height: inherit;
@ font-size: inherit;
@ }
@ table.diff td {
@ vertical-align: top;
@ line-height: inherit;
@ font-size: inherit;
@ }
@ table.diff pre {
@ margin: 0 0 0 0;
@ line-height: inherit;
@ font-size: inherit;
@ }
@ td.diffln {
@ width: 1px;
@ text-align: right;
@ padding: 0 1em 0 0;
@ }
@ td.difflne {
@ padding-bottom: 0.4em;
@ }
@ td.diffsep {
@ width: 1px;
@ padding: 0 0.3em 0 1em;
@ line-height: inherit;
@ font-size: inherit;
@ }
@ td.diffsep pre {
@ line-height: inherit;
@ font-size: inherit;
@ }
@ td.difftxt pre {
@ overflow-x: auto;
@ }
@ td.diffln ins {
@ background-color: #a0e4b2;
@ text-decoration: none;
@ line-height: inherit;
@ font-size: inherit;
@ }
@ td.diffln del {
@ background-color: #ffc0c0;
@ text-decoration: none;
@ line-height: inherit;
@ font-size: inherit;
@ }
@ td.difftxt del {
@ background-color: #ffe8e8;
@ text-decoration: none;
@ line-height: inherit;
@ font-size: inherit;
@ }
@ td.difftxt del > del {
@ background-color: #ffc0c0;
@ text-decoration: none;
@ font-weight: bold;
@ }
@ td.difftxt del > del.edit {
@ background-color: #c0c0ff;
@ text-decoration: none;
@ font-weight: bold;
@ }
@ td.difftxt ins {
@ background-color: #dafbe1;
@ text-decoration: none;
@ line-height: inherit;
@ font-size: inherit;
@ }
@ td.difftxt ins > ins {
@ background-color: #a0e4b2;
@ text-decoration: none;
@ font-weight: bold;
@ }
@ td.difftxt ins > ins.edit {
|
| ︙ | ︙ | |||
549 550 551 552 553 554 555 556 557 558 559 560 561 562 |
file_delete(blob_str(&temp2));
blob_reset(&temp1);
blob_reset(&temp2);
blob_reset(&cmd);
}
}
/*
** Run a diff between the version zFrom and files on disk. zFrom might
** be NULL which means to simply show the difference between the edited
** files on disk and the check-out on which they are based.
**
** Use the internal diff logic if zDiffCmd is NULL. Otherwise call the
| > > > > > > > > > > > > > > > > > > > | 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 |
file_delete(blob_str(&temp2));
blob_reset(&temp1);
blob_reset(&temp2);
blob_reset(&cmd);
}
}
/*
** Return true if the disk file is identical to the Blob. Return zero
** if the files differ in any way.
*/
static int file_same_as_blob(Blob *blob, const char *zDiskFile){
Blob file;
int rc = 0;
if( blob_size(blob)!=file_size(zDiskFile, ExtFILE) ) return 0;
blob_zero(&file);
blob_read_from_file(&file, zDiskFile, ExtFILE);
if( blob_size(&file)!=blob_size(blob) ){
rc = 0;
}else{
rc = memcmp(blob_buffer(&file), blob_buffer(blob), blob_size(&file))==0;
}
blob_reset(&file);
return rc;
}
/*
** Run a diff between the version zFrom and files on disk. zFrom might
** be NULL which means to simply show the difference between the edited
** files on disk and the check-out on which they are based.
**
** Use the internal diff logic if zDiffCmd is NULL. Otherwise call the
|
| ︙ | ︙ | |||
670 671 672 673 674 675 676 |
continue;
}
if( srcid>0 ){
content_get(srcid, &content);
}else{
blob_zero(&content);
}
| > | | > | 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 |
continue;
}
if( srcid>0 ){
content_get(srcid, &content);
}else{
blob_zero(&content);
}
if( isChnged==0 || !file_same_as_blob(&content, zFullName) ){
diff_print_index(zPathname, pCfg, pOut);
diff_file(&content, zFullName, zPathname, pCfg, pOut);
}
blob_reset(&content);
}
blob_reset(&fname);
}
db_finalize(&q);
db_end_transaction(1); /* ROLLBACK */
}
|
| ︙ | ︙ | |||
991 992 993 994 995 996 997 | ** Options: ** --binary PATTERN Treat files that match the glob PATTERN ** as binary ** --branch BRANCH Show diff of all changes on BRANCH ** --brief Show filenames only ** -b|--browser Show the diff output in a web-browser ** --by Shorthand for "--browser -y" | | | 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 | ** Options: ** --binary PATTERN Treat files that match the glob PATTERN ** as binary ** --branch BRANCH Show diff of all changes on BRANCH ** --brief Show filenames only ** -b|--browser Show the diff output in a web-browser ** --by Shorthand for "--browser -y" ** -ci|--checkin VERSION Show diff of all changes in VERSION ** --command PROG External diff program. Overrides "diff-command" ** -c|--context N Show N lines of context around each change ** --diff-binary BOOL Include binary files with external commands ** --exec-abs-paths Force absolute path names on external commands ** --exec-rel-paths Force relative path names on external commands ** -r|--from VERSION Select VERSION as source for the diff ** -w|--ignore-all-space Ignore white space when comparing lines |
| ︙ | ︙ | |||
1033 1034 1035 1036 1037 1038 1039 |
if( find_option("tk",0,0)!=0 || has_option("tclsh") ){
diff_tk("diff", 2);
return;
}
isGDiff = g.argv[1][0]=='g';
zFrom = find_option("from", "r", 1);
zTo = find_option("to", 0, 1);
| | | 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 |
if( find_option("tk",0,0)!=0 || has_option("tclsh") ){
diff_tk("diff", 2);
return;
}
isGDiff = g.argv[1][0]=='g';
zFrom = find_option("from", "r", 1);
zTo = find_option("to", 0, 1);
zCheckin = find_option("checkin", "ci", 1);
zBranch = find_option("branch", 0, 1);
againstUndo = find_option("undo",0,0)!=0;
if( againstUndo && ( zFrom!=0 || zTo!=0 || zCheckin!=0 || zBranch!=0) ){
fossil_fatal("cannot use --undo together with --from, --to, --checkin,"
" or --branch");
}
if( zBranch ){
|
| ︙ | ︙ |
Changes to src/dispatch.c.
| ︙ | ︙ | |||
592 593 594 595 596 597 598 | ** ** Show help text for commands and pages. Useful for proof-reading. ** Defaults to just the CLI commands. Specify --www to see only the ** web pages, or --everything to see both commands and pages. ** ** Options: ** -e|--everything Show all commands and pages. | | > | 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 |
**
** Show help text for commands and pages. Useful for proof-reading.
** Defaults to just the CLI commands. Specify --www to see only the
** web pages, or --everything to see both commands and pages.
**
** Options:
** -e|--everything Show all commands and pages.
** -t|--test Include test- commands.
** -w|--www Show WWW pages.
** -s|--settings Show settings.
** -h|--html Transform output to HTML.
** -r|--raw No output formatting.
** -o|--options Show global options.
*/
void test_all_help_cmd(void){
int mask = CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER;
int useHtml = find_option("html","h",0)!=0;
int rawOut = find_option("raw","r",0)!=0;
if( find_option("www","w",0) ){
|
| ︙ | ︙ | |||
1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 |
fossil_print(" * %s\n", az[i]);
}
fossil_print("Also consider using:\n");
fossil_print(" fossil help TOPIC ;# show help on TOPIC\n");
fossil_print(" fossil help -a ;# show all commands\n");
fossil_print(" fossil help -w ;# show all web-pages\n");
fossil_print(" fossil help -s ;# show all settings\n");
fossil_exit(1);
}
z = pCmd->zHelp;
if( z==0 ){
fossil_fatal("no help available for the %s %s",
pCmd->zName, zCmdOrPage);
}
| > | 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 |
fossil_print(" * %s\n", az[i]);
}
fossil_print("Also consider using:\n");
fossil_print(" fossil help TOPIC ;# show help on TOPIC\n");
fossil_print(" fossil help -a ;# show all commands\n");
fossil_print(" fossil help -w ;# show all web-pages\n");
fossil_print(" fossil help -s ;# show all settings\n");
fossil_print(" fossil help -o ;# show global options\n");
fossil_exit(1);
}
z = pCmd->zHelp;
if( z==0 ){
fossil_fatal("no help available for the %s %s",
pCmd->zName, zCmdOrPage);
}
|
| ︙ | ︙ |
Changes to src/export.c.
| ︙ | ︙ | |||
1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 |
manifest_destroy(pMan);
pMan = 0;
/* Include Fossil-generated auxiliary files in the check-in */
if( fManifest & MFESTFLG_RAW ){
Blob manifest;
content_get(rid, &manifest);
fprintf(xCmd,"M 100644 inline manifest\ndata %d\n%s\n",
blob_strlen(&manifest), blob_str(&manifest));
blob_reset(&manifest);
}
if( fManifest & MFESTFLG_UUID ){
int n = (int)strlen(zUuid);
fprintf(xCmd,"M 100644 inline manifest.uuid\ndata %d\n%s\n", n, zUuid);
| > | 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 |
manifest_destroy(pMan);
pMan = 0;
/* Include Fossil-generated auxiliary files in the check-in */
if( fManifest & MFESTFLG_RAW ){
Blob manifest;
content_get(rid, &manifest);
sterilize_manifest(&manifest, CFTYPE_MANIFEST);
fprintf(xCmd,"M 100644 inline manifest\ndata %d\n%s\n",
blob_strlen(&manifest), blob_str(&manifest));
blob_reset(&manifest);
}
if( fManifest & MFESTFLG_UUID ){
int n = (int)strlen(zUuid);
fprintf(xCmd,"M 100644 inline manifest.uuid\ndata %d\n%s\n", n, zUuid);
|
| ︙ | ︙ | |||
1715 1716 1717 1718 1719 1720 1721 |
zPushCmd = mprintf("git push --mirror %$", zPushUrl);
rc = fossil_system(zPushCmd);
if( rc ){
fossil_fatal("cannot push content using: %s", zPushCmd);
}else if( db_is_writeable("repository") ){
db_unprotect(PROTECT_CONFIG);
db_multi_exec("REPLACE INTO config(name,value,mtime)"
| | | 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 |
zPushCmd = mprintf("git push --mirror %$", zPushUrl);
rc = fossil_system(zPushCmd);
if( rc ){
fossil_fatal("cannot push content using: %s", zPushCmd);
}else if( db_is_writeable("repository") ){
db_unprotect(PROTECT_CONFIG);
db_multi_exec("REPLACE INTO config(name,value,mtime)"
"VALUES('gitpush:%q','{}',now())", zPushUrl);
db_protect_pop();
}
fossil_free(zPushCmd);
}
}
/*
|
| ︙ | ︙ |
Changes to src/extcgi.c.
| ︙ | ︙ | |||
66 67 68 69 70 71 72 73 74 75 76 77 78 79 | "REQUEST_URI", "SCRIPT_DIRECTORY", "SCRIPT_FILENAME", "SCRIPT_NAME", "SERVER_NAME", "SERVER_PORT", "SERVER_PROTOCOL", }; /* ** Check a pathname to determine if it is acceptable for use as ** extension CGI. Some pathnames are excluded for security reasons. ** Return NULL on success or a static error string if there is ** a failure. | > | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | "REQUEST_URI", "SCRIPT_DIRECTORY", "SCRIPT_FILENAME", "SCRIPT_NAME", "SERVER_NAME", "SERVER_PORT", "SERVER_PROTOCOL", "SERVER_SOFTWARE", }; /* ** Check a pathname to determine if it is acceptable for use as ** extension CGI. Some pathnames are excluded for security reasons. ** Return NULL on success or a static error string if there is ** a failure. |
| ︙ | ︙ | |||
169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
FILE *fromChild = 0; /* FILE for reading from child */
int pidChild = 0; /* Process id of the child */
int rc; /* Reply code from subroutine call */
int nContent = -1; /* Content length */
const char *zPathInfo; /* Original PATH_INFO value */
Blob reply; /* The reply */
char zLine[1000]; /* One line of the CGI reply */
zPathInfo = P("PATH_INFO");
login_check_credentials();
blob_init(&reply, 0, 0);
if( g.zExtRoot==0 ){
zFailReason = "extroot is not set";
goto ext_not_found;
| > | 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
FILE *fromChild = 0; /* FILE for reading from child */
int pidChild = 0; /* Process id of the child */
int rc; /* Reply code from subroutine call */
int nContent = -1; /* Content length */
const char *zPathInfo; /* Original PATH_INFO value */
Blob reply; /* The reply */
char zLine[1000]; /* One line of the CGI reply */
const char *zSrvSw; /* SERVER_SOFTWARE */
zPathInfo = P("PATH_INFO");
login_check_credentials();
blob_init(&reply, 0, 0);
if( g.zExtRoot==0 ){
zFailReason = "extroot is not set";
goto ext_not_found;
|
| ︙ | ︙ | |||
257 258 259 260 261 262 263 264 265 266 267 268 269 270 |
}
cgi_set_parameter_nocopy("FOSSIL_NONCE", style_nonce(), 0);
cgi_set_parameter_nocopy("FOSSIL_REPOSITORY", g.zRepositoryName, 0);
cgi_set_parameter_nocopy("FOSSIL_URI", g.zTop, 0);
cgi_set_parameter_nocopy("FOSSIL_CAPABILITIES",
db_text("","SELECT fullcap(cap) FROM user WHERE login=%Q",
g.zLogin ? g.zLogin : "nobody"), 0);
cgi_replace_parameter("GATEWAY_INTERFACE","CGI/1.0");
for(i=0; i<sizeof(azCgiEnv)/sizeof(azCgiEnv[0]); i++){
(void)P(azCgiEnv[i]);
}
fossil_clearenv();
for(i=0; i<sizeof(azCgiEnv)/sizeof(azCgiEnv[0]); i++){
const char *zVal = P(azCgiEnv[i]);
| > > > > > > > > > > | 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
}
cgi_set_parameter_nocopy("FOSSIL_NONCE", style_nonce(), 0);
cgi_set_parameter_nocopy("FOSSIL_REPOSITORY", g.zRepositoryName, 0);
cgi_set_parameter_nocopy("FOSSIL_URI", g.zTop, 0);
cgi_set_parameter_nocopy("FOSSIL_CAPABILITIES",
db_text("","SELECT fullcap(cap) FROM user WHERE login=%Q",
g.zLogin ? g.zLogin : "nobody"), 0);
zSrvSw = P("SERVER_SOFTWARE");
if( zSrvSw==0 ){
zSrvSw = get_version();
}else{
char *z = mprintf("fossil version %s", get_version());
if( strncmp(zSrvSw,z,strlen(z)-4)!=0 ){
zSrvSw = mprintf("%z, %s", z, zSrvSw);
}
}
cgi_replace_parameter("SERVER_SOFTWARE", zSrvSw);
cgi_replace_parameter("GATEWAY_INTERFACE","CGI/1.0");
for(i=0; i<sizeof(azCgiEnv)/sizeof(azCgiEnv[0]); i++){
(void)P(azCgiEnv[i]);
}
fossil_clearenv();
for(i=0; i<sizeof(azCgiEnv)/sizeof(azCgiEnv[0]); i++){
const char *zVal = P(azCgiEnv[i]);
|
| ︙ | ︙ |
Changes to src/file.c.
| ︙ | ︙ | |||
1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 |
** the root of zBasis in its name.
**
** If zTag is not NULL, then try to create the temp-file using zTag
** as a differentiator. If that fails, or if zTag is NULL, then use
** a bunch of random characters as the tag.
**
** Dangerous characters in zBasis are changed.
*/
void file_tempname(Blob *pBuf, const char *zBasis, const char *zTag){
#if defined(_WIN32)
const char *azDirs[] = {
0, /* GetTempPath */
0, /* TEMP */
0, /* TMP */
| > > | 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 |
** the root of zBasis in its name.
**
** If zTag is not NULL, then try to create the temp-file using zTag
** as a differentiator. If that fails, or if zTag is NULL, then use
** a bunch of random characters as the tag.
**
** Dangerous characters in zBasis are changed.
**
** See also fossil_temp_filename() and file_time_tempname();
*/
void file_tempname(Blob *pBuf, const char *zBasis, const char *zTag){
#if defined(_WIN32)
const char *azDirs[] = {
0, /* GetTempPath */
0, /* TEMP */
0, /* TMP */
|
| ︙ | ︙ | |||
1957 1958 1959 1960 1961 1962 1963 |
nBasis = 6;
zBasis = "fossil";
}
do{
blob_zero(pBuf);
if( cnt++>20 ) fossil_fatal("cannot generate a temporary filename");
if( zTag==0 ){
| > | | | | 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 |
nBasis = 6;
zBasis = "fossil";
}
do{
blob_zero(pBuf);
if( cnt++>20 ) fossil_fatal("cannot generate a temporary filename");
if( zTag==0 ){
const int nRand = sizeof(zRand)-1;
sqlite3_randomness(nRand, zRand);
for(i=0; i<nRand; i++){
zRand[i] = (char)zChars[ ((unsigned char)zRand[i])%(sizeof(zChars)-1) ];
}
zRand[nRand] = 0;
zTag = zRand;
}
blob_appendf(pBuf, "%s/%.*s~%s%s", zDir, nBasis, zBasis, zTag, zSuffix);
zTag = 0;
for(z=blob_str(pBuf); z!=0 && (z=strpbrk(z,"'\"`;|$&"))!=0; z++){
z[0] = '_';
}
|
| ︙ | ︙ | |||
1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 |
fossil_path_free((char *)azDirs[0]);
#endif
}
/*
** Compute a temporary filename in zDir. The filename is based on
** the current time.
*/
char *file_time_tempname(const char *zDir, const char *zSuffix){
struct tm *tm;
unsigned int r;
static unsigned int cnt = 0;
time_t t;
t = time(0);
| > > | 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 |
fossil_path_free((char *)azDirs[0]);
#endif
}
/*
** Compute a temporary filename in zDir. The filename is based on
** the current time.
**
** See also fossil_temp_filename() and file_tempname();
*/
char *file_time_tempname(const char *zDir, const char *zSuffix){
struct tm *tm;
unsigned int r;
static unsigned int cnt = 0;
time_t t;
t = time(0);
|
| ︙ | ︙ | |||
2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 |
/*
** COMMAND: test-tempname
** Usage: fossil test-name [--time SUFFIX] [--tag NAME] BASENAME ...
**
** Generate temporary filenames derived from BASENAME. Use the --time
** option to generate temp names based on the time of day. If --tag NAME
** is specified, try to use NAME as the differentiator in the temp file.
*/
void file_test_tempname(void){
int i;
const char *zSuffix = find_option("time",0,1);
Blob x = BLOB_INITIALIZER;
char *z;
const char *zTag = find_option("tag",0,1);
verify_all_options();
for(i=2; i<g.argc; i++){
if( zSuffix ){
z = file_time_tempname(g.argv[i], zSuffix);
fossil_print("%s\n", z);
fossil_free(z);
}else{
file_tempname(&x, g.argv[i], zTag);
| > > > > > > > > > | 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 |
/*
** COMMAND: test-tempname
** Usage: fossil test-name [--time SUFFIX] [--tag NAME] BASENAME ...
**
** Generate temporary filenames derived from BASENAME. Use the --time
** option to generate temp names based on the time of day. If --tag NAME
** is specified, try to use NAME as the differentiator in the temp file.
**
** If --time is used, file_time_tempname() generates the filename.
** If BASENAME is present, file_tempname() generates the filename.
** Without --time or BASENAME, fossil_temp_filename() generates the filename.
*/
void file_test_tempname(void){
int i;
const char *zSuffix = find_option("time",0,1);
Blob x = BLOB_INITIALIZER;
char *z;
const char *zTag = find_option("tag",0,1);
verify_all_options();
if( g.argc<=2 ){
z = fossil_temp_filename();
fossil_print("%s\n", z);
sqlite3_free(z);
}
for(i=2; i<g.argc; i++){
if( zSuffix ){
z = file_time_tempname(g.argv[i], zSuffix);
fossil_print("%s\n", z);
fossil_free(z);
}else{
file_tempname(&x, g.argv[i], zTag);
|
| ︙ | ︙ |
Changes to src/forum.c.
| ︙ | ︙ | |||
498 499 500 501 502 503 504 |
zPosterName = forum_post_display_name(p, pManifest);
zEditorName = zPosterName;
}
zDate = db_text(0, "SELECT datetime(%.17g,toLocal())", p->rDate);
if( p->pEditPrev ){
zPosterName = forum_post_display_name(p->pEditHead, 0);
zEditorName = forum_post_display_name(p, pManifest);
| | | | | | | 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 |
zPosterName = forum_post_display_name(p, pManifest);
zEditorName = zPosterName;
}
zDate = db_text(0, "SELECT datetime(%.17g,toLocal())", p->rDate);
if( p->pEditPrev ){
zPosterName = forum_post_display_name(p->pEditHead, 0);
zEditorName = forum_post_display_name(p, pManifest);
zHist = bHist ? "" : zQuery[0]==0 ? "?hist" : "&hist";
@ <h3 class='forumPostHdr'>(%d(p->sid)\
@ .%0*d(fossil_num_digits(p->nEdit))(p->rev)) \
if( fossil_strcmp(zPosterName, zEditorName)==0 ){
@ By %s(zPosterName) on %h(zDate) edited from \
@ %z(href("%R/forumpost/%S?%s%s",p->pEditPrev->zUuid,zQuery,zHist))\
@ %d(p->sid).%0*d(fossil_num_digits(p->nEdit))(p->pEditPrev->rev)</a>
}else{
@ Originally by %s(zPosterName) \
@ with edits by %s(zEditorName) on %h(zDate) from \
@ %z(href("%R/forumpost/%S%s%s",p->pEditPrev->zUuid,zQuery,zHist))\
@ %d(p->sid).%0*d(fossil_num_digits(p->nEdit))(p->pEditPrev->rev)</a>
}
}else{
zPosterName = forum_post_display_name(p, pManifest);
@ <h3 class='forumPostHdr'>(%d(p->sid)) \
@ By %s(zPosterName) on %h(zDate)
}
fossil_free(zDate);
/* If debugging is enabled, link to the artifact page. */
if( g.perm.Debug ){
@ <span class="debug">\
@ <a href="%R/artifact/%h(p->zUuid)">(artifact-%d(p->fpid))</a></span>
}
/* If this is a reply, refer back to the parent post. */
if( p->pIrt ){
@ in reply to %z(href("%R/forumpost/%S%s",p->pIrt->zUuid,zQuery))\
@ %d(p->pIrt->sid)\
if( p->pIrt->nEdit ){
@ .%0*d(fossil_num_digits(p->pIrt->nEdit))(p->pIrt->rev)\
}
@ </a>
}
/* If this post was later edited, refer forward to the next edit. */
if( p->pEditNext ){
@ updated by %z(href("%R/forumpost/%S%s",p->pEditNext->zUuid,zQuery))\
@ %d(p->pEditNext->sid)\
@ .%0*d(fossil_num_digits(p->nEdit))(p->pEditNext->rev)</a>
}
/* Provide a link to select the individual post. */
if( !bSelect ){
@ %z(href("%R/forumpost/%!S%s",p->zUuid,zQuery))[link]</a>
}
/* Provide a link to the raw source code. */
if( !bUnf ){
@ %z(href("%R/forumpost/%!S?raw",p->zUuid))[source]</a>
}
@ </h3>
|
| ︙ | ︙ | |||
630 631 632 633 634 635 636 637 638 639 640 641 642 |
** Display a forum thread. If mode is FD_RAW or FD_SINGLE, display only a
** single post from the thread and (optionally) its edit history.
*/
static void forum_display_thread(
int froot, /* Forum thread root post ID */
int fpid, /* Selected forum post ID, or 0 if none selected */
int mode, /* Forum display mode, one of the FD_* enumerations */
int bUnf, /* True if rendering unformatted */
int bHist /* True if showing edit history, ignored for FD_RAW */
){
ForumThread *pThread; /* Thread structure */
ForumPost *pSelect; /* Currently selected post, or NULL if none */
ForumPost *p; /* Post iterator pointer */
| > | > | 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 |
** Display a forum thread. If mode is FD_RAW or FD_SINGLE, display only a
** single post from the thread and (optionally) its edit history.
*/
static void forum_display_thread(
int froot, /* Forum thread root post ID */
int fpid, /* Selected forum post ID, or 0 if none selected */
int mode, /* Forum display mode, one of the FD_* enumerations */
int autoMode, /* mode was selected automatically */
int bUnf, /* True if rendering unformatted */
int bHist /* True if showing edit history, ignored for FD_RAW */
){
ForumThread *pThread; /* Thread structure */
ForumPost *pSelect; /* Currently selected post, or NULL if none */
ForumPost *p; /* Post iterator pointer */
char zQuery[30]; /* Common query string */
int iIndentScale = 4; /* Indent scale factor, measured in "ex" units */
int sid; /* Comparison serial ID */
int i;
/* In raw mode, force unformatted display and disable history. */
if( mode == FD_RAW ){
bUnf = 1;
bHist = 0;
}
|
| ︙ | ︙ | |||
673 674 675 676 677 678 679 |
** selected forum post does not exist in the thread. Otherwise proceed to
** display the entire thread without marking any posts as selected. */
if( !pSelect && (mode==FD_RAW || mode==FD_SINGLE) ){
return;
}
/* Create the common query string to append to nearly all post links. */
| > > > | > | > > > > > > > > > > > > > > | > > > > > > > > | 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 |
** selected forum post does not exist in the thread. Otherwise proceed to
** display the entire thread without marking any posts as selected. */
if( !pSelect && (mode==FD_RAW || mode==FD_SINGLE) ){
return;
}
/* Create the common query string to append to nearly all post links. */
i = 0;
if( !autoMode ){
char m = 'a';
switch( mode ){
case FD_RAW: m = 'r'; break;
case FD_CHRONO: m = 'c'; break;
case FD_HIER: m = 'h'; break;
case FD_SINGLE: m = 's'; break;
}
zQuery[i++] = '?';
zQuery[i++] = 't';
zQuery[i++] = '=';
zQuery[i++] = m;
}
if( bUnf ){
zQuery[i] = i==0 ? '?' : '&'; i++;
zQuery[i++] = 'u';
zQuery[i++] = 'n';
zQuery[i++] = 'f';
}
if( bHist ){
zQuery[i] = i==0 ? '?' : '&'; i++;
zQuery[i++] = 'h';
zQuery[i++] = 'i';
zQuery[i++] = 's';
zQuery[i++] = 't';
}
assert( i<sizeof(zQuery) );
zQuery[i] = 0;
/* Identify which post to display first. If history is shown, start with the
** original, unedited post. Otherwise advance to the post's latest edit. */
if( mode==FD_RAW || mode==FD_SINGLE ){
p = pSelect;
if( bHist && p->pEditHead ) p = p->pEditHead;
}else{
|
| ︙ | ︙ | |||
742 743 744 745 746 747 748 |
@ <td>%S(p->zUuid)</tr>
}
@ </table>
}
/* Clean up. */
forumthread_delete(pThread);
| < | 770 771 772 773 774 775 776 777 778 779 780 781 782 783 |
@ <td>%S(p->zUuid)</tr>
}
@ </table>
}
/* Clean up. */
forumthread_delete(pThread);
}
/*
** Emit Forum Javascript which applies (or optionally can apply)
** to all forum-related pages. It does not include page-specific
** code (e.g. "forum.js").
*/
|
| ︙ | ︙ | |||
811 812 813 814 815 816 817 818 819 820 821 822 823 824 |
char *zThreadTitle;
const char *zName = P("name");
const char *zMode = PD("t","a");
int bRaw = PB("raw");
int bUnf = PB("unf");
int bHist = PB("hist");
int mode = 0;
login_check_credentials();
if( !g.perm.RdForum ){
login_needed(g.anon.RdForum);
return;
}
if( zName==0 ){
webpage_error("Missing \"name=\" query parameter");
| > | 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 |
char *zThreadTitle;
const char *zName = P("name");
const char *zMode = PD("t","a");
int bRaw = PB("raw");
int bUnf = PB("unf");
int bHist = PB("hist");
int mode = 0;
int autoMode = 0;
login_check_credentials();
if( !g.perm.RdForum ){
login_needed(g.anon.RdForum);
return;
}
if( zName==0 ){
webpage_error("Missing \"name=\" query parameter");
|
| ︙ | ︙ | |||
844 845 846 847 848 849 850 |
bUnf = 1;
bHist = 0;
cgi_replace_query_parameter("unf", "on");
cgi_delete_query_parameter("hist");
cgi_delete_query_parameter("raw");
}else{
switch( *zMode ){
| | > | 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 |
bUnf = 1;
bHist = 0;
cgi_replace_query_parameter("unf", "on");
cgi_delete_query_parameter("hist");
cgi_delete_query_parameter("raw");
}else{
switch( *zMode ){
case 'a': mode = cgi_from_mobile() ? FD_CHRONO : FD_HIER;
autoMode=1; break;
case 'c': mode = FD_CHRONO; break;
case 'h': mode = FD_HIER; break;
case 's': mode = FD_SINGLE; break;
case 'r': mode = FD_CHRONO; break;
case 'y': mode = FD_SINGLE; break;
default: webpage_error("Invalid thread mode: \"%s\"", zMode);
}
|
| ︙ | ︙ | |||
885 886 887 888 889 890 891 |
style_submenu_element("Hierarchical", "%R/%s/%s?t=h%s%s", g.zPath, zName,
bUnf ? "&unf" : "", bHist ? "&hist" : "");
}
style_submenu_checkbox("unf", "Unformatted", 0, 0);
style_submenu_checkbox("hist", "History", 0, 0);
/* Display the thread. */
| | | 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 |
style_submenu_element("Hierarchical", "%R/%s/%s?t=h%s%s", g.zPath, zName,
bUnf ? "&unf" : "", bHist ? "&hist" : "");
}
style_submenu_checkbox("unf", "Unformatted", 0, 0);
style_submenu_checkbox("hist", "History", 0, 0);
/* Display the thread. */
forum_display_thread(froot, fpid, mode, autoMode, bUnf, bHist);
/* Emit Forum Javascript. */
builtin_request_js("forum.js");
forum_emit_js();
/* Emit the page style. */
style_finish_page();
|
| ︙ | ︙ |
Changes to src/fossil.bootstrap.js.
| ︙ | ︙ | |||
287 288 289 290 291 292 293 294 |
*/
F.page.setPageTitle = function(title){
const t = document.querySelector('title');
if(t) t.innerText = title;
return this;
};
})(window);
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 |
*/
F.page.setPageTitle = function(title){
const t = document.querySelector('title');
if(t) t.innerText = title;
return this;
};
/**
Returns a function, that, as long as it continues to be invoked,
will not be triggered. The function will be called after it stops
being called for N milliseconds. If `immediate` is passed, call
the callback immediately and hinder future invocations until at
least the given time has passed.
If passed only 1 argument, or passed a falsy 2nd argument,
the default wait time set in this function's $defaultDelay
property is used.
Source: underscore.js, by way of https://davidwalsh.name/javascript-debounce-function
*/
F.debounce = function f(func, wait, immediate) {
var timeout;
if(!wait) wait = f.$defaultDelay;
return function() {
const context = this, args = Array.prototype.slice.call(arguments);
const later = function() {
timeout = undefined;
if(!immediate) func.apply(context, args);
};
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if(callNow) func.apply(context, args);
};
};
F.debounce.$defaultDelay = 500 /*arbitrary*/;
})(window);
|
Changes to src/fossil.diff.js.
| ︙ | ︙ | |||
735 736 737 738 739 740 741 |
return this;
}
window.fossil.page.tweakSbsDiffs = function(){
document.querySelectorAll('table.splitdiff').forEach((e)=>Diff.initTableDiff(e));
Diff.checkTableWidth();
};
Diff.initTableDiff().checkTableWidth();
| | | 735 736 737 738 739 740 741 742 743 |
return this;
}
window.fossil.page.tweakSbsDiffs = function(){
document.querySelectorAll('table.splitdiff').forEach((e)=>Diff.initTableDiff(e));
Diff.checkTableWidth();
};
Diff.initTableDiff().checkTableWidth();
window.addEventListener('resize', F.debounce(()=>Diff.checkTableWidth()));
}, false);
|
Changes to src/fossil.page.chat.js.
| ︙ | ︙ | |||
41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
Returns an almost-ISO8601 form of Date object d.
*/
const iso8601ish = function(d){
return d.toISOString()
.replace('T',' ').replace(/\.\d+/,'')
.replace('Z', ' zulu');
};
/** Returns the local time string of Date object d, defaulting
to the current time. */
const localTimeString = function ff(d){
d || (d = new Date());
return [
d.getFullYear(),'-',pad2(d.getMonth()+1/*sigh*/),
'-',pad2(d.getDate()),
| > | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
Returns an almost-ISO8601 form of Date object d.
*/
const iso8601ish = function(d){
return d.toISOString()
.replace('T',' ').replace(/\.\d+/,'')
.replace('Z', ' zulu');
};
const pad2 = (x)=>('0'+x).substr(-2);
/** Returns the local time string of Date object d, defaulting
to the current time. */
const localTimeString = function ff(d){
d || (d = new Date());
return [
d.getFullYear(),'-',pad2(d.getMonth()+1/*sigh*/),
'-',pad2(d.getDate()),
|
| ︙ | ︙ | |||
92 93 94 95 96 97 98 |
var extra = 0;
if(com){
ht = wh;
}else{
elemsToCount.forEach((e)=>e ? extra += D.effectiveHeight(e) : false);
ht = wh - extra;
}
| | | | | < < < < | | > > | 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
var extra = 0;
if(com){
ht = wh;
}else{
elemsToCount.forEach((e)=>e ? extra += D.effectiveHeight(e) : false);
ht = wh - extra;
}
f.chat.e.inputX.style.maxHeight = (ht/2)+"px";
/* ^^^^ this is a middle ground between having no size cap
on the input field and having a fixed arbitrary cap. */;
contentArea.style.height =
contentArea.style.maxHeight = [
"calc(", (ht>=100 ? ht : 100), "px",
" - 0.75em"/*fudge value*/,")"
/* ^^^^ hypothetically not needed, but both Chrome/FF on
Linux will force scrollbars on the body if this value is
too small (<0.75em in my tests). */
].join('');
if(false){
console.debug("resized.",wh, extra, ht,
window.getComputedStyle(contentArea).maxHeight,
contentArea);
console.debug("Set input max height to: ",
f.chat.e.inputX.style.maxHeight);
}
};
resized.$disabled = true/*gets deleted when setup is finished*/;
window.addEventListener('resize', F.debounce(resized, 250), false);
return resized;
})();
fossil.FRK = ForceResizeKludge/*for debugging*/;
const Chat = ForceResizeKludge.chat = (function(){
const cs = {
verboseErrors: false /* if true then certain, mostly extraneous,
error messages may be sent to the console. */,
e:{/*map of certain DOM elements.*/
messageInjectPoint: E1('#message-inject-point'),
pageTitle: E1('head title'),
loadOlderToolbar: undefined /* the load-posts toolbar (dynamically created) */,
inputWrapper: E1("#chat-input-area"),
inputElementWrapper: E1('#chat-input-line-wrapper'),
fileSelectWrapper: E1('#chat-input-file-area'),
viewMessages: E1('#chat-messages-wrapper'),
btnSubmit: E1('#chat-button-submit'),
btnAttach: E1('#chat-button-attach'),
inputX: E1('#chat-input-field-x'),
input1: E1('#chat-input-field-single'),
inputM: E1('#chat-input-field-multi'),
inputFile: E1('#chat-input-file'),
contentDiv: E1('div.content'),
viewConfig: E1('#chat-config'),
viewPreview: E1('#chat-preview'),
previewContent: E1('#chat-preview-content'),
btnPreview: E1('#chat-button-preview'),
views: document.querySelectorAll('.chat-view'),
|
| ︙ | ︙ | |||
174 175 176 177 178 179 180 |
},
/** Gets (no args) or sets (1 arg) the current input text field value,
taking into account single- vs multi-line input. The getter returns
a string and the setter returns this object. */
inputValue: function(){
const e = this.inputElement();
if(arguments.length){
| > | | | | 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
},
/** Gets (no args) or sets (1 arg) the current input text field value,
taking into account single- vs multi-line input. The getter returns
a string and the setter returns this object. */
inputValue: function(){
const e = this.inputElement();
if(arguments.length){
if(e.isContentEditable) e.innerText = arguments[0];
else e.value = arguments[0];
return this;
}
return e.isContentEditable ? e.innerText : e.value;
},
/** Asks the current user input field to take focus. Returns this. */
inputFocus: function(){
this.inputElement().focus();
return this;
},
/** Returns the current message input element. */
inputElement: function(){
return this.e.inputFields[this.e.inputFields.$currentIndex];
},
/** Enables (if yes is truthy) or disables all elements in
* this.disableDuringAjax. */
enableAjaxComponents: function(yes){
D[yes ? 'enable' : 'disable'](this.disableDuringAjax);
return this;
},
|
| ︙ | ︙ | |||
415 416 417 418 419 420 421 |
"active-user-list": false,
/* When on, the [active-user-list] setting includes the
timestamp of each user's most recent message. */
"active-user-list-timestamps": false,
/* When on, the [audible-alert] is played for one's own
messages, else it is only played for other users'
messages. */
| | > > > > > > | 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 |
"active-user-list": false,
/* When on, the [active-user-list] setting includes the
timestamp of each user's most recent message. */
"active-user-list-timestamps": false,
/* When on, the [audible-alert] is played for one's own
messages, else it is only played for other users'
messages. */
"alert-own-messages": false,
/* "Experimental mode" input: use a contenteditable field
for input. This is generally more comfortable to use,
and more modern, than plain text input fields, but
the list of browser-specific quirks and bugs is...
not short. */
"edit-widget-x": false
}
},
/** Plays a new-message notification sound IF the audible-alert
setting is true, else this is a no-op. Returns this.
*/
playNewMessageSound: function f(){
if(f.uri){
|
| ︙ | ︙ | |||
577 578 579 580 581 582 583 |
animate: function f(e,a,cb){
if(!f.$disabled){
D.addClassBriefly(e, a, 0, cb);
}
return this;
}
};
| > > > > > > | | | 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 |
animate: function f(e,a,cb){
if(!f.$disabled){
D.addClassBriefly(e, a, 0, cb);
}
return this;
}
};
cs.e.inputFields = [ cs.e.input1, cs.e.inputM, cs.e.inputX ];
cs.e.inputFields.$currentIndex = 0;
cs.e.inputFields.forEach(function(e,ndx){
if(ndx===cs.e.inputFields.$currentIndex) D.removeClass(e,'hidden');
else D.addClass(e,'hidden');
});
if(D.attr(cs.e.inputX,'contenteditable','plaintext-only').isContentEditable){
cs.$browserHasPlaintextOnly = true;
}else{
/* Only the Chrome family supports contenteditable=plaintext-only */
cs.$browserHasPlaintextOnly = false;
D.attr(cs.e.inputX,'contenteditable','true');
}
cs.animate.$disabled = true;
F.fetch.beforesend = ()=>cs.ajaxStart();
F.fetch.aftersend = ()=>cs.ajaxEnd();
cs.pageTitleOrig = cs.e.pageTitle.innerText;
const qs = (e)=>document.querySelector(e);
const argsToArray = function(args){
|
| ︙ | ︙ | |||
607 608 609 610 611 612 613 |
};
/**
Reports an error in the form of a new message in the chat
feed. All arguments are appended to the message's content area
using fossil.dom.append(), so may be of any type supported by
that function.
*/
| | > | > > | | 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 |
};
/**
Reports an error in the form of a new message in the chat
feed. All arguments are appended to the message's content area
using fossil.dom.append(), so may be of any type supported by
that function.
*/
cs.reportErrorAsMessage = function f(/*msg args*/){
if(undefined === f.$msgid) f.$msgid=0;
const args = argsToArray(arguments).map(function(v){
return (v instanceof Error) ? v.message : v;
});
console.error("chat error:",args);
const d = new Date().toISOString(),
mw = new this.MessageWidget({
isError: true,
xfrom: null,
msgid: "error-"+(++f.$msgid),
mtime: d,
lmtime: d,
xmsg: args
});
this.injectMessageElem(mw.e.body);
mw.scrollIntoView();
};
|
| ︙ | ︙ | |||
684 685 686 687 688 689 690 |
id = e.dataset.msgid;
}else{
e = this.getMessageElemById(id);
}
if(!e || !id) return false;
else if(e.$isToggling) return;
e.$isToggling = true;
| | | 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 |
id = e.dataset.msgid;
}else{
e = this.getMessageElemById(id);
}
if(!e || !id) return false;
else if(e.$isToggling) return;
e.$isToggling = true;
const content = e.querySelector('.content-target');
if(!content.$elems){
content.$elems = [
content.firstElementChild, // parsed elem
undefined // plaintext elem
];
}else if(content.$elems[1]){
// We have both content types. Simply toggle them.
|
| ︙ | ︙ | |||
820 821 822 823 824 825 826 827 828 829 830 831 832 833 |
cs.setUserFilter(uname);
}
return false;
}, false);
return cs;
})()/*Chat initialization*/;
/**
Custom widget type for rendering messages (one message per
instance). These are modelled after FIELDSET elements but we
don't use FIELDSET because of cross-browser inconsistencies in
features of the FIELDSET/LEGEND combination, e.g. inability to
align legends via CSS in Firefox and clicking-related
deficiencies in Safari.
| > > > > > > > > > > | 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 |
cs.setUserFilter(uname);
}
return false;
}, false);
return cs;
})()/*Chat initialization*/;
/** Returns the first .message-widget element in DOM element
e's lineage. */
const findMessageWidgetParent = function(e){
while( e && !e.classList.contains('message-widget')){
e = e.parentNode;
}
return e;
};
/**
Custom widget type for rendering messages (one message per
instance). These are modelled after FIELDSET elements but we
don't use FIELDSET because of cross-browser inconsistencies in
features of the FIELDSET/LEGEND combination, e.g. inability to
align legends via CSS in Firefox and clicking-related
deficiencies in Safari.
|
| ︙ | ︙ | |||
846 847 848 849 850 851 852 |
D.append(this.e.body, this.e.tab, this.e.content);
this.e.tab.setAttribute('role', 'button');
if(arguments.length){
this.setMessage(arguments[0]);
}
};
/* Left-zero-pad a number to at least 2 digits */
| < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 |
D.append(this.e.body, this.e.tab, this.e.content);
this.e.tab.setAttribute('role', 'button');
if(arguments.length){
this.setMessage(arguments[0]);
}
};
/* Left-zero-pad a number to at least 2 digits */
const dowMap = {
/* Map of Date.getDay() values to weekday names. */
0: "Sunday", 1: "Monday", 2: "Tuesday",
3: "Wednesday", 4: "Thursday", 5: "Friday",
6: "Saturday"
};
/* Given a Date, returns the timestamp string used in the
"tab" part of message widgets. */
const theTime = function(d){
return [
//d.getFullYear(),'-',pad2(d.getMonth()+1/*sigh*/),
//'-',pad2(d.getDate()), ' ',
d.getHours(),":",
(d.getMinutes()+100).toString().slice(1,3),
' ', dowMap[d.getDay()]
].join('');
};
const canEmbedFile = function f(msg){
if(!f.$rx){
f.$rx = /\.((html?)|(txt))$/i;
f.$specificTypes = [
'text/plain',
'text/html'
// add more as we discover which ones Firefox won't
// force the user to try to download.
];
}
if(msg.fmime){
return (msg.fmime.startsWith("image/")
|| f.$specificTypes.indexOf(msg.fmime)>=0);
}
return msg.fname && f.$rx.test(msg.fname);
};
const adjustIFrameSize = function(msgObj){
const iframe = msgObj.e.iframe;
const body = iframe.contentWindow.document.querySelector('body');
if(body && !body.style.fontSize){
/** _Attempt_ to force the iframe to inherit the message's text size
if the body has no explicit size set. On desktop systems
the size is apparently being inherited in that case, but on mobile
not. */
body.style.fontSize = window.getComputedStyle(msgObj.e.content);
}
if('' === iframe.style.maxHeight){
/* Resize iframe height to fit the content. Workaround: if we
adjust the iframe height while it's hidden then its height
is 0, so we must briefly unhide it. */
const isHidden = iframe.classList.contains('hidden');
if(isHidden) D.removeClass(iframe, 'hidden');
iframe.style.maxHeight = iframe.style.height
= iframe.contentWindow.document.documentElement.scrollHeight + 'px';
if(isHidden) D.addClass(iframe, 'hidden');
}
};
cf.prototype = {
scrollIntoView: function(){
this.e.content.scrollIntoView();
},
setMessage: function(m){
const ds = this.e.body.dataset;
ds.timestamp = m.mtime;
|
| ︙ | ︙ | |||
898 899 900 901 902 903 904 |
}else{/*notification*/
D.addClass(this.e.body, 'notification');
if(m.isError){
D.addClass([contentTarget, this.e.tab], 'error');
}
D.append(
this.e.tab,
| | > | > > | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > | > > | 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 |
}else{/*notification*/
D.addClass(this.e.body, 'notification');
if(m.isError){
D.addClass([contentTarget, this.e.tab], 'error');
}
D.append(
this.e.tab,
D.append(D.code(), 'notification @ ',theTime(d))
);
}
if( m.xfrom && m.fsize>0 ){
if( m.fmime
&& m.fmime.startsWith("image/")
&& Chat.settings.getBool('images-inline',true)
){
const extension = m.fname.split('.').pop();
contentTarget.appendChild(D.img("chat-download/" + m.msgid +(
extension ? ('.'+extension) : ''/*So that IMG tag mimetype guessing works*/
)));
ds.hasImage = 1;
}else{
// Add a download link.
const downloadUri = window.fossil.rootPath+
'chat-download/' + m.msgid+'/'+encodeURIComponent(m.fname);
const w = D.addClass(D.div(), 'attachment-link');
const a = D.a(downloadUri,
// ^^^ add m.fname to URL to cause downloaded file to have that name.
"(" + m.fname + " " + m.fsize + " bytes)"
)
D.attr(a,'target','_blank');
D.append(w, a);
if(canEmbedFile(m)){
/* Add an option to embed HTML attachments in an iframe. The primary
use case is attached diffs. */
D.addClass(contentTarget, 'wide');
const embedTarget = this.e.content;
const self = this;
const btnEmbed = D.attr(D.checkbox("1", false), 'id',
'embed-'+ds.msgid);
const btnLabel = D.label(btnEmbed, "Embed");
/* Maintenance reminder: do not disable the toggle
button while the content is loading because that will
cause it to get stuck in disabled mode if the browser
decides that loading the content should prompt the
user to download it, rather than embed it in the
iframe. */
btnEmbed.addEventListener('change',function(){
if(self.e.iframe){
if(btnEmbed.checked){
D.removeClass(self.e.iframe, 'hidden');
if(self.e.$iframeLoaded) adjustIFrameSize(self);
}
else D.addClass(self.e.iframe, 'hidden');
return;
}
const iframe = self.e.iframe = document.createElement('iframe');
D.append(embedTarget, iframe);
iframe.addEventListener('load', function(){
self.e.$iframeLoaded = true;
adjustIFrameSize(self);
});
iframe.setAttribute('src', downloadUri);
});
D.append(w, btnEmbed, btnLabel);
}
contentTarget.appendChild(w);
}
}
if(m.xmsg){
if(m.fsize>0){
/* We have file/image content, so need another element for
the message text. */
contentTarget = D.div();
D.append(this.e.content, contentTarget);
}
D.addClass(contentTarget, 'content-target'
/*target element for the 'toggle text mode' feature*/);
// The m.xmsg text comes from the same server as this script and
// is guaranteed by that server to be "safe" HTML - safe in the
// sense that it is not possible for a malefactor to inject HTML
// or javascript or CSS. The m.xmsg content might contain
// hyperlinks, but otherwise it will be markup-free. See the
// chat_format_to_html() routine in the server for details.
//
// Hence, even though innerHTML is normally frowned upon, it is
// perfectly safe to use in this context.
if(m.xmsg && 'string' !== typeof m.xmsg){
// Used by Chat.reportErrorAsMessage()
D.append(contentTarget, m.xmsg);
}else{
contentTarget.innerHTML = m.xmsg;
contentTarget.querySelectorAll('a').forEach(addAnchorTargetBlank);
if(F.pikchr){
F.pikchr.addSrcView(contentTarget.querySelectorAll('svg.pikchr'));
}
}
}
//console.debug("tab",this.e.tab);
//console.debug("this.e.tab.firstElementChild",this.e.tab.firstElementChild);
this.e.tab.firstElementChild.addEventListener('click', this._handleLegendClicked, false);
/*if(eXFrom){
eXFrom.addEventListener('click', ()=>this.e.tab.click(), false);
}*/
return this;
},
/* Event handler for clicking .message-user elements to show their
|
| ︙ | ︙ | |||
1086 1087 1088 1089 1090 1091 1092 |
return;
}
this.$eMsg = tgtMsg;
this.refresh();
}
}/*f.popup*/;
}/*end static init*/
| | < < < | | 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 |
return;
}
this.$eMsg = tgtMsg;
this.refresh();
}
}/*f.popup*/;
}/*end static init*/
const theMsg = findMessageWidgetParent(ev.target);
if(theMsg) f.popup.show(theMsg);
}/*_handleLegendClicked()*/
};
return cf;
})()/*MessageWidget*/;
const BlobXferState = (function(){
/* State for paste and drag/drop */
const bxs = {
dropDetails: document.querySelector('#chat-drop-details'),
blob: undefined,
clear: function(){
this.blob = undefined;
D.clearElement(this.dropDetails);
Chat.e.inputFile.value = "";
}
};
/** Updates the paste/drop zone with details of the pasted/dropped
data. The argument must be a Blob or Blob-like object (File) or
it can be falsy to reset/clear that state.*/
const updateDropZoneContent = bxs.updateDropZoneContent = function(blob){
//console.debug("updateDropZoneContent()",blob);
const dd = bxs.dropDetails;
bxs.blob = blob;
D.clearElement(dd);
if(!blob){
Chat.e.inputFile.value = '';
return;
|
| ︙ | ︙ | |||
1159 1160 1161 1162 1163 1164 1165 |
document.addEventListener('paste', pasteListener, true);
if(window.Selection && window.Range && !Chat.$browserHasPlaintextOnly){
/* Acrobatics to keep *some* installations of Firefox
from pasting formatting into contenteditable fields.
This also works on Chrome, but chrome has the
contenteditable=plaintext-only property which does this
for us. */
| | | 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 |
document.addEventListener('paste', pasteListener, true);
if(window.Selection && window.Range && !Chat.$browserHasPlaintextOnly){
/* Acrobatics to keep *some* installations of Firefox
from pasting formatting into contenteditable fields.
This also works on Chrome, but chrome has the
contenteditable=plaintext-only property which does this
for us. */
Chat.e.inputX.addEventListener(
'paste',
function(ev){
if (ev.clipboardData && ev.clipboardData.getData) {
const pastedText = ev.clipboardData.getData('text/plain');
const selection = window.getSelection();
if (!selection.rangeCount) return false;
selection.deleteFromDocument(/*remove selected content*/);
|
| ︙ | ︙ | |||
1183 1184 1185 1186 1187 1188 1189 |
which is not compatible with how we use it, so... */
ev.dataTransfer.effectAllowed = 'none';
ev.dataTransfer.dropEffect = 'none';
ev.preventDefault();
ev.stopPropagation();
return false;
};
| < < | < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 |
which is not compatible with how we use it, so... */
ev.dataTransfer.effectAllowed = 'none';
ev.dataTransfer.dropEffect = 'none';
ev.preventDefault();
ev.stopPropagation();
return false;
};
['drop','dragenter','dragleave','dragend'].forEach(
(k)=>Chat.e.inputX.addEventListener(k, noDragDropEvents, false)
);
return bxs;
})()/*drag/drop/paste*/;
const tzOffsetToString = function(off){
const hours = Math.round(off/60), min = Math.round(off % 30);
return ''+(hours + (min ? '.5' : ''));
};
const localTime8601 = function(d){
return [
d.getYear()+1900, '-', pad2(d.getMonth()+1), '-', pad2(d.getDate()),
'T', pad2(d.getHours()),':', pad2(d.getMinutes()),':',pad2(d.getSeconds())
].join('');
};
/**
Called by Chat.submitMessage() when message sending failed. Injects a fake message
containing the content and attachment of the failed message and gives the user buttons
to discard it or edit and retry.
*/
const recoverFailedMessage = function(state){
const w = D.addClass(D.div(), 'failed-message');
D.append(w, D.append(
D.span(),"This message was not successfully sent to the server:"
));
if(state.msg){
const ta = D.textarea();
ta.value = state.msg;
D.append(w,ta);
}
if(state.blob){
D.append(w,D.append(D.span(),"Attachment: ",(state.blob.name||"unnamed")));
//console.debug("blob = ",state.blob);
}
const buttons = D.addClass(D.div(), 'buttons');
D.append(w, buttons);
D.append(buttons, D.button("Discard message?", function(){
const theMsg = findMessageWidgetParent(w);
if(theMsg) Chat.deleteMessageElem(theMsg);
}));
D.append(buttons, D.button("Edit message and try again?", function(){
if(state.msg) Chat.inputValue(state.msg);
if(state.blob) BlobXferState.updateDropZoneContent(state.blob);
const theMsg = findMessageWidgetParent(w);
if(theMsg) Chat.deleteMessageElem(theMsg);
}));
Chat.reportErrorAsMessage(w);
};
/**
Submits the contents of the message input field (if not empty)
and/or the file attachment field to the server. If both are
empty, this is a no-op.
*/
Chat.submitMessage = function f(){
if(!f.spaces){
f.spaces = /\s+$/;
f.markdownContinuation = /\\\s+$/;
}
this.setCurrentView(this.e.viewMessages);
const fd = new FormData();
const fallback = {msg: this.inputValue()};
var msg = fallback.msg.trim();
if(msg && (msg.indexOf('\n')>0 || f.spaces.test(msg))){
/* Cosmetic: trim whitespace from the ends of lines to try to
keep copy/paste from terminals, especially wide ones, from
forcing a horizontal scrollbar on all clients. This breaks
markdown's use of blackslash-space-space for paragraph
continuation, but *not* doing this affects all clients every
time someone pastes in console copy/paste from an affected
|
| ︙ | ︙ | |||
1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 |
});
msg = xmsg.join('\n');
}
if(msg) fd.set('msg',msg);
const file = BlobXferState.blob || this.e.inputFile.files[0];
if(file) fd.set("file", file);
if( !msg && !file ) return;
const self = this;
fd.set("lmtime", localTime8601(new Date()));
F.fetch("chat-send",{
payload: fd,
responseType: 'text',
| > > | > > < > | 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 |
});
msg = xmsg.join('\n');
}
if(msg) fd.set('msg',msg);
const file = BlobXferState.blob || this.e.inputFile.files[0];
if(file) fd.set("file", file);
if( !msg && !file ) return;
fallback.blob = file;
const self = this;
fd.set("lmtime", localTime8601(new Date()));
F.fetch("chat-send",{
payload: fd,
responseType: 'text',
onerror:function(err){
self.reportErrorAsMessage(err);
recoverFailedMessage(fallback);
},
onload:function(txt){
if(!txt) return/*success response*/;
try{
const json = JSON.parse(txt);
self.newContent({msgs:[json]});
}catch(e){
self.reportError(e);
}
recoverFailedMessage(fallback);
}
});
BlobXferState.clear();
Chat.inputValue("").inputFocus();
};
const inputWidgetKeydown = function f(ev){
|
| ︙ | ︙ | |||
1321 1322 1323 1324 1325 1326 1327 |
/* Ship it! */
ev.preventDefault();
ev.stopPropagation();
Chat.submitMessage();
return false;
}
};
| > | > | 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 |
/* Ship it! */
ev.preventDefault();
ev.stopPropagation();
Chat.submitMessage();
return false;
}
};
Chat.e.inputFields.forEach(
(e)=>e.addEventListener('keydown', inputWidgetKeydown, false)
);
Chat.e.btnSubmit.addEventListener('click',(e)=>{
e.preventDefault();
Chat.submitMessage();
return false;
});
Chat.e.btnAttach.addEventListener(
'click', ()=>Chat.e.inputFile.click(), false);
|
| ︙ | ︙ | |||
1381 1382 1383 1384 1385 1386 1387 |
/* Settings menu entries... the most frequently-needed ones "should"
(arguably) be closer to the start of this list. */
/**
Settings ops structure:
label: string for the UI
| | > | > > > > > > > > > > > > > > > > | | > | > > > > > > > > > > > > > | > | < | | | > | | | > | | | | | > > > > > > > > > > > > | | | | | | | | | | | | | | | | | | | < < < < | | > | < < < < > | 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 |
/* Settings menu entries... the most frequently-needed ones "should"
(arguably) be closer to the start of this list. */
/**
Settings ops structure:
label: string for the UI
boolValue: string (name of Chat.settings setting) or a function
which returns true or false. If it is a string, it gets
replaced by a function which returns
Chat.settings.getBool(thatString) and the string gets assigned
to the persistentSetting property of this object.
select: SELECT element (instead of boolValue)
callback: optional handler to call after setting is modified.
Its "this" is the options object. If this object has a
boolValue string or a persistentSetting property, the argument
passed to the callback is a settings object in the form {key:K,
value:V}. If this object does not have boolValue string or
persistentSetting then the callback is passed an event object
in response to the config option's UI widget being activated,
normally a 'change' event.
children: [array of settings objects]. These get listed under
this element and indented slightly for visual grouping. Only
one level of indention is supported.
Elements which only have a label and maybe a hint and
children can be used as headings.
If a setting has a boolValue set, that gets rendered as a
checkbox which toggles the given persistent setting (if
boolValue is a string) AND listens for changes to that setting
fired via Chat.settings.set() so that the checkbox can stay in
sync with external changes to that setting. Various Chat UI
elements stay in sync with the config UI via those settings
events. The checkbox element gets added to the options object
so that the callback() can reference it via this.checkbox.
*/
const settingsOps = [{
label: "Chat Configuration Options",
hint: F.storage.isTransient()
? "Local store is unavailable. These settings are transient."
: ["Most of these settings are persistent via ",
F.storage.storageImplName(), ": ",
F.storage.storageHelpDescription()].join('')
},{
label: "Editing Options...",
children:[{
label: "Chat-only mode",
hint: "Toggle the page between normal fossil view and chat-only view.",
boolValue: 'chat-only-mode'
},{
label: "Ctrl-enter to Send",
hint: [
"When on, only Ctrl-Enter will send messages and Enter adds ",
"blank lines. When off, both Enter and Ctrl-Enter send. ",
"When the input field has focus and is empty ",
"then Ctrl-Enter toggles this setting."
].join(''),
boolValue: 'edit-ctrl-send'
},{
label: "Compact mode",
hint: [
"Toggle between a space-saving or more spacious writing area. ",
"When the input field has focus, is empty, and preview mode ",
"is NOT active then Shift-Enter toggles this setting."].join(''),
boolValue: 'edit-compact-mode'
},{
label: "Use 'contenteditable' editing mode",
boolValue: 'edit-widget-x',
hint: [
"When enabled, chat input uses a so-called 'contenteditable' ",
"field. Though generally more comfortable and modern than ",
"plain-text input fields, browser-specific quirks and bugs ",
"may lead to frustration. Ideal for mobile devices."
].join('')
}]
},{
label: "Appearance Options...",
children:[{
label: "Left-align my posts",
hint: "Default alignment of your own messages is selected "
+ "based window width/height ratio.",
boolValue: ()=>!document.body.classList.contains('my-messages-right'),
callback: function f(){
document.body.classList[
this.checkbox.checked ? 'remove' : 'add'
]('my-messages-right');
}
},{
label: "Monospace message font",
hint: "Use monospace font for message and input text.",
boolValue: 'monospace-messages',
callback: function(setting){
document.body.classList[
setting.value ? 'add' : 'remove'
]('monospace-messages');
}
},{
label: "Show images inline",
hint: "When enabled, attached images are shown inline, "+
"else they appear as a download link.",
boolValue: 'images-inline'
}]
}];
/** Set up selection list of notification sounds. */
if(1){
const selectSound = D.select();
D.option(selectSound, "", "(no audio)");
const firstSoundIndex = selectSound.options.length;
|
| ︙ | ︙ | |||
1463 1464 1465 1466 1467 1468 1469 |
/* Missing file - removed after this setting was
applied. Fall back to the first sound in the list. */
selectSound.selectedIndex = firstSoundIndex;
}
}
Chat.setNewMessageSound(selectSound.value);
settingsOps.push({
| > | > > | | | | | | | | < < | | | | | > > > > > > > > > > > > > > > > | | > < | > > | | > > | > | > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > | | > > > | 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 |
/* Missing file - removed after this setting was
applied. Fall back to the first sound in the list. */
selectSound.selectedIndex = firstSoundIndex;
}
}
Chat.setNewMessageSound(selectSound.value);
settingsOps.push({
label: "Sound Options...",
hint: "How to enable audio playback is browser-specific!",
children:[{
hint: "Audio alert",
select: selectSound,
callback: function(ev){
const v = ev.target.value;
Chat.setNewMessageSound(v);
F.toast.message("Audio notifications "+(v ? "enabled" : "disabled")+".");
if(v) setTimeout(()=>Chat.playNewMessageSound(), 0);
}
},{
label: "Play notification for your own messages",
hint: "When enabled, the audio notification will be played for all messages, "+
"including your own. When disabled only messages from other users "+
"will trigger a notification.",
boolValue: 'alert-own-messages'
}]
});
}/*audio notification config*/
settingsOps.push({
label: "Active User List...",
hint: [
"/chat cannot track active connections, but it can tell ",
"you who has posted recently..."].join(''),
children:[
namedOptions.activeUsers,{
label: "Timestamps in active users list",
indent: true,
hint: "Show most recent message timestamps in the active user list.",
boolValue: 'active-user-list-timestamps'
}
]
});
/**
Build UI for config options...
*/
settingsOps.forEach(function f(op,indentOrIndex){
const menuEntry = D.addClass(D.div(), 'menu-entry');
if(true===indentOrIndex) D.addClass(menuEntry, 'child');
const label = op.label
? D.append(D.label(),op.label) : undefined;
const labelWrapper = D.addClass(D.div(), 'label-wrapper');
var hint;
if(op.hint){
hint = D.append(D.addClass(D.label(),'hint'),op.hint);
}
if(op.hasOwnProperty('select')){
const col0 = D.addClass(D.span(/*empty, but for spacing*/),
'toggle-wrapper');
D.append(menuEntry, labelWrapper, col0);
D.append(labelWrapper, op.select);
if(hint) D.append(labelWrapper, hint);
if(label) D.append(label);
if(op.callback){
op.select.addEventListener('change', (ev)=>op.callback(ev), false);
}
}else if(op.hasOwnProperty('boolValue')){
if(undefined === f.$id) f.$id = 0;
++f.$id;
if('string' ===typeof op.boolValue){
const key = op.boolValue;
op.boolValue = ()=>Chat.settings.getBool(key);
op.persistentSetting = key;
}
const check = op.checkbox
= D.attr(D.checkbox(1, op.boolValue()),
'aria-label', op.label);
const id = 'cfgopt'+f.$id;
const col0 = D.addClass(D.span(), 'toggle-wrapper');
check.checked = op.boolValue();
op.checkbox = check;
D.attr(check, 'id', id);
if(hint) D.attr(hint, 'for', id);
D.append(menuEntry, labelWrapper, col0);
D.append(col0, check);
if(label){
D.attr(label, 'for', id);
D.append(labelWrapper, label);
}
if(hint) D.append(labelWrapper, hint);
}else{
if(op.callback){
menuEntry.addEventListener('click', (ev)=>op.callback(ev));
}
D.append(menuEntry, labelWrapper);
if(label) D.append(labelWrapper, label);
if(hint) D.append(labelWrapper, hint);
}
D.append(optionsMenu, menuEntry);
if(op.persistentSetting){
Chat.settings.addListener(
op.persistentSetting,
function(setting){
if(op.checkbox) op.checkbox.checked = !!setting.value;
else if(op.select) op.select.value = setting.value;
if(op.callback) op.callback(setting);
}
);
if(op.checkbox){
op.checkbox.addEventListener(
'change', function(){
Chat.settings.set(op.persistentSetting, op.checkbox.checked)
}, false);
}
}else if(op.callback && op.checkbox){
op.checkbox.addEventListener('change', (ev)=>op.callback(ev), false);
}
if(op.children){
D.addClass(menuEntry, 'parent');
op.children.forEach((x)=>f(x,true));
}
});
})()/*#chat-button-settings setup*/;
(function(){
/* Install default settings... must come after
chat-button-settings setup so that the listeners which that
installs are notified via the properties getting initialized
here. */
Chat.settings.addListener('monospace-messages',function(s){
document.body.classList[s.value ? 'add' : 'remove']('monospace-messages');
})
Chat.settings.addListener('active-user-list',function(s){
Chat.showActiveUserList(s.value);
});
Chat.settings.addListener('active-user-list-timestamps',function(s){
Chat.showActiveUserTimestamps(s.value);
});
Chat.settings.addListener('chat-only-mode',function(s){
Chat.chatOnlyMode(s.value);
});
Chat.settings.addListener('edit-widget-x',function(s){
let eSelected;
if(s.value){
if(Chat.e.inputX===Chat.inputElement()) return;
eSelected = Chat.e.inputX;
}else{
eSelected = Chat.settings.getBool('edit-compact-mode')
? Chat.e.input1 : Chat.e.inputM;
}
const v = Chat.inputValue();
Chat.inputValue('');
Chat.e.inputFields.forEach(function(e,ndx){
if(eSelected===e){
Chat.e.inputFields.$currentIndex = ndx;
D.removeClass(e, 'hidden');
}
else D.addClass(e,'hidden');
});
Chat.inputValue(v);
eSelected.focus();
});
Chat.settings.addListener('edit-compact-mode',function(s){
if(Chat.e.inputX!==Chat.inputElement()){
/* Text field/textarea mode: swap them if needed.
Compact mode of inputX is toggled via CSS. */
const a = s.value
? [Chat.e.input1, Chat.e.inputM, 0]
: [Chat.e.inputM, Chat.e.input1, 1];
const v = Chat.inputValue();
Chat.inputValue('');
Chat.e.inputFields.$currentIndex = a[2];
Chat.inputValue(v);
D.removeClass(a[0], 'hidden');
D.addClass(a[1], 'hidden');
}
Chat.e.inputElementWrapper.classList[
s.value ? 'add' : 'remove'
]('compact');
Chat.e.inputFields[Chat.e.inputFields.$currentIndex].focus();
});
Chat.settings.addListener('edit-ctrl-send',function(s){
const label = (s.value ? "Ctrl-" : "")+"Enter submits messages.";
Chat.e.inputFields.forEach((e)=>{
const v = e.dataset.placeholder0 + " " +label;
if(e.isContentEditable) e.dataset.placeholder = v;
else D.attr(e,'placeholder',v);
});
Chat.e.btnSubmit.title = label;
});
const valueKludges = {
/* Convert certain string-format values to other types... */
"false": false,
"true": true
};
|
| ︙ | ︙ | |||
1605 1606 1607 1608 1609 1610 1611 |
this.e.previewContent.innerHTML = t;
this.e.viewPreview.querySelectorAll('a').forEach(addAnchorTargetBlank);
this.inputFocus();
};
Chat.e.viewPreview.querySelector('#chat-preview-close').
addEventListener('click', ()=>Chat.setCurrentView(Chat.e.viewMessages), false);
let previewPending = false;
| | | 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 |
this.e.previewContent.innerHTML = t;
this.e.viewPreview.querySelectorAll('a').forEach(addAnchorTargetBlank);
this.inputFocus();
};
Chat.e.viewPreview.querySelector('#chat-preview-close').
addEventListener('click', ()=>Chat.setCurrentView(Chat.e.viewMessages), false);
let previewPending = false;
const elemsToEnable = [btnPreview, Chat.e.btnSubmit, Chat.e.inputFields];
const submit = function(ev){
ev.preventDefault();
ev.stopPropagation();
if(previewPending) return false;
const txt = Chat.inputValue();
if(!txt){
Chat.setPreviewText('');
|
| ︙ | ︙ |
Changes to src/fossil.page.pikchrshow.js.
| ︙ | ︙ | |||
501 502 503 504 505 506 507 | box "box" box rad 10px "box (with" "rounded" "corners)" at 1in right of previous circle "circle" at 1in right of previous ellipse "ellipse" at 1in right of previous # second row of objects OVAL1: oval "oval" at 1in below first box | | | 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 |
box "box"
box rad 10px "box (with" "rounded" "corners)" at 1in right of previous
circle "circle" at 1in right of previous
ellipse "ellipse" at 1in right of previous
# second row of objects
OVAL1: oval "oval" at 1in below first box
oval "(tall &" "thin)" "oval" width OVAL1.height height OVAL1.width \
at 1in right of previous
cylinder "cylinder" at 1in right of previous
file "file" at 1in right of previous
# third row shows line-type objects
dot "dot" above at 1in below first oval
line right from 1.8cm right of previous "lines" above
|
| ︙ | ︙ | |||
588 589 590 591 592 593 594 |
# content for the Charlie lane
C1: circle same as A1 at B1-(0,$laneh) "1"
arrow 50%
circle same "2"
arrow right 0.8in "goes" "offline"
C5: circle same as A3 "5"
arrow right until even with first ellipse.w \
| | | 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 |
# content for the Charlie lane
C1: circle same as A1 at B1-(0,$laneh) "1"
arrow 50%
circle same "2"
arrow right 0.8in "goes" "offline"
C5: circle same as A3 "5"
arrow right until even with first ellipse.w \
"back online" above "pushes 5" below "pulls 3 & 4" below
ellipse same "future"
# content for the Darlene lane
D1: circle same as A1 at C1-(0,$laneh) "1"
arrow 50%
circle same "2"
arrow right until even with C5.w
|
| ︙ | ︙ |
Changes to src/gzip.c.
| ︙ | ︙ | |||
19 20 21 22 23 24 25 | ** file. The GZIP format is described in RFC-1952. ** ** State information is stored in static variables, so this implementation ** can only be building up a single GZIP file at a time. */ #include "config.h" #include <assert.h> | < < < < | < | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
** file. The GZIP format is described in RFC-1952.
**
** State information is stored in static variables, so this implementation
** can only be building up a single GZIP file at a time.
*/
#include "config.h"
#include <assert.h>
#include <zlib.h>
#include "gzip.h"
/*
** State information for the GZIP file under construction.
*/
struct gzip_state {
int eState; /* 0: idle 1: header 2: compressing */
|
| ︙ | ︙ |
Changes to src/hook.c.
| ︙ | ︙ | |||
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 |
db_unprotect(PROTECT_CONFIG);
db_multi_exec(
"INSERT OR IGNORE INTO config(name,value) VALUES('hooks','[]');\n"
);
for(i=3; i<g.argc; i++){
const char *zId = g.argv[i];
if( strcmp(zId,"all")==0 ){
db_set("hooks","[]", 0);
break;
}
if( sqlite3_strglob("*[^0-9]*", g.argv[i])==0 ){
fossil_fatal("not a valid ID: \"%s\"", g.argv[i]);
}
db_multi_exec(
"UPDATE config"
| > > | 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
db_unprotect(PROTECT_CONFIG);
db_multi_exec(
"INSERT OR IGNORE INTO config(name,value) VALUES('hooks','[]');\n"
);
for(i=3; i<g.argc; i++){
const char *zId = g.argv[i];
if( strcmp(zId,"all")==0 ){
db_unprotect(PROTECT_ALL);
db_set("hooks","[]", 0);
db_protect_pop();
break;
}
if( sqlite3_strglob("*[^0-9]*", g.argv[i])==0 ){
fossil_fatal("not a valid ID: \"%s\"", g.argv[i]);
}
db_multi_exec(
"UPDATE config"
|
| ︙ | ︙ | |||
351 352 353 354 355 356 357 |
}else
if( strncmp(zCmd, "list", nCmd)==0 ){
Stmt q;
int n = 0;
verify_all_options();
db_prepare(&q,
"SELECT jx.key,"
| | | | | 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 |
}else
if( strncmp(zCmd, "list", nCmd)==0 ){
Stmt q;
int n = 0;
verify_all_options();
db_prepare(&q,
"SELECT jx.key,"
" jx.value->>'seq',"
" jx.value->>'cmd',"
" jx.value->>'type'"
" FROM config, json_each(config.value) AS jx"
" WHERE config.name='hooks' AND json_valid(config.value)"
);
while( db_step(&q)==SQLITE_ROW ){
if( n++ ) fossil_print("\n");
fossil_print("%3d: type = %s\n",
db_column_int(&q,0), db_column_text(&q,3));
|
| ︙ | ︙ | |||
391 392 393 394 395 396 397 |
verify_all_options();
if( g.argc<4 ) usage("test ID");
id = atoi(g.argv[3]);
if( zOrigRcvid==0 ){
zOrigRcvid = db_text(0, "SELECT max(rcvid)-1 FROM rcvfrom");
}
db_prepare(&q,
| < | | 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 |
verify_all_options();
if( g.argc<4 ) usage("test ID");
id = atoi(g.argv[3]);
if( zOrigRcvid==0 ){
zOrigRcvid = db_text(0, "SELECT max(rcvid)-1 FROM rcvfrom");
}
db_prepare(&q,
"SELECT value->>'$[%d].cmd', value->>'$[%d].type'=='after-receive'"
" FROM config"
" WHERE name='hooks' AND json_valid(value)",
id, id
);
while( db_step(&q)==SQLITE_ROW ){
const char *zCmd = db_column_text(&q,0);
char *zCmd2 = hook_subst(zCmd, zAuxFilename);
|
| ︙ | ︙ | |||
458 459 460 461 462 463 464 |
zLastRcvid = db_get("hook-last-rcvid","0");
zNewRcvid = db_text("0","SELECT max(rcvid) FROM rcvfrom");
if( atoi(zLastRcvid)>=atoi(zNewRcvid) ){
goto hook_backoffice_done; /* no new content */
}
blob_init(&chng, 0, 0);
db_prepare(&q,
| | | | | 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 |
zLastRcvid = db_get("hook-last-rcvid","0");
zNewRcvid = db_text("0","SELECT max(rcvid) FROM rcvfrom");
if( atoi(zLastRcvid)>=atoi(zNewRcvid) ){
goto hook_backoffice_done; /* no new content */
}
blob_init(&chng, 0, 0);
db_prepare(&q,
"SELECT jx.value->>'cmd'"
" FROM config, json_each(config.value) AS jx"
" WHERE config.name='hooks' AND json_valid(config.value)"
" AND jx.value->>'type'='after-receive'"
" ORDER BY jx.value->>'seq';"
);
while( db_step(&q)==SQLITE_ROW ){
char *zCmd;
int fdFromChild;
FILE *toChild;
int childPid;
if( cnt==0 ){
|
| ︙ | ︙ | |||
498 499 500 501 502 503 504 |
** Return true if one or more hooks of type zType exit.
*/
int hook_exists(const char *zType){
return db_exists(
"SELECT 1"
" FROM config, json_each(config.value) AS jx"
" WHERE config.name='hooks' AND json_valid(config.value)"
| | < | | | | 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 |
** Return true if one or more hooks of type zType exit.
*/
int hook_exists(const char *zType){
return db_exists(
"SELECT 1"
" FROM config, json_each(config.value) AS jx"
" WHERE config.name='hooks' AND json_valid(config.value)"
" AND jx.value->>'type'=%Q;",
zType
);
}
/*
** Run all hooks of type zType. Use zAuxFile as the auxiliary information
** file.
**
** If any hook returns non-zero, then stop running and return non-zero.
** Return zero only if all hooks return zero.
*/
int hook_run(const char *zType, const char *zAuxFile, int traceFlag){
Stmt q;
int rc = 0;
if( !db_exists("SELECT 1 FROM config WHERE name='hooks'") ){
return 0;
}
db_prepare(&q,
"SELECT jx.value->>'cmd' "
" FROM config, json_each(config.value) AS jx"
" WHERE config.name='hooks' AND json_valid(config.value)"
" AND jx.value->>'type'==%Q"
" ORDER BY jx.value->'seq';",
zType
);
while( db_step(&q)==SQLITE_ROW ){
char *zCmd;
zCmd = hook_subst(db_column_text(&q,0), zAuxFile);
if( traceFlag ){
fossil_print("%s hook: %s\n", zType, zCmd);
|
| ︙ | ︙ |
Changes to src/http.c.
| ︙ | ︙ | |||
203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
blob_reset(&x);
}
if( save_httpauth_prompt() ){
set_httpauth(zHttpAuth);
}
return zHttpAuth;
}
/*
** Sign the content in pSend, compress it, and send it to the server
** via HTTP or HTTPS. Get a reply, uncompress the reply, and store the reply
** in pRecv. pRecv is assumed to be uninitialized when
** this routine is called - this routine will initialize it.
**
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
blob_reset(&x);
}
if( save_httpauth_prompt() ){
set_httpauth(zHttpAuth);
}
return zHttpAuth;
}
/*
** Send content pSend to the the server identified by g.url using the
** external program given by g.zHttpCmd. Capture the reply from that
** program and load it into pReply.
**
** This routine implements the --transport-command option for "fossil sync".
*/
static int http_exchange_external(
Blob *pSend, /* Message to be sent */
Blob *pReply, /* Write the reply here */
int mHttpFlags, /* Flags. See above */
const char *zAltMimetype /* Alternative mimetype if not NULL */
){
char *zUplink;
char *zDownlink;
char *zCmd;
char *zFullUrl;
int rc;
zUplink = fossil_temp_filename();
zDownlink = fossil_temp_filename();
zFullUrl = url_full(&g.url);
zCmd = mprintf("%s %$ %$ %$", g.zHttpCmd, zFullUrl,zUplink,zDownlink);
fossil_free(zFullUrl);
blob_write_to_file(pSend, zUplink);
if( g.fHttpTrace ){
fossil_print("RUN %s\n", zCmd);
}
rc = fossil_system(zCmd);
if( rc ){
fossil_warning("Transport command failed: %s\n", zCmd);
}
fossil_free(zCmd);
file_delete(zUplink);
if( file_size(zDownlink, ExtFILE)<0 ){
blob_zero(pReply);
}else{
blob_read_from_file(pReply, zDownlink, ExtFILE);
file_delete(zDownlink);
}
return rc;
}
/*
** Sign the content in pSend, compress it, and send it to the server
** via HTTP or HTTPS. Get a reply, uncompress the reply, and store the reply
** in pRecv. pRecv is assumed to be uninitialized when
** this routine is called - this routine will initialize it.
**
|
| ︙ | ︙ | |||
233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
int iRecvLen; /* Received length of the reply payload */
int rc = 0; /* Result code */
int iHttpVersion; /* Which version of HTTP protocol server uses */
char *zLine; /* A single line of the reply header */
int i; /* Loop counter */
int isError = 0; /* True if the reply is an error message */
int isCompressed = 1; /* True if the reply is compressed */
if( transport_open(&g.url) ){
fossil_warning("%s", transport_errmsg(&g.url));
return 1;
}
/* Construct the login card and prepare the complete payload */
| > > > > > | 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
int iRecvLen; /* Received length of the reply payload */
int rc = 0; /* Result code */
int iHttpVersion; /* Which version of HTTP protocol server uses */
char *zLine; /* A single line of the reply header */
int i; /* Loop counter */
int isError = 0; /* True if the reply is an error message */
int isCompressed = 1; /* True if the reply is compressed */
if( g.zHttpCmd!=0 ){
/* Handle the --transport-command option for "fossil sync" and similar */
return http_exchange_external(pSend,pReply,mHttpFlags,zAltMimetype);
}
if( transport_open(&g.url) ){
fossil_warning("%s", transport_errmsg(&g.url));
return 1;
}
/* Construct the login card and prepare the complete payload */
|
| ︙ | ︙ | |||
477 478 479 480 481 482 483 | transport_close(&g.url); return 1; } /* ** COMMAND: test-httpmsg ** | | > > > > > > | > > > > | | | > > > > > > > | | 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 |
transport_close(&g.url);
return 1;
}
/*
** COMMAND: test-httpmsg
**
** Usage: %fossil test-httpmsg ?OPTIONS? URL ?PAYLOAD? ?OUTPUT?
**
** Send an HTTP message to URL and get the reply. PAYLOAD is a file containing
** the payload, or "-" to read payload from standard input. a POST message
** is sent if PAYLOAD is specified and is non-empty. If PAYLOAD is omitted
** or is an empty file, then a GET message is sent.
**
** If a second filename (OUTPUT) is given after PAYLOAD, then the reply
** is written into that second file instead of being written on standard
** output. Use the "--out OUTPUT" option to specify an output file for
** a GET request where there is no PAYLOAD.
**
** Options:
**
** --compress Use ZLIB compression on the payload
** --mimetype TYPE Mimetype of the payload
** --out FILE Store the reply in FILE
** -v Verbose output
** --xfer PAYLOAD in a Fossil xfer protocol message
*/
void test_httpmsg_command(void){
const char *zMimetype;
const char *zInFile;
const char *zOutFile;
Blob in, out;
unsigned int mHttpFlags = HTTP_GENERIC|HTTP_NOCOMPRESS;
zMimetype = find_option("mimetype",0,1);
zOutFile = find_option("out","o",1);
if( find_option("verbose","v",0)!=0 ) mHttpFlags |= HTTP_VERBOSE;
if( find_option("compress",0,0)!=0 ) mHttpFlags &= ~HTTP_NOCOMPRESS;
if( find_option("xfer",0,0)!=0 ){
mHttpFlags |= HTTP_USE_LOGIN;
mHttpFlags &= ~HTTP_GENERIC;
}
verify_all_options();
if( g.argc<3 || g.argc>5 ){
usage("URL ?PAYLOAD? ?OUTPUT?");
}
zInFile = g.argc>=4 ? g.argv[3] : 0;
if( g.argc==5 ){
if( zOutFile ){
fossil_fatal("output file specified twice: \"--out %s\" and \"%s\"",
zOutFile, g.argv[4]);
}
zOutFile = g.argv[4];
}
url_parse(g.argv[2], 0);
if( g.url.protocol[0]!='h' ){
fossil_fatal("the %s command supports only http: and https:", g.argv[1]);
}
if( zInFile ){
blob_read_from_file(&in, zInFile, ExtFILE);
if( zMimetype==0 && (mHttpFlags & HTTP_GENERIC)!=0 ){
if( fossil_strcmp(zInFile,"-")==0 ){
zMimetype = "application/x-unknown";
}else{
zMimetype = mimetype_from_name(zInFile);
}
}
}else{
|
| ︙ | ︙ |
Changes to src/http_socket.c.
| ︙ | ︙ | |||
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
** if overridden in ~/.ssh/config) the rcvfrom may not match the host
** to which we connect.
*/
void socket_ssh_resolve_addr(UrlData *pUrlData){
struct addrinfo *ai = 0;
struct addrinfo hints;
char zRemote[NI_MAXHOST];
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
if( getaddrinfo(pUrlData->name, NULL, &hints, &ai)==0
&& ai!=0
&& getnameinfo(ai->ai_addr, ai->ai_addrlen, zRemote,
sizeof(zRemote), 0, 0, NI_NUMERICHOST)==0 ){
g.zIpAddr = mprintf("%s (%s)", zRemote, pUrlData->name);
}
if( ai ) freeaddrinfo(ai);
| > > > | 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
** if overridden in ~/.ssh/config) the rcvfrom may not match the host
** to which we connect.
*/
void socket_ssh_resolve_addr(UrlData *pUrlData){
struct addrinfo *ai = 0;
struct addrinfo hints;
char zRemote[NI_MAXHOST];
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
fossil_free(g.zIpAddr);
g.zIpAddr = 0;
if( getaddrinfo(pUrlData->name, NULL, &hints, &ai)==0
&& ai!=0
&& getnameinfo(ai->ai_addr, ai->ai_addrlen, zRemote,
sizeof(zRemote), 0, 0, NI_NUMERICHOST)==0 ){
g.zIpAddr = mprintf("%s (%s)", zRemote, pUrlData->name);
}
if( ai ) freeaddrinfo(ai);
|
| ︙ | ︙ |
Changes to src/http_ssl.c.
| ︙ | ︙ | |||
14 15 16 17 18 19 20 | ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This file manages low-level SSL communications. ** ** This file implements a singleton. A single SSL connection may be active | | > > > | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This file manages low-level SSL communications. ** ** This file implements a singleton. A single SSL connection may be active ** at a time. State information is stored in static variables. ** ** The SSL connections can be either a client or a server. But all ** connections for a single process must be of the same type, either client ** or server. ** ** SSL support is abstracted out into this module because Fossil can ** be compiled without SSL support (which requires OpenSSL library) */ #include "config.h" #include "http_ssl.h" |
| ︙ | ︙ | |||
39 40 41 42 43 44 45 | #include <sys/types.h> /* ** There can only be a single OpenSSL IO connection open at a time. ** State information about that IO is stored in the following ** local variables: */ | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
#include <sys/types.h>
/*
** There can only be a single OpenSSL IO connection open at a time.
** State information about that IO is stored in the following
** local variables:
*/
static int sslIsInit = 0; /* 0: uninit 1: init as client 2: init as server */
static BIO *iBio = 0; /* OpenSSL I/O abstraction */
static char *sslErrMsg = 0; /* Text of most recent OpenSSL error */
static SSL_CTX *sslCtx; /* SSL context */
static SSL *ssl;
static struct { /* Accept this SSL cert for this session only */
char *zHost; /* Subject or host name */
char *zHash; /* SHA2-256 hash of the cert */
} sException;
static int sslNoCertVerify = 0; /* Do not verify SSL certs */
/* This is a self-signed cert in the PEM format that can be used when
** no other certs are available.
*/
static const char sslSelfCert[] =
"-----BEGIN CERTIFICATE-----\n"
"MIIDMTCCAhkCFGrDmuJkkzWERP/ITBvzwwI2lv0TMA0GCSqGSIb3DQEBCwUAMFQx\n"
"CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJOQzESMBAGA1UEBwwJQ2hhcmxvdHRlMRMw\n"
"EQYDVQQKDApGb3NzaWwtU0NNMQ8wDQYDVQQDDAZGb3NzaWwwIBcNMjExMjI3MTEz\n"
"MTU2WhgPMjEyMTEyMjcxMTMxNTZaMFQxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJO\n"
"QzESMBAGA1UEBwwJQ2hhcmxvdHRlMRMwEQYDVQQKDApGb3NzaWwtU0NNMQ8wDQYD\n"
"VQQDDAZGb3NzaWwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCCbTU2\n"
"6GRQHQqLq7vyZ0OxpAxmgfAKCxt6eIz+jBi2ZM/CB5vVXWVh2+SkSiWEA3UZiUqX\n"
"xZlzmS/CglZdiwLLDJML8B4OiV72oivFH/vJ7+cbvh1dTxnYiHuww7GfQngPrLfe\n"
"fiIYPDk1GTUJHBQ7Ue477F7F8vKuHdVgwktF/JDM6M60aSqlo2D/oysirrb+dlur\n"
"Tlv0rjsYOfq6bLAajoL3qi/vek6DNssoywbge4PfbTgS9g7Gcgncbcet5pvaS12J\n"
"avhFcd4JU4Ity49Hl9S/C2MfZ1tE53xVggRwKz4FPj65M5uymTdcxtjKXtCxIE1k\n"
"KxJxXQh7rIYjm+RTAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAFkdtpqcybAzJN8G\n"
"+ONuUm5sXNbWta7JGvm8l0BTSBcCUtJA3hn16iJqXA9KmLnaF2denC4EYk+KlVU1\n"
"QXxskPJ4jB8A5B05jMijYv0nzCxKhviI8CR7GLEEGKzeg9pbW0+O3vaVehoZtdFX\n"
"z3SsCssr9QjCLiApQxMzW1Iv3od2JXeHBwfVMFrWA1VCEUCRs8OSW/VOqDPJLVEi\n"
"G6wxc4kN9dLK+5S29q3nzl24/qzXoF8P9Re5KBCbrwaHgy+OEEceq5jkmfGFxXjw\n"
"pvVCNry5uAhH5NqbXZampUWqiWtM4eTaIPo7Y2mDA1uWhuWtO6F9PsnFJlQHCnwy\n"
"s/TsrXk=\n"
"-----END CERTIFICATE-----\n";
/* This is the private-key corresponding to the cert above
*/
static const char sslSelfPKey[] =
"-----BEGIN PRIVATE KEY-----\n"
"MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCCbTU26GRQHQqL\n"
"q7vyZ0OxpAxmgfAKCxt6eIz+jBi2ZM/CB5vVXWVh2+SkSiWEA3UZiUqXxZlzmS/C\n"
"glZdiwLLDJML8B4OiV72oivFH/vJ7+cbvh1dTxnYiHuww7GfQngPrLfefiIYPDk1\n"
"GTUJHBQ7Ue477F7F8vKuHdVgwktF/JDM6M60aSqlo2D/oysirrb+dlurTlv0rjsY\n"
"Ofq6bLAajoL3qi/vek6DNssoywbge4PfbTgS9g7Gcgncbcet5pvaS12JavhFcd4J\n"
"U4Ity49Hl9S/C2MfZ1tE53xVggRwKz4FPj65M5uymTdcxtjKXtCxIE1kKxJxXQh7\n"
"rIYjm+RTAgMBAAECggEANfTH1vc8yIe7HRzmm9lsf8jF+II4s2705y2H5qY+cvYx\n"
"nKtZJGOG1X0KkYy7CGoFv5K0cSUl3lS5FVamM/yWIzoIex/Sz2C1EIL2aI5as6ez\n"
"jB6SN0/J+XI8+Vt7186/rHxfdIPpxuzjHbxX3HTpScETNWcLrghbrPxakbTPPxwt\n"
"+x7QlPmmkFNuMfvkzToFf9NdwL++44TeBPOpvD/Lrw+eyqdth9RJPq9cM96plh9V\n"
"HuRqeD8+QNafaXBdSQs3FJK/cDK/vWGKZWIfFVSDbDhwYljkXGijreFjtXQfkkpF\n"
"rl1J87/H9Ee7z8fTD2YXQHl+0/rghAVtac3u54dpQQKBgQC2XG3OEeMrOp9dNkUd\n"
"F8VffUg0ecwG+9L3LCe7U71K0kPmXjV6xNnuYcNQu84kptc5vI8wD23p29LaxdNc\n"
"9m0lcw06/YYBOPkNphcHkINYZTvVJF10mL3isymzMaTtwDkZUkOjL1B+MTiFT/qp\n"
"ARKrTYGJ4HxY7+tUkI5pUmg4PQKBgQC3GA4d1Rz3Pb/RRpcsZgWknKsKhoN36mSn\n"
"xFJ3wPBvVv2B1ltTMzh/+the0ty6clzMrvoLERzRcheDsNrc/j/TUVG8sVdBYJwX\n"
"tMZyFW4NVMOErT/1ukh6jBqIMBo6NJL3EV/AKj0yniksgKOr0/AAduAccnGST8Jd\n"
"SHOdjwvHzwKBgGZBq/zqgNTDuYseHGE07CMgcDWkumiMGv8ozlq3mSR0hUiPOTPP\n"
"YFjQjyIdPXnF6FfiyPPtIvgIoNK2LVAqiod+XUPf152l4dnqcW13dn9BvOxGyPTR\n"
"lWCikFaAFviOWjY9r9m4dU1dslDmySqthFd0TZgPvgps9ivkJ0cdw30NAoGAMC/E\n"
"h1VvKiK2OP27C5ROJ+STn1GHiCfIFd81VQ8SODtMvL8NifgRBp2eFFaqgOdYRQZI\n"
"CGGYlAbS6XXCJCdF5Peh62dA75PdgN+y2pOJQzjrvB9cle9Q4++7i9wdCvSLOTr5\n"
"WDnFoWy+qVexu6crovOmR9ZWzYrwPFy1EOJ010ECgYBl7Q+jmjOSqsVwhFZ0U7LG\n"
"diN+vXhWfn1wfOWd8u79oaqU/Oy7xyKW2p3H5z2KFrBM/vib53Lh4EwFZjcX+jVG\n"
"krAmbL+M/hP7z3TD2UbESAzR/c6l7FU45xN84Lsz5npkR8H/uAHuqLgb9e430Mjx\n"
"YNMwdb8rChHHChNZu6zuxw==\n"
"-----END PRIVATE KEY-----\n";
/*
** Read a PEM certificate from memory and push it into an SSL_CTX.
** Return the number of errors.
*/
static int sslctx_use_cert_from_mem(
SSL_CTX *ctx,
const char *pData,
int nData
){
BIO *in;
int rc = 1;
X509 *x = 0;
X509 *cert = 0;
in = BIO_new_mem_buf(pData, nData);
if( in==0 ) goto end_of_ucfm;
// x = X509_new_ex(ctx->libctx, ctx->propq);
x = X509_new();
if( x==0 ) goto end_of_ucfm;
cert = PEM_read_bio_X509(in, &x, 0, 0);
if( cert==0 ) goto end_of_ucfm;
rc = SSL_CTX_use_certificate(ctx, x)<=0;
end_of_ucfm:
X509_free(x);
BIO_free(in);
return rc;
}
/*
** Read a PEM private key from memory and add it to an SSL_CTX.
** Return the number of errors.
*/
static int sslctx_use_pkey_from_mem(
SSL_CTX *ctx,
const char *pData,
int nData
){
int rc = 1;
BIO *in;
EVP_PKEY *pkey = 0;
in = BIO_new_mem_buf(pData, nData);
if( in==0 ) goto end_of_upkfm;
pkey = PEM_read_bio_PrivateKey(in, 0, 0, 0);
if( pkey==0 ) goto end_of_upkfm;
rc = SSL_CTX_use_PrivateKey(ctx, pkey)<=0;
EVP_PKEY_free(pkey);
end_of_upkfm:
BIO_free(in);
return rc;
}
/*
** Clear the SSL error message
*/
static void ssl_clear_errmsg(void){
free(sslErrMsg);
sslErrMsg = 0;
}
|
| ︙ | ︙ | |||
87 88 89 90 91 92 93 94 95 96 97 98 |
static int ssl_client_cert_callback(SSL *ssl, X509 **x509, EVP_PKEY **pkey){
fossil_warning("The remote server requested a client certificate for "
"authentication. Specify the pathname to a file containing the PEM "
"encoded certificate and private key with the --ssl-identity option "
"or the ssl-identity setting.");
return 0; /* no cert available */
}
/*
** Call this routine once before any other use of the SSL interface.
** This routine does initial configuration of the SSL module.
*/
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < > > > > > < > | > > > > > > > > > > | < < > > | > | < > > > > | < | > | | > > > > | | < < | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 |
static int ssl_client_cert_callback(SSL *ssl, X509 **x509, EVP_PKEY **pkey){
fossil_warning("The remote server requested a client certificate for "
"authentication. Specify the pathname to a file containing the PEM "
"encoded certificate and private key with the --ssl-identity option "
"or the ssl-identity setting.");
return 0; /* no cert available */
}
/*
** Convert an OpenSSL ASN1_TIME to an ISO8601 timestamp.
**
** Per RFC 5280, ASN1 timestamps in X.509 certificates must
** be in UTC (Zulu timezone) with no fractional seconds.
**
** If showUtc==1, add " UTC" at the end of the returned string. This is
** not ISO8601-compliant, but makes the displayed value more user-friendly.
*/
static const char *ssl_asn1time_to_iso8601(ASN1_TIME *asn1_time,
int showUtc){
assert( showUtc==0 || showUtc==1 );
if( !ASN1_TIME_check(asn1_time) ){
return mprintf("Bad time value");
}else{
char res[20];
char *pr = res;
const char *pt = (char *)asn1_time->data;
/* 0123456789 1234
** UTCTime: YYMMDDHHMMSSZ (YY >= 50 ? 19YY : 20YY)
** GeneralizedTime: YYYYMMDDHHMMSSZ */
if( asn1_time->length < 15 ){
/* UTCTime, fill out century digits */
*pr++ = pt[0]>='5' ? '1' : '2';
*pr++ = pt[0]>='5' ? '9' : '0';
}else{
/* GeneralizedTime, copy century digits and advance source */
*pr++ = pt[0]; *pr++ = pt[1];
pt += 2;
}
*pr++ = pt[0]; *pr++ = pt[1]; *pr++ = '-';
*pr++ = pt[2]; *pr++ = pt[3]; *pr++ = '-';
*pr++ = pt[4]; *pr++ = pt[5]; *pr++ = ' ';
*pr++ = pt[6]; *pr++ = pt[7]; *pr++ = ':';
*pr++ = pt[8]; *pr++ = pt[9]; *pr++ = ':';
*pr++ = pt[10]; *pr++ = pt[11]; *pr = '\0';
return mprintf("%s%s", res, (showUtc ? " UTC" : ""));
}
}
/*
** Call this routine once before any other use of the SSL interface.
** This routine does initial configuration of the SSL module.
*/
static void ssl_global_init_client(void){
const char *identityFile;
if( sslIsInit==0 ){
const char *zFile;
const char *zCaFile = 0;
const char *zCaDirectory = 0;
int i;
SSL_library_init();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
sslCtx = SSL_CTX_new(SSLv23_client_method());
/* Disable SSLv2 and SSLv3 */
SSL_CTX_set_options(sslCtx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3);
/* Find the trust store */
zFile = 0;
for(i=0; zFile==0 && i<5; i++){
switch( i ){
case 0: /* First priority is environmentn variables */
zFile = fossil_getenv(X509_get_default_cert_file_env());
break;
case 1:
zFile = fossil_getenv(X509_get_default_cert_dir_env());
break;
case 2:
if( !g.repositoryOpen ) db_open_config(0,0);
zFile = db_get("ssl-ca-location",0);
break;
case 3:
zFile = X509_get_default_cert_file();
break;
case 4:
zFile = X509_get_default_cert_dir();
break;
}
if( zFile==0 ) continue;
switch( file_isdir(zFile, ExtFILE) ){
case 0: { /* doesn't exist */
zFile = 0;
break;
}
case 1: { /* directory */
zCaFile = 0;
zCaDirectory = zFile;
break;
}
case 2: { /* file */
zCaFile = zFile;
zCaDirectory = 0;
break;
}
}
}
if( zFile==0 ){
/* fossil_fatal("Cannot find a trust store"); */
}else if( SSL_CTX_load_verify_locations(sslCtx, zCaFile, zCaDirectory)==0 ){
fossil_fatal("Cannot load CA root certificates from %s", zFile);
}
/* Load client SSL identity, preferring the filename specified on the
** command line */
if( g.zSSLIdentity!=0 ){
identityFile = g.zSSLIdentity;
}else{
|
| ︙ | ︙ | |||
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
}
}
/* Register a callback to tell the user what to do when the server asks
** for a cert */
SSL_CTX_set_client_cert_cb(sslCtx, ssl_client_cert_callback);
sslIsInit = 1;
}
}
/*
** Call this routine to shutdown the SSL module prior to program exit.
*/
void ssl_global_shutdown(void){
if( sslIsInit ){
SSL_CTX_free(sslCtx);
ssl_clear_errmsg();
sslIsInit = 0;
}
}
/*
| > > | | | 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 |
}
}
/* Register a callback to tell the user what to do when the server asks
** for a cert */
SSL_CTX_set_client_cert_cb(sslCtx, ssl_client_cert_callback);
sslIsInit = 1;
}else{
assert( sslIsInit==1 );
}
}
/*
** Call this routine to shutdown the SSL module prior to program exit.
*/
void ssl_global_shutdown(void){
if( sslIsInit ){
SSL_CTX_free(sslCtx);
ssl_clear_errmsg();
sslIsInit = 0;
}
}
/*
** Close the currently open client SSL connection. If no connection is open,
** this routine is a no-op.
*/
void ssl_close_client(void){
if( iBio!=NULL ){
(void)BIO_reset(iBio);
BIO_free_all(iBio);
iBio = NULL;
}
}
|
| ︙ | ︙ | |||
239 240 241 242 243 244 245 |
** real server or a man-in-the-middle imposter.
*/
void ssl_disable_cert_verification(void){
sslNoCertVerify = 1;
}
/*
| > > > | < | | | | 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 |
** real server or a man-in-the-middle imposter.
*/
void ssl_disable_cert_verification(void){
sslNoCertVerify = 1;
}
/*
** Open an SSL connection as a client that is to connect to the server
** identified by pUrlData.
**
* The identify of the server is determined as follows:
**
** pUrlData->name Name of the server. Ex: fossil-scm.org
** g.url.name Name of the proxy server, if proxying.
** pUrlData->port TCP/IP port to use. Ex: 80
**
** Return the number of errors.
*/
int ssl_open_client(UrlData *pUrlData){
X509 *cert;
const char *zRemoteHost;
ssl_global_init_client();
if( pUrlData->useProxy ){
int rc;
char *connStr = mprintf("%s:%d", g.url.name, pUrlData->port);
BIO *sBio = BIO_new_connect(connStr);
free(connStr);
if( BIO_do_connect(sBio)<=0 ){
ssl_set_errmsg("SSL: cannot connect to proxy %s:%d (%s)",
pUrlData->name, pUrlData->port,
ERR_reason_error_string(ERR_get_error()));
ssl_close_client();
return 1;
}
rc = establish_proxy_tunnel(pUrlData, sBio);
if( rc<200||rc>299 ){
ssl_set_errmsg("SSL: proxy connect failed with HTTP status code %d", rc);
return 1;
}
|
| ︙ | ︙ | |||
314 315 316 317 318 319 320 |
char *connStr = mprintf("%s:%d", pUrlData->name, pUrlData->port);
BIO_set_conn_hostname(iBio, connStr);
free(connStr);
if( BIO_do_connect(iBio)<=0 ){
ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)",
pUrlData->name, pUrlData->port,
ERR_reason_error_string(ERR_get_error()));
| | | | > > > > > > > | 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 |
char *connStr = mprintf("%s:%d", pUrlData->name, pUrlData->port);
BIO_set_conn_hostname(iBio, connStr);
free(connStr);
if( BIO_do_connect(iBio)<=0 ){
ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)",
pUrlData->name, pUrlData->port,
ERR_reason_error_string(ERR_get_error()));
ssl_close_client();
return 1;
}
}
if( BIO_do_handshake(iBio)<=0 ) {
ssl_set_errmsg("Error establishing SSL connection %s:%d (%s)",
pUrlData->useProxy?pUrlData->hostname:pUrlData->name,
pUrlData->useProxy?pUrlData->proxyOrigPort:pUrlData->port,
ERR_reason_error_string(ERR_get_error()));
ssl_close_client();
return 1;
}
/* Check if certificate is valid */
cert = SSL_get_peer_certificate(ssl);
if ( cert==NULL ){
ssl_set_errmsg("No SSL certificate was presented by the peer");
ssl_close_client();
return 1;
}
/* Debugging hint: On unix-like system, run something like:
**
** SSL_CERT_DIR=/tmp ./fossil sync
**
** to cause certificate validation to fail, and thus test the fallback
** logic.
*/
if( !sslNoCertVerify && SSL_get_verify_result(ssl)!=X509_V_OK ){
int x, desclen;
char *desc, *prompt;
Blob ans;
char cReply;
BIO *mem;
unsigned char md[EVP_MAX_MD_SIZE];
|
| ︙ | ︙ | |||
369 370 371 372 373 374 375 |
if( ssl_certificate_exception_exists(pUrlData, zHash) ){
/* Ignore the failure because an exception exists */
ssl_one_time_exception(pUrlData, zHash);
}else{
/* Tell the user about the failure and ask what to do */
mem = BIO_new(BIO_s_mem());
| | | > > > > | | < | > > | > > | 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 |
if( ssl_certificate_exception_exists(pUrlData, zHash) ){
/* Ignore the failure because an exception exists */
ssl_one_time_exception(pUrlData, zHash);
}else{
/* Tell the user about the failure and ask what to do */
mem = BIO_new(BIO_s_mem());
BIO_puts(mem, " subject: ");
X509_NAME_print_ex(mem, X509_get_subject_name(cert), 0, XN_FLAG_ONELINE);
BIO_puts(mem, "\n issuer: ");
X509_NAME_print_ex(mem, X509_get_issuer_name(cert), 0, XN_FLAG_ONELINE);
BIO_printf(mem, "\n notBefore: %s",
ssl_asn1time_to_iso8601(X509_get_notBefore(cert), 1));
BIO_printf(mem, "\n notAfter: %s",
ssl_asn1time_to_iso8601(X509_get_notAfter(cert), 1));
BIO_printf(mem, "\n sha256: %s", zHash);
desclen = BIO_get_mem_data(mem, &desc);
prompt = mprintf("Unable to verify SSL cert from %s\n%.*s\n"
"accept this cert and continue (y/N/fingerprint)? ",
pUrlData->name, desclen, desc);
BIO_free(mem);
prompt_user(prompt, &ans);
free(prompt);
cReply = blob_str(&ans)[0];
if( cReply!='y' && cReply!='Y'
&& fossil_stricmp(blob_str(&ans),zHash)!=0
){
X509_free(cert);
ssl_set_errmsg("SSL cert declined");
ssl_close_client();
blob_reset(&ans);
return 1;
}
blob_reset(&ans);
ssl_one_time_exception(pUrlData, zHash);
prompt_user("remember this exception (y/N)? ", &ans);
cReply = blob_str(&ans)[0];
if( cReply=='y' || cReply=='Y') {
db_open_config(0,0);
ssl_remember_certificate_exception(pUrlData, zHash);
}
|
| ︙ | ︙ | |||
473 474 475 476 477 478 479 | fossil_free(sException.zHost); sException.zHost = fossil_strdup(pUrlData->name); fossil_free(sException.zHash); sException.zHash = fossil_strdup(zHash); } /* | | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > | | | | > > | < < < > > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > | > > > > > | > > | > > > | > > > > > > | | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | > > > | > > > > > > | > > > > > > > > > > < < > > | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > | 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 |
fossil_free(sException.zHost);
sException.zHost = fossil_strdup(pUrlData->name);
fossil_free(sException.zHash);
sException.zHash = fossil_strdup(zHash);
}
/*
** Send content out over the SSL connection from the client to
** the server.
*/
size_t ssl_send(void *NotUsed, void *pContent, size_t N){
size_t total = 0;
while( N>0 ){
int sent = BIO_write(iBio, pContent, N);
if( sent<=0 ){
if( BIO_should_retry(iBio) ){
continue;
}
break;
}
total += sent;
N -= sent;
pContent = (void*)&((char*)pContent)[sent];
}
return total;
}
/*
** Receive content back from the client SSL connection. In other
** words read the reply back from the server.
*/
size_t ssl_receive(void *NotUsed, void *pContent, size_t N){
size_t total = 0;
while( N>0 ){
int got = BIO_read(iBio, pContent, N);
if( got<=0 ){
if( BIO_should_retry(iBio) ){
continue;
}
break;
}
total += got;
N -= got;
pContent = (void*)&((char*)pContent)[got];
}
return total;
}
/*
** Initialize the SSL library so that it is able to handle
** server-side connections. Invoke fossil_fatal() if there are
** any problems.
**
** If zKeyFile and zCertFile are not NULL, then they are the names
** of disk files that hold the certificate and private-key for the
** server. If zCertFile is not NULL but zKeyFile is NULL, then
** zCertFile is assumed to be a concatenation of the certificate and
** the private-key in the PEM format.
**
** If zCertFile is "unsafe-builtin", then a built-in self-signed cert
** is used. This built-in cert is insecure and should only be used for
** testing and debugging.
*/
void ssl_init_server(const char *zCertFile, const char *zKeyFile){
if( sslIsInit==0 && zCertFile ){
SSL_library_init();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
sslCtx = SSL_CTX_new(SSLv23_server_method());
if( sslCtx==0 ){
ERR_print_errors_fp(stderr);
fossil_fatal("Error initializing the SSL server");
}
if( fossil_strcmp(zCertFile,"unsafe-builtin")==0 ){
if( sslctx_use_cert_from_mem(sslCtx, sslSelfCert, -1)
|| sslctx_use_pkey_from_mem(sslCtx, sslSelfPKey, -1)
){
fossil_fatal("Error loading self-signed CERT and KEY");
}
}else{
if( SSL_CTX_use_certificate_chain_file(sslCtx,zCertFile)!=1 ){
ERR_print_errors_fp(stderr);
fossil_fatal("Error loading CERT file \"%s\"", zCertFile);
}
if( zKeyFile==0 ) zKeyFile = zCertFile;
if( SSL_CTX_use_PrivateKey_file(sslCtx, zKeyFile, SSL_FILETYPE_PEM)<=0 ){
ERR_print_errors_fp(stderr);
if( strcmp(zKeyFile,zCertFile)==0 ){
fossil_fatal("The private key is not found in \"%s\". "
"Either append the private key to the certification in that "
"file or use a separate --pkey option to specify the private key.",
zKeyFile);
}else{
fossil_fatal("Error loading the private key from file \"%s\"",
zKeyFile);
}
}
}
if( !SSL_CTX_check_private_key(sslCtx) ){
fossil_fatal("PRIVATE KEY \"%s\" does not match CERT \"%s\"",
zKeyFile, zCertFile);
}
SSL_CTX_set_mode(sslCtx, SSL_MODE_AUTO_RETRY);
sslIsInit = 2;
}else{
assert( sslIsInit==2 );
}
}
typedef struct SslServerConn {
SSL *ssl; /* The SSL codec */
int atEof; /* True when EOF reached. */
int iSocket; /* The socket */
BIO *bio; /* BIO object. Needed for EOF detection. */
} SslServerConn;
/*
** Create a new server-side codec. The argument is the socket's file
** descriptor from which the codec reads and writes. The returned
** memory must eventually be passed to ssl_close_server().
*/
void *ssl_new_server(int iSocket){
SslServerConn *pServer = fossil_malloc_zero(sizeof(*pServer));
BIO *b = BIO_new_socket(iSocket, 0);
pServer->ssl = SSL_new(sslCtx);
pServer->atEof = 0;
pServer->iSocket = iSocket;
pServer->bio = b;
SSL_set_bio(pServer->ssl, b, b);
SSL_accept(pServer->ssl);
return (void*)pServer;
}
/*
** Close a server-side code previously returned from ssl_new_server().
*/
void ssl_close_server(void *pServerArg){
SslServerConn *pServer = (SslServerConn*)pServerArg;
SSL_free(pServer->ssl);
fossil_free(pServer);
}
/*
** Return TRUE if there are no more bytes available to be read from
** the client.
*/
int ssl_eof(void *pServerArg){
SslServerConn *pServer = (SslServerConn*)pServerArg;
return pServer->atEof;
}
/*
** Read cleartext bytes that have been received from the client and
** decrypted by the SSL server codec.
*/
size_t ssl_read_server(void *pServerArg, char *zBuf, size_t nBuf){
int n, err = 0;
size_t rc = 0;
SslServerConn *pServer = (SslServerConn*)pServerArg;
if( nBuf>0x7fffffff ){ fossil_fatal("SSL read too big"); }
while( 0==err && nBuf!=rc && 0==pServer->atEof ){
n = SSL_read(pServer->ssl, zBuf + rc, (int)(nBuf - rc));
if( n==0 ){
pServer->atEof = 1;
break;
}
err = SSL_get_error(pServer->ssl, n);
if(0==err){
rc += n;
pServer->atEof = BIO_eof(pServer->bio);
}else{
fossil_fatal("SSL read error.");
}
}
return rc;
}
/*
** Read a single line of text from the client.
*/
char *ssl_gets(void *pServerArg, char *zBuf, int nBuf){
int n = 0;
int i;
SslServerConn *pServer = (SslServerConn*)pServerArg;
if( pServer->atEof ) return 0;
for(i=0; i<nBuf-1; i++){
n = SSL_read(pServer->ssl, &zBuf[i], 1);
if( n<=0 ){
return 0;
}
if( zBuf[i]=='\n' ) break;
}
zBuf[i+1] = 0;
return zBuf;
}
/*
** Write cleartext bytes into the SSL server codec so that they can
** be encrypted and sent back to the client.
*/
size_t ssl_write_server(void *pServerArg, char *zBuf, size_t nBuf){
int n;
SslServerConn *pServer = (SslServerConn*)pServerArg;
if( nBuf<=0 ) return 0;
if( nBuf>0x7fffffff ){ fossil_fatal("SSL write too big"); }
n = SSL_write(pServer->ssl, zBuf, (int)nBuf);
if( n<=0 ){
return -SSL_get_error(pServer->ssl, n);
}else{
return n;
}
}
#endif /* FOSSIL_ENABLE_SSL */
/*
** zPath is a name that might be a file or directory containing a trust
** store. *pzStore is the name of the trust store to actually use.
**
** If *pzStore is not NULL (meaning no trust store has been found yet)
** and if zPath exists, then set *pzStore to point to zPath.
*/
static void trust_location_usable(const char *zPath, const char **pzStore){
if( *pzStore!=0 ) return;
if( file_isdir(zPath, ExtFILE)>0 ) *pzStore = zPath;
}
/*
** COMMAND: tls-config*
** COMMAND: ssl-config
**
** Usage: %fossil ssl-config [SUBCOMMAND] [OPTIONS...] [ARGS...]
**
** This command is used to view or modify the TLS (Transport Layer
** Security) configuration for Fossil. TLS (formerly SSL) is the
** encryption technology used for secure HTTPS transport.
**
** Sub-commands:
**
** remove-exception DOMAINS Remove TLS cert exceptions for the domains
** listed. Or remove them all if the --all
** option is specified.
**
** scrub ?--force? Remove all SSL configuration data from the
** repository. Use --force to omit the
** confirmation.
**
** show ?-v? Show the TLS configuration. Add -v to see
** additional explaination
*/
void test_tlsconfig_info(void){
const char *zCmd;
size_t nCmd;
int nHit = 0;
db_find_and_open_repository(OPEN_OK_NOT_FOUND|OPEN_SUBSTITUTE,0);
db_open_config(1,0);
if( g.argc==2 || (g.argc>=3 && g.argv[2][0]=='-') ){
zCmd = "show";
nCmd = 4;
}else{
zCmd = g.argv[2];
nCmd = strlen(zCmd);
}
if( strncmp("scrub",zCmd,nCmd)==0 && nCmd>4 ){
int bForce = find_option("force","f",0)!=0;
verify_all_options();
if( !bForce ){
Blob ans;
char cReply;
prompt_user(
"Scrubbing the SSL configuration will permanently delete information.\n"
"Changes cannot be undone. Continue (y/N)? ", &ans);
cReply = blob_str(&ans)[0];
if( cReply!='y' && cReply!='Y' ){
fossil_exit(1);
}
}
db_unprotect(PROTECT_ALL);
db_multi_exec(
"PRAGMA secure_delete=ON;"
"DELETE FROM config WHERE name GLOB 'ssl-*';"
);
db_protect_pop();
}else
if( strncmp("show",zCmd,nCmd)==0 ){
const char *zName, *zValue;
const char *zUsed = 0; /* Trust store location actually used */
size_t nName;
Stmt q;
int verbose = find_option("verbose","v",0)!=0;
verify_all_options();
#if !defined(FOSSIL_ENABLE_SSL)
fossil_print("OpenSSL-version: (none)\n");
if( verbose ){
fossil_print("\n"
" The OpenSSL library is not used by this build of Fossil\n\n"
);
}
#else
fossil_print("OpenSSL-version: %s (0x%09x)\n",
SSLeay_version(SSLEAY_VERSION), OPENSSL_VERSION_NUMBER);
if( verbose ){
fossil_print("\n"
" The version of the OpenSSL library being used\n"
" by this instance of Fossil. Version 3.0.0 or\n"
" later is recommended.\n\n"
);
}
fossil_print("Trust store location\n");
zName = X509_get_default_cert_file_env();
zValue = fossil_getenv(zName);
if( zValue==0 ) zValue = "";
trust_location_usable(zValue, &zUsed);
nName = strlen(zName);
fossil_print(" %s:%*s%s\n", zName, 19-nName, "", zValue);
zName = X509_get_default_cert_dir_env();
zValue = fossil_getenv(zName);
if( zValue==0 ) zValue = "";
trust_location_usable(zValue, &zUsed);
nName = strlen(zName);
fossil_print(" %s:%*s%s\n", zName, 19-nName, "", zValue);
if( verbose ){
fossil_print("\n"
" Environment variables that determine alternative locations for\n"
" the root certificates used by Fossil when it is acting as a SSL\n"
" client. If specified, these alternative locations take top\n"
" priority.\n\n"
);
}
zValue = db_get("ssl-ca-location","");
trust_location_usable(zValue, &zUsed);
fossil_print(" ssl-ca-location: %s\n", zValue);
if( verbose ){
fossil_print("\n"
" This setting is the name of a file or directory that contains\n"
" the complete set of root certificates used by Fossil when it\n"
" is acting as a SSL client. If defined, this setting takes\n"
" priority over built-in paths.\n\n"
);
}
zValue = X509_get_default_cert_file();
trust_location_usable(zValue, &zUsed);
fossil_print(" OpenSSL-cert-file: %s\n", zValue);
zValue = X509_get_default_cert_dir();
trust_location_usable(zValue, &zUsed);
fossil_print(" OpenSSL-cert-dir: %s\n", X509_get_default_cert_dir());
if( verbose ){
fossil_print("\n"
" The default locations for the set of root certificates\n"
" used by the \"fossil sync\" and similar commands to verify\n"
" the identity of servers for \"https:\" URLs. These values\n"
" come into play when Fossil is used as a TLS client. These\n"
" values are built into your OpenSSL library.\n\n"
);
}
if( zUsed==0 ) zUsed = "";
fossil_print(" Trust store used: %s\n", zUsed);
if( verbose ){
fossil_print("\n"
" The location that is actually used for the root certificates\n"
" used to verify the identity of servers for \"https:\" URLs.\n"
" This will be one of the first of the five locations listed\n"
" above that actually exists.\n\n"
);
}
#endif /* FOSSIL_ENABLE_SSL */
fossil_print("ssl-identity: %s\n", db_get("ssl-identity",""));
if( verbose ){
fossil_print("\n"
" This setting is the name of a file that contains the PEM-format\n"
" certificate and private-key used by Fossil clients to authenticate\n"
" with servers. Few servers actually require this, so this setting\n"
" is usually blank.\n\n"
);
}
db_prepare(&q,
"SELECT name, '', value FROM global_config"
" WHERE name GLOB 'cert:*'"
"UNION ALL "
"SELECT name, date(mtime,'unixepoch'), value FROM config"
" WHERE name GLOB 'cert:*'"
" ORDER BY name"
);
nHit = 0;
while( db_step(&q)==SQLITE_ROW ){
/* 123456789 123456789 123456789 */
if( verbose ){
fossil_print("exception: %-40s %s\n"
" hash: %.57s\n",
db_column_text(&q,0)+5, db_column_text(&q,1),
db_column_text(&q,2));
}else{
fossil_print("exception: %-40s %s\n",
db_column_text(&q,0)+5, db_column_text(&q,1));
}
nHit++;
}
db_finalize(&q);
if( nHit && verbose ){
fossil_print("\n"
" The exceptions are server certificates that the Fossil client\n"
" is unable to verify using root certificates, but which should be\n"
" accepted anyhow.\n\n"
);
}
}else
if( strncmp("remove-exception",zCmd,nCmd)==0 ){
int i;
Blob sql;
char *zSep = "(";
db_begin_transaction();
blob_init(&sql, 0, 0);
if( g.argc==4 && find_option("all",0,0)!=0 ){
blob_append_sql(&sql,
"DELETE FROM global_config WHERE name GLOB 'cert:*';\n"
"DELETE FROM global_config WHERE name GLOB 'trusted:*';\n"
"DELETE FROM config WHERE name GLOB 'cert:*';\n"
"DELETE FROM config WHERE name GLOB 'trusted:*';\n"
);
}else{
if( g.argc<4 ){
usage("remove-exception DOMAIN-NAME ...");
}
blob_append_sql(&sql,"DELETE FROM global_config WHERE name IN ");
for(i=3; i<g.argc; i++){
blob_append_sql(&sql,"%s'cert:%q','trust:%q'",
zSep/*safe-for-%s*/, g.argv[i], g.argv[i]);
zSep = ",";
}
blob_append_sql(&sql,");\n");
zSep = "(";
blob_append_sql(&sql,"DELETE FROM config WHERE name IN ");
for(i=3; i<g.argc; i++){
blob_append_sql(&sql,"%s'cert:%q','trusted:%q'",
zSep/*safe-for-%s*/, g.argv[i], g.argv[i]);
zSep = ",";
}
blob_append_sql(&sql,");");
}
db_unprotect(PROTECT_CONFIG);
db_exec_sql(blob_str(&sql));
db_protect_pop();
db_commit_transaction();
blob_reset(&sql);
}else
/*default*/{
fossil_fatal("unknown sub-command \"%s\".\nshould be one of:"
" remove-exception scrub show",
zCmd);
}
}
/*
** WEBPAGE: .well-known
**
** If the "--acme" option was supplied to "fossil server" or "fossil http" or
** similar, then this page returns the content of files found in the
** ".well-known" subdirectory of the same directory that contains the
** repository file. This facilitates Automated Certificate
** Management using tools like "certbot".
**
** The content is returned directly, without any interpretation, using
** a generic mimetype.
*/
void wellknown_page(void){
char *zPath = 0;
const char *zTail = P("name");
Blob content;
int i;
char c;
if( !g.fAllowACME ) goto wellknown_notfound;
if( g.zRepositoryName==0 ) goto wellknown_notfound;
if( zTail==0 ) goto wellknown_notfound;
zPath = mprintf("%z/.well-known/%s", file_dirname(g.zRepositoryName), zTail);
for(i=0; (c = zTail[i])!=0; i++){
if( fossil_isalnum(c) ) continue;
if( c=='.' ){
if( i==0 || zTail[i-1]=='/' || zTail[i-1]=='.' ) goto wellknown_notfound;
continue;
}
if( c==',' || c!='-' || c=='/' || c==':' || c=='_' || c=='~' ) continue;
goto wellknown_notfound;
}
if( strstr("/..", zPath)!=0 ) goto wellknown_notfound;
if( !file_isfile(zPath, ExtFILE) ) goto wellknown_notfound;
blob_read_from_file(&content, zPath, ExtFILE);
cgi_set_content(&content);
cgi_set_content_type(mimetype_from_name(zPath));
cgi_reply();
return;
wellknown_notfound:
fossil_free(zPath);
webpage_notfound_error(0);
return;
}
|
Changes to src/http_transport.c.
| ︙ | ︙ | |||
139 140 141 142 143 144 145 |
blob_append_escaped_arg(&zCmd, pUrlData->fossil, 1);
blob_append(&zCmd, " test-http", 10);
if( pUrlData->path && pUrlData->path[0] ){
blob_append_escaped_arg(&zCmd, pUrlData->path, 1);
}else{
fossil_fatal("ssh:// URI does not specify a path to the repository");
}
| | | | 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
blob_append_escaped_arg(&zCmd, pUrlData->fossil, 1);
blob_append(&zCmd, " test-http", 10);
if( pUrlData->path && pUrlData->path[0] ){
blob_append_escaped_arg(&zCmd, pUrlData->path, 1);
}else{
fossil_fatal("ssh:// URI does not specify a path to the repository");
}
if( g.fSshTrace || g.fHttpTrace ){
fossil_print("RUN %s\n", blob_str(&zCmd)); /* Show the whole SSH command */
}
popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid, 0);
if( sshPid==0 ){
socket_set_errmsg("cannot start ssh tunnel using [%b]", &zCmd);
}
blob_reset(&zCmd);
return sshPid==0;
|
| ︙ | ︙ | |||
168 169 170 171 172 173 174 |
int rc = 0;
if( transport.isOpen==0 ){
if( pUrlData->isSsh ){
rc = transport_ssh_open(pUrlData);
if( rc==0 ) transport.isOpen = 1;
}else if( pUrlData->isHttps ){
#ifdef FOSSIL_ENABLE_SSL
| | | | > | < | < | 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
int rc = 0;
if( transport.isOpen==0 ){
if( pUrlData->isSsh ){
rc = transport_ssh_open(pUrlData);
if( rc==0 ) transport.isOpen = 1;
}else if( pUrlData->isHttps ){
#ifdef FOSSIL_ENABLE_SSL
rc = ssl_open_client(pUrlData);
if( rc==0 ) transport.isOpen = 1;
#else
socket_set_errmsg("HTTPS: Fossil has been compiled without SSL support");
rc = 1;
#endif
}else if( pUrlData->isFile ){
if( !db_looks_like_a_repository(pUrlData->name) ){
fossil_fatal("not a fossil repository: \"%s\"", pUrlData->name);
}
transport.zOutFile = fossil_temp_filename();
transport.zInFile = fossil_temp_filename();
transport.pFile = fossil_fopen(transport.zOutFile, "wb");
if( transport.pFile==0 ){
fossil_fatal("cannot output temporary file: %s", transport.zOutFile);
}
transport.isOpen = 1;
}else{
rc = socket_open(pUrlData);
|
| ︙ | ︙ | |||
212 213 214 215 216 217 218 |
fclose(transport.pLog);
transport.pLog = 0;
}
if( pUrlData->isSsh ){
transport_ssh_close();
}else if( pUrlData->isHttps ){
#ifdef FOSSIL_ENABLE_SSL
| | | | | 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
fclose(transport.pLog);
transport.pLog = 0;
}
if( pUrlData->isSsh ){
transport_ssh_close();
}else if( pUrlData->isHttps ){
#ifdef FOSSIL_ENABLE_SSL
ssl_close_client();
#endif
}else if( pUrlData->isFile ){
if( transport.pFile ){
fclose(transport.pFile);
transport.pFile = 0;
}
file_delete(transport.zInFile);
file_delete(transport.zOutFile);
sqlite3_free(transport.zInFile);
sqlite3_free(transport.zOutFile);
}else{
socket_close();
}
transport.isOpen = 0;
}
}
|
| ︙ | ︙ | |||
275 276 277 278 279 280 281 282 283 284 285 286 287 288 |
if( pUrlData->isFile ){
char *zCmd;
fclose(transport.pFile);
zCmd = mprintf("%$ http --in %$ --out %$ --ipaddr 127.0.0.1"
" %$ --localauth",
g.nameOfExe, transport.zOutFile, transport.zInFile, pUrlData->name
);
fossil_system(zCmd);
free(zCmd);
transport.pFile = fossil_fopen(transport.zInFile, "rb");
}
}
/*
| > | 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 |
if( pUrlData->isFile ){
char *zCmd;
fclose(transport.pFile);
zCmd = mprintf("%$ http --in %$ --out %$ --ipaddr 127.0.0.1"
" %$ --localauth",
g.nameOfExe, transport.zOutFile, transport.zInFile, pUrlData->name
);
if( g.fHttpTrace ) fossil_print("RUN %s\n", zCmd);
fossil_system(zCmd);
free(zCmd);
transport.pFile = fossil_fopen(transport.zInFile, "rb");
}
}
/*
|
| ︙ | ︙ |
Changes to src/import.c.
| ︙ | ︙ | |||
2006 2007 2008 2009 2010 2011 2012 |
db_end_transaction(0);
fossil_print(" \r");
if( omitRebuild ){
omitVacuum = 1;
}else{
db_begin_transaction();
fossil_print("Rebuilding repository meta-data...\n");
| | | 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 |
db_end_transaction(0);
fossil_print(" \r");
if( omitRebuild ){
omitVacuum = 1;
}else{
db_begin_transaction();
fossil_print("Rebuilding repository meta-data...\n");
rebuild_db(1, !incrFlag);
verify_cancel();
db_end_transaction(0);
}
if( !omitVacuum ){
fossil_print("Vacuuming..."); fflush(stdout);
db_multi_exec("VACUUM");
}
|
| ︙ | ︙ |
Changes to src/info.c.
| ︙ | ︙ | |||
491 492 493 494 495 496 497 |
char const *zType;
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
rid = name_to_rid_www("name");
if( rid==0 ){
style_header("Check-in Information Error");
| | | 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 |
char const *zType;
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
rid = name_to_rid_www("name");
if( rid==0 ){
style_header("Check-in Information Error");
@ No such object: %h(PD("name",""))
style_finish_page();
return;
}
zHash = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
style_header("Tags and Properties");
zType = whatis_rid_type_label(rid);
if(!zType) zType = "Artifact";
|
| ︙ | ︙ | |||
625 626 627 628 629 630 631 |
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
style_set_current_feature("vinfo");
zName = P("name");
rid = name_to_rid_www("name");
if( rid==0 ){
style_header("Check-in Information Error");
| | | 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 |
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
style_set_current_feature("vinfo");
zName = P("name");
rid = name_to_rid_www("name");
if( rid==0 ){
style_header("Check-in Information Error");
@ No such object: %h(zName)
style_finish_page();
return;
}
zRe = P("regex");
if( zRe ) re_compile(&pRe, zRe, 0);
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
zParent = db_text(0,
|
| ︙ | ︙ | |||
1765 1766 1767 1768 1769 1770 1771 |
if( zRe ) re_compile(&pRe, zRe, 0);
if( verbose ) objdescFlags |= OBJDESC_DETAIL;
if( isPatch ){
Blob c1, c2, *pOut;
DiffConfig DCfg;
pOut = cgi_output_blob();
cgi_set_content_type("text/plain");
| | | 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 |
if( zRe ) re_compile(&pRe, zRe, 0);
if( verbose ) objdescFlags |= OBJDESC_DETAIL;
if( isPatch ){
Blob c1, c2, *pOut;
DiffConfig DCfg;
pOut = cgi_output_blob();
cgi_set_content_type("text/plain");
diffFlags = DIFF_VERBOSE;
content_get(v1, &c1);
content_get(v2, &c2);
diff_config_init(&DCfg, diffFlags);
DCfg.pRe = pRe;
text_diff(&c1, &c2, pOut, &DCfg);
blob_reset(&c1);
blob_reset(&c2);
|
| ︙ | ︙ | |||
2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 |
}
style_submenu_element("Artifact", "%R/artifact/%S", zUuid);
zMime = mimetype_from_name(zName);
style_submenu_element("Annotate", "%R/annotate?filename=%T&checkin=%T",
zName, zCI);
style_submenu_element("Blame", "%R/blame?filename=%T&checkin=%T",
zName, zCI);
blob_init(&downloadName, zName, -1);
objType = OBJTYPE_CONTENT;
}else{
@ <h2>Artifact
style_copy_button(1, "hash-ar", 0, 2, "%s", zUuid);
if( g.perm.Setup ){
@ (%d(rid)):</h2>
| > | 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 |
}
style_submenu_element("Artifact", "%R/artifact/%S", zUuid);
zMime = mimetype_from_name(zName);
style_submenu_element("Annotate", "%R/annotate?filename=%T&checkin=%T",
zName, zCI);
style_submenu_element("Blame", "%R/blame?filename=%T&checkin=%T",
zName, zCI);
style_submenu_element("Doc", "%R/doc/%T/%T", zCI, zName);
blob_init(&downloadName, zName, -1);
objType = OBJTYPE_CONTENT;
}else{
@ <h2>Artifact
style_copy_button(1, "hash-ar", 0, 2, "%s", zUuid);
if( g.perm.Setup ){
@ (%d(rid)):</h2>
|
| ︙ | ︙ | |||
3305 3306 3307 3308 3309 3310 3311 |
@ <input type="checkbox" name="pclr" checked="checked" />
}else{
@ <input type="checkbox" name="pclr" />
}
@ Propagate color to descendants</label></div>
@ <div class='font-size-80'>Be aware that fixed background
@ colors will not interact well with all available skins.
| | | 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 |
@ <input type="checkbox" name="pclr" checked="checked" />
}else{
@ <input type="checkbox" name="pclr" />
}
@ Propagate color to descendants</label></div>
@ <div class='font-size-80'>Be aware that fixed background
@ colors will not interact well with all available skins.
@ It is recommended that Fossil be allowed to select these
@ colors automatically so that it can take the skin's
@ preferences into account.</div>
@ </td></tr>
@ <tr><th align="right" valign="top">Tags:</th>
@ <td valign="top">
@ <label><input type="checkbox" id="newtag" name="newtag"%s(zNewTagFlag) />
|
| ︙ | ︙ |
Changes to src/interwiki.c.
| ︙ | ︙ | |||
81 82 83 84 85 86 87 |
for(i=0; fossil_isalnum(zTarget[i]); i++){}
if( zTarget[i]!=':' ) return 0;
nCode = i;
if( nCode==4 && strncmp(zTarget,"wiki",4)==0 ) return 0;
zPage = zTarget + nCode + 1;
nPage = (int)strlen(zPage);
db_static_prepare(&q,
| | < < | | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
for(i=0; fossil_isalnum(zTarget[i]); i++){}
if( zTarget[i]!=':' ) return 0;
nCode = i;
if( nCode==4 && strncmp(zTarget,"wiki",4)==0 ) return 0;
zPage = zTarget + nCode + 1;
nPage = (int)strlen(zPage);
db_static_prepare(&q,
"SELECT value->>'base', value->>'hash', value->>'wiki'"
" FROM config WHERE name=lower($name) AND json_valid(value)"
);
zName = mprintf("interwiki:%.*s", nCode, zTarget);
db_bind_text(&q, "$name", zName);
while( db_step(&q)==SQLITE_ROW ){
const char *zBase = db_column_text(&q,0);
if( zBase==0 || zBase[0]==0 ) break;
if( nPage==0 || zPage[0]=='/' ){
|
| ︙ | ︙ | |||
236 237 238 239 240 241 242 |
}else
if( strncmp(zCmd, "list", nCmd)==0 ){
Stmt q;
int n = 0;
verify_all_options();
db_prepare(&q,
"SELECT substr(name,11),"
| | < < | | 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
}else
if( strncmp(zCmd, "list", nCmd)==0 ){
Stmt q;
int n = 0;
verify_all_options();
db_prepare(&q,
"SELECT substr(name,11),"
" value->>'base', value->>'hash', value->>'wiki'"
" FROM config WHERE name glob 'interwiki:*' AND json_valid(value)"
);
while( db_step(&q)==SQLITE_ROW ){
const char *zBase, *z, *zName;
if( n++ ) fossil_print("\n");
zName = db_column_text(&q,0);
zBase = db_column_text(&q,1);
fossil_print("%-15s %s\n", zName, zBase);
|
| ︙ | ︙ | |||
273 274 275 276 277 278 279 |
** Append text to the "Markdown" or "Wiki" rules pages that shows
** a table of all interwiki tags available on this system.
*/
void interwiki_append_map_table(Blob *out){
int n = 0;
Stmt q;
db_prepare(&q,
| | | | 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 |
** Append text to the "Markdown" or "Wiki" rules pages that shows
** a table of all interwiki tags available on this system.
*/
void interwiki_append_map_table(Blob *out){
int n = 0;
Stmt q;
db_prepare(&q,
"SELECT substr(name,11), value->>'base'"
" FROM config WHERE name glob 'interwiki:*' AND json_valid(value)"
" ORDER BY name;"
);
while( db_step(&q)==SQLITE_ROW ){
if( n==0 ){
blob_appendf(out, "<blockquote><table>\n");
}
blob_appendf(out,"<tr><td>%h</td><td> → </td>",
|
| ︙ | ︙ | |||
350 351 352 353 354 355 356 |
@ <p>Interwiki links are hyperlink targets of the form
@ <blockquote><i>Tag</i><b>:</b><i>PageName</i></blockquote>
@ <p>Such links resolve to links to <i>PageName</i> on a separate server
@ identified by <i>Tag</i>. The Interwiki Map or "intermap" is a mapping
@ from <i>Tags</i> to complete Server URLs.
db_prepare(&q,
"SELECT substr(name,11),"
| | < < | | 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 |
@ <p>Interwiki links are hyperlink targets of the form
@ <blockquote><i>Tag</i><b>:</b><i>PageName</i></blockquote>
@ <p>Such links resolve to links to <i>PageName</i> on a separate server
@ identified by <i>Tag</i>. The Interwiki Map or "intermap" is a mapping
@ from <i>Tags</i> to complete Server URLs.
db_prepare(&q,
"SELECT substr(name,11),"
" value->>'base', value->>'hash', value->>'wiki'"
" FROM config WHERE name glob 'interwiki:*' AND json_valid(value)"
);
while( db_step(&q)==SQLITE_ROW ){
if( n==0 ){
@ The current mapping is as follows:
@ <ol>
}
@ <li><p> %h(db_column_text(&q,0))
|
| ︙ | ︙ |
Changes to src/json.c.
| ︙ | ︙ | |||
2183 2184 2185 2186 2187 2188 2189 |
On large repos (e.g. fossil's) this operation is likely to take
longer than the client timeout, which will cause it to fail (but
it's sqlite3, so it'll fail gracefully).
*/
db_close(1);
db_open_repository(g.zRepositoryName);
db_begin_transaction();
| | | 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 |
On large repos (e.g. fossil's) this operation is likely to take
longer than the client timeout, which will cause it to fail (but
it's sqlite3, so it'll fail gracefully).
*/
db_close(1);
db_open_repository(g.zRepositoryName);
db_begin_transaction();
rebuild_db(0, 0);
db_end_transaction(0);
return NULL;
}
}
/*
** Impl of /json/g. Requires admin/setup rights.
|
| ︙ | ︙ |
Changes to src/login.c.
| ︙ | ︙ | |||
2114 2115 2116 2117 2118 2119 2120 | ); db_protect_pop(); } /* ** COMMAND: login-group* ** | | > | > > | | | > | | | | > > | | > > > > | | | | | | | | 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 |
);
db_protect_pop();
}
/*
** COMMAND: login-group*
**
** Usage: %fossil login-group ?SUBCOMMAND? ?OPTIONS?
**
** Run various subcommands to manage login-group related settings of the open
** repository or of the repository identified by the -R or --repository option.
**
** > fossil login-group
**
** Show the login-group to which the repository belongs.
**
** > fossil login-group join ?--name NAME?
**
** Add this repository to login group to which REPO belongs, or creates a
** new login group between itself and REPO if REPO does not already belong
** to a login-group. When creating a new login-group, the name of the new
** group is determined by the "--name" option.
**
** > fossil login-group leave
**
** Takes the repository out of whatever login group it is currently
** a part of.
**
** Options valid for all subcommands:
**
** -R|--repository REPO Run commands on repository REPO
**
** About Login Groups:
**
** A login-group is a set of repositories that share user credentials.
** If a user is logged into one member of the group, then that user can
** access any other group member as long as they have an entry in the USER
** table of that member. If a user changes their password using web
** interface, their password is also automatically changed in every other
** member of the login group.
*/
void login_group_command(void){
const char *zLGName;
const char *zCmd;
int nCmd;
Stmt q;
db_find_and_open_repository(0, 0);
if( g.argc>2 ){
zCmd = g.argv[2];
nCmd = (int)strlen(zCmd);
if( strncmp(zCmd,"join",nCmd)==0 && nCmd>=1 ){
const char *zNewName = find_option("name",0,1);
const char *zOther;
char *zErr = 0;
|
| ︙ | ︙ |
Changes to src/main.c.
| ︙ | ︙ | |||
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | #include "main.h" #include <string.h> #include <time.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <stdlib.h> /* atexit() */ #if !defined(_WIN32) # include <errno.h> /* errno global */ # include <unistd.h> # include <signal.h> # define GETPID getpid #endif #ifdef FOSSIL_ENABLE_SSL # include "openssl/crypto.h" #endif | > < < < < < < | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | #include "main.h" #include <string.h> #include <time.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <stdlib.h> /* atexit() */ #include <zlib.h> #if !defined(_WIN32) # include <errno.h> /* errno global */ # include <unistd.h> # include <signal.h> # define GETPID getpid #endif #ifdef FOSSIL_ENABLE_SSL # include "openssl/crypto.h" #endif #if INTERFACE #ifdef FOSSIL_ENABLE_TCL # include "tcl.h" #endif #ifdef FOSSIL_ENABLE_JSON # include "cson_amalgamation.h" /* JSON API. */ # include "json_detail.h" |
| ︙ | ︙ | |||
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | int fSqlStats; /* True if --sqltrace or --sqlstats are present */ int fSqlPrint; /* True if --sqlprint flag is present */ int fCgiTrace; /* True if --cgitrace is enabled */ int fQuiet; /* True if -quiet flag is present */ int fJail; /* True if running with a chroot jail */ int fHttpTrace; /* Trace outbound HTTP requests */ int fAnyTrace; /* Any kind of tracing */ char *zHttpAuth; /* HTTP Authorization user:pass information */ int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */ int fSshTrace; /* Trace the SSH setup traffic */ int fSshClient; /* HTTP client flags for SSH client */ int fNoHttpCompress; /* Do not compress HTTP traffic (for debugging) */ char *zSshCmd; /* SSH command string */ int fNoSync; /* Do not do an autosync ever. --nosync */ int fIPv4; /* Use only IPv4, not IPv6. --ipv4 */ char *zPath; /* Name of webpage being served */ char *zExtra; /* Extra path information past the webpage name */ char *zBaseURL; /* Full text of the URL being served */ char *zHttpsURL; /* zBaseURL translated to https: */ char *zTop; /* Parent directory of zPath */ | > > | 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | int fSqlStats; /* True if --sqltrace or --sqlstats are present */ int fSqlPrint; /* True if --sqlprint flag is present */ int fCgiTrace; /* True if --cgitrace is enabled */ int fQuiet; /* True if -quiet flag is present */ int fJail; /* True if running with a chroot jail */ int fHttpTrace; /* Trace outbound HTTP requests */ int fAnyTrace; /* Any kind of tracing */ int fAllowACME; /* Deliver files from .well-known */ char *zHttpAuth; /* HTTP Authorization user:pass information */ int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */ int fSshTrace; /* Trace the SSH setup traffic */ int fSshClient; /* HTTP client flags for SSH client */ int fNoHttpCompress; /* Do not compress HTTP traffic (for debugging) */ char *zSshCmd; /* SSH command string */ const char *zHttpCmd; /* External program to do HTTP requests */ int fNoSync; /* Do not do an autosync ever. --nosync */ int fIPv4; /* Use only IPv4, not IPv6. --ipv4 */ char *zPath; /* Name of webpage being served */ char *zExtra; /* Extra path information past the webpage name */ char *zBaseURL; /* Full text of the URL being served */ char *zHttpsURL; /* zBaseURL translated to https: */ char *zTop; /* Parent directory of zPath */ |
| ︙ | ︙ | |||
197 198 199 200 201 202 203 204 205 206 207 208 209 210 | int xferPanic; /* Write error messages in XFER protocol */ int fullHttpReply; /* True for full HTTP reply. False for CGI reply */ Th_Interp *interp; /* The TH1 interpreter */ char *th1Setup; /* The TH1 post-creation setup script, if any */ int th1Flags; /* The TH1 integration state flags */ FILE *httpIn; /* Accept HTTP input from here */ FILE *httpOut; /* Send HTTP output here */ int xlinkClusterOnly; /* Set when cloning. Only process clusters */ int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */ int *aCommitFile; /* Array of files to be committed */ int markPrivate; /* All new artifacts are private if true */ char *ckinLockFail; /* Check-in lock failure received from server */ int clockSkewSeen; /* True if clocks on client and server out of sync */ int wikiFlags; /* Wiki conversion flags applied to %W */ | > > | 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | int xferPanic; /* Write error messages in XFER protocol */ int fullHttpReply; /* True for full HTTP reply. False for CGI reply */ Th_Interp *interp; /* The TH1 interpreter */ char *th1Setup; /* The TH1 post-creation setup script, if any */ int th1Flags; /* The TH1 integration state flags */ FILE *httpIn; /* Accept HTTP input from here */ FILE *httpOut; /* Send HTTP output here */ int httpUseSSL; /* True to use an SSL codec for HTTP traffic */ void *httpSSLConn; /* The SSL connection */ int xlinkClusterOnly; /* Set when cloning. Only process clusters */ int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */ int *aCommitFile; /* Array of files to be committed */ int markPrivate; /* All new artifacts are private if true */ char *ckinLockFail; /* Check-in lock failure received from server */ int clockSkewSeen; /* True if clocks on client and server out of sync */ int wikiFlags; /* Wiki conversion flags applied to %W */ |
| ︙ | ︙ | |||
696 697 698 699 700 701 702 | fossil_printf_selfcheck(); fossil_limit_memory(1); /* When updating the minimum SQLite version, change the number here, ** and also MINIMUM_SQLITE_VERSION value set in ../auto.def. Take ** care that both places agree! */ | | > > | | 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 |
fossil_printf_selfcheck();
fossil_limit_memory(1);
/* When updating the minimum SQLite version, change the number here,
** and also MINIMUM_SQLITE_VERSION value set in ../auto.def. Take
** care that both places agree! */
if( sqlite3_libversion_number()<3038000
|| strncmp(sqlite3_sourceid(),"2022-01-12",10)<0
){
fossil_panic("Unsuitable SQLite version %s, must be at least 3.38.0",
sqlite3_libversion());
}
sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0);
memset(&g, 0, sizeof(g));
g.now = time(0);
|
| ︙ | ︙ | |||
1192 1193 1194 1195 1196 1197 1198 |
if( !bVerbose ) return;
blob_appendf(pOut, "Compiled on %s %s using %s (%d-bit)\n",
__DATE__, __TIME__, COMPILER_NAME, sizeof(void*)*8);
blob_appendf(pOut, "Schema version %s\n", AUX_SCHEMA_MAX);
fossil_get_page_size(&pageSize);
blob_appendf(pOut, "Detected memory page size is %lu bytes\n",
(unsigned long)pageSize);
| < < < < | 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 |
if( !bVerbose ) return;
blob_appendf(pOut, "Compiled on %s %s using %s (%d-bit)\n",
__DATE__, __TIME__, COMPILER_NAME, sizeof(void*)*8);
blob_appendf(pOut, "Schema version %s\n", AUX_SCHEMA_MAX);
fossil_get_page_size(&pageSize);
blob_appendf(pOut, "Detected memory page size is %lu bytes\n",
(unsigned long)pageSize);
blob_appendf(pOut, "zlib %s, loaded %s\n", ZLIB_VERSION, zlibVersion());
#if FOSSIL_HARDENED_SHA1
blob_appendf(pOut, "hardened-SHA1 by Marc Stevens and Dan Shumow\n");
#endif
#if defined(FOSSIL_ENABLE_SSL)
blob_appendf(pOut, "SSL (%s)\n", SSLeay_version(SSLEAY_VERSION));
#endif
#if defined(FOSSIL_HAVE_FUSEFS)
|
| ︙ | ︙ | |||
1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 |
}
}
/*
** Send an HTTP redirect back to the designated Index Page.
*/
NORETURN void fossil_redirect_home(void){
cgi_redirectf("%R%s", db_get("index-page", "/index"));
}
/*
** If running as root, chroot to the directory containing the
** repository zRepo and then drop root privileges. Return the
** new repository name.
| > > > > > > > > | 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 |
}
}
/*
** Send an HTTP redirect back to the designated Index Page.
*/
NORETURN void fossil_redirect_home(void){
/* In order for ?skin=... to work when visiting the site from
** a typical external link, we have to process is here, as
** that parameter gets lost during the redirect. We "could"
** pass the whole query string along instead, but that seems
** unnecessary. */
if(cgi_setup_query_string()>1){
cookie_render();
}
cgi_redirectf("%R%s", db_get("index-page", "/index"));
}
/*
** If running as root, chroot to the directory containing the
** repository zRepo and then drop root privileges. Return the
** new repository name.
|
| ︙ | ︙ | |||
1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 |
if( fossil_strcmp(g.zRepositoryName, "/")==0 ){
zBase++;
#if defined(_WIN32) || defined(__CYGWIN__)
if( sqlite3_strglob("/[a-zA-Z]:/*", zPathInfo)==0 ) i = 4;
#endif
}
while( 1 ){
while( zPathInfo[i] && zPathInfo[i]!='/' ){ i++; }
/* The candidate repository name is some prefix of the PATH_INFO
** with ".fossil" appended */
zRepo = zToFree = mprintf("%s%.*s.fossil",zBase,i,zPathInfo);
if( g.fHttpTrace ){
@ <!-- Looking for repository named "%h(zRepo)" -->
fprintf(stderr, "# looking for repository named \"%s\"\n", zRepo);
}
/* For safety -- to prevent an attacker from accessing arbitrary disk
** files by sending a maliciously crafted request URI to a public
** server -- make sure the repository basename contains no
** characters other than alphanumerics, "/", "_", "-", and ".", and
** that "-" never occurs immediately after a "/" and that "." is always
** surrounded by two alphanumerics. Any character that does not
** satisfy these constraints is converted into "_".
*/
szFile = 0;
| > | > > > > > > | 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 |
if( fossil_strcmp(g.zRepositoryName, "/")==0 ){
zBase++;
#if defined(_WIN32) || defined(__CYGWIN__)
if( sqlite3_strglob("/[a-zA-Z]:/*", zPathInfo)==0 ) i = 4;
#endif
}
while( 1 ){
size_t nBase = strlen(zBase);
while( zPathInfo[i] && zPathInfo[i]!='/' ){ i++; }
/* The candidate repository name is some prefix of the PATH_INFO
** with ".fossil" appended */
zRepo = zToFree = mprintf("%s%.*s.fossil",zBase,i,zPathInfo);
if( g.fHttpTrace ){
@ <!-- Looking for repository named "%h(zRepo)" -->
fprintf(stderr, "# looking for repository named \"%s\"\n", zRepo);
}
/* For safety -- to prevent an attacker from accessing arbitrary disk
** files by sending a maliciously crafted request URI to a public
** server -- make sure the repository basename contains no
** characters other than alphanumerics, "/", "_", "-", and ".", and
** that "-" never occurs immediately after a "/" and that "." is always
** surrounded by two alphanumerics. Any character that does not
** satisfy these constraints is converted into "_".
*/
szFile = 0;
for(j=nBase+1, k=0; zRepo[j] && k<i-1; j++, k++){
char c = zRepo[j];
if( fossil_isalnum(c) ) continue;
#if defined(_WIN32) || defined(__CYGWIN__)
/* Allow names to begin with "/X:/" on windows */
if( c==':' && j==2 && sqlite3_strglob("/[a-zA-Z]:/*", zRepo)==0 ){
continue;
}
#endif
if( c=='/' ) continue;
if( c=='_' ) continue;
if( c=='-' && zRepo[j-1]!='/' ) continue;
if( c=='.' && fossil_isalnum(zRepo[j-1]) && fossil_isalnum(zRepo[j+1])){
continue;
}
if( c=='.' && g.fAllowACME && j==nBase+1
&& strncmp(&zRepo[j-1],"/.well-known/",12)==0
){
/* We allow .well-known as the top-level directory for ACME */
continue;
}
/* If we reach this point, it means that the request URI contains
** an illegal character or character combination. Provoke a
** "Not Found" error. */
szFile = 1;
if( g.fHttpTrace ){
@ <!-- Unsafe pathname rejected: "%h(zRepo)" -->
|
| ︙ | ︙ | |||
1761 1762 1763 1764 1765 1766 1767 |
** being delivered accidently. This is not intended to be a
** general-purpose web server. The "--file GLOB" mechanism is
** designed to allow the delivery of a few static images or HTML
** pages.
*/
if( pFileGlob!=0
&& file_isfile(zCleanRepo, ExtFILE)
| | > > > > > > > > > > > > > > > | 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 |
** being delivered accidently. This is not intended to be a
** general-purpose web server. The "--file GLOB" mechanism is
** designed to allow the delivery of a few static images or HTML
** pages.
*/
if( pFileGlob!=0
&& file_isfile(zCleanRepo, ExtFILE)
&& glob_match(pFileGlob, file_cleanup_fullpath(zRepo+nBase))
&& sqlite3_strglob("*.fossil*",zRepo)!=0
&& (zMimetype = mimetype_from_name(zRepo))!=0
&& strcmp(zMimetype, "application/x-fossil-artifact")!=0
){
Blob content;
blob_read_from_file(&content, file_cleanup_fullpath(zRepo), ExtFILE);
cgi_set_content_type(zMimetype);
cgi_set_content(&content);
cgi_reply();
return;
}
/* In support of the ACME protocol, files under the .well-known/
** directory is always accepted.
*/
if( g.fAllowACME
&& strncmp(&zRepo[nBase],"/.well-known/",12)==0
&& file_isfile(zCleanRepo, ExtFILE)
){
Blob content;
blob_read_from_file(&content, file_cleanup_fullpath(zRepo), ExtFILE);
cgi_set_content_type(mimetype_from_name(zRepo));
cgi_set_content(&content);
cgi_reply();
return;
}
zRepo[j] = '.';
}
/* If we reach this point, it means that the search of the PATH_INFO
** string is finished. Either zRepo contains the name of the
** repository to be used, or else no repository could be found and
** some kind of error response is required.
|
| ︙ | ︙ | |||
2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 |
return;
}
}
}
#endif
@ %d(GETPID())
}
/*
** COMMAND: http*
**
** Usage: %fossil http ?REPOSITORY? ?OPTIONS?
**
** Handle a single HTTP request appearing on stdin. The resulting webpage
| > > > > > > > > > > > > > > > > > > > | 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 |
return;
}
}
}
#endif
@ %d(GETPID())
}
/*
** Check for options to "fossil server" or "fossil ui" that imply that
** SSL should be used, and initialize the SSL decoder.
*/
static void decode_ssl_options(void){
#if FOSSIL_ENABLE_SSL
const char *zCertFile = 0;
const char *zKeyFile = 0;
zCertFile = find_option("cert",0,1);
zKeyFile = find_option("pkey",0,1);
if( zCertFile ){
g.httpUseSSL = 1;
ssl_init_server(zCertFile, zKeyFile);
}else if( zKeyFile ){
fossil_fatal("--pkey without a corresponding --cert");
}
#endif
}
/*
** COMMAND: http*
**
** Usage: %fossil http ?REPOSITORY? ?OPTIONS?
**
** Handle a single HTTP request appearing on stdin. The resulting webpage
|
| ︙ | ︙ | |||
2594 2595 2596 2597 2598 2599 2600 | ** thus also no redirecting from http: to https: will take place. ** ** If the --localauth option is given, then automatic login is performed ** for requests coming from localhost, if the "localauth" setting is not ** enabled. ** ** Options: | > | > > > | | | | | | | | | > > | | > | | | | > | | | | < < | | > | 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 |
** thus also no redirecting from http: to https: will take place.
**
** If the --localauth option is given, then automatic login is performed
** for requests coming from localhost, if the "localauth" setting is not
** enabled.
**
** Options:
** --acme Deliver files from the ".well-known" subdirectory
** --baseurl URL base URL (useful with reverse proxies)
** --cert FILE Use TLS (HTTPS) encryption with the certificate (the
** fullchain.pem) taken from FILE.
** --chroot DIR Use directory for chroot instead of repository path.
** --ckout-alias N Treat URIs of the form /doc/N/... as if they were
** /doc/ckout/...
** --extroot DIR document root for the /ext extension mechanism
** --files GLOB comma-separate glob patterns for static file to serve
** --host NAME specify hostname of the server
** --https signal a request coming in via https
** --in FILE Take input from FILE instead of standard input
** --ipaddr ADDR Assume the request comes from the given IP address
** --jsmode MODE Determine how JavaScript is delivered with pages.
** Mode can be one of:
** inline All JavaScript is inserted inline at
** one or more points in the HTML file.
** separate Separate HTTP requests are made for
** each JavaScript file.
** bundled Groups JavaScript files into one or
** more bundled requests which
** concatenate scripts together.
** Depending on the needs of any given page, inline
** and bundled modes might result in a single
** amalgamated script or several, but both approaches
** result in fewer HTTP requests than the separate mode.
** --localauth enable automatic login for local connections
** --mainmenu FILE Override the mainmenu config setting with the contents
** of the given file.
** --nocompress do not compress HTTP replies
** --nodelay omit backoffice processing if it would delay
** process exit
** --nojail drop root privilege but do not enter the chroot jail
** --nossl signal that no SSL connections are available
** --notfound URL use URL as "HTTP 404, object not found" page.
** --out FILE write results to FILE instead of to standard output
** --pkey FILE Read the private key used for TLS from FILE.
** --repolist If REPOSITORY is directory, URL "/" lists all repos
** --scgi Interpret input as SCGI rather than HTTP
** --skin LABEL Use override skin LABEL
** --th-trace trace TH1 execution (for debugging purposes)
** --usepidkey Use saved encryption key from parent process. This is
** only necessary when using SEE on Windows.
**
** See also: [[cgi]], [[server]], [[winsrv]]
*/
void cmd_http(void){
const char *zIpAddr = 0;
const char *zNotFound;
const char *zHost;
const char *zAltBase;
const char *zFileGlob;
const char *zInFile;
const char *zOutFile;
const char *zChRoot;
int useSCGI;
int noJail;
int allowRepoList;
Th_InitTraceLog();
builtin_set_js_delivery_mode(find_option("jsmode",0,1),0);
|
| ︙ | ︙ | |||
2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 |
dehttpize(z);
zFileGlob = z;
}else{
zFileGlob = find_option("files",0,1);
}
skin_override();
zNotFound = find_option("notfound", 0, 1);
noJail = find_option("nojail",0,0)!=0;
allowRepoList = find_option("repolist",0,0)!=0;
g.useLocalauth = find_option("localauth", 0, 0)!=0;
g.sslNotAvailable = find_option("nossl", 0, 0)!=0;
g.fNoHttpCompress = find_option("nocompress",0,0)!=0;
g.zExtRoot = find_option("extroot",0,1);
g.zCkoutAlias = find_option("ckout-alias",0,1);
| > | 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 |
dehttpize(z);
zFileGlob = z;
}else{
zFileGlob = find_option("files",0,1);
}
skin_override();
zNotFound = find_option("notfound", 0, 1);
zChRoot = find_option("chroot",0,1);
noJail = find_option("nojail",0,0)!=0;
allowRepoList = find_option("repolist",0,0)!=0;
g.useLocalauth = find_option("localauth", 0, 0)!=0;
g.sslNotAvailable = find_option("nossl", 0, 0)!=0;
g.fNoHttpCompress = find_option("nocompress",0,0)!=0;
g.zExtRoot = find_option("extroot",0,1);
g.zCkoutAlias = find_option("ckout-alias",0,1);
|
| ︙ | ︙ | |||
2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 |
}
zHost = find_option("host", 0, 1);
if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost);
g.zMainMenuFile = find_option("mainmenu",0,1);
if( g.zMainMenuFile!=0 && file_size(g.zMainMenuFile,ExtFILE)<0 ){
fossil_fatal("Cannot read --mainmenu file %s", g.zMainMenuFile);
}
/* We should be done with options.. */
verify_all_options();
if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
g.cgiOutput = 1;
g.fullHttpReply = 1;
find_server_repository(2, 0);
if( zIpAddr==0 ){
zIpAddr = cgi_ssh_remote_addr(0);
if( zIpAddr && zIpAddr[0] ){
g.fSshClient |= CGI_SSH_CLIENT;
}
}
| > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > | 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 |
}
zHost = find_option("host", 0, 1);
if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost);
g.zMainMenuFile = find_option("mainmenu",0,1);
if( g.zMainMenuFile!=0 && file_size(g.zMainMenuFile,ExtFILE)<0 ){
fossil_fatal("Cannot read --mainmenu file %s", g.zMainMenuFile);
}
decode_ssl_options();
if( find_option("acme",0,0)!=0 ) g.fAllowACME = 1;
/* We should be done with options.. */
verify_all_options();
if( g.httpUseSSL ){
if( useSCGI ){
fossil_fatal("SSL not (yet) supported for SCGI");
}
if( g.fSshClient & CGI_SSH_CLIENT ){
fossil_fatal("SSL not compatible with SSH");
}
if( zInFile || zOutFile ){
fossil_fatal("SSL usable only on a socket");
}
cgi_replace_parameter("HTTPS","on");
}
if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
g.cgiOutput = 1;
g.fullHttpReply = 1;
find_server_repository(2, 0);
if( zIpAddr==0 ){
zIpAddr = cgi_ssh_remote_addr(0);
if( zIpAddr && zIpAddr[0] ){
g.fSshClient |= CGI_SSH_CLIENT;
}
}
if( zChRoot ){
enter_chroot_jail((char*)zChRoot, noJail);
}else{
g.zRepositoryName = enter_chroot_jail(g.zRepositoryName, noJail);
}
if( useSCGI ){
cgi_handle_scgi_request();
}else if( g.fSshClient & CGI_SSH_CLIENT ){
ssh_request_loop(zIpAddr, glob_create(zFileGlob));
}else{
#if FOSSIL_ENABLE_SSL
if( g.httpUseSSL ){
g.httpSSLConn = ssl_new_server(0);
}
#endif
cgi_handle_http_request(zIpAddr);
}
process_one_web_page(zNotFound, glob_create(zFileGlob), allowRepoList);
#if FOSSIL_ENABLE_SSL
if( g.httpUseSSL && g.httpSSLConn ){
ssl_close_server(g.httpSSLConn);
g.httpSSLConn = 0;
}
#endif /* FOSSIL_ENABLE_SSL */
}
/*
** Process all requests in a single SSH connection if possible.
*/
void ssh_request_loop(const char *zIpAddr, Glob *FileGlob){
blob_zero(&g.cgiIn);
|
| ︙ | ︙ | |||
2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 | ** having to log in. This can be disabled by turning off the "localauth" ** setting. Automatic login for the "server" command is available if the ** --localauth option is present and the "localauth" setting is off and the ** connection is from localhost. The "ui" command also enables --repolist ** by default. ** ** Options: ** --baseurl URL Use URL as the base (useful for reverse proxies) ** --ckout-alias NAME Treat URIs of the form /doc/NAME/... as if they were ** /doc/ckout/... ** --create Create a new REPOSITORY if it does not already exist ** --extroot DIR Document root for the /ext extension mechanism ** --files GLOBLIST Comma-separated list of glob patterns for static files ** --fossilcmd PATH Full pathname of the "fossil" executable on the remote ** system when REPOSITORY is remote. Default: "fossil" | > > > > | 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 | ** having to log in. This can be disabled by turning off the "localauth" ** setting. Automatic login for the "server" command is available if the ** --localauth option is present and the "localauth" setting is off and the ** connection is from localhost. The "ui" command also enables --repolist ** by default. ** ** Options: ** --acme Deliver files from the ".well-known" subdirectory. ** --baseurl URL Use URL as the base (useful for reverse proxies) ** --cert FILE Use TLS (HTTPS) encryption with the certificate (the ** fullchain.pem) taken from FILE. ** --chroot DIR Use directory for chroot instead of repository path. ** --ckout-alias NAME Treat URIs of the form /doc/NAME/... as if they were ** /doc/ckout/... ** --create Create a new REPOSITORY if it does not already exist ** --extroot DIR Document root for the /ext extension mechanism ** --files GLOBLIST Comma-separated list of glob patterns for static files ** --fossilcmd PATH Full pathname of the "fossil" executable on the remote ** system when REPOSITORY is remote. Default: "fossil" |
| ︙ | ︙ | |||
2921 2922 2923 2924 2925 2926 2927 | ** of the given file. ** --max-latency N Do not let any single HTTP request run for more than N ** seconds (only works on unix) ** --nobrowser Do not automatically launch a web-browser for the ** "fossil ui" command. ** --nocompress Do not compress HTTP replies ** --nojail Drop root privileges but do not enter the chroot jail | | > | | > > | 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 |
** of the given file.
** --max-latency N Do not let any single HTTP request run for more than N
** seconds (only works on unix)
** --nobrowser Do not automatically launch a web-browser for the
** "fossil ui" command.
** --nocompress Do not compress HTTP replies
** --nojail Drop root privileges but do not enter the chroot jail
** --nossl do not force redirects to SSL even if the repository
** setting "redirect-to-https" requests it. This is set
** by default for the "ui" command.
** --notfound URL Redirect to URL if a page is not found.
** --page PAGE Start "ui" on PAGE. ex: --page "timeline?y=ci"
** --pkey FILE Read the private key used for TLS from FILE.
** -P|--port TCPPORT listen to request on port TCPPORT
** --repolist If REPOSITORY is dir, URL "/" lists repos.
** --scgi Accept SCGI rather than HTTP
** --skin LABEL Use override skin LABEL
** --th-trace trace TH1 execution (for debugging purposes)
** --usepidkey Use saved encryption key from parent process. This is
** only necessary when using SEE on Windows.
**
** See also: [[cgi]], [[http]], [[winsrv]]
*/
void cmd_webserver(void){
int iPort, mxPort; /* Range of TCP ports allowed */
const char *zPort; /* Value of the --port option */
const char *zBrowser; /* Name of web browser program */
char *zBrowserCmd = 0; /* Command to launch the web browser */
int isUiCmd; /* True if command is "ui", not "server' */
const char *zNotFound; /* The --notfound option or NULL */
int flags = 0; /* Server flags */
#if !defined(_WIN32)
const char *zChRoot; /* Use for chroot instead of repository path */
int noJail; /* Do not enter the chroot jail */
const char *zTimeout = 0; /* Max runtime of any single HTTP request */
#endif
int allowRepoList; /* List repositories on URL "/" */
const char *zAltBase; /* Argument to the --baseurl option */
const char *zFileGlob; /* Static content must match this */
char *zIpAddr = 0; /* Bind to this IP address */
|
| ︙ | ︙ | |||
2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 |
dehttpize(z);
zFileGlob = z;
}else{
zFileGlob = find_option("files",0,1);
}
skin_override();
#if !defined(_WIN32)
noJail = find_option("nojail",0,0)!=0;
zTimeout = find_option("max-latency",0,1);
#endif
g.useLocalauth = find_option("localauth", 0, 0)!=0;
Th_InitTraceLog();
zPort = find_option("port", "P", 1);
isUiCmd = g.argv[1][0]=='u';
| > | 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 |
dehttpize(z);
zFileGlob = z;
}else{
zFileGlob = find_option("files",0,1);
}
skin_override();
#if !defined(_WIN32)
zChRoot = find_option("chroot",0,1);
noJail = find_option("nojail",0,0)!=0;
zTimeout = find_option("max-latency",0,1);
#endif
g.useLocalauth = find_option("localauth", 0, 0)!=0;
Th_InitTraceLog();
zPort = find_option("port", "P", 1);
isUiCmd = g.argv[1][0]=='u';
|
| ︙ | ︙ | |||
3004 3005 3006 3007 3008 3009 3010 |
fCreate = find_option("create",0,0)!=0;
if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
if( zAltBase ){
set_base_url(zAltBase);
}
g.sslNotAvailable = find_option("nossl", 0, 0)!=0 || isUiCmd;
fNoBrowser = find_option("nobrowser", 0, 0)!=0;
| > | > > > > > > > > > > > > > > > > > > | 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 |
fCreate = find_option("create",0,0)!=0;
if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
if( zAltBase ){
set_base_url(zAltBase);
}
g.sslNotAvailable = find_option("nossl", 0, 0)!=0 || isUiCmd;
fNoBrowser = find_option("nobrowser", 0, 0)!=0;
decode_ssl_options();
if( find_option("https",0,0)!=0 || g.httpUseSSL ){
cgi_replace_parameter("HTTPS","on");
}
if( find_option("localhost", 0, 0)!=0 ){
flags |= HTTP_SERVER_LOCALHOST;
}
g.zCkoutAlias = find_option("ckout-alias",0,1);
g.zMainMenuFile = find_option("mainmenu",0,1);
if( g.zMainMenuFile!=0 && file_size(g.zMainMenuFile,ExtFILE)<0 ){
fossil_fatal("Cannot read --mainmenu file %s", g.zMainMenuFile);
}
if( find_option("acme",0,0)!=0 ) g.fAllowACME = 1;
/* Undocumented option: --debug-nofork
**
** This sets the HTTP_SERVER_NOFORK flag, which causes only the
** very first incoming TCP/IP connection to be processed. Used for
** debugging, since debugging across a fork() can be tricky
*/
if( find_option("debug-nofork",0,0)!=0 ){
flags |= HTTP_SERVER_NOFORK;
#if !defined(_WIN32)
/* Disable the timeout during debugging */
zTimeout = "100000000";
#endif
}
/* We should be done with options.. */
verify_all_options();
if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
if( g.httpUseSSL && (flags & HTTP_SERVER_SCGI)!=0 ){
fossil_fatal("SCGI does not (yet) support TLS-encrypted connections");
}
if( isUiCmd && 3==g.argc && file_isdir(g.argv[2], ExtFILE)>0 ){
/* If REPOSITORY arg is the root of a checkout,
** chdir to that checkout so that the current version
** gets highlighted in the timeline by default. */
const char * zDir = g.argv[2];
if(dir_has_ckout_db(zDir)){
if(0!=file_chdir(zDir, 0)){
|
| ︙ | ︙ | |||
3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 |
iPort = mxPort = atoi(zPort);
}else{
iPort = db_get_int("http-port", 8080);
mxPort = iPort+100;
}
if( isUiCmd && !fNoBrowser ){
char *zBrowserArg;
if( zRemote ) db_open_config(0,0);
zBrowser = fossil_web_browser();
if( zIpAddr==0 ){
| > | | | | 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 |
iPort = mxPort = atoi(zPort);
}else{
iPort = db_get_int("http-port", 8080);
mxPort = iPort+100;
}
if( isUiCmd && !fNoBrowser ){
char *zBrowserArg;
const char *zProtocol = g.httpUseSSL ? "https" : "http";
if( zRemote ) db_open_config(0,0);
zBrowser = fossil_web_browser();
if( zIpAddr==0 ){
zBrowserArg = mprintf("%s://localhost:%%d/%s", zProtocol, zInitPage);
}else if( strchr(zIpAddr,':') ){
zBrowserArg = mprintf("%s://[%s]:%%d/%s", zProtocol, zIpAddr, zInitPage);
}else{
zBrowserArg = mprintf("%s://%s:%%d/%s", zProtocol, zIpAddr, zInitPage);
}
zBrowserCmd = mprintf("%s %!$ &", zBrowser, zBrowserArg);
fossil_free(zBrowserArg);
}
if( zRemote ){
/* If a USER@HOST:REPO argument is supplied, then use SSH to run
** "fossil ui --nobrowser" on the remote system and to set up a
|
| ︙ | ︙ | |||
3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 |
}
if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
db_close(1);
/* Start up an HTTP server
*/
#if !defined(_WIN32)
/* Unix implementation */
if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
fossil_fatal("unable to listen on TCP socket %d", iPort);
}
/* For the parent process, the cgi_http_server() command above never
** returns (except in the case of an error). Instead, for each incoming
| > > | 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 |
}
if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
db_close(1);
/* Start up an HTTP server
*/
fossil_setenv("SERVER_SOFTWARE", "fossil version " RELEASE_VERSION
" " MANIFEST_VERSION " " MANIFEST_DATE);
#if !defined(_WIN32)
/* Unix implementation */
if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
fossil_fatal("unable to listen on TCP socket %d", iPort);
}
/* For the parent process, the cgi_http_server() command above never
** returns (except in the case of an error). Instead, for each incoming
|
| ︙ | ︙ | |||
3174 3175 3176 3177 3178 3179 3180 |
fprintf(stderr, "/***** Subprocess %d *****/\n", getpid());
}
g.cgiOutput = 1;
find_server_repository(2, 0);
if( fossil_strcmp(g.zRepositoryName,"/")==0 ){
allowRepoList = 1;
}else{
| > > > | > > > > > > > > > > > > > | | 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 |
fprintf(stderr, "/***** Subprocess %d *****/\n", getpid());
}
g.cgiOutput = 1;
find_server_repository(2, 0);
if( fossil_strcmp(g.zRepositoryName,"/")==0 ){
allowRepoList = 1;
}else{
if( zChRoot ){
enter_chroot_jail((char*)zChRoot, noJail);
}else{
g.zRepositoryName = enter_chroot_jail(g.zRepositoryName, noJail);
}
}
if( flags & HTTP_SERVER_SCGI ){
cgi_handle_scgi_request();
}else if( g.httpUseSSL ){
#if FOSSIL_ENABLE_SSL
g.httpSSLConn = ssl_new_server(0);
#endif
cgi_handle_http_request(0);
}else{
cgi_handle_http_request(0);
}
process_one_web_page(zNotFound, glob_create(zFileGlob), allowRepoList);
if( g.fAnyTrace ){
fprintf(stderr, "/***** Webpage finished in subprocess %d *****/\n",
getpid());
}
#if FOSSIL_ENABLE_SSL
if( g.httpUseSSL && g.httpSSLConn ){
ssl_close_server(g.httpSSLConn);
g.httpSSLConn = 0;
}
#endif /* FOSSIL_ENABLE_SSL */
#else /* WIN32 */
/* Win32 implementation */
if( allowRepoList ){
flags |= HTTP_SERVER_REPOLIST;
}
if( win32_http_service(iPort, zAltBase, zNotFound, zFileGlob, flags) ){
win32_http_server(iPort, mxPort, zBrowserCmd, zStopperFile,
zAltBase, zNotFound, zFileGlob, zIpAddr, flags);
|
| ︙ | ︙ |
Changes to src/main.mk.
1 2 | # ############################################################################## | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # ############################################################################## # WARNING: DO NOT EDIT, AUTOMATICALLY GENERATED FILE (SEE "tools/makemake.tcl") ############################################################################## # # This file is automatically generated. Instead of editing this # file, edit "makemake.tcl" then run "tclsh makemake.tcl" # to regenerate this file. # # This file is included by primary Makefile. # XBCC = $(BCC) $(BCCFLAGS) XTCC = $(TCC) $(CFLAGS_INCLUDE) -I$(OBJDIR) $(TCCFLAGS) TESTFLAGS := -quiet SRC = \ $(SRCDIR)/add.c \ $(SRCDIR)/ajax.c \ $(SRCDIR)/alerts.c \ |
| ︙ | ︙ | |||
105 106 107 108 109 110 111 | $(SRCDIR)/merge.c \ $(SRCDIR)/merge3.c \ $(SRCDIR)/moderate.c \ $(SRCDIR)/name.c \ $(SRCDIR)/patch.c \ $(SRCDIR)/path.c \ $(SRCDIR)/piechart.c \ | < | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | $(SRCDIR)/merge.c \ $(SRCDIR)/merge3.c \ $(SRCDIR)/moderate.c \ $(SRCDIR)/name.c \ $(SRCDIR)/patch.c \ $(SRCDIR)/path.c \ $(SRCDIR)/piechart.c \ $(SRCDIR)/pikchrshow.c \ $(SRCDIR)/pivot.c \ $(SRCDIR)/popen.c \ $(SRCDIR)/pqueue.c \ $(SRCDIR)/printf.c \ $(SRCDIR)/publish.c \ $(SRCDIR)/purge.c \ |
| ︙ | ︙ | |||
365 366 367 368 369 370 371 | $(OBJDIR)/merge_.c \ $(OBJDIR)/merge3_.c \ $(OBJDIR)/moderate_.c \ $(OBJDIR)/name_.c \ $(OBJDIR)/patch_.c \ $(OBJDIR)/path_.c \ $(OBJDIR)/piechart_.c \ | < | 364 365 366 367 368 369 370 371 372 373 374 375 376 377 | $(OBJDIR)/merge_.c \ $(OBJDIR)/merge3_.c \ $(OBJDIR)/moderate_.c \ $(OBJDIR)/name_.c \ $(OBJDIR)/patch_.c \ $(OBJDIR)/path_.c \ $(OBJDIR)/piechart_.c \ $(OBJDIR)/pikchrshow_.c \ $(OBJDIR)/pivot_.c \ $(OBJDIR)/popen_.c \ $(OBJDIR)/pqueue_.c \ $(OBJDIR)/printf_.c \ $(OBJDIR)/publish_.c \ $(OBJDIR)/purge_.c \ |
| ︙ | ︙ | |||
515 516 517 518 519 520 521 | $(OBJDIR)/merge.o \ $(OBJDIR)/merge3.o \ $(OBJDIR)/moderate.o \ $(OBJDIR)/name.o \ $(OBJDIR)/patch.o \ $(OBJDIR)/path.o \ $(OBJDIR)/piechart.o \ | < | 513 514 515 516 517 518 519 520 521 522 523 524 525 526 | $(OBJDIR)/merge.o \ $(OBJDIR)/merge3.o \ $(OBJDIR)/moderate.o \ $(OBJDIR)/name.o \ $(OBJDIR)/patch.o \ $(OBJDIR)/path.o \ $(OBJDIR)/piechart.o \ $(OBJDIR)/pikchrshow.o \ $(OBJDIR)/pivot.o \ $(OBJDIR)/popen.o \ $(OBJDIR)/pqueue.o \ $(OBJDIR)/printf.o \ $(OBJDIR)/publish.o \ $(OBJDIR)/purge.o \ |
| ︙ | ︙ | |||
582 583 584 585 586 587 588 | codecheck: $(TRANS_SRC) $(OBJDIR)/codecheck1 $(OBJDIR)/codecheck1 $(TRANS_SRC) $(OBJDIR): -mkdir $(OBJDIR) | | | | | | | | | | | | | | > > < < < < < < < < < < < | | > > > > < < < < < < < | | | | | | > | | | | > | | | < > | 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 |
codecheck: $(TRANS_SRC) $(OBJDIR)/codecheck1
$(OBJDIR)/codecheck1 $(TRANS_SRC)
$(OBJDIR):
-mkdir $(OBJDIR)
$(OBJDIR)/translate: $(SRCDIR_tools)/translate.c
$(XBCC) -o $(OBJDIR)/translate $(SRCDIR_tools)/translate.c
$(OBJDIR)/makeheaders: $(SRCDIR_tools)/makeheaders.c
$(XBCC) -o $(OBJDIR)/makeheaders $(SRCDIR_tools)/makeheaders.c
$(OBJDIR)/mkindex: $(SRCDIR_tools)/mkindex.c
$(XBCC) -o $(OBJDIR)/mkindex $(SRCDIR_tools)/mkindex.c
$(OBJDIR)/mkbuiltin: $(SRCDIR_tools)/mkbuiltin.c
$(XBCC) -o $(OBJDIR)/mkbuiltin $(SRCDIR_tools)/mkbuiltin.c
$(OBJDIR)/mkversion: $(SRCDIR_tools)/mkversion.c
$(XBCC) -o $(OBJDIR)/mkversion $(SRCDIR_tools)/mkversion.c
$(OBJDIR)/codecheck1: $(SRCDIR_tools)/codecheck1.c
$(XBCC) -o $(OBJDIR)/codecheck1 $(SRCDIR_tools)/codecheck1.c
# Run the test suite.
# Other flags that can be included in TESTFLAGS are:
#
# -halt Stop testing after the first failed test
# -keep Keep the temporary workspace for debugging
# -prot Write a detailed log of the tests to the file ./prot
# -verbose Include even more details in the output
# -quiet Hide most output from the terminal
# -strict Treat known bugs as failures
#
# TESTFLAGS can also include names of specific test files to limit
# the run to just those test cases.
#
test: $(OBJDIR) $(APPNAME)
$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS)
$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion $(OBJDIR)/phony.h
$(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid \
$(SRCDIR)/../manifest \
$(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
$(OBJDIR)/phony.h:
# Force rebuild of VERSION.h every time we run "make"
# Setup the options used to compile the included SQLite library.
SQLITE_OPTIONS = -DNDEBUG=1 \
-DSQLITE_DQS=0 \
-DSQLITE_THREADSAFE=0 \
-DSQLITE_DEFAULT_MEMSTATUS=0 \
-DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \
-DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
-DSQLITE_OMIT_DECLTYPE \
-DSQLITE_OMIT_DEPRECATED \
-DSQLITE_OMIT_PROGRESS_CALLBACK \
-DSQLITE_OMIT_SHARED_CACHE \
-DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_MAX_EXPR_DEPTH=0 \
-DSQLITE_ENABLE_LOCKING_STYLE=0 \
-DSQLITE_DEFAULT_FILE_FORMAT=4 \
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
-DSQLITE_ENABLE_FTS4 \
-DSQLITE_ENABLE_DBSTAT_VTAB \
-DSQLITE_ENABLE_FTS5 \
-DSQLITE_ENABLE_STMTVTAB \
-DSQLITE_HAVE_ZLIB \
-DSQLITE_ENABLE_DBPAGE_VTAB \
-DSQLITE_TRUSTED_SCHEMA=0
# Setup the options used to compile the included SQLite shell.
SHELL_OPTIONS = -DNDEBUG=1 \
-DSQLITE_DQS=0 \
-DSQLITE_THREADSAFE=0 \
-DSQLITE_DEFAULT_MEMSTATUS=0 \
-DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \
-DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
-DSQLITE_OMIT_DECLTYPE \
-DSQLITE_OMIT_DEPRECATED \
-DSQLITE_OMIT_PROGRESS_CALLBACK \
-DSQLITE_OMIT_SHARED_CACHE \
-DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_MAX_EXPR_DEPTH=0 \
-DSQLITE_ENABLE_LOCKING_STYLE=0 \
-DSQLITE_DEFAULT_FILE_FORMAT=4 \
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
-DSQLITE_ENABLE_FTS4 \
-DSQLITE_ENABLE_DBSTAT_VTAB \
-DSQLITE_ENABLE_FTS5 \
-DSQLITE_ENABLE_STMTVTAB \
-DSQLITE_HAVE_ZLIB \
-DSQLITE_ENABLE_DBPAGE_VTAB \
-DSQLITE_TRUSTED_SCHEMA=0 \
-Dmain=sqlite3_shell \
-DSQLITE_SHELL_IS_UTF8=1 \
-DSQLITE_OMIT_LOAD_EXTENSION=1 \
-DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
-DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname \
-DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc
# The USE_SYSTEM_SQLITE variable may be undefined, set to 0 or 1.
# If it is set to 1, then there is no need to build or link
# the sqlite3.o object. Instead, the system SQLite will be linked
# using -lsqlite3.
#
# Closely related is SQLITE3_ORIGIN, with the same numeric mapping plus
# a value of 2 means that we are building a client-provided sqlite3.c.
SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
SQLITE3_OBJ.1 =
# SQLITE3_OBJ.2 is set by the configure process
SQLITE3_OBJ. = $(SQLITE3_OBJ.0)
# The USE_LINENOISE variable may be undefined, set to 0, or set
# to 1. If it is set to 0, then there is no need to build or link
# the linenoise.o object.
LINENOISE_DEF.0 =
LINENOISE_DEF.1 = -DHAVE_LINENOISE
LINENOISE_DEF. = $(LINENOISE_DEF.0)
LINENOISE_OBJ.0 =
LINENOISE_OBJ.1 = $(OBJDIR)/linenoise.o
LINENOISE_OBJ. = $(LINENOISE_OBJ.0)
# The USE_SEE variable may be undefined, 0 or 1. If undefined or 0,
# in-tree SQLite is used. If 1, then sqlite3-see.c (not part of the
# source tree) is used and extra flags are provided to enable the
# SQLite Encryption Extension.
SQLITE3_SRC.0 = $(SRCDIR_extsrc)/sqlite3.c
SQLITE3_SRC.1 = $(SRCDIR_extsrc)/sqlite3-see.c
# SQLITE3_SRC.2 is set by top-level configure/makefile process.
SQLITE3_SRC. = $(SRCDIR_extsrc)/sqlite3.c
SQLITE3_SRC = $(SQLITE3_SRC.$(SQLITE3_ORIGIN))
SQLITE3_SHELL_SRC.0 = $(SRCDIR_extsrc)/shell.c
SQLITE3_SHELL_SRC.1 = $(SRCDIR_extsrc)/shell-see.c
# SQLITE3_SHELL_SRC.2 comes from the configure process
SQLITE3_SHELL_SRC. = $(SRCDIR_extsrc)/shell.c
SQLITE3_SHELL_SRC = $(SQLITE3_SHELL_SRC.$(SQLITE3_ORIGIN))
SEE_FLAGS.0 =
SEE_FLAGS.1 = -DSQLITE_HAS_CODEC -DSQLITE_SHELL_DBKEY_PROC=fossil_key
SEE_FLAGS. =
SEE_FLAGS = $(SEE_FLAGS.$(USE_SEE))
EXTRAOBJ = \
$(SQLITE3_OBJ.$(SQLITE3_ORIGIN)) \
$(LINENOISE_OBJ.$(USE_LINENOISE)) \
$(OBJDIR)/pikchr.o \
$(OBJDIR)/shell.o \
$(OBJDIR)/th.o \
$(OBJDIR)/th_lang.o \
$(OBJDIR)/th_tcl.o \
$(OBJDIR)/cson_amalgamation.o
|
| ︙ | ︙ | |||
855 856 857 858 859 860 861 | $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \ $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \ $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \ $(OBJDIR)/name_.c:$(OBJDIR)/name.h \ $(OBJDIR)/patch_.c:$(OBJDIR)/patch.h \ $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ $(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \ | < | 842 843 844 845 846 847 848 849 850 851 852 853 854 855 | $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \ $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \ $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \ $(OBJDIR)/name_.c:$(OBJDIR)/name.h \ $(OBJDIR)/patch_.c:$(OBJDIR)/patch.h \ $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ $(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \ $(OBJDIR)/pikchrshow_.c:$(OBJDIR)/pikchrshow.h \ $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ $(OBJDIR)/publish_.c:$(OBJDIR)/publish.h \ $(OBJDIR)/purge_.c:$(OBJDIR)/purge.h \ |
| ︙ | ︙ | |||
910 911 912 913 914 915 916 | $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h \ $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h \ $(OBJDIR)/winfile_.c:$(OBJDIR)/winfile.h \ $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h \ $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h \ $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h \ $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h \ | > | | 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 | $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h \ $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h \ $(OBJDIR)/winfile_.c:$(OBJDIR)/winfile.h \ $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h \ $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h \ $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h \ $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h \ $(SRCDIR_extsrc)/pikchr.c:$(OBJDIR)/pikchr.h \ $(SRCDIR_extsrc)/sqlite3.h \ $(SRCDIR)/th.h \ $(OBJDIR)/VERSION.h touch $(OBJDIR)/headers $(OBJDIR)/headers: Makefile $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/json_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_status.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h Makefile: $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate |
| ︙ | ︙ | |||
1661 1662 1663 1664 1665 1666 1667 | $(OBJDIR)/translate $(SRCDIR)/piechart.c >$@ $(OBJDIR)/piechart.o: $(OBJDIR)/piechart_.c $(OBJDIR)/piechart.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/piechart.o -c $(OBJDIR)/piechart_.c $(OBJDIR)/piechart.h: $(OBJDIR)/headers | < < < < < < < < | 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 | $(OBJDIR)/translate $(SRCDIR)/piechart.c >$@ $(OBJDIR)/piechart.o: $(OBJDIR)/piechart_.c $(OBJDIR)/piechart.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/piechart.o -c $(OBJDIR)/piechart_.c $(OBJDIR)/piechart.h: $(OBJDIR)/headers $(OBJDIR)/pikchrshow_.c: $(SRCDIR)/pikchrshow.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/pikchrshow.c >$@ $(OBJDIR)/pikchrshow.o: $(OBJDIR)/pikchrshow_.c $(OBJDIR)/pikchrshow.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/pikchrshow.o -c $(OBJDIR)/pikchrshow_.c $(OBJDIR)/pikchrshow.h: $(OBJDIR)/headers |
| ︙ | ︙ | |||
2104 2105 2106 2107 2108 2109 2110 | $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c $(OBJDIR)/zip.h: $(OBJDIR)/headers $(OBJDIR)/sqlite3.o: $(SQLITE3_SRC) $(XTCC) $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $(SEE_FLAGS) \ -c $(SQLITE3_SRC) -o $@ | | | | | | | | | 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 | $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c $(OBJDIR)/zip.h: $(OBJDIR)/headers $(OBJDIR)/sqlite3.o: $(SQLITE3_SRC) $(XTCC) $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $(SEE_FLAGS) \ -c $(SQLITE3_SRC) -o $@ $(OBJDIR)/shell.o: $(SQLITE3_SHELL_SRC) $(SRCDIR_extsrc)/sqlite3.h $(XTCC) $(SHELL_OPTIONS) $(SHELL_CFLAGS) $(SEE_FLAGS) $(LINENOISE_DEF.$(USE_LINENOISE)) -c $(SQLITE3_SHELL_SRC) -o $@ $(OBJDIR)/linenoise.o: $(SRCDIR_extsrc)/linenoise.c $(SRCDIR_extsrc)/linenoise.h $(XTCC) -c $(SRCDIR_extsrc)/linenoise.c -o $@ $(OBJDIR)/th.o: $(SRCDIR)/th.c $(XTCC) -c $(SRCDIR)/th.c -o $@ $(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c $(XTCC) -c $(SRCDIR)/th_lang.c -o $@ $(OBJDIR)/th_tcl.o: $(SRCDIR)/th_tcl.c $(XTCC) -c $(SRCDIR)/th_tcl.c -o $@ $(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c $(XTCC) -c $(SRCDIR_extsrc)/pikchr.c -o $@ $(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c $(XTCC) -c $(SRCDIR_extsrc)/cson_amalgamation.c -o $@ # # The list of all the targets that do not correspond to real files. This stops # 'make' from getting confused when someone makes an error in a rule. # .PHONY: all install test clean |
Changes to src/md5.c.
| ︙ | ︙ | |||
20 21 22 23 24 25 26 | */ #include "config.h" #include <string.h> #include <stdio.h> #include <sqlite3.h> #include "md5.h" | | > > > | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | */ #include "config.h" #include <string.h> #include <stdio.h> #include <sqlite3.h> #include "md5.h" #if 0 /* defined FOSSIL_ENABLE_SSL */ /* MD5 is deprecated in OpenSSL. So we have to fall back to our own ** implementation */ # include <openssl/md5.h> # define MD5Context MD5_CTX # define MD5Init MD5_Init # define MD5Update MD5_Update # define MD5Final MD5_Final |
| ︙ | ︙ |
Changes to src/merge.c.
| ︙ | ︙ | |||
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 | db_must_be_within_tree(); debug_show_vfile(); } /* ** COMMAND: merge ** ** Usage: %fossil merge ?OPTIONS? ?VERSION? ** ** The argument VERSION is a version that should be merged into the ** current checkout. All changes from VERSION back to the nearest ** common ancestor are merged. Except, if either of the --cherrypick or ** --backout options are used only the changes associated with the ** single check-in VERSION are merged. The --backout option causes ** the changes associated with VERSION to be removed from the current | > | > | 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 | db_must_be_within_tree(); debug_show_vfile(); } /* ** COMMAND: merge ** COMMAND: cherry-pick ** ** Usage: %fossil merge ?OPTIONS? ?VERSION? ** ** The argument VERSION is a version that should be merged into the ** current checkout. All changes from VERSION back to the nearest ** common ancestor are merged. Except, if either of the --cherrypick or ** --backout options are used only the changes associated with the ** single check-in VERSION are merged. The --backout option causes ** the changes associated with VERSION to be removed from the current ** checkout rather than added. When invoked with the name cherry-pick, ** this command works exactly like merge --cherrypick. ** ** If the VERSION argument is omitted, then Fossil attempts to find ** a recent fork on the current branch to merge. ** ** Only file content is merged. The result continues to use the ** file and directory names from the current checkout even if those ** names might have been changed in the branch being merged in. |
| ︙ | ︙ | |||
305 306 307 308 309 310 311 | ** a sequence of changes in a branch to be merged ** without having to merge the entire branch. ** ** --binary GLOBPATTERN Treat files that match GLOBPATTERN as binary ** and do not try to merge parallel changes. This ** option overrides the "binary-glob" setting. ** | < < < < | 307 308 309 310 311 312 313 314 315 316 317 318 319 320 | ** a sequence of changes in a branch to be merged ** without having to merge the entire branch. ** ** --binary GLOBPATTERN Treat files that match GLOBPATTERN as binary ** and do not try to merge parallel changes. This ** option overrides the "binary-glob" setting. ** ** --cherrypick Do a cherrypick merge VERSION into the current ** checkout. A cherrypick merge pulls in the changes ** of the single check-in VERSION, rather than all ** changes back to the nearest common ancestor. ** ** -f|--force Force the merge even if it would be a no-op. ** |
| ︙ | ︙ | |||
366 367 368 369 370 371 372 373 374 375 376 377 378 379 |
undo_capture_command_line();
verboseFlag = find_option("verbose","v",0)!=0;
forceMissingFlag = find_option("force-missing",0,0)!=0;
if( !verboseFlag ){
verboseFlag = find_option("detail",0,0)!=0; /* deprecated */
}
pickFlag = find_option("cherrypick",0,0)!=0;
integrateFlag = find_option("integrate",0,0)!=0;
backoutFlag = find_option("backout",0,0)!=0;
zBinGlob = find_option("binary",0,1);
dryRunFlag = find_option("dry-run","n",0)!=0;
if( !dryRunFlag ){
dryRunFlag = find_option("nochange",0,0)!=0; /* deprecated */
}
| > > > | 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
undo_capture_command_line();
verboseFlag = find_option("verbose","v",0)!=0;
forceMissingFlag = find_option("force-missing",0,0)!=0;
if( !verboseFlag ){
verboseFlag = find_option("detail",0,0)!=0; /* deprecated */
}
pickFlag = find_option("cherrypick",0,0)!=0;
if('c'==*g.zCmdName/*called as cherry-pick, possibly a short form*/){
pickFlag = 1;
}
integrateFlag = find_option("integrate",0,0)!=0;
backoutFlag = find_option("backout",0,0)!=0;
zBinGlob = find_option("binary",0,1);
dryRunFlag = find_option("dry-run","n",0)!=0;
if( !dryRunFlag ){
dryRunFlag = find_option("nochange",0,0)!=0; /* deprecated */
}
|
| ︙ | ︙ |
Changes to src/merge3.c.
| ︙ | ︙ | |||
114 115 116 117 118 119 120 | ** The aC[] array is updated and the new index into aC[] is returned. */ static int output_one_side( Blob *pOut, /* Write to this blob */ Blob *pSrc, /* The edited file that is to be copied to pOut */ int *aC, /* Array of integer triples describing the edit */ int i, /* Index in aC[] of current location in pSrc */ | | > | | | | | | | | 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
** The aC[] array is updated and the new index into aC[] is returned.
*/
static int output_one_side(
Blob *pOut, /* Write to this blob */
Blob *pSrc, /* The edited file that is to be copied to pOut */
int *aC, /* Array of integer triples describing the edit */
int i, /* Index in aC[] of current location in pSrc */
int sz, /* Number of lines in unedited source to output */
int *pLn /* Line number counter */
){
while( sz>0 ){
if( aC[i]==0 && aC[i+1]==0 && aC[i+2]==0 ) break;
if( aC[i]>=sz ){
blob_copy_lines(pOut, pSrc, sz); *pLn += sz;
aC[i] -= sz;
break;
}
blob_copy_lines(pOut, pSrc, aC[i]); *pLn += aC[i];
blob_copy_lines(pOut, pSrc, aC[i+2]); *pLn += aC[i+2];
sz -= aC[i] + aC[i+1];
i += 3;
}
return i;
}
/*
** Text of boundary markers for merge conflicts.
*/
static const char *const mergeMarker[] = {
/*123456789 123456789 123456789 123456789 123456789 123456789 123456789*/
"<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<",
"||||||| COMMON ANCESTOR content follows |||||||||||||||||||||||||",
"======= MERGED IN content follows ===============================",
">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
};
/*
** Return true if the input blob contains any CR/LF pairs on the first
** ten lines. This should be enough to detect files that use mainly CR/LF
** line endings without causing a performance impact for LF only files.
*/
|
| ︙ | ︙ | |||
173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
void ensure_line_end(Blob *pBlob, int useCrLf){
if( pBlob->nUsed<=0 ) return;
if( pBlob->aData[pBlob->nUsed-1]!='\n' ){
if( useCrLf ) blob_append_char(pBlob, '\r');
blob_append_char(pBlob, '\n');
}
}
/*
** Do a three-way merge. Initialize pOut to contain the result.
**
** The merge is an edit against pV2. Both pV1 and pV2 have a
** common origin at pPivot. Apply the changes of pPivot ==> pV1
** to pV2.
| > > > > > > > > > > | 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
void ensure_line_end(Blob *pBlob, int useCrLf){
if( pBlob->nUsed<=0 ) return;
if( pBlob->aData[pBlob->nUsed-1]!='\n' ){
if( useCrLf ) blob_append_char(pBlob, '\r');
blob_append_char(pBlob, '\n');
}
}
/*
** Write out one of the four merge-marks.
*/
void append_merge_mark(Blob *pOut, int iMark, int ln, int useCrLf){
ensure_line_end(pOut, useCrLf);
blob_append(pOut, mergeMarker[iMark], -1);
if( ln>0 ) blob_appendf(pOut, " (line %d)", ln);
ensure_line_end(pOut, useCrLf);
}
/*
** Do a three-way merge. Initialize pOut to contain the result.
**
** The merge is an edit against pV2. Both pV1 and pV2 have a
** common origin at pPivot. Apply the changes of pPivot ==> pV1
** to pV2.
|
| ︙ | ︙ | |||
194 195 196 197 198 199 200 201 202 203 204 205 206 207 | int *aC1; /* Changes from pPivot to pV1 */ int *aC2; /* Changes from pPivot to pV2 */ int i1, i2; /* Index into aC1[] and aC2[] */ int nCpy, nDel, nIns; /* Number of lines to copy, delete, or insert */ int limit1, limit2; /* Sizes of aC1[] and aC2[] */ int nConflict = 0; /* Number of merge conflicts seen so far */ int useCrLf = 0; DiffConfig DCfg; blob_zero(pOut); /* Merge results stored in pOut */ /* If both pV1 and pV2 start with a UTF-8 byte-order-mark (BOM), ** keep it in the output. This should be secure enough not to cause ** unintended changes to the merged file and consistent with what | > | 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | int *aC1; /* Changes from pPivot to pV1 */ int *aC2; /* Changes from pPivot to pV2 */ int i1, i2; /* Index into aC1[] and aC2[] */ int nCpy, nDel, nIns; /* Number of lines to copy, delete, or insert */ int limit1, limit2; /* Sizes of aC1[] and aC2[] */ int nConflict = 0; /* Number of merge conflicts seen so far */ int useCrLf = 0; int ln1, ln2, lnPivot; /* Line numbers for all files */ DiffConfig DCfg; blob_zero(pOut); /* Merge results stored in pOut */ /* If both pV1 and pV2 start with a UTF-8 byte-order-mark (BOM), ** keep it in the output. This should be secure enough not to cause ** unintended changes to the merged file and consistent with what |
| ︙ | ︙ | |||
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
/* Loop over the two edit vectors and use them to compute merged text
** which is written into pOut. i1 and i2 are multiples of 3 which are
** indices into aC1[] and aC2[] to the edit triple currently being
** processed
*/
i1 = i2 = 0;
while( i1<limit1 && i2<limit2 ){
DEBUG( printf("%d: %2d %2d %2d %d: %2d %2d %2d\n",
i1/3, aC1[i1], aC1[i1+1], aC1[i1+2],
i2/3, aC2[i2], aC2[i2+1], aC2[i2+2]); )
if( aC1[i1]>0 && aC2[i2]>0 ){
/* Output text that is unchanged in both V1 and V2 */
nCpy = min(aC1[i1], aC2[i2]);
DEBUG( printf("COPY %d\n", nCpy); )
| > | | | | | | | | | | | | | < | | | < | | | < | | | < | | 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 |
/* Loop over the two edit vectors and use them to compute merged text
** which is written into pOut. i1 and i2 are multiples of 3 which are
** indices into aC1[] and aC2[] to the edit triple currently being
** processed
*/
i1 = i2 = 0;
ln1 = ln2 = lnPivot = 1;
while( i1<limit1 && i2<limit2 ){
DEBUG( printf("%d: %2d %2d %2d %d: %2d %2d %2d\n",
i1/3, aC1[i1], aC1[i1+1], aC1[i1+2],
i2/3, aC2[i2], aC2[i2+1], aC2[i2+2]); )
if( aC1[i1]>0 && aC2[i2]>0 ){
/* Output text that is unchanged in both V1 and V2 */
nCpy = min(aC1[i1], aC2[i2]);
DEBUG( printf("COPY %d\n", nCpy); )
blob_copy_lines(pOut, pPivot, nCpy); lnPivot += nCpy;
blob_copy_lines(0, pV1, nCpy); ln1 += nCpy;
blob_copy_lines(0, pV2, nCpy); ln2 += nCpy;
aC1[i1] -= nCpy;
aC2[i2] -= nCpy;
}else
if( aC1[i1] >= aC2[i2+1] && aC1[i1]>0 && aC2[i2+1]+aC2[i2+2]>0 ){
/* Output edits to V2 that occurs within unchanged regions of V1 */
nDel = aC2[i2+1];
nIns = aC2[i2+2];
DEBUG( printf("EDIT -%d+%d left\n", nDel, nIns); )
blob_copy_lines(0, pPivot, nDel); lnPivot += nDel;
blob_copy_lines(0, pV1, nDel); ln1 += nDel;
blob_copy_lines(pOut, pV2, nIns); ln2 += nIns;
aC1[i1] -= nDel;
i2 += 3;
}else
if( aC2[i2] >= aC1[i1+1] && aC2[i2]>0 && aC1[i1+1]+aC1[i1+2]>0 ){
/* Output edits to V1 that occur within unchanged regions of V2 */
nDel = aC1[i1+1];
nIns = aC1[i1+2];
DEBUG( printf("EDIT -%d+%d right\n", nDel, nIns); )
blob_copy_lines(0, pPivot, nDel); lnPivot += nDel;
blob_copy_lines(0, pV2, nDel); ln2 += nDel;
blob_copy_lines(pOut, pV1, nIns); ln1 += nIns;
aC2[i2] -= nDel;
i1 += 3;
}else
if( sameEdit(&aC1[i1], &aC2[i2], pV1, pV2) ){
/* Output edits that are identical in both V1 and V2. */
assert( aC1[i1]==0 );
nDel = aC1[i1+1];
nIns = aC1[i1+2];
DEBUG( printf("EDIT -%d+%d both\n", nDel, nIns); )
blob_copy_lines(0, pPivot, nDel); lnPivot += nDel;
blob_copy_lines(pOut, pV1, nIns); ln1 += nIns;
blob_copy_lines(0, pV2, nIns); ln2 += nIns;
i1 += 3;
i2 += 3;
}else
{
/* We have found a region where different edits to V1 and V2 overlap.
** This is a merge conflict. Find the size of the conflict, then
** output both possible edits separated by distinctive marks.
*/
int sz = 1; /* Size of the conflict in lines */
nConflict++;
while( !ends_at_CPY(&aC1[i1], sz) || !ends_at_CPY(&aC2[i2], sz) ){
sz++;
}
DEBUG( printf("CONFLICT %d\n", sz); )
append_merge_mark(pOut, 0, ln1, useCrLf);
i1 = output_one_side(pOut, pV1, aC1, i1, sz, &ln1);
append_merge_mark(pOut, 1, lnPivot, useCrLf);
blob_copy_lines(pOut, pPivot, sz); lnPivot += sz;
append_merge_mark(pOut, 2, ln2, useCrLf);
i2 = output_one_side(pOut, pV2, aC2, i2, sz, &ln2);
append_merge_mark(pOut, 3, -1, useCrLf);
}
/* If we are finished with an edit triple, advance to the next
** triple.
*/
if( i1<limit1 && aC1[i1]==0 && aC1[i1+1]==0 && aC1[i1+2]==0 ) i1+=3;
if( i2<limit2 && aC2[i2]==0 && aC2[i2+1]==0 && aC2[i2+2]==0 ) i2+=3;
|
| ︙ | ︙ | |||
376 377 378 379 380 381 382 |
int n = blob_size(p) - len + 1;
assert( len==(int)strlen(mergeMarker[1]) );
assert( len==(int)strlen(mergeMarker[2]) );
assert( len==(int)strlen(mergeMarker[3]) );
assert( count(mergeMarker)==4 );
for(i=0; i<n; ){
for(j=0; j<4; j++){
| | | > | 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 |
int n = blob_size(p) - len + 1;
assert( len==(int)strlen(mergeMarker[1]) );
assert( len==(int)strlen(mergeMarker[2]) );
assert( len==(int)strlen(mergeMarker[3]) );
assert( count(mergeMarker)==4 );
for(i=0; i<n; ){
for(j=0; j<4; j++){
if( (memcmp(&z[i], mergeMarker[j], len)==0) ){
return 1;
}
}
while( i<n && z[i]!='\n' ){ i++; }
while( i<n && (z[i]=='\n' || z[i]=='\r') ){ i++; }
}
return 0;
}
|
| ︙ | ︙ |
Deleted src/miniz.c.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to src/piechart.c.
| ︙ | ︙ | |||
154 155 156 157 158 159 160 |
rTooSmall = 0.0;
nTooSmall = 0;
if( (pieFlags & PIE_OTHER)!=0 && nTotal>1 ){
db_prepare(&q, "SELECT sum(amt), count(*) FROM piechart WHERE amt<:amt");
db_bind_double(&q, ":amt", rTotal/OTHER_CUTOFF);
if( db_step(&q)==SQLITE_ROW ){
rTooSmall = db_column_double(&q, 0);
| | | 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
rTooSmall = 0.0;
nTooSmall = 0;
if( (pieFlags & PIE_OTHER)!=0 && nTotal>1 ){
db_prepare(&q, "SELECT sum(amt), count(*) FROM piechart WHERE amt<:amt");
db_bind_double(&q, ":amt", rTotal/OTHER_CUTOFF);
if( db_step(&q)==SQLITE_ROW ){
rTooSmall = db_column_double(&q, 0);
nTooSmall = db_column_int(&q, 1);
}
db_finalize(&q);
}
if( nTooSmall>1 ){
db_prepare(&q, "SELECT amt, label FROM piechart WHERE amt>=:limit"
" UNION ALL SELECT %.17g, '%d others';",
rTooSmall, nTooSmall);
|
| ︙ | ︙ |
Changes to src/pivot.c.
| ︙ | ︙ | |||
60 61 62 63 64 65 66 |
/*
** Set a secondary file. The primary file must be set first. There
** must be at least one secondary but there can be more than one if
** desired.
*/
void pivot_set_secondary(int rid){
| | | 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
/*
** Set a secondary file. The primary file must be set first. There
** must be at least one secondary but there can be more than one if
** desired.
*/
void pivot_set_secondary(int rid){
/* Insert the secondary record */
db_multi_exec(
"INSERT OR IGNORE INTO aqueue(rid, mtime, pending, src)"
" SELECT %d, mtime, 1, 0 FROM event WHERE objid=%d AND type='ci'",
rid, rid
);
}
|
| ︙ | ︙ |
Changes to src/rebuild.c.
| ︙ | ︙ | |||
366 367 368 369 370 371 372 |
/*
** Core function to rebuild the information in the derived tables of a
** fossil repository from the blobs. This function is shared between
** 'rebuild_database' ('rebuild') and 'reconstruct_cmd'
** ('reconstruct'), both of which have to regenerate this information
** from scratch.
| < < < < < | | 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 |
/*
** Core function to rebuild the information in the derived tables of a
** fossil repository from the blobs. This function is shared between
** 'rebuild_database' ('rebuild') and 'reconstruct_cmd'
** ('reconstruct'), both of which have to regenerate this information
** from scratch.
*/
int rebuild_db(int doOut, int doClustering){
Stmt s, q;
int errCnt = 0;
int incrSize;
Blob sql;
bag_clear(&bagDone);
ttyOutput = doOut;
|
| ︙ | ︙ | |||
603 604 605 606 607 608 609 | ** --force Force the rebuild to complete even if errors are seen ** --ifneeded Only do the rebuild if it would change the schema version ** --index Always add in the full-text search index ** --noverify Skip the verification of changes to the BLOB table ** --noindex Always omit the full-text search index ** --pagesize N Set the database pagesize to N. (512..65536 and power of 2) ** --quiet Only show output if there are errors | < < < | 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 |
** --force Force the rebuild to complete even if errors are seen
** --ifneeded Only do the rebuild if it would change the schema version
** --index Always add in the full-text search index
** --noverify Skip the verification of changes to the BLOB table
** --noindex Always omit the full-text search index
** --pagesize N Set the database pagesize to N. (512..65536 and power of 2)
** --quiet Only show output if there are errors
** --stats Show artifact statistics after rebuilding
** --vacuum Run VACUUM on the database after rebuilding
** --wal Set Write-Ahead-Log journalling mode on the database
*/
void rebuild_database(void){
int forceFlag;
int errCnt = 0;
int omitVerify;
int doClustering;
const char *zPagesize;
int newPagesize = 0;
int activateWal;
int runVacuum;
int runDeanalyze;
int runAnalyze;
int runCompress;
int showStats;
int runReindex;
int optNoIndex;
int optIndex;
int optIfNeeded;
int compressOnlyFlag;
omitVerify = find_option("noverify",0,0)!=0;
forceFlag = find_option("force","f",0)!=0;
doClustering = find_option("cluster", 0, 0)!=0;
runVacuum = find_option("vacuum",0,0)!=0;
runDeanalyze = find_option("deanalyze",0,0)!=0;
runAnalyze = find_option("analyze",0,0)!=0;
runCompress = find_option("compress",0,0)!=0;
zPagesize = find_option("pagesize",0,1);
showStats = find_option("stats",0,0)!=0;
|
| ︙ | ︙ | |||
677 678 679 680 681 682 683 |
verify_all_options();
db_begin_transaction();
db_unprotect(PROTECT_ALL);
if( !compressOnlyFlag ){
search_drop_index();
ttyOutput = 1;
| | | 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 |
verify_all_options();
db_begin_transaction();
db_unprotect(PROTECT_ALL);
if( !compressOnlyFlag ){
search_drop_index();
ttyOutput = 1;
errCnt = rebuild_db(1, doClustering);
reconstruct_private_table();
}
db_multi_exec(
"REPLACE INTO config(name,value,mtime) VALUES('content-schema',%Q,now());"
"REPLACE INTO config(name,value,mtime) VALUES('aux-schema',%Q,now());"
"REPLACE INTO config(name,value,mtime) VALUES('rebuilt',%Q,now());",
CONTENT_SCHEMA, AUX_SCHEMA_MAX, get_version()
|
| ︙ | ︙ | |||
751 752 753 754 755 756 757 |
if( k>0 ) subtotal += g.parseCnt[k];
}
fossil_print("%-15s %6d\n", "Other:", g.parseCnt[CFTYPE_ANY] - subtotal);
}
}
/*
| | | | > > > > > > > > > | | > | > > > > > > > > > > > > > > > | > | > > > > | > > > > > > > > > > > > > > > > > | 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 |
if( k>0 ) subtotal += g.parseCnt[k];
}
fossil_print("%-15s %6d\n", "Other:", g.parseCnt[CFTYPE_ANY] - subtotal);
}
}
/*
** COMMAND: detach*
**
** Usage: %fossil detach ?REPOSITORY?
**
** Change the project-code and make other changes to REPOSITORY so that
** it becomes a new and distinct child project. After being detached,
** REPOSITORY will not longer be able to push and pull from other clones
** of the original project. However REPOSITORY will still be able to pull
** from those other clones using the --from-parent-project option of the
** "fossil pull" command.
**
** This is an experts-only command. You should not use this command unless
** you fully understand what you are doing.
**
** The original use-case for this command was to create test repositories
** from real-world working repositories that could be safely altered by
** making strange commits or other changes, without having to worry that
** those test changes would leak back into the original project via an
** accidental auto-sync.
*/
void test_detach_cmd(void){
const char *zXfer[] = {
"project-name", "parent-project-name",
"project-code", "parent-project-code",
"last-sync-url", "parent-project-url",
"last-sync-pw", "parent-project-pw"
};
int i;
Blob ans;
char cReply;
db_find_and_open_repository(0, 2);
prompt_user("This change will be difficult to undo. Are you sure (y/N)? ",
&ans);
cReply = blob_str(&ans)[0];
if( cReply!='y' && cReply!='Y' ) return;
db_begin_transaction();
db_unprotect(PROTECT_CONFIG);
for(i=0; i<ArraySize(zXfer)-1; i+=2 ){
db_multi_exec(
"REPLACE INTO config(name,value,mtime)"
" SELECT %Q, value, now() FROM config WHERE name=%Q",
zXfer[i+1], zXfer[i]
);
}
db_multi_exec(
"DELETE FROM config WHERE name IN"
"(WITH pattern(x) AS (VALUES"
" ('baseurl:*'),"
" ('cert:*'),"
" ('ckout:*'),"
" ('gitpush:*'),"
" ('http-auth:*'),"
" ('last-sync-*'),"
" ('link:*'),"
" ('login-group-*'),"
" ('peer-*'),"
" ('subrepo:*'),"
" ('sync-*'),"
" ('syncfrom:*'),"
" ('syncwith:*'),"
" ('ssl-*')"
") SELECT name FROM config, pattern WHERE name GLOB x);"
"UPDATE config SET value=lower(hex(randomblob(20)))"
" WHERE name='project-code';"
"UPDATE config SET value='detached-' || value"
" WHERE name='project-name' AND value NOT GLOB 'detached-*';"
);
db_protect_pop();
db_end_transaction(0);
fossil_print("New project code: %s\n", db_get("project-code",""));
}
/*
** COMMAND: test-create-clusters
**
** Create clusters for all unclustered artifacts if the number of unclustered
** artifacts exceeds the current clustering threshold.
|
| ︙ | ︙ | |||
922 923 924 925 926 927 928 929 930 931 932 |
if( privateOnly || bVerily ){
bNeedRebuild = db_exists("SELECT 1 FROM private");
delete_private_content();
}
if( !privateOnly ){
db_unprotect(PROTECT_ALL);
db_multi_exec(
"UPDATE user SET pw='';"
"DELETE FROM config WHERE name IN"
"(WITH pattern(x) AS (VALUES"
" ('last-sync-*'),"
| > > > > > > > | < > > | | < | < < | 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 |
if( privateOnly || bVerily ){
bNeedRebuild = db_exists("SELECT 1 FROM private");
delete_private_content();
}
if( !privateOnly ){
db_unprotect(PROTECT_ALL);
db_multi_exec(
"PRAGMA secure_delete=ON;"
"UPDATE user SET pw='';"
"DELETE FROM config WHERE name IN"
"(WITH pattern(x) AS (VALUES"
" ('baseurl:*'),"
" ('cert:*'),"
" ('ckout:*'),"
" ('draft[1-9]-*'),"
" ('gitpush:*'),"
" ('http-auth:*'),"
" ('last-sync-*'),"
" ('link:*'),"
" ('login-group-*'),"
" ('parent-project-*'),"
" ('peer-*'),"
" ('skin:*'),"
" ('subrepo:*'),"
" ('sync-*'),"
" ('syncfrom:*'),"
" ('syncwith:*'),"
" ('ssl-*')"
") SELECT name FROM config, pattern WHERE name GLOB x);"
);
if( bVerily ){
db_multi_exec(
"DELETE FROM concealed;\n"
"UPDATE rcvfrom SET ipaddr='unknown';\n"
"DROP TABLE IF EXISTS accesslog;\n"
|
| ︙ | ︙ | |||
961 962 963 964 965 966 967 |
}
if( !bNeedRebuild ){
db_end_transaction(0);
db_unprotect(PROTECT_ALL);
db_multi_exec("VACUUM;");
db_protect_pop();
}else{
| | | 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 |
}
if( !bNeedRebuild ){
db_end_transaction(0);
db_unprotect(PROTECT_ALL);
db_multi_exec("VACUUM;");
db_protect_pop();
}else{
rebuild_db(1, 0);
db_end_transaction(0);
}
}
/*
** Recursively read all files from the directory zPath and install
** every file read as a new artifact in the repository.
|
| ︙ | ︙ | |||
1253 1254 1255 1256 1257 1258 1259 |
db_begin_transaction();
db_initial_setup(0, 0, 0);
fossil_print("Reading files from directory \"%s\"...\n", g.argv[3]);
recon_read_dir(g.argv[3]);
fossil_print("\nBuilding the Fossil repository...\n");
| | | 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 |
db_begin_transaction();
db_initial_setup(0, 0, 0);
fossil_print("Reading files from directory \"%s\"...\n", g.argv[3]);
recon_read_dir(g.argv[3]);
fossil_print("\nBuilding the Fossil repository...\n");
rebuild_db(1, 1);
/* Backwards compatibility: Mark check-ins with "+private" tags as private. */
reconstruct_private_table();
/* Newer method: Import the list of private artifacts to the PRIVATE table. */
if( fKeepPrivate ){
char *zFnDotPrivate = mprintf("%s/.private", g.argv[3]);
private_import(zFnDotPrivate);
|
| ︙ | ︙ |
Changes to src/repolist.c.
| ︙ | ︙ | |||
254 255 256 257 258 259 260 |
g.zBaseURL = 0;
set_base_url(zNewBase);
db_open_repository(zSkinRepo);
fossil_free(zSkinRepo);
fossil_free(zSkinUrl);
}
if( g.repositoryOpen ){
| | | 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
g.zBaseURL = 0;
set_base_url(zNewBase);
db_open_repository(zSkinRepo);
fossil_free(zSkinRepo);
fossil_free(zSkinUrl);
}
if( g.repositoryOpen ){
/* This case runs if remote_repo_info() found a repository
** that has the "repolist_skin" property set to non-zero and left
** that repository open in g.db. Use the skin of that repository
** for display. */
login_check_credentials();
style_set_current_feature("repolist");
style_header("Repository List");
@ %s(blob_str(&html))
|
| ︙ | ︙ |
Changes to src/security_audit.c.
| ︙ | ︙ | |||
97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
void secaudit0_page(void){
const char *zAnonCap; /* Capabilities of user "anonymous" and "nobody" */
const char *zDevCap; /* Capabilities of user group "developer" */
const char *zReadCap; /* Capabilities of user group "reader" */
const char *zPubPages; /* GLOB pattern for public pages */
const char *zSelfCap; /* Capabilities of self-registered users */
int hasSelfReg = 0; /* True if able to self-register */
char *z;
int n;
CapabilityString *pCap;
char **azCSP; /* Parsed content security policy */
login_check_credentials();
if( !g.perm.Admin ){
| > | 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
void secaudit0_page(void){
const char *zAnonCap; /* Capabilities of user "anonymous" and "nobody" */
const char *zDevCap; /* Capabilities of user group "developer" */
const char *zReadCap; /* Capabilities of user group "reader" */
const char *zPubPages; /* GLOB pattern for public pages */
const char *zSelfCap; /* Capabilities of self-registered users */
int hasSelfReg = 0; /* True if able to self-register */
const char *zPublicUrl; /* Canonical access URL */
char *z;
int n;
CapabilityString *pCap;
char **azCSP; /* Parsed content security policy */
login_check_credentials();
if( !g.perm.Admin ){
|
| ︙ | ︙ | |||
199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
}
@ </ul>
if( zPubPages && zPubPages[0] ){
@ <p>Change GLOB patterns exceptions using the "Public pages" setting
@ on the <a href="setup_access">Access Settings</a> page.</p>
}
}
/* Make sure the HTTPS is required for login, at least, so that the
** password does not go across the Internet in the clear.
*/
if( db_get_int("redirect-to-https",0)==0 ){
@ <li><p><b>WARNING:</b>
@ Sensitive material such as login passwords can be sent over an
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
}
@ </ul>
if( zPubPages && zPubPages[0] ){
@ <p>Change GLOB patterns exceptions using the "Public pages" setting
@ on the <a href="setup_access">Access Settings</a> page.</p>
}
}
zPublicUrl = public_url();
if( zPublicUrl!=0 ){
int nOther = db_int(0, "SELECT count(*) FROM config"
" WHERE name GLOB 'baseurl:*'"
" AND name<>'baseurl:%q'", zPublicUrl);
@ <li><p>The canonical URL for this repository is
@ <a href="%s(zPublicUrl)">%h(zPublicUrl)</a>.
if( nOther==1 ){
@ This is also <a href="urllist?urlonly">1 other URL</a> that has
@ been used to access this repository.
}else if( nOther>=2 ){
@ There are also
@ <a href="urllist?all&urlonly">%d(nOther) other URLs</a> that have
@ been used to access this repository.
}
}else{
int nUrl = db_int(0, "SELECT count(*) FROM config"
" WHERE name GLOB 'baseurl:*'");
@ <li><p>This repository does not have a canonical access URL.
if( nUrl==1 ){
@ There is
@ <a href="urllist?urlonly">1 non-canonical URL</a>
@ that has been used to access this repository.
}else if( nUrl>=2 ){
@ There are
@ <a href="urllist?all&urlonly">%d(nUrl) non-canonical URLs</a>
@ that have been used to access this repository.
}
}
/* Make sure the HTTPS is required for login, at least, so that the
** password does not go across the Internet in the clear.
*/
if( db_get_int("redirect-to-https",0)==0 ){
@ <li><p><b>WARNING:</b>
@ Sensitive material such as login passwords can be sent over an
|
| ︙ | ︙ |
Changes to src/setup.c.
| ︙ | ︙ | |||
1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 |
@ <hr />
textarea_attribute("Project Description", 3, 80,
"project-description", "pd", "", 0);
@ <p>Describe your project. This will be used in page headers for search
@ engines as well as a short RSS description.
@ (Property: "project-description")</p>
@ <hr />
entry_attribute("Tarball and ZIP-archive Prefix", 20, "short-project-name",
"spn", "", 0);
@ <p>This is used as a prefix on the names of generated tarballs and
@ ZIP archive. For best results, keep this prefix brief and avoid special
@ characters such as "/" and "\".
@ If no tarball prefix is specified, then the full Project Name above is used.
@ (Property: "short-project-name")
| > > > > > > > > > > > | 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 |
@ <hr />
textarea_attribute("Project Description", 3, 80,
"project-description", "pd", "", 0);
@ <p>Describe your project. This will be used in page headers for search
@ engines as well as a short RSS description.
@ (Property: "project-description")</p>
@ <hr />
entry_attribute("Canonical Server URL", 40, "email-url",
"eurl", "", 0);
@ <p>This is the URL used access this repository as a server.
@ Other repositories use this URL to clone or sync against this repository.
@ This is also the basename for hyperlinks included in email alert text.
@ Omit the trailing "/".
@ If this repo will not be set up as a persistent server and will not
@ be sending email alerts, then leave this entry blank.
@ Suggested value: "%h(g.zBaseURL)"
@ (Property: "email-url")</p>
@ <hr>
entry_attribute("Tarball and ZIP-archive Prefix", 20, "short-project-name",
"spn", "", 0);
@ <p>This is used as a prefix on the names of generated tarballs and
@ ZIP archive. For best results, keep this prefix brief and avoid special
@ characters such as "/" and "\".
@ If no tarball prefix is specified, then the full Project Name above is used.
@ (Property: "short-project-name")
|
| ︙ | ︙ |
Changes to src/setupuser.c.
| ︙ | ︙ | |||
345 346 347 348 349 350 351 |
/* Check for requests to delete the user */
if( P("delete") && cgi_csrf_safe(1) ){
int n;
if( P("verifydelete") ){
/* Verified delete user request */
db_unprotect(PROTECT_USER);
| | | 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 |
/* Check for requests to delete the user */
if( P("delete") && cgi_csrf_safe(1) ){
int n;
if( P("verifydelete") ){
/* Verified delete user request */
db_unprotect(PROTECT_USER);
if( alert_tables_exist() ){
/* Also delete any subscriptions associated with this user */
db_multi_exec("DELETE FROM subscriber WHERE suname="
"(SELECT login FROM user WHERE uid=%d)", uid);
}
db_multi_exec("DELETE FROM user WHERE uid=%d", uid);
db_protect_pop();
moderation_disapprove_for_missing_users();
|
| ︙ | ︙ | |||
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 |
login_verify_csrf_secret();
db_unprotect(PROTECT_USER);
db_multi_exec(
"REPLACE INTO user(uid,login,info,pw,cap,mtime) "
"VALUES(nullif(%d,0),%Q,%Q,%Q,%Q,now())",
uid, zLogin, P("info"), zPw, zCap
);
db_protect_pop();
setup_incr_cfgcnt();
admin_log( "Updated user [%q] with capabilities [%q].",
zLogin, zCap );
if( atoi(PD("all","0"))>0 ){
Blob sql;
char *zErr = 0;
blob_zero(&sql);
if( zOldLogin==0 ){
blob_appendf(&sql,
"INSERT INTO user(login)"
" SELECT %Q WHERE NOT EXISTS(SELECT 1 FROM user WHERE login=%Q);",
zLogin, zLogin
);
zOldLogin = zLogin;
}
blob_appendf(&sql,
"UPDATE user SET login=%Q,"
" pw=coalesce(shared_secret(%Q,%Q,"
"(SELECT value FROM config WHERE name='project-code')),pw),"
" info=%Q,"
" cap=%Q,"
" mtime=now()"
| > > > > > > > > > > > > > > > > > > > > > > > | 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 |
login_verify_csrf_secret();
db_unprotect(PROTECT_USER);
db_multi_exec(
"REPLACE INTO user(uid,login,info,pw,cap,mtime) "
"VALUES(nullif(%d,0),%Q,%Q,%Q,%Q,now())",
uid, zLogin, P("info"), zPw, zCap
);
if( zOldLogin && fossil_strcmp(zLogin, zOldLogin)!=0 ){
if( alert_tables_exist() ){
/* Rename matching subscriber entry, else the user cannot
re-subscribe with their same email address. */
db_multi_exec("UPDATE subscriber SET suname=%Q WHERE suname=%Q",
zLogin, zOldLogin);
}
admin_log( "Renamed user [%q] to [%q].", zOldLogin, zLogin );
}
db_protect_pop();
setup_incr_cfgcnt();
admin_log( "Updated user [%q] with capabilities [%q].",
zLogin, zCap );
if( atoi(PD("all","0"))>0 ){
Blob sql;
char *zErr = 0;
blob_zero(&sql);
if( zOldLogin==0 ){
blob_appendf(&sql,
"INSERT INTO user(login)"
" SELECT %Q WHERE NOT EXISTS(SELECT 1 FROM user WHERE login=%Q);",
zLogin, zLogin
);
zOldLogin = zLogin;
}
#if 0
/* Problem: when renaming a user we need to update the subcriber
** names to match but we cannot know from here if each member of
** the login group has the subscriber tables, so we cannot blindly
** include this SQL. */
else if( fossil_strcmp(zLogin, zOldLogin)!=0
&& alert_tables_exist() ){
/* Rename matching subscriber entry, else the user cannot
re-subscribe with their same email address. */
blob_appendf(&sql,
"UPDATE subscriber SET suname=%Q WHERE suname=%Q;",
zLogin, zOldLogin);
}
#endif
blob_appendf(&sql,
"UPDATE user SET login=%Q,"
" pw=coalesce(shared_secret(%Q,%Q,"
"(SELECT value FROM config WHERE name='project-code')),pw),"
" info=%Q,"
" cap=%Q,"
" mtime=now()"
|
| ︙ | ︙ |
Changes to src/shun.c.
| ︙ | ︙ | |||
58 59 60 61 62 63 64 |
login_needed(0);
return;
}
if( P("rebuild") ){
db_close(1);
db_open_repository(g.zRepositoryName);
db_begin_transaction();
| | | 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
login_needed(0);
return;
}
if( P("rebuild") ){
db_close(1);
db_open_repository(g.zRepositoryName);
db_begin_transaction();
rebuild_db(0, 0);
admin_log("Rebuilt database.");
db_end_transaction(0);
}
if( zUuid ){
char *p;
int i = 0;
int j = 0;
|
| ︙ | ︙ |
Changes to src/sqlcmd.c.
| ︙ | ︙ | |||
19 20 21 22 23 24 25 | ** shell against the repository database. The command-line shell itself ** is a copy of the "shell.c" code from SQLite. This file contains logic ** to initialize the code in shell.c. */ #include "config.h" #include "sqlcmd.h" #include <stdlib.h> /* atexit() */ | < < < < | < < | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | ** shell against the repository database. The command-line shell itself ** is a copy of the "shell.c" code from SQLite. This file contains logic ** to initialize the code in shell.c. */ #include "config.h" #include "sqlcmd.h" #include <stdlib.h> /* atexit() */ #include <zlib.h> #ifndef _WIN32 # include "linenoise.h" #endif /* ** True if the "fossil sql" command has the --test flag. False otherwise. */ |
| ︙ | ︙ | |||
282 283 284 285 286 287 288 | sqlite3_auto_extension((void(*)(void))sqlcmd_autoinit); } #if USE_SEE /* ** This routine is called by the patched sqlite3 command-line shell in order ** to load the encryption key for the open Fossil database. The memory that | | < | < | | | 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 |
sqlite3_auto_extension((void(*)(void))sqlcmd_autoinit);
}
#if USE_SEE
/*
** This routine is called by the patched sqlite3 command-line shell in order
** to load the encryption key for the open Fossil database. The memory that
** is pointed to by the value placed in pzKey must be obtained from malloc.
*/
void fossil_key(const char **pzKey, int *pnKey){
char *zSavedKey = db_get_saved_encryption_key();
char *zKey;
size_t savedKeySize = db_get_saved_encryption_key_size();
if( zSavedKey==0 || savedKeySize==0 ) return;
zKey = (char*)malloc( savedKeySize );
if( zKey ){
memcpy(zKey, zSavedKey, savedKeySize);
*pzKey = zKey;
if( fossil_getenv("FOSSIL_USE_SEE_TEXTKEY")==0 ){
*pnKey = (int)strlen(zKey);
}else{
*pnKey = -1;
}
}else{
fossil_fatal("failed to allocate %u bytes for key", savedKeySize);
}
}
#endif
/*
** This routine closes the Fossil databases and/or invalidates the global
** state variables that keep track of them.
|
| ︙ | ︙ |
Changes to src/stash.c.
| ︙ | ︙ | |||
306 307 308 309 310 311 312 |
** Apply a stash to the current checkout.
*/
static void stash_apply(int stashid, int nConflict){
int vid;
Stmt q;
db_prepare(&q,
"SELECT blob.rid, isRemoved, isExec, isLink, origname, newname, delta"
| | > > | | 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 |
** Apply a stash to the current checkout.
*/
static void stash_apply(int stashid, int nConflict){
int vid;
Stmt q;
db_prepare(&q,
"SELECT blob.rid, isRemoved, isExec, isLink, origname, newname, delta"
" FROM stashfile, blob WHERE stashid=%d AND blob.uuid=stashfile.hash"
" UNION ALL SELECT 0, isRemoved, isExec, isLink, origname, newname, delta"
" FROM stashfile WHERE stashid=%d AND stashfile.hash IS NULL",
stashid, stashid
);
vid = db_lget_int("checkout",0);
db_multi_exec("CREATE TEMP TABLE sfile(pathname TEXT PRIMARY KEY %s)",
filename_collation());
while( db_step(&q)==SQLITE_ROW ){
int rid = db_column_int(&q, 0);
int isRemoved = db_column_int(&q, 1);
|
| ︙ | ︙ | |||
410 411 412 413 414 415 416 |
Stmt q;
Blob empty;
int bWebpage = (pCfg->diffFlags & (DIFF_WEBPAGE|DIFF_JSON|DIFF_TCL))!=0;
blob_zero(&empty);
diff_begin(pCfg);
db_prepare(&q,
"SELECT blob.rid, isRemoved, isExec, isLink, origname, newname, delta"
| | > > | | 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 |
Stmt q;
Blob empty;
int bWebpage = (pCfg->diffFlags & (DIFF_WEBPAGE|DIFF_JSON|DIFF_TCL))!=0;
blob_zero(&empty);
diff_begin(pCfg);
db_prepare(&q,
"SELECT blob.rid, isRemoved, isExec, isLink, origname, newname, delta"
" FROM stashfile, blob WHERE stashid=%d AND blob.uuid=stashfile.hash"
" UNION ALL SELECT 0, isRemoved, isExec, isLink, origname, newname, delta"
" FROM stashfile WHERE stashid=%d AND stashfile.hash IS NULL",
stashid, stashid
);
while( db_step(&q)==SQLITE_ROW ){
int rid = db_column_int(&q, 0);
int isRemoved = db_column_int(&q, 1);
int isLink = db_column_int(&q, 3);
const char *zOrig = db_column_text(&q, 4);
const char *zNew = db_column_text(&q, 5);
|
| ︙ | ︙ |
Changes to src/stat.c.
| ︙ | ︙ | |||
390 391 392 393 394 395 396 |
a = t/fsize;
fossil_print("%*s%d:%d\n", colWidth, "compression-ratio:", a, b);
}
n = db_int(0, "SELECT COUNT(*) FROM event e WHERE e.type='ci'");
fossil_print("%*s%,d\n", colWidth, "check-ins:", n);
n = db_int(0, "SELECT count(*) FROM filename /*scan*/");
fossil_print("%*s%,d across all branches\n", colWidth, "files:", n);
| | > > | > > > < | 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 |
a = t/fsize;
fossil_print("%*s%d:%d\n", colWidth, "compression-ratio:", a, b);
}
n = db_int(0, "SELECT COUNT(*) FROM event e WHERE e.type='ci'");
fossil_print("%*s%,d\n", colWidth, "check-ins:", n);
n = db_int(0, "SELECT count(*) FROM filename /*scan*/");
fossil_print("%*s%,d across all branches\n", colWidth, "files:", n);
n = db_int(0, "SELECT count(*) FROM ("
"SELECT DISTINCT substr(tagname,6) "
"FROM tag JOIN tagxref USING('tagid')"
" WHERE tagname GLOB 'wiki-*'"
" AND TYPEOF(tagxref.value+0)='integer'"
")");
m = db_int(0, "SELECT COUNT(*) FROM event WHERE type='w'");
fossil_print("%*s%,d (%,d changes)\n", colWidth, "wiki-pages:", n, m);
n = db_int(0, "SELECT count(*) FROM tag /*scan*/"
" WHERE tagname GLOB 'tkt-*'");
m = db_int(0, "SELECT COUNT(*) FROM event WHERE type='t'");
fossil_print("%*s%,d (%,d changes)\n", colWidth, "tickets:", n, m);
n = db_int(0, "SELECT COUNT(*) FROM event WHERE type='e'");
fossil_print("%*s%,d\n", colWidth, "events:", n);
if( db_table_exists("repository","forumpost") ){
n = db_int(0, "SELECT count(*) FROM forumpost/*scan*/");
if( n>0 ){
int nThread = db_int(0, "SELECT count(*) FROM forumpost"
" WHERE froot=fpid");
fossil_print("%*s%,d (on %,d threads)\n", colWidth, "forum-posts:",
n, nThread);
}
}
n = db_int(0, "SELECT COUNT(*) FROM event WHERE type='g'");
fossil_print("%*s%,d\n", colWidth, "tag-changes:", n);
z = db_text(0, "SELECT datetime(mtime) || ' - about ' ||"
" CAST(julianday('now') - mtime AS INTEGER)"
" || ' days ago' FROM event "
" ORDER BY mtime DESC LIMIT 1");
fossil_print("%*s%s\n", colWidth, "latest-change:", z);
|
| ︙ | ︙ | |||
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 |
g.argv = newArgv;
g.argc = 2;
fossil_print("Full repository verification follows:\n");
test_integrity();
}
}
}
/*
** WEBPAGE: urllist
**
** Show ways in which this repository has been accessed
*/
void urllist_page(void){
Stmt q;
int cnt;
int showAll = P("all")!=0;
int nOmitted;
sqlite3_int64 iNow;
login_check_credentials();
if( !g.perm.Admin ){ login_needed(0); return; }
style_set_current_feature("stat");
style_header("URLs and Checkouts");
style_adunit_config(ADUNIT_RIGHT_OK);
style_submenu_element("Stat", "stat");
style_submenu_element("Schema", "repo_schema");
iNow = db_int64(0, "SELECT strftime('%%s','now')");
| > > > > > > > > > > > > > > > > > > > > > > > | | > > > > | < | > | > > > > > > > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 |
g.argv = newArgv;
g.argc = 2;
fossil_print("Full repository verification follows:\n");
test_integrity();
}
}
}
/*
** Return a string which is the public URL used to access this repository.
** Or return a NULL pointer if this repository does not have a public
** access URL.
**
** Algorithm:
**
** The public URL is given by the email-url property. But it is only
** returned if there have been one more more accesses (as recorded by
** "baseurl:URL" entries in the CONFIG table).
*/
const char *public_url(void){
const char *zUrl = db_get("email-url", 0);
if( zUrl==0 ) return 0;
if( !db_exists("SELECT 1 FROM config WHERE name='baseurl:%q'", zUrl) ){
return 0;
}
return zUrl;
}
/*
** WEBPAGE: urllist
**
** Show ways in which this repository has been accessed
*/
void urllist_page(void){
Stmt q;
int cnt;
int total = 0;
int showAll = P("all")!=0;
int nOmitted;
sqlite3_int64 iNow;
char *zPriorRepo = 0;
login_check_credentials();
if( !g.perm.Admin ){ login_needed(0); return; }
style_set_current_feature("stat");
style_header("URLs and Checkouts");
style_adunit_config(ADUNIT_RIGHT_OK);
style_submenu_element("Stat", "stat");
style_submenu_element("Schema", "repo_schema");
iNow = db_int64(0, "SELECT strftime('%%s','now')");
db_prepare(&q, "SELECT substr(name,9), datetime(mtime,'unixepoch'), mtime"
" FROM config WHERE name GLOB 'baseurl:*' ORDER BY 3 DESC");
cnt = 0;
nOmitted = 0;
while( db_step(&q)==SQLITE_ROW ){
if( cnt==0 ){
@ <div class="section">URLs used to access this repository</div>
@ <table border="0" width='100%%'>
}
if( !showAll && db_column_int64(&q,2)<(iNow - 3600*24*30) && cnt>8 ){
nOmitted++;
}else{
@ <tr><td width='100%%'>%h(db_column_text(&q,0))</td>
@ <td><nobr>%h(db_column_text(&q,1))</nobr></td></tr>
}
cnt++;
}
db_finalize(&q);
if( nOmitted ){
@ <tr><td><a href="urllist?all"><i>Show %d(nOmitted) more...</i></a>
}
if( cnt ){
@ </table>
total += cnt;
}
if( P("urlonly") ){
style_finish_page();
return;
}
db_prepare(&q, "SELECT substr(name,7), datetime(mtime,'unixepoch')"
" FROM config WHERE name GLOB 'ckout:*' ORDER BY 2 DESC");
cnt = 0;
while( db_step(&q)==SQLITE_ROW ){
const char *zPath = db_column_text(&q,0);
if( vfile_top_of_checkout(zPath) ){
if( cnt==0 ){
@ <div class="section">Checkouts</div>
@ <table border="0" width='100%%'>
}
@ <tr><td width='100%%'>%h(zPath)</td>
@ <td><nobr>%h(db_column_text(&q,1))</nobr></td></tr>
cnt++;
}
}
db_finalize(&q);
if( cnt ){
@ </table>
total += cnt;
}
cnt = 0;
db_prepare(&q,
"SELECT substr(name,10), datetime(mtime,'unixepoch')"
" FROM config WHERE name GLOB 'syncwith:*'"
"UNION ALL "
"SELECT substr(name,10), datetime(mtime,'unixepoch')"
" FROM config WHERE name GLOB 'syncfrom:*'"
"UNION ALL "
"SELECT substr(name,9), datetime(mtime,'unixepoch')"
" FROM config WHERE name GLOB 'gitpush:*'"
"GROUP BY 1 ORDER BY 2 DESC"
);
while( db_step(&q)==SQLITE_ROW ){
const char *zURL = db_column_text(&q,0);
UrlData x;
if( cnt==0 ){
@ <div class="section">Recently synced with these URLs</div>
@ <table border='0' width='100%%'>
}
memset(&x, 0, sizeof(x));
url_parse_local(zURL, URL_OMIT_USER, &x);
@ <tr><td width='100%%'><a href='%h(x.canonical)'>%h(x.canonical)</a>
@ <td><nobr>%h(db_column_text(&q,1))</nobr></td></tr>
cnt++;
url_unparse(&x);
}
db_finalize(&q);
if( cnt ){
@ </table>
total += cnt;
}
cnt = 0;
db_prepare(&q,
"SELECT"
" substr(name,6),"
" datetime(mtime,'unixepoch'),"
" value->>'type',"
" value->>'src'\n"
"FROM config\n"
"WHERE name GLOB 'link:*'\n"
"AND json_valid(value)\n"
"ORDER BY 4, 2 DESC"
);
while( db_step(&q)==SQLITE_ROW ){
const char *zUrl = db_column_text(&q, 0);
const char *zType = db_column_text(&q, 2);
const char *zSrc = db_column_text(&q, 3);
if( zUrl==0 || zSrc==0 ) continue;
if( cnt++==0 ){
@ <div class="section">Links from other repositories</div>
@ <table border='0' width='100%%'>
}
if( zPriorRepo==0 || strcmp(zPriorRepo,zSrc)!=0 ){
fossil_free(zPriorRepo);
zPriorRepo = fossil_strdup(zSrc);
@ <tr><td colspan="4">\
@ From <a href='%T(zSrc)'>%h(zSrc)</a>...</td></tr>
}
@ <tr><td> </td>
@ <td width='90%%'><a href='%h(zUrl)'>%h(zUrl)</a></td>
if( zType ){
@ <td> (%h(zType)) </td>
}else{
@ <td> </td>
}
@ <td><nobr>%h(db_column_text(&q,1))</nobr></td></tr>
}
db_finalize(&q);
fossil_free(zPriorRepo);
if( cnt ){
@ </table>
total += cnt;
}
cnt = 0;
db_prepare(&q,
"SELECT"
" value,"
" url_nouser(value),"
" substr(name,10),"
" datetime(mtime,'unixepoch')"
"FROM config\n"
"WHERE name GLOB 'sync-url:*'\n"
"ORDER BY 2"
);
while( db_step(&q)==SQLITE_ROW ){
const char *zUrl = db_column_text(&q, 0);
const char *zLink = db_column_text(&q, 1);
const char *zName = db_column_text(&q, 2);
if( cnt++==0 ){
@ <div class="section">Defined sync targets</div>
@ <table border='0' width='100%%'>
}
@ <tr><td>%h(zName)</td><td> </td>
@ <td width='95%%'><a href='%h(zLink)'>%h(zUrl)</a></td>
@ <td><nobr>%h(db_column_text(&q,3))</nobr></td></tr>
}
db_finalize(&q);
if( cnt ){
@ </table>
total += cnt;
}
if( total==0 ){
@ <p>No record of any URLs or checkouts</p>
}
style_finish_page();
}
/*
** WEBPAGE: repo_schema
**
|
| ︙ | ︙ |
Changes to src/style.c.
| ︙ | ︙ | |||
1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 |
#ifndef _WIN32
@ RSS = %.2f(fossil_rss()/1000000.0) MB</br />
#endif
@ cgi_csrf_safe(0) = %d(cgi_csrf_safe(0))<br />
@ fossil_exe_id() = %h(fossil_exe_id())<br />
@ <hr />
P("HTTP_USER_AGENT");
cgi_print_all(showAll, 0);
if( showAll && blob_size(&g.httpHeader)>0 ){
@ <hr />
@ <pre>
@ %h(blob_str(&g.httpHeader))
@ </pre>
}
| > | 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 |
#ifndef _WIN32
@ RSS = %.2f(fossil_rss()/1000000.0) MB</br />
#endif
@ cgi_csrf_safe(0) = %d(cgi_csrf_safe(0))<br />
@ fossil_exe_id() = %h(fossil_exe_id())<br />
@ <hr />
P("HTTP_USER_AGENT");
P("SERVER_SOFTWARE");
cgi_print_all(showAll, 0);
if( showAll && blob_size(&g.httpHeader)>0 ){
@ <hr />
@ <pre>
@ %h(blob_str(&g.httpHeader))
@ </pre>
}
|
| ︙ | ︙ |
Changes to src/style.chat.css.
| ︙ | ︙ | |||
27 28 29 30 31 32 33 |
}
body.chat.my-messages-right .message-widget.notification {
/* Center-aligns a system-level notification message. */
align-items: center;
}
/* The content area of a message. */
body.chat .message-widget-content {
| < | > > > > > > > > > > > > > > > > > > > > | > > > > | | > > > > > > > > > > > > > > > > > > > > > | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
}
body.chat.my-messages-right .message-widget.notification {
/* Center-aligns a system-level notification message. */
align-items: center;
}
/* The content area of a message. */
body.chat .message-widget-content {
border-radius: 0.25em;
border: 1px solid rgba(0,0,0,0.2);
box-shadow: 0.2em 0.2em 0.2em rgba(0, 0, 0, 0.29);
padding: 0.25em 0.5em;
margin-top: 0;
min-width: 9em /*avoid unsightly "underlap" with the neighboring
.message-widget-tab element*/;
white-space: normal;
}
body.chat .message-widget-content.wide {
/* Special case for when embedding content which we really want to
expand, namely iframes. */
width: 98%;
}
body.chat .message-widget-content label[for] {
margin-left: 0.25em;
cursor: pointer;
}
body.chat .message-widget-content > .attachment-link {
display: flex;
flex-direction: row;
}
body.chat .message-widget-content > .attachment-link > a {
margin-right: 1em;
}
body.chat .message-widget-content > iframe {
width: 100%;
max-width: 100%;
resize: both;
}
body.chat .message-widget-content> a {
/* Cosmetic: keep skin-induced on-hover underlining from shifting
content placed below this. */
border-bottom: 1px transparent;
}
body.chat.monospace-messages .message-widget-content,
body.chat.monospace-messages .chat-input-field{
font-family: monospace;
}
body.chat .message-widget-content > * {
margin: 0;
padding: 0;
}
body.chat .message-widget-content > pre {
white-space: pre-wrap;
}
body.chat .message-widget-content > .markdown > *:first-child {
margin-top: 0;
}
body.chat .message-widget-content > .markdown > *:last-child {
margin-bottom: 0;
}
body.chat .message-widget-content.error .buttons {
display: flex;
flex-direction: row;
justify-content: space-around;
flex-wrap: wrap;
}
body.chat .message-widget-content.error .buttons > button {
margin: 0.25em;
}
body.chat .message-widget-content.error a {
color: inherit;
}
body.chat .message-widget-content.error .failed-message {
display: flex;
flex-direction: column;
}
body.chat .message-widget-content.error .failed-message textarea {
min-height: 5rem;
}
/* User name and timestamp (a LEGEND-like element) */
body.chat .message-widget .message-widget-tab {
border-radius: 0.25em 0.25em 0 0;
margin: 0 0.25em 0em 0.15em;
padding: 0 0.5em 0.15em 0.5em;
cursor: pointer;
white-space: nowrap;
|
| ︙ | ︙ | |||
179 180 181 182 183 184 185 |
}
body.chat:not(.chat-only-mode) #chat-input-area{
/* Safari user reports that 2em is necessary to keep the file selection
widget from overlapping the page footer, whereas a margin of 0 is fine
for FF/Chrome (and 2em is a *huge* waste of space for those). */
margin-bottom: 0;
}
| | < < > > | > > > > > > | | | | | | | | | | | | | < | > | | < | | | | | | 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 |
}
body.chat:not(.chat-only-mode) #chat-input-area{
/* Safari user reports that 2em is necessary to keep the file selection
widget from overlapping the page footer, whereas a margin of 0 is fine
for FF/Chrome (and 2em is a *huge* waste of space for those). */
margin-bottom: 0;
}
.chat-input-field {
flex: 10 1 auto;
margin: 0;
}
#chat-input-field-x,
#chat-input-field-multi {
overflow: auto;
resize: vertical;
}
#chat-input-field-x {
display: inline-block/*supposed workaround for Chrome weirdness*/;
padding: 0.2em;
background-color: rgba(156,156,156,0.3);
white-space: pre-wrap;
/* ^^^ Firefox, when pasting plain text into a contenteditable field,
loses all newlines unless we explicitly set this. Chrome does not. */
cursor: text;
/* ^^^ In some browsers the cursor may not change for a contenteditable
element until it has focus, causing potential confusion. */
}
#chat-input-field-x:empty::before {
content: attr(data-placeholder);
opacity: 0.6;
}
.chat-input-field:not(:focus){
border-width: 1px;
border-style: solid;
border-radius: 0.25em;
}
.chat-input-field:focus{
/* This transparent border helps avoid the text shifting around
when the contenteditable attribute causes a border (which we
apparently cannot style) to be added. */
border-width: 1px;
border-style: solid;
border-color: transparent;
border-radius: 0.25em;
}
/* Widget holding the chat message input field, send button, and
settings button. */
body.chat #chat-input-line-wrapper {
display: flex;
flex-direction: row;
align-items: stretch;
flex-wrap: nowrap;
}
/*body.chat #chat-input-line-wrapper:not(.compact) {
flex-wrap: nowrap;
}*/
body.chat #chat-input-line-wrapper.compact {
/* "The problem" with wrapping, together with a contenteditable input
field, is that the latter grows as the user types, so causes
wrapping to happen while they type, then to unwrap as soon as the
input field is cleared (when the message is sent). When we stay
wrapped in compact mode, the wrapped buttons simply take up too
much space. */
/*flex-wrap: wrap;
justify-content: flex-end;*/
flex-direction: column;
/**
We "really do" need column orientation here because it's the
only way to eliminate the possibility that (A) the buttons
get truncated in very narrow windows and (B) that they keep
stable positions.
*/
}
body.chat #chat-input-line-wrapper.compact #chat-input-field-x {
}
body.chat #chat-buttons-wrapper {
flex: 0 1 auto;
display: flex;
flex-direction: column;
align-items: center;
min-width: 4em;
min-height: 1.5em;
align-self: flex-end
/*keep buttons stable at bottom/right even when input field
resizes */;
}
body.chat #chat-input-line-wrapper.compact #chat-buttons-wrapper {
flex-direction: row;
flex: 1 1 auto;
align-self: stretch;
justify-content: flex-end;
/*flex-wrap: wrap;*/
/* Wrapping would be ideal except that the edit widget
grows in width as the user types, moving the buttons
around */
}
body.chat #chat-buttons-wrapper > .cbutton {
padding: 0;
display: inline-block;
border-width: 1px;
border-style: solid;
border-radius: 0.25em;
min-width: 4ex;
max-width: 4ex;
min-height: 3ex;
max-height: 3ex;
margin: 0.125em;
display: inline-flex;
justify-content: center;
align-items: center;
cursor: pointer;
font-size: 130%;
}
body.chat #chat-buttons-wrapper > .cbutton:hover {
background-color: rgba(200,200,200,0.3);
}
body.chat #chat-input-line-wrapper.compact #chat-buttons-wrapper > .cbutton {
margin: 2px 0.125em 0 0.125em;
min-width: 6ex;
max-width: 6ex;
min-height: 2.3ex;
max-height: 2.3ex;
font-size: 120%;
}
body.chat #chat-input-line-wrapper.compact #chat-buttons-wrapper #chat-button-submit {
min-width: 12ex;
}
.chat-input-field {
font-family: inherit
}
body.chat #chat-input-line-wrapper:not(.compact) #chat-input-field-multi,
body.chat #chat-input-line-wrapper:not(.compact) #chat-input-field-x {
min-height: 4rem;
/*
Problems related to max-height:
- If we do NOT set a max-height then pasting/typing a large amount
of text can cause this element to grow without bounds, larger than
the window, and there's no way to navigate it sensibly. In this
case, manually resizing the element (desktop only - mobile doesn't
offer that) will force it to stay at the selected size even if more
content is added to it later.
- If we DO set a max-height then its growth is bounded but it also
cannot manually expanded by the user.
The lesser of the two evils seems to be to rely on the browser
feature that a manual resize of the element will pin its size.
*/
}
body.chat #chat-input-line-wrapper > #chat-button-settings{
margin: 0 0 0 0.25em;
max-width: 2em;
}
body.chat #chat-input-line-wrapper > input[type=text],
body.chat #chat-input-line-wrapper > textarea {
flex: 20 1 auto;
max-width: revert;
min-width: 20em;
}
body.chat #chat-input-line-wrapper.compact > input[type=text] {
margin: 0 0 0.25em 0/* gap for if/when buttons wrap*/;
}
/* Widget holding the file selection control and preview */
body.chat #chat-input-file-area {
display: flex;
flex-direction: row;
margin: 0;
|
| ︙ | ︙ | |||
365 366 367 368 369 370 371 |
body.chat #chat-drop-details {
padding: 0 1em;
white-space: pre;
font-family: monospace;
margin: auto;
flex: 0;
}
| > > > | | 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 |
body.chat #chat-drop-details {
padding: 0 1em;
white-space: pre;
font-family: monospace;
margin: auto;
flex: 0;
}
body.chat #chat-drop-details:empty {
padding: 0;
margin: 0;
}
body.chat #chat-drop-details img {
max-width: 45%;
max-height: 45%;
}
body.chat .chat-view {
flex: 20 1 auto
/*ensure that these grow more than the non-.chat-view elements.
|
| ︙ | ︙ | |||
393 394 395 396 397 398 399 400 401 402 |
}
body.chat #chat-config #chat-config-options {
/* /chat config options go here */
flex: 1 1 auto;
display: flex;
flex-direction: column;
overflow: auto;
}
body.chat #chat-config #chat-config-options .menu-entry {
display: flex;
| > | | > > | > > > > > > > > | | > > > > > > > > > > > > | > > > > > > > > > > > > > > > | > < < < < | < < < | 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 |
}
body.chat #chat-config #chat-config-options {
/* /chat config options go here */
flex: 1 1 auto;
display: flex;
flex-direction: column;
overflow: auto;
align-items: stretch;
}
body.chat #chat-config #chat-config-options .menu-entry {
display: flex;
align-items: center;
flex-direction: row-reverse;
flex-wrap: nowrap;
padding: 1em;
flex: 1 1 auto;
align-self: stretch;
}
body.chat #chat-config #chat-config-options .menu-entry.parent{
border-radius: 1em 1em 0 1em;
margin-top: 1em;
}
body.chat #chat-config #chat-config-options .menu-entry.child {
/*padding-left: 2.5em;*/
margin-left: 2em;
}
body.chat #chat-config #chat-config-options .menu-entry:nth-of-type(even){
background-color: rgba(175,175,175,0.15);
}
body.chat #chat-config #chat-config-options .menu-entry:nth-of-type(odd){
background-color: rgba(175,175,175,0.35);
}
body.chat #chat-config #chat-config-options .menu-entry:first-child {
/* Config list header */
border-radius: 0 0 1em 1em;
}
body.chat #chat-config #chat-config-options .menu-entry:first-child .label-wrapper {
align-items: start;
}
body.chat #chat-config #chat-config-options .menu-entry > .toggle-wrapper {
/* Holder for a checkbox, if any */
min-width: 1.5rem;
margin-right: 1rem;
}
body.chat #chat-config #chat-config-options .menu-entry .label-wrapper {
/* Wrapper for a LABEL and a .hint element. */
display: flex;
flex-direction: column;
align-self: baseline;
flex: 1 1 auto;
}
body.chat #chat-config #chat-config-options .menu-entry label {
/* Config option label. */
font-weight: bold;
white-space: initial;
}
body.chat #chat-config #chat-config-options .menu-entry label[for] {
cursor: pointer;
}
body.chat #chat-config #chat-config-options .menu-entry .hint {
/* Config menu hint text */
font-size: 85%;
font-weight: normal;
white-space: pre-wrap;
display: inline-block;
opacity: 0.85;
}
body.chat #chat-config #chat-config-options .menu-entry select {
}
body.chat #chat-preview #chat-preview-content {
overflow: auto;
flex: 1 1 auto;
padding: 0.5em;
|
| ︙ | ︙ |
Changes to src/sync.c.
| ︙ | ︙ | |||
16 17 18 19 20 21 22 23 24 25 26 27 28 29 | ******************************************************************************* ** ** This file contains code used to push, pull, and sync a repository */ #include "config.h" #include "sync.h" #include <assert.h> /* ** If the repository is configured for autosyncing, then do an ** autosync. Bits of the "flags" parameter determine details of behavior: ** ** SYNC_PULL Pull content from the server to the local repo ** SYNC_PUSH Push content from local up to the server | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
*******************************************************************************
**
** This file contains code used to push, pull, and sync a repository
*/
#include "config.h"
#include "sync.h"
#include <assert.h>
/*
** Explain what type of sync operation is about to occur
*/
static void sync_explain(unsigned syncFlags){
if( g.url.isAlias ){
if( (syncFlags & (SYNC_PUSH|SYNC_PULL))==(SYNC_PUSH|SYNC_PULL) ){
fossil_print("Sync with %s\n", g.url.canonical);
}else if( syncFlags & SYNC_PUSH ){
fossil_print("Push to %s\n", g.url.canonical);
}else if( syncFlags & SYNC_PULL ){
fossil_print("Pull from %s\n", g.url.canonical);
}
}
}
/*
** Call client_sync() one or more times in order to complete a
** sync operation. Usually, client_sync() is called only once, though
** is can be called multiple times if the SYNC_ALLURL flags is set.
*/
static int client_sync_all_urls(
unsigned syncFlags, /* Mask of SYNC_* flags */
unsigned configRcvMask, /* Receive these configuration items */
unsigned configSendMask, /* Send these configuration items */
const char *zAltPCode /* Alternative project code (usually NULL) */
){
int nErr;
int nOther;
char **azOther;
int i;
Stmt q;
sync_explain(syncFlags);
nErr = client_sync(syncFlags, configRcvMask, configSendMask, zAltPCode);
if( nErr==0 ) url_remember();
if( (syncFlags & SYNC_ALLURL)==0 ) return nErr;
nOther = 0;
azOther = 0;
db_prepare(&q,
"SELECT substr(name,10) FROM config"
" WHERE name glob 'sync-url:*'"
" AND value<>(SELECT value FROM config WHERE name='last-sync-url')"
);
while( db_step(&q)==SQLITE_ROW ){
const char *zUrl = db_column_text(&q, 0);
azOther = fossil_realloc(azOther, sizeof(*azOther)*(nOther+1));
azOther[nOther++] = fossil_strdup(zUrl);
}
db_finalize(&q);
for(i=0; i<nOther; i++){
int rc;
url_unparse(&g.url);
url_parse(azOther[i], URL_PROMPT_PW|URL_ASK_REMEMBER_PW|URL_USE_CONFIG);
sync_explain(syncFlags);
rc = client_sync(syncFlags, configRcvMask, configSendMask, zAltPCode);
nErr += rc;
if( (g.url.flags & URL_REMEMBER_PW)!=0 && rc==0 ){
char *zKey = mprintf("sync-pw:%s", azOther[i]);
char *zPw = obscure(g.url.passwd);
if( zPw && zPw[0] ){
db_set(zKey/*works-like:""*/, zPw, 0);
}
fossil_free(zPw);
fossil_free(zKey);
}
fossil_free(azOther[i]);
azOther[i] = 0;
}
fossil_free(azOther);
return nErr;
}
/*
** If the repository is configured for autosyncing, then do an
** autosync. Bits of the "flags" parameter determine details of behavior:
**
** SYNC_PULL Pull content from the server to the local repo
** SYNC_PUSH Push content from local up to the server
|
| ︙ | ︙ | |||
46 47 48 49 50 51 52 |
int configSync = 0; /* configuration changes transferred */
if( g.fNoSync ){
return 0;
}
zAutosync = db_get("autosync", 0);
if( zAutosync==0 ) zAutosync = "on"; /* defend against misconfig */
if( is_false(zAutosync) ) return 0;
| | > > > | > > > | | < | | > | 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
int configSync = 0; /* configuration changes transferred */
if( g.fNoSync ){
return 0;
}
zAutosync = db_get("autosync", 0);
if( zAutosync==0 ) zAutosync = "on"; /* defend against misconfig */
if( is_false(zAutosync) ) return 0;
if( db_get_boolean("dont-push",0)
|| sqlite3_strglob("*pull*", zAutosync)==0
){
flags &= ~SYNC_CKIN_LOCK;
if( flags & SYNC_PUSH ) return 0;
}
if( find_option("verbose","v",0)!=0 ) flags |= SYNC_VERBOSE;
url_parse(0, URL_REMEMBER|URL_USE_CONFIG);
if( g.url.protocol==0 ) return 0;
if( g.url.user!=0 && g.url.passwd==0 ){
g.url.passwd = unobscure(db_get("last-sync-pw", 0));
g.url.flags |= URL_PROMPT_PW;
url_prompt_for_password();
}
g.zHttpAuth = get_httpauth();
if( sqlite3_strglob("*all*", zAutosync)==0 ){
rc = client_sync_all_urls(flags|SYNC_ALLURL, configSync, 0, 0);
}else{
url_remember();
sync_explain(flags);
url_enable_proxy("via proxy: ");
rc = client_sync(flags, configSync, 0, 0);
}
return rc;
}
/*
** This routine will try a number of times to perform autosync with a
** 0.5 second sleep between attempts.
**
|
| ︙ | ︙ | |||
126 127 128 129 130 131 132 |
int urlOptional = 0;
if( find_option("autourl",0,0)!=0 ){
urlOptional = 1;
urlFlags = 0;
}
zHttpAuth = find_option("httpauth","B",1);
if( find_option("once",0,0)!=0 ) urlFlags &= ~URL_REMEMBER;
| | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < < < < < < < < < < > > > > > | > > > | > > > > < > | | < < < < < | < | < < < < < < < < | | > > > > > > > > | | | > | > > > > | | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > | 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 |
int urlOptional = 0;
if( find_option("autourl",0,0)!=0 ){
urlOptional = 1;
urlFlags = 0;
}
zHttpAuth = find_option("httpauth","B",1);
if( find_option("once",0,0)!=0 ) urlFlags &= ~URL_REMEMBER;
if( (*pSyncFlags) & SYNC_FROMPARENT ) urlFlags |= URL_USE_PARENT;
if( !uvOnly ){
if( find_option("private",0,0)!=0 ){
*pSyncFlags |= SYNC_PRIVATE;
}
/* The --verily option to sync, push, and pull forces extra igot cards
** to be exchanged. This can overcome malfunctions in the sync protocol.
*/
if( find_option("verily",0,0)!=0 ){
*pSyncFlags |= SYNC_RESYNC;
}
}
if( find_option("private",0,0)!=0 ){
*pSyncFlags |= SYNC_PRIVATE;
}
if( find_option("verbose","v",0)!=0 ){
*pSyncFlags |= SYNC_VERBOSE;
}
if( find_option("no-http-compression",0,0)!=0 ){
*pSyncFlags |= SYNC_NOHTTPCOMPRESS;
}
if( find_option("all",0,0)!=0 ){
*pSyncFlags |= SYNC_ALLURL;
}
if( ((*pSyncFlags) & SYNC_PULL)!=0
&& find_option("share-links",0,0)!=0
){
*pSyncFlags |= SYNC_SHARE_LINKS;
}
/* Option: --transport-command COMMAND
**
** Causes COMMAND to be run with three arguments in order to talk
** to the server.
**
** COMMAND URL PAYLOAD REPLY
**
** URL is the server name. PAYLOAD is the name of a temporary file
** that will contain the xfer-protocol payload to send to the server.
** REPLY is a temporary filename in which COMMAND should write the
** content of the reply from the server.
**
** CMD is reponsible for HTTP redirects. The following Fossil command
** can be used for CMD to achieve a working sync:
**
** fossil test-httpmsg --xfer
*/
g.zHttpCmd = find_option("transport-command",0,1);
url_proxy_options();
clone_ssh_find_options();
if( !uvOnly ) db_find_and_open_repository(0, 0);
db_open_config(0, 1);
if( g.argc==2 ){
if( db_get_boolean("auto-shun",0) ) configSync = CONFIGSET_SHUN;
}else if( g.argc==3 ){
zUrl = g.argv[2];
if( (*pSyncFlags) & SYNC_ALLURL ){
fossil_fatal("cannot use both the --all option and specific URL \"%s\"",
zUrl);
}
}
if( ((*pSyncFlags) & (SYNC_PUSH|SYNC_PULL))==(SYNC_PUSH|SYNC_PULL)
&& db_get_boolean("uv-sync",0)
){
*pSyncFlags |= SYNC_UNVERSIONED;
}
urlFlags &= ~urlOmitFlags;
if( urlFlags & URL_REMEMBER ){
clone_ssh_db_set_options();
}
url_parse(zUrl, urlFlags|URL_USE_CONFIG);
remember_or_get_http_auth(zHttpAuth, urlFlags & URL_REMEMBER, zUrl);
if( g.url.protocol==0 ){
if( urlOptional ) fossil_exit(0);
usage("URL");
}
user_select();
url_enable_proxy("via proxy: ");
*pConfigFlags |= configSync;
}
/*
** COMMAND: pull
**
** Usage: %fossil pull ?URL? ?options?
**
** Pull all sharable changes from a remote repository into the local
** repository. Sharable changes include public check-ins, edits to
** wiki pages, tickets, tech-notes, and forum posts. Add
** the --private option to pull private branches. Use the
** "configuration pull" command to pull website configuration details.
**
** If URL is not specified, then the URL from the most recent clone, push,
** pull, remote, or sync command is used. See "fossil help clone" for
** details on the URL formats.
**
** Options:
**
** --all Pull from all remotes, not just the default
** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol,
** if required by the remote website
** --from-parent-project Pull content from the parent project
** --ipv4 Use only IPv4, not IPv6
** --no-http-compression Do not compress HTTP traffic
** --once Do not remember URL for subsequent syncs
** --private Pull private branches too
** --project-code CODE Use CODE as the project code
** --proxy PROXY Use the specified HTTP proxy
** -R|--repository REPO Local repository to pull into
** --share-links Share links to mirror repos
** --ssl-identity FILE Local SSL credentials, if requested by remote
** --ssh-command SSH Use SSH as the "ssh" command
** --transport-command CMD Use external command CMD to move messages
** between client and server
** -v|--verbose Additional (debugging) output
** --verily Exchange extra information with the remote
** to ensure no content is overlooked
**
** See also: [[clone]], [[config]], [[push]], [[remote]], [[sync]]
*/
void pull_cmd(void){
unsigned configFlags = 0;
unsigned syncFlags = SYNC_PULL;
unsigned urlOmitFlags = 0;
const char *zAltPCode = find_option("project-code",0,1);
if( find_option("from-parent-project",0,0)!=0 ){
syncFlags |= SYNC_FROMPARENT;
}
if( zAltPCode ) urlOmitFlags = URL_REMEMBER;
process_sync_args(&configFlags, &syncFlags, 0, urlOmitFlags);
/* We should be done with options.. */
verify_all_options();
client_sync_all_urls(syncFlags, configFlags, 0, zAltPCode);
}
/*
** COMMAND: push
**
** Usage: %fossil push ?URL? ?options?
**
** Push all sharable changes from the local repository to a remote
** repository. Sharable changes include public check-ins, edits to
** wiki pages, tickets, tech-notes, and forum posts. Use
** --private to also push private branches. Use the "configuration
** push" command to push website configuration details.
**
** If URL is not specified, then the URL from the most recent clone, push,
** pull, remote, or sync command is used. See "fossil help clone" for
** details on the URL formats.
**
** Options:
**
** --all Push to all remotes, not just the default
** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol,
** if required by the remote website
** --ipv4 Use only IPv4, not IPv6
** --no-http-compression Do not compress HTTP traffic
** --once Do not remember URL for subsequent syncs
** --proxy PROXY Use the specified HTTP proxy
** --private Push private branches too
** -R|--repository REPO Local repository to push from
** --ssl-identity FILE Local SSL credentials, if requested by remote
** --ssh-command SSH Use SSH as the "ssh" command
** --transport-command CMD Use external command CMD to communicate with
** the server
** -v|--verbose Additional (debugging) output
** --verily Exchange extra information with the remote
** to ensure no content is overlooked
**
** See also: [[clone]], [[config]], [[pull]], [[remote]], [[sync]]
*/
void push_cmd(void){
unsigned configFlags = 0;
unsigned syncFlags = SYNC_PUSH;
process_sync_args(&configFlags, &syncFlags, 0, 0);
/* We should be done with options.. */
verify_all_options();
if( db_get_boolean("dont-push",0) ){
fossil_fatal("pushing is prohibited: the 'dont-push' option is set");
}
client_sync_all_urls(syncFlags, 0, 0, 0);
}
/*
** COMMAND: sync
**
** Usage: %fossil sync ?URL? ?options?
**
** Synchronize all sharable changes between the local repository and a
** remote repository. Sharable changes include public check-ins and
** edits to wiki pages, tickets, forum posts, and technical notes.
**
** If URL is not specified, then the URL from the most recent clone, push,
** pull, remote, or sync command is used. See "fossil help clone" for
** details on the URL formats.
**
** Options:
**
** --all Sync with all remotes, not just the default
** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol,
** if required by the remote website
** --ipv4 Use only IPv4, not IPv6
** --no-http-compression Do not compress HTTP traffic
** --once Do not remember URL for subsequent syncs
** --proxy PROXY Use the specified HTTP proxy
** --private Sync private branches too
** -R|--repository REPO Local repository to sync with
** --share-links Share links to mirror repos
** --ssl-identity FILE Local SSL credentials, if requested by remote
** --ssh-command SSH Use SSH as the "ssh" command
** --transport-command CMD Use external command CMD to move message
** between the client and the server
** -u|--unversioned Also sync unversioned content
** -v|--verbose Additional (debugging) output
** --verily Exchange extra information with the remote
** to ensure no content is overlooked
**
** See also: [[clone]], [[pull]], [[push]], [[remote]]
*/
void sync_cmd(void){
unsigned configFlags = 0;
unsigned syncFlags = SYNC_PUSH|SYNC_PULL;
if( find_option("unversioned","u",0)!=0 ){
syncFlags |= SYNC_UNVERSIONED;
}
process_sync_args(&configFlags, &syncFlags, 0, 0);
/* We should be done with options.. */
verify_all_options();
if( db_get_boolean("dont-push",0) ) syncFlags &= ~SYNC_PUSH;
if( (syncFlags & SYNC_PUSH)==0 ){
fossil_warning("pull only: the 'dont-push' option is set");
}
client_sync_all_urls(syncFlags, configFlags, 0, 0);
}
/*
** Handle the "fossil unversioned sync" and "fossil unversioned revert"
** commands.
*/
void sync_unversioned(unsigned syncFlags){
unsigned configFlags = 0;
(void)find_option("uv-noop",0,0);
process_sync_args(&configFlags, &syncFlags, 1, 0);
verify_all_options();
client_sync(syncFlags, 0, 0, 0);
}
/*
** COMMAND: remote
** COMMAND: remote-url*
**
** Usage: %fossil remote ?SUBCOMMAND ...?
**
** View or modify the URLs of remote repositories used for syncing.
** The "default" remote is the URL used in the most recent "sync",
** "push", "pull", "clone", or similar command. The default remote can
** change with each sync command. Other named remotes are persistent.
**
** > fossil remote
**
** With no arguments, this command shows the current default remote
** URL. If there is no default, it shows "off".
**
** > fossil remote add NAME URL
**
** Add a new named URL. Afterwards, NAME can be used as a short
** symbolic name for URL in contexts where a URL is required. The
** URL argument can be "default" or a prior symbolic name, to make
** a copy of an existing URL under a new name.
**
** > fossil config-data
**
** DEBUG USE ONLY - Show the name and value of every CONFIG table
** entry in the repository that is associated with the remote URL store.
** Passwords are obscured in the output.
**
** > fossil remote delete NAME
**
** Delete a named URL previously created by the "add" subcommand.
**
** > fossil remote list|ls
**
** Show all remote repository URLs.
**
** > fossil remote off
**
** Forget the default URL. This disables autosync.
**
** This is a convenient way to enter "airplane mode". To enter
** airplane mode, first save the current default URL, then turn the
** default off. Perhaps like this:
**
** fossil remote add main default
** fossil remote off
**
** To exit airplane mode and turn autosync back on again:
**
** fossil remote main
**
** > fossil remote scrub
**
** Forget any saved passwords for remote repositories, but continue
** to remember the URLs themselves. You will be prompted for the
** password the next time it is needed.
**
** > fossil remote REF
**
** Make REF the new default URL, replacing the prior default.
** REF may be a URL or a NAME from a prior "add".
*/
void remote_url_cmd(void){
char *zUrl, *zArg;
int nArg;
db_find_and_open_repository(0, 0);
/* We should be done with options.. */
verify_all_options();
/* 2021-10-25: A note about data structures.
**
** The remote URLs are stored in the CONFIG table. The URL is stored
** separately from the password. The password is obscured using the
** obscure() function.
**
** Originally, Fossil only preserved a single remote URL. That URL
** is stored in "last-sync-url" and the password in "last-sync-pw". The
** ability to have multiple remotes was added later so these names
** were retained for backwards compatibility. The other remotes are
** stored in "sync-url:NAME" and "sync-pw:NAME" where NAME is the name
** of the remote.
**
** The last-sync-url is called "default" for the display list.
**
** The last-sync-url might be duplicated into one of the sync-url:NAME
** entries. Thus, when doing a "fossil sync --all" or an autosync with
** autosync=all, each sync-url:NAME entry is checked to see if it is the
** same as last-sync-url and if it is then that entry is skipped.
*/
if( g.argc==2 ){
/* "fossil remote" with no arguments: Show the last sync URL. */
zUrl = db_get("last-sync-url", 0);
if( zUrl==0 ){
fossil_print("off\n");
}else{
|
| ︙ | ︙ | |||
464 465 466 467 468 469 470 |
char *zUrl;
UrlData x;
if( g.argc!=5 ) usage("add NAME URL");
memset(&x, 0, sizeof(x));
zName = g.argv[3];
zUrl = g.argv[4];
if( strcmp(zName,"default")==0 ) goto remote_add_default;
| < > > > > > > | 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 |
char *zUrl;
UrlData x;
if( g.argc!=5 ) usage("add NAME URL");
memset(&x, 0, sizeof(x));
zName = g.argv[3];
zUrl = g.argv[4];
if( strcmp(zName,"default")==0 ) goto remote_add_default;
db_begin_write();
if( fossil_strcmp(zUrl,"default")==0 ){
x.canonical = db_get("last-sync-url",0);
x.passwd = unobscure(db_get("last-sync-pw",0));
}else{
url_parse_local(zUrl, URL_PROMPT_PW, &x);
}
db_unprotect(PROTECT_CONFIG);
db_multi_exec(
"REPLACE INTO config(name, value, mtime)"
" VALUES('sync-url:%q',%Q,now())",
zName, x.canonical
);
db_multi_exec(
|
| ︙ | ︙ | |||
493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 |
db_begin_write();
db_unprotect(PROTECT_CONFIG);
db_multi_exec("DELETE FROM config WHERE name glob 'sync-url:%q'", zName);
db_multi_exec("DELETE FROM config WHERE name glob 'sync-pw:%q'", zName);
db_protect_pop();
db_commit_transaction();
return;
}
if( sqlite3_strlike("http://%",zArg,0)==0
|| sqlite3_strlike("https://%",zArg,0)==0
|| sqlite3_strlike("ssh:%",zArg,0)==0
|| sqlite3_strlike("file:%",zArg,0)==0
|| db_exists("SELECT 1 FROM config WHERE name='sync-url:%q'",zArg)
){
remote_add_default:
db_unset("last-sync-url", 0);
db_unset("last-sync-pw", 0);
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 |
db_begin_write();
db_unprotect(PROTECT_CONFIG);
db_multi_exec("DELETE FROM config WHERE name glob 'sync-url:%q'", zName);
db_multi_exec("DELETE FROM config WHERE name glob 'sync-pw:%q'", zName);
db_protect_pop();
db_commit_transaction();
return;
}
if( strncmp(zArg, "scrub", nArg)==0 ){
if( g.argc!=3 ) usage("scrub");
db_begin_write();
db_unprotect(PROTECT_CONFIG);
db_multi_exec("DELETE FROM config WHERE name glob 'sync-pw:*'");
db_multi_exec("DELETE FROM config WHERE name = 'last-sync-pw'");
db_protect_pop();
db_commit_transaction();
return;
}
if( strncmp(zArg, "config-data", nArg)==0 ){
/* Undocumented command: "fossil remote config-data"
**
** Show the CONFIG table entries that relate to remembering remote URLs
*/
Stmt q;
int n;
n = db_int(13,
"SELECT max(length(name))"
" FROM config"
" WHERE name GLOB 'sync-*:*' OR name GLOB 'last-sync-*'"
);
db_prepare(&q,
"SELECT name,"
" CASE WHEN name LIKE '%%sync-pw%%'"
" THEN printf('%%.*c',length(value),'*') ELSE value END"
" FROM config"
" WHERE name GLOB 'sync-*:*' OR name GLOB 'last-sync-*'"
" ORDER BY name LIKE '%%sync-pw%%', name"
);
while( db_step(&q)==SQLITE_ROW ){
fossil_print("%-*s %s\n",
n, db_column_text(&q,0),
db_column_text(&q,1)
);
}
db_finalize(&q);
return;
}
if( sqlite3_strlike("http://%",zArg,0)==0
|| sqlite3_strlike("https://%",zArg,0)==0
|| sqlite3_strlike("ssh:%",zArg,0)==0
|| sqlite3_strlike("file:%",zArg,0)==0
|| db_exists("SELECT 1 FROM config WHERE name='sync-url:%q'",zArg)
){
remote_add_default:
db_unset("last-sync-url", 0);
db_unset("last-sync-pw", 0);
url_parse(g.argv[2], URL_REMEMBER|URL_PROMPT_PW|
URL_USE_CONFIG|URL_ASK_REMEMBER_PW);
url_remember();
return;
}
fossil_fatal("unknown command \"%s\" - should be a URL or one of: "
"add delete list off", zArg);
}
|
| ︙ | ︙ |
Changes to src/tar.c.
| ︙ | ︙ | |||
15 16 17 18 19 20 21 | ** ******************************************************************************* ** ** This file contains code used to generate tarballs. */ #include "config.h" #include <assert.h> | < < < < | < | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
**
*******************************************************************************
**
** This file contains code used to generate tarballs.
*/
#include "config.h"
#include <assert.h>
#include <zlib.h>
#include "tar.h"
/*
** State information for the tarball builder.
*/
static struct tarball_t {
unsigned char *aHdr; /* Space for building headers */
|
| ︙ | ︙ | |||
526 527 528 529 530 531 532 |
if( eflg & (MFESTFLG_RAW|MFESTFLG_UUID) ){
if( eflg & MFESTFLG_RAW ){
blob_append(&filename, "manifest", -1);
zName = blob_str(&filename);
if( listFlag ) fossil_print("%s\n", zName);
if( pTar ){
| < | 521 522 523 524 525 526 527 528 529 530 531 532 533 534 |
if( eflg & (MFESTFLG_RAW|MFESTFLG_UUID) ){
if( eflg & MFESTFLG_RAW ){
blob_append(&filename, "manifest", -1);
zName = blob_str(&filename);
if( listFlag ) fossil_print("%s\n", zName);
if( pTar ){
tar_add_file(zName, &mfile, 0, mTime);
}
}
}
blob_reset(&mfile);
if( eflg & MFESTFLG_UUID ){
blob_resize(&filename, nPrefix);
|
| ︙ | ︙ |
Changes to src/th_main.c.
| ︙ | ︙ | |||
845 846 847 848 849 850 851 |
}else if( azCap[i][0]=='@' ){
rc = login_has_capability(azCap[i]+1, anCap[i]-1, LOGIN_ANON);
}else if( azCap[i][0]=='*' ){
rc = 1;
}else{
rc = login_has_capability(azCap[i], anCap[i], 0);
}
| | | 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 |
}else if( azCap[i][0]=='@' ){
rc = login_has_capability(azCap[i]+1, anCap[i]-1, LOGIN_ANON);
}else if( azCap[i][0]=='*' ){
rc = 1;
}else{
rc = login_has_capability(azCap[i], anCap[i], 0);
}
if( rc ) break;
}
Th_Free(interp, azCap);
Th_SetResultInt(interp, rc);
return TH_OK;
}
|
| ︙ | ︙ |
Changes to src/timeline.c.
| ︙ | ︙ | |||
1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 |
** forks Show only forks and their children
** cherrypicks Show all cherrypicks
** ym=YYYY-MM Show only events for the given year/month
** yw=YYYY-WW Show only events for the given week of the given year
** yw=YYYY-MM-DD Show events for the week that includes the given day
** ymd=YYYY-MM-DD Show only events on the given day. The use "ymd=now"
** to see all changes for the current week.
** days=N Show events over the previous N days
** datefmt=N Override the date format: 0=HH:MM, 1=HH:MM:SS,
** 2=YYYY-MM-DD HH:MM:SS, 3=YYMMDD HH:MM, and 4 means "off".
** bisect Show the check-ins that are in the current bisect
** showid Show RIDs
** showsql Show the SQL text
**
** p= and d= can appear individually or together. If either p= or d=
** appear, then u=, y=, a=, and b= are ignored.
**
** If both a= and b= appear then both upper and lower bounds are honored.
**
** CHECKIN or TIMEORTAG can be a check-in hash prefix, or a tag, or the
** name of a branch.
*/
void page_timeline(void){
Stmt q; /* Query used to generate the timeline */
Blob sql; /* text of SQL used to generate timeline */
| > > > > > > | 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 |
** forks Show only forks and their children
** cherrypicks Show all cherrypicks
** ym=YYYY-MM Show only events for the given year/month
** yw=YYYY-WW Show only events for the given week of the given year
** yw=YYYY-MM-DD Show events for the week that includes the given day
** ymd=YYYY-MM-DD Show only events on the given day. The use "ymd=now"
** to see all changes for the current week.
** year=YYYY Show only events on the given year. The use "year=0"
** to see all changes for the current year.
** days=N Show events over the previous N days
** datefmt=N Override the date format: 0=HH:MM, 1=HH:MM:SS,
** 2=YYYY-MM-DD HH:MM:SS, 3=YYMMDD HH:MM, and 4 means "off".
** bisect Show the check-ins that are in the current bisect
** showid Show RIDs
** showsql Show the SQL text
**
** p= and d= can appear individually or together. If either p= or d=
** appear, then u=, y=, a=, and b= are ignored.
**
** If both a= and b= appear then both upper and lower bounds are honored.
**
** When multiple time-related filters are used, e.g. ym, yw, and ymd,
** which one(s) is/are applied is unspecified and may change between
** fossil versions.
**
** CHECKIN or TIMEORTAG can be a check-in hash prefix, or a tag, or the
** name of a branch.
*/
void page_timeline(void){
Stmt q; /* Query used to generate the timeline */
Blob sql; /* text of SQL used to generate timeline */
|
| ︙ | ︙ | |||
1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 |
const char *zTagSql = 0; /* Tag/branch match SQL expression */
const char *zSearch = P("s"); /* Search string */
const char *zUses = P("uf"); /* Only show check-ins hold this file */
const char *zYearMonth = P("ym"); /* Show check-ins for the given YYYY-MM */
const char *zYearWeek = P("yw"); /* Check-ins for YYYY-WW (week-of-year) */
char *zYearWeekStart = 0; /* YYYY-MM-DD for start of YYYY-WW */
const char *zDay = P("ymd"); /* Check-ins for the day YYYY-MM-DD */
const char *zNDays = P("days"); /* Show events over the previous N days */
int nDays = 0; /* Numeric value for zNDays */
const char *zChng = P("chng"); /* List of GLOBs for files that changed */
int useDividers = P("nd")==0; /* Show dividers if "nd" is missing */
int renameOnly = P("namechng")!=0; /* Show only check-ins that rename files */
int forkOnly = PB("forks"); /* Show only forks and their children */
int bisectLocal = PB("bisect"); /* Show the check-ins of the bisect */
| > | 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 |
const char *zTagSql = 0; /* Tag/branch match SQL expression */
const char *zSearch = P("s"); /* Search string */
const char *zUses = P("uf"); /* Only show check-ins hold this file */
const char *zYearMonth = P("ym"); /* Show check-ins for the given YYYY-MM */
const char *zYearWeek = P("yw"); /* Check-ins for YYYY-WW (week-of-year) */
char *zYearWeekStart = 0; /* YYYY-MM-DD for start of YYYY-WW */
const char *zDay = P("ymd"); /* Check-ins for the day YYYY-MM-DD */
const char *zYear = P("year"); /* Events for the year YYYY */
const char *zNDays = P("days"); /* Show events over the previous N days */
int nDays = 0; /* Numeric value for zNDays */
const char *zChng = P("chng"); /* List of GLOBs for files that changed */
int useDividers = P("nd")==0; /* Show dividers if "nd" is missing */
int renameOnly = P("namechng")!=0; /* Show only check-ins that rename files */
int forkOnly = PB("forks"); /* Show only forks and their children */
int bisectLocal = PB("bisect"); /* Show the check-ins of the bisect */
|
| ︙ | ︙ | |||
2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 |
}
else if( zNDays ){
nDays = atoi(zNDays);
if( nDays<1 ) nDays = 1;
blob_append_sql(&cond, " AND event.mtime>=julianday('now','-%d days') ",
nDays);
nEntry = -1;
}
if( zTagSql ){
db_multi_exec(
"CREATE TEMP TABLE selected_nodes(rid INTEGER PRIMARY KEY);"
"INSERT OR IGNORE INTO selected_nodes"
" SELECT tagxref.rid FROM tagxref NATURAL JOIN tag"
" WHERE %s AND tagtype>0", zTagSql/*safe-for-%s*/
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 |
}
else if( zNDays ){
nDays = atoi(zNDays);
if( nDays<1 ) nDays = 1;
blob_append_sql(&cond, " AND event.mtime>=julianday('now','-%d days') ",
nDays);
nEntry = -1;
}
else if( zYear &&
((4==strlen(zYear) && atoi(zYear)>1900)
|| (1==strlen(zYear) && 0==atoi(zYear)))){
int year = atoi(zYear);
char *zNext = 0;
if(0==year){/*use current year*/
Stmt qy;
db_prepare(&qy, "SELECT strftime('%%Y','now')");
db_step(&qy);
year = db_column_int(&qy, 0);
zYear = fossil_strdup(db_column_text(&qy, 0));
db_finalize(&qy);
}else{
zNext = mprintf("%d", year+1);
if( db_int(0,
"SELECT EXISTS (SELECT 1 FROM event CROSS JOIN blob"
" WHERE blob.rid=event.objid AND strftime('%%Y',mtime)=%Q %s)",
zNext, blob_sql_text(&cond))
){
zNewerButton = fossil_strdup(url_render(&url, "year", zNext, 0, 0));
zNewerButtonLabel = "Following year";
}
fossil_free(zNext);
}
zNext = mprintf("%d", year-1);
if( db_int(0,
"SELECT EXISTS (SELECT 1 FROM event CROSS JOIN blob"
" WHERE blob.rid=event.objid AND strftime('%%Y',mtime)=%Q %s)",
zNext, blob_sql_text(&cond))
){
zOlderButton = fossil_strdup(url_render(&url, "year", zNext, 0, 0));
zOlderButtonLabel = "Previous year";
}
fossil_free(zNext);
blob_append_sql(&cond, " AND %Q=strftime('%%Y',event.mtime) ",
zYear);
nEntry = -1;
}
if( zTagSql ){
db_multi_exec(
"CREATE TEMP TABLE selected_nodes(rid INTEGER PRIMARY KEY);"
"INSERT OR IGNORE INTO selected_nodes"
" SELECT tagxref.rid FROM tagxref NATURAL JOIN tag"
" WHERE %s AND tagtype>0", zTagSql/*safe-for-%s*/
|
| ︙ | ︙ |
Changes to src/tktsetup.c.
| ︙ | ︙ | |||
535 536 537 538 539 540 541 542 543 544 545 |
@ if {$seenRow} {
@ html "<hr />\n"
@ } else {
@ html "<tr><td class='tktDspLabel'>User Comments:</td></tr>\n"
@ html "<tr><td colspan='5' class='tktDspValue'>\n"
@ set seenRow 1
@ }
@ html "[htmlize $xlogin]"
@ if {$xlogin ne $xusername && [string length $xusername]>0} {
@ html " (claiming to be [htmlize $xusername])"
@ }
| > | > | 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 |
@ if {$seenRow} {
@ html "<hr />\n"
@ } else {
@ html "<tr><td class='tktDspLabel'>User Comments:</td></tr>\n"
@ html "<tr><td colspan='5' class='tktDspValue'>\n"
@ set seenRow 1
@ }
@ html "<span class='tktDspCommenter'>"
@ html "[htmlize $xlogin]"
@ if {$xlogin ne $xusername && [string length $xusername]>0} {
@ html " (claiming to be [htmlize $xusername])"
@ }
@ html " added on $xdate:"
@ html "</span>\n"
@ if {$alwaysPlaintext || $xmimetype eq "text/plain"} {
@ set r [randhex]
@ if {$xmimetype ne "text/plain"} {html "([htmlize $xmimetype])\n"}
@ wiki "<verbatim-$r>[string trimright $xcomment]</verbatim-$r>\n"
@ } elseif {$xmimetype eq "text/x-fossil-wiki"} {
@ wiki "<p>\n[string trimright $xcomment]\n</p>\n"
@ } elseif {$xmimetype eq "text/x-markdown"} {
|
| ︙ | ︙ |
Changes to src/unversioned.c.
| ︙ | ︙ | |||
15 16 17 18 19 20 21 | ** ******************************************************************************* ** ** This file contains code used to implement unversioned file interfaces. */ #include "config.h" #include <assert.h> | < < < < | < | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | ** ******************************************************************************* ** ** This file contains code used to implement unversioned file interfaces. */ #include "config.h" #include <assert.h> #include <zlib.h> #include "unversioned.h" #include <time.h> /* ** SQL code to implement the tables needed by the unversioned. */ static const char zUnversionedInit[] = |
| ︙ | ︙ |
Changes to src/update.c.
| ︙ | ︙ | |||
514 515 516 517 518 519 520 521 522 523 |
}
if( rc>0 ){
fossil_print("***** %d merge conflicts in %s\n", rc, zNewName);
nConflict++;
}
}else{
if( !dryRunFlag ){
blob_write_to_file(&t, zFullNewPath);
file_setexe(zFullNewPath, isexe);
}
| > > > > > > > > | > > > > | 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 |
}
if( rc>0 ){
fossil_print("***** %d merge conflicts in %s\n", rc, zNewName);
nConflict++;
}
}else{
if( !dryRunFlag ){
if( !keepMergeFlag ){
/* Name of backup file with Original content */
char *zOrig = file_newname(zFullPath, "original", 1);
/* Backup non-mergeable binary file when --keep-merge-files is
not specified */
file_copy(zFullPath, zOrig);
fossil_free(zOrig);
}
blob_write_to_file(&t, zFullNewPath);
file_setexe(zFullNewPath, isexe);
}
fossil_print("***** Cannot merge binary file %s", zNewName);
if( !dryRunFlag ){
fossil_print(", original copy backed up locally");
}
fossil_print("\n");
nConflict++;
}
}
if( nameChng && !dryRunFlag ) file_delete(zFullPath);
blob_reset(&v);
blob_reset(&t);
blob_reset(&r);
|
| ︙ | ︙ |
Changes to src/url.c.
| ︙ | ︙ | |||
37 38 39 40 41 42 43 44 45 46 47 48 |
*/
#define URL_PROMPT_PW 0x001 /* Prompt for password if needed */
#define URL_REMEMBER 0x002 /* Remember the url for later reuse */
#define URL_ASK_REMEMBER_PW 0x004 /* Ask whether to remember prompted pw */
#define URL_REMEMBER_PW 0x008 /* Should remember pw */
#define URL_PROMPTED 0x010 /* Prompted for PW already */
#define URL_OMIT_USER 0x020 /* Omit the user name from URL */
/*
** The URL related data used with this subsystem.
*/
struct UrlData {
| > > | | | | | | | | | | | | | | | | | | < | < > > > > > > > > > > > | > > > > > > > > > | > | | | | | | | | | | | | | | | | | | | > > > | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
*/
#define URL_PROMPT_PW 0x001 /* Prompt for password if needed */
#define URL_REMEMBER 0x002 /* Remember the url for later reuse */
#define URL_ASK_REMEMBER_PW 0x004 /* Ask whether to remember prompted pw */
#define URL_REMEMBER_PW 0x008 /* Should remember pw */
#define URL_PROMPTED 0x010 /* Prompted for PW already */
#define URL_OMIT_USER 0x020 /* Omit the user name from URL */
#define URL_USE_CONFIG 0x040 /* Use remembered URLs from CONFIG table */
#define URL_USE_PARENT 0x080 /* Use the URL of the parent project */
/*
** The URL related data used with this subsystem.
*/
struct UrlData {
int isFile; /* True if a "file:" url */
int isHttps; /* True if a "https:" url */
int isSsh; /* True if an "ssh:" url */
int isAlias; /* Input URL was an alias */
char *name; /* Hostname for http: or filename for file: */
char *hostname; /* The HOST: parameter on http headers */
const char *protocol; /* "http" or "https" or "ssh" or "file" */
int port; /* TCP port number for http: or https: */
int dfltPort; /* The default port for the given protocol */
char *path; /* Pathname for http: */
char *user; /* User id for http: */
char *passwd; /* Password for http: */
char *canonical; /* Canonical representation of the URL */
char *proxyAuth; /* Proxy-Authorizer: string */
char *fossil; /* The fossil query parameter on ssh: */
unsigned flags; /* Boolean flags controlling URL processing */
int useProxy; /* Used to remember that a proxy is in use */
char *proxyUrlPath;
int proxyOrigPort; /* Tunneled port number for https through proxy */
};
#endif /* INTERFACE */
/*
** Parse the URL in the zUrl argument. Store results in the pUrlData object.
** Populate members of pUrlData as follows:
**
** isFile True if FILE:
** isHttps True if HTTPS:
** isSsh True if SSH:
** protocol "http" or "https" or "file" or "ssh"
** name Hostname for HTTP:, HTTPS:, SSH:. Filename for FILE:
** port TCP port number for HTTP or HTTPS.
** dfltPort Default TCP port number (80 or 443).
** path Path name for HTTP or HTTPS.
** user Userid.
** passwd Password.
** hostname HOST:PORT or just HOST if port is the default.
** canonical The URL in canonical form, omitting the password
**
** If zUrl==0 and URL_USE_CONFIG is set, then parse the URL stored
** in last-sync-url and last-sync-pw of the CONFIG table. Or if
** URL_USE_PARENT is also set, then use parent-project-url and
** parent-project-pw from the CONFIG table instead of last-sync-url
** and last-sync-pw.
**
** If zUrl is a symbolic name and URL_USE_CONFIG is true, then look up
** the URL in sync-url:%Q and sync-pw:%Q elements of the CONFIG table where
** %Q is the symbolic name.
**
** This routine differs from url_parse() in that this routine stores the
** results in pUrlData and does not change the values of global variables.
** The url_parse() routine puts its result in g.url.
*/
void url_parse_local(
const char *zUrl,
unsigned int urlFlags,
UrlData *pUrlData
){
int i, j, c;
char *zFile = 0;
if( urlFlags & URL_USE_CONFIG ){
if( zUrl==0 || strcmp(zUrl,"default")==0 ){
const char *zPwConfig = "last-sync-pw";
if( urlFlags & URL_USE_PARENT ){
zUrl = db_get("parent-project-url", 0);
if( zUrl==0 ){
zUrl = db_get("last-sync-url",0);
}else{
zPwConfig = "parent-project-pw";
}
}else{
zUrl = db_get("last-sync-url", 0);
}
if( zUrl==0 ) return;
if( pUrlData->passwd==0 ){
pUrlData->passwd = unobscure(db_get(zPwConfig, 0));
}
pUrlData->isAlias = 1;
}else{
char *zKey = sqlite3_mprintf("sync-url:%q", zUrl);
char *zAlt = db_get(zKey, 0);
sqlite3_free(zKey);
if( zAlt ){
pUrlData->passwd = unobscure(
db_text(0, "SELECT value FROM config WHERE name='sync-pw:%q'",zUrl)
);
zUrl = zAlt;
urlFlags |= URL_REMEMBER_PW;
pUrlData->isAlias = 1;
}else{
pUrlData->isAlias = 0;
}
}
}else{
if( zUrl==0 ) return;
}
if( strncmp(zUrl, "http://", 7)==0
|| strncmp(zUrl, "https://", 8)==0
|| strncmp(zUrl, "ssh://", 6)==0
){
int iStart;
|
| ︙ | ︙ | |||
139 140 141 142 143 144 145 |
pUrlData->protocol = "https";
pUrlData->dfltPort = 443;
iStart = 8;
}else if( zUrl[0]=='s' ){
pUrlData->isSsh = 1;
pUrlData->protocol = "ssh";
pUrlData->dfltPort = 22;
| | | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
pUrlData->protocol = "https";
pUrlData->dfltPort = 443;
iStart = 8;
}else if( zUrl[0]=='s' ){
pUrlData->isSsh = 1;
pUrlData->protocol = "ssh";
pUrlData->dfltPort = 22;
pUrlData->fossil = fossil_strdup("fossil");
iStart = 6;
}else{
pUrlData->isHttps = 0;
pUrlData->protocol = "http";
pUrlData->dfltPort = 80;
iStart = 7;
}
|
| ︙ | ︙ | |||
224 225 226 227 228 229 230 |
while( pUrlData->path[i] && pUrlData->path[i]!='&' ){ i++; }
}
if( pUrlData->path[i] ){
pUrlData->path[i] = 0;
i++;
}
if( fossil_strcmp(zName,"fossil")==0 ){
| | | > > > > | 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 |
while( pUrlData->path[i] && pUrlData->path[i]!='&' ){ i++; }
}
if( pUrlData->path[i] ){
pUrlData->path[i] = 0;
i++;
}
if( fossil_strcmp(zName,"fossil")==0 ){
pUrlData->fossil = fossil_strdup(zValue);
dehttpize(pUrlData->fossil);
fossil_free(zExe);
zExe = mprintf("%cfossil=%T", cQuerySep, pUrlData->fossil);
cQuerySep = '&';
}
}
dehttpize(pUrlData->path);
if( pUrlData->dfltPort==pUrlData->port ){
pUrlData->canonical = mprintf(
"%s://%s%T%T%z",
pUrlData->protocol, zLogin, pUrlData->name, pUrlData->path, zExe
);
}else{
pUrlData->canonical = mprintf(
"%s://%s%T:%d%T%z",
pUrlData->protocol, zLogin, pUrlData->name, pUrlData->port,
pUrlData->path, zExe
);
}
if( pUrlData->isSsh && pUrlData->path[1] ){
char *zOld = pUrlData->path;
pUrlData->path = mprintf("%s", zOld+1);
fossil_free(zOld);
}
free(zLogin);
}else if( strncmp(zUrl, "file:", 5)==0 ){
pUrlData->isFile = 1;
if( zUrl[5]=='/' && zUrl[6]=='/' ){
i = 7;
}else{
i = 5;
|
| ︙ | ︙ | |||
278 279 280 281 282 283 284 |
if( pUrlData->isFile ){
Blob cfile;
dehttpize(zFile);
file_canonical_name(zFile, &cfile, 0);
free(zFile);
zFile = 0;
pUrlData->protocol = "file";
| | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 |
if( pUrlData->isFile ){
Blob cfile;
dehttpize(zFile);
file_canonical_name(zFile, &cfile, 0);
free(zFile);
zFile = 0;
pUrlData->protocol = "file";
pUrlData->path = mprintf("");
pUrlData->name = mprintf("%b", &cfile);
pUrlData->canonical = mprintf("file://%T", pUrlData->name);
blob_reset(&cfile);
}else if( pUrlData->user!=0 && pUrlData->passwd==0
&& (urlFlags & URL_PROMPT_PW)!=0 ){
url_prompt_for_password_local(pUrlData);
}else if( pUrlData->user!=0 && ( urlFlags & URL_ASK_REMEMBER_PW ) ){
if( isatty(fileno(stdin)) && ( urlFlags & URL_REMEMBER_PW )==0 ){
if( save_password_prompt(pUrlData->passwd) ){
pUrlData->flags = urlFlags |= URL_REMEMBER_PW;
}else{
pUrlData->flags = urlFlags &= ~URL_REMEMBER_PW;
}
}
}
}
/*
** Construct the complete URL for a UrlData object, including the
** login name and password, into memory obtained from fossil_malloc()
** and return a pointer to that URL text.
*/
char *url_full(const UrlData *p){
Blob x = BLOB_INITIALIZER;
if( p->isFile || p->user==0 || p->user[0]==0 ){
return fossil_strdup(p->canonical);
}
blob_appendf(&x, "%s://", p->protocol);
if( p->user && p->user[0] ){
blob_appendf(&x, "%t", p->user);
if( p->passwd && p->passwd[0] ){
blob_appendf(&x, ":%t", p->passwd);
}
blob_appendf(&x, "@");
}
blob_appendf(&x, "%T", p->name);
if( p->dfltPort!=p->port ){
blob_appendf(&x, ":%d", p->port);
}
blob_appendf(&x, "%T", p->path);
(void)blob_str(&x);
return x.aData;
}
/*
** Construct a URL for a UrlData object that omits the
** login name and password, into memory obtained from fossil_malloc()
** and return a pointer to that URL text.
*/
char *url_nouser(const UrlData *p){
Blob x = BLOB_INITIALIZER;
if( p->isFile || p->user==0 || p->user[0]==0 ){
return fossil_strdup(p->canonical);
}
blob_appendf(&x, "%s://", p->protocol);
blob_appendf(&x, "%T", p->name);
if( p->dfltPort!=p->port ){
blob_appendf(&x, ":%d", p->port);
}
blob_appendf(&x, "%T", p->path);
(void)blob_str(&x);
return x.aData;
}
/*
** SQL function to remove the username/password from a URL
*/
void url_nouser_func(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const char *zOrig = (const char*)sqlite3_value_text(argv[0]);
UrlData x;
if( zOrig==0 ) return;
memset(&x, 0, sizeof(x));
url_parse_local(zOrig, URL_OMIT_USER, &x);
sqlite3_result_text(context, x.canonical, -1, SQLITE_TRANSIENT);
url_unparse(&x);
}
/*
** Reclaim malloced memory from a UrlData object
*/
void url_unparse(UrlData *p){
if( p==0 ){
p = &g.url;
}
fossil_free(p->canonical);
fossil_free(p->name);
fossil_free(p->path);
fossil_free(p->user);
fossil_free(p->passwd);
fossil_free(p->fossil);
memset(p, 0, sizeof(*p));
}
/*
** Parse the given URL, which describes a sync server. Populate variables
** in the global "g.url" structure as shown below. If zUrl is NULL, then
** parse the URL given in the last-sync-url setting, taking the password
|
| ︙ | ︙ | |||
379 380 381 382 383 384 385 386 387 388 389 390 391 392 |
fossil_print("g.url.hostname = %s\n", g.url.hostname);
fossil_print("g.url.path = %s\n", g.url.path);
fossil_print("g.url.user = %s\n", g.url.user);
fossil_print("g.url.passwd = %s\n", g.url.passwd);
fossil_print("g.url.canonical = %s\n", g.url.canonical);
fossil_print("g.url.fossil = %s\n", g.url.fossil);
fossil_print("g.url.flags = 0x%02x\n", g.url.flags);
if( g.url.isFile || g.url.isSsh ) break;
if( i==0 ){
fossil_print("********\n");
url_enable_proxy("Using proxy: ");
}
url_unparse(0);
}
| > | 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 |
fossil_print("g.url.hostname = %s\n", g.url.hostname);
fossil_print("g.url.path = %s\n", g.url.path);
fossil_print("g.url.user = %s\n", g.url.user);
fossil_print("g.url.passwd = %s\n", g.url.passwd);
fossil_print("g.url.canonical = %s\n", g.url.canonical);
fossil_print("g.url.fossil = %s\n", g.url.fossil);
fossil_print("g.url.flags = 0x%02x\n", g.url.flags);
fossil_print("url_full(g.url) = %z\n", url_full(&g.url));
if( g.url.isFile || g.url.isSsh ) break;
if( i==0 ){
fossil_print("********\n");
url_enable_proxy("Using proxy: ");
}
url_unparse(0);
}
|
| ︙ | ︙ | |||
597 598 599 600 601 602 603 |
void url_prompt_for_password_local(UrlData *pUrlData){
if( pUrlData->isSsh || pUrlData->isFile ) return;
if( isatty(fileno(stdin))
&& (pUrlData->flags & URL_PROMPT_PW)!=0
&& (pUrlData->flags & URL_PROMPTED)==0
){
pUrlData->flags |= URL_PROMPTED;
| | | 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 |
void url_prompt_for_password_local(UrlData *pUrlData){
if( pUrlData->isSsh || pUrlData->isFile ) return;
if( isatty(fileno(stdin))
&& (pUrlData->flags & URL_PROMPT_PW)!=0
&& (pUrlData->flags & URL_PROMPTED)==0
){
pUrlData->flags |= URL_PROMPTED;
pUrlData->passwd = prompt_for_user_password(pUrlData->canonical);
if( pUrlData->passwd[0]
&& (pUrlData->flags & (URL_REMEMBER|URL_ASK_REMEMBER_PW))!=0
){
if( save_password_prompt(pUrlData->passwd) ){
pUrlData->flags |= URL_REMEMBER_PW;
}else{
pUrlData->flags &= ~URL_REMEMBER_PW;
|
| ︙ | ︙ | |||
626 627 628 629 630 631 632 |
}
/*
** Remember the URL and password if requested.
*/
void url_remember(void){
if( g.url.flags & URL_REMEMBER ){
| > > > | > > > > | > | 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 |
}
/*
** Remember the URL and password if requested.
*/
void url_remember(void){
if( g.url.flags & URL_REMEMBER ){
if( g.url.flags & URL_USE_PARENT ){
db_set("parent-project-url", g.url.canonical, 0);
}else{
db_set("last-sync-url", g.url.canonical, 0);
}
if( g.url.user!=0 && g.url.passwd!=0 && ( g.url.flags & URL_REMEMBER_PW ) ){
if( g.url.flags & URL_USE_PARENT ){
db_set("parent-project-pw", obscure(g.url.passwd), 0);
}else{
db_set("last-sync-pw", obscure(g.url.passwd), 0);
}
}
}
}
/* Preemptively prompt for a password if a username is given in the
** URL but no password.
*/
|
| ︙ | ︙ |
Changes to src/user.c.
| ︙ | ︙ | |||
268 269 270 271 272 273 274 |
/*
** Prompt to save Fossil user password
*/
int save_password_prompt(const char *passwd){
Blob x;
char c;
| < < < < | 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
/*
** Prompt to save Fossil user password
*/
int save_password_prompt(const char *passwd){
Blob x;
char c;
if( fossil_security_level()>=1 ) return 0;
prompt_user("remember password (Y/n)? ", &x);
c = blob_str(&x)[0];
blob_reset(&x);
return ( c!='n' && c!='N' );
}
|
| ︙ | ︙ | |||
538 539 540 541 542 543 544 |
if( attempt_user(fossil_getenv("USER")) ) return;
if( attempt_user(fossil_getenv("LOGNAME")) ) return;
if( attempt_user(fossil_getenv("USERNAME")) ) return;
memset(&url, 0, sizeof(url));
| | | 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 |
if( attempt_user(fossil_getenv("USER")) ) return;
if( attempt_user(fossil_getenv("LOGNAME")) ) return;
if( attempt_user(fossil_getenv("USERNAME")) ) return;
memset(&url, 0, sizeof(url));
url_parse_local(0, URL_USE_CONFIG, &url);
if( url.user && attempt_user(url.user) ) return;
fossil_print(
"Cannot figure out who you are! Consider using the --user\n"
"command line option, setting your USER environment variable,\n"
"or setting a default user with \"fossil user default USER\".\n"
);
|
| ︙ | ︙ | |||
568 569 570 571 572 573 574 |
fossil_print("checkout default-user: %s\n", g.localOpen ?
db_lget("default-user","") : "<<no open checkout>>");
fossil_print("default-user: %s\n", db_get("default-user",""));
fossil_print("FOSSIL_USER: %s\n", fossil_getenv("FOSSIL_USER"));
fossil_print("USER: %s\n", fossil_getenv("USER"));
fossil_print("LOGNAME: %s\n", fossil_getenv("LOGNAME"));
fossil_print("USERNAME: %s\n", fossil_getenv("USERNAME"));
| | | 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 |
fossil_print("checkout default-user: %s\n", g.localOpen ?
db_lget("default-user","") : "<<no open checkout>>");
fossil_print("default-user: %s\n", db_get("default-user",""));
fossil_print("FOSSIL_USER: %s\n", fossil_getenv("FOSSIL_USER"));
fossil_print("USER: %s\n", fossil_getenv("USER"));
fossil_print("LOGNAME: %s\n", fossil_getenv("LOGNAME"));
fossil_print("USERNAME: %s\n", fossil_getenv("USERNAME"));
url_parse(0, URL_USE_CONFIG);
fossil_print("URL user: %s\n", g.url.user);
user_select();
fossil_print("Final g.zLogin: %s\n", g.zLogin);
fossil_print("Final g.userUid: %d\n", g.userUid);
}
|
| ︙ | ︙ |
Changes to src/util.c.
| ︙ | ︙ | |||
643 644 645 646 647 648 649 650 651 652 653 654 655 656 |
}
/*
** Construct a temporary filename.
**
** The returned string is obtained from sqlite3_malloc() and must be
** freed by the caller.
*/
char *fossil_temp_filename(void){
char *zTFile = 0;
const char *zDir;
char cDirSep;
char zSep[2];
size_t nDir;
| > > | 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 |
}
/*
** Construct a temporary filename.
**
** The returned string is obtained from sqlite3_malloc() and must be
** freed by the caller.
**
** See also: file_tempname() and file_time_timename();
*/
char *fossil_temp_filename(void){
char *zTFile = 0;
const char *zDir;
char cDirSep;
char zSep[2];
size_t nDir;
|
| ︙ | ︙ |
Changes to src/wiki.c.
| ︙ | ︙ | |||
227 228 229 230 231 232 233 |
int w, h;
char *zOut = pikchr(zPikchr, "pikchr", 0, &w, &h);
if( w>0 ){
@ <div class="pikchr-svg" style="max-width:%d(w)px">
@ %s(zOut)
@ </div>
}else{
| | | | 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
int w, h;
char *zOut = pikchr(zPikchr, "pikchr", 0, &w, &h);
if( w>0 ){
@ <div class="pikchr-svg" style="max-width:%d(w)px">
@ %s(zOut)
@ </div>
}else{
@ <pre class='error'>
@ %h(zOut)
@ </pre>
}
free(zOut);
}else{
@ <pre class='textPlain'>
@ %h(blob_str(pWiki))
@ </pre>
|
| ︙ | ︙ | |||
798 799 800 801 802 803 804 |
}
/*
** Given a mimetype, return its common name.
*/
static const char *mimetype_common_name(const char *zMimetype){
int i;
| | | 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 |
}
/*
** Given a mimetype, return its common name.
*/
static const char *mimetype_common_name(const char *zMimetype){
int i;
for(i=6; i>=0; i-=3){
if( zMimetype && fossil_strcmp(zMimetype, azStyles[i])==0 ){
return azStyles[i+1];
}
}
return azStyles[1];
}
|
| ︙ | ︙ | |||
1724 1725 1726 1727 1728 1729 1730 |
** URL: /wikiappend?name=PAGENAME&mimetype=MIMETYPE
**
** Append text to the end of a wiki page.
*/
void wikiappend_page(void){
char *zTag;
int rid = 0;
| < > > > > > > | > | < | < < > | < < < < < < | < < | < < | | | | | | | | | | | | | | | | | | | | | | | < > > | > > > > > | | 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 |
** URL: /wikiappend?name=PAGENAME&mimetype=MIMETYPE
**
** Append text to the end of a wiki page.
*/
void wikiappend_page(void){
char *zTag;
int rid = 0;
const char *zPageName;
const char *zUser;
const char *zMimetype;
int goodCaptcha = 1;
const char *zFormat;
Manifest *pWiki = 0;
int isSandbox;
login_check_credentials();
if( !g.perm.ApndWiki ){
login_needed(g.anon.ApndWiki);
return;
}
zPageName = PD("name","");
zMimetype = wiki_filter_mimetypes(P("mimetype"));
if( check_name(zPageName) ) return;
isSandbox = is_sandbox(zPageName);
if(!isSandbox){
zTag = mprintf("wiki-%s", zPageName);
rid = db_int(0,
"SELECT rid FROM tagxref"
" WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
" ORDER BY mtime DESC", zTag
);
free(zTag);
pWiki = rid ? manifest_get(rid, CFTYPE_WIKI, 0) : 0;
if( !pWiki ){
fossil_redirect_home();
return;
}
zMimetype = wiki_filter_mimetypes(pWiki->zMimetype)
/* see https://fossil-scm.org/forum/forumpost/0acfdaac80 */;
}
if( !isSandbox && P("submit")!=0 && P("r")!=0 && P("u")!=0
&& (goodCaptcha = captcha_is_correct(0))
){
char *zDate;
Blob cksum;
Blob body;
Blob wiki;
blob_zero(&body);
login_verify_csrf_secret();
blob_append(&body, pWiki->zWiki, -1);
blob_zero(&wiki);
db_begin_transaction();
zDate = date_in_standard_format("now");
blob_appendf(&wiki, "D %s\n", zDate);
blob_appendf(&wiki, "L %F\n", zPageName);
if( fossil_strcmp(zMimetype, "text/x-fossil-wiki")!=0 ){
blob_appendf(&wiki, "N %s\n", zMimetype);
}
if( rid ){
char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
blob_appendf(&wiki, "P %s\n", zUuid);
free(zUuid);
}
if( !login_is_nobody() ){
blob_appendf(&wiki, "U %F\n", login_name());
}
appendRemark(&body, zMimetype);
blob_appendf(&wiki, "W %d\n%s\n", blob_size(&body), blob_str(&body));
md5sum_blob(&wiki, &cksum);
blob_appendf(&wiki, "Z %b\n", &cksum);
blob_reset(&cksum);
wiki_put(&wiki, rid, wiki_need_moderation(0));
db_end_transaction(0);
manifest_destroy(pWiki);
cgi_redirectf("wiki?name=%T", zPageName);
return;
}
if( !isSandbox && P("cancel")!=0 ){
manifest_destroy(pWiki);
cgi_redirectf("wiki?name=%T", zPageName);
return;
}
style_set_current_page("%T?name=%T", g.zPath, zPageName);
style_set_current_feature("wiki");
style_header("Append Comment To: %s", zPageName);
if( !goodCaptcha ){
@ <p class="generalError">Error: Incorrect security code.</p>
}
if( isSandbox ){
@ <p class="generalError">Error: the Sandbox page may not
@ be appended to.</p>
}
if( !isSandbox && P("preview")!=0 ){
Blob preview;
blob_zero(&preview);
appendRemark(&preview, zMimetype);
@ Preview:<hr />
safe_html_context(DOCSRC_WIKI);
wiki_render_by_mimetype(&preview, zMimetype);
@ <hr />
|
| ︙ | ︙ | |||
1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 |
@ rows="10" wrap="virtual">%h(PD("r",""))</textarea>
@ <br />
@ <input type="submit" name="preview" value="Preview Your Comment" />
@ <input type="submit" name="submit" value="Append Your Changes" />
@ <input type="submit" name="cancel" value="Cancel" />
captcha_generate(0);
@ </form>
style_finish_page();
}
/*
** WEBPAGE: whistory
** URL: /whistory?name=PAGENAME
**
| > | 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 |
@ rows="10" wrap="virtual">%h(PD("r",""))</textarea>
@ <br />
@ <input type="submit" name="preview" value="Preview Your Comment" />
@ <input type="submit" name="submit" value="Append Your Changes" />
@ <input type="submit" name="cancel" value="Cancel" />
captcha_generate(0);
@ </form>
manifest_destroy(pWiki);
style_finish_page();
}
/*
** WEBPAGE: whistory
** URL: /whistory?name=PAGENAME
**
|
| ︙ | ︙ |
Changes to src/winhttp.c.
| ︙ | ︙ | |||
338 339 340 341 342 343 344 345 346 347 348 |
static void win32_http_request(void *pAppData){
HttpRequest *p = (HttpRequest*)pAppData;
FILE *in = 0, *out = 0, *aux = 0;
int amt, got, i;
int wanted = 0;
char *z;
char *zIp;
char zCmdFName[MAX_PATH];
char zRequestFName[MAX_PATH];
char zReplyFName[MAX_PATH];
char zCmd[2000]; /* Command-line to process the request */
| > | > > > > > > | > > > > > | | > | | | > > > > > | | > | | > > > > > | | > | | | 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 |
static void win32_http_request(void *pAppData){
HttpRequest *p = (HttpRequest*)pAppData;
FILE *in = 0, *out = 0, *aux = 0;
int amt, got, i;
int wanted = 0;
char *z;
char *zIp;
void *sslConn = 0;
char zCmdFName[MAX_PATH];
char zRequestFName[MAX_PATH];
char zReplyFName[MAX_PATH];
char zCmd[2000]; /* Command-line to process the request */
char zBuf[65536]; /* The HTTP request header */
const int szHdr = 4000; /* Reduced header size */
sqlite3_snprintf(MAX_PATH, zCmdFName,
"%s_%06d_cmd.txt", zTempPrefix, p->id);
sqlite3_snprintf(MAX_PATH, zRequestFName,
"%s_%06d_in.txt", zTempPrefix, p->id);
sqlite3_snprintf(MAX_PATH, zReplyFName,
"%s_%06d_out.txt", zTempPrefix, p->id);
amt = 0;
if( g.httpUseSSL ){
#ifdef FOSSIL_ENABLE_SSL
sslConn = ssl_new_server(p->s);
#endif
}
while( amt<szHdr ){
if( sslConn ){
#ifdef FOSSIL_ENABLE_SSL
got = ssl_read_server(sslConn, &zBuf[amt], szHdr-amt);
#endif
}else{
got = recv(p->s, &zBuf[amt], szHdr-amt, 0);
if( got==SOCKET_ERROR ) goto end_request;
}
if( got==0 ){
wanted = 0;
break;
}
amt += got;
zBuf[amt] = 0;
z = strstr(zBuf, "\r\n\r\n");
if( z ){
wanted = find_content_length(zBuf) + (&z[4]-zBuf) - amt;
break;
}else{
z = strstr(zBuf, "\n\n");
if( z ){
wanted = find_content_length(zBuf) + (&z[2]-zBuf) - amt;
break;
}
}
}
if( amt>=szHdr ) goto end_request;
out = fossil_fopen(zRequestFName, "wb");
if( out==0 ) goto end_request;
fwrite(zBuf, 1, amt, out);
while( wanted>0 ){
if( sslConn ){
#ifdef FOSSIL_ENABLE_SSL
got = ssl_read_server(sslConn, zBuf, sizeof(zBuf));
#endif
}else{
got = recv(p->s, zBuf, sizeof(zBuf), 0);
if( got==SOCKET_ERROR ) goto end_request;
}
if( got>0 ){
fwrite(zBuf, 1, got, out);
}else{
break;
}
wanted -= got;
}
/*
|
| ︙ | ︙ | |||
403 404 405 406 407 408 409 | } fossil_free(zIp); aux = fossil_fopen(zCmdFName, "wb"); if( aux==0 ) goto end_request; fwrite(zCmd, 1, strlen(zCmd), aux); sqlite3_snprintf(sizeof(zCmd), zCmd, | | | > | > > > > > | > > > > > > | 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 |
}
fossil_free(zIp);
aux = fossil_fopen(zCmdFName, "wb");
if( aux==0 ) goto end_request;
fwrite(zCmd, 1, strlen(zCmd), aux);
sqlite3_snprintf(sizeof(zCmd), zCmd,
"\"%s\" http -args \"%s\"%s%s",
g.nameOfExe, zCmdFName,
g.httpUseSSL ? "" : " --nossl", p->zOptions
);
in = fossil_fopen(zReplyFName, "w+b");
fflush(out);
fflush(aux);
fossil_system(zCmd);
if( in ){
while( (got = fread(zBuf, 1, sizeof(zBuf), in))>0 ){
if( sslConn ){
#ifdef FOSSIL_ENABLE_SSL
ssl_write_server(sslConn, zBuf, got);
#endif
}else{
send(p->s, zBuf, got, 0);
}
}
}
end_request:
if( out ) fclose(out);
if( aux ) fclose(aux);
if( in ) fclose(in);
/* Initiate shutdown prior to closing the socket */
if( sslConn!=0 ){
#ifdef FOSSIL_ENABLE_SSL
ssl_close_server(sslConn);
#endif
}
if( shutdown(p->s,1)==0 ) shutdown(p->s,0);
closesocket(p->s);
/* Make multiple attempts to delete the temporary files. Sometimes AV
** software keeps the files open for a few seconds, preventing the file
** from being deleted on the first try. */
for(i=1; i<=10 && file_delete(zRequestFName); i++){ Sleep(1000*i); }
for(i=1; i<=10 && file_delete(zCmdFName); i++){ Sleep(1000*i); }
|
| ︙ | ︙ | |||
617 618 619 620 621 622 623 |
if( !GetTempPathW(MAX_PATH, zTmpPath) ){
fossil_panic("unable to get path to the temporary directory.");
}
zTempPrefix = mprintf("%sfossil_server_P%d",
fossil_unicode_to_utf8(zTmpPath), iPort);
fossil_print("Temporary files: %s*\n", zTempPrefix);
fossil_print("Listening for %s requests on TCP port %d\n",
| | > | 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 |
if( !GetTempPathW(MAX_PATH, zTmpPath) ){
fossil_panic("unable to get path to the temporary directory.");
}
zTempPrefix = mprintf("%sfossil_server_P%d",
fossil_unicode_to_utf8(zTmpPath), iPort);
fossil_print("Temporary files: %s*\n", zTempPrefix);
fossil_print("Listening for %s requests on TCP port %d\n",
(flags&HTTP_SERVER_SCGI)!=0 ? "SCGI" :
g.httpUseSSL ? "TLS-encrypted HTTPS" : "HTTP", iPort);
if( zBrowser ){
zBrowser = mprintf(zBrowser /*works-like:"%d"*/, iPort);
fossil_print("Launch webbrowser: %s\n", zBrowser);
fossil_system(zBrowser);
}
fossil_print("Type Ctrl-C to stop the HTTP server\n");
/* Create an event used to signal when this server is exiting. */
|
| ︙ | ︙ | |||
947 948 949 950 951 952 953 | ** ** Sets the start type of the service. TYPE can be "manual", ** which means you need to start the service yourself with the ** 'fossil winsrv start' command or with the "net start" command ** from the operating system. If TYPE is set to "auto", the service ** will be started automatically by the system during startup. ** | | | 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 | ** ** Sets the start type of the service. TYPE can be "manual", ** which means you need to start the service yourself with the ** 'fossil winsrv start' command or with the "net start" command ** from the operating system. If TYPE is set to "auto", the service ** will be started automatically by the system during startup. ** ** --username USERNAME ** ** Specifies the user account which will be used to run the ** service. The account needs the "Logon as a service" right ** enabled in its profile. Specify local accounts as follows: ** ".\\USERNAME". By default, the "LocalSystem" account will be ** used. ** |
| ︙ | ︙ | |||
1051 1052 1053 1054 1055 1056 1057 |
SC_HANDLE hSvc;
SERVICE_DESCRIPTIONW
svcDescr = {L"Fossil - Distributed Software Configuration Management"};
DWORD dwStartType = SERVICE_DEMAND_START;
const char *zAltBase = find_option("baseurl", 0, 1);
const char *zDisplay = find_option("display", "D", 1);
const char *zStart = find_option("start", "S", 1);
| | | 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 |
SC_HANDLE hSvc;
SERVICE_DESCRIPTIONW
svcDescr = {L"Fossil - Distributed Software Configuration Management"};
DWORD dwStartType = SERVICE_DEMAND_START;
const char *zAltBase = find_option("baseurl", 0, 1);
const char *zDisplay = find_option("display", "D", 1);
const char *zStart = find_option("start", "S", 1);
const char *zUsername = find_option("username", 0, 1);
const char *zPassword = find_option("password", "W", 1);
const char *zPort = find_option("port", "P", 1);
const char *zNotFound = find_option("notfound", 0, 1);
const char *zFileGlob = find_option("files", 0, 1);
const char *zLocalAuth = find_option("localauth", 0, 0);
const char *zRepository = find_repository_option();
int useSCGI = find_option("scgi", 0, 0)!=0;
|
| ︙ | ︙ |
Changes to src/xfer.c.
| ︙ | ︙ | |||
1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 |
** # ... code here
** set common_done 1
** }
*/
int xfer_run_common_script(void){
return xfer_run_script(xfer_common_code(), 0, 0);
}
/*
** If this variable is set, disable login checks. Used for debugging
** only.
*/
static int disableLogin = 0;
| > > > > > > > > > > > > > > > > > > > > > > | 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 |
** # ... code here
** set common_done 1
** }
*/
int xfer_run_common_script(void){
return xfer_run_script(xfer_common_code(), 0, 0);
}
/*
** This routine makes a "syncwith:URL" entry in the CONFIG table to
** indicate that a sync is occuring with zUrl.
**
** Add a "syncfrom:URL" entry instead of "syncwith:URL" if bSyncFrom is true.
*/
static void xfer_syncwith(const char *zUrl, int bSyncFrom){
UrlData x;
memset(&x, 0, sizeof(x));
url_parse_local(zUrl, URL_OMIT_USER, &x);
if( x.protocol && strncmp(x.protocol,"http",4)==0
&& x.name && sqlite3_strlike("%localhost%", x.name, 0)!=0
){
db_unprotect(PROTECT_CONFIG);
db_multi_exec("REPLACE INTO config(name,value,mtime)"
"VALUES('sync%q:%q','{}',now())",
bSyncFrom ? "from" : "with", x.canonical);
db_protect_pop();
}
url_unparse(&x);
}
/*
** If this variable is set, disable login checks. Used for debugging
** only.
*/
static int disableLogin = 0;
|
| ︙ | ︙ | |||
1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 |
int rc;
const char *zScript = 0;
char *zUuidList = 0;
int nUuidList = 0;
char **pzUuidList = 0;
int *pnUuidList = 0;
int uvCatalogSent = 0;
if( fossil_strcmp(PD("REQUEST_METHOD","POST"),"POST") ){
fossil_redirect_home();
}
g.zLogin = "anonymous";
login_set_anon_nobody_capabilities();
login_check_credentials();
| > | 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 |
int rc;
const char *zScript = 0;
char *zUuidList = 0;
int nUuidList = 0;
char **pzUuidList = 0;
int *pnUuidList = 0;
int uvCatalogSent = 0;
int bSendLinks = 0;
if( fossil_strcmp(PD("REQUEST_METHOD","POST"),"POST") ){
fossil_redirect_home();
}
g.zLogin = "anonymous";
login_set_anon_nobody_capabilities();
login_check_credentials();
|
| ︙ | ︙ | |||
1575 1576 1577 1578 1579 1580 1581 |
if( blob_eq(&xfer.aToken[1], "send-private") ){
login_check_credentials();
if( !g.perm.Private ){
server_private_xfer_not_authorized();
}else{
xfer.syncPrivate = 1;
}
| | | | | 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 |
if( blob_eq(&xfer.aToken[1], "send-private") ){
login_check_credentials();
if( !g.perm.Private ){
server_private_xfer_not_authorized();
}else{
xfer.syncPrivate = 1;
}
}else
/* pragma send-catalog
**
** The client wants to see igot cards for all known artifacts.
** This is used as part of "sync --verily" to help ensure that
** no artifacts have been missed on prior syncs.
*/
if( blob_eq(&xfer.aToken[1], "send-catalog") ){
xfer.resync = 0x7fffffff;
}else
/* pragma client-version VERSION ?DATE? ?TIME?
**
** The client announces to the server what version of Fossil it
** is running. The DATE and TIME are a pure numeric ISO8601 time
** for the specific check-in of the client.
*/
if( xfer.nToken>=3 && blob_eq(&xfer.aToken[1], "client-version") ){
xfer.remoteVersion = atoi(blob_str(&xfer.aToken[2]));
if( xfer.nToken>=5 ){
xfer.remoteDate = atoi(blob_str(&xfer.aToken[3]));
xfer.remoteTime = atoi(blob_str(&xfer.aToken[4]));
@ pragma server-version %d(RELEASE_VERSION_NUMBER) \
@ %d(MANIFEST_NUMERIC_DATE) %d(MANIFEST_NUMERIC_TIME)
}
}else
/* pragma uv-hash HASH
**
** The client wants to make sure that unversioned files are all synced.
** If the HASH does not match, send a complete catalog of
** "uvigot" cards.
*/
|
| ︙ | ︙ | |||
1624 1625 1626 1627 1628 1629 1630 |
@ pragma uv-push-ok
}else if( g.perm.Read ){
@ pragma uv-pull-only
}
send_unversioned_catalog(&xfer);
}
uvCatalogSent = 1;
| | | | > | > | 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 |
@ pragma uv-push-ok
}else if( g.perm.Read ){
@ pragma uv-pull-only
}
send_unversioned_catalog(&xfer);
}
uvCatalogSent = 1;
}else
/* pragma ci-lock CHECKIN-HASH CLIENT-ID
**
** The client wants to make non-branch commit against the check-in
** identified by CHECKIN-HASH. The server will remember this and
** subsequent ci-lock requests from different clients will generate
** a ci-lock-fail pragma in the reply.
*/
if( blob_eq(&xfer.aToken[1], "ci-lock")
&& xfer.nToken==4
&& blob_is_hname(&xfer.aToken[2])
){
Stmt q;
sqlite3_int64 iNow = time(0);
sqlite3_int64 maxAge = db_get_int("lock-timeout",60);
int seenFault = 0;
db_prepare(&q,
"SELECT value->>'login',"
" mtime,"
" value->>'clientid',"
" (SELECT rid FROM blob WHERE uuid=substr(name,9)),"
" name"
" FROM config"
" WHERE name GLOB 'ci-lock-*'"
" AND json_valid(value)"
);
while( db_step(&q)==SQLITE_ROW ){
int x = db_column_int(&q,3);
const char *zName = db_column_text(&q,4);
if( db_column_int64(&q,1)<=iNow-maxAge || !is_a_leaf(x) ){
/* check-in locks expire after maxAge seconds, or when the
** check-in is no longer a leaf */
|
| ︙ | ︙ | |||
1684 1685 1686 1687 1688 1689 1690 |
blob_str(&xfer.aToken[3])
);
db_protect_pop();
}
if( db_get_boolean("forbid-delta-manifests",0) ){
@ pragma avoid-delta-manifests
}
| | | > > > > > > > > > > > > > > > > > > > > > > | 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 |
blob_str(&xfer.aToken[3])
);
db_protect_pop();
}
if( db_get_boolean("forbid-delta-manifests",0) ){
@ pragma avoid-delta-manifests
}
}else
/* pragma ci-unlock CLIENT-ID
**
** Remove any locks previously held by CLIENT-ID. Clients send this
** pragma with their own ID whenever they know that they no longer
** have any commits pending.
*/
if( blob_eq(&xfer.aToken[1], "ci-unlock")
&& xfer.nToken==3
&& blob_is_hname(&xfer.aToken[2])
){
db_unprotect(PROTECT_CONFIG);
db_multi_exec(
"DELETE FROM config"
" WHERE name GLOB 'ci-lock-*'"
" AND (NOT json_valid(value) OR value->>'clientid'==%Q)",
blob_str(&xfer.aToken[2])
);
db_protect_pop();
}else
/* pragma client-url URL
**
** This pragma is an informational notification to the server that
** their relationship could, in theory, be inverted by having the
** server call the client at URL.
*/
if( blob_eq(&xfer.aToken[1], "client-url")
&& xfer.nToken==3
&& g.perm.Write
){
xfer_syncwith(blob_str(&xfer.aToken[2]), 1);
}else
/* pragma req-links
**
** The client sends this message to the server to ask the server
** to tell it about alternative repositories in the reply.
*/
if( blob_eq(&xfer.aToken[1], "req-links") ){
bSendLinks = 1;
}
}else
/* Unknown message
*/
{
|
| ︙ | ︙ | |||
1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 |
create_cluster();
send_unclustered(&xfer);
if( xfer.syncPrivate ) send_private(&xfer);
}
hook_expecting_more_artifacts(xfer.nGimmeSent?60:0);
db_multi_exec("DROP TABLE onremote; DROP TABLE unk;");
manifest_crosslink_end(MC_PERMIT_HOOKS);
/* Send the server timestamp last, in case prior processing happened
** to use up a significant fraction of our time window.
*/
zNow = db_text(0, "SELECT strftime('%%Y-%%m-%%dT%%H:%%M:%%S', 'now')");
@ # timestamp %s(zNow)
free(zNow);
db_commit_transaction();
configure_rebuild();
}
/*
** COMMAND: test-xfer
**
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | > > | > | | | < > | | > > | > | > > > > > > > | | | | | | | | | | | | | | | > > | 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 |
create_cluster();
send_unclustered(&xfer);
if( xfer.syncPrivate ) send_private(&xfer);
}
hook_expecting_more_artifacts(xfer.nGimmeSent?60:0);
db_multi_exec("DROP TABLE onremote; DROP TABLE unk;");
manifest_crosslink_end(MC_PERMIT_HOOKS);
/* Send URLs for alternative repositories for the same project,
** if requested by the client. */
if( bSendLinks && g.zBaseURL ){
Stmt q;
db_prepare(&q,
"WITH remote(mtime, url, arg) AS (\n"
" SELECT mtime, substr(name,10), '{}' FROM config\n"
" WHERE name GLOB 'syncwith:http*'\n"
" UNION ALL\n"
" SELECT mtime, substr(name,10), '{}' FROM config\n"
" WHERE name GLOB 'syncfrom:http*'\n"
" UNION ALL\n"
" SELECT mtime, substr(name,9), '{\"type\":\"git\"}' FROM config\n"
" WHERE name GLOB 'gitpush:*'\n"
")\n"
"SELECT url, json_insert(arg,'$.src',%Q), max(mtime)\n"
" FROM remote WHERE mtime>unixepoch('now','-1 month')\n"
" GROUP BY url;",
g.zBaseURL
);
while( db_step(&q)==SQLITE_ROW ){
UrlData x;
const char *zUrl = db_column_text(&q, 0);
const char *zArg = db_column_text(&q, 1);
i64 iMtime = db_column_int64(&q, 2);
memset(&x, 0, sizeof(x));
url_parse_local(zUrl, URL_OMIT_USER, &x);
if( x.name!=0 && sqlite3_strlike("%localhost%", x.name, 0)!=0 ){
@ pragma link %F(x.canonical) %F(zArg) %lld(iMtime)
}
url_unparse(&x);
}
db_finalize(&q);
}
/* Send the server timestamp last, in case prior processing happened
** to use up a significant fraction of our time window.
*/
zNow = db_text(0, "SELECT strftime('%%Y-%%m-%%dT%%H:%%M:%%S', 'now')");
@ # timestamp %s(zNow)
free(zNow);
db_commit_transaction();
configure_rebuild();
}
/*
** COMMAND: test-xfer
**
** Usage: %fossil test-xfer ?OPTIONS? XFERFILE
**
** Pass the sync-protocol input file XFERFILE into the server-side sync
** protocol handler. Generate a reply on standard output.
**
** This command was original created to help debug the server side of
** sync messages. The XFERFILE is the uncompressed content of an
** "xfer" HTTP request from client to server. This command interprets
** that message and generates the content of an HTTP reply (without any
** encoding and without the HTTP reply headers) and writes that reply
** on standard output.
**
** One possible usages scenario is to capture some XFERFILE examples
** using a command like:
**
** fossil push http://bogus/ --httptrace
**
** The complete HTTP requests are stored in files named "http-request-N.txt".
** Find one of those requests, remove the HTTP header, and make other edits
** as necessary to generate an appropriate XFERFILE test case. Then run:
**
** fossil test-xfer xferfile.txt
**
** Options:
**
** --host HOSTNAME Supply a server hostname used to populate
** g.zBaseURL and similar.
*/
void cmd_test_xfer(void){
const char *zHost;
db_find_and_open_repository(0,0);
zHost = find_option("host",0,1);
verify_all_options();
if( g.argc!=2 && g.argc!=3 ){
usage("?MESSAGEFILE?");
}
if( zHost==0 ) zHost = "localhost:8080";
g.zBaseURL = mprintf("http://%s", zHost);
g.zHttpsURL = mprintf("https://%s", zHost);
g.zTop = mprintf("");
blob_zero(&g.cgiIn);
blob_read_from_file(&g.cgiIn, g.argc==2 ? "-" : g.argv[2], ExtFILE);
disableLogin = 1;
page_xfer();
fossil_print("%s", cgi_extract_content());
}
/*
** Format strings for progress reporting.
*/
static const char zLabelFormat[] = "%-10s %10s %10s %10s %10s\n";
static const char zValueFormat[] = "\r%-10s %10d %10d %10d %10d\n";
static const char zBriefFormat[] =
"Round-trips: %d Artifacts sent: %d received: %d\r";
#if INTERFACE
/*
** Flag options for controlling client_sync()
*/
#define SYNC_PUSH 0x00001 /* push content client to server */
#define SYNC_PULL 0x00002 /* pull content server to client */
#define SYNC_CLONE 0x00004 /* clone the repository */
#define SYNC_PRIVATE 0x00008 /* Also transfer private content */
#define SYNC_VERBOSE 0x00010 /* Extra diagnostics */
#define SYNC_RESYNC 0x00020 /* --verily */
#define SYNC_FROMPARENT 0x00040 /* Pull from the parent project */
#define SYNC_UNVERSIONED 0x00100 /* Sync unversioned content */
#define SYNC_UV_REVERT 0x00200 /* Copy server unversioned to client */
#define SYNC_UV_TRACE 0x00400 /* Describe UV activities */
#define SYNC_UV_DRYRUN 0x00800 /* Do not actually exchange files */
#define SYNC_IFABLE 0x01000 /* Inability to sync is not fatal */
#define SYNC_CKIN_LOCK 0x02000 /* Lock the current check-in */
#define SYNC_NOHTTPCOMPRESS 0x04000 /* Do not compression HTTP messages */
#define SYNC_ALLURL 0x08000 /* The --all flag - sync to all URLs */
#define SYNC_SHARE_LINKS 0x10000 /* Request alternate repo links */
#endif
/*
** Floating-point absolute value
*/
static double fossil_fabs(double x){
return x>0.0 ? x : -x;
|
| ︙ | ︙ | |||
1882 1883 1884 1885 1886 1887 1888 |
int autopushFailed = 0; /* Autopush following commit failed if true */
const char *zCkinLock; /* Name of check-in to lock. NULL for none */
const char *zClientId; /* A unique identifier for this check-out */
unsigned int mHttpFlags;/* Flags for the http_exchange() subsystem */
if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE|SYNC_UNVERSIONED))==0
| | > > > > > > > > > > > > > | | > > > > > > | 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 |
int autopushFailed = 0; /* Autopush following commit failed if true */
const char *zCkinLock; /* Name of check-in to lock. NULL for none */
const char *zClientId; /* A unique identifier for this check-out */
unsigned int mHttpFlags;/* Flags for the http_exchange() subsystem */
if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE|SYNC_UNVERSIONED))==0
&& configRcvMask==0
&& configSendMask==0
){
return 0; /* Nothing to do */
}
/* Compute an appropriate project code. zPCode is the project code
** for the local repository. zAltPCode will usually be NULL, but might
** also be an alternative project code to expect on the server. When
** zAltPCode is not NULL, that means we are doing a cross-project import -
** in other words, reading content from one project into a different
** project.
*/
if( syncFlags & SYNC_FROMPARENT ){
const char *zPX;
configRcvMask = 0;
configSendMask = 0;
syncFlags &= ~(SYNC_PUSH);
zPX = db_get("parent-project-code", 0);
if( zPX==0 || db_get("parent-project-name",0)==0 ){
fossil_fatal("there is no parent project: set the 'parent-project-code'"
" and 'parent-project-name' config parameters in order"
" to pull from a parent project");
}
if( zPX ){
zAltPCode = zPX;
}
}
if( zAltPCode!=0 && zPCode!=0 && sqlite3_stricmp(zPCode, zAltPCode)==0 ){
zAltPCode = 0;
}
transport_stats(0, 0, 1);
socket_global_init();
memset(&xfer, 0, sizeof(xfer));
xfer.pIn = &recv;
xfer.pOut = &send;
|
| ︙ | ︙ | |||
1941 1942 1943 1944 1945 1946 1947 |
** to the other side. But "uvigot" cards received back from the remote
** side will normally cause many of these entries to be removed since they
** do not really need to be sent.
*/
if( (syncFlags & (SYNC_UNVERSIONED|SYNC_CLONE))!=0 ){
unversioned_schema();
db_multi_exec(
| | | | 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 |
** to the other side. But "uvigot" cards received back from the remote
** side will normally cause many of these entries to be removed since they
** do not really need to be sent.
*/
if( (syncFlags & (SYNC_UNVERSIONED|SYNC_CLONE))!=0 ){
unversioned_schema();
db_multi_exec(
"CREATE TEMP TABLE IF NOT EXISTS uv_tosend("
" name TEXT PRIMARY KEY," /* Name of file to send client->server */
" mtimeOnly BOOLEAN" /* True to only send mtime, not content */
") WITHOUT ROWID;"
"REPLACE INTO uv_toSend(name,mtimeOnly)"
" SELECT name, 0 FROM unversioned WHERE hash IS NOT NULL;"
);
}
/*
** The request from the client always begin with a clone, pull,
** or push message.
|
| ︙ | ︙ | |||
1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 |
if( (syncFlags & SYNC_PULL)==0 ) zOpType = "Push";
if( (syncFlags & SYNC_RESYNC)!=0 ) xfer.resync = 0x7fffffff;
}
if( syncFlags & SYNC_VERBOSE ){
fossil_print(zLabelFormat /*works-like:"%s%s%s%s%d"*/,
"", "Bytes", "Cards", "Artifacts", "Deltas");
}
while( go ){
int newPhantom = 0;
char *zRandomness;
db_begin_transaction();
db_record_repository_filename(0);
db_multi_exec(
| > > > > > > > > > > > > > > > > | 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 |
if( (syncFlags & SYNC_PULL)==0 ) zOpType = "Push";
if( (syncFlags & SYNC_RESYNC)!=0 ) xfer.resync = 0x7fffffff;
}
if( syncFlags & SYNC_VERBOSE ){
fossil_print(zLabelFormat /*works-like:"%s%s%s%s%d"*/,
"", "Bytes", "Cards", "Artifacts", "Deltas");
}
/* Send the client-url pragma on the first cycle if the client has
** a known public url.
*/
if( zAltPCode==0 ){
const char *zSelfUrl = public_url();
if( zSelfUrl ){
blob_appendf(&send, "pragma client-url %s\n", zSelfUrl);
}
}
/* Request URLs of alternative repositories
*/
if( zAltPCode==0 && (syncFlags & SYNC_SHARE_LINKS)!=0 ){
blob_appendf(&send, "pragma req-links\n");
}
while( go ){
int newPhantom = 0;
char *zRandomness;
db_begin_transaction();
db_record_repository_filename(0);
db_multi_exec(
|
| ︙ | ︙ | |||
2142 2143 2144 2145 2146 2147 2148 |
go = 2;
break;
}
/* Remember the URL of the sync target in the config file on the
** first successful round-trip */
if( nCycle==0 && db_is_writeable("repository") ){
| < < | < | 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 |
go = 2;
break;
}
/* Remember the URL of the sync target in the config file on the
** first successful round-trip */
if( nCycle==0 && db_is_writeable("repository") ){
xfer_syncwith(g.url.canonical, 0);
}
/* Output current stats */
if( syncFlags & SYNC_VERBOSE ){
fossil_print(zValueFormat /*works-like:"%s%d%d%d%d"*/, "Sent:",
blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent,
xfer.nFileSent, xfer.nDeltaSent);
|
| ︙ | ︙ | |||
2520 2521 2522 2523 2524 2525 2526 |
**
** If the server is unwill to accept new unversioned content (because
** this client lacks the necessary permissions) then it sends a
** "uv-pull-only" pragma so that the client will know not to waste
** bandwidth trying to upload unversioned content. If the server
** does accept new unversioned content, it sends "uv-push-ok".
*/
| | | 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 |
**
** If the server is unwill to accept new unversioned content (because
** this client lacks the necessary permissions) then it sends a
** "uv-pull-only" pragma so that the client will know not to waste
** bandwidth trying to upload unversioned content. If the server
** does accept new unversioned content, it sends "uv-push-ok".
*/
else if( syncFlags & SYNC_UNVERSIONED ){
if( blob_eq(&xfer.aToken[1], "uv-pull-only") ){
uvPullOnly = 1;
if( syncFlags & SYNC_UV_REVERT ) uvDoPush = 1;
}else if( blob_eq(&xfer.aToken[1], "uv-push-ok") ){
uvDoPush = 1;
}
}
|
| ︙ | ︙ | |||
2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 |
**
** Discourage the use of delta manifests. The remote side sends
** this pragma when its forbid-delta-manifests setting is true.
*/
else if( blob_eq(&xfer.aToken[1], "avoid-delta-manifests") ){
g.bAvoidDeltaManifests = 1;
}
}else
/* error MESSAGE
**
** The server is reporting an error. The client will abandon
** the sync session.
**
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 |
**
** Discourage the use of delta manifests. The remote side sends
** this pragma when its forbid-delta-manifests setting is true.
*/
else if( blob_eq(&xfer.aToken[1], "avoid-delta-manifests") ){
g.bAvoidDeltaManifests = 1;
}
/* pragma link URL ARG MTIME
**
** The server has sent the URL for a link to another repository.
** Record this as a link:URL entry in the config table.
*/
else if( blob_eq(&xfer.aToken[1], "link")
&& xfer.nToken==5
&& (syncFlags & SYNC_SHARE_LINKS)!=0
){
UrlData x;
char *zUrl = blob_str(&xfer.aToken[2]);
char *zArg = blob_str(&xfer.aToken[3]);
i64 iTime = strtoll(blob_str(&xfer.aToken[4]),0,0);
memset(&x, 0, sizeof(x));
defossilize(zUrl);
defossilize(zArg);
url_parse_local(zUrl, URL_OMIT_USER, &x);
if( x.protocol
&& strncmp(x.protocol,"http",4)==0
&& iTime>0
){
db_unprotect(PROTECT_CONFIG);
db_multi_exec(
"INSERT INTO config(name,value,mtime)\n"
" VALUES('link:%q',%Q,%lld)\n"
" ON CONFLICT DO UPDATE\n"
" SET value=excluded.value, mtime=excluded.mtime\n"
" WHERE mtime<excluded.mtime;",
zUrl, zArg, iTime
);
db_protect_pop();
}
url_unparse(&x);
}
}else
/* error MESSAGE
**
** The server is reporting an error. The client will abandon
** the sync session.
**
|
| ︙ | ︙ | |||
2681 2682 2683 2684 2685 2686 2687 |
}else if( rSkew*24.0*3600.0 < -10.0 ){
fossil_warning("*** time skew *** server is slow by %s",
db_timespan_name(-rSkew));
g.clockSkewSeen = 1;
}
fossil_force_newline();
| > | | | > | 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 |
}else if( rSkew*24.0*3600.0 < -10.0 ){
fossil_warning("*** time skew *** server is slow by %s",
db_timespan_name(-rSkew));
g.clockSkewSeen = 1;
}
fossil_force_newline();
if( g.zHttpCmd==0 ){
fossil_print(
"%s done, wire bytes sent: %lld received: %lld ip: %s\n",
zOpType, nSent, nRcvd, g.zIpAddr);
}
if( syncFlags & SYNC_VERBOSE ){
fossil_print(
"Uncompressed payload sent: %lld received: %lld\n", nUncSent, nUncRcvd);
}
transport_close(&g.url);
transport_global_shutdown(&g.url);
if( nErr && go==2 ){
|
| ︙ | ︙ |
Changes to src/xfersetup.c.
| ︙ | ︙ | |||
42 43 44 45 46 47 48 |
"Specific TH1 code to run after \"push\" transfer requests.");
setup_menu_entry("Commit", "xfersetup_commit",
"Specific TH1 code to run after processing a commit.");
setup_menu_entry("Ticket", "xfersetup_ticket",
"Specific TH1 code to run after processing a ticket change.");
@ </table>
| | | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
"Specific TH1 code to run after \"push\" transfer requests.");
setup_menu_entry("Commit", "xfersetup_commit",
"Specific TH1 code to run after processing a commit.");
setup_menu_entry("Ticket", "xfersetup_ticket",
"Specific TH1 code to run after processing a ticket change.");
@ </table>
url_parse(0, URL_USE_CONFIG);
if( g.url.protocol ){
unsigned syncFlags;
const char *zButton;
char *zWarning;
if( db_get_boolean("dont-push", 0) ){
syncFlags = SYNC_PULL;
|
| ︙ | ︙ |
Changes to src/zip.c.
| ︙ | ︙ | |||
15 16 17 18 19 20 21 | ** ******************************************************************************* ** ** This file contains code used to generate ZIP and SQLAR archives. */ #include "config.h" #include <assert.h> | < < < < | < | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | ** ******************************************************************************* ** ** This file contains code used to generate ZIP and SQLAR archives. */ #include "config.h" #include <assert.h> #include <zlib.h> #include "zip.h" /* ** Type of archive to build. */ #define ARCHIVE_ZIP 0 #define ARCHIVE_SQLAR 1 |
| ︙ | ︙ | |||
680 681 682 683 684 685 686 |
if( eflg & MFESTFLG_RAW ){
blob_append(&filename, "manifest", -1);
zName = blob_str(&filename);
if( listFlag ) fossil_print("%s\n", zName);
if( pZip ){
zip_add_folders(&sArchive, zName);
| < | 675 676 677 678 679 680 681 682 683 684 685 686 687 688 |
if( eflg & MFESTFLG_RAW ){
blob_append(&filename, "manifest", -1);
zName = blob_str(&filename);
if( listFlag ) fossil_print("%s\n", zName);
if( pZip ){
zip_add_folders(&sArchive, zName);
zip_add_file(&sArchive, zName, &mfile, 0);
}
}
if( eflg & MFESTFLG_UUID ){
blob_append(&hash, "\n", 1);
blob_resize(&filename, nPrefix);
blob_append(&filename, "manifest.uuid", -1);
|
| ︙ | ︙ |
Name change from src/codecheck1.c to tools/codecheck1.c.
| ︙ | ︙ |
Name change from src/makeheaders.c to tools/makeheaders.c.
| ︙ | ︙ |
Name change from src/makeheaders.html to tools/makeheaders.html.
| ︙ | ︙ |
Name change from src/makemake.tcl to tools/makemake.tcl.
1 2 3 4 5 6 7 8 9 | #!/usr/bin/tclsh # # ### Run this Tcl script EVERY time you modify it in any way! ### # # This Tcl script generates make files for various platforms. The makefiles # then need to be committed. # # If you modify this file then: # | > > | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #!/usr/bin/tclsh # # ### Run this Tcl script EVERY time you modify it in any way! ### # ### It must be run from the directory it lives in so that ### # ### directories resolve properly! ### # # This Tcl script generates make files for various platforms. The makefiles # then need to be committed. # # If you modify this file then: # # 1. cd tools; tclsh makemake.tcl # # 2. if errors are reported, fix them and go to step 1 # # 3. if "fossil diff" reports changes in any of the generated # files, commit the changed files to the repo # # Files generated include: |
| ︙ | ︙ | |||
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# variable. There are other variables that you can alter, down to
# the "STOP HERE" comment. The stuff below "STOP HERE" should rarely need
# to change. After modification, go to step 1 above.
#
# Delete unused source files in the "src" variable, then go to step 1 above.
#
#############################################################################
# Basenames of all source files that get preprocessed using
# "translate" and "makeheaders". To add new C-language source files to the
# project, simply add the basename to this list and rerun this script.
#
# Set the separate extra_files variable further down for how to add non-C
# files, such as string and BLOB resources.
#
set src {
add
ajax
alerts
allrepo
attach
backlink
| > > > > > > > > > > | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# variable. There are other variables that you can alter, down to
# the "STOP HERE" comment. The stuff below "STOP HERE" should rarely need
# to change. After modification, go to step 1 above.
#
# Delete unused source files in the "src" variable, then go to step 1 above.
#
#############################################################################
# $srcDir is used to set the target source dir in several places. Not
# all code-generation bits use $srcDir and instead hard-code, so
# replacing it only here (should it ever changes) is not sufficient.
#
set srcDir ../src
# Directory $srcDirExt houses single-file source code solutions which
# are imported directly into the fossil source tree.
set srcDirExt ../extsrc
# Basenames of all source files that get preprocessed using
# "translate" and "makeheaders". To add new C-language source files to the
# project, simply add the basename to this list and rerun this script.
#
# Set the separate extra_files variable further down for how to add non-C
# files, such as string and BLOB resources.
#
set src {
add
ajax
alerts
allrepo
attach
backlink
|
| ︙ | ︙ | |||
126 127 128 129 130 131 132 | merge merge3 moderate name patch path piechart | < | 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | merge merge3 moderate name patch path piechart pikchrshow pivot popen pqueue printf publish purge |
| ︙ | ︙ | |||
183 184 185 186 187 188 189 190 | winfile winhttp xfer xfersetup zip http_ssl } | | > > > > > | > > > | 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
winfile
winhttp
xfer
xfersetup
zip
http_ssl
}
# Source files which live under $srcDirExt, but only those for which
# we need to run makeheaders. External sources which have their own
# header files must not be in this list.
set src_ext {
pikchr
}
# Additional resource files that get built into the executable.
# These paths are all resolved from the src/ directory, so must
# be relative to that.
set extra_files {
diff.tcl
markdown.md
wiki.wiki
*.js
default.css
style.*.css
|
| ︙ | ︙ | |||
213 214 215 216 217 218 219 | -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 | < < < < < < < < < < < | 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
-DSQLITE_LIKE_DOESNT_MATCH_BLOBS
-DSQLITE_OMIT_DECLTYPE
-DSQLITE_OMIT_DEPRECATED
-DSQLITE_OMIT_PROGRESS_CALLBACK
-DSQLITE_OMIT_SHARED_CACHE
-DSQLITE_OMIT_LOAD_EXTENSION
-DSQLITE_MAX_EXPR_DEPTH=0
-DSQLITE_ENABLE_LOCKING_STYLE=0
-DSQLITE_DEFAULT_FILE_FORMAT=4
-DSQLITE_ENABLE_EXPLAIN_COMMENTS
-DSQLITE_ENABLE_FTS4
-DSQLITE_ENABLE_DBSTAT_VTAB
-DSQLITE_ENABLE_FTS5
-DSQLITE_ENABLE_STMTVTAB
-DSQLITE_HAVE_ZLIB
-DSQLITE_ENABLE_DBPAGE_VTAB
-DSQLITE_TRUSTED_SCHEMA=0
}
#lappend SQLITE_OPTIONS -DSQLITE_ENABLE_FTS3=1
#lappend SQLITE_OPTIONS -DSQLITE_ENABLE_STAT4
#lappend SQLITE_OPTIONS -DSQLITE_WIN32_NO_ANSI
#lappend SQLITE_OPTIONS -DSQLITE_WINNT_MAX_PATH_CHARS=4096
# Options used to compile the included SQLite shell.
#
set SHELL_OPTIONS [concat $SQLITE_OPTIONS {
-Dmain=sqlite3_shell
-DSQLITE_SHELL_IS_UTF8=1
-DSQLITE_OMIT_LOAD_EXTENSION=1
-DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE)
-DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname
-DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc
}]
# Options used to compile the included SQLite shell on Windows.
#
set SHELL_WIN32_OPTIONS $SHELL_OPTIONS
lappend SHELL_WIN32_OPTIONS -Daccess=file_access
lappend SHELL_WIN32_OPTIONS -Dsystem=fossil_system
lappend SHELL_WIN32_OPTIONS -Dgetenv=fossil_getenv
lappend SHELL_WIN32_OPTIONS -Dfopen=fossil_fopen
|
| ︙ | ︙ | |||
282 283 284 285 286 287 288 |
puts $output_file [lindex $args 0]
}
}
# Expand any wildcards in "extra_files"
set new_extra_files {}
foreach file $extra_files {
| > > > > > | > > | | | | | 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 |
puts $output_file [lindex $args 0]
}
}
# Expand any wildcards in "extra_files"
set new_extra_files {}
foreach file $extra_files {
# we need $file to resolve from $srcDir, but simply prepending
# $srcDir to each name breaks how the names are stringified and
# looked up from C.
set cwd [pwd]
cd $srcDir
foreach x [glob $file] { # -nocomplain flag?
lappend new_extra_files $x
}
cd $cwd
}
set extra_files $new_extra_files
##############################################################################
##############################################################################
##############################################################################
# Start by generating the "main.mk" makefile used for all unix systems.
#
set mainMk $srcDir/main.mk
puts "building $mainMk"
set output_file [open $mainMk w]
fconfigure $output_file -translation binary
writeln {#
##############################################################################
# WARNING: DO NOT EDIT, AUTOMATICALLY GENERATED FILE (SEE "tools/makemake.tcl")
##############################################################################
#
# This file is automatically generated. Instead of editing this
# file, edit "makemake.tcl" then run "tclsh makemake.tcl"
# to regenerate this file.
#
# This file is included by primary Makefile.
#
XBCC = $(BCC) $(BCCFLAGS)
XTCC = $(TCC) $(CFLAGS_INCLUDE) -I$(OBJDIR) $(TCCFLAGS)
TESTFLAGS := -quiet
}
writeln -nonewline "SRC ="
foreach s [lsort $src] {
writeln -nonewline " \\\n \$(SRCDIR)/$s.c"
}
|
| ︙ | ︙ | |||
337 338 339 340 341 342 343 |
foreach s [lsort $src] {
writeln -nonewline " \\\n \$(OBJDIR)/$s.o"
}
writeln [string map [list \
<<<SQLITE_OPTIONS>>> [join $SQLITE_OPTIONS " \\\n "] \
<<<SHELL_OPTIONS>>> [join $SHELL_OPTIONS " \\\n "] \
| | | | | | | | | | | | | | | | < < < | | > > > > < < < < < < < | | | | | | > | | | | > | | | < > | 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 |
foreach s [lsort $src] {
writeln -nonewline " \\\n \$(OBJDIR)/$s.o"
}
writeln [string map [list \
<<<SQLITE_OPTIONS>>> [join $SQLITE_OPTIONS " \\\n "] \
<<<SHELL_OPTIONS>>> [join $SHELL_OPTIONS " \\\n "] \
<<<NEXT_LINE>>> \\] {
all: $(OBJDIR) $(APPNAME)
install: all
mkdir -p $(INSTALLDIR)
cp $(APPNAME) $(INSTALLDIR)
codecheck: $(TRANS_SRC) $(OBJDIR)/codecheck1
$(OBJDIR)/codecheck1 $(TRANS_SRC)
$(OBJDIR):
-mkdir $(OBJDIR)
$(OBJDIR)/translate: $(SRCDIR_tools)/translate.c
$(XBCC) -o $(OBJDIR)/translate $(SRCDIR_tools)/translate.c
$(OBJDIR)/makeheaders: $(SRCDIR_tools)/makeheaders.c
$(XBCC) -o $(OBJDIR)/makeheaders $(SRCDIR_tools)/makeheaders.c
$(OBJDIR)/mkindex: $(SRCDIR_tools)/mkindex.c
$(XBCC) -o $(OBJDIR)/mkindex $(SRCDIR_tools)/mkindex.c
$(OBJDIR)/mkbuiltin: $(SRCDIR_tools)/mkbuiltin.c
$(XBCC) -o $(OBJDIR)/mkbuiltin $(SRCDIR_tools)/mkbuiltin.c
$(OBJDIR)/mkversion: $(SRCDIR_tools)/mkversion.c
$(XBCC) -o $(OBJDIR)/mkversion $(SRCDIR_tools)/mkversion.c
$(OBJDIR)/codecheck1: $(SRCDIR_tools)/codecheck1.c
$(XBCC) -o $(OBJDIR)/codecheck1 $(SRCDIR_tools)/codecheck1.c
# Run the test suite.
# Other flags that can be included in TESTFLAGS are:
#
# -halt Stop testing after the first failed test
# -keep Keep the temporary workspace for debugging
# -prot Write a detailed log of the tests to the file ./prot
# -verbose Include even more details in the output
# -quiet Hide most output from the terminal
# -strict Treat known bugs as failures
#
# TESTFLAGS can also include names of specific test files to limit
# the run to just those test cases.
#
test: $(OBJDIR) $(APPNAME)
$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS)
$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion $(OBJDIR)/phony.h
$(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid <<<NEXT_LINE>>>
$(SRCDIR)/../manifest <<<NEXT_LINE>>>
$(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
$(OBJDIR)/phony.h:
# Force rebuild of VERSION.h every time we run "make"
# Setup the options used to compile the included SQLite library.
SQLITE_OPTIONS = <<<SQLITE_OPTIONS>>>
# Setup the options used to compile the included SQLite shell.
SHELL_OPTIONS = <<<SHELL_OPTIONS>>>
# The USE_SYSTEM_SQLITE variable may be undefined, set to 0 or 1.
# If it is set to 1, then there is no need to build or link
# the sqlite3.o object. Instead, the system SQLite will be linked
# using -lsqlite3.
#
# Closely related is SQLITE3_ORIGIN, with the same numeric mapping plus
# a value of 2 means that we are building a client-provided sqlite3.c.
SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
SQLITE3_OBJ.1 =
# SQLITE3_OBJ.2 is set by the configure process
SQLITE3_OBJ. = $(SQLITE3_OBJ.0)
# The USE_LINENOISE variable may be undefined, set to 0, or set
# to 1. If it is set to 0, then there is no need to build or link
# the linenoise.o object.
LINENOISE_DEF.0 =
LINENOISE_DEF.1 = -DHAVE_LINENOISE
LINENOISE_DEF. = $(LINENOISE_DEF.0)
LINENOISE_OBJ.0 =
LINENOISE_OBJ.1 = $(OBJDIR)/linenoise.o
LINENOISE_OBJ. = $(LINENOISE_OBJ.0)
# The USE_SEE variable may be undefined, 0 or 1. If undefined or 0,
# in-tree SQLite is used. If 1, then sqlite3-see.c (not part of the
# source tree) is used and extra flags are provided to enable the
# SQLite Encryption Extension.
SQLITE3_SRC.0 = $(SRCDIR_extsrc)/sqlite3.c
SQLITE3_SRC.1 = $(SRCDIR_extsrc)/sqlite3-see.c
# SQLITE3_SRC.2 is set by top-level configure/makefile process.
SQLITE3_SRC. = $(SRCDIR_extsrc)/sqlite3.c
SQLITE3_SRC = $(SQLITE3_SRC.$(SQLITE3_ORIGIN))
SQLITE3_SHELL_SRC.0 = $(SRCDIR_extsrc)/shell.c
SQLITE3_SHELL_SRC.1 = $(SRCDIR_extsrc)/shell-see.c
# SQLITE3_SHELL_SRC.2 comes from the configure process
SQLITE3_SHELL_SRC. = $(SRCDIR_extsrc)/shell.c
SQLITE3_SHELL_SRC = $(SQLITE3_SHELL_SRC.$(SQLITE3_ORIGIN))
SEE_FLAGS.0 =
SEE_FLAGS.1 = -DSQLITE_HAS_CODEC -DSQLITE_SHELL_DBKEY_PROC=fossil_key
SEE_FLAGS. =
SEE_FLAGS = $(SEE_FLAGS.$(USE_SEE))
}]
writeln [string map [list <<<NEXT_LINE>>> \\] {
EXTRAOBJ = <<<NEXT_LINE>>>
$(SQLITE3_OBJ.$(SQLITE3_ORIGIN)) <<<NEXT_LINE>>>
$(LINENOISE_OBJ.$(USE_LINENOISE)) <<<NEXT_LINE>>>
$(OBJDIR)/pikchr.o <<<NEXT_LINE>>>
$(OBJDIR)/shell.o <<<NEXT_LINE>>>
$(OBJDIR)/th.o <<<NEXT_LINE>>>
$(OBJDIR)/th_lang.o <<<NEXT_LINE>>>
$(OBJDIR)/th_tcl.o <<<NEXT_LINE>>>
$(OBJDIR)/cson_amalgamation.o
}]
|
| ︙ | ︙ | |||
477 478 479 480 481 482 483 |
}
set mhargs {}
foreach s [lsort $src] {
append mhargs "\$(OBJDIR)/${s}_.c:\$(OBJDIR)/$s.h <<<NEXT_LINE>>>"
set extra_h($s) { }
}
| > > > > | | | 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 |
}
set mhargs {}
foreach s [lsort $src] {
append mhargs "\$(OBJDIR)/${s}_.c:\$(OBJDIR)/$s.h <<<NEXT_LINE>>>"
set extra_h($s) { }
}
foreach s [lsort $src_ext] {
append mhargs "\$(SRCDIR_extsrc)/${s}.c:\$(OBJDIR)/$s.h <<<NEXT_LINE>>>"
set extra_h($s) { }
}
append mhargs "\$(SRCDIR_extsrc)/sqlite3.h <<<NEXT_LINE>>>"
append mhargs "\$(SRCDIR)/th.h <<<NEXT_LINE>>>"
#append mhargs "\$(SRCDIR_extsrc)/cson_amalgamation.h <<<NEXT_LINE>>>"
append mhargs "\$(OBJDIR)/VERSION.h "
set mhargs [string map [list <<<NEXT_LINE>>> \\\n\t] $mhargs]
writeln "\$(OBJDIR)/page_index.h: \$(TRANS_SRC) \$(OBJDIR)/mkindex"
writeln "\t\$(OBJDIR)/mkindex \$(TRANS_SRC) >\$@\n"
writeln "\$(OBJDIR)/builtin_data.h: \$(OBJDIR)/mkbuiltin \$(EXTRA_FILES)"
writeln "\t\$(OBJDIR)/mkbuiltin --prefix \$(SRCDIR)/ \$(EXTRA_FILES) >\$@\n"
|
| ︙ | ︙ | |||
510 511 512 513 514 515 516 | writeln "\$(OBJDIR)/$s.h:\t\$(OBJDIR)/headers\n" } writeln "\$(OBJDIR)/sqlite3.o:\t\$(SQLITE3_SRC)" writeln "\t\$(XTCC) \$(SQLITE_OPTIONS) \$(SQLITE_CFLAGS) \$(SEE_FLAGS) \\" writeln "\t\t-c \$(SQLITE3_SRC) -o \$@" | | | | | | | | | 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 |
writeln "\$(OBJDIR)/$s.h:\t\$(OBJDIR)/headers\n"
}
writeln "\$(OBJDIR)/sqlite3.o:\t\$(SQLITE3_SRC)"
writeln "\t\$(XTCC) \$(SQLITE_OPTIONS) \$(SQLITE_CFLAGS) \$(SEE_FLAGS) \\"
writeln "\t\t-c \$(SQLITE3_SRC) -o \$@"
writeln "\$(OBJDIR)/shell.o:\t\$(SQLITE3_SHELL_SRC) \$(SRCDIR_extsrc)/sqlite3.h"
writeln "\t\$(XTCC) \$(SHELL_OPTIONS) \$(SHELL_CFLAGS) \$(SEE_FLAGS) \$(LINENOISE_DEF.\$(USE_LINENOISE)) -c \$(SQLITE3_SHELL_SRC) -o \$@\n"
writeln "\$(OBJDIR)/linenoise.o:\t\$(SRCDIR_extsrc)/linenoise.c \$(SRCDIR_extsrc)/linenoise.h"
writeln "\t\$(XTCC) -c \$(SRCDIR_extsrc)/linenoise.c -o \$@\n"
writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th.c -o \$@\n"
writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_lang.c -o \$@\n"
writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$@\n"
writeln {
$(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c
$(XTCC) -c $(SRCDIR_extsrc)/pikchr.c -o $@
$(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c
$(XTCC) -c $(SRCDIR_extsrc)/cson_amalgamation.c -o $@
#
# The list of all the targets that do not correspond to real files. This stops
# 'make' from getting confused when someone makes an error in a rule.
#
.PHONY: all install test clean
|
| ︙ | ︙ | |||
555 556 557 558 559 560 561 |
puts "building ../win/Makefile.mingw"
set output_file [open ../win/Makefile.mingw w]
fconfigure $output_file -translation binary
writeln {#!/usr/bin/make
#
##############################################################################
| | | 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 |
puts "building ../win/Makefile.mingw"
set output_file [open ../win/Makefile.mingw w]
fconfigure $output_file -translation binary
writeln {#!/usr/bin/make
#
##############################################################################
# WARNING: DO NOT EDIT, AUTOMATICALLY GENERATED FILE (SEE "tools/makemake.tcl")
##############################################################################
#
# This file is automatically generated. Instead of editing this
# file, edit "makemake.tcl" then run "tclsh makemake.tcl"
# to regenerate this file.
#
# This is a makefile for use on Cygwin/Darwin/FreeBSD/Linux/Windows using
|
| ︙ | ︙ | |||
584 585 586 587 588 589 590 591 592 593 594 595 596 597 | # PREFIX = x86_64-w64-mingw32- #### The toplevel directory of the source tree. Fossil can be built # in a directory that is separate from the source tree. Just change # the following to point from the build directory to the src/ folder. # SRCDIR = src #### The directory into which object code files should be written. # OBJDIR = wbld #### C compiler for use in building executables that will run on # the platform that is doing the build. This is used to compile | > > | 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 | # PREFIX = x86_64-w64-mingw32- #### The toplevel directory of the source tree. Fossil can be built # in a directory that is separate from the source tree. Just change # the following to point from the build directory to the src/ folder. # SRCDIR = src SRCDIR_extsrc = extsrc SRCDIR_tools = tools #### The directory into which object code files should be written. # OBJDIR = wbld #### C compiler for use in building executables that will run on # the platform that is doing the build. This is used to compile |
| ︙ | ︙ | |||
657 658 659 660 661 662 663 | # # USE_MMAN_H = 1 #### Use the SQLite Encryption Extension # # USE_SEE = 1 | < < < < | 674 675 676 677 678 679 680 681 682 683 684 685 686 687 | # # USE_MMAN_H = 1 #### Use the SQLite Encryption Extension # # USE_SEE = 1 #### Use the Tcl source directory instead of the install directory? # This is useful when Tcl has been compiled statically with MinGW. # FOSSIL_TCL_SOURCE = 1 #### Check if the workaround for the MinGW command line handling needs to # be enabled by default. This check may be somewhat fragile due to the |
| ︙ | ︙ | |||
696 697 698 699 700 701 702 | #### Determine if the optimized assembly routines provided with zlib should be # used, taking into account whether zlib is actually enabled and the target # processor architecture. # ifndef X64 SSLCONFIG = mingw | < < < < < < < | 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 | #### Determine if the optimized assembly routines provided with zlib should be # used, taking into account whether zlib is actually enabled and the target # processor architecture. # ifndef X64 SSLCONFIG = mingw ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" ZLIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o else SSLCONFIG = mingw64 ZLIBCONFIG = ZLIBTARGETS = endif #### Disable creation of the OpenSSL shared libraries. Also, disable support # for SSLv3 (i.e. thereby forcing the use of TLS). # SSLCONFIG += no-ssl3 no-weak-ssl-ciphers no-shared #### When using zlib, make sure that OpenSSL is configured to use the zlib # that Fossil knows about (i.e. the one within the source tree). # SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib #### The directories where the OpenSSL include and library files are located. # OPENSSLDIR = $(SRCDIR)/../compat/openssl OPENSSLINCDIR = $(OPENSSLDIR)/include OPENSSLLIBDIR = $(OPENSSLDIR) |
| ︙ | ︙ | |||
779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 | #### C compiler and options for use in building executables that will # run on the target platform. This is usually the almost the same # as BCC, unless you are cross-compiling. This C compiler builds # the finished binary for fossil. The BCC compiler above is used # for building intermediate code-generator tools. # TCC = $(PREFIX)$(TCCEXE) -Wall -Wdeclaration-after-statement #### Add the necessary command line options to build with debugging # symbols, if enabled. # ifdef FOSSIL_ENABLE_SYMBOLS TCC += -g else TCC += -Os endif | > < < < < | < < | < < < < < < < | 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 | #### C compiler and options for use in building executables that will # run on the target platform. This is usually the almost the same # as BCC, unless you are cross-compiling. This C compiler builds # the finished binary for fossil. The BCC compiler above is used # for building intermediate code-generator tools. # TCC = $(PREFIX)$(TCCEXE) -Wall -Wdeclaration-after-statement TCC += -I$(SRCDIR_extsrc) #### Add the necessary command line options to build with debugging # symbols, if enabled. # ifdef FOSSIL_ENABLE_SYMBOLS TCC += -g else TCC += -Os endif TCC += -L$(ZLIBDIR) -I$(ZINCDIR) #### Compile resources for use in building executables that will run # on the target platform. # RCC = $(PREFIX)windres -I$(SRCDIR) -I$(ZINCDIR) RCC += -I$(SRCDIR_extsrc) # With HTTPS support ifdef FOSSIL_ENABLE_SSL TCC += -L$(OPENSSLLIBDIR) -I$(OPENSSLINCDIR) RCC += -I$(OPENSSLINCDIR) endif # With Tcl support ifdef FOSSIL_ENABLE_TCL ifdef FOSSIL_TCL_SOURCE TCC += -L$(TCLSRCDIR)/win -I$(TCLSRCDIR)/generic -I$(TCLSRCDIR)/win RCC += -I$(TCLSRCDIR)/generic -I$(TCLSRCDIR)/win else TCC += -L$(TCLLIBDIR) -I$(TCLINCDIR) RCC += -I$(TCLINCDIR) endif endif # With MinGW command line handling workaround ifdef MINGW_IS_32BIT_ONLY TCC += -DBROKEN_MINGW_CMDLINE=1 RCC += -DBROKEN_MINGW_CMDLINE=1 endif # With HTTPS support |
| ︙ | ︙ | |||
932 933 934 935 936 937 938 | #### Extra arguments for linking the finished binary. Fossil needs # to link against the Z-Lib compression library. There are no # other mandatory dependencies. # LIB += -lmingwex | | < < | 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 | #### Extra arguments for linking the finished binary. Fossil needs # to link against the Z-Lib compression library. There are no # other mandatory dependencies. # LIB += -lmingwex #### zlib is required. # LIB += -lz #### These libraries MUST appear in the same order as they do for Tcl # or linking with it will not work (exact reason unknown). # ifdef FOSSIL_ENABLE_TCL ifdef FOSSIL_ENABLE_TCL_STUBS LIB += -lkernel32 -lws2_32 |
| ︙ | ︙ | |||
1043 1044 1045 1046 1047 1048 1049 |
endif}
writeln {
all: $(OBJDIR) $(APPNAME)
$(OBJDIR)/fossil.o: $(SRCDIR)/../win/fossil.rc $(OBJDIR)/VERSION.h
ifdef USE_WINDOWS
| < < | 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 |
endif}
writeln {
all: $(OBJDIR) $(APPNAME)
$(OBJDIR)/fossil.o: $(SRCDIR)/../win/fossil.rc $(OBJDIR)/VERSION.h
ifdef USE_WINDOWS
$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.rc) $(subst /,\,$(OBJDIR))
$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.ico) $(subst /,\,$(OBJDIR))
$(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.exe.manifest) $(subst /,\,$(OBJDIR))
else
$(CP) $(SRCDIR)/../win/fossil.rc $(OBJDIR)
$(CP) $(SRCDIR)/../win/fossil.ico $(OBJDIR)
$(CP) $(SRCDIR)/../win/fossil.exe.manifest $(OBJDIR)
endif
$(RCC) $(OBJDIR)/fossil.rc -o $(OBJDIR)/fossil.o
install: $(OBJDIR) $(APPNAME)
|
| ︙ | ︙ | |||
1071 1072 1073 1074 1075 1076 1077 | $(OBJDIR): ifdef USE_WINDOWS $(MKDIR) $(subst /,\,$(OBJDIR)) else $(MKDIR) $(OBJDIR) endif | | | | | | | | | | | | | | | > > > > > < < < < < < < | | | | | | > | | | | > | | | | < < < < | 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 |
$(OBJDIR):
ifdef USE_WINDOWS
$(MKDIR) $(subst /,\,$(OBJDIR))
else
$(MKDIR) $(OBJDIR)
endif
$(TRANSLATE): $(SRCDIR_tools)/translate.c
$(XBCC) -o $@ $(SRCDIR_tools)/translate.c
$(MAKEHEADERS): $(SRCDIR_tools)/makeheaders.c
$(XBCC) -o $@ $(SRCDIR_tools)/makeheaders.c
$(MKINDEX): $(SRCDIR_tools)/mkindex.c
$(XBCC) -o $@ $(SRCDIR_tools)/mkindex.c
$(MKBUILTIN): $(SRCDIR_tools)/mkbuiltin.c
$(XBCC) -o $@ $(SRCDIR_tools)/mkbuiltin.c
$(MKVERSION): $(SRCDIR_tools)/mkversion.c
$(XBCC) -o $@ $(SRCDIR_tools)/mkversion.c
$(CODECHECK1): $(SRCDIR_tools)/codecheck1.c
$(XBCC) -o $@ $(SRCDIR_tools)/codecheck1.c
# WARNING. DANGER. Running the test suite modifies the repository the
# build is done from, i.e. the checkout belongs to. Do not sync/push
# the repository after running the tests.
test: $(OBJDIR) $(APPNAME)
$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME)
$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) $(OBJDIR)/phony.h
$(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@
$(OBJDIR)/phony.h:
# Force rebuild of VERSION.h every time "make" is run
# The USE_SYSTEM_SQLITE variable may be undefined, set to 0 or 1.
# If it is set to 1, then there is no need to build or link
# the sqlite3.o object. Instead, the system SQLite will be linked
# using -lsqlite3.
#
# Closely related is SQLITE3_ORIGIN, with the same 0/1 mapping,
# plus a value of 2 means that we are building a client-provided
# sqlite3.c.
SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
SQLITE3_OBJ.1 =
# SQLITE3_OBJ.2 is set by the configure process
SQLITE3_OBJ. = $(SQLITE3_OBJ.0)
# The USE_SEE variable may be undefined, 0 or 1. If undefined or 0,
# in-tree SQLite is used. If 1, then sqlite3-see.c (not part of the
# source tree) is used and extra flags are provided to enable the
# SQLite Encryption Extension.
SQLITE3_SRC.0 = $(SRCDIR_extsrc)/sqlite3.c
SQLITE3_SRC.1 = $(SRCDIR_extsrc)/sqlite3-see.c
# SQLITE3_SRC.2 is set by top-level configure/makefile process.
SQLITE3_SRC. = $(SRCDIR_extsrc)/sqlite3.c
SQLITE3_SRC = $(SQLITE3_SRC.$(SQLITE3_ORIGIN))
SQLITE3_SHELL_SRC.0 = $(SRCDIR_extsrc)/shell.c
SQLITE3_SHELL_SRC.1 = $(SRCDIR_extsrc)/shell-see.c
# SQLITE3_SHELL_SRC.2 comes from the configure process
SQLITE3_SHELL_SRC. = $(SRCDIR_extsrc)/shell.c
SQLITE3_SHELL_SRC = $(SQLITE3_SHELL_SRC.$(SQLITE3_ORIGIN))
SEE_FLAGS.0 =
SEE_FLAGS.1 = -DSQLITE_HAS_CODEC -DSQLITE_SHELL_DBKEY_PROC=fossil_key
SEE_FLAGS. =
SEE_FLAGS = $(SEE_FLAGS.$(USE_SEE))
}
writeln [string map [list <<<NEXT_LINE>>> \\] {
EXTRAOBJ = <<<NEXT_LINE>>>
$(SQLITE3_OBJ.$(SQLITE3_ORIGIN)) <<<NEXT_LINE>>>
$(OBJDIR)/pikchr.o <<<NEXT_LINE>>>
$(OBJDIR)/shell.o <<<NEXT_LINE>>>
$(OBJDIR)/th.o <<<NEXT_LINE>>>
$(OBJDIR)/th_lang.o <<<NEXT_LINE>>>
$(OBJDIR)/th_tcl.o <<<NEXT_LINE>>>
$(OBJDIR)/cson_amalgamation.o
}]
writeln {
$(ZLIBDIR)/inffas86.o:
$(TCC) -c -o $@ -DASMINF -I$(ZLIBDIR) -O3 $(ZLIBDIR)/contrib/inflate86/inffas86.c
$(ZLIBDIR)/match.o:
$(TCC) -c -o $@ -DASMV $(ZLIBDIR)/contrib/asm686/match.S
zlib: $(ZLIBTARGETS)
$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) CC=$(PREFIX)$(TCCEXE) $(ZLIBCONFIG) -f win32/Makefile.gcc libz.a
clean-zlib:
$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) CC=$(PREFIX)$(TCCEXE) -f win32/Makefile.gcc clean
BLDTARGETS = zlib
openssl: $(BLDTARGETS)
cd $(OPENSSLLIBDIR);./Configure --cross-compile-prefix=$(PREFIX) $(SSLCONFIG)
sed -i -e 's/^PERL=C:\\.*$$/PERL=perl.exe/i' $(OPENSSLLIBDIR)/Makefile
$(MAKE) -C $(OPENSSLLIBDIR) PREFIX=$(PREFIX) CC=$(PREFIX)$(TCCEXE) build_libs
clean-openssl:
|
| ︙ | ︙ | |||
1213 1214 1215 1216 1217 1218 1219 |
innosetup: $(OBJDIR) $(APPNAME)
$(INNOSETUP) ./setup/fossil.iss -DAppVersion=$(shell $(CAT) ./VERSION)
}
set mhargs {}
foreach s [lsort $src] {
| | > > > > > | | | > | 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 |
innosetup: $(OBJDIR) $(APPNAME)
$(INNOSETUP) ./setup/fossil.iss -DAppVersion=$(shell $(CAT) ./VERSION)
}
set mhargs {}
foreach s [lsort $src] {
if {[string length $mhargs] > 0} {append mhargs " <<<NEXT_LINE>>>"}
append mhargs "\$(OBJDIR)/${s}_.c:\$(OBJDIR)/$s.h"
set extra_h($s) { }
}
foreach s [lsort $src_ext] {
if {[string length $mhargs] > 0} {append mhargs " <<<NEXT_LINE>>>"}
append mhargs "\$(SRCDIR_extsrc)/${s}.c:\$(OBJDIR)/$s.h"
set extra_h($s) { }
}
append mhargs " <<<NEXT_LINE>>>\$(SRCDIR_extsrc)/sqlite3.h"
append mhargs " <<<NEXT_LINE>>>\$(SRCDIR)/th.h"
append mhargs " <<<NEXT_LINE>>>\$(OBJDIR)/VERSION.h"
set mhargs [string map [list <<<NEXT_LINE>>> \\\n\t] $mhargs]
writeln "\$(OBJDIR)/page_index.h: \$(TRANS_SRC) \$(MKINDEX)"
writeln "\t\$(MKINDEX) \$(TRANS_SRC) >\$@\n"
writeln "\$(OBJDIR)/builtin_data.h:\t\$(MKBUILTIN) \$(EXTRA_FILES)"
writeln "\t\$(MKBUILTIN) --prefix \$(SRCDIR)/ \$(EXTRA_FILES) >\$@\n"
writeln "\$(OBJDIR)/headers:\t\$(OBJDIR)/page_index.h \$(OBJDIR)/builtin_data.h \$(MAKEHEADERS) \$(OBJDIR)/VERSION.h"
|
| ︙ | ︙ | |||
1253 1254 1255 1256 1257 1258 1259 |
lappend SQLITE_WIN32_OPTIONS -DSQLITE_WIN32_NO_ANSI
set MINGW_SQLITE_OPTIONS $SQLITE_WIN32_OPTIONS
lappend MINGW_SQLITE_OPTIONS {$(MINGW_OPTIONS)}
lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MALLOC_H
lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MSIZE
| < < < < | | | | | | > > | | 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 |
lappend SQLITE_WIN32_OPTIONS -DSQLITE_WIN32_NO_ANSI
set MINGW_SQLITE_OPTIONS $SQLITE_WIN32_OPTIONS
lappend MINGW_SQLITE_OPTIONS {$(MINGW_OPTIONS)}
lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MALLOC_H
lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MSIZE
set j " \\\n "
writeln "SQLITE_OPTIONS = [join $MINGW_SQLITE_OPTIONS $j]\n"
set j " \\\n "
writeln "SHELL_OPTIONS = [join $SHELL_WIN32_OPTIONS $j]\n"
writeln "\$(OBJDIR)/sqlite3.o:\t\$(SQLITE3_SRC) \$(SRCDIR)/../win/Makefile.mingw"
writeln "\t\$(XTCC) \$(SQLITE_OPTIONS) \$(SQLITE_CFLAGS) \$(SEE_FLAGS) \\"
writeln "\t\t-c \$(SQLITE3_SRC) -o \$@\n"
writeln "\$(OBJDIR)/cson_amalgamation.o:\t\$(SRCDIR_extsrc)/cson_amalgamation.c"
writeln "\t\$(XTCC) -c \$(SRCDIR_extsrc)/cson_amalgamation.c -o \$@\n"
writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_dir.o \$(OBJDIR)/jsos_finfo.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_status.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h\n"
writeln "\$(OBJDIR)/shell.o:\t\$(SQLITE3_SHELL_SRC) \$(SRCDIR_extsrc)/sqlite3.h \$(SRCDIR)/../win/Makefile.mingw"
writeln "\t\$(XTCC) \$(SHELL_OPTIONS) \$(SHELL_CFLAGS) \$(SEE_FLAGS) -c \$(SQLITE3_SHELL_SRC) -o \$@\n"
writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th.c -o \$@\n"
writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_lang.c -o \$@\n"
writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$@\n"
writeln "\$(OBJDIR)/pikchr.o:\t\$(SRCDIR_extsrc)/pikchr.c"
writeln "\t\$(XTCC) -c \$(SRCDIR_extsrc)/pikchr.c -o \$@\n"
close $output_file
#
# End of the win/Makefile.mingw output
##############################################################################
##############################################################################
##############################################################################
# Begin win/Makefile.dmc output
#
puts "building ../win/Makefile.dmc"
set output_file [open ../win/Makefile.dmc w]
fconfigure $output_file -translation binary
writeln {#
##############################################################################
# WARNING: DO NOT EDIT, AUTOMATICALLY GENERATED FILE (SEE "tools/makemake.tcl")
##############################################################################
#
# This file is automatically generated. Instead of editing this
# file, edit "makemake.tcl" then run "tclsh makemake.tcl"
# to regenerate this file.
#
B = ..
SRCDIR = $B\src
SRCDIR_extsrc = $B\extsrc
SRCDIR_tools = $B\tools
OBJDIR = .
O = .obj
E = .exe
# Maybe DMDIR, SSL or INCL needs adjustment
DMDIR = c:\DM
INCL = -I. -I$(SRCDIR) -I$(SRCDIR_extsrc) -I$B\win\include -I$(DMDIR)\extra\include
#SSL = -DFOSSIL_ENABLE_SSL=1
SSL =
CFLAGS = -o
BCC = $(DMDIR)\bin\dmc $(CFLAGS)
TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
|
| ︙ | ︙ | |||
1367 1368 1369 1370 1371 1372 1373 |
writeln "\t+echo fossil >> \$@"
writeln "\t+echo fossil >> \$@"
writeln "\t+echo \$(LIBS) >> \$@"
writeln "\t+echo. >> \$@"
writeln "\t+echo fossil >> \$@"
writeln {
| | | | | | | | | | | 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 |
writeln "\t+echo fossil >> \$@"
writeln "\t+echo fossil >> \$@"
writeln "\t+echo \$(LIBS) >> \$@"
writeln "\t+echo. >> \$@"
writeln "\t+echo fossil >> \$@"
writeln {
translate$E: $(SRCDIR_tools)\translate.c
$(BCC) -o$@ $**
makeheaders$E: $(SRCDIR_tools)\makeheaders.c
$(BCC) -o$@ $**
mkindex$E: $(SRCDIR_tools)\mkindex.c
$(BCC) -o$@ $**
mkbuiltin$E: $(SRCDIR_tools)\mkbuiltin.c
$(BCC) -o$@ $**
mkversion$E: $(SRCDIR_tools)\mkversion.c
$(BCC) -o$@ $**
codecheck1$E: $(SRCDIR_tools)\codecheck1.c
$(BCC) -o$@ $**
$(OBJDIR)\shell$O : $(SRCDIR_extsrc)\shell.c
$(TCC) -o$@ -c $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) $**
$(OBJDIR)\sqlite3$O : $(SRCDIR_extsrc)\sqlite3.c
$(TCC) -o$@ -c $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $**
$(OBJDIR)\th$O : $(SRCDIR)\th.c
$(TCC) -o$@ -c $**
$(OBJDIR)\th_lang$O : $(SRCDIR)\th_lang.c
$(TCC) -o$@ -c $**
$(OBJDIR)\cson_amalgamation.h : $(SRCDIR_extsrc)\cson_amalgamation.h
cp $@ $@
VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
+$** > $@
page_index.h: mkindex$E $(SRC)
+$** > $@
|
| ︙ | ︙ | |||
1444 1445 1446 1447 1448 1449 1450 |
writeln "\t+translate\$E \$** > \$@\n"
}
writeln -nonewline "headers: makeheaders\$E page_index.h builtin_data.h VERSION.h\n\t +makeheaders\$E "
foreach s [lsort $src] {
writeln -nonewline "${s}_.c:$s.h "
}
| | | > > | 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 |
writeln "\t+translate\$E \$** > \$@\n"
}
writeln -nonewline "headers: makeheaders\$E page_index.h builtin_data.h VERSION.h\n\t +makeheaders\$E "
foreach s [lsort $src] {
writeln -nonewline "${s}_.c:$s.h "
}
writeln "\$(SRCDIR_extsrc)\\sqlite3.h \$(SRCDIR)\\th.h VERSION.h \$(SRCDIR_extsrc)\\cson_amalgamation.h"
writeln "\t@copy /Y nul: headers"
close $output_file
#
# End of the win/Makefile.dmc output
##############################################################################
##############################################################################
##############################################################################
# Begin win/Makefile.msc output
#
puts "building ../win/Makefile.msc"
set output_file [open ../win/Makefile.msc w]
fconfigure $output_file -translation binary
writeln {#
##############################################################################
# WARNING: DO NOT EDIT, AUTOMATICALLY GENERATED FILE (SEE "tools/makemake.tcl")
##############################################################################
#
#
# This file is automatically generated. Instead of editing this
# file, edit "makemake.tcl" then run "tclsh makemake.tcl"
# to regenerate this file.
#
B = ..
SRCDIR = $(B)\src
SRCDIR_extsrc = $(B)\extsrc
SRCDIR_tools = $(B)\tools
T = .
OBJDIR = $(T)
OX = $(OBJDIR)
O = .obj
E = .exe
P = .pdb
DBGOPTS = /Od
|
| ︙ | ︙ | |||
1539 1540 1541 1542 1543 1544 1545 | !endif # Enable the JSON API? !ifndef FOSSIL_ENABLE_JSON FOSSIL_ENABLE_JSON = 0 !endif | < < < < < | 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 | !endif # Enable the JSON API? !ifndef FOSSIL_ENABLE_JSON FOSSIL_ENABLE_JSON = 0 !endif # Enable OpenSSL support? !ifndef FOSSIL_ENABLE_SSL FOSSIL_ENABLE_SSL = 0 !endif # Enable the Tcl integration subsystem? !ifndef FOSSIL_ENABLE_TCL |
| ︙ | ︙ | |||
1627 1628 1629 1630 1631 1632 1633 | !if $(FOSSIL_DYNAMIC_BUILD)!=0 ZLIB = zdll.lib !else ZLIB = zlib.lib !endif | | < < | 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 | !if $(FOSSIL_DYNAMIC_BUILD)!=0 ZLIB = zdll.lib !else ZLIB = zlib.lib !endif INCL = /I. /I"$(OX)" /I"$(SRCDIR)" /I"$(SRCDIR_extsrc)" /I"$(B)\win\include" INCL = $(INCL) /I"$(ZINCDIR)" !if $(FOSSIL_ENABLE_SSL)!=0 INCL = $(INCL) /I"$(SSLINCDIR)" !endif !if $(FOSSIL_ENABLE_TCL)!=0 INCL = $(INCL) /I"$(TCLINCDIR)" |
| ︙ | ︙ | |||
1709 1710 1711 1712 1713 1714 1715 | LIBDIR = !if $(FOSSIL_DYNAMIC_BUILD)!=0 TCC = $(TCC) /DFOSSIL_DYNAMIC_BUILD=1 RCC = $(RCC) /DFOSSIL_DYNAMIC_BUILD=1 !endif | < < < < < < < | 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 | LIBDIR = !if $(FOSSIL_DYNAMIC_BUILD)!=0 TCC = $(TCC) /DFOSSIL_DYNAMIC_BUILD=1 RCC = $(RCC) /DFOSSIL_DYNAMIC_BUILD=1 !endif LIBS = $(LIBS) $(ZLIB) LIBDIR = $(LIBDIR) /LIBPATH:"$(ZLIBDIR)" !if $(FOSSIL_ENABLE_JSON)!=0 TCC = $(TCC) /DFOSSIL_ENABLE_JSON=1 RCC = $(RCC) /DFOSSIL_ENABLE_JSON=1 !endif !if $(FOSSIL_ENABLE_SSL)!=0 |
| ︙ | ︙ | |||
1770 1771 1772 1773 1774 1775 1776 |
set j " \\\n "
writeln "SQLITE_OPTIONS = [join $MSC_SQLITE_OPTIONS $j]\n"
regsub -all {[-]D} [join $SHELL_WIN32_OPTIONS { }] {/D} MSC_SHELL_OPTIONS
set j " \\\n "
writeln "SHELL_OPTIONS = [join $MSC_SHELL_OPTIONS $j]\n"
| < < < < | 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 |
set j " \\\n "
writeln "SQLITE_OPTIONS = [join $MSC_SQLITE_OPTIONS $j]\n"
regsub -all {[-]D} [join $SHELL_WIN32_OPTIONS { }] {/D} MSC_SHELL_OPTIONS
set j " \\\n "
writeln "SHELL_OPTIONS = [join $MSC_SHELL_OPTIONS $j]\n"
writeln -nonewline "SRC = "
set i 0
foreach s [lsort $src] {
if {$i > 0} {
writeln " \\"
writeln -nonewline " "
}
|
| ︙ | ︙ | |||
1795 1796 1797 1798 1799 1800 1801 |
writeln " \\"
writeln -nonewline " "
}
set s [regsub -all / $s \\]
writeln -nonewline "\"\$(SRCDIR)\\${s}\""; incr i
}
writeln "\n"
| | < < < < | 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 |
writeln " \\"
writeln -nonewline " "
}
set s [regsub -all / $s \\]
writeln -nonewline "\"\$(SRCDIR)\\${s}\""; incr i
}
writeln "\n"
set AdditionalObj [list shell sqlite3 th th_lang th_tcl cson_amalgamation pikchr]
writeln -nonewline "OBJ = "
set i 0
foreach s [lsort [concat $src $AdditionalObj]] {
if {$i > 0} {
writeln " \\"
writeln -nonewline " "
}
writeln -nonewline "\"\$(OX)\\$s\$O\""; incr i
}
if {$i > 0} {
writeln " \\"
}
writeln -nonewline " \"\$(OX)\\fossil.res\"\n\n"
writeln [string map [list <<<NEXT_LINE>>> \\] {
!ifndef BASEAPPNAME
BASEAPPNAME = fossil
!endif
APPNAME = $(OX)\$(BASEAPPNAME)$(E)
|
| ︙ | ︙ | |||
1866 1867 1868 1869 1870 1871 1872 | @pushd "$(SSLDIR)" && $(MAKE) && popd !endif clean-openssl: @pushd "$(SSLDIR)" && $(MAKE) clean && popd !endif | < < | 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 | @pushd "$(SSLDIR)" && $(MAKE) && popd !endif clean-openssl: @pushd "$(SSLDIR)" && $(MAKE) clean && popd !endif !if $(FOSSIL_BUILD_ZLIB)!=0 APPTARGETS = $(APPTARGETS) zlib !endif !if $(FOSSIL_ENABLE_SSL)!=0 !if $(FOSSIL_BUILD_SSL)!=0 APPTARGETS = $(APPTARGETS) openssl !endif !endif |
| ︙ | ︙ | |||
1891 1892 1893 1894 1895 1896 1897 |
"$(OX)\linkopts": "$(B)\win\Makefile.msc"}]
set redir {>}
foreach s [lsort [concat $src $AdditionalObj]] {
writeln "\techo \"\$(OX)\\$s.obj\" $redir \$@"
set redir {>>}
}
set redir {>>}
| < < < | | | | | | | | | | | | | 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 |
"$(OX)\linkopts": "$(B)\win\Makefile.msc"}]
set redir {>}
foreach s [lsort [concat $src $AdditionalObj]] {
writeln "\techo \"\$(OX)\\$s.obj\" $redir \$@"
set redir {>>}
}
set redir {>>}
writeln "\techo \$(LIBS) $redir \$@"
writeln {
"$(OBJDIR)\translate$E": "$(SRCDIR_tools)\translate.c"
$(BCC) /Fe$@ /Fo$(@D)\ /Fd$(@D)\ $**
"$(OBJDIR)\makeheaders$E": "$(SRCDIR_tools)\makeheaders.c"
$(BCC) /Fe$@ /Fo$(@D)\ /Fd$(@D)\ $**
"$(OBJDIR)\mkindex$E": "$(SRCDIR_tools)\mkindex.c"
$(BCC) /Fe$@ /Fo$(@D)\ /Fd$(@D)\ $**
"$(OBJDIR)\mkbuiltin$E": "$(SRCDIR_tools)\mkbuiltin.c"
$(BCC) /Fe$@ /Fo$(@D)\ /Fd$(@D)\ $**
"$(OBJDIR)\mkversion$E": "$(SRCDIR_tools)\mkversion.c"
$(BCC) /Fe$@ /Fo$(@D)\ /Fd$(@D)\ $**
"$(OBJDIR)\codecheck1$E": "$(SRCDIR_tools)\codecheck1.c"
$(BCC) /Fe$@ /Fo$(@D)\ /Fd$(@D)\ $**
!if $(USE_SEE)!=0
SEE_FLAGS = /DSQLITE_HAS_CODEC=1 /DSQLITE_SHELL_DBKEY_PROC=fossil_key
SQLITE3_SHELL_SRC = $(SRCDIR)\shell-see.c
SQLITE3_SRC = $(SRCDIR_extsrc)\sqlite3-see.c
!else
SEE_FLAGS =
SQLITE3_SHELL_SRC = $(SRCDIR_extsrc)\shell.c
SQLITE3_SRC = $(SRCDIR_extsrc)\sqlite3.c
!endif
"$(OX)\shell$O" : "$(SQLITE3_SHELL_SRC)" "$(B)\win\Makefile.msc"
$(TCC) /Fo$@ /Fd$(@D)\ $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) $(SEE_FLAGS) -c "$(SQLITE3_SHELL_SRC)"
"$(OX)\sqlite3$O" : "$(SQLITE3_SRC)" "$(B)\win\Makefile.msc"
$(TCC) /Fo$@ /Fd$(@D)\ -c $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $(SEE_FLAGS) "$(SQLITE3_SRC)"
"$(OX)\th$O" : "$(SRCDIR)\th.c"
$(TCC) /Fo$@ /Fd$(@D)\ -c $**
"$(OX)\th_lang$O" : "$(SRCDIR)\th_lang.c"
$(TCC) /Fo$@ /Fd$(@D)\ -c $**
"$(OX)\th_tcl$O" : "$(SRCDIR)\th_tcl.c"
$(TCC) /Fo$@ /Fd$(@D)\ -c $**
"$(OX)\pikchr$O" : "$(SRCDIR_extsrc)\pikchr.c"
$(TCC) /Fo$@ /Fd$(@D)\ -c $**
"$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" "$(B)\phony.h"
"$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" > $@
"$(B)\phony.h" :
rem Force rebuild of VERSION.h whenever nmake is run
"$(OX)\cson_amalgamation$O" : "$(SRCDIR_extsrc)\cson_amalgamation.c"
$(TCC) /Fo$@ /Fd$(@D)\ -c $**
"$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC)
$** > $@
"$(OX)\builtin_data.h": "$(OBJDIR)\mkbuiltin$E" "$(OX)\builtin_data.reslist"
"$(OBJDIR)\mkbuiltin$E" --prefix "$(SRCDIR)/" --reslist "$(OX)\builtin_data.reslist" > $@
|
| ︙ | ︙ | |||
2035 2036 2037 2038 2039 2040 2041 |
foreach s [lsort $src] {
if {$i > 0} {
writeln " \\"
writeln -nonewline "\t\t\t"
}
writeln -nonewline "\"\$(OX)\\${s}_.c\":\"\$(OX)\\$s.h\""; incr i
}
| | | | | 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 |
foreach s [lsort $src] {
if {$i > 0} {
writeln " \\"
writeln -nonewline "\t\t\t"
}
writeln -nonewline "\"\$(OX)\\${s}_.c\":\"\$(OX)\\$s.h\""; incr i
}
writeln " \\\n\t\t\t\"\$(SRCDIR_extsrc)\\sqlite3.h\" \\"
writeln "\t\t\t\"\$(SRCDIR)\\th.h\" \\"
writeln "\t\t\t\"\$(OX)\\VERSION.h\" \\"
writeln "\t\t\t\"\$(SRCDIR_extsrc)\\cson_amalgamation.h\""
writeln "\t@copy /Y nul: $@"
close $output_file
#
# End of the win/Makefile.msc output
##############################################################################
##############################################################################
##############################################################################
# Begin win/Makefile.PellesCGMake output
#
puts "building ../win/Makefile.PellesCGMake"
set output_file [open ../win/Makefile.PellesCGMake w]
fconfigure $output_file -translation binary
writeln [string map [list \
<<<SQLITE_OPTIONS>>> [join $SQLITE_WIN32_OPTIONS { }] \
<<<SHELL_OPTIONS>>> [join $SHELL_WIN32_OPTIONS { }]] {#
##############################################################################
# WARNING: DO NOT EDIT, AUTOMATICALLY GENERATED FILE (SEE "tools/makemake.tcl")
##############################################################################
#
# This file is automatically generated. Instead of editing this
# file, edit "makemake.tcl" then run "tclsh makemake.tcl"
# to regenerate this file.
#
# HowTo
|
| ︙ | ︙ | |||
2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 | TARGETMACHINE_LN=ix86 TARGETEXTEND= endif # define the project directories B=.. SRCDIR=$(B)/src/ WINDIR=$(B)/win/ ZLIBSRCDIR=../../zlib/ # define linker command and options LINK=$(PellesCDir)/bin/polink.exe LINKFLAGS=-subsystem:console -machine:$(TARGETMACHINE_LN) /LIBPATH:$(PellesCDir)\lib\win$(TARGETEXTEND) /LIBPATH:$(PellesCDir)\lib kernel32.lib advapi32.lib delayimp$(TARGETEXTEND).lib Wsock32.lib dnsapi.lib Crtmt$(TARGETEXTEND).lib # define standard C-compiler and flags, used to compile # the fossil binary. Some special definitions follow for # special files follow CC=$(PellesCDir)\bin\pocc.exe DEFINES=-D_pgmptr=g.argv[0] CCFLAGS=-T$(TARGETMACHINE_CC)-coff -Ot -W2 -Gd -Go -Ze -MT $(DEFINES) | > > | | | | | 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 | TARGETMACHINE_LN=ix86 TARGETEXTEND= endif # define the project directories B=.. SRCDIR=$(B)/src/ SRCDIR_extsrc=$(B)/extsrc/ SRCDIR_tools=$(B)/tools/ WINDIR=$(B)/win/ ZLIBSRCDIR=../../zlib/ # define linker command and options LINK=$(PellesCDir)/bin/polink.exe LINKFLAGS=-subsystem:console -machine:$(TARGETMACHINE_LN) /LIBPATH:$(PellesCDir)\lib\win$(TARGETEXTEND) /LIBPATH:$(PellesCDir)\lib kernel32.lib advapi32.lib delayimp$(TARGETEXTEND).lib Wsock32.lib dnsapi.lib Crtmt$(TARGETEXTEND).lib # define standard C-compiler and flags, used to compile # the fossil binary. Some special definitions follow for # special files follow CC=$(PellesCDir)\bin\pocc.exe DEFINES=-D_pgmptr=g.argv[0] CCFLAGS=-T$(TARGETMACHINE_CC)-coff -Ot -W2 -Gd -Go -Ze -MT $(DEFINES) INCLUDE=/I $(PellesCDir)\Include\Win /I $(PellesCDir)\Include /I $(ZLIBSRCDIR) /I $(SRCDIR) /I $(SRCDIR_extsrc) # define commands for building the windows resource files RESOURCE=fossil.res RC=$(PellesCDir)\bin\porc.exe RCFLAGS=$(INCLUDE) -D__POCC__=1 -D_M_X$(TARGETVERSION) # define the special utilities files, needed to generate # the automatically generated source files UTILS=translate.exe mkindex.exe makeheaders.exe mkbuiltin.exe UTILS_OBJ=$(UTILS:.exe=.obj) UTILS_SRC=$(foreach uf,$(UTILS),$(SRCDIR_tools)$(uf:.exe=.c)) # define the SQLite files, which need special flags on compile SQLITESRC=sqlite3.c ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR_extsrc)$(sf)) SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj)) SQLITEDEFINES=<<<SQLITE_OPTIONS>>> # define the SQLite shell files, which need special flags on compile SQLITESHELLSRC=shell.c ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR_extsrc)$(sf)) SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj)) SQLITESHELLDEFINES=<<<SHELL_OPTIONS>>> # define the th scripting files, which need special flags on compile THSRC=th.c th_lang.c ORIGTHSRC=$(foreach sf,$(THSRC),$(SRCDIR)$(sf)) THOBJ=$(foreach sf,$(THSRC),$(sf:.c=.obj)) |
| ︙ | ︙ | |||
2189 2190 2191 2192 2193 2194 2195 | $(LINK) $(LINKFLAGS) -out:"$@" $< # compiling standard fossil utils $(UTILS_OBJ): %.obj: $(SRCDIR)%.c $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@" # compile special windows utils | | | | | | | 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 | $(LINK) $(LINKFLAGS) -out:"$@" $< # compiling standard fossil utils $(UTILS_OBJ): %.obj: $(SRCDIR)%.c $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@" # compile special windows utils version.obj: $(SRCDIR_tools)mkversion.c $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@" # generate the translated c-source files $(TRANSLATEDSRC): %_.c: $(SRCDIR)%.c translate.exe translate.exe $< >$@ # generate the index source, containing all web references,.. page_index.h: $(TRANSLATEDSRC) mkindex.exe mkindex.exe $(TRANSLATEDSRC) >$@ builtin_data.h: $(EXTRA_FILES) mkbuiltin.exe mkbuiltin.exe --prefix $(SRCDIR)/ $(EXTRA_FILES) >$@ # extracting version info from manifest VERSION.h: version.exe ..\manifest.uuid ..\manifest ..\VERSION version.exe ..\manifest.uuid ..\manifest ..\VERSION >$@ # generate the simplified headers headers: makeheaders.exe page_index.h builtin_data.h VERSION.h ../src/extsrc/sqlite3.h ../src/th.h makeheaders.exe $(foreach ts,$(TRANSLATEDSRC),$(ts):$(ts:_.c=.h)) ../src/extsrc/sqlite3.h ../src/th.h VERSION.h echo Done >$@ # compile C sources with relevant options $(TRANSLATEDOBJ): %_.obj: %_.c %.h $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@" $(SQLITEOBJ): %.obj: $(SRCDIR_extsrc)%.c $(SRCDIR_extsrc)%.h $(CC) $(CCFLAGS) $(SQLITEDEFINES) $(INCLUDE) "$<" -Fo"$@" $(SQLITESHELLOBJ): %.obj: $(SRCDIR_extsrc)%.c $(CC) $(CCFLAGS) $(SQLITESHELLDEFINES) $(INCLUDE) "$<" -Fo"$@" $(THOBJ): %.obj: $(SRCDIR)%.c $(SRCDIR)th.h $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@" $(ZLIBOBJ): %.obj: $(ZLIBSRCDIR)%.c $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@" |
| ︙ | ︙ |
Name change from src/mkbuiltin.c to tools/mkbuiltin.c.
| ︙ | ︙ |
Name change from src/mkindex.c to tools/mkindex.c.
| ︙ | ︙ |
Name change from src/mkversion.c to tools/mkversion.c.
| ︙ | ︙ |
Name change from src/sqlcompattest.c to tools/sqlcompattest.c.
| ︙ | ︙ |
Name change from src/translate.c to tools/translate.c.
| ︙ | ︙ |
Changes to win/Makefile.PellesCGMake.
1 2 | # ############################################################################## | | | 1 2 3 4 5 6 7 8 9 10 | # ############################################################################## # WARNING: DO NOT EDIT, AUTOMATICALLY GENERATED FILE (SEE "tools/makemake.tcl") ############################################################################## # # This file is automatically generated. Instead of editing this # file, edit "makemake.tcl" then run "tclsh makemake.tcl" # to regenerate this file. # # HowTo |
| ︙ | ︙ | |||
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | TARGETMACHINE_LN=ix86 TARGETEXTEND= endif # define the project directories B=.. SRCDIR=$(B)/src/ WINDIR=$(B)/win/ ZLIBSRCDIR=../../zlib/ # define linker command and options LINK=$(PellesCDir)/bin/polink.exe LINKFLAGS=-subsystem:console -machine:$(TARGETMACHINE_LN) /LIBPATH:$(PellesCDir)\lib\win$(TARGETEXTEND) /LIBPATH:$(PellesCDir)\lib kernel32.lib advapi32.lib delayimp$(TARGETEXTEND).lib Wsock32.lib dnsapi.lib Crtmt$(TARGETEXTEND).lib # define standard C-compiler and flags, used to compile # the fossil binary. Some special definitions follow for # special files follow CC=$(PellesCDir)\bin\pocc.exe DEFINES=-D_pgmptr=g.argv[0] CCFLAGS=-T$(TARGETMACHINE_CC)-coff -Ot -W2 -Gd -Go -Ze -MT $(DEFINES) | > > | | | | | | | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | TARGETMACHINE_LN=ix86 TARGETEXTEND= endif # define the project directories B=.. SRCDIR=$(B)/src/ SRCDIR_extsrc=$(B)/extsrc/ SRCDIR_tools=$(B)/tools/ WINDIR=$(B)/win/ ZLIBSRCDIR=../../zlib/ # define linker command and options LINK=$(PellesCDir)/bin/polink.exe LINKFLAGS=-subsystem:console -machine:$(TARGETMACHINE_LN) /LIBPATH:$(PellesCDir)\lib\win$(TARGETEXTEND) /LIBPATH:$(PellesCDir)\lib kernel32.lib advapi32.lib delayimp$(TARGETEXTEND).lib Wsock32.lib dnsapi.lib Crtmt$(TARGETEXTEND).lib # define standard C-compiler and flags, used to compile # the fossil binary. Some special definitions follow for # special files follow CC=$(PellesCDir)\bin\pocc.exe DEFINES=-D_pgmptr=g.argv[0] CCFLAGS=-T$(TARGETMACHINE_CC)-coff -Ot -W2 -Gd -Go -Ze -MT $(DEFINES) INCLUDE=/I $(PellesCDir)\Include\Win /I $(PellesCDir)\Include /I $(ZLIBSRCDIR) /I $(SRCDIR) /I $(SRCDIR_extsrc) # define commands for building the windows resource files RESOURCE=fossil.res RC=$(PellesCDir)\bin\porc.exe RCFLAGS=$(INCLUDE) -D__POCC__=1 -D_M_X$(TARGETVERSION) # define the special utilities files, needed to generate # the automatically generated source files UTILS=translate.exe mkindex.exe makeheaders.exe mkbuiltin.exe UTILS_OBJ=$(UTILS:.exe=.obj) UTILS_SRC=$(foreach uf,$(UTILS),$(SRCDIR_tools)$(uf:.exe=.c)) # define the SQLite files, which need special flags on compile SQLITESRC=sqlite3.c ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR_extsrc)$(sf)) SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj)) SQLITEDEFINES=-DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -DSQLITE_WIN32_NO_ANSI # define the SQLite shell files, which need special flags on compile SQLITESHELLSRC=shell.c ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR_extsrc)$(sf)) SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj)) SQLITESHELLDEFINES=-DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen # define the th scripting files, which need special flags on compile THSRC=th.c th_lang.c ORIGTHSRC=$(foreach sf,$(THSRC),$(SRCDIR)$(sf)) THOBJ=$(foreach sf,$(THSRC),$(sf:.c=.obj)) # define the zlib files, needed by this compile |
| ︙ | ︙ | |||
127 128 129 130 131 132 133 | $(LINK) $(LINKFLAGS) -out:"$@" $< # compiling standard fossil utils $(UTILS_OBJ): %.obj: $(SRCDIR)%.c $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@" # compile special windows utils | | | | | | | 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | $(LINK) $(LINKFLAGS) -out:"$@" $< # compiling standard fossil utils $(UTILS_OBJ): %.obj: $(SRCDIR)%.c $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@" # compile special windows utils version.obj: $(SRCDIR_tools)mkversion.c $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@" # generate the translated c-source files $(TRANSLATEDSRC): %_.c: $(SRCDIR)%.c translate.exe translate.exe $< >$@ # generate the index source, containing all web references,.. page_index.h: $(TRANSLATEDSRC) mkindex.exe mkindex.exe $(TRANSLATEDSRC) >$@ builtin_data.h: $(EXTRA_FILES) mkbuiltin.exe mkbuiltin.exe --prefix $(SRCDIR)/ $(EXTRA_FILES) >$@ # extracting version info from manifest VERSION.h: version.exe ..\manifest.uuid ..\manifest ..\VERSION version.exe ..\manifest.uuid ..\manifest ..\VERSION >$@ # generate the simplified headers headers: makeheaders.exe page_index.h builtin_data.h VERSION.h ../src/extsrc/sqlite3.h ../src/th.h makeheaders.exe $(foreach ts,$(TRANSLATEDSRC),$(ts):$(ts:_.c=.h)) ../src/extsrc/sqlite3.h ../src/th.h VERSION.h echo Done >$@ # compile C sources with relevant options $(TRANSLATEDOBJ): %_.obj: %_.c %.h $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@" $(SQLITEOBJ): %.obj: $(SRCDIR_extsrc)%.c $(SRCDIR_extsrc)%.h $(CC) $(CCFLAGS) $(SQLITEDEFINES) $(INCLUDE) "$<" -Fo"$@" $(SQLITESHELLOBJ): %.obj: $(SRCDIR_extsrc)%.c $(CC) $(CCFLAGS) $(SQLITESHELLDEFINES) $(INCLUDE) "$<" -Fo"$@" $(THOBJ): %.obj: $(SRCDIR)%.c $(SRCDIR)th.h $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@" $(ZLIBOBJ): %.obj: $(ZLIBSRCDIR)%.c $(CC) $(CCFLAGS) $(INCLUDE) "$<" -Fo"$@" |
| ︙ | ︙ |
Changes to win/Makefile.dmc.
1 2 | # ############################################################################## | | > > | | | | | | | | | | | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | # ############################################################################## # WARNING: DO NOT EDIT, AUTOMATICALLY GENERATED FILE (SEE "tools/makemake.tcl") ############################################################################## # # This file is automatically generated. Instead of editing this # file, edit "makemake.tcl" then run "tclsh makemake.tcl" # to regenerate this file. # B = .. SRCDIR = $B\src SRCDIR_extsrc = $B\extsrc SRCDIR_tools = $B\tools OBJDIR = . O = .obj E = .exe # Maybe DMDIR, SSL or INCL needs adjustment DMDIR = c:\DM INCL = -I. -I$(SRCDIR) -I$(SRCDIR_extsrc) -I$B\win\include -I$(DMDIR)\extra\include #SSL = -DFOSSIL_ENABLE_SSL=1 SSL = CFLAGS = -o BCC = $(DMDIR)\bin\dmc $(CFLAGS) TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 dnsapi SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen SRC = add_.c ajax_.c alerts_.c allrepo_.c attach_.c backlink_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.c captcha_.c cgi_.c chat_.c checkin_.c checkout_.c clearsign_.c clone_.c color_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c deltafunc_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c extcgi_.c file_.c fileedit_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.c glob_.c graph_.c gzip_.c hname_.c hook_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c interwiki_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c patch_.c path_.c piechart_.c pikchrshow_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c repolist_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c terminal_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c xfer_.c xfersetup_.c zip_.c OBJ = $(OBJDIR)\add$O $(OBJDIR)\ajax$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\backlink$O $(OBJDIR)\backoffice$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\capabilities$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\chat$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\color$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\cookies$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\deltafunc$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\etag$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\extcgi$O $(OBJDIR)\file$O $(OBJDIR)\fileedit$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\forum$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\fuzz$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\hname$O $(OBJDIR)\hook$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\interwiki$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\patch$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pikchrshow$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\repolist$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\setupuser$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\smtp$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\terminal$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\unversioned$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O RC=$(DMDIR)\bin\rcc RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ APPNAME = $(OBJDIR)\fossil$(E) all: $(APPNAME) $(APPNAME) : translate$E mkindex$E codecheck1$E headers $(OBJ) $(OBJDIR)\link cd $(OBJDIR) codecheck1$E $(SRC) $(DMDIR)\bin\link @link $(OBJDIR)\fossil.res: $B\win\fossil.rc $(RC) $(RCFLAGS) -o$@ $** $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res +echo add ajax alerts allrepo attach backlink backoffice bag bisect blob branch browse builtin bundle cache capabilities captcha cgi chat checkin checkout clearsign clone color comformat configure content cookies db delta deltacmd deltafunc descendants diff diffcmd dispatch doc encode etag event export extcgi file fileedit finfo foci forum fshell fusefs fuzz glob graph gzip hname hook http http_socket http_ssl http_transport import info interwiki json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name patch path piechart pikchrshow pivot popen pqueue printf publish purge rebuild regexp repolist report rss schema search security_audit setup setupuser sha1 sha1hard sha3 shun sitemap skins smtp sqlcmd stash stat statrep style sync tag tar terminal th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile wiki wikiformat winfile winhttp xfer xfersetup zip shell sqlite3 th th_lang > $@ +echo fossil >> $@ +echo fossil >> $@ +echo $(LIBS) >> $@ +echo. >> $@ +echo fossil >> $@ translate$E: $(SRCDIR_tools)\translate.c $(BCC) -o$@ $** makeheaders$E: $(SRCDIR_tools)\makeheaders.c $(BCC) -o$@ $** mkindex$E: $(SRCDIR_tools)\mkindex.c $(BCC) -o$@ $** mkbuiltin$E: $(SRCDIR_tools)\mkbuiltin.c $(BCC) -o$@ $** mkversion$E: $(SRCDIR_tools)\mkversion.c $(BCC) -o$@ $** codecheck1$E: $(SRCDIR_tools)\codecheck1.c $(BCC) -o$@ $** $(OBJDIR)\shell$O : $(SRCDIR_extsrc)\shell.c $(TCC) -o$@ -c $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) $** $(OBJDIR)\sqlite3$O : $(SRCDIR_extsrc)\sqlite3.c $(TCC) -o$@ -c $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $** $(OBJDIR)\th$O : $(SRCDIR)\th.c $(TCC) -o$@ -c $** $(OBJDIR)\th_lang$O : $(SRCDIR)\th_lang.c $(TCC) -o$@ -c $** $(OBJDIR)\cson_amalgamation.h : $(SRCDIR_extsrc)\cson_amalgamation.h cp $@ $@ VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION +$** > $@ page_index.h: mkindex$E $(SRC) +$** > $@ |
| ︙ | ︙ | |||
678 679 680 681 682 683 684 | $(OBJDIR)\piechart$O : piechart_.c piechart.h $(TCC) -o$@ -c piechart_.c piechart_.c : $(SRCDIR)\piechart.c +translate$E $** > $@ | < < < < < < | 680 681 682 683 684 685 686 687 688 689 690 691 692 693 | $(OBJDIR)\piechart$O : piechart_.c piechart.h $(TCC) -o$@ -c piechart_.c piechart_.c : $(SRCDIR)\piechart.c +translate$E $** > $@ $(OBJDIR)\pikchrshow$O : pikchrshow_.c pikchrshow.h $(TCC) -o$@ -c pikchrshow_.c pikchrshow_.c : $(SRCDIR)\pikchrshow.c +translate$E $** > $@ $(OBJDIR)\pivot$O : pivot_.c pivot.h |
| ︙ | ︙ | |||
1009 1010 1011 1012 1013 1014 1015 | $(OBJDIR)\zip$O : zip_.c zip.h $(TCC) -o$@ -c zip_.c zip_.c : $(SRCDIR)\zip.c +translate$E $** > $@ headers: makeheaders$E page_index.h builtin_data.h VERSION.h | | | 1005 1006 1007 1008 1009 1010 1011 1012 1013 | $(OBJDIR)\zip$O : zip_.c zip.h $(TCC) -o$@ -c zip_.c zip_.c : $(SRCDIR)\zip.c +translate$E $** > $@ headers: makeheaders$E page_index.h builtin_data.h VERSION.h +makeheaders$E add_.c:add.h ajax_.c:ajax.h alerts_.c:alerts.h allrepo_.c:allrepo.h attach_.c:attach.h backlink_.c:backlink.h backoffice_.c:backoffice.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h capabilities_.c:capabilities.h captcha_.c:captcha.h cgi_.c:cgi.h chat_.c:chat.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h color_.c:color.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h cookies_.c:cookies.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h deltafunc_.c:deltafunc.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h dispatch_.c:dispatch.h doc_.c:doc.h encode_.c:encode.h etag_.c:etag.h event_.c:event.h export_.c:export.h extcgi_.c:extcgi.h file_.c:file.h fileedit_.c:fileedit.h finfo_.c:finfo.h foci_.c:foci.h forum_.c:forum.h fshell_.c:fshell.h fusefs_.c:fusefs.h fuzz_.c:fuzz.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h hname_.c:hname.h hook_.c:hook.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h interwiki_.c:interwiki.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h patch_.c:patch.h path_.c:path.h piechart_.c:piechart.h pikchrshow_.c:pikchrshow.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h repolist_.c:repolist.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h security_audit_.c:security_audit.h setup_.c:setup.h setupuser_.c:setupuser.h sha1_.c:sha1.h sha1hard_.c:sha1hard.h sha3_.c:sha3.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h smtp_.c:smtp.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h terminal_.c:terminal.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h unversioned_.c:unversioned.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR_extsrc)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR_extsrc)\cson_amalgamation.h @copy /Y nul: headers |
Changes to win/Makefile.mingw.
1 2 3 | #!/usr/bin/make # ############################################################################## | | | 1 2 3 4 5 6 7 8 9 10 11 | #!/usr/bin/make # ############################################################################## # WARNING: DO NOT EDIT, AUTOMATICALLY GENERATED FILE (SEE "tools/makemake.tcl") ############################################################################## # # This file is automatically generated. Instead of editing this # file, edit "makemake.tcl" then run "tclsh makemake.tcl" # to regenerate this file. # # This is a makefile for use on Cygwin/Darwin/FreeBSD/Linux/Windows using |
| ︙ | ︙ | |||
26 27 28 29 30 31 32 33 34 35 36 37 38 39 | # PREFIX = x86_64-w64-mingw32- #### The toplevel directory of the source tree. Fossil can be built # in a directory that is separate from the source tree. Just change # the following to point from the build directory to the src/ folder. # SRCDIR = src #### The directory into which object code files should be written. # OBJDIR = wbld #### C compiler for use in building executables that will run on # the platform that is doing the build. This is used to compile | > > | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | # PREFIX = x86_64-w64-mingw32- #### The toplevel directory of the source tree. Fossil can be built # in a directory that is separate from the source tree. Just change # the following to point from the build directory to the src/ folder. # SRCDIR = src SRCDIR_extsrc = extsrc SRCDIR_tools = tools #### The directory into which object code files should be written. # OBJDIR = wbld #### C compiler for use in building executables that will run on # the platform that is doing the build. This is used to compile |
| ︙ | ︙ | |||
99 100 101 102 103 104 105 | # # USE_MMAN_H = 1 #### Use the SQLite Encryption Extension # # USE_SEE = 1 | < < < < | 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | # # USE_MMAN_H = 1 #### Use the SQLite Encryption Extension # # USE_SEE = 1 #### Use the Tcl source directory instead of the install directory? # This is useful when Tcl has been compiled statically with MinGW. # FOSSIL_TCL_SOURCE = 1 #### Check if the workaround for the MinGW command line handling needs to # be enabled by default. This check may be somewhat fragile due to the |
| ︙ | ︙ | |||
138 139 140 141 142 143 144 | #### Determine if the optimized assembly routines provided with zlib should be # used, taking into account whether zlib is actually enabled and the target # processor architecture. # ifndef X64 SSLCONFIG = mingw | < < < < < < < | 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | #### Determine if the optimized assembly routines provided with zlib should be # used, taking into account whether zlib is actually enabled and the target # processor architecture. # ifndef X64 SSLCONFIG = mingw ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" ZLIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o else SSLCONFIG = mingw64 ZLIBCONFIG = ZLIBTARGETS = endif #### Disable creation of the OpenSSL shared libraries. Also, disable support # for SSLv3 (i.e. thereby forcing the use of TLS). # SSLCONFIG += no-ssl3 no-weak-ssl-ciphers no-shared #### When using zlib, make sure that OpenSSL is configured to use the zlib # that Fossil knows about (i.e. the one within the source tree). # SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib #### The directories where the OpenSSL include and library files are located. # OPENSSLDIR = $(SRCDIR)/../compat/openssl OPENSSLINCDIR = $(OPENSSLDIR)/include OPENSSLLIBDIR = $(OPENSSLDIR) |
| ︙ | ︙ | |||
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 | #### C compiler and options for use in building executables that will # run on the target platform. This is usually the almost the same # as BCC, unless you are cross-compiling. This C compiler builds # the finished binary for fossil. The BCC compiler above is used # for building intermediate code-generator tools. # TCC = $(PREFIX)$(TCCEXE) -Wall -Wdeclaration-after-statement #### Add the necessary command line options to build with debugging # symbols, if enabled. # ifdef FOSSIL_ENABLE_SYMBOLS TCC += -g else TCC += -Os endif | > < < < < | < < | < < < < < < < | 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 | #### C compiler and options for use in building executables that will # run on the target platform. This is usually the almost the same # as BCC, unless you are cross-compiling. This C compiler builds # the finished binary for fossil. The BCC compiler above is used # for building intermediate code-generator tools. # TCC = $(PREFIX)$(TCCEXE) -Wall -Wdeclaration-after-statement TCC += -I$(SRCDIR_extsrc) #### Add the necessary command line options to build with debugging # symbols, if enabled. # ifdef FOSSIL_ENABLE_SYMBOLS TCC += -g else TCC += -Os endif TCC += -L$(ZLIBDIR) -I$(ZINCDIR) #### Compile resources for use in building executables that will run # on the target platform. # RCC = $(PREFIX)windres -I$(SRCDIR) -I$(ZINCDIR) RCC += -I$(SRCDIR_extsrc) # With HTTPS support ifdef FOSSIL_ENABLE_SSL TCC += -L$(OPENSSLLIBDIR) -I$(OPENSSLINCDIR) RCC += -I$(OPENSSLINCDIR) endif # With Tcl support ifdef FOSSIL_ENABLE_TCL ifdef FOSSIL_TCL_SOURCE TCC += -L$(TCLSRCDIR)/win -I$(TCLSRCDIR)/generic -I$(TCLSRCDIR)/win RCC += -I$(TCLSRCDIR)/generic -I$(TCLSRCDIR)/win else TCC += -L$(TCLLIBDIR) -I$(TCLINCDIR) RCC += -I$(TCLINCDIR) endif endif # With MinGW command line handling workaround ifdef MINGW_IS_32BIT_ONLY TCC += -DBROKEN_MINGW_CMDLINE=1 RCC += -DBROKEN_MINGW_CMDLINE=1 endif # With HTTPS support |
| ︙ | ︙ | |||
374 375 376 377 378 379 380 | #### Extra arguments for linking the finished binary. Fossil needs # to link against the Z-Lib compression library. There are no # other mandatory dependencies. # LIB += -lmingwex | | < < | 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 | #### Extra arguments for linking the finished binary. Fossil needs # to link against the Z-Lib compression library. There are no # other mandatory dependencies. # LIB += -lmingwex #### zlib is required. # LIB += -lz #### These libraries MUST appear in the same order as they do for Tcl # or linking with it will not work (exact reason unknown). # ifdef FOSSIL_ENABLE_TCL ifdef FOSSIL_ENABLE_TCL_STUBS LIB += -lkernel32 -lws2_32 |
| ︙ | ︙ | |||
514 515 516 517 518 519 520 | $(SRCDIR)/merge.c \ $(SRCDIR)/merge3.c \ $(SRCDIR)/moderate.c \ $(SRCDIR)/name.c \ $(SRCDIR)/patch.c \ $(SRCDIR)/path.c \ $(SRCDIR)/piechart.c \ | < | 491 492 493 494 495 496 497 498 499 500 501 502 503 504 | $(SRCDIR)/merge.c \ $(SRCDIR)/merge3.c \ $(SRCDIR)/moderate.c \ $(SRCDIR)/name.c \ $(SRCDIR)/patch.c \ $(SRCDIR)/path.c \ $(SRCDIR)/piechart.c \ $(SRCDIR)/pikchrshow.c \ $(SRCDIR)/pivot.c \ $(SRCDIR)/popen.c \ $(SRCDIR)/pqueue.c \ $(SRCDIR)/printf.c \ $(SRCDIR)/publish.c \ $(SRCDIR)/purge.c \ |
| ︙ | ︙ | |||
773 774 775 776 777 778 779 | $(OBJDIR)/merge_.c \ $(OBJDIR)/merge3_.c \ $(OBJDIR)/moderate_.c \ $(OBJDIR)/name_.c \ $(OBJDIR)/patch_.c \ $(OBJDIR)/path_.c \ $(OBJDIR)/piechart_.c \ | < | 749 750 751 752 753 754 755 756 757 758 759 760 761 762 | $(OBJDIR)/merge_.c \ $(OBJDIR)/merge3_.c \ $(OBJDIR)/moderate_.c \ $(OBJDIR)/name_.c \ $(OBJDIR)/patch_.c \ $(OBJDIR)/path_.c \ $(OBJDIR)/piechart_.c \ $(OBJDIR)/pikchrshow_.c \ $(OBJDIR)/pivot_.c \ $(OBJDIR)/popen_.c \ $(OBJDIR)/pqueue_.c \ $(OBJDIR)/printf_.c \ $(OBJDIR)/publish_.c \ $(OBJDIR)/purge_.c \ |
| ︙ | ︙ | |||
923 924 925 926 927 928 929 | $(OBJDIR)/merge.o \ $(OBJDIR)/merge3.o \ $(OBJDIR)/moderate.o \ $(OBJDIR)/name.o \ $(OBJDIR)/patch.o \ $(OBJDIR)/path.o \ $(OBJDIR)/piechart.o \ | < | 898 899 900 901 902 903 904 905 906 907 908 909 910 911 | $(OBJDIR)/merge.o \ $(OBJDIR)/merge3.o \ $(OBJDIR)/moderate.o \ $(OBJDIR)/name.o \ $(OBJDIR)/patch.o \ $(OBJDIR)/path.o \ $(OBJDIR)/piechart.o \ $(OBJDIR)/pikchrshow.o \ $(OBJDIR)/pivot.o \ $(OBJDIR)/popen.o \ $(OBJDIR)/pqueue.o \ $(OBJDIR)/printf.o \ $(OBJDIR)/publish.o \ $(OBJDIR)/purge.o \ |
| ︙ | ︙ | |||
1023 1024 1025 1026 1027 1028 1029 | RMDIR = rm -rf endif all: $(OBJDIR) $(APPNAME) $(OBJDIR)/fossil.o: $(SRCDIR)/../win/fossil.rc $(OBJDIR)/VERSION.h ifdef USE_WINDOWS | < < | 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 | RMDIR = rm -rf endif all: $(OBJDIR) $(APPNAME) $(OBJDIR)/fossil.o: $(SRCDIR)/../win/fossil.rc $(OBJDIR)/VERSION.h ifdef USE_WINDOWS $(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.rc) $(subst /,\,$(OBJDIR)) $(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.ico) $(subst /,\,$(OBJDIR)) $(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.exe.manifest) $(subst /,\,$(OBJDIR)) else $(CP) $(SRCDIR)/../win/fossil.rc $(OBJDIR) $(CP) $(SRCDIR)/../win/fossil.ico $(OBJDIR) $(CP) $(SRCDIR)/../win/fossil.exe.manifest $(OBJDIR) endif $(RCC) $(OBJDIR)/fossil.rc -o $(OBJDIR)/fossil.o install: $(OBJDIR) $(APPNAME) |
| ︙ | ︙ | |||
1051 1052 1053 1054 1055 1056 1057 | $(OBJDIR): ifdef USE_WINDOWS $(MKDIR) $(subst /,\,$(OBJDIR)) else $(MKDIR) $(OBJDIR) endif | | | | | | | | | | | | | | | > > > > > < < < < < < < | | | | | | > | | | | > | | | | < < < < | 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 | $(OBJDIR): ifdef USE_WINDOWS $(MKDIR) $(subst /,\,$(OBJDIR)) else $(MKDIR) $(OBJDIR) endif $(TRANSLATE): $(SRCDIR_tools)/translate.c $(XBCC) -o $@ $(SRCDIR_tools)/translate.c $(MAKEHEADERS): $(SRCDIR_tools)/makeheaders.c $(XBCC) -o $@ $(SRCDIR_tools)/makeheaders.c $(MKINDEX): $(SRCDIR_tools)/mkindex.c $(XBCC) -o $@ $(SRCDIR_tools)/mkindex.c $(MKBUILTIN): $(SRCDIR_tools)/mkbuiltin.c $(XBCC) -o $@ $(SRCDIR_tools)/mkbuiltin.c $(MKVERSION): $(SRCDIR_tools)/mkversion.c $(XBCC) -o $@ $(SRCDIR_tools)/mkversion.c $(CODECHECK1): $(SRCDIR_tools)/codecheck1.c $(XBCC) -o $@ $(SRCDIR_tools)/codecheck1.c # WARNING. DANGER. Running the test suite modifies the repository the # build is done from, i.e. the checkout belongs to. Do not sync/push # the repository after running the tests. test: $(OBJDIR) $(APPNAME) $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) $(OBJDIR)/phony.h $(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@ $(OBJDIR)/phony.h: # Force rebuild of VERSION.h every time "make" is run # The USE_SYSTEM_SQLITE variable may be undefined, set to 0 or 1. # If it is set to 1, then there is no need to build or link # the sqlite3.o object. Instead, the system SQLite will be linked # using -lsqlite3. # # Closely related is SQLITE3_ORIGIN, with the same 0/1 mapping, # plus a value of 2 means that we are building a client-provided # sqlite3.c. SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o SQLITE3_OBJ.1 = # SQLITE3_OBJ.2 is set by the configure process SQLITE3_OBJ. = $(SQLITE3_OBJ.0) # The USE_SEE variable may be undefined, 0 or 1. If undefined or 0, # in-tree SQLite is used. If 1, then sqlite3-see.c (not part of the # source tree) is used and extra flags are provided to enable the # SQLite Encryption Extension. SQLITE3_SRC.0 = $(SRCDIR_extsrc)/sqlite3.c SQLITE3_SRC.1 = $(SRCDIR_extsrc)/sqlite3-see.c # SQLITE3_SRC.2 is set by top-level configure/makefile process. SQLITE3_SRC. = $(SRCDIR_extsrc)/sqlite3.c SQLITE3_SRC = $(SQLITE3_SRC.$(SQLITE3_ORIGIN)) SQLITE3_SHELL_SRC.0 = $(SRCDIR_extsrc)/shell.c SQLITE3_SHELL_SRC.1 = $(SRCDIR_extsrc)/shell-see.c # SQLITE3_SHELL_SRC.2 comes from the configure process SQLITE3_SHELL_SRC. = $(SRCDIR_extsrc)/shell.c SQLITE3_SHELL_SRC = $(SQLITE3_SHELL_SRC.$(SQLITE3_ORIGIN)) SEE_FLAGS.0 = SEE_FLAGS.1 = -DSQLITE_HAS_CODEC -DSQLITE_SHELL_DBKEY_PROC=fossil_key SEE_FLAGS. = SEE_FLAGS = $(SEE_FLAGS.$(USE_SEE)) EXTRAOBJ = \ $(SQLITE3_OBJ.$(SQLITE3_ORIGIN)) \ $(OBJDIR)/pikchr.o \ $(OBJDIR)/shell.o \ $(OBJDIR)/th.o \ $(OBJDIR)/th_lang.o \ $(OBJDIR)/th_tcl.o \ $(OBJDIR)/cson_amalgamation.o $(ZLIBDIR)/inffas86.o: $(TCC) -c -o $@ -DASMINF -I$(ZLIBDIR) -O3 $(ZLIBDIR)/contrib/inflate86/inffas86.c $(ZLIBDIR)/match.o: $(TCC) -c -o $@ -DASMV $(ZLIBDIR)/contrib/asm686/match.S zlib: $(ZLIBTARGETS) $(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) CC=$(PREFIX)$(TCCEXE) $(ZLIBCONFIG) -f win32/Makefile.gcc libz.a clean-zlib: $(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) CC=$(PREFIX)$(TCCEXE) -f win32/Makefile.gcc clean BLDTARGETS = zlib openssl: $(BLDTARGETS) cd $(OPENSSLLIBDIR);./Configure --cross-compile-prefix=$(PREFIX) $(SSLCONFIG) sed -i -e 's/^PERL=C:\\.*$$/PERL=perl.exe/i' $(OPENSSLLIBDIR)/Makefile $(MAKE) -C $(OPENSSLLIBDIR) PREFIX=$(PREFIX) CC=$(PREFIX)$(TCCEXE) build_libs clean-openssl: |
| ︙ | ︙ | |||
1196 1197 1198 1199 1200 1201 1202 | $(MKINDEX) $(TRANS_SRC) >$@ $(OBJDIR)/builtin_data.h: $(MKBUILTIN) $(EXTRA_FILES) $(MKBUILTIN) --prefix $(SRCDIR)/ $(EXTRA_FILES) >$@ $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/builtin_data.h $(MAKEHEADERS) $(OBJDIR)/VERSION.h $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h \ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | | | | 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 | $(MKINDEX) $(TRANS_SRC) >$@ $(OBJDIR)/builtin_data.h: $(MKBUILTIN) $(EXTRA_FILES) $(MKBUILTIN) --prefix $(SRCDIR)/ $(EXTRA_FILES) >$@ $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/builtin_data.h $(MAKEHEADERS) $(OBJDIR)/VERSION.h $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h \ $(OBJDIR)/ajax_.c:$(OBJDIR)/ajax.h \ $(OBJDIR)/alerts_.c:$(OBJDIR)/alerts.h \ $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h \ $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h \ $(OBJDIR)/backlink_.c:$(OBJDIR)/backlink.h \ $(OBJDIR)/backoffice_.c:$(OBJDIR)/backoffice.h \ $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h \ $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h \ $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h \ $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h \ $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h \ $(OBJDIR)/builtin_.c:$(OBJDIR)/builtin.h \ $(OBJDIR)/bundle_.c:$(OBJDIR)/bundle.h \ $(OBJDIR)/cache_.c:$(OBJDIR)/cache.h \ $(OBJDIR)/capabilities_.c:$(OBJDIR)/capabilities.h \ $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h \ $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h \ $(OBJDIR)/chat_.c:$(OBJDIR)/chat.h \ $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h \ $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h \ $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h \ $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h \ $(OBJDIR)/color_.c:$(OBJDIR)/color.h \ $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h \ $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h \ $(OBJDIR)/content_.c:$(OBJDIR)/content.h \ $(OBJDIR)/cookies_.c:$(OBJDIR)/cookies.h \ $(OBJDIR)/db_.c:$(OBJDIR)/db.h \ $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h \ $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h \ $(OBJDIR)/deltafunc_.c:$(OBJDIR)/deltafunc.h \ $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h \ $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h \ $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h \ $(OBJDIR)/dispatch_.c:$(OBJDIR)/dispatch.h \ $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \ $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \ $(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \ $(OBJDIR)/event_.c:$(OBJDIR)/event.h \ $(OBJDIR)/export_.c:$(OBJDIR)/export.h \ $(OBJDIR)/extcgi_.c:$(OBJDIR)/extcgi.h \ $(OBJDIR)/file_.c:$(OBJDIR)/file.h \ $(OBJDIR)/fileedit_.c:$(OBJDIR)/fileedit.h \ $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \ $(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \ $(OBJDIR)/forum_.c:$(OBJDIR)/forum.h \ $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ $(OBJDIR)/fuzz_.c:$(OBJDIR)/fuzz.h \ $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ $(OBJDIR)/hname_.c:$(OBJDIR)/hname.h \ $(OBJDIR)/hook_.c:$(OBJDIR)/hook.h \ $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \ $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \ $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \ $(OBJDIR)/import_.c:$(OBJDIR)/import.h \ $(OBJDIR)/info_.c:$(OBJDIR)/info.h \ $(OBJDIR)/interwiki_.c:$(OBJDIR)/interwiki.h \ $(OBJDIR)/json_.c:$(OBJDIR)/json.h \ $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h \ $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h \ $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h \ $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h \ $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h \ $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h \ $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h \ $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h \ $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h \ $(OBJDIR)/json_status_.c:$(OBJDIR)/json_status.h \ $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h \ $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h \ $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h \ $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h \ $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h \ $(OBJDIR)/loadctrl_.c:$(OBJDIR)/loadctrl.h \ $(OBJDIR)/login_.c:$(OBJDIR)/login.h \ $(OBJDIR)/lookslike_.c:$(OBJDIR)/lookslike.h \ $(OBJDIR)/main_.c:$(OBJDIR)/main.h \ $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h \ $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h \ $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h \ $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \ $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \ $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \ $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \ $(OBJDIR)/name_.c:$(OBJDIR)/name.h \ $(OBJDIR)/patch_.c:$(OBJDIR)/patch.h \ $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ $(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \ $(OBJDIR)/pikchrshow_.c:$(OBJDIR)/pikchrshow.h \ $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ $(OBJDIR)/publish_.c:$(OBJDIR)/publish.h \ $(OBJDIR)/purge_.c:$(OBJDIR)/purge.h \ $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ $(OBJDIR)/repolist_.c:$(OBJDIR)/repolist.h \ $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ $(OBJDIR)/security_audit_.c:$(OBJDIR)/security_audit.h \ $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ $(OBJDIR)/setupuser_.c:$(OBJDIR)/setupuser.h \ $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ $(OBJDIR)/sha1hard_.c:$(OBJDIR)/sha1hard.h \ $(OBJDIR)/sha3_.c:$(OBJDIR)/sha3.h \ $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ $(OBJDIR)/smtp_.c:$(OBJDIR)/smtp.h \ $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \ $(OBJDIR)/statrep_.c:$(OBJDIR)/statrep.h \ $(OBJDIR)/style_.c:$(OBJDIR)/style.h \ $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h \ $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h \ $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h \ $(OBJDIR)/terminal_.c:$(OBJDIR)/terminal.h \ $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \ $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \ $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \ $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \ $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \ $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h \ $(OBJDIR)/unversioned_.c:$(OBJDIR)/unversioned.h \ $(OBJDIR)/update_.c:$(OBJDIR)/update.h \ $(OBJDIR)/url_.c:$(OBJDIR)/url.h \ $(OBJDIR)/user_.c:$(OBJDIR)/user.h \ $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h \ $(OBJDIR)/util_.c:$(OBJDIR)/util.h \ $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h \ $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h \ $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h \ $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h \ $(OBJDIR)/winfile_.c:$(OBJDIR)/winfile.h \ $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h \ $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h \ $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h \ $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h \ $(SRCDIR_extsrc)/pikchr.c:$(OBJDIR)/pikchr.h \ $(SRCDIR_extsrc)/sqlite3.h \ $(SRCDIR)/th.h \ $(OBJDIR)/VERSION.h echo Done >$(OBJDIR)/headers $(OBJDIR)/headers: Makefile Makefile: $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(TRANSLATE) |
| ︙ | ︙ | |||
2096 2097 2098 2099 2100 2101 2102 | $(TRANSLATE) $(SRCDIR)/piechart.c >$@ $(OBJDIR)/piechart.o: $(OBJDIR)/piechart_.c $(OBJDIR)/piechart.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/piechart.o -c $(OBJDIR)/piechart_.c $(OBJDIR)/piechart.h: $(OBJDIR)/headers | < < < < < < < < | 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 | $(TRANSLATE) $(SRCDIR)/piechart.c >$@ $(OBJDIR)/piechart.o: $(OBJDIR)/piechart_.c $(OBJDIR)/piechart.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/piechart.o -c $(OBJDIR)/piechart_.c $(OBJDIR)/piechart.h: $(OBJDIR)/headers $(OBJDIR)/pikchrshow_.c: $(SRCDIR)/pikchrshow.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/pikchrshow.c >$@ $(OBJDIR)/pikchrshow.o: $(OBJDIR)/pikchrshow_.c $(OBJDIR)/pikchrshow.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/pikchrshow.o -c $(OBJDIR)/pikchrshow_.c $(OBJDIR)/pikchrshow.h: $(OBJDIR)/headers |
| ︙ | ︙ | |||
2550 2551 2552 2553 2554 2555 2556 |
-DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
-DSQLITE_OMIT_DECLTYPE \
-DSQLITE_OMIT_DEPRECATED \
-DSQLITE_OMIT_PROGRESS_CALLBACK \
-DSQLITE_OMIT_SHARED_CACHE \
-DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_MAX_EXPR_DEPTH=0 \
| < < < < < < < < < < | | | | | | 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 |
-DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
-DSQLITE_OMIT_DECLTYPE \
-DSQLITE_OMIT_DEPRECATED \
-DSQLITE_OMIT_PROGRESS_CALLBACK \
-DSQLITE_OMIT_SHARED_CACHE \
-DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_MAX_EXPR_DEPTH=0 \
-DSQLITE_ENABLE_LOCKING_STYLE=0 \
-DSQLITE_DEFAULT_FILE_FORMAT=4 \
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
-DSQLITE_ENABLE_FTS4 \
-DSQLITE_ENABLE_DBSTAT_VTAB \
-DSQLITE_ENABLE_FTS5 \
-DSQLITE_ENABLE_STMTVTAB \
-DSQLITE_HAVE_ZLIB \
-DSQLITE_ENABLE_DBPAGE_VTAB \
-DSQLITE_TRUSTED_SCHEMA=0 \
-DSQLITE_WIN32_NO_ANSI \
$(MINGW_OPTIONS) \
-DSQLITE_USE_MALLOC_H \
-DSQLITE_USE_MSIZE
SHELL_OPTIONS = -DNDEBUG=1 \
-DSQLITE_DQS=0 \
-DSQLITE_THREADSAFE=0 \
-DSQLITE_DEFAULT_MEMSTATUS=0 \
-DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \
-DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
-DSQLITE_OMIT_DECLTYPE \
-DSQLITE_OMIT_DEPRECATED \
-DSQLITE_OMIT_PROGRESS_CALLBACK \
-DSQLITE_OMIT_SHARED_CACHE \
-DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_MAX_EXPR_DEPTH=0 \
-DSQLITE_ENABLE_LOCKING_STYLE=0 \
-DSQLITE_DEFAULT_FILE_FORMAT=4 \
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
-DSQLITE_ENABLE_FTS4 \
-DSQLITE_ENABLE_DBSTAT_VTAB \
-DSQLITE_ENABLE_FTS5 \
-DSQLITE_ENABLE_STMTVTAB \
-DSQLITE_HAVE_ZLIB \
-DSQLITE_ENABLE_DBPAGE_VTAB \
-DSQLITE_TRUSTED_SCHEMA=0 \
-Dmain=sqlite3_shell \
-DSQLITE_SHELL_IS_UTF8=1 \
-DSQLITE_OMIT_LOAD_EXTENSION=1 \
-DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
-DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname \
-DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc \
-Daccess=file_access \
-Dsystem=fossil_system \
-Dgetenv=fossil_getenv \
-Dfopen=fossil_fopen
$(OBJDIR)/sqlite3.o: $(SQLITE3_SRC) $(SRCDIR)/../win/Makefile.mingw
$(XTCC) $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $(SEE_FLAGS) \
-c $(SQLITE3_SRC) -o $@
$(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c
$(XTCC) -c $(SRCDIR_extsrc)/cson_amalgamation.c -o $@
$(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/jsos_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_status.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
$(OBJDIR)/shell.o: $(SQLITE3_SHELL_SRC) $(SRCDIR_extsrc)/sqlite3.h $(SRCDIR)/../win/Makefile.mingw
$(XTCC) $(SHELL_OPTIONS) $(SHELL_CFLAGS) $(SEE_FLAGS) -c $(SQLITE3_SHELL_SRC) -o $@
$(OBJDIR)/th.o: $(SRCDIR)/th.c
$(XTCC) -c $(SRCDIR)/th.c -o $@
$(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c
$(XTCC) -c $(SRCDIR)/th_lang.c -o $@
$(OBJDIR)/th_tcl.o: $(SRCDIR)/th_tcl.c
$(XTCC) -c $(SRCDIR)/th_tcl.c -o $@
$(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c
$(XTCC) -c $(SRCDIR_extsrc)/pikchr.c -o $@
|
Changes to win/Makefile.mingw.mistachkin.
1 2 3 | #!/usr/bin/make # ############################################################################## | | | 1 2 3 4 5 6 7 8 9 10 11 | #!/usr/bin/make # ############################################################################## # WARNING: DO NOT EDIT, AUTOMATICALLY GENERATED FILE (SEE "tools/makemake.tcl") ############################################################################## # # This file is automatically generated. Instead of editing this # file, edit "makemake.tcl" then run "tclsh makemake.tcl" # to regenerate this file. # # This is a makefile for use on Cygwin/Darwin/FreeBSD/Linux/Windows using |
| ︙ | ︙ | |||
26 27 28 29 30 31 32 33 34 35 36 37 38 39 | # PREFIX = x86_64-w64-mingw32- #### The toplevel directory of the source tree. Fossil can be built # in a directory that is separate from the source tree. Just change # the following to point from the build directory to the src/ folder. # SRCDIR = src #### The directory into which object code files should be written. # OBJDIR = wbld #### C compiler for use in building executables that will run on # the platform that is doing the build. This is used to compile | > > | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | # PREFIX = x86_64-w64-mingw32- #### The toplevel directory of the source tree. Fossil can be built # in a directory that is separate from the source tree. Just change # the following to point from the build directory to the src/ folder. # SRCDIR = src SRCDIR_extsrc = extsrc SRCDIR_tools = tools #### The directory into which object code files should be written. # OBJDIR = wbld #### C compiler for use in building executables that will run on # the platform that is doing the build. This is used to compile |
| ︙ | ︙ | |||
99 100 101 102 103 104 105 | # # USE_MMAN_H = 1 #### Use the SQLite Encryption Extension # # USE_SEE = 1 | < < < < | 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | # # USE_MMAN_H = 1 #### Use the SQLite Encryption Extension # # USE_SEE = 1 #### Use the Tcl source directory instead of the install directory? # This is useful when Tcl has been compiled statically with MinGW. # FOSSIL_TCL_SOURCE = 1 #### Check if the workaround for the MinGW command line handling needs to # be enabled by default. This check may be somewhat fragile due to the |
| ︙ | ︙ | |||
138 139 140 141 142 143 144 | #### Determine if the optimized assembly routines provided with zlib should be # used, taking into account whether zlib is actually enabled and the target # processor architecture. # ifndef X64 SSLCONFIG = mingw | < < < < < < < | 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | #### Determine if the optimized assembly routines provided with zlib should be # used, taking into account whether zlib is actually enabled and the target # processor architecture. # ifndef X64 SSLCONFIG = mingw ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" ZLIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o else SSLCONFIG = mingw64 ZLIBCONFIG = ZLIBTARGETS = endif #### Disable creation of the OpenSSL shared libraries. Also, disable support # for SSLv3 (i.e. thereby forcing the use of TLS). # SSLCONFIG += no-ssl3 no-weak-ssl-ciphers no-shared #### When using zlib, make sure that OpenSSL is configured to use the zlib # that Fossil knows about (i.e. the one within the source tree). # SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib #### The directories where the OpenSSL include and library files are located. # OPENSSLDIR = $(SRCDIR)/../compat/openssl OPENSSLINCDIR = $(OPENSSLDIR)/include OPENSSLLIBDIR = $(OPENSSLDIR) |
| ︙ | ︙ | |||
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 | #### C compiler and options for use in building executables that will # run on the target platform. This is usually the almost the same # as BCC, unless you are cross-compiling. This C compiler builds # the finished binary for fossil. The BCC compiler above is used # for building intermediate code-generator tools. # TCC = $(PREFIX)$(TCCEXE) -Wall -Wdeclaration-after-statement #### Add the necessary command line options to build with debugging # symbols, if enabled. # ifdef FOSSIL_ENABLE_SYMBOLS TCC += -g else TCC += -Os endif | > < < < < | < < | < < < < < < < | 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 | #### C compiler and options for use in building executables that will # run on the target platform. This is usually the almost the same # as BCC, unless you are cross-compiling. This C compiler builds # the finished binary for fossil. The BCC compiler above is used # for building intermediate code-generator tools. # TCC = $(PREFIX)$(TCCEXE) -Wall -Wdeclaration-after-statement TCC += -I$(SRCDIR_extsrc) #### Add the necessary command line options to build with debugging # symbols, if enabled. # ifdef FOSSIL_ENABLE_SYMBOLS TCC += -g else TCC += -Os endif TCC += -L$(ZLIBDIR) -I$(ZINCDIR) #### Compile resources for use in building executables that will run # on the target platform. # RCC = $(PREFIX)windres -I$(SRCDIR) -I$(ZINCDIR) RCC += -I$(SRCDIR_extsrc) # With HTTPS support ifdef FOSSIL_ENABLE_SSL TCC += -L$(OPENSSLLIBDIR) -I$(OPENSSLINCDIR) RCC += -I$(OPENSSLINCDIR) endif # With Tcl support ifdef FOSSIL_ENABLE_TCL ifdef FOSSIL_TCL_SOURCE TCC += -L$(TCLSRCDIR)/win -I$(TCLSRCDIR)/generic -I$(TCLSRCDIR)/win RCC += -I$(TCLSRCDIR)/generic -I$(TCLSRCDIR)/win else TCC += -L$(TCLLIBDIR) -I$(TCLINCDIR) RCC += -I$(TCLINCDIR) endif endif # With MinGW command line handling workaround ifdef MINGW_IS_32BIT_ONLY TCC += -DBROKEN_MINGW_CMDLINE=1 RCC += -DBROKEN_MINGW_CMDLINE=1 endif # With HTTPS support |
| ︙ | ︙ | |||
374 375 376 377 378 379 380 | #### Extra arguments for linking the finished binary. Fossil needs # to link against the Z-Lib compression library. There are no # other mandatory dependencies. # LIB += -lmingwex | | < < | 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 | #### Extra arguments for linking the finished binary. Fossil needs # to link against the Z-Lib compression library. There are no # other mandatory dependencies. # LIB += -lmingwex #### zlib is required. # LIB += -lz #### These libraries MUST appear in the same order as they do for Tcl # or linking with it will not work (exact reason unknown). # ifdef FOSSIL_ENABLE_TCL ifdef FOSSIL_ENABLE_TCL_STUBS LIB += -lkernel32 -lws2_32 |
| ︙ | ︙ | |||
514 515 516 517 518 519 520 | $(SRCDIR)/merge.c \ $(SRCDIR)/merge3.c \ $(SRCDIR)/moderate.c \ $(SRCDIR)/name.c \ $(SRCDIR)/patch.c \ $(SRCDIR)/path.c \ $(SRCDIR)/piechart.c \ | < | 491 492 493 494 495 496 497 498 499 500 501 502 503 504 | $(SRCDIR)/merge.c \ $(SRCDIR)/merge3.c \ $(SRCDIR)/moderate.c \ $(SRCDIR)/name.c \ $(SRCDIR)/patch.c \ $(SRCDIR)/path.c \ $(SRCDIR)/piechart.c \ $(SRCDIR)/pikchrshow.c \ $(SRCDIR)/pivot.c \ $(SRCDIR)/popen.c \ $(SRCDIR)/pqueue.c \ $(SRCDIR)/printf.c \ $(SRCDIR)/publish.c \ $(SRCDIR)/purge.c \ |
| ︙ | ︙ | |||
621 622 623 624 625 626 627 | $(SRCDIR)/../skins/xekri/footer.txt \ $(SRCDIR)/../skins/xekri/header.txt \ $(SRCDIR)/accordion.js \ $(SRCDIR)/alerts/bflat2.wav \ $(SRCDIR)/alerts/bflat3.wav \ $(SRCDIR)/alerts/bloop.wav \ $(SRCDIR)/alerts/plunk.wav \ | < > | 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 | $(SRCDIR)/../skins/xekri/footer.txt \ $(SRCDIR)/../skins/xekri/header.txt \ $(SRCDIR)/accordion.js \ $(SRCDIR)/alerts/bflat2.wav \ $(SRCDIR)/alerts/bflat3.wav \ $(SRCDIR)/alerts/bloop.wav \ $(SRCDIR)/alerts/plunk.wav \ $(SRCDIR)/ci_edit.js \ $(SRCDIR)/copybtn.js \ $(SRCDIR)/default.css \ $(SRCDIR)/diff.js \ $(SRCDIR)/diff.tcl \ $(SRCDIR)/forum.js \ $(SRCDIR)/fossil.bootstrap.js \ $(SRCDIR)/fossil.confirmer.js \ $(SRCDIR)/fossil.copybutton.js \ $(SRCDIR)/fossil.diff.js \ $(SRCDIR)/fossil.dom.js \ $(SRCDIR)/fossil.fetch.js \ $(SRCDIR)/fossil.numbered-lines.js \ $(SRCDIR)/fossil.page.brlist.js \ $(SRCDIR)/fossil.page.chat.js \ $(SRCDIR)/fossil.page.fileedit.js \ $(SRCDIR)/fossil.page.forumpost.js \ $(SRCDIR)/fossil.page.pikchrshow.js \ $(SRCDIR)/fossil.page.whistory.js \ $(SRCDIR)/fossil.page.wikiedit.js \ $(SRCDIR)/fossil.pikchr.js \ $(SRCDIR)/fossil.popupwidget.js \ |
| ︙ | ︙ | |||
672 673 674 675 676 677 678 679 680 681 682 683 684 685 | $(SRCDIR)/sounds/a.wav \ $(SRCDIR)/sounds/b.wav \ $(SRCDIR)/sounds/c.wav \ $(SRCDIR)/sounds/d.wav \ $(SRCDIR)/sounds/e.wav \ $(SRCDIR)/sounds/f.wav \ $(SRCDIR)/style.admin_log.css \ $(SRCDIR)/style.fileedit.css \ $(SRCDIR)/style.wikiedit.css \ $(SRCDIR)/tree.js \ $(SRCDIR)/useredit.js \ $(SRCDIR)/wiki.wiki TRANS_SRC = \ | > | 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 | $(SRCDIR)/sounds/a.wav \ $(SRCDIR)/sounds/b.wav \ $(SRCDIR)/sounds/c.wav \ $(SRCDIR)/sounds/d.wav \ $(SRCDIR)/sounds/e.wav \ $(SRCDIR)/sounds/f.wav \ $(SRCDIR)/style.admin_log.css \ $(SRCDIR)/style.chat.css \ $(SRCDIR)/style.fileedit.css \ $(SRCDIR)/style.wikiedit.css \ $(SRCDIR)/tree.js \ $(SRCDIR)/useredit.js \ $(SRCDIR)/wiki.wiki TRANS_SRC = \ |
| ︙ | ︙ | |||
772 773 774 775 776 777 778 | $(OBJDIR)/merge_.c \ $(OBJDIR)/merge3_.c \ $(OBJDIR)/moderate_.c \ $(OBJDIR)/name_.c \ $(OBJDIR)/patch_.c \ $(OBJDIR)/path_.c \ $(OBJDIR)/piechart_.c \ | < | 749 750 751 752 753 754 755 756 757 758 759 760 761 762 | $(OBJDIR)/merge_.c \ $(OBJDIR)/merge3_.c \ $(OBJDIR)/moderate_.c \ $(OBJDIR)/name_.c \ $(OBJDIR)/patch_.c \ $(OBJDIR)/path_.c \ $(OBJDIR)/piechart_.c \ $(OBJDIR)/pikchrshow_.c \ $(OBJDIR)/pivot_.c \ $(OBJDIR)/popen_.c \ $(OBJDIR)/pqueue_.c \ $(OBJDIR)/printf_.c \ $(OBJDIR)/publish_.c \ $(OBJDIR)/purge_.c \ |
| ︙ | ︙ | |||
922 923 924 925 926 927 928 | $(OBJDIR)/merge.o \ $(OBJDIR)/merge3.o \ $(OBJDIR)/moderate.o \ $(OBJDIR)/name.o \ $(OBJDIR)/patch.o \ $(OBJDIR)/path.o \ $(OBJDIR)/piechart.o \ | < | 898 899 900 901 902 903 904 905 906 907 908 909 910 911 | $(OBJDIR)/merge.o \ $(OBJDIR)/merge3.o \ $(OBJDIR)/moderate.o \ $(OBJDIR)/name.o \ $(OBJDIR)/patch.o \ $(OBJDIR)/path.o \ $(OBJDIR)/piechart.o \ $(OBJDIR)/pikchrshow.o \ $(OBJDIR)/pivot.o \ $(OBJDIR)/popen.o \ $(OBJDIR)/pqueue.o \ $(OBJDIR)/printf.o \ $(OBJDIR)/publish.o \ $(OBJDIR)/purge.o \ |
| ︙ | ︙ | |||
1022 1023 1024 1025 1026 1027 1028 | RMDIR = rm -rf endif all: $(OBJDIR) $(APPNAME) $(OBJDIR)/fossil.o: $(SRCDIR)/../win/fossil.rc $(OBJDIR)/VERSION.h ifdef USE_WINDOWS | < < | 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 | RMDIR = rm -rf endif all: $(OBJDIR) $(APPNAME) $(OBJDIR)/fossil.o: $(SRCDIR)/../win/fossil.rc $(OBJDIR)/VERSION.h ifdef USE_WINDOWS $(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.rc) $(subst /,\,$(OBJDIR)) $(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.ico) $(subst /,\,$(OBJDIR)) $(CP) $(subst /,\,$(SRCDIR)\..\win\fossil.exe.manifest) $(subst /,\,$(OBJDIR)) else $(CP) $(SRCDIR)/../win/fossil.rc $(OBJDIR) $(CP) $(SRCDIR)/../win/fossil.ico $(OBJDIR) $(CP) $(SRCDIR)/../win/fossil.exe.manifest $(OBJDIR) endif $(RCC) $(OBJDIR)/fossil.rc -o $(OBJDIR)/fossil.o install: $(OBJDIR) $(APPNAME) |
| ︙ | ︙ | |||
1050 1051 1052 1053 1054 1055 1056 | $(OBJDIR): ifdef USE_WINDOWS $(MKDIR) $(subst /,\,$(OBJDIR)) else $(MKDIR) $(OBJDIR) endif | | | | | | | | | | | | | | | > > > > > < < < < < < < | | | | | | > | | | | > | | | | < < < < | 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 | $(OBJDIR): ifdef USE_WINDOWS $(MKDIR) $(subst /,\,$(OBJDIR)) else $(MKDIR) $(OBJDIR) endif $(TRANSLATE): $(SRCDIR_tools)/translate.c $(XBCC) -o $@ $(SRCDIR_tools)/translate.c $(MAKEHEADERS): $(SRCDIR_tools)/makeheaders.c $(XBCC) -o $@ $(SRCDIR_tools)/makeheaders.c $(MKINDEX): $(SRCDIR_tools)/mkindex.c $(XBCC) -o $@ $(SRCDIR_tools)/mkindex.c $(MKBUILTIN): $(SRCDIR_tools)/mkbuiltin.c $(XBCC) -o $@ $(SRCDIR_tools)/mkbuiltin.c $(MKVERSION): $(SRCDIR_tools)/mkversion.c $(XBCC) -o $@ $(SRCDIR_tools)/mkversion.c $(CODECHECK1): $(SRCDIR_tools)/codecheck1.c $(XBCC) -o $@ $(SRCDIR_tools)/codecheck1.c # WARNING. DANGER. Running the test suite modifies the repository the # build is done from, i.e. the checkout belongs to. Do not sync/push # the repository after running the tests. test: $(OBJDIR) $(APPNAME) $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) $(OBJDIR)/phony.h $(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@ $(OBJDIR)/phony.h: # Force rebuild of VERSION.h every time "make" is run # The USE_SYSTEM_SQLITE variable may be undefined, set to 0 or 1. # If it is set to 1, then there is no need to build or link # the sqlite3.o object. Instead, the system SQLite will be linked # using -lsqlite3. # # Closely related is SQLITE3_ORIGIN, with the same 0/1 mapping, # plus a value of 2 means that we are building a client-provided # sqlite3.c. SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o SQLITE3_OBJ.1 = # SQLITE3_OBJ.2 is set by the configure process SQLITE3_OBJ. = $(SQLITE3_OBJ.0) # The USE_SEE variable may be undefined, 0 or 1. If undefined or 0, # in-tree SQLite is used. If 1, then sqlite3-see.c (not part of the # source tree) is used and extra flags are provided to enable the # SQLite Encryption Extension. SQLITE3_SRC.0 = $(SRCDIR_extsrc)/sqlite3.c SQLITE3_SRC.1 = $(SRCDIR_extsrc)/sqlite3-see.c # SQLITE3_SRC.2 is set by top-level configure/makefile process. SQLITE3_SRC. = $(SRCDIR_extsrc)/sqlite3.c SQLITE3_SRC = $(SQLITE3_SRC.$(SQLITE3_ORIGIN)) SQLITE3_SHELL_SRC.0 = $(SRCDIR_extsrc)/shell.c SQLITE3_SHELL_SRC.1 = $(SRCDIR_extsrc)/shell-see.c # SQLITE3_SHELL_SRC.2 comes from the configure process SQLITE3_SHELL_SRC. = $(SRCDIR_extsrc)/shell.c SQLITE3_SHELL_SRC = $(SQLITE3_SHELL_SRC.$(SQLITE3_ORIGIN)) SEE_FLAGS.0 = SEE_FLAGS.1 = -DSQLITE_HAS_CODEC -DSQLITE_SHELL_DBKEY_PROC=fossil_key SEE_FLAGS. = SEE_FLAGS = $(SEE_FLAGS.$(USE_SEE)) EXTRAOBJ = \ $(SQLITE3_OBJ.$(SQLITE3_ORIGIN)) \ $(OBJDIR)/pikchr.o \ $(OBJDIR)/shell.o \ $(OBJDIR)/th.o \ $(OBJDIR)/th_lang.o \ $(OBJDIR)/th_tcl.o \ $(OBJDIR)/cson_amalgamation.o $(ZLIBDIR)/inffas86.o: $(TCC) -c -o $@ -DASMINF -I$(ZLIBDIR) -O3 $(ZLIBDIR)/contrib/inflate86/inffas86.c $(ZLIBDIR)/match.o: $(TCC) -c -o $@ -DASMV $(ZLIBDIR)/contrib/asm686/match.S zlib: $(ZLIBTARGETS) $(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) CC=$(PREFIX)$(TCCEXE) $(ZLIBCONFIG) -f win32/Makefile.gcc libz.a clean-zlib: $(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) CC=$(PREFIX)$(TCCEXE) -f win32/Makefile.gcc clean BLDTARGETS = zlib openssl: $(BLDTARGETS) cd $(OPENSSLLIBDIR);./Configure --cross-compile-prefix=$(PREFIX) $(SSLCONFIG) sed -i -e 's/^PERL=C:\\.*$$/PERL=perl.exe/i' $(OPENSSLLIBDIR)/Makefile $(MAKE) -C $(OPENSSLLIBDIR) PREFIX=$(PREFIX) CC=$(PREFIX)$(TCCEXE) build_libs clean-openssl: |
| ︙ | ︙ | |||
1195 1196 1197 1198 1199 1200 1201 | $(MKINDEX) $(TRANS_SRC) >$@ $(OBJDIR)/builtin_data.h: $(MKBUILTIN) $(EXTRA_FILES) $(MKBUILTIN) --prefix $(SRCDIR)/ $(EXTRA_FILES) >$@ $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/builtin_data.h $(MAKEHEADERS) $(OBJDIR)/VERSION.h $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h \ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | | | | 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 | $(MKINDEX) $(TRANS_SRC) >$@ $(OBJDIR)/builtin_data.h: $(MKBUILTIN) $(EXTRA_FILES) $(MKBUILTIN) --prefix $(SRCDIR)/ $(EXTRA_FILES) >$@ $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/builtin_data.h $(MAKEHEADERS) $(OBJDIR)/VERSION.h $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h \ $(OBJDIR)/ajax_.c:$(OBJDIR)/ajax.h \ $(OBJDIR)/alerts_.c:$(OBJDIR)/alerts.h \ $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h \ $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h \ $(OBJDIR)/backlink_.c:$(OBJDIR)/backlink.h \ $(OBJDIR)/backoffice_.c:$(OBJDIR)/backoffice.h \ $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h \ $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h \ $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h \ $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h \ $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h \ $(OBJDIR)/builtin_.c:$(OBJDIR)/builtin.h \ $(OBJDIR)/bundle_.c:$(OBJDIR)/bundle.h \ $(OBJDIR)/cache_.c:$(OBJDIR)/cache.h \ $(OBJDIR)/capabilities_.c:$(OBJDIR)/capabilities.h \ $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h \ $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h \ $(OBJDIR)/chat_.c:$(OBJDIR)/chat.h \ $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h \ $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h \ $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h \ $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h \ $(OBJDIR)/color_.c:$(OBJDIR)/color.h \ $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h \ $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h \ $(OBJDIR)/content_.c:$(OBJDIR)/content.h \ $(OBJDIR)/cookies_.c:$(OBJDIR)/cookies.h \ $(OBJDIR)/db_.c:$(OBJDIR)/db.h \ $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h \ $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h \ $(OBJDIR)/deltafunc_.c:$(OBJDIR)/deltafunc.h \ $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h \ $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h \ $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h \ $(OBJDIR)/dispatch_.c:$(OBJDIR)/dispatch.h \ $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \ $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \ $(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \ $(OBJDIR)/event_.c:$(OBJDIR)/event.h \ $(OBJDIR)/export_.c:$(OBJDIR)/export.h \ $(OBJDIR)/extcgi_.c:$(OBJDIR)/extcgi.h \ $(OBJDIR)/file_.c:$(OBJDIR)/file.h \ $(OBJDIR)/fileedit_.c:$(OBJDIR)/fileedit.h \ $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \ $(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \ $(OBJDIR)/forum_.c:$(OBJDIR)/forum.h \ $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ $(OBJDIR)/fuzz_.c:$(OBJDIR)/fuzz.h \ $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ $(OBJDIR)/hname_.c:$(OBJDIR)/hname.h \ $(OBJDIR)/hook_.c:$(OBJDIR)/hook.h \ $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \ $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \ $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h \ $(OBJDIR)/import_.c:$(OBJDIR)/import.h \ $(OBJDIR)/info_.c:$(OBJDIR)/info.h \ $(OBJDIR)/interwiki_.c:$(OBJDIR)/interwiki.h \ $(OBJDIR)/json_.c:$(OBJDIR)/json.h \ $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h \ $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h \ $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h \ $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h \ $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h \ $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h \ $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h \ $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h \ $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h \ $(OBJDIR)/json_status_.c:$(OBJDIR)/json_status.h \ $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h \ $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h \ $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h \ $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h \ $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h \ $(OBJDIR)/loadctrl_.c:$(OBJDIR)/loadctrl.h \ $(OBJDIR)/login_.c:$(OBJDIR)/login.h \ $(OBJDIR)/lookslike_.c:$(OBJDIR)/lookslike.h \ $(OBJDIR)/main_.c:$(OBJDIR)/main.h \ $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h \ $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h \ $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h \ $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \ $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \ $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \ $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \ $(OBJDIR)/name_.c:$(OBJDIR)/name.h \ $(OBJDIR)/patch_.c:$(OBJDIR)/patch.h \ $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ $(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \ $(OBJDIR)/pikchrshow_.c:$(OBJDIR)/pikchrshow.h \ $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ $(OBJDIR)/publish_.c:$(OBJDIR)/publish.h \ $(OBJDIR)/purge_.c:$(OBJDIR)/purge.h \ $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ $(OBJDIR)/repolist_.c:$(OBJDIR)/repolist.h \ $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ $(OBJDIR)/security_audit_.c:$(OBJDIR)/security_audit.h \ $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ $(OBJDIR)/setupuser_.c:$(OBJDIR)/setupuser.h \ $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ $(OBJDIR)/sha1hard_.c:$(OBJDIR)/sha1hard.h \ $(OBJDIR)/sha3_.c:$(OBJDIR)/sha3.h \ $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ $(OBJDIR)/smtp_.c:$(OBJDIR)/smtp.h \ $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \ $(OBJDIR)/statrep_.c:$(OBJDIR)/statrep.h \ $(OBJDIR)/style_.c:$(OBJDIR)/style.h \ $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h \ $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h \ $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h \ $(OBJDIR)/terminal_.c:$(OBJDIR)/terminal.h \ $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \ $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \ $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \ $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \ $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \ $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h \ $(OBJDIR)/unversioned_.c:$(OBJDIR)/unversioned.h \ $(OBJDIR)/update_.c:$(OBJDIR)/update.h \ $(OBJDIR)/url_.c:$(OBJDIR)/url.h \ $(OBJDIR)/user_.c:$(OBJDIR)/user.h \ $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h \ $(OBJDIR)/util_.c:$(OBJDIR)/util.h \ $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h \ $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h \ $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h \ $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h \ $(OBJDIR)/winfile_.c:$(OBJDIR)/winfile.h \ $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h \ $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h \ $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h \ $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h \ $(SRCDIR_extsrc)/pikchr.c:$(OBJDIR)/pikchr.h \ $(SRCDIR_extsrc)/sqlite3.h \ $(SRCDIR)/th.h \ $(OBJDIR)/VERSION.h echo Done >$(OBJDIR)/headers $(OBJDIR)/headers: Makefile Makefile: $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(TRANSLATE) |
| ︙ | ︙ | |||
2095 2096 2097 2098 2099 2100 2101 | $(TRANSLATE) $(SRCDIR)/piechart.c >$@ $(OBJDIR)/piechart.o: $(OBJDIR)/piechart_.c $(OBJDIR)/piechart.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/piechart.o -c $(OBJDIR)/piechart_.c $(OBJDIR)/piechart.h: $(OBJDIR)/headers | < < < < < < < < | 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 | $(TRANSLATE) $(SRCDIR)/piechart.c >$@ $(OBJDIR)/piechart.o: $(OBJDIR)/piechart_.c $(OBJDIR)/piechart.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/piechart.o -c $(OBJDIR)/piechart_.c $(OBJDIR)/piechart.h: $(OBJDIR)/headers $(OBJDIR)/pikchrshow_.c: $(SRCDIR)/pikchrshow.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/pikchrshow.c >$@ $(OBJDIR)/pikchrshow.o: $(OBJDIR)/pikchrshow_.c $(OBJDIR)/pikchrshow.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/pikchrshow.o -c $(OBJDIR)/pikchrshow_.c $(OBJDIR)/pikchrshow.h: $(OBJDIR)/headers |
| ︙ | ︙ | |||
2603 2604 2605 2606 2607 2608 2609 |
-DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname \
-DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc \
-Daccess=file_access \
-Dsystem=fossil_system \
-Dgetenv=fossil_getenv \
-Dfopen=fossil_fopen
| < < < < | | | | | | 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 |
-DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname \
-DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc \
-Daccess=file_access \
-Dsystem=fossil_system \
-Dgetenv=fossil_getenv \
-Dfopen=fossil_fopen
$(OBJDIR)/sqlite3.o: $(SQLITE3_SRC) $(SRCDIR)/../win/Makefile.mingw.mistachkin
$(XTCC) $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $(SEE_FLAGS) \
-c $(SQLITE3_SRC) -o $@
$(OBJDIR)/cson_amalgamation.o: $(SRCDIR_extsrc)/cson_amalgamation.c
$(XTCC) -c $(SRCDIR_extsrc)/cson_amalgamation.c -o $@
$(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/jsos_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_status.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
$(OBJDIR)/shell.o: $(SQLITE3_SHELL_SRC) $(SRCDIR_extsrc)/sqlite3.h $(SRCDIR)/../win/Makefile.mingw.mistachkin
$(XTCC) $(SHELL_OPTIONS) $(SHELL_CFLAGS) $(SEE_FLAGS) -c $(SQLITE3_SHELL_SRC) -o $@
$(OBJDIR)/th.o: $(SRCDIR)/th.c
$(XTCC) -c $(SRCDIR)/th.c -o $@
$(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c
$(XTCC) -c $(SRCDIR)/th_lang.c -o $@
$(OBJDIR)/th_tcl.o: $(SRCDIR)/th_tcl.c
$(XTCC) -c $(SRCDIR)/th_tcl.c -o $@
$(OBJDIR)/pikchr.o: $(SRCDIR_extsrc)/pikchr.c
$(XTCC) -c $(SRCDIR_extsrc)/pikchr.c -o $@
|
Changes to win/Makefile.msc.
1 2 | # ############################################################################## | | > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # ############################################################################## # WARNING: DO NOT EDIT, AUTOMATICALLY GENERATED FILE (SEE "tools/makemake.tcl") ############################################################################## # # # This file is automatically generated. Instead of editing this # file, edit "makemake.tcl" then run "tclsh makemake.tcl" # to regenerate this file. # B = .. SRCDIR = $(B)\src SRCDIR_extsrc = $(B)\extsrc SRCDIR_tools = $(B)\tools T = . OBJDIR = $(T) OX = $(OBJDIR) O = .obj E = .exe P = .pdb DBGOPTS = /Od |
| ︙ | ︙ | |||
74 75 76 77 78 79 80 | !endif # Enable the JSON API? !ifndef FOSSIL_ENABLE_JSON FOSSIL_ENABLE_JSON = 0 !endif | < < < < < | 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | !endif # Enable the JSON API? !ifndef FOSSIL_ENABLE_JSON FOSSIL_ENABLE_JSON = 0 !endif # Enable OpenSSL support? !ifndef FOSSIL_ENABLE_SSL FOSSIL_ENABLE_SSL = 0 !endif # Enable the Tcl integration subsystem? !ifndef FOSSIL_ENABLE_TCL |
| ︙ | ︙ | |||
162 163 164 165 166 167 168 | !if $(FOSSIL_DYNAMIC_BUILD)!=0 ZLIB = zdll.lib !else ZLIB = zlib.lib !endif | | < < | 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | !if $(FOSSIL_DYNAMIC_BUILD)!=0 ZLIB = zdll.lib !else ZLIB = zlib.lib !endif INCL = /I. /I"$(OX)" /I"$(SRCDIR)" /I"$(SRCDIR_extsrc)" /I"$(B)\win\include" INCL = $(INCL) /I"$(ZINCDIR)" !if $(FOSSIL_ENABLE_SSL)!=0 INCL = $(INCL) /I"$(SSLINCDIR)" !endif !if $(FOSSIL_ENABLE_TCL)!=0 INCL = $(INCL) /I"$(TCLINCDIR)" |
| ︙ | ︙ | |||
244 245 246 247 248 249 250 | LIBDIR = !if $(FOSSIL_DYNAMIC_BUILD)!=0 TCC = $(TCC) /DFOSSIL_DYNAMIC_BUILD=1 RCC = $(RCC) /DFOSSIL_DYNAMIC_BUILD=1 !endif | < < < < < < < | 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 | LIBDIR = !if $(FOSSIL_DYNAMIC_BUILD)!=0 TCC = $(TCC) /DFOSSIL_DYNAMIC_BUILD=1 RCC = $(RCC) /DFOSSIL_DYNAMIC_BUILD=1 !endif LIBS = $(LIBS) $(ZLIB) LIBDIR = $(LIBDIR) /LIBPATH:"$(ZLIBDIR)" !if $(FOSSIL_ENABLE_JSON)!=0 TCC = $(TCC) /DFOSSIL_ENABLE_JSON=1 RCC = $(RCC) /DFOSSIL_ENABLE_JSON=1 !endif !if $(FOSSIL_ENABLE_SSL)!=0 |
| ︙ | ︙ | |||
309 310 311 312 313 314 315 |
/DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
/DSQLITE_OMIT_DECLTYPE \
/DSQLITE_OMIT_DEPRECATED \
/DSQLITE_OMIT_PROGRESS_CALLBACK \
/DSQLITE_OMIT_SHARED_CACHE \
/DSQLITE_OMIT_LOAD_EXTENSION \
/DSQLITE_MAX_EXPR_DEPTH=0 \
| < < < < < < < < < < | 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 |
/DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
/DSQLITE_OMIT_DECLTYPE \
/DSQLITE_OMIT_DEPRECATED \
/DSQLITE_OMIT_PROGRESS_CALLBACK \
/DSQLITE_OMIT_SHARED_CACHE \
/DSQLITE_OMIT_LOAD_EXTENSION \
/DSQLITE_MAX_EXPR_DEPTH=0 \
/DSQLITE_ENABLE_LOCKING_STYLE=0 \
/DSQLITE_DEFAULT_FILE_FORMAT=4 \
/DSQLITE_ENABLE_EXPLAIN_COMMENTS \
/DSQLITE_ENABLE_FTS4 \
/DSQLITE_ENABLE_DBSTAT_VTAB \
/DSQLITE_ENABLE_FTS5 \
/DSQLITE_ENABLE_STMTVTAB \
/DSQLITE_HAVE_ZLIB \
/DSQLITE_ENABLE_DBPAGE_VTAB \
/DSQLITE_TRUSTED_SCHEMA=0 \
/DSQLITE_WIN32_NO_ANSI
SHELL_OPTIONS = /DNDEBUG=1 \
/DSQLITE_DQS=0 \
/DSQLITE_THREADSAFE=0 \
/DSQLITE_DEFAULT_MEMSTATUS=0 \
/DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \
/DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
/DSQLITE_OMIT_DECLTYPE \
/DSQLITE_OMIT_DEPRECATED \
/DSQLITE_OMIT_PROGRESS_CALLBACK \
/DSQLITE_OMIT_SHARED_CACHE \
/DSQLITE_OMIT_LOAD_EXTENSION \
/DSQLITE_MAX_EXPR_DEPTH=0 \
/DSQLITE_ENABLE_LOCKING_STYLE=0 \
/DSQLITE_DEFAULT_FILE_FORMAT=4 \
/DSQLITE_ENABLE_EXPLAIN_COMMENTS \
/DSQLITE_ENABLE_FTS4 \
/DSQLITE_ENABLE_DBSTAT_VTAB \
/DSQLITE_ENABLE_FTS5 \
/DSQLITE_ENABLE_STMTVTAB \
/DSQLITE_HAVE_ZLIB \
/DSQLITE_ENABLE_DBPAGE_VTAB \
/DSQLITE_TRUSTED_SCHEMA=0 \
/Dmain=sqlite3_shell \
/DSQLITE_SHELL_IS_UTF8=1 \
/DSQLITE_OMIT_LOAD_EXTENSION=1 \
/DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
/DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname \
/DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc \
/Daccess=file_access \
/Dsystem=fossil_system \
/Dgetenv=fossil_getenv \
/Dfopen=fossil_fopen
SRC = "$(OX)\add_.c" \
"$(OX)\ajax_.c" \
"$(OX)\alerts_.c" \
"$(OX)\allrepo_.c" \
"$(OX)\attach_.c" \
"$(OX)\backlink_.c" \
"$(OX)\backoffice_.c" \
|
| ︙ | ︙ | |||
457 458 459 460 461 462 463 |
"$(OX)\merge_.c" \
"$(OX)\merge3_.c" \
"$(OX)\moderate_.c" \
"$(OX)\name_.c" \
"$(OX)\patch_.c" \
"$(OX)\path_.c" \
"$(OX)\piechart_.c" \
| < | 435 436 437 438 439 440 441 442 443 444 445 446 447 448 |
"$(OX)\merge_.c" \
"$(OX)\merge3_.c" \
"$(OX)\moderate_.c" \
"$(OX)\name_.c" \
"$(OX)\patch_.c" \
"$(OX)\path_.c" \
"$(OX)\piechart_.c" \
"$(OX)\pikchrshow_.c" \
"$(OX)\pivot_.c" \
"$(OX)\popen_.c" \
"$(OX)\pqueue_.c" \
"$(OX)\printf_.c" \
"$(OX)\publish_.c" \
"$(OX)\purge_.c" \
|
| ︙ | ︙ | |||
775 776 777 778 779 780 781 |
"$(OX)\wiki$O" \
"$(OX)\wikiformat$O" \
"$(OX)\winfile$O" \
"$(OX)\winhttp$O" \
"$(OX)\xfer$O" \
"$(OX)\xfersetup$O" \
"$(OX)\zip$O" \
| < < < | 752 753 754 755 756 757 758 759 760 761 762 763 764 765 |
"$(OX)\wiki$O" \
"$(OX)\wikiformat$O" \
"$(OX)\winfile$O" \
"$(OX)\winhttp$O" \
"$(OX)\xfer$O" \
"$(OX)\xfersetup$O" \
"$(OX)\zip$O" \
"$(OX)\fossil.res"
!ifndef BASEAPPNAME
BASEAPPNAME = fossil
!endif
|
| ︙ | ︙ | |||
833 834 835 836 837 838 839 | @pushd "$(SSLDIR)" && $(MAKE) && popd !endif clean-openssl: @pushd "$(SSLDIR)" && $(MAKE) clean && popd !endif | < < | 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 | @pushd "$(SSLDIR)" && $(MAKE) && popd !endif clean-openssl: @pushd "$(SSLDIR)" && $(MAKE) clean && popd !endif !if $(FOSSIL_BUILD_ZLIB)!=0 APPTARGETS = $(APPTARGETS) zlib !endif !if $(FOSSIL_ENABLE_SSL)!=0 !if $(FOSSIL_BUILD_SSL)!=0 APPTARGETS = $(APPTARGETS) openssl !endif !endif |
| ︙ | ︙ | |||
1006 1007 1008 1009 1010 1011 1012 | echo "$(OX)\wiki.obj" >> $@ echo "$(OX)\wikiformat.obj" >> $@ echo "$(OX)\winfile.obj" >> $@ echo "$(OX)\winhttp.obj" >> $@ echo "$(OX)\xfer.obj" >> $@ echo "$(OX)\xfersetup.obj" >> $@ echo "$(OX)\zip.obj" >> $@ | < < < | | | | | | | | | | | | | 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 | echo "$(OX)\wiki.obj" >> $@ echo "$(OX)\wikiformat.obj" >> $@ echo "$(OX)\winfile.obj" >> $@ echo "$(OX)\winhttp.obj" >> $@ echo "$(OX)\xfer.obj" >> $@ echo "$(OX)\xfersetup.obj" >> $@ echo "$(OX)\zip.obj" >> $@ echo $(LIBS) >> $@ "$(OBJDIR)\translate$E": "$(SRCDIR_tools)\translate.c" $(BCC) /Fe$@ /Fo$(@D)\ /Fd$(@D)\ $** "$(OBJDIR)\makeheaders$E": "$(SRCDIR_tools)\makeheaders.c" $(BCC) /Fe$@ /Fo$(@D)\ /Fd$(@D)\ $** "$(OBJDIR)\mkindex$E": "$(SRCDIR_tools)\mkindex.c" $(BCC) /Fe$@ /Fo$(@D)\ /Fd$(@D)\ $** "$(OBJDIR)\mkbuiltin$E": "$(SRCDIR_tools)\mkbuiltin.c" $(BCC) /Fe$@ /Fo$(@D)\ /Fd$(@D)\ $** "$(OBJDIR)\mkversion$E": "$(SRCDIR_tools)\mkversion.c" $(BCC) /Fe$@ /Fo$(@D)\ /Fd$(@D)\ $** "$(OBJDIR)\codecheck1$E": "$(SRCDIR_tools)\codecheck1.c" $(BCC) /Fe$@ /Fo$(@D)\ /Fd$(@D)\ $** !if $(USE_SEE)!=0 SEE_FLAGS = /DSQLITE_HAS_CODEC=1 /DSQLITE_SHELL_DBKEY_PROC=fossil_key SQLITE3_SHELL_SRC = $(SRCDIR)\shell-see.c SQLITE3_SRC = $(SRCDIR_extsrc)\sqlite3-see.c !else SEE_FLAGS = SQLITE3_SHELL_SRC = $(SRCDIR_extsrc)\shell.c SQLITE3_SRC = $(SRCDIR_extsrc)\sqlite3.c !endif "$(OX)\shell$O" : "$(SQLITE3_SHELL_SRC)" "$(B)\win\Makefile.msc" $(TCC) /Fo$@ /Fd$(@D)\ $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) $(SEE_FLAGS) -c "$(SQLITE3_SHELL_SRC)" "$(OX)\sqlite3$O" : "$(SQLITE3_SRC)" "$(B)\win\Makefile.msc" $(TCC) /Fo$@ /Fd$(@D)\ -c $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $(SEE_FLAGS) "$(SQLITE3_SRC)" "$(OX)\th$O" : "$(SRCDIR)\th.c" $(TCC) /Fo$@ /Fd$(@D)\ -c $** "$(OX)\th_lang$O" : "$(SRCDIR)\th_lang.c" $(TCC) /Fo$@ /Fd$(@D)\ -c $** "$(OX)\th_tcl$O" : "$(SRCDIR)\th_tcl.c" $(TCC) /Fo$@ /Fd$(@D)\ -c $** "$(OX)\pikchr$O" : "$(SRCDIR_extsrc)\pikchr.c" $(TCC) /Fo$@ /Fd$(@D)\ -c $** "$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" "$(B)\phony.h" "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" > $@ "$(B)\phony.h" : rem Force rebuild of VERSION.h whenever nmake is run "$(OX)\cson_amalgamation$O" : "$(SRCDIR_extsrc)\cson_amalgamation.c" $(TCC) /Fo$@ /Fd$(@D)\ -c $** "$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC) $** > $@ "$(OX)\builtin_data.h": "$(OBJDIR)\mkbuiltin$E" "$(OX)\builtin_data.reslist" "$(OBJDIR)\mkbuiltin$E" --prefix "$(SRCDIR)/" --reslist "$(OX)\builtin_data.reslist" > $@ |
| ︙ | ︙ | |||
1788 1789 1790 1791 1792 1793 1794 | "$(OX)\piechart$O" : "$(OX)\piechart_.c" "$(OX)\piechart.h" $(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\piechart_.c" "$(OX)\piechart_.c" : "$(SRCDIR)\piechart.c" "$(OBJDIR)\translate$E" $** > $@ | < < < < < < | 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 | "$(OX)\piechart$O" : "$(OX)\piechart_.c" "$(OX)\piechart.h" $(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\piechart_.c" "$(OX)\piechart_.c" : "$(SRCDIR)\piechart.c" "$(OBJDIR)\translate$E" $** > $@ "$(OX)\pikchrshow$O" : "$(OX)\pikchrshow_.c" "$(OX)\pikchrshow.h" $(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\pikchrshow_.c" "$(OX)\pikchrshow_.c" : "$(SRCDIR)\pikchrshow.c" "$(OBJDIR)\translate$E" $** > $@ "$(OX)\pivot$O" : "$(OX)\pivot_.c" "$(OX)\pivot.h" |
| ︙ | ︙ | |||
2215 2216 2217 2218 2219 2220 2221 | "$(OX)\merge_.c":"$(OX)\merge.h" \ "$(OX)\merge3_.c":"$(OX)\merge3.h" \ "$(OX)\moderate_.c":"$(OX)\moderate.h" \ "$(OX)\name_.c":"$(OX)\name.h" \ "$(OX)\patch_.c":"$(OX)\patch.h" \ "$(OX)\path_.c":"$(OX)\path.h" \ "$(OX)\piechart_.c":"$(OX)\piechart.h" \ | < | 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 | "$(OX)\merge_.c":"$(OX)\merge.h" \ "$(OX)\merge3_.c":"$(OX)\merge3.h" \ "$(OX)\moderate_.c":"$(OX)\moderate.h" \ "$(OX)\name_.c":"$(OX)\name.h" \ "$(OX)\patch_.c":"$(OX)\patch.h" \ "$(OX)\path_.c":"$(OX)\path.h" \ "$(OX)\piechart_.c":"$(OX)\piechart.h" \ "$(OX)\pikchrshow_.c":"$(OX)\pikchrshow.h" \ "$(OX)\pivot_.c":"$(OX)\pivot.h" \ "$(OX)\popen_.c":"$(OX)\popen.h" \ "$(OX)\pqueue_.c":"$(OX)\pqueue.h" \ "$(OX)\printf_.c":"$(OX)\printf.h" \ "$(OX)\publish_.c":"$(OX)\publish.h" \ "$(OX)\purge_.c":"$(OX)\purge.h" \ |
| ︙ | ︙ | |||
2270 2271 2272 2273 2274 2275 2276 | "$(OX)\wiki_.c":"$(OX)\wiki.h" \ "$(OX)\wikiformat_.c":"$(OX)\wikiformat.h" \ "$(OX)\winfile_.c":"$(OX)\winfile.h" \ "$(OX)\winhttp_.c":"$(OX)\winhttp.h" \ "$(OX)\xfer_.c":"$(OX)\xfer.h" \ "$(OX)\xfersetup_.c":"$(OX)\xfersetup.h" \ "$(OX)\zip_.c":"$(OX)\zip.h" \ | | | | 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 | "$(OX)\wiki_.c":"$(OX)\wiki.h" \ "$(OX)\wikiformat_.c":"$(OX)\wikiformat.h" \ "$(OX)\winfile_.c":"$(OX)\winfile.h" \ "$(OX)\winhttp_.c":"$(OX)\winhttp.h" \ "$(OX)\xfer_.c":"$(OX)\xfer.h" \ "$(OX)\xfersetup_.c":"$(OX)\xfersetup.h" \ "$(OX)\zip_.c":"$(OX)\zip.h" \ "$(SRCDIR_extsrc)\sqlite3.h" \ "$(SRCDIR)\th.h" \ "$(OX)\VERSION.h" \ "$(SRCDIR_extsrc)\cson_amalgamation.h" @copy /Y nul: $@ |
Changes to win/buildmsvc.bat.
| ︙ | ︙ | |||
44 45 46 47 48 49 50 | REM IF DEFINED VSVARS32 IF EXIST "%VSVARS32%" ( %_AECHO% Build environment batch file manually overridden to "%VSVARS32%"... GOTO skip_detectVisualStudio ) REM | | | | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | REM IF DEFINED VSVARS32 IF EXIST "%VSVARS32%" ( %_AECHO% Build environment batch file manually overridden to "%VSVARS32%"... GOTO skip_detectVisualStudio ) REM REM Visual Studio 2017 / 2019 / 2022 REM CALL :fn_TryUseVsWhereExe IF NOT DEFINED VSWHEREINSTALLDIR GOTO skip_detectVisualStudio2017 SET VSVARS32=%VSWHEREINSTALLDIR%\Common7\Tools\VsDevCmd.bat IF EXIST "%VSVARS32%" ( %_AECHO% Using Visual Studio 2017 / 2019 / 2022... GOTO skip_detectVisualStudio ) :skip_detectVisualStudio2017 REM REM Visual Studio 2015 REM |
| ︙ | ︙ | |||
374 375 376 377 378 379 380 |
SET VSWHEREINSTALLDIR=C:\Program Files\Microsoft Visual Studio\2017\Community
GOTO skip_setVsWhereInstallDir
)
FOR /F "delims=" %%D IN ('%VS_WHEREIS_CMD%') DO (SET VSWHEREINSTALLDIR=%%D)
:skip_setVsWhereInstallDir
%_VECHO% VsWhereInstallDir = '%VSWHEREINSTALLDIR%'
IF NOT DEFINED VSWHEREINSTALLDIR (
| | | | 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 |
SET VSWHEREINSTALLDIR=C:\Program Files\Microsoft Visual Studio\2017\Community
GOTO skip_setVsWhereInstallDir
)
FOR /F "delims=" %%D IN ('%VS_WHEREIS_CMD%') DO (SET VSWHEREINSTALLDIR=%%D)
:skip_setVsWhereInstallDir
%_VECHO% VsWhereInstallDir = '%VSWHEREINSTALLDIR%'
IF NOT DEFINED VSWHEREINSTALLDIR (
%_AECHO% Visual Studio 2017 / 2019 / 2022 is not installed.
GOTO :EOF
)
%_AECHO% Visual Studio 2017 / 2019 / 2022 is installed.
GOTO :EOF
:usage
ECHO.
ECHO Usage: %~nx0 [...]
ECHO.
GOTO errors
|
| ︙ | ︙ |
Changes to win/fossil.rc.
| ︙ | ︙ | |||
28 29 30 31 32 33 34 | # define VS_FF_NONE 0x00000000L #endif /* !defined(VS_FF_NONE) */ #include "VERSION.h" #define _RC_COMPILE_ #include "config.h" #include "sqlite3.h" | < < < < < < < < < < | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | # define VS_FF_NONE 0x00000000L #endif /* !defined(VS_FF_NONE) */ #include "VERSION.h" #define _RC_COMPILE_ #include "config.h" #include "sqlite3.h" #include "zlib.h" #if defined(FOSSIL_ENABLE_SSL) #include "openssl/opensslv.h" #endif /* defined(FOSSIL_ENABLE_SSL) */ #if defined(FOSSIL_ENABLE_TCL) #include "tcl.h" |
| ︙ | ︙ | |||
105 106 107 108 109 110 111 |
VALUE "CompilerName", COMPILER_NAME "\0"
VALUE "SQLiteVersion", "SQLite " SQLITE_VERSION " " SQLITE_SOURCE_ID "\0"
#if defined(FOSSIL_DYNAMIC_BUILD)
VALUE "DynamicBuild", "Yes\0"
#else
VALUE "DynamicBuild", "No\0"
#endif
| < < < < | 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
VALUE "CompilerName", COMPILER_NAME "\0"
VALUE "SQLiteVersion", "SQLite " SQLITE_VERSION " " SQLITE_SOURCE_ID "\0"
#if defined(FOSSIL_DYNAMIC_BUILD)
VALUE "DynamicBuild", "Yes\0"
#else
VALUE "DynamicBuild", "No\0"
#endif
VALUE "ZlibVersion", "zlib " ZLIB_VERSION "\0"
#if defined(BROKEN_MINGW_CMDLINE)
VALUE "CommandLineIsUnicode", "No\0"
#else
VALUE "CommandLineIsUnicode", "Yes\0"
#endif /* defined(BROKEN_MINGW_CMDLINE) */
#if defined(FOSSIL_ENABLE_SSL)
VALUE "SslEnabled", "Yes, " OPENSSL_VERSION_TEXT "\0"
|
| ︙ | ︙ |
Changes to www/adding_code.wiki.
| ︙ | ︙ | |||
43 44 45 46 47 48 49 | write code. <h2>3.0 Adding New Source Code Files</h2> New source code files are added in the "src/" subdirectory of the Fossil source tree. Suppose one wants to add a new source code file named "xyzzy.c". The first step is to add this file to the various makefiles. | | | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
write code.
<h2>3.0 Adding New Source Code Files</h2>
New source code files are added in the "src/" subdirectory of the Fossil
source tree. Suppose one wants to add a new source code file named
"xyzzy.c". The first step is to add this file to the various makefiles.
Do so by editing the file tools/makemake.tcl and adding "xyzzy" (without
the final ".c") to the list of source modules at the top of that script.
Save the result and then run the makemake.tcl script using a TCL
interpreter. The command to run the makemake.tcl script is:
<b>tclsh makemake.tcl</b>
The working directory must be src/ when the command above is run.
|
| ︙ | ︙ | |||
89 90 91 92 93 94 95 | exceptions to this rule. Don't worry about those exceptions. The files you write will require this #include line.) The "#if INTERFACE ... #endif" section is optional and is only needed if there are structure definitions or typedefs or macros that need to be used by other source code files. The makeheaders preprocessor uses definitions in the INTERFACE section to help it generate header | | | 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | exceptions to this rule. Don't worry about those exceptions. The files you write will require this #include line.) The "#if INTERFACE ... #endif" section is optional and is only needed if there are structure definitions or typedefs or macros that need to be used by other source code files. The makeheaders preprocessor uses definitions in the INTERFACE section to help it generate header files. See [../tools/makeheaders.html | makeheaders.html] for additional information. After creating a template file such as shown above, and after updating the makefiles, you should be able to recompile Fossil and have it include your new source file, even before you source file contains any code. It is recommended that you try this. |
| ︙ | ︙ |
Changes to www/bugtheory.wiki.
| ︙ | ︙ | |||
110 111 112 113 114 115 116 | to repopulate the table using the new column names. Note that the TICKET table schema and content is part of the local state of a repository and is not shared with other repositories during a sync, push, or pull. Each repository also defines scripts used to generate web pages for creating new tickets, viewing existing tickets, and modifying an existing ticket. These scripts consist of HTML with an embedded | | | < < | 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | to repopulate the table using the new column names. Note that the TICKET table schema and content is part of the local state of a repository and is not shared with other repositories during a sync, push, or pull. Each repository also defines scripts used to generate web pages for creating new tickets, viewing existing tickets, and modifying an existing ticket. These scripts consist of HTML with an embedded scripts written a Tcl-like language called "[./th1.md|TH1]". Every new fossil repository is created with default scripts. Administrators wishing to customize their ticket entry, viewing, and editing screens should modify the default scripts to suit their needs. These screen generator scripts are part of the local state of a repository and are not shared with other repositories during a sync, push, or pull. <i>To be continued...</i> |
Changes to www/changes.wiki.
1 2 3 4 5 6 7 8 9 10 |
<title>Change Log</title>
<h2 id='v2_17'>Changes for version 2.17 (2021-10-09)</h2>
* Major improvements to the "diff" subsystem, including: <ul>
<li> Added new [/help?cmd=diff|formatting options]: --by, -b, --webpage, --json, --tcl.
<li> Partial-line matching for unified diffs
<li> Better partial-line matching for side-by-side diffs
<li> Buttons on web-based diffs to show more context
<li> Performance improvements
</ul>
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
<title>Change Log</title>
<h2 id='v2_18'>Changes for version 2.18 (pending)</h2>
* Added support for [./ssl-server.md|SSL/TLS server mode] for commands
like "[/help?cmd=server|fossil server]" and "[/help?cmd=http|fossil http]"
* Added the --share-links option to [/help?cmd=sync|fossil sync] and
[/help?cmd=pull|fossil pull]. Enhance the
[/doc/trunk/www/sync.wiki|sync protocol] so that it is able to support
sharing of links to other clones.
* Added the --transport-command option to [/help?cmd=sync|fossil sync]
and similar.
* [/help?cmd=/chat|The /chat page] input options have been reworked
again for better cross-browser portability.
* Add new setting "[/help?cmd=large-file-size|large-file-size]". If the size
of any file in a commit exceeds this size, a warning is issued.
* When sending a [/help?cmd=/chat|/chat] message fails, it is no longer
immediately lost and sending may optionally be retried.
* [/help?cmd=/chat|/chat] can now optionally embed attachments of certain
types directly into message bodies via an iframe.
* The new [/help?cmd=cherry-pick|cherry-pick command] is an alias for
[/help?cmd=merge|merge --cherrypick].
* Promote the test-detach command into the [/help?cmd=detach|detach command].
* For "fossil pull" with the --from-parent-project option, if not URL is
specified used the last URL specified for the --from-parent-project.
* Add options --project-name and --project-desc to the
"[/help?cmd=init|fossil init]" command.
* Query parameter "year=YYYY" is now accepted by [/help?cmd=/timeline|/timeline].
* Add the "--as FILENAME" option to the "[/help?cmd=chat|fossil chat send]"
command.
<h2 id='v2_17'>Changes for version 2.17 (2021-10-09)</h2>
* Major improvements to the "diff" subsystem, including: <ul>
<li> Added new [/help?cmd=diff|formatting options]: --by, -b, --webpage, --json, --tcl.
<li> Partial-line matching for unified diffs
<li> Better partial-line matching for side-by-side diffs
<li> Buttons on web-based diffs to show more context
<li> Performance improvements
</ul>
|
| ︙ | ︙ |
Changes to www/chat.md.
| ︙ | ︙ | |||
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | who performed the deletion, not the author of the deleted comment). That can potentially lead to odd corner cases where a user shows up in the list but has no messages which are currently visible because they were deleted, or an admin user who has not posted anything but deleted a message. That is a known minor cosmetic-only bug with a resolution of "will not fix." ## Implementation Details *You do not need to understand how Fossil chat works in order to use it. But many developers prefer to know how their tools work. This section is provided for the benefit of those curious developers.* The [/chat](/help?cmd=/chat) webpage downloads a small amount of HTML and a small amount of javascript to run the chat session. The javascript uses XMLHttpRequest (XHR) to download chat content, post new content, or delete historical messages. The following web interfaces are used by the XHR: | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | | | | | | | | | | | | | 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
who performed the deletion, not the author of the deleted
comment). That can potentially lead to odd corner cases where a user
shows up in the list but has no messages which are currently visible
because they were deleted, or an admin user who has not posted
anything but deleted a message. That is a known minor cosmetic-only
bug with a resolution of "will not fix."
### <a id="cli"></a> The `fossil chat` Command
Type [fossil chat](/help?cmd=chat) from within any open check-out
to bring up a chatroom for the project that is in that checkout.
The new chat window will attempt to connect to the default sync
target for that check-out (the server whose URL is shown by the
[fossil remote](/help?cmd=remote) command).
### <a id="robots"></a> Chat Messages From Robots
The [fossil chat send](/help?cmd=chat) can be used by project-specific
robots to send notifications to the chatroom. For example, on the
[SQLite project](https://sqlite.org/) (for which the Fossil chatroom
feature, and indeed all of Fossil, was invented) there are long-running
fuzz servers that sometimes run across obscure problems. Whenever this
happens, a message is sent to the SQLite developers chatroom altering
them to the problem.
The recommended way to allow robots to send chat messages is to create
a new user on the server for each robot. Give each such robot account
the "C" privilege only. That means that the robot user account will be
able to send chat messages, but not do anything else. Then, in the
program or script that runs the robot, when it wants to send a chat
message, have it run a command like this:
> ~~~~
fossil chat send --remote https://robot:PASSWORD@project.org/fossil \
--message 'MESSAGE TEXT' --file file-to-attach.txt
~~~~
Substitute the appropriate project URL, robot account
name and password, message text and file attachment, of course.
## Implementation Details
*You do not need to understand how Fossil chat works in order to use it.
But many developers prefer to know how their tools work.
This section is provided for the benefit of those curious developers.*
The [/chat](/help?cmd=/chat) webpage downloads a small amount of HTML
and a small amount of javascript to run the chat session. The
javascript uses XMLHttpRequest (XHR) to download chat content, post
new content, or delete historical messages. The following web
interfaces are used by the XHR:
* [/chat-poll](/help?name=/chat-poll) →
Downloads chat content as JSON.
Chat messages are numbered sequentially.
The client tells the server the largest chat message it currently
holds, and the server sends back subsequent messages. If there
are no subsequent messages, the /chat-poll page blocks until new
messages are available.
* [/chat-send](/help?name=/chat-send) →
Sends a new chat message to the server.
* [/chat-delete](/help?name=/chat-delete) →
Deletes a chat message.
Fossil chat uses the venerable "hanging GET" or
"[long polling](wikipedia:/wiki/Push_technology#Long_polling)"
technique to recieve asynchronous notification of new messages.
This is done because long polling works well with CGI and SCGI,
which are the usual mechanisms for setting up a Fossil server.
More advanced notification techniques such as
[Server-sent events](wikipedia:/wiki/Server-sent_events) and especially
[WebSockets](wikipedia:/wiki/WebSocket) might seem more appropriate for
a chat system, but those technologies are not compatible with CGI.
Downloading of posted files and images uses a separate, non-XHR interface:
* [/chat-download](/help?name=/chat-download) →
Fetches the file content associated with a post (one file per
post, maximum). In the UI, this is accessed via links to uploaded
files and via inlined image tags.
Chat messages are stored on the server-side in the CHAT table of
the repository.
> ~~~
CREATE TABLE repository.chat(
msgid INTEGER PRIMARY KEY AUTOINCREMENT,
mtime JULIANDAY, -- Time for this entry - Julianday Zulu
lmtime TEXT, -- Client YYYY-MM-DDZHH:MM:SS when message originally sent
xfrom TEXT, -- Login of the sender
xmsg TEXT, -- Raw, unformatted text of the message
fname TEXT, -- Filename of the uploaded file, or NULL
fmime TEXT, -- MIMEType of the upload file, or NULL
mdel INT, -- msgid of another message to delete
file BLOB -- Text of the uploaded file, or NULL
);
~~~
The CHAT table is not cross-linked with any other tables in the repository
schema. An administrator can "DROP TABLE chat;" at any time, without
harm (apart from deleting all chat history, of course). The CHAT table
is dropped when running [fossil scrub --verily](/help?cmd=scrub).
|
| ︙ | ︙ |
Changes to www/concepts.wiki.
| ︙ | ︙ | |||
13 14 15 16 17 18 19 | to setup and operate. This document is intended as a quick introduction to the concepts behind Fossil. See also: | | | | | | | | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
to setup and operate.
This document is intended as a quick introduction to the concepts
behind Fossil.
See also:
* [./glossary.md | Glossary]
* [./quickstart.wiki | Quick start guide]
<h2>2.0 Composition Of A Project</h2>
<verbatim type="pikchr float-right">
R1: cylinder "Remote" "Repository" fill 0xadd8e6 rad 70%
R2: cylinder same "Remote" "Repository" at 2.5*R1.wid right of R1
spline <-> from R1.e to 0.6<R1.se,R2.sw> then to 0.4<R1.ne,R2.nw> then to R2.w
text "HTTPS" at .5<R1.ne,R2.nw>
R3: cylinder same "Local" "Repository" fill 0x90ee90 \
at dist(R1.e,R2.w) below .5<R1,R2>
spline <-> from .5<R1.s,R1.se> to 0.6<R1.s,R3.w> to 0.5<R1.se,R3.n> to .5<R3.nw,R3.n> \
"HTTPS" above behind R1
spline <-> from R2.sw to .6<R2.sw,R3.n> to .5<R2.s,R3.e> to R3.ne "HTTPS" ljust
T1: line from 1.0cm heading 200 from R3.sw go 2.2cm heading 150 then 2.2cm west close \
fill 0xffff00 "Local" below "Source Tree" below
T2: line from 1.0cm heading 160 from R3.se same "Local" below "Source Tree" below
line <-> from R3.sw to T1.start
line <-> from R3.se to T2.start
</verbatim>
|
| ︙ | ︙ | |||
89 90 91 92 93 94 95 | remote repository into a local repository. Or one can do a "sync" which is a shortcut for doing both a push and a pull at the same time. Fossil also has the concept of "cloning". A "clone" is like a "pull", except that instead of beginning with an existing local repository, a clone begins with nothing and creates a new local repository that is a duplicate of a remote repository. | | > | 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | remote repository into a local repository. Or one can do a "sync" which is a shortcut for doing both a push and a pull at the same time. Fossil also has the concept of "cloning". A "clone" is like a "pull", except that instead of beginning with an existing local repository, a clone begins with nothing and creates a new local repository that is a duplicate of a remote repository. Communication between repositories is normally via HTTPS. (SSH is also supported, as is unencrypted HTTP.) Remote repositories are identified by URL. You can also point a web browser at a repository and get human-readable status, history, and tracking information about the project. <h3 id="artifacts">2.1 Identification Of Artifacts</h3> A particular version of a particular file is called an "artifact". Each |
| ︙ | ︙ |
Changes to www/contribute.wiki.
| ︙ | ︙ | |||
25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<h2>2.0 Submitting Patches</h2>
Suggested changes or bug fixes can be submitted by creating a patch
against the current source tree:
<tt>fossil diff -i > my-change.patch</tt>
Post patches to
[https://fossil-scm.org/forum | the forum] or email them to
<a href="mailto:drh@sqlite.org">drh@sqlite.org</a>. Be sure to
describe in detail what the patch does and which version of Fossil
it is written against. It's best to make patches against tip-of-trunk
rather than against past releases.
| > > > > | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
<h2>2.0 Submitting Patches</h2>
Suggested changes or bug fixes can be submitted by creating a patch
against the current source tree:
<tt>fossil diff -i > my-change.patch</tt>
Alternatively, you can create a binary patch:
<tt>fossil patch create my-change.db</tt>
Post patches to
[https://fossil-scm.org/forum | the forum] or email them to
<a href="mailto:drh@sqlite.org">drh@sqlite.org</a>. Be sure to
describe in detail what the patch does and which version of Fossil
it is written against. It's best to make patches against tip-of-trunk
rather than against past releases.
|
| ︙ | ︙ |
Changes to www/env-opts.md.
| ︙ | ︙ | |||
227 228 229 230 231 232 233 234 235 236 237 238 239 240 | `REQUEST_METHOD`: If defined, included in error log messages. `REQUEST_URI`: If defined, included in error log messages. `SCRIPT_NAME`: If defined, included in error log messages. `SSH_CONNECTION`: Informs CGI processing if the remote client is SSH. `SQLITE_FORCE_PROXY_LOCKING`: From `sqlite3.c`, 1 means force always use proxy, 0 means never use proxy, and undefined means use proxy for non-local files only. `SQLITE_TMPDIR`: Names the temporary file location for SQLite. When set, this will be used instead of `TMPDIR`. | > > > | 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 | `REQUEST_METHOD`: If defined, included in error log messages. `REQUEST_URI`: If defined, included in error log messages. `SCRIPT_NAME`: If defined, included in error log messages. `SSH_CONNECTION`: Informs CGI processing if the remote client is SSH. `SSL_CERT_FILE`, `SSL_CERT_DIR`: Override the [`ssl-ca-location`] (/help?cmd=ssl-ca-location) setting. `SQLITE_FORCE_PROXY_LOCKING`: From `sqlite3.c`, 1 means force always use proxy, 0 means never use proxy, and undefined means use proxy for non-local files only. `SQLITE_TMPDIR`: Names the temporary file location for SQLite. When set, this will be used instead of `TMPDIR`. |
| ︙ | ︙ | |||
306 307 308 309 310 311 312 313 314 315 316 317 318 319 | environment. See the comment above the implementation of [`json_getenv`][json.c] for some further discussion. [json.c]: /artifact/6df1d80dece8968b?ln=277,290 ### Comment Editor The editor used to edit a check-in or stash comment is named by the local or global setting `editor`. If neither is set, then the environment variables `VISUAL`, and `EDITOR` are checked in that order. On Windows, if no editor is named, then Notepad is used. Note that the | > > > > > > | 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 | environment. See the comment above the implementation of [`json_getenv`][json.c] for some further discussion. [json.c]: /artifact/6df1d80dece8968b?ln=277,290 ### CGI Server Extensions The [CGI Server Extensions](/doc/trunk/www/serverext.wiki) feature passes parameters to the CGI program using environment variables, as listed in the [CGI Inputs](/doc/trunk/www/serverext.wiki#cgi-inputs) section. ### Comment Editor The editor used to edit a check-in or stash comment is named by the local or global setting `editor`. If neither is set, then the environment variables `VISUAL`, and `EDITOR` are checked in that order. On Windows, if no editor is named, then Notepad is used. Note that the |
| ︙ | ︙ |
Changes to www/fileformat.wiki.
| ︙ | ︙ | |||
72 73 74 75 76 77 78 | <li> [#attachment | Attachments] </li> <li> [#event | TechNotes] </li> <li> [#forum | Forum Posts] </li> </ul> These eight structural artifact types are described in subsections below. | | | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | <li> [#attachment | Attachments] </li> <li> [#event | TechNotes] </li> <li> [#forum | Forum Posts] </li> </ul> These eight structural artifact types are described in subsections below. Structural artifacts are UTF-8 text. The artifact may be PGP clearsigned. After removal of the PGP clearsign header and suffix (if any) a structural artifact consists of one or more "cards" separated by a single newline (ASCII: 0x0a) character. Each card begins with a single character "card type". Zero or more arguments may follow the card type. All arguments are separated from each other and from the card-type character by a single space character. There is no surplus white space between arguments |
| ︙ | ︙ |
Changes to www/fossil-v-git.wiki.
| ︙ | ︙ | |||
401 402 403 404 405 406 407 | allows an anonymous developer to rebase and push specific locally-named private branches, so that a Git repo clone often isn't really a clone at all: it may have an arbitrary number of differences relative to the repository it originally cloned from. Git encourages siloed development. Select work in a developer's local repository may remain private indefinitely. | < < < < < < < < < < < | 401 402 403 404 405 406 407 408 409 410 411 412 413 414 | allows an anonymous developer to rebase and push specific locally-named private branches, so that a Git repo clone often isn't really a clone at all: it may have an arbitrary number of differences relative to the repository it originally cloned from. Git encourages siloed development. Select work in a developer's local repository may remain private indefinitely. All of this is exactly what one wants when doing bazaar-style development. Fossil's normal mode of operation differs on every one of these points, with the specific designed-in goal of promoting SQLite's cathedral development model: |
| ︙ | ︙ | |||
498 499 500 501 502 503 504 505 506 507 508 509 510 511 | Where Git encourages siloed development, Fossil fights against it. Fossil places a lot of emphasis on synchronizing everyone's work and on reporting on the state of the project and the work of its developers, so that everyone — especially the project leader — can maintain a better mental picture of what is happening, leading to better situational awareness. You can think about this difference in terms of [https://en.wikipedia.org/wiki/Feedback | feedback loop size], which we know from the mathematics of [https://en.wikipedia.org/wiki/Control_theory | control theory] to directly affect the speed at which any system can safely make changes. The larger the feedback loop, the slower the whole system must run in | > > > > > > > > > > > | 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 | Where Git encourages siloed development, Fossil fights against it. Fossil places a lot of emphasis on synchronizing everyone's work and on reporting on the state of the project and the work of its developers, so that everyone — especially the project leader — can maintain a better mental picture of what is happening, leading to better situational awareness. By contrast, "…[https://guides.github.com/activities/forking|forking is at the core of social coding at GitHub]". As of January 2022, [https://github.com/search?q=is:public|Github hosts 47 million distinct software projects], most of which were created by forking a previously-existing project. Since this is [https://evansdata.com/reports/viewRelease.php?reportID=9 | roughly twice the number of developers in the world], it beggars belief that most of these forks are still under active development. The vast bulk of these must be abandoned one-off efforts. This is part of the nature of bazaar style development. You can think about this difference in terms of [https://en.wikipedia.org/wiki/Feedback | feedback loop size], which we know from the mathematics of [https://en.wikipedia.org/wiki/Control_theory | control theory] to directly affect the speed at which any system can safely make changes. The larger the feedback loop, the slower the whole system must run in |
| ︙ | ︙ | |||
522 523 524 525 526 527 528 | <h4 id="scale">2.5.2 Scale</h4> The Linux kernel has a far bigger developer community than that of SQLite: there are thousands and thousands of contributors to Linux, most of whom do not know each others names. These thousands are responsible | | | | | > | | | > > > > | 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 | <h4 id="scale">2.5.2 Scale</h4> The Linux kernel has a far bigger developer community than that of SQLite: there are thousands and thousands of contributors to Linux, most of whom do not know each others names. These thousands are responsible for producing roughly 89× more code than is in SQLite. (10.7 [https://en.wikipedia.org/wiki/Source_lines_of_code|MLOC] vs. 0.12 MLOC according to [https://dwheeler.com/sloccount/|SLOCCount].) The Linux kernel and its development process were already uncommonly large back in 2005 when Git was designed, specifically to support the consequences of having such a large set of developers working on such a large code base. 95% of the code in SQLite comes from just four programmers, and 64% of it is from the lead developer alone. The SQLite developers know each other well and interact daily. Fossil was designed for this development model. When choosing your DVCS, we think you should ask yourself whether the scale of your software configuration management problems is closer to those Linus Torvalds designed Git to cope with or whether your work's scale is closer to that of SQLite, for which D. Richard Hipp designed Fossil. An [https://en.wikipedia.org/wiki/Impact_wrench|automotive air impact wrench] running at 8000 RPM driving an M8 socket-cap bolt at 16 cm/s is not the best way to hang a picture on the living room wall. Fossil works well for projects several times the size of SQLite, [https://core.tcl-lang.org/tcl/ | such as Tcl], with a repository over twice the size and with many more core committers. <h4 id="branches">2.5.3 Individual Branches vs. The Entire Change History</h4> Both Fossil and Git store history as a directed acyclic graph (DAG) of changes, but Git tends to focus more on individual branches of the DAG, whereas Fossil puts more emphasis on the entire DAG. |
| ︙ | ︙ |
Changes to www/gitusers.md.
| ︙ | ︙ | |||
128 129 130 131 132 133 134 | We think this is a more sensible command design than `git pull` vs `git checkout`. ([…vs `git checkout` vs `git checkout`!][gcokoan]) [fpull]: /help?cmd=pull [gpull]: https://git-scm.com/docs/git-pull [gcokoan]: https://stevelosh.com/blog/2013/04/git-koans/#s2-one-thing-well | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | We think this is a more sensible command design than `git pull` vs `git checkout`. ([…vs `git checkout` vs `git checkout`!][gcokoan]) [fpull]: /help?cmd=pull [gpull]: https://git-scm.com/docs/git-pull [gcokoan]: https://stevelosh.com/blog/2013/04/git-koans/#s2-one-thing-well #### <a id="close" name="dotfile"></a> Closing a Check-Out The [`fossil close`][close] command dissociates a check-out directory from the Fossil repository database, nondestructively inverting [`fossil open`][open]. (Contrast [its closest inverse](#worktree), `git worktree remove`, which *is* destructive in Git!) This Fossil command does not |
| ︙ | ︙ | |||
322 323 324 325 326 327 328 | you’re following [the directory scheme exemplified above](#rname). That said, it does emphasize an earlier point: Fossil doesn’t care where you put the repo DB file or what you name it. [clone]: /help?cmd=clone [close]: /help?cmd=close | | | 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 | you’re following [the directory scheme exemplified above](#rname). That said, it does emphasize an earlier point: Fossil doesn’t care where you put the repo DB file or what you name it. [clone]: /help?cmd=clone [close]: /help?cmd=close [gloss]: ./glossary.md [open]: /help?cmd=open [set]: /help?cmd=setting [server]: /help?cmd=server [stash]: /help?cmd=stash [undo]: /help?cmd=undo |
| ︙ | ︙ | |||
484 485 486 487 488 489 490 | in Fossil, because the indexes always let us find our way back into the hash tree. ## <a id="slcom"></a> Summary Line Convention In Commit Comments The Git convention of a [length-limited summary line][lsl] at the start | | | < < | > | > > | < > | < > > > | < | 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 | in Fossil, because the indexes always let us find our way back into the hash tree. ## <a id="slcom"></a> Summary Line Convention In Commit Comments The Git convention of a [length-limited summary line][lsl] at the start of commit comments is not enforced or obeyed by default in Fossil. However, there is a setting under Admin → Timeline → “Truncate comment at first blank line (Git-style)” to change this for `/timeline` displays. Alternately, you could enable the “Allow block-markup in timeline” setting under Admin → Timeline, then apply [local skin customizations][cskin] to put that first comment in in bold or whatever suits. Because this isn’t a typical Fossil convention, you’re likely to find other odd differences between it and Git-based infrastructure. For instance, Vim doesn’t ship with syntax support for Fossil commit messages if you set `EDITOR=vim` in your shell environment, so you won’t get over-limit highlighting for first-line text beyond the 50th character and such, because it doesn’t recognize Fossil commit messages and apply similar rules as to Git commit messages. [cskin]: ./customskin.md [lsl]: https://chris.beams.io/posts/git-commit/#limit-50 <a id="staging"></a> |
| ︙ | ︙ |
Added www/glossary.md.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 |
# Glossary
There are several terms-of-art in Fossil that have specific meanings
which are either not immediately obvious to an outsider or which have
technical associations that can lead someone to either use the terms
incorrectly or to get the wrong idea from someone using those terms
correctly. We hope to teach users how to properly “speak Fossil” with
this glossary.
Each definition is followed by a bullet-point list of clarifying
details. These are not part of the definition itself.
## <a id="project"></a>Project
A collection of one or more computer files that serve some conceptually
unified purpose, which purpose changes and evolves over time, with the
history of that project being a valuable record.
* We qualify the Fossil definition of this common word like this to
set aside cases where a zip file or tarball would suffice. If you
can pack your project up into such an archive once and be done with
it, Fossil is overkill.
And yet that is often just the beginning, since there is often a
need for something to be changed, so now you have “version 2” of the
archive file. If you can foresee yourself creating versioned archive
files for your project, then you probably should be using Fossil for
it instead, then using Fossil’s [zip] or [tarball] command to
automatically produce archives of the latest version rather than
manually produce and track versions of the archive. The web version
of these commands ([`/zip`][zw] and [`/tarball`][tw]) are
particularly useful for public distribution of the latest version of
a project’s files.
* Fossil was designed to host the SQLite software project, which is
comprised of source code, makefiles, scripts, documentation files,
and so forth. Fossil is also useful for many other purposes, such as
a fiction book project where each chapter is held in a separate file
and assembled into a finished whole deliverable.
* We speak of projects being more than one file because even though
Fossil can be made to track the history of a single file, it is far
more often the case that when you get to something of a scale
sufficient to be called a “project,” there is more than one
version-tracked file involved, if not at the start, then certainly
by the end of the project.
We used the example of a fiction book above, with one chapter per
file. That implies scripts for combining those chapters into the
finished book and converting that into PDF and ePub outputs, each of
which benefit from being version-tracked.
You could instead use a Word DOCX file for the entire book project,
with these implicit scripts replaced by Word menu commands. Fossil
will happily track that single file’s evolution for you, though
there are [good reasons](./image-format-vs-repo-size.md) to *not* do
that.
Let us say you choose to solve the primary problems brought up in
that document by using a format like AsciiDoc instead. You could
still use a single file for the entire book’s prose content, but
even then you’re still likely to want separate files for a style
sheet, a script to convert the HTML to PDF and ePub in a reliably
repeatable fashion, cover artwork files, instructions to the
printing house, and so forth.
* Fossil requires that all the files for a project be collected into a
single directory hierarchy, owned by a single user with full rights
to modify those files. Fossil is not a good choice for managing a
project that has files scattered hither and yon all over the file
system, nor of collections of files with complicated ownership and
access rights.
A good mental model for a Fossil project is a versioned zip file or
tarball. If you cannot easily conceive of creating or extracting
such an archive for your project, Fossil is probably not a good fit.
As a counterexample, a project made of an operating system
installation’s configuration file set is not a good use of Fossil,
because you’ll have all of your OS’s *other* files intermixed.
Worse, Fossil doesn’t track OS permissions, so even if you were to
try to use Fossil as a system deployment tool by archiving versions
of the OS configuration files and then unpacking them on a new
system, the extracted project files would have read/write access by
the user who did the extraction, which probably isn’t want you were
wanting.
Even with these problems aside, do you really want a `.fslckout`
SQLite database at the root of your filesystem? Are you prepared for
the consequences of saying `fossil clean --verily` on such a system?
We believe Fossil is a poor choice for a whole-system configuration
backup utility.
And as a counter-counterexample, a project made of your user’s [Vim]
configuration is a much better use of Fossil, because it’s all held
within `~/.vim`, and your user has full rights to that subdirectory.
[tarball]: /help?cmd=tarball
[tw]: /help?cmd=/tarball
[Vim]: https://www.vim.org/
[zip]: /help?cmd=zip
[zw]: /help?cmd=/zip
## Repository <a id="repository" name="repo"></a>
A single file that contains all historical versions of all files in a
project, which can be [cloned] to other machines and
[synchronized][sync] with them. Jargon: repo.
* A Fossil repo is similar to an archive file in that it is a single
file that stores compressed versions of one or more files. Files can be
extracted from the repo, and new files can be added to the repo,
but a Fossil repo has other capabilities
above and beyond what simple archive formats can do.
* Fossil does not care what you name your repository files, though
we do suggest “`.fossil`” as a standard extension. There is
only one place in Fossil where that convention is required, being the
[`fossil server DIRECTORY`][svrcmd] command, since it serves up
`*.fossil` files from `DIRECTORY`. If you don’t use that feature,
you can name your repo files anything you like.
* Cloned and synced repos redundantly store all available information
about that project, so if any one repo is lost, all of the cloned
historical content of the project as of the last sync is preserved
in each surviving repo.
Each user generally clones the project repository down to each
computer they use to participate in that project, and there is
usually at least one central host for the project as well, so there
is usually plenty of redundancy in any given Fossil-based project.
That said, a Fossil repository clone is a backup only in a limited
sense, because some information can’t be cloned, some doesn’t sync
by default, and some data is neither clonable nor syncable. We cover
these limitations and the workarounds for them in a separate
document, [Backing Up a Remote Fossil Repository][backup].
* Rather than be a backup, a Fossil repository clone is a
communication method for coordinating work on the project among
multiple machines and users: local work done against one repository
is communicated up to its parent repository on the next sync, and
work done on other repositories that were previously synced up to
that parent get pulled down into the local repo clone.
This bidirectional sync is automatic and on by default in Fossil.
You can [disable it][asdis], or you can [push] or [pull]
unidirectionally, if you wish.
The Fossil philosophy is that all project information resides in
each clone of the repository. In the ideal world, this would occur
instantly and automatically, but in actual use, Fossil falls
somewhat short of that mark. Some limitations are simply
technological: a given clone may be temporarily out of communication
with its parent repository, network delays exist, and so forth.
Fossil is [an AP mode system][CAP]. (This is sometimes called
“eventual consistency.”) Other cases come down to administrative
necessity, as covered in [the backup doc][backup].
* Fossil doesn’t require that you have redundant clones. Whether you
do or not is a local decision based on usage needs, communication
requirements, desire for backups, and so forth.
* Fossil doesn’t care where the repositories are stored, but we
recommend keeping them all in a single subdirectory such as
"`~/fossils`" or "`%USERPROFILE%\Fossils`". A flat set of files
suffices for simple purposes, but you may have use for something
more complicated. This author uses a scheme like the following on
mobile machines that shuttle between home and the office:
``` pikchr toggle indent
scale=0.8
box "~/museum/" fit
move right 0.1
line right dotted
move right 0.05
box invis "where one stores valuable fossils" ljust
arrow down 50% from first box.s then right 50%
box "work/" fit
move right 0.1
line dotted
move right 0.05
box invis "projects from $DAYJOB" ljust
arrow down 50% from 2nd vertex of previous arrow then right 50%
box "home/" fit
move right 0.1
line dotted right until even with previous line.end
move right 0.05
box invis "personal at-home projects" ljust
arrow down 50% from 2nd vertex of previous arrow then right 50%
box "other/" fit
move right 0.1
line dotted right until even with previous line.end
move right 0.05
box invis "clones of Fossil itself, SQLite, etc." ljust
```
[asdis]: /help?cmd=autosync
[backup]: ./backup.md
[CAP]: ./cap-theorem.md
[cloned]: /help?cmd=clone
[pull]: /help?cmd=pull
[push]: /help?cmd=push
[svrcmd]: /help?cmd=server
[sync]: /help?cmd=sync
## Check-in <a id="check-in" name="ci"></a>
A version of the project’s files that have been committed to the
repository. It is a snapshot of the project at an instant in time, as
seen from a single [check-out’s](#co) perspective. Synonyms: version,
snapshot, revision, commit. Sometimes styled “`CHECKIN`”, especially in
command documentation where any [valid checkin name][ciname] can be
used.
* The long list of synonyms is confusing to new Fossil users,
particularly the noun sense of the word “commit,” but it’s easy
enough to internalize the concepts. [Committing][commit] creates a
*commit.* It may also be said to create a checked-in *version* of a
particular *revision* of the project’s files, thus creating an
immutable *snapshot* of the project’s state at the time of the
commit. Fossil users find each of these different words for the
same concept useful for expressive purposes among ourselves, but to
Fossil proper, they all mean the same thing.
You will find all of these synonyms used in the Fossil documentation.
Some day we may settle on a single term, but it doesn’t seem likely.
* Check-ins are immutable.
* Check-ins exist only inside the repository. Contrast a
[check-out](#co).
* Check-ins may have [one or more names][ciname], but only the SHA
hash is globally unique, across all time; we call it the check-in’s
canonical name. The other names are either imprecise, contextual, or
change their meaning over time and across [repositories](#repo).
[ciname]: ./checkin_names.wiki
## Check-out <a id="check-out" name="co"></a>
A set of files extracted from a [repository](#repo) that represent a
particular [check-in](#ci) of the [project](#project).
* Unlike a check-in, a check-out is mutable. It may start out as a
version of a particular check-in extracted from the repository, but
the user is then free to make modifications to the checked-out
files. Once those changes are formally [committed][commit], they
become a new immutable check-in, derived from its parent check-in.
* You can switch from one check-in to another within a check-out
directory by passing those names to [the `fossil update`
command][update].
* Check-outs relate to repositories in a one-to-many fashion: it is
common to have a single repo clone on a machine but to have it
[open] in [multiple working directories][mwd]. Check-out directories
are associated with the repos they were created from by settings
stored in the check-out drectory. This is in the `.fslckout` file on
POSIX type systems, but for historical compatibility reasons, it’s
called `_FOSSIL_` by native Windows builds of Fossil.
(Contrast the Cygwin and WSL Fossil binaries, which use POSIX file
naming rules.)
* In the same way that one cannot extract files from a zip archive
without having a copy of that zip file, one cannot make check-outs
without access to the repository file or a clone thereof.
* Because a Fossil repository is a SQLite database file, the same
rules for avoiding data corruption apply to it. In particular, it is
[nearly a hard requirement][h2cflp] that the repository clone be on
the same machine as the one where you make check-outs and the
subsequent check-ins.
That said, the relative locations of the repo and the check-out
within the local file system are arbitrary. The repository may be
located inside the folder holding the check-out, but it certainly
does not have to be, and it usually is not. As an example, [the
Fossil plugin for Visual Studio Code][fpvsc] defaults to storing the
repo clone within the project directory as a file called `.fsl`, but
this is because VSCode’s version control features assume it’s being
used with Git, where the repository is the `.git` subdirectory
contents. With Fossil, [different check-out workflows][cwork] are
preferred.
[commit]: /help?cmd=commit
[cwork]: ./ckout-workflows.md
[h2cflp]: https://www.sqlite.org/howtocorrupt.html#_file_locking_problems
[fpvsc]: https://marketplace.visualstudio.com/items?itemName=koog1000.fossil
[open]: /help?cmd=open
[mwd]: ./ckout-workflows.md#mcw
[update]: /help?cmd=update
<div style="height:50em" id="this-space-intentionally-left-blank"></div>
|
Changes to www/interwiki.md.
| ︙ | ︙ | |||
109 110 111 112 113 114 115 | The intermap is stored in the CONFIG table of the repository database, in entries with names of the form "<tt>interwiki:</tt><i>Tag</i>". The value for each such entry is a JSON string that defines the base URL and extensions for Hash and Wiki links. ## See Also | < | | | 109 110 111 112 113 114 115 116 117 | The intermap is stored in the CONFIG table of the repository database, in entries with names of the form "<tt>interwiki:</tt><i>Tag</i>". The value for each such entry is a JSON string that defines the base URL and extensions for Hash and Wiki links. ## See Also 1. [](https://www.mediawiki.org/wiki/Manual:Interwiki) 2. [](https://duckduckgo.com/?q=interwiki+links&ia=web) |
Changes to www/makefile.wiki.
| ︙ | ︙ | |||
21 22 23 24 25 26 27 | source tree. The src/ subdirectory contains all code, including the code for the separate preprocessor programs. Each preprocessor program is a separate C program implemented in a single file of C source code. The three preprocessor programs are: | | | | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | source tree. The src/ subdirectory contains all code, including the code for the separate preprocessor programs. Each preprocessor program is a separate C program implemented in a single file of C source code. The three preprocessor programs are: 1. [/file/tools/mkindex.c | mkindex.c] 2. [/file/tools/translate.c | translate.c] 3. [/file/tools/makeheaders.c | makeheaders.c] Fossil uses [http://www.sqlite.org/ | SQLite] for on-disk storage. The SQLite implementation is contained in three source code files that do not participate in the preprocessing steps. These three files that implement SQLite are: 4. sqlite3.c |
| ︙ | ︙ | |||
79 80 81 82 83 84 85 | CSS scripts, headers, and footers used to implement built-in skins. New resources files are added to the "extra_files" variable in [/file/src/makemake.tcl | makemake.tcl]. The src/ subdirectory also contains documentation about the makeheaders preprocessor program: | | | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | CSS scripts, headers, and footers used to implement built-in skins. New resources files are added to the "extra_files" variable in [/file/src/makemake.tcl | makemake.tcl]. The src/ subdirectory also contains documentation about the makeheaders preprocessor program: 13. [../tools/makeheaders.html | makeheaders.html] Click on the link to read this documentation. In addition there is a [http://www.tcl-lang.org/ | Tcl] script used to build the various makefiles: 14. makemake.tcl Running this Tcl script will automatically regenerate all makefiles. |
| ︙ | ︙ | |||
224 225 226 227 228 229 230 | <h2>4.3 The makeheaders preprocessor</h2> For each C source module "src.c", there is an automatically generated header module "src.h" that contains all of the datatype and procedure declarations needed by the source module. These header files are generated automatically by the makeheaders program. The sources to makeheaders are contained in a single file "makeheaders.c". Additional documentation | | | 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 | <h2>4.3 The makeheaders preprocessor</h2> For each C source module "src.c", there is an automatically generated header module "src.h" that contains all of the datatype and procedure declarations needed by the source module. These header files are generated automatically by the makeheaders program. The sources to makeheaders are contained in a single file "makeheaders.c". Additional documentation on makeheaders can be found in [../tools/makeheaders.html | tools/makeheaders.html]. The makeheaders program is run once. It scans all inputs source files and generates header files for each one. Note that the sqlite3.c and shell.c source files are not scanned by makeheaders. Makeheaders only runs over "ordinary" source files, not the exceptional source files. However, makeheaders also uses some extra header files as input. The general format is like this: |
| ︙ | ︙ | |||
290 291 292 293 294 295 296 | Fossil needs to be linked against [http://www.zlib.net | zlib]. If the HTTPS option is enabled, then it will also need to link against the appropriate SSL implementation. And, of course, Fossil needs to link against the standard C library. No other libraries or external dependences are used. | < < < | 290 291 292 293 294 295 296 297 298 299 300 301 302 303 | Fossil needs to be linked against [http://www.zlib.net | zlib]. If the HTTPS option is enabled, then it will also need to link against the appropriate SSL implementation. And, of course, Fossil needs to link against the standard C library. No other libraries or external dependences are used. <h1>7.0 Debugging</h1> Debug mode is controlled via FOSSIL_DEBUG preprocessor macro which could be set explicitly at the make command for the target platform. However, in practice it is instead recommended to add a respective configure option for the target platform and then perform a clean build. This way the |
| ︙ | ︙ |
Changes to www/mkindex.tcl.
| ︙ | ︙ | |||
60 61 62 63 64 65 66 67 |
fiveminutes.wiki {Up and Running in 5 Minutes as a Single User}
forum.wiki {Fossil Forums}
foss-cklist.wiki {Checklist For Successful Open-Source Projects}
fossil-from-msvc.wiki {Integrating Fossil in the Microsoft Express 2010 IDE}
fossil-is-not-relational.md {Introduction to the (Non-relational) Fossil Data Model}
fossil_prompt.wiki {Fossilized Bash Prompt}
fossil-v-git.wiki {Fossil Versus Git}
globs.md {File Name Glob Patterns}
| > | | 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
fiveminutes.wiki {Up and Running in 5 Minutes as a Single User}
forum.wiki {Fossil Forums}
foss-cklist.wiki {Checklist For Successful Open-Source Projects}
fossil-from-msvc.wiki {Integrating Fossil in the Microsoft Express 2010 IDE}
fossil-is-not-relational.md {Introduction to the (Non-relational) Fossil Data Model}
fossil_prompt.wiki {Fossilized Bash Prompt}
fossil-v-git.wiki {Fossil Versus Git}
gitusers.md {Git to Fossil Translation Guide}
globs.md {File Name Glob Patterns}
glossary.md {Glossary}
grep.md {Fossil grep vs POSIX grep}
hacker-howto.wiki {Hacker How-To}
hacker-howto.wiki {Fossil Developers Guide}
hashes.md {Hashes: Fossil Artifact Identification}
hashpolicy.wiki {Hash Policy: Choosing Between SHA1 and SHA3-256}
/help {Lists of Commands and Webpages}
hints.wiki {Fossil Tips And Usage Hints}
|
| ︙ | ︙ | |||
104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
serverext.wiki {Adding Extensions To A Fossil Server Using CGI Scripts}
settings.wiki {Fossil Settings}
/sitemap {Site Map}
shunning.wiki {Shunning: Deleting Content From Fossil}
stats.wiki {Performance Statistics}
style.wiki {Source Code Style Guidelines}
ssl.wiki {Using SSL with Fossil}
sync.wiki {The Fossil Sync Protocol}
tech_overview.wiki {A Technical Overview Of The Design And Implementation
Of Fossil}
tech_overview.wiki {SQLite Databases Used By Fossil}
th1.md {The TH1 Scripting Language}
theory1.wiki {Thoughts On The Design Of The Fossil DVCS}
tickets.wiki {The Fossil Ticket System}
| > | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
serverext.wiki {Adding Extensions To A Fossil Server Using CGI Scripts}
settings.wiki {Fossil Settings}
/sitemap {Site Map}
shunning.wiki {Shunning: Deleting Content From Fossil}
stats.wiki {Performance Statistics}
style.wiki {Source Code Style Guidelines}
ssl.wiki {Using SSL with Fossil}
ssl-server.md {SSL/TLS Server Mode}
sync.wiki {The Fossil Sync Protocol}
tech_overview.wiki {A Technical Overview Of The Design And Implementation
Of Fossil}
tech_overview.wiki {SQLite Databases Used By Fossil}
th1.md {The TH1 Scripting Language}
theory1.wiki {Thoughts On The Design Of The Fossil DVCS}
tickets.wiki {The Fossil Ticket System}
|
| ︙ | ︙ |
Changes to www/newrepo.wiki.
| ︙ | ︙ | |||
110 111 112 113 114 115 116 | a branch or experimental code. Making your repository available over the web is trivial to do. We assume you have some web space where you can store your fossil file and run a CGI script. If not, then this option is not for you. If you do, then here's how... | | | 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | a branch or experimental code. Making your repository available over the web is trivial to do. We assume you have some web space where you can store your fossil file and run a CGI script. If not, then this option is not for you. If you do, then here's how... Copy the fossil repository file to your web server (it doesn't matter where, really). In your <tt>cgi-bin</tt> (or equivalent) directory, create a file which looks like this: <verbatim> #!/path/to/fossil |
| ︙ | ︙ |
Changes to www/password.wiki.
| ︙ | ︙ | |||
24 25 26 27 28 29 30 | Fossil self-hosting repository. Then the value of USER.PW for alice would be the SHA1 hash of <blockquote> CE59BB9F186226D80E49D1FA2DB29F935CCA0333/alice/asdfg </blockquote> | < | | | | | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | Fossil self-hosting repository. Then the value of USER.PW for alice would be the SHA1 hash of <blockquote> CE59BB9F186226D80E49D1FA2DB29F935CCA0333/alice/asdfg </blockquote> Note that by including the project-code and the login as part of the hash, a different USER.PW value results even if two or more users on the repository select the same "asdfg" password or if user alice reuses the same password on multiple projects. Whenever a password is changed using the web interface or using the "user" command-line method, the new password is stored using the SHA1 encoding. Thus, cleartext passwords will gradually migrate to become SHA1 passwords. All remaining cleartext passwords can be converted to SHA1 passwords using the following command: |
| ︙ | ︙ | |||
75 76 77 78 79 80 81 | address of the client is stored in the USER.COOKIE and USER.IPADDR fields of the USER table on the server. The USER.CEXPIRE field holds an expiration date for the cookie, encoded as a Julian day number. On all subsequent HTTP requests, the cookie value is matched against the USER table to enable access to the repository. | < < < < < < < < < < < < < < | 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | address of the client is stored in the USER.COOKIE and USER.IPADDR fields of the USER table on the server. The USER.CEXPIRE field holds an expiration date for the cookie, encoded as a Julian day number. On all subsequent HTTP requests, the cookie value is matched against the USER table to enable access to the repository. Note that in order to log into a Fossil server, it is necessary to write information into the repository database. Hence, login is not possible on a Fossil repository with a read-only database file. The user password is sent over the wire as cleartext on the initial login attempt. The plan moving forward is to compute the SHA1 hash of the password on the client using JavaScript and then send only the hash |
| ︙ | ︙ |
Changes to www/permutedindex.html.
| ︙ | ︙ | |||
67 68 69 70 71 72 73 74 75 76 77 78 79 80 | <li><a href="selfhost.wiki">Fossil Self Hosting Repositories</a></li> <li><a href="settings.wiki">Fossil Settings</a></li> <li><a href="hints.wiki">Fossil Tips And Usage Hints</a></li> <li><a href="fossil-v-git.wiki">Fossil Versus Git</a></li> <li><a href="fossil_prompt.wiki">Fossilized Bash Prompt</a></li> <li><a href="faq.wiki">Frequently Asked Questions</a></li> <li><a href="gitusers.md">Git to Fossil Translation Guide</a></li> <li><a href="hacker-howto.wiki">Hacker How-To</a></li> <li><a href="adding_code.wiki">Hacking Fossil</a></li> <li><a href="hashpolicy.wiki">Hash Policy: Choosing Between SHA1 and SHA3-256</a></li> <li><a href="hashes.md">Hashes: Fossil Artifact Identification</a></li> <li><a href="index.wiki">Home Page</a></li> <li><a href="aboutcgi.wiki">How CGI Works In Fossil</a></li> <li><a href="aboutdownload.wiki">How The Download Page Works</a></li> | > | 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | <li><a href="selfhost.wiki">Fossil Self Hosting Repositories</a></li> <li><a href="settings.wiki">Fossil Settings</a></li> <li><a href="hints.wiki">Fossil Tips And Usage Hints</a></li> <li><a href="fossil-v-git.wiki">Fossil Versus Git</a></li> <li><a href="fossil_prompt.wiki">Fossilized Bash Prompt</a></li> <li><a href="faq.wiki">Frequently Asked Questions</a></li> <li><a href="gitusers.md">Git to Fossil Translation Guide</a></li> <li><a href="glossary.md">Glossary</a></li> <li><a href="hacker-howto.wiki">Hacker How-To</a></li> <li><a href="adding_code.wiki">Hacking Fossil</a></li> <li><a href="hashpolicy.wiki">Hash Policy: Choosing Between SHA1 and SHA3-256</a></li> <li><a href="hashes.md">Hashes: Fossil Artifact Identification</a></li> <li><a href="index.wiki">Home Page</a></li> <li><a href="aboutcgi.wiki">How CGI Works In Fossil</a></li> <li><a href="aboutdownload.wiki">How The Download Page Works</a></li> |
| ︙ | ︙ | |||
101 102 103 104 105 106 107 108 109 110 111 112 113 114 | <li><a href="rebaseharm.md">Rebase Considered Harmful</a></li> <li><a href="reviews.wiki">Reviews</a></li> <li><a href="chroot.md">Server Chroot Jail</a></li> <li><a href="shunning.wiki">Shunning: Deleting Content From Fossil</a></li> <li><a href="../../../sitemap">Site Map</a></li> <li><a href="style.wiki">Source Code Style Guidelines</a></li> <li><a href="tech_overview.wiki">SQLite Databases Used By Fossil</a></li> <li><a href="backoffice.md">The "Backoffice" mechanism of Fossil</a></li> <li><a href="patchcmd.md">The "fossil patch" Command</a></li> <li><a href="blame.wiki">The Annotate/Blame Algorithm Of Fossil</a></li> <li><a href="defcsp.md">The Default Content Security Policy</a></li> <li><a href="fileedit-page.md">The fileedit Page</a></li> <li><a href="makefile.wiki">The Fossil Build Process</a></li> <li><a href="sync.wiki">The Fossil Sync Protocol</a></li> | > | 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | <li><a href="rebaseharm.md">Rebase Considered Harmful</a></li> <li><a href="reviews.wiki">Reviews</a></li> <li><a href="chroot.md">Server Chroot Jail</a></li> <li><a href="shunning.wiki">Shunning: Deleting Content From Fossil</a></li> <li><a href="../../../sitemap">Site Map</a></li> <li><a href="style.wiki">Source Code Style Guidelines</a></li> <li><a href="tech_overview.wiki">SQLite Databases Used By Fossil</a></li> <li><a href="ssl-server.md">SSL/TLS Server Mode</a></li> <li><a href="backoffice.md">The "Backoffice" mechanism of Fossil</a></li> <li><a href="patchcmd.md">The "fossil patch" Command</a></li> <li><a href="blame.wiki">The Annotate/Blame Algorithm Of Fossil</a></li> <li><a href="defcsp.md">The Default Content Security Policy</a></li> <li><a href="fileedit-page.md">The fileedit Page</a></li> <li><a href="makefile.wiki">The Fossil Build Process</a></li> <li><a href="sync.wiki">The Fossil Sync Protocol</a></li> |
| ︙ | ︙ |
Changes to www/quickstart.wiki.
| ︙ | ︙ | |||
23 24 25 26 27 28 29 | </blockquote> <h2 id="workflow" name="fslclone">General Work Flow</h2> <p>Fossil works with repository files (a database in a single file with the project's complete history) and with checked-out local trees (the working directory you use to do your work). | | | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
</blockquote>
<h2 id="workflow" name="fslclone">General Work Flow</h2>
<p>Fossil works with repository files (a database in a single file with the project's
complete history) and with checked-out local trees (the working directory
you use to do your work).
(See [./glossary.md | the glossary] for more background.)
The workflow looks like this:</p>
<ul>
<li>Create or clone a repository file. ([/help/init|fossil init] or
[/help/clone | fossil clone])
<li>Check out a local tree. ([/help/open | fossil open])
<li>Perform operations on the repository (including repository
|
| ︙ | ︙ |
Changes to www/server/any/cgi.md.
| ︙ | ︙ | |||
66 67 68 69 70 71 72 73 | Once deployed, a URL like: <b>http://mydomain.org/cgi-bin/repo/XYZ</b> will serve up the repository `/home/fossil/repos/XYZ.fossil` if it exists. Additional options available to the CGI script are [documented separately](../../cgi.wiki). *[Return to the top-level Fossil server article.](../)* | > > > > > > > > > > > > > > > > > > > | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
Once deployed, a URL like: <b>http://mydomain.org/cgi-bin/repo/XYZ</b>
will serve up the repository `/home/fossil/repos/XYZ.fossil` if it
exists.
Additional options available to the CGI script are [documented
separately](../../cgi.wiki).
#### CGI with Apache behind an Nginx proxy
For the case where the Fossil repositories live on a computer, itself behind
an Internet-facing machine that employs Nginx to reverse proxy HTTP(S) requests
and take care of the TLS part of the connections in a transparent manner for
the downstream web servers, the CGI parameter `HTTPS=on` might not be set.
However, Fossil in CGI mode needs it in order to generate the correct links.
Apache can be instructed to pass this parameter further to the CGI scripts for
TLS connections with a stanza like
SetEnvIf X-Forwarded-Proto "https" HTTPS=on
in its config file section for CGI, provided that
proxy_set_header X-Forwarded-Proto $scheme;
has been be added in the relevant proxying section of the Nginx config file.
*[Return to the top-level Fossil server article.](../)*
|
Changes to www/serverext.wiki.
| ︙ | ︙ | |||
116 117 118 119 120 121 122 | any kind of program you like. But the creator of SQLite and Fossil is fond of [https://www.tcl.tk|Tcl/Tk] and so he tends to gravitate toward Tcl-based technologies like Wapp.) The fileup1 script is a demo program that lets the user upload a file using a form, and then displays that file in the reply. There is a link on the page that causes the fileup1 script to return a copy of its own source-code, so you can see how it works. | | | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | any kind of program you like. But the creator of SQLite and Fossil is fond of [https://www.tcl.tk|Tcl/Tk] and so he tends to gravitate toward Tcl-based technologies like Wapp.) The fileup1 script is a demo program that lets the user upload a file using a form, and then displays that file in the reply. There is a link on the page that causes the fileup1 script to return a copy of its own source-code, so you can see how it works. <h2 id="cgi-inputs">3.0 CGI Inputs</h2> The /ext extension mechanism is an ordinary CGI interface. Parameters are passed to the CGI program using environment variables. The following standard CGI environment variables are supported: * AUTH_TYPE * AUTH_CONTENT |
| ︙ | ︙ | |||
150 151 152 153 154 155 156 157 158 159 160 161 162 163 | * REQUEST_URI * SCRIPT_DIRECTORY * SCRIPT_FILENAME * SCRIPT_NAME * SERVER_NAME * SERVER_PORT * SERVER_PROTOCOL Do a web search for "[https://duckduckgo.com/?q=cgi+environment_variables|cgi environment variables]" to find more detail about what each of the above variables mean and how they are used. Live listings of the values of some or all of these environment variables can be found at links like these: | > | 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | * REQUEST_URI * SCRIPT_DIRECTORY * SCRIPT_FILENAME * SCRIPT_NAME * SERVER_NAME * SERVER_PORT * SERVER_PROTOCOL * SERVER_SOFTWARE Do a web search for "[https://duckduckgo.com/?q=cgi+environment_variables|cgi environment variables]" to find more detail about what each of the above variables mean and how they are used. Live listings of the values of some or all of these environment variables can be found at links like these: |
| ︙ | ︙ |
Added www/ssl-server.md.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# SSL/TLS Server Mode
## History
Fossil has supported [client-side SSL/TLS][0] since [2010][1]. This means
that commands like "[fossil sync](/help?cmd=sync)" could use SSL/TLS when
contacting a server. But on the server side, commands like
"[fossil server](/help?cmd=server)" operated in clear-text only. To implement
an encrypted server, you had to put Fossil behind a web server or reverse
proxy that handled the SSL/TLS decryption/encryption and passed cleartext
down to Fossil.
[0]: ./ssl.wiki
[1]: /timeline?c=b05cb4a0e15d0712&y=ci&n=13
Beginning in [late December 2021](/timeline?c=f6263bb64195b07f&y=a&n=13),
this has been fixed. Commands like
* "[fossil server](/help?cmd=server)"
* "[fossil ui](/help?cmd=ui)", and
* "[fossil http](/help?cmd=http)"
now all handle server-mode SSL/TLS encryption natively. It is now possible
to run a secure Fossil server without having to put Fossil behind an encrypting
web server or reverse proxy. Hence, it is now possible to stand up a complete
Fossil project website on an inexpensive VPS with no added software other than
Fossil itself and something like [certbot](https://certbot.eff.org) for
obtaining a CA-signed certificate.
## Usage
To put any of the Fossil server commands into SSL/TLS mode, simply
add the "--cert" command-line option.
> ~~~
fossil ui --cert unsafe-builtin
~~~
The --cert option is what tells Fossil to use TLS encryption.
Normally, the argument to --cert is the name of a file containing
the certificate (the "fullchain.pem" file) for the website. In this
example, the magic name "unsafe-builtin" is used, which causes Fossil
to use a self-signed cert rather than a real cert obtained from a
[Certificate Authority](https://en.wikipedia.org/wiki/Certificate_authority)
or "CA". As the name implies, this self-signed cert is not secure and
should only be used for testing. Your web-browser will complain bitterly
and will refuse to display the pages using the "unsafe-builtin" cert.
Firefox will allow you to click an "I know the risks" button and continue.
Other web browsers will stubornly refuse to display the page, under the theory
that weak encryption is worse than no encryption at all. Continue reading
to see how to solve this.
## About Certs
Certs are based on public-key or asymmetric cryptography. To create a cert,
you first create a new "key pair" consisting of a public key and a private key.
The public key can be freely shared with the world, but you must keep the
private key secret. If anyone gains access to your private key then he will be
able to impersonate you and break into your system.
To obtain a cert, you send your public key and the name of the domain you
want to protect to a certificate authority. The CA then digitally signs
the combination of those two things using their own private key and sends
the signed combination back to you. The CA's digital signature of your
public key and domain name is the cert.
SSL/TLS servers need two things in order to prove their identity to clients:
1. The cert that was signed by a CA
2. The private key
The SSL/TLS servers send the cert to each client, so that the client
can verify it. But the private key is kept strictly private and is never
shared with anyone.
## How To Tell Fossil About Your Cert And Private Key
If you do not have your own cert and private key, you can ask Fossil
to use "unsafe-builtin", which is a self-signed cert that is built into
Fossil. This is wildly insecure, since the private key is not really private -
it is [in plain sight](/info/c2a7b14c3f541edb96?ln=89-116) in the Fossil
source tree for anybody to read. <b>Never add the private key that is
built into Fossil to your OS's trust store</b> as doing so will severely
compromise your computer. The built-in cert is only useful for testing.
If you want actual security, you will need to come up with your own private
key and cert.
Fossil wants to read certs and public keys in the
[PEM format](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail).
PEM is a pure ASCII text format. The private key consists of text
like this:
>
`-----BEGIN PRIVATE KEY-----`
*base-64 encoding of the private key*
`-----END PRIVATE KEY-----`
Similarly, a PEM-encoded cert will look like this:
>
`-----BEGIN CERTIFICATE-----`
*base-64 encoding of the certificate*
`-----END CERTIFICATE-----`
In both formats, text outside of the delimiters is ignored. That means
that if you have a PEM-formatted private key and a separate PEM-formatted
certificate, you can concatenate the two into a single file and the
individual components will still be easily accessible.
If you have a single file that holds both your private key and your
cert, you can hand it off to the "[fossil server](/help?cmd=server)"
command using the --cert option. Like this:
> ~~~
fossil server --port 443 --cert mycert.pem /home/www/myproject.fossil
~~~
The command above is sufficient to run a fully-encrypted web site for
the "myproject.fossil" Fossil repository. This command must be run as
root, since it wants to listen on TCP port 443, and only root processes are
allowed to do that. This is safe, however, since before reading any
information off of the wire, Fossil will put itself inside a chroot jail
at /home/www and drop all root privileges.
### Keeping The Cert And Private Key In Separate Files
If you do not want to combine your cert and private key into a single
big PEM file, you can keep them separate using the --pkey option to
Fossil.
> ~~~
fossil server --port 443 --cert fullchain.pem --pkey privkey.pem /home/www/myproject.fossil
~~~
## The ACME Protocol
The [ACME Protocol][2] is used to prove to a CA that you control a
website. CAs require proof that you control a domain before they
will issue a cert for that domain. The usual means of dealing
with ACME is to run the separate [certbot](https://certbot.eff.org) tool.
Here is, in a nutshell, what certbot will do to obtain your cert:
1. Certbot sends your "signing request" (the document that contains
your public key and your domain name) to the CA.
2. After receiving the signing request, the CA needs to verify that you
control the domain of the cert. To do this (or, one common
way of doing this, at least) the CA sends a secret token back to
certbot through a secure backchannel, and instructs certbot to make
that token accessible on the (unencrypted, ordinary "http:") web site
for the domain in a particular file under the ".well-known" subdirectory.
3. Certbot puts the token where the CA requested it, then notifies the
CA that it is there.
4. The CA accesses the token to confirm that you do indeed control the
website. It then creates the cert and sends it back to certbot.
5. Certbot stores your cert and deletes the ".well-known" token.
In order for all of this to happen, certbot needs to be able to create
a subdirectory named ".well-known", within a directory you specify, and
then populate that subdirectory with a token file of some kind. To support
this, the "[fossil server](/help?cmd=server)" and
"[fossil http](/help?cmd=http)" commands have the --acme option.
When the --acme option is specified and Fossil sees a URL where the path
begins with ".well-known", then instead of doing its normal processing, it
looks for a file with that pathname and returns it to the client. If
the "server" or "http" command is referencing a single Fossil repository,
then the ".well-known" sub-directory should be in the same directory as
the repository file. If the "server" or "http" command are run against
a directory full of Fossil repositories, then the ".well-known" sub-directory
should be in that top-level directory.
Thus, to set up a project website, you should first run Fossil in ordinary
unencrypted HTTP mode like this:
> ~~~
fossil server --port 80 --acme /home/www/myproject.fossil
~~~
Then you create your public/private key pair and run certbot, giving it
a --webroot of /home/www. Certbot will create the sub-directory
named "/home/www/.well-known" and put token files there, which the CA
will verify. Then certbot will store your new cert in a particular file.
Once certbot has obtained your cert, then you can concatenate that
cert with your private key and run Fossil in SSL/TLS mode as shown above.
[2]: https://en.wikipedia.org/wiki/Automated_Certificate_Management_Environment
|
Changes to www/ssl.wiki.
| ︙ | ︙ | |||
224 225 226 227 228 229 230 | If you attempt to connect to a server which requests a client certificate, but don't provide one, fossil will show an error message which explains what to do to authenticate with the server. <h2 id="server">Fossil TLS Configuration: Server Side</h2> | | | | | | | | 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 | If you attempt to connect to a server which requests a client certificate, but don't provide one, fossil will show an error message which explains what to do to authenticate with the server. <h2 id="server">Fossil TLS Configuration: Server Side</h2> Fossil's built-in HTTP server feature did not add [./ssl-server.md|support HTTP over TLS] (a.k.a. HTTPS) until version 2.18 (2022). Prior to that, system administrators that wanted to add HTTPS support to a Fossil server had to put Fossil behind a web-server or reverse-proxy that would do the HTTPS to HTTP translation. [./server/ | Instructions for doing so] are found elsewhere in this documentation. A few of the most useful of these are: * <a id="stunnel" href="./server/any/stunnel.md">Serving via stunnel</a> * <a id="althttpd" href="./server/any/althttpd.md">Serving via stunnel + althttpd</a> * <a id="nginx" href="./server/debian/nginx.md#tls">Serving via SCGI with nginx on Debian</a> <h2 id="enforcing">Enforcing TLS Access</h2> |
| ︙ | ︙ |
Changes to www/sync.wiki.
| ︙ | ︙ | |||
30 31 32 33 34 35 36 | an administrator can sync local state using the [/help?cmd=configuration|config push] and [/help?cmd=configuration|config pull] commands. <h3 id="crdt">1.1 Conflict-Free Replicated Datatypes</h3> | | | | < | | | | | | > | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | an administrator can sync local state using the [/help?cmd=configuration|config push] and [/help?cmd=configuration|config pull] commands. <h3 id="crdt">1.1 Conflict-Free Replicated Datatypes</h3> <p>The "bag of artifacts" data model used by Fossil is apparently an implementation of a particular [https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type|Conflict-Free Replicated Datatype (CRDT)] called a "G-Set" or "Grow-only Set". The academic literature on CRDTs only began to appear in about 2011, and Fossil predates that research by at least 4 years. But it is nice to know that theorists have now proven that the underlying data model of Fossil can provide strongly-consistent replicas using only peer-to-peer communication and without any kind of central authority.</p> <p>If you are already familiar with CRDTs and were wondering if Fossil used them, the answer is "yes". We just don't call them by that name.</p> <h2>2.0 Transport</h2> |
| ︙ | ︙ | |||
75 76 77 78 79 80 81 | to represent the listener and initiator of the interaction, respectively. Nothing in this protocol requires that the server actually be a back-room processor housed in a datacenter, nor does the client need to be a desktop or handheld device. For the purposes of this article "client" simply means the repository that initiates the conversation and "server" is the repository that responds. Nothing more.</p> | | > > > > > > > > > > > > > > > > > > > > > > > | 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | to represent the listener and initiator of the interaction, respectively. Nothing in this protocol requires that the server actually be a back-room processor housed in a datacenter, nor does the client need to be a desktop or handheld device. For the purposes of this article "client" simply means the repository that initiates the conversation and "server" is the repository that responds. Nothing more.</p> <h4>2.0.1 HTTPS Transport</h4> <p>In the current implementation of Fossil, the server only understands HTTP requests. The client can send either clear-text HTTP requests or encrypted HTTPS requests. But when HTTPS requests are sent, they first must be decrypted by a web server or proxy before being passed to the Fossil server. This limitation may be relaxed in a future release.</p> <h4>2.0.2 SSH Transport</h4> <p>When doing a sync using an "ssh:..." URL, the same HTTP transport protocol is used. Fossil simply uses [https://en.wikipedia.org/wiki/Secure_Shell|ssh] to start an instance of the [/help?cmd=test-http|fossil test-http] command running on the remote machine. It then sends HTTP requests and gets back HTTP replies over the SSH connection, rather than sending and receiving over an internet socket. To see the specific "ssh" command that the Fossil client runs in order to set up a connection, add either of the the "--httptrace" or "--sshtrace" options to the "fossil sync" command line. <h4>2.0.3 FILE Transport</h4> <p>When doing a sync using a "file:..." URL, the same HTTP protocol is still used. But instead of sending each HTTP request over a socket or via SSH, the HTTP request is written into a temporary file. The client then invokes the [/help?cmd=http|fossil http] command in a subprocess to process the request and and generate a reply. The client then reads the HTTP reply out of a temporary file on disk, and deletes the two temporary files. To see the specific "fossil http" command that is run in order to implement the "file:" transport, add the "--httptrace" option to the "fossil sync" command. <h3>2.1 Server Identification</h3> <p>The server is identified by a URL argument that accompanies the push, pull, or sync command on the client. (As a convenience to users, the URL can be omitted on the client command and the same URL from the most recent push, pull, or sync will be reused. This saves typing in the common case where the client does multiple syncs to |
| ︙ | ︙ | |||
568 569 570 571 572 573 574 | <li> ignore-glob <li> keep-glob <li> crlf-glob <ul></td><td valign="top"><ul> <li> crnl-glob <li> encoding-glob <li> empty-dirs | | | 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 | <li> ignore-glob <li> keep-glob <li> crlf-glob <ul></td><td valign="top"><ul> <li> crnl-glob <li> encoding-glob <li> empty-dirs <li> <s>allow-symlinks</s> (removed 2020-08, version 2.12.1) <li> dotfiles <li> parent-project-code <li> parent-projet-name <li> hash-policy <li> mv-rm-files <li> ticket-table <li> ticket-common |
| ︙ | ︙ | |||
1003 1004 1005 1006 1007 1008 1009 | <li>Clusters are artifacts that contain IDs of other artifacts. <li>Clusters are created automatically on the server during a pull. <li>Repositories keep track of all artifacts that are not named in any cluster and send igot messages for those artifacts. <li>Repositories keep track of all the phantoms they hold and send gimme messages for those artifacts. </ol> | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 |
<li>Clusters are artifacts that contain IDs of other artifacts.
<li>Clusters are created automatically on the server during a pull.
<li>Repositories keep track of all artifacts that are not named in any
cluster and send igot messages for those artifacts.
<li>Repositories keep track of all the phantoms they hold and send
gimme messages for those artifacts.
</ol>
<h2>7.0 Troubleshooting And Debugging Hints</h2>
<p>
If you run the [/help?cmd=sync|fossil sync] command
(or [/help?cmd=pull|pull] or [/help?cmd=push|push] or
[/help?cmd=clone|clone]) with the --httptrace option, Fossil
will keep a copy of each HTTP request and reply in files
named:
<ul>
<li> <tt>http-request-</tt><i>N</i><tt>.txt</tt>
<li> <tt>http-reply-</tt><i>N</i><tt>.txt</tt>
</ul>
<p>In the above, <i>N</i> is a integer that increments with each
round-trip. If you are having trouble on the server side,
you can run the "[/help?cmd=test-http|fossil test-http]" command in a
debugger using one the "http-request-N.txt" files as input and
single step through the processing performed by the server.
<p>The "--transport-command CMD" option on [/help?cmd=sync|fossil sync]
(and similar) causes the external program "CMD" to be used to move
the sync message to the server and retrieve the sync reply. The
CMD is given three arguments:
<ol>
<li> The URL of the server
<li> The name of a temporary file that contains the output-bound sync
protocol text, with the HTTP headers
<li> The name of a temporary file into which the CMD should write the
reply sync protocol text, again without any HTTP headers
</ol>
<p>In a complex debugging situation, you can run the command
"fossil sync --transport-command ./debugging_script" where
"debugging_script" is some script of your own that invokes
the anomolous behavior your are trying to debug.
|
Changes to www/userlinks.wiki.
1 2 3 4 5 6 7 |
<title>Links For Fossil Users:</title>
* [./permutedindex.html | Documentation index] with [/search?c=d | full text search].
* [./reviews.wiki | Testimonials] from satisfied Fossil users and
[./quotes.wiki | Quotes] about Fossil and other DVCSes.
* [./faq.wiki | Frequently Asked Questions]
* The [./concepts.wiki | concepts] behind Fossil.
| | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<title>Links For Fossil Users:</title>
* [./permutedindex.html | Documentation index] with [/search?c=d | full text search].
* [./reviews.wiki | Testimonials] from satisfied Fossil users and
[./quotes.wiki | Quotes] about Fossil and other DVCSes.
* [./faq.wiki | Frequently Asked Questions]
* The [./concepts.wiki | concepts] behind Fossil.
[./glossary.md | Another viewpoint].
* [./quickstart.wiki | Quick Start] guide to using Fossil.
* [./qandc.wiki | Questions & Criticisms] directed at Fossil.
* [./build.wiki | Compiling and Installing]
* Fossil supports [./embeddeddoc.wiki | embedded documentation]
that is versioned along with project source code.
* Fossil uses an [./fileformat.wiki | enduring file format] that is
designed to be readable, searchable, and extensible by people
|
| ︙ | ︙ |
Changes to www/whyusefossil.wiki.
| ︙ | ︙ | |||
37 38 39 40 41 42 43 |
<li>Avoid wasting time doing manual file copying
<li>Avoid human errors during manual backups
</ol>
</ol>
<p id="definitions"><b>II. Definitions</b></p>
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
<li>Avoid wasting time doing manual file copying
<li>Avoid human errors during manual backups
</ol>
</ol>
<p id="definitions"><b>II. Definitions</b></p>
Moved to [./glossary.md | a separate document].
<p><b>III. Basic Fossil commands</b>
<ul>
<li><p><b>clone</b> →
Make a copy of a repository. The original repository
is usually (but not always) on a remote machine and the copy is on
|
| ︙ | ︙ |
Added www/wsl_caveats.wiki.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | <title>Caveats and Precautions for Fossil Usage with Windows Subsystem for Linux</title> <h2>When These Issues Matter</h2> The discussion following is relevant to those who: * Are using the Windows Subsystem for Linux (aka "WSL"); * Create a Fossil checkout in a directory accessible from WSL and Windows; * Use both Linux Fossil and Windows tools to modify files in a checkout; * Desire to or must preserve execute permissions set for repository files; * and Use Linux Fossil to commit changes made within the checkout. Note that these criteria apply conjunctively; if any are not met, then the consequences of the issues below are at worst annoying and otherwise harmless or absent. <h2>What Can Go Wrong (Why It Matters)</h2> The most readily seen manifestation of the problem occurs when "<tt>fossil status</tt>" or "<tt>fossil changes</tt>" is run, using Linux Fossil from WSL after Windows tools (including fossil.exe) have been used to modify files within a checkout. Unless filter options block it, those subcommands will tag some (and often many) checkout files with <b>EXECUTABLE</b> or <b>NOEXEC</b>, indicating that the file's user execute permission has been altered such that it differs from what is recorded in the repository for that version of the file. This "user execute permission" is referred to as "the X-bit" hereafter, referring to either the recorded version state or a checkout file attributes state. This is merely annoying and distracting if the altered X-bit will never be committed using Linux Fossil. It can be quite distracting because those tags tend to mask the presence or absence of other changes whose detection is the usual reason for using Fossil's changes or status subcommands. However, in the problematic usage scenario, those tags will most often represent inadvertant toggling of the X-bit on the affected file. The X-bit is kept in the repository for good reason (usually), and arbitrary changes to it by means of a commit when that change is not intended is virtually always a bad result. (At best, the change causes useless churn; at worst it frustrates the intended purpose of having an X-bit.) <h2>Technical Discusion of the Problem</h2> The genesis of altered X-bits, while not obvious at first glance, involves obvious facts. The Windows OS does not deal with the triple of user/group/other executable permissions the way that Unix and similar operating systems do. Hence, tools which run on Windows, including Fossil built for Windows, do not manage the X-bit; it may not even exist yet for files which have not had their permissions set by any Linux program running in WSL. When such tools modify a file which has had its X-bit set (or cleared) by a program in WSL, an existing X-bit value may not be preserved depending upon how the modification is effected. The WSL infrastructure (or virtual system) compensates for the absence of an X-bit in Windows filesystems with two stratagems: (1) Establishing a default for its value when no Linux program has yet set it; and (2) stashing Linux "mode" bits in a "special" place for each file once it has been subject to a chmod() call. That default's default can be changed by way of /etc/wsl.conf content. However, this default cannot be right for files which are tracked in a Fossil repository as having the other value. And Windows tools generally are not written to deal with "mode" bits in that "special" place. (They are kept in a NTFS extended file attribute named $LXMOD, not accessible through the WIN32 API; the OS layer below WIN32 must be used to get at them.) Hence, inadvertant X-bit changes are unavoidable, or avoided only by luck, in the general usage case noted above. <h2>Problematic Usage Scenarios</h2> <h3>A Simple Example</h3> * Open a checkout in Windows (using fossil.exe) from a project whose files have a mixture of executable and non-executable files. Use a checkout directory visible when running under WSL. * Navigate to the same directory in a Linux shell on WSL, then run "fossil status". * Depending upon /etc/wsl.conf content (or defaults in its absence), the status ouput will tag checkout files as EXECUTABLE or NOEXEC. <h3>Continuation of Simple Example</h3> * In the same checkout as above "Simple Example", on WSL, run "fossil revert" to correct all those errant X-bit values. * Run "fossil status" again in WSL to verify absence of toggled X-bits. * Run "ls -l" from WSL to find two files, one with its X-bit set and the other with it clear. * From Windows, perform these steps on each of those files: (1) read the_file content into a buffer<br> (2) rename the_file the_file.bak<br> (3) write buffer content to new file, the_file<br> (4) del the_file.bak (or leave it)<br> (Note that this sequence is similar to what many editors do when a user modifies a file then uses undo to reverse the changes.) * Run "fossil status" again in WSL and observe that one of the two files has had its X-bit toggled. <h3>A Fossil-Only Example</h3> * In the another (different) checkout of the same version, somehow cause "legitimate" X-bit toggles of two files whose X-bits differ. (This "somehow" probably will involve WSL to toggle file bits and fossil on WSL to commit the toggles.) * In the Simple Example checkout, use fossil.exe on Windows to update the checkout, ostensibly bringing the X-bit toggles into the affected checkout files. * In the Simple Example checkout, use fossil on WSL to run "fossil status", and observe at least one X-bit discrepancy. <h2>Recommended Workflow</h2> There are two simple approaches for dealing with this issue when one wishes to continue using the same checkout directory from Windows and WSL. Either one is effective. These are: * Do not use fossil on WSL for any operations which will modify the repository. Instead, block those operations in some manner. * Do not use any tools on Windows, (including certain subcommands of fossil.exe,) which may modify the X-bits on files within the shared checkout, instead restricting use of Windows tools to those which are known to only (and actually) modify file content in place while preserving X-bit values. (The "actually" proviso emphasizes that tools which only simulate in-place file modification, but do so via create combined with delete and rename, are to be avoided. A simulation which works flawlessly on Windows may not preserve the WSL X-bit.) There are more complex ways to deal with this issue, involving use of fossil on WSL to fix (or revert) toggled X-bits prior to any commit, together with actions needed to preserve all intended changes to the checkout as fossil revert is done. Such methods are overly clever or fragile for elaboration here. Another way to deal with this issue is to correct any toggled X-bits within a checkout before using "fossil commit" on WSL by means other than "fossil revert". <h2>Corrective Measures or Mitigation</h2> It is possible, by either manual or automated means, to perform a pre-commit check and/or correction for mis-toggled X-bits. The X-bit states are available from the repository for whatever versions it has stored. And several Linux tools are able to read or alter the X-bit state of files. With these components, a tool can be readily built to aid avoidance of a commit (via fossil on WSL) that would record mis-toggled X-bits into the repository. Fossil itself on WSL will detect mis-toggled X-bits for files which have not been otherise modified, but altered file content masks such detection, and it is just such modification that is among the problematic scenarios. So Fossil alone cannot yet reliably do the detection or correction needed to avoid or remedy the mis-toggled X-bit commit problem. It is also feasible to detect or correct the mis-toggled X-bit problem within Windows with a special-purpose tool which can read, create or modify the X-bits stored by WSL for any file which has been subject to the Linux chmod(...) system call. Creation of these tools is beyond the scope of this document. |