Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Merge with trunk; resolved tar and zip generation to handle include/exclude globs. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | jan-manifest-tags |
| Files: | files | file ages | folders |
| SHA1: |
de9e7651a97afcc2b1bb669cbd3dbdd8 |
| User & Date: | jan 2016-08-03 01:18:14.693 |
Context
|
2016-08-03
| ||
| 14:30 | For opened working trees, store current branch at top of manifest.tags. ... (check-in: 0fb54e5afe user: jan tags: jan-manifest-tags) | |
| 01:18 | Merge with trunk; resolved tar and zip generation to handle include/exclude globs. ... (check-in: de9e7651a9 user: jan tags: jan-manifest-tags) | |
|
2016-08-02
| ||
| 15:18 | Merge the "purge" command onto trunk, even though it is incomplete. ... (check-in: b78a32f43d user: drh tags: trunk) | |
|
2016-03-11
| ||
| 23:45 | Merged updates from trunk. Builds on Windows. ... (check-in: 9a41671bb2 user: rberteig tags: jan-manifest-tags) | |
Changes
Changes to .fossil-settings/ignore-glob.
1 2 3 4 5 | compat/openssl* compat/tcl* fossil fossil.exe win/fossil.exe | > > | 1 2 3 4 5 6 7 | compat/openssl* compat/tcl* fossil fossil.exe win/fossil.exe *shell-see.* *sqlite3-see.* |
Changes to Makefile.in.
| ︙ | ︙ | |||
39 40 41 42 43 44 45 46 47 48 49 50 51 | TCLSH = tclsh LIB = @LDFLAGS@ @EXTRA_LDFLAGS@ @LIBS@ 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@ FOSSIL_ENABLE_MINIZ = @FOSSIL_ENABLE_MINIZ@ include $(SRCDIR)/main.mk distclean: clean rm -f autoconfig.h config.log Makefile | > | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | TCLSH = tclsh LIB = @LDFLAGS@ @EXTRA_LDFLAGS@ @LIBS@ 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_SEE = @USE_SEE@ FOSSIL_ENABLE_MINIZ = @FOSSIL_ENABLE_MINIZ@ include $(SRCDIR)/main.mk distclean: clean rm -f autoconfig.h config.log Makefile |
Changes to VERSION.
|
| | | 1 | 1.36 |
Changes to auto.def.
| ︙ | ︙ | |||
13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
with-legacy-mv-rm=0 => {Enable legacy behavior for mv/rm (skip checkout files)}
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}
with-tcl-private-stubs=0
=> {Enable Tcl integration via private stubs mechanism}
internal-sqlite=1 => {Don't use the internal SQLite, use the system one}
static=0 => {Link a static executable}
fusefs=1 => {Disable the Fuse Filesystem}
fossil-debug=0 => {Build with fossil debugging enabled}
json=0 => {Build with fossil JSON API enabled}
}
| > | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
with-legacy-mv-rm=0 => {Enable legacy behavior for mv/rm (skip checkout files)}
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}
with-tcl-private-stubs=0
=> {Enable Tcl integration via private stubs mechanism}
with-see=0 => {Enable the SQLite Encryption Extension (SEE)}
internal-sqlite=1 => {Don't use the internal SQLite, use the system one}
static=0 => {Link a static executable}
fusefs=1 => {Disable the Fuse Filesystem}
fossil-debug=0 => {Build with fossil debugging enabled}
json=0 => {Build with fossil JSON API enabled}
}
|
| ︙ | ︙ | |||
36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
cc-check-progs tclsh
define EXTRA_CFLAGS ""
define EXTRA_LDFLAGS ""
define USE_SYSTEM_SQLITE 0
define USE_LINENOISE 0
define FOSSIL_ENABLE_MINIZ 0
# This procedure is a customized version of "cc-check-function-in-lib",
# that does not modify the LIBS variable. Its use prevents prematurely
# pulling in libraries that will be added later anyhow (e.g. "-ldl").
proc check-function-in-lib {function libs {otherlibs {}}} {
if {[string length $otherlibs]} {
msg-checking "Checking for $function in $libs with $otherlibs..."
| > | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
cc-check-progs tclsh
define EXTRA_CFLAGS ""
define EXTRA_LDFLAGS ""
define USE_SYSTEM_SQLITE 0
define USE_LINENOISE 0
define FOSSIL_ENABLE_MINIZ 0
define USE_SEE 0
# This procedure is a customized version of "cc-check-function-in-lib",
# that does not modify the LIBS variable. Its use prevents prematurely
# pulling in libraries that will be added later anyhow (e.g. "-ldl").
proc check-function-in-lib {function libs {otherlibs {}}} {
if {[string length $otherlibs]} {
msg-checking "Checking for $function in $libs with $otherlibs..."
|
| ︙ | ︙ | |||
130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
define-append EXTRA_CFLAGS {-D_XOPEN_SOURCE=500 -D__EXTENSIONS__}
}
if {[opt-bool fossil-debug]} {
define-append EXTRA_CFLAGS -DFOSSIL_DEBUG
msg-result "Debugging support enabled"
}
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
# reading config.h first.
define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_JSON
| > > > > > > | 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
define-append EXTRA_CFLAGS {-D_XOPEN_SOURCE=500 -D__EXTENSIONS__}
}
if {[opt-bool fossil-debug]} {
define-append EXTRA_CFLAGS -DFOSSIL_DEBUG
msg-result "Debugging support enabled"
}
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
# reading config.h first.
define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_JSON
|
| ︙ | ︙ |
Changes to src/add.c.
| ︙ | ︙ | |||
796 797 798 799 800 801 802 |
Stmt move;
if( db_table_exists(db_name("temp"), "fmove") ){
db_prepare(&move, "SELECT x, y FROM fmove ORDER BY x;");
while( db_step(&move)==SQLITE_ROW ){
const char *zOldName = db_column_text(&move, 0);
const char *zNewName = db_column_text(&move, 1);
if( !dryRunFlag ){
| > > > > > > > | | | | | | > | 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 |
Stmt move;
if( db_table_exists(db_name("temp"), "fmove") ){
db_prepare(&move, "SELECT x, y FROM fmove ORDER BY x;");
while( db_step(&move)==SQLITE_ROW ){
const char *zOldName = db_column_text(&move, 0);
const char *zNewName = db_column_text(&move, 1);
if( !dryRunFlag ){
int isOldDir = file_isdir(zOldName);
if( isOldDir==1 ){
int isNewDir = file_isdir(zNewName);
if( isNewDir==0 ){
file_rename(zOldName, zNewName, isOldDir, isNewDir);
}
}else{
if( file_wd_islink(zOldName) ){
symlink_copy(zOldName, zNewName);
}else{
file_copy(zOldName, zNewName);
}
file_delete(zOldName);
}
}
fossil_print("MOVED_FILE %s\n", zOldName);
}
db_finalize(&move);
db_multi_exec("DROP TABLE fmove;");
}
}
|
| ︙ | ︙ |
Changes to src/allrepo.c.
| ︙ | ︙ | |||
85 86 87 88 89 90 91 | ** that can be useful before or after a period of disconnected operation. ** ** On Win32 systems, the file is named "_fossil" and is located in ** %LOCALAPPDATA%, %APPDATA% or %HOMEPATH%. ** ** Available operations are: ** | | | 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | ** that can be useful before or after a period of disconnected operation. ** ** On Win32 systems, the file is named "_fossil" and is located in ** %LOCALAPPDATA%, %APPDATA% or %HOMEPATH%. ** ** Available operations are: ** ** cache Manages the cache used for potentially expensive web ** pages. Any additional arguments are passed on verbatim ** to the cache command. ** ** changes Shows all local checkouts that have uncommitted changes. ** This operation has no additional options. ** ** clean Delete all "extra" files in all local checkouts. Extreme |
| ︙ | ︙ | |||
136 137 138 139 140 141 142 | ** unset conjunction with the "max-loadavg" setting which cannot ** otherwise be set globally. ** ** In addition, the following maintenance operations are supported: ** ** add Add all the repositories named to the set of repositories ** tracked by Fossil. Normally Fossil is able to keep up with | | | 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | ** unset conjunction with the "max-loadavg" setting which cannot ** otherwise be set globally. ** ** In addition, the following maintenance operations are supported: ** ** add Add all the repositories named to the set of repositories ** tracked by Fossil. Normally Fossil is able to keep up with ** this list by itself, but sometimes it can benefit from this ** hint if you rename repositories. ** ** ignore Arguments are repositories that should be ignored by ** subsequent clean, extras, list, pull, push, rebuild, and ** sync operations. The -c|--ckout option causes the listed ** local checkouts to be ignored instead. ** |
| ︙ | ︙ | |||
375 376 377 378 379 380 381 382 383 384 385 386 387 388 |
" ORDER BY 1"
);
}
db_multi_exec("CREATE TEMP TABLE todel(x TEXT)");
db_prepare(&q, "SELECT name, tag FROM repolist ORDER BY 1");
while( db_step(&q)==SQLITE_ROW ){
const char *zFilename = db_column_text(&q, 0);
if( file_access(zFilename, F_OK)
|| !file_is_canonical(zFilename)
|| (useCheckouts && file_isdir(zFilename)!=1)
){
db_multi_exec("INSERT INTO todel VALUES(%Q)", db_column_text(&q, 1));
nToDel++;
continue;
| > > > | 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 |
" ORDER BY 1"
);
}
db_multi_exec("CREATE TEMP TABLE todel(x TEXT)");
db_prepare(&q, "SELECT name, tag FROM repolist ORDER BY 1");
while( db_step(&q)==SQLITE_ROW ){
const char *zFilename = db_column_text(&q, 0);
#if !USE_SEE
if( sqlite3_strglob("*.efossil", zFilename)==0 ) continue;
#endif
if( file_access(zFilename, F_OK)
|| !file_is_canonical(zFilename)
|| (useCheckouts && file_isdir(zFilename)!=1)
){
db_multi_exec("INSERT INTO todel VALUES(%Q)", db_column_text(&q, 1));
nToDel++;
continue;
|
| ︙ | ︙ |
Changes to src/attach.c.
| ︙ | ︙ | |||
24 25 26 27 28 29 30 | /* ** WEBPAGE: attachlist ** List attachments. ** ** tkt=TICKETUUID ** page=WIKIPAGE ** | | | | | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
/*
** WEBPAGE: attachlist
** List attachments.
**
** tkt=TICKETUUID
** page=WIKIPAGE
**
** At most one of technote=, tkt= or page= are supplied.
** If none is given, all attachments are listed. If one is given,
** only attachments for the designated technote, ticket or wiki page
** are shown. TECHNOTEUUID and TICKETUUID may be just a prefix of the
** relevant technical note or ticket, in which case all attachments
** of all technical notes or tickets with the prefix will be listed.
*/
void attachlist_page(void){
const char *zPage = P("page");
const char *zTkt = P("tkt");
const char *zTechNote = P("technote");
Blob sql;
Stmt q;
|
| ︙ | ︙ | |||
84 85 86 87 88 89 90 |
const char *zSrc = db_column_text(&q, 1);
const char *zTarget = db_column_text(&q, 2);
const char *zFilename = db_column_text(&q, 3);
const char *zComment = db_column_text(&q, 4);
const char *zUser = db_column_text(&q, 5);
const char *zUuid = db_column_text(&q, 6);
int attachid = db_column_int(&q, 7);
| | | 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
const char *zSrc = db_column_text(&q, 1);
const char *zTarget = db_column_text(&q, 2);
const char *zFilename = db_column_text(&q, 3);
const char *zComment = db_column_text(&q, 4);
const char *zUser = db_column_text(&q, 5);
const char *zUuid = db_column_text(&q, 6);
int attachid = db_column_int(&q, 7);
/* type 0 is a wiki page, 1 is a ticket, 2 is a tech note */
int type = db_column_int(&q, 8);
const char *zDispUser = zUser && zUser[0] ? zUser : "anonymous";
int i;
char *zUrlTail;
for(i=0; zFilename[i]; i++){
if( zFilename[i]=='/' && zFilename[i+1]!=0 ){
zFilename = &zFilename[i+1];
|
| ︙ | ︙ | |||
107 108 109 110 111 112 113 |
zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename);
}
@ <li><p>
@ Attachment %z(href("%R/ainfo/%!S",zUuid))%S(zUuid)</a>
if( moderation_pending(attachid) ){
@ <span class="modpending">*** Awaiting Moderator Approval ***</span>
}
| | | 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename);
}
@ <li><p>
@ Attachment %z(href("%R/ainfo/%!S",zUuid))%S(zUuid)</a>
if( moderation_pending(attachid) ){
@ <span class="modpending">*** Awaiting Moderator Approval ***</span>
}
@ <br /><a href="%R/attachview?%s(zUrlTail)">%h(zFilename)</a>
@ [<a href="%R/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br />
if( zComment ) while( fossil_isspace(zComment[0]) ) zComment++;
if( zComment && zComment[0] ){
@ %!W(zComment)<br />
}
if( zPage==0 && zTkt==0 && zTechNote==0 ){
if( zSrc==0 || zSrc[0]==0 ){
|
| ︙ | ︙ | |||
244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
rid = content_put(pAttach);
db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d);", rid);
db_multi_exec("INSERT OR IGNORE INTO unclustered VALUES(%d);", rid);
}
manifest_crosslink(rid, pAttach, MC_NONE);
}
/*
** WEBPAGE: attachadd
** Add a new attachment.
**
** tkt=TICKETUUID
** page=WIKIPAGE
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
rid = content_put(pAttach);
db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d);", rid);
db_multi_exec("INSERT OR IGNORE INTO unclustered VALUES(%d);", rid);
}
manifest_crosslink(rid, pAttach, MC_NONE);
}
/*
** Commit a new attachment into the repository
*/
void attach_commit(
const char *zName, /* The filename of the attachment */
const char *zTarget, /* The artifact uuid to attach to */
const char *aContent, /* The content of the attachment */
int szContent, /* The length of the attachment */
int needModerator, /* Moderate the attachment? */
const char *zComment /* The comment for the attachment */
){
Blob content;
Blob manifest;
Blob cksum;
char *zUUID;
char *zDate;
int rid;
int i, n;
int addCompress = 0;
Manifest *pManifest;
db_begin_transaction();
blob_init(&content, aContent, szContent);
pManifest = manifest_parse(&content, 0, 0);
manifest_destroy(pManifest);
blob_init(&content, aContent, szContent);
if( pManifest ){
blob_compress(&content, &content);
addCompress = 1;
}
rid = content_put_ex(&content, 0, 0, 0, needModerator);
zUUID = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
blob_zero(&manifest);
for(i=n=0; zName[i]; i++){
if( zName[i]=='/' || zName[i]=='\\' ) n = i+1;
}
zName += n;
if( zName[0]==0 ) zName = "unknown";
blob_appendf(&manifest, "A %F%s %F %s\n",
zName, addCompress ? ".gz" : "", zTarget, zUUID);
while( fossil_isspace(zComment[0]) ) zComment++;
n = strlen(zComment);
while( n>0 && fossil_isspace(zComment[n-1]) ){ n--; }
if( n>0 ){
blob_appendf(&manifest, "C %#F\n", n, zComment);
}
zDate = date_in_standard_format("now");
blob_appendf(&manifest, "D %s\n", zDate);
blob_appendf(&manifest, "U %F\n", login_name());
md5sum_blob(&manifest, &cksum);
blob_appendf(&manifest, "Z %b\n", &cksum);
attach_put(&manifest, rid, needModerator);
assert( blob_is_reset(&manifest) );
db_end_transaction(0);
}
/*
** WEBPAGE: attachadd
** Add a new attachment.
**
** tkt=TICKETUUID
** page=WIKIPAGE
|
| ︙ | ︙ | |||
298 299 300 301 302 303 304 |
}
if( !db_exists("SELECT 1 FROM tag WHERE tagname='event-%q'", zTechNote) ){
zTechNote = db_text(0, "SELECT substr(tagname,7) FROM tag"
" WHERE tagname GLOB 'event-%q*'", zTechNote);
if( zTechNote==0) fossil_redirect_home();
}
zTarget = zTechNote;
| | | < < < < < < < < < < < < < < < < < < < < < < | | < < < < < < < < < < | < | < < < < < < < < < < < < | 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 |
}
if( !db_exists("SELECT 1 FROM tag WHERE tagname='event-%q'", zTechNote) ){
zTechNote = db_text(0, "SELECT substr(tagname,7) FROM tag"
" WHERE tagname GLOB 'event-%q*'", zTechNote);
if( zTechNote==0) fossil_redirect_home();
}
zTarget = zTechNote;
zTargetType = mprintf("Tech Note <a href=\"%R/technote/%s\">%S</a>",
zTechNote, zTechNote);
}else{
if( g.perm.ApndTkt==0 || g.perm.Attach==0 ){
login_needed(g.anon.ApndTkt && g.anon.Attach);
return;
}
if( !db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'", zTkt) ){
zTkt = db_text(0, "SELECT substr(tagname,5) FROM tag"
" WHERE tagname GLOB 'tkt-%q*'", zTkt);
if( zTkt==0 ) fossil_redirect_home();
}
zTarget = zTkt;
zTargetType = mprintf("Ticket <a href=\"%R/tktview/%s\">%S</a>",
zTkt, zTkt);
}
if( zFrom==0 ) zFrom = mprintf("%s/home", g.zTop);
if( P("cancel") ){
cgi_redirect(zFrom);
}
if( P("ok") && szContent>0 && (goodCaptcha = captcha_is_correct()) ){
int needModerator = (zTkt!=0 && ticket_need_moderation(0)) ||
(zPage!=0 && wiki_need_moderation(0));
const char *zComment = PD("comment", "");
attach_commit(zName, zTarget, aContent, szContent, needModerator, zComment);
cgi_redirect(zFrom);
}
style_header("Add Attachment");
if( !goodCaptcha ){
@ <p class="generalError">Error: Incorrect security code.</p>
}
@ <h2>Add Attachment To %s(zTargetType)</h2>
|
| ︙ | ︙ | |||
480 481 482 483 484 485 486 |
if( g.perm.Write && g.perm.WrWiki ){
style_submenu_element("Delete","Delete","%R/ainfo/%s?del", zUuid);
}
}
zDate = db_text(0, "SELECT datetime(%.12f)", pAttach->rDate);
if( P("confirm")
| | | 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 |
if( g.perm.Write && g.perm.WrWiki ){
style_submenu_element("Delete","Delete","%R/ainfo/%s?del", zUuid);
}
}
zDate = db_text(0, "SELECT datetime(%.12f)", pAttach->rDate);
if( P("confirm")
&& ((zTktUuid && g.perm.WrTkt) ||
(zWikiName && g.perm.WrWiki) ||
(zTNUuid && g.perm.Write && g.perm.WrWiki))
){
int i, n, rid;
char *zDate;
Blob manifest;
Blob cksum;
|
| ︙ | ︙ | |||
614 615 616 617 618 619 620 |
}else{
@ <pre>
@ %h(z)
@ </pre>
}
}else if( strncmp(zMime, "image/", 6)==0 ){
int sz = db_int(0, "SELECT size FROM blob WHERE rid=%d", ridSrc);
| | | 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 |
}else{
@ <pre>
@ %h(z)
@ </pre>
}
}else if( strncmp(zMime, "image/", 6)==0 ){
int sz = db_int(0, "SELECT size FROM blob WHERE rid=%d", ridSrc);
@ <i>(file is %d(sz) bytes of image data)</i><br />
@ <img src="%R/raw/%s(zSrc)?m=%s(zMime)"></img>
style_submenu_element("Image", "Image", "%R/raw/%s?m=%s", zSrc, zMime);
}else{
int sz = db_int(0, "SELECT size FROM blob WHERE rid=%d", ridSrc);
@ <i>(file is %d(sz) bytes of binary data)</i>
}
@ </blockquote>
|
| ︙ | ︙ | |||
668 669 670 671 672 673 674 |
}
if( cnt ){
@ </ul>
}
db_finalize(&q);
}
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
}
if( cnt ){
@ </ul>
}
db_finalize(&q);
}
/*
** COMMAND: attachment*
**
** Usage: %fossil attachment add ?PAGENAME? FILENAME ?OPTIONS?
**
** Add an attachment to an existing wiki page or tech note.
**
** Options:
** -t|--technote DATETIME Specifies the timestamp of
** the technote to which the attachment
** is to be made. The attachment will be
** to the most recently modified tech note
** with the specified timestamp.
** -t|--technote TECHNOTE-ID Specifies the technote to be
** updated by its technote id.
**
** One of PAGENAME, DATETIME or TECHNOTE-ID must be specified.
*/
void attachment_cmd(void){
int n;
db_find_and_open_repository(0, 0);
if( g.argc<3 ){
goto attachment_cmd_usage;
}
n = strlen(g.argv[2]);
if( n==0 ){
goto attachment_cmd_usage;
}
if( strncmp(g.argv[2],"add",n)==0 ){
const char *zPageName = 0; /* Name of the wiki page to attach to */
const char *zFile; /* Name of the file to be attached */
const char *zETime; /* The name of the technote to attach to */
Manifest *pWiki = 0; /* Parsed wiki page content */
char *zBody = 0; /* Wiki page content */
int rid;
const char *zTarget; /* Target of the attachment */
Blob content; /* The content of the attachment */
zETime = find_option("technote","t",1);
if( !zETime ){
if( g.argc!=5 ){
usage("add PAGENAME FILENAME");
}
zPageName = g.argv[3];
rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x"
" WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
" ORDER BY x.mtime DESC LIMIT 1",
zPageName
);
if( (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0 ){
zBody = pWiki->zWiki;
}
if( zBody==0 ){
fossil_fatal("wiki page [%s] not found",zPageName);
}
zTarget = zPageName;
zFile = g.argv[4];
}else{
if( g.argc!=4 ){
usage("add FILENAME --technote DATETIME|TECHNOTE-ID");
}
rid = wiki_technote_to_rid(zETime);
if( rid<0 ){
fossil_fatal("ambiguous tech note id: %s", zETime);
}
if( (pWiki = manifest_get(rid, CFTYPE_EVENT, 0))!=0 ){
zBody = pWiki->zWiki;
}
if( zBody==0 ){
fossil_fatal("technote [%s] not found",zETime);
}
zTarget = db_text(0,
"SELECT substr(tagname,7) FROM tag WHERE tagid=(SELECT tagid FROM event WHERE objid='%d')",
rid
);
zFile = g.argv[3];
}
blob_read_from_file(&content, zFile);
user_select();
attach_commit(
zFile, /* The filename of the attachment */
zTarget, /* The artifact uuid to attach to */
blob_buffer(&content), /* The content of the attachment */
blob_size(&content), /* The length of the attachment */
0, /* No need to moderate the attachment */
"" /* Empty attachment comment */
);
if( !zETime ){
fossil_print("Attached %s to wiki page %s.\n", zFile, zPageName);
}else{
fossil_print("Attached %s to tech note %s.\n", zFile, zETime);
}
}else{
goto attachment_cmd_usage;
}
return;
attachment_cmd_usage:
usage("add ?PAGENAME? FILENAME [-t|--technote DATETIME ]");
}
|
Changes to src/bisect.c.
| ︙ | ︙ | |||
429 430 431 432 433 434 435 |
break;
}
}
if( i>=sizeof(aBisectOption)/sizeof(aBisectOption[0]) ){
fossil_fatal("no such bisect option: %s", g.argv[3]);
}
}else{
| | | 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 |
break;
}
}
if( i>=sizeof(aBisectOption)/sizeof(aBisectOption[0]) ){
fossil_fatal("no such bisect option: %s", g.argv[3]);
}
}else{
usage("options ?NAME? ?VALUE?");
}
}else if( strncmp(zCmd, "reset", n)==0 ){
db_multi_exec(
"DELETE FROM vvar WHERE name IN "
" ('bisect-good', 'bisect-bad', 'bisect-log')"
);
}else if( strcmp(zCmd, "ui")==0 ){
|
| ︙ | ︙ |
Changes to src/blob.c.
| ︙ | ︙ | |||
117 118 119 120 121 122 123 | return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9'); } /* ** COMMAND: test-isspace ** | | | 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9');
}
/*
** COMMAND: test-isspace
**
** Verify that the fossil_isspace() routine is working correctly by
** testing it on all possible inputs.
*/
void isspace_cmd(void){
int i;
for(i=0; i<=255; i++){
if( i==' ' || i=='\n' || i=='\t' || i=='\v'
|| i=='\f' || i=='\r' ){
|
| ︙ | ︙ | |||
651 652 653 654 655 656 657 |
/*
** Return true if the blob contains a valid UUID_SIZE-digit base16 identifier.
*/
int blob_is_uuid(Blob *pBlob){
return blob_size(pBlob)==UUID_SIZE
&& validate16(blob_buffer(pBlob), UUID_SIZE);
}
| < < < | 651 652 653 654 655 656 657 658 659 660 661 662 663 664 |
/*
** Return true if the blob contains a valid UUID_SIZE-digit base16 identifier.
*/
int blob_is_uuid(Blob *pBlob){
return blob_size(pBlob)==UUID_SIZE
&& validate16(blob_buffer(pBlob), UUID_SIZE);
}
/*
** Return true if the blob contains a valid 32-bit integer. Store
** the integer value in *pValue.
*/
int blob_is_int(Blob *pBlob, int *pValue){
const char *z = blob_buffer(pBlob);
|
| ︙ | ︙ |
Changes to src/branch.c.
| ︙ | ︙ | |||
174 175 176 177 178 179 180 | } /* Commit */ db_end_transaction(0); /* Do an autosync push, if requested */ | | | 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
}
/* Commit */
db_end_transaction(0);
/* Do an autosync push, if requested */
if( !isPrivate ) autosync_loop(SYNC_PUSH, db_get_int("autosync-tries",1),0);
}
#if INTERFACE
/*
** Allows bits in the mBplqFlags parameter to branch_prepare_list_query().
*/
#define BRL_CLOSED_ONLY 0x001 /* Show only closed branches */
|
| ︙ | ︙ |
Changes to src/browse.c.
| ︙ | ︙ | |||
977 978 979 980 981 982 983 |
*/
void test_fileage_cmd(void){
int mid;
Stmt q;
const char *zGlob = find_option("glob",0,1);
db_find_and_open_repository(0,0);
verify_all_options();
| | | | 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 |
*/
void test_fileage_cmd(void){
int mid;
Stmt q;
const char *zGlob = find_option("glob",0,1);
db_find_and_open_repository(0,0);
verify_all_options();
if( g.argc!=3 ) usage("CHECKIN");
mid = name_to_typed_rid(g.argv[2],"ci");
compute_fileage(mid, zGlob);
db_prepare(&q,
"SELECT fid, mid, julianday('now') - mtime, pathname"
" FROM fileage"
);
while( db_step(&q)==SQLITE_ROW ){
char *zAge = human_readable_age(db_column_double(&q,2));
fossil_print("%8d %8d %16s %s\n",
db_column_int(&q,0),
db_column_int(&q,1),
zAge,
db_column_text(&q,3));
fossil_free(zAge);
}
db_finalize(&q);
}
/*
** WEBPAGE: fileage
**
** Show all files in a single check-in (identified by the name= query
** parameter) in order of increasing age.
**
** Parameters:
** name=VERSION Selects the check-in version (default=tip).
** glob=STRING Only shows files matching this glob pattern
|
| ︙ | ︙ | |||
1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 |
const char *zUuid;
const char *zNow; /* Time of check-in */
int showId = PB("showid");
Stmt q1, q2;
double baseTime;
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
zName = P("name");
if( zName==0 ) zName = "tip";
rid = symbolic_name_to_rid(zName, "ci");
if( rid==0 ){
fossil_fatal("not a valid check-in: %s", zName);
}
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
| > | 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 |
const char *zUuid;
const char *zNow; /* Time of check-in */
int showId = PB("showid");
Stmt q1, q2;
double baseTime;
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
if( exclude_spiders() ) return;
zName = P("name");
if( zName==0 ) zName = "tip";
rid = symbolic_name_to_rid(zName, "ci");
if( rid==0 ){
fossil_fatal("not a valid check-in: %s", zName);
}
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
|
| ︙ | ︙ | |||
1085 1086 1087 1088 1089 1090 1091 |
@ <td>
db_bind_int(&q2, ":mid", mid);
while( db_step(&q2)==SQLITE_ROW ){
const char *zFUuid = db_column_text(&q2,0);
const char *zFile = db_column_text(&q2,1);
int fid = db_column_int(&q2,2);
if( showId ){
| | | | 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 |
@ <td>
db_bind_int(&q2, ":mid", mid);
while( db_step(&q2)==SQLITE_ROW ){
const char *zFUuid = db_column_text(&q2,0);
const char *zFile = db_column_text(&q2,1);
int fid = db_column_int(&q2,2);
if( showId ){
@ %z(href("%R/artifact/%!S",zFUuid))%h(zFile)</a> (%d(fid))<br />
}else{
@ %z(href("%R/artifact/%!S",zFUuid))%h(zFile)</a><br />
}
}
db_reset(&q2);
@ </td>
@ <td>
@ %z(href("%R/info/%!S",zUuid))[%S(zUuid)]</a>
if( showId ){
|
| ︙ | ︙ |
Changes to src/builtin.c.
| ︙ | ︙ | |||
54 55 56 57 58 59 60 |
const char *builtin_text(const char *zFilename){
return (char*)builtin_file(zFilename, 0);
}
/*
** COMMAND: test-builtin-list
**
| | | 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
const char *builtin_text(const char *zFilename){
return (char*)builtin_file(zFilename, 0);
}
/*
** COMMAND: test-builtin-list
**
** List the names and sizes of all built-in resources.
*/
void test_builtin_list(void){
int i;
for(i=0; i<sizeof(aBuiltinFiles)/sizeof(aBuiltinFiles[0]); i++){
fossil_print("%-30s %6d\n", aBuiltinFiles[i].zName,aBuiltinFiles[i].nByte);
}
}
|
| ︙ | ︙ |
Changes to src/bundle.c.
| ︙ | ︙ | |||
24 25 26 27 28 29 30 | /* ** SQL code used to initialize the schema of a bundle. ** ** The bblob.delta field can be an integer, a text string, or NULL. ** If an integer, then the corresponding blobid is the delta basis. ** If a text string, then that string is a SHA1 hash for the delta ** basis, which is presumably in the master repository. If NULL, then | | | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | /* ** SQL code used to initialize the schema of a bundle. ** ** The bblob.delta field can be an integer, a text string, or NULL. ** If an integer, then the corresponding blobid is the delta basis. ** If a text string, then that string is a SHA1 hash for the delta ** basis, which is presumably in the master repository. If NULL, then ** data contains content without delta compression. */ static const char zBundleInit[] = @ CREATE TABLE IF NOT EXISTS "%w".bconfig( @ bcname TEXT, @ bcvalue ANY @ ); @ CREATE TABLE IF NOT EXISTS "%w".bblob( |
| ︙ | ︙ | |||
368 369 370 371 372 373 374 |
deltaFrom = db_int(0,
"SELECT max(fid) FROM mlink"
" WHERE fnid=(SELECT fnid FROM mlink WHERE fid=%d)"
" AND fid<%d", rid, mnToBundle);
}
}
| | | 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 |
deltaFrom = db_int(0,
"SELECT max(fid) FROM mlink"
" WHERE fnid=(SELECT fnid FROM mlink WHERE fid=%d)"
" AND fid<%d", rid, mnToBundle);
}
}
/* Try to insert the artifact as a delta
*/
if( deltaFrom ){
Blob basis, delta;
content_get(deltaFrom, &basis);
blob_delta_create(&basis, &content, &delta);
if( blob_size(&delta)>0.9*blob_size(&content) ){
deltaFrom = 0;
|
| ︙ | ︙ |
Changes to src/cache.c.
| ︙ | ︙ | |||
235 236 237 238 239 240 241 242 243 244 245 246 247 248 |
*/
void cache_initialize(void){
sqlite3_close(cacheOpen(1));
}
/*
** COMMAND: cache*
** Usage: %fossil cache SUBCOMMAND
**
** Manage the cache used for potentially expensive web pages such as
** /zip and /tarball. SUBCOMMAND can be:
**
** clear Remove all entries from the cache.
**
| > | | | | 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 |
*/
void cache_initialize(void){
sqlite3_close(cacheOpen(1));
}
/*
** COMMAND: cache*
**
** Usage: %fossil cache SUBCOMMAND
**
** Manage the cache used for potentially expensive web pages such as
** /zip and /tarball. SUBCOMMAND can be:
**
** clear Remove all entries from the cache.
**
** init Create the cache file if it does not already exist.
**
** list|ls List the keys and content sizes and other stats for
** all entries currently in the cache.
**
** status Show a summary of the cache status.
**
** The cache is stored in a file that is distinct from the repository
** but that is held in the same directory as the repository. The cache
** file can be deleted in order to completely disable the cache.
*/
void cache_cmd(void){
const char *zCmd;
|
| ︙ | ︙ | |||
353 354 355 356 357 358 359 |
" FROM cache"
" ORDER BY tm DESC"
);
if( pStmt ){
@ <ol>
while( sqlite3_step(pStmt)==SQLITE_ROW ){
const unsigned char *zName = sqlite3_column_text(pStmt,0);
| | | 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 |
" FROM cache"
" ORDER BY tm DESC"
);
if( pStmt ){
@ <ol>
while( sqlite3_step(pStmt)==SQLITE_ROW ){
const unsigned char *zName = sqlite3_column_text(pStmt,0);
@ <li><p>%z(href("%R/cacheget?key=%T",zName))%h(zName)</a><br />
@ size: %s(sqlite3_column_text(pStmt,1))
@ hit-count: %d(sqlite3_column_int(pStmt,2))
@ last-access: %s(sqlite3_column_text(pStmt,3))</p></li>
}
sqlite3_finalize(pStmt);
@ </ol>
}
|
| ︙ | ︙ |
Changes to src/captcha.c.
| ︙ | ︙ | |||
576 577 578 579 580 581 582 | /* ** Check to see if the current request is coming from an agent that might ** be a spider. If the agent is not a spider, then return 0 without doing ** anything. But if the user agent appears to be a spider, offer ** a captcha challenge to allow the user agent to prove that it is human ** and return non-zero. */ | | | 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 |
/*
** Check to see if the current request is coming from an agent that might
** be a spider. If the agent is not a spider, then return 0 without doing
** anything. But if the user agent appears to be a spider, offer
** a captcha challenge to allow the user agent to prove that it is human
** and return non-zero.
*/
int exclude_spiders(void){
const char *zCookieValue;
char *zCookieName;
if( g.isHuman ) return 0;
#if 0
{
const char *zReferer = P("HTTP_REFERER");
if( zReferer && strncmp(g.zBaseURL, zReferer, strlen(g.zBaseURL))==0 ){
|
| ︙ | ︙ | |||
598 599 600 601 602 603 604 |
if( captcha_is_correct() ){
cgi_set_cookie(zCookieName, "1", login_cookie_path(), 8*3600);
return 0;
}
/* This appears to be a spider. Offer the captcha */
style_header("Verification");
| | | 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 |
if( captcha_is_correct() ){
cgi_set_cookie(zCookieName, "1", login_cookie_path(), 8*3600);
return 0;
}
/* This appears to be a spider. Offer the captcha */
style_header("Verification");
@ <form method='POST' action='%s(g.zPath)'>
cgi_query_parameters_to_hidden();
@ <p>Please demonstrate that you are human, not a spider or robot</p>
captcha_generate(1);
@ </form>
style_footer();
return 1;
}
|
Changes to src/checkin.c.
| ︙ | ︙ | |||
544 545 546 547 548 549 550 551 552 |
blob_reset(&name);
}
}
}
/*
** COMMAND: extras
** Usage: %fossil extras ?OPTIONS? ?PATH1 ...?
**
| > | | | | | | | 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 |
blob_reset(&name);
}
}
}
/*
** COMMAND: extras
**
** Usage: %fossil extras ?OPTIONS? ?PATH1 ...?
**
** Print a list of all files in the source tree that are not part of the
** current checkout. See also the "clean" command. If paths are specified,
** only files in the given directories will be listed.
**
** Files and subdirectories whose names begin with "." are normally
** ignored but can be included by adding the --dotfiles option.
**
** Files whose names match any of the glob patterns in the "ignore-glob"
** setting are ignored. This setting can be overridden by the --ignore
** option, whose CSG argument is a comma-separated list of glob patterns.
**
** Pathnames are displayed according to the "relative-paths" setting,
** unless overridden by the --abs-paths or --rel-paths options.
**
** Options:
** --abs-paths Display absolute pathnames.
** --case-sensitive <BOOL> override case-sensitive setting
|
| ︙ | ︙ | |||
629 630 631 632 633 634 635 636 637 | } blob_reset(&rewrittenPathname); db_finalize(&q); } /* ** COMMAND: clean ** Usage: %fossil clean ?OPTIONS? ?PATH ...? ** | > | | | | < | > > > > > | > > | > > | > > > | | < < | | | | | 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 | } blob_reset(&rewrittenPathname); db_finalize(&q); } /* ** COMMAND: clean ** ** Usage: %fossil clean ?OPTIONS? ?PATH ...? ** ** Delete all "extra" files in the source tree. "Extra" files are files ** that are not officially part of the checkout. If one or more PATH ** arguments appear, then only the files named, or files contained with ** directories named, will be removed. ** ** If the --prompt option is used, prompts are issued to confirm the ** permanent removal of each file. Otherwise, files are backed up to the ** undo buffer prior to removal, and prompts are issued only for files ** whose removal cannot be undone due to their large size or due to ** --disable-undo being used. ** ** The --force option treats all prompts as having been answered yes, ** whereas --no-prompt treats them as having been answered no. ** ** Files matching any glob pattern specified by the --clean option are ** deleted without prompting, and the removal cannot be undone. ** ** No file that matches glob patterns specified by --ignore or --keep will ** ever be deleted. Files and subdirectories whose names begin with "." ** are automatically ignored unless the --dotfiles option is used. ** ** The default values for --clean, --ignore, and --keep are determined by ** the (versionable) clean-glob, ignore-glob, and keep-glob settings. ** ** The --verily option ignores the keep-glob and ignore-glob settings and ** turns on --force, --emptydirs, --dotfiles, and --disable-undo. Use the ** --verily option when you really want to clean up everything. Extreme ** care should be exercised when using the --verily option. ** ** Options: ** --allckouts Check for empty directories within any checkouts ** that may be nested within the current one. This ** option should be used with great care because the ** empty-dirs setting (and other applicable settings) ** belonging to the other repositories, if any, will |
| ︙ | ︙ | |||
674 675 676 677 678 679 680 | ** explicitly exempted via the empty-dirs setting ** or another applicable setting or command line ** argument. Matching files, if any, are removed ** prior to checking for any empty directories; ** therefore, directories that contain only files ** that were removed will be removed as well. ** -f|--force Remove files without prompting. | | > | 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 | ** explicitly exempted via the empty-dirs setting ** or another applicable setting or command line ** argument. Matching files, if any, are removed ** prior to checking for any empty directories; ** therefore, directories that contain only files ** that were removed will be removed as well. ** -f|--force Remove files without prompting. ** -i|--prompt Prompt before removing each file. This option ** implies the --disable-undo option. ** -x|--verily WARNING: Removes everything that is not a managed ** file or the repository itself. This option ** implies the --force, --emptydirs, --dotfiles, and ** --disable-undo options. Furthermore, it completely ** disregards the keep-glob and ignore-glob settings. ** However, it does honor the --ignore and --keep ** options. |
| ︙ | ︙ | |||
1800 1801 1802 1803 1804 1805 1806 |
g.markPrivate = 1;
}
/*
** Autosync if autosync is enabled and this is not a private check-in.
*/
if( !g.markPrivate ){
| | < < < | < | 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 |
g.markPrivate = 1;
}
/*
** Autosync if autosync is enabled and this is not a private check-in.
*/
if( !g.markPrivate ){
if( autosync_loop(SYNC_PULL, db_get_int("autosync-tries", 1), 1) ){
fossil_exit(1);
}
}
/* Require confirmation to continue with the check-in if there is
** clock skew
*/
if( g.clockSkewSeen ){
|
| ︙ | ︙ | |||
2232 2233 2234 2235 2236 2237 2238 |
get_checkin_taglist(nvid, &tagslist);
blob_write_to_file(&tagslist, zManifestFile);
blob_reset(&tagslist);
free(zManifestFile);
}
if( !g.markPrivate ){
| | | 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 |
get_checkin_taglist(nvid, &tagslist);
blob_write_to_file(&tagslist, zManifestFile);
blob_reset(&tagslist);
free(zManifestFile);
}
if( !g.markPrivate ){
autosync_loop(SYNC_PUSH|SYNC_PULL, db_get_int("autosync-tries", 1), 0);
}
if( count_nonbranch_children(vid)>1 ){
fossil_print("**** warning: a fork has occurred *****\n");
}
}
|
Changes to src/checkout.c.
| ︙ | ︙ | |||
327 328 329 330 331 332 333 | /* ** COMMAND: close* ** ** Usage: %fossil close ?OPTIONS? ** ** The opposite of "open". Close the current database connection. | | | 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 | /* ** COMMAND: close* ** ** Usage: %fossil close ?OPTIONS? ** ** The opposite of "open". Close the current database connection. ** Require a -f or --force flag if there are unsaved changes in the ** current check-out or if there is non-empty stash. ** ** Options: ** --force|-f necessary to close a check out with uncommitted changes ** ** See also: open */ |
| ︙ | ︙ |
Changes to src/config.h.
| ︙ | ︙ | |||
97 98 99 100 101 102 103 104 105 106 107 108 109 110 | # else # if defined(COMPILER_VERSION) && !defined(NO_COMPILER_VERSION) # define COMPILER_NAME "pellesc32-" COMPILER_VERSION # else # define COMPILER_NAME "pellesc32" # endif # endif # elif defined(_MSC_VER) # if !defined(COMPILER_VERSION) # define COMPILER_VERSION COMPILER_STRINGIFY(_MSC_VER) # endif # if defined(COMPILER_VERSION) && !defined(NO_COMPILER_VERSION) # define COMPILER_NAME "msc-" COMPILER_VERSION # else | > > > > > > > > > > > | 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 | # else # if defined(COMPILER_VERSION) && !defined(NO_COMPILER_VERSION) # define COMPILER_NAME "pellesc32-" COMPILER_VERSION # else # define COMPILER_NAME "pellesc32" # endif # endif # elif defined(__clang__) # if !defined(COMPILER_VERSION) # if defined(__clang_version__) # define COMPILER_VERSION __clang_version__ # endif # endif # if defined(COMPILER_VERSION) && !defined(NO_COMPILER_VERSION) # define COMPILER_NAME "clang-" COMPILER_VERSION # else # define COMPILER_NAME "clang" # endif # elif defined(_MSC_VER) # if !defined(COMPILER_VERSION) # define COMPILER_VERSION COMPILER_STRINGIFY(_MSC_VER) # endif # if defined(COMPILER_VERSION) && !defined(NO_COMPILER_VERSION) # define COMPILER_NAME "msc-" COMPILER_VERSION # else |
| ︙ | ︙ | |||
135 136 137 138 139 140 141 | # endif # endif # if defined(COMPILER_VERSION) && !defined(NO_COMPILER_VERSION) # define COMPILER_NAME "mingw32-" COMPILER_VERSION # else # define COMPILER_NAME "mingw32" # endif | < < > > | 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 | # endif # endif # if defined(COMPILER_VERSION) && !defined(NO_COMPILER_VERSION) # define COMPILER_NAME "mingw32-" COMPILER_VERSION # else # define COMPILER_NAME "mingw32" # endif # elif defined(__GNUC__) # if !defined(COMPILER_VERSION) # if defined(__VERSION__) # define COMPILER_VERSION __VERSION__ # endif # endif # if defined(COMPILER_VERSION) && !defined(NO_COMPILER_VERSION) # define COMPILER_NAME "gcc-" COMPILER_VERSION # else # define COMPILER_NAME "gcc" # endif # elif defined(_WIN32) # define COMPILER_NAME "win32" # else # define COMPILER_NAME "unknown" # endif #endif #if !defined(_RC_COMPILE_) && !defined(SQLITE_AMALGAMATION) |
| ︙ | ︙ |
Changes to src/configure.c.
| ︙ | ︙ | |||
828 829 830 831 832 833 834 | /* ** COMMAND: configuration* ** ** Usage: %fossil configuration METHOD ... ?OPTIONS? ** ** Where METHOD is one of: export import merge pull push reset. All methods | | | 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 | /* ** COMMAND: configuration* ** ** Usage: %fossil configuration METHOD ... ?OPTIONS? ** ** Where METHOD is one of: export import merge pull push reset. All methods ** accept the -R or --repository option to specify a repository. ** ** %fossil configuration export AREA FILENAME ** ** Write to FILENAME exported configuration information for AREA. ** AREA can be one of: all email project shun skin ticket user ** ** %fossil configuration import FILENAME |
| ︙ | ︙ |
Changes to src/content.c.
| ︙ | ︙ | |||
280 281 282 283 284 285 286 |
}
mx = n;
rc = content_get(a[n], pBlob);
n--;
while( rc && n>=0 ){
rc = content_of_blob(a[n], &delta);
if( rc ){
| | > > | | | | | | | > | 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 |
}
mx = n;
rc = content_get(a[n], pBlob);
n--;
while( rc && n>=0 ){
rc = content_of_blob(a[n], &delta);
if( rc ){
if( blob_delta_apply(pBlob, &delta, &next)<0 ){
rc = 1;
}else{
blob_reset(&delta);
if( (mx-n)%8==0 ){
content_cache_insert(a[n+1], pBlob);
}else{
blob_reset(pBlob);
}
*pBlob = next;
}
}
n--;
}
free(a);
if( !rc ) blob_reset(pBlob);
}
if( rc==0 ){
|
| ︙ | ︙ | |||
332 333 334 335 336 337 338 |
fossil_fatal("%s",g.zErrMsg);
}
content_get(rid, &content);
blob_write_to_file(&content, zFile);
}
/*
| | | 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 |
fossil_fatal("%s",g.zErrMsg);
}
content_get(rid, &content);
blob_write_to_file(&content, zFile);
}
/*
** COMMAND: test-content-rawget
**
** Extract a blob from the database and write it into a file. This
** version does not expand the delta.
*/
void test_content_rawget_cmd(void){
int rid;
Blob content;
|
| ︙ | ︙ | |||
661 662 663 664 665 666 667 | bag_insert(&contentCache.missing, rid); db_end_transaction(0); return rid; } /* | | | 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 |
bag_insert(&contentCache.missing, rid);
db_end_transaction(0);
return rid;
}
/*
** COMMAND: test-content-put
**
** Usage: %fossil test-content-put FILE
**
** Read the content of FILE and add it to the Blob table as a new
** artifact using a direct call to content_put().
*/
void test_content_put_cmd(void){
|
| ︙ | ︙ | |||
701 702 703 704 705 706 707 |
blob_reset(&x);
db_multi_exec("DELETE FROM delta WHERE rid=%d", rid);
}
}
}
/*
| | | 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 |
blob_reset(&x);
db_multi_exec("DELETE FROM delta WHERE rid=%d", rid);
}
}
}
/*
** COMMAND: test-content-undelta
**
** Make sure the content at RECORDID is not a delta
*/
void test_content_undelta_cmd(void){
int rid;
if( g.argc!=3 ) usage("RECORDID");
db_must_be_within_tree();
|
| ︙ | ︙ | |||
812 813 814 815 816 817 818 | blob_reset(&src); blob_reset(&data); blob_reset(&delta); return rc; } /* | | | 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 |
blob_reset(&src);
blob_reset(&data);
blob_reset(&delta);
return rc;
}
/*
** COMMAND: test-content-deltify
**
** Convert the content at RID into a delta from SRCID.
*/
void test_content_deltify_cmd(void){
if( g.argc!=5 ) usage("RID SRCID FORCE");
db_must_be_within_tree();
content_deltify(atoi(g.argv[2]), atoi(g.argv[3]), atoi(g.argv[4]));
|
| ︙ | ︙ | |||
958 959 960 961 962 963 964 |
fossil_print("low-level database integrity-check: ");
fossil_print("%s\n", db_text(0, "PRAGMA integrity_check(10)"));
}
/*
** COMMAND: test-orphans
**
| | | 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 |
fossil_print("low-level database integrity-check: ");
fossil_print("%s\n", db_text(0, "PRAGMA integrity_check(10)"));
}
/*
** COMMAND: test-orphans
**
** Search the repository for orphaned artifacts.
*/
void test_orphans(void){
Stmt q;
int cnt = 0;
db_find_and_open_repository(0, 0);
db_multi_exec(
|
| ︙ | ︙ |
Changes to src/cson_amalgamation.c.
| ︙ | ︙ | |||
17 18 19 20 21 22 23 | # ifdef _MSC_VER # ifdef JSON_PARSER_DLL_EXPORTS # define JSON_PARSER_DLL_API __declspec(dllexport) # else # define JSON_PARSER_DLL_API __declspec(dllimport) # endif # else | | | | | | | | | | | | | | 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 |
# ifdef _MSC_VER
# ifdef JSON_PARSER_DLL_EXPORTS
# define JSON_PARSER_DLL_API __declspec(dllexport)
# else
# define JSON_PARSER_DLL_API __declspec(dllimport)
# endif
# else
# define JSON_PARSER_DLL_API
# endif
#else
# define JSON_PARSER_DLL_API
#endif
/* Determine the integer type use to parse non-floating point numbers */
#ifdef _WIN32
typedef __int64 JSON_int_t;
#define JSON_PARSER_INTEGER_SSCANF_TOKEN "%I64d"
#define JSON_PARSER_INTEGER_SPRINTF_TOKEN "%I64d"
#elif (__STDC_VERSION__ >= 199901L) || (HAVE_LONG_LONG == 1)
typedef long long JSON_int_t;
#define JSON_PARSER_INTEGER_SSCANF_TOKEN "%lld"
#define JSON_PARSER_INTEGER_SPRINTF_TOKEN "%lld"
#else
typedef long JSON_int_t;
#define JSON_PARSER_INTEGER_SSCANF_TOKEN "%ld"
#define JSON_PARSER_INTEGER_SPRINTF_TOKEN "%ld"
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef enum
{
JSON_E_NONE = 0,
JSON_E_INVALID_CHAR,
JSON_E_INVALID_KEYWORD,
JSON_E_INVALID_ESCAPE_SEQUENCE,
JSON_E_INVALID_UNICODE_SEQUENCE,
JSON_E_INVALID_NUMBER,
JSON_E_NESTING_DEPTH_REACHED,
JSON_E_UNBALANCED_COLLECTION,
JSON_E_EXPECTED_KEY,
JSON_E_EXPECTED_COLON,
JSON_E_OUT_OF_MEMORY
} JSON_error;
typedef enum
{
JSON_T_NONE = 0,
JSON_T_ARRAY_BEGIN,
JSON_T_ARRAY_END,
JSON_T_OBJECT_BEGIN,
JSON_T_OBJECT_END,
JSON_T_INTEGER,
JSON_T_FLOAT,
JSON_T_NULL,
JSON_T_TRUE,
JSON_T_FALSE,
JSON_T_STRING,
JSON_T_KEY,
JSON_T_MAX
} JSON_type;
typedef struct JSON_value_struct {
union {
JSON_int_t integer_value;
double float_value;
struct {
const char* value;
size_t length;
} str;
} vu;
} JSON_value;
typedef struct JSON_parser_struct* JSON_parser;
/*! \brief JSON parser callback
\param ctx The pointer passed to new_JSON_parser.
\param type An element of JSON_type but not JSON_T_NONE.
\param value A representation of the parsed value. This parameter is NULL for
JSON_T_ARRAY_BEGIN, JSON_T_ARRAY_END, JSON_T_OBJECT_BEGIN, JSON_T_OBJECT_END,
JSON_T_NULL, JSON_T_TRUE, and JSON_T_FALSE. String values are always returned
as zero-terminated C strings.
\return Non-zero if parsing should continue, else zero.
*/
typedef int (*JSON_parser_callback)(void* ctx, int type, const JSON_value* value);
/**
A typedef for allocator functions semantically compatible with malloc().
*/
typedef void* (*JSON_malloc_t)(size_t n);
/**
A typedef for deallocator functions semantically compatible with free().
*/
typedef void (*JSON_free_t)(void* mem);
/*! \brief The structure used to configure a JSON parser object
*/
typedef struct {
/** Pointer to a callback, called when the parser has something to tell
the user. This parameter may be NULL. In this case the input is
merely checked for validity.
*/
JSON_parser_callback callback;
|
| ︙ | ︙ | |||
174 175 176 177 178 179 180 |
- no comments
- Uses realloc() for memory de/allocation.
\param config. Used to configure the parser.
*/
JSON_PARSER_DLL_API void init_JSON_config(JSON_config * config);
| | | | | | | | 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 |
- no comments
- Uses realloc() for memory de/allocation.
\param config. Used to configure the parser.
*/
JSON_PARSER_DLL_API void init_JSON_config(JSON_config * config);
/*! \brief Create a JSON parser object
\param config. Used to configure the parser. Set to NULL to use
the default configuration. See init_JSON_config. Its contents are
copied by this function, so it need not outlive the returned
object.
\return The parser object, which is owned by the caller and must eventually
be freed by calling delete_JSON_parser().
*/
JSON_PARSER_DLL_API JSON_parser new_JSON_parser(JSON_config const* config);
/*! \brief Destroy a previously created JSON parser object. */
JSON_PARSER_DLL_API void delete_JSON_parser(JSON_parser jc);
/*! \brief Parse a character.
\return Non-zero, if all characters passed to this function are part of are valid JSON.
*/
JSON_PARSER_DLL_API int JSON_parser_char(JSON_parser jc, int next_char);
/*! \brief Finalize parsing.
Call this method once after all input characters have been consumed.
\return Non-zero, if all parsed characters are valid JSON, zero otherwise.
*/
JSON_PARSER_DLL_API int JSON_parser_done(JSON_parser jc);
/*! \brief Determine if a given string is valid JSON white space
\return Non-zero if the string is valid, zero otherwise.
*/
JSON_PARSER_DLL_API int JSON_parser_is_legal_white_space_string(const char* s);
/*! \brief Gets the last error that occurred during the use of JSON_parser.
\return A value from the JSON_error enum.
*/
JSON_PARSER_DLL_API int JSON_parser_get_last_error(JSON_parser jc);
/*! \brief Re-sets the parser to prepare it for another parse run.
\return True (non-zero) on success, 0 on error (e.g. !jc).
*/
JSON_PARSER_DLL_API int JSON_parser_reset(JSON_parser jc);
#ifdef __cplusplus
}
#endif
#endif /* JSON_PARSER_H */
/* end file parser/JSON_parser.h */
/* begin file parser/JSON_parser.c */
/*
Copyright (c) 2007-2013 Jean Gressmann (jean@0x42.de)
|
| ︙ | ︙ | |||
1429 1430 1431 1432 1433 1434 1435 |
#endif
#if defined(__cplusplus)
extern "C" {
#endif
| | | 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 |
#endif
#if defined(__cplusplus)
extern "C" {
#endif
/**
This type holds the "vtbl" for type-specific operations when
working with cson_value objects.
All cson_values of a given logical type share a pointer to a single
library-internal instance of this class.
*/
|
| ︙ | ︙ | |||
1605 1606 1607 1608 1609 1610 1611 | #define CSON_DBL(V) CSON_CAST(cson_double_t,(V)) #define CSON_STR(V) CSON_CAST(cson_string,(V)) #define CSON_OBJ(V) CSON_CAST(cson_object,(V)) #define CSON_ARRAY(V) CSON_CAST(cson_array,(V)) /** Holds special shared "constant" (though they are non-const) | | | | | | 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 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 |
#define CSON_DBL(V) CSON_CAST(cson_double_t,(V))
#define CSON_STR(V) CSON_CAST(cson_string,(V))
#define CSON_OBJ(V) CSON_CAST(cson_object,(V))
#define CSON_ARRAY(V) CSON_CAST(cson_array,(V))
/**
Holds special shared "constant" (though they are non-const)
values.
*/
static struct CSON_EMPTY_HOLDER_
{
char trueValue;
cson_string stringValue;
} CSON_EMPTY_HOLDER = {
1/*trueValue*/,
cson_string_empty_m
};
/**
Indexes into the CSON_SPECIAL_VALUES array.
If this enum changes in any way,
makes damned sure that CSON_SPECIAL_VALUES is updated
to match!!!
*/
enum CSON_INTERNAL_VALUES {
CSON_VAL_UNDEF = 0,
CSON_VAL_NULL = 1,
CSON_VAL_TRUE = 2,
CSON_VAL_FALSE = 3,
CSON_VAL_INT_0 = 4,
CSON_VAL_DBL_0 = 5,
CSON_VAL_STR_EMPTY = 6,
CSON_INTERNAL_VALUES_LENGTH
};
/**
Some "special" shared cson_value instances.
These values MUST be initialized in the order specified
by the CSON_INTERNAL_VALUES enum.
Note that they are not const because they are used as
shared-allocation objects in non-const contexts. However, the
public API provides no way to modifying them, and clients who
modify values directly are subject to The Wrath of Undefined
Behaviour.
*/
static cson_value CSON_SPECIAL_VALUES[] = {
|
| ︙ | ︙ | |||
1663 1664 1665 1666 1667 1668 1669 |
};
/**
Returns non-0 (true) if m is one of our special
"built-in" values, e.g. from CSON_SPECIAL_VALUES and some
"empty" values.
| | | 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 |
};
/**
Returns non-0 (true) if m is one of our special
"built-in" values, e.g. from CSON_SPECIAL_VALUES and some
"empty" values.
If this returns true, m MUST NOT be free()d!
*/
static char cson_value_is_builtin( void const * m )
{
if((m >= (void const *)&CSON_EMPTY_HOLDER)
&& ( m < (void const *)(&CSON_EMPTY_HOLDER+1)))
return 1;
|
| ︙ | ︙ | |||
2181 2182 2183 2184 2185 2186 2187 |
int (*visitor)(cson_kvp * obj, void * visitorState ),
void * visitorState );
static int cson_value_list_visit( cson_value_list * self,
int (*visitor)(cson_value * obj, void * visitorState ),
void * visitorState );
#endif
#endif
| | | 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 |
int (*visitor)(cson_kvp * obj, void * visitorState ),
void * visitorState );
static int cson_value_list_visit( cson_value_list * self,
int (*visitor)(cson_value * obj, void * visitorState ),
void * visitorState );
#endif
#endif
#if 0
# define LIST_T cson_value_list
# define VALUE_T cson_value *
# define VALUE_T_IS_PTR 1
# define LIST_T cson_kvp_list
# define VALUE_T cson_kvp *
# define VALUE_T_IS_PTR 1
|
| ︙ | ︙ | |||
2360 2361 2362 2363 2364 2365 2366 |
cson_value * cson_value_new_object()
{
return cson_value_object_alloc();
}
cson_object * cson_new_object()
{
| | | 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 |
cson_value * cson_value_new_object()
{
return cson_value_object_alloc();
}
cson_object * cson_new_object()
{
return cson_value_get_object( cson_value_new_object() );
}
cson_value * cson_value_new_array()
{
return cson_value_array_alloc();
}
|
| ︙ | ︙ | |||
2606 2607 2608 2609 2610 2611 2612 |
if( ! val || !val->api ) return cson_rc.ArgError;
else
{
cson_int_t i = 0;
int rc = 0;
switch(val->api->typeID)
{
| | | 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 |
if( ! val || !val->api ) return cson_rc.ArgError;
else
{
cson_int_t i = 0;
int rc = 0;
switch(val->api->typeID)
{
case CSON_TYPE_UNDEF:
case CSON_TYPE_NULL:
i = 0;
break;
case CSON_TYPE_BOOL: {
char b = 0;
cson_value_fetch_bool( val, &b );
i = b;
|
| ︙ | ︙ | |||
2659 2660 2661 2662 2663 2664 2665 |
if( ! val || !val->api ) return cson_rc.ArgError;
else
{
cson_double_t d = 0.0;
int rc = 0;
switch(val->api->typeID)
{
| | | 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 |
if( ! val || !val->api ) return cson_rc.ArgError;
else
{
cson_double_t d = 0.0;
int rc = 0;
switch(val->api->typeID)
{
case CSON_TYPE_UNDEF:
case CSON_TYPE_NULL:
d = 0;
break;
case CSON_TYPE_BOOL: {
char b = 0;
cson_value_fetch_bool( val, &b );
d = b ? 1.0 : 0.0;
|
| ︙ | ︙ | |||
2789 2790 2791 2792 2793 2794 2795 | } #if 0 /** Removes and returns the last value from the given array, shrinking its size by 1. Returns NULL if ar is NULL, ar->list.count is 0, or the element at that index is NULL. | | | 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 | } #if 0 /** Removes and returns the last value from the given array, shrinking its size by 1. Returns NULL if ar is NULL, ar->list.count is 0, or the element at that index is NULL. If removeRef is true then cson_value_free() is called to remove ar's reference count for the value. In that case NULL is returned, even if the object still has live references. If removeRef is false then the caller takes over ownership of that reference count point. If removeRef is false then the caller takes over ownership |
| ︙ | ︙ | |||
2856 2857 2858 2859 2860 2861 2862 |
{
cson_value * c = cson_value_new(CSON_TYPE_INTEGER,0);
#if !defined(NDEBUG) && CSON_VOID_PTR_IS_BIG
assert( sizeof(cson_int_t) <= sizeof(void *) );
#endif
if( c )
{
| | | | 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 |
{
cson_value * c = cson_value_new(CSON_TYPE_INTEGER,0);
#if !defined(NDEBUG) && CSON_VOID_PTR_IS_BIG
assert( sizeof(cson_int_t) <= sizeof(void *) );
#endif
if( c )
{
memcpy(CSON_INT(c), &v, sizeof(v));
}
return c;
}
}
cson_value * cson_new_double( cson_double_t v )
{
return cson_value_new_double(v);
}
cson_value * cson_value_new_double( cson_double_t v )
{
if( 0.0 == v ) return &CSON_SPECIAL_VALUES[CSON_VAL_DBL_0];
else
{
cson_value * c = cson_value_new(CSON_TYPE_DOUBLE,0);
if( c )
{
memcpy(CSON_DBL(c), &v, sizeof(v));
}
return c;
}
}
cson_string * cson_new_string(char const * str, unsigned int len)
{
|
| ︙ | ︙ | |||
3066 3067 3068 3069 3070 3071 3072 |
if( obj->kvp.count )
{
qsort( obj->kvp.list, obj->kvp.count, sizeof(cson_kvp*),
cson_kvp_cmp );
}
}
| | | 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 |
if( obj->kvp.count )
{
qsort( obj->kvp.list, obj->kvp.count, sizeof(cson_kvp*),
cson_kvp_cmp );
}
}
#endif
int cson_object_unset( cson_object * obj, char const * key )
{
if( ! obj || !key || !*key ) return cson_rc.ArgError;
else
{
unsigned int ndx = 0;
|
| ︙ | ︙ | |||
3236 3237 3238 3239 3240 3241 3242 | If p->node is-a Object then value is inserted into the object using p->key. In any other case cson_rc.InternalError is returned. Returns cson_rc.AllocError if an allocation fails. Returns 0 on success. On error, parsing must be ceased immediately. | | | 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 |
If p->node is-a Object then value is inserted into the object
using p->key. In any other case cson_rc.InternalError is returned.
Returns cson_rc.AllocError if an allocation fails.
Returns 0 on success. On error, parsing must be ceased immediately.
Ownership of val is ALWAYS TRANSFERED to this function. If this
function fails, val will be cleaned up and destroyed. (This
simplifies error handling in the core parser.)
*/
static int cson_parser_set_key( cson_parser * p, cson_value * val )
{
assert( p && val );
|
| ︙ | ︙ | |||
3483 3484 3485 3486 3487 3488 3489 |
break;
}
++p->totalKeyCount;
break;
}
case JSON_T_STRING: {
cson_value * v = cson_value_new_string( value->vu.str.value, value->vu.str.length );
| | | 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 |
break;
}
++p->totalKeyCount;
break;
}
case JSON_T_STRING: {
cson_value * v = cson_value_new_string( value->vu.str.value, value->vu.str.length );
rc = ( NULL == v )
? cson_rc.AllocError
: cson_parser_push_value( p, v );
break;
}
default:
assert(0);
rc = cson_rc.InternalError;
|
| ︙ | ︙ | |||
3530 3531 3532 3533 3534 3535 3536 | Cleans up all contents of p but does not free p. To properly take over ownership of the parser's root node on a successful parse: - Copy p->root's pointer and set p->root to NULL. - Eventually free up p->root with cson_value_free(). | | | 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 |
Cleans up all contents of p but does not free p.
To properly take over ownership of the parser's root node on a
successful parse:
- Copy p->root's pointer and set p->root to NULL.
- Eventually free up p->root with cson_value_free().
If you do not set p->root to NULL, p->root will be freed along with
any other items inserted into it (or under it) during the parsing
process.
*/
static int cson_parser_clean( cson_parser * p )
{
if( ! p ) return cson_rc.ArgError;
|
| ︙ | ︙ | |||
3569 3570 3571 3572 3573 3574 3575 |
unsigned char ch[2] = {0,0};
cson_parse_opt const opt = opt_ ? *opt_ : cson_parse_opt_empty;
int rc = 0;
unsigned int len = 1;
cson_parse_info info = info_ ? *info_ : cson_parse_info_empty;
cson_parser p = cson_parser_empty;
if( ! tgt || ! src ) return cson_rc.ArgError;
| | | 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 |
unsigned char ch[2] = {0,0};
cson_parse_opt const opt = opt_ ? *opt_ : cson_parse_opt_empty;
int rc = 0;
unsigned int len = 1;
cson_parse_info info = info_ ? *info_ : cson_parse_info_empty;
cson_parser p = cson_parser_empty;
if( ! tgt || ! src ) return cson_rc.ArgError;
{
JSON_config jopt = {0};
init_JSON_config( &jopt );
jopt.allow_comments = opt.allowComments;
jopt.depth = opt.maxDepth;
jopt.callback_ctx = &p;
jopt.handle_floats_manually = 0;
|
| ︙ | ︙ | |||
4638 4639 4640 4641 4642 4643 4644 |
#else
rc = cson_value_clone(v);
#endif
#undef TRY_SHARING
cson_value_add_reference(rc);
return rc;
}
| | | 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 |
#else
rc = cson_value_clone(v);
#endif
#undef TRY_SHARING
cson_value_add_reference(rc);
return rc;
}
static cson_value * cson_value_clone_array( cson_value const * orig )
{
unsigned int i = 0;
cson_array const * asrc = cson_value_get_array( orig );
unsigned int alen = cson_array_length_get( asrc );
cson_value * destV = NULL;
cson_array * destA = NULL;
|
| ︙ | ︙ | |||
4678 4679 4680 4681 4682 4683 4684 |
return NULL;
}
cson_value_free(cl)/*remove our artificial reference */;
}
}
return destV;
}
| | | 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 |
return NULL;
}
cson_value_free(cl)/*remove our artificial reference */;
}
}
return destV;
}
static cson_value * cson_value_clone_object( cson_value const * orig )
{
cson_object const * src = cson_value_get_object( orig );
cson_value * destV = NULL;
cson_object * dest = NULL;
cson_kvp const * kvp = NULL;
cson_object_iterator iter = cson_object_iterator_empty;
|
| ︙ | ︙ | |||
4832 4833 4834 4835 4836 4837 4838 |
v = cson_strdup( "null", 4 );
break;
}
case CSON_TYPE_STRING: {
cson_string const * jstr = cson_value_get_string(orig);
unsigned const int slen = cson_string_length_bytes( jstr );
assert( NULL != jstr );
| | | 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 |
v = cson_strdup( "null", 4 );
break;
}
case CSON_TYPE_STRING: {
cson_string const * jstr = cson_value_get_string(orig);
unsigned const int slen = cson_string_length_bytes( jstr );
assert( NULL != jstr );
v = cson_strdup( cson_string_cstr( jstr ), slen );
break;
}
case CSON_TYPE_INTEGER: {
char buf[BufSize] = {0};
if( 0 < sprintf( v, "%"CSON_INT_T_PFMT, cson_value_get_integer(orig)) )
{
v = cson_strdup( buf, strlen(buf) );
|
| ︙ | ︙ | |||
4885 4886 4887 4888 4889 4890 4891 |
v = cson_strdup( "null", 4 );
break;
}
case CSON_TYPE_STRING: {
cson_string const * jstr = cson_value_get_string(orig);
unsigned const int slen = cson_string_length_bytes( jstr );
assert( NULL != jstr );
| | | 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 |
v = cson_strdup( "null", 4 );
break;
}
case CSON_TYPE_STRING: {
cson_string const * jstr = cson_value_get_string(orig);
unsigned const int slen = cson_string_length_bytes( jstr );
assert( NULL != jstr );
v = cson_strdup( cson_string_cstr( jstr ), slen );
break;
}
case CSON_TYPE_INTEGER: {
char buf[BufSize] = {0};
if( 0 < sprintf( v, "%"CSON_INT_T_PFMT, cson_value_get_integer(orig)) )
{
v = cson_strdup( buf, strlen(buf) );
|
| ︙ | ︙ | |||
5349 5350 5351 5352 5353 5354 5355 |
char const * colName = NULL;
int i = 0;
int rc = 0;
int colCount = 0;
assert(st);
colCount = sqlite3_column_count(st);
if( colCount <= 0 ) return NULL;
| | | 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 |
char const * colName = NULL;
int i = 0;
int rc = 0;
int colCount = 0;
assert(st);
colCount = sqlite3_column_count(st);
if( colCount <= 0 ) return NULL;
aryV = cson_value_new_array();
if( ! aryV ) return NULL;
ary = cson_value_get_array(aryV);
assert(ary);
for( i = 0; (0 ==rc) && (i < colCount); ++i )
{
colName = sqlite3_column_name( st, i );
|
| ︙ | ︙ | |||
5489 5490 5491 5492 5493 5494 5495 |
error:
cson_value_free(aryV);
aryV = NULL;
end:
return aryV;
}
| | | 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 |
error:
cson_value_free(aryV);
aryV = NULL;
end:
return aryV;
}
/**
Internal impl of cson_sqlite3_stmt_to_json() when the 'fat'
parameter is non-0.
*/
static int cson_sqlite3_stmt_to_json_fat( sqlite3_stmt * st, cson_value ** tgt )
{
#define RETURN(RC) { if(rootV) cson_value_free(rootV); return RC; }
|
| ︙ | ︙ | |||
5634 5635 5636 5637 5638 5639 5640 |
{
sqlite3_stmt * st = NULL;
int rc = sqlite3_prepare_v2( db, sql, -1, &st, NULL );
if( 0 != rc ) return cson_rc.IOError /* FIXME: Better error code? */;
rc = cson_sqlite3_stmt_to_json( st, tgt, fat );
sqlite3_finalize( st );
return rc;
| | | 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 |
{
sqlite3_stmt * st = NULL;
int rc = sqlite3_prepare_v2( db, sql, -1, &st, NULL );
if( 0 != rc ) return cson_rc.IOError /* FIXME: Better error code? */;
rc = cson_sqlite3_stmt_to_json( st, tgt, fat );
sqlite3_finalize( st );
return rc;
}
}
int cson_sqlite3_bind_value( sqlite3_stmt * st, int ndx, cson_value const * v )
{
int rc = 0;
char convertErr = 0;
if(!st) return cson_rc.ArgError;
|
| ︙ | ︙ |
Changes to src/db.c.
| ︙ | ︙ | |||
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 |
db_now_function, 0, 0);
sqlite3_create_function(db, "toLocal", 0, SQLITE_UTF8, 0,
db_tolocal_function, 0, 0);
sqlite3_create_function(db, "fromLocal", 0, SQLITE_UTF8, 0,
db_fromlocal_function, 0, 0);
}
/*
** Open a database file. Return a pointer to the new database
** connection. An error results in process abort.
*/
LOCAL sqlite3 *db_open(const char *zDbName){
int rc;
sqlite3 *db;
if( g.fSqlTrace ) fossil_trace("-- sqlite3_open: [%s]\n", zDbName);
rc = sqlite3_open_v2(
zDbName, &db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
g.zVfsName
);
if( rc!=SQLITE_OK ){
db_err("[%s]: %s", zDbName, sqlite3_errmsg(db));
}
sqlite3_busy_timeout(db, 5000);
sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
sqlite3_create_function(db, "user", 0, SQLITE_UTF8, 0, db_sql_user, 0, 0);
sqlite3_create_function(db, "cgi", 1, SQLITE_UTF8, 0, db_sql_cgi, 0, 0);
sqlite3_create_function(db, "cgi", 2, SQLITE_UTF8, 0, db_sql_cgi, 0, 0);
sqlite3_create_function(db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
sqlite3_create_function(
db, "is_selected", 1, SQLITE_UTF8, 0, file_is_selected,0,0
);
sqlite3_create_function(
db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0
);
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > | > > | 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 |
db_now_function, 0, 0);
sqlite3_create_function(db, "toLocal", 0, SQLITE_UTF8, 0,
db_tolocal_function, 0, 0);
sqlite3_create_function(db, "fromLocal", 0, SQLITE_UTF8, 0,
db_fromlocal_function, 0, 0);
}
/*
** If the database file zDbFile has a name that suggests that it is
** encrypted, then prompt for the encryption key and return it in the
** blob *pKey. Or, if the encryption key has previously been requested,
** just return a copy of the previous result.
*/
static void db_encryption_key(
const char *zDbFile, /* Name of the database file */
Blob *pKey /* Put the encryption key here */
){
blob_init(pKey, 0, 0);
#if USE_SEE
if( sqlite3_strglob("*.efossil", zDbFile)==0 ){
static char *zSavedKey = 0;
if( zSavedKey ){
blob_set(pKey, zSavedKey);
}else{
char *zPrompt = mprintf("\rencryption key for '%s': ", zDbFile);
prompt_for_password(zPrompt, pKey, 0);
fossil_free(zPrompt);
zSavedKey = fossil_strdup(blob_str(pKey));
}
}
#endif
}
/*
** Open a database file. Return a pointer to the new database
** connection. An error results in process abort.
*/
LOCAL sqlite3 *db_open(const char *zDbName){
int rc;
sqlite3 *db;
Blob key;
if( g.fSqlTrace ) fossil_trace("-- sqlite3_open: [%s]\n", zDbName);
rc = sqlite3_open_v2(
zDbName, &db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
g.zVfsName
);
if( rc!=SQLITE_OK ){
db_err("[%s]: %s", zDbName, sqlite3_errmsg(db));
}
db_encryption_key(zDbName, &key);
if( blob_size(&key)>0 ){
char *zCmd = sqlite3_mprintf("PRAGMA key(%Q)", blob_str(&key));
sqlite3_exec(db, zCmd, 0, 0, 0);
sqlite3_free(zCmd);
}
blob_reset(&key);
sqlite3_busy_timeout(db, 5000);
sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
sqlite3_create_function(db, "user", 0, SQLITE_UTF8, 0, db_sql_user, 0, 0);
sqlite3_create_function(db, "cgi", 1, SQLITE_UTF8, 0, db_sql_cgi, 0, 0);
sqlite3_create_function(db, "cgi", 2, SQLITE_UTF8, 0, db_sql_cgi, 0, 0);
sqlite3_create_function(db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
sqlite3_create_function(
db, "is_selected", 1, SQLITE_UTF8, 0, file_is_selected,0,0
);
sqlite3_create_function(
db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0
);
if( g.fSqlTrace ) sqlite3_trace_v2(db, SQLITE_TRACE_STMT, db_sql_trace, 0);
db_add_aux_functions(db);
re_add_sql_func(db); /* The REGEXP operator */
foci_register(db); /* The "files_of_checkin" virtual table */
sqlite3_exec(db, "PRAGMA foreign_keys=OFF;", 0, 0, 0);
return db;
}
/*
** Detaches the zLabel database.
*/
void db_detach(const char *zLabel){
db_multi_exec("DETACH DATABASE %Q", zLabel);
}
/*
** zDbName is the name of a database file. Attach zDbName using
** the name zLabel.
*/
void db_attach(const char *zDbName, const char *zLabel){
Blob key;
db_encryption_key(zDbName, &key);
db_multi_exec("ATTACH DATABASE %Q AS %Q KEY %Q",
zDbName, zLabel, blob_str(&key));
blob_reset(&key);
}
/*
** zDbName is the name of a database file. If no other database
** file is open, then open this one. If another database file is
** already open, then attach zDbName using the name zLabel.
*/
|
| ︙ | ︙ | |||
1525 1526 1527 1528 1529 1530 1531 |
if( zUser==0 ){
zUser = db_get("default-user", 0);
}
if( zUser==0 ){
zUser = fossil_getenv("FOSSIL_USER");
}
if( zUser==0 ){
| < < < > | | | | > | 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 |
if( zUser==0 ){
zUser = db_get("default-user", 0);
}
if( zUser==0 ){
zUser = fossil_getenv("FOSSIL_USER");
}
if( zUser==0 ){
zUser = fossil_getenv("USER");
}
if( zUser==0 ){
zUser = fossil_getenv("LOGNAME");
}
if( zUser==0 ){
zUser = fossil_getenv("USERNAME");
}
if( zUser==0 ){
zUser = "root";
}
db_multi_exec(
"INSERT OR IGNORE INTO user(login, info) VALUES(%Q,'')", zUser
);
|
| ︙ | ︙ | |||
1688 1689 1690 1691 1692 1693 1694 | } /* ** COMMAND: new* ** COMMAND: init ** ** Usage: %fossil new ?OPTIONS? FILENAME | | | 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 | } /* ** COMMAND: new* ** COMMAND: init ** ** Usage: %fossil new ?OPTIONS? FILENAME ** or: %fossil init ?OPTIONS? FILENAME ** ** Create a repository for a new project in the file named FILENAME. ** This command is distinct from "clone". The "clone" command makes ** a copy of an existing project. This command starts a new project. ** ** By default, your current login name is used to create the default ** admin user. This can be overridden using the -A|--admin-user |
| ︙ | ︙ | |||
1769 1770 1771 1772 1773 1774 1775 |
if( g.fSqlPrint ){
for(i=0; i<argc; i++){
char c = i==argc-1 ? '\n' : ' ';
fossil_print("%s%c", sqlite3_value_text(argv[i]), c);
}
}
}
| > > | > > > > | > > | 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 |
if( g.fSqlPrint ){
for(i=0; i<argc; i++){
char c = i==argc-1 ? '\n' : ' ';
fossil_print("%s%c", sqlite3_value_text(argv[i]), c);
}
}
}
LOCAL int db_sql_trace(unsigned m, void *notUsed, void *pP, void *pX){
sqlite3_stmt *pStmt = (sqlite3_stmt*)pP;
char *zSql;
int n;
const char *zArg = (const char*)pX;
if( zArg[0]=='-' ) return 0;
zSql = sqlite3_expanded_sql(pStmt);
n = (int)strlen(zSql);
fossil_trace("%s%s\n", zSql, (n>0 && zSql[n-1]==';') ? "" : ";");
sqlite3_free(zSql);
return 0;
}
/*
** Implement the user() SQL function. user() takes no arguments and
** returns the user ID of the current user.
*/
LOCAL void db_sql_user(
|
| ︙ | ︙ | |||
2614 2615 2616 2617 2618 2619 2620 | return 0; } /* ** COMMAND: settings ** COMMAND: unset* ** | | | | 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 | return 0; } /* ** COMMAND: settings ** COMMAND: unset* ** ** Usage: %fossil settings ?PROPERTY? ?VALUE? ?OPTIONS? ** or: %fossil unset PROPERTY ?OPTIONS? ** ** The "settings" command with no arguments lists all properties and their ** values. With just a property name it shows the value of that property. ** With a value argument it changes the property for the current repository. ** ** Settings marked as versionable are overridden by the contents of the ** file named .fossil-settings/PROPERTY in the check-out root, if that |
| ︙ | ︙ | |||
2674 2675 2676 2677 2678 2679 2680 | ** case-sensitive If TRUE, the files whose names differ only in case ** are considered distinct. If FALSE files whose names ** differ only in case are the same file. Defaults to ** TRUE for unix and FALSE for Cygwin, Mac and Windows. ** ** clean-glob The VALUE is a comma or newline-separated list of GLOB ** (versionable) patterns specifying files that the "clean" command will | | | | 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 | ** case-sensitive If TRUE, the files whose names differ only in case ** are considered distinct. If FALSE files whose names ** differ only in case are the same file. Defaults to ** TRUE for unix and FALSE for Cygwin, Mac and Windows. ** ** clean-glob The VALUE is a comma or newline-separated list of GLOB ** (versionable) patterns specifying files that the "clean" command will ** delete without prompting or allowing undo. ** Example: *.a,*.lib,*.o ** ** clearsign When enabled, fossil will attempt to sign all commits ** with gpg. When disabled (the default), commits will ** be unsigned. Default: off ** ** crnl-glob A comma or newline-separated list of GLOB patterns for ** (versionable) text files in which it is ok to have CR, CR+NL or mixed |
| ︙ | ︙ | |||
2809 2810 2811 2812 2813 2814 2815 | ** ssl-ca-location 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. | | | 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 | ** ssl-ca-location 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. ** ** ssl-identity The full pathname to a file containing a certificate ** and private key in PEM format. Create by concatenating ** the certificate and private key files. ** This identity will be presented to SSL servers to |
| ︙ | ︙ | |||
2969 2970 2971 2972 2973 2974 2975 |
}
rSpan /= 356.24; /* Convert units to years */
return sqlite3_mprintf("%.1f years", rSpan);
}
/*
** COMMAND: test-timespan
| > | > | | 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 |
}
rSpan /= 356.24; /* Convert units to years */
return sqlite3_mprintf("%.1f years", rSpan);
}
/*
** COMMAND: test-timespan
**
** Usage: %fossil test-timespan TIMESTAMP
**
** Print the approximate span of time from now to TIMESTAMP.
*/
void test_timespan_cmd(void){
double rDiff;
if( g.argc!=3 ) usage("TIMESTAMP");
sqlite3_open(":memory:", &g.db);
rDiff = db_double(0.0, "SELECT julianday('now') - julianday(%Q)", g.argv[2]);
fossil_print("Time differences: %s\n", db_timespan_name(rDiff));
sqlite3_close(g.db);
g.db = 0;
}
/*
** COMMAND: test-without-rowid
**
** Usage: %fossil test-without-rowid FILENAME...
**
** Change the Fossil repository FILENAME to make use of the WITHOUT ROWID
** optimization. FILENAME can also be the ~/.fossil file or a local
** .fslckout or _FOSSIL_ file.
**
** The purpose of this command is for testing the WITHOUT ROWID capabilities
** of SQLite. There is no big advantage to using WITHOUT ROWID in Fossil.
|
| ︙ | ︙ |
Changes to src/deltacmd.c.
| ︙ | ︙ | |||
39 40 41 42 43 44 45 | zRes = blob_buffer(pDelta); len = delta_create(zOrig, lenOrig, zTarg, lenTarg, zRes); blob_resize(pDelta, len); return 0; } /* | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
zRes = blob_buffer(pDelta);
len = delta_create(zOrig, lenOrig, zTarg, lenTarg, zRes);
blob_resize(pDelta, len);
return 0;
}
/*
** COMMAND: test-delta-create
**
** Usage: %fossil test-delta-create FILE1 FILE2 DELTA
**
** Create and output a delta that carries FILE1 into FILE2.
** Store the result in DELTA.
*/
void delta_create_cmd(void){
|
| ︙ | ︙ | |||
67 68 69 70 71 72 73 | } blob_reset(&orig); blob_reset(&target); blob_reset(&delta); } /* | | | 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
}
blob_reset(&orig);
blob_reset(&target);
blob_reset(&delta);
}
/*
** COMMAND: test-delta-analyze
**
** Usage: %fossil test-delta-analyze FILE1 FILE2
**
** Create and a delta that carries FILE1 into FILE2. Print the
** number bytes copied and the number of bytes inserted.
*/
void delta_analyze_cmd(void){
|
| ︙ | ︙ | |||
139 140 141 142 143 144 145 |
blob_reset(pOriginal);
}
*pTarget = out;
return len;
}
/*
| | | 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
blob_reset(pOriginal);
}
*pTarget = out;
return len;
}
/*
** COMMAND: test-delta-apply
**
** Usage: %fossil test-delta-apply FILE1 DELTA
**
** Apply DELTA to FILE1 and output the result.
*/
void delta_apply_cmd(void){
Blob orig, target, delta;
|
| ︙ | ︙ | |||
167 168 169 170 171 172 173 | blob_reset(&orig); blob_reset(&target); blob_reset(&delta); } /* | | | 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | blob_reset(&orig); blob_reset(&target); blob_reset(&delta); } /* ** COMMAND: test-delta ** ** Usage: %fossil test-delta FILE1 FILE2 ** ** Read two files named on the command-line. Create and apply deltas ** going in both directions. Verify that the original files are ** correctly recovered. */ |
| ︙ | ︙ |
Changes to src/descendants.c.
| ︙ | ︙ | |||
429 430 431 432 433 434 435 |
fossil_free(z);
}
fossil_free(zLastBr);
db_finalize(&q);
}
/*
| | | 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 |
fossil_free(z);
}
fossil_free(zLastBr);
db_finalize(&q);
}
/*
** WEBPAGE: leaves
**
** Show leaf check-ins in a timeline. By default only open leaves
** are listed.
**
** A "leaf" is a check-in with no children in the same branch. A
** "closed leaf" is a leaf that has a "closed" tag. An "open leaf"
** is a leaf without a "closed" tag.
|
| ︙ | ︙ |
Changes to src/diff.c.
| ︙ | ︙ | |||
2279 2280 2281 2282 2283 2284 2285 |
unsigned clr1, clr2, clr;
int bBlame = g.zPath[0]!='a';/* True for BLAME output. False for ANNOTATE. */
/* Gather query parameters */
showLog = atoi(PD("log","1"));
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
| | | 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 |
unsigned clr1, clr2, clr;
int bBlame = g.zPath[0]!='a';/* True for BLAME output. False for ANNOTATE. */
/* Gather query parameters */
showLog = atoi(PD("log","1"));
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
if( exclude_spiders() ) return;
load_control();
mid = name_to_typed_rid(PD("checkin","0"),"ci");
zFilename = P("filename");
fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
if( mid==0 || fnid==0 ){ fossil_redirect_home(); }
iLimit = atoi(PD("limit","20"));
if( P("filevers") ) annFlags |= ANN_FILE_VERS;
|
| ︙ | ︙ | |||
2375 2376 2377 2378 2379 2380 2381 |
p->zFUuid,p[-1].zFUuid);
@ %z(zLink)[diff-to-previous]</a>
}
}
#endif
}
@ </ol>
| | | 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 |
p->zFUuid,p[-1].zFUuid);
@ %z(zLink)[diff-to-previous]</a>
}
}
#endif
}
@ </ol>
@ <hr />
}
if( !ann.bLimit ){
@ <h2>Origin for each line in
@ %z(href("%R/finfo?name=%h&ci=%!S", zFilename, zCI))%h(zFilename)</a>
@ from check-in %z(href("%R/info/%!S",zCI))%S(zCI)</a>:</h2>
iLimit = ann.nVers+10;
}else{
|
| ︙ | ︙ | |||
2433 2434 2435 2436 2437 2438 2439 | } /* ** COMMAND: annotate ** COMMAND: blame ** COMMAND: praise ** | | | 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 | } /* ** COMMAND: annotate ** COMMAND: blame ** COMMAND: praise ** ** Usage: %fossil (annotate|blame|praise) ?OPTIONS? FILENAME ** ** Output the text of a file with markings to show when each line of ** the file was last modified. The "annotate" command shows line numbers ** and omits the username. The "blame" and "praise" commands show the user ** who made each check-in and omits the line number. ** ** Options: |
| ︙ | ︙ |
Changes to src/diff.tcl.
| ︙ | ︙ | |||
225 226 227 228 229 230 231 | } enableSync y } wm withdraw . wm title . $CFG(TITLE) wm iconname . $CFG(TITLE) | > > > > > | > > > > > | | 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 |
}
enableSync y
}
wm withdraw .
wm title . $CFG(TITLE)
wm iconname . $CFG(TITLE)
# Keystroke bindings for on the top-level window for navigation and
# control also fire when those same keystrokes are pressed in the
# Search entry box. Disable them, to prevent the diff screen from
# disappearing abruptly and unexpectedly when searching for "q".
#
# bind . <q> exit
# bind . <p> {catch searchPrev; break}
# bind . <n> {catch searchNext; break}
# bind . <Escape><Escape> exit
bind . <Destroy> {after 0 exit}
bind . <Tab> {cycleDiffs; break}
bind . <<PrevWindow>> {cycleDiffs 1; break}
bind . <Control-f> {searchOnOff; break}
bind . <Control-g> {catch searchNext; break}
bind . <Return> {
event generate bb.files <1>
event generate .bb.files <ButtonRelease-1>
break
}
foreach {key axis args} {
Up y {scroll -5 units}
k y {scroll -5 units}
Down y {scroll 5 units}
|
| ︙ | ︙ | |||
257 258 259 260 261 262 263 264 265 266 267 268 269 270 |
} {
bind . <$key> "scroll-$axis $args; break"
bind . <Shift-$key> continue
}
frame .bb
::ttk::menubutton .bb.files -text "Files"
toplevel .wfiles
wm withdraw .wfiles
update idletasks
wm transient .wfiles .
wm overrideredirect .wfiles 1
listbox .wfiles.lb -width 0 -height $CFG(LB_HEIGHT) -activestyle none \
-yscroll {.wfiles.sb set}
| > > > > | 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 |
} {
bind . <$key> "scroll-$axis $args; break"
bind . <Shift-$key> continue
}
frame .bb
::ttk::menubutton .bb.files -text "Files"
if {[tk windowingsystem] eq "win32"} {
::ttk::style theme use winnative
.bb.files configure -padding {20 1 10 2}
}
toplevel .wfiles
wm withdraw .wfiles
update idletasks
wm transient .wfiles .
wm overrideredirect .wfiles 1
listbox .wfiles.lb -width 0 -height $CFG(LB_HEIGHT) -activestyle none \
-yscroll {.wfiles.sb set}
|
| ︙ | ︙ | |||
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 |
if {$x(-column)==1} {
grid config .lnB -column 0
grid config .txtB -column 1
.txtB tag config add -background $CFG(RM_BG)
grid config .lnA -column 3
grid config .txtA -column 4
.txtA tag config rm -background $CFG(ADD_BG)
} else {
grid config .lnA -column 0
grid config .txtA -column 1
.txtA tag config rm -background $CFG(RM_BG)
grid config .lnB -column 3
grid config .txtB -column 4
.txtB tag config add -background $CFG(ADD_BG)
}
.mkr config -state normal
set clt [.mkr search -all < 1.0 end]
set cgt [.mkr search -all > 1.0 end]
foreach c $clt {.mkr replace $c "$c +1 chars" >}
foreach c $cgt {.mkr replace $c "$c +1 chars" <}
.mkr config -state disabled
}
::ttk::button .bb.quit -text {Quit} -command exit
::ttk::button .bb.invert -text {Invert} -command invertDiff
::ttk::button .bb.save -text {Save As...} -command saveDiff
pack .bb.quit .bb.invert -side left
if {$fossilcmd!=""} {pack .bb.save -side left}
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 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 |
if {$x(-column)==1} {
grid config .lnB -column 0
grid config .txtB -column 1
.txtB tag config add -background $CFG(RM_BG)
grid config .lnA -column 3
grid config .txtA -column 4
.txtA tag config rm -background $CFG(ADD_BG)
.bb.invert config -text Uninvert
} else {
grid config .lnA -column 0
grid config .txtA -column 1
.txtA tag config rm -background $CFG(RM_BG)
grid config .lnB -column 3
grid config .txtB -column 4
.txtB tag config add -background $CFG(ADD_BG)
.bb.invert config -text Invert
}
.mkr config -state normal
set clt [.mkr search -all < 1.0 end]
set cgt [.mkr search -all > 1.0 end]
foreach c $clt {.mkr replace $c "$c +1 chars" >}
foreach c $cgt {.mkr replace $c "$c +1 chars" <}
.mkr config -state disabled
}
proc searchOnOff {} {
if {[info exists ::search]} {
unset ::search
.txtA tag remove search 1.0 end
.txtB tag remove search 1.0 end
pack forget .bb.sframe
} else {
set ::search .txtA
if {![winfo exists .bb.sframe]} {
frame .bb.sframe
::ttk::entry .bb.sframe.e -width 10
pack .bb.sframe.e -side left -fill y -expand 1
bind .bb.sframe.e <Return> {searchNext; break}
::ttk::button .bb.sframe.nx -text \u2193 -width 1 -command searchNext
::ttk::button .bb.sframe.pv -text \u2191 -width 1 -command searchPrev
tk_optionMenu .bb.sframe.typ ::search_type \
Exact {No Case} {RegExp} {Whole Word}
.bb.sframe.typ config -width 10
set ::search_type Exact
pack .bb.sframe.nx .bb.sframe.pv .bb.sframe.typ -side left
}
pack .bb.sframe -side left
after idle {focus .bb.sframe.e}
}
}
proc searchNext {} {searchStep -forwards +1 1.0 end}
proc searchPrev {} {searchStep -backwards -1 end 1.0}
proc searchStep {direction incr start stop} {
set pattern [.bb.sframe.e get]
if {$pattern==""} return
set count 0
set w $::search
if {"$w"==".txtA"} {set other .txtB} {set other .txtA}
if {[lsearch [$w mark names] search]<0} {
$w mark set search $start
}
switch $::search_type {
Exact {set st -exact}
{No Case} {set st -nocase}
{RegExp} {set st -regexp}
{Whole Word} {set st -regexp; set pattern \\y$pattern\\y}
}
set idx [$w search -count count $direction $st -- \
$pattern "search $incr chars" $stop]
if {"$idx"==""} {
set idx [$other search -count count $direction $st -- $pattern $start $stop]
if {"$idx"!=""} {
set this $w
set w $other
set other $this
} else {
set idx [$w search -count count $direction $st -- $pattern $start $stop]
}
}
$w tag remove search 1.0 end
$w mark unset search
$other tag remove search 1.0 end
$other mark unset search
if {"$idx"!=""} {
$w mark set search $idx
$w yview -pickplace $idx
$w tag add search search "$idx +$count chars"
$w tag config search -background {#fcc000}
}
set ::search $w
}
::ttk::button .bb.quit -text {Quit} -command exit
::ttk::button .bb.invert -text {Invert} -command invertDiff
::ttk::button .bb.save -text {Save As...} -command saveDiff
::ttk::button .bb.search -text {Search} -command searchOnOff
pack .bb.quit .bb.invert -side left
if {$fossilcmd!=""} {pack .bb.save -side left}
pack .bb.files .bb.search -side left
grid rowconfigure . 1 -weight 1
grid columnconfigure . 1 -weight 1
grid columnconfigure . 4 -weight 1
grid .bb -row 0 -columnspan 6
eval grid [cols] -row 1 -sticky nsew
grid .sby -row 1 -column 5 -sticky ns
grid .sbxA -row 2 -columnspan 2 -sticky ew
|
| ︙ | ︙ |
Changes to src/diffcmd.c.
| ︙ | ︙ | |||
760 761 762 763 764 765 766 | ** COMMAND: diff ** COMMAND: gdiff ** ** Usage: %fossil diff|gdiff ?OPTIONS? ?FILE1? ?FILE2 ...? ** ** Show the difference between the current version of each of the FILEs ** specified (as they exist on disk) and that same file as it was checked | | | 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 | ** COMMAND: diff ** COMMAND: gdiff ** ** Usage: %fossil diff|gdiff ?OPTIONS? ?FILE1? ?FILE2 ...? ** ** Show the difference between the current version of each of the FILEs ** specified (as they exist on disk) and that same file as it was checked ** out. Or if the FILE arguments are omitted, show the unsaved changes ** currently in the working check-out. ** ** If the "--from VERSION" or "-r VERSION" option is used it specifies ** the source check-in for the diff operation. If not specified, the ** source check-in is the base check-in for the current check-out. ** ** If the "--to VERSION" option appears, it specifies the check-in from |
| ︙ | ︙ | |||
795 796 797 798 799 800 801 | ** --binary PATTERN Treat files that match the glob PATTERN as binary ** --branch BRANCH Show diff of all changes on BRANCH ** --brief Show filenames only ** --context|-c N Use N lines of context ** --diff-binary BOOL Include binary files when using external commands ** --exec-abs-paths Force absolute path names with external commands. ** --exec-rel-paths Force relative path names with external commands. | | | | | | | | 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 |
** --binary PATTERN Treat files that match the glob PATTERN as binary
** --branch BRANCH Show diff of all changes on BRANCH
** --brief Show filenames only
** --context|-c N Use N lines of context
** --diff-binary BOOL Include binary files when using external commands
** --exec-abs-paths Force absolute path names with external commands.
** --exec-rel-paths Force relative path names with external commands.
** --from|-r VERSION Select VERSION as source for the diff
** --internal|-i Use internal diff logic
** --side-by-side|-y Side-by-side diff
** --strip-trailing-cr Strip trailing CR
** --tk Launch a Tcl/Tk GUI for display
** --to VERSION Select VERSION as target for the diff
** --undo Diff against the "undo" buffer
** --unified Unified diff
** -v|--verbose Output complete text of added or deleted files
** -w|--ignore-all-space Ignore white space when comparing lines
** -W|--width <num> Width of lines in side-by-side diff
** -Z|--ignore-trailing-space Ignore changes to end-of-line whitespace
*/
void diff_cmd(void){
int isGDiff; /* True for gdiff. False for normal diff */
int isInternDiff; /* True for internal diff */
|
| ︙ | ︙ |
Changes to src/doc.c.
| ︙ | ︙ | |||
82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
{ "asf", 3, "video/x-ms-asf" },
{ "asx", 3, "video/x-ms-asx" },
{ "au", 2, "audio/ulaw" },
{ "avi", 3, "video/x-msvideo" },
{ "bat", 3, "application/x-msdos-program" },
{ "bcpio", 5, "application/x-bcpio" },
{ "bin", 3, "application/octet-stream" },
{ "c", 1, "text/plain" },
{ "cc", 2, "text/plain" },
{ "ccad", 4, "application/clariscad" },
{ "cdf", 3, "application/x-netcdf" },
{ "class", 5, "application/octet-stream" },
{ "cod", 3, "application/vnd.rim.cod" },
{ "com", 3, "application/x-msdos-program" },
| > > | 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
{ "asf", 3, "video/x-ms-asf" },
{ "asx", 3, "video/x-ms-asx" },
{ "au", 2, "audio/ulaw" },
{ "avi", 3, "video/x-msvideo" },
{ "bat", 3, "application/x-msdos-program" },
{ "bcpio", 5, "application/x-bcpio" },
{ "bin", 3, "application/octet-stream" },
{ "bz2", 3, "application/x-bzip2" },
{ "bzip", 4, "application/x-bzip" },
{ "c", 1, "text/plain" },
{ "cc", 2, "text/plain" },
{ "ccad", 4, "application/clariscad" },
{ "cdf", 3, "application/x-netcdf" },
{ "class", 5, "application/octet-stream" },
{ "cod", 3, "application/vnd.rim.cod" },
{ "com", 3, "application/x-msdos-program" },
|
| ︙ | ︙ | |||
344 345 346 347 348 349 350 |
}
}
}
return "application/x-fossil-artifact";
}
/*
| | | 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 |
}
}
}
return "application/x-fossil-artifact";
}
/*
** COMMAND: test-mimetype
**
** Usage: %fossil test-mimetype FILENAME...
**
** Return the deduced mimetype for each file listed.
**
** If Fossil is compiled with -DFOSSIL_DEBUG then the "mimetype-test"
** filename is special and verifies the integrity of the mimetype table.
|
| ︙ | ︙ | |||
549 550 551 552 553 554 555 | ** If FILE ends in "/" then the names "FILE/index.html", "FILE/index.wiki", ** and "FILE/index.md" are tried in that order. If the binary was compiled ** with TH1 embedded documentation support and the "th1-docs" setting is ** enabled, the name "FILE/index.th1" is also tried. If none of those are ** found, then FILE is completely replaced by "404.md" and tried. If that ** is not found, then a default 404 screen is generated. ** | > | | | < | 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 | ** If FILE ends in "/" then the names "FILE/index.html", "FILE/index.wiki", ** and "FILE/index.md" are tried in that order. If the binary was compiled ** with TH1 embedded documentation support and the "th1-docs" setting is ** enabled, the name "FILE/index.th1" is also tried. If none of those are ** found, then FILE is completely replaced by "404.md" and tried. If that ** is not found, then a default 404 screen is generated. ** ** If the file's mimetype is "text/x-fossil-wiki" or "text/x-markdown" ** then headers and footers are added. If the document has mimetype ** text/html then headers and footers are usually not added. However, ** if a "text/html" document begins with the following div: ** ** <div class='fossil-doc' data-title='TEXT'> ** ** then headers and footers are supplied. The optional data-title field ** specifies the title of the document in that case. ** ** For fossil-doc documents and for markdown documents, text of the |
| ︙ | ︙ |
Changes to src/encode.c.
| ︙ | ︙ | |||
365 366 367 368 369 370 371 372 373 374 375 376 377 378 |
}
z64[n] = 0;
return z64;
}
/*
** COMMAND: test-encode64
** Usage: %fossil test-encode64 STRING
*/
void test_encode64_cmd(void){
char *z;
int i;
for(i=2; i<g.argc; i++){
z = encode64(g.argv[i], -1);
| > | 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 |
}
z64[n] = 0;
return z64;
}
/*
** COMMAND: test-encode64
**
** Usage: %fossil test-encode64 STRING
*/
void test_encode64_cmd(void){
char *z;
int i;
for(i=2; i<g.argc; i++){
z = encode64(g.argv[i], -1);
|
| ︙ | ︙ | |||
430 431 432 433 434 435 436 437 438 439 440 441 442 443 |
zData[j] = 0;
*pnByte = j;
return zData;
}
/*
** COMMAND: test-decode64
** Usage: %fossil test-decode64 STRING
*/
void test_decode64_cmd(void){
char *z;
int i, n;
for(i=2; i<g.argc; i++){
z = decode64(g.argv[i], &n);
| > | 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 |
zData[j] = 0;
*pnByte = j;
return zData;
}
/*
** COMMAND: test-decode64
**
** Usage: %fossil test-decode64 STRING
*/
void test_decode64_cmd(void){
char *z;
int i, n;
for(i=2; i<g.argc; i++){
z = decode64(g.argv[i], &n);
|
| ︙ | ︙ |
Changes to src/event.c.
| ︙ | ︙ | |||
47 48 49 50 51 52 53 | free(zId); } /* ** WEBPAGE: technote ** WEBPAGE: event ** | | | > | | | > | 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 |
free(zId);
}
/*
** WEBPAGE: technote
** WEBPAGE: event
**
** Display a technical note (formerly called an "event").
**
** PARAMETERS:
**
** name=ID Identify the technical note to display. ID must be
** complete.
** aid=ARTIFACTID Which specific version of the tech-note. Optional.
** v=BOOLEAN Show details if TRUE. Default is FALSE. Optional.
**
** Display an existing tech-note identified by its ID, optionally at a
** specific version, and optionally with additional details.
*/
void event_page(void){
int rid = 0; /* rid of the event artifact */
char *zUuid; /* UUID corresponding to rid */
const char *zId; /* Event identifier */
const char *zVerbose; /* Value of verbose option */
char *zETime; /* Time of the tech-note */
|
| ︙ | ︙ | |||
338 339 340 341 342 343 344 | return 1; } /* ** WEBPAGE: technoteedit ** WEBPAGE: eventedit ** | | | | 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 |
return 1;
}
/*
** WEBPAGE: technoteedit
** WEBPAGE: eventedit
**
** Revise or create a technical note (formerly called an "event").
**
** Parameters:
**
** name=ID Hex hash ID of the tech-note. If omitted, a new
** tech-note is created.
*/
void eventedit_page(void){
char *zTag;
int rid = 0;
Blob event;
const char *zId;
|
| ︙ | ︙ | |||
536 537 538 539 540 541 542 | @ </td></tr></table> @ </div></form> style_footer(); } /* ** Add a new tech note to the repository. The timestamp is | | | < < < < < < < < < < < | < < < < < < < | | 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 |
@ </td></tr></table>
@ </div></form>
style_footer();
}
/*
** Add a new tech note to the repository. The timestamp is
** given by the zETime parameter. rid must be zero to create
** a new page. If no previous page with the name zPageName exists
** and isNew is false, then this routine throws an error.
*/
void event_cmd_commit(
char *zETime, /* timestamp */
int rid, /* Artifact id of the tech note */
Blob *pContent, /* content of the new page */
const char *zMimeType, /* mimetype of the content */
const char *zComment, /* comment to go on the timeline */
const char *zTags, /* tags */
const char *zClr /* background color */
){
const char *zId; /* id of the tech note */
if ( rid==0 ){
zId = db_text(0, "SELECT lower(hex(randomblob(20)))");
}else{
zId = db_text(0,
"SELECT substr(tagname,7) FROM tag"
" WHERE tagid=(SELECT tagid FROM event WHERE objid='%d')",
rid
);
|
| ︙ | ︙ |
Changes to src/export.c.
| ︙ | ︙ | |||
17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
** This file contains code used to export the content of a Fossil
** repository in the git-fast-import format.
*/
#include "config.h"
#include "export.h"
#include <assert.h>
/*
** Output a "committer" record for the given user.
*/
static void print_person(const char *zUser){
static Stmt q;
const char *zContact;
char *zName;
| > > > > > > > > > > > > > > > > > > | 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 |
** This file contains code used to export the content of a Fossil
** repository in the git-fast-import format.
*/
#include "config.h"
#include "export.h"
#include <assert.h>
#if INTERFACE
/*
** struct mark_t
** holds information for translating between git commits
** and fossil commits.
** -git_name: This is the mark name that identifies the commit to git.
** It will always begin with a ':'.
** -rid: The unique object ID that identifies this commit within the
** repository database.
** -uuid: The SHA-1 of artifact corresponding to rid.
*/
struct mark_t{
char *name;
int rid;
char uuid[41];
};
#endif
/*
** Output a "committer" record for the given user.
*/
static void print_person(const char *zUser){
static Stmt q;
const char *zContact;
char *zName;
|
| ︙ | ︙ | |||
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | free(zName); free(zEmail); db_reset(&q); } #define BLOBMARK(rid) ((rid) * 2) #define COMMITMARK(rid) ((rid) * 2 + 1) /* ** COMMAND: export ** ** Usage: %fossil export --git ?OPTIONS? ?REPOSITORY? ** ** Write an export of all check-ins to standard output. The export is ** written in the git-fast-export file format assuming the --git option is ** provided. The git-fast-export format is currently the only VCS ** interchange format supported, though other formats may be added in ** the future. ** ** Run this command within a checkout. Or use the -R or --repository ** option to specify a Fossil repository to be exported. ** ** Only check-ins are exported using --git. Git does not support tickets | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 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 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 |
free(zName);
free(zEmail);
db_reset(&q);
}
#define BLOBMARK(rid) ((rid) * 2)
#define COMMITMARK(rid) ((rid) * 2 + 1)
/*
** insert_commit_xref()
** Insert a new (mark,rid,uuid) entry into the 'xmark' table.
** zName and zUuid must be non-null and must point to NULL-terminated strings.
*/
void insert_commit_xref(int rid, const char *zName, const char *zUuid){
db_multi_exec(
"INSERT OR IGNORE INTO xmark(tname, trid, tuuid)"
"VALUES(%Q,%d,%Q)",
zName, rid, zUuid
);
}
/*
** create_mark()
** Create a new (mark,rid,uuid) entry for the given rid in the 'xmark' table,
** and return that information as a struct mark_t in *mark.
** This function returns -1 in the case where 'rid' does not exist, otherwise
** it returns 0.
** mark->name is dynamically allocated and is owned by the caller upon return.
*/
int create_mark(int rid, struct mark_t *mark){
char sid[13];
char *zUuid = rid_to_uuid(rid);
if(!zUuid){
fossil_trace("Undefined rid=%d\n", rid);
return -1;
}
mark->rid = rid;
sqlite3_snprintf(sizeof(sid), sid, ":%d", COMMITMARK(rid));
mark->name = fossil_strdup(sid);
sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", zUuid);
free(zUuid);
insert_commit_xref(mark->rid, mark->name, mark->uuid);
return 0;
}
/*
** mark_name_from_rid()
** Find the mark associated with the given rid. Mark names always start
** with ':', and are pulled from the 'xmark' temporary table.
** This function returns NULL if the rid does not exist in the 'xmark' table.
** Otherwise, it returns the name of the mark, which is dynamically allocated
** and is owned by the caller of this function.
*/
char * mark_name_from_rid(int rid){
char *zMark = db_text(0, "SELECT tname FROM xmark WHERE trid=%d", rid);
if(zMark==NULL){
struct mark_t mark;
if(create_mark(rid, &mark)==0){
zMark = mark.name;
}else{
return NULL;
}
}
return zMark;
}
/*
** parse_mark()
** Create a new (mark,rid,uuid) entry in the 'xmark' table given a line
** from a marks file. Return the cross-ref information as a struct mark_t
** in *mark.
** This function returns -1 in the case that the line is blank, malformed, or
** the rid/uuid named in 'line' does not match what is in the repository
** database. Otherwise, 0 is returned.
** mark->name is dynamically allocated, and owned by the caller.
*/
int parse_mark(char *line, struct mark_t *mark){
char *cur_tok;
cur_tok = strtok(line, " \t");
if(!cur_tok||strlen(cur_tok)<2){
return -1;
}
mark->rid = atoi(&cur_tok[1]);
if(cur_tok[0]!='c'){
/* This is probably a blob mark */
mark->name = NULL;
return 0;
}
cur_tok = strtok(NULL, " \t");
if(!cur_tok){
/* This mark was generated by an older version of Fossil and doesn't
** include the mark name and uuid. create_mark() will name the new mark
** exactly as it was when exported to git, so that we should have a
** valid mapping from git sha1<->mark name<->fossil sha1. */
return create_mark(mark->rid, mark);
}else{
mark->name = fossil_strdup(cur_tok);
}
cur_tok = strtok(NULL, "\n");
if(!cur_tok||strlen(cur_tok)!=40){
free(mark->name);
fossil_trace("Invalid SHA-1 in marks file: %s\n", cur_tok);
return -1;
}else{
sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", cur_tok);
}
/* make sure that rid corresponds to UUID */
if(fast_uuid_to_rid(mark->uuid)!=mark->rid){
free(mark->name);
fossil_trace("Non-existent SHA-1 in marks file: %s\n", mark->uuid);
return -1;
}
/* insert a cross-ref into the 'xmark' table */
insert_commit_xref(mark->rid, mark->name, mark->uuid);
return 0;
}
/*
** import_marks()
** Import the marks specified in file 'f' into the 'xmark' table.
** If 'blobs' is non-null, insert all blob marks into it.
** If 'vers' is non-null, insert all commit marks into it.
** Each line in the file must be at most 100 characters in length. This
** seems like a reasonable maximum for a 40-character uuid, and 1-13
** character rid.
** The function returns -1 if any of the lines in file 'f' are malformed,
** or the rid/uuid information doesn't match what is in the repository
** database. Otherwise, 0 is returned.
*/
int import_marks(FILE* f, Bag *blobs, Bag *vers){
char line[101];
while(fgets(line, sizeof(line), f)){
struct mark_t mark;
if(strlen(line)==100&&line[99]!='\n'){
/* line too long */
return -1;
}
if( parse_mark(line, &mark)<0 ){
return -1;
}else if( line[0]=='b' ){
/* Don't import blob marks into 'xmark' table--git doesn't use them,
** so they need to be left free for git to reuse. */
if(blobs!=NULL){
bag_insert(blobs, mark.rid);
}
}else if( vers!=NULL ){
bag_insert(vers, mark.rid);
}
free(mark.name);
}
return 0;
}
/*
** If 'blobs' is non-null, it must point to a Bag of blob rids to be
** written to disk. Blob rids are written as 'b<rid>'.
** If 'vers' is non-null, it must point to a Bag of commit rids to be
** written to disk. Commit rids are written as 'c<rid> :<mark> <uuid>'.
** All commit (mark,rid,uuid) tuples are stored in 'xmark' table.
** This function does not fail, but may produce errors if a uuid cannot
** be found for an rid in 'vers'.
*/
void export_marks(FILE* f, Bag *blobs, Bag *vers){
int rid;
if( blobs!=NULL ){
rid = bag_first(blobs);
if(rid!=0){
do{
fprintf(f, "b%d\n", rid);
}while((rid = bag_next(blobs, rid))!=0);
}
}
if( vers!=NULL ){
rid = bag_first(vers);
if( rid!=0 ){
do{
char *zUuid = rid_to_uuid(rid);
char *zMark;
if(zUuid==NULL){
fossil_trace("No uuid matching rid=%d when exporting marks\n", rid);
continue;
}
zMark = mark_name_from_rid(rid);
fprintf(f, "c%d %s %s\n", rid, zMark, zUuid);
free(zMark);
free(zUuid);
}while( (rid = bag_next(vers, rid))!=0 );
}
}
}
/*
** COMMAND: export
**
** Usage: %fossil export --git ?OPTIONS? ?REPOSITORY?
**
** Write an export of all check-ins to standard output. The export is
** written in the git-fast-export file format assuming the --git option is
** provided. The git-fast-export format is currently the only VCS
** interchange format supported, though other formats may be added in
** the future.
**
** Run this command within a checkout. Or use the -R or --repository
** option to specify a Fossil repository to be exported.
**
** Only check-ins are exported using --git. Git does not support tickets
** or wiki or tech notes or attachments, so none of those are exported.
**
** If the "--import-marks FILE" option is used, it contains a list of
** rids to skip.
**
** If the "--export-marks FILE" option is used, the rid of all commits and
** blobs written on exit for use with "--import-marks" on the next run.
**
|
| ︙ | ︙ | |||
145 146 147 148 149 150 151 152 153 |
db_find_and_open_repository(0, 2);
verify_all_options();
if( g.argc!=2 && g.argc!=3 ){ usage("--git ?REPOSITORY?"); }
db_multi_exec("CREATE TEMPORARY TABLE oldblob(rid INTEGER PRIMARY KEY)");
db_multi_exec("CREATE TEMPORARY TABLE oldcommit(rid INTEGER PRIMARY KEY)");
if( markfile_in!=0 ){
Stmt qb,qc;
| > < > > > > < > | > | | > > | > | | < < < | 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 |
db_find_and_open_repository(0, 2);
verify_all_options();
if( g.argc!=2 && g.argc!=3 ){ usage("--git ?REPOSITORY?"); }
db_multi_exec("CREATE TEMPORARY TABLE oldblob(rid INTEGER PRIMARY KEY)");
db_multi_exec("CREATE TEMPORARY TABLE oldcommit(rid INTEGER PRIMARY KEY)");
db_multi_exec("CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT)");
if( markfile_in!=0 ){
Stmt qb,qc;
FILE *f;
int rid;
f = fossil_fopen(markfile_in, "r");
if( f==0 ){
fossil_fatal("cannot open %s for reading", markfile_in);
}
if(import_marks(f, &blobs, &vers)<0){
fossil_fatal("error importing marks from file: %s\n", markfile_in);
}
db_prepare(&qb, "INSERT OR IGNORE INTO oldblob VALUES (:rid)");
db_prepare(&qc, "INSERT OR IGNORE INTO oldcommit VALUES (:rid)");
rid = bag_first(&blobs);
if(rid!=0){
do{
db_bind_int(&qb, ":rid", rid);
db_step(&qb);
db_reset(&qb);
}while((rid = bag_next(&blobs, rid))!=0);
}
rid = bag_first(&vers);
if(rid!=0){
do{
db_bind_int(&qc, ":rid", rid);
db_step(&qc);
db_reset(&qc);
}while((rid = bag_next(&vers, rid))!=0);
}
db_finalize(&qb);
db_finalize(&qc);
fclose(f);
}
/* Step 1: Generate "blob" records for every artifact that is part
|
| ︙ | ︙ | |||
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
Stmt q4;
const char *zSecondsSince1970 = db_column_text(&q, 0);
int ckinId = db_column_int(&q, 1);
const char *zComment = db_column_text(&q, 2);
const char *zUser = db_column_text(&q, 3);
const char *zBranch = db_column_text(&q, 4);
char *zBr;
bag_insert(&vers, ckinId);
db_bind_int(&q2, ":rid", ckinId);
db_step(&q2);
db_reset(&q2);
if( zBranch==0 ) zBranch = "trunk";
zBr = mprintf("%s", zBranch);
for(i=0; zBr[i]; i++){
if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_';
}
| > > | > | > > > | > > | 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 |
Stmt q4;
const char *zSecondsSince1970 = db_column_text(&q, 0);
int ckinId = db_column_int(&q, 1);
const char *zComment = db_column_text(&q, 2);
const char *zUser = db_column_text(&q, 3);
const char *zBranch = db_column_text(&q, 4);
char *zBr;
char *zMark;
bag_insert(&vers, ckinId);
db_bind_int(&q2, ":rid", ckinId);
db_step(&q2);
db_reset(&q2);
if( zBranch==0 ) zBranch = "trunk";
zBr = mprintf("%s", zBranch);
for(i=0; zBr[i]; i++){
if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_';
}
zMark = mark_name_from_rid(ckinId);
printf("commit refs/heads/%s\nmark %s\n", zBr, zMark);
free(zMark);
free(zBr);
printf("committer");
print_person(zUser);
printf(" %s +0000\n", zSecondsSince1970);
if( zComment==0 ) zComment = "null comment";
printf("data %d\n%s\n", (int)strlen(zComment), zComment);
db_prepare(&q3,
"SELECT pid FROM plink"
" WHERE cid=%d AND isprim"
" AND pid IN (SELECT objid FROM event)",
ckinId
);
if( db_step(&q3) == SQLITE_ROW ){
int pid = db_column_int(&q3, 0);
zMark = mark_name_from_rid(pid);
printf("from %s\n", zMark);
free(zMark);
db_prepare(&q4,
"SELECT pid FROM plink"
" WHERE cid=%d AND NOT isprim"
" AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)"
" ORDER BY pid",
ckinId);
while( db_step(&q4)==SQLITE_ROW ){
zMark = mark_name_from_rid(db_column_int(&q4, 0));
printf("merge %s\n", zMark);
free(zMark);
}
db_finalize(&q4);
}else{
printf("deleteall\n");
}
db_prepare(&q4,
|
| ︙ | ︙ | |||
314 315 316 317 318 319 320 |
}
db_finalize(&q4);
db_finalize(&q3);
printf("\n");
}
db_finalize(&q2);
db_finalize(&q);
| < | 532 533 534 535 536 537 538 539 540 541 542 543 544 545 |
}
db_finalize(&q4);
db_finalize(&q3);
printf("\n");
}
db_finalize(&q2);
db_finalize(&q);
manifest_cache_clear();
/* Output tags */
db_prepare(&q,
"SELECT tagname, rid, strftime('%%s',mtime)"
" FROM tagxref JOIN tag USING(tagid)"
|
| ︙ | ︙ | |||
343 344 345 346 347 348 349 |
printf("tag %s\n", zEncoded);
printf("from :%d\n", COMMITMARK(rid));
printf("tagger <tagger> %s +0000\n", zSecSince1970);
printf("data 0\n");
fossil_free(zEncoded);
}
db_finalize(&q);
| < | < < < < < < < < < > > | 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 |
printf("tag %s\n", zEncoded);
printf("from :%d\n", COMMITMARK(rid));
printf("tagger <tagger> %s +0000\n", zSecSince1970);
printf("data 0\n");
fossil_free(zEncoded);
}
db_finalize(&q);
if( markfile_out!=0 ){
FILE *f;
f = fossil_fopen(markfile_out, "w");
if( f == 0 ){
fossil_fatal("cannot open %s for writing", markfile_out);
}
export_marks(f, &blobs, &vers);
if( ferror(f)!=0 || fclose(f)!=0 ) {
fossil_fatal("error while writing %s", markfile_out);
}
}
bag_clear(&blobs);
bag_clear(&vers);
}
|
Changes to src/file.c.
| ︙ | ︙ | |||
22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ** Functions named file_wd_* are to be used for files inside working ** directories. They follow symlinks depending on 'allow-symlinks' setting. */ #include "config.h" #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <string.h> #include <errno.h> #include "file.h" /* ** On Windows, include the Platform SDK header file. */ | > | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | ** Functions named file_wd_* are to be used for files inside working ** directories. They follow symlinks depending on 'allow-symlinks' setting. */ #include "config.h" #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <stdio.h> #include <string.h> #include <errno.h> #include "file.h" /* ** On Windows, include the Platform SDK header file. */ |
| ︙ | ︙ | |||
396 397 398 399 400 401 402 403 404 405 406 407 408 409 |
const char *zTail = file_tail(z);
if( zTail && zTail!=z ){
return mprintf("%.*s", (int)(zTail-z-1), z);
}else{
return 0;
}
}
/*
** Copy the content of a file from one place to another.
*/
void file_copy(const char *zFrom, const char *zTo){
FILE *in, *out;
int got;
| > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
const char *zTail = file_tail(z);
if( zTail && zTail!=z ){
return mprintf("%.*s", (int)(zTail-z-1), z);
}else{
return 0;
}
}
/*
** Rename a file or directory.
** Returns zero upon success.
*/
int file_rename(
const char *zFrom,
const char *zTo,
int isFromDir,
int isToDir
){
int rc;
#if defined(_WIN32)
wchar_t *zMbcsFrom = fossil_utf8_to_path(zFrom, isFromDir);
wchar_t *zMbcsTo = fossil_utf8_to_path(zTo, isToDir);
rc = _wrename(zMbcsFrom, zMbcsTo);
#else
char *zMbcsFrom = fossil_utf8_to_path(zFrom, isFromDir);
char *zMbcsTo = fossil_utf8_to_path(zTo, isToDir);
rc = rename(zMbcsFrom, zMbcsTo);
#endif
fossil_path_free(zMbcsTo);
fossil_path_free(zMbcsFrom);
return rc;
}
/*
** Copy the content of a file from one place to another.
*/
void file_copy(const char *zFrom, const char *zTo){
FILE *in, *out;
int got;
|
| ︙ | ︙ | |||
491 492 493 494 495 496 497 |
** Sets the mtime of the named file to the date/time shown.
*/
void test_set_mtime(void){
const char *zFile;
char *zDate;
i64 iMTime;
if( g.argc!=4 ){
| | | 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 |
** Sets the mtime of the named file to the date/time shown.
*/
void test_set_mtime(void){
const char *zFile;
char *zDate;
i64 iMTime;
if( g.argc!=4 ){
usage("FILENAME DATE/TIME");
}
db_open_or_attach(":memory:", "mem", 0);
iMTime = db_int64(0, "SELECT strftime('%%s',%Q)", g.argv[3]);
zFile = g.argv[2];
file_set_mtime(zFile, iMTime);
iMTime = file_wd_mtime(zFile);
zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", iMTime);
|
| ︙ | ︙ | |||
794 795 796 797 798 799 800 | z[j] = 0; return j; } /* ** COMMAND: test-simplify-name ** | | | 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 |
z[j] = 0;
return j;
}
/*
** COMMAND: test-simplify-name
**
** Usage: %fossil test-simplify-name FILENAME...
**
** Print the simplified versions of each FILENAME.
*/
void cmd_test_simplify_name(void){
int i;
char *z;
for(i=2; i<g.argc; i++){
|
| ︙ | ︙ | |||
894 895 896 897 898 899 900 |
}
#endif
blob_resize(pOut, file_simplify_name(blob_buffer(pOut),
blob_size(pOut), slash));
}
/*
| | > | 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 |
}
#endif
blob_resize(pOut, file_simplify_name(blob_buffer(pOut),
blob_size(pOut), slash));
}
/*
** COMMAND: test-canonical-name
**
** Usage: %fossil test-canonical-name FILENAME...
**
** Test the operation of the canonical name generator.
** Also test Fossil's ability to measure attributes of a file.
*/
void cmd_test_canonical_name(void){
int i;
|
| ︙ | ︙ | |||
1031 1032 1033 1034 1035 1036 1037 |
blob_append(&tmp, &zPath[i], -1);
blob_reset(pOut);
memcpy(pOut, &tmp, sizeof(tmp));
}
}
/*
| | | 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 |
blob_append(&tmp, &zPath[i], -1);
blob_reset(pOut);
memcpy(pOut, &tmp, sizeof(tmp));
}
}
/*
** COMMAND: test-relative-name
**
** Test the operation of the relative name generator.
*/
void cmd_test_relative_name(void){
int i;
Blob x;
int slashFlag = find_option("slash",0,0)!=0;
|
| ︙ | ︙ | |||
1145 1146 1147 1148 1149 1150 1151 | } blob_reset(&localRoot); blob_reset(&full); return 1; } /* | | | 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 | } blob_reset(&localRoot); blob_reset(&full); return 1; } /* ** COMMAND: test-tree-name ** ** Test the operation of the tree name generator. ** ** Options: ** --absolute Return an absolute path instead of a relative one. ** --case-sensitive B Enable or disable case-sensitive filenames. B is ** a boolean: "yes", "no", "true", "false", etc. |
| ︙ | ︙ |
Changes to src/finfo.c.
| ︙ | ︙ | |||
529 530 531 532 533 534 535 |
if( fpid>0 ){
@ %z(href("%R/fdiff?sbs=1&v1=%!S&v2=%!S",zPUuid,zUuid))[diff]</a>
}
}
if( fDebug & FINFO_DEBUG_MLINK ){
int ii;
char *zAncLink;
| | | 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 |
if( fpid>0 ){
@ %z(href("%R/fdiff?sbs=1&v1=%!S&v2=%!S",zPUuid,zUuid))[diff]</a>
}
}
if( fDebug & FINFO_DEBUG_MLINK ){
int ii;
char *zAncLink;
@ <br />fid=%d(frid) pid=%d(fpid) mid=%d(fmid)
if( nParent>0 ){
@ parents=%d(aParent[0])
for(ii=1; ii<nParent; ii++){
@ %d(aParent[ii])
}
}
zAncLink = href("%R/finfo?name=%T&ci=%!S&debug=1",zFilename,zCkin);
|
| ︙ | ︙ | |||
571 572 573 574 575 576 577 |
** a particular check-in. This screen is intended for use by developers
** in debugging Fossil.
*/
void mlink_page(void){
const char *zFName = P("name");
const char *zCI = P("ci");
Stmt q;
| | | 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 |
** a particular check-in. This screen is intended for use by developers
** in debugging Fossil.
*/
void mlink_page(void){
const char *zFName = P("name");
const char *zCI = P("ci");
Stmt q;
login_check_credentials();
if( !g.perm.Admin ){ login_needed(g.anon.Admin); return; }
style_header("MLINK Table");
if( zFName==0 && zCI==0 ){
@ <span class='generalError'>
@ Requires either a name= or ci= query parameter
@ </span>
|
| ︙ | ︙ | |||
674 675 676 677 678 679 680 |
/* 6 */ " mperm,"
/* 7 */ " isaux"
" FROM mlink WHERE mid=%d ORDER BY 1",
mid
);
@ <h1>MLINK table for check-in %h(zCI)</h1>
render_checkin_context(mid, 1);
| | | 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 |
/* 6 */ " mperm,"
/* 7 */ " isaux"
" FROM mlink WHERE mid=%d ORDER BY 1",
mid
);
@ <h1>MLINK table for check-in %h(zCI)</h1>
render_checkin_context(mid, 1);
@ <hr />
@ <div class='brlist'>
@ <table id='mlinktable'>
@ <thead><tr>
@ <th>File</th>
@ <th>From</th>
@ <th>Merge?</th>
@ <th>New</th>
|
| ︙ | ︙ |
Changes to src/foci.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 68 69 70 71 72 73 74 75 76 77 78 |
**
** Author contact information:
** drh@hwaci.com
** http://www.hwaci.com/drh/
**
*******************************************************************************
**
** This routine implements eponymous virtual table for SQLite that gives
** all of the files associated with a single check-in. The table works
** as a table-valued function.
**
** The source code filename "foci" is short for "Files of Check-in".
**
** Usage example:
**
** SELECT * FROM files_of_checkin('trunk');
**
** The "schema" for the temp.foci table is:
**
** CREATE TABLE files_of_checkin(
** checkinID INTEGER, -- RID for the check-in manifest
** filename TEXT, -- Name of a file
** uuid TEXT, -- SHA1 hash of the file
** previousName TEXT, -- Name of the file in previous check-in
** perm TEXT, -- Permissions on the file
** symname TEXT HIDDEN -- Symbolic name of the check-in.
** );
**
** The hidden symname column is (optionally) used as a query parameter to
** identify the particular check-in to parse. The checkinID parameter
** (such is a unique numeric RID rather than symbolic name) can also be used
** to identify the check-in. Example:
**
** SELECT * FROM files_of_checkin
** WHERE checkinID=symbolic_name_to_rid('trunk');
**
*/
#include "config.h"
#include "foci.h"
#include <assert.h>
/*
** The schema for the virtual table:
*/
static const char zFociSchema[] =
@ CREATE TABLE files_of_checkin(
@ checkinID INTEGER, -- RID for the check-in manifest
@ filename TEXT, -- Name of a file
@ uuid TEXT, -- SHA1 hash of the file
@ previousName TEXT, -- Name of the file in previous check-in
@ perm TEXT, -- Permissions on the file
@ symname TEXT HIDDEN -- Symbolic name of the check-in
@ );
;
#define FOCI_CHECKINID 0
#define FOCI_FILENAME 1
#define FOCI_UUID 2
#define FOCI_PREVNAME 3
#define FOCI_PERM 4
#define FOCI_SYMNAME 5
#if INTERFACE
/*
** The subclasses of sqlite3_vtab and sqlite3_vtab_cursor tables
** that implement the files_of_checkin virtual table.
*/
struct FociTable {
|
| ︙ | ︙ | |||
101 102 103 104 105 106 107 | return SQLITE_OK; } /* ** Available scan methods: ** ** (0) A full scan. Visit every manifest in the repo. (Slow) | | > | > | > > | > > > | 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 |
return SQLITE_OK;
}
/*
** Available scan methods:
**
** (0) A full scan. Visit every manifest in the repo. (Slow)
** (1) checkinID=?. visit only the single manifest specified.
** (2) symName=? visit only the single manifest specified.
*/
static int fociBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
int i;
pIdxInfo->estimatedCost = 10000.0;
for(i=0; i<pIdxInfo->nConstraint; i++){
if( pIdxInfo->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ
&& (pIdxInfo->aConstraint[i].iColumn==FOCI_CHECKINID
|| pIdxInfo->aConstraint[i].iColumn==FOCI_SYMNAME)
){
if( pIdxInfo->aConstraint[i].iColumn==FOCI_CHECKINID ){
pIdxInfo->idxNum = 1;
}else{
pIdxInfo->idxNum = 2;
}
pIdxInfo->estimatedCost = 1.0;
pIdxInfo->aConstraintUsage[i].argvIndex = 1;
pIdxInfo->aConstraintUsage[i].omit = 1;
break;
}
}
return SQLITE_OK;
|
| ︙ | ︙ | |||
164 165 166 167 168 169 170 |
sqlite3_vtab_cursor *pCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
FociCursor *pCur = (FociCursor *)pCursor;
manifest_destroy(pCur->pMan);
if( idxNum ){
| > > > > > > | | | | | | > > | 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 |
sqlite3_vtab_cursor *pCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
FociCursor *pCur = (FociCursor *)pCursor;
manifest_destroy(pCur->pMan);
if( idxNum ){
int rid;
if( idxNum==1 ){
rid = sqlite3_value_int(argv[0]);
}else{
rid = symbolic_name_to_rid((const char*)sqlite3_value_text(argv[0]),"ci");
}
pCur->pMan = manifest_get(rid, CFTYPE_MANIFEST, 0);
if( pCur->pMan ){
manifest_file_rewind(pCur->pMan);
pCur->pFile = manifest_file_next(pCur->pMan, 0);
}
}else{
pCur->pMan = 0;
}
pCur->iFile = 0;
return SQLITE_OK;
}
static int fociColumn(
sqlite3_vtab_cursor *pCursor,
sqlite3_context *ctx,
int i
){
FociCursor *pCsr = (FociCursor *)pCursor;
switch( i ){
case FOCI_CHECKINID:
sqlite3_result_int(ctx, pCsr->pMan->rid);
break;
case FOCI_FILENAME:
sqlite3_result_text(ctx, pCsr->pFile->zName, -1,
SQLITE_TRANSIENT);
break;
case FOCI_UUID:
sqlite3_result_text(ctx, pCsr->pFile->zUuid, -1,
SQLITE_TRANSIENT);
break;
case FOCI_PREVNAME:
sqlite3_result_text(ctx, pCsr->pFile->zPrior, -1,
SQLITE_TRANSIENT);
break;
case FOCI_PERM:
sqlite3_result_text(ctx, pCsr->pFile->zPerm, -1,
SQLITE_TRANSIENT);
break;
case FOCI_SYMNAME:
break;
}
return SQLITE_OK;
}
static int fociRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
FociCursor *pCsr = (FociCursor *)pCursor;
|
| ︙ | ︙ |
Added src/fshell.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
/*
** Copyright (c) 2016 D. Richard Hipp
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the Simplified BSD License (also
** known as the "2-Clause License" or "FreeBSD License".)
** This program is distributed in the hope that it will be useful,
** but without any warranty; without even the implied warranty of
** merchantability or fitness for a particular purpose.
**
** Author contact information:
** drh@hwaci.com
** http://www.hwaci.com/drh/
**
*******************************************************************************
**
** This module contains the code that implements the "fossil shell" command.
**
** The fossil shell prompts for lines of user input, then parses each line
** after the fashion of a standard Bourne shell and forks a child process
** to run the corresponding Fossil command. This only works on Unix.
**
** The "fossil shell" command is intended for use with SEE-enabled fossil.
** It allows multiple commands to be issued without having to reenter the
** crypto phasephrase for each command.
*/
#include "config.h"
#include "fshell.h"
#include <ctype.h>
#ifndef _WIN32
#include <sys/types.h>
#include <sys/wait.h>
#endif
/*
** COMMAND: shell*
**
** Usage: %fossil shell
**
** Prompt for lines of input from stdin. Parse each line and evaluate
** it as a separate fossil command, in a child process. The initial
** "fossil" is omitted from each line.
**
** This command only works on unix-like platforms that support fork().
** It is non-functional on Windows.
*/
void shell_cmd(void){
#ifdef _WIN32
fossil_fatal("the 'shell' command is not supported on windows");
#else
int nArg;
int mxArg = 0;
int n, i;
char **azArg = 0;
int fDebug;
pid_t childPid;
char zLine[10000];
fDebug = find_option("debug", 0, 0)!=0;
db_find_and_open_repository(OPEN_ANY_SCHEMA|OPEN_OK_NOT_FOUND, 0);
db_close(0);
sqlite3_shutdown();
while( printf("fossil> "),fflush(stdout),fgets(zLine, sizeof(zLine), stdin) ){
/* Parse the line of input */
n = (int)strlen(zLine);
for(i=0, nArg=1; i<n; i++){
while( fossil_isspace(zLine[i]) ){ i++; }
if( i>=n ) break;
if( nArg>=mxArg ){
mxArg = nArg+10;
azArg = fossil_realloc(azArg, sizeof(char*)*mxArg);
if( nArg==1 ) azArg[0] = g.argv[0];
}
if( zLine[i]=='"' || zLine[i]=='\'' ){
char cQuote = zLine[i];
i++;
azArg[nArg++] = &zLine[i];
for(i++; i<n && zLine[i]!=cQuote; i++){}
}else{
azArg[nArg++] = &zLine[i];
while( i<n && !isspace(zLine[i]) ){ i++; }
}
zLine[i] = 0;
}
/* If the --debug flag was used, display the parsed arguments */
if( fDebug ){
for(i=1; i<nArg; i++){
fossil_print("argv[%d] = [%s]\n", i, azArg[i]);
}
}
/* Special cases */
if( nArg<2 ) continue;
if( fossil_strcmp(azArg[1],"exit")==0 ) break;
/* Fork a process to handle the command */
childPid = fork();
if( childPid<0 ){
printf("could not fork a child process to handle the command\n");
fflush(stdout);
continue;
}
if( childPid==0 ){
/* This is the child process */
int main(int, char**);
main(nArg, azArg);
exit(0);
}else{
/* The parent process */
int status;
waitpid(childPid, &status, 0);
}
}
#endif
}
|
Changes to src/fusefs.c.
| ︙ | ︙ | |||
49 50 51 52 53 54 55 | ManifestFile *pFile; /* Name of a cached file */ Blob content; /* Content of the cached file */ /* Parsed path */ char *az[3]; /* 0=type, 1=id, 2=path */ } fusefs; /* | | | 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
ManifestFile *pFile; /* Name of a cached file */
Blob content; /* Content of the cached file */
/* Parsed path */
char *az[3]; /* 0=type, 1=id, 2=path */
} fusefs;
/*
** Clear the fusefs.az[] array.
*/
static void fusefs_clear_path(void){
int i;
for(i=0; i<count(fusefs.az); i++){
fossil_free(fusefs.az[i]);
fusefs.az[i] = 0;
}
|
| ︙ | ︙ | |||
287 288 289 290 291 292 293 | #endif /* FOSSIL_HAVE_FUSEFS */ /* ** COMMAND: fusefs ** ** Usage: %fossil fusefs [--debug] DIRECTORY ** | | | | | | | | 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 |
#endif /* FOSSIL_HAVE_FUSEFS */
/*
** COMMAND: fusefs
**
** Usage: %fossil fusefs [--debug] DIRECTORY
**
** This command uses the Fuse Filesystem (FuseFS) to mount a directory
** at DIRECTORY that contains the content of all check-ins in the
** repository. The names of files are DIRECTORY/checkins/VERSION/PATH
** where DIRECTORY is the root of the mount, VERSION is any valid
** check-in name (examples: "trunk" or "tip" or a tag or any unique
** prefix of a SHA1 hash, etc) and PATH is the pathname of the file in
** the check-in. If DIRECTORY does not exist, then an attempt is made
** to create it.
**
** The DIRECTORY/checkins directory is not searchable so one cannot
** do "ls DIRECTORY/checkins" to get a listing of all possible check-in
** names. There are countless variations on check-in names and it is
** impractical to list them all. But all other directories are searchable
** and so the "ls" command will work everywhere else in the fusefs
** file hierarchy.
**
** The FuseFS typically only works on Linux, and then only on Linux
** systems that have the right kernel drivers and have installed the
** appropriate support libraries.
**
** After stopping the "fossil fusefs" command, it might also be necessary
** to run "fusermount -u DIRECTORY" to reset the FuseFS before using it
** again.
*/
void fusefs_cmd(void){
|
| ︙ | ︙ |
Changes to src/graph.c.
| ︙ | ︙ | |||
216 217 218 219 220 221 222 | /* ** Return the index of a rail currently not in use for any row between ** top and bottom, inclusive. */ static int findFreeRail( GraphContext *p, /* The graph context */ int top, int btm, /* Span of rows for which the rail is needed */ | < > | 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
/*
** Return the index of a rail currently not in use for any row between
** top and bottom, inclusive.
*/
static int findFreeRail(
GraphContext *p, /* The graph context */
int top, int btm, /* Span of rows for which the rail is needed */
int iNearto /* Find rail nearest to this rail */
){
GraphRow *pRow;
int i;
int iBest = 0;
int iBestDist = 9999;
u64 inUseMask = 0;
for(pRow=p->pFirst; pRow && pRow->idx<top; pRow=pRow->pNext){}
while( pRow && pRow->idx<=btm ){
inUseMask |= pRow->railInUse;
pRow = pRow->pNext;
}
for(i=0; i<32; i++){
if( (inUseMask & BIT(i))==0 ){
|
| ︙ | ︙ | |||
297 298 299 300 301 302 303 |
** on the same rail. */
pParent->mergeOut = pParent->iRail;
pParent->mergeUpto = pChild->idx;
}else{
/* The thin merge arrow riser is taller than the thick primary
** child riser, so use separate rails. */
int iTarget = pParent->iRail;
| | < | 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 |
** on the same rail. */
pParent->mergeOut = pParent->iRail;
pParent->mergeUpto = pChild->idx;
}else{
/* The thin merge arrow riser is taller than the thick primary
** child riser, so use separate rails. */
int iTarget = pParent->iRail;
pParent->mergeOut = findFreeRail(p, pChild->idx, pParent->idx-1, iTarget);
pParent->mergeUpto = pChild->idx;
mask = BIT(pParent->mergeOut);
for(pLoop=pChild->pNext; pLoop && pLoop->rid!=pParent->rid;
pLoop=pLoop->pNext){
pLoop->railInUse |= mask;
}
}
|
| ︙ | ︙ | |||
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 |
if( pRow->mergeOut>p->mxRail ) p->mxRail = pRow->mergeOut;
while( p->mxRail<GR_MAX_RAIL && pRow->mergeDown>(BIT(p->mxRail+1)-1) ){
p->mxRail++;
}
}
}
/*
** Compute the complete graph
*/
void graph_finish(GraphContext *p, int omitDescenders){
GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent;
int i;
u64 mask;
| > > > > > > > > > > > > < | 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 |
if( pRow->mergeOut>p->mxRail ) p->mxRail = pRow->mergeOut;
while( p->mxRail<GR_MAX_RAIL && pRow->mergeDown>(BIT(p->mxRail+1)-1) ){
p->mxRail++;
}
}
}
/*
** Draw a riser from pRow to the top of the graph
*/
static void riser_to_top(GraphRow *pRow){
u64 mask = BIT(pRow->iRail);
pRow->aiRiser[pRow->iRail] = 0;
while( pRow ){
pRow->railInUse |= mask;
pRow = pRow->pPrev;
}
}
/*
** Compute the complete graph
*/
void graph_finish(GraphContext *p, int omitDescenders){
GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent;
int i;
u64 mask;
int hasDup = 0; /* True if one or more isDup entries */
const char *zTrunk;
if( p==0 || p->pFirst==0 || p->nErr ) return;
p->nErr = 1; /* Assume an error until proven otherwise */
/* Initialize all rows */
|
| ︙ | ︙ | |||
438 439 440 441 442 443 444 |
if( i==0 ){
if( pRow->zBranch!=zTrunk ) continue;
}else {
if( pRow->iRail>=0 ) continue;
}
if( pRow->nParent==0 || hashFind(p,pRow->aParent[0])==0 ){
if( omitDescenders ){
| | < | < < < | < < < | < | < < < > > | | 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 |
if( i==0 ){
if( pRow->zBranch!=zTrunk ) continue;
}else {
if( pRow->iRail>=0 ) continue;
}
if( pRow->nParent==0 || hashFind(p,pRow->aParent[0])==0 ){
if( omitDescenders ){
pRow->iRail = findFreeRail(p, pRow->idxTop, pRow->idx, 0);
}else{
pRow->iRail = ++p->mxRail;
}
if( p->mxRail>=GR_MAX_RAIL ) return;
mask = BIT(pRow->iRail);
if( !omitDescenders ){
pRow->bDescender = pRow->nParent>0;
for(pLoop=pRow; pLoop; pLoop=pLoop->pNext){
pLoop->railInUse |= mask;
}
}
assignChildrenToRail(pRow);
}
}
}
/* Assign rails to all rows that are still unassigned.
*/
for(pRow=p->pLast; pRow; pRow=pRow->pPrev){
int parentRid;
if( pRow->iRail>=0 ){
if( pRow->pChild==0 && !pRow->timeWarp ){
if( !omitDescenders && count_nonbranch_children(pRow->rid)!=0 ){
riser_to_top(pRow);
}
}
continue;
}
if( pRow->isDup ){
continue;
}else{
assert( pRow->nParent>0 );
parentRid = pRow->aParent[0];
pParent = hashFind(p, parentRid);
if( pParent==0 ){
pRow->iRail = ++p->mxRail;
if( p->mxRail>=GR_MAX_RAIL ) return;
pRow->railInUse = BIT(pRow->iRail);
continue;
}
if( pParent->idx>pRow->idx ){
/* Common case: Child occurs after parent and is above the
** parent in the timeline */
pRow->iRail = findFreeRail(p, 0, pParent->idx, pParent->iRail);
if( p->mxRail>=GR_MAX_RAIL ) return;
pParent->aiRiser[pRow->iRail] = pRow->idx;
}else{
/* Timewarp case: Child occurs earlier in time than parent and
** appears below the parent in the timeline. */
int iDownRail = ++p->mxRail;
if( iDownRail<1 ) iDownRail = ++p->mxRail;
pRow->iRail = ++p->mxRail;
if( p->mxRail>=GR_MAX_RAIL ) return;
pRow->railInUse = BIT(pRow->iRail);
pParent->aiRiser[iDownRail] = pRow->idx;
mask = BIT(iDownRail);
for(pLoop=p->pFirst; pLoop; pLoop=pLoop->pNext){
pLoop->railInUse |= mask;
}
}
}
mask = BIT(pRow->iRail);
pRow->railInUse |= mask;
if( pRow->pChild ){
assignChildrenToRail(pRow);
}else if( !omitDescenders && count_nonbranch_children(pRow->rid)!=0 ){
riser_to_top(pRow);
}
if( pParent ){
for(pLoop=pParent->pPrev; pLoop && pLoop!=pRow; pLoop=pLoop->pPrev){
pLoop->railInUse |= mask;
}
}
}
/*
** Insert merge rails and merge arrows
*/
for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
for(i=1; i<pRow->nParent; i++){
int parentRid = pRow->aParent[i];
pDesc = hashFind(p, parentRid);
if( pDesc==0 ){
/* Merge from a node that is off-screen */
int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0);
if( p->mxRail>=GR_MAX_RAIL ) return;
mask = BIT(iMrail);
pRow->mergeIn[iMrail] = 1;
pRow->mergeDown |= mask;
for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){
pLoop->railInUse |= mask;
}
|
| ︙ | ︙ |
Changes to src/http_socket.c.
| ︙ | ︙ | |||
144 145 146 147 148 149 150 151 | struct addrinfo *ai = 0; struct addrinfo *p; struct addrinfo hints; char zPort[30]; char zRemote[NI_MAXHOST]; socket_global_init(); memset(&hints, 0, sizeof(struct addrinfo)); | > < | 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
struct addrinfo *ai = 0;
struct addrinfo *p;
struct addrinfo hints;
char zPort[30];
char zRemote[NI_MAXHOST];
socket_global_init();
socket_close();
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = g.fIPv4 ? AF_INET : AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
sqlite3_snprintf(sizeof(zPort),zPort,"%d", pUrlData->port);
rc = getaddrinfo(pUrlData->name, zPort, &hints, &ai);
if( rc ){
socket_set_errmsg("getaddrinfo() fails: %s", gai_strerror(rc));
|
| ︙ | ︙ |
Changes to src/http_ssl.c.
| ︙ | ︙ | |||
450 451 452 453 454 455 456 |
return cert;
}
/*
** Send content out over the SSL connection.
*/
size_t ssl_send(void *NotUsed, void *pContent, size_t N){
| < | | > > > > > < | | > > > > > | 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 |
return cert;
}
/*
** Send content out over the SSL connection.
*/
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 SSL connection.
*/
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;
}
|
| ︙ | ︙ |
Changes to src/import.c.
| ︙ | ︙ | |||
32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
char *zPrior; /* Prior name if the name was changed */
char isFrom; /* True if obtained from the parent */
char isExe; /* True if executable */
char isLink; /* True if symlink */
};
#endif
/*
** State information about an on-going fast-import parse.
*/
static struct {
void (*xFinish)(void); /* Function to finish a prior record */
int nData; /* Bytes of data */
| > > > > > > > > > > | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
char *zPrior; /* Prior name if the name was changed */
char isFrom; /* True if obtained from the parent */
char isExe; /* True if executable */
char isLink; /* True if symlink */
};
#endif
/*
** State information common to all import types.
*/
static struct {
const char *zTrunkName; /* Name of trunk branch */
const char *zBranchPre; /* Prepended to non-trunk branch names */
const char *zBranchSuf; /* Appended to non-trunk branch names */
const char *zTagPre; /* Prepended to non-trunk tag names */
const char *zTagSuf; /* Appended to non-trunk tag names */
} gimport;
/*
** State information about an on-going fast-import parse.
*/
static struct {
void (*xFinish)(void); /* Function to finish a prior record */
int nData; /* Bytes of data */
|
| ︙ | ︙ | |||
196 197 198 199 200 201 202 |
** control artifact to the BLOB table.
*/
static void finish_tag(void){
Blob record, cksum;
if( gg.zDate && gg.zTag && gg.zFrom && gg.zUser ){
blob_zero(&record);
blob_appendf(&record, "D %s\n", gg.zDate);
| | > | 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
** control artifact to the BLOB table.
*/
static void finish_tag(void){
Blob record, cksum;
if( gg.zDate && gg.zTag && gg.zFrom && gg.zUser ){
blob_zero(&record);
blob_appendf(&record, "D %s\n", gg.zDate);
blob_appendf(&record, "T +%F%F%F %s\n", gimport.zTagPre, gg.zTag,
gimport.zTagSuf, gg.zFrom);
blob_appendf(&record, "U %F\n", gg.zUser);
md5sum_blob(&record, &cksum);
blob_appendf(&record, "Z %b\n", &cksum);
fast_insert_content(&record, 0, 0, 1);
blob_reset(&cksum);
}
import_reset(0);
|
| ︙ | ︙ | |||
273 274 275 276 277 278 279 |
zFromBranch = 0;
}
/* Add the required "T" cards to the manifest. Make sure they are added
** in sorted order and without any duplicates. Otherwise, fossil will not
** recognize the document as a valid manifest. */
if( !gg.tagCommit && fossil_strcmp(zFromBranch, gg.zBranch)!=0 ){
| | > | > | > | | 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 |
zFromBranch = 0;
}
/* Add the required "T" cards to the manifest. Make sure they are added
** in sorted order and without any duplicates. Otherwise, fossil will not
** recognize the document as a valid manifest. */
if( !gg.tagCommit && fossil_strcmp(zFromBranch, gg.zBranch)!=0 ){
aTCard[nTCard++] = mprintf("T *branch * %F%F%F\n", gimport.zBranchPre,
gg.zBranch, gimport.zBranchSuf);
aTCard[nTCard++] = mprintf("T *sym-%F%F%F *\n", gimport.zBranchPre,
gg.zBranch, gimport.zBranchSuf);
if( zFromBranch ){
aTCard[nTCard++] = mprintf("T -sym-%F%F%F *\n", gimport.zBranchPre,
zFromBranch, gimport.zBranchSuf);
}
}
if( gg.zFrom==0 ){
aTCard[nTCard++] = mprintf("T *sym-%F *\n", gimport.zTrunkName);
}
qsort(aTCard, nTCard, sizeof(char *), string_cmp);
for(i=0; i<nTCard; i++){
if( i==0 || fossil_strcmp(aTCard[i-1], aTCard[i]) ){
blob_appendf(&record, "%s", aTCard[i]);
}
}
|
| ︙ | ︙ | |||
311 312 313 314 315 316 317 |
** but overwrite that entry if a later instance of the same tag appears.
**
** This behavior seems like a bug in git-fast-export, but it is easier
** to work around the problem than to fix git-fast-export.
*/
if( gg.tagCommit && gg.zDate && gg.zUser && gg.zFrom ){
blob_appendf(&record, "D %s\n", gg.zDate);
| | > | 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 |
** but overwrite that entry if a later instance of the same tag appears.
**
** This behavior seems like a bug in git-fast-export, but it is easier
** to work around the problem than to fix git-fast-export.
*/
if( gg.tagCommit && gg.zDate && gg.zUser && gg.zFrom ){
blob_appendf(&record, "D %s\n", gg.zDate);
blob_appendf(&record, "T +sym-%F%F%F %s\n", gimport.zBranchPre, gg.zBranch,
gimport.zBranchSuf, gg.zPrevCheckin);
blob_appendf(&record, "U %F\n", gg.zUser);
md5sum_blob(&record, &cksum);
blob_appendf(&record, "Z %b\n", &cksum);
db_multi_exec(
"INSERT OR REPLACE INTO xtag(tname, tcontent)"
" VALUES(%Q,%Q)", gg.zBranch, blob_str(&record)
);
|
| ︙ | ︙ | |||
747 748 749 750 751 752 753 | const char *zTrunk; /* Name of trunk folder in repo root */ int lenTrunk; /* String length of zTrunk */ const char *zBranches; /* Name of branches folder in repo root */ int lenBranches; /* String length of zBranches */ const char *zTags; /* Name of tags folder in repo root */ int lenTags; /* String length of zTags */ Bag newBranches; /* Branches that were created in this revision */ | | > > > | 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 |
const char *zTrunk; /* Name of trunk folder in repo root */
int lenTrunk; /* String length of zTrunk */
const char *zBranches; /* Name of branches folder in repo root */
int lenBranches; /* String length of zBranches */
const char *zTags; /* Name of tags folder in repo root */
int lenTags; /* String length of zTags */
Bag newBranches; /* Branches that were created in this revision */
int revFlag; /* Add svn-rev-nn tags on every checkin */
const char *zRevPre; /* Prepended to revision tag names */
const char *zRevSuf; /* Appended to revision tag names */
const char **azIgnTree; /* NULL-terminated list of dirs to ignore */
} gsvn;
typedef struct {
char *zKey;
char *zVal;
} KeyVal;
typedef struct {
KeyVal *aHeaders;
|
| ︙ | ︙ | |||
923 924 925 926 927 928 929 | } /* ** Returns the UUID for the RID, or NULL if not found. ** The returned string is allocated via db_text() and must be ** free()d by the caller. */ | | < | 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 |
}
/*
** Returns the UUID for the RID, or NULL if not found.
** The returned string is allocated via db_text() and must be
** free()d by the caller.
*/
char *rid_to_uuid(int rid){
return db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
}
#define SVN_UNKNOWN 0
#define SVN_TRUNK 1
#define SVN_BRANCH 2
#define SVN_TAG 3
|
| ︙ | ︙ | |||
967 968 969 970 971 972 973 |
if( !bag_find(&gsvn.newBranches, branchId) ){
parentRid = db_int(0, "SELECT trid, max(trev) FROM xrevisions"
" WHERE trev<%d AND tbranch=%d",
gsvn.rev, branchId);
}
if( parentRid>0 ){
pParentManifest = manifest_get(parentRid, CFTYPE_MANIFEST, 0);
| > | | | | | > | 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 |
if( !bag_find(&gsvn.newBranches, branchId) ){
parentRid = db_int(0, "SELECT trid, max(trev) FROM xrevisions"
" WHERE trev<%d AND tbranch=%d",
gsvn.rev, branchId);
}
if( parentRid>0 ){
pParentManifest = manifest_get(parentRid, CFTYPE_MANIFEST, 0);
if( pParentManifest ){
pParentFile = manifest_file_next(pParentManifest, 0);
parentBranch = db_int(0, "SELECT tbranch FROM xrevisions WHERE trid=%d",
parentRid);
if( parentBranch!=branchId && branchType!=SVN_TAG ){
sameAsParent = 0;
}
}
}
if( mergeRid<MAX_INT_32 ){
if( gsvn.zComment ){
blob_appendf(&manifest, "C %F\n", gsvn.zComment);
}else{
blob_append(&manifest, "C (no\\scomment)\n", 16);
|
| ︙ | ︙ | |||
1016 1017 1018 1019 1020 1021 1022 |
char *zParentUuid = rid_to_uuid(parentRid);
if( parentRid==mergeRid || mergeRid==0){
char *zParentBranch =
db_text(0, "SELECT tname FROM xbranches WHERE tid=%d",
parentBranch
);
blob_appendf(&manifest, "P %s\n", zParentUuid);
| | > | > | | > | > | | > | > | > | | > | > | > | 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 |
char *zParentUuid = rid_to_uuid(parentRid);
if( parentRid==mergeRid || mergeRid==0){
char *zParentBranch =
db_text(0, "SELECT tname FROM xbranches WHERE tid=%d",
parentBranch
);
blob_appendf(&manifest, "P %s\n", zParentUuid);
blob_appendf(&manifest, "T *branch * %F%F%F\n", gimport.zBranchPre,
zBranch, gimport.zBranchSuf);
blob_appendf(&manifest, "T *sym-%F%F%F *\n", gimport.zBranchPre,
zBranch, gimport.zBranchSuf);
if( gsvn.revFlag ){
blob_appendf(&manifest, "T +sym-%Fr%d%F *\n", gimport.zTagPre,
gsvn.rev, gimport.zTagSuf);
}
blob_appendf(&manifest, "T -sym-%F%F%F *\n", gimport.zBranchPre,
zParentBranch, gimport.zBranchSuf);
fossil_free(zParentBranch);
}else{
char *zMergeUuid = rid_to_uuid(mergeRid);
blob_appendf(&manifest, "P %s %s\n", zParentUuid, zMergeUuid);
if( gsvn.revFlag ){
blob_appendf(&manifest, "T +sym-%F%d%F *\n", gsvn.zRevPre,
gsvn.rev, gsvn.zRevSuf);
}
fossil_free(zMergeUuid);
}
fossil_free(zParentUuid);
}else{
blob_appendf(&manifest, "T *branch * %F%F%F\n",
gimport.zBranchPre, zBranch, gimport.zBranchSuf);
blob_appendf(&manifest, "T *sym-%F%F%F *\n", gimport.zBranchPre,
zBranch, gimport.zBranchSuf);
if( gsvn.revFlag ){
blob_appendf(&manifest, "T +sym-%F%d%F *\n", gsvn.zRevPre, gsvn.rev,
gsvn.zRevSuf);
}
}
}else if( branchType==SVN_TAG ){
char *zParentUuid = rid_to_uuid(parentRid);
blob_reset(&manifest);
blob_appendf(&manifest, "D %s\n", gsvn.zDate);
blob_appendf(&manifest, "T +sym-%F%F%F %s\n", gimport.zTagPre, zBranch,
gimport.zTagSuf, zParentUuid);
fossil_free(zParentUuid);
}
}else{
char *zParentUuid = rid_to_uuid(parentRid);
blob_appendf(&manifest, "D %s\n", gsvn.zDate);
if( branchType!=SVN_TAG ){
blob_appendf(&manifest, "T +closed %s\n", zParentUuid);
}else{
blob_appendf(&manifest, "T -sym-%F%F%F %s\n", gimport.zBranchPre,
zBranch, gimport.zBranchSuf, zParentUuid);
}
fossil_free(zParentUuid);
}
if( gsvn.zUser ){
blob_appendf(&manifest, "U %F\n", gsvn.zUser);
}else{
const char *zUserOvrd = find_option("user-override",0,1);
|
| ︙ | ︙ | |||
1151 1152 1153 1154 1155 1156 1157 |
}
zDiff += lenData;
}
}
/*
** Extract the branch or tag that the given path is on. Return the branch ID.
| > | > > > > > > > > > > > > | 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 |
}
zDiff += lenData;
}
}
/*
** Extract the branch or tag that the given path is on. Return the branch ID.
** Return 0 if not a branch, tag, or trunk, or if ignored by --ignore-tree.
*/
static int svn_parse_path(char *zPath, char **zFile, int *type){
char *zBranch = 0;
int branchId = 0;
if( gsvn.azIgnTree ){
const char **pzIgnTree;
unsigned nPath = strlen(zPath);
for( pzIgnTree = gsvn.azIgnTree; *pzIgnTree; ++pzIgnTree ){
const char *zIgn = *pzIgnTree;
int nIgn = strlen(zIgn);
if( strncmp(zPath, zIgn, nIgn) == 0
&& ( nPath == nIgn || (nPath > nIgn && zPath[nIgn] == '/')) ){
return 0;
}
}
}
*type = SVN_UNKNOWN;
*zFile = 0;
if( gsvn.lenTrunk==0 ){
zBranch = "trunk";
*zFile = zPath;
*type = SVN_TRUNK;
}else
|
| ︙ | ︙ | |||
1432 1433 1434 1435 1436 1437 1438 |
}
}else
if( strncmp(zAction, "change", 6)==0 ){
int rid = 0;
if( zKind==0 ){
fossil_fatal("Missing Node-kind");
}
| | | 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 |
}
}else
if( strncmp(zAction, "change", 6)==0 ){
int rid = 0;
if( zKind==0 ){
fossil_fatal("Missing Node-kind");
}
if( rec.contentFlag && strncmp(zKind, "dir", 3)!=0 ){
if( deltaFlag ){
Blob deltaSrc;
Blob target;
rid = db_int(0, "SELECT rid FROM blob WHERE uuid=("
" SELECT tuuid FROM xfiles"
" WHERE tpath=%Q AND tbranch=%d"
")", zFile, branchId);
|
| ︙ | ︙ | |||
1492 1493 1494 1495 1496 1497 1498 1499 | ** construct a new Fossil repository named by the NEW-REPOSITORY ** argument. If no input file is supplied the interchange format ** data is read from standard input. ** ** The following formats are currently understood by this command ** ** --git Import from the git-fast-export file format (default) ** | > > > | | | > > > > > | | | | | > > > | > > > > > > > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | > > > > > > > > > > > | | | > | 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 1636 1637 1638 1639 1640 1641 1642 1643 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 |
** construct a new Fossil repository named by the NEW-REPOSITORY
** argument. If no input file is supplied the interchange format
** data is read from standard input.
**
** The following formats are currently understood by this command
**
** --git Import from the git-fast-export file format (default)
** Options:
** --import-marks FILE Restore marks table from FILE
** --export-marks FILE Save marks table to FILE
**
** --svn Import from the svnadmin-dump file format. The default
** behaviour (unless overridden by --flat) is to treat 3
** folders in the SVN root as special, following the
** common layout of SVN repositories. These are (by
** default) trunk/, branches/ and tags/. The SVN --deltas
** format is supported but not required.
** Options:
** --trunk FOLDER Name of trunk folder
** --branches FOLDER Name of branches folder
** --tags FOLDER Name of tags folder
** --base PATH Path to project root in repository
** --flat The whole dump is a single branch
** --rev-tags Tag each revision, implied by -i
** --no-rev-tags Disables tagging effect of -i
** --rename-rev PAT Rev tag names, default "svn-rev-%"
** --ignore-tree DIR Ignores subtree rooted at DIR
**
** Common Options:
** -i|--incremental allow importing into an existing repository
** -f|--force overwrite repository if already exists
** -q|--quiet omit progress output
** --no-rebuild skip the "rebuilding metadata" step
** --no-vacuum skip the final VACUUM of the database file
** --rename-trunk NAME use NAME as name of imported trunk branch
** --rename-branch PAT rename all branch names using PAT pattern
** --rename-tag PAT rename all tag names using PAT pattern
**
** The --incremental option allows an existing repository to be extended
** with new content. The --rename-* options may be useful to avoid name
** conflicts when using the --incremental option.
**
** The argument to --rename-* contains one "%" character to be replaced
** with the original name. For example, "--rename-tag svn-%-tag" renames
** the tag called "release" to "svn-release-tag".
**
** --ignore-tree is useful for importing Subversion repositories which
** move branches to subdirectories of "branches/deleted" instead of
** deleting them. It can be supplied multiple times if necessary.
**
** See also: export
*/
void import_cmd(void){
char *zPassword;
FILE *pIn;
Stmt q;
int forceFlag = find_option("force", "f", 0)!=0;
int svnFlag = find_option("svn", 0, 0)!=0;
int gitFlag = find_option("git", 0, 0)!=0;
int omitRebuild = find_option("no-rebuild",0,0)!=0;
int omitVacuum = find_option("no-vacuum",0,0)!=0;
/* Options common to all input formats */
int incrFlag = find_option("incremental", "i", 0)!=0;
/* Options for --svn only */
const char *zBase = "";
int flatFlag = 0;
/* Options for --git only */
const char *markfile_in = 0;
const char *markfile_out = 0;
/* Interpret --rename-* options. Use a table to avoid code duplication. */
const struct {
const char *zOpt, **varPre, *zDefaultPre, **varSuf, *zDefaultSuf;
int format; /* 1=git, 2=svn, 3=any */
} renOpts[] = {
{"rename-branch", &gimport.zBranchPre, "", &gimport.zBranchSuf, "", 3},
{"rename-tag" , &gimport.zTagPre , "", &gimport.zTagSuf , "", 3},
{"rename-rev" , &gsvn.zRevPre, "svn-rev-", &gsvn.zRevSuf , "", 2},
}, *renOpt = renOpts;
int i;
for( i = 0; i < sizeof(renOpts) / sizeof(*renOpts); ++i, ++renOpt ){
if( 1 << svnFlag & renOpt->format ){
const char *zArgument = find_option(renOpt->zOpt, 0, 1);
if( zArgument ){
const char *sep = strchr(zArgument, '%');
if( !sep ){
fossil_fatal("missing '%%' in argument to --%s", renOpt->zOpt);
}else if( strchr(sep + 1, '%') ){
fossil_fatal("multiple '%%' in argument to --%s", renOpt->zOpt);
}
*renOpt->varPre = fossil_malloc(sep - zArgument + 1);
memcpy((char *)*renOpt->varPre, zArgument, sep - zArgument);
((char *)*renOpt->varPre)[sep - zArgument] = 0;
*renOpt->varSuf = sep + 1;
}else{
*renOpt->varPre = renOpt->zDefaultPre;
*renOpt->varSuf = renOpt->zDefaultSuf;
}
}
}
if( !(gimport.zTrunkName = find_option("rename-trunk", 0, 1)) ){
gimport.zTrunkName = "trunk";
}
if( svnFlag ){
/* Get --svn related options here, so verify_all_options() fails when
* svn-only options are specified with --git
*/
const char *zIgnTree;
unsigned nIgnTree = 0;
while( (zIgnTree = find_option("ignore-tree", 0, 1)) ){
if ( *zIgnTree ){
gsvn.azIgnTree = fossil_realloc(gsvn.azIgnTree,
sizeof(*gsvn.azIgnTree) * (nIgnTree + 2));
gsvn.azIgnTree[nIgnTree++] = zIgnTree;
gsvn.azIgnTree[nIgnTree] = 0;
}
}
zBase = find_option("base", 0, 1);
flatFlag = find_option("flat", 0, 0)!=0;
gsvn.zTrunk = find_option("trunk", 0, 1);
gsvn.zBranches = find_option("branches", 0, 1);
gsvn.zTags = find_option("tags", 0, 1);
gsvn.revFlag = find_option("rev-tags", 0, 0)
|| (incrFlag && !find_option("no-rev-tags", 0, 0));
}else if( gitFlag ){
markfile_in = find_option("import-marks", 0, 1);
markfile_out = find_option("export-marks", 0, 1);
}
verify_all_options();
if( g.argc!=3 && g.argc!=4 ){
usage("--git|--svn ?OPTIONS? NEW-REPOSITORY ?INPUT-FILE?");
}
if( g.argc==4 ){
|
| ︙ | ︙ | |||
1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 |
if( gsvn.zTags[gsvn.lenTags-1]!='/' ){
gsvn.zTags = mprintf("%s/", gsvn.zTags);
gsvn.lenTags++;
}
}
svn_dump_import(pIn);
}else{
/* The following temp-tables are used to hold information needed for
** the import.
**
** The XMARK table provides a mapping from fast-import "marks" and symbols
** into artifact ids (UUIDs - the 40-byte hex SHA1 hash of artifacts).
** Given any valid fast-import symbol, the corresponding fossil rid and
** uuid can found by searching against the xmark.tname field.
| > > > | 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 |
if( gsvn.zTags[gsvn.lenTags-1]!='/' ){
gsvn.zTags = mprintf("%s/", gsvn.zTags);
gsvn.lenTags++;
}
}
svn_dump_import(pIn);
}else{
Bag blobs, vers;
bag_init(&blobs);
bag_init(&vers);
/* The following temp-tables are used to hold information needed for
** the import.
**
** The XMARK table provides a mapping from fast-import "marks" and symbols
** into artifact ids (UUIDs - the 40-byte hex SHA1 hash of artifacts).
** Given any valid fast-import symbol, the corresponding fossil rid and
** uuid can found by searching against the xmark.tname field.
|
| ︙ | ︙ | |||
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 |
** occurrence of the tag is the last until the import finishes.
*/
db_multi_exec(
"CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT);"
"CREATE TEMP TABLE xbranch(tname TEXT UNIQUE, brnm TEXT);"
"CREATE TEMP TABLE xtag(tname TEXT UNIQUE, tcontent TEXT);"
);
manifest_crosslink_begin();
git_fast_import(pIn);
db_prepare(&q, "SELECT tcontent FROM xtag");
while( db_step(&q)==SQLITE_ROW ){
Blob record;
db_ephemeral_blob(&q, 0, &record);
fast_insert_content(&record, 0, 0, 1);
import_reset(0);
}
db_finalize(&q);
manifest_crosslink_end(MC_NONE);
}
verify_cancel();
db_end_transaction(0);
fossil_print(" \r");
if( omitRebuild ){
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
** occurrence of the tag is the last until the import finishes.
*/
db_multi_exec(
"CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT);"
"CREATE TEMP TABLE xbranch(tname TEXT UNIQUE, brnm TEXT);"
"CREATE TEMP TABLE xtag(tname TEXT UNIQUE, tcontent TEXT);"
);
if( markfile_in ){
FILE *f = fossil_fopen(markfile_in, "r");
if( !f ){
fossil_fatal("cannot open %s for reading\n", markfile_in);
}
if(import_marks(f, &blobs, NULL)<0){
fossil_fatal("error importing marks from file: %s\n", markfile_in);
}
fclose(f);
}
manifest_crosslink_begin();
git_fast_import(pIn);
db_prepare(&q, "SELECT tcontent FROM xtag");
while( db_step(&q)==SQLITE_ROW ){
Blob record;
db_ephemeral_blob(&q, 0, &record);
fast_insert_content(&record, 0, 0, 1);
import_reset(0);
}
db_finalize(&q);
if( markfile_out ){
int rid;
Stmt q_marks;
FILE *f;
db_prepare(&q_marks, "SELECT DISTINCT trid FROM xmark");
while( db_step(&q_marks)==SQLITE_ROW ){
rid = db_column_int(&q_marks, 0);
if( db_int(0, "SELECT count(objid) FROM event"
" WHERE objid=%d AND type='ci'", rid)==0 ){
if( bag_find(&blobs, rid)==0 ){
bag_insert(&blobs, rid);
}
}else{
bag_insert(&vers, rid);
}
}
db_finalize(&q_marks);
f = fossil_fopen(markfile_out, "w");
if( !f ){
fossil_fatal("cannot open %s for writing\n", markfile_out);
}
export_marks(f, &blobs, &vers);
fclose(f);
bag_clear(&blobs);
bag_clear(&vers);
}
manifest_crosslink_end(MC_NONE);
}
verify_cancel();
db_end_transaction(0);
fossil_print(" \r");
if( omitRebuild ){
|
| ︙ | ︙ |
Changes to src/info.c.
| ︙ | ︙ | |||
1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 |
);
while( db_step(&q)==SQLITE_ROW ){
const char *zDate = db_column_text(&q, 0);
const char *zUser = db_column_text(&q, 1);
const char *zCom = db_column_text(&q, 2);
const char *zType = db_column_text(&q, 3);
const char *zUuid = db_column_text(&q, 4);
if( cnt>0 ){
@ Also
}
if( zType[0]=='w' ){
@ Wiki edit
objType |= OBJTYPE_WIKI;
}else if( zType[0]=='t' ){
@ Ticket change
objType |= OBJTYPE_TICKET;
}else if( zType[0]=='c' ){
@ Manifest of check-in
objType |= OBJTYPE_CHECKIN;
}else if( zType[0]=='e' ){
| > > | | | > > > | | 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 |
);
while( db_step(&q)==SQLITE_ROW ){
const char *zDate = db_column_text(&q, 0);
const char *zUser = db_column_text(&q, 1);
const char *zCom = db_column_text(&q, 2);
const char *zType = db_column_text(&q, 3);
const char *zUuid = db_column_text(&q, 4);
int eventTagId = db_column_int(&q, 5);
if( cnt>0 ){
@ Also
}
if( zType[0]=='w' ){
@ Wiki edit
objType |= OBJTYPE_WIKI;
}else if( zType[0]=='t' ){
@ Ticket change
objType |= OBJTYPE_TICKET;
}else if( zType[0]=='c' ){
@ Manifest of check-in
objType |= OBJTYPE_CHECKIN;
}else if( zType[0]=='e' ){
if( eventTagId != 0) {
@ Instance of technote
objType |= OBJTYPE_EVENT;
hyperlink_to_event_tagid(db_column_int(&q, 5));
}else{
@ Attachment to technote
}
}else{
@ Tag referencing
}
if( zType[0]!='e' || eventTagId == 0){
hyperlink_to_uuid(zUuid);
}
@ - %!W(zCom) by
hyperlink_to_user(zUser,zDate," on");
hyperlink_to_date(zDate, ".");
if( pDownloadName && blob_size(pDownloadName)==0 ){
blob_appendf(pDownloadName, "%S.txt", zUuid);
|
| ︙ | ︙ | |||
1381 1382 1383 1384 1385 1386 1387 |
if( cnt>0 ){
@ Also attachment "%h(zFilename)" to
}else{
@ Attachment "%h(zFilename)" to
}
objType |= OBJTYPE_ATTACHMENT;
if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
| > > > | | | | > > > > > > > > > > > > > > > | 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 |
if( cnt>0 ){
@ Also attachment "%h(zFilename)" to
}else{
@ Attachment "%h(zFilename)" to
}
objType |= OBJTYPE_ATTACHMENT;
if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
if ( db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'",
zTarget)
){
if( g.perm.Hyperlink && g.anon.RdTkt ){
@ ticket [%z(href("%R/tktview?name=%!S",zTarget))%S(zTarget)</a>]
}else{
@ ticket [%S(zTarget)]
}
}else if( db_exists("SELECT 1 FROM tag WHERE tagname='event-%q'",
zTarget)
){
if( g.perm.Hyperlink && g.anon.RdWiki ){
@ tech note [%z(href("%R/technote/%h",zTarget))%S(zTarget)</a>]
}else{
@ tech note [%S(zTarget)]
}
}else{
if( g.perm.Hyperlink && g.anon.RdWiki ){
@ wiki page [%z(href("%R/wiki?name=%t",zTarget))%h(zTarget)</a>]
}else{
@ wiki page [%h(zTarget)]
}
}
}else{
if( g.perm.Hyperlink && g.anon.RdWiki ){
@ wiki page [%z(href("%R/wiki?name=%t",zTarget))%h(zTarget)</a>]
}else{
@ wiki page [%h(zTarget)]
}
|
| ︙ | ︙ | |||
1425 1426 1427 1428 1429 1430 1431 | /* ** WEBPAGE: fdiff ** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN®ex=REGEX ** ** Two arguments, v1 and v2, identify the files to be diffed. Show the ** difference between the two artifacts. Show diff side by side unless sbs | | > | 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 | /* ** WEBPAGE: fdiff ** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN®ex=REGEX ** ** Two arguments, v1 and v2, identify the files to be diffed. Show the ** difference between the two artifacts. Show diff side by side unless sbs ** is 0. Generate plain text if "patch" is present, otherwise generate ** "pretty" HTML. ** ** Additional parameters: ** ** verbose Show more detail when describing artifacts ** dc=N Show N lines of context around each diff ** w Ignore whitespace */ |
| ︙ | ︙ | |||
1813 1814 1815 1816 1817 1818 1819 | ** URL: /whatis/SHA1HASH ** ** Additional query parameters: ** ** ln - show line numbers ** ln=N - highlight line number N ** ln=M-N - highlight lines M through N inclusive | | | 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 | ** URL: /whatis/SHA1HASH ** ** Additional query parameters: ** ** ln - show line numbers ** ln=N - highlight line number N ** ln=M-N - highlight lines M through N inclusive ** ln=M-N+Y-Z - highlight lines M through N and Y through Z (inclusive) ** verbose - show more detail in the description ** download - redirect to the download (artifact page only) ** ** The /artifact page show the complete content of a file ** identified by SHA1HASH as preformatted text. The ** /whatis page shows only a description of the file. */ |
| ︙ | ︙ | |||
1951 1952 1953 1954 1955 1956 1957 |
output_text_with_line_numbers(z, zLn);
}else{
@ <pre>
@ %h(z)
@ </pre>
}
}else if( strncmp(zMime, "image/", 6)==0 ){
| | | 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 |
output_text_with_line_numbers(z, zLn);
}else{
@ <pre>
@ %h(z)
@ </pre>
}
}else if( strncmp(zMime, "image/", 6)==0 ){
@ <i>(file is %d(blob_size(&content)) bytes of image data)</i><br />
@ <img src="%R/raw/%s(zUuid)?m=%s(zMime)" />
style_submenu_element("Image", "Image",
"%R/raw/%s?m=%s", zUuid, zMime);
}else{
@ <i>(file is %d(blob_size(&content)) bytes of binary data)</i>
}
@ </blockquote>
|
| ︙ | ︙ | |||
2046 2047 2048 2049 2050 2051 2052 |
modPending = moderation_pending(rid);
if( modPending ){
@ <span class="modpending">*** Awaiting Moderator Approval ***</span>
}
@ <tr><th>Ticket:</th>
@ <td>%z(href("%R/tktview/%s",zTktName))%s(zTktName)</a>
if( zTktTitle ){
| | | 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 |
modPending = moderation_pending(rid);
if( modPending ){
@ <span class="modpending">*** Awaiting Moderator Approval ***</span>
}
@ <tr><th>Ticket:</th>
@ <td>%z(href("%R/tktview/%s",zTktName))%s(zTktName)</a>
if( zTktTitle ){
@<br />%h(zTktTitle)
}
@</td></tr>
@ <tr><th>Date:</th><td>
hyperlink_to_date(zDate, "</td></tr>");
@ <tr><th>User:</th><td>
hyperlink_to_user(pTktChng->zUser, zDate, "</td></tr>");
@ </table>
|
| ︙ | ︙ |
Changes to src/json_wiki.c.
| ︙ | ︙ | |||
372 373 374 375 376 377 378 379 |
jstr = cson_value_get_string(contentV);
contentLen = (int)cson_string_length_bytes(jstr);
if(contentLen){
blob_append(&content, cson_string_cstr(jstr),contentLen);
}
zMimeType = json_find_option_cstr("mimetype","mimetype","M");
| > | | 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 |
jstr = cson_value_get_string(contentV);
contentLen = (int)cson_string_length_bytes(jstr);
if(contentLen){
blob_append(&content, cson_string_cstr(jstr),contentLen);
}
zMimeType = json_find_option_cstr("mimetype","mimetype","M");
zMimeType = wiki_filter_mimetypes(zMimeType);
wiki_cmd_commit(zPageName, rid, &content, zMimeType, 0);
blob_reset(&content);
/*
Our return value here has a race condition: if this operation
is called concurrently for the same wiki page via two requests,
payV could reflect the results of the other save operation.
*/
payV = json_get_wiki_page_by_name(
|
| ︙ | ︙ |
Changes to src/loadctrl.c.
| ︙ | ︙ | |||
33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
}
#endif
return 0.0;
}
/*
** COMMAND: test-loadavg
** %fossil test-loadavg
**
** Print the load average on the host machine.
*/
void loadavg_test_cmd(void){
fossil_print("load-average: %f\n", load_average());
}
| > | 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
}
#endif
return 0.0;
}
/*
** COMMAND: test-loadavg
**
** %fossil test-loadavg
**
** Print the load average on the host machine.
*/
void loadavg_test_cmd(void){
fossil_print("load-average: %f\n", load_average());
}
|
| ︙ | ︙ |
Changes to src/login.c.
| ︙ | ︙ | |||
391 392 393 394 395 396 397 398 399 400 401 402 403 404 |
if( prefix_match("spider", zAgent+i) ) return 0;
if( prefix_match("crawl", zAgent+i) ) return 0;
/* If a URI appears in the User-Agent, it is probably a bot */
if( strncmp("http", zAgent+i,4)==0 ) return 0;
}
if( strncmp(zAgent, "Mozilla/", 8)==0 ){
if( atoi(&zAgent[8])<4 ) return 0; /* Many bots advertise as Mozilla/3 */
if( sqlite3_strglob("*Firefox/[1-9]*", zAgent)==0 ) return 1;
if( sqlite3_strglob("*Chrome/[1-9]*", zAgent)==0 ) return 1;
if( sqlite3_strglob("*(compatible;?MSIE?[1789]*", zAgent)==0 ) return 1;
if( sqlite3_strglob("*Trident/[1-9]*;?rv:[1-9]*", zAgent)==0 ) return 1; /* IE11+ */
if( sqlite3_strglob("*AppleWebKit/[1-9]*(KHTML*", zAgent)==0 ) return 1;
return 0;
}
| > > > > > > > | 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 |
if( prefix_match("spider", zAgent+i) ) return 0;
if( prefix_match("crawl", zAgent+i) ) return 0;
/* If a URI appears in the User-Agent, it is probably a bot */
if( strncmp("http", zAgent+i,4)==0 ) return 0;
}
if( strncmp(zAgent, "Mozilla/", 8)==0 ){
if( atoi(&zAgent[8])<4 ) return 0; /* Many bots advertise as Mozilla/3 */
/* 2016-05-30: A pernicious spider that likes to walk Fossil timelines has
** been detected on the SQLite website. The spider changes its user-agent
** string frequently, but it always seems to include the following text:
*/
if( sqlite3_strglob("*Safari/537.36Mozilla/5.0*", zAgent)==0 ) return 0;
if( sqlite3_strglob("*Firefox/[1-9]*", zAgent)==0 ) return 1;
if( sqlite3_strglob("*Chrome/[1-9]*", zAgent)==0 ) return 1;
if( sqlite3_strglob("*(compatible;?MSIE?[1789]*", zAgent)==0 ) return 1;
if( sqlite3_strglob("*Trident/[1-9]*;?rv:[1-9]*", zAgent)==0 ) return 1; /* IE11+ */
if( sqlite3_strglob("*AppleWebKit/[1-9]*(KHTML*", zAgent)==0 ) return 1;
return 0;
}
|
| ︙ | ︙ | |||
986 987 988 989 990 991 992 |
/* Set the global variables recording the userid and login. The
** "nobody" user is a special case in that g.zLogin==0.
*/
g.userUid = uid;
if( fossil_strcmp(g.zLogin,"nobody")==0 ){
g.zLogin = 0;
}
| > | > > > > > | 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 |
/* Set the global variables recording the userid and login. The
** "nobody" user is a special case in that g.zLogin==0.
*/
g.userUid = uid;
if( fossil_strcmp(g.zLogin,"nobody")==0 ){
g.zLogin = 0;
}
if( PB("isrobot") ){
g.isHuman = 0;
}else if( g.zLogin==0 ){
g.isHuman = isHuman(P("HTTP_USER_AGENT"));
}else{
g.isHuman = 1;
}
/* Set the capabilities */
login_replace_capabilities(zCap, 0);
login_set_anon_nobody_capabilities();
/* The auto-hyperlink setting allows hyperlinks to be displayed for users
** who do not have the "h" permission as long as their UserAgent string
|
| ︙ | ︙ |
Changes to src/lookslike.c.
| ︙ | ︙ | |||
48 49 50 51 52 53 54 55 56 57 58 59 60 61 | #define LOOK_ODD ((int)0x00000080) /* An odd number of bytes was found. */ #define LOOK_SHORT ((int)0x00000100) /* Unable to perform full check. */ #define LOOK_INVALID ((int)0x00000200) /* Invalid sequence was found. */ #define LOOK_BINARY (LOOK_NUL | LOOK_LONG | LOOK_SHORT) /* May be binary. */ #define LOOK_EOL (LOOK_LONE_CR | LOOK_LONE_LF | LOOK_CRLF) /* Line seps. */ #endif /* INTERFACE */ /* ** This function attempts to scan each logical line within the blob to ** determine the type of content it appears to contain. The return value ** is a combination of one or more of the LOOK_XXX flags (see above): ** ** !LOOK_BINARY -- The content appears to consist entirely of text; however, | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
#define LOOK_ODD ((int)0x00000080) /* An odd number of bytes was found. */
#define LOOK_SHORT ((int)0x00000100) /* Unable to perform full check. */
#define LOOK_INVALID ((int)0x00000200) /* Invalid sequence was found. */
#define LOOK_BINARY (LOOK_NUL | LOOK_LONG | LOOK_SHORT) /* May be binary. */
#define LOOK_EOL (LOOK_LONE_CR | LOOK_LONE_LF | LOOK_CRLF) /* Line seps. */
#endif /* INTERFACE */
/* definitions for various UTF-8 sequence lengths, encoded as start value
* and size of each valid range belonging to some lead byte*/
#define US2A 0x80, 0x01 /* for lead byte 0xC0 */
#define US2B 0x80, 0x40 /* for lead bytes 0xC2-0xDF */
#define US3A 0xA0, 0x20 /* for lead byte 0xE0 */
#define US3B 0x80, 0x40 /* for lead bytes 0xE1-0xEF */
#define US4A 0x90, 0x30 /* for lead byte 0xF0 */
#define US4B 0x80, 0x40 /* for lead bytes 0xF1-0xF3 */
#define US4C 0x80, 0x10 /* for lead byte 0xF4 */
#define US0A 0x00, 0x00 /* for any other lead byte */
/* a table used for quick lookup of the definition that goes with a
* particular lead byte */
static const unsigned char lb_tab[] = {
US0A, US0A, US0A, US0A, US0A, US0A, US0A, US0A,
US0A, US0A, US0A, US0A, US0A, US0A, US0A, US0A,
US0A, US0A, US0A, US0A, US0A, US0A, US0A, US0A,
US0A, US0A, US0A, US0A, US0A, US0A, US0A, US0A,
US0A, US0A, US0A, US0A, US0A, US0A, US0A, US0A,
US0A, US0A, US0A, US0A, US0A, US0A, US0A, US0A,
US0A, US0A, US0A, US0A, US0A, US0A, US0A, US0A,
US0A, US0A, US0A, US0A, US0A, US0A, US0A, US0A,
US2A, US0A, US2B, US2B, US2B, US2B, US2B, US2B,
US2B, US2B, US2B, US2B, US2B, US2B, US2B, US2B,
US2B, US2B, US2B, US2B, US2B, US2B, US2B, US2B,
US2B, US2B, US2B, US2B, US2B, US2B, US2B, US2B,
US3A, US3B, US3B, US3B, US3B, US3B, US3B, US3B,
US3B, US3B, US3B, US3B, US3B, US3B, US3B, US3B,
US4A, US4B, US4B, US4B, US4C, US0A, US0A, US0A,
US0A, US0A, US0A, US0A, US0A, US0A, US0A, US0A
};
/*
** This function attempts to scan each logical line within the blob to
** determine the type of content it appears to contain. The return value
** is a combination of one or more of the LOOK_XXX flags (see above):
**
** !LOOK_BINARY -- The content appears to consist entirely of text; however,
|
| ︙ | ︙ | |||
130 131 132 133 134 135 136 |
}
if( j>LENGTH_MASK ){
flags |= LOOK_LONG; /* Very long line -> binary */
}
return flags;
}
| < | | > > | | | | | | | > > | < < | > | > | > > > | | < | 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 |
}
if( j>LENGTH_MASK ){
flags |= LOOK_LONG; /* Very long line -> binary */
}
return flags;
}
/*
** Checks for proper UTF-8. It uses the method described in:
** http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences
** except for the "overlong form" of \u0000 which is not considered
** invalid here: Some languages like Java and Tcl use it. This function
** also considers valid the derivatives CESU-8 & WTF-8 (as described in
** the same wikipedia article referenced previously). For UTF-8 characters
** > 0x7f, the variable 'c' not necessary means the real lead byte.
** It's number of higher 1-bits indicate the number of continuation
** bytes that are expected to be followed. E.g. when 'c' has a value
** in the range 0xc0..0xdf it means that after 'c' a single continuation
** byte is expected. A value 0xe0..0xef means that after 'c' two more
** continuation bytes are expected.
*/
int invalid_utf8(
const Blob *pContent
){
const unsigned char *z = (unsigned char *) blob_buffer(pContent);
unsigned int n = blob_size(pContent);
unsigned char c; /* lead byte to be handled. */
if( n==0 ) return 0; /* Empty file -> OK */
c = *z;
while( --n>0 ){
if( c>=0x80 ){
const unsigned char *def; /* pointer to range table*/
c <<= 1; /* multiply by 2 and get rid of highest bit */
def = &lb_tab[c]; /* search fb's valid range in table */
if( (unsigned int)(*++z-def[0])>=def[1] ){
return LOOK_INVALID; /* Invalid UTF-8 */
}
c = (c>=0xC0) ? (c|3) : ' '; /* determine next lead byte */
} else {
c = *++z;
}
}
return (c>=0x80) ? LOOK_INVALID : 0; /* Final lead byte must be ASCII. */
}
/*
** Define the type needed to represent a Unicode (UTF-16) character.
*/
#ifndef WCHAR_T
# ifdef _WIN32
# define WCHAR_T wchar_t
|
| ︙ | ︙ | |||
396 397 398 399 400 401 402 |
fUnicode = 0;
}else{
fUnicode = could_be_utf16(&blob, 0) || fForceUtf16;
}
if( fUnicode ){
lookFlags = looks_like_utf16(&blob, bRevUtf16, 0);
}else{
| | | 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 |
fUnicode = 0;
}else{
fUnicode = could_be_utf16(&blob, 0) || fForceUtf16;
}
if( fUnicode ){
lookFlags = looks_like_utf16(&blob, bRevUtf16, 0);
}else{
lookFlags = looks_like_utf8(&blob, 0) | invalid_utf8(&blob);
}
}
fossil_print("File \"%s\" has %d bytes.\n",g.argv[2],blob_size(&blob));
fossil_print("Starts with UTF-8 BOM: %s\n",fUtf8?"yes":"no");
fossil_print("Starts with UTF-16 BOM: %s\n",
fUtf16?(bRevUtf16?"reversed":"yes"):"no");
fossil_print("Looks like UTF-%s: %s\n",fUnicode?"16":"8",
|
| ︙ | ︙ |
Changes to src/main.c.
| ︙ | ︙ | |||
983 984 985 986 987 988 989 | } multi_column_list(aCmd, nCmd); } /* ** COMMAND: test-list-webpage ** | | | 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 |
}
multi_column_list(aCmd, nCmd);
}
/*
** COMMAND: test-list-webpage
**
** List all web pages.
*/
void cmd_test_webpage_list(void){
int i, nCmd;
const char *aCmd[count(aCommand)];
for(i=nCmd=0; i<count(aCommand); i++){
if(0x08 & aCommand[i].cmdFlags){
aCmd[nCmd++] = aWebpage[i].zName;
|
| ︙ | ︙ | |||
1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 |
blob_append(pOut, "UNICODE_COMMAND_LINE\n", -1);
#endif
#if defined(FOSSIL_DYNAMIC_BUILD)
blob_append(pOut, "DYNAMIC_BUILD\n", -1);
#else
blob_append(pOut, "STATIC_BUILD\n", -1);
#endif
}
/*
** This function returns the user-agent string for Fossil, for
** use in HTTP(S) requests.
*/
const char *get_user_agent(){
| > > > | 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 |
blob_append(pOut, "UNICODE_COMMAND_LINE\n", -1);
#endif
#if defined(FOSSIL_DYNAMIC_BUILD)
blob_append(pOut, "DYNAMIC_BUILD\n", -1);
#else
blob_append(pOut, "STATIC_BUILD\n", -1);
#endif
#if defined(USE_SEE)
blob_append(pOut, "USE_SEE\n", -1);
#endif
}
/*
** This function returns the user-agent string for Fossil, for
** use in HTTP(S) requests.
*/
const char *get_user_agent(){
|
| ︙ | ︙ | |||
1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 |
}else{
putchar(*z);
z++;
}
}
putchar('\n');
}
/*
** WEBPAGE: help
** URL: /help?name=CMD
**
** Show the built-in help text for CMD. CMD can be a command-line interface
** command or a page name from the web interface.
*/
void help_page(void){
const char *zCmd = P("cmd");
if( zCmd==0 ) zCmd = P("name");
style_header("Command-line Help");
if( zCmd ){
int rc, idx;
char *z, *s, *d;
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < > > > | > > > | 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 |
}else{
putchar(*z);
z++;
}
}
putchar('\n');
}
/*
** COMMAND: test-all-help
**
** Usage: %fossil test-all-help ?OPTIONS?
**
** 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.
*/
void test_all_help_cmd(void){
int i;
int mask = CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER;
if( find_option("www","w",0) ){
mask = CMDFLAG_WEBPAGE;
}
if( find_option("everything","e",0) ){
mask = CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER | CMDFLAG_WEBPAGE;
}
if( find_option("test","t",0) ){
mask |= CMDFLAG_TEST;
}
fossil_print("Help text for:\n");
if( mask & CMDFLAG_1ST_TIER ) fossil_print(" * Commands\n");
if( mask & CMDFLAG_2ND_TIER ) fossil_print(" * Auxiliary commands\n");
if( mask & CMDFLAG_TEST ) fossil_print(" * Test commands\n");
if( mask & CMDFLAG_WEBPAGE ) fossil_print(" * Web pages\n");
fossil_print("---\n");
for(i=0; i<count(aCommand); i++){
if( (aCommand[i].cmdFlags & mask)==0 ) continue;
fossil_print("# %s\n", aCommand[i].zName);
fossil_print("%s\n\n", aCmdHelp[i].zText);
}
fossil_print("---\n");
version_cmd();
}
/*
** WEBPAGE: help
** URL: /help?name=CMD
**
** Show the built-in help text for CMD. CMD can be a command-line interface
** command or a page name from the web interface.
*/
void help_page(void){
const char *zCmd = P("cmd");
if( zCmd==0 ) zCmd = P("name");
style_header("Command-line Help");
if( zCmd ){
int rc, idx;
char *z, *s, *d;
style_submenu_element("Command-List", "Command-List", "%s/help", g.zTop);
if( *zCmd=='/' ){
/* Some of the webpages require query parameters in order to work.
** @ <h1>The "<a href='%R%s(zCmd)'>%s(zCmd)</a>" page:</h1> */
@ <h1>The "%s(zCmd)" page:</h1>
}else{
@ <h1>The "%s(zCmd)" command:</h1>
}
rc = name_search(zCmd, aCommand, count(aCommand), 0, &idx);
if( rc==1 ){
@ unknown command: %s(zCmd)
}else if( rc==2 ){
@ ambiguous command prefix: %s(zCmd)
}else{
z = (char*)aCmdHelp[idx].zText;
|
| ︙ | ︙ | |||
1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 |
vfile_scan(&base, blob_size(&base), 0, 0, 0);
db_multi_exec("DELETE FROM sfile WHERE x NOT GLOB '*[^/].fossil'");
n = db_int(0, "SELECT count(*) FROM sfile");
if( n>0 ){
Stmt q;
@ <html>
@ <head>
@ <title>Repository List</title>
@ </head>
@ <body>
@ <h1>Available Repositories:</h1>
@ <ol>
db_prepare(&q, "SELECT x, substr(x,-7,-100000)||'/home'"
" FROM sfile ORDER BY x COLLATE nocase;");
while( db_step(&q)==SQLITE_ROW ){
const char *zName = db_column_text(&q, 0);
const char *zUrl = db_column_text(&q, 1);
| > | | 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 |
vfile_scan(&base, blob_size(&base), 0, 0, 0);
db_multi_exec("DELETE FROM sfile WHERE x NOT GLOB '*[^/].fossil'");
n = db_int(0, "SELECT count(*) FROM sfile");
if( n>0 ){
Stmt q;
@ <html>
@ <head>
@ <base href="%s(g.zBaseURL)/" />
@ <title>Repository List</title>
@ </head>
@ <body>
@ <h1>Available Repositories:</h1>
@ <ol>
db_prepare(&q, "SELECT x, substr(x,-7,-100000)||'/home'"
" FROM sfile ORDER BY x COLLATE nocase;");
while( db_step(&q)==SQLITE_ROW ){
const char *zName = db_column_text(&q, 0);
const char *zUrl = db_column_text(&q, 1);
@ <li><a href="%R/%h(zUrl)" target="_blank">%h(zName)</a></li>
}
@ </ol>
@ </body>
@ </html>
cgi_reply();
}
sqlite3_close(g.db);
|
| ︙ | ︙ | |||
1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 |
*/
static void process_one_web_page(
const char *zNotFound, /* Redirect here on a 404 if not NULL */
Glob *pFileGlob, /* Deliver static files matching */
int allowRepoList /* Send repo list for "/" URL */
){
const char *zPathInfo;
char *zPath = NULL;
int idx;
int i;
/* Handle universal query parameters */
if( PB("utc") ){
g.fTimeFormat = 1;
}else if( PB("localtime") ){
g.fTimeFormat = 2;
}
/* If the repository has not been opened already, then find the
** repository based on the first element of PATH_INFO and open it.
*/
| > | > > > > > > > > > > | 1642 1643 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 |
*/
static void process_one_web_page(
const char *zNotFound, /* Redirect here on a 404 if not NULL */
Glob *pFileGlob, /* Deliver static files matching */
int allowRepoList /* Send repo list for "/" URL */
){
const char *zPathInfo;
const char *zDirPathInfo;
char *zPath = NULL;
int idx;
int i;
/* Handle universal query parameters */
if( PB("utc") ){
g.fTimeFormat = 1;
}else if( PB("localtime") ){
g.fTimeFormat = 2;
}
/* If the repository has not been opened already, then find the
** repository based on the first element of PATH_INFO and open it.
*/
zDirPathInfo = zPathInfo = PD("PATH_INFO","");
/* For the PATH_INFO that will be used to help build the final
** g.zBaseURL and g.zTop (only), skip over the initial directory
** portion of PATH_INFO; otherwise, it may be duplicated.
*/
if( g.zTop ){
int nTop = strlen(g.zTop);
if ( strncmp(zDirPathInfo, g.zTop, nTop)==0 ){
zDirPathInfo += nTop;
}
}
if( !g.repositoryOpen ){
char *zRepo, *zToFree;
const char *zOldScript = PD("SCRIPT_NAME", "");
char *zNewScript;
int j, k;
i64 szFile;
|
| ︙ | ︙ | |||
1643 1644 1645 1646 1647 1648 1649 |
}
if( szFile==0 && sqlite3_strglob("*/.fossil",zRepo)!=0 ){
if( zRepo[0]=='/' && zRepo[1]=='/' ){ zRepo++; j--; }
szFile = file_size(zRepo);
/* this should only be set from the --baseurl option, not CGI */
if( g.zBaseURL && g.zBaseURL[0]!=0 && g.zTop && g.zTop[0]!=0 &&
file_isdir(g.zRepositoryName)==1 ){
| > | | > | 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 |
}
if( szFile==0 && sqlite3_strglob("*/.fossil",zRepo)!=0 ){
if( zRepo[0]=='/' && zRepo[1]=='/' ){ zRepo++; j--; }
szFile = file_size(zRepo);
/* this should only be set from the --baseurl option, not CGI */
if( g.zBaseURL && g.zBaseURL[0]!=0 && g.zTop && g.zTop[0]!=0 &&
file_isdir(g.zRepositoryName)==1 ){
if( zPathInfo==zDirPathInfo ){
g.zBaseURL = mprintf("%s%.*s", g.zBaseURL, i, zPathInfo);
g.zTop = mprintf("%s%.*s", g.zTop, i, zPathInfo);
}
}
}
if( szFile<0 && i>0 ){
const char *zMimetype;
assert( fossil_strcmp(&zRepo[j], ".fossil")==0 );
zRepo[j] = 0;
if( zPathInfo[i]=='/' && file_isdir(zRepo)==1 ){
|
| ︙ | ︙ | |||
2075 2076 2077 2078 2079 2080 2081 |
** found it is returned verbatim. This feature allows "fossil server"
** to function as a primitive web-server delivering arbitrary content.
*/
pFileGlob = glob_create(blob_str(&value));
blob_reset(&value);
continue;
}
| | < > | > > | 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 |
** found it is returned verbatim. This feature allows "fossil server"
** to function as a primitive web-server delivering arbitrary content.
*/
pFileGlob = glob_create(blob_str(&value));
blob_reset(&value);
continue;
}
if( blob_eq(&key, "setenv:") && blob_token(&line, &value) ){
/* setenv: NAME VALUE
** setenv: NAME
**
** Sets environment variable NAME to VALUE. If VALUE is omitted, then
** the environment variable is unset.
*/
blob_token(&line,&value2);
fossil_setenv(blob_str(&value), blob_str(&value2));
blob_reset(&value);
blob_reset(&value2);
continue;
}
if( blob_eq(&key, "debug:") && blob_token(&line, &value) ){
/* debug: FILENAME
|
| ︙ | ︙ | |||
2393 2394 2395 2396 2397 2398 2399 | #endif /* ** COMMAND: server* ** COMMAND: ui ** ** Usage: %fossil server ?OPTIONS? ?REPOSITORY? | | | 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 | #endif /* ** COMMAND: server* ** COMMAND: ui ** ** Usage: %fossil server ?OPTIONS? ?REPOSITORY? ** or: %fossil ui ?OPTIONS? ?REPOSITORY? ** ** Open a socket and begin listening and responding to HTTP requests on ** TCP port 8080, or on any other TCP port defined by the -P or ** --port option. The optional argument is the name of the repository. ** The repository argument may be omitted if the working directory is ** within an open checkout. ** |
| ︙ | ︙ | |||
2488 2489 2490 2491 2492 2493 2494 |
g.useLocalauth = find_option("localauth", 0, 0)!=0;
Th_InitTraceLog();
zPort = find_option("port", "P", 1);
isUiCmd = g.argv[1][0]=='u';
if( isUiCmd ){
zInitPage = find_option("page", 0, 1);
}
| < | 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 |
g.useLocalauth = find_option("localauth", 0, 0)!=0;
Th_InitTraceLog();
zPort = find_option("port", "P", 1);
isUiCmd = g.argv[1][0]=='u';
if( isUiCmd ){
zInitPage = find_option("page", 0, 1);
}
zNotFound = find_option("notfound", 0, 1);
allowRepoList = find_option("repolist",0,0)!=0;
zAltBase = find_option("baseurl", 0, 1);
fCreate = find_option("create",0,0)!=0;
if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
if( zAltBase ){
set_base_url(zAltBase);
|
| ︙ | ︙ | |||
2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 |
if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
if( isUiCmd ){
flags |= HTTP_SERVER_LOCALHOST|HTTP_SERVER_REPOLIST;
g.useLocalauth = 1;
allowRepoList = 1;
}
find_server_repository(2, fCreate);
if( zPort ){
int i;
for(i=strlen(zPort)-1; i>=0 && zPort[i]!=':'; i--){}
if( i>0 ){
zIpAddr = mprintf("%.*s", i, zPort);
zPort += i+1;
}
| > > > > > > > | 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 |
if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
if( isUiCmd ){
flags |= HTTP_SERVER_LOCALHOST|HTTP_SERVER_REPOLIST;
g.useLocalauth = 1;
allowRepoList = 1;
}
find_server_repository(2, fCreate);
if( zInitPage==0 ){
if( isUiCmd && g.localOpen ){
zInitPage = "timeline?c=current";
}else{
zInitPage = "";
}
}
if( zPort ){
int i;
for(i=strlen(zPort)-1; i>=0 && zPort[i]!=':'; i--){}
if( i>0 ){
zIpAddr = mprintf("%.*s", i, zPort);
zPort += i+1;
}
|
| ︙ | ︙ | |||
2596 2597 2598 2599 2600 2601 2602 |
}
if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
db_close(1);
if( allowRepoList ){
flags |= HTTP_SERVER_REPOLIST;
}
| | | | | | 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 |
}
if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
db_close(1);
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);
}
#endif
}
/*
** COMMAND: test-echo
**
** Usage: %fossil test-echo [--hex] ARGS...
**
** Echo all command-line arguments (enclosed in [...]) to the screen so that
** wildcard expansion behavior of the host shell can be investigated.
**
** With the --hex option, show the output as hexadecimal. This can be used
|
| ︙ | ︙ |
Changes to src/main.mk.
| ︙ | ︙ | |||
43 44 45 46 47 48 49 50 51 52 53 54 55 56 | $(SRCDIR)/doc.c \ $(SRCDIR)/encode.c \ $(SRCDIR)/event.c \ $(SRCDIR)/export.c \ $(SRCDIR)/file.c \ $(SRCDIR)/finfo.c \ $(SRCDIR)/foci.c \ $(SRCDIR)/fusefs.c \ $(SRCDIR)/glob.c \ $(SRCDIR)/graph.c \ $(SRCDIR)/gzip.c \ $(SRCDIR)/http.c \ $(SRCDIR)/http_socket.c \ $(SRCDIR)/http_ssl.c \ | > | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | $(SRCDIR)/doc.c \ $(SRCDIR)/encode.c \ $(SRCDIR)/event.c \ $(SRCDIR)/export.c \ $(SRCDIR)/file.c \ $(SRCDIR)/finfo.c \ $(SRCDIR)/foci.c \ $(SRCDIR)/fshell.c \ $(SRCDIR)/fusefs.c \ $(SRCDIR)/glob.c \ $(SRCDIR)/graph.c \ $(SRCDIR)/gzip.c \ $(SRCDIR)/http.c \ $(SRCDIR)/http_socket.c \ $(SRCDIR)/http_ssl.c \ |
| ︙ | ︙ | |||
215 216 217 218 219 220 221 222 223 224 225 226 227 228 | $(OBJDIR)/doc_.c \ $(OBJDIR)/encode_.c \ $(OBJDIR)/event_.c \ $(OBJDIR)/export_.c \ $(OBJDIR)/file_.c \ $(OBJDIR)/finfo_.c \ $(OBJDIR)/foci_.c \ $(OBJDIR)/fusefs_.c \ $(OBJDIR)/glob_.c \ $(OBJDIR)/graph_.c \ $(OBJDIR)/gzip_.c \ $(OBJDIR)/http_.c \ $(OBJDIR)/http_socket_.c \ $(OBJDIR)/http_ssl_.c \ | > | 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | $(OBJDIR)/doc_.c \ $(OBJDIR)/encode_.c \ $(OBJDIR)/event_.c \ $(OBJDIR)/export_.c \ $(OBJDIR)/file_.c \ $(OBJDIR)/finfo_.c \ $(OBJDIR)/foci_.c \ $(OBJDIR)/fshell_.c \ $(OBJDIR)/fusefs_.c \ $(OBJDIR)/glob_.c \ $(OBJDIR)/graph_.c \ $(OBJDIR)/gzip_.c \ $(OBJDIR)/http_.c \ $(OBJDIR)/http_socket_.c \ $(OBJDIR)/http_ssl_.c \ |
| ︙ | ︙ | |||
336 337 338 339 340 341 342 343 344 345 346 347 348 349 | $(OBJDIR)/doc.o \ $(OBJDIR)/encode.o \ $(OBJDIR)/event.o \ $(OBJDIR)/export.o \ $(OBJDIR)/file.o \ $(OBJDIR)/finfo.o \ $(OBJDIR)/foci.o \ $(OBJDIR)/fusefs.o \ $(OBJDIR)/glob.o \ $(OBJDIR)/graph.o \ $(OBJDIR)/gzip.o \ $(OBJDIR)/http.o \ $(OBJDIR)/http_socket.o \ $(OBJDIR)/http_ssl.o \ | > | 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 | $(OBJDIR)/doc.o \ $(OBJDIR)/encode.o \ $(OBJDIR)/event.o \ $(OBJDIR)/export.o \ $(OBJDIR)/file.o \ $(OBJDIR)/finfo.o \ $(OBJDIR)/foci.o \ $(OBJDIR)/fshell.o \ $(OBJDIR)/fusefs.o \ $(OBJDIR)/glob.o \ $(OBJDIR)/graph.o \ $(OBJDIR)/gzip.o \ $(OBJDIR)/http.o \ $(OBJDIR)/http_socket.o \ $(OBJDIR)/http_ssl.o \ |
| ︙ | ︙ | |||
457 458 459 460 461 462 463 | $(OBJDIR)/mkversion: $(SRCDIR)/mkversion.c $(BCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c $(OBJDIR)/codecheck1: $(SRCDIR)/codecheck1.c $(BCC) -o $(OBJDIR)/codecheck1 $(SRCDIR)/codecheck1.c | | | 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 | $(OBJDIR)/mkversion: $(SRCDIR)/mkversion.c $(BCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c $(OBJDIR)/codecheck1: $(SRCDIR)/codecheck1.c $(BCC) -o $(OBJDIR)/codecheck1 $(SRCDIR)/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 |
| ︙ | ︙ | |||
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 |
$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
$(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
# Setup the options used to compile the included SQLite library.
SQLITE_OPTIONS = -DNDEBUG=1 \
-DSQLITE_OMIT_LOAD_EXTENSION=1 \
-DSQLITE_ENABLE_LOCKING_STYLE=0 \
-DSQLITE_THREADSAFE=0 \
-DSQLITE_DEFAULT_FILE_FORMAT=4 \
-DSQLITE_OMIT_DEPRECATED \
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
-DSQLITE_ENABLE_FTS4 \
-DSQLITE_ENABLE_FTS3_PARENTHESIS \
-DSQLITE_ENABLE_DBSTAT_VTAB \
-DSQLITE_ENABLE_JSON1 \
-DSQLITE_ENABLE_FTS5
# Setup the options used to compile the included SQLite shell.
SHELL_OPTIONS = -Dmain=sqlite3_shell \
-DSQLITE_OMIT_LOAD_EXTENSION=1 \
-DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
-DSQLITE_SHELL_DBNAME_PROC=fossil_open
# Setup the options used to compile the included miniz library.
MINIZ_OPTIONS = -DMINIZ_NO_STDIO \
-DMINIZ_NO_TIME \
-DMINIZ_NO_ARCHIVE_APIS
# The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
# to 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.
| > > | | > > > > > > > > > > > > > > > > > | 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 |
$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
$(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
# Setup the options used to compile the included SQLite library.
SQLITE_OPTIONS = -DNDEBUG=1 \
-DSQLITE_OMIT_LOAD_EXTENSION=1 \
-DSQLITE_ENABLE_LOCKING_STYLE=0 \
-DSQLITE_LIKE_DOESNT_MATCH_BLOBS=1 \
-DSQLITE_THREADSAFE=0 \
-DSQLITE_DEFAULT_FILE_FORMAT=4 \
-DSQLITE_OMIT_DEPRECATED \
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
-DSQLITE_ENABLE_FTS4 \
-DSQLITE_ENABLE_FTS3_PARENTHESIS \
-DSQLITE_ENABLE_DBSTAT_VTAB \
-DSQLITE_ENABLE_JSON1 \
-DSQLITE_ENABLE_FTS5
# Setup the options used to compile the included SQLite shell.
SHELL_OPTIONS = -Dmain=sqlite3_shell \
-DSQLITE_SHELL_IS_UTF8=1 \
-DSQLITE_OMIT_LOAD_EXTENSION=1 \
-DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
-DSQLITE_SHELL_DBNAME_PROC=fossil_open
# Setup the options used to compile the included miniz library.
MINIZ_OPTIONS = -DMINIZ_NO_STDIO \
-DMINIZ_NO_TIME \
-DMINIZ_NO_ARCHIVE_APIS
# The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
# to 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.
SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
SQLITE3_OBJ.1 =
SQLITE3_OBJ. = $(SQLITE3_OBJ.0)
# The FOSSIL_ENABLE_MINIZ variable may be undefined, set to 0, or
# set to 1. If it is set to 1, the miniz library included in the
# source tree should be used; otherwise, it should not.
MINIZ_OBJ.0 =
MINIZ_OBJ.1 = $(OBJDIR)/miniz.o
MINIZ_OBJ. = $(MINIZ_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, ordinary 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 = sqlite3.c
SQLITE3_SRC.1 = sqlite3-see.c
SQLITE3_SRC. = sqlite3.c
SQLITE3_SRC = $(SRCDIR)/$(SQLITE3_SRC.$(USE_SEE))
SQLITE3_SHELL_SRC.0 = shell.c
SQLITE3_SHELL_SRC.1 = shell-see.c
SQLITE3_SHELL_SRC. = shell.c
SQLITE3_SHELL_SRC = $(SRCDIR)/$(SQLITE3_SHELL_SRC.$(USE_SEE))
SEE_FLAGS.0 =
SEE_FLAGS.1 = -DSQLITE_HAS_CODEC
SEE_FLAGS. =
SEE_FLAGS = $(SEE_FLAGS.$(USE_SEE))
EXTRAOBJ = \
$(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE)) \
$(MINIZ_OBJ.$(FOSSIL_ENABLE_MINIZ)) \
$(LINENOISE_OBJ.$(USE_LINENOISE)) \
$(OBJDIR)/shell.o \
|
| ︙ | ︙ | |||
592 593 594 595 596 597 598 599 600 601 602 603 604 605 | $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \ $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \ $(OBJDIR)/event_.c:$(OBJDIR)/event.h \ $(OBJDIR)/export_.c:$(OBJDIR)/export.h \ $(OBJDIR)/file_.c:$(OBJDIR)/file.h \ $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \ $(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \ $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \ $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \ | > | 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 | $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \ $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \ $(OBJDIR)/event_.c:$(OBJDIR)/event.h \ $(OBJDIR)/export_.c:$(OBJDIR)/export.h \ $(OBJDIR)/file_.c:$(OBJDIR)/file.h \ $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \ $(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \ $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \ $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \ |
| ︙ | ︙ | |||
948 949 950 951 952 953 954 955 956 957 958 959 960 961 | $(OBJDIR)/foci_.c: $(SRCDIR)/foci.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/foci.c >$@ $(OBJDIR)/foci.o: $(OBJDIR)/foci_.c $(OBJDIR)/foci.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/foci.o -c $(OBJDIR)/foci_.c $(OBJDIR)/foci.h: $(OBJDIR)/headers $(OBJDIR)/fusefs_.c: $(SRCDIR)/fusefs.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/fusefs.c >$@ $(OBJDIR)/fusefs.o: $(OBJDIR)/fusefs_.c $(OBJDIR)/fusefs.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/fusefs.o -c $(OBJDIR)/fusefs_.c | > > > > > > > > | 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 | $(OBJDIR)/foci_.c: $(SRCDIR)/foci.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/foci.c >$@ $(OBJDIR)/foci.o: $(OBJDIR)/foci_.c $(OBJDIR)/foci.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/foci.o -c $(OBJDIR)/foci_.c $(OBJDIR)/foci.h: $(OBJDIR)/headers $(OBJDIR)/fshell_.c: $(SRCDIR)/fshell.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/fshell.c >$@ $(OBJDIR)/fshell.o: $(OBJDIR)/fshell_.c $(OBJDIR)/fshell.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/fshell.o -c $(OBJDIR)/fshell_.c $(OBJDIR)/fshell.h: $(OBJDIR)/headers $(OBJDIR)/fusefs_.c: $(SRCDIR)/fusefs.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/fusefs.c >$@ $(OBJDIR)/fusefs.o: $(OBJDIR)/fusefs_.c $(OBJDIR)/fusefs.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/fusefs.o -c $(OBJDIR)/fusefs_.c |
| ︙ | ︙ | |||
1637 1638 1639 1640 1641 1642 1643 | $(OBJDIR)/translate $(SRCDIR)/zip.c >$@ $(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c $(OBJDIR)/zip.h: $(OBJDIR)/headers | | | | | | | 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 | $(OBJDIR)/translate $(SRCDIR)/zip.c >$@ $(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h $(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)/sqlite3.h $(XTCC) $(SHELL_OPTIONS) $(SHELL_CFLAGS) $(LINENOISE_DEF.$(USE_LINENOISE)) -c $(SQLITE3_SHELL_SRC) -o $@ $(OBJDIR)/linenoise.o: $(SRCDIR)/linenoise.c $(SRCDIR)/linenoise.h $(XTCC) -c $(SRCDIR)/linenoise.c -o $@ $(OBJDIR)/th.o: $(SRCDIR)/th.c $(XTCC) -c $(SRCDIR)/th.c -o $@ |
| ︙ | ︙ |
Changes to src/makeheaders.c.
| ︙ | ︙ | |||
1104 1105 1106 1107 1108 1109 1110 |
** If pTable is not NULL, then insert every identifier seen into the
** IdentTable. This includes any identifiers seen inside of {...}.
**
** The number of errors encountered is returned. An error is an
** unterminated token.
*/
static int GetBigToken(InStream *pIn, Token *pToken, IdentTable *pTable){
| | | 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 |
** If pTable is not NULL, then insert every identifier seen into the
** IdentTable. This includes any identifiers seen inside of {...}.
**
** The number of errors encountered is returned. An error is an
** unterminated token.
*/
static int GetBigToken(InStream *pIn, Token *pToken, IdentTable *pTable){
const char *zStart;
int iStart;
int nBrace;
int c;
int nLine;
int nErr;
nErr = GetNonspaceToken(pIn,pToken);
|
| ︙ | ︙ | |||
1133 1134 1135 1136 1137 1138 1139 |
if( pToken->zText[0]=='{' ) break;
return nErr;
default:
return nErr;
}
| < | 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 |
if( pToken->zText[0]=='{' ) break;
return nErr;
default:
return nErr;
}
iStart = pIn->i;
zStart = pToken->zText;
nLine = pToken->nLine;
nBrace = 1;
while( nBrace ){
nErr += GetNonspaceToken(pIn,pToken);
/* printf("%04d: nBrace=%d [%.*s]\n",pToken->nLine,nBrace,
|
| ︙ | ︙ | |||
1679 1680 1681 1682 1683 1684 1685 |
/*
** This routine is called when we see a method for a class that begins
** with the PUBLIC, PRIVATE, or PROTECTED keywords. Such methods are
** added to their class definitions.
*/
static int ProcessMethodDef(Token *pFirst, Token *pLast, int flags){
| < < | 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 |
/*
** This routine is called when we see a method for a class that begins
** with the PUBLIC, PRIVATE, or PROTECTED keywords. Such methods are
** added to their class definitions.
*/
static int ProcessMethodDef(Token *pFirst, Token *pLast, int flags){
Token *pClass;
char *zDecl;
Decl *pDecl;
String str;
int type;
pLast = pLast->pPrev;
while( pFirst->zText[0]=='P' ){
int rc = 1;
switch( pFirst->nText ){
case 6: rc = strncmp(pFirst->zText,"PUBLIC",6); break;
case 7: rc = strncmp(pFirst->zText,"PRIVATE",7); break;
case 9: rc = strncmp(pFirst->zText,"PROTECTED",9); break;
|
| ︙ | ︙ |
Changes to src/makeheaders.html.
| ︙ | ︙ | |||
141 142 143 144 145 146 147 | files change, the entire program must be recompiled. It also happens that those important .h files tend to be the ones that change most frequently. This means that the entire program must be recompiled frequently, leading to a lengthy modify-compile-test cycle and a corresponding decrease in programmer productivity. <p><li> | | | | | 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 | files change, the entire program must be recompiled. It also happens that those important .h files tend to be the ones that change most frequently. This means that the entire program must be recompiled frequently, leading to a lengthy modify-compile-test cycle and a corresponding decrease in programmer productivity. <p><li> The C programming language requires that declarations depending upon each other must occur in a particular order. In a program with complex, interwoven data structures, the correct declaration order can become very difficult to determine manually, especially when the declarations involved are spread out over several files. </ol> </p> <a name="H0004"></a> <h3>1.2 The Makeheaders Solution</h3> <p> The makeheaders program is designed to ameliorate the problems associated with the traditional C programming model by automatically generating the interface information in the .h files from interface information contained in other .h files and from implementation information in the .c files. When the makeheaders program is run, it scans the source files for a project, then generates a series of new .h files, one for each .c file. The generated .h files contain exactly those declarations required by the corresponding .c files, no more and no less. |
| ︙ | ︙ | |||
193 194 195 196 197 198 199 | a problem. Simply rerun makeheaders to resynchronize everything. <p><li> The generated .h file contains the minimal set of declarations needed by the .c file. This means that when something changes, a minimal amount of recompilation is required to produce an updated executable. | | | 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | a problem. Simply rerun makeheaders to resynchronize everything. <p><li> The generated .h file contains the minimal set of declarations needed by the .c file. This means that when something changes, a minimal amount of recompilation is required to produce an updated executable. Experience has shown that this gives a dramatic improvement in programmer productivity by facilitating a rapid modify-compile-test cycle during development. <p><li> The makeheaders program automatically sorts declarations into the correct order, completely eliminating the wearisome and error-prone task of sorting declarations by hand. </ol> |
| ︙ | ︙ | |||
235 236 237 238 239 240 241 | but manually entered .h files that contain structure declarations and so forth will be scanned and the declarations will be copied into the generated .h files as appropriate. But if makeheaders sees that the .h file that it has generated is no different from the .h file it generated last time, it doesn't update the file. | | | 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | but manually entered .h files that contain structure declarations and so forth will be scanned and the declarations will be copied into the generated .h files as appropriate. But if makeheaders sees that the .h file that it has generated is no different from the .h file it generated last time, it doesn't update the file. This prevents the corresponding .c files from having to be needlessly recompiled. </p> <p> There are several options to the makeheaders program that can be used to alter its behavior. The default behavior is to write a single .h file for each .c file and |
| ︙ | ︙ | |||
297 298 299 300 301 302 303 | In this example, makeheaders will scan the three files named ``alpha.c'', ``beta.c'' and ``gamma.c'' but because of the colon on the end of third filename it will only generate headers for the first two files. Unfortunately, | | | 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 | In this example, makeheaders will scan the three files named ``alpha.c'', ``beta.c'' and ``gamma.c'' but because of the colon on the end of third filename it will only generate headers for the first two files. Unfortunately, it is not possible to get makeheaders to process any file whose name contains a colon. </p> <p> In a large project, the length of the command line for makeheaders can become very long. If the operating system doesn't support long command lines |
| ︙ | ︙ | |||
335 336 337 338 339 340 341 | Such prototypes are normally omitted. </p> <p> Finally, makeheaders also includes a ``-doc'' option. This command line option prevents makeheaders from generating any headers at all. | | | 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 | Such prototypes are normally omitted. </p> <p> Finally, makeheaders also includes a ``-doc'' option. This command line option prevents makeheaders from generating any headers at all. Instead, makeheaders will write to standard output information about every definition and declaration that it encounters in its scan of source files. The information output includes the type of the definition or declaration and any comment that preceeds the definition or declaration. The output is in a format that can be easily parsed, and is intended to be read by another program that will generate |
| ︙ | ︙ | |||
380 381 382 383 384 385 386 | <a name="H0007"></a> <h3>3.1 The Basic Setup</h3> <p> The simpliest way to use makeheaders is to put all definitions in one or more .c files and all structure and type declarations in separate .h files. | | | 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 | <a name="H0007"></a> <h3>3.1 The Basic Setup</h3> <p> The simpliest way to use makeheaders is to put all definitions in one or more .c files and all structure and type declarations in separate .h files. The only restriction is that you should take care to chose basenames for your .h files that are different from the basenames for you .c files. Recall that if your .c file is named (for example) ``alpha.c'' makeheaders will attempt to generate a corresponding header file named ``alpha.h''. For that reason, you don't want to use that name for any of the .h files you write since that will prevent makeheaders |
| ︙ | ︙ | |||
457 458 459 460 461 462 463 | <pre> makeheaders *.[ch] </pre> The makeheaders program will scan all of the .c files and all of the manually written .h files and then automatically generate .h files | | | | | 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 | <pre> makeheaders *.[ch] </pre> The makeheaders program will scan all of the .c files and all of the manually written .h files and then automatically generate .h files corresponding to all .c files. </p> <p> Note that the wildcard expression used in the above example, ``<code>*.[ch]</code>'', will expand to include all .h files in the current directory, both those entered manually be the programmer and others generated automatically by a prior run of makeheaders. But that is not a problem. The makeheaders program will recognize and ignore any files it has previously generated that show up on its input list. </p> <a name="H0008"></a> <h3>3.2 What Declarations Get Copied</h3> <p> |
| ︙ | ︙ | |||
528 529 530 531 532 533 534 | declaration of that variable is placed in the header of every .c file that uses the variable. </p> <p><li> When a structure, union or enumeration declaration or a function prototype or a C++ class declaration appears in a | | | 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 | declaration of that variable is placed in the header of every .c file that uses the variable. </p> <p><li> When a structure, union or enumeration declaration or a function prototype or a C++ class declaration appears in a manually produced .h file, that declaration is copied into the automatically generated .h files of all .c files that use the structure, union, enumeration, function or class. But declarations that appear in a .c file are considered private to that .c file and are not copied into any automatically generated files. </p> |
| ︙ | ︙ | |||
608 609 610 611 612 613 614 | <p> You can instruct makeheaders to treat any part of a .c file as if it were a .h file by enclosing that part of the .c file within: <pre> #if INTERFACE #endif </pre> | | | | | 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 | <p> You can instruct makeheaders to treat any part of a .c file as if it were a .h file by enclosing that part of the .c file within: <pre> #if INTERFACE #endif </pre> Thus any structure definitions that appear after the ``#if INTERFACE'' but before the corresponding ``#endif'' are eligable to be copied into the automatically generated .h files of other .c files. </p> <p> If you use the ``#if INTERFACE'' mechanism in a .c file, then the generated header for that .c file will contain a line |
| ︙ | ︙ | |||
726 727 728 729 730 731 732 | <pre> #if EXPORT_INTERFACE #endif </pre> will become part of the exported interface. The ``#if EXPORT_INTERFACE'' mechanism can be used in either .c or .h files. | | | 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 | <pre> #if EXPORT_INTERFACE #endif </pre> will become part of the exported interface. The ``#if EXPORT_INTERFACE'' mechanism can be used in either .c or .h files. (The ``#if INTERFACE'' can also be used in both .h and .c files, but since it's use in a .h file would be redundant, we haven't mentioned it before.) </p> <a name="H0011"></a> <h3>3.5 Local declarations processed by makeheaders</h3> |
| ︙ | ︙ | |||
749 750 751 752 753 754 755 | <p> Sometimes it is convenient to have makeheaders sort a sequence of private declarations into the correct order for us automatically. Or, we could have static functions and procedures for which we would like makeheaders to generate prototypes, but the arguments to these functions and procedures uses private declarations. | | | 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 | <p> Sometimes it is convenient to have makeheaders sort a sequence of private declarations into the correct order for us automatically. Or, we could have static functions and procedures for which we would like makeheaders to generate prototypes, but the arguments to these functions and procedures uses private declarations. In both of these cases, we want makeheaders to be aware of the private declarations and copy them into the local header file, but we don't want makeheaders to propagate the declarations outside of the file in which they are declared. </p> <p> When this situation arises, enclose the private declarations |
| ︙ | ︙ | |||
813 814 815 816 817 818 819 | file ``alpha.cpp'' will induce makeheaders to generate a header file named ``alpha.hpp''. </p> <p> Makeheaders augments class definitions by inserting prototypes to methods were appropriate. If a method definition begins with one | | | 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 | file ``alpha.cpp'' will induce makeheaders to generate a header file named ``alpha.hpp''. </p> <p> Makeheaders augments class definitions by inserting prototypes to methods were appropriate. If a method definition begins with one of the special keywords <b>PUBLIC</b>, <b>PROTECTED</b>, or <b>PRIVATE</b> (in upper-case to distinguish them from the regular C++ keywords with the same meaning) then a prototype for that method will be inserted into the class definition. If none of these keywords appear, then the prototype is not inserted. For example, in the following code, the constructor is not explicitly declared in the class definition but makeheaders will add it there because of the PUBLIC keyword that appears before the constructor |
| ︙ | ︙ | |||
872 873 874 875 876 877 878 | Perhaps these issued will be addressed in future revisions. </p> <a name="H0013"></a> <h3>3.7 Conditional Compilation</h3> <p> | | | 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 | Perhaps these issued will be addressed in future revisions. </p> <a name="H0013"></a> <h3>3.7 Conditional Compilation</h3> <p> The makeheaders program understands and tracks the conditional compilation constructs in the source code files it scans. Hence, if the following code appears in a source file <pre> #ifdef UNIX # define WORKS_WELL 1 #else # define WORKS_WELL 0 |
| ︙ | ︙ | |||
1052 1053 1054 1055 1056 1057 1058 | as well as Cygwin32 and MSVC 5.0 for Win32. </p> <a name="H0017"></a> <h2>6.0 Summary And Conclusion</h2> <p> | | | 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 | as well as Cygwin32 and MSVC 5.0 for Win32. </p> <a name="H0017"></a> <h2>6.0 Summary And Conclusion</h2> <p> The makeheaders program will automatically generate a minimal header file for each of a set of C source and header files, and will generate a composite header file for the entire source file suite, for either internal or external use. It can also be used as the parser in an automated program documentation system. </p> |
| ︙ | ︙ |
Changes to src/makemake.tcl.
| ︙ | ︙ | |||
50 51 52 53 54 55 56 57 58 59 60 61 62 63 | doc encode event export file finfo foci fusefs glob graph gzip http http_socket http_transport | > | 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | doc encode event export file finfo foci fshell fusefs glob graph gzip http http_socket http_transport |
| ︙ | ︙ | |||
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 |
# Options used to compile the included SQLite library.
#
set SQLITE_OPTIONS {
-DNDEBUG=1
-DSQLITE_OMIT_LOAD_EXTENSION=1
-DSQLITE_ENABLE_LOCKING_STYLE=0
-DSQLITE_THREADSAFE=0
-DSQLITE_DEFAULT_FILE_FORMAT=4
-DSQLITE_OMIT_DEPRECATED
-DSQLITE_ENABLE_EXPLAIN_COMMENTS
-DSQLITE_ENABLE_FTS4
-DSQLITE_ENABLE_FTS3_PARENTHESIS
-DSQLITE_ENABLE_DBSTAT_VTAB
-DSQLITE_ENABLE_JSON1
-DSQLITE_ENABLE_FTS5
}
#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 {
-Dmain=sqlite3_shell
-DSQLITE_OMIT_LOAD_EXTENSION=1
-DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE)
-DSQLITE_SHELL_DBNAME_PROC=fossil_open
}
# miniz (libz drop-in alternative) precompiler flags.
#
| > > | 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 |
# Options used to compile the included SQLite library.
#
set SQLITE_OPTIONS {
-DNDEBUG=1
-DSQLITE_OMIT_LOAD_EXTENSION=1
-DSQLITE_ENABLE_LOCKING_STYLE=0
-DSQLITE_LIKE_DOESNT_MATCH_BLOBS=1
-DSQLITE_THREADSAFE=0
-DSQLITE_DEFAULT_FILE_FORMAT=4
-DSQLITE_OMIT_DEPRECATED
-DSQLITE_ENABLE_EXPLAIN_COMMENTS
-DSQLITE_ENABLE_FTS4
-DSQLITE_ENABLE_FTS3_PARENTHESIS
-DSQLITE_ENABLE_DBSTAT_VTAB
-DSQLITE_ENABLE_JSON1
-DSQLITE_ENABLE_FTS5
}
#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 {
-Dmain=sqlite3_shell
-DSQLITE_SHELL_IS_UTF8=1
-DSQLITE_OMIT_LOAD_EXTENSION=1
-DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE)
-DSQLITE_SHELL_DBNAME_PROC=fossil_open
}
# miniz (libz drop-in alternative) precompiler flags.
#
|
| ︙ | ︙ | |||
301 302 303 304 305 306 307 | $(OBJDIR)/mkversion: $(SRCDIR)/mkversion.c $(BCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c $(OBJDIR)/codecheck1: $(SRCDIR)/codecheck1.c $(BCC) -o $(OBJDIR)/codecheck1 $(SRCDIR)/codecheck1.c | | | 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 | $(OBJDIR)/mkversion: $(SRCDIR)/mkversion.c $(BCC) -o $(OBJDIR)/mkversion $(SRCDIR)/mkversion.c $(OBJDIR)/codecheck1: $(SRCDIR)/codecheck1.c $(BCC) -o $(OBJDIR)/codecheck1 $(SRCDIR)/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 |
| ︙ | ︙ | |||
335 336 337 338 339 340 341 | # Setup the options used to compile the included miniz library. MINIZ_OPTIONS = <<<MINIZ_OPTIONS>>> # The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set # to 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. | | | > > > > > > > > > > > > > > > > > | 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 |
# Setup the options used to compile the included miniz library.
MINIZ_OPTIONS = <<<MINIZ_OPTIONS>>>
# The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
# to 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.
SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
SQLITE3_OBJ.1 =
SQLITE3_OBJ. = $(SQLITE3_OBJ.0)
# The FOSSIL_ENABLE_MINIZ variable may be undefined, set to 0, or
# set to 1. If it is set to 1, the miniz library included in the
# source tree should be used; otherwise, it should not.
MINIZ_OBJ.0 =
MINIZ_OBJ.1 = $(OBJDIR)/miniz.o
MINIZ_OBJ. = $(MINIZ_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, ordinary 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 = sqlite3.c
SQLITE3_SRC.1 = sqlite3-see.c
SQLITE3_SRC. = sqlite3.c
SQLITE3_SRC = $(SRCDIR)/$(SQLITE3_SRC.$(USE_SEE))
SQLITE3_SHELL_SRC.0 = shell.c
SQLITE3_SHELL_SRC.1 = shell-see.c
SQLITE3_SHELL_SRC. = shell.c
SQLITE3_SHELL_SRC = $(SRCDIR)/$(SQLITE3_SHELL_SRC.$(USE_SEE))
SEE_FLAGS.0 =
SEE_FLAGS.1 = -DSQLITE_HAS_CODEC
SEE_FLAGS. =
SEE_FLAGS = $(SEE_FLAGS.$(USE_SEE))
}]
writeln [string map [list <<<NEXT_LINE>>> \\] {
EXTRAOBJ = <<<NEXT_LINE>>>
$(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE)) <<<NEXT_LINE>>>
$(MINIZ_OBJ.$(FOSSIL_ENABLE_MINIZ)) <<<NEXT_LINE>>>
$(LINENOISE_OBJ.$(USE_LINENOISE)) <<<NEXT_LINE>>>
|
| ︙ | ︙ | |||
418 419 420 421 422 423 424 |
writeln "\$(OBJDIR)/${s}_.c:\t\$(SRCDIR)/$s.c \$(OBJDIR)/translate"
writeln "\t\$(OBJDIR)/translate \$(SRCDIR)/$s.c >\$@\n"
writeln "\$(OBJDIR)/$s.o:\t\$(OBJDIR)/${s}_.c \$(OBJDIR)/$s.h$extra_h($s)\$(SRCDIR)/config.h"
writeln "\t\$(XTCC) -o \$(OBJDIR)/$s.o -c \$(OBJDIR)/${s}_.c\n"
writeln "\$(OBJDIR)/$s.h:\t\$(OBJDIR)/headers\n"
}
| | | > | | | 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 |
writeln "\$(OBJDIR)/${s}_.c:\t\$(SRCDIR)/$s.c \$(OBJDIR)/translate"
writeln "\t\$(OBJDIR)/translate \$(SRCDIR)/$s.c >\$@\n"
writeln "\$(OBJDIR)/$s.o:\t\$(OBJDIR)/${s}_.c \$(OBJDIR)/$s.h$extra_h($s)\$(SRCDIR)/config.h"
writeln "\t\$(XTCC) -o \$(OBJDIR)/$s.o -c \$(OBJDIR)/${s}_.c\n"
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)/sqlite3.h"
writeln "\t\$(XTCC) \$(SHELL_OPTIONS) \$(SHELL_CFLAGS) \$(LINENOISE_DEF.\$(USE_LINENOISE)) -c \$(SQLITE3_SHELL_SRC) -o \$@\n"
writeln "\$(OBJDIR)/linenoise.o:\t\$(SRCDIR)/linenoise.c \$(SRCDIR)/linenoise.h"
writeln "\t\$(XTCC) -c \$(SRCDIR)/linenoise.c -o \$@\n"
writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th.c -o \$@\n"
|
| ︙ | ︙ | |||
499 500 501 502 503 504 505 506 507 508 509 510 511 | # 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 and options for use in building executables that # will run on the platform that is doing the build. This is used # to compile code-generator programs as part of the build process. # See TCC below for the C compiler for building the finished binary. # | > > > > > > > > | | 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 | # 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 # code-generator programs as part of the build process. See TCC # and TCCEXE below for the C compiler for building the finished # binary. # BCCEXE = gcc #### C Compiler and options for use in building executables that # will run on the platform that is doing the build. This is used # to compile code-generator programs as part of the build process. # See TCC below for the C compiler for building the finished binary. # BCC = $(BCCEXE) #### Enable compiling with debug symbols (much larger binary) # # FOSSIL_ENABLE_SYMBOLS = 1 #### Enable JSON (http://www.json.org) support using "cson" # |
| ︙ | ︙ | |||
555 556 557 558 559 560 561 562 563 564 565 566 567 568 | #### Load Tcl using the private stubs mechanism # # FOSSIL_ENABLE_TCL_PRIVATE_STUBS = 1 #### Use 'system' SQLite # # USE_SYSTEM_SQLITE = 1 #### Use the miniz compression library # # FOSSIL_ENABLE_MINIZ = 1 #### Use the Tcl source directory instead of the install directory? # This is useful when Tcl has been compiled statically with MinGW. | > > > > | 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 | #### Load Tcl using the private stubs mechanism # # FOSSIL_ENABLE_TCL_PRIVATE_STUBS = 1 #### Use 'system' SQLite # # USE_SYSTEM_SQLITE = 1 #### Use the SQLite Encryption Extension # # USE_SEE = 1 #### Use the miniz compression library # # FOSSIL_ENABLE_MINIZ = 1 #### Use the Tcl source directory instead of the install directory? # This is useful when Tcl has been compiled statically with MinGW. |
| ︙ | ︙ | |||
597 598 599 600 601 602 603 | # used, taking into account whether zlib is actually enabled and the target # processor architecture. # ifndef X64 SSLCONFIG = mingw ifndef FOSSIL_ENABLE_MINIZ ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" | | | | | | 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 | # used, taking into account whether zlib is actually enabled and the target # processor architecture. # ifndef X64 SSLCONFIG = mingw ifndef FOSSIL_ENABLE_MINIZ ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" ZLIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o else ZLIBCONFIG = ZLIBTARGETS = endif else SSLCONFIG = mingw64 ZLIBCONFIG = ZLIBTARGETS = endif #### Disable creation of the OpenSSL shared libraries. Also, disable support # for both SSLv2 and SSLv3 (i.e. thereby forcing the use of TLS). # SSLCONFIG += no-ssl2 no-ssl3 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). # ifndef FOSSIL_ENABLE_MINIZ SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib endif #### The directories where the OpenSSL include and library files are located. # The recommended usage here is to use the Sysinternals junction tool # to create a hard link between an "openssl-1.x" sub-directory of the # Fossil source code directory and the target OpenSSL source directory. # OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2h OPENSSLINCDIR = $(OPENSSLDIR)/include OPENSSLLIBDIR = $(OPENSSLDIR) #### Either the directory where the Tcl library is installed or the Tcl # source code directory resides (depending on the value of the macro # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory, # this directory must have "include" and "lib" sub-directories. If |
| ︙ | ︙ | |||
666 667 668 669 670 671 672 | endif TCLTARGET = libtclstub86.a else LIBTCL = -ltcl86 TCLTARGET = binaries endif | > > > > > > > > | | | | 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 | endif TCLTARGET = libtclstub86.a else LIBTCL = -ltcl86 TCLTARGET = binaries endif #### C compiler for use in building executables that will run on the # target platform. This is usually the same as BCCEXE, unless you # are cross-compiling. This C compiler builds the finished binary # for fossil. See BCC and BCCEXE above for the C compiler for # building intermediate code-generator tools. # TCCEXE = gcc #### 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 #### Add the necessary command line options to build with debugging # symbols, if enabled. # ifdef FOSSIL_ENABLE_SYMBOLS TCC += -g else |
| ︙ | ︙ | |||
780 781 782 783 784 785 786 787 788 789 790 791 792 793 | endif # With JSON support ifdef FOSSIL_ENABLE_JSON TCC += -DFOSSIL_ENABLE_JSON=1 RCC += -DFOSSIL_ENABLE_JSON=1 endif #### The option -static has no effect on MinGW(-w64), only dynamic # executables can be built when linking with MSVCRT. OpenSSL # (optional) and zlib (required) however are always linked in # statically. Therefore, the FOSSIL_DYNAMIC_BUILD option does # not really apply to MinGW (i.e. since ALL external libraries # are NOT linked dynamically). | > > > > > > | 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 | endif # With JSON support ifdef FOSSIL_ENABLE_JSON TCC += -DFOSSIL_ENABLE_JSON=1 RCC += -DFOSSIL_ENABLE_JSON=1 endif # With SQLite Encryption Extension support ifdef USE_SEE TCC += -DUSE_SEE=1 RCC += -DUSE_SEE=1 endif #### The option -static has no effect on MinGW(-w64), only dynamic # executables can be built when linking with MSVCRT. OpenSSL # (optional) and zlib (required) however are always linked in # statically. Therefore, the FOSSIL_DYNAMIC_BUILD option does # not really apply to MinGW (i.e. since ALL external libraries # are NOT linked dynamically). |
| ︙ | ︙ | |||
985 986 987 988 989 990 991 | $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) $(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@ # The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set # to 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. | | | > > > > > > > > > > > > > > > > > < < < < < < > > > > > | | > > | | | | | | | 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 |
$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION)
$(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@
# The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
# to 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.
SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
SQLITE3_OBJ.1 =
SQLITE3_OBJ. = $(SQLITE3_OBJ.0)
# The FOSSIL_ENABLE_MINIZ variable may be undefined, set to 0, or
# set to 1. If it is set to 1, the miniz library included in the
# source tree should be used; otherwise, it should not.
MINIZ_OBJ.0 =
MINIZ_OBJ.1 = $(OBJDIR)/miniz.o
MINIZ_OBJ. = $(MINIZ_OBJ.0)
# The USE_SEE variable may be undefined, 0 or 1. If undefined or
# 0, ordinary 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 = sqlite3.c
SQLITE3_SRC.1 = sqlite3-see.c
SQLITE3_SRC. = sqlite3.c
SQLITE3_SRC = $(SRCDIR)/$(SQLITE3_SRC.$(USE_SEE))
SQLITE3_SHELL_SRC.0 = shell.c
SQLITE3_SHELL_SRC.1 = shell-see.c
SQLITE3_SHELL_SRC. = shell.c
SQLITE3_SHELL_SRC = $(SRCDIR)/$(SQLITE3_SHELL_SRC.$(USE_SEE))
SEE_FLAGS.0 =
SEE_FLAGS.1 = -DSQLITE_HAS_CODEC
SEE_FLAGS. =
SEE_FLAGS = $(SEE_FLAGS.$(USE_SEE))
}
writeln [string map [list <<<NEXT_LINE>>> \\] {
EXTRAOBJ = <<<NEXT_LINE>>>
$(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE)) <<<NEXT_LINE>>>
$(MINIZ_OBJ.$(FOSSIL_ENABLE_MINIZ)) <<<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
ifdef FOSSIL_ENABLE_MINIZ
BLDTARGETS =
else
BLDTARGETS = zlib
endif
openssl: $(BLDTARGETS)
cd $(OPENSSLLIBDIR);./Configure --cross-compile-prefix=$(PREFIX) $(SSLCONFIG)
$(MAKE) -C $(OPENSSLLIBDIR) CC=$(TCCEXE) build_libs
clean-openssl:
$(MAKE) -C $(OPENSSLLIBDIR) CC=$(TCCEXE) clean
tcl:
cd $(TCLSRCDIR)/win;./configure
$(MAKE) -C $(TCLSRCDIR)/win CC=$(TCCEXE) $(TCLTARGET)
clean-tcl:
$(MAKE) -C $(TCLSRCDIR)/win CC=$(TCCEXE) distclean
APPTARGETS += $(BLDTARGETS)
ifdef FOSSIL_BUILD_SSL
APPTARGETS += openssl
endif
$(APPNAME): $(APPTARGETS) $(OBJDIR)/headers $(CODECHECK1) $(OBJ) $(EXTRAOBJ) $(OBJDIR)/fossil.o
$(CODECHECK1) $(TRANS_SRC)
|
| ︙ | ︙ | |||
1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 |
foreach s [lsort $src] {
writeln "\$(OBJDIR)/${s}_.c:\t\$(SRCDIR)/$s.c \$(TRANSLATE)"
writeln "\t\$(TRANSLATE) \$(SRCDIR)/$s.c >\$@\n"
writeln "\$(OBJDIR)/$s.o:\t\$(OBJDIR)/${s}_.c \$(OBJDIR)/$s.h$extra_h($s)\$(SRCDIR)/config.h"
writeln "\t\$(XTCC) -o \$(OBJDIR)/$s.o -c \$(OBJDIR)/${s}_.c\n"
writeln "\$(OBJDIR)/${s}.h:\t\$(OBJDIR)/headers\n"
}
set SQLITE_WIN32_OPTIONS $SQLITE_OPTIONS
lappend SQLITE_WIN32_OPTIONS -DSQLITE_WIN32_NO_ANSI
set MINGW_SQLITE_OPTIONS $SQLITE_WIN32_OPTIONS
| > > > | | | > | | | 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 |
foreach s [lsort $src] {
writeln "\$(OBJDIR)/${s}_.c:\t\$(SRCDIR)/$s.c \$(TRANSLATE)"
writeln "\t\$(TRANSLATE) \$(SRCDIR)/$s.c >\$@\n"
writeln "\$(OBJDIR)/$s.o:\t\$(OBJDIR)/${s}_.c \$(OBJDIR)/$s.h$extra_h($s)\$(SRCDIR)/config.h"
writeln "\t\$(XTCC) -o \$(OBJDIR)/$s.o -c \$(OBJDIR)/${s}_.c\n"
writeln "\$(OBJDIR)/${s}.h:\t\$(OBJDIR)/headers\n"
}
writeln {MINGW_OPTIONS = -D_HAVE__MINGW_H
}
set SQLITE_WIN32_OPTIONS $SQLITE_OPTIONS
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 MINIZ_WIN32_OPTIONS $MINIZ_OPTIONS
set j " \\\n "
writeln "SQLITE_OPTIONS = [join $MINGW_SQLITE_OPTIONS $j]\n"
set j " \\\n "
writeln "SHELL_OPTIONS = [join $SHELL_WIN32_OPTIONS $j]\n"
set j " \\\n "
writeln "MINIZ_OPTIONS = [join $MINIZ_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)/cson_amalgamation.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/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)/sqlite3.h \$(SRCDIR)/../win/Makefile.mingw"
writeln "\t\$(XTCC) \$(SHELL_OPTIONS) \$(SHELL_CFLAGS) -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"
|
| ︙ | ︙ | |||
1412 1413 1414 1415 1416 1417 1418 1419 1420 | FOSSIL_ENABLE_TH1_HOOKS = 0 !endif # Enable support for Windows XP with Visual Studio 201x? !ifndef FOSSIL_ENABLE_WINXP FOSSIL_ENABLE_WINXP = 0 !endif !if $(FOSSIL_ENABLE_SSL)!=0 | > > > > > | | 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 | FOSSIL_ENABLE_TH1_HOOKS = 0 !endif # Enable support for Windows XP with Visual Studio 201x? !ifndef FOSSIL_ENABLE_WINXP FOSSIL_ENABLE_WINXP = 0 !endif # Enable support for the SQLite Encryption Extension? !ifndef USE_SEE USE_SEE = 0 !endif !if $(FOSSIL_ENABLE_SSL)!=0 SSLDIR = $(B)\compat\openssl-1.0.2h SSLINCDIR = $(SSLDIR)\inc32 !if $(FOSSIL_DYNAMIC_BUILD)!=0 SSLLIBDIR = $(SSLDIR)\out32dll !else SSLLIBDIR = $(SSLDIR)\out32 !endif SSLLFLAGS = /nologo /opt:ref /debug |
| ︙ | ︙ | |||
1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 |
TCC = $(TCC) /DFOSSIL_ENABLE_TCL_STUBS=1
RCC = $(RCC) /DFOSSIL_ENABLE_TCL_STUBS=1
TCC = $(TCC) /DFOSSIL_ENABLE_TCL_PRIVATE_STUBS=1
RCC = $(RCC) /DFOSSIL_ENABLE_TCL_PRIVATE_STUBS=1
TCC = $(TCC) /DUSE_TCL_STUBS=1
RCC = $(RCC) /DUSE_TCL_STUBS=1
!endif
}
regsub -all {[-]D} [join $SQLITE_WIN32_OPTIONS { }] {/D} MSC_SQLITE_OPTIONS
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 "
| > > > > > | 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 |
TCC = $(TCC) /DFOSSIL_ENABLE_TCL_STUBS=1
RCC = $(RCC) /DFOSSIL_ENABLE_TCL_STUBS=1
TCC = $(TCC) /DFOSSIL_ENABLE_TCL_PRIVATE_STUBS=1
RCC = $(RCC) /DFOSSIL_ENABLE_TCL_PRIVATE_STUBS=1
TCC = $(TCC) /DUSE_TCL_STUBS=1
RCC = $(RCC) /DUSE_TCL_STUBS=1
!endif
!if $(USE_SEE)!=0
TCC = $(TCC) /DUSE_SEE=1
RCC = $(RCC) /DUSE_SEE=1
!endif
}
regsub -all {[-]D} [join $SQLITE_WIN32_OPTIONS { }] {/D} MSC_SQLITE_OPTIONS
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 "
|
| ︙ | ︙ | |||
1754 1755 1756 1757 1758 1759 1760 | mkversion$E: $(SRCDIR)\mkversion.c $(BCC) $** codecheck1$E: $(SRCDIR)\codecheck1.c $(BCC) $** | > > > | > > > | > > > | > > > | | 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 | mkversion$E: $(SRCDIR)\mkversion.c $(BCC) $** codecheck1$E: $(SRCDIR)\codecheck1.c $(BCC) $** !if $(USE_SEE)!=0 SQLITE3_SHELL_SRC = $(SRCDIR)\shell-see.c !else SQLITE3_SHELL_SRC = $(SRCDIR)\shell.c !endif $(OX)\shell$O : $(SQLITE3_SHELL_SRC) $B\win\Makefile.msc $(TCC) /Fo$@ $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) -c $(SQLITE3_SHELL_SRC) !if $(USE_SEE)!=0 SQLITE3_SRC = $(SRCDIR)\sqlite3-see.c !else SQLITE3_SRC = $(SRCDIR)\sqlite3.c !endif $(OX)\sqlite3$O : $(SQLITE3_SRC) $B\win\Makefile.msc $(TCC) /Fo$@ -c $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $(SEE_FLAGS) $(SQLITE3_SRC) $(OX)\th$O : $(SRCDIR)\th.c $(TCC) /Fo$@ -c $** $(OX)\th_lang$O : $(SRCDIR)\th_lang.c $(TCC) /Fo$@ -c $** |
| ︙ | ︙ |
Changes to src/manifest.c.
| ︙ | ︙ | |||
1418 1419 1420 1421 1422 1423 1424 |
if( *ppOther==0 ) return;
}
if( fetch_baseline(pParent, 0) || fetch_baseline(pChild, 0) ){
manifest_destroy(*ppOther);
return;
}
isPublic = !content_is_private(mid);
| | | 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 |
if( *ppOther==0 ) return;
}
if( fetch_baseline(pParent, 0) || fetch_baseline(pChild, 0) ){
manifest_destroy(*ppOther);
return;
}
isPublic = !content_is_private(mid);
/* If pParent is not the primary parent of pChild, and the primary
** parent of pChild is a phantom, then abort this routine without
** doing any work. The mlink entries will be computed when the
** primary parent dephantomizes.
*/
if( !isPrim && otherRid==mid
&& !db_exists("SELECT 1 FROM blob WHERE uuid=%Q AND size>0",
|
| ︙ | ︙ | |||
1528 1529 1530 1531 1532 1533 1534 |
if( pChildFile==0 && pParentFile->zUuid!=0 ){
add_one_mlink(pmid, pParentFile->zUuid, mid, 0, pParentFile->zName, 0,
isPublic, isPrim, 0);
}
}
}
manifest_cache_insert(*ppOther);
| | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > | 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 1636 1637 1638 1639 1640 1641 1642 1643 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 |
if( pChildFile==0 && pParentFile->zUuid!=0 ){
add_one_mlink(pmid, pParentFile->zUuid, mid, 0, pParentFile->zName, 0,
isPublic, isPrim, 0);
}
}
}
manifest_cache_insert(*ppOther);
/* If pParent is the primary parent of pChild, also run this analysis
** for all merge parents of pChild
*/
if( isPrim ){
for(i=1; i<pChild->nParent; i++){
pmid = uuid_to_rid(pChild->azParent[i], 0);
if( pmid<=0 ) continue;
add_mlink(pmid, 0, mid, pChild, 0);
}
}
}
/*
** For a check-in with RID "rid" that has nParent parent check-ins given
** by the UUIDs in azParent[], create all appropriate plink and mlink table
** entries.
**
** The primary parent is the first UUID on the azParent[] list.
**
** Return the RID of the primary parent.
*/
static int manifest_add_checkin_linkages(
int rid, /* The RID of the check-in */
Manifest *p, /* Manifest for this check-in */
int nParent, /* Number of parents for this check-in */
char **azParent /* UUIDs for each parent */
){
int i;
int parentid = 0;
char zBaseId[30]; /* Baseline manifest RID for deltas. "NULL" otherwise */
Stmt q;
if( p->zBaseline ){
sqlite3_snprintf(sizeof(zBaseId), zBaseId, "%d",
uuid_to_rid(p->zBaseline,1));
}else{
sqlite3_snprintf(sizeof(zBaseId), zBaseId, "NULL");
}
for(i=0; i<nParent; i++){
int pid = uuid_to_rid(azParent[i], 1);
db_multi_exec(
"INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime, baseid)"
"VALUES(%d, %d, %d, %.17g, %s)",
pid, rid, i==0, p->rDate, zBaseId/*safe-for-%s*/);
if( i==0 ) parentid = pid;
}
add_mlink(parentid, 0, rid, p, 1);
if( nParent>1 ){
/* Change MLINK.PID from 0 to -1 for files that are added by merge. */
db_multi_exec(
"UPDATE mlink SET pid=-1"
" WHERE mid=%d"
" AND pid=0"
" AND fnid IN "
" (SELECT fnid FROM mlink WHERE mid=%d GROUP BY fnid"
" HAVING count(*)<%d)",
rid, rid, nParent
);
}
db_prepare(&q, "SELECT cid, isprim FROM plink WHERE pid=%d", rid);
while( db_step(&q)==SQLITE_ROW ){
int cid = db_column_int(&q, 0);
int isprim = db_column_int(&q, 1);
add_mlink(rid, p, cid, 0, isprim);
}
db_finalize(&q);
if( nParent==0 ){
/* For root files (files without parents) add mlink entries
** showing all content as new. */
int isPublic = !content_is_private(rid);
for(i=0; i<p->nFile; i++){
add_one_mlink(0, 0, rid, p->aFile[i].zUuid, p->aFile[i].zName, 0,
isPublic, 1, manifest_file_mperm(&p->aFile[i]));
}
}
return parentid;
}
/*
** There exists a "parent" tag against checkin rid that has value zValue.
** If value is well-formed (meaning that it is a list of UUIDs), then use
** zValue to reparent check-in rid.
*/
void manifest_reparent_checkin(int rid, const char *zValue){
int nParent;
char *zCopy = 0;
char **azParent = 0;
Manifest *p = 0;
int i;
int n = (int)strlen(zValue);
nParent = (n+1)/(UUID_SIZE+1);
if( nParent*(UUID_SIZE+1) - 1 !=n ) return;
if( nParent<1 ) return;
zCopy = fossil_strdup(zValue);
azParent = fossil_malloc( sizeof(azParent[0])*nParent );
for(i=0; i<nParent; i++){
azParent[i] = &zCopy[i*(UUID_SIZE+1)];
if( i<nParent-1 && azParent[i][UUID_SIZE]!=' ' ) break;
azParent[i][UUID_SIZE] = 0;
if( !validate16(azParent[i],UUID_SIZE) ) break;
}
if( i==nParent
&& !db_exists("SELECT 1 FROM plink WHERE cid=%d AND pid=%d",
rid, uuid_to_rid(azParent[0],0))
){
p = manifest_get(rid, CFTYPE_MANIFEST, 0);
}
if( p!=0 ){
db_multi_exec(
"DELETE FROM plink WHERE cid=%d;"
"DELETE FROM mlink WHERE mid=%d;",
rid, rid
);
manifest_add_checkin_linkages(rid,p,nParent,azParent);
}
manifest_destroy(p);
fossil_free(azParent);
fossil_free(zCopy);
}
/*
** Setup to do multiple manifest_crosslink() calls.
**
** This routine creates TEMP tables for holding information for
** processing that must be deferred until all artifacts have been
** seen at least once. The deferred processing is accomplished
** by the call to manifest_crosslink_end().
*/
void manifest_crosslink_begin(void){
assert( manifest_crosslink_busy==0 );
manifest_crosslink_busy = 1;
db_begin_transaction();
db_multi_exec(
"CREATE TEMP TABLE pending_tkt(uuid TEXT UNIQUE);"
|
| ︙ | ︙ | |||
1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 |
assert( manifest_crosslink_busy==1 );
if( permitHooks ){
rc = xfer_run_common_script();
if( rc==TH_OK ){
zScript = xfer_ticket_code();
}
}
db_prepare(&q, "SELECT uuid FROM pending_tkt");
while( db_step(&q)==SQLITE_ROW ){
const char *zUuid = db_column_text(&q, 0);
ticket_rebuild_entry(zUuid);
if( permitHooks && rc==TH_OK ){
rc = xfer_run_script(zScript, zUuid, 0);
}
| > > > > > > > > > > > | 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 |
assert( manifest_crosslink_busy==1 );
if( permitHooks ){
rc = xfer_run_common_script();
if( rc==TH_OK ){
zScript = xfer_ticket_code();
}
}
db_prepare(&q,
"SELECT rid, value FROM tagxref"
" WHERE tagid=%d AND tagtype=1",
TAG_PARENT
);
while( db_step(&q)==SQLITE_ROW ){
int rid = db_column_int(&q,0);
const char *zValue = db_column_text(&q,1);
manifest_reparent_checkin(rid, zValue);
}
db_finalize(&q);
db_prepare(&q, "SELECT uuid FROM pending_tkt");
while( db_step(&q)==SQLITE_ROW ){
const char *zUuid = db_column_text(&q, 0);
ticket_rebuild_entry(zUuid);
if( permitHooks && rc==TH_OK ){
rc = xfer_run_script(zScript, zUuid, 0);
}
|
| ︙ | ︙ | |||
1796 1797 1798 1799 1800 1801 1802 |
** Processing for other control artifacts was added later. The name
** of the routine, "manifest_crosslink", and the name of this source
** file, is a legacy of its original use.
*/
int manifest_crosslink(int rid, Blob *pContent, int flags){
int i, rc = TH_OK;
Manifest *p;
| < | 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 |
** Processing for other control artifacts was added later. The name
** of the routine, "manifest_crosslink", and the name of this source
** file, is a legacy of its original use.
*/
int manifest_crosslink(int rid, Blob *pContent, int flags){
int i, rc = TH_OK;
Manifest *p;
int parentid = 0;
int permitHooks = (flags & MC_PERMIT_HOOKS);
const char *zScript = 0;
const char *zUuid = 0;
if( (p = manifest_cache_find(rid))!=0 ){
blob_reset(pContent);
|
| ︙ | ︙ | |||
1835 1836 1837 1838 1839 1840 1841 |
if( p->type==CFTYPE_MANIFEST ){
if( permitHooks ){
zScript = xfer_commit_code();
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
}
if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){
char *zCom;
| < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 |
if( p->type==CFTYPE_MANIFEST ){
if( permitHooks ){
zScript = xfer_commit_code();
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
}
if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){
char *zCom;
parentid = manifest_add_checkin_linkages(rid,p,p->nParent,p->azParent);
search_doc_touch('c', rid, 0);
db_multi_exec(
"REPLACE INTO event(type,mtime,objid,user,comment,"
"bgcolor,euser,ecomment,omtime)"
"VALUES('ci',"
" coalesce("
" (SELECT julianday(value) FROM tagxref WHERE tagid=%d AND rid=%d),"
|
| ︙ | ︙ | |||
2064 2065 2066 2067 2068 2069 2070 |
const char *zTarget = db_column_text(&qatt, 2);
const char *zName = db_column_text(&qatt, 3);
const char isAdd = (zSrc && zSrc[0]) ? 1 : 0;
char *zComment;
if( isAdd ){
zComment = mprintf(
"Add attachment [/artifact/%!S|%h] to"
| | | | > > | | | 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 |
const char *zTarget = db_column_text(&qatt, 2);
const char *zName = db_column_text(&qatt, 3);
const char isAdd = (zSrc && zSrc[0]) ? 1 : 0;
char *zComment;
if( isAdd ){
zComment = mprintf(
"Add attachment [/artifact/%!S|%h] to"
" tech note [/technote/%!S|%S]",
zSrc, zName, zTarget, zTarget);
}else{
zComment = mprintf(
"Delete attachment \"%h\" from"
" tech note [/technote/%!S|%S]",
zName, zTarget, zTarget);
}
db_multi_exec("UPDATE event SET comment=%Q, type='e'"
" WHERE objid=%Q",
zComment, zAttachId);
fossil_free(zComment);
}
db_finalize(&qatt);
}
if( p->type==CFTYPE_TICKET ){
char *zTag;
Stmt qatt;
assert( manifest_crosslink_busy==1 );
|
| ︙ | ︙ | |||
2110 2111 2112 2113 2114 2115 2116 |
}else{
zComment = mprintf("Delete attachment \"%h\" from ticket [%!S|%S]",
zName, zTarget, zTarget);
}
db_multi_exec("UPDATE event SET comment=%Q, type='t'"
" WHERE objid=%Q",
zComment, zAttachId);
| | | | | 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 |
}else{
zComment = mprintf("Delete attachment \"%h\" from ticket [%!S|%S]",
zName, zTarget, zTarget);
}
db_multi_exec("UPDATE event SET comment=%Q, type='t'"
" WHERE objid=%Q",
zComment, zAttachId);
fossil_free(zComment);
}
db_finalize(&qatt);
}
if( p->type==CFTYPE_ATTACHMENT ){
char *zComment = 0;
const char isAdd = (p->zAttachSrc && p->zAttachSrc[0]) ? 1 : 0;
/* We assume that we're attaching to a wiki page until we
** prove otherwise (which could on a later artifact if we
** process the attachment artifact before the artifact to
** which it is attached!) */
char attachToType = 'w';
if( fossil_is_uuid(p->zAttachTarget) ){
if( db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'",
p->zAttachTarget)
){
attachToType = 't'; /* Attaching to known ticket */
}else if( db_exists("SELECT 1 FROM tag WHERE tagname='event-%q'",
p->zAttachTarget)
){
attachToType = 'e'; /* Attaching to known tech note */
}
}
db_multi_exec(
"INSERT INTO attachment(attachid, mtime, src, target,"
"filename, comment, user)"
|
| ︙ | ︙ | |||
2160 2161 2162 2163 2164 2165 2166 |
}else{
zComment = mprintf("Delete attachment \"%h\" from wiki page [%h]",
p->zAttachName, p->zAttachTarget);
}
}else if( 'e' == attachToType ){
if( isAdd ){
zComment = mprintf(
| | | | > > | > | | 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 |
}else{
zComment = mprintf("Delete attachment \"%h\" from wiki page [%h]",
p->zAttachName, p->zAttachTarget);
}
}else if( 'e' == attachToType ){
if( isAdd ){
zComment = mprintf(
"Add attachment [/artifact/%!S|%h] to tech note [/technote/%!S|%S]",
p->zAttachSrc, p->zAttachName, p->zAttachTarget, p->zAttachTarget);
}else{
zComment = mprintf(
"Delete attachment \"/artifact/%!S|%h\" from"
" tech note [/technote/%!S|%S]",
p->zAttachName, p->zAttachName,
p->zAttachTarget,p->zAttachTarget);
}
}else{
if( isAdd ){
zComment = mprintf(
"Add attachment [/artifact/%!S|%h] to ticket [%!S|%S]",
p->zAttachSrc, p->zAttachName, p->zAttachTarget, p->zAttachTarget);
}else{
zComment = mprintf("Delete attachment \"%h\" from ticket [%!S|%S]",
|
| ︙ | ︙ |
Changes to src/markdown.c.
| ︙ | ︙ | |||
33 34 35 36 37 38 39 |
********************/
#if INTERFACE
/* mkd_autolink -- type of autolink */
enum mkd_autolink {
MKDA_NOT_AUTOLINK, /* used internally when it is not an autolink*/
| | | | 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
********************/
#if INTERFACE
/* mkd_autolink -- type of autolink */
enum mkd_autolink {
MKDA_NOT_AUTOLINK, /* used internally when it is not an autolink*/
MKDA_NORMAL, /* normal http/http/ftp link */
MKDA_EXPLICIT_EMAIL, /* e-mail link with explicit mailto: */
MKDA_IMPLICIT_EMAIL /* e-mail link without mailto: */
};
/* mkd_renderer -- functions for rendering parsed data */
struct mkd_renderer {
/* document level callbacks */
void (*prolog)(struct Blob *ob, void *opaque);
|
| ︙ | ︙ | |||
346 347 348 349 350 351 352 |
i++;
}
if( i>=size || data[i]!='>' || nb!=1 ) return 0;
return i+1;
}
| | | 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 |
i++;
}
if( i>=size || data[i]!='>' || nb!=1 ) return 0;
return i+1;
}
/* tag_length -- returns the length of the given tag, or 0 if it's not valid */
static size_t tag_length(char *data, size_t size, enum mkd_autolink *autolink){
size_t i, j;
/* a valid tag can't be shorter than 3 chars */
if( size<3 ) return 0;
/* begins with a '<' optionally followed by '/', followed by letter */
|
| ︙ | ︙ | |||
401 402 403 404 405 406 407 |
/* one of the forbidden chars has been found */
*autolink = MKDA_NOT_AUTOLINK;
}else if( (j = is_mail_autolink(data+i, size-i))!=0 ){
*autolink = (i==8) ? MKDA_EXPLICIT_EMAIL : MKDA_IMPLICIT_EMAIL;
return i+j;
}
| | | 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 |
/* one of the forbidden chars has been found */
*autolink = MKDA_NOT_AUTOLINK;
}else if( (j = is_mail_autolink(data+i, size-i))!=0 ){
*autolink = (i==8) ? MKDA_EXPLICIT_EMAIL : MKDA_IMPLICIT_EMAIL;
return i+j;
}
/* looking for something looking like a tag end */
while( i<size && data[i]!='>' ){ i++; }
if( i>=size ) return 0;
return i+1;
}
/* parse_inline -- parses inline markdown elements */
|
| ︙ | ︙ | |||
518 519 520 521 522 523 524 |
i++;
}
}
return 0;
}
| | | 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 |
i++;
}
}
return 0;
}
/* parse_emph1 -- parsing single emphasis */
/* closed by a symbol not preceded by whitespace and not followed by symbol */
static size_t parse_emph1(
struct Blob *ob,
struct render *rndr,
char *data,
size_t size,
char c
|
| ︙ | ︙ | |||
563 564 565 566 567 568 569 |
return r ? i+1 : 0;
}
}
return 0;
}
| | | 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 |
return r ? i+1 : 0;
}
}
return 0;
}
/* parse_emph2 -- parsing single emphasis */
static size_t parse_emph2(
struct Blob *ob,
struct render *rndr,
char *data,
size_t size,
char c
){
|
| ︙ | ︙ | |||
602 603 604 605 606 607 608 |
}
i++;
}
return 0;
}
| | | 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 |
}
i++;
}
return 0;
}
/* parse_emph3 -- parsing single emphasis */
/* finds the first closing tag, and delegates to the other emph */
static size_t parse_emph3(
struct Blob *ob,
struct render *rndr,
char *data,
size_t size,
char c
|
| ︙ | ︙ | |||
775 776 777 778 779 780 781 |
}
}
return 2;
}
/* char_entity -- '&' escaped when it doesn't belong to an entity */
| | | 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 |
}
}
return 2;
}
/* char_entity -- '&' escaped when it doesn't belong to an entity */
/* valid entities are assumed to be anything matching &#?[A-Za-z0-9]+; */
static size_t char_entity(
struct Blob *ob,
struct render *rndr,
char *data,
size_t offset,
size_t size
){
|
| ︙ | ︙ | |||
1020 1021 1022 1023 1024 1025 1026 |
if( id_end>=size ) goto char_link_cleanup;
if( i+1==id_end ){
/* implicit id - use the contents */
id_data = data+1;
id_size = txt_e-1;
}else{
| | | 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 |
if( id_end>=size ) goto char_link_cleanup;
if( i+1==id_end ){
/* implicit id - use the contents */
id_data = data+1;
id_size = txt_e-1;
}else{
/* explicit id - between brackets */
id_data = data+i+1;
id_size = id_end-(i+1);
}
if( get_link_ref(rndr, link, title, id_data, id_size)<0 ){
goto char_link_cleanup;
}
|
| ︙ | ︙ | |||
1136 1137 1138 1139 1140 1141 1142 |
return (i>=size || data[i]=='\n') ? 2 : 0;
}
return 0;
}
| | | 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 |
return (i>=size || data[i]=='\n') ? 2 : 0;
}
return 0;
}
/* is_table_sep -- returns whether there is a table separator at pos */
static int is_table_sep(char *data, size_t pos){
return data[pos]=='|' && (pos==0 || data[pos-1]!='\\');
}
/* is_tableline -- returns the number of column tables in the given line */
static int is_tableline(char *data, size_t size){
|
| ︙ | ︙ | |||
1185 1186 1187 1188 1189 1190 1191 |
}
}else{
return 0;
}
}
| | | 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 |
}
}else{
return 0;
}
}
/* prefix_code -- returns prefix length for block code */
static size_t prefix_code(char *data, size_t size){
if( size>0 && data[0]=='\t' ) return 1;
if( size>3 && data[0]==' ' && data[1]==' ' && data[2]==' ' && data[3]==' ' ){
return 4;
}
return 0;
}
|
| ︙ | ︙ | |||
1242 1243 1244 1245 1246 1247 1248 | static void parse_block( struct Blob *ob, struct render *rndr, char *data, size_t size); | | | 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 |
static void parse_block(
struct Blob *ob,
struct render *rndr,
char *data,
size_t size);
/* parse_blockquote -- handles parsing of a blockquote fragment */
static size_t parse_blockquote(
struct Blob *ob,
struct render *rndr,
char *data,
size_t size
){
size_t beg, end = 0, pre, work_size = 0;
|
| ︙ | ︙ | |||
1292 1293 1294 1295 1296 1297 1298 |
rndr->make.blockquote(ob, out ? out : &fallback, rndr->make.opaque);
}
release_work_buffer(rndr, out);
return end;
}
| | | 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 |
rndr->make.blockquote(ob, out ? out : &fallback, rndr->make.opaque);
}
release_work_buffer(rndr, out);
return end;
}
/* parse_paragraph -- handles parsing of a regular paragraph */
static size_t parse_paragraph(
struct Blob *ob,
struct render *rndr,
char *data,
size_t size
){
size_t i = 0, end = 0;
|
| ︙ | ︙ | |||
1375 1376 1377 1378 1379 1380 1381 |
release_work_buffer(rndr, span);
}
}
return end;
}
| | | 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 |
release_work_buffer(rndr, span);
}
}
return end;
}
/* parse_blockcode -- handles parsing of a block-level code fragment */
static size_t parse_blockcode(
struct Blob *ob,
struct render *rndr,
char *data,
size_t size
){
size_t beg, end, pre;
|
| ︙ | ︙ | |||
1811 1812 1813 1814 1815 1816 1817 |
int flags /* table flags */
){
size_t i = 0, col = 0;
size_t beg, end, total = 0;
struct Blob *cells = new_work_buffer(rndr);
int align;
| | | 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 |
int flags /* table flags */
){
size_t i = 0, col = 0;
size_t beg, end, total = 0;
struct Blob *cells = new_work_buffer(rndr);
int align;
/* skip leading blanks and separator */
while( i<size && (data[i]==' ' || data[i]=='\t') ){ i++; }
if( i<size && data[i]=='|' ) i++;
/* go over all the cells */
while( i<size && total==0 ){
/* check optional left/center align marker */
align = 0;
|
| ︙ | ︙ | |||
2028 2029 2030 2031 2032 2033 2034 | /* is_ref -- returns whether a line is a reference or not */ static int is_ref( char *data, /* input text */ size_t beg, /* offset of the beginning of the line */ size_t end, /* offset of the end of the text */ size_t *last, /* last character of the link */ | | | 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 |
/* is_ref -- returns whether a line is a reference or not */
static int is_ref(
char *data, /* input text */
size_t beg, /* offset of the beginning of the line */
size_t end, /* offset of the end of the text */
size_t *last, /* last character of the link */
struct Blob *refs /* array of link references */
){
size_t i = 0;
size_t id_offset, id_end;
size_t link_offset, link_end;
size_t title_offset, title_end;
size_t line_end;
struct link_ref lr = {
|
| ︙ | ︙ |
Changes to src/markdown.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 |
# Markdown Overview #
## Paragraphs ##
> Paragraphs are divided by blank lines.
## Headings ##
>
# Top-level Heading Alternative Top Level Heading
=============================
>
## Second-level Heading Alternative 2nd Level Heading
-----------------------------
## Links ##
> 1. **\[display text\]\(URL\)**
> 2. **\[display text\]\(URL "Title"\)**
> 3. **\<URL\>**
> 4. **\[display text\]\[label\]**
> With link format 4 ("reference links") the label must be resolved by
> including a line of the form **\[label\]: URL** or
> **\[label\]: URL "Title"** somewhere else
> in the document.
## Fonts ##
> * _\*italic\*_
> * *\_italic\_*
> * __\*\*bold\*\*__
> * **\_\_bold\_\_**
> * `` `code` ``
> Note that the \`...\` construct disables HTML markup, so one can write,
> for example, **\``<html>`\`** to yield **`<html>`**.
## Lists ##
>
* bullet item
+ bullet item
- bullet item
1. numbered item
## Block Quotes ##
> Begin each line of a paragraph with ">" to block quote that paragraph.
> >
> This paragraph is indented
> >
> > Double-indented paragraph
## Miscellaneous ##
> * In-line images using **\!\[alt-text\]\(image-URL\)**
> * Use HTML for complex formatting issues.
> * Escape special characters (ex: "\[", "\(", "\*")
> using backslash (ex: "\\\[", "\\\(", "\\\*").
> * See [daringfireball.net](http://daringfireball.net/projects/markdown/syntax)
> for additional information.
## Special Features For Fossil ##
> * In hyperlinks, if the URL begins with "/" then the root of the Fossil
> repository is prepended. This allows for repository-relative hyperlinks.
> * For documents that begin with top-level heading (ex: "# heading #"), the
> heading is omitted from the body of the document and becomes the document
> title displayed at the top of the Fossil page.
|
Changes to src/markdown_html.c.
| ︙ | ︙ | |||
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 |
static int html_link(
struct Blob *ob,
struct Blob *link,
struct Blob *title,
struct Blob *content,
void *opaque
){
BLOB_APPEND_LITERAL(ob, "<a href=\"");
html_escape(ob, blob_buffer(link), blob_size(link));
if( title && blob_size(title)>0 ){
BLOB_APPEND_LITERAL(ob, "\" title=\"");
html_escape(ob, blob_buffer(title), blob_size(title));
}
BLOB_APPEND_LITERAL(ob, "\">");
BLOB_APPEND_BLOB(ob, content);
| > > > > > > | 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 |
static int html_link(
struct Blob *ob,
struct Blob *link,
struct Blob *title,
struct Blob *content,
void *opaque
){
char *zLink = blob_buffer(link);
BLOB_APPEND_LITERAL(ob, "<a href=\"");
if( zLink && zLink[0]=='/' ){
/* For any hyperlink that begins with "/", make it refer to the root
** of the Fossil repository */
blob_append(ob, g.zTop, -1);
}
html_escape(ob, blob_buffer(link), blob_size(link));
if( title && blob_size(title)>0 ){
BLOB_APPEND_LITERAL(ob, "\" title=\"");
html_escape(ob, blob_buffer(title), blob_size(title));
}
BLOB_APPEND_LITERAL(ob, "\">");
BLOB_APPEND_BLOB(ob, content);
|
| ︙ | ︙ |
Changes to src/md5.c.
| ︙ | ︙ | |||
420 421 422 423 424 425 426 427 428 429 430 431 432 433 |
DigestToBase16(zResult, blob_buffer(pCksum));
return 0;
}
/*
** COMMAND: md5sum*
** Usage: %fossil md5sum FILES....
**
** Compute an MD5 checksum of all files named on the command-line.
** If a file is named "-" then content is read from standard input.
*/
void md5sum_test(void){
int i;
| > | 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 |
DigestToBase16(zResult, blob_buffer(pCksum));
return 0;
}
/*
** COMMAND: md5sum*
**
** Usage: %fossil md5sum FILES....
**
** Compute an MD5 checksum of all files named on the command-line.
** If a file is named "-" then content is read from standard input.
*/
void md5sum_test(void){
int i;
|
| ︙ | ︙ |
Changes to src/merge.c.
| ︙ | ︙ | |||
126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
fForkSeen = fossil_find_nearest_fork(rid, db_open_local(0))!=0;
}
}
}
db_finalize(&q);
return fForkSeen;
}
/*
** COMMAND: merge
**
** Usage: %fossil merge ?OPTIONS? ?VERSION?
**
** The argument VERSION is a version that should be merged into the
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
fForkSeen = fossil_find_nearest_fork(rid, db_open_local(0))!=0;
}
}
}
db_finalize(&q);
return fForkSeen;
}
/*
** Add an entry to the FV table for all files renamed between
** version N and the version specified by vid.
*/
static void add_renames(
const char *zFnCol, /* The FV column for the filename in vid */
int vid, /* The desired version's RID */
int nid, /* Version N's RID */
int revOk, /* Ok to move backwards (child->parent) if true */
const char *zDebug /* Generate trace output if not NULL */
){
int nChng; /* Number of file name changes */
int *aChng; /* An array of file name changes */
int i; /* Loop counter */
find_filename_changes(nid, vid, revOk, &nChng, &aChng, zDebug);
if( nChng==0 ) return;
for(i=0; i<nChng; i++){
char *zN, *zV;
zN = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2]);
zV = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2+1]);
db_multi_exec(
"INSERT OR IGNORE INTO fv(%s,fnn) VALUES(%Q,%Q)",
zFnCol /*safe-for-%s*/, zV, zN
);
if( db_changes()==0 ){
db_multi_exec(
"UPDATE fv SET %s=%Q WHERE fnn=%Q",
zFnCol /*safe-for-%s*/, zV, zN
);
}
free(zN);
free(zV);
}
free(aChng);
}
/*
** COMMAND: merge
**
** Usage: %fossil merge ?OPTIONS? ?VERSION?
**
** The argument VERSION is a version that should be merged into the
|
| ︙ | ︙ | |||
175 176 177 178 179 180 181 |
** -n|--dry-run If given, display instead of run actions
**
** -v|--verbose Show additional details of the merge
*/
void merge_cmd(void){
int vid; /* Current version "V" */
int mid; /* Version we are merging from "M" */
| | > < < < > > | 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 |
** -n|--dry-run If given, display instead of run actions
**
** -v|--verbose Show additional details of the merge
*/
void merge_cmd(void){
int vid; /* Current version "V" */
int mid; /* Version we are merging from "M" */
int pid = 0; /* The pivot version - most recent common ancestor P */
int nid = 0; /* The name pivot version "N" */
int verboseFlag; /* True if the -v|--verbose option is present */
int integrateFlag; /* True if the --integrate option is present */
int pickFlag; /* True if the --cherrypick option is present */
int backoutFlag; /* True if the --backout option is present */
int dryRunFlag; /* True if the --dry-run or -n option is present */
int forceFlag; /* True if the --force or -f option is present */
int forceMissingFlag; /* True if the --force-missing option is present */
const char *zBinGlob; /* The value of --binary */
const char *zPivot; /* The value of --baseline */
int debugFlag; /* True if --debug is present */
int nConflict = 0; /* Number of conflicts seen */
int nOverwrite = 0; /* Number of unmanaged files overwritten */
char vAncestor = 'p'; /* If P is an ancestor of V then 'p', else 'n' */
Stmt q;
/* Notation:
**
** V The current checkout
** M The version being merged in
** P The "pivot" - the most recent common ancestor of V and M.
** N The "name pivot" - for detecting renames
*/
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 */
|
| ︙ | ︙ | |||
227 228 229 230 231 232 233 |
if( zBinGlob==0 ) zBinGlob = db_get("binary-glob",0);
vid = db_lget_int("checkout", 0);
if( vid==0 ){
fossil_fatal("nothing is checked out");
}
if( !dryRunFlag ){
if( autosync_loop(SYNC_PULL + SYNC_VERBOSE*verboseFlag,
| | | | 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 |
if( zBinGlob==0 ) zBinGlob = db_get("binary-glob",0);
vid = db_lget_int("checkout", 0);
if( vid==0 ){
fossil_fatal("nothing is checked out");
}
if( !dryRunFlag ){
if( autosync_loop(SYNC_PULL + SYNC_VERBOSE*verboseFlag,
db_get_int("autosync-tries", 1), 1) ){
fossil_fatal("merge abandoned due to sync failure");
}
}
/* Find mid, the artifactID of the version to be merged into the current
** check-out */
if( g.argc==3 ){
/* Mid is specified as an argument on the command-line */
|
| ︙ | ︙ | |||
289 290 291 292 293 294 295 |
pid = name_to_typed_rid(zPivot, "ci");
if( pid==0 || !is_a_version(pid) ){
fossil_fatal("not a version: %s", zPivot);
}
if( pickFlag ){
fossil_fatal("incompatible options: --cherrypick & --baseline");
}
| > | > | | | | | | | | | | | > > > > > > > > > > | 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 |
pid = name_to_typed_rid(zPivot, "ci");
if( pid==0 || !is_a_version(pid) ){
fossil_fatal("not a version: %s", zPivot);
}
if( pickFlag ){
fossil_fatal("incompatible options: --cherrypick & --baseline");
}
}
if( pickFlag || backoutFlag ){
if( integrateFlag ){
fossil_fatal("incompatible options: --integrate & --cherrypick or --backout");
}
pid = db_int(0, "SELECT pid FROM plink WHERE cid=%d AND isprim", mid);
if( pid<=0 ){
fossil_fatal("cannot find an ancestor for %s", g.argv[2]);
}
}else{
if( !zPivot ){
pivot_set_primary(mid);
pivot_set_secondary(vid);
db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0");
while( db_step(&q)==SQLITE_ROW ){
pivot_set_secondary(db_column_int(&q,0));
}
db_finalize(&q);
pid = pivot_find(0);
if( pid<=0 ){
fossil_fatal("cannot find a common ancestor between the current "
"checkout and %s", g.argv[2]);
}
}
pivot_set_primary(mid);
pivot_set_secondary(vid);
nid = pivot_find(1);
if( nid!=pid ){
pivot_set_primary(nid);
pivot_set_secondary(pid);
nid = pivot_find(1);
}
}
if( backoutFlag ){
int t = pid;
pid = mid;
mid = t;
}
if( nid==0 ) nid = pid;
if( !is_a_version(pid) ){
fossil_fatal("not a version: record #%d", pid);
}
if( !forceFlag && mid==pid ){
fossil_print("Merge skipped because it is a no-op. "
" Use --force to override.\n");
return;
|
| ︙ | ︙ | |||
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 |
if( !dryRunFlag ) undo_begin();
if( load_vfile_from_rid(mid) && !forceMissingFlag ){
fossil_fatal("missing content, unable to merge");
}
if( load_vfile_from_rid(pid) && !forceMissingFlag ){
fossil_fatal("missing content, unable to merge");
}
if( debugFlag ){
char *z;
z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pid);
fossil_print("P=%d %z\n", pid, z);
z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
fossil_print("M=%d %z\n", mid, z);
z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
fossil_print("V=%d %z\n", vid, z);
}
/*
** The vfile.pathname field is used to match files against each other. The
** FV table contains one row for each each unique filename in
** in the current checkout, the pivot, and the version being merged.
*/
db_multi_exec(
"DROP TABLE IF EXISTS fv;"
"CREATE TEMP TABLE fv("
| > > > > > > > > > > > > > | | | | | | | | | > | > > > > > > > > > | | | | > > > | | < < < < < < < < < < < < < < < | < < < | | > > > | < > > > | > | > > > > | | | < | < < | | < < | | < < < < < | | < < | | < | | | < < < < < | < | > | | > > > > > > > > > > > > > > > > > > > > > > | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 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 571 572 573 574 575 576 577 578 579 580 581 |
if( !dryRunFlag ) undo_begin();
if( load_vfile_from_rid(mid) && !forceMissingFlag ){
fossil_fatal("missing content, unable to merge");
}
if( load_vfile_from_rid(pid) && !forceMissingFlag ){
fossil_fatal("missing content, unable to merge");
}
if( zPivot ){
vAncestor = db_exists(
"WITH RECURSIVE ancestor(id) AS ("
" VALUES(%d)"
" UNION ALL"
" SELECT pid FROM plink, ancestor"
" WHERE cid=ancestor.id AND pid!=%d AND cid!=%d)"
"SELECT 1 FROM ancestor WHERE id=%d LIMIT 1",
vid, nid, pid, pid
) ? 'p' : 'n';
}
if( debugFlag ){
char *z;
z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nid);
fossil_print("N=%d %z\n", nid, z);
z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pid);
fossil_print("P=%d %z\n", pid, z);
z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
fossil_print("M=%d %z\n", mid, z);
z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
fossil_print("V=%d %z\n", vid, z);
}
/*
** The vfile.pathname field is used to match files against each other. The
** FV table contains one row for each each unique filename in
** in the current checkout, the pivot, and the version being merged.
*/
db_multi_exec(
"DROP TABLE IF EXISTS fv;"
"CREATE TEMP TABLE fv("
" fn TEXT UNIQUE %s," /* The filename */
" idv INTEGER DEFAULT 0," /* VFILE entry for current version */
" idp INTEGER DEFAULT 0," /* VFILE entry for the pivot */
" idm INTEGER DEFAULT 0," /* VFILE entry for version merging in */
" chnged BOOLEAN," /* True if current version has been edited */
" ridv INTEGER DEFAULT 0," /* Record ID for current version */
" ridp INTEGER DEFAULT 0," /* Record ID for pivot */
" ridm INTEGER DEFAULT 0," /* Record ID for merge */
" isexe BOOLEAN," /* Execute permission enabled */
" fnp TEXT UNIQUE %s," /* The filename in the pivot */
" fnm TEXT UNIQUE %s," /* The filename in the merged version */
" fnn TEXT UNIQUE %s," /* The filename in the name pivot */
" islinkv BOOLEAN," /* True if current version is a symlink */
" islinkm BOOLEAN" /* True if merged version in is a symlink */
");",
filename_collation(), filename_collation(), filename_collation(),
filename_collation()
);
/*
** Compute name changes from N to V, P, and M
*/
add_renames("fn", vid, nid, 0, debugFlag ? "N->V" : 0);
add_renames("fnp", pid, nid, 0, debugFlag ? "N->P" : 0);
add_renames("fnm", mid, nid, backoutFlag, debugFlag ? "N->M" : 0);
/*
** Add files found in V
*/
db_multi_exec(
"UPDATE OR IGNORE fv SET fn=coalesce(fn%c,fnn) WHERE fn IS NULL;"
"REPLACE INTO fv(fn,fnp,fnm,fnn,idv,ridv,islinkv,isexe,chnged)"
" SELECT pathname, fnp, fnm, fnn, id, rid, islink, vf.isexe, vf.chnged"
" FROM vfile vf"
" LEFT JOIN fv ON fn=coalesce(origname,pathname)"
" AND rid>0 AND vf.chnged NOT IN (3,5)"
" WHERE vid=%d;",
vAncestor, vid
);
/*
** Add files found in P
*/
db_multi_exec(
"UPDATE OR IGNORE fv SET fnp=coalesce(fnn,"
" (SELECT coalesce(origname,pathname) FROM vfile WHERE id=idv))"
" WHERE fnp IS NULL;"
"INSERT OR IGNORE INTO fv(fnp)"
" SELECT coalesce(origname,pathname) FROM vfile WHERE vid=%d;",
pid
);
/*
** Add files found in M
*/
db_multi_exec(
"UPDATE OR IGNORE fv SET fnm=fnp WHERE fnm IS NULL;"
"INSERT OR IGNORE INTO fv(fnm)"
" SELECT pathname FROM vfile WHERE vid=%d;",
mid
);
/*
** Compute the file version ids for P and M
*/
if( pid==vid ){
db_multi_exec(
"UPDATE fv SET idp=idv, ridp=ridv WHERE ridv>0 AND chnged NOT IN (3,5)"
);
}else{
db_multi_exec(
"UPDATE fv SET"
" idp=coalesce((SELECT id FROM vfile WHERE vid=%d AND fnp=pathname),0),"
" ridp=coalesce((SELECT rid FROM vfile WHERE vid=%d AND fnp=pathname),0)",
pid, pid
);
}
db_multi_exec(
"UPDATE fv SET"
" idm=coalesce((SELECT id FROM vfile WHERE vid=%d AND fnm=pathname),0),"
" ridm=coalesce((SELECT rid FROM vfile WHERE vid=%d AND fnm=pathname),0),"
" islinkm=coalesce((SELECT islink FROM vfile"
" WHERE vid=%d AND fnm=pathname),0),"
" isexe=coalesce((SELECT isexe FROM vfile WHERE vid=%d AND fnm=pathname),"
" isexe)",
mid, mid, mid, mid
);
if( debugFlag ){
db_prepare(&q,
"SELECT rowid, fn, fnp, fnm, chnged, ridv, ridp, ridm, "
" isexe, islinkv, islinkm, fnn FROM fv"
);
while( db_step(&q)==SQLITE_ROW ){
fossil_print("%3d: ridv=%-4d ridp=%-4d ridm=%-4d chnged=%d isexe=%d "
" islinkv=%d islinkm=%d\n",
db_column_int(&q, 0),
db_column_int(&q, 5),
db_column_int(&q, 6),
db_column_int(&q, 7),
db_column_int(&q, 4),
db_column_int(&q, 8),
db_column_int(&q, 9),
db_column_int(&q, 10));
fossil_print(" fn = [%s]\n", db_column_text(&q, 1));
fossil_print(" fnp = [%s]\n", db_column_text(&q, 2));
fossil_print(" fnm = [%s]\n", db_column_text(&q, 3));
fossil_print(" fnn = [%s]\n", db_column_text(&q, 11));
}
db_finalize(&q);
}
/*
** Update the execute bit on files where it's changed from P->M but not P->V
*/
db_prepare(&q,
"SELECT idv, fn, fv.isexe FROM fv, vfile p, vfile v"
" WHERE p.id=idp AND v.id=idv AND fv.isexe!=p.isexe AND v.isexe=p.isexe"
);
while( db_step(&q)==SQLITE_ROW ){
int idv = db_column_int(&q, 0);
const char *zName = db_column_text(&q, 1);
int isExe = db_column_int(&q, 2);
fossil_print("%s %s\n", isExe ? "EXECUTABLE" : "UNEXEC", zName);
if( !dryRunFlag ){
char *zFullPath = mprintf("%s/%s", g.zLocalRoot, zName);
file_wd_setexe(zFullPath, isExe);
free(zFullPath);
db_multi_exec("UPDATE vfile SET isexe=%d WHERE id=%d", isExe, idv);
}
}
db_finalize(&q);
/*
** Find files in M and V but not in P and report conflicts.
** The file in M will be ignored. It will be treated as if it
** does not exist.
*/
db_prepare(&q,
"SELECT idm FROM fv WHERE idp=0 AND idv>0 AND idm>0"
);
while( db_step(&q)==SQLITE_ROW ){
int idm = db_column_int(&q, 0);
char *zName = db_text(0, "SELECT pathname FROM vfile WHERE id=%d", idm);
fossil_warning("WARNING: no common ancestor for %s", zName);
free(zName);
db_multi_exec("UPDATE fv SET idm=0 WHERE idm=%d", idm);
}
db_finalize(&q);
/*
** Find files that have changed from P->M but not P->V.
** Copy the M content over into V.
*/
db_prepare(&q,
|
| ︙ | ︙ | |||
644 645 646 647 648 649 650 |
while( db_step(&q)==SQLITE_ROW ){
int idv = db_column_int(&q, 0);
const char *zName = db_column_text(&q, 1);
int chnged = db_column_int(&q, 2);
/* Delete the file idv */
fossil_print("DELETE %s\n", zName);
if( chnged ){
| | > > > > > > > > > > | > > > | > > > > | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
while( db_step(&q)==SQLITE_ROW ){
int idv = db_column_int(&q, 0);
const char *zName = db_column_text(&q, 1);
int chnged = db_column_int(&q, 2);
/* Delete the file idv */
fossil_print("DELETE %s\n", zName);
if( chnged ){
fossil_warning("WARNING: local edits lost for %s", zName);
nConflict++;
}
if( !dryRunFlag ) undo_save(zName);
db_multi_exec(
"UPDATE vfile SET deleted=1 WHERE id=%d", idv
);
if( !dryRunFlag ){
char *zFullPath = mprintf("%s%s", g.zLocalRoot, zName);
file_delete(zFullPath);
free(zFullPath);
}
}
db_finalize(&q);
/* For certain sets of renames (e.g. A -> B and B -> A), a file that is
** being renamed must first be moved to a temporary location to avoid
** being overwritten by another rename operation. A row is added to the
** TMPRN table for each of these temporary renames.
*/
db_multi_exec(
"DROP TABLE IF EXISTS tmprn;"
"CREATE TEMP TABLE tmprn(fn UNIQUE, tmpfn);"
);
/*
** Rename files that have taken a rename on P->M but which keep the same
** name on P->V. If a file is renamed on P->V only or on both P->V and
** P->M then we retain the V name of the file.
*/
db_prepare(&q,
"SELECT idv, fnp, fnm, isexe FROM fv"
" WHERE idv>0 AND idp>0 AND idm>0 AND fnp=fn AND fnm!=fnp"
);
while( db_step(&q)==SQLITE_ROW ){
int idv = db_column_int(&q, 0);
const char *zOldName = db_column_text(&q, 1);
const char *zNewName = db_column_text(&q, 2);
int isExe = db_column_int(&q, 3);
fossil_print("RENAME %s -> %s\n", zOldName, zNewName);
if( !dryRunFlag ) undo_save(zOldName);
if( !dryRunFlag ) undo_save(zNewName);
db_multi_exec(
"UPDATE vfile SET pathname=NULL, origname=pathname"
" WHERE vid=%d AND pathname=%Q;"
"UPDATE vfile SET pathname=%Q, origname=coalesce(origname,pathname)"
" WHERE id=%d;",
vid, zNewName, zNewName, idv
);
if( !dryRunFlag ){
char *zFullOldPath, *zFullNewPath;
zFullOldPath = db_text(0,"SELECT tmpfn FROM tmprn WHERE fn=%Q", zOldName);
if( !zFullOldPath ){
zFullOldPath = mprintf("%s%s", g.zLocalRoot, zOldName);
}
zFullNewPath = mprintf("%s%s", g.zLocalRoot, zNewName);
if( file_wd_size(zFullNewPath)>=0 ){
char zTmpPath[300];
file_tempname(sizeof(zTmpPath), zTmpPath);
db_multi_exec("INSERT INTO tmprn(fn,tmpfn) VALUES(%Q,%Q)",
zNewName, zTmpPath);
if( file_wd_islink(zFullNewPath) ){
symlink_copy(zFullNewPath, zTmpPath);
}else{
file_copy(zFullNewPath, zTmpPath);
}
}
if( file_wd_islink(zFullOldPath) ){
symlink_copy(zFullOldPath, zFullNewPath);
}else{
file_copy(zFullOldPath, zFullNewPath);
}
file_wd_setexe(zFullNewPath, isExe);
file_delete(zFullOldPath);
free(zFullNewPath);
free(zFullOldPath);
}
}
db_finalize(&q);
/* A file that has been deleted and replaced by a renamed file will have a
** NULL pathname. Change it to something that makes the output of "status"
** and similar commands make sense for such files and that will (most likely)
** not be an actual existing pathname.
*/
db_multi_exec(
"UPDATE vfile SET pathname=origname || ' (overwritten by rename)'"
" WHERE pathname IS NULL"
);
/*
** Add to V files that are not in V or P but are in M
*/
db_prepare(&q,
"SELECT idm, fnm FROM fv"
" WHERE idp=0 AND idv=0 AND idm>0"
);
while( db_step(&q)==SQLITE_ROW ){
int idm = db_column_int(&q, 0);
const char *zName;
char *zFullName;
db_multi_exec(
"INSERT INTO vfile(vid,chnged,deleted,rid,mrid,isexe,islink,pathname)"
" SELECT %d,%d,0,rid,mrid,isexe,islink,pathname FROM vfile WHERE id=%d",
vid, integrateFlag?5:3, idm
);
zName = db_column_text(&q, 1);
zFullName = mprintf("%s%s", g.zLocalRoot, zName);
if( file_wd_isfile_or_link(zFullName)
&& !db_exists("SELECT 1 FROM fv WHERE fn=%Q", zName) ){
fossil_print("ADDED %s (overwrites an unmanaged file)\n", zName);
nOverwrite++;
}else{
fossil_print("ADDED %s\n", zName);
}
fossil_free(zFullName);
if( !dryRunFlag ){
undo_save(zName);
vfile_to_disk(0, idm, 0, 0);
}
}
db_finalize(&q);
/* Report on conflicts
*/
if( nConflict ){
fossil_warning("WARNING: %d merge conflicts", nConflict);
}
if( nOverwrite ){
|
| ︙ | ︙ |
Changes to src/merge3.c.
| ︙ | ︙ | |||
338 339 340 341 342 343 344 | blob_read_from_file(&file, zFullpath); rc = contains_merge_marker(&file); blob_reset(&file); return rc; } /* | | | 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 | blob_read_from_file(&file, zFullpath); rc = contains_merge_marker(&file); blob_reset(&file); return rc; } /* ** COMMAND: 3-way-merge* ** ** Usage: %fossil 3-way-merge BASELINE V1 V2 MERGED ** ** Inputs are files BASELINE, V1, and V2. The file MERGED is generated ** as output. ** ** BASELINE is a common ancestor of two files V1 and V2 that have diverging |
| ︙ | ︙ |
Changes to src/name.c.
| ︙ | ︙ | |||
369 370 371 372 373 374 375 |
);
if( c<2 ) c = 0;
}
return c;
}
/*
| | | 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 |
);
if( c<2 ) c = 0;
}
return c;
}
/*
** COMMAND: test-name-to-id
**
** Convert a name to a full artifact ID.
*/
void test_name_to_id(void){
int i;
Blob name;
db_must_be_within_tree();
|
| ︙ | ︙ | |||
663 664 665 666 667 668 669 670 671 672 673 674 675 676 |
comment_print(db_column_text(&q,1), 0, 12, -1, g.comFmtFlags);
}
db_finalize(&q);
}
/*
** COMMAND: whatis*
** Usage: %fossil whatis NAME
**
** Resolve the symbol NAME into its canonical 40-character SHA1-hash
** artifact name and provide a description of what role that artifact
** plays.
**
** Options:
| > | 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 |
comment_print(db_column_text(&q,1), 0, 12, -1, g.comFmtFlags);
}
db_finalize(&q);
}
/*
** COMMAND: whatis*
**
** Usage: %fossil whatis NAME
**
** Resolve the symbol NAME into its canonical 40-character SHA1-hash
** artifact name and provide a description of what role that artifact
** plays.
**
** Options:
|
| ︙ | ︙ | |||
688 689 690 691 692 693 694 |
db_find_and_open_repository(0,0);
verboseFlag = find_option("verbose","v",0)!=0;
zType = find_option("type",0,1);
/* We should be done with options.. */
verify_all_options();
| | | 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 |
db_find_and_open_repository(0,0);
verboseFlag = find_option("verbose","v",0)!=0;
zType = find_option("type",0,1);
/* We should be done with options.. */
verify_all_options();
if( g.argc<3 ) usage("NAME ...");
for(i=2; i<g.argc; i++){
zName = g.argv[i];
if( i>2 ) fossil_print("%.79c\n",'-');
rid = symbolic_name_to_rid(zName, zType);
if( rid<0 ){
Stmt q;
int cnt = 0;
|
| ︙ | ︙ | |||
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 |
whatis_rid(rid, verboseFlag);
}
}
}
/*
** COMMAND: test-whatis-all
** Usage: %fossil test-whatis-all
**
** Show "whatis" information about every artifact in the repository
*/
void test_whatis_all_cmd(void){
Stmt q;
int cnt = 0;
db_find_and_open_repository(0,0);
db_prepare(&q, "SELECT rid FROM blob ORDER BY rid");
while( db_step(&q)==SQLITE_ROW ){
if( cnt++ ) fossil_print("%.79c\n", '-');
whatis_rid(db_column_int(&q,0), 1);
}
db_finalize(&q);
}
/*
** COMMAND: test-ambiguous
** Usage: %fossil test-ambiguous [--minsize N]
**
** Show a list of ambiguous SHA1-hash abbreviations of N characters or
** more where N defaults to 4. Change N to a different value using
** the "--minsize N" command-line option.
*/
void test_ambiguous_cmd(void){
| > > | 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 |
whatis_rid(rid, verboseFlag);
}
}
}
/*
** COMMAND: test-whatis-all
**
** Usage: %fossil test-whatis-all
**
** Show "whatis" information about every artifact in the repository
*/
void test_whatis_all_cmd(void){
Stmt q;
int cnt = 0;
db_find_and_open_repository(0,0);
db_prepare(&q, "SELECT rid FROM blob ORDER BY rid");
while( db_step(&q)==SQLITE_ROW ){
if( cnt++ ) fossil_print("%.79c\n", '-');
whatis_rid(db_column_int(&q,0), 1);
}
db_finalize(&q);
}
/*
** COMMAND: test-ambiguous
**
** Usage: %fossil test-ambiguous [--minsize N]
**
** Show a list of ambiguous SHA1-hash abbreviations of N characters or
** more where N defaults to 4. Change N to a different value using
** the "--minsize N" command-line option.
*/
void test_ambiguous_cmd(void){
|
| ︙ | ︙ | |||
929 930 931 932 933 934 935 | /* Mark private elements */ db_multi_exec( "UPDATE description SET isPrivate=1 WHERE rid IN private" ); } /* | | > > > > > | | | 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 |
/* Mark private elements */
db_multi_exec(
"UPDATE description SET isPrivate=1 WHERE rid IN private"
);
}
/*
** Print the content of the description table on stdout.
**
** The description table is computed using the WHERE clause zWhere if
** the zWhere parameter is not NULL. If zWhere is NULL, then this
** routine assumes that the description table already exists and is
** populated and merely prints the contents.
*/
int describe_artifacts_to_stdout(const char *zWhere, const char *zLabel){
Stmt q;
int cnt = 0;
if( zWhere!=0 ) describe_artifacts(zWhere);
db_prepare(&q,
"SELECT uuid, summary, isPrivate\n"
" FROM description\n"
" ORDER BY ctime, type;"
);
while( db_step(&q)==SQLITE_ROW ){
if( zLabel ){
fossil_print("%s\n", zLabel);
zLabel = 0;
}
fossil_print(" %.16s %s", db_column_text(&q,0), db_column_text(&q,1));
if( db_column_int(&q,2) ) fossil_print(" (unpublished)");
fossil_print("\n");
cnt++;
}
db_finalize(&q);
if( zWhere!=0 ) db_multi_exec("DELETE FROM description;");
return cnt;
}
/*
** COMMAND: test-describe-artifacts
**
** Usage: %fossil test-describe-artifacts [--from S] [--count N]
|
| ︙ | ︙ |
Changes to src/path.c.
| ︙ | ︙ | |||
193 194 195 196 197 198 199 |
int i;
if( path.nStep<2 ) return 0;
for(p=path.pEnd, i=0; p && i<path.nStep/2; p=p->pFrom, i++){}
return p;
}
/*
| | | 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
int i;
if( path.nStep<2 ) return 0;
for(p=path.pEnd, i=0; p && i<path.nStep/2; p=p->pFrom, i++){}
return p;
}
/*
** COMMAND: test-shortest-path
**
** Usage: %fossil test-shortest-path ?--no-merge? VERSION1 VERSION2
**
** Report the shortest path between two check-ins. If the --no-merge flag
** is used, follow only direct parent-child paths and omit merge links.
*/
void shortest_path_test_cmd(void){
|
| ︙ | ︙ | |||
299 300 301 302 303 304 305 | } db_finalize(&s); path_reset(); return 0; } /* | | | 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 |
}
db_finalize(&s);
path_reset();
return 0;
}
/*
** COMMAND: test-ancestor-path
**
** Usage: %fossil test-ancestor-path VERSION1 VERSION2
**
** Report the path from VERSION1 to VERSION2 through their most recent
** common ancestor.
*/
void ancestor_path_test_cmd(void){
|
| ︙ | ︙ | |||
450 451 452 453 454 455 456 |
}
db_finalize(&q1);
if( nChng ){
aChng = *aiChng = fossil_malloc( nChng*2*sizeof(int) );
for(pChng=pAll, i=0; pChng; pChng=pChng->pNext){
if( pChng->newName==0 ) continue;
if( pChng->origName==0 ) continue;
| < | 450 451 452 453 454 455 456 457 458 459 460 461 462 463 |
}
db_finalize(&q1);
if( nChng ){
aChng = *aiChng = fossil_malloc( nChng*2*sizeof(int) );
for(pChng=pAll, i=0; pChng; pChng=pChng->pNext){
if( pChng->newName==0 ) continue;
if( pChng->origName==0 ) continue;
aChng[i] = pChng->origName;
aChng[i+1] = pChng->newName;
if( zDebug ){
fossil_print("%s summary %d[%z] -> %d[%z]\n",
zDebug,
aChng[i],
db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i]),
|
| ︙ | ︙ |
Changes to src/piechart.c.
| ︙ | ︙ | |||
297 298 299 300 301 302 303 |
}
db_finalize(&ins);
blob_reset(&all);
if( n>0 ){
@ <svg width=%d(width) height=%d(height) style="border:1px solid #d3d3d3;">
piechart_render(width,height, PIE_OTHER);
@ </svg>
| | | | | | 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 |
}
db_finalize(&ins);
blob_reset(&all);
if( n>0 ){
@ <svg width=%d(width) height=%d(height) style="border:1px solid #d3d3d3;">
piechart_render(width,height, PIE_OTHER);
@ </svg>
@ <hr />
}
@ <form method="post" action='%R/test-piechart'>
@ <p>One slice per line. Value and then Label.<p>
@ <textarea name='data' rows='20' cols='80'>%h(zData)</textarea><br />
@ Width: <input type='text' size='8' name='width' value='%d(width)'/>
@ Height: <input type='text' size='8' name='height' value='%d(height)'/><br />
@ <input type='hidden' name='width' value='%d(width)'/>
@ <input type='hidden' name='height' value='%d(height)'/>
@ <input type='submit' value='Draw The Pie Chart'/>
@ </form>
@ <hr /><p>Previous Data:</p>
@ <table border="1">
db_prepare(&q, "SELECT rowid, amt, label FROM piechart");
while( db_step(&q)==SQLITE_ROW ){
@ <tr><td>%d(db_column_int(&q,0))</td>
@ <td>%g(db_column_double(&q,1))</td>
@ <td>%h(db_column_text(&q,2))</td></tr>
}
|
| ︙ | ︙ |
Changes to src/pivot.c.
| ︙ | ︙ | |||
71 72 73 74 75 76 77 78 | ); } /* ** Find the most recent common ancestor of the primary and one of ** the secondaries. Return its rid. Return 0 if no common ancestor ** can be found. */ | > > | | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
);
}
/*
** Find the most recent common ancestor of the primary and one of
** the secondaries. Return its rid. Return 0 if no common ancestor
** can be found.
**
** If ignoreMerges is true, follow only "primary" parent links.
*/
int pivot_find(int ignoreMerges){
Stmt q1, q2, u1, i1;
int rid = 0;
/* aqueue must contain at least one primary and one other. Otherwise
** we abort early
*/
if( db_int(0, "SELECT count(distinct src) FROM aqueue")<2 ){
|
| ︙ | ︙ | |||
100 101 102 103 104 105 106 |
** is not.
*/
db_prepare(&q2,
"SELECT 1 FROM aqueue A, plink, aqueue B"
" WHERE plink.pid=:rid"
" AND plink.cid=B.rid"
" AND A.rid=:rid"
| | > | > | 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 |
** is not.
*/
db_prepare(&q2,
"SELECT 1 FROM aqueue A, plink, aqueue B"
" WHERE plink.pid=:rid"
" AND plink.cid=B.rid"
" AND A.rid=:rid"
" AND A.src!=B.src %s",
ignoreMerges ? "AND plink.isprim" : ""
);
/* Mark the :rid record has having been checked. It is not the
** common ancestor.
*/
db_prepare(&u1,
"UPDATE aqueue SET pending=0 WHERE rid=:rid"
);
/* Add to the queue all ancestors of :rid.
*/
db_prepare(&i1,
"INSERT OR IGNORE INTO aqueue "
"SELECT plink.pid,"
" coalesce((SELECT mtime FROM plink X WHERE X.cid=plink.pid), 0.0),"
" 1,"
" aqueue.src "
" FROM plink, aqueue"
" WHERE plink.cid=:rid"
" AND aqueue.rid=:rid %s",
ignoreMerges ? "AND plink.isprim" : ""
);
while( db_step(&q1)==SQLITE_ROW ){
rid = db_column_int(&q1, 0);
db_reset(&q1);
db_bind_int(&q2, ":rid", rid);
if( db_step(&q2)==SQLITE_ROW ){
|
| ︙ | ︙ | |||
145 146 147 148 149 150 151 | db_finalize(&q2); db_finalize(&i1); db_finalize(&u1); return rid; } /* | | | | 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 |
db_finalize(&q2);
db_finalize(&i1);
db_finalize(&u1);
return rid;
}
/*
** COMMAND: test-find-pivot
**
** Test the pivot_find() procedure.
*/
void test_find_pivot(void){
int i, rid;
if( g.argc<4 ){
usage("PRIMARY SECONDARY ...");
}
db_must_be_within_tree();
pivot_set_primary(name_to_rid(g.argv[2]));
for(i=3; i<g.argc; i++){
pivot_set_secondary(name_to_rid(g.argv[i]));
}
rid = pivot_find(0);
printf("pivot=%s\n",
db_text("?","SELECT uuid FROM blob WHERE rid=%d",rid)
);
}
|
Changes to src/purge.c.
| ︙ | ︙ | |||
20 21 22 23 24 25 26 | ** manages the graveyard of purged content. */ #include "config.h" #include "purge.h" #include <assert.h> /* | | | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | ** manages the graveyard of purged content. */ #include "config.h" #include "purge.h" #include <assert.h> /* ** SQL code used to initialize the schema of the graveyard. ** ** The purgeevent table contains one entry for each purge event. For each ** purge event, multiple artifacts might have been removed. Each removed ** artifact is stored as an entry in the purgeitem table. ** ** The purgeevent and purgeitem tables are not synced, even by the ** "fossil config" command. They exist only as a backup in case of a |
| ︙ | ︙ | |||
50 51 52 53 54 55 56 57 58 59 60 61 62 63 | @ isPrivate BOOLEAN, -- True if artifact was originally private @ sz INT NOT NULL, -- Uncompressed size of the purged artifact @ desc TEXT, -- Brief description of this artifact @ data BLOB -- Compressed artifact content @ ); ; /* ** This routine purges multiple artifacts from the repository, transfering ** those artifacts into the PURGEITEM table. ** ** Prior to invoking this routine, the caller must create a (TEMP) table ** named zTab that contains the RID of every artifact to be purged. ** | > > > > > > > > > | 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | @ isPrivate BOOLEAN, -- True if artifact was originally private @ sz INT NOT NULL, -- Uncompressed size of the purged artifact @ desc TEXT, -- Brief description of this artifact @ data BLOB -- Compressed artifact content @ ); ; /* ** Flags for the purge_artifact_list() function. */ #if INTERFACE #define PURGE_MOVETO_GRAVEYARD 0x0001 /* Move artifacts in graveyard */ #define PURGE_EXPLAIN_ONLY 0x0002 /* Show what would have happened */ #define PURGE_PRINT_SUMMARY 0x0004 /* Print a summary report at end */ #endif /* ** This routine purges multiple artifacts from the repository, transfering ** those artifacts into the PURGEITEM table. ** ** Prior to invoking this routine, the caller must create a (TEMP) table ** named zTab that contains the RID of every artifact to be purged. ** |
| ︙ | ︙ | |||
79 80 81 82 83 84 85 | ** (h) BACKLINK ** (i) ATTACHMENT ** (j) TICKETCHNG ** (7) If any ticket artifacts were removed (6j) then rebuild the ** corresponding ticket entries. Possibly remove entries from ** the ticket table. ** | | | > > > > > > > > > > | 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 |
** (h) BACKLINK
** (i) ATTACHMENT
** (j) TICKETCHNG
** (7) If any ticket artifacts were removed (6j) then rebuild the
** corresponding ticket entries. Possibly remove entries from
** the ticket table.
**
** Steps 1-4 (saving the purged artifacts into the graveyard) are only
** undertaken if the moveToGraveyard flag is true.
*/
int purge_artifact_list(
const char *zTab, /* TEMP table containing list of RIDS to be purged */
const char *zNote, /* Text of the purgeevent.pnotes field */
unsigned purgeFlags /* zero or more PURGE_* flags */
){
int peid = 0; /* New purgeevent ID */
Stmt q; /* General-use prepared statement */
char *z;
assert( g.repositoryOpen ); /* Main database must already be open */
db_begin_transaction();
z = sqlite3_mprintf("IN \"%w\"", zTab);
describe_artifacts(z);
sqlite3_free(z);
describe_artifacts_to_stdout(0, 0);
/* The explain-only flags causes this routine to list the artifacts
** that would have been purged but to not actually make any changes
** to the repository.
*/
if( purgeFlags & PURGE_EXPLAIN_ONLY ){
db_end_transaction(0);
return 0;
}
/* Make sure we are not removing a manifest that is the baseline of some
** manifest that is being left behind. This step is not strictly necessary.
** is is just a safety check. */
if( purge_baseline_out_from_under_delta(zTab) ){
fossil_fatal("attempt to purge a baseline manifest without also purging "
"all of its deltas");
|
| ︙ | ︙ | |||
119 120 121 122 123 124 125 |
content_undelta(rid);
verify_before_commit(rid);
}
db_finalize(&q);
/* Construct the graveyard and copy the artifacts to be purged into the
** graveyard */
| | | 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
content_undelta(rid);
verify_before_commit(rid);
}
db_finalize(&q);
/* Construct the graveyard and copy the artifacts to be purged into the
** graveyard */
if( purgeFlags & PURGE_MOVETO_GRAVEYARD ){
db_multi_exec(zPurgeInit /*works-like:"%w%w"*/,
db_name("repository"), db_name("repository"));
db_multi_exec(
"INSERT INTO purgeevent(ctime,pnotes) VALUES(now(),%Q)", zNote
);
peid = db_last_insert_rowid();
db_prepare(&q, "SELECT rid FROM delta WHERE rid IN \"%w\""
|
| ︙ | ︙ | |||
187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
ticket_rebuild_entry(db_column_text(&q, 0));
}
db_finalize(&q);
/* db_multi_exec("DROP TABLE \"%w_tickets\"", zTab); */
/* Mission accomplished */
db_end_transaction(0);
return peid;
}
/*
** The TEMP table named zTab contains RIDs for a set of check-ins.
**
** Check to see if any check-in in zTab is a baseline manifest for some
| > > > > > > > | 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
ticket_rebuild_entry(db_column_text(&q, 0));
}
db_finalize(&q);
/* db_multi_exec("DROP TABLE \"%w_tickets\"", zTab); */
/* Mission accomplished */
db_end_transaction(0);
if( purgeFlags & PURGE_PRINT_SUMMARY ){
fossil_print("%d artifacts purged\n",
db_int(0, "SELECT count(*) FROM \"%w\";", zTab));
fossil_print("undoable using \"%s purge undo %d\".\n",
g.nameOfExe, peid);
}
return peid;
}
/*
** The TEMP table named zTab contains RIDs for a set of check-ins.
**
** Check to see if any check-in in zTab is a baseline manifest for some
|
| ︙ | ︙ | |||
218 219 220 221 222 223 224 | } } /* ** The TEMP table named zTab contains the RIDs for a set of check-in ** artifacts. Expand this set (by adding new entries to zTab) to include | | | 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 | } } /* ** The TEMP table named zTab contains the RIDs for a set of check-in ** artifacts. Expand this set (by adding new entries to zTab) to include ** all other artifacts that are used by the check-ins in ** the original list. ** ** If the bExclusive flag is true, then the set is only expanded by ** artifacts that are used exclusively by the check-ins in the set. ** When bExclusive is false, then all artifacts used by the check-ins ** are added even if those artifacts are also used by other check-ins ** not in the set. |
| ︙ | ︙ | |||
420 421 422 423 424 425 426 |
blob_reset(&c2);
}
db_finalize(&q);
if( iSrc>0 ) bag_remove(&busy, iSrc);
}
/*
| | | > > > > > > > > > > > > > | | | < < < | | > > | > > | | | > > > > > > > > > > > > > > | | > > > > > > > > > > > > > > > > > > > > > | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | | | | | | | | | | | | | | | | | | < < < < < < < < < < < < < < < < < < > | < < < < < < | < < | < < < > > | 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 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 |
blob_reset(&c2);
}
db_finalize(&q);
if( iSrc>0 ) bag_remove(&busy, iSrc);
}
/*
** COMMAND: purge*
**
** The purge command removes content from a repository and stores that content
** in a "graveyard". The graveyard exists so that content can be recovered
** using the "fossil purge undo" command. The "fossil purge obliterate"
** command empties the graveyard, making the content unrecoverable.
**
** ==== WARNING: This command can potentially destroy historical data and ====
** ==== leave your repository in a goofy state. Know what you are doing! ====
** ==== Make a backup of your repository before using this command! ====
**
** ==== FURTHER WARNING: This command is a work-in-progress and may yet ====
** ==== contains bugs. ====
**
** fossil purge artifacts UUID... ?OPTIONS?
**
** Move arbitrary artifacts identified by the UUID list into the
** graveyard.
**
** fossil purge cat UUID...
**
** Write the content of one or more artifacts in the graveyard onto
** standard output.
**
** fossil purge checkins TAGS... ?OPTIONS?
**
** Move the check-ins or branches identified by TAGS and all of
** their descendants out of the repository and into the graveyard.
** If TAGS includes a branch name then it means all the check-ins
** on the most recent occurrence of that branch.
**
** fossil purge files NAME ... ?OPTIONS?
**
** Move all instances of files called NAME into the graveyard.
** NAME should be the name of the file relative to the root of the
** repository. If NAME is a directory, then all files within that
** directory are moved.
**
** fossil purge list|ls ?-l?
**
** Show the graveyard of prior purges. The -l option gives more
** detail in the output.
**
** fossil purge obliterate ID... ?--force?
**
** Remove one or more purge events from the graveyard. Once a purge
** event is obliterated, it can no longer be undone. The --force
** option suppresses the confirmation prompt.
**
** fossil purge tickets NAME ... ?OPTIONS?
**
** TBD...
**
** fossil purge undo ID
**
** Restore the content previously removed by purge ID.
**
** fossil purge wiki NAME ... ?OPTIONS?
**
** TBD...
**
** COMMON OPTIONS:
**
** --explain Make no changes, but show what would happen.
** --dry-run An alias for --explain
**
** SUMMARY:
** fossil purge artifacts UUID.. [OPTIONS]
** fossil purge cat UUID...
** fossil purge checkins TAGS... [OPTIONS]
** fossil purge files FILENAME... [OPTIONS]
** fossil purge list
** fossil purge obliterate ID...
** fossil purge tickets NAME... [OPTIONS]
** fossil purge undo ID
** fossil purge wiki NAME... [OPTIONS]
*/
void purge_cmd(void){
int purgeFlags = PURGE_MOVETO_GRAVEYARD | PURGE_PRINT_SUMMARY;
const char *zSubcmd;
int n;
int i;
Stmt q;
if( g.argc<3 ) usage("SUBCOMMAND ?ARGS?");
zSubcmd = g.argv[2];
db_find_and_open_repository(0,0);
n = (int)strlen(zSubcmd);
if( find_option("explain",0,0)!=0 || find_option("dry-run",0,0)!=0 ){
purgeFlags |= PURGE_EXPLAIN_ONLY;
}
if( strncmp(zSubcmd, "artifacts", n)==0 ){
verify_all_options();
db_begin_transaction();
db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
for(i=3; i<g.argc; i++){
int r = name_to_typed_rid(g.argv[i], "");
db_multi_exec("INSERT OR IGNORE INTO ok(rid) VALUES(%d);", r);
}
describe_artifacts_to_stdout("IN ok", 0);
purge_artifact_list("ok", "", purgeFlags);
db_end_transaction(0);
}else if( strncmp(zSubcmd, "cat", n)==0 ){
int i, piid;
Blob content;
if( g.argc<4 ) usage("cat UUID...");
for(i=3; i<g.argc; i++){
piid = db_int(0, "SELECT piid FROM purgeitem WHERE uuid LIKE '%q%%'",
g.argv[i]);
if( piid==0 ) fossil_fatal("no such item: %s", g.argv[3]);
purge_extract_item(piid, &content);
blob_write_to_file(&content, "-");
blob_reset(&content);
}
}else if( strncmp(zSubcmd, "checkins", n)==0 ){
int vid;
if( find_option("explain",0,0)!=0 || find_option("dry-run",0,0)!=0 ){
purgeFlags |= PURGE_EXPLAIN_ONLY;
}
verify_all_options();
db_begin_transaction();
if( g.argc<=3 ) usage("checkins TAGS... [OPTIONS]");
db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
for(i=3; i<g.argc; i++){
int r = name_to_typed_rid(g.argv[i], "br");
compute_descendants(r, 1000000000);
}
vid = db_lget_int("checkout",0);
if( db_exists("SELECT 1 FROM ok WHERE rid=%d",vid) ){
fossil_fatal("cannot purge the current checkout");
}
find_checkin_associates("ok", 1);
purge_artifact_list("ok", "", purgeFlags);
db_end_transaction(0);
}else if( strncmp(zSubcmd, "files", n)==0 ){
verify_all_options();
db_begin_transaction();
db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
for(i=3; i<g.argc; i++){
db_multi_exec(
"INSERT OR IGNORE INTO ok(rid) "
" SELECT fid FROM mlink, filename"
" WHERE mlink.fnid=filename.fnid"
" AND (filename.name=%Q OR filename.name GLOB '%q/*')",
g.argv[i], g.argv[i]
);
}
purge_artifact_list("ok", "", purgeFlags);
db_end_transaction(0);
}else if( strncmp(zSubcmd, "list", n)==0 || strcmp(zSubcmd,"ls")==0 ){
int showDetail = find_option("l","l",0)!=0;
if( !db_table_exists("repository","purgeevent") ) return;
db_prepare(&q, "SELECT peid, datetime(ctime,'unixepoch',toLocal())"
" FROM purgeevent");
while( db_step(&q)==SQLITE_ROW ){
fossil_print("%4d on %s\n", db_column_int(&q,0), db_column_text(&q,1));
if( showDetail ){
purge_list_event_content(db_column_int(&q,0));
}
}
db_finalize(&q);
}else if( strncmp(zSubcmd, "obliterate", n)==0 ){
int i;
int bForce = find_option("force","f",0)!=0;
if( g.argc<4 ) usage("obliterate ID...");
if( !bForce ){
Blob ans;
char cReply;
prompt_user(
"Obliterating the graveyard 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_begin_transaction();
for(i=3; i<g.argc; i++){
int peid = atoi(g.argv[i]);
if( !db_exists("SELECT 1 FROM purgeevent WHERE peid=%d",peid) ){
fossil_fatal("no such purge event: %s", g.argv[i]);
}
db_multi_exec(
"DELETE FROM purgeevent WHERE peid=%d;"
"DELETE FROM purgeitem WHERE peid=%d;",
peid, peid
);
}
db_end_transaction(0);
}else if( strncmp(zSubcmd, "tickets", n)==0 ){
fossil_fatal("not yet implemented....");
}else if( strncmp(zSubcmd, "undo", n)==0 ){
int peid;
if( g.argc!=4 ) usage("undo ID");
peid = atoi(g.argv[3]);
if( (purgeFlags & PURGE_EXPLAIN_ONLY)==0 ){
db_begin_transaction();
db_multi_exec(
"CREATE TEMP TABLE ix("
" piid INTEGER PRIMARY KEY,"
" srcid INTEGER"
");"
"CREATE INDEX ixsrcid ON ix(srcid);"
"INSERT INTO ix(piid,srcid) "
" SELECT piid, coalesce(srcid,0) FROM purgeitem WHERE peid=%d;",
peid
);
db_multi_exec(
"DELETE FROM shun"
" WHERE uuid IN (SELECT uuid FROM purgeitem WHERE peid=%d);",
peid
);
manifest_crosslink_begin();
purge_item_resurrect(0, 0);
manifest_crosslink_end(0);
db_multi_exec("DELETE FROM purgeevent WHERE peid=%d", peid);
db_multi_exec("DELETE FROM purgeitem WHERE peid=%d", peid);
db_end_transaction(0);
}
}else if( strncmp(zSubcmd, "wiki", n)==0 ){
fossil_fatal("not yet implemented....");
}else{
fossil_fatal("unknown subcommand \"%s\".\n"
"should be one of: cat, checkins, files, list, obliterate,"
" tickets, undo, wiki", zSubcmd);
}
}
|
Changes to src/rebuild.c.
| ︙ | ︙ | |||
680 681 682 683 684 685 686 |
if( k>0 ) subtotal += g.parseCnt[k];
}
fossil_print("%-15s %6d\n", "Other:", g.parseCnt[CFTYPE_ANY] - subtotal);
}
}
/*
| > > | | | 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 |
if( k>0 ) subtotal += g.parseCnt[k];
}
fossil_print("%-15s %6d\n", "Other:", g.parseCnt[CFTYPE_ANY] - subtotal);
}
}
/*
** COMMAND: test-detach
**
** Usage: %fossil test-detach ?REPOSITORY?
**
** Change the project-code and make other changes in order to prevent
** the repository from ever again pushing or pulling to other
** repositories. Used to create a "test" repository for development
** testing by cloning a working project repository.
*/
void test_detach_cmd(void){
db_find_and_open_repository(0, 2);
db_begin_transaction();
db_multi_exec(
"DELETE FROM config WHERE name='last-sync-url';"
"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_end_transaction(0);
}
/*
** COMMAND: test-create-clusters
**
** Create clusters for all unclustered artifacts if the number of unclustered
** artifacts exceeds the current clustering threshold.
*/
void test_createcluster_cmd(void){
if( g.argc==3 ){
db_open_repository(g.argv[2]);
|
| ︙ | ︙ | |||
792 793 794 795 796 797 798 |
}
db_finalize(&q);
}
}
/*
** COMMAND: scrub*
| > | | 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 |
}
db_finalize(&q);
}
}
/*
** COMMAND: scrub*
**
** Usage: %fossil scrub ?OPTIONS? ?REPOSITORY?
**
** The command removes sensitive information (such as passwords) from a
** repository so that the repository can be sent to an untrusted reader.
**
** By default, only passwords are removed. However, if the --verily option
** is added, then private branches, concealed email addresses, IP
** addresses of correspondents, and similar privacy-sensitive fields
|
| ︙ | ︙ |
Changes to src/report.c.
| ︙ | ︙ | |||
1181 1182 1183 1184 1185 1186 1187 |
zDir = !strcmp("ASC",zDir) ? "ASC" : "DESC";
zSql = mprintf("SELECT * FROM (%s) ORDER BY %d %s", zSql, nField, zDir);
}
}
count = 0;
if( !tabs ){
| | | 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 |
zDir = !strcmp("ASC",zDir) ? "ASC" : "DESC";
zSql = mprintf("SELECT * FROM (%s) ORDER BY %d %s", zSql, nField, zDir);
}
}
count = 0;
if( !tabs ){
struct GenerateHTML sState = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
db_multi_exec("PRAGMA empty_result_callbacks=ON");
style_submenu_element("Raw", "Raw",
"rptview?tablist=1&%h", PD("QUERY_STRING",""));
if( g.perm.Admin
|| (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
style_submenu_element("Edit", "Edit", "rptedit?rn=%d", rn);
|
| ︙ | ︙ |
Changes to src/search.c.
| ︙ | ︙ | |||
315 316 317 318 319 320 321 | if( wantGap ) blob_append(&p->snip, p->zMarkGap, -1); return score; } /* ** COMMAND: test-match ** | | | 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 |
if( wantGap ) blob_append(&p->snip, p->zMarkGap, -1);
return score;
}
/*
** COMMAND: test-match
**
** Usage: %fossil test-match SEARCHSTRING FILE1 FILE2 ...
*/
void test_match_cmd(void){
Search *p;
int i;
Blob x;
int score;
char *zDoc;
|
| ︙ | ︙ | |||
451 452 453 454 455 456 457 |
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const char *zType = (const char*)sqlite3_value_text(argv[0]);
int rid = sqlite3_value_int(argv[1]);
const char *zName = (const char*)sqlite3_value_text(argv[2]);
| | | | 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 |
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const char *zType = (const char*)sqlite3_value_text(argv[0]);
int rid = sqlite3_value_int(argv[1]);
const char *zName = (const char*)sqlite3_value_text(argv[2]);
int nHdr = 0;
char *z = search_stext_cached(zType[0], rid, zName, &nHdr);
if( nHdr || zType[0]!='d' ){
sqlite3_result_text(context, z, nHdr, SQLITE_TRANSIENT);
}else{
sqlite3_result_value(context, argv[2]);
}
}
static void search_body_sqlfunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const char *zType = (const char*)sqlite3_value_text(argv[0]);
int rid = sqlite3_value_int(argv[1]);
const char *zName = (const char*)sqlite3_value_text(argv[2]);
int nHdr = 0;
char *z = search_stext_cached(zType[0], rid, zName, &nHdr);
sqlite3_result_text(context, z+nHdr+1, -1, SQLITE_TRANSIENT);
}
/*
** Encode a string for use as a query parameter in a URL
*/
|
| ︙ | ︙ | |||
514 515 516 517 518 519 520 |
search_urlencode_sqlfunc, 0, 0);
}
/*
** Testing the search function.
**
** COMMAND: search*
| > | | | | | < | | | | | > > > > > > | 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 |
search_urlencode_sqlfunc, 0, 0);
}
/*
** Testing the search function.
**
** COMMAND: search*
**
** Usage: %fossil search [-all|-a] [-limit|-n #] [-width|-W #] pattern...
**
** Search for timeline entries matching all words provided on the
** command line. Whole-word matches scope more highly than partial
** matches.
**
** Outputs, by default, some top-N fraction of the results. The -all
** option can be used to output all matches, regardless of their search
** score. The -limit option can be used to limit the number of entries
** returned. The -width option can be used to set the output width used
** when printing matches.
**
** Options:
**
** -a|--all Output all matches, not just best matches.
** -n|--limit N Limit output to N matches.
** -W|--width WIDTH Set display width to WIDTH columns, 0 for
** unlimited. Defaults the terminal's width.
*/
void search_cmd(void){
Blob pattern;
int i;
Blob sql = empty_blob;
Stmt q;
int iBest;
|
| ︙ | ︙ | |||
941 942 943 944 945 946 947 |
@ <ol>
}
nRow++;
@ <li><p><a href='%R%s(zUrl)'>%h(zLabel)</a>
if( fDebug ){
@ (%e(db_column_double(&q,3)), %s(db_column_text(&q,4)))
}
| | | 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 |
@ <ol>
}
nRow++;
@ <li><p><a href='%R%s(zUrl)'>%h(zLabel)</a>
if( fDebug ){
@ (%e(db_column_double(&q,3)), %s(db_column_text(&q,4)))
}
@ <br /><span class='snippet'>%z(cleanSnippet(zSnippet))</span></li>
}
db_finalize(&q);
if( nRow ){
@ </ol>
}
return nRow;
}
|
| ︙ | ︙ | |||
1632 1633 1634 1635 1636 1637 1638 | ** index search is disabled ** ** index (on|off) Turn the search index on or off ** ** enable cdtw Enable various kinds of search. c=Check-ins, ** d=Documents, t=Tickets, w=Wiki. ** | | | 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 | ** index search is disabled ** ** index (on|off) Turn the search index on or off ** ** enable cdtw Enable various kinds of search. c=Check-ins, ** d=Documents, t=Tickets, w=Wiki. ** ** disable cdtw Disable various kinds of search ** ** stemmer (on|off) Turn the Porter stemmer on or off for indexed ** search. (Unindexed search is never stemmed.) ** ** The current search settings are displayed after any changes are applied. ** Run this command with no arguments to simply see the settings. */ |
| ︙ | ︙ |
Changes to src/setup.c.
| ︙ | ︙ | |||
173 174 175 176 177 178 179 |
const char *zLogin = db_column_text(&s, 1);
const char *zCap = db_column_text(&s, 2);
const char *zDate = db_column_text(&s, 4);
@ <tr>
@ <td><a href='setup_uedit?id=%d(uid)'>%d(uid)</a>
@ <td><a href='setup_uedit?id=%d(uid)'>%h(zLogin)</a>
@ <td>%h(zCap)
| | | 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
const char *zLogin = db_column_text(&s, 1);
const char *zCap = db_column_text(&s, 2);
const char *zDate = db_column_text(&s, 4);
@ <tr>
@ <td><a href='setup_uedit?id=%d(uid)'>%d(uid)</a>
@ <td><a href='setup_uedit?id=%d(uid)'>%h(zLogin)</a>
@ <td>%h(zCap)
if( fossil_strcmp(zLogin,"anonymous")==0 ){
@ <td>All logged-in users
}else if( fossil_strcmp(zLogin,"developer")==0 ){
@ <td>Users with '<b>v</b>' capability
}else if( fossil_strcmp(zLogin,"nobody")==0 ){
@ <td>All users without login
}else if( fossil_strcmp(zLogin,"reader")==0 ){
|
| ︙ | ︙ | |||
490 491 492 493 494 495 496 |
for(i=0; zCap[i]; i++){
char c = zCap[i];
if( c>='a' && c<='z' ) oa[c&0x7f] = " checked=\"checked\"";
}
}
/* figure out inherited permissions */
| | | 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 |
for(i=0; zCap[i]; i++){
char c = zCap[i];
if( c>='a' && c<='z' ) oa[c&0x7f] = " checked=\"checked\"";
}
}
/* figure out inherited permissions */
memset((char *)inherit, 0, sizeof(inherit));
if( fossil_strcmp(zLogin, "developer") ){
char *z1, *z2;
z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='developer'");
while( z1 && *z1 ){
inherit[0x7f & *(z1++)] =
"<span class=\"ueditInheritDeveloper\"><sub>[D]</sub></span>";
}
|
| ︙ | ︙ | |||
544 545 546 547 548 549 550 |
@ <form action="%s(g.zPath)" method="post"><div>
login_insert_csrf_secret();
if( login_is_special(zLogin) ){
@ <input type="hidden" name="login" value="%s(zLogin)">
@ <input type="hidden" name="info" value="">
@ <input type="hidden" name="pw" value="*">
}
| | | 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 |
@ <form action="%s(g.zPath)" method="post"><div>
login_insert_csrf_secret();
if( login_is_special(zLogin) ){
@ <input type="hidden" name="login" value="%s(zLogin)">
@ <input type="hidden" name="info" value="">
@ <input type="hidden" name="pw" value="*">
}
@ <script>
@ function updateCapabilityString(){
@ /*
@ ** This function updates the "#usetupEditCapability" span content
@ ** with the capabilities selected by the interactive user, based
@ ** upon the state of the capability checkboxes.
@ */
@ try {
|
| ︙ | ︙ | |||
728 729 730 731 732 733 734 |
@ <td> </td>
@ <td><input type="submit" name="submit" value="Apply Changes" /></td>
@ </tr>
}
@ </table>
@ </div></form>
@ </div>
| | | 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 |
@ <td> </td>
@ <td><input type="submit" name="submit" value="Apply Changes" /></td>
@ </tr>
}
@ </table>
@ </div></form>
@ </div>
@ <script>updateCapabilityString();</script>
@ <h2>Privileges And Capabilities:</h2>
@ <ul>
if( higherUser ){
@ <li><p class="missingPriv">
@ User %h(zLogin) has Setup privileges and you only have Admin privileges
@ so you are not permitted to make changes to %h(zLogin).
@ </p></li>
|
| ︙ | ︙ | |||
1152 1153 1154 1155 1156 1157 1158 |
@ even for relatively small projects.</p>
@
@ <p>Additional parameters that control this behavior:</p>
@ <blockquote>
onoff_attribute("Enable hyperlinks for humans (as deduced from the UserAgent "
" HTTP header string)",
"auto-hyperlink-ishuman", "ahis", 0, 0);
| | | | 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 |
@ even for relatively small projects.</p>
@
@ <p>Additional parameters that control this behavior:</p>
@ <blockquote>
onoff_attribute("Enable hyperlinks for humans (as deduced from the UserAgent "
" HTTP header string)",
"auto-hyperlink-ishuman", "ahis", 0, 0);
@ <br />
onoff_attribute("Require mouse movement before enabling hyperlinks",
"auto-hyperlink-mouseover", "ahmo", 0, 0);
@ <br />
entry_attribute("Delay before enabling hyperlinks (milliseconds)", 5,
"auto-hyperlink-delay", "ah-delay", "10", 0);
@ </blockquote>
@ <p>Hyperlinks for user "nobody" are normally enabled as soon as the page
@ finishes loading. But the first check-box below can be set to require mouse
@ movement before enabling the links. One can also set a delay prior to enabling
@ links by enter a positive number of milliseconds in the entry box above.</p>
|
| ︙ | ︙ | |||
1312 1313 1314 1315 1316 1317 1318 |
@ </table>
@
@ <p><form action="%s(g.zTop)/setup_login_group" method="post"><div>
login_insert_csrf_secret();
@ To leave this login group press
@ <input type="submit" value="Leave Login Group" name="leave">
@ </form></p>
| | | 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 |
@ </table>
@
@ <p><form action="%s(g.zTop)/setup_login_group" method="post"><div>
login_insert_csrf_secret();
@ To leave this login group press
@ <input type="submit" value="Leave Login Group" name="leave">
@ </form></p>
@ <hr /><h2>Implementation Details</h2>
@ <p>The following are fields from the CONFIG table related to login-groups,
@ provided here for instructional and debugging purposes:</p>
@ <table border='1' id='configTab'>
@ <thead><tr><th>Config.Name<th>Config.Value<th>Config.mtime</tr></thead><tbody>
db_prepare(&q, "SELECT name, value, datetime(mtime,'unixepoch') FROM config"
" WHERE name GLOB 'peer-*'"
" OR name GLOB 'project-*'"
|
| ︙ | ︙ | |||
1431 1432 1433 1434 1435 1436 1437 | db_end_transaction(0); style_footer(); } /* ** WEBPAGE: setup_settings ** | | | 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 |
db_end_transaction(0);
style_footer();
}
/*
** WEBPAGE: setup_settings
**
** Change or view miscellaneous settings. Part of the
** Admin pages requiring Admin privileges.
*/
void setup_settings(void){
Setting const *pSet;
login_check_credentials();
if( !g.perm.Setup ){
|
| ︙ | ︙ | |||
2151 2152 2153 2154 2155 2156 2157 |
@ <td>Search nothing. (Disables document search).</tr>
@ </table>
@ <hr />
entry_attribute("Document Branch", 20, "doc-branch", "db", "trunk", 0);
@ <p>When searching documents, use the versions of the files found at the
@ type of the "Document Branch" branch. Recommended value: "trunk".
@ Document search is disabled if blank.
| | | | | | | | 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 |
@ <td>Search nothing. (Disables document search).</tr>
@ </table>
@ <hr />
entry_attribute("Document Branch", 20, "doc-branch", "db", "trunk", 0);
@ <p>When searching documents, use the versions of the files found at the
@ type of the "Document Branch" branch. Recommended value: "trunk".
@ Document search is disabled if blank.
@ <hr />
onoff_attribute("Search Check-in Comments", "search-ci", "sc", 0, 0);
@ <br />
onoff_attribute("Search Documents", "search-doc", "sd", 0, 0);
@ <br />
onoff_attribute("Search Tickets", "search-tkt", "st", 0, 0);
@ <br />
onoff_attribute("Search Wiki","search-wiki", "sw", 0, 0);
@ <hr />
@ <p><input type="submit" name="submit" value="Apply Changes" /></p>
@ <hr />
if( P("fts0") ){
search_drop_index();
}else if( P("fts1") ){
search_drop_index();
search_create_index();
search_fill_index();
search_update_index(search_restrict(SRCH_ALL));
|
| ︙ | ︙ |
Changes to src/sha1.c.
| ︙ | ︙ | |||
446 447 448 449 450 451 452 |
}
sqlite3_result_text(context, sha1_shared_secret(zPw, zLogin, zProjid), -1,
fossil_free);
}
/*
** COMMAND: sha1sum*
| > | | | 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 |
}
sqlite3_result_text(context, sha1_shared_secret(zPw, zLogin, zProjid), -1,
fossil_free);
}
/*
** COMMAND: sha1sum*
**
** Usage: %fossil sha1sum FILE...
**
** Compute an SHA1 checksum of all files named on the command-line.
** If a file is named "-" then take its content from standard input.
*/
void sha1sum_test(void){
int i;
Blob in;
Blob cksum;
for(i=2; i<g.argc; i++){
|
| ︙ | ︙ |
Changes to src/shell.c.
| ︙ | ︙ | |||
86 87 88 89 90 91 92 | # define shell_read_history(X) linenoiseHistoryLoad(X) # define shell_write_history(X) linenoiseHistorySave(X) # define shell_stifle_history(X) linenoiseHistorySetMaxLen(X) # define shell_readline(X) linenoise(X) #else | | | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | # define shell_read_history(X) linenoiseHistoryLoad(X) # define shell_write_history(X) linenoiseHistorySave(X) # define shell_stifle_history(X) linenoiseHistorySetMaxLen(X) # define shell_readline(X) linenoise(X) #else # define shell_read_history(X) # define shell_write_history(X) # define shell_stifle_history(X) # define SHELL_USE_LOCAL_GETLINE 1 #endif |
| ︙ | ︙ | |||
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | #define isatty(x) 1 #endif /* ctype macros that work with signed characters */ #define IsSpace(X) isspace((unsigned char)X) #define IsDigit(X) isdigit((unsigned char)X) #define ToLower(X) (char)tolower((unsigned char)X) /* On Windows, we normally run with output mode of TEXT so that \n characters ** are automatically translated into \r\n. However, this behavior needs ** to be disabled in some cases (ex: when generating CSV output and when ** rendering quoted strings that contain \n characters). The following ** routines take care of that. */ #if defined(_WIN32) || defined(WIN32) | > > > > > > > > > | | | | | | | | | 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 |
#define isatty(x) 1
#endif
/* ctype macros that work with signed characters */
#define IsSpace(X) isspace((unsigned char)X)
#define IsDigit(X) isdigit((unsigned char)X)
#define ToLower(X) (char)tolower((unsigned char)X)
#if defined(_WIN32) || defined(WIN32)
#include <windows.h>
/* string conversion routines only needed on Win32 */
extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
extern char *sqlite3_win32_mbcs_to_utf8_v2(const char *, int);
extern char *sqlite3_win32_utf8_to_mbcs_v2(const char *, int);
#endif
/* On Windows, we normally run with output mode of TEXT so that \n characters
** are automatically translated into \r\n. However, this behavior needs
** to be disabled in some cases (ex: when generating CSV output and when
** rendering quoted strings that contain \n characters). The following
** routines take care of that.
*/
#if defined(_WIN32) || defined(WIN32)
static void setBinaryMode(FILE *file, int isOutput){
if( isOutput ) fflush(file);
_setmode(_fileno(file), _O_BINARY);
}
static void setTextMode(FILE *file, int isOutput){
if( isOutput ) fflush(file);
_setmode(_fileno(file), _O_TEXT);
}
#else
# define setBinaryMode(X,Y)
# define setTextMode(X,Y)
#endif
/* True if the timer is enabled */
static int enableTimer = 0;
/* Return the current wall-clock time */
|
| ︙ | ︙ | |||
200 201 202 203 204 205 206 |
getrusage(RUSAGE_SELF, &sBegin);
iBegin = timeOfDay();
}
}
/* Return the difference of two time_structs in seconds */
static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
| | | 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
getrusage(RUSAGE_SELF, &sBegin);
iBegin = timeOfDay();
}
}
/* Return the difference of two time_structs in seconds */
static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
return (pEnd->tv_usec - pStart->tv_usec)*0.000001 +
(double)(pEnd->tv_sec - pStart->tv_sec);
}
/*
** Print the timing results.
*/
static void endTimer(void){
|
| ︙ | ︙ | |||
225 226 227 228 229 230 231 | #define BEGIN_TIMER beginTimer() #define END_TIMER endTimer() #define HAS_TIMER 1 #elif (defined(_WIN32) || defined(WIN32)) | < < | 234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
#define BEGIN_TIMER beginTimer()
#define END_TIMER endTimer()
#define HAS_TIMER 1
#elif (defined(_WIN32) || defined(WIN32))
/* Saved resource information for the beginning of an operation */
static HANDLE hProcess;
static FILETIME ftKernelBegin;
static FILETIME ftUserBegin;
static sqlite3_int64 ftWallBegin;
typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME,
LPFILETIME, LPFILETIME);
|
| ︙ | ︙ | |||
257 258 259 260 261 262 263 |
HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
if( NULL != hinstLib ){
getProcessTimesAddr =
(GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
if( NULL != getProcessTimesAddr ){
return 1;
}
| | | 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 |
HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
if( NULL != hinstLib ){
getProcessTimesAddr =
(GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
if( NULL != getProcessTimesAddr ){
return 1;
}
FreeLibrary(hinstLib);
}
}
}
return 0;
}
/*
|
| ︙ | ︙ | |||
303 304 305 306 307 308 309 | } #define BEGIN_TIMER beginTimer() #define END_TIMER endTimer() #define HAS_TIMER hasTimer() #else | | | 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 | } #define BEGIN_TIMER beginTimer() #define END_TIMER endTimer() #define HAS_TIMER hasTimer() #else #define BEGIN_TIMER #define END_TIMER #define HAS_TIMER 0 #endif /* ** Used to prevent warnings about unused parameters */ |
| ︙ | ︙ | |||
357 358 359 360 361 362 363 364 365 366 367 368 369 370 | /* ** Prompt strings. Initialized in main. Settable with ** .prompt main continue */ static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/ static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */ /* ** Write I/O traces to the following stream. */ #ifdef SQLITE_ENABLE_IOTRACE static FILE *iotrace = 0; #endif | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
/*
** Prompt strings. Initialized in main. Settable with
** .prompt main continue
*/
static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/
static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */
/*
** Render output like fprintf(). Except, if the output is going to the
** console and if this is running on a Windows machine, translate the
** output from UTF-8 into MBCS.
*/
#if defined(_WIN32) || defined(WIN32)
void utf8_printf(FILE *out, const char *zFormat, ...){
va_list ap;
va_start(ap, zFormat);
if( stdout_is_console && (out==stdout || out==stderr) ){
char *z1 = sqlite3_vmprintf(zFormat, ap);
char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0);
sqlite3_free(z1);
fputs(z2, out);
sqlite3_free(z2);
}else{
vfprintf(out, zFormat, ap);
}
va_end(ap);
}
#elif !defined(utf8_printf)
# define utf8_printf fprintf
#endif
/*
** Render output like fprintf(). This should not be used on anything that
** includes string formatting (e.g. "%s").
*/
#if !defined(raw_printf)
# define raw_printf fprintf
#endif
/*
** Write I/O traces to the following stream.
*/
#ifdef SQLITE_ENABLE_IOTRACE
static FILE *iotrace = 0;
#endif
|
| ︙ | ︙ | |||
378 379 380 381 382 383 384 |
static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
va_list ap;
char *z;
if( iotrace==0 ) return;
va_start(ap, zFormat);
z = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
| | | 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 |
static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
va_list ap;
char *z;
if( iotrace==0 ) return;
va_start(ap, zFormat);
z = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
utf8_printf(iotrace, "%s", z);
sqlite3_free(z);
}
#endif
/*
** Determines if a string is a number of not.
|
| ︙ | ︙ | |||
412 413 414 415 416 417 418 |
while( IsDigit(*z) ){ z++; }
if( realnum ) *realnum = 1;
}
return *z==0;
}
/*
| | | | 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 |
while( IsDigit(*z) ){ z++; }
if( realnum ) *realnum = 1;
}
return *z==0;
}
/*
** A global char* and an SQL function to access its current value
** from within an SQL statement. This program used to use the
** sqlite_exec_printf() API to substitue a string into an SQL statement.
** The correct way to do this with sqlite3 is to use the bind API, but
** since the shell is built around the callback paradigm it would be a lot
** of work. Instead just use this hack, which is quite harmless.
*/
static const char *zShellStatic = 0;
static void shellstaticFunc(
|
| ︙ | ︙ | |||
479 480 481 482 483 484 485 |
n--;
if( n>0 && zLine[n-1]=='\r' ) n--;
zLine[n] = 0;
break;
}
}
#if defined(_WIN32) || defined(WIN32)
| | < | | 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 |
n--;
if( n>0 && zLine[n-1]=='\r' ) n--;
zLine[n] = 0;
break;
}
}
#if defined(_WIN32) || defined(WIN32)
/* For interactive input on Windows systems, translate the
** multi-byte characterset characters into UTF-8. */
if( stdin_is_interactive ){
char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0);
if( zTrans ){
int nTrans = strlen30(zTrans)+1;
if( nTrans>nLine ){
zLine = realloc(zLine, nTrans);
if( zLine==0 ){
sqlite3_free(zTrans);
return 0;
|
| ︙ | ︙ | |||
535 536 537 538 539 540 541 542 |
zResult = shell_readline(zPrompt);
if( zResult && *zResult ) shell_add_history(zResult);
#endif
}
return zResult;
}
/*
| > < | < < < > | < < < | > | | < < < < | < < < < < < < < < < < < | | 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 |
zResult = shell_readline(zPrompt);
if( zResult && *zResult ) shell_add_history(zResult);
#endif
}
return zResult;
}
#if defined(SQLITE_ENABLE_SESSION)
/*
** State information for a single open session
*/
typedef struct OpenSession OpenSession;
struct OpenSession {
char *zName; /* Symbolic name for this session */
int nFilter; /* Number of xFilter rejection GLOB patterns */
char **azFilter; /* Array of xFilter rejection GLOB patterns */
sqlite3_session *p; /* The open session */
};
#endif
/*
** Shell output mode information from before ".explain on",
** saved so that it can be restored by ".explain off"
*/
typedef struct SavedModeInfo SavedModeInfo;
struct SavedModeInfo {
int valid; /* Is there legit data in here? */
int mode; /* Mode prior to ".explain on" */
int showHeader; /* The ".header" setting prior to ".explain on" */
|
| ︙ | ︙ | |||
621 622 623 624 625 626 627 628 629 630 631 632 633 634 | char *zFreeOnClose; /* Filename to free when closing */ const char *zVfs; /* Name of VFS to use */ sqlite3_stmt *pStmt; /* Current statement if any. */ FILE *pLog; /* Write log output here */ int *aiIndent; /* Array of indents used in MODE_Explain */ int nIndent; /* Size of array aiIndent[] */ int iIndent; /* Index of current op in aiIndent[] */ }; /* ** These are the allowed shellFlgs values */ #define SHFLG_Scratch 0x00001 /* The --scratch option is used */ #define SHFLG_Pagecache 0x00002 /* The --pagecache option is used */ | > > > > | 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 | char *zFreeOnClose; /* Filename to free when closing */ const char *zVfs; /* Name of VFS to use */ sqlite3_stmt *pStmt; /* Current statement if any. */ FILE *pLog; /* Write log output here */ int *aiIndent; /* Array of indents used in MODE_Explain */ int nIndent; /* Size of array aiIndent[] */ int iIndent; /* Index of current op in aiIndent[] */ #if defined(SQLITE_ENABLE_SESSION) int nSession; /* Number of active sessions */ OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */ #endif }; /* ** These are the allowed shellFlgs values */ #define SHFLG_Scratch 0x00001 /* The --scratch option is used */ #define SHFLG_Pagecache 0x00002 /* The --pagecache option is used */ |
| ︙ | ︙ | |||
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 |
#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
#define MODE_Html 4 /* Generate an XHTML table */
#define MODE_Insert 5 /* Generate SQL "insert" statements */
#define MODE_Tcl 6 /* Generate ANSI-C or TCL quoted elements */
#define MODE_Csv 7 /* Quote strings, numbers are plain */
#define MODE_Explain 8 /* Like MODE_Column, but do not truncate data */
#define MODE_Ascii 9 /* Use ASCII unit and record separators (0x1F/0x1E) */
static const char *modeDescr[] = {
"line",
"column",
"list",
"semi",
"html",
"insert",
"tcl",
"csv",
"explain",
"ascii",
};
/*
** These are the column/row/line separators used by the various
** import/export modes.
*/
#define SEP_Column "|"
| > > | 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 |
#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
#define MODE_Html 4 /* Generate an XHTML table */
#define MODE_Insert 5 /* Generate SQL "insert" statements */
#define MODE_Tcl 6 /* Generate ANSI-C or TCL quoted elements */
#define MODE_Csv 7 /* Quote strings, numbers are plain */
#define MODE_Explain 8 /* Like MODE_Column, but do not truncate data */
#define MODE_Ascii 9 /* Use ASCII unit and record separators (0x1F/0x1E) */
#define MODE_Pretty 10 /* Pretty-print schemas */
static const char *modeDescr[] = {
"line",
"column",
"list",
"semi",
"html",
"insert",
"tcl",
"csv",
"explain",
"ascii",
"prettyprint",
};
/*
** These are the column/row/line separators used by the various
** import/export modes.
*/
#define SEP_Column "|"
|
| ︙ | ︙ | |||
702 703 704 705 706 707 708 |
/*
** Output the given string as a quoted string using SQL quoting conventions.
*/
static void output_quoted_string(FILE *out, const char *z){
int i;
int nSingle = 0;
| | | 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 |
/*
** Output the given string as a quoted string using SQL quoting conventions.
*/
static void output_quoted_string(FILE *out, const char *z){
int i;
int nSingle = 0;
setBinaryMode(out, 1);
for(i=0; z[i]; i++){
if( z[i]=='\'' ) nSingle++;
}
if( nSingle==0 ){
utf8_printf(out,"'%s'",z);
}else{
raw_printf(out,"'");
|
| ︙ | ︙ | |||
725 726 727 728 729 730 731 |
}else{
utf8_printf(out,"%s",z);
break;
}
}
raw_printf(out,"'");
}
| | | 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 |
}else{
utf8_printf(out,"%s",z);
break;
}
}
raw_printf(out,"'");
}
setTextMode(out, 1);
}
/*
** Output the given string as a quoted according to C or TCL quoting rules.
*/
static void output_c_string(FILE *out, const char *z){
unsigned int c;
|
| ︙ | ︙ | |||
767 768 769 770 771 772 773 |
** Output the given string with characters that are special to
** HTML escaped.
*/
static void output_html_string(FILE *out, const char *z){
int i;
if( z==0 ) z = "";
while( *z ){
| | | | | | | 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 |
** Output the given string with characters that are special to
** HTML escaped.
*/
static void output_html_string(FILE *out, const char *z){
int i;
if( z==0 ) z = "";
while( *z ){
for(i=0; z[i]
&& z[i]!='<'
&& z[i]!='&'
&& z[i]!='>'
&& z[i]!='\"'
&& z[i]!='\'';
i++){}
if( i>0 ){
utf8_printf(out,"%.*s",i,z);
}
if( z[i]=='<' ){
raw_printf(out,"<");
|
| ︙ | ︙ | |||
799 800 801 802 803 804 805 |
}
/*
** If a field contains any character identified by a 1 in the following
** array, then the string must be quoted for CSV.
*/
static const char needCsvQuote[] = {
| | | | | | | | | | | | | | | | | | | | 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 |
}
/*
** If a field contains any character identified by a 1 in the following
** array, then the string must be quoted for CSV.
*/
static const char needCsvQuote[] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
/*
** Output a single term of CSV. Actually, p->colSeparator is used for
** the separator, which may or may not be a comma. p->nullValue is
** the null value. Strings are quoted if necessary. The separator
** 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{
int i;
int nSep = strlen30(p->colSeparator);
for(i=0; z[i]; i++){
if( needCsvQuote[((unsigned char*)z)[i]]
|| (z[i]==p->colSeparator[0] &&
(nSep==1 || memcmp(z, p->colSeparator, nSep)==0)) ){
i = 0;
break;
}
}
if( i==0 ){
putc('"', out);
|
| ︙ | ︙ | |||
865 866 867 868 869 870 871 872 873 874 875 876 877 878 |
static void interrupt_handler(int NotUsed){
UNUSED_PARAMETER(NotUsed);
seenInterrupt++;
if( seenInterrupt>2 ) exit(1);
if( globalDb ) sqlite3_interrupt(globalDb);
}
#endif
/*
** This is the callback routine that the shell
** invokes for each row of a query result.
*/
static int shell_callback(
void *pArg,
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
static void interrupt_handler(int NotUsed){
UNUSED_PARAMETER(NotUsed);
seenInterrupt++;
if( seenInterrupt>2 ) exit(1);
if( globalDb ) sqlite3_interrupt(globalDb);
}
#endif
/*
** When the ".auth ON" is set, the following authorizer callback is
** invoked. It always returns SQLITE_OK.
*/
static int shellAuth(
void *pClientData,
int op,
const char *zA1,
const char *zA2,
const char *zA3,
const char *zA4
){
ShellState *p = (ShellState*)pClientData;
static const char *azAction[] = { 0,
"CREATE_INDEX", "CREATE_TABLE", "CREATE_TEMP_INDEX",
"CREATE_TEMP_TABLE", "CREATE_TEMP_TRIGGER", "CREATE_TEMP_VIEW",
"CREATE_TRIGGER", "CREATE_VIEW", "DELETE",
"DROP_INDEX", "DROP_TABLE", "DROP_TEMP_INDEX",
"DROP_TEMP_TABLE", "DROP_TEMP_TRIGGER", "DROP_TEMP_VIEW",
"DROP_TRIGGER", "DROP_VIEW", "INSERT",
"PRAGMA", "READ", "SELECT",
"TRANSACTION", "UPDATE", "ATTACH",
"DETACH", "ALTER_TABLE", "REINDEX",
"ANALYZE", "CREATE_VTABLE", "DROP_VTABLE",
"FUNCTION", "SAVEPOINT", "RECURSIVE"
};
int i;
const char *az[4];
az[0] = zA1;
az[1] = zA2;
az[2] = zA3;
az[3] = zA4;
raw_printf(p->out, "authorizer: %s", azAction[op]);
for(i=0; i<4; i++){
raw_printf(p->out, " ");
if( az[i] ){
output_c_string(p->out, az[i]);
}else{
raw_printf(p->out, "NULL");
}
}
raw_printf(p->out, "\n");
return SQLITE_OK;
}
/*
** This is the callback routine that the shell
** invokes for each row of a query result.
*/
static int shell_callback(
void *pArg,
|
| ︙ | ︙ | |||
982 983 984 985 986 987 988 |
utf8_printf(p->out,"%-*.*s%s",w,w,
azArg[i] ? azArg[i] : p->nullValue,
i==nArg-1 ? rowSep : " ");
}
}
break;
}
| | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < | 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 |
utf8_printf(p->out,"%-*.*s%s",w,w,
azArg[i] ? azArg[i] : p->nullValue,
i==nArg-1 ? rowSep : " ");
}
}
break;
}
case MODE_Semi: { /* .schema and .fullschema output */
utf8_printf(p->out, "%s;\n", azArg[0]);
break;
}
case MODE_Pretty: { /* .schema and .fullschema with --indent */
char *z;
int j;
int nParen = 0;
char cEnd = 0;
char c;
int nLine = 0;
assert( nArg==1 );
if( azArg[0]==0 ) break;
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( IsSpace(z[j-1]) || z[j-1]=='(' ) continue;
}else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){
j--;
}
z[j++] = c;
}
while( j>0 && IsSpace(z[j-1]) ){ j--; }
z[j] = 0;
if( strlen30(z)>=79 ){
for(i=j=0; (c = z[i])!=0; i++){
if( c==cEnd ){
cEnd = 0;
}else if( c=='"' || c=='\'' || c=='`' ){
cEnd = c;
}else if( c=='[' ){
cEnd = ']';
}else if( c=='(' ){
nParen++;
}else if( c==')' ){
nParen--;
if( nLine>0 && nParen==0 && j>0 ){
utf8_printf(p->out, "%.*s\n", j, z);
j = 0;
}
}
z[j++] = c;
if( nParen==1 && (c=='(' || c==',' || c=='\n') ){
if( c=='\n' ) j--;
utf8_printf(p->out, "%.*s\n ", j, z);
j = 0;
nLine++;
while( IsSpace(z[i+1]) ){ i++; }
}
}
z[j] = 0;
}
utf8_printf(p->out, "%s;\n", z);
sqlite3_free(z);
break;
}
case MODE_List: {
if( p->cnt++==0 && p->showHeader ){
for(i=0; i<nArg; i++){
utf8_printf(p->out,"%s%s",azCol[i],
i==nArg-1 ? p->rowSeparator : p->colSeparator);
}
}
if( azArg==0 ) break;
for(i=0; i<nArg; i++){
char *z = azArg[i];
if( z==0 ) z = p->nullValue;
utf8_printf(p->out, "%s", z);
if( i<nArg-1 ){
utf8_printf(p->out, "%s", p->colSeparator);
}else{
utf8_printf(p->out, "%s", p->rowSeparator);
}
}
break;
}
case MODE_Html: {
|
| ︙ | ︙ | |||
1042 1043 1044 1045 1046 1047 1048 |
output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
}
utf8_printf(p->out, "%s", p->rowSeparator);
break;
}
case MODE_Csv: {
| | | | 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 |
output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
}
utf8_printf(p->out, "%s", p->rowSeparator);
break;
}
case MODE_Csv: {
setBinaryMode(p->out, 1);
if( p->cnt++==0 && p->showHeader ){
for(i=0; i<nArg; i++){
output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
}
utf8_printf(p->out, "%s", p->rowSeparator);
}
if( nArg>0 ){
for(i=0; i<nArg; i++){
output_csv(p, azArg[i], i<nArg-1);
}
utf8_printf(p->out, "%s", p->rowSeparator);
}
setTextMode(p->out, 1);
break;
}
case MODE_Insert: {
p->cnt++;
if( azArg==0 ) break;
utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
if( p->showHeader ){
|
| ︙ | ︙ | |||
1168 1169 1170 1171 1172 1173 1174 | } /* zIn is either a pointer to a NULL-terminated string in memory obtained ** from malloc(), or a NULL pointer. The string pointed to by zAppend is ** added to zIn, and the result returned in memory obtained from malloc(). ** zIn, if it was not NULL, is freed. ** | | | 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 |
}
/* zIn is either a pointer to a NULL-terminated string in memory obtained
** from malloc(), or a NULL pointer. The string pointed to by zAppend is
** added to zIn, and the result returned in memory obtained from malloc().
** zIn, if it was not NULL, is freed.
**
** If the third argument, quote, is not '\0', then it is used as a
** quote character for zAppend.
*/
static char *appendText(char *zIn, char const *zAppend, char quote){
int len;
int i;
int nAppend = strlen30(zAppend);
int nIn = (zIn?strlen30(zIn):0);
|
| ︙ | ︙ | |||
1215 1216 1217 1218 1219 1220 1221 | /* ** 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. ** ** If the number of columns is 1 and that column contains text "--" | | | 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 | /* ** 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. ** ** If the number of columns is 1 and that column contains text "--" ** then write the semicolon on a separate line. That way, if a ** "--" comment occurs at the end of the statement, the comment ** won't consume the semicolon terminator. */ static int run_table_dump_query( ShellState *p, /* Query context */ const char *zSelect, /* SELECT statement to extract content */ const char *zFirstRow /* Print before first row, if not NULL */ |
| ︙ | ︙ | |||
1245 1246 1247 1248 1249 1250 1251 |
while( rc==SQLITE_ROW ){
if( zFirstRow ){
utf8_printf(p->out, "%s", zFirstRow);
zFirstRow = 0;
}
z = (const char*)sqlite3_column_text(pSelect, 0);
utf8_printf(p->out, "%s", z);
| | | | 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 |
while( rc==SQLITE_ROW ){
if( zFirstRow ){
utf8_printf(p->out, "%s", zFirstRow);
zFirstRow = 0;
}
z = (const char*)sqlite3_column_text(pSelect, 0);
utf8_printf(p->out, "%s", z);
for(i=1; i<nResult; i++){
utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i));
}
if( z==0 ) z = "";
while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
if( z[0] ){
raw_printf(p->out, "\n;\n");
}else{
raw_printf(p->out, ";\n");
}
rc = sqlite3_step(pSelect);
}
rc = sqlite3_finalize(pSelect);
if( rc!=SQLITE_OK ){
utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
sqlite3_errmsg(p->db));
if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
|
| ︙ | ︙ | |||
1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 |
int nErrMsg = 1+strlen30(sqlite3_errmsg(db));
char *zErrMsg = sqlite3_malloc64(nErrMsg);
if( zErrMsg ){
memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg);
}
return zErrMsg;
}
/*
** Display memory stats.
*/
static int display_stats(
sqlite3 *db, /* Database to query */
ShellState *pArg, /* Pointer to ShellState */
int bReset /* True to reset the stats */
){
int iCur;
int iHiwtr;
if( pArg && pArg->out ){
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 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 |
int nErrMsg = 1+strlen30(sqlite3_errmsg(db));
char *zErrMsg = sqlite3_malloc64(nErrMsg);
if( zErrMsg ){
memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg);
}
return zErrMsg;
}
#ifdef __linux__
/*
** Attempt to display I/O stats on Linux using /proc/PID/io
*/
static void displayLinuxIoStats(FILE *out){
FILE *in;
char z[200];
sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
in = fopen(z, "rb");
if( in==0 ) return;
while( fgets(z, sizeof(z), in)!=0 ){
static const struct {
const char *zPattern;
const char *zDesc;
} aTrans[] = {
{ "rchar: ", "Bytes received by read():" },
{ "wchar: ", "Bytes sent to write():" },
{ "syscr: ", "Read() system calls:" },
{ "syscw: ", "Write() system calls:" },
{ "read_bytes: ", "Bytes read from storage:" },
{ "write_bytes: ", "Bytes written to storage:" },
{ "cancelled_write_bytes: ", "Cancelled write bytes:" },
};
int i;
for(i=0; i<ArraySize(aTrans); i++){
int n = (int)strlen(aTrans[i].zPattern);
if( strncmp(aTrans[i].zPattern, z, n)==0 ){
raw_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
break;
}
}
}
fclose(in);
}
#endif
/*
** Display memory stats.
*/
static int display_stats(
sqlite3 *db, /* Database to query */
ShellState *pArg, /* Pointer to ShellState */
int bReset /* True to reset the stats */
){
int iCur;
int iHiwtr;
if( pArg && pArg->out ){
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset);
raw_printf(pArg->out,
"Memory Used: %d (max %d) bytes\n",
iCur, iHiwtr);
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset);
|
| ︙ | ︙ | |||
1376 1377 1378 1379 1380 1381 1382 |
raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n",
iCur);
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
raw_printf(pArg->out, "Page cache hits: %d\n", iCur);
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
| | | | | > > > > | 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 |
raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n",
iCur);
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
raw_printf(pArg->out, "Page cache hits: %d\n", iCur);
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
raw_printf(pArg->out, "Page cache misses: %d\n", iCur);
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
raw_printf(pArg->out, "Page cache writes: %d\n", iCur);
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n",
iCur);
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 && pArg->out && db && 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);
}
#ifdef __linux__
displayLinuxIoStats(pArg->out);
#endif
/* Do not remove this machine readable comment: extra-stats-output-here */
return 0;
}
/*
|
| ︙ | ︙ | |||
1445 1446 1447 1448 1449 1450 1451 |
}
n++;
sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain);
rEstLoop *= rEst;
| | | 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 |
}
n++;
sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain);
rEstLoop *= rEst;
raw_printf(pArg->out,
" nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n",
nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst
);
}
}
raw_printf(pArg->out, "---------------------------\n");
#endif
|
| ︙ | ︙ | |||
1472 1473 1474 1475 1476 1477 1478 | } return 0; } /* ** If compiled statement pSql appears to be an EXPLAIN statement, allocate ** and populate the ShellState.aiIndent[] array with the number of | | | 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 | } return 0; } /* ** If compiled statement pSql appears to be an EXPLAIN statement, allocate ** and populate the ShellState.aiIndent[] array with the number of ** spaces each opcode should be indented before it is output. ** ** The indenting rules are: ** ** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent ** all opcodes that occur between the p2 jump destination and the opcode ** itself by 2 spaces. ** |
| ︙ | ︙ | |||
1557 1558 1559 1560 1561 1562 1563 |
if( str_in_array(zOp, azNext) ){
for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
}
if( str_in_array(zOp, azGoto) && p2op<p->nIndent
&& (abYield[p2op] || sqlite3_column_int(pSql, 2))
){
| | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | > > > < | > > | < > > > > > > > > > > > > > > | | < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | 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 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 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 1970 1971 1972 1973 1974 1975 1976 |
if( str_in_array(zOp, azNext) ){
for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
}
if( str_in_array(zOp, azGoto) && p2op<p->nIndent
&& (abYield[p2op] || sqlite3_column_int(pSql, 2))
){
for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
}
}
p->iIndent = 0;
sqlite3_free(abYield);
sqlite3_reset(pSql);
}
/*
** Free the array allocated by explain_data_prepare().
*/
static void explain_data_delete(ShellState *p){
sqlite3_free(p->aiIndent);
p->aiIndent = 0;
p->nIndent = 0;
p->iIndent = 0;
}
/*
** Disable and restore .wheretrace and .selecttrace settings.
*/
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
extern int sqlite3SelectTrace;
static int savedSelectTrace;
#endif
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
extern int sqlite3WhereTrace;
static int savedWhereTrace;
#endif
static void disable_debug_trace_modes(void){
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
savedSelectTrace = sqlite3SelectTrace;
sqlite3SelectTrace = 0;
#endif
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
savedWhereTrace = sqlite3WhereTrace;
sqlite3WhereTrace = 0;
#endif
}
static void restore_debug_trace_modes(void){
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
sqlite3SelectTrace = savedSelectTrace;
#endif
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
sqlite3WhereTrace = savedWhereTrace;
#endif
}
/*
** Run a prepared statement
*/
static void exec_prepared_stmt(
ShellState *pArg, /* Pointer to ShellState */
sqlite3_stmt *pStmt, /* Statment to run */
int (*xCallback)(void*,int,char**,char**,int*) /* Callback function */
){
int rc;
/* perform the first step. this will tell us if we
** have a result set or not and how wide it is.
*/
rc = sqlite3_step(pStmt);
/* if we have a result set... */
if( SQLITE_ROW == rc ){
/* if we have a callback... */
if( xCallback ){
/* allocate space for col name ptr, value ptr, and type */
int nCol = sqlite3_column_count(pStmt);
void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
if( !pData ){
rc = SQLITE_NOMEM;
}else{
char **azCols = (char **)pData; /* Names of result columns */
char **azVals = &azCols[nCol]; /* Results */
int *aiTypes = (int *)&azVals[nCol]; /* Result types */
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);
if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
azVals[i] = "";
}else{
azVals[i] = (char*)sqlite3_column_text(pStmt, i);
}
if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
rc = SQLITE_NOMEM;
break; /* from for */
}
} /* end for */
/* if data and types extracted successfully... */
if( SQLITE_ROW == rc ){
/* call the supplied callback with the result row data */
if( xCallback(pArg, nCol, azVals, azCols, aiTypes) ){
rc = SQLITE_ABORT;
}else{
rc = sqlite3_step(pStmt);
}
}
} while( SQLITE_ROW == rc );
sqlite3_free(pData);
}
}else{
do{
rc = sqlite3_step(pStmt);
} while( rc == SQLITE_ROW );
}
}
}
/*
** Execute a statement or set of statements. Print
** any result rows/columns depending on the current mode
** set via the supplied callback.
**
** This is very similar to SQLite's built-in sqlite3_exec()
** function except it takes a slightly different callback
** and callback data argument.
*/
static int shell_exec(
sqlite3 *db, /* An open database */
const char *zSql, /* SQL to be evaluated */
int (*xCallback)(void*,int,char**,char**,int*), /* Callback function */
/* (not the same as sqlite3_exec) */
ShellState *pArg, /* Pointer to ShellState */
char **pzErrMsg /* Error msg written here */
){
sqlite3_stmt *pStmt = NULL; /* Statement to execute. */
int rc = SQLITE_OK; /* Return Code */
int rc2;
const char *zLeftover; /* Tail of unprocessed SQL */
if( pzErrMsg ){
*pzErrMsg = NULL;
}
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);
}
}else{
if( !pStmt ){
/* this happens for a comment or white-space */
zSql = zLeftover;
while( IsSpace(zSql[0]) ) zSql++;
continue;
}
zStmtSql = sqlite3_sql(pStmt);
while( IsSpace(zStmtSql[0]) ) zStmtSql++;
/* save off the prepared statment handle and reset row count */
if( pArg ){
pArg->pStmt = pStmt;
pArg->cnt = 0;
}
/* echo the sql statement if echo on */
if( pArg && pArg->echoOn ){
utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
}
/* Show the EXPLAIN QUERY PLAN if .eqp is on */
if( pArg && pArg->autoEQP && sqlite3_strlike("EXPLAIN%",zStmtSql,0)!=0 ){
sqlite3_stmt *pExplain;
char *zEQP;
disable_debug_trace_modes();
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 ){
raw_printf(pArg->out,"--EQP-- %d,",sqlite3_column_int(pExplain, 0));
raw_printf(pArg->out,"%d,", sqlite3_column_int(pExplain, 1));
raw_printf(pArg->out,"%d,", sqlite3_column_int(pExplain, 2));
utf8_printf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3));
}
}
sqlite3_finalize(pExplain);
sqlite3_free(zEQP);
if( pArg->autoEQP>=2 ){
/* 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, xCallback);
explain_data_delete(pArg);
}
sqlite3_finalize(pExplain);
sqlite3_free(zEQP);
}
restore_debug_trace_modes();
}
if( pArg ){
pArg->cMode = pArg->mode;
if( pArg->autoExplain
&& sqlite3_column_count(pStmt)==8
&& sqlite3_strlike("EXPLAIN%", zStmtSql,0)==0
){
pArg->cMode = MODE_Explain;
}
/* If the shell is currently in ".explain" mode, gather the extra
** data required to add indents to the output.*/
if( pArg->cMode==MODE_Explain ){
explain_data_prepare(pArg, pStmt);
}
}
exec_prepared_stmt(pArg, pStmt, xCallback);
explain_data_delete(pArg);
/* print usage stats if stats on */
if( pArg && pArg->statsOn ){
display_stats(db, pArg, 0);
}
/* print loop-counters if required */
if( pArg && pArg->scanstatsOn ){
display_scanstats(db, pArg);
}
/* Finalize the statement just executed. If this fails, save a
** copy of the error message. Otherwise, set zSql to point to the
** 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++;
|
| ︙ | ︙ | |||
1773 1774 1775 1776 1777 1778 1779 | ShellState *p = (ShellState *)pArg; UNUSED_PARAMETER(azCol); if( nArg!=3 ) return 1; zTable = azArg[0]; zType = azArg[1]; zSql = azArg[2]; | | | 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 |
ShellState *p = (ShellState *)pArg;
UNUSED_PARAMETER(azCol);
if( nArg!=3 ) return 1;
zTable = azArg[0];
zType = azArg[1];
zSql = azArg[2];
if( strcmp(zTable, "sqlite_sequence")==0 ){
zPrepStmt = "DELETE FROM sqlite_sequence;\n";
}else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
raw_printf(p->out, "ANALYZE sqlite_master;\n");
}else if( strncmp(zTable, "sqlite_", 7)==0 ){
return 0;
}else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
|
| ︙ | ︙ | |||
1803 1804 1805 1806 1807 1808 1809 |
if( strcmp(zType, "table")==0 ){
sqlite3_stmt *pTableInfo = 0;
char *zSelect = 0;
char *zTableInfo = 0;
char *zTmp = 0;
int nRow = 0;
| | | 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 |
if( strcmp(zType, "table")==0 ){
sqlite3_stmt *pTableInfo = 0;
char *zSelect = 0;
char *zTableInfo = 0;
char *zTmp = 0;
int nRow = 0;
zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0);
zTableInfo = appendText(zTableInfo, zTable, '"');
zTableInfo = appendText(zTableInfo, ");", 0);
rc = sqlite3_prepare_v2(p->db, zTableInfo, -1, &pTableInfo, 0);
free(zTableInfo);
if( rc!=SQLITE_OK || !pTableInfo ){
|
| ︙ | ︙ | |||
1862 1863 1864 1865 1866 1867 1868 | ** Run zQuery. Use dump_callback() as the callback routine so that ** the contents of the query are output as SQL statements. ** ** If we get a SQLITE_CORRUPT error, rerun the query after appending ** "ORDER BY rowid DESC" to the end. */ static int run_schema_dump_query( | | | 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 |
** Run zQuery. Use dump_callback() as the callback routine so that
** the contents of the query are output as SQL statements.
**
** If we get a SQLITE_CORRUPT error, rerun the query after appending
** "ORDER BY rowid DESC" to the end.
*/
static int run_schema_dump_query(
ShellState *p,
const char *zQuery
){
int rc;
char *zErr = 0;
rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
if( rc==SQLITE_CORRUPT ){
char *zQ2;
|
| ︙ | ︙ | |||
1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 | return rc; } /* ** Text of a help message */ static char zHelp[] = ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n" ".bail on|off Stop after hitting an error. Default OFF\n" ".binary on|off Turn binary output on or off. Default OFF\n" ".changes on|off Show number of rows changed by SQL\n" ".clone NEWDB Clone data into NEWDB from the existing database\n" ".databases List names and files of attached databases\n" ".dbinfo ?DB? Show status information about the database\n" ".dump ?TABLE? ... Dump the database in an SQL text format\n" " If TABLE specified, only dump tables matching\n" " LIKE pattern TABLE.\n" ".echo on|off Turn command echo on or off\n" | > | | | 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 | return rc; } /* ** Text of a help message */ static char zHelp[] = ".auth ON|OFF Show authorizer callbacks\n" ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n" ".bail on|off Stop after hitting an error. Default OFF\n" ".binary on|off Turn binary output on or off. Default OFF\n" ".changes on|off Show number of rows changed by SQL\n" ".clone NEWDB Clone data into NEWDB from the existing database\n" ".databases List names and files of attached databases\n" ".dbinfo ?DB? Show status information about the database\n" ".dump ?TABLE? ... Dump the database in an SQL text format\n" " If TABLE specified, only dump tables matching\n" " LIKE pattern TABLE.\n" ".echo on|off Turn command echo on or off\n" ".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN\n" ".exit Exit this program\n" ".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic\n" ".fullschema ?--indent? Show schema and the content of sqlite_stat tables\n" ".headers on|off Turn display of headers on or off\n" ".help Show this message\n" ".import FILE TABLE Import data from FILE into TABLE\n" ".indexes ?TABLE? Show names of all indexes\n" " If TABLE specified, only show indexes for tables\n" " matching LIKE pattern TABLE.\n" #ifdef SQLITE_ENABLE_IOTRACE |
| ︙ | ︙ | |||
1946 1947 1948 1949 1950 1951 1952 | ".print STRING... Print literal STRING\n" ".prompt MAIN CONTINUE Replace the standard prompts\n" ".quit Exit this program\n" ".read FILENAME Execute SQL in FILENAME\n" ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n" ".save FILE Write in-memory database into FILE\n" ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off\n" | | < | > > > | > > > > > > > > > > > > > > > > > > > > > > > > | 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 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 |
".print STRING... Print literal STRING\n"
".prompt MAIN CONTINUE Replace the standard prompts\n"
".quit Exit this program\n"
".read FILENAME Execute SQL in FILENAME\n"
".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n"
".save FILE Write in-memory database into FILE\n"
".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off\n"
".schema ?PATTERN? Show the CREATE statements matching PATTERN\n"
" Add --indent for pretty-printing\n"
".separator COL ?ROW? Change the column separator and optionally the row\n"
" separator for both the output mode and .import\n"
#if defined(SQLITE_ENABLE_SESSION)
".session CMD ... Create or control sessions\n"
#endif
".shell CMD ARGS... Run CMD ARGS... in a system shell\n"
".show Show the current values for various settings\n"
".stats ?on|off? Show stats or turn stats on or off\n"
".system CMD ARGS... Run CMD ARGS... in a system shell\n"
".tables ?TABLE? List names of tables\n"
" If TABLE specified, only list tables matching\n"
" LIKE pattern TABLE.\n"
".timeout MS Try opening locked tables for MS milliseconds\n"
".timer on|off Turn SQL timer on or off\n"
".trace FILE|off Output each SQL statement as it is run\n"
".vfsinfo ?AUX? Information about the top-level VFS\n"
".vfslist List all available VFSes\n"
".vfsname ?AUX? Print the name of the VFS stack\n"
".width NUM1 NUM2 ... Set column widths for \"column\" mode\n"
" Negative values right-justify\n"
;
#if defined(SQLITE_ENABLE_SESSION)
/*
** Print help information for the ".sessions" command
*/
void session_help(ShellState *p){
raw_printf(p->out,
".session ?NAME? SUBCOMMAND ?ARGS...?\n"
"If ?NAME? is omitted, the first defined session is used.\n"
"Subcommands:\n"
" attach TABLE Attach TABLE\n"
" changeset FILE Write a changeset into FILE\n"
" close Close one session\n"
" enable ?BOOLEAN? Set or query the enable bit\n"
" filter GLOB... Reject tables matching GLOBs\n"
" indirect ?BOOLEAN? Mark or query the indirect status\n"
" isempty Query whether the session is empty\n"
" list List currently open session names\n"
" open DB NAME Open a new session on DB\n"
" patchset FILE Write a patchset into FILE\n"
);
}
#endif
/* Forward reference */
static int process_input(ShellState *p, FILE *in);
/*
** Implementation of the "readfile(X)" SQL function. The entire content
** of the file named X is read and returned as a BLOB. NULL is returned
** if the file does not exist or is unreadable.
|
| ︙ | ︙ | |||
2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 |
}else{
rc = fwrite(z, 1, sqlite3_value_bytes(argv[1]), out);
}
fclose(out);
sqlite3_result_int64(context, rc);
}
/*
** Make sure the database is open. If it is not, then open it. If
** the database fails to open, print an error message and exit.
*/
static void open_db(ShellState *p, int keepAlive){
if( p->db==0 ){
sqlite3_initialize();
sqlite3_open(p->zDbFilename, &p->db);
globalDb = p->db;
if( p->db && sqlite3_errcode(p->db)==SQLITE_OK ){
sqlite3_create_function(p->db, "shellstatic", 0, SQLITE_UTF8, 0,
shellstaticFunc, 0, 0);
}
if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 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 |
}else{
rc = fwrite(z, 1, sqlite3_value_bytes(argv[1]), out);
}
fclose(out);
sqlite3_result_int64(context, rc);
}
#if defined(SQLITE_ENABLE_SESSION)
/*
** Close a single OpenSession object and release all of its associated
** resources.
*/
static void session_close(OpenSession *pSession){
int i;
sqlite3session_delete(pSession->p);
sqlite3_free(pSession->zName);
for(i=0; i<pSession->nFilter; i++){
sqlite3_free(pSession->azFilter[i]);
}
sqlite3_free(pSession->azFilter);
memset(pSession, 0, sizeof(OpenSession));
}
#endif
/*
** Close all OpenSession objects and release all associated resources.
*/
#if defined(SQLITE_ENABLE_SESSION)
static void session_close_all(ShellState *p){
int i;
for(i=0; i<p->nSession; i++){
session_close(&p->aSession[i]);
}
p->nSession = 0;
}
#else
# define session_close_all(X)
#endif
/*
** Implementation of the xFilter function for an open session. Omit
** any tables named by ".session filter" but let all other table through.
*/
#if defined(SQLITE_ENABLE_SESSION)
static int session_filter(void *pCtx, const char *zTab){
OpenSession *pSession = (OpenSession*)pCtx;
int i;
for(i=0; i<pSession->nFilter; i++){
if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
}
return 1;
}
#endif
/*
** Make sure the database is open. If it is not, then open it. If
** the database fails to open, print an error message and exit.
*/
static void open_db(ShellState *p, int keepAlive){
if( p->db==0 ){
sqlite3_initialize();
sqlite3_open(p->zDbFilename, &p->db);
globalDb = p->db;
if( p->db && sqlite3_errcode(p->db)==SQLITE_OK ){
sqlite3_create_function(p->db, "shellstatic", 0, SQLITE_UTF8, 0,
shellstaticFunc, 0, 0);
}
if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
p->zDbFilename, sqlite3_errmsg(p->db));
if( keepAlive ) return;
exit(1);
}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
sqlite3_enable_load_extension(p->db, 1);
#endif
|
| ︙ | ︙ | |||
2211 2212 2213 2214 2215 2216 2217 |
*/
static void output_file_close(FILE *f){
if( f && f!=stdout && f!=stderr ) fclose(f);
}
/*
** Try to open an output file. The names "stdout" and "stderr" are
| | | 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 |
*/
static void output_file_close(FILE *f){
if( f && f!=stdout && f!=stderr ) fclose(f);
}
/*
** Try to open an output file. The names "stdout" and "stderr" are
** recognized and do the right thing. NULL is returned if the output
** filename is "off".
*/
static FILE *output_file_open(const char *zFile){
FILE *f;
if( strcmp(zFile,"stdout")==0 ){
f = stdout;
}else if( strcmp(zFile, "stderr")==0 ){
|
| ︙ | ︙ | |||
2234 2235 2236 2237 2238 2239 2240 | } return f; } /* ** A routine for handling output from sqlite3_trace(). */ | | > > > > > > > > > | 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 |
}
return f;
}
/*
** A routine for handling output from sqlite3_trace().
*/
static int sql_trace_callback(
unsigned mType,
void *pArg,
void *pP,
void *pX
){
FILE *f = (FILE*)pArg;
UNUSED_PARAMETER(mType);
UNUSED_PARAMETER(pP);
if( f ){
const char *z = (const char*)pX;
int i = (int)strlen(z);
while( i>0 && z[i-1]==';' ){ i--; }
utf8_printf(f, "%.*s;\n", i, z);
}
return 0;
}
/*
** A no-op routine that runs with the ".breakpoint" doc-command. This is
** a useful spot to set a debugger breakpoint.
*/
static void test_breakpoint(void){
|
| ︙ | ︙ | |||
2400 2401 2402 2403 2404 2405 2406 |
** work for WITHOUT ROWID tables.
*/
static void tryToCloneData(
ShellState *p,
sqlite3 *newDb,
const char *zTable
){
| | | 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 |
** work for WITHOUT ROWID tables.
*/
static void tryToCloneData(
ShellState *p,
sqlite3 *newDb,
const char *zTable
){
sqlite3_stmt *pQuery = 0;
sqlite3_stmt *pInsert = 0;
char *zQuery = 0;
char *zInsert = 0;
int rc;
int i, j, n;
int nTable = (int)strlen(zTable);
int k = 0;
|
| ︙ | ︙ | |||
2637 2638 2639 2640 2641 2642 2643 | sqlite3_finalize(pStmt); return res; } /* ** Convert a 2-byte or 4-byte big-endian integer into a native integer */ | | | | 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 |
sqlite3_finalize(pStmt);
return res;
}
/*
** Convert a 2-byte or 4-byte big-endian integer into a native integer
*/
static unsigned int get2byteInt(unsigned char *a){
return (a[0]<<8) + a[1];
}
static unsigned int get4byteInt(unsigned char *a){
return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
}
/*
** Implementation of the ".info" command.
**
** Return 1 on error, 2 to exit, and 0 otherwise.
|
| ︙ | ︙ | |||
2704 2705 2706 2707 2708 2709 2710 |
utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
for(i=0; i<ArraySize(aField); i++){
int ofst = aField[i].ofst;
unsigned int val = get4byteInt(aHdr + ofst);
utf8_printf(p->out, "%-20s %u", aField[i].zName, val);
switch( ofst ){
case 56: {
| | | | | 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 |
utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
for(i=0; i<ArraySize(aField); i++){
int ofst = aField[i].ofst;
unsigned int val = get4byteInt(aHdr + ofst);
utf8_printf(p->out, "%-20s %u", aField[i].zName, val);
switch( ofst ){
case 56: {
if( val==1 ) raw_printf(p->out, " (utf8)");
if( val==2 ) raw_printf(p->out, " (utf16le)");
if( val==3 ) raw_printf(p->out, " (utf16be)");
}
}
raw_printf(p->out, "\n");
}
if( zDb==0 ){
zSchemaTab = sqlite3_mprintf("main.sqlite_master");
}else if( strcmp(zDb,"temp")==0 ){
|
| ︙ | ︙ | |||
2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 |
/*
** Print an out-of-memory message to stderr and return 1.
*/
static int shellNomemError(void){
raw_printf(stderr, "Error: out of memory\n");
return 1;
}
/*
** If an input line begins with "." then invoke this routine to
** process that line.
**
** Return 1 on error, 2 to exit, and 0 otherwise.
*/
| > > > > > > > > > > > | 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 |
/*
** Print an out-of-memory message to stderr and return 1.
*/
static int shellNomemError(void){
raw_printf(stderr, "Error: out of memory\n");
return 1;
}
/*
** Compare the string as a command-line option with either one or two
** initial "-" characters.
*/
static int optionMatch(const char *zStr, const char *zOpt){
if( zStr[0]!='-' ) return 0;
zStr++;
if( zStr[0]=='-' ) zStr++;
return strcmp(zStr, zOpt)==0;
}
/*
** If an input line begins with "." then invoke this routine to
** process that line.
**
** Return 1 on error, 2 to exit, and 0 otherwise.
*/
|
| ︙ | ︙ | |||
2766 2767 2768 2769 2770 2771 2772 |
*/
while( zLine[h] && nArg<ArraySize(azArg) ){
while( IsSpace(zLine[h]) ){ h++; }
if( zLine[h]==0 ) break;
if( zLine[h]=='\'' || zLine[h]=='"' ){
int delim = zLine[h++];
azArg[nArg++] = &zLine[h];
| | | > > > > > > > > > > > > > > > | 3091 3092 3093 3094 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 |
*/
while( zLine[h] && nArg<ArraySize(azArg) ){
while( IsSpace(zLine[h]) ){ h++; }
if( zLine[h]==0 ) break;
if( zLine[h]=='\'' || zLine[h]=='"' ){
int delim = zLine[h++];
azArg[nArg++] = &zLine[h];
while( zLine[h] && zLine[h]!=delim ){
if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
h++;
}
if( zLine[h]==delim ){
zLine[h++] = 0;
}
if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
}else{
azArg[nArg++] = &zLine[h];
while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
if( zLine[h] ) zLine[h++] = 0;
resolve_backslashes(azArg[nArg-1]);
}
}
/* Process the input line.
*/
if( nArg==0 ) return 0; /* no tokens, no error */
n = strlen30(azArg[0]);
c = azArg[0][0];
if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){
if( nArg!=2 ){
raw_printf(stderr, "Usage: .auth ON|OFF\n");
rc = 1;
goto meta_command_exit;
}
open_db(p, 0);
if( booleanValue(azArg[1]) ){
sqlite3_set_authorizer(p->db, shellAuth, p);
}else{
sqlite3_set_authorizer(p->db, 0, 0);
}
}else
if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
|| (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
){
const char *zDestFile = 0;
const char *zDb = 0;
sqlite3 *pDest;
sqlite3_backup *pBackup;
|
| ︙ | ︙ | |||
2855 2856 2857 2858 2859 2860 2861 |
rc = 1;
}
}else
if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
if( nArg==2 ){
if( booleanValue(azArg[1]) ){
| | | | 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 |
rc = 1;
}
}else
if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
if( nArg==2 ){
if( booleanValue(azArg[1]) ){
setBinaryMode(p->out, 1);
}else{
setTextMode(p->out, 1);
}
}else{
raw_printf(stderr, "Usage: .binary on|off\n");
rc = 1;
}
}else
|
| ︙ | ︙ | |||
2929 2930 2931 2932 2933 2934 2935 |
}
raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
raw_printf(p->out, "BEGIN TRANSACTION;\n");
p->writableSchema = 0;
sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
p->nErr = 0;
if( nArg==1 ){
| | | | 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 |
}
raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
raw_printf(p->out, "BEGIN TRANSACTION;\n");
p->writableSchema = 0;
sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
p->nErr = 0;
if( nArg==1 ){
run_schema_dump_query(p,
"SELECT name, type, sql FROM sqlite_master "
"WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'"
);
run_schema_dump_query(p,
"SELECT name, type, sql FROM sqlite_master "
"WHERE name=='sqlite_sequence'"
);
run_table_dump_query(p,
"SELECT sql FROM sqlite_master "
"WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0
);
|
| ︙ | ︙ | |||
2978 2979 2980 2981 2982 2983 2984 |
raw_printf(stderr, "Usage: .echo on|off\n");
rc = 1;
}
}else
if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
if( nArg==2 ){
| > > > | > | | | 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 |
raw_printf(stderr, "Usage: .echo on|off\n");
rc = 1;
}
}else
if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
if( nArg==2 ){
if( strcmp(azArg[1],"full")==0 ){
p->autoEQP = 2;
}else{
p->autoEQP = booleanValue(azArg[1]);
}
}else{
raw_printf(stderr, "Usage: .eqp on|off|full\n");
rc = 1;
}
}else
if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
rc = 2;
}else
|
| ︙ | ︙ | |||
3016 3017 3018 3019 3020 3021 3022 |
}
}else
if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
ShellState data;
char *zErrMsg = 0;
int doStats = 0;
| < < < < < < > > > > > > > > > > | 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 |
}
}else
if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
ShellState data;
char *zErrMsg = 0;
int doStats = 0;
memcpy(&data, p, sizeof(data));
data.showHeader = 0;
data.cMode = data.mode = MODE_Semi;
if( nArg==2 && optionMatch(azArg[1], "indent") ){
data.cMode = data.mode = MODE_Pretty;
nArg = 1;
}
if( nArg!=1 ){
raw_printf(stderr, "Usage: .fullschema ?--indent?\n");
rc = 1;
goto meta_command_exit;
}
open_db(p, 0);
rc = sqlite3_exec(p->db,
"SELECT sql FROM"
" (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
" FROM sqlite_master UNION ALL"
" SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) "
"WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
"ORDER BY rowid",
|
| ︙ | ︙ | |||
3167 3168 3169 3170 3171 3172 3173 |
nByte = strlen30(zSql);
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
char cSep = '(';
while( xRead(&sCtx) ){
| | | 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 |
nByte = strlen30(zSql);
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
char cSep = '(';
while( xRead(&sCtx) ){
zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z);
cSep = ',';
if( sCtx.cTerm!=sCtx.cColSep ) break;
}
if( cSep=='(' ){
sqlite3_free(zCreate);
sqlite3_free(sCtx.z);
xCloser(sCtx.in);
|
| ︙ | ︙ | |||
3364 3365 3366 3367 3368 3369 3370 |
{ "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH },
{ "worker_threads", SQLITE_LIMIT_WORKER_THREADS },
};
int i, n2;
open_db(p, 0);
if( nArg==1 ){
for(i=0; i<ArraySize(aLimit); i++){
| | | 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 |
{ "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH },
{ "worker_threads", SQLITE_LIMIT_WORKER_THREADS },
};
int i, n2;
open_db(p, 0);
if( nArg==1 ){
for(i=0; i<ArraySize(aLimit); i++){
printf("%20s %d\n", aLimit[i].zLimitName,
sqlite3_limit(p->db, aLimit[i].limitCode, -1));
}
}else if( nArg>3 ){
raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
rc = 1;
goto meta_command_exit;
}else{
|
| ︙ | ︙ | |||
3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 |
const char *zSavedFilename = p->zDbFilename;
char *zNewFilename = 0;
p->db = 0;
if( nArg>=2 ) zNewFilename = sqlite3_mprintf("%s", azArg[1]);
p->zDbFilename = zNewFilename;
open_db(p, 1);
if( p->db!=0 ){
sqlite3_close(savedDb);
sqlite3_free(p->zFreeOnClose);
p->zFreeOnClose = zNewFilename;
}else{
sqlite3_free(zNewFilename);
p->db = savedDb;
p->zDbFilename = zSavedFilename;
| > | 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 |
const char *zSavedFilename = p->zDbFilename;
char *zNewFilename = 0;
p->db = 0;
if( nArg>=2 ) zNewFilename = sqlite3_mprintf("%s", azArg[1]);
p->zDbFilename = zNewFilename;
open_db(p, 1);
if( p->db!=0 ){
session_close_all(p);
sqlite3_close(savedDb);
sqlite3_free(p->zFreeOnClose);
p->zFreeOnClose = zNewFilename;
}else{
sqlite3_free(zNewFilename);
p->db = savedDb;
p->zDbFilename = zSavedFilename;
|
| ︙ | ︙ | |||
3658 3659 3660 3661 3662 3663 3664 |
if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
ShellState data;
char *zErrMsg = 0;
open_db(p, 0);
memcpy(&data, p, sizeof(data));
data.showHeader = 0;
data.cMode = data.mode = MODE_Semi;
| > > > | > > | 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 |
if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
ShellState data;
char *zErrMsg = 0;
open_db(p, 0);
memcpy(&data, p, sizeof(data));
data.showHeader = 0;
data.cMode = data.mode = MODE_Semi;
if( nArg>=2 && optionMatch(azArg[1], "indent") ){
data.cMode = data.mode = MODE_Pretty;
nArg--;
if( nArg==2 ) azArg[1] = azArg[2];
}
if( nArg==2 && azArg[1][0]!='-' ){
int i;
for(i=0; azArg[1][i]; i++) azArg[1][i] = ToLower(azArg[1][i]);
if( strcmp(azArg[1],"sqlite_master")==0 ){
char *new_argv[2], *new_colv[2];
new_argv[0] = "CREATE TABLE sqlite_master (\n"
" type text,\n"
" name text,\n"
|
| ︙ | ︙ | |||
3713 3714 3715 3716 3717 3718 3719 |
" FROM sqlite_master UNION ALL"
" SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) "
"WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
"ORDER BY rowid",
callback, &data, &zErrMsg
);
}else{
| | < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 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 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 |
" FROM sqlite_master UNION ALL"
" SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) "
"WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
"ORDER BY rowid",
callback, &data, &zErrMsg
);
}else{
raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n");
rc = 1;
goto meta_command_exit;
}
if( zErrMsg ){
utf8_printf(stderr,"Error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
rc = 1;
}else if( rc != SQLITE_OK ){
raw_printf(stderr,"Error: querying schema information\n");
rc = 1;
}else{
rc = 0;
}
}else
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
sqlite3SelectTrace = integerValue(azArg[1]);
}else
#endif
#if defined(SQLITE_ENABLE_SESSION)
if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
OpenSession *pSession = &p->aSession[0];
char **azCmd = &azArg[1];
int iSes = 0;
int nCmd = nArg - 1;
int i;
if( nArg<=1 ) goto session_syntax_error;
open_db(p, 0);
if( nArg>=3 ){
for(iSes=0; iSes<p->nSession; iSes++){
if( strcmp(p->aSession[iSes].zName, azArg[1])==0 ) break;
}
if( iSes<p->nSession ){
pSession = &p->aSession[iSes];
azCmd++;
nCmd--;
}else{
pSession = &p->aSession[0];
iSes = 0;
}
}
/* .session attach TABLE
** Invoke the sqlite3session_attach() interface to attach a particular
** table so that it is never filtered.
*/
if( strcmp(azCmd[0],"attach")==0 ){
if( nCmd!=2 ) goto session_syntax_error;
if( pSession->p==0 ){
session_not_open:
raw_printf(stderr, "ERROR: No sessions are open\n");
}else{
rc = sqlite3session_attach(pSession->p, azCmd[1]);
if( rc ){
raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc);
rc = 0;
}
}
}else
/* .session changeset FILE
** .session patchset FILE
** Write a changeset or patchset into a file. The file is overwritten.
*/
if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){
FILE *out = 0;
if( nCmd!=2 ) goto session_syntax_error;
if( pSession->p==0 ) goto session_not_open;
out = fopen(azCmd[1], "wb");
if( out==0 ){
utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n", azCmd[1]);
}else{
int szChng;
void *pChng;
if( azCmd[0][0]=='c' ){
rc = sqlite3session_changeset(pSession->p, &szChng, &pChng);
}else{
rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
}
if( rc ){
printf("Error: error code %d\n", rc);
rc = 0;
}
if( pChng
&& fwrite(pChng, szChng, 1, out)!=1 ){
raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n",
szChng);
}
sqlite3_free(pChng);
fclose(out);
}
}else
/* .session close
** Close the identified session
*/
if( strcmp(azCmd[0], "close")==0 ){
if( nCmd!=1 ) goto session_syntax_error;
if( p->nSession ){
session_close(pSession);
p->aSession[iSes] = p->aSession[--p->nSession];
}
}else
/* .session enable ?BOOLEAN?
** Query or set the enable flag
*/
if( strcmp(azCmd[0], "enable")==0 ){
int ii;
if( nCmd>2 ) goto session_syntax_error;
ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
if( p->nSession ){
ii = sqlite3session_enable(pSession->p, ii);
utf8_printf(p->out, "session %s enable flag = %d\n",
pSession->zName, ii);
}
}else
/* .session filter GLOB ....
** Set a list of GLOB patterns of table names to be excluded.
*/
if( strcmp(azCmd[0], "filter")==0 ){
int ii, nByte;
if( nCmd<2 ) goto session_syntax_error;
if( p->nSession ){
for(ii=0; ii<pSession->nFilter; ii++){
sqlite3_free(pSession->azFilter[ii]);
}
sqlite3_free(pSession->azFilter);
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++){
pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
}
pSession->nFilter = ii-1;
}
}else
/* .session indirect ?BOOLEAN?
** Query or set the indirect flag
*/
if( strcmp(azCmd[0], "indirect")==0 ){
int ii;
if( nCmd>2 ) goto session_syntax_error;
ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
if( p->nSession ){
ii = sqlite3session_indirect(pSession->p, ii);
utf8_printf(p->out, "session %s indirect flag = %d\n",
pSession->zName, ii);
}
}else
/* .session isempty
** Determine if the session is empty
*/
if( strcmp(azCmd[0], "isempty")==0 ){
int ii;
if( nCmd!=1 ) goto session_syntax_error;
if( p->nSession ){
ii = sqlite3session_isempty(pSession->p);
utf8_printf(p->out, "session %s isempty flag = %d\n",
pSession->zName, ii);
}
}else
/* .session list
** List all currently open sessions
*/
if( strcmp(azCmd[0],"list")==0 ){
for(i=0; i<p->nSession; i++){
utf8_printf(p->out, "%d %s\n", i, p->aSession[i].zName);
}
}else
/* .session open DB NAME
** Open a new session called NAME on the attached database DB.
** DB is normally "main".
*/
if( strcmp(azCmd[0],"open")==0 ){
char *zName;
if( nCmd!=3 ) goto session_syntax_error;
zName = azCmd[2];
if( zName[0]==0 ) goto session_syntax_error;
for(i=0; i<p->nSession; i++){
if( strcmp(p->aSession[i].zName,zName)==0 ){
utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
goto meta_command_exit;
}
}
if( p->nSession>=ArraySize(p->aSession) ){
raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(p->aSession));
goto meta_command_exit;
}
pSession = &p->aSession[p->nSession];
rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
if( rc ){
raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
rc = 0;
goto meta_command_exit;
}
pSession->nFilter = 0;
sqlite3session_table_filter(pSession->p, session_filter, pSession);
p->nSession++;
pSession->zName = sqlite3_mprintf("%s", zName);
}else
/* If no command name matches, show a syntax error */
session_syntax_error:
session_help(p);
}else
#endif
#ifdef SQLITE_DEBUG
/* Undocumented commands for internal testing. Subject to change
** without notice. */
if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
int i, v;
|
| ︙ | ︙ | |||
3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 |
}
x = system(zCmd);
sqlite3_free(zCmd);
if( x ) raw_printf(stderr, "System command returns %d\n", x);
}else
if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
int i;
if( nArg!=1 ){
raw_printf(stderr, "Usage: .show\n");
rc = 1;
goto meta_command_exit;
}
| > | | | | > > | | 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 |
}
x = system(zCmd);
sqlite3_free(zCmd);
if( x ) raw_printf(stderr, "System command returns %d\n", x);
}else
if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
static const char *azBool[] = { "off", "on", "full", "unk" };
int i;
if( nArg!=1 ){
raw_printf(stderr, "Usage: .show\n");
rc = 1;
goto meta_command_exit;
}
utf8_printf(p->out, "%12.12s: %s\n","echo", azBool[p->echoOn!=0]);
utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
utf8_printf(p->out, "%12.12s: %s\n","explain",
p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
utf8_printf(p->out, "%12.12s: ", "nullvalue");
output_c_string(p->out, p->nullValue);
raw_printf(p->out, "\n");
utf8_printf(p->out,"%12.12s: %s\n","output",
strlen30(p->outfile) ? p->outfile : "stdout");
utf8_printf(p->out,"%12.12s: ", "colseparator");
output_c_string(p->out, p->colSeparator);
raw_printf(p->out, "\n");
utf8_printf(p->out,"%12.12s: ", "rowseparator");
output_c_string(p->out, p->rowSeparator);
raw_printf(p->out, "\n");
utf8_printf(p->out, "%12.12s: %s\n","stats", azBool[p->statsOn!=0]);
utf8_printf(p->out, "%12.12s: ", "width");
for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
raw_printf(p->out, "%d ", p->colWidth[i]);
}
raw_printf(p->out, "\n");
}else
if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
if( nArg==2 ){
p->statsOn = booleanValue(azArg[1]);
}else if( nArg==1 ){
display_stats(p->db, p, 0);
}else{
raw_printf(stderr, "Usage: .stats ?on|off?\n");
rc = 1;
}
}else
if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){
sqlite3_stmt *pStmt;
char **azResult;
|
| ︙ | ︙ | |||
3990 3991 3992 3993 3994 3995 3996 |
if( (testctrl<SQLITE_TESTCTRL_FIRST) || (testctrl>SQLITE_TESTCTRL_LAST) ){
utf8_printf(stderr,"Error: invalid testctrl option: %s\n", azArg[1]);
}else{
switch(testctrl){
/* sqlite3_test_control(int, db, int) */
case SQLITE_TESTCTRL_OPTIMIZATIONS:
| | | | 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 |
if( (testctrl<SQLITE_TESTCTRL_FIRST) || (testctrl>SQLITE_TESTCTRL_LAST) ){
utf8_printf(stderr,"Error: invalid testctrl option: %s\n", azArg[1]);
}else{
switch(testctrl){
/* sqlite3_test_control(int, db, int) */
case SQLITE_TESTCTRL_OPTIMIZATIONS:
case SQLITE_TESTCTRL_RESERVE:
if( nArg==3 ){
int opt = (int)strtol(azArg[2], 0, 0);
rc2 = sqlite3_test_control(testctrl, p->db, opt);
raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
} else {
utf8_printf(stderr,"Error: testctrl %s takes a single int option\n",
azArg[1]);
}
break;
|
| ︙ | ︙ | |||
4016 4017 4018 4019 4020 4021 4022 |
} else {
utf8_printf(stderr,"Error: testctrl %s takes no options\n",
azArg[1]);
}
break;
/* sqlite3_test_control(int, uint) */
| | | | | | | | | | | | | | | | | | | 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 |
} else {
utf8_printf(stderr,"Error: testctrl %s takes no options\n",
azArg[1]);
}
break;
/* sqlite3_test_control(int, uint) */
case SQLITE_TESTCTRL_PENDING_BYTE:
if( nArg==3 ){
unsigned int opt = (unsigned int)integerValue(azArg[2]);
rc2 = sqlite3_test_control(testctrl, opt);
raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
} else {
utf8_printf(stderr,"Error: testctrl %s takes a single unsigned"
" int option\n", azArg[1]);
}
break;
/* sqlite3_test_control(int, int) */
case SQLITE_TESTCTRL_ASSERT:
case SQLITE_TESTCTRL_ALWAYS:
case SQLITE_TESTCTRL_NEVER_CORRUPT:
if( nArg==3 ){
int opt = booleanValue(azArg[2]);
rc2 = sqlite3_test_control(testctrl, opt);
raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
} else {
utf8_printf(stderr,"Error: testctrl %s takes a single int option\n",
azArg[1]);
}
break;
/* sqlite3_test_control(int, char *) */
#ifdef SQLITE_N_KEYWORD
case SQLITE_TESTCTRL_ISKEYWORD:
if( nArg==3 ){
const char *opt = azArg[2];
rc2 = sqlite3_test_control(testctrl, opt);
raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
} else {
utf8_printf(stderr,
"Error: testctrl %s takes a single char * option\n",
azArg[1]);
}
break;
#endif
case SQLITE_TESTCTRL_IMPOSTER:
if( nArg==5 ){
rc2 = sqlite3_test_control(testctrl, p->db,
azArg[2],
integerValue(azArg[3]),
integerValue(azArg[4]));
raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
}else{
raw_printf(stderr,"Usage: .testctrl imposter dbName onoff tnum\n");
}
break;
case SQLITE_TESTCTRL_BITVEC_TEST:
case SQLITE_TESTCTRL_FAULT_INSTALL:
case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS:
case SQLITE_TESTCTRL_SCRATCHMALLOC:
default:
utf8_printf(stderr,
"Error: CLI support for testctrl %s not implemented\n",
azArg[1]);
break;
}
}
}else
if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
open_db(p, 0);
sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
}else
if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){
if( nArg==2 ){
enableTimer = booleanValue(azArg[1]);
if( enableTimer && !HAS_TIMER ){
raw_printf(stderr, "Error: timer not available on this system.\n");
enableTimer = 0;
}
}else{
raw_printf(stderr, "Usage: .timer on|off\n");
rc = 1;
}
}else
if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
open_db(p, 0);
if( nArg!=2 ){
raw_printf(stderr, "Usage: .trace FILE|off\n");
rc = 1;
goto meta_command_exit;
}
output_file_close(p->traceOut);
p->traceOut = output_file_open(azArg[1]);
#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
if( p->traceOut==0 ){
sqlite3_trace_v2(p->db, 0, 0, 0);
}else{
sqlite3_trace_v2(p->db, SQLITE_TRACE_STMT, sql_trace_callback,p->traceOut);
}
#endif
}else
#if SQLITE_USER_AUTHENTICATION
if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
if( nArg<2 ){
|
| ︙ | ︙ | |||
4178 4179 4180 4181 4182 4183 4184 |
raw_printf(stderr, "User-Delete failed: %d\n", rc);
rc = 1;
}
}else{
raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
rc = 1;
goto meta_command_exit;
| | | 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 |
raw_printf(stderr, "User-Delete failed: %d\n", rc);
rc = 1;
}
}else{
raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
rc = 1;
goto meta_command_exit;
}
}else
#endif /* SQLITE_USER_AUTHENTICATION */
if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
sqlite3_libversion(), sqlite3_sourceid());
}else
|
| ︙ | ︙ | |||
4233 4234 4235 4236 4237 4238 4239 |
sqlite3_free(zVfsName);
}
}
}else
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
| < | 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 |
sqlite3_free(zVfsName);
}
}
}else
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
sqlite3WhereTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff;
}else
#endif
if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
int j;
assert( nArg<=ArraySize(azArg) );
|
| ︙ | ︙ | |||
4410 4411 4412 4413 4414 4415 4416 |
if( p->backslashOn ) resolve_backslashes(zSql);
BEGIN_TIMER;
rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg);
END_TIMER;
if( rc || zErrMsg ){
char zPrefix[100];
if( in!=0 || !stdin_is_interactive ){
| | | 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 |
if( p->backslashOn ) resolve_backslashes(zSql);
BEGIN_TIMER;
rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg);
END_TIMER;
if( rc || zErrMsg ){
char zPrefix[100];
if( in!=0 || !stdin_is_interactive ){
sqlite3_snprintf(sizeof(zPrefix), zPrefix,
"Error: near line %d:", startline);
}else{
sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:");
}
if( zErrMsg!=0 ){
utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg);
sqlite3_free(zErrMsg);
|
| ︙ | ︙ | |||
4552 4553 4554 4555 4556 4557 4558 | } sqlite3_free(zBuf); } /* ** Show available command line options */ | | | 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 | } sqlite3_free(zBuf); } /* ** Show available command line options */ static const char zOptions[] = " -ascii set output mode to 'ascii'\n" " -bail stop after hitting an error\n" " -batch force batch I/O\n" " -column set output mode to 'column'\n" " -cmd COMMAND run \"COMMAND\" before reading stdin\n" " -csv set output mode to 'csv'\n" " -echo print commands before execution\n" |
| ︙ | ︙ | |||
4589 4590 4591 4592 4593 4594 4595 |
" -vfs NAME use NAME as the default VFS\n"
#ifdef SQLITE_ENABLE_VFSTRACE
" -vfstrace enable tracing of all VFS calls\n"
#endif
;
static void usage(int showDetail){
utf8_printf(stderr,
| | | 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 |
" -vfs NAME use NAME as the default VFS\n"
#ifdef SQLITE_ENABLE_VFSTRACE
" -vfstrace enable tracing of all VFS calls\n"
#endif
;
static void usage(int showDetail){
utf8_printf(stderr,
"Usage: %s [OPTIONS] FILENAME [SQL]\n"
"FILENAME is the name of an SQLite database. A new database is created\n"
"if the file does not previously exist.\n", Argv0);
if( showDetail ){
utf8_printf(stderr, "OPTIONS include:\n%s", zOptions);
}else{
raw_printf(stderr, "Use the -help option for additional information\n");
}
|
| ︙ | ︙ | |||
4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 |
utf8_printf(stderr, "%s: Error: missing argument to %s\n",
argv[0], argv[argc-1]);
exit(1);
}
return argv[i];
}
int SQLITE_CDECL main(int argc, char **argv){
char *zErrMsg = 0;
ShellState data;
const char *zInitFile = 0;
int i;
int rc = 0;
int warnInmemoryDb = 0;
int readStdin = 1;
int nCmd = 0;
char **azCmd = 0;
#if USE_SYSTEM_SQLITE+0!=1
if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){
utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
sqlite3_sourceid(), SQLITE_SOURCE_ID);
exit(1);
}
#endif
| > > > > > > > > > > > > > > > > > > > > > > > | > > > > > | > > > > > < < < | 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 |
utf8_printf(stderr, "%s: Error: missing argument to %s\n",
argv[0], argv[argc-1]);
exit(1);
}
return argv[i];
}
#ifndef SQLITE_SHELL_IS_UTF8
# if (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
# define SQLITE_SHELL_IS_UTF8 (0)
# else
# define SQLITE_SHELL_IS_UTF8 (1)
# endif
#endif
#if SQLITE_SHELL_IS_UTF8
int SQLITE_CDECL main(int argc, char **argv){
#else
int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
char **argv;
#endif
char *zErrMsg = 0;
ShellState data;
const char *zInitFile = 0;
int i;
int rc = 0;
int warnInmemoryDb = 0;
int readStdin = 1;
int nCmd = 0;
char **azCmd = 0;
setBinaryMode(stdin, 0);
setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
stdin_is_interactive = isatty(0);
stdout_is_console = isatty(1);
#if USE_SYSTEM_SQLITE+0!=1
if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){
utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
sqlite3_sourceid(), SQLITE_SOURCE_ID);
exit(1);
}
#endif
main_init(&data);
#if !SQLITE_SHELL_IS_UTF8
sqlite3_initialize();
argv = sqlite3_malloc64(sizeof(argv[0])*argc);
if( argv==0 ){
raw_printf(stderr, "out of memory\n");
exit(1);
}
for(i=0; i<argc; i++){
argv[i] = sqlite3_win32_unicode_to_utf8(wargv[i]);
if( argv[i]==0 ){
raw_printf(stderr, "out of memory\n");
exit(1);
}
}
#endif
assert( argc>=1 && argv && argv[0] );
Argv0 = argv[0];
/* Make sure we have a valid signal handler early, before anything
** else is done.
*/
#ifdef SIGINT
signal(SIGINT, interrupt_handler);
#endif
|
| ︙ | ︙ | |||
4730 4731 4732 4733 4734 4735 4736 |
|| strcmp(z,"-cmd")==0
){
(void)cmdline_option_value(argc, argv, ++i);
}else if( strcmp(z,"-init")==0 ){
zInitFile = cmdline_option_value(argc, argv, ++i);
}else if( strcmp(z,"-batch")==0 ){
/* Need to check for batch mode here to so we can avoid printing
| | > > | 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 |
|| strcmp(z,"-cmd")==0
){
(void)cmdline_option_value(argc, argv, ++i);
}else if( strcmp(z,"-init")==0 ){
zInitFile = cmdline_option_value(argc, argv, ++i);
}else if( strcmp(z,"-batch")==0 ){
/* Need to check for batch mode here to so we can avoid printing
** informational messages (like from process_sqliterc) before
** we do the actual processing of arguments later in a second pass.
*/
stdin_is_interactive = 0;
}else if( strcmp(z,"-heap")==0 ){
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
const char *zSize;
sqlite3_int64 szHeap;
zSize = cmdline_option_value(argc, argv, ++i);
szHeap = integerValue(zSize);
if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
#else
(void)cmdline_option_value(argc, argv, ++i);
#endif
}else if( strcmp(z,"-scratch")==0 ){
int n, sz;
sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
if( sz>400000 ) sz = 400000;
if( sz<2500 ) sz = 2500;
n = (int)integerValue(cmdline_option_value(argc,argv,++i));
|
| ︙ | ︙ | |||
4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 |
data.showHeader = 1;
}else if( strcmp(z,"-noheader")==0 ){
data.showHeader = 0;
}else if( strcmp(z,"-echo")==0 ){
data.echoOn = 1;
}else if( strcmp(z,"-eqp")==0 ){
data.autoEQP = 1;
}else if( strcmp(z,"-stats")==0 ){
data.statsOn = 1;
}else if( strcmp(z,"-scanstats")==0 ){
data.scanstatsOn = 1;
}else if( strcmp(z,"-backslash")==0 ){
/* Undocumented command-line option: -backslash
** Causes C-style backslash escapes to be evaluated in SQL statements
| > > | 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 |
data.showHeader = 1;
}else if( strcmp(z,"-noheader")==0 ){
data.showHeader = 0;
}else if( strcmp(z,"-echo")==0 ){
data.echoOn = 1;
}else if( strcmp(z,"-eqp")==0 ){
data.autoEQP = 1;
}else if( strcmp(z,"-eqpfull")==0 ){
data.autoEQP = 2;
}else if( strcmp(z,"-stats")==0 ){
data.statsOn = 1;
}else if( strcmp(z,"-scanstats")==0 ){
data.scanstatsOn = 1;
}else if( strcmp(z,"-backslash")==0 ){
/* Undocumented command-line option: -backslash
** Causes C-style backslash escapes to be evaluated in SQL statements
|
| ︙ | ︙ | |||
5002 5003 5004 5005 5006 5007 5008 5009 5010 |
}
}else{
rc = process_input(&data, stdin);
}
}
set_table_name(&data, 0);
if( data.db ){
sqlite3_close(data.db);
}
| > | > > > > | 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 |
}
}else{
rc = process_input(&data, stdin);
}
}
set_table_name(&data, 0);
if( data.db ){
session_close_all(&data);
sqlite3_close(data.db);
}
sqlite3_free(data.zFreeOnClose);
#if !SQLITE_SHELL_IS_UTF8
for(i=0; i<argc; i++) sqlite3_free(argv[i]);
sqlite3_free(argv);
#endif
return rc;
}
|
Changes to src/sitemap.c.
| ︙ | ︙ | |||
18 19 20 21 22 23 24 | ** This file contains code to implement the sitemap webpage. */ #include "config.h" #include "sitemap.h" #include <assert.h> /* | | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
** This file contains code to implement the sitemap webpage.
*/
#include "config.h"
#include "sitemap.h"
#include <assert.h>
/*
** WEBPAGE: sitemap
**
** List some of the web pages offered by the Fossil web engine. This
** page is intended as a supplement to the menu bar on the main screen.
** That is, this page is designed to hold links that are omitted from
** the main menu due to lack of space.
*/
void sitemap_page(void){
int srchFlags;
login_check_credentials();
srchFlags = search_restrict(SRCH_ALL);
|
| ︙ | ︙ |
Changes to src/skins.c.
| ︙ | ︙ | |||
491 492 493 494 495 496 497 |
zCurrent = db_get(zName, 0);
db_multi_exec("%s", zCurrent/*safe-for-%s*/);
}
}
style_header("Skins");
if( zErr ){
| | | 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 |
zCurrent = db_get(zName, 0);
db_multi_exec("%s", zCurrent/*safe-for-%s*/);
}
}
style_header("Skins");
if( zErr ){
@ <p style="color:red">%h(zErr)</p>
}
@ <p>A "skin" is a combination of
@ <a href="setup_skinedit?w=0">CSS</a>,
@ <a href="setup_skinedit?w=2">Header</a>,
@ <a href="setup_skinedit?w=1">Footer</a>, and
@ <a href="setup_skinedit?w=3">Details</a>
@ that determines the look and feel
|
| ︙ | ︙ |
Changes to src/sqlcmd.c.
| ︙ | ︙ | |||
163 164 165 166 167 168 169 | ** ** Fossil Options: ** ** --no-repository Skip opening the repository database. ** ** WARNING: Careless use of this command can corrupt a Fossil repository ** in ways that are unrecoverable. Be sure you know what you are doing before | | | | | | < | < < < | 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 |
**
** Fossil Options:
**
** --no-repository Skip opening the repository database.
**
** WARNING: Careless use of this command can corrupt a Fossil repository
** in ways that are unrecoverable. Be sure you know what you are doing before
** running any SQL commands that modify the repository database.
**
** The following extensions to the usual SQLite commands are provided:
**
** content(X) Return the content of artifact X. X can be a
** SHA1 hash or prefix or a tag.
**
** compress(X) Compress text X.
**
** decompress(X) Decompress text X. Undoes the work of
** compress(X).
**
** checkin_mtime(X,Y) Return the mtime for the file Y (a BLOB.RID)
** found in check-in X (another BLOB.RID value).
**
** symbolic_name_to_rid(X) Return the BLOB.RID corresponding to symbolic
** name X.
**
** now() Return the number of seconds since 1970.
**
** REGEXP The REGEXP operator works, unlike in
** standard SQLite.
**
** files_of_checkin(X) A table-valued function that returns info on
** all files contained in check-in X. Example:
** SELECT * FROM files_of_checkin('trunk');
*/
void cmd_sqlite3(void){
int noRepository;
extern int sqlite3_shell(int, char**);
noRepository = find_option("no-repository", 0, 0)!=0;
if( !noRepository ){
db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
|
| ︙ | ︙ |
Changes to src/sqlite3.c.
more than 10,000 changes
Changes to src/sqlite3.h.
| ︙ | ︙ | |||
26 27 28 29 30 31 32 | ** on how SQLite interfaces are supposed to operate. ** ** The name of this file under configuration management is "sqlite.h.in". ** The makefile makes some minor changes to this file (such as inserting ** the version number) and changes its name to "sqlite3.h" as ** part of the build process. */ | | | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
** on how SQLite interfaces are supposed to operate.
**
** The name of this file under configuration management is "sqlite.h.in".
** The makefile makes some minor changes to this file (such as inserting
** the version number) and changes its name to "sqlite3.h" as
** part of the build process.
*/
#ifndef SQLITE3_H
#define SQLITE3_H
#include <stdarg.h> /* Needed for the definition of va_list */
/*
** Make sure we can call this stuff from C++.
*/
#ifdef __cplusplus
extern "C" {
|
| ︙ | ︙ | |||
50 51 52 53 54 55 56 57 | #endif #ifndef SQLITE_API # define SQLITE_API #endif #ifndef SQLITE_CDECL # define SQLITE_CDECL #endif #ifndef SQLITE_STDCALL | > > > | > > > > > > | 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 | #endif #ifndef SQLITE_API # define SQLITE_API #endif #ifndef SQLITE_CDECL # define SQLITE_CDECL #endif #ifndef SQLITE_APICALL # define SQLITE_APICALL #endif #ifndef SQLITE_STDCALL # define SQLITE_STDCALL SQLITE_APICALL #endif #ifndef SQLITE_CALLBACK # define SQLITE_CALLBACK #endif #ifndef SQLITE_SYSAPI # define SQLITE_SYSAPI #endif /* ** These no-op macros are used in front of interfaces to mark those ** interfaces as either deprecated or experimental. New applications ** should not use deprecated interfaces - they are supported for backwards ** compatibility only. Application writers should be aware that |
| ︙ | ︙ | |||
107 108 109 110 111 112 113 | ** string contains the date and time of the check-in (UTC) and an SHA1 ** hash of the entire source tree. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ | | | | | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | ** string contains the date and time of the check-in (UTC) and an SHA1 ** hash of the entire source tree. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.14.0" #define SQLITE_VERSION_NUMBER 3014000 #define SQLITE_SOURCE_ID "2016-08-02 08:45:26 7c38a79cdd42aaa45715aea330d10ca859098837" /* ** 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 |
| ︙ | ︙ | |||
142 143 144 145 146 147 148 | ** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns ** a pointer to a string constant whose value is the same as the ** [SQLITE_SOURCE_ID] C preprocessor macro. ** ** See also: [sqlite_version()] and [sqlite_source_id()]. */ SQLITE_API SQLITE_EXTERN const char sqlite3_version[]; | | | | | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | ** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns ** a pointer to a string constant whose value is the same as the ** [SQLITE_SOURCE_ID] C preprocessor macro. ** ** See also: [sqlite_version()] and [sqlite_source_id()]. */ SQLITE_API SQLITE_EXTERN const char sqlite3_version[]; SQLITE_API const char *SQLITE_APICALL sqlite3_libversion(void); SQLITE_API const char *SQLITE_APICALL sqlite3_sourceid(void); SQLITE_API int SQLITE_APICALL sqlite3_libversion_number(void); /* ** CAPI3REF: Run-Time Library Compilation Options Diagnostics ** ** ^The sqlite3_compileoption_used() function returns 0 or 1 ** indicating whether the specified option was defined at ** compile time. ^The SQLITE_ prefix may be omitted from the |
| ︙ | ︙ | |||
169 170 171 172 173 174 175 | ** and sqlite3_compileoption_get() may be omitted by specifying the ** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time. ** ** See also: SQL functions [sqlite_compileoption_used()] and ** [sqlite_compileoption_get()] and the [compile_options pragma]. */ #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS | | | | 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | ** and sqlite3_compileoption_get() may be omitted by specifying the ** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time. ** ** See also: SQL functions [sqlite_compileoption_used()] and ** [sqlite_compileoption_get()] and the [compile_options pragma]. */ #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS SQLITE_API int SQLITE_APICALL sqlite3_compileoption_used(const char *zOptName); SQLITE_API const char *SQLITE_APICALL sqlite3_compileoption_get(int N); #endif /* ** CAPI3REF: Test To See If The Library Is Threadsafe ** ** ^The sqlite3_threadsafe() function returns zero if and only if ** SQLite was compiled with mutexing code omitted due to the |
| ︙ | ︙ | |||
209 210 211 212 213 214 215 | ** sqlite3_threadsafe() function shows only the compile-time setting of ** thread safety, not any run-time changes to that setting made by ** sqlite3_config(). In other words, the return value from sqlite3_threadsafe() ** is unchanged by calls to sqlite3_config().)^ ** ** See the [threading mode] documentation for additional information. */ | | | 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
** sqlite3_threadsafe() function shows only the compile-time setting of
** thread safety, not any run-time changes to that setting made by
** sqlite3_config(). In other words, the return value from sqlite3_threadsafe()
** is unchanged by calls to sqlite3_config().)^
**
** See the [threading mode] documentation for additional information.
*/
SQLITE_API int SQLITE_APICALL sqlite3_threadsafe(void);
/*
** CAPI3REF: Database Connection Handle
** KEYWORDS: {database connection} {database connections}
**
** Each open SQLite database is represented by a pointer to an instance of
** the opaque structure named "sqlite3". It is useful to think of an sqlite3
|
| ︙ | ︙ | |||
306 307 308 309 310 311 312 | ** must be either a NULL ** pointer or an [sqlite3] object pointer obtained ** from [sqlite3_open()], [sqlite3_open16()], or ** [sqlite3_open_v2()], and not previously closed. ** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer ** argument is a harmless no-op. */ | | | | | 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 | ** must be either a NULL ** pointer or an [sqlite3] object pointer obtained ** from [sqlite3_open()], [sqlite3_open16()], or ** [sqlite3_open_v2()], and not previously closed. ** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer ** argument is a harmless no-op. */ SQLITE_API int SQLITE_APICALL sqlite3_close(sqlite3*); SQLITE_API int SQLITE_APICALL sqlite3_close_v2(sqlite3*); /* ** The type for a callback function. ** This is legacy and deprecated. It is included for historical ** compatibility and is not documented. */ typedef int (SQLITE_CALLBACK *sqlite3_callback)(void*,int,char**, char**); /* ** CAPI3REF: One-Step Query Execution Interface ** METHOD: sqlite3 ** ** The sqlite3_exec() interface is a convenience wrapper around ** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()], |
| ︙ | ︙ | |||
378 379 380 381 382 383 384 | ** is a valid and open [database connection]. ** <li> The application must not close the [database connection] specified by ** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running. ** <li> The application must not modify the SQL statement text passed into ** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running. ** </ul> */ | | | | 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 |
** is a valid and open [database connection].
** <li> The application must not close the [database connection] specified by
** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
** <li> The application must not modify the SQL statement text passed into
** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
** </ul>
*/
SQLITE_API int SQLITE_APICALL sqlite3_exec(
sqlite3*, /* An open database */
const char *sql, /* SQL to be evaluated */
int (SQLITE_CALLBACK *callback)(void*,int,char**,char**), /* Callback function */
void *, /* 1st argument to callback */
char **errmsg /* Error msg written here */
);
/*
** CAPI3REF: Result Codes
** KEYWORDS: {result code definitions}
|
| ︙ | ︙ | |||
502 503 504 505 506 507 508 509 510 511 512 513 514 515 | #define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8)) #define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8)) #define SQLITE_CONSTRAINT_ROWID (SQLITE_CONSTRAINT |(10<<8)) #define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8)) #define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8)) #define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8)) #define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8)) /* ** 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. | > | 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 | #define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8)) #define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8)) #define SQLITE_CONSTRAINT_ROWID (SQLITE_CONSTRAINT |(10<<8)) #define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8)) #define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8)) #define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8)) #define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8)) #define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8)) /* ** 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. |
| ︙ | ︙ | |||
728 729 730 731 732 733 734 |
** fails to zero-fill short reads might seem to work. However,
** failure to zero-fill short reads will eventually lead to
** database corruption.
*/
typedef struct sqlite3_io_methods sqlite3_io_methods;
struct sqlite3_io_methods {
int iVersion;
| | | | | | | | | | | | | | | | | | | | 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 |
** fails to zero-fill short reads might seem to work. However,
** failure to zero-fill short reads will eventually lead to
** database corruption.
*/
typedef struct sqlite3_io_methods sqlite3_io_methods;
struct sqlite3_io_methods {
int iVersion;
int (SQLITE_CALLBACK *xClose)(sqlite3_file*);
int (SQLITE_CALLBACK *xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
int (SQLITE_CALLBACK *xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
int (SQLITE_CALLBACK *xTruncate)(sqlite3_file*, sqlite3_int64 size);
int (SQLITE_CALLBACK *xSync)(sqlite3_file*, int flags);
int (SQLITE_CALLBACK *xFileSize)(sqlite3_file*, sqlite3_int64 *pSize);
int (SQLITE_CALLBACK *xLock)(sqlite3_file*, int);
int (SQLITE_CALLBACK *xUnlock)(sqlite3_file*, int);
int (SQLITE_CALLBACK *xCheckReservedLock)(sqlite3_file*, int *pResOut);
int (SQLITE_CALLBACK *xFileControl)(sqlite3_file*, int op, void *pArg);
int (SQLITE_CALLBACK *xSectorSize)(sqlite3_file*);
int (SQLITE_CALLBACK *xDeviceCharacteristics)(sqlite3_file*);
/* Methods above are valid for version 1 */
int (SQLITE_CALLBACK *xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
int (SQLITE_CALLBACK *xShmLock)(sqlite3_file*, int offset, int n, int flags);
void (SQLITE_CALLBACK *xShmBarrier)(sqlite3_file*);
int (SQLITE_CALLBACK *xShmUnmap)(sqlite3_file*, int deleteFlag);
/* Methods above are valid for version 2 */
int (SQLITE_CALLBACK *xFetch)(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
int (SQLITE_CALLBACK *xUnfetch)(sqlite3_file*, sqlite3_int64 iOfst, void *p);
/* Methods above are valid for version 3 */
/* Additional methods may be added in future releases */
};
/*
** CAPI3REF: Standard File Control Opcodes
** KEYWORDS: {file control opcodes} {file control opcode}
|
| ︙ | ︙ | |||
923 924 925 926 927 928 929 | ** ** <li>[[SQLITE_FCNTL_BUSYHANDLER]] ** ^The [SQLITE_FCNTL_BUSYHANDLER] ** file-control may be invoked by SQLite on the database file handle ** shortly after it is opened in order to provide a custom VFS with access ** to the connections busy-handler callback. The argument is of type (void **) ** - an array of two (void *) values. The first (void *) actually points | | | 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 | ** ** <li>[[SQLITE_FCNTL_BUSYHANDLER]] ** ^The [SQLITE_FCNTL_BUSYHANDLER] ** file-control may be invoked by SQLite on the database file handle ** shortly after it is opened in order to provide a custom VFS with access ** to the connections busy-handler callback. The argument is of type (void **) ** - an array of two (void *) values. The first (void *) actually points ** to a function of type (int (SQLITE_CALLBACK *)(void *)). In order to invoke the connections ** busy-handler, this function should be invoked with the second (void *) in ** the array as the only argument. If it returns non-zero, then the operation ** should be retried. If it returns zero, the custom VFS should abandon the ** current operation. ** ** <li>[[SQLITE_FCNTL_TEMPFILENAME]] ** ^Application can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control |
| ︙ | ︙ | |||
1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 | ** at the internal representation of an [sqlite3_mutex]. It only ** deals with pointers to the [sqlite3_mutex] object. ** ** Mutexes are created using [sqlite3_mutex_alloc()]. */ typedef struct sqlite3_mutex sqlite3_mutex; /* ** CAPI3REF: OS Interface Object ** ** An instance of the sqlite3_vfs object defines the interface between ** the SQLite core and the underlying operating system. The "vfs" ** in the name of the object stands for "virtual file system". See ** the [VFS | VFS documentation] for further information. | > > > > > > > > > > | 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 | ** at the internal representation of an [sqlite3_mutex]. It only ** deals with pointers to the [sqlite3_mutex] object. ** ** Mutexes are created using [sqlite3_mutex_alloc()]. */ typedef struct sqlite3_mutex sqlite3_mutex; /* ** CAPI3REF: Loadable Extension Thunk ** ** A pointer to the opaque sqlite3_api_routines structure is passed as ** the third parameter to entry points of [loadable extensions]. This ** structure must be typedefed in order to work around compiler warnings ** on some platforms. */ typedef struct sqlite3_api_routines sqlite3_api_routines; /* ** CAPI3REF: OS Interface Object ** ** An instance of the sqlite3_vfs object defines the interface between ** the SQLite core and the underlying operating system. The "vfs" ** in the name of the object stands for "virtual file system". See ** the [VFS | VFS documentation] for further information. |
| ︙ | ︙ | |||
1189 1190 1191 1192 1193 1194 1195 | ** varies from one VFS to another, and from one version of the same VFS to the ** next. Applications that use these interfaces must be prepared for any ** or all of these interfaces to be NULL or for their behavior to change ** from one release to the next. Applications must not attempt to access ** any of these methods if the iVersion of the VFS is less than 3. */ typedef struct sqlite3_vfs sqlite3_vfs; | | | | | | | | | | | | | | | | | | | | 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 |
** varies from one VFS to another, and from one version of the same VFS to the
** next. Applications that use these interfaces must be prepared for any
** or all of these interfaces to be NULL or for their behavior to change
** from one release to the next. Applications must not attempt to access
** any of these methods if the iVersion of the VFS is less than 3.
*/
typedef struct sqlite3_vfs sqlite3_vfs;
typedef void (SQLITE_SYSAPI *sqlite3_syscall_ptr)(void);
struct sqlite3_vfs {
int iVersion; /* Structure version number (currently 3) */
int szOsFile; /* Size of subclassed sqlite3_file */
int mxPathname; /* Maximum file pathname length */
sqlite3_vfs *pNext; /* Next registered VFS */
const char *zName; /* Name of this virtual file system */
void *pAppData; /* Pointer to application-specific data */
int (SQLITE_CALLBACK *xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*,
int flags, int *pOutFlags);
int (SQLITE_CALLBACK *xDelete)(sqlite3_vfs*, const char *zName, int syncDir);
int (SQLITE_CALLBACK *xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut);
int (SQLITE_CALLBACK *xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut);
void *(SQLITE_CALLBACK *xDlOpen)(sqlite3_vfs*, const char *zFilename);
void (SQLITE_CALLBACK *xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg);
void (SQLITE_CALLBACK *(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void);
void (SQLITE_CALLBACK *xDlClose)(sqlite3_vfs*, void*);
int (SQLITE_CALLBACK *xRandomness)(sqlite3_vfs*, int nByte, char *zOut);
int (SQLITE_CALLBACK *xSleep)(sqlite3_vfs*, int microseconds);
int (SQLITE_CALLBACK *xCurrentTime)(sqlite3_vfs*, double*);
int (SQLITE_CALLBACK *xGetLastError)(sqlite3_vfs*, int, char *);
/*
** The methods above are in version 1 of the sqlite_vfs object
** definition. Those that follow are added in version 2 or later
*/
int (SQLITE_CALLBACK *xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*);
/*
** The methods above are in versions 1 and 2 of the sqlite_vfs object.
** Those below are for version 3 and greater.
*/
int (SQLITE_CALLBACK *xSetSystemCall)(sqlite3_vfs*, const char *zName, sqlite3_syscall_ptr);
sqlite3_syscall_ptr (SQLITE_CALLBACK *xGetSystemCall)(sqlite3_vfs*, const char *zName);
const char *(SQLITE_CALLBACK *xNextSystemCall)(sqlite3_vfs*, const char *zName);
/*
** The methods above are in versions 1 through 3 of the sqlite_vfs object.
** New fields may be appended in future versions. The iVersion
** value will increment whenever this happens.
*/
};
/*
** CAPI3REF: Flags for the xAccess VFS method
**
|
| ︙ | ︙ | |||
1366 1367 1368 1369 1370 1371 1372 | ** (using the [SQLITE_OS_OTHER=1] compile-time ** option) the application must supply a suitable implementation for ** sqlite3_os_init() and sqlite3_os_end(). An application-supplied ** implementation of sqlite3_os_init() or sqlite3_os_end() ** must return [SQLITE_OK] on success and some other [error code] upon ** failure. */ | | | | | | 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 | ** (using the [SQLITE_OS_OTHER=1] compile-time ** option) the application must supply a suitable implementation for ** sqlite3_os_init() and sqlite3_os_end(). An application-supplied ** implementation of sqlite3_os_init() or sqlite3_os_end() ** must return [SQLITE_OK] on success and some other [error code] upon ** failure. */ SQLITE_API int SQLITE_APICALL sqlite3_initialize(void); SQLITE_API int SQLITE_APICALL sqlite3_shutdown(void); SQLITE_API int SQLITE_APICALL sqlite3_os_init(void); SQLITE_API int SQLITE_APICALL sqlite3_os_end(void); /* ** CAPI3REF: Configuring The SQLite Library ** ** The sqlite3_config() interface is used to make global configuration ** changes to SQLite in order to tune SQLite to the specific needs of ** the application. The default configuration is recommended for most |
| ︙ | ︙ | |||
1488 1489 1490 1491 1492 1493 1494 |
** serialization.
**
** SQLite will never invoke xInit() more than once without an intervening
** call to xShutdown().
*/
typedef struct sqlite3_mem_methods sqlite3_mem_methods;
struct sqlite3_mem_methods {
| | | | | | | | | 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 |
** serialization.
**
** SQLite will never invoke xInit() more than once without an intervening
** call to xShutdown().
*/
typedef struct sqlite3_mem_methods sqlite3_mem_methods;
struct sqlite3_mem_methods {
void *(SQLITE_CALLBACK *xMalloc)(int); /* Memory allocation function */
void (SQLITE_CALLBACK *xFree)(void*); /* Free a prior allocation */
void *(SQLITE_CALLBACK *xRealloc)(void*,int); /* Resize an allocation */
int (SQLITE_CALLBACK *xSize)(void*); /* Return the size of an allocation */
int (SQLITE_CALLBACK *xRoundup)(int); /* Round up request size to allocation size */
int (SQLITE_CALLBACK *xInit)(void*); /* Initialize the memory allocator */
void (SQLITE_CALLBACK *xShutdown)(void*); /* Deinitialize the memory allocator */
void *pAppData; /* Argument to xInit() and xShutdown() */
};
/*
** CAPI3REF: Configuration Options
** KEYWORDS: {configuration option}
**
|
| ︙ | ︙ | |||
1711 1712 1713 1714 1715 1716 1717 | ** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies of ** the current page cache implementation into that object.)^ </dd> ** ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt> ** <dd> The SQLITE_CONFIG_LOG option is used to configure the SQLite ** global [error log]. ** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a | | | 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 | ** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies of ** the current page cache implementation into that object.)^ </dd> ** ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt> ** <dd> The SQLITE_CONFIG_LOG option is used to configure the SQLite ** global [error log]. ** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a ** function with a call signature of void(SQLITE_CALLBACK *)(void*,int,const char*), ** and a pointer to void. ^If the function pointer is not NULL, it is ** invoked by [sqlite3_log()] to process each logging event. ^If the ** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op. ** ^The void pointer that is the second argument to SQLITE_CONFIG_LOG is ** passed through as the first parameter to the application-defined logger ** function whenever that function is invoked. ^The second parameter to ** the logger function is a copy of the first parameter to the corresponding |
| ︙ | ︙ | |||
1764 1765 1766 1767 1768 1769 1770 | ** They are retained for backwards compatibility but are now no-ops. ** </dd> ** ** [[SQLITE_CONFIG_SQLLOG]] ** <dt>SQLITE_CONFIG_SQLLOG ** <dd>This option is only available if sqlite is compiled with the ** [SQLITE_ENABLE_SQLLOG] pre-processor macro defined. The first argument should | | | 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 | ** They are retained for backwards compatibility but are now no-ops. ** </dd> ** ** [[SQLITE_CONFIG_SQLLOG]] ** <dt>SQLITE_CONFIG_SQLLOG ** <dd>This option is only available if sqlite is compiled with the ** [SQLITE_ENABLE_SQLLOG] pre-processor macro defined. The first argument should ** be a pointer to a function of type void(SQLITE_CALLBACK *)(void*,sqlite3*,const char*, int). ** The second should be of type (void*). The callback is invoked by the library ** in three separate circumstances, identified by the value passed as the ** fourth parameter. If the fourth parameter is 0, then the database connection ** passed as the second argument has just been opened. The third argument ** points to a buffer containing the name of the main database file. If the ** fourth parameter is 1, then the SQL statement that the third parameter ** points to has just been executed. Or, if the fourth parameter is 2, then |
| ︙ | ︙ | |||
1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 | ** is an unsigned integer and sets the "Minimum PMA Size" for the multithreaded ** sorter to that integer. The default minimum PMA Size is set by the ** [SQLITE_SORTER_PMASZ] compile-time option. New threads are launched ** to help with sort operations when multithreaded sorting ** is enabled (using the [PRAGMA threads] command) and the amount of content ** to be sorted exceeds the page size times the minimum of the ** [PRAGMA cache_size] setting and this value. ** </dl> */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ #define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ #define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */ | > > > > > > > > > > > > > > | 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 | ** is an unsigned integer and sets the "Minimum PMA Size" for the multithreaded ** sorter to that integer. The default minimum PMA Size is set by the ** [SQLITE_SORTER_PMASZ] compile-time option. New threads are launched ** to help with sort operations when multithreaded sorting ** is enabled (using the [PRAGMA threads] command) and the amount of content ** to be sorted exceeds the page size times the minimum of the ** [PRAGMA cache_size] setting and this value. ** ** [[SQLITE_CONFIG_STMTJRNL_SPILL]] ** <dt>SQLITE_CONFIG_STMTJRNL_SPILL ** <dd>^The SQLITE_CONFIG_STMTJRNL_SPILL option takes a single parameter which ** becomes the [statement journal] spill-to-disk threshold. ** [Statement journals] are held in memory until their size (in bytes) ** exceeds this threshold, at which point they are written to disk. ** Or if the threshold is -1, statement journals are always held ** exclusively in memory. ** Since many statement journals never become large, setting the spill ** threshold to a value such as 64KiB can greatly reduce the amount of ** I/O required to support statement rollback. ** The default value for this setting is controlled by the ** [SQLITE_STMTJRNL_SPILL] compile-time option. ** </dl> */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ #define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ #define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */ |
| ︙ | ︙ | |||
1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 | #define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ #define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */ #define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */ /* ** CAPI3REF: Database Connection Configuration Options ** ** These constants are the available integer configuration options that ** can be passed as the second argument to the [sqlite3_db_config()] interface. ** | > | 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 | #define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ #define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */ #define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */ #define SQLITE_CONFIG_STMTJRNL_SPILL 26 /* int nByte */ /* ** CAPI3REF: Database Connection Configuration Options ** ** These constants are the available integer configuration options that ** can be passed as the second argument to the [sqlite3_db_config()] interface. ** |
| ︙ | ︙ | |||
1900 1901 1902 1903 1904 1905 1906 1907 1908 | ** The first argument is an integer which is 0 to disable triggers, ** positive to enable triggers or negative to leave the setting unchanged. ** The second parameter is a pointer to an integer into which ** is written 0 or 1 to indicate whether triggers are disabled or enabled ** following this call. The second parameter may be a NULL pointer, in ** which case the trigger setting is not reported back. </dd> ** ** </dl> */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | > > | | 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 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 | ** The first argument is an integer which is 0 to disable triggers, ** positive to enable triggers or negative to leave the setting unchanged. ** The second parameter is a pointer to an integer into which ** is written 0 or 1 to indicate whether triggers are disabled or enabled ** following this call. The second parameter may be a NULL pointer, in ** which case the trigger setting is not reported back. </dd> ** ** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt> ** <dd> ^This option is used to enable or disable the two-argument ** version of the [fts3_tokenizer()] function which is part of the ** [FTS3] full-text search engine extension. ** There should be two additional arguments. ** The first argument is an integer which is 0 to disable fts3_tokenizer() or ** positive to enable fts3_tokenizer() or negative to leave the setting ** unchanged. ** The second parameter is a pointer to an integer into which ** is written 0 or 1 to indicate whether fts3_tokenizer is disabled or enabled ** following this call. The second parameter may be a NULL pointer, in ** which case the new setting is not reported back. </dd> ** ** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt> ** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()] ** interface independently of the [load_extension()] SQL function. ** The [sqlite3_enable_load_extension()] API enables or disables both the ** C-API [sqlite3_load_extension()] and the SQL function [load_extension()]. ** There should be two additional arguments. ** When the first argument to this interface is 1, then only the C-API is ** enabled and the SQL function remains disabled. If the first argment to ** this interface is 0, then both the C-API and the SQL function are disabled. ** If the first argument is -1, then no changes are made to state of either the ** C-API or the SQL function. ** The second parameter is a pointer to an integer into which ** is written 0 or 1 to indicate whether [sqlite3_load_extension()] interface ** is disabled or enabled following this call. The second parameter may ** be a NULL pointer, in which case the new setting is not reported back. ** </dd> ** ** </dl> */ #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ /* ** CAPI3REF: Enable Or Disable Extended Result Codes ** METHOD: sqlite3 ** ** ^The sqlite3_extended_result_codes() routine enables or disables the ** [extended result codes] feature of SQLite. ^The extended result ** codes are disabled by default for historical compatibility. */ SQLITE_API int SQLITE_APICALL sqlite3_extended_result_codes(sqlite3*, int onoff); /* ** CAPI3REF: Last Insert Rowid ** METHOD: sqlite3 ** ** ^Each entry in most SQLite tables (except for [WITHOUT ROWID] tables) ** has a unique 64-bit signed |
| ︙ | ︙ | |||
1967 1968 1969 1970 1971 1972 1973 | ** If a separate thread performs a new [INSERT] on the same ** database connection while the [sqlite3_last_insert_rowid()] ** function is running and thus changes the last insert [rowid], ** then the value returned by [sqlite3_last_insert_rowid()] is ** unpredictable and might not equal either the old or the new ** last insert [rowid]. */ | | | 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 | ** If a separate thread performs a new [INSERT] on the same ** database connection while the [sqlite3_last_insert_rowid()] ** function is running and thus changes the last insert [rowid], ** then the value returned by [sqlite3_last_insert_rowid()] is ** unpredictable and might not equal either the old or the new ** last insert [rowid]. */ SQLITE_API sqlite3_int64 SQLITE_APICALL sqlite3_last_insert_rowid(sqlite3*); /* ** CAPI3REF: Count The Number Of Rows Modified ** METHOD: sqlite3 ** ** ^This function returns the number of rows modified, inserted or ** deleted by the most recently completed INSERT, UPDATE or DELETE |
| ︙ | ︙ | |||
2020 2021 2022 2023 2024 2025 2026 | ** See also the [sqlite3_total_changes()] interface, the ** [count_changes pragma], and the [changes() SQL function]. ** ** If a separate thread makes changes on the same database connection ** while [sqlite3_changes()] is running then the value returned ** is unpredictable and not meaningful. */ | | | 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 | ** See also the [sqlite3_total_changes()] interface, the ** [count_changes pragma], and the [changes() SQL function]. ** ** If a separate thread makes changes on the same database connection ** while [sqlite3_changes()] is running then the value returned ** is unpredictable and not meaningful. */ SQLITE_API int SQLITE_APICALL sqlite3_changes(sqlite3*); /* ** CAPI3REF: Total Number Of Rows Modified ** METHOD: sqlite3 ** ** ^This function returns the total number of rows inserted, modified or ** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed |
| ︙ | ︙ | |||
2044 2045 2046 2047 2048 2049 2050 | ** See also the [sqlite3_changes()] interface, the ** [count_changes pragma], and the [total_changes() SQL function]. ** ** If a separate thread makes changes on the same database connection ** while [sqlite3_total_changes()] is running then the value ** returned is unpredictable and not meaningful. */ | | | 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 | ** See also the [sqlite3_changes()] interface, the ** [count_changes pragma], and the [total_changes() SQL function]. ** ** If a separate thread makes changes on the same database connection ** while [sqlite3_total_changes()] is running then the value ** returned is unpredictable and not meaningful. */ SQLITE_API int SQLITE_APICALL sqlite3_total_changes(sqlite3*); /* ** CAPI3REF: Interrupt A Long-Running Query ** METHOD: sqlite3 ** ** ^This function causes any pending database operation to abort and ** return at its earliest opportunity. This routine is typically |
| ︙ | ︙ | |||
2084 2085 2086 2087 2088 2089 2090 | ** ^A call to sqlite3_interrupt(D) that occurs when there are no running ** SQL statements is a no-op and has no effect on SQL statements ** that are started after the sqlite3_interrupt() call returns. ** ** If the database connection closes while [sqlite3_interrupt()] ** is running then bad things will likely happen. */ | | | 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 | ** ^A call to sqlite3_interrupt(D) that occurs when there are no running ** SQL statements is a no-op and has no effect on SQL statements ** that are started after the sqlite3_interrupt() call returns. ** ** If the database connection closes while [sqlite3_interrupt()] ** is running then bad things will likely happen. */ SQLITE_API void SQLITE_APICALL sqlite3_interrupt(sqlite3*); /* ** CAPI3REF: Determine If An SQL Statement Is Complete ** ** These routines are useful during command-line input to determine if the ** currently entered text seems to form a complete SQL statement or ** if additional input is needed before sending the text into |
| ︙ | ︙ | |||
2119 2120 2121 2122 2123 2124 2125 | ** ** The input to [sqlite3_complete()] must be a zero-terminated ** UTF-8 string. ** ** The input to [sqlite3_complete16()] must be a zero-terminated ** UTF-16 string in native byte order. */ | | | | 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 |
**
** The input to [sqlite3_complete()] must be a zero-terminated
** UTF-8 string.
**
** The input to [sqlite3_complete16()] must be a zero-terminated
** UTF-16 string in native byte order.
*/
SQLITE_API int SQLITE_APICALL sqlite3_complete(const char *sql);
SQLITE_API int SQLITE_APICALL sqlite3_complete16(const void *sql);
/*
** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
** KEYWORDS: {busy-handler callback} {busy handler}
** METHOD: sqlite3
**
** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X
|
| ︙ | ︙ | |||
2181 2182 2183 2184 2185 2186 2187 | ** database connection that invoked the busy handler. In other words, ** the busy handler is not reentrant. Any such actions ** result in undefined behavior. ** ** A busy handler must not close the database connection ** or [prepared statement] that invoked the busy handler. */ | | | 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 | ** database connection that invoked the busy handler. In other words, ** the busy handler is not reentrant. Any such actions ** result in undefined behavior. ** ** A busy handler must not close the database connection ** or [prepared statement] that invoked the busy handler. */ SQLITE_API int SQLITE_APICALL sqlite3_busy_handler(sqlite3*,int(SQLITE_CALLBACK *)(void*,int),void*); /* ** CAPI3REF: Set A Busy Timeout ** METHOD: sqlite3 ** ** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps ** for a specified amount of time when a table is locked. ^The handler |
| ︙ | ︙ | |||
2204 2205 2206 2207 2208 2209 2210 | ** ^(There can only be a single busy handler for a particular ** [database connection] at any given moment. If another busy handler ** was defined (using [sqlite3_busy_handler()]) prior to calling ** this routine, that other busy handler is cleared.)^ ** ** See also: [PRAGMA busy_timeout] */ | | | 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 | ** ^(There can only be a single busy handler for a particular ** [database connection] at any given moment. If another busy handler ** was defined (using [sqlite3_busy_handler()]) prior to calling ** this routine, that other busy handler is cleared.)^ ** ** See also: [PRAGMA busy_timeout] */ SQLITE_API int SQLITE_APICALL sqlite3_busy_timeout(sqlite3*, int ms); /* ** CAPI3REF: Convenience Routines For Running Queries ** METHOD: sqlite3 ** ** This is a legacy interface that is preserved for backwards compatibility. ** Use of this interface is not recommended. |
| ︙ | ︙ | |||
2279 2280 2281 2282 2283 2284 2285 | ** [sqlite3_exec()]. The sqlite3_get_table() routine does not have access ** to any internal data structures of SQLite. It uses only the public ** interface defined here. As a consequence, errors that occur in the ** wrapper layer outside of the internal [sqlite3_exec()] call are not ** reflected in subsequent calls to [sqlite3_errcode()] or ** [sqlite3_errmsg()]. */ | | | | 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 | ** [sqlite3_exec()]. The sqlite3_get_table() routine does not have access ** to any internal data structures of SQLite. It uses only the public ** interface defined here. As a consequence, errors that occur in the ** wrapper layer outside of the internal [sqlite3_exec()] call are not ** reflected in subsequent calls to [sqlite3_errcode()] or ** [sqlite3_errmsg()]. */ SQLITE_API int SQLITE_APICALL sqlite3_get_table( sqlite3 *db, /* An open database */ const char *zSql, /* SQL to be evaluated */ char ***pazResult, /* Results of the query */ int *pnRow, /* Number of result rows written here */ int *pnColumn, /* Number of result columns written here */ char **pzErrmsg /* Error msg written here */ ); SQLITE_API void SQLITE_APICALL sqlite3_free_table(char **result); /* ** CAPI3REF: Formatted String Printing Functions ** ** These routines are work-alikes of the "printf()" family of functions ** from the standard C library. ** These routines understand most of the common K&R formatting options, |
| ︙ | ︙ | |||
2394 2395 2396 2397 2398 2399 2400 | ** table and column names into a constructed SQL statement. ** ** ^(The "%z" formatting option works like "%s" but with the ** addition that after the string has been read and copied into ** the result, [sqlite3_free()] is called on the input string.)^ */ SQLITE_API char *SQLITE_CDECL sqlite3_mprintf(const char*,...); | | | | 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 | ** table and column names into a constructed SQL statement. ** ** ^(The "%z" formatting option works like "%s" but with the ** addition that after the string has been read and copied into ** the result, [sqlite3_free()] is called on the input string.)^ */ SQLITE_API char *SQLITE_CDECL sqlite3_mprintf(const char*,...); SQLITE_API char *SQLITE_APICALL sqlite3_vmprintf(const char*, va_list); SQLITE_API char *SQLITE_CDECL sqlite3_snprintf(int,char*,const char*, ...); SQLITE_API char *SQLITE_APICALL sqlite3_vsnprintf(int,char*,const char*, va_list); /* ** CAPI3REF: Memory Allocation Subsystem ** ** The SQLite core uses these three routines for all of its own ** internal memory allocation needs. "Core" in the previous sentence ** does not include operating-system specific VFS implementation. The |
| ︙ | ︙ | |||
2486 2487 2488 2489 2490 2491 2492 | ** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have ** not yet been released. ** ** The application must not read or write any part of ** a block of memory after it has been released using ** [sqlite3_free()] or [sqlite3_realloc()]. */ | | | | | | | | 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 | ** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have ** not yet been released. ** ** The application must not read or write any part of ** a block of memory after it has been released using ** [sqlite3_free()] or [sqlite3_realloc()]. */ SQLITE_API void *SQLITE_APICALL sqlite3_malloc(int); SQLITE_API void *SQLITE_APICALL sqlite3_malloc64(sqlite3_uint64); SQLITE_API void *SQLITE_APICALL sqlite3_realloc(void*, int); SQLITE_API void *SQLITE_APICALL sqlite3_realloc64(void*, sqlite3_uint64); SQLITE_API void SQLITE_APICALL sqlite3_free(void*); SQLITE_API sqlite3_uint64 SQLITE_APICALL sqlite3_msize(void*); /* ** CAPI3REF: Memory Allocator Statistics ** ** SQLite provides these two interfaces for reporting on the status ** of the [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()] ** routines, which form the built-in memory allocation subsystem. |
| ︙ | ︙ | |||
2516 2517 2518 2519 2520 2521 2522 | ** ** ^The memory high-water mark is reset to the current value of ** [sqlite3_memory_used()] if and only if the parameter to ** [sqlite3_memory_highwater()] is true. ^The value returned ** by [sqlite3_memory_highwater(1)] is the high-water mark ** prior to the reset. */ | | | | 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 | ** ** ^The memory high-water mark is reset to the current value of ** [sqlite3_memory_used()] if and only if the parameter to ** [sqlite3_memory_highwater()] is true. ^The value returned ** by [sqlite3_memory_highwater(1)] is the high-water mark ** prior to the reset. */ SQLITE_API sqlite3_int64 SQLITE_APICALL sqlite3_memory_used(void); SQLITE_API sqlite3_int64 SQLITE_APICALL sqlite3_memory_highwater(int resetFlag); /* ** CAPI3REF: Pseudo-Random Number Generator ** ** SQLite contains a high-quality pseudo-random number generator (PRNG) used to ** select random [ROWID | ROWIDs] when inserting new records into a table that ** already uses the largest possible [ROWID]. The PRNG is also used for |
| ︙ | ︙ | |||
2540 2541 2542 2543 2544 2545 2546 | ** seeded using randomness obtained from the xRandomness method of ** the default [sqlite3_vfs] object. ** ^If the previous call to this routine had an N of 1 or more and a ** non-NULL P then the pseudo-randomness is generated ** internally and without recourse to the [sqlite3_vfs] xRandomness ** method. */ | | | 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 | ** seeded using randomness obtained from the xRandomness method of ** the default [sqlite3_vfs] object. ** ^If the previous call to this routine had an N of 1 or more and a ** non-NULL P then the pseudo-randomness is generated ** internally and without recourse to the [sqlite3_vfs] xRandomness ** method. */ SQLITE_API void SQLITE_APICALL sqlite3_randomness(int N, void *P); /* ** CAPI3REF: Compile-Time Authorization Callbacks ** METHOD: sqlite3 ** ** ^This routine registers an authorizer callback with a particular ** [database connection], supplied in the first argument. |
| ︙ | ︙ | |||
2623 2624 2625 2626 2627 2628 2629 | ** ** ^Note that the authorizer callback is invoked only during ** [sqlite3_prepare()] or its variants. Authorization is not ** performed during statement evaluation in [sqlite3_step()], unless ** as stated in the previous paragraph, sqlite3_step() invokes ** sqlite3_prepare_v2() to reprepare a statement after a schema change. */ | | | | 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 | ** ** ^Note that the authorizer callback is invoked only during ** [sqlite3_prepare()] or its variants. Authorization is not ** performed during statement evaluation in [sqlite3_step()], unless ** as stated in the previous paragraph, sqlite3_step() invokes ** sqlite3_prepare_v2() to reprepare a statement after a schema change. */ SQLITE_API int SQLITE_APICALL sqlite3_set_authorizer( sqlite3*, int (SQLITE_CALLBACK *xAuth)(void*,int,const char*,const char*,const char*,const char*), void *pUserData ); /* ** CAPI3REF: Authorizer Return Codes ** ** The [sqlite3_set_authorizer | authorizer callback function] must |
| ︙ | ︙ | |||
2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 | #define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */ #define SQLITE_COPY 0 /* No longer used */ #define SQLITE_RECURSIVE 33 /* NULL NULL */ /* ** CAPI3REF: Tracing And Profiling Functions ** METHOD: sqlite3 ** ** These routines register callback functions that can be used for ** tracing and profiling the execution of SQL statements. ** ** ^The callback function registered by sqlite3_trace() is invoked at ** various times when an SQL statement is being run by [sqlite3_step()]. ** ^The sqlite3_trace() callback is invoked with a UTF-8 rendering of the | > > > | 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 | #define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */ #define SQLITE_COPY 0 /* No longer used */ #define SQLITE_RECURSIVE 33 /* NULL NULL */ /* ** CAPI3REF: Tracing And Profiling Functions ** METHOD: sqlite3 ** ** These routines are deprecated. Use the [sqlite3_trace_v2()] interface ** instead of the routines described here. ** ** These routines register callback functions that can be used for ** tracing and profiling the execution of SQL statements. ** ** ^The callback function registered by sqlite3_trace() is invoked at ** various times when an SQL statement is being run by [sqlite3_step()]. ** ^The sqlite3_trace() callback is invoked with a UTF-8 rendering of the |
| ︙ | ︙ | |||
2728 2729 2730 2731 2732 2733 2734 | ** time is in units of nanoseconds, however the current implementation ** is only capable of millisecond resolution so the six least significant ** digits in the time are meaningless. Future versions of SQLite ** might provide greater resolution on the profiler callback. The ** sqlite3_profile() function is considered experimental and is ** subject to change in future versions of SQLite. */ | > | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 | ** time is in units of nanoseconds, however the current implementation ** is only capable of millisecond resolution so the six least significant ** digits in the time are meaningless. Future versions of SQLite ** might provide greater resolution on the profiler callback. The ** sqlite3_profile() function is considered experimental and is ** subject to change in future versions of SQLite. */ SQLITE_API SQLITE_DEPRECATED void *SQLITE_APICALL sqlite3_trace(sqlite3*, void(SQLITE_CALLBACK *xTrace)(void*,const char*), void*); SQLITE_API SQLITE_DEPRECATED void *SQLITE_APICALL sqlite3_profile(sqlite3*, void(SQLITE_CALLBACK *xProfile)(void*,const char*,sqlite3_uint64), void*); /* ** CAPI3REF: SQL Trace Event Codes ** KEYWORDS: SQLITE_TRACE ** ** These constants identify classes of events that can be monitored ** using the [sqlite3_trace_v2()] tracing logic. The third argument ** to [sqlite3_trace_v2()] is an OR-ed combination of one or more of ** the following constants. ^The first argument to the trace callback ** is one of the following constants. ** ** New tracing constants may be added in future releases. ** ** ^A trace callback has four arguments: xCallback(T,C,P,X). ** ^The T argument is one of the integer type codes above. ** ^The C argument is a copy of the context pointer passed in as the ** fourth argument to [sqlite3_trace_v2()]. ** The P and X arguments are pointers whose meanings depend on T. ** ** <dl> ** [[SQLITE_TRACE_STMT]] <dt>SQLITE_TRACE_STMT</dt> ** <dd>^An SQLITE_TRACE_STMT callback is invoked when a prepared statement ** first begins running and possibly at other times during the ** execution of the prepared statement, such as at the start of each ** trigger subprogram. ^The P argument is a pointer to the ** [prepared statement]. ^The X argument is a pointer to a string which ** is the unexpanded SQL text of the prepared statement or an SQL comment ** that indicates the invocation of a trigger. ^The callback can compute ** the same text that would have been returned by the legacy [sqlite3_trace()] ** interface by using the X argument when X begins with "--" and invoking ** [sqlite3_expanded_sql(P)] otherwise. ** ** [[SQLITE_TRACE_PROFILE]] <dt>SQLITE_TRACE_PROFILE</dt> ** <dd>^An SQLITE_TRACE_PROFILE callback provides approximately the same ** information as is provided by the [sqlite3_profile()] callback. ** ^The P argument is a pointer to the [prepared statement] and the ** X argument points to a 64-bit integer which is the estimated of ** the number of nanosecond that the prepared statement took to run. ** ^The SQLITE_TRACE_PROFILE callback is invoked when the statement finishes. ** ** [[SQLITE_TRACE_ROW]] <dt>SQLITE_TRACE_ROW</dt> ** <dd>^An SQLITE_TRACE_ROW callback is invoked whenever a prepared ** statement generates a single row of result. ** ^The P argument is a pointer to the [prepared statement] and the ** X argument is unused. ** ** [[SQLITE_TRACE_CLOSE]] <dt>SQLITE_TRACE_CLOSE</dt> ** <dd>^An SQLITE_TRACE_CLOSE callback is invoked when a database ** connection closes. ** ^The P argument is a pointer to the [database connection] object ** and the X argument is unused. ** </dl> */ #define SQLITE_TRACE_STMT 0x01 #define SQLITE_TRACE_PROFILE 0x02 #define SQLITE_TRACE_ROW 0x04 #define SQLITE_TRACE_CLOSE 0x08 /* ** CAPI3REF: SQL Trace Hook ** METHOD: sqlite3 ** ** ^The sqlite3_trace_v2(D,M,X,P) interface registers a trace callback ** function X against [database connection] D, using property mask M ** and context pointer P. ^If the X callback is ** NULL or if the M mask is zero, then tracing is disabled. The ** M argument should be the bitwise OR-ed combination of ** zero or more [SQLITE_TRACE] constants. ** ** ^Each call to either sqlite3_trace() or sqlite3_trace_v2() overrides ** (cancels) any prior calls to sqlite3_trace() or sqlite3_trace_v2(). ** ** ^The X callback is invoked whenever any of the events identified by ** mask M occur. ^The integer return value from the callback is currently ** ignored, though this may change in future releases. Callback ** implementations should return zero to ensure future compatibility. ** ** ^A trace callback is invoked with four arguments: callback(T,C,P,X). ** ^The T argument is one of the [SQLITE_TRACE] ** constants to indicate why the callback was invoked. ** ^The C argument is a copy of the context pointer. ** The P and X arguments are pointers whose meanings depend on T. ** ** The sqlite3_trace_v2() interface is intended to replace the legacy ** interfaces [sqlite3_trace()] and [sqlite3_profile()], both of which ** are deprecated. */ SQLITE_API int SQLITE_APICALL sqlite3_trace_v2( sqlite3*, unsigned uMask, int(SQLITE_CALLBACK *xCallback)(unsigned,void*,void*,void*), void *pCtx ); /* ** CAPI3REF: Query Progress Callbacks ** METHOD: sqlite3 ** ** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback ** function X to be invoked periodically during long running calls to |
| ︙ | ︙ | |||
2764 2765 2766 2767 2768 2769 2770 | ** ** The progress handler callback must not do anything that will modify ** the database connection that invoked the progress handler. ** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their ** database connections for the meaning of "modify" in this paragraph. ** */ | | | 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 | ** ** The progress handler callback must not do anything that will modify ** the database connection that invoked the progress handler. ** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their ** database connections for the meaning of "modify" in this paragraph. ** */ SQLITE_API void SQLITE_APICALL sqlite3_progress_handler(sqlite3*, int, int(SQLITE_CALLBACK *)(void*), void*); /* ** CAPI3REF: Opening A New Database Connection ** CONSTRUCTOR: sqlite3 ** ** ^These routines open an SQLite database file as specified by the ** filename argument. ^The filename argument is interpreted as UTF-8 for |
| ︙ | ︙ | |||
2993 2994 2995 2996 2997 2998 2999 | ** ** <b>Note to Windows Runtime users:</b> The temporary directory must be set ** prior to calling sqlite3_open() or sqlite3_open_v2(). Otherwise, various ** features that require the use of temporary files may fail. ** ** See also: [sqlite3_temp_directory] */ | | | | | 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 | ** ** <b>Note to Windows Runtime users:</b> The temporary directory must be set ** prior to calling sqlite3_open() or sqlite3_open_v2(). Otherwise, various ** features that require the use of temporary files may fail. ** ** See also: [sqlite3_temp_directory] */ SQLITE_API int SQLITE_APICALL sqlite3_open( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); SQLITE_API int SQLITE_APICALL sqlite3_open16( const void *filename, /* Database filename (UTF-16) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); SQLITE_API int SQLITE_APICALL sqlite3_open_v2( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb, /* OUT: SQLite db handle */ int flags, /* Flags */ const char *zVfs /* Name of VFS module to use */ ); /* |
| ︙ | ︙ | |||
3047 3048 3049 3050 3051 3052 3053 | ** ** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and ** sqlite3_uri_boolean(F,P,B) returns B. If F is not a NULL pointer and ** is not a database file pathname pointer that SQLite passed into the xOpen ** VFS method, then the behavior of this routine is undefined and probably ** undesirable. */ | | | | | 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 | ** ** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and ** sqlite3_uri_boolean(F,P,B) returns B. If F is not a NULL pointer and ** is not a database file pathname pointer that SQLite passed into the xOpen ** VFS method, then the behavior of this routine is undefined and probably ** undesirable. */ SQLITE_API const char *SQLITE_APICALL sqlite3_uri_parameter(const char *zFilename, const char *zParam); SQLITE_API int SQLITE_APICALL sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); SQLITE_API sqlite3_int64 SQLITE_APICALL sqlite3_uri_int64(const char*, const char*, sqlite3_int64); /* ** CAPI3REF: Error Codes And Messages ** METHOD: sqlite3 ** ** ^If the most recent sqlite3_* API call associated with |
| ︙ | ︙ | |||
3093 3094 3095 3096 3097 3098 3099 | ** 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. */ | | | | | | | 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 |
** 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 SQLITE_APICALL sqlite3_errcode(sqlite3 *db);
SQLITE_API int SQLITE_APICALL sqlite3_extended_errcode(sqlite3 *db);
SQLITE_API const char *SQLITE_APICALL sqlite3_errmsg(sqlite3*);
SQLITE_API const void *SQLITE_APICALL sqlite3_errmsg16(sqlite3*);
SQLITE_API const char *SQLITE_APICALL sqlite3_errstr(int);
/*
** 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.
|
| ︙ | ︙ | |||
3165 3166 3167 3168 3169 3170 3171 | ** attack. Developers might also want to use the [sqlite3_set_authorizer()] ** interface to further control untrusted SQL. The size of the database ** created by an untrusted script can be contained using the ** [max_page_count] [PRAGMA]. ** ** New run-time limit categories may be added in future releases. */ | | | 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 |
** attack. Developers might also want to use the [sqlite3_set_authorizer()]
** interface to further control untrusted SQL. The size of the database
** created by an untrusted script can be contained using the
** [max_page_count] [PRAGMA].
**
** New run-time limit categories may be added in future releases.
*/
SQLITE_API int SQLITE_APICALL sqlite3_limit(sqlite3*, int id, int newVal);
/*
** CAPI3REF: Run-Time Limit Categories
** KEYWORDS: {limit category} {*limit categories}
**
** These constants define various performance limits
** that can be lowered at run-time using [sqlite3_limit()].
|
| ︙ | ︙ | |||
3317 3318 3319 3320 3321 3322 3323 | ** ^The specific value of WHERE-clause [parameter] might influence the ** choice of query plan if the parameter is the left-hand side of a [LIKE] ** or [GLOB] operator or if the parameter is compared to an indexed column ** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled. ** </li> ** </ol> */ | | | | | | | | > > > > > > > > > > > > > > > > > > > > > > > | > | 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 | ** ^The specific value of WHERE-clause [parameter] might influence the ** choice of query plan if the parameter is the left-hand side of a [LIKE] ** or [GLOB] operator or if the parameter is compared to an indexed column ** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled. ** </li> ** </ol> */ SQLITE_API int SQLITE_APICALL sqlite3_prepare( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); SQLITE_API int SQLITE_APICALL sqlite3_prepare_v2( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); SQLITE_API int SQLITE_APICALL sqlite3_prepare16( sqlite3 *db, /* Database handle */ const void *zSql, /* SQL statement, UTF-16 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const void **pzTail /* OUT: Pointer to unused portion of zSql */ ); SQLITE_API int SQLITE_APICALL sqlite3_prepare16_v2( sqlite3 *db, /* Database handle */ const void *zSql, /* SQL statement, UTF-16 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const void **pzTail /* OUT: Pointer to unused portion of zSql */ ); /* ** CAPI3REF: Retrieving Statement SQL ** METHOD: sqlite3_stmt ** ** ^The sqlite3_sql(P) interface returns a pointer to a copy of the UTF-8 ** SQL text used to create [prepared statement] P if P was ** created by either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()]. ** ^The sqlite3_expanded_sql(P) interface returns a pointer to a UTF-8 ** string containing the SQL text of prepared statement P with ** [bound parameters] expanded. ** ** ^(For example, if a prepared statement is created using the SQL ** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345 ** and parameter :xyz is unbound, then sqlite3_sql() will return ** the original string, "SELECT $abc,:xyz" but sqlite3_expanded_sql() ** will return "SELECT 2345,NULL".)^ ** ** ^The sqlite3_expanded_sql() interface returns NULL if insufficient memory ** is available to hold the result, or if the result would exceed the ** the maximum string length determined by the [SQLITE_LIMIT_LENGTH]. ** ** ^The [SQLITE_TRACE_SIZE_LIMIT] compile-time option limits the size of ** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time ** option causes sqlite3_expanded_sql() to always return NULL. ** ** ^The string returned by sqlite3_sql(P) is managed by SQLite and is ** automatically freed when the prepared statement is finalized. ** ^The string returned by sqlite3_expanded_sql(P), on the other hand, ** is obtained from [sqlite3_malloc()] and must be free by the application ** by passing it to [sqlite3_free()]. */ SQLITE_API const char *SQLITE_APICALL sqlite3_sql(sqlite3_stmt *pStmt); SQLITE_API char *SQLITE_APICALL sqlite3_expanded_sql(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If An SQL Statement Writes The Database ** METHOD: sqlite3_stmt ** ** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if ** and only if the [prepared statement] X makes no direct changes to |
| ︙ | ︙ | |||
3386 3387 3388 3389 3390 3391 3392 | ** since the statements themselves do not actually modify the database but ** rather they control the timing of when other statements modify the ** database. ^The [ATTACH] and [DETACH] statements also cause ** sqlite3_stmt_readonly() to return true since, while those statements ** change the configuration of a database connection, they do not make ** changes to the content of the database files on disk. */ | | | | 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 |
** since the statements themselves do not actually modify the database but
** rather they control the timing of when other statements modify the
** database. ^The [ATTACH] and [DETACH] statements also cause
** sqlite3_stmt_readonly() to return true since, while those statements
** change the configuration of a database connection, they do not make
** changes to the content of the database files on disk.
*/
SQLITE_API int SQLITE_APICALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Determine If A Prepared Statement Has Been Reset
** METHOD: sqlite3_stmt
**
** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the
** [prepared statement] S has been stepped at least once using
** [sqlite3_step(S)] but has neither run to completion (returned
** [SQLITE_DONE] from [sqlite3_step(S)]) nor
** been reset using [sqlite3_reset(S)]. ^The sqlite3_stmt_busy(S)
** interface returns false if S is a NULL pointer. If S is not a
** NULL pointer and is not a pointer to a valid [prepared statement]
** object, then the behavior is undefined and probably undesirable.
**
** This interface can be used in combination [sqlite3_next_stmt()]
** to locate all prepared statements associated with a database
** connection that are in need of being reset. This can be used,
** for example, in diagnostic routines to search for prepared
** statements that are holding a transaction open.
*/
SQLITE_API int SQLITE_APICALL sqlite3_stmt_busy(sqlite3_stmt*);
/*
** CAPI3REF: Dynamically Typed Value Object
** KEYWORDS: {protected sqlite3_value} {unprotected sqlite3_value}
**
** SQLite uses the sqlite3_value object to represent all values
** that can be stored in a database table. SQLite uses dynamic typing
|
| ︙ | ︙ | |||
3571 3572 3573 3574 3575 3576 3577 | ** [SQLITE_MAX_LENGTH]. ** ^[SQLITE_RANGE] is returned if the parameter ** index is out of range. ^[SQLITE_NOMEM] is returned if malloc() fails. ** ** See also: [sqlite3_bind_parameter_count()], ** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()]. */ | | | | | | | | | | | | | | | | | 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 |
** [SQLITE_MAX_LENGTH].
** ^[SQLITE_RANGE] is returned if the parameter
** index is out of range. ^[SQLITE_NOMEM] is returned if malloc() fails.
**
** See also: [sqlite3_bind_parameter_count()],
** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()].
*/
SQLITE_API int SQLITE_APICALL sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(SQLITE_CALLBACK *)(void*));
SQLITE_API int SQLITE_APICALL sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64,
void(SQLITE_CALLBACK *)(void*));
SQLITE_API int SQLITE_APICALL sqlite3_bind_double(sqlite3_stmt*, int, double);
SQLITE_API int SQLITE_APICALL sqlite3_bind_int(sqlite3_stmt*, int, int);
SQLITE_API int SQLITE_APICALL sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
SQLITE_API int SQLITE_APICALL sqlite3_bind_null(sqlite3_stmt*, int);
SQLITE_API int SQLITE_APICALL sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(SQLITE_CALLBACK *)(void*));
SQLITE_API int SQLITE_APICALL sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(SQLITE_CALLBACK *)(void*));
SQLITE_API int SQLITE_APICALL sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,
void(SQLITE_CALLBACK *)(void*), unsigned char encoding);
SQLITE_API int SQLITE_APICALL sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
SQLITE_API int SQLITE_APICALL sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
SQLITE_API int SQLITE_APICALL sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64);
/*
** CAPI3REF: Number Of SQL Parameters
** METHOD: sqlite3_stmt
**
** ^This routine can be used to find the number of [SQL parameters]
** in a [prepared statement]. SQL parameters are tokens of the
** form "?", "?NNN", ":AAA", "$AAA", or "@AAA" that serve as
** placeholders for values that are [sqlite3_bind_blob | bound]
** to the parameters at a later time.
**
** ^(This routine actually returns the index of the largest (rightmost)
** parameter. For all forms except ?NNN, this will correspond to the
** number of unique parameters. If parameters of the ?NNN form are used,
** there may be gaps in the list.)^
**
** See also: [sqlite3_bind_blob|sqlite3_bind()],
** [sqlite3_bind_parameter_name()], and
** [sqlite3_bind_parameter_index()].
*/
SQLITE_API int SQLITE_APICALL sqlite3_bind_parameter_count(sqlite3_stmt*);
/*
** CAPI3REF: Name Of A Host Parameter
** METHOD: sqlite3_stmt
**
** ^The sqlite3_bind_parameter_name(P,N) interface returns
** the name of the N-th [SQL parameter] in the [prepared statement] P.
|
| ︙ | ︙ | |||
3633 3634 3635 3636 3637 3638 3639 | ** originally specified as UTF-16 in [sqlite3_prepare16()] or ** [sqlite3_prepare16_v2()]. ** ** See also: [sqlite3_bind_blob|sqlite3_bind()], ** [sqlite3_bind_parameter_count()], and ** [sqlite3_bind_parameter_index()]. */ | | | | | | 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 | ** originally specified as UTF-16 in [sqlite3_prepare16()] or ** [sqlite3_prepare16_v2()]. ** ** See also: [sqlite3_bind_blob|sqlite3_bind()], ** [sqlite3_bind_parameter_count()], and ** [sqlite3_bind_parameter_index()]. */ SQLITE_API const char *SQLITE_APICALL sqlite3_bind_parameter_name(sqlite3_stmt*, int); /* ** CAPI3REF: Index Of A Parameter With A Given Name ** METHOD: sqlite3_stmt ** ** ^Return the index of an SQL parameter given its name. ^The ** index value returned is suitable for use as the second ** parameter to [sqlite3_bind_blob|sqlite3_bind()]. ^A zero ** is returned if no matching parameter is found. ^The parameter ** name must be given in UTF-8 even if the original statement ** was prepared from UTF-16 text using [sqlite3_prepare16_v2()]. ** ** See also: [sqlite3_bind_blob|sqlite3_bind()], ** [sqlite3_bind_parameter_count()], and ** [sqlite3_bind_parameter_name()]. */ SQLITE_API int SQLITE_APICALL sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); /* ** CAPI3REF: Reset All Bindings On A Prepared Statement ** METHOD: sqlite3_stmt ** ** ^Contrary to the intuition of many, [sqlite3_reset()] does not reset ** the [sqlite3_bind_blob | bindings] on a [prepared statement]. ** ^Use this routine to reset all host parameters to NULL. */ SQLITE_API int SQLITE_APICALL sqlite3_clear_bindings(sqlite3_stmt*); /* ** CAPI3REF: Number Of Columns In A Result Set ** METHOD: sqlite3_stmt ** ** ^Return the number of columns in the result set returned by the ** [prepared statement]. ^This routine returns 0 if pStmt is an SQL ** statement that does not return data (for example an [UPDATE]). ** ** See also: [sqlite3_data_count()] */ SQLITE_API int SQLITE_APICALL sqlite3_column_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Column Names In A Result Set ** METHOD: sqlite3_stmt ** ** ^These routines return the name assigned to a particular column ** in the result set of a [SELECT] statement. ^The sqlite3_column_name() |
| ︙ | ︙ | |||
3701 3702 3703 3704 3705 3706 3707 | ** NULL pointer is returned. ** ** ^The name of a result column is the value of the "AS" clause for ** that column, if there is an AS clause. If there is no AS clause ** then the name of the column is unspecified and may change from ** one release of SQLite to the next. */ | | | | 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 | ** NULL pointer is returned. ** ** ^The name of a result column is the value of the "AS" clause for ** that column, if there is an AS clause. If there is no AS clause ** then the name of the column is unspecified and may change from ** one release of SQLite to the next. */ SQLITE_API const char *SQLITE_APICALL sqlite3_column_name(sqlite3_stmt*, int N); SQLITE_API const void *SQLITE_APICALL sqlite3_column_name16(sqlite3_stmt*, int N); /* ** CAPI3REF: Source Of Data In A Query Result ** METHOD: sqlite3_stmt ** ** ^These routines provide a means to determine the database, table, and ** table column that is the origin of a particular result column in |
| ︙ | ︙ | |||
3750 3751 3752 3753 3754 3755 3756 | ** undefined. ** ** If two or more threads call one or more ** [sqlite3_column_database_name | column metadata interfaces] ** for the same [prepared statement] and result column ** at the same time then the results are undefined. */ | | | | | | | | 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 | ** undefined. ** ** If two or more threads call one or more ** [sqlite3_column_database_name | column metadata interfaces] ** for the same [prepared statement] and result column ** at the same time then the results are undefined. */ SQLITE_API const char *SQLITE_APICALL sqlite3_column_database_name(sqlite3_stmt*,int); SQLITE_API const void *SQLITE_APICALL sqlite3_column_database_name16(sqlite3_stmt*,int); SQLITE_API const char *SQLITE_APICALL sqlite3_column_table_name(sqlite3_stmt*,int); SQLITE_API const void *SQLITE_APICALL sqlite3_column_table_name16(sqlite3_stmt*,int); SQLITE_API const char *SQLITE_APICALL sqlite3_column_origin_name(sqlite3_stmt*,int); SQLITE_API const void *SQLITE_APICALL sqlite3_column_origin_name16(sqlite3_stmt*,int); /* ** CAPI3REF: Declared Datatype Of A Query Result ** METHOD: sqlite3_stmt ** ** ^(The first parameter is a [prepared statement]. ** If this statement is a [SELECT] statement and the Nth column of the |
| ︙ | ︙ | |||
3787 3788 3789 3790 3791 3792 3793 | ** ^SQLite uses dynamic run-time typing. ^So just because a column ** is declared to contain a particular type does not mean that the ** data stored in that column is of the declared type. SQLite is ** strongly typed, but the typing is dynamic not static. ^Type ** is associated with individual values, not with the containers ** used to hold those values. */ | | | | 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 | ** ^SQLite uses dynamic run-time typing. ^So just because a column ** is declared to contain a particular type does not mean that the ** data stored in that column is of the declared type. SQLite is ** strongly typed, but the typing is dynamic not static. ^Type ** is associated with individual values, not with the containers ** used to hold those values. */ SQLITE_API const char *SQLITE_APICALL sqlite3_column_decltype(sqlite3_stmt*,int); SQLITE_API const void *SQLITE_APICALL sqlite3_column_decltype16(sqlite3_stmt*,int); /* ** CAPI3REF: Evaluate An SQL Statement ** METHOD: sqlite3_stmt ** ** After a [prepared statement] has been prepared using either ** [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or one of the legacy |
| ︙ | ︙ | |||
3868 3869 3870 3871 3872 3873 3874 | ** We admit that this is a goofy design. The problem has been fixed ** with the "v2" interface. If you prepare all of your SQL statements ** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead ** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()] interfaces, ** then the more specific [error codes] are returned directly ** by sqlite3_step(). The use of the "v2" interface is recommended. */ | | | | 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 | ** We admit that this is a goofy design. The problem has been fixed ** with the "v2" interface. If you prepare all of your SQL statements ** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead ** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()] interfaces, ** then the more specific [error codes] are returned directly ** by sqlite3_step(). The use of the "v2" interface is recommended. */ SQLITE_API int SQLITE_APICALL sqlite3_step(sqlite3_stmt*); /* ** CAPI3REF: Number of columns in a result set ** METHOD: sqlite3_stmt ** ** ^The sqlite3_data_count(P) interface returns the number of columns in the ** current row of the result set of [prepared statement] P. ** ^If prepared statement P does not have results ready to return ** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of ** interfaces) then sqlite3_data_count(P) returns 0. ** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer. ** ^The sqlite3_data_count(P) routine returns 0 if the previous call to ** [sqlite3_step](P) returned [SQLITE_DONE]. ^The sqlite3_data_count(P) ** will return non-zero if previous call to [sqlite3_step](P) returned ** [SQLITE_ROW], except in the case of the [PRAGMA incremental_vacuum] ** where it always returns zero since each step of that multi-step ** pragma returns 0 columns of data. ** ** See also: [sqlite3_column_count()] */ SQLITE_API int SQLITE_APICALL sqlite3_data_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Fundamental Datatypes ** KEYWORDS: SQLITE_TEXT ** ** ^(Every value in SQLite has one of five fundamental datatypes: ** |
| ︙ | ︙ | |||
4079 4080 4081 4082 4083 4084 4085 | ** ** ^(If a memory allocation error occurs during the evaluation of any ** of these routines, a default value is returned. The default value ** is either the integer 0, the floating point number 0.0, or a NULL ** pointer. Subsequent calls to [sqlite3_errcode()] will return ** [SQLITE_NOMEM].)^ */ | | | | | | | | | | | | 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 | ** ** ^(If a memory allocation error occurs during the evaluation of any ** of these routines, a default value is returned. The default value ** is either the integer 0, the floating point number 0.0, or a NULL ** pointer. Subsequent calls to [sqlite3_errcode()] will return ** [SQLITE_NOMEM].)^ */ SQLITE_API const void *SQLITE_APICALL sqlite3_column_blob(sqlite3_stmt*, int iCol); SQLITE_API int SQLITE_APICALL sqlite3_column_bytes(sqlite3_stmt*, int iCol); SQLITE_API int SQLITE_APICALL sqlite3_column_bytes16(sqlite3_stmt*, int iCol); SQLITE_API double SQLITE_APICALL sqlite3_column_double(sqlite3_stmt*, int iCol); SQLITE_API int SQLITE_APICALL sqlite3_column_int(sqlite3_stmt*, int iCol); SQLITE_API sqlite3_int64 SQLITE_APICALL sqlite3_column_int64(sqlite3_stmt*, int iCol); SQLITE_API const unsigned char *SQLITE_APICALL sqlite3_column_text(sqlite3_stmt*, int iCol); SQLITE_API const void *SQLITE_APICALL sqlite3_column_text16(sqlite3_stmt*, int iCol); SQLITE_API int SQLITE_APICALL sqlite3_column_type(sqlite3_stmt*, int iCol); SQLITE_API sqlite3_value *SQLITE_APICALL sqlite3_column_value(sqlite3_stmt*, int iCol); /* ** CAPI3REF: Destroy A Prepared Statement Object ** DESTRUCTOR: sqlite3_stmt ** ** ^The sqlite3_finalize() function is called to delete a [prepared statement]. ** ^If the most recent evaluation of the statement encountered no errors |
| ︙ | ︙ | |||
4116 4117 4118 4119 4120 4121 4122 | ** ** The application must finalize every [prepared statement] in order to avoid ** resource leaks. It is a grievous error for the application to try to use ** a prepared statement after it has been finalized. Any use of a prepared ** statement after it has been finalized can result in undefined and ** undesirable behavior such as segfaults and heap corruption. */ | | | 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 | ** ** The application must finalize every [prepared statement] in order to avoid ** resource leaks. It is a grievous error for the application to try to use ** a prepared statement after it has been finalized. Any use of a prepared ** statement after it has been finalized can result in undefined and ** undesirable behavior such as segfaults and heap corruption. */ SQLITE_API int SQLITE_APICALL sqlite3_finalize(sqlite3_stmt *pStmt); /* ** CAPI3REF: Reset A Prepared Statement Object ** METHOD: sqlite3_stmt ** ** The sqlite3_reset() function is called to reset a [prepared statement] ** object back to its initial state, ready to be re-executed. |
| ︙ | ︙ | |||
4143 4144 4145 4146 4147 4148 4149 | ** ^If the most recent call to [sqlite3_step(S)] for the ** [prepared statement] S indicated an error, then ** [sqlite3_reset(S)] returns an appropriate [error code]. ** ** ^The [sqlite3_reset(S)] interface does not change the values ** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. */ | | | 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 |
** ^If the most recent call to [sqlite3_step(S)] for the
** [prepared statement] S indicated an error, then
** [sqlite3_reset(S)] returns an appropriate [error code].
**
** ^The [sqlite3_reset(S)] interface does not change the values
** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S.
*/
SQLITE_API int SQLITE_APICALL sqlite3_reset(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Create Or Redefine SQL Functions
** KEYWORDS: {function creation routines}
** KEYWORDS: {application-defined SQL function}
** KEYWORDS: {application-defined SQL functions}
** METHOD: sqlite3
|
| ︙ | ︙ | |||
4243 4244 4245 4246 4247 4248 4249 | ** ^Built-in functions may be overloaded by new application-defined functions. ** ** ^An application-defined function is permitted to call other ** SQLite interfaces. However, such calls must not ** close the database connection nor finalize or reset the prepared ** statement in which the function is running. */ | | | | | | | | | | | | | | | 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 | ** ^Built-in functions may be overloaded by new application-defined functions. ** ** ^An application-defined function is permitted to call other ** SQLite interfaces. However, such calls must not ** close the database connection nor finalize or reset the prepared ** statement in which the function is running. */ SQLITE_API int SQLITE_APICALL sqlite3_create_function( sqlite3 *db, const char *zFunctionName, int nArg, int eTextRep, void *pApp, void (SQLITE_CALLBACK *xFunc)(sqlite3_context*,int,sqlite3_value**), void (SQLITE_CALLBACK *xStep)(sqlite3_context*,int,sqlite3_value**), void (SQLITE_CALLBACK *xFinal)(sqlite3_context*) ); SQLITE_API int SQLITE_APICALL sqlite3_create_function16( sqlite3 *db, const void *zFunctionName, int nArg, int eTextRep, void *pApp, void (SQLITE_CALLBACK *xFunc)(sqlite3_context*,int,sqlite3_value**), void (SQLITE_CALLBACK *xStep)(sqlite3_context*,int,sqlite3_value**), void (SQLITE_CALLBACK *xFinal)(sqlite3_context*) ); SQLITE_API int SQLITE_APICALL sqlite3_create_function_v2( sqlite3 *db, const char *zFunctionName, int nArg, int eTextRep, void *pApp, void (SQLITE_CALLBACK *xFunc)(sqlite3_context*,int,sqlite3_value**), void (SQLITE_CALLBACK *xStep)(sqlite3_context*,int,sqlite3_value**), void (SQLITE_CALLBACK *xFinal)(sqlite3_context*), void(SQLITE_CALLBACK *xDestroy)(void*) ); /* ** CAPI3REF: Text Encodings ** ** These constant define integer codes that represent the various ** text encodings supported by SQLite. |
| ︙ | ︙ | |||
4309 4310 4311 4312 4313 4314 4315 | ** These functions are [deprecated]. In order to maintain ** backwards compatibility with older code, these functions continue ** to be supported. However, new applications should avoid ** the use of these functions. To encourage programmers to avoid ** these functions, we will not explain what they do. */ #ifndef SQLITE_OMIT_DEPRECATED | | | | | | | | 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 |
** These functions are [deprecated]. In order to maintain
** backwards compatibility with older code, these functions continue
** to be supported. However, new applications should avoid
** the use of these functions. To encourage programmers to avoid
** these functions, we will not explain what they do.
*/
#ifndef SQLITE_OMIT_DEPRECATED
SQLITE_API SQLITE_DEPRECATED int SQLITE_APICALL sqlite3_aggregate_count(sqlite3_context*);
SQLITE_API SQLITE_DEPRECATED int SQLITE_APICALL sqlite3_expired(sqlite3_stmt*);
SQLITE_API SQLITE_DEPRECATED int SQLITE_APICALL sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
SQLITE_API SQLITE_DEPRECATED int SQLITE_APICALL sqlite3_global_recover(void);
SQLITE_API SQLITE_DEPRECATED void SQLITE_APICALL sqlite3_thread_cleanup(void);
SQLITE_API SQLITE_DEPRECATED int SQLITE_APICALL sqlite3_memory_alarm(void(SQLITE_CALLBACK *)(void*,sqlite3_int64,int),
void*,sqlite3_int64);
#endif
/*
** CAPI3REF: Obtaining SQL Values
** METHOD: sqlite3_value
**
|
| ︙ | ︙ | |||
4364 4365 4366 4367 4368 4369 4370 | ** [sqlite3_value_text16()] can be invalidated by a subsequent call to ** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], ** or [sqlite3_value_text16()]. ** ** These routines must be called from the same thread as ** the SQL function that supplied the [sqlite3_value*] parameters. */ | | | | | | | | | | | | | | | | | 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 | ** [sqlite3_value_text16()] can be invalidated by a subsequent call to ** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], ** or [sqlite3_value_text16()]. ** ** These routines must be called from the same thread as ** the SQL function that supplied the [sqlite3_value*] parameters. */ SQLITE_API const void *SQLITE_APICALL sqlite3_value_blob(sqlite3_value*); SQLITE_API int SQLITE_APICALL sqlite3_value_bytes(sqlite3_value*); SQLITE_API int SQLITE_APICALL sqlite3_value_bytes16(sqlite3_value*); SQLITE_API double SQLITE_APICALL sqlite3_value_double(sqlite3_value*); SQLITE_API int SQLITE_APICALL sqlite3_value_int(sqlite3_value*); SQLITE_API sqlite3_int64 SQLITE_APICALL sqlite3_value_int64(sqlite3_value*); SQLITE_API const unsigned char *SQLITE_APICALL sqlite3_value_text(sqlite3_value*); SQLITE_API const void *SQLITE_APICALL sqlite3_value_text16(sqlite3_value*); SQLITE_API const void *SQLITE_APICALL sqlite3_value_text16le(sqlite3_value*); SQLITE_API const void *SQLITE_APICALL sqlite3_value_text16be(sqlite3_value*); SQLITE_API int SQLITE_APICALL sqlite3_value_type(sqlite3_value*); SQLITE_API int SQLITE_APICALL sqlite3_value_numeric_type(sqlite3_value*); /* ** CAPI3REF: Finding The Subtype Of SQL Values ** METHOD: sqlite3_value ** ** The sqlite3_value_subtype(V) function returns the subtype for ** an [application-defined SQL function] argument V. The subtype ** information can be used to pass a limited amount of context from ** one SQL function to another. Use the [sqlite3_result_subtype()] ** routine to set the subtype for the return value of an SQL function. ** ** SQLite makes no use of subtype itself. It merely passes the subtype ** from the result of one [application-defined SQL function] into the ** input of another. */ SQLITE_API unsigned int SQLITE_APICALL sqlite3_value_subtype(sqlite3_value*); /* ** CAPI3REF: Copy And Free SQL Values ** METHOD: sqlite3_value ** ** ^The sqlite3_value_dup(V) interface makes a copy of the [sqlite3_value] ** object D and returns a pointer to that copy. ^The [sqlite3_value] returned ** is a [protected sqlite3_value] object even if the input is not. ** ^The sqlite3_value_dup(V) interface returns NULL if V is NULL or if a ** memory allocation fails. ** ** ^The sqlite3_value_free(V) interface frees an [sqlite3_value] object ** previously obtained from [sqlite3_value_dup()]. ^If V is a NULL pointer ** then sqlite3_value_free(V) is a harmless no-op. */ SQLITE_API sqlite3_value *SQLITE_APICALL sqlite3_value_dup(const sqlite3_value*); SQLITE_API void SQLITE_APICALL sqlite3_value_free(sqlite3_value*); /* ** CAPI3REF: Obtain Aggregate Function Context ** METHOD: sqlite3_context ** ** Implementations of aggregate SQL functions use this ** routine to allocate memory for storing their state. |
| ︙ | ︙ | |||
4453 4454 4455 4456 4457 4458 4459 | ** [sqlite3_context | SQL function context] that is the first parameter ** to the xStep or xFinal callback routine that implements the aggregate ** function. ** ** This routine must be called from the same thread in which ** the aggregate SQL function is running. */ | | | | | 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 | ** [sqlite3_context | SQL function context] that is the first parameter ** to the xStep or xFinal callback routine that implements the aggregate ** function. ** ** This routine must be called from the same thread in which ** the aggregate SQL function is running. */ SQLITE_API void *SQLITE_APICALL sqlite3_aggregate_context(sqlite3_context*, int nBytes); /* ** CAPI3REF: User Data For Functions ** METHOD: sqlite3_context ** ** ^The sqlite3_user_data() interface returns a copy of ** the pointer that was the pUserData parameter (the 5th parameter) ** of the [sqlite3_create_function()] ** and [sqlite3_create_function16()] routines that originally ** registered the application defined function. ** ** This routine must be called from the same thread in which ** the application-defined function is running. */ SQLITE_API void *SQLITE_APICALL sqlite3_user_data(sqlite3_context*); /* ** CAPI3REF: Database Connection For Functions ** METHOD: sqlite3_context ** ** ^The sqlite3_context_db_handle() interface returns a copy of ** the pointer to the [database connection] (the 1st parameter) ** of the [sqlite3_create_function()] ** and [sqlite3_create_function16()] routines that originally ** registered the application defined function. */ SQLITE_API sqlite3 *SQLITE_APICALL sqlite3_context_db_handle(sqlite3_context*); /* ** CAPI3REF: Function Auxiliary Data ** METHOD: sqlite3_context ** ** These functions may be used by (non-aggregate) SQL functions to ** associate metadata with argument values. If the same value is passed to |
| ︙ | ︙ | |||
4533 4534 4535 4536 4537 4538 4539 | ** ^(In practice, metadata is preserved between function calls for ** function parameters that are compile-time constants, including literal ** values and [parameters] and expressions composed from the same.)^ ** ** These routines must be called from the same thread in which ** the SQL function is running. */ | | | | | 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 | ** ^(In practice, metadata is preserved between function calls for ** function parameters that are compile-time constants, including literal ** values and [parameters] and expressions composed from the same.)^ ** ** These routines must be called from the same thread in which ** the SQL function is running. */ SQLITE_API void *SQLITE_APICALL sqlite3_get_auxdata(sqlite3_context*, int N); SQLITE_API void SQLITE_APICALL sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (SQLITE_CALLBACK *)(void*)); /* ** CAPI3REF: Constants Defining Special Destructor Behavior ** ** These are special values for the destructor that is passed in as the ** final argument to routines like [sqlite3_result_blob()]. ^If the destructor ** argument is SQLITE_STATIC, it means that the content pointer is constant ** and will never change. It does not need to be destroyed. ^The ** SQLITE_TRANSIENT value means that the content will likely change in ** the near future and that SQLite should make its own private copy of ** the content before returning. ** ** The typedef is necessary to work around problems in certain ** C++ compilers. */ typedef void (SQLITE_CALLBACK *sqlite3_destructor_type)(void*); #define SQLITE_STATIC ((sqlite3_destructor_type)0) #define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1) /* ** CAPI3REF: Setting The Result Of An SQL Function ** METHOD: sqlite3_context ** |
| ︙ | ︙ | |||
4670 4671 4672 4673 4674 4675 4676 | ** [unprotected sqlite3_value] object is required, so either ** kind of [sqlite3_value] object can be used with this interface. ** ** If these routines are called from within the different thread ** than the one containing the application-defined function that received ** the [sqlite3_context] pointer, the results are undefined. */ | | | | | | | | | | | | | | | | | | | | | | | | 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 |
** [unprotected sqlite3_value] object is required, so either
** kind of [sqlite3_value] object can be used with this interface.
**
** If these routines are called from within the different thread
** than the one containing the application-defined function that received
** the [sqlite3_context] pointer, the results are undefined.
*/
SQLITE_API void SQLITE_APICALL sqlite3_result_blob(sqlite3_context*, const void*, int, void(SQLITE_CALLBACK *)(void*));
SQLITE_API void SQLITE_APICALL sqlite3_result_blob64(sqlite3_context*,const void*,
sqlite3_uint64,void(SQLITE_CALLBACK *)(void*));
SQLITE_API void SQLITE_APICALL sqlite3_result_double(sqlite3_context*, double);
SQLITE_API void SQLITE_APICALL sqlite3_result_error(sqlite3_context*, const char*, int);
SQLITE_API void SQLITE_APICALL sqlite3_result_error16(sqlite3_context*, const void*, int);
SQLITE_API void SQLITE_APICALL sqlite3_result_error_toobig(sqlite3_context*);
SQLITE_API void SQLITE_APICALL sqlite3_result_error_nomem(sqlite3_context*);
SQLITE_API void SQLITE_APICALL sqlite3_result_error_code(sqlite3_context*, int);
SQLITE_API void SQLITE_APICALL sqlite3_result_int(sqlite3_context*, int);
SQLITE_API void SQLITE_APICALL sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
SQLITE_API void SQLITE_APICALL sqlite3_result_null(sqlite3_context*);
SQLITE_API void SQLITE_APICALL sqlite3_result_text(sqlite3_context*, const char*, int, void(SQLITE_CALLBACK *)(void*));
SQLITE_API void SQLITE_APICALL sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64,
void(SQLITE_CALLBACK *)(void*), unsigned char encoding);
SQLITE_API void SQLITE_APICALL sqlite3_result_text16(sqlite3_context*, const void*, int, void(SQLITE_CALLBACK *)(void*));
SQLITE_API void SQLITE_APICALL sqlite3_result_text16le(sqlite3_context*, const void*, int,void(SQLITE_CALLBACK *)(void*));
SQLITE_API void SQLITE_APICALL sqlite3_result_text16be(sqlite3_context*, const void*, int,void(SQLITE_CALLBACK *)(void*));
SQLITE_API void SQLITE_APICALL sqlite3_result_value(sqlite3_context*, sqlite3_value*);
SQLITE_API void SQLITE_APICALL sqlite3_result_zeroblob(sqlite3_context*, int n);
SQLITE_API int SQLITE_APICALL sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n);
/*
** CAPI3REF: Setting The Subtype Of An SQL Function
** METHOD: sqlite3_context
**
** The sqlite3_result_subtype(C,T) function causes the subtype of
** the result from the [application-defined SQL function] with
** [sqlite3_context] C to be the value T. Only the lower 8 bits
** of the subtype T are preserved in current versions of SQLite;
** higher order bits are discarded.
** The number of subtype bytes preserved by SQLite might increase
** in future releases of SQLite.
*/
SQLITE_API void SQLITE_APICALL sqlite3_result_subtype(sqlite3_context*,unsigned int);
/*
** CAPI3REF: Define New Collating Sequences
** METHOD: sqlite3
**
** ^These functions add, remove, or modify a [collation] associated
** with the [database connection] specified as the first argument.
|
| ︙ | ︙ | |||
4787 4788 4789 4790 4791 4792 4793 | ** themselves rather than expecting SQLite to deal with it for them. ** This is different from every other SQLite interface. The inconsistency ** is unfortunate but cannot be changed without breaking backwards ** compatibility. ** ** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()]. */ | | | | | | | | | 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 | ** themselves rather than expecting SQLite to deal with it for them. ** This is different from every other SQLite interface. The inconsistency ** is unfortunate but cannot be changed without breaking backwards ** compatibility. ** ** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()]. */ SQLITE_API int SQLITE_APICALL sqlite3_create_collation( sqlite3*, const char *zName, int eTextRep, void *pArg, int(SQLITE_CALLBACK *xCompare)(void*,int,const void*,int,const void*) ); SQLITE_API int SQLITE_APICALL sqlite3_create_collation_v2( sqlite3*, const char *zName, int eTextRep, void *pArg, int(SQLITE_CALLBACK *xCompare)(void*,int,const void*,int,const void*), void(SQLITE_CALLBACK *xDestroy)(void*) ); SQLITE_API int SQLITE_APICALL sqlite3_create_collation16( sqlite3*, const void *zName, int eTextRep, void *pArg, int(SQLITE_CALLBACK *xCompare)(void*,int,const void*,int,const void*) ); /* ** CAPI3REF: Collation Needed Callbacks ** METHOD: sqlite3 ** ** ^To avoid having to register all collation sequences before a database |
| ︙ | ︙ | |||
4837 4838 4839 4840 4841 4842 4843 | ** sequence function required. The fourth parameter is the name of the ** required collation sequence.)^ ** ** The callback function should register the desired collation using ** [sqlite3_create_collation()], [sqlite3_create_collation16()], or ** [sqlite3_create_collation_v2()]. */ | | | | | | | | | | | | 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 | ** sequence function required. The fourth parameter is the name of the ** required collation sequence.)^ ** ** The callback function should register the desired collation using ** [sqlite3_create_collation()], [sqlite3_create_collation16()], or ** [sqlite3_create_collation_v2()]. */ SQLITE_API int SQLITE_APICALL sqlite3_collation_needed( sqlite3*, void*, void(SQLITE_CALLBACK *)(void*,sqlite3*,int eTextRep,const char*) ); SQLITE_API int SQLITE_APICALL sqlite3_collation_needed16( sqlite3*, void*, void(SQLITE_CALLBACK *)(void*,sqlite3*,int eTextRep,const void*) ); #ifdef SQLITE_HAS_CODEC /* ** Specify the key for an encrypted database. This routine should be ** called right after sqlite3_open(). ** ** The code to implement this API is not available in the public release ** of SQLite. */ SQLITE_API int SQLITE_APICALL sqlite3_key( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The key */ ); SQLITE_API int SQLITE_APICALL sqlite3_key_v2( sqlite3 *db, /* Database to be rekeyed */ const char *zDbName, /* Name of the database */ const void *pKey, int nKey /* The key */ ); /* ** Change the key on an open database. If the current database is not ** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the ** database is decrypted. ** ** The code to implement this API is not available in the public release ** of SQLite. */ SQLITE_API int SQLITE_APICALL sqlite3_rekey( sqlite3 *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The new key */ ); SQLITE_API int SQLITE_APICALL sqlite3_rekey_v2( sqlite3 *db, /* Database to be rekeyed */ const char *zDbName, /* Name of the database */ const void *pKey, int nKey /* The new key */ ); /* ** Specify the activation key for a SEE database. Unless ** activated, none of the SEE routines will work. */ SQLITE_API void SQLITE_APICALL sqlite3_activate_see( const char *zPassPhrase /* Activation phrase */ ); #endif #ifdef SQLITE_ENABLE_CEROD /* ** Specify the activation key for a CEROD database. Unless ** activated, none of the CEROD routines will work. */ SQLITE_API void SQLITE_APICALL sqlite3_activate_cerod( const char *zPassPhrase /* Activation phrase */ ); #endif /* ** CAPI3REF: Suspend Execution For A Short Time ** |
| ︙ | ︙ | |||
4920 4921 4922 4923 4924 4925 4926 | ** ** ^SQLite implements this interface by calling the xSleep() ** method of the default [sqlite3_vfs] object. If the xSleep() method ** of the default VFS is not implemented correctly, or not implemented at ** all, then the behavior of sqlite3_sleep() may deviate from the description ** in the previous paragraphs. */ | | | 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 | ** ** ^SQLite implements this interface by calling the xSleep() ** method of the default [sqlite3_vfs] object. If the xSleep() method ** of the default VFS is not implemented correctly, or not implemented at ** all, then the behavior of sqlite3_sleep() may deviate from the description ** in the previous paragraphs. */ SQLITE_API int SQLITE_APICALL sqlite3_sleep(int); /* ** CAPI3REF: Name Of The Folder Holding Temporary Files ** ** ^(If this global variable is made to point to a string which is ** the name of a folder (a.k.a. directory), then all temporary files ** created by SQLite when using a built-in [sqlite3_vfs | VFS] |
| ︙ | ︙ | |||
5039 5040 5041 5042 5043 5044 5045 | ** find out whether SQLite automatically rolled back the transaction after ** an error is to use this function. ** ** If another thread changes the autocommit status of the database ** connection while this routine is running, then the return value ** is undefined. */ | | | | | | | 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 | ** find out whether SQLite automatically rolled back the transaction after ** an error is to use this function. ** ** If another thread changes the autocommit status of the database ** connection while this routine is running, then the return value ** is undefined. */ SQLITE_API int SQLITE_APICALL sqlite3_get_autocommit(sqlite3*); /* ** CAPI3REF: Find The Database Handle Of A Prepared Statement ** METHOD: sqlite3_stmt ** ** ^The sqlite3_db_handle interface returns the [database connection] handle ** to which a [prepared statement] belongs. ^The [database connection] ** returned by sqlite3_db_handle is the same [database connection] ** that was the first argument ** to the [sqlite3_prepare_v2()] call (or its variants) that was used to ** create the statement in the first place. */ SQLITE_API sqlite3 *SQLITE_APICALL sqlite3_db_handle(sqlite3_stmt*); /* ** CAPI3REF: Return The Filename For A Database Connection ** METHOD: sqlite3 ** ** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename ** associated with database N of connection D. ^The main database file ** has the name "main". If there is no attached database N on the database ** connection D, or if database N is a temporary or in-memory database, then ** a NULL pointer is returned. ** ** ^The filename returned by this function is the output of the ** xFullPathname method of the [VFS]. ^In other words, the filename ** will be an absolute pathname, even if the filename used ** to open the database originally was a URI or relative pathname. */ SQLITE_API const char *SQLITE_APICALL sqlite3_db_filename(sqlite3 *db, const char *zDbName); /* ** CAPI3REF: Determine if a database is read-only ** METHOD: sqlite3 ** ** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N ** of connection D is read-only, 0 if it is read/write, or -1 if N is not ** the name of a database on connection D. */ SQLITE_API int SQLITE_APICALL sqlite3_db_readonly(sqlite3 *db, const char *zDbName); /* ** CAPI3REF: Find the next prepared statement ** METHOD: sqlite3 ** ** ^This interface returns a pointer to the next [prepared statement] after ** pStmt associated with the [database connection] pDb. ^If pStmt is NULL ** then this interface returns a pointer to the first prepared statement ** associated with the database connection pDb. ^If no prepared statement ** satisfies the conditions of this routine, it returns NULL. ** ** The [database connection] pointer D in a call to ** [sqlite3_next_stmt(D,S)] must refer to an open database ** connection and in particular must not be a NULL pointer. */ SQLITE_API sqlite3_stmt *SQLITE_APICALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); /* ** CAPI3REF: Commit And Rollback Notification Callbacks ** METHOD: sqlite3 ** ** ^The sqlite3_commit_hook() interface registers a callback ** function to be invoked whenever a transaction is [COMMIT | committed]. |
| ︙ | ︙ | |||
5144 5145 5146 5147 5148 5149 5150 | ** rolled back if an explicit "ROLLBACK" statement is executed, or ** an error or constraint causes an implicit rollback to occur. ** ^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. */ | | | | | 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 | ** rolled back if an explicit "ROLLBACK" statement is executed, or ** an error or constraint causes an implicit rollback to occur. ** ^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 *SQLITE_APICALL sqlite3_commit_hook(sqlite3*, int(SQLITE_CALLBACK *)(void*), void*); SQLITE_API void *SQLITE_APICALL sqlite3_rollback_hook(sqlite3*, void(SQLITE_CALLBACK *)(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 ** to be invoked whenever a row is updated, inserted or deleted in ** a [rowid table]. ** ^Any callback set by a previous call to this function ** for the same database connection is overridden. ** ** ^The second argument is a pointer to the function to invoke when a ** row is updated, inserted or deleted in a rowid table. ** ^The first argument to the callback is a copy of the third argument ** to sqlite3_update_hook(). |
| ︙ | ︙ | |||
5193 5194 5195 5196 5197 5198 5199 | ** database connections for the meaning of "modify" in this paragraph. ** ** ^The sqlite3_update_hook(D,C,P) function ** returns the P argument from the previous call ** on the same [database connection] D, or NULL for ** the first call on D. ** | | | | | | 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 | ** database connections for the meaning of "modify" in this paragraph. ** ** ^The sqlite3_update_hook(D,C,P) function ** returns the P argument from the previous call ** on the same [database connection] D, or NULL for ** the first call on D. ** ** See also the [sqlite3_commit_hook()], [sqlite3_rollback_hook()], ** and [sqlite3_preupdate_hook()] interfaces. */ SQLITE_API void *SQLITE_APICALL sqlite3_update_hook( sqlite3*, void(SQLITE_CALLBACK *)(void *,int ,char const *,char const *,sqlite3_int64), void* ); /* ** CAPI3REF: Enable Or Disable Shared Pager Cache ** ** ^(This routine enables or disables the sharing of the database cache |
| ︙ | ︙ | |||
5236 5237 5238 5239 5240 5241 5242 | ** [sqlite3_open_v2()] with [SQLITE_OPEN_SHAREDCACHE]. ** ** This interface is threadsafe on processors where writing a ** 32-bit integer is atomic. ** ** See Also: [SQLite Shared-Cache Mode] */ | | | | | 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 | ** [sqlite3_open_v2()] with [SQLITE_OPEN_SHAREDCACHE]. ** ** This interface is threadsafe on processors where writing a ** 32-bit integer is atomic. ** ** See Also: [SQLite Shared-Cache Mode] */ SQLITE_API int SQLITE_APICALL sqlite3_enable_shared_cache(int); /* ** CAPI3REF: Attempt To Free Heap Memory ** ** ^The sqlite3_release_memory() interface attempts to free N bytes ** of heap memory by deallocating non-essential memory allocations ** held by the database library. Memory used to cache database ** pages to improve performance is an example of non-essential memory. ** ^sqlite3_release_memory() returns the number of bytes actually freed, ** which might be more or less than the amount requested. ** ^The sqlite3_release_memory() routine is a no-op returning zero ** if SQLite is not compiled with [SQLITE_ENABLE_MEMORY_MANAGEMENT]. ** ** See also: [sqlite3_db_release_memory()] */ SQLITE_API int SQLITE_APICALL sqlite3_release_memory(int); /* ** CAPI3REF: Free Memory Used By A Database Connection ** METHOD: sqlite3 ** ** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap ** memory as possible from database connection D. Unlike the ** [sqlite3_release_memory()] interface, this interface is in effect even ** when the [SQLITE_ENABLE_MEMORY_MANAGEMENT] compile-time option is ** omitted. ** ** See also: [sqlite3_release_memory()] */ SQLITE_API int SQLITE_APICALL sqlite3_db_release_memory(sqlite3*); /* ** CAPI3REF: Impose A Limit On Heap Size ** ** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the ** soft limit on the amount of heap memory that may be allocated by SQLite. ** ^SQLite strives to keep heap memory utilization below the soft heap |
| ︙ | ︙ | |||
5318 5319 5320 5321 5322 5323 5324 | ** the page cache is the predominate memory user in SQLite, most ** applications will achieve adequate soft heap limit enforcement without ** the use of [SQLITE_ENABLE_MEMORY_MANAGEMENT]. ** ** The circumstances under which SQLite will enforce the soft heap limit may ** changes in future releases of SQLite. */ | | | | 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 | ** the page cache is the predominate memory user in SQLite, most ** applications will achieve adequate soft heap limit enforcement without ** the use of [SQLITE_ENABLE_MEMORY_MANAGEMENT]. ** ** The circumstances under which SQLite will enforce the soft heap limit may ** changes in future releases of SQLite. */ SQLITE_API sqlite3_int64 SQLITE_APICALL sqlite3_soft_heap_limit64(sqlite3_int64 N); /* ** CAPI3REF: Deprecated Soft Heap Limit Interface ** DEPRECATED ** ** This is a deprecated version of the [sqlite3_soft_heap_limit64()] ** interface. This routine is provided for historical compatibility ** only. All new applications should use the ** [sqlite3_soft_heap_limit64()] interface rather than this one. */ SQLITE_API SQLITE_DEPRECATED void SQLITE_APICALL sqlite3_soft_heap_limit(int N); /* ** CAPI3REF: Extract Metadata About A Column Of A Table ** METHOD: sqlite3 ** ** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns |
| ︙ | ︙ | |||
5399 5400 5401 5402 5403 5404 5405 | ** auto increment: 0 ** </pre>)^ ** ** ^This function causes all database schemas to be read from disk and ** parsed, if that has not already been done, and returns an error if ** any errors are encountered while loading the schema. */ | | | 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 | ** auto increment: 0 ** </pre>)^ ** ** ^This function causes all database schemas to be read from disk and ** parsed, if that has not already been done, and returns an error if ** any errors are encountered while loading the schema. */ SQLITE_API int SQLITE_APICALL sqlite3_table_column_metadata( sqlite3 *db, /* Connection handle */ const char *zDbName, /* Database name or NULL */ const char *zTableName, /* Table name */ const char *zColumnName, /* Column name */ char const **pzDataType, /* OUTPUT: Declared data type */ char const **pzCollSeq, /* OUTPUT: Collation sequence name */ int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ |
| ︙ | ︙ | |||
5441 5442 5443 5444 5445 5446 5447 | ** ^If an error occurs and pzErrMsg is not 0, then the ** [sqlite3_load_extension()] interface shall attempt to ** fill *pzErrMsg with error message text stored in memory ** obtained from [sqlite3_malloc()]. The calling function ** should free this memory by calling [sqlite3_free()]. ** ** ^Extension loading must be enabled using | | > > > > > > > > > | > > > > > > > > > > > | | | 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 | ** ^If an error occurs and pzErrMsg is not 0, then the ** [sqlite3_load_extension()] interface shall attempt to ** fill *pzErrMsg with error message text stored in memory ** obtained from [sqlite3_malloc()]. The calling function ** should free this memory by calling [sqlite3_free()]. ** ** ^Extension loading must be enabled using ** [sqlite3_enable_load_extension()] or ** [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],1,NULL) ** prior to calling this API, ** otherwise an error will be returned. ** ** <b>Security warning:</b> It is recommended that the ** [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method be used to enable only this ** interface. The use of the [sqlite3_enable_load_extension()] interface ** should be avoided. This will keep the SQL function [load_extension()] ** disabled and prevent SQL injections from giving attackers ** access to extension loading capabilities. ** ** See also the [load_extension() SQL function]. */ SQLITE_API int SQLITE_APICALL sqlite3_load_extension( sqlite3 *db, /* Load the extension into this database connection */ const char *zFile, /* Name of the shared library containing extension */ const char *zProc, /* Entry point. Derived from zFile if 0 */ char **pzErrMsg /* Put error message here if not 0 */ ); /* ** CAPI3REF: Enable Or Disable Extension Loading ** METHOD: sqlite3 ** ** ^So as not to open security holes in older applications that are ** unprepared to deal with [extension loading], and as a means of disabling ** [extension loading] while evaluating user-entered SQL, the following API ** is provided to turn the [sqlite3_load_extension()] mechanism on and off. ** ** ^Extension loading is off by default. ** ^Call the sqlite3_enable_load_extension() routine with onoff==1 ** to turn extension loading on and call it with onoff==0 to turn ** it back off again. ** ** ^This interface enables or disables both the C-API ** [sqlite3_load_extension()] and the SQL function [load_extension()]. ** Use [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],..) ** to enable or disable only the C-API. ** ** <b>Security warning:</b> It is recommended that extension loading ** be disabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method ** rather than this interface, so the [load_extension()] SQL function ** remains disabled. This will prevent SQL injections from giving attackers ** access to extension loading capabilities. */ SQLITE_API int SQLITE_APICALL sqlite3_enable_load_extension(sqlite3 *db, int onoff); /* ** CAPI3REF: Automatically Load Statically Linked Extensions ** ** ^This interface causes the xEntryPoint() function to be invoked for ** each new [database connection] that is created. The idea here is that ** xEntryPoint() is the entry point for a statically linked [SQLite extension] ** that is to be automatically loaded into all new database connections. ** ** ^(Even though the function prototype shows that xEntryPoint() takes ** no arguments and returns void, SQLite invokes xEntryPoint() with three ** arguments and expects an integer result as if the signature of the ** entry point where as follows: ** ** <blockquote><pre> ** int xEntryPoint( ** sqlite3 *db, ** const char **pzErrMsg, ** const struct sqlite3_api_routines *pThunk |
| ︙ | ︙ | |||
5505 5506 5507 5508 5509 5510 5511 | ** ^Calling sqlite3_auto_extension(X) with an entry point X that is already ** on the list of automatic extensions is a harmless no-op. ^No entry point ** will be called more than once for each database connection that is opened. ** ** See also: [sqlite3_reset_auto_extension()] ** and [sqlite3_cancel_auto_extension()] */ | | | | | 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 | ** ^Calling sqlite3_auto_extension(X) with an entry point X that is already ** on the list of automatic extensions is a harmless no-op. ^No entry point ** will be called more than once for each database connection that is opened. ** ** See also: [sqlite3_reset_auto_extension()] ** and [sqlite3_cancel_auto_extension()] */ SQLITE_API int SQLITE_APICALL sqlite3_auto_extension(void(SQLITE_CALLBACK *xEntryPoint)(void)); /* ** CAPI3REF: Cancel Automatic Extension Loading ** ** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the ** initialization routine X that was registered using a prior call to ** [sqlite3_auto_extension(X)]. ^The [sqlite3_cancel_auto_extension(X)] ** routine returns 1 if initialization routine X was successfully ** unregistered and it returns 0 if X was not on the list of initialization ** routines. */ SQLITE_API int SQLITE_APICALL sqlite3_cancel_auto_extension(void(SQLITE_CALLBACK *xEntryPoint)(void)); /* ** CAPI3REF: Reset Automatic Extension Loading ** ** ^This interface disables all automatic extensions previously ** registered using [sqlite3_auto_extension()]. */ SQLITE_API void SQLITE_APICALL sqlite3_reset_auto_extension(void); /* ** The interface to the virtual-table mechanism is currently considered ** to be experimental. The interface might change in incompatible ways. ** If this is a problem for you, do not use the interface at this time. ** ** When the virtual-table mechanism stabilizes, we will declare the |
| ︙ | ︙ | |||
5562 5563 5564 5565 5566 5567 5568 |
** ^The registration remains valid until it is replaced by a different
** module or until the [database connection] closes. The content
** of this structure must not change while it is registered with
** any database connection.
*/
struct sqlite3_module {
int iVersion;
| | | | | | | | | | | | | | | | | | | | | | | | | 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 |
** ^The registration remains valid until it is replaced by a different
** module or until the [database connection] closes. The content
** of this structure must not change while it is registered with
** any database connection.
*/
struct sqlite3_module {
int iVersion;
int (SQLITE_CALLBACK *xCreate)(sqlite3*, void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVTab, char**);
int (SQLITE_CALLBACK *xConnect)(sqlite3*, void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVTab, char**);
int (SQLITE_CALLBACK *xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*);
int (SQLITE_CALLBACK *xDisconnect)(sqlite3_vtab *pVTab);
int (SQLITE_CALLBACK *xDestroy)(sqlite3_vtab *pVTab);
int (SQLITE_CALLBACK *xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);
int (SQLITE_CALLBACK *xClose)(sqlite3_vtab_cursor*);
int (SQLITE_CALLBACK *xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr,
int argc, sqlite3_value **argv);
int (SQLITE_CALLBACK *xNext)(sqlite3_vtab_cursor*);
int (SQLITE_CALLBACK *xEof)(sqlite3_vtab_cursor*);
int (SQLITE_CALLBACK *xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int);
int (SQLITE_CALLBACK *xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid);
int (SQLITE_CALLBACK *xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *);
int (SQLITE_CALLBACK *xBegin)(sqlite3_vtab *pVTab);
int (SQLITE_CALLBACK *xSync)(sqlite3_vtab *pVTab);
int (SQLITE_CALLBACK *xCommit)(sqlite3_vtab *pVTab);
int (SQLITE_CALLBACK *xRollback)(sqlite3_vtab *pVTab);
int (SQLITE_CALLBACK *xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
void (SQLITE_CALLBACK **pxFunc)(sqlite3_context*,int,sqlite3_value**),
void **ppArg);
int (SQLITE_CALLBACK *xRename)(sqlite3_vtab *pVtab, const char *zNew);
/* The methods above are in version 1 of the sqlite_module object. Those
** below are for version 2 and greater. */
int (SQLITE_CALLBACK *xSavepoint)(sqlite3_vtab *pVTab, int);
int (SQLITE_CALLBACK *xRelease)(sqlite3_vtab *pVTab, int);
int (SQLITE_CALLBACK *xRollbackTo)(sqlite3_vtab *pVTab, int);
};
/*
** CAPI3REF: Virtual Table Indexing Information
** KEYWORDS: sqlite3_index_info
**
** The sqlite3_index_info structure and its substructures is used as part
|
| ︙ | ︙ | |||
5770 5771 5772 5773 5774 5775 5776 | ** invoke the destructor function (if it is not NULL) when SQLite ** no longer needs the pClientData pointer. ^The destructor will also ** be invoked if the call to sqlite3_create_module_v2() fails. ** ^The sqlite3_create_module() ** interface is equivalent to sqlite3_create_module_v2() with a NULL ** destructor. */ | | | | | 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 | ** invoke the destructor function (if it is not NULL) when SQLite ** no longer needs the pClientData pointer. ^The destructor will also ** be invoked if the call to sqlite3_create_module_v2() fails. ** ^The sqlite3_create_module() ** interface is equivalent to sqlite3_create_module_v2() with a NULL ** destructor. */ SQLITE_API int SQLITE_APICALL sqlite3_create_module( sqlite3 *db, /* SQLite connection to register module with */ const char *zName, /* Name of the module */ const sqlite3_module *p, /* Methods for the module */ void *pClientData /* Client data for xCreate/xConnect */ ); SQLITE_API int SQLITE_APICALL sqlite3_create_module_v2( sqlite3 *db, /* SQLite connection to register module with */ const char *zName, /* Name of the module */ const sqlite3_module *p, /* Methods for the module */ void *pClientData, /* Client data for xCreate/xConnect */ void(SQLITE_CALLBACK *xDestroy)(void*) /* Module destructor function */ ); /* ** CAPI3REF: Virtual Table Instance Object ** KEYWORDS: sqlite3_vtab ** ** Every [virtual table module] implementation uses a subclass |
| ︙ | ︙ | |||
5839 5840 5841 5842 5843 5844 5845 | ** CAPI3REF: Declare The Schema Of A Virtual Table ** ** ^The [xCreate] and [xConnect] methods of a ** [virtual table module] call this interface ** to declare the format (the names and datatypes of the columns) of ** the virtual tables they implement. */ | | | | 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 | ** CAPI3REF: Declare The Schema Of A Virtual Table ** ** ^The [xCreate] and [xConnect] methods of a ** [virtual table module] call this interface ** to declare the format (the names and datatypes of the columns) of ** the virtual tables they implement. */ SQLITE_API int SQLITE_APICALL sqlite3_declare_vtab(sqlite3*, const char *zSQL); /* ** CAPI3REF: Overload A Function For A Virtual Table ** METHOD: sqlite3 ** ** ^(Virtual tables can provide alternative implementations of functions ** using the [xFindFunction] method of the [virtual table module]. ** But global versions of those functions ** must exist in order to be overloaded.)^ ** ** ^(This API makes sure a global version of a function with a particular ** name and number of parameters exists. If no such function exists ** before this API is called, a new function is created.)^ ^The implementation ** of the new function always causes an exception to be thrown. So ** the new function is not good for anything by itself. Its only ** purpose is to be a placeholder function that can be overloaded ** by a [virtual table]. */ SQLITE_API int SQLITE_APICALL sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); /* ** The interface to the virtual-table mechanism defined above (back up ** to a comment remarkably similar to this one) is currently considered ** to be experimental. The interface might change in incompatible ways. ** If this is a problem for you, do not use the interface at this time. ** |
| ︙ | ︙ | |||
5957 5958 5959 5960 5961 5962 5963 | ** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces ** and the built-in [zeroblob] SQL function may be used to create a ** zero-filled blob to read or write using the incremental-blob interface. ** ** To avoid a resource leak, every open [BLOB handle] should eventually ** be released by a call to [sqlite3_blob_close()]. */ | | | 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 | ** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces ** and the built-in [zeroblob] SQL function may be used to create a ** zero-filled blob to read or write using the incremental-blob interface. ** ** To avoid a resource leak, every open [BLOB handle] should eventually ** be released by a call to [sqlite3_blob_close()]. */ SQLITE_API int SQLITE_APICALL sqlite3_blob_open( sqlite3*, const char *zDb, const char *zTable, const char *zColumn, sqlite3_int64 iRow, int flags, sqlite3_blob **ppBlob |
| ︙ | ︙ | |||
5990 5991 5992 5993 5994 5995 5996 | ** ^All subsequent calls to [sqlite3_blob_read()], [sqlite3_blob_write()] or ** [sqlite3_blob_reopen()] on an aborted blob handle immediately return ** SQLITE_ABORT. ^Calling [sqlite3_blob_bytes()] on an aborted blob handle ** always returns zero. ** ** ^This function sets the database handle error code and message. */ | | | 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 | ** ^All subsequent calls to [sqlite3_blob_read()], [sqlite3_blob_write()] or ** [sqlite3_blob_reopen()] on an aborted blob handle immediately return ** SQLITE_ABORT. ^Calling [sqlite3_blob_bytes()] on an aborted blob handle ** always returns zero. ** ** ^This function sets the database handle error code and message. */ SQLITE_API int SQLITE_APICALL sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); /* ** CAPI3REF: Close A BLOB Handle ** DESTRUCTOR: sqlite3_blob ** ** ^This function closes an open [BLOB handle]. ^(The BLOB handle is closed ** unconditionally. Even if this routine returns an error code, the |
| ︙ | ︙ | |||
6013 6014 6015 6016 6017 6018 6019 | ** Calling this function with an argument that is not a NULL pointer or an ** open blob handle results in undefined behaviour. ^Calling this routine ** with a null pointer (such as would be returned by a failed call to ** [sqlite3_blob_open()]) is a harmless no-op. ^Otherwise, if this function ** is passed a valid open blob handle, the values returned by the ** sqlite3_errcode() and sqlite3_errmsg() functions are set before returning. */ | | | | 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 | ** Calling this function with an argument that is not a NULL pointer or an ** open blob handle results in undefined behaviour. ^Calling this routine ** with a null pointer (such as would be returned by a failed call to ** [sqlite3_blob_open()]) is a harmless no-op. ^Otherwise, if this function ** is passed a valid open blob handle, the values returned by the ** sqlite3_errcode() and sqlite3_errmsg() functions are set before returning. */ SQLITE_API int SQLITE_APICALL sqlite3_blob_close(sqlite3_blob *); /* ** CAPI3REF: Return The Size Of An Open BLOB ** METHOD: sqlite3_blob ** ** ^Returns the size in bytes of the BLOB accessible via the ** successfully opened [BLOB handle] in its only argument. ^The ** incremental blob I/O routines can only read or overwriting existing ** blob content; they cannot change the size of a blob. ** ** This routine only works on a [BLOB handle] which has been created ** by a prior successful call to [sqlite3_blob_open()] and which has not ** been closed by [sqlite3_blob_close()]. Passing any other pointer in ** to this routine results in undefined and probably undesirable behavior. */ SQLITE_API int SQLITE_APICALL sqlite3_blob_bytes(sqlite3_blob *); /* ** CAPI3REF: Read Data From A BLOB Incrementally ** METHOD: sqlite3_blob ** ** ^(This function is used to read data from an open [BLOB handle] into a ** caller-supplied buffer. N bytes of data are copied into buffer Z |
| ︙ | ︙ | |||
6058 6059 6060 6061 6062 6063 6064 | ** This routine only works on a [BLOB handle] which has been created ** by a prior successful call to [sqlite3_blob_open()] and which has not ** been closed by [sqlite3_blob_close()]. Passing any other pointer in ** to this routine results in undefined and probably undesirable behavior. ** ** See also: [sqlite3_blob_write()]. */ | | | 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 | ** This routine only works on a [BLOB handle] which has been created ** by a prior successful call to [sqlite3_blob_open()] and which has not ** been closed by [sqlite3_blob_close()]. Passing any other pointer in ** to this routine results in undefined and probably undesirable behavior. ** ** See also: [sqlite3_blob_write()]. */ SQLITE_API int SQLITE_APICALL sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); /* ** CAPI3REF: Write Data Into A BLOB Incrementally ** METHOD: sqlite3_blob ** ** ^(This function is used to write data into an open [BLOB handle] from a ** caller-supplied buffer. N bytes of data are copied from the buffer Z |
| ︙ | ︙ | |||
6100 6101 6102 6103 6104 6105 6106 | ** This routine only works on a [BLOB handle] which has been created ** by a prior successful call to [sqlite3_blob_open()] and which has not ** been closed by [sqlite3_blob_close()]. Passing any other pointer in ** to this routine results in undefined and probably undesirable behavior. ** ** See also: [sqlite3_blob_read()]. */ | | | 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 | ** This routine only works on a [BLOB handle] which has been created ** by a prior successful call to [sqlite3_blob_open()] and which has not ** been closed by [sqlite3_blob_close()]. Passing any other pointer in ** to this routine results in undefined and probably undesirable behavior. ** ** See also: [sqlite3_blob_read()]. */ SQLITE_API int SQLITE_APICALL sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); /* ** CAPI3REF: Virtual File System Objects ** ** A virtual filesystem (VFS) is an [sqlite3_vfs] object ** that SQLite uses to interact ** with the underlying operating system. Most SQLite builds come with a |
| ︙ | ︙ | |||
6131 6132 6133 6134 6135 6136 6137 | ** VFS is registered with a name that is NULL or an empty string, ** then the behavior is undefined. ** ** ^Unregister a VFS with the sqlite3_vfs_unregister() interface. ** ^(If the default VFS is unregistered, another VFS is chosen as ** the default. The choice for the new VFS is arbitrary.)^ */ | | | | | 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 | ** VFS is registered with a name that is NULL or an empty string, ** then the behavior is undefined. ** ** ^Unregister a VFS with the sqlite3_vfs_unregister() interface. ** ^(If the default VFS is unregistered, another VFS is chosen as ** the default. The choice for the new VFS is arbitrary.)^ */ SQLITE_API sqlite3_vfs *SQLITE_APICALL sqlite3_vfs_find(const char *zVfsName); SQLITE_API int SQLITE_APICALL sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); SQLITE_API int SQLITE_APICALL sqlite3_vfs_unregister(sqlite3_vfs*); /* ** CAPI3REF: Mutexes ** ** The SQLite core uses these routines for thread ** synchronization. Though they are intended for internal ** use by SQLite, code that links against SQLite is |
| ︙ | ︙ | |||
6249 6250 6251 6252 6253 6254 6255 | ** ** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or ** sqlite3_mutex_leave() is a NULL pointer, then all three routines ** behave as no-ops. ** ** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. */ | | | | | | | 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 | ** ** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or ** sqlite3_mutex_leave() is a NULL pointer, then all three routines ** behave as no-ops. ** ** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. */ SQLITE_API sqlite3_mutex *SQLITE_APICALL sqlite3_mutex_alloc(int); SQLITE_API void SQLITE_APICALL sqlite3_mutex_free(sqlite3_mutex*); SQLITE_API void SQLITE_APICALL sqlite3_mutex_enter(sqlite3_mutex*); SQLITE_API int SQLITE_APICALL sqlite3_mutex_try(sqlite3_mutex*); SQLITE_API void SQLITE_APICALL sqlite3_mutex_leave(sqlite3_mutex*); /* ** CAPI3REF: Mutex Methods Object ** ** An instance of this structure defines the low-level routines ** used to allocate and use mutexes. ** |
| ︙ | ︙ | |||
6322 6323 6324 6325 6326 6327 6328 |
** ^SQLite will invoke the xMutexEnd() method when [sqlite3_shutdown()] is
** called, but only if the prior call to xMutexInit returned SQLITE_OK.
** If xMutexInit fails in any way, it is expected to clean up after itself
** prior to returning.
*/
typedef struct sqlite3_mutex_methods sqlite3_mutex_methods;
struct sqlite3_mutex_methods {
| | | | | | | | | | | 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 |
** ^SQLite will invoke the xMutexEnd() method when [sqlite3_shutdown()] is
** called, but only if the prior call to xMutexInit returned SQLITE_OK.
** If xMutexInit fails in any way, it is expected to clean up after itself
** prior to returning.
*/
typedef struct sqlite3_mutex_methods sqlite3_mutex_methods;
struct sqlite3_mutex_methods {
int (SQLITE_CALLBACK *xMutexInit)(void);
int (SQLITE_CALLBACK *xMutexEnd)(void);
sqlite3_mutex *(SQLITE_CALLBACK *xMutexAlloc)(int);
void (SQLITE_CALLBACK *xMutexFree)(sqlite3_mutex *);
void (SQLITE_CALLBACK *xMutexEnter)(sqlite3_mutex *);
int (SQLITE_CALLBACK *xMutexTry)(sqlite3_mutex *);
void (SQLITE_CALLBACK *xMutexLeave)(sqlite3_mutex *);
int (SQLITE_CALLBACK *xMutexHeld)(sqlite3_mutex *);
int (SQLITE_CALLBACK *xMutexNotheld)(sqlite3_mutex *);
};
/*
** CAPI3REF: Mutex Verification Routines
**
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines
** are intended for use inside assert() statements. The SQLite core
|
| ︙ | ︙ | |||
6363 6364 6365 6366 6367 6368 6369 | ** the reason the mutex does not exist is because the build is not ** using mutexes. And we do not want the assert() containing the ** call to sqlite3_mutex_held() to fail, so a non-zero return is ** the appropriate thing to do. The sqlite3_mutex_notheld() ** interface should also return 1 when given a NULL pointer. */ #ifndef NDEBUG | | | | 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 | ** the reason the mutex does not exist is because the build is not ** using mutexes. And we do not want the assert() containing the ** call to sqlite3_mutex_held() to fail, so a non-zero return is ** the appropriate thing to do. The sqlite3_mutex_notheld() ** interface should also return 1 when given a NULL pointer. */ #ifndef NDEBUG SQLITE_API int SQLITE_APICALL sqlite3_mutex_held(sqlite3_mutex*); SQLITE_API int SQLITE_APICALL sqlite3_mutex_notheld(sqlite3_mutex*); #endif /* ** CAPI3REF: Mutex Types ** ** The [sqlite3_mutex_alloc()] interface takes a single argument ** which is one of these integer constants. |
| ︙ | ︙ | |||
6404 6405 6406 6407 6408 6409 6410 | ** ** ^This interface returns a pointer the [sqlite3_mutex] object that ** serializes access to the [database connection] given in the argument ** when the [threading mode] is Serialized. ** ^If the [threading mode] is Single-thread or Multi-thread then this ** routine returns a NULL pointer. */ | | | 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 | ** ** ^This interface returns a pointer the [sqlite3_mutex] object that ** serializes access to the [database connection] given in the argument ** when the [threading mode] is Serialized. ** ^If the [threading mode] is Single-thread or Multi-thread then this ** routine returns a NULL pointer. */ SQLITE_API sqlite3_mutex *SQLITE_APICALL sqlite3_db_mutex(sqlite3*); /* ** CAPI3REF: Low-Level Control Of Database Files ** METHOD: sqlite3 ** ** ^The [sqlite3_file_control()] interface makes a direct call to the ** xFileControl method for the [sqlite3_io_methods] object associated |
| ︙ | ︙ | |||
6439 6440 6441 6442 6443 6444 6445 | ** or [sqlite3_errmsg()]. The underlying xFileControl method might ** also return SQLITE_ERROR. There is no way to distinguish between ** an incorrect zDbName and an SQLITE_ERROR return from the underlying ** xFileControl method. ** ** See also: [SQLITE_FCNTL_LOCKSTATE] */ | | | 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 | ** or [sqlite3_errmsg()]. The underlying xFileControl method might ** also return SQLITE_ERROR. There is no way to distinguish between ** an incorrect zDbName and an SQLITE_ERROR return from the underlying ** xFileControl method. ** ** See also: [SQLITE_FCNTL_LOCKSTATE] */ SQLITE_API int SQLITE_APICALL sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); /* ** CAPI3REF: Testing Interface ** ** ^The sqlite3_test_control() interface is used to read out internal ** state of SQLite and to inject faults into SQLite for testing ** purposes. ^The first parameter is an operation code that determines |
| ︙ | ︙ | |||
6521 6522 6523 6524 6525 6526 6527 | ** ** If either the current value or the highwater mark is too large to ** be represented by a 32-bit integer, then the values returned by ** sqlite3_status() are undefined. ** ** See also: [sqlite3_db_status()] */ | | | | 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 | ** ** If either the current value or the highwater mark is too large to ** be represented by a 32-bit integer, then the values returned by ** sqlite3_status() are undefined. ** ** See also: [sqlite3_db_status()] */ SQLITE_API int SQLITE_APICALL sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); SQLITE_API int SQLITE_APICALL sqlite3_status64( int op, sqlite3_int64 *pCurrent, sqlite3_int64 *pHighwater, int resetFlag ); |
| ︙ | ︙ | |||
6647 6648 6649 6650 6651 6652 6653 | ** reset back down to the current value. ** ** ^The sqlite3_db_status() routine returns SQLITE_OK on success and a ** non-zero [error code] on failure. ** ** See also: [sqlite3_status()] and [sqlite3_stmt_status()]. */ | | | 6855 6856 6857 6858 6859 6860 6861 6862 6863 6864 6865 6866 6867 6868 6869 |
** reset back down to the current value.
**
** ^The sqlite3_db_status() routine returns SQLITE_OK on success and a
** non-zero [error code] on failure.
**
** See also: [sqlite3_status()] and [sqlite3_stmt_status()].
*/
SQLITE_API int SQLITE_APICALL sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
/*
** CAPI3REF: Status Parameters for database connections
** KEYWORDS: {SQLITE_DBSTATUS options}
**
** These constants are the available integer "verbs" that can be passed as
** the second argument to the [sqlite3_db_status()] interface.
|
| ︙ | ︙ | |||
6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 | ** the current value is always zero.)^ ** ** [[SQLITE_DBSTATUS_CACHE_USED]] ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt> ** <dd>This parameter returns the approximate number of bytes of heap ** memory used by all pager caches associated with the database connection.)^ ** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0. ** ** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt> ** <dd>This parameter returns the approximate number of bytes of heap ** memory used to store the schema for all databases associated ** with the connection - main, temp, and any [ATTACH]-ed databases.)^ ** ^The full amount of memory used by the schemas is reported, even if the ** schema memory is shared with other database connections due to ** [shared cache mode] being enabled. | > > > > > > > > > > > > | 6901 6902 6903 6904 6905 6906 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 | ** the current value is always zero.)^ ** ** [[SQLITE_DBSTATUS_CACHE_USED]] ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt> ** <dd>This parameter returns the approximate number of bytes of heap ** memory used by all pager caches associated with the database connection.)^ ** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0. ** ** [[SQLITE_DBSTATUS_CACHE_USED_SHARED]] ** ^(<dt>SQLITE_DBSTATUS_CACHE_USED_SHARED</dt> ** <dd>This parameter is similar to DBSTATUS_CACHE_USED, except that if a ** pager cache is shared between two or more connections the bytes of heap ** memory used by that pager cache is divided evenly between the attached ** connections.)^ In other words, if none of the pager caches associated ** with the database connection are shared, this request returns the same ** value as DBSTATUS_CACHE_USED. Or, if one or more or the pager caches are ** shared, the value returned by this call will be smaller than that returned ** by DBSTATUS_CACHE_USED. ^The highwater mark associated with ** SQLITE_DBSTATUS_CACHE_USED_SHARED is always 0. ** ** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt> ** <dd>This parameter returns the approximate number of bytes of heap ** memory used to store the schema for all databases associated ** with the connection - main, temp, and any [ATTACH]-ed databases.)^ ** ^The full amount of memory used by the schemas is reported, even if the ** schema memory is shared with other database connections due to ** [shared cache mode] being enabled. |
| ︙ | ︙ | |||
6750 6751 6752 6753 6754 6755 6756 | #define SQLITE_DBSTATUS_LOOKASIDE_HIT 4 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 #define SQLITE_DBSTATUS_CACHE_HIT 7 #define SQLITE_DBSTATUS_CACHE_MISS 8 #define SQLITE_DBSTATUS_CACHE_WRITE 9 #define SQLITE_DBSTATUS_DEFERRED_FKS 10 | > | | 6970 6971 6972 6973 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 | #define SQLITE_DBSTATUS_LOOKASIDE_HIT 4 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 #define SQLITE_DBSTATUS_CACHE_HIT 7 #define SQLITE_DBSTATUS_CACHE_MISS 8 #define SQLITE_DBSTATUS_CACHE_WRITE 9 #define SQLITE_DBSTATUS_DEFERRED_FKS 10 #define SQLITE_DBSTATUS_CACHE_USED_SHARED 11 #define SQLITE_DBSTATUS_MAX 11 /* Largest defined DBSTATUS */ /* ** CAPI3REF: Prepared Statement Status ** METHOD: sqlite3_stmt ** ** ^(Each prepared statement maintains various |
| ︙ | ︙ | |||
6777 6778 6779 6780 6781 6782 6783 | ** to be interrogated.)^ ** ^The current value of the requested counter is returned. ** ^If the resetFlg is true, then the counter is reset to zero after this ** interface call returns. ** ** See also: [sqlite3_status()] and [sqlite3_db_status()]. */ | | | 6998 6999 7000 7001 7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 |
** to be interrogated.)^
** ^The current value of the requested counter is returned.
** ^If the resetFlg is true, then the counter is reset to zero after this
** interface call returns.
**
** See also: [sqlite3_status()] and [sqlite3_db_status()].
*/
SQLITE_API int SQLITE_APICALL sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
/*
** CAPI3REF: Status Parameters for prepared statements
** KEYWORDS: {SQLITE_STMTSTATUS counter} {SQLITE_STMTSTATUS counters}
**
** These preprocessor macros define integer codes that name counter
** values associated with the [sqlite3_stmt_status()] interface.
|
| ︙ | ︙ | |||
7013 7014 7015 7016 7017 7018 7019 |
** is not obligated to free any memory, but well-behaved implementations should
** do their best.
*/
typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2;
struct sqlite3_pcache_methods2 {
int iVersion;
void *pArg;
| | | | | | | | | | | | | | | | | | | | | | | 7234 7235 7236 7237 7238 7239 7240 7241 7242 7243 7244 7245 7246 7247 7248 7249 7250 7251 7252 7253 7254 7255 7256 7257 7258 7259 7260 7261 7262 7263 7264 7265 7266 7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 |
** is not obligated to free any memory, but well-behaved implementations should
** do their best.
*/
typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2;
struct sqlite3_pcache_methods2 {
int iVersion;
void *pArg;
int (SQLITE_CALLBACK *xInit)(void*);
void (SQLITE_CALLBACK *xShutdown)(void*);
sqlite3_pcache *(SQLITE_CALLBACK *xCreate)(int szPage, int szExtra, int bPurgeable);
void (SQLITE_CALLBACK *xCachesize)(sqlite3_pcache*, int nCachesize);
int (SQLITE_CALLBACK *xPagecount)(sqlite3_pcache*);
sqlite3_pcache_page *(SQLITE_CALLBACK *xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
void (SQLITE_CALLBACK *xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard);
void (SQLITE_CALLBACK *xRekey)(sqlite3_pcache*, sqlite3_pcache_page*,
unsigned oldKey, unsigned newKey);
void (SQLITE_CALLBACK *xTruncate)(sqlite3_pcache*, unsigned iLimit);
void (SQLITE_CALLBACK *xDestroy)(sqlite3_pcache*);
void (SQLITE_CALLBACK *xShrink)(sqlite3_pcache*);
};
/*
** This is the obsolete pcache_methods object that has now been replaced
** by sqlite3_pcache_methods2. This object is not used by SQLite. It is
** retained in the header file for backwards compatibility only.
*/
typedef struct sqlite3_pcache_methods sqlite3_pcache_methods;
struct sqlite3_pcache_methods {
void *pArg;
int (SQLITE_CALLBACK *xInit)(void*);
void (SQLITE_CALLBACK *xShutdown)(void*);
sqlite3_pcache *(SQLITE_CALLBACK *xCreate)(int szPage, int bPurgeable);
void (SQLITE_CALLBACK *xCachesize)(sqlite3_pcache*, int nCachesize);
int (SQLITE_CALLBACK *xPagecount)(sqlite3_pcache*);
void *(SQLITE_CALLBACK *xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
void (SQLITE_CALLBACK *xUnpin)(sqlite3_pcache*, void*, int discard);
void (SQLITE_CALLBACK *xRekey)(sqlite3_pcache*, void*, unsigned oldKey, unsigned newKey);
void (SQLITE_CALLBACK *xTruncate)(sqlite3_pcache*, unsigned iLimit);
void (SQLITE_CALLBACK *xDestroy)(sqlite3_pcache*);
};
/*
** CAPI3REF: Online Backup Object
**
** The sqlite3_backup object records state information about an ongoing
|
| ︙ | ︙ | |||
7104 7105 7106 7107 7108 7109 7110 | ** ^The S and M arguments passed to ** sqlite3_backup_init(D,N,S,M) identify the [database connection] ** and database name of the source database, respectively. ** ^The source and destination [database connections] (parameters S and D) ** must be different or else sqlite3_backup_init(D,N,S,M) will fail with ** an error. ** | | | 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338 7339 | ** ^The S and M arguments passed to ** sqlite3_backup_init(D,N,S,M) identify the [database connection] ** and database name of the source database, respectively. ** ^The source and destination [database connections] (parameters S and D) ** must be different or else sqlite3_backup_init(D,N,S,M) will fail with ** an error. ** ** ^A call to sqlite3_backup_init() will fail, returning NULL, if ** there is already a read or read-write transaction open on the ** destination database. ** ** ^If an error occurs within sqlite3_backup_init(D,N,S,M), then NULL is ** returned and an error code and error message are stored in the ** destination [database connection] D. ** ^The error code and message for the failed call to sqlite3_backup_init() |
| ︙ | ︙ | |||
7246 7247 7248 7249 7250 7251 7252 | ** The [sqlite3_backup] object itself is partially threadsafe. Multiple ** threads may safely make multiple concurrent calls to sqlite3_backup_step(). ** However, the sqlite3_backup_remaining() and sqlite3_backup_pagecount() ** APIs are not strictly speaking threadsafe. If they are invoked at the ** same time as another thread is invoking sqlite3_backup_step() it is ** possible that they return invalid values. */ | | | | | | | 7467 7468 7469 7470 7471 7472 7473 7474 7475 7476 7477 7478 7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489 7490 | ** The [sqlite3_backup] object itself is partially threadsafe. Multiple ** threads may safely make multiple concurrent calls to sqlite3_backup_step(). ** However, the sqlite3_backup_remaining() and sqlite3_backup_pagecount() ** APIs are not strictly speaking threadsafe. If they are invoked at the ** same time as another thread is invoking sqlite3_backup_step() it is ** possible that they return invalid values. */ SQLITE_API sqlite3_backup *SQLITE_APICALL sqlite3_backup_init( sqlite3 *pDest, /* Destination database handle */ const char *zDestName, /* Destination database name */ sqlite3 *pSource, /* Source database handle */ const char *zSourceName /* Source database name */ ); SQLITE_API int SQLITE_APICALL sqlite3_backup_step(sqlite3_backup *p, int nPage); SQLITE_API int SQLITE_APICALL sqlite3_backup_finish(sqlite3_backup *p); SQLITE_API int SQLITE_APICALL sqlite3_backup_remaining(sqlite3_backup *p); SQLITE_API int SQLITE_APICALL sqlite3_backup_pagecount(sqlite3_backup *p); /* ** CAPI3REF: Unlock Notification ** METHOD: sqlite3 ** ** ^When running in shared-cache mode, a database operation may fail with ** an [SQLITE_LOCKED] error if the required locks on the shared-cache or |
| ︙ | ︙ | |||
7372 7373 7374 7375 7376 7377 7378 | ** ** One way around this problem is to check the extended error code returned ** by an sqlite3_step() call. ^(If there is a blocking connection, then the ** extended error code is set to SQLITE_LOCKED_SHAREDCACHE. Otherwise, in ** the special "DROP TABLE/INDEX" case, the extended error code is just ** SQLITE_LOCKED.)^ */ | | | | | | | 7593 7594 7595 7596 7597 7598 7599 7600 7601 7602 7603 7604 7605 7606 7607 7608 7609 7610 7611 7612 7613 7614 7615 7616 7617 7618 7619 7620 7621 7622 7623 7624 7625 7626 7627 7628 7629 7630 7631 7632 7633 7634 7635 7636 7637 7638 7639 7640 | ** ** One way around this problem is to check the extended error code returned ** by an sqlite3_step() call. ^(If there is a blocking connection, then the ** extended error code is set to SQLITE_LOCKED_SHAREDCACHE. Otherwise, in ** the special "DROP TABLE/INDEX" case, the extended error code is just ** SQLITE_LOCKED.)^ */ SQLITE_API int SQLITE_APICALL sqlite3_unlock_notify( sqlite3 *pBlocked, /* Waiting connection */ void (SQLITE_CALLBACK *xNotify)(void **apArg, int nArg), /* Callback function to invoke */ void *pNotifyArg /* Argument to pass to xNotify */ ); /* ** CAPI3REF: String Comparison ** ** ^The [sqlite3_stricmp()] and [sqlite3_strnicmp()] APIs allow applications ** and extensions to compare the contents of two buffers containing UTF-8 ** strings in a case-independent fashion, using the same definition of "case ** independence" that SQLite uses internally when comparing identifiers. */ SQLITE_API int SQLITE_APICALL sqlite3_stricmp(const char *, const char *); SQLITE_API int SQLITE_APICALL sqlite3_strnicmp(const char *, const char *, int); /* ** CAPI3REF: String Globbing * ** ^The [sqlite3_strglob(P,X)] interface returns zero if and only if ** string X matches the [GLOB] pattern P. ** ^The definition of [GLOB] pattern matching used in ** [sqlite3_strglob(P,X)] is the same as for the "X GLOB P" operator in the ** SQL dialect understood by SQLite. ^The [sqlite3_strglob(P,X)] function ** is case sensitive. ** ** Note that this routine returns zero on a match and non-zero if the strings ** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()]. ** ** See also: [sqlite3_strlike()]. */ SQLITE_API int SQLITE_APICALL sqlite3_strglob(const char *zGlob, const char *zStr); /* ** CAPI3REF: String LIKE Matching * ** ^The [sqlite3_strlike(P,X,E)] interface returns zero if and only if ** string X matches the [LIKE] pattern P with escape character E. ** ^The definition of [LIKE] pattern matching used in |
| ︙ | ︙ | |||
7428 7429 7430 7431 7432 7433 7434 | ** only ASCII characters are case folded. ** ** Note that this routine returns zero on a match and non-zero if the strings ** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()]. ** ** See also: [sqlite3_strglob()]. */ | | | 7649 7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660 7661 7662 7663 | ** only ASCII characters are case folded. ** ** Note that this routine returns zero on a match and non-zero if the strings ** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()]. ** ** See also: [sqlite3_strglob()]. */ SQLITE_API int SQLITE_APICALL sqlite3_strlike(const char *zGlob, const char *zStr, unsigned int cEsc); /* ** CAPI3REF: Error Logging Interface ** ** ^The [sqlite3_log()] interface writes a message into the [error log] ** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()]. ** ^If logging is enabled, the zFormat string and subsequent arguments are |
| ︙ | ︙ | |||
7485 7486 7487 7488 7489 7490 7491 | ** are undefined. ** ** A single database handle may have at most a single write-ahead log callback ** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any ** previously registered write-ahead log callback. ^Note that the ** [sqlite3_wal_autocheckpoint()] interface and the ** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will | | | | | 7706 7707 7708 7709 7710 7711 7712 7713 7714 7715 7716 7717 7718 7719 7720 7721 7722 7723 7724 | ** are undefined. ** ** A single database handle may have at most a single write-ahead log callback ** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any ** previously registered write-ahead log callback. ^Note that the ** [sqlite3_wal_autocheckpoint()] interface and the ** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will ** overwrite any prior [sqlite3_wal_hook()] settings. */ SQLITE_API void *SQLITE_APICALL sqlite3_wal_hook( sqlite3*, int(SQLITE_CALLBACK *)(void *,sqlite3*,const char*,int), void* ); /* ** CAPI3REF: Configure an auto-checkpoint ** METHOD: sqlite3 ** |
| ︙ | ︙ | |||
7522 7523 7524 7525 7526 7527 7528 | ** ** ^Every new [database connection] defaults to having the auto-checkpoint ** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT] ** pages. The use of this interface ** is only necessary if the default setting is found to be suboptimal ** for a particular application. */ | | | 7743 7744 7745 7746 7747 7748 7749 7750 7751 7752 7753 7754 7755 7756 7757 | ** ** ^Every new [database connection] defaults to having the auto-checkpoint ** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT] ** pages. The use of this interface ** is only necessary if the default setting is found to be suboptimal ** for a particular application. */ SQLITE_API int SQLITE_APICALL sqlite3_wal_autocheckpoint(sqlite3 *db, int N); /* ** CAPI3REF: Checkpoint a database ** METHOD: sqlite3 ** ** ^(The sqlite3_wal_checkpoint(D,X) is equivalent to ** [sqlite3_wal_checkpoint_v2](D,X,[SQLITE_CHECKPOINT_PASSIVE],0,0).)^ |
| ︙ | ︙ | |||
7544 7545 7546 7547 7548 7549 7550 | ** This interface used to be the only way to cause a checkpoint to ** occur. But then the newer and more powerful [sqlite3_wal_checkpoint_v2()] ** interface was added. This interface is retained for backwards ** compatibility and as a convenience for applications that need to manually ** start a callback but which do not need the full power (and corresponding ** complication) of [sqlite3_wal_checkpoint_v2()]. */ | | | 7765 7766 7767 7768 7769 7770 7771 7772 7773 7774 7775 7776 7777 7778 7779 | ** This interface used to be the only way to cause a checkpoint to ** occur. But then the newer and more powerful [sqlite3_wal_checkpoint_v2()] ** interface was added. This interface is retained for backwards ** compatibility and as a convenience for applications that need to manually ** start a callback but which do not need the full power (and corresponding ** complication) of [sqlite3_wal_checkpoint_v2()]. */ SQLITE_API int SQLITE_APICALL sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); /* ** CAPI3REF: Checkpoint a database ** METHOD: sqlite3 ** ** ^(The sqlite3_wal_checkpoint_v2(D,X,M,L,C) interface runs a checkpoint ** operation on database X of [database connection] D in mode M. Status |
| ︙ | ︙ | |||
7638 7639 7640 7641 7642 7643 7644 | ** the sqlite3_wal_checkpoint_v2() interface ** sets the error information that is queried by ** [sqlite3_errcode()] and [sqlite3_errmsg()]. ** ** ^The [PRAGMA wal_checkpoint] command can be used to invoke this interface ** from SQL. */ | | | 7859 7860 7861 7862 7863 7864 7865 7866 7867 7868 7869 7870 7871 7872 7873 | ** the sqlite3_wal_checkpoint_v2() interface ** sets the error information that is queried by ** [sqlite3_errcode()] and [sqlite3_errmsg()]. ** ** ^The [PRAGMA wal_checkpoint] command can be used to invoke this interface ** from SQL. */ SQLITE_API int SQLITE_APICALL sqlite3_wal_checkpoint_v2( sqlite3 *db, /* Database handle */ const char *zDb, /* Name of attached database (or NULL) */ int eMode, /* SQLITE_CHECKPOINT_* value */ int *pnLog, /* OUT: Size of WAL log in frames */ int *pnCkpt /* OUT: Total number of frames checkpointed */ ); |
| ︙ | ︙ | |||
7727 7728 7729 7730 7731 7732 7733 | ** This function may only be called from within a call to the [xUpdate] method ** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The ** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL], ** [SQLITE_ABORT], or [SQLITE_REPLACE], according to the [ON CONFLICT] mode ** of the SQL statement that triggered the call to the [xUpdate] method of the ** [virtual table]. */ | | | 7948 7949 7950 7951 7952 7953 7954 7955 7956 7957 7958 7959 7960 7961 7962 |
** This function may only be called from within a call to the [xUpdate] method
** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The
** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL],
** [SQLITE_ABORT], or [SQLITE_REPLACE], according to the [ON CONFLICT] mode
** of the SQL statement that triggered the call to the [xUpdate] method of the
** [virtual table].
*/
SQLITE_API int SQLITE_APICALL sqlite3_vtab_on_conflict(sqlite3 *);
/*
** CAPI3REF: Conflict resolution modes
** KEYWORDS: {conflict resolution mode}
**
** These constants are returned by [sqlite3_vtab_on_conflict()] to
** inform a [virtual table] implementation what the [ON CONFLICT] mode
|
| ︙ | ︙ | |||
7832 7833 7834 7835 7836 7837 7838 | ** ^Statistics might not be available for all loops in all statements. ^In cases ** where there exist loops with no available statistics, this function behaves ** as if the loop did not exist - it returns non-zero and leave the variable ** that pOut points to unchanged. ** ** See also: [sqlite3_stmt_scanstatus_reset()] */ | | | | 8053 8054 8055 8056 8057 8058 8059 8060 8061 8062 8063 8064 8065 8066 8067 8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 8083 | ** ^Statistics might not be available for all loops in all statements. ^In cases ** where there exist loops with no available statistics, this function behaves ** as if the loop did not exist - it returns non-zero and leave the variable ** that pOut points to unchanged. ** ** See also: [sqlite3_stmt_scanstatus_reset()] */ SQLITE_API int SQLITE_APICALL sqlite3_stmt_scanstatus( sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ int idx, /* Index of loop to report on */ int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ void *pOut /* Result written here */ ); /* ** CAPI3REF: Zero Scan-Status Counters ** METHOD: sqlite3_stmt ** ** ^Zero all [sqlite3_stmt_scanstatus()] related event counters. ** ** This API is only available if the library is built with pre-processor ** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined. */ SQLITE_API void SQLITE_APICALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); /* ** CAPI3REF: Flush caches to disk mid-transaction ** ** ^If a write-transaction is open on [database connection] D when the ** [sqlite3_db_cacheflush(D)] interface invoked, any dirty ** pages in the pager-cache that are not currently in use are written out |
| ︙ | ︙ | |||
7880 7881 7882 7883 7884 7885 7886 | ** abandoned and an SQLite [error code] is returned to the caller immediately. ** ** ^Otherwise, if no error occurs, [sqlite3_db_cacheflush()] returns SQLITE_OK. ** ** ^This function does not set the database handle error code or message ** returned by the [sqlite3_errcode()] and [sqlite3_errmsg()] functions. */ | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 8101 8102 8103 8104 8105 8106 8107 8108 8109 8110 8111 8112 8113 8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 8126 8127 8128 8129 8130 8131 8132 8133 8134 8135 8136 8137 8138 8139 8140 8141 8142 8143 8144 8145 8146 8147 8148 8149 8150 8151 8152 8153 8154 8155 8156 8157 8158 8159 8160 8161 8162 8163 8164 8165 8166 8167 8168 8169 8170 8171 8172 8173 8174 8175 8176 8177 8178 8179 8180 8181 8182 8183 8184 8185 8186 8187 8188 8189 8190 8191 8192 8193 8194 8195 8196 8197 8198 8199 8200 8201 8202 8203 8204 8205 8206 8207 8208 8209 8210 8211 8212 8213 8214 8215 8216 8217 8218 8219 8220 8221 8222 8223 |
** abandoned and an SQLite [error code] is returned to the caller immediately.
**
** ^Otherwise, if no error occurs, [sqlite3_db_cacheflush()] returns SQLITE_OK.
**
** ^This function does not set the database handle error code or message
** returned by the [sqlite3_errcode()] and [sqlite3_errmsg()] functions.
*/
SQLITE_API int SQLITE_APICALL sqlite3_db_cacheflush(sqlite3*);
/*
** CAPI3REF: The pre-update hook.
**
** ^These interfaces are only available if SQLite is compiled using the
** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option.
**
** ^The [sqlite3_preupdate_hook()] interface registers a callback function
** that is invoked prior to each [INSERT], [UPDATE], and [DELETE] operation
** on a [rowid table].
** ^At most one preupdate hook may be registered at a time on a single
** [database connection]; each call to [sqlite3_preupdate_hook()] overrides
** the previous setting.
** ^The preupdate hook is disabled by invoking [sqlite3_preupdate_hook()]
** with a NULL pointer as the second parameter.
** ^The third parameter to [sqlite3_preupdate_hook()] is passed through as
** the first parameter to callbacks.
**
** ^The preupdate hook only fires for changes to [rowid tables]; the preupdate
** hook is not invoked for changes to [virtual tables] or [WITHOUT ROWID]
** tables.
**
** ^The second parameter to the preupdate callback is a pointer to
** the [database connection] that registered the preupdate hook.
** ^The third parameter to the preupdate callback is one of the constants
** [SQLITE_INSERT], [SQLITE_DELETE], or [SQLITE_UPDATE] to indentify the
** kind of update operation that is about to occur.
** ^(The fourth parameter to the preupdate callback is the name of the
** database within the database connection that is being modified. This
** will be "main" for the main database or "temp" for TEMP tables or
** the name given after the AS keyword in the [ATTACH] statement for attached
** databases.)^
** ^The fifth parameter to the preupdate callback is the name of the
** table that is being modified.
** ^The sixth parameter to the preupdate callback is the initial [rowid] of the
** row being changes for SQLITE_UPDATE and SQLITE_DELETE changes and is
** undefined for SQLITE_INSERT changes.
** ^The seventh parameter to the preupdate callback is the final [rowid] of
** the row being changed for SQLITE_UPDATE and SQLITE_INSERT changes and is
** undefined for SQLITE_DELETE changes.
**
** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()],
** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces
** provide additional information about a preupdate event. These routines
** may only be called from within a preupdate callback. Invoking any of
** these routines from outside of a preupdate callback or with a
** [database connection] pointer that is different from the one supplied
** to the preupdate callback results in undefined and probably undesirable
** behavior.
**
** ^The [sqlite3_preupdate_count(D)] interface returns the number of columns
** in the row that is being inserted, updated, or deleted.
**
** ^The [sqlite3_preupdate_old(D,N,P)] interface writes into P a pointer to
** a [protected sqlite3_value] that contains the value of the Nth column of
** the table row before it is updated. The N parameter must be between 0
** and one less than the number of columns or the behavior will be
** undefined. This must only be used within SQLITE_UPDATE and SQLITE_DELETE
** preupdate callbacks; if it is used by an SQLITE_INSERT callback then the
** behavior is undefined. The [sqlite3_value] that P points to
** will be destroyed when the preupdate callback returns.
**
** ^The [sqlite3_preupdate_new(D,N,P)] interface writes into P a pointer to
** a [protected sqlite3_value] that contains the value of the Nth column of
** the table row after it is updated. The N parameter must be between 0
** and one less than the number of columns or the behavior will be
** undefined. This must only be used within SQLITE_INSERT and SQLITE_UPDATE
** preupdate callbacks; if it is used by an SQLITE_DELETE callback then the
** behavior is undefined. The [sqlite3_value] that P points to
** will be destroyed when the preupdate callback returns.
**
** ^The [sqlite3_preupdate_depth(D)] interface returns 0 if the preupdate
** callback was invoked as a result of a direct insert, update, or delete
** operation; or 1 for inserts, updates, or deletes invoked by top-level
** triggers; or 2 for changes resulting from triggers called by top-level
** triggers; and so forth.
**
** See also: [sqlite3_update_hook()]
*/
SQLITE_API SQLITE_EXPERIMENTAL void *SQLITE_APICALL sqlite3_preupdate_hook(
sqlite3 *db,
void(SQLITE_CALLBACK *xPreUpdate)(
void *pCtx, /* Copy of third arg to preupdate_hook() */
sqlite3 *db, /* Database handle */
int op, /* SQLITE_UPDATE, DELETE or INSERT */
char const *zDb, /* Database name */
char const *zName, /* Table name */
sqlite3_int64 iKey1, /* Rowid of row about to be deleted/updated */
sqlite3_int64 iKey2 /* New rowid value (for a rowid UPDATE) */
),
void*
);
SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_APICALL sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **);
SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_APICALL sqlite3_preupdate_count(sqlite3 *);
SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_APICALL sqlite3_preupdate_depth(sqlite3 *);
SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_APICALL sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
/*
** CAPI3REF: Low-level system error code
**
** ^Attempt to return the underlying operating system error code or error
** number that caused the most recent I/O error or failure to open a file.
** The return value is OS-dependent. For example, on unix systems, after
** [sqlite3_open_v2()] returns [SQLITE_CANTOPEN], this interface could be
** called to get back the underlying "errno" that caused the problem, such
** as ENOSPC, EAUTH, EISDIR, and so forth.
*/
SQLITE_API int SQLITE_APICALL sqlite3_system_errno(sqlite3*);
/*
** CAPI3REF: Database Snapshot
** KEYWORDS: {snapshot}
** EXPERIMENTAL
**
** An instance of the snapshot object records the state of a [WAL mode]
|
| ︙ | ︙ | |||
7930 7931 7932 7933 7934 7935 7936 | ** The [sqlite3_snapshot] object returned from a successful call to ** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()] ** to avoid a memory leak. ** ** The [sqlite3_snapshot_get()] interface is only available when the ** SQLITE_ENABLE_SNAPSHOT compile-time option is used. */ | | | | > | > | > > | > | | > > > > > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | 8259 8260 8261 8262 8263 8264 8265 8266 8267 8268 8269 8270 8271 8272 8273 8274 8275 8276 8277 8278 8279 8280 8281 8282 8283 8284 8285 8286 8287 8288 8289 8290 8291 8292 8293 8294 8295 8296 8297 8298 8299 8300 8301 8302 8303 8304 8305 8306 8307 8308 8309 8310 8311 8312 8313 8314 8315 8316 8317 8318 8319 8320 8321 8322 8323 8324 8325 8326 8327 8328 8329 8330 8331 8332 8333 8334 8335 8336 8337 8338 8339 8340 8341 8342 8343 8344 8345 8346 8347 8348 8349 8350 8351 8352 8353 8354 8355 8356 8357 8358 8359 8360 8361 8362 8363 8364 8365 8366 8367 8368 8369 8370 | ** The [sqlite3_snapshot] object returned from a successful call to ** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()] ** to avoid a memory leak. ** ** The [sqlite3_snapshot_get()] interface is only available when the ** SQLITE_ENABLE_SNAPSHOT compile-time option is used. */ SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_APICALL sqlite3_snapshot_get( sqlite3 *db, const char *zSchema, sqlite3_snapshot **ppSnapshot ); /* ** CAPI3REF: Start a read transaction on an historical snapshot ** EXPERIMENTAL ** ** ^The [sqlite3_snapshot_open(D,S,P)] interface starts a ** read transaction for schema S of ** [database connection] D such that the read transaction ** refers to historical [snapshot] P, rather than the most ** recent change to the database. ** ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK on success ** or an appropriate [error code] if it fails. ** ** ^In order to succeed, a call to [sqlite3_snapshot_open(D,S,P)] must be ** the first operation following the [BEGIN] that takes the schema S ** out of [autocommit mode]. ** ^In other words, schema S must not currently be in ** a transaction for [sqlite3_snapshot_open(D,S,P)] to work, but the ** database connection D must be out of [autocommit mode]. ** ^A [snapshot] will fail to open if it has been overwritten by a ** [checkpoint]. ** ^(A call to [sqlite3_snapshot_open(D,S,P)] will fail if the ** database connection D does not know that the database file for ** schema S is in [WAL mode]. A database connection might not know ** that the database file is in [WAL mode] if there has been no prior ** I/O on that database connection, or if the database entered [WAL mode] ** after the most recent I/O on the database connection.)^ ** (Hint: Run "[PRAGMA application_id]" against a newly opened ** database connection in order to make it ready to use snapshots.) ** ** The [sqlite3_snapshot_open()] interface is only available when the ** SQLITE_ENABLE_SNAPSHOT compile-time option is used. */ SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_APICALL sqlite3_snapshot_open( sqlite3 *db, const char *zSchema, sqlite3_snapshot *pSnapshot ); /* ** CAPI3REF: Destroy a snapshot ** EXPERIMENTAL ** ** ^The [sqlite3_snapshot_free(P)] interface destroys [sqlite3_snapshot] P. ** The application must eventually free every [sqlite3_snapshot] object ** using this routine to avoid a memory leak. ** ** The [sqlite3_snapshot_free()] interface is only available when the ** SQLITE_ENABLE_SNAPSHOT compile-time option is used. */ SQLITE_API SQLITE_EXPERIMENTAL void SQLITE_APICALL sqlite3_snapshot_free(sqlite3_snapshot*); /* ** CAPI3REF: Compare the ages of two snapshot handles. ** EXPERIMENTAL ** ** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages ** of two valid snapshot handles. ** ** If the two snapshot handles are not associated with the same database ** file, the result of the comparison is undefined. ** ** Additionally, the result of the comparison is only valid if both of the ** snapshot handles were obtained by calling sqlite3_snapshot_get() since the ** last time the wal file was deleted. The wal file is deleted when the ** database is changed back to rollback mode or when the number of database ** clients drops to zero. If either snapshot handle was obtained before the ** wal file was last deleted, the value returned by this function ** is undefined. ** ** Otherwise, this API returns a negative value if P1 refers to an older ** snapshot than P2, zero if the two handles refer to the same database ** snapshot, and a positive value if P1 is a newer snapshot than P2. */ SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_APICALL sqlite3_snapshot_cmp( sqlite3_snapshot *p1, sqlite3_snapshot *p2 ); /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ #ifdef SQLITE_OMIT_FLOATING_POINT # undef double #endif #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif #endif /* SQLITE3_H */ /******** Begin file sqlite3rtree.h *********/ /* ** 2010 August 30 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. |
| ︙ | ︙ | |||
8026 8027 8028 8029 8030 8031 8032 | /* ** Register a geometry callback named zGeom that can be used as part of an ** R-Tree geometry query as follows: ** ** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zGeom(... params ...) */ | | | | | | | | | 8396 8397 8398 8399 8400 8401 8402 8403 8404 8405 8406 8407 8408 8409 8410 8411 8412 8413 8414 8415 8416 8417 8418 8419 8420 8421 8422 8423 8424 8425 8426 8427 8428 8429 8430 8431 8432 8433 8434 8435 8436 8437 8438 8439 8440 8441 8442 8443 8444 8445 8446 8447 8448 8449 8450 8451 8452 8453 8454 8455 8456 8457 8458 8459 |
/*
** Register a geometry callback named zGeom that can be used as part of an
** R-Tree geometry query as follows:
**
** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zGeom(... params ...)
*/
SQLITE_API int SQLITE_APICALL sqlite3_rtree_geometry_callback(
sqlite3 *db,
const char *zGeom,
int (SQLITE_CALLBACK *xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*),
void *pContext
);
/*
** A pointer to a structure of the following type is passed as the first
** argument to callbacks registered using rtree_geometry_callback().
*/
struct sqlite3_rtree_geometry {
void *pContext; /* Copy of pContext passed to s_r_g_c() */
int nParam; /* Size of array aParam[] */
sqlite3_rtree_dbl *aParam; /* Parameters passed to SQL geom function */
void *pUser; /* Callback implementation user data */
void (SQLITE_CALLBACK *xDelUser)(void *); /* Called by SQLite to clean up pUser */
};
/*
** Register a 2nd-generation geometry callback named zScore that can be
** used as part of an R-Tree geometry query as follows:
**
** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zQueryFunc(... params ...)
*/
SQLITE_API int SQLITE_APICALL sqlite3_rtree_query_callback(
sqlite3 *db,
const char *zQueryFunc,
int (SQLITE_CALLBACK *xQueryFunc)(sqlite3_rtree_query_info*),
void *pContext,
void (SQLITE_CALLBACK *xDestructor)(void*)
);
/*
** A pointer to a structure of the following type is passed as the
** argument to scored geometry callback registered using
** sqlite3_rtree_query_callback().
**
** Note that the first 5 fields of this structure are identical to
** sqlite3_rtree_geometry. This structure is a subclass of
** sqlite3_rtree_geometry.
*/
struct sqlite3_rtree_query_info {
void *pContext; /* pContext from when function registered */
int nParam; /* Number of function parameters */
sqlite3_rtree_dbl *aParam; /* value of function parameters */
void *pUser; /* callback can use this, if desired */
void (SQLITE_CALLBACK *xDelUser)(void*); /* function to free pUser */
sqlite3_rtree_dbl *aCoord; /* Coordinates of node or entry to check */
unsigned int *anQueue; /* Number of pending entries in the queue */
int nCoord; /* Number of coordinates */
int iLevel; /* Level of current node or entry */
int mxLevel; /* The largest iLevel value in the tree */
sqlite3_int64 iRowid; /* Rowid for current entry */
sqlite3_rtree_dbl rParentScore; /* Score of parent node */
|
| ︙ | ︙ | |||
8104 8105 8106 8107 8108 8109 8110 8111 8112 8113 8114 8115 8116 8117 | #ifdef __cplusplus } /* end of the 'extern "C"' block */ #endif #endif /* ifndef _SQLITE3RTREE_H_ */ /* ** 2014 May 31 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 8513 8514 8515 8516 8517 8518 8519 8520 8521 8522 8523 8524 8525 8526 8527 8528 8529 8530 8531 8532 8533 8534 8535 8536 8537 8538 8539 8540 8541 8542 8543 8544 8545 8546 8547 8548 8549 8550 8551 8552 8553 8554 8555 8556 8557 8558 8559 8560 8561 8562 8563 8564 8565 8566 8567 8568 8569 8570 8571 8572 8573 8574 8575 8576 8577 8578 8579 8580 8581 8582 8583 8584 8585 8586 8587 8588 8589 8590 8591 8592 8593 8594 8595 8596 8597 8598 8599 8600 8601 8602 8603 8604 8605 8606 8607 8608 8609 8610 8611 8612 8613 8614 8615 8616 8617 8618 8619 8620 8621 8622 8623 8624 8625 8626 8627 8628 8629 8630 8631 8632 8633 8634 8635 8636 8637 8638 8639 8640 8641 8642 8643 8644 8645 8646 8647 8648 8649 8650 8651 8652 8653 8654 8655 8656 8657 8658 8659 8660 8661 8662 8663 8664 8665 8666 8667 8668 8669 8670 8671 8672 8673 8674 8675 8676 8677 8678 8679 8680 8681 8682 8683 8684 8685 8686 8687 8688 8689 8690 8691 8692 8693 8694 8695 8696 8697 8698 8699 8700 8701 8702 8703 8704 8705 8706 8707 8708 8709 8710 8711 8712 8713 8714 8715 8716 8717 8718 8719 8720 8721 8722 8723 8724 8725 8726 8727 8728 8729 8730 8731 8732 8733 8734 8735 8736 8737 8738 8739 8740 8741 8742 8743 8744 8745 8746 8747 8748 8749 8750 8751 8752 8753 8754 8755 8756 8757 8758 8759 8760 8761 8762 8763 8764 8765 8766 8767 8768 8769 8770 8771 8772 8773 8774 8775 8776 8777 8778 8779 8780 8781 8782 8783 8784 8785 8786 8787 8788 8789 8790 8791 8792 8793 8794 8795 8796 8797 8798 8799 8800 8801 8802 8803 8804 8805 8806 8807 8808 8809 8810 8811 8812 8813 8814 8815 8816 8817 8818 8819 8820 8821 8822 8823 8824 8825 8826 8827 8828 8829 8830 8831 8832 8833 8834 8835 8836 8837 8838 8839 8840 8841 8842 8843 8844 8845 8846 8847 8848 8849 8850 8851 8852 8853 8854 8855 8856 8857 8858 8859 8860 8861 8862 8863 8864 8865 8866 8867 8868 8869 8870 8871 8872 8873 8874 8875 8876 8877 8878 8879 8880 8881 8882 8883 8884 8885 8886 8887 8888 8889 8890 8891 8892 8893 8894 8895 8896 8897 8898 8899 8900 8901 8902 8903 8904 8905 8906 8907 8908 8909 8910 8911 8912 8913 8914 8915 8916 8917 8918 8919 8920 8921 8922 8923 8924 8925 8926 8927 8928 8929 8930 8931 8932 8933 8934 8935 8936 8937 8938 8939 8940 8941 8942 8943 8944 8945 8946 8947 8948 8949 8950 8951 8952 8953 8954 8955 8956 8957 8958 8959 8960 8961 8962 8963 8964 8965 8966 8967 8968 8969 8970 8971 8972 8973 8974 8975 8976 8977 8978 8979 8980 8981 8982 8983 8984 8985 8986 8987 8988 8989 8990 8991 8992 8993 8994 8995 8996 8997 8998 8999 9000 9001 9002 9003 9004 9005 9006 9007 9008 9009 9010 9011 9012 9013 9014 9015 9016 9017 9018 9019 9020 9021 9022 9023 9024 9025 9026 9027 9028 9029 9030 9031 9032 9033 9034 9035 9036 9037 9038 9039 9040 9041 9042 9043 9044 9045 9046 9047 9048 9049 9050 9051 9052 9053 9054 9055 9056 9057 9058 9059 9060 9061 9062 9063 9064 9065 9066 9067 9068 9069 9070 9071 9072 9073 9074 9075 9076 9077 9078 9079 9080 9081 9082 9083 9084 9085 9086 9087 9088 9089 9090 9091 9092 9093 9094 9095 9096 9097 9098 9099 9100 9101 9102 9103 9104 9105 9106 9107 9108 9109 9110 9111 9112 9113 9114 9115 9116 9117 9118 9119 9120 9121 9122 9123 9124 9125 9126 9127 9128 9129 9130 9131 9132 9133 9134 9135 9136 9137 9138 9139 9140 9141 9142 9143 9144 9145 9146 9147 9148 9149 9150 9151 9152 9153 9154 9155 9156 9157 9158 9159 9160 9161 9162 9163 9164 9165 9166 9167 9168 9169 9170 9171 9172 9173 9174 9175 9176 9177 9178 9179 9180 9181 9182 9183 9184 9185 9186 9187 9188 9189 9190 9191 9192 9193 9194 9195 9196 9197 9198 9199 9200 9201 9202 9203 9204 9205 9206 9207 9208 9209 9210 9211 9212 9213 9214 9215 9216 9217 9218 9219 9220 9221 9222 9223 9224 9225 9226 9227 9228 9229 9230 9231 9232 9233 9234 9235 9236 9237 9238 9239 9240 9241 9242 9243 9244 9245 9246 9247 9248 9249 9250 9251 9252 9253 9254 9255 9256 9257 9258 9259 9260 9261 9262 9263 9264 9265 9266 9267 9268 9269 9270 9271 9272 9273 9274 9275 9276 9277 9278 9279 9280 9281 9282 9283 9284 9285 9286 9287 9288 9289 9290 9291 9292 9293 9294 9295 9296 9297 9298 9299 9300 9301 9302 9303 9304 9305 9306 9307 9308 9309 9310 9311 9312 9313 9314 9315 9316 9317 9318 9319 9320 9321 9322 9323 9324 9325 9326 9327 9328 9329 9330 9331 9332 9333 9334 9335 9336 9337 9338 9339 9340 9341 9342 9343 9344 9345 9346 9347 9348 9349 9350 9351 9352 9353 9354 9355 9356 9357 9358 9359 9360 9361 9362 9363 9364 9365 9366 9367 9368 9369 9370 9371 9372 9373 9374 9375 9376 9377 9378 9379 9380 9381 9382 9383 9384 9385 9386 9387 9388 9389 9390 9391 9392 9393 9394 9395 9396 9397 9398 9399 9400 9401 9402 9403 9404 9405 9406 9407 9408 9409 9410 9411 9412 9413 9414 9415 9416 9417 9418 9419 9420 9421 9422 9423 9424 9425 9426 9427 9428 9429 9430 9431 9432 9433 9434 9435 9436 9437 9438 9439 9440 9441 9442 9443 9444 9445 9446 9447 9448 9449 9450 9451 9452 9453 9454 9455 9456 9457 9458 9459 9460 9461 9462 9463 9464 9465 9466 9467 9468 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 9510 9511 9512 9513 9514 9515 9516 9517 9518 9519 9520 9521 9522 9523 9524 9525 9526 9527 9528 9529 9530 9531 9532 9533 9534 9535 9536 9537 9538 9539 9540 9541 9542 9543 9544 9545 9546 9547 9548 9549 9550 9551 9552 9553 9554 9555 9556 9557 9558 9559 9560 9561 9562 9563 9564 9565 9566 9567 9568 9569 9570 9571 9572 9573 9574 9575 9576 9577 9578 9579 9580 9581 9582 9583 9584 9585 9586 9587 9588 9589 9590 9591 9592 9593 9594 9595 9596 9597 9598 9599 9600 9601 9602 9603 9604 9605 9606 9607 9608 9609 9610 9611 9612 9613 9614 9615 9616 9617 9618 9619 9620 9621 9622 9623 9624 9625 9626 9627 9628 9629 9630 9631 9632 9633 9634 9635 9636 9637 9638 9639 9640 9641 9642 9643 9644 9645 9646 9647 9648 9649 9650 9651 9652 9653 9654 9655 9656 9657 9658 9659 9660 9661 9662 9663 9664 9665 9666 9667 9668 9669 9670 9671 9672 9673 9674 9675 9676 9677 9678 9679 9680 9681 9682 9683 9684 9685 9686 9687 9688 9689 9690 9691 9692 9693 9694 9695 9696 9697 9698 9699 9700 9701 9702 9703 9704 9705 9706 9707 9708 9709 9710 9711 9712 9713 9714 9715 9716 9717 9718 9719 9720 9721 9722 9723 9724 9725 9726 9727 9728 9729 9730 9731 9732 9733 9734 9735 9736 9737 9738 9739 9740 9741 9742 9743 9744 9745 9746 9747 9748 9749 9750 9751 9752 9753 9754 9755 9756 9757 9758 9759 9760 9761 9762 9763 9764 9765 9766 9767 9768 |
#ifdef __cplusplus
} /* end of the 'extern "C"' block */
#endif
#endif /* ifndef _SQLITE3RTREE_H_ */
/******** End of sqlite3rtree.h *********/
/******** Begin file sqlite3session.h *********/
#if !defined(__SQLITESESSION_H_) && defined(SQLITE_ENABLE_SESSION)
#define __SQLITESESSION_H_ 1
/*
** Make sure we can call this stuff from C++.
*/
#ifdef __cplusplus
extern "C" {
#endif
/*
** CAPI3REF: Session Object Handle
*/
typedef struct sqlite3_session sqlite3_session;
/*
** CAPI3REF: Changeset Iterator Handle
*/
typedef struct sqlite3_changeset_iter sqlite3_changeset_iter;
/*
** CAPI3REF: Create A New Session Object
**
** Create a new session object attached to database handle db. If successful,
** a pointer to the new object is written to *ppSession and SQLITE_OK is
** returned. If an error occurs, *ppSession is set to NULL and an SQLite
** error code (e.g. SQLITE_NOMEM) is returned.
**
** It is possible to create multiple session objects attached to a single
** database handle.
**
** Session objects created using this function should be deleted using the
** [sqlite3session_delete()] function before the database handle that they
** are attached to is itself closed. If the database handle is closed before
** the session object is deleted, then the results of calling any session
** module function, including [sqlite3session_delete()] on the session object
** are undefined.
**
** Because the session module uses the [sqlite3_preupdate_hook()] API, it
** is not possible for an application to register a pre-update hook on a
** database handle that has one or more session objects attached. Nor is
** it possible to create a session object attached to a database handle for
** which a pre-update hook is already defined. The results of attempting
** either of these things are undefined.
**
** The session object will be used to create changesets for tables in
** database zDb, where zDb is either "main", or "temp", or the name of an
** attached database. It is not an error if database zDb is not attached
** to the database when the session object is created.
*/
int sqlite3session_create(
sqlite3 *db, /* Database handle */
const char *zDb, /* Name of db (e.g. "main") */
sqlite3_session **ppSession /* OUT: New session object */
);
/*
** CAPI3REF: Delete A Session Object
**
** Delete a session object previously allocated using
** [sqlite3session_create()]. Once a session object has been deleted, the
** results of attempting to use pSession with any other session module
** function are undefined.
**
** Session objects must be deleted before the database handle to which they
** are attached is closed. Refer to the documentation for
** [sqlite3session_create()] for details.
*/
void sqlite3session_delete(sqlite3_session *pSession);
/*
** CAPI3REF: Enable Or Disable A Session Object
**
** Enable or disable the recording of changes by a session object. When
** enabled, a session object records changes made to the database. When
** disabled - it does not. A newly created session object is enabled.
** Refer to the documentation for [sqlite3session_changeset()] for further
** details regarding how enabling and disabling a session object affects
** the eventual changesets.
**
** Passing zero to this function disables the session. Passing a value
** greater than zero enables it. Passing a value less than zero is a
** no-op, and may be used to query the current state of the session.
**
** The return value indicates the final state of the session object: 0 if
** the session is disabled, or 1 if it is enabled.
*/
int sqlite3session_enable(sqlite3_session *pSession, int bEnable);
/*
** CAPI3REF: Set Or Clear the Indirect Change Flag
**
** Each change recorded by a session object is marked as either direct or
** indirect. A change is marked as indirect if either:
**
** <ul>
** <li> The session object "indirect" flag is set when the change is
** made, or
** <li> The change is made by an SQL trigger or foreign key action
** instead of directly as a result of a users SQL statement.
** </ul>
**
** If a single row is affected by more than one operation within a session,
** then the change is considered indirect if all operations meet the criteria
** for an indirect change above, or direct otherwise.
**
** This function is used to set, clear or query the session object indirect
** flag. If the second argument passed to this function is zero, then the
** indirect flag is cleared. If it is greater than zero, the indirect flag
** is set. Passing a value less than zero does not modify the current value
** of the indirect flag, and may be used to query the current state of the
** indirect flag for the specified session object.
**
** The return value indicates the final state of the indirect flag: 0 if
** it is clear, or 1 if it is set.
*/
int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect);
/*
** CAPI3REF: Attach A Table To A Session Object
**
** If argument zTab is not NULL, then it is the name of a table to attach
** to the session object passed as the first argument. All subsequent changes
** made to the table while the session object is enabled will be recorded. See
** documentation for [sqlite3session_changeset()] for further details.
**
** Or, if argument zTab is NULL, then changes are recorded for all tables
** in the database. If additional tables are added to the database (by
** executing "CREATE TABLE" statements) after this call is made, changes for
** the new tables are also recorded.
**
** Changes can only be recorded for tables that have a PRIMARY KEY explicitly
** defined as part of their CREATE TABLE statement. It does not matter if the
** PRIMARY KEY is an "INTEGER PRIMARY KEY" (rowid alias) or not. The PRIMARY
** KEY may consist of a single column, or may be a composite key.
**
** It is not an error if the named table does not exist in the database. Nor
** is it an error if the named table does not have a PRIMARY KEY. However,
** no changes will be recorded in either of these scenarios.
**
** Changes are not recorded for individual rows that have NULL values stored
** in one or more of their PRIMARY KEY columns.
**
** SQLITE_OK is returned if the call completes without error. Or, if an error
** occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned.
*/
int sqlite3session_attach(
sqlite3_session *pSession, /* Session object */
const char *zTab /* Table name */
);
/*
** CAPI3REF: Set a table filter on a Session Object.
**
** The second argument (xFilter) is the "filter callback". For changes to rows
** in tables that are not attached to the Session oject, the filter is called
** to determine whether changes to the table's rows should be tracked or not.
** If xFilter returns 0, changes is not tracked. Note that once a table is
** attached, xFilter will not be called again.
*/
void sqlite3session_table_filter(
sqlite3_session *pSession, /* Session object */
int(SQLITE_CALLBACK *xFilter)(
void *pCtx, /* Copy of third arg to _filter_table() */
const char *zTab /* Table name */
),
void *pCtx /* First argument passed to xFilter */
);
/*
** CAPI3REF: Generate A Changeset From A Session Object
**
** Obtain a changeset containing changes to the tables attached to the
** session object passed as the first argument. If successful,
** set *ppChangeset to point to a buffer containing the changeset
** and *pnChangeset to the size of the changeset in bytes before returning
** SQLITE_OK. If an error occurs, set both *ppChangeset and *pnChangeset to
** zero and return an SQLite error code.
**
** A changeset consists of zero or more INSERT, UPDATE and/or DELETE changes,
** each representing a change to a single row of an attached table. An INSERT
** change contains the values of each field of a new database row. A DELETE
** contains the original values of each field of a deleted database row. An
** UPDATE change contains the original values of each field of an updated
** database row along with the updated values for each updated non-primary-key
** column. It is not possible for an UPDATE change to represent a change that
** modifies the values of primary key columns. If such a change is made, it
** is represented in a changeset as a DELETE followed by an INSERT.
**
** Changes are not recorded for rows that have NULL values stored in one or
** more of their PRIMARY KEY columns. If such a row is inserted or deleted,
** no corresponding change is present in the changesets returned by this
** function. If an existing row with one or more NULL values stored in
** PRIMARY KEY columns is updated so that all PRIMARY KEY columns are non-NULL,
** only an INSERT is appears in the changeset. Similarly, if an existing row
** with non-NULL PRIMARY KEY values is updated so that one or more of its
** PRIMARY KEY columns are set to NULL, the resulting changeset contains a
** DELETE change only.
**
** The contents of a changeset may be traversed using an iterator created
** using the [sqlite3changeset_start()] API. A changeset may be applied to
** a database with a compatible schema using the [sqlite3changeset_apply()]
** API.
**
** Within a changeset generated by this function, all changes related to a
** single table are grouped together. In other words, when iterating through
** a changeset or when applying a changeset to a database, all changes related
** to a single table are processed before moving on to the next table. Tables
** are sorted in the same order in which they were attached (or auto-attached)
** to the sqlite3_session object. The order in which the changes related to
** a single table are stored is undefined.
**
** Following a successful call to this function, it is the responsibility of
** the caller to eventually free the buffer that *ppChangeset points to using
** [sqlite3_free()].
**
** <h3>Changeset Generation</h3>
**
** Once a table has been attached to a session object, the session object
** records the primary key values of all new rows inserted into the table.
** It also records the original primary key and other column values of any
** deleted or updated rows. For each unique primary key value, data is only
** recorded once - the first time a row with said primary key is inserted,
** updated or deleted in the lifetime of the session.
**
** There is one exception to the previous paragraph: when a row is inserted,
** updated or deleted, if one or more of its primary key columns contain a
** NULL value, no record of the change is made.
**
** The session object therefore accumulates two types of records - those
** that consist of primary key values only (created when the user inserts
** a new record) and those that consist of the primary key values and the
** original values of other table columns (created when the users deletes
** or updates a record).
**
** When this function is called, the requested changeset is created using
** both the accumulated records and the current contents of the database
** file. Specifically:
**
** <ul>
** <li> For each record generated by an insert, the database is queried
** for a row with a matching primary key. If one is found, an INSERT
** change is added to the changeset. If no such row is found, no change
** is added to the changeset.
**
** <li> For each record generated by an update or delete, the database is
** queried for a row with a matching primary key. If such a row is
** found and one or more of the non-primary key fields have been
** modified from their original values, an UPDATE change is added to
** the changeset. Or, if no such row is found in the table, a DELETE
** change is added to the changeset. If there is a row with a matching
** primary key in the database, but all fields contain their original
** values, no change is added to the changeset.
** </ul>
**
** This means, amongst other things, that if a row is inserted and then later
** deleted while a session object is active, neither the insert nor the delete
** will be present in the changeset. Or if a row is deleted and then later a
** row with the same primary key values inserted while a session object is
** active, the resulting changeset will contain an UPDATE change instead of
** a DELETE and an INSERT.
**
** When a session object is disabled (see the [sqlite3session_enable()] API),
** it does not accumulate records when rows are inserted, updated or deleted.
** This may appear to have some counter-intuitive effects if a single row
** is written to more than once during a session. For example, if a row
** is inserted while a session object is enabled, then later deleted while
** the same session object is disabled, no INSERT record will appear in the
** changeset, even though the delete took place while the session was disabled.
** Or, if one field of a row is updated while a session is disabled, and
** another field of the same row is updated while the session is enabled, the
** resulting changeset will contain an UPDATE change that updates both fields.
*/
int sqlite3session_changeset(
sqlite3_session *pSession, /* Session object */
int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */
void **ppChangeset /* OUT: Buffer containing changeset */
);
/*
** CAPI3REF: Load The Difference Between Tables Into A Session
**
** If it is not already attached to the session object passed as the first
** argument, this function attaches table zTbl in the same manner as the
** [sqlite3session_attach()] function. If zTbl does not exist, or if it
** does not have a primary key, this function is a no-op (but does not return
** an error).
**
** Argument zFromDb must be the name of a database ("main", "temp" etc.)
** attached to the same database handle as the session object that contains
** a table compatible with the table attached to the session by this function.
** A table is considered compatible if it:
**
** <ul>
** <li> Has the same name,
** <li> Has the same set of columns declared in the same order, and
** <li> Has the same PRIMARY KEY definition.
** </ul>
**
** If the tables are not compatible, SQLITE_SCHEMA is returned. If the tables
** are compatible but do not have any PRIMARY KEY columns, it is not an error
** but no changes are added to the session object. As with other session
** APIs, tables without PRIMARY KEYs are simply ignored.
**
** This function adds a set of changes to the session object that could be
** used to update the table in database zFrom (call this the "from-table")
** so that its content is the same as the table attached to the session
** object (call this the "to-table"). Specifically:
**
** <ul>
** <li> For each row (primary key) that exists in the to-table but not in
** the from-table, an INSERT record is added to the session object.
**
** <li> For each row (primary key) that exists in the to-table but not in
** the from-table, a DELETE record is added to the session object.
**
** <li> For each row (primary key) that exists in both tables, but features
** different in each, an UPDATE record is added to the session.
** </ul>
**
** To clarify, if this function is called and then a changeset constructed
** using [sqlite3session_changeset()], then after applying that changeset to
** database zFrom the contents of the two compatible tables would be
** identical.
**
** It an error if database zFrom does not exist or does not contain the
** required compatible table.
**
** If the operation successful, SQLITE_OK is returned. Otherwise, an SQLite
** error code. In this case, if argument pzErrMsg is not NULL, *pzErrMsg
** may be set to point to a buffer containing an English language error
** message. It is the responsibility of the caller to free this buffer using
** sqlite3_free().
*/
int sqlite3session_diff(
sqlite3_session *pSession,
const char *zFromDb,
const char *zTbl,
char **pzErrMsg
);
/*
** CAPI3REF: Generate A Patchset From A Session Object
**
** The differences between a patchset and a changeset are that:
**
** <ul>
** <li> DELETE records consist of the primary key fields only. The
** original values of other fields are omitted.
** <li> The original values of any modified fields are omitted from
** UPDATE records.
** </ul>
**
** A patchset blob may be used with up to date versions of all
** sqlite3changeset_xxx API functions except for sqlite3changeset_invert(),
** which returns SQLITE_CORRUPT if it is passed a patchset. Similarly,
** attempting to use a patchset blob with old versions of the
** sqlite3changeset_xxx APIs also provokes an SQLITE_CORRUPT error.
**
** Because the non-primary key "old.*" fields are omitted, no
** SQLITE_CHANGESET_DATA conflicts can be detected or reported if a patchset
** is passed to the sqlite3changeset_apply() API. Other conflict types work
** in the same way as for changesets.
**
** Changes within a patchset are ordered in the same way as for changesets
** generated by the sqlite3session_changeset() function (i.e. all changes for
** a single table are grouped together, tables appear in the order in which
** they were attached to the session object).
*/
int sqlite3session_patchset(
sqlite3_session *pSession, /* Session object */
int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */
void **ppPatchset /* OUT: Buffer containing changeset */
);
/*
** CAPI3REF: Test if a changeset has recorded any changes.
**
** Return non-zero if no changes to attached tables have been recorded by
** the session object passed as the first argument. Otherwise, if one or
** more changes have been recorded, return zero.
**
** Even if this function returns zero, it is possible that calling
** [sqlite3session_changeset()] on the session handle may still return a
** changeset that contains no changes. This can happen when a row in
** an attached table is modified and then later on the original values
** are restored. However, if this function returns non-zero, then it is
** guaranteed that a call to sqlite3session_changeset() will return a
** changeset containing zero changes.
*/
int sqlite3session_isempty(sqlite3_session *pSession);
/*
** CAPI3REF: Create An Iterator To Traverse A Changeset
**
** Create an iterator used to iterate through the contents of a changeset.
** If successful, *pp is set to point to the iterator handle and SQLITE_OK
** is returned. Otherwise, if an error occurs, *pp is set to zero and an
** SQLite error code is returned.
**
** The following functions can be used to advance and query a changeset
** iterator created by this function:
**
** <ul>
** <li> [sqlite3changeset_next()]
** <li> [sqlite3changeset_op()]
** <li> [sqlite3changeset_new()]
** <li> [sqlite3changeset_old()]
** </ul>
**
** It is the responsibility of the caller to eventually destroy the iterator
** by passing it to [sqlite3changeset_finalize()]. The buffer containing the
** changeset (pChangeset) must remain valid until after the iterator is
** destroyed.
**
** Assuming the changeset blob was created by one of the
** [sqlite3session_changeset()], [sqlite3changeset_concat()] or
** [sqlite3changeset_invert()] functions, all changes within the changeset
** that apply to a single table are grouped together. This means that when
** an application iterates through a changeset using an iterator created by
** this function, all changes that relate to a single table are visted
** consecutively. There is no chance that the iterator will visit a change
** the applies to table X, then one for table Y, and then later on visit
** another change for table X.
*/
int sqlite3changeset_start(
sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */
int nChangeset, /* Size of changeset blob in bytes */
void *pChangeset /* Pointer to blob containing changeset */
);
/*
** CAPI3REF: Advance A Changeset Iterator
**
** This function may only be used with iterators created by function
** [sqlite3changeset_start()]. If it is called on an iterator passed to
** a conflict-handler callback by [sqlite3changeset_apply()], SQLITE_MISUSE
** is returned and the call has no effect.
**
** Immediately after an iterator is created by sqlite3changeset_start(), it
** does not point to any change in the changeset. Assuming the changeset
** is not empty, the first call to this function advances the iterator to
** point to the first change in the changeset. Each subsequent call advances
** the iterator to point to the next change in the changeset (if any). If
** no error occurs and the iterator points to a valid change after a call
** to sqlite3changeset_next() has advanced it, SQLITE_ROW is returned.
** Otherwise, if all changes in the changeset have already been visited,
** SQLITE_DONE is returned.
**
** If an error occurs, an SQLite error code is returned. Possible error
** codes include SQLITE_CORRUPT (if the changeset buffer is corrupt) or
** SQLITE_NOMEM.
*/
int sqlite3changeset_next(sqlite3_changeset_iter *pIter);
/*
** CAPI3REF: Obtain The Current Operation From A Changeset Iterator
**
** The pIter argument passed to this function may either be an iterator
** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator
** created by [sqlite3changeset_start()]. In the latter case, the most recent
** call to [sqlite3changeset_next()] must have returned [SQLITE_ROW]. If this
** is not the case, this function returns [SQLITE_MISUSE].
**
** If argument pzTab is not NULL, then *pzTab is set to point to a
** nul-terminated utf-8 encoded string containing the name of the table
** affected by the current change. The buffer remains valid until either
** sqlite3changeset_next() is called on the iterator or until the
** conflict-handler function returns. If pnCol is not NULL, then *pnCol is
** set to the number of columns in the table affected by the change. If
** pbIncorrect is not NULL, then *pbIndirect is set to true (1) if the change
** is an indirect change, or false (0) otherwise. See the documentation for
** [sqlite3session_indirect()] for a description of direct and indirect
** changes. Finally, if pOp is not NULL, then *pOp is set to one of
** [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], depending on the
** type of change that the iterator currently points to.
**
** If no error occurs, SQLITE_OK is returned. If an error does occur, an
** SQLite error code is returned. The values of the output variables may not
** be trusted in this case.
*/
int sqlite3changeset_op(
sqlite3_changeset_iter *pIter, /* Iterator object */
const char **pzTab, /* OUT: Pointer to table name */
int *pnCol, /* OUT: Number of columns in table */
int *pOp, /* OUT: SQLITE_INSERT, DELETE or UPDATE */
int *pbIndirect /* OUT: True for an 'indirect' change */
);
/*
** CAPI3REF: Obtain The Primary Key Definition Of A Table
**
** For each modified table, a changeset includes the following:
**
** <ul>
** <li> The number of columns in the table, and
** <li> Which of those columns make up the tables PRIMARY KEY.
** </ul>
**
** This function is used to find which columns comprise the PRIMARY KEY of
** the table modified by the change that iterator pIter currently points to.
** If successful, *pabPK is set to point to an array of nCol entries, where
** nCol is the number of columns in the table. Elements of *pabPK are set to
** 0x01 if the corresponding column is part of the tables primary key, or
** 0x00 if it is not.
**
** If argumet pnCol is not NULL, then *pnCol is set to the number of columns
** in the table.
**
** If this function is called when the iterator does not point to a valid
** entry, SQLITE_MISUSE is returned and the output variables zeroed. Otherwise,
** SQLITE_OK is returned and the output variables populated as described
** above.
*/
int sqlite3changeset_pk(
sqlite3_changeset_iter *pIter, /* Iterator object */
unsigned char **pabPK, /* OUT: Array of boolean - true for PK cols */
int *pnCol /* OUT: Number of entries in output array */
);
/*
** CAPI3REF: Obtain old.* Values From A Changeset Iterator
**
** The pIter argument passed to this function may either be an iterator
** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator
** created by [sqlite3changeset_start()]. In the latter case, the most recent
** call to [sqlite3changeset_next()] must have returned SQLITE_ROW.
** Furthermore, it may only be called if the type of change that the iterator
** currently points to is either [SQLITE_DELETE] or [SQLITE_UPDATE]. Otherwise,
** this function returns [SQLITE_MISUSE] and sets *ppValue to NULL.
**
** Argument iVal must be greater than or equal to 0, and less than the number
** of columns in the table affected by the current change. Otherwise,
** [SQLITE_RANGE] is returned and *ppValue is set to NULL.
**
** If successful, this function sets *ppValue to point to a protected
** sqlite3_value object containing the iVal'th value from the vector of
** original row values stored as part of the UPDATE or DELETE change and
** returns SQLITE_OK. The name of the function comes from the fact that this
** is similar to the "old.*" columns available to update or delete triggers.
**
** If some other error occurs (e.g. an OOM condition), an SQLite error code
** is returned and *ppValue is set to NULL.
*/
int sqlite3changeset_old(
sqlite3_changeset_iter *pIter, /* Changeset iterator */
int iVal, /* Column number */
sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */
);
/*
** CAPI3REF: Obtain new.* Values From A Changeset Iterator
**
** The pIter argument passed to this function may either be an iterator
** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator
** created by [sqlite3changeset_start()]. In the latter case, the most recent
** call to [sqlite3changeset_next()] must have returned SQLITE_ROW.
** Furthermore, it may only be called if the type of change that the iterator
** currently points to is either [SQLITE_UPDATE] or [SQLITE_INSERT]. Otherwise,
** this function returns [SQLITE_MISUSE] and sets *ppValue to NULL.
**
** Argument iVal must be greater than or equal to 0, and less than the number
** of columns in the table affected by the current change. Otherwise,
** [SQLITE_RANGE] is returned and *ppValue is set to NULL.
**
** If successful, this function sets *ppValue to point to a protected
** sqlite3_value object containing the iVal'th value from the vector of
** new row values stored as part of the UPDATE or INSERT change and
** returns SQLITE_OK. If the change is an UPDATE and does not include
** a new value for the requested column, *ppValue is set to NULL and
** SQLITE_OK returned. The name of the function comes from the fact that
** this is similar to the "new.*" columns available to update or delete
** triggers.
**
** If some other error occurs (e.g. an OOM condition), an SQLite error code
** is returned and *ppValue is set to NULL.
*/
int sqlite3changeset_new(
sqlite3_changeset_iter *pIter, /* Changeset iterator */
int iVal, /* Column number */
sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */
);
/*
** CAPI3REF: Obtain Conflicting Row Values From A Changeset Iterator
**
** This function should only be used with iterator objects passed to a
** conflict-handler callback by [sqlite3changeset_apply()] with either
** [SQLITE_CHANGESET_DATA] or [SQLITE_CHANGESET_CONFLICT]. If this function
** is called on any other iterator, [SQLITE_MISUSE] is returned and *ppValue
** is set to NULL.
**
** Argument iVal must be greater than or equal to 0, and less than the number
** of columns in the table affected by the current change. Otherwise,
** [SQLITE_RANGE] is returned and *ppValue is set to NULL.
**
** If successful, this function sets *ppValue to point to a protected
** sqlite3_value object containing the iVal'th value from the
** "conflicting row" associated with the current conflict-handler callback
** and returns SQLITE_OK.
**
** If some other error occurs (e.g. an OOM condition), an SQLite error code
** is returned and *ppValue is set to NULL.
*/
int sqlite3changeset_conflict(
sqlite3_changeset_iter *pIter, /* Changeset iterator */
int iVal, /* Column number */
sqlite3_value **ppValue /* OUT: Value from conflicting row */
);
/*
** CAPI3REF: Determine The Number Of Foreign Key Constraint Violations
**
** This function may only be called with an iterator passed to an
** SQLITE_CHANGESET_FOREIGN_KEY conflict handler callback. In this case
** it sets the output variable to the total number of known foreign key
** violations in the destination database and returns SQLITE_OK.
**
** In all other cases this function returns SQLITE_MISUSE.
*/
int sqlite3changeset_fk_conflicts(
sqlite3_changeset_iter *pIter, /* Changeset iterator */
int *pnOut /* OUT: Number of FK violations */
);
/*
** CAPI3REF: Finalize A Changeset Iterator
**
** This function is used to finalize an iterator allocated with
** [sqlite3changeset_start()].
**
** This function should only be called on iterators created using the
** [sqlite3changeset_start()] function. If an application calls this
** function with an iterator passed to a conflict-handler by
** [sqlite3changeset_apply()], [SQLITE_MISUSE] is immediately returned and the
** call has no effect.
**
** If an error was encountered within a call to an sqlite3changeset_xxx()
** function (for example an [SQLITE_CORRUPT] in [sqlite3changeset_next()] or an
** [SQLITE_NOMEM] in [sqlite3changeset_new()]) then an error code corresponding
** to that error is returned by this function. Otherwise, SQLITE_OK is
** returned. This is to allow the following pattern (pseudo-code):
**
** sqlite3changeset_start();
** while( SQLITE_ROW==sqlite3changeset_next() ){
** // Do something with change.
** }
** rc = sqlite3changeset_finalize();
** if( rc!=SQLITE_OK ){
** // An error has occurred
** }
*/
int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter);
/*
** CAPI3REF: Invert A Changeset
**
** This function is used to "invert" a changeset object. Applying an inverted
** changeset to a database reverses the effects of applying the uninverted
** changeset. Specifically:
**
** <ul>
** <li> Each DELETE change is changed to an INSERT, and
** <li> Each INSERT change is changed to a DELETE, and
** <li> For each UPDATE change, the old.* and new.* values are exchanged.
** </ul>
**
** This function does not change the order in which changes appear within
** the changeset. It merely reverses the sense of each individual change.
**
** If successful, a pointer to a buffer containing the inverted changeset
** is stored in *ppOut, the size of the same buffer is stored in *pnOut, and
** SQLITE_OK is returned. If an error occurs, both *pnOut and *ppOut are
** zeroed and an SQLite error code returned.
**
** It is the responsibility of the caller to eventually call sqlite3_free()
** on the *ppOut pointer to free the buffer allocation following a successful
** call to this function.
**
** WARNING/TODO: This function currently assumes that the input is a valid
** changeset. If it is not, the results are undefined.
*/
int sqlite3changeset_invert(
int nIn, const void *pIn, /* Input changeset */
int *pnOut, void **ppOut /* OUT: Inverse of input */
);
/*
** CAPI3REF: Concatenate Two Changeset Objects
**
** This function is used to concatenate two changesets, A and B, into a
** single changeset. The result is a changeset equivalent to applying
** changeset A followed by changeset B.
**
** This function combines the two input changesets using an
** sqlite3_changegroup object. Calling it produces similar results as the
** following code fragment:
**
** sqlite3_changegroup *pGrp;
** rc = sqlite3_changegroup_new(&pGrp);
** if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nA, pA);
** if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nB, pB);
** if( rc==SQLITE_OK ){
** rc = sqlite3changegroup_output(pGrp, pnOut, ppOut);
** }else{
** *ppOut = 0;
** *pnOut = 0;
** }
**
** Refer to the sqlite3_changegroup documentation below for details.
*/
int sqlite3changeset_concat(
int nA, /* Number of bytes in buffer pA */
void *pA, /* Pointer to buffer containing changeset A */
int nB, /* Number of bytes in buffer pB */
void *pB, /* Pointer to buffer containing changeset B */
int *pnOut, /* OUT: Number of bytes in output changeset */
void **ppOut /* OUT: Buffer containing output changeset */
);
/*
** Changegroup handle.
*/
typedef struct sqlite3_changegroup sqlite3_changegroup;
/*
** CAPI3REF: Combine two or more changesets into a single changeset.
**
** An sqlite3_changegroup object is used to combine two or more changesets
** (or patchsets) into a single changeset (or patchset). A single changegroup
** object may combine changesets or patchsets, but not both. The output is
** always in the same format as the input.
**
** If successful, this function returns SQLITE_OK and populates (SQLITE_CALLBACK *pp) with
** a pointer to a new sqlite3_changegroup object before returning. The caller
** should eventually free the returned object using a call to
** sqlite3changegroup_delete(). If an error occurs, an SQLite error code
** (i.e. SQLITE_NOMEM) is returned and *pp is set to NULL.
**
** The usual usage pattern for an sqlite3_changegroup object is as follows:
**
** <ul>
** <li> It is created using a call to sqlite3changegroup_new().
**
** <li> Zero or more changesets (or patchsets) are added to the object
** by calling sqlite3changegroup_add().
**
** <li> The result of combining all input changesets together is obtained
** by the application via a call to sqlite3changegroup_output().
**
** <li> The object is deleted using a call to sqlite3changegroup_delete().
** </ul>
**
** Any number of calls to add() and output() may be made between the calls to
** new() and delete(), and in any order.
**
** As well as the regular sqlite3changegroup_add() and
** sqlite3changegroup_output() functions, also available are the streaming
** versions sqlite3changegroup_add_strm() and sqlite3changegroup_output_strm().
*/
int sqlite3changegroup_new(sqlite3_changegroup **pp);
/*
** Add all changes within the changeset (or patchset) in buffer pData (size
** nData bytes) to the changegroup.
**
** If the buffer contains a patchset, then all prior calls to this function
** on the same changegroup object must also have specified patchsets. Or, if
** the buffer contains a changeset, so must have the earlier calls to this
** function. Otherwise, SQLITE_ERROR is returned and no changes are added
** to the changegroup.
**
** Rows within the changeset and changegroup are identified by the values in
** their PRIMARY KEY columns. A change in the changeset is considered to
** apply to the same row as a change already present in the changegroup if
** the two rows have the same primary key.
**
** Changes to rows that that do not already appear in the changegroup are
** simply copied into it. Or, if both the new changeset and the changegroup
** contain changes that apply to a single row, the final contents of the
** changegroup depends on the type of each change, as follows:
**
** <table border=1 style="margin-left:8ex;margin-right:8ex">
** <tr><th style="white-space:pre">Existing Change </th>
** <th style="white-space:pre">New Change </th>
** <th>Output Change
** <tr><td>INSERT <td>INSERT <td>
** The new change is ignored. This case does not occur if the new
** changeset was recorded immediately after the changesets already
** added to the changegroup.
** <tr><td>INSERT <td>UPDATE <td>
** The INSERT change remains in the changegroup. The values in the
** INSERT change are modified as if the row was inserted by the
** existing change and then updated according to the new change.
** <tr><td>INSERT <td>DELETE <td>
** The existing INSERT is removed from the changegroup. The DELETE is
** not added.
** <tr><td>UPDATE <td>INSERT <td>
** The new change is ignored. This case does not occur if the new
** changeset was recorded immediately after the changesets already
** added to the changegroup.
** <tr><td>UPDATE <td>UPDATE <td>
** The existing UPDATE remains within the changegroup. It is amended
** so that the accompanying values are as if the row was updated once
** by the existing change and then again by the new change.
** <tr><td>UPDATE <td>DELETE <td>
** The existing UPDATE is replaced by the new DELETE within the
** changegroup.
** <tr><td>DELETE <td>INSERT <td>
** If one or more of the column values in the row inserted by the
** new change differ from those in the row deleted by the existing
** change, the existing DELETE is replaced by an UPDATE within the
** changegroup. Otherwise, if the inserted row is exactly the same
** as the deleted row, the existing DELETE is simply discarded.
** <tr><td>DELETE <td>UPDATE <td>
** The new change is ignored. This case does not occur if the new
** changeset was recorded immediately after the changesets already
** added to the changegroup.
** <tr><td>DELETE <td>DELETE <td>
** The new change is ignored. This case does not occur if the new
** changeset was recorded immediately after the changesets already
** added to the changegroup.
** </table>
**
** If the new changeset contains changes to a table that is already present
** in the changegroup, then the number of columns and the position of the
** primary key columns for the table must be consistent. If this is not the
** case, this function fails with SQLITE_SCHEMA. If the input changeset
** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is
** returned. Or, if an out-of-memory condition occurs during processing, this
** function returns SQLITE_NOMEM. In all cases, if an error occurs the
** final contents of the changegroup is undefined.
**
** If no error occurs, SQLITE_OK is returned.
*/
int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
/*
** Obtain a buffer containing a changeset (or patchset) representing the
** current contents of the changegroup. If the inputs to the changegroup
** were themselves changesets, the output is a changeset. Or, if the
** inputs were patchsets, the output is also a patchset.
**
** As with the output of the sqlite3session_changeset() and
** sqlite3session_patchset() functions, all changes related to a single
** table are grouped together in the output of this function. Tables appear
** in the same order as for the very first changeset added to the changegroup.
** If the second or subsequent changesets added to the changegroup contain
** changes for tables that do not appear in the first changeset, they are
** appended onto the end of the output changeset, again in the order in
** which they are first encountered.
**
** If an error occurs, an SQLite error code is returned and the output
** variables (SQLITE_CALLBACK *pnData) and (*ppData) are set to 0. Otherwise, SQLITE_OK
** is returned and the output variables are set to the size of and a
** pointer to the output buffer, respectively. In this case it is the
** responsibility of the caller to eventually free the buffer using a
** call to sqlite3_free().
*/
int sqlite3changegroup_output(
sqlite3_changegroup*,
int *pnData, /* OUT: Size of output buffer in bytes */
void **ppData /* OUT: Pointer to output buffer */
);
/*
** Delete a changegroup object.
*/
void sqlite3changegroup_delete(sqlite3_changegroup*);
/*
** CAPI3REF: Apply A Changeset To A Database
**
** Apply a changeset to a database. This function attempts to update the
** "main" database attached to handle db with the changes found in the
** changeset passed via the second and third arguments.
**
** The fourth argument (xFilter) passed to this function is the "filter
** callback". If it is not NULL, then for each table affected by at least one
** change in the changeset, the filter callback is invoked with
** the table name as the second argument, and a copy of the context pointer
** passed as the sixth argument to this function as the first. If the "filter
** callback" returns zero, then no attempt is made to apply any changes to
** the table. Otherwise, if the return value is non-zero or the xFilter
** argument to this function is NULL, all changes related to the table are
** attempted.
**
** For each table that is not excluded by the filter callback, this function
** tests that the target database contains a compatible table. A table is
** considered compatible if all of the following are true:
**
** <ul>
** <li> The table has the same name as the name recorded in the
** changeset, and
** <li> The table has the same number of columns as recorded in the
** changeset, and
** <li> The table has primary key columns in the same position as
** recorded in the changeset.
** </ul>
**
** If there is no compatible table, it is not an error, but none of the
** changes associated with the table are applied. A warning message is issued
** via the sqlite3_log() mechanism with the error code SQLITE_SCHEMA. At most
** one such warning is issued for each table in the changeset.
**
** For each change for which there is a compatible table, an attempt is made
** to modify the table contents according to the UPDATE, INSERT or DELETE
** change. If a change cannot be applied cleanly, the conflict handler
** function passed as the fifth argument to sqlite3changeset_apply() may be
** invoked. A description of exactly when the conflict handler is invoked for
** each type of change is below.
**
** Unlike the xFilter argument, xConflict may not be passed NULL. The results
** of passing anything other than a valid function pointer as the xConflict
** argument are undefined.
**
** Each time the conflict handler function is invoked, it must return one
** of [SQLITE_CHANGESET_OMIT], [SQLITE_CHANGESET_ABORT] or
** [SQLITE_CHANGESET_REPLACE]. SQLITE_CHANGESET_REPLACE may only be returned
** if the second argument passed to the conflict handler is either
** SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If the conflict-handler
** returns an illegal value, any changes already made are rolled back and
** the call to sqlite3changeset_apply() returns SQLITE_MISUSE. Different
** actions are taken by sqlite3changeset_apply() depending on the value
** returned by each invocation of the conflict-handler function. Refer to
** the documentation for the three
** [SQLITE_CHANGESET_OMIT|available return values] for details.
**
** <dl>
** <dt>DELETE Changes<dd>
** For each DELETE change, this function checks if the target database
** contains a row with the same primary key value (or values) as the
** original row values stored in the changeset. If it does, and the values
** stored in all non-primary key columns also match the values stored in
** the changeset the row is deleted from the target database.
**
** If a row with matching primary key values is found, but one or more of
** the non-primary key fields contains a value different from the original
** row value stored in the changeset, the conflict-handler function is
** invoked with [SQLITE_CHANGESET_DATA] as the second argument.
**
** If no row with matching primary key values is found in the database,
** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND]
** passed as the second argument.
**
** If the DELETE operation is attempted, but SQLite returns SQLITE_CONSTRAINT
** (which can only happen if a foreign key constraint is violated), the
** conflict-handler function is invoked with [SQLITE_CHANGESET_CONSTRAINT]
** passed as the second argument. This includes the case where the DELETE
** operation is attempted because an earlier call to the conflict handler
** function returned [SQLITE_CHANGESET_REPLACE].
**
** <dt>INSERT Changes<dd>
** For each INSERT change, an attempt is made to insert the new row into
** the database.
**
** If the attempt to insert the row fails because the database already
** contains a row with the same primary key values, the conflict handler
** function is invoked with the second argument set to
** [SQLITE_CHANGESET_CONFLICT].
**
** If the attempt to insert the row fails because of some other constraint
** violation (e.g. NOT NULL or UNIQUE), the conflict handler function is
** invoked with the second argument set to [SQLITE_CHANGESET_CONSTRAINT].
** This includes the case where the INSERT operation is re-attempted because
** an earlier call to the conflict handler function returned
** [SQLITE_CHANGESET_REPLACE].
**
** <dt>UPDATE Changes<dd>
** For each UPDATE change, this function checks if the target database
** contains a row with the same primary key value (or values) as the
** original row values stored in the changeset. If it does, and the values
** stored in all non-primary key columns also match the values stored in
** the changeset the row is updated within the target database.
**
** If a row with matching primary key values is found, but one or more of
** the non-primary key fields contains a value different from an original
** row value stored in the changeset, the conflict-handler function is
** invoked with [SQLITE_CHANGESET_DATA] as the second argument. Since
** UPDATE changes only contain values for non-primary key fields that are
** to be modified, only those fields need to match the original values to
** avoid the SQLITE_CHANGESET_DATA conflict-handler callback.
**
** If no row with matching primary key values is found in the database,
** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND]
** passed as the second argument.
**
** If the UPDATE operation is attempted, but SQLite returns
** SQLITE_CONSTRAINT, the conflict-handler function is invoked with
** [SQLITE_CHANGESET_CONSTRAINT] passed as the second argument.
** This includes the case where the UPDATE operation is attempted after
** an earlier call to the conflict handler function returned
** [SQLITE_CHANGESET_REPLACE].
** </dl>
**
** It is safe to execute SQL statements, including those that write to the
** table that the callback related to, from within the xConflict callback.
** This can be used to further customize the applications conflict
** resolution strategy.
**
** All changes made by this function are enclosed in a savepoint transaction.
** If any other error (aside from a constraint failure when attempting to
** write to the target database) occurs, then the savepoint transaction is
** rolled back, restoring the target database to its original state, and an
** SQLite error code returned.
*/
int sqlite3changeset_apply(
sqlite3 *db, /* Apply change to "main" db of this handle */
int nChangeset, /* Size of changeset in bytes */
void *pChangeset, /* Changeset blob */
int(SQLITE_CALLBACK *xFilter)(
void *pCtx, /* Copy of sixth arg to _apply() */
const char *zTab /* Table name */
),
int(SQLITE_CALLBACK *xConflict)(
void *pCtx, /* Copy of sixth arg to _apply() */
int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
sqlite3_changeset_iter *p /* Handle describing change and conflict */
),
void *pCtx /* First argument passed to xConflict */
);
/*
** CAPI3REF: Constants Passed To The Conflict Handler
**
** Values that may be passed as the second argument to a conflict-handler.
**
** <dl>
** <dt>SQLITE_CHANGESET_DATA<dd>
** The conflict handler is invoked with CHANGESET_DATA as the second argument
** when processing a DELETE or UPDATE change if a row with the required
** PRIMARY KEY fields is present in the database, but one or more other
** (non primary-key) fields modified by the update do not contain the
** expected "before" values.
**
** The conflicting row, in this case, is the database row with the matching
** primary key.
**
** <dt>SQLITE_CHANGESET_NOTFOUND<dd>
** The conflict handler is invoked with CHANGESET_NOTFOUND as the second
** argument when processing a DELETE or UPDATE change if a row with the
** required PRIMARY KEY fields is not present in the database.
**
** There is no conflicting row in this case. The results of invoking the
** sqlite3changeset_conflict() API are undefined.
**
** <dt>SQLITE_CHANGESET_CONFLICT<dd>
** CHANGESET_CONFLICT is passed as the second argument to the conflict
** handler while processing an INSERT change if the operation would result
** in duplicate primary key values.
**
** The conflicting row in this case is the database row with the matching
** primary key.
**
** <dt>SQLITE_CHANGESET_FOREIGN_KEY<dd>
** If foreign key handling is enabled, and applying a changeset leaves the
** database in a state containing foreign key violations, the conflict
** handler is invoked with CHANGESET_FOREIGN_KEY as the second argument
** exactly once before the changeset is committed. If the conflict handler
** returns CHANGESET_OMIT, the changes, including those that caused the
** foreign key constraint violation, are committed. Or, if it returns
** CHANGESET_ABORT, the changeset is rolled back.
**
** No current or conflicting row information is provided. The only function
** it is possible to call on the supplied sqlite3_changeset_iter handle
** is sqlite3changeset_fk_conflicts().
**
** <dt>SQLITE_CHANGESET_CONSTRAINT<dd>
** If any other constraint violation occurs while applying a change (i.e.
** a UNIQUE, CHECK or NOT NULL constraint), the conflict handler is
** invoked with CHANGESET_CONSTRAINT as the second argument.
**
** There is no conflicting row in this case. The results of invoking the
** sqlite3changeset_conflict() API are undefined.
**
** </dl>
*/
#define SQLITE_CHANGESET_DATA 1
#define SQLITE_CHANGESET_NOTFOUND 2
#define SQLITE_CHANGESET_CONFLICT 3
#define SQLITE_CHANGESET_CONSTRAINT 4
#define SQLITE_CHANGESET_FOREIGN_KEY 5
/*
** CAPI3REF: Constants Returned By The Conflict Handler
**
** A conflict handler callback must return one of the following three values.
**
** <dl>
** <dt>SQLITE_CHANGESET_OMIT<dd>
** If a conflict handler returns this value no special action is taken. The
** change that caused the conflict is not applied. The session module
** continues to the next change in the changeset.
**
** <dt>SQLITE_CHANGESET_REPLACE<dd>
** This value may only be returned if the second argument to the conflict
** handler was SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If this
** is not the case, any changes applied so far are rolled back and the
** call to sqlite3changeset_apply() returns SQLITE_MISUSE.
**
** If CHANGESET_REPLACE is returned by an SQLITE_CHANGESET_DATA conflict
** handler, then the conflicting row is either updated or deleted, depending
** on the type of change.
**
** If CHANGESET_REPLACE is returned by an SQLITE_CHANGESET_CONFLICT conflict
** handler, then the conflicting row is removed from the database and a
** second attempt to apply the change is made. If this second attempt fails,
** the original row is restored to the database before continuing.
**
** <dt>SQLITE_CHANGESET_ABORT<dd>
** If this value is returned, any changes applied so far are rolled back
** and the call to sqlite3changeset_apply() returns SQLITE_ABORT.
** </dl>
*/
#define SQLITE_CHANGESET_OMIT 0
#define SQLITE_CHANGESET_REPLACE 1
#define SQLITE_CHANGESET_ABORT 2
/*
** CAPI3REF: Streaming Versions of API functions.
**
** The six streaming API xxx_strm() functions serve similar purposes to the
** corresponding non-streaming API functions:
**
** <table border=1 style="margin-left:8ex;margin-right:8ex">
** <tr><th>Streaming function<th>Non-streaming equivalent</th>
** <tr><td>sqlite3changeset_apply_str<td>[sqlite3changeset_apply]
** <tr><td>sqlite3changeset_concat_str<td>[sqlite3changeset_concat]
** <tr><td>sqlite3changeset_invert_str<td>[sqlite3changeset_invert]
** <tr><td>sqlite3changeset_start_str<td>[sqlite3changeset_start]
** <tr><td>sqlite3session_changeset_str<td>[sqlite3session_changeset]
** <tr><td>sqlite3session_patchset_str<td>[sqlite3session_patchset]
** </table>
**
** Non-streaming functions that accept changesets (or patchsets) as input
** require that the entire changeset be stored in a single buffer in memory.
** Similarly, those that return a changeset or patchset do so by returning
** a pointer to a single large buffer allocated using sqlite3_malloc().
** Normally this is convenient. However, if an application running in a
** low-memory environment is required to handle very large changesets, the
** large contiguous memory allocations required can become onerous.
**
** In order to avoid this problem, instead of a single large buffer, input
** is passed to a streaming API functions by way of a callback function that
** the sessions module invokes to incrementally request input data as it is
** required. In all cases, a pair of API function parameters such as
**
** <pre>
** int nChangeset,
** void *pChangeset,
** </pre>
**
** Is replaced by:
**
** <pre>
** int (SQLITE_CALLBACK *xInput)(void *pIn, void *pData, int *pnData),
** void *pIn,
** </pre>
**
** Each time the xInput callback is invoked by the sessions module, the first
** argument passed is a copy of the supplied pIn context pointer. The second
** argument, pData, points to a buffer (SQLITE_CALLBACK *pnData) bytes in size. Assuming no
** error occurs the xInput method should copy up to (SQLITE_CALLBACK *pnData) bytes of data
** into the buffer and set (SQLITE_CALLBACK *pnData) to the actual number of bytes copied
** before returning SQLITE_OK. If the input is completely exhausted, (SQLITE_CALLBACK *pnData)
** should be set to zero to indicate this. Or, if an error occurs, an SQLite
** error code should be returned. In all cases, if an xInput callback returns
** an error, all processing is abandoned and the streaming API function
** returns a copy of the error code to the caller.
**
** In the case of sqlite3changeset_start_strm(), the xInput callback may be
** invoked by the sessions module at any point during the lifetime of the
** iterator. If such an xInput callback returns an error, the iterator enters
** an error state, whereby all subsequent calls to iterator functions
** immediately fail with the same error code as returned by xInput.
**
** Similarly, streaming API functions that return changesets (or patchsets)
** return them in chunks by way of a callback function instead of via a
** pointer to a single large buffer. In this case, a pair of parameters such
** as:
**
** <pre>
** int *pnChangeset,
** void **ppChangeset,
** </pre>
**
** Is replaced by:
**
** <pre>
** int (SQLITE_CALLBACK *xOutput)(void *pOut, const void *pData, int nData),
** void *pOut
** </pre>
**
** The xOutput callback is invoked zero or more times to return data to
** the application. The first parameter passed to each call is a copy of the
** pOut pointer supplied by the application. The second parameter, pData,
** points to a buffer nData bytes in size containing the chunk of output
** data being returned. If the xOutput callback successfully processes the
** supplied data, it should return SQLITE_OK to indicate success. Otherwise,
** it should return some other SQLite error code. In this case processing
** is immediately abandoned and the streaming API function returns a copy
** of the xOutput error code to the application.
**
** The sessions module never invokes an xOutput callback with the third
** parameter set to a value less than or equal to zero. Other than this,
** no guarantees are made as to the size of the chunks of data returned.
*/
int sqlite3changeset_apply_strm(
sqlite3 *db, /* Apply change to "main" db of this handle */
int (SQLITE_CALLBACK *xInput)(void *pIn, void *pData, int *pnData), /* Input function */
void *pIn, /* First arg for xInput */
int(SQLITE_CALLBACK *xFilter)(
void *pCtx, /* Copy of sixth arg to _apply() */
const char *zTab /* Table name */
),
int(SQLITE_CALLBACK *xConflict)(
void *pCtx, /* Copy of sixth arg to _apply() */
int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
sqlite3_changeset_iter *p /* Handle describing change and conflict */
),
void *pCtx /* First argument passed to xConflict */
);
int sqlite3changeset_concat_strm(
int (SQLITE_CALLBACK *xInputA)(void *pIn, void *pData, int *pnData),
void *pInA,
int (SQLITE_CALLBACK *xInputB)(void *pIn, void *pData, int *pnData),
void *pInB,
int (SQLITE_CALLBACK *xOutput)(void *pOut, const void *pData, int nData),
void *pOut
);
int sqlite3changeset_invert_strm(
int (SQLITE_CALLBACK *xInput)(void *pIn, void *pData, int *pnData),
void *pIn,
int (SQLITE_CALLBACK *xOutput)(void *pOut, const void *pData, int nData),
void *pOut
);
int sqlite3changeset_start_strm(
sqlite3_changeset_iter **pp,
int (SQLITE_CALLBACK *xInput)(void *pIn, void *pData, int *pnData),
void *pIn
);
int sqlite3session_changeset_strm(
sqlite3_session *pSession,
int (SQLITE_CALLBACK *xOutput)(void *pOut, const void *pData, int nData),
void *pOut
);
int sqlite3session_patchset_strm(
sqlite3_session *pSession,
int (SQLITE_CALLBACK *xOutput)(void *pOut, const void *pData, int nData),
void *pOut
);
int sqlite3changegroup_add_strm(sqlite3_changegroup*,
int (SQLITE_CALLBACK *xInput)(void *pIn, void *pData, int *pnData),
void *pIn
);
int sqlite3changegroup_output_strm(sqlite3_changegroup*,
int (SQLITE_CALLBACK *xOutput)(void *pOut, const void *pData, int nData),
void *pOut
);
/*
** Make sure we can call this stuff from C++.
*/
#ifdef __cplusplus
}
#endif
#endif /* !defined(__SQLITESESSION_H_) && defined(SQLITE_ENABLE_SESSION) */
/******** End of sqlite3session.h *********/
/******** Begin file fts5.h *********/
/*
** 2014 May 31
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
|
| ︙ | ︙ | |||
8143 8144 8145 8146 8147 8148 8149 | ** the sqlite3_module.xFindFunction() method. */ typedef struct Fts5ExtensionApi Fts5ExtensionApi; typedef struct Fts5Context Fts5Context; typedef struct Fts5PhraseIter Fts5PhraseIter; | | | 9794 9795 9796 9797 9798 9799 9800 9801 9802 9803 9804 9805 9806 9807 9808 | ** the sqlite3_module.xFindFunction() method. */ typedef struct Fts5ExtensionApi Fts5ExtensionApi; typedef struct Fts5Context Fts5Context; typedef struct Fts5PhraseIter Fts5PhraseIter; typedef void (SQLITE_CALLBACK *fts5_extension_function)( const Fts5ExtensionApi *pApi, /* API offered by current FTS version */ Fts5Context *pFts, /* First arg to pass to pApi functions */ sqlite3_context *pCtx, /* Context for returning result/error */ int nVal, /* Number of values in apVal[] array */ sqlite3_value **apVal /* Array of trailing arguments */ ); |
| ︙ | ︙ | |||
8194 8195 8196 8197 8198 8199 8200 | ** returned. ** ** This function may be quite inefficient if used with an FTS5 table ** created with the "columnsize=0" option. ** ** xColumnText: ** This function attempts to retrieve the text of column iCol of the | | | | | 9845 9846 9847 9848 9849 9850 9851 9852 9853 9854 9855 9856 9857 9858 9859 9860 9861 9862 9863 | ** returned. ** ** This function may be quite inefficient if used with an FTS5 table ** created with the "columnsize=0" option. ** ** xColumnText: ** This function attempts to retrieve the text of column iCol of the ** current document. If successful, (SQLITE_CALLBACK *pz) is set to point to a buffer ** containing the text in utf-8 encoding, (SQLITE_CALLBACK *pn) is set to the size in bytes ** (not characters) of the buffer and SQLITE_OK is returned. Otherwise, ** if an error occurs, an SQLite error code is returned and the final values ** of (SQLITE_CALLBACK *pz) and (*pn) are undefined. ** ** xPhraseCount: ** Returns the number of phrases in the current query expression. ** ** xPhraseSize: ** Returns the number of tokens in phrase iPhrase of the query. Phrases ** are numbered starting from zero. |
| ︙ | ︙ | |||
8248 8249 8250 8251 8252 8253 8254 | ** xQueryPhrase(pFts5, iPhrase, pUserData, xCallback): ** This API function is used to query the FTS table for phrase iPhrase ** of the current query. Specifically, a query equivalent to: ** ** ... FROM ftstable WHERE ftstable MATCH $p ORDER BY rowid ** ** with $p set to a phrase equivalent to the phrase iPhrase of the | > > | | | | | | 9899 9900 9901 9902 9903 9904 9905 9906 9907 9908 9909 9910 9911 9912 9913 9914 9915 9916 9917 9918 9919 | ** xQueryPhrase(pFts5, iPhrase, pUserData, xCallback): ** This API function is used to query the FTS table for phrase iPhrase ** of the current query. Specifically, a query equivalent to: ** ** ... FROM ftstable WHERE ftstable MATCH $p ORDER BY rowid ** ** with $p set to a phrase equivalent to the phrase iPhrase of the ** current query is executed. Any column filter that applies to ** phrase iPhrase of the current query is included in $p. For each ** row visited, the callback function passed as the fourth argument ** is invoked. The context and API objects passed to the callback ** function may be used to access the properties of each matched row. ** Invoking Api.xUserData() returns a copy of the pointer passed as ** the third argument to pUserData. ** ** If the callback function returns any value other than SQLITE_OK, the ** query is abandoned and the xQueryPhrase function returns immediately. ** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK. ** Otherwise, the error code is propagated upwards. ** ** If the query runs to completion without incident, SQLITE_OK is returned. |
| ︙ | ︙ | |||
8305 8306 8307 8308 8309 8310 8311 | ** ** ** xRowCount(pFts5, pnRow) ** ** This function is used to retrieve the total number of rows in the table. ** In other words, the same value that would be returned by: ** | | | 9958 9959 9960 9961 9962 9963 9964 9965 9966 9967 9968 9969 9970 9971 9972 | ** ** ** xRowCount(pFts5, pnRow) ** ** This function is used to retrieve the total number of rows in the table. ** In other words, the same value that would be returned by: ** ** SELECT count(SQLITE_CALLBACK *) FROM ftstable; ** ** xPhraseFirst() ** This function is used, along with type Fts5PhraseIter and the xPhraseNext ** method, to iterate through all instances of a single query phrase within ** the current row. This is the same information as is accessible via the ** xInstCount/xInst APIs. While the xInstCount/xInst APIs are more convenient ** to use, this API may be faster under some circumstances. To iterate |
| ︙ | ︙ | |||
8372 8373 8374 8375 8376 8377 8378 |
**
** xPhraseNextColumn()
** See xPhraseFirstColumn above.
*/
struct Fts5ExtensionApi {
int iVersion; /* Currently always set to 3 */
| | | | | | | | | | | | | | | | | | | | | | | 10025 10026 10027 10028 10029 10030 10031 10032 10033 10034 10035 10036 10037 10038 10039 10040 10041 10042 10043 10044 10045 10046 10047 10048 10049 10050 10051 10052 10053 10054 10055 10056 10057 10058 10059 10060 10061 10062 10063 10064 10065 10066 10067 10068 10069 10070 10071 |
**
** xPhraseNextColumn()
** See xPhraseFirstColumn above.
*/
struct Fts5ExtensionApi {
int iVersion; /* Currently always set to 3 */
void *(SQLITE_CALLBACK *xUserData)(Fts5Context*);
int (SQLITE_CALLBACK *xColumnCount)(Fts5Context*);
int (SQLITE_CALLBACK *xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
int (SQLITE_CALLBACK *xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken);
int (SQLITE_CALLBACK *xTokenize)(Fts5Context*,
const char *pText, int nText, /* Text to tokenize */
void *pCtx, /* Context passed to xToken() */
int (SQLITE_CALLBACK *xToken)(void*, int, const char*, int, int, int) /* Callback */
);
int (SQLITE_CALLBACK *xPhraseCount)(Fts5Context*);
int (SQLITE_CALLBACK *xPhraseSize)(Fts5Context*, int iPhrase);
int (SQLITE_CALLBACK *xInstCount)(Fts5Context*, int *pnInst);
int (SQLITE_CALLBACK *xInst)(Fts5Context*, int iIdx, int *piPhrase, int *piCol, int *piOff);
sqlite3_int64 (SQLITE_CALLBACK *xRowid)(Fts5Context*);
int (SQLITE_CALLBACK *xColumnText)(Fts5Context*, int iCol, const char **pz, int *pn);
int (SQLITE_CALLBACK *xColumnSize)(Fts5Context*, int iCol, int *pnToken);
int (SQLITE_CALLBACK *xQueryPhrase)(Fts5Context*, int iPhrase, void *pUserData,
int(SQLITE_CALLBACK *)(const Fts5ExtensionApi*,Fts5Context*,void*)
);
int (SQLITE_CALLBACK *xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*));
void *(SQLITE_CALLBACK *xGetAuxdata)(Fts5Context*, int bClear);
int (SQLITE_CALLBACK *xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
void (SQLITE_CALLBACK *xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff);
int (SQLITE_CALLBACK *xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*);
void (SQLITE_CALLBACK *xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol);
};
/*
** CUSTOM AUXILIARY FUNCTIONS
*************************************************************************/
/*************************************************************************
|
| ︙ | ︙ | |||
8432 8433 8434 8435 8436 8437 8438 | ** pointer provided by the application when the fts5_tokenizer object ** was registered with FTS5 (the third argument to xCreateTokenizer()). ** The second and third arguments are an array of nul-terminated strings ** containing the tokenizer arguments, if any, specified following the ** tokenizer name as part of the CREATE VIRTUAL TABLE statement used ** to create the FTS5 table. ** | | | 10085 10086 10087 10088 10089 10090 10091 10092 10093 10094 10095 10096 10097 10098 10099 | ** pointer provided by the application when the fts5_tokenizer object ** was registered with FTS5 (the third argument to xCreateTokenizer()). ** The second and third arguments are an array of nul-terminated strings ** containing the tokenizer arguments, if any, specified following the ** tokenizer name as part of the CREATE VIRTUAL TABLE statement used ** to create the FTS5 table. ** ** The final argument is an output variable. If successful, (SQLITE_CALLBACK *ppOut) ** should be set to point to the new tokenizer handle and SQLITE_OK ** returned. If an error occurs, some value other than SQLITE_OK should ** be returned. In this case, fts5 assumes that the final value of *ppOut ** is undefined. ** ** xDelete: ** This function is invoked to delete a tokenizer handle previously |
| ︙ | ︙ | |||
8606 8607 8608 8609 8610 8611 8612 |
** provide synonyms when tokenizing document text (method (2)) or query
** text (method (3)), not both. Doing so will not cause any errors, but is
** inefficient.
*/
typedef struct Fts5Tokenizer Fts5Tokenizer;
typedef struct fts5_tokenizer fts5_tokenizer;
struct fts5_tokenizer {
| | | | | | 10259 10260 10261 10262 10263 10264 10265 10266 10267 10268 10269 10270 10271 10272 10273 10274 10275 10276 10277 10278 10279 |
** provide synonyms when tokenizing document text (method (2)) or query
** text (method (3)), not both. Doing so will not cause any errors, but is
** inefficient.
*/
typedef struct Fts5Tokenizer Fts5Tokenizer;
typedef struct fts5_tokenizer fts5_tokenizer;
struct fts5_tokenizer {
int (SQLITE_CALLBACK *xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
void (SQLITE_CALLBACK *xDelete)(Fts5Tokenizer*);
int (SQLITE_CALLBACK *xTokenize)(Fts5Tokenizer*,
void *pCtx,
int flags, /* Mask of FTS5_TOKENIZE_* flags */
const char *pText, int nText,
int (SQLITE_CALLBACK *xToken)(
void *pCtx, /* Copy of 2nd argument to xTokenize() */
int tflags, /* Mask of FTS5_TOKEN_* flags */
const char *pToken, /* Pointer to buffer containing token */
int nToken, /* Size of token in bytes */
int iStart, /* Byte offset of token within input text */
int iEnd /* Byte offset of end of token within input text */
)
|
| ︙ | ︙ | |||
8645 8646 8647 8648 8649 8650 8651 |
** FTS5 EXTENSION REGISTRATION API
*/
typedef struct fts5_api fts5_api;
struct fts5_api {
int iVersion; /* Currently always set to 2 */
/* Create a new tokenizer */
| | | | | | > | 10298 10299 10300 10301 10302 10303 10304 10305 10306 10307 10308 10309 10310 10311 10312 10313 10314 10315 10316 10317 10318 10319 10320 10321 10322 10323 10324 10325 10326 10327 10328 10329 10330 10331 10332 10333 10334 10335 10336 10337 10338 10339 10340 10341 10342 |
** FTS5 EXTENSION REGISTRATION API
*/
typedef struct fts5_api fts5_api;
struct fts5_api {
int iVersion; /* Currently always set to 2 */
/* Create a new tokenizer */
int (SQLITE_CALLBACK *xCreateTokenizer)(
fts5_api *pApi,
const char *zName,
void *pContext,
fts5_tokenizer *pTokenizer,
void (SQLITE_CALLBACK *xDestroy)(void*)
);
/* Find an existing tokenizer */
int (SQLITE_CALLBACK *xFindTokenizer)(
fts5_api *pApi,
const char *zName,
void **ppContext,
fts5_tokenizer *pTokenizer
);
/* Create a new auxiliary function */
int (SQLITE_CALLBACK *xCreateFunction)(
fts5_api *pApi,
const char *zName,
void *pContext,
fts5_extension_function xFunction,
void (SQLITE_CALLBACK *xDestroy)(void*)
);
};
/*
** END OF REGISTRATION API
*************************************************************************/
#ifdef __cplusplus
} /* end of the 'extern "C"' block */
#endif
#endif /* _FTS5_H */
/******** End of fts5.h *********/
|
Changes to src/stat.c.
| ︙ | ︙ | |||
79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
style_submenu_element("Web-Cache", "Web-Cache Stats", "cachestat");
}
style_submenu_element("Activity Reports", 0, "reports");
style_submenu_element("SHA1 Collisions", 0, "hash-collisions");
if( sqlite3_compileoption_used("ENABLE_DBSTAT_VTAB") ){
style_submenu_element("Table Sizes", 0, "repo-tabsize");
}
@ <table class="label-value">
@ <tr><th>Repository Size:</th><td>
fsize = file_size(g.zRepositoryName);
bigSizeName(sizeof(zBuf), zBuf, fsize);
@ %s(zBuf)
@ </td></tr>
if( !brief ){
| > > > | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
style_submenu_element("Web-Cache", "Web-Cache Stats", "cachestat");
}
style_submenu_element("Activity Reports", 0, "reports");
style_submenu_element("SHA1 Collisions", 0, "hash-collisions");
if( sqlite3_compileoption_used("ENABLE_DBSTAT_VTAB") ){
style_submenu_element("Table Sizes", 0, "repo-tabsize");
}
if( g.perm.Admin || g.perm.Setup || db_get_boolean("test_env_enable",0) ){
style_submenu_element("Environment", 0, "test_env");
}
@ <table class="label-value">
@ <tr><th>Repository Size:</th><td>
fsize = file_size(g.zRepositoryName);
bigSizeName(sizeof(zBuf), zBuf, fsize);
@ %s(zBuf)
@ </td></tr>
if( !brief ){
|
| ︙ | ︙ | |||
361 362 363 364 365 366 367 368 369 370 371 372 373 374 |
login_check_credentials();
if( !g.perm.Admin ){ login_needed(0); return; }
style_header("Repository Schema");
style_adunit_config(ADUNIT_RIGHT_OK);
style_submenu_element("Stat", "Repository Stats", "stat");
style_submenu_element("URLs", "URLs and Checkouts", "urllist");
db_prepare(&q, "SELECT sql FROM %s.sqlite_master WHERE sql IS NOT NULL",
db_name("repository"));
@ <pre>
while( db_step(&q)==SQLITE_ROW ){
@ %h(db_column_text(&q, 0));
}
@ </pre>
| > > > | 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
login_check_credentials();
if( !g.perm.Admin ){ login_needed(0); return; }
style_header("Repository Schema");
style_adunit_config(ADUNIT_RIGHT_OK);
style_submenu_element("Stat", "Repository Stats", "stat");
style_submenu_element("URLs", "URLs and Checkouts", "urllist");
if( sqlite3_compileoption_used("ENABLE_DBSTAT_VTAB") ){
style_submenu_element("Table Sizes", 0, "repo-tabsize");
}
db_prepare(&q, "SELECT sql FROM %s.sqlite_master WHERE sql IS NOT NULL",
db_name("repository"));
@ <pre>
while( db_step(&q)==SQLITE_ROW ){
@ %h(db_column_text(&q, 0));
}
@ </pre>
|
| ︙ | ︙ | |||
387 388 389 390 391 392 393 394 395 |
char zBuf[100];
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
style_header("Repository Table Sizes");
style_adunit_config(ADUNIT_RIGHT_OK);
style_submenu_element("Stat", "Repository Stats", "stat");
db_multi_exec(
"CREATE VIRTUAL TABLE temp.dbx USING dbstat(%s);"
| > > > | | 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 |
char zBuf[100];
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
style_header("Repository Table Sizes");
style_adunit_config(ADUNIT_RIGHT_OK);
style_submenu_element("Stat", "Repository Stats", "stat");
if( g.perm.Admin ){
style_submenu_element("Schema", "Repository Schema", "repo_schema");
}
db_multi_exec(
"CREATE VIRTUAL TABLE temp.dbx USING dbstat(%s);"
"CREATE TEMP TABLE trans(name TEXT PRIMARY KEY,tabname TEXT)WITHOUT ROWID;"
"INSERT INTO trans(name,tabname)"
" SELECT name, tbl_name FROM %s.sqlite_master;"
"CREATE TEMP TABLE piechart(amt REAL, label TEXT);"
"INSERT INTO piechart(amt,label)"
" SELECT count(*), "
" coalesce((SELECT tabname FROM trans WHERE trans.name=dbx.name),name)"
" FROM dbx"
|
| ︙ | ︙ |
Changes to src/statrep.c.
| ︙ | ︙ | |||
309 310 311 312 313 314 315 |
@ <td colspan='2'>Yearly total: %d(nEventsPerYear)</td>
@</tr>
}
@ </tbody></table>
if(nEventTotal){
const char *zAvgLabel = includeMonth ? "month" : "year";
int nAvg = iterations ? (nEventTotal/iterations) : 0;
| | | | 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 |
@ <td colspan='2'>Yearly total: %d(nEventsPerYear)</td>
@</tr>
}
@ </tbody></table>
if(nEventTotal){
const char *zAvgLabel = includeMonth ? "month" : "year";
int nAvg = iterations ? (nEventTotal/iterations) : 0;
@ <br /><div>Total events: %d(nEventTotal)
@ <br />Average per active %s(zAvgLabel): %d(nAvg)
@ </div>
}
if( !includeMonth ){
output_table_sorting_javascript("statsTable","tnx",-1);
}
}
|
| ︙ | ︙ | |||
340 341 342 343 344 345 346 |
"CREATE TEMP VIEW piechart(amt,label) AS"
" SELECT count(*), ifnull(euser,user) FROM v_reports"
" GROUP BY ifnull(euser,user) ORDER BY count(*) DESC;"
);
if( db_int(0, "SELECT count(*) FROM piechart")>=2 ){
@ <center><svg width=700 height=400>
piechart_render(700, 400, PIE_OTHER|PIE_PERCENT);
| | | 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 |
"CREATE TEMP VIEW piechart(amt,label) AS"
" SELECT count(*), ifnull(euser,user) FROM v_reports"
" GROUP BY ifnull(euser,user) ORDER BY count(*) DESC;"
);
if( db_int(0, "SELECT count(*) FROM piechart")>=2 ){
@ <center><svg width=700 height=400>
piechart_render(700, 400, PIE_OTHER|PIE_PERCENT);
@ </svg></centre><hr />
}
@ <table class='statistics-report-table-events' border='0'
@ cellpadding='2' cellspacing='0' id='statsTable'>
@ <thead><tr>
@ <th>User</th>
@ <th>Events</th>
@ <th width='90%%'><!-- relative commits graph --></th>
|
| ︙ | ︙ | |||
501 502 503 504 505 506 507 |
" WHERE ifnull(coalesce(euser,user,'')=%Q,1)"
" GROUP BY 2 ORDER BY cast(strftime('%%w', mtime) AS INT);"
, zUserName
);
if( db_int(0, "SELECT count(*) FROM piechart")>=2 ){
@ <center><svg width=700 height=400>
piechart_render(700, 400, PIE_OTHER|PIE_PERCENT);
| | | 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 |
" WHERE ifnull(coalesce(euser,user,'')=%Q,1)"
" GROUP BY 2 ORDER BY cast(strftime('%%w', mtime) AS INT);"
, zUserName
);
if( db_int(0, "SELECT count(*) FROM piechart")>=2 ){
@ <center><svg width=700 height=400>
piechart_render(700, 400, PIE_OTHER|PIE_PERCENT);
@ </svg></centre><hr />
}
@ <table class='statistics-report-table-events' border='0'
@ cellpadding='2' cellspacing='0' id='statsTable'>
@ <thead><tr>
@ <th>DoW</th>
@ <th>Day</th>
@ <th>Events</th>
|
| ︙ | ︙ | |||
569 570 571 572 573 574 575 |
" SELECT substr(date('now'),1,4) UNION ALL"
" SELECT b-1 FROM a"
" WHERE b>0+(SELECT substr(date(min(mtime)),1,4) FROM event)"
") SELECT b, b FROM a ORDER BY b DESC");
if( zYear==0 || strlen(zYear)!=4 ){
zYear = db_text("1970","SELECT substr(date('now'),1,4);");
}
| | | 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 |
" SELECT substr(date('now'),1,4) UNION ALL"
" SELECT b-1 FROM a"
" WHERE b>0+(SELECT substr(date(min(mtime)),1,4) FROM event)"
") SELECT b, b FROM a ORDER BY b DESC");
if( zYear==0 || strlen(zYear)!=4 ){
zYear = db_text("1970","SELECT substr(date('now'),1,4);");
}
cgi_printf("<br />");
db_prepare(&q,
"SELECT DISTINCT strftime('%%W',mtime) AS wk, "
" count(*) AS n "
" FROM v_reports "
" WHERE %Q=substr(date(mtime),1,4) "
" AND mtime < current_timestamp "
" AND ifnull(coalesce(euser,user,'')=%Q,1)"
|
| ︙ | ︙ | |||
631 632 633 634 635 636 637 |
}
cgi_printf("</td></tr>");
}
db_finalize(&q);
cgi_printf("</tbody></table>");
if(total){
int nAvg = iterations ? (total/iterations) : 0;
| | | 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 |
}
cgi_printf("</td></tr>");
}
db_finalize(&q);
cgi_printf("</tbody></table>");
if(total){
int nAvg = iterations ? (total/iterations) : 0;
cgi_printf("<br /><div>Total events: %d<br />"
"Average per active week: %d</div>",
total, nAvg);
}
output_table_sorting_javascript("statsTable","tnx",-1);
}
/* Report types
|
| ︙ | ︙ |
Changes to src/style.c.
| ︙ | ︙ | |||
199 200 201 202 203 204 205 |
@ gebi("a%d(i+1)").href="%s(aHref[i])";
}
}
for(i=0; i<nFormAction; i++){
@ gebi("form%d(i+1)").action="%s(aFormAction[i])";
}
@ }
| | | 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
@ gebi("a%d(i+1)").href="%s(aHref[i])";
}
}
for(i=0; i<nFormAction; i++){
@ gebi("form%d(i+1)").action="%s(aFormAction[i])";
}
@ }
if( sqlite3_strglob("*Opera Mini/[1-9]*", PD("HTTP_USER_AGENT",""))==0 ){
/* Special case for Opera Mini, which executes JS server-side */
@ var isOperaMini = Object.prototype.toString.call(window.operamini)
@ === "[object OperaMini]";
@ if( isOperaMini ){
@ setTimeout("setAllHrefs();",%d(nDelay));
@ }
}else if( db_get_boolean("auto-hyperlink-ishuman",0) && g.isHuman ){
|
| ︙ | ︙ | |||
1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 |
style_header("Environment Test");
showAll = atoi(PD("showall","0"));
if( !showAll ){
style_submenu_element("Show Cookies", 0, "%R/test_env?showall=1");
}else{
style_submenu_element("Hide Cookies", 0, "%R/test_env");
}
#if !defined(_WIN32)
@ uid=%d(getuid()), gid=%d(getgid())<br />
#endif
@ g.zBaseURL = %h(g.zBaseURL)<br />
@ g.zHttpsURL = %h(g.zHttpsURL)<br />
@ g.zTop = %h(g.zTop)<br />
@ g.zPath = %h(g.zPath)<br />
| > > | 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 |
style_header("Environment Test");
showAll = atoi(PD("showall","0"));
if( !showAll ){
style_submenu_element("Show Cookies", 0, "%R/test_env?showall=1");
}else{
style_submenu_element("Hide Cookies", 0, "%R/test_env");
}
style_submenu_element("Stats", 0, "%R/stat");
#if !defined(_WIN32)
@ uid=%d(getuid()), gid=%d(getgid())<br />
#endif
@ g.zBaseURL = %h(g.zBaseURL)<br />
@ g.zHttpsURL = %h(g.zHttpsURL)<br />
@ g.zTop = %h(g.zTop)<br />
@ g.zPath = %h(g.zPath)<br />
|
| ︙ | ︙ | |||
1600 1601 1602 1603 1604 1605 1606 |
}
zCap[i] = 0;
if( i>0 ){
@ anonymous-adds = %s(zCap)<br />
}
@ g.zRepositoryName = %h(g.zRepositoryName)<br />
@ load_average() = %f(load_average())<br />
| | | | 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 |
}
zCap[i] = 0;
if( i>0 ){
@ anonymous-adds = %s(zCap)<br />
}
@ g.zRepositoryName = %h(g.zRepositoryName)<br />
@ load_average() = %f(load_average())<br />
@ <hr />
P("HTTP_USER_AGENT");
cgi_print_all(showAll);
if( showAll && blob_size(&g.httpHeader)>0 ){
@ <hr />
@ <pre>
@ %h(blob_str(&g.httpHeader))
@ </pre>
}
if( g.perm.Setup ){
const char *zRedir = P("redirect");
if( zRedir ) cgi_redirect(zRedir);
|
| ︙ | ︙ |
Changes to src/sync.c.
| ︙ | ︙ | |||
75 76 77 78 79 80 81 |
url_enable_proxy("via proxy: ");
rc = client_sync(flags, configSync, 0);
return rc;
}
/*
** This routine will try a number of times to perform autosync with a
| | > > > > | > > > > > > > > | 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 |
url_enable_proxy("via proxy: ");
rc = client_sync(flags, configSync, 0);
return rc;
}
/*
** This routine will try a number of times to perform autosync with a
** 0.5 second sleep between attempts.
**
** Return zero on success and non-zero on a failure. If failure occurs
** and doPrompt flag is true, ask the user if they want to continue, and
** if they answer "yes" then return zero in spite of the failure.
*/
int autosync_loop(int flags, int nTries, int doPrompt){
int n = 0;
int rc = 0;
while( (n==0 || n<nTries) && (rc=autosync(flags)) ){
if( rc ){
if( ++n<nTries ){
fossil_warning("Autosync failed, making another attempt.");
sqlite3_sleep(500);
}else{
fossil_warning("Autosync failed.");
}
}
}
if( rc && doPrompt ){
Blob ans;
char cReply;
prompt_user("continue in spite of sync failure (y/N)? ", &ans);
cReply = blob_str(&ans)[0];
if( cReply=='y' || cReply=='Y' ) rc = 0;
blob_reset(&ans);
}
return rc;
}
/*
** This routine processes the command-line argument for push, pull,
** and sync. If a command-line argument is given, that is the URL
|
| ︙ | ︙ | |||
249 250 251 252 253 254 255 | /* ** COMMAND: sync ** ** Usage: %fossil sync ?URL? ?options? ** | | | | | 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 | /* ** COMMAND: sync ** ** Usage: %fossil sync ?URL? ?options? ** ** Synchronize all sharable changes between the local repository and a a ** remote repository. Sharable changes include public check-ins and ** edits to wiki pages, tickets, and technical notes. ** ** If URL is not specified, then the URL from the most recent clone, push, ** pull, remote-url, or sync command is used. See "fossil help clone" for ** details on the URL formats. ** ** Options: ** |
| ︙ | ︙ | |||
314 315 316 317 318 319 320 |
char *zUrl;
db_find_and_open_repository(0, 0);
/* We should be done with options.. */
verify_all_options();
if( g.argc!=2 && g.argc!=3 ){
| | | 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 |
char *zUrl;
db_find_and_open_repository(0, 0);
/* We should be done with options.. */
verify_all_options();
if( g.argc!=2 && g.argc!=3 ){
usage("?URL|off?");
}
if( g.argc==3 ){
db_unset("last-sync-url", 0);
db_unset("last-sync-pw", 0);
db_unset("http-auth", 0);
if( is_false(g.argv[2]) ) return;
url_parse(g.argv[2], URL_REMEMBER|URL_PROMPT_PW|URL_ASK_REMEMBER_PW);
|
| ︙ | ︙ |
Changes to src/tag.c.
| ︙ | ︙ | |||
146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
id = db_last_insert_rowid();
}
return id;
}
/*
** Insert a tag into the database.
*/
int tag_insert(
const char *zTag, /* Name of the tag (w/o the "+" or "-" prefix */
int tagtype, /* 0:cancel 1:singleton 2:propagated */
const char *zValue, /* Value if the tag is really a property */
int srcId, /* Artifact that contains this tag */
double mtime, /* Timestamp. Use default if <=0.0 */
| > > > | 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
id = db_last_insert_rowid();
}
return id;
}
/*
** Insert a tag into the database.
**
** Also translate zTag into a tagid and return the tagid. (In other words
** if zTag is "bgcolor" then return TAG_BGCOLOR.)
*/
int tag_insert(
const char *zTag, /* Name of the tag (w/o the "+" or "-" prefix */
int tagtype, /* 0:cancel 1:singleton 2:propagated */
const char *zValue, /* Value if the tag is really a property */
int srcId, /* Artifact that contains this tag */
double mtime, /* Timestamp. Use default if <=0.0 */
|
| ︙ | ︙ | |||
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
if( tagid==TAG_DATE ){
db_multi_exec("UPDATE event "
" SET mtime=julianday(%Q),"
" omtime=coalesce(omtime,mtime)"
" WHERE objid=%d",
zValue, rid);
}
if( tagtype==1 ) tagtype = 0;
tag_propagate(rid, tagid, tagtype, rid, zValue, mtime);
return tagid;
}
/*
** COMMAND: test-tag
| > > > > | | 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 |
if( tagid==TAG_DATE ){
db_multi_exec("UPDATE event "
" SET mtime=julianday(%Q),"
" omtime=coalesce(omtime,mtime)"
" WHERE objid=%d",
zValue, rid);
}
if( tagid==TAG_PARENT && tagtype==1 ){
manifest_reparent_checkin(rid, zValue);
}
if( tagtype==1 ) tagtype = 0;
tag_propagate(rid, tagid, tagtype, rid, zValue, mtime);
return tagid;
}
/*
** COMMAND: test-tag
**
** Usage: %fossil test-tag (+|*|-)TAGNAME ARTIFACT-ID ?VALUE?
**
** Add a tag or anti-tag to the rebuildable tables of the local repository.
** No tag artifact is created so the new tag is erased the next
** time the repository is rebuilt. This routine is for testing
** use only.
*/
void testtag_cmd(void){
|
| ︙ | ︙ | |||
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 |
g.markPrivate = content_is_private(rid);
zValue = g.argc==5 ? g.argv[4] : 0;
db_begin_transaction();
tag_insert(zTag, tagtype, zValue, -1, 0.0, rid);
db_end_transaction(0);
}
/*
** Add a control record to the repository that either creates
** or cancels a tag.
*/
void tag_add_artifact(
const char *zPrefix, /* Prefix to prepend to tag name */
const char *zTagname, /* The tag to add or cancel */
const char *zObjName, /* Name of object attached to */
const char *zValue, /* Value for the tag. Might be NULL */
int tagtype, /* 0:cancel 1:singleton 2:propagated */
const char *zDateOvrd, /* Override date string */
const char *zUserOvrd /* Override user name */
){
int rid;
int nrid;
char *zDate;
Blob uuid;
Blob ctrl;
Blob cksum;
static const char zTagtype[] = { '-', '+', '*' };
assert( tagtype>=0 && tagtype<=2 );
user_select();
blob_zero(&uuid);
blob_append(&uuid, zObjName, -1);
if( name_to_uuid(&uuid, 9, "*") ){
fossil_fatal("%s", g.zErrMsg);
return;
| > > > > > > > > > > > > > > > > > > | 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 |
g.markPrivate = content_is_private(rid);
zValue = g.argc==5 ? g.argv[4] : 0;
db_begin_transaction();
tag_insert(zTag, tagtype, zValue, -1, 0.0, rid);
db_end_transaction(0);
}
/*
** OR this value into the tagtype argument to tag_add_artifact to
** cause the tag to be displayed on standard output rather than be
** inserted. Used for --dryrun options and debugging.
*/
#if INTERFACE
#define TAG_ADD_DRYRUN 0x04
#endif
/*
** Add a control record to the repository that either creates
** or cancels a tag.
**
** tagtype should normally be 0, 1, or 2. But if the TAG_ADD_DRYRUN bit
** is also set, then simply print the text of the tag on standard output
** (for testing purposes) rather than create the tag.
*/
void tag_add_artifact(
const char *zPrefix, /* Prefix to prepend to tag name */
const char *zTagname, /* The tag to add or cancel */
const char *zObjName, /* Name of object attached to */
const char *zValue, /* Value for the tag. Might be NULL */
int tagtype, /* 0:cancel 1:singleton 2:propagated */
const char *zDateOvrd, /* Override date string */
const char *zUserOvrd /* Override user name */
){
int rid;
int nrid;
char *zDate;
Blob uuid;
Blob ctrl;
Blob cksum;
static const char zTagtype[] = { '-', '+', '*' };
int dryRun = 0;
if( tagtype & TAG_ADD_DRYRUN ){
tagtype &= ~TAG_ADD_DRYRUN;
dryRun = 1;
}
assert( tagtype>=0 && tagtype<=2 );
user_select();
blob_zero(&uuid);
blob_append(&uuid, zObjName, -1);
if( name_to_uuid(&uuid, 9, "*") ){
fossil_fatal("%s", g.zErrMsg);
return;
|
| ︙ | ︙ | |||
324 325 326 327 328 329 330 |
blob_appendf(&ctrl, " %F\n", zValue);
}else{
blob_appendf(&ctrl, "\n");
}
blob_appendf(&ctrl, "U %F\n", zUserOvrd ? zUserOvrd : login_name());
md5sum_blob(&ctrl, &cksum);
blob_appendf(&ctrl, "Z %b\n", &cksum);
| > > > > | | > > | | > > > > > > > > > > > > | > | > > > > > | 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 |
blob_appendf(&ctrl, " %F\n", zValue);
}else{
blob_appendf(&ctrl, "\n");
}
blob_appendf(&ctrl, "U %F\n", zUserOvrd ? zUserOvrd : login_name());
md5sum_blob(&ctrl, &cksum);
blob_appendf(&ctrl, "Z %b\n", &cksum);
if( dryRun ){
fossil_print("%s", blob_str(&ctrl));
blob_reset(&ctrl);
}else{
nrid = content_put(&ctrl);
manifest_crosslink(nrid, &ctrl, MC_PERMIT_HOOKS);
}
assert( blob_is_reset(&ctrl) );
manifest_to_disk(rid);
}
/*
** COMMAND: tag
**
** Usage: %fossil tag SUBCOMMAND ...
**
** Run various subcommands to control tags and properties.
**
** %fossil tag add ?OPTIONS? TAGNAME CHECK-IN ?VALUE?
**
** Add a new tag or property to CHECK-IN. The tag will
** be usable instead of a CHECK-IN in commands such as
** update and merge. If the --propagate flag is present,
** the tag value propagates to all descendants of CHECK-IN
**
** Options:
** --raw Raw tag name.
** --propagate Propagating tag.
** --date-override DATETIME Set date and time added.
** --user-override USER Name USER when adding the tag.
** --dryrun|-n Display the tag text, but to not
** actually insert it into the database.
**
** The --date-override and --user-override options support
** importing history from other SCM systems. DATETIME has
** the form 'YYYY-MMM-DD HH:MM:SS'.
**
** %fossil tag cancel ?--raw? TAGNAME CHECK-IN
**
** Remove the tag TAGNAME from CHECK-IN, and also remove
** the propagation of the tag to any descendants. Use the
** the --dryrun or -n options to see what would have happened.
**
** %fossil tag find ?OPTIONS? TAGNAME
**
** List all objects that use TAGNAME. TYPE can be "ci" for
** check-ins or "e" for events. The limit option limits the number
** of results to the given value.
**
** Options:
** --raw Raw tag name.
** -t|--type TYPE One of "ci", or "e".
** -n|--limit N Limit to N results.
**
** %fossil tag list|ls ?--raw? ?CHECK-IN?
**
** List all tags, or if CHECK-IN is supplied, list
** all tags and their values for CHECK-IN.
**
** The option --raw allows the manipulation of all types of tags
|
| ︙ | ︙ | |||
378 379 380 381 382 383 384 | ** will be taken as an artifact or baseline ID and fossil will ** probably complain that no such revision was found. However ** ** fossil update tag:decaf ** ** will assume that "decaf" is a tag/branch name. ** | < < < < > > | | > > | | | 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 |
** will be taken as an artifact or baseline ID and fossil will
** probably complain that no such revision was found. However
**
** fossil update tag:decaf
**
** will assume that "decaf" is a tag/branch name.
**
*/
void tag_cmd(void){
int n;
int fRaw = find_option("raw","",0)!=0;
int fPropagate = find_option("propagate","",0)!=0;
const char *zPrefix = fRaw ? "" : "sym-";
const char *zFindLimit = find_option("limit","n",1);
const int nFindLimit = zFindLimit ? atoi(zFindLimit) : -2000;
db_find_and_open_repository(0, 0);
if( g.argc<3 ){
goto tag_cmd_usage;
}
n = strlen(g.argv[2]);
if( n==0 ){
goto tag_cmd_usage;
}
if( strncmp(g.argv[2],"add",n)==0 ){
char *zValue;
int dryRun = 0;
const char *zDateOvrd = find_option("date-override",0,1);
const char *zUserOvrd = find_option("user-override",0,1);
if( find_option("dryrun","n",0)!=0 ) dryRun = TAG_ADD_DRYRUN;
if( g.argc!=5 && g.argc!=6 ){
usage("add ?options? TAGNAME CHECK-IN ?VALUE?");
}
zValue = g.argc==6 ? g.argv[5] : 0;
db_begin_transaction();
tag_add_artifact(zPrefix, g.argv[3], g.argv[4], zValue,
1+fPropagate+dryRun,zDateOvrd,zUserOvrd);
db_end_transaction(0);
}else
if( strncmp(g.argv[2],"branch",n)==0 ){
fossil_fatal("the \"fossil tag branch\" command is discontinued\n"
"Use the \"fossil branch new\" command instead.");
}else
if( strncmp(g.argv[2],"cancel",n)==0 ){
int dryRun = 0;
if( find_option("dryrun","n",0)!=0 ) dryRun = TAG_ADD_DRYRUN;
if( g.argc!=5 ){
usage("cancel ?options? TAGNAME CHECK-IN");
}
db_begin_transaction();
tag_add_artifact(zPrefix, g.argv[3], g.argv[4], 0, dryRun, 0, 0);
db_end_transaction(0);
}else
if( strncmp(g.argv[2],"find",n)==0 ){
Stmt q;
const char *zType = find_option("type","t",1);
Blob sql = empty_blob;
|
| ︙ | ︙ | |||
519 520 521 522 523 524 525 |
fossil_print("%s=%s\n", zName, zValue);
}else{
fossil_print("%s\n", zName);
}
}
db_finalize(&q);
}else{
| | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
fossil_print("%s=%s\n", zName, zValue);
}else{
fossil_print("%s\n", zName);
}
}
db_finalize(&q);
}else{
usage("list ?CHECK-IN?");
}
}else
{
goto tag_cmd_usage;
}
/* Cleanup */
return;
tag_cmd_usage:
usage("add|cancel|find|list ...");
}
/*
** COMMAND: reparent*
**
** Usage: %fossil reparent [OPTIONS] CHECK-IN PARENT ....
**
** Create a "parent" tag that causes CHECK-IN to be interpreted as a
** child of PARENT. If multiple PARENTs are listed, then the first is
** the primary parent and others are merge ancestors.
**
** This is an experts-only command. It is used to patch up a repository
** that has been damaged by a shun or that has been pieced together from
** two or more separate repositories. You should never need to reparent
** during normal operations.
**
** Reparenting is accomplished by adding a parent tag. So to undo the
** reparenting operation, simply delete the tag.
**
** --test Make database entries but do not add the tag artifact.
** So the reparent operation will be undone by the next
** "fossil rebuild" command.
** --dryrun | -n Print the tag that would have been created but do not
** actually change the database in any way.
*/
void reparent_cmd(void){
int bTest = find_option("test","",0)!=0;
int rid;
int i;
Blob value;
char *zUuid;
int dryRun = 0;
if( find_option("dryrun","n",0)!=0 ) dryRun = TAG_ADD_DRYRUN;
db_find_and_open_repository(0, 0);
verify_all_options();
if( g.argc<4 ){
usage("reparent [OPTIONS] PARENT ...");
}
rid = name_to_typed_rid(g.argv[2], "ci");
blob_init(&value, 0, 0);
for(i=3; i<g.argc; i++){
int pid = name_to_typed_rid(g.argv[i], "ci");
if( i>3 ) blob_append(&value, " ", 1);
zUuid = rid_to_uuid(pid);
blob_append(&value, zUuid, UUID_SIZE);
fossil_free(zUuid);
}
if( bTest && !dryRun ){
tag_insert("parent", 1, blob_str(&value), -1, 0.0, rid);
}else{
zUuid = rid_to_uuid(rid);
tag_add_artifact("","parent",zUuid,blob_str(&value),1|dryRun,0,0);
}
}
/*
** WEBPAGE: taglist
**
** List all non-propagating symbolic tags.
*/
void taglist_page(void){
|
| ︙ | ︙ |
Changes to src/tar.c.
| ︙ | ︙ | |||
71 72 73 74 75 76 77 |
db_multi_exec(
"CREATE TEMP TABLE dir(name UNIQUE);"
);
}
/*
| | | | 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 |
db_multi_exec(
"CREATE TEMP TABLE dir(name UNIQUE);"
);
}
/*
** Verify that all characters in 'zName' are in the
** ISO646 (=ASCII) character set.
*/
static int is_iso646_name(
const char *zName, /* file path */
int nName /* path length */
){
int i;
for(i = 0; i < nName; i++){
unsigned char c = (unsigned char)zName[i];
if( c>0x7e ) return 0;
}
return 1;
}
/*
** copy string pSrc into pDst, truncating or padding with 0 if necessary
*/
static void padded_copy(
char *pDest,
int nDest,
const char *pSrc,
int nSrc
){
|
| ︙ | ︙ | |||
444 445 446 447 448 449 450 | } tar_finish(&zip); blob_write_to_file(&zip, g.argv[2]); } /* ** Given the RID for a check-in, construct a tarball containing | | > | | > > > > > > | 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 |
}
tar_finish(&zip);
blob_write_to_file(&zip, g.argv[2]);
}
/*
** Given the RID for a check-in, construct a tarball containing
** all files in that check-in that match pGlob (or all files if
** pGlob is NULL).
**
** If RID is for an object that is not a real manifest, then the
** resulting tarball contains a single file which is the RID
** object. pInclude and pExclude are ignored in this case.
**
** If the RID object does not exist in the repository, then
** pTar is zeroed.
**
** zDir is a "synthetic" subdirectory which all files get
** added to as part of the tarball. It may be 0 or an empty string, in
** which case it is ignored. The intention is to create a tarball which
** politely expands into a subdir instead of filling your current dir
** with source files. For example, pass a UUID or "ProjectName".
**
*/
void tarball_of_checkin(
int rid, /* The RID of the checkin from which to form a tarball */
Blob *pTar, /* Write the tarball into this blob */
const char *zDir, /* Directory prefix for all file added to tarball */
Glob *pInclude, /* Only add files matching this pattern */
Glob *pExclude /* Exclude files matching this pattern */
){
Blob mfile, hash, file;
Manifest *pManifest;
ManifestFile *pFile;
Blob filename;
int nPrefix;
char *zName;
unsigned int mTime;
|
| ︙ | ︙ | |||
484 485 486 487 488 489 490 |
if( zDir && zDir[0] ){
blob_appendf(&filename, "%s/", zDir);
}
nPrefix = blob_size(&filename);
pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0);
if( pManifest ){
| | > > > > > > > > > > > > > > > > > | | | | | | > > > | | 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 |
if( zDir && zDir[0] ){
blob_appendf(&filename, "%s/", zDir);
}
nPrefix = blob_size(&filename);
pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0);
if( pManifest ){
int flg, eflg = 0;
mTime = (pManifest->rDate - 2440587.5)*86400.0;
tar_begin(mTime);
flg = db_get_manifest_setting();
if( flg ){
/* eflg is the effective flags, taking include/exclude into account */
if( (pInclude==0 || glob_match(pInclude, "manifest"))
&& !glob_match(pExclude, "manifest")
&& (flg & MFESTFLG_RAW) ){
eflg |= MFESTFLG_RAW;
}
if( (pInclude==0 || glob_match(pInclude, "manifest.uuid"))
&& !glob_match(pExclude, "manifest.uuid")
&& (flg & MFESTFLG_UUID) ){
eflg |= MFESTFLG_UUID;
}
if( (pInclude==0 || glob_match(pInclude, "manifest.tags"))
&& !glob_match(pExclude, "manifest.tags")
&& (flg & MFESTFLG_TAGS) ){
eflg |= MFESTFLG_TAGS;
}
if( eflg & (MFESTFLG_RAW|MFESTFLG_UUID) ){
if( eflg & MFESTFLG_RAW ){
blob_append(&filename, "manifest", -1);
zName = blob_str(&filename);
}
if( eflg & MFESTFLG_UUID ){
sha1sum_blob(&mfile, &hash);
}
if( eflg & MFESTFLG_RAW ) {
sterilize_manifest(&mfile);
tar_add_file(zName, &mfile, 0, mTime);
}
}
blob_reset(&mfile);
if( eflg & MFESTFLG_UUID ){
blob_append(&hash, "\n", 1);
blob_resize(&filename, nPrefix);
blob_append(&filename, "manifest.uuid", -1);
zName = blob_str(&filename);
tar_add_file(zName, &hash, 0, mTime);
blob_reset(&hash);
}
if( eflg & MFESTFLG_TAGS ){
Blob tagslist;
blob_zero(&tagslist);
get_checkin_taglist(rid, &tagslist);
blob_resize(&filename, nPrefix);
blob_append(&filename, "manifest.tags", -1);
zName = blob_str(&filename);
tar_add_file(zName, &tagslist, 0, mTime);
blob_reset(&tagslist);
}
}
manifest_file_rewind(pManifest);
while( (pFile = manifest_file_next(pManifest,0))!=0 ){
int fid;
if( pInclude!=0 && !glob_match(pInclude, pFile->zName) ) continue;
if( glob_match(pExclude, pFile->zName) ) continue;
fid = uuid_to_rid(pFile->zUuid, 0);
if( fid ){
content_get(fid, &file);
blob_resize(&filename, nPrefix);
blob_append(&filename, pFile->zName, -1);
zName = blob_str(&filename);
tar_add_file(zName, &file, manifest_file_mperm(pFile), mTime);
blob_reset(&file);
|
| ︙ | ︙ | |||
556 557 558 559 560 561 562 | ** COMMAND: tarball* ** ** Usage: %fossil tarball VERSION OUTPUTFILE ** ** Generate a compressed tarball for a specified version. If the --name ** option is used, its argument becomes the name of the top-level directory ** in the resulting tarball. If --name is omitted, the top-level directory | | > > > > > > > | | > > > > > > > > | 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 |
** COMMAND: tarball*
**
** Usage: %fossil tarball VERSION OUTPUTFILE
**
** Generate a compressed tarball for a specified version. If the --name
** option is used, its argument becomes the name of the top-level directory
** in the resulting tarball. If --name is omitted, the top-level directory
** name is derived from the project name, the check-in date and time, and
** the artifact ID of the check-in.
**
** The GLOBLIST argument to --exclude and --include can be a comma-separated
** list of glob patterns, where each glob pattern may optionally be enclosed
** in "..." or '...' so that it may contain commas. If a file matches both
** --include and --exclude then it is excluded.
**
** Options:
** -X|--exclude GLOBLIST Comma-separated list of GLOBs of files to exclude
** --include GLOBLIST Comma-separated list of GLOBs of files to include
** --name DIRECTORYNAME The name of the top-level directory in the archive
** -R REPOSITORY Specify a Fossil repository
*/
void tarball_cmd(void){
int rid;
Blob tarball;
const char *zName;
Glob *pInclude = 0;
Glob *pExclude = 0;
const char *zInclude;
const char *zExclude;
zName = find_option("name", 0, 1);
zExclude = find_option("exclude", "X", 1);
if( zExclude ) pExclude = glob_create(zExclude);
zInclude = find_option("include", 0, 1);
if( zInclude ) pInclude = glob_create(zInclude);
db_find_and_open_repository(0, 0);
/* We should be done with options.. */
verify_all_options();
if( g.argc!=4 ){
usage("VERSION OUTPUTFILE");
|
| ︙ | ︙ | |||
593 594 595 596 597 598 599 |
" || substr(blob.uuid, 1, 10)"
" FROM event, blob"
" WHERE event.objid=%d"
" AND blob.rid=%d",
db_get("project-name", "unnamed"), rid, rid
);
}
| | > > | | | | | > | | < | | > > > > > > > > > > > > | > > > > > | > > > > > > > | | | > > > > > > | | | > | > | 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 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 |
" || substr(blob.uuid, 1, 10)"
" FROM event, blob"
" WHERE event.objid=%d"
" AND blob.rid=%d",
db_get("project-name", "unnamed"), rid, rid
);
}
tarball_of_checkin(rid, &tarball, zName, pInclude, pExclude);
glob_free(pInclude);
glob_free(pExclude);
blob_write_to_file(&tarball, g.argv[3]);
blob_reset(&tarball);
}
/*
** WEBPAGE: tarball
** URL: /tarball
**
** Generate a compressed tarball for a check-in and return that
** tarball as the HTTP reply content.
**
** Query parameters:
**
** name=NAME[.tar.gz] The base name of the output file. The default
** value is a configuration parameter in the project
** settings. A prefix of the name, omitting the extension,
** is used as the top-most directory name.
**
** uuid=TAG The check-in that is turned into a tarball.
** Defaults to "trunk".
**
** in=PATTERN Only include files that match the comma-separate
** list of GLOB patterns in PATTERN, as with ex=
**
** ex=PATTERN Omit any file that match PATTERN. PATTERN is a
** comma-separated list of GLOB patterns, where each
** pattern can optionally be quoted using ".." or '..'.
** Any file matching both ex= and in= is excluded.
*/
void tarball_page(void){
int rid;
char *zName, *zRid, *zKey;
int nName, nRid;
const char *zInclude; /* The in= query parameter */
const char *zExclude; /* The ex= query parameter */
Blob cacheKey; /* The key to cache */
Glob *pInclude = 0; /* The compiled in= glob pattern */
Glob *pExclude = 0; /* The compiled ex= glob pattern */
Blob tarball; /* Tarball accumulated here */
login_check_credentials();
if( !g.perm.Zip ){ login_needed(g.anon.Zip); return; }
load_control();
zName = mprintf("%s", PD("name",""));
nName = strlen(zName);
zRid = mprintf("%s", PD("uuid","trunk"));
nRid = strlen(zRid);
zInclude = P("in");
if( zInclude ) pInclude = glob_create(zInclude);
zExclude = P("ex");
if( zExclude ) pExclude = glob_create(zExclude);
if( nName>7 && fossil_strcmp(&zName[nName-7], ".tar.gz")==0 ){
/* Special case: Remove the ".tar.gz" suffix. */
nName -= 7;
zName[nName] = 0;
}else{
/* If the file suffix is not ".tar.gz" then just remove the
** suffix up to and including the last "." */
for(nName=strlen(zName)-1; nName>5; nName--){
if( zName[nName]=='.' ){
zName[nName] = 0;
break;
}
}
}
rid = name_to_typed_rid(nRid?zRid:zName, "ci");
if( rid==0 ){
@ Not found
return;
}
if( nRid==0 && nName>10 ) zName[10] = 0;
/* Compute a unique key for the cache entry based on query parameters */
blob_init(&cacheKey, 0, 0);
blob_appendf(&cacheKey, "/tarball/%z", rid_to_uuid(rid));
if( zInclude ) blob_appendf(&cacheKey, ",in=%Q", zInclude);
if( zExclude ) blob_appendf(&cacheKey, ",ex=%Q", zExclude);
blob_appendf(&cacheKey, "/%q", zName);
zKey = blob_str(&cacheKey);
if( P("debug")!=0 ){
style_header("Tarball Generator Debug Screen");
@ zName = "%h(zName)"<br />
@ rid = %d(rid)<br />
if( zInclude ){
@ zInclude = "%h(zInclude)"<br />
}
if( zExclude ){
@ zExclude = "%h(zExclude)"<br />
}
@ zKey = "%h(zKey)"
style_footer();
return;
}
if( referred_from_login() ){
style_header("Tarball Download");
@ <form action='%R/tarball'>
cgi_query_parameters_to_hidden();
@ <p>Tarball named <b>%h(zName).tar.gz</b> holding the content
@ of check-in <b>%h(zRid)</b>:
@ <input type="submit" value="Download" />
@ </form>
style_footer();
return;
}
blob_zero(&tarball);
if( cache_read(&tarball, zKey)==0 ){
tarball_of_checkin(rid, &tarball, zName, pInclude, pExclude);
cache_write(&tarball, zKey);
}
glob_free(pInclude);
glob_free(pExclude);
fossil_free(zName);
fossil_free(zRid);
blob_reset(&cacheKey);
cgi_set_content(&tarball);
cgi_set_content_type("application/x-compressed");
}
|
Changes to src/th_main.c.
| ︙ | ︙ | |||
280 281 282 283 284 285 286 |
){
int rc;
if( argc<2 || argc>3 ){
return Th_WrongNumArgs(interp, "enable_output [LABEL] BOOLEAN");
}
rc = Th_ToInt(interp, argv[argc-1], argl[argc-1], &enableOutput);
if( g.thTrace ){
| | | 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
){
int rc;
if( argc<2 || argc>3 ){
return Th_WrongNumArgs(interp, "enable_output [LABEL] BOOLEAN");
}
rc = Th_ToInt(interp, argv[argc-1], argl[argc-1], &enableOutput);
if( g.thTrace ){
Th_Trace("enable_output {%.*s} -> %d<br />\n", argl[1],argv[1],enableOutput);
}
return rc;
}
/*
** Returns a name for a TH1 return code.
*/
|
| ︙ | ︙ | |||
330 331 332 333 334 335 336 |
}
}
static void sendError(const char *z, int n, int forceCgi){
int savedEnable = enableOutput;
enableOutput = 1;
if( forceCgi || g.cgiOutput ){
| | | 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 |
}
}
static void sendError(const char *z, int n, int forceCgi){
int savedEnable = enableOutput;
enableOutput = 1;
if( forceCgi || g.cgiOutput ){
sendText("<hr /><p class=\"thmainError\">", -1, 0);
}
sendText("ERROR: ", -1, 0);
sendText((char*)z, n, 1);
sendText(forceCgi || g.cgiOutput ? "</p>" : "\n", -1, 0);
enableOutput = savedEnable;
}
|
| ︙ | ︙ | |||
726 727 728 729 730 731 732 733 734 735 736 737 738 739 | ** "useTclStubs" = USE_TCL_STUBS ** "tclStubs" = FOSSIL_ENABLE_TCL_STUBS ** "tclPrivateStubs" = FOSSIL_ENABLE_TCL_PRIVATE_STUBS ** "json" = FOSSIL_ENABLE_JSON ** "markdown" = FOSSIL_ENABLE_MARKDOWN ** "unicodeCmdLine" = !BROKEN_MINGW_CMDLINE ** "dynamicBuild" = FOSSIL_DYNAMIC_BUILD ** ** Specifying an unknown feature will return a value of false, it will not ** raise a script error. */ static int hasfeatureCmd( Th_Interp *interp, void *p, | > | 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 | ** "useTclStubs" = USE_TCL_STUBS ** "tclStubs" = FOSSIL_ENABLE_TCL_STUBS ** "tclPrivateStubs" = FOSSIL_ENABLE_TCL_PRIVATE_STUBS ** "json" = FOSSIL_ENABLE_JSON ** "markdown" = FOSSIL_ENABLE_MARKDOWN ** "unicodeCmdLine" = !BROKEN_MINGW_CMDLINE ** "dynamicBuild" = FOSSIL_DYNAMIC_BUILD ** "see" = USE_SEE ** ** Specifying an unknown feature will return a value of false, it will not ** raise a script error. */ static int hasfeatureCmd( Th_Interp *interp, void *p, |
| ︙ | ︙ | |||
805 806 807 808 809 810 811 812 813 814 815 816 817 818 |
rc = 1;
}
#endif
#if defined(FOSSIL_DYNAMIC_BUILD)
else if( 0 == fossil_strnicmp( zArg, "dynamicBuild\0", 13 ) ){
rc = 1;
}
#endif
else if( 0 == fossil_strnicmp( zArg, "markdown\0", 9 ) ){
rc = 1;
}
if( g.thTrace ){
Th_Trace("[hasfeature %#h] => %d<br />\n", argl[1], zArg, rc);
}
| > > > > > | 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 |
rc = 1;
}
#endif
#if defined(FOSSIL_DYNAMIC_BUILD)
else if( 0 == fossil_strnicmp( zArg, "dynamicBuild\0", 13 ) ){
rc = 1;
}
#endif
#if defined(USE_SEE)
else if( 0 == fossil_strnicmp( zArg, "see\0", 4 ) ){
rc = 1;
}
#endif
else if( 0 == fossil_strnicmp( zArg, "markdown\0", 9 ) ){
rc = 1;
}
if( g.thTrace ){
Th_Trace("[hasfeature %#h] => %d<br />\n", argl[1], zArg, rc);
}
|
| ︙ | ︙ | |||
2319 2320 2321 2322 2323 2324 2325 |
zResult = (char*)Th_GetResult(g.interp, &n);
sendText((char*)zResult, n, encode);
}else if( z[i]=='<' && isBeginScriptTag(&z[i]) ){
sendText(z, i, 0);
z += i+5;
for(i=0; z[i] && (z[i]!='<' || !isEndScriptTag(&z[i])); i++){}
if( g.thTrace ){
| | | 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 |
zResult = (char*)Th_GetResult(g.interp, &n);
sendText((char*)zResult, n, encode);
}else if( z[i]=='<' && isBeginScriptTag(&z[i]) ){
sendText(z, i, 0);
z += i+5;
for(i=0; z[i] && (z[i]!='<' || !isEndScriptTag(&z[i])); i++){}
if( g.thTrace ){
Th_Trace("eval {<pre>%#h</pre>}<br />", i, z);
}
rc = Th_Eval(g.interp, 0, (const char*)z, i);
if( rc!=TH_OK ) break;
z += i;
if( z[0] ){ z += 6; }
i = 0;
}else{
|
| ︙ | ︙ |
Changes to src/timeline.c.
| ︙ | ︙ | |||
137 138 139 140 141 142 143 |
default: r = mx; g = mn, b = h2; break;
}
sqlite3_snprintf(8, zColor, "#%02x%02x%02x", r,g,b);
return zColor;
}
/*
| | | | 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 |
default: r = mx; g = mn, b = h2; break;
}
sqlite3_snprintf(8, zColor, "#%02x%02x%02x", r,g,b);
return zColor;
}
/*
** COMMAND: test-hash-color
**
** Usage: %fossil test-hash-color TAG ...
**
** Print out the color names associated with each tag. Used for
** testing the hash_color() function.
*/
void test_hash_color(void){
int i;
for(i=2; i<g.argc; i++){
fossil_print("%20s: %s\n", g.argv[i], hash_color(g.argv[i]));
}
}
/*
** WEBPAGE: hash-color-test
**
** Print out the color names associated with each tag. Used for
** testing the hash_color() function.
*/
void test_hash_color_page(void){
const char *zBr;
char zNm[10];
|
| ︙ | ︙ | |||
176 177 178 179 180 181 182 |
@ %h(zBr) - %s(hash_color(zBr)) -
@ Omnes nos quasi oves erravimus unusquisque in viam
@ suam declinavit.</p>
cnt++;
}
}
if( cnt ){
| | | 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
@ %h(zBr) - %s(hash_color(zBr)) -
@ Omnes nos quasi oves erravimus unusquisque in viam
@ suam declinavit.</p>
cnt++;
}
}
if( cnt ){
@ <hr />
}
@ <form method="post" action="%s(g.zTop)/hash-color-test">
@ <p>Enter candidate branch names below and see them displayed in their
@ default background colors above.</p>
for(i=0; i<10; i++){
sqlite3_snprintf(sizeof(zNm),zNm,"b%d",i);
zBr = P(zNm);
|
| ︙ | ︙ | |||
297 298 299 300 301 302 303 |
if( pendingEndTr>1 ){
@ <tr class="timelineSpacer"></tr>
}
pendingEndTr = 0;
}
if( fossil_strcmp(zType,"div")==0 ){
if( !prevWasDivider ){
| | | 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 |
if( pendingEndTr>1 ){
@ <tr class="timelineSpacer"></tr>
}
pendingEndTr = 0;
}
if( fossil_strcmp(zType,"div")==0 ){
if( !prevWasDivider ){
@ <tr><td colspan="3"><hr class="timelineMarker" /></td></tr>
}
prevWasDivider = 1;
continue;
}
prevWasDivider = 0;
/* Date format codes:
** (0) HH:MM
|
| ︙ | ︙ | |||
1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 |
}
assert( i<=ArraySize(az) );
}
if( i>2 ){
style_submenu_multichoice("y", i/2, az, isDisabled);
}
}
/*
** WEBPAGE: timeline
**
** Query parameters:
**
** a=TIMEORTAG after this event
** b=TIMEORTAG before this event
** c=TIMEORTAG "circa" this event
** m=TIMEORTAG mark this event
| > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | | | < | | | | | | > > | > | < < < | 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 |
}
assert( i<=ArraySize(az) );
}
if( i>2 ){
style_submenu_multichoice("y", i/2, az, isDisabled);
}
}
/*
** If the zChng string is not NULL, then it should be a comma-separated
** list of glob patterns for filenames. Add an term to the WHERE clause
** for the SQL statement under construction that excludes any check-in that
** does not modify one or more files matching the globs.
*/
static void addFileGlobExclusion(
const char *zChng, /* The filename GLOB list */
Blob *pSql /* The SELECT statement under construction */
){
if( zChng==0 || zChng[0]==0 ) return;
blob_append_sql(pSql," AND event.objid IN ("
"SELECT mlink.mid FROM mlink, filename"
" WHERE mlink.fnid=filename.fnid AND %s)",
glob_expr("filename.name", zChng));
}
static void addFileGlobDescription(
const char *zChng, /* The filename GLOB list */
Blob *pDescription /* Result description */
){
if( zChng==0 || zChng[0]==0 ) return;
blob_appendf(pDescription, " that include changes to files matching %Q",
zChng);
}
/*
** WEBPAGE: timeline
**
** Query parameters:
**
** a=TIMEORTAG after this event
** b=TIMEORTAG before this event
** c=TIMEORTAG "circa" this event
** m=TIMEORTAG mark this event
** n=COUNT suggested number of events in output
** p=CHECKIN parents and ancestors of CHECKIN
** d=CHECKIN descendants of CHECIN
** dp=CHECKIN The same as d=CHECKIN&p=CHECKIN
** t=TAG show only check-ins with the given TAG
** r=TAG show check-ins related to TAG
** u=USER only show items associated with USER
** y=TYPE 'ci', 'w', 't', 'e', or (default) 'all'
** ng No Graph.
** nd Do not highlight the focus check-in
** v Show details of files changed
** f=CHECKIN Show family (immediate parents and children) of CHECKIN
** from=CHECKIN Path from...
** to=CHECKIN ... to this
** shortest ... show only the shortest path
** uf=FILE_SHA1 Show only check-ins that contain the given file version
** chng=GLOBLIST Show only check-ins that involve changes to a file whose
** name matches one of the comma-separate GLOBLIST.
** brbg Background color from branch name
** ubg Background color from user
** namechng Show only check-ins that have filename changes
** forks Show only forks and their children
** 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
** ymd=YYYY-MM-DD Show only events on the given day
** datefmt=N Override the date format
** bisect Show the check-ins that are in the current bisect
**
** 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.
*/
void page_timeline(void){
Stmt q; /* Query used to generate the timeline */
Blob sql; /* text of SQL used to generate timeline */
Blob desc; /* Description of the timeline */
int nEntry; /* Max number of entries on timeline */
int p_rid = name_to_typed_rid(P("p"),"ci"); /* artifact p and its parents */
|
| ︙ | ︙ | |||
1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 |
const char *zTagName = P("t"); /* Show events with this tag */
const char *zBrName = P("r"); /* Show events related to this tag */
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) */
const char *zDay = P("ymd"); /* Check-ins for the day YYYY-MM-DD */
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 bisectOnly = PB("bisect"); /* Show the check-ins of the bisect */
int tagid; /* Tag ID */
int tmFlags = 0; /* Timeline flags */
const char *zThisTag = 0; /* Suppress links to this tag */
| > | 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 |
const char *zTagName = P("t"); /* Show events with this tag */
const char *zBrName = P("r"); /* Show events related to this tag */
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) */
const char *zDay = P("ymd"); /* Check-ins for the day YYYY-MM-DD */
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 bisectOnly = PB("bisect"); /* Show the check-ins of the bisect */
int tagid; /* Tag ID */
int tmFlags = 0; /* Timeline flags */
const char *zThisTag = 0; /* Suppress links to this tag */
|
| ︙ | ︙ | |||
1438 1439 1440 1441 1442 1443 1444 |
blob_append(&sql, " AND event.objid IN (0", -1);
while( p ){
blob_append_sql(&sql, ",%d", p->rid);
p = p->u.pTo;
}
blob_append(&sql, ")", -1);
path_reset();
| > > > > > | > | < | 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 |
blob_append(&sql, " AND event.objid IN (0", -1);
while( p ){
blob_append_sql(&sql, ",%d", p->rid);
p = p->u.pTo;
}
blob_append(&sql, ")", -1);
path_reset();
addFileGlobExclusion(zChng, &sql);
tmFlags |= TIMELINE_DISJOINT;
db_multi_exec("%s", blob_sql_text(&sql));
style_submenu_binary("v","With Files","Without Files",
zType[0]!='a' && zType[0]!='c');
blob_appendf(&desc, "%d check-ins going from ",
db_int(0, "SELECT count(*) FROM timeline"));
blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h", zFrom), zFrom);
blob_append(&desc, " to ", -1);
blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h",zTo), zTo);
addFileGlobDescription(zChng, &desc);
}else if( (p_rid || d_rid) && g.perm.Read ){
/* If p= or d= is present, ignore all other parameters other than n= */
char *zUuid;
int np, nd;
tmFlags |= TIMELINE_DISJOINT;
if( p_rid && d_rid ){
|
| ︙ | ︙ | |||
1515 1516 1517 1518 1519 1520 1521 |
style_submenu_binary("v","With Files","Without Files",
zType[0]!='a' && zType[0]!='c');
if( (tmFlags & TIMELINE_UNHIDE)==0 ){
timeline_submenu(&url, "Unhide", "unhide", "", 0);
}
}else{
/* Otherwise, a timeline based on a span of time */
| | > > > | | | | | | | | | | | | | | | | | | | | | > | 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 1636 1637 1638 1639 1640 1641 1642 1643 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 |
style_submenu_binary("v","With Files","Without Files",
zType[0]!='a' && zType[0]!='c');
if( (tmFlags & TIMELINE_UNHIDE)==0 ){
timeline_submenu(&url, "Unhide", "unhide", "", 0);
}
}else{
/* Otherwise, a timeline based on a span of time */
int n;
const char *zEType = "timeline item";
char *zDate;
Blob cond;
blob_zero(&cond);
addFileGlobExclusion(zChng, &cond);
if( zUses ){
blob_append_sql(&cond, " AND event.objid IN usesfile ");
}
if( renameOnly ){
blob_append_sql(&cond, " AND event.objid IN rnfile ");
}
if( forkOnly ){
blob_append_sql(&cond, " AND event.objid IN rnfork ");
}
if( bisectOnly ){
blob_append_sql(&cond, " AND event.objid IN (SELECT rid FROM bilog) ");
}
if( zYearMonth ){
blob_append_sql(&cond, " AND %Q=strftime('%%Y-%%m',event.mtime) ",
zYearMonth);
}
else if( zYearWeek ){
blob_append_sql(&cond, " AND %Q=strftime('%%Y-%%W',event.mtime) ",
zYearWeek);
}
else if( zDay ){
blob_append_sql(&cond, " AND %Q=strftime('%%Y-%%m-%%d',event.mtime) ",
zDay);
}
if( tagid ){
blob_append_sql(&cond,
" AND (EXISTS(SELECT 1 FROM tagxref"
" WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)\n", tagid);
if( zBrName ){
/* The next two blob_appendf() calls add SQL that causes check-ins that
** are not part of the branch which are parents or children of the
** branch to be included in the report. This related check-ins are
** useful in helping to visualize what has happened on a quiescent
** branch that is infrequently merged with a much more activate branch.
*/
blob_append_sql(&cond,
" OR EXISTS(SELECT 1 FROM plink CROSS JOIN tagxref ON rid=cid"
" WHERE tagid=%d AND tagtype>0 AND pid=blob.rid)\n",
tagid
);
if( (tmFlags & TIMELINE_UNHIDE)==0 ){
blob_append_sql(&cond,
" AND NOT EXISTS(SELECT 1 FROM plink JOIN tagxref ON rid=cid"
" WHERE tagid=%d AND tagtype>0 AND pid=blob.rid)\n",
TAG_HIDDEN
);
}
if( P("mionly")==0 ){
blob_append_sql(&cond,
" OR EXISTS(SELECT 1 FROM plink CROSS JOIN tagxref ON rid=pid"
" WHERE tagid=%d AND tagtype>0 AND cid=blob.rid)\n",
tagid
);
if( (tmFlags & TIMELINE_UNHIDE)==0 ){
blob_append_sql(&cond,
" AND NOT EXISTS(SELECT 1 FROM plink JOIN tagxref ON rid=pid"
" WHERE tagid=%d AND tagtype>0 AND cid=blob.rid)\n",
TAG_HIDDEN
);
}
}
}
blob_append_sql(&cond, ")");
}
if( (zType[0]=='w' && !g.perm.RdWiki)
|| (zType[0]=='t' && !g.perm.RdTkt)
|| (zType[0]=='e' && !g.perm.RdWiki)
|| (zType[0]=='c' && !g.perm.Read)
|| (zType[0]=='g' && !g.perm.Read)
){
zType = "all";
}
if( zType[0]=='a' ){
if( !g.perm.Read || !g.perm.RdWiki || !g.perm.RdTkt ){
char cSep = '(';
blob_append_sql(&cond, " AND event.type IN ");
if( g.perm.Read ){
blob_append_sql(&cond, "%c'ci','g'", cSep);
cSep = ',';
}
if( g.perm.RdWiki ){
blob_append_sql(&cond, "%c'w','e'", cSep);
cSep = ',';
}
if( g.perm.RdTkt ){
blob_append_sql(&cond, "%c't'", cSep);
cSep = ',';
}
blob_append_sql(&cond, ")");
}
}else{ /* zType!="all" */
blob_append_sql(&cond, " AND event.type=%Q", zType);
if( zType[0]=='c' ){
zEType = "check-in";
}else if( zType[0]=='w' ){
zEType = "wiki edit";
}else if( zType[0]=='t' ){
zEType = "ticket change";
}else if( zType[0]=='e' ){
zEType = "technical note";
}else if( zType[0]=='g' ){
zEType = "tag";
}
}
if( zUser ){
int n = db_int(0,"SELECT count(*) FROM event"
" WHERE user=%Q OR euser=%Q", zUser, zUser);
if( n<=nEntry ){
zCirca = zBefore = zAfter = 0;
nEntry = -1;
}
blob_append_sql(&cond, " AND (event.user=%Q OR event.euser=%Q)",
zUser, zUser);
zThisUser = zUser;
}
if( zSearch ){
blob_append_sql(&cond,
" AND (event.comment LIKE '%%%q%%' OR event.brief LIKE '%%%q%%')",
zSearch, zSearch);
}
rBefore = symbolic_name_to_mtime(zBefore);
rAfter = symbolic_name_to_mtime(zAfter);
rCirca = symbolic_name_to_mtime(zCirca);
blob_append_sql(&sql, "%s", blob_sql_text(&cond));
if( rAfter>0.0 ){
if( rBefore>0.0 ){
blob_append_sql(&sql,
" AND event.mtime>=%.17g AND event.mtime<=%.17g"
" ORDER BY event.mtime ASC", rAfter-ONE_SECOND, rBefore+ONE_SECOND);
nEntry = -1;
}else{
|
| ︙ | ︙ | |||
1727 1728 1729 1730 1731 1732 1733 1734 1735 |
if( zTagName ){
blob_appendf(&desc, " tagged with \"%h\"", zTagName);
tmFlags |= TIMELINE_DISJOINT;
}else if( zBrName ){
blob_appendf(&desc, " related to \"%h\"", zBrName);
tmFlags |= TIMELINE_DISJOINT;
}
if( rAfter>0.0 ){
if( rBefore>0.0 ){
| > | < < < < | < < | | | < | | < < | < | | > > > > | | < | > > > > > > > > > > < > > | 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 |
if( zTagName ){
blob_appendf(&desc, " tagged with \"%h\"", zTagName);
tmFlags |= TIMELINE_DISJOINT;
}else if( zBrName ){
blob_appendf(&desc, " related to \"%h\"", zBrName);
tmFlags |= TIMELINE_DISJOINT;
}
addFileGlobDescription(zChng, &desc);
if( rAfter>0.0 ){
if( rBefore>0.0 ){
blob_appendf(&desc, " occurring between %h and %h.<br />",
zAfter, zBefore);
}else{
blob_appendf(&desc, " occurring on or after %h.<br />", zAfter);
}
}else if( rBefore>0.0 ){
blob_appendf(&desc, " occurring on or before %h.<br />", zBefore);
}else if( rCirca>0.0 ){
blob_appendf(&desc, " occurring around %h.<br />", zCirca);
}
if( zSearch ){
blob_appendf(&desc, " matching \"%h\"", zSearch);
}
if( g.perm.Hyperlink ){
double rDate;
zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/");
if( (!zDate || !zDate[0]) && ( zAfter || zBefore ) ){
zDate = mprintf("%s", (zAfter ? zAfter : zBefore));
}
if( zDate ){
rDate = symbolic_name_to_mtime(zDate);
if( db_int(0,
"SELECT EXISTS (SELECT 1 FROM event CROSS JOIN blob"
" WHERE blob.rid=event.objid AND mtime<=%.17g%s)",
rDate-ONE_SECOND, blob_sql_text(&cond))
){
timeline_submenu(&url, "Older", "b", zDate, "a");
zOlderButton = fossil_strdup(url_render(&url, "b", zDate, "a", 0));
}
free(zDate);
}
zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/");
if( (!zDate || !zDate[0]) && ( zAfter || zBefore ) ){
zDate = mprintf("%s", (zBefore ? zBefore : zAfter));
}
if( zDate ){
rDate = symbolic_name_to_mtime(zDate);
if( db_int(0,
"SELECT EXISTS (SELECT 1 FROM event CROSS JOIN blob"
" WHERE blob.rid=event.objid AND mtime>=%.17g%s)",
rDate+ONE_SECOND, blob_sql_text(&cond))
){
timeline_submenu(&url, "Newer", "a", zDate, "b");
}
free(zDate);
}
if( zType[0]=='a' || zType[0]=='c' ){
if( (tmFlags & TIMELINE_UNHIDE)==0 ){
timeline_submenu(&url, "Unhide", "unhide", "", 0);
}
}
style_submenu_entry("n","Max:",4,0);
timeline_y_submenu(disableY);
style_submenu_binary("v","With Files","Without Files",
zType[0]!='a' && zType[0]!='c');
}
blob_zero(&cond);
}
if( PB("showsql") ){
@ <pre>%h(blob_sql_text(&sql))</pre>
}
if( search_restrict(SRCH_CKIN)!=0 ){
style_submenu_element("Search", 0, "%R/search?y=c");
}
|
| ︙ | ︙ | |||
2005 2006 2007 2008 2009 2010 2011 | ** before ** after ** descendants | children ** ancestors | parents ** ** The CHECKIN can be any unique prefix of 4 characters or more. ** The DATETIME should be in the ISO8601 format. For | | | 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 | ** before ** after ** descendants | children ** ancestors | parents ** ** The CHECKIN can be any unique prefix of 4 characters or more. ** The DATETIME should be in the ISO8601 format. For ** example: "2007-08-18 07:21:21". You can also say "current" ** for the current version or "now" for the current time. ** ** Options: ** -n|--limit N Output the first N entries (default 20 lines). ** N=0 means no limit. ** -p|--path PATH Output items affecting PATH only. ** PATH can be a file or a sub directory. |
| ︙ | ︙ |
Changes to src/tkt.c.
| ︙ | ︙ | |||
421 422 423 424 425 426 427 |
/*
** For trouble-shooting purposes, render a dump of the aField[] table to
** the webpage currently under construction.
*/
static void showAllFields(void){
int i;
| | | | 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 |
/*
** For trouble-shooting purposes, render a dump of the aField[] table to
** the webpage currently under construction.
*/
static void showAllFields(void){
int i;
@ <div style="color:blue">
@ <p>Database fields:</p><ul>
for(i=0; i<nField; i++){
@ <li>aField[%d(i)].zName = "%h(aField[i].zName)";
@ originally = "%h(aField[i].zValue)";
@ currently = "%h(PD(aField[i].zName,""))";
if( aField[i].zAppend ){
@ zAppend = "%h(aField[i].zAppend)";
}
@ mUsed = %d(aField[i].mUsed);
}
@ </ul></div>
}
/*
** WEBPAGE: tktview
** URL: tktview?name=UUID
**
** View a ticket identified by the name= query parameter.
|
| ︙ | ︙ | |||
650 651 652 653 654 655 656 |
blob_reset(&tktchng);
return TH_OK;
}
needMod = ticket_need_moderation(0);
if( g.zPath[0]=='d' ){
const char *zNeedMod = needMod ? "required" : "skipped";
/* If called from /debug_tktnew or /debug_tktedit... */
| | > | | 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 |
blob_reset(&tktchng);
return TH_OK;
}
needMod = ticket_need_moderation(0);
if( g.zPath[0]=='d' ){
const char *zNeedMod = needMod ? "required" : "skipped";
/* If called from /debug_tktnew or /debug_tktedit... */
@ <div style="color:blue">
@ <p>Ticket artifact that would have been submitted:</p>
@ <blockquote><pre>%h(blob_str(&tktchng))</pre></blockquote>
@ <blockquote><pre>Moderation would be %h(zNeedMod).</pre></blockquote>
@ </div>
@ <hr />
return TH_OK;
}else{
if( g.thTrace ){
Th_Trace("submit_ticket {\n<blockquote><pre>\n%h\n</pre></blockquote>\n"
"}<br />\n",
blob_str(&tktchng));
}
|
| ︙ | ︙ | |||
1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 |
blob_reset(&val);
}
@ </ol>
}
/*
** COMMAND: ticket*
** Usage: %fossil ticket SUBCOMMAND ...
**
** Run various subcommands to control tickets
**
| > | | | | | | > | | | | | | | | | | | | | | | | | | | | | 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 |
blob_reset(&val);
}
@ </ol>
}
/*
** COMMAND: ticket*
**
** Usage: %fossil ticket SUBCOMMAND ...
**
** Run various subcommands to control tickets
**
** %fossil ticket show (REPORTTITLE|REPORTNR) ?TICKETFILTER? ?OPTIONS?
**
** Options:
** -l|--limit LIMITCHAR
** -q|--quote
** -R|--repository FILE
**
** Run the ticket report, identified by the report format title
** used in the GUI. The data is written as flat file on stdout,
** using TAB as separator. The separator can be changed using
** the -l or --limit option.
**
** If TICKETFILTER is given on the commandline, the query is
** limited with a new WHERE-condition.
** example: Report lists a column # with the uuid
** TICKETFILTER may be [#]='uuuuuuuuu'
** example: Report only lists rows with status not open
** TICKETFILTER: status != 'open'
**
** If --quote is used, the tickets are encoded by quoting special
** chars (space -> \\s, tab -> \\t, newline -> \\n, cr -> \\r,
** formfeed -> \\f, vtab -> \\v, nul -> \\0, \\ -> \\\\).
** Otherwise, the simplified encoding as on the show report raw page
** in the GUI is used. This has no effect in JSON mode.
**
** Instead of the report title it's possible to use the report
** number; the special report number 0 lists all columns defined in
** the ticket table.
**
** %fossil ticket list fields
** %fossil ticket ls fields
**
** List all fields defined for ticket in the fossil repository.
**
** %fossil ticket list reports
** %fossil ticket ls reports
**
** List all ticket reports defined in the fossil repository.
**
** %fossil ticket set TICKETUUID (FIELD VALUE)+ ?-q|--quote?
** %fossil ticket change TICKETUUID (FIELD VALUE)+ ?-q|--quote?
**
** Change ticket identified by TICKETUUID to set the values of
** each field FIELD to VALUE.
**
** Field names as defined in the TICKET table. By default, these
** names include: type, status, subsystem, priority, severity, foundin,
** resolution, title, and comment, but other field names can be added
** or substituted in customized installations.
**
** If you use +FIELD, the VALUE is appended to the field FIELD. You
** can use more than one field/value pair on the commandline. Using
** --quote enables the special character decoding as in "ticket
** show", which allows setting multiline text or text with special
** characters.
**
** %fossil ticket add FIELD VALUE ?FIELD VALUE .. ? ?-q|--quote?
**
** Like set, but create a new ticket with the given values.
**
** %fossil ticket history TICKETUUID
**
** Show the complete change history for the ticket
**
** Note that the values in set|add are not validated against the
** definitions given in "Ticket Common Script".
*/
void ticket_cmd(void){
int n;
const char *zUser;
const char *zDate;
const char *zTktUuid;
|
| ︙ | ︙ |
Changes to src/tktsetup.c.
| ︙ | ︙ | |||
275 276 277 278 279 280 281 |
*/
const char *ticket_change_code(void){
return db_get("ticket-change", zDefaultTicketChange);
}
/*
** WEBPAGE: tktsetup_change
| | | 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
*/
const char *ticket_change_code(void){
return db_get("ticket-change", zDefaultTicketChange);
}
/*
** WEBPAGE: tktsetup_change
** Administrative screen used to view or edit the TH1 script
** that shows ticket changes.
*/
void tktsetup_change_page(void){
static const char zDesc[] =
@ Enter TH1 script that runs after processing the ticket editing
@ and creation pages.
;
|
| ︙ | ︙ | |||
522 523 524 525 526 527 528 |
@ set alwaysPlaintext [info exists plaintext]
@ query {SELECT datetime(tkt_mtime) AS xdate, login AS xlogin,
@ mimetype as xmimetype, icomment AS xcomment,
@ username AS xusername
@ FROM ticketchng
@ WHERE tkt_id=$tkt_id AND length(icomment)>0} {
@ if {$seenRow} {
| | | 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 |
@ set alwaysPlaintext [info exists plaintext]
@ query {SELECT datetime(tkt_mtime) AS xdate, login AS xlogin,
@ mimetype as xmimetype, icomment AS xcomment,
@ username AS xusername
@ FROM ticketchng
@ WHERE tkt_id=$tkt_id AND length(icomment)>0} {
@ 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} {
|
| ︙ | ︙ | |||
649 650 651 652 653 654 655 | @ <input type="text" name="username" value="$<username>" size="30" />:<br /> @ <textarea name="icomment" cols="80" rows="15" @ wrap="virtual" class="wikiedit">$<icomment></textarea> @ </td></tr> @ @ <th1>enable_output [info exists preview]</th1> @ <tr><td colspan="2"> | | | | 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 |
@ <input type="text" name="username" value="$<username>" size="30" />:<br />
@ <textarea name="icomment" cols="80" rows="15"
@ wrap="virtual" class="wikiedit">$<icomment></textarea>
@ </td></tr>
@
@ <th1>enable_output [info exists preview]</th1>
@ <tr><td colspan="2">
@ Description Preview:<br /><hr />
@ <th1>
@ if {$mutype eq "Wiki"} {
@ wiki $icomment
@ } elseif {$mutype eq "Plain Text"} {
@ set r [randhex]
@ wiki "<verbatim-$r>\n[string trimright $icomment]\n</verbatim-$r>"
@ } elseif {$mutype eq {[links only]}} {
@ set r [randhex]
@ wiki "<verbatim-$r links>\n[string trimright $icomment]</verbatim-$r>"
@ } else {
@ wiki "<nowiki>\n[string trimright $icomment]\n</nowiki>"
@ }
@ </th1>
@ <hr />
@ </td></tr>
@ <th1>enable_output 1</th1>
@
@ <tr>
@ <td align="right">
@ <input type="submit" name="preview" value="Preview" />
@ </td>
|
| ︙ | ︙ |
Changes to src/unicode.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 | ** ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This file is copied from ext/fts5/fts5_unicode2.c of SQLite3 with ** minor changes. */ #include "config.h" #include "unicode.h" /* ** Return true if the argument corresponds to a unicode codepoint |
| ︙ | ︙ | |||
47 48 49 50 51 52 53 |
0x000BBC81, 0x000DD401, 0x000DF801, 0x000E1002, 0x000E1C01,
0x000FD801, 0x00120808, 0x00156806, 0x00162402, 0x00163403,
0x00164437, 0x0017CC02, 0x0018001D, 0x00187802, 0x00192C15,
0x0019A804, 0x0019C001, 0x001B5001, 0x001B580F, 0x001B9C07,
0x001BF402, 0x001C000E, 0x001C3C01, 0x001C4401, 0x001CC01B,
0x001E980B, 0x001FAC09, 0x001FD804, 0x00205804, 0x00206C09,
0x00209403, 0x0020A405, 0x0020C00F, 0x00216403, 0x00217801,
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | | > > | | | | | > | | | | | > | | | | 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 |
0x000BBC81, 0x000DD401, 0x000DF801, 0x000E1002, 0x000E1C01,
0x000FD801, 0x00120808, 0x00156806, 0x00162402, 0x00163403,
0x00164437, 0x0017CC02, 0x0018001D, 0x00187802, 0x00192C15,
0x0019A804, 0x0019C001, 0x001B5001, 0x001B580F, 0x001B9C07,
0x001BF402, 0x001C000E, 0x001C3C01, 0x001C4401, 0x001CC01B,
0x001E980B, 0x001FAC09, 0x001FD804, 0x00205804, 0x00206C09,
0x00209403, 0x0020A405, 0x0020C00F, 0x00216403, 0x00217801,
0x00235030, 0x0024E803, 0x0024F812, 0x00254407, 0x00258804,
0x0025C001, 0x00260403, 0x0026F001, 0x0026F807, 0x00271C02,
0x00272C03, 0x00275C01, 0x00278802, 0x0027C802, 0x0027E802,
0x00280403, 0x0028F001, 0x0028F805, 0x00291C02, 0x00292C03,
0x00294401, 0x0029C002, 0x0029D401, 0x002A0403, 0x002AF001,
0x002AF808, 0x002B1C03, 0x002B2C03, 0x002B8802, 0x002BC002,
0x002C0403, 0x002CF001, 0x002CF807, 0x002D1C02, 0x002D2C03,
0x002D5802, 0x002D8802, 0x002DC001, 0x002E0801, 0x002EF805,
0x002F1803, 0x002F2804, 0x002F5C01, 0x002FCC08, 0x00300004,
0x0030F807, 0x00311803, 0x00312804, 0x00315402, 0x00318802,
0x0031FC01, 0x00320403, 0x0032F001, 0x0032F807, 0x00331803,
0x00332804, 0x00335402, 0x00338802, 0x00340403, 0x0034F807,
0x00351803, 0x00352804, 0x00353C01, 0x00355C01, 0x00358802,
0x0035E401, 0x00360802, 0x00372801, 0x00373C06, 0x00375801,
0x00376008, 0x0037C803, 0x0038C401, 0x0038D007, 0x0038FC01,
0x00391C09, 0x00396802, 0x003AC401, 0x003AD006, 0x003AEC02,
0x003B2006, 0x003C041F, 0x003CD00C, 0x003DC417, 0x003E340B,
0x003E6424, 0x003EF80F, 0x003F380D, 0x0040AC14, 0x00412806,
0x00415804, 0x00417803, 0x00418803, 0x00419C07, 0x0041C404,
0x0042080C, 0x00423C01, 0x00426806, 0x0043EC01, 0x004D740C,
0x004E400A, 0x00500001, 0x0059B402, 0x005A0001, 0x005A6C02,
0x005BAC03, 0x005C4803, 0x005CC805, 0x005D4802, 0x005DC802,
0x005ED023, 0x005F6004, 0x005F7401, 0x0060000F, 0x00621402,
0x0062A401, 0x0064800C, 0x0064C00C, 0x00650001, 0x00651002,
0x00677822, 0x00685C05, 0x00687802, 0x0069540A, 0x0069801D,
0x0069FC01, 0x006A8007, 0x006AA006, 0x006AC00F, 0x006C0005,
0x006CD011, 0x006D6823, 0x006E0003, 0x006E840D, 0x006F980E,
0x006FF004, 0x00709014, 0x0070EC05, 0x0071F802, 0x00730008,
0x00734019, 0x0073B401, 0x0073C803, 0x0073E002, 0x00770036,
0x0077EC05, 0x007EF401, 0x007EFC03, 0x007F3403, 0x007F7403,
0x007FB403, 0x007FF402, 0x00800065, 0x0081980A, 0x0081E805,
0x00822805, 0x0082801F, 0x00834021, 0x00840002, 0x00840C04,
0x00842002, 0x00845001, 0x00845803, 0x00847806, 0x00849401,
0x00849C01, 0x0084A401, 0x0084B801, 0x0084E802, 0x00850005,
0x00852804, 0x00853C01, 0x00862802, 0x0086426F, 0x00900027,
0x0091000B, 0x0092704E, 0x00940276, 0x009E53E0, 0x00ADD820,
0x00AE6022, 0x00AEF40C, 0x00AF2808, 0x00AFB004, 0x00B39406,
0x00B3BC03, 0x00B3E404, 0x00B3F802, 0x00B5C001, 0x00B5FC01,
0x00B7804F, 0x00B8C015, 0x00BA001A, 0x00BA6C59, 0x00BC00D6,
0x00BFC00C, 0x00C00005, 0x00C02019, 0x00C0A807, 0x00C0D802,
0x00C0F403, 0x00C26404, 0x00C28001, 0x00C3EC01, 0x00C64002,
0x00C6580A, 0x00C70024, 0x00C8001F, 0x00C8A81E, 0x00C94001,
0x00C98020, 0x00CA2827, 0x00CB003F, 0x00CC0100, 0x01370040,
0x02924037, 0x0293F802, 0x02983403, 0x0299BC10, 0x029A7802,
0x029BC008, 0x029C0017, 0x029C8002, 0x029E2402, 0x02A00801,
0x02A01801, 0x02A02C01, 0x02A08C09, 0x02A0D804, 0x02A1D004,
0x02A20002, 0x02A2D012, 0x02A33802, 0x02A38012, 0x02A3E003,
0x02A3F001, 0x02A4980A, 0x02A51C0D, 0x02A57C01, 0x02A60004,
0x02A6CC1B, 0x02A77802, 0x02A79401, 0x02A8A40E, 0x02A90C01,
0x02A93002, 0x02A97004, 0x02A9DC03, 0x02A9EC03, 0x02AAC001,
0x02AAC803, 0x02AADC02, 0x02AAF802, 0x02AB0401, 0x02AB7802,
0x02ABAC07, 0x02ABD402, 0x02AD6C01, 0x02AF8C0B, 0x03600001,
0x036DFC02, 0x036FFC02, 0x037FFC01, 0x03EC7801, 0x03ECA401,
0x03EEC810, 0x03F4F802, 0x03F7F002, 0x03F8001A, 0x03F88033,
0x03F95013, 0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807,
0x03FCEC06, 0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405,
0x04040003, 0x0404DC09, 0x0405E411, 0x04063003, 0x0406400C,
0x04068001, 0x0407402E, 0x040B8001, 0x040DD805, 0x040E7C01,
0x040F4001, 0x0415BC01, 0x04215C01, 0x0421DC02, 0x04247C01,
0x0424FC01, 0x04280403, 0x04281402, 0x04283004, 0x0428E003,
0x0428FC01, 0x04294009, 0x0429FC01, 0x042B2001, 0x042B9402,
0x042BC007, 0x042CE407, 0x042E6404, 0x04400003, 0x0440E016,
0x0441FC04, 0x0442C012, 0x04440003, 0x04449C0E, 0x04450004,
0x0445CC03, 0x04460003, 0x0446CC0E, 0x04471409, 0x04476C01,
0x04477403, 0x0448B013, 0x044AA401, 0x044B7C0C, 0x044C0004,
0x044CF001, 0x044CF807, 0x044D1C02, 0x044D2C03, 0x044D5C01,
0x044D8802, 0x044D9807, 0x044DC005, 0x0450D412, 0x04512C05,
0x04516C01, 0x04517401, 0x0452C014, 0x04531801, 0x0456BC07,
0x0456E020, 0x04577002, 0x0458C014, 0x0459800D, 0x045AAC0D,
0x045C740F, 0x045CF004, 0x0470BC08, 0x0470E008, 0x04710405,
0x0471C002, 0x04724816, 0x0472A40E, 0x0491C005, 0x05A9B802,
0x05ABC006, 0x05ACC010, 0x05AD1002, 0x05BD442E, 0x05BE3C04,
0x06F27008, 0x074000F6, 0x07440027, 0x0744A4C0, 0x07480046,
0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01, 0x075C5401,
0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401, 0x075EA401,
0x075F0C01, 0x0760028C, 0x076A6C05, 0x076A840F, 0x07800007,
0x07802011, 0x07806C07, 0x07808C02, 0x07809805, 0x07A34007,
0x07A51007, 0x07A57802, 0x07BBC002, 0x07C0002C, 0x07C0C064,
0x07C2800F, 0x07C2C40F, 0x07C3040F, 0x07C34425, 0x07C4401F,
0x07C4C03C, 0x07C5C03D, 0x07C7981D, 0x07C8402C, 0x07C90009,
0x07C94002, 0x07CC03D3, 0x07DB800D, 0x07DBC007, 0x07DC0074,
0x07DE0055, 0x07E0000C, 0x07E04038, 0x07E1400A, 0x07E18028,
0x07E2401E, 0x07E4400F, 0x07E48008, 0x07E4C001, 0x07E4CC0C,
0x07E5000C, 0x07E5400F, 0x07E60012, 0x07E70001, 0x38000401,
0x38008060, 0x380400F0,
};
static const unsigned int aAscii[4] = {
0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001,
};
if( (unsigned int)c<128 ){
return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
}else if( (unsigned int)c<(1<<22) ){
unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
int iRes = 0;
int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
int iLo = 0;
while( iHi>=iLo ){
int iTest = (iHi + iLo) / 2;
if( key >= aEntry[iTest] ){
|
| ︙ | ︙ | |||
256 257 258 259 260 261 262 |
** http://www.unicode.org for details.
*/
static const struct TableEntry {
unsigned short iCode;
unsigned char flags;
unsigned char nRange;
} aEntry[] = {
| | | | | | | | | | | | | | | | | | | | | | | | | | | | > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | | | | < > > < | | | | | < > > > > > > | 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 |
** http://www.unicode.org for details.
*/
static const struct TableEntry {
unsigned short iCode;
unsigned char flags;
unsigned char nRange;
} aEntry[] = {
{65, 14, 26}, {181, 66, 1}, {192, 14, 23},
{216, 14, 7}, {256, 1, 48}, {306, 1, 6},
{313, 1, 16}, {330, 1, 46}, {376, 150, 1},
{377, 1, 6}, {383, 138, 1}, {385, 52, 1},
{386, 1, 4}, {390, 46, 1}, {391, 0, 1},
{393, 44, 2}, {395, 0, 1}, {398, 34, 1},
{399, 40, 1}, {400, 42, 1}, {401, 0, 1},
{403, 44, 1}, {404, 48, 1}, {406, 54, 1},
{407, 50, 1}, {408, 0, 1}, {412, 54, 1},
{413, 56, 1}, {415, 58, 1}, {416, 1, 6},
{422, 62, 1}, {423, 0, 1}, {425, 62, 1},
{428, 0, 1}, {430, 62, 1}, {431, 0, 1},
{433, 60, 2}, {435, 1, 4}, {439, 64, 1},
{440, 0, 1}, {444, 0, 1}, {452, 2, 1},
{453, 0, 1}, {455, 2, 1}, {456, 0, 1},
{458, 2, 1}, {459, 1, 18}, {478, 1, 18},
{497, 2, 1}, {498, 1, 4}, {502, 156, 1},
{503, 168, 1}, {504, 1, 40}, {544, 144, 1},
{546, 1, 18}, {570, 74, 1}, {571, 0, 1},
{573, 142, 1}, {574, 72, 1}, {577, 0, 1},
{579, 140, 1}, {580, 30, 1}, {581, 32, 1},
{582, 1, 10}, {837, 38, 1}, {880, 1, 4},
{886, 0, 1}, {895, 38, 1}, {902, 20, 1},
{904, 18, 3}, {908, 28, 1}, {910, 26, 2},
{913, 14, 17}, {931, 14, 9}, {962, 0, 1},
{975, 4, 1}, {976, 174, 1}, {977, 176, 1},
{981, 180, 1}, {982, 178, 1}, {984, 1, 24},
{1008, 170, 1}, {1009, 172, 1}, {1012, 164, 1},
{1013, 162, 1}, {1015, 0, 1}, {1017, 186, 1},
{1018, 0, 1}, {1021, 144, 3}, {1024, 36, 16},
{1040, 14, 32}, {1120, 1, 34}, {1162, 1, 54},
{1216, 6, 1}, {1217, 1, 14}, {1232, 1, 96},
{1329, 24, 38}, {4256, 70, 38}, {4295, 70, 1},
{4301, 70, 1}, {5112, 184, 6}, {7296, 122, 1},
{7297, 124, 1}, {7298, 126, 1}, {7299, 130, 2},
{7301, 128, 1}, {7302, 132, 1}, {7303, 134, 1},
{7304, 96, 1}, {7680, 1, 150}, {7835, 166, 1},
{7838, 116, 1}, {7840, 1, 96}, {7944, 184, 8},
{7960, 184, 6}, {7976, 184, 8}, {7992, 184, 8},
{8008, 184, 6}, {8025, 185, 8}, {8040, 184, 8},
{8072, 184, 8}, {8088, 184, 8}, {8104, 184, 8},
{8120, 184, 2}, {8122, 160, 2}, {8124, 182, 1},
{8126, 120, 1}, {8136, 158, 4}, {8140, 182, 1},
{8152, 184, 2}, {8154, 154, 2}, {8168, 184, 2},
{8170, 152, 2}, {8172, 186, 1}, {8184, 146, 2},
{8186, 148, 2}, {8188, 182, 1}, {8486, 118, 1},
{8490, 112, 1}, {8491, 114, 1}, {8498, 12, 1},
{8544, 8, 16}, {8579, 0, 1}, {9398, 10, 26},
{11264, 24, 47}, {11360, 0, 1}, {11362, 108, 1},
{11363, 136, 1}, {11364, 110, 1}, {11367, 1, 6},
{11373, 104, 1}, {11374, 106, 1}, {11375, 100, 1},
{11376, 102, 1}, {11378, 0, 1}, {11381, 0, 1},
{11390, 98, 2}, {11392, 1, 100}, {11499, 1, 4},
{11506, 0, 1}, {42560, 1, 46}, {42624, 1, 28},
{42786, 1, 14}, {42802, 1, 62}, {42873, 1, 4},
{42877, 94, 1}, {42878, 1, 10}, {42891, 0, 1},
{42893, 86, 1}, {42896, 1, 4}, {42902, 1, 20},
{42922, 80, 1}, {42923, 76, 1}, {42924, 78, 1},
{42925, 82, 1}, {42926, 80, 1}, {42928, 90, 1},
{42929, 84, 1}, {42930, 88, 1}, {42931, 68, 1},
{42932, 1, 4}, {43888, 92, 80}, {65313, 14, 26},
};
static const unsigned short aiOff[] = {
1, 2, 8, 15, 16, 26, 28, 32,
34, 37, 38, 40, 48, 63, 64, 69,
71, 79, 80, 116, 202, 203, 205, 206,
207, 209, 210, 211, 213, 214, 217, 218,
219, 775, 928, 7264, 10792, 10795, 23217, 23221,
23228, 23231, 23254, 23256, 23275, 23278, 26672, 30204,
35267, 54721, 54753, 54754, 54756, 54787, 54793, 54809,
57153, 57274, 57921, 58019, 58363, 59314, 59315, 59324,
59325, 59326, 59332, 59356, 61722, 65268, 65341, 65373,
65406, 65408, 65410, 65415, 65424, 65436, 65439, 65450,
65462, 65472, 65476, 65478, 65480, 65482, 65488, 65506,
65511, 65514, 65521, 65527, 65528, 65529,
};
int ret = c;
assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 );
if( c<128 ){
if( c>='A' && c<='Z' ) ret = c + ('a' - 'A');
}else if( c<65536 ){
const struct TableEntry *p;
int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
int iLo = 0;
int iRes = -1;
assert( c>aEntry[0].iCode );
while( iHi>=iLo ){
int iTest = (iHi + iLo) / 2;
int cmp = (c - aEntry[iTest].iCode);
if( cmp>=0 ){
iRes = iTest;
iLo = iTest+1;
}else{
iHi = iTest-1;
}
}
assert( iRes>=0 && c>=aEntry[iRes].iCode );
p = &aEntry[iRes];
if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){
ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
assert( ret>0 );
}
if( bRemoveDiacritic ) ret = unicode_remove_diacritic(ret);
}
else if( c>=66560 && c<66600 ){
ret = c + 40;
}
else if( c>=66736 && c<66772 ){
ret = c + 40;
}
else if( c>=68736 && c<68787 ){
ret = c + 64;
}
else if( c>=71840 && c<71872 ){
ret = c + 32;
}
else if( c>=125184 && c<125218 ){
ret = c + 34;
}
return ret;
}
|
Changes to src/update.c.
| ︙ | ︙ | |||
151 152 153 154 155 156 157 |
verify_all_options();
db_must_be_within_tree();
vid = db_lget_int("checkout", 0);
user_select();
if( !dryRunFlag && !internalUpdate ){
if( autosync_loop(SYNC_PULL + SYNC_VERBOSE*verboseFlag,
| | | | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
verify_all_options();
db_must_be_within_tree();
vid = db_lget_int("checkout", 0);
user_select();
if( !dryRunFlag && !internalUpdate ){
if( autosync_loop(SYNC_PULL + SYNC_VERBOSE*verboseFlag,
db_get_int("autosync-tries", 1), 1) ){
fossil_fatal("update abandoned due to sync failure");
}
}
/* Create any empty directories now, as well as after the update,
** so changes in settings are reflected now */
if( !dryRunFlag ) ensure_empty_dirs_created();
|
| ︙ | ︙ |
Changes to src/user.c.
| ︙ | ︙ | |||
17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
**
** Commands and procedures used for creating, processing, editing, and
** querying information about users.
*/
#include "config.h"
#include "user.h"
/*
** Strip leading and trailing space from a string and add the string
** onto the end of a blob.
*/
static void strip_string(Blob *pBlob, char *z){
int i;
| > > > | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
**
** Commands and procedures used for creating, processing, editing, and
** querying information about users.
*/
#include "config.h"
#include "user.h"
#if defined(_WIN32)
#include <conio.h>
#endif
/*
** Strip leading and trailing space from a string and add the string
** onto the end of a blob.
*/
static void strip_string(Blob *pBlob, char *z){
int i;
|
| ︙ | ︙ | |||
83 84 85 86 87 88 89 90 91 92 93 94 |
}
}
pwd[i]='\0';
fputs("\n", stderr);
return pwd;
}
#endif
/*
** Do a single prompt for a passphrase. Store the results in the blob.
*/
static void prompt_for_passphrase(const char *zPrompt, Blob *pPassphrase){
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > | 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 |
}
}
pwd[i]='\0';
fputs("\n", stderr);
return pwd;
}
#endif
#if defined(_WIN32) || defined(WIN32)
# include <io.h>
# include <fcntl.h>
# undef popen
# define popen _popen
# undef pclose
# define pclose _pclose
#endif
/*
** Scramble substitution matrix:
*/
static char aSubst[256];
/*
** Descramble the password
*/
static void userDescramble(char *z){
int i;
for(i=0; z[i]; i++) z[i] = aSubst[(unsigned char)z[i]];
}
/* Print a string in 5-letter groups */
static void printFive(const unsigned char *z){
int i;
for(i=0; z[i]; i++){
if( i>0 && (i%5)==0 ) putchar(' ');
putchar(z[i]);
}
putchar('\n');
}
/* Return a pseudo-random integer between 0 and N-1 */
static int randint(int N){
unsigned char x;
assert( N<256 );
sqlite3_randomness(1, &x);
return x % N;
}
/*
** Generate and print a random scrambling of letters a through z (omitting x)
** and set up the aSubst[] matrix to descramble.
*/
static void userGenerateScrambleCode(void){
unsigned char zOrig[30];
unsigned char zA[30];
unsigned char zB[30];
int nA = 25;
int nB = 0;
int i;
memcpy(zOrig, "abcdefghijklmnopqrstuvwyz", nA+1);
memcpy(zA, zOrig, nA+1);
assert( nA==(int)strlen((char*)zA) );
for(i=0; i<sizeof(aSubst); i++) aSubst[i] = i;
printFive(zA);
while( nA>0 ){
int x = randint(nA);
zB[nB++] = zA[x];
zA[x] = zA[--nA];
}
assert( nB==25 );
zB[nB] = 0;
printFive(zB);
for(i=0; i<nB; i++) aSubst[zB[i]] = zOrig[i];
}
/*
** Return the value of the FOSSIL_SECURITY_LEVEL environment variable.
** Or return 0 if that variable does not exist.
*/
int fossil_security_level(void){
const char *zLevel = fossil_getenv("FOSSIL_SECURITY_LEVEL");
if( zLevel==0 ) return 0;
return atoi(zLevel);
}
/*
** Do a single prompt for a passphrase. Store the results in the blob.
**
**
** The return value is a pointer to a static buffer that is overwritten
** on subsequent calls to this same routine.
*/
static void prompt_for_passphrase(const char *zPrompt, Blob *pPassphrase){
char *z;
#if 0
*/
** If the FOSSIL_PWREADER environment variable is set, then it will
** be the name of a program that prompts the user for their password/
** passphrase in a secure manner. The program should take one or more
** arguments which are the prompts and should output the acquired
** passphrase as a single line on stdout. This function will read the
** output using popen().
**
** If FOSSIL_PWREADER is not set, or if it is not the name of an
** executable, then use the C-library getpass() routine.
*/
const char *zProg = fossil_getenv("FOSSIL_PWREADER");
if( zProg && zProg[0] ){
static char zPass[100];
Blob cmd;
FILE *in;
blob_zero(&cmd);
blob_appendf(&cmd, "%s \"Fossil Passphrase\" \"%s\"", zProg, zPrompt);
zPass[0] = 0;
in = popen(blob_str(&cmd), "r");
fgets(zPass, sizeof(zPass), in);
pclose(in);
blob_reset(&cmd);
z = zPass;
}else
#endif
if( fossil_security_level()>=2 ){
userGenerateScrambleCode();
z = getpass(zPrompt);
if( z ) userDescramble(z);
printf("\033[3A\033[J"); /* Erase previous three lines */
fflush(stdout);
}else{
z = getpass(zPrompt);
}
strip_string(pPassphrase, z);
}
/*
** Prompt the user for a password. Store the result in the pPassphrase
** blob.
**
|
| ︙ | ︙ | |||
137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
int save_password_prompt(const char *passwd){
Blob x;
char c;
const char *old = db_get("last-sync-pw", 0);
if( (old!=0) && fossil_strcmp(unobscure(old), passwd)==0 ){
return 0;
}
prompt_user("remember password (Y/n)? ", &x);
c = blob_str(&x)[0];
blob_reset(&x);
return ( c!='n' && c!='N' );
}
/*
| > | 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
int save_password_prompt(const char *passwd){
Blob x;
char c;
const char *old = db_get("last-sync-pw", 0);
if( (old!=0) && fossil_strcmp(unobscure(old), passwd)==0 ){
return 0;
}
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' );
}
/*
|
| ︙ | ︙ | |||
175 176 177 178 179 180 181 |
z = fgets(zLine, sizeof(zLine), stdin);
if( z ){
int n = (int)strlen(z);
if( n>0 && z[n-1]=='\n' ) fossil_new_line_started();
strip_string(pIn, z);
}
}
| < | 297 298 299 300 301 302 303 304 305 306 307 308 309 310 |
z = fgets(zLine, sizeof(zLine), stdin);
if( z ){
int n = (int)strlen(z);
if( n>0 && z[n-1]=='\n' ) fossil_new_line_started();
strip_string(pIn, z);
}
}
/*
** COMMAND: user*
**
** Usage: %fossil user SUBCOMMAND ... ?-R|--repository FILE?
**
** Run various subcommands on users of the open repository or of
|
| ︙ | ︙ | |||
384 385 386 387 388 389 390 391 392 393 394 395 396 397 |
"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"
);
fossil_fatal("cannot determine user");
}
/*
** COMMAND: test-hash-passwords
**
** Usage: %fossil test-hash-passwords REPOSITORY
**
** Convert all local password storage to use a SHA1 hash of the password
| > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
"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"
);
fossil_fatal("cannot determine user");
}
/*
** COMMAND: test-usernames
**
** Usage: %fossil test-usernames
**
** Print details about sources of fossil usernames.
*/
void test_usernames_cmd(void){
db_find_and_open_repository(0, 0);
fossil_print("Initial g.zLogin: %s\n", g.zLogin);
fossil_print("Initial g.userUid: %d\n", g.userUid);
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, 0);
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);
}
/*
** COMMAND: test-hash-passwords
**
** Usage: %fossil test-hash-passwords REPOSITORY
**
** Convert all local password storage to use a SHA1 hash of the password
|
| ︙ | ︙ | |||
472 473 474 475 476 477 478 |
blob_append_sql(&sql," ORDER BY rowid DESC LIMIT %d OFFSET %d", n+1, skip);
if( skip ){
style_submenu_element("Newer", "Newer entries",
"%s/access_log?o=%d&n=%d&y=%d", g.zTop, skip>=n ? skip-n : 0,
n, y);
}
rc = db_prepare_ignore_error(&q, "%s", blob_sql_text(&sql));
| < | | | 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 |
blob_append_sql(&sql," ORDER BY rowid DESC LIMIT %d OFFSET %d", n+1, skip);
if( skip ){
style_submenu_element("Newer", "Newer entries",
"%s/access_log?o=%d&n=%d&y=%d", g.zTop, skip>=n ? skip-n : 0,
n, y);
}
rc = db_prepare_ignore_error(&q, "%s", blob_sql_text(&sql));
fLogEnabled = db_get_boolean("access-log", 0);
@ <div align="center">Access logging is %s(fLogEnabled?"on":"off").
@ (Change this on the <a href="setup_settings">settings</a> page.)</div>
@ <table border="1" cellpadding="5" id="logtable" align="center">
@ <thead><tr><th width="33%%">Date</th><th width="34%%">User</th>
@ <th width="33%%">IP Address</th></tr></thead><tbody>
while( rc==SQLITE_OK && db_step(&q)==SQLITE_ROW ){
const char *zName = db_column_text(&q, 0);
const char *zIP = db_column_text(&q, 1);
const char *zDate = db_column_text(&q, 2);
int bSuccess = db_column_int(&q, 3);
|
| ︙ | ︙ | |||
501 502 503 504 505 506 507 |
}
@ <td>%s(zDate)</td><td>%h(zName)</td><td>%h(zIP)</td></tr>
}
if( skip>0 || cnt>n ){
style_submenu_element("All", "All entries",
"%s/access_log?n=10000000", g.zTop);
}
| | | | 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 |
}
@ <td>%s(zDate)</td><td>%h(zName)</td><td>%h(zIP)</td></tr>
}
if( skip>0 || cnt>n ){
style_submenu_element("All", "All entries",
"%s/access_log?n=10000000", g.zTop);
}
@ </tbody></table>
db_finalize(&q);
@ <hr />
@ <form method="post" action="%s(g.zTop)/access_log">
@ <label><input type="checkbox" name="delold">
@ Delete all but the most recent 200 entries</input></label>
@ <input type="submit" name="deloldbtn" value="Delete"></input>
@ </form>
@ <form method="post" action="%s(g.zTop)/access_log">
@ <label><input type="checkbox" name="delanon">
|
| ︙ | ︙ |
Changes to src/vfile.c.
| ︙ | ︙ | |||
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 |
" WHERE vid=%d ", g.zLocalRoot, PERM_EXE, PERM_LNK, PERM_REG,
vid);
while( db_step(&q)==SQLITE_ROW ){
int id, rid, isDeleted;
const char *zName;
int chnged = 0;
int oldChnged;
int origPerm;
int currentPerm;
i64 oldMtime;
i64 currentMtime;
i64 origSize;
i64 currentSize;
id = db_column_int(&q, 0);
zName = db_column_text(&q, 1);
rid = db_column_int(&q, 2);
isDeleted = db_column_int(&q, 3);
oldChnged = chnged = db_column_int(&q, 4);
oldMtime = db_column_int64(&q, 7);
origSize = db_column_int64(&q, 6);
currentSize = file_wd_size(zName);
currentMtime = file_wd_mtime(0);
origPerm = db_column_int(&q, 8);
currentPerm = file_wd_perm(zName);
if( chnged==0 && (isDeleted || rid==0) ){
/* "fossil rm" or "fossil add" always change the file */
chnged = 1;
}else if( !file_wd_isfile_or_link(0) && currentSize>=0 ){
if( cksigFlags & CKSIG_ENOTFILE ){
fossil_warning("not an ordinary file: %s", zName);
nErr++;
| > > > > | 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 |
" WHERE vid=%d ", g.zLocalRoot, PERM_EXE, PERM_LNK, PERM_REG,
vid);
while( db_step(&q)==SQLITE_ROW ){
int id, rid, isDeleted;
const char *zName;
int chnged = 0;
int oldChnged;
#ifndef _WIN32
int origPerm;
int currentPerm;
#endif
i64 oldMtime;
i64 currentMtime;
i64 origSize;
i64 currentSize;
id = db_column_int(&q, 0);
zName = db_column_text(&q, 1);
rid = db_column_int(&q, 2);
isDeleted = db_column_int(&q, 3);
oldChnged = chnged = db_column_int(&q, 4);
oldMtime = db_column_int64(&q, 7);
origSize = db_column_int64(&q, 6);
currentSize = file_wd_size(zName);
currentMtime = file_wd_mtime(0);
#ifndef _WIN32
origPerm = db_column_int(&q, 8);
currentPerm = file_wd_perm(zName);
#endif
if( chnged==0 && (isDeleted || rid==0) ){
/* "fossil rm" or "fossil add" always change the file */
chnged = 1;
}else if( !file_wd_isfile_or_link(0) && currentSize>=0 ){
if( cksigFlags & CKSIG_ENOTFILE ){
fossil_warning("not an ordinary file: %s", zName);
nErr++;
|
| ︙ | ︙ |
Changes to src/wiki.c.
| ︙ | ︙ | |||
120 121 122 123 124 125 126 127 128 129 130 131 |
** Return true if the given pagename is the name of the sandbox
*/
static int is_sandbox(const char *zPagename){
return fossil_stricmp(zPagename,"sandbox")==0 ||
fossil_stricmp(zPagename,"sand box")==0;
}
/*
** Only allow certain mimetypes through.
** All others become "text/x-fossil-wiki"
*/
const char *wiki_filter_mimetypes(const char *zMimetype){
| > > > > > > > > > | > > > > > > | | < | > | 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 |
** Return true if the given pagename is the name of the sandbox
*/
static int is_sandbox(const char *zPagename){
return fossil_stricmp(zPagename,"sandbox")==0 ||
fossil_stricmp(zPagename,"sand box")==0;
}
/*
** Formal, common and short names for the various wiki styles.
*/
static const char *const azStyles[] = {
"text/x-fossil-wiki", "Fossil Wiki", "wiki",
"text/x-markdown", "Markdown", "markdown",
"text/plain", "Plain Text", "plain"
};
/*
** Only allow certain mimetypes through.
** All others become "text/x-fossil-wiki"
*/
const char *wiki_filter_mimetypes(const char *zMimetype){
if( zMimetype!=0 ){
int i;
for(i=0; i<sizeof(azStyles)/sizeof(azStyles[0]); i+=3){
if( fossil_strcmp(zMimetype,azStyles[i+2])==0 ){
return azStyles[i];
}
}
if( fossil_strcmp(zMimetype, "text/x-markdown")==0
|| fossil_strcmp(zMimetype, "text/plain")==0 ){
return zMimetype;
}
}
return "text/x-fossil-wiki";
}
/*
** Render wiki text according to its mimetype.
**
|
| ︙ | ︙ | |||
410 411 412 413 414 415 416 |
db_multi_exec("INSERT INTO modreq(objid) VALUES(%d)", nrid);
}
db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
db_multi_exec("INSERT OR IGNORE INTO unclustered VALUES(%d);", nrid);
manifest_crosslink(nrid, pWiki, MC_NONE);
}
| < < < < < < < < < | | 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 |
db_multi_exec("INSERT INTO modreq(objid) VALUES(%d)", nrid);
}
db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
db_multi_exec("INSERT OR IGNORE INTO unclustered VALUES(%d);", nrid);
manifest_crosslink(nrid, pWiki, MC_NONE);
}
/*
** Output a selection box from which the user can select the
** wiki mimetype.
*/
void mimetype_option_menu(const char *zMimetype){
unsigned i;
@ <select name="mimetype" size="1">
for(i=0; i<sizeof(azStyles)/sizeof(azStyles[0]); i+=3){
if( fossil_strcmp(zMimetype,azStyles[i])==0 ){
@ <option value="%s(azStyles[i])" selected>%s(azStyles[i+1])</option>
}else{
@ <option value="%s(azStyles[i])">%s(azStyles[i+1])</option>
}
}
@ </select>
|
| ︙ | ︙ | |||
674 675 676 677 678 679 680 |
char *zId;
zDate = db_text(0, "SELECT datetime('now')");
zRemark = PD("r","");
zUser = PD("u",g.zLogin);
if( fossil_strcmp(zMimetype, "text/x-fossil-wiki")==0 ){
zId = db_text(0, "SELECT lower(hex(randomblob(8)))");
| | | 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 |
char *zId;
zDate = db_text(0, "SELECT datetime('now')");
zRemark = PD("r","");
zUser = PD("u",g.zLogin);
if( fossil_strcmp(zMimetype, "text/x-fossil-wiki")==0 ){
zId = db_text(0, "SELECT lower(hex(randomblob(8)))");
blob_appendf(p, "\n\n<hr /><div id=\"%s\"><i>On %s UTC %h",
zId, zDate, login_name());
if( zUser[0] && fossil_strcmp(zUser,login_name()) ){
blob_appendf(p, " (claiming to be %h)", zUser);
}
blob_appendf(p, " added:</i><br />\n%s</div id=\"%s\">", zRemark, zId);
}else if( fossil_strcmp(zMimetype, "text/x-markdown")==0 ){
blob_appendf(p, "\n\n------\n*On %s UTC %h", zDate, login_name());
|
| ︙ | ︙ | |||
795 796 797 798 799 800 801 |
if( !goodCaptcha ){
@ <p class="generalError">Error: Incorrect security code.</p>
}
if( P("preview")!=0 ){
Blob preview;
blob_zero(&preview);
appendRemark(&preview, zMimetype);
| | | | 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 |
if( !goodCaptcha ){
@ <p class="generalError">Error: Incorrect security code.</p>
}
if( P("preview")!=0 ){
Blob preview;
blob_zero(&preview);
appendRemark(&preview, zMimetype);
@ Preview:<hr />
wiki_render_by_mimetype(&preview, zMimetype);
@ <hr />
blob_reset(&preview);
}
zUser = PD("u", g.zLogin);
form_begin(0, "%R/wikiappend");
login_insert_csrf_secret();
@ <input type="hidden" name="name" value="%h(zPageName)" />
@ <input type="hidden" name="mimetype" value="%h(zMimetype)" />
|
| ︙ | ︙ | |||
1066 1067 1068 1069 1070 1071 1072 | @ through the matching </verbatim>.</p></li> @ </ol> style_footer(); } /* ** Add a new wiki page to the repository. The page name is | | | < | < < < < < < < < < < < < < < < < < < < < | 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 |
@ through the matching </verbatim>.</p></li>
@ </ol>
style_footer();
}
/*
** Add a new wiki page to the repository. The page name is
** given by the zPageName parameter. rid must be zero to create
** a new page otherwise the page identified by rid is updated.
**
** The content of the new page is given by the blob pContent.
**
** zMimeType specifies the N-card for the wiki page. If it is 0,
** empty, or "text/x-fossil-wiki" (the default format) then it is
** ignored.
*/
int wiki_cmd_commit(const char *zPageName, int rid, Blob *pContent,
const char *zMimeType, int localUser){
Blob wiki; /* Wiki page content */
Blob cksum; /* wiki checksum */
char *zDate; /* timestamp */
char *zUuid; /* uuid for rid */
blob_zero(&wiki);
zDate = date_in_standard_format("now");
blob_appendf(&wiki, "D %s\n", zDate);
free(zDate);
blob_appendf(&wiki, "L %F\n", zPageName );
if( zMimeType && *zMimeType
&& 0!=fossil_strcmp(zMimeType,"text/x-fossil-wiki") ){
|
| ︙ | ︙ | |||
1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 | blob_appendf(&wiki, "Z %b\n", &cksum); blob_reset(&cksum); db_begin_transaction(); wiki_put(&wiki, 0, wiki_need_moderation(localUser)); db_end_transaction(0); return 1; } /* ** COMMAND: wiki* ** | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | > | | > | > > | | | | > > | > | | > > > | | > > > > | > > | | | | | > | | > > | > > > > > | 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 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 |
blob_appendf(&wiki, "Z %b\n", &cksum);
blob_reset(&cksum);
db_begin_transaction();
wiki_put(&wiki, 0, wiki_need_moderation(localUser));
db_end_transaction(0);
return 1;
}
/*
** Determine the rid for a tech note given either its id or its
** timestamp. Returns 0 if there is no such item and -1 if the details
** are ambiguous and could refer to multiple items.
*/
int wiki_technote_to_rid(const char *zETime) {
int rid=0; /* Artifact ID of the tech note */
int nETime = strlen(zETime);
Stmt q;
if( nETime>=4 && nETime<=UUID_SIZE && validate16(zETime, nETime) ){
char zUuid[UUID_SIZE+1];
memcpy(zUuid, zETime, nETime+1);
canonical16(zUuid, nETime);
db_prepare(&q,
"SELECT e.objid"
" FROM event e, tag t"
" WHERE e.type='e' AND e.tagid IS NOT NULL AND t.tagid=e.tagid"
" AND t.tagname GLOB 'event-%q*'",
zUuid
);
if( db_step(&q)==SQLITE_ROW ){
rid = db_column_int(&q, 0);
if( db_step(&q)==SQLITE_ROW ) rid = -1;
}
db_finalize(&q);
}
if (!rid) {
if (strlen(zETime)>4) {
rid = db_int(0, "SELECT objid"
" FROM event"
" WHERE datetime(mtime)=datetime('%q')"
" AND type='e'"
" AND tagid IS NOT NULL"
" ORDER BY objid DESC LIMIT 1",
zETime);
}
}
return rid;
}
/*
** COMMAND: wiki*
**
** Usage: %fossil wiki (export|create|commit|list) WikiName
**
** Run various subcommands to work with wiki entries or tech notes.
**
** %fossil wiki export PAGENAME ?FILE?
** %fossil wiki export ?FILE? -t|--technote DATETIME|TECHNOTE-ID
**
** Sends the latest version of either a wiki page or of a tech note
** to the given file or standard output.
** If PAGENAME is provided, the wiki page will be output. For
** a tech note either DATETIME or TECHNOTE-ID must be specified. If
** DATETIME is used, the most recently modified tech note with that
** DATETIME will be sent.
**
** %fossil wiki (create|commit) PAGENAME ?FILE? ?OPTIONS?
**
** Create a new or commit changes to an existing wiki page or
** technote from FILE or from standard input. PAGENAME is the
** name of the wiki entry or the timeline comment of the
** technote.
**
** Options:
** -M|--mimetype TEXT-FORMAT The mime type of the update.
** Defaults to the type used by
** the previous version of the
** page, or text/x-fossil-wiki.
** Valid values are: text/x-fossil-wiki,
** text/markdown and text/plain. fossil,
** markdown or plain can be specified as
** synonyms of these values.
** -t|--technote DATETIME Specifies the timestamp of
** the technote to be created or
** updated. When updating a tech note
** the most recently modified tech note
** with the specified timestamp will be
** updated.
** -t|--technote TECHNOTE-ID Specifies the technote to be
** updated by its technote id.
** --technote-tags TAGS The set of tags for a technote.
** --technote-bgcolor COLOR The color used for the technote
** on the timeline.
**
** %fossil wiki list ?OPTIONS?
** %fossil wiki ls ?OPTIONS?
**
** Lists all wiki entries, one per line, ordered
** case-insensitively by name.
**
** Options:
** -t|--technote Technotes will be listed instead of
** pages. The technotes will be in order
** of timestamp with the most recent
** first.
** -s|--show-technote-ids The id of the tech note will be listed
** along side the timestamp. The tech note
** id will be the first word on each line.
** This option only applies if the
** --technote option is also specified.
**
*/
void wiki_cmd(void){
int n;
db_find_and_open_repository(0, 0);
if( g.argc<3 ){
goto wiki_cmd_usage;
|
| ︙ | ︙ | |||
1212 1213 1214 1215 1216 1217 1218 |
}
if( zBody==0 ){
fossil_fatal("wiki page [%s] not found",zPageName);
}
zFile = (g.argc==4) ? "-" : g.argv[4];
}else{
if( (g.argc!=3) && (g.argc!=4) ){
| | < < < | | > > | | | | | | | < < < < | | > > > | > > > > > > | > | > > > > > > > > < > | | | < | > | | < < | | | > > > > > > | > > > > | > > > > > > > > > > > > > > > > > > > > > > > > | 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 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 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 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 |
}
if( zBody==0 ){
fossil_fatal("wiki page [%s] not found",zPageName);
}
zFile = (g.argc==4) ? "-" : g.argv[4];
}else{
if( (g.argc!=3) && (g.argc!=4) ){
usage("export ?FILE? --technote DATETIME|TECHNOTE-ID");
}
rid = wiki_technote_to_rid(zETime);
if ( rid==-1 ){
fossil_fatal("ambiguous tech note id: %s", zETime);
}
if( (pWiki = manifest_get(rid, CFTYPE_EVENT, 0))!=0 ){
zBody = pWiki->zWiki;
}
if( zBody==0 ){
fossil_fatal("technote [%s] not found",zETime);
}
zFile = (g.argc==3) ? "-" : g.argv[3];
}
for(i=strlen(zBody); i>0 && fossil_isspace(zBody[i-1]); i--){}
zBody[i] = 0;
blob_init(&body, zBody, -1);
blob_append(&body, "\n", 1);
blob_write_to_file(&body, zFile);
blob_reset(&body);
manifest_destroy(pWiki);
return;
}else if( strncmp(g.argv[2],"commit",n)==0
|| strncmp(g.argv[2],"create",n)==0 ){
const char *zPageName; /* page name */
Blob content; /* Input content */
int rid = 0;
Manifest *pWiki = 0; /* Parsed wiki page content */
const char *zMimeType = find_option("mimetype", "M", 1);
const char *zETime = find_option("technote", "t", 1);
const char *zTags = find_option("technote-tags", NULL, 1);
const char *zClr = find_option("technote-bgcolor", NULL, 1);
if( g.argc!=4 && g.argc!=5 ){
usage("commit|create PAGENAME ?FILE? [--mimetype TEXT-FORMAT]"
" [--technote DATETIME] [--technote-tags TAGS]"
" [--technote-bgcolor COLOR]");
}
zPageName = g.argv[3];
if( g.argc==4 ){
blob_read_from_channel(&content, stdin, -1);
}else{
blob_read_from_file(&content, g.argv[4]);
}
if( !zMimeType || !*zMimeType ){
/* Try to deduce the mime type based on the prior version. */
if ( !zETime ){
rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x"
" WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
" ORDER BY x.mtime DESC LIMIT 1",
zPageName
);
if( rid>0 && (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0
&& (pWiki->zMimetype && *pWiki->zMimetype) ){
zMimeType = pWiki->zMimetype;
}
}else{
rid = wiki_technote_to_rid(zETime);
if( rid>0 && (pWiki = manifest_get(rid, CFTYPE_EVENT, 0))!=0
&& (pWiki->zMimetype && *pWiki->zMimetype) ){
zMimeType = pWiki->zMimetype;
}
}
}else{
zMimeType = wiki_filter_mimetypes(zMimeType);
}
if( g.argv[2][1]=='r' && rid>0 ){
if ( !zETime ){
fossil_fatal("wiki page %s already exists", zPageName);
}else{
/* Creating a tech note with same timestamp is permitted
and should create a new tech note */
rid = 0;
}
}else if( g.argv[2][1]=='o' && rid == 0 ){
if ( !zETime ){
fossil_fatal("no such wiki page: %s", zPageName);
}else{
fossil_fatal("no such tech note: %s", zETime);
}
}
if( !zETime ){
wiki_cmd_commit(zPageName, rid, &content, zMimeType, 1);
if( g.argv[2][1]=='r' ){
fossil_print("Created new wiki page %s.\n", zPageName);
}else{
fossil_print("Updated wiki page %s.\n", zPageName);
}
}else{
if( rid != -1 ){
char *zMETime; /* Normalized, mutable version of zETime */
zMETime = db_text(0, "SELECT coalesce(datetime(%Q),datetime('now'))",
zETime);
event_cmd_commit(zMETime, rid, &content, zMimeType, zPageName,
zTags, zClr);
if( g.argv[2][1]=='r' ){
fossil_print("Created new tech note %s.\n", zMETime);
}else{
fossil_print("Updated tech note %s.\n", zMETime);
}
free(zMETime);
}else{
fossil_fatal("ambiguous tech note id: %s", zETime);
}
}
manifest_destroy(pWiki);
blob_reset(&content);
}else if( strncmp(g.argv[2],"delete",n)==0 ){
if( g.argc!=5 ){
usage("delete PAGENAME");
}
fossil_fatal("delete not yet implemented.");
}else if(( strncmp(g.argv[2],"list",n)==0 )
|| ( strncmp(g.argv[2],"ls",n)==0 )){
Stmt q;
int showIds = 0;
if ( !find_option("technote","t",0) ){
db_prepare(&q,
"SELECT substr(tagname, 6) FROM tag WHERE tagname GLOB 'wiki-*'"
" ORDER BY lower(tagname) /*sort*/"
);
}else{
showIds = find_option("show-technote-ids","s",0)!=0;
db_prepare(&q,
"SELECT datetime(e.mtime), substr(t.tagname,7)"
" FROM event e, tag t"
" WHERE e.type='e'"
" AND e.tagid IS NOT NULL"
" AND t.tagid=e.tagid"
" ORDER BY e.mtime DESC /*sort*/"
);
}
while( db_step(&q)==SQLITE_ROW ){
const char *zName = db_column_text(&q, 0);
if( showIds ){
const char *zUuid = db_column_text(&q, 1);
fossil_print("%s ",zUuid);
}
fossil_print( "%s\n",zName);
}
db_finalize(&q);
}else{
goto wiki_cmd_usage;
}
return;
wiki_cmd_usage:
usage("export|create|commit|list ...");
}
/*
** COMMAND: test-markdown-render
**
** Usage: %fossil test-markdown-render FILE
**
** Render markdown wiki from FILE to stdout.
**
*/
void test_markdown_render(void){
Blob in, out;
db_find_and_open_repository(0,0);
verify_all_options();
if( g.argc!=3 ) usage("FILE");
blob_zero(&out);
blob_read_from_file(&in, g.argv[2]);
markdown_to_html(&in, 0, &out);
blob_write_to_file(&out, "-");
}
|
Changes to src/wikiformat.c.
| ︙ | ︙ | |||
1717 1718 1719 1720 1721 1722 1723 | wiki_convert(&in, 0, flags); blob_reset(&in); } /* ** COMMAND: test-wiki-render ** | | | 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 | wiki_convert(&in, 0, flags); blob_reset(&in); } /* ** COMMAND: test-wiki-render ** ** Usage: %fossil test-wiki-render FILE [OPTIONS] ** ** Options: ** --buttons Set the WIKI_BUTTONS flag ** --htmlonly Set the WIKI_HTMLONLY flag ** --linksonly Set the WIKI_LINKSONLY flag ** --nobadlinks Set the WIKI_NOBADLINKS flag ** --inline Set the WIKI_INLINE flag |
| ︙ | ︙ |
Changes to src/winhttp.c.
| ︙ | ︙ | |||
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
** for windows. It also implements a Windows Service which allows the HTTP
** server to be run without any user logged on.
*/
#include "config.h"
#ifdef _WIN32
/* This code is for win32 only */
#include <windows.h>
#include "winhttp.h"
/*
** The HttpRequest structure holds information about each incoming
** HTTP request.
*/
typedef struct HttpRequest HttpRequest;
struct HttpRequest {
int id; /* ID counter */
SOCKET s; /* Socket on which to receive data */
SOCKADDR_IN addr; /* Address from which data is coming */
int flags; /* Flags passed to win32_http_server() */
| > | | 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 |
** for windows. It also implements a Windows Service which allows the HTTP
** server to be run without any user logged on.
*/
#include "config.h"
#ifdef _WIN32
/* This code is for win32 only */
#include <windows.h>
#include <process.h>
#include "winhttp.h"
/*
** The HttpRequest structure holds information about each incoming
** HTTP request.
*/
typedef struct HttpRequest HttpRequest;
struct HttpRequest {
int id; /* ID counter */
SOCKET s; /* Socket on which to receive data */
SOCKADDR_IN addr; /* Address from which data is coming */
int flags; /* Flags passed to win32_http_server() */
const char *zOptions; /* --baseurl, --notfound and/or --localauth options */
};
/*
** Prefix for a temporary file.
*/
static char *zTempPrefix;
|
| ︙ | ︙ | |||
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 |
** Start a listening socket and process incoming HTTP requests on
** that socket.
*/
void win32_http_server(
int mnPort, int mxPort, /* Range of allowed TCP port numbers */
const char *zBrowser, /* Command to launch browser. (Or NULL) */
const char *zStopper, /* Stop server when this file is exists (Or NULL) */
const char *zNotFound, /* The --notfound option, or NULL */
const char *zFileGlob, /* The --fileglob option, or NULL */
const char *zIpAddr, /* Bind to this IP address, if not NULL */
int flags /* One or more HTTP_SERVER_ flags */
){
WSADATA wd;
SOCKET s = INVALID_SOCKET;
SOCKADDR_IN addr;
int idCnt = 0;
int iPort = mnPort;
Blob options;
wchar_t zTmpPath[MAX_PATH];
if( zStopper ) file_delete(zStopper);
blob_zero(&options);
if( zNotFound ){
blob_appendf(&options, " --notfound %s", zNotFound);
}
if( zFileGlob ){
blob_appendf(&options, " --files-urlenc %T", zFileGlob);
}
if( g.useLocalauth ){
| > > > > | 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 |
** Start a listening socket and process incoming HTTP requests on
** that socket.
*/
void win32_http_server(
int mnPort, int mxPort, /* Range of allowed TCP port numbers */
const char *zBrowser, /* Command to launch browser. (Or NULL) */
const char *zStopper, /* Stop server when this file is exists (Or NULL) */
const char *zBaseUrl, /* The --baseurl option, or NULL */
const char *zNotFound, /* The --notfound option, or NULL */
const char *zFileGlob, /* The --fileglob option, or NULL */
const char *zIpAddr, /* Bind to this IP address, if not NULL */
int flags /* One or more HTTP_SERVER_ flags */
){
WSADATA wd;
SOCKET s = INVALID_SOCKET;
SOCKADDR_IN addr;
int idCnt = 0;
int iPort = mnPort;
Blob options;
wchar_t zTmpPath[MAX_PATH];
if( zStopper ) file_delete(zStopper);
blob_zero(&options);
if( zBaseUrl ){
blob_appendf(&options, " --baseurl %s", zBaseUrl);
}
if( zNotFound ){
blob_appendf(&options, " --notfound %s", zNotFound);
}
if( zFileGlob ){
blob_appendf(&options, " --files-urlenc %T", zFileGlob);
}
if( g.useLocalauth ){
|
| ︙ | ︙ | |||
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
/*
** The HttpService structure is used to pass information to the service main
** function and to the service control handler function.
*/
typedef struct HttpService HttpService;
struct HttpService {
int port; /* Port on which the http server should run */
const char *zNotFound; /* The --notfound option, or NULL */
const char *zFileGlob; /* The --files option, or NULL */
int flags; /* One or more HTTP_SERVER_ flags */
int isRunningAsService; /* Are we running as a service ? */
const wchar_t *zServiceName;/* Name of the service */
SOCKET s; /* Socket on which the http server listens */
};
/*
** Variables used for running as windows service.
*/
| > | | 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 |
/*
** The HttpService structure is used to pass information to the service main
** function and to the service control handler function.
*/
typedef struct HttpService HttpService;
struct HttpService {
int port; /* Port on which the http server should run */
const char *zBaseUrl; /* The --baseurl option, or NULL */
const char *zNotFound; /* The --notfound option, or NULL */
const char *zFileGlob; /* The --files option, or NULL */
int flags; /* One or more HTTP_SERVER_ flags */
int isRunningAsService; /* Are we running as a service ? */
const wchar_t *zServiceName;/* Name of the service */
SOCKET s; /* Socket on which the http server listens */
};
/*
** Variables used for running as windows service.
*/
static HttpService hsData = {8080, NULL, NULL, NULL, 0, 0, NULL, INVALID_SOCKET};
static SERVICE_STATUS ssStatus;
static SERVICE_STATUS_HANDLE sshStatusHandle;
/*
** Get message string of the last system error. Return a pointer to the
** message string. Call fossil_unicode_free() to deallocate any memory used
** to store the message string when done.
|
| ︙ | ︙ | |||
515 516 517 518 519 520 521 | /* Set service specific data and report that the service is starting. */ ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; ssStatus.dwServiceSpecificExitCode = 0; win32_report_service_status(SERVICE_START_PENDING, NO_ERROR, 3000); /* Execute the http server */ win32_http_server(hsData.port, hsData.port, | | | | 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 |
/* Set service specific data and report that the service is starting. */
ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
ssStatus.dwServiceSpecificExitCode = 0;
win32_report_service_status(SERVICE_START_PENDING, NO_ERROR, 3000);
/* Execute the http server */
win32_http_server(hsData.port, hsData.port,
NULL, NULL, hsData.zBaseUrl, hsData.zNotFound,
hsData.zFileGlob, 0, hsData.flags);
/* Service has stopped now. */
win32_report_service_status(SERVICE_STOPPED, NO_ERROR, 0);
return;
}
/*
|
| ︙ | ︙ | |||
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 |
** Try to start the http server as a windows service. If we are running in
** a interactive console session, this routine fails and returns a non zero
** integer value. When running as service, this routine does not return until
** the service is stopped. In this case, the return value is zero.
*/
int win32_http_service(
int nPort, /* TCP port number */
const char *zNotFound, /* The --notfound option, or NULL */
const char *zFileGlob, /* The --files option, or NULL */
int flags /* One or more HTTP_SERVER_ flags */
){
/* Define the service table. */
SERVICE_TABLE_ENTRYW ServiceTable[] =
{{L"", (LPSERVICE_MAIN_FUNCTIONW)win32_http_service_main}, {NULL, NULL}};
/* Initialize the HttpService structure. */
hsData.port = nPort;
hsData.zNotFound = zNotFound;
hsData.zFileGlob = zFileGlob;
hsData.flags = flags;
/* Try to start the control dispatcher thread for the service. */
if( !StartServiceCtrlDispatcherW(ServiceTable) ){
if( GetLastError()==ERROR_FAILED_SERVICE_CONTROLLER_CONNECT ){
return 1;
}else{
fossil_fatal("error from StartServiceCtrlDispatcher()");
}
}
return 0;
}
/* dupe ifdef needed for mkindex
** COMMAND: winsrv*
| > > > | | | 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 |
** Try to start the http server as a windows service. If we are running in
** a interactive console session, this routine fails and returns a non zero
** integer value. When running as service, this routine does not return until
** the service is stopped. In this case, the return value is zero.
*/
int win32_http_service(
int nPort, /* TCP port number */
const char *zBaseUrl, /* The --baseurl option, or NULL */
const char *zNotFound, /* The --notfound option, or NULL */
const char *zFileGlob, /* The --files option, or NULL */
int flags /* One or more HTTP_SERVER_ flags */
){
/* Define the service table. */
SERVICE_TABLE_ENTRYW ServiceTable[] =
{{L"", (LPSERVICE_MAIN_FUNCTIONW)win32_http_service_main}, {NULL, NULL}};
/* Initialize the HttpService structure. */
hsData.port = nPort;
hsData.zBaseUrl = zBaseUrl;
hsData.zNotFound = zNotFound;
hsData.zFileGlob = zFileGlob;
hsData.flags = flags;
/* Try to start the control dispatcher thread for the service. */
if( !StartServiceCtrlDispatcherW(ServiceTable) ){
if( GetLastError()==ERROR_FAILED_SERVICE_CONTROLLER_CONNECT ){
return 1;
}else{
fossil_fatal("error from StartServiceCtrlDispatcher()");
}
}
return 0;
}
/* dupe ifdef needed for mkindex
** COMMAND: winsrv*
**
** Usage: %fossil winsrv METHOD ?SERVICE-NAME? ?OPTIONS?
**
** Where METHOD is one of: create delete show start stop.
**
** The winsrv command manages Fossil as a Windows service. This allows
** (for example) Fossil to be running in the background when no user
** is logged in.
**
** In the following description of the methods, "Fossil-DSCM" will be
** used as the default SERVICE-NAME:
**
** %fossil winsrv create ?SERVICE-NAME? ?OPTIONS?
**
** Creates a service. Available options include:
**
** -D|--display DISPLAY-NAME
**
** Sets the display name of the service. This name is shown
** by graphical interface programs. By default, the display name
|
| ︙ | ︙ | |||
614 615 616 617 618 619 620 621 622 623 624 625 626 627 | ** -W|--password PASSWORD ** ** Password for the user account. ** ** The following options are more or less the same as for the "server" ** command and influence the behaviour of the http server: ** ** -P|--port TCPPORT ** ** Specifies the TCP port (default port is 8080) on which the ** server should listen. ** ** -R|--repository REPOSITORY ** | > > > > | 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 | ** -W|--password PASSWORD ** ** Password for the user account. ** ** The following options are more or less the same as for the "server" ** command and influence the behaviour of the http server: ** ** --baseurl URL ** ** Use URL as the base (useful for reverse proxies) ** ** -P|--port TCPPORT ** ** Specifies the TCP port (default port is 8080) on which the ** server should listen. ** ** -R|--repository REPOSITORY ** |
| ︙ | ︙ | |||
654 655 656 657 658 659 660 | ** If REPOSITORY is directory, URL "/" lists all repositories. ** ** --scgi ** ** Create an SCGI server instead of an HTTP server ** ** | | | | | | 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 | ** If REPOSITORY is directory, URL "/" lists all repositories. ** ** --scgi ** ** Create an SCGI server instead of an HTTP server ** ** ** %fossil winsrv delete ?SERVICE-NAME? ** ** Deletes a service. If the service is currently running, it will be ** stopped first and then deleted. ** ** ** %fossil winsrv show ?SERVICE-NAME? ** ** Shows how the service is configured and its current state. ** ** ** %fossil winsrv start ?SERVICE-NAME? ** ** Start the service. ** ** ** %fossil winsrv stop ?SERVICE-NAME? ** ** Stop the service. ** ** ** NOTE: This command is available on Windows operating systems only and ** requires administrative rights on the machine executed. ** |
| ︙ | ︙ | |||
696 697 698 699 700 701 702 703 704 705 706 707 708 709 |
if( strncmp(zMethod, "create", n)==0 ){
SC_HANDLE hScm;
SC_HANDLE hSvc;
SERVICE_DESCRIPTIONW
svcDescr = {L"Fossil - Distributed Software Configuration Management"};
DWORD dwStartType = SERVICE_DEMAND_START;
const char *zDisplay = find_option("display", "D", 1);
const char *zStart = find_option("start", "S", 1);
const char *zUsername = find_option("username", "U", 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);
| > | 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 |
if( strncmp(zMethod, "create", n)==0 ){
SC_HANDLE hScm;
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", "U", 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);
|
| ︙ | ︙ | |||
751 752 753 754 755 756 757 758 759 760 761 762 763 764 |
}else{
db_open_repository(zRepository);
}
db_close(0);
/* Build the fully-qualified path to the service binary file. */
blob_zero(&binPath);
blob_appendf(&binPath, "\"%s\" server", g.nameOfExe);
if( zPort ) blob_appendf(&binPath, " --port %s", zPort);
if( useSCGI ) blob_appendf(&binPath, " --scgi");
if( allowRepoList ) blob_appendf(&binPath, " --repolist");
if( zNotFound ) blob_appendf(&binPath, " --notfound \"%s\"", zNotFound);
if( zFileGlob ) blob_appendf(&binPath, " --files-urlenc %T", zFileGlob);
if( zLocalAuth ) blob_append(&binPath, " --localauth", -1);
blob_appendf(&binPath, " \"%s\"", g.zRepositoryName);
| > | 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 |
}else{
db_open_repository(zRepository);
}
db_close(0);
/* Build the fully-qualified path to the service binary file. */
blob_zero(&binPath);
blob_appendf(&binPath, "\"%s\" server", g.nameOfExe);
if( zAltBase ) blob_appendf(&binPath, " --baseurl %s", zAltBase);
if( zPort ) blob_appendf(&binPath, " --port %s", zPort);
if( useSCGI ) blob_appendf(&binPath, " --scgi");
if( allowRepoList ) blob_appendf(&binPath, " --repolist");
if( zNotFound ) blob_appendf(&binPath, " --notfound \"%s\"", zNotFound);
if( zFileGlob ) blob_appendf(&binPath, " --files-urlenc %T", zFileGlob);
if( zLocalAuth ) blob_append(&binPath, " --localauth", -1);
blob_appendf(&binPath, " \"%s\"", g.zRepositoryName);
|
| ︙ | ︙ |
Changes to src/xfersetup.c.
| ︙ | ︙ | |||
59 60 61 62 63 64 65 |
}else{
syncFlags = SYNC_PUSH | SYNC_PULL;
zButton = "Synchronize";
zWarning = mprintf("WARNING: Pushing to \"%s\" is enabled.",
g.url.canonical);
}
@ <p>Press the <strong>%h(zButton)</strong> button below to
| | | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
}else{
syncFlags = SYNC_PUSH | SYNC_PULL;
zButton = "Synchronize";
zWarning = mprintf("WARNING: Pushing to \"%s\" is enabled.",
g.url.canonical);
}
@ <p>Press the <strong>%h(zButton)</strong> button below to
@ synchronize with the <em>%h(g.url.canonical)</em> repository now.<br />
@ This may be useful when testing the various transfer scripts.</p>
@ <p>You can use the <code>http -async</code> command in your scripts, but
@ make sure the <code>th1-uri-regexp</code> setting is set first.</p>
if( zWarning ){
@
@ <big><b>%h(zWarning)</b></big>
free(zWarning);
|
| ︙ | ︙ |
Changes to src/zip.c.
| ︙ | ︙ | |||
307 308 309 310 311 312 313 | /* ** Given the RID for a manifest, construct a ZIP archive containing ** all files in the corresponding baseline. ** ** If RID is for an object that is not a real manifest, then the ** resulting ZIP archive contains a single file which is the RID | | | > > > > > > | 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 |
/*
** Given the RID for a manifest, construct a ZIP archive containing
** all files in the corresponding baseline.
**
** If RID is for an object that is not a real manifest, then the
** resulting ZIP archive contains a single file which is the RID
** object. The pInclude and pExclude parameters are ignored in this case.
**
** If the RID object does not exist in the repository, then
** pZip is zeroed.
**
** zDir is a "synthetic" subdirectory which all zipped files get
** added to as part of the zip file. It may be 0 or an empty string,
** in which case it is ignored. The intention is to create a zip which
** politely expands into a subdir instead of filling your current dir
** with source files. For example, pass a UUID or "ProjectName".
**
*/
void zip_of_checkin(
int rid, /* The RID of the checkin to construct the ZIP archive from */
Blob *pZip, /* Write the ZIP archive content into this blob */
const char *zDir, /* Top-level directory of the ZIP archive */
Glob *pInclude, /* Only include files that match this pattern */
Glob *pExclude /* Exclude files that match this pattern */
){
Blob mfile, hash, file;
Manifest *pManifest;
ManifestFile *pFile;
Blob filename;
int nPrefix;
content_get(rid, &mfile);
|
| ︙ | ︙ | |||
342 343 344 345 346 347 348 |
if( zDir && zDir[0] ){
blob_appendf(&filename, "%s/", zDir);
}
nPrefix = blob_size(&filename);
pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0);
if( pManifest ){
| | > > > > > > > > > > > > > > > > > | | | | | | > > > | | 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 |
if( zDir && zDir[0] ){
blob_appendf(&filename, "%s/", zDir);
}
nPrefix = blob_size(&filename);
pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0);
if( pManifest ){
int flg, eflg = 0;
char *zName;
zip_set_timedate(pManifest->rDate);
flg = db_get_manifest_setting();
if( flg ){
/* eflg is the effective flags, taking include/exclude into account */
if( (pInclude==0 || glob_match(pInclude, "manifest"))
&& !glob_match(pExclude, "manifest")
&& (flg & MFESTFLG_RAW) ){
eflg |= MFESTFLG_RAW;
}
if( (pInclude==0 || glob_match(pInclude, "manifest.uuid"))
&& !glob_match(pExclude, "manifest.uuid")
&& (flg & MFESTFLG_UUID) ){
eflg |= MFESTFLG_UUID;
}
if( (pInclude==0 || glob_match(pInclude, "manifest.tags"))
&& !glob_match(pExclude, "manifest.tags")
&& (flg & MFESTFLG_TAGS) ){
eflg |= MFESTFLG_TAGS;
}
if( eflg & (MFESTFLG_RAW|MFESTFLG_UUID) ){
if( eflg & MFESTFLG_RAW ){
blob_append(&filename, "manifest", -1);
zName = blob_str(&filename);
zip_add_folders(zName);
}
if( eflg & MFESTFLG_UUID ){
sha1sum_blob(&mfile, &hash);
}
if( eflg & MFESTFLG_RAW ){
sterilize_manifest(&mfile);
zip_add_file(zName, &mfile, 0);
}
}
blob_reset(&mfile);
if( eflg & MFESTFLG_UUID ){
blob_append(&hash, "\n", 1);
blob_resize(&filename, nPrefix);
blob_append(&filename, "manifest.uuid", -1);
zName = blob_str(&filename);
zip_add_folders(zName);
zip_add_file(zName, &hash, 0);
blob_reset(&hash);
}
if( eflg & MFESTFLG_TAGS ){
Blob tagslist;
blob_zero(&tagslist);
get_checkin_taglist(rid, &tagslist);
blob_resize(&filename, nPrefix);
blob_append(&filename, "manifest.tags", -1);
zName = blob_str(&filename);
zip_add_folders(zName);
zip_add_file(zName, &tagslist, 0);
blob_reset(&tagslist);
}
}
manifest_file_rewind(pManifest);
while( (pFile = manifest_file_next(pManifest,0))!=0 ){
int fid;
if( pInclude!=0 && !glob_match(pInclude, pFile->zName) ) continue;
if( glob_match(pExclude, pFile->zName) ) continue;
fid = uuid_to_rid(pFile->zUuid, 0);
if( fid ){
content_get(fid, &file);
blob_resize(&filename, nPrefix);
blob_append(&filename, pFile->zName, -1);
zName = blob_str(&filename);
zip_add_folders(zName);
zip_add_file(zName, &file, manifest_file_mperm(pFile));
|
| ︙ | ︙ | |||
407 408 409 410 411 412 413 | blob_reset(&filename); zip_close(pZip); } /* ** COMMAND: zip* ** | | | | > > > > > > > > > > > | > > > > > > > > | > > | | | | | > | | < > | > > > > > > > > > > > > > > > > | 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 |
blob_reset(&filename);
zip_close(pZip);
}
/*
** COMMAND: zip*
**
** Usage: %fossil zip VERSION OUTPUTFILE [OPTIONS]
**
** Generate a ZIP archive for a check-in. If the --name option is
** used, its argument becomes the name of the top-level directory in the
** resulting ZIP archive. If --name is omitted, the top-level directory
** named is derived from the project name, the check-in date and time, and
** the artifact ID of the check-in.
**
** The GLOBLIST argument to --exclude and --include can be a comma-separated
** list of glob patterns, where each glob pattern may optionally be enclosed
** in "..." or '...' so that it may contain commas. If a file matches both
** --include and --exclude then it is excluded.
**
** Options:
** -X|--exclude GLOBLIST Comma-separated list of GLOBs of files to exclude
** --include GLOBLIST Comma-separated list of GLOBs of files to include
** --name DIRECTORYNAME The name of the top-level directory in the archive
** -R REPOSITORY Specify a Fossil repository
*/
void zip_cmd(void){
int rid;
Blob zip;
const char *zName;
Glob *pInclude = 0;
Glob *pExclude = 0;
const char *zInclude;
const char *zExclude;
zName = find_option("name", 0, 1);
zExclude = find_option("exclude", "X", 1);
if( zExclude ) pExclude = glob_create(zExclude);
zInclude = find_option("include", 0, 1);
if( zInclude ) pInclude = glob_create(zInclude);
db_find_and_open_repository(0, 0);
/* We should be done with options.. */
verify_all_options();
if( g.argc!=4 ){
usage("VERSION OUTPUTFILE");
}
rid = name_to_typed_rid(g.argv[2],"ci");
if( zName==0 ){
zName = db_text("default-name",
"SELECT replace(%Q,' ','_') "
" || strftime('_%%Y-%%m-%%d_%%H%%M%%S_', event.mtime) "
" || substr(blob.uuid, 1, 10)"
" FROM event, blob"
" WHERE event.objid=%d"
" AND blob.rid=%d",
db_get("project-name", "unnamed"), rid, rid
);
}
zip_of_checkin(rid, &zip, zName, pInclude, pExclude);
blob_write_to_file(&zip, g.argv[3]);
glob_free(pInclude);
glob_free(pExclude);
}
/*
** WEBPAGE: zip
** URL: /zip
**
** Generate a ZIP archive for a checkin specified by the uuid= query parameter.
** Return that ZIP archive as the HTTP reply content.
**
** Query parameters:
**
** name=NAME[.tar.gz] The base name of the output file. The default
** value is a configuration parameter in the project
** settings. A prefix of the name, omitting the extension,
** is used as the top-most directory name.
**
** uuid=TAG The check-in that is turned into a tarball.
** Defaults to "trunk".
**
** in=PATTERN Only include files that match the comma-separate
** list of GLOB patterns in PATTERN, as with ex=
**
** ex=PATTERN Omit any file that match PATTERN. PATTERN is a
** comma-separated list of GLOB patterns, where each
** pattern can optionally be quoted using ".." or '..'.
** Any file matching both ex= and in= is excluded.
*/
void baseline_zip_page(void){
int rid;
char *zName, *zRid;
int nName, nRid;
Blob zip;
char *zKey;
const char *zInclude; /* The in= query parameter */
const char *zExclude; /* The ex= query parameter */
Blob cacheKey; /* The key to cache */
Glob *pInclude = 0; /* The compiled in= glob pattern */
Glob *pExclude = 0; /* The compiled ex= glob pattern */
login_check_credentials();
if( !g.perm.Zip ){ login_needed(g.anon.Zip); return; }
load_control();
zName = mprintf("%s", PD("name",""));
nName = strlen(zName);
zRid = mprintf("%s", PD("uuid","trunk"));
nRid = strlen(zRid);
zInclude = P("in");
if( zInclude ) pInclude = glob_create(zInclude);
zExclude = P("ex");
if( zExclude ) pExclude = glob_create(zExclude);
if( nName>4 && fossil_strcmp(&zName[nName-4], ".zip")==0 ){
/* Special case: Remove the ".zip" suffix. */
nName -= 4;
zName[nName] = 0;
}else{
/* If the file suffix is not ".zip" then just remove the
** suffix up to and including the last "." */
|
| ︙ | ︙ | |||
507 508 509 510 511 512 513 |
@ of check-in <b>%h(zRid)</b>:
@ <input type="submit" value="Download" />
@ </form>
style_footer();
return;
}
if( nRid==0 && nName>10 ) zName[10] = 0;
| | > > > > > > > > | > | > | 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 |
@ of check-in <b>%h(zRid)</b>:
@ <input type="submit" value="Download" />
@ </form>
style_footer();
return;
}
if( nRid==0 && nName>10 ) zName[10] = 0;
/* Compute a unique key for the cache entry based on query parameters */
blob_init(&cacheKey, 0, 0);
blob_appendf(&cacheKey, "/zip/%z", rid_to_uuid(rid));
if( zInclude ) blob_appendf(&cacheKey, ",in=%Q", zInclude);
if( zExclude ) blob_appendf(&cacheKey, ",ex=%Q", zExclude);
blob_appendf(&cacheKey, "/%q", zName);
zKey = blob_str(&cacheKey);
blob_zero(&zip);
if( cache_read(&zip, zKey)==0 ){
zip_of_checkin(rid, &zip, zName, pInclude, pExclude);
cache_write(&zip, zKey);
}
fossil_free( zName );
fossil_free( zRid );
blob_reset(&cacheKey);
glob_free(pInclude);
glob_free(pExclude);
cgi_set_content(&zip);
cgi_set_content_type("application/zip");
}
|
Changes to test/merge6.test.
| ︙ | ︙ | |||
60 61 62 63 64 65 66 |
fossil merge branch_for_f3_f4
fossil commit -m "new trunk files f2, f3, and f4 via merge"
fossil ls
test merge_multi-4 {[normalize_result] eq {f1
f2
f3
| | | 60 61 62 63 64 65 66 67 68 69 70 71 |
fossil merge branch_for_f3_f4
fossil commit -m "new trunk files f2, f3, and f4 via merge"
fossil ls
test merge_multi-4 {[normalize_result] eq {f1
f2
f3
f4}}
###############################################################################
test_cleanup
|
Added test/merge_exe.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
#
# Copyright (c) 2016 D. Richard Hipp
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the Simplified BSD License (also
# known as the "2-Clause License" or "FreeBSD License".)
#
# This program is distributed in the hope that it will be useful,
# but without any warranty; without even the implied warranty of
# merchantability or fitness for a particular purpose.
#
# Author contact information:
# drh@hwaci.com
# http://www.hwaci.com/drh/
#
############################################################################
#
# Testing changes to a file's execute bit caused by a merge
#
if {$tcl_platform(platform) eq "unix"} {
proc setx {fn isexe} {
file attributes $fn -permissions [expr {$isexe ? "+" : "-"}]x
}
proc test_exe {fn expected} {
test merge_exe-$fn {[file executable $fn]==$expected}
}
} else {
# WARNING: This is a hack for setting and testing a file's execute bit
# on Windows. Never operate directly on Fossil database files like this
# unless you really need to and really know what you're doing.
proc query {sql} {
return [exec $::fossilexe sqlite3 --no-repository _FOSSIL_ $sql]
}
proc setx {fn isexe} {
set isexe [expr {bool($isexe)}]
query "UPDATE vfile SET isexe=$isexe WHERE pathname='$fn'"
}
proc test_exe {fn expected} {
set result [query "SELECT isexe FROM vfile WHERE pathname='$fn'"]
test merge_exe-$fn {$result==$expected}
}
}
test_setup
write_file f1 "line"
write_file f2 "line"
write_file f3 "line"
write_file f4 "line"
fossil addremove
setx f3 1
setx f4 1
fossil commit -m "add files"
write_file f0 "f0"
fossil add f0
setx f0 1
fossil mv --hard f1 f1n
setx f1n 1
write_file f2 "line\nline2"
setx f2 1
write_file f3 "line\nline2"
setx f3 0
setx f4 0
fossil commit -b b -m "changes"
fossil update trunk
write_file f3 "line3\nline"
fossil commit -m "edit f3"
fossil merge b
test_status_list merge_exe-mrg $RESULT {
EXECUTABLE f1
EXECUTABLE f2
UNEXEC f3
UNEXEC f4
UPDATE f2
MERGE f3
RENAME f1 -> f1n
ADDED f0
}
foreach {fn isexe} {f0 1 f1n 1 f2 1 f3 0 f4 0} {
test_exe $fn $isexe
}
###############################################################################
test_cleanup
|
Changes to test/merge_renames.test.
1 2 3 4 5 6 7 8 9 10 11 | # # Tests for merging with renames # # require_no_open_checkout ###################################### # Test 1 # # Reported: Ticket [554f44ee74e3d] # ###################################### | > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#
# Tests for merging with renames
#
#
proc commit_id {version} {
regexp -line {^artifact:\s+(\S+)} [fossil whatis $version] - id
return $id
}
require_no_open_checkout
######################################
# Test 1 #
# Reported: Ticket [554f44ee74e3d] #
######################################
|
| ︙ | ︙ | |||
29 30 31 32 33 34 35 | write_file f1 "line5" fossil commit -m "c4" write_file f1 "line6" fossil commit -m "c4" fossil update pivot | | < < < < < < < < < < < < < | < < < | < < < < < < < < < < < < < < | < < < | < < < < < < < < < < < < < < | < < < > | > > > > > > > > > > > > > > | < > > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 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 |
write_file f1 "line5"
fossil commit -m "c4"
write_file f1 "line6"
fossil commit -m "c4"
fossil update pivot
fossil mv --hard f1 f2
fossil commit -b rename -m "c5"
fossil merge trunk
fossil commit -m "trunk merged"
fossil update pivot
write_file f3 "someline"
fossil add f3
fossil commit -b branch2 -m "newbranch"
fossil merge trunk
test_status_list merge_renames-1 $RESULT {UPDATE f1}
######################################
# Test 2 #
# Reported: Ticket [74413366fe5067] #
######################################
test_setup
write_file f1 "line"
fossil add f1
fossil commit -m "base file"
fossil tag add pivot current
write_file f2 "line2"
fossil add f2
fossil commit -m "newfile"
fossil mv --hard f2 f2new
fossil commit -m "rename"
fossil update pivot
write_file f1 "line3"
fossil commit -b branch -m "change"
fossil merge trunk
fossil commit -m "trunk merged"
fossil update trunk
fossil merge branch
test_status_list merge_renames-2 $RESULT {UPDATE f1}
######################################
# Test 3 #
# Reported: Ticket [30b28cf351] #
######################################
test_setup
write_file f1 "line"
fossil add f1
fossil commit -m "base file"
fossil tag add pivot current
write_file f2 "line2"
fossil add f2
fossil commit -m "newfile"
fossil mv --hard f2 f2new
fossil commit -m "rename"
fossil update pivot
write_file f1 "line3"
fossil commit -b branch -m "change"
fossil merge trunk
fossil commit -m "trunk merged"
fossil update trunk
fossil merge branch
test_status_list merge_renames-3 $RESULT {UPDATE f1}
######################################
# Test 4 #
# Reported: Ticket [67176c3aa4] #
######################################
test_setup
write_file f1 "f1"
fossil add f1
fossil commit -m "add f1"
write_file f1 "f1.1"
fossil commit --branch b -m "change f1"
fossil update trunk
fossil mv --hard f1 f2
fossil commit -m "f1 -> f2"
fossil merge b
test_status_list merge_renames-4-1 $RESULT {UPDATE f2}
test_file_contents merge_renames-4-2 f2 "f1.1"
######################################
# Test 5 #
# Handle Rename/Add via Merge #
######################################
test_setup
write_file f1 "old f1 line"
fossil add f1
fossil commit -m "base file"
write_file f3 "f3 line"
fossil add f3
fossil commit -m "branch file" -b branch_for_f3
fossil update trunk
fossil mv --hard f1 f2
write_file f1 "new f1 line"
fossil add f1
fossil commit -m "rename and add file with old name"
fossil update branch_for_f3
fossil merge trunk
test_status_list merge_renames-5-1 $RESULT {
RENAME f1 -> f2
ADDED f1
}
fossil commit -m "trunk merged, should have 3 files"
fossil ls
test merge_renames-5-2 {[normalize_result] eq {f1
f2
f3}}
#####################################
# Test 6 #
# Merging a branch multiple times #
#####################################
test_setup
write_file f1 "f1"
fossil add f1
fossil commit -m "add f1"
fossil mv --hard f1 f2
fossil commit -b b -m "f1 -> f2"
fossil update trunk
write_file f3 "f3"
write_file f4 "f4"
fossil add f3 f4
fossil ci -m "add f3, f4"
fossil mv --hard f3 f3-old
fossil mv --hard f4 f3
fossil mv --hard f3-old f4
fossil ci -m "swap f3 and f4"
write_file f1 "f1.1"
fossil commit -m "edit f1"
fossil update b
fossil merge trunk
fossil commit -m "merge trunk"
fossil update trunk
write_file f1 "f1.2"
write_file f3 "f3.1"
write_file f4 "f4.1"
fossil commit -m "edit f1, f4"
fossil update b
fossil merge trunk
test_status_list merge_renames-6-1 $RESULT {
UPDATE f2
UPDATE f3
UPDATE f4
}
test_file_contents merge_renames-6-2 f2 "f1.2"
test_file_contents merge_renames-6-3 f3 "f3.1"
test_file_contents merge_renames-6-4 f4 "f4.1"
########################################################################
# Test 7 #
# Merging with an uncommitted rename of a file that has been renamed #
# in the merged branch and adding a new file with the original name #
########################################################################
test_setup
write_file f1 "f1"
fossil add f1
fossil commit -m "add f1"
fossil mv --hard f1 f2
write_file f2 "f2"
fossil commit -b b -m "f1 -> f2, edit f2"
fossil update trunk
fossil mv --hard f1 f3
write_file f1 "f1.1"
fossil add f1
fossil merge b
test_status_list merge_renames-7-1 $RESULT {UPDATE f3}
test_file_contents merge_renames-7-2 f1 "f1.1"
test_file_contents merge_renames-7-3 f3 "f2"
######################################################
# Test 8 #
# Merging two branches that both add the same file #
######################################################
test_setup
write_file f1 "f1.1"
fossil add f1
fossil commit -b b1 -m "add f1"
fossil update trunk
write_file f1 "f1.2"
fossil add f1
fossil commit -b b2 -m "add f1"
fossil update trunk
fossil merge b1
fossil merge b2
test_status_list merge_renames-8-1 $RESULT {
WARNING: no common ancestor for f1
}
fossil revert
fossil merge --integrate b1
fossil merge b2
test_status_list merge_renames-8-2 $RESULT {
WARNING: no common ancestor for f1
}
#############################################
# Test 9 #
# Merging a delete/rename/add combination #
#############################################
test_setup
write_file f1 "f1"
write_file f2 "f2"
fossil add f1 f2
fossil commit -m "add files"
fossil rm --hard f2
fossil commit -b b -m "delete f2"
fossil mv --hard f1 f2
fossil commit -m "f1 -> f2"
write_file f1 "f1.1"
fossil add f1
fossil commit -m "add new f1"
fossil update trunk
fossil merge b
set expectedMerge {
DELETE f2
RENAME f1 -> f2
ADDED f1
}
test_status_list merge_renames-9-1 $RESULT $expectedMerge
fossil changes
test_status_list merge_renames-9-2 $RESULT "
MERGED_WITH [commit_id b]
ADDED_BY_MERGE f1
RENAMED f2
DELETED f2 (overwritten by rename)
"
test_file_contents merge_renames-9-3 f1 "f1.1"
test_file_contents merge_renames-9-4 f2 "f1"
# Undo and ensure a dry run merge results in no changes
fossil undo
test_status_list merge_renames-9-5 $RESULT {
UNDO f1
UNDO f2
}
fossil merge -n b
test_status_list merge_renames-9-6 $RESULT "
$expectedMerge
REMINDER: this was a dry run - no files were actually changed.
"
test merge_renames-9-7 {[fossil changes] eq ""}
###################################################################
# Test 10 #
# Merge swapped filenames, backout the swap, then merge changes #
###################################################################
test_setup
write_file f1 "f1"
write_file f2 "f2"
fossil add f1 f2
fossil commit -m "add files" ;# N
fossil mv --hard f1 f1-tmp
fossil mv --hard f2 f1
fossil mv --hard f1-tmp f2
fossil commit -b b -m "swap f1, f2" ;# P
fossil update trunk
fossil merge b
test_status_list merge_renames-10-1 $RESULT {
RENAME f1 -> f2
RENAME f2 -> f1
}
test_file_contents merge_renames-10-2 f1 "f2"
test_file_contents merge_renames-10-3 f2 "f1"
fossil commit -m "merge b"
fossil update b
write_file f1 f1.1
write_file f2 f2.1
fossil commit -m "edit" ;# M
fossil update trunk
fossil merge --backout trunk
test_status_list merge_renames-10-4 $RESULT {
RENAME f1 -> f2
RENAME f2 -> f1
}
test_file_contents merge_renames-10-5 f1 "f1"
test_file_contents merge_renames-10-6 f2 "f2"
test_status_list merge_renames-10-7 [fossil changes] "
RENAMED f1
RENAMED f2
BACKOUT [commit_id trunk]
"
fossil commit -m "swap back" ;# V
fossil merge b
test_status_list merge_renames-10-8 $RESULT {
UPDATE f1
UPDATE f2
}
test_file_contents merge_renames-10-9 f1 "f2.1"
test_file_contents merge_renames-10-10 f2 "f1.1"
############################################
# Test 11 #
# Specifying a baseline #
############################################
test_setup
write_file f1 "line"
fossil add f1
fossil commit -m "add f1"
write_file f1 "line\nline2"
fossil commit -b b -m "edit f2" --tag p1
fossil mv --hard f1 f2
fossil commit -m "f1 -> f2"
write_file f2 "line\nline2\nline3"
fossil commit -m "edit f2" --tag p2
write_file f2 "line\nline2\nline3\nline4"
fossil commit -m "edit f2"
fossil update trunk
fossil merge --baseline p1 b
test_status_list merge_renames-11-1 $RESULT {
MERGE f1
RENAME f1 -> f2
}
test_file_contents merge_renames-11-2 f2 "line\nline3\nline4"
fossil revert
fossil merge --baseline p2 b
test_status_list merge_renames-11-3 $RESULT {MERGE f1}
test_file_contents merge_renames-11-4 f1 "line\nline4"
#################################################################
# Test 12 #
# Merge involving a pivot that isn't a first-parent ancestor #
# of either the checked-out commit or the commit being merged #
#################################################################
test_setup
write_file f1 "f1\n"
fossil add f1
fossil commit -m "add f1" --tag n
fossil mv --hard f1 f1n
fossil commit -m "f1 -> f1n"
fossil mv --hard f1n f1v
write_file f1v "f1v\n"
fossil commit -b v -m "f1n -> f1v, edit f1v"
fossil update trunk
fossil mv --hard f1n f1m
fossil commit -b m -m "f1n -> f1m"
fossil update n
fossil mv --hard f1 f1p
write_file f1p "f1\np"
fossil commit -b p -m "f1 -> f1p, edit f1p"
fossil update m
fossil merge p
test_status_list merge_renames-12-1 $RESULT {UPDATE f1m}
test_file_contents merge_renames-12-2 f1m "f1\np"
fossil commit -m "merge p"
write_file f1m "f1\nm"
fossil commit -m "edit f1m"
fossil update v
fossil merge p
test_status_list merge_renames-12-3 $RESULT {MERGE f1v}
test_file_contents merge_renames-12-4 f1v "f1v\np"
fossil commit -m "merge p"
fossil merge m
test_status_list merge_renames-12-5 $RESULT {MERGE f1v}
test_file_contents merge_renames-12-6 f1v "f1v\nm"
fossil commit -m "merge m"
######################################
#
# Tests for troubles not specifically linked with renames but that I'd like to
# write:
# [c26c63eb1b] - 'merge --backout' does not handle conflicts properly
# [953031915f] - Lack of warning when overwriting extra files
# [4df5f38f1e] - Troubles merging a file delete with a file change
###############################################################################
test_cleanup
|
Added test/merge_warn.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
#
# Copyright (c) 2016 D. Richard Hipp
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the Simplified BSD License (also
# known as the "2-Clause License" or "FreeBSD License".)
#
# This program is distributed in the hope that it will be useful,
# but without any warranty; without even the implied warranty of
# merchantability or fitness for a particular purpose.
#
# Author contact information:
# drh@hwaci.com
# http://www.hwaci.com/drh/
#
############################################################################
#
# Testing "merge" command warnings
#
test_setup
write_file f1 "f1"
fossil add f1
fossil commit -m "add f1" --tag pivot
write_file f2 "f2"
fossil add f2
fossil commit -m "add f2"
fossil update pivot
fossil rm --hard f1
write_file f2 "f2.1"
write_file f3 "f3"
fossil add f2 f3
fossil commit -b b -m "delete f1, add f2 and f3" --tag mrg
write_file f4 "f4"
fossil add f4
fossil commit -m "add f4"
fossil update trunk
write_file f1 "f1.1"
write_file f3 "f3.1"
fossil merge --integrate mrg
test_status_list merge_warn-1 $RESULT {
WARNING: no common ancestor for f2
DELETE f1
WARNING: local edits lost for f1
ADDED f3 (overwrites an unmanaged file)
WARNING: 1 merge conflicts
WARNING: 1 unmanaged files were overwritten
}
test merge_warn-2 {
[string first "ignoring --integrate: mrg is not a leaf" $RESULT]>=0
}
###############################################################################
test_cleanup
|
Changes to test/mv-rm.test.
| ︙ | ︙ | |||
44 45 46 47 48 49 50 51 | file mkdir [file join $rootDir subdirB] write_file [file join $rootDir subdirB f9] "f9" file mkdir [file join $rootDir subdirC] write_file [file join $rootDir subdirC f10] "f10" write_file [file join $rootDir subdirC f11] "f11" | > | | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | file mkdir [file join $rootDir subdirB] write_file [file join $rootDir subdirB f9] "f9" file mkdir [file join $rootDir subdirC] write_file [file join $rootDir subdirC f10] "f10" write_file [file join $rootDir subdirC f11] "f11" write_file f12 "f12" fossil add f1 f2 f3 f4 f5 f6 f7 f8 subdirB/f9 subdirC/f10 subdirC/f11 f12 fossil commit -m "c1" ######################################## # Test 1: Soft Move Relative Directory # ######################################## file mkdir [file join $rootDir subdir1] |
| ︙ | ︙ | |||
378 379 380 381 382 383 384 385 386 387 388 389 |
}
fossil revert
test rm-hard-absolute-6 {
[normalize_result] eq "REVERT f8${undoMsg}"
}
cd $rootDir
###############################################################################
test_cleanup
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
}
fossil revert
test rm-hard-absolute-6 {
[normalize_result] eq "REVERT f8${undoMsg}"
}
cd $rootDir
#######################################
# Test 17: Move File to New Directory #
#######################################
fossil mv --hard f12 d2/f13
test mv-file-new-directory-1 {
[normalize_result] eq "RENAME f12 d2/f13\nMOVED_FILE ${rootDir}/f12"
}
test mv-file-new-directory-2 {[file size d2/f13] == 3}
test mv-file-new-directory-3 {[read_file d2/f13] eq "f12"}
fossil revert
test mv-file-new-directory-4 {
[normalize_result] eq "DELETE d2/f13\nREVERT f12${undoMsg}"
}
test mv-file-new-directory-5 {[file size f12] == 3}
test mv-file-new-directory-6 {[read_file f12] eq "f12"}
cd $rootDir
############################################
# Test 18: Move Directory to New Directory #
############################################
fossil mv --hard subdirC subdirD
test mv-file-new-directory-7 {
[normalize_result] eq "RENAME subdirC subdirD\nMOVED_FILE ${rootDir}/subdirC"
}
test mv-file-new-directory-8 {[file size subdirD/f10] == 3}
test mv-file-new-directory-9 {[read_file subdirD/f10] eq "f10"}
test mv-file-new-directory-10 {[file size subdirD/f11] == 3}
test mv-file-new-directory-11 {[read_file subdirD/f11] eq "f11"}
fossil revert
test mv-file-new-directory-12 {
[normalize_result] eq "REVERT subdirC/f10\nREVERT subdirC/f11${undoMsg}"
}
test mv-file-new-directory-13 {[file size subdirC/f10] == 3}
test mv-file-new-directory-14 {[read_file subdirC/f10] eq "f10"}
test mv-file-new-directory-15 {[file size subdirC/f11] == 3}
test mv-file-new-directory-16 {[read_file subdirC/f11] eq "f11"}
cd $rootDir
###############################################################################
test_cleanup
|
Changes to test/tester.tcl.
| ︙ | ︙ | |||
388 389 390 391 392 393 394 395 396 397 398 399 400 401 |
test $name 1 $constraints
} else {
protOut " Expected:\n [join $expected "\n "]" 1
protOut " Got:\n [join $result "\n "]" 1
test $name 0 $constraints
}
}
# Append all arguments into a single value and then returns it.
#
proc appendArgs {args} {
eval append result $args
}
| > > > > > > > > > > > > > > > > > > > | 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 |
test $name 1 $constraints
} else {
protOut " Expected:\n [join $expected "\n "]" 1
protOut " Got:\n [join $result "\n "]" 1
test $name 0 $constraints
}
}
# Perform a test on the contents of a file
#
proc test_file_contents {name path expected {constraints ""}} {
if {[file exists $path]} {
set result [read_file $path]
set passed [expr {$result eq $expected}]
if {!$passed} {
set expectedLines [split $expected "\n"]
set resultLines [split $result "\n"]
protOut " Expected:\n [join $expectedLines "\n "]" 1
protOut " Got:\n [join $resultLines "\n "]" 1
}
} else {
set passed 0
protOut " File does not exist: $path" 1
}
test $name $passed $constraints
}
# Append all arguments into a single value and then returns it.
#
proc appendArgs {args} {
eval append result $args
}
|
| ︙ | ︙ |
Changes to test/utf.test.
more than 10,000 changes
Added test/wiki.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 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 |
#
# Copyright (c) 2016 D. Richard Hipp
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the Simplified BSD License (also
# known as the "2-Clause License" or "FreeBSD License".)
#
# This program is distributed in the hope that it will be useful,
# but without any warranty; without even the implied warranty of
# merchantability or fitness for a particular purpose.
#
# Author contact information:
# drh@hwaci.com
# http://www.hwaci.com/drh/
#
############################################################################
#
# Test wiki and attachment command Support
#
test_setup
# Return true if two files are similar (i.e. not only compress trailing spaces
# from a line, but remove any final LF from the file as well)
proc similar_file {a b} {
set x [read_file $a]
regsub -all { +\n} $x \n x
regsub -all {\n$} $x {} x
set y [read_file $b]
regsub -all { +\n} $y \n y
regsub -all {\n$} $y {} y
return [expr {$x==$y}]
}
# Return the mime type in the manifest for a given wiki page
# Defaults to "error: some text" if the manifest can't be located and
# "text/x-fossil-wiki" (the default mimetype for rendering)
# if the N card is omitted in the manifest.
# Note: Makes fossil calls, so $CODE and $RESULT will be corrupted
proc get_mime_type {name} {
global CODE RESULT
fossil http << "GET /wiki?name=$name"
if {$CODE != 0} {
return error: /wiki?name=$name $CODE $RESULT"
}
set CODE [regexp {href="/info/([0-9a-f]+)"} $RESULT match info]
if {$CODE == 0} {
return "error: No info link found for wiki page $name"
}
fossil http << "GET /artifact/$info"
if {$CODE != 0} {
return "error: /artifact/$info $CODE $RESULT"
}
set CODE [regexp {<pre>(.*)</pre>} $RESULT match pre]
if {$CODE == 0} {
return "error: No pre block in /artifact/$info"
}
set CODE [regexp -line {^N (.*)$} $pre match mimetype]
if {$CODE == 0} {
return "text/x-fossil-wiki"
}
return $mimetype
}
###############################################################################
# Initially there should be no wiki entries
fossil wiki list
test wiki-0 {[normalize_result] eq {}}
###############################################################################
# Adding an entry should add it to the wiki list
write_file f1 "first wiki note"
fossil wiki create tcltest f1
test wiki-1 {$CODE == 0}
fossil wiki list
test wiki-2 {[normalize_result] eq {tcltest}}
###############################################################################
# Trying to add the same entry should fail
fossil wiki create tcltest f1 -expectError
test wiki-3 {$CODE != 0}
###############################################################################
# exporting the wiki page should give back similar text
fossil wiki export tcltest a1
test wiki-4 {[similar_file f1 a1]}
###############################################################################
# commiting a change to an existing page should replace the page on export
write_file f2 "second version of the page"
fossil wiki commit tcltest f2
test wiki-5 {$CODE == 0}
fossil wiki export tcltest a2
test wiki-6 {[similar_file f2 a2]}
###############################################################################
# But we shouldn't be able to update non-existant pages
fossil wiki commit doesntexist f1 -expectError
test wiki-7 {$CODE != 0}
###############################################################################
# There shouldn't be any tech notes at this point
fossil wiki list --technote
test wiki-8 {[normalize_result] eq {}}
###############################################################################
# Creating a tech note with a specified timestamp should add a technote
write_file f3 "A technote"
fossil wiki create technote f3 --technote {2016-01-01 12:34}
test wiki-9 {$CODE == 0}
fossil wiki list --technote
test wiki-10 {[normalize_result] eq {2016-01-01 12:34:00}}
fossil wiki list --technote --show-technote-ids
set technotelist [split $RESULT "\n"]
set veryfirsttechnoteid [lindex [split [lindex $technotelist 0]] 0]
###############################################################################
# exporting that technote should give back similar text
fossil wiki export a3 --technote {2016-01-01 12:34:00}
test wiki-11 {[similar_file f3 a3]}
###############################################################################
# Trying to add a technote with the same timestamp should succeed and create a
# second tech note
fossil wiki create 2ndnote f3 -technote {2016-01-01 12:34}
test wiki-13 {$CODE == 0}
fossil wiki list --technote
set technotelist [split $RESULT "\n"]
test wiki-13.1 {[llength $technotelist] == 2}
###############################################################################
# commiting a change to an existing technote should replace the page on export
# (this should update the tech note from wiki-13 as that the most recently
# updated one, that should also be the one exported by the export command)
write_file f4 "technote 2nd variant"
fossil wiki commit technote f4 --technote {2016-01-01 12:34}
test wiki-14 {$CODE == 0}
fossil wiki export a4 --technote {2016-01-01 12:34}
test wiki-15 {[similar_file f4 a4]}
# Also check that the tech note with the same timestamp, but modified less
# recently still has its original text
fossil wiki export a4.1 --technote $veryfirsttechnoteid
test wiki-15.1 {[similar_file f3 a4.1]}
###############################################################################
# But we shouldn't be able to update non-existant pages
fossil wiki commit doesntexist f1 -expectError
test wiki-16 {$CODE != 0}
###############################################################################
# Check specifying tags for a technote is OK
write_file f5 "technote with tags"
fossil wiki create {tagged technote} f5 --technote {2016-01-02 12:34} --technote-tags {A B}
test wiki-17 {$CODE == 0}
write_file f5.1 "editted and tagged technote"
fossil wiki commit {tagged technote} f5 --technote {2016-01-02 12:34} --technote-tags {C D}
test wiki-18 {$CODE == 0}
###############################################################################
# Check specifying a bgcolor for a technote is OK
write_file f6 "bgcolored technote"
fossil wiki create bgcolor f6 --technote {2016-01-03 12:34} --technote-bgcolor red
test wiki-19 {$CODE == 0}
write_file f6.1 "editted technote with a background color"
fossil wiki commit bgcolor f6.1 --technote {2016-01-03 12:34} --technote-bgcolor yellow
test wiki-20 {$CODE == 0}
###############################################################################
# Test adding an attachment to both a non-existant (should fail) and existing wiki page
write_file fa "This is a file to be attached"
fossil attachment add doesntexist fa -expectError
test wiki-21 {$CODE != 0}
fossil attachment add tcltest fa
test wiki-22 {$CODE == 0}
###############################################################################
# Test adding an attachment to both a non-existant (should fail) and existing tech note
fossil attachment add fa --technote {2016-07-22 12:00} -expectError
test wiki-23 {$CODE != 0}
fossil attachment add fa --technote {2016-01-03 12:34}
test wiki-24 {$CODE == 0}
###############################################################################
# Check that a wiki page with an attachment can be updated
fossil wiki commit tcltest f1
test wiki-25 {$CODE == 0}
###############################################################################
# Check that a technote with an attachment can be updated
fossil wiki commit technote f6 --technote {2016-01-03 12:34}
test wiki-26 {$CODE == 0}
fossil wiki commit technote f6 --technote {2016-01-03 12:34} --technote-tags {E F}
test wiki-27 {$CODE == 0}
fossil wiki commit technote f6 --technote {2016-01-03 12:34} --technote-bgcolor blue
test wiki-28 {$CODE == 0}
###############################################################################
# Check longest form of timestamp for the technote
write_file f7 "Different timestamps"
fossil wiki create technotenow f7 --technote {2016-01-04 12:34:56+00:00}
test wiki-29 {$CODE == 0}
###############################################################################
# Check a technote appears on the timeline
write_file f8 "Contents of a 'unique' tech note"
fossil wiki create {Unique technote} f8 --technote {2016-01-05 01:02:03}
fossil timeline
test wiki-30 {[string match *Unique*technote* $RESULT]}
###############################################################################
# Check for a collision between an attachment and a note, this was a
# bug that resulted from some code treating the attachment entry as if it
# were a technote when it isn't really.
#
# First, wait for the top of the next second so the attachment
# happens at a known time, then add an attachment to an existing note
# and a new note immediately after.
set t0 [clock seconds]
while {$t0 == [clock seconds]} {
after 100
}
set t1 [clock format [clock seconds] -gmt 1 -format "%Y-%m-%d %H:%M:%S"]
write_file f9 "Timestamp: $t1"
fossil attachment add f9 --technote {2016-01-05 01:02:03}
test wiki-31 {$CODE == 0}
fossil wiki create {Attachment collision} f9 --technote now
test wiki-32 {$CODE == 0}
#
# Now waste time until the next second so that the remaining tests
# don't have to worry about a potential collision
set t0 [clock seconds]
while {$t0 == [clock seconds]} {
after 100
}
###############################################################################
# Check a technote with no timestamp cannot be created, but that
# "now" is a valid stamp.
set t2 [clock format [clock seconds] -gmt 1 -format "%Y-%m-%d %H:%M:%S"]
write_file f10 "Even unstampted notes are delivered.\nStamped $t2"
fossil wiki create "Unstamped Note" f10 --technote -expectError
test wiki-33 {$CODE != 0}
fossil wiki create "Unstamped Note" f10 --technote now
test wiki-34 {$CODE == 0}
fossil wiki list -t
test wiki-35 {[string match "*$t2*" $RESULT]}
###############################################################################
# Check an attachment to it in the same second works.
write_file f11 "Time Stamp was $t2"
fossil attachment add f11 --technote $t2
test wiki-36 {$CODE == 0}
fossil timeline
test wiki-36-1 {$CODE == 0}
fossil wiki list -t
test wiki-36-2 {$CODE == 0}
###############################################################################
# Check that we have the expected number of tech notes on the list (and not
# extra ones from other events (such as the attachments) - 8 tech notes
# expected created by tests 9, 13, 17, 19, 29, 31, 32 and 34
fossil wiki list --technote
set technotelist [split $RESULT "\n"]
test wiki-37 {[llength $technotelist] == 8}
###############################################################################
# Check that using the show-technote-ids shows the same tech notes in the same
# order (with the technote id as the first word of the line)
fossil wiki list --technote --show-technote-ids
set technoteidlist [split $RESULT "\n"]
test wiki-38 {[llength $technotelist] == 8}
for {set i 0} {$i < [llength $technotelist]} {incr i} {
set match "???????????????????????????????????????? "
append match [lindex $technotelist $i]
test "wiki-39-$i" {[string match $match [lindex $technoteidlist $i]]}
}
###############################################################################
# Create new tech note with a old timestamp so that it is oldest and then check that
# the contents of the oldest tech note (by tech note id, both full and short) match up
write_file f12 "A really old tech note"
fossil wiki create {Old tech note} f12 --technote {2001-07-07 09:08:07}
fossil wiki list --technote --show-technote-ids
set technotelist [split $RESULT "\n"]
set anoldtechnoteid [lindex [split [lindex $technotelist [llength $technotelist]-1]] 0]
fossil wiki export a12 --technote $anoldtechnoteid
test wiki-40 {[similar_file f12 a12]}
###############################################################################
# Also check that we can specify a prefix of the tech note id (note: with
# 9 items in the tech note at this point there is a chance of a collision.
# However with a 20 character prefix the chance of the collision is
# approximately 1 in 10^22 so this test ignores that possibility.)
fossil wiki export a12.1 --technote [string range $anoldtechnoteid 0 20]
test wiki-41 {[similar_file f12 a12.1]}
###############################################################################
# Now we need to force a collision in the first four characters of the tech
# note id if we don't already have one so we can check we get an error if the
# tech note id is ambiguous
set idcounts [dict create]
set maxcount 0
fossil wiki list --technote --show-technote-ids
set technotelist [split $RESULT "\n"]
for {set i 0} {$i < [llength $technotelist]} {incr i} {
set fullid [lindex $technotelist $i]
set id [string range $fullid 0 3]
dict incr idcounts $id
if {[dict get $idcounts $id] > $maxcount} {
set maxid $id
incr maxcount
}
}
# get i so that, as a julian date, it is in the 1800s, i.e., older than
# any other tech note, but after 1 AD
set i 2400000
while {$maxcount < 2} {
# keep getting older
incr i -1
write_file f13 "A tech note with timestamp of jday=$i"
fossil wiki create "timestamp of $i" f13 --technote "$i"
fossil wiki list --technote --show-technote-ids
set technotelist [split $RESULT "\n"]
set oldesttechnoteid [lindex [split [lindex $technotelist [llength $technotelist]-1]] 0]
set id [string range $oldesttechnoteid 0 3]
dict incr idcounts $id
if {[dict get $idcounts $id] > $maxcount} {
set maxid $id
incr maxcount
}
}
# Save the duplicate id for this and later tests
set duplicateid $maxid
fossil wiki export a13 --technote $duplicateid -expectError
test wiki-42 {$CODE != 0}
###############################################################################
# Check we can update technote by its id
write_file f14 "Updated text for the really old tech note"
fossil wiki commit {Old tech note} f14 --technote $anoldtechnoteid
fossil wiki export a14 --technote $anoldtechnoteid
test wiki-43 {[similar_file f14 a14]}
###############################################################################
# Check we can add attachments to a technote by its id
fossil attachment add fa --technote $anoldtechnoteid
test wiki-44 {$CODE == 0}
###############################################################################
# Also check that we can specify a prefix of the tech note id
write_file f15 "Updated text for the really old tech note specified by its id"
fossil wiki commit {Old tech note} f15 --technote [string range $anoldtechnoteid 0 20]
fossil wiki export a15 --technote $anoldtechnoteid
test wiki-45 {[similar_file f15 a15]}
###############################################################################
# Check we can add attachments to a technote by a prefix of its id
fossil attachment add fa --technote [string range $anoldtechnoteid 0 20]
test wiki-46 {$CODE == 0}
###############################################################################
# And we get an error for the ambiguous tech note id
fossil wiki commit {Old tech note} f15 --technote $duplicateid -expectError
test wiki-47 {$CODE != 0}
fossil attachment add fa --technote $duplicateid -expectError
test wiki-48 {$CODE != 0}
###############################################################################
# Check the default mimetype is text/x-fossil-wiki
test wiki-49 {[get_mime_type tcltest] == "text/x-fossil-wiki"}
###############################################################################
# Check long form of the mimetypes are recorded correctly
fossil wiki create tcltest-x-fossil f1 -mimetype text/x-fossil-wiki
test wiki-50 {[get_mime_type tcltest-x-fossil] == "text/x-fossil-wiki"}
fossil wiki create tcltest-x-markdown f1 -mimetype text/x-markdown
test wiki-51 {[get_mime_type tcltest-x-markdown] == "text/x-markdown"}
fossil wiki create tcltest-plain f1 -mimetype text/plain
test wiki-52 {[get_mime_type tcltest-plain] == "text/plain"}
fossil wiki create tcltest-x-random f1 -mimetype text/x-random
test wiki-53 {[get_mime_type tcltest-x-random] == "text/x-fossil-wiki"}
###############################################################################
# Check short form of the mimetypes are recorded correctly
fossil wiki create tcltest-x-fossil-short f1 -mimetype wiki
test wiki-54 {[get_mime_type tcltest-x-fossil-short] == "text/x-fossil-wiki"}
fossil wiki create tcltest-x-markdown-short f1 -mimetype markdown
test wiki-55 {[get_mime_type tcltest-x-markdown-short] == "text/x-markdown"}
fossil wiki create tcltest-plain-short f1 -mimetype plain
test wiki-56 {[get_mime_type tcltest-plain-short] == "text/plain"}
fossil wiki create tcltest-x-random-short f1 -mimetype random
test wiki-57 {[get_mime_type tcltest-x-random-short] == "text/x-fossil-wiki"}
###############################################################################
test_cleanup
|
Changes to win/Makefile.PellesCGMake.
| ︙ | ︙ | |||
81 82 83 84 85 86 87 | UTILS_OBJ=$(UTILS:.exe=.obj) UTILS_SRC=$(foreach uf,$(UTILS),$(SRCDIR)$(uf:.exe=.c)) # define the SQLite files, which need special flags on compile SQLITESRC=sqlite3.c ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf)) SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj)) | | | | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | UTILS_OBJ=$(UTILS:.exe=.obj) UTILS_SRC=$(foreach uf,$(UTILS),$(SRCDIR)$(uf:.exe=.c)) # define the SQLite files, which need special flags on compile SQLITESRC=sqlite3.c ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf)) SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj)) SQLITEDEFINES=-DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_WIN32_NO_ANSI # define the SQLite shell files, which need special flags on compile SQLITESHELLSRC=shell.c ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf)) SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj)) SQLITESHELLDEFINES=-Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen # 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 |
| ︙ | ︙ |
Changes to win/Makefile.dmc.
| ︙ | ︙ | |||
22 23 24 25 26 27 28 | SSL = CFLAGS = -o BCC = $(DMDIR)\bin\dmc $(CFLAGS) TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 | | | | | | | 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 | SSL = CFLAGS = -o BCC = $(DMDIR)\bin\dmc $(CFLAGS) TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fshell_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c piechart_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O 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 allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo foci fshell fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path piechart pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup sha1 shun sitemap skins sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ +echo fossil >> $@ +echo fossil >> $@ +echo $(LIBS) >> $@ +echo. >> $@ +echo fossil >> $@ translate$E: $(SRCDIR)\translate.c |
| ︙ | ︙ | |||
318 319 320 321 322 323 324 325 326 327 328 329 330 331 | +translate$E $** > $@ $(OBJDIR)\foci$O : foci_.c foci.h $(TCC) -o$@ -c foci_.c foci_.c : $(SRCDIR)\foci.c +translate$E $** > $@ $(OBJDIR)\fusefs$O : fusefs_.c fusefs.h $(TCC) -o$@ -c fusefs_.c fusefs_.c : $(SRCDIR)\fusefs.c +translate$E $** > $@ | > > > > > > | 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 | +translate$E $** > $@ $(OBJDIR)\foci$O : foci_.c foci.h $(TCC) -o$@ -c foci_.c foci_.c : $(SRCDIR)\foci.c +translate$E $** > $@ $(OBJDIR)\fshell$O : fshell_.c fshell.h $(TCC) -o$@ -c fshell_.c fshell_.c : $(SRCDIR)\fshell.c +translate$E $** > $@ $(OBJDIR)\fusefs$O : fusefs_.c fusefs.h $(TCC) -o$@ -c fusefs_.c fusefs_.c : $(SRCDIR)\fusefs.c +translate$E $** > $@ |
| ︙ | ︙ | |||
836 837 838 839 840 841 842 | $(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 | | | 842 843 844 845 846 847 848 849 850 | $(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 allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fshell_.c:fshell.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h piechart_.c:piechart.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h @copy /Y nul: headers |
Changes to win/Makefile.mingw.
| ︙ | ︙ | |||
30 31 32 33 34 35 36 37 38 39 40 41 42 | # 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 and options for use in building executables that # will run on the platform that is doing the build. This is used # to compile code-generator programs as part of the build process. # See TCC below for the C compiler for building the finished binary. # | > > > > > > > > | | 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 | # 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 # code-generator programs as part of the build process. See TCC # and TCCEXE below for the C compiler for building the finished # binary. # BCCEXE = gcc #### C Compiler and options for use in building executables that # will run on the platform that is doing the build. This is used # to compile code-generator programs as part of the build process. # See TCC below for the C compiler for building the finished binary. # BCC = $(BCCEXE) #### Enable compiling with debug symbols (much larger binary) # # FOSSIL_ENABLE_SYMBOLS = 1 #### Enable JSON (http://www.json.org) support using "cson" # |
| ︙ | ︙ | |||
86 87 88 89 90 91 92 93 94 95 96 97 98 99 | #### Load Tcl using the private stubs mechanism # # FOSSIL_ENABLE_TCL_PRIVATE_STUBS = 1 #### Use 'system' SQLite # # USE_SYSTEM_SQLITE = 1 #### Use the miniz compression library # # FOSSIL_ENABLE_MINIZ = 1 #### Use the Tcl source directory instead of the install directory? # This is useful when Tcl has been compiled statically with MinGW. | > > > > | 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | #### Load Tcl using the private stubs mechanism # # FOSSIL_ENABLE_TCL_PRIVATE_STUBS = 1 #### Use 'system' SQLite # # USE_SYSTEM_SQLITE = 1 #### Use the SQLite Encryption Extension # # USE_SEE = 1 #### Use the miniz compression library # # FOSSIL_ENABLE_MINIZ = 1 #### Use the Tcl source directory instead of the install directory? # This is useful when Tcl has been compiled statically with MinGW. |
| ︙ | ︙ | |||
128 129 130 131 132 133 134 | # used, taking into account whether zlib is actually enabled and the target # processor architecture. # ifndef X64 SSLCONFIG = mingw ifndef FOSSIL_ENABLE_MINIZ ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" | | | | | | 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 | # used, taking into account whether zlib is actually enabled and the target # processor architecture. # ifndef X64 SSLCONFIG = mingw ifndef FOSSIL_ENABLE_MINIZ ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" ZLIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o else ZLIBCONFIG = ZLIBTARGETS = endif else SSLCONFIG = mingw64 ZLIBCONFIG = ZLIBTARGETS = endif #### Disable creation of the OpenSSL shared libraries. Also, disable support # for both SSLv2 and SSLv3 (i.e. thereby forcing the use of TLS). # SSLCONFIG += no-ssl2 no-ssl3 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). # ifndef FOSSIL_ENABLE_MINIZ SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib endif #### The directories where the OpenSSL include and library files are located. # The recommended usage here is to use the Sysinternals junction tool # to create a hard link between an "openssl-1.x" sub-directory of the # Fossil source code directory and the target OpenSSL source directory. # OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2h OPENSSLINCDIR = $(OPENSSLDIR)/include OPENSSLLIBDIR = $(OPENSSLDIR) #### Either the directory where the Tcl library is installed or the Tcl # source code directory resides (depending on the value of the macro # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory, # this directory must have "include" and "lib" sub-directories. If |
| ︙ | ︙ | |||
197 198 199 200 201 202 203 | endif TCLTARGET = libtclstub86.a else LIBTCL = -ltcl86 TCLTARGET = binaries endif | > > > > > > > > | | | | 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 | endif TCLTARGET = libtclstub86.a else LIBTCL = -ltcl86 TCLTARGET = binaries endif #### C compiler for use in building executables that will run on the # target platform. This is usually the same as BCCEXE, unless you # are cross-compiling. This C compiler builds the finished binary # for fossil. See BCC and BCCEXE above for the C compiler for # building intermediate code-generator tools. # TCCEXE = gcc #### 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 #### Add the necessary command line options to build with debugging # symbols, if enabled. # ifdef FOSSIL_ENABLE_SYMBOLS TCC += -g else |
| ︙ | ︙ | |||
311 312 313 314 315 316 317 318 319 320 321 322 323 324 | endif # With JSON support ifdef FOSSIL_ENABLE_JSON TCC += -DFOSSIL_ENABLE_JSON=1 RCC += -DFOSSIL_ENABLE_JSON=1 endif #### The option -static has no effect on MinGW(-w64), only dynamic # executables can be built when linking with MSVCRT. OpenSSL # (optional) and zlib (required) however are always linked in # statically. Therefore, the FOSSIL_DYNAMIC_BUILD option does # not really apply to MinGW (i.e. since ALL external libraries # are NOT linked dynamically). | > > > > > > | 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 | endif # With JSON support ifdef FOSSIL_ENABLE_JSON TCC += -DFOSSIL_ENABLE_JSON=1 RCC += -DFOSSIL_ENABLE_JSON=1 endif # With SQLite Encryption Extension support ifdef USE_SEE TCC += -DUSE_SEE=1 RCC += -DUSE_SEE=1 endif #### The option -static has no effect on MinGW(-w64), only dynamic # executables can be built when linking with MSVCRT. OpenSSL # (optional) and zlib (required) however are always linked in # statically. Therefore, the FOSSIL_DYNAMIC_BUILD option does # not really apply to MinGW (i.e. since ALL external libraries # are NOT linked dynamically). |
| ︙ | ︙ | |||
426 427 428 429 430 431 432 433 434 435 436 437 438 439 | $(SRCDIR)/doc.c \ $(SRCDIR)/encode.c \ $(SRCDIR)/event.c \ $(SRCDIR)/export.c \ $(SRCDIR)/file.c \ $(SRCDIR)/finfo.c \ $(SRCDIR)/foci.c \ $(SRCDIR)/fusefs.c \ $(SRCDIR)/glob.c \ $(SRCDIR)/graph.c \ $(SRCDIR)/gzip.c \ $(SRCDIR)/http.c \ $(SRCDIR)/http_socket.c \ $(SRCDIR)/http_ssl.c \ | > | 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 | $(SRCDIR)/doc.c \ $(SRCDIR)/encode.c \ $(SRCDIR)/event.c \ $(SRCDIR)/export.c \ $(SRCDIR)/file.c \ $(SRCDIR)/finfo.c \ $(SRCDIR)/foci.c \ $(SRCDIR)/fshell.c \ $(SRCDIR)/fusefs.c \ $(SRCDIR)/glob.c \ $(SRCDIR)/graph.c \ $(SRCDIR)/gzip.c \ $(SRCDIR)/http.c \ $(SRCDIR)/http_socket.c \ $(SRCDIR)/http_ssl.c \ |
| ︙ | ︙ | |||
598 599 600 601 602 603 604 605 606 607 608 609 610 611 | $(OBJDIR)/doc_.c \ $(OBJDIR)/encode_.c \ $(OBJDIR)/event_.c \ $(OBJDIR)/export_.c \ $(OBJDIR)/file_.c \ $(OBJDIR)/finfo_.c \ $(OBJDIR)/foci_.c \ $(OBJDIR)/fusefs_.c \ $(OBJDIR)/glob_.c \ $(OBJDIR)/graph_.c \ $(OBJDIR)/gzip_.c \ $(OBJDIR)/http_.c \ $(OBJDIR)/http_socket_.c \ $(OBJDIR)/http_ssl_.c \ | > | 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 | $(OBJDIR)/doc_.c \ $(OBJDIR)/encode_.c \ $(OBJDIR)/event_.c \ $(OBJDIR)/export_.c \ $(OBJDIR)/file_.c \ $(OBJDIR)/finfo_.c \ $(OBJDIR)/foci_.c \ $(OBJDIR)/fshell_.c \ $(OBJDIR)/fusefs_.c \ $(OBJDIR)/glob_.c \ $(OBJDIR)/graph_.c \ $(OBJDIR)/gzip_.c \ $(OBJDIR)/http_.c \ $(OBJDIR)/http_socket_.c \ $(OBJDIR)/http_ssl_.c \ |
| ︙ | ︙ | |||
719 720 721 722 723 724 725 726 727 728 729 730 731 732 | $(OBJDIR)/doc.o \ $(OBJDIR)/encode.o \ $(OBJDIR)/event.o \ $(OBJDIR)/export.o \ $(OBJDIR)/file.o \ $(OBJDIR)/finfo.o \ $(OBJDIR)/foci.o \ $(OBJDIR)/fusefs.o \ $(OBJDIR)/glob.o \ $(OBJDIR)/graph.o \ $(OBJDIR)/gzip.o \ $(OBJDIR)/http.o \ $(OBJDIR)/http_socket.o \ $(OBJDIR)/http_ssl.o \ | > | 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 | $(OBJDIR)/doc.o \ $(OBJDIR)/encode.o \ $(OBJDIR)/event.o \ $(OBJDIR)/export.o \ $(OBJDIR)/file.o \ $(OBJDIR)/finfo.o \ $(OBJDIR)/foci.o \ $(OBJDIR)/fshell.o \ $(OBJDIR)/fusefs.o \ $(OBJDIR)/glob.o \ $(OBJDIR)/graph.o \ $(OBJDIR)/gzip.o \ $(OBJDIR)/http.o \ $(OBJDIR)/http_socket.o \ $(OBJDIR)/http_ssl.o \ |
| ︙ | ︙ | |||
909 910 911 912 913 914 915 | $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) $(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@ # The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set # to 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. | | | > > > > > > > > > > > > > > > > > < < < < < < > > > > > | | > > | | | | | | | 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 | $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) $(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@ # The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set # to 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. SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o SQLITE3_OBJ.1 = SQLITE3_OBJ. = $(SQLITE3_OBJ.0) # The FOSSIL_ENABLE_MINIZ variable may be undefined, set to 0, or # set to 1. If it is set to 1, the miniz library included in the # source tree should be used; otherwise, it should not. MINIZ_OBJ.0 = MINIZ_OBJ.1 = $(OBJDIR)/miniz.o MINIZ_OBJ. = $(MINIZ_OBJ.0) # The USE_SEE variable may be undefined, 0 or 1. If undefined or # 0, ordinary 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 = sqlite3.c SQLITE3_SRC.1 = sqlite3-see.c SQLITE3_SRC. = sqlite3.c SQLITE3_SRC = $(SRCDIR)/$(SQLITE3_SRC.$(USE_SEE)) SQLITE3_SHELL_SRC.0 = shell.c SQLITE3_SHELL_SRC.1 = shell-see.c SQLITE3_SHELL_SRC. = shell.c SQLITE3_SHELL_SRC = $(SRCDIR)/$(SQLITE3_SHELL_SRC.$(USE_SEE)) SEE_FLAGS.0 = SEE_FLAGS.1 = -DSQLITE_HAS_CODEC SEE_FLAGS. = SEE_FLAGS = $(SEE_FLAGS.$(USE_SEE)) EXTRAOBJ = \ $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE)) \ $(MINIZ_OBJ.$(FOSSIL_ENABLE_MINIZ)) \ $(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 ifdef FOSSIL_ENABLE_MINIZ BLDTARGETS = else BLDTARGETS = zlib endif openssl: $(BLDTARGETS) cd $(OPENSSLLIBDIR);./Configure --cross-compile-prefix=$(PREFIX) $(SSLCONFIG) $(MAKE) -C $(OPENSSLLIBDIR) CC=$(TCCEXE) build_libs clean-openssl: $(MAKE) -C $(OPENSSLLIBDIR) CC=$(TCCEXE) clean tcl: cd $(TCLSRCDIR)/win;./configure $(MAKE) -C $(TCLSRCDIR)/win CC=$(TCCEXE) $(TCLTARGET) clean-tcl: $(MAKE) -C $(TCLSRCDIR)/win CC=$(TCCEXE) distclean APPTARGETS += $(BLDTARGETS) ifdef FOSSIL_BUILD_SSL APPTARGETS += openssl endif $(APPNAME): $(APPTARGETS) $(OBJDIR)/headers $(CODECHECK1) $(OBJ) $(EXTRAOBJ) $(OBJDIR)/fossil.o $(CODECHECK1) $(TRANS_SRC) |
| ︙ | ︙ | |||
1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 | $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \ $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \ $(OBJDIR)/event_.c:$(OBJDIR)/event.h \ $(OBJDIR)/export_.c:$(OBJDIR)/export.h \ $(OBJDIR)/file_.c:$(OBJDIR)/file.h \ $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \ $(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \ $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \ $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \ | > | 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 | $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \ $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \ $(OBJDIR)/event_.c:$(OBJDIR)/event.h \ $(OBJDIR)/export_.c:$(OBJDIR)/export.h \ $(OBJDIR)/file_.c:$(OBJDIR)/file.h \ $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \ $(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \ $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h \ $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h \ |
| ︙ | ︙ | |||
1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 | $(OBJDIR)/foci_.c: $(SRCDIR)/foci.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/foci.c >$@ $(OBJDIR)/foci.o: $(OBJDIR)/foci_.c $(OBJDIR)/foci.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/foci.o -c $(OBJDIR)/foci_.c $(OBJDIR)/foci.h: $(OBJDIR)/headers $(OBJDIR)/fusefs_.c: $(SRCDIR)/fusefs.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/fusefs.c >$@ $(OBJDIR)/fusefs.o: $(OBJDIR)/fusefs_.c $(OBJDIR)/fusefs.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/fusefs.o -c $(OBJDIR)/fusefs_.c | > > > > > > > > | 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 | $(OBJDIR)/foci_.c: $(SRCDIR)/foci.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/foci.c >$@ $(OBJDIR)/foci.o: $(OBJDIR)/foci_.c $(OBJDIR)/foci.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/foci.o -c $(OBJDIR)/foci_.c $(OBJDIR)/foci.h: $(OBJDIR)/headers $(OBJDIR)/fshell_.c: $(SRCDIR)/fshell.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/fshell.c >$@ $(OBJDIR)/fshell.o: $(OBJDIR)/fshell_.c $(OBJDIR)/fshell.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/fshell.o -c $(OBJDIR)/fshell_.c $(OBJDIR)/fshell.h: $(OBJDIR)/headers $(OBJDIR)/fusefs_.c: $(SRCDIR)/fusefs.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/fusefs.c >$@ $(OBJDIR)/fusefs.o: $(OBJDIR)/fusefs_.c $(OBJDIR)/fusefs.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/fusefs.o -c $(OBJDIR)/fusefs_.c |
| ︙ | ︙ | |||
2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 |
$(TRANSLATE) $(SRCDIR)/zip.c >$@
$(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h
$(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c
$(OBJDIR)/zip.h: $(OBJDIR)/headers
SQLITE_OPTIONS = -DNDEBUG=1 \
-DSQLITE_OMIT_LOAD_EXTENSION=1 \
-DSQLITE_ENABLE_LOCKING_STYLE=0 \
-DSQLITE_THREADSAFE=0 \
-DSQLITE_DEFAULT_FILE_FORMAT=4 \
-DSQLITE_OMIT_DEPRECATED \
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
-DSQLITE_ENABLE_FTS4 \
-DSQLITE_ENABLE_FTS3_PARENTHESIS \
-DSQLITE_ENABLE_DBSTAT_VTAB \
-DSQLITE_ENABLE_JSON1 \
-DSQLITE_ENABLE_FTS5 \
-DSQLITE_WIN32_NO_ANSI \
| > > > | > | | > | | | 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 |
$(TRANSLATE) $(SRCDIR)/zip.c >$@
$(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h
$(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c
$(OBJDIR)/zip.h: $(OBJDIR)/headers
MINGW_OPTIONS = -D_HAVE__MINGW_H
SQLITE_OPTIONS = -DNDEBUG=1 \
-DSQLITE_OMIT_LOAD_EXTENSION=1 \
-DSQLITE_ENABLE_LOCKING_STYLE=0 \
-DSQLITE_LIKE_DOESNT_MATCH_BLOBS=1 \
-DSQLITE_THREADSAFE=0 \
-DSQLITE_DEFAULT_FILE_FORMAT=4 \
-DSQLITE_OMIT_DEPRECATED \
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
-DSQLITE_ENABLE_FTS4 \
-DSQLITE_ENABLE_FTS3_PARENTHESIS \
-DSQLITE_ENABLE_DBSTAT_VTAB \
-DSQLITE_ENABLE_JSON1 \
-DSQLITE_ENABLE_FTS5 \
-DSQLITE_WIN32_NO_ANSI \
$(MINGW_OPTIONS) \
-DSQLITE_USE_MALLOC_H \
-DSQLITE_USE_MSIZE
SHELL_OPTIONS = -Dmain=sqlite3_shell \
-DSQLITE_SHELL_IS_UTF8=1 \
-DSQLITE_OMIT_LOAD_EXTENSION=1 \
-DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
-DSQLITE_SHELL_DBNAME_PROC=fossil_open \
-Daccess=file_access \
-Dsystem=fossil_system \
-Dgetenv=fossil_getenv \
-Dfopen=fossil_fopen
MINIZ_OPTIONS = -DMINIZ_NO_STDIO \
-DMINIZ_NO_TIME \
-DMINIZ_NO_ARCHIVE_APIS
$(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)/cson_amalgamation.c
$(XTCC) -c $(SRCDIR)/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)/sqlite3.h $(SRCDIR)/../win/Makefile.mingw
$(XTCC) $(SHELL_OPTIONS) $(SHELL_CFLAGS) -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)/miniz.o: $(SRCDIR)/miniz.c
$(XTCC) $(MINIZ_OPTIONS) -c $(SRCDIR)/miniz.c -o $@
|
Changes to win/Makefile.mingw.mistachkin.
| ︙ | ︙ | |||
30 31 32 33 34 35 36 37 38 39 40 41 42 | # 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 and options for use in building executables that # will run on the platform that is doing the build. This is used # to compile code-generator programs as part of the build process. # See TCC below for the C compiler for building the finished binary. # | > > > > > > > > | | 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 | # 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 # code-generator programs as part of the build process. See TCC # and TCCEXE below for the C compiler for building the finished # binary. # BCCEXE = gcc #### C Compiler and options for use in building executables that # will run on the platform that is doing the build. This is used # to compile code-generator programs as part of the build process. # See TCC below for the C compiler for building the finished binary. # BCC = $(BCCEXE) #### Enable compiling with debug symbols (much larger binary) # # FOSSIL_ENABLE_SYMBOLS = 1 #### Enable JSON (http://www.json.org) support using "cson" # |
| ︙ | ︙ | |||
86 87 88 89 90 91 92 93 94 95 96 97 98 99 | #### Load Tcl using the private stubs mechanism # FOSSIL_ENABLE_TCL_PRIVATE_STUBS = 1 #### Use 'system' SQLite # # USE_SYSTEM_SQLITE = 1 #### Use the miniz compression library # # FOSSIL_ENABLE_MINIZ = 1 #### Use the Tcl source directory instead of the install directory? # This is useful when Tcl has been compiled statically with MinGW. | > > > > | 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | #### Load Tcl using the private stubs mechanism # FOSSIL_ENABLE_TCL_PRIVATE_STUBS = 1 #### Use 'system' SQLite # # USE_SYSTEM_SQLITE = 1 #### Use the SQLite Encryption Extension # # USE_SEE = 1 #### Use the miniz compression library # # FOSSIL_ENABLE_MINIZ = 1 #### Use the Tcl source directory instead of the install directory? # This is useful when Tcl has been compiled statically with MinGW. |
| ︙ | ︙ | |||
128 129 130 131 132 133 134 | # used, taking into account whether zlib is actually enabled and the target # processor architecture. # ifndef X64 SSLCONFIG = mingw ifndef FOSSIL_ENABLE_MINIZ ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" | | | | | | 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 | # used, taking into account whether zlib is actually enabled and the target # processor architecture. # ifndef X64 SSLCONFIG = mingw ifndef FOSSIL_ENABLE_MINIZ ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" ZLIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o else ZLIBCONFIG = ZLIBTARGETS = endif else SSLCONFIG = mingw64 ZLIBCONFIG = ZLIBTARGETS = endif #### Disable creation of the OpenSSL shared libraries. Also, disable support # for both SSLv2 and SSLv3 (i.e. thereby forcing the use of TLS). # SSLCONFIG += no-ssl2 no-ssl3 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). # ifndef FOSSIL_ENABLE_MINIZ SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib endif #### The directories where the OpenSSL include and library files are located. # The recommended usage here is to use the Sysinternals junction tool # to create a hard link between an "openssl-1.x" sub-directory of the # Fossil source code directory and the target OpenSSL source directory. # OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2h OPENSSLINCDIR = $(OPENSSLDIR)/include OPENSSLLIBDIR = $(OPENSSLDIR) #### Either the directory where the Tcl library is installed or the Tcl # source code directory resides (depending on the value of the macro # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory, # this directory must have "include" and "lib" sub-directories. If |
| ︙ | ︙ | |||
197 198 199 200 201 202 203 | endif TCLTARGET = libtclstub86.a else LIBTCL = -ltcl86 TCLTARGET = binaries endif | > > > > > > > > | | | | 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 | endif TCLTARGET = libtclstub86.a else LIBTCL = -ltcl86 TCLTARGET = binaries endif #### C compiler for use in building executables that will run on the # target platform. This is usually the same as BCCEXE, unless you # are cross-compiling. This C compiler builds the finished binary # for fossil. See BCC and BCCEXE above for the C compiler for # building intermediate code-generator tools. # TCCEXE = gcc #### 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 #### Add the necessary command line options to build with debugging # symbols, if enabled. # ifdef FOSSIL_ENABLE_SYMBOLS TCC += -g else |
| ︙ | ︙ | |||
311 312 313 314 315 316 317 318 319 320 321 322 323 324 | endif # With JSON support ifdef FOSSIL_ENABLE_JSON TCC += -DFOSSIL_ENABLE_JSON=1 RCC += -DFOSSIL_ENABLE_JSON=1 endif #### The option -static has no effect on MinGW(-w64), only dynamic # executables can be built when linking with MSVCRT. OpenSSL # (optional) and zlib (required) however are always linked in # statically. Therefore, the FOSSIL_DYNAMIC_BUILD option does # not really apply to MinGW (i.e. since ALL external libraries # are NOT linked dynamically). | > > > > > > | 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 | endif # With JSON support ifdef FOSSIL_ENABLE_JSON TCC += -DFOSSIL_ENABLE_JSON=1 RCC += -DFOSSIL_ENABLE_JSON=1 endif # With SQLite Encryption Extension support ifdef USE_SEE TCC += -DUSE_SEE=1 RCC += -DUSE_SEE=1 endif #### The option -static has no effect on MinGW(-w64), only dynamic # executables can be built when linking with MSVCRT. OpenSSL # (optional) and zlib (required) however are always linked in # statically. Therefore, the FOSSIL_DYNAMIC_BUILD option does # not really apply to MinGW (i.e. since ALL external libraries # are NOT linked dynamically). |
| ︙ | ︙ | |||
909 910 911 912 913 914 915 | $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) $(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@ # The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set # to 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. | | | > > > > > > > > > > > > > > > > > < < < < < < > > > > > | | > > | | | | | | | 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 | $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) $(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@ # The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set # to 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. SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o SQLITE3_OBJ.1 = SQLITE3_OBJ. = $(SQLITE3_OBJ.0) # The FOSSIL_ENABLE_MINIZ variable may be undefined, set to 0, or # set to 1. If it is set to 1, the miniz library included in the # source tree should be used; otherwise, it should not. MINIZ_OBJ.0 = MINIZ_OBJ.1 = $(OBJDIR)/miniz.o MINIZ_OBJ. = $(MINIZ_OBJ.0) # The USE_SEE variable may be undefined, 0 or 1. If undefined or # 0, ordinary 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 = sqlite3.c SQLITE3_SRC.1 = sqlite3-see.c SQLITE3_SRC. = sqlite3.c SQLITE3_SRC = $(SRCDIR)/$(SQLITE3_SRC.$(USE_SEE)) SQLITE3_SHELL_SRC.0 = shell.c SQLITE3_SHELL_SRC.1 = shell-see.c SQLITE3_SHELL_SRC. = shell.c SQLITE3_SHELL_SRC = $(SRCDIR)/$(SQLITE3_SHELL_SRC.$(USE_SEE)) SEE_FLAGS.0 = SEE_FLAGS.1 = -DSQLITE_HAS_CODEC SEE_FLAGS. = SEE_FLAGS = $(SEE_FLAGS.$(USE_SEE)) EXTRAOBJ = \ $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE)) \ $(MINIZ_OBJ.$(FOSSIL_ENABLE_MINIZ)) \ $(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 ifdef FOSSIL_ENABLE_MINIZ BLDTARGETS = else BLDTARGETS = zlib endif openssl: $(BLDTARGETS) cd $(OPENSSLLIBDIR);./Configure --cross-compile-prefix=$(PREFIX) $(SSLCONFIG) $(MAKE) -C $(OPENSSLLIBDIR) CC=$(TCCEXE) build_libs clean-openssl: $(MAKE) -C $(OPENSSLLIBDIR) CC=$(TCCEXE) clean tcl: cd $(TCLSRCDIR)/win;./configure $(MAKE) -C $(TCLSRCDIR)/win CC=$(TCCEXE) $(TCLTARGET) clean-tcl: $(MAKE) -C $(TCLSRCDIR)/win CC=$(TCCEXE) distclean APPTARGETS += $(BLDTARGETS) ifdef FOSSIL_BUILD_SSL APPTARGETS += openssl endif $(APPNAME): $(APPTARGETS) $(OBJDIR)/headers $(CODECHECK1) $(OBJ) $(EXTRAOBJ) $(OBJDIR)/fossil.o $(CODECHECK1) $(TRANS_SRC) |
| ︙ | ︙ | |||
2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 |
$(TRANSLATE) $(SRCDIR)/zip.c >$@
$(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h
$(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c
$(OBJDIR)/zip.h: $(OBJDIR)/headers
SQLITE_OPTIONS = -DNDEBUG=1 \
-DSQLITE_OMIT_LOAD_EXTENSION=1 \
-DSQLITE_ENABLE_LOCKING_STYLE=0 \
-DSQLITE_THREADSAFE=0 \
-DSQLITE_DEFAULT_FILE_FORMAT=4 \
-DSQLITE_OMIT_DEPRECATED \
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
-DSQLITE_ENABLE_FTS4 \
-DSQLITE_ENABLE_FTS3_PARENTHESIS \
-DSQLITE_ENABLE_DBSTAT_VTAB \
-DSQLITE_ENABLE_JSON1 \
-DSQLITE_ENABLE_FTS5 \
-DSQLITE_WIN32_NO_ANSI \
| > > > | > | | > | | | 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 |
$(TRANSLATE) $(SRCDIR)/zip.c >$@
$(OBJDIR)/zip.o: $(OBJDIR)/zip_.c $(OBJDIR)/zip.h $(SRCDIR)/config.h
$(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c
$(OBJDIR)/zip.h: $(OBJDIR)/headers
MINGW_OPTIONS = -D_HAVE__MINGW_H
SQLITE_OPTIONS = -DNDEBUG=1 \
-DSQLITE_OMIT_LOAD_EXTENSION=1 \
-DSQLITE_ENABLE_LOCKING_STYLE=0 \
-DSQLITE_LIKE_DOESNT_MATCH_BLOBS=1 \
-DSQLITE_THREADSAFE=0 \
-DSQLITE_DEFAULT_FILE_FORMAT=4 \
-DSQLITE_OMIT_DEPRECATED \
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
-DSQLITE_ENABLE_FTS4 \
-DSQLITE_ENABLE_FTS3_PARENTHESIS \
-DSQLITE_ENABLE_DBSTAT_VTAB \
-DSQLITE_ENABLE_JSON1 \
-DSQLITE_ENABLE_FTS5 \
-DSQLITE_WIN32_NO_ANSI \
$(MINGW_OPTIONS) \
-DSQLITE_USE_MALLOC_H \
-DSQLITE_USE_MSIZE
SHELL_OPTIONS = -Dmain=sqlite3_shell \
-DSQLITE_SHELL_IS_UTF8=1 \
-DSQLITE_OMIT_LOAD_EXTENSION=1 \
-DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
-DSQLITE_SHELL_DBNAME_PROC=fossil_open \
-Daccess=file_access \
-Dsystem=fossil_system \
-Dgetenv=fossil_getenv \
-Dfopen=fossil_fopen
MINIZ_OPTIONS = -DMINIZ_NO_STDIO \
-DMINIZ_NO_TIME \
-DMINIZ_NO_ARCHIVE_APIS
$(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)/cson_amalgamation.c
$(XTCC) -c $(SRCDIR)/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)/sqlite3.h $(SRCDIR)/../win/Makefile.mingw.mistachkin
$(XTCC) $(SHELL_OPTIONS) $(SHELL_CFLAGS) -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)/miniz.o: $(SRCDIR)/miniz.c
$(XTCC) $(MINIZ_OPTIONS) -c $(SRCDIR)/miniz.c -o $@
|
Changes to win/Makefile.msc.
| ︙ | ︙ | |||
89 90 91 92 93 94 95 96 97 | FOSSIL_ENABLE_TH1_HOOKS = 0 !endif # Enable support for Windows XP with Visual Studio 201x? !ifndef FOSSIL_ENABLE_WINXP FOSSIL_ENABLE_WINXP = 0 !endif !if $(FOSSIL_ENABLE_SSL)!=0 | > > > > > | | 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | FOSSIL_ENABLE_TH1_HOOKS = 0 !endif # Enable support for Windows XP with Visual Studio 201x? !ifndef FOSSIL_ENABLE_WINXP FOSSIL_ENABLE_WINXP = 0 !endif # Enable support for the SQLite Encryption Extension? !ifndef USE_SEE USE_SEE = 0 !endif !if $(FOSSIL_ENABLE_SSL)!=0 SSLDIR = $(B)\compat\openssl-1.0.2h SSLINCDIR = $(SSLDIR)\inc32 !if $(FOSSIL_DYNAMIC_BUILD)!=0 SSLLIBDIR = $(SSLDIR)\out32dll !else SSLLIBDIR = $(SSLDIR)\out32 !endif SSLLFLAGS = /nologo /opt:ref /debug |
| ︙ | ︙ | |||
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 |
TCC = $(TCC) /DFOSSIL_ENABLE_TCL_STUBS=1
RCC = $(RCC) /DFOSSIL_ENABLE_TCL_STUBS=1
TCC = $(TCC) /DFOSSIL_ENABLE_TCL_PRIVATE_STUBS=1
RCC = $(RCC) /DFOSSIL_ENABLE_TCL_PRIVATE_STUBS=1
TCC = $(TCC) /DUSE_TCL_STUBS=1
RCC = $(RCC) /DUSE_TCL_STUBS=1
!endif
SQLITE_OPTIONS = /DNDEBUG=1 \
/DSQLITE_OMIT_LOAD_EXTENSION=1 \
/DSQLITE_ENABLE_LOCKING_STYLE=0 \
/DSQLITE_THREADSAFE=0 \
/DSQLITE_DEFAULT_FILE_FORMAT=4 \
/DSQLITE_OMIT_DEPRECATED \
/DSQLITE_ENABLE_EXPLAIN_COMMENTS \
/DSQLITE_ENABLE_FTS4 \
/DSQLITE_ENABLE_FTS3_PARENTHESIS \
/DSQLITE_ENABLE_DBSTAT_VTAB \
/DSQLITE_ENABLE_JSON1 \
/DSQLITE_ENABLE_FTS5 \
/DSQLITE_WIN32_NO_ANSI
SHELL_OPTIONS = /Dmain=sqlite3_shell \
/DSQLITE_OMIT_LOAD_EXTENSION=1 \
/DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
/DSQLITE_SHELL_DBNAME_PROC=fossil_open \
/Daccess=file_access \
/Dsystem=fossil_system \
/Dgetenv=fossil_getenv \
/Dfopen=fossil_fopen
| > > > > > > > | 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 |
TCC = $(TCC) /DFOSSIL_ENABLE_TCL_STUBS=1
RCC = $(RCC) /DFOSSIL_ENABLE_TCL_STUBS=1
TCC = $(TCC) /DFOSSIL_ENABLE_TCL_PRIVATE_STUBS=1
RCC = $(RCC) /DFOSSIL_ENABLE_TCL_PRIVATE_STUBS=1
TCC = $(TCC) /DUSE_TCL_STUBS=1
RCC = $(RCC) /DUSE_TCL_STUBS=1
!endif
!if $(USE_SEE)!=0
TCC = $(TCC) /DUSE_SEE=1
RCC = $(RCC) /DUSE_SEE=1
!endif
SQLITE_OPTIONS = /DNDEBUG=1 \
/DSQLITE_OMIT_LOAD_EXTENSION=1 \
/DSQLITE_ENABLE_LOCKING_STYLE=0 \
/DSQLITE_LIKE_DOESNT_MATCH_BLOBS=1 \
/DSQLITE_THREADSAFE=0 \
/DSQLITE_DEFAULT_FILE_FORMAT=4 \
/DSQLITE_OMIT_DEPRECATED \
/DSQLITE_ENABLE_EXPLAIN_COMMENTS \
/DSQLITE_ENABLE_FTS4 \
/DSQLITE_ENABLE_FTS3_PARENTHESIS \
/DSQLITE_ENABLE_DBSTAT_VTAB \
/DSQLITE_ENABLE_JSON1 \
/DSQLITE_ENABLE_FTS5 \
/DSQLITE_WIN32_NO_ANSI
SHELL_OPTIONS = /Dmain=sqlite3_shell \
/DSQLITE_SHELL_IS_UTF8=1 \
/DSQLITE_OMIT_LOAD_EXTENSION=1 \
/DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
/DSQLITE_SHELL_DBNAME_PROC=fossil_open \
/Daccess=file_access \
/Dsystem=fossil_system \
/Dgetenv=fossil_getenv \
/Dfopen=fossil_fopen
|
| ︙ | ︙ | |||
359 360 361 362 363 364 365 366 367 368 369 370 371 372 |
doc_.c \
encode_.c \
event_.c \
export_.c \
file_.c \
finfo_.c \
foci_.c \
fusefs_.c \
glob_.c \
graph_.c \
gzip_.c \
http_.c \
http_socket_.c \
http_ssl_.c \
| > | 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 |
doc_.c \
encode_.c \
event_.c \
export_.c \
file_.c \
finfo_.c \
foci_.c \
fshell_.c \
fusefs_.c \
glob_.c \
graph_.c \
gzip_.c \
http_.c \
http_socket_.c \
http_ssl_.c \
|
| ︙ | ︙ | |||
530 531 532 533 534 535 536 537 538 539 540 541 542 543 |
$(OX)\doc$O \
$(OX)\encode$O \
$(OX)\event$O \
$(OX)\export$O \
$(OX)\file$O \
$(OX)\finfo$O \
$(OX)\foci$O \
$(OX)\fusefs$O \
$(OX)\glob$O \
$(OX)\graph$O \
$(OX)\gzip$O \
$(OX)\http$O \
$(OX)\http_socket$O \
$(OX)\http_ssl$O \
| > | 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 |
$(OX)\doc$O \
$(OX)\encode$O \
$(OX)\event$O \
$(OX)\export$O \
$(OX)\file$O \
$(OX)\finfo$O \
$(OX)\foci$O \
$(OX)\fshell$O \
$(OX)\fusefs$O \
$(OX)\glob$O \
$(OX)\graph$O \
$(OX)\gzip$O \
$(OX)\http$O \
$(OX)\http_socket$O \
$(OX)\http_ssl$O \
|
| ︙ | ︙ | |||
710 711 712 713 714 715 716 717 718 719 720 721 722 723 | echo $(OX)\doc.obj >> $@ echo $(OX)\encode.obj >> $@ echo $(OX)\event.obj >> $@ echo $(OX)\export.obj >> $@ echo $(OX)\file.obj >> $@ echo $(OX)\finfo.obj >> $@ echo $(OX)\foci.obj >> $@ echo $(OX)\fusefs.obj >> $@ echo $(OX)\glob.obj >> $@ echo $(OX)\graph.obj >> $@ echo $(OX)\gzip.obj >> $@ echo $(OX)\http.obj >> $@ echo $(OX)\http_socket.obj >> $@ echo $(OX)\http_ssl.obj >> $@ | > | 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 | echo $(OX)\doc.obj >> $@ echo $(OX)\encode.obj >> $@ echo $(OX)\event.obj >> $@ echo $(OX)\export.obj >> $@ echo $(OX)\file.obj >> $@ echo $(OX)\finfo.obj >> $@ echo $(OX)\foci.obj >> $@ echo $(OX)\fshell.obj >> $@ echo $(OX)\fusefs.obj >> $@ echo $(OX)\glob.obj >> $@ echo $(OX)\graph.obj >> $@ echo $(OX)\gzip.obj >> $@ echo $(OX)\http.obj >> $@ echo $(OX)\http_socket.obj >> $@ echo $(OX)\http_ssl.obj >> $@ |
| ︙ | ︙ | |||
827 828 829 830 831 832 833 | mkversion$E: $(SRCDIR)\mkversion.c $(BCC) $** codecheck1$E: $(SRCDIR)\codecheck1.c $(BCC) $** | > > > | > > > | > > > | > > > | | 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 | mkversion$E: $(SRCDIR)\mkversion.c $(BCC) $** codecheck1$E: $(SRCDIR)\codecheck1.c $(BCC) $** !if $(USE_SEE)!=0 SQLITE3_SHELL_SRC = $(SRCDIR)\shell-see.c !else SQLITE3_SHELL_SRC = $(SRCDIR)\shell.c !endif $(OX)\shell$O : $(SQLITE3_SHELL_SRC) $B\win\Makefile.msc $(TCC) /Fo$@ $(SHELL_OPTIONS) $(SQLITE_OPTIONS) $(SHELL_CFLAGS) -c $(SQLITE3_SHELL_SRC) !if $(USE_SEE)!=0 SQLITE3_SRC = $(SRCDIR)\sqlite3-see.c !else SQLITE3_SRC = $(SRCDIR)\sqlite3.c !endif $(OX)\sqlite3$O : $(SQLITE3_SRC) $B\win\Makefile.msc $(TCC) /Fo$@ -c $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) $(SEE_FLAGS) $(SQLITE3_SRC) $(OX)\th$O : $(SRCDIR)\th.c $(TCC) /Fo$@ -c $** $(OX)\th_lang$O : $(SRCDIR)\th_lang.c $(TCC) /Fo$@ -c $** |
| ︙ | ︙ | |||
1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 | translate$E $** > $@ $(OX)\foci$O : foci_.c foci.h $(TCC) /Fo$@ -c foci_.c foci_.c : $(SRCDIR)\foci.c translate$E $** > $@ $(OX)\fusefs$O : fusefs_.c fusefs.h $(TCC) /Fo$@ -c fusefs_.c fusefs_.c : $(SRCDIR)\fusefs.c translate$E $** > $@ | > > > > > > | 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 | translate$E $** > $@ $(OX)\foci$O : foci_.c foci.h $(TCC) /Fo$@ -c foci_.c foci_.c : $(SRCDIR)\foci.c translate$E $** > $@ $(OX)\fshell$O : fshell_.c fshell.h $(TCC) /Fo$@ -c fshell_.c fshell_.c : $(SRCDIR)\fshell.c translate$E $** > $@ $(OX)\fusefs$O : fusefs_.c fusefs.h $(TCC) /Fo$@ -c fusefs_.c fusefs_.c : $(SRCDIR)\fusefs.c translate$E $** > $@ |
| ︙ | ︙ | |||
1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 | doc_.c:doc.h \ encode_.c:encode.h \ event_.c:event.h \ export_.c:export.h \ file_.c:file.h \ finfo_.c:finfo.h \ foci_.c:foci.h \ fusefs_.c:fusefs.h \ glob_.c:glob.h \ graph_.c:graph.h \ gzip_.c:gzip.h \ http_.c:http.h \ http_socket_.c:http_socket.h \ http_ssl_.c:http_ssl.h \ | > | 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 | doc_.c:doc.h \ encode_.c:encode.h \ event_.c:event.h \ export_.c:export.h \ file_.c:file.h \ finfo_.c:finfo.h \ foci_.c:foci.h \ fshell_.c:fshell.h \ fusefs_.c:fusefs.h \ glob_.c:glob.h \ graph_.c:graph.h \ gzip_.c:gzip.h \ http_.c:http.h \ http_socket_.c:http_socket.h \ http_ssl_.c:http_ssl.h \ |
| ︙ | ︙ |
Changes to win/fossil.rc.
| ︙ | ︙ | |||
159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
#else
VALUE "TclPrivateStubsEnabled", "No\0"
#endif /* defined(FOSSIL_ENABLE_TCL_PRIVATE_STUBS) */
#endif /* defined(FOSSIL_ENABLE_TCL) */
#if defined(FOSSIL_ENABLE_JSON)
VALUE "JsonEnabled", "Yes, cson " FOSSIL_JSON_API_VERSION "\0"
#endif /* defined(FOSSIL_ENABLE_JSON) */
VALUE "MarkdownEnabled", "Yes\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 0x4b0
END
| > > > > > | 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
#else
VALUE "TclPrivateStubsEnabled", "No\0"
#endif /* defined(FOSSIL_ENABLE_TCL_PRIVATE_STUBS) */
#endif /* defined(FOSSIL_ENABLE_TCL) */
#if defined(FOSSIL_ENABLE_JSON)
VALUE "JsonEnabled", "Yes, cson " FOSSIL_JSON_API_VERSION "\0"
#endif /* defined(FOSSIL_ENABLE_JSON) */
#if defined(USE_SEE)
VALUE "UseSeeEnabled", "Yes\0"
#else
VALUE "UseSeeEnabled", "No\0"
#endif /* defined(USE_SEE) */
VALUE "MarkdownEnabled", "Yes\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 0x4b0
END
|
| ︙ | ︙ |
Changes to win/include/dirent.h.
1 | /* | | > < | | < < < < < < < < < < < < < < < < < | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | /* * Dirent interface for Microsoft Visual Studio * Version 1.21 * * Copyright (C) 2006-2012 Toni Ronkko * This file is part of dirent. Dirent may be freely distributed * under the MIT license. For all details and documentation, see * https://github.com/tronkko/dirent */ #ifndef DIRENT_H #define DIRENT_H /* * Define architecture flags so we don't need to include windows.h. * Avoiding windows.h makes it simpler to use windows sockets in conjunction |
| ︙ | ︙ | |||
58 59 60 61 62 63 64 | #define _DIRENT_HAVE_D_NAMLEN /* Entries missing from MSVC 6.0 */ #if !defined(FILE_ATTRIBUTE_DEVICE) # define FILE_ATTRIBUTE_DEVICE 0x40 #endif | | | > > | > > | > > | > > | > > | > > | > > | > > | > > | > > | > > | > | | > > > > | > > > > | > > > > | > > > > | > > > > | > > > > | > > > > | > > > > | | | | | | | | | > | > > | > > | > > | > > | > > | > > | > > | > > | > | > > > | > > | > | > > | > | > > | > > | > > | > > | > | > > > | > > | | 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 |
#define _DIRENT_HAVE_D_NAMLEN
/* Entries missing from MSVC 6.0 */
#if !defined(FILE_ATTRIBUTE_DEVICE)
# define FILE_ATTRIBUTE_DEVICE 0x40
#endif
/* File type and permission flags for stat(), general mask */
#if !defined(S_IFMT)
# define S_IFMT _S_IFMT
#endif
/* Directory bit */
#if !defined(S_IFDIR)
# define S_IFDIR _S_IFDIR
#endif
/* Character device bit */
#if !defined(S_IFCHR)
# define S_IFCHR _S_IFCHR
#endif
/* Pipe bit */
#if !defined(S_IFFIFO)
# define S_IFFIFO _S_IFFIFO
#endif
/* Regular file bit */
#if !defined(S_IFREG)
# define S_IFREG _S_IFREG
#endif
/* Read permission */
#if !defined(S_IREAD)
# define S_IREAD _S_IREAD
#endif
/* Write permission */
#if !defined(S_IWRITE)
# define S_IWRITE _S_IWRITE
#endif
/* Execute permission */
#if !defined(S_IEXEC)
# define S_IEXEC _S_IEXEC
#endif
/* Pipe */
#if !defined(S_IFIFO)
# define S_IFIFO _S_IFIFO
#endif
/* Block device */
#if !defined(S_IFBLK)
# define S_IFBLK 0
#endif
/* Link */
#if !defined(S_IFLNK)
# define S_IFLNK 0
#endif
/* Socket */
#if !defined(S_IFSOCK)
# define S_IFSOCK 0
#endif
/* Read user permission */
#if !defined(S_IRUSR)
# define S_IRUSR S_IREAD
#endif
/* Write user permission */
#if !defined(S_IWUSR)
# define S_IWUSR S_IWRITE
#endif
/* Execute user permission */
#if !defined(S_IXUSR)
# define S_IXUSR 0
#endif
/* Read group permission */
#if !defined(S_IRGRP)
# define S_IRGRP 0
#endif
/* Write group permission */
#if !defined(S_IWGRP)
# define S_IWGRP 0
#endif
/* Execute group permission */
#if !defined(S_IXGRP)
# define S_IXGRP 0
#endif
/* Read others permission */
#if !defined(S_IROTH)
# define S_IROTH 0
#endif
/* Write others permission */
#if !defined(S_IWOTH)
# define S_IWOTH 0
#endif
/* Execute others permission */
#if !defined(S_IXOTH)
# define S_IXOTH 0
#endif
/* Maximum length of file name */
#if !defined(PATH_MAX)
# define PATH_MAX MAX_PATH
#endif
#if !defined(FILENAME_MAX)
# define FILENAME_MAX MAX_PATH
#endif
#if !defined(NAME_MAX)
# define NAME_MAX FILENAME_MAX
#endif
/* File type flags for d_type */
#define DT_UNKNOWN 0
#define DT_REG S_IFREG
#define DT_DIR S_IFDIR
#define DT_FIFO S_IFIFO
#define DT_SOCK S_IFSOCK
#define DT_CHR S_IFCHR
#define DT_BLK S_IFBLK
#define DT_LNK S_IFLNK
/* Macros for converting between st_mode and d_type */
#define IFTODT(mode) ((mode) & S_IFMT)
#define DTTOIF(type) (type)
/*
* File type macros. Note that block devices, sockets and links cannot be
* distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
* only defined for compatibility. These macros should always return false
* on Windows.
*/
#if !defined(S_ISFIFO)
# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
#endif
#if !defined(S_ISDIR)
# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#endif
#if !defined(S_ISREG)
# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
#endif
#if !defined(S_ISLNK)
# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
#endif
#if !defined(S_ISSOCK)
# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
#endif
#if !defined(S_ISCHR)
# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
#endif
#if !defined(S_ISBLK)
# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
#endif
/* Return the exact length of d_namlen without zero terminator */
#define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
/* Return number of bytes needed to store d_namlen */
#define _D_ALLOC_NAMLEN(p) (PATH_MAX)
#ifdef __cplusplus
extern "C" {
#endif
/* Wide-character version */
struct _wdirent {
/* Always zero */
long d_ino;
/* Structure size */
unsigned short d_reclen;
/* Length of name without \0 */
size_t d_namlen;
/* File type */
int d_type;
/* File name */
wchar_t d_name[PATH_MAX];
};
typedef struct _wdirent _wdirent;
struct _WDIR {
/* Current directory entry */
struct _wdirent ent;
/* Private file data */
WIN32_FIND_DATAW data;
/* True if data is valid */
int cached;
/* Win32 search handle */
HANDLE handle;
/* Initial directory name */
wchar_t *patt;
};
typedef struct _WDIR _WDIR;
static _WDIR *_wopendir (const wchar_t *dirname);
static struct _wdirent *_wreaddir (_WDIR *dirp);
static int _wclosedir (_WDIR *dirp);
static void _wrewinddir (_WDIR* dirp);
/* For compatibility with Symbian */
#define wdirent _wdirent
#define WDIR _WDIR
#define wopendir _wopendir
#define wreaddir _wreaddir
#define wclosedir _wclosedir
#define wrewinddir _wrewinddir
/* Multi-byte character versions */
struct dirent {
/* Always zero */
long d_ino;
/* Structure size */
unsigned short d_reclen;
/* Length of name without \0 */
size_t d_namlen;
/* File type */
int d_type;
/* File name */
char d_name[PATH_MAX];
};
typedef struct dirent dirent;
struct DIR {
struct dirent ent;
struct _WDIR *wdirp;
};
|
| ︙ | ︙ |
Changes to www/branching.wiki.
1 2 3 4 5 6 | <title>Branching, Forking, Merging, and Tagging</title> <h2>Background</h2> In a simple and perfect world, the development of a project would proceed linearly, as shown in figure 1. | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <title>Branching, Forking, Merging, and Tagging</title> <h2>Background</h2> In a simple and perfect world, the development of a project would proceed linearly, as shown in figure 1. <table border=1 cellpadding=10 hspace=10 vspace=10 align="center"> <tr><td align="center"> <img src="branch01.gif" width=280 height=68><br> Figure 1 </td></tr></table> Each circle represents a check-in. For the sake of clarity, the check-ins are given small consecutive numbers. In a real system, of course, the check-in numbers would be 40-character SHA1 hashes since it is not possible to allocate collision-free sequential numbers in a distributed system. But as sequential numbers are easier to read, we will substitute them for the 40-character SHA1 hashes in this document. |
| ︙ | ︙ | |||
36 37 38 39 40 41 42 | it has no descendants. (We will give a more precise definition later of "leaf.") Alas, reality often interferes with the simple linear development of a project. Suppose two programmers make independent modifications to check-in 2. After both changes are committed, the check-in graph looks like figure 2: | | | | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | it has no descendants. (We will give a more precise definition later of "leaf.") Alas, reality often interferes with the simple linear development of a project. Suppose two programmers make independent modifications to check-in 2. After both changes are committed, the check-in graph looks like figure 2: <table border=1 cellpadding=10 hspace=10 vspace=10 align="center"> <tr><td align="center"> <img src="branch02.gif" width=210 height=140><br> Figure 2 </td></tr></table> The graph in figure 2 has two leaves: check-ins 3 and 4. Check-in 2 has two children, check-ins 3 and 4. We call this state a <i>fork</i>. Fossil tries to prevent forks. Suppose two programmers named Alice and Bob are each editing check-in 2 separately. Alice finishes her edits first and commits her changes, resulting in check-in 3. Later, when Bob |
| ︙ | ︙ | |||
75 76 77 78 79 80 81 | graphs with a single leaf. To resolve this situation, Alice can use the fossil <b>merge</b> command to merge in Bob's changes in her local copy of check-in 3. Then she can commit the results as check-in 5. This results in a DAG as shown in figure 3. | | | | 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | graphs with a single leaf. To resolve this situation, Alice can use the fossil <b>merge</b> command to merge in Bob's changes in her local copy of check-in 3. Then she can commit the results as check-in 5. This results in a DAG as shown in figure 3. <table border=1 cellpadding=10 hspace=10 vspace=10 align="center"> <tr><td align="center"> <img src="branch03.gif" width=282 height=152><br> Figure 3 </td></tr></table> Check-in 5 is a child of check-in 3 because it was created by editing check-in 3. But check-in 5 also inherits the changes from check-in 4 by virtue of the merge. So we say that check-in 5 is a <i>merge child</i> of check-in 4 and that it is a <i>direct child</i> of check-in 3. The graph is now back to a single leaf (check-in 5). |
| ︙ | ︙ | |||
122 123 124 125 126 127 128 | development and another leaf that is the latest version that has been tested. When multiple leaves are desirable, we call this <i>branching</i> instead of <i>forking</i>. Figure 4 shows an example of a project where there are two branches, one for development work and another for testing. | | | | 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | development and another leaf that is the latest version that has been tested. When multiple leaves are desirable, we call this <i>branching</i> instead of <i>forking</i>. Figure 4 shows an example of a project where there are two branches, one for development work and another for testing. <table border=1 cellpadding=10 hspace=10 vspace=10 align="center"> <tr><td align="center"> <img src="branch04.gif" width=426 height=123><br> Figure 4 </td></tr></table> The hypothetical scenario of figure 4 is this: The project starts and progresses to a point where (at check-in 2) it is ready to enter testing for its first release. In a real project, of course, there might be hundreds or thousands of check-ins before a project reaches this point, but for simplicity of presentation we will say that the project is ready after check-in 2. |
| ︙ | ︙ | |||
162 163 164 165 166 167 168 | <a name="tags"></a> <h2>Tags And Properties</h2> Tags and properties are used in fossil to help express the intent, and thus to distinguish between forks and branches. Figure 5 shows the same scenario as figure 4 but with tags and properties added: | | | | 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | <a name="tags"></a> <h2>Tags And Properties</h2> Tags and properties are used in fossil to help express the intent, and thus to distinguish between forks and branches. Figure 5 shows the same scenario as figure 4 but with tags and properties added: <table border=1 cellpadding=10 hspace=10 vspace=10 align="center"> <tr><td align="center"> <img src="branch05.gif" width=485 height=177><br> Figure 5 </td></tr></table> A <i>tag</i> is a name that is attached to a check-in. A <i>property</i> is a name/value pair. Internally, fossil implements tags as properties with a NULL value. So, tags and properties really are much the same thing, and henceforth we will use the word "tag" to mean either a tag or a property. |
| ︙ | ︙ |
Changes to www/build.wiki.
| ︙ | ︙ | |||
139 140 141 142 143 144 145 | file "<b>win\buildmsvc.bat</b>" may be used and it will attempt to detect and use the latest installed version of MSVC.<br><br>To enable the optional <a href="https://www.openssl.org/">OpenSSL</a> support, first <a href="https://www.openssl.org/source/">download the official source code for OpenSSL</a> and extract it to an appropriately named "<b>openssl-X.Y.ZA</b>" subdirectory within the local [/tree?ci=trunk&name=compat | compat] directory (e.g. | | | 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | file "<b>win\buildmsvc.bat</b>" may be used and it will attempt to detect and use the latest installed version of MSVC.<br><br>To enable the optional <a href="https://www.openssl.org/">OpenSSL</a> support, first <a href="https://www.openssl.org/source/">download the official source code for OpenSSL</a> and extract it to an appropriately named "<b>openssl-X.Y.ZA</b>" subdirectory within the local [/tree?ci=trunk&name=compat | compat] directory (e.g. "<b>compat/openssl-1.0.2h</b>"), then make sure that some recent <a href="http://www.perl.org/">Perl</a> binaries are installed locally, and finally run one of the following commands: <blockquote><pre> nmake /f Makefile.msc FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin </pre></blockquote> <blockquote><pre> buildmsvc.bat FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin |
| ︙ | ︙ |
Changes to www/changes.wiki.
1 2 | <title>Change Log</title> | > > > > > | > > | < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<title>Change Log</title>
<h2>Changes for Version 1.36 (2016-00-00)</h2>
* Update internal Unicode character tables, used in regular expression
handling, from version 8.0 to 9.0.
<h2>Changes for Version 1.35 (2016-06-14)</h2>
* Enable symlinks by default on all non-Windows platforms.
* Enhance the [/md_rules|Markdown formatting] so that hyperlinks that begin
with "/" are relative to the root of the Fossil repository.
* Rework the [/help?cmd=/setup_ulist|/setup_list page] (the User List page)
to display all users in a click-to-sort table.
* Fix backslash-octal escape on filenames while importing from git
* When markdown documents begin with <h1> HTML elements, use that
header at the document title.
* Added the [/help?cmd=/bigbloblist|/bigbloblist page].
* Enhance the [/help?cmd=/finfo|/finfo page] so that when it is showing
the ancestors of a particular file version, it only shows direct
ancestors and omits changes on branches, thus making it show the same set
|
| ︙ | ︙ | |||
27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
<li>Add tcl_platform(engine) and tcl_platform(platform) array
elements.</li>
</ul>
* Get autosetup working with MinGW.
* Fix autosetup detection of zlib in the source tree.
* Added autosetup detection of OpenSSL when it may be present under the
"compat" subdirectory of the source tree.
<h2>Changes for Version 1.34 (2015-11-02)</h2>
* Make the [/help?cmd=clean|fossil clean] command undoable for files less
than 10MiB.
* Update internal Unicode character tables, used in regular expression
handling, from version 7.0 to 8.0.
| > > > > > > > > > > | 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
<li>Add tcl_platform(engine) and tcl_platform(platform) array
elements.</li>
</ul>
* Get autosetup working with MinGW.
* Fix autosetup detection of zlib in the source tree.
* Added autosetup detection of OpenSSL when it may be present under the
"compat" subdirectory of the source tree.
* Added the [/help?cmd=reparent|fossil reparent] command
* Added --include and --exclude options to [/help?cmd=tarball|fossil tarball]
and [/help?cmd=zip|fossil zip] and the in= and ex= query parameters to the
[/help?cmd=/tarball|/tarball] and [/help?cmd=/zip|/zip] web pages.
* Add support for [./encryptedrepos.wiki|encrypted Fossil repositories].
* If the FOSSIL_PWREADER environment variable is set, then use the program it
names in place of getpass() to read passwords and passphrases
* Option --baseurl now works on Windows.
* Numerious documentation improvements.
* Update the built-in SQLite to version 3.13.0.
<h2>Changes for Version 1.34 (2015-11-02)</h2>
* Make the [/help?cmd=clean|fossil clean] command undoable for files less
than 10MiB.
* Update internal Unicode character tables, used in regular expression
handling, from version 7.0 to 8.0.
|
| ︙ | ︙ |
Changes to www/copyright-release.html.
| ︙ | ︙ | |||
72 73 74 75 76 77 78 | </ul> </ol> <p>By filling in the following information and signing your name, you agree to be bound by all of the terms set forth in this agreement. Please print clearly.</p> | < | | < | 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 |
</ul>
</ol>
<p>By filling in the following information and signing your name,
you agree to be bound by all of the terms
set forth in this agreement. Please print clearly.</p>
<p><table width="80%" border="1" cellpadding="0" cellspacing="0" align="center">
<tr><td width="20%" valign="top">Your name & email:</td><td width="80%">
<!-- Replace this line with your name and email --> <p>
</td></tr>
<tr><td valign="top">Company name:<br>(if applicable)</td><td>
<!-- Replace this line with your company name --> <p>
</td></tr>
<tr><td valign="top">Postal address:</td><td>
<!-- Replace this line and the next line with your postal address -->
<p> </p><p> </p><p> </p>
</td></tr>
<tr><td valign="top">Signature:</td><td> <p> </td></tr>
<tr><td valign="top">Date:</td><td> <p> </td></tr>
</table>
<p>Send completed forms to:
<blockquote>
Hipp, Wyrick & Company, Inc.<br>
6200 Maple Cove Lane<br>
Charlotte, NC 28269-1086<br>
USA
</p>
|
Changes to www/embeddeddoc.wiki.
| ︙ | ︙ | |||
67 68 69 70 71 72 73 | The mimetype (and thus the rendering) of documentation files is determined by the file suffix. Fossil currently understands [/mimetype_list|many different file suffixes], including all the popular ones such as ".css", ".gif", ".htm", ".html", ".jpg", ".jpeg", ".png", and ".txt". Documentation files whose names end in ".wiki" use the | | | 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | The mimetype (and thus the rendering) of documentation files is determined by the file suffix. Fossil currently understands [/mimetype_list|many different file suffixes], including all the popular ones such as ".css", ".gif", ".htm", ".html", ".jpg", ".jpeg", ".png", and ".txt". Documentation files whose names end in ".wiki" use the [/wiki_rules | fossil wiki markup] - a safe subset of HTML together with some wiki rules for paragraph breaks, lists, and hyperlinks. Documentation files ending in ".md" or ".markdown" use the [/md_rules | Markdown markup langauge]. Documentation files ending in ".txt" are plain text. Wiki, markdown, and plain text documentation files are rendered with the standard fossil header and footer added. |
| ︙ | ︙ |
Added www/encryptedrepos.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 | <title>How To Use Encrypted Repositories</title> <h2>Introduction</h2><blockquote> Fossil can be compiled so that it works with encrypted repositories using the [https://www.sqlite.org/see/doc/trunk/www/readme.wiki|SQLite Encryption Extension]. This technical note explains the process. </blockquote> <h2>Building An Encryption-Enabled Fossil</h2><blockquote> The SQLite Encryption Extension (SEE) is proprietary software and requires [http://www.hwaci.com/cgi-bin/see-step1|purchasing a license]. <p> Assuming you have an SEE license, the first step of compiling Fossil to use SEE is to create an SEE-enabled version of the SQLite database source code. This alternative SQLite database source file should be called "sqlite3-see.c" and should be placed in the src/ subfolder of the Fossil sources, right beside the public-domain "sqlite3.c" source file. Also make a copy of the SEE-enabled "shell.c" file, renamed as "shell-see.c", and place it in the src/ subfolder beside the original "shell.c". <p> Add the --with-see command-line option to the configuration script to enable the use of SEE on unix-like systems. <blockquote><pre> ./configure --with-see; make </pre></blockquote> <p>To build for Windows using MSVC, add the "USE_SEE=1" argument to the "nmake" command line. <blockquote><pre> nmake -f makefile.msc USE_SEE=1 </pre></blockquote> </blockquote> <h2>Using Encrypted Repositories</h2><blockquote> Any Fossil repositories whose filename ends with ".efossil" is taken to be an encrypted repository. Fossil will prompt for the encryption password and attempt to open the repository database using that password. <p> Every invocation of fossil on an encrypted repository requires retyping the encryption password. To avoid excess password typing, consider using the "fossil shell" command which prompts for the password just once, then reuses it for each subsequent Fossil command entered at the prompt. <p> On Windows, the "fossil server", "fossil ui", and "fossil shell" commands do not (currently) work on an encrypted repository. </blockquote> <h2>Additional Security</h2><blockquote> Use the FOSSIL_SECURITY_LEVEL environment for additional protection. <blockquote><pre> export FOSSIL_SECURITY_LEVEL=1 </pre></blockquote> A setting of 1 or greater prevents fossil from trying to remember the previous sync password. <blockquote><pre> export FOSSIL_SECURITY_LEVEL=2 </pre></blockquote> A setting of 2 or greater causes all password prompts to be preceeded by a random translation matrix similar to the following: <blockquote><pre> abcde fghij klmno pqrst uvwyz qresw gjymu dpcoa fhkzv inlbt </pre></blockquote> When entering the password, the user must substitute the letter on the second line that corresponds to the letter on the first line. Uppercase substitutes for uppercase inputs, and lowercase substitutes for lowercase inputs. Letters that are not in the translation matrix (digits, punctuation, and "x") are not modified. For example, given the translation matrix above, if the password is "pilot-9crazy-xube", then the user must type "fmpav-9ekqtb-xirw". This simple substitution cypher helps prevent password capture by keyloggers. </blockquote> |
Added www/env-opts.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 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 |
Environment Variables and Global Options
========================================
Fossil uses a number of environment variables and supports a number
of global options. Most of these seem to be primarily documented in
the source code, with the primary exception of `--args` which is
described in the usage text printed by running fossil with no
arguments at all.
Global Options
--------------
The following options are understood by the fossil command itself, and
are collected before any subcommand begins processing.
`--args FILENAME`: Read the file `FILENAME` and replace these two
arguments with its content. Each line of the file is assumed to be an
argument unless it starts with '-' and contains a space, in which case
it is assumed to be another flag and is treated as such. `--args
FILENAME` may be used in conjunction with any other flags.
`--case-sensitive BOOL`: Override the `case-sensitive` setting, which
can override the native preferences of the platform for case sensitive
file names: insensitive on Windows, sensitive on Unix. There are
probably odd interactions possible if you mix case sensitive and case
insensitive file systems on any single platform. This option or the
global setting should be used to force the case sensitivity to the
most sensible condition.
`--chdir DIRECTORY`: Change to the named directory before processing
any commands.
`--comfmtflags NUMBER`: Specify flags that control how check-in comments
and certain other text outputs are formatted for display. The flags are
individual bits in `NUMBER`, which must be specified in base 10:
* _0_ — Uses the revised algorithm with no special handling.
* _1_ — Uses the legacy algorithm, other flags are ignored.
* _2_ — Trims leading and trailing carriage-returns and line-feeds
where they do not materially impact pre-existing formatting
(i.e. at the start of the comment string _and_ right before
line indentation).
* _4_ — Trims leading and trailing spaces where they do not materially
impact the pre-existing formatting (i.e. at the start of the
comment string _and_ right before line indentation).
* _8_ — Attempts to break lines on word boundaries while honoring the
logical line length.
* _16_ — Looks for the original comment text within the text being
printed. Upon matching, a new line will be emitted, thus
preserving more of the pre-existing formatting.
`--errorlog ERRLOG`: Name a file to which fossil will log panics,
errors, and warnings.
`--help`: If `--help` is found anywhere on the command line, translate
the command to `fossil help cmdname` where `cmdname` is the first
argument that does not begin with a `-` character. If all arguments
start with `-`, translate to `fossil help argv[1] argv[2]...`.
`--httptrace`: (Sets `g.fHttpTrace`.) Trace outbound HTTP requests.
`--localtime`: Override the `timeline-utc` option to explicitly use
local time.
`--nocgi`: Prevent fossil from acting as a CGI by default even if the
`GATEWAY_INTERFACE` environment variable is set.
`--no-th-hook`: (Sets `g.fNoThHook`.) Override the `th1-hooks` setting
and prevent any TH1 hooks from being executed.
`--quiet`: (Sets `g.fQuiet`.) Cause fossil to suppress various messages and progress
indicators that would otherwise be printed.
`--sqltrace`: (Sets `g.SqlTrace`.) Implies `--sqlstats`. Trace certain
SQLite database activity, especially showing every SQL query
processed.
`--sqlstats`: (Sets `g.fSqlStats`.) Print a number of performance
statistics about each SQLite database used when it is closed.
`--sshtrace`: (Sets `g.fSshTrace`.)
`--ssl-identity SSLIDENTITY`:
`--systemtrace`: (Sets `g.fSystemTrace`.) Trace all commands launched
as sub processes.
`--user LOGIN`: (Sets `g.zLogin`) Also `-U LOGIN`. Set the user name
used with the repository.
`--utc`: Override the `timeline-utc` option to explicitly use
UTC time.
`--vfs VFSNAME`: Load the named VFS into SQLite.
Environment Variables
---------------------
`APPDATA`: (Windows) Location of the `~/.fossil` file. The first
environment variable found in the environment from the list
`FOSSIL_HOME`, `LOCALAPPDATA` (Windows), `APPDATA` (Windows),
`HOMEDRIVE` and `HOMEPATH` (Windows, used together), and `HOME` is
used as the location of the `~/.fossil` file.
`EDITOR`: Name the editor to use for check-in and stash comments.
Overridden by the local or global `editor` setting or the `VISUAL`
environment variable.
`FOSSIL_FORCE_TICKET_MODERATION`: If set, *ALL* changes for tickets
will be required to go through moderation (even those performed by the
local interactive user via the command line). This can be useful for
local (or remote) testing of the moderation subsystem and its impact
on the contents and status of tickets.
`FOSSIL_FORCE_WIKI_MODERATION`: If set, *ALL* changes for wiki pages
will be required to go through moderation (even those performed by the
local interactive user via the command line). This can be useful for
local (or remote) testing of the moderation subsystem and its impact
on the contents and status of wiki pages.
`FOSSIL_HOME`: Location of the `~/.fossil` file. The first environment
variable found in the environment from the list `FOSSIL_HOME`,
`LOCALAPPDATA` (Windows), `APPDATA` (Windows), `HOMEDRIVE` and
`HOMEPATH` (Windows, used together), and `HOME` is used as the
location of the `~/.fossil` file.
`FOSSIL_USER`: Name of the default user account if the checkout, local
or global `default-user` setting is not present. The first environment
variable found in the environment from the list `FOSSIL_USER`, `USER`,
`LOGNAME`, and `USERNAME` is the user name. If none of those are set,
then the default user name is "root". See the discussion of Fossil
Username below for a lot more detail.
`FOSSIL_TCL_PATH`: When Tcl stubs support is configured, point to a
specific file or folder containing the version of Tcl to load at run
time.
`FOSSIL_TEMP`: Fallback location of the temporary directories and files
created and deleted when running the test suite. The first environment
variable found in the environment from the list `FOSSIL_TEST_TEMP`,
`FOSSIL_TEMP`, `TEMP`, and `TMP` is used.
`FOSSIL_TEST_DANGEROUS_IGNORE_OPEN_CHECKOUT`: When set to the literal
value `YES_DO_IT`, the test suite will relax the constraint that some
tests may not run within an open checkout. This is subject to removal
in the future.
`FOSSIL_TEST_TEMP`: Primary location of the temporary directories
and files created and deleted when running the test suite. The
first environment variable found in the environment from the list
`FOSSIL_TEST_TEMP`, `FOSSIL_TEMP`, `TEMP`, and `TMP` is used.
`FOSSIL_VFS`: Name a VFS to load into SQLite.
`GATEWAY_INTERFACE`: If present and the `--nocgi` option is not, assume
fossil is invoked from a web server as a CGI command, and act
accordingly.
`HOME`: Location of the `~/.fossil` file. The first environment
variable found in the environment from the list `FOSSIL_HOME`,
`LOCALAPPDATA` (Windows), `APPDATA` (Windows), `HOMEDRIVE` and
`HOMEPATH` (Windows, used together), and `HOME` is used as the
location of the `~/.fossil` file.
`HOMEDRIVE`, `HOMEPATH`: (Windows) Location of the `~/.fossil` file.
The first environment variable found in the environment from the list
`FOSSIL_HOME`, `LOCALAPPDATA` (Windows), `APPDATA` (Windows),
`HOMEDRIVE` and `HOMEPATH` (Windows, used together), and `HOME` is
used as the location of the `~/.fossil` file.
`HTTP_HOST`: If defined, included in error log messages.
`http_proxy`: If the global or local settings `proxy` is not set, this
is used as the default value for the `proxy` setting.
`HTTP_USER_AGENT`: If defined, included in error log messages.
`LOCALAPPDATA`: (Windows) Location of the `~/.fossil` file. The first
environment variable found in the environment from the list
`FOSSIL_HOME`, `LOCALAPPDATA` (Windows), `APPDATA` (Windows),
`HOMEDRIVE` and `HOMEPATH` (Windows, used together), and `HOME` is
used as the location of the `~/.fossil` file.
`LOGNAME`: Name of the logged in user on many Unix-like platforms.
Used as the fossil user name if `FOSSIL_USER` is not specified. See
the discussion of Fossil Username below for a lot more detail.
`PATH`: Used by most platforms to locate programs invoked without a
fully qualified name. Explicitly used by `fossil ui` on certain platforms
to choose the browser to launch.
`PATH_INFO`: If defined, included in error log messages.
`QUERY_STRING`: If defined, included in error log messages.
`REMOTE_ADDR`: If defined, included in error log messages.
`REMOTE_HOST`: Used by `fossil http` run from `stunnel` to identify
the remote host.
`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`.
`SYSTEMROOT`: (Windows) Used to locate `notepad.exe` as a
fall back comment editor.
`TEMP`: On Windows, the location of temporary files. The first
environment variable found in the environment that names an existing
directory from the list `TMP`, `TEMP`, `USERPROFILE`, the Windows
directory (usually `C:\WINDOWS`), `TEMP`, `TMP`, and the current
directory (aka `.`) is the temporary folder.
`TERM`: If the linenoise library is used (almost certainly not on
Windows), it will check `TERM` to verify that the interactive terminal
is not named on a short list on terminals known to not work with
linenoise. Linenoise is a library that provides command history and
command line editing to interactive programs, and can be used in the
`fossil sqlite3` command.
`TH1_DELETE_INTERP`: Set this variable to ask fossil to explicitly
delete the TH1 interpreter, if it is loaded, then check that it
released all of its allocated memory, when exiting fossil. This is not
strictly necessary, but makes debugging memory leaks easier. See
[main.c near line 386](/artifact/e75796be5338a81c?ln=386,391) for the
code.
`TH1_ENABLE_DOCS`: Override the local or global setting `tcl-docs`
to enable TH1 documents in fossil.
`TH1_ENABLE_HOOKS`: Override the local or global setting `tcl-hooks`
to enable TH1 hooks in fossil.
`TH1_ENABLE_TCL`: Override the local or global setting `tcl` to enable
Tcl in fossil.
`TMP`: On Windows, the location of temporary files. The first
environment variable found in the environment that names an existing
directory from the list `TMP`, `TEMP`, `USERPROFILE`, the Windows
directory (usually `C:\WINDOWS`), `TEMP`, `TMP`, and the current
directory (aka `.`) is the temporary folder.
`TMPDIR`: Names the temporary file location for SQLite.
`USER`: Name of the logged in user on many Unix-like platforms.
Used as the fossil user name if `FOSSIL_USER` is not specified. See
the discussion of Fossil Username below for a lot more detail.
`USERNAME`: Name of the logged in user on Windows platforms.
Used as the fossil user name if `FOSSIL_USER` is not specified. See
the discussion of Fossil Username below for a lot more detail.
`USERPROFILE`: On Windows, the location of temporary files. The first
environment variable found in the environment that names an existing
directory from the list `TMP`, `TEMP`, `USERPROFILE`, the Windows
directory (usually `C:\WINDOWS`), `TEMP`, `TMP`, and the current
directory (aka `.`) is the temporary folder.
`VISUAL`: Name the editor to use for check-in and stash comments.
Overrides the `EDITOR` environment variable. Overridden by the local
or global `editor` setting.
Notes on Related Values
-----------------------
### CGI and JSON Parameters
The JSON API implementation looks up many values in the first of
several places searched. This unifies the parameter handling logic,
allows the caller to choose whether to prefer URL parameters, request
headers, or the POST payload, and allows the `fossil json` command to
share most of the same logic as the `/json` API path. The search order
is a POST payload, GET/COOKIE/non-JSON POST, JSON POST, the system
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
operation will be aborted if `notepad.exe` is not found in the Windows
folder.
On Unix-like platforms, if no editor is named, then a message is
displayed on stdout, and stdin is read until a single line containing
only a dot is seen.
### Error logging
If logging errors to a file, fossil will include the values of the
following environment variables in the error log entry if they are
defined: `HTTP_HOST`, `HTTP_USER_AGENT`, `PATH_INFO`, `QUERY_STRING`,
`REMOTE_ADDR`, `REQUEST_METHOD`, `REQUEST_URI`, and `SCRIPT_NAME`.
### Fossil Username
In absence of any explicit setting, fossil will use the same name you
logged in to your platform with, as the user name when interacting
with local and remote repositories. Note that only the name is shared,
fossil makes no attempt to share or leverage any platform's
authentication mechanisms or passwords.
When logging in to a repository, it tries a series of sources for the
user name, and the first non-blank name that succeeds is the logged in
user. The order is:
1. The --user and -U command-line options.
2. If running within an open checkout (the local database is open),
check in its table of values stored per open checkout for the
value stored by `fossil user default USERNAME`.
3. The default user in the repository (setting `default-user`)
4. The `FOSSIL_USER` environment variable.
5. The `USER` environment variable.
6. The `LOGNAME` environment variable.
7. The `USERNAME` environment variable.
8. Check if the user can be extracted from the remote URL, if
there is a remote URL.
Items 2 and 3 are both set by `fossil user default USERNAME`, the
first within an open checkout, the second outside and using the `-R
REPOSITORY` option to identify the repository. Both cases require that
the named user be present in the repository when the default user is
assigned. Although the default user is internally stored as if it were
a setting named `default-user`, it is not accessible through
the `fossil set` command.
Items 5, 6, and 7 cover most of the names of an environment variable
set automatically by the platform with the name of the platform's
logged in user for use by programs. Historically, `USER` comes from
Unix System-V, `LOGNAME` from BSD, and `USERNAME` from Windows, but
many Linux distributions will set both `USER` and `LOGNAME` for broad
compatibility.
When creating a new repository, fossil needs a user name for the admin
user granted the "s" permission. But since fossil generally expects
that `fossil new` or `fossil clone` are used outside of any checkout
(especially when run for the first time without any checkouts at all
or the users's global settings database), it looks in a shorter list
of places for a non-blank name. In the special case of a clone,
`default-user` can be copied from the original, and so it can be set
in the clone even before any users have been created, and in that case
it will be the new admin user. If `default-user` is not set, then the
first found environment variable from the list `FOSSIL_USER`, `USER`,
`LOGNAME`, and `USERNAME`, is the user name. As a final fallback, if
none of those are set, then the default user name is "root".
### Home Directory
Fossil keeps some information interesting to each user in the user's
home directory. This includes the global settings and the list of
repositories and checkouts used by `fossil all`.
The user's home directory is specified by the first environment
variable found in the environment from the list `FOSSIL_HOME`,
`LOCALAPPDATA` (Windows), `APPDATA` (Windows), `HOMEDRIVE` and
`HOMEPATH` (Windows, used together), and `HOME`.
SQLite has its own notion of the user's home directory, which is only
exposed if the interactive SQL shell is run with the "fossil
sqlite3" command. Being a separate library, SQLite uses many of the
same variables to find the home directory, but uses them in a
different order, and does not use the `FOSSIL_HOME` variable at all.
### SQLite VFS to use
See [the SQLite documentation](http://www.sqlite.org/vfs.html) for an
explanation of what a VFS actually is and what it does.
If the default VFS underneath SQLite is not suitable, an alternative
can be selected with either the `--vfs VFSNAME` option or the
`FOSSIL_VFS` environment variable. The `--vfs` option takes
precedence.
### Temporary File Location
Fossil places some temporary files in the current directory, notably
supporting files related to merge conflicts are placed in the same
folder as the merge result.
Other temporary files need a home. On Unix-like systems, the first
folder from the hard coded list `/var/tmp`, `/usr/tmp`, `/tmp`,
`/temp`, and `.` that is found to exist in the file system is used by
fossil. The SQLite library has its own code for finding a safe place for
temporary files. It checks the environment variables `SQLITE_TMPDIR`
and `TMPDIR` ahead of the hard coded list `/var/tmp`, `/usr/tmp`,
`/tmp`, and `.` for the first directory that exists.
On Windows, fossil calls [`GetTempPath`][gtp], and also queries the
environment variables `TEMP`, and `TMP`. If none of those three places
exist, then it uses `.`. Notice that `GetTempPath` itself used `TMP`,
`TEMP`, `USERPROFILE`, and the Windows folder (named in the variable
`SystemRoot`). Since the Windows folder always exists, but in modern
versions of Windows is generally *not* writable by the logged in user,
not having `TEMP`, `TMP`, or `USERPROFILE` set is almost guaranteed to
cause trouble.
[gtp]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364992%28v=vs.85%29.aspx
That said, it is not unusual for utilities on all platforms to assume
that `TEMP` or `TMP` point somewhere safe for temporary files.
If the identified temporary folder is not writable, then weird things
will happen on all platforms.
### Web browser
Occasionally, fossil wants to launch a web browser for the user, most
obviously as part of the `fossil ui` command. In that specific case,
the browser is launched pointing at the web server started by `fossil
ui` listening on a private TCP port.
On all platforms, if the local or global settings `web-browser` is
set, that is the command used to open an URL.
Otherwise, the specific actions vary by platform.
On Unix-like platforms other than Apple's, it looks for the first
program from the list `xdg-open`, `gnome-open`, `firefox`, and
`google-chrome` that it can find on the `PATH`.
On Apple platforms, it assumes that `open` is the command to open an
URL in the user's configured default browser.
On Windows platforms, it assumes that `start` is the command to open
an URL in the user's configured default browser.
|
Changes to www/faq.wiki.
| ︙ | ︙ | |||
23 24 25 26 27 28 29 | <blockquote> <b>fossil [/help/ui|ui]</b> <i>REPOSITORY-FILENAME</i> </blockquote> And your default web browser should pop up and automatically point to the fossil interface. (Hint: You can omit the <i>REPOSITORY-FILENAME</i> | | > > > | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | <blockquote> <b>fossil [/help/ui|ui]</b> <i>REPOSITORY-FILENAME</i> </blockquote> And your default web browser should pop up and automatically point to the fossil interface. (Hint: You can omit the <i>REPOSITORY-FILENAME</i> if you are within an open check-out.) See also: [http://fuelscm.org/] </blockquote></li> <a name="q2"></a> <p><b>(2) What is the difference between a "branch" and a "fork"?</b></p> <blockquote>This is a big question - too big to answer in a FAQ. Please read the <a href="branching.wiki">Branching, Forking, Merging, and Tagging</a> document.</blockquote></li> |
| ︙ | ︙ |
Changes to www/fossil-v-git.wiki.
1 2 3 4 5 6 7 8 | <title>Fossil Versus Git</title> <h2>1.0 Don't Stress!</h2> If you start out using one DVCS and later decide you like the other better, you can easily [./inout.wiki | move your content]¹. Fossil and [http://git-scm.com | Git] are very similar in many respects, | | | | | | | | | | | | | | | | 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 |
<title>Fossil Versus Git</title>
<h2>1.0 Don't Stress!</h2>
If you start out using one DVCS and later decide you like the other better,
you can easily [./inout.wiki | move your content]¹.
Fossil and [http://git-scm.com | Git] are very similar in many respects,
but they also have important differences.
See the table below for
a high-level summary and the text that follows for more details.
Keep in mind that you are reading this on a Fossil website,
so the information here
might be biased in favor of Fossil. Ask around with people who have
used both Fossil and Git for other opinions.
¹<small><i>Git does not support
wiki, tickets, or tech-notes, so those elements will not transfer when
exporting from Fossil to Git.</i></small>
<h2>2.0 Executive Summary:</h2>
<blockquote><table border=1 cellpadding=5 align=center>
<tr><th width="50%">GIT</th><th width="50%">FOSSIL</th></tr>
<tr><td>File versioning only</td>
<td>Versioning, Tickets, Wiki, and Technotes</td></tr>
<tr><td>Ad-hoc, pile-of-files key/value database</td>
<td>Relational SQL database</td></tr>
<tr><td>Bazaar-style development</td><td>Cathedral-style development</td></tr>
<tr><td>Designed for Linux development</td>
<td>Designed for SQLite development</td></tr>
<tr><td>Lots of little tools</td><td>Stand-alone executable</td></tr>
<tr><td>One check-out per repository</td>
<td>Many check-outs per repository</td></tr>
<tr><td>Remembers what you should have done</td>
<td>Remembers what you actually did</td></tr>
<tr><td>GPL</td><td>BSD</td></tr>
</table></blockquote>
<h2>3.0 Discussion</h2>
<h3>3.1 Feature Set</h3>
Git provides file versioning services only, whereas Fossil adds
integrated [./wikitheory.wiki | wiki],
[./bugtheory.wiki | ticketing & bug tracking],
[./embeddeddoc.wiki | embedded documentation], and
[./event.wiki | Technical notes].
These additional capabilities are available for Git as 3rd-party and/or
user-installed add-ons, but with Fossil they are integrated into
the design. One way to describe Fossil is that it is
"[https://github.com/ | github]-in-a-box".
If you clone Git's self-hosting repository you get just Git's source code.
If you clone Fossil's self-hosting repository, you get the entire
Fossil website - source code, documentation, ticket history, and so forth.
For developers who choose to self-host projects (rather than using a
3rd-party service such as GitHub) Fossil is much easier to set up, since
the stand-alone Fossil executable together with a 2-line CGI script
suffice to instantiate a full-featured developer website. To accomplish
the same using Git requires locating, installing, configuring, integrating,
and managing a wide assortment of separate tools. Standing up a developer
website using Fossil can be done in minutes, whereas doing the same using
Git requires hours or days.
<h3>3.2 Database</h3>
The baseline data structures for Fossil and Git are the same (modulo
formatting details). Both systems store check-ins as immutable
objects referencing their immediate ancestors and named by their SHA1 hash.
The difference is that Git stores its objects as individual files
in the ".git" folder or compressed into
bespoke "pack-files", whereas Fossil stores its objects in a
relational ([https://www.sqlite.org/|SQLite]) database file. To put it
another way, Git uses an ad-hoc pile-of-files key/value database whereas
Fossil uses a proven, general-purpose SQL database. This
difference is more than an implementation detail. It
has important consequences.
With Git, one can easily locate the ancestors of a particular check-in
by following the pointers embedded in the check-in object, but it is
difficult to go the other direction and locate the descendants of a
check-in. It is so difficult, in fact, that neither native Git nor
GitHub provide this capability. With Git, if you are looking at some
historical check-in then you cannot ask
"what came next" or "what are the children of this check-in".
Fossil, on the other hand, parses essential information about check-ins
(parents, children, committers, comments, files changed, etc.)
into a relational database that can be easily
queried using concise SQL statements to find both ancestors and
descendents of a check-in.
Leaf check-ins in Git that lack a "ref" become "detached", making them
difficult to locate and subject to garbage collection. This
"detached head" problem has caused untold grief for countless
Git users. With Fossil, all check-ins are easily located using
a variety of attributes (parents, children, committer, date, full-text
search of the check-in comment) and so detached heads are simply not possible.
The ease with which check-ins can be located and queried in Fossil
has resulted in a huge variety of reports and status screens
([./webpage-ex.md|examples]) that show project state
in ways that help developers
maintain enhanced awareness and comprehension
and avoid errors.
<h3>3.3 Cathedral vs. Bazaar</h3>
Fossil and Git promote different development styles. Git promotes a
"bazaar" development style in which numerous anonymous developers make
small and sometimes haphazard contributions. Fossil
promotes a "cathedral" development model in which the project is
closely supervised by an highly engaged architect and implemented by
a clique of developers.
Nota Bene: This is not to say that Git cannot be used for cathedral-style
development or that Fossil cannot be used for bazaar-style development.
They can be. But those modes are not their design intent nor the their
low-friction path.
Git encourages a style in which individual developers work in relative
isolation, maintaining their
own branches and occasionally rebasing and pushing selected changes up
to the main repository. Developers using Git often have their own
private branches that nobody else ever sees. Work becomes siloed.
This is exactly what one wants when doing bazaar-style development.
Fossil, in contrast, strives to keep all changes from all contributors
mirrored in the main repository (in separate branches) at all times.
Work in progress from one developer is readily visible to all other
|
| ︙ | ︙ | |||
162 163 164 165 166 167 168 | <h3>3.5 Lots of little tools vs. Self-contained system</h3> Git consists of many small tools, each doing one small part of the job, which can be recombined (by experts) to perform powerful operations. Git has a lot of complexity and many dependencies and requires an "installer" script or program to get it running. | | | | | | | | | | | | 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 | <h3>3.5 Lots of little tools vs. Self-contained system</h3> Git consists of many small tools, each doing one small part of the job, which can be recombined (by experts) to perform powerful operations. Git has a lot of complexity and many dependencies and requires an "installer" script or program to get it running. Fossil is a single self-contained stand-alone executable with hardly any dependencies. Fossil can be (and often is) run inside a minimally configured chroot jail. To install Fossil, one merely puts the executable on $PATH. The designer of Git says that the unix philosophy is to have lots of small tools that collaborate to get the job done. The designer of Fossil says that the unix philosophy is "it just works". Both individuals have written their DVCSes to reflect their own view of the "unix philosophy". <h3>3.6 One vs. Many Check-outs per Repository</h3> A "repository" in Git is a pile-of-files in the ".git" subdirectory of a single check-out. The check-out and the repository are inseperable. With Fossil, a "repository" is a single SQLite database file that can be stored anywhere. There can be multiple active check-outs from the same repository, perhaps open on different branches or on different snapshots of the same branch. Long-running tests or builds can be running in one check-out while changes are being committed in another. <h3>3.7 What you should have done vs. What you actually did</h3> Git puts a lot of emphasis on maintaining a "clean" check-in history. Extraneous and experimental branches by individual developers often never make it into the main repository. And branches are often rebased before being pushed, to make it appear as if development had been linear. Git strives to record what the development of a project should have looked like had there been no mistakes. Fossil, in contrast, puts more emphasis on recording exactly what happened, including all of the messy errors, dead-ends, experimental branches, and so forth. One might argue that this makes the history of a Fossil project "messy". But another point of view is that this makes the history "accurate". In actual practice, the superior reporting tools available in Fossil mean that the added "mess" is not a factor. One commentator has mused that Git records history according to the victors, whereas Fossil records history as it actually happened. <h3>3.8 GPL vs. BSD</h3> Git is covered by the GPL license whereas Fossil is covered by a two-clause BSD license. Consider the difference between GPL and BSD licenses: GPL is designed to make writing easier at the expense of making reading harder. BSD is designed to make reading easier and the expense of making writing harder. To a first approximation, the GPL license grants the right to read source code to anyone who promises to give back enhancements. In other words, the act of reading GPL source code (a prerequiste for making changes) implies acceptance of the license which requires updates to be contributed back under the same license. (The details are more complex, but the foregoing captures the essence of the idea.) A big advantage of the GPL is that anybody can contribute to the code without having to sign additional legal documentation because they have implied their acceptance of the GPL |
| ︙ | ︙ | |||
247 248 249 250 251 252 253 | cliquish, cathedral-style approach more typical of BSD-licensed projects. <h2>4.0 Missing Features</h2> Most of the capabilities found in Git are also available in Fossil and the other way around. For example, both systems have local check-outs, remote repositories, push/pull/sync, bisect capabilities, and a "stash". | | | 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 | cliquish, cathedral-style approach more typical of BSD-licensed projects. <h2>4.0 Missing Features</h2> Most of the capabilities found in Git are also available in Fossil and the other way around. For example, both systems have local check-outs, remote repositories, push/pull/sync, bisect capabilities, and a "stash". Both systems store project history as a directed acyclic graph (DAG) of immutable check-in objects. But there are a few capabilities in one system that are missing from the other. <h3>4.1 Features found in Fossil but missing from Git</h3> |
| ︙ | ︙ | |||
269 270 271 272 273 274 275 | * <b>Wiki, Embedded documentation, Trouble-tickets, and Tech-Notes</b> Git only provides versioning of source code. Fossil strives to provide other related configuration management services as well. * <b>Named branches</b> | | | | 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 | * <b>Wiki, Embedded documentation, Trouble-tickets, and Tech-Notes</b> Git only provides versioning of source code. Fossil strives to provide other related configuration management services as well. * <b>Named branches</b> Branches in Fossil have persistent names that are propagated to collaborators via [/help?cmd=push|push] and [/help?cmd=pull|pull]. All developers see the same name on the same branch. Git, in contrast, uses only local branch names, so developers working on the same project can (and frequently do) use a different name for the same branch. * <b>The [/help?cmd=all|fossil all] command</b> Fossil keeps track of all repositories and check-outs and allows operations over all of them with a single command. For example, in Fossil is possible to request a pull of all repositories on a laptop from their respective servers, prior to taking the laptop off network. |
| ︙ | ︙ |
Changes to www/index.wiki.
| ︙ | ︙ | |||
16 17 18 19 20 21 22 |
<li> [http://www.fossil-scm.org/schimpf-book/home | Jim Schimpf's book]
<li> Mailing list
<ul>
<li> [http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/fossil-users | sign-up]
<li> [http://www.mail-archive.com/fossil-users@lists.fossil-scm.org | archives]
</ul>
</ul>
| | | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<li> [http://www.fossil-scm.org/schimpf-book/home | Jim Schimpf's book]
<li> Mailing list
<ul>
<li> [http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/fossil-users | sign-up]
<li> [http://www.mail-archive.com/fossil-users@lists.fossil-scm.org | archives]
</ul>
</ul>
<img src="fossil3.gif" align="center">
</div>
<p>Fossil is a simple, high-reliability, distributed software configuration
management system with these advanced features:
1. <b>Integrated Bug Tracking, Wiki, and Technotes</b> -
In addition to doing [./concepts.wiki | distributed version control]
|
| ︙ | ︙ | |||
82 83 84 85 86 87 88 |
the repository are consistent prior to each commit.
8. <b>Free and Open-Source</b> - Uses the [../COPYRIGHT-BSD2.txt|2-clause BSD license].
<hr>
<h3>Links For Fossil Users:</h3>
| | < < < | > > > > | 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 |
the repository are consistent prior to each commit.
8. <b>Free and Open-Source</b> - Uses the [../COPYRIGHT-BSD2.txt|2-clause BSD license].
<hr>
<h3>Links For Fossil Users:</h3>
* [./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.
* [./quickstart.wiki | Quick Start] guide to using Fossil.
* [./qandc.wiki | Questions & Criticisms] directed at Fossil.
* [./build.wiki | Compiling and Installing]
* "Fuel" is cross-platform GUI front-end for Fossil
written in Qt. [http://fuelscm.org/].
Fuel is an independent project run by a different group of
developers.
* 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
not yet born.
* A tutorial on [./branching.wiki | branching], what it means and how
to do it using Fossil.
|
| ︙ | ︙ |
Changes to www/makefile.wiki.
| ︙ | ︙ | |||
225 226 227 228 229 230 231 232 233 234 235 236 237 238 | Some files require special C-preprocessor macro definitions. When compiling sqlite.c, the following macros are recommended: * -DSQLITE_OMIT_LOAD_EXTENSION=1 * -DSQLITE_ENABLE_DBSTAT_VTAB=1 * -DSQLITE_ENABLE_FTS4=1 * -DSQLITE_ENABLE_LOCKING_STYLE=0 * -DSQLITE_THREADSAFE=0 * -DSQLITE_DEFAULT_FILE_FORMAT=4 * -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1 The first three symbol definitions above are required; the others are merely recommended. Extension loading is omitted as a security measure. The dbstat virtual table is needed for the [/help?cmd=/repo-tabsize|/repo-tabsize] page. | > | 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | Some files require special C-preprocessor macro definitions. When compiling sqlite.c, the following macros are recommended: * -DSQLITE_OMIT_LOAD_EXTENSION=1 * -DSQLITE_ENABLE_DBSTAT_VTAB=1 * -DSQLITE_ENABLE_FTS4=1 * -DSQLITE_ENABLE_LOCKING_STYLE=0 * -DSQLITE_LIKE_DOESNT_MATCH_BLOBS=1 * -DSQLITE_THREADSAFE=0 * -DSQLITE_DEFAULT_FILE_FORMAT=4 * -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1 The first three symbol definitions above are required; the others are merely recommended. Extension loading is omitted as a security measure. The dbstat virtual table is needed for the [/help?cmd=/repo-tabsize|/repo-tabsize] page. |
| ︙ | ︙ |
Changes to www/mkindex.tcl.
1 2 3 4 5 | #!/bin/sh # # Run this TCL script to generate a WIKI page that contains a # permuted index of the various documentation files. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 |
#!/bin/sh
#
# Run this TCL script to generate a WIKI page that contains a
# permuted index of the various documentation files.
#
# tclsh mkindex.tcl
#
set doclist {
adding_code.wiki {Adding New Features To Fossil}
adding_code.wiki {Hacking Fossil}
antibot.wiki {Defense against Spiders and Bots}
blame.wiki {The Annotate/Blame Algorithm Of Fossil}
|
| ︙ | ︙ | |||
22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
contribute.wiki {Contributing Code or Documentation To The Fossil Project}
customgraph.md {Theming: Customizing the Timeline Graph}
customskin.md {Theming: Customizing The Appearance of Web Pages}
custom_ticket.wiki {Customizing The Ticket System}
delta_encoder_algorithm.wiki {Fossil Delta Encoding Algorithm}
delta_format.wiki {Fossil Delta Format}
embeddeddoc.wiki {Embedded Project Documentation}
event.wiki {Events}
faq.wiki {Frequently Asked Questions}
fileformat.wiki {Fossil File Format}
fiveminutes.wiki {Update and Running in 5 Minutes as a Single User}
foss-cklist.wiki {Checklist For Successful Open-Source Projects}
fossil-from-msvc.wiki {Integrating Fossil in the Microsoft Express 2010 IDE}
fossil-v-git.wiki {Fossil Versus Git}
| > > | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
contribute.wiki {Contributing Code or Documentation To The Fossil Project}
customgraph.md {Theming: Customizing the Timeline Graph}
customskin.md {Theming: Customizing The Appearance of Web Pages}
custom_ticket.wiki {Customizing The Ticket System}
delta_encoder_algorithm.wiki {Fossil Delta Encoding Algorithm}
delta_format.wiki {Fossil Delta Format}
embeddeddoc.wiki {Embedded Project Documentation}
encryptedrepos.wiki {How To Use Encrypted Repositories}
env-opts.md {Environment Variables and Global Options}
event.wiki {Events}
faq.wiki {Frequently Asked Questions}
fileformat.wiki {Fossil File Format}
fiveminutes.wiki {Update and Running in 5 Minutes as a Single User}
foss-cklist.wiki {Checklist For Successful Open-Source Projects}
fossil-from-msvc.wiki {Integrating Fossil in the Microsoft Express 2010 IDE}
fossil-v-git.wiki {Fossil Versus Git}
|
| ︙ | ︙ |
Changes to www/password.wiki.
| ︙ | ︙ | |||
131 132 133 134 135 136 137 | will work for both older and newer clients. If the USER.PW on the server only holds the SHA1 hash of the password, then only newer clients will be able to authenticate to the server. The client normally gets the login and password from the "remote URL". <blockquote><pre> | | | | 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 | will work for both older and newer clients. If the USER.PW on the server only holds the SHA1 hash of the password, then only newer clients will be able to authenticate to the server. The client normally gets the login and password from the "remote URL". <blockquote><pre> http://<span style="color:blue">login:password</span>@servername.org/path </pre></blockquote> For older clients, the password is used for the shared secret as stated in the URL and with no encoding. For newer clients, the shared secret is derived from the password by transformed the password using the SHA1 hash encoding described above. However, if the first character of the password is "*" (ASCII 0x2a) then the "*" is skipped and the rest of the password is used directly as the share secret without the SHA1 encoding. <blockquote><pre> http://<span style="color:blue">login:*password</span>@servername.org/path </pre></blockquote> This *-before-the-password trick can be used by newer clients to sync against a legacy server that does not understand the new SHA1 password encoding. |
Changes to www/permutedindex.html.
| ︙ | ︙ | |||
69 70 71 72 73 74 75 76 77 78 79 80 81 82 | <li><a href="theory1.wiki">Design Of The Fossil DVCS — Thoughts On The</a></li> <li><a href="embeddeddoc.wiki">Documentation — Embedded Project</a></li> <li><a href="contribute.wiki">Documentation To The Fossil Project — Contributing Code or</a></li> <li><a href="theory1.wiki">DVCS — Thoughts On The Design Of The Fossil</a></li> <li><a href="quotes.wiki">DVCSes in General — Quotes: What People Are Saying About Fossil, Git, and</a></li> <li><a href="embeddeddoc.wiki">Embedded Project Documentation</a></li> <li><a href="delta_encoder_algorithm.wiki">Encoding Algorithm — Fossil Delta</a></li> <li><a href="event.wiki">Events</a></li> <li><a href="webpage-ex.md">Examples — Webpage</a></li> <li><a href="inout.wiki">Export To And From Git — Import And</a></li> <li><a href="fossil-from-msvc.wiki">Express 2010 IDE — Integrating Fossil in the Microsoft</a></li> <li><a href="adding_code.wiki">Features To Fossil — Adding New</a></li> <li><a href="fileformat.wiki">File Format — Fossil</a></li> <li><a href="branching.wiki">Forking, Merging, and Tagging — Branching,</a></li> | > > | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | <li><a href="theory1.wiki">Design Of The Fossil DVCS — Thoughts On The</a></li> <li><a href="embeddeddoc.wiki">Documentation — Embedded Project</a></li> <li><a href="contribute.wiki">Documentation To The Fossil Project — Contributing Code or</a></li> <li><a href="theory1.wiki">DVCS — Thoughts On The Design Of The Fossil</a></li> <li><a href="quotes.wiki">DVCSes in General — Quotes: What People Are Saying About Fossil, Git, and</a></li> <li><a href="embeddeddoc.wiki">Embedded Project Documentation</a></li> <li><a href="delta_encoder_algorithm.wiki">Encoding Algorithm — Fossil Delta</a></li> <li><a href="encryptedrepos.wiki">Encrypted Repositories — How To Use</a></li> <li><a href="env-opts.md">Environment Variables and Global Options</a></li> <li><a href="event.wiki">Events</a></li> <li><a href="webpage-ex.md">Examples — Webpage</a></li> <li><a href="inout.wiki">Export To And From Git — Import And</a></li> <li><a href="fossil-from-msvc.wiki">Express 2010 IDE — Integrating Fossil in the Microsoft</a></li> <li><a href="adding_code.wiki">Features To Fossil — Adding New</a></li> <li><a href="fileformat.wiki">File Format — Fossil</a></li> <li><a href="branching.wiki">Forking, Merging, and Tagging — Branching,</a></li> |
| ︙ | ︙ | |||
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 | <li><a href="faq.wiki">Frequently Asked Questions</a></li> <li><a href="shunning.wiki">From Fossil — Shunning: Deleting Content</a></li> <li><a href="inout.wiki">From Git — Import And Export To And</a></li> <li><a href="quotes.wiki">General — Quotes: What People Are Saying About Fossil, Git, and DVCSes in</a></li> <li><a href="fossil-v-git.wiki">Git — Fossil Versus</a></li> <li><a href="inout.wiki">Git — Import And Export To And From</a></li> <li><a href="quotes.wiki">Git, and DVCSes in General — Quotes: What People Are Saying About Fossil,</a></li> <li><a href="customgraph.md">Graph — Theming: Customizing the Timeline</a></li> <li><a href="quickstart.wiki">Guide — Fossil Quick Start</a></li> <li><a href="style.wiki">Guidelines — Source Code Style</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="hints.wiki">Hints — Fossil Tips And Usage</a></li> <li><a href="index.wiki">Home Page</a></li> <li><a href="selfhost.wiki">Hosting Repositories — Fossil Self</a></li> <li><a href="server.wiki">How To Configure A Fossil Server</a></li> <li><a href="newrepo.wiki">How To Create A New Fossil Repository</a></li> <li><a href="hacker-howto.wiki">How-To — Hacker</a></li> <li><a href="fossil-from-msvc.wiki">IDE — Integrating Fossil in the Microsoft Express 2010</a></li> <li><a href="tech_overview.wiki">Implementation Of Fossil — A Technical Overview Of The Design And</a></li> <li><a href="inout.wiki">Import And Export To And From Git</a></li> <li><a href="build.wiki">Installing Fossil — Compiling and</a></li> <li><a href="fossil-from-msvc.wiki">Integrating Fossil in the Microsoft Express 2010 IDE</a></li> <li><a href="selfcheck.wiki">Integrity Self Checks — Fossil Repository</a></li> <li><a href="webui.wiki">Interface — The Fossil Web</a></li> <li><a href="th1.md">Language — The TH1 Scripting</a></li> <li><a href="copyright-release.html">License Agreement — Contributor</a></li> <li><a href="password.wiki">Management And Authentication — Password</a></li> <li><a href="branching.wiki">Merging, and Tagging — Branching, Forking,</a></li> <li><a href="fossil-from-msvc.wiki">Microsoft Express 2010 IDE — Integrating Fossil in the</a></li> <li><a href="fiveminutes.wiki">Minutes as a Single User — Update and Running in 5</a></li> <li><a href="checkin_names.wiki">Names — Check-in And Version</a></li> <li><a href="adding_code.wiki">New Features To Fossil — Adding</a></li> <li><a href="newrepo.wiki">New Fossil Repository — How To Create A</a></li> <li><a href="foss-cklist.wiki">Open-Source Projects — Checklist For Successful</a></li> <li><a href="pop.wiki">Operations — Principles Of</a></li> <li><a href="tech_overview.wiki">Overview Of The Design And Implementation Of Fossil — A Technical</a></li> <li><a href="index.wiki">Page — Home</a></li> <li><a href="customskin.md">Pages — Theming: Customizing The Appearance of Web</a></li> <li><a href="password.wiki">Password Management And Authentication</a></li> <li><a href="quotes.wiki">People Are Saying About Fossil, Git, and DVCSes in General — Quotes: What</a></li> <li><a href="stats.wiki">Performance Statistics</a></li> <li><a href="../test/release-checklist.wiki">Pre-Release Testing Checklist</a></li> <li><a href="pop.wiki">Principles Of Operations</a></li> <li><a href="private.wiki">Private Branches — Creating, Syncing, and Deleting</a></li> <li><a href="makefile.wiki">Process — The Fossil Build</a></li> <li><a href="contribute.wiki">Project — Contributing Code or Documentation To The Fossil</a></li> <li><a href="embeddeddoc.wiki">Project Documentation — Embedded</a></li> <li><a href="foss-cklist.wiki">Projects — Checklist For Successful Open-Source</a></li> <li><a href="sync.wiki">Protocol — The Fossil Sync</a></li> <li><a href="faq.wiki">Questions — Frequently Asked</a></li> <li><a href="qandc.wiki">Questions And Criticisms</a></li> <li><a href="quickstart.wiki">Quick Start Guide — Fossil</a></li> <li><a href="quotes.wiki">Quotes: What People Are Saying About Fossil, Git, and DVCSes in General</a></li> <li><a href="selfhost.wiki">Repositories — Fossil Self Hosting</a></li> <li><a href="newrepo.wiki">Repository — How To Create A New Fossil</a></li> <li><a href="selfcheck.wiki">Repository Integrity Self Checks — Fossil</a></li> <li><a href="reviews.wiki">Reviews</a></li> <li><a href="fiveminutes.wiki">Running in 5 Minutes as a Single User — Update and</a></li> <li><a href="quotes.wiki">Saying About Fossil, Git, and DVCSes in General — Quotes: What People Are</a></li> <li><a href="th1.md">Scripting Language — The TH1</a></li> <li><a href="selfcheck.wiki">Self Checks — Fossil Repository Integrity</a></li> | > > > > | 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 | <li><a href="faq.wiki">Frequently Asked Questions</a></li> <li><a href="shunning.wiki">From Fossil — Shunning: Deleting Content</a></li> <li><a href="inout.wiki">From Git — Import And Export To And</a></li> <li><a href="quotes.wiki">General — Quotes: What People Are Saying About Fossil, Git, and DVCSes in</a></li> <li><a href="fossil-v-git.wiki">Git — Fossil Versus</a></li> <li><a href="inout.wiki">Git — Import And Export To And From</a></li> <li><a href="quotes.wiki">Git, and DVCSes in General — Quotes: What People Are Saying About Fossil,</a></li> <li><a href="env-opts.md">Global Options — Environment Variables and</a></li> <li><a href="customgraph.md">Graph — Theming: Customizing the Timeline</a></li> <li><a href="quickstart.wiki">Guide — Fossil Quick Start</a></li> <li><a href="style.wiki">Guidelines — Source Code Style</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="hints.wiki">Hints — Fossil Tips And Usage</a></li> <li><a href="index.wiki">Home Page</a></li> <li><a href="selfhost.wiki">Hosting Repositories — Fossil Self</a></li> <li><a href="server.wiki">How To Configure A Fossil Server</a></li> <li><a href="newrepo.wiki">How To Create A New Fossil Repository</a></li> <li><a href="encryptedrepos.wiki">How To Use Encrypted Repositories</a></li> <li><a href="hacker-howto.wiki">How-To — Hacker</a></li> <li><a href="fossil-from-msvc.wiki">IDE — Integrating Fossil in the Microsoft Express 2010</a></li> <li><a href="tech_overview.wiki">Implementation Of Fossil — A Technical Overview Of The Design And</a></li> <li><a href="inout.wiki">Import And Export To And From Git</a></li> <li><a href="build.wiki">Installing Fossil — Compiling and</a></li> <li><a href="fossil-from-msvc.wiki">Integrating Fossil in the Microsoft Express 2010 IDE</a></li> <li><a href="selfcheck.wiki">Integrity Self Checks — Fossil Repository</a></li> <li><a href="webui.wiki">Interface — The Fossil Web</a></li> <li><a href="th1.md">Language — The TH1 Scripting</a></li> <li><a href="copyright-release.html">License Agreement — Contributor</a></li> <li><a href="password.wiki">Management And Authentication — Password</a></li> <li><a href="branching.wiki">Merging, and Tagging — Branching, Forking,</a></li> <li><a href="fossil-from-msvc.wiki">Microsoft Express 2010 IDE — Integrating Fossil in the</a></li> <li><a href="fiveminutes.wiki">Minutes as a Single User — Update and Running in 5</a></li> <li><a href="checkin_names.wiki">Names — Check-in And Version</a></li> <li><a href="adding_code.wiki">New Features To Fossil — Adding</a></li> <li><a href="newrepo.wiki">New Fossil Repository — How To Create A</a></li> <li><a href="foss-cklist.wiki">Open-Source Projects — Checklist For Successful</a></li> <li><a href="pop.wiki">Operations — Principles Of</a></li> <li><a href="env-opts.md">Options — Environment Variables and Global</a></li> <li><a href="tech_overview.wiki">Overview Of The Design And Implementation Of Fossil — A Technical</a></li> <li><a href="index.wiki">Page — Home</a></li> <li><a href="customskin.md">Pages — Theming: Customizing The Appearance of Web</a></li> <li><a href="password.wiki">Password Management And Authentication</a></li> <li><a href="quotes.wiki">People Are Saying About Fossil, Git, and DVCSes in General — Quotes: What</a></li> <li><a href="stats.wiki">Performance Statistics</a></li> <li><a href="../test/release-checklist.wiki">Pre-Release Testing Checklist</a></li> <li><a href="pop.wiki">Principles Of Operations</a></li> <li><a href="private.wiki">Private Branches — Creating, Syncing, and Deleting</a></li> <li><a href="makefile.wiki">Process — The Fossil Build</a></li> <li><a href="contribute.wiki">Project — Contributing Code or Documentation To The Fossil</a></li> <li><a href="embeddeddoc.wiki">Project Documentation — Embedded</a></li> <li><a href="foss-cklist.wiki">Projects — Checklist For Successful Open-Source</a></li> <li><a href="sync.wiki">Protocol — The Fossil Sync</a></li> <li><a href="faq.wiki">Questions — Frequently Asked</a></li> <li><a href="qandc.wiki">Questions And Criticisms</a></li> <li><a href="quickstart.wiki">Quick Start Guide — Fossil</a></li> <li><a href="quotes.wiki">Quotes: What People Are Saying About Fossil, Git, and DVCSes in General</a></li> <li><a href="selfhost.wiki">Repositories — Fossil Self Hosting</a></li> <li><a href="encryptedrepos.wiki">Repositories — How To Use Encrypted</a></li> <li><a href="newrepo.wiki">Repository — How To Create A New Fossil</a></li> <li><a href="selfcheck.wiki">Repository Integrity Self Checks — Fossil</a></li> <li><a href="reviews.wiki">Reviews</a></li> <li><a href="fiveminutes.wiki">Running in 5 Minutes as a Single User — Update and</a></li> <li><a href="quotes.wiki">Saying About Fossil, Git, and DVCSes in General — Quotes: What People Are</a></li> <li><a href="th1.md">Scripting Language — The TH1</a></li> <li><a href="selfcheck.wiki">Self Checks — Fossil Repository Integrity</a></li> |
| ︙ | ︙ | |||
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | <li><a href="custom_ticket.wiki">Ticket System — Customizing The</a></li> <li><a href="tickets.wiki">Ticket System — The Fossil</a></li> <li><a href="customgraph.md">Timeline Graph — Theming: Customizing the</a></li> <li><a href="hints.wiki">Tips And Usage Hints — Fossil</a></li> <li><a href="bugtheory.wiki">Tracking In Fossil — Bug</a></li> <li><a href="fiveminutes.wiki">Update and Running in 5 Minutes as a Single User</a></li> <li><a href="hints.wiki">Usage Hints — Fossil Tips And</a></li> <li><a href="fiveminutes.wiki">User — Update and Running in 5 Minutes as a Single</a></li> <li><a href="ssl.wiki">Using SSL with Fossil</a></li> <li><a href="checkin_names.wiki">Version Names — Check-in And</a></li> <li><a href="fossil-v-git.wiki">Versus Git — Fossil</a></li> <li><a href="webui.wiki">Web Interface — The Fossil</a></li> <li><a href="customskin.md">Web Pages — Theming: Customizing The Appearance of</a></li> <li><a href="webpage-ex.md">Webpage Examples</a></li> <li><a href="quotes.wiki">What People Are Saying About Fossil, Git, and DVCSes in General — Quotes:</a></li> <li><a href="wikitheory.wiki">Wiki In Fossil</a></li> <li><a href="ssl.wiki">with Fossil — Using SSL</a></li> </ul></div> | > > | 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | <li><a href="custom_ticket.wiki">Ticket System — Customizing The</a></li> <li><a href="tickets.wiki">Ticket System — The Fossil</a></li> <li><a href="customgraph.md">Timeline Graph — Theming: Customizing the</a></li> <li><a href="hints.wiki">Tips And Usage Hints — Fossil</a></li> <li><a href="bugtheory.wiki">Tracking In Fossil — Bug</a></li> <li><a href="fiveminutes.wiki">Update and Running in 5 Minutes as a Single User</a></li> <li><a href="hints.wiki">Usage Hints — Fossil Tips And</a></li> <li><a href="encryptedrepos.wiki">Use Encrypted Repositories — How To</a></li> <li><a href="fiveminutes.wiki">User — Update and Running in 5 Minutes as a Single</a></li> <li><a href="ssl.wiki">Using SSL with Fossil</a></li> <li><a href="env-opts.md">Variables and Global Options — Environment</a></li> <li><a href="checkin_names.wiki">Version Names — Check-in And</a></li> <li><a href="fossil-v-git.wiki">Versus Git — Fossil</a></li> <li><a href="webui.wiki">Web Interface — The Fossil</a></li> <li><a href="customskin.md">Web Pages — Theming: Customizing The Appearance of</a></li> <li><a href="webpage-ex.md">Webpage Examples</a></li> <li><a href="quotes.wiki">What People Are Saying About Fossil, Git, and DVCSes in General — Quotes:</a></li> <li><a href="wikitheory.wiki">Wiki In Fossil</a></li> <li><a href="ssl.wiki">with Fossil — Using SSL</a></li> </ul></div> |
Changes to www/scgi.wiki.
| ︙ | ︙ | |||
13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
this in Nginx is:
<blockquote><pre>
location ~ ^/demo_project/ {
include scgi_params;
scgi_pass localhost:9000;
scgi_param SCRIPT_NAME "/demo_project";
}
</pre></blockquote>
Note that Nginx does not normally send either the PATH_INFO or SCRIPT_NAME
variables via SCGI, but Fossil needs one or the other. So the configuration
above needs to add SCRIPT_NAME. If you do not do this, Fossil returns an
error.
| > | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
this in Nginx is:
<blockquote><pre>
location ~ ^/demo_project/ {
include scgi_params;
scgi_pass localhost:9000;
scgi_param SCRIPT_NAME "/demo_project";
scgi_param HTTPS "on";
}
</pre></blockquote>
Note that Nginx does not normally send either the PATH_INFO or SCRIPT_NAME
variables via SCGI, but Fossil needs one or the other. So the configuration
above needs to add SCRIPT_NAME. If you do not do this, Fossil returns an
error.
|
Changes to www/server.wiki.
| ︙ | ︙ | |||
225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
that does not support CGI. A typical Nginx configuration to support SCGI
with Fossil would look something like this:
<blockquote><pre>
location /demo_project/ {
include scgi_params;
scgi_pass localhost:9000;
scgi_param SCRIPT_NAME "/demo_project";
}
</pre></blockquote>
<p>
Note that Fossil requires the SCRIPT_NAME variable
in order to function properly, but Nginx does not provide this
variable by default.
So it is necessary to provide the SCRIPT_NAME parameter in the configuration.
| > | 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
that does not support CGI. A typical Nginx configuration to support SCGI
with Fossil would look something like this:
<blockquote><pre>
location /demo_project/ {
include scgi_params;
scgi_pass localhost:9000;
scgi_param SCRIPT_NAME "/demo_project";
scgi_param HTTPS "on";
}
</pre></blockquote>
<p>
Note that Fossil requires the SCRIPT_NAME variable
in order to function properly, but Nginx does not provide this
variable by default.
So it is necessary to provide the SCRIPT_NAME parameter in the configuration.
|
| ︙ | ︙ | |||
343 344 345 346 347 348 349 | systems that support the "getloadavg()" API. Most modern Unix systems have this interface, but Windows does not, so the feature will not work on Windows. Note also that Linux implements "getloadavg()" by accessing the "/proc/loadavg" file in the "proc" virtual filesystem. If you are running a Fossil instance inside a chroot() jail on Linux, you will need to make the "/proc" file system available inside that jail in order for this feature to work. On the self-hosting Fossil repository, this was accomplished by adding a line | | | | > | 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 | systems that support the "getloadavg()" API. Most modern Unix systems have this interface, but Windows does not, so the feature will not work on Windows. Note also that Linux implements "getloadavg()" by accessing the "/proc/loadavg" file in the "proc" virtual filesystem. If you are running a Fossil instance inside a chroot() jail on Linux, you will need to make the "/proc" file system available inside that jail in order for this feature to work. On the self-hosting Fossil repository, this was accomplished by adding a line to the "/etc/fstab" file that looks like: <blockquote><pre> chroot_jail_proc /home/www/proc proc ro 0 0 </pre></blockquote> The /home/www/proc pathname should be adjusted so that the "/proc" component is in the root of the chroot jail, of course. <p> To see if the load-average limiter is functional, visit the [/test_env] page of the server to view the current load average. If the value for the load average is greater than zero, that means that it is possible to activate the load-average limiter on that repository. If the load average shows exactly "0.0", then that means that Fossil is unable to find the load average (either because it is in a chroot() jail without /proc access, or because it is running on a system that does not support "getloadavg()") and so the load-average limiter will not function. </blockquote> |
Changes to www/sync.wiki.
| ︙ | ︙ | |||
13 14 15 16 17 18 19 | collection of artifacts. Each artifact is identified by its SHA1 hash expressed as a 40-character lower-case hexadecimal string. Synchronization is simply the process of sharing artifacts between servers so that all servers have copies of all artifacts. Because artifacts are unordered, the order in which artifacts are received at a server is inconsequential. It is assumed that the SHA1 hashes of artifacts are unique - that every artifact has a different SHA1 hash. | | | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | collection of artifacts. Each artifact is identified by its SHA1 hash expressed as a 40-character lower-case hexadecimal string. Synchronization is simply the process of sharing artifacts between servers so that all servers have copies of all artifacts. Because artifacts are unordered, the order in which artifacts are received at a server is inconsequential. It is assumed that the SHA1 hashes of artifacts are unique - that every artifact has a different SHA1 hash. To a first approximation, synchronization proceeds by sharing lists SHA1 hashes of available artifacts, then sharing those artifacts that are not found on one side or the other of the connection. In practice, a repository might contain millions of artifacts. The list of SHA1 hashes for this many artifacts can be large. So optimizations are employed that usually reduce the number of SHA1 hashes that need to be shared to a few hundred.</p> |
| ︙ | ︙ | |||
148 149 150 151 152 153 154 | from the server. The nonce is the SHA1 hash of the remainder of the message - all text that follows the newline character that terminates the login card. The signature is the SHA1 hash of the concatenation of the nonce and the users password.</p> <p>For each login card, the server looks up the user and verifies that the nonce matches the SHA1 hash of the remainder of the | | | | 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 | from the server. The nonce is the SHA1 hash of the remainder of the message - all text that follows the newline character that terminates the login card. The signature is the SHA1 hash of the concatenation of the nonce and the users password.</p> <p>For each login card, the server looks up the user and verifies that the nonce matches the SHA1 hash of the remainder of the message. It then checks the signature hash to make sure the signature matches. If everything checks out, then the client is granted all privileges of the specified user.</p> <p>Privileges are cumulative. There can be multiple successful login cards. The session privileges are the bit-wise OR of the privileges of each individual login.</p> <h3>3.3 File and Compressed File Cards</h3> <p>Artifacts are transferred using either "file" cards, or "cfile" cards. (The name "file" card comes from the fact that most artifacts correspond to files, and "cfile" is just a compressed file.) </p> <h4>3.3.1 File Cards</h4> <p>For sync protocols, artifacts are transferred using "file" cards. File cards come in two different formats depending |
| ︙ | ︙ | |||
228 229 230 231 232 233 234 | that immediately follow the cfile card. If the cfile card has only three arguments, that means the payload is the complete content of the artifact. If the cfile card has four arguments, then the payload is a delta and the second argument is the ID of another artifact that is the source of the delta and the third argument is the original size of the delta artifact.</p> | | | 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 | that immediately follow the cfile card. If the cfile card has only three arguments, that means the payload is the complete content of the artifact. If the cfile card has four arguments, then the payload is a delta and the second argument is the ID of another artifact that is the source of the delta and the third argument is the original size of the delta artifact.</p> <p>Unlike file cards, cfile cards are only sent in one direction during a clone from server to client for clone protocol version "3" or greater.</p> <h3>3.4 Push and Pull Cards</h3> <p>Among the first cards in a client-to-server message are the push and pull cards. The push card tells the server that the client is pushing content. The pull card tells the server |
| ︙ | ︙ | |||
383 384 385 386 387 388 389 | <blockquote> <b>reqconfig</b> <i>configuration-name</i> </blockquote> <p>As of [/timeline?r=trunk&c=2015-03-19+03%3A57%3A46&n=20|2015-03-19], the configuration-name must be one of the following values: | | | 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 | <blockquote> <b>reqconfig</b> <i>configuration-name</i> </blockquote> <p>As of [/timeline?r=trunk&c=2015-03-19+03%3A57%3A46&n=20|2015-03-19], the configuration-name must be one of the following values: <table border=0 align="center"> <tr><td valign="top"> <ul> <li> css <li> header <li> footer <li> logo-mimetype <li> logo-image |
| ︙ | ︙ | |||
434 435 436 437 438 439 440 | <li> ticket-title-expr <li> ticket-closed-expr <li> @reportfmt <li> @user <li> @concealed <li> @shun </ul></td></tr> | | | | 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 | <li> ticket-title-expr <li> ticket-closed-expr <li> @reportfmt <li> @user <li> @concealed <li> @shun </ul></td></tr> </table> <p>New configuration-names are likely to be added in future releases of Fossil. If the server receives a configuration-name that it does not understand, the entire reqconfig card is silently ignored. The reqconfig card might also be ignored if the user lacks sufficient privilege to access the requested information. <p>The configuration-names that begin with an alphabetic character refer to values in the "config" table of the server database. For example, the "logo-image" configuration item refers to the project logo image that is configured on the Admin page of the [./webui.wiki | web-interface]. The value of the configuration item is returned to the client using a "config" card. <p>If the configuration-name begins with "@", that refers to a class of values instead of a single value. The content of these configuration items is returned in a "config" card that contains pure SQL text that is intended to be evaluated by the client. <p>The @user and @concealed configuration items contain sensitive information and are ignored for clients without sufficient privilege. <h3>3.10 Configuration Cards</h3> |
| ︙ | ︙ | |||
489 490 491 492 493 494 495 | <blockquote> <b>error</b> <i>error-message</i> </blockquote> <p>The error message is English text that is encoded in order to be a single token. A space (ASCII 0x20) is represented as "\s" (ASCII 0x5C, 0x73). A | | | 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 | <blockquote> <b>error</b> <i>error-message</i> </blockquote> <p>The error message is English text that is encoded in order to be a single token. A space (ASCII 0x20) is represented as "\s" (ASCII 0x5C, 0x73). A newline (ASCII 0x0a) is "\n" (ASCII 0x6C, x6E). A backslash (ASCII 0x5C) is represented as two backslashes "\\". Apart from space and newline, no other whitespace characters nor any unprintable characters are allowed in the error message.</p> <h3>3.12 Comment Cards</h3> |
| ︙ | ︙ | |||
656 657 658 659 660 661 662 |
<p>Here are the key points of the synchronization protocol:</p>
<ol>
<li>The client sends one or more PUSH HTTP requests to the server.
The request and reply content type is "application/x-fossil".
<li>HTTP request content is compressed using zlib.
<li>The content of request and reply consists of cards with one
| | | 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 |
<p>Here are the key points of the synchronization protocol:</p>
<ol>
<li>The client sends one or more PUSH HTTP requests to the server.
The request and reply content type is "application/x-fossil".
<li>HTTP request content is compressed using zlib.
<li>The content of request and reply consists of cards with one
card per line.
<li>Card formats are:
<ul>
<li> <b>login</b> <i>userid nonce signature</i>
<li> <b>push</b> <i>servercode projectcode</i>
<li> <b>pull</b> <i>servercode projectcode</i>
<li> <b>clone</b>
<li> <b>file</b> <i>artifact-id size</i> <b>\n</b> <i>content</i>
|
| ︙ | ︙ |
Changes to www/tech_overview.wiki.
1 2 3 4 5 6 7 8 9 | <title>Technical Overview</title> <h2 align="center"> A Technical Overview<br>Of The Design And Implementation<br>Of Fossil </h2> <h2>1.0 Introduction</h2> At its lowest level, a Fossil repository consists of an unordered set of immutable "artifacts". You might think of these artifacts as "files", | | | | | | | | | 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 | <title>Technical Overview</title> <h2 align="center"> A Technical Overview<br>Of The Design And Implementation<br>Of Fossil </h2> <h2>1.0 Introduction</h2> At its lowest level, a Fossil repository consists of an unordered set of immutable "artifacts". You might think of these artifacts as "files", since in many cases the artifacts are exactly that. But other "control artifacts" are also included in the mix. These control artifacts define the relationships between artifacts - which files go together to form a particular version of the project, who checked in that version and when, what was the check-in comment, what wiki pages are included with the project, what are the edit histories of each wiki page, what bug reports or tickets are included, who contributed to the evolution of each ticket, and so forth. This low-level file format is called the "global state" of the repository, since this is the information that is synced to peer repositories using push and pull operations. The low-level file format is also called "enduring" since it is intended to last for many years. The details of the low-level, enduring, global file format are [./fileformat.wiki | described separately]. This article is about how Fossil is currently implemented. Instead of dealing with vague abstractions of "enduring file formats" as the [./fileformat.wiki | other document] does, this article provides some detail on how Fossil actually stores information on disk. <h2>2.0 Three Databases</h2> Fossil stores state information in [http://www.sqlite.org/ | SQLite] database files. SQLite keeps an entire relational database, including multiple tables and indices, in a single disk file. The SQLite library allows the database files to be efficiently queried and updated using the industry-standard SQL language. SQLite updates are atomic, so even in the event of a system crashes or power failure the repository content is protected. Fossil uses three separate classes of SQLite databases: <ol> <li>The configuration database <li>Repository databases <li>Checkout databases </ol> The configuration database is a one-per-user database that holds global configuration information used by Fossil. There is one repository database per project. The repository database is the file that people are normally referring to when they say "a Fossil repository". The checkout database is found in the working checkout for a project and contains state information that is unique to that working checkout. Fossil does not always use all three database files. The web interface, for example, typically only uses the repository database. And the [/help/all | fossil setting] command only opens the configuration database when the --global option is used. But other commands use all three databases at once. For example, the [/help/status | fossil status] command will first locate the checkout database, then use the checkout database to find the repository database, then open the configuration database. Whenever multiple databases are used at the same time, they are all opened on the same SQLite database connection using SQLite's [http://www.sqlite.org/lang_attach.html | ATTACH] command. The chart below provides a quick summary of how each of these database files are used by Fossil, with detailed discussion following. <table border="1" width="80%" cellpadding="0" align="center"> <tr> <td width="33%" valign="top"> <h3 align="center">Configuration Database<br>"~/.fossil"</h3> <ul> <li>Global [/help/setting |settings] <li>List of active repositories used by the [/help/all | all] command </ul> |
| ︙ | ︙ | |||
101 102 103 104 105 106 107 |
local edits
<li>The "[/help/stash | stash]"
<li>Information needed to "[/help/undo|undo]" or "[/help/redo|redo]"
</ul>
</td>
</tr>
</table>
| < | 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
local edits
<li>The "[/help/stash | stash]"
<li>Information needed to "[/help/undo|undo]" or "[/help/redo|redo]"
</ul>
</td>
</tr>
</table>
<h3>2.1 The Configuration Database</h3>
The configuration database holds cross-repository preferences and a list of all
repositories for a single user.
The [/help/setting | fossil setting] command can be used to specify various
|
| ︙ | ︙ | |||
133 134 135 136 137 138 139 | LOCALAPPDATA, APPDATA, or HOMEPATH environment variables, in that order. You can override this default location by defining the environment variable FOSSIL_HOME pointing to an appropriate (writable) directory. <h3>2.2 Repository Databases</h3> | | | | | | | 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 | LOCALAPPDATA, APPDATA, or HOMEPATH environment variables, in that order. You can override this default location by defining the environment variable FOSSIL_HOME pointing to an appropriate (writable) directory. <h3>2.2 Repository Databases</h3> The repository database is the file that is commonly referred to as "the repository". This is because the repository database contains, among other things, the complete revision, ticket, and wiki history for a project. It is customary to name the repository database after then name of the project, with a ".fossil" suffix. For example, the repository database for the self-hosting Fossil repository is called "fossil.fossil" and the repository database for SQLite is called "sqlite.fossil". <h4>2.2.1 Global Project State</h4> The bulk of the repository database (typically 75 to 85%) consists of the artifacts that comprise the [./fileformat.wiki | enduring, global, shared state] of the project. The artifacts are stored as BLOBs, compressed using [http://www.zlib.net/ | zlib compression] and, where applicable, using [./delta_encoder_algorithm.wiki | delta compression]. The combination of zlib and delta compression results in a considerable space savings. For the SQLite project, at the time of this writing, the total size of all artifacts is over 2.0 GB but thanks to the combined zlib and delta compression, that content only takes up 32 MB of space in the repository database, for a compression ratio of about 64:1. The average size of a content BLOB in the database is around 500 bytes. Note that the zlib and delta compression is not an inherent part of the Fossil file format; it is just an optimization. The enduring file format for Fossil is the unordered set of artifacts. The compression techniques are just a detail of how the current implementation of Fossil happens to store these artifacts efficiently on disk. All of the original uncompressed and undeltaed artifacts can be extracted from a Fossil repository database using the [/help/deconstruct | fossil deconstruct] command. Individual artifacts can be extracted using the [/help/artifact | fossil artifact] command. When accessing the repository database using raw SQL and the [/help/sqlite3 | fossil sql] command, the extension function "<tt>content()</tt>" with a single argument which is the SHA1 hash of an artifact will return the complete undeleted and uncompressed content of that artifact. Going the other way, the [/help/reconstruct | fossil reconstruct] command will scan a directory hierarchy and add all files found to a new repository database. The [/help/import | fossil import] command works by reading the input git-fast-export stream and using it to construct corresponding artifacts which are then written into the repository database. |
| ︙ | ︙ | |||
223 224 225 226 227 228 229 | this information (and the user credentials and privileges too) is local to each repository database; it is not shared between repositories by [/help/sync | fossil sync]. That is because it is entirely reasonable that two different websites for the same project might have completely different display preferences and user communities. One instance of the project might be a fork of the other, for example, which pulls from the other but never pushes and extends the project in ways that the keepers of | | | | | | | | 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 |
this information (and the user credentials and privileges too) is
local to each repository database; it is not shared between repositories
by [/help/sync | fossil sync]. That is because it is entirely reasonable
that two different websites for the same project might have completely
different display preferences and user communities. One instance of the
project might be a fork of the other, for example, which pulls from the
other but never pushes and extends the project in ways that the keepers of
the other website disapprove of.
Display and processing information includes the following:
* The name and description of the project
* The CSS file, header, and footer used by all web pages
* The project logo image
* Fields of tickets that are considered "significant" and which are
therefore collected from artifacts and made available for display
* Templates for screens to view, edit, and create tickets
* Ticket report formats and display preferences
* Local values for [/help/setting | settings] that override the
global values defined in the per-user configuration database.
Though the display and processing preferences do not move between
repository instances using [/help/sync | fossil sync], this information
can be shared between repositories using the
[/help/config | fossil config push] and
[/help/config | fossil config pull] commands.
The display and processing information is also copied into new
repositories when they are created using
[/help/clone | fossil clone].
<h4>2.2.4 User Credentials And Privileges</h4>
Just because two development teams are collaborating on a project and allow
push and/or pull between their repositories does not mean that they
trust each other enough to share passwords and access privileges.
Hence the names and emails and passwords and privileges of users are
considered private information that is kept locally in each repository.
Each repository database has a table holding the username, privileges,
and login credentials for users authorized to interact with that particular
database. In addition, there is a table named "concealed" that maps the
SHA1 hash of each users email address back into their true email address.
The concealed table allows just the SHA1 hash of email addresses to
be stored in tickets, and thus prevents actual email addresses from falling
into the hands of spammers who happen to clone the repository.
The content of the user and concealed tables can be pushed and pulled using the
[/help/config | fossil config push] and
[/help/config | fossil config pull] commands with the "user" and
"email" as the AREA argument, but only if you have administrative
privileges on the remote repository.
<h4>2.2.5 Shunned Artifact List</h4>
The set of canonical artifacts for a project - the global state for the
project - is intended to be an append-only database. In other words,
new artifacts can be added but artifacts can never be removed. But
it sometimes happens that inappropriate content is mistakenly or
maliciously added to a repository. The only way to get rid of
the undesired content is to [./shunning.wiki | "shun"] it.
The "shun" table in the repository database records the SHA1 hash of
all shunned artifacts.
The shun table can be pushed or pulled using
the [/help/config | fossil config] command with the "shun" AREA argument.
The shun table is also copied during a [/help/clone | clone].
<h3>2.3 Checkout Databases</h3>
|
| ︙ | ︙ |
Changes to www/th1.md.
| ︙ | ︙ | |||
340 341 342 343 344 345 346 347 348 349 350 351 352 353 | 1. **useTclStubs** -- _Tcl stubs enabled in the Tcl headers._ 1. **tclStubs** -- _Uses Tcl stubs (i.e. linking with stubs library)._ 1. **tclPrivateStubs** -- _Uses Tcl private stubs (i.e. header-only)._ 1. **json** -- _Support for the JSON APIs._ 1. **markdown** -- _Support for Markdown documentation format._ 1. **unicodeCmdLine** -- _The command line arguments are Unicode._ 1. **dynamicBuild** -- _Dynamically linked to libraries._ Specifying an unknown feature will return a value of false, it will not raise a script error. <a name="html"></a>TH1 html Command ----------------------------------- | > | 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 | 1. **useTclStubs** -- _Tcl stubs enabled in the Tcl headers._ 1. **tclStubs** -- _Uses Tcl stubs (i.e. linking with stubs library)._ 1. **tclPrivateStubs** -- _Uses Tcl private stubs (i.e. header-only)._ 1. **json** -- _Support for the JSON APIs._ 1. **markdown** -- _Support for Markdown documentation format._ 1. **unicodeCmdLine** -- _The command line arguments are Unicode._ 1. **dynamicBuild** -- _Dynamically linked to libraries._ 1. **see** -- _Uses the SQLite Encryption Extension._ Specifying an unknown feature will return a value of false, it will not raise a script error. <a name="html"></a>TH1 html Command ----------------------------------- |
| ︙ | ︙ |
Changes to www/webpage-ex.md.
| ︙ | ︙ | |||
62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
href='$ROOT/timeline?namechng'>Example</a>
Show check-ins that contain file name changes
* <a target='_blank' class='exbtn'
href='$ROOT/timeline?u=drh&c=2014-01-08&y=ci'>Example</a>
Show check-ins circa 2014-01-08 by user "drh".
<big><b>→</b></big> (Hint: In the pages above, click the graph nodes
for any two check-ins or files to see a diff.)
<big><b>←</b></big>
* <a target='_blank' class='exbtn'
href='$ROOT/search?s=interesting+pages'>Example</a>
Full-text search for "interesting pages".
| > > > > > | 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
href='$ROOT/timeline?namechng'>Example</a>
Show check-ins that contain file name changes
* <a target='_blank' class='exbtn'
href='$ROOT/timeline?u=drh&c=2014-01-08&y=ci'>Example</a>
Show check-ins circa 2014-01-08 by user "drh".
* <a target='_blank' class='exbtn'
href='$ROOT/timeline?from=version-1.34&to=version-1.35&chng=src/timeline.c,src/doc.c'>Example</a>
Show all check-ins between version-1.34 and version-1.35 that make
changes to either of the files src/timeline.c or src/doc.c.
<big><b>→</b></big> (Hint: In the pages above, click the graph nodes
for any two check-ins or files to see a diff.)
<big><b>←</b></big>
* <a target='_blank' class='exbtn'
href='$ROOT/search?s=interesting+pages'>Example</a>
Full-text search for "interesting pages".
|
| ︙ | ︙ | |||
117 118 119 120 121 122 123 |
* <a target='_blank' class='exbtn'
href='$ROOT/bigbloblist'>Example</a>
The largest objects in the repository.
* <a target='_blank' class='exbtn'
href='$ROOT/hash-collisions'>Example</a>
SHA1 prefix collisions
| > > > > | 122 123 124 125 126 127 128 129 130 131 132 |
* <a target='_blank' class='exbtn'
href='$ROOT/bigbloblist'>Example</a>
The largest objects in the repository.
* <a target='_blank' class='exbtn'
href='$ROOT/hash-collisions'>Example</a>
SHA1 prefix collisions
* <a target='_blank' class='exbtn'
href='$ROOT/sitemap'>Example</a>
The "sitemap" containing links to many other pages
|
Changes to www/wikitheory.wiki.
1 2 3 | <title>Wiki In Fossil</title> <h2>Introduction</h2> | | > | | < < < < | < < | < < < < < < < < < < < < < | 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 |
<title>Wiki In Fossil</title>
<h2>Introduction</h2>
Fossil uses [/wiki_rules | Fossil wiki markup] and/or
[/md_rules | Markdown markup] for many things:
* Stand-alone wiki pages.
* Description and comments in [./bugtheory.wiki | bug reports].
* Check-in comments.
* [./embeddeddoc.wiki | Embedded documentation] files whose
name ends in ".wiki" or ".md" or ".markdown".
* [./event.wiki | Technical notes].
The [/wiki_rules | formatting rules for fossil wiki]
are designed to be simple and intuitive. The idea is that wiki provides
paragraph breaks, numbered and bulleted lists, and hyperlinking for
simple documents together with a safe subset of HTML for more complex
formatting tasks.
The [/md_rules | Markdown formatting rules] are more complex, but
are also more widely known, and are thus provided as an alternative.
<h2>Stand-alone Wiki Pages</h2>
Each wiki page has its own revision history which is independent of
the sequence of check-ins (check-ins). Wiki pages can branch and merge
just like check-ins, though as of this writing (2008-07-29) there is
no mechanism in the user interface to support branching and merging.
|
| ︙ | ︙ | |||
56 57 58 59 60 61 62 | Every change to a wiki page is a separate [./fileformat.wiki | control artifact] of type [./fileformat.wiki#wikichng | "Wiki Page"]. <h2>Embedded Documentation</h2> | | | > | | 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 | Every change to a wiki page is a separate [./fileformat.wiki | control artifact] of type [./fileformat.wiki#wikichng | "Wiki Page"]. <h2>Embedded Documentation</h2> Files in the source tree that use the ".wiki", ".md", or ".markdown" suffixes can be accessed and displayed using special URLs to the fossil server. This allows project documentation to be stored in the source tree and accessed online. (Details are described [./embeddeddoc.wiki | separately].) Some projects prefer to store their documentation in wiki. There is nothing wrong with that. But other projects prefer to keep documentation as part of the source tree, so that it is versioned along with the source tree and so that only developers with check-in privileges can change it. Embedded documentation serves this latter purpose. Both forms of documentation use the exact same markup. Some projects may choose to use both forms of documentation at the same time. Because the same format is used, it is trivial to move a file from wiki to embedded documentation or back again as the project evolves. <h2>Bug-reports and check-in comments</h2> The comments on check-ins and the text in the descriptions of bug reports both use wiki formatting. Exactly the same set of formatting rules apply. There is never a need to learn one formatting language for documentation and a different markup for bugs or for check-in comments. |