Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Sync with trunk to get sqlite changes et al. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | ssh-shared-account |
| Files: | files | file ages | folders |
| SHA1: |
021e41014d69a67b767f494a12bbff76 |
| User & Date: | amb 2013-07-27 21:09:30.150 |
Context
|
2013-07-30
| ||
| 05:11 | Remove an obsolete comment. No changes to code. check-in: 0b643946f0 user: amb tags: ssh-shared-account | |
|
2013-07-27
| ||
| 21:09 | Sync with trunk to get sqlite changes et al. check-in: 021e41014d user: amb tags: ssh-shared-account | |
|
2013-07-26
| ||
| 15:46 | Change <td><b></b></td> to <th></th>. check-in: a60b008f1a user: joel tags: trunk | |
| 06:40 | Only setup Fossil user if URL is SSH. This is done to avoid problems when cloning a fossil that has SSH settings using into a file:// URL. check-in: 1ebba56f2a user: amb tags: ssh-shared-account | |
Changes
Changes to src/blob.c.
| ︙ | ︙ | |||
1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 |
** is either no BOM at all or an (le/be) UTF-16 BOM, a conversion to UTF-8 is
** done. If useMbcs is false and there is no BOM, the input string is assumed
** to be UTF-8 already, so no conversion is done.
*/
void blob_to_utf8_no_bom(Blob *pBlob, int useMbcs){
char *zUtf8;
int bomSize = 0;
int bomReverse = 0;
if( starts_with_utf8_bom(pBlob, &bomSize) ){
struct Blob temp;
zUtf8 = blob_str(pBlob) + bomSize;
blob_zero(&temp);
blob_append(&temp, zUtf8, -1);
blob_swap(pBlob, &temp);
blob_reset(&temp);
| > > | 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 |
** is either no BOM at all or an (le/be) UTF-16 BOM, a conversion to UTF-8 is
** done. If useMbcs is false and there is no BOM, the input string is assumed
** to be UTF-8 already, so no conversion is done.
*/
void blob_to_utf8_no_bom(Blob *pBlob, int useMbcs){
char *zUtf8;
int bomSize = 0;
#if defined(_WIN32) || defined(__CYGWIN__)
int bomReverse = 0;
#endif
if( starts_with_utf8_bom(pBlob, &bomSize) ){
struct Blob temp;
zUtf8 = blob_str(pBlob) + bomSize;
blob_zero(&temp);
blob_append(&temp, zUtf8, -1);
blob_swap(pBlob, &temp);
blob_reset(&temp);
|
| ︙ | ︙ |
Changes to src/checkin.c.
| ︙ | ︙ | |||
101 102 103 104 105 106 107 |
nErr++;
}
}
}else if( isNew ){
blob_appendf(report, "ADDED %s\n", zDisplayName);
}else if( isDeleted ){
blob_appendf(report, "DELETED %s\n", zDisplayName);
| | > | | | < | | | | 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 |
nErr++;
}
}
}else if( isNew ){
blob_appendf(report, "ADDED %s\n", zDisplayName);
}else if( isDeleted ){
blob_appendf(report, "DELETED %s\n", zDisplayName);
}else if( isChnged ){
if( isChnged==2 ){
blob_appendf(report, "UPDATED_BY_MERGE %s\n", zDisplayName);
}else if( isChnged==3 ){
blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName);
}else if( file_contains_merge_marker(zFullName) ){
blob_appendf(report, "CONFLICT %s\n", zDisplayName);
}else{
blob_appendf(report, "EDITED %s\n", zDisplayName);
}
}else if( isRenamed ){
blob_appendf(report, "RENAMED %s\n", zDisplayName);
}else{
report->nUsed -= nPrefix;
}
free(zFullName);
}
blob_reset(&rewrittenPathname);
db_finalize(&q);
db_prepare(&q, "SELECT uuid, id FROM vmerge JOIN blob ON merge=rid"
" WHERE id<=0");
while( db_step(&q)==SQLITE_ROW ){
const char *zLabel = "MERGED_WITH";
switch( db_column_int(&q, 1) ){
case -1: zLabel = "CHERRYPICK "; break;
case -2: zLabel = "BACKOUT "; break;
}
blob_append(report, zPrefix, nPrefix);
blob_appendf(report, "%s %s\n", zLabel, db_column_text(&q, 0));
}
db_finalize(&q);
if( nErr ){
fossil_fatal("aborting due to prior errors");
|
| ︙ | ︙ | |||
326 327 328 329 330 331 332 |
}else if( !file_wd_isfile_or_link(zFullName) ){
if( file_access(zFullName, 0)==0 ){
type = "NOT_A_FILE ";
}else{
type = "MISSING ";
}
}else if( chnged ){
| > > > > > > > | > | 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 |
}else if( !file_wd_isfile_or_link(zFullName) ){
if( file_access(zFullName, 0)==0 ){
type = "NOT_A_FILE ";
}else{
type = "MISSING ";
}
}else if( chnged ){
if( chnged==2 ){
type = "UPDATED_BY_MERGE ";
}else if( chnged==3 ){
type = "ADDED_BY_MERGE ";
}else if( file_contains_merge_marker(zFullName) ){
type = "CONFLICT ";
}else{
type = "EDITED ";
}
}else if( renamed ){
type = "RENAMED ";
}else{
type = "UNCHANGED ";
}
}
if( showAge ){
|
| ︙ | ︙ |
Changes to src/db.c.
| ︙ | ︙ | |||
710 711 712 713 714 715 716 717 718 719 720 721 722 723 |
** connection. An error results in process abort.
*/
LOCAL sqlite3 *db_open(const char *zDbName){
int rc;
const char *zVfs;
sqlite3 *db;
if( g.fSqlTrace ) fossil_trace("-- sqlite3_open: [%s]\n", zDbName);
zVfs = fossil_getenv("FOSSIL_VFS");
rc = sqlite3_open_v2(
zDbName, &db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
zVfs
);
| > > > | 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 |
** connection. An error results in process abort.
*/
LOCAL sqlite3 *db_open(const char *zDbName){
int rc;
const char *zVfs;
sqlite3 *db;
#if defined(__CYGWIN__)
zDbName = fossil_utf8_to_filename(zDbName);
#endif
if( g.fSqlTrace ) fossil_trace("-- sqlite3_open: [%s]\n", zDbName);
zVfs = fossil_getenv("FOSSIL_VFS");
rc = sqlite3_open_v2(
zDbName, &db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
zVfs
);
|
| ︙ | ︙ | |||
1018 1019 1020 1021 1022 1023 1024 |
}else{
#ifdef FOSSIL_ENABLE_JSON
g.json.resultCode = FSL_JSON_E_DB_NOT_VALID;
#endif
fossil_panic("not a valid repository: %s", zDbName);
}
}
| > > > > > | < | 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 |
}else{
#ifdef FOSSIL_ENABLE_JSON
g.json.resultCode = FSL_JSON_E_DB_NOT_VALID;
#endif
fossil_panic("not a valid repository: %s", zDbName);
}
}
#if defined(__CYGWIN__)
g.zRepositoryName = fossil_utf8_to_filename(zDbName);
#else
g.zRepositoryName = mprintf("%s", zDbName);
#endif
db_open_or_attach(g.zRepositoryName, "repository", 0);
g.repositoryOpen = 1;
/* Cache "allow-symlinks" option, because we'll need it on every stat call */
g.allowSymlinks = db_get_boolean("allow-symlinks", 0);
}
/*
** Flags for the db_find_and_open_repository() function.
*/
|
| ︙ | ︙ |
Changes to src/diff.c.
| ︙ | ︙ | |||
49 50 51 52 53 54 55 |
*/
#define DIFF_CANNOT_COMPUTE_BINARY \
"cannot compute difference between binary files\n"
#define DIFF_CANNOT_COMPUTE_SYMLINK \
"cannot compute difference between symlink and regular file\n"
| | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > > | 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
*/
#define DIFF_CANNOT_COMPUTE_BINARY \
"cannot compute difference between binary files\n"
#define DIFF_CANNOT_COMPUTE_SYMLINK \
"cannot compute difference between symlink and regular file\n"
#define DIFF_TOO_MANY_CHANGES \
"more than 10,000 changes\n"
/*
** Maximum length of a line in a text file, in bytes. (2**13 = 8192 bytes)
*/
#define LENGTH_MASK_SZ 13
#define LENGTH_MASK ((1<<LENGTH_MASK_SZ)-1)
#endif /* INTERFACE */
/*
** Information about each line of a file being diffed.
**
** The lower LENGTH_MASK_SZ bits of the hash (DLine.h) are the length
** of the line. If any line is longer than LENGTH_MASK characters,
** the file is considered binary.
|
| ︙ | ︙ | |||
202 203 204 205 206 207 208 | } /* Return results */ *pnLine = nLine; return a; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
}
/* Return results */
*pnLine = nLine;
return a;
}
/*
** Return true if two DLine elements are identical.
*/
static int same_dline(DLine *pA, DLine *pB){
return pA->h==pB->h && memcmp(pA->z,pB->z,pA->h & LENGTH_MASK)==0;
}
|
| ︙ | ︙ | |||
574 575 576 577 578 579 580 | int r; /* Index into R[] */ int nr; /* Number of COPY/DELETE/INSERT triples to process */ int mxr; /* Maximum value for r */ int na, nb; /* Number of lines shown from A and B */ int i, j; /* Loop counters */ int m; /* Number of lines to output */ int skip; /* Number of lines to skip */ | | | 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 | int r; /* Index into R[] */ int nr; /* Number of COPY/DELETE/INSERT triples to process */ int mxr; /* Maximum value for r */ int na, nb; /* Number of lines shown from A and B */ int i, j; /* Loop counters */ int m; /* Number of lines to output */ int skip; /* Number of lines to skip */ static int nChunk = 0; /* Number of diff chunks seen so far */ int nContext; /* Number of lines of context */ int showLn; /* Show line numbers */ int html; /* Render as HTML */ int showDivider = 0; /* True to show the divider between diff blocks */ nContext = diff_context_lines(diffFlags); showLn = (diffFlags & DIFF_LINENO)!=0; |
| ︙ | ︙ | |||
655 656 657 658 659 660 661 |
nChunk++;
if( showLn ){
if( !showDivider ){
/* Do not show a top divider */
showDivider = 1;
}else if( html ){
blob_appendf(pOut, "<span class=\"diffhr\">%.80c</span>\n", '.');
| < > | 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 |
nChunk++;
if( showLn ){
if( !showDivider ){
/* Do not show a top divider */
showDivider = 1;
}else if( html ){
blob_appendf(pOut, "<span class=\"diffhr\">%.80c</span>\n", '.');
}else{
blob_appendf(pOut, "%.80c\n", '.');
}
if( html ) blob_appendf(pOut, "<span id=\"chunk%d\"></span>", nChunk);
}else{
if( html ) blob_appendf(pOut, "<span class=\"diffln\">");
/*
* If the patch changes an empty file or results in an empty file,
* the block header must use 0,0 as position indicator and not 1,0.
* Otherwise, patch would be confused and may reject the diff.
*/
|
| ︙ | ︙ | |||
725 726 727 728 729 730 731 |
}
/*
** Status of a single output line
*/
typedef struct SbsLine SbsLine;
struct SbsLine {
| | < | > > > > > | > > > > > > > > > | > > > > > | > > > > | | | | > < < | | < | < | | | > > > < > | < | < | < | < < > | < | > | < | < < | | > > > > > > > > | < | | > > > | | > | > | | | | | | > > > | | < < > | 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 |
}
/*
** Status of a single output line
*/
typedef struct SbsLine SbsLine;
struct SbsLine {
Blob *apCols[5]; /* Array of pointers to output columns */
int width; /* Maximum width of a column in the output */
unsigned char escHtml; /* True to escape html characters */
int iStart; /* Write zStart prior to character iStart */
const char *zStart; /* A <span> tag */
int iEnd; /* Write </span> prior to character iEnd */
int iStart2; /* Write zStart2 prior to character iStart2 */
const char *zStart2; /* A <span> tag */
int iEnd2; /* Write </span> prior to character iEnd2 */
ReCompiled *pRe; /* Only colorize matching lines, if not NULL */
};
/*
** Column indices for SbsLine.apCols[]
*/
#define SBS_LNA 0 /* Left line number */
#define SBS_TXTA 1 /* Left text */
#define SBS_MKR 2 /* Middle separator column */
#define SBS_LNB 3 /* Right line number */
#define SBS_TXTB 4 /* Right text */
/*
** Append newlines to all columns.
*/
static void sbsWriteNewlines(SbsLine *p){
int i;
for( i=p->escHtml ? SBS_LNA : SBS_TXTB; i<=SBS_TXTB; i++ ){
blob_append(p->apCols[i], "\n", 1);
}
}
/*
** Append n spaces to the column.
*/
static void sbsWriteSpace(SbsLine *p, int n, int col){
blob_appendf(p->apCols[col], "%*s", n, "");
}
/*
** Write the text of pLine into column iCol of p.
**
** If outputting HTML, write the full line. Otherwise, only write the
** width characters. Translate tabs into spaces. Add newlines if col
** is SBS_TXTB. Translate HTML characters if escHtml is true. Pad the
** rendering to width bytes if col is SBS_TXTA and escHtml is false.
**
** This comment contains multibyte unicode characters (ü, Æ, ð) in order
** to test the ability of the diff code to handle such characters.
*/
static void sbsWriteText(SbsLine *p, DLine *pLine, int col){
Blob *pCol = p->apCols[col];
int n = pLine->h & LENGTH_MASK;
int i; /* Number of input characters consumed */
int k; /* Cursor position */
int needEndSpan = 0;
const char *zIn = pLine->z;
int w = p->width;
int colorize = p->escHtml;
if( colorize && p->pRe && re_dline_match(p->pRe, pLine, 1)==0 ){
colorize = 0;
}
for(i=k=0; (p->escHtml || k<w) && i<n; i++, k++){
char c = zIn[i];
if( colorize ){
if( i==p->iStart ){
int x = strlen(p->zStart);
blob_append(pCol, p->zStart, x);
needEndSpan = 1;
if( p->iStart2 ){
p->iStart = p->iStart2;
p->zStart = p->zStart2;
p->iStart2 = 0;
}
}else if( i==p->iEnd ){
blob_append(pCol, "</span>", 7);
needEndSpan = 0;
if( p->iEnd2 ){
p->iEnd = p->iEnd2;
p->iEnd2 = 0;
}
}
}
if( c=='\t' && !p->escHtml ){
blob_append(pCol, " ", 1);
while( (k&7)!=7 && (p->escHtml || k<w) ){
blob_append(pCol, " ", 1);
k++;
}
}else if( c=='\r' || c=='\f' ){
blob_append(pCol, " ", 1);
}else if( c=='<' && p->escHtml ){
blob_append(pCol, "<", 4);
}else if( c=='&' && p->escHtml ){
blob_append(pCol, "&", 5);
}else if( c=='>' && p->escHtml ){
blob_append(pCol, ">", 4);
}else if( c=='"' && p->escHtml ){
blob_append(pCol, """, 6);
}else{
blob_append(pCol, &zIn[i], 1);
if( (c&0xc0)==0x80 ) k--;
}
}
if( needEndSpan ){
blob_append(pCol, "</span>", 7);
}
if( col==SBS_TXTB ){
sbsWriteNewlines(p);
}else if( !p->escHtml ){
sbsWriteSpace(p, w-k, SBS_TXTA);
}
}
/*
** Append a column to the final output blob.
*/
static void sbsWriteColumn(Blob *pOut, Blob *pCol, int col){
blob_appendf(pOut,
"<td><div class=\"diff%scol\">\n"
"<pre>\n"
"%s"
"</pre>\n"
"</div></td>\n",
col % 3 ? (col == SBS_MKR ? "mkr" : "txt") : "ln",
blob_str(pCol)
);
}
/*
** Append a separator line to column iCol
*/
static void sbsWriteSep(SbsLine *p, int len, int col){
char ch = '.';
if( len<1 ){
len = 1;
ch = ' ';
}
blob_appendf(p->apCols[col], "<span class=\"diffhr\">%.*c</span>\n", len, ch);
}
/*
** Append the appropriate marker into the center column of the diff.
*/
static void sbsWriteMarker(SbsLine *p, const char *zTxt, const char *zHtml){
blob_append(p->apCols[SBS_MKR], p->escHtml ? zHtml : zTxt, -1);
}
/*
** Append a line number to the column.
*/
static void sbsWriteLineno(SbsLine *p, int ln, int col){
if( p->escHtml ){
blob_appendf(p->apCols[col], "%d", ln+1);
}else{
char zLn[7];
sqlite3_snprintf(7, zLn, "%5d ", ln+1);
blob_appendf(p->apCols[col], "%s ", zLn);
}
}
/*
** The two text segments zLeft and zRight are known to be different on
** both ends, but they might have a common segment in the middle. If
** they do not have a common segment, return 0. If they do have a large
** common segment, return 1 and before doing so set:
|
| ︙ | ︙ | |||
1016 1017 1018 1019 1020 1021 1022 |
if( nSuffix<nShort ){
while( nSuffix>0 && (zLeft[nLeft-nSuffix]&0xc0)==0x80 ) nSuffix--;
}
if( nSuffix==nLeft || nSuffix==nRight ) nPrefix = 0;
}
if( nPrefix+nSuffix > nShort ) nPrefix = nShort - nSuffix;
| < | | | | | | | | | | | | | | | | | | | | | | 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 |
if( nSuffix<nShort ){
while( nSuffix>0 && (zLeft[nLeft-nSuffix]&0xc0)==0x80 ) nSuffix--;
}
if( nSuffix==nLeft || nSuffix==nRight ) nPrefix = 0;
}
if( nPrefix+nSuffix > nShort ) nPrefix = nShort - nSuffix;
/* A single chunk of text inserted on the right */
if( nPrefix+nSuffix==nLeft ){
sbsWriteLineno(p, lnLeft, SBS_LNA);
p->iStart2 = p->iEnd2 = 0;
p->iStart = p->iEnd = -1;
sbsWriteText(p, pLeft, SBS_TXTA);
if( nLeft==nRight && zLeft[nLeft]==zRight[nRight] ){
sbsWriteMarker(p, " ", "");
}else{
sbsWriteMarker(p, " | ", "|");
}
sbsWriteLineno(p, lnRight, SBS_LNB);
p->iStart = nPrefix;
p->iEnd = nRight - nSuffix;
p->zStart = zClassAdd;
sbsWriteText(p, pRight, SBS_TXTB);
return;
}
/* A single chunk of text deleted from the left */
if( nPrefix+nSuffix==nRight ){
/* Text deleted from the left */
sbsWriteLineno(p, lnLeft, SBS_LNA);
p->iStart2 = p->iEnd2 = 0;
p->iStart = nPrefix;
p->iEnd = nLeft - nSuffix;
p->zStart = zClassRm;
sbsWriteText(p, pLeft, SBS_TXTA);
sbsWriteMarker(p, " | ", "|");
sbsWriteLineno(p, lnRight, SBS_LNB);
p->iStart = p->iEnd = -1;
sbsWriteText(p, pRight, SBS_TXTB);
return;
}
/* At this point we know that there is a chunk of text that has
** changed between the left and the right. Check to see if there
** is a large unchanged section in the middle of that changed block.
*/
nLeftDiff = nLeft - nSuffix - nPrefix;
nRightDiff = nRight - nSuffix - nPrefix;
if( p->escHtml
&& nLeftDiff >= 6
&& nRightDiff >= 6
&& textLCS(&zLeft[nPrefix], nLeftDiff, &zRight[nPrefix], nRightDiff, aLCS)
){
sbsWriteLineno(p, lnLeft, SBS_LNA);
p->iStart = nPrefix;
p->iEnd = nPrefix + aLCS[0];
if( aLCS[2]==0 ){
sbsShiftLeft(p, pLeft->z);
p->zStart = zClassRm;
}else{
p->zStart = zClassChng;
}
p->iStart2 = nPrefix + aLCS[1];
p->iEnd2 = nLeft - nSuffix;
p->zStart2 = aLCS[3]==nRightDiff ? zClassRm : zClassChng;
sbsSimplifyLine(p, zLeft+nPrefix);
sbsWriteText(p, pLeft, SBS_TXTA);
sbsWriteMarker(p, " | ", "|");
sbsWriteLineno(p, lnRight, SBS_LNB);
p->iStart = nPrefix;
p->iEnd = nPrefix + aLCS[2];
if( aLCS[0]==0 ){
sbsShiftLeft(p, pRight->z);
p->zStart = zClassAdd;
}else{
p->zStart = zClassChng;
}
p->iStart2 = nPrefix + aLCS[3];
p->iEnd2 = nRight - nSuffix;
p->zStart2 = aLCS[1]==nLeftDiff ? zClassAdd : zClassChng;
sbsSimplifyLine(p, zRight+nPrefix);
sbsWriteText(p, pRight, SBS_TXTB);
return;
}
/* If all else fails, show a single big change between left and right */
sbsWriteLineno(p, lnLeft, SBS_LNA);
p->iStart2 = p->iEnd2 = 0;
p->iStart = nPrefix;
p->iEnd = nLeft - nSuffix;
p->zStart = zClassChng;
sbsWriteText(p, pLeft, SBS_TXTA);
sbsWriteMarker(p, " | ", "|");
sbsWriteLineno(p, lnRight, SBS_LNB);
p->iEnd = nRight - nSuffix;
sbsWriteText(p, pRight, SBS_TXTB);
}
/*
** Minimum of two values
*/
static int minInt(int a, int b){ return a<b ? a : b; }
|
| ︙ | ︙ | |||
1355 1356 1357 1358 1359 1360 1361 | int r; /* Index into R[] */ int nr; /* Number of COPY/DELETE/INSERT triples to process */ int mxr; /* Maximum value for r */ int na, nb; /* Number of lines shown from A and B */ int i, j; /* Loop counters */ int m, ma, mb;/* Number of lines to output */ int skip; /* Number of lines to skip */ | | > < < > > > > > > > > > > > | 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 |
int r; /* Index into R[] */
int nr; /* Number of COPY/DELETE/INSERT triples to process */
int mxr; /* Maximum value for r */
int na, nb; /* Number of lines shown from A and B */
int i, j; /* Loop counters */
int m, ma, mb;/* Number of lines to output */
int skip; /* Number of lines to skip */
static int nChunk = 0; /* Number of chunks of diff output seen so far */
SbsLine s; /* Output line buffer */
int nContext; /* Lines of context above and below each change */
int showDivider = 0; /* True to show the divider */
Blob aCols[5]; /* Array of column blobs */
memset(&s, 0, sizeof(s));
s.width = diff_width(diffFlags);
nContext = diff_context_lines(diffFlags);
s.escHtml = (diffFlags & DIFF_HTML)!=0;
if( s.escHtml ){
for(i=SBS_LNA; i<=SBS_TXTB; i++){
blob_zero(&aCols[i]);
s.apCols[i] = &aCols[i];
}
}else{
for(i=SBS_LNA; i<=SBS_TXTB; i++){
s.apCols[i] = pOut;
}
}
s.pRe = pRe;
s.iStart = -1;
s.iStart2 = 0;
s.iEnd = -1;
A = p->aFrom;
B = p->aTo;
R = p->aEdit;
mxr = p->nEdit;
while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; }
for(r=0; r<mxr; r += 3*nr){
/* Figure out how many triples to show in a single block */
for(nr=1; R[r+nr*3]>0 && R[r+nr*3]<nContext*2; nr++){}
/* printf("r=%d nr=%d\n", r, nr); */
/* If there is a regex, skip this block (generate no diff output)
** if the regex matches or does not match both insert and delete.
|
| ︙ | ︙ | |||
1434 1435 1436 1437 1438 1439 1440 |
na += R[r+i*3];
nb += R[r+i*3];
}
/* Draw the separator between blocks */
if( showDivider ){
if( s.escHtml ){
| | > > | > > > > | < | | | | | < | 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 |
na += R[r+i*3];
nb += R[r+i*3];
}
/* Draw the separator between blocks */
if( showDivider ){
if( s.escHtml ){
char zLn[10];
sqlite3_snprintf(sizeof(zLn), zLn, "%d", a+skip+1);
sbsWriteSep(&s, strlen(zLn), SBS_LNA);
sbsWriteSep(&s, s.width, SBS_TXTA);
sbsWriteSep(&s, 0, SBS_MKR);
sqlite3_snprintf(sizeof(zLn), zLn, "%d", b+skip+1);
sbsWriteSep(&s, strlen(zLn), SBS_LNB);
sbsWriteSep(&s, s.width, SBS_TXTB);
}else{
blob_appendf(pOut, "%.*c\n", s.width*2+16, '.');
}
}
showDivider = 1;
nChunk++;
if( s.escHtml ){
blob_appendf(s.apCols[SBS_LNA], "<span id=\"chunk%d\"></span>", nChunk);
}
/* Show the initial common area */
a += skip;
b += skip;
m = R[r] - skip;
for(j=0; j<m; j++){
sbsWriteLineno(&s, a+j, SBS_LNA);
s.iStart = s.iEnd = -1;
sbsWriteText(&s, &A[a+j], SBS_TXTA);
sbsWriteMarker(&s, " ", "");
sbsWriteLineno(&s, b+j, SBS_LNB);
sbsWriteText(&s, &B[b+j], SBS_TXTB);
}
a += m;
b += m;
/* Show the differences */
for(i=0; i<nr; i++){
unsigned char *alignment;
|
| ︙ | ︙ | |||
1483 1484 1485 1486 1487 1488 1489 |
mb += R[r+i*3+2] + m;
}
alignment = sbsAlignment(&A[a], ma, &B[b], mb);
for(j=0; ma+mb>0; j++){
if( alignment[j]==1 ){
/* Delete one line from the left */
| < | | < | < | < < < < | | < < < < > | | < < | | | | | < < < | | | | | < < | | | | | > > > > | > > > > < | 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 |
mb += R[r+i*3+2] + m;
}
alignment = sbsAlignment(&A[a], ma, &B[b], mb);
for(j=0; ma+mb>0; j++){
if( alignment[j]==1 ){
/* Delete one line from the left */
sbsWriteLineno(&s, a, SBS_LNA);
s.iStart = 0;
s.zStart = "<span class=\"diffrm\">";
s.iEnd = LENGTH(&A[a]);
sbsWriteText(&s, &A[a], SBS_TXTA);
sbsWriteMarker(&s, " <", "<");
sbsWriteNewlines(&s);
assert( ma>0 );
ma--;
a++;
}else if( alignment[j]==3 ){
/* The left line is changed into the right line */
sbsWriteLineChange(&s, &A[a], a, &B[b], b);
assert( ma>0 && mb>0 );
ma--;
mb--;
a++;
b++;
}else if( alignment[j]==2 ){
/* Insert one line on the right */
if( !s.escHtml ){
sbsWriteSpace(&s, s.width + 7, SBS_TXTA);
}
sbsWriteMarker(&s, " > ", ">");
sbsWriteLineno(&s, b, SBS_LNB);
s.iStart = 0;
s.zStart = "<span class=\"diffadd\">";
s.iEnd = LENGTH(&B[b]);
sbsWriteText(&s, &B[b], SBS_TXTB);
assert( mb>0 );
mb--;
b++;
}else{
/* Delete from the left and insert on the right */
sbsWriteLineno(&s, a, SBS_LNA);
s.iStart = 0;
s.zStart = "<span class=\"diffrm\">";
s.iEnd = LENGTH(&A[a]);
sbsWriteText(&s, &A[a], SBS_TXTA);
sbsWriteMarker(&s, " | ", "|");
sbsWriteLineno(&s, b, SBS_LNB);
s.iStart = 0;
s.zStart = "<span class=\"diffadd\">";
s.iEnd = LENGTH(&B[b]);
sbsWriteText(&s, &B[b], SBS_TXTB);
ma--;
mb--;
a++;
b++;
}
}
fossil_free(alignment);
if( i<nr-1 ){
m = R[r+i*3+3];
for(j=0; j<m; j++){
sbsWriteLineno(&s, a+j, SBS_LNA);
s.iStart = s.iEnd = -1;
sbsWriteText(&s, &A[a+j], SBS_TXTA);
sbsWriteMarker(&s, " ", "");
sbsWriteLineno(&s, b+j, SBS_LNB);
sbsWriteText(&s, &B[b+j], SBS_TXTB);
}
b += m;
a += m;
}
}
/* Show the final common area */
assert( nr==i );
m = R[r+nr*3];
if( m>nContext ) m = nContext;
for(j=0; j<m; j++){
sbsWriteLineno(&s, a+j, SBS_LNA);
s.iStart = s.iEnd = -1;
sbsWriteText(&s, &A[a+j], SBS_TXTA);
sbsWriteMarker(&s, " ", "");
sbsWriteLineno(&s, b+j, SBS_LNB);
sbsWriteText(&s, &B[b+j], SBS_TXTB);
}
}
if( s.escHtml && blob_size(s.apCols[SBS_LNA])>0 ){
blob_append(pOut, "<table class=\"sbsdiffcols\" width=\"90%\"><tr>\n", -1);
for(i=SBS_LNA; i<=SBS_TXTB; i++){
sbsWriteColumn(pOut, s.apCols[i], i);
blob_reset(s.apCols[i]);
}
blob_append(pOut, "</tr></table>\n", -1);
}
}
/*
** Compute the optimal longest common subsequence (LCS) using an
** exhaustive search. This version of the LCS is only used for
** shorter input strings since runtime is O(N*N) where N is the
** input string length.
|
| ︙ | ︙ | |||
1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 |
** appropriate default if no width is given.
*/
int diff_width(u64 diffFlags){
int w = (diffFlags & DIFF_WIDTH_MASK)/(DIFF_CONTEXT_MASK+1);
if( w==0 ) w = 80;
return w;
}
/*
** Generate a report of the differences between files pA and pB.
** If pOut is not NULL then a unified diff is appended there. It
** is assumed that pOut has already been initialized. If pOut is
** NULL, then a pointer to an array of integers is returned.
** The integers come in triples. For each triple,
| > > > > > > > > > > > | 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 |
** appropriate default if no width is given.
*/
int diff_width(u64 diffFlags){
int w = (diffFlags & DIFF_WIDTH_MASK)/(DIFF_CONTEXT_MASK+1);
if( w==0 ) w = 80;
return w;
}
/*
** Append the error message to pOut.
*/
void diff_errmsg(Blob *pOut, const char *msg, int diffFlags){
if( diffFlags & DIFF_HTML ){
blob_appendf(pOut, "<p class=\"generalError\">%s</p>", msg);
}else{
blob_append(pOut, msg, -1);
}
}
/*
** Generate a report of the differences between files pA and pB.
** If pOut is not NULL then a unified diff is appended there. It
** is assumed that pOut has already been initialized. If pOut is
** NULL, then a pointer to an array of integers is returned.
** The integers come in triples. For each triple,
|
| ︙ | ︙ | |||
2030 2031 2032 2033 2034 2035 2036 |
&c.nFrom, ignoreEolWs);
c.aTo = break_into_lines(blob_str(pB_Blob), blob_size(pB_Blob),
&c.nTo, ignoreEolWs);
if( c.aFrom==0 || c.aTo==0 ){
fossil_free(c.aFrom);
fossil_free(c.aTo);
if( pOut ){
| | < < < | < | 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 |
&c.nFrom, ignoreEolWs);
c.aTo = break_into_lines(blob_str(pB_Blob), blob_size(pB_Blob),
&c.nTo, ignoreEolWs);
if( c.aFrom==0 || c.aTo==0 ){
fossil_free(c.aFrom);
fossil_free(c.aTo);
if( pOut ){
diff_errmsg(pOut, DIFF_CANNOT_COMPUTE_BINARY, diffFlags);
}
return 0;
}
/* Compute the difference */
diff_all(&c);
if( (diffFlags & DIFF_NOTTOOBIG)!=0 ){
int i, m, n;
int *a = c.aEdit;
int mx = c.nEdit;
for(i=m=n=0; i<mx; i+=3){ m += a[i]; n += a[i+1]+a[i+2]; }
if( n>10000 ){
fossil_free(c.aFrom);
fossil_free(c.aTo);
fossil_free(c.aEdit);
diff_errmsg(pOut, DIFF_TOO_MANY_CHANGES, diffFlags);
return 0;
}
}
if( (diffFlags & DIFF_NOOPT)==0 ){
diff_optimize(&c);
}
|
| ︙ | ︙ | |||
2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 |
ReCompiled *pRe = 0; /* Regex filter for diff output */
if( find_option("tk",0,0)!=0 ){
diff_tk("test-diff", 2);
return;
}
find_option("i",0,0);
zRe = find_option("regexp","e",1);
if( zRe ){
const char *zErr = re_compile(&pRe, zRe, 0);
if( zErr ) fossil_fatal("regex error: %s", zErr);
}
diffFlag = diff_options();
verify_all_options();
| > | 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 |
ReCompiled *pRe = 0; /* Regex filter for diff output */
if( find_option("tk",0,0)!=0 ){
diff_tk("test-diff", 2);
return;
}
find_option("i",0,0);
find_option("v",0,0);
zRe = find_option("regexp","e",1);
if( zRe ){
const char *zErr = re_compile(&pRe, zRe, 0);
if( zErr ) fossil_fatal("regex error: %s", zErr);
}
diffFlag = diff_options();
verify_all_options();
|
| ︙ | ︙ | |||
2614 2615 2616 2617 2618 2619 2620 |
fileVers ? p->zFUuid : p->zMUuid, p->zDate);
}else{
zPrefix[0] = 0;
}
fossil_print("%21s %4d: %.*s\n", zPrefix, i+1, n, z);
}
}
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 2355 2356 2357 2358 2359 2360 2361 |
fileVers ? p->zFUuid : p->zMUuid, p->zDate);
}else{
zPrefix[0] = 0;
}
fossil_print("%21s %4d: %.*s\n", zPrefix, i+1, n, z);
}
}
|
Changes to src/diffcmd.c.
| ︙ | ︙ | |||
595 596 597 598 599 600 601 |
zName = "diff-command";
}
return db_get(zName, zDefault);
}
/* A Tcl/Tk script used to render diff output.
*/
| | > | | < | | | | | | < | | | > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > | > > > > > | > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < > | | | | > > > | > > > | | 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 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 |
zName = "diff-command";
}
return db_get(zName, zDefault);
}
/* A Tcl/Tk script used to render diff output.
*/
static const char zDiffScript[] =
@ package require Tk
@
@ array set CFG {
@ TITLE {Fossil Diff}
@ LN_COL_BG #dddddd
@ LN_COL_FG #444444
@ TXT_COL_BG #ffffff
@ TXT_COL_FG #000000
@ MKR_COL_BG #444444
@ MKR_COL_FG #dddddd
@ CHNG_BG #d0d0ff
@ ADD_BG #c0ffc0
@ RM_BG #ffc0c0
@ HR_FG #888888
@ HR_PAD_TOP 4
@ HR_PAD_BTM 8
@ FN_BG #444444
@ FN_FG #ffffff
@ FN_PAD 5
@ FONTS {{DejaVu Sans Mono} Consolas Monaco}
@ FONT_SIZE 9
@ PADX 5
@ WIDTH 80
@ HEIGHT 45
@ LB_HEIGHT 25
@ }
@
@ if {![namespace exists ttk]} {
@ interp alias {} ::ttk::scrollbar {} ::scrollbar
@ interp alias {} ::ttk::menubutton {} ::menubutton
@ }
@
@ proc dehtml {x} {
@ set x [regsub -all {<[^>]*>} $x {}]
@ return [string map {& & < < > > ' ' " \"} $x]
@ }
@
@ proc cols {} {
@ return [list .lnA .txtA .mkr .lnB .txtB]
@ }
@
@ proc colType {c} {
@ regexp {[a-z]+} $c type
@ return $type
@ }
@
@ proc readDiffs {cmd} {
@ set in [open $cmd r]
@ fconfigure $in -encoding utf-8
@ set nDiffs 0
@ array set widths {txt 0 ln 0 mkr 0}
@ while {[gets $in line] != -1} {
@ if {![regexp {^=+\s+(.*?)\s+=+$} $line all fn]} {
@ continue
@ }
@ if {[string compare -length 6 [gets $in] "<table"]} {
@ continue
@ }
@ incr nDiffs
@ set idx [expr {$nDiffs > 1 ? [.txtA index end] : "1.0"}]
@ .wfiles.lb insert end $fn
@
@ foreach c [cols] {
@ while {[gets $in] ne "<pre>"} continue
@
@ if {$nDiffs > 1} {
@ $c insert end \n -
@ }
@ if {[colType $c] eq "txt"} {
@ $c insert end $fn\n fn
@ } else {
@ $c insert end \n fn
@ }
@ $c insert end \n -
@
@ set type [colType $c]
@ set str {}
@ while {[set line [gets $in]] ne "</pre>"} {
@ set len [string length [dehtml $line]]
@ if {$len > $widths($type)} {
@ set widths($type) $len
@ }
@ append str $line\n
@ }
@
@ set re {<span class="diff([a-z]+)">([^<]*)</span>}
@ # Use \r as separator since it can't appear in the diff output (it gets
@ # converted to a space).
@ set str [regsub -all $re $str "\r\\1\r\\2\r"]
@ foreach {pre class mid} [split $str \r] {
@ if {$class ne ""} {
@ $c insert end [dehtml $pre] - [dehtml $mid] [list $class -]
@ } else {
@ $c insert end [dehtml $pre] -
@ }
@ }
@ }
@ }
@ close $in
@
@ foreach c [cols] {
@ set type [colType $c]
@ if {$type ne "txt"} {
@ $c config -width $widths($type)
@ }
@ $c config -state disabled
@ }
@ if {$nDiffs <= [.wfiles.lb cget -height]} {
@ .wfiles.lb config -height $nDiffs
@ grid remove .wfiles.sb
@ }
@
@ return $nDiffs
@ }
@
@ proc viewDiff {idx} {
@ .txtA yview $idx
@ .txtA xview moveto 0
@ }
@
@ proc cycleDiffs {{reverse 0}} {
@ if {$reverse} {
@ set range [.txtA tag prevrange fn @0,0 1.0]
@ if {$range eq ""} {
@ viewDiff {fn.last -1c}
@ } else {
@ viewDiff [lindex $range 0]
@ }
@ } else {
@ set range [.txtA tag nextrange fn {@0,0 +1c} end]
@ if {$range eq "" || [lindex [.txtA yview] 1] == 1} {
@ viewDiff fn.first
@ } else {
@ viewDiff [lindex $range 0]
@ }
@ }
@ }
@
@ proc xvis {col} {
@ set view [$col xview]
@ return [expr {[lindex $view 1]-[lindex $view 0]}]
@ }
@
@ proc scroll-x {args} {
@ set c .txt[expr {[xvis .txtA] < [xvis .txtB] ? "A" : "B"}]
@ eval $c xview $args
@ }
@
@ interp alias {} scroll-y {} .txtA yview
@
@ proc noop {args} {}
@
@ proc enableSync {axis} {
@ update idletasks
@ interp alias {} sync-$axis {}
@ rename _sync-$axis sync-$axis
@ }
@
@ proc disableSync {axis} {
@ rename sync-$axis _sync-$axis
@ interp alias {} sync-$axis {} noop
@ }
@
@ proc sync-x {col first last} {
@ disableSync x
@ $col xview moveto [expr {$first*[xvis $col]/($last-$first)}]
@ foreach side {A B} {
@ set sb .sbx$side
@ set xview [.txt$side xview]
@ if {[lindex $xview 0] > 0 || [lindex $xview 1] < 1} {
@ grid $sb
@ eval $sb set $xview
@ } else {
@ grid remove $sb
@ }
@ }
@ enableSync x
@ }
@
@ proc sync-y {first last} {
@ disableSync y
@ foreach c [cols] {
@ $c yview moveto $first
@ }
@ if {$first > 0 || $last < 1} {
@ grid .sby
@ .sby set $first $last
@ } else {
@ grid remove .sby
@ }
@ enableSync y
@ }
@
@ wm withdraw .
@ wm title . $CFG(TITLE)
@ wm iconname . $CFG(TITLE)
@ bind . <q> exit
@ bind . <Tab> {cycleDiffs; break}
@ bind . <<PrevWindow>> {cycleDiffs 1; break}
@ bind . <Return> {
@ event generate .files <1>
@ event generate .files <ButtonRelease-1>
@ break
@ }
@ foreach {key axis args} {
@ Up y {scroll -5 units}
@ Down y {scroll 5 units}
@ Left x {scroll -5 units}
@ Right x {scroll 5 units}
@ Prior y {scroll -1 page}
@ Next y {scroll 1 page}
@ Home y {moveto 0}
@ End y {moveto 1}
@ } {
@ bind . <$key> "scroll-$axis $args; break"
@ bind . <Shift-$key> continue
@ }
@
@ ::ttk::menubutton .files -text "Files"
@ toplevel .wfiles
@ wm withdraw .wfiles
@ update idletasks
@ wm transient .wfiles .
@ wm overrideredirect .wfiles 1
@ listbox .wfiles.lb -width 0 -height $CFG(LB_HEIGHT) -activestyle none \
@ -yscroll {.wfiles.sb set}
@ ::ttk::scrollbar .wfiles.sb -command {.wfiles.lb yview}
@ grid .wfiles.lb .wfiles.sb -sticky ns
@ bind .files <1> {
@ set x [winfo rootx %W]
@ set y [expr {[winfo rooty %W]+[winfo height %W]}]
@ wm geometry .wfiles +$x+$y
@ wm deiconify .wfiles
@ focus .wfiles.lb
@ }
@ bind .wfiles <FocusOut> {wm withdraw .wfiles}
@ bind .wfiles <Escape> {focus .}
@ foreach evt {1 Return} {
@ bind .wfiles.lb <$evt> {
@ catch {
@ set idx [lindex [.txtA tag ranges fn] [expr {[%W curselection]*2}]]
@ viewDiff $idx
@ }
@ focus .
@ break
@ }
@ }
@ bind .wfiles.lb <Motion> {
@ %W selection clear 0 end
@ %W selection set @%x,%y
@ }
@
@ foreach {side syncCol} {A .txtB B .txtA} {
@ set ln .ln$side
@ text $ln
@ $ln tag config - -justify right
@
@ set txt .txt$side
@ text $txt -width $CFG(WIDTH) -height $CFG(HEIGHT) -wrap none \
@ -xscroll "sync-x $syncCol"
@ catch {$txt config -tabstyle wordprocessor} ;# Required for Tk>=8.5
@ foreach tag {add rm chng} {
@ $txt tag config $tag -background $CFG([string toupper $tag]_BG)
@ $txt tag lower $tag
@ }
@ $txt tag config fn -background $CFG(FN_BG) -foreground $CFG(FN_FG) \
@ -justify center
@ }
@ text .mkr
@
@ font create mono -family courier -size $CFG(FONT_SIZE)
@ foreach font $CFG(FONTS) {
@ if {[lsearch -exact [font families] $font] != -1} {
@ font config mono -family $font
@ break
@ }
@ }
@ foreach c [cols] {
@ set keyPrefix [string toupper [colType $c]]_COL_
@ $c config -bg $CFG(${keyPrefix}BG) -fg $CFG(${keyPrefix}FG) -borderwidth 0 \
@ -font mono -padx $CFG(PADX) -yscroll sync-y
@ $c tag config hr -spacing1 $CFG(HR_PAD_TOP) -spacing3 $CFG(HR_PAD_BTM) \
@ -foreground $CFG(HR_FG)
@ $c tag config fn -spacing1 $CFG(FN_PAD) -spacing3 $CFG(FN_PAD)
@ bindtags $c ". $c Text all"
@ bind $c <1> {focus %W}
@ }
@
@ ::ttk::scrollbar .sby -command {.txtA yview} -orient vertical
@ ::ttk::scrollbar .sbxA -command {.txtA xview} -orient horizontal
@ ::ttk::scrollbar .sbxB -command {.txtB xview} -orient horizontal
@ frame .spacer
@
@ if {[readDiffs $cmd] == 0} {
@ tk_messageBox -type ok -title $CFG(TITLE) -message "No changes"
@ exit
@ }
@ update idletasks
@
@ grid rowconfigure . 1 -weight 1
@ grid columnconfigure . 1 -weight 1
@ grid columnconfigure . 4 -weight 1
@ grid .files -row 0 -columnspan 6
@ eval grid [cols] -row 1 -sticky nsew
@ grid .sby -row 1 -column 5 -sticky ns
@ grid .sbxA -row 2 -columnspan 2 -sticky ew
@ grid .spacer -row 2 -column 2
@ grid .sbxB -row 2 -column 3 -columnspan 2 -sticky ew
@
@ .spacer config -height [winfo height .sbxA]
@ wm deiconify .
;
/*
** Show diff output in a Tcl/Tk window, in response to the --tk option
** to the diff command.
**
** Steps:
** (1) Write the Tcl/Tk script used for rendering into a temp file.
** (2) Invoke "wish" on the temp file using fossil_system().
** (3) Delete the temp file.
*/
void diff_tk(const char *zSubCmd, int firstArg){
int i;
Blob script;
char *zTempFile;
char *zCmd;
blob_zero(&script);
blob_appendf(&script, "set cmd {| \"%/\" %s --html -y -i -v",
g.nameOfExe, zSubCmd);
for(i=firstArg; i<g.argc; i++){
const char *z = g.argv[i];
if( z[0]=='-' ){
if( strglob("*-html",z) ) continue;
if( strglob("*-y",z) ) continue;
if( strglob("*-i",z) ) continue;
|
| ︙ | ︙ |
Changes to src/event.c.
| ︙ | ︙ | |||
397 398 399 400 401 402 403 | if( n<20 ) n = 20; if( n>40 ) n = 40; @ <form method="post" action="%s(g.zTop)/eventedit"><div> login_insert_csrf_secret(); @ <input type="hidden" name="name" value="%h(zEventId)" /> @ <table border="0" cellspacing="10"> | | | | | | | 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 | if( n<20 ) n = 20; if( n>40 ) n = 40; @ <form method="post" action="%s(g.zTop)/eventedit"><div> login_insert_csrf_secret(); @ <input type="hidden" name="name" value="%h(zEventId)" /> @ <table border="0" cellspacing="10"> @ <tr><th align="right" valign="top">Event Time:</th> @ <td valign="top"> @ <input type="text" name="t" size="25" value="%h(zETime)" /> @ </td></tr> @ <tr><th align="right" valign="top">Timeline Comment:</th> @ <td valign="top"> @ <textarea name="c" class="eventedit" cols="80" @ rows="3" wrap="virtual">%h(zComment)</textarea> @ </td></tr> @ <tr><th align="right" valign="top">Background Color:</th> @ <td valign="top"> render_color_chooser(0, zClr, 0, "clr", "cclr"); @ </td></tr> @ <tr><th align="right" valign="top">Tags:</th> @ <td valign="top"> @ <input type="text" name="g" size="40" value="%h(zTags)" /> @ </td></tr> @ <tr><th align="right" valign="top">Page Content:</th> @ <td valign="top"> @ <textarea name="w" class="eventedit" cols="80" @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea> @ </td></tr> @ <tr><td colspan="2"> @ <input type="submit" name="preview" value="Preview Your Changes" /> |
| ︙ | ︙ |
Changes to src/info.c.
| ︙ | ︙ | |||
314 315 316 317 318 319 320 |
content_get(toid, &to);
}else{
blob_zero(&to);
}
blob_zero(&out);
if( diffFlags & DIFF_SIDEBYSIDE ){
text_diff(&from, &to, &out, pRe, diffFlags | DIFF_HTML | DIFF_NOTTOOBIG);
| < < | | < | 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 |
content_get(toid, &to);
}else{
blob_zero(&to);
}
blob_zero(&out);
if( diffFlags & DIFF_SIDEBYSIDE ){
text_diff(&from, &to, &out, pRe, diffFlags | DIFF_HTML | DIFF_NOTTOOBIG);
@ %s(blob_str(&out))
}else{
text_diff(&from, &to, &out, pRe,
diffFlags | DIFF_LINENO | DIFF_HTML | DIFF_NOTTOOBIG);
@ <pre class="udiff">
@ %s(blob_str(&out))
@ </pre>
}
blob_reset(&from);
blob_reset(&to);
blob_reset(&out);
}
/*
** Write a line of web-page output that shows changes that have occurred
** to a file between two check-ins.
*/
static void append_file_change_line(
const char *zName, /* Name of the file that has changed */
|
| ︙ | ︙ | |||
357 358 359 360 361 362 363 |
}else if( fossil_strcmp(zNew, zOld)==0 ){
@ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared")
@ for %h(zName)</p>
}else{
@ <p>Changes to %h(zName)</p>
}
if( diffFlags ){
| < < | 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 |
}else if( fossil_strcmp(zNew, zOld)==0 ){
@ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared")
@ for %h(zName)</p>
}else{
@ <p>Changes to %h(zName)</p>
}
if( diffFlags ){
append_diff(zOld, zNew, diffFlags, pRe);
}
}else{
if( zOld && zNew ){
if( fossil_strcmp(zOld, zNew)!=0 ){
@ <p>Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
@ from %z(href("%R/artifact/%s",zOld))[%S(zOld)]</a>
@ to %z(href("%R/artifact/%s",zNew))[%S(zNew)].</a>
|
| ︙ | ︙ | |||
383 384 385 386 387 388 389 |
@ <p>Deleted %z(href("%s/finfo?name=%T",g.zTop,zName))%h(zName)</a>
@ version %z(href("%R/artifact/%s",zOld))[%S(zOld)]</a>
}else{
@ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
@ version %z(href("%R/artifact/%s",zNew))[%S(zNew)]</a>
}
if( diffFlags ){
| < < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
@ <p>Deleted %z(href("%s/finfo?name=%T",g.zTop,zName))%h(zName)</a>
@ version %z(href("%R/artifact/%s",zOld))[%S(zOld)]</a>
}else{
@ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
@ version %z(href("%R/artifact/%s",zNew))[%S(zNew)]</a>
}
if( diffFlags ){
append_diff(zOld, zNew, diffFlags, pRe);
}else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){
@
@ %z(href("%R/fdiff?v1=%S&v2=%S&sbs=1",zOld,zNew))[diff]</a>
}
}
}
/*
** Generate javascript to enhance HTML diffs.
*/
void append_diff_javascript(int sideBySide){
if( !sideBySide ) return;
@ <script>(function(){
@ var SCROLL_LEN = 25;
@ function initSbsDiff(diff){
@ var txtCols = diff.querySelectorAll('.difftxtcol');
@ var txtPres = diff.querySelectorAll('.difftxtcol pre');
@ var width = Math.max(txtPres[0].scrollWidth, txtPres[1].scrollWidth);
@ for(var i=0; i<2; i++){
@ txtPres[i].style.width = width + 'px';
@ txtCols[i].onscroll = function(e){
@ txtCols[0].scrollLeft = txtCols[1].scrollLeft = this.scrollLeft;
@ };
@ }
@ diff.tabIndex = 0;
@ diff.onkeydown = function(e){
@ e = e || event;
@ var len = {37: -SCROLL_LEN, 39: SCROLL_LEN}[e.keyCode];
@ if( !len ) return;
@ txtCols[0].scrollLeft += len;
@ return false;
@ };
@ }
@
@ var diffs = document.querySelectorAll('.sbsdiffcols');
@ for(var i=0; i<diffs.length; i++){
@ initSbsDiff(diffs[i]);
@ }
@ }())</script>
}
/*
** Construct an appropriate diffFlag for text_diff() based on query
** parameters and the to boolean arguments.
*/
u64 construct_diff_flags(int verboseFlag, int sideBySide){
u64 diffFlags;
|
| ︙ | ︙ | |||
673 674 675 676 677 678 679 680 681 682 683 684 685 686 |
const char *zOld = db_column_text(&q,2);
const char *zNew = db_column_text(&q,3);
const char *zOldName = db_column_text(&q, 4);
append_file_change_line(zName, zOld, zNew, zOldName, diffFlags,pRe,mperm);
}
db_finalize(&q);
}
style_footer();
}
/*
** WEBPAGE: winfo
** URL: /winfo?name=UUID
**
| > | 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 |
const char *zOld = db_column_text(&q,2);
const char *zNew = db_column_text(&q,3);
const char *zOldName = db_column_text(&q, 4);
append_file_change_line(zName, zOld, zNew, zOldName, diffFlags,pRe,mperm);
}
db_finalize(&q);
}
append_diff_javascript(sideBySide);
style_footer();
}
/*
** WEBPAGE: winfo
** URL: /winfo?name=UUID
**
|
| ︙ | ︙ | |||
986 987 988 989 990 991 992 |
manifest_file_mperm(pFileTo));
pFileFrom = manifest_file_next(pFrom, 0);
pFileTo = manifest_file_next(pTo, 0);
}
}
manifest_destroy(pFrom);
manifest_destroy(pTo);
| | | 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 |
manifest_file_mperm(pFileTo));
pFileFrom = manifest_file_next(pFrom, 0);
pFileTo = manifest_file_next(pTo, 0);
}
}
manifest_destroy(pFrom);
manifest_destroy(pTo);
append_diff_javascript(sideBySide);
style_footer();
}
#if INTERFACE
/*
** Possible return values from object_description()
*/
|
| ︙ | ︙ | |||
1242 1243 1244 1245 1246 1247 1248 |
** difference between the two artifacts. Show diff side by side unless sbs
** is 0. Generate plaintext if "patch" is present.
*/
void diff_page(void){
int v1, v2;
int isPatch;
int sideBySide;
| < < | | < > < < < < < < < < < < < < < | | | | | > > | > > > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | < | | < | 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 |
** difference between the two artifacts. Show diff side by side unless sbs
** is 0. Generate plaintext if "patch" is present.
*/
void diff_page(void){
int v1, v2;
int isPatch;
int sideBySide;
char *zV1;
char *zV2;
const char *zRe;
ReCompiled *pRe = 0;
u64 diffFlags;
login_check_credentials();
if( !g.perm.Read ){ login_needed(); return; }
v1 = name_to_rid_www("v1");
v2 = name_to_rid_www("v2");
if( v1==0 || v2==0 ) fossil_redirect_home();
zRe = P("regex");
if( zRe ) re_compile(&pRe, zRe, 0);
isPatch = P("patch")!=0;
if( isPatch ){
Blob c1, c2, *pOut;
pOut = cgi_output_blob();
cgi_set_content_type("text/plain");
diffFlags = 4;
content_get(v1, &c1);
content_get(v2, &c2);
text_diff(&c1, &c2, pOut, pRe, diffFlags);
blob_reset(&c1);
blob_reset(&c2);
return;
}
sideBySide = !is_false(PD("sbs","1"));
zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1);
zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2);
diffFlags = construct_diff_flags(1, sideBySide) | DIFF_HTML;
style_header("Diff");
style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch",
g.zTop, P("v1"), P("v2"));
if( !sideBySide ){
style_submenu_element("Side-by-side Diff", "sbsdiff",
"%s/fdiff?v1=%T&v2=%T&sbs=1",
g.zTop, P("v1"), P("v2"));
}else{
style_submenu_element("Unified Diff", "udiff",
"%s/fdiff?v1=%T&v2=%T&sbs=0",
g.zTop, P("v1"), P("v2"));
}
if( P("smhdr")!=0 ){
@ <h2>Differences From Artifact
@ %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a> To
@ %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>.</h2>
}else{
@ <h2>Differences From
@ Artifact %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a>:</h2>
object_description(v1, 0, 0);
@ <h2>To Artifact %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>:</h2>
object_description(v2, 0, 0);
}
if( pRe ){
@ <b>Only differences that match regular expression "%h(zRe)"
@ are shown.</b>
}
@ <hr />
append_diff(zV1, zV2, diffFlags, pRe);
append_diff_javascript(sideBySide);
style_footer();
}
/*
** WEBPAGE: raw
** URL: /raw?name=ARTIFACTID&m=TYPE
**
** Return the uninterpreted content of an artifact. Used primarily
|
| ︙ | ︙ | |||
2203 2204 2205 2206 2207 2208 2209 |
@ <p>Make changes to attributes of check-in
@ [%z(href("%R/ci/%s",zUuid))%s(zUuid)</a>]:</p>
form_begin(0, "%R/ci_edit");
login_insert_csrf_secret();
@ <div><input type="hidden" name="r" value="%S(zUuid)" />
@ <table border="0" cellspacing="10">
| | | | | | | | 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 |
@ <p>Make changes to attributes of check-in
@ [%z(href("%R/ci/%s",zUuid))%s(zUuid)</a>]:</p>
form_begin(0, "%R/ci_edit");
login_insert_csrf_secret();
@ <div><input type="hidden" name="r" value="%S(zUuid)" />
@ <table border="0" cellspacing="10">
@ <tr><th align="right" valign="top">User:</th>
@ <td valign="top">
@ <input type="text" name="u" size="20" value="%h(zNewUser)" />
@ </td></tr>
@ <tr><th align="right" valign="top">Comment:</th>
@ <td valign="top">
@ <textarea name="c" rows="10" cols="80">%h(zNewComment)</textarea>
@ </td></tr>
@ <tr><th align="right" valign="top">Check-in Time:</th>
@ <td valign="top">
@ <input type="text" name="dt" size="20" value="%h(zNewDate)" />
@ </td></tr>
if( zChngTime ){
@ <tr><th align="right" valign="top">Timestamp of this change:</th>
@ <td valign="top">
@ <input type="text" name="chngtime" size="20" value="%h(zChngTime)" />
@ </td></tr>
}
@ <tr><th align="right" valign="top">Background Color:</th>
@ <td valign="top">
render_color_chooser(fNewPropagateColor, zNewColor, "pclr", "clr", "clrcust");
@ </td></tr>
@ <tr><th align="right" valign="top">Tags:</th>
@ <td valign="top">
@ <label><input type="checkbox" id="newtag" name="newtag"%s(zNewTagFlag) />
@ Add the following new tag name to this check-in:</label>
@ <input type="text" style="width:15;" name="tagname" value="%h(zNewTag)"
@ onkeyup="gebi('newtag').checked=!!this.value" />
db_prepare(&q,
"SELECT tag.tagid, tagname FROM tagxref, tag"
|
| ︙ | ︙ | |||
2263 2264 2265 2266 2267 2268 2269 |
}else{
@ Cancel special tag <b>%h(zTagName)</b></label>
}
}
db_finalize(&q);
@ </td></tr>
| | | | 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 |
}else{
@ Cancel special tag <b>%h(zTagName)</b></label>
}
}
db_finalize(&q);
@ </td></tr>
@ <tr><th align="right" valign="top">Branching:</th>
@ <td valign="top">
@ <label><input id="newbr" type="checkbox" name="newbr"%s(zNewBrFlag) />
@ Make this check-in the start of a new branch named:</label>
@ <input type="text" style="width:15;" name="brname" value="%h(zNewBranch)"
@ onkeyup="gebi('newbr').checked=!!this.value" />
@ </td></tr>
if( is_a_leaf(rid)
&& !db_exists("SELECT 1 FROM tagxref "
" WHERE tagid=%d AND rid=%d AND tagtype>0",
TAG_CLOSED, rid)
){
@ <tr><th align="right" valign="top">Leaf Closure:</th>
@ <td valign="top">
@ <label><input type="checkbox" name="close"%s(zCloseFlag) />
@ Mark this leaf as "closed" so that it no longer appears on the
@ "leaves" page and is no longer labeled as a "<b>Leaf</b>".</label>
@ </td></tr>
}
|
| ︙ | ︙ |
Added src/lookslike.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 |
/*
** Copyright (c) 2013 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 try to guess if a particular file is
** text or binary, what types of line endings it uses, is it UTF8 or
** UTF16, etc.
*/
#include "config.h"
#include "lookslike.h"
#include <assert.h>
#if INTERFACE
/*
** This macro is designed to return non-zero if the specified blob contains
** data that MAY be binary in nature; otherwise, zero will be returned.
*/
#define looks_like_binary(blob) \
((looks_like_utf8((blob), LOOK_BINARY) & LOOK_BINARY) != LOOK_NONE)
/*
** Output flags for the looks_like_utf8() and looks_like_utf16() routines used
** to convey status information about the blob content.
*/
#define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */
#define LOOK_NUL ((int)0x00000001) /* One or more NUL chars were found. */
#define LOOK_CR ((int)0x00000002) /* One or more CR chars were found. */
#define LOOK_LONE_CR ((int)0x00000004) /* An unpaired CR char was found. */
#define LOOK_LF ((int)0x00000008) /* One or more LF chars were found. */
#define LOOK_LONE_LF ((int)0x00000010) /* An unpaired LF char was found. */
#define LOOK_CRLF ((int)0x00000020) /* One or more CR/LF pairs were found. */
#define LOOK_LONG ((int)0x00000040) /* An over length line was found. */
#define LOOK_ODD ((int)0x00000080) /* An odd number of bytes was found. */
#define LOOK_SHORT ((int)0x00000100) /* Unable to perform full check. */
#define LOOK_INVALID ((int)0x00000200) /* Invalid sequence was found. */
#define LOOK_BINARY (LOOK_NUL | LOOK_LONG | LOOK_SHORT) /* May be binary. */
#define LOOK_EOL (LOOK_LONE_CR | LOOK_LONE_LF | LOOK_CRLF) /* Line seps. */
#endif /* INTERFACE */
/*
** This function attempts to scan each logical line within the blob to
** determine the type of content it appears to contain. The return value
** is a combination of one or more of the LOOK_XXX flags (see above):
**
** !LOOK_BINARY -- The content appears to consist entirely of text; however,
** the encoding may not be UTF-8.
**
** LOOK_BINARY -- The content appears to be binary because it contains one
** or more embedded NUL characters or an extremely long line.
** Since this function does not understand UTF-16, it may
** falsely consider UTF-16 text to be binary.
**
** Additional flags (i.e. those other than the ones included in LOOK_BINARY)
** may be present in the result as well; however, they should not impact the
** determination of text versus binary content.
**
************************************ WARNING **********************************
**
** This function does not validate that the blob content is properly formed
** UTF-8. It assumes that all code points are the same size. It does not
** validate any code points. It makes no attempt to detect if any [invalid]
** switches between UTF-8 and other encodings occur.
**
** The only code points that this function cares about are the NUL character,
** carriage-return, and line-feed.
**
** This function examines the contents of the blob until one of the flags
** specified in "stopFlags" is set.
**
************************************ WARNING **********************************
*/
int looks_like_utf8(const Blob *pContent, int stopFlags){
const char *z = blob_buffer(pContent);
unsigned int n = blob_size(pContent);
int j, c, flags = LOOK_NONE; /* Assume UTF-8 text, prove otherwise */
if( n==0 ) return flags; /* Empty file -> text */
c = *z;
if( c==0 ){
flags |= LOOK_NUL; /* NUL character in a file -> binary */
}else if( c=='\r' ){
flags |= LOOK_CR;
if( n<=1 || z[1]!='\n' ){
flags |= LOOK_LONE_CR; /* More chars, next char is not LF */
}
}
j = (c!='\n');
if( !j ) flags |= (LOOK_LF | LOOK_LONE_LF); /* Found LF as first char */
while( !(flags&stopFlags) && --n>0 ){
int c2 = c;
c = *++z; ++j;
if( c==0 ){
flags |= LOOK_NUL; /* NUL character in a file -> binary */
}else if( c=='\n' ){
flags |= LOOK_LF;
if( c2=='\r' ){
flags |= (LOOK_CR | LOOK_CRLF); /* Found LF preceded by CR */
}else{
flags |= LOOK_LONE_LF;
}
if( j>LENGTH_MASK ){
flags |= LOOK_LONG; /* Very long line -> binary */
}
j = 0;
}else if( c=='\r' ){
flags |= LOOK_CR;
if( n<=1 || z[1]!='\n' ){
flags |= LOOK_LONE_CR; /* More chars, next char is not LF */
}
}
}
if( n ){
flags |= LOOK_SHORT; /* The whole blob was not examined */
}
if( j>LENGTH_MASK ){
flags |= LOOK_LONG; /* Very long line -> binary */
}
return flags;
}
/*
** Define the type needed to represent a Unicode (UTF-16) character.
*/
#ifndef WCHAR_T
# ifdef _WIN32
# define WCHAR_T wchar_t
# else
# define WCHAR_T unsigned short
# endif
#endif
/*
** Maximum length of a line in a text file, in UTF-16 characters. (4096)
** The number of bytes represented by this value cannot exceed LENGTH_MASK
** bytes, because that is the line buffer size used by the diff engine.
*/
#define UTF16_LENGTH_MASK_SZ (LENGTH_MASK_SZ-(sizeof(WCHAR_T)-sizeof(char)))
#define UTF16_LENGTH_MASK ((1<<UTF16_LENGTH_MASK_SZ)-1)
/*
** This macro is used to swap the byte order of a UTF-16 character in the
** looks_like_utf16() function.
*/
#define UTF16_SWAP(ch) ((((ch) << 8) & 0xFF00) | (((ch) >> 8) & 0xFF))
#define UTF16_SWAP_IF(expr,ch) ((expr) ? UTF16_SWAP((ch)) : (ch))
/*
** This function attempts to scan each logical line within the blob to
** determine the type of content it appears to contain. The return value
** is a combination of one or more of the LOOK_XXX flags (see above):
**
** !LOOK_BINARY -- The content appears to consist entirely of text; however,
** the encoding may not be UTF-16.
**
** LOOK_BINARY -- The content appears to be binary because it contains one
** or more embedded NUL characters or an extremely long line.
** Since this function does not understand UTF-8, it may
** falsely consider UTF-8 text to be binary.
**
** Additional flags (i.e. those other than the ones included in LOOK_BINARY)
** may be present in the result as well; however, they should not impact the
** determination of text versus binary content.
**
************************************ WARNING **********************************
**
** This function does not validate that the blob content is properly formed
** UTF-16. It assumes that all code points are the same size. It does not
** validate any code points. It makes no attempt to detect if any [invalid]
** switches between the UTF-16be and UTF-16le encodings occur.
**
** The only code points that this function cares about are the NUL character,
** carriage-return, and line-feed.
**
** This function examines the contents of the blob until one of the flags
** specified in "stopFlags" is set.
**
************************************ WARNING **********************************
*/
int looks_like_utf16(const Blob *pContent, int bReverse, int stopFlags){
const WCHAR_T *z = (WCHAR_T *)blob_buffer(pContent);
unsigned int n = blob_size(pContent);
int j, c, flags = LOOK_NONE; /* Assume UTF-16 text, prove otherwise */
if( n==0 ) return flags; /* Empty file -> text */
if( n%sizeof(WCHAR_T) ){
flags |= LOOK_ODD; /* Odd number of bytes -> binary (UTF-8?) */
if( n<sizeof(WCHAR_T) ) return flags; /* One byte -> binary (UTF-8?) */
}
c = *z;
if( bReverse ){
c = UTF16_SWAP(c);
}
if( c==0 ){
flags |= LOOK_NUL; /* NUL character in a file -> binary */
}else if( c=='\r' ){
flags |= LOOK_CR;
if( n<(2*sizeof(WCHAR_T)) || UTF16_SWAP_IF(bReverse, z[1])!='\n' ){
flags |= LOOK_LONE_CR; /* More chars, next char is not LF */
}
}
j = (c!='\n');
if( !j ) flags |= (LOOK_LF | LOOK_LONE_LF); /* Found LF as first char */
while( 1 ){
int c2 = c;
if( flags&stopFlags ) break;
n -= sizeof(WCHAR_T);
if( n<sizeof(WCHAR_T) ) break;
c = *++z;
if( bReverse ){
c = UTF16_SWAP(c);
}
++j;
if( c==0 ){
flags |= LOOK_NUL; /* NUL character in a file -> binary */
}else if( c=='\n' ){
flags |= LOOK_LF;
if( c2=='\r' ){
flags |= (LOOK_CR | LOOK_CRLF); /* Found LF preceded by CR */
}else{
flags |= LOOK_LONE_LF;
}
if( j>UTF16_LENGTH_MASK ){
flags |= LOOK_LONG; /* Very long line -> binary */
}
j = 0;
}else if( c=='\r' ){
flags |= LOOK_CR;
if( n<(2*sizeof(WCHAR_T)) || UTF16_SWAP_IF(bReverse, z[1])!='\n' ){
flags |= LOOK_LONE_CR; /* More chars, next char is not LF */
}
}
}
if( n ){
flags |= LOOK_SHORT; /* The whole blob was not examined */
}
if( j>UTF16_LENGTH_MASK ){
flags |= LOOK_LONG; /* Very long line -> binary */
}
return flags;
}
/*
** This function returns an array of bytes representing the byte-order-mark
** for UTF-8.
*/
const unsigned char *get_utf8_bom(int *pnByte){
static const unsigned char bom[] = {
0xEF, 0xBB, 0xBF, 0x00, 0x00, 0x00
};
if( pnByte ) *pnByte = 3;
return bom;
}
/*
** This function returns non-zero if the blob starts with a UTF-8
** byte-order-mark (BOM).
*/
int starts_with_utf8_bom(const Blob *pContent, int *pnByte){
const char *z = blob_buffer(pContent);
int bomSize = 0;
const unsigned char *bom = get_utf8_bom(&bomSize);
if( pnByte ) *pnByte = bomSize;
if( blob_size(pContent)<bomSize ) return 0;
return memcmp(z, bom, bomSize)==0;
}
/*
** This function returns non-zero if the blob starts with a UTF-16
** byte-order-mark (BOM), either in the endianness of the machine
** or in reversed byte order. The UTF-32 BOM is ruled out by checking
** if the UTF-16 BOM is not immediately followed by (utf16) 0.
** pnByte is only set when the function returns 1.
**
** pbReverse is always set, even when no BOM is found. Without a BOM,
** it is set to 1 on little-endian and 0 on big-endian platforms. See
** clause D98 of conformance (section 3.10) of the Unicode standard.
*/
int starts_with_utf16_bom(
const Blob *pContent, /* IN: Blob content to perform BOM detection on. */
int *pnByte, /* OUT: The number of bytes used for the BOM. */
int *pbReverse /* OUT: Non-zero for BOM in reverse byte-order. */
){
const unsigned short *z = (unsigned short *)blob_buffer(pContent);
int bomSize = sizeof(unsigned short);
int size = blob_size(pContent);
if( size<bomSize ) goto noBom; /* No: cannot read BOM. */
if( size>=(2*bomSize) && z[1]==0 ) goto noBom; /* No: possible UTF-32. */
if( z[0]==0xfeff ){
if( pbReverse ) *pbReverse = 0;
}else if( z[0]==0xfffe ){
if( pbReverse ) *pbReverse = 1;
}else{
static const int one = 1;
noBom:
if( pbReverse ) *pbReverse = *(char *) &one;
return 0; /* No: UTF-16 byte-order-mark not found. */
}
if( pnByte ) *pnByte = bomSize;
return 1; /* Yes. */
}
/*
** Returns non-zero if the specified content could be valid UTF-16.
*/
int could_be_utf16(const Blob *pContent, int *pbReverse){
return (blob_size(pContent) % sizeof(WCHAR_T) == 0) ?
starts_with_utf16_bom(pContent, 0, pbReverse) : 0;
}
/*
** COMMAND: test-looks-like-utf
**
** Usage: %fossil test-looks-like-utf FILENAME
**
** Options:
** --utf8 Ignoring BOM and file size, force UTF-8 checking
** --utf16 Ignoring BOM and file size, force UTF-16 checking
**
** FILENAME is the name of a file to check for textual content in the UTF-8
** and/or UTF-16 encodings.
*/
void looks_like_utf_test_cmd(void){
Blob blob; /* the contents of the specified file */
int fUtf8; /* return value of starts_with_utf8_bom() */
int fUtf16; /* return value of starts_with_utf16_bom() */
int fUnicode; /* return value of could_be_utf16() */
int lookFlags; /* output flags from looks_like_utf8/utf16() */
int bRevUtf16 = 0; /* non-zero -> UTF-16 byte order reversed */
int bRevUnicode = 0; /* non-zero -> UTF-16 byte order reversed */
int fForceUtf8 = find_option("utf8",0,0)!=0;
int fForceUtf16 = find_option("utf16",0,0)!=0;
if( g.argc!=3 ) usage("FILENAME");
blob_read_from_file(&blob, g.argv[2]);
fUtf8 = starts_with_utf8_bom(&blob, 0);
fUtf16 = starts_with_utf16_bom(&blob, 0, &bRevUtf16);
if( fForceUtf8 ){
fUnicode = 0;
}else{
fUnicode = could_be_utf16(&blob, &bRevUnicode) || fForceUtf16;
}
lookFlags = fUnicode ? looks_like_utf16(&blob, bRevUnicode, 0) :
looks_like_utf8(&blob, 0);
fossil_print("File \"%s\" has %d bytes.\n",g.argv[2],blob_size(&blob));
fossil_print("Starts with UTF-8 BOM: %s\n",fUtf8?"yes":"no");
fossil_print("Starts with UTF-16 BOM: %s\n",
fUtf16?(bRevUtf16?"reversed":"yes"):"no");
fossil_print("Looks like UTF-%s: %s\n",fUnicode?"16":"8",
(lookFlags&LOOK_BINARY)?"no":"yes");
fossil_print("Has flag LOOK_NUL: %s\n",(lookFlags&LOOK_NUL)?"yes":"no");
fossil_print("Has flag LOOK_CR: %s\n",(lookFlags&LOOK_CR)?"yes":"no");
fossil_print("Has flag LOOK_LONE_CR: %s\n",
(lookFlags&LOOK_LONE_CR)?"yes":"no");
fossil_print("Has flag LOOK_LF: %s\n",(lookFlags&LOOK_LF)?"yes":"no");
fossil_print("Has flag LOOK_LONE_LF: %s\n",
(lookFlags&LOOK_LONE_LF)?"yes":"no");
fossil_print("Has flag LOOK_CRLF: %s\n",(lookFlags&LOOK_CRLF)?"yes":"no");
fossil_print("Has flag LOOK_LONG: %s\n",(lookFlags&LOOK_LONG)?"yes":"no");
fossil_print("Has flag LOOK_INVALID: %s\n",
(lookFlags&LOOK_INVALID)?"yes":"no");
fossil_print("Has flag LOOK_ODD: %s\n",(lookFlags&LOOK_ODD)?"yes":"no");
fossil_print("Has flag LOOK_SHORT: %s\n",(lookFlags&LOOK_SHORT)?"yes":"no");
blob_reset(&blob);
}
|
Changes to src/main.mk.
| ︙ | ︙ | |||
65 66 67 68 69 70 71 72 73 74 75 76 77 78 | $(SRCDIR)/json_status.c \ $(SRCDIR)/json_tag.c \ $(SRCDIR)/json_timeline.c \ $(SRCDIR)/json_user.c \ $(SRCDIR)/json_wiki.c \ $(SRCDIR)/leaf.c \ $(SRCDIR)/login.c \ $(SRCDIR)/main.c \ $(SRCDIR)/manifest.c \ $(SRCDIR)/markdown.c \ $(SRCDIR)/markdown_html.c \ $(SRCDIR)/md5.c \ $(SRCDIR)/merge.c \ $(SRCDIR)/merge3.c \ | > | 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | $(SRCDIR)/json_status.c \ $(SRCDIR)/json_tag.c \ $(SRCDIR)/json_timeline.c \ $(SRCDIR)/json_user.c \ $(SRCDIR)/json_wiki.c \ $(SRCDIR)/leaf.c \ $(SRCDIR)/login.c \ $(SRCDIR)/lookslike.c \ $(SRCDIR)/main.c \ $(SRCDIR)/manifest.c \ $(SRCDIR)/markdown.c \ $(SRCDIR)/markdown_html.c \ $(SRCDIR)/md5.c \ $(SRCDIR)/merge.c \ $(SRCDIR)/merge3.c \ |
| ︙ | ︙ | |||
173 174 175 176 177 178 179 180 181 182 183 184 185 186 | $(OBJDIR)/json_status_.c \ $(OBJDIR)/json_tag_.c \ $(OBJDIR)/json_timeline_.c \ $(OBJDIR)/json_user_.c \ $(OBJDIR)/json_wiki_.c \ $(OBJDIR)/leaf_.c \ $(OBJDIR)/login_.c \ $(OBJDIR)/main_.c \ $(OBJDIR)/manifest_.c \ $(OBJDIR)/markdown_.c \ $(OBJDIR)/markdown_html_.c \ $(OBJDIR)/md5_.c \ $(OBJDIR)/merge_.c \ $(OBJDIR)/merge3_.c \ | > | 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | $(OBJDIR)/json_status_.c \ $(OBJDIR)/json_tag_.c \ $(OBJDIR)/json_timeline_.c \ $(OBJDIR)/json_user_.c \ $(OBJDIR)/json_wiki_.c \ $(OBJDIR)/leaf_.c \ $(OBJDIR)/login_.c \ $(OBJDIR)/lookslike_.c \ $(OBJDIR)/main_.c \ $(OBJDIR)/manifest_.c \ $(OBJDIR)/markdown_.c \ $(OBJDIR)/markdown_html_.c \ $(OBJDIR)/md5_.c \ $(OBJDIR)/merge_.c \ $(OBJDIR)/merge3_.c \ |
| ︙ | ︙ | |||
281 282 283 284 285 286 287 288 289 290 291 292 293 294 | $(OBJDIR)/json_status.o \ $(OBJDIR)/json_tag.o \ $(OBJDIR)/json_timeline.o \ $(OBJDIR)/json_user.o \ $(OBJDIR)/json_wiki.o \ $(OBJDIR)/leaf.o \ $(OBJDIR)/login.o \ $(OBJDIR)/main.o \ $(OBJDIR)/manifest.o \ $(OBJDIR)/markdown.o \ $(OBJDIR)/markdown_html.o \ $(OBJDIR)/md5.o \ $(OBJDIR)/merge.o \ $(OBJDIR)/merge3.o \ | > | 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 | $(OBJDIR)/json_status.o \ $(OBJDIR)/json_tag.o \ $(OBJDIR)/json_timeline.o \ $(OBJDIR)/json_user.o \ $(OBJDIR)/json_wiki.o \ $(OBJDIR)/leaf.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 \ |
| ︙ | ︙ | |||
400 401 402 403 404 405 406 | clean: rm -rf $(OBJDIR)/* $(APPNAME) $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex $(OBJDIR)/mkindex $(TRANS_SRC) >$@ $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h | | | 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 | clean: rm -rf $(OBJDIR)/* $(APPNAME) $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex $(OBJDIR)/mkindex $(TRANS_SRC) >$@ $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(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)/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 $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_status_.c:$(OBJDIR)/json_status.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/lookslike_.c:$(OBJDIR)/lookslike.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/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 $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h $(OBJDIR)/util_.c:$(OBJDIR)/util.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/wysiwyg_.c:$(OBJDIR)/wysiwyg.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h touch $(OBJDIR)/headers $(OBJDIR)/headers: Makefile $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/json_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_status.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h Makefile: $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/add.c >$(OBJDIR)/add_.c |
| ︙ | ︙ | |||
790 791 792 793 794 795 796 797 798 799 800 801 802 803 | $(OBJDIR)/login_.c: $(SRCDIR)/login.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/login.c >$(OBJDIR)/login_.c $(OBJDIR)/login.o: $(OBJDIR)/login_.c $(OBJDIR)/login.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/login.o -c $(OBJDIR)/login_.c $(OBJDIR)/login.h: $(OBJDIR)/headers $(OBJDIR)/main_.c: $(SRCDIR)/main.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/main.c >$(OBJDIR)/main_.c $(OBJDIR)/main.o: $(OBJDIR)/main_.c $(OBJDIR)/main.h $(OBJDIR)/page_index.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/main.o -c $(OBJDIR)/main_.c $(OBJDIR)/main.h: $(OBJDIR)/headers | > > > > > > > | 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 | $(OBJDIR)/login_.c: $(SRCDIR)/login.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/login.c >$(OBJDIR)/login_.c $(OBJDIR)/login.o: $(OBJDIR)/login_.c $(OBJDIR)/login.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/login.o -c $(OBJDIR)/login_.c $(OBJDIR)/login.h: $(OBJDIR)/headers $(OBJDIR)/lookslike_.c: $(SRCDIR)/lookslike.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/lookslike.c >$(OBJDIR)/lookslike_.c $(OBJDIR)/lookslike.o: $(OBJDIR)/lookslike_.c $(OBJDIR)/lookslike.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/lookslike.o -c $(OBJDIR)/lookslike_.c $(OBJDIR)/lookslike.h: $(OBJDIR)/headers $(OBJDIR)/main_.c: $(SRCDIR)/main.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/main.c >$(OBJDIR)/main_.c $(OBJDIR)/main.o: $(OBJDIR)/main_.c $(OBJDIR)/main.h $(OBJDIR)/page_index.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/main.o -c $(OBJDIR)/main_.c $(OBJDIR)/main.h: $(OBJDIR)/headers |
| ︙ | ︙ | |||
1151 1152 1153 1154 1155 1156 1157 | $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c $(OBJDIR)/zip.h: $(OBJDIR)/headers $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o $(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h | | | 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 | $(XTCC) -o $(OBJDIR)/zip.o -c $(OBJDIR)/zip_.c $(OBJDIR)/zip.h: $(OBJDIR)/headers $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o $(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h $(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -Dsqlite3_strglob=strglob -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o $(OBJDIR)/th.o: $(SRCDIR)/th.c $(XTCC) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o $(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c $(XTCC) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o |
| ︙ | ︙ |
Changes to src/makemake.tcl.
| ︙ | ︙ | |||
68 69 70 71 72 73 74 75 76 77 78 79 80 81 | json_status json_tag json_timeline json_user json_wiki leaf login main manifest markdown markdown_html md5 merge merge3 | > | 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | json_status json_tag json_timeline json_user json_wiki leaf login lookslike main manifest markdown markdown_html md5 merge merge3 |
| ︙ | ︙ | |||
294 295 296 297 298 299 300 301 302 303 304 305 306 307 |
append opt " -DSQLITE_ENABLE_LOCKING_STYLE=0"
set SQLITE_OPTIONS $opt
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h"
set opt {-Dmain=sqlite3_shell}
append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"
writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th.c -o \$(OBJDIR)/th.o\n"
writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_lang.c -o \$(OBJDIR)/th_lang.o\n"
| > | 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 |
append opt " -DSQLITE_ENABLE_LOCKING_STYLE=0"
set SQLITE_OPTIONS $opt
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h"
set opt {-Dmain=sqlite3_shell}
append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
append opt " -Dsqlite3_strglob=strglob"
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"
writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th.c -o \$(OBJDIR)/th.o\n"
writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_lang.c -o \$(OBJDIR)/th_lang.o\n"
|
| ︙ | ︙ |
Changes to src/merge3.c.
| ︙ | ︙ | |||
338 339 340 341 342 343 344 | blob_read_from_file(&file, zFullpath); rc = contains_merge_marker(&file); blob_reset(&file); return rc; } /* | | | | > > > > | > > > > > > > > > > > > > > > | 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 |
blob_read_from_file(&file, zFullpath);
rc = contains_merge_marker(&file);
blob_reset(&file);
return rc;
}
/*
** COMMAND: 3-way-merge*
**
** Usage: %fossil 3-way-merge BASELINE V1 V2 MERGED
**
** Inputs are files BASELINE, V1, and V2. The file MERGED is generated
** as output.
**
** BASELINE is a common ancestor of two files V1 and V2 that have diverging
** edits. The generated output file MERGED is the combination of all
** changes in both V1 and V2.
**
** This command has no effect on the Fossil repository. It is a utility
** command made available for the convenience of users. This command can
** be used, for example, to help import changes from an upstream project.
**
** Suppose an upstream project has a file named "Xup.c" which is imported
** with modifications to the local project as "Xlocal.c". Suppose further
** that the "Xbase.c" is an exact copy of the last imported "Xup.c".
** Then to import the latest "Xup.c" while preserving all the local changes:
**
** fossil 3-way-merge Xbase.c Xlocal.c Xup.c Xlocal.c
** cp Xup.c Xbase.c
** # Verify that everything still works
** fossil commit
**
*/
void delta_3waymerge_cmd(void){
Blob pivot, v1, v2, merged;
if( g.argc!=6 ){
usage("PIVOT V1 V2 MERGED");
}
if( blob_read_from_file(&pivot, g.argv[2])<0 ){
|
| ︙ | ︙ |
Changes to src/search.c.
| ︙ | ︙ | |||
164 165 166 167 168 169 170 |
search_score_sqlfunc, 0, 0);
}
/*
** Testing the search function.
**
** COMMAND: search*
| | | > > > > > > > > > > > > > > > | 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 |
search_score_sqlfunc, 0, 0);
}
/*
** Testing the search function.
**
** COMMAND: search*
** %fossil search [-all|-a] [-limit|-n #] pattern...
**
** Search for timeline entries matching all words
** provided on the command line. Whole-word matches
** scope more highly than partial matches.
**
** Outputs, by default, some top-N fraction of the
** results. The -all option can be used to output
** all matches, regardless of their search score.
** -limit can be used to limit the number of entries
** returned.
*/
void search_cmd(void){
Search *p;
Blob pattern;
int i;
Blob sql = empty_blob;
Stmt q;
int iBest;
char fAll = NULL != find_option("all", "a", 0); /* If set, do not lop
off the end of the
results. */
char const * zLimit = find_option("limit","n",1);
int const nLimit = zLimit ? atoi(zLimit) : -1; /* Max number of entries
to list */
db_must_be_within_tree();
if( g.argc<2 ) return;
blob_init(&pattern, g.argv[2], -1);
for(i=3; i<g.argc; i++){
blob_appendf(&pattern, " %s", g.argv[i]);
}
|
| ︙ | ︙ | |||
196 197 198 199 200 201 202 |
" SELECT blob.rid, uuid, datetime(event.mtime, 'localtime'),"
" coalesce(ecomment,comment),"
" score(coalesce(ecomment,comment)) AS y"
" FROM event, blob"
" WHERE blob.rid=event.objid AND y>0;"
);
iBest = db_int(0, "SELECT max(x) FROM srch");
| | | > > > > | | > > > | | 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
" SELECT blob.rid, uuid, datetime(event.mtime, 'localtime'),"
" coalesce(ecomment,comment),"
" score(coalesce(ecomment,comment)) AS y"
" FROM event, blob"
" WHERE blob.rid=event.objid AND y>0;"
);
iBest = db_int(0, "SELECT max(x) FROM srch");
blob_append(&sql,
"SELECT rid, uuid, date, comment, 0, 0 FROM srch "
"WHERE 1 ", -1);
if(!fAll){
blob_appendf(&sql,"AND x>%d ", iBest/3);
}
blob_append(&sql, "ORDER BY x DESC, date DESC ", -1);
if(nLimit>0){
blob_appendf(&sql, "LIMIT %d", nLimit);
}
db_prepare(&q, blob_str(&sql));
blob_reset(&sql);
print_timeline(&q, 1000, 0);
db_finalize(&q);
}
|
Changes to src/setup.c.
| ︙ | ︙ | |||
195 196 197 198 199 200 201 | } @ </table> @ </td><td class="usetupColumnLayout"> @ <span class="note">Notes:</span> @ <ol> @ <li><p>The permission flags are as follows:</p> @ <table> | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 |
}
@ </table>
@ </td><td class="usetupColumnLayout">
@ <span class="note">Notes:</span>
@ <ol>
@ <li><p>The permission flags are as follows:</p>
@ <table>
@ <tr><th valign="top">a</th>
@ <td><i>Admin:</i> Create and delete users</td></tr>
@ <tr><th valign="top">b</th>
@ <td><i>Attach:</i> Add attachments to wiki or tickets</td></tr>
@ <tr><th valign="top">c</th>
@ <td><i>Append-Tkt:</i> Append to tickets</td></tr>
@ <tr><th valign="top">d</th>
@ <td><i>Delete:</i> Delete wiki and tickets</td></tr>
@ <tr><th valign="top">e</th>
@ <td><i>Email:</i> View sensitive data such as EMail addresses</td></tr>
@ <tr><th valign="top">f</th>
@ <td><i>New-Wiki:</i> Create new wiki pages</td></tr>
@ <tr><th valign="top">g</th>
@ <td><i>Clone:</i> Clone the repository</td></tr>
@ <tr><th valign="top">h</th>
@ <td><i>Hyperlinks:</i> Show hyperlinks to detailed
@ repository history</td></tr>
@ <tr><th valign="top">i</th>
@ <td><i>Check-In:</i> Commit new versions in the repository</td></tr>
@ <tr><th valign="top">j</th>
@ <td><i>Read-Wiki:</i> View wiki pages</td></tr>
@ <tr><th valign="top">k</th>
@ <td><i>Write-Wiki:</i> Edit wiki pages</td></tr>
@ <tr><th valign="top">l</th>
@ <td><i>Mod-Wiki:</i> Moderator for wiki pages</td></tr>
@ <tr><th valign="top">m</th>
@ <td><i>Append-Wiki:</i> Append to wiki pages</td></tr>
@ <tr><th valign="top">n</th>
@ <td><i>New-Tkt:</i> Create new tickets</td></tr>
@ <tr><th valign="top">o</th>
@ <td><i>Check-Out:</i> Check out versions</td></tr>
@ <tr><th valign="top">p</th>
@ <td><i>Password:</i> Change your own password</td></tr>
@ <tr><th valign="top">q</th>
@ <td><i>Mod-Tkt:</i> Moderator for tickets</td></tr>
@ <tr><th valign="top">r</th>
@ <td><i>Read-Tkt:</i> View tickets</td></tr>
@ <tr><th valign="top">s</th>
@ <td><i>Setup/Super-user:</i> Setup and configure this website</td></tr>
@ <tr><th valign="top">t</th>
@ <td><i>Tkt-Report:</i> Create new bug summary reports</td></tr>
@ <tr><th valign="top">u</th>
@ <td><i>Reader:</i> Inherit privileges of
@ user <tt>reader</tt></td></tr>
@ <tr><th valign="top">v</th>
@ <td><i>Developer:</i> Inherit privileges of
@ user <tt>developer</tt></td></tr>
@ <tr><th valign="top">w</th>
@ <td><i>Write-Tkt:</i> Edit tickets</td></tr>
@ <tr><th valign="top">x</th>
@ <td><i>Private:</i> Push and/or pull private branches</td></tr>
@ <tr><th valign="top">z</th>
@ <td><i>Zip download:</i> Download a baseline via the
@ <tt>/zip</tt> URL even without
@ check<span class="capability">o</span>ut
@ and <span class="capability">h</span>istory permissions</td></tr>
@ </table>
@ </li>
@
|
| ︙ | ︙ | |||
1060 1061 1062 1063 1064 1065 1066 |
@ is not currently part of any login-group.
@ To join a login group, fill out the form below.</p>
@
@ <form action="%s(g.zTop)/setup_login_group" method="post"><div>
login_insert_csrf_secret();
@ <blockquote><table border="0">
@
| | | | | | 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 |
@ is not currently part of any login-group.
@ To join a login group, fill out the form below.</p>
@
@ <form action="%s(g.zTop)/setup_login_group" method="post"><div>
login_insert_csrf_secret();
@ <blockquote><table border="0">
@
@ <tr><th align="right">Repository filename in group to join:</th>
@ <td width="5"></td><td>
@ <input type="text" size="50" value="%h(zRepo)" name="repo"></td></tr>
@
@ <tr><th align="right">Login on the above repo:</th>
@ <td width="5"></td><td>
@ <input type="text" size="20" value="%h(zLogin)" name="login"></td></tr>
@
@ <tr><th align="right">Password:</th>
@ <td width="5"></td><td>
@ <input type="password" size="20" name="pw"></td></tr>
@
@ <tr><th align="right">Name of login-group:</th>
@ <td width="5"></td><td>
@ <input type="text" size="30" value="%h(zNewName)" name="newname">
@ (only used if creating a new login-group).</td></tr>
@
@ <tr><td colspan="3" align="center">
@ <input type="submit" value="Join" name="join"></td></tr>
@ </table></blockquote></div></form>
|
| ︙ | ︙ |
Changes to src/shell.c.
| ︙ | ︙ | |||
1717 1718 1719 1720 1721 1722 1723 |
}
if( (c==cSep && pc==cQuote)
|| (c=='\n' && pc==cQuote)
|| (c=='\n' && pc=='\r' && p->n>2 && p->z[p->n-2]==cQuote)
|| (c==EOF && pc==cQuote)
){
do{ p->n--; }while( p->z[p->n]!=cQuote );
| < < < > | 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 |
}
if( (c==cSep && pc==cQuote)
|| (c=='\n' && pc==cQuote)
|| (c=='\n' && pc=='\r' && p->n>2 && p->z[p->n-2]==cQuote)
|| (c==EOF && pc==cQuote)
){
do{ p->n--; }while( p->z[p->n]!=cQuote );
p->cTerm = c;
break;
}
if( pc==cQuote && c!='\r' ){
fprintf(stderr, "%s:%d: unescaped %c character\n",
p->zFile, p->nLine, cQuote);
}
if( c==EOF ){
fprintf(stderr, "%s:%d: unterminated %c-quoted field\n",
p->zFile, startLine, cQuote);
p->cTerm = EOF;
break;
}
csv_append_char(p, c);
pc = c;
}
}else{
while( c!=EOF && c!=cSep && c!='\n' ){
csv_append_char(p, c);
c = fgetc(p->in);
}
if( c=='\n' ){
p->nLine++;
if( p->n>1 && p->z[p->n-1]=='\r' ) p->n--;
}
p->cTerm = c;
}
if( p->z ) p->z[p->n] = 0;
return p->z;
}
/*
** If an input line begins with "." then invoke this routine to
** process that line.
**
|
| ︙ | ︙ |
Changes to src/shun.c.
| ︙ | ︙ | |||
291 292 293 294 295 296 297 |
db_prepare(&q,
"SELECT login, datetime(rcvfrom.mtime), rcvfrom.ipaddr"
" FROM rcvfrom LEFT JOIN user USING(uid)"
" WHERE rcvid=%d",
rcvid
);
@ <table cellspacing="15" cellpadding="0" border="0">
| | | | | | | 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 |
db_prepare(&q,
"SELECT login, datetime(rcvfrom.mtime), rcvfrom.ipaddr"
" FROM rcvfrom LEFT JOIN user USING(uid)"
" WHERE rcvid=%d",
rcvid
);
@ <table cellspacing="15" cellpadding="0" border="0">
@ <tr><th valign="top" align="right">rcvid:</th>
@ <td valign="top">%d(rcvid)</td></tr>
if( db_step(&q)==SQLITE_ROW ){
const char *zUser = db_column_text(&q, 0);
const char *zDate = db_column_text(&q, 1);
const char *zIpAddr = db_column_text(&q, 2);
@ <tr><th valign="top" align="right">User:</th>
@ <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,
"SELECT rid, uuid, size FROM blob WHERE rcvid=%d", rcvid
);
@ <tr><th valign="top" align="right">Artifacts:</th>
@ <td valign="top">
while( db_step(&q)==SQLITE_ROW ){
int rid = db_column_int(&q, 0);
const char *zUuid = db_column_text(&q, 1);
int size = db_column_int(&q, 2);
@ <a href="%s(g.zTop)/info/%s(zUuid)">%s(zUuid)</a>
@ (rid: %d(rid), size: %d(size))<br />
|
| ︙ | ︙ |
Changes to src/sqlite3.c.
| ︙ | ︙ | |||
668 669 670 671 672 673 674 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.8.0" #define SQLITE_VERSION_NUMBER 3008000 | | | 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.8.0" #define SQLITE_VERSION_NUMBER 3008000 #define SQLITE_SOURCE_ID "2013-07-18 14:50:56 5dcffa671f592ae9355628afa439ae9a2d26f0cd" /* ** 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 |
| ︙ | ︙ | |||
3118 3119 3120 3121 3122 3123 3124 | ** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback ** function X to be invoked periodically during long running calls to ** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for ** database connection D. An example use for this ** interface is to keep a GUI updated during a large query. ** ** ^The parameter P is passed through as the only parameter to the | | | 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 | ** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback ** function X to be invoked periodically during long running calls to ** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for ** database connection D. An example use for this ** interface is to keep a GUI updated during a large query. ** ** ^The parameter P is passed through as the only parameter to the ** callback function X. ^The parameter N is the approximate number of ** [virtual machine instructions] that are evaluated between successive ** invocations of the callback X. ** ** ^Only a single progress handler may be defined at one time per ** [database connection]; setting a new progress handler cancels the ** old one. ^Setting parameter X to NULL disables the progress handler. ** ^The progress handler is also disabled by setting N to a value less |
| ︙ | ︙ | |||
4743 4744 4745 4746 4747 4748 4749 | /* ** CAPI3REF: Function Auxiliary Data ** ** The following two functions may be used by scalar SQL functions to ** associate metadata with argument values. If the same value is passed to ** multiple invocations of the same SQL function during query execution, under | | | | < | | | > | | | > | > > | > > > > > > | | | 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 | /* ** CAPI3REF: Function Auxiliary Data ** ** The following two functions may be used by scalar SQL functions to ** associate metadata with argument values. If the same value is passed to ** multiple invocations of the same SQL function during query execution, under ** some circumstances the associated metadata may be preserved. This might ** be used, for example, in a regular-expression matching ** function. The compiled version of the regular expression is stored as ** metadata associated with the SQL value passed as the regular expression ** pattern. The compiled regular expression can be reused on multiple ** invocations of the same function so that the original pattern string ** does not need to be recompiled on each invocation. ** ** ^The sqlite3_get_auxdata() interface returns a pointer to the metadata ** associated by the sqlite3_set_auxdata() function with the Nth argument ** value to the application-defined function. ^If no metadata has been ever ** been set for the Nth argument of the function, or if the corresponding ** function parameter has changed since the meta-data was set, ** then sqlite3_get_auxdata() returns a NULL pointer. ** ** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th ** argument of the application-defined function. ^Subsequent ** calls to sqlite3_get_auxdata(C,N) return P from the most recent ** sqlite3_set_auxdata(C,N,P,X) call if the data has not been dropped, or ** NULL if the data has been dropped. ** ^(If it is not NULL, SQLite will invoke the destructor ** function X passed to sqlite3_set_auxdata(C,N,P,X) when <ul> ** <li> the corresponding function parameter changes, ** <li> [sqlite3_reset()] or [sqlite3_finalize()] is called for the ** SQL statement, ** <li> sqlite3_set_auxdata() is invoked again on the same parameter, or ** <li> a memory allocation error occurs. </ul>)^ ** ** SQLite is free to call the destructor and drop metadata on any ** parameter of any function at any time. ^The only guarantee is that ** the destructor will be called when the [prepared statement] is destroyed. ** Note in particular that the destructor X in the call to ** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before ** the sqlite3_set_auxdata() call even returns. Hence sqlite3_set_auxdata() ** should be called near the end of the function implementation and the ** implementation should not make any use of P after sqlite3_set_auxdata() ** has been called. ** ** ^(In practice, metadata is preserved between function calls for ** function parameters that are compile-time constants, including literal ** values and [parameters] and expressions composed from the same.)^ ** ** These routines must be called from the same thread in which ** the SQL function is running. */ SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); |
| ︙ | ︙ | |||
5687 5688 5689 5690 5691 5692 5693 | ** xEntryPoint() returns an error, the [sqlite3_open()], [sqlite3_open16()], ** or [sqlite3_open_v2()] call that provoked the xEntryPoint() will fail. ** ** ^Calling sqlite3_auto_extension(X) with an entry point X that is already ** on the list of automatic extensions is a harmless no-op. ^No entry point ** will be called more than once for each database connection that is opened. ** | | > > > > > > > > > > > > > | 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 | ** xEntryPoint() returns an error, the [sqlite3_open()], [sqlite3_open16()], ** or [sqlite3_open_v2()] call that provoked the xEntryPoint() will fail. ** ** ^Calling sqlite3_auto_extension(X) with an entry point X that is already ** on the list of automatic extensions is a harmless no-op. ^No entry point ** will be called more than once for each database connection that is opened. ** ** See also: [sqlite3_reset_auto_extension()] ** and [sqlite3_cancel_auto_extension()] */ SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void)); /* ** CAPI3REF: Cancel Automatic Extension Loading ** ** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the ** initialization routine X that was registered using a prior call to ** [sqlite3_auto_extension(X)]. ^The [sqlite3_cancel_auto_extension(X)] ** routine returns 1 if initialization routine X was successfully ** unregistered and it returns 0 if X was not on the list of initialization ** routines. */ SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void)); /* ** CAPI3REF: Reset Automatic Extension Loading ** ** ^This interface disables all automatic extensions previously ** registered using [sqlite3_auto_extension()]. */ SQLITE_API void sqlite3_reset_auto_extension(void); |
| ︙ | ︙ | |||
6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 | ** wal file in wal mode databases, or the number of pages written to the ** database file in rollback mode databases. Any pages written as part of ** transaction rollback or database recovery operations are not included. ** If an IO or other error occurs while writing a page to disk, the effect ** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. ** </dd> ** </dl> */ #define SQLITE_DBSTATUS_LOOKASIDE_USED 0 #define SQLITE_DBSTATUS_CACHE_USED 1 #define SQLITE_DBSTATUS_SCHEMA_USED 2 #define SQLITE_DBSTATUS_STMT_USED 3 #define SQLITE_DBSTATUS_LOOKASIDE_HIT 4 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 #define SQLITE_DBSTATUS_CACHE_HIT 7 #define SQLITE_DBSTATUS_CACHE_MISS 8 #define SQLITE_DBSTATUS_CACHE_WRITE 9 | > > > > > > > | | 6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857 6858 | ** wal file in wal mode databases, or the number of pages written to the ** database file in rollback mode databases. Any pages written as part of ** transaction rollback or database recovery operations are not included. ** If an IO or other error occurs while writing a page to disk, the effect ** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. ** </dd> ** ** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt> ** <dd>This parameter returns the zero for the current value if and only if ** there all foreign key constraints (deferred or immediate) have been ** resolved. The highwater mark is always 0. ** </dd> ** </dl> */ #define SQLITE_DBSTATUS_LOOKASIDE_USED 0 #define SQLITE_DBSTATUS_CACHE_USED 1 #define SQLITE_DBSTATUS_SCHEMA_USED 2 #define SQLITE_DBSTATUS_STMT_USED 3 #define SQLITE_DBSTATUS_LOOKASIDE_HIT 4 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 #define SQLITE_DBSTATUS_CACHE_HIT 7 #define SQLITE_DBSTATUS_CACHE_MISS 8 #define SQLITE_DBSTATUS_CACHE_WRITE 9 #define SQLITE_DBSTATUS_DEFERRED_FKS 10 #define SQLITE_DBSTATUS_MAX 10 /* Largest defined DBSTATUS */ /* ** CAPI3REF: Prepared Statement Status ** ** ^(Each prepared statement maintains various ** [SQLITE_STMTSTATUS counters] that measure the number |
| ︙ | ︙ | |||
10115 10116 10117 10118 10119 10120 10121 |
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
/* Access authorization function */
void *pAuthArg; /* 1st argument to the access auth function */
#endif
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
int (*xProgress)(void *); /* The progress callback */
void *pProgressArg; /* Argument to the progress callback */
| | > | 10144 10145 10146 10147 10148 10149 10150 10151 10152 10153 10154 10155 10156 10157 10158 10159 10160 10161 10162 10163 10164 10165 10166 10167 10168 10169 10170 10171 10172 10173 10174 10175 10176 |
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
/* Access authorization function */
void *pAuthArg; /* 1st argument to the access auth function */
#endif
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
int (*xProgress)(void *); /* The progress callback */
void *pProgressArg; /* Argument to the progress callback */
unsigned nProgressOps; /* Number of opcodes for progress callback */
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
int nVTrans; /* Allocated size of aVTrans */
Hash aModule; /* populated by sqlite3_create_module() */
VtabCtx *pVtabCtx; /* Context for active vtab connect/create */
VTable **aVTrans; /* Virtual tables with open transactions */
VTable *pDisconnect; /* Disconnect these in next sqlite3_prepare() */
#endif
FuncDefHash aFunc; /* Hash table of connection functions */
Hash aCollSeq; /* All collating sequences */
BusyHandler busyHandler; /* Busy callback */
Db aDbStatic[2]; /* Static space for the 2 default backends */
Savepoint *pSavepoint; /* List of active savepoints */
int busyTimeout; /* Busy handler timeout, in msec */
int nSavepoint; /* Number of non-transaction savepoints */
int nStatement; /* Number of nested statement-transactions */
i64 nDeferredCons; /* Net deferred constraints this transaction. */
i64 nDeferredImmCons; /* Net deferred immediate constraints */
int *pnBytesFreed; /* If not NULL, increment this in DbFree() */
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
/* The following variables are all protected by the STATIC_MASTER
** mutex, not by sqlite3.mutex. They are used by code in notify.c.
**
** When X.pUnlockConnection==Y, that means that X is waiting for Y to
|
| ︙ | ︙ | |||
10188 10189 10190 10191 10192 10193 10194 10195 10196 10197 10198 10199 10200 10201 | #define SQLITE_ReverseOrder 0x00010000 /* Reverse unordered SELECTs */ #define SQLITE_RecTriggers 0x00020000 /* Enable recursive triggers */ #define SQLITE_ForeignKeys 0x00040000 /* Enforce foreign key constraints */ #define SQLITE_AutoIndex 0x00080000 /* Enable automatic indexes */ #define SQLITE_PreferBuiltin 0x00100000 /* Preference to built-in funcs */ #define SQLITE_LoadExtension 0x00200000 /* Enable load_extension */ #define SQLITE_EnableTrigger 0x00400000 /* True to enable triggers */ /* ** Bits of the sqlite3.dbOptFlags field that are used by the ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to ** selectively disable various optimizations. */ #define SQLITE_QueryFlattener 0x0001 /* Query flattening */ | > > > | 10218 10219 10220 10221 10222 10223 10224 10225 10226 10227 10228 10229 10230 10231 10232 10233 10234 | #define SQLITE_ReverseOrder 0x00010000 /* Reverse unordered SELECTs */ #define SQLITE_RecTriggers 0x00020000 /* Enable recursive triggers */ #define SQLITE_ForeignKeys 0x00040000 /* Enforce foreign key constraints */ #define SQLITE_AutoIndex 0x00080000 /* Enable automatic indexes */ #define SQLITE_PreferBuiltin 0x00100000 /* Preference to built-in funcs */ #define SQLITE_LoadExtension 0x00200000 /* Enable load_extension */ #define SQLITE_EnableTrigger 0x00400000 /* True to enable triggers */ #define SQLITE_DeferFKs 0x00800000 /* Defer all FK constraints */ #define SQLITE_QueryOnly 0x01000000 /* Disable database changes */ /* ** Bits of the sqlite3.dbOptFlags field that are used by the ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to ** selectively disable various optimizations. */ #define SQLITE_QueryFlattener 0x0001 /* Query flattening */ |
| ︙ | ︙ | |||
10334 10335 10336 10337 10338 10339 10340 10341 10342 10343 10344 10345 10346 10347 |
** sqlite3.pSavepoint. The first element in the list is the most recently
** opened savepoint. Savepoints are added to the list by the vdbe
** OP_Savepoint instruction.
*/
struct Savepoint {
char *zName; /* Savepoint name (nul-terminated) */
i64 nDeferredCons; /* Number of deferred fk violations */
Savepoint *pNext; /* Parent savepoint (if any) */
};
/*
** The following are used as the second parameter to sqlite3Savepoint(),
** and as the P1 argument to the OP_Savepoint instruction.
*/
| > | 10367 10368 10369 10370 10371 10372 10373 10374 10375 10376 10377 10378 10379 10380 10381 |
** sqlite3.pSavepoint. The first element in the list is the most recently
** opened savepoint. Savepoints are added to the list by the vdbe
** OP_Savepoint instruction.
*/
struct Savepoint {
char *zName; /* Savepoint name (nul-terminated) */
i64 nDeferredCons; /* Number of deferred fk violations */
i64 nDeferredImmCons; /* Number of deferred imm fk. */
Savepoint *pNext; /* Parent savepoint (if any) */
};
/*
** The following are used as the second parameter to sqlite3Savepoint(),
** and as the P1 argument to the OP_Savepoint instruction.
*/
|
| ︙ | ︙ | |||
13528 13529 13530 13531 13532 13533 13534 13535 13536 13537 13538 13539 13540 13541 | int iStatement; /* Statement number (or 0 if has not opened stmt) */ int aCounter[4]; /* Counters used by sqlite3_stmt_status() */ #ifndef SQLITE_OMIT_TRACE i64 startTime; /* Time when query started - used for profiling */ #endif i64 nFkConstraint; /* Number of imm. FK constraints this VM */ i64 nStmtDefCons; /* Number of def. constraints when stmt started */ char *zSql; /* Text of the SQL statement that generated this */ void *pFree; /* Free this when deleting the vdbe */ #ifdef SQLITE_DEBUG FILE *trace; /* Write an execution trace here, if not NULL */ #endif #ifdef SQLITE_ENABLE_TREE_EXPLAIN Explain *pExplain; /* The explainer */ | > | 13562 13563 13564 13565 13566 13567 13568 13569 13570 13571 13572 13573 13574 13575 13576 | int iStatement; /* Statement number (or 0 if has not opened stmt) */ int aCounter[4]; /* Counters used by sqlite3_stmt_status() */ #ifndef SQLITE_OMIT_TRACE i64 startTime; /* Time when query started - used for profiling */ #endif i64 nFkConstraint; /* Number of imm. FK constraints this VM */ i64 nStmtDefCons; /* Number of def. constraints when stmt started */ i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */ char *zSql; /* Text of the SQL statement that generated this */ void *pFree; /* Free this when deleting the vdbe */ #ifdef SQLITE_DEBUG FILE *trace; /* Write an execution trace here, if not NULL */ #endif #ifdef SQLITE_ENABLE_TREE_EXPLAIN Explain *pExplain; /* The explainer */ |
| ︙ | ︙ | |||
13887 13888 13889 13890 13891 13892 13893 13894 13895 13896 13897 13898 13899 13900 |
sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet);
}
}
*pHighwater = 0;
*pCurrent = nRet;
break;
}
default: {
rc = SQLITE_ERROR;
}
}
sqlite3_mutex_leave(db->mutex);
return rc;
| > > > > > > > > > > | 13922 13923 13924 13925 13926 13927 13928 13929 13930 13931 13932 13933 13934 13935 13936 13937 13938 13939 13940 13941 13942 13943 13944 13945 |
sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet);
}
}
*pHighwater = 0;
*pCurrent = nRet;
break;
}
/* Set *pCurrent to non-zero if there are unresolved deferred foreign
** key constraints. Set *pCurrent to zero if all foreign key constraints
** have been satisfied. The *pHighwater is always set to zero.
*/
case SQLITE_DBSTATUS_DEFERRED_FKS: {
*pHighwater = 0;
*pCurrent = db->nDeferredImmCons>0 || db->nDeferredCons>0;
break;
}
default: {
rc = SQLITE_ERROR;
}
}
sqlite3_mutex_leave(db->mutex);
return rc;
|
| ︙ | ︙ | |||
61944 61945 61946 61947 61948 61949 61950 61951 61952 61953 61954 61955 61956 61957 61958 61959 61960 61961 61962 61963 61964 61965 61966 61967 61968 |
}
/* If the statement transaction is being rolled back, also restore the
** database handles deferred constraint counter to the value it had when
** the statement transaction was opened. */
if( eOp==SAVEPOINT_ROLLBACK ){
db->nDeferredCons = p->nStmtDefCons;
}
}
return rc;
}
/*
** This function is called when a transaction opened by the database
** handle associated with the VM passed as an argument is about to be
** committed. If there are outstanding deferred foreign key constraint
** violations, return SQLITE_ERROR. Otherwise, SQLITE_OK.
**
** If there are outstanding FK violations and this function returns
** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT_FOREIGNKEY
** and write an error message to it. Then return SQLITE_ERROR.
*/
#ifndef SQLITE_OMIT_FOREIGN_KEY
SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){
sqlite3 *db = p->db;
| > > | > | 61989 61990 61991 61992 61993 61994 61995 61996 61997 61998 61999 62000 62001 62002 62003 62004 62005 62006 62007 62008 62009 62010 62011 62012 62013 62014 62015 62016 62017 62018 62019 62020 62021 62022 62023 62024 |
}
/* If the statement transaction is being rolled back, also restore the
** database handles deferred constraint counter to the value it had when
** the statement transaction was opened. */
if( eOp==SAVEPOINT_ROLLBACK ){
db->nDeferredCons = p->nStmtDefCons;
db->nDeferredImmCons = p->nStmtDefImmCons;
}
}
return rc;
}
/*
** This function is called when a transaction opened by the database
** handle associated with the VM passed as an argument is about to be
** committed. If there are outstanding deferred foreign key constraint
** violations, return SQLITE_ERROR. Otherwise, SQLITE_OK.
**
** If there are outstanding FK violations and this function returns
** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT_FOREIGNKEY
** and write an error message to it. Then return SQLITE_ERROR.
*/
#ifndef SQLITE_OMIT_FOREIGN_KEY
SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){
sqlite3 *db = p->db;
if( (deferred && (db->nDeferredCons+db->nDeferredImmCons)>0)
|| (!deferred && p->nFkConstraint>0)
){
p->rc = SQLITE_CONSTRAINT_FOREIGNKEY;
p->errorAction = OE_Abort;
sqlite3SetString(&p->zErrMsg, db, "foreign key constraint failed");
return SQLITE_ERROR;
}
return SQLITE_OK;
}
|
| ︙ | ︙ | |||
62095 62096 62097 62098 62099 62100 62101 62102 62103 62104 62105 62106 62107 62108 |
sqlite3VdbeLeave(p);
return SQLITE_BUSY;
}else if( rc!=SQLITE_OK ){
p->rc = rc;
sqlite3RollbackAll(db, SQLITE_OK);
}else{
db->nDeferredCons = 0;
sqlite3CommitInternalChanges(db);
}
}else{
sqlite3RollbackAll(db, SQLITE_OK);
}
db->nStatement = 0;
}else if( eStatementOp==0 ){
| > > | 62143 62144 62145 62146 62147 62148 62149 62150 62151 62152 62153 62154 62155 62156 62157 62158 |
sqlite3VdbeLeave(p);
return SQLITE_BUSY;
}else if( rc!=SQLITE_OK ){
p->rc = rc;
sqlite3RollbackAll(db, SQLITE_OK);
}else{
db->nDeferredCons = 0;
db->nDeferredImmCons = 0;
db->flags &= ~SQLITE_DeferFKs;
sqlite3CommitInternalChanges(db);
}
}else{
sqlite3RollbackAll(db, SQLITE_OK);
}
db->nStatement = 0;
}else if( eStatementOp==0 ){
|
| ︙ | ︙ | |||
63534 63535 63536 63537 63538 63539 63540 |
** reset the interrupt flag. This prevents a call to sqlite3_interrupt
** from interrupting a statement that has not yet started.
*/
if( db->nVdbeActive==0 ){
db->u1.isInterrupted = 0;
}
| | > > | 63584 63585 63586 63587 63588 63589 63590 63591 63592 63593 63594 63595 63596 63597 63598 63599 63600 |
** reset the interrupt flag. This prevents a call to sqlite3_interrupt
** from interrupting a statement that has not yet started.
*/
if( db->nVdbeActive==0 ){
db->u1.isInterrupted = 0;
}
assert( db->nVdbeWrite>0 || db->autoCommit==0
|| (db->nDeferredCons==0 && db->nDeferredImmCons==0)
);
#ifndef SQLITE_OMIT_TRACE
if( db->xProfile && !db->init.busy ){
sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime);
}
#endif
|
| ︙ | ︙ | |||
65382 65383 65384 65385 65386 65387 65388 65389 | int pc=0; /* The program counter */ Op *aOp = p->aOp; /* Copy of p->aOp */ Op *pOp; /* Current operation */ int rc = SQLITE_OK; /* Value to return */ sqlite3 *db = p->db; /* The database */ u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ u8 encoding = ENC(db); /* The database encoding */ #ifndef SQLITE_OMIT_PROGRESS_CALLBACK | > > < | < < | 65434 65435 65436 65437 65438 65439 65440 65441 65442 65443 65444 65445 65446 65447 65448 65449 65450 65451 65452 | int pc=0; /* The program counter */ Op *aOp = p->aOp; /* Copy of p->aOp */ Op *pOp; /* Current operation */ int rc = SQLITE_OK; /* Value to return */ sqlite3 *db = p->db; /* The database */ u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ u8 encoding = ENC(db); /* The database encoding */ int iCompare = 0; /* Result of last OP_Compare operation */ unsigned nVmStep = 0; /* Number of virtual machine steps */ #ifndef SQLITE_OMIT_PROGRESS_CALLBACK unsigned nProgressOps = 0; /* nVmStep at last progress callback. */ #endif Mem *aMem = p->aMem; /* Copy of p->aMem */ Mem *pIn1 = 0; /* 1st input operand */ Mem *pIn2 = 0; /* 2nd input operand */ Mem *pIn3 = 0; /* 3rd input operand */ Mem *pOut = 0; /* Output operand */ int *aPermute = 0; /* Permutation of columns for OP_Compare */ i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */ |
| ︙ | ︙ | |||
65845 65846 65847 65848 65849 65850 65851 | assert( p->bIsReader || p->readOnly!=0 ); p->rc = SQLITE_OK; assert( p->explain==0 ); p->pResultSet = 0; db->busyHandler.nBusy = 0; CHECK_FOR_INTERRUPT; sqlite3VdbeIOTraceSql(p); | < < < | 65896 65897 65898 65899 65900 65901 65902 65903 65904 65905 65906 65907 65908 65909 |
assert( p->bIsReader || p->readOnly!=0 );
p->rc = SQLITE_OK;
assert( p->explain==0 );
p->pResultSet = 0;
db->busyHandler.nBusy = 0;
CHECK_FOR_INTERRUPT;
sqlite3VdbeIOTraceSql(p);
#ifdef SQLITE_DEBUG
sqlite3BeginBenignMalloc();
if( p->pc==0 && (p->db->flags & SQLITE_VdbeListing)!=0 ){
int i;
printf("VDBE Program Listing:\n");
sqlite3VdbePrintSql(p);
for(i=0; i<p->nOp; i++){
|
| ︙ | ︙ | |||
65893 65894 65895 65896 65897 65898 65899 |
#ifdef SQLITE_TEST
if( sqlite3_interrupt_count>0 ){
sqlite3_interrupt_count--;
if( sqlite3_interrupt_count==0 ){
sqlite3_interrupt(db);
}
}
| < < < < < < < < < < < < < < < < < < < < < | 65941 65942 65943 65944 65945 65946 65947 65948 65949 65950 65951 65952 65953 65954 |
#ifdef SQLITE_TEST
if( sqlite3_interrupt_count>0 ){
sqlite3_interrupt_count--;
if( sqlite3_interrupt_count==0 ){
sqlite3_interrupt(db);
}
}
#endif
/* On any opcode with the "out2-prerelease" tag, free any
** external allocations out of mem[p2] and set mem[p2] to be
** an undefined integer. Opcodes will either fill in the integer
** value or convert mem[p2] to a different type.
*/
|
| ︙ | ︙ | |||
66008 66009 66010 66011 66012 66013 66014 66015 |
**
** An unconditional jump to address P2.
** The next instruction executed will be
** the one at index P2 from the beginning of
** the program.
*/
case OP_Goto: { /* jump */
CHECK_FOR_INTERRUPT;
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 66035 66036 66037 66038 66039 66040 66041 66042 66043 66044 66045 66046 66047 66048 66049 66050 66051 66052 66053 66054 66055 66056 66057 66058 66059 66060 66061 66062 66063 66064 66065 66066 66067 66068 66069 66070 66071 66072 66073 66074 66075 66076 66077 66078 66079 66080 |
**
** An unconditional jump to address P2.
** The next instruction executed will be
** the one at index P2 from the beginning of
** the program.
*/
case OP_Goto: { /* jump */
pc = pOp->p2 - 1;
/* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev,
** OP_VNext, OP_RowSetNext, or OP_SorterNext) all jump here upon
** completion. Check to see if sqlite3_interrupt() has been called
** or if the progress callback needs to be invoked.
**
** This code uses unstructured "goto" statements and does not look clean.
** But that is not due to sloppy coding habits. The code is written this
** way for performance, to avoid having to run the interrupt and progress
** checks on every opcode. This helps sqlite3_step() to run about 1.5%
** faster according to "valgrind --tool=cachegrind" */
check_for_interrupt:
CHECK_FOR_INTERRUPT;
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/* Call the progress callback if it is configured and the required number
** of VDBE ops have been executed (either since this invocation of
** sqlite3VdbeExec() or since last time the progress callback was called).
** If the progress callback returns non-zero, exit the virtual machine with
** a return code SQLITE_ABORT.
*/
if( db->xProgress!=0 && (nVmStep - nProgressOps)>=db->nProgressOps ){
int prc;
prc = db->xProgress(db->pProgressArg);
if( prc!=0 ){
rc = SQLITE_INTERRUPT;
goto vdbe_error_halt;
}
nProgressOps = nVmStep;
}
#endif
break;
}
/* Opcode: Gosub P1 P2 * * *
**
** Write the current address onto register P1
** and then jump to address P2.
|
| ︙ | ︙ | |||
66130 66131 66132 66133 66134 66135 66136 |
}
rc = sqlite3VdbeHalt(p);
assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
if( rc==SQLITE_BUSY ){
p->rc = rc = SQLITE_BUSY;
}else{
assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT );
| | | 66187 66188 66189 66190 66191 66192 66193 66194 66195 66196 66197 66198 66199 66200 66201 |
}
rc = sqlite3VdbeHalt(p);
assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
if( rc==SQLITE_BUSY ){
p->rc = rc = SQLITE_BUSY;
}else{
assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT );
assert( rc==SQLITE_OK || db->nDeferredCons>0 || db->nDeferredImmCons>0 );
rc = p->rc ? SQLITE_ERROR : SQLITE_DONE;
}
goto vdbe_return;
}
/* Opcode: Integer P1 P2 * * *
**
|
| ︙ | ︙ | |||
68026 68027 68028 68029 68030 68031 68032 68033 68034 68035 68036 68037 68038 68039 |
db->nSavepoint++;
}
/* Link the new savepoint into the database handle's list. */
u.as.pNew->pNext = db->pSavepoint;
db->pSavepoint = u.as.pNew;
u.as.pNew->nDeferredCons = db->nDeferredCons;
}
}
}else{
u.as.iSavepoint = 0;
/* Find the named savepoint. If there is no such savepoint, then an
** an error is returned to the user. */
| > | 68083 68084 68085 68086 68087 68088 68089 68090 68091 68092 68093 68094 68095 68096 68097 |
db->nSavepoint++;
}
/* Link the new savepoint into the database handle's list. */
u.as.pNew->pNext = db->pSavepoint;
db->pSavepoint = u.as.pNew;
u.as.pNew->nDeferredCons = db->nDeferredCons;
u.as.pNew->nDeferredImmCons = db->nDeferredImmCons;
}
}
}else{
u.as.iSavepoint = 0;
/* Find the named savepoint. If there is no such savepoint, then an
** an error is returned to the user. */
|
| ︙ | ︙ | |||
68113 68114 68115 68116 68117 68118 68119 68120 68121 68122 68123 68124 68125 68126 |
db->pSavepoint = u.as.pSavepoint->pNext;
sqlite3DbFree(db, u.as.pSavepoint);
if( !isTransaction ){
db->nSavepoint--;
}
}else{
db->nDeferredCons = u.as.pSavepoint->nDeferredCons;
}
if( !isTransaction ){
rc = sqlite3VtabSavepoint(db, u.as.p1, u.as.iSavepoint);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
}
}
| > | 68171 68172 68173 68174 68175 68176 68177 68178 68179 68180 68181 68182 68183 68184 68185 |
db->pSavepoint = u.as.pSavepoint->pNext;
sqlite3DbFree(db, u.as.pSavepoint);
if( !isTransaction ){
db->nSavepoint--;
}
}else{
db->nDeferredCons = u.as.pSavepoint->nDeferredCons;
db->nDeferredImmCons = u.as.pSavepoint->nDeferredImmCons;
}
if( !isTransaction ){
rc = sqlite3VtabSavepoint(db, u.as.p1, u.as.iSavepoint);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
}
}
|
| ︙ | ︙ | |||
68242 68243 68244 68245 68246 68247 68248 68249 68250 68251 68252 68253 68254 68255 |
Btree *pBt;
#endif /* local variables moved into u.au */
assert( p->bIsReader );
assert( p->readOnly==0 || pOp->p2==0 );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
u.au.pBt = db->aDb[pOp->p1].pBt;
if( u.au.pBt ){
rc = sqlite3BtreeBeginTrans(u.au.pBt, pOp->p2);
if( rc==SQLITE_BUSY ){
p->pc = pc;
p->rc = rc = SQLITE_BUSY;
| > > > > | 68301 68302 68303 68304 68305 68306 68307 68308 68309 68310 68311 68312 68313 68314 68315 68316 68317 68318 |
Btree *pBt;
#endif /* local variables moved into u.au */
assert( p->bIsReader );
assert( p->readOnly==0 || pOp->p2==0 );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){
rc = SQLITE_READONLY;
goto abort_due_to_error;
}
u.au.pBt = db->aDb[pOp->p1].pBt;
if( u.au.pBt ){
rc = sqlite3BtreeBeginTrans(u.au.pBt, pOp->p2);
if( rc==SQLITE_BUSY ){
p->pc = pc;
p->rc = rc = SQLITE_BUSY;
|
| ︙ | ︙ | |||
68274 68275 68276 68277 68278 68279 68280 68281 68282 68283 68284 68285 68286 68287 |
rc = sqlite3BtreeBeginStmt(u.au.pBt, p->iStatement);
}
/* Store the current value of the database handles deferred constraint
** counter. If the statement transaction needs to be rolled back,
** the value of this counter needs to be restored too. */
p->nStmtDefCons = db->nDeferredCons;
}
}
break;
}
/* Opcode: ReadCookie P1 P2 P3 * *
**
| > | 68337 68338 68339 68340 68341 68342 68343 68344 68345 68346 68347 68348 68349 68350 68351 |
rc = sqlite3BtreeBeginStmt(u.au.pBt, p->iStatement);
}
/* Store the current value of the database handles deferred constraint
** counter. If the statement transaction needs to be rolled back,
** the value of this counter needs to be restored too. */
p->nStmtDefCons = db->nDeferredCons;
p->nStmtDefImmCons = db->nDeferredImmCons;
}
}
break;
}
/* Opcode: ReadCookie P1 P2 P3 * *
**
|
| ︙ | ︙ | |||
69849 69850 69851 69852 69853 69854 69855 |
case OP_Prev: /* jump */
case OP_Next: { /* jump */
#if 0 /* local variables moved into u.br */
VdbeCursor *pC;
int res;
#endif /* local variables moved into u.br */
| < | 69913 69914 69915 69916 69917 69918 69919 69920 69921 69922 69923 69924 69925 69926 |
case OP_Prev: /* jump */
case OP_Next: { /* jump */
#if 0 /* local variables moved into u.br */
VdbeCursor *pC;
int res;
#endif /* local variables moved into u.br */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p5<=ArraySize(p->aCounter) );
u.br.pC = p->apCsr[pOp->p1];
if( u.br.pC==0 ){
break; /* See ticket #2273 */
}
assert( u.br.pC->isSorter==(pOp->opcode==OP_SorterNext) );
|
| ︙ | ︙ | |||
69878 69879 69880 69881 69882 69883 69884 |
pc = pOp->p2 - 1;
if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
}
u.br.pC->rowidIsValid = 0;
| | | 69941 69942 69943 69944 69945 69946 69947 69948 69949 69950 69951 69952 69953 69954 69955 |
pc = pOp->p2 - 1;
if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
}
u.br.pC->rowidIsValid = 0;
goto check_for_interrupt;
}
/* Opcode: IdxInsert P1 P2 P3 * P5
**
** Register P2 holds an SQL index key made using the
** MakeRecord instructions. This opcode writes that key
** into the index P1. Data for the entry is nil.
|
| ︙ | ︙ | |||
70424 70425 70426 70427 70428 70429 70430 |
** register P3. Or, if boolean index P1 is initially empty, leave P3
** unchanged and jump to instruction P2.
*/
case OP_RowSetRead: { /* jump, in1, out3 */
#if 0 /* local variables moved into u.cb */
i64 val;
#endif /* local variables moved into u.cb */
| | | | 70487 70488 70489 70490 70491 70492 70493 70494 70495 70496 70497 70498 70499 70500 70501 70502 70503 70504 70505 70506 70507 70508 70509 70510 70511 70512 70513 |
** register P3. Or, if boolean index P1 is initially empty, leave P3
** unchanged and jump to instruction P2.
*/
case OP_RowSetRead: { /* jump, in1, out3 */
#if 0 /* local variables moved into u.cb */
i64 val;
#endif /* local variables moved into u.cb */
pIn1 = &aMem[pOp->p1];
if( (pIn1->flags & MEM_RowSet)==0
|| sqlite3RowSetNext(pIn1->u.pRowSet, &u.cb.val)==0
){
/* The boolean index is empty */
sqlite3VdbeMemSetNull(pIn1);
pc = pOp->p2 - 1;
}else{
/* A value was pulled from the index */
sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.cb.val);
}
goto check_for_interrupt;
}
/* Opcode: RowSetTest P1 P2 P3 P4
**
** Register P3 is assumed to hold a 64-bit integer value. If register P1
** contains a RowSet object and that RowSet object contains
** the value held in P3, jump to register P2. Otherwise, insert the
|
| ︙ | ︙ | |||
70656 70657 70658 70659 70660 70661 70662 |
**
** Increment a "constraint counter" by P2 (P2 may be negative or positive).
** If P1 is non-zero, the database constraint counter is incremented
** (deferred foreign key constraints). Otherwise, if P1 is zero, the
** statement counter is incremented (immediate foreign key constraints).
*/
case OP_FkCounter: {
| > > | | | | 70719 70720 70721 70722 70723 70724 70725 70726 70727 70728 70729 70730 70731 70732 70733 70734 70735 70736 70737 70738 70739 70740 70741 70742 70743 70744 70745 70746 70747 70748 70749 70750 70751 70752 70753 70754 70755 70756 70757 70758 |
**
** Increment a "constraint counter" by P2 (P2 may be negative or positive).
** If P1 is non-zero, the database constraint counter is incremented
** (deferred foreign key constraints). Otherwise, if P1 is zero, the
** statement counter is incremented (immediate foreign key constraints).
*/
case OP_FkCounter: {
if( db->flags & SQLITE_DeferFKs ){
db->nDeferredImmCons += pOp->p2;
}else if( pOp->p1 ){
db->nDeferredCons += pOp->p2;
}else{
p->nFkConstraint += pOp->p2;
}
break;
}
/* Opcode: FkIfZero P1 P2 * * *
**
** This opcode tests if a foreign key constraint-counter is currently zero.
** If so, jump to instruction P2. Otherwise, fall through to the next
** instruction.
**
** If P1 is non-zero, then the jump is taken if the database constraint-counter
** is zero (the one that counts deferred constraint violations). If P1 is
** zero, the jump is taken if the statement constraint-counter is zero
** (immediate foreign key constraint violations).
*/
case OP_FkIfZero: { /* jump */
if( pOp->p1 ){
if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1;
}else{
if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1;
}
break;
}
#endif /* #ifndef SQLITE_OMIT_FOREIGN_KEY */
#ifndef SQLITE_OMIT_AUTOINCREMENT
/* Opcode: MemMax P1 P2 * * *
|
| ︙ | ︙ | |||
71365 71366 71367 71368 71369 71370 71371 |
u.cp.res = u.cp.pModule->xEof(u.cp.pCur->pVtabCursor);
}
if( !u.cp.res ){
/* If there is data, jump to P2 */
pc = pOp->p2 - 1;
}
| | | 71430 71431 71432 71433 71434 71435 71436 71437 71438 71439 71440 71441 71442 71443 71444 |
u.cp.res = u.cp.pModule->xEof(u.cp.pCur->pVtabCursor);
}
if( !u.cp.res ){
/* If there is data, jump to P2 */
pc = pOp->p2 - 1;
}
goto check_for_interrupt;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VRename P1 * * P4 *
**
** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
|
| ︙ | ︙ | |||
89260 89261 89262 89263 89264 89265 89266 |
sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0);
sqlite3ReleaseTempReg(pParse, regRec);
sqlite3ReleaseTempRange(pParse, regTemp, nCol);
}
}
| > > | > | 89325 89326 89327 89328 89329 89330 89331 89332 89333 89334 89335 89336 89337 89338 89339 89340 89341 89342 |
sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0);
sqlite3ReleaseTempReg(pParse, regRec);
sqlite3ReleaseTempRange(pParse, regTemp, nCol);
}
}
if( !pFKey->isDeferred && !(pParse->db->flags & SQLITE_DeferFKs)
&& !pParse->pToplevel
&& !pParse->isMultiWrite
){
/* Special case: If this is an INSERT statement that will insert exactly
** one row into the table, raise a constraint immediately instead of
** incrementing a counter. This is necessary as the VM code is being
** generated for will not open a statement transaction. */
assert( nIncr==1 );
sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
OE_Abort, "foreign key constraint failed", P4_STATIC
|
| ︙ | ︙ | |||
89651 89652 89653 89654 89655 89656 89657 |
/* Loop through all the foreign key constraints that refer to this table */
for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){
Index *pIdx = 0; /* Foreign key index for pFKey */
SrcList *pSrc;
int *aiCol = 0;
| > | > | 89719 89720 89721 89722 89723 89724 89725 89726 89727 89728 89729 89730 89731 89732 89733 89734 89735 |
/* Loop through all the foreign key constraints that refer to this table */
for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){
Index *pIdx = 0; /* Foreign key index for pFKey */
SrcList *pSrc;
int *aiCol = 0;
if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs)
&& !pParse->pToplevel && !pParse->isMultiWrite
){
assert( regOld==0 && regNew!=0 );
/* Inserting a single row into a parent table cannot cause an immediate
** foreign key violation. So do nothing in this case. */
continue;
}
if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
|
| ︙ | ︙ | |||
92613 92614 92615 92616 92617 92618 92619 92620 92621 92622 92623 92624 92625 92626 92627 92628 92629 92630 92631 | #endif /* SQLITE_CORE */ #ifndef SQLITE_CORE /* This case when the file really is being compiled as a loadable ** extension */ # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; # define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; #else /* This case when the file is being statically linked into the ** application */ # define SQLITE_EXTENSION_INIT1 /*no-op*/ # define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */ #endif #endif /* _SQLITE3EXT_H_ */ /************** End of sqlite3ext.h ******************************************/ /************** Continuing where we left off in loadext.c ********************/ /* #include <string.h> */ | > > > | 92683 92684 92685 92686 92687 92688 92689 92690 92691 92692 92693 92694 92695 92696 92697 92698 92699 92700 92701 92702 92703 92704 |
#endif /* SQLITE_CORE */
#ifndef SQLITE_CORE
/* This case when the file really is being compiled as a loadable
** extension */
# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0;
# define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v;
# define SQLITE_EXTENSION_INIT3 \
extern const sqlite3_api_routines *sqlite3_api;
#else
/* This case when the file is being statically linked into the
** application */
# define SQLITE_EXTENSION_INIT1 /*no-op*/
# define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */
# define SQLITE_EXTENSION_INIT3 /*no-op*/
#endif
#endif /* _SQLITE3EXT_H_ */
/************** End of sqlite3ext.h ******************************************/
/************** Continuing where we left off in loadext.c ********************/
/* #include <string.h> */
|
| ︙ | ︙ | |||
93273 93274 93275 93276 93277 93278 93279 93280 93281 93282 93283 93284 93285 93286 |
}
}
sqlite3_mutex_leave(mutex);
assert( (rc&0xff)==rc );
return rc;
}
}
/*
** Reset the automatic extension loading mechanism.
*/
SQLITE_API void sqlite3_reset_auto_extension(void){
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize()==SQLITE_OK )
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 93346 93347 93348 93349 93350 93351 93352 93353 93354 93355 93356 93357 93358 93359 93360 93361 93362 93363 93364 93365 93366 93367 93368 93369 93370 93371 93372 93373 93374 93375 93376 93377 93378 93379 93380 93381 93382 93383 93384 93385 93386 93387 93388 |
}
}
sqlite3_mutex_leave(mutex);
assert( (rc&0xff)==rc );
return rc;
}
}
/*
** Cancel a prior call to sqlite3_auto_extension. Remove xInit from the
** set of routines that is invoked for each new database connection, if it
** is currently on the list. If xInit is not on the list, then this
** routine is a no-op.
**
** Return 1 if xInit was found on the list and removed. Return 0 if xInit
** was not on the list.
*/
SQLITE_API int sqlite3_cancel_auto_extension(void (*xInit)(void)){
#if SQLITE_THREADSAFE
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
int i;
int n = 0;
wsdAutoextInit;
sqlite3_mutex_enter(mutex);
for(i=wsdAutoext.nExt-1; i>=0; i--){
if( wsdAutoext.aExt[i]==xInit ){
wsdAutoext.nExt--;
wsdAutoext.aExt[i] = wsdAutoext.aExt[wsdAutoext.nExt];
n++;
break;
}
}
sqlite3_mutex_leave(mutex);
return n;
}
/*
** Reset the automatic extension loading mechanism.
*/
SQLITE_API void sqlite3_reset_auto_extension(void){
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize()==SQLITE_OK )
|
| ︙ | ︙ | |||
93514 93515 93516 93517 93518 93519 93520 93521 93522 93523 93524 93525 93526 93527 93528 93529 93530 93531 93532 93533 93534 93535 93536 93537 93538 93539 93540 |
{ "short_column_names", SQLITE_ShortColNames },
{ "count_changes", SQLITE_CountRows },
{ "empty_result_callbacks", SQLITE_NullCallback },
{ "legacy_file_format", SQLITE_LegacyFileFmt },
{ "fullfsync", SQLITE_FullFSync },
{ "checkpoint_fullfsync", SQLITE_CkptFullFSync },
{ "reverse_unordered_selects", SQLITE_ReverseOrder },
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
{ "automatic_index", SQLITE_AutoIndex },
#endif
#ifdef SQLITE_DEBUG
{ "sql_trace", SQLITE_SqlTrace },
{ "vdbe_listing", SQLITE_VdbeListing },
{ "vdbe_trace", SQLITE_VdbeTrace },
{ "vdbe_addoptrace", SQLITE_VdbeAddopTrace},
{ "vdbe_debug", SQLITE_SqlTrace | SQLITE_VdbeListing
| SQLITE_VdbeTrace },
#endif
#ifndef SQLITE_OMIT_CHECK
{ "ignore_check_constraints", SQLITE_IgnoreChecks },
#endif
/* The following is VERY experimental */
{ "writable_schema", SQLITE_WriteSchema|SQLITE_RecoveryMode },
/* TODO: Maybe it shouldn't be possible to change the ReadUncommitted
** flag if there are any active statements. */
{ "read_uncommitted", SQLITE_ReadUncommitted },
| > | | > | 93616 93617 93618 93619 93620 93621 93622 93623 93624 93625 93626 93627 93628 93629 93630 93631 93632 93633 93634 93635 93636 93637 93638 93639 93640 93641 93642 93643 93644 93645 93646 93647 93648 93649 93650 93651 93652 93653 93654 93655 93656 93657 |
{ "short_column_names", SQLITE_ShortColNames },
{ "count_changes", SQLITE_CountRows },
{ "empty_result_callbacks", SQLITE_NullCallback },
{ "legacy_file_format", SQLITE_LegacyFileFmt },
{ "fullfsync", SQLITE_FullFSync },
{ "checkpoint_fullfsync", SQLITE_CkptFullFSync },
{ "reverse_unordered_selects", SQLITE_ReverseOrder },
{ "query_only", SQLITE_QueryOnly },
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
{ "automatic_index", SQLITE_AutoIndex },
#endif
#ifdef SQLITE_DEBUG
{ "sql_trace", SQLITE_SqlTrace },
{ "vdbe_listing", SQLITE_VdbeListing },
{ "vdbe_trace", SQLITE_VdbeTrace },
{ "vdbe_addoptrace", SQLITE_VdbeAddopTrace},
{ "vdbe_debug", SQLITE_SqlTrace | SQLITE_VdbeListing
| SQLITE_VdbeTrace },
#endif
#ifndef SQLITE_OMIT_CHECK
{ "ignore_check_constraints", SQLITE_IgnoreChecks },
#endif
/* The following is VERY experimental */
{ "writable_schema", SQLITE_WriteSchema|SQLITE_RecoveryMode },
/* TODO: Maybe it shouldn't be possible to change the ReadUncommitted
** flag if there are any active statements. */
{ "read_uncommitted", SQLITE_ReadUncommitted },
{ "recursive_triggers", SQLITE_RecTriggers },
/* This flag may only be set if both foreign-key and trigger support
** are present in the build. */
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
{ "foreign_keys", SQLITE_ForeignKeys },
{ "defer_foreign_keys", SQLITE_DeferFKs },
#endif
};
int i;
const struct sPragmaType *p;
for(i=0, p=aPragma; i<ArraySize(aPragma); i++, p++){
if( sqlite3StrICmp(zLeft, p->zName)==0 ){
sqlite3 *db = pParse->db;
|
| ︙ | ︙ | |||
93565 93566 93567 93568 93569 93570 93571 93572 93573 93574 93575 93576 93577 93578 |
mask &= ~(SQLITE_ForeignKeys);
}
if( sqlite3GetBoolean(zRight, 0) ){
db->flags |= mask;
}else{
db->flags &= ~mask;
}
/* Many of the flag-pragmas modify the code generated by the SQL
** compiler (eg. count_changes). So add an opcode to expire all
** compiled SQL statements after modifying a pragma value.
*/
sqlite3VdbeAddOp2(v, OP_Expire, 0, 0);
| > | 93669 93670 93671 93672 93673 93674 93675 93676 93677 93678 93679 93680 93681 93682 93683 |
mask &= ~(SQLITE_ForeignKeys);
}
if( sqlite3GetBoolean(zRight, 0) ){
db->flags |= mask;
}else{
db->flags &= ~mask;
if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0;
}
/* Many of the flag-pragmas modify the code generated by the SQL
** compiler (eg. count_changes). So add an opcode to expire all
** compiled SQL statements after modifying a pragma value.
*/
sqlite3VdbeAddOp2(v, OP_Expire, 0, 0);
|
| ︙ | ︙ | |||
95977 95978 95979 95980 95981 95982 95983 95984 95985 95986 95987 95988 95989 95990 |
const char *zTail8 = 0;
int rc = SQLITE_OK;
assert( ppStmt );
*ppStmt = 0;
if( !sqlite3SafetyCheckOk(db) ){
return SQLITE_MISUSE_BKPT;
}
sqlite3_mutex_enter(db->mutex);
zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE);
if( zSql8 ){
rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, 0, ppStmt, &zTail8);
}
| > > > > > > | 96082 96083 96084 96085 96086 96087 96088 96089 96090 96091 96092 96093 96094 96095 96096 96097 96098 96099 96100 96101 |
const char *zTail8 = 0;
int rc = SQLITE_OK;
assert( ppStmt );
*ppStmt = 0;
if( !sqlite3SafetyCheckOk(db) ){
return SQLITE_MISUSE_BKPT;
}
if( nBytes>=0 ){
int sz;
const char *z = (const char*)zSql;
for(sz=0; sz<nBytes && (z[sz]!=0 || z[sz+1]!=0); sz += 2){}
nBytes = sz;
}
sqlite3_mutex_enter(db->mutex);
zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE);
if( zSql8 ){
rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, 0, ppStmt, &zTail8);
}
|
| ︙ | ︙ | |||
104068 104069 104070 104071 104072 104073 104074 |
db->aVTrans = 0;
for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
int (*x)(sqlite3_vtab *);
sqlite3_vtab *pVtab = aVTrans[i]->pVtab;
if( pVtab && (x = pVtab->pModule->xSync)!=0 ){
rc = x(pVtab);
sqlite3DbFree(db, *pzErrmsg);
| | | | 104179 104180 104181 104182 104183 104184 104185 104186 104187 104188 104189 104190 104191 104192 104193 104194 |
db->aVTrans = 0;
for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
int (*x)(sqlite3_vtab *);
sqlite3_vtab *pVtab = aVTrans[i]->pVtab;
if( pVtab && (x = pVtab->pModule->xSync)!=0 ){
rc = x(pVtab);
sqlite3DbFree(db, *pzErrmsg);
*pzErrmsg = pVtab->zErrMsg;
pVtab->zErrMsg = 0;
}
}
db->aVTrans = aVTrans;
return rc;
}
/*
|
| ︙ | ︙ | |||
104389 104390 104391 104392 104393 104394 104395 104396 104397 104398 104399 104400 104401 104402 | typedef struct WhereAndInfo WhereAndInfo; typedef struct WhereLevel WhereLevel; typedef struct WhereLoop WhereLoop; typedef struct WherePath WherePath; typedef struct WhereTerm WhereTerm; typedef struct WhereLoopBuilder WhereLoopBuilder; typedef struct WhereScan WhereScan; /* ** Cost X is tracked as 10*log2(X) stored in a 16-bit integer. The ** maximum cost for ordinary tables is 64*(2**63) which becomes 6900. ** (Virtual tables can return a larger cost, but let's assume they do not.) ** So all costs can be stored in a 16-bit unsigned integer without risk ** of overflow. | > > | 104500 104501 104502 104503 104504 104505 104506 104507 104508 104509 104510 104511 104512 104513 104514 104515 | typedef struct WhereAndInfo WhereAndInfo; typedef struct WhereLevel WhereLevel; typedef struct WhereLoop WhereLoop; typedef struct WherePath WherePath; typedef struct WhereTerm WhereTerm; typedef struct WhereLoopBuilder WhereLoopBuilder; typedef struct WhereScan WhereScan; typedef struct WhereOrCost WhereOrCost; typedef struct WhereOrSet WhereOrSet; /* ** Cost X is tracked as 10*log2(X) stored in a 16-bit integer. The ** maximum cost for ordinary tables is 64*(2**63) which becomes 6900. ** (Virtual tables can return a larger cost, but let's assume they do not.) ** So all costs can be stored in a 16-bit unsigned integer without risk ** of overflow. |
| ︙ | ︙ | |||
104495 104496 104497 104498 104499 104500 104501 104502 104503 104504 104505 104506 104507 104508 | /**** whereLoopXfer() copies fields above ***********************/ # define WHERE_LOOP_XFER_SZ offsetof(WhereLoop,nLSlot) u16 nLSlot; /* Number of slots allocated for aLTerm[] */ WhereTerm **aLTerm; /* WhereTerms used */ WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */ WhereTerm *aLTermSpace[4]; /* Initial aLTerm[] space */ }; /* Forward declaration of methods */ static int whereLoopResize(sqlite3*, WhereLoop*, int); /* ** Each instance of this object holds a sequence of WhereLoop objects ** that implement some or all of a query plan. | > > > > > > > > > > > > > > > > > > > > > | 104608 104609 104610 104611 104612 104613 104614 104615 104616 104617 104618 104619 104620 104621 104622 104623 104624 104625 104626 104627 104628 104629 104630 104631 104632 104633 104634 104635 104636 104637 104638 104639 104640 104641 104642 |
/**** whereLoopXfer() copies fields above ***********************/
# define WHERE_LOOP_XFER_SZ offsetof(WhereLoop,nLSlot)
u16 nLSlot; /* Number of slots allocated for aLTerm[] */
WhereTerm **aLTerm; /* WhereTerms used */
WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */
WhereTerm *aLTermSpace[4]; /* Initial aLTerm[] space */
};
/* This object holds the prerequisites and the cost of running a
** subquery on one operand of an OR operator in the WHERE clause.
** See WhereOrSet for additional information
*/
struct WhereOrCost {
Bitmask prereq; /* Prerequisites */
WhereCost rRun; /* Cost of running this subquery */
WhereCost nOut; /* Number of outputs for this subquery */
};
/* The WhereOrSet object holds a set of possible WhereOrCosts that
** correspond to the subquery(s) of OR-clause processing. At most
** favorable N_OR_COST elements are retained.
*/
#define N_OR_COST 3
struct WhereOrSet {
u16 n; /* Number of valid a[] entries */
WhereOrCost a[N_OR_COST]; /* Set of best costs */
};
/* Forward declaration of methods */
static int whereLoopResize(sqlite3*, WhereLoop*, int);
/*
** Each instance of this object holds a sequence of WhereLoop objects
** that implement some or all of a query plan.
|
| ︙ | ︙ | |||
104710 104711 104712 104713 104714 104715 104716 |
** to construct WhereLoop objects for a particular query.
*/
struct WhereLoopBuilder {
WhereInfo *pWInfo; /* Information about this WHERE */
WhereClause *pWC; /* WHERE clause terms */
ExprList *pOrderBy; /* ORDER BY clause */
WhereLoop *pNew; /* Template WhereLoop */
| | | 104844 104845 104846 104847 104848 104849 104850 104851 104852 104853 104854 104855 104856 104857 104858 |
** to construct WhereLoop objects for a particular query.
*/
struct WhereLoopBuilder {
WhereInfo *pWInfo; /* Information about this WHERE */
WhereClause *pWC; /* WHERE clause terms */
ExprList *pOrderBy; /* ORDER BY clause */
WhereLoop *pNew; /* Template WhereLoop */
WhereOrSet *pOrSet; /* Record best loops here, if not NULL */
};
/*
** The WHERE clause processing routine has two halves. The
** first part does the start of the WHERE loop and the second
** half does the tail of the WHERE loop. An instance of
** this structure is returned by the first half and passed
|
| ︙ | ︙ | |||
104852 104853 104854 104855 104856 104857 104858 104859 104860 104861 104862 104863 104864 104865 |
** Return TRUE if an UPDATE or DELETE statement can operate directly on
** the rowids returned by a WHERE clause. Return FALSE if doing an
** UPDATE or DELETE might change subsequent WHERE clause results.
*/
SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo *pWInfo){
return pWInfo->okOnePass;
}
/*
** Initialize a preallocated WhereClause structure.
*/
static void whereClauseInit(
WhereClause *pWC, /* The WhereClause to be initialized */
WhereInfo *pWInfo /* The WHERE processing context */
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 104986 104987 104988 104989 104990 104991 104992 104993 104994 104995 104996 104997 104998 104999 105000 105001 105002 105003 105004 105005 105006 105007 105008 105009 105010 105011 105012 105013 105014 105015 105016 105017 105018 105019 105020 105021 105022 105023 105024 105025 105026 105027 105028 105029 105030 105031 105032 105033 105034 105035 105036 105037 105038 105039 105040 105041 105042 105043 105044 105045 105046 105047 |
** Return TRUE if an UPDATE or DELETE statement can operate directly on
** the rowids returned by a WHERE clause. Return FALSE if doing an
** UPDATE or DELETE might change subsequent WHERE clause results.
*/
SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo *pWInfo){
return pWInfo->okOnePass;
}
/*
** Move the content of pSrc into pDest
*/
static void whereOrMove(WhereOrSet *pDest, WhereOrSet *pSrc){
pDest->n = pSrc->n;
memcpy(pDest->a, pSrc->a, pDest->n*sizeof(pDest->a[0]));
}
/*
** Try to insert a new prerequisite/cost entry into the WhereOrSet pSet.
**
** The new entry might overwrite an existing entry, or it might be
** appended, or it might be discarded. Do whatever is the right thing
** so that pSet keeps the N_OR_COST best entries seen so far.
*/
static int whereOrInsert(
WhereOrSet *pSet, /* The WhereOrSet to be updated */
Bitmask prereq, /* Prerequisites of the new entry */
WhereCost rRun, /* Run-cost of the new entry */
WhereCost nOut /* Number of outputs for the new entry */
){
u16 i;
WhereOrCost *p;
for(i=pSet->n, p=pSet->a; i>0; i--, p++){
if( rRun<=p->rRun && (prereq & p->prereq)==prereq ){
goto whereOrInsert_done;
}
if( p->rRun<=rRun && (p->prereq & prereq)==p->prereq ){
return 0;
}
}
if( pSet->n<N_OR_COST ){
p = &pSet->a[pSet->n++];
p->nOut = nOut;
}else{
p = pSet->a;
for(i=1; i<pSet->n; i++){
if( p->rRun>pSet->a[i].rRun ) p = pSet->a + i;
}
if( p->rRun<=rRun ) return 0;
}
whereOrInsert_done:
p->prereq = prereq;
p->rRun = rRun;
if( p->nOut>nOut ) p->nOut = nOut;
return 1;
}
/*
** Initialize a preallocated WhereClause structure.
*/
static void whereClauseInit(
WhereClause *pWC, /* The WhereClause to be initialized */
WhereInfo *pWInfo /* The WHERE processing context */
|
| ︙ | ︙ | |||
108087 108088 108089 108090 108091 108092 108093 108094 |
** is not contained in the ON clause of a LEFT JOIN.
** See ticket http://www.sqlite.org/src/info/f2369304e4
*/
if( pWC->nTerm>1 ){
int iTerm;
for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
Expr *pExpr = pWC->a[iTerm].pExpr;
if( ExprHasProperty(pExpr, EP_FromJoin) ) continue;
| > | | 108269 108270 108271 108272 108273 108274 108275 108276 108277 108278 108279 108280 108281 108282 108283 108284 108285 |
** is not contained in the ON clause of a LEFT JOIN.
** See ticket http://www.sqlite.org/src/info/f2369304e4
*/
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_ORINFO) ) continue;
if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
pAndExpr = sqlite3ExprAnd(pParse->db, pAndExpr, pExpr);
}
if( pAndExpr ){
pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0);
}
|
| ︙ | ︙ | |||
108416 108417 108418 108419 108420 108421 108422 | ** ** An existing WhereLoop entry might be overwritten if the new template ** is better and has fewer dependencies. Or the template will be ignored ** and no insert will occur if an existing WhereLoop is faster and has ** fewer dependencies than the template. Otherwise a new WhereLoop is ** added based on the template. ** | | | | | | | < | < > > | > | < | | < < < < < < < | < | 108599 108600 108601 108602 108603 108604 108605 108606 108607 108608 108609 108610 108611 108612 108613 108614 108615 108616 108617 108618 108619 108620 108621 108622 108623 108624 108625 108626 108627 108628 108629 108630 108631 108632 108633 108634 108635 108636 108637 108638 108639 108640 108641 108642 108643 108644 108645 108646 108647 108648 108649 108650 |
**
** An existing WhereLoop entry might be overwritten if the new template
** is better and has fewer dependencies. Or the template will be ignored
** and no insert will occur if an existing WhereLoop is faster and has
** fewer dependencies than the template. Otherwise a new WhereLoop is
** added based on the template.
**
** If pBuilder->pOrSet is not NULL then we only care about only the
** prerequisites and rRun and nOut costs of the N best loops. That
** information is gathered in the pBuilder->pOrSet object. This special
** processing mode is used only for OR clause processing.
**
** When accumulating multiple loops (when pBuilder->pOrSet is NULL) we
** still might overwrite similar loops with the new template if the
** template is better. Loops may be overwritten if the following
** conditions are met:
**
** (1) They have the same iTab.
** (2) They have the same iSortIdx.
** (3) The template has same or fewer dependencies than the current loop
** (4) The template has the same or lower cost than the current loop
** (5) The template uses more terms of the same index but has no additional
** dependencies
*/
static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
WhereLoop **ppPrev, *p, *pNext = 0;
WhereInfo *pWInfo = pBuilder->pWInfo;
sqlite3 *db = pWInfo->pParse->db;
/* If pBuilder->pOrSet is defined, then only keep track of the costs
** and prereqs.
*/
if( pBuilder->pOrSet!=0 ){
#if WHERETRACE_ENABLED
u16 n = pBuilder->pOrSet->n;
int x =
#endif
whereOrInsert(pBuilder->pOrSet, pTemplate->prereq, pTemplate->rRun,
pTemplate->nOut);
#if WHERETRACE_ENABLED
if( sqlite3WhereTrace & 0x8 ){
sqlite3DebugPrintf(x?" or-%d: ":" or-X: ", n);
whereLoopPrint(pTemplate, pWInfo->pTabList);
}
#endif
return SQLITE_OK;
}
/* Search for an existing WhereLoop to overwrite, or which takes
** priority over pTemplate.
*/
for(ppPrev=&pWInfo->pLoops, p=*ppPrev; p; ppPrev=&p->pNextLoop, p=*ppPrev){
|
| ︙ | ︙ | |||
108555 108556 108557 108558 108559 108560 108561 |
}
return SQLITE_OK;
/* Jump here if the insert is a no-op */
whereLoopInsert_noop:
#if WHERETRACE_ENABLED
if( sqlite3WhereTrace & 0x8 ){
| | | 108730 108731 108732 108733 108734 108735 108736 108737 108738 108739 108740 108741 108742 108743 108744 |
}
return SQLITE_OK;
/* Jump here if the insert is a no-op */
whereLoopInsert_noop:
#if WHERETRACE_ENABLED
if( sqlite3WhereTrace & 0x8 ){
sqlite3DebugPrintf("ins-noop: ");
whereLoopPrint(pTemplate, pWInfo->pTabList);
}
#endif
return SQLITE_OK;
}
/*
|
| ︙ | ︙ | |||
108837 108838 108839 108840 108841 108842 108843 |
}
pProbe = &sPk;
}
rSize = whereCost(pSrc->pTab->nRowEst);
rLogSize = estLog(rSize);
/* Automatic indexes */
| | | 109012 109013 109014 109015 109016 109017 109018 109019 109020 109021 109022 109023 109024 109025 109026 |
}
pProbe = &sPk;
}
rSize = whereCost(pSrc->pTab->nRowEst);
rLogSize = estLog(rSize);
/* Automatic indexes */
if( !pBuilder->pOrSet
&& (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0
&& pSrc->pIndex==0
&& !pSrc->viaCoroutine
&& !pSrc->notIndexed
&& !pSrc->isCorrelated
){
/* Generate auto-index WhereLoops */
|
| ︙ | ︙ | |||
109123 109124 109125 109126 109127 109128 109129 | WhereClause *pWC; WhereLoop *pNew; WhereTerm *pTerm, *pWCEnd; int rc = SQLITE_OK; int iCur; WhereClause tempWC; WhereLoopBuilder sSubBuild; | | | | < < | < < | > < | > > | > > > | > > > > > | | < | < < > > > | | | | > > > | | | < < | 109298 109299 109300 109301 109302 109303 109304 109305 109306 109307 109308 109309 109310 109311 109312 109313 109314 109315 109316 109317 109318 109319 109320 109321 109322 109323 109324 109325 109326 109327 109328 109329 109330 109331 109332 109333 109334 109335 109336 109337 109338 109339 109340 109341 109342 109343 109344 109345 109346 109347 109348 109349 109350 109351 109352 109353 109354 109355 109356 109357 109358 109359 109360 109361 109362 109363 109364 109365 109366 109367 109368 109369 109370 109371 109372 109373 109374 109375 109376 109377 109378 109379 109380 109381 109382 109383 109384 109385 109386 109387 109388 109389 109390 |
WhereClause *pWC;
WhereLoop *pNew;
WhereTerm *pTerm, *pWCEnd;
int rc = SQLITE_OK;
int iCur;
WhereClause tempWC;
WhereLoopBuilder sSubBuild;
WhereOrSet sSum, sCur, sPrev;
struct SrcList_item *pItem;
pWC = pBuilder->pWC;
if( pWInfo->wctrlFlags & WHERE_AND_ONLY ) return SQLITE_OK;
pWCEnd = pWC->a + pWC->nTerm;
pNew = pBuilder->pNew;
for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
if( (pTerm->eOperator & WO_OR)!=0
&& (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0
){
WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
WhereTerm *pOrTerm;
int once = 1;
int i, j;
pItem = pWInfo->pTabList->a + pNew->iTab;
iCur = pItem->iCursor;
sSubBuild = *pBuilder;
sSubBuild.pOrderBy = 0;
sSubBuild.pOrSet = &sCur;
for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
if( (pOrTerm->eOperator & WO_AND)!=0 ){
sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc;
}else if( pOrTerm->leftCursor==iCur ){
tempWC.pWInfo = pWC->pWInfo;
tempWC.pOuter = pWC;
tempWC.op = TK_AND;
tempWC.nTerm = 1;
tempWC.a = pOrTerm;
sSubBuild.pWC = &tempWC;
}else{
continue;
}
sCur.n = 0;
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pItem->pTab) ){
rc = whereLoopAddVirtual(&sSubBuild);
for(i=0; i<sCur.n; i++) sCur.a[i].prereq |= mExtra;
}else
#endif
{
rc = whereLoopAddBtree(&sSubBuild, mExtra);
}
assert( rc==SQLITE_OK || sCur.n==0 );
if( sCur.n==0 ){
sSum.n = 0;
break;
}else if( once ){
whereOrMove(&sSum, &sCur);
once = 0;
}else{
whereOrMove(&sPrev, &sSum);
sSum.n = 0;
for(i=0; i<sPrev.n; i++){
for(j=0; j<sCur.n; j++){
whereOrInsert(&sSum, sPrev.a[i].prereq | sCur.a[j].prereq,
whereCostAdd(sPrev.a[i].rRun, sCur.a[j].rRun),
whereCostAdd(sPrev.a[i].nOut, sCur.a[j].nOut));
}
}
}
}
pNew->nLTerm = 1;
pNew->aLTerm[0] = pTerm;
pNew->wsFlags = WHERE_MULTI_OR;
pNew->rSetup = 0;
pNew->iSortIdx = 0;
memset(&pNew->u, 0, sizeof(pNew->u));
for(i=0; rc==SQLITE_OK && i<sSum.n; i++){
/* TUNING: Multiple by 3.5 for the secondary table lookup */
pNew->rRun = sSum.a[i].rRun + 18;
pNew->nOut = sSum.a[i].nOut;
pNew->prereq = sSum.a[i].prereq;
rc = whereLoopInsert(pBuilder, pNew);
}
}
}
return rc;
}
/*
** Add all WhereLoop objects for all tables
|
| ︙ | ︙ | |||
110001 110002 110003 110004 110005 110006 110007 | pWInfo->pResultSet = pResultSet; pWInfo->iBreak = sqlite3VdbeMakeLabel(v); pWInfo->wctrlFlags = wctrlFlags; pWInfo->savedNQueryLoop = pParse->nQueryLoop; pMaskSet = &pWInfo->sMaskSet; sWLB.pWInfo = pWInfo; sWLB.pWC = &pWInfo->sWC; | | > | 110183 110184 110185 110186 110187 110188 110189 110190 110191 110192 110193 110194 110195 110196 110197 110198 | pWInfo->pResultSet = pResultSet; pWInfo->iBreak = sqlite3VdbeMakeLabel(v); pWInfo->wctrlFlags = wctrlFlags; pWInfo->savedNQueryLoop = pParse->nQueryLoop; pMaskSet = &pWInfo->sMaskSet; sWLB.pWInfo = pWInfo; sWLB.pWC = &pWInfo->sWC; sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo); assert( EIGHT_BYTE_ALIGNMENT(sWLB.pNew) ); whereLoopInit(sWLB.pNew); #ifdef SQLITE_DEBUG sWLB.pNew->cId = '*'; #endif /* Split the WHERE clause into separate subexpressions where each ** subexpression is separated by an AND operator. |
| ︙ | ︙ | |||
116125 116126 116127 116128 116129 116130 116131 116132 116133 116134 116135 116136 116137 116138 |
sqlite3ExpirePreparedStatements(db);
sqlite3ResetAllSchemasOfConnection(db);
}
sqlite3BtreeLeaveAll(db);
/* Any deferred constraint violations have now been resolved. */
db->nDeferredCons = 0;
/* If one has been configured, invoke the rollback-hook callback */
if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){
db->xRollbackCallback(db->pRollbackArg);
}
}
| > > | 116308 116309 116310 116311 116312 116313 116314 116315 116316 116317 116318 116319 116320 116321 116322 116323 |
sqlite3ExpirePreparedStatements(db);
sqlite3ResetAllSchemasOfConnection(db);
}
sqlite3BtreeLeaveAll(db);
/* Any deferred constraint violations have now been resolved. */
db->nDeferredCons = 0;
db->nDeferredImmCons = 0;
db->flags &= ~SQLITE_DeferFKs;
/* If one has been configured, invoke the rollback-hook callback */
if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){
db->xRollbackCallback(db->pRollbackArg);
}
}
|
| ︙ | ︙ | |||
116386 116387 116388 116389 116390 116391 116392 |
int nOps,
int (*xProgress)(void*),
void *pArg
){
sqlite3_mutex_enter(db->mutex);
if( nOps>0 ){
db->xProgress = xProgress;
| | | 116571 116572 116573 116574 116575 116576 116577 116578 116579 116580 116581 116582 116583 116584 116585 |
int nOps,
int (*xProgress)(void*),
void *pArg
){
sqlite3_mutex_enter(db->mutex);
if( nOps>0 ){
db->xProgress = xProgress;
db->nProgressOps = (unsigned)nOps;
db->pProgressArg = pArg;
}else{
db->xProgress = 0;
db->nProgressOps = 0;
db->pProgressArg = 0;
}
sqlite3_mutex_leave(db->mutex);
|
| ︙ | ︙ | |||
119085 119086 119087 119088 119089 119090 119091 | # define SQLITE_ENABLE_FTS3 #endif #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* If not building as part of the core, include sqlite3ext.h. */ #ifndef SQLITE_CORE | | | 119270 119271 119272 119273 119274 119275 119276 119277 119278 119279 119280 119281 119282 119283 119284 | # define SQLITE_ENABLE_FTS3 #endif #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* If not building as part of the core, include sqlite3ext.h. */ #ifndef SQLITE_CORE SQLITE_EXTENSION_INIT3 #endif /************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/ /************** Begin file fts3_tokenizer.h **********************************/ /* ** 2006 July 10 ** |
| ︙ | ︙ | |||
124993 124994 124995 124996 124997 124998 124999 | } #endif #if !SQLITE_CORE /* ** Initialize API pointer table, if required. */ | > > > | | 125178 125179 125180 125181 125182 125183 125184 125185 125186 125187 125188 125189 125190 125191 125192 125193 125194 125195 |
}
#endif
#if !SQLITE_CORE
/*
** Initialize API pointer table, if required.
*/
#ifdef _WIN32
__declspec(dllexport)
#endif
SQLITE_API int sqlite3_fts3_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
SQLITE_EXTENSION_INIT2(pApi)
return sqlite3Fts3Init(db);
}
|
| ︙ | ︙ | |||
140040 140041 140042 140043 140044 140045 140046 |
** the context object when it is no longer required. */
return sqlite3_create_function_v2(db, zGeom, -1, SQLITE_ANY,
(void *)pGeomCtx, geomCallback, 0, 0, doSqlite3Free
);
}
#if !SQLITE_CORE
| > > > | | 140228 140229 140230 140231 140232 140233 140234 140235 140236 140237 140238 140239 140240 140241 140242 140243 140244 140245 |
** the context object when it is no longer required. */
return sqlite3_create_function_v2(db, zGeom, -1, SQLITE_ANY,
(void *)pGeomCtx, geomCallback, 0, 0, doSqlite3Free
);
}
#if !SQLITE_CORE
#ifdef _WIN32
__declspec(dllexport)
#endif
SQLITE_API int sqlite3_rtree_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
SQLITE_EXTENSION_INIT2(pApi)
return sqlite3RtreeInit(db);
}
|
| ︙ | ︙ | |||
140542 140543 140544 140545 140546 140547 140548 |
);
}
return rc;
}
#if !SQLITE_CORE
| > > > | | 140733 140734 140735 140736 140737 140738 140739 140740 140741 140742 140743 140744 140745 140746 140747 140748 140749 140750 |
);
}
return rc;
}
#if !SQLITE_CORE
#ifdef _WIN32
__declspec(dllexport)
#endif
SQLITE_API int sqlite3_icu_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
SQLITE_EXTENSION_INIT2(pApi)
return sqlite3IcuInit(db);
}
|
| ︙ | ︙ |
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.0" #define SQLITE_VERSION_NUMBER 3008000 | | | 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.0" #define SQLITE_VERSION_NUMBER 3008000 #define SQLITE_SOURCE_ID "2013-07-18 14:50:56 5dcffa671f592ae9355628afa439ae9a2d26f0cd" /* ** 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 |
| ︙ | ︙ | |||
2555 2556 2557 2558 2559 2560 2561 | ** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback ** function X to be invoked periodically during long running calls to ** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for ** database connection D. An example use for this ** interface is to keep a GUI updated during a large query. ** ** ^The parameter P is passed through as the only parameter to the | | | 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 | ** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback ** function X to be invoked periodically during long running calls to ** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for ** database connection D. An example use for this ** interface is to keep a GUI updated during a large query. ** ** ^The parameter P is passed through as the only parameter to the ** callback function X. ^The parameter N is the approximate number of ** [virtual machine instructions] that are evaluated between successive ** invocations of the callback X. ** ** ^Only a single progress handler may be defined at one time per ** [database connection]; setting a new progress handler cancels the ** old one. ^Setting parameter X to NULL disables the progress handler. ** ^The progress handler is also disabled by setting N to a value less |
| ︙ | ︙ | |||
4180 4181 4182 4183 4184 4185 4186 | /* ** CAPI3REF: Function Auxiliary Data ** ** The following two functions may be used by scalar SQL functions to ** associate metadata with argument values. If the same value is passed to ** multiple invocations of the same SQL function during query execution, under | | | | < | | | > | | | > | > > | > > > > > > | | | 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 | /* ** CAPI3REF: Function Auxiliary Data ** ** The following two functions may be used by scalar SQL functions to ** associate metadata with argument values. If the same value is passed to ** multiple invocations of the same SQL function during query execution, under ** some circumstances the associated metadata may be preserved. This might ** be used, for example, in a regular-expression matching ** function. The compiled version of the regular expression is stored as ** metadata associated with the SQL value passed as the regular expression ** pattern. The compiled regular expression can be reused on multiple ** invocations of the same function so that the original pattern string ** does not need to be recompiled on each invocation. ** ** ^The sqlite3_get_auxdata() interface returns a pointer to the metadata ** associated by the sqlite3_set_auxdata() function with the Nth argument ** value to the application-defined function. ^If no metadata has been ever ** been set for the Nth argument of the function, or if the corresponding ** function parameter has changed since the meta-data was set, ** then sqlite3_get_auxdata() returns a NULL pointer. ** ** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th ** argument of the application-defined function. ^Subsequent ** calls to sqlite3_get_auxdata(C,N) return P from the most recent ** sqlite3_set_auxdata(C,N,P,X) call if the data has not been dropped, or ** NULL if the data has been dropped. ** ^(If it is not NULL, SQLite will invoke the destructor ** function X passed to sqlite3_set_auxdata(C,N,P,X) when <ul> ** <li> the corresponding function parameter changes, ** <li> [sqlite3_reset()] or [sqlite3_finalize()] is called for the ** SQL statement, ** <li> sqlite3_set_auxdata() is invoked again on the same parameter, or ** <li> a memory allocation error occurs. </ul>)^ ** ** SQLite is free to call the destructor and drop metadata on any ** parameter of any function at any time. ^The only guarantee is that ** the destructor will be called when the [prepared statement] is destroyed. ** Note in particular that the destructor X in the call to ** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before ** the sqlite3_set_auxdata() call even returns. Hence sqlite3_set_auxdata() ** should be called near the end of the function implementation and the ** implementation should not make any use of P after sqlite3_set_auxdata() ** has been called. ** ** ^(In practice, metadata is preserved between function calls for ** function parameters that are compile-time constants, including literal ** values and [parameters] and expressions composed from the same.)^ ** ** These routines must be called from the same thread in which ** the SQL function is running. */ SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); |
| ︙ | ︙ | |||
5124 5125 5126 5127 5128 5129 5130 | ** xEntryPoint() returns an error, the [sqlite3_open()], [sqlite3_open16()], ** or [sqlite3_open_v2()] call that provoked the xEntryPoint() will fail. ** ** ^Calling sqlite3_auto_extension(X) with an entry point X that is already ** on the list of automatic extensions is a harmless no-op. ^No entry point ** will be called more than once for each database connection that is opened. ** | | > > > > > > > > > > > > > | 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 | ** xEntryPoint() returns an error, the [sqlite3_open()], [sqlite3_open16()], ** or [sqlite3_open_v2()] call that provoked the xEntryPoint() will fail. ** ** ^Calling sqlite3_auto_extension(X) with an entry point X that is already ** on the list of automatic extensions is a harmless no-op. ^No entry point ** will be called more than once for each database connection that is opened. ** ** See also: [sqlite3_reset_auto_extension()] ** and [sqlite3_cancel_auto_extension()] */ SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void)); /* ** CAPI3REF: Cancel Automatic Extension Loading ** ** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the ** initialization routine X that was registered using a prior call to ** [sqlite3_auto_extension(X)]. ^The [sqlite3_cancel_auto_extension(X)] ** routine returns 1 if initialization routine X was successfully ** unregistered and it returns 0 if X was not on the list of initialization ** routines. */ SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void)); /* ** CAPI3REF: Reset Automatic Extension Loading ** ** ^This interface disables all automatic extensions previously ** registered using [sqlite3_auto_extension()]. */ SQLITE_API void sqlite3_reset_auto_extension(void); |
| ︙ | ︙ | |||
6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 | ** wal file in wal mode databases, or the number of pages written to the ** database file in rollback mode databases. Any pages written as part of ** transaction rollback or database recovery operations are not included. ** If an IO or other error occurs while writing a page to disk, the effect ** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. ** </dd> ** </dl> */ #define SQLITE_DBSTATUS_LOOKASIDE_USED 0 #define SQLITE_DBSTATUS_CACHE_USED 1 #define SQLITE_DBSTATUS_SCHEMA_USED 2 #define SQLITE_DBSTATUS_STMT_USED 3 #define SQLITE_DBSTATUS_LOOKASIDE_HIT 4 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 #define SQLITE_DBSTATUS_CACHE_HIT 7 #define SQLITE_DBSTATUS_CACHE_MISS 8 #define SQLITE_DBSTATUS_CACHE_WRITE 9 | > > > > > > > | | 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 | ** wal file in wal mode databases, or the number of pages written to the ** database file in rollback mode databases. Any pages written as part of ** transaction rollback or database recovery operations are not included. ** If an IO or other error occurs while writing a page to disk, the effect ** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. ** </dd> ** ** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt> ** <dd>This parameter returns the zero for the current value if and only if ** there all foreign key constraints (deferred or immediate) have been ** resolved. The highwater mark is always 0. ** </dd> ** </dl> */ #define SQLITE_DBSTATUS_LOOKASIDE_USED 0 #define SQLITE_DBSTATUS_CACHE_USED 1 #define SQLITE_DBSTATUS_SCHEMA_USED 2 #define SQLITE_DBSTATUS_STMT_USED 3 #define SQLITE_DBSTATUS_LOOKASIDE_HIT 4 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5 #define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 #define SQLITE_DBSTATUS_CACHE_HIT 7 #define SQLITE_DBSTATUS_CACHE_MISS 8 #define SQLITE_DBSTATUS_CACHE_WRITE 9 #define SQLITE_DBSTATUS_DEFERRED_FKS 10 #define SQLITE_DBSTATUS_MAX 10 /* Largest defined DBSTATUS */ /* ** CAPI3REF: Prepared Statement Status ** ** ^(Each prepared statement maintains various ** [SQLITE_STMTSTATUS counters] that measure the number |
| ︙ | ︙ |
Changes to src/style.c.
| ︙ | ︙ | |||
460 461 462 463 464 465 466 | @ </div> @ </body></html> ; /* ** The default Cascading Style Sheet. ** It's assembled by different strings for each class. | | | 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 |
@ </div>
@ </body></html>
;
/*
** The default Cascading Style Sheet.
** It's assembled by different strings for each class.
** The default css contains all definitions.
** The style sheet, send to the client only contains the ones,
** not defined in the user defined css.
*/
const char zDefaultCSS[] =
@ /* General settings for the entire page */
@ body {
@ margin: 0ex 1ex;
|
| ︙ | ︙ | |||
963 964 965 966 967 968 969 |
@ color: red;
},
{ "ul.filelist",
"List of files in a timeline",
@ margin-top: 3px;
@ line-height: 100%;
},
| | | > | > > > > > > > > > > > | > | | | > > | > > > | > > > > > > > | 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 |
@ color: red;
},
{ "ul.filelist",
"List of files in a timeline",
@ margin-top: 3px;
@ line-height: 100%;
},
{ "table.sbsdiffcols",
"side-by-side diff display (column-based)",
@ border-spacing: 0;
@ font-size: xx-small;
},
{ "table.sbsdiffcols td",
"sbs diff table cell",
@ padding: 0;
@ vertical-align: top;
},
{ "table.sbsdiffcols pre",
"sbs diff pre block",
@ margin: 0;
@ padding: 0;
@ border: 0;
@ font-size: inherit;
@ background: inherit;
@ color: inherit;
},
{ "div.difflncol",
"diff line number column",
@ padding-right: 1em;
@ text-align: right;
@ color: #a0a0a0;
},
{ "div.difftxtcol",
"diff text column",
@ width: 45em;
@ overflow-x: auto;
},
{ "div.diffmkrcol",
"diff marker column",
@ padding: 0 1em;
},
{ "span.diffchng",
"changes in a diff",
@ background-color: #c0c0ff;
},
{ "span.diffadd",
"added code in a diff",
@ background-color: #c0ffc0;
},
{ "span.diffrm",
"deleted in a diff",
@ background-color: #ffc8c8;
},
{ "span.diffhr",
"suppressed lines in a diff",
@ display: inline-block;
@ margin: .5em 0 1em;
@ color: #0000ff;
},
{ "span.diffln",
"line numbers in a diff",
@ color: #a0a0a0;
},
{ "span.modpending",
|
| ︙ | ︙ | |||
1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 |
{ ".statistics-report-table-events td",
"",
@ padding: 0.1em 1em 0.1em 1em;
},
{ ".statistics-report-row-year",
"",
@ text-align: left;
},
{ "tr.row0",
"even table row color",
@ /* use default */
},
{ "tr.row1",
"odd table row color",
| > > > > > > > > > > > > > | 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 |
{ ".statistics-report-table-events td",
"",
@ padding: 0.1em 1em 0.1em 1em;
},
{ ".statistics-report-row-year",
"",
@ text-align: left;
},
{ ".statistics-report-graph-line",
"for the /stats_report views",
@ background-color: #446979;
},
{ ".statistics-report-week-number-label",
"for the /stats_report views",
@ text-align: right;
@ font-size: 0.8em;
},
{ ".statistics-report-week-of-year-list",
"for the /stats_report views",
@ font-size: 0.8em;
},
{ "tr.row0",
"even table row color",
@ /* use default */
},
{ "tr.row1",
"odd table row color",
|
| ︙ | ︙ |
Changes to src/timeline.c.
| ︙ | ︙ | |||
1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 |
const char *zBefore = P("b"); /* Events before this time */
const char *zCirca = P("c"); /* Events near this time */
const char *zTagName = P("t"); /* Show events with this tag */
const char *zBrName = P("r"); /* Show events related to this tag */
const char *zSearch = P("s"); /* Search string */
const char *zUses = P("uf"); /* Only show checkins hold this file */
const char *zYearMonth = P("ym"); /* Show checkins for the given YYYY-MM */
int useDividers = P("nd")==0; /* Show dividers if "nd" is missing */
int renameOnly = P("namechng")!=0; /* Show only checkins that rename files */
int tagid; /* Tag ID */
int tmFlags; /* Timeline flags */
const char *zThisTag = 0; /* Suppress links to this tag */
const char *zThisUser = 0; /* Suppress links to this user */
HQuery url; /* URL for various branch links */
| > | 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 |
const char *zBefore = P("b"); /* Events before this time */
const char *zCirca = P("c"); /* Events near this time */
const char *zTagName = P("t"); /* Show events with this tag */
const char *zBrName = P("r"); /* Show events related to this tag */
const char *zSearch = P("s"); /* Search string */
const char *zUses = P("uf"); /* Only show checkins hold this file */
const char *zYearMonth = P("ym"); /* Show checkins for the given YYYY-MM */
const char *zYearWeek = P("yw"); /* Show checkins for the given YYYY-WW (weak-of-year) */
int useDividers = P("nd")==0; /* Show dividers if "nd" is missing */
int renameOnly = P("namechng")!=0; /* Show only checkins that rename files */
int tagid; /* Tag ID */
int tmFlags; /* Timeline flags */
const char *zThisTag = 0; /* Suppress links to this tag */
const char *zThisUser = 0; /* Suppress links to this user */
HQuery url; /* URL for various branch links */
|
| ︙ | ︙ | |||
1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 |
if( renameOnly ){
blob_appendf(&sql, " AND event.objid IN rnfile ");
}
if( zYearMonth ){
blob_appendf(&sql, " AND %Q=strftime('%%Y-%%m',event.mtime) ",
zYearMonth);
}
if( tagid>0 ){
blob_appendf(&sql,
"AND (EXISTS(SELECT 1 FROM tagxref"
" WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)", tagid);
if( zBrName ){
url_add_parameter(&url, "r", zBrName);
| > > > > | 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 |
if( renameOnly ){
blob_appendf(&sql, " AND event.objid IN rnfile ");
}
if( zYearMonth ){
blob_appendf(&sql, " AND %Q=strftime('%%Y-%%m',event.mtime) ",
zYearMonth);
}
else if( zYearWeek ){
blob_appendf(&sql, " AND %Q=strftime('%%Y-%%W',event.mtime) ",
zYearWeek);
}
if( tagid>0 ){
blob_appendf(&sql,
"AND (EXISTS(SELECT 1 FROM tagxref"
" WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)", tagid);
if( zBrName ){
url_add_parameter(&url, "r", zBrName);
|
| ︙ | ︙ | |||
1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 |
}
blob_appendf(&sql, " LIMIT %d", nEntry);
db_multi_exec("%s", blob_str(&sql));
n = db_int(0, "SELECT count(*) FROM timeline WHERE etype!='div' /*scan*/");
if( zYearMonth ){
blob_appendf(&desc, "%s events for %h", zEType, zYearMonth);
}else if( zAfter==0 && zBefore==0 && zCirca==0 ){
blob_appendf(&desc, "%d most recent %ss", n, zEType);
}else{
blob_appendf(&desc, "%d %ss", n, zEType);
}
if( zUses ){
char *zFilenames = names_of_file(zUses);
| > > | 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 |
}
blob_appendf(&sql, " LIMIT %d", nEntry);
db_multi_exec("%s", blob_str(&sql));
n = db_int(0, "SELECT count(*) FROM timeline WHERE etype!='div' /*scan*/");
if( zYearMonth ){
blob_appendf(&desc, "%s events for %h", zEType, zYearMonth);
}else if( zYearWeek ){
blob_appendf(&desc, "%s events for year/week %h", zEType, zYearWeek);
}else if( zAfter==0 && zBefore==0 && zCirca==0 ){
blob_appendf(&desc, "%d most recent %ss", n, zEType);
}else{
blob_appendf(&desc, "%d %ss", n, zEType);
}
if( zUses ){
char *zFilenames = names_of_file(zUses);
|
| ︙ | ︙ | |||
1827 1828 1829 1830 1831 1832 1833 |
@ <li>
@ <a href="%s(g.zTop)/timeline?p=%S(zUuid)&d=%S(zUuid)">%S(zUuid)</a>
}
db_finalize(&q);
style_footer();
}
| > > > > > > > > > > > > > > > > > > > > > > > > > | > > > | < | | > | 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 |
@ <li>
@ <a href="%s(g.zTop)/timeline?p=%S(zUuid)&d=%S(zUuid)">%S(zUuid)</a>
}
db_finalize(&q);
style_footer();
}
/*
** Helper for stats_report_by_month_year(), which generates a list of
** week numbers. zTimeframe should be either a timeframe in the form YYYY
** or YYYY-MM.
*/
static void stats_report_output_week_links(const char * zTimeframe){
Stmt stWeek = empty_Stmt;
char yearPart[5] = {0,0,0,0,0};
memcpy(yearPart, zTimeframe, 4);
db_prepare(&stWeek,
"SELECT DISTINCT strftime('%%W',mtime) AS wk, "
"count(*) AS n, "
"substr(date(mtime),1,%d) AS ym "
"FROM event "
"WHERE ym=%Q AND mtime < current_timestamp "
"GROUP BY wk ORDER BY wk",
strlen(zTimeframe),
zTimeframe);
while( SQLITE_ROW == db_step(&stWeek) ){
const char * zWeek = db_column_text(&stWeek,0);
const int nCount = db_column_int(&stWeek,1);
cgi_printf("<a href='%s/timeline?"
"yw=%t-%t&n=%d'>%s</a>",
g.zTop, yearPart, zWeek,
nCount, zWeek);
}
db_finalize(&stWeek);
}
/*
** Implements the "byyear" and "bymonth" reports for /stats_report.
** If includeMonth is true then it generates the "bymonth" report,
** else the "byyear" report. If zUserName is not NULL and not empty
** then the report is restricted to events created by the named user
** account.
*/
static void stats_report_by_month_year(char includeMonth,
char includeWeeks,
const char * zUserName){
Stmt query = empty_Stmt;
int nRowNumber = 0; /* current TR number */
int nEventTotal = 0; /* Total event count */
int rowClass = 0; /* counter for alternating
row colors */
Blob sql = empty_blob; /* SQL */
const char * zTimeLabel = includeMonth ? "Year/Month" : "Year";
char zPrevYear[5] = {0}; /* For keeping track of when
we change years while looping */
int nEventsPerYear = 0; /* Total event count for the
current year */
char showYearTotal = 0; /* Flag telling us when to show
the per-year event totals */
Blob header = empty_blob; /* Page header text */
int nMaxEvents = 1; /* for calculating length of graph bars. */
blob_appendf(&header, "Timeline Events by year%s",
(includeMonth ? "/month" : ""));
blob_appendf(&sql,
"SELECT substr(date(mtime),1,%d) AS timeframe, "
"count(*) AS eventCount "
"FROM event ",
|
| ︙ | ︙ | |||
1877 1878 1879 1880 1881 1882 1883 | blob_reset(&sql); @ <h1>%b(&header)</h1> @ <table class='statistics-report-table-events' border='0' cellpadding='2' @ cellspacing='0' id='statsTable'> @ <thead> @ <th>%s(zTimeLabel)</th> @ <th>Events</th> | | > > > > > > > > > > > > | | | > | | | | | | | | > > > > | | > > > > > > > > > > | < < < < < < | > > < > > | > > > > > > > | | | > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | > > | | | > | 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 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 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 |
blob_reset(&sql);
@ <h1>%b(&header)</h1>
@ <table class='statistics-report-table-events' border='0' cellpadding='2'
@ cellspacing='0' id='statsTable'>
@ <thead>
@ <th>%s(zTimeLabel)</th>
@ <th>Events</th>
@ <th width='90%%'><!-- relative commits graph --></th>
@ </thead><tbody>
blob_reset(&header);
/*
Run the query twice. The first time we calculate the maximum
number of events for a given row. Maybe someone with better SQL
Fu can re-implement this with a single query.
*/
while( SQLITE_ROW == db_step(&query) ){
const int nCount = db_column_int(&query, 1);
if(nCount>nMaxEvents){
nMaxEvents = nCount;
}
}
db_reset(&query);
while( SQLITE_ROW == db_step(&query) ){
const char * zTimeframe = db_column_text(&query, 0);
const int nCount = db_column_int(&query, 1);
const int nSize = nCount
? (int)(100 * nCount / nMaxEvents)
: 1;
showYearTotal = 0;
if(includeMonth){
/* For Month/year view, add a separator for each distinct year. */
if(!*zPrevYear ||
(0!=fossil_strncmp(zPrevYear,zTimeframe,4))){
showYearTotal = *zPrevYear;
if(showYearTotal){
rowClass = ++nRowNumber % 2;
@ <tr class='row%d(rowClass)'>
@ <td></td>
@ <td colspan='2'>Yearly total: %d(nEventsPerYear)</td>
@</tr>
}
nEventsPerYear = 0;
memcpy(zPrevYear,zTimeframe,4);
rowClass = ++nRowNumber % 2;
@ <tr class='row%d(rowClass)'>
@ <th colspan='3' class='statistics-report-row-year'>%s(zPrevYear)</th>
@ </tr>
}
}
rowClass = ++nRowNumber % 2;
nEventTotal += nCount;
nEventsPerYear += nCount;
@<tr class='row%d(rowClass)'>
@ <td>
if(includeMonth){
cgi_printf("<a href='%s/timeline?"
"ym=%t&n=%d",
g.zTop, zTimeframe, nCount );
/* Reminder: n=nCount is not actually correct for bymonth unless
that was the only user who caused events.
*/
if( zUserName && *zUserName ){
cgi_printf("&u=%t", zUserName);
}
cgi_printf("' target='_new'>%s</a>",zTimeframe);
}else {
cgi_printf("<a href='?view=byweek&y=%s", zTimeframe);
if(zUserName && *zUserName){
cgi_printf("&u=%t", zUserName);
}
cgi_printf("'>%s</a>", zTimeframe);
}
@ </td><td>%d(nCount)</td>
@ <td>
@ <div class='statistics-report-graph-line'
@ style='height:16px;width:%d(nSize)%%;'>
@ </div></td>
@</tr>
if(includeWeeks){
/* This part works fine for months but it terribly slow (4.5s on my PC),
so it's only shown for by-year for now. Suggestions/patches for
a better/faster layout are welcomed. */
@ <tr class='row%d(rowClass)'>
@ <td colspan='2' class='statistics-report-week-number-label'>Week #:</td>
@ <td class='statistics-report-week-of-year-list'>
stats_report_output_week_links(zTimeframe);
@ </td></tr>
}
/*
Potential improvement: calculate the min/max event counts and
use percent-based graph bars.
*/
}
db_finalize(&query);
if(includeMonth && !showYearTotal && *zPrevYear){
/* Add final year total separator. */
rowClass = ++nRowNumber % 2;
@ <tr class='row%d(rowClass)'>
@ <td></td>
@ <td colspan='2'>Yearly total: %d(nEventsPerYear)</td>
@</tr>
}
@ </tbody></table>
if(nEventTotal){
@ <br><div>Total events: %d(nEventTotal)</div>
}
if( !includeMonth ){
output_table_sorting_javascript("statsTable","tnx");
}
}
/*
** Implements the "byuser" view for /stats_report.
*/
static void stats_report_by_user(){
Stmt query = empty_Stmt;
int nRowNumber = 0; /* current TR number */
int nEventTotal = 0; /* Total event count */
int rowClass = 0; /* counter for alternating
row colors */
Blob sql = empty_blob; /* SQL */
int nMaxEvents = 1; /* max number of events for
all rows. */
blob_append(&sql,
"SELECT user, "
"COUNT(*) AS eventCount "
"FROM event "
"GROUP BY user ORDER BY eventCount DESC",
-1);
db_prepare(&query, blob_str(&sql));
blob_reset(&sql);
@ <h1>Timeline Events by User</h1>
@ <table class='statistics-report-table-events' border='0'
@ cellpadding='2' cellspacing='0' id='statsTable'>
@ <thead><tr>
@ <th>User</th>
@ <th>Events</th>
@ <th width='90%%'><!-- relative commits graph --></th>
@ </tr></thead><tbody>
while( SQLITE_ROW == db_step(&query) ){
const int nCount = db_column_int(&query, 1);
if(nCount>nMaxEvents){
nMaxEvents = nCount;
}
}
db_reset(&query);
while( SQLITE_ROW == db_step(&query) ){
const char * zUser = db_column_text(&query, 0);
const int nCount = db_column_int(&query, 1);
const int nSize = nCount
? (int)(100 * nCount / nMaxEvents)
: 0;
if(!nCount) continue /* arguable! Possible? */;
rowClass = ++nRowNumber % 2;
nEventTotal += nCount;
@<tr class='row%d(rowClass)'>
@ <td>
@ <a href="?view=bymonth&user=%h(zUser)" target="_new">%h(zUser)</a>
@ </td><td>%d(nCount)</td>
@ <td>
@ <div class='statistics-report-graph-line'
@ style='height:16px;width:%d(nSize)%%;'>
@ </div></td>
@</tr>
/*
Potential improvement: calculate the min/max event counts and
use percent-based graph bars.
*/
}
@ </tbody></table>
db_finalize(&query);
output_table_sorting_javascript("statsTable","tnx");
}
/*
** Helper for stats_report_by_month_year(), which generates a list of
** week numbers. zTimeframe should be either a timeframe in the form YYYY
** or YYYY-MM.
*/
static void stats_report_year_weeks(const char * zUserName){
const char * zYear = P("y");
int nYear = zYear ? strlen(zYear) : 0;
int i = 0;
Stmt qYears = empty_Stmt;
char * zDefaultYear = NULL;
Blob sql = empty_blob;
int nMaxEvents = 1; /* max number of events for
all rows. */
cgi_printf("Select year: ");
blob_append(&sql,
"SELECT DISTINCT substr(date(mtime),1,4) AS y "
"FROM event WHERE 1 ", -1);
if(zUserName&&*zUserName){
blob_appendf(&sql,"AND user=%Q ", zUserName);
}
blob_append(&sql,"GROUP BY y ORDER BY y", -1);
db_prepare(&qYears, blob_str(&sql));
blob_reset(&sql);
while( SQLITE_ROW == db_step(&qYears) ){
const char * zT = db_column_text(&qYears, 0);
if( i++ ){
cgi_printf(" ");
}
cgi_printf("<a href='?view=byweek&y=%s", zT);
if(zUserName && *zUserName){
cgi_printf("&user=%t",zUserName);
}
cgi_printf("'>%s</a>",zT);
}
db_finalize(&qYears);
cgi_printf("<br/>");
if(!zYear || !*zYear){
zDefaultYear = db_text("????", "SELECT strftime('%%Y')");
zYear = zDefaultYear;
nYear = 4;
}
if(4 == nYear){
Stmt stWeek = empty_Stmt;
int rowCount = 0;
int total = 0;
Blob header = empty_blob;
blob_appendf(&header, "Timeline events for the calendar weeks "
"of %h", zYear);
blob_appendf(&sql,
"SELECT DISTINCT strftime('%%%%W',mtime) AS wk, "
"count(*) AS n "
"FROM event "
"WHERE %Q=substr(date(mtime),1,4) "
"AND mtime < current_timestamp ",
zYear);
if(zUserName&&*zUserName){
blob_appendf(&sql, " AND user=%Q ", zUserName);
blob_appendf(&header," for user %h", zUserName);
}
blob_appendf(&sql, "GROUP BY wk ORDER BY wk DESC");
cgi_printf("<h1>%h</h1>", blob_str(&header));
blob_reset(&header);
cgi_printf("<table class='statistics-report-table-events' "
"border='0' cellpadding='2' width='100%%' "
"cellspacing='0' id='statsTable'>");
cgi_printf("<thead><tr>"
"<th>Week</th>"
"<th>Events</th>"
"<th width='90%%'><!-- relative commits graph --></th>"
"</tr></thead>"
"<tbody>");
db_prepare(&stWeek, blob_str(&sql));
blob_reset(&sql);
while( SQLITE_ROW == db_step(&stWeek) ){
const int nCount = db_column_int(&stWeek, 1);
if(nCount>nMaxEvents){
nMaxEvents = nCount;
}
}
db_reset(&stWeek);
while( SQLITE_ROW == db_step(&stWeek) ){
const char * zWeek = db_column_text(&stWeek,0);
const int nCount = db_column_int(&stWeek,1);
const int nSize = nCount
? (int)(100 * nCount / nMaxEvents)
: 0;
total += nCount;
cgi_printf("<tr class='row%d'>", ++rowCount % 2 );
cgi_printf("<td><a href='%s/timeline?yw=%t-%s&n=%d",
g.zTop, zYear, zWeek, nCount);
if(zUserName && *zUserName){
cgi_printf("&u=%t",zUserName);
}
cgi_printf("'>%s</a></td>",zWeek);
cgi_printf("<td>%d</td>",nCount);
cgi_printf("<td>");
if(nCount){
cgi_printf("<div class='statistics-report-graph-line'"
"style='height:16px;width:%d%%;'></div>",
nSize);
}
cgi_printf("</td></tr>");
}
db_finalize(&stWeek);
free(zDefaultYear);
cgi_printf("</tbody></table>");
if(total){
cgi_printf("<br><div>Total events: %d</div>",
total);
}
output_table_sorting_javascript("statsTable","tnx");
}
}
/*
** WEBPAGE: stats_report
**
** Shows activity reports for the repository.
**
** Query Parameters:
**
** view=REPORT_NAME Valid values: bymonth, byyear, byuser
** user=NAME Restricts statistics to the given user
*/
void stats_report_page(){
HQuery url; /* URL for various branch links */
const char * zView = P("view"); /* Which view/report to show. */
const char *zUserName = P("user");
if(!zUserName) zUserName = P("u");
url_initialize(&url, "stats_report");
if(zUserName && *zUserName){
url_add_parameter(&url,"user", zUserName);
timeline_submenu(&url, "(Remove User Flag)", "view", zView, "user");
}
timeline_submenu(&url, "By Year", "view", "byyear", 0);
timeline_submenu(&url, "By Month", "view", "bymonth", 0);
timeline_submenu(&url, "By Week", "view", "byweek", 0);
timeline_submenu(&url, "By User", "view", "byuser", "user");
url_reset(&url);
style_header("Activity Reports");
if(0==fossil_strcmp(zView,"byyear")){
stats_report_by_month_year(0, 0, zUserName);
}else if(0==fossil_strcmp(zView,"bymonth")){
stats_report_by_month_year(1, 0, zUserName);
}else if(0==fossil_strcmp(zView,"byweek")){
stats_report_year_weeks(zUserName);
}else if(0==fossil_strcmp(zView,"byuser")){
stats_report_by_user();
}else{
@ <h1>Select a report to show:</h1>
@ <ul>
@ <li><a href='?view=byyear'>Events by year</a></li>
@ <li><a href='?view=bymonth'>Events by month</a></li>
@ <li><a href='?view=byweek'>Events by calendar week</a></li>
@ <li><a href='?view=byuser'>Events by user</a></li>
@ </ul>
}
style_footer();
}
|
Changes to src/translate.c.
| ︙ | ︙ | |||
28 29 30 31 32 33 34 35 36 37 38 39 40 41 | ** to insert special codes (ex: \n and \") for many common characters, ** which interferes with the readability of the HTML. ** ** This tool allows us to put raw HTML, without the special codes, in ** the middle of a C program. This program then translates the text ** into standard C by inserting all necessary backslashes and other ** punctuation. ** */ #include <stdio.h> #include <ctype.h> #include <stdlib.h> #include <string.h> | > > > > > > > > > > > > > > > | 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 | ** to insert special codes (ex: \n and \") for many common characters, ** which interferes with the readability of the HTML. ** ** This tool allows us to put raw HTML, without the special codes, in ** the middle of a C program. This program then translates the text ** into standard C by inserting all necessary backslashes and other ** punctuation. ** ** Enhancement #1: ** ** If the last non-whitespace character prior to the first "@" of a ** @-block is "=" or "," then the @-block is a string literal initializer ** rather than text that is to be output via cgi_printf(). Render it ** as such. ** ** Enhancement #2: ** ** Comments of the form: "/* @-comment: CC" cause CC to become a ** comment character for the @-substitution. Typical values for CC are ** "--" (for SQL text) or "#" (for TCL script) or "//" (for C++ code). ** Lines of subsequent @-blocks that begin with CC are omitted from the ** output. ** */ #include <stdio.h> #include <ctype.h> #include <stdlib.h> #include <string.h> |
| ︙ | ︙ |
Changes to src/wiki.c.
| ︙ | ︙ | |||
784 785 786 787 788 789 790 |
blob_zero(&w2);
if( rid2 && (pW2 = manifest_get(rid2, CFTYPE_WIKI))!=0 ){
blob_init(&w2, pW2->zWiki, -1);
}
blob_zero(&d);
diffFlags = construct_diff_flags(1,0);
text_diff(&w2, &w1, &d, 0, diffFlags | DIFF_HTML | DIFF_LINENO);
| | | | 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 |
blob_zero(&w2);
if( rid2 && (pW2 = manifest_get(rid2, CFTYPE_WIKI))!=0 ){
blob_init(&w2, pW2->zWiki, -1);
}
blob_zero(&d);
diffFlags = construct_diff_flags(1,0);
text_diff(&w2, &w1, &d, 0, diffFlags | DIFF_HTML | DIFF_LINENO);
@ <pre class="udiff">
@ %s(blob_str(&d))
@ <pre>
manifest_destroy(pW1);
manifest_destroy(pW2);
style_footer();
}
/*
** prepare()s pStmt with a query requesting:
|
| ︙ | ︙ |
Changes to test/diff-test-1.wiki.
1 2 3 4 5 6 | <title>Graph Test One</title> This page contains list of URLs of interesting diffs. Click on all URLs, one by one, to verify the correct operation of the diff logic. | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<title>Graph Test One</title>
This page contains list of URLs of interesting diffs.
Click on all URLs, one by one, to verify
the correct operation of the diff logic.
* <a href="../../../info/030035345c#chunk73" target="testwindow">
Multiple edits on a single line.</a> This is an SQLite version
update diff. It is a large diff and contains many other interesting
features. Scan the whole diff.
* <a href="../../../fdiff?v1=6da016415dc52d61&v2=af6df3466e3c4a88"
target="testwindow">Tricky alignment and multiple edits per line</a>.
* <a href="../../../fdiff?v1=7108d4748b111d23&v2=2303a98525b39d19#chunk3"
target="testwindow">Add a column to a table</a>
* <a href="../../../fdiff?v1=d1c60722e0b9d775&v2=58d1a8991bacb113"
target="testwindow">Column alignment with multibyte characters.</a>
The edit of a line with multibyte characters is the first chunk.
* <a href="../../../fdiff?v1=57b0d8183cab0e3d&v2=37b3ef49d73cdfe6"
target="testwindow">Large diff of sqlite3.c</a>. This diff was very
slow prior to the performance enhancement change [9e15437e97].
* <a href="../../../info/bda00cbada#chunk49" target="testwindow">
A difficult indentation change.
* <a href="../../../fdiff?v1=955cc67ace8fb622&v2=e2e1c87b86664b45#chunk13"
target="testwindow">Another tricky indentation.</a> Notice especially
lines 59398 and 59407 on the left.
* <a href="../../../fdiff?v2=955cc67ace8fb622&v1=e2e1c87b86664b45#chunk13"
target="testwindow">Inverse of the previous.</a>
* <a href="../../../fdiff?v1=955cc67ace8fb622&v2=e2e1c87b86664b45#chunk24"
|
| ︙ | ︙ |
Changes to test/merge1.test.
| ︙ | ︙ | |||
42 43 44 45 46 47 48 |
write_file_indented t23 {
111 - This is line ONE of the demo program - 1111
222 - The second line program line in code - 2222
333 - This is a test OF THE merging algohm - 3333
444 - If all goes well, we will be pleased - 4444
555 - we think it well and other stuff too - 5555
}
| | | | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
write_file_indented t23 {
111 - This is line ONE of the demo program - 1111
222 - The second line program line in code - 2222
333 - This is a test OF THE merging algohm - 3333
444 - If all goes well, we will be pleased - 4444
555 - we think it well and other stuff too - 5555
}
fossil 3-way-merge t1 t3 t2 a32
test merge1-1.1 {[same_file t23 a32]}
fossil 3-way-merge t1 t2 t3 a23
test merge1-1.2 {[same_file t23 a23]}
write_file_indented t1 {
111 - This is line one of the demo program - 1111
222 - The second line program line in code - 2222
333 - This is a test of the merging algohm - 3333
444 - If all goes well, we will be pleased - 4444
|
| ︙ | ︙ | |||
94 95 96 97 98 99 100 | 111 - This is line ONE of the demo program - 1111 >>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 222 - The second line program line in code - 2222 333 - This is a test of the merging algohm - 3333 444 - If all goes well, we will be pleased - 4444 555 - we think it well and other stuff too - 5555 } | | | | 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
111 - This is line ONE of the demo program - 1111
>>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
222 - The second line program line in code - 2222
333 - This is a test of the merging algohm - 3333
444 - If all goes well, we will be pleased - 4444
555 - we think it well and other stuff too - 5555
}
fossil 3-way-merge t1 t3 t2 a32
test merge1-2.1 {[same_file t32 a32]}
fossil 3-way-merge t1 t2 t3 a23
test merge1-2.2 {[same_file t23 a23]}
write_file_indented t1 {
111 - This is line one of the demo program - 1111
222 - The second line program line in code - 2222
333 - This is a test of the merging algohm - 3333
444 - If all goes well, we will be pleased - 4444
|
| ︙ | ︙ | |||
127 128 129 130 131 132 133 |
write_file_indented t23 {
111 - This is line ONE of the demo program - 1111
222 - The second line program line in code - 2222
333 - This is a test of the merging algohm - 3333
444 - If all goes well, we will be pleased - 4444
555 - we think it well and other stuff too - 5555
}
| | | | 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
write_file_indented t23 {
111 - This is line ONE of the demo program - 1111
222 - The second line program line in code - 2222
333 - This is a test of the merging algohm - 3333
444 - If all goes well, we will be pleased - 4444
555 - we think it well and other stuff too - 5555
}
fossil 3-way-merge t1 t3 t2 a32
test merge1-3.1 {[same_file t23 a32]}
fossil 3-way-merge t1 t2 t3 a23
test merge1-3.2 {[same_file t23 a23]}
write_file_indented t1 {
111 - This is line one of the demo program - 1111
222 - The second line program line in code - 2222
333 - This is a test of the merging algohm - 3333
444 - If all goes well, we will be pleased - 4444
|
| ︙ | ︙ | |||
179 180 181 182 183 184 185 | ======= MERGED IN content follows ================================== >>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 222 - The second line program line in code - 2222 333 - This is a test of the merging algohm - 3333 444 - If all goes well, we will be pleased - 4444 555 - we think it well and other stuff too - 5555 } | | | | 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
======= MERGED IN content follows ==================================
>>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
222 - The second line program line in code - 2222
333 - This is a test of the merging algohm - 3333
444 - If all goes well, we will be pleased - 4444
555 - we think it well and other stuff too - 5555
}
fossil 3-way-merge t1 t3 t2 a32
test merge1-4.1 {[same_file t32 a32]}
fossil 3-way-merge t1 t2 t3 a23
test merge1-4.2 {[same_file t23 a23]}
write_file_indented t1 {
111 - This is line one of the demo program - 1111
222 - The second line program line in code - 2222
333 - This is a test of the merging algohm - 3333
444 - If all goes well, we will be pleased - 4444
|
| ︙ | ︙ | |||
212 213 214 215 216 217 218 |
write_file_indented t32 {
222 - The second line program line in code - 2222
333 - This is a test of the merging algohm - 3333
444 - If all goes well, we will be pleased - 4444
555 - we think it well and other stuff too - 5555
666 - Extra line at the end of the file wi - 6666
}
| | | | 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
write_file_indented t32 {
222 - The second line program line in code - 2222
333 - This is a test of the merging algohm - 3333
444 - If all goes well, we will be pleased - 4444
555 - we think it well and other stuff too - 5555
666 - Extra line at the end of the file wi - 6666
}
fossil 3-way-merge t1 t3 t2 a32
test merge1-5.1 {[same_file t32 a32]}
fossil 3-way-merge t1 t2 t3 a23
test merge1-5.2 {[same_file t32 a23]}
write_file_indented t1 {
111 - This is line one of the demo program - 1111
222 - The second line program line in code - 2222
333 - This is a test of the merging algohm - 3333
444 - If all goes well, we will be pleased - 4444
|
| ︙ | ︙ | |||
241 242 243 244 245 246 247 |
555 - we think it well and other stuff too - 5555
}
write_file_indented t32 {
111 - This is line one of the demo program - 1111
333 - This is a test of the merging algohm - 3333
555 - we think it well and other stuff too - 5555
}
| | | | 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
555 - we think it well and other stuff too - 5555
}
write_file_indented t32 {
111 - This is line one of the demo program - 1111
333 - This is a test of the merging algohm - 3333
555 - we think it well and other stuff too - 5555
}
fossil 3-way-merge t1 t3 t2 a32
test merge1-6.1 {[same_file t32 a32]}
fossil 3-way-merge t1 t2 t3 a23
test merge1-6.2 {[same_file t32 a23]}
write_file_indented t1 {
abcd
efgh
ijkl
mnop
|
| ︙ | ︙ | |||
326 327 328 329 330 331 332 | GHIJ >>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> KLMN OPQR STUV XYZ. } | | | 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 |
GHIJ
>>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
KLMN
OPQR
STUV
XYZ.
}
fossil 3-way-merge t1 t2 t3 a23
test merge1-7.1 {[same_file t23 a23]}
write_file_indented t2 {
abcd
efgh 2
ijkl 2
mnop
|
| ︙ | ︙ | |||
394 395 396 397 398 399 400 | GHIJ >>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> KLMN OPQR STUV XYZ. } | | | 394 395 396 397 398 399 400 401 402 |
GHIJ
>>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
KLMN
OPQR
STUV
XYZ.
}
fossil 3-way-merge t1 t2 t3 a23
test merge1-7.2 {[same_file t23 a23]}
|
Changes to test/merge2.test.
| ︙ | ︙ | |||
29 30 31 32 33 34 35 |
write_file t2 [set f2 [random_changes $f1 2 4 0 0.1]]
expr {srand($i*2+1)}
write_file t3 [set f3 [random_changes $f1 2 4 2 0.1]]
expr {srand($i*2+1)}
write_file t23 [random_changes $f2 2 4 2 0.1]
expr {srand($i*2)}
write_file t32 [random_changes $f3 2 4 0 0.1]
| | | | 29 30 31 32 33 34 35 36 37 38 39 40 41 |
write_file t2 [set f2 [random_changes $f1 2 4 0 0.1]]
expr {srand($i*2+1)}
write_file t3 [set f3 [random_changes $f1 2 4 2 0.1]]
expr {srand($i*2+1)}
write_file t23 [random_changes $f2 2 4 2 0.1]
expr {srand($i*2)}
write_file t32 [random_changes $f3 2 4 0 0.1]
fossil 3-way-merge t1 t2 t3 a23
test merge-$base-$i-23 {[same_file a23 t23]}
fossil 3-way-merge t1 t3 t2 a32
test merge-$base-$i-32 {[same_file a32 t32]}
}
}
|
Changes to test/merge3.test.
| ︙ | ︙ | |||
18 19 20 21 22 23 24 |
# Tests of the 3-way merge
#
proc merge-test {testid basis v1 v2 result} {
write_file t1 [join [string trim $basis] \n]\n
write_file t2 [join [string trim $v1] \n]\n
write_file t3 [join [string trim $v2] \n]\n
| | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# Tests of the 3-way merge
#
proc merge-test {testid basis v1 v2 result} {
write_file t1 [join [string trim $basis] \n]\n
write_file t2 [join [string trim $v1] \n]\n
write_file t3 [join [string trim $v2] \n]\n
fossil 3-way-merge t1 t2 t3 t4
set x [read_file t4]
regsub -all {<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <+} $x \
{MINE:} x
regsub -all {======= COMMON ANCESTOR content follows =+} $x {COM:} x
regsub -all {======= MERGED IN content follows =+} $x {YOURS:} x
regsub -all {>>>>>>> END MERGE CONFLICT >+} $x {END} x
set x [split [string trim $x] \n]
|
| ︙ | ︙ |
Changes to test/merge4.test.
| ︙ | ︙ | |||
18 19 20 21 22 23 24 |
# Tests of the 3-way merge
#
proc merge-test {testid basis v1 v2 result1 result2} {
write_file t1 [join [string trim $basis] \n]\n
write_file t2 [join [string trim $v1] \n]\n
write_file t3 [join [string trim $v2] \n]\n
| | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# Tests of the 3-way merge
#
proc merge-test {testid basis v1 v2 result1 result2} {
write_file t1 [join [string trim $basis] \n]\n
write_file t2 [join [string trim $v1] \n]\n
write_file t3 [join [string trim $v2] \n]\n
fossil 3-way-merge t1 t2 t3 t4
fossil 3-way-merge t1 t3 t2 t5
set x [read_file t4]
regsub -all {<<<<<<< BEGIN MERGE CONFLICT.*<<} $x {>} x
regsub -all {=======.*=======} $x {=} x
regsub -all {>>>>>>> END MERGE CONFLICT.*>>>>} $x {<} x
set x [split [string trim $x] \n]
set y [read_file t5]
regsub -all {<<<<<<< BEGIN MERGE CONFLICT.*<<} $y {>} y
|
| ︙ | ︙ |
Changes to win/Makefile.dmc.
| ︙ | ︙ | |||
24 25 26 27 28 29 30 | CFLAGS = -o BCC = $(DMDIR)\bin\dmc $(CFLAGS) TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 | | | | | 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 | CFLAGS = -o BCC = $(DMDIR)\bin\dmc $(CFLAGS) TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.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 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 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 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 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)\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)\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)\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)\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)\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 headers $(OBJ) $(OBJDIR)\link cd $(OBJDIR) $(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 captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo 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 login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf 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 winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ +echo fossil >> $@ +echo fossil >> $@ +echo $(LIBS) >> $@ +echo. >> $@ +echo fossil >> $@ translate$E: $(SRCDIR)\translate.c |
| ︙ | ︙ | |||
438 439 440 441 442 443 444 445 446 447 448 449 450 451 | +translate$E $** > $@ $(OBJDIR)\login$O : login_.c login.h $(TCC) -o$@ -c login_.c login_.c : $(SRCDIR)\login.c +translate$E $** > $@ $(OBJDIR)\main$O : main_.c main.h $(TCC) -o$@ -c main_.c main_.c : $(SRCDIR)\main.c +translate$E $** > $@ | > > > > > > | 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 | +translate$E $** > $@ $(OBJDIR)\login$O : login_.c login.h $(TCC) -o$@ -c login_.c login_.c : $(SRCDIR)\login.c +translate$E $** > $@ $(OBJDIR)\lookslike$O : lookslike_.c lookslike.h $(TCC) -o$@ -c lookslike_.c lookslike_.c : $(SRCDIR)\lookslike.c +translate$E $** > $@ $(OBJDIR)\main$O : main_.c main.h $(TCC) -o$@ -c main_.c main_.c : $(SRCDIR)\main.c +translate$E $** > $@ |
| ︙ | ︙ | |||
746 747 748 749 750 751 752 | $(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 VERSION.h | | | 752 753 754 755 756 757 758 759 760 | $(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 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 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 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 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 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 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.
| ︙ | ︙ | |||
296 297 298 299 300 301 302 303 304 305 306 307 308 309 | $(SRCDIR)/json_status.c \ $(SRCDIR)/json_tag.c \ $(SRCDIR)/json_timeline.c \ $(SRCDIR)/json_user.c \ $(SRCDIR)/json_wiki.c \ $(SRCDIR)/leaf.c \ $(SRCDIR)/login.c \ $(SRCDIR)/main.c \ $(SRCDIR)/manifest.c \ $(SRCDIR)/markdown.c \ $(SRCDIR)/markdown_html.c \ $(SRCDIR)/md5.c \ $(SRCDIR)/merge.c \ $(SRCDIR)/merge3.c \ | > | 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | $(SRCDIR)/json_status.c \ $(SRCDIR)/json_tag.c \ $(SRCDIR)/json_timeline.c \ $(SRCDIR)/json_user.c \ $(SRCDIR)/json_wiki.c \ $(SRCDIR)/leaf.c \ $(SRCDIR)/login.c \ $(SRCDIR)/lookslike.c \ $(SRCDIR)/main.c \ $(SRCDIR)/manifest.c \ $(SRCDIR)/markdown.c \ $(SRCDIR)/markdown_html.c \ $(SRCDIR)/md5.c \ $(SRCDIR)/merge.c \ $(SRCDIR)/merge3.c \ |
| ︙ | ︙ | |||
404 405 406 407 408 409 410 411 412 413 414 415 416 417 | $(OBJDIR)/json_status_.c \ $(OBJDIR)/json_tag_.c \ $(OBJDIR)/json_timeline_.c \ $(OBJDIR)/json_user_.c \ $(OBJDIR)/json_wiki_.c \ $(OBJDIR)/leaf_.c \ $(OBJDIR)/login_.c \ $(OBJDIR)/main_.c \ $(OBJDIR)/manifest_.c \ $(OBJDIR)/markdown_.c \ $(OBJDIR)/markdown_html_.c \ $(OBJDIR)/md5_.c \ $(OBJDIR)/merge_.c \ $(OBJDIR)/merge3_.c \ | > | 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 | $(OBJDIR)/json_status_.c \ $(OBJDIR)/json_tag_.c \ $(OBJDIR)/json_timeline_.c \ $(OBJDIR)/json_user_.c \ $(OBJDIR)/json_wiki_.c \ $(OBJDIR)/leaf_.c \ $(OBJDIR)/login_.c \ $(OBJDIR)/lookslike_.c \ $(OBJDIR)/main_.c \ $(OBJDIR)/manifest_.c \ $(OBJDIR)/markdown_.c \ $(OBJDIR)/markdown_html_.c \ $(OBJDIR)/md5_.c \ $(OBJDIR)/merge_.c \ $(OBJDIR)/merge3_.c \ |
| ︙ | ︙ | |||
512 513 514 515 516 517 518 519 520 521 522 523 524 525 | $(OBJDIR)/json_status.o \ $(OBJDIR)/json_tag.o \ $(OBJDIR)/json_timeline.o \ $(OBJDIR)/json_user.o \ $(OBJDIR)/json_wiki.o \ $(OBJDIR)/leaf.o \ $(OBJDIR)/login.o \ $(OBJDIR)/main.o \ $(OBJDIR)/manifest.o \ $(OBJDIR)/markdown.o \ $(OBJDIR)/markdown_html.o \ $(OBJDIR)/md5.o \ $(OBJDIR)/merge.o \ $(OBJDIR)/merge3.o \ | > | 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 | $(OBJDIR)/json_status.o \ $(OBJDIR)/json_tag.o \ $(OBJDIR)/json_timeline.o \ $(OBJDIR)/json_user.o \ $(OBJDIR)/json_wiki.o \ $(OBJDIR)/leaf.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 \ |
| ︙ | ︙ | |||
733 734 735 736 737 738 739 740 741 742 743 744 745 746 | $(OBJDIR)/json_status_.c:$(OBJDIR)/json_status.h \ $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h \ $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h \ $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h \ $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h \ $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h \ $(OBJDIR)/login_.c:$(OBJDIR)/login.h \ $(OBJDIR)/main_.c:$(OBJDIR)/main.h \ $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h \ $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h \ $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h \ $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \ $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \ $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \ | > | 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 | $(OBJDIR)/json_status_.c:$(OBJDIR)/json_status.h \ $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h \ $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h \ $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h \ $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h \ $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h \ $(OBJDIR)/login_.c:$(OBJDIR)/login.h \ $(OBJDIR)/lookslike_.c:$(OBJDIR)/lookslike.h \ $(OBJDIR)/main_.c:$(OBJDIR)/main.h \ $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h \ $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h \ $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h \ $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \ $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \ $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \ |
| ︙ | ︙ | |||
1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 | $(OBJDIR)/login_.c: $(SRCDIR)/login.c $(OBJDIR)/translate $(TRANSLATE) $(SRCDIR)/login.c >$(OBJDIR)/login_.c $(OBJDIR)/login.o: $(OBJDIR)/login_.c $(OBJDIR)/login.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/login.o -c $(OBJDIR)/login_.c $(OBJDIR)/login.h: $(OBJDIR)/headers $(OBJDIR)/main_.c: $(SRCDIR)/main.c $(OBJDIR)/translate $(TRANSLATE) $(SRCDIR)/main.c >$(OBJDIR)/main_.c $(OBJDIR)/main.o: $(OBJDIR)/main_.c $(OBJDIR)/main.h $(OBJDIR)/page_index.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/main.o -c $(OBJDIR)/main_.c | > > > > > > > > | 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 | $(OBJDIR)/login_.c: $(SRCDIR)/login.c $(OBJDIR)/translate $(TRANSLATE) $(SRCDIR)/login.c >$(OBJDIR)/login_.c $(OBJDIR)/login.o: $(OBJDIR)/login_.c $(OBJDIR)/login.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/login.o -c $(OBJDIR)/login_.c $(OBJDIR)/login.h: $(OBJDIR)/headers $(OBJDIR)/lookslike_.c: $(SRCDIR)/lookslike.c $(OBJDIR)/translate $(TRANSLATE) $(SRCDIR)/lookslike.c >$(OBJDIR)/lookslike_.c $(OBJDIR)/lookslike.o: $(OBJDIR)/lookslike_.c $(OBJDIR)/lookslike.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/lookslike.o -c $(OBJDIR)/lookslike_.c $(OBJDIR)/lookslike.h: $(OBJDIR)/headers $(OBJDIR)/main_.c: $(SRCDIR)/main.c $(OBJDIR)/translate $(TRANSLATE) $(SRCDIR)/main.c >$(OBJDIR)/main_.c $(OBJDIR)/main.o: $(OBJDIR)/main_.c $(OBJDIR)/main.h $(OBJDIR)/page_index.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/main.o -c $(OBJDIR)/main_.c |
| ︙ | ︙ |
Changes to win/Makefile.mingw.mistachkin.
| ︙ | ︙ | |||
296 297 298 299 300 301 302 303 304 305 306 307 308 309 | $(SRCDIR)/json_status.c \ $(SRCDIR)/json_tag.c \ $(SRCDIR)/json_timeline.c \ $(SRCDIR)/json_user.c \ $(SRCDIR)/json_wiki.c \ $(SRCDIR)/leaf.c \ $(SRCDIR)/login.c \ $(SRCDIR)/main.c \ $(SRCDIR)/manifest.c \ $(SRCDIR)/markdown.c \ $(SRCDIR)/markdown_html.c \ $(SRCDIR)/md5.c \ $(SRCDIR)/merge.c \ $(SRCDIR)/merge3.c \ | > | 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | $(SRCDIR)/json_status.c \ $(SRCDIR)/json_tag.c \ $(SRCDIR)/json_timeline.c \ $(SRCDIR)/json_user.c \ $(SRCDIR)/json_wiki.c \ $(SRCDIR)/leaf.c \ $(SRCDIR)/login.c \ $(SRCDIR)/lookslike.c \ $(SRCDIR)/main.c \ $(SRCDIR)/manifest.c \ $(SRCDIR)/markdown.c \ $(SRCDIR)/markdown_html.c \ $(SRCDIR)/md5.c \ $(SRCDIR)/merge.c \ $(SRCDIR)/merge3.c \ |
| ︙ | ︙ | |||
404 405 406 407 408 409 410 411 412 413 414 415 416 417 | $(OBJDIR)/json_status_.c \ $(OBJDIR)/json_tag_.c \ $(OBJDIR)/json_timeline_.c \ $(OBJDIR)/json_user_.c \ $(OBJDIR)/json_wiki_.c \ $(OBJDIR)/leaf_.c \ $(OBJDIR)/login_.c \ $(OBJDIR)/main_.c \ $(OBJDIR)/manifest_.c \ $(OBJDIR)/markdown_.c \ $(OBJDIR)/markdown_html_.c \ $(OBJDIR)/md5_.c \ $(OBJDIR)/merge_.c \ $(OBJDIR)/merge3_.c \ | > | 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 | $(OBJDIR)/json_status_.c \ $(OBJDIR)/json_tag_.c \ $(OBJDIR)/json_timeline_.c \ $(OBJDIR)/json_user_.c \ $(OBJDIR)/json_wiki_.c \ $(OBJDIR)/leaf_.c \ $(OBJDIR)/login_.c \ $(OBJDIR)/lookslike_.c \ $(OBJDIR)/main_.c \ $(OBJDIR)/manifest_.c \ $(OBJDIR)/markdown_.c \ $(OBJDIR)/markdown_html_.c \ $(OBJDIR)/md5_.c \ $(OBJDIR)/merge_.c \ $(OBJDIR)/merge3_.c \ |
| ︙ | ︙ | |||
512 513 514 515 516 517 518 519 520 521 522 523 524 525 | $(OBJDIR)/json_status.o \ $(OBJDIR)/json_tag.o \ $(OBJDIR)/json_timeline.o \ $(OBJDIR)/json_user.o \ $(OBJDIR)/json_wiki.o \ $(OBJDIR)/leaf.o \ $(OBJDIR)/login.o \ $(OBJDIR)/main.o \ $(OBJDIR)/manifest.o \ $(OBJDIR)/markdown.o \ $(OBJDIR)/markdown_html.o \ $(OBJDIR)/md5.o \ $(OBJDIR)/merge.o \ $(OBJDIR)/merge3.o \ | > | 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 | $(OBJDIR)/json_status.o \ $(OBJDIR)/json_tag.o \ $(OBJDIR)/json_timeline.o \ $(OBJDIR)/json_user.o \ $(OBJDIR)/json_wiki.o \ $(OBJDIR)/leaf.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 \ |
| ︙ | ︙ | |||
733 734 735 736 737 738 739 740 741 742 743 744 745 746 | $(OBJDIR)/json_status_.c:$(OBJDIR)/json_status.h \ $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h \ $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h \ $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h \ $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h \ $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h \ $(OBJDIR)/login_.c:$(OBJDIR)/login.h \ $(OBJDIR)/main_.c:$(OBJDIR)/main.h \ $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h \ $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h \ $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h \ $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \ $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \ $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \ | > | 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 | $(OBJDIR)/json_status_.c:$(OBJDIR)/json_status.h \ $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h \ $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h \ $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h \ $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h \ $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h \ $(OBJDIR)/login_.c:$(OBJDIR)/login.h \ $(OBJDIR)/lookslike_.c:$(OBJDIR)/lookslike.h \ $(OBJDIR)/main_.c:$(OBJDIR)/main.h \ $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h \ $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h \ $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h \ $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \ $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \ $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \ |
| ︙ | ︙ | |||
1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 | $(OBJDIR)/login_.c: $(SRCDIR)/login.c $(OBJDIR)/translate $(TRANSLATE) $(SRCDIR)/login.c >$(OBJDIR)/login_.c $(OBJDIR)/login.o: $(OBJDIR)/login_.c $(OBJDIR)/login.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/login.o -c $(OBJDIR)/login_.c $(OBJDIR)/login.h: $(OBJDIR)/headers $(OBJDIR)/main_.c: $(SRCDIR)/main.c $(OBJDIR)/translate $(TRANSLATE) $(SRCDIR)/main.c >$(OBJDIR)/main_.c $(OBJDIR)/main.o: $(OBJDIR)/main_.c $(OBJDIR)/main.h $(OBJDIR)/page_index.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/main.o -c $(OBJDIR)/main_.c | > > > > > > > > | 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 | $(OBJDIR)/login_.c: $(SRCDIR)/login.c $(OBJDIR)/translate $(TRANSLATE) $(SRCDIR)/login.c >$(OBJDIR)/login_.c $(OBJDIR)/login.o: $(OBJDIR)/login_.c $(OBJDIR)/login.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/login.o -c $(OBJDIR)/login_.c $(OBJDIR)/login.h: $(OBJDIR)/headers $(OBJDIR)/lookslike_.c: $(SRCDIR)/lookslike.c $(OBJDIR)/translate $(TRANSLATE) $(SRCDIR)/lookslike.c >$(OBJDIR)/lookslike_.c $(OBJDIR)/lookslike.o: $(OBJDIR)/lookslike_.c $(OBJDIR)/lookslike.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/lookslike.o -c $(OBJDIR)/lookslike_.c $(OBJDIR)/lookslike.h: $(OBJDIR)/headers $(OBJDIR)/main_.c: $(SRCDIR)/main.c $(OBJDIR)/translate $(TRANSLATE) $(SRCDIR)/main.c >$(OBJDIR)/main_.c $(OBJDIR)/main.o: $(OBJDIR)/main_.c $(OBJDIR)/main.h $(OBJDIR)/page_index.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/main.o -c $(OBJDIR)/main_.c |
| ︙ | ︙ |
Changes to win/Makefile.msc.
| ︙ | ︙ | |||
114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
json_status_.c \
json_tag_.c \
json_timeline_.c \
json_user_.c \
json_wiki_.c \
leaf_.c \
login_.c \
main_.c \
manifest_.c \
markdown_.c \
markdown_html_.c \
md5_.c \
merge_.c \
merge3_.c \
| > | 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
json_status_.c \
json_tag_.c \
json_timeline_.c \
json_user_.c \
json_wiki_.c \
leaf_.c \
login_.c \
lookslike_.c \
main_.c \
manifest_.c \
markdown_.c \
markdown_html_.c \
md5_.c \
merge_.c \
merge3_.c \
|
| ︙ | ︙ | |||
222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
$(OX)\json_status$O \
$(OX)\json_tag$O \
$(OX)\json_timeline$O \
$(OX)\json_user$O \
$(OX)\json_wiki$O \
$(OX)\leaf$O \
$(OX)\login$O \
$(OX)\main$O \
$(OX)\manifest$O \
$(OX)\markdown$O \
$(OX)\markdown_html$O \
$(OX)\md5$O \
$(OX)\merge$O \
$(OX)\merge3$O \
| > | 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
$(OX)\json_status$O \
$(OX)\json_tag$O \
$(OX)\json_timeline$O \
$(OX)\json_user$O \
$(OX)\json_wiki$O \
$(OX)\leaf$O \
$(OX)\login$O \
$(OX)\lookslike$O \
$(OX)\main$O \
$(OX)\manifest$O \
$(OX)\markdown$O \
$(OX)\markdown_html$O \
$(OX)\md5$O \
$(OX)\merge$O \
$(OX)\merge3$O \
|
| ︙ | ︙ | |||
348 349 350 351 352 353 354 355 356 357 358 359 360 361 | echo $(OX)\json_status.obj >> $@ echo $(OX)\json_tag.obj >> $@ echo $(OX)\json_timeline.obj >> $@ echo $(OX)\json_user.obj >> $@ echo $(OX)\json_wiki.obj >> $@ echo $(OX)\leaf.obj >> $@ echo $(OX)\login.obj >> $@ echo $(OX)\main.obj >> $@ echo $(OX)\manifest.obj >> $@ echo $(OX)\markdown.obj >> $@ echo $(OX)\markdown_html.obj >> $@ echo $(OX)\md5.obj >> $@ echo $(OX)\merge.obj >> $@ echo $(OX)\merge3.obj >> $@ | > | 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 | echo $(OX)\json_status.obj >> $@ echo $(OX)\json_tag.obj >> $@ echo $(OX)\json_timeline.obj >> $@ echo $(OX)\json_user.obj >> $@ echo $(OX)\json_wiki.obj >> $@ echo $(OX)\leaf.obj >> $@ echo $(OX)\login.obj >> $@ echo $(OX)\lookslike.obj >> $@ echo $(OX)\main.obj >> $@ echo $(OX)\manifest.obj >> $@ echo $(OX)\markdown.obj >> $@ echo $(OX)\markdown_html.obj >> $@ echo $(OX)\md5.obj >> $@ echo $(OX)\merge.obj >> $@ echo $(OX)\merge3.obj >> $@ |
| ︙ | ︙ | |||
807 808 809 810 811 812 813 814 815 816 817 818 819 820 | translate$E $** > $@ $(OX)\login$O : login_.c login.h $(TCC) /Fo$@ -c login_.c login_.c : $(SRCDIR)\login.c translate$E $** > $@ $(OX)\main$O : main_.c main.h $(TCC) /Fo$@ -c main_.c main_.c : $(SRCDIR)\main.c translate$E $** > $@ | > > > > > > | 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 | translate$E $** > $@ $(OX)\login$O : login_.c login.h $(TCC) /Fo$@ -c login_.c login_.c : $(SRCDIR)\login.c translate$E $** > $@ $(OX)\lookslike$O : lookslike_.c lookslike.h $(TCC) /Fo$@ -c lookslike_.c lookslike_.c : $(SRCDIR)\lookslike.c translate$E $** > $@ $(OX)\main$O : main_.c main.h $(TCC) /Fo$@ -c main_.c main_.c : $(SRCDIR)\main.c translate$E $** > $@ |
| ︙ | ︙ | |||
1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 | 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 \ login_.c:login.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 \ | > | 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 | 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 \ 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 \ |
| ︙ | ︙ |
Added www/adding_code.wiki.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 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 |
<title>Adding Features To Fossil</title>
<h2>1.0 Introduction</h2>
This article provides a brief overview of how to write new code that extends
or enhances Fossil.
<h2>2.0 Programming Language</h2>
Fossil is written in C-89. There are specific [./style.wiki | style guidelines]
that are required for any new code that will be accepted into the Fossil core.
But, of course, if you are writing an extension just for yourself, you can
use any programming style you want.
The source code for Fossil is not feed directly into the C compiler, however.
There are three separate code [./makefile.wiki#preprocessing|preprocessors]
that run over the code first.
1. The <b>mkindex</b> preprocessor scans all regular source files looking
for special comments that contain "help" text and which identify routines
that implement specific commands or which generate particular web pages.
2. The <b>makeheaders</b> preprocessor generates all the ".h" files
automatically. Fossil programmers write ".c" files only and let the
makeheaders preprocessor create the ".h" files.
3. The <b>translate</b> preprocessor converts source code lines that
begin with "@" into string literals, or into print statements that
generate web page output, depending on context.
The [./makefile.wiki|Makefile] for Fossil takes care of running these
preprocessors with all the right arguments and in the right order. So it is
not necessary to understand the details of how these preprocessors work.
(Though, the sources for all three preprocessors are included in the source
tree and are well commented, if you want to dig deeper.) It is only necessary
to know that these preprocessors exist and hence will effect the way you
write code.
<h2>3.0 Adding New Source Code Files</h2>
New source code files are added in the "src/" subdirectory of the Fossil
source tree. Suppose one wants to add a new source code file named
"xyzzy.c". The first step is to add this file to the various makefiles.
Do so by editing the file src/makemake.tcl and adding "xyzzy" (without
the final ".c") to the list of source modules at the top of that script.
Save the result and then run the makemake.tcl script using a TCL
interpreter. The command to run the makemake.tcl script is:
<b>tclsh makemake.tcl</b>
The working directory must be src/ when the command above is run.
Note that TCL is not normally required to build Fossil, but
it is required for this step. If you do not have a TCL interpreter on
your system already, they are easy to install. A popular choice is the
[http://www.activestate.com/activetcl|Active Tcl] installation from
ActiveState.
After the makefiles have been updated, create the xyzzy.c source file
from the following template:
<blockquote><verbatim>
/*
** Copyright boilerplate goes here.
*****************************************************
** High-level description of what this module goes
** here.
*/
#include "config.h"
#include "xyzzy.h"
#if INTERFACE
/* Exported object (structure) definitions or #defines
** go here */
#endif /* INTEFACE */
/* New code goes here */
</verbatim></blockquote>
Note in particular the <b>#include "xyzzy.h"</b> line near the top.
The "xyzzy.h" file is automatically generated by makeheaders. Every
normal Fossil source file must have a #include at the top that imports
its private header file. (Some source files, such as "sqlite3.c" are
exceptions to this rule. Don't worry about those exceptions. The
files you write will require this #include line.)
The "#if INTERFACE ... #endif" section is optional and is only needed
if there are structure definitions or typedefs or macros that need to
be used by other source code files. The makeheaders preprocessor
uses definitions in the INTERFACE section to help it generate header
files. See [../src/makeheaders.html | makeheaders.html] for additional
information.
After creating a template file such as shown above, and after updating
the makefiles, you should be able to recompile Fossil and have it include
your new source file, even before you source file contains any code.
It is recommended that you try this.
Be sure to [/help/add|fossil add] your new source file to the self-hosting
Fossil repository and then [/help/commit|commit] your changes!
<h2>4.0 Creating A New Command</h2>
By "commands" we mean the keywords that follow "fossil" when invoking
Fossil from the command-line. So, for example, in
<b>fossil diff xyzzy.c</b>
The "command" is "diff". Commands may optionally be followed by
arguments and/or options. To create new commands in Fossil, add code
(either to an existing source file, or to a new source file created as
described above) according to the following template:
<blockquote><verbatim>
/*
** COMMAND: xyzzy
**
** Help text goes here.
*/
void xyzzy_cmd(void){
/* Implement the command here */
fossil_print("Hello, World!\n");
}
</verbatim></blockquote>
The example above creates a new command named "xyzzy" that prints the
message "Hello, World!" on the console. This command is a normal command
that will show up in the list of command from [/help/help|fossil help].
If you add an asterisk to the end of the command name, like this:
<blockquote><verbatim>
** COMMAND: xyzzy*
</verbatim></blockquote>
Then the command will only show up if you add the "--all" option to
[/help/help|fossil help]. Or, if the command name starts with
"test" then the command will be considered experimental and will only
show up when the --test option is used with [/help/help|fossil help].
The example above is a fully functioning Fossil command. You can add
the text shown to an existing Fossil source file, recompiling then test
it out by typing:
<b>./fossil xyzzy<br>
./fossil help xyzzy<br>
./fossil xyzzy --help</b>
The name of the C function that implements the command can be anything
you like (as long as it does not collide with some other symbol in the
Fossil code) but it is traditional to name the function
"<i>commandname</i><b>_cmd</b>", as is done in the example.
You could also use "printf()" instead of "fossil_print()" to generate
the output text, if desired. But "fossil_print()" is recommended as
it has extra logic to insert \r characters at the right times on
windows systems.
Once you have the command running, you can then start adding code to
make it do useful things. There are logs of utility functions in
Fossil for parsing command-line options and for
opening and accessing and manipulating the repository and
the working check-out. Study at the implementations of existing commands
to get an idea of how things are done. You can easily find the implementations
of existing commands by searching for "COMMAND: <i>name</i>" in the
files of the "src/" directory.
<h2>5.0 Creating A New Web Page</h2>
As with commands, new webpages can be added simply by inserting a function
that generates the webpage together with a special header comment. A
template follows:
<blockquote><verbatim>
/*
** WEBPAGE: helloworld
*/
void helloworld_page(void){
style_header("Hello World!");
@ <p>Hello, World!</p>
style_footer();
}
</verbatim></blockquote>
Add the code above to a new or existing Fossil source code file, then
recompile fossil and run [/help/ui|fossil ui] then enter
"http://localhost:8080/helloworld" in your web browser and the routine
above will generate a web page that says "Hello World."
It really is that simple.
The special "WEBPAGE:" comment is picked up by the "mkindex" preprocessor
and used to generate a table that maps the "helloworld" webpage name
into a pointer to the "helloworld_page()" function. The function that
implements a webpage can be named anything you like (as long as it does
not collide with another name) but the traditional name is
"<i>pagename</i><b>_page</b>".
HTML pages begin with a call to style_header() and end with the call to
style_footer(). Content is generated by the "@" lines that are translated
(by the "translate" preprocessor) into printf-like code that generates the
content of the webpage. Different techniques are used to generate
non-HTML content. In the unlikely event that you need to generate
non-HTML content, look at existing webpage implementations
(ex: "logo" or "style.css") to see how that is done.
There are lots of other things that a real web-page implementation will
need to do, such verifying user credentials, parsing query parameters,
and interacting with the repository. But now that you have the general
idea of how webpages are implemented, you can look at the many other
webpage implementations already built into Fossil to see how all that
works.
<h2>6.0 See Also</h2>
* [./makefile.wiki|The Fossil Build Process]
* [./tech_overview.wiki|A Technical Overview Of Fossil]
* [./contribute.wiki|Contributing To The Fossil Project]
|
Changes to www/build.wiki.
| ︙ | ︙ | |||
120 121 122 123 124 125 126 127 128 129 130 131 132 133 | <li><p> If the makefiles that come with Fossil do not work for you, or for some other reason you want to know how to build Fossil manually, then refer to the [./makefile.wiki | Fossil Build Process] document which describes in detail what the makefiles do behind the scenes. <li><p> To build on older Macs (circa 2002, MacOS 10.2) edit the Makefile generated by configure to add the following lines: <blockquote><pre> TCC += -DSQLITE_WITHOUT_ZONEMALLOC TCC += -DWITHOUT_ICONV TCC += -Dsocketlen_t=int | > > > > > > > | 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | <li><p> If the makefiles that come with Fossil do not work for you, or for some other reason you want to know how to build Fossil manually, then refer to the [./makefile.wiki | Fossil Build Process] document which describes in detail what the makefiles do behind the scenes. <li><p> The fossil executable is self-contained and stand-alone and usually requires no special libraries or other software to be installed. However, the "--tk" option to the [/help/diff|diff command] requires that Tcl/Tk be installed on the local machine. You can get Tcl/Tk from [http://www.activestate.com/activetcl|ActiveState]. <li><p> To build on older Macs (circa 2002, MacOS 10.2) edit the Makefile generated by configure to add the following lines: <blockquote><pre> TCC += -DSQLITE_WITHOUT_ZONEMALLOC TCC += -DWITHOUT_ICONV TCC += -Dsocketlen_t=int |
| ︙ | ︙ |
Changes to www/contribute.wiki.
| ︙ | ︙ | |||
76 77 78 79 80 81 82 | <h2>5.0 See Also</h2> * [./build.wiki | How To Compile And Install Fossil] * [./makefile.wiki | The Fossil Build Process] * [./tech_overview.wiki | A Technical Overview of Fossil] | > | 76 77 78 79 80 81 82 83 | <h2>5.0 See Also</h2> * [./build.wiki | How To Compile And Install Fossil] * [./makefile.wiki | The Fossil Build Process] * [./tech_overview.wiki | A Technical Overview of Fossil] * [./adding_code.wiki | Adding Features To Fossil] |
Changes to www/faq.tcl.
| ︙ | ︙ | |||
35 36 37 38 39 40 41 |
faq {
How do I create a new branch?
} {
There are lots of ways:
When you are checking in a new change using the <b>[/help/commit|commit]</b>
command, you can add the option "--branch <i>BRANCH-NAME</i>" to
| | < < | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
faq {
How do I create a new branch?
} {
There are lots of ways:
When you are checking in a new change using the <b>[/help/commit|commit]</b>
command, you can add the option "--branch <i>BRANCH-NAME</i>" to
make the new check-in be the first check-in for a new branch.
If you want to create a new branch whose initial content is the
same as an existing check-in, use this command:
<blockquote>
<b>fossil [/help/branch|branch] new</b> <i>BRANCH-NAME BASIS</i>
</blockquote>
|
| ︙ | ︙ | |||
68 69 70 71 72 73 74 |
faq {
How do I tag a check-in?
} {
There are several ways:
When you are checking in a new change using the <b>[/help/commit|commit]</b>
command, you can add a tag to that check-in using the
| | > > | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
faq {
How do I tag a check-in?
} {
There are several ways:
When you are checking in a new change using the <b>[/help/commit|commit]</b>
command, you can add a tag to that check-in using the
"--tag <i>TAGNAME</i>" command-line option. You can repeat the --tag
option to give a check-in multiple tags. Tags need not be unique. So,
for example, it is common to give every released version a "release" tag.
If you want add a tag to an existing check-in, you can use the
<b>[/help/tag|tag]</b> command. For example:
<blockquote>
<b>fossil [/help/branch|tag] add</b> <i>TAGNAME</i> <i>CHECK-IN</i>
</blockquote>
|
| ︙ | ︙ |
Changes to www/faq.wiki.
| ︙ | ︙ | |||
39 40 41 42 43 44 45 | <a name="q3"></a> <p><b>(3) How do I create a new branch?</b></p> <blockquote>There are lots of ways: When you are checking in a new change using the <b>[/help/commit|commit]</b> command, you can add the option "--branch <i>BRANCH-NAME</i>" to | | < < | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | <a name="q3"></a> <p><b>(3) How do I create a new branch?</b></p> <blockquote>There are lots of ways: When you are checking in a new change using the <b>[/help/commit|commit]</b> command, you can add the option "--branch <i>BRANCH-NAME</i>" to make the new check-in be the first check-in for a new branch. If you want to create a new branch whose initial content is the same as an existing check-in, use this command: <blockquote> <b>fossil [/help/branch|branch] new</b> <i>BRANCH-NAME BASIS</i> </blockquote> |
| ︙ | ︙ | |||
71 72 73 74 75 76 77 | <a name="q4"></a> <p><b>(4) How do I tag a check-in?</b></p> <blockquote>There are several ways: When you are checking in a new change using the <b>[/help/commit|commit]</b> command, you can add a tag to that check-in using the | | > > | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | <a name="q4"></a> <p><b>(4) How do I tag a check-in?</b></p> <blockquote>There are several ways: When you are checking in a new change using the <b>[/help/commit|commit]</b> command, you can add a tag to that check-in using the "--tag <i>TAGNAME</i>" command-line option. You can repeat the --tag option to give a check-in multiple tags. Tags need not be unique. So, for example, it is common to give every released version a "release" tag. If you want add a tag to an existing check-in, you can use the <b>[/help/tag|tag]</b> command. For example: <blockquote> <b>fossil [/help/branch|tag] add</b> <i>TAGNAME</i> <i>CHECK-IN</i> </blockquote> |
| ︙ | ︙ |
Changes to www/fossil-v-git.wiki.
| ︙ | ︙ | |||
33 34 35 36 37 38 39 | <h2>3.0 Discussion</h2> <h3>3.1 Feature Set</h3> Git provides file versioning services only, whereas Fossil adds an integrated [./wikitheory.wiki | wiki], [./bugtheory.wiki | ticketing & bug tracking], | | | 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | <h2>3.0 Discussion</h2> <h3>3.1 Feature Set</h3> Git provides file versioning services only, whereas Fossil adds an integrated [./wikitheory.wiki | wiki], [./bugtheory.wiki | ticketing & bug tracking], [./embeddeddoc.wiki | embedded documentation], and [./event.wiki | News/Blog features]. These additional capabilities are available for Git as 3rd-party user-installed add-ons, but with Fossil they are integrated into the design. One way to describe Fossil is that it is "[https://github.com/ | github]-in-a-box". <h3>3.2 Sharding versus Replicating</h3> |
| ︙ | ︙ | |||
72 73 74 75 76 77 78 | at a time. Git encourages a programming model where each developer works in his or her own branch and then merges changes up the hierarchy until they reach the master branch. Fossil is designed for smaller and non-hierarchical teams where all developers are operating directly on the master branch, or at most a small number of well defined branches. | | | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | at a time. Git encourages a programming model where each developer works in his or her own branch and then merges changes up the hierarchy until they reach the master branch. Fossil is designed for smaller and non-hierarchical teams where all developers are operating directly on the master branch, or at most a small number of well defined branches. The [./concepts.wiki#workflow | autosync] mode of Fossil makes it easy for multiple developers to work on a single branch and maintain linear development on that branch and avoid needless forking and merging. <h3>3.3 Branches</h3> Git (and especially GitHub) encourages a workflow where each developer |
| ︙ | ︙ | |||
113 114 115 116 117 118 119 | branches in Fossil are feature-centric. The Git approach scales much better for large projects like the Linux kernel with thousands of contributors who in many cases don't even know each others names. The integrators serve a gatekeeper role to help keep undesirable code out of the official Linux source tree. On the other hand, not many projects are as big or as loosely organized as the Linux kernel. | | > > > > > | 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | branches in Fossil are feature-centric. The Git approach scales much better for large projects like the Linux kernel with thousands of contributors who in many cases don't even know each others names. The integrators serve a gatekeeper role to help keep undesirable code out of the official Linux source tree. On the other hand, not many projects are as big or as loosely organized as the Linux kernel. Most projects have a small team of developers who all know each other well and trust each other, and who enjoy working together collaboratively without the overhead and hierarchy of integrators. One consequence of the "everybody-sees-everything" focus of Fossil is that branch names are global and are part of the distributed and synchronized content of a Fossil repository, rather than being private and user-specific as they are in Git. <h3>3.4 Complexity</h3> Git is a complex system. It can be tricky to use and requires a fair amount of knowledge and experience to master. Fossil strives to be a much simpler system that can be learned and mastered much more quickly. Fossil strives to have fewer "gotchas" and quirks that can trip up a |
| ︙ | ︙ | |||
137 138 139 140 141 142 143 | the thinking about version control. Git requires the developer to maintain a more complex mental model than most other DVCSes. Git takes longer to learn. And you have to spend more time thinking about what you are doing with Git. Fossil strives for simplicity. Fossil wants to be easy to learn and to | | > | | | 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | the thinking about version control. Git requires the developer to maintain a more complex mental model than most other DVCSes. Git takes longer to learn. And you have to spend more time thinking about what you are doing with Git. Fossil strives for simplicity. Fossil wants to be easy to learn and to require little thinking about how to operating it. [./quotes.wiki | Reports from the field] indicate that Fossil is mostly successful at this effort. <h3>3.5 Web Interface</h3> Git has a web interface, but it requires a fair amount of setup and an external web server. Fossil comes with a fully functional [./webui.wiki | built-in web-server] and a really simple mechanism (the "[/help/ui|fossil ui]" command) to automatically start the web server and bring up a web browser to navigate it. The web interface for Fossil is not only easier to set up, it is also more powerful and easier to use. The web interface to Fossil is a practical replacement to the 3rd-party "GUI Tools" that users often employ to operate Git. <h3>3.6 Implementation Strategy</h3> |
| ︙ | ︙ | |||
186 187 188 189 190 191 192 | are simply rolled back after the system reboots. <h3>3.8 Audit Trail</h3> Git features the "rebase" command which can be used to change the sequence of check-ins in the repository. Rebase can be used to "clean up" a complex sequence of check-ins to make their intent easier for others | | | < < < | > > > > > > > > | | > > | | | | 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 | are simply rolled back after the system reboots. <h3>3.8 Audit Trail</h3> Git features the "rebase" command which can be used to change the sequence of check-ins in the repository. Rebase can be used to "clean up" a complex sequence of check-ins to make their intent easier for others to understand. This is important if you view the history of a project as part of the documentation for the project. Fossil takes an opposing view. Fossil views history as sacrosanct and stubornly refuses to change it. Fossil allows mistakes to be corrected (for example, check-in comments can be revised, and check-ins can be moved onto new branches even after the check-in has occurred) but the correction is an addition to the respository and the original actions are preserved and displayed alongside the corrections, thus preserving an historically accurate audit trail. This is analogous to an accountant marking through an incorrect entry in a ledger and writing in a correction beside it, rather than erasing and incorrect entry. To put it another way, Git remembers what you should have done whereas Fossil remembers what you actually did. The lack of a "rebase" command and the inability to rewrite history is considered a feature of Fossil, not an omission or bug. <h3>3.9 License</h3> Both Git and Fossil are open-source. Git is under [http://www.gnu.org/licenses/gpl.html | GPL] whereas Fossil is under the [http://en.wikipedia.org/wiki/BSD_licenses | two-clause BSD license]. The difference should not be of a concern to most users. However, some corporate lawyers have objections to using GPL products and are more comfortable with a BSD-style license. |
Changes to www/hints.wiki.
1 2 | <title>Fossil Tips And Usage Hints</title> | | | | > > | 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 |
<title>Fossil Tips And Usage Hints</title>
1. Click on nodes of any timeline graph to see diffs between the two
selected versions.
2. Add the "--tk" option to "[/help?cmd=diff | fossil diff]" commands
to get a pop-up
window containing a complete side-by-side diff. (NB: The pop-up
window is run as a separate Tcl/Tk process, so you will need to
have Tcl/Tk installed on your machine for this to work. Visit
[http://www.activestate.com/activetcl] to for a quick download of
Tcl/Tk if you do not already have it on your system.)
3. The "[/help?cmd=clean | fossil clean -f]" command makes a great
alternative to "make clean".
4. Use "[/help?cmd=all | fossil all changes]" to look for any uncommitted
edits in any of your Fossil projects. Use
"[/help?cmd=all | fossil all pull]" on your laptop
prior to going off network (for example, on a long plane ride)
to make sure you have all the latest content locally. Then run
"[/help/all|fossil all push]" when you get back online to upload
your changes.
5. Sub-menu options on Timelines lets you select either 20 or 200
records. But you can manual edit the "n=" query parameter in the
URL to get any number of records you desire. To see a complete
timeline graph, set n to some ridiculously large value like 10000000.
6. You can manually add a "c=CHECKIN" query parameter to the timeline
|
| ︙ | ︙ |
Changes to www/makefile.wiki.
| ︙ | ︙ | |||
10 11 12 13 14 15 16 17 18 19 20 21 22 23 | want to compile the code themselves can use one of the [./build.wiki | existing makefiles]. So must people do not need to be concerned with the build complexities of Fossil. But hard-core developers who desire a deep understanding of how Fossil is put together can benefit from reviewing this article. <h1>2.0 Source Code Tour</h1> The source code for Fossil is found in the [/dir?ci=trunk&name=src | src/] subdirectory of the source tree. The src/ subdirectory contains all code, including the code for the separate preprocessor programs. | > | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | want to compile the code themselves can use one of the [./build.wiki | existing makefiles]. So must people do not need to be concerned with the build complexities of Fossil. But hard-core developers who desire a deep understanding of how Fossil is put together can benefit from reviewing this article. <a name="srctour"></a> <h1>2.0 Source Code Tour</h1> The source code for Fossil is found in the [/dir?ci=trunk&name=src | src/] subdirectory of the source tree. The src/ subdirectory contains all code, including the code for the separate preprocessor programs. |
| ︙ | ︙ | |||
115 116 117 118 119 120 121 122 123 124 125 126 127 128 | The pathnames in the above command might need to be adjusted to get the directories right. The point is that the manifest.uuid, manifest, and VERSION files in the root of the source tree are the three arguments and the generated VERSION.h file appears on standard output. <h1>4.0 Preprocessing</h1> There are three preprocessors for the Fossil sources. The mkindex and translate preprocessors can be run in any order. The makeheaders preprocessor must be run after translate. <h2>4.1 The mkindex preprocessor</h2> | > | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | The pathnames in the above command might need to be adjusted to get the directories right. The point is that the manifest.uuid, manifest, and VERSION files in the root of the source tree are the three arguments and the generated VERSION.h file appears on standard output. <a name="preprocessing"></a> <h1>4.0 Preprocessing</h1> There are three preprocessors for the Fossil sources. The mkindex and translate preprocessors can be run in any order. The makeheaders preprocessor must be run after translate. <h2>4.1 The mkindex preprocessor</h2> |
| ︙ | ︙ | |||
234 235 236 237 238 239 240 | <h1>6.0 Linkage</h1> Fossil needs to be linked against [http://www.zlib.net | zlib]. If the HTTPS option is enabled, then it will also need to link against the appropriate SSL implementation. And, of course, Fossil needs to link against the standard C library. No other libraries or external dependences are used. | > > > > > | 236 237 238 239 240 241 242 243 244 245 246 247 | <h1>6.0 Linkage</h1> Fossil needs to be linked against [http://www.zlib.net | zlib]. If the HTTPS option is enabled, then it will also need to link against the appropriate SSL implementation. And, of course, Fossil needs to link against the standard C library. No other libraries or external dependences are used. <h1>7.0 See Also</h1> * [./tech_overview.wiki | A Technical Overview Of Fossil] * [./adding_code.wiki | How To Add Features To Fossil] |
Changes to www/mkindex.tcl.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#!/bin/sh
#
# Run this TCL script to generate a WIKI page that contains a
# permuted index of the various documentation files.
#
# tclsh mkindex.tcl >permutedindex.wiki
#
set doclist {
antibot.wiki {Defense against Spiders and Bots}
bugtheory.wiki {Bug Tracking In Fossil}
branching.wiki {Branching, Forking, Merging, and Tagging}
build.wiki {Compiling and Installing Fossil}
checkin_names.wiki {Checkin And Version Names}
checkin.wiki {Check-in Checklist}
changes.wiki {Fossil Changelog}
| > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#!/bin/sh
#
# Run this TCL script to generate a WIKI page that contains a
# permuted index of the various documentation files.
#
# tclsh mkindex.tcl >permutedindex.wiki
#
set doclist {
adding_code.wiki {Adding New Features To Fossil}
adding_code.wiki {Hacking Fossil}
antibot.wiki {Defense against Spiders and Bots}
bugtheory.wiki {Bug Tracking In Fossil}
branching.wiki {Branching, Forking, Merging, and Tagging}
build.wiki {Compiling and Installing Fossil}
checkin_names.wiki {Checkin And Version Names}
checkin.wiki {Check-in Checklist}
changes.wiki {Fossil Changelog}
|
| ︙ | ︙ |
Changes to www/permutedindex.wiki.
| ︙ | ︙ | |||
11 12 13 14 15 16 17 18 19 20 21 22 23 24 | </ul> <a name="pindex"></a> <h2>Permuted Index:</h2> <ul> <li><a href="fiveminutes.wiki">5 Minutes as a Single User — Update and Running in</a></li> <li><a href="fossil-from-msvc.wiki">2010 IDE — Integrating Fossil in the Microsoft Express</a></li> <li><a href="tech_overview.wiki">A Technical Overview Of The Design And Implementation Of Fossil</a></li> <li><a href="antibot.wiki">against Spiders and Bots — Defense</a></li> <li><a href="copyright-release.html">Agreement — Contributor License</a></li> <li><a href="delta_encoder_algorithm.wiki">Algorithm — Fossil Delta Encoding</a></li> <li><a href="fiveminutes.wiki">as a Single User — Update and Running in 5 Minutes</a></li> <li><a href="faq.wiki">Asked Questions — Frequently</a></li> <li><a href="password.wiki">Authentication — Password Management And</a></li> <li><a href="antibot.wiki">Bots — Defense against Spiders and</a></li> | > | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | </ul> <a name="pindex"></a> <h2>Permuted Index:</h2> <ul> <li><a href="fiveminutes.wiki">5 Minutes as a Single User — Update and Running in</a></li> <li><a href="fossil-from-msvc.wiki">2010 IDE — Integrating Fossil in the Microsoft Express</a></li> <li><a href="tech_overview.wiki">A Technical Overview Of The Design And Implementation Of Fossil</a></li> <li><a href="adding_code.wiki">Adding New Features To Fossil</a></li> <li><a href="antibot.wiki">against Spiders and Bots — Defense</a></li> <li><a href="copyright-release.html">Agreement — Contributor License</a></li> <li><a href="delta_encoder_algorithm.wiki">Algorithm — Fossil Delta Encoding</a></li> <li><a href="fiveminutes.wiki">as a Single User — Update and Running in 5 Minutes</a></li> <li><a href="faq.wiki">Asked Questions — Frequently</a></li> <li><a href="password.wiki">Authentication — Password Management And</a></li> <li><a href="antibot.wiki">Bots — Defense against Spiders and</a></li> |
| ︙ | ︙ | |||
59 60 61 62 63 64 65 66 67 68 69 70 71 72 | <li><a href="theory1.wiki">DVCS — Thoughts On The Design Of The Fossil</a></li> <li><a href="quotes.wiki">DVCSes in General — Quotes: What People Are Saying About Fossil, Git, and</a></li> <li><a href="embeddeddoc.wiki">Embedded Project Documentation</a></li> <li><a href="delta_encoder_algorithm.wiki">Encoding Algorithm — Fossil Delta</a></li> <li><a href="event.wiki">Events</a></li> <li><a href="inout.wiki">Export To And From Git — Import And</a></li> <li><a href="fossil-from-msvc.wiki">Express 2010 IDE — Integrating Fossil in the Microsoft</a></li> <li><a href="fileformat.wiki">File Format — Fossil</a></li> <li><a href="branching.wiki">Forking, Merging, and Tagging — Branching,</a></li> <li><a href="delta_format.wiki">Format — Fossil Delta</a></li> <li><a href="fileformat.wiki">Format — Fossil File</a></li> <li><a href="changes.wiki">Fossil Changelog</a></li> <li><a href="concepts.wiki">Fossil Core Concepts</a></li> <li><a href="delta_encoder_algorithm.wiki">Fossil Delta Encoding Algorithm</a></li> | > | 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | <li><a href="theory1.wiki">DVCS — Thoughts On The Design Of The Fossil</a></li> <li><a href="quotes.wiki">DVCSes in General — Quotes: What People Are Saying About Fossil, Git, and</a></li> <li><a href="embeddeddoc.wiki">Embedded Project Documentation</a></li> <li><a href="delta_encoder_algorithm.wiki">Encoding Algorithm — Fossil Delta</a></li> <li><a href="event.wiki">Events</a></li> <li><a href="inout.wiki">Export To And From Git — Import And</a></li> <li><a href="fossil-from-msvc.wiki">Express 2010 IDE — Integrating Fossil in the Microsoft</a></li> <li><a href="adding_code.wiki">Features To Fossil — Adding New</a></li> <li><a href="fileformat.wiki">File Format — Fossil</a></li> <li><a href="branching.wiki">Forking, Merging, and Tagging — Branching,</a></li> <li><a href="delta_format.wiki">Format — Fossil Delta</a></li> <li><a href="fileformat.wiki">Format — Fossil File</a></li> <li><a href="changes.wiki">Fossil Changelog</a></li> <li><a href="concepts.wiki">Fossil Core Concepts</a></li> <li><a href="delta_encoder_algorithm.wiki">Fossil Delta Encoding Algorithm</a></li> |
| ︙ | ︙ | |||
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 | <li><a href="inout.wiki">From Git — Import And Export To And</a></li> <li><a href="quotes.wiki">General — Quotes: What People Are Saying About Fossil, Git, and DVCSes in</a></li> <li><a href="fossil-v-git.wiki">Git — Fossil Versus</a></li> <li><a href="inout.wiki">Git — Import And Export To And From</a></li> <li><a href="quotes.wiki">Git, and DVCSes in General — Quotes: What People Are Saying About Fossil,</a></li> <li><a href="quickstart.wiki">Guide — Fossil Quick Start</a></li> <li><a href="style.wiki">Guidelines — Source Code Style</a></li> <li><a href="hints.wiki">Hints — Fossil Tips And Usage</a></li> <li><a href="index.wiki">Home Page</a></li> <li><a href="selfhost.wiki">Hosting Repositories — Fossil Self</a></li> <li><a href="server.wiki">How To Configure A Fossil Server</a></li> <li><a href="newrepo.wiki">How To Create A New Fossil Repository</a></li> <li><a href="fossil-from-msvc.wiki">IDE — Integrating Fossil in the Microsoft Express 2010</a></li> <li><a href="tech_overview.wiki">Implementation Of Fossil — A Technical Overview Of The Design And</a></li> <li><a href="inout.wiki">Import And Export To And From Git</a></li> <li><a href="build.wiki">Installing Fossil — Compiling and</a></li> <li><a href="fossil-from-msvc.wiki">Integrating Fossil in the Microsoft Express 2010 IDE</a></li> <li><a href="selfcheck.wiki">Integrity Self Checks — Fossil Repository</a></li> <li><a href="webui.wiki">Interface — The Fossil Web</a></li> <li><a href="copyright-release.html">License Agreement — Contributor</a></li> <li><a href="password.wiki">Management And Authentication — Password</a></li> <li><a href="branching.wiki">Merging, and Tagging — Branching, Forking,</a></li> <li><a href="fossil-from-msvc.wiki">Microsoft Express 2010 IDE — Integrating Fossil in the</a></li> <li><a href="fiveminutes.wiki">Minutes as a Single User — Update and Running in 5</a></li> <li><a href="checkin_names.wiki">Names — Checkin And Version</a></li> <li><a href="newrepo.wiki">New Fossil Repository — How To Create A</a></li> <li><a href="foss-cklist.wiki">Open-Source Projects — Checklist For Successful</a></li> <li><a href="pop.wiki">Operations — Principles Of</a></li> <li><a href="tech_overview.wiki">Overview Of The Design And Implementation Of Fossil — A Technical</a></li> <li><a href="index.wiki">Page — Home</a></li> <li><a href="password.wiki">Password Management And Authentication</a></li> <li><a href="quotes.wiki">People Are Saying About Fossil, Git, and DVCSes in General — Quotes: What</a></li> | > > | 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 | <li><a href="inout.wiki">From Git — Import And Export To And</a></li> <li><a href="quotes.wiki">General — Quotes: What People Are Saying About Fossil, Git, and DVCSes in</a></li> <li><a href="fossil-v-git.wiki">Git — Fossil Versus</a></li> <li><a href="inout.wiki">Git — Import And Export To And From</a></li> <li><a href="quotes.wiki">Git, and DVCSes in General — Quotes: What People Are Saying About Fossil,</a></li> <li><a href="quickstart.wiki">Guide — Fossil Quick Start</a></li> <li><a href="style.wiki">Guidelines — Source Code Style</a></li> <li><a href="adding_code.wiki">Hacking Fossil</a></li> <li><a href="hints.wiki">Hints — Fossil Tips And Usage</a></li> <li><a href="index.wiki">Home Page</a></li> <li><a href="selfhost.wiki">Hosting Repositories — Fossil Self</a></li> <li><a href="server.wiki">How To Configure A Fossil Server</a></li> <li><a href="newrepo.wiki">How To Create A New Fossil Repository</a></li> <li><a href="fossil-from-msvc.wiki">IDE — Integrating Fossil in the Microsoft Express 2010</a></li> <li><a href="tech_overview.wiki">Implementation Of Fossil — A Technical Overview Of The Design And</a></li> <li><a href="inout.wiki">Import And Export To And From Git</a></li> <li><a href="build.wiki">Installing Fossil — Compiling and</a></li> <li><a href="fossil-from-msvc.wiki">Integrating Fossil in the Microsoft Express 2010 IDE</a></li> <li><a href="selfcheck.wiki">Integrity Self Checks — Fossil Repository</a></li> <li><a href="webui.wiki">Interface — The Fossil Web</a></li> <li><a href="copyright-release.html">License Agreement — Contributor</a></li> <li><a href="password.wiki">Management And Authentication — Password</a></li> <li><a href="branching.wiki">Merging, and Tagging — Branching, Forking,</a></li> <li><a href="fossil-from-msvc.wiki">Microsoft Express 2010 IDE — Integrating Fossil in the</a></li> <li><a href="fiveminutes.wiki">Minutes as a Single User — Update and Running in 5</a></li> <li><a href="checkin_names.wiki">Names — Checkin And Version</a></li> <li><a href="adding_code.wiki">New Features To Fossil — Adding</a></li> <li><a href="newrepo.wiki">New Fossil Repository — How To Create A</a></li> <li><a href="foss-cklist.wiki">Open-Source Projects — Checklist For Successful</a></li> <li><a href="pop.wiki">Operations — Principles Of</a></li> <li><a href="tech_overview.wiki">Overview Of The Design And Implementation Of Fossil — A Technical</a></li> <li><a href="index.wiki">Page — Home</a></li> <li><a href="password.wiki">Password Management And Authentication</a></li> <li><a href="quotes.wiki">People Are Saying About Fossil, Git, and DVCSes in General — Quotes: What</a></li> |
| ︙ | ︙ |
Changes to www/quickstart.wiki.
| ︙ | ︙ | |||
171 172 173 174 175 176 177 178 179 |
<blockquote>
<b>[/help/commit | fossil commit]</b>
</blockquote>
<p>You will be prompted for check-in comments using whatever editor
is specified by your VISUAL or EDITOR environment variable.</p>
<h2>Sharing Changes</h2>
| > > > > > > > > | | 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 |
<blockquote>
<b>[/help/commit | fossil commit]</b>
</blockquote>
<p>You will be prompted for check-in comments using whatever editor
is specified by your VISUAL or EDITOR environment variable.</p>
In the default configuration, the [/help/commit|commit]
command will also automatically [/help/push|push] your changes, but that
feature can be disabled. (More information about
[./concepts.wiki#workflow|autosync] and how to disable it.)
Remember that your coworkers can not see your changes until you
commit and push them.</p>
<h2>Sharing Changes</h2>
<p>When [./concepts.wiki#workflow|autosync] is turned off,
the changes you [/help/commit | commit] are only
on your local repository.
To share those changes with other repositories, do:</p>
<blockquote>
<b>[/help/push | fossil push]</b> <i>URL</i>
</blockquote>
|
| ︙ | ︙ | |||
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
abbreviation to the 40-character
artifact identifier for a particular check-in, or it can be a
date/time stamp. ([./checkin_names.wiki | more info])
If you omit
the <i>VERSION</i>, then fossil moves you to the
latest version of the branch your are currently on.</p>
<h2>Branching And Merging</h2>
<p>Use the --branch option to the [/help/commit | commit] command
to start a new branch. Note that in Fossil, branches are normally
created when you commit, not before you start editing. You can
use the [/help/branch | branch new] command to create a new branch
before you start editing, if you want, but most people just wait
until they are ready to commit.
To merge two branches back together, first
| > > > > > > > | | > > > | > > | | < < < < < < < < < | | | > | | | > > > > | > > > > > > | 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 |
abbreviation to the 40-character
artifact identifier for a particular check-in, or it can be a
date/time stamp. ([./checkin_names.wiki | more info])
If you omit
the <i>VERSION</i>, then fossil moves you to the
latest version of the branch your are currently on.</p>
<p>The default behaviors is for [./concepts.wiki#workflow|autosync] to
be turned on. That means that a [/help/pull|pull] automatically occurs
when you run [/help/update|update] and a [/help/push|push] happens
automatically after you [/help/commit|commit]. So in normal practice,
the push, pull, and sync commands are rarely used. But it is important
to know about them, all the same.</p>
<h2>Branching And Merging</h2>
<p>Use the --branch option to the [/help/commit | commit] command
to start a new branch. Note that in Fossil, branches are normally
created when you commit, not before you start editing. You can
use the [/help/branch | branch new] command to create a new branch
before you start editing, if you want, but most people just wait
until they are ready to commit.
To merge two branches back together, first
[/help/update | update] to the branch you want to merge into.
Then do a [/help/merge|merge] another branch that you want to incorporate
the changes from. For example, to merge "featureX" changes into "trunk"
do this:</p>
<blockquote>
<b>fossil [/help/update|update] trunk</b><br>
<b>fossil [/help/merge|merge] featureX</b><br>
<i># make sure the merge didn't break anything...</i><br>
<b>fossil [/help/commit|commit]
</blockquote>
<p>The argument to the [/help/merge|merge] command can be any of the
version identifier forms that work for [/help/update|update].
([./checkin_names.wiki|more info].)
The merge command has options to cherrypick individual
changes, or to back out individual changes, if you don't want to
do a full merge.</p>
The merge command puts all changes in your working check-out.
No changes are made to the repository.
You must run [/help/commit|commit] separately
to add the merge changes into your repository to make them persistent
and so that your coworkers can see them.
But before you do that, you will normally want to run a few tests
to verify that the merge didn't cause logic breaks in your code.
The same branch can be merged multiple times without trouble. Fossil
automatically keeps up with things and avoids conflicts when doing
multiple merges. So even if you have merged the featureX branch
into trunk previously, you can do so again and Fossil will automatically
know to pull in only those changes that have occurred since the previous
merge.
<p>If a merge or update doesn't work out (perhaps something breaks or
there are many merge conflicts) then you back up using:</p>
<blockquote>
<b>[/help/undo | fossil undo]</b>
</blockquote>
|
| ︙ | ︙ | |||
278 279 280 281 282 283 284 |
<blockquote>
<b>[/help/ui | fossil ui]</b> <i>repository-filename</i>
</blockquote>
<p>The <b>ui</b> command is intended for accessing the web interface
from a local desktop. The <b>ui</b> command binds to the loopback IP
| | | 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
<blockquote>
<b>[/help/ui | fossil ui]</b> <i>repository-filename</i>
</blockquote>
<p>The <b>ui</b> command is intended for accessing the web interface
from a local desktop. The <b>ui</b> command binds to the loopback IP
address only (and thus makes the web interface visible only on the
local machine) and it automatically start your web browser pointing at the
server. For cross-machine collaboration, use the <b>server</b> command,
which binds on all IP addresses and does not try to start a web browser.
You can omit the <i>repository-filename</i> if you are within
a checked-out local tree. The <b>server</b> uses port 8080 by default
but you can specify a different port using the <b>-port</b> option.</p>
|
| ︙ | ︙ | |||
319 320 321 322 323 324 325 |
</b></blockquote>
<p>Adjust the paths to suit your installation, of course. Notice that
fossil runs as root. This is not required - you can run it as an
unprivileged user. But it is more secure to run fossil as root.
When you do run fossil as root, it automatically puts itself in a
chroot jail in the same directory as the repository, then drops
| | | 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 |
</b></blockquote>
<p>Adjust the paths to suit your installation, of course. Notice that
fossil runs as root. This is not required - you can run it as an
unprivileged user. But it is more secure to run fossil as root.
When you do run fossil as root, it automatically puts itself in a
chroot jail in the same directory as the repository, then drops
root privileges prior to reading any information from the socket.</p>
<a name="proxy"></a>
<h2>HTTP Proxies</h2>
<p>If you are behind a restrictive firewall that requires you to use
an HTTP proxy to reach the internet, then you can configure the proxy
in three different ways. You can tell fossil about your proxy using
|
| ︙ | ︙ | |||
367 368 369 370 371 372 373 |
<blockquote>
<b>fossil sync http://192.168.1.36:8080/ --proxy off</b>
</blockquote>
<h2>More Hints</h2>
| | > > > | 389 390 391 392 393 394 395 396 397 398 399 400 401 |
<blockquote>
<b>fossil sync http://192.168.1.36:8080/ --proxy off</b>
</blockquote>
<h2>More Hints</h2>
<p>A [/help | complete list of commands] is available, as is the
[./hints.wiki|helpful hints] document. See the
[./permutedindex.wiki#pindex|permuted index] for additional
documentation.
<p>Explore and have fun!</p>
|
Changes to www/server.wiki.
| ︙ | ︙ | |||
105 106 107 108 109 110 111 | </blockquote> <h2>Various security concerns with hosted repositories</h2><blockquote> <p> There are two main concerns relating to usage of Fossil for sharing sensitive information (source or any other data): <ul> <li>Interception of the Fossil synchronization stream, thereby capturing data, and | | > | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | </blockquote> <h2>Various security concerns with hosted repositories</h2><blockquote> <p> There are two main concerns relating to usage of Fossil for sharing sensitive information (source or any other data): <ul> <li>Interception of the Fossil synchronization stream, thereby capturing data, and <li>Direct access to the Fossil repository on the server </ul> </p> <p> Regarding the first, it is adequate to secure the server using SSL, and disallowing any non-SSL access. The data stream will be encrypted by the HTTPS protocol, rendering the data reasonably secure. The truly paranoid may wish to deploy <i>ssh</i> encrypted tunnels, but that is quite a bit more difficult and cumbersome to set up (particularly for a larger number of users). </p> <p> As far as direct access to the repository, the same steps must be taken as for any other internet-facing data-store. Access passwords to any disk-accessing accounts should be strong (and preferably changed from time to time). However, the data in the repository itself are <i>not</i> encrypted (unless you save encrypted data yourself), and so the system administrators of your server will be able to access your data (as with any hosting service setup). The only workaround in this case is to host the server yourself, in which case you will need to allocate resources to deal with administration issues. </p> |
| ︙ | ︙ |
Changes to www/tech_overview.wiki.
| ︙ | ︙ | |||
330 331 332 333 334 335 336 | fossil close command really isn't needed; one can accomplish the same thing simply by deleting the checkout database. Note that the stash, the undo stack, and the state of the bisect command are all contained within the checkout database. That means that the fossil close command will delete all stash content, the undo stack, and the bisect state. The close command is not undoable. Use it with care. | > > > > > > | 330 331 332 333 334 335 336 337 338 339 340 341 342 | fossil close command really isn't needed; one can accomplish the same thing simply by deleting the checkout database. Note that the stash, the undo stack, and the state of the bisect command are all contained within the checkout database. That means that the fossil close command will delete all stash content, the undo stack, and the bisect state. The close command is not undoable. Use it with care. <h2>3.0 See Also</h2> * [./makefile.wiki | The Fossil Build Process] * [./contribute.wiki | How To Contribute Code To Fossil] * [./adding_code.wiki | Adding New Features To Fossil] |