Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | merge trunk |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | multi-thread |
| Files: | files | file ages | folders |
| SHA1: |
e5a1100bccacfa08d238859ba5f5bb23 |
| User & Date: | jan.nijtmans 2014-12-06 15:57:00.000 |
Context
|
2014-12-06
| ||
| 16:57 | Fix merge conflict with trunk check-in: acd718448f user: jan.nijtmans tags: multi-thread | |
| 15:57 | merge trunk check-in: e5a1100bcc user: jan.nijtmans tags: multi-thread | |
| 15:47 | Merge the new DBP-workflow commands into trunk: bundle, purge, publish, and unpublished. check-in: a81a47f66c user: drh tags: trunk | |
|
2014-11-28
| ||
| 17:33 | merge trunk check-in: 59cde7bb12 user: jan.nijtmans tags: multi-thread | |
Changes
Added src/bundle.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 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 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 |
/*
** Copyright (c) 2014 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 file contains code used to implement and manage a "bundle" file.
*/
#include "config.h"
#include "bundle.h"
#include <assert.h>
/*
** 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 contain 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(
@ blobid INTEGER PRIMARY KEY, -- Blob ID
@ uuid TEXT NOT NULL, -- SHA1 hash of expanded blob
@ sz INT NOT NULL, -- Size of blob after expansion
@ delta ANY, -- Delta compression basis, or NULL
@ notes TEXT, -- Description of content
@ data BLOB -- compressed content
@ );
;
/*
** Attach a bundle file to the current database connection using the
** attachment name zBName.
*/
static void bundle_attach_file(
const char *zFile, /* Name of the file that contains the bundle */
const char *zBName, /* Attachment name */
int doInit /* Initialize a new bundle, if true */
){
int rc;
char *zErrMsg = 0;
char *zSql;
if( !doInit && file_size(zFile)<0 ){
fossil_fatal("no such file: %s", zFile);
}
assert( g.db );
zSql = sqlite3_mprintf("ATTACH %Q AS %Q", zFile, zBName);
if( zSql==0 ) fossil_fatal("out of memory");
rc = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg);
sqlite3_free(zSql);
if( rc!=SQLITE_OK || zErrMsg ){
if( zErrMsg==0 ) zErrMsg = sqlite3_errmsg(g.db);
fossil_fatal("not a valid bundle: %s", zFile);
}
if( doInit ){
db_multi_exec(zBundleInit /*works-like:"%w%w"*/, zBName, zBName);
}else{
sqlite3_stmt *pStmt;
zSql = sqlite3_mprintf("SELECT bcname, bcvalue"
" FROM \"%w\".bconfig", zBName);
if( zSql==0 ) fossil_fatal("out of memory");
rc = sqlite3_prepare(g.db, zSql, -1, &pStmt, 0);
if( rc ) fossil_fatal("not a valid bundle: %s", zFile);
sqlite3_free(zSql);
sqlite3_finalize(pStmt);
zSql = sqlite3_mprintf("SELECT blobid, uuid, sz, delta, notes, data"
" FROM \"%w\".bblob", zBName);
if( zSql==0 ) fossil_fatal("out of memory");
rc = sqlite3_prepare(g.db, zSql, -1, &pStmt, 0);
if( rc ) fossil_fatal("not a valid bundle: %s", zFile);
sqlite3_free(zSql);
sqlite3_finalize(pStmt);
}
}
/*
** fossil bundle ls BUNDLE ?OPTIONS?
**
** Display the content of a bundle in human-readable form.
*/
static void bundle_ls_cmd(void){
Stmt q;
sqlite3_int64 sumSz = 0;
sqlite3_int64 sumLen = 0;
int bDetails = find_option("details","l",0)!=0;
verify_all_options();
if( g.argc!=4 ) usage("ls BUNDLE ?OPTIONS?");
bundle_attach_file(g.argv[3], "b1", 0);
db_prepare(&q,
"SELECT bcname, bcvalue FROM bconfig"
" WHERE typeof(bcvalue)='text'"
" AND bcvalue NOT GLOB char(0x2a,0x0a,0x2a);"
);
while( db_step(&q)==SQLITE_ROW ){
fossil_print("%s: %s\n", db_column_text(&q,0), db_column_text(&q,1));
}
db_finalize(&q);
fossil_print("%.78c\n",'-');
if( bDetails ){
db_prepare(&q,
"SELECT blobid, substr(uuid,1,10), coalesce(substr(delta,1,10),''),"
" sz, length(data), notes"
" FROM bblob"
);
while( db_step(&q)==SQLITE_ROW ){
fossil_print("%4d %10s %10s %8d %8d %s\n",
db_column_int(&q,0),
db_column_text(&q,1),
db_column_text(&q,2),
db_column_int(&q,3),
db_column_int(&q,4),
db_column_text(&q,5));
sumSz += db_column_int(&q,3);
sumLen += db_column_int(&q,4);
}
db_finalize(&q);
fossil_print("%27s %8lld %8lld\n", "Total:", sumSz, sumLen);
}else{
db_prepare(&q,
"SELECT substr(uuid,1,16), notes FROM bblob"
);
while( db_step(&q)==SQLITE_ROW ){
fossil_print("%16s %s\n",
db_column_text(&q,0),
db_column_text(&q,1));
}
db_finalize(&q);
}
}
/*
** Implement the "fossil bundle append BUNDLE FILE..." command. Add
** the named files into the BUNDLE. Create the BUNDLE if it does not
** alraedy exist.
*/
static void bundle_append_cmd(void){
Blob content, hash;
int i;
Stmt q;
verify_all_options();
bundle_attach_file(g.argv[3], "b1", 1);
db_prepare(&q,
"INSERT INTO bblob(blobid, uuid, sz, delta, data, notes) "
"VALUES(NULL, $uuid, $sz, NULL, $data, $filename)");
db_begin_transaction();
for(i=4; i<g.argc; i++){
int sz;
blob_read_from_file(&content, g.argv[i]);
sz = blob_size(&content);
sha1sum_blob(&content, &hash);
blob_compress(&content, &content);
db_bind_text(&q, "$uuid", blob_str(&hash));
db_bind_int(&q, "$sz", sz);
db_bind_blob(&q, "$data", &content);
db_bind_text(&q, "$filename", g.argv[i]);
db_step(&q);
db_reset(&q);
blob_reset(&content);
blob_reset(&hash);
}
db_end_transaction(0);
db_finalize(&q);
}
/*
** Identify a subsection of the checkin tree using command-line switches.
** There must be one of the following switch available:
**
** --branch BRANCHNAME All checkins on the most recent
** instance of BRANCHNAME
** --from TAG1 [--to TAG2] Checkin TAG1 and all primary descendants
** up to and including TAG2
** --checkin TAG Checkin TAG only
**
** Store the RIDs for all applicable checkins in the zTab table that
** should already exist. Invoke fossil_fatal() if any kind of error is
** seen.
*/
void subtree_from_arguments(const char *zTab){
const char *zBr;
const char *zFrom;
const char *zTo;
const char *zCkin;
int rid = 0, endRid;
zBr = find_option("branch",0,1);
zFrom = find_option("from",0,1);
zTo = find_option("to",0,1);
zCkin = find_option("checkin",0,1);
if( zCkin ){
if( zFrom ) fossil_fatal("cannot use both --checkin and --from");
if( zBr ) fossil_fatal("cannot use both --checkin and --branch");
rid = symbolic_name_to_rid(zCkin, "ci");
endRid = rid;
}else{
endRid = zTo ? name_to_typed_rid(zTo, "ci") : 0;
}
if( zFrom ){
rid = name_to_typed_rid(zFrom, "ci");
}else if( zBr ){
rid = name_to_typed_rid(zBr, "br");
}else if( zCkin==0 ){
fossil_fatal("need one of: --branch, --from, --checkin");
}
db_multi_exec("INSERT OR IGNORE INTO \"%w\" VALUES(%d)", zTab, rid);
if( rid!=endRid ){
Blob sql;
blob_zero(&sql);
blob_appendf(&sql,
"WITH RECURSIVE child(rid) AS (VALUES(%d) UNION ALL "
" SELECT cid FROM plink, child"
" WHERE plink.pid=child.rid"
" AND plink.isPrim", rid);
if( endRid>0 ){
double endTime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d",
endRid);
blob_appendf(&sql,
" AND child.rid!=%d"
" AND (SELECT mtime FROM event WHERE objid=plink.cid)<=%.17g",
endRid, endTime
);
}
if( zBr ){
blob_appendf(&sql,
" AND EXISTS(SELECT 1 FROM tagxref"
" WHERE tagid=%d AND tagtype>0"
" AND value=%Q and rid=plink.cid)",
TAG_BRANCH, zBr);
}
blob_appendf(&sql, ") INSERT OR IGNORE INTO \"%w\" SELECT rid FROM child;",
zTab);
db_multi_exec("%s", blob_str(&sql)/*safe-for-%s*/);
}
}
/*
** COMMAND: test-subtree
**
** Usage: %fossil test-subtree ?OPTIONS?
**
** Show the subset of checkins that match the supplied options. This
** command is used to test the subtree_from_options() subroutine in the
** implementation and does not really have any other practical use that
** we know of.
**
** Options:
** --branch BRANCH Include only checkins on BRANCH
** --from TAG Start the subtree at TAG
** --to TAG End the subtree at TAG
** --checkin TAG The subtree is the single checkin TAG
** --all Include FILE and TAG artifacts
** --exclusive Include FILES exclusively on checkins
*/
void test_subtree_cmd(void){
int bAll = find_option("all",0,0)!=0;
int bExcl = find_option("exclusive",0,0)!=0;
db_find_and_open_repository(0,0);
db_begin_transaction();
db_multi_exec("CREATE TEMP TABLE tobundle(rid INTEGER PRIMARY KEY);");
subtree_from_arguments("tobundle");
verify_all_options();
if( bAll ) find_checkin_associates("tobundle",bExcl);
describe_artifacts_to_stdout("IN tobundle", 0);
db_end_transaction(1);
}
/* fossil bundle export BUNDLE ?OPTIONS?
**
** OPTIONS:
** --branch BRANCH --from TAG --to TAG
** --checkin TAG
** --standalone
*/
static void bundle_export_cmd(void){
int bStandalone = find_option("standalone",0,0)!=0;
int mnToBundle; /* Minimum RID in the bundle */
Stmt q;
/* Decode the arguments (like --branch) that specify which artifacts
** should be in the bundle */
db_multi_exec("CREATE TEMP TABLE tobundle(rid INTEGER PRIMARY KEY);");
subtree_from_arguments("tobundle");
find_checkin_associates("tobundle", 0);
verify_all_options();
describe_artifacts("IN tobundle");
if( g.argc!=4 ) usage("export BUNDLE ?OPTIONS?");
/* Create the new bundle */
bundle_attach_file(g.argv[3], "b1", 1);
db_begin_transaction();
/* Add 'mtime' and 'project-code' entries to the bconfig table */
db_multi_exec(
"INSERT INTO bconfig(bcname,bcvalue)"
" VALUES('mtime',datetime('now'));"
);
db_multi_exec(
"INSERT INTO bconfig(bcname,bcvalue)"
" SELECT name, value FROM config"
" WHERE name IN ('project-code');"
);
/* Directly copy content from the repository into the bundle as long
** as the repository content is a delta from some other artifact that
** is also in the bundle.
*/
db_multi_exec(
"REPLACE INTO bblob(blobid,uuid,sz,delta,data,notes) "
" SELECT"
" tobundle.rid,"
" blob.uuid,"
" blob.size,"
" delta.srcid,"
" blob.content,"
" (SELECT summary FROM description WHERE rid=blob.rid)"
" FROM tobundle, blob, delta"
" WHERE blob.rid=tobundle.rid"
" AND delta.rid=tobundle.rid"
" AND delta.srcid IN tobundle;"
);
/* For all the remaining artifacts, we need to construct their deltas
** manually.
*/
mnToBundle = db_int(0,"SELECT min(rid) FROM tobundle");
db_prepare(&q,
"SELECT rid FROM tobundle"
" WHERE rid NOT IN (SELECT blobid FROM bblob)"
" ORDER BY +rid;"
);
while( db_step(&q)==SQLITE_ROW ){
Blob content;
int rid = db_column_int(&q,0);
int deltaFrom = 0;
/* Get the raw, uncompressed content of the artifact into content */
content_get(rid, &content);
/* Try to find another artifact, not within the bundle, that is a
** plausible candidate for being a delta basis for the content. Set
** deltaFrom to the RID of that other artifact. Leave deltaFrom set
** to zero if the content should not be delta-compressed
*/
if( !bStandalone ){
if( db_exists("SELECT 1 FROM plink WHERE cid=%d",rid) ){
deltaFrom = db_int(0,
"SELECT max(cid) FROM plink"
" WHERE cid<%d", mnToBundle);
}else{
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 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;
}else{
Stmt ins;
blob_compress(&delta, &delta);
db_prepare(&ins,
"REPLACE INTO bblob(blobid,uuid,sz,delta,data,notes)"
" SELECT %d, uuid, size, (SELECT uuid FROM blob WHERE rid=%d),"
" :delta, (SELECT summary FROM description WHERE rid=blob.rid)"
" FROM blob WHERE rid=%d", rid, deltaFrom, rid);
db_bind_blob(&ins, ":delta", &delta);
db_step(&ins);
db_finalize(&ins);
}
blob_reset(&basis);
blob_reset(&delta);
}
/* If unable to insert the artifact as a delta, insert full-text */
if( deltaFrom==0 ){
Stmt ins;
blob_compress(&content, &content);
db_prepare(&ins,
"REPLACE INTO bblob(blobid,uuid,sz,delta,data,notes)"
" SELECT rid, uuid, size, NULL, :content,"
" (SELECT summary FROM description WHERE rid=blob.rid)"
" FROM blob WHERE rid=%d", rid);
db_bind_blob(&ins, ":content", &content);
db_step(&ins);
db_finalize(&ins);
}
blob_reset(&content);
}
db_finalize(&q);
db_end_transaction(0);
}
/*
** There is a TEMP table bix(blobid,delta) containing a set of purgeitems
** that need to be transferred to the BLOB table. This routine does
** all items that have srcid=iSrc. The pBasis blob holds the content
** of the source document if iSrc>0.
*/
static void bundle_import_elements(int iSrc, Blob *pBasis, int isPriv){
Stmt q;
static Bag busy;
assert( pBasis!=0 || iSrc==0 );
if( iSrc>0 ){
if( bag_find(&busy, iSrc) ){
fossil_fatal("delta loop while uncompressing bundle artifacts");
}
bag_insert(&busy, iSrc);
}
db_prepare(&q,
"SELECT uuid, data, bblob.delta, bix.blobid"
" FROM bix, bblob"
" WHERE bix.delta=%d"
" AND bix.blobid=bblob.blobid;",
iSrc
);
while( db_step(&q)==SQLITE_ROW ){
Blob h1, h2, c1, c2;
int rid;
blob_zero(&h1);
db_column_blob(&q, 0, &h1);
blob_zero(&c1);
db_column_blob(&q, 1, &c1);
blob_uncompress(&c1, &c1);
blob_zero(&c2);
if( db_column_type(&q,2)==SQLITE_TEXT && db_column_bytes(&q,2)==40 ){
Blob basis;
rid = db_int(0,"SELECT rid FROM blob WHERE uuid=%Q",
db_column_text(&q,2));
content_get(rid, &basis);
blob_delta_apply(&basis, &c1, &c2);
blob_reset(&basis);
blob_reset(&c1);
}else if( pBasis ){
blob_delta_apply(pBasis, &c1, &c2);
blob_reset(&c1);
}else{
c2 = c1;
}
sha1sum_blob(&c2, &h2);
if( blob_compare(&h1, &h2)!=0 ){
fossil_fatal("SHA1 hash mismatch - wanted %s, got %s",
blob_str(&h1), blob_str(&h2));
}
blob_reset(&h2);
rid = content_put_ex(&c2, blob_str(&h1), 0, 0, isPriv);
if( rid==0 ){
fossil_fatal("%s", g.zErrMsg);
}else{
if( !isPriv ) content_make_public(rid);
content_get(rid, &c1);
manifest_crosslink(rid, &c1, MC_NO_ERRORS);
db_multi_exec("INSERT INTO got(rid) VALUES(%d)",rid);
}
bundle_import_elements(db_column_int(&q,3), &c2, isPriv);
blob_reset(&c2);
}
db_finalize(&q);
if( iSrc>0 ) bag_remove(&busy, iSrc);
}
/*
** Extract an item from content from the bundle
*/
static void bundle_extract_item(
int blobid, /* ID of the item to extract */
Blob *pOut /* Write the content into this blob */
){
Stmt q;
Blob x, basis, h1, h2;
static Bag busy;
db_prepare(&q, "SELECT uuid, delta, data FROM bblob"
" WHERE blobid=%d", blobid);
if( db_step(&q)!=SQLITE_ROW ){
db_finalize(&q);
fossil_fatal("no such item: %d", blobid);
}
if( bag_find(&busy, blobid) ) fossil_fatal("delta loop");
blob_zero(&x);
db_column_blob(&q, 2, &x);
blob_uncompress(&x, &x);
if( db_column_type(&q,1)==SQLITE_INTEGER ){
bundle_extract_item(db_column_int(&q,1), &basis);
blob_delta_apply(&basis, &x, pOut);
blob_reset(&basis);
blob_reset(&x);
}else if( db_column_type(&q,1)==SQLITE_TEXT ){
int rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q",
db_column_text(&q,1));
if( rid==0 ){
fossil_fatal("cannot find delta basis %s", db_column_text(&q,1));
}
content_get(rid, &basis);
db_column_blob(&q, 2, &x);
blob_delta_apply(&basis, &x, pOut);
blob_reset(&basis);
blob_reset(&x);
}else{
*pOut = x;
}
blob_zero(&h1);
db_column_blob(&q, 0, &h1);
sha1sum_blob(pOut, &h2);
if( blob_compare(&h1, &h2)!=0 ){
fossil_fatal("SHA1 hash mismatch - wanted %s, got %s",
blob_str(&h1), blob_str(&h2));
}
blob_reset(&h1);
blob_reset(&h2);
bag_remove(&busy, blobid);
db_finalize(&q);
}
/* fossil bundle cat BUNDLE UUID...
**
** Write elements of a bundle on standard output
*/
static void bundle_cat_cmd(void){
int i;
Blob x;
verify_all_options();
if( g.argc<5 ) usage("cat BUNDLE UUID...");
bundle_attach_file(g.argv[3], "b1", 1);
blob_zero(&x);
for(i=4; i<g.argc; i++){
int blobid = db_int(0,"SELECT blobid FROM bblob WHERE uuid LIKE '%q%%'",
g.argv[i]);
if( blobid==0 ){
fossil_fatal("no such artifact in bundle: %s", g.argv[i]);
}
bundle_extract_item(blobid, &x);
blob_write_to_file(&x, "-");
blob_reset(&x);
}
}
/* fossil bundle import BUNDLE ?OPTIONS?
**
** Attempt to import the changes contained in BUNDLE. Make the change
** private so that they do not sync.
**
** OPTIONS:
** --force Import even if the project-code does not match
** --publish Imported changes are not private
*/
static void bundle_import_cmd(void){
int forceFlag = find_option("force","f",0)!=0;
int isPriv = find_option("publish",0,0)==0;
char *zMissingDeltas;
verify_all_options();
if ( g.argc!=4 ) usage("import BUNDLE ?OPTIONS?");
bundle_attach_file(g.argv[3], "b1", 1);
/* Only import a bundle that was generated from a repo with the same
** project code, unless the --force flag is true */
if( !forceFlag ){
if( !db_exists("SELECT 1 FROM config, bconfig"
" WHERE config.name='project-code'"
" AND bconfig.bcname='project-code'"
" AND config.value=bconfig.bcvalue;")
){
fossil_fatal("project-code in the bundle does not match the "
"repository project code. (override with --force).");
}
}
/* If the bundle contains deltas with a basis that is external to the
** bundle and those external basis files are missing from the local
** repo, then the delta encodings cannot be decoded and the bundle cannot
** be extracted. */
zMissingDeltas = db_text(0,
"SELECT group_concat(substr(delta,1,10),' ')"
" FROM bblob"
" WHERE typeof(delta)='text' AND length(delta)=40"
" AND NOT EXISTS(SELECT 1 FROM blob WHERE uuid=bblob.delta)");
if( zMissingDeltas && zMissingDeltas[0] ){
fossil_fatal("delta basis artifacts not found in repository: %s",
zMissingDeltas);
}
db_begin_transaction();
db_multi_exec(
"CREATE TEMP TABLE bix("
" blobid INTEGER PRIMARY KEY,"
" delta INTEGER"
");"
"CREATE INDEX bixdelta ON bix(delta);"
"INSERT INTO bix(blobid,delta)"
" SELECT blobid,"
" CASE WHEN typeof(delta)=='integer'"
" THEN delta ELSE 0 END"
" FROM bblob"
" WHERE NOT EXISTS(SELECT 1 FROM blob WHERE uuid=bblob.uuid AND size>=0);"
"CREATE TEMP TABLE got(rid INTEGER PRIMARY KEY ON CONFLICT IGNORE);"
);
manifest_crosslink_begin();
bundle_import_elements(0, 0, isPriv);
manifest_crosslink_end(0);
describe_artifacts_to_stdout("IN got", "Imported content:");
db_end_transaction(0);
}
/* fossil bundle purge BUNDLE
**
** Try to undo a prior "bundle import BUNDLE".
**
** If the --force option is omitted, then this will only work if
** there have been no checkins or tags added that use the import.
**
** This routine never removes content that is not already in the bundle
** so the bundle serves as a backup. The purge can be undone using
** "fossil bundle import BUNDLE".
*/
static void bundle_purge_cmd(void){
int bForce = find_option("force",0,0)!=0;
int bTest = find_option("test",0,0)!=0; /* Undocumented --test option */
const char *zFile = g.argv[3];
verify_all_options();
if ( g.argc!=4 ) usage("purge BUNDLE ?OPTIONS?");
bundle_attach_file(zFile, "b1", 0);
db_begin_transaction();
/* Find all checkins of the bundle */
db_multi_exec(
"CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY);"
"INSERT OR IGNORE INTO ok SELECT blob.rid FROM bblob, blob, plink"
" WHERE bblob.uuid=blob.uuid"
" AND plink.cid=blob.rid;"
);
/* Check to see if new checkins have been committed to checkins in
** the bundle. Do not allow the purge if that is true and if --force
** is omitted.
*/
if( !bForce ){
Stmt q;
int n = 0;
db_prepare(&q,
"SELECT cid FROM plink WHERE pid IN ok AND cid NOT IN ok"
);
while( db_step(&q)==SQLITE_ROW ){
whatis_rid(db_column_int(&q,0),0);
fossil_print("%.78c\n", '-');
n++;
}
db_finalize(&q);
if( n>0 ){
fossil_fatal("checkins above are derived from checkins in the bundle.");
}
}
/* Find all files associated with those check-ins that are used
** nowhere else. */
find_checkin_associates("ok", 1);
/* Check to see if any associated files are not in the bundle. Issue
** an error if there are any, unless --force is used.
*/
if( !bForce ){
db_multi_exec(
"CREATE TEMP TABLE err1(rid INTEGER PRIMARY KEY);"
"INSERT INTO err1 "
" SELECT blob.rid FROM ok CROSS JOIN blob"
" WHERE blob.rid=ok.rid"
" AND blob.uuid NOT IN (SELECT uuid FROM bblob);"
);
if( db_changes() ){
describe_artifacts_to_stdout("IN err1", 0);
fossil_fatal("artifacts above associated with bundle checkins "
" are not in the bundle");
}else{
db_multi_exec("DROP TABLE err1;");
}
}
if( bTest ){
describe_artifacts_to_stdout(
"IN (SELECT blob.rid FROM ok, blob, bblob"
" WHERE blob.rid=ok.rid AND blob.uuid=bblob.uuid)",
"Purged artifacts found in the bundle:");
describe_artifacts_to_stdout(
"IN (SELECT blob.rid FROM ok, blob"
" WHERE blob.rid=ok.rid "
" AND blob.uuid NOT IN (SELECT uuid FROM bblob))",
"Purged artifacts NOT in the bundle:");
describe_artifacts_to_stdout(
"IN (SELECT blob.rid FROM bblob, blob"
" WHERE blob.uuid=bblob.uuid "
" AND blob.rid NOT IN ok)",
"Artifacts in the bundle but not purged:");
}else{
purge_artifact_list("ok",0,0);
}
db_end_transaction(0);
}
/*
** COMMAND: bundle
**
** Usage: %fossil bundle SUBCOMMAND ARGS...
**
** fossil bundle append BUNDLE FILE...
**
** Add files named on the command line to BUNDLE. This subcommand has
** little practical use and is mostly intended for testing.
**
** fossil bundle cat BUNDLE UUID...
**
** Extract one or more artifacts from the bundle and write them
** consecutively on standard output. This subcommand was designed
** for testing and introspection of bundles and is not something
** commonly used.
**
** fossil bundle export BUNDLE ?OPTIONS?
**
** Generate a new bundle, in the file named BUNDLE, that contains a
** subset of the checkins in the repository (usually a single branch)
** described by the --branch, --from, --to, and/or --checkin options,
** at least one of which is required. If BUNDLE already exists, the
** specified content is added to the bundle.
**
** --branch BRANCH Package all check-ins on BRANCH.
** --from TAG1 --to TAG2 Package checkins between TAG1 and TAG2.
** --checkin TAG Package the single checkin TAG
** --standalone Do no use delta-encoding against
** artifacts not in the bundle
**
** fossil bundle extend BUNDLE
**
** The BUNDLE must already exist. This subcommand adds to the bundle
** any checkins that are descendants of checkins already in the bundle,
** and any tags that apply to artifacts in the bundle.
**
** fossil bundle import BUNDLE ?--publish?
**
** Import all content from BUNDLE into the repository. By default, the
** imported files are private and will not sync. Use the --publish
** option makes the import public.
**
** fossil bundle ls BUNDLE
**
** List the contents of BUNDLE on standard output
**
** fossil bundle purge BUNDLE
**
** Remove from the repository all files that are used exclusively
** by checkins in BUNDLE. This has the effect of undoing a
** "fossil bundle import".
**
** SUMMARY:
** fossil bundle append BUNDLE FILE... Add files to BUNDLE
** fossil bundle cat BUNDLE UUID... Extract file from BUNDLE
** fossil bundle export BUNDLE ?OPTIONS? Create a new BUNDLE
** --branch BRANCH --from TAG1 --to TAG2 Checkins to include
** --checkin TAG Use only checkin TAG
** --standalone Omit dependencies
** fossil bundle extend BUNDLE Update with newer content
** fossil bundle import BUNDLE ?OPTIONS? Import a bundle
** --publish Publish the import
** --force Cross-repo import
** fossil bundle ls BUNDLE List content of a bundle
** fossil bundle purge BUNDLE Undo an import
*/
void bundle_cmd(void){
const char *zSubcmd;
int n;
if( g.argc<4 ) usage("SUBCOMMAND BUNDLE ?OPTIONS?");
zSubcmd = g.argv[2];
db_find_and_open_repository(0,0);
n = (int)strlen(zSubcmd);
if( strncmp(zSubcmd, "append", n)==0 ){
bundle_append_cmd();
}else if( strncmp(zSubcmd, "cat", n)==0 ){
bundle_cat_cmd();
}else if( strncmp(zSubcmd, "export", n)==0 ){
bundle_export_cmd();
}else if( strncmp(zSubcmd, "extend", n)==0 ){
fossil_fatal("not yet implemented");
}else if( strncmp(zSubcmd, "import", n)==0 ){
bundle_import_cmd();
}else if( strncmp(zSubcmd, "ls", n)==0 ){
bundle_ls_cmd();
}else if( strncmp(zSubcmd, "purge", n)==0 ){
bundle_purge_cmd();
}else{
fossil_fatal("unknown subcommand for bundle: %s", zSubcmd);
}
}
|
Changes to src/codecheck1.c.
| ︙ | ︙ | |||
307 308 309 310 311 312 313 314 315 316 317 318 319 320 |
** string.
*/
struct {
const char *zFName; /* Name of the function */
int iFmtArg; /* Index of format argument. Leftmost is 1. */
unsigned fmtFlags; /* Processing flags */
} aFmtFunc[] = {
{ "blob_append_sql", 2, FMT_NO_S },
{ "blob_appendf", 2, 0 },
{ "cgi_panic", 1, 0 },
{ "cgi_redirectf", 1, 0 },
{ "db_blob", 2, FMT_NO_S },
{ "db_double", 2, FMT_NO_S },
{ "db_err", 1, 0 },
| > | 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 |
** string.
*/
struct {
const char *zFName; /* Name of the function */
int iFmtArg; /* Index of format argument. Leftmost is 1. */
unsigned fmtFlags; /* Processing flags */
} aFmtFunc[] = {
{ "admin_log", 1, 0 },
{ "blob_append_sql", 2, FMT_NO_S },
{ "blob_appendf", 2, 0 },
{ "cgi_panic", 1, 0 },
{ "cgi_redirectf", 1, 0 },
{ "db_blob", 2, FMT_NO_S },
{ "db_double", 2, FMT_NO_S },
{ "db_err", 1, 0 },
|
| ︙ | ︙ |
Changes to src/content.c.
| ︙ | ︙ | |||
565 566 567 568 569 570 571 |
);
db_bind_blob(&s1, ":data", &cmpr);
db_exec(&s1);
rid = db_last_insert_rowid();
if( !pBlob ){
db_multi_exec("INSERT OR IGNORE INTO phantom VALUES(%d)", rid);
}
| > | | | < | 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 |
);
db_bind_blob(&s1, ":data", &cmpr);
db_exec(&s1);
rid = db_last_insert_rowid();
if( !pBlob ){
db_multi_exec("INSERT OR IGNORE INTO phantom VALUES(%d)", rid);
}
}
if( g.markPrivate || isPrivate ){
db_multi_exec("INSERT INTO private VALUES(%d)", rid);
markAsUnclustered = 0;
}
if( nBlob==0 ) blob_reset(&cmpr);
/* If the srcId is specified, then the data we just added is
** really a delta. Record this fact in the delta table.
*/
if( srcId ){
|
| ︙ | ︙ |
Changes to src/db.c.
| ︙ | ︙ | |||
422 423 424 425 426 427 428 429 430 431 432 433 434 435 |
return sqlite3_changes(g.db);
}
/*
** Extract text, integer, or blob values from the N-th column of the
** current row.
*/
int db_column_bytes(Stmt *pStmt, int N){
return sqlite3_column_bytes(pStmt->pStmt, N);
}
int db_column_int(Stmt *pStmt, int N){
return sqlite3_column_int(pStmt->pStmt, N);
}
i64 db_column_int64(Stmt *pStmt, int N){
| > > > | 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 |
return sqlite3_changes(g.db);
}
/*
** Extract text, integer, or blob values from the N-th column of the
** current row.
*/
int db_column_type(Stmt *pStmt, int N){
return sqlite3_column_type(pStmt->pStmt, N);
}
int db_column_bytes(Stmt *pStmt, int N){
return sqlite3_column_bytes(pStmt->pStmt, N);
}
int db_column_int(Stmt *pStmt, int N){
return sqlite3_column_int(pStmt->pStmt, N);
}
i64 db_column_int64(Stmt *pStmt, int N){
|
| ︙ | ︙ | |||
484 485 486 487 488 489 490 491 492 493 494 495 496 497 |
int db_exec(Stmt *pStmt){
int rc;
while( (rc = db_step(pStmt))==SQLITE_ROW ){}
rc = db_reset(pStmt);
db_check_result(rc);
return rc;
}
/*
** Execute multiple SQL statements.
*/
int db_multi_exec(const char *zSql, ...){
Blob sql;
int rc = SQLITE_OK;
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
int db_exec(Stmt *pStmt){
int rc;
while( (rc = db_step(pStmt))==SQLITE_ROW ){}
rc = db_reset(pStmt);
db_check_result(rc);
return rc;
}
/*
** Print the output of one or more SQL queries on standard output.
** This routine is used for debugging purposes only.
*/
int db_debug(const char *zSql, ...){
Blob sql;
int rc = SQLITE_OK;
va_list ap;
const char *z, *zEnd;
sqlite3_stmt *pStmt;
blob_init(&sql, 0, 0);
va_start(ap, zSql);
blob_vappendf(&sql, zSql, ap);
va_end(ap);
z = blob_str(&sql);
while( rc==SQLITE_OK && z[0] ){
pStmt = 0;
rc = sqlite3_prepare_v2(g.db, z, -1, &pStmt, &zEnd);
if( rc!=SQLITE_OK ) break;
if( pStmt ){
int nRow = 0;
db.nPrepare++;
while( sqlite3_step(pStmt)==SQLITE_ROW ){
int i, n;
if( nRow++ > 0 ) fossil_print("\n");
n = sqlite3_column_count(pStmt);
for(i=0; i<n; i++){
fossil_print("%s = %s\n", sqlite3_column_name(pStmt, i),
sqlite3_column_text(pStmt,i));
}
}
rc = sqlite3_finalize(pStmt);
if( rc ) db_err("%s: {%.*s}", sqlite3_errmsg(g.db), (int)(zEnd-z), z);
}
z = zEnd;
}
blob_reset(&sql);
return rc;
}
/*
** Execute multiple SQL statements.
*/
int db_multi_exec(const char *zSql, ...){
Blob sql;
int rc = SQLITE_OK;
|
| ︙ | ︙ | |||
704 705 706 707 708 709 710 711 712 713 714 715 716 717 |
int rc = mtime_of_manifest_file(sqlite3_value_int(argv[0]),
sqlite3_value_int(argv[1]), &mtime);
if( rc==0 ){
sqlite3_result_int64(context, mtime);
}
}
/*
** 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;
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
int rc = mtime_of_manifest_file(sqlite3_value_int(argv[0]),
sqlite3_value_int(argv[1]), &mtime);
if( rc==0 ){
sqlite3_result_int64(context, mtime);
}
}
void db_sym2rid_function(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
char const * arg;
char const * type;
if(1 != argc && 2 != argc){
sqlite3_result_error(context, "Expecting one or two arguments", -1);
return;
}
arg = (const char*)sqlite3_value_text(argv[0]);
if(!arg){
sqlite3_result_error(context, "Expecting a STRING argument", -1);
}else{
int rid;
type = (2==argc) ? (const char*)sqlite3_value_text(argv[1]) : 0;
if(!type) type = "ci";
rid = symbolic_name_to_rid( arg, type );
if(rid<0){
sqlite3_result_error(context, "Symbolic name is ambiguous.", -1);
}else if(0==rid){
sqlite3_result_null(context);
}else{
sqlite3_result_int64(context, rid);
}
}
}
/*
** 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;
|
| ︙ | ︙ | |||
736 737 738 739 740 741 742 743 744 745 746 747 748 749 |
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(db, db_sql_trace, 0);
re_add_sql_func(db);
foci_register(db);
sqlite3_exec(db, "PRAGMA foreign_keys=OFF;", 0, 0, 0);
#if USE_SYSTEM_SQLITE+0==1
sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, g.maxWorkerThreads);
| > > > > > > > > | 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 |
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
);
sqlite3_create_function(
db, "symbolic_name_to_rid", 1, SQLITE_UTF8, 0, db_sym2rid_function,
0, 0
);
sqlite3_create_function(
db, "symbolic_name_to_rid", 2, SQLITE_UTF8, 0, db_sym2rid_function,
0, 0
);
if( g.fSqlTrace ) sqlite3_trace(db, db_sql_trace, 0);
re_add_sql_func(db);
foci_register(db);
sqlite3_exec(db, "PRAGMA foreign_keys=OFF;", 0, 0, 0);
#if USE_SYSTEM_SQLITE+0==1
sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, g.maxWorkerThreads);
|
| ︙ | ︙ | |||
2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 |
int versionable; /* Is this setting versionable? */
int forceTextArea; /* Force using a text area for display? */
const char *def; /* Default value */
};
#endif /* INTERFACE */
struct stControlSettings const ctrlSettings[] = {
{ "access-log", 0, 0, 0, 0, "off" },
{ "allow-symlinks", 0, 0, 1, 0, "off" },
{ "auto-captcha", "autocaptcha", 0, 0, 0, "on" },
{ "auto-hyperlink", 0, 0, 0, 0, "on", },
{ "auto-shun", 0, 0, 0, 0, "on" },
{ "autosync", 0, 0, 0, 0, "on" },
{ "autosync-tries", 0, 16, 0, 0, "1" },
{ "binary-glob", 0, 40, 1, 0, "" },
| > | 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 |
int versionable; /* Is this setting versionable? */
int forceTextArea; /* Force using a text area for display? */
const char *def; /* Default value */
};
#endif /* INTERFACE */
struct stControlSettings const ctrlSettings[] = {
{ "access-log", 0, 0, 0, 0, "off" },
{ "admin-log", 0, 0, 0, 0, "off" },
{ "allow-symlinks", 0, 0, 1, 0, "off" },
{ "auto-captcha", "autocaptcha", 0, 0, 0, "on" },
{ "auto-hyperlink", 0, 0, 0, 0, "on", },
{ "auto-shun", 0, 0, 0, 0, "on" },
{ "autosync", 0, 0, 0, 0, "on" },
{ "autosync-tries", 0, 16, 0, 0, "1" },
{ "binary-glob", 0, 40, 1, 0, "" },
|
| ︙ | ︙ | |||
2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 | ** file exists. ** ** The "unset" command clears a property setting. ** ** ** access-log If enabled, record successful and failed login attempts ** in the "accesslog" table. Default: off ** ** allow-symlinks If enabled, don't follow symlinks, and instead treat ** (versionable) them as symlinks on Unix. Has no effect on Windows ** (existing links in repository created on Unix become ** plain-text files with link destination path inside). ** Default: off ** | > > > | 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 | ** file exists. ** ** The "unset" command clears a property setting. ** ** ** access-log If enabled, record successful and failed login attempts ** in the "accesslog" table. Default: off ** ** admin-log If enabled, record configuration changes in the ** "admin_log" table. Default: off ** ** allow-symlinks If enabled, don't follow symlinks, and instead treat ** (versionable) them as symlinks on Unix. Has no effect on Windows ** (existing links in repository created on Unix become ** plain-text files with link destination path inside). ** Default: off ** |
| ︙ | ︙ | |||
2674 2675 2676 2677 2678 2679 2680 |
blob_append_sql(&allSql,
"ALTER TABLE \"%w\" RENAME TO \"x_%w\";\n"
"%s WITHOUT ROWID;\n"
"INSERT INTO \"%w\" SELECT * FROM \"x_%w\";\n"
"DROP TABLE \"x_%w\";\n",
zTName, zTName, blob_sql_text(&newSql), zTName, zTName, zTName
);
| | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 |
blob_append_sql(&allSql,
"ALTER TABLE \"%w\" RENAME TO \"x_%w\";\n"
"%s WITHOUT ROWID;\n"
"INSERT INTO \"%w\" SELECT * FROM \"x_%w\";\n"
"DROP TABLE \"x_%w\";\n",
zTName, zTName, blob_sql_text(&newSql), zTName, zTName, zTName
);
fossil_print("Converting table %s of %s to WITHOUT ROWID.\n",
zTName, g.argv[i]);
blob_reset(&newSql);
}
blob_append_sql(&allSql, "COMMIT;\n");
db_finalize(&q);
if( dryRun ){
fossil_print("SQL that would have been evaluated:\n");
fossil_print("%.78c\n", '-');
fossil_print("%s", blob_sql_text(&allSql));
}else{
db_multi_exec("%s", blob_sql_text(&allSql));
}
blob_reset(&allSql);
db_close(1);
}
}
/*
** Make sure the adminlog table exists. Create it if it does not
*/
void create_admin_log_table(void){
static int once = 0;
if( once ) return;
once = 1;
db_multi_exec(
"CREATE TABLE IF NOT EXISTS \"%w\".admin_log(\n"
" id INTEGER PRIMARY KEY,\n"
" time INTEGER, -- Seconds since 1970\n"
" page TEXT, -- path of page\n"
" who TEXT, -- User who made the change\n "
" what TEXT -- What changed\n"
")", db_name("repository")
);
}
/*
** Write a message into the admin_event table, if admin logging is
** enabled via the admin-log configuration option.
*/
void admin_log(const char *zFormat, ...){
Blob what = empty_blob;
va_list ap;
if( !db_get_boolean("admin-log", 0) ){
/* Potential leak here (on %z params) but
the alternative is to let blob_vappendf()
do it below. */
return;
}
create_admin_log_table();
va_start(ap,zFormat);
blob_vappendf( &what, zFormat, ap );
va_end(ap);
db_multi_exec("INSERT INTO admin_log(time,page,who,what)"
" VALUES(now(), %Q, %Q, %B)",
g.zPath, g.zLogin, &what);
blob_reset(&what);
}
|
Changes to src/descendants.c.
| ︙ | ︙ | |||
287 288 289 290 291 292 293 | db_finalize(&ins); db_finalize(&q); } /* ** COMMAND: descendants* ** | | | | | 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 | db_finalize(&ins); db_finalize(&q); } /* ** COMMAND: descendants* ** ** Usage: %fossil descendants ?CHECKIN? ?OPTIONS? ** ** Find all leaf descendants of the checkin specified or if the argument ** is omitted, of the checkin currently checked out. ** ** Options: ** -R|--repository FILE Extract info from repository FILE ** -W|--width <num> Width of lines (default is to auto-detect). ** Must be >20 or 0 (= no limit, resulting in a ** single line per entry). ** |
| ︙ | ︙ | |||
332 333 334 335 336 337 338 |
compute_leaves(base, 0);
db_prepare(&q,
"%s"
" AND event.objid IN (SELECT rid FROM leaves)"
" ORDER BY event.mtime DESC",
timeline_query_for_tty()
);
| | | 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 |
compute_leaves(base, 0);
db_prepare(&q,
"%s"
" AND event.objid IN (SELECT rid FROM leaves)"
" ORDER BY event.mtime DESC",
timeline_query_for_tty()
);
print_timeline(&q, 0, width, 0);
db_finalize(&q);
}
/*
** COMMAND: leaves*
**
** Usage: %fossil leaves ?OPTIONS?
|
| ︙ | ︙ |
Changes to src/finfo.c.
| ︙ | ︙ | |||
493 494 495 496 497 498 499 500 501 502 503 504 505 506 |
int srcid = db_int(0, "SELECT srcid FROM delta WHERE rid=%d", frid);
int sz = db_int(0, "SELECT length(content) FROM blob WHERE rid=%d", frid);
@ <br>fid=%d(frid) pid=%d(fpid) mid=%d(fmid) sz=%d(sz)
if( srcid ){
@ srcid=%d(srcid)
}
}
@ </td></tr>
}
db_finalize(&q);
if( pGraph ){
graph_finish(pGraph, 0);
if( pGraph->nErr ){
graph_free(pGraph);
| > | 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 |
int srcid = db_int(0, "SELECT srcid FROM delta WHERE rid=%d", frid);
int sz = db_int(0, "SELECT length(content) FROM blob WHERE rid=%d", frid);
@ <br>fid=%d(frid) pid=%d(fpid) mid=%d(fmid) sz=%d(sz)
if( srcid ){
@ srcid=%d(srcid)
}
}
tag_private_status(frid);
@ </td></tr>
}
db_finalize(&q);
if( pGraph ){
graph_finish(pGraph, 0);
if( pGraph->nErr ){
graph_free(pGraph);
|
| ︙ | ︙ |
Changes to src/foci.c.
| ︙ | ︙ | |||
102 103 104 105 106 107 108 |
return SQLITE_OK;
}
/*
** Open a new focivfs cursor.
*/
static int fociOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
| < < < | 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
return SQLITE_OK;
}
/*
** Open a new focivfs cursor.
*/
static int fociOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
FociCursor *pCsr;
pCsr = (FociCursor *)sqlite3_malloc(sizeof(FociCursor));
memset(pCsr, 0, sizeof(FociCursor));
pCsr->base.pVtab = pVTab;
*ppCursor = (sqlite3_vtab_cursor *)pCsr;
return SQLITE_OK;
}
|
| ︙ | ︙ |
Changes to src/info.c.
| ︙ | ︙ | |||
929 930 931 932 933 934 935 936 937 938 939 940 941 942 |
@ tags: %s(blob_str(&links)),
blob_reset(&links);
}else{
@ tags: %h(zTagList),
}
@ date:
hyperlink_to_date(zDate, ")");
}
db_finalize(&q);
}
/*
** WEBPAGE: vdiff
| > | 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 |
@ tags: %s(blob_str(&links)),
blob_reset(&links);
}else{
@ tags: %h(zTagList),
}
@ date:
hyperlink_to_date(zDate, ")");
tag_private_status(rid);
}
db_finalize(&q);
}
/*
** WEBPAGE: vdiff
|
| ︙ | ︙ | |||
1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 |
@ <li>Executable file
objType |= OBJTYPE_EXE;
}else{
@ <li>File
}
objType |= OBJTYPE_CONTENT;
@ %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
if( showDetail ){
@ <ul>
}
prevName = fossil_strdup(zName);
}
if( showDetail ){
@ <li>
hyperlink_to_date(zDate,"");
| > | | 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 |
@ <li>Executable file
objType |= OBJTYPE_EXE;
}else{
@ <li>File
}
objType |= OBJTYPE_CONTENT;
@ %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
tag_private_status(rid);
if( showDetail ){
@ <ul>
}
prevName = fossil_strdup(zName);
}
if( showDetail ){
@ <li>
hyperlink_to_date(zDate,"");
@ — part of checkin
hyperlink_to_uuid(zVers);
}else{
@ — part of checkin
hyperlink_to_uuid(zVers);
@ at
hyperlink_to_date(zDate,"");
}
|
| ︙ | ︙ | |||
1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 |
}
@ - %!w(zCom) by
hyperlink_to_user(zUser,zDate," on");
hyperlink_to_date(zDate, ".");
if( pDownloadName && blob_size(pDownloadName)==0 ){
blob_appendf(pDownloadName, "%.10s.txt", zUuid);
}
cnt++;
}
db_finalize(&q);
}
db_prepare(&q,
"SELECT target, filename, datetime(mtime), user, src"
" FROM attachment"
| > | 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 |
}
@ - %!w(zCom) by
hyperlink_to_user(zUser,zDate," on");
hyperlink_to_date(zDate, ".");
if( pDownloadName && blob_size(pDownloadName)==0 ){
blob_appendf(pDownloadName, "%.10s.txt", zUuid);
}
tag_private_status(rid);
cnt++;
}
db_finalize(&q);
}
db_prepare(&q,
"SELECT target, filename, datetime(mtime), user, src"
" FROM attachment"
|
| ︙ | ︙ | |||
1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 |
@ added by
hyperlink_to_user(zUser,zDate," on");
hyperlink_to_date(zDate,".");
cnt++;
if( pDownloadName && blob_size(pDownloadName)==0 ){
blob_append(pDownloadName, zFilename, -1);
}
}
db_finalize(&q);
if( cnt==0 ){
@ Control artifact.
if( pDownloadName && blob_size(pDownloadName)==0 ){
blob_appendf(pDownloadName, "%.10s.txt", zUuid);
}
}
return objType;
}
/*
** WEBPAGE: fdiff
| > > | 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 |
@ added by
hyperlink_to_user(zUser,zDate," on");
hyperlink_to_date(zDate,".");
cnt++;
if( pDownloadName && blob_size(pDownloadName)==0 ){
blob_append(pDownloadName, zFilename, -1);
}
tag_private_status(rid);
}
db_finalize(&q);
if( cnt==0 ){
@ Control artifact.
if( pDownloadName && blob_size(pDownloadName)==0 ){
blob_appendf(pDownloadName, "%.10s.txt", zUuid);
}
tag_private_status(rid);
}
return objType;
}
/*
** WEBPAGE: fdiff
|
| ︙ | ︙ |
Changes to src/main.mk.
| ︙ | ︙ | |||
19 20 21 22 23 24 25 26 27 28 29 30 31 32 | $(SRCDIR)/attach.c \ $(SRCDIR)/bag.c \ $(SRCDIR)/bisect.c \ $(SRCDIR)/blob.c \ $(SRCDIR)/branch.c \ $(SRCDIR)/browse.c \ $(SRCDIR)/builtin.c \ $(SRCDIR)/cache.c \ $(SRCDIR)/captcha.c \ $(SRCDIR)/cgi.c \ $(SRCDIR)/checkin.c \ $(SRCDIR)/checkout.c \ $(SRCDIR)/clearsign.c \ $(SRCDIR)/clone.c \ | > | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | $(SRCDIR)/attach.c \ $(SRCDIR)/bag.c \ $(SRCDIR)/bisect.c \ $(SRCDIR)/blob.c \ $(SRCDIR)/branch.c \ $(SRCDIR)/browse.c \ $(SRCDIR)/builtin.c \ $(SRCDIR)/bundle.c \ $(SRCDIR)/cache.c \ $(SRCDIR)/captcha.c \ $(SRCDIR)/cgi.c \ $(SRCDIR)/checkin.c \ $(SRCDIR)/checkout.c \ $(SRCDIR)/clearsign.c \ $(SRCDIR)/clone.c \ |
| ︙ | ︙ | |||
85 86 87 88 89 90 91 92 93 94 95 96 97 98 | $(SRCDIR)/moderate.c \ $(SRCDIR)/name.c \ $(SRCDIR)/path.c \ $(SRCDIR)/pivot.c \ $(SRCDIR)/popen.c \ $(SRCDIR)/pqueue.c \ $(SRCDIR)/printf.c \ $(SRCDIR)/rebuild.c \ $(SRCDIR)/regexp.c \ $(SRCDIR)/report.c \ $(SRCDIR)/rss.c \ $(SRCDIR)/schema.c \ $(SRCDIR)/search.c \ $(SRCDIR)/setup.c \ | > > | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | $(SRCDIR)/moderate.c \ $(SRCDIR)/name.c \ $(SRCDIR)/path.c \ $(SRCDIR)/pivot.c \ $(SRCDIR)/popen.c \ $(SRCDIR)/pqueue.c \ $(SRCDIR)/printf.c \ $(SRCDIR)/publish.c \ $(SRCDIR)/purge.c \ $(SRCDIR)/rebuild.c \ $(SRCDIR)/regexp.c \ $(SRCDIR)/report.c \ $(SRCDIR)/rss.c \ $(SRCDIR)/schema.c \ $(SRCDIR)/search.c \ $(SRCDIR)/setup.c \ |
| ︙ | ︙ | |||
137 138 139 140 141 142 143 144 145 146 147 148 149 150 | $(OBJDIR)/attach_.c \ $(OBJDIR)/bag_.c \ $(OBJDIR)/bisect_.c \ $(OBJDIR)/blob_.c \ $(OBJDIR)/branch_.c \ $(OBJDIR)/browse_.c \ $(OBJDIR)/builtin_.c \ $(OBJDIR)/cache_.c \ $(OBJDIR)/captcha_.c \ $(OBJDIR)/cgi_.c \ $(OBJDIR)/checkin_.c \ $(OBJDIR)/checkout_.c \ $(OBJDIR)/clearsign_.c \ $(OBJDIR)/clone_.c \ | > | 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | $(OBJDIR)/attach_.c \ $(OBJDIR)/bag_.c \ $(OBJDIR)/bisect_.c \ $(OBJDIR)/blob_.c \ $(OBJDIR)/branch_.c \ $(OBJDIR)/browse_.c \ $(OBJDIR)/builtin_.c \ $(OBJDIR)/bundle_.c \ $(OBJDIR)/cache_.c \ $(OBJDIR)/captcha_.c \ $(OBJDIR)/cgi_.c \ $(OBJDIR)/checkin_.c \ $(OBJDIR)/checkout_.c \ $(OBJDIR)/clearsign_.c \ $(OBJDIR)/clone_.c \ |
| ︙ | ︙ | |||
203 204 205 206 207 208 209 210 211 212 213 214 215 216 | $(OBJDIR)/moderate_.c \ $(OBJDIR)/name_.c \ $(OBJDIR)/path_.c \ $(OBJDIR)/pivot_.c \ $(OBJDIR)/popen_.c \ $(OBJDIR)/pqueue_.c \ $(OBJDIR)/printf_.c \ $(OBJDIR)/rebuild_.c \ $(OBJDIR)/regexp_.c \ $(OBJDIR)/report_.c \ $(OBJDIR)/rss_.c \ $(OBJDIR)/schema_.c \ $(OBJDIR)/search_.c \ $(OBJDIR)/setup_.c \ | > > | 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | $(OBJDIR)/moderate_.c \ $(OBJDIR)/name_.c \ $(OBJDIR)/path_.c \ $(OBJDIR)/pivot_.c \ $(OBJDIR)/popen_.c \ $(OBJDIR)/pqueue_.c \ $(OBJDIR)/printf_.c \ $(OBJDIR)/publish_.c \ $(OBJDIR)/purge_.c \ $(OBJDIR)/rebuild_.c \ $(OBJDIR)/regexp_.c \ $(OBJDIR)/report_.c \ $(OBJDIR)/rss_.c \ $(OBJDIR)/schema_.c \ $(OBJDIR)/search_.c \ $(OBJDIR)/setup_.c \ |
| ︙ | ︙ | |||
252 253 254 255 256 257 258 259 260 261 262 263 264 265 | $(OBJDIR)/attach.o \ $(OBJDIR)/bag.o \ $(OBJDIR)/bisect.o \ $(OBJDIR)/blob.o \ $(OBJDIR)/branch.o \ $(OBJDIR)/browse.o \ $(OBJDIR)/builtin.o \ $(OBJDIR)/cache.o \ $(OBJDIR)/captcha.o \ $(OBJDIR)/cgi.o \ $(OBJDIR)/checkin.o \ $(OBJDIR)/checkout.o \ $(OBJDIR)/clearsign.o \ $(OBJDIR)/clone.o \ | > | 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 | $(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 \ |
| ︙ | ︙ | |||
318 319 320 321 322 323 324 325 326 327 328 329 330 331 | $(OBJDIR)/moderate.o \ $(OBJDIR)/name.o \ $(OBJDIR)/path.o \ $(OBJDIR)/pivot.o \ $(OBJDIR)/popen.o \ $(OBJDIR)/pqueue.o \ $(OBJDIR)/printf.o \ $(OBJDIR)/rebuild.o \ $(OBJDIR)/regexp.o \ $(OBJDIR)/report.o \ $(OBJDIR)/rss.o \ $(OBJDIR)/schema.o \ $(OBJDIR)/search.o \ $(OBJDIR)/setup.o \ | > > | 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 | $(OBJDIR)/moderate.o \ $(OBJDIR)/name.o \ $(OBJDIR)/path.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 \ |
| ︙ | ︙ | |||
476 477 478 479 480 481 482 483 484 485 486 487 488 489 | $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h \ $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h \ $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h \ $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h \ $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h \ $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h \ $(OBJDIR)/builtin_.c:$(OBJDIR)/builtin.h \ $(OBJDIR)/cache_.c:$(OBJDIR)/cache.h \ $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h \ $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h \ $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h \ $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h \ $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h \ $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h \ | > | 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 | $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h \ $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h \ $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h \ $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h \ $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h \ $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h \ $(OBJDIR)/builtin_.c:$(OBJDIR)/builtin.h \ $(OBJDIR)/bundle_.c:$(OBJDIR)/bundle.h \ $(OBJDIR)/cache_.c:$(OBJDIR)/cache.h \ $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h \ $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h \ $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h \ $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h \ $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h \ $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h \ |
| ︙ | ︙ | |||
542 543 544 545 546 547 548 549 550 551 552 553 554 555 | $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \ $(OBJDIR)/name_.c:$(OBJDIR)/name.h \ $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ | > > | 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 | $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \ $(OBJDIR)/name_.c:$(OBJDIR)/name.h \ $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ $(OBJDIR)/publish_.c:$(OBJDIR)/publish.h \ $(OBJDIR)/purge_.c:$(OBJDIR)/purge.h \ $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| ︙ | ︙ | |||
658 659 660 661 662 663 664 665 666 667 668 669 670 671 | $(OBJDIR)/builtin_.c: $(SRCDIR)/builtin.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/builtin.c >$@ $(OBJDIR)/builtin.o: $(OBJDIR)/builtin_.c $(OBJDIR)/builtin.h $(OBJDIR)/builtin_data.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/builtin.o -c $(OBJDIR)/builtin_.c $(OBJDIR)/builtin.h: $(OBJDIR)/headers $(OBJDIR)/cache_.c: $(SRCDIR)/cache.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/cache.c >$@ $(OBJDIR)/cache.o: $(OBJDIR)/cache_.c $(OBJDIR)/cache.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/cache.o -c $(OBJDIR)/cache_.c | > > > > > > > > | 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 | $(OBJDIR)/builtin_.c: $(SRCDIR)/builtin.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/builtin.c >$@ $(OBJDIR)/builtin.o: $(OBJDIR)/builtin_.c $(OBJDIR)/builtin.h $(OBJDIR)/builtin_data.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/builtin.o -c $(OBJDIR)/builtin_.c $(OBJDIR)/builtin.h: $(OBJDIR)/headers $(OBJDIR)/bundle_.c: $(SRCDIR)/bundle.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/bundle.c >$@ $(OBJDIR)/bundle.o: $(OBJDIR)/bundle_.c $(OBJDIR)/bundle.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/bundle.o -c $(OBJDIR)/bundle_.c $(OBJDIR)/bundle.h: $(OBJDIR)/headers $(OBJDIR)/cache_.c: $(SRCDIR)/cache.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/cache.c >$@ $(OBJDIR)/cache.o: $(OBJDIR)/cache_.c $(OBJDIR)/cache.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/cache.o -c $(OBJDIR)/cache_.c |
| ︙ | ︙ | |||
1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 | $(OBJDIR)/printf_.c: $(SRCDIR)/printf.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/printf.c >$@ $(OBJDIR)/printf.o: $(OBJDIR)/printf_.c $(OBJDIR)/printf.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c $(OBJDIR)/printf.h: $(OBJDIR)/headers $(OBJDIR)/rebuild_.c: $(SRCDIR)/rebuild.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/rebuild.c >$@ $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c | > > > > > > > > > > > > > > > > | 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 | $(OBJDIR)/printf_.c: $(SRCDIR)/printf.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/printf.c >$@ $(OBJDIR)/printf.o: $(OBJDIR)/printf_.c $(OBJDIR)/printf.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c $(OBJDIR)/printf.h: $(OBJDIR)/headers $(OBJDIR)/publish_.c: $(SRCDIR)/publish.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/publish.c >$@ $(OBJDIR)/publish.o: $(OBJDIR)/publish_.c $(OBJDIR)/publish.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/publish.o -c $(OBJDIR)/publish_.c $(OBJDIR)/publish.h: $(OBJDIR)/headers $(OBJDIR)/purge_.c: $(SRCDIR)/purge.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/purge.c >$@ $(OBJDIR)/purge.o: $(OBJDIR)/purge_.c $(OBJDIR)/purge.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/purge.o -c $(OBJDIR)/purge_.c $(OBJDIR)/purge.h: $(OBJDIR)/headers $(OBJDIR)/rebuild_.c: $(SRCDIR)/rebuild.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/rebuild.c >$@ $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c |
| ︙ | ︙ |
Changes to src/makemake.tcl.
| ︙ | ︙ | |||
26 27 28 29 30 31 32 33 34 35 36 37 38 39 | attach bag bisect blob branch browse builtin cache captcha cgi checkin checkout clearsign clone | > | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone |
| ︙ | ︙ | |||
91 92 93 94 95 96 97 98 99 100 101 102 103 104 | moderate name path pivot popen pqueue printf rebuild regexp report rss schema search setup | > > | 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | moderate name path pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup |
| ︙ | ︙ |
Changes to src/mkversion.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/*
** This C program generates the "VERSION.h" header file from information
** extracted out of the "manifest", "manifest.uuid", and "VERSION" files.
** Call this program with three arguments:
**
** ./a.out manifest.uuid manifest VERSION
**
** Note that the manifest.uuid and manifest files are generated by Fossil.
*/
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]){
FILE *m,*u,*v;
char *z;
int i, x, d;
char b[1000];
char vx[1000];
memset(b,0,sizeof(b));
memset(vx,0,sizeof(vx));
u = fopen(argv[1],"r");
| > | > > > | > > > | 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 |
/*
** This C program generates the "VERSION.h" header file from information
** extracted out of the "manifest", "manifest.uuid", and "VERSION" files.
** Call this program with three arguments:
**
** ./a.out manifest.uuid manifest VERSION
**
** Note that the manifest.uuid and manifest files are generated by Fossil.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
FILE *m,*u,*v;
char *z;
int i, x, d;
char b[1000];
char vx[1000];
memset(b,0,sizeof(b));
memset(vx,0,sizeof(vx));
u = fopen(argv[1],"r");
if( fgets(b, sizeof(b)-1,u)==0 ){
fprintf(stderr, "malformed manifest.uuid file: %s\n", argv[1]);
exit(1);
}
fclose(u);
for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){}
*z = 0;
printf("#define MANIFEST_UUID \"%s\"\n",b);
printf("#define MANIFEST_VERSION \"[%10.10s]\"\n",b);
m = fopen(argv[2],"r");
while(b == fgets(b, sizeof(b)-1,m)){
if(0 == strncmp("D ",b,2)){
printf("#define MANIFEST_DATE \"%.10s %.8s\"\n",b+2,b+13);
printf("#define MANIFEST_YEAR \"%.4s\"\n",b+2);
}
}
fclose(m);
v = fopen(argv[3],"r");
if( fgets(b, sizeof(b)-1,v)==0 ){
fprintf(stderr, "malformed VERSION file: %s\n", argv[3]);
exit(1);
}
fclose(v);
for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){}
*z = 0;
printf("#define RELEASE_VERSION \"%s\"\n", b);
x=0;
i=0;
z=b;
|
| ︙ | ︙ |
Changes to src/moderate.c.
| ︙ | ︙ | |||
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 |
fossil_free(zTktid);
}
attachRid = db_int(0, "SELECT attachRid FROM modreq WHERE objid=%d", rid);
if( rid==objid ){
db_multi_exec("DELETE FROM modreq WHERE objid=%d", rid);
}
if( attachRid && object_used(attachRid) ) attachRid = 0;
rid = attachRid;
}
db_end_transaction(0);
}
/*
** Approve an object held for moderation.
*/
void moderation_approve(int rid){
if( !moderation_pending(rid) ) return;
db_begin_transaction();
db_multi_exec(
"DELETE FROM private WHERE rid=%d;"
"INSERT OR IGNORE INTO unclustered VALUES(%d);"
"INSERT OR IGNORE INTO unsent VALUES(%d);",
rid, rid, rid
);
db_multi_exec("DELETE FROM modreq WHERE objid=%d", rid);
db_end_transaction(0);
}
/*
** WEBPAGE: modreq
**
** Show all pending moderation request
| > > | 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 |
fossil_free(zTktid);
}
attachRid = db_int(0, "SELECT attachRid FROM modreq WHERE objid=%d", rid);
if( rid==objid ){
db_multi_exec("DELETE FROM modreq WHERE objid=%d", rid);
}
if( attachRid && object_used(attachRid) ) attachRid = 0;
admin_log("Disapproved moderation of rid %d.", rid);
rid = attachRid;
}
db_end_transaction(0);
}
/*
** Approve an object held for moderation.
*/
void moderation_approve(int rid){
if( !moderation_pending(rid) ) return;
db_begin_transaction();
db_multi_exec(
"DELETE FROM private WHERE rid=%d;"
"INSERT OR IGNORE INTO unclustered VALUES(%d);"
"INSERT OR IGNORE INTO unsent VALUES(%d);",
rid, rid, rid
);
db_multi_exec("DELETE FROM modreq WHERE objid=%d", rid);
admin_log("Approved moderation of rid %d.", rid);
db_end_transaction(0);
}
/*
** WEBPAGE: modreq
**
** Show all pending moderation request
|
| ︙ | ︙ |
Changes to src/name.c.
| ︙ | ︙ | |||
40 41 42 43 44 45 46 47 48 49 50 51 52 53 | if( !fossil_isdigit(z[5]) ) return 0; if( !fossil_isdigit(z[6]) ) return 0; if( z[7]!='-') return 0; if( !fossil_isdigit(z[8]) ) return 0; if( !fossil_isdigit(z[9]) ) return 0; return 1; } /* ** Convert a symbolic name into a RID. Acceptable forms: ** ** * SHA1 hash ** * SHA1 hash prefix of at least 4 characters ** * Symbolic Name | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
if( !fossil_isdigit(z[5]) ) return 0;
if( !fossil_isdigit(z[6]) ) return 0;
if( z[7]!='-') return 0;
if( !fossil_isdigit(z[8]) ) return 0;
if( !fossil_isdigit(z[9]) ) return 0;
return 1;
}
/*
** Return the RID that is the "root" of the branch that contains
** check-in "rid" if inBranch==0 or the first check-in in the branch
** if inBranch==1.
*/
int start_of_branch(int rid, int inBranch){
Stmt q;
int rc;
char *zBr;
zBr = db_text("trunk","SELECT value FROM tagxref"
" WHERE rid=%d AND tagid=%d"
" AND tagtype>0",
rid, TAG_BRANCH);
db_prepare(&q,
"SELECT pid, EXISTS(SELECT 1 FROM tagxref"
" WHERE tagid=%d AND tagtype>0"
" AND value=%Q AND rid=plink.pid)"
" FROM plink"
" WHERE cid=:cid AND isprim",
TAG_BRANCH, zBr
);
fossil_free(zBr);
do{
db_reset(&q);
db_bind_int(&q, ":cid", rid);
rc = db_step(&q);
if( rc!=SQLITE_ROW ) break;
if( inBranch && db_column_int(&q,1)==0 ) break;
rid = db_column_int(&q, 0);
}while( db_column_int(&q, 1)==1 && rid>0 );
db_finalize(&q);
return rid;
}
/*
** Convert a symbolic name into a RID. Acceptable forms:
**
** * SHA1 hash
** * SHA1 hash prefix of at least 4 characters
** * Symbolic Name
|
| ︙ | ︙ | |||
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
** * "next"
**
** Return the RID of the matching artifact. Or return 0 if the name does not
** match any known object. Or return -1 if the name is ambiguous.
**
** The zType parameter specifies the type of artifact: ci, t, w, e, g.
** If zType is NULL or "" or "*" then any type of artifact will serve.
** zType is "ci" in most use cases since we are usually searching for
** a check-in.
*/
int symbolic_name_to_rid(const char *zTag, const char *zType){
int vid;
int rid = 0;
int nTag;
int i;
| > > > | > > > > > | 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 |
** * "next"
**
** Return the RID of the matching artifact. Or return 0 if the name does not
** match any known object. Or return -1 if the name is ambiguous.
**
** The zType parameter specifies the type of artifact: ci, t, w, e, g.
** If zType is NULL or "" or "*" then any type of artifact will serve.
** If zType is "br" then find the first check-in of the named branch
** rather than the last.
** zType is "ci" in most use cases since we are usually searching for
** a check-in.
*/
int symbolic_name_to_rid(const char *zTag, const char *zType){
int vid;
int rid = 0;
int nTag;
int i;
int startOfBranch = 0;
if( zType==0 || zType[0]==0 ){
zType = "*";
}else if( zType[0]=='b' ){
zType = "ci";
startOfBranch = 1;
}
if( zTag==0 || zTag[0]==0 ) return 0;
/* special keyword: "tip" */
if( fossil_strcmp(zTag, "tip")==0 && (zType[0]=='*' || zType[0]=='c') ){
rid = db_int(0,
"SELECT objid"
" FROM event"
|
| ︙ | ︙ | |||
149 150 151 152 153 154 155 156 157 158 159 160 |
" FROM tag, tagxref, event"
" WHERE tag.tagname='sym-%q' "
" AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 "
" AND event.objid=tagxref.rid "
" AND event.type GLOB '%q'",
&zTag[4], zType
);
return rid;
}
/* root:TAG -> The origin of the branch */
if( memcmp(zTag, "root:", 5)==0 ){
| > < < < < < < < < < < < < < < < < < < < < < < < < | | 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
" FROM tag, tagxref, event"
" WHERE tag.tagname='sym-%q' "
" AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 "
" AND event.objid=tagxref.rid "
" AND event.type GLOB '%q'",
&zTag[4], zType
);
if( startOfBranch ) rid = start_of_branch(rid,1);
return rid;
}
/* root:TAG -> The origin of the branch */
if( memcmp(zTag, "root:", 5)==0 ){
rid = symbolic_name_to_rid(zTag+5, zType);
return start_of_branch(rid, 0);
}
/* symbolic-name ":" date-time */
nTag = strlen(zTag);
for(i=0; i<nTag-10 && zTag[i]!=':'; i++){}
if( zTag[i]==':' && fossil_isdate(&zTag[i+1]) ){
char *zDate = mprintf("%s", &zTag[i+1]);
|
| ︙ | ︙ | |||
243 244 245 246 247 248 249 |
" FROM tag, tagxref, event"
" WHERE tag.tagname='sym-%q' "
" AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 "
" AND event.objid=tagxref.rid "
" AND event.type GLOB '%q'",
zTag, zType
);
| | > > > | 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
" FROM tag, tagxref, event"
" WHERE tag.tagname='sym-%q' "
" AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 "
" AND event.objid=tagxref.rid "
" AND event.type GLOB '%q'",
zTag, zType
);
if( rid>0 ){
if( startOfBranch ) rid = start_of_branch(rid,1);
return rid;
}
/* Undocumented: numeric tags get translated directly into the RID */
if( memcmp(zTag, "rid:", 4)==0 ){
zTag += 4;
for(i=0; fossil_isdigit(zTag[i]); i++){}
if( zTag[i]==0 ){
if( strcmp(zType,"*")==0 ){
|
| ︙ | ︙ | |||
389 390 391 392 393 394 395 |
*/
int name_to_typed_rid(const char *zName, const char *zType){
int rid;
if( zName==0 || zName[0]==0 ) return 0;
rid = symbolic_name_to_rid(zName, zType);
if( rid<0 ){
| | < | < < < > | 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 |
*/
int name_to_typed_rid(const char *zName, const char *zType){
int rid;
if( zName==0 || zName[0]==0 ) return 0;
rid = symbolic_name_to_rid(zName, zType);
if( rid<0 ){
fossil_fatal("ambiguous name: %s", zName);
}else if( rid==0 ){
fossil_fatal("not found: %s", zName);
}
return rid;
}
int name_to_rid(const char *zName){
return name_to_typed_rid(zName, "*");
}
/*
** WEBPAGE: ambiguous
|
| ︙ | ︙ | |||
503 504 505 506 507 508 509 | } return rid; } /* ** Generate a description of artifact "rid" */ | | | 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 |
}
return rid;
}
/*
** Generate a description of artifact "rid"
*/
void whatis_rid(int rid, int verboseFlag){
Stmt q;
int cnt;
/* Basic information about the object. */
db_prepare(&q,
"SELECT uuid, size, datetime(mtime%s), ipaddr"
" FROM blob, rcvfrom"
|
| ︙ | ︙ | |||
655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 |
** plays.
*/
void whatis_cmd(void){
int rid;
const char *zName;
int verboseFlag;
int i;
db_find_and_open_repository(0,0);
verboseFlag = find_option("verbose","v",0)!=0;
/* We should be done with options.. */
verify_all_options();
if( g.argc<3 ) usage("whatis NAME ...");
for(i=2; i<g.argc; i++){
zName = g.argv[i];
if( i>2 ) fossil_print("%.79c\n",'-');
| > > | | 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 |
** plays.
*/
void whatis_cmd(void){
int rid;
const char *zName;
int verboseFlag;
int i;
const char *zType = 0;
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("whatis 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;
fossil_print("name: %s (ambiguous)\n", zName);
db_prepare(&q,
"SELECT rid FROM blob WHERE uuid>=lower(%Q) AND uuid<(lower(%Q)||'z')",
zName, zName
|
| ︙ | ︙ | |||
755 756 757 758 759 760 761 |
db_finalize(&q);
db_prepare(&q, "SELECT uuid FROM dups ORDER BY length(uuid) DESC, uuid");
while( db_step(&q)==SQLITE_ROW ){
fossil_print("%s\n", db_column_text(&q, 0));
}
db_finalize(&q);
}
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 |
db_finalize(&q);
db_prepare(&q, "SELECT uuid FROM dups ORDER BY length(uuid) DESC, uuid");
while( db_step(&q)==SQLITE_ROW ){
fossil_print("%s\n", db_column_text(&q, 0));
}
db_finalize(&q);
}
/*
** Schema for the description table
*/
static const char zDescTab[] =
@ CREATE TEMP TABLE IF NOT EXISTS description(
@ rid INTEGER PRIMARY KEY, -- RID of the object
@ uuid TEXT, -- SHA1 hash of the object
@ ctime DATETIME, -- Time of creation
@ isPrivate BOOLEAN DEFAULT 0, -- True for unpublished artifacts
@ type TEXT, -- file, checkin, wiki, ticket, etc.
@ summary TEXT, -- Summary comment for the object
@ detail TEXT -- filename, checkin comment, etc
@ );
;
/*
** Create the description table if it does not already exists.
** Populate fields of this table with descriptions for all artifacts
** whose RID matches the SQL expression in zWhere.
*/
void describe_artifacts(const char *zWhere){
db_multi_exec("%s", zDescTab/*safe-for-%s*/);
/* Describe checkins */
db_multi_exec(
"INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
"SELECT blob.rid, blob.uuid, event.mtime, 'checkin',\n"
" 'checkin on ' || strftime('%%Y-%%m-%%d %%H:%%M',event.mtime)\n"
" FROM event, blob\n"
" WHERE event.objid %s AND event.type='ci'\n"
" AND event.objid=blob.rid;",
zWhere /*safe-for-%s*/
);
/* Describe files */
db_multi_exec(
"INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
"SELECT blob.rid, blob.uuid, event.mtime, 'file', 'file '||filename.name\n"
" FROM mlink, blob, event, filename\n"
" WHERE mlink.fid %s\n"
" AND mlink.mid=event.objid\n"
" AND filename.fnid=mlink.fnid\n"
" AND mlink.fid=blob.rid;",
zWhere /*safe-for-%s*/
);
/* Describe tags */
db_multi_exec(
"INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
"SELECT blob.rid, blob.uuid, tagxref.mtime, 'tag',\n"
" 'tag '||substr((SELECT uuid FROM blob WHERE rid=tagxref.rid),1,16)\n"
" FROM tagxref, blob\n"
" WHERE tagxref.srcid %s AND tagxref.srcid!=tagxref.rid\n"
" AND tagxref.srcid=blob.rid;",
zWhere /*safe-for-%s*/
);
/* Cluster artifacts */
db_multi_exec(
"INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
"SELECT blob.rid, blob.uuid, tagxref.mtime, 'cluster', 'cluster'\n"
" FROM tagxref, blob\n"
" WHERE tagxref.rid %s\n"
" AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='cluster')\n"
" AND blob.rid=tagxref.rid;",
zWhere /*safe-for-%s*/
);
/* Ticket change artifacts */
db_multi_exec(
"INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
"SELECT blob.rid, blob.uuid, tagxref.mtime, 'ticket',\n"
" 'ticket '||substr(tag.tagname,5,21)\n"
" FROM tagxref, tag, blob\n"
" WHERE tagxref.rid %s\n"
" AND tag.tagid=tagxref.tagid\n"
" AND tag.tagname GLOB 'tkt-*'"
" AND blob.rid=tagxref.rid;",
zWhere /*safe-for-%s*/
);
/* Wiki edit artifacts */
db_multi_exec(
"INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
"SELECT blob.rid, blob.uuid, tagxref.mtime, 'wiki',\n"
" printf('wiki \"%%s\"',substr(tag.tagname,6))\n"
" FROM tagxref, tag, blob\n"
" WHERE tagxref.rid %s\n"
" AND tag.tagid=tagxref.tagid\n"
" AND tag.tagname GLOB 'wiki-*'"
" AND blob.rid=tagxref.rid;",
zWhere /*safe-for-%s*/
);
/* Event edit artifacts */
db_multi_exec(
"INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n"
"SELECT blob.rid, blob.uuid, tagxref.mtime, 'event',\n"
" 'event '||substr(tag.tagname,7)\n"
" FROM tagxref, tag, blob\n"
" WHERE tagxref.rid %s\n"
" AND tag.tagid=tagxref.tagid\n"
" AND tag.tagname GLOB 'event-*'"
" AND blob.rid=tagxref.rid;",
zWhere /*safe-for-%s*/
);
/* Attachments */
db_multi_exec(
"INSERT OR IGNORE INTO description(rid,uuid,ctime,type,detail)\n"
"SELECT blob.rid, blob.uuid, attachment.mtime, 'attachment',\n"
" 'attachment '||attachment.filename\n"
" FROM attachment, blob\n"
" WHERE attachment.src %s\n"
" AND blob.rid=attachment.src;",
zWhere /*safe-for-%s*/
);
/* Everything else */
db_multi_exec(
"INSERT OR IGNORE INTO description(rid,uuid,type,summary)\n"
"SELECT blob.rid, blob.uuid,"
" CASE WHEN blob.size<0 THEN 'phantom' ELSE '' END,\n"
" 'unknown'\n"
" FROM blob WHERE blob.rid %s;",
zWhere /*safe-for-%s*/
);
/* Mark private elements */
db_multi_exec(
"UPDATE description SET isPrivate=1 WHERE rid IN private"
);
}
/*
** Print the content of the description table on stdout
*/
int describe_artifacts_to_stdout(const char *zWhere, const char *zLabel){
Stmt q;
int cnt = 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);
db_multi_exec("DELETE FROM description;");
return cnt;
}
/*
** COMMAND: test-describe-artifacts
**
** Usage: %fossil test-describe-artifacts
**
** Display a one-line description of every artifact.
*/
void test_describe_artifacts_cmd(void){
db_find_and_open_repository(0,0);
describe_artifacts_to_stdout("IN (SELECT rid FROM blob)", 0);
}
/*
** COMMAND: test-unsent
**
** Usage: %fossil test-unsent
**
** Show all artifacts in the unsent table
*/
void test_unsent_cmd(void){
db_find_and_open_repository(0,0);
describe_artifacts_to_stdout("IN unsent", 0);
}
/*
** COMMAND: test-unclustered
**
** Usage: %fossil test-unclustered
**
** Show all artifacts in the unclustered table
*/
void test_unclusterd_cmd(void){
db_find_and_open_repository(0,0);
describe_artifacts_to_stdout("IN unclustered", 0);
}
/*
** COMMAND: test-phantoms
**
** Usage: %fossil test-phantoms
**
** Show all phantom artifacts
*/
void test_phatoms_cmd(void){
db_find_and_open_repository(0,0);
describe_artifacts_to_stdout("IN (SELECT rid FROM blob WHERE size<0)", 0);
}
|
Added src/publish.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) 2014 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 file contains code used to implement the "publish" and
** "unpublished" commands.
*/
#include "config.h"
#include "publish.h"
#include <assert.h>
/*
** COMMAND: unpublished
**
** Usage: %fossil unpublished ?OPTIONS?
**
** Show a list of unpublished or "private" artifacts. Unpublished artifacts
** will never push and hence will not be shared with collaborators.
**
** By default, this command only shows unpublished checkins. To show
** all unpublished artifacts, use the --all command-line option.
**
** OPTIONS:
** --all Show all artifacts, not just checkins
*/
void unpublished_cmd(void){
int bAll = find_option("all",0,0)!=0;
db_find_and_open_repository(0,0);
verify_all_options();
if( bAll ){
describe_artifacts_to_stdout("IN private", 0);
}else{
describe_artifacts_to_stdout(
"IN (SELECT rid FROM private CROSS JOIN event"
" WHERE private.rid=event.objid"
" AND event.type='ci')", 0);
}
}
/*
** COMMAND: publish
**
** Usage: %fossil publish ?--only? TAGS...
**
** Cause artifacts identified by TAGS... to be published (made non-private).
** This can be used (for example) to convert a private branch into a public
** branch, or to publish a bundle that was imported privately.
**
** If any of TAGS names a branch, then all checkins on that most recent
** instance of that branch are included, not just the most recent checkin.
**
** If any of TAGS name checkins then all files and tags associated with
** those checkins are also published automatically. Except if the --only
** option is used, then only the specific artifacts identified by TAGS
** are published.
**
** If a TAG is already public, this command is a harmless no-op.
*/
void publish_cmd(void){
int bOnly = find_option("only",0,0)!=0;
int bTest = find_option("test",0,0)!=0; /* Undocumented --test option */
int bExclusive = find_option("exclusive",0,0)!=0; /* undocumented */
int i;
db_find_and_open_repository(0,0);
verify_all_options();
if( g.argc<3 ) usage("?--only? TAGS...");
db_begin_transaction();
db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY);");
for(i=2; i<g.argc; i++){
int rid = name_to_rid(g.argv[i]);
if( db_exists("SELECT 1 FROM tagxref"
" WHERE rid=%d AND tagid=%d"
" AND tagtype>0 AND value=%Q",
rid,TAG_BRANCH,g.argv[i]) ){
rid = start_of_branch(rid, 1);
compute_descendants(rid, 1000000000);
}else{
db_multi_exec("INSERT OR IGNORE INTO ok VALUES(%d)", rid);
}
}
if( !bOnly ){
find_checkin_associates("ok", bExclusive);
}
if( bTest ){
/* If the --test option is used, then do not actually publish any
** artifacts. Instead, just list the artifact information on standard
** output. The --test option is useful for verifying correct operation
** of the logic that figures out which artifacts to publish, such as
** the find_checkin_associates() routine
*/
describe_artifacts_to_stdout("IN ok", 0);
}else{
/* Standard behavior is simply to remove the published documents from
** the PRIVATE table */
db_multi_exec(
"DELETE FROM ok WHERE rid NOT IN private;"
"DELETE FROM private WHERE rid IN ok;"
"INSERT OR IGNORE INTO unsent SELECT rid FROM ok;"
"INSERT OR IGNORE INTO unclustered SELECT rid FROM ok;"
);
}
db_end_transaction(0);
}
|
Added src/purge.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 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 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 |
/*
** Copyright (c) 2014 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 file contains code used to implement the "purge" command and
** related functionality for removing checkins from a repository. It also
** manages the graveyard of purged content.
*/
#include "config.h"
#include "purge.h"
#include <assert.h>
/*
** SQL code used to initialize the schema of a bundle.
**
** 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
** mistaken purge or for content recovery in case there is a bug in the
** purge command.
*/
static const char zPurgeInit[] =
@ CREATE TABLE IF NOT EXISTS "%w".purgeevent(
@ peid INTEGER PRIMARY KEY, -- Unique ID for the purge event
@ ctime DATETIME, -- When purge occurred. Seconds since 1970.
@ pnotes TEXT -- Human-readable notes about the purge event
@ );
@ CREATE TABLE IF NOT EXISTS "%w".purgeitem(
@ piid INTEGER PRIMARY KEY, -- ID for the purge item
@ peid INTEGER REFERENCES purgeevent ON DELETE CASCADE, -- Purge event
@ orid INTEGER, -- Original RID before purged
@ uuid TEXT NOT NULL, -- SHA1 hash of the purged artifact
@ srcid INTEGER, -- Basis purgeitem for delta compression
@ 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.
**
** This routine does the following:
**
** (1) Create the purgeevent and purgeitem tables, if required
** (2) Create a new purgeevent
** (3) Make sure no DELTA table entries depend on purged artifacts
** (4) Create new purgeitem entries for each purged artifact
** (5) Remove purged artifacts from the BLOB table
** (6) Remove references to purged artifacts in the following tables:
** (a) EVENT
** (b) PRIVATE
** (c) MLINK
** (d) PLINK
** (e) LEAF
** (f) UNCLUSTERED
** (g) UNSENT
** (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.
**
** Stops 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 */
int moveToGraveyard /* Move purged artifacts into the graveyard */
){
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);
/* 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");
}
/* Make sure that no delta that is left behind requires a purged artifact
** as its basis. If such artifacts exist, go ahead and undelta them now.
*/
db_prepare(&q, "SELECT rid FROM delta WHERE srcid IN \"%w\""
" AND rid NOT IN \"%w\"", zTab, zTab);
while( db_step(&q)==SQLITE_ROW ){
int rid = db_column_int(&q, 0);
content_undelta(rid);
verify_before_commit(rid);
}
db_finalize(&q);
/* Construct the graveyard and copy the artifacts to be purged into the
** graveyard */
if( moveToGraveyard ){
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\""
" AND srcid NOT IN \"%w\"", zTab, zTab);
while( db_step(&q)==SQLITE_ROW ){
int rid = db_column_int(&q, 0);
content_undelta(rid);
}
db_finalize(&q);
db_multi_exec(
"INSERT INTO purgeitem(peid,orid,uuid,sz,isPrivate,desc,data)"
" SELECT %d, rid, uuid, size,"
" EXISTS(SELECT 1 FROM private WHERE private.rid=blob.rid),"
" (SELECT summary FROM description WHERE rid=blob.rid),"
" content"
" FROM blob WHERE rid IN \"%w\"",
peid, zTab
);
db_multi_exec(
"UPDATE purgeitem"
" SET srcid=(SELECT piid FROM purgeitem px, delta"
" WHERE px.orid=delta.srcid"
" AND delta.rid=purgeitem.orid)"
" WHERE peid=%d",
peid
);
}
/* Remove the artifacts being purged. Also remove all references to those
** artifacts from the secondary tables. */
db_multi_exec("DELETE FROM blob WHERE rid IN \"%w\"", zTab);
db_multi_exec("DELETE FROM delta WHERE rid IN \"%w\"", zTab);
db_multi_exec("DELETE FROM delta WHERE srcid IN \"%w\"", zTab);
db_multi_exec("DELETE FROM event WHERE objid IN \"%w\"", zTab);
db_multi_exec("DELETE FROM private WHERE rid IN \"%w\"", zTab);
db_multi_exec("DELETE FROM mlink WHERE mid IN \"%w\"", zTab);
db_multi_exec("DELETE FROM plink WHERE pid IN \"%w\"", zTab);
db_multi_exec("DELETE FROM plink WHERE cid IN \"%w\"", zTab);
db_multi_exec("DELETE FROM leaf WHERE rid IN \"%w\"", zTab);
db_multi_exec("DELETE FROM phantom WHERE rid IN \"%w\"", zTab);
db_multi_exec("DELETE FROM unclustered WHERE rid IN \"%w\"", zTab);
db_multi_exec("DELETE FROM unsent WHERE rid IN \"%w\"", zTab);
db_multi_exec("DELETE FROM tagxref"
" WHERE rid IN \"%w\""
" OR srcid IN \"%w\""
" OR origid IN \"%w\"", zTab, zTab, zTab);
db_multi_exec("DELETE FROM backlink WHERE srctype=0 AND srcid IN \"%w\"",
zTab);
db_multi_exec(
"CREATE TEMP TABLE \"%w_tickets\" AS"
" SELECT DISTINCT tkt_uuid FROM ticket WHERE tkt_id IN"
" (SELECT tkt_id FROM ticketchng WHERE tkt_rid IN \"%w\")",
zTab, zTab);
db_multi_exec("DELETE FROM ticketchng WHERE tkt_rid IN \"%w\"", zTab);
db_prepare(&q, "SELECT tkt_uuid FROM \"%w_tickets\"", zTab);
while( db_step(&q)==SQLITE_ROW ){
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 checkins.
**
** Check to see if any checkin in zTab is a baseline manifest for some
** delta manifest that is not in zTab. Return true if zTab contains a
** baseline for a delta that is not in zTab.
**
** This is a database integrity preservation check. The checkins in zTab
** are about to be deleted or otherwise made inaccessible. This routine
** is checking to ensure that purging the checkins in zTab will not delete
** a baseline manifest out from under a delta.
*/
int purge_baseline_out_from_under_delta(const char *zTab){
if( !db_exists("SELECT 1 FROM %s.sqlite_master WHERE name='plink'"
" AND sql GLOB '* baseid *'", db_name("repository")) ){
/* Skip this check if the current database is an older schema that
** does not contain the PLINK.BASEID field. */
return 0;
}else{
return db_int(0,
"SELECT 1 FROM plink WHERE baseid IN \"%w\" AND cid NOT IN \"%w\"",
zTab, zTab);
}
}
/*
** The TEMP table named zTab contains the RIDs for a set of checkin
** artifacts. Expand this set (by adding new entries to zTab) to include
** all other artifacts that are used the set of checkins in
** the original list.
**
** If the bExclusive flag is true, then the set is only expanded by
** artifacts that are used exclusively by the checkins in the set.
** When bExclusive is false, then all artifacts used by the checkins
** are added even if those artifacts are also used by other checkins
** not in the set.
**
** The "fossil publish" command with the (undocumented) --test and
** --exclusive options can be used for interactiving testing of this
** function.
*/
void find_checkin_associates(const char *zTab, int bExclusive){
db_begin_transaction();
/* Compute the set of files that need to be added to zTab */
db_multi_exec("CREATE TEMP TABLE \"%w_files\"(fid INTEGER PRIMARY KEY)",zTab);
db_multi_exec(
"INSERT OR IGNORE INTO \"%w_files\"(fid)"
" SELECT fid FROM mlink WHERE fid!=0 AND mid IN \"%w\"",
zTab, zTab
);
if( bExclusive ){
/* But take out all files that are referenced by check-ins not in zTab */
db_multi_exec(
"DELETE FROM \"%w_files\""
" WHERE fid IN (SELECT fid FROM mlink"
" WHERE fid IN \"%w_files\""
" AND mid NOT IN \"%w\")",
zTab, zTab, zTab
);
}
/* Compute the set of tags that need to be added to zTag */
db_multi_exec("CREATE TEMP TABLE \"%w_tags\"(tid INTEGER PRIMARY KEY)",zTab);
db_multi_exec(
"INSERT OR IGNORE INTO \"%w_tags\"(tid)"
" SELECT DISTINCT srcid FROM tagxref WHERE rid in \"%w\" AND srcid!=0",
zTab, zTab
);
if( bExclusive ){
/* But take out tags that references some check-ins in zTab and other
** check-ins not in zTab. The current Fossil implementation never creates
** such tags, so the following should usually be a no-op. But the file
** format specification allows such tags, so we should check for them.
*/
db_multi_exec(
"DELETE FROM \"%w_tags\""
" WHERE tid IN (SELECT srcid FROM tagxref"
" WHERE srcid IN \"%w_tags\""
" AND rid NOT IN \"%w\")",
zTab, zTab, zTab
);
}
/* Transfer the extra artifacts into zTab */
db_multi_exec(
"INSERT OR IGNORE INTO \"%w\" SELECT fid FROM \"%w_files\";"
"INSERT OR IGNORE INTO \"%w\" SELECT tid FROM \"%w_tags\";"
"DROP TABLE \"%w_files\";"
"DROP TABLE \"%w_tags\";",
zTab, zTab, zTab, zTab, zTab, zTab
);
db_end_transaction(0);
}
/*
** Display the content of a single purge event.
*/
static void purge_list_event_content(int peid){
Stmt q;
sqlite3_int64 sz = 0;
db_prepare(&q, "SELECT piid, substr(uuid,1,16), srcid, isPrivate,"
" length(data), desc"
" FROM purgeitem WHERE peid=%d", peid);
while( db_step(&q)==SQLITE_ROW ){
fossil_print(" %5d %s %4s %c %10d %s\n",
db_column_int(&q,0),
db_column_text(&q,1),
db_column_text(&q,2),
db_column_int(&q,3) ? 'P' : ' ',
db_column_int(&q,4),
db_column_text(&q,5));
sz += db_column_int(&q,4);
}
db_finalize(&q);
fossil_print("%.11c%16s%.8c%10lld\n", ' ', "Total:", ' ', sz);
}
/*
** Extract the content for purgeitem number piid into a Blob. Return
** the number of errors.
*/
static int purge_extract_item(
int piid, /* ID of the item to extract */
Blob *pOut /* Write the content into this blob */
){
Stmt q;
int srcid;
Blob h1, h2, x;
static Bag busy;
db_prepare(&q, "SELECT uuid, srcid, data FROM purgeitem"
" WHERE piid=%d", piid);
if( db_step(&q)!=SQLITE_ROW ){
db_finalize(&q);
fossil_fatal("missing purge-item %d", piid);
}
if( bag_find(&busy, piid) ) return 1;
srcid = db_column_int(&q, 1);
blob_zero(pOut);
blob_zero(&x);
db_column_blob(&q, 2, &x);
blob_uncompress(&x, pOut);
blob_reset(&x);
if( srcid>0 ){
Blob baseline, out;
bag_insert(&busy, piid);
purge_extract_item(srcid, &baseline);
blob_zero(&out);
blob_delta_apply(&baseline, pOut, &out);
blob_reset(pOut);
*pOut = out;
blob_reset(&baseline);
}
bag_remove(&busy, piid);
blob_zero(&h1);
db_column_blob(&q, 0, &h1);
sha1sum_blob(pOut, &h2);
if( blob_compare(&h1, &h2)!=0 ){
fossil_fatal("SHA1 hash mismatch - wanted %s, got %s",
blob_str(&h1), blob_str(&h2));
}
blob_reset(&h1);
blob_reset(&h2);
db_finalize(&q);
return 0;
}
/*
** There is a TEMP table ix(piid,srcid) containing a set of purgeitems
** that need to be transferred to the BLOB table. This routine does
** all items that have srcid=iSrc. The pBasis blob holds the content
** of the source document if iSrc>0.
*/
static void purge_item_resurrect(int iSrc, Blob *pBasis){
Stmt q;
static Bag busy;
assert( pBasis!=0 || iSrc==0 );
if( iSrc>0 ){
if( bag_find(&busy, iSrc) ){
fossil_fatal("delta loop while uncompressing purged artifacts");
}
bag_insert(&busy, iSrc);
}
db_prepare(&q,
"SELECT uuid, data, isPrivate, ix.piid"
" FROM ix, purgeitem"
" WHERE ix.srcid=%d"
" AND ix.piid=purgeitem.piid;",
iSrc
);
while( db_step(&q)==SQLITE_ROW ){
Blob h1, h2, c1, c2;
int isPriv, rid;
blob_zero(&h1);
db_column_blob(&q, 0, &h1);
blob_zero(&c1);
db_column_blob(&q, 1, &c1);
blob_uncompress(&c1, &c1);
blob_zero(&c2);
if( pBasis ){
blob_delta_apply(pBasis, &c1, &c2);
blob_reset(&c1);
}else{
c2 = c1;
}
sha1sum_blob(&c2, &h2);
if( blob_compare(&h1, &h2)!=0 ){
fossil_fatal("SHA1 hash mismatch - wanted %s, got %s",
blob_str(&h1), blob_str(&h2));
}
blob_reset(&h2);
isPriv = db_column_int(&q, 2);
rid = content_put_ex(&c2, blob_str(&h1), 0, 0, isPriv);
if( rid==0 ){
fossil_fatal("%s", g.zErrMsg);
}else{
if( !isPriv ) content_make_public(rid);
content_get(rid, &c1);
manifest_crosslink(rid, &c1, MC_NO_ERRORS);
}
purge_item_resurrect(db_column_int(&q,3), &c2);
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.
**
** 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 checkins identified by TAGS and all of their descendants
** out of the repository and into the graveyard. The "checkins"
** subcommand keyword is option and can be omitted as long as TAGS
** does not conflict with any other subcommand.
**
** If a TAGS includes a branch name then it means all the checkins
** on the most recent occurrance of that branch.
**
** --explain Make no changes, but show what would happen.
** --dry-run Make no chances.
**
** fossil purge list|ls ?-l?
**
** Show the graveyard of prior purges. The -l option gives more
** detail in the output.
**
** fossil purge obliterate ID...
**
** Remove one or more purge events from the graveyard. Once a purge
** event is obliterated, it can no longer be undone.
**
** fossil purge undo ID
**
** Restore the content previously removed by purge ID.
**
** SUMMARY:
** fossil purge cat UUID...
** fossil purge [checkins] TAGS... [--explain]
** fossil purge list
** fossil purge obliterate ID...
** fossil purge undo ID
*/
void purge_cmd(void){
const char *zSubcmd;
int n;
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( 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);
}
/* The "checkins" subcommand goes here in alphabetical order, but it must
** be moved to the end since it is the default case */
}else if( strncmp(zSubcmd, "list", n)==0 || strcmp(zSubcmd,"ls")==0 ){
int showDetail = find_option("l","l",0)!=0;
if( db_int(-1,"PRAGMA table_info('purgeevent')")<0 ) return;
db_prepare(&q, "SELECT peid, datetime(ctime,'unixepoch','localtime')"
" 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;
if( g.argc<4 ) usage("obliterate ID...");
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, "undo", n)==0 ){
int peid;
if( g.argc!=4 ) usage("undo ID");
peid = atoi(g.argv[3]);
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{
/* The "checkins" command is the default and so must occur last */
int explainOnly = find_option("explain",0,0)!=0;
int dryRun = find_option("dry-run",0,0)!=0;
int i;
int vid;
int nCkin;
int nArtifact;
verify_all_options();
db_begin_transaction();
i = strncmp(zSubcmd,"checkins",n)==0 ? 3 : 2;
if( i>=g.argc ) usage("[checkin] TAGS... [--explain]");
db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
for(; 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");
}
nCkin = db_int(0, "SELECT count(*) FROM ok");
find_checkin_associates("ok", 1);
nArtifact = db_int(0, "SELECT count(*) FROM ok");
if( explainOnly ){
describe_artifacts_to_stdout("IN ok", 0);
}else{
int peid = purge_artifact_list("ok","",1);
fossil_print("%d checkins and %d artifacts purged.\n", nCkin, nArtifact);
fossil_print("undoable using \"%s purge undo %d\".\n",
g.nameOfExe, peid);
}
db_end_transaction(explainOnly||dryRun);
}
}
|
Changes to src/rebuild.c.
| ︙ | ︙ | |||
344 345 346 347 348 349 350 |
percent_complete(0);
}
rebuild_update_schema();
for(;;){
zTable = db_text(0,
"SELECT name FROM sqlite_master /*scan*/"
" WHERE type='table'"
| | | > | 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 |
percent_complete(0);
}
rebuild_update_schema();
for(;;){
zTable = db_text(0,
"SELECT name FROM sqlite_master /*scan*/"
" WHERE type='table'"
" AND name NOT IN ('admin_log', 'blob','delta','rcvfrom','user',"
"'config','shun','private','reportfmt',"
"'concealed','accesslog','modreq',"
"'purgeevent','purgeitem')"
" AND name NOT GLOB 'sqlite_*'"
" AND name NOT GLOB 'fx_*'"
);
if( zTable==0 ) break;
db_multi_exec("DROP TABLE %Q", zTable);
free(zTable);
}
|
| ︙ | ︙ | |||
827 828 829 830 831 832 833 |
"DELETE FROM config WHERE name GLOB 'peer-*';"
"DELETE FROM config WHERE name GLOB 'login-group-*';"
"DELETE FROM config WHERE name GLOB 'skin:*';"
"DELETE FROM config WHERE name GLOB 'subrepo:*';"
);
if( bVerily ){
db_multi_exec(
| | | | | > > > > | 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 |
"DELETE FROM config WHERE name GLOB 'peer-*';"
"DELETE FROM config WHERE name GLOB 'login-group-*';"
"DELETE FROM config WHERE name GLOB 'skin:*';"
"DELETE FROM config WHERE name GLOB 'subrepo:*';"
);
if( bVerily ){
db_multi_exec(
"DELETE FROM concealed;\n"
"UPDATE rcvfrom SET ipaddr='unknown';\n"
"DROP TABLE IF EXISTS accesslog;\n"
"UPDATE user SET photo=NULL, info='';\n"
"DROP TABLE IF EXISTS purgeevent;\n"
"DROP TABLE IF EXISTS purgeitem;\n"
"DROP TABLE IF EXISTS admin_log;\n"
"DROP TABLE IF EXISTS vcache;\n"
);
}
}
if( !bNeedRebuild ){
db_end_transaction(0);
db_multi_exec("VACUUM;");
}else{
|
| ︙ | ︙ |
Changes to src/schema.c.
| ︙ | ︙ | |||
79 80 81 82 83 84 85 | @ rcvid INTEGER, -- Origin of this record @ size INTEGER, -- Size of content. -1 for a phantom. @ uuid TEXT UNIQUE NOT NULL, -- SHA1 hash of the content @ content BLOB, -- Compressed content of this record @ CHECK( length(uuid)==40 AND rid>0 ) @ ); @ CREATE TABLE delta( | | | | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | @ rcvid INTEGER, -- Origin of this record @ size INTEGER, -- Size of content. -1 for a phantom. @ uuid TEXT UNIQUE NOT NULL, -- SHA1 hash of the content @ content BLOB, -- Compressed content of this record @ CHECK( length(uuid)==40 AND rid>0 ) @ ); @ CREATE TABLE delta( @ rid INTEGER PRIMARY KEY, -- BLOB that is delta-compressed @ srcid INTEGER NOT NULL REFERENCES blob -- Baseline for delta-compression @ ); @ CREATE INDEX delta_i1 ON delta(srcid); @ @ ------------------------------------------------------------------------- @ -- The BLOB and DELTA tables above hold the "global state" of a Fossil @ -- project; the stuff that is normally exchanged during "sync". The @ -- "local state" of a repository is contained in the remaining tables of |
| ︙ | ︙ |
Changes to src/setup.c.
| ︙ | ︙ | |||
103 104 105 106 107 108 109 |
" changes and attachments.");
setup_menu_entry("Ad-Unit", "setup_adunit",
"Edit HTML text for an ad unit inserted after the menu bar");
setup_menu_entry("Logo", "setup_logo",
"Change the logo and background images for the server");
setup_menu_entry("Shunned", "shun",
"Show artifacts that are shunned by this repository");
| | | > > | 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
" changes and attachments.");
setup_menu_entry("Ad-Unit", "setup_adunit",
"Edit HTML text for an ad unit inserted after the menu bar");
setup_menu_entry("Logo", "setup_logo",
"Change the logo and background images for the server");
setup_menu_entry("Shunned", "shun",
"Show artifacts that are shunned by this repository");
setup_menu_entry("Artifact Receipts Log", "rcvfromlist",
"A record of received artifacts and their sources");
setup_menu_entry("User Log", "access_log",
"A record of login attempts");
setup_menu_entry("Administrative Log", "admin_log",
"View the admin_log entries");
setup_menu_entry("Stats", "stat",
"Display repository statistics");
setup_menu_entry("SQL", "admin_sql",
"Enter raw SQL commands");
setup_menu_entry("TH1", "admin_th1",
"Enter raw TH1 commands");
@ </table>
|
| ︙ | ︙ | |||
378 379 380 381 382 383 384 |
style_footer();
return;
}
login_verify_csrf_secret();
db_multi_exec(
"REPLACE INTO user(uid,login,info,pw,cap,mtime) "
"VALUES(nullif(%d,0),%Q,%Q,%Q,%Q,now())",
| | > > | 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 |
style_footer();
return;
}
login_verify_csrf_secret();
db_multi_exec(
"REPLACE INTO user(uid,login,info,pw,cap,mtime) "
"VALUES(nullif(%d,0),%Q,%Q,%Q,%Q,now())",
uid, zLogin, P("info"), zPw, zCap
);
admin_log( "Updated user [%q] with capabilities [%q].",
zLogin, zCap );
if( atoi(PD("all","0"))>0 ){
Blob sql;
char *zErr = 0;
blob_zero(&sql);
if( zOldLogin==0 ){
blob_appendf(&sql,
"INSERT INTO user(login)"
|
| ︙ | ︙ | |||
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 |
" mtime=now()"
" WHERE login=%Q;",
zLogin, P("pw"), zLogin, P("info"), zCap,
zOldLogin
);
login_group_sql(blob_str(&sql), "<li> ", " </li>\n", &zErr);
blob_reset(&sql);
if( zErr ){
style_header("User Change Error");
@ <span class="loginError">%s(zErr)</span>
@
@ <p><a href="setup_uedit?id=%d(uid)">[Bummer]</a></p>
style_footer();
return;
}
}
| > > > > | 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 |
" mtime=now()"
" WHERE login=%Q;",
zLogin, P("pw"), zLogin, P("info"), zCap,
zOldLogin
);
login_group_sql(blob_str(&sql), "<li> ", " </li>\n", &zErr);
blob_reset(&sql);
admin_log( "Updated user [%q] in all login groups "
"with capabilities [%q].",
zLogin, zCap );
if( zErr ){
style_header("User Change Error");
admin_log( "Error updating user '%q': %s'.", zLogin, zErr );
@ <span class="loginError">%s(zErr)</span>
@
@ <p><a href="setup_uedit?id=%d(uid)">[Bummer]</a></p>
style_footer();
return;
}
}
|
| ︙ | ︙ | |||
860 861 862 863 864 865 866 867 868 869 870 871 872 873 |
zQ = "off";
}
if( zQ ){
int iQ = fossil_strcmp(zQ,"on")==0 || atoi(zQ);
if( iQ!=iVal ){
login_verify_csrf_secret();
db_set(zVar, iQ ? "1" : "0", 0);
iVal = iQ;
}
}
@ <input type="checkbox" name="%s(zQParm)"
if( iVal ){
@ checked="checked"
}
| > > | 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 |
zQ = "off";
}
if( zQ ){
int iQ = fossil_strcmp(zQ,"on")==0 || atoi(zQ);
if( iQ!=iVal ){
login_verify_csrf_secret();
db_set(zVar, iQ ? "1" : "0", 0);
admin_log("Set option [%q] to [%q].",
zVar, iQ ? "on" : "off");
iVal = iQ;
}
}
@ <input type="checkbox" name="%s(zQParm)"
if( iVal ){
@ checked="checked"
}
|
| ︙ | ︙ | |||
887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 |
const char *zQParm, /* The query parameter */
char *zDflt, /* Default value if VAR table entry does not exist */
int disabled /* 1 if disabled */
){
const char *zVal = db_get(zVar, zDflt);
const char *zQ = P(zQParm);
if( zQ && fossil_strcmp(zQ,zVal)!=0 ){
login_verify_csrf_secret();
db_set(zVar, zQ, 0);
zVal = zQ;
}
@ <input type="text" id="%s(zQParm)" name="%s(zQParm)" value="%h(zVal)" size="%d(width)"
if( disabled ){
@ disabled="disabled"
}
@ /> <b>%s(zLabel)</b>
| > > > | 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 |
const char *zQParm, /* The query parameter */
char *zDflt, /* Default value if VAR table entry does not exist */
int disabled /* 1 if disabled */
){
const char *zVal = db_get(zVar, zDflt);
const char *zQ = P(zQParm);
if( zQ && fossil_strcmp(zQ,zVal)!=0 ){
const int nZQ = (int)strlen(zQ);
login_verify_csrf_secret();
db_set(zVar, zQ, 0);
admin_log("Set entry_attribute %Q to: %.*s%s",
zVar, 20, zQ, (nZQ>20 ? "..." : ""));
zVal = zQ;
}
@ <input type="text" id="%s(zQParm)" name="%s(zQParm)" value="%h(zVal)" size="%d(width)"
if( disabled ){
@ disabled="disabled"
}
@ /> <b>%s(zLabel)</b>
|
| ︙ | ︙ | |||
913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 |
const char *zQP, /* The query parameter */
const char *zDflt, /* Default value if VAR table entry does not exist */
int disabled /* 1 if the textarea should not be editable */
){
const char *z = db_get(zVar, (char*)zDflt);
const char *zQ = P(zQP);
if( zQ && !disabled && fossil_strcmp(zQ,z)!=0){
login_verify_csrf_secret();
db_set(zVar, zQ, 0);
z = zQ;
}
if( rows>0 && cols>0 ){
@ <textarea id="id%s(zQP)" name="%s(zQP)" rows="%d(rows)"
if( disabled ){
@ disabled="disabled"
}
| > > > | 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 |
const char *zQP, /* The query parameter */
const char *zDflt, /* Default value if VAR table entry does not exist */
int disabled /* 1 if the textarea should not be editable */
){
const char *z = db_get(zVar, (char*)zDflt);
const char *zQ = P(zQP);
if( zQ && !disabled && fossil_strcmp(zQ,z)!=0){
const int nZQ = (int)strlen(zQ);
login_verify_csrf_secret();
db_set(zVar, zQ, 0);
admin_log("Set textarea_attribute %Q to: %.*s%s",
zVar, 20, zQ, (nZQ>20 ? "..." : ""));
z = zQ;
}
if( rows>0 && cols>0 ){
@ <textarea id="id%s(zQP)" name="%s(zQP)" rows="%d(rows)"
if( disabled ){
@ disabled="disabled"
}
|
| ︙ | ︙ | |||
944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 |
int nChoice, /* Number of choices */
const char *const *azChoice /* Choices. 2 per choice: (VAR value, Display) */
){
const char *z = db_get(zVar, (char*)zDflt);
const char *zQ = P(zQP);
int i;
if( zQ && fossil_strcmp(zQ,z)!=0){
login_verify_csrf_secret();
db_set(zVar, zQ, 0);
z = zQ;
}
@ <select size="1" name="%s(zQP)" id="id%s(zQP)">
for(i=0; i<nChoice*2; i+=2){
const char *zSel = fossil_strcmp(azChoice[i],z)==0 ? " selected" : "";
@ <option value="%h(azChoice[i])"%s(zSel)>%h(azChoice[i+1])</option>
}
| > > > | 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 |
int nChoice, /* Number of choices */
const char *const *azChoice /* Choices. 2 per choice: (VAR value, Display) */
){
const char *z = db_get(zVar, (char*)zDflt);
const char *zQ = P(zQP);
int i;
if( zQ && fossil_strcmp(zQ,z)!=0){
const int nZQ = (int)strlen(zQ);
login_verify_csrf_secret();
db_set(zVar, zQ, 0);
admin_log("Set multiple_choice_attribute %Q to: %.*s%s",
zVar, 20, zQ, (nZQ>20 ? "..." : ""));
z = zQ;
}
@ <select size="1" name="%s(zQP)" id="id%s(zQP)">
for(i=0; i<nChoice*2; i+=2){
const char *zSel = fossil_strcmp(azChoice[i],z)==0 ? " selected" : "";
@ <option value="%h(azChoice[i])"%s(zSel)>%h(azChoice[i+1])</option>
}
|
| ︙ | ︙ | |||
2021 2022 2023 2024 2025 2026 2027 |
@ <pre class="th1result">%h(zR)</pre>
}else{
@ <pre class="th1error">%h(zR)</pre>
}
}
style_footer();
}
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 |
@ <pre class="th1result">%h(zR)</pre>
}else{
@ <pre class="th1error">%h(zR)</pre>
}
}
style_footer();
}
static void admin_log_render_limits(){
int const count = db_int(0,"SELECT COUNT(*) FROM admin_log");
int i;
int limits[] = {
10, 20, 50, 100, 250, 500, 0
};
for(i = 0; limits[i]; ++i ){
cgi_printf("%s<a href='?n=%d'>%d</a>",
i ? " " : "",
limits[i], limits[i]);
if(limits[i]>count) break;
}
}
/*
** WEBPAGE: admin_log
**
** Shows the contents of the admin_log table, which is only created if
** the admin-log setting is enabled. Requires Admin or Setup ('a' or
** 's') permissions.
*/
void page_admin_log(){
Stmt stLog = empty_Stmt;
Blob qLog = empty_blob;
int limit;
int fLogEnabled;
int counter = 0;
login_check_credentials();
if( !g.perm.Setup && !g.perm.Admin ){
login_needed();
}
style_header("Admin Log");
create_admin_log_table();
limit = atoi(PD("n","20"));
fLogEnabled = db_get_boolean("admin-log", 0);
@ <div>Admin logging is %s(fLogEnabled?"on":"off").</div>
@ <div>Limit results to: <span>
admin_log_render_limits();
@ </span></div>
blob_append_sql(&qLog,
"SELECT datetime(time,'unixepoch'), who, page, what "
"FROM admin_log "
"ORDER BY time DESC ");
if(limit>0){
@ %d(limit) Most recent entries:
blob_append_sql(&qLog, "LIMIT %d", limit);
}
db_prepare(&stLog, "%s", blob_sql_text(&qLog));
blob_reset(&qLog);
@ <table id="adminLogTable" class="adminLogTable" width="100%%">
@ <thead>
@ <th>Time</th>
@ <th>User</th>
@ <th>Page</th>
@ <th width="60%%">Message</th>
@ </thead><tbody>
while( SQLITE_ROW == db_step(&stLog) ){
char const * zTime = db_column_text(&stLog, 0);
char const * zUser = db_column_text(&stLog, 1);
char const * zPage = db_column_text(&stLog, 2);
char const * zMessage = db_column_text(&stLog, 3);
@ <tr class="row%d(counter++%2)">
@ <td class="adminTime">%s(zTime)</td>
@ <td>%s(zUser)</td>
@ <td>%s(zPage)</td>
@ <td>%h(zMessage)</td>
@ </tr>
}
@ </tbody></table>
if(limit>0 && counter<limit){
@ <div>%d(counter) entries shown.</div>
}
style_footer();
}
|
Changes to src/shun.c.
| ︙ | ︙ | |||
54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
login_needed();
}
if( P("rebuild") ){
db_close(1);
db_open_repository(g.zRepositoryName);
db_begin_transaction();
rebuild_db(0, 0, 0);
db_end_transaction(0);
}
if( zUuid ){
char *p;
int i = 0;
int j = 0;
zCanonical = fossil_malloc(strlen(zUuid)+2);
| > | 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
login_needed();
}
if( P("rebuild") ){
db_close(1);
db_open_repository(g.zRepositoryName);
db_begin_transaction();
rebuild_db(0, 0, 0);
admin_log("Rebuilt database.");
db_end_transaction(0);
}
if( zUuid ){
char *p;
int i = 0;
int j = 0;
zCanonical = fossil_malloc(strlen(zUuid)+2);
|
| ︙ | ︙ | |||
99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
int allExist = 1;
login_verify_csrf_secret();
while( *p ){
db_multi_exec("DELETE FROM shun WHERE uuid=%Q", p);
if( !db_exists("SELECT 1 FROM blob WHERE uuid=%Q", p) ){
allExist = 0;
}
p += UUID_SIZE+1;
}
if( allExist ){
@ <p class="noMoreShun">Artifact(s)<br />
for( p = zUuid ; *p ; p += UUID_SIZE+1 ){
@ <a href="%s(g.zTop)/artifact/%s(p)">%s(p)</a><br />
}
| > | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
int allExist = 1;
login_verify_csrf_secret();
while( *p ){
db_multi_exec("DELETE FROM shun WHERE uuid=%Q", p);
if( !db_exists("SELECT 1 FROM blob WHERE uuid=%Q", p) ){
allExist = 0;
}
admin_log("Unshunned %Q", p);
p += UUID_SIZE+1;
}
if( allExist ){
@ <p class="noMoreShun">Artifact(s)<br />
for( p = zUuid ; *p ; p += UUID_SIZE+1 ){
@ <a href="%s(g.zTop)/artifact/%s(p)">%s(p)</a><br />
}
|
| ︙ | ︙ | |||
137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
}
tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='tkt-%q'", p);
if( tagid ){
db_multi_exec("DELETE FROM ticket WHERE tkt_uuid=%Q", p);
db_multi_exec("DELETE FROM tag WHERE tagid=%d", tagid);
db_multi_exec("DELETE FROM tagxref WHERE tagid=%d", tagid);
}
p += UUID_SIZE+1;
}
@ <p class="shunned">Artifact(s)<br />
for( p = zUuid ; *p ; p += UUID_SIZE+1 ){
@ <a href="%s(g.zTop)/artifact/%s(p)">%s(p)</a><br />
}
@ have been shunned. They will no longer be pushed.
| > | 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
}
tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='tkt-%q'", p);
if( tagid ){
db_multi_exec("DELETE FROM ticket WHERE tkt_uuid=%Q", p);
db_multi_exec("DELETE FROM tag WHERE tagid=%d", tagid);
db_multi_exec("DELETE FROM tagxref WHERE tagid=%d", tagid);
}
admin_log("Shunned %Q", p);
p += UUID_SIZE+1;
}
@ <p class="shunned">Artifact(s)<br />
for( p = zUuid ; *p ; p += UUID_SIZE+1 ){
@ <a href="%s(g.zTop)/artifact/%s(p)">%s(p)</a><br />
}
@ have been shunned. They will no longer be pushed.
|
| ︙ | ︙ | |||
290 291 292 293 294 295 296 297 298 299 300 301 302 303 |
/*
** WEBPAGE: rcvfromlist
**
** Show a listing of RCVFROM table entries.
*/
void rcvfromlist_page(void){
int ofst = atoi(PD("ofst","0"));
int cnt;
Stmt q;
login_check_credentials();
if( !g.perm.Admin ){
login_needed();
}
| > | > > > > > > > > > | > | | | > > | > | > > > > | 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 |
/*
** WEBPAGE: rcvfromlist
**
** Show a listing of RCVFROM table entries.
*/
void rcvfromlist_page(void){
int ofst = atoi(PD("ofst","0"));
int showAll = P("all")!=0;
int cnt;
Stmt q;
login_check_credentials();
if( !g.perm.Admin ){
login_needed();
}
style_header("Artifact Receipts");
if( showAll ){
ofst = 0;
}else{
style_submenu_element("All", "All", "rcvfromlist?all=1");
}
if( ofst>0 ){
style_submenu_element("Newer", "Newer", "rcvfromlist?ofst=%d",
ofst>30 ? ofst-30 : 0);
}
db_multi_exec(
"CREATE TEMP TABLE rcvidUsed(x INTEGER PRIMARY KEY);"
"INSERT OR IGNORE INTO rcvidUsed(x) SELECT rcvid FROM blob;"
);
db_prepare(&q,
"SELECT rcvid, login, datetime(rcvfrom.mtime), rcvfrom.ipaddr,"
" EXISTS(SELECT 1 FROM rcvidUsed WHERE x=rcvfrom.rcvid)"
" FROM rcvfrom LEFT JOIN user USING(uid)"
" ORDER BY rcvid DESC LIMIT %d OFFSET %d",
showAll ? -1 : 31, ofst
);
@ <p>Whenever new artifacts are added to the repository, either by
@ push or using the web interface, an entry is made in the RCVFROM table
@ to record the source of that artifact. This log facilitates
@ finding and fixing attempts to inject illicit content into the
@ repository.</p>
@
@ <p>Click on the "rcvid" to show a list of specific artifacts received
@ by a transaction. After identifying illicit artifacts, remove them
@ using the "Shun" button. If an "rcvid" is not hyperlinked, that means
@ all artifacts associated with that rcvid have already been shunned
@ or purged.</p>
@
@ <table cellpadding="0" cellspacing="0" border="0">
@ <tr><th style="padding-right: 15px;text-align: right;">rcvid</th>
@ <th style="padding-right: 15px;text-align: left;">Date</th>
@ <th style="padding-right: 15px;text-align: left;">User</th>
@ <th style="text-align: left;">IP Address</th></tr>
cnt = 0;
while( db_step(&q)==SQLITE_ROW ){
int rcvid = db_column_int(&q, 0);
const char *zUser = db_column_text(&q, 1);
const char *zDate = db_column_text(&q, 2);
const char *zIpAddr = db_column_text(&q, 3);
if( cnt==30 && !showAll ){
style_submenu_element("Older", "Older",
"rcvfromlist?ofst=%d", ofst+30);
}else{
cnt++;
@ <tr>
if( db_column_int(&q,4) ){
@ <td style="padding-right: 15px;text-align: right;">
@ <a href="rcvfrom?rcvid=%d(rcvid)">%d(rcvid)</a></td>
}else{
@ <td style="padding-right: 15px;text-align: right;">%d(rcvid)</td>
}
@ <td style="padding-right: 15px;text-align: left;">%s(zDate)</td>
@ <td style="padding-right: 15px;text-align: left;">%h(zUser)</td>
@ <td style="text-align: left;">%s(zIpAddr)</td>
@ </tr>
}
}
db_finalize(&q);
|
| ︙ | ︙ | |||
360 361 362 363 364 365 366 |
int rcvid = atoi(PD("rcvid","0"));
Stmt q;
login_check_credentials();
if( !g.perm.Admin ){
login_needed();
}
| | | > | > | 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 |
int rcvid = atoi(PD("rcvid","0"));
Stmt q;
login_check_credentials();
if( !g.perm.Admin ){
login_needed();
}
style_header("Artifact Receipt %d", rcvid);
if( db_exists(
"SELECT 1 FROM blob WHERE rcvid=%d AND"
" NOT EXISTS (SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)", rcvid)
){
style_submenu_element("Shun All", "Shun All",
"shun?shun&rcvid=%d#addshun", rcvid);
}
if( db_exists(
"SELECT 1 FROM blob WHERE rcvid=%d AND"
" EXISTS (SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)", rcvid)
){
style_submenu_element("Unshun All", "Unshun All",
"shun?accept&rcvid=%d#delshun", rcvid);
}
db_prepare(&q,
"SELECT login, datetime(rcvfrom.mtime), rcvfrom.ipaddr"
" FROM rcvfrom LEFT JOIN user USING(uid)"
" WHERE rcvid=%d",
rcvid
);
|
| ︙ | ︙ | |||
394 395 396 397 398 399 400 401 |
@ <td valign="top">%s(zUser)</td></tr>
@ <tr><th valign="top" align="right">Date:</th>
@ <td valign="top">%s(zDate)</td></tr>
@ <tr><th valign="top" align="right">IP Address:</th>
@ <td valign="top">%s(zIpAddr)</td></tr>
}
db_finalize(&q);
db_prepare(&q,
| > > > > > > > | < > > | | 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 |
@ <td valign="top">%s(zUser)</td></tr>
@ <tr><th valign="top" align="right">Date:</th>
@ <td valign="top">%s(zDate)</td></tr>
@ <tr><th valign="top" align="right">IP Address:</th>
@ <td valign="top">%s(zIpAddr)</td></tr>
}
db_finalize(&q);
db_multi_exec(
"CREATE TEMP TABLE toshow(rid INTEGER PRIMARY KEY);"
"INSERT INTO toshow SELECT rid FROM blob WHERE rcvid=%d", rcvid
);
describe_artifacts("IN toshow");
db_prepare(&q,
"SELECT blob.rid, blob.uuid, blob.size, description.summary\n"
" FROM blob LEFT JOIN description ON (blob.rid=description.rid)"
" WHERE blob.rcvid=%d", rcvid
);
@ <tr><th valign="top" align="right">Artifacts:</th>
@ <td valign="top">
while( db_step(&q)==SQLITE_ROW ){
const char *zUuid = db_column_text(&q, 1);
int size = db_column_int(&q, 2);
const char *zDesc = db_column_text(&q, 3);
if( zDesc==0 ) zDesc = "";
@ <a href="%s(g.zTop)/info/%s(zUuid)">%s(zUuid)</a>
@ %h(zDesc) (size: %d(size))<br />
}
@ </td></tr>
@ </table>
db_finalize(&q);
style_footer();
}
|
Changes to src/sqlcmd.c.
| ︙ | ︙ | |||
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
rc = uncompress(pOut, &nOut, &pIn[4], nIn-4);
if( rc==Z_OK ){
sqlite3_result_blob(context, pOut, nOut, sqlite3_free);
}else{
sqlite3_result_error(context, "input is not zlib compressed", -1);
}
}
/*
** This is the "automatic extension" initializer that runs right after
** the connection to the repository database is opened. Set up the
** database connection to be more useful to the human operator.
*/
static int sqlcmd_autoinit(
sqlite3 *db,
const char **pzErrMsg,
const void *notUsed
){
| > > > > > > > > > > > > > > < | | > | < < < < < > < < < < < < < < < | | | | | | 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 |
rc = uncompress(pOut, &nOut, &pIn[4], nIn-4);
if( rc==Z_OK ){
sqlite3_result_blob(context, pOut, nOut, sqlite3_free);
}else{
sqlite3_result_error(context, "input is not zlib compressed", -1);
}
}
/*
** Add the content(), compress(), and decompress() SQL functions to
** database connection db.
*/
int add_content_sql_commands(sqlite3 *db){
sqlite3_create_function(db, "content", 1, SQLITE_UTF8, 0,
sqlcmd_content, 0, 0);
sqlite3_create_function(db, "compress", 1, SQLITE_UTF8, 0,
sqlcmd_compress, 0, 0);
sqlite3_create_function(db, "decompress", 1, SQLITE_UTF8, 0,
sqlcmd_decompress, 0, 0);
return SQLITE_OK;
}
/*
** This is the "automatic extension" initializer that runs right after
** the connection to the repository database is opened. Set up the
** database connection to be more useful to the human operator.
*/
static int sqlcmd_autoinit(
sqlite3 *db,
const char **pzErrMsg,
const void *notUsed
){
#if USE_SYSTEM_SQLITE+0==1
sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, g.maxWorkerThreads);
#endif
add_content_sql_commands(db);
re_add_sql_func(db);
g.zMainDbType = "repository";
foci_register(db);
g.repositoryOpen = 1;
g.db = db;
return SQLITE_OK;
}
/*
** COMMAND: sqlite3
**
** Usage: %fossil sqlite3 ?DATABASE? ?OPTIONS?
**
** Run the standalone sqlite3 command-line shell on DATABASE with OPTIONS.
** If DATABASE is omitted, then the repository that serves the working
** directory is opened.
**
** 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 modifies the repository database.
*/
void cmd_sqlite3(void){
extern int sqlite3_shell(int, char**);
|
| ︙ | ︙ |
Changes to src/sqlite3.c.
| ︙ | ︙ | |||
229 230 231 232 233 234 235 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.8.8" #define SQLITE_VERSION_NUMBER 3008008 | | | 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.8.8" #define SQLITE_VERSION_NUMBER 3008008 #define SQLITE_SOURCE_ID "2014-12-06 14:56:49 6aeece19a235344be2537e66a3fe08b1febfb5a0" /* ** 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 |
| ︙ | ︙ | |||
1341 1342 1343 1344 1345 1346 1347 | ** <li> SQLITE_SHM_LOCK | SQLITE_SHM_SHARED ** <li> SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE ** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED ** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE ** </ul> ** ** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as | | | 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 | ** <li> SQLITE_SHM_LOCK | SQLITE_SHM_SHARED ** <li> SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE ** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED ** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE ** </ul> ** ** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as ** was given on the corresponding lock. ** ** The xShmLock method can transition between unlocked and SHARED or ** between unlocked and EXCLUSIVE. It cannot transition between SHARED ** and EXCLUSIVE. */ #define SQLITE_SHM_UNLOCK 1 #define SQLITE_SHM_LOCK 2 |
| ︙ | ︙ | |||
1644 1645 1646 1647 1648 1649 1650 | ** This option can be used to overload the default memory allocation ** routines with a wrapper that simulations memory allocation failure or ** tracks memory usage, for example. </dd> ** ** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt> ** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int, ** interpreted as a boolean, which enables or disables the collection of | | | | 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 | ** This option can be used to overload the default memory allocation ** routines with a wrapper that simulations memory allocation failure or ** tracks memory usage, for example. </dd> ** ** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt> ** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int, ** interpreted as a boolean, which enables or disables the collection of ** memory allocation statistics. ^(When memory allocation statistics are ** disabled, the following SQLite interfaces become non-operational: ** <ul> ** <li> [sqlite3_memory_used()] ** <li> [sqlite3_memory_highwater()] ** <li> [sqlite3_soft_heap_limit64()] ** <li> [sqlite3_status()] ** </ul>)^ ** ^Memory allocation statistics are enabled by default unless SQLite is |
| ︙ | ︙ | |||
1686 1687 1688 1689 1690 1691 1692 | ** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt> ** <dd> ^The SQLITE_CONFIG_PAGECACHE option specifies a static memory buffer ** that SQLite can use for the database page cache with the default page ** cache implementation. ** This configuration should not be used if an application-define page ** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2] ** configuration option. | | > | > | | | | 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 | ** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt> ** <dd> ^The SQLITE_CONFIG_PAGECACHE option specifies a static memory buffer ** that SQLite can use for the database page cache with the default page ** cache implementation. ** This configuration should not be used if an application-define page ** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2] ** configuration option. ** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to ** 8-byte aligned ** memory, the size of each page buffer (sz), and the number of pages (N). ** The sz argument should be the size of the largest database page ** (a power of two between 512 and 32768) plus some extra bytes for each ** page header. ^The number of extra bytes needed by the page header ** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option ** to [sqlite3_config()]. ** ^It is harmless, apart from the wasted memory, ** for the sz parameter to be larger than necessary. The first ** argument should pointer to an 8-byte aligned block of memory that ** is at least sz*N bytes of memory, otherwise subsequent behavior is ** undefined. ** ^SQLite will use the memory provided by the first argument to satisfy its ** memory needs for the first N pages that it adds to cache. ^If additional ** page cache memory is needed beyond what is provided by this option, then ** SQLite goes to [sqlite3_malloc()] for the additional storage space.</dd> ** ** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt> ** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer ** that SQLite will use for all of its dynamic memory allocation needs ** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and ** [SQLITE_CONFIG_PAGECACHE]. ** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled ** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns ** [SQLITE_ERROR] if invoked otherwise. ** ^There are three arguments to SQLITE_CONFIG_HEAP: ** An 8-byte aligned pointer to the memory, ** the number of bytes in the memory buffer, and the minimum allocation size. ** ^If the first pointer (the memory pointer) is NULL, then SQLite reverts ** to using its default memory allocator (the system malloc() implementation), ** undoing any prior invocation of [SQLITE_CONFIG_MALLOC]. ^If the ** memory pointer is not NULL then the alternative memory ** allocator is engaged to handle all of SQLites memory allocation needs. ** The first pointer (the memory pointer) must be aligned to an 8-byte ** boundary or subsequent behavior of SQLite will be undefined. ** The minimum allocation size is capped at 2**12. Reasonable values ** for the minimum allocation size are 2**5 through 2**8.</dd> ** ** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt> ** <dd> ^(The SQLITE_CONFIG_MUTEX option takes a single argument which is a ** pointer to an instance of the [sqlite3_mutex_methods] structure. ** The argument specifies alternative low-level mutex routines to be used ** in place the mutex routines built into SQLite.)^ ^SQLite makes a copy of ** the content of the [sqlite3_mutex_methods] structure before the call to ** [sqlite3_config()] returns. ^If SQLite is compiled with ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then ** the entire mutexing subsystem is omitted from the build and hence calls to ** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will ** return [SQLITE_ERROR].</dd> ** ** [[SQLITE_CONFIG_GETMUTEX]] <dt>SQLITE_CONFIG_GETMUTEX</dt> |
| ︙ | ︙ | |||
1766 1767 1768 1769 1770 1771 1772 | ** <dd> ^(The SQLITE_CONFIG_PCACHE2 option takes a single argument which is ** a pointer to an [sqlite3_pcache_methods2] object. This object specifies ** the interface to a custom page cache implementation.)^ ** ^SQLite makes a copy of the [sqlite3_pcache_methods2] object.</dd> ** ** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt> ** <dd> ^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which | | | | 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 | ** <dd> ^(The SQLITE_CONFIG_PCACHE2 option takes a single argument which is ** a pointer to an [sqlite3_pcache_methods2] object. This object specifies ** the interface to a custom page cache implementation.)^ ** ^SQLite makes a copy of the [sqlite3_pcache_methods2] object.</dd> ** ** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt> ** <dd> ^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which ** 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(*)(void*,int,const char*), ** and a pointer to void. ^If the function pointer is not NULL, it is |
| ︙ | ︙ | |||
1792 1793 1794 1795 1796 1797 1798 | ** supplied by the application must not invoke any SQLite interface. ** In a multi-threaded application, the application-defined logger ** function must be threadsafe. </dd> ** ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI ** <dd>^(The SQLITE_CONFIG_URI option takes a single argument of type int. ** If non-zero, then URI handling is globally enabled. If the parameter is zero, | | | > | 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 | ** supplied by the application must not invoke any SQLite interface. ** In a multi-threaded application, the application-defined logger ** function must be threadsafe. </dd> ** ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI ** <dd>^(The SQLITE_CONFIG_URI option takes a single argument of type int. ** If non-zero, then URI handling is globally enabled. If the parameter is zero, ** then URI handling is globally disabled.)^ ^If URI handling is globally ** enabled, all filenames passed to [sqlite3_open()], [sqlite3_open_v2()], ** [sqlite3_open16()] or ** specified as part of [ATTACH] commands are interpreted as URIs, regardless ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database ** connection is opened. ^If it is globally disabled, filenames are ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the ** database connection is opened. ^(By default, URI handling is globally ** disabled. The default value may be changed by compiling with the ** [SQLITE_USE_URI] symbol defined.)^ |
| ︙ | ︙ | |||
1855 1856 1857 1858 1859 1860 1861 | ** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^ ** ^If either argument to this option is negative, then that argument is ** changed to its compile-time default. ** ** [[SQLITE_CONFIG_WIN32_HEAPSIZE]] ** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE ** <dd>^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is | | | | | | 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 | ** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^ ** ^If either argument to this option is negative, then that argument is ** changed to its compile-time default. ** ** [[SQLITE_CONFIG_WIN32_HEAPSIZE]] ** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE ** <dd>^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is ** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro ** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value ** that specifies the maximum size of the created heap. ** </dl> ** ** [[SQLITE_CONFIG_PCACHE_HDRSZ]] ** <dt>SQLITE_CONFIG_PCACHE_HDRSZ ** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which ** is a pointer to an integer and writes into that integer the number of extra ** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE]. ** The amount of extra space required can change depending on the compiler, ** target platform, and SQLite version. ** </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* */ |
| ︙ | ︙ | |||
2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 | ** UTF-16 string in native byte order. */ SQLITE_API int sqlite3_complete(const char *sql); SQLITE_API int sqlite3_complete16(const void *sql); /* ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors ** ** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X ** that might be invoked with argument P whenever ** an attempt is made to access a database table associated with ** [database connection] D when another thread ** or process has the table locked. ** The sqlite3_busy_handler() interface is used to implement ** [sqlite3_busy_timeout()] and [PRAGMA busy_timeout]. ** ** ^If the busy callback is NULL, then [SQLITE_BUSY] ** is returned immediately upon encountering the lock. ^If the busy callback ** is not NULL, then the callback might be invoked with two arguments. ** ** ^The first argument to the busy handler is a copy of the void* pointer which ** is the third argument to sqlite3_busy_handler(). ^The second argument to ** the busy handler callback is the number of times that the busy handler has | > | | 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 |
** UTF-16 string in native byte order.
*/
SQLITE_API int sqlite3_complete(const char *sql);
SQLITE_API int sqlite3_complete16(const void *sql);
/*
** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
** KEYWORDS: {busy-handler callback} {busy handler}
**
** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X
** that might be invoked with argument P whenever
** an attempt is made to access a database table associated with
** [database connection] D when another thread
** or process has the table locked.
** The sqlite3_busy_handler() interface is used to implement
** [sqlite3_busy_timeout()] and [PRAGMA busy_timeout].
**
** ^If the busy callback is NULL, then [SQLITE_BUSY]
** is returned immediately upon encountering the lock. ^If the busy callback
** is not NULL, then the callback might be invoked with two arguments.
**
** ^The first argument to the busy handler is a copy of the void* pointer which
** is the third argument to sqlite3_busy_handler(). ^The second argument to
** the busy handler callback is the number of times that the busy handler has
** been invoked previously for the same locking event. ^If the
** busy callback returns 0, then no additional attempts are made to
** access the database and [SQLITE_BUSY] is returned
** to the application.
** ^If the callback returns non-zero, then another attempt
** is made to access the database and the cycle repeats.
**
** The presence of a busy handler does not guarantee that it will be invoked
|
| ︙ | ︙ | |||
4640 4641 4642 4643 4644 4645 4646 | ** 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 sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); | | > | 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 |
** 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 sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*,
sqlite3_uint64,void(*)(void*));
SQLITE_API void sqlite3_result_double(sqlite3_context*, double);
SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int);
SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int);
SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*);
SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*);
SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int);
SQLITE_API void sqlite3_result_int(sqlite3_context*, int);
|
| ︙ | ︙ | |||
7366 7367 7368 7369 7370 7371 7372 | ** for a particular application. */ SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); /* ** CAPI3REF: Checkpoint a database ** | < < < < < | | < < | > > | < < > > > > > > | > | | | | | < | | > > | | | | | | | | | > | > > > > | | > > | | | > | < < > | | | | | | | | | | | > | | | | | > > > > > > > > | > | | | | | | | > | 7371 7372 7373 7374 7375 7376 7377 7378 7379 7380 7381 7382 7383 7384 7385 7386 7387 7388 7389 7390 7391 7392 7393 7394 7395 7396 7397 7398 7399 7400 7401 7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 7425 7426 7427 7428 7429 7430 7431 7432 7433 7434 7435 7436 7437 7438 7439 7440 7441 7442 7443 7444 7445 7446 7447 7448 7449 7450 7451 7452 7453 7454 7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474 7475 7476 7477 7478 7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489 7490 7491 7492 7493 7494 7495 7496 7497 7498 7499 7500 7501 7502 7503 7504 7505 7506 7507 7508 7509 7510 7511 7512 7513 7514 |
** for a particular application.
*/
SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
/*
** CAPI3REF: Checkpoint a database
**
** ^(The sqlite3_wal_checkpoint(D,X) is equivalent to
** [sqlite3_wal_checkpoint_v2](D,X,[SQLITE_CHECKPOINT_PASSIVE],0,0).)^
**
** In brief, sqlite3_wal_checkpoint(D,X) causes the content in the
** [write-ahead log] for database X on [database connection] D to be
** transferred into the database file and for the write-ahead log to
** be reset. See the [checkpointing] documentation for addition
** information.
**
** 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 sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
/*
** CAPI3REF: Checkpoint a database
**
** ^(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
** information is written back into integers pointed to by L and C.)^
** ^(The M parameter must be a valid [checkpoint mode]:)^
**
** <dl>
** <dt>SQLITE_CHECKPOINT_PASSIVE<dd>
** ^Checkpoint as many frames as possible without waiting for any database
** readers or writers to finish, then sync the database file if all frames
** in the log were checkpointed. ^The [busy-handler callback]
** is never invoked in the SQLITE_CHECKPOINT_PASSIVE mode.
** ^On the other hand, passive mode might leave the checkpoint unfinished
** if there are concurrent readers or writers.
**
** <dt>SQLITE_CHECKPOINT_FULL<dd>
** ^This mode blocks (it invokes the
** [sqlite3_busy_handler|busy-handler callback]) until there is no
** database writer and all readers are reading from the most recent database
** snapshot. ^It then checkpoints all frames in the log file and syncs the
** database file. ^This mode blocks new database writers while it is pending,
** but new database readers are allowed to continue unimpeded.
**
** <dt>SQLITE_CHECKPOINT_RESTART<dd>
** ^This mode works the same way as SQLITE_CHECKPOINT_FULL with the addition
** that after checkpointing the log file it blocks (calls the
** [busy-handler callback])
** until all readers are reading from the database file only. ^This ensures
** that the next writer will restart the log file from the beginning.
** ^Like SQLITE_CHECKPOINT_FULL, this mode blocks new
** database writer attempts while it is pending, but does not impede readers.
**
** <dt>SQLITE_CHECKPOINT_TRUNCATE<dd>
** ^This mode works the same way as SQLITE_CHECKPOINT_RESTART with the
** addition that it also truncates the log file to zero bytes just prior
** to a successful return.
** </dl>
**
** ^If pnLog is not NULL, then *pnLog is set to the total number of frames in
** the log file or to -1 if the checkpoint could not run because
** of an error or because the database is not in [WAL mode]. ^If pnCkpt is not
** NULL,then *pnCkpt is set to the total number of checkpointed frames in the
** log file (including any that were already checkpointed before the function
** was called) or to -1 if the checkpoint could not run due to an error or
** because the database is not in WAL mode. ^Note that upon successful
** completion of an SQLITE_CHECKPOINT_TRUNCATE, the log file will have been
** truncated to zero bytes and so both *pnLog and *pnCkpt will be set to zero.
**
** ^All calls obtain an exclusive "checkpoint" lock on the database file. ^If
** any other process is running a checkpoint operation at the same time, the
** lock cannot be obtained and SQLITE_BUSY is returned. ^Even if there is a
** busy-handler configured, it will not be invoked in this case.
**
** ^The SQLITE_CHECKPOINT_FULL, RESTART and TRUNCATE modes also obtain the
** exclusive "writer" lock on the database file. ^If the writer lock cannot be
** obtained immediately, and a busy-handler is configured, it is invoked and
** the writer lock retried until either the busy-handler returns 0 or the lock
** is successfully obtained. ^The busy-handler is also invoked while waiting for
** database readers as described above. ^If the busy-handler returns 0 before
** the writer lock is obtained or while waiting for database readers, the
** checkpoint operation proceeds from that point in the same way as
** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible
** without blocking any further. ^SQLITE_BUSY is returned in this case.
**
** ^If parameter zDb is NULL or points to a zero length string, then the
** specified operation is attempted on all WAL databases [attached] to
** [database connection] db. In this case the
** values written to output parameters *pnLog and *pnCkpt are undefined. ^If
** an SQLITE_BUSY error is encountered when processing one or more of the
** attached WAL databases, the operation is still attempted on any remaining
** attached databases and SQLITE_BUSY is returned at the end. ^If any other
** error occurs while processing an attached database, processing is abandoned
** and the error code is returned to the caller immediately. ^If no error
** (SQLITE_BUSY or otherwise) is encountered while processing the attached
** databases, SQLITE_OK is returned.
**
** ^If database zDb is the name of an attached database that is not in WAL
** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. ^If
** zDb is not NULL (or a zero length string) and is not the name of any
** attached database, SQLITE_ERROR is returned to the caller.
**
** ^Unless it returns SQLITE_MISUSE,
** 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 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 */
);
/*
** CAPI3REF: Checkpoint Mode Values
** KEYWORDS: {checkpoint mode}
**
** These constants define all valid values for the "checkpoint mode" passed
** as the third parameter to the [sqlite3_wal_checkpoint_v2()] interface.
** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the
** meaning of each of these checkpoint modes.
*/
#define SQLITE_CHECKPOINT_PASSIVE 0 /* Do as much as possible w/o blocking */
#define SQLITE_CHECKPOINT_FULL 1 /* Wait for writers, then checkpoint */
#define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for for readers */
#define SQLITE_CHECKPOINT_TRUNCATE 3 /* Like RESTART but also truncate WAL */
/*
** CAPI3REF: Virtual Table Interface Configuration
**
** This function may be called by either the [xConnect] or [xCreate] method
** of a [virtual table] implementation to configure
** various facets of the virtual table interface.
|
| ︙ | ︙ | |||
7575 7576 7577 7578 7579 7580 7581 | ** ** The following constants can be used for the T parameter to the ** [sqlite3_stmt_scanstatus(S,X,T,V)] interface. Each constant designates a ** different metric for sqlite3_stmt_scanstatus() to return. ** ** <dl> ** [[SQLITE_SCANSTAT_NLOOP]] <dt>SQLITE_SCANSTAT_NLOOP</dt> | | | | | | | | | | | | 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 | ** ** The following constants can be used for the T parameter to the ** [sqlite3_stmt_scanstatus(S,X,T,V)] interface. Each constant designates a ** different metric for sqlite3_stmt_scanstatus() to return. ** ** <dl> ** [[SQLITE_SCANSTAT_NLOOP]] <dt>SQLITE_SCANSTAT_NLOOP</dt> ** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be ** set to the total number of times that the X-th loop has run.</dd> ** ** [[SQLITE_SCANSTAT_NVISIT]] <dt>SQLITE_SCANSTAT_NVISIT</dt> ** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be set ** to the total number of rows examined by all iterations of the X-th loop.</dd> ** ** [[SQLITE_SCANSTAT_EST]] <dt>SQLITE_SCANSTAT_EST</dt> ** <dd>^The "double" variable pointed to by the T parameter will be set to the ** query planner's estimate for the average number of rows output from each ** iteration of the X-th loop. If the query planner's estimates was accurate, ** then this value will approximate the quotient NVISIT/NLOOP and the ** product of this value for all prior loops with the same SELECTID will ** be the NLOOP value for the current loop. ** ** [[SQLITE_SCANSTAT_NAME]] <dt>SQLITE_SCANSTAT_NAME</dt> ** <dd>^The "const char *" variable pointed to by the T parameter will be set ** to a zero-terminated UTF-8 string containing the name of the index or table ** used for the X-th loop. ** ** [[SQLITE_SCANSTAT_EXPLAIN]] <dt>SQLITE_SCANSTAT_EXPLAIN</dt> ** <dd>^The "const char *" variable pointed to by the T parameter will be set ** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] ** description for the X-th loop. ** ** [[SQLITE_SCANSTAT_SELECTID]] <dt>SQLITE_SCANSTAT_SELECT</dt> ** <dd>^The "int" variable pointed to by the T parameter will be set to the ** "select-id" for the X-th loop. The select-id identifies which query or ** subquery the loop is part of. The main query has a select-id of zero. ** The select-id is the same value as is output in the first column ** of an [EXPLAIN QUERY PLAN] query. |
| ︙ | ︙ | |||
7621 7622 7623 7624 7625 7626 7627 | /* ** CAPI3REF: Prepared Statement Scan Status ** ** Return status data for a single loop within query pStmt. ** ** The "iScanStatusOp" parameter determines which status information to return. | | | | 7645 7646 7647 7648 7649 7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660 | /* ** CAPI3REF: Prepared Statement Scan Status ** ** Return status data for a single loop within query pStmt. ** ** The "iScanStatusOp" parameter determines which status information to return. ** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior ** of this interface is undefined. ** ^The requested measurement is written into a variable pointed to by ** the "pOut" parameter. ** Parameter "idx" identifies the specific loop to retrieve statistics for. ** Loops are numbered starting from zero. ^If idx is out of range - less than ** zero or greater than or equal to the total number of loops used to implement ** the statement - a non-zero value is returned and the variable that pOut ** points to is unchanged. |
| ︙ | ︙ | |||
11673 11674 11675 11676 11677 11678 11679 | AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ Table *pTab; /* Table for TK_COLUMN expressions. */ }; /* ** The following are the meanings of bits in the Expr.flags field. */ | | > | 11697 11698 11699 11700 11701 11702 11703 11704 11705 11706 11707 11708 11709 11710 11711 11712 11713 11714 11715 11716 11717 11718 11719 11720 11721 11722 11723 11724 11725 11726 11727 11728 11729 11730 11731 | AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ Table *pTab; /* Table for TK_COLUMN expressions. */ }; /* ** The following are the meanings of bits in the Expr.flags field. */ #define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */ #define EP_Agg 0x000002 /* Contains one or more aggregate functions */ #define EP_Resolved 0x000004 /* IDs have been resolved to COLUMNs */ #define EP_Error 0x000008 /* Expression contains one or more errors */ #define EP_Distinct 0x000010 /* Aggregate function with DISTINCT keyword */ #define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */ #define EP_DblQuoted 0x000040 /* token.z was originally in "..." */ #define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */ #define EP_Collate 0x000100 /* Tree contains a TK_COLLATE operator */ #define EP_Generic 0x000200 /* Ignore COLLATE or affinity on this tree */ #define EP_IntValue 0x000400 /* Integer value contained in u.iValue */ #define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */ #define EP_Skip 0x001000 /* COLLATE, AS, or UNLIKELY */ #define EP_Reduced 0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */ #define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */ #define EP_Static 0x008000 /* Held in memory not obtained from malloc() */ #define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */ #define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */ #define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ #define EP_Constant 0x080000 /* Node is a constant */ #define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ /* ** These macros can be used to test, set, or clear bits in the ** Expr.flags field. */ #define ExprHasProperty(E,P) (((E)->flags&(P))!=0) #define ExprHasAllProperty(E,P) (((E)->flags&(P))==(P)) |
| ︙ | ︙ | |||
48197 48198 48199 48200 48201 48202 48203 |
**
** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
*/
SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){
int rc = SQLITE_OK;
if( pPager->pWal ){
rc = sqlite3WalCheckpoint(pPager->pWal, eMode,
| > | | 48222 48223 48224 48225 48226 48227 48228 48229 48230 48231 48232 48233 48234 48235 48236 48237 |
**
** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
*/
SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){
int rc = SQLITE_OK;
if( pPager->pWal ){
rc = sqlite3WalCheckpoint(pPager->pWal, eMode,
(eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
pPager->pBusyHandlerArg,
pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
pnLog, pnCkpt
);
}
return rc;
}
|
| ︙ | ︙ | |||
50007 50008 50009 50010 50011 50012 50013 50014 50015 50016 50017 50018 50019 50020 |
/*
** The cache of the wal-index header must be valid to call this function.
** Return the page-size in bytes used by the database.
*/
static int walPagesize(Wal *pWal){
return (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16);
}
/*
** Copy as much content as we can from the WAL back into the database file
** in response to an sqlite3_wal_checkpoint() request or the equivalent.
**
** The amount of information copies from WAL to database might be limited
** by active readers. This routine will never overwrite a database page
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 50033 50034 50035 50036 50037 50038 50039 50040 50041 50042 50043 50044 50045 50046 50047 50048 50049 50050 50051 50052 50053 50054 50055 50056 50057 50058 50059 50060 50061 50062 50063 50064 50065 50066 50067 50068 50069 50070 50071 50072 50073 50074 50075 50076 50077 50078 |
/*
** The cache of the wal-index header must be valid to call this function.
** Return the page-size in bytes used by the database.
*/
static int walPagesize(Wal *pWal){
return (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16);
}
/*
** The following is guaranteed when this function is called:
**
** a) the WRITER lock is held,
** b) the entire log file has been checkpointed, and
** c) any existing readers are reading exclusively from the database
** file - there are no readers that may attempt to read a frame from
** the log file.
**
** This function updates the shared-memory structures so that the next
** client to write to the database (which may be this one) does so by
** writing frames into the start of the log file.
**
** The value of parameter salt1 is used as the aSalt[1] value in the
** new wal-index header. It should be passed a pseudo-random value (i.e.
** one obtained from sqlite3_randomness()).
*/
static void walRestartHdr(Wal *pWal, u32 salt1){
volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
int i; /* Loop counter */
u32 *aSalt = pWal->hdr.aSalt; /* Big-endian salt values */
pWal->nCkpt++;
pWal->hdr.mxFrame = 0;
sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0]));
memcpy(&pWal->hdr.aSalt[1], &salt1, 4);
walIndexWriteHdr(pWal);
pInfo->nBackfill = 0;
pInfo->aReadMark[1] = 0;
for(i=2; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
assert( pInfo->aReadMark[0]==0 );
}
/*
** Copy as much content as we can from the WAL back into the database file
** in response to an sqlite3_wal_checkpoint() request or the equivalent.
**
** The amount of information copies from WAL to database might be limited
** by active readers. This routine will never overwrite a database page
|
| ︙ | ︙ | |||
50042 50043 50044 50045 50046 50047 50048 | ** The caller must be holding sufficient locks to ensure that no other ** checkpoint is running (in any other thread or process) at the same ** time. */ static int walCheckpoint( Wal *pWal, /* Wal connection */ int eMode, /* One of PASSIVE, FULL or RESTART */ | | < > > | | 50100 50101 50102 50103 50104 50105 50106 50107 50108 50109 50110 50111 50112 50113 50114 50115 50116 50117 50118 50119 50120 50121 50122 50123 50124 50125 50126 50127 50128 50129 50130 50131 50132 50133 50134 50135 50136 50137 50138 50139 50140 50141 50142 50143 50144 |
** The caller must be holding sufficient locks to ensure that no other
** checkpoint is running (in any other thread or process) at the same
** time.
*/
static int walCheckpoint(
Wal *pWal, /* Wal connection */
int eMode, /* One of PASSIVE, FULL or RESTART */
int (*xBusy)(void*), /* Function to call when busy */
void *pBusyArg, /* Context argument for xBusyHandler */
int sync_flags, /* Flags for OsSync() (or 0) */
u8 *zBuf /* Temporary buffer to use */
){
int rc; /* Return code */
int szPage; /* Database page-size */
WalIterator *pIter = 0; /* Wal iterator context */
u32 iDbpage = 0; /* Next database page to write */
u32 iFrame = 0; /* Wal frame containing data for iDbpage */
u32 mxSafeFrame; /* Max frame that can be backfilled */
u32 mxPage; /* Max database page to write */
int i; /* Loop counter */
volatile WalCkptInfo *pInfo; /* The checkpoint status information */
szPage = walPagesize(pWal);
testcase( szPage<=32768 );
testcase( szPage>=65536 );
pInfo = walCkptInfo(pWal);
if( pInfo->nBackfill>=pWal->hdr.mxFrame ) return SQLITE_OK;
/* Allocate the iterator */
rc = walIteratorInit(pWal, &pIter);
if( rc!=SQLITE_OK ){
return rc;
}
assert( pIter );
/* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked
** in the SQLITE_CHECKPOINT_PASSIVE mode. */
assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 );
/* Compute in mxSafeFrame the index of the last frame of the WAL that is
** safe to write into the database. Frames beyond mxSafeFrame might
** overwrite database pages that are in use by active readers and thus
** cannot be backfilled from the WAL.
*/
mxSafeFrame = pWal->hdr.mxFrame;
|
| ︙ | ︙ | |||
50160 50161 50162 50163 50164 50165 50166 |
if( rc==SQLITE_BUSY ){
/* Reset the return code so as not to report a checkpoint failure
** just because there are active readers. */
rc = SQLITE_OK;
}
| | | | | | > > > > > > > > > > > > > > > > > > > | 50219 50220 50221 50222 50223 50224 50225 50226 50227 50228 50229 50230 50231 50232 50233 50234 50235 50236 50237 50238 50239 50240 50241 50242 50243 50244 50245 50246 50247 50248 50249 50250 50251 50252 50253 50254 50255 50256 50257 50258 50259 50260 50261 50262 50263 50264 |
if( rc==SQLITE_BUSY ){
/* Reset the return code so as not to report a checkpoint failure
** just because there are active readers. */
rc = SQLITE_OK;
}
/* If this is an SQLITE_CHECKPOINT_RESTART or TRUNCATE operation, and the
** entire wal file has been copied into the database file, then block
** until all readers have finished using the wal file. This ensures that
** the next process to write to the database restarts the wal file.
*/
if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){
assert( pWal->writeLock );
if( pInfo->nBackfill<pWal->hdr.mxFrame ){
rc = SQLITE_BUSY;
}else if( eMode>=SQLITE_CHECKPOINT_RESTART ){
u32 salt1;
sqlite3_randomness(4, &salt1);
assert( mxSafeFrame==pWal->hdr.mxFrame );
rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(1), WAL_NREADER-1);
if( rc==SQLITE_OK ){
if( eMode==SQLITE_CHECKPOINT_TRUNCATE ){
/* IMPLEMENTATION-OF: R-44699-57140 This mode works the same way as
** SQLITE_CHECKPOINT_RESTART with the addition that it also
** truncates the log file to zero bytes just prior to a
** successful return.
**
** In theory, it might be safe to do this without updating the
** wal-index header in shared memory, as all subsequent reader or
** writer clients should see that the entire log file has been
** checkpointed and behave accordingly. This seems unsafe though,
** as it would leave the system in a state where the contents of
** the wal-index header do not match the contents of the
** file-system. To avoid this, update the wal-index header to
** indicate that the log file contains zero valid frames. */
walRestartHdr(pWal, salt1);
rc = sqlite3OsTruncate(pWal->pWalFd, 0);
}
walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
}
}
}
walcheckpoint_out:
walIteratorFree(pIter);
|
| ︙ | ︙ | |||
50958 50959 50960 50961 50962 50963 50964 |
pWal->hdr.aFrameCksum[1] = aWalData[2];
walCleanupHash(pWal);
}
return rc;
}
| < | 51036 51037 51038 51039 51040 51041 51042 51043 51044 51045 51046 51047 51048 51049 |
pWal->hdr.aFrameCksum[1] = aWalData[2];
walCleanupHash(pWal);
}
return rc;
}
/*
** This function is called just before writing a set of frames to the log
** file (see sqlite3WalFrames()). It checks to see if, instead of appending
** to the current log file, it is possible to overwrite the start of the
** existing log file with the new frames (i.e. "reset" the log). If so,
** it sets pWal->hdr.mxFrame to 0. Otherwise, pWal->hdr.mxFrame is left
** unchanged.
|
| ︙ | ︙ | |||
50991 50992 50993 50994 50995 50996 50997 |
** readers are currently using the WAL), then the transactions
** frames will overwrite the start of the existing log. Update the
** wal-index header to reflect this.
**
** In theory it would be Ok to update the cache of the header only
** at this point. But updating the actual wal-index header is also
** safe and means there is no special case for sqlite3WalUndo()
| | < < < | < < < < < < < < < | 51068 51069 51070 51071 51072 51073 51074 51075 51076 51077 51078 51079 51080 51081 51082 51083 |
** readers are currently using the WAL), then the transactions
** frames will overwrite the start of the existing log. Update the
** wal-index header to reflect this.
**
** In theory it would be Ok to update the cache of the header only
** at this point. But updating the actual wal-index header is also
** safe and means there is no special case for sqlite3WalUndo()
** to handle if this transaction is rolled back. */
walRestartHdr(pWal, salt1);
walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
}else if( rc!=SQLITE_BUSY ){
return rc;
}
}
walUnlockShared(pWal, WAL_READ_LOCK(0));
pWal->readLock = -1;
|
| ︙ | ︙ | |||
51292 51293 51294 51295 51296 51297 51298 | ** we can from WAL into the database. ** ** If parameter xBusy is not NULL, it is a pointer to a busy-handler ** callback. In this case this function runs a blocking checkpoint. */ SQLITE_PRIVATE int sqlite3WalCheckpoint( Wal *pWal, /* Wal connection */ | | > > > > > > > > | | | > > > > > > | < | | > | < | > | | 51357 51358 51359 51360 51361 51362 51363 51364 51365 51366 51367 51368 51369 51370 51371 51372 51373 51374 51375 51376 51377 51378 51379 51380 51381 51382 51383 51384 51385 51386 51387 51388 51389 51390 51391 51392 51393 51394 51395 51396 51397 51398 51399 51400 51401 51402 51403 51404 51405 51406 51407 51408 51409 51410 51411 51412 51413 51414 51415 51416 51417 51418 51419 51420 51421 51422 51423 51424 51425 51426 51427 51428 51429 51430 51431 51432 51433 51434 51435 51436 51437 51438 51439 51440 51441 51442 51443 51444 |
** we can from WAL into the database.
**
** If parameter xBusy is not NULL, it is a pointer to a busy-handler
** callback. In this case this function runs a blocking checkpoint.
*/
SQLITE_PRIVATE int sqlite3WalCheckpoint(
Wal *pWal, /* Wal connection */
int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */
int (*xBusy)(void*), /* Function to call when busy */
void *pBusyArg, /* Context argument for xBusyHandler */
int sync_flags, /* Flags to sync db file with (or 0) */
int nBuf, /* Size of temporary buffer */
u8 *zBuf, /* Temporary buffer to use */
int *pnLog, /* OUT: Number of frames in WAL */
int *pnCkpt /* OUT: Number of backfilled frames in WAL */
){
int rc; /* Return code */
int isChanged = 0; /* True if a new wal-index header is loaded */
int eMode2 = eMode; /* Mode to pass to walCheckpoint() */
int (*xBusy2)(void*) = xBusy; /* Busy handler for eMode2 */
assert( pWal->ckptLock==0 );
assert( pWal->writeLock==0 );
/* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked
** in the SQLITE_CHECKPOINT_PASSIVE mode. */
assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 );
if( pWal->readOnly ) return SQLITE_READONLY;
WALTRACE(("WAL%p: checkpoint begins\n", pWal));
/* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive
** "checkpoint" lock on the database file. */
rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
if( rc ){
/* EVIDENCE-OF: R-10421-19736 If any other process is running a
** checkpoint operation at the same time, the lock cannot be obtained and
** SQLITE_BUSY is returned.
** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured,
** it will not be invoked in this case.
*/
testcase( rc==SQLITE_BUSY );
testcase( xBusy!=0 );
return rc;
}
pWal->ckptLock = 1;
/* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and
** TRUNCATE modes also obtain the exclusive "writer" lock on the database
** file.
**
** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained
** immediately, and a busy-handler is configured, it is invoked and the
** writer lock retried until either the busy-handler returns 0 or the
** lock is successfully obtained.
*/
if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1);
if( rc==SQLITE_OK ){
pWal->writeLock = 1;
}else if( rc==SQLITE_BUSY ){
eMode2 = SQLITE_CHECKPOINT_PASSIVE;
xBusy2 = 0;
rc = SQLITE_OK;
}
}
/* Read the wal-index header. */
if( rc==SQLITE_OK ){
rc = walIndexReadHdr(pWal, &isChanged);
if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){
sqlite3OsUnfetch(pWal->pDbFd, 0, 0);
}
}
/* Copy data from the log to the database file. */
if( rc==SQLITE_OK ){
if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
rc = SQLITE_CORRUPT_BKPT;
}else{
rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf);
}
/* If no error occurred, set the output variables. */
if( rc==SQLITE_OK || rc==SQLITE_BUSY ){
if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame;
if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill);
}
|
| ︙ | ︙ | |||
53819 53820 53821 53822 53823 53824 53825 |
/* The request could not be fulfilled using a freelist slot. Check
** to see if defragmentation is necessary.
*/
testcase( gap+2+nByte==top );
if( gap+2+nByte>top ){
defragment_page:
| | | 53898 53899 53900 53901 53902 53903 53904 53905 53906 53907 53908 53909 53910 53911 53912 |
/* The request could not be fulfilled using a freelist slot. Check
** to see if defragmentation is necessary.
*/
testcase( gap+2+nByte==top );
if( gap+2+nByte>top ){
defragment_page:
assert( pPage->nCell>0 || CORRUPT_DB );
rc = defragmentPage(pPage);
if( rc ) return rc;
top = get2byteNotZero(&data[hdr+5]);
assert( gap+nByte<=top );
}
|
| ︙ | ︙ | |||
58879 58880 58881 58882 58883 58884 58885 | Pgno pgnoNew; /* Page number of pNew */ assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( sqlite3PagerIswriteable(pParent->pDbPage) ); assert( pPage->nOverflow==1 ); /* This error condition is now caught prior to reaching this function */ | | | 58958 58959 58960 58961 58962 58963 58964 58965 58966 58967 58968 58969 58970 58971 58972 | Pgno pgnoNew; /* Page number of pNew */ assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( sqlite3PagerIswriteable(pParent->pDbPage) ); assert( pPage->nOverflow==1 ); /* This error condition is now caught prior to reaching this function */ if( NEVER(pPage->nCell==0) ) return SQLITE_CORRUPT_BKPT; /* Allocate a new page. This page will become the right-sibling of ** pPage. Make the parent page writable, so that the new divider cell ** may be inserted. If both these operations are successful, proceed. */ rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0); |
| ︙ | ︙ | |||
59322 59323 59324 59325 59326 59327 59328 |
assert( pOld->hdrOffset==0 );
/* The right pointer of the child page pOld becomes the left
** pointer of the divider cell */
memcpy(apCell[nCell], &pOld->aData[8], 4);
}else{
assert( leafCorrection==4 );
if( szCell[nCell]<4 ){
| | > > > > | 59401 59402 59403 59404 59405 59406 59407 59408 59409 59410 59411 59412 59413 59414 59415 59416 59417 59418 59419 |
assert( pOld->hdrOffset==0 );
/* The right pointer of the child page pOld becomes the left
** pointer of the divider cell */
memcpy(apCell[nCell], &pOld->aData[8], 4);
}else{
assert( leafCorrection==4 );
if( szCell[nCell]<4 ){
/* Do not allow any cells smaller than 4 bytes. If a smaller cell
** does exist, pad it with 0x00 bytes. */
assert( szCell[nCell]==3 );
assert( apCell[nCell]==&pTemp[iSpace1-3] );
pTemp[iSpace1++] = 0x00;
szCell[nCell] = 4;
}
}
nCell++;
}
}
|
| ︙ | ︙ | |||
59557 59558 59559 59560 59561 59562 59563 |
/* Cell pCell is destined for new sibling page pNew. Originally, it
** was either part of sibling page iOld (possibly an overflow cell),
** or else the divider cell to the left of sibling page iOld. So,
** if sibling page iOld had the same page number as pNew, and if
** pCell really was a part of sibling page iOld (not a divider or
** overflow cell), we can skip updating the pointer map entries. */
| > > > | > | 59640 59641 59642 59643 59644 59645 59646 59647 59648 59649 59650 59651 59652 59653 59654 59655 59656 59657 59658 |
/* Cell pCell is destined for new sibling page pNew. Originally, it
** was either part of sibling page iOld (possibly an overflow cell),
** or else the divider cell to the left of sibling page iOld. So,
** if sibling page iOld had the same page number as pNew, and if
** pCell really was a part of sibling page iOld (not a divider or
** overflow cell), we can skip updating the pointer map entries. */
if( iOld>=nNew
|| pNew->pgno!=aPgno[iOld]
|| pCell<aOld
|| pCell>=&aOld[usableSize]
){
if( !leafCorrection ){
ptrmapPut(pBt, get4byte(pCell), PTRMAP_BTREE, pNew->pgno, &rc);
}
if( szCell[i]>pNew->minLocal ){
ptrmapPutOvflPtr(pNew, pCell, &rc);
}
}
|
| ︙ | ︙ | |||
65697 65698 65699 65700 65701 65702 65703 |
if( p->aVar ){
p->nVar = (ynVar)nVar;
for(n=0; n<nVar; n++){
p->aVar[n].flags = MEM_Null;
p->aVar[n].db = db;
}
}
| | | 65784 65785 65786 65787 65788 65789 65790 65791 65792 65793 65794 65795 65796 65797 65798 |
if( p->aVar ){
p->nVar = (ynVar)nVar;
for(n=0; n<nVar; n++){
p->aVar[n].flags = MEM_Null;
p->aVar[n].db = db;
}
}
if( p->azVar && pParse->nzVar>0 ){
p->nzVar = pParse->nzVar;
memcpy(p->azVar, pParse->azVar, p->nzVar*sizeof(p->azVar[0]));
memset(pParse->azVar, 0, pParse->nzVar*sizeof(pParse->azVar[0]));
}
if( p->aMem ){
p->aMem--; /* aMem[] goes from 1..nMem */
p->nMem = nMem; /* not from 0..nMem-1 */
|
| ︙ | ︙ | |||
75627 75628 75629 75630 75631 75632 75633 | break; } #ifndef SQLITE_OMIT_WAL /* Opcode: Checkpoint P1 P2 P3 * * ** ** Checkpoint database P1. This is a no-op if P1 is not currently in | | | > | 75714 75715 75716 75717 75718 75719 75720 75721 75722 75723 75724 75725 75726 75727 75728 75729 75730 75731 75732 75733 75734 75735 75736 75737 75738 75739 75740 75741 75742 75743 75744 75745 75746 75747 |
break;
}
#ifndef SQLITE_OMIT_WAL
/* Opcode: Checkpoint P1 P2 P3 * *
**
** Checkpoint database P1. This is a no-op if P1 is not currently in
** WAL mode. Parameter P2 is one of SQLITE_CHECKPOINT_PASSIVE, FULL,
** RESTART, or TRUNCATE. Write 1 or 0 into mem[P3] if the checkpoint returns
** SQLITE_BUSY or not, respectively. Write the number of pages in the
** WAL after the checkpoint into mem[P3+1] and the number of pages
** in the WAL that have been checkpointed after the checkpoint
** completes into mem[P3+2]. However on an error, mem[P3+1] and
** mem[P3+2] are initialized to -1.
*/
case OP_Checkpoint: {
int i; /* Loop counter */
int aRes[3]; /* Results */
Mem *pMem; /* Write results here */
assert( p->readOnly==0 );
aRes[0] = 0;
aRes[1] = aRes[2] = -1;
assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE
|| pOp->p2==SQLITE_CHECKPOINT_FULL
|| pOp->p2==SQLITE_CHECKPOINT_RESTART
|| pOp->p2==SQLITE_CHECKPOINT_TRUNCATE
);
rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &aRes[1], &aRes[2]);
if( rc==SQLITE_BUSY ){
rc = SQLITE_OK;
aRes[0] = 1;
}
for(i=0, pMem = &aMem[pOp->p3]; i<3; i++, pMem++){
|
| ︙ | ︙ | |||
80409 80410 80411 80412 80413 80414 80415 80416 80417 80418 80419 80420 80421 80422 |
break;
}
}
}
if( pMatch ){
pExpr->iTable = pMatch->iCursor;
pExpr->pTab = pMatch->pTab;
pSchema = pExpr->pTab->pSchema;
}
} /* if( pSrcList ) */
#ifndef SQLITE_OMIT_TRIGGER
/* If we have not already resolved the name, then maybe
** it is a new.* or old.* trigger argument reference
| > > > > | 80497 80498 80499 80500 80501 80502 80503 80504 80505 80506 80507 80508 80509 80510 80511 80512 80513 80514 |
break;
}
}
}
if( pMatch ){
pExpr->iTable = pMatch->iCursor;
pExpr->pTab = pMatch->pTab;
assert( (pMatch->jointype & JT_RIGHT)==0 ); /* RIGHT JOIN not (yet) supported */
if( (pMatch->jointype & JT_LEFT)!=0 ){
ExprSetProperty(pExpr, EP_CanBeNull);
}
pSchema = pExpr->pTab->pSchema;
}
} /* if( pSrcList ) */
#ifndef SQLITE_OMIT_TRIGGER
/* If we have not already resolved the name, then maybe
** it is a new.* or old.* trigger argument reference
|
| ︙ | ︙ | |||
82966 82967 82968 82969 82970 82971 82972 |
case TK_INTEGER:
case TK_STRING:
case TK_FLOAT:
case TK_BLOB:
return 0;
case TK_COLUMN:
assert( p->pTab!=0 );
| > | | 83058 83059 83060 83061 83062 83063 83064 83065 83066 83067 83068 83069 83070 83071 83072 83073 |
case TK_INTEGER:
case TK_STRING:
case TK_FLOAT:
case TK_BLOB:
return 0;
case TK_COLUMN:
assert( p->pTab!=0 );
return ExprHasProperty(p, EP_CanBeNull) ||
(p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0);
default:
return 1;
}
}
/*
** Return TRUE if the given expression is a constant which would be
|
| ︙ | ︙ | |||
88349 88350 88351 88352 88353 88354 88355 |
int i; /* Used to iterate through samples */
tRowcnt sumEq = 0; /* Sum of the nEq values */
tRowcnt avgEq = 0;
tRowcnt nRow; /* Number of rows in index */
i64 nSum100 = 0; /* Number of terms contributing to sumEq */
i64 nDist100; /* Number of distinct values in index */
| | | 88442 88443 88444 88445 88446 88447 88448 88449 88450 88451 88452 88453 88454 88455 88456 |
int i; /* Used to iterate through samples */
tRowcnt sumEq = 0; /* Sum of the nEq values */
tRowcnt avgEq = 0;
tRowcnt nRow; /* Number of rows in index */
i64 nSum100 = 0; /* Number of terms contributing to sumEq */
i64 nDist100; /* Number of distinct values in index */
if( !pIdx->aiRowEst || iCol>=pIdx->nKeyCol || pIdx->aiRowEst[iCol+1]==0 ){
nRow = pFinal->anLt[iCol];
nDist100 = (i64)100 * pFinal->anDLt[iCol];
nSample--;
}else{
nRow = pIdx->aiRowEst[0];
nDist100 = ((i64)100 * pIdx->aiRowEst[0]) / pIdx->aiRowEst[iCol+1];
}
|
| ︙ | ︙ | |||
103919 103920 103921 103922 103923 103924 103925 |
}
}
break;
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
#ifndef SQLITE_OMIT_WAL
/*
| | > > | 104012 104013 104014 104015 104016 104017 104018 104019 104020 104021 104022 104023 104024 104025 104026 104027 104028 104029 104030 104031 104032 104033 104034 104035 104036 104037 104038 104039 |
}
}
break;
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
#ifndef SQLITE_OMIT_WAL
/*
** PRAGMA [database.]wal_checkpoint = passive|full|restart|truncate
**
** Checkpoint the database.
*/
case PragTyp_WAL_CHECKPOINT: {
int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED);
int eMode = SQLITE_CHECKPOINT_PASSIVE;
if( zRight ){
if( sqlite3StrICmp(zRight, "full")==0 ){
eMode = SQLITE_CHECKPOINT_FULL;
}else if( sqlite3StrICmp(zRight, "restart")==0 ){
eMode = SQLITE_CHECKPOINT_RESTART;
}else if( sqlite3StrICmp(zRight, "truncate")==0 ){
eMode = SQLITE_CHECKPOINT_TRUNCATE;
}
}
sqlite3VdbeSetNumCols(v, 3);
pParse->nMem = 3;
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "busy", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "log", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "checkpointed", SQLITE_STATIC);
|
| ︙ | ︙ | |||
109838 109839 109840 109841 109842 109843 109844 | ** if the select-list is the same as the ORDER BY list, then this query ** can be rewritten as a GROUP BY. In other words, this: ** ** SELECT DISTINCT xyz FROM ... ORDER BY xyz ** ** is transformed to: ** | | < | 109933 109934 109935 109936 109937 109938 109939 109940 109941 109942 109943 109944 109945 109946 109947 109948 109949 109950 109951 109952 109953 109954 109955 109956 109957 109958 109959 |
** if the select-list is the same as the ORDER BY list, then this query
** can be rewritten as a GROUP BY. In other words, this:
**
** SELECT DISTINCT xyz FROM ... ORDER BY xyz
**
** is transformed to:
**
** SELECT xyz FROM ... GROUP BY xyz ORDER BY xyz
**
** The second form is preferred as a single index (or temp-table) may be
** used for both the ORDER BY and DISTINCT processing. As originally
** written the query must use a temp-table for at least one of the ORDER
** BY and DISTINCT, and an index or separate temp-table for the other.
*/
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
&& sqlite3ExprListCompare(sSort.pOrderBy, p->pEList, -1)==0
){
p->selFlags &= ~SF_Distinct;
p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
pGroupBy = p->pGroupBy;
/* Notice that even thought SF_Distinct has been cleared from p->selFlags,
** the sDistinct.isTnct is still set. Hence, isTnct represents the
** original setting of the SF_Distinct flag, not the current setting */
assert( sDistinct.isTnct );
}
/* If there is an ORDER BY clause, then this sorting
|
| ︙ | ︙ | |||
114806 114807 114808 114809 114810 114811 114812 114813 114814 114815 114816 114817 114818 114819 |
return 0;
}
memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm);
if( pOld!=pWC->aStatic ){
sqlite3DbFree(db, pOld);
}
pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
}
pTerm = &pWC->a[idx = pWC->nTerm++];
if( p && ExprHasProperty(p, EP_Unlikely) ){
pTerm->truthProb = sqlite3LogEst(p->iTable) - 270;
}else{
pTerm->truthProb = 1;
}
| > | 114900 114901 114902 114903 114904 114905 114906 114907 114908 114909 114910 114911 114912 114913 114914 |
return 0;
}
memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm);
if( pOld!=pWC->aStatic ){
sqlite3DbFree(db, pOld);
}
pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
memset(&pWC->a[pWC->nTerm], 0, sizeof(pWC->a[0])*(pWC->nSlot-pWC->nTerm));
}
pTerm = &pWC->a[idx = pWC->nTerm++];
if( p && ExprHasProperty(p, EP_Unlikely) ){
pTerm->truthProb = sqlite3LogEst(p->iTable) - 270;
}else{
pTerm->truthProb = 1;
}
|
| ︙ | ︙ | |||
117531 117532 117533 117534 117535 117536 117537 |
Vdbe *v, /* Vdbe to add scanstatus entry to */
SrcList *pSrclist, /* FROM clause pLvl reads data from */
WhereLevel *pLvl, /* Level to add scanstatus() entry for */
int addrExplain /* Address of OP_Explain (or 0) */
){
const char *zObj = 0;
WhereLoop *pLoop = pLvl->pWLoop;
| | | 117626 117627 117628 117629 117630 117631 117632 117633 117634 117635 117636 117637 117638 117639 117640 |
Vdbe *v, /* Vdbe to add scanstatus entry to */
SrcList *pSrclist, /* FROM clause pLvl reads data from */
WhereLevel *pLvl, /* Level to add scanstatus() entry for */
int addrExplain /* Address of OP_Explain (or 0) */
){
const char *zObj = 0;
WhereLoop *pLoop = pLvl->pWLoop;
if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 && pLoop->u.btree.pIndex!=0 ){
zObj = pLoop->u.btree.pIndex->zName;
}else{
zObj = pSrclist->a[pLvl->iFrom].zName;
}
sqlite3VdbeScanStatus(
v, addrExplain, pLvl->addrBody, pLvl->addrVisit, pLoop->nOut, zObj
);
|
| ︙ | ︙ | |||
118175 118176 118177 118178 118179 118180 118181 |
*/
if( pWC->nTerm>1 ){
int iTerm;
for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
Expr *pExpr = pWC->a[iTerm].pExpr;
if( &pWC->a[iTerm] == pTerm ) continue;
if( ExprHasProperty(pExpr, EP_FromJoin) ) continue;
| < | < > | 118270 118271 118272 118273 118274 118275 118276 118277 118278 118279 118280 118281 118282 118283 118284 118285 118286 |
*/
if( pWC->nTerm>1 ){
int iTerm;
for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
Expr *pExpr = pWC->a[iTerm].pExpr;
if( &pWC->a[iTerm] == pTerm ) continue;
if( ExprHasProperty(pExpr, EP_FromJoin) ) continue;
if( (pWC->a[iTerm].wtFlags & TERM_VIRTUAL)!=0 ) continue;
if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO );
pExpr = sqlite3ExprDup(db, pExpr, 0);
pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr);
}
if( pAndExpr ){
pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0);
}
}
|
| ︙ | ︙ | |||
127077 127078 127079 127080 127081 127082 127083 127084 127085 127086 127087 127088 127089 127090 |
/* Free any outstanding Savepoint structures. */
sqlite3CloseSavepoints(db);
/* Close all database connections */
for(j=0; j<db->nDb; j++){
struct Db *pDb = &db->aDb[j];
if( pDb->pBt ){
sqlite3BtreeClose(pDb->pBt);
pDb->pBt = 0;
if( j!=1 ){
pDb->pSchema = 0;
}
}
}
| > > > > > > > > | 127171 127172 127173 127174 127175 127176 127177 127178 127179 127180 127181 127182 127183 127184 127185 127186 127187 127188 127189 127190 127191 127192 |
/* Free any outstanding Savepoint structures. */
sqlite3CloseSavepoints(db);
/* Close all database connections */
for(j=0; j<db->nDb; j++){
struct Db *pDb = &db->aDb[j];
if( pDb->pBt ){
if( pDb->pSchema ){
/* Must clear the KeyInfo cache. See ticket [e4a18565a36884b00edf] */
for(i=sqliteHashFirst(&pDb->pSchema->idxHash); i; i=sqliteHashNext(i)){
Index *pIdx = sqliteHashData(i);
sqlite3KeyInfoUnref(pIdx->pKeyInfo);
pIdx->pKeyInfo = 0;
}
}
sqlite3BtreeClose(pDb->pBt);
pDb->pBt = 0;
if( j!=1 ){
pDb->pSchema = 0;
}
}
}
|
| ︙ | ︙ | |||
127981 127982 127983 127984 127985 127986 127987 | if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif /* Initialize the output variables to -1 in case an error occurs. */ if( pnLog ) *pnLog = -1; if( pnCkpt ) *pnCkpt = -1; | | | | > | > > | 128083 128084 128085 128086 128087 128088 128089 128090 128091 128092 128093 128094 128095 128096 128097 128098 128099 128100 128101 128102 128103 |
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif
/* Initialize the output variables to -1 in case an error occurs. */
if( pnLog ) *pnLog = -1;
if( pnCkpt ) *pnCkpt = -1;
assert( SQLITE_CHECKPOINT_PASSIVE==0 );
assert( SQLITE_CHECKPOINT_FULL==1 );
assert( SQLITE_CHECKPOINT_RESTART==2 );
assert( SQLITE_CHECKPOINT_TRUNCATE==3 );
if( eMode<SQLITE_CHECKPOINT_PASSIVE || eMode>SQLITE_CHECKPOINT_TRUNCATE ){
/* EVIDENCE-OF: R-03996-12088 The M parameter must be a valid checkpoint
** mode: */
return SQLITE_MISUSE;
}
sqlite3_mutex_enter(db->mutex);
if( zDb && zDb[0] ){
iDb = sqlite3FindDbName(db, zDb);
}
|
| ︙ | ︙ | |||
128012 128013 128014 128015 128016 128017 128018 |
/*
** Checkpoint database zDb. If zDb is NULL, or if the buffer zDb points
** to contains a zero-length string, all attached databases are
** checkpointed.
*/
SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){
| > > | | 128117 128118 128119 128120 128121 128122 128123 128124 128125 128126 128127 128128 128129 128130 128131 128132 128133 |
/*
** Checkpoint database zDb. If zDb is NULL, or if the buffer zDb points
** to contains a zero-length string, all attached databases are
** checkpointed.
*/
SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){
/* EVIDENCE-OF: R-41613-20553 The sqlite3_wal_checkpoint(D,X) is equivalent to
** sqlite3_wal_checkpoint_v2(D,X,SQLITE_CHECKPOINT_PASSIVE,0,0). */
return sqlite3_wal_checkpoint_v2(db,zDb,SQLITE_CHECKPOINT_PASSIVE,0,0);
}
#ifndef SQLITE_OMIT_WAL
/*
** Run a checkpoint on database iDb. This is a no-op if database iDb is
** not currently open in WAL mode.
**
|
| ︙ | ︙ | |||
139162 139163 139164 139165 139166 139167 139168 | ** of m for the first i bytes of a word. ** ** Return true if the m-value for z is 1 or more. In other words, ** return true if z contains at least one vowel that is followed ** by a consonant. ** ** In this routine z[] is in reverse order. So we are really looking | | | 139269 139270 139271 139272 139273 139274 139275 139276 139277 139278 139279 139280 139281 139282 139283 |
** of m for the first i bytes of a word.
**
** Return true if the m-value for z is 1 or more. In other words,
** return true if z contains at least one vowel that is followed
** by a consonant.
**
** In this routine z[] is in reverse order. So we are really looking
** for an instance of a consonant followed by a vowel.
*/
static int m_gt_0(const char *z){
while( isVowel(z) ){ z++; }
if( *z==0 ) return 0;
while( isConsonant(z) ){ z++; }
return *z!=0;
}
|
| ︙ | ︙ |
Changes to src/sqlite3.h.
| ︙ | ︙ | |||
105 106 107 108 109 110 111 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.8.8" #define SQLITE_VERSION_NUMBER 3008008 | | | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.8.8" #define SQLITE_VERSION_NUMBER 3008008 #define SQLITE_SOURCE_ID "2014-12-06 14:56:49 6aeece19a235344be2537e66a3fe08b1febfb5a0" /* ** 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 |
| ︙ | ︙ | |||
1217 1218 1219 1220 1221 1222 1223 | ** <li> SQLITE_SHM_LOCK | SQLITE_SHM_SHARED ** <li> SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE ** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED ** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE ** </ul> ** ** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as | | | 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 | ** <li> SQLITE_SHM_LOCK | SQLITE_SHM_SHARED ** <li> SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE ** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED ** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE ** </ul> ** ** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as ** was given on the corresponding lock. ** ** The xShmLock method can transition between unlocked and SHARED or ** between unlocked and EXCLUSIVE. It cannot transition between SHARED ** and EXCLUSIVE. */ #define SQLITE_SHM_UNLOCK 1 #define SQLITE_SHM_LOCK 2 |
| ︙ | ︙ | |||
1520 1521 1522 1523 1524 1525 1526 | ** This option can be used to overload the default memory allocation ** routines with a wrapper that simulations memory allocation failure or ** tracks memory usage, for example. </dd> ** ** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt> ** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int, ** interpreted as a boolean, which enables or disables the collection of | | | | 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 | ** This option can be used to overload the default memory allocation ** routines with a wrapper that simulations memory allocation failure or ** tracks memory usage, for example. </dd> ** ** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt> ** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int, ** interpreted as a boolean, which enables or disables the collection of ** memory allocation statistics. ^(When memory allocation statistics are ** disabled, the following SQLite interfaces become non-operational: ** <ul> ** <li> [sqlite3_memory_used()] ** <li> [sqlite3_memory_highwater()] ** <li> [sqlite3_soft_heap_limit64()] ** <li> [sqlite3_status()] ** </ul>)^ ** ^Memory allocation statistics are enabled by default unless SQLite is |
| ︙ | ︙ | |||
1562 1563 1564 1565 1566 1567 1568 | ** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt> ** <dd> ^The SQLITE_CONFIG_PAGECACHE option specifies a static memory buffer ** that SQLite can use for the database page cache with the default page ** cache implementation. ** This configuration should not be used if an application-define page ** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2] ** configuration option. | | > | > | | | | 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 | ** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt> ** <dd> ^The SQLITE_CONFIG_PAGECACHE option specifies a static memory buffer ** that SQLite can use for the database page cache with the default page ** cache implementation. ** This configuration should not be used if an application-define page ** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2] ** configuration option. ** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to ** 8-byte aligned ** memory, the size of each page buffer (sz), and the number of pages (N). ** The sz argument should be the size of the largest database page ** (a power of two between 512 and 32768) plus some extra bytes for each ** page header. ^The number of extra bytes needed by the page header ** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option ** to [sqlite3_config()]. ** ^It is harmless, apart from the wasted memory, ** for the sz parameter to be larger than necessary. The first ** argument should pointer to an 8-byte aligned block of memory that ** is at least sz*N bytes of memory, otherwise subsequent behavior is ** undefined. ** ^SQLite will use the memory provided by the first argument to satisfy its ** memory needs for the first N pages that it adds to cache. ^If additional ** page cache memory is needed beyond what is provided by this option, then ** SQLite goes to [sqlite3_malloc()] for the additional storage space.</dd> ** ** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt> ** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer ** that SQLite will use for all of its dynamic memory allocation needs ** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and ** [SQLITE_CONFIG_PAGECACHE]. ** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled ** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns ** [SQLITE_ERROR] if invoked otherwise. ** ^There are three arguments to SQLITE_CONFIG_HEAP: ** An 8-byte aligned pointer to the memory, ** the number of bytes in the memory buffer, and the minimum allocation size. ** ^If the first pointer (the memory pointer) is NULL, then SQLite reverts ** to using its default memory allocator (the system malloc() implementation), ** undoing any prior invocation of [SQLITE_CONFIG_MALLOC]. ^If the ** memory pointer is not NULL then the alternative memory ** allocator is engaged to handle all of SQLites memory allocation needs. ** The first pointer (the memory pointer) must be aligned to an 8-byte ** boundary or subsequent behavior of SQLite will be undefined. ** The minimum allocation size is capped at 2**12. Reasonable values ** for the minimum allocation size are 2**5 through 2**8.</dd> ** ** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt> ** <dd> ^(The SQLITE_CONFIG_MUTEX option takes a single argument which is a ** pointer to an instance of the [sqlite3_mutex_methods] structure. ** The argument specifies alternative low-level mutex routines to be used ** in place the mutex routines built into SQLite.)^ ^SQLite makes a copy of ** the content of the [sqlite3_mutex_methods] structure before the call to ** [sqlite3_config()] returns. ^If SQLite is compiled with ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then ** the entire mutexing subsystem is omitted from the build and hence calls to ** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will ** return [SQLITE_ERROR].</dd> ** ** [[SQLITE_CONFIG_GETMUTEX]] <dt>SQLITE_CONFIG_GETMUTEX</dt> |
| ︙ | ︙ | |||
1642 1643 1644 1645 1646 1647 1648 | ** <dd> ^(The SQLITE_CONFIG_PCACHE2 option takes a single argument which is ** a pointer to an [sqlite3_pcache_methods2] object. This object specifies ** the interface to a custom page cache implementation.)^ ** ^SQLite makes a copy of the [sqlite3_pcache_methods2] object.</dd> ** ** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt> ** <dd> ^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which | | | | 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 | ** <dd> ^(The SQLITE_CONFIG_PCACHE2 option takes a single argument which is ** a pointer to an [sqlite3_pcache_methods2] object. This object specifies ** the interface to a custom page cache implementation.)^ ** ^SQLite makes a copy of the [sqlite3_pcache_methods2] object.</dd> ** ** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt> ** <dd> ^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which ** 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(*)(void*,int,const char*), ** and a pointer to void. ^If the function pointer is not NULL, it is |
| ︙ | ︙ | |||
1668 1669 1670 1671 1672 1673 1674 | ** supplied by the application must not invoke any SQLite interface. ** In a multi-threaded application, the application-defined logger ** function must be threadsafe. </dd> ** ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI ** <dd>^(The SQLITE_CONFIG_URI option takes a single argument of type int. ** If non-zero, then URI handling is globally enabled. If the parameter is zero, | | | > | 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 | ** supplied by the application must not invoke any SQLite interface. ** In a multi-threaded application, the application-defined logger ** function must be threadsafe. </dd> ** ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI ** <dd>^(The SQLITE_CONFIG_URI option takes a single argument of type int. ** If non-zero, then URI handling is globally enabled. If the parameter is zero, ** then URI handling is globally disabled.)^ ^If URI handling is globally ** enabled, all filenames passed to [sqlite3_open()], [sqlite3_open_v2()], ** [sqlite3_open16()] or ** specified as part of [ATTACH] commands are interpreted as URIs, regardless ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database ** connection is opened. ^If it is globally disabled, filenames are ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the ** database connection is opened. ^(By default, URI handling is globally ** disabled. The default value may be changed by compiling with the ** [SQLITE_USE_URI] symbol defined.)^ |
| ︙ | ︙ | |||
1731 1732 1733 1734 1735 1736 1737 | ** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^ ** ^If either argument to this option is negative, then that argument is ** changed to its compile-time default. ** ** [[SQLITE_CONFIG_WIN32_HEAPSIZE]] ** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE ** <dd>^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is | | | | | | 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 | ** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^ ** ^If either argument to this option is negative, then that argument is ** changed to its compile-time default. ** ** [[SQLITE_CONFIG_WIN32_HEAPSIZE]] ** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE ** <dd>^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is ** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro ** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value ** that specifies the maximum size of the created heap. ** </dl> ** ** [[SQLITE_CONFIG_PCACHE_HDRSZ]] ** <dt>SQLITE_CONFIG_PCACHE_HDRSZ ** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which ** is a pointer to an integer and writes into that integer the number of extra ** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE]. ** The amount of extra space required can change depending on the compiler, ** target platform, and SQLite version. ** </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* */ |
| ︙ | ︙ | |||
2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 | ** UTF-16 string in native byte order. */ SQLITE_API int sqlite3_complete(const char *sql); SQLITE_API int sqlite3_complete16(const void *sql); /* ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors ** ** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X ** that might be invoked with argument P whenever ** an attempt is made to access a database table associated with ** [database connection] D when another thread ** or process has the table locked. ** The sqlite3_busy_handler() interface is used to implement ** [sqlite3_busy_timeout()] and [PRAGMA busy_timeout]. ** ** ^If the busy callback is NULL, then [SQLITE_BUSY] ** is returned immediately upon encountering the lock. ^If the busy callback ** is not NULL, then the callback might be invoked with two arguments. ** ** ^The first argument to the busy handler is a copy of the void* pointer which ** is the third argument to sqlite3_busy_handler(). ^The second argument to ** the busy handler callback is the number of times that the busy handler has | > | | 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 |
** UTF-16 string in native byte order.
*/
SQLITE_API int sqlite3_complete(const char *sql);
SQLITE_API int sqlite3_complete16(const void *sql);
/*
** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
** KEYWORDS: {busy-handler callback} {busy handler}
**
** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X
** that might be invoked with argument P whenever
** an attempt is made to access a database table associated with
** [database connection] D when another thread
** or process has the table locked.
** The sqlite3_busy_handler() interface is used to implement
** [sqlite3_busy_timeout()] and [PRAGMA busy_timeout].
**
** ^If the busy callback is NULL, then [SQLITE_BUSY]
** is returned immediately upon encountering the lock. ^If the busy callback
** is not NULL, then the callback might be invoked with two arguments.
**
** ^The first argument to the busy handler is a copy of the void* pointer which
** is the third argument to sqlite3_busy_handler(). ^The second argument to
** the busy handler callback is the number of times that the busy handler has
** been invoked previously for the same locking event. ^If the
** busy callback returns 0, then no additional attempts are made to
** access the database and [SQLITE_BUSY] is returned
** to the application.
** ^If the callback returns non-zero, then another attempt
** is made to access the database and the cycle repeats.
**
** The presence of a busy handler does not guarantee that it will be invoked
|
| ︙ | ︙ | |||
4516 4517 4518 4519 4520 4521 4522 | ** 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 sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); | | > | 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 |
** 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 sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*,
sqlite3_uint64,void(*)(void*));
SQLITE_API void sqlite3_result_double(sqlite3_context*, double);
SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int);
SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int);
SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*);
SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*);
SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int);
SQLITE_API void sqlite3_result_int(sqlite3_context*, int);
|
| ︙ | ︙ | |||
7242 7243 7244 7245 7246 7247 7248 | ** for a particular application. */ SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); /* ** CAPI3REF: Checkpoint a database ** | < < < < < | | < < | > > | < < > > > > > > | > | | | | | < | | > > | | | | | | | | | > | > > > > | | > > | | | > | < < > | | | | | | | | | | | > | | | | | > > > > > > > > | > | | | | | | | > | 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 7280 7281 7282 7283 7284 7285 7286 7287 7288 7289 7290 7291 7292 7293 7294 7295 7296 7297 7298 7299 7300 7301 7302 7303 7304 7305 7306 7307 7308 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 7344 7345 7346 7347 7348 7349 7350 7351 7352 7353 7354 7355 7356 7357 7358 7359 7360 7361 7362 7363 7364 7365 7366 7367 7368 7369 7370 7371 7372 7373 7374 7375 7376 7377 7378 7379 7380 7381 7382 7383 7384 7385 7386 7387 7388 7389 7390 |
** for a particular application.
*/
SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
/*
** CAPI3REF: Checkpoint a database
**
** ^(The sqlite3_wal_checkpoint(D,X) is equivalent to
** [sqlite3_wal_checkpoint_v2](D,X,[SQLITE_CHECKPOINT_PASSIVE],0,0).)^
**
** In brief, sqlite3_wal_checkpoint(D,X) causes the content in the
** [write-ahead log] for database X on [database connection] D to be
** transferred into the database file and for the write-ahead log to
** be reset. See the [checkpointing] documentation for addition
** information.
**
** 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 sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
/*
** CAPI3REF: Checkpoint a database
**
** ^(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
** information is written back into integers pointed to by L and C.)^
** ^(The M parameter must be a valid [checkpoint mode]:)^
**
** <dl>
** <dt>SQLITE_CHECKPOINT_PASSIVE<dd>
** ^Checkpoint as many frames as possible without waiting for any database
** readers or writers to finish, then sync the database file if all frames
** in the log were checkpointed. ^The [busy-handler callback]
** is never invoked in the SQLITE_CHECKPOINT_PASSIVE mode.
** ^On the other hand, passive mode might leave the checkpoint unfinished
** if there are concurrent readers or writers.
**
** <dt>SQLITE_CHECKPOINT_FULL<dd>
** ^This mode blocks (it invokes the
** [sqlite3_busy_handler|busy-handler callback]) until there is no
** database writer and all readers are reading from the most recent database
** snapshot. ^It then checkpoints all frames in the log file and syncs the
** database file. ^This mode blocks new database writers while it is pending,
** but new database readers are allowed to continue unimpeded.
**
** <dt>SQLITE_CHECKPOINT_RESTART<dd>
** ^This mode works the same way as SQLITE_CHECKPOINT_FULL with the addition
** that after checkpointing the log file it blocks (calls the
** [busy-handler callback])
** until all readers are reading from the database file only. ^This ensures
** that the next writer will restart the log file from the beginning.
** ^Like SQLITE_CHECKPOINT_FULL, this mode blocks new
** database writer attempts while it is pending, but does not impede readers.
**
** <dt>SQLITE_CHECKPOINT_TRUNCATE<dd>
** ^This mode works the same way as SQLITE_CHECKPOINT_RESTART with the
** addition that it also truncates the log file to zero bytes just prior
** to a successful return.
** </dl>
**
** ^If pnLog is not NULL, then *pnLog is set to the total number of frames in
** the log file or to -1 if the checkpoint could not run because
** of an error or because the database is not in [WAL mode]. ^If pnCkpt is not
** NULL,then *pnCkpt is set to the total number of checkpointed frames in the
** log file (including any that were already checkpointed before the function
** was called) or to -1 if the checkpoint could not run due to an error or
** because the database is not in WAL mode. ^Note that upon successful
** completion of an SQLITE_CHECKPOINT_TRUNCATE, the log file will have been
** truncated to zero bytes and so both *pnLog and *pnCkpt will be set to zero.
**
** ^All calls obtain an exclusive "checkpoint" lock on the database file. ^If
** any other process is running a checkpoint operation at the same time, the
** lock cannot be obtained and SQLITE_BUSY is returned. ^Even if there is a
** busy-handler configured, it will not be invoked in this case.
**
** ^The SQLITE_CHECKPOINT_FULL, RESTART and TRUNCATE modes also obtain the
** exclusive "writer" lock on the database file. ^If the writer lock cannot be
** obtained immediately, and a busy-handler is configured, it is invoked and
** the writer lock retried until either the busy-handler returns 0 or the lock
** is successfully obtained. ^The busy-handler is also invoked while waiting for
** database readers as described above. ^If the busy-handler returns 0 before
** the writer lock is obtained or while waiting for database readers, the
** checkpoint operation proceeds from that point in the same way as
** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible
** without blocking any further. ^SQLITE_BUSY is returned in this case.
**
** ^If parameter zDb is NULL or points to a zero length string, then the
** specified operation is attempted on all WAL databases [attached] to
** [database connection] db. In this case the
** values written to output parameters *pnLog and *pnCkpt are undefined. ^If
** an SQLITE_BUSY error is encountered when processing one or more of the
** attached WAL databases, the operation is still attempted on any remaining
** attached databases and SQLITE_BUSY is returned at the end. ^If any other
** error occurs while processing an attached database, processing is abandoned
** and the error code is returned to the caller immediately. ^If no error
** (SQLITE_BUSY or otherwise) is encountered while processing the attached
** databases, SQLITE_OK is returned.
**
** ^If database zDb is the name of an attached database that is not in WAL
** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. ^If
** zDb is not NULL (or a zero length string) and is not the name of any
** attached database, SQLITE_ERROR is returned to the caller.
**
** ^Unless it returns SQLITE_MISUSE,
** 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 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 */
);
/*
** CAPI3REF: Checkpoint Mode Values
** KEYWORDS: {checkpoint mode}
**
** These constants define all valid values for the "checkpoint mode" passed
** as the third parameter to the [sqlite3_wal_checkpoint_v2()] interface.
** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the
** meaning of each of these checkpoint modes.
*/
#define SQLITE_CHECKPOINT_PASSIVE 0 /* Do as much as possible w/o blocking */
#define SQLITE_CHECKPOINT_FULL 1 /* Wait for writers, then checkpoint */
#define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for for readers */
#define SQLITE_CHECKPOINT_TRUNCATE 3 /* Like RESTART but also truncate WAL */
/*
** CAPI3REF: Virtual Table Interface Configuration
**
** This function may be called by either the [xConnect] or [xCreate] method
** of a [virtual table] implementation to configure
** various facets of the virtual table interface.
|
| ︙ | ︙ | |||
7451 7452 7453 7454 7455 7456 7457 | ** ** The following constants can be used for the T parameter to the ** [sqlite3_stmt_scanstatus(S,X,T,V)] interface. Each constant designates a ** different metric for sqlite3_stmt_scanstatus() to return. ** ** <dl> ** [[SQLITE_SCANSTAT_NLOOP]] <dt>SQLITE_SCANSTAT_NLOOP</dt> | | | | | | | | | | | | 7475 7476 7477 7478 7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489 7490 7491 7492 7493 7494 7495 7496 7497 7498 7499 7500 7501 7502 7503 7504 7505 7506 7507 7508 7509 7510 7511 7512 | ** ** The following constants can be used for the T parameter to the ** [sqlite3_stmt_scanstatus(S,X,T,V)] interface. Each constant designates a ** different metric for sqlite3_stmt_scanstatus() to return. ** ** <dl> ** [[SQLITE_SCANSTAT_NLOOP]] <dt>SQLITE_SCANSTAT_NLOOP</dt> ** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be ** set to the total number of times that the X-th loop has run.</dd> ** ** [[SQLITE_SCANSTAT_NVISIT]] <dt>SQLITE_SCANSTAT_NVISIT</dt> ** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be set ** to the total number of rows examined by all iterations of the X-th loop.</dd> ** ** [[SQLITE_SCANSTAT_EST]] <dt>SQLITE_SCANSTAT_EST</dt> ** <dd>^The "double" variable pointed to by the T parameter will be set to the ** query planner's estimate for the average number of rows output from each ** iteration of the X-th loop. If the query planner's estimates was accurate, ** then this value will approximate the quotient NVISIT/NLOOP and the ** product of this value for all prior loops with the same SELECTID will ** be the NLOOP value for the current loop. ** ** [[SQLITE_SCANSTAT_NAME]] <dt>SQLITE_SCANSTAT_NAME</dt> ** <dd>^The "const char *" variable pointed to by the T parameter will be set ** to a zero-terminated UTF-8 string containing the name of the index or table ** used for the X-th loop. ** ** [[SQLITE_SCANSTAT_EXPLAIN]] <dt>SQLITE_SCANSTAT_EXPLAIN</dt> ** <dd>^The "const char *" variable pointed to by the T parameter will be set ** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] ** description for the X-th loop. ** ** [[SQLITE_SCANSTAT_SELECTID]] <dt>SQLITE_SCANSTAT_SELECT</dt> ** <dd>^The "int" variable pointed to by the T parameter will be set to the ** "select-id" for the X-th loop. The select-id identifies which query or ** subquery the loop is part of. The main query has a select-id of zero. ** The select-id is the same value as is output in the first column ** of an [EXPLAIN QUERY PLAN] query. |
| ︙ | ︙ | |||
7497 7498 7499 7500 7501 7502 7503 | /* ** CAPI3REF: Prepared Statement Scan Status ** ** Return status data for a single loop within query pStmt. ** ** The "iScanStatusOp" parameter determines which status information to return. | | | | 7521 7522 7523 7524 7525 7526 7527 7528 7529 7530 7531 7532 7533 7534 7535 7536 | /* ** CAPI3REF: Prepared Statement Scan Status ** ** Return status data for a single loop within query pStmt. ** ** The "iScanStatusOp" parameter determines which status information to return. ** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior ** of this interface is undefined. ** ^The requested measurement is written into a variable pointed to by ** the "pOut" parameter. ** Parameter "idx" identifies the specific loop to retrieve statistics for. ** Loops are numbered starting from zero. ^If idx is out of range - less than ** zero or greater than or equal to the total number of loops used to implement ** the statement - a non-zero value is returned and the variable that pOut ** points to is unchanged. |
| ︙ | ︙ |
Changes to src/style.c.
| ︙ | ︙ | |||
1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 |
{ "#usetupEditCapability",
"format for capabilities string, mentioned on the user edit page",
@ font-weight: bold;
},
{ "#canvas", "timeline graph node colors",
@ color: black;
@ background-color: white;
},
{ 0,
0,
0
}
};
| > > > > > > > > > > | 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 |
{ "#usetupEditCapability",
"format for capabilities string, mentioned on the user edit page",
@ font-weight: bold;
},
{ "#canvas", "timeline graph node colors",
@ color: black;
@ background-color: white;
},
{ "table.adminLogTable",
"Class for the /admin_log table",
@ text-align: left
},
{ ".adminLogTable .adminTime",
"Class for the /admin_log table",
@ text-align: left
@ vertical-align: top;
@ white-space: nowrap;
},
{ 0,
0,
0
}
};
|
| ︙ | ︙ |
Changes to src/timeline.c.
| ︙ | ︙ | |||
18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
** This file contains code to implement the timeline web page
**
*/
#include "config.h"
#include <string.h>
#include <time.h>
#include "timeline.h"
/*
** Generate a hyperlink to a version.
*/
void hyperlink_to_uuid(const char *zUuid){
if( g.perm.Hyperlink ){
@ %z(xhref("class='timelineHistLink'","%R/info/%s",zUuid))[%S(zUuid)]</a>
| > > > > > > > > > > | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
** This file contains code to implement the timeline web page
**
*/
#include "config.h"
#include <string.h>
#include <time.h>
#include "timeline.h"
/*
** Add an appropriate tag to the output if "rid" is unpublished (private)
*/
#define UNPUB_TAG "<em>(unpublished)</em>"
void tag_private_status(int rid){
if( content_is_private(rid) ){
cgi_printf("%s", UNPUB_TAG);
}
}
/*
** Generate a hyperlink to a version.
*/
void hyperlink_to_uuid(const char *zUuid){
if( g.perm.Hyperlink ){
@ %z(xhref("class='timelineHistLink'","%R/info/%s",zUuid))[%S(zUuid)]</a>
|
| ︙ | ︙ | |||
454 455 456 457 458 459 460 |
}
@ tags: %s(blob_str(&links)))
blob_reset(&links);
}else{
@ tags: %h(zTagList))
}
}
| | | | > > > > > | | | | | 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 |
}
@ tags: %s(blob_str(&links)))
blob_reset(&links);
}else{
@ tags: %h(zTagList))
}
}
tag_private_status(rid);
/* Generate extra hyperlinks at the end of the comment */
if( xExtra ){
xExtra(rid);
}
/* Generate the file-change list if requested */
if( (tmFlags & (TIMELINE_FCHANGES|TIMELINE_FRENAMES))!=0
&& zType[0]=='c' && g.perm.Hyperlink
){
int inUl = 0;
if( !fchngQueryInit ){
db_prepare(&fchngQuery,
"SELECT (pid==0) AS isnew,"
" fid,"
" (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name,"
" (SELECT uuid FROM blob WHERE rid=fid),"
" (SELECT uuid FROM blob WHERE rid=pid),"
" (SELECT name FROM filename WHERE fnid=mlink.pfnid) AS oldnm"
" FROM mlink"
" WHERE mid=:mid AND (pid!=fid OR pfnid>0)"
" AND (fid>0 OR"
" fnid NOT IN (SELECT pfnid FROM mlink WHERE mid=:mid))"
" ORDER BY 3 /*sort*/"
);
fchngQueryInit = 1;
}
db_bind_int(&fchngQuery, ":mid", rid);
while( db_step(&fchngQuery)==SQLITE_ROW ){
const char *zFilename = db_column_text(&fchngQuery, 2);
int isNew = db_column_int(&fchngQuery, 0);
int fid = db_column_int(&fchngQuery, 1);
int isDel = fid==0;
const char *zOldName = db_column_text(&fchngQuery, 5);
const char *zOld = db_column_text(&fchngQuery, 4);
const char *zNew = db_column_text(&fchngQuery, 3);
const char *zUnpubTag = "";
if( !inUl ){
@ <ul class="filelist">
inUl = 1;
}
if( (tmFlags & TIMELINE_FRENAMES)!=0 ){
if( !isNew && !isDel && zOldName!=0 ){
@ <li> %h(zOldName) → %h(zFilename)
}
continue;
}
if( content_is_private(fid) ){
zUnpubTag = UNPUB_TAG;
}
if( isNew ){
@ <li> %h(zFilename) %s(zUnpubTag) (new file)
@ %z(href("%R/artifact/%s",zNew))[view]</a></li>
}else if( isDel ){
@ <li> %h(zFilename) (deleted)</li>
}else if( fossil_strcmp(zOld,zNew)==0 && zOldName!=0 ){
@ <li> %h(zOldName) → %h(zFilename) %s(zUnpubTag)
@ %z(href("%R/artifact/%s",zNew))[view]</a></li>
}else{
if( zOldName!=0 ){
@ <li> %h(zOldName) → %h(zFilename) %s(zUnpubTag)
}else{
@ <li> %h(zFilename) %s(zUnpubTag)
}
@ %z(href("%R/fdiff?sbs=1&v1=%s&v2=%s",zOld,zNew))[diff]</a></li>
}
}
db_reset(&fchngQuery);
if( inUl ){
@ </ul>
|
| ︙ | ︙ | |||
1615 1616 1617 1618 1619 1620 1621 |
zBrType = "*BRANCH* ";
}
sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], zBrType);
n = strlen(zPrefix);
}
if( fossil_strcmp(zCurrentUuid,zId)==0 ){
sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], "*CURRENT* ");
| | > > > > | 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 |
zBrType = "*BRANCH* ";
}
sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], zBrType);
n = strlen(zPrefix);
}
if( fossil_strcmp(zCurrentUuid,zId)==0 ){
sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], "*CURRENT* ");
n += strlen(zPrefix+n);
}
if( content_is_private(rid) ){
sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], "*UNPUBLISHED* ");
n += strlen(zPrefix+n);
}
zFree = mprintf("[%S] %s%s", zId, zPrefix, zCom);
/* record another X lines */
nLine += comment_print(zFree, zCom, 9, width, g.comFmtFlags);
fossil_free(zFree);
if(verboseFlag){
|
| ︙ | ︙ |
Changes to win/Makefile.dmc.
| ︙ | ︙ | |||
26 27 28 29 30 31 32 | 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_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS 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 | | | | | 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 | 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_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS 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 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 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 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 skins_.c sqlcmd_.c stash_.c stat_.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)\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)\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)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$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 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 pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup sha1 shun skins sqlcmd stash stat 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 |
| ︙ | ︙ | |||
174 175 176 177 178 179 180 181 182 183 184 185 186 187 | +translate$E $** > $@ $(OBJDIR)\builtin$O : builtin_.c builtin.h $(TCC) -o$@ -c builtin_.c builtin_.c : $(SRCDIR)\builtin.c +translate$E $** > $@ $(OBJDIR)\cache$O : cache_.c cache.h $(TCC) -o$@ -c cache_.c cache_.c : $(SRCDIR)\cache.c +translate$E $** > $@ | > > > > > > | 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | +translate$E $** > $@ $(OBJDIR)\builtin$O : builtin_.c builtin.h $(TCC) -o$@ -c builtin_.c builtin_.c : $(SRCDIR)\builtin.c +translate$E $** > $@ $(OBJDIR)\bundle$O : bundle_.c bundle.h $(TCC) -o$@ -c bundle_.c bundle_.c : $(SRCDIR)\bundle.c +translate$E $** > $@ $(OBJDIR)\cache$O : cache_.c cache.h $(TCC) -o$@ -c cache_.c cache_.c : $(SRCDIR)\cache.c +translate$E $** > $@ |
| ︙ | ︙ | |||
570 571 572 573 574 575 576 577 578 579 580 581 582 583 | +translate$E $** > $@ $(OBJDIR)\printf$O : printf_.c printf.h $(TCC) -o$@ -c printf_.c printf_.c : $(SRCDIR)\printf.c +translate$E $** > $@ $(OBJDIR)\rebuild$O : rebuild_.c rebuild.h $(TCC) -o$@ -c rebuild_.c rebuild_.c : $(SRCDIR)\rebuild.c +translate$E $** > $@ | > > > > > > > > > > > > | 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 | +translate$E $** > $@ $(OBJDIR)\printf$O : printf_.c printf.h $(TCC) -o$@ -c printf_.c printf_.c : $(SRCDIR)\printf.c +translate$E $** > $@ $(OBJDIR)\publish$O : publish_.c publish.h $(TCC) -o$@ -c publish_.c publish_.c : $(SRCDIR)\publish.c +translate$E $** > $@ $(OBJDIR)\purge$O : purge_.c purge.h $(TCC) -o$@ -c purge_.c purge_.c : $(SRCDIR)\purge.c +translate$E $** > $@ $(OBJDIR)\rebuild$O : rebuild_.c rebuild.h $(TCC) -o$@ -c rebuild_.c rebuild_.c : $(SRCDIR)\rebuild.c +translate$E $** > $@ |
| ︙ | ︙ | |||
800 801 802 803 804 805 806 | $(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 | | | 818 819 820 821 822 823 824 825 826 | $(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 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 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 skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.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.
| ︙ | ︙ | |||
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX))) X64 = 1 endif endif ifndef X64 SSLCONFIG = mingw ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o else SSLCONFIG = mingw64 ZLIBCONFIG = LIBTARGETS = endif ifndef FOSSIL_ENABLE_MINIZ | > > > > > | 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX))) X64 = 1 endif endif ifndef X64 SSLCONFIG = mingw ifndef FOSSIL_ENABLE_MINIZ ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o else ZLIBCONFIG = LIBTARGETS = endif else SSLCONFIG = mingw64 ZLIBCONFIG = LIBTARGETS = endif ifndef FOSSIL_ENABLE_MINIZ |
| ︙ | ︙ | |||
350 351 352 353 354 355 356 357 358 359 360 361 362 363 | $(SRCDIR)/attach.c \ $(SRCDIR)/bag.c \ $(SRCDIR)/bisect.c \ $(SRCDIR)/blob.c \ $(SRCDIR)/branch.c \ $(SRCDIR)/browse.c \ $(SRCDIR)/builtin.c \ $(SRCDIR)/cache.c \ $(SRCDIR)/captcha.c \ $(SRCDIR)/cgi.c \ $(SRCDIR)/checkin.c \ $(SRCDIR)/checkout.c \ $(SRCDIR)/clearsign.c \ $(SRCDIR)/clone.c \ | > | 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 | $(SRCDIR)/attach.c \ $(SRCDIR)/bag.c \ $(SRCDIR)/bisect.c \ $(SRCDIR)/blob.c \ $(SRCDIR)/branch.c \ $(SRCDIR)/browse.c \ $(SRCDIR)/builtin.c \ $(SRCDIR)/bundle.c \ $(SRCDIR)/cache.c \ $(SRCDIR)/captcha.c \ $(SRCDIR)/cgi.c \ $(SRCDIR)/checkin.c \ $(SRCDIR)/checkout.c \ $(SRCDIR)/clearsign.c \ $(SRCDIR)/clone.c \ |
| ︙ | ︙ | |||
416 417 418 419 420 421 422 423 424 425 426 427 428 429 | $(SRCDIR)/moderate.c \ $(SRCDIR)/name.c \ $(SRCDIR)/path.c \ $(SRCDIR)/pivot.c \ $(SRCDIR)/popen.c \ $(SRCDIR)/pqueue.c \ $(SRCDIR)/printf.c \ $(SRCDIR)/rebuild.c \ $(SRCDIR)/regexp.c \ $(SRCDIR)/report.c \ $(SRCDIR)/rss.c \ $(SRCDIR)/schema.c \ $(SRCDIR)/search.c \ $(SRCDIR)/setup.c \ | > > | 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 | $(SRCDIR)/moderate.c \ $(SRCDIR)/name.c \ $(SRCDIR)/path.c \ $(SRCDIR)/pivot.c \ $(SRCDIR)/popen.c \ $(SRCDIR)/pqueue.c \ $(SRCDIR)/printf.c \ $(SRCDIR)/publish.c \ $(SRCDIR)/purge.c \ $(SRCDIR)/rebuild.c \ $(SRCDIR)/regexp.c \ $(SRCDIR)/report.c \ $(SRCDIR)/rss.c \ $(SRCDIR)/schema.c \ $(SRCDIR)/search.c \ $(SRCDIR)/setup.c \ |
| ︙ | ︙ | |||
468 469 470 471 472 473 474 475 476 477 478 479 480 481 | $(OBJDIR)/attach_.c \ $(OBJDIR)/bag_.c \ $(OBJDIR)/bisect_.c \ $(OBJDIR)/blob_.c \ $(OBJDIR)/branch_.c \ $(OBJDIR)/browse_.c \ $(OBJDIR)/builtin_.c \ $(OBJDIR)/cache_.c \ $(OBJDIR)/captcha_.c \ $(OBJDIR)/cgi_.c \ $(OBJDIR)/checkin_.c \ $(OBJDIR)/checkout_.c \ $(OBJDIR)/clearsign_.c \ $(OBJDIR)/clone_.c \ | > | 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 | $(OBJDIR)/attach_.c \ $(OBJDIR)/bag_.c \ $(OBJDIR)/bisect_.c \ $(OBJDIR)/blob_.c \ $(OBJDIR)/branch_.c \ $(OBJDIR)/browse_.c \ $(OBJDIR)/builtin_.c \ $(OBJDIR)/bundle_.c \ $(OBJDIR)/cache_.c \ $(OBJDIR)/captcha_.c \ $(OBJDIR)/cgi_.c \ $(OBJDIR)/checkin_.c \ $(OBJDIR)/checkout_.c \ $(OBJDIR)/clearsign_.c \ $(OBJDIR)/clone_.c \ |
| ︙ | ︙ | |||
534 535 536 537 538 539 540 541 542 543 544 545 546 547 | $(OBJDIR)/moderate_.c \ $(OBJDIR)/name_.c \ $(OBJDIR)/path_.c \ $(OBJDIR)/pivot_.c \ $(OBJDIR)/popen_.c \ $(OBJDIR)/pqueue_.c \ $(OBJDIR)/printf_.c \ $(OBJDIR)/rebuild_.c \ $(OBJDIR)/regexp_.c \ $(OBJDIR)/report_.c \ $(OBJDIR)/rss_.c \ $(OBJDIR)/schema_.c \ $(OBJDIR)/search_.c \ $(OBJDIR)/setup_.c \ | > > | 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 | $(OBJDIR)/moderate_.c \ $(OBJDIR)/name_.c \ $(OBJDIR)/path_.c \ $(OBJDIR)/pivot_.c \ $(OBJDIR)/popen_.c \ $(OBJDIR)/pqueue_.c \ $(OBJDIR)/printf_.c \ $(OBJDIR)/publish_.c \ $(OBJDIR)/purge_.c \ $(OBJDIR)/rebuild_.c \ $(OBJDIR)/regexp_.c \ $(OBJDIR)/report_.c \ $(OBJDIR)/rss_.c \ $(OBJDIR)/schema_.c \ $(OBJDIR)/search_.c \ $(OBJDIR)/setup_.c \ |
| ︙ | ︙ | |||
583 584 585 586 587 588 589 590 591 592 593 594 595 596 | $(OBJDIR)/attach.o \ $(OBJDIR)/bag.o \ $(OBJDIR)/bisect.o \ $(OBJDIR)/blob.o \ $(OBJDIR)/branch.o \ $(OBJDIR)/browse.o \ $(OBJDIR)/builtin.o \ $(OBJDIR)/cache.o \ $(OBJDIR)/captcha.o \ $(OBJDIR)/cgi.o \ $(OBJDIR)/checkin.o \ $(OBJDIR)/checkout.o \ $(OBJDIR)/clearsign.o \ $(OBJDIR)/clone.o \ | > | 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 | $(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 \ |
| ︙ | ︙ | |||
649 650 651 652 653 654 655 656 657 658 659 660 661 662 | $(OBJDIR)/moderate.o \ $(OBJDIR)/name.o \ $(OBJDIR)/path.o \ $(OBJDIR)/pivot.o \ $(OBJDIR)/popen.o \ $(OBJDIR)/pqueue.o \ $(OBJDIR)/printf.o \ $(OBJDIR)/rebuild.o \ $(OBJDIR)/regexp.o \ $(OBJDIR)/report.o \ $(OBJDIR)/rss.o \ $(OBJDIR)/schema.o \ $(OBJDIR)/search.o \ $(OBJDIR)/setup.o \ | > > | 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 | $(OBJDIR)/moderate.o \ $(OBJDIR)/name.o \ $(OBJDIR)/path.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 \ |
| ︙ | ︙ | |||
891 892 893 894 895 896 897 898 899 900 901 902 903 904 | $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h \ $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h \ $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h \ $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h \ $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h \ $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h \ $(OBJDIR)/builtin_.c:$(OBJDIR)/builtin.h \ $(OBJDIR)/cache_.c:$(OBJDIR)/cache.h \ $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h \ $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h \ $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h \ $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h \ $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h \ $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h \ | > | 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 | $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h \ $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h \ $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h \ $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h \ $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h \ $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h \ $(OBJDIR)/builtin_.c:$(OBJDIR)/builtin.h \ $(OBJDIR)/bundle_.c:$(OBJDIR)/bundle.h \ $(OBJDIR)/cache_.c:$(OBJDIR)/cache.h \ $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h \ $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h \ $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h \ $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h \ $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h \ $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h \ |
| ︙ | ︙ | |||
957 958 959 960 961 962 963 964 965 966 967 968 969 970 | $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \ $(OBJDIR)/name_.c:$(OBJDIR)/name.h \ $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ | > > | 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 | $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \ $(OBJDIR)/name_.c:$(OBJDIR)/name.h \ $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ $(OBJDIR)/publish_.c:$(OBJDIR)/publish.h \ $(OBJDIR)/purge_.c:$(OBJDIR)/purge.h \ $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| ︙ | ︙ | |||
1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 | $(OBJDIR)/builtin_.c: $(SRCDIR)/builtin.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/builtin.c >$@ $(OBJDIR)/builtin.o: $(OBJDIR)/builtin_.c $(OBJDIR)/builtin.h $(OBJDIR)/builtin_data.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/builtin.o -c $(OBJDIR)/builtin_.c $(OBJDIR)/builtin.h: $(OBJDIR)/headers $(OBJDIR)/cache_.c: $(SRCDIR)/cache.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/cache.c >$@ $(OBJDIR)/cache.o: $(OBJDIR)/cache_.c $(OBJDIR)/cache.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/cache.o -c $(OBJDIR)/cache_.c | > > > > > > > > | 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 | $(OBJDIR)/builtin_.c: $(SRCDIR)/builtin.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/builtin.c >$@ $(OBJDIR)/builtin.o: $(OBJDIR)/builtin_.c $(OBJDIR)/builtin.h $(OBJDIR)/builtin_data.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/builtin.o -c $(OBJDIR)/builtin_.c $(OBJDIR)/builtin.h: $(OBJDIR)/headers $(OBJDIR)/bundle_.c: $(SRCDIR)/bundle.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/bundle.c >$@ $(OBJDIR)/bundle.o: $(OBJDIR)/bundle_.c $(OBJDIR)/bundle.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/bundle.o -c $(OBJDIR)/bundle_.c $(OBJDIR)/bundle.h: $(OBJDIR)/headers $(OBJDIR)/cache_.c: $(SRCDIR)/cache.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/cache.c >$@ $(OBJDIR)/cache.o: $(OBJDIR)/cache_.c $(OBJDIR)/cache.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/cache.o -c $(OBJDIR)/cache_.c |
| ︙ | ︙ | |||
1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 | $(OBJDIR)/printf_.c: $(SRCDIR)/printf.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/printf.c >$@ $(OBJDIR)/printf.o: $(OBJDIR)/printf_.c $(OBJDIR)/printf.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c $(OBJDIR)/printf.h: $(OBJDIR)/headers $(OBJDIR)/rebuild_.c: $(SRCDIR)/rebuild.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/rebuild.c >$@ $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c | > > > > > > > > > > > > > > > > | 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 | $(OBJDIR)/printf_.c: $(SRCDIR)/printf.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/printf.c >$@ $(OBJDIR)/printf.o: $(OBJDIR)/printf_.c $(OBJDIR)/printf.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c $(OBJDIR)/printf.h: $(OBJDIR)/headers $(OBJDIR)/publish_.c: $(SRCDIR)/publish.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/publish.c >$@ $(OBJDIR)/publish.o: $(OBJDIR)/publish_.c $(OBJDIR)/publish.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/publish.o -c $(OBJDIR)/publish_.c $(OBJDIR)/publish.h: $(OBJDIR)/headers $(OBJDIR)/purge_.c: $(SRCDIR)/purge.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/purge.c >$@ $(OBJDIR)/purge.o: $(OBJDIR)/purge_.c $(OBJDIR)/purge.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/purge.o -c $(OBJDIR)/purge_.c $(OBJDIR)/purge.h: $(OBJDIR)/headers $(OBJDIR)/rebuild_.c: $(SRCDIR)/rebuild.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/rebuild.c >$@ $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c |
| ︙ | ︙ |
Changes to win/Makefile.msc.
| ︙ | ︙ | |||
202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
attach_.c \
bag_.c \
bisect_.c \
blob_.c \
branch_.c \
browse_.c \
builtin_.c \
cache_.c \
captcha_.c \
cgi_.c \
checkin_.c \
checkout_.c \
clearsign_.c \
clone_.c \
| > | 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
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 \
|
| ︙ | ︙ | |||
268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
moderate_.c \
name_.c \
path_.c \
pivot_.c \
popen_.c \
pqueue_.c \
printf_.c \
rebuild_.c \
regexp_.c \
report_.c \
rss_.c \
schema_.c \
search_.c \
setup_.c \
| > > | 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 |
moderate_.c \
name_.c \
path_.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 \
|
| ︙ | ︙ | |||
318 319 320 321 322 323 324 325 326 327 328 329 330 331 |
$(OX)\attach$O \
$(OX)\bag$O \
$(OX)\bisect$O \
$(OX)\blob$O \
$(OX)\branch$O \
$(OX)\browse$O \
$(OX)\builtin$O \
$(OX)\cache$O \
$(OX)\captcha$O \
$(OX)\cgi$O \
$(OX)\checkin$O \
$(OX)\checkout$O \
$(OX)\clearsign$O \
$(OX)\clone$O \
| > | 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 |
$(OX)\attach$O \
$(OX)\bag$O \
$(OX)\bisect$O \
$(OX)\blob$O \
$(OX)\branch$O \
$(OX)\browse$O \
$(OX)\builtin$O \
$(OX)\bundle$O \
$(OX)\cache$O \
$(OX)\captcha$O \
$(OX)\cgi$O \
$(OX)\checkin$O \
$(OX)\checkout$O \
$(OX)\clearsign$O \
$(OX)\clone$O \
|
| ︙ | ︙ | |||
385 386 387 388 389 390 391 392 393 394 395 396 397 398 |
$(OX)\moderate$O \
$(OX)\name$O \
$(OX)\path$O \
$(OX)\pivot$O \
$(OX)\popen$O \
$(OX)\pqueue$O \
$(OX)\printf$O \
$(OX)\rebuild$O \
$(OX)\regexp$O \
$(OX)\report$O \
$(OX)\rss$O \
$(OX)\schema$O \
$(OX)\search$O \
$(OX)\setup$O \
| > > | 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 |
$(OX)\moderate$O \
$(OX)\name$O \
$(OX)\path$O \
$(OX)\pivot$O \
$(OX)\popen$O \
$(OX)\pqueue$O \
$(OX)\printf$O \
$(OX)\publish$O \
$(OX)\purge$O \
$(OX)\rebuild$O \
$(OX)\regexp$O \
$(OX)\report$O \
$(OX)\rss$O \
$(OX)\schema$O \
$(OX)\search$O \
$(OX)\setup$O \
|
| ︙ | ︙ | |||
488 489 490 491 492 493 494 495 496 497 498 499 500 501 | echo $(OX)\attach.obj >> $@ echo $(OX)\bag.obj >> $@ echo $(OX)\bisect.obj >> $@ echo $(OX)\blob.obj >> $@ echo $(OX)\branch.obj >> $@ echo $(OX)\browse.obj >> $@ echo $(OX)\builtin.obj >> $@ echo $(OX)\cache.obj >> $@ echo $(OX)\captcha.obj >> $@ echo $(OX)\cgi.obj >> $@ echo $(OX)\checkin.obj >> $@ echo $(OX)\checkout.obj >> $@ echo $(OX)\clearsign.obj >> $@ echo $(OX)\clone.obj >> $@ | > | 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 | echo $(OX)\attach.obj >> $@ echo $(OX)\bag.obj >> $@ echo $(OX)\bisect.obj >> $@ echo $(OX)\blob.obj >> $@ echo $(OX)\branch.obj >> $@ echo $(OX)\browse.obj >> $@ echo $(OX)\builtin.obj >> $@ echo $(OX)\bundle.obj >> $@ echo $(OX)\cache.obj >> $@ echo $(OX)\captcha.obj >> $@ echo $(OX)\cgi.obj >> $@ echo $(OX)\checkin.obj >> $@ echo $(OX)\checkout.obj >> $@ echo $(OX)\clearsign.obj >> $@ echo $(OX)\clone.obj >> $@ |
| ︙ | ︙ | |||
555 556 557 558 559 560 561 562 563 564 565 566 567 568 | echo $(OX)\moderate.obj >> $@ echo $(OX)\name.obj >> $@ echo $(OX)\path.obj >> $@ echo $(OX)\pivot.obj >> $@ echo $(OX)\popen.obj >> $@ echo $(OX)\pqueue.obj >> $@ echo $(OX)\printf.obj >> $@ echo $(OX)\rebuild.obj >> $@ echo $(OX)\regexp.obj >> $@ echo $(OX)\report.obj >> $@ echo $(OX)\rss.obj >> $@ echo $(OX)\schema.obj >> $@ echo $(OX)\search.obj >> $@ echo $(OX)\setup.obj >> $@ | > > | 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 | echo $(OX)\moderate.obj >> $@ echo $(OX)\name.obj >> $@ echo $(OX)\path.obj >> $@ echo $(OX)\pivot.obj >> $@ echo $(OX)\popen.obj >> $@ echo $(OX)\pqueue.obj >> $@ echo $(OX)\printf.obj >> $@ echo $(OX)\publish.obj >> $@ echo $(OX)\purge.obj >> $@ echo $(OX)\rebuild.obj >> $@ echo $(OX)\regexp.obj >> $@ echo $(OX)\report.obj >> $@ echo $(OX)\rss.obj >> $@ echo $(OX)\schema.obj >> $@ echo $(OX)\search.obj >> $@ echo $(OX)\setup.obj >> $@ |
| ︙ | ︙ | |||
750 751 752 753 754 755 756 757 758 759 760 761 762 763 | translate$E $** > $@ $(OX)\builtin$O : builtin_.c builtin.h $(TCC) /Fo$@ -c builtin_.c builtin_.c : $(SRCDIR)\builtin.c translate$E $** > $@ $(OX)\cache$O : cache_.c cache.h $(TCC) /Fo$@ -c cache_.c cache_.c : $(SRCDIR)\cache.c translate$E $** > $@ | > > > > > > | 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 | translate$E $** > $@ $(OX)\builtin$O : builtin_.c builtin.h $(TCC) /Fo$@ -c builtin_.c builtin_.c : $(SRCDIR)\builtin.c translate$E $** > $@ $(OX)\bundle$O : bundle_.c bundle.h $(TCC) /Fo$@ -c bundle_.c bundle_.c : $(SRCDIR)\bundle.c translate$E $** > $@ $(OX)\cache$O : cache_.c cache.h $(TCC) /Fo$@ -c cache_.c cache_.c : $(SRCDIR)\cache.c translate$E $** > $@ |
| ︙ | ︙ | |||
1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 | translate$E $** > $@ $(OX)\printf$O : printf_.c printf.h $(TCC) /Fo$@ -c printf_.c printf_.c : $(SRCDIR)\printf.c translate$E $** > $@ $(OX)\rebuild$O : rebuild_.c rebuild.h $(TCC) /Fo$@ -c rebuild_.c rebuild_.c : $(SRCDIR)\rebuild.c translate$E $** > $@ | > > > > > > > > > > > > | 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 | translate$E $** > $@ $(OX)\printf$O : printf_.c printf.h $(TCC) /Fo$@ -c printf_.c printf_.c : $(SRCDIR)\printf.c translate$E $** > $@ $(OX)\publish$O : publish_.c publish.h $(TCC) /Fo$@ -c publish_.c publish_.c : $(SRCDIR)\publish.c translate$E $** > $@ $(OX)\purge$O : purge_.c purge.h $(TCC) /Fo$@ -c purge_.c purge_.c : $(SRCDIR)\purge.c translate$E $** > $@ $(OX)\rebuild$O : rebuild_.c rebuild.h $(TCC) /Fo$@ -c rebuild_.c rebuild_.c : $(SRCDIR)\rebuild.c translate$E $** > $@ |
| ︙ | ︙ | |||
1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 | 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 \ 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 \ | > | 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 | 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 \ |
| ︙ | ︙ | |||
1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 | moderate_.c:moderate.h \ name_.c:name.h \ path_.c:path.h \ pivot_.c:pivot.h \ popen_.c:popen.h \ pqueue_.c:pqueue.h \ printf_.c:printf.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 \ | > > | 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 | moderate_.c:moderate.h \ name_.c:name.h \ path_.c:path.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 \ |
| ︙ | ︙ |
Changes to www/checkin_names.wiki.
| ︙ | ︙ | |||
113 114 115 116 117 118 119 120 121 122 123 124 125 126 | fossil info tag:deed2 </tt></blockquote> The "tag:deed2" name will refer to the most recent check-in tagged with "deed2" not to the check-in whose canonical name begins with "deed2". <h2>Timestamps</h2> A timestamp in one of the formats shown below means the most recent check-in that occurs no later than the timestamp given: * <i>YYYY-MM-DD</i> * <i>YYYY-MM-DD HH:MM</i> | > > > > > > > > > > > > > > > > > > > > > | 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 | fossil info tag:deed2 </tt></blockquote> The "tag:deed2" name will refer to the most recent check-in tagged with "deed2" not to the check-in whose canonical name begins with "deed2". <h2>Whole Branches</h2> Usually whan a branch name is specified, it means the latest checkin on that branch. But for some commands (ex: [/help/purge|purge]) a branch name on the argument means the earliest connected checkin on the branch. This seems confusing when being explained here, but it works out to be intuitive in practice. For example, the command "fossil purge XYZ" means to purge the checkin XYZ and all of its descendents. But when XYZ is in the form of a branch name, one generally wants to purge the entire branch, not just the last checkin on the branch. And so for this reason, commands like purge will interpret a branch name to be the first checkin of the branch rather than the last. If there are two or more branches with the same name, then these commands will select the first check-in of the branch that has the most recent checkin. What happens is that Fossil searches for the most recent checkin with the given tag, just as it always does. But if that tag is a branch name, it then walks back down the branch looking for the first check-in of that branch. Again, this behavior only occurs on a few commands where it make sense. <h2>Timestamps</h2> A timestamp in one of the formats shown below means the most recent check-in that occurs no later than the timestamp given: * <i>YYYY-MM-DD</i> * <i>YYYY-MM-DD HH:MM</i> |
| ︙ | ︙ |