Fossil SCM
Sync with trunk to get sqlite changes et al.
Commit
021e41014d69a67b767f494a12bbff76c0261eaa
Parent
1ebba56f2aa59a8…
44 files changed
+2
+17
-9
+9
-2
+9
-2
+202
-516
+307
-38
+5
-5
+94
-78
+119
+12
-2
+2
+23
-4
+29
-7
+29
-29
+1
-3
+5
-5
+320
-126
+47
-18
+47
-9
+228
-39
+15
+2
-2
+3
-3
+14
-14
+2
-2
+1
-1
+2
-2
+10
-4
+12
+12
+10
+1
+7
+1
+4
-4
+4
-4
+31
-18
+5
-3
+7
+2
+4
+51
-26
+2
-1
+6
~
src/blob.c
~
src/checkin.c
~
src/db.c
~
src/db.c
~
src/diff.c
~
src/diffcmd.c
~
src/event.c
~
src/info.c
~
src/lookslike.c
~
src/main.mk
~
src/makemake.tcl
~
src/merge3.c
~
src/search.c
~
src/setup.c
~
src/shell.c
~
src/shun.c
~
src/sqlite3.c
~
src/sqlite3.h
~
src/style.c
~
src/timeline.c
~
src/translate.c
~
src/wiki.c
~
test/diff-test-1.wiki
~
test/merge1.test
~
test/merge2.test
~
test/merge3.test
~
test/merge4.test
~
win/Makefile.dmc
~
win/Makefile.mingw
~
win/Makefile.mingw.mistachkin
~
win/Makefile.msc
~
www/adding_code.wiki
~
www/build.wiki
~
www/contribute.wiki
~
www/faq.tcl
~
www/faq.wiki
~
www/fossil-v-git.wiki
~
www/hints.wiki
~
www/makefile.wiki
~
www/mkindex.tcl
~
www/permutedindex.wiki
~
www/quickstart.wiki
~
www/server.wiki
~
www/tech_overview.wiki
+2
| --- src/blob.c | ||
| +++ src/blob.c | ||
| @@ -1096,11 +1096,13 @@ | ||
| 1096 | 1096 | ** to be UTF-8 already, so no conversion is done. |
| 1097 | 1097 | */ |
| 1098 | 1098 | void blob_to_utf8_no_bom(Blob *pBlob, int useMbcs){ |
| 1099 | 1099 | char *zUtf8; |
| 1100 | 1100 | int bomSize = 0; |
| 1101 | +#if defined(_WIN32) || defined(__CYGWIN__) | |
| 1101 | 1102 | int bomReverse = 0; |
| 1103 | +#endif | |
| 1102 | 1104 | if( starts_with_utf8_bom(pBlob, &bomSize) ){ |
| 1103 | 1105 | struct Blob temp; |
| 1104 | 1106 | zUtf8 = blob_str(pBlob) + bomSize; |
| 1105 | 1107 | blob_zero(&temp); |
| 1106 | 1108 | blob_append(&temp, zUtf8, -1); |
| 1107 | 1109 |
| --- src/blob.c | |
| +++ src/blob.c | |
| @@ -1096,11 +1096,13 @@ | |
| 1096 | ** to be UTF-8 already, so no conversion is done. |
| 1097 | */ |
| 1098 | void blob_to_utf8_no_bom(Blob *pBlob, int useMbcs){ |
| 1099 | char *zUtf8; |
| 1100 | int bomSize = 0; |
| 1101 | int bomReverse = 0; |
| 1102 | if( starts_with_utf8_bom(pBlob, &bomSize) ){ |
| 1103 | struct Blob temp; |
| 1104 | zUtf8 = blob_str(pBlob) + bomSize; |
| 1105 | blob_zero(&temp); |
| 1106 | blob_append(&temp, zUtf8, -1); |
| 1107 |
| --- src/blob.c | |
| +++ src/blob.c | |
| @@ -1096,11 +1096,13 @@ | |
| 1096 | ** to be UTF-8 already, so no conversion is done. |
| 1097 | */ |
| 1098 | void blob_to_utf8_no_bom(Blob *pBlob, int useMbcs){ |
| 1099 | char *zUtf8; |
| 1100 | int bomSize = 0; |
| 1101 | #if defined(_WIN32) || defined(__CYGWIN__) |
| 1102 | int bomReverse = 0; |
| 1103 | #endif |
| 1104 | if( starts_with_utf8_bom(pBlob, &bomSize) ){ |
| 1105 | struct Blob temp; |
| 1106 | zUtf8 = blob_str(pBlob) + bomSize; |
| 1107 | blob_zero(&temp); |
| 1108 | blob_append(&temp, zUtf8, -1); |
| 1109 |
+17
-9
| --- src/checkin.c | ||
| +++ src/checkin.c | ||
| @@ -103,16 +103,16 @@ | ||
| 103 | 103 | } |
| 104 | 104 | }else if( isNew ){ |
| 105 | 105 | blob_appendf(report, "ADDED %s\n", zDisplayName); |
| 106 | 106 | }else if( isDeleted ){ |
| 107 | 107 | blob_appendf(report, "DELETED %s\n", zDisplayName); |
| 108 | - }else if( isChnged==2 ){ | |
| 109 | - blob_appendf(report, "UPDATED_BY_MERGE %s\n", zDisplayName); | |
| 110 | - }else if( isChnged==3 ){ | |
| 111 | - blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName); | |
| 112 | - }else if( isChnged==1 ){ | |
| 113 | - if( file_contains_merge_marker(zFullName) ){ | |
| 108 | + }else if( isChnged ){ | |
| 109 | + if( isChnged==2 ){ | |
| 110 | + blob_appendf(report, "UPDATED_BY_MERGE %s\n", zDisplayName); | |
| 111 | + }else if( isChnged==3 ){ | |
| 112 | + blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName); | |
| 113 | + }else if( file_contains_merge_marker(zFullName) ){ | |
| 114 | 114 | blob_appendf(report, "CONFLICT %s\n", zDisplayName); |
| 115 | 115 | }else{ |
| 116 | 116 | blob_appendf(report, "EDITED %s\n", zDisplayName); |
| 117 | 117 | } |
| 118 | 118 | }else if( isRenamed ){ |
| @@ -127,12 +127,12 @@ | ||
| 127 | 127 | db_prepare(&q, "SELECT uuid, id FROM vmerge JOIN blob ON merge=rid" |
| 128 | 128 | " WHERE id<=0"); |
| 129 | 129 | while( db_step(&q)==SQLITE_ROW ){ |
| 130 | 130 | const char *zLabel = "MERGED_WITH"; |
| 131 | 131 | switch( db_column_int(&q, 1) ){ |
| 132 | - case -1: zLabel = "CHERRYPICK"; break; | |
| 133 | - case -2: zLabel = "BACKOUT "; break; | |
| 132 | + case -1: zLabel = "CHERRYPICK "; break; | |
| 133 | + case -2: zLabel = "BACKOUT "; break; | |
| 134 | 134 | } |
| 135 | 135 | blob_append(report, zPrefix, nPrefix); |
| 136 | 136 | blob_appendf(report, "%s %s\n", zLabel, db_column_text(&q, 0)); |
| 137 | 137 | } |
| 138 | 138 | db_finalize(&q); |
| @@ -328,11 +328,19 @@ | ||
| 328 | 328 | type = "NOT_A_FILE "; |
| 329 | 329 | }else{ |
| 330 | 330 | type = "MISSING "; |
| 331 | 331 | } |
| 332 | 332 | }else if( chnged ){ |
| 333 | - type = "EDITED "; | |
| 333 | + if( chnged==2 ){ | |
| 334 | + type = "UPDATED_BY_MERGE "; | |
| 335 | + }else if( chnged==3 ){ | |
| 336 | + type = "ADDED_BY_MERGE "; | |
| 337 | + }else if( file_contains_merge_marker(zFullName) ){ | |
| 338 | + type = "CONFLICT "; | |
| 339 | + }else{ | |
| 340 | + type = "EDITED "; | |
| 341 | + } | |
| 334 | 342 | }else if( renamed ){ |
| 335 | 343 | type = "RENAMED "; |
| 336 | 344 | }else{ |
| 337 | 345 | type = "UNCHANGED "; |
| 338 | 346 | } |
| 339 | 347 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -103,16 +103,16 @@ | |
| 103 | } |
| 104 | }else if( isNew ){ |
| 105 | blob_appendf(report, "ADDED %s\n", zDisplayName); |
| 106 | }else if( isDeleted ){ |
| 107 | blob_appendf(report, "DELETED %s\n", zDisplayName); |
| 108 | }else if( isChnged==2 ){ |
| 109 | blob_appendf(report, "UPDATED_BY_MERGE %s\n", zDisplayName); |
| 110 | }else if( isChnged==3 ){ |
| 111 | blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName); |
| 112 | }else if( isChnged==1 ){ |
| 113 | if( file_contains_merge_marker(zFullName) ){ |
| 114 | blob_appendf(report, "CONFLICT %s\n", zDisplayName); |
| 115 | }else{ |
| 116 | blob_appendf(report, "EDITED %s\n", zDisplayName); |
| 117 | } |
| 118 | }else if( isRenamed ){ |
| @@ -127,12 +127,12 @@ | |
| 127 | db_prepare(&q, "SELECT uuid, id FROM vmerge JOIN blob ON merge=rid" |
| 128 | " WHERE id<=0"); |
| 129 | while( db_step(&q)==SQLITE_ROW ){ |
| 130 | const char *zLabel = "MERGED_WITH"; |
| 131 | switch( db_column_int(&q, 1) ){ |
| 132 | case -1: zLabel = "CHERRYPICK"; break; |
| 133 | case -2: zLabel = "BACKOUT "; break; |
| 134 | } |
| 135 | blob_append(report, zPrefix, nPrefix); |
| 136 | blob_appendf(report, "%s %s\n", zLabel, db_column_text(&q, 0)); |
| 137 | } |
| 138 | db_finalize(&q); |
| @@ -328,11 +328,19 @@ | |
| 328 | type = "NOT_A_FILE "; |
| 329 | }else{ |
| 330 | type = "MISSING "; |
| 331 | } |
| 332 | }else if( chnged ){ |
| 333 | type = "EDITED "; |
| 334 | }else if( renamed ){ |
| 335 | type = "RENAMED "; |
| 336 | }else{ |
| 337 | type = "UNCHANGED "; |
| 338 | } |
| 339 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -103,16 +103,16 @@ | |
| 103 | } |
| 104 | }else if( isNew ){ |
| 105 | blob_appendf(report, "ADDED %s\n", zDisplayName); |
| 106 | }else if( isDeleted ){ |
| 107 | blob_appendf(report, "DELETED %s\n", zDisplayName); |
| 108 | }else if( isChnged ){ |
| 109 | if( isChnged==2 ){ |
| 110 | blob_appendf(report, "UPDATED_BY_MERGE %s\n", zDisplayName); |
| 111 | }else if( isChnged==3 ){ |
| 112 | blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName); |
| 113 | }else if( file_contains_merge_marker(zFullName) ){ |
| 114 | blob_appendf(report, "CONFLICT %s\n", zDisplayName); |
| 115 | }else{ |
| 116 | blob_appendf(report, "EDITED %s\n", zDisplayName); |
| 117 | } |
| 118 | }else if( isRenamed ){ |
| @@ -127,12 +127,12 @@ | |
| 127 | db_prepare(&q, "SELECT uuid, id FROM vmerge JOIN blob ON merge=rid" |
| 128 | " WHERE id<=0"); |
| 129 | while( db_step(&q)==SQLITE_ROW ){ |
| 130 | const char *zLabel = "MERGED_WITH"; |
| 131 | switch( db_column_int(&q, 1) ){ |
| 132 | case -1: zLabel = "CHERRYPICK "; break; |
| 133 | case -2: zLabel = "BACKOUT "; break; |
| 134 | } |
| 135 | blob_append(report, zPrefix, nPrefix); |
| 136 | blob_appendf(report, "%s %s\n", zLabel, db_column_text(&q, 0)); |
| 137 | } |
| 138 | db_finalize(&q); |
| @@ -328,11 +328,19 @@ | |
| 328 | type = "NOT_A_FILE "; |
| 329 | }else{ |
| 330 | type = "MISSING "; |
| 331 | } |
| 332 | }else if( chnged ){ |
| 333 | if( chnged==2 ){ |
| 334 | type = "UPDATED_BY_MERGE "; |
| 335 | }else if( chnged==3 ){ |
| 336 | type = "ADDED_BY_MERGE "; |
| 337 | }else if( file_contains_merge_marker(zFullName) ){ |
| 338 | type = "CONFLICT "; |
| 339 | }else{ |
| 340 | type = "EDITED "; |
| 341 | } |
| 342 | }else if( renamed ){ |
| 343 | type = "RENAMED "; |
| 344 | }else{ |
| 345 | type = "UNCHANGED "; |
| 346 | } |
| 347 |
M
src/db.c
+9
-2
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -712,10 +712,13 @@ | ||
| 712 | 712 | LOCAL sqlite3 *db_open(const char *zDbName){ |
| 713 | 713 | int rc; |
| 714 | 714 | const char *zVfs; |
| 715 | 715 | sqlite3 *db; |
| 716 | 716 | |
| 717 | +#if defined(__CYGWIN__) | |
| 718 | + zDbName = fossil_utf8_to_filename(zDbName); | |
| 719 | +#endif | |
| 717 | 720 | if( g.fSqlTrace ) fossil_trace("-- sqlite3_open: [%s]\n", zDbName); |
| 718 | 721 | zVfs = fossil_getenv("FOSSIL_VFS"); |
| 719 | 722 | rc = sqlite3_open_v2( |
| 720 | 723 | zDbName, &db, |
| 721 | 724 | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, |
| @@ -1020,13 +1023,17 @@ | ||
| 1020 | 1023 | g.json.resultCode = FSL_JSON_E_DB_NOT_VALID; |
| 1021 | 1024 | #endif |
| 1022 | 1025 | fossil_panic("not a valid repository: %s", zDbName); |
| 1023 | 1026 | } |
| 1024 | 1027 | } |
| 1025 | - db_open_or_attach(zDbName, "repository", 0); | |
| 1026 | - g.repositoryOpen = 1; | |
| 1028 | +#if defined(__CYGWIN__) | |
| 1029 | + g.zRepositoryName = fossil_utf8_to_filename(zDbName); | |
| 1030 | +#else | |
| 1027 | 1031 | g.zRepositoryName = mprintf("%s", zDbName); |
| 1032 | +#endif | |
| 1033 | + db_open_or_attach(g.zRepositoryName, "repository", 0); | |
| 1034 | + g.repositoryOpen = 1; | |
| 1028 | 1035 | /* Cache "allow-symlinks" option, because we'll need it on every stat call */ |
| 1029 | 1036 | g.allowSymlinks = db_get_boolean("allow-symlinks", 0); |
| 1030 | 1037 | } |
| 1031 | 1038 | |
| 1032 | 1039 | /* |
| 1033 | 1040 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -712,10 +712,13 @@ | |
| 712 | LOCAL sqlite3 *db_open(const char *zDbName){ |
| 713 | int rc; |
| 714 | const char *zVfs; |
| 715 | sqlite3 *db; |
| 716 | |
| 717 | if( g.fSqlTrace ) fossil_trace("-- sqlite3_open: [%s]\n", zDbName); |
| 718 | zVfs = fossil_getenv("FOSSIL_VFS"); |
| 719 | rc = sqlite3_open_v2( |
| 720 | zDbName, &db, |
| 721 | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, |
| @@ -1020,13 +1023,17 @@ | |
| 1020 | g.json.resultCode = FSL_JSON_E_DB_NOT_VALID; |
| 1021 | #endif |
| 1022 | fossil_panic("not a valid repository: %s", zDbName); |
| 1023 | } |
| 1024 | } |
| 1025 | db_open_or_attach(zDbName, "repository", 0); |
| 1026 | g.repositoryOpen = 1; |
| 1027 | g.zRepositoryName = mprintf("%s", zDbName); |
| 1028 | /* Cache "allow-symlinks" option, because we'll need it on every stat call */ |
| 1029 | g.allowSymlinks = db_get_boolean("allow-symlinks", 0); |
| 1030 | } |
| 1031 | |
| 1032 | /* |
| 1033 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -712,10 +712,13 @@ | |
| 712 | LOCAL sqlite3 *db_open(const char *zDbName){ |
| 713 | int rc; |
| 714 | const char *zVfs; |
| 715 | sqlite3 *db; |
| 716 | |
| 717 | #if defined(__CYGWIN__) |
| 718 | zDbName = fossil_utf8_to_filename(zDbName); |
| 719 | #endif |
| 720 | if( g.fSqlTrace ) fossil_trace("-- sqlite3_open: [%s]\n", zDbName); |
| 721 | zVfs = fossil_getenv("FOSSIL_VFS"); |
| 722 | rc = sqlite3_open_v2( |
| 723 | zDbName, &db, |
| 724 | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, |
| @@ -1020,13 +1023,17 @@ | |
| 1023 | g.json.resultCode = FSL_JSON_E_DB_NOT_VALID; |
| 1024 | #endif |
| 1025 | fossil_panic("not a valid repository: %s", zDbName); |
| 1026 | } |
| 1027 | } |
| 1028 | #if defined(__CYGWIN__) |
| 1029 | g.zRepositoryName = fossil_utf8_to_filename(zDbName); |
| 1030 | #else |
| 1031 | g.zRepositoryName = mprintf("%s", zDbName); |
| 1032 | #endif |
| 1033 | db_open_or_attach(g.zRepositoryName, "repository", 0); |
| 1034 | g.repositoryOpen = 1; |
| 1035 | /* Cache "allow-symlinks" option, because we'll need it on every stat call */ |
| 1036 | g.allowSymlinks = db_get_boolean("allow-symlinks", 0); |
| 1037 | } |
| 1038 | |
| 1039 | /* |
| 1040 |
M
src/db.c
+9
-2
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -712,10 +712,13 @@ | ||
| 712 | 712 | LOCAL sqlite3 *db_open(const char *zDbName){ |
| 713 | 713 | int rc; |
| 714 | 714 | const char *zVfs; |
| 715 | 715 | sqlite3 *db; |
| 716 | 716 | |
| 717 | +#if defined(__CYGWIN__) | |
| 718 | + zDbName = fossil_utf8_to_filename(zDbName); | |
| 719 | +#endif | |
| 717 | 720 | if( g.fSqlTrace ) fossil_trace("-- sqlite3_open: [%s]\n", zDbName); |
| 718 | 721 | zVfs = fossil_getenv("FOSSIL_VFS"); |
| 719 | 722 | rc = sqlite3_open_v2( |
| 720 | 723 | zDbName, &db, |
| 721 | 724 | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, |
| @@ -1020,13 +1023,17 @@ | ||
| 1020 | 1023 | g.json.resultCode = FSL_JSON_E_DB_NOT_VALID; |
| 1021 | 1024 | #endif |
| 1022 | 1025 | fossil_panic("not a valid repository: %s", zDbName); |
| 1023 | 1026 | } |
| 1024 | 1027 | } |
| 1025 | - db_open_or_attach(zDbName, "repository", 0); | |
| 1026 | - g.repositoryOpen = 1; | |
| 1028 | +#if defined(__CYGWIN__) | |
| 1029 | + g.zRepositoryName = fossil_utf8_to_filename(zDbName); | |
| 1030 | +#else | |
| 1027 | 1031 | g.zRepositoryName = mprintf("%s", zDbName); |
| 1032 | +#endif | |
| 1033 | + db_open_or_attach(g.zRepositoryName, "repository", 0); | |
| 1034 | + g.repositoryOpen = 1; | |
| 1028 | 1035 | /* Cache "allow-symlinks" option, because we'll need it on every stat call */ |
| 1029 | 1036 | g.allowSymlinks = db_get_boolean("allow-symlinks", 0); |
| 1030 | 1037 | } |
| 1031 | 1038 | |
| 1032 | 1039 | /* |
| 1033 | 1040 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -712,10 +712,13 @@ | |
| 712 | LOCAL sqlite3 *db_open(const char *zDbName){ |
| 713 | int rc; |
| 714 | const char *zVfs; |
| 715 | sqlite3 *db; |
| 716 | |
| 717 | if( g.fSqlTrace ) fossil_trace("-- sqlite3_open: [%s]\n", zDbName); |
| 718 | zVfs = fossil_getenv("FOSSIL_VFS"); |
| 719 | rc = sqlite3_open_v2( |
| 720 | zDbName, &db, |
| 721 | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, |
| @@ -1020,13 +1023,17 @@ | |
| 1020 | g.json.resultCode = FSL_JSON_E_DB_NOT_VALID; |
| 1021 | #endif |
| 1022 | fossil_panic("not a valid repository: %s", zDbName); |
| 1023 | } |
| 1024 | } |
| 1025 | db_open_or_attach(zDbName, "repository", 0); |
| 1026 | g.repositoryOpen = 1; |
| 1027 | g.zRepositoryName = mprintf("%s", zDbName); |
| 1028 | /* Cache "allow-symlinks" option, because we'll need it on every stat call */ |
| 1029 | g.allowSymlinks = db_get_boolean("allow-symlinks", 0); |
| 1030 | } |
| 1031 | |
| 1032 | /* |
| 1033 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -712,10 +712,13 @@ | |
| 712 | LOCAL sqlite3 *db_open(const char *zDbName){ |
| 713 | int rc; |
| 714 | const char *zVfs; |
| 715 | sqlite3 *db; |
| 716 | |
| 717 | #if defined(__CYGWIN__) |
| 718 | zDbName = fossil_utf8_to_filename(zDbName); |
| 719 | #endif |
| 720 | if( g.fSqlTrace ) fossil_trace("-- sqlite3_open: [%s]\n", zDbName); |
| 721 | zVfs = fossil_getenv("FOSSIL_VFS"); |
| 722 | rc = sqlite3_open_v2( |
| 723 | zDbName, &db, |
| 724 | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, |
| @@ -1020,13 +1023,17 @@ | |
| 1023 | g.json.resultCode = FSL_JSON_E_DB_NOT_VALID; |
| 1024 | #endif |
| 1025 | fossil_panic("not a valid repository: %s", zDbName); |
| 1026 | } |
| 1027 | } |
| 1028 | #if defined(__CYGWIN__) |
| 1029 | g.zRepositoryName = fossil_utf8_to_filename(zDbName); |
| 1030 | #else |
| 1031 | g.zRepositoryName = mprintf("%s", zDbName); |
| 1032 | #endif |
| 1033 | db_open_or_attach(g.zRepositoryName, "repository", 0); |
| 1034 | g.repositoryOpen = 1; |
| 1035 | /* Cache "allow-symlinks" option, because we'll need it on every stat call */ |
| 1036 | g.allowSymlinks = db_get_boolean("allow-symlinks", 0); |
| 1037 | } |
| 1038 | |
| 1039 | /* |
| 1040 |
+202
-516
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -51,47 +51,20 @@ | ||
| 51 | 51 | "cannot compute difference between binary files\n" |
| 52 | 52 | |
| 53 | 53 | #define DIFF_CANNOT_COMPUTE_SYMLINK \ |
| 54 | 54 | "cannot compute difference between symlink and regular file\n" |
| 55 | 55 | |
| 56 | -#define DIFF_TOO_MANY_CHANGES_TXT \ | |
| 56 | +#define DIFF_TOO_MANY_CHANGES \ | |
| 57 | 57 | "more than 10,000 changes\n" |
| 58 | 58 | |
| 59 | -#define DIFF_TOO_MANY_CHANGES_HTML \ | |
| 60 | - "<p class='generalError'>More than 10,000 changes</p>\n" | |
| 61 | - | |
| 62 | -/* | |
| 63 | -** This macro is designed to return non-zero if the specified blob contains | |
| 64 | -** data that MAY be binary in nature; otherwise, zero will be returned. | |
| 65 | -*/ | |
| 66 | -#define looks_like_binary(blob) \ | |
| 67 | - ((looks_like_utf8((blob), LOOK_BINARY) & LOOK_BINARY) != LOOK_NONE) | |
| 68 | - | |
| 69 | -/* | |
| 70 | -** Output flags for the looks_like_utf8() and looks_like_utf16() routines used | |
| 71 | -** to convey status information about the blob content. | |
| 72 | -*/ | |
| 73 | -#define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */ | |
| 74 | -#define LOOK_NUL ((int)0x00000001) /* One or more NUL chars were found. */ | |
| 75 | -#define LOOK_CR ((int)0x00000002) /* One or more CR chars were found. */ | |
| 76 | -#define LOOK_LONE_CR ((int)0x00000004) /* An unpaired CR char was found. */ | |
| 77 | -#define LOOK_LF ((int)0x00000008) /* One or more LF chars were found. */ | |
| 78 | -#define LOOK_LONE_LF ((int)0x00000010) /* An unpaired LF char was found. */ | |
| 79 | -#define LOOK_CRLF ((int)0x00000020) /* One or more CR/LF pairs were found. */ | |
| 80 | -#define LOOK_LONG ((int)0x00000040) /* An over length line was found. */ | |
| 81 | -#define LOOK_ODD ((int)0x00000080) /* An odd number of bytes was found. */ | |
| 82 | -#define LOOK_SHORT ((int)0x00000100) /* Unable to perform full check. */ | |
| 83 | -#define LOOK_INVALID ((int)0x00000200) /* Invalid sequence was found. */ | |
| 84 | -#define LOOK_BINARY (LOOK_NUL | LOOK_LONG | LOOK_SHORT) /* May be binary. */ | |
| 85 | -#define LOOK_EOL (LOOK_LONE_CR | LOOK_LONE_LF | LOOK_CRLF) /* Line seps. */ | |
| 86 | -#endif /* INTERFACE */ | |
| 87 | - | |
| 88 | 59 | /* |
| 89 | 60 | ** Maximum length of a line in a text file, in bytes. (2**13 = 8192 bytes) |
| 90 | 61 | */ |
| 91 | 62 | #define LENGTH_MASK_SZ 13 |
| 92 | 63 | #define LENGTH_MASK ((1<<LENGTH_MASK_SZ)-1) |
| 64 | + | |
| 65 | +#endif /* INTERFACE */ | |
| 93 | 66 | |
| 94 | 67 | /* |
| 95 | 68 | ** Information about each line of a file being diffed. |
| 96 | 69 | ** |
| 97 | 70 | ** The lower LENGTH_MASK_SZ bits of the hash (DLine.h) are the length |
| @@ -204,282 +177,10 @@ | ||
| 204 | 177 | /* Return results */ |
| 205 | 178 | *pnLine = nLine; |
| 206 | 179 | return a; |
| 207 | 180 | } |
| 208 | 181 | |
| 209 | -/* | |
| 210 | -** This function attempts to scan each logical line within the blob to | |
| 211 | -** determine the type of content it appears to contain. The return value | |
| 212 | -** is a combination of one or more of the LOOK_XXX flags (see above): | |
| 213 | -** | |
| 214 | -** !LOOK_BINARY -- The content appears to consist entirely of text; however, | |
| 215 | -** the encoding may not be UTF-8. | |
| 216 | -** | |
| 217 | -** LOOK_BINARY -- The content appears to be binary because it contains one | |
| 218 | -** or more embedded NUL characters or an extremely long line. | |
| 219 | -** Since this function does not understand UTF-16, it may | |
| 220 | -** falsely consider UTF-16 text to be binary. | |
| 221 | -** | |
| 222 | -** Additional flags (i.e. those other than the ones included in LOOK_BINARY) | |
| 223 | -** may be present in the result as well; however, they should not impact the | |
| 224 | -** determination of text versus binary content. | |
| 225 | -** | |
| 226 | -************************************ WARNING ********************************** | |
| 227 | -** | |
| 228 | -** This function does not validate that the blob content is properly formed | |
| 229 | -** UTF-8. It assumes that all code points are the same size. It does not | |
| 230 | -** validate any code points. It makes no attempt to detect if any [invalid] | |
| 231 | -** switches between UTF-8 and other encodings occur. | |
| 232 | -** | |
| 233 | -** The only code points that this function cares about are the NUL character, | |
| 234 | -** carriage-return, and line-feed. | |
| 235 | -** | |
| 236 | -** This function examines the contents of the blob until one of the flags | |
| 237 | -** specified in "stopFlags" is set. | |
| 238 | -** | |
| 239 | -************************************ WARNING ********************************** | |
| 240 | -*/ | |
| 241 | -int looks_like_utf8(const Blob *pContent, int stopFlags){ | |
| 242 | - const char *z = blob_buffer(pContent); | |
| 243 | - unsigned int n = blob_size(pContent); | |
| 244 | - int j, c, flags = LOOK_NONE; /* Assume UTF-8 text, prove otherwise */ | |
| 245 | - | |
| 246 | - if( n==0 ) return flags; /* Empty file -> text */ | |
| 247 | - c = *z; | |
| 248 | - if( c==0 ){ | |
| 249 | - flags |= LOOK_NUL; /* NUL character in a file -> binary */ | |
| 250 | - }else if( c=='\r' ){ | |
| 251 | - flags |= LOOK_CR; | |
| 252 | - if( n<=1 || z[1]!='\n' ){ | |
| 253 | - flags |= LOOK_LONE_CR; /* More chars, next char is not LF */ | |
| 254 | - } | |
| 255 | - } | |
| 256 | - j = (c!='\n'); | |
| 257 | - if( !j ) flags |= (LOOK_LF | LOOK_LONE_LF); /* Found LF as first char */ | |
| 258 | - while( !(flags&stopFlags) && --n>0 ){ | |
| 259 | - int c2 = c; | |
| 260 | - c = *++z; ++j; | |
| 261 | - if( c==0 ){ | |
| 262 | - flags |= LOOK_NUL; /* NUL character in a file -> binary */ | |
| 263 | - }else if( c=='\n' ){ | |
| 264 | - flags |= LOOK_LF; | |
| 265 | - if( c2=='\r' ){ | |
| 266 | - flags |= (LOOK_CR | LOOK_CRLF); /* Found LF preceded by CR */ | |
| 267 | - }else{ | |
| 268 | - flags |= LOOK_LONE_LF; | |
| 269 | - } | |
| 270 | - if( j>LENGTH_MASK ){ | |
| 271 | - flags |= LOOK_LONG; /* Very long line -> binary */ | |
| 272 | - } | |
| 273 | - j = 0; | |
| 274 | - }else if( c=='\r' ){ | |
| 275 | - flags |= LOOK_CR; | |
| 276 | - if( n<=1 || z[1]!='\n' ){ | |
| 277 | - flags |= LOOK_LONE_CR; /* More chars, next char is not LF */ | |
| 278 | - } | |
| 279 | - } | |
| 280 | - } | |
| 281 | - if( n ){ | |
| 282 | - flags |= LOOK_SHORT; /* The whole blob was not examined */ | |
| 283 | - } | |
| 284 | - if( j>LENGTH_MASK ){ | |
| 285 | - flags |= LOOK_LONG; /* Very long line -> binary */ | |
| 286 | - } | |
| 287 | - return flags; | |
| 288 | -} | |
| 289 | - | |
| 290 | -/* | |
| 291 | -** Define the type needed to represent a Unicode (UTF-16) character. | |
| 292 | -*/ | |
| 293 | -#ifndef WCHAR_T | |
| 294 | -# ifdef _WIN32 | |
| 295 | -# define WCHAR_T wchar_t | |
| 296 | -# else | |
| 297 | -# define WCHAR_T unsigned short | |
| 298 | -# endif | |
| 299 | -#endif | |
| 300 | - | |
| 301 | -/* | |
| 302 | -** Maximum length of a line in a text file, in UTF-16 characters. (4096) | |
| 303 | -** The number of bytes represented by this value cannot exceed LENGTH_MASK | |
| 304 | -** bytes, because that is the line buffer size used by the diff engine. | |
| 305 | -*/ | |
| 306 | -#define UTF16_LENGTH_MASK_SZ (LENGTH_MASK_SZ-(sizeof(WCHAR_T)-sizeof(char))) | |
| 307 | -#define UTF16_LENGTH_MASK ((1<<UTF16_LENGTH_MASK_SZ)-1) | |
| 308 | - | |
| 309 | -/* | |
| 310 | -** This macro is used to swap the byte order of a UTF-16 character in the | |
| 311 | -** looks_like_utf16() function. | |
| 312 | -*/ | |
| 313 | -#define UTF16_SWAP(ch) ((((ch) << 8) & 0xFF00) | (((ch) >> 8) & 0xFF)) | |
| 314 | -#define UTF16_SWAP_IF(expr,ch) ((expr) ? UTF16_SWAP((ch)) : (ch)) | |
| 315 | - | |
| 316 | -/* | |
| 317 | -** This function attempts to scan each logical line within the blob to | |
| 318 | -** determine the type of content it appears to contain. The return value | |
| 319 | -** is a combination of one or more of the LOOK_XXX flags (see above): | |
| 320 | -** | |
| 321 | -** !LOOK_BINARY -- The content appears to consist entirely of text; however, | |
| 322 | -** the encoding may not be UTF-16. | |
| 323 | -** | |
| 324 | -** LOOK_BINARY -- The content appears to be binary because it contains one | |
| 325 | -** or more embedded NUL characters or an extremely long line. | |
| 326 | -** Since this function does not understand UTF-8, it may | |
| 327 | -** falsely consider UTF-8 text to be binary. | |
| 328 | -** | |
| 329 | -** Additional flags (i.e. those other than the ones included in LOOK_BINARY) | |
| 330 | -** may be present in the result as well; however, they should not impact the | |
| 331 | -** determination of text versus binary content. | |
| 332 | -** | |
| 333 | -************************************ WARNING ********************************** | |
| 334 | -** | |
| 335 | -** This function does not validate that the blob content is properly formed | |
| 336 | -** UTF-16. It assumes that all code points are the same size. It does not | |
| 337 | -** validate any code points. It makes no attempt to detect if any [invalid] | |
| 338 | -** switches between the UTF-16be and UTF-16le encodings occur. | |
| 339 | -** | |
| 340 | -** The only code points that this function cares about are the NUL character, | |
| 341 | -** carriage-return, and line-feed. | |
| 342 | -** | |
| 343 | -** This function examines the contents of the blob until one of the flags | |
| 344 | -** specified in "stopFlags" is set. | |
| 345 | -** | |
| 346 | -************************************ WARNING ********************************** | |
| 347 | -*/ | |
| 348 | -int looks_like_utf16(const Blob *pContent, int bReverse, int stopFlags){ | |
| 349 | - const WCHAR_T *z = (WCHAR_T *)blob_buffer(pContent); | |
| 350 | - unsigned int n = blob_size(pContent); | |
| 351 | - int j, c, flags = LOOK_NONE; /* Assume UTF-16 text, prove otherwise */ | |
| 352 | - | |
| 353 | - if( n==0 ) return flags; /* Empty file -> text */ | |
| 354 | - if( n%sizeof(WCHAR_T) ){ | |
| 355 | - flags |= LOOK_ODD; /* Odd number of bytes -> binary (UTF-8?) */ | |
| 356 | - if( n<sizeof(WCHAR_T) ) return flags; /* One byte -> binary (UTF-8?) */ | |
| 357 | - } | |
| 358 | - c = *z; | |
| 359 | - if( bReverse ){ | |
| 360 | - c = UTF16_SWAP(c); | |
| 361 | - } | |
| 362 | - if( c==0 ){ | |
| 363 | - flags |= LOOK_NUL; /* NUL character in a file -> binary */ | |
| 364 | - }else if( c=='\r' ){ | |
| 365 | - flags |= LOOK_CR; | |
| 366 | - if( n<(2*sizeof(WCHAR_T)) || UTF16_SWAP_IF(bReverse, z[1])!='\n' ){ | |
| 367 | - flags |= LOOK_LONE_CR; /* More chars, next char is not LF */ | |
| 368 | - } | |
| 369 | - } | |
| 370 | - j = (c!='\n'); | |
| 371 | - if( !j ) flags |= (LOOK_LF | LOOK_LONE_LF); /* Found LF as first char */ | |
| 372 | - while( 1 ){ | |
| 373 | - int c2 = c; | |
| 374 | - if( flags&stopFlags ) break; | |
| 375 | - n -= sizeof(WCHAR_T); | |
| 376 | - if( n<sizeof(WCHAR_T) ) break; | |
| 377 | - c = *++z; | |
| 378 | - if( bReverse ){ | |
| 379 | - c = UTF16_SWAP(c); | |
| 380 | - } | |
| 381 | - ++j; | |
| 382 | - if( c==0 ){ | |
| 383 | - flags |= LOOK_NUL; /* NUL character in a file -> binary */ | |
| 384 | - }else if( c=='\n' ){ | |
| 385 | - flags |= LOOK_LF; | |
| 386 | - if( c2=='\r' ){ | |
| 387 | - flags |= (LOOK_CR | LOOK_CRLF); /* Found LF preceded by CR */ | |
| 388 | - }else{ | |
| 389 | - flags |= LOOK_LONE_LF; | |
| 390 | - } | |
| 391 | - if( j>UTF16_LENGTH_MASK ){ | |
| 392 | - flags |= LOOK_LONG; /* Very long line -> binary */ | |
| 393 | - } | |
| 394 | - j = 0; | |
| 395 | - }else if( c=='\r' ){ | |
| 396 | - flags |= LOOK_CR; | |
| 397 | - if( n<(2*sizeof(WCHAR_T)) || UTF16_SWAP_IF(bReverse, z[1])!='\n' ){ | |
| 398 | - flags |= LOOK_LONE_CR; /* More chars, next char is not LF */ | |
| 399 | - } | |
| 400 | - } | |
| 401 | - } | |
| 402 | - if( n ){ | |
| 403 | - flags |= LOOK_SHORT; /* The whole blob was not examined */ | |
| 404 | - } | |
| 405 | - if( j>UTF16_LENGTH_MASK ){ | |
| 406 | - flags |= LOOK_LONG; /* Very long line -> binary */ | |
| 407 | - } | |
| 408 | - return flags; | |
| 409 | -} | |
| 410 | - | |
| 411 | -/* | |
| 412 | -** This function returns an array of bytes representing the byte-order-mark | |
| 413 | -** for UTF-8. | |
| 414 | -*/ | |
| 415 | -const unsigned char *get_utf8_bom(int *pnByte){ | |
| 416 | - static const unsigned char bom[] = { | |
| 417 | - 0xEF, 0xBB, 0xBF, 0x00, 0x00, 0x00 | |
| 418 | - }; | |
| 419 | - if( pnByte ) *pnByte = 3; | |
| 420 | - return bom; | |
| 421 | -} | |
| 422 | - | |
| 423 | -/* | |
| 424 | -** This function returns non-zero if the blob starts with a UTF-8 | |
| 425 | -** byte-order-mark (BOM). | |
| 426 | -*/ | |
| 427 | -int starts_with_utf8_bom(const Blob *pContent, int *pnByte){ | |
| 428 | - const char *z = blob_buffer(pContent); | |
| 429 | - int bomSize = 0; | |
| 430 | - const unsigned char *bom = get_utf8_bom(&bomSize); | |
| 431 | - | |
| 432 | - if( pnByte ) *pnByte = bomSize; | |
| 433 | - if( blob_size(pContent)<bomSize ) return 0; | |
| 434 | - return memcmp(z, bom, bomSize)==0; | |
| 435 | -} | |
| 436 | - | |
| 437 | -/* | |
| 438 | -** This function returns non-zero if the blob starts with a UTF-16 | |
| 439 | -** byte-order-mark (BOM), either in the endianness of the machine | |
| 440 | -** or in reversed byte order. The UTF-32 BOM is ruled out by checking | |
| 441 | -** if the UTF-16 BOM is not immediately followed by (utf16) 0. | |
| 442 | -** pnByte is only set when the function returns 1. | |
| 443 | -** | |
| 444 | -** pbReverse is always set, even when no BOM is found. Without a BOM, | |
| 445 | -** it is set to 1 on little-endian and 0 on big-endian platforms. See | |
| 446 | -** clause D98 of conformance (section 3.10) of the Unicode standard. | |
| 447 | -*/ | |
| 448 | -int starts_with_utf16_bom( | |
| 449 | - const Blob *pContent, /* IN: Blob content to perform BOM detection on. */ | |
| 450 | - int *pnByte, /* OUT: The number of bytes used for the BOM. */ | |
| 451 | - int *pbReverse /* OUT: Non-zero for BOM in reverse byte-order. */ | |
| 452 | -){ | |
| 453 | - const unsigned short *z = (unsigned short *)blob_buffer(pContent); | |
| 454 | - int bomSize = sizeof(unsigned short); | |
| 455 | - int size = blob_size(pContent); | |
| 456 | - | |
| 457 | - if( size<bomSize ) goto noBom; /* No: cannot read BOM. */ | |
| 458 | - if( size>=(2*bomSize) && z[1]==0 ) goto noBom; /* No: possible UTF-32. */ | |
| 459 | - if( z[0]==0xfeff ){ | |
| 460 | - if( pbReverse ) *pbReverse = 0; | |
| 461 | - }else if( z[0]==0xfffe ){ | |
| 462 | - if( pbReverse ) *pbReverse = 1; | |
| 463 | - }else{ | |
| 464 | - static const int one = 1; | |
| 465 | - noBom: | |
| 466 | - if( pbReverse ) *pbReverse = *(char *) &one; | |
| 467 | - return 0; /* No: UTF-16 byte-order-mark not found. */ | |
| 468 | - } | |
| 469 | - if( pnByte ) *pnByte = bomSize; | |
| 470 | - return 1; /* Yes. */ | |
| 471 | -} | |
| 472 | - | |
| 473 | -/* | |
| 474 | -** Returns non-zero if the specified content could be valid UTF-16. | |
| 475 | -*/ | |
| 476 | -int could_be_utf16(const Blob *pContent, int *pbReverse){ | |
| 477 | - return (blob_size(pContent) % sizeof(WCHAR_T) == 0) ? | |
| 478 | - starts_with_utf16_bom(pContent, 0, pbReverse) : 0; | |
| 479 | -} | |
| 480 | - | |
| 481 | 182 | /* |
| 482 | 183 | ** Return true if two DLine elements are identical. |
| 483 | 184 | */ |
| 484 | 185 | static int same_dline(DLine *pA, DLine *pB){ |
| 485 | 186 | return pA->h==pB->h && memcmp(pA->z,pB->z,pA->h & LENGTH_MASK)==0; |
| @@ -576,11 +277,11 @@ | ||
| 576 | 277 | int mxr; /* Maximum value for r */ |
| 577 | 278 | int na, nb; /* Number of lines shown from A and B */ |
| 578 | 279 | int i, j; /* Loop counters */ |
| 579 | 280 | int m; /* Number of lines to output */ |
| 580 | 281 | int skip; /* Number of lines to skip */ |
| 581 | - int nChunk = 0; /* Number of diff chunks seen so far */ | |
| 282 | + static int nChunk = 0; /* Number of diff chunks seen so far */ | |
| 582 | 283 | int nContext; /* Number of lines of context */ |
| 583 | 284 | int showLn; /* Show line numbers */ |
| 584 | 285 | int html; /* Render as HTML */ |
| 585 | 286 | int showDivider = 0; /* True to show the divider between diff blocks */ |
| 586 | 287 | |
| @@ -657,14 +358,14 @@ | ||
| 657 | 358 | if( !showDivider ){ |
| 658 | 359 | /* Do not show a top divider */ |
| 659 | 360 | showDivider = 1; |
| 660 | 361 | }else if( html ){ |
| 661 | 362 | blob_appendf(pOut, "<span class=\"diffhr\">%.80c</span>\n", '.'); |
| 662 | - blob_appendf(pOut, "<a name=\"chunk%d\"></a>\n", nChunk); | |
| 663 | 363 | }else{ |
| 664 | 364 | blob_appendf(pOut, "%.80c\n", '.'); |
| 665 | 365 | } |
| 366 | + if( html ) blob_appendf(pOut, "<span id=\"chunk%d\"></span>", nChunk); | |
| 666 | 367 | }else{ |
| 667 | 368 | if( html ) blob_appendf(pOut, "<span class=\"diffln\">"); |
| 668 | 369 | /* |
| 669 | 370 | * If the patch changes an empty file or results in an empty file, |
| 670 | 371 | * the block header must use 0,0 as position indicator and not 1,0. |
| @@ -727,12 +428,11 @@ | ||
| 727 | 428 | /* |
| 728 | 429 | ** Status of a single output line |
| 729 | 430 | */ |
| 730 | 431 | typedef struct SbsLine SbsLine; |
| 731 | 432 | struct SbsLine { |
| 732 | - char *zLine; /* The output line under construction */ | |
| 733 | - int n; /* Index of next unused slot in the zLine[] */ | |
| 433 | + Blob *apCols[5]; /* Array of pointers to output columns */ | |
| 734 | 434 | int width; /* Maximum width of a column in the output */ |
| 735 | 435 | unsigned char escHtml; /* True to escape html characters */ |
| 736 | 436 | int iStart; /* Write zStart prior to character iStart */ |
| 737 | 437 | const char *zStart; /* A <span> tag */ |
| 738 | 438 | int iEnd; /* Write </span> prior to character iEnd */ |
| @@ -741,125 +441,155 @@ | ||
| 741 | 441 | int iEnd2; /* Write </span> prior to character iEnd2 */ |
| 742 | 442 | ReCompiled *pRe; /* Only colorize matching lines, if not NULL */ |
| 743 | 443 | }; |
| 744 | 444 | |
| 745 | 445 | /* |
| 746 | -** Flags for sbsWriteText() | |
| 446 | +** Column indices for SbsLine.apCols[] | |
| 447 | +*/ | |
| 448 | +#define SBS_LNA 0 /* Left line number */ | |
| 449 | +#define SBS_TXTA 1 /* Left text */ | |
| 450 | +#define SBS_MKR 2 /* Middle separator column */ | |
| 451 | +#define SBS_LNB 3 /* Right line number */ | |
| 452 | +#define SBS_TXTB 4 /* Right text */ | |
| 453 | + | |
| 454 | +/* | |
| 455 | +** Append newlines to all columns. | |
| 456 | +*/ | |
| 457 | +static void sbsWriteNewlines(SbsLine *p){ | |
| 458 | + int i; | |
| 459 | + for( i=p->escHtml ? SBS_LNA : SBS_TXTB; i<=SBS_TXTB; i++ ){ | |
| 460 | + blob_append(p->apCols[i], "\n", 1); | |
| 461 | + } | |
| 462 | +} | |
| 463 | + | |
| 464 | +/* | |
| 465 | +** Append n spaces to the column. | |
| 747 | 466 | */ |
| 748 | -#define SBS_NEWLINE 0x0001 /* End with \n\000 */ | |
| 749 | -#define SBS_PAD 0x0002 /* Pad output to width spaces */ | |
| 467 | +static void sbsWriteSpace(SbsLine *p, int n, int col){ | |
| 468 | + blob_appendf(p->apCols[col], "%*s", n, ""); | |
| 469 | +} | |
| 750 | 470 | |
| 751 | 471 | /* |
| 752 | -** Write up to width characters of pLine into p->zLine[]. Translate tabs into | |
| 753 | -** spaces. Add a newline if SBS_NEWLINE is set. Translate HTML characters | |
| 754 | -** if SBS_HTML is set. Pad the rendering out width bytes if SBS_PAD is set. | |
| 472 | +** Write the text of pLine into column iCol of p. | |
| 473 | +** | |
| 474 | +** If outputting HTML, write the full line. Otherwise, only write the | |
| 475 | +** width characters. Translate tabs into spaces. Add newlines if col | |
| 476 | +** is SBS_TXTB. Translate HTML characters if escHtml is true. Pad the | |
| 477 | +** rendering to width bytes if col is SBS_TXTA and escHtml is false. | |
| 755 | 478 | ** |
| 756 | 479 | ** This comment contains multibyte unicode characters (ü, Æ, ð) in order |
| 757 | 480 | ** to test the ability of the diff code to handle such characters. |
| 758 | 481 | */ |
| 759 | -static void sbsWriteText(SbsLine *p, DLine *pLine, unsigned flags){ | |
| 482 | +static void sbsWriteText(SbsLine *p, DLine *pLine, int col){ | |
| 483 | + Blob *pCol = p->apCols[col]; | |
| 760 | 484 | int n = pLine->h & LENGTH_MASK; |
| 761 | 485 | int i; /* Number of input characters consumed */ |
| 762 | - int j; /* Number of output characters generated */ | |
| 763 | 486 | int k; /* Cursor position */ |
| 764 | 487 | int needEndSpan = 0; |
| 765 | 488 | const char *zIn = pLine->z; |
| 766 | - char *z = &p->zLine[p->n]; | |
| 767 | 489 | int w = p->width; |
| 768 | 490 | int colorize = p->escHtml; |
| 769 | 491 | if( colorize && p->pRe && re_dline_match(p->pRe, pLine, 1)==0 ){ |
| 770 | 492 | colorize = 0; |
| 771 | 493 | } |
| 772 | - for(i=j=k=0; k<w && i<n; i++, k++){ | |
| 494 | + for(i=k=0; (p->escHtml || k<w) && i<n; i++, k++){ | |
| 773 | 495 | char c = zIn[i]; |
| 774 | 496 | if( colorize ){ |
| 775 | 497 | if( i==p->iStart ){ |
| 776 | 498 | int x = strlen(p->zStart); |
| 777 | - memcpy(z+j, p->zStart, x); | |
| 778 | - j += x; | |
| 499 | + blob_append(pCol, p->zStart, x); | |
| 779 | 500 | needEndSpan = 1; |
| 780 | 501 | if( p->iStart2 ){ |
| 781 | 502 | p->iStart = p->iStart2; |
| 782 | 503 | p->zStart = p->zStart2; |
| 783 | 504 | p->iStart2 = 0; |
| 784 | 505 | } |
| 785 | 506 | }else if( i==p->iEnd ){ |
| 786 | - memcpy(z+j, "</span>", 7); | |
| 787 | - j += 7; | |
| 507 | + blob_append(pCol, "</span>", 7); | |
| 788 | 508 | needEndSpan = 0; |
| 789 | 509 | if( p->iEnd2 ){ |
| 790 | 510 | p->iEnd = p->iEnd2; |
| 791 | 511 | p->iEnd2 = 0; |
| 792 | 512 | } |
| 793 | 513 | } |
| 794 | 514 | } |
| 795 | - if( c=='\t' ){ | |
| 796 | - z[j++] = ' '; | |
| 797 | - while( (k&7)!=7 && k<w ){ z[j++] = ' '; k++; } | |
| 515 | + if( c=='\t' && !p->escHtml ){ | |
| 516 | + blob_append(pCol, " ", 1); | |
| 517 | + while( (k&7)!=7 && (p->escHtml || k<w) ){ | |
| 518 | + blob_append(pCol, " ", 1); | |
| 519 | + k++; | |
| 520 | + } | |
| 798 | 521 | }else if( c=='\r' || c=='\f' ){ |
| 799 | - z[j++] = ' '; | |
| 522 | + blob_append(pCol, " ", 1); | |
| 800 | 523 | }else if( c=='<' && p->escHtml ){ |
| 801 | - memcpy(&z[j], "<", 4); | |
| 802 | - j += 4; | |
| 524 | + blob_append(pCol, "<", 4); | |
| 803 | 525 | }else if( c=='&' && p->escHtml ){ |
| 804 | - memcpy(&z[j], "&", 5); | |
| 805 | - j += 5; | |
| 526 | + blob_append(pCol, "&", 5); | |
| 806 | 527 | }else if( c=='>' && p->escHtml ){ |
| 807 | - memcpy(&z[j], ">", 4); | |
| 808 | - j += 4; | |
| 528 | + blob_append(pCol, ">", 4); | |
| 809 | 529 | }else if( c=='"' && p->escHtml ){ |
| 810 | - memcpy(&z[j], """, 6); | |
| 811 | - j += 6; | |
| 530 | + blob_append(pCol, """, 6); | |
| 812 | 531 | }else{ |
| 813 | - z[j++] = c; | |
| 532 | + blob_append(pCol, &zIn[i], 1); | |
| 814 | 533 | if( (c&0xc0)==0x80 ) k--; |
| 815 | 534 | } |
| 816 | 535 | } |
| 817 | 536 | if( needEndSpan ){ |
| 818 | - memcpy(&z[j], "</span>", 7); | |
| 819 | - j += 7; | |
| 820 | - } | |
| 821 | - if( (flags & SBS_PAD)!=0 ){ | |
| 822 | - while( k<w ){ k++; z[j++] = ' '; } | |
| 823 | - } | |
| 824 | - if( flags & SBS_NEWLINE ){ | |
| 825 | - z[j++] = '\n'; | |
| 826 | - } | |
| 827 | - p->n += j; | |
| 828 | -} | |
| 829 | - | |
| 830 | -/* | |
| 831 | -** Append a string to an SbSLine without coding, interpretation, or padding. | |
| 832 | -*/ | |
| 833 | -static void sbsWrite(SbsLine *p, const char *zIn, int nIn){ | |
| 834 | - memcpy(p->zLine+p->n, zIn, nIn); | |
| 835 | - p->n += nIn; | |
| 836 | -} | |
| 837 | - | |
| 838 | -/* | |
| 839 | -** Append n spaces to the string. | |
| 840 | -*/ | |
| 841 | -static void sbsWriteSpace(SbsLine *p, int n){ | |
| 842 | - while( n-- ) p->zLine[p->n++] = ' '; | |
| 843 | -} | |
| 844 | - | |
| 845 | -/* | |
| 846 | -** Append a string to the output only if we are rendering HTML. | |
| 847 | -*/ | |
| 848 | -static void sbsWriteHtml(SbsLine *p, const char *zIn){ | |
| 849 | - if( p->escHtml ) sbsWrite(p, zIn, strlen(zIn)); | |
| 850 | -} | |
| 851 | - | |
| 852 | -/* | |
| 853 | -** Write a 6-digit line number followed by a single space onto the line. | |
| 854 | -*/ | |
| 855 | -static void sbsWriteLineno(SbsLine *p, int ln){ | |
| 856 | - sbsWriteHtml(p, "<span class=\"diffln\">"); | |
| 857 | - sqlite3_snprintf(7, &p->zLine[p->n], "%5d ", ln+1); | |
| 858 | - p->n += 6; | |
| 859 | - sbsWriteHtml(p, "</span>"); | |
| 860 | - p->zLine[p->n++] = ' '; | |
| 537 | + blob_append(pCol, "</span>", 7); | |
| 538 | + } | |
| 539 | + if( col==SBS_TXTB ){ | |
| 540 | + sbsWriteNewlines(p); | |
| 541 | + }else if( !p->escHtml ){ | |
| 542 | + sbsWriteSpace(p, w-k, SBS_TXTA); | |
| 543 | + } | |
| 544 | +} | |
| 545 | + | |
| 546 | +/* | |
| 547 | +** Append a column to the final output blob. | |
| 548 | +*/ | |
| 549 | +static void sbsWriteColumn(Blob *pOut, Blob *pCol, int col){ | |
| 550 | + blob_appendf(pOut, | |
| 551 | + "<td><div class=\"diff%scol\">\n" | |
| 552 | + "<pre>\n" | |
| 553 | + "%s" | |
| 554 | + "</pre>\n" | |
| 555 | + "</div></td>\n", | |
| 556 | + col % 3 ? (col == SBS_MKR ? "mkr" : "txt") : "ln", | |
| 557 | + blob_str(pCol) | |
| 558 | + ); | |
| 559 | +} | |
| 560 | + | |
| 561 | +/* | |
| 562 | +** Append a separator line to column iCol | |
| 563 | +*/ | |
| 564 | +static void sbsWriteSep(SbsLine *p, int len, int col){ | |
| 565 | + char ch = '.'; | |
| 566 | + if( len<1 ){ | |
| 567 | + len = 1; | |
| 568 | + ch = ' '; | |
| 569 | + } | |
| 570 | + blob_appendf(p->apCols[col], "<span class=\"diffhr\">%.*c</span>\n", len, ch); | |
| 571 | +} | |
| 572 | + | |
| 573 | +/* | |
| 574 | +** Append the appropriate marker into the center column of the diff. | |
| 575 | +*/ | |
| 576 | +static void sbsWriteMarker(SbsLine *p, const char *zTxt, const char *zHtml){ | |
| 577 | + blob_append(p->apCols[SBS_MKR], p->escHtml ? zHtml : zTxt, -1); | |
| 578 | +} | |
| 579 | + | |
| 580 | +/* | |
| 581 | +** Append a line number to the column. | |
| 582 | +*/ | |
| 583 | +static void sbsWriteLineno(SbsLine *p, int ln, int col){ | |
| 584 | + if( p->escHtml ){ | |
| 585 | + blob_appendf(p->apCols[col], "%d", ln+1); | |
| 586 | + }else{ | |
| 587 | + char zLn[7]; | |
| 588 | + sqlite3_snprintf(7, zLn, "%5d ", ln+1); | |
| 589 | + blob_appendf(p->apCols[col], "%s ", zLn); | |
| 590 | + } | |
| 861 | 591 | } |
| 862 | 592 | |
| 863 | 593 | /* |
| 864 | 594 | ** The two text segments zLeft and zRight are known to be different on |
| 865 | 595 | ** both ends, but they might have a common segment in the middle. If |
| @@ -1018,43 +748,42 @@ | ||
| 1018 | 748 | } |
| 1019 | 749 | if( nSuffix==nLeft || nSuffix==nRight ) nPrefix = 0; |
| 1020 | 750 | } |
| 1021 | 751 | if( nPrefix+nSuffix > nShort ) nPrefix = nShort - nSuffix; |
| 1022 | 752 | |
| 1023 | - | |
| 1024 | 753 | /* A single chunk of text inserted on the right */ |
| 1025 | 754 | if( nPrefix+nSuffix==nLeft ){ |
| 1026 | - sbsWriteLineno(p, lnLeft); | |
| 755 | + sbsWriteLineno(p, lnLeft, SBS_LNA); | |
| 1027 | 756 | p->iStart2 = p->iEnd2 = 0; |
| 1028 | 757 | p->iStart = p->iEnd = -1; |
| 1029 | - sbsWriteText(p, pLeft, SBS_PAD); | |
| 758 | + sbsWriteText(p, pLeft, SBS_TXTA); | |
| 1030 | 759 | if( nLeft==nRight && zLeft[nLeft]==zRight[nRight] ){ |
| 1031 | - sbsWrite(p, " ", 3); | |
| 760 | + sbsWriteMarker(p, " ", ""); | |
| 1032 | 761 | }else{ |
| 1033 | - sbsWrite(p, " | ", 3); | |
| 762 | + sbsWriteMarker(p, " | ", "|"); | |
| 1034 | 763 | } |
| 1035 | - sbsWriteLineno(p, lnRight); | |
| 764 | + sbsWriteLineno(p, lnRight, SBS_LNB); | |
| 1036 | 765 | p->iStart = nPrefix; |
| 1037 | 766 | p->iEnd = nRight - nSuffix; |
| 1038 | 767 | p->zStart = zClassAdd; |
| 1039 | - sbsWriteText(p, pRight, SBS_NEWLINE); | |
| 768 | + sbsWriteText(p, pRight, SBS_TXTB); | |
| 1040 | 769 | return; |
| 1041 | 770 | } |
| 1042 | 771 | |
| 1043 | 772 | /* A single chunk of text deleted from the left */ |
| 1044 | 773 | if( nPrefix+nSuffix==nRight ){ |
| 1045 | 774 | /* Text deleted from the left */ |
| 1046 | - sbsWriteLineno(p, lnLeft); | |
| 775 | + sbsWriteLineno(p, lnLeft, SBS_LNA); | |
| 1047 | 776 | p->iStart2 = p->iEnd2 = 0; |
| 1048 | 777 | p->iStart = nPrefix; |
| 1049 | 778 | p->iEnd = nLeft - nSuffix; |
| 1050 | 779 | p->zStart = zClassRm; |
| 1051 | - sbsWriteText(p, pLeft, SBS_PAD); | |
| 1052 | - sbsWrite(p, " | ", 3); | |
| 1053 | - sbsWriteLineno(p, lnRight); | |
| 780 | + sbsWriteText(p, pLeft, SBS_TXTA); | |
| 781 | + sbsWriteMarker(p, " | ", "|"); | |
| 782 | + sbsWriteLineno(p, lnRight, SBS_LNB); | |
| 1054 | 783 | p->iStart = p->iEnd = -1; |
| 1055 | - sbsWriteText(p, pRight, SBS_NEWLINE); | |
| 784 | + sbsWriteText(p, pRight, SBS_TXTB); | |
| 1056 | 785 | return; |
| 1057 | 786 | } |
| 1058 | 787 | |
| 1059 | 788 | /* At this point we know that there is a chunk of text that has |
| 1060 | 789 | ** changed between the left and the right. Check to see if there |
| @@ -1065,11 +794,11 @@ | ||
| 1065 | 794 | if( p->escHtml |
| 1066 | 795 | && nLeftDiff >= 6 |
| 1067 | 796 | && nRightDiff >= 6 |
| 1068 | 797 | && textLCS(&zLeft[nPrefix], nLeftDiff, &zRight[nPrefix], nRightDiff, aLCS) |
| 1069 | 798 | ){ |
| 1070 | - sbsWriteLineno(p, lnLeft); | |
| 799 | + sbsWriteLineno(p, lnLeft, SBS_LNA); | |
| 1071 | 800 | p->iStart = nPrefix; |
| 1072 | 801 | p->iEnd = nPrefix + aLCS[0]; |
| 1073 | 802 | if( aLCS[2]==0 ){ |
| 1074 | 803 | sbsShiftLeft(p, pLeft->z); |
| 1075 | 804 | p->zStart = zClassRm; |
| @@ -1078,13 +807,13 @@ | ||
| 1078 | 807 | } |
| 1079 | 808 | p->iStart2 = nPrefix + aLCS[1]; |
| 1080 | 809 | p->iEnd2 = nLeft - nSuffix; |
| 1081 | 810 | p->zStart2 = aLCS[3]==nRightDiff ? zClassRm : zClassChng; |
| 1082 | 811 | sbsSimplifyLine(p, zLeft+nPrefix); |
| 1083 | - sbsWriteText(p, pLeft, SBS_PAD); | |
| 1084 | - sbsWrite(p, " | ", 3); | |
| 1085 | - sbsWriteLineno(p, lnRight); | |
| 812 | + sbsWriteText(p, pLeft, SBS_TXTA); | |
| 813 | + sbsWriteMarker(p, " | ", "|"); | |
| 814 | + sbsWriteLineno(p, lnRight, SBS_LNB); | |
| 1086 | 815 | p->iStart = nPrefix; |
| 1087 | 816 | p->iEnd = nPrefix + aLCS[2]; |
| 1088 | 817 | if( aLCS[0]==0 ){ |
| 1089 | 818 | sbsShiftLeft(p, pRight->z); |
| 1090 | 819 | p->zStart = zClassAdd; |
| @@ -1093,25 +822,25 @@ | ||
| 1093 | 822 | } |
| 1094 | 823 | p->iStart2 = nPrefix + aLCS[3]; |
| 1095 | 824 | p->iEnd2 = nRight - nSuffix; |
| 1096 | 825 | p->zStart2 = aLCS[1]==nLeftDiff ? zClassAdd : zClassChng; |
| 1097 | 826 | sbsSimplifyLine(p, zRight+nPrefix); |
| 1098 | - sbsWriteText(p, pRight, SBS_NEWLINE); | |
| 827 | + sbsWriteText(p, pRight, SBS_TXTB); | |
| 1099 | 828 | return; |
| 1100 | 829 | } |
| 1101 | 830 | |
| 1102 | 831 | /* If all else fails, show a single big change between left and right */ |
| 1103 | - sbsWriteLineno(p, lnLeft); | |
| 832 | + sbsWriteLineno(p, lnLeft, SBS_LNA); | |
| 1104 | 833 | p->iStart2 = p->iEnd2 = 0; |
| 1105 | 834 | p->iStart = nPrefix; |
| 1106 | 835 | p->iEnd = nLeft - nSuffix; |
| 1107 | 836 | p->zStart = zClassChng; |
| 1108 | - sbsWriteText(p, pLeft, SBS_PAD); | |
| 1109 | - sbsWrite(p, " | ", 3); | |
| 1110 | - sbsWriteLineno(p, lnRight); | |
| 837 | + sbsWriteText(p, pLeft, SBS_TXTA); | |
| 838 | + sbsWriteMarker(p, " | ", "|"); | |
| 839 | + sbsWriteLineno(p, lnRight, SBS_LNB); | |
| 1111 | 840 | p->iEnd = nRight - nSuffix; |
| 1112 | - sbsWriteText(p, pRight, SBS_NEWLINE); | |
| 841 | + sbsWriteText(p, pRight, SBS_TXTB); | |
| 1113 | 842 | } |
| 1114 | 843 | |
| 1115 | 844 | /* |
| 1116 | 845 | ** Minimum of two values |
| 1117 | 846 | */ |
| @@ -1357,30 +1086,40 @@ | ||
| 1357 | 1086 | int mxr; /* Maximum value for r */ |
| 1358 | 1087 | int na, nb; /* Number of lines shown from A and B */ |
| 1359 | 1088 | int i, j; /* Loop counters */ |
| 1360 | 1089 | int m, ma, mb;/* Number of lines to output */ |
| 1361 | 1090 | int skip; /* Number of lines to skip */ |
| 1362 | - int nChunk = 0; /* Number of chunks of diff output seen so far */ | |
| 1091 | + static int nChunk = 0; /* Number of chunks of diff output seen so far */ | |
| 1363 | 1092 | SbsLine s; /* Output line buffer */ |
| 1364 | 1093 | int nContext; /* Lines of context above and below each change */ |
| 1365 | 1094 | int showDivider = 0; /* True to show the divider */ |
| 1095 | + Blob aCols[5]; /* Array of column blobs */ | |
| 1366 | 1096 | |
| 1367 | 1097 | memset(&s, 0, sizeof(s)); |
| 1368 | 1098 | s.width = diff_width(diffFlags); |
| 1369 | - s.zLine = fossil_malloc( 15*s.width + 200 ); | |
| 1370 | - if( s.zLine==0 ) return; | |
| 1371 | 1099 | nContext = diff_context_lines(diffFlags); |
| 1372 | 1100 | s.escHtml = (diffFlags & DIFF_HTML)!=0; |
| 1101 | + if( s.escHtml ){ | |
| 1102 | + for(i=SBS_LNA; i<=SBS_TXTB; i++){ | |
| 1103 | + blob_zero(&aCols[i]); | |
| 1104 | + s.apCols[i] = &aCols[i]; | |
| 1105 | + } | |
| 1106 | + }else{ | |
| 1107 | + for(i=SBS_LNA; i<=SBS_TXTB; i++){ | |
| 1108 | + s.apCols[i] = pOut; | |
| 1109 | + } | |
| 1110 | + } | |
| 1373 | 1111 | s.pRe = pRe; |
| 1374 | 1112 | s.iStart = -1; |
| 1375 | 1113 | s.iStart2 = 0; |
| 1376 | 1114 | s.iEnd = -1; |
| 1377 | 1115 | A = p->aFrom; |
| 1378 | 1116 | B = p->aTo; |
| 1379 | 1117 | R = p->aEdit; |
| 1380 | 1118 | mxr = p->nEdit; |
| 1381 | 1119 | while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; } |
| 1120 | + | |
| 1382 | 1121 | for(r=0; r<mxr; r += 3*nr){ |
| 1383 | 1122 | /* Figure out how many triples to show in a single block */ |
| 1384 | 1123 | for(nr=1; R[r+nr*3]>0 && R[r+nr*3]<nContext*2; nr++){} |
| 1385 | 1124 | /* printf("r=%d nr=%d\n", r, nr); */ |
| 1386 | 1125 | |
| @@ -1436,35 +1175,39 @@ | ||
| 1436 | 1175 | } |
| 1437 | 1176 | |
| 1438 | 1177 | /* Draw the separator between blocks */ |
| 1439 | 1178 | if( showDivider ){ |
| 1440 | 1179 | if( s.escHtml ){ |
| 1441 | - blob_appendf(pOut, "<span class=\"diffhr\">%.*c</span>\n", | |
| 1442 | - s.width*2+16, '.'); | |
| 1180 | + char zLn[10]; | |
| 1181 | + sqlite3_snprintf(sizeof(zLn), zLn, "%d", a+skip+1); | |
| 1182 | + sbsWriteSep(&s, strlen(zLn), SBS_LNA); | |
| 1183 | + sbsWriteSep(&s, s.width, SBS_TXTA); | |
| 1184 | + sbsWriteSep(&s, 0, SBS_MKR); | |
| 1185 | + sqlite3_snprintf(sizeof(zLn), zLn, "%d", b+skip+1); | |
| 1186 | + sbsWriteSep(&s, strlen(zLn), SBS_LNB); | |
| 1187 | + sbsWriteSep(&s, s.width, SBS_TXTB); | |
| 1443 | 1188 | }else{ |
| 1444 | 1189 | blob_appendf(pOut, "%.*c\n", s.width*2+16, '.'); |
| 1445 | 1190 | } |
| 1446 | 1191 | } |
| 1447 | 1192 | showDivider = 1; |
| 1448 | 1193 | nChunk++; |
| 1449 | 1194 | if( s.escHtml ){ |
| 1450 | - blob_appendf(pOut, "<a name=\"chunk%d\"></a>\n", nChunk); | |
| 1195 | + blob_appendf(s.apCols[SBS_LNA], "<span id=\"chunk%d\"></span>", nChunk); | |
| 1451 | 1196 | } |
| 1452 | 1197 | |
| 1453 | 1198 | /* Show the initial common area */ |
| 1454 | 1199 | a += skip; |
| 1455 | 1200 | b += skip; |
| 1456 | 1201 | m = R[r] - skip; |
| 1457 | 1202 | for(j=0; j<m; j++){ |
| 1458 | - s.n = 0; | |
| 1459 | - sbsWriteLineno(&s, a+j); | |
| 1203 | + sbsWriteLineno(&s, a+j, SBS_LNA); | |
| 1460 | 1204 | s.iStart = s.iEnd = -1; |
| 1461 | - sbsWriteText(&s, &A[a+j], SBS_PAD); | |
| 1462 | - sbsWrite(&s, " ", 3); | |
| 1463 | - sbsWriteLineno(&s, b+j); | |
| 1464 | - sbsWriteText(&s, &B[b+j], SBS_NEWLINE); | |
| 1465 | - blob_append(pOut, s.zLine, s.n); | |
| 1205 | + sbsWriteText(&s, &A[a+j], SBS_TXTA); | |
| 1206 | + sbsWriteMarker(&s, " ", ""); | |
| 1207 | + sbsWriteLineno(&s, b+j, SBS_LNB); | |
| 1208 | + sbsWriteText(&s, &B[b+j], SBS_TXTB); | |
| 1466 | 1209 | } |
| 1467 | 1210 | a += m; |
| 1468 | 1211 | b += m; |
| 1469 | 1212 | |
| 1470 | 1213 | /* Show the differences */ |
| @@ -1485,87 +1228,71 @@ | ||
| 1485 | 1228 | |
| 1486 | 1229 | alignment = sbsAlignment(&A[a], ma, &B[b], mb); |
| 1487 | 1230 | for(j=0; ma+mb>0; j++){ |
| 1488 | 1231 | if( alignment[j]==1 ){ |
| 1489 | 1232 | /* Delete one line from the left */ |
| 1490 | - s.n = 0; | |
| 1491 | - sbsWriteLineno(&s, a); | |
| 1233 | + sbsWriteLineno(&s, a, SBS_LNA); | |
| 1492 | 1234 | s.iStart = 0; |
| 1493 | 1235 | s.zStart = "<span class=\"diffrm\">"; |
| 1494 | 1236 | s.iEnd = LENGTH(&A[a]); |
| 1495 | - sbsWriteText(&s, &A[a], SBS_PAD); | |
| 1496 | - if( s.escHtml ){ | |
| 1497 | - sbsWrite(&s, " <\n", 6); | |
| 1498 | - }else{ | |
| 1499 | - sbsWrite(&s, " <\n", 3); | |
| 1500 | - } | |
| 1501 | - blob_append(pOut, s.zLine, s.n); | |
| 1237 | + sbsWriteText(&s, &A[a], SBS_TXTA); | |
| 1238 | + sbsWriteMarker(&s, " <", "<"); | |
| 1239 | + sbsWriteNewlines(&s); | |
| 1502 | 1240 | assert( ma>0 ); |
| 1503 | 1241 | ma--; |
| 1504 | 1242 | a++; |
| 1505 | 1243 | }else if( alignment[j]==3 ){ |
| 1506 | 1244 | /* The left line is changed into the right line */ |
| 1507 | - s.n = 0; | |
| 1508 | 1245 | sbsWriteLineChange(&s, &A[a], a, &B[b], b); |
| 1509 | - blob_append(pOut, s.zLine, s.n); | |
| 1510 | 1246 | assert( ma>0 && mb>0 ); |
| 1511 | 1247 | ma--; |
| 1512 | 1248 | mb--; |
| 1513 | 1249 | a++; |
| 1514 | 1250 | b++; |
| 1515 | 1251 | }else if( alignment[j]==2 ){ |
| 1516 | 1252 | /* Insert one line on the right */ |
| 1517 | - s.n = 0; | |
| 1518 | - sbsWriteSpace(&s, s.width + 7); | |
| 1519 | - if( s.escHtml ){ | |
| 1520 | - sbsWrite(&s, " > ", 6); | |
| 1521 | - }else{ | |
| 1522 | - sbsWrite(&s, " > ", 3); | |
| 1523 | - } | |
| 1524 | - sbsWriteLineno(&s, b); | |
| 1253 | + if( !s.escHtml ){ | |
| 1254 | + sbsWriteSpace(&s, s.width + 7, SBS_TXTA); | |
| 1255 | + } | |
| 1256 | + sbsWriteMarker(&s, " > ", ">"); | |
| 1257 | + sbsWriteLineno(&s, b, SBS_LNB); | |
| 1525 | 1258 | s.iStart = 0; |
| 1526 | 1259 | s.zStart = "<span class=\"diffadd\">"; |
| 1527 | 1260 | s.iEnd = LENGTH(&B[b]); |
| 1528 | - sbsWriteText(&s, &B[b], SBS_NEWLINE); | |
| 1529 | - blob_append(pOut, s.zLine, s.n); | |
| 1261 | + sbsWriteText(&s, &B[b], SBS_TXTB); | |
| 1530 | 1262 | assert( mb>0 ); |
| 1531 | 1263 | mb--; |
| 1532 | 1264 | b++; |
| 1533 | 1265 | }else{ |
| 1534 | 1266 | /* Delete from the left and insert on the right */ |
| 1535 | - s.n = 0; | |
| 1536 | - sbsWriteLineno(&s, a); | |
| 1267 | + sbsWriteLineno(&s, a, SBS_LNA); | |
| 1537 | 1268 | s.iStart = 0; |
| 1538 | 1269 | s.zStart = "<span class=\"diffrm\">"; |
| 1539 | 1270 | s.iEnd = LENGTH(&A[a]); |
| 1540 | - sbsWriteText(&s, &A[a], SBS_PAD); | |
| 1541 | - sbsWrite(&s, " | ", 3); | |
| 1542 | - sbsWriteLineno(&s, b); | |
| 1271 | + sbsWriteText(&s, &A[a], SBS_TXTA); | |
| 1272 | + sbsWriteMarker(&s, " | ", "|"); | |
| 1273 | + sbsWriteLineno(&s, b, SBS_LNB); | |
| 1543 | 1274 | s.iStart = 0; |
| 1544 | 1275 | s.zStart = "<span class=\"diffadd\">"; |
| 1545 | 1276 | s.iEnd = LENGTH(&B[b]); |
| 1546 | - sbsWriteText(&s, &B[b], SBS_NEWLINE); | |
| 1547 | - blob_append(pOut, s.zLine, s.n); | |
| 1277 | + sbsWriteText(&s, &B[b], SBS_TXTB); | |
| 1548 | 1278 | ma--; |
| 1549 | 1279 | mb--; |
| 1550 | 1280 | a++; |
| 1551 | 1281 | b++; |
| 1552 | 1282 | } |
| 1553 | - | |
| 1554 | 1283 | } |
| 1555 | 1284 | fossil_free(alignment); |
| 1556 | 1285 | if( i<nr-1 ){ |
| 1557 | 1286 | m = R[r+i*3+3]; |
| 1558 | 1287 | for(j=0; j<m; j++){ |
| 1559 | - s.n = 0; | |
| 1560 | - sbsWriteLineno(&s, a+j); | |
| 1288 | + sbsWriteLineno(&s, a+j, SBS_LNA); | |
| 1561 | 1289 | s.iStart = s.iEnd = -1; |
| 1562 | - sbsWriteText(&s, &A[a+j], SBS_PAD); | |
| 1563 | - sbsWrite(&s, " ", 3); | |
| 1564 | - sbsWriteLineno(&s, b+j); | |
| 1565 | - sbsWriteText(&s, &B[b+j], SBS_NEWLINE); | |
| 1566 | - blob_append(pOut, s.zLine, s.n); | |
| 1290 | + sbsWriteText(&s, &A[a+j], SBS_TXTA); | |
| 1291 | + sbsWriteMarker(&s, " ", ""); | |
| 1292 | + sbsWriteLineno(&s, b+j, SBS_LNB); | |
| 1293 | + sbsWriteText(&s, &B[b+j], SBS_TXTB); | |
| 1567 | 1294 | } |
| 1568 | 1295 | b += m; |
| 1569 | 1296 | a += m; |
| 1570 | 1297 | } |
| 1571 | 1298 | } |
| @@ -1573,21 +1300,27 @@ | ||
| 1573 | 1300 | /* Show the final common area */ |
| 1574 | 1301 | assert( nr==i ); |
| 1575 | 1302 | m = R[r+nr*3]; |
| 1576 | 1303 | if( m>nContext ) m = nContext; |
| 1577 | 1304 | for(j=0; j<m; j++){ |
| 1578 | - s.n = 0; | |
| 1579 | - sbsWriteLineno(&s, a+j); | |
| 1305 | + sbsWriteLineno(&s, a+j, SBS_LNA); | |
| 1580 | 1306 | s.iStart = s.iEnd = -1; |
| 1581 | - sbsWriteText(&s, &A[a+j], SBS_PAD); | |
| 1582 | - sbsWrite(&s, " ", 3); | |
| 1583 | - sbsWriteLineno(&s, b+j); | |
| 1584 | - sbsWriteText(&s, &B[b+j], SBS_NEWLINE); | |
| 1585 | - blob_append(pOut, s.zLine, s.n); | |
| 1307 | + sbsWriteText(&s, &A[a+j], SBS_TXTA); | |
| 1308 | + sbsWriteMarker(&s, " ", ""); | |
| 1309 | + sbsWriteLineno(&s, b+j, SBS_LNB); | |
| 1310 | + sbsWriteText(&s, &B[b+j], SBS_TXTB); | |
| 1586 | 1311 | } |
| 1587 | 1312 | } |
| 1588 | - free(s.zLine); | |
| 1313 | + | |
| 1314 | + if( s.escHtml && blob_size(s.apCols[SBS_LNA])>0 ){ | |
| 1315 | + blob_append(pOut, "<table class=\"sbsdiffcols\" width=\"90%\"><tr>\n", -1); | |
| 1316 | + for(i=SBS_LNA; i<=SBS_TXTB; i++){ | |
| 1317 | + sbsWriteColumn(pOut, s.apCols[i], i); | |
| 1318 | + blob_reset(s.apCols[i]); | |
| 1319 | + } | |
| 1320 | + blob_append(pOut, "</tr></table>\n", -1); | |
| 1321 | + } | |
| 1589 | 1322 | } |
| 1590 | 1323 | |
| 1591 | 1324 | /* |
| 1592 | 1325 | ** Compute the optimal longest common subsequence (LCS) using an |
| 1593 | 1326 | ** exhaustive search. This version of the LCS is only used for |
| @@ -1990,10 +1723,21 @@ | ||
| 1990 | 1723 | int diff_width(u64 diffFlags){ |
| 1991 | 1724 | int w = (diffFlags & DIFF_WIDTH_MASK)/(DIFF_CONTEXT_MASK+1); |
| 1992 | 1725 | if( w==0 ) w = 80; |
| 1993 | 1726 | return w; |
| 1994 | 1727 | } |
| 1728 | + | |
| 1729 | +/* | |
| 1730 | +** Append the error message to pOut. | |
| 1731 | +*/ | |
| 1732 | +void diff_errmsg(Blob *pOut, const char *msg, int diffFlags){ | |
| 1733 | + if( diffFlags & DIFF_HTML ){ | |
| 1734 | + blob_appendf(pOut, "<p class=\"generalError\">%s</p>", msg); | |
| 1735 | + }else{ | |
| 1736 | + blob_append(pOut, msg, -1); | |
| 1737 | + } | |
| 1738 | +} | |
| 1995 | 1739 | |
| 1996 | 1740 | /* |
| 1997 | 1741 | ** Generate a report of the differences between files pA and pB. |
| 1998 | 1742 | ** If pOut is not NULL then a unified diff is appended there. It |
| 1999 | 1743 | ** is assumed that pOut has already been initialized. If pOut is |
| @@ -2032,11 +1776,11 @@ | ||
| 2032 | 1776 | &c.nTo, ignoreEolWs); |
| 2033 | 1777 | if( c.aFrom==0 || c.aTo==0 ){ |
| 2034 | 1778 | fossil_free(c.aFrom); |
| 2035 | 1779 | fossil_free(c.aTo); |
| 2036 | 1780 | if( pOut ){ |
| 2037 | - blob_appendf(pOut, DIFF_CANNOT_COMPUTE_BINARY); | |
| 1781 | + diff_errmsg(pOut, DIFF_CANNOT_COMPUTE_BINARY, diffFlags); | |
| 2038 | 1782 | } |
| 2039 | 1783 | return 0; |
| 2040 | 1784 | } |
| 2041 | 1785 | |
| 2042 | 1786 | /* Compute the difference */ |
| @@ -2048,15 +1792,11 @@ | ||
| 2048 | 1792 | for(i=m=n=0; i<mx; i+=3){ m += a[i]; n += a[i+1]+a[i+2]; } |
| 2049 | 1793 | if( n>10000 ){ |
| 2050 | 1794 | fossil_free(c.aFrom); |
| 2051 | 1795 | fossil_free(c.aTo); |
| 2052 | 1796 | fossil_free(c.aEdit); |
| 2053 | - if( diffFlags & DIFF_HTML ){ | |
| 2054 | - blob_append(pOut, DIFF_TOO_MANY_CHANGES_HTML, -1); | |
| 2055 | - }else{ | |
| 2056 | - blob_append(pOut, DIFF_TOO_MANY_CHANGES_TXT, -1); | |
| 2057 | - } | |
| 1797 | + diff_errmsg(pOut, DIFF_TOO_MANY_CHANGES, diffFlags); | |
| 2058 | 1798 | return 0; |
| 2059 | 1799 | } |
| 2060 | 1800 | } |
| 2061 | 1801 | if( (diffFlags & DIFF_NOOPT)==0 ){ |
| 2062 | 1802 | diff_optimize(&c); |
| @@ -2159,10 +1899,11 @@ | ||
| 2159 | 1899 | if( find_option("tk",0,0)!=0 ){ |
| 2160 | 1900 | diff_tk("test-diff", 2); |
| 2161 | 1901 | return; |
| 2162 | 1902 | } |
| 2163 | 1903 | find_option("i",0,0); |
| 1904 | + find_option("v",0,0); | |
| 2164 | 1905 | zRe = find_option("regexp","e",1); |
| 2165 | 1906 | if( zRe ){ |
| 2166 | 1907 | const char *zErr = re_compile(&pRe, zRe, 0); |
| 2167 | 1908 | if( zErr ) fossil_fatal("regex error: %s", zErr); |
| 2168 | 1909 | } |
| @@ -2616,60 +2357,5 @@ | ||
| 2616 | 2357 | zPrefix[0] = 0; |
| 2617 | 2358 | } |
| 2618 | 2359 | fossil_print("%21s %4d: %.*s\n", zPrefix, i+1, n, z); |
| 2619 | 2360 | } |
| 2620 | 2361 | } |
| 2621 | - | |
| 2622 | -/* | |
| 2623 | -** COMMAND: test-looks-like-utf | |
| 2624 | -** | |
| 2625 | -** Usage: %fossil test-looks-like-utf FILENAME | |
| 2626 | -** | |
| 2627 | -** Options: | |
| 2628 | -** --utf8 Ignoring BOM and file size, force UTF-8 checking | |
| 2629 | -** --utf16 Ignoring BOM and file size, force UTF-16 checking | |
| 2630 | -** | |
| 2631 | -** FILENAME is the name of a file to check for textual content in the UTF-8 | |
| 2632 | -** and/or UTF-16 encodings. | |
| 2633 | -*/ | |
| 2634 | -void looks_like_utf_test_cmd(void){ | |
| 2635 | - Blob blob; /* the contents of the specified file */ | |
| 2636 | - int fUtf8; /* return value of starts_with_utf8_bom() */ | |
| 2637 | - int fUtf16; /* return value of starts_with_utf16_bom() */ | |
| 2638 | - int fUnicode; /* return value of could_be_utf16() */ | |
| 2639 | - int lookFlags; /* output flags from looks_like_utf8/utf16() */ | |
| 2640 | - int bRevUtf16 = 0; /* non-zero -> UTF-16 byte order reversed */ | |
| 2641 | - int bRevUnicode = 0; /* non-zero -> UTF-16 byte order reversed */ | |
| 2642 | - int fForceUtf8 = find_option("utf8",0,0)!=0; | |
| 2643 | - int fForceUtf16 = find_option("utf16",0,0)!=0; | |
| 2644 | - if( g.argc!=3 ) usage("FILENAME"); | |
| 2645 | - blob_read_from_file(&blob, g.argv[2]); | |
| 2646 | - fUtf8 = starts_with_utf8_bom(&blob, 0); | |
| 2647 | - fUtf16 = starts_with_utf16_bom(&blob, 0, &bRevUtf16); | |
| 2648 | - if( fForceUtf8 ){ | |
| 2649 | - fUnicode = 0; | |
| 2650 | - }else{ | |
| 2651 | - fUnicode = could_be_utf16(&blob, &bRevUnicode) || fForceUtf16; | |
| 2652 | - } | |
| 2653 | - lookFlags = fUnicode ? looks_like_utf16(&blob, bRevUnicode, 0) : | |
| 2654 | - looks_like_utf8(&blob, 0); | |
| 2655 | - fossil_print("File \"%s\" has %d bytes.\n",g.argv[2],blob_size(&blob)); | |
| 2656 | - fossil_print("Starts with UTF-8 BOM: %s\n",fUtf8?"yes":"no"); | |
| 2657 | - fossil_print("Starts with UTF-16 BOM: %s\n", | |
| 2658 | - fUtf16?(bRevUtf16?"reversed":"yes"):"no"); | |
| 2659 | - fossil_print("Looks like UTF-%s: %s\n",fUnicode?"16":"8", | |
| 2660 | - (lookFlags&LOOK_BINARY)?"no":"yes"); | |
| 2661 | - fossil_print("Has flag LOOK_NUL: %s\n",(lookFlags&LOOK_NUL)?"yes":"no"); | |
| 2662 | - fossil_print("Has flag LOOK_CR: %s\n",(lookFlags&LOOK_CR)?"yes":"no"); | |
| 2663 | - fossil_print("Has flag LOOK_LONE_CR: %s\n", | |
| 2664 | - (lookFlags&LOOK_LONE_CR)?"yes":"no"); | |
| 2665 | - fossil_print("Has flag LOOK_LF: %s\n",(lookFlags&LOOK_LF)?"yes":"no"); | |
| 2666 | - fossil_print("Has flag LOOK_LONE_LF: %s\n", | |
| 2667 | - (lookFlags&LOOK_LONE_LF)?"yes":"no"); | |
| 2668 | - fossil_print("Has flag LOOK_CRLF: %s\n",(lookFlags&LOOK_CRLF)?"yes":"no"); | |
| 2669 | - fossil_print("Has flag LOOK_LONG: %s\n",(lookFlags&LOOK_LONG)?"yes":"no"); | |
| 2670 | - fossil_print("Has flag LOOK_INVALID: %s\n", | |
| 2671 | - (lookFlags&LOOK_INVALID)?"yes":"no"); | |
| 2672 | - fossil_print("Has flag LOOK_ODD: %s\n",(lookFlags&LOOK_ODD)?"yes":"no"); | |
| 2673 | - fossil_print("Has flag LOOK_SHORT: %s\n",(lookFlags&LOOK_SHORT)?"yes":"no"); | |
| 2674 | - blob_reset(&blob); | |
| 2675 | -} | |
| 2676 | 2362 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -51,47 +51,20 @@ | |
| 51 | "cannot compute difference between binary files\n" |
| 52 | |
| 53 | #define DIFF_CANNOT_COMPUTE_SYMLINK \ |
| 54 | "cannot compute difference between symlink and regular file\n" |
| 55 | |
| 56 | #define DIFF_TOO_MANY_CHANGES_TXT \ |
| 57 | "more than 10,000 changes\n" |
| 58 | |
| 59 | #define DIFF_TOO_MANY_CHANGES_HTML \ |
| 60 | "<p class='generalError'>More than 10,000 changes</p>\n" |
| 61 | |
| 62 | /* |
| 63 | ** This macro is designed to return non-zero if the specified blob contains |
| 64 | ** data that MAY be binary in nature; otherwise, zero will be returned. |
| 65 | */ |
| 66 | #define looks_like_binary(blob) \ |
| 67 | ((looks_like_utf8((blob), LOOK_BINARY) & LOOK_BINARY) != LOOK_NONE) |
| 68 | |
| 69 | /* |
| 70 | ** Output flags for the looks_like_utf8() and looks_like_utf16() routines used |
| 71 | ** to convey status information about the blob content. |
| 72 | */ |
| 73 | #define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */ |
| 74 | #define LOOK_NUL ((int)0x00000001) /* One or more NUL chars were found. */ |
| 75 | #define LOOK_CR ((int)0x00000002) /* One or more CR chars were found. */ |
| 76 | #define LOOK_LONE_CR ((int)0x00000004) /* An unpaired CR char was found. */ |
| 77 | #define LOOK_LF ((int)0x00000008) /* One or more LF chars were found. */ |
| 78 | #define LOOK_LONE_LF ((int)0x00000010) /* An unpaired LF char was found. */ |
| 79 | #define LOOK_CRLF ((int)0x00000020) /* One or more CR/LF pairs were found. */ |
| 80 | #define LOOK_LONG ((int)0x00000040) /* An over length line was found. */ |
| 81 | #define LOOK_ODD ((int)0x00000080) /* An odd number of bytes was found. */ |
| 82 | #define LOOK_SHORT ((int)0x00000100) /* Unable to perform full check. */ |
| 83 | #define LOOK_INVALID ((int)0x00000200) /* Invalid sequence was found. */ |
| 84 | #define LOOK_BINARY (LOOK_NUL | LOOK_LONG | LOOK_SHORT) /* May be binary. */ |
| 85 | #define LOOK_EOL (LOOK_LONE_CR | LOOK_LONE_LF | LOOK_CRLF) /* Line seps. */ |
| 86 | #endif /* INTERFACE */ |
| 87 | |
| 88 | /* |
| 89 | ** Maximum length of a line in a text file, in bytes. (2**13 = 8192 bytes) |
| 90 | */ |
| 91 | #define LENGTH_MASK_SZ 13 |
| 92 | #define LENGTH_MASK ((1<<LENGTH_MASK_SZ)-1) |
| 93 | |
| 94 | /* |
| 95 | ** Information about each line of a file being diffed. |
| 96 | ** |
| 97 | ** The lower LENGTH_MASK_SZ bits of the hash (DLine.h) are the length |
| @@ -204,282 +177,10 @@ | |
| 204 | /* Return results */ |
| 205 | *pnLine = nLine; |
| 206 | return a; |
| 207 | } |
| 208 | |
| 209 | /* |
| 210 | ** This function attempts to scan each logical line within the blob to |
| 211 | ** determine the type of content it appears to contain. The return value |
| 212 | ** is a combination of one or more of the LOOK_XXX flags (see above): |
| 213 | ** |
| 214 | ** !LOOK_BINARY -- The content appears to consist entirely of text; however, |
| 215 | ** the encoding may not be UTF-8. |
| 216 | ** |
| 217 | ** LOOK_BINARY -- The content appears to be binary because it contains one |
| 218 | ** or more embedded NUL characters or an extremely long line. |
| 219 | ** Since this function does not understand UTF-16, it may |
| 220 | ** falsely consider UTF-16 text to be binary. |
| 221 | ** |
| 222 | ** Additional flags (i.e. those other than the ones included in LOOK_BINARY) |
| 223 | ** may be present in the result as well; however, they should not impact the |
| 224 | ** determination of text versus binary content. |
| 225 | ** |
| 226 | ************************************ WARNING ********************************** |
| 227 | ** |
| 228 | ** This function does not validate that the blob content is properly formed |
| 229 | ** UTF-8. It assumes that all code points are the same size. It does not |
| 230 | ** validate any code points. It makes no attempt to detect if any [invalid] |
| 231 | ** switches between UTF-8 and other encodings occur. |
| 232 | ** |
| 233 | ** The only code points that this function cares about are the NUL character, |
| 234 | ** carriage-return, and line-feed. |
| 235 | ** |
| 236 | ** This function examines the contents of the blob until one of the flags |
| 237 | ** specified in "stopFlags" is set. |
| 238 | ** |
| 239 | ************************************ WARNING ********************************** |
| 240 | */ |
| 241 | int looks_like_utf8(const Blob *pContent, int stopFlags){ |
| 242 | const char *z = blob_buffer(pContent); |
| 243 | unsigned int n = blob_size(pContent); |
| 244 | int j, c, flags = LOOK_NONE; /* Assume UTF-8 text, prove otherwise */ |
| 245 | |
| 246 | if( n==0 ) return flags; /* Empty file -> text */ |
| 247 | c = *z; |
| 248 | if( c==0 ){ |
| 249 | flags |= LOOK_NUL; /* NUL character in a file -> binary */ |
| 250 | }else if( c=='\r' ){ |
| 251 | flags |= LOOK_CR; |
| 252 | if( n<=1 || z[1]!='\n' ){ |
| 253 | flags |= LOOK_LONE_CR; /* More chars, next char is not LF */ |
| 254 | } |
| 255 | } |
| 256 | j = (c!='\n'); |
| 257 | if( !j ) flags |= (LOOK_LF | LOOK_LONE_LF); /* Found LF as first char */ |
| 258 | while( !(flags&stopFlags) && --n>0 ){ |
| 259 | int c2 = c; |
| 260 | c = *++z; ++j; |
| 261 | if( c==0 ){ |
| 262 | flags |= LOOK_NUL; /* NUL character in a file -> binary */ |
| 263 | }else if( c=='\n' ){ |
| 264 | flags |= LOOK_LF; |
| 265 | if( c2=='\r' ){ |
| 266 | flags |= (LOOK_CR | LOOK_CRLF); /* Found LF preceded by CR */ |
| 267 | }else{ |
| 268 | flags |= LOOK_LONE_LF; |
| 269 | } |
| 270 | if( j>LENGTH_MASK ){ |
| 271 | flags |= LOOK_LONG; /* Very long line -> binary */ |
| 272 | } |
| 273 | j = 0; |
| 274 | }else if( c=='\r' ){ |
| 275 | flags |= LOOK_CR; |
| 276 | if( n<=1 || z[1]!='\n' ){ |
| 277 | flags |= LOOK_LONE_CR; /* More chars, next char is not LF */ |
| 278 | } |
| 279 | } |
| 280 | } |
| 281 | if( n ){ |
| 282 | flags |= LOOK_SHORT; /* The whole blob was not examined */ |
| 283 | } |
| 284 | if( j>LENGTH_MASK ){ |
| 285 | flags |= LOOK_LONG; /* Very long line -> binary */ |
| 286 | } |
| 287 | return flags; |
| 288 | } |
| 289 | |
| 290 | /* |
| 291 | ** Define the type needed to represent a Unicode (UTF-16) character. |
| 292 | */ |
| 293 | #ifndef WCHAR_T |
| 294 | # ifdef _WIN32 |
| 295 | # define WCHAR_T wchar_t |
| 296 | # else |
| 297 | # define WCHAR_T unsigned short |
| 298 | # endif |
| 299 | #endif |
| 300 | |
| 301 | /* |
| 302 | ** Maximum length of a line in a text file, in UTF-16 characters. (4096) |
| 303 | ** The number of bytes represented by this value cannot exceed LENGTH_MASK |
| 304 | ** bytes, because that is the line buffer size used by the diff engine. |
| 305 | */ |
| 306 | #define UTF16_LENGTH_MASK_SZ (LENGTH_MASK_SZ-(sizeof(WCHAR_T)-sizeof(char))) |
| 307 | #define UTF16_LENGTH_MASK ((1<<UTF16_LENGTH_MASK_SZ)-1) |
| 308 | |
| 309 | /* |
| 310 | ** This macro is used to swap the byte order of a UTF-16 character in the |
| 311 | ** looks_like_utf16() function. |
| 312 | */ |
| 313 | #define UTF16_SWAP(ch) ((((ch) << 8) & 0xFF00) | (((ch) >> 8) & 0xFF)) |
| 314 | #define UTF16_SWAP_IF(expr,ch) ((expr) ? UTF16_SWAP((ch)) : (ch)) |
| 315 | |
| 316 | /* |
| 317 | ** This function attempts to scan each logical line within the blob to |
| 318 | ** determine the type of content it appears to contain. The return value |
| 319 | ** is a combination of one or more of the LOOK_XXX flags (see above): |
| 320 | ** |
| 321 | ** !LOOK_BINARY -- The content appears to consist entirely of text; however, |
| 322 | ** the encoding may not be UTF-16. |
| 323 | ** |
| 324 | ** LOOK_BINARY -- The content appears to be binary because it contains one |
| 325 | ** or more embedded NUL characters or an extremely long line. |
| 326 | ** Since this function does not understand UTF-8, it may |
| 327 | ** falsely consider UTF-8 text to be binary. |
| 328 | ** |
| 329 | ** Additional flags (i.e. those other than the ones included in LOOK_BINARY) |
| 330 | ** may be present in the result as well; however, they should not impact the |
| 331 | ** determination of text versus binary content. |
| 332 | ** |
| 333 | ************************************ WARNING ********************************** |
| 334 | ** |
| 335 | ** This function does not validate that the blob content is properly formed |
| 336 | ** UTF-16. It assumes that all code points are the same size. It does not |
| 337 | ** validate any code points. It makes no attempt to detect if any [invalid] |
| 338 | ** switches between the UTF-16be and UTF-16le encodings occur. |
| 339 | ** |
| 340 | ** The only code points that this function cares about are the NUL character, |
| 341 | ** carriage-return, and line-feed. |
| 342 | ** |
| 343 | ** This function examines the contents of the blob until one of the flags |
| 344 | ** specified in "stopFlags" is set. |
| 345 | ** |
| 346 | ************************************ WARNING ********************************** |
| 347 | */ |
| 348 | int looks_like_utf16(const Blob *pContent, int bReverse, int stopFlags){ |
| 349 | const WCHAR_T *z = (WCHAR_T *)blob_buffer(pContent); |
| 350 | unsigned int n = blob_size(pContent); |
| 351 | int j, c, flags = LOOK_NONE; /* Assume UTF-16 text, prove otherwise */ |
| 352 | |
| 353 | if( n==0 ) return flags; /* Empty file -> text */ |
| 354 | if( n%sizeof(WCHAR_T) ){ |
| 355 | flags |= LOOK_ODD; /* Odd number of bytes -> binary (UTF-8?) */ |
| 356 | if( n<sizeof(WCHAR_T) ) return flags; /* One byte -> binary (UTF-8?) */ |
| 357 | } |
| 358 | c = *z; |
| 359 | if( bReverse ){ |
| 360 | c = UTF16_SWAP(c); |
| 361 | } |
| 362 | if( c==0 ){ |
| 363 | flags |= LOOK_NUL; /* NUL character in a file -> binary */ |
| 364 | }else if( c=='\r' ){ |
| 365 | flags |= LOOK_CR; |
| 366 | if( n<(2*sizeof(WCHAR_T)) || UTF16_SWAP_IF(bReverse, z[1])!='\n' ){ |
| 367 | flags |= LOOK_LONE_CR; /* More chars, next char is not LF */ |
| 368 | } |
| 369 | } |
| 370 | j = (c!='\n'); |
| 371 | if( !j ) flags |= (LOOK_LF | LOOK_LONE_LF); /* Found LF as first char */ |
| 372 | while( 1 ){ |
| 373 | int c2 = c; |
| 374 | if( flags&stopFlags ) break; |
| 375 | n -= sizeof(WCHAR_T); |
| 376 | if( n<sizeof(WCHAR_T) ) break; |
| 377 | c = *++z; |
| 378 | if( bReverse ){ |
| 379 | c = UTF16_SWAP(c); |
| 380 | } |
| 381 | ++j; |
| 382 | if( c==0 ){ |
| 383 | flags |= LOOK_NUL; /* NUL character in a file -> binary */ |
| 384 | }else if( c=='\n' ){ |
| 385 | flags |= LOOK_LF; |
| 386 | if( c2=='\r' ){ |
| 387 | flags |= (LOOK_CR | LOOK_CRLF); /* Found LF preceded by CR */ |
| 388 | }else{ |
| 389 | flags |= LOOK_LONE_LF; |
| 390 | } |
| 391 | if( j>UTF16_LENGTH_MASK ){ |
| 392 | flags |= LOOK_LONG; /* Very long line -> binary */ |
| 393 | } |
| 394 | j = 0; |
| 395 | }else if( c=='\r' ){ |
| 396 | flags |= LOOK_CR; |
| 397 | if( n<(2*sizeof(WCHAR_T)) || UTF16_SWAP_IF(bReverse, z[1])!='\n' ){ |
| 398 | flags |= LOOK_LONE_CR; /* More chars, next char is not LF */ |
| 399 | } |
| 400 | } |
| 401 | } |
| 402 | if( n ){ |
| 403 | flags |= LOOK_SHORT; /* The whole blob was not examined */ |
| 404 | } |
| 405 | if( j>UTF16_LENGTH_MASK ){ |
| 406 | flags |= LOOK_LONG; /* Very long line -> binary */ |
| 407 | } |
| 408 | return flags; |
| 409 | } |
| 410 | |
| 411 | /* |
| 412 | ** This function returns an array of bytes representing the byte-order-mark |
| 413 | ** for UTF-8. |
| 414 | */ |
| 415 | const unsigned char *get_utf8_bom(int *pnByte){ |
| 416 | static const unsigned char bom[] = { |
| 417 | 0xEF, 0xBB, 0xBF, 0x00, 0x00, 0x00 |
| 418 | }; |
| 419 | if( pnByte ) *pnByte = 3; |
| 420 | return bom; |
| 421 | } |
| 422 | |
| 423 | /* |
| 424 | ** This function returns non-zero if the blob starts with a UTF-8 |
| 425 | ** byte-order-mark (BOM). |
| 426 | */ |
| 427 | int starts_with_utf8_bom(const Blob *pContent, int *pnByte){ |
| 428 | const char *z = blob_buffer(pContent); |
| 429 | int bomSize = 0; |
| 430 | const unsigned char *bom = get_utf8_bom(&bomSize); |
| 431 | |
| 432 | if( pnByte ) *pnByte = bomSize; |
| 433 | if( blob_size(pContent)<bomSize ) return 0; |
| 434 | return memcmp(z, bom, bomSize)==0; |
| 435 | } |
| 436 | |
| 437 | /* |
| 438 | ** This function returns non-zero if the blob starts with a UTF-16 |
| 439 | ** byte-order-mark (BOM), either in the endianness of the machine |
| 440 | ** or in reversed byte order. The UTF-32 BOM is ruled out by checking |
| 441 | ** if the UTF-16 BOM is not immediately followed by (utf16) 0. |
| 442 | ** pnByte is only set when the function returns 1. |
| 443 | ** |
| 444 | ** pbReverse is always set, even when no BOM is found. Without a BOM, |
| 445 | ** it is set to 1 on little-endian and 0 on big-endian platforms. See |
| 446 | ** clause D98 of conformance (section 3.10) of the Unicode standard. |
| 447 | */ |
| 448 | int starts_with_utf16_bom( |
| 449 | const Blob *pContent, /* IN: Blob content to perform BOM detection on. */ |
| 450 | int *pnByte, /* OUT: The number of bytes used for the BOM. */ |
| 451 | int *pbReverse /* OUT: Non-zero for BOM in reverse byte-order. */ |
| 452 | ){ |
| 453 | const unsigned short *z = (unsigned short *)blob_buffer(pContent); |
| 454 | int bomSize = sizeof(unsigned short); |
| 455 | int size = blob_size(pContent); |
| 456 | |
| 457 | if( size<bomSize ) goto noBom; /* No: cannot read BOM. */ |
| 458 | if( size>=(2*bomSize) && z[1]==0 ) goto noBom; /* No: possible UTF-32. */ |
| 459 | if( z[0]==0xfeff ){ |
| 460 | if( pbReverse ) *pbReverse = 0; |
| 461 | }else if( z[0]==0xfffe ){ |
| 462 | if( pbReverse ) *pbReverse = 1; |
| 463 | }else{ |
| 464 | static const int one = 1; |
| 465 | noBom: |
| 466 | if( pbReverse ) *pbReverse = *(char *) &one; |
| 467 | return 0; /* No: UTF-16 byte-order-mark not found. */ |
| 468 | } |
| 469 | if( pnByte ) *pnByte = bomSize; |
| 470 | return 1; /* Yes. */ |
| 471 | } |
| 472 | |
| 473 | /* |
| 474 | ** Returns non-zero if the specified content could be valid UTF-16. |
| 475 | */ |
| 476 | int could_be_utf16(const Blob *pContent, int *pbReverse){ |
| 477 | return (blob_size(pContent) % sizeof(WCHAR_T) == 0) ? |
| 478 | starts_with_utf16_bom(pContent, 0, pbReverse) : 0; |
| 479 | } |
| 480 | |
| 481 | /* |
| 482 | ** Return true if two DLine elements are identical. |
| 483 | */ |
| 484 | static int same_dline(DLine *pA, DLine *pB){ |
| 485 | return pA->h==pB->h && memcmp(pA->z,pB->z,pA->h & LENGTH_MASK)==0; |
| @@ -576,11 +277,11 @@ | |
| 576 | int mxr; /* Maximum value for r */ |
| 577 | int na, nb; /* Number of lines shown from A and B */ |
| 578 | int i, j; /* Loop counters */ |
| 579 | int m; /* Number of lines to output */ |
| 580 | int skip; /* Number of lines to skip */ |
| 581 | int nChunk = 0; /* Number of diff chunks seen so far */ |
| 582 | int nContext; /* Number of lines of context */ |
| 583 | int showLn; /* Show line numbers */ |
| 584 | int html; /* Render as HTML */ |
| 585 | int showDivider = 0; /* True to show the divider between diff blocks */ |
| 586 | |
| @@ -657,14 +358,14 @@ | |
| 657 | if( !showDivider ){ |
| 658 | /* Do not show a top divider */ |
| 659 | showDivider = 1; |
| 660 | }else if( html ){ |
| 661 | blob_appendf(pOut, "<span class=\"diffhr\">%.80c</span>\n", '.'); |
| 662 | blob_appendf(pOut, "<a name=\"chunk%d\"></a>\n", nChunk); |
| 663 | }else{ |
| 664 | blob_appendf(pOut, "%.80c\n", '.'); |
| 665 | } |
| 666 | }else{ |
| 667 | if( html ) blob_appendf(pOut, "<span class=\"diffln\">"); |
| 668 | /* |
| 669 | * If the patch changes an empty file or results in an empty file, |
| 670 | * the block header must use 0,0 as position indicator and not 1,0. |
| @@ -727,12 +428,11 @@ | |
| 727 | /* |
| 728 | ** Status of a single output line |
| 729 | */ |
| 730 | typedef struct SbsLine SbsLine; |
| 731 | struct SbsLine { |
| 732 | char *zLine; /* The output line under construction */ |
| 733 | int n; /* Index of next unused slot in the zLine[] */ |
| 734 | int width; /* Maximum width of a column in the output */ |
| 735 | unsigned char escHtml; /* True to escape html characters */ |
| 736 | int iStart; /* Write zStart prior to character iStart */ |
| 737 | const char *zStart; /* A <span> tag */ |
| 738 | int iEnd; /* Write </span> prior to character iEnd */ |
| @@ -741,125 +441,155 @@ | |
| 741 | int iEnd2; /* Write </span> prior to character iEnd2 */ |
| 742 | ReCompiled *pRe; /* Only colorize matching lines, if not NULL */ |
| 743 | }; |
| 744 | |
| 745 | /* |
| 746 | ** Flags for sbsWriteText() |
| 747 | */ |
| 748 | #define SBS_NEWLINE 0x0001 /* End with \n\000 */ |
| 749 | #define SBS_PAD 0x0002 /* Pad output to width spaces */ |
| 750 | |
| 751 | /* |
| 752 | ** Write up to width characters of pLine into p->zLine[]. Translate tabs into |
| 753 | ** spaces. Add a newline if SBS_NEWLINE is set. Translate HTML characters |
| 754 | ** if SBS_HTML is set. Pad the rendering out width bytes if SBS_PAD is set. |
| 755 | ** |
| 756 | ** This comment contains multibyte unicode characters (ü, Æ, ð) in order |
| 757 | ** to test the ability of the diff code to handle such characters. |
| 758 | */ |
| 759 | static void sbsWriteText(SbsLine *p, DLine *pLine, unsigned flags){ |
| 760 | int n = pLine->h & LENGTH_MASK; |
| 761 | int i; /* Number of input characters consumed */ |
| 762 | int j; /* Number of output characters generated */ |
| 763 | int k; /* Cursor position */ |
| 764 | int needEndSpan = 0; |
| 765 | const char *zIn = pLine->z; |
| 766 | char *z = &p->zLine[p->n]; |
| 767 | int w = p->width; |
| 768 | int colorize = p->escHtml; |
| 769 | if( colorize && p->pRe && re_dline_match(p->pRe, pLine, 1)==0 ){ |
| 770 | colorize = 0; |
| 771 | } |
| 772 | for(i=j=k=0; k<w && i<n; i++, k++){ |
| 773 | char c = zIn[i]; |
| 774 | if( colorize ){ |
| 775 | if( i==p->iStart ){ |
| 776 | int x = strlen(p->zStart); |
| 777 | memcpy(z+j, p->zStart, x); |
| 778 | j += x; |
| 779 | needEndSpan = 1; |
| 780 | if( p->iStart2 ){ |
| 781 | p->iStart = p->iStart2; |
| 782 | p->zStart = p->zStart2; |
| 783 | p->iStart2 = 0; |
| 784 | } |
| 785 | }else if( i==p->iEnd ){ |
| 786 | memcpy(z+j, "</span>", 7); |
| 787 | j += 7; |
| 788 | needEndSpan = 0; |
| 789 | if( p->iEnd2 ){ |
| 790 | p->iEnd = p->iEnd2; |
| 791 | p->iEnd2 = 0; |
| 792 | } |
| 793 | } |
| 794 | } |
| 795 | if( c=='\t' ){ |
| 796 | z[j++] = ' '; |
| 797 | while( (k&7)!=7 && k<w ){ z[j++] = ' '; k++; } |
| 798 | }else if( c=='\r' || c=='\f' ){ |
| 799 | z[j++] = ' '; |
| 800 | }else if( c=='<' && p->escHtml ){ |
| 801 | memcpy(&z[j], "<", 4); |
| 802 | j += 4; |
| 803 | }else if( c=='&' && p->escHtml ){ |
| 804 | memcpy(&z[j], "&", 5); |
| 805 | j += 5; |
| 806 | }else if( c=='>' && p->escHtml ){ |
| 807 | memcpy(&z[j], ">", 4); |
| 808 | j += 4; |
| 809 | }else if( c=='"' && p->escHtml ){ |
| 810 | memcpy(&z[j], """, 6); |
| 811 | j += 6; |
| 812 | }else{ |
| 813 | z[j++] = c; |
| 814 | if( (c&0xc0)==0x80 ) k--; |
| 815 | } |
| 816 | } |
| 817 | if( needEndSpan ){ |
| 818 | memcpy(&z[j], "</span>", 7); |
| 819 | j += 7; |
| 820 | } |
| 821 | if( (flags & SBS_PAD)!=0 ){ |
| 822 | while( k<w ){ k++; z[j++] = ' '; } |
| 823 | } |
| 824 | if( flags & SBS_NEWLINE ){ |
| 825 | z[j++] = '\n'; |
| 826 | } |
| 827 | p->n += j; |
| 828 | } |
| 829 | |
| 830 | /* |
| 831 | ** Append a string to an SbSLine without coding, interpretation, or padding. |
| 832 | */ |
| 833 | static void sbsWrite(SbsLine *p, const char *zIn, int nIn){ |
| 834 | memcpy(p->zLine+p->n, zIn, nIn); |
| 835 | p->n += nIn; |
| 836 | } |
| 837 | |
| 838 | /* |
| 839 | ** Append n spaces to the string. |
| 840 | */ |
| 841 | static void sbsWriteSpace(SbsLine *p, int n){ |
| 842 | while( n-- ) p->zLine[p->n++] = ' '; |
| 843 | } |
| 844 | |
| 845 | /* |
| 846 | ** Append a string to the output only if we are rendering HTML. |
| 847 | */ |
| 848 | static void sbsWriteHtml(SbsLine *p, const char *zIn){ |
| 849 | if( p->escHtml ) sbsWrite(p, zIn, strlen(zIn)); |
| 850 | } |
| 851 | |
| 852 | /* |
| 853 | ** Write a 6-digit line number followed by a single space onto the line. |
| 854 | */ |
| 855 | static void sbsWriteLineno(SbsLine *p, int ln){ |
| 856 | sbsWriteHtml(p, "<span class=\"diffln\">"); |
| 857 | sqlite3_snprintf(7, &p->zLine[p->n], "%5d ", ln+1); |
| 858 | p->n += 6; |
| 859 | sbsWriteHtml(p, "</span>"); |
| 860 | p->zLine[p->n++] = ' '; |
| 861 | } |
| 862 | |
| 863 | /* |
| 864 | ** The two text segments zLeft and zRight are known to be different on |
| 865 | ** both ends, but they might have a common segment in the middle. If |
| @@ -1018,43 +748,42 @@ | |
| 1018 | } |
| 1019 | if( nSuffix==nLeft || nSuffix==nRight ) nPrefix = 0; |
| 1020 | } |
| 1021 | if( nPrefix+nSuffix > nShort ) nPrefix = nShort - nSuffix; |
| 1022 | |
| 1023 | |
| 1024 | /* A single chunk of text inserted on the right */ |
| 1025 | if( nPrefix+nSuffix==nLeft ){ |
| 1026 | sbsWriteLineno(p, lnLeft); |
| 1027 | p->iStart2 = p->iEnd2 = 0; |
| 1028 | p->iStart = p->iEnd = -1; |
| 1029 | sbsWriteText(p, pLeft, SBS_PAD); |
| 1030 | if( nLeft==nRight && zLeft[nLeft]==zRight[nRight] ){ |
| 1031 | sbsWrite(p, " ", 3); |
| 1032 | }else{ |
| 1033 | sbsWrite(p, " | ", 3); |
| 1034 | } |
| 1035 | sbsWriteLineno(p, lnRight); |
| 1036 | p->iStart = nPrefix; |
| 1037 | p->iEnd = nRight - nSuffix; |
| 1038 | p->zStart = zClassAdd; |
| 1039 | sbsWriteText(p, pRight, SBS_NEWLINE); |
| 1040 | return; |
| 1041 | } |
| 1042 | |
| 1043 | /* A single chunk of text deleted from the left */ |
| 1044 | if( nPrefix+nSuffix==nRight ){ |
| 1045 | /* Text deleted from the left */ |
| 1046 | sbsWriteLineno(p, lnLeft); |
| 1047 | p->iStart2 = p->iEnd2 = 0; |
| 1048 | p->iStart = nPrefix; |
| 1049 | p->iEnd = nLeft - nSuffix; |
| 1050 | p->zStart = zClassRm; |
| 1051 | sbsWriteText(p, pLeft, SBS_PAD); |
| 1052 | sbsWrite(p, " | ", 3); |
| 1053 | sbsWriteLineno(p, lnRight); |
| 1054 | p->iStart = p->iEnd = -1; |
| 1055 | sbsWriteText(p, pRight, SBS_NEWLINE); |
| 1056 | return; |
| 1057 | } |
| 1058 | |
| 1059 | /* At this point we know that there is a chunk of text that has |
| 1060 | ** changed between the left and the right. Check to see if there |
| @@ -1065,11 +794,11 @@ | |
| 1065 | if( p->escHtml |
| 1066 | && nLeftDiff >= 6 |
| 1067 | && nRightDiff >= 6 |
| 1068 | && textLCS(&zLeft[nPrefix], nLeftDiff, &zRight[nPrefix], nRightDiff, aLCS) |
| 1069 | ){ |
| 1070 | sbsWriteLineno(p, lnLeft); |
| 1071 | p->iStart = nPrefix; |
| 1072 | p->iEnd = nPrefix + aLCS[0]; |
| 1073 | if( aLCS[2]==0 ){ |
| 1074 | sbsShiftLeft(p, pLeft->z); |
| 1075 | p->zStart = zClassRm; |
| @@ -1078,13 +807,13 @@ | |
| 1078 | } |
| 1079 | p->iStart2 = nPrefix + aLCS[1]; |
| 1080 | p->iEnd2 = nLeft - nSuffix; |
| 1081 | p->zStart2 = aLCS[3]==nRightDiff ? zClassRm : zClassChng; |
| 1082 | sbsSimplifyLine(p, zLeft+nPrefix); |
| 1083 | sbsWriteText(p, pLeft, SBS_PAD); |
| 1084 | sbsWrite(p, " | ", 3); |
| 1085 | sbsWriteLineno(p, lnRight); |
| 1086 | p->iStart = nPrefix; |
| 1087 | p->iEnd = nPrefix + aLCS[2]; |
| 1088 | if( aLCS[0]==0 ){ |
| 1089 | sbsShiftLeft(p, pRight->z); |
| 1090 | p->zStart = zClassAdd; |
| @@ -1093,25 +822,25 @@ | |
| 1093 | } |
| 1094 | p->iStart2 = nPrefix + aLCS[3]; |
| 1095 | p->iEnd2 = nRight - nSuffix; |
| 1096 | p->zStart2 = aLCS[1]==nLeftDiff ? zClassAdd : zClassChng; |
| 1097 | sbsSimplifyLine(p, zRight+nPrefix); |
| 1098 | sbsWriteText(p, pRight, SBS_NEWLINE); |
| 1099 | return; |
| 1100 | } |
| 1101 | |
| 1102 | /* If all else fails, show a single big change between left and right */ |
| 1103 | sbsWriteLineno(p, lnLeft); |
| 1104 | p->iStart2 = p->iEnd2 = 0; |
| 1105 | p->iStart = nPrefix; |
| 1106 | p->iEnd = nLeft - nSuffix; |
| 1107 | p->zStart = zClassChng; |
| 1108 | sbsWriteText(p, pLeft, SBS_PAD); |
| 1109 | sbsWrite(p, " | ", 3); |
| 1110 | sbsWriteLineno(p, lnRight); |
| 1111 | p->iEnd = nRight - nSuffix; |
| 1112 | sbsWriteText(p, pRight, SBS_NEWLINE); |
| 1113 | } |
| 1114 | |
| 1115 | /* |
| 1116 | ** Minimum of two values |
| 1117 | */ |
| @@ -1357,30 +1086,40 @@ | |
| 1357 | int mxr; /* Maximum value for r */ |
| 1358 | int na, nb; /* Number of lines shown from A and B */ |
| 1359 | int i, j; /* Loop counters */ |
| 1360 | int m, ma, mb;/* Number of lines to output */ |
| 1361 | int skip; /* Number of lines to skip */ |
| 1362 | int nChunk = 0; /* Number of chunks of diff output seen so far */ |
| 1363 | SbsLine s; /* Output line buffer */ |
| 1364 | int nContext; /* Lines of context above and below each change */ |
| 1365 | int showDivider = 0; /* True to show the divider */ |
| 1366 | |
| 1367 | memset(&s, 0, sizeof(s)); |
| 1368 | s.width = diff_width(diffFlags); |
| 1369 | s.zLine = fossil_malloc( 15*s.width + 200 ); |
| 1370 | if( s.zLine==0 ) return; |
| 1371 | nContext = diff_context_lines(diffFlags); |
| 1372 | s.escHtml = (diffFlags & DIFF_HTML)!=0; |
| 1373 | s.pRe = pRe; |
| 1374 | s.iStart = -1; |
| 1375 | s.iStart2 = 0; |
| 1376 | s.iEnd = -1; |
| 1377 | A = p->aFrom; |
| 1378 | B = p->aTo; |
| 1379 | R = p->aEdit; |
| 1380 | mxr = p->nEdit; |
| 1381 | while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; } |
| 1382 | for(r=0; r<mxr; r += 3*nr){ |
| 1383 | /* Figure out how many triples to show in a single block */ |
| 1384 | for(nr=1; R[r+nr*3]>0 && R[r+nr*3]<nContext*2; nr++){} |
| 1385 | /* printf("r=%d nr=%d\n", r, nr); */ |
| 1386 | |
| @@ -1436,35 +1175,39 @@ | |
| 1436 | } |
| 1437 | |
| 1438 | /* Draw the separator between blocks */ |
| 1439 | if( showDivider ){ |
| 1440 | if( s.escHtml ){ |
| 1441 | blob_appendf(pOut, "<span class=\"diffhr\">%.*c</span>\n", |
| 1442 | s.width*2+16, '.'); |
| 1443 | }else{ |
| 1444 | blob_appendf(pOut, "%.*c\n", s.width*2+16, '.'); |
| 1445 | } |
| 1446 | } |
| 1447 | showDivider = 1; |
| 1448 | nChunk++; |
| 1449 | if( s.escHtml ){ |
| 1450 | blob_appendf(pOut, "<a name=\"chunk%d\"></a>\n", nChunk); |
| 1451 | } |
| 1452 | |
| 1453 | /* Show the initial common area */ |
| 1454 | a += skip; |
| 1455 | b += skip; |
| 1456 | m = R[r] - skip; |
| 1457 | for(j=0; j<m; j++){ |
| 1458 | s.n = 0; |
| 1459 | sbsWriteLineno(&s, a+j); |
| 1460 | s.iStart = s.iEnd = -1; |
| 1461 | sbsWriteText(&s, &A[a+j], SBS_PAD); |
| 1462 | sbsWrite(&s, " ", 3); |
| 1463 | sbsWriteLineno(&s, b+j); |
| 1464 | sbsWriteText(&s, &B[b+j], SBS_NEWLINE); |
| 1465 | blob_append(pOut, s.zLine, s.n); |
| 1466 | } |
| 1467 | a += m; |
| 1468 | b += m; |
| 1469 | |
| 1470 | /* Show the differences */ |
| @@ -1485,87 +1228,71 @@ | |
| 1485 | |
| 1486 | alignment = sbsAlignment(&A[a], ma, &B[b], mb); |
| 1487 | for(j=0; ma+mb>0; j++){ |
| 1488 | if( alignment[j]==1 ){ |
| 1489 | /* Delete one line from the left */ |
| 1490 | s.n = 0; |
| 1491 | sbsWriteLineno(&s, a); |
| 1492 | s.iStart = 0; |
| 1493 | s.zStart = "<span class=\"diffrm\">"; |
| 1494 | s.iEnd = LENGTH(&A[a]); |
| 1495 | sbsWriteText(&s, &A[a], SBS_PAD); |
| 1496 | if( s.escHtml ){ |
| 1497 | sbsWrite(&s, " <\n", 6); |
| 1498 | }else{ |
| 1499 | sbsWrite(&s, " <\n", 3); |
| 1500 | } |
| 1501 | blob_append(pOut, s.zLine, s.n); |
| 1502 | assert( ma>0 ); |
| 1503 | ma--; |
| 1504 | a++; |
| 1505 | }else if( alignment[j]==3 ){ |
| 1506 | /* The left line is changed into the right line */ |
| 1507 | s.n = 0; |
| 1508 | sbsWriteLineChange(&s, &A[a], a, &B[b], b); |
| 1509 | blob_append(pOut, s.zLine, s.n); |
| 1510 | assert( ma>0 && mb>0 ); |
| 1511 | ma--; |
| 1512 | mb--; |
| 1513 | a++; |
| 1514 | b++; |
| 1515 | }else if( alignment[j]==2 ){ |
| 1516 | /* Insert one line on the right */ |
| 1517 | s.n = 0; |
| 1518 | sbsWriteSpace(&s, s.width + 7); |
| 1519 | if( s.escHtml ){ |
| 1520 | sbsWrite(&s, " > ", 6); |
| 1521 | }else{ |
| 1522 | sbsWrite(&s, " > ", 3); |
| 1523 | } |
| 1524 | sbsWriteLineno(&s, b); |
| 1525 | s.iStart = 0; |
| 1526 | s.zStart = "<span class=\"diffadd\">"; |
| 1527 | s.iEnd = LENGTH(&B[b]); |
| 1528 | sbsWriteText(&s, &B[b], SBS_NEWLINE); |
| 1529 | blob_append(pOut, s.zLine, s.n); |
| 1530 | assert( mb>0 ); |
| 1531 | mb--; |
| 1532 | b++; |
| 1533 | }else{ |
| 1534 | /* Delete from the left and insert on the right */ |
| 1535 | s.n = 0; |
| 1536 | sbsWriteLineno(&s, a); |
| 1537 | s.iStart = 0; |
| 1538 | s.zStart = "<span class=\"diffrm\">"; |
| 1539 | s.iEnd = LENGTH(&A[a]); |
| 1540 | sbsWriteText(&s, &A[a], SBS_PAD); |
| 1541 | sbsWrite(&s, " | ", 3); |
| 1542 | sbsWriteLineno(&s, b); |
| 1543 | s.iStart = 0; |
| 1544 | s.zStart = "<span class=\"diffadd\">"; |
| 1545 | s.iEnd = LENGTH(&B[b]); |
| 1546 | sbsWriteText(&s, &B[b], SBS_NEWLINE); |
| 1547 | blob_append(pOut, s.zLine, s.n); |
| 1548 | ma--; |
| 1549 | mb--; |
| 1550 | a++; |
| 1551 | b++; |
| 1552 | } |
| 1553 | |
| 1554 | } |
| 1555 | fossil_free(alignment); |
| 1556 | if( i<nr-1 ){ |
| 1557 | m = R[r+i*3+3]; |
| 1558 | for(j=0; j<m; j++){ |
| 1559 | s.n = 0; |
| 1560 | sbsWriteLineno(&s, a+j); |
| 1561 | s.iStart = s.iEnd = -1; |
| 1562 | sbsWriteText(&s, &A[a+j], SBS_PAD); |
| 1563 | sbsWrite(&s, " ", 3); |
| 1564 | sbsWriteLineno(&s, b+j); |
| 1565 | sbsWriteText(&s, &B[b+j], SBS_NEWLINE); |
| 1566 | blob_append(pOut, s.zLine, s.n); |
| 1567 | } |
| 1568 | b += m; |
| 1569 | a += m; |
| 1570 | } |
| 1571 | } |
| @@ -1573,21 +1300,27 @@ | |
| 1573 | /* Show the final common area */ |
| 1574 | assert( nr==i ); |
| 1575 | m = R[r+nr*3]; |
| 1576 | if( m>nContext ) m = nContext; |
| 1577 | for(j=0; j<m; j++){ |
| 1578 | s.n = 0; |
| 1579 | sbsWriteLineno(&s, a+j); |
| 1580 | s.iStart = s.iEnd = -1; |
| 1581 | sbsWriteText(&s, &A[a+j], SBS_PAD); |
| 1582 | sbsWrite(&s, " ", 3); |
| 1583 | sbsWriteLineno(&s, b+j); |
| 1584 | sbsWriteText(&s, &B[b+j], SBS_NEWLINE); |
| 1585 | blob_append(pOut, s.zLine, s.n); |
| 1586 | } |
| 1587 | } |
| 1588 | free(s.zLine); |
| 1589 | } |
| 1590 | |
| 1591 | /* |
| 1592 | ** Compute the optimal longest common subsequence (LCS) using an |
| 1593 | ** exhaustive search. This version of the LCS is only used for |
| @@ -1990,10 +1723,21 @@ | |
| 1990 | int diff_width(u64 diffFlags){ |
| 1991 | int w = (diffFlags & DIFF_WIDTH_MASK)/(DIFF_CONTEXT_MASK+1); |
| 1992 | if( w==0 ) w = 80; |
| 1993 | return w; |
| 1994 | } |
| 1995 | |
| 1996 | /* |
| 1997 | ** Generate a report of the differences between files pA and pB. |
| 1998 | ** If pOut is not NULL then a unified diff is appended there. It |
| 1999 | ** is assumed that pOut has already been initialized. If pOut is |
| @@ -2032,11 +1776,11 @@ | |
| 2032 | &c.nTo, ignoreEolWs); |
| 2033 | if( c.aFrom==0 || c.aTo==0 ){ |
| 2034 | fossil_free(c.aFrom); |
| 2035 | fossil_free(c.aTo); |
| 2036 | if( pOut ){ |
| 2037 | blob_appendf(pOut, DIFF_CANNOT_COMPUTE_BINARY); |
| 2038 | } |
| 2039 | return 0; |
| 2040 | } |
| 2041 | |
| 2042 | /* Compute the difference */ |
| @@ -2048,15 +1792,11 @@ | |
| 2048 | for(i=m=n=0; i<mx; i+=3){ m += a[i]; n += a[i+1]+a[i+2]; } |
| 2049 | if( n>10000 ){ |
| 2050 | fossil_free(c.aFrom); |
| 2051 | fossil_free(c.aTo); |
| 2052 | fossil_free(c.aEdit); |
| 2053 | if( diffFlags & DIFF_HTML ){ |
| 2054 | blob_append(pOut, DIFF_TOO_MANY_CHANGES_HTML, -1); |
| 2055 | }else{ |
| 2056 | blob_append(pOut, DIFF_TOO_MANY_CHANGES_TXT, -1); |
| 2057 | } |
| 2058 | return 0; |
| 2059 | } |
| 2060 | } |
| 2061 | if( (diffFlags & DIFF_NOOPT)==0 ){ |
| 2062 | diff_optimize(&c); |
| @@ -2159,10 +1899,11 @@ | |
| 2159 | if( find_option("tk",0,0)!=0 ){ |
| 2160 | diff_tk("test-diff", 2); |
| 2161 | return; |
| 2162 | } |
| 2163 | find_option("i",0,0); |
| 2164 | zRe = find_option("regexp","e",1); |
| 2165 | if( zRe ){ |
| 2166 | const char *zErr = re_compile(&pRe, zRe, 0); |
| 2167 | if( zErr ) fossil_fatal("regex error: %s", zErr); |
| 2168 | } |
| @@ -2616,60 +2357,5 @@ | |
| 2616 | zPrefix[0] = 0; |
| 2617 | } |
| 2618 | fossil_print("%21s %4d: %.*s\n", zPrefix, i+1, n, z); |
| 2619 | } |
| 2620 | } |
| 2621 | |
| 2622 | /* |
| 2623 | ** COMMAND: test-looks-like-utf |
| 2624 | ** |
| 2625 | ** Usage: %fossil test-looks-like-utf FILENAME |
| 2626 | ** |
| 2627 | ** Options: |
| 2628 | ** --utf8 Ignoring BOM and file size, force UTF-8 checking |
| 2629 | ** --utf16 Ignoring BOM and file size, force UTF-16 checking |
| 2630 | ** |
| 2631 | ** FILENAME is the name of a file to check for textual content in the UTF-8 |
| 2632 | ** and/or UTF-16 encodings. |
| 2633 | */ |
| 2634 | void looks_like_utf_test_cmd(void){ |
| 2635 | Blob blob; /* the contents of the specified file */ |
| 2636 | int fUtf8; /* return value of starts_with_utf8_bom() */ |
| 2637 | int fUtf16; /* return value of starts_with_utf16_bom() */ |
| 2638 | int fUnicode; /* return value of could_be_utf16() */ |
| 2639 | int lookFlags; /* output flags from looks_like_utf8/utf16() */ |
| 2640 | int bRevUtf16 = 0; /* non-zero -> UTF-16 byte order reversed */ |
| 2641 | int bRevUnicode = 0; /* non-zero -> UTF-16 byte order reversed */ |
| 2642 | int fForceUtf8 = find_option("utf8",0,0)!=0; |
| 2643 | int fForceUtf16 = find_option("utf16",0,0)!=0; |
| 2644 | if( g.argc!=3 ) usage("FILENAME"); |
| 2645 | blob_read_from_file(&blob, g.argv[2]); |
| 2646 | fUtf8 = starts_with_utf8_bom(&blob, 0); |
| 2647 | fUtf16 = starts_with_utf16_bom(&blob, 0, &bRevUtf16); |
| 2648 | if( fForceUtf8 ){ |
| 2649 | fUnicode = 0; |
| 2650 | }else{ |
| 2651 | fUnicode = could_be_utf16(&blob, &bRevUnicode) || fForceUtf16; |
| 2652 | } |
| 2653 | lookFlags = fUnicode ? looks_like_utf16(&blob, bRevUnicode, 0) : |
| 2654 | looks_like_utf8(&blob, 0); |
| 2655 | fossil_print("File \"%s\" has %d bytes.\n",g.argv[2],blob_size(&blob)); |
| 2656 | fossil_print("Starts with UTF-8 BOM: %s\n",fUtf8?"yes":"no"); |
| 2657 | fossil_print("Starts with UTF-16 BOM: %s\n", |
| 2658 | fUtf16?(bRevUtf16?"reversed":"yes"):"no"); |
| 2659 | fossil_print("Looks like UTF-%s: %s\n",fUnicode?"16":"8", |
| 2660 | (lookFlags&LOOK_BINARY)?"no":"yes"); |
| 2661 | fossil_print("Has flag LOOK_NUL: %s\n",(lookFlags&LOOK_NUL)?"yes":"no"); |
| 2662 | fossil_print("Has flag LOOK_CR: %s\n",(lookFlags&LOOK_CR)?"yes":"no"); |
| 2663 | fossil_print("Has flag LOOK_LONE_CR: %s\n", |
| 2664 | (lookFlags&LOOK_LONE_CR)?"yes":"no"); |
| 2665 | fossil_print("Has flag LOOK_LF: %s\n",(lookFlags&LOOK_LF)?"yes":"no"); |
| 2666 | fossil_print("Has flag LOOK_LONE_LF: %s\n", |
| 2667 | (lookFlags&LOOK_LONE_LF)?"yes":"no"); |
| 2668 | fossil_print("Has flag LOOK_CRLF: %s\n",(lookFlags&LOOK_CRLF)?"yes":"no"); |
| 2669 | fossil_print("Has flag LOOK_LONG: %s\n",(lookFlags&LOOK_LONG)?"yes":"no"); |
| 2670 | fossil_print("Has flag LOOK_INVALID: %s\n", |
| 2671 | (lookFlags&LOOK_INVALID)?"yes":"no"); |
| 2672 | fossil_print("Has flag LOOK_ODD: %s\n",(lookFlags&LOOK_ODD)?"yes":"no"); |
| 2673 | fossil_print("Has flag LOOK_SHORT: %s\n",(lookFlags&LOOK_SHORT)?"yes":"no"); |
| 2674 | blob_reset(&blob); |
| 2675 | } |
| 2676 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -51,47 +51,20 @@ | |
| 51 | "cannot compute difference between binary files\n" |
| 52 | |
| 53 | #define DIFF_CANNOT_COMPUTE_SYMLINK \ |
| 54 | "cannot compute difference between symlink and regular file\n" |
| 55 | |
| 56 | #define DIFF_TOO_MANY_CHANGES \ |
| 57 | "more than 10,000 changes\n" |
| 58 | |
| 59 | /* |
| 60 | ** Maximum length of a line in a text file, in bytes. (2**13 = 8192 bytes) |
| 61 | */ |
| 62 | #define LENGTH_MASK_SZ 13 |
| 63 | #define LENGTH_MASK ((1<<LENGTH_MASK_SZ)-1) |
| 64 | |
| 65 | #endif /* INTERFACE */ |
| 66 | |
| 67 | /* |
| 68 | ** Information about each line of a file being diffed. |
| 69 | ** |
| 70 | ** The lower LENGTH_MASK_SZ bits of the hash (DLine.h) are the length |
| @@ -204,282 +177,10 @@ | |
| 177 | /* Return results */ |
| 178 | *pnLine = nLine; |
| 179 | return a; |
| 180 | } |
| 181 | |
| 182 | /* |
| 183 | ** Return true if two DLine elements are identical. |
| 184 | */ |
| 185 | static int same_dline(DLine *pA, DLine *pB){ |
| 186 | return pA->h==pB->h && memcmp(pA->z,pB->z,pA->h & LENGTH_MASK)==0; |
| @@ -576,11 +277,11 @@ | |
| 277 | int mxr; /* Maximum value for r */ |
| 278 | int na, nb; /* Number of lines shown from A and B */ |
| 279 | int i, j; /* Loop counters */ |
| 280 | int m; /* Number of lines to output */ |
| 281 | int skip; /* Number of lines to skip */ |
| 282 | static int nChunk = 0; /* Number of diff chunks seen so far */ |
| 283 | int nContext; /* Number of lines of context */ |
| 284 | int showLn; /* Show line numbers */ |
| 285 | int html; /* Render as HTML */ |
| 286 | int showDivider = 0; /* True to show the divider between diff blocks */ |
| 287 | |
| @@ -657,14 +358,14 @@ | |
| 358 | if( !showDivider ){ |
| 359 | /* Do not show a top divider */ |
| 360 | showDivider = 1; |
| 361 | }else if( html ){ |
| 362 | blob_appendf(pOut, "<span class=\"diffhr\">%.80c</span>\n", '.'); |
| 363 | }else{ |
| 364 | blob_appendf(pOut, "%.80c\n", '.'); |
| 365 | } |
| 366 | if( html ) blob_appendf(pOut, "<span id=\"chunk%d\"></span>", nChunk); |
| 367 | }else{ |
| 368 | if( html ) blob_appendf(pOut, "<span class=\"diffln\">"); |
| 369 | /* |
| 370 | * If the patch changes an empty file or results in an empty file, |
| 371 | * the block header must use 0,0 as position indicator and not 1,0. |
| @@ -727,12 +428,11 @@ | |
| 428 | /* |
| 429 | ** Status of a single output line |
| 430 | */ |
| 431 | typedef struct SbsLine SbsLine; |
| 432 | struct SbsLine { |
| 433 | Blob *apCols[5]; /* Array of pointers to output columns */ |
| 434 | int width; /* Maximum width of a column in the output */ |
| 435 | unsigned char escHtml; /* True to escape html characters */ |
| 436 | int iStart; /* Write zStart prior to character iStart */ |
| 437 | const char *zStart; /* A <span> tag */ |
| 438 | int iEnd; /* Write </span> prior to character iEnd */ |
| @@ -741,125 +441,155 @@ | |
| 441 | int iEnd2; /* Write </span> prior to character iEnd2 */ |
| 442 | ReCompiled *pRe; /* Only colorize matching lines, if not NULL */ |
| 443 | }; |
| 444 | |
| 445 | /* |
| 446 | ** Column indices for SbsLine.apCols[] |
| 447 | */ |
| 448 | #define SBS_LNA 0 /* Left line number */ |
| 449 | #define SBS_TXTA 1 /* Left text */ |
| 450 | #define SBS_MKR 2 /* Middle separator column */ |
| 451 | #define SBS_LNB 3 /* Right line number */ |
| 452 | #define SBS_TXTB 4 /* Right text */ |
| 453 | |
| 454 | /* |
| 455 | ** Append newlines to all columns. |
| 456 | */ |
| 457 | static void sbsWriteNewlines(SbsLine *p){ |
| 458 | int i; |
| 459 | for( i=p->escHtml ? SBS_LNA : SBS_TXTB; i<=SBS_TXTB; i++ ){ |
| 460 | blob_append(p->apCols[i], "\n", 1); |
| 461 | } |
| 462 | } |
| 463 | |
| 464 | /* |
| 465 | ** Append n spaces to the column. |
| 466 | */ |
| 467 | static void sbsWriteSpace(SbsLine *p, int n, int col){ |
| 468 | blob_appendf(p->apCols[col], "%*s", n, ""); |
| 469 | } |
| 470 | |
| 471 | /* |
| 472 | ** Write the text of pLine into column iCol of p. |
| 473 | ** |
| 474 | ** If outputting HTML, write the full line. Otherwise, only write the |
| 475 | ** width characters. Translate tabs into spaces. Add newlines if col |
| 476 | ** is SBS_TXTB. Translate HTML characters if escHtml is true. Pad the |
| 477 | ** rendering to width bytes if col is SBS_TXTA and escHtml is false. |
| 478 | ** |
| 479 | ** This comment contains multibyte unicode characters (ü, Æ, ð) in order |
| 480 | ** to test the ability of the diff code to handle such characters. |
| 481 | */ |
| 482 | static void sbsWriteText(SbsLine *p, DLine *pLine, int col){ |
| 483 | Blob *pCol = p->apCols[col]; |
| 484 | int n = pLine->h & LENGTH_MASK; |
| 485 | int i; /* Number of input characters consumed */ |
| 486 | int k; /* Cursor position */ |
| 487 | int needEndSpan = 0; |
| 488 | const char *zIn = pLine->z; |
| 489 | int w = p->width; |
| 490 | int colorize = p->escHtml; |
| 491 | if( colorize && p->pRe && re_dline_match(p->pRe, pLine, 1)==0 ){ |
| 492 | colorize = 0; |
| 493 | } |
| 494 | for(i=k=0; (p->escHtml || k<w) && i<n; i++, k++){ |
| 495 | char c = zIn[i]; |
| 496 | if( colorize ){ |
| 497 | if( i==p->iStart ){ |
| 498 | int x = strlen(p->zStart); |
| 499 | blob_append(pCol, p->zStart, x); |
| 500 | needEndSpan = 1; |
| 501 | if( p->iStart2 ){ |
| 502 | p->iStart = p->iStart2; |
| 503 | p->zStart = p->zStart2; |
| 504 | p->iStart2 = 0; |
| 505 | } |
| 506 | }else if( i==p->iEnd ){ |
| 507 | blob_append(pCol, "</span>", 7); |
| 508 | needEndSpan = 0; |
| 509 | if( p->iEnd2 ){ |
| 510 | p->iEnd = p->iEnd2; |
| 511 | p->iEnd2 = 0; |
| 512 | } |
| 513 | } |
| 514 | } |
| 515 | if( c=='\t' && !p->escHtml ){ |
| 516 | blob_append(pCol, " ", 1); |
| 517 | while( (k&7)!=7 && (p->escHtml || k<w) ){ |
| 518 | blob_append(pCol, " ", 1); |
| 519 | k++; |
| 520 | } |
| 521 | }else if( c=='\r' || c=='\f' ){ |
| 522 | blob_append(pCol, " ", 1); |
| 523 | }else if( c=='<' && p->escHtml ){ |
| 524 | blob_append(pCol, "<", 4); |
| 525 | }else if( c=='&' && p->escHtml ){ |
| 526 | blob_append(pCol, "&", 5); |
| 527 | }else if( c=='>' && p->escHtml ){ |
| 528 | blob_append(pCol, ">", 4); |
| 529 | }else if( c=='"' && p->escHtml ){ |
| 530 | blob_append(pCol, """, 6); |
| 531 | }else{ |
| 532 | blob_append(pCol, &zIn[i], 1); |
| 533 | if( (c&0xc0)==0x80 ) k--; |
| 534 | } |
| 535 | } |
| 536 | if( needEndSpan ){ |
| 537 | blob_append(pCol, "</span>", 7); |
| 538 | } |
| 539 | if( col==SBS_TXTB ){ |
| 540 | sbsWriteNewlines(p); |
| 541 | }else if( !p->escHtml ){ |
| 542 | sbsWriteSpace(p, w-k, SBS_TXTA); |
| 543 | } |
| 544 | } |
| 545 | |
| 546 | /* |
| 547 | ** Append a column to the final output blob. |
| 548 | */ |
| 549 | static void sbsWriteColumn(Blob *pOut, Blob *pCol, int col){ |
| 550 | blob_appendf(pOut, |
| 551 | "<td><div class=\"diff%scol\">\n" |
| 552 | "<pre>\n" |
| 553 | "%s" |
| 554 | "</pre>\n" |
| 555 | "</div></td>\n", |
| 556 | col % 3 ? (col == SBS_MKR ? "mkr" : "txt") : "ln", |
| 557 | blob_str(pCol) |
| 558 | ); |
| 559 | } |
| 560 | |
| 561 | /* |
| 562 | ** Append a separator line to column iCol |
| 563 | */ |
| 564 | static void sbsWriteSep(SbsLine *p, int len, int col){ |
| 565 | char ch = '.'; |
| 566 | if( len<1 ){ |
| 567 | len = 1; |
| 568 | ch = ' '; |
| 569 | } |
| 570 | blob_appendf(p->apCols[col], "<span class=\"diffhr\">%.*c</span>\n", len, ch); |
| 571 | } |
| 572 | |
| 573 | /* |
| 574 | ** Append the appropriate marker into the center column of the diff. |
| 575 | */ |
| 576 | static void sbsWriteMarker(SbsLine *p, const char *zTxt, const char *zHtml){ |
| 577 | blob_append(p->apCols[SBS_MKR], p->escHtml ? zHtml : zTxt, -1); |
| 578 | } |
| 579 | |
| 580 | /* |
| 581 | ** Append a line number to the column. |
| 582 | */ |
| 583 | static void sbsWriteLineno(SbsLine *p, int ln, int col){ |
| 584 | if( p->escHtml ){ |
| 585 | blob_appendf(p->apCols[col], "%d", ln+1); |
| 586 | }else{ |
| 587 | char zLn[7]; |
| 588 | sqlite3_snprintf(7, zLn, "%5d ", ln+1); |
| 589 | blob_appendf(p->apCols[col], "%s ", zLn); |
| 590 | } |
| 591 | } |
| 592 | |
| 593 | /* |
| 594 | ** The two text segments zLeft and zRight are known to be different on |
| 595 | ** both ends, but they might have a common segment in the middle. If |
| @@ -1018,43 +748,42 @@ | |
| 748 | } |
| 749 | if( nSuffix==nLeft || nSuffix==nRight ) nPrefix = 0; |
| 750 | } |
| 751 | if( nPrefix+nSuffix > nShort ) nPrefix = nShort - nSuffix; |
| 752 | |
| 753 | /* A single chunk of text inserted on the right */ |
| 754 | if( nPrefix+nSuffix==nLeft ){ |
| 755 | sbsWriteLineno(p, lnLeft, SBS_LNA); |
| 756 | p->iStart2 = p->iEnd2 = 0; |
| 757 | p->iStart = p->iEnd = -1; |
| 758 | sbsWriteText(p, pLeft, SBS_TXTA); |
| 759 | if( nLeft==nRight && zLeft[nLeft]==zRight[nRight] ){ |
| 760 | sbsWriteMarker(p, " ", ""); |
| 761 | }else{ |
| 762 | sbsWriteMarker(p, " | ", "|"); |
| 763 | } |
| 764 | sbsWriteLineno(p, lnRight, SBS_LNB); |
| 765 | p->iStart = nPrefix; |
| 766 | p->iEnd = nRight - nSuffix; |
| 767 | p->zStart = zClassAdd; |
| 768 | sbsWriteText(p, pRight, SBS_TXTB); |
| 769 | return; |
| 770 | } |
| 771 | |
| 772 | /* A single chunk of text deleted from the left */ |
| 773 | if( nPrefix+nSuffix==nRight ){ |
| 774 | /* Text deleted from the left */ |
| 775 | sbsWriteLineno(p, lnLeft, SBS_LNA); |
| 776 | p->iStart2 = p->iEnd2 = 0; |
| 777 | p->iStart = nPrefix; |
| 778 | p->iEnd = nLeft - nSuffix; |
| 779 | p->zStart = zClassRm; |
| 780 | sbsWriteText(p, pLeft, SBS_TXTA); |
| 781 | sbsWriteMarker(p, " | ", "|"); |
| 782 | sbsWriteLineno(p, lnRight, SBS_LNB); |
| 783 | p->iStart = p->iEnd = -1; |
| 784 | sbsWriteText(p, pRight, SBS_TXTB); |
| 785 | return; |
| 786 | } |
| 787 | |
| 788 | /* At this point we know that there is a chunk of text that has |
| 789 | ** changed between the left and the right. Check to see if there |
| @@ -1065,11 +794,11 @@ | |
| 794 | if( p->escHtml |
| 795 | && nLeftDiff >= 6 |
| 796 | && nRightDiff >= 6 |
| 797 | && textLCS(&zLeft[nPrefix], nLeftDiff, &zRight[nPrefix], nRightDiff, aLCS) |
| 798 | ){ |
| 799 | sbsWriteLineno(p, lnLeft, SBS_LNA); |
| 800 | p->iStart = nPrefix; |
| 801 | p->iEnd = nPrefix + aLCS[0]; |
| 802 | if( aLCS[2]==0 ){ |
| 803 | sbsShiftLeft(p, pLeft->z); |
| 804 | p->zStart = zClassRm; |
| @@ -1078,13 +807,13 @@ | |
| 807 | } |
| 808 | p->iStart2 = nPrefix + aLCS[1]; |
| 809 | p->iEnd2 = nLeft - nSuffix; |
| 810 | p->zStart2 = aLCS[3]==nRightDiff ? zClassRm : zClassChng; |
| 811 | sbsSimplifyLine(p, zLeft+nPrefix); |
| 812 | sbsWriteText(p, pLeft, SBS_TXTA); |
| 813 | sbsWriteMarker(p, " | ", "|"); |
| 814 | sbsWriteLineno(p, lnRight, SBS_LNB); |
| 815 | p->iStart = nPrefix; |
| 816 | p->iEnd = nPrefix + aLCS[2]; |
| 817 | if( aLCS[0]==0 ){ |
| 818 | sbsShiftLeft(p, pRight->z); |
| 819 | p->zStart = zClassAdd; |
| @@ -1093,25 +822,25 @@ | |
| 822 | } |
| 823 | p->iStart2 = nPrefix + aLCS[3]; |
| 824 | p->iEnd2 = nRight - nSuffix; |
| 825 | p->zStart2 = aLCS[1]==nLeftDiff ? zClassAdd : zClassChng; |
| 826 | sbsSimplifyLine(p, zRight+nPrefix); |
| 827 | sbsWriteText(p, pRight, SBS_TXTB); |
| 828 | return; |
| 829 | } |
| 830 | |
| 831 | /* If all else fails, show a single big change between left and right */ |
| 832 | sbsWriteLineno(p, lnLeft, SBS_LNA); |
| 833 | p->iStart2 = p->iEnd2 = 0; |
| 834 | p->iStart = nPrefix; |
| 835 | p->iEnd = nLeft - nSuffix; |
| 836 | p->zStart = zClassChng; |
| 837 | sbsWriteText(p, pLeft, SBS_TXTA); |
| 838 | sbsWriteMarker(p, " | ", "|"); |
| 839 | sbsWriteLineno(p, lnRight, SBS_LNB); |
| 840 | p->iEnd = nRight - nSuffix; |
| 841 | sbsWriteText(p, pRight, SBS_TXTB); |
| 842 | } |
| 843 | |
| 844 | /* |
| 845 | ** Minimum of two values |
| 846 | */ |
| @@ -1357,30 +1086,40 @@ | |
| 1086 | int mxr; /* Maximum value for r */ |
| 1087 | int na, nb; /* Number of lines shown from A and B */ |
| 1088 | int i, j; /* Loop counters */ |
| 1089 | int m, ma, mb;/* Number of lines to output */ |
| 1090 | int skip; /* Number of lines to skip */ |
| 1091 | static int nChunk = 0; /* Number of chunks of diff output seen so far */ |
| 1092 | SbsLine s; /* Output line buffer */ |
| 1093 | int nContext; /* Lines of context above and below each change */ |
| 1094 | int showDivider = 0; /* True to show the divider */ |
| 1095 | Blob aCols[5]; /* Array of column blobs */ |
| 1096 | |
| 1097 | memset(&s, 0, sizeof(s)); |
| 1098 | s.width = diff_width(diffFlags); |
| 1099 | nContext = diff_context_lines(diffFlags); |
| 1100 | s.escHtml = (diffFlags & DIFF_HTML)!=0; |
| 1101 | if( s.escHtml ){ |
| 1102 | for(i=SBS_LNA; i<=SBS_TXTB; i++){ |
| 1103 | blob_zero(&aCols[i]); |
| 1104 | s.apCols[i] = &aCols[i]; |
| 1105 | } |
| 1106 | }else{ |
| 1107 | for(i=SBS_LNA; i<=SBS_TXTB; i++){ |
| 1108 | s.apCols[i] = pOut; |
| 1109 | } |
| 1110 | } |
| 1111 | s.pRe = pRe; |
| 1112 | s.iStart = -1; |
| 1113 | s.iStart2 = 0; |
| 1114 | s.iEnd = -1; |
| 1115 | A = p->aFrom; |
| 1116 | B = p->aTo; |
| 1117 | R = p->aEdit; |
| 1118 | mxr = p->nEdit; |
| 1119 | while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; } |
| 1120 | |
| 1121 | for(r=0; r<mxr; r += 3*nr){ |
| 1122 | /* Figure out how many triples to show in a single block */ |
| 1123 | for(nr=1; R[r+nr*3]>0 && R[r+nr*3]<nContext*2; nr++){} |
| 1124 | /* printf("r=%d nr=%d\n", r, nr); */ |
| 1125 | |
| @@ -1436,35 +1175,39 @@ | |
| 1175 | } |
| 1176 | |
| 1177 | /* Draw the separator between blocks */ |
| 1178 | if( showDivider ){ |
| 1179 | if( s.escHtml ){ |
| 1180 | char zLn[10]; |
| 1181 | sqlite3_snprintf(sizeof(zLn), zLn, "%d", a+skip+1); |
| 1182 | sbsWriteSep(&s, strlen(zLn), SBS_LNA); |
| 1183 | sbsWriteSep(&s, s.width, SBS_TXTA); |
| 1184 | sbsWriteSep(&s, 0, SBS_MKR); |
| 1185 | sqlite3_snprintf(sizeof(zLn), zLn, "%d", b+skip+1); |
| 1186 | sbsWriteSep(&s, strlen(zLn), SBS_LNB); |
| 1187 | sbsWriteSep(&s, s.width, SBS_TXTB); |
| 1188 | }else{ |
| 1189 | blob_appendf(pOut, "%.*c\n", s.width*2+16, '.'); |
| 1190 | } |
| 1191 | } |
| 1192 | showDivider = 1; |
| 1193 | nChunk++; |
| 1194 | if( s.escHtml ){ |
| 1195 | blob_appendf(s.apCols[SBS_LNA], "<span id=\"chunk%d\"></span>", nChunk); |
| 1196 | } |
| 1197 | |
| 1198 | /* Show the initial common area */ |
| 1199 | a += skip; |
| 1200 | b += skip; |
| 1201 | m = R[r] - skip; |
| 1202 | for(j=0; j<m; j++){ |
| 1203 | sbsWriteLineno(&s, a+j, SBS_LNA); |
| 1204 | s.iStart = s.iEnd = -1; |
| 1205 | sbsWriteText(&s, &A[a+j], SBS_TXTA); |
| 1206 | sbsWriteMarker(&s, " ", ""); |
| 1207 | sbsWriteLineno(&s, b+j, SBS_LNB); |
| 1208 | sbsWriteText(&s, &B[b+j], SBS_TXTB); |
| 1209 | } |
| 1210 | a += m; |
| 1211 | b += m; |
| 1212 | |
| 1213 | /* Show the differences */ |
| @@ -1485,87 +1228,71 @@ | |
| 1228 | |
| 1229 | alignment = sbsAlignment(&A[a], ma, &B[b], mb); |
| 1230 | for(j=0; ma+mb>0; j++){ |
| 1231 | if( alignment[j]==1 ){ |
| 1232 | /* Delete one line from the left */ |
| 1233 | sbsWriteLineno(&s, a, SBS_LNA); |
| 1234 | s.iStart = 0; |
| 1235 | s.zStart = "<span class=\"diffrm\">"; |
| 1236 | s.iEnd = LENGTH(&A[a]); |
| 1237 | sbsWriteText(&s, &A[a], SBS_TXTA); |
| 1238 | sbsWriteMarker(&s, " <", "<"); |
| 1239 | sbsWriteNewlines(&s); |
| 1240 | assert( ma>0 ); |
| 1241 | ma--; |
| 1242 | a++; |
| 1243 | }else if( alignment[j]==3 ){ |
| 1244 | /* The left line is changed into the right line */ |
| 1245 | sbsWriteLineChange(&s, &A[a], a, &B[b], b); |
| 1246 | assert( ma>0 && mb>0 ); |
| 1247 | ma--; |
| 1248 | mb--; |
| 1249 | a++; |
| 1250 | b++; |
| 1251 | }else if( alignment[j]==2 ){ |
| 1252 | /* Insert one line on the right */ |
| 1253 | if( !s.escHtml ){ |
| 1254 | sbsWriteSpace(&s, s.width + 7, SBS_TXTA); |
| 1255 | } |
| 1256 | sbsWriteMarker(&s, " > ", ">"); |
| 1257 | sbsWriteLineno(&s, b, SBS_LNB); |
| 1258 | s.iStart = 0; |
| 1259 | s.zStart = "<span class=\"diffadd\">"; |
| 1260 | s.iEnd = LENGTH(&B[b]); |
| 1261 | sbsWriteText(&s, &B[b], SBS_TXTB); |
| 1262 | assert( mb>0 ); |
| 1263 | mb--; |
| 1264 | b++; |
| 1265 | }else{ |
| 1266 | /* Delete from the left and insert on the right */ |
| 1267 | sbsWriteLineno(&s, a, SBS_LNA); |
| 1268 | s.iStart = 0; |
| 1269 | s.zStart = "<span class=\"diffrm\">"; |
| 1270 | s.iEnd = LENGTH(&A[a]); |
| 1271 | sbsWriteText(&s, &A[a], SBS_TXTA); |
| 1272 | sbsWriteMarker(&s, " | ", "|"); |
| 1273 | sbsWriteLineno(&s, b, SBS_LNB); |
| 1274 | s.iStart = 0; |
| 1275 | s.zStart = "<span class=\"diffadd\">"; |
| 1276 | s.iEnd = LENGTH(&B[b]); |
| 1277 | sbsWriteText(&s, &B[b], SBS_TXTB); |
| 1278 | ma--; |
| 1279 | mb--; |
| 1280 | a++; |
| 1281 | b++; |
| 1282 | } |
| 1283 | } |
| 1284 | fossil_free(alignment); |
| 1285 | if( i<nr-1 ){ |
| 1286 | m = R[r+i*3+3]; |
| 1287 | for(j=0; j<m; j++){ |
| 1288 | sbsWriteLineno(&s, a+j, SBS_LNA); |
| 1289 | s.iStart = s.iEnd = -1; |
| 1290 | sbsWriteText(&s, &A[a+j], SBS_TXTA); |
| 1291 | sbsWriteMarker(&s, " ", ""); |
| 1292 | sbsWriteLineno(&s, b+j, SBS_LNB); |
| 1293 | sbsWriteText(&s, &B[b+j], SBS_TXTB); |
| 1294 | } |
| 1295 | b += m; |
| 1296 | a += m; |
| 1297 | } |
| 1298 | } |
| @@ -1573,21 +1300,27 @@ | |
| 1300 | /* Show the final common area */ |
| 1301 | assert( nr==i ); |
| 1302 | m = R[r+nr*3]; |
| 1303 | if( m>nContext ) m = nContext; |
| 1304 | for(j=0; j<m; j++){ |
| 1305 | sbsWriteLineno(&s, a+j, SBS_LNA); |
| 1306 | s.iStart = s.iEnd = -1; |
| 1307 | sbsWriteText(&s, &A[a+j], SBS_TXTA); |
| 1308 | sbsWriteMarker(&s, " ", ""); |
| 1309 | sbsWriteLineno(&s, b+j, SBS_LNB); |
| 1310 | sbsWriteText(&s, &B[b+j], SBS_TXTB); |
| 1311 | } |
| 1312 | } |
| 1313 | |
| 1314 | if( s.escHtml && blob_size(s.apCols[SBS_LNA])>0 ){ |
| 1315 | blob_append(pOut, "<table class=\"sbsdiffcols\" width=\"90%\"><tr>\n", -1); |
| 1316 | for(i=SBS_LNA; i<=SBS_TXTB; i++){ |
| 1317 | sbsWriteColumn(pOut, s.apCols[i], i); |
| 1318 | blob_reset(s.apCols[i]); |
| 1319 | } |
| 1320 | blob_append(pOut, "</tr></table>\n", -1); |
| 1321 | } |
| 1322 | } |
| 1323 | |
| 1324 | /* |
| 1325 | ** Compute the optimal longest common subsequence (LCS) using an |
| 1326 | ** exhaustive search. This version of the LCS is only used for |
| @@ -1990,10 +1723,21 @@ | |
| 1723 | int diff_width(u64 diffFlags){ |
| 1724 | int w = (diffFlags & DIFF_WIDTH_MASK)/(DIFF_CONTEXT_MASK+1); |
| 1725 | if( w==0 ) w = 80; |
| 1726 | return w; |
| 1727 | } |
| 1728 | |
| 1729 | /* |
| 1730 | ** Append the error message to pOut. |
| 1731 | */ |
| 1732 | void diff_errmsg(Blob *pOut, const char *msg, int diffFlags){ |
| 1733 | if( diffFlags & DIFF_HTML ){ |
| 1734 | blob_appendf(pOut, "<p class=\"generalError\">%s</p>", msg); |
| 1735 | }else{ |
| 1736 | blob_append(pOut, msg, -1); |
| 1737 | } |
| 1738 | } |
| 1739 | |
| 1740 | /* |
| 1741 | ** Generate a report of the differences between files pA and pB. |
| 1742 | ** If pOut is not NULL then a unified diff is appended there. It |
| 1743 | ** is assumed that pOut has already been initialized. If pOut is |
| @@ -2032,11 +1776,11 @@ | |
| 1776 | &c.nTo, ignoreEolWs); |
| 1777 | if( c.aFrom==0 || c.aTo==0 ){ |
| 1778 | fossil_free(c.aFrom); |
| 1779 | fossil_free(c.aTo); |
| 1780 | if( pOut ){ |
| 1781 | diff_errmsg(pOut, DIFF_CANNOT_COMPUTE_BINARY, diffFlags); |
| 1782 | } |
| 1783 | return 0; |
| 1784 | } |
| 1785 | |
| 1786 | /* Compute the difference */ |
| @@ -2048,15 +1792,11 @@ | |
| 1792 | for(i=m=n=0; i<mx; i+=3){ m += a[i]; n += a[i+1]+a[i+2]; } |
| 1793 | if( n>10000 ){ |
| 1794 | fossil_free(c.aFrom); |
| 1795 | fossil_free(c.aTo); |
| 1796 | fossil_free(c.aEdit); |
| 1797 | diff_errmsg(pOut, DIFF_TOO_MANY_CHANGES, diffFlags); |
| 1798 | return 0; |
| 1799 | } |
| 1800 | } |
| 1801 | if( (diffFlags & DIFF_NOOPT)==0 ){ |
| 1802 | diff_optimize(&c); |
| @@ -2159,10 +1899,11 @@ | |
| 1899 | if( find_option("tk",0,0)!=0 ){ |
| 1900 | diff_tk("test-diff", 2); |
| 1901 | return; |
| 1902 | } |
| 1903 | find_option("i",0,0); |
| 1904 | find_option("v",0,0); |
| 1905 | zRe = find_option("regexp","e",1); |
| 1906 | if( zRe ){ |
| 1907 | const char *zErr = re_compile(&pRe, zRe, 0); |
| 1908 | if( zErr ) fossil_fatal("regex error: %s", zErr); |
| 1909 | } |
| @@ -2616,60 +2357,5 @@ | |
| 2357 | zPrefix[0] = 0; |
| 2358 | } |
| 2359 | fossil_print("%21s %4d: %.*s\n", zPrefix, i+1, n, z); |
| 2360 | } |
| 2361 | } |
| 2362 |
+307
-38
| --- src/diffcmd.c | ||
| +++ src/diffcmd.c | ||
| @@ -597,52 +597,321 @@ | ||
| 597 | 597 | return db_get(zName, zDefault); |
| 598 | 598 | } |
| 599 | 599 | |
| 600 | 600 | /* A Tcl/Tk script used to render diff output. |
| 601 | 601 | */ |
| 602 | -static const char zDiffScript[] = | |
| 602 | +static const char zDiffScript[] = | |
| 603 | 603 | @ package require Tk |
| 604 | -@ wm withdraw . | |
| 605 | -@ wm title . {Fossil Diff} | |
| 606 | -@ wm iconname . {Fossil Diff} | |
| 607 | -@ bind . <q> exit | |
| 608 | -@ set body {} | |
| 609 | -@ set mx 80 ;# Length of the longest line of text | |
| 610 | -@ set nLine 0 ;# Number of lines of text | |
| 611 | -@ text .t -width 180 -yscroll {.sb set} | |
| 612 | -@ if {$tcl_platform(platform)=="windows"} {.t config -font {courier 9}} | |
| 613 | -@ .t tag config ln -foreground gray | |
| 614 | -@ .t tag config chng -background {#d0d0ff} | |
| 615 | -@ .t tag config add -background {#c0ffc0} | |
| 616 | -@ .t tag config rm -background {#ffc0c0} | |
| 604 | +@ | |
| 605 | +@ array set CFG { | |
| 606 | +@ TITLE {Fossil Diff} | |
| 607 | +@ LN_COL_BG #dddddd | |
| 608 | +@ LN_COL_FG #444444 | |
| 609 | +@ TXT_COL_BG #ffffff | |
| 610 | +@ TXT_COL_FG #000000 | |
| 611 | +@ MKR_COL_BG #444444 | |
| 612 | +@ MKR_COL_FG #dddddd | |
| 613 | +@ CHNG_BG #d0d0ff | |
| 614 | +@ ADD_BG #c0ffc0 | |
| 615 | +@ RM_BG #ffc0c0 | |
| 616 | +@ HR_FG #888888 | |
| 617 | +@ HR_PAD_TOP 4 | |
| 618 | +@ HR_PAD_BTM 8 | |
| 619 | +@ FN_BG #444444 | |
| 620 | +@ FN_FG #ffffff | |
| 621 | +@ FN_PAD 5 | |
| 622 | +@ FONTS {{DejaVu Sans Mono} Consolas Monaco} | |
| 623 | +@ FONT_SIZE 9 | |
| 624 | +@ PADX 5 | |
| 625 | +@ WIDTH 80 | |
| 626 | +@ HEIGHT 45 | |
| 627 | +@ LB_HEIGHT 25 | |
| 628 | +@ } | |
| 629 | +@ | |
| 630 | +@ if {![namespace exists ttk]} { | |
| 631 | +@ interp alias {} ::ttk::scrollbar {} ::scrollbar | |
| 632 | +@ interp alias {} ::ttk::menubutton {} ::menubutton | |
| 633 | +@ } | |
| 634 | +@ | |
| 617 | 635 | @ proc dehtml {x} { |
| 636 | +@ set x [regsub -all {<[^>]*>} $x {}] | |
| 618 | 637 | @ return [string map {& & < < > > ' ' " \"} $x] |
| 619 | 638 | @ } |
| 620 | -@ # puts $cmd | |
| 621 | -@ set in [open $cmd r] | |
| 622 | -@ while {![eof $in]} { | |
| 623 | -@ set line [gets $in] | |
| 624 | -@ if {[regexp {^<a name="chunk.*"></a>} $line]} continue | |
| 625 | -@ if {[regexp {^===} $line]} { | |
| 626 | -@ set n [string length $line] | |
| 627 | -@ if {$n>$mx} {set mx $n} | |
| 628 | -@ } | |
| 629 | -@ incr nLine | |
| 630 | -@ while {[regexp {^(.*?)<span class="diff([a-z]+)">(.*?)</span>(.*)$} $line \ | |
| 631 | -@ all pre class mid tail]} { | |
| 632 | -@ .t insert end [dehtml $pre] {} [dehtml $mid] $class | |
| 633 | -@ set line $tail | |
| 634 | -@ } | |
| 635 | -@ .t insert end [dehtml $line]\n {} | |
| 639 | +@ | |
| 640 | +@ proc cols {} { | |
| 641 | +@ return [list .lnA .txtA .mkr .lnB .txtB] | |
| 642 | +@ } | |
| 643 | +@ | |
| 644 | +@ proc colType {c} { | |
| 645 | +@ regexp {[a-z]+} $c type | |
| 646 | +@ return $type | |
| 647 | +@ } | |
| 648 | +@ | |
| 649 | +@ proc readDiffs {cmd} { | |
| 650 | +@ set in [open $cmd r] | |
| 651 | +@ fconfigure $in -encoding utf-8 | |
| 652 | +@ set nDiffs 0 | |
| 653 | +@ array set widths {txt 0 ln 0 mkr 0} | |
| 654 | +@ while {[gets $in line] != -1} { | |
| 655 | +@ if {![regexp {^=+\s+(.*?)\s+=+$} $line all fn]} { | |
| 656 | +@ continue | |
| 657 | +@ } | |
| 658 | +@ if {[string compare -length 6 [gets $in] "<table"]} { | |
| 659 | +@ continue | |
| 660 | +@ } | |
| 661 | +@ incr nDiffs | |
| 662 | +@ set idx [expr {$nDiffs > 1 ? [.txtA index end] : "1.0"}] | |
| 663 | +@ .wfiles.lb insert end $fn | |
| 664 | +@ | |
| 665 | +@ foreach c [cols] { | |
| 666 | +@ while {[gets $in] ne "<pre>"} continue | |
| 667 | +@ | |
| 668 | +@ if {$nDiffs > 1} { | |
| 669 | +@ $c insert end \n - | |
| 670 | +@ } | |
| 671 | +@ if {[colType $c] eq "txt"} { | |
| 672 | +@ $c insert end $fn\n fn | |
| 673 | +@ } else { | |
| 674 | +@ $c insert end \n fn | |
| 675 | +@ } | |
| 676 | +@ $c insert end \n - | |
| 677 | +@ | |
| 678 | +@ set type [colType $c] | |
| 679 | +@ set str {} | |
| 680 | +@ while {[set line [gets $in]] ne "</pre>"} { | |
| 681 | +@ set len [string length [dehtml $line]] | |
| 682 | +@ if {$len > $widths($type)} { | |
| 683 | +@ set widths($type) $len | |
| 684 | +@ } | |
| 685 | +@ append str $line\n | |
| 686 | +@ } | |
| 687 | +@ | |
| 688 | +@ set re {<span class="diff([a-z]+)">([^<]*)</span>} | |
| 689 | +@ # Use \r as separator since it can't appear in the diff output (it gets | |
| 690 | +@ # converted to a space). | |
| 691 | +@ set str [regsub -all $re $str "\r\\1\r\\2\r"] | |
| 692 | +@ foreach {pre class mid} [split $str \r] { | |
| 693 | +@ if {$class ne ""} { | |
| 694 | +@ $c insert end [dehtml $pre] - [dehtml $mid] [list $class -] | |
| 695 | +@ } else { | |
| 696 | +@ $c insert end [dehtml $pre] - | |
| 697 | +@ } | |
| 698 | +@ } | |
| 699 | +@ } | |
| 700 | +@ } | |
| 701 | +@ close $in | |
| 702 | +@ | |
| 703 | +@ foreach c [cols] { | |
| 704 | +@ set type [colType $c] | |
| 705 | +@ if {$type ne "txt"} { | |
| 706 | +@ $c config -width $widths($type) | |
| 707 | +@ } | |
| 708 | +@ $c config -state disabled | |
| 709 | +@ } | |
| 710 | +@ if {$nDiffs <= [.wfiles.lb cget -height]} { | |
| 711 | +@ .wfiles.lb config -height $nDiffs | |
| 712 | +@ grid remove .wfiles.sb | |
| 713 | +@ } | |
| 714 | +@ | |
| 715 | +@ return $nDiffs | |
| 716 | +@ } | |
| 717 | +@ | |
| 718 | +@ proc viewDiff {idx} { | |
| 719 | +@ .txtA yview $idx | |
| 720 | +@ .txtA xview moveto 0 | |
| 721 | +@ } | |
| 722 | +@ | |
| 723 | +@ proc cycleDiffs {{reverse 0}} { | |
| 724 | +@ if {$reverse} { | |
| 725 | +@ set range [.txtA tag prevrange fn @0,0 1.0] | |
| 726 | +@ if {$range eq ""} { | |
| 727 | +@ viewDiff {fn.last -1c} | |
| 728 | +@ } else { | |
| 729 | +@ viewDiff [lindex $range 0] | |
| 730 | +@ } | |
| 731 | +@ } else { | |
| 732 | +@ set range [.txtA tag nextrange fn {@0,0 +1c} end] | |
| 733 | +@ if {$range eq "" || [lindex [.txtA yview] 1] == 1} { | |
| 734 | +@ viewDiff fn.first | |
| 735 | +@ } else { | |
| 736 | +@ viewDiff [lindex $range 0] | |
| 737 | +@ } | |
| 738 | +@ } | |
| 739 | +@ } | |
| 740 | +@ | |
| 741 | +@ proc xvis {col} { | |
| 742 | +@ set view [$col xview] | |
| 743 | +@ return [expr {[lindex $view 1]-[lindex $view 0]}] | |
| 744 | +@ } | |
| 745 | +@ | |
| 746 | +@ proc scroll-x {args} { | |
| 747 | +@ set c .txt[expr {[xvis .txtA] < [xvis .txtB] ? "A" : "B"}] | |
| 748 | +@ eval $c xview $args | |
| 749 | +@ } | |
| 750 | +@ | |
| 751 | +@ interp alias {} scroll-y {} .txtA yview | |
| 752 | +@ | |
| 753 | +@ proc noop {args} {} | |
| 754 | +@ | |
| 755 | +@ proc enableSync {axis} { | |
| 756 | +@ update idletasks | |
| 757 | +@ interp alias {} sync-$axis {} | |
| 758 | +@ rename _sync-$axis sync-$axis | |
| 759 | +@ } | |
| 760 | +@ | |
| 761 | +@ proc disableSync {axis} { | |
| 762 | +@ rename sync-$axis _sync-$axis | |
| 763 | +@ interp alias {} sync-$axis {} noop | |
| 764 | +@ } | |
| 765 | +@ | |
| 766 | +@ proc sync-x {col first last} { | |
| 767 | +@ disableSync x | |
| 768 | +@ $col xview moveto [expr {$first*[xvis $col]/($last-$first)}] | |
| 769 | +@ foreach side {A B} { | |
| 770 | +@ set sb .sbx$side | |
| 771 | +@ set xview [.txt$side xview] | |
| 772 | +@ if {[lindex $xview 0] > 0 || [lindex $xview 1] < 1} { | |
| 773 | +@ grid $sb | |
| 774 | +@ eval $sb set $xview | |
| 775 | +@ } else { | |
| 776 | +@ grid remove $sb | |
| 777 | +@ } | |
| 778 | +@ } | |
| 779 | +@ enableSync x | |
| 780 | +@ } | |
| 781 | +@ | |
| 782 | +@ proc sync-y {first last} { | |
| 783 | +@ disableSync y | |
| 784 | +@ foreach c [cols] { | |
| 785 | +@ $c yview moveto $first | |
| 786 | +@ } | |
| 787 | +@ if {$first > 0 || $last < 1} { | |
| 788 | +@ grid .sby | |
| 789 | +@ .sby set $first $last | |
| 790 | +@ } else { | |
| 791 | +@ grid remove .sby | |
| 792 | +@ } | |
| 793 | +@ enableSync y | |
| 794 | +@ } | |
| 795 | +@ | |
| 796 | +@ wm withdraw . | |
| 797 | +@ wm title . $CFG(TITLE) | |
| 798 | +@ wm iconname . $CFG(TITLE) | |
| 799 | +@ bind . <q> exit | |
| 800 | +@ bind . <Tab> {cycleDiffs; break} | |
| 801 | +@ bind . <<PrevWindow>> {cycleDiffs 1; break} | |
| 802 | +@ bind . <Return> { | |
| 803 | +@ event generate .files <1> | |
| 804 | +@ event generate .files <ButtonRelease-1> | |
| 805 | +@ break | |
| 806 | +@ } | |
| 807 | +@ foreach {key axis args} { | |
| 808 | +@ Up y {scroll -5 units} | |
| 809 | +@ Down y {scroll 5 units} | |
| 810 | +@ Left x {scroll -5 units} | |
| 811 | +@ Right x {scroll 5 units} | |
| 812 | +@ Prior y {scroll -1 page} | |
| 813 | +@ Next y {scroll 1 page} | |
| 814 | +@ Home y {moveto 0} | |
| 815 | +@ End y {moveto 1} | |
| 816 | +@ } { | |
| 817 | +@ bind . <$key> "scroll-$axis $args; break" | |
| 818 | +@ bind . <Shift-$key> continue | |
| 819 | +@ } | |
| 820 | +@ | |
| 821 | +@ ::ttk::menubutton .files -text "Files" | |
| 822 | +@ toplevel .wfiles | |
| 823 | +@ wm withdraw .wfiles | |
| 824 | +@ update idletasks | |
| 825 | +@ wm transient .wfiles . | |
| 826 | +@ wm overrideredirect .wfiles 1 | |
| 827 | +@ listbox .wfiles.lb -width 0 -height $CFG(LB_HEIGHT) -activestyle none \ | |
| 828 | +@ -yscroll {.wfiles.sb set} | |
| 829 | +@ ::ttk::scrollbar .wfiles.sb -command {.wfiles.lb yview} | |
| 830 | +@ grid .wfiles.lb .wfiles.sb -sticky ns | |
| 831 | +@ bind .files <1> { | |
| 832 | +@ set x [winfo rootx %W] | |
| 833 | +@ set y [expr {[winfo rooty %W]+[winfo height %W]}] | |
| 834 | +@ wm geometry .wfiles +$x+$y | |
| 835 | +@ wm deiconify .wfiles | |
| 836 | +@ focus .wfiles.lb | |
| 837 | +@ } | |
| 838 | +@ bind .wfiles <FocusOut> {wm withdraw .wfiles} | |
| 839 | +@ bind .wfiles <Escape> {focus .} | |
| 840 | +@ foreach evt {1 Return} { | |
| 841 | +@ bind .wfiles.lb <$evt> { | |
| 842 | +@ catch { | |
| 843 | +@ set idx [lindex [.txtA tag ranges fn] [expr {[%W curselection]*2}]] | |
| 844 | +@ viewDiff $idx | |
| 845 | +@ } | |
| 846 | +@ focus . | |
| 847 | +@ break | |
| 848 | +@ } | |
| 849 | +@ } | |
| 850 | +@ bind .wfiles.lb <Motion> { | |
| 851 | +@ %W selection clear 0 end | |
| 852 | +@ %W selection set @%x,%y | |
| 853 | +@ } | |
| 854 | +@ | |
| 855 | +@ foreach {side syncCol} {A .txtB B .txtA} { | |
| 856 | +@ set ln .ln$side | |
| 857 | +@ text $ln | |
| 858 | +@ $ln tag config - -justify right | |
| 859 | +@ | |
| 860 | +@ set txt .txt$side | |
| 861 | +@ text $txt -width $CFG(WIDTH) -height $CFG(HEIGHT) -wrap none \ | |
| 862 | +@ -xscroll "sync-x $syncCol" | |
| 863 | +@ catch {$txt config -tabstyle wordprocessor} ;# Required for Tk>=8.5 | |
| 864 | +@ foreach tag {add rm chng} { | |
| 865 | +@ $txt tag config $tag -background $CFG([string toupper $tag]_BG) | |
| 866 | +@ $txt tag lower $tag | |
| 867 | +@ } | |
| 868 | +@ $txt tag config fn -background $CFG(FN_BG) -foreground $CFG(FN_FG) \ | |
| 869 | +@ -justify center | |
| 870 | +@ } | |
| 871 | +@ text .mkr | |
| 872 | +@ | |
| 873 | +@ font create mono -family courier -size $CFG(FONT_SIZE) | |
| 874 | +@ foreach font $CFG(FONTS) { | |
| 875 | +@ if {[lsearch -exact [font families] $font] != -1} { | |
| 876 | +@ font config mono -family $font | |
| 877 | +@ break | |
| 878 | +@ } | |
| 879 | +@ } | |
| 880 | +@ foreach c [cols] { | |
| 881 | +@ set keyPrefix [string toupper [colType $c]]_COL_ | |
| 882 | +@ $c config -bg $CFG(${keyPrefix}BG) -fg $CFG(${keyPrefix}FG) -borderwidth 0 \ | |
| 883 | +@ -font mono -padx $CFG(PADX) -yscroll sync-y | |
| 884 | +@ $c tag config hr -spacing1 $CFG(HR_PAD_TOP) -spacing3 $CFG(HR_PAD_BTM) \ | |
| 885 | +@ -foreground $CFG(HR_FG) | |
| 886 | +@ $c tag config fn -spacing1 $CFG(FN_PAD) -spacing3 $CFG(FN_PAD) | |
| 887 | +@ bindtags $c ". $c Text all" | |
| 888 | +@ bind $c <1> {focus %W} | |
| 889 | +@ } | |
| 890 | +@ | |
| 891 | +@ ::ttk::scrollbar .sby -command {.txtA yview} -orient vertical | |
| 892 | +@ ::ttk::scrollbar .sbxA -command {.txtA xview} -orient horizontal | |
| 893 | +@ ::ttk::scrollbar .sbxB -command {.txtB xview} -orient horizontal | |
| 894 | +@ frame .spacer | |
| 895 | +@ | |
| 896 | +@ if {[readDiffs $cmd] == 0} { | |
| 897 | +@ tk_messageBox -type ok -title $CFG(TITLE) -message "No changes" | |
| 898 | +@ exit | |
| 636 | 899 | @ } |
| 637 | -@ close $in | |
| 638 | -@ if {$mx>250} {set mx 250} ;# Limit window width to 200 characters | |
| 639 | -@ if {$nLine>55} {set nLine 55} ;# Limit window height to 55 lines | |
| 640 | -@ .t config -height $nLine -width $mx | |
| 641 | -@ pack .t -side left -fill both -expand 1 | |
| 642 | -@ scrollbar .sb -command {.t yview} -orient vertical | |
| 643 | -@ pack .sb -side left -fill y | |
| 900 | +@ update idletasks | |
| 901 | +@ | |
| 902 | +@ grid rowconfigure . 1 -weight 1 | |
| 903 | +@ grid columnconfigure . 1 -weight 1 | |
| 904 | +@ grid columnconfigure . 4 -weight 1 | |
| 905 | +@ grid .files -row 0 -columnspan 6 | |
| 906 | +@ eval grid [cols] -row 1 -sticky nsew | |
| 907 | +@ grid .sby -row 1 -column 5 -sticky ns | |
| 908 | +@ grid .sbxA -row 2 -columnspan 2 -sticky ew | |
| 909 | +@ grid .spacer -row 2 -column 2 | |
| 910 | +@ grid .sbxB -row 2 -column 3 -columnspan 2 -sticky ew | |
| 911 | +@ | |
| 912 | +@ .spacer config -height [winfo height .sbxA] | |
| 644 | 913 | @ wm deiconify . |
| 645 | 914 | ; |
| 646 | 915 | |
| 647 | 916 | /* |
| 648 | 917 | ** Show diff output in a Tcl/Tk window, in response to the --tk option |
| @@ -657,11 +926,11 @@ | ||
| 657 | 926 | int i; |
| 658 | 927 | Blob script; |
| 659 | 928 | char *zTempFile; |
| 660 | 929 | char *zCmd; |
| 661 | 930 | blob_zero(&script); |
| 662 | - blob_appendf(&script, "set cmd {| \"%/\" %s --html -y -i", | |
| 931 | + blob_appendf(&script, "set cmd {| \"%/\" %s --html -y -i -v", | |
| 663 | 932 | g.nameOfExe, zSubCmd); |
| 664 | 933 | for(i=firstArg; i<g.argc; i++){ |
| 665 | 934 | const char *z = g.argv[i]; |
| 666 | 935 | if( z[0]=='-' ){ |
| 667 | 936 | if( strglob("*-html",z) ) continue; |
| 668 | 937 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -597,52 +597,321 @@ | |
| 597 | return db_get(zName, zDefault); |
| 598 | } |
| 599 | |
| 600 | /* A Tcl/Tk script used to render diff output. |
| 601 | */ |
| 602 | static const char zDiffScript[] = |
| 603 | @ package require Tk |
| 604 | @ wm withdraw . |
| 605 | @ wm title . {Fossil Diff} |
| 606 | @ wm iconname . {Fossil Diff} |
| 607 | @ bind . <q> exit |
| 608 | @ set body {} |
| 609 | @ set mx 80 ;# Length of the longest line of text |
| 610 | @ set nLine 0 ;# Number of lines of text |
| 611 | @ text .t -width 180 -yscroll {.sb set} |
| 612 | @ if {$tcl_platform(platform)=="windows"} {.t config -font {courier 9}} |
| 613 | @ .t tag config ln -foreground gray |
| 614 | @ .t tag config chng -background {#d0d0ff} |
| 615 | @ .t tag config add -background {#c0ffc0} |
| 616 | @ .t tag config rm -background {#ffc0c0} |
| 617 | @ proc dehtml {x} { |
| 618 | @ return [string map {& & < < > > ' ' " \"} $x] |
| 619 | @ } |
| 620 | @ # puts $cmd |
| 621 | @ set in [open $cmd r] |
| 622 | @ while {![eof $in]} { |
| 623 | @ set line [gets $in] |
| 624 | @ if {[regexp {^<a name="chunk.*"></a>} $line]} continue |
| 625 | @ if {[regexp {^===} $line]} { |
| 626 | @ set n [string length $line] |
| 627 | @ if {$n>$mx} {set mx $n} |
| 628 | @ } |
| 629 | @ incr nLine |
| 630 | @ while {[regexp {^(.*?)<span class="diff([a-z]+)">(.*?)</span>(.*)$} $line \ |
| 631 | @ all pre class mid tail]} { |
| 632 | @ .t insert end [dehtml $pre] {} [dehtml $mid] $class |
| 633 | @ set line $tail |
| 634 | @ } |
| 635 | @ .t insert end [dehtml $line]\n {} |
| 636 | @ } |
| 637 | @ close $in |
| 638 | @ if {$mx>250} {set mx 250} ;# Limit window width to 200 characters |
| 639 | @ if {$nLine>55} {set nLine 55} ;# Limit window height to 55 lines |
| 640 | @ .t config -height $nLine -width $mx |
| 641 | @ pack .t -side left -fill both -expand 1 |
| 642 | @ scrollbar .sb -command {.t yview} -orient vertical |
| 643 | @ pack .sb -side left -fill y |
| 644 | @ wm deiconify . |
| 645 | ; |
| 646 | |
| 647 | /* |
| 648 | ** Show diff output in a Tcl/Tk window, in response to the --tk option |
| @@ -657,11 +926,11 @@ | |
| 657 | int i; |
| 658 | Blob script; |
| 659 | char *zTempFile; |
| 660 | char *zCmd; |
| 661 | blob_zero(&script); |
| 662 | blob_appendf(&script, "set cmd {| \"%/\" %s --html -y -i", |
| 663 | g.nameOfExe, zSubCmd); |
| 664 | for(i=firstArg; i<g.argc; i++){ |
| 665 | const char *z = g.argv[i]; |
| 666 | if( z[0]=='-' ){ |
| 667 | if( strglob("*-html",z) ) continue; |
| 668 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -597,52 +597,321 @@ | |
| 597 | return db_get(zName, zDefault); |
| 598 | } |
| 599 | |
| 600 | /* A Tcl/Tk script used to render diff output. |
| 601 | */ |
| 602 | static const char zDiffScript[] = |
| 603 | @ package require Tk |
| 604 | @ |
| 605 | @ array set CFG { |
| 606 | @ TITLE {Fossil Diff} |
| 607 | @ LN_COL_BG #dddddd |
| 608 | @ LN_COL_FG #444444 |
| 609 | @ TXT_COL_BG #ffffff |
| 610 | @ TXT_COL_FG #000000 |
| 611 | @ MKR_COL_BG #444444 |
| 612 | @ MKR_COL_FG #dddddd |
| 613 | @ CHNG_BG #d0d0ff |
| 614 | @ ADD_BG #c0ffc0 |
| 615 | @ RM_BG #ffc0c0 |
| 616 | @ HR_FG #888888 |
| 617 | @ HR_PAD_TOP 4 |
| 618 | @ HR_PAD_BTM 8 |
| 619 | @ FN_BG #444444 |
| 620 | @ FN_FG #ffffff |
| 621 | @ FN_PAD 5 |
| 622 | @ FONTS {{DejaVu Sans Mono} Consolas Monaco} |
| 623 | @ FONT_SIZE 9 |
| 624 | @ PADX 5 |
| 625 | @ WIDTH 80 |
| 626 | @ HEIGHT 45 |
| 627 | @ LB_HEIGHT 25 |
| 628 | @ } |
| 629 | @ |
| 630 | @ if {![namespace exists ttk]} { |
| 631 | @ interp alias {} ::ttk::scrollbar {} ::scrollbar |
| 632 | @ interp alias {} ::ttk::menubutton {} ::menubutton |
| 633 | @ } |
| 634 | @ |
| 635 | @ proc dehtml {x} { |
| 636 | @ set x [regsub -all {<[^>]*>} $x {}] |
| 637 | @ return [string map {& & < < > > ' ' " \"} $x] |
| 638 | @ } |
| 639 | @ |
| 640 | @ proc cols {} { |
| 641 | @ return [list .lnA .txtA .mkr .lnB .txtB] |
| 642 | @ } |
| 643 | @ |
| 644 | @ proc colType {c} { |
| 645 | @ regexp {[a-z]+} $c type |
| 646 | @ return $type |
| 647 | @ } |
| 648 | @ |
| 649 | @ proc readDiffs {cmd} { |
| 650 | @ set in [open $cmd r] |
| 651 | @ fconfigure $in -encoding utf-8 |
| 652 | @ set nDiffs 0 |
| 653 | @ array set widths {txt 0 ln 0 mkr 0} |
| 654 | @ while {[gets $in line] != -1} { |
| 655 | @ if {![regexp {^=+\s+(.*?)\s+=+$} $line all fn]} { |
| 656 | @ continue |
| 657 | @ } |
| 658 | @ if {[string compare -length 6 [gets $in] "<table"]} { |
| 659 | @ continue |
| 660 | @ } |
| 661 | @ incr nDiffs |
| 662 | @ set idx [expr {$nDiffs > 1 ? [.txtA index end] : "1.0"}] |
| 663 | @ .wfiles.lb insert end $fn |
| 664 | @ |
| 665 | @ foreach c [cols] { |
| 666 | @ while {[gets $in] ne "<pre>"} continue |
| 667 | @ |
| 668 | @ if {$nDiffs > 1} { |
| 669 | @ $c insert end \n - |
| 670 | @ } |
| 671 | @ if {[colType $c] eq "txt"} { |
| 672 | @ $c insert end $fn\n fn |
| 673 | @ } else { |
| 674 | @ $c insert end \n fn |
| 675 | @ } |
| 676 | @ $c insert end \n - |
| 677 | @ |
| 678 | @ set type [colType $c] |
| 679 | @ set str {} |
| 680 | @ while {[set line [gets $in]] ne "</pre>"} { |
| 681 | @ set len [string length [dehtml $line]] |
| 682 | @ if {$len > $widths($type)} { |
| 683 | @ set widths($type) $len |
| 684 | @ } |
| 685 | @ append str $line\n |
| 686 | @ } |
| 687 | @ |
| 688 | @ set re {<span class="diff([a-z]+)">([^<]*)</span>} |
| 689 | @ # Use \r as separator since it can't appear in the diff output (it gets |
| 690 | @ # converted to a space). |
| 691 | @ set str [regsub -all $re $str "\r\\1\r\\2\r"] |
| 692 | @ foreach {pre class mid} [split $str \r] { |
| 693 | @ if {$class ne ""} { |
| 694 | @ $c insert end [dehtml $pre] - [dehtml $mid] [list $class -] |
| 695 | @ } else { |
| 696 | @ $c insert end [dehtml $pre] - |
| 697 | @ } |
| 698 | @ } |
| 699 | @ } |
| 700 | @ } |
| 701 | @ close $in |
| 702 | @ |
| 703 | @ foreach c [cols] { |
| 704 | @ set type [colType $c] |
| 705 | @ if {$type ne "txt"} { |
| 706 | @ $c config -width $widths($type) |
| 707 | @ } |
| 708 | @ $c config -state disabled |
| 709 | @ } |
| 710 | @ if {$nDiffs <= [.wfiles.lb cget -height]} { |
| 711 | @ .wfiles.lb config -height $nDiffs |
| 712 | @ grid remove .wfiles.sb |
| 713 | @ } |
| 714 | @ |
| 715 | @ return $nDiffs |
| 716 | @ } |
| 717 | @ |
| 718 | @ proc viewDiff {idx} { |
| 719 | @ .txtA yview $idx |
| 720 | @ .txtA xview moveto 0 |
| 721 | @ } |
| 722 | @ |
| 723 | @ proc cycleDiffs {{reverse 0}} { |
| 724 | @ if {$reverse} { |
| 725 | @ set range [.txtA tag prevrange fn @0,0 1.0] |
| 726 | @ if {$range eq ""} { |
| 727 | @ viewDiff {fn.last -1c} |
| 728 | @ } else { |
| 729 | @ viewDiff [lindex $range 0] |
| 730 | @ } |
| 731 | @ } else { |
| 732 | @ set range [.txtA tag nextrange fn {@0,0 +1c} end] |
| 733 | @ if {$range eq "" || [lindex [.txtA yview] 1] == 1} { |
| 734 | @ viewDiff fn.first |
| 735 | @ } else { |
| 736 | @ viewDiff [lindex $range 0] |
| 737 | @ } |
| 738 | @ } |
| 739 | @ } |
| 740 | @ |
| 741 | @ proc xvis {col} { |
| 742 | @ set view [$col xview] |
| 743 | @ return [expr {[lindex $view 1]-[lindex $view 0]}] |
| 744 | @ } |
| 745 | @ |
| 746 | @ proc scroll-x {args} { |
| 747 | @ set c .txt[expr {[xvis .txtA] < [xvis .txtB] ? "A" : "B"}] |
| 748 | @ eval $c xview $args |
| 749 | @ } |
| 750 | @ |
| 751 | @ interp alias {} scroll-y {} .txtA yview |
| 752 | @ |
| 753 | @ proc noop {args} {} |
| 754 | @ |
| 755 | @ proc enableSync {axis} { |
| 756 | @ update idletasks |
| 757 | @ interp alias {} sync-$axis {} |
| 758 | @ rename _sync-$axis sync-$axis |
| 759 | @ } |
| 760 | @ |
| 761 | @ proc disableSync {axis} { |
| 762 | @ rename sync-$axis _sync-$axis |
| 763 | @ interp alias {} sync-$axis {} noop |
| 764 | @ } |
| 765 | @ |
| 766 | @ proc sync-x {col first last} { |
| 767 | @ disableSync x |
| 768 | @ $col xview moveto [expr {$first*[xvis $col]/($last-$first)}] |
| 769 | @ foreach side {A B} { |
| 770 | @ set sb .sbx$side |
| 771 | @ set xview [.txt$side xview] |
| 772 | @ if {[lindex $xview 0] > 0 || [lindex $xview 1] < 1} { |
| 773 | @ grid $sb |
| 774 | @ eval $sb set $xview |
| 775 | @ } else { |
| 776 | @ grid remove $sb |
| 777 | @ } |
| 778 | @ } |
| 779 | @ enableSync x |
| 780 | @ } |
| 781 | @ |
| 782 | @ proc sync-y {first last} { |
| 783 | @ disableSync y |
| 784 | @ foreach c [cols] { |
| 785 | @ $c yview moveto $first |
| 786 | @ } |
| 787 | @ if {$first > 0 || $last < 1} { |
| 788 | @ grid .sby |
| 789 | @ .sby set $first $last |
| 790 | @ } else { |
| 791 | @ grid remove .sby |
| 792 | @ } |
| 793 | @ enableSync y |
| 794 | @ } |
| 795 | @ |
| 796 | @ wm withdraw . |
| 797 | @ wm title . $CFG(TITLE) |
| 798 | @ wm iconname . $CFG(TITLE) |
| 799 | @ bind . <q> exit |
| 800 | @ bind . <Tab> {cycleDiffs; break} |
| 801 | @ bind . <<PrevWindow>> {cycleDiffs 1; break} |
| 802 | @ bind . <Return> { |
| 803 | @ event generate .files <1> |
| 804 | @ event generate .files <ButtonRelease-1> |
| 805 | @ break |
| 806 | @ } |
| 807 | @ foreach {key axis args} { |
| 808 | @ Up y {scroll -5 units} |
| 809 | @ Down y {scroll 5 units} |
| 810 | @ Left x {scroll -5 units} |
| 811 | @ Right x {scroll 5 units} |
| 812 | @ Prior y {scroll -1 page} |
| 813 | @ Next y {scroll 1 page} |
| 814 | @ Home y {moveto 0} |
| 815 | @ End y {moveto 1} |
| 816 | @ } { |
| 817 | @ bind . <$key> "scroll-$axis $args; break" |
| 818 | @ bind . <Shift-$key> continue |
| 819 | @ } |
| 820 | @ |
| 821 | @ ::ttk::menubutton .files -text "Files" |
| 822 | @ toplevel .wfiles |
| 823 | @ wm withdraw .wfiles |
| 824 | @ update idletasks |
| 825 | @ wm transient .wfiles . |
| 826 | @ wm overrideredirect .wfiles 1 |
| 827 | @ listbox .wfiles.lb -width 0 -height $CFG(LB_HEIGHT) -activestyle none \ |
| 828 | @ -yscroll {.wfiles.sb set} |
| 829 | @ ::ttk::scrollbar .wfiles.sb -command {.wfiles.lb yview} |
| 830 | @ grid .wfiles.lb .wfiles.sb -sticky ns |
| 831 | @ bind .files <1> { |
| 832 | @ set x [winfo rootx %W] |
| 833 | @ set y [expr {[winfo rooty %W]+[winfo height %W]}] |
| 834 | @ wm geometry .wfiles +$x+$y |
| 835 | @ wm deiconify .wfiles |
| 836 | @ focus .wfiles.lb |
| 837 | @ } |
| 838 | @ bind .wfiles <FocusOut> {wm withdraw .wfiles} |
| 839 | @ bind .wfiles <Escape> {focus .} |
| 840 | @ foreach evt {1 Return} { |
| 841 | @ bind .wfiles.lb <$evt> { |
| 842 | @ catch { |
| 843 | @ set idx [lindex [.txtA tag ranges fn] [expr {[%W curselection]*2}]] |
| 844 | @ viewDiff $idx |
| 845 | @ } |
| 846 | @ focus . |
| 847 | @ break |
| 848 | @ } |
| 849 | @ } |
| 850 | @ bind .wfiles.lb <Motion> { |
| 851 | @ %W selection clear 0 end |
| 852 | @ %W selection set @%x,%y |
| 853 | @ } |
| 854 | @ |
| 855 | @ foreach {side syncCol} {A .txtB B .txtA} { |
| 856 | @ set ln .ln$side |
| 857 | @ text $ln |
| 858 | @ $ln tag config - -justify right |
| 859 | @ |
| 860 | @ set txt .txt$side |
| 861 | @ text $txt -width $CFG(WIDTH) -height $CFG(HEIGHT) -wrap none \ |
| 862 | @ -xscroll "sync-x $syncCol" |
| 863 | @ catch {$txt config -tabstyle wordprocessor} ;# Required for Tk>=8.5 |
| 864 | @ foreach tag {add rm chng} { |
| 865 | @ $txt tag config $tag -background $CFG([string toupper $tag]_BG) |
| 866 | @ $txt tag lower $tag |
| 867 | @ } |
| 868 | @ $txt tag config fn -background $CFG(FN_BG) -foreground $CFG(FN_FG) \ |
| 869 | @ -justify center |
| 870 | @ } |
| 871 | @ text .mkr |
| 872 | @ |
| 873 | @ font create mono -family courier -size $CFG(FONT_SIZE) |
| 874 | @ foreach font $CFG(FONTS) { |
| 875 | @ if {[lsearch -exact [font families] $font] != -1} { |
| 876 | @ font config mono -family $font |
| 877 | @ break |
| 878 | @ } |
| 879 | @ } |
| 880 | @ foreach c [cols] { |
| 881 | @ set keyPrefix [string toupper [colType $c]]_COL_ |
| 882 | @ $c config -bg $CFG(${keyPrefix}BG) -fg $CFG(${keyPrefix}FG) -borderwidth 0 \ |
| 883 | @ -font mono -padx $CFG(PADX) -yscroll sync-y |
| 884 | @ $c tag config hr -spacing1 $CFG(HR_PAD_TOP) -spacing3 $CFG(HR_PAD_BTM) \ |
| 885 | @ -foreground $CFG(HR_FG) |
| 886 | @ $c tag config fn -spacing1 $CFG(FN_PAD) -spacing3 $CFG(FN_PAD) |
| 887 | @ bindtags $c ". $c Text all" |
| 888 | @ bind $c <1> {focus %W} |
| 889 | @ } |
| 890 | @ |
| 891 | @ ::ttk::scrollbar .sby -command {.txtA yview} -orient vertical |
| 892 | @ ::ttk::scrollbar .sbxA -command {.txtA xview} -orient horizontal |
| 893 | @ ::ttk::scrollbar .sbxB -command {.txtB xview} -orient horizontal |
| 894 | @ frame .spacer |
| 895 | @ |
| 896 | @ if {[readDiffs $cmd] == 0} { |
| 897 | @ tk_messageBox -type ok -title $CFG(TITLE) -message "No changes" |
| 898 | @ exit |
| 899 | @ } |
| 900 | @ update idletasks |
| 901 | @ |
| 902 | @ grid rowconfigure . 1 -weight 1 |
| 903 | @ grid columnconfigure . 1 -weight 1 |
| 904 | @ grid columnconfigure . 4 -weight 1 |
| 905 | @ grid .files -row 0 -columnspan 6 |
| 906 | @ eval grid [cols] -row 1 -sticky nsew |
| 907 | @ grid .sby -row 1 -column 5 -sticky ns |
| 908 | @ grid .sbxA -row 2 -columnspan 2 -sticky ew |
| 909 | @ grid .spacer -row 2 -column 2 |
| 910 | @ grid .sbxB -row 2 -column 3 -columnspan 2 -sticky ew |
| 911 | @ |
| 912 | @ .spacer config -height [winfo height .sbxA] |
| 913 | @ wm deiconify . |
| 914 | ; |
| 915 | |
| 916 | /* |
| 917 | ** Show diff output in a Tcl/Tk window, in response to the --tk option |
| @@ -657,11 +926,11 @@ | |
| 926 | int i; |
| 927 | Blob script; |
| 928 | char *zTempFile; |
| 929 | char *zCmd; |
| 930 | blob_zero(&script); |
| 931 | blob_appendf(&script, "set cmd {| \"%/\" %s --html -y -i -v", |
| 932 | g.nameOfExe, zSubCmd); |
| 933 | for(i=firstArg; i<g.argc; i++){ |
| 934 | const char *z = g.argv[i]; |
| 935 | if( z[0]=='-' ){ |
| 936 | if( strglob("*-html",z) ) continue; |
| 937 |
+5
-5
| --- src/event.c | ||
| +++ src/event.c | ||
| @@ -399,32 +399,32 @@ | ||
| 399 | 399 | @ <form method="post" action="%s(g.zTop)/eventedit"><div> |
| 400 | 400 | login_insert_csrf_secret(); |
| 401 | 401 | @ <input type="hidden" name="name" value="%h(zEventId)" /> |
| 402 | 402 | @ <table border="0" cellspacing="10"> |
| 403 | 403 | |
| 404 | - @ <tr><td align="right" valign="top"><b>Event Time:</b></td> | |
| 404 | + @ <tr><th align="right" valign="top">Event Time:</th> | |
| 405 | 405 | @ <td valign="top"> |
| 406 | 406 | @ <input type="text" name="t" size="25" value="%h(zETime)" /> |
| 407 | 407 | @ </td></tr> |
| 408 | 408 | |
| 409 | - @ <tr><td align="right" valign="top"><b>Timeline Comment:</b></td> | |
| 409 | + @ <tr><th align="right" valign="top">Timeline Comment:</th> | |
| 410 | 410 | @ <td valign="top"> |
| 411 | 411 | @ <textarea name="c" class="eventedit" cols="80" |
| 412 | 412 | @ rows="3" wrap="virtual">%h(zComment)</textarea> |
| 413 | 413 | @ </td></tr> |
| 414 | 414 | |
| 415 | - @ <tr><td align="right" valign="top"><b>Background Color:</b></td> | |
| 415 | + @ <tr><th align="right" valign="top">Background Color:</th> | |
| 416 | 416 | @ <td valign="top"> |
| 417 | 417 | render_color_chooser(0, zClr, 0, "clr", "cclr"); |
| 418 | 418 | @ </td></tr> |
| 419 | 419 | |
| 420 | - @ <tr><td align="right" valign="top"><b>Tags:</b></td> | |
| 420 | + @ <tr><th align="right" valign="top">Tags:</th> | |
| 421 | 421 | @ <td valign="top"> |
| 422 | 422 | @ <input type="text" name="g" size="40" value="%h(zTags)" /> |
| 423 | 423 | @ </td></tr> |
| 424 | 424 | |
| 425 | - @ <tr><td align="right" valign="top"><b>Page Content:</b></td> | |
| 425 | + @ <tr><th align="right" valign="top">Page Content:</th> | |
| 426 | 426 | @ <td valign="top"> |
| 427 | 427 | @ <textarea name="w" class="eventedit" cols="80" |
| 428 | 428 | @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea> |
| 429 | 429 | @ </td></tr> |
| 430 | 430 | |
| 431 | 431 |
| --- src/event.c | |
| +++ src/event.c | |
| @@ -399,32 +399,32 @@ | |
| 399 | @ <form method="post" action="%s(g.zTop)/eventedit"><div> |
| 400 | login_insert_csrf_secret(); |
| 401 | @ <input type="hidden" name="name" value="%h(zEventId)" /> |
| 402 | @ <table border="0" cellspacing="10"> |
| 403 | |
| 404 | @ <tr><td align="right" valign="top"><b>Event Time:</b></td> |
| 405 | @ <td valign="top"> |
| 406 | @ <input type="text" name="t" size="25" value="%h(zETime)" /> |
| 407 | @ </td></tr> |
| 408 | |
| 409 | @ <tr><td align="right" valign="top"><b>Timeline Comment:</b></td> |
| 410 | @ <td valign="top"> |
| 411 | @ <textarea name="c" class="eventedit" cols="80" |
| 412 | @ rows="3" wrap="virtual">%h(zComment)</textarea> |
| 413 | @ </td></tr> |
| 414 | |
| 415 | @ <tr><td align="right" valign="top"><b>Background Color:</b></td> |
| 416 | @ <td valign="top"> |
| 417 | render_color_chooser(0, zClr, 0, "clr", "cclr"); |
| 418 | @ </td></tr> |
| 419 | |
| 420 | @ <tr><td align="right" valign="top"><b>Tags:</b></td> |
| 421 | @ <td valign="top"> |
| 422 | @ <input type="text" name="g" size="40" value="%h(zTags)" /> |
| 423 | @ </td></tr> |
| 424 | |
| 425 | @ <tr><td align="right" valign="top"><b>Page Content:</b></td> |
| 426 | @ <td valign="top"> |
| 427 | @ <textarea name="w" class="eventedit" cols="80" |
| 428 | @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea> |
| 429 | @ </td></tr> |
| 430 | |
| 431 |
| --- src/event.c | |
| +++ src/event.c | |
| @@ -399,32 +399,32 @@ | |
| 399 | @ <form method="post" action="%s(g.zTop)/eventedit"><div> |
| 400 | login_insert_csrf_secret(); |
| 401 | @ <input type="hidden" name="name" value="%h(zEventId)" /> |
| 402 | @ <table border="0" cellspacing="10"> |
| 403 | |
| 404 | @ <tr><th align="right" valign="top">Event Time:</th> |
| 405 | @ <td valign="top"> |
| 406 | @ <input type="text" name="t" size="25" value="%h(zETime)" /> |
| 407 | @ </td></tr> |
| 408 | |
| 409 | @ <tr><th align="right" valign="top">Timeline Comment:</th> |
| 410 | @ <td valign="top"> |
| 411 | @ <textarea name="c" class="eventedit" cols="80" |
| 412 | @ rows="3" wrap="virtual">%h(zComment)</textarea> |
| 413 | @ </td></tr> |
| 414 | |
| 415 | @ <tr><th align="right" valign="top">Background Color:</th> |
| 416 | @ <td valign="top"> |
| 417 | render_color_chooser(0, zClr, 0, "clr", "cclr"); |
| 418 | @ </td></tr> |
| 419 | |
| 420 | @ <tr><th align="right" valign="top">Tags:</th> |
| 421 | @ <td valign="top"> |
| 422 | @ <input type="text" name="g" size="40" value="%h(zTags)" /> |
| 423 | @ </td></tr> |
| 424 | |
| 425 | @ <tr><th align="right" valign="top">Page Content:</th> |
| 426 | @ <td valign="top"> |
| 427 | @ <textarea name="w" class="eventedit" cols="80" |
| 428 | @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea> |
| 429 | @ </td></tr> |
| 430 | |
| 431 |
+94
-78
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -316,25 +316,22 @@ | ||
| 316 | 316 | blob_zero(&to); |
| 317 | 317 | } |
| 318 | 318 | blob_zero(&out); |
| 319 | 319 | if( diffFlags & DIFF_SIDEBYSIDE ){ |
| 320 | 320 | text_diff(&from, &to, &out, pRe, diffFlags | DIFF_HTML | DIFF_NOTTOOBIG); |
| 321 | - @ <div class="sbsdiff"> | |
| 322 | 321 | @ %s(blob_str(&out)) |
| 323 | - @ </div> | |
| 324 | 322 | }else{ |
| 325 | 323 | text_diff(&from, &to, &out, pRe, |
| 326 | 324 | diffFlags | DIFF_LINENO | DIFF_HTML | DIFF_NOTTOOBIG); |
| 327 | - @ <div class="udiff"> | |
| 325 | + @ <pre class="udiff"> | |
| 328 | 326 | @ %s(blob_str(&out)) |
| 329 | - @ </div> | |
| 327 | + @ </pre> | |
| 330 | 328 | } |
| 331 | 329 | blob_reset(&from); |
| 332 | 330 | blob_reset(&to); |
| 333 | 331 | blob_reset(&out); |
| 334 | 332 | } |
| 335 | - | |
| 336 | 333 | |
| 337 | 334 | /* |
| 338 | 335 | ** Write a line of web-page output that shows changes that have occurred |
| 339 | 336 | ** to a file between two check-ins. |
| 340 | 337 | */ |
| @@ -359,13 +356,11 @@ | ||
| 359 | 356 | @ for %h(zName)</p> |
| 360 | 357 | }else{ |
| 361 | 358 | @ <p>Changes to %h(zName)</p> |
| 362 | 359 | } |
| 363 | 360 | if( diffFlags ){ |
| 364 | - @ <pre style="white-space:pre;"> | |
| 365 | 361 | append_diff(zOld, zNew, diffFlags, pRe); |
| 366 | - @ </pre> | |
| 367 | 362 | } |
| 368 | 363 | }else{ |
| 369 | 364 | if( zOld && zNew ){ |
| 370 | 365 | if( fossil_strcmp(zOld, zNew)!=0 ){ |
| 371 | 366 | @ <p>Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| @@ -385,20 +380,51 @@ | ||
| 385 | 380 | }else{ |
| 386 | 381 | @ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 387 | 382 | @ version %z(href("%R/artifact/%s",zNew))[%S(zNew)]</a> |
| 388 | 383 | } |
| 389 | 384 | if( diffFlags ){ |
| 390 | - @ <pre style="white-space:pre;"> | |
| 391 | 385 | append_diff(zOld, zNew, diffFlags, pRe); |
| 392 | - @ </pre> | |
| 393 | 386 | }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){ |
| 394 | 387 | @ |
| 395 | 388 | @ %z(href("%R/fdiff?v1=%S&v2=%S&sbs=1",zOld,zNew))[diff]</a> |
| 396 | 389 | } |
| 397 | - @ </p> | |
| 398 | 390 | } |
| 399 | 391 | } |
| 392 | + | |
| 393 | +/* | |
| 394 | +** Generate javascript to enhance HTML diffs. | |
| 395 | +*/ | |
| 396 | +void append_diff_javascript(int sideBySide){ | |
| 397 | + if( !sideBySide ) return; | |
| 398 | + @ <script>(function(){ | |
| 399 | + @ var SCROLL_LEN = 25; | |
| 400 | + @ function initSbsDiff(diff){ | |
| 401 | + @ var txtCols = diff.querySelectorAll('.difftxtcol'); | |
| 402 | + @ var txtPres = diff.querySelectorAll('.difftxtcol pre'); | |
| 403 | + @ var width = Math.max(txtPres[0].scrollWidth, txtPres[1].scrollWidth); | |
| 404 | + @ for(var i=0; i<2; i++){ | |
| 405 | + @ txtPres[i].style.width = width + 'px'; | |
| 406 | + @ txtCols[i].onscroll = function(e){ | |
| 407 | + @ txtCols[0].scrollLeft = txtCols[1].scrollLeft = this.scrollLeft; | |
| 408 | + @ }; | |
| 409 | + @ } | |
| 410 | + @ diff.tabIndex = 0; | |
| 411 | + @ diff.onkeydown = function(e){ | |
| 412 | + @ e = e || event; | |
| 413 | + @ var len = {37: -SCROLL_LEN, 39: SCROLL_LEN}[e.keyCode]; | |
| 414 | + @ if( !len ) return; | |
| 415 | + @ txtCols[0].scrollLeft += len; | |
| 416 | + @ return false; | |
| 417 | + @ }; | |
| 418 | + @ } | |
| 419 | + @ | |
| 420 | + @ var diffs = document.querySelectorAll('.sbsdiffcols'); | |
| 421 | + @ for(var i=0; i<diffs.length; i++){ | |
| 422 | + @ initSbsDiff(diffs[i]); | |
| 423 | + @ } | |
| 424 | + @ }())</script> | |
| 425 | +} | |
| 400 | 426 | |
| 401 | 427 | /* |
| 402 | 428 | ** Construct an appropriate diffFlag for text_diff() based on query |
| 403 | 429 | ** parameters and the to boolean arguments. |
| 404 | 430 | */ |
| @@ -675,10 +701,11 @@ | ||
| 675 | 701 | const char *zOldName = db_column_text(&q, 4); |
| 676 | 702 | append_file_change_line(zName, zOld, zNew, zOldName, diffFlags,pRe,mperm); |
| 677 | 703 | } |
| 678 | 704 | db_finalize(&q); |
| 679 | 705 | } |
| 706 | + append_diff_javascript(sideBySide); | |
| 680 | 707 | style_footer(); |
| 681 | 708 | } |
| 682 | 709 | |
| 683 | 710 | /* |
| 684 | 711 | ** WEBPAGE: winfo |
| @@ -988,11 +1015,11 @@ | ||
| 988 | 1015 | pFileTo = manifest_file_next(pTo, 0); |
| 989 | 1016 | } |
| 990 | 1017 | } |
| 991 | 1018 | manifest_destroy(pFrom); |
| 992 | 1019 | manifest_destroy(pTo); |
| 993 | - | |
| 1020 | + append_diff_javascript(sideBySide); | |
| 994 | 1021 | style_footer(); |
| 995 | 1022 | } |
| 996 | 1023 | |
| 997 | 1024 | #if INTERFACE |
| 998 | 1025 | /* |
| @@ -1244,85 +1271,74 @@ | ||
| 1244 | 1271 | */ |
| 1245 | 1272 | void diff_page(void){ |
| 1246 | 1273 | int v1, v2; |
| 1247 | 1274 | int isPatch; |
| 1248 | 1275 | int sideBySide; |
| 1249 | - Blob c1, c2, diff, *pOut; | |
| 1250 | 1276 | char *zV1; |
| 1251 | 1277 | char *zV2; |
| 1252 | 1278 | const char *zRe; |
| 1253 | 1279 | ReCompiled *pRe = 0; |
| 1254 | 1280 | u64 diffFlags; |
| 1255 | - const char *zStyle = "sbsdiff"; | |
| 1256 | 1281 | |
| 1257 | 1282 | login_check_credentials(); |
| 1258 | 1283 | if( !g.perm.Read ){ login_needed(); return; } |
| 1259 | 1284 | v1 = name_to_rid_www("v1"); |
| 1260 | 1285 | v2 = name_to_rid_www("v2"); |
| 1261 | 1286 | if( v1==0 || v2==0 ) fossil_redirect_home(); |
| 1262 | - sideBySide = !is_false(PD("sbs","1")); | |
| 1263 | - zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1); | |
| 1264 | - zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2); | |
| 1287 | + zRe = P("regex"); | |
| 1288 | + if( zRe ) re_compile(&pRe, zRe, 0); | |
| 1265 | 1289 | isPatch = P("patch")!=0; |
| 1266 | 1290 | if( isPatch ){ |
| 1291 | + Blob c1, c2, *pOut; | |
| 1267 | 1292 | pOut = cgi_output_blob(); |
| 1268 | 1293 | cgi_set_content_type("text/plain"); |
| 1269 | 1294 | diffFlags = 4; |
| 1270 | - }else{ | |
| 1271 | - blob_zero(&diff); | |
| 1272 | - pOut = &diff; | |
| 1273 | - diffFlags = construct_diff_flags(1, sideBySide) | DIFF_HTML; | |
| 1274 | - if( sideBySide ){ | |
| 1275 | - zStyle = "sbsdiff"; | |
| 1276 | - }else{ | |
| 1277 | - diffFlags |= DIFF_LINENO; | |
| 1278 | - zStyle = "udiff"; | |
| 1279 | - } | |
| 1280 | - } | |
| 1281 | - zRe = P("regex"); | |
| 1282 | - if( zRe ) re_compile(&pRe, zRe, 0); | |
| 1283 | - content_get(v1, &c1); | |
| 1284 | - content_get(v2, &c2); | |
| 1285 | - text_diff(&c1, &c2, pOut, pRe, diffFlags); | |
| 1286 | - blob_reset(&c1); | |
| 1287 | - blob_reset(&c2); | |
| 1288 | - if( !isPatch ){ | |
| 1289 | - style_header("Diff"); | |
| 1290 | - style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch", | |
| 1291 | - g.zTop, P("v1"), P("v2")); | |
| 1292 | - if( !sideBySide ){ | |
| 1293 | - style_submenu_element("Side-by-side Diff", "sbsdiff", | |
| 1294 | - "%s/fdiff?v1=%T&v2=%T&sbs=1", | |
| 1295 | - g.zTop, P("v1"), P("v2")); | |
| 1296 | - }else{ | |
| 1297 | - style_submenu_element("Unified Diff", "udiff", | |
| 1298 | - "%s/fdiff?v1=%T&v2=%T&sbs=0", | |
| 1299 | - g.zTop, P("v1"), P("v2")); | |
| 1300 | - } | |
| 1301 | - | |
| 1302 | - if( P("smhdr")!=0 ){ | |
| 1303 | - @ <h2>Differences From Artifact | |
| 1304 | - @ %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a> To | |
| 1305 | - @ %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>.</h2> | |
| 1306 | - }else{ | |
| 1307 | - @ <h2>Differences From | |
| 1308 | - @ Artifact %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a>:</h2> | |
| 1309 | - object_description(v1, 0, 0); | |
| 1310 | - @ <h2>To Artifact %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>:</h2> | |
| 1311 | - object_description(v2, 0, 0); | |
| 1312 | - } | |
| 1313 | - if( pRe ){ | |
| 1314 | - @ <b>Only differences that match regular expression "%h(zRe)" | |
| 1315 | - @ are shown.</b> | |
| 1316 | - } | |
| 1317 | - @ <hr /> | |
| 1318 | - @ <div class="%s(zStyle)"> | |
| 1319 | - @ %s(blob_str(&diff)) | |
| 1320 | - @ </div> | |
| 1321 | - blob_reset(&diff); | |
| 1322 | - style_footer(); | |
| 1323 | - } | |
| 1295 | + content_get(v1, &c1); | |
| 1296 | + content_get(v2, &c2); | |
| 1297 | + text_diff(&c1, &c2, pOut, pRe, diffFlags); | |
| 1298 | + blob_reset(&c1); | |
| 1299 | + blob_reset(&c2); | |
| 1300 | + return; | |
| 1301 | + } | |
| 1302 | + | |
| 1303 | + sideBySide = !is_false(PD("sbs","1")); | |
| 1304 | + zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1); | |
| 1305 | + zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2); | |
| 1306 | + diffFlags = construct_diff_flags(1, sideBySide) | DIFF_HTML; | |
| 1307 | + | |
| 1308 | + style_header("Diff"); | |
| 1309 | + style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch", | |
| 1310 | + g.zTop, P("v1"), P("v2")); | |
| 1311 | + if( !sideBySide ){ | |
| 1312 | + style_submenu_element("Side-by-side Diff", "sbsdiff", | |
| 1313 | + "%s/fdiff?v1=%T&v2=%T&sbs=1", | |
| 1314 | + g.zTop, P("v1"), P("v2")); | |
| 1315 | + }else{ | |
| 1316 | + style_submenu_element("Unified Diff", "udiff", | |
| 1317 | + "%s/fdiff?v1=%T&v2=%T&sbs=0", | |
| 1318 | + g.zTop, P("v1"), P("v2")); | |
| 1319 | + } | |
| 1320 | + | |
| 1321 | + if( P("smhdr")!=0 ){ | |
| 1322 | + @ <h2>Differences From Artifact | |
| 1323 | + @ %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a> To | |
| 1324 | + @ %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>.</h2> | |
| 1325 | + }else{ | |
| 1326 | + @ <h2>Differences From | |
| 1327 | + @ Artifact %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a>:</h2> | |
| 1328 | + object_description(v1, 0, 0); | |
| 1329 | + @ <h2>To Artifact %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>:</h2> | |
| 1330 | + object_description(v2, 0, 0); | |
| 1331 | + } | |
| 1332 | + if( pRe ){ | |
| 1333 | + @ <b>Only differences that match regular expression "%h(zRe)" | |
| 1334 | + @ are shown.</b> | |
| 1335 | + } | |
| 1336 | + @ <hr /> | |
| 1337 | + append_diff(zV1, zV2, diffFlags, pRe); | |
| 1338 | + append_diff_javascript(sideBySide); | |
| 1339 | + style_footer(); | |
| 1324 | 1340 | } |
| 1325 | 1341 | |
| 1326 | 1342 | /* |
| 1327 | 1343 | ** WEBPAGE: raw |
| 1328 | 1344 | ** URL: /raw?name=ARTIFACTID&m=TYPE |
| @@ -2205,38 +2221,38 @@ | ||
| 2205 | 2221 | form_begin(0, "%R/ci_edit"); |
| 2206 | 2222 | login_insert_csrf_secret(); |
| 2207 | 2223 | @ <div><input type="hidden" name="r" value="%S(zUuid)" /> |
| 2208 | 2224 | @ <table border="0" cellspacing="10"> |
| 2209 | 2225 | |
| 2210 | - @ <tr><td align="right" valign="top"><b>User:</b></td> | |
| 2226 | + @ <tr><th align="right" valign="top">User:</th> | |
| 2211 | 2227 | @ <td valign="top"> |
| 2212 | 2228 | @ <input type="text" name="u" size="20" value="%h(zNewUser)" /> |
| 2213 | 2229 | @ </td></tr> |
| 2214 | 2230 | |
| 2215 | - @ <tr><td align="right" valign="top"><b>Comment:</b></td> | |
| 2231 | + @ <tr><th align="right" valign="top">Comment:</th> | |
| 2216 | 2232 | @ <td valign="top"> |
| 2217 | 2233 | @ <textarea name="c" rows="10" cols="80">%h(zNewComment)</textarea> |
| 2218 | 2234 | @ </td></tr> |
| 2219 | 2235 | |
| 2220 | - @ <tr><td align="right" valign="top"><b>Check-in Time:</b></td> | |
| 2236 | + @ <tr><th align="right" valign="top">Check-in Time:</th> | |
| 2221 | 2237 | @ <td valign="top"> |
| 2222 | 2238 | @ <input type="text" name="dt" size="20" value="%h(zNewDate)" /> |
| 2223 | 2239 | @ </td></tr> |
| 2224 | 2240 | |
| 2225 | 2241 | if( zChngTime ){ |
| 2226 | - @ <tr><td align="right" valign="top"><b>Timestamp of this change:</b></td> | |
| 2242 | + @ <tr><th align="right" valign="top">Timestamp of this change:</th> | |
| 2227 | 2243 | @ <td valign="top"> |
| 2228 | 2244 | @ <input type="text" name="chngtime" size="20" value="%h(zChngTime)" /> |
| 2229 | 2245 | @ </td></tr> |
| 2230 | 2246 | } |
| 2231 | 2247 | |
| 2232 | - @ <tr><td align="right" valign="top"><b>Background Color:</b></td> | |
| 2248 | + @ <tr><th align="right" valign="top">Background Color:</th> | |
| 2233 | 2249 | @ <td valign="top"> |
| 2234 | 2250 | render_color_chooser(fNewPropagateColor, zNewColor, "pclr", "clr", "clrcust"); |
| 2235 | 2251 | @ </td></tr> |
| 2236 | 2252 | |
| 2237 | - @ <tr><td align="right" valign="top"><b>Tags:</b></td> | |
| 2253 | + @ <tr><th align="right" valign="top">Tags:</th> | |
| 2238 | 2254 | @ <td valign="top"> |
| 2239 | 2255 | @ <label><input type="checkbox" id="newtag" name="newtag"%s(zNewTagFlag) /> |
| 2240 | 2256 | @ Add the following new tag name to this check-in:</label> |
| 2241 | 2257 | @ <input type="text" style="width:15;" name="tagname" value="%h(zNewTag)" |
| 2242 | 2258 | @ onkeyup="gebi('newtag').checked=!!this.value" /> |
| @@ -2265,11 +2281,11 @@ | ||
| 2265 | 2281 | } |
| 2266 | 2282 | } |
| 2267 | 2283 | db_finalize(&q); |
| 2268 | 2284 | @ </td></tr> |
| 2269 | 2285 | |
| 2270 | - @ <tr><td align="right" valign="top"><b>Branching:</b></td> | |
| 2286 | + @ <tr><th align="right" valign="top">Branching:</th> | |
| 2271 | 2287 | @ <td valign="top"> |
| 2272 | 2288 | @ <label><input id="newbr" type="checkbox" name="newbr"%s(zNewBrFlag) /> |
| 2273 | 2289 | @ Make this check-in the start of a new branch named:</label> |
| 2274 | 2290 | @ <input type="text" style="width:15;" name="brname" value="%h(zNewBranch)" |
| 2275 | 2291 | @ onkeyup="gebi('newbr').checked=!!this.value" /> |
| @@ -2278,11 +2294,11 @@ | ||
| 2278 | 2294 | if( is_a_leaf(rid) |
| 2279 | 2295 | && !db_exists("SELECT 1 FROM tagxref " |
| 2280 | 2296 | " WHERE tagid=%d AND rid=%d AND tagtype>0", |
| 2281 | 2297 | TAG_CLOSED, rid) |
| 2282 | 2298 | ){ |
| 2283 | - @ <tr><td align="right" valign="top"><b>Leaf Closure:</b></td> | |
| 2299 | + @ <tr><th align="right" valign="top">Leaf Closure:</th> | |
| 2284 | 2300 | @ <td valign="top"> |
| 2285 | 2301 | @ <label><input type="checkbox" name="close"%s(zCloseFlag) /> |
| 2286 | 2302 | @ Mark this leaf as "closed" so that it no longer appears on the |
| 2287 | 2303 | @ "leaves" page and is no longer labeled as a "<b>Leaf</b>".</label> |
| 2288 | 2304 | @ </td></tr> |
| 2289 | 2305 | |
| 2290 | 2306 | ADDED src/lookslike.c |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -316,25 +316,22 @@ | |
| 316 | blob_zero(&to); |
| 317 | } |
| 318 | blob_zero(&out); |
| 319 | if( diffFlags & DIFF_SIDEBYSIDE ){ |
| 320 | text_diff(&from, &to, &out, pRe, diffFlags | DIFF_HTML | DIFF_NOTTOOBIG); |
| 321 | @ <div class="sbsdiff"> |
| 322 | @ %s(blob_str(&out)) |
| 323 | @ </div> |
| 324 | }else{ |
| 325 | text_diff(&from, &to, &out, pRe, |
| 326 | diffFlags | DIFF_LINENO | DIFF_HTML | DIFF_NOTTOOBIG); |
| 327 | @ <div class="udiff"> |
| 328 | @ %s(blob_str(&out)) |
| 329 | @ </div> |
| 330 | } |
| 331 | blob_reset(&from); |
| 332 | blob_reset(&to); |
| 333 | blob_reset(&out); |
| 334 | } |
| 335 | |
| 336 | |
| 337 | /* |
| 338 | ** Write a line of web-page output that shows changes that have occurred |
| 339 | ** to a file between two check-ins. |
| 340 | */ |
| @@ -359,13 +356,11 @@ | |
| 359 | @ for %h(zName)</p> |
| 360 | }else{ |
| 361 | @ <p>Changes to %h(zName)</p> |
| 362 | } |
| 363 | if( diffFlags ){ |
| 364 | @ <pre style="white-space:pre;"> |
| 365 | append_diff(zOld, zNew, diffFlags, pRe); |
| 366 | @ </pre> |
| 367 | } |
| 368 | }else{ |
| 369 | if( zOld && zNew ){ |
| 370 | if( fossil_strcmp(zOld, zNew)!=0 ){ |
| 371 | @ <p>Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| @@ -385,20 +380,51 @@ | |
| 385 | }else{ |
| 386 | @ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 387 | @ version %z(href("%R/artifact/%s",zNew))[%S(zNew)]</a> |
| 388 | } |
| 389 | if( diffFlags ){ |
| 390 | @ <pre style="white-space:pre;"> |
| 391 | append_diff(zOld, zNew, diffFlags, pRe); |
| 392 | @ </pre> |
| 393 | }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){ |
| 394 | @ |
| 395 | @ %z(href("%R/fdiff?v1=%S&v2=%S&sbs=1",zOld,zNew))[diff]</a> |
| 396 | } |
| 397 | @ </p> |
| 398 | } |
| 399 | } |
| 400 | |
| 401 | /* |
| 402 | ** Construct an appropriate diffFlag for text_diff() based on query |
| 403 | ** parameters and the to boolean arguments. |
| 404 | */ |
| @@ -675,10 +701,11 @@ | |
| 675 | const char *zOldName = db_column_text(&q, 4); |
| 676 | append_file_change_line(zName, zOld, zNew, zOldName, diffFlags,pRe,mperm); |
| 677 | } |
| 678 | db_finalize(&q); |
| 679 | } |
| 680 | style_footer(); |
| 681 | } |
| 682 | |
| 683 | /* |
| 684 | ** WEBPAGE: winfo |
| @@ -988,11 +1015,11 @@ | |
| 988 | pFileTo = manifest_file_next(pTo, 0); |
| 989 | } |
| 990 | } |
| 991 | manifest_destroy(pFrom); |
| 992 | manifest_destroy(pTo); |
| 993 | |
| 994 | style_footer(); |
| 995 | } |
| 996 | |
| 997 | #if INTERFACE |
| 998 | /* |
| @@ -1244,85 +1271,74 @@ | |
| 1244 | */ |
| 1245 | void diff_page(void){ |
| 1246 | int v1, v2; |
| 1247 | int isPatch; |
| 1248 | int sideBySide; |
| 1249 | Blob c1, c2, diff, *pOut; |
| 1250 | char *zV1; |
| 1251 | char *zV2; |
| 1252 | const char *zRe; |
| 1253 | ReCompiled *pRe = 0; |
| 1254 | u64 diffFlags; |
| 1255 | const char *zStyle = "sbsdiff"; |
| 1256 | |
| 1257 | login_check_credentials(); |
| 1258 | if( !g.perm.Read ){ login_needed(); return; } |
| 1259 | v1 = name_to_rid_www("v1"); |
| 1260 | v2 = name_to_rid_www("v2"); |
| 1261 | if( v1==0 || v2==0 ) fossil_redirect_home(); |
| 1262 | sideBySide = !is_false(PD("sbs","1")); |
| 1263 | zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1); |
| 1264 | zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2); |
| 1265 | isPatch = P("patch")!=0; |
| 1266 | if( isPatch ){ |
| 1267 | pOut = cgi_output_blob(); |
| 1268 | cgi_set_content_type("text/plain"); |
| 1269 | diffFlags = 4; |
| 1270 | }else{ |
| 1271 | blob_zero(&diff); |
| 1272 | pOut = &diff; |
| 1273 | diffFlags = construct_diff_flags(1, sideBySide) | DIFF_HTML; |
| 1274 | if( sideBySide ){ |
| 1275 | zStyle = "sbsdiff"; |
| 1276 | }else{ |
| 1277 | diffFlags |= DIFF_LINENO; |
| 1278 | zStyle = "udiff"; |
| 1279 | } |
| 1280 | } |
| 1281 | zRe = P("regex"); |
| 1282 | if( zRe ) re_compile(&pRe, zRe, 0); |
| 1283 | content_get(v1, &c1); |
| 1284 | content_get(v2, &c2); |
| 1285 | text_diff(&c1, &c2, pOut, pRe, diffFlags); |
| 1286 | blob_reset(&c1); |
| 1287 | blob_reset(&c2); |
| 1288 | if( !isPatch ){ |
| 1289 | style_header("Diff"); |
| 1290 | style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch", |
| 1291 | g.zTop, P("v1"), P("v2")); |
| 1292 | if( !sideBySide ){ |
| 1293 | style_submenu_element("Side-by-side Diff", "sbsdiff", |
| 1294 | "%s/fdiff?v1=%T&v2=%T&sbs=1", |
| 1295 | g.zTop, P("v1"), P("v2")); |
| 1296 | }else{ |
| 1297 | style_submenu_element("Unified Diff", "udiff", |
| 1298 | "%s/fdiff?v1=%T&v2=%T&sbs=0", |
| 1299 | g.zTop, P("v1"), P("v2")); |
| 1300 | } |
| 1301 | |
| 1302 | if( P("smhdr")!=0 ){ |
| 1303 | @ <h2>Differences From Artifact |
| 1304 | @ %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a> To |
| 1305 | @ %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>.</h2> |
| 1306 | }else{ |
| 1307 | @ <h2>Differences From |
| 1308 | @ Artifact %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a>:</h2> |
| 1309 | object_description(v1, 0, 0); |
| 1310 | @ <h2>To Artifact %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>:</h2> |
| 1311 | object_description(v2, 0, 0); |
| 1312 | } |
| 1313 | if( pRe ){ |
| 1314 | @ <b>Only differences that match regular expression "%h(zRe)" |
| 1315 | @ are shown.</b> |
| 1316 | } |
| 1317 | @ <hr /> |
| 1318 | @ <div class="%s(zStyle)"> |
| 1319 | @ %s(blob_str(&diff)) |
| 1320 | @ </div> |
| 1321 | blob_reset(&diff); |
| 1322 | style_footer(); |
| 1323 | } |
| 1324 | } |
| 1325 | |
| 1326 | /* |
| 1327 | ** WEBPAGE: raw |
| 1328 | ** URL: /raw?name=ARTIFACTID&m=TYPE |
| @@ -2205,38 +2221,38 @@ | |
| 2205 | form_begin(0, "%R/ci_edit"); |
| 2206 | login_insert_csrf_secret(); |
| 2207 | @ <div><input type="hidden" name="r" value="%S(zUuid)" /> |
| 2208 | @ <table border="0" cellspacing="10"> |
| 2209 | |
| 2210 | @ <tr><td align="right" valign="top"><b>User:</b></td> |
| 2211 | @ <td valign="top"> |
| 2212 | @ <input type="text" name="u" size="20" value="%h(zNewUser)" /> |
| 2213 | @ </td></tr> |
| 2214 | |
| 2215 | @ <tr><td align="right" valign="top"><b>Comment:</b></td> |
| 2216 | @ <td valign="top"> |
| 2217 | @ <textarea name="c" rows="10" cols="80">%h(zNewComment)</textarea> |
| 2218 | @ </td></tr> |
| 2219 | |
| 2220 | @ <tr><td align="right" valign="top"><b>Check-in Time:</b></td> |
| 2221 | @ <td valign="top"> |
| 2222 | @ <input type="text" name="dt" size="20" value="%h(zNewDate)" /> |
| 2223 | @ </td></tr> |
| 2224 | |
| 2225 | if( zChngTime ){ |
| 2226 | @ <tr><td align="right" valign="top"><b>Timestamp of this change:</b></td> |
| 2227 | @ <td valign="top"> |
| 2228 | @ <input type="text" name="chngtime" size="20" value="%h(zChngTime)" /> |
| 2229 | @ </td></tr> |
| 2230 | } |
| 2231 | |
| 2232 | @ <tr><td align="right" valign="top"><b>Background Color:</b></td> |
| 2233 | @ <td valign="top"> |
| 2234 | render_color_chooser(fNewPropagateColor, zNewColor, "pclr", "clr", "clrcust"); |
| 2235 | @ </td></tr> |
| 2236 | |
| 2237 | @ <tr><td align="right" valign="top"><b>Tags:</b></td> |
| 2238 | @ <td valign="top"> |
| 2239 | @ <label><input type="checkbox" id="newtag" name="newtag"%s(zNewTagFlag) /> |
| 2240 | @ Add the following new tag name to this check-in:</label> |
| 2241 | @ <input type="text" style="width:15;" name="tagname" value="%h(zNewTag)" |
| 2242 | @ onkeyup="gebi('newtag').checked=!!this.value" /> |
| @@ -2265,11 +2281,11 @@ | |
| 2265 | } |
| 2266 | } |
| 2267 | db_finalize(&q); |
| 2268 | @ </td></tr> |
| 2269 | |
| 2270 | @ <tr><td align="right" valign="top"><b>Branching:</b></td> |
| 2271 | @ <td valign="top"> |
| 2272 | @ <label><input id="newbr" type="checkbox" name="newbr"%s(zNewBrFlag) /> |
| 2273 | @ Make this check-in the start of a new branch named:</label> |
| 2274 | @ <input type="text" style="width:15;" name="brname" value="%h(zNewBranch)" |
| 2275 | @ onkeyup="gebi('newbr').checked=!!this.value" /> |
| @@ -2278,11 +2294,11 @@ | |
| 2278 | if( is_a_leaf(rid) |
| 2279 | && !db_exists("SELECT 1 FROM tagxref " |
| 2280 | " WHERE tagid=%d AND rid=%d AND tagtype>0", |
| 2281 | TAG_CLOSED, rid) |
| 2282 | ){ |
| 2283 | @ <tr><td align="right" valign="top"><b>Leaf Closure:</b></td> |
| 2284 | @ <td valign="top"> |
| 2285 | @ <label><input type="checkbox" name="close"%s(zCloseFlag) /> |
| 2286 | @ Mark this leaf as "closed" so that it no longer appears on the |
| 2287 | @ "leaves" page and is no longer labeled as a "<b>Leaf</b>".</label> |
| 2288 | @ </td></tr> |
| 2289 | |
| 2290 | DDED src/lookslike.c |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -316,25 +316,22 @@ | |
| 316 | blob_zero(&to); |
| 317 | } |
| 318 | blob_zero(&out); |
| 319 | if( diffFlags & DIFF_SIDEBYSIDE ){ |
| 320 | text_diff(&from, &to, &out, pRe, diffFlags | DIFF_HTML | DIFF_NOTTOOBIG); |
| 321 | @ %s(blob_str(&out)) |
| 322 | }else{ |
| 323 | text_diff(&from, &to, &out, pRe, |
| 324 | diffFlags | DIFF_LINENO | DIFF_HTML | DIFF_NOTTOOBIG); |
| 325 | @ <pre class="udiff"> |
| 326 | @ %s(blob_str(&out)) |
| 327 | @ </pre> |
| 328 | } |
| 329 | blob_reset(&from); |
| 330 | blob_reset(&to); |
| 331 | blob_reset(&out); |
| 332 | } |
| 333 | |
| 334 | /* |
| 335 | ** Write a line of web-page output that shows changes that have occurred |
| 336 | ** to a file between two check-ins. |
| 337 | */ |
| @@ -359,13 +356,11 @@ | |
| 356 | @ for %h(zName)</p> |
| 357 | }else{ |
| 358 | @ <p>Changes to %h(zName)</p> |
| 359 | } |
| 360 | if( diffFlags ){ |
| 361 | append_diff(zOld, zNew, diffFlags, pRe); |
| 362 | } |
| 363 | }else{ |
| 364 | if( zOld && zNew ){ |
| 365 | if( fossil_strcmp(zOld, zNew)!=0 ){ |
| 366 | @ <p>Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| @@ -385,20 +380,51 @@ | |
| 380 | }else{ |
| 381 | @ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 382 | @ version %z(href("%R/artifact/%s",zNew))[%S(zNew)]</a> |
| 383 | } |
| 384 | if( diffFlags ){ |
| 385 | append_diff(zOld, zNew, diffFlags, pRe); |
| 386 | }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){ |
| 387 | @ |
| 388 | @ %z(href("%R/fdiff?v1=%S&v2=%S&sbs=1",zOld,zNew))[diff]</a> |
| 389 | } |
| 390 | } |
| 391 | } |
| 392 | |
| 393 | /* |
| 394 | ** Generate javascript to enhance HTML diffs. |
| 395 | */ |
| 396 | void append_diff_javascript(int sideBySide){ |
| 397 | if( !sideBySide ) return; |
| 398 | @ <script>(function(){ |
| 399 | @ var SCROLL_LEN = 25; |
| 400 | @ function initSbsDiff(diff){ |
| 401 | @ var txtCols = diff.querySelectorAll('.difftxtcol'); |
| 402 | @ var txtPres = diff.querySelectorAll('.difftxtcol pre'); |
| 403 | @ var width = Math.max(txtPres[0].scrollWidth, txtPres[1].scrollWidth); |
| 404 | @ for(var i=0; i<2; i++){ |
| 405 | @ txtPres[i].style.width = width + 'px'; |
| 406 | @ txtCols[i].onscroll = function(e){ |
| 407 | @ txtCols[0].scrollLeft = txtCols[1].scrollLeft = this.scrollLeft; |
| 408 | @ }; |
| 409 | @ } |
| 410 | @ diff.tabIndex = 0; |
| 411 | @ diff.onkeydown = function(e){ |
| 412 | @ e = e || event; |
| 413 | @ var len = {37: -SCROLL_LEN, 39: SCROLL_LEN}[e.keyCode]; |
| 414 | @ if( !len ) return; |
| 415 | @ txtCols[0].scrollLeft += len; |
| 416 | @ return false; |
| 417 | @ }; |
| 418 | @ } |
| 419 | @ |
| 420 | @ var diffs = document.querySelectorAll('.sbsdiffcols'); |
| 421 | @ for(var i=0; i<diffs.length; i++){ |
| 422 | @ initSbsDiff(diffs[i]); |
| 423 | @ } |
| 424 | @ }())</script> |
| 425 | } |
| 426 | |
| 427 | /* |
| 428 | ** Construct an appropriate diffFlag for text_diff() based on query |
| 429 | ** parameters and the to boolean arguments. |
| 430 | */ |
| @@ -675,10 +701,11 @@ | |
| 701 | const char *zOldName = db_column_text(&q, 4); |
| 702 | append_file_change_line(zName, zOld, zNew, zOldName, diffFlags,pRe,mperm); |
| 703 | } |
| 704 | db_finalize(&q); |
| 705 | } |
| 706 | append_diff_javascript(sideBySide); |
| 707 | style_footer(); |
| 708 | } |
| 709 | |
| 710 | /* |
| 711 | ** WEBPAGE: winfo |
| @@ -988,11 +1015,11 @@ | |
| 1015 | pFileTo = manifest_file_next(pTo, 0); |
| 1016 | } |
| 1017 | } |
| 1018 | manifest_destroy(pFrom); |
| 1019 | manifest_destroy(pTo); |
| 1020 | append_diff_javascript(sideBySide); |
| 1021 | style_footer(); |
| 1022 | } |
| 1023 | |
| 1024 | #if INTERFACE |
| 1025 | /* |
| @@ -1244,85 +1271,74 @@ | |
| 1271 | */ |
| 1272 | void diff_page(void){ |
| 1273 | int v1, v2; |
| 1274 | int isPatch; |
| 1275 | int sideBySide; |
| 1276 | char *zV1; |
| 1277 | char *zV2; |
| 1278 | const char *zRe; |
| 1279 | ReCompiled *pRe = 0; |
| 1280 | u64 diffFlags; |
| 1281 | |
| 1282 | login_check_credentials(); |
| 1283 | if( !g.perm.Read ){ login_needed(); return; } |
| 1284 | v1 = name_to_rid_www("v1"); |
| 1285 | v2 = name_to_rid_www("v2"); |
| 1286 | if( v1==0 || v2==0 ) fossil_redirect_home(); |
| 1287 | zRe = P("regex"); |
| 1288 | if( zRe ) re_compile(&pRe, zRe, 0); |
| 1289 | isPatch = P("patch")!=0; |
| 1290 | if( isPatch ){ |
| 1291 | Blob c1, c2, *pOut; |
| 1292 | pOut = cgi_output_blob(); |
| 1293 | cgi_set_content_type("text/plain"); |
| 1294 | diffFlags = 4; |
| 1295 | content_get(v1, &c1); |
| 1296 | content_get(v2, &c2); |
| 1297 | text_diff(&c1, &c2, pOut, pRe, diffFlags); |
| 1298 | blob_reset(&c1); |
| 1299 | blob_reset(&c2); |
| 1300 | return; |
| 1301 | } |
| 1302 | |
| 1303 | sideBySide = !is_false(PD("sbs","1")); |
| 1304 | zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1); |
| 1305 | zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2); |
| 1306 | diffFlags = construct_diff_flags(1, sideBySide) | DIFF_HTML; |
| 1307 | |
| 1308 | style_header("Diff"); |
| 1309 | style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch", |
| 1310 | g.zTop, P("v1"), P("v2")); |
| 1311 | if( !sideBySide ){ |
| 1312 | style_submenu_element("Side-by-side Diff", "sbsdiff", |
| 1313 | "%s/fdiff?v1=%T&v2=%T&sbs=1", |
| 1314 | g.zTop, P("v1"), P("v2")); |
| 1315 | }else{ |
| 1316 | style_submenu_element("Unified Diff", "udiff", |
| 1317 | "%s/fdiff?v1=%T&v2=%T&sbs=0", |
| 1318 | g.zTop, P("v1"), P("v2")); |
| 1319 | } |
| 1320 | |
| 1321 | if( P("smhdr")!=0 ){ |
| 1322 | @ <h2>Differences From Artifact |
| 1323 | @ %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a> To |
| 1324 | @ %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>.</h2> |
| 1325 | }else{ |
| 1326 | @ <h2>Differences From |
| 1327 | @ Artifact %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a>:</h2> |
| 1328 | object_description(v1, 0, 0); |
| 1329 | @ <h2>To Artifact %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>:</h2> |
| 1330 | object_description(v2, 0, 0); |
| 1331 | } |
| 1332 | if( pRe ){ |
| 1333 | @ <b>Only differences that match regular expression "%h(zRe)" |
| 1334 | @ are shown.</b> |
| 1335 | } |
| 1336 | @ <hr /> |
| 1337 | append_diff(zV1, zV2, diffFlags, pRe); |
| 1338 | append_diff_javascript(sideBySide); |
| 1339 | style_footer(); |
| 1340 | } |
| 1341 | |
| 1342 | /* |
| 1343 | ** WEBPAGE: raw |
| 1344 | ** URL: /raw?name=ARTIFACTID&m=TYPE |
| @@ -2205,38 +2221,38 @@ | |
| 2221 | form_begin(0, "%R/ci_edit"); |
| 2222 | login_insert_csrf_secret(); |
| 2223 | @ <div><input type="hidden" name="r" value="%S(zUuid)" /> |
| 2224 | @ <table border="0" cellspacing="10"> |
| 2225 | |
| 2226 | @ <tr><th align="right" valign="top">User:</th> |
| 2227 | @ <td valign="top"> |
| 2228 | @ <input type="text" name="u" size="20" value="%h(zNewUser)" /> |
| 2229 | @ </td></tr> |
| 2230 | |
| 2231 | @ <tr><th align="right" valign="top">Comment:</th> |
| 2232 | @ <td valign="top"> |
| 2233 | @ <textarea name="c" rows="10" cols="80">%h(zNewComment)</textarea> |
| 2234 | @ </td></tr> |
| 2235 | |
| 2236 | @ <tr><th align="right" valign="top">Check-in Time:</th> |
| 2237 | @ <td valign="top"> |
| 2238 | @ <input type="text" name="dt" size="20" value="%h(zNewDate)" /> |
| 2239 | @ </td></tr> |
| 2240 | |
| 2241 | if( zChngTime ){ |
| 2242 | @ <tr><th align="right" valign="top">Timestamp of this change:</th> |
| 2243 | @ <td valign="top"> |
| 2244 | @ <input type="text" name="chngtime" size="20" value="%h(zChngTime)" /> |
| 2245 | @ </td></tr> |
| 2246 | } |
| 2247 | |
| 2248 | @ <tr><th align="right" valign="top">Background Color:</th> |
| 2249 | @ <td valign="top"> |
| 2250 | render_color_chooser(fNewPropagateColor, zNewColor, "pclr", "clr", "clrcust"); |
| 2251 | @ </td></tr> |
| 2252 | |
| 2253 | @ <tr><th align="right" valign="top">Tags:</th> |
| 2254 | @ <td valign="top"> |
| 2255 | @ <label><input type="checkbox" id="newtag" name="newtag"%s(zNewTagFlag) /> |
| 2256 | @ Add the following new tag name to this check-in:</label> |
| 2257 | @ <input type="text" style="width:15;" name="tagname" value="%h(zNewTag)" |
| 2258 | @ onkeyup="gebi('newtag').checked=!!this.value" /> |
| @@ -2265,11 +2281,11 @@ | |
| 2281 | } |
| 2282 | } |
| 2283 | db_finalize(&q); |
| 2284 | @ </td></tr> |
| 2285 | |
| 2286 | @ <tr><th align="right" valign="top">Branching:</th> |
| 2287 | @ <td valign="top"> |
| 2288 | @ <label><input id="newbr" type="checkbox" name="newbr"%s(zNewBrFlag) /> |
| 2289 | @ Make this check-in the start of a new branch named:</label> |
| 2290 | @ <input type="text" style="width:15;" name="brname" value="%h(zNewBranch)" |
| 2291 | @ onkeyup="gebi('newbr').checked=!!this.value" /> |
| @@ -2278,11 +2294,11 @@ | |
| 2294 | if( is_a_leaf(rid) |
| 2295 | && !db_exists("SELECT 1 FROM tagxref " |
| 2296 | " WHERE tagid=%d AND rid=%d AND tagtype>0", |
| 2297 | TAG_CLOSED, rid) |
| 2298 | ){ |
| 2299 | @ <tr><th align="right" valign="top">Leaf Closure:</th> |
| 2300 | @ <td valign="top"> |
| 2301 | @ <label><input type="checkbox" name="close"%s(zCloseFlag) /> |
| 2302 | @ Mark this leaf as "closed" so that it no longer appears on the |
| 2303 | @ "leaves" page and is no longer labeled as a "<b>Leaf</b>".</label> |
| 2304 | @ </td></tr> |
| 2305 | |
| 2306 | DDED src/lookslike.c |
+119
| --- a/src/lookslike.c | ||
| +++ b/src/lookslike.c | ||
| @@ -0,0 +1,119 @@ | ||
| 1 | +utf8((blob), LOOK_BINARY, 0) & LOOK_BINARY) != LOOK_NONE) | |
| 2 | + | |
| 3 | +/* | |
| 4 | +** Output flags for the looks_like_utf8() and looks_like_utf16() routines used | |
| 5 | +** to convey status information about the blob content. | |
| 6 | +*/ | |
| 7 | +#define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */ | |
| 8 | +#define LOOK_NUL ((int)0x00000001) /* One or more Nfossil_isalnumne LOOK_NUL ((int)0x00000001) /* One or more Nutf8((blob), Lz[i+n]!=0&&SQL. This is only a | |
| 9 | +** high-level check, not intended to be used for any application-level | |
| 10 | +** logic other than in defense against spiders in limited context((blob), LOOK_BINARY, 0) & LOOK_BINARY) != LOOK_NONE) | |
| 11 | + | |
| 12 | +/* | |
| 13 | +** Output flags for the looks_like_utf8() and looks_like_utf16() routines used | |
| 14 | +** to convey status information about the blob content. | |
| 15 | +*/ | |
| 16 | +#define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */ | |
| 17 | +#define LOOK_NUL ((int)0x00000001) /* One or more Nfossil_isalnumne LOOK_NUL ((int)0x00000001) /* One or more Nutf8((blob), LRY, 0) & LOOK_BINARY) != LOOK_NONE) | |
| 18 | + | |
| 19 | +/* | |
| 20 | +** Output flags for the looks_like_utf8() and looks_like_utf16() routines used | |
| 21 | +** to convey status information about the blob content. | |
| 22 | +*/ | |
| 23 | +#define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */ | |
| 24 | +#define LOOK_NUL ((int)0x00000001) /* One or more Nfossil_isalnumne LOOK_NUL ((int)0x00000001) /* One or more Nutf8((blob), Lmight_be_sql(cCR tatus i10ormation a02LOOK_BINARY, 0) & LOOK_BI were LOOK_NUL ((int)0x00LONE_CR 20d ") || L(" or ") | |
| 25 | + /* ^^^^^ F tatus i10ormation a08/* One or more Nfossil_is were LOOK_NUL ((int)0x00LONE_LF ((int)0x00000010 ") | |
| 26 | + /* ^^^^^ no=08ere LOOK_NUL ((/LF paiLF ((int)0x00000010") || L20F ((int)0x00000010") || L("updaten 0; | |
| 27 | +#define L(GLOB1" andf8() an88((blob), LOO4f8() and looks_like_utf16() routines used | |
| 28 | +** to 2onvey status i10ormation a8efine LOOK_NONE ((in04#define LOOK_NONE ((int)0x0000000020/* Nothing sp10ial was found. */ | |
| 29 | +#08fine LOOK_NUL ((int)0x00000001) /* One or more N20ssil_isalnumne LOOK_NUL ((int)0x00000001) /* One or more Nutf8((blob), Lz[i+n]!=0&&SQL. This is only aited context((blob), LOOK_BINARY, 0)define LOOK_CR [i+n]!=0&&SQL. This is onlCRLFere LOOK_ne or more Nfossil_isalnumne LOOK_NUL ((int)0x00000001) /* One or more Nutf8((blob), Lz[i+n]!=0&&SQL. This is only aited context((blob), LOOK_BINARY, 0) & LOOK_BINARY) != LOOK_NONE) | |
| 30 | + | |
| 31 | +/* | |
| 32 | +** Output flags for the looks_like_utf8() and looks_like_utf16() routines used | |
| 33 | +** to convey status information about the blob content. | |
| 34 | +*/ | |
| 35 | +#define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */ | |
| 36 | +#define LOOK_NUL ((int)0x00000001) /* One or more Nfossil_isalnumne LOOK_NUL ((int)0x00000001) /* One or more Nutf8((blob), LRY, 0) & LOOK_BINARY) != LOOK_NONE) | |
| 37 | + | |
| 38 | +/* | |
| 39 | +** Output flags for the looks_like_utf8() and looks_like_utf16() routines used | |
| 40 | +** to convey status information about the blob content. | |
| 41 | +*/ | |
| 42 | +#define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */ | |
| 43 | +#define LOOK_NUL ((int)0x00000001) /* One or more Nfossil_isalnumne LOOK_NUL ((int)0x00000001) /* One or more Nutf8((blob), Lmight_be_sql(const char *zTxt){ | |
| 44 | + if( zTxt==0 || zTxt[0]==0 ) return 0; | |
| 45 | +#define L(GLOB) 0==sqlite3_strlike("%" GLOB "%",zTxt, '%') | |
| 46 | + return L(";") || L("'") | |
| 47 | + || L("select") || L("order") || L("drop") | |
| 48 | + || L(" and ") || L(" or ") | |
| 49 | + /* ^^^^^ noting that \n and \t should also be checked */ | |
| 50 | + || L("null") || L("delete") || L("update") | |
| 51 | + |;<num> Repeatest_looks_like_utflooks_like_utf_testshort *z = (unsigned short1]==0possible UTF-32. */ | |
| 52 | + if( z[0]z[0]==0xfffeutf8((blob), LOOK_BINARY, 0) & LOOK_BINARY) != LOOK_NONE) | |
| 53 | + | |
| 54 | +/* | |
| 55 | +** Output flflags |= LOOK_CR; | |
| 56 | +F | flags |= LOOK_LF; | flags |= LOOK_CR;flags |= LOOK_CR; | |
| 57 | +F | flags |= LOOK_LF; | flags |= LOOK_CR;f8() and looks_like_utf16() roututf8((blob), LOOKf8() and looks_like_utf16() routines used | |
| 58 | +** to convey status information about the blob content. | |
| 59 | +*/ | |
| 60 | +#define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */ | |
| 61 | +#define LOOK_NUL ((int)0x00000001) /* One or more Nfossil_isalnumne LOOK_NUL ((int)0x00000001) /* One or more Nutf8((blobflags |= LOOK_CR;(blob), Lz[i+n]!=0&&SQL. This is only a | |
| 62 | +** high-level check, not intended to be used for any application-level | |
| 63 | +** logic other tMore chars, next char is--n>0() and flags |= LOOK_LF; | * to convey status informatiBF LOOK_BINARY) != nformationBF LOOK_BINARY) != LOO((int)0x00000000) /* NothingBF LOOK_BINARY) != int)0x0000BF LOOK_BINARY) != LOOK ((int)0x00000001) /* One BF LOOK_BINARY) != ),flags |= LOOK_CR; | |
| 64 | + K_CR CRLFurn 0; | |
| 65 | +#define L(GLOB) 0=LF (rop") | |
| 66 | + || L(" andf8() an88((blob), LOOKf8() and looks_like_utf16() routines used | |
| 67 | +** to convey status i10ormation about the blob content. | |
| 68 | +*/ | |
| 69 | +#define LOOK_NONE ((int)0x0000000020More chars, next char is0/* Nothing special was found. */ | |
| 70 | +#define LOOK_NUL , c2; | |
| 71 | + if( c2>=0xC0 ){ | |
| 72 | + *def = &lb_tab[(2*c2)-0x180]; | |
| 73 | + if( c2>=0xe80 ){ | |
| 74 | + if( ((c2<0xc2) || (c2>=0xf4) || ((c&0xc0)!=0x80)) && | |
| 75 | + (((c2!=0xf4) || (c>=0x90)) &c = (c2 >= 0xe0) ? (c2<<1)+1 : ' '|flags |= LOOK_CR; | |
| 76 | + intended to be used for any application-level | |
| 77 | +** logic other than in defense against spiders F | flags |= LOOK_LF; | * to convey status informat** to convey status information about the blob content. | |
| 78 | +*/ | |
| 79 | +#define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */ | |
| 80 | +#define LOOK_NUL ((int)0x00000001) /* One or more Nfossil_isalnumne LOOK_NUL ((int)0x00000001) /* One or more Nutf8((blob), Lz[i+n]!=0&&SQL. This is only a | |
| 81 | +** high-level check, not intended to be used for any application-level | |
| 82 | +** logic other than in defense against spiders in limited context((blob), LOOK_BINARY, 0) & LOOK_BINARY) != LOOK_NONE) | |
| 83 | + | |
| 84 | +/* | |
| 85 | +** Output flags for the looks_like_utf8() and looks_like_utf16() routines used | |
| 86 | +** to convey status information about the blob content. | |
| 87 | +*/ | |
| 88 | +#define LOOK_NONE ((int)0((blob), LOOK_BINARY, 0) & LO{ | |
| 89 | + *def || (c> ){ | |
| 90 | + return 1 }c>=0x8tf8((blob), LOOK_BINARY, 0) & LOOK_BINARY) != LOOK_NONE) | |
| 91 | + | |
| 92 | +/* | |
| 93 | +** Output flags for the looks_like_utf8() and looks_like_utf16() routines used | |
| 94 | +** to convey status information about the blob content. | |
| 95 | +*/ | |
| 96 | +#define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */ | |
| 97 | +#define LOOK_NUL ((int)0x00000001) /* One or more Nfossil_isalnumne LOOK_NUL ((int)0x00000001) /* One or more Nutf8((blob), Lz[i+n]!=0&&SQL. This is only a | |
| 98 | +** high-level check, not intended to be used for any application-level | |
| 99 | +** logic other than in defense against spiders in limited context((blob), LOOK_BINARY, 0) & LOOK_BINARY) != LOOK_NONE) | |
| 100 | + | |
| 101 | +/* | |
| 102 | +** Output flags for the looks_like_utf8() and looks_like_utf16() routines used | |
| 103 | +** to convey status information about the blob content. | |
| 104 | +*/ | |
| 105 | +#define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */ | |
| 106 | +#define LOOK_NUL ((int)0x00000001) /* One or more Nfossil_isalnumne LOOKY, 0) & LOOK_BINARY) }utf8((blob), LOOKK_BINARY, 0) & LOOK_BINARY) != LOOK_NONE) | |
| 107 | + | |
| 108 | +/* | |
| 109 | +** Output flags for the looks_like_utf8() and looks_like_utf16() routines used | |
| 110 | +** to convey status information about the blob content. | |
| 111 | +*/ | |
| 112 | +#define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */ | |
| 113 | +#define LOOK_NUL ((int)0x00000001) /* One or more Nfossil_isalnumne LOOK_NUL ((int)0x00000001) /* One or more Nutf8((blob), Lz[i+n]!=0&&SQL. This is o1if( flags&stopFlags ) break; | |
| 114 | + n -= sizeof(WCHAR_T); | |
| 115 | + if( n< break/*bRevUnicodefUtf16((int)0x00000000) utf8((blob), LOOK_BINARY, 0) & LfUnicode = 0; | |
| 116 | + }else{ | |
| 117 | +&bRevUnicode) || fForceUtEF, 0xBB, 0xBFlookFlags = fUnicode ? : | |
| 118 | +und. */ | |
| 119 | +#define |
| --- a/src/lookslike.c | |
| +++ b/src/lookslike.c | |
| @@ -0,0 +1,119 @@ | |
| --- a/src/lookslike.c | |
| +++ b/src/lookslike.c | |
| @@ -0,0 +1,119 @@ | |
| 1 | utf8((blob), LOOK_BINARY, 0) & LOOK_BINARY) != LOOK_NONE) |
| 2 | |
| 3 | /* |
| 4 | ** Output flags for the looks_like_utf8() and looks_like_utf16() routines used |
| 5 | ** to convey status information about the blob content. |
| 6 | */ |
| 7 | #define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */ |
| 8 | #define LOOK_NUL ((int)0x00000001) /* One or more Nfossil_isalnumne LOOK_NUL ((int)0x00000001) /* One or more Nutf8((blob), Lz[i+n]!=0&&SQL. This is only a |
| 9 | ** high-level check, not intended to be used for any application-level |
| 10 | ** logic other than in defense against spiders in limited context((blob), LOOK_BINARY, 0) & LOOK_BINARY) != LOOK_NONE) |
| 11 | |
| 12 | /* |
| 13 | ** Output flags for the looks_like_utf8() and looks_like_utf16() routines used |
| 14 | ** to convey status information about the blob content. |
| 15 | */ |
| 16 | #define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */ |
| 17 | #define LOOK_NUL ((int)0x00000001) /* One or more Nfossil_isalnumne LOOK_NUL ((int)0x00000001) /* One or more Nutf8((blob), LRY, 0) & LOOK_BINARY) != LOOK_NONE) |
| 18 | |
| 19 | /* |
| 20 | ** Output flags for the looks_like_utf8() and looks_like_utf16() routines used |
| 21 | ** to convey status information about the blob content. |
| 22 | */ |
| 23 | #define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */ |
| 24 | #define LOOK_NUL ((int)0x00000001) /* One or more Nfossil_isalnumne LOOK_NUL ((int)0x00000001) /* One or more Nutf8((blob), Lmight_be_sql(cCR tatus i10ormation a02LOOK_BINARY, 0) & LOOK_BI were LOOK_NUL ((int)0x00LONE_CR 20d ") || L(" or ") |
| 25 | /* ^^^^^ F tatus i10ormation a08/* One or more Nfossil_is were LOOK_NUL ((int)0x00LONE_LF ((int)0x00000010 ") |
| 26 | /* ^^^^^ no=08ere LOOK_NUL ((/LF paiLF ((int)0x00000010") || L20F ((int)0x00000010") || L("updaten 0; |
| 27 | #define L(GLOB1" andf8() an88((blob), LOO4f8() and looks_like_utf16() routines used |
| 28 | ** to 2onvey status i10ormation a8efine LOOK_NONE ((in04#define LOOK_NONE ((int)0x0000000020/* Nothing sp10ial was found. */ |
| 29 | #08fine LOOK_NUL ((int)0x00000001) /* One or more N20ssil_isalnumne LOOK_NUL ((int)0x00000001) /* One or more Nutf8((blob), Lz[i+n]!=0&&SQL. This is only aited context((blob), LOOK_BINARY, 0)define LOOK_CR [i+n]!=0&&SQL. This is onlCRLFere LOOK_ne or more Nfossil_isalnumne LOOK_NUL ((int)0x00000001) /* One or more Nutf8((blob), Lz[i+n]!=0&&SQL. This is only aited context((blob), LOOK_BINARY, 0) & LOOK_BINARY) != LOOK_NONE) |
| 30 | |
| 31 | /* |
| 32 | ** Output flags for the looks_like_utf8() and looks_like_utf16() routines used |
| 33 | ** to convey status information about the blob content. |
| 34 | */ |
| 35 | #define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */ |
| 36 | #define LOOK_NUL ((int)0x00000001) /* One or more Nfossil_isalnumne LOOK_NUL ((int)0x00000001) /* One or more Nutf8((blob), LRY, 0) & LOOK_BINARY) != LOOK_NONE) |
| 37 | |
| 38 | /* |
| 39 | ** Output flags for the looks_like_utf8() and looks_like_utf16() routines used |
| 40 | ** to convey status information about the blob content. |
| 41 | */ |
| 42 | #define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */ |
| 43 | #define LOOK_NUL ((int)0x00000001) /* One or more Nfossil_isalnumne LOOK_NUL ((int)0x00000001) /* One or more Nutf8((blob), Lmight_be_sql(const char *zTxt){ |
| 44 | if( zTxt==0 || zTxt[0]==0 ) return 0; |
| 45 | #define L(GLOB) 0==sqlite3_strlike("%" GLOB "%",zTxt, '%') |
| 46 | return L(";") || L("'") |
| 47 | || L("select") || L("order") || L("drop") |
| 48 | || L(" and ") || L(" or ") |
| 49 | /* ^^^^^ noting that \n and \t should also be checked */ |
| 50 | || L("null") || L("delete") || L("update") |
| 51 | |;<num> Repeatest_looks_like_utflooks_like_utf_testshort *z = (unsigned short1]==0possible UTF-32. */ |
| 52 | if( z[0]z[0]==0xfffeutf8((blob), LOOK_BINARY, 0) & LOOK_BINARY) != LOOK_NONE) |
| 53 | |
| 54 | /* |
| 55 | ** Output flflags |= LOOK_CR; |
| 56 | F | flags |= LOOK_LF; | flags |= LOOK_CR;flags |= LOOK_CR; |
| 57 | F | flags |= LOOK_LF; | flags |= LOOK_CR;f8() and looks_like_utf16() roututf8((blob), LOOKf8() and looks_like_utf16() routines used |
| 58 | ** to convey status information about the blob content. |
| 59 | */ |
| 60 | #define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */ |
| 61 | #define LOOK_NUL ((int)0x00000001) /* One or more Nfossil_isalnumne LOOK_NUL ((int)0x00000001) /* One or more Nutf8((blobflags |= LOOK_CR;(blob), Lz[i+n]!=0&&SQL. This is only a |
| 62 | ** high-level check, not intended to be used for any application-level |
| 63 | ** logic other tMore chars, next char is--n>0() and flags |= LOOK_LF; | * to convey status informatiBF LOOK_BINARY) != nformationBF LOOK_BINARY) != LOO((int)0x00000000) /* NothingBF LOOK_BINARY) != int)0x0000BF LOOK_BINARY) != LOOK ((int)0x00000001) /* One BF LOOK_BINARY) != ),flags |= LOOK_CR; |
| 64 | K_CR CRLFurn 0; |
| 65 | #define L(GLOB) 0=LF (rop") |
| 66 | || L(" andf8() an88((blob), LOOKf8() and looks_like_utf16() routines used |
| 67 | ** to convey status i10ormation about the blob content. |
| 68 | */ |
| 69 | #define LOOK_NONE ((int)0x0000000020More chars, next char is0/* Nothing special was found. */ |
| 70 | #define LOOK_NUL , c2; |
| 71 | if( c2>=0xC0 ){ |
| 72 | *def = &lb_tab[(2*c2)-0x180]; |
| 73 | if( c2>=0xe80 ){ |
| 74 | if( ((c2<0xc2) || (c2>=0xf4) || ((c&0xc0)!=0x80)) && |
| 75 | (((c2!=0xf4) || (c>=0x90)) &c = (c2 >= 0xe0) ? (c2<<1)+1 : ' '|flags |= LOOK_CR; |
| 76 | intended to be used for any application-level |
| 77 | ** logic other than in defense against spiders F | flags |= LOOK_LF; | * to convey status informat** to convey status information about the blob content. |
| 78 | */ |
| 79 | #define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */ |
| 80 | #define LOOK_NUL ((int)0x00000001) /* One or more Nfossil_isalnumne LOOK_NUL ((int)0x00000001) /* One or more Nutf8((blob), Lz[i+n]!=0&&SQL. This is only a |
| 81 | ** high-level check, not intended to be used for any application-level |
| 82 | ** logic other than in defense against spiders in limited context((blob), LOOK_BINARY, 0) & LOOK_BINARY) != LOOK_NONE) |
| 83 | |
| 84 | /* |
| 85 | ** Output flags for the looks_like_utf8() and looks_like_utf16() routines used |
| 86 | ** to convey status information about the blob content. |
| 87 | */ |
| 88 | #define LOOK_NONE ((int)0((blob), LOOK_BINARY, 0) & LO{ |
| 89 | *def || (c> ){ |
| 90 | return 1 }c>=0x8tf8((blob), LOOK_BINARY, 0) & LOOK_BINARY) != LOOK_NONE) |
| 91 | |
| 92 | /* |
| 93 | ** Output flags for the looks_like_utf8() and looks_like_utf16() routines used |
| 94 | ** to convey status information about the blob content. |
| 95 | */ |
| 96 | #define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */ |
| 97 | #define LOOK_NUL ((int)0x00000001) /* One or more Nfossil_isalnumne LOOK_NUL ((int)0x00000001) /* One or more Nutf8((blob), Lz[i+n]!=0&&SQL. This is only a |
| 98 | ** high-level check, not intended to be used for any application-level |
| 99 | ** logic other than in defense against spiders in limited context((blob), LOOK_BINARY, 0) & LOOK_BINARY) != LOOK_NONE) |
| 100 | |
| 101 | /* |
| 102 | ** Output flags for the looks_like_utf8() and looks_like_utf16() routines used |
| 103 | ** to convey status information about the blob content. |
| 104 | */ |
| 105 | #define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */ |
| 106 | #define LOOK_NUL ((int)0x00000001) /* One or more Nfossil_isalnumne LOOKY, 0) & LOOK_BINARY) }utf8((blob), LOOKK_BINARY, 0) & LOOK_BINARY) != LOOK_NONE) |
| 107 | |
| 108 | /* |
| 109 | ** Output flags for the looks_like_utf8() and looks_like_utf16() routines used |
| 110 | ** to convey status information about the blob content. |
| 111 | */ |
| 112 | #define LOOK_NONE ((int)0x00000000) /* Nothing special was found. */ |
| 113 | #define LOOK_NUL ((int)0x00000001) /* One or more Nfossil_isalnumne LOOK_NUL ((int)0x00000001) /* One or more Nutf8((blob), Lz[i+n]!=0&&SQL. This is o1if( flags&stopFlags ) break; |
| 114 | n -= sizeof(WCHAR_T); |
| 115 | if( n< break/*bRevUnicodefUtf16((int)0x00000000) utf8((blob), LOOK_BINARY, 0) & LfUnicode = 0; |
| 116 | }else{ |
| 117 | &bRevUnicode) || fForceUtEF, 0xBB, 0xBFlookFlags = fUnicode ? : |
| 118 | und. */ |
| 119 | #define |
+12
-2
| --- src/main.mk | ||
| +++ src/main.mk | ||
| @@ -67,10 +67,11 @@ | ||
| 67 | 67 | $(SRCDIR)/json_timeline.c \ |
| 68 | 68 | $(SRCDIR)/json_user.c \ |
| 69 | 69 | $(SRCDIR)/json_wiki.c \ |
| 70 | 70 | $(SRCDIR)/leaf.c \ |
| 71 | 71 | $(SRCDIR)/login.c \ |
| 72 | + $(SRCDIR)/lookslike.c \ | |
| 72 | 73 | $(SRCDIR)/main.c \ |
| 73 | 74 | $(SRCDIR)/manifest.c \ |
| 74 | 75 | $(SRCDIR)/markdown.c \ |
| 75 | 76 | $(SRCDIR)/markdown_html.c \ |
| 76 | 77 | $(SRCDIR)/md5.c \ |
| @@ -175,10 +176,11 @@ | ||
| 175 | 176 | $(OBJDIR)/json_timeline_.c \ |
| 176 | 177 | $(OBJDIR)/json_user_.c \ |
| 177 | 178 | $(OBJDIR)/json_wiki_.c \ |
| 178 | 179 | $(OBJDIR)/leaf_.c \ |
| 179 | 180 | $(OBJDIR)/login_.c \ |
| 181 | + $(OBJDIR)/lookslike_.c \ | |
| 180 | 182 | $(OBJDIR)/main_.c \ |
| 181 | 183 | $(OBJDIR)/manifest_.c \ |
| 182 | 184 | $(OBJDIR)/markdown_.c \ |
| 183 | 185 | $(OBJDIR)/markdown_html_.c \ |
| 184 | 186 | $(OBJDIR)/md5_.c \ |
| @@ -283,10 +285,11 @@ | ||
| 283 | 285 | $(OBJDIR)/json_timeline.o \ |
| 284 | 286 | $(OBJDIR)/json_user.o \ |
| 285 | 287 | $(OBJDIR)/json_wiki.o \ |
| 286 | 288 | $(OBJDIR)/leaf.o \ |
| 287 | 289 | $(OBJDIR)/login.o \ |
| 290 | + $(OBJDIR)/lookslike.o \ | |
| 288 | 291 | $(OBJDIR)/main.o \ |
| 289 | 292 | $(OBJDIR)/manifest.o \ |
| 290 | 293 | $(OBJDIR)/markdown.o \ |
| 291 | 294 | $(OBJDIR)/markdown_html.o \ |
| 292 | 295 | $(OBJDIR)/md5.o \ |
| @@ -402,11 +405,11 @@ | ||
| 402 | 405 | |
| 403 | 406 | |
| 404 | 407 | $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex |
| 405 | 408 | $(OBJDIR)/mkindex $(TRANS_SRC) >$@ |
| 406 | 409 | $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h |
| 407 | - $(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)/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 | |
| 410 | + $(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 | |
| 408 | 411 | touch $(OBJDIR)/headers |
| 409 | 412 | $(OBJDIR)/headers: Makefile |
| 410 | 413 | $(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 |
| 411 | 414 | Makefile: |
| 412 | 415 | $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate |
| @@ -792,10 +795,17 @@ | ||
| 792 | 795 | |
| 793 | 796 | $(OBJDIR)/login.o: $(OBJDIR)/login_.c $(OBJDIR)/login.h $(SRCDIR)/config.h |
| 794 | 797 | $(XTCC) -o $(OBJDIR)/login.o -c $(OBJDIR)/login_.c |
| 795 | 798 | |
| 796 | 799 | $(OBJDIR)/login.h: $(OBJDIR)/headers |
| 800 | +$(OBJDIR)/lookslike_.c: $(SRCDIR)/lookslike.c $(OBJDIR)/translate | |
| 801 | + $(OBJDIR)/translate $(SRCDIR)/lookslike.c >$(OBJDIR)/lookslike_.c | |
| 802 | + | |
| 803 | +$(OBJDIR)/lookslike.o: $(OBJDIR)/lookslike_.c $(OBJDIR)/lookslike.h $(SRCDIR)/config.h | |
| 804 | + $(XTCC) -o $(OBJDIR)/lookslike.o -c $(OBJDIR)/lookslike_.c | |
| 805 | + | |
| 806 | +$(OBJDIR)/lookslike.h: $(OBJDIR)/headers | |
| 797 | 807 | $(OBJDIR)/main_.c: $(SRCDIR)/main.c $(OBJDIR)/translate |
| 798 | 808 | $(OBJDIR)/translate $(SRCDIR)/main.c >$(OBJDIR)/main_.c |
| 799 | 809 | |
| 800 | 810 | $(OBJDIR)/main.o: $(OBJDIR)/main_.c $(OBJDIR)/main.h $(OBJDIR)/page_index.h $(SRCDIR)/config.h |
| 801 | 811 | $(XTCC) -o $(OBJDIR)/main.o -c $(OBJDIR)/main_.c |
| @@ -1153,11 +1163,11 @@ | ||
| 1153 | 1163 | $(OBJDIR)/zip.h: $(OBJDIR)/headers |
| 1154 | 1164 | $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c |
| 1155 | 1165 | $(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 |
| 1156 | 1166 | |
| 1157 | 1167 | $(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h |
| 1158 | - $(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o | |
| 1168 | + $(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -Dsqlite3_strglob=strglob -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o | |
| 1159 | 1169 | |
| 1160 | 1170 | $(OBJDIR)/th.o: $(SRCDIR)/th.c |
| 1161 | 1171 | $(XTCC) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o |
| 1162 | 1172 | |
| 1163 | 1173 | $(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c |
| 1164 | 1174 |
| --- src/main.mk | |
| +++ src/main.mk | |
| @@ -67,10 +67,11 @@ | |
| 67 | $(SRCDIR)/json_timeline.c \ |
| 68 | $(SRCDIR)/json_user.c \ |
| 69 | $(SRCDIR)/json_wiki.c \ |
| 70 | $(SRCDIR)/leaf.c \ |
| 71 | $(SRCDIR)/login.c \ |
| 72 | $(SRCDIR)/main.c \ |
| 73 | $(SRCDIR)/manifest.c \ |
| 74 | $(SRCDIR)/markdown.c \ |
| 75 | $(SRCDIR)/markdown_html.c \ |
| 76 | $(SRCDIR)/md5.c \ |
| @@ -175,10 +176,11 @@ | |
| 175 | $(OBJDIR)/json_timeline_.c \ |
| 176 | $(OBJDIR)/json_user_.c \ |
| 177 | $(OBJDIR)/json_wiki_.c \ |
| 178 | $(OBJDIR)/leaf_.c \ |
| 179 | $(OBJDIR)/login_.c \ |
| 180 | $(OBJDIR)/main_.c \ |
| 181 | $(OBJDIR)/manifest_.c \ |
| 182 | $(OBJDIR)/markdown_.c \ |
| 183 | $(OBJDIR)/markdown_html_.c \ |
| 184 | $(OBJDIR)/md5_.c \ |
| @@ -283,10 +285,11 @@ | |
| 283 | $(OBJDIR)/json_timeline.o \ |
| 284 | $(OBJDIR)/json_user.o \ |
| 285 | $(OBJDIR)/json_wiki.o \ |
| 286 | $(OBJDIR)/leaf.o \ |
| 287 | $(OBJDIR)/login.o \ |
| 288 | $(OBJDIR)/main.o \ |
| 289 | $(OBJDIR)/manifest.o \ |
| 290 | $(OBJDIR)/markdown.o \ |
| 291 | $(OBJDIR)/markdown_html.o \ |
| 292 | $(OBJDIR)/md5.o \ |
| @@ -402,11 +405,11 @@ | |
| 402 | |
| 403 | |
| 404 | $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex |
| 405 | $(OBJDIR)/mkindex $(TRANS_SRC) >$@ |
| 406 | $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h |
| 407 | $(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)/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 |
| 408 | touch $(OBJDIR)/headers |
| 409 | $(OBJDIR)/headers: Makefile |
| 410 | $(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 |
| 411 | Makefile: |
| 412 | $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate |
| @@ -792,10 +795,17 @@ | |
| 792 | |
| 793 | $(OBJDIR)/login.o: $(OBJDIR)/login_.c $(OBJDIR)/login.h $(SRCDIR)/config.h |
| 794 | $(XTCC) -o $(OBJDIR)/login.o -c $(OBJDIR)/login_.c |
| 795 | |
| 796 | $(OBJDIR)/login.h: $(OBJDIR)/headers |
| 797 | $(OBJDIR)/main_.c: $(SRCDIR)/main.c $(OBJDIR)/translate |
| 798 | $(OBJDIR)/translate $(SRCDIR)/main.c >$(OBJDIR)/main_.c |
| 799 | |
| 800 | $(OBJDIR)/main.o: $(OBJDIR)/main_.c $(OBJDIR)/main.h $(OBJDIR)/page_index.h $(SRCDIR)/config.h |
| 801 | $(XTCC) -o $(OBJDIR)/main.o -c $(OBJDIR)/main_.c |
| @@ -1153,11 +1163,11 @@ | |
| 1153 | $(OBJDIR)/zip.h: $(OBJDIR)/headers |
| 1154 | $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c |
| 1155 | $(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 |
| 1156 | |
| 1157 | $(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h |
| 1158 | $(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o |
| 1159 | |
| 1160 | $(OBJDIR)/th.o: $(SRCDIR)/th.c |
| 1161 | $(XTCC) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o |
| 1162 | |
| 1163 | $(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c |
| 1164 |
| --- src/main.mk | |
| +++ src/main.mk | |
| @@ -67,10 +67,11 @@ | |
| 67 | $(SRCDIR)/json_timeline.c \ |
| 68 | $(SRCDIR)/json_user.c \ |
| 69 | $(SRCDIR)/json_wiki.c \ |
| 70 | $(SRCDIR)/leaf.c \ |
| 71 | $(SRCDIR)/login.c \ |
| 72 | $(SRCDIR)/lookslike.c \ |
| 73 | $(SRCDIR)/main.c \ |
| 74 | $(SRCDIR)/manifest.c \ |
| 75 | $(SRCDIR)/markdown.c \ |
| 76 | $(SRCDIR)/markdown_html.c \ |
| 77 | $(SRCDIR)/md5.c \ |
| @@ -175,10 +176,11 @@ | |
| 176 | $(OBJDIR)/json_timeline_.c \ |
| 177 | $(OBJDIR)/json_user_.c \ |
| 178 | $(OBJDIR)/json_wiki_.c \ |
| 179 | $(OBJDIR)/leaf_.c \ |
| 180 | $(OBJDIR)/login_.c \ |
| 181 | $(OBJDIR)/lookslike_.c \ |
| 182 | $(OBJDIR)/main_.c \ |
| 183 | $(OBJDIR)/manifest_.c \ |
| 184 | $(OBJDIR)/markdown_.c \ |
| 185 | $(OBJDIR)/markdown_html_.c \ |
| 186 | $(OBJDIR)/md5_.c \ |
| @@ -283,10 +285,11 @@ | |
| 285 | $(OBJDIR)/json_timeline.o \ |
| 286 | $(OBJDIR)/json_user.o \ |
| 287 | $(OBJDIR)/json_wiki.o \ |
| 288 | $(OBJDIR)/leaf.o \ |
| 289 | $(OBJDIR)/login.o \ |
| 290 | $(OBJDIR)/lookslike.o \ |
| 291 | $(OBJDIR)/main.o \ |
| 292 | $(OBJDIR)/manifest.o \ |
| 293 | $(OBJDIR)/markdown.o \ |
| 294 | $(OBJDIR)/markdown_html.o \ |
| 295 | $(OBJDIR)/md5.o \ |
| @@ -402,11 +405,11 @@ | |
| 405 | |
| 406 | |
| 407 | $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex |
| 408 | $(OBJDIR)/mkindex $(TRANS_SRC) >$@ |
| 409 | $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h |
| 410 | $(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 |
| 411 | touch $(OBJDIR)/headers |
| 412 | $(OBJDIR)/headers: Makefile |
| 413 | $(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 |
| 414 | Makefile: |
| 415 | $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate |
| @@ -792,10 +795,17 @@ | |
| 795 | |
| 796 | $(OBJDIR)/login.o: $(OBJDIR)/login_.c $(OBJDIR)/login.h $(SRCDIR)/config.h |
| 797 | $(XTCC) -o $(OBJDIR)/login.o -c $(OBJDIR)/login_.c |
| 798 | |
| 799 | $(OBJDIR)/login.h: $(OBJDIR)/headers |
| 800 | $(OBJDIR)/lookslike_.c: $(SRCDIR)/lookslike.c $(OBJDIR)/translate |
| 801 | $(OBJDIR)/translate $(SRCDIR)/lookslike.c >$(OBJDIR)/lookslike_.c |
| 802 | |
| 803 | $(OBJDIR)/lookslike.o: $(OBJDIR)/lookslike_.c $(OBJDIR)/lookslike.h $(SRCDIR)/config.h |
| 804 | $(XTCC) -o $(OBJDIR)/lookslike.o -c $(OBJDIR)/lookslike_.c |
| 805 | |
| 806 | $(OBJDIR)/lookslike.h: $(OBJDIR)/headers |
| 807 | $(OBJDIR)/main_.c: $(SRCDIR)/main.c $(OBJDIR)/translate |
| 808 | $(OBJDIR)/translate $(SRCDIR)/main.c >$(OBJDIR)/main_.c |
| 809 | |
| 810 | $(OBJDIR)/main.o: $(OBJDIR)/main_.c $(OBJDIR)/main.h $(OBJDIR)/page_index.h $(SRCDIR)/config.h |
| 811 | $(XTCC) -o $(OBJDIR)/main.o -c $(OBJDIR)/main_.c |
| @@ -1153,11 +1163,11 @@ | |
| 1163 | $(OBJDIR)/zip.h: $(OBJDIR)/headers |
| 1164 | $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c |
| 1165 | $(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 |
| 1166 | |
| 1167 | $(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h |
| 1168 | $(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -Dsqlite3_strglob=strglob -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o |
| 1169 | |
| 1170 | $(OBJDIR)/th.o: $(SRCDIR)/th.c |
| 1171 | $(XTCC) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o |
| 1172 | |
| 1173 | $(OBJDIR)/th_lang.o: $(SRCDIR)/th_lang.c |
| 1174 |
+2
| --- src/makemake.tcl | ||
| +++ src/makemake.tcl | ||
| @@ -70,10 +70,11 @@ | ||
| 70 | 70 | json_timeline |
| 71 | 71 | json_user |
| 72 | 72 | json_wiki |
| 73 | 73 | leaf |
| 74 | 74 | login |
| 75 | + lookslike | |
| 75 | 76 | main |
| 76 | 77 | manifest |
| 77 | 78 | markdown |
| 78 | 79 | markdown_html |
| 79 | 80 | md5 |
| @@ -296,10 +297,11 @@ | ||
| 296 | 297 | writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n" |
| 297 | 298 | |
| 298 | 299 | writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h" |
| 299 | 300 | set opt {-Dmain=sqlite3_shell} |
| 300 | 301 | append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1" |
| 302 | +append opt " -Dsqlite3_strglob=strglob" | |
| 301 | 303 | writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n" |
| 302 | 304 | |
| 303 | 305 | writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c" |
| 304 | 306 | writeln "\t\$(XTCC) -c \$(SRCDIR)/th.c -o \$(OBJDIR)/th.o\n" |
| 305 | 307 | |
| 306 | 308 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -70,10 +70,11 @@ | |
| 70 | json_timeline |
| 71 | json_user |
| 72 | json_wiki |
| 73 | leaf |
| 74 | login |
| 75 | main |
| 76 | manifest |
| 77 | markdown |
| 78 | markdown_html |
| 79 | md5 |
| @@ -296,10 +297,11 @@ | |
| 296 | writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n" |
| 297 | |
| 298 | writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h" |
| 299 | set opt {-Dmain=sqlite3_shell} |
| 300 | append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1" |
| 301 | writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n" |
| 302 | |
| 303 | writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c" |
| 304 | writeln "\t\$(XTCC) -c \$(SRCDIR)/th.c -o \$(OBJDIR)/th.o\n" |
| 305 | |
| 306 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -70,10 +70,11 @@ | |
| 70 | json_timeline |
| 71 | json_user |
| 72 | json_wiki |
| 73 | leaf |
| 74 | login |
| 75 | lookslike |
| 76 | main |
| 77 | manifest |
| 78 | markdown |
| 79 | markdown_html |
| 80 | md5 |
| @@ -296,10 +297,11 @@ | |
| 297 | writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n" |
| 298 | |
| 299 | writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h" |
| 300 | set opt {-Dmain=sqlite3_shell} |
| 301 | append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1" |
| 302 | append opt " -Dsqlite3_strglob=strglob" |
| 303 | writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n" |
| 304 | |
| 305 | writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c" |
| 306 | writeln "\t\$(XTCC) -c \$(SRCDIR)/th.c -o \$(OBJDIR)/th.o\n" |
| 307 | |
| 308 |
+23
-4
| --- src/merge3.c | ||
| +++ src/merge3.c | ||
| @@ -340,16 +340,35 @@ | ||
| 340 | 340 | blob_reset(&file); |
| 341 | 341 | return rc; |
| 342 | 342 | } |
| 343 | 343 | |
| 344 | 344 | /* |
| 345 | -** COMMAND: test-3-way-merge | |
| 345 | +** COMMAND: 3-way-merge* | |
| 346 | +** | |
| 347 | +** Usage: %fossil 3-way-merge BASELINE V1 V2 MERGED | |
| 348 | +** | |
| 349 | +** Inputs are files BASELINE, V1, and V2. The file MERGED is generated | |
| 350 | +** as output. | |
| 351 | +** | |
| 352 | +** BASELINE is a common ancestor of two files V1 and V2 that have diverging | |
| 353 | +** edits. The generated output file MERGED is the combination of all | |
| 354 | +** changes in both V1 and V2. | |
| 355 | +** | |
| 356 | +** This command has no effect on the Fossil repository. It is a utility | |
| 357 | +** command made available for the convenience of users. This command can | |
| 358 | +** be used, for example, to help import changes from an upstream project. | |
| 346 | 359 | ** |
| 347 | -** Usage: %fossil test-3-way-merge PIVOT V1 V2 MERGED | |
| 360 | +** Suppose an upstream project has a file named "Xup.c" which is imported | |
| 361 | +** with modifications to the local project as "Xlocal.c". Suppose further | |
| 362 | +** that the "Xbase.c" is an exact copy of the last imported "Xup.c". | |
| 363 | +** Then to import the latest "Xup.c" while preserving all the local changes: | |
| 348 | 364 | ** |
| 349 | -** Combine change in going from PIVOT->VERSION1 with the change going | |
| 350 | -** from PIVOT->VERSION2 and write the combined changes into MERGED. | |
| 365 | +** fossil 3-way-merge Xbase.c Xlocal.c Xup.c Xlocal.c | |
| 366 | +** cp Xup.c Xbase.c | |
| 367 | +** # Verify that everything still works | |
| 368 | +** fossil commit | |
| 369 | +** | |
| 351 | 370 | */ |
| 352 | 371 | void delta_3waymerge_cmd(void){ |
| 353 | 372 | Blob pivot, v1, v2, merged; |
| 354 | 373 | if( g.argc!=6 ){ |
| 355 | 374 | usage("PIVOT V1 V2 MERGED"); |
| 356 | 375 |
| --- src/merge3.c | |
| +++ src/merge3.c | |
| @@ -340,16 +340,35 @@ | |
| 340 | blob_reset(&file); |
| 341 | return rc; |
| 342 | } |
| 343 | |
| 344 | /* |
| 345 | ** COMMAND: test-3-way-merge |
| 346 | ** |
| 347 | ** Usage: %fossil test-3-way-merge PIVOT V1 V2 MERGED |
| 348 | ** |
| 349 | ** Combine change in going from PIVOT->VERSION1 with the change going |
| 350 | ** from PIVOT->VERSION2 and write the combined changes into MERGED. |
| 351 | */ |
| 352 | void delta_3waymerge_cmd(void){ |
| 353 | Blob pivot, v1, v2, merged; |
| 354 | if( g.argc!=6 ){ |
| 355 | usage("PIVOT V1 V2 MERGED"); |
| 356 |
| --- src/merge3.c | |
| +++ src/merge3.c | |
| @@ -340,16 +340,35 @@ | |
| 340 | blob_reset(&file); |
| 341 | return rc; |
| 342 | } |
| 343 | |
| 344 | /* |
| 345 | ** COMMAND: 3-way-merge* |
| 346 | ** |
| 347 | ** Usage: %fossil 3-way-merge BASELINE V1 V2 MERGED |
| 348 | ** |
| 349 | ** Inputs are files BASELINE, V1, and V2. The file MERGED is generated |
| 350 | ** as output. |
| 351 | ** |
| 352 | ** BASELINE is a common ancestor of two files V1 and V2 that have diverging |
| 353 | ** edits. The generated output file MERGED is the combination of all |
| 354 | ** changes in both V1 and V2. |
| 355 | ** |
| 356 | ** This command has no effect on the Fossil repository. It is a utility |
| 357 | ** command made available for the convenience of users. This command can |
| 358 | ** be used, for example, to help import changes from an upstream project. |
| 359 | ** |
| 360 | ** Suppose an upstream project has a file named "Xup.c" which is imported |
| 361 | ** with modifications to the local project as "Xlocal.c". Suppose further |
| 362 | ** that the "Xbase.c" is an exact copy of the last imported "Xup.c". |
| 363 | ** Then to import the latest "Xup.c" while preserving all the local changes: |
| 364 | ** |
| 365 | ** fossil 3-way-merge Xbase.c Xlocal.c Xup.c Xlocal.c |
| 366 | ** cp Xup.c Xbase.c |
| 367 | ** # Verify that everything still works |
| 368 | ** fossil commit |
| 369 | ** |
| 370 | */ |
| 371 | void delta_3waymerge_cmd(void){ |
| 372 | Blob pivot, v1, v2, merged; |
| 373 | if( g.argc!=6 ){ |
| 374 | usage("PIVOT V1 V2 MERGED"); |
| 375 |
+29
-7
| --- src/search.c | ||
| +++ src/search.c | ||
| @@ -166,20 +166,35 @@ | ||
| 166 | 166 | |
| 167 | 167 | /* |
| 168 | 168 | ** Testing the search function. |
| 169 | 169 | ** |
| 170 | 170 | ** COMMAND: search* |
| 171 | -** %fossil search pattern... | |
| 171 | +** %fossil search [-all|-a] [-limit|-n #] pattern... | |
| 172 | +** | |
| 173 | +** Search for timeline entries matching all words | |
| 174 | +** provided on the command line. Whole-word matches | |
| 175 | +** scope more highly than partial matches. | |
| 172 | 176 | ** |
| 173 | -** Search for timeline entries matching the pattern. | |
| 177 | +** Outputs, by default, some top-N fraction of the | |
| 178 | +** results. The -all option can be used to output | |
| 179 | +** all matches, regardless of their search score. | |
| 180 | +** -limit can be used to limit the number of entries | |
| 181 | +** returned. | |
| 174 | 182 | */ |
| 175 | 183 | void search_cmd(void){ |
| 176 | 184 | Search *p; |
| 177 | 185 | Blob pattern; |
| 178 | 186 | int i; |
| 187 | + Blob sql = empty_blob; | |
| 179 | 188 | Stmt q; |
| 180 | 189 | int iBest; |
| 190 | + char fAll = NULL != find_option("all", "a", 0); /* If set, do not lop | |
| 191 | + off the end of the | |
| 192 | + results. */ | |
| 193 | + char const * zLimit = find_option("limit","n",1); | |
| 194 | + int const nLimit = zLimit ? atoi(zLimit) : -1; /* Max number of entries | |
| 195 | + to list */ | |
| 181 | 196 | |
| 182 | 197 | db_must_be_within_tree(); |
| 183 | 198 | if( g.argc<2 ) return; |
| 184 | 199 | blob_init(&pattern, g.argv[2], -1); |
| 185 | 200 | for(i=3; i<g.argc; i++){ |
| @@ -198,13 +213,20 @@ | ||
| 198 | 213 | " score(coalesce(ecomment,comment)) AS y" |
| 199 | 214 | " FROM event, blob" |
| 200 | 215 | " WHERE blob.rid=event.objid AND y>0;" |
| 201 | 216 | ); |
| 202 | 217 | iBest = db_int(0, "SELECT max(x) FROM srch"); |
| 203 | - db_prepare(&q, | |
| 204 | - "SELECT rid, uuid, date, comment, 0, 0 FROM srch" | |
| 205 | - " WHERE x>%d ORDER BY x DESC, date DESC", | |
| 206 | - iBest/3 | |
| 207 | - ); | |
| 218 | + blob_append(&sql, | |
| 219 | + "SELECT rid, uuid, date, comment, 0, 0 FROM srch " | |
| 220 | + "WHERE 1 ", -1); | |
| 221 | + if(!fAll){ | |
| 222 | + blob_appendf(&sql,"AND x>%d ", iBest/3); | |
| 223 | + } | |
| 224 | + blob_append(&sql, "ORDER BY x DESC, date DESC ", -1); | |
| 225 | + if(nLimit>0){ | |
| 226 | + blob_appendf(&sql, "LIMIT %d", nLimit); | |
| 227 | + } | |
| 228 | + db_prepare(&q, blob_str(&sql)); | |
| 229 | + blob_reset(&sql); | |
| 208 | 230 | print_timeline(&q, 1000, 0); |
| 209 | 231 | db_finalize(&q); |
| 210 | 232 | } |
| 211 | 233 |
| --- src/search.c | |
| +++ src/search.c | |
| @@ -166,20 +166,35 @@ | |
| 166 | |
| 167 | /* |
| 168 | ** Testing the search function. |
| 169 | ** |
| 170 | ** COMMAND: search* |
| 171 | ** %fossil search pattern... |
| 172 | ** |
| 173 | ** Search for timeline entries matching the pattern. |
| 174 | */ |
| 175 | void search_cmd(void){ |
| 176 | Search *p; |
| 177 | Blob pattern; |
| 178 | int i; |
| 179 | Stmt q; |
| 180 | int iBest; |
| 181 | |
| 182 | db_must_be_within_tree(); |
| 183 | if( g.argc<2 ) return; |
| 184 | blob_init(&pattern, g.argv[2], -1); |
| 185 | for(i=3; i<g.argc; i++){ |
| @@ -198,13 +213,20 @@ | |
| 198 | " score(coalesce(ecomment,comment)) AS y" |
| 199 | " FROM event, blob" |
| 200 | " WHERE blob.rid=event.objid AND y>0;" |
| 201 | ); |
| 202 | iBest = db_int(0, "SELECT max(x) FROM srch"); |
| 203 | db_prepare(&q, |
| 204 | "SELECT rid, uuid, date, comment, 0, 0 FROM srch" |
| 205 | " WHERE x>%d ORDER BY x DESC, date DESC", |
| 206 | iBest/3 |
| 207 | ); |
| 208 | print_timeline(&q, 1000, 0); |
| 209 | db_finalize(&q); |
| 210 | } |
| 211 |
| --- src/search.c | |
| +++ src/search.c | |
| @@ -166,20 +166,35 @@ | |
| 166 | |
| 167 | /* |
| 168 | ** Testing the search function. |
| 169 | ** |
| 170 | ** COMMAND: search* |
| 171 | ** %fossil search [-all|-a] [-limit|-n #] pattern... |
| 172 | ** |
| 173 | ** Search for timeline entries matching all words |
| 174 | ** provided on the command line. Whole-word matches |
| 175 | ** scope more highly than partial matches. |
| 176 | ** |
| 177 | ** Outputs, by default, some top-N fraction of the |
| 178 | ** results. The -all option can be used to output |
| 179 | ** all matches, regardless of their search score. |
| 180 | ** -limit can be used to limit the number of entries |
| 181 | ** returned. |
| 182 | */ |
| 183 | void search_cmd(void){ |
| 184 | Search *p; |
| 185 | Blob pattern; |
| 186 | int i; |
| 187 | Blob sql = empty_blob; |
| 188 | Stmt q; |
| 189 | int iBest; |
| 190 | char fAll = NULL != find_option("all", "a", 0); /* If set, do not lop |
| 191 | off the end of the |
| 192 | results. */ |
| 193 | char const * zLimit = find_option("limit","n",1); |
| 194 | int const nLimit = zLimit ? atoi(zLimit) : -1; /* Max number of entries |
| 195 | to list */ |
| 196 | |
| 197 | db_must_be_within_tree(); |
| 198 | if( g.argc<2 ) return; |
| 199 | blob_init(&pattern, g.argv[2], -1); |
| 200 | for(i=3; i<g.argc; i++){ |
| @@ -198,13 +213,20 @@ | |
| 213 | " score(coalesce(ecomment,comment)) AS y" |
| 214 | " FROM event, blob" |
| 215 | " WHERE blob.rid=event.objid AND y>0;" |
| 216 | ); |
| 217 | iBest = db_int(0, "SELECT max(x) FROM srch"); |
| 218 | blob_append(&sql, |
| 219 | "SELECT rid, uuid, date, comment, 0, 0 FROM srch " |
| 220 | "WHERE 1 ", -1); |
| 221 | if(!fAll){ |
| 222 | blob_appendf(&sql,"AND x>%d ", iBest/3); |
| 223 | } |
| 224 | blob_append(&sql, "ORDER BY x DESC, date DESC ", -1); |
| 225 | if(nLimit>0){ |
| 226 | blob_appendf(&sql, "LIMIT %d", nLimit); |
| 227 | } |
| 228 | db_prepare(&q, blob_str(&sql)); |
| 229 | blob_reset(&sql); |
| 230 | print_timeline(&q, 1000, 0); |
| 231 | db_finalize(&q); |
| 232 | } |
| 233 |
+29
-29
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -197,62 +197,62 @@ | ||
| 197 | 197 | @ </td><td class="usetupColumnLayout"> |
| 198 | 198 | @ <span class="note">Notes:</span> |
| 199 | 199 | @ <ol> |
| 200 | 200 | @ <li><p>The permission flags are as follows:</p> |
| 201 | 201 | @ <table> |
| 202 | - @ <tr><td valign="top"><b>a</b></td> | |
| 202 | + @ <tr><th valign="top">a</th> | |
| 203 | 203 | @ <td><i>Admin:</i> Create and delete users</td></tr> |
| 204 | - @ <tr><td valign="top"><b>b</b></td> | |
| 204 | + @ <tr><th valign="top">b</th> | |
| 205 | 205 | @ <td><i>Attach:</i> Add attachments to wiki or tickets</td></tr> |
| 206 | - @ <tr><td valign="top"><b>c</b></td> | |
| 206 | + @ <tr><th valign="top">c</th> | |
| 207 | 207 | @ <td><i>Append-Tkt:</i> Append to tickets</td></tr> |
| 208 | - @ <tr><td valign="top"><b>d</b></td> | |
| 208 | + @ <tr><th valign="top">d</th> | |
| 209 | 209 | @ <td><i>Delete:</i> Delete wiki and tickets</td></tr> |
| 210 | - @ <tr><td valign="top"><b>e</b></td> | |
| 210 | + @ <tr><th valign="top">e</th> | |
| 211 | 211 | @ <td><i>Email:</i> View sensitive data such as EMail addresses</td></tr> |
| 212 | - @ <tr><td valign="top"><b>f</b></td> | |
| 212 | + @ <tr><th valign="top">f</th> | |
| 213 | 213 | @ <td><i>New-Wiki:</i> Create new wiki pages</td></tr> |
| 214 | - @ <tr><td valign="top"><b>g</b></td> | |
| 214 | + @ <tr><th valign="top">g</th> | |
| 215 | 215 | @ <td><i>Clone:</i> Clone the repository</td></tr> |
| 216 | - @ <tr><td valign="top"><b>h</b></td> | |
| 216 | + @ <tr><th valign="top">h</th> | |
| 217 | 217 | @ <td><i>Hyperlinks:</i> Show hyperlinks to detailed |
| 218 | 218 | @ repository history</td></tr> |
| 219 | - @ <tr><td valign="top"><b>i</b></td> | |
| 219 | + @ <tr><th valign="top">i</th> | |
| 220 | 220 | @ <td><i>Check-In:</i> Commit new versions in the repository</td></tr> |
| 221 | - @ <tr><td valign="top"><b>j</b></td> | |
| 221 | + @ <tr><th valign="top">j</th> | |
| 222 | 222 | @ <td><i>Read-Wiki:</i> View wiki pages</td></tr> |
| 223 | - @ <tr><td valign="top"><b>k</b></td> | |
| 223 | + @ <tr><th valign="top">k</th> | |
| 224 | 224 | @ <td><i>Write-Wiki:</i> Edit wiki pages</td></tr> |
| 225 | - @ <tr><td valign="top"><b>l</b></td> | |
| 225 | + @ <tr><th valign="top">l</th> | |
| 226 | 226 | @ <td><i>Mod-Wiki:</i> Moderator for wiki pages</td></tr> |
| 227 | - @ <tr><td valign="top"><b>m</b></td> | |
| 227 | + @ <tr><th valign="top">m</th> | |
| 228 | 228 | @ <td><i>Append-Wiki:</i> Append to wiki pages</td></tr> |
| 229 | - @ <tr><td valign="top"><b>n</b></td> | |
| 229 | + @ <tr><th valign="top">n</th> | |
| 230 | 230 | @ <td><i>New-Tkt:</i> Create new tickets</td></tr> |
| 231 | - @ <tr><td valign="top"><b>o</b></td> | |
| 231 | + @ <tr><th valign="top">o</th> | |
| 232 | 232 | @ <td><i>Check-Out:</i> Check out versions</td></tr> |
| 233 | - @ <tr><td valign="top"><b>p</b></td> | |
| 233 | + @ <tr><th valign="top">p</th> | |
| 234 | 234 | @ <td><i>Password:</i> Change your own password</td></tr> |
| 235 | - @ <tr><td valign="top"><b>q</b></td> | |
| 235 | + @ <tr><th valign="top">q</th> | |
| 236 | 236 | @ <td><i>Mod-Tkt:</i> Moderator for tickets</td></tr> |
| 237 | - @ <tr><td valign="top"><b>r</b></td> | |
| 237 | + @ <tr><th valign="top">r</th> | |
| 238 | 238 | @ <td><i>Read-Tkt:</i> View tickets</td></tr> |
| 239 | - @ <tr><td valign="top"><b>s</b></td> | |
| 239 | + @ <tr><th valign="top">s</th> | |
| 240 | 240 | @ <td><i>Setup/Super-user:</i> Setup and configure this website</td></tr> |
| 241 | - @ <tr><td valign="top"><b>t</b></td> | |
| 241 | + @ <tr><th valign="top">t</th> | |
| 242 | 242 | @ <td><i>Tkt-Report:</i> Create new bug summary reports</td></tr> |
| 243 | - @ <tr><td valign="top"><b>u</b></td> | |
| 243 | + @ <tr><th valign="top">u</th> | |
| 244 | 244 | @ <td><i>Reader:</i> Inherit privileges of |
| 245 | 245 | @ user <tt>reader</tt></td></tr> |
| 246 | - @ <tr><td valign="top"><b>v</b></td> | |
| 246 | + @ <tr><th valign="top">v</th> | |
| 247 | 247 | @ <td><i>Developer:</i> Inherit privileges of |
| 248 | 248 | @ user <tt>developer</tt></td></tr> |
| 249 | - @ <tr><td valign="top"><b>w</b></td> | |
| 249 | + @ <tr><th valign="top">w</th> | |
| 250 | 250 | @ <td><i>Write-Tkt:</i> Edit tickets</td></tr> |
| 251 | - @ <tr><td valign="top"><b>x</b></td> | |
| 251 | + @ <tr><th valign="top">x</th> | |
| 252 | 252 | @ <td><i>Private:</i> Push and/or pull private branches</td></tr> |
| 253 | - @ <tr><td valign="top"><b>z</b></td> | |
| 253 | + @ <tr><th valign="top">z</th> | |
| 254 | 254 | @ <td><i>Zip download:</i> Download a baseline via the |
| 255 | 255 | @ <tt>/zip</tt> URL even without |
| 256 | 256 | @ check<span class="capability">o</span>ut |
| 257 | 257 | @ and <span class="capability">h</span>istory permissions</td></tr> |
| 258 | 258 | @ </table> |
| @@ -1062,23 +1062,23 @@ | ||
| 1062 | 1062 | @ |
| 1063 | 1063 | @ <form action="%s(g.zTop)/setup_login_group" method="post"><div> |
| 1064 | 1064 | login_insert_csrf_secret(); |
| 1065 | 1065 | @ <blockquote><table border="0"> |
| 1066 | 1066 | @ |
| 1067 | - @ <tr><td align="right"><b>Repository filename in group to join:</b></td> | |
| 1067 | + @ <tr><th align="right">Repository filename in group to join:</th> | |
| 1068 | 1068 | @ <td width="5"></td><td> |
| 1069 | 1069 | @ <input type="text" size="50" value="%h(zRepo)" name="repo"></td></tr> |
| 1070 | 1070 | @ |
| 1071 | - @ <tr><td align="right"><b>Login on the above repo:</b></td> | |
| 1071 | + @ <tr><th align="right">Login on the above repo:</th> | |
| 1072 | 1072 | @ <td width="5"></td><td> |
| 1073 | 1073 | @ <input type="text" size="20" value="%h(zLogin)" name="login"></td></tr> |
| 1074 | 1074 | @ |
| 1075 | - @ <tr><td align="right"><b>Password:</b></td> | |
| 1075 | + @ <tr><th align="right">Password:</th> | |
| 1076 | 1076 | @ <td width="5"></td><td> |
| 1077 | 1077 | @ <input type="password" size="20" name="pw"></td></tr> |
| 1078 | 1078 | @ |
| 1079 | - @ <tr><td align="right"><b>Name of login-group:</b></td> | |
| 1079 | + @ <tr><th align="right">Name of login-group:</th> | |
| 1080 | 1080 | @ <td width="5"></td><td> |
| 1081 | 1081 | @ <input type="text" size="30" value="%h(zNewName)" name="newname"> |
| 1082 | 1082 | @ (only used if creating a new login-group).</td></tr> |
| 1083 | 1083 | @ |
| 1084 | 1084 | @ <tr><td colspan="3" align="center"> |
| 1085 | 1085 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -197,62 +197,62 @@ | |
| 197 | @ </td><td class="usetupColumnLayout"> |
| 198 | @ <span class="note">Notes:</span> |
| 199 | @ <ol> |
| 200 | @ <li><p>The permission flags are as follows:</p> |
| 201 | @ <table> |
| 202 | @ <tr><td valign="top"><b>a</b></td> |
| 203 | @ <td><i>Admin:</i> Create and delete users</td></tr> |
| 204 | @ <tr><td valign="top"><b>b</b></td> |
| 205 | @ <td><i>Attach:</i> Add attachments to wiki or tickets</td></tr> |
| 206 | @ <tr><td valign="top"><b>c</b></td> |
| 207 | @ <td><i>Append-Tkt:</i> Append to tickets</td></tr> |
| 208 | @ <tr><td valign="top"><b>d</b></td> |
| 209 | @ <td><i>Delete:</i> Delete wiki and tickets</td></tr> |
| 210 | @ <tr><td valign="top"><b>e</b></td> |
| 211 | @ <td><i>Email:</i> View sensitive data such as EMail addresses</td></tr> |
| 212 | @ <tr><td valign="top"><b>f</b></td> |
| 213 | @ <td><i>New-Wiki:</i> Create new wiki pages</td></tr> |
| 214 | @ <tr><td valign="top"><b>g</b></td> |
| 215 | @ <td><i>Clone:</i> Clone the repository</td></tr> |
| 216 | @ <tr><td valign="top"><b>h</b></td> |
| 217 | @ <td><i>Hyperlinks:</i> Show hyperlinks to detailed |
| 218 | @ repository history</td></tr> |
| 219 | @ <tr><td valign="top"><b>i</b></td> |
| 220 | @ <td><i>Check-In:</i> Commit new versions in the repository</td></tr> |
| 221 | @ <tr><td valign="top"><b>j</b></td> |
| 222 | @ <td><i>Read-Wiki:</i> View wiki pages</td></tr> |
| 223 | @ <tr><td valign="top"><b>k</b></td> |
| 224 | @ <td><i>Write-Wiki:</i> Edit wiki pages</td></tr> |
| 225 | @ <tr><td valign="top"><b>l</b></td> |
| 226 | @ <td><i>Mod-Wiki:</i> Moderator for wiki pages</td></tr> |
| 227 | @ <tr><td valign="top"><b>m</b></td> |
| 228 | @ <td><i>Append-Wiki:</i> Append to wiki pages</td></tr> |
| 229 | @ <tr><td valign="top"><b>n</b></td> |
| 230 | @ <td><i>New-Tkt:</i> Create new tickets</td></tr> |
| 231 | @ <tr><td valign="top"><b>o</b></td> |
| 232 | @ <td><i>Check-Out:</i> Check out versions</td></tr> |
| 233 | @ <tr><td valign="top"><b>p</b></td> |
| 234 | @ <td><i>Password:</i> Change your own password</td></tr> |
| 235 | @ <tr><td valign="top"><b>q</b></td> |
| 236 | @ <td><i>Mod-Tkt:</i> Moderator for tickets</td></tr> |
| 237 | @ <tr><td valign="top"><b>r</b></td> |
| 238 | @ <td><i>Read-Tkt:</i> View tickets</td></tr> |
| 239 | @ <tr><td valign="top"><b>s</b></td> |
| 240 | @ <td><i>Setup/Super-user:</i> Setup and configure this website</td></tr> |
| 241 | @ <tr><td valign="top"><b>t</b></td> |
| 242 | @ <td><i>Tkt-Report:</i> Create new bug summary reports</td></tr> |
| 243 | @ <tr><td valign="top"><b>u</b></td> |
| 244 | @ <td><i>Reader:</i> Inherit privileges of |
| 245 | @ user <tt>reader</tt></td></tr> |
| 246 | @ <tr><td valign="top"><b>v</b></td> |
| 247 | @ <td><i>Developer:</i> Inherit privileges of |
| 248 | @ user <tt>developer</tt></td></tr> |
| 249 | @ <tr><td valign="top"><b>w</b></td> |
| 250 | @ <td><i>Write-Tkt:</i> Edit tickets</td></tr> |
| 251 | @ <tr><td valign="top"><b>x</b></td> |
| 252 | @ <td><i>Private:</i> Push and/or pull private branches</td></tr> |
| 253 | @ <tr><td valign="top"><b>z</b></td> |
| 254 | @ <td><i>Zip download:</i> Download a baseline via the |
| 255 | @ <tt>/zip</tt> URL even without |
| 256 | @ check<span class="capability">o</span>ut |
| 257 | @ and <span class="capability">h</span>istory permissions</td></tr> |
| 258 | @ </table> |
| @@ -1062,23 +1062,23 @@ | |
| 1062 | @ |
| 1063 | @ <form action="%s(g.zTop)/setup_login_group" method="post"><div> |
| 1064 | login_insert_csrf_secret(); |
| 1065 | @ <blockquote><table border="0"> |
| 1066 | @ |
| 1067 | @ <tr><td align="right"><b>Repository filename in group to join:</b></td> |
| 1068 | @ <td width="5"></td><td> |
| 1069 | @ <input type="text" size="50" value="%h(zRepo)" name="repo"></td></tr> |
| 1070 | @ |
| 1071 | @ <tr><td align="right"><b>Login on the above repo:</b></td> |
| 1072 | @ <td width="5"></td><td> |
| 1073 | @ <input type="text" size="20" value="%h(zLogin)" name="login"></td></tr> |
| 1074 | @ |
| 1075 | @ <tr><td align="right"><b>Password:</b></td> |
| 1076 | @ <td width="5"></td><td> |
| 1077 | @ <input type="password" size="20" name="pw"></td></tr> |
| 1078 | @ |
| 1079 | @ <tr><td align="right"><b>Name of login-group:</b></td> |
| 1080 | @ <td width="5"></td><td> |
| 1081 | @ <input type="text" size="30" value="%h(zNewName)" name="newname"> |
| 1082 | @ (only used if creating a new login-group).</td></tr> |
| 1083 | @ |
| 1084 | @ <tr><td colspan="3" align="center"> |
| 1085 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -197,62 +197,62 @@ | |
| 197 | @ </td><td class="usetupColumnLayout"> |
| 198 | @ <span class="note">Notes:</span> |
| 199 | @ <ol> |
| 200 | @ <li><p>The permission flags are as follows:</p> |
| 201 | @ <table> |
| 202 | @ <tr><th valign="top">a</th> |
| 203 | @ <td><i>Admin:</i> Create and delete users</td></tr> |
| 204 | @ <tr><th valign="top">b</th> |
| 205 | @ <td><i>Attach:</i> Add attachments to wiki or tickets</td></tr> |
| 206 | @ <tr><th valign="top">c</th> |
| 207 | @ <td><i>Append-Tkt:</i> Append to tickets</td></tr> |
| 208 | @ <tr><th valign="top">d</th> |
| 209 | @ <td><i>Delete:</i> Delete wiki and tickets</td></tr> |
| 210 | @ <tr><th valign="top">e</th> |
| 211 | @ <td><i>Email:</i> View sensitive data such as EMail addresses</td></tr> |
| 212 | @ <tr><th valign="top">f</th> |
| 213 | @ <td><i>New-Wiki:</i> Create new wiki pages</td></tr> |
| 214 | @ <tr><th valign="top">g</th> |
| 215 | @ <td><i>Clone:</i> Clone the repository</td></tr> |
| 216 | @ <tr><th valign="top">h</th> |
| 217 | @ <td><i>Hyperlinks:</i> Show hyperlinks to detailed |
| 218 | @ repository history</td></tr> |
| 219 | @ <tr><th valign="top">i</th> |
| 220 | @ <td><i>Check-In:</i> Commit new versions in the repository</td></tr> |
| 221 | @ <tr><th valign="top">j</th> |
| 222 | @ <td><i>Read-Wiki:</i> View wiki pages</td></tr> |
| 223 | @ <tr><th valign="top">k</th> |
| 224 | @ <td><i>Write-Wiki:</i> Edit wiki pages</td></tr> |
| 225 | @ <tr><th valign="top">l</th> |
| 226 | @ <td><i>Mod-Wiki:</i> Moderator for wiki pages</td></tr> |
| 227 | @ <tr><th valign="top">m</th> |
| 228 | @ <td><i>Append-Wiki:</i> Append to wiki pages</td></tr> |
| 229 | @ <tr><th valign="top">n</th> |
| 230 | @ <td><i>New-Tkt:</i> Create new tickets</td></tr> |
| 231 | @ <tr><th valign="top">o</th> |
| 232 | @ <td><i>Check-Out:</i> Check out versions</td></tr> |
| 233 | @ <tr><th valign="top">p</th> |
| 234 | @ <td><i>Password:</i> Change your own password</td></tr> |
| 235 | @ <tr><th valign="top">q</th> |
| 236 | @ <td><i>Mod-Tkt:</i> Moderator for tickets</td></tr> |
| 237 | @ <tr><th valign="top">r</th> |
| 238 | @ <td><i>Read-Tkt:</i> View tickets</td></tr> |
| 239 | @ <tr><th valign="top">s</th> |
| 240 | @ <td><i>Setup/Super-user:</i> Setup and configure this website</td></tr> |
| 241 | @ <tr><th valign="top">t</th> |
| 242 | @ <td><i>Tkt-Report:</i> Create new bug summary reports</td></tr> |
| 243 | @ <tr><th valign="top">u</th> |
| 244 | @ <td><i>Reader:</i> Inherit privileges of |
| 245 | @ user <tt>reader</tt></td></tr> |
| 246 | @ <tr><th valign="top">v</th> |
| 247 | @ <td><i>Developer:</i> Inherit privileges of |
| 248 | @ user <tt>developer</tt></td></tr> |
| 249 | @ <tr><th valign="top">w</th> |
| 250 | @ <td><i>Write-Tkt:</i> Edit tickets</td></tr> |
| 251 | @ <tr><th valign="top">x</th> |
| 252 | @ <td><i>Private:</i> Push and/or pull private branches</td></tr> |
| 253 | @ <tr><th valign="top">z</th> |
| 254 | @ <td><i>Zip download:</i> Download a baseline via the |
| 255 | @ <tt>/zip</tt> URL even without |
| 256 | @ check<span class="capability">o</span>ut |
| 257 | @ and <span class="capability">h</span>istory permissions</td></tr> |
| 258 | @ </table> |
| @@ -1062,23 +1062,23 @@ | |
| 1062 | @ |
| 1063 | @ <form action="%s(g.zTop)/setup_login_group" method="post"><div> |
| 1064 | login_insert_csrf_secret(); |
| 1065 | @ <blockquote><table border="0"> |
| 1066 | @ |
| 1067 | @ <tr><th align="right">Repository filename in group to join:</th> |
| 1068 | @ <td width="5"></td><td> |
| 1069 | @ <input type="text" size="50" value="%h(zRepo)" name="repo"></td></tr> |
| 1070 | @ |
| 1071 | @ <tr><th align="right">Login on the above repo:</th> |
| 1072 | @ <td width="5"></td><td> |
| 1073 | @ <input type="text" size="20" value="%h(zLogin)" name="login"></td></tr> |
| 1074 | @ |
| 1075 | @ <tr><th align="right">Password:</th> |
| 1076 | @ <td width="5"></td><td> |
| 1077 | @ <input type="password" size="20" name="pw"></td></tr> |
| 1078 | @ |
| 1079 | @ <tr><th align="right">Name of login-group:</th> |
| 1080 | @ <td width="5"></td><td> |
| 1081 | @ <input type="text" size="30" value="%h(zNewName)" name="newname"> |
| 1082 | @ (only used if creating a new login-group).</td></tr> |
| 1083 | @ |
| 1084 | @ <tr><td colspan="3" align="center"> |
| 1085 |
+1
-3
| --- src/shell.c | ||
| +++ src/shell.c | ||
| @@ -1719,11 +1719,10 @@ | ||
| 1719 | 1719 | || (c=='\n' && pc==cQuote) |
| 1720 | 1720 | || (c=='\n' && pc=='\r' && p->n>2 && p->z[p->n-2]==cQuote) |
| 1721 | 1721 | || (c==EOF && pc==cQuote) |
| 1722 | 1722 | ){ |
| 1723 | 1723 | do{ p->n--; }while( p->z[p->n]!=cQuote ); |
| 1724 | - p->z[p->n] = 0; | |
| 1725 | 1724 | p->cTerm = c; |
| 1726 | 1725 | break; |
| 1727 | 1726 | } |
| 1728 | 1727 | if( pc==cQuote && c!='\r' ){ |
| 1729 | 1728 | fprintf(stderr, "%s:%d: unescaped %c character\n", |
| @@ -1730,11 +1729,10 @@ | ||
| 1730 | 1729 | p->zFile, p->nLine, cQuote); |
| 1731 | 1730 | } |
| 1732 | 1731 | if( c==EOF ){ |
| 1733 | 1732 | fprintf(stderr, "%s:%d: unterminated %c-quoted field\n", |
| 1734 | 1733 | p->zFile, startLine, cQuote); |
| 1735 | - p->z[p->n] = 0; | |
| 1736 | 1734 | p->cTerm = EOF; |
| 1737 | 1735 | break; |
| 1738 | 1736 | } |
| 1739 | 1737 | csv_append_char(p, c); |
| 1740 | 1738 | pc = c; |
| @@ -1746,13 +1744,13 @@ | ||
| 1746 | 1744 | } |
| 1747 | 1745 | if( c=='\n' ){ |
| 1748 | 1746 | p->nLine++; |
| 1749 | 1747 | if( p->n>1 && p->z[p->n-1]=='\r' ) p->n--; |
| 1750 | 1748 | } |
| 1751 | - p->z[p->n] = 0; | |
| 1752 | 1749 | p->cTerm = c; |
| 1753 | 1750 | } |
| 1751 | + if( p->z ) p->z[p->n] = 0; | |
| 1754 | 1752 | return p->z; |
| 1755 | 1753 | } |
| 1756 | 1754 | |
| 1757 | 1755 | /* |
| 1758 | 1756 | ** If an input line begins with "." then invoke this routine to |
| 1759 | 1757 |
| --- src/shell.c | |
| +++ src/shell.c | |
| @@ -1719,11 +1719,10 @@ | |
| 1719 | || (c=='\n' && pc==cQuote) |
| 1720 | || (c=='\n' && pc=='\r' && p->n>2 && p->z[p->n-2]==cQuote) |
| 1721 | || (c==EOF && pc==cQuote) |
| 1722 | ){ |
| 1723 | do{ p->n--; }while( p->z[p->n]!=cQuote ); |
| 1724 | p->z[p->n] = 0; |
| 1725 | p->cTerm = c; |
| 1726 | break; |
| 1727 | } |
| 1728 | if( pc==cQuote && c!='\r' ){ |
| 1729 | fprintf(stderr, "%s:%d: unescaped %c character\n", |
| @@ -1730,11 +1729,10 @@ | |
| 1730 | p->zFile, p->nLine, cQuote); |
| 1731 | } |
| 1732 | if( c==EOF ){ |
| 1733 | fprintf(stderr, "%s:%d: unterminated %c-quoted field\n", |
| 1734 | p->zFile, startLine, cQuote); |
| 1735 | p->z[p->n] = 0; |
| 1736 | p->cTerm = EOF; |
| 1737 | break; |
| 1738 | } |
| 1739 | csv_append_char(p, c); |
| 1740 | pc = c; |
| @@ -1746,13 +1744,13 @@ | |
| 1746 | } |
| 1747 | if( c=='\n' ){ |
| 1748 | p->nLine++; |
| 1749 | if( p->n>1 && p->z[p->n-1]=='\r' ) p->n--; |
| 1750 | } |
| 1751 | p->z[p->n] = 0; |
| 1752 | p->cTerm = c; |
| 1753 | } |
| 1754 | return p->z; |
| 1755 | } |
| 1756 | |
| 1757 | /* |
| 1758 | ** If an input line begins with "." then invoke this routine to |
| 1759 |
| --- src/shell.c | |
| +++ src/shell.c | |
| @@ -1719,11 +1719,10 @@ | |
| 1719 | || (c=='\n' && pc==cQuote) |
| 1720 | || (c=='\n' && pc=='\r' && p->n>2 && p->z[p->n-2]==cQuote) |
| 1721 | || (c==EOF && pc==cQuote) |
| 1722 | ){ |
| 1723 | do{ p->n--; }while( p->z[p->n]!=cQuote ); |
| 1724 | p->cTerm = c; |
| 1725 | break; |
| 1726 | } |
| 1727 | if( pc==cQuote && c!='\r' ){ |
| 1728 | fprintf(stderr, "%s:%d: unescaped %c character\n", |
| @@ -1730,11 +1729,10 @@ | |
| 1729 | p->zFile, p->nLine, cQuote); |
| 1730 | } |
| 1731 | if( c==EOF ){ |
| 1732 | fprintf(stderr, "%s:%d: unterminated %c-quoted field\n", |
| 1733 | p->zFile, startLine, cQuote); |
| 1734 | p->cTerm = EOF; |
| 1735 | break; |
| 1736 | } |
| 1737 | csv_append_char(p, c); |
| 1738 | pc = c; |
| @@ -1746,13 +1744,13 @@ | |
| 1744 | } |
| 1745 | if( c=='\n' ){ |
| 1746 | p->nLine++; |
| 1747 | if( p->n>1 && p->z[p->n-1]=='\r' ) p->n--; |
| 1748 | } |
| 1749 | p->cTerm = c; |
| 1750 | } |
| 1751 | if( p->z ) p->z[p->n] = 0; |
| 1752 | return p->z; |
| 1753 | } |
| 1754 | |
| 1755 | /* |
| 1756 | ** If an input line begins with "." then invoke this routine to |
| 1757 |
+5
-5
| --- src/shun.c | ||
| +++ src/shun.c | ||
| @@ -293,28 +293,28 @@ | ||
| 293 | 293 | " FROM rcvfrom LEFT JOIN user USING(uid)" |
| 294 | 294 | " WHERE rcvid=%d", |
| 295 | 295 | rcvid |
| 296 | 296 | ); |
| 297 | 297 | @ <table cellspacing="15" cellpadding="0" border="0"> |
| 298 | - @ <tr><td valign="top" align="right"><b>rcvid:</b></td> | |
| 298 | + @ <tr><th valign="top" align="right">rcvid:</th> | |
| 299 | 299 | @ <td valign="top">%d(rcvid)</td></tr> |
| 300 | 300 | if( db_step(&q)==SQLITE_ROW ){ |
| 301 | 301 | const char *zUser = db_column_text(&q, 0); |
| 302 | 302 | const char *zDate = db_column_text(&q, 1); |
| 303 | 303 | const char *zIpAddr = db_column_text(&q, 2); |
| 304 | - @ <tr><td valign="top" align="right"><b>User:</b></td> | |
| 304 | + @ <tr><th valign="top" align="right">User:</th> | |
| 305 | 305 | @ <td valign="top">%s(zUser)</td></tr> |
| 306 | - @ <tr><td valign="top" align="right"><b>Date:</b></td> | |
| 306 | + @ <tr><th valign="top" align="right">Date:</th> | |
| 307 | 307 | @ <td valign="top">%s(zDate)</td></tr> |
| 308 | - @ <tr><td valign="top" align="right"><b>IP Address:</b></td> | |
| 308 | + @ <tr><th valign="top" align="right">IP Address:</th> | |
| 309 | 309 | @ <td valign="top">%s(zIpAddr)</td></tr> |
| 310 | 310 | } |
| 311 | 311 | db_finalize(&q); |
| 312 | 312 | db_prepare(&q, |
| 313 | 313 | "SELECT rid, uuid, size FROM blob WHERE rcvid=%d", rcvid |
| 314 | 314 | ); |
| 315 | - @ <tr><td valign="top" align="right"><b>Artifacts:</b></td> | |
| 315 | + @ <tr><th valign="top" align="right">Artifacts:</th> | |
| 316 | 316 | @ <td valign="top"> |
| 317 | 317 | while( db_step(&q)==SQLITE_ROW ){ |
| 318 | 318 | int rid = db_column_int(&q, 0); |
| 319 | 319 | const char *zUuid = db_column_text(&q, 1); |
| 320 | 320 | int size = db_column_int(&q, 2); |
| 321 | 321 |
| --- src/shun.c | |
| +++ src/shun.c | |
| @@ -293,28 +293,28 @@ | |
| 293 | " FROM rcvfrom LEFT JOIN user USING(uid)" |
| 294 | " WHERE rcvid=%d", |
| 295 | rcvid |
| 296 | ); |
| 297 | @ <table cellspacing="15" cellpadding="0" border="0"> |
| 298 | @ <tr><td valign="top" align="right"><b>rcvid:</b></td> |
| 299 | @ <td valign="top">%d(rcvid)</td></tr> |
| 300 | if( db_step(&q)==SQLITE_ROW ){ |
| 301 | const char *zUser = db_column_text(&q, 0); |
| 302 | const char *zDate = db_column_text(&q, 1); |
| 303 | const char *zIpAddr = db_column_text(&q, 2); |
| 304 | @ <tr><td valign="top" align="right"><b>User:</b></td> |
| 305 | @ <td valign="top">%s(zUser)</td></tr> |
| 306 | @ <tr><td valign="top" align="right"><b>Date:</b></td> |
| 307 | @ <td valign="top">%s(zDate)</td></tr> |
| 308 | @ <tr><td valign="top" align="right"><b>IP Address:</b></td> |
| 309 | @ <td valign="top">%s(zIpAddr)</td></tr> |
| 310 | } |
| 311 | db_finalize(&q); |
| 312 | db_prepare(&q, |
| 313 | "SELECT rid, uuid, size FROM blob WHERE rcvid=%d", rcvid |
| 314 | ); |
| 315 | @ <tr><td valign="top" align="right"><b>Artifacts:</b></td> |
| 316 | @ <td valign="top"> |
| 317 | while( db_step(&q)==SQLITE_ROW ){ |
| 318 | int rid = db_column_int(&q, 0); |
| 319 | const char *zUuid = db_column_text(&q, 1); |
| 320 | int size = db_column_int(&q, 2); |
| 321 |
| --- src/shun.c | |
| +++ src/shun.c | |
| @@ -293,28 +293,28 @@ | |
| 293 | " FROM rcvfrom LEFT JOIN user USING(uid)" |
| 294 | " WHERE rcvid=%d", |
| 295 | rcvid |
| 296 | ); |
| 297 | @ <table cellspacing="15" cellpadding="0" border="0"> |
| 298 | @ <tr><th valign="top" align="right">rcvid:</th> |
| 299 | @ <td valign="top">%d(rcvid)</td></tr> |
| 300 | if( db_step(&q)==SQLITE_ROW ){ |
| 301 | const char *zUser = db_column_text(&q, 0); |
| 302 | const char *zDate = db_column_text(&q, 1); |
| 303 | const char *zIpAddr = db_column_text(&q, 2); |
| 304 | @ <tr><th valign="top" align="right">User:</th> |
| 305 | @ <td valign="top">%s(zUser)</td></tr> |
| 306 | @ <tr><th valign="top" align="right">Date:</th> |
| 307 | @ <td valign="top">%s(zDate)</td></tr> |
| 308 | @ <tr><th valign="top" align="right">IP Address:</th> |
| 309 | @ <td valign="top">%s(zIpAddr)</td></tr> |
| 310 | } |
| 311 | db_finalize(&q); |
| 312 | db_prepare(&q, |
| 313 | "SELECT rid, uuid, size FROM blob WHERE rcvid=%d", rcvid |
| 314 | ); |
| 315 | @ <tr><th valign="top" align="right">Artifacts:</th> |
| 316 | @ <td valign="top"> |
| 317 | while( db_step(&q)==SQLITE_ROW ){ |
| 318 | int rid = db_column_int(&q, 0); |
| 319 | const char *zUuid = db_column_text(&q, 1); |
| 320 | int size = db_column_int(&q, 2); |
| 321 |
+320
-126
| --- src/sqlite3.c | ||
| +++ src/sqlite3.c | ||
| @@ -670,11 +670,11 @@ | ||
| 670 | 670 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 671 | 671 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 672 | 672 | */ |
| 673 | 673 | #define SQLITE_VERSION "3.8.0" |
| 674 | 674 | #define SQLITE_VERSION_NUMBER 3008000 |
| 675 | -#define SQLITE_SOURCE_ID "2013-07-09 03:04:32 52a49cbc1621094b2fe2b021209b768d29e0426b" | |
| 675 | +#define SQLITE_SOURCE_ID "2013-07-18 14:50:56 5dcffa671f592ae9355628afa439ae9a2d26f0cd" | |
| 676 | 676 | |
| 677 | 677 | /* |
| 678 | 678 | ** CAPI3REF: Run-Time Library Version Numbers |
| 679 | 679 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 680 | 680 | ** |
| @@ -3120,11 +3120,11 @@ | ||
| 3120 | 3120 | ** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for |
| 3121 | 3121 | ** database connection D. An example use for this |
| 3122 | 3122 | ** interface is to keep a GUI updated during a large query. |
| 3123 | 3123 | ** |
| 3124 | 3124 | ** ^The parameter P is passed through as the only parameter to the |
| 3125 | -** callback function X. ^The parameter N is the number of | |
| 3125 | +** callback function X. ^The parameter N is the approximate number of | |
| 3126 | 3126 | ** [virtual machine instructions] that are evaluated between successive |
| 3127 | 3127 | ** invocations of the callback X. |
| 3128 | 3128 | ** |
| 3129 | 3129 | ** ^Only a single progress handler may be defined at one time per |
| 3130 | 3130 | ** [database connection]; setting a new progress handler cancels the |
| @@ -4745,12 +4745,12 @@ | ||
| 4745 | 4745 | ** CAPI3REF: Function Auxiliary Data |
| 4746 | 4746 | ** |
| 4747 | 4747 | ** The following two functions may be used by scalar SQL functions to |
| 4748 | 4748 | ** associate metadata with argument values. If the same value is passed to |
| 4749 | 4749 | ** multiple invocations of the same SQL function during query execution, under |
| 4750 | -** some circumstances the associated metadata may be preserved. This may | |
| 4751 | -** be used, for example, to add a regular-expression matching scalar | |
| 4750 | +** some circumstances the associated metadata may be preserved. This might | |
| 4751 | +** be used, for example, in a regular-expression matching | |
| 4752 | 4752 | ** function. The compiled version of the regular expression is stored as |
| 4753 | 4753 | ** metadata associated with the SQL value passed as the regular expression |
| 4754 | 4754 | ** pattern. The compiled regular expression can be reused on multiple |
| 4755 | 4755 | ** invocations of the same function so that the original pattern string |
| 4756 | 4756 | ** does not need to be recompiled on each invocation. |
| @@ -4760,27 +4760,36 @@ | ||
| 4760 | 4760 | ** value to the application-defined function. ^If no metadata has been ever |
| 4761 | 4761 | ** been set for the Nth argument of the function, or if the corresponding |
| 4762 | 4762 | ** function parameter has changed since the meta-data was set, |
| 4763 | 4763 | ** then sqlite3_get_auxdata() returns a NULL pointer. |
| 4764 | 4764 | ** |
| 4765 | -** ^The sqlite3_set_auxdata() interface saves the metadata | |
| 4766 | -** pointed to by its 3rd parameter as the metadata for the N-th | |
| 4767 | -** argument of the application-defined function. Subsequent | |
| 4768 | -** calls to sqlite3_get_auxdata() might return this data, if it has | |
| 4769 | -** not been destroyed. | |
| 4770 | -** ^If it is not NULL, SQLite will invoke the destructor | |
| 4771 | -** function given by the 4th parameter to sqlite3_set_auxdata() on | |
| 4772 | -** the metadata when the corresponding function parameter changes | |
| 4773 | -** or when the SQL statement completes, whichever comes first. | |
| 4765 | +** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th | |
| 4766 | +** argument of the application-defined function. ^Subsequent | |
| 4767 | +** calls to sqlite3_get_auxdata(C,N) return P from the most recent | |
| 4768 | +** sqlite3_set_auxdata(C,N,P,X) call if the data has not been dropped, or | |
| 4769 | +** NULL if the data has been dropped. | |
| 4770 | +** ^(If it is not NULL, SQLite will invoke the destructor | |
| 4771 | +** function X passed to sqlite3_set_auxdata(C,N,P,X) when <ul> | |
| 4772 | +** <li> the corresponding function parameter changes, | |
| 4773 | +** <li> [sqlite3_reset()] or [sqlite3_finalize()] is called for the | |
| 4774 | +** SQL statement, | |
| 4775 | +** <li> sqlite3_set_auxdata() is invoked again on the same parameter, or | |
| 4776 | +** <li> a memory allocation error occurs. </ul>)^ | |
| 4774 | 4777 | ** |
| 4775 | 4778 | ** SQLite is free to call the destructor and drop metadata on any |
| 4776 | 4779 | ** parameter of any function at any time. ^The only guarantee is that |
| 4777 | -** the destructor will be called before the metadata is dropped. | |
| 4780 | +** the destructor will be called when the [prepared statement] is destroyed. | |
| 4781 | +** Note in particular that the destructor X in the call to | |
| 4782 | +** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before | |
| 4783 | +** the sqlite3_set_auxdata() call even returns. Hence sqlite3_set_auxdata() | |
| 4784 | +** should be called near the end of the function implementation and the | |
| 4785 | +** implementation should not make any use of P after sqlite3_set_auxdata() | |
| 4786 | +** has been called. | |
| 4778 | 4787 | ** |
| 4779 | 4788 | ** ^(In practice, metadata is preserved between function calls for |
| 4780 | -** expressions that are constant at compile time. This includes literal | |
| 4781 | -** values and [parameters].)^ | |
| 4789 | +** function parameters that are compile-time constants, including literal | |
| 4790 | +** values and [parameters] and expressions composed from the same.)^ | |
| 4782 | 4791 | ** |
| 4783 | 4792 | ** These routines must be called from the same thread in which |
| 4784 | 4793 | ** the SQL function is running. |
| 4785 | 4794 | */ |
| 4786 | 4795 | SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); |
| @@ -5689,14 +5698,27 @@ | ||
| 5689 | 5698 | ** |
| 5690 | 5699 | ** ^Calling sqlite3_auto_extension(X) with an entry point X that is already |
| 5691 | 5700 | ** on the list of automatic extensions is a harmless no-op. ^No entry point |
| 5692 | 5701 | ** will be called more than once for each database connection that is opened. |
| 5693 | 5702 | ** |
| 5694 | -** See also: [sqlite3_reset_auto_extension()]. | |
| 5703 | +** See also: [sqlite3_reset_auto_extension()] | |
| 5704 | +** and [sqlite3_cancel_auto_extension()] | |
| 5695 | 5705 | */ |
| 5696 | 5706 | SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void)); |
| 5697 | 5707 | |
| 5708 | +/* | |
| 5709 | +** CAPI3REF: Cancel Automatic Extension Loading | |
| 5710 | +** | |
| 5711 | +** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the | |
| 5712 | +** initialization routine X that was registered using a prior call to | |
| 5713 | +** [sqlite3_auto_extension(X)]. ^The [sqlite3_cancel_auto_extension(X)] | |
| 5714 | +** routine returns 1 if initialization routine X was successfully | |
| 5715 | +** unregistered and it returns 0 if X was not on the list of initialization | |
| 5716 | +** routines. | |
| 5717 | +*/ | |
| 5718 | +SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void)); | |
| 5719 | + | |
| 5698 | 5720 | /* |
| 5699 | 5721 | ** CAPI3REF: Reset Automatic Extension Loading |
| 5700 | 5722 | ** |
| 5701 | 5723 | ** ^This interface disables all automatic extensions previously |
| 5702 | 5724 | ** registered using [sqlite3_auto_extension()]. |
| @@ -6805,10 +6827,16 @@ | ||
| 6805 | 6827 | ** transaction rollback or database recovery operations are not included. |
| 6806 | 6828 | ** If an IO or other error occurs while writing a page to disk, the effect |
| 6807 | 6829 | ** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The |
| 6808 | 6830 | ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. |
| 6809 | 6831 | ** </dd> |
| 6832 | +** | |
| 6833 | +** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt> | |
| 6834 | +** <dd>This parameter returns the zero for the current value if and only if | |
| 6835 | +** there all foreign key constraints (deferred or immediate) have been | |
| 6836 | +** resolved. The highwater mark is always 0. | |
| 6837 | +** </dd> | |
| 6810 | 6838 | ** </dl> |
| 6811 | 6839 | */ |
| 6812 | 6840 | #define SQLITE_DBSTATUS_LOOKASIDE_USED 0 |
| 6813 | 6841 | #define SQLITE_DBSTATUS_CACHE_USED 1 |
| 6814 | 6842 | #define SQLITE_DBSTATUS_SCHEMA_USED 2 |
| @@ -6817,11 +6845,12 @@ | ||
| 6817 | 6845 | #define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5 |
| 6818 | 6846 | #define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 |
| 6819 | 6847 | #define SQLITE_DBSTATUS_CACHE_HIT 7 |
| 6820 | 6848 | #define SQLITE_DBSTATUS_CACHE_MISS 8 |
| 6821 | 6849 | #define SQLITE_DBSTATUS_CACHE_WRITE 9 |
| 6822 | -#define SQLITE_DBSTATUS_MAX 9 /* Largest defined DBSTATUS */ | |
| 6850 | +#define SQLITE_DBSTATUS_DEFERRED_FKS 10 | |
| 6851 | +#define SQLITE_DBSTATUS_MAX 10 /* Largest defined DBSTATUS */ | |
| 6823 | 6852 | |
| 6824 | 6853 | |
| 6825 | 6854 | /* |
| 6826 | 6855 | ** CAPI3REF: Prepared Statement Status |
| 6827 | 6856 | ** |
| @@ -10117,11 +10146,11 @@ | ||
| 10117 | 10146 | void *pAuthArg; /* 1st argument to the access auth function */ |
| 10118 | 10147 | #endif |
| 10119 | 10148 | #ifndef SQLITE_OMIT_PROGRESS_CALLBACK |
| 10120 | 10149 | int (*xProgress)(void *); /* The progress callback */ |
| 10121 | 10150 | void *pProgressArg; /* Argument to the progress callback */ |
| 10122 | - int nProgressOps; /* Number of opcodes for progress callback */ | |
| 10151 | + unsigned nProgressOps; /* Number of opcodes for progress callback */ | |
| 10123 | 10152 | #endif |
| 10124 | 10153 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 10125 | 10154 | int nVTrans; /* Allocated size of aVTrans */ |
| 10126 | 10155 | Hash aModule; /* populated by sqlite3_create_module() */ |
| 10127 | 10156 | VtabCtx *pVtabCtx; /* Context for active vtab connect/create */ |
| @@ -10135,10 +10164,11 @@ | ||
| 10135 | 10164 | Savepoint *pSavepoint; /* List of active savepoints */ |
| 10136 | 10165 | int busyTimeout; /* Busy handler timeout, in msec */ |
| 10137 | 10166 | int nSavepoint; /* Number of non-transaction savepoints */ |
| 10138 | 10167 | int nStatement; /* Number of nested statement-transactions */ |
| 10139 | 10168 | i64 nDeferredCons; /* Net deferred constraints this transaction. */ |
| 10169 | + i64 nDeferredImmCons; /* Net deferred immediate constraints */ | |
| 10140 | 10170 | int *pnBytesFreed; /* If not NULL, increment this in DbFree() */ |
| 10141 | 10171 | |
| 10142 | 10172 | #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY |
| 10143 | 10173 | /* The following variables are all protected by the STATIC_MASTER |
| 10144 | 10174 | ** mutex, not by sqlite3.mutex. They are used by code in notify.c. |
| @@ -10190,10 +10220,13 @@ | ||
| 10190 | 10220 | #define SQLITE_ForeignKeys 0x00040000 /* Enforce foreign key constraints */ |
| 10191 | 10221 | #define SQLITE_AutoIndex 0x00080000 /* Enable automatic indexes */ |
| 10192 | 10222 | #define SQLITE_PreferBuiltin 0x00100000 /* Preference to built-in funcs */ |
| 10193 | 10223 | #define SQLITE_LoadExtension 0x00200000 /* Enable load_extension */ |
| 10194 | 10224 | #define SQLITE_EnableTrigger 0x00400000 /* True to enable triggers */ |
| 10225 | +#define SQLITE_DeferFKs 0x00800000 /* Defer all FK constraints */ | |
| 10226 | +#define SQLITE_QueryOnly 0x01000000 /* Disable database changes */ | |
| 10227 | + | |
| 10195 | 10228 | |
| 10196 | 10229 | /* |
| 10197 | 10230 | ** Bits of the sqlite3.dbOptFlags field that are used by the |
| 10198 | 10231 | ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to |
| 10199 | 10232 | ** selectively disable various optimizations. |
| @@ -10336,10 +10369,11 @@ | ||
| 10336 | 10369 | ** OP_Savepoint instruction. |
| 10337 | 10370 | */ |
| 10338 | 10371 | struct Savepoint { |
| 10339 | 10372 | char *zName; /* Savepoint name (nul-terminated) */ |
| 10340 | 10373 | i64 nDeferredCons; /* Number of deferred fk violations */ |
| 10374 | + i64 nDeferredImmCons; /* Number of deferred imm fk. */ | |
| 10341 | 10375 | Savepoint *pNext; /* Parent savepoint (if any) */ |
| 10342 | 10376 | }; |
| 10343 | 10377 | |
| 10344 | 10378 | /* |
| 10345 | 10379 | ** The following are used as the second parameter to sqlite3Savepoint(), |
| @@ -13530,10 +13564,11 @@ | ||
| 13530 | 13564 | #ifndef SQLITE_OMIT_TRACE |
| 13531 | 13565 | i64 startTime; /* Time when query started - used for profiling */ |
| 13532 | 13566 | #endif |
| 13533 | 13567 | i64 nFkConstraint; /* Number of imm. FK constraints this VM */ |
| 13534 | 13568 | i64 nStmtDefCons; /* Number of def. constraints when stmt started */ |
| 13569 | + i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */ | |
| 13535 | 13570 | char *zSql; /* Text of the SQL statement that generated this */ |
| 13536 | 13571 | void *pFree; /* Free this when deleting the vdbe */ |
| 13537 | 13572 | #ifdef SQLITE_DEBUG |
| 13538 | 13573 | FILE *trace; /* Write an execution trace here, if not NULL */ |
| 13539 | 13574 | #endif |
| @@ -13889,10 +13924,20 @@ | ||
| 13889 | 13924 | } |
| 13890 | 13925 | *pHighwater = 0; |
| 13891 | 13926 | *pCurrent = nRet; |
| 13892 | 13927 | break; |
| 13893 | 13928 | } |
| 13929 | + | |
| 13930 | + /* Set *pCurrent to non-zero if there are unresolved deferred foreign | |
| 13931 | + ** key constraints. Set *pCurrent to zero if all foreign key constraints | |
| 13932 | + ** have been satisfied. The *pHighwater is always set to zero. | |
| 13933 | + */ | |
| 13934 | + case SQLITE_DBSTATUS_DEFERRED_FKS: { | |
| 13935 | + *pHighwater = 0; | |
| 13936 | + *pCurrent = db->nDeferredImmCons>0 || db->nDeferredCons>0; | |
| 13937 | + break; | |
| 13938 | + } | |
| 13894 | 13939 | |
| 13895 | 13940 | default: { |
| 13896 | 13941 | rc = SQLITE_ERROR; |
| 13897 | 13942 | } |
| 13898 | 13943 | } |
| @@ -61946,10 +61991,11 @@ | ||
| 61946 | 61991 | /* If the statement transaction is being rolled back, also restore the |
| 61947 | 61992 | ** database handles deferred constraint counter to the value it had when |
| 61948 | 61993 | ** the statement transaction was opened. */ |
| 61949 | 61994 | if( eOp==SAVEPOINT_ROLLBACK ){ |
| 61950 | 61995 | db->nDeferredCons = p->nStmtDefCons; |
| 61996 | + db->nDeferredImmCons = p->nStmtDefImmCons; | |
| 61951 | 61997 | } |
| 61952 | 61998 | } |
| 61953 | 61999 | return rc; |
| 61954 | 62000 | } |
| 61955 | 62001 | |
| @@ -61964,11 +62010,13 @@ | ||
| 61964 | 62010 | ** and write an error message to it. Then return SQLITE_ERROR. |
| 61965 | 62011 | */ |
| 61966 | 62012 | #ifndef SQLITE_OMIT_FOREIGN_KEY |
| 61967 | 62013 | SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){ |
| 61968 | 62014 | sqlite3 *db = p->db; |
| 61969 | - if( (deferred && db->nDeferredCons>0) || (!deferred && p->nFkConstraint>0) ){ | |
| 62015 | + if( (deferred && (db->nDeferredCons+db->nDeferredImmCons)>0) | |
| 62016 | + || (!deferred && p->nFkConstraint>0) | |
| 62017 | + ){ | |
| 61970 | 62018 | p->rc = SQLITE_CONSTRAINT_FOREIGNKEY; |
| 61971 | 62019 | p->errorAction = OE_Abort; |
| 61972 | 62020 | sqlite3SetString(&p->zErrMsg, db, "foreign key constraint failed"); |
| 61973 | 62021 | return SQLITE_ERROR; |
| 61974 | 62022 | } |
| @@ -62097,10 +62145,12 @@ | ||
| 62097 | 62145 | }else if( rc!=SQLITE_OK ){ |
| 62098 | 62146 | p->rc = rc; |
| 62099 | 62147 | sqlite3RollbackAll(db, SQLITE_OK); |
| 62100 | 62148 | }else{ |
| 62101 | 62149 | db->nDeferredCons = 0; |
| 62150 | + db->nDeferredImmCons = 0; | |
| 62151 | + db->flags &= ~SQLITE_DeferFKs; | |
| 62102 | 62152 | sqlite3CommitInternalChanges(db); |
| 62103 | 62153 | } |
| 62104 | 62154 | }else{ |
| 62105 | 62155 | sqlite3RollbackAll(db, SQLITE_OK); |
| 62106 | 62156 | } |
| @@ -63536,11 +63586,13 @@ | ||
| 63536 | 63586 | */ |
| 63537 | 63587 | if( db->nVdbeActive==0 ){ |
| 63538 | 63588 | db->u1.isInterrupted = 0; |
| 63539 | 63589 | } |
| 63540 | 63590 | |
| 63541 | - assert( db->nVdbeWrite>0 || db->autoCommit==0 || db->nDeferredCons==0 ); | |
| 63591 | + assert( db->nVdbeWrite>0 || db->autoCommit==0 | |
| 63592 | + || (db->nDeferredCons==0 && db->nDeferredImmCons==0) | |
| 63593 | + ); | |
| 63542 | 63594 | |
| 63543 | 63595 | #ifndef SQLITE_OMIT_TRACE |
| 63544 | 63596 | if( db->xProfile && !db->init.busy ){ |
| 63545 | 63597 | sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime); |
| 63546 | 63598 | } |
| @@ -65384,16 +65436,15 @@ | ||
| 65384 | 65436 | Op *pOp; /* Current operation */ |
| 65385 | 65437 | int rc = SQLITE_OK; /* Value to return */ |
| 65386 | 65438 | sqlite3 *db = p->db; /* The database */ |
| 65387 | 65439 | u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ |
| 65388 | 65440 | u8 encoding = ENC(db); /* The database encoding */ |
| 65389 | -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK | |
| 65390 | - int checkProgress; /* True if progress callbacks are enabled */ | |
| 65391 | - int nProgressOps = 0; /* Opcodes executed since progress callback. */ | |
| 65392 | -#endif | |
| 65393 | 65441 | int iCompare = 0; /* Result of last OP_Compare operation */ |
| 65394 | 65442 | unsigned nVmStep = 0; /* Number of virtual machine steps */ |
| 65443 | +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK | |
| 65444 | + unsigned nProgressOps = 0; /* nVmStep at last progress callback. */ | |
| 65445 | +#endif | |
| 65395 | 65446 | Mem *aMem = p->aMem; /* Copy of p->aMem */ |
| 65396 | 65447 | Mem *pIn1 = 0; /* 1st input operand */ |
| 65397 | 65448 | Mem *pIn2 = 0; /* 2nd input operand */ |
| 65398 | 65449 | Mem *pIn3 = 0; /* 3rd input operand */ |
| 65399 | 65450 | Mem *pOut = 0; /* Output operand */ |
| @@ -65847,13 +65898,10 @@ | ||
| 65847 | 65898 | assert( p->explain==0 ); |
| 65848 | 65899 | p->pResultSet = 0; |
| 65849 | 65900 | db->busyHandler.nBusy = 0; |
| 65850 | 65901 | CHECK_FOR_INTERRUPT; |
| 65851 | 65902 | sqlite3VdbeIOTraceSql(p); |
| 65852 | -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK | |
| 65853 | - checkProgress = db->xProgress!=0; | |
| 65854 | -#endif | |
| 65855 | 65903 | #ifdef SQLITE_DEBUG |
| 65856 | 65904 | sqlite3BeginBenignMalloc(); |
| 65857 | 65905 | if( p->pc==0 && (p->db->flags & SQLITE_VdbeListing)!=0 ){ |
| 65858 | 65906 | int i; |
| 65859 | 65907 | printf("VDBE Program Listing:\n"); |
| @@ -65895,31 +65943,10 @@ | ||
| 65895 | 65943 | sqlite3_interrupt_count--; |
| 65896 | 65944 | if( sqlite3_interrupt_count==0 ){ |
| 65897 | 65945 | sqlite3_interrupt(db); |
| 65898 | 65946 | } |
| 65899 | 65947 | } |
| 65900 | -#endif | |
| 65901 | - | |
| 65902 | -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK | |
| 65903 | - /* Call the progress callback if it is configured and the required number | |
| 65904 | - ** of VDBE ops have been executed (either since this invocation of | |
| 65905 | - ** sqlite3VdbeExec() or since last time the progress callback was called). | |
| 65906 | - ** If the progress callback returns non-zero, exit the virtual machine with | |
| 65907 | - ** a return code SQLITE_ABORT. | |
| 65908 | - */ | |
| 65909 | - if( checkProgress ){ | |
| 65910 | - if( db->nProgressOps==nProgressOps ){ | |
| 65911 | - int prc; | |
| 65912 | - prc = db->xProgress(db->pProgressArg); | |
| 65913 | - if( prc!=0 ){ | |
| 65914 | - rc = SQLITE_INTERRUPT; | |
| 65915 | - goto vdbe_error_halt; | |
| 65916 | - } | |
| 65917 | - nProgressOps = 0; | |
| 65918 | - } | |
| 65919 | - nProgressOps++; | |
| 65920 | - } | |
| 65921 | 65948 | #endif |
| 65922 | 65949 | |
| 65923 | 65950 | /* On any opcode with the "out2-prerelease" tag, free any |
| 65924 | 65951 | ** external allocations out of mem[p2] and set mem[p2] to be |
| 65925 | 65952 | ** an undefined integer. Opcodes will either fill in the integer |
| @@ -66010,12 +66037,42 @@ | ||
| 66010 | 66037 | ** The next instruction executed will be |
| 66011 | 66038 | ** the one at index P2 from the beginning of |
| 66012 | 66039 | ** the program. |
| 66013 | 66040 | */ |
| 66014 | 66041 | case OP_Goto: { /* jump */ |
| 66015 | - CHECK_FOR_INTERRUPT; | |
| 66016 | 66042 | pc = pOp->p2 - 1; |
| 66043 | + | |
| 66044 | + /* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev, | |
| 66045 | + ** OP_VNext, OP_RowSetNext, or OP_SorterNext) all jump here upon | |
| 66046 | + ** completion. Check to see if sqlite3_interrupt() has been called | |
| 66047 | + ** or if the progress callback needs to be invoked. | |
| 66048 | + ** | |
| 66049 | + ** This code uses unstructured "goto" statements and does not look clean. | |
| 66050 | + ** But that is not due to sloppy coding habits. The code is written this | |
| 66051 | + ** way for performance, to avoid having to run the interrupt and progress | |
| 66052 | + ** checks on every opcode. This helps sqlite3_step() to run about 1.5% | |
| 66053 | + ** faster according to "valgrind --tool=cachegrind" */ | |
| 66054 | +check_for_interrupt: | |
| 66055 | + CHECK_FOR_INTERRUPT; | |
| 66056 | +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK | |
| 66057 | + /* Call the progress callback if it is configured and the required number | |
| 66058 | + ** of VDBE ops have been executed (either since this invocation of | |
| 66059 | + ** sqlite3VdbeExec() or since last time the progress callback was called). | |
| 66060 | + ** If the progress callback returns non-zero, exit the virtual machine with | |
| 66061 | + ** a return code SQLITE_ABORT. | |
| 66062 | + */ | |
| 66063 | + if( db->xProgress!=0 && (nVmStep - nProgressOps)>=db->nProgressOps ){ | |
| 66064 | + int prc; | |
| 66065 | + prc = db->xProgress(db->pProgressArg); | |
| 66066 | + if( prc!=0 ){ | |
| 66067 | + rc = SQLITE_INTERRUPT; | |
| 66068 | + goto vdbe_error_halt; | |
| 66069 | + } | |
| 66070 | + nProgressOps = nVmStep; | |
| 66071 | + } | |
| 66072 | +#endif | |
| 66073 | + | |
| 66017 | 66074 | break; |
| 66018 | 66075 | } |
| 66019 | 66076 | |
| 66020 | 66077 | /* Opcode: Gosub P1 P2 * * * |
| 66021 | 66078 | ** |
| @@ -66132,11 +66189,11 @@ | ||
| 66132 | 66189 | assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR ); |
| 66133 | 66190 | if( rc==SQLITE_BUSY ){ |
| 66134 | 66191 | p->rc = rc = SQLITE_BUSY; |
| 66135 | 66192 | }else{ |
| 66136 | 66193 | assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ); |
| 66137 | - assert( rc==SQLITE_OK || db->nDeferredCons>0 ); | |
| 66194 | + assert( rc==SQLITE_OK || db->nDeferredCons>0 || db->nDeferredImmCons>0 ); | |
| 66138 | 66195 | rc = p->rc ? SQLITE_ERROR : SQLITE_DONE; |
| 66139 | 66196 | } |
| 66140 | 66197 | goto vdbe_return; |
| 66141 | 66198 | } |
| 66142 | 66199 | |
| @@ -68028,10 +68085,11 @@ | ||
| 68028 | 68085 | |
| 68029 | 68086 | /* Link the new savepoint into the database handle's list. */ |
| 68030 | 68087 | u.as.pNew->pNext = db->pSavepoint; |
| 68031 | 68088 | db->pSavepoint = u.as.pNew; |
| 68032 | 68089 | u.as.pNew->nDeferredCons = db->nDeferredCons; |
| 68090 | + u.as.pNew->nDeferredImmCons = db->nDeferredImmCons; | |
| 68033 | 68091 | } |
| 68034 | 68092 | } |
| 68035 | 68093 | }else{ |
| 68036 | 68094 | u.as.iSavepoint = 0; |
| 68037 | 68095 | |
| @@ -68115,10 +68173,11 @@ | ||
| 68115 | 68173 | if( !isTransaction ){ |
| 68116 | 68174 | db->nSavepoint--; |
| 68117 | 68175 | } |
| 68118 | 68176 | }else{ |
| 68119 | 68177 | db->nDeferredCons = u.as.pSavepoint->nDeferredCons; |
| 68178 | + db->nDeferredImmCons = u.as.pSavepoint->nDeferredImmCons; | |
| 68120 | 68179 | } |
| 68121 | 68180 | |
| 68122 | 68181 | if( !isTransaction ){ |
| 68123 | 68182 | rc = sqlite3VtabSavepoint(db, u.as.p1, u.as.iSavepoint); |
| 68124 | 68183 | if( rc!=SQLITE_OK ) goto abort_due_to_error; |
| @@ -68244,10 +68303,14 @@ | ||
| 68244 | 68303 | |
| 68245 | 68304 | assert( p->bIsReader ); |
| 68246 | 68305 | assert( p->readOnly==0 || pOp->p2==0 ); |
| 68247 | 68306 | assert( pOp->p1>=0 && pOp->p1<db->nDb ); |
| 68248 | 68307 | assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 ); |
| 68308 | + if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){ | |
| 68309 | + rc = SQLITE_READONLY; | |
| 68310 | + goto abort_due_to_error; | |
| 68311 | + } | |
| 68249 | 68312 | u.au.pBt = db->aDb[pOp->p1].pBt; |
| 68250 | 68313 | |
| 68251 | 68314 | if( u.au.pBt ){ |
| 68252 | 68315 | rc = sqlite3BtreeBeginTrans(u.au.pBt, pOp->p2); |
| 68253 | 68316 | if( rc==SQLITE_BUSY ){ |
| @@ -68276,10 +68339,11 @@ | ||
| 68276 | 68339 | |
| 68277 | 68340 | /* Store the current value of the database handles deferred constraint |
| 68278 | 68341 | ** counter. If the statement transaction needs to be rolled back, |
| 68279 | 68342 | ** the value of this counter needs to be restored too. */ |
| 68280 | 68343 | p->nStmtDefCons = db->nDeferredCons; |
| 68344 | + p->nStmtDefImmCons = db->nDeferredImmCons; | |
| 68281 | 68345 | } |
| 68282 | 68346 | } |
| 68283 | 68347 | break; |
| 68284 | 68348 | } |
| 68285 | 68349 | |
| @@ -69851,11 +69915,10 @@ | ||
| 69851 | 69915 | #if 0 /* local variables moved into u.br */ |
| 69852 | 69916 | VdbeCursor *pC; |
| 69853 | 69917 | int res; |
| 69854 | 69918 | #endif /* local variables moved into u.br */ |
| 69855 | 69919 | |
| 69856 | - CHECK_FOR_INTERRUPT; | |
| 69857 | 69920 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); |
| 69858 | 69921 | assert( pOp->p5<=ArraySize(p->aCounter) ); |
| 69859 | 69922 | u.br.pC = p->apCsr[pOp->p1]; |
| 69860 | 69923 | if( u.br.pC==0 ){ |
| 69861 | 69924 | break; /* See ticket #2273 */ |
| @@ -69880,11 +69943,11 @@ | ||
| 69880 | 69943 | #ifdef SQLITE_TEST |
| 69881 | 69944 | sqlite3_search_count++; |
| 69882 | 69945 | #endif |
| 69883 | 69946 | } |
| 69884 | 69947 | u.br.pC->rowidIsValid = 0; |
| 69885 | - break; | |
| 69948 | + goto check_for_interrupt; | |
| 69886 | 69949 | } |
| 69887 | 69950 | |
| 69888 | 69951 | /* Opcode: IdxInsert P1 P2 P3 * P5 |
| 69889 | 69952 | ** |
| 69890 | 69953 | ** Register P2 holds an SQL index key made using the |
| @@ -70426,11 +70489,11 @@ | ||
| 70426 | 70489 | */ |
| 70427 | 70490 | case OP_RowSetRead: { /* jump, in1, out3 */ |
| 70428 | 70491 | #if 0 /* local variables moved into u.cb */ |
| 70429 | 70492 | i64 val; |
| 70430 | 70493 | #endif /* local variables moved into u.cb */ |
| 70431 | - CHECK_FOR_INTERRUPT; | |
| 70494 | + | |
| 70432 | 70495 | pIn1 = &aMem[pOp->p1]; |
| 70433 | 70496 | if( (pIn1->flags & MEM_RowSet)==0 |
| 70434 | 70497 | || sqlite3RowSetNext(pIn1->u.pRowSet, &u.cb.val)==0 |
| 70435 | 70498 | ){ |
| 70436 | 70499 | /* The boolean index is empty */ |
| @@ -70438,11 +70501,11 @@ | ||
| 70438 | 70501 | pc = pOp->p2 - 1; |
| 70439 | 70502 | }else{ |
| 70440 | 70503 | /* A value was pulled from the index */ |
| 70441 | 70504 | sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.cb.val); |
| 70442 | 70505 | } |
| 70443 | - break; | |
| 70506 | + goto check_for_interrupt; | |
| 70444 | 70507 | } |
| 70445 | 70508 | |
| 70446 | 70509 | /* Opcode: RowSetTest P1 P2 P3 P4 |
| 70447 | 70510 | ** |
| 70448 | 70511 | ** Register P3 is assumed to hold a 64-bit integer value. If register P1 |
| @@ -70658,11 +70721,13 @@ | ||
| 70658 | 70721 | ** If P1 is non-zero, the database constraint counter is incremented |
| 70659 | 70722 | ** (deferred foreign key constraints). Otherwise, if P1 is zero, the |
| 70660 | 70723 | ** statement counter is incremented (immediate foreign key constraints). |
| 70661 | 70724 | */ |
| 70662 | 70725 | case OP_FkCounter: { |
| 70663 | - if( pOp->p1 ){ | |
| 70726 | + if( db->flags & SQLITE_DeferFKs ){ | |
| 70727 | + db->nDeferredImmCons += pOp->p2; | |
| 70728 | + }else if( pOp->p1 ){ | |
| 70664 | 70729 | db->nDeferredCons += pOp->p2; |
| 70665 | 70730 | }else{ |
| 70666 | 70731 | p->nFkConstraint += pOp->p2; |
| 70667 | 70732 | } |
| 70668 | 70733 | break; |
| @@ -70679,13 +70744,13 @@ | ||
| 70679 | 70744 | ** zero, the jump is taken if the statement constraint-counter is zero |
| 70680 | 70745 | ** (immediate foreign key constraint violations). |
| 70681 | 70746 | */ |
| 70682 | 70747 | case OP_FkIfZero: { /* jump */ |
| 70683 | 70748 | if( pOp->p1 ){ |
| 70684 | - if( db->nDeferredCons==0 ) pc = pOp->p2-1; | |
| 70749 | + if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1; | |
| 70685 | 70750 | }else{ |
| 70686 | - if( p->nFkConstraint==0 ) pc = pOp->p2-1; | |
| 70751 | + if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1; | |
| 70687 | 70752 | } |
| 70688 | 70753 | break; |
| 70689 | 70754 | } |
| 70690 | 70755 | #endif /* #ifndef SQLITE_OMIT_FOREIGN_KEY */ |
| 70691 | 70756 | |
| @@ -71367,11 +71432,11 @@ | ||
| 71367 | 71432 | |
| 71368 | 71433 | if( !u.cp.res ){ |
| 71369 | 71434 | /* If there is data, jump to P2 */ |
| 71370 | 71435 | pc = pOp->p2 - 1; |
| 71371 | 71436 | } |
| 71372 | - break; | |
| 71437 | + goto check_for_interrupt; | |
| 71373 | 71438 | } |
| 71374 | 71439 | #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
| 71375 | 71440 | |
| 71376 | 71441 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 71377 | 71442 | /* Opcode: VRename P1 * * P4 * |
| @@ -89262,11 +89327,14 @@ | ||
| 89262 | 89327 | sqlite3ReleaseTempReg(pParse, regRec); |
| 89263 | 89328 | sqlite3ReleaseTempRange(pParse, regTemp, nCol); |
| 89264 | 89329 | } |
| 89265 | 89330 | } |
| 89266 | 89331 | |
| 89267 | - if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){ | |
| 89332 | + if( !pFKey->isDeferred && !(pParse->db->flags & SQLITE_DeferFKs) | |
| 89333 | + && !pParse->pToplevel | |
| 89334 | + && !pParse->isMultiWrite | |
| 89335 | + ){ | |
| 89268 | 89336 | /* Special case: If this is an INSERT statement that will insert exactly |
| 89269 | 89337 | ** one row into the table, raise a constraint immediately instead of |
| 89270 | 89338 | ** incrementing a counter. This is necessary as the VM code is being |
| 89271 | 89339 | ** generated for will not open a statement transaction. */ |
| 89272 | 89340 | assert( nIncr==1 ); |
| @@ -89653,11 +89721,13 @@ | ||
| 89653 | 89721 | for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){ |
| 89654 | 89722 | Index *pIdx = 0; /* Foreign key index for pFKey */ |
| 89655 | 89723 | SrcList *pSrc; |
| 89656 | 89724 | int *aiCol = 0; |
| 89657 | 89725 | |
| 89658 | - if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){ | |
| 89726 | + if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs) | |
| 89727 | + && !pParse->pToplevel && !pParse->isMultiWrite | |
| 89728 | + ){ | |
| 89659 | 89729 | assert( regOld==0 && regNew!=0 ); |
| 89660 | 89730 | /* Inserting a single row into a parent table cannot cause an immediate |
| 89661 | 89731 | ** foreign key violation. So do nothing in this case. */ |
| 89662 | 89732 | continue; |
| 89663 | 89733 | } |
| @@ -92615,15 +92685,18 @@ | ||
| 92615 | 92685 | #ifndef SQLITE_CORE |
| 92616 | 92686 | /* This case when the file really is being compiled as a loadable |
| 92617 | 92687 | ** extension */ |
| 92618 | 92688 | # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; |
| 92619 | 92689 | # define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; |
| 92690 | +# define SQLITE_EXTENSION_INIT3 \ | |
| 92691 | + extern const sqlite3_api_routines *sqlite3_api; | |
| 92620 | 92692 | #else |
| 92621 | 92693 | /* This case when the file is being statically linked into the |
| 92622 | 92694 | ** application */ |
| 92623 | 92695 | # define SQLITE_EXTENSION_INIT1 /*no-op*/ |
| 92624 | 92696 | # define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */ |
| 92697 | +# define SQLITE_EXTENSION_INIT3 /*no-op*/ | |
| 92625 | 92698 | #endif |
| 92626 | 92699 | |
| 92627 | 92700 | #endif /* _SQLITE3EXT_H_ */ |
| 92628 | 92701 | |
| 92629 | 92702 | /************** End of sqlite3ext.h ******************************************/ |
| @@ -93275,10 +93348,39 @@ | ||
| 93275 | 93348 | sqlite3_mutex_leave(mutex); |
| 93276 | 93349 | assert( (rc&0xff)==rc ); |
| 93277 | 93350 | return rc; |
| 93278 | 93351 | } |
| 93279 | 93352 | } |
| 93353 | + | |
| 93354 | +/* | |
| 93355 | +** Cancel a prior call to sqlite3_auto_extension. Remove xInit from the | |
| 93356 | +** set of routines that is invoked for each new database connection, if it | |
| 93357 | +** is currently on the list. If xInit is not on the list, then this | |
| 93358 | +** routine is a no-op. | |
| 93359 | +** | |
| 93360 | +** Return 1 if xInit was found on the list and removed. Return 0 if xInit | |
| 93361 | +** was not on the list. | |
| 93362 | +*/ | |
| 93363 | +SQLITE_API int sqlite3_cancel_auto_extension(void (*xInit)(void)){ | |
| 93364 | +#if SQLITE_THREADSAFE | |
| 93365 | + sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); | |
| 93366 | +#endif | |
| 93367 | + int i; | |
| 93368 | + int n = 0; | |
| 93369 | + wsdAutoextInit; | |
| 93370 | + sqlite3_mutex_enter(mutex); | |
| 93371 | + for(i=wsdAutoext.nExt-1; i>=0; i--){ | |
| 93372 | + if( wsdAutoext.aExt[i]==xInit ){ | |
| 93373 | + wsdAutoext.nExt--; | |
| 93374 | + wsdAutoext.aExt[i] = wsdAutoext.aExt[wsdAutoext.nExt]; | |
| 93375 | + n++; | |
| 93376 | + break; | |
| 93377 | + } | |
| 93378 | + } | |
| 93379 | + sqlite3_mutex_leave(mutex); | |
| 93380 | + return n; | |
| 93381 | +} | |
| 93280 | 93382 | |
| 93281 | 93383 | /* |
| 93282 | 93384 | ** Reset the automatic extension loading mechanism. |
| 93283 | 93385 | */ |
| 93284 | 93386 | SQLITE_API void sqlite3_reset_auto_extension(void){ |
| @@ -93516,10 +93618,11 @@ | ||
| 93516 | 93618 | { "empty_result_callbacks", SQLITE_NullCallback }, |
| 93517 | 93619 | { "legacy_file_format", SQLITE_LegacyFileFmt }, |
| 93518 | 93620 | { "fullfsync", SQLITE_FullFSync }, |
| 93519 | 93621 | { "checkpoint_fullfsync", SQLITE_CkptFullFSync }, |
| 93520 | 93622 | { "reverse_unordered_selects", SQLITE_ReverseOrder }, |
| 93623 | + { "query_only", SQLITE_QueryOnly }, | |
| 93521 | 93624 | #ifndef SQLITE_OMIT_AUTOMATIC_INDEX |
| 93522 | 93625 | { "automatic_index", SQLITE_AutoIndex }, |
| 93523 | 93626 | #endif |
| 93524 | 93627 | #ifdef SQLITE_DEBUG |
| 93525 | 93628 | { "sql_trace", SQLITE_SqlTrace }, |
| @@ -93536,16 +93639,17 @@ | ||
| 93536 | 93639 | { "writable_schema", SQLITE_WriteSchema|SQLITE_RecoveryMode }, |
| 93537 | 93640 | |
| 93538 | 93641 | /* TODO: Maybe it shouldn't be possible to change the ReadUncommitted |
| 93539 | 93642 | ** flag if there are any active statements. */ |
| 93540 | 93643 | { "read_uncommitted", SQLITE_ReadUncommitted }, |
| 93541 | - { "recursive_triggers", SQLITE_RecTriggers }, | |
| 93644 | + { "recursive_triggers", SQLITE_RecTriggers }, | |
| 93542 | 93645 | |
| 93543 | 93646 | /* This flag may only be set if both foreign-key and trigger support |
| 93544 | 93647 | ** are present in the build. */ |
| 93545 | 93648 | #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) |
| 93546 | - { "foreign_keys", SQLITE_ForeignKeys }, | |
| 93649 | + { "foreign_keys", SQLITE_ForeignKeys }, | |
| 93650 | + { "defer_foreign_keys", SQLITE_DeferFKs }, | |
| 93547 | 93651 | #endif |
| 93548 | 93652 | }; |
| 93549 | 93653 | int i; |
| 93550 | 93654 | const struct sPragmaType *p; |
| 93551 | 93655 | for(i=0, p=aPragma; i<ArraySize(aPragma); i++, p++){ |
| @@ -93567,10 +93671,11 @@ | ||
| 93567 | 93671 | |
| 93568 | 93672 | if( sqlite3GetBoolean(zRight, 0) ){ |
| 93569 | 93673 | db->flags |= mask; |
| 93570 | 93674 | }else{ |
| 93571 | 93675 | db->flags &= ~mask; |
| 93676 | + if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0; | |
| 93572 | 93677 | } |
| 93573 | 93678 | |
| 93574 | 93679 | /* Many of the flag-pragmas modify the code generated by the SQL |
| 93575 | 93680 | ** compiler (eg. count_changes). So add an opcode to expire all |
| 93576 | 93681 | ** compiled SQL statements after modifying a pragma value. |
| @@ -95979,10 +96084,16 @@ | ||
| 95979 | 96084 | |
| 95980 | 96085 | assert( ppStmt ); |
| 95981 | 96086 | *ppStmt = 0; |
| 95982 | 96087 | if( !sqlite3SafetyCheckOk(db) ){ |
| 95983 | 96088 | return SQLITE_MISUSE_BKPT; |
| 96089 | + } | |
| 96090 | + if( nBytes>=0 ){ | |
| 96091 | + int sz; | |
| 96092 | + const char *z = (const char*)zSql; | |
| 96093 | + for(sz=0; sz<nBytes && (z[sz]!=0 || z[sz+1]!=0); sz += 2){} | |
| 96094 | + nBytes = sz; | |
| 95984 | 96095 | } |
| 95985 | 96096 | sqlite3_mutex_enter(db->mutex); |
| 95986 | 96097 | zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE); |
| 95987 | 96098 | if( zSql8 ){ |
| 95988 | 96099 | rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, 0, ppStmt, &zTail8); |
| @@ -104070,12 +104181,12 @@ | ||
| 104070 | 104181 | int (*x)(sqlite3_vtab *); |
| 104071 | 104182 | sqlite3_vtab *pVtab = aVTrans[i]->pVtab; |
| 104072 | 104183 | if( pVtab && (x = pVtab->pModule->xSync)!=0 ){ |
| 104073 | 104184 | rc = x(pVtab); |
| 104074 | 104185 | sqlite3DbFree(db, *pzErrmsg); |
| 104075 | - *pzErrmsg = sqlite3DbStrDup(db, pVtab->zErrMsg); | |
| 104076 | - sqlite3_free(pVtab->zErrMsg); | |
| 104186 | + *pzErrmsg = pVtab->zErrMsg; | |
| 104187 | + pVtab->zErrMsg = 0; | |
| 104077 | 104188 | } |
| 104078 | 104189 | } |
| 104079 | 104190 | db->aVTrans = aVTrans; |
| 104080 | 104191 | return rc; |
| 104081 | 104192 | } |
| @@ -104391,10 +104502,12 @@ | ||
| 104391 | 104502 | typedef struct WhereLoop WhereLoop; |
| 104392 | 104503 | typedef struct WherePath WherePath; |
| 104393 | 104504 | typedef struct WhereTerm WhereTerm; |
| 104394 | 104505 | typedef struct WhereLoopBuilder WhereLoopBuilder; |
| 104395 | 104506 | typedef struct WhereScan WhereScan; |
| 104507 | +typedef struct WhereOrCost WhereOrCost; | |
| 104508 | +typedef struct WhereOrSet WhereOrSet; | |
| 104396 | 104509 | |
| 104397 | 104510 | /* |
| 104398 | 104511 | ** Cost X is tracked as 10*log2(X) stored in a 16-bit integer. The |
| 104399 | 104512 | ** maximum cost for ordinary tables is 64*(2**63) which becomes 6900. |
| 104400 | 104513 | ** (Virtual tables can return a larger cost, but let's assume they do not.) |
| @@ -104497,10 +104610,31 @@ | ||
| 104497 | 104610 | u16 nLSlot; /* Number of slots allocated for aLTerm[] */ |
| 104498 | 104611 | WhereTerm **aLTerm; /* WhereTerms used */ |
| 104499 | 104612 | WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */ |
| 104500 | 104613 | WhereTerm *aLTermSpace[4]; /* Initial aLTerm[] space */ |
| 104501 | 104614 | }; |
| 104615 | + | |
| 104616 | +/* This object holds the prerequisites and the cost of running a | |
| 104617 | +** subquery on one operand of an OR operator in the WHERE clause. | |
| 104618 | +** See WhereOrSet for additional information | |
| 104619 | +*/ | |
| 104620 | +struct WhereOrCost { | |
| 104621 | + Bitmask prereq; /* Prerequisites */ | |
| 104622 | + WhereCost rRun; /* Cost of running this subquery */ | |
| 104623 | + WhereCost nOut; /* Number of outputs for this subquery */ | |
| 104624 | +}; | |
| 104625 | + | |
| 104626 | +/* The WhereOrSet object holds a set of possible WhereOrCosts that | |
| 104627 | +** correspond to the subquery(s) of OR-clause processing. At most | |
| 104628 | +** favorable N_OR_COST elements are retained. | |
| 104629 | +*/ | |
| 104630 | +#define N_OR_COST 3 | |
| 104631 | +struct WhereOrSet { | |
| 104632 | + u16 n; /* Number of valid a[] entries */ | |
| 104633 | + WhereOrCost a[N_OR_COST]; /* Set of best costs */ | |
| 104634 | +}; | |
| 104635 | + | |
| 104502 | 104636 | |
| 104503 | 104637 | /* Forward declaration of methods */ |
| 104504 | 104638 | static int whereLoopResize(sqlite3*, WhereLoop*, int); |
| 104505 | 104639 | |
| 104506 | 104640 | /* |
| @@ -104712,11 +104846,11 @@ | ||
| 104712 | 104846 | struct WhereLoopBuilder { |
| 104713 | 104847 | WhereInfo *pWInfo; /* Information about this WHERE */ |
| 104714 | 104848 | WhereClause *pWC; /* WHERE clause terms */ |
| 104715 | 104849 | ExprList *pOrderBy; /* ORDER BY clause */ |
| 104716 | 104850 | WhereLoop *pNew; /* Template WhereLoop */ |
| 104717 | - WhereLoop *pBest; /* If non-NULL, store single best loop here */ | |
| 104851 | + WhereOrSet *pOrSet; /* Record best loops here, if not NULL */ | |
| 104718 | 104852 | }; |
| 104719 | 104853 | |
| 104720 | 104854 | /* |
| 104721 | 104855 | ** The WHERE clause processing routine has two halves. The |
| 104722 | 104856 | ** first part does the start of the WHERE loop and the second |
| @@ -104854,10 +104988,58 @@ | ||
| 104854 | 104988 | ** UPDATE or DELETE might change subsequent WHERE clause results. |
| 104855 | 104989 | */ |
| 104856 | 104990 | SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo *pWInfo){ |
| 104857 | 104991 | return pWInfo->okOnePass; |
| 104858 | 104992 | } |
| 104993 | + | |
| 104994 | +/* | |
| 104995 | +** Move the content of pSrc into pDest | |
| 104996 | +*/ | |
| 104997 | +static void whereOrMove(WhereOrSet *pDest, WhereOrSet *pSrc){ | |
| 104998 | + pDest->n = pSrc->n; | |
| 104999 | + memcpy(pDest->a, pSrc->a, pDest->n*sizeof(pDest->a[0])); | |
| 105000 | +} | |
| 105001 | + | |
| 105002 | +/* | |
| 105003 | +** Try to insert a new prerequisite/cost entry into the WhereOrSet pSet. | |
| 105004 | +** | |
| 105005 | +** The new entry might overwrite an existing entry, or it might be | |
| 105006 | +** appended, or it might be discarded. Do whatever is the right thing | |
| 105007 | +** so that pSet keeps the N_OR_COST best entries seen so far. | |
| 105008 | +*/ | |
| 105009 | +static int whereOrInsert( | |
| 105010 | + WhereOrSet *pSet, /* The WhereOrSet to be updated */ | |
| 105011 | + Bitmask prereq, /* Prerequisites of the new entry */ | |
| 105012 | + WhereCost rRun, /* Run-cost of the new entry */ | |
| 105013 | + WhereCost nOut /* Number of outputs for the new entry */ | |
| 105014 | +){ | |
| 105015 | + u16 i; | |
| 105016 | + WhereOrCost *p; | |
| 105017 | + for(i=pSet->n, p=pSet->a; i>0; i--, p++){ | |
| 105018 | + if( rRun<=p->rRun && (prereq & p->prereq)==prereq ){ | |
| 105019 | + goto whereOrInsert_done; | |
| 105020 | + } | |
| 105021 | + if( p->rRun<=rRun && (p->prereq & prereq)==p->prereq ){ | |
| 105022 | + return 0; | |
| 105023 | + } | |
| 105024 | + } | |
| 105025 | + if( pSet->n<N_OR_COST ){ | |
| 105026 | + p = &pSet->a[pSet->n++]; | |
| 105027 | + p->nOut = nOut; | |
| 105028 | + }else{ | |
| 105029 | + p = pSet->a; | |
| 105030 | + for(i=1; i<pSet->n; i++){ | |
| 105031 | + if( p->rRun>pSet->a[i].rRun ) p = pSet->a + i; | |
| 105032 | + } | |
| 105033 | + if( p->rRun<=rRun ) return 0; | |
| 105034 | + } | |
| 105035 | +whereOrInsert_done: | |
| 105036 | + p->prereq = prereq; | |
| 105037 | + p->rRun = rRun; | |
| 105038 | + if( p->nOut>nOut ) p->nOut = nOut; | |
| 105039 | + return 1; | |
| 105040 | +} | |
| 104859 | 105041 | |
| 104860 | 105042 | /* |
| 104861 | 105043 | ** Initialize a preallocated WhereClause structure. |
| 104862 | 105044 | */ |
| 104863 | 105045 | static void whereClauseInit( |
| @@ -108089,12 +108271,13 @@ | ||
| 108089 | 108271 | */ |
| 108090 | 108272 | if( pWC->nTerm>1 ){ |
| 108091 | 108273 | int iTerm; |
| 108092 | 108274 | for(iTerm=0; iTerm<pWC->nTerm; iTerm++){ |
| 108093 | 108275 | Expr *pExpr = pWC->a[iTerm].pExpr; |
| 108276 | + if( &pWC->a[iTerm] == pTerm ) continue; | |
| 108094 | 108277 | if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; |
| 108095 | - if( pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_ORINFO) ) continue; | |
| 108278 | + if( pWC->a[iTerm].wtFlags & (TERM_ORINFO) ) continue; | |
| 108096 | 108279 | if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; |
| 108097 | 108280 | pExpr = sqlite3ExprDup(pParse->db, pExpr, 0); |
| 108098 | 108281 | pAndExpr = sqlite3ExprAnd(pParse->db, pAndExpr, pExpr); |
| 108099 | 108282 | } |
| 108100 | 108283 | if( pAndExpr ){ |
| @@ -108418,16 +108601,16 @@ | ||
| 108418 | 108601 | ** is better and has fewer dependencies. Or the template will be ignored |
| 108419 | 108602 | ** and no insert will occur if an existing WhereLoop is faster and has |
| 108420 | 108603 | ** fewer dependencies than the template. Otherwise a new WhereLoop is |
| 108421 | 108604 | ** added based on the template. |
| 108422 | 108605 | ** |
| 108423 | -** If pBuilder->pBest is not NULL then we only care about the very | |
| 108424 | -** best template and that template should be stored in pBuilder->pBest. | |
| 108425 | -** If pBuilder->pBest is NULL then a list of the best templates are stored | |
| 108426 | -** in pBuilder->pWInfo->pLoops. | |
| 108606 | +** If pBuilder->pOrSet is not NULL then we only care about only the | |
| 108607 | +** prerequisites and rRun and nOut costs of the N best loops. That | |
| 108608 | +** information is gathered in the pBuilder->pOrSet object. This special | |
| 108609 | +** processing mode is used only for OR clause processing. | |
| 108427 | 108610 | ** |
| 108428 | -** When accumulating multiple loops (when pBuilder->pBest is NULL) we | |
| 108611 | +** When accumulating multiple loops (when pBuilder->pOrSet is NULL) we | |
| 108429 | 108612 | ** still might overwrite similar loops with the new template if the |
| 108430 | 108613 | ** template is better. Loops may be overwritten if the following |
| 108431 | 108614 | ** conditions are met: |
| 108432 | 108615 | ** |
| 108433 | 108616 | ** (1) They have the same iTab. |
| @@ -108440,34 +108623,26 @@ | ||
| 108440 | 108623 | static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ |
| 108441 | 108624 | WhereLoop **ppPrev, *p, *pNext = 0; |
| 108442 | 108625 | WhereInfo *pWInfo = pBuilder->pWInfo; |
| 108443 | 108626 | sqlite3 *db = pWInfo->pParse->db; |
| 108444 | 108627 | |
| 108445 | - /* If pBuilder->pBest is defined, then only keep track of the single | |
| 108446 | - ** best WhereLoop. pBuilder->pBest->maskSelf==0 indicates that no | |
| 108447 | - ** prior WhereLoops have been evaluated and that the current pTemplate | |
| 108448 | - ** is therefore the first and hence the best and should be retained. | |
| 108628 | + /* If pBuilder->pOrSet is defined, then only keep track of the costs | |
| 108629 | + ** and prereqs. | |
| 108449 | 108630 | */ |
| 108450 | - if( (p = pBuilder->pBest)!=0 ){ | |
| 108451 | - if( p->maskSelf!=0 ){ | |
| 108452 | - WhereCost rCost = whereCostAdd(p->rRun,p->rSetup); | |
| 108453 | - WhereCost rTemplate = whereCostAdd(pTemplate->rRun,pTemplate->rSetup); | |
| 108454 | - if( rCost < rTemplate ){ | |
| 108455 | - testcase( rCost==rTemplate-1 ); | |
| 108456 | - goto whereLoopInsert_noop; | |
| 108457 | - } | |
| 108458 | - if( rCost==rTemplate && (p->prereq & pTemplate->prereq)==p->prereq ){ | |
| 108459 | - goto whereLoopInsert_noop; | |
| 108460 | - } | |
| 108461 | - } | |
| 108631 | + if( pBuilder->pOrSet!=0 ){ | |
| 108632 | +#if WHERETRACE_ENABLED | |
| 108633 | + u16 n = pBuilder->pOrSet->n; | |
| 108634 | + int x = | |
| 108635 | +#endif | |
| 108636 | + whereOrInsert(pBuilder->pOrSet, pTemplate->prereq, pTemplate->rRun, | |
| 108637 | + pTemplate->nOut); | |
| 108462 | 108638 | #if WHERETRACE_ENABLED |
| 108463 | 108639 | if( sqlite3WhereTrace & 0x8 ){ |
| 108464 | - sqlite3DebugPrintf(p->maskSelf==0 ? "ins-init: " : "ins-best: "); | |
| 108640 | + sqlite3DebugPrintf(x?" or-%d: ":" or-X: ", n); | |
| 108465 | 108641 | whereLoopPrint(pTemplate, pWInfo->pTabList); |
| 108466 | 108642 | } |
| 108467 | 108643 | #endif |
| 108468 | - whereLoopXfer(db, p, pTemplate); | |
| 108469 | 108644 | return SQLITE_OK; |
| 108470 | 108645 | } |
| 108471 | 108646 | |
| 108472 | 108647 | /* Search for an existing WhereLoop to overwrite, or which takes |
| 108473 | 108648 | ** priority over pTemplate. |
| @@ -108557,11 +108732,11 @@ | ||
| 108557 | 108732 | |
| 108558 | 108733 | /* Jump here if the insert is a no-op */ |
| 108559 | 108734 | whereLoopInsert_noop: |
| 108560 | 108735 | #if WHERETRACE_ENABLED |
| 108561 | 108736 | if( sqlite3WhereTrace & 0x8 ){ |
| 108562 | - sqlite3DebugPrintf(pBuilder->pBest ? "ins-skip: " : "ins-noop: "); | |
| 108737 | + sqlite3DebugPrintf("ins-noop: "); | |
| 108563 | 108738 | whereLoopPrint(pTemplate, pWInfo->pTabList); |
| 108564 | 108739 | } |
| 108565 | 108740 | #endif |
| 108566 | 108741 | return SQLITE_OK; |
| 108567 | 108742 | } |
| @@ -108839,11 +109014,11 @@ | ||
| 108839 | 109014 | } |
| 108840 | 109015 | rSize = whereCost(pSrc->pTab->nRowEst); |
| 108841 | 109016 | rLogSize = estLog(rSize); |
| 108842 | 109017 | |
| 108843 | 109018 | /* Automatic indexes */ |
| 108844 | - if( !pBuilder->pBest | |
| 109019 | + if( !pBuilder->pOrSet | |
| 108845 | 109020 | && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0 |
| 108846 | 109021 | && pSrc->pIndex==0 |
| 108847 | 109022 | && !pSrc->viaCoroutine |
| 108848 | 109023 | && !pSrc->notIndexed |
| 108849 | 109024 | && !pSrc->isCorrelated |
| @@ -109125,11 +109300,11 @@ | ||
| 109125 | 109300 | WhereTerm *pTerm, *pWCEnd; |
| 109126 | 109301 | int rc = SQLITE_OK; |
| 109127 | 109302 | int iCur; |
| 109128 | 109303 | WhereClause tempWC; |
| 109129 | 109304 | WhereLoopBuilder sSubBuild; |
| 109130 | - WhereLoop sBest; | |
| 109305 | + WhereOrSet sSum, sCur, sPrev; | |
| 109131 | 109306 | struct SrcList_item *pItem; |
| 109132 | 109307 | |
| 109133 | 109308 | pWC = pBuilder->pWC; |
| 109134 | 109309 | if( pWInfo->wctrlFlags & WHERE_AND_ONLY ) return SQLITE_OK; |
| 109135 | 109310 | pWCEnd = pWC->a + pWC->nTerm; |
| @@ -109140,20 +109315,18 @@ | ||
| 109140 | 109315 | && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0 |
| 109141 | 109316 | ){ |
| 109142 | 109317 | WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc; |
| 109143 | 109318 | WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm]; |
| 109144 | 109319 | WhereTerm *pOrTerm; |
| 109145 | - WhereCost rTotal = 0; | |
| 109146 | - WhereCost nRow = 0; | |
| 109147 | - Bitmask prereq = mExtra; | |
| 109320 | + int once = 1; | |
| 109321 | + int i, j; | |
| 109148 | 109322 | |
| 109149 | - whereLoopInit(&sBest); | |
| 109150 | 109323 | pItem = pWInfo->pTabList->a + pNew->iTab; |
| 109151 | 109324 | iCur = pItem->iCursor; |
| 109152 | 109325 | sSubBuild = *pBuilder; |
| 109153 | 109326 | sSubBuild.pOrderBy = 0; |
| 109154 | - sSubBuild.pBest = &sBest; | |
| 109327 | + sSubBuild.pOrSet = &sCur; | |
| 109155 | 109328 | |
| 109156 | 109329 | for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){ |
| 109157 | 109330 | if( (pOrTerm->eOperator & WO_AND)!=0 ){ |
| 109158 | 109331 | sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc; |
| 109159 | 109332 | }else if( pOrTerm->leftCursor==iCur ){ |
| @@ -109164,43 +109337,52 @@ | ||
| 109164 | 109337 | tempWC.a = pOrTerm; |
| 109165 | 109338 | sSubBuild.pWC = &tempWC; |
| 109166 | 109339 | }else{ |
| 109167 | 109340 | continue; |
| 109168 | 109341 | } |
| 109169 | - sBest.maskSelf = 0; | |
| 109170 | - sBest.rSetup = 0; | |
| 109171 | - sBest.rRun = 0; | |
| 109342 | + sCur.n = 0; | |
| 109172 | 109343 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 109173 | 109344 | if( IsVirtual(pItem->pTab) ){ |
| 109174 | 109345 | rc = whereLoopAddVirtual(&sSubBuild); |
| 109346 | + for(i=0; i<sCur.n; i++) sCur.a[i].prereq |= mExtra; | |
| 109175 | 109347 | }else |
| 109176 | 109348 | #endif |
| 109177 | 109349 | { |
| 109178 | 109350 | rc = whereLoopAddBtree(&sSubBuild, mExtra); |
| 109179 | 109351 | } |
| 109180 | - /* sBest.maskSelf is always zero if an error occurs */ | |
| 109181 | - assert( rc==SQLITE_OK || sBest.maskSelf==0 ); | |
| 109182 | - if( sBest.maskSelf==0 ) break; | |
| 109183 | - assert( sBest.rSetup==0 ); | |
| 109184 | - rTotal = whereCostAdd(rTotal, sBest.rRun); | |
| 109185 | - nRow = whereCostAdd(nRow, sBest.nOut); | |
| 109186 | - prereq |= sBest.prereq; | |
| 109187 | - } | |
| 109188 | - assert( pNew->nLSlot>=1 ); | |
| 109189 | - if( sBest.maskSelf ){ | |
| 109190 | - pNew->nLTerm = 1; | |
| 109191 | - pNew->aLTerm[0] = pTerm; | |
| 109192 | - pNew->wsFlags = WHERE_MULTI_OR; | |
| 109193 | - pNew->rSetup = 0; | |
| 109352 | + assert( rc==SQLITE_OK || sCur.n==0 ); | |
| 109353 | + if( sCur.n==0 ){ | |
| 109354 | + sSum.n = 0; | |
| 109355 | + break; | |
| 109356 | + }else if( once ){ | |
| 109357 | + whereOrMove(&sSum, &sCur); | |
| 109358 | + once = 0; | |
| 109359 | + }else{ | |
| 109360 | + whereOrMove(&sPrev, &sSum); | |
| 109361 | + sSum.n = 0; | |
| 109362 | + for(i=0; i<sPrev.n; i++){ | |
| 109363 | + for(j=0; j<sCur.n; j++){ | |
| 109364 | + whereOrInsert(&sSum, sPrev.a[i].prereq | sCur.a[j].prereq, | |
| 109365 | + whereCostAdd(sPrev.a[i].rRun, sCur.a[j].rRun), | |
| 109366 | + whereCostAdd(sPrev.a[i].nOut, sCur.a[j].nOut)); | |
| 109367 | + } | |
| 109368 | + } | |
| 109369 | + } | |
| 109370 | + } | |
| 109371 | + pNew->nLTerm = 1; | |
| 109372 | + pNew->aLTerm[0] = pTerm; | |
| 109373 | + pNew->wsFlags = WHERE_MULTI_OR; | |
| 109374 | + pNew->rSetup = 0; | |
| 109375 | + pNew->iSortIdx = 0; | |
| 109376 | + memset(&pNew->u, 0, sizeof(pNew->u)); | |
| 109377 | + for(i=0; rc==SQLITE_OK && i<sSum.n; i++){ | |
| 109194 | 109378 | /* TUNING: Multiple by 3.5 for the secondary table lookup */ |
| 109195 | - pNew->rRun = rTotal + 18; assert( 18==whereCost(7)-whereCost(2) ); | |
| 109196 | - pNew->nOut = nRow; | |
| 109197 | - pNew->prereq = prereq; | |
| 109198 | - memset(&pNew->u, 0, sizeof(pNew->u)); | |
| 109379 | + pNew->rRun = sSum.a[i].rRun + 18; | |
| 109380 | + pNew->nOut = sSum.a[i].nOut; | |
| 109381 | + pNew->prereq = sSum.a[i].prereq; | |
| 109199 | 109382 | rc = whereLoopInsert(pBuilder, pNew); |
| 109200 | 109383 | } |
| 109201 | - whereLoopClear(pWInfo->pParse->db, &sBest); | |
| 109202 | 109384 | } |
| 109203 | 109385 | } |
| 109204 | 109386 | return rc; |
| 109205 | 109387 | } |
| 109206 | 109388 | |
| @@ -110003,11 +110185,12 @@ | ||
| 110003 | 110185 | pWInfo->wctrlFlags = wctrlFlags; |
| 110004 | 110186 | pWInfo->savedNQueryLoop = pParse->nQueryLoop; |
| 110005 | 110187 | pMaskSet = &pWInfo->sMaskSet; |
| 110006 | 110188 | sWLB.pWInfo = pWInfo; |
| 110007 | 110189 | sWLB.pWC = &pWInfo->sWC; |
| 110008 | - sWLB.pNew = (WhereLoop*)&pWInfo->a[nTabList]; | |
| 110190 | + sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo); | |
| 110191 | + assert( EIGHT_BYTE_ALIGNMENT(sWLB.pNew) ); | |
| 110009 | 110192 | whereLoopInit(sWLB.pNew); |
| 110010 | 110193 | #ifdef SQLITE_DEBUG |
| 110011 | 110194 | sWLB.pNew->cId = '*'; |
| 110012 | 110195 | #endif |
| 110013 | 110196 | |
| @@ -116127,10 +116310,12 @@ | ||
| 116127 | 116310 | } |
| 116128 | 116311 | sqlite3BtreeLeaveAll(db); |
| 116129 | 116312 | |
| 116130 | 116313 | /* Any deferred constraint violations have now been resolved. */ |
| 116131 | 116314 | db->nDeferredCons = 0; |
| 116315 | + db->nDeferredImmCons = 0; | |
| 116316 | + db->flags &= ~SQLITE_DeferFKs; | |
| 116132 | 116317 | |
| 116133 | 116318 | /* If one has been configured, invoke the rollback-hook callback */ |
| 116134 | 116319 | if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){ |
| 116135 | 116320 | db->xRollbackCallback(db->pRollbackArg); |
| 116136 | 116321 | } |
| @@ -116388,11 +116573,11 @@ | ||
| 116388 | 116573 | void *pArg |
| 116389 | 116574 | ){ |
| 116390 | 116575 | sqlite3_mutex_enter(db->mutex); |
| 116391 | 116576 | if( nOps>0 ){ |
| 116392 | 116577 | db->xProgress = xProgress; |
| 116393 | - db->nProgressOps = nOps; | |
| 116578 | + db->nProgressOps = (unsigned)nOps; | |
| 116394 | 116579 | db->pProgressArg = pArg; |
| 116395 | 116580 | }else{ |
| 116396 | 116581 | db->xProgress = 0; |
| 116397 | 116582 | db->nProgressOps = 0; |
| 116398 | 116583 | db->pProgressArg = 0; |
| @@ -119087,11 +119272,11 @@ | ||
| 119087 | 119272 | |
| 119088 | 119273 | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) |
| 119089 | 119274 | |
| 119090 | 119275 | /* If not building as part of the core, include sqlite3ext.h. */ |
| 119091 | 119276 | #ifndef SQLITE_CORE |
| 119092 | -SQLITE_API extern const sqlite3_api_routines *sqlite3_api; | |
| 119277 | +SQLITE_EXTENSION_INIT3 | |
| 119093 | 119278 | #endif |
| 119094 | 119279 | |
| 119095 | 119280 | /************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/ |
| 119096 | 119281 | /************** Begin file fts3_tokenizer.h **********************************/ |
| 119097 | 119282 | /* |
| @@ -124995,11 +125180,14 @@ | ||
| 124995 | 125180 | |
| 124996 | 125181 | #if !SQLITE_CORE |
| 124997 | 125182 | /* |
| 124998 | 125183 | ** Initialize API pointer table, if required. |
| 124999 | 125184 | */ |
| 125000 | -SQLITE_API int sqlite3_extension_init( | |
| 125185 | +#ifdef _WIN32 | |
| 125186 | +__declspec(dllexport) | |
| 125187 | +#endif | |
| 125188 | +SQLITE_API int sqlite3_fts3_init( | |
| 125001 | 125189 | sqlite3 *db, |
| 125002 | 125190 | char **pzErrMsg, |
| 125003 | 125191 | const sqlite3_api_routines *pApi |
| 125004 | 125192 | ){ |
| 125005 | 125193 | SQLITE_EXTENSION_INIT2(pApi) |
| @@ -140042,11 +140230,14 @@ | ||
| 140042 | 140230 | (void *)pGeomCtx, geomCallback, 0, 0, doSqlite3Free |
| 140043 | 140231 | ); |
| 140044 | 140232 | } |
| 140045 | 140233 | |
| 140046 | 140234 | #if !SQLITE_CORE |
| 140047 | -SQLITE_API int sqlite3_extension_init( | |
| 140235 | +#ifdef _WIN32 | |
| 140236 | +__declspec(dllexport) | |
| 140237 | +#endif | |
| 140238 | +SQLITE_API int sqlite3_rtree_init( | |
| 140048 | 140239 | sqlite3 *db, |
| 140049 | 140240 | char **pzErrMsg, |
| 140050 | 140241 | const sqlite3_api_routines *pApi |
| 140051 | 140242 | ){ |
| 140052 | 140243 | SQLITE_EXTENSION_INIT2(pApi) |
| @@ -140544,11 +140735,14 @@ | ||
| 140544 | 140735 | |
| 140545 | 140736 | return rc; |
| 140546 | 140737 | } |
| 140547 | 140738 | |
| 140548 | 140739 | #if !SQLITE_CORE |
| 140549 | -SQLITE_API int sqlite3_extension_init( | |
| 140740 | +#ifdef _WIN32 | |
| 140741 | +__declspec(dllexport) | |
| 140742 | +#endif | |
| 140743 | +SQLITE_API int sqlite3_icu_init( | |
| 140550 | 140744 | sqlite3 *db, |
| 140551 | 140745 | char **pzErrMsg, |
| 140552 | 140746 | const sqlite3_api_routines *pApi |
| 140553 | 140747 | ){ |
| 140554 | 140748 | SQLITE_EXTENSION_INIT2(pApi) |
| 140555 | 140749 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -670,11 +670,11 @@ | |
| 670 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 671 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 672 | */ |
| 673 | #define SQLITE_VERSION "3.8.0" |
| 674 | #define SQLITE_VERSION_NUMBER 3008000 |
| 675 | #define SQLITE_SOURCE_ID "2013-07-09 03:04:32 52a49cbc1621094b2fe2b021209b768d29e0426b" |
| 676 | |
| 677 | /* |
| 678 | ** CAPI3REF: Run-Time Library Version Numbers |
| 679 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 680 | ** |
| @@ -3120,11 +3120,11 @@ | |
| 3120 | ** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for |
| 3121 | ** database connection D. An example use for this |
| 3122 | ** interface is to keep a GUI updated during a large query. |
| 3123 | ** |
| 3124 | ** ^The parameter P is passed through as the only parameter to the |
| 3125 | ** callback function X. ^The parameter N is the number of |
| 3126 | ** [virtual machine instructions] that are evaluated between successive |
| 3127 | ** invocations of the callback X. |
| 3128 | ** |
| 3129 | ** ^Only a single progress handler may be defined at one time per |
| 3130 | ** [database connection]; setting a new progress handler cancels the |
| @@ -4745,12 +4745,12 @@ | |
| 4745 | ** CAPI3REF: Function Auxiliary Data |
| 4746 | ** |
| 4747 | ** The following two functions may be used by scalar SQL functions to |
| 4748 | ** associate metadata with argument values. If the same value is passed to |
| 4749 | ** multiple invocations of the same SQL function during query execution, under |
| 4750 | ** some circumstances the associated metadata may be preserved. This may |
| 4751 | ** be used, for example, to add a regular-expression matching scalar |
| 4752 | ** function. The compiled version of the regular expression is stored as |
| 4753 | ** metadata associated with the SQL value passed as the regular expression |
| 4754 | ** pattern. The compiled regular expression can be reused on multiple |
| 4755 | ** invocations of the same function so that the original pattern string |
| 4756 | ** does not need to be recompiled on each invocation. |
| @@ -4760,27 +4760,36 @@ | |
| 4760 | ** value to the application-defined function. ^If no metadata has been ever |
| 4761 | ** been set for the Nth argument of the function, or if the corresponding |
| 4762 | ** function parameter has changed since the meta-data was set, |
| 4763 | ** then sqlite3_get_auxdata() returns a NULL pointer. |
| 4764 | ** |
| 4765 | ** ^The sqlite3_set_auxdata() interface saves the metadata |
| 4766 | ** pointed to by its 3rd parameter as the metadata for the N-th |
| 4767 | ** argument of the application-defined function. Subsequent |
| 4768 | ** calls to sqlite3_get_auxdata() might return this data, if it has |
| 4769 | ** not been destroyed. |
| 4770 | ** ^If it is not NULL, SQLite will invoke the destructor |
| 4771 | ** function given by the 4th parameter to sqlite3_set_auxdata() on |
| 4772 | ** the metadata when the corresponding function parameter changes |
| 4773 | ** or when the SQL statement completes, whichever comes first. |
| 4774 | ** |
| 4775 | ** SQLite is free to call the destructor and drop metadata on any |
| 4776 | ** parameter of any function at any time. ^The only guarantee is that |
| 4777 | ** the destructor will be called before the metadata is dropped. |
| 4778 | ** |
| 4779 | ** ^(In practice, metadata is preserved between function calls for |
| 4780 | ** expressions that are constant at compile time. This includes literal |
| 4781 | ** values and [parameters].)^ |
| 4782 | ** |
| 4783 | ** These routines must be called from the same thread in which |
| 4784 | ** the SQL function is running. |
| 4785 | */ |
| 4786 | SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); |
| @@ -5689,14 +5698,27 @@ | |
| 5689 | ** |
| 5690 | ** ^Calling sqlite3_auto_extension(X) with an entry point X that is already |
| 5691 | ** on the list of automatic extensions is a harmless no-op. ^No entry point |
| 5692 | ** will be called more than once for each database connection that is opened. |
| 5693 | ** |
| 5694 | ** See also: [sqlite3_reset_auto_extension()]. |
| 5695 | */ |
| 5696 | SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void)); |
| 5697 | |
| 5698 | /* |
| 5699 | ** CAPI3REF: Reset Automatic Extension Loading |
| 5700 | ** |
| 5701 | ** ^This interface disables all automatic extensions previously |
| 5702 | ** registered using [sqlite3_auto_extension()]. |
| @@ -6805,10 +6827,16 @@ | |
| 6805 | ** transaction rollback or database recovery operations are not included. |
| 6806 | ** If an IO or other error occurs while writing a page to disk, the effect |
| 6807 | ** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The |
| 6808 | ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. |
| 6809 | ** </dd> |
| 6810 | ** </dl> |
| 6811 | */ |
| 6812 | #define SQLITE_DBSTATUS_LOOKASIDE_USED 0 |
| 6813 | #define SQLITE_DBSTATUS_CACHE_USED 1 |
| 6814 | #define SQLITE_DBSTATUS_SCHEMA_USED 2 |
| @@ -6817,11 +6845,12 @@ | |
| 6817 | #define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5 |
| 6818 | #define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 |
| 6819 | #define SQLITE_DBSTATUS_CACHE_HIT 7 |
| 6820 | #define SQLITE_DBSTATUS_CACHE_MISS 8 |
| 6821 | #define SQLITE_DBSTATUS_CACHE_WRITE 9 |
| 6822 | #define SQLITE_DBSTATUS_MAX 9 /* Largest defined DBSTATUS */ |
| 6823 | |
| 6824 | |
| 6825 | /* |
| 6826 | ** CAPI3REF: Prepared Statement Status |
| 6827 | ** |
| @@ -10117,11 +10146,11 @@ | |
| 10117 | void *pAuthArg; /* 1st argument to the access auth function */ |
| 10118 | #endif |
| 10119 | #ifndef SQLITE_OMIT_PROGRESS_CALLBACK |
| 10120 | int (*xProgress)(void *); /* The progress callback */ |
| 10121 | void *pProgressArg; /* Argument to the progress callback */ |
| 10122 | int nProgressOps; /* Number of opcodes for progress callback */ |
| 10123 | #endif |
| 10124 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 10125 | int nVTrans; /* Allocated size of aVTrans */ |
| 10126 | Hash aModule; /* populated by sqlite3_create_module() */ |
| 10127 | VtabCtx *pVtabCtx; /* Context for active vtab connect/create */ |
| @@ -10135,10 +10164,11 @@ | |
| 10135 | Savepoint *pSavepoint; /* List of active savepoints */ |
| 10136 | int busyTimeout; /* Busy handler timeout, in msec */ |
| 10137 | int nSavepoint; /* Number of non-transaction savepoints */ |
| 10138 | int nStatement; /* Number of nested statement-transactions */ |
| 10139 | i64 nDeferredCons; /* Net deferred constraints this transaction. */ |
| 10140 | int *pnBytesFreed; /* If not NULL, increment this in DbFree() */ |
| 10141 | |
| 10142 | #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY |
| 10143 | /* The following variables are all protected by the STATIC_MASTER |
| 10144 | ** mutex, not by sqlite3.mutex. They are used by code in notify.c. |
| @@ -10190,10 +10220,13 @@ | |
| 10190 | #define SQLITE_ForeignKeys 0x00040000 /* Enforce foreign key constraints */ |
| 10191 | #define SQLITE_AutoIndex 0x00080000 /* Enable automatic indexes */ |
| 10192 | #define SQLITE_PreferBuiltin 0x00100000 /* Preference to built-in funcs */ |
| 10193 | #define SQLITE_LoadExtension 0x00200000 /* Enable load_extension */ |
| 10194 | #define SQLITE_EnableTrigger 0x00400000 /* True to enable triggers */ |
| 10195 | |
| 10196 | /* |
| 10197 | ** Bits of the sqlite3.dbOptFlags field that are used by the |
| 10198 | ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to |
| 10199 | ** selectively disable various optimizations. |
| @@ -10336,10 +10369,11 @@ | |
| 10336 | ** OP_Savepoint instruction. |
| 10337 | */ |
| 10338 | struct Savepoint { |
| 10339 | char *zName; /* Savepoint name (nul-terminated) */ |
| 10340 | i64 nDeferredCons; /* Number of deferred fk violations */ |
| 10341 | Savepoint *pNext; /* Parent savepoint (if any) */ |
| 10342 | }; |
| 10343 | |
| 10344 | /* |
| 10345 | ** The following are used as the second parameter to sqlite3Savepoint(), |
| @@ -13530,10 +13564,11 @@ | |
| 13530 | #ifndef SQLITE_OMIT_TRACE |
| 13531 | i64 startTime; /* Time when query started - used for profiling */ |
| 13532 | #endif |
| 13533 | i64 nFkConstraint; /* Number of imm. FK constraints this VM */ |
| 13534 | i64 nStmtDefCons; /* Number of def. constraints when stmt started */ |
| 13535 | char *zSql; /* Text of the SQL statement that generated this */ |
| 13536 | void *pFree; /* Free this when deleting the vdbe */ |
| 13537 | #ifdef SQLITE_DEBUG |
| 13538 | FILE *trace; /* Write an execution trace here, if not NULL */ |
| 13539 | #endif |
| @@ -13889,10 +13924,20 @@ | |
| 13889 | } |
| 13890 | *pHighwater = 0; |
| 13891 | *pCurrent = nRet; |
| 13892 | break; |
| 13893 | } |
| 13894 | |
| 13895 | default: { |
| 13896 | rc = SQLITE_ERROR; |
| 13897 | } |
| 13898 | } |
| @@ -61946,10 +61991,11 @@ | |
| 61946 | /* If the statement transaction is being rolled back, also restore the |
| 61947 | ** database handles deferred constraint counter to the value it had when |
| 61948 | ** the statement transaction was opened. */ |
| 61949 | if( eOp==SAVEPOINT_ROLLBACK ){ |
| 61950 | db->nDeferredCons = p->nStmtDefCons; |
| 61951 | } |
| 61952 | } |
| 61953 | return rc; |
| 61954 | } |
| 61955 | |
| @@ -61964,11 +62010,13 @@ | |
| 61964 | ** and write an error message to it. Then return SQLITE_ERROR. |
| 61965 | */ |
| 61966 | #ifndef SQLITE_OMIT_FOREIGN_KEY |
| 61967 | SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){ |
| 61968 | sqlite3 *db = p->db; |
| 61969 | if( (deferred && db->nDeferredCons>0) || (!deferred && p->nFkConstraint>0) ){ |
| 61970 | p->rc = SQLITE_CONSTRAINT_FOREIGNKEY; |
| 61971 | p->errorAction = OE_Abort; |
| 61972 | sqlite3SetString(&p->zErrMsg, db, "foreign key constraint failed"); |
| 61973 | return SQLITE_ERROR; |
| 61974 | } |
| @@ -62097,10 +62145,12 @@ | |
| 62097 | }else if( rc!=SQLITE_OK ){ |
| 62098 | p->rc = rc; |
| 62099 | sqlite3RollbackAll(db, SQLITE_OK); |
| 62100 | }else{ |
| 62101 | db->nDeferredCons = 0; |
| 62102 | sqlite3CommitInternalChanges(db); |
| 62103 | } |
| 62104 | }else{ |
| 62105 | sqlite3RollbackAll(db, SQLITE_OK); |
| 62106 | } |
| @@ -63536,11 +63586,13 @@ | |
| 63536 | */ |
| 63537 | if( db->nVdbeActive==0 ){ |
| 63538 | db->u1.isInterrupted = 0; |
| 63539 | } |
| 63540 | |
| 63541 | assert( db->nVdbeWrite>0 || db->autoCommit==0 || db->nDeferredCons==0 ); |
| 63542 | |
| 63543 | #ifndef SQLITE_OMIT_TRACE |
| 63544 | if( db->xProfile && !db->init.busy ){ |
| 63545 | sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime); |
| 63546 | } |
| @@ -65384,16 +65436,15 @@ | |
| 65384 | Op *pOp; /* Current operation */ |
| 65385 | int rc = SQLITE_OK; /* Value to return */ |
| 65386 | sqlite3 *db = p->db; /* The database */ |
| 65387 | u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ |
| 65388 | u8 encoding = ENC(db); /* The database encoding */ |
| 65389 | #ifndef SQLITE_OMIT_PROGRESS_CALLBACK |
| 65390 | int checkProgress; /* True if progress callbacks are enabled */ |
| 65391 | int nProgressOps = 0; /* Opcodes executed since progress callback. */ |
| 65392 | #endif |
| 65393 | int iCompare = 0; /* Result of last OP_Compare operation */ |
| 65394 | unsigned nVmStep = 0; /* Number of virtual machine steps */ |
| 65395 | Mem *aMem = p->aMem; /* Copy of p->aMem */ |
| 65396 | Mem *pIn1 = 0; /* 1st input operand */ |
| 65397 | Mem *pIn2 = 0; /* 2nd input operand */ |
| 65398 | Mem *pIn3 = 0; /* 3rd input operand */ |
| 65399 | Mem *pOut = 0; /* Output operand */ |
| @@ -65847,13 +65898,10 @@ | |
| 65847 | assert( p->explain==0 ); |
| 65848 | p->pResultSet = 0; |
| 65849 | db->busyHandler.nBusy = 0; |
| 65850 | CHECK_FOR_INTERRUPT; |
| 65851 | sqlite3VdbeIOTraceSql(p); |
| 65852 | #ifndef SQLITE_OMIT_PROGRESS_CALLBACK |
| 65853 | checkProgress = db->xProgress!=0; |
| 65854 | #endif |
| 65855 | #ifdef SQLITE_DEBUG |
| 65856 | sqlite3BeginBenignMalloc(); |
| 65857 | if( p->pc==0 && (p->db->flags & SQLITE_VdbeListing)!=0 ){ |
| 65858 | int i; |
| 65859 | printf("VDBE Program Listing:\n"); |
| @@ -65895,31 +65943,10 @@ | |
| 65895 | sqlite3_interrupt_count--; |
| 65896 | if( sqlite3_interrupt_count==0 ){ |
| 65897 | sqlite3_interrupt(db); |
| 65898 | } |
| 65899 | } |
| 65900 | #endif |
| 65901 | |
| 65902 | #ifndef SQLITE_OMIT_PROGRESS_CALLBACK |
| 65903 | /* Call the progress callback if it is configured and the required number |
| 65904 | ** of VDBE ops have been executed (either since this invocation of |
| 65905 | ** sqlite3VdbeExec() or since last time the progress callback was called). |
| 65906 | ** If the progress callback returns non-zero, exit the virtual machine with |
| 65907 | ** a return code SQLITE_ABORT. |
| 65908 | */ |
| 65909 | if( checkProgress ){ |
| 65910 | if( db->nProgressOps==nProgressOps ){ |
| 65911 | int prc; |
| 65912 | prc = db->xProgress(db->pProgressArg); |
| 65913 | if( prc!=0 ){ |
| 65914 | rc = SQLITE_INTERRUPT; |
| 65915 | goto vdbe_error_halt; |
| 65916 | } |
| 65917 | nProgressOps = 0; |
| 65918 | } |
| 65919 | nProgressOps++; |
| 65920 | } |
| 65921 | #endif |
| 65922 | |
| 65923 | /* On any opcode with the "out2-prerelease" tag, free any |
| 65924 | ** external allocations out of mem[p2] and set mem[p2] to be |
| 65925 | ** an undefined integer. Opcodes will either fill in the integer |
| @@ -66010,12 +66037,42 @@ | |
| 66010 | ** The next instruction executed will be |
| 66011 | ** the one at index P2 from the beginning of |
| 66012 | ** the program. |
| 66013 | */ |
| 66014 | case OP_Goto: { /* jump */ |
| 66015 | CHECK_FOR_INTERRUPT; |
| 66016 | pc = pOp->p2 - 1; |
| 66017 | break; |
| 66018 | } |
| 66019 | |
| 66020 | /* Opcode: Gosub P1 P2 * * * |
| 66021 | ** |
| @@ -66132,11 +66189,11 @@ | |
| 66132 | assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR ); |
| 66133 | if( rc==SQLITE_BUSY ){ |
| 66134 | p->rc = rc = SQLITE_BUSY; |
| 66135 | }else{ |
| 66136 | assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ); |
| 66137 | assert( rc==SQLITE_OK || db->nDeferredCons>0 ); |
| 66138 | rc = p->rc ? SQLITE_ERROR : SQLITE_DONE; |
| 66139 | } |
| 66140 | goto vdbe_return; |
| 66141 | } |
| 66142 | |
| @@ -68028,10 +68085,11 @@ | |
| 68028 | |
| 68029 | /* Link the new savepoint into the database handle's list. */ |
| 68030 | u.as.pNew->pNext = db->pSavepoint; |
| 68031 | db->pSavepoint = u.as.pNew; |
| 68032 | u.as.pNew->nDeferredCons = db->nDeferredCons; |
| 68033 | } |
| 68034 | } |
| 68035 | }else{ |
| 68036 | u.as.iSavepoint = 0; |
| 68037 | |
| @@ -68115,10 +68173,11 @@ | |
| 68115 | if( !isTransaction ){ |
| 68116 | db->nSavepoint--; |
| 68117 | } |
| 68118 | }else{ |
| 68119 | db->nDeferredCons = u.as.pSavepoint->nDeferredCons; |
| 68120 | } |
| 68121 | |
| 68122 | if( !isTransaction ){ |
| 68123 | rc = sqlite3VtabSavepoint(db, u.as.p1, u.as.iSavepoint); |
| 68124 | if( rc!=SQLITE_OK ) goto abort_due_to_error; |
| @@ -68244,10 +68303,14 @@ | |
| 68244 | |
| 68245 | assert( p->bIsReader ); |
| 68246 | assert( p->readOnly==0 || pOp->p2==0 ); |
| 68247 | assert( pOp->p1>=0 && pOp->p1<db->nDb ); |
| 68248 | assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 ); |
| 68249 | u.au.pBt = db->aDb[pOp->p1].pBt; |
| 68250 | |
| 68251 | if( u.au.pBt ){ |
| 68252 | rc = sqlite3BtreeBeginTrans(u.au.pBt, pOp->p2); |
| 68253 | if( rc==SQLITE_BUSY ){ |
| @@ -68276,10 +68339,11 @@ | |
| 68276 | |
| 68277 | /* Store the current value of the database handles deferred constraint |
| 68278 | ** counter. If the statement transaction needs to be rolled back, |
| 68279 | ** the value of this counter needs to be restored too. */ |
| 68280 | p->nStmtDefCons = db->nDeferredCons; |
| 68281 | } |
| 68282 | } |
| 68283 | break; |
| 68284 | } |
| 68285 | |
| @@ -69851,11 +69915,10 @@ | |
| 69851 | #if 0 /* local variables moved into u.br */ |
| 69852 | VdbeCursor *pC; |
| 69853 | int res; |
| 69854 | #endif /* local variables moved into u.br */ |
| 69855 | |
| 69856 | CHECK_FOR_INTERRUPT; |
| 69857 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); |
| 69858 | assert( pOp->p5<=ArraySize(p->aCounter) ); |
| 69859 | u.br.pC = p->apCsr[pOp->p1]; |
| 69860 | if( u.br.pC==0 ){ |
| 69861 | break; /* See ticket #2273 */ |
| @@ -69880,11 +69943,11 @@ | |
| 69880 | #ifdef SQLITE_TEST |
| 69881 | sqlite3_search_count++; |
| 69882 | #endif |
| 69883 | } |
| 69884 | u.br.pC->rowidIsValid = 0; |
| 69885 | break; |
| 69886 | } |
| 69887 | |
| 69888 | /* Opcode: IdxInsert P1 P2 P3 * P5 |
| 69889 | ** |
| 69890 | ** Register P2 holds an SQL index key made using the |
| @@ -70426,11 +70489,11 @@ | |
| 70426 | */ |
| 70427 | case OP_RowSetRead: { /* jump, in1, out3 */ |
| 70428 | #if 0 /* local variables moved into u.cb */ |
| 70429 | i64 val; |
| 70430 | #endif /* local variables moved into u.cb */ |
| 70431 | CHECK_FOR_INTERRUPT; |
| 70432 | pIn1 = &aMem[pOp->p1]; |
| 70433 | if( (pIn1->flags & MEM_RowSet)==0 |
| 70434 | || sqlite3RowSetNext(pIn1->u.pRowSet, &u.cb.val)==0 |
| 70435 | ){ |
| 70436 | /* The boolean index is empty */ |
| @@ -70438,11 +70501,11 @@ | |
| 70438 | pc = pOp->p2 - 1; |
| 70439 | }else{ |
| 70440 | /* A value was pulled from the index */ |
| 70441 | sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.cb.val); |
| 70442 | } |
| 70443 | break; |
| 70444 | } |
| 70445 | |
| 70446 | /* Opcode: RowSetTest P1 P2 P3 P4 |
| 70447 | ** |
| 70448 | ** Register P3 is assumed to hold a 64-bit integer value. If register P1 |
| @@ -70658,11 +70721,13 @@ | |
| 70658 | ** If P1 is non-zero, the database constraint counter is incremented |
| 70659 | ** (deferred foreign key constraints). Otherwise, if P1 is zero, the |
| 70660 | ** statement counter is incremented (immediate foreign key constraints). |
| 70661 | */ |
| 70662 | case OP_FkCounter: { |
| 70663 | if( pOp->p1 ){ |
| 70664 | db->nDeferredCons += pOp->p2; |
| 70665 | }else{ |
| 70666 | p->nFkConstraint += pOp->p2; |
| 70667 | } |
| 70668 | break; |
| @@ -70679,13 +70744,13 @@ | |
| 70679 | ** zero, the jump is taken if the statement constraint-counter is zero |
| 70680 | ** (immediate foreign key constraint violations). |
| 70681 | */ |
| 70682 | case OP_FkIfZero: { /* jump */ |
| 70683 | if( pOp->p1 ){ |
| 70684 | if( db->nDeferredCons==0 ) pc = pOp->p2-1; |
| 70685 | }else{ |
| 70686 | if( p->nFkConstraint==0 ) pc = pOp->p2-1; |
| 70687 | } |
| 70688 | break; |
| 70689 | } |
| 70690 | #endif /* #ifndef SQLITE_OMIT_FOREIGN_KEY */ |
| 70691 | |
| @@ -71367,11 +71432,11 @@ | |
| 71367 | |
| 71368 | if( !u.cp.res ){ |
| 71369 | /* If there is data, jump to P2 */ |
| 71370 | pc = pOp->p2 - 1; |
| 71371 | } |
| 71372 | break; |
| 71373 | } |
| 71374 | #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
| 71375 | |
| 71376 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 71377 | /* Opcode: VRename P1 * * P4 * |
| @@ -89262,11 +89327,14 @@ | |
| 89262 | sqlite3ReleaseTempReg(pParse, regRec); |
| 89263 | sqlite3ReleaseTempRange(pParse, regTemp, nCol); |
| 89264 | } |
| 89265 | } |
| 89266 | |
| 89267 | if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){ |
| 89268 | /* Special case: If this is an INSERT statement that will insert exactly |
| 89269 | ** one row into the table, raise a constraint immediately instead of |
| 89270 | ** incrementing a counter. This is necessary as the VM code is being |
| 89271 | ** generated for will not open a statement transaction. */ |
| 89272 | assert( nIncr==1 ); |
| @@ -89653,11 +89721,13 @@ | |
| 89653 | for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){ |
| 89654 | Index *pIdx = 0; /* Foreign key index for pFKey */ |
| 89655 | SrcList *pSrc; |
| 89656 | int *aiCol = 0; |
| 89657 | |
| 89658 | if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){ |
| 89659 | assert( regOld==0 && regNew!=0 ); |
| 89660 | /* Inserting a single row into a parent table cannot cause an immediate |
| 89661 | ** foreign key violation. So do nothing in this case. */ |
| 89662 | continue; |
| 89663 | } |
| @@ -92615,15 +92685,18 @@ | |
| 92615 | #ifndef SQLITE_CORE |
| 92616 | /* This case when the file really is being compiled as a loadable |
| 92617 | ** extension */ |
| 92618 | # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; |
| 92619 | # define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; |
| 92620 | #else |
| 92621 | /* This case when the file is being statically linked into the |
| 92622 | ** application */ |
| 92623 | # define SQLITE_EXTENSION_INIT1 /*no-op*/ |
| 92624 | # define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */ |
| 92625 | #endif |
| 92626 | |
| 92627 | #endif /* _SQLITE3EXT_H_ */ |
| 92628 | |
| 92629 | /************** End of sqlite3ext.h ******************************************/ |
| @@ -93275,10 +93348,39 @@ | |
| 93275 | sqlite3_mutex_leave(mutex); |
| 93276 | assert( (rc&0xff)==rc ); |
| 93277 | return rc; |
| 93278 | } |
| 93279 | } |
| 93280 | |
| 93281 | /* |
| 93282 | ** Reset the automatic extension loading mechanism. |
| 93283 | */ |
| 93284 | SQLITE_API void sqlite3_reset_auto_extension(void){ |
| @@ -93516,10 +93618,11 @@ | |
| 93516 | { "empty_result_callbacks", SQLITE_NullCallback }, |
| 93517 | { "legacy_file_format", SQLITE_LegacyFileFmt }, |
| 93518 | { "fullfsync", SQLITE_FullFSync }, |
| 93519 | { "checkpoint_fullfsync", SQLITE_CkptFullFSync }, |
| 93520 | { "reverse_unordered_selects", SQLITE_ReverseOrder }, |
| 93521 | #ifndef SQLITE_OMIT_AUTOMATIC_INDEX |
| 93522 | { "automatic_index", SQLITE_AutoIndex }, |
| 93523 | #endif |
| 93524 | #ifdef SQLITE_DEBUG |
| 93525 | { "sql_trace", SQLITE_SqlTrace }, |
| @@ -93536,16 +93639,17 @@ | |
| 93536 | { "writable_schema", SQLITE_WriteSchema|SQLITE_RecoveryMode }, |
| 93537 | |
| 93538 | /* TODO: Maybe it shouldn't be possible to change the ReadUncommitted |
| 93539 | ** flag if there are any active statements. */ |
| 93540 | { "read_uncommitted", SQLITE_ReadUncommitted }, |
| 93541 | { "recursive_triggers", SQLITE_RecTriggers }, |
| 93542 | |
| 93543 | /* This flag may only be set if both foreign-key and trigger support |
| 93544 | ** are present in the build. */ |
| 93545 | #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) |
| 93546 | { "foreign_keys", SQLITE_ForeignKeys }, |
| 93547 | #endif |
| 93548 | }; |
| 93549 | int i; |
| 93550 | const struct sPragmaType *p; |
| 93551 | for(i=0, p=aPragma; i<ArraySize(aPragma); i++, p++){ |
| @@ -93567,10 +93671,11 @@ | |
| 93567 | |
| 93568 | if( sqlite3GetBoolean(zRight, 0) ){ |
| 93569 | db->flags |= mask; |
| 93570 | }else{ |
| 93571 | db->flags &= ~mask; |
| 93572 | } |
| 93573 | |
| 93574 | /* Many of the flag-pragmas modify the code generated by the SQL |
| 93575 | ** compiler (eg. count_changes). So add an opcode to expire all |
| 93576 | ** compiled SQL statements after modifying a pragma value. |
| @@ -95979,10 +96084,16 @@ | |
| 95979 | |
| 95980 | assert( ppStmt ); |
| 95981 | *ppStmt = 0; |
| 95982 | if( !sqlite3SafetyCheckOk(db) ){ |
| 95983 | return SQLITE_MISUSE_BKPT; |
| 95984 | } |
| 95985 | sqlite3_mutex_enter(db->mutex); |
| 95986 | zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE); |
| 95987 | if( zSql8 ){ |
| 95988 | rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, 0, ppStmt, &zTail8); |
| @@ -104070,12 +104181,12 @@ | |
| 104070 | int (*x)(sqlite3_vtab *); |
| 104071 | sqlite3_vtab *pVtab = aVTrans[i]->pVtab; |
| 104072 | if( pVtab && (x = pVtab->pModule->xSync)!=0 ){ |
| 104073 | rc = x(pVtab); |
| 104074 | sqlite3DbFree(db, *pzErrmsg); |
| 104075 | *pzErrmsg = sqlite3DbStrDup(db, pVtab->zErrMsg); |
| 104076 | sqlite3_free(pVtab->zErrMsg); |
| 104077 | } |
| 104078 | } |
| 104079 | db->aVTrans = aVTrans; |
| 104080 | return rc; |
| 104081 | } |
| @@ -104391,10 +104502,12 @@ | |
| 104391 | typedef struct WhereLoop WhereLoop; |
| 104392 | typedef struct WherePath WherePath; |
| 104393 | typedef struct WhereTerm WhereTerm; |
| 104394 | typedef struct WhereLoopBuilder WhereLoopBuilder; |
| 104395 | typedef struct WhereScan WhereScan; |
| 104396 | |
| 104397 | /* |
| 104398 | ** Cost X is tracked as 10*log2(X) stored in a 16-bit integer. The |
| 104399 | ** maximum cost for ordinary tables is 64*(2**63) which becomes 6900. |
| 104400 | ** (Virtual tables can return a larger cost, but let's assume they do not.) |
| @@ -104497,10 +104610,31 @@ | |
| 104497 | u16 nLSlot; /* Number of slots allocated for aLTerm[] */ |
| 104498 | WhereTerm **aLTerm; /* WhereTerms used */ |
| 104499 | WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */ |
| 104500 | WhereTerm *aLTermSpace[4]; /* Initial aLTerm[] space */ |
| 104501 | }; |
| 104502 | |
| 104503 | /* Forward declaration of methods */ |
| 104504 | static int whereLoopResize(sqlite3*, WhereLoop*, int); |
| 104505 | |
| 104506 | /* |
| @@ -104712,11 +104846,11 @@ | |
| 104712 | struct WhereLoopBuilder { |
| 104713 | WhereInfo *pWInfo; /* Information about this WHERE */ |
| 104714 | WhereClause *pWC; /* WHERE clause terms */ |
| 104715 | ExprList *pOrderBy; /* ORDER BY clause */ |
| 104716 | WhereLoop *pNew; /* Template WhereLoop */ |
| 104717 | WhereLoop *pBest; /* If non-NULL, store single best loop here */ |
| 104718 | }; |
| 104719 | |
| 104720 | /* |
| 104721 | ** The WHERE clause processing routine has two halves. The |
| 104722 | ** first part does the start of the WHERE loop and the second |
| @@ -104854,10 +104988,58 @@ | |
| 104854 | ** UPDATE or DELETE might change subsequent WHERE clause results. |
| 104855 | */ |
| 104856 | SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo *pWInfo){ |
| 104857 | return pWInfo->okOnePass; |
| 104858 | } |
| 104859 | |
| 104860 | /* |
| 104861 | ** Initialize a preallocated WhereClause structure. |
| 104862 | */ |
| 104863 | static void whereClauseInit( |
| @@ -108089,12 +108271,13 @@ | |
| 108089 | */ |
| 108090 | if( pWC->nTerm>1 ){ |
| 108091 | int iTerm; |
| 108092 | for(iTerm=0; iTerm<pWC->nTerm; iTerm++){ |
| 108093 | Expr *pExpr = pWC->a[iTerm].pExpr; |
| 108094 | if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; |
| 108095 | if( pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_ORINFO) ) continue; |
| 108096 | if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; |
| 108097 | pExpr = sqlite3ExprDup(pParse->db, pExpr, 0); |
| 108098 | pAndExpr = sqlite3ExprAnd(pParse->db, pAndExpr, pExpr); |
| 108099 | } |
| 108100 | if( pAndExpr ){ |
| @@ -108418,16 +108601,16 @@ | |
| 108418 | ** is better and has fewer dependencies. Or the template will be ignored |
| 108419 | ** and no insert will occur if an existing WhereLoop is faster and has |
| 108420 | ** fewer dependencies than the template. Otherwise a new WhereLoop is |
| 108421 | ** added based on the template. |
| 108422 | ** |
| 108423 | ** If pBuilder->pBest is not NULL then we only care about the very |
| 108424 | ** best template and that template should be stored in pBuilder->pBest. |
| 108425 | ** If pBuilder->pBest is NULL then a list of the best templates are stored |
| 108426 | ** in pBuilder->pWInfo->pLoops. |
| 108427 | ** |
| 108428 | ** When accumulating multiple loops (when pBuilder->pBest is NULL) we |
| 108429 | ** still might overwrite similar loops with the new template if the |
| 108430 | ** template is better. Loops may be overwritten if the following |
| 108431 | ** conditions are met: |
| 108432 | ** |
| 108433 | ** (1) They have the same iTab. |
| @@ -108440,34 +108623,26 @@ | |
| 108440 | static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ |
| 108441 | WhereLoop **ppPrev, *p, *pNext = 0; |
| 108442 | WhereInfo *pWInfo = pBuilder->pWInfo; |
| 108443 | sqlite3 *db = pWInfo->pParse->db; |
| 108444 | |
| 108445 | /* If pBuilder->pBest is defined, then only keep track of the single |
| 108446 | ** best WhereLoop. pBuilder->pBest->maskSelf==0 indicates that no |
| 108447 | ** prior WhereLoops have been evaluated and that the current pTemplate |
| 108448 | ** is therefore the first and hence the best and should be retained. |
| 108449 | */ |
| 108450 | if( (p = pBuilder->pBest)!=0 ){ |
| 108451 | if( p->maskSelf!=0 ){ |
| 108452 | WhereCost rCost = whereCostAdd(p->rRun,p->rSetup); |
| 108453 | WhereCost rTemplate = whereCostAdd(pTemplate->rRun,pTemplate->rSetup); |
| 108454 | if( rCost < rTemplate ){ |
| 108455 | testcase( rCost==rTemplate-1 ); |
| 108456 | goto whereLoopInsert_noop; |
| 108457 | } |
| 108458 | if( rCost==rTemplate && (p->prereq & pTemplate->prereq)==p->prereq ){ |
| 108459 | goto whereLoopInsert_noop; |
| 108460 | } |
| 108461 | } |
| 108462 | #if WHERETRACE_ENABLED |
| 108463 | if( sqlite3WhereTrace & 0x8 ){ |
| 108464 | sqlite3DebugPrintf(p->maskSelf==0 ? "ins-init: " : "ins-best: "); |
| 108465 | whereLoopPrint(pTemplate, pWInfo->pTabList); |
| 108466 | } |
| 108467 | #endif |
| 108468 | whereLoopXfer(db, p, pTemplate); |
| 108469 | return SQLITE_OK; |
| 108470 | } |
| 108471 | |
| 108472 | /* Search for an existing WhereLoop to overwrite, or which takes |
| 108473 | ** priority over pTemplate. |
| @@ -108557,11 +108732,11 @@ | |
| 108557 | |
| 108558 | /* Jump here if the insert is a no-op */ |
| 108559 | whereLoopInsert_noop: |
| 108560 | #if WHERETRACE_ENABLED |
| 108561 | if( sqlite3WhereTrace & 0x8 ){ |
| 108562 | sqlite3DebugPrintf(pBuilder->pBest ? "ins-skip: " : "ins-noop: "); |
| 108563 | whereLoopPrint(pTemplate, pWInfo->pTabList); |
| 108564 | } |
| 108565 | #endif |
| 108566 | return SQLITE_OK; |
| 108567 | } |
| @@ -108839,11 +109014,11 @@ | |
| 108839 | } |
| 108840 | rSize = whereCost(pSrc->pTab->nRowEst); |
| 108841 | rLogSize = estLog(rSize); |
| 108842 | |
| 108843 | /* Automatic indexes */ |
| 108844 | if( !pBuilder->pBest |
| 108845 | && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0 |
| 108846 | && pSrc->pIndex==0 |
| 108847 | && !pSrc->viaCoroutine |
| 108848 | && !pSrc->notIndexed |
| 108849 | && !pSrc->isCorrelated |
| @@ -109125,11 +109300,11 @@ | |
| 109125 | WhereTerm *pTerm, *pWCEnd; |
| 109126 | int rc = SQLITE_OK; |
| 109127 | int iCur; |
| 109128 | WhereClause tempWC; |
| 109129 | WhereLoopBuilder sSubBuild; |
| 109130 | WhereLoop sBest; |
| 109131 | struct SrcList_item *pItem; |
| 109132 | |
| 109133 | pWC = pBuilder->pWC; |
| 109134 | if( pWInfo->wctrlFlags & WHERE_AND_ONLY ) return SQLITE_OK; |
| 109135 | pWCEnd = pWC->a + pWC->nTerm; |
| @@ -109140,20 +109315,18 @@ | |
| 109140 | && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0 |
| 109141 | ){ |
| 109142 | WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc; |
| 109143 | WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm]; |
| 109144 | WhereTerm *pOrTerm; |
| 109145 | WhereCost rTotal = 0; |
| 109146 | WhereCost nRow = 0; |
| 109147 | Bitmask prereq = mExtra; |
| 109148 | |
| 109149 | whereLoopInit(&sBest); |
| 109150 | pItem = pWInfo->pTabList->a + pNew->iTab; |
| 109151 | iCur = pItem->iCursor; |
| 109152 | sSubBuild = *pBuilder; |
| 109153 | sSubBuild.pOrderBy = 0; |
| 109154 | sSubBuild.pBest = &sBest; |
| 109155 | |
| 109156 | for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){ |
| 109157 | if( (pOrTerm->eOperator & WO_AND)!=0 ){ |
| 109158 | sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc; |
| 109159 | }else if( pOrTerm->leftCursor==iCur ){ |
| @@ -109164,43 +109337,52 @@ | |
| 109164 | tempWC.a = pOrTerm; |
| 109165 | sSubBuild.pWC = &tempWC; |
| 109166 | }else{ |
| 109167 | continue; |
| 109168 | } |
| 109169 | sBest.maskSelf = 0; |
| 109170 | sBest.rSetup = 0; |
| 109171 | sBest.rRun = 0; |
| 109172 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 109173 | if( IsVirtual(pItem->pTab) ){ |
| 109174 | rc = whereLoopAddVirtual(&sSubBuild); |
| 109175 | }else |
| 109176 | #endif |
| 109177 | { |
| 109178 | rc = whereLoopAddBtree(&sSubBuild, mExtra); |
| 109179 | } |
| 109180 | /* sBest.maskSelf is always zero if an error occurs */ |
| 109181 | assert( rc==SQLITE_OK || sBest.maskSelf==0 ); |
| 109182 | if( sBest.maskSelf==0 ) break; |
| 109183 | assert( sBest.rSetup==0 ); |
| 109184 | rTotal = whereCostAdd(rTotal, sBest.rRun); |
| 109185 | nRow = whereCostAdd(nRow, sBest.nOut); |
| 109186 | prereq |= sBest.prereq; |
| 109187 | } |
| 109188 | assert( pNew->nLSlot>=1 ); |
| 109189 | if( sBest.maskSelf ){ |
| 109190 | pNew->nLTerm = 1; |
| 109191 | pNew->aLTerm[0] = pTerm; |
| 109192 | pNew->wsFlags = WHERE_MULTI_OR; |
| 109193 | pNew->rSetup = 0; |
| 109194 | /* TUNING: Multiple by 3.5 for the secondary table lookup */ |
| 109195 | pNew->rRun = rTotal + 18; assert( 18==whereCost(7)-whereCost(2) ); |
| 109196 | pNew->nOut = nRow; |
| 109197 | pNew->prereq = prereq; |
| 109198 | memset(&pNew->u, 0, sizeof(pNew->u)); |
| 109199 | rc = whereLoopInsert(pBuilder, pNew); |
| 109200 | } |
| 109201 | whereLoopClear(pWInfo->pParse->db, &sBest); |
| 109202 | } |
| 109203 | } |
| 109204 | return rc; |
| 109205 | } |
| 109206 | |
| @@ -110003,11 +110185,12 @@ | |
| 110003 | pWInfo->wctrlFlags = wctrlFlags; |
| 110004 | pWInfo->savedNQueryLoop = pParse->nQueryLoop; |
| 110005 | pMaskSet = &pWInfo->sMaskSet; |
| 110006 | sWLB.pWInfo = pWInfo; |
| 110007 | sWLB.pWC = &pWInfo->sWC; |
| 110008 | sWLB.pNew = (WhereLoop*)&pWInfo->a[nTabList]; |
| 110009 | whereLoopInit(sWLB.pNew); |
| 110010 | #ifdef SQLITE_DEBUG |
| 110011 | sWLB.pNew->cId = '*'; |
| 110012 | #endif |
| 110013 | |
| @@ -116127,10 +116310,12 @@ | |
| 116127 | } |
| 116128 | sqlite3BtreeLeaveAll(db); |
| 116129 | |
| 116130 | /* Any deferred constraint violations have now been resolved. */ |
| 116131 | db->nDeferredCons = 0; |
| 116132 | |
| 116133 | /* If one has been configured, invoke the rollback-hook callback */ |
| 116134 | if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){ |
| 116135 | db->xRollbackCallback(db->pRollbackArg); |
| 116136 | } |
| @@ -116388,11 +116573,11 @@ | |
| 116388 | void *pArg |
| 116389 | ){ |
| 116390 | sqlite3_mutex_enter(db->mutex); |
| 116391 | if( nOps>0 ){ |
| 116392 | db->xProgress = xProgress; |
| 116393 | db->nProgressOps = nOps; |
| 116394 | db->pProgressArg = pArg; |
| 116395 | }else{ |
| 116396 | db->xProgress = 0; |
| 116397 | db->nProgressOps = 0; |
| 116398 | db->pProgressArg = 0; |
| @@ -119087,11 +119272,11 @@ | |
| 119087 | |
| 119088 | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) |
| 119089 | |
| 119090 | /* If not building as part of the core, include sqlite3ext.h. */ |
| 119091 | #ifndef SQLITE_CORE |
| 119092 | SQLITE_API extern const sqlite3_api_routines *sqlite3_api; |
| 119093 | #endif |
| 119094 | |
| 119095 | /************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/ |
| 119096 | /************** Begin file fts3_tokenizer.h **********************************/ |
| 119097 | /* |
| @@ -124995,11 +125180,14 @@ | |
| 124995 | |
| 124996 | #if !SQLITE_CORE |
| 124997 | /* |
| 124998 | ** Initialize API pointer table, if required. |
| 124999 | */ |
| 125000 | SQLITE_API int sqlite3_extension_init( |
| 125001 | sqlite3 *db, |
| 125002 | char **pzErrMsg, |
| 125003 | const sqlite3_api_routines *pApi |
| 125004 | ){ |
| 125005 | SQLITE_EXTENSION_INIT2(pApi) |
| @@ -140042,11 +140230,14 @@ | |
| 140042 | (void *)pGeomCtx, geomCallback, 0, 0, doSqlite3Free |
| 140043 | ); |
| 140044 | } |
| 140045 | |
| 140046 | #if !SQLITE_CORE |
| 140047 | SQLITE_API int sqlite3_extension_init( |
| 140048 | sqlite3 *db, |
| 140049 | char **pzErrMsg, |
| 140050 | const sqlite3_api_routines *pApi |
| 140051 | ){ |
| 140052 | SQLITE_EXTENSION_INIT2(pApi) |
| @@ -140544,11 +140735,14 @@ | |
| 140544 | |
| 140545 | return rc; |
| 140546 | } |
| 140547 | |
| 140548 | #if !SQLITE_CORE |
| 140549 | SQLITE_API int sqlite3_extension_init( |
| 140550 | sqlite3 *db, |
| 140551 | char **pzErrMsg, |
| 140552 | const sqlite3_api_routines *pApi |
| 140553 | ){ |
| 140554 | SQLITE_EXTENSION_INIT2(pApi) |
| 140555 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -670,11 +670,11 @@ | |
| 670 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 671 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 672 | */ |
| 673 | #define SQLITE_VERSION "3.8.0" |
| 674 | #define SQLITE_VERSION_NUMBER 3008000 |
| 675 | #define SQLITE_SOURCE_ID "2013-07-18 14:50:56 5dcffa671f592ae9355628afa439ae9a2d26f0cd" |
| 676 | |
| 677 | /* |
| 678 | ** CAPI3REF: Run-Time Library Version Numbers |
| 679 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 680 | ** |
| @@ -3120,11 +3120,11 @@ | |
| 3120 | ** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for |
| 3121 | ** database connection D. An example use for this |
| 3122 | ** interface is to keep a GUI updated during a large query. |
| 3123 | ** |
| 3124 | ** ^The parameter P is passed through as the only parameter to the |
| 3125 | ** callback function X. ^The parameter N is the approximate number of |
| 3126 | ** [virtual machine instructions] that are evaluated between successive |
| 3127 | ** invocations of the callback X. |
| 3128 | ** |
| 3129 | ** ^Only a single progress handler may be defined at one time per |
| 3130 | ** [database connection]; setting a new progress handler cancels the |
| @@ -4745,12 +4745,12 @@ | |
| 4745 | ** CAPI3REF: Function Auxiliary Data |
| 4746 | ** |
| 4747 | ** The following two functions may be used by scalar SQL functions to |
| 4748 | ** associate metadata with argument values. If the same value is passed to |
| 4749 | ** multiple invocations of the same SQL function during query execution, under |
| 4750 | ** some circumstances the associated metadata may be preserved. This might |
| 4751 | ** be used, for example, in a regular-expression matching |
| 4752 | ** function. The compiled version of the regular expression is stored as |
| 4753 | ** metadata associated with the SQL value passed as the regular expression |
| 4754 | ** pattern. The compiled regular expression can be reused on multiple |
| 4755 | ** invocations of the same function so that the original pattern string |
| 4756 | ** does not need to be recompiled on each invocation. |
| @@ -4760,27 +4760,36 @@ | |
| 4760 | ** value to the application-defined function. ^If no metadata has been ever |
| 4761 | ** been set for the Nth argument of the function, or if the corresponding |
| 4762 | ** function parameter has changed since the meta-data was set, |
| 4763 | ** then sqlite3_get_auxdata() returns a NULL pointer. |
| 4764 | ** |
| 4765 | ** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th |
| 4766 | ** argument of the application-defined function. ^Subsequent |
| 4767 | ** calls to sqlite3_get_auxdata(C,N) return P from the most recent |
| 4768 | ** sqlite3_set_auxdata(C,N,P,X) call if the data has not been dropped, or |
| 4769 | ** NULL if the data has been dropped. |
| 4770 | ** ^(If it is not NULL, SQLite will invoke the destructor |
| 4771 | ** function X passed to sqlite3_set_auxdata(C,N,P,X) when <ul> |
| 4772 | ** <li> the corresponding function parameter changes, |
| 4773 | ** <li> [sqlite3_reset()] or [sqlite3_finalize()] is called for the |
| 4774 | ** SQL statement, |
| 4775 | ** <li> sqlite3_set_auxdata() is invoked again on the same parameter, or |
| 4776 | ** <li> a memory allocation error occurs. </ul>)^ |
| 4777 | ** |
| 4778 | ** SQLite is free to call the destructor and drop metadata on any |
| 4779 | ** parameter of any function at any time. ^The only guarantee is that |
| 4780 | ** the destructor will be called when the [prepared statement] is destroyed. |
| 4781 | ** Note in particular that the destructor X in the call to |
| 4782 | ** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before |
| 4783 | ** the sqlite3_set_auxdata() call even returns. Hence sqlite3_set_auxdata() |
| 4784 | ** should be called near the end of the function implementation and the |
| 4785 | ** implementation should not make any use of P after sqlite3_set_auxdata() |
| 4786 | ** has been called. |
| 4787 | ** |
| 4788 | ** ^(In practice, metadata is preserved between function calls for |
| 4789 | ** function parameters that are compile-time constants, including literal |
| 4790 | ** values and [parameters] and expressions composed from the same.)^ |
| 4791 | ** |
| 4792 | ** These routines must be called from the same thread in which |
| 4793 | ** the SQL function is running. |
| 4794 | */ |
| 4795 | SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); |
| @@ -5689,14 +5698,27 @@ | |
| 5698 | ** |
| 5699 | ** ^Calling sqlite3_auto_extension(X) with an entry point X that is already |
| 5700 | ** on the list of automatic extensions is a harmless no-op. ^No entry point |
| 5701 | ** will be called more than once for each database connection that is opened. |
| 5702 | ** |
| 5703 | ** See also: [sqlite3_reset_auto_extension()] |
| 5704 | ** and [sqlite3_cancel_auto_extension()] |
| 5705 | */ |
| 5706 | SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void)); |
| 5707 | |
| 5708 | /* |
| 5709 | ** CAPI3REF: Cancel Automatic Extension Loading |
| 5710 | ** |
| 5711 | ** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the |
| 5712 | ** initialization routine X that was registered using a prior call to |
| 5713 | ** [sqlite3_auto_extension(X)]. ^The [sqlite3_cancel_auto_extension(X)] |
| 5714 | ** routine returns 1 if initialization routine X was successfully |
| 5715 | ** unregistered and it returns 0 if X was not on the list of initialization |
| 5716 | ** routines. |
| 5717 | */ |
| 5718 | SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void)); |
| 5719 | |
| 5720 | /* |
| 5721 | ** CAPI3REF: Reset Automatic Extension Loading |
| 5722 | ** |
| 5723 | ** ^This interface disables all automatic extensions previously |
| 5724 | ** registered using [sqlite3_auto_extension()]. |
| @@ -6805,10 +6827,16 @@ | |
| 6827 | ** transaction rollback or database recovery operations are not included. |
| 6828 | ** If an IO or other error occurs while writing a page to disk, the effect |
| 6829 | ** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The |
| 6830 | ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. |
| 6831 | ** </dd> |
| 6832 | ** |
| 6833 | ** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt> |
| 6834 | ** <dd>This parameter returns the zero for the current value if and only if |
| 6835 | ** there all foreign key constraints (deferred or immediate) have been |
| 6836 | ** resolved. The highwater mark is always 0. |
| 6837 | ** </dd> |
| 6838 | ** </dl> |
| 6839 | */ |
| 6840 | #define SQLITE_DBSTATUS_LOOKASIDE_USED 0 |
| 6841 | #define SQLITE_DBSTATUS_CACHE_USED 1 |
| 6842 | #define SQLITE_DBSTATUS_SCHEMA_USED 2 |
| @@ -6817,11 +6845,12 @@ | |
| 6845 | #define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5 |
| 6846 | #define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 |
| 6847 | #define SQLITE_DBSTATUS_CACHE_HIT 7 |
| 6848 | #define SQLITE_DBSTATUS_CACHE_MISS 8 |
| 6849 | #define SQLITE_DBSTATUS_CACHE_WRITE 9 |
| 6850 | #define SQLITE_DBSTATUS_DEFERRED_FKS 10 |
| 6851 | #define SQLITE_DBSTATUS_MAX 10 /* Largest defined DBSTATUS */ |
| 6852 | |
| 6853 | |
| 6854 | /* |
| 6855 | ** CAPI3REF: Prepared Statement Status |
| 6856 | ** |
| @@ -10117,11 +10146,11 @@ | |
| 10146 | void *pAuthArg; /* 1st argument to the access auth function */ |
| 10147 | #endif |
| 10148 | #ifndef SQLITE_OMIT_PROGRESS_CALLBACK |
| 10149 | int (*xProgress)(void *); /* The progress callback */ |
| 10150 | void *pProgressArg; /* Argument to the progress callback */ |
| 10151 | unsigned nProgressOps; /* Number of opcodes for progress callback */ |
| 10152 | #endif |
| 10153 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 10154 | int nVTrans; /* Allocated size of aVTrans */ |
| 10155 | Hash aModule; /* populated by sqlite3_create_module() */ |
| 10156 | VtabCtx *pVtabCtx; /* Context for active vtab connect/create */ |
| @@ -10135,10 +10164,11 @@ | |
| 10164 | Savepoint *pSavepoint; /* List of active savepoints */ |
| 10165 | int busyTimeout; /* Busy handler timeout, in msec */ |
| 10166 | int nSavepoint; /* Number of non-transaction savepoints */ |
| 10167 | int nStatement; /* Number of nested statement-transactions */ |
| 10168 | i64 nDeferredCons; /* Net deferred constraints this transaction. */ |
| 10169 | i64 nDeferredImmCons; /* Net deferred immediate constraints */ |
| 10170 | int *pnBytesFreed; /* If not NULL, increment this in DbFree() */ |
| 10171 | |
| 10172 | #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY |
| 10173 | /* The following variables are all protected by the STATIC_MASTER |
| 10174 | ** mutex, not by sqlite3.mutex. They are used by code in notify.c. |
| @@ -10190,10 +10220,13 @@ | |
| 10220 | #define SQLITE_ForeignKeys 0x00040000 /* Enforce foreign key constraints */ |
| 10221 | #define SQLITE_AutoIndex 0x00080000 /* Enable automatic indexes */ |
| 10222 | #define SQLITE_PreferBuiltin 0x00100000 /* Preference to built-in funcs */ |
| 10223 | #define SQLITE_LoadExtension 0x00200000 /* Enable load_extension */ |
| 10224 | #define SQLITE_EnableTrigger 0x00400000 /* True to enable triggers */ |
| 10225 | #define SQLITE_DeferFKs 0x00800000 /* Defer all FK constraints */ |
| 10226 | #define SQLITE_QueryOnly 0x01000000 /* Disable database changes */ |
| 10227 | |
| 10228 | |
| 10229 | /* |
| 10230 | ** Bits of the sqlite3.dbOptFlags field that are used by the |
| 10231 | ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to |
| 10232 | ** selectively disable various optimizations. |
| @@ -10336,10 +10369,11 @@ | |
| 10369 | ** OP_Savepoint instruction. |
| 10370 | */ |
| 10371 | struct Savepoint { |
| 10372 | char *zName; /* Savepoint name (nul-terminated) */ |
| 10373 | i64 nDeferredCons; /* Number of deferred fk violations */ |
| 10374 | i64 nDeferredImmCons; /* Number of deferred imm fk. */ |
| 10375 | Savepoint *pNext; /* Parent savepoint (if any) */ |
| 10376 | }; |
| 10377 | |
| 10378 | /* |
| 10379 | ** The following are used as the second parameter to sqlite3Savepoint(), |
| @@ -13530,10 +13564,11 @@ | |
| 13564 | #ifndef SQLITE_OMIT_TRACE |
| 13565 | i64 startTime; /* Time when query started - used for profiling */ |
| 13566 | #endif |
| 13567 | i64 nFkConstraint; /* Number of imm. FK constraints this VM */ |
| 13568 | i64 nStmtDefCons; /* Number of def. constraints when stmt started */ |
| 13569 | i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */ |
| 13570 | char *zSql; /* Text of the SQL statement that generated this */ |
| 13571 | void *pFree; /* Free this when deleting the vdbe */ |
| 13572 | #ifdef SQLITE_DEBUG |
| 13573 | FILE *trace; /* Write an execution trace here, if not NULL */ |
| 13574 | #endif |
| @@ -13889,10 +13924,20 @@ | |
| 13924 | } |
| 13925 | *pHighwater = 0; |
| 13926 | *pCurrent = nRet; |
| 13927 | break; |
| 13928 | } |
| 13929 | |
| 13930 | /* Set *pCurrent to non-zero if there are unresolved deferred foreign |
| 13931 | ** key constraints. Set *pCurrent to zero if all foreign key constraints |
| 13932 | ** have been satisfied. The *pHighwater is always set to zero. |
| 13933 | */ |
| 13934 | case SQLITE_DBSTATUS_DEFERRED_FKS: { |
| 13935 | *pHighwater = 0; |
| 13936 | *pCurrent = db->nDeferredImmCons>0 || db->nDeferredCons>0; |
| 13937 | break; |
| 13938 | } |
| 13939 | |
| 13940 | default: { |
| 13941 | rc = SQLITE_ERROR; |
| 13942 | } |
| 13943 | } |
| @@ -61946,10 +61991,11 @@ | |
| 61991 | /* If the statement transaction is being rolled back, also restore the |
| 61992 | ** database handles deferred constraint counter to the value it had when |
| 61993 | ** the statement transaction was opened. */ |
| 61994 | if( eOp==SAVEPOINT_ROLLBACK ){ |
| 61995 | db->nDeferredCons = p->nStmtDefCons; |
| 61996 | db->nDeferredImmCons = p->nStmtDefImmCons; |
| 61997 | } |
| 61998 | } |
| 61999 | return rc; |
| 62000 | } |
| 62001 | |
| @@ -61964,11 +62010,13 @@ | |
| 62010 | ** and write an error message to it. Then return SQLITE_ERROR. |
| 62011 | */ |
| 62012 | #ifndef SQLITE_OMIT_FOREIGN_KEY |
| 62013 | SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){ |
| 62014 | sqlite3 *db = p->db; |
| 62015 | if( (deferred && (db->nDeferredCons+db->nDeferredImmCons)>0) |
| 62016 | || (!deferred && p->nFkConstraint>0) |
| 62017 | ){ |
| 62018 | p->rc = SQLITE_CONSTRAINT_FOREIGNKEY; |
| 62019 | p->errorAction = OE_Abort; |
| 62020 | sqlite3SetString(&p->zErrMsg, db, "foreign key constraint failed"); |
| 62021 | return SQLITE_ERROR; |
| 62022 | } |
| @@ -62097,10 +62145,12 @@ | |
| 62145 | }else if( rc!=SQLITE_OK ){ |
| 62146 | p->rc = rc; |
| 62147 | sqlite3RollbackAll(db, SQLITE_OK); |
| 62148 | }else{ |
| 62149 | db->nDeferredCons = 0; |
| 62150 | db->nDeferredImmCons = 0; |
| 62151 | db->flags &= ~SQLITE_DeferFKs; |
| 62152 | sqlite3CommitInternalChanges(db); |
| 62153 | } |
| 62154 | }else{ |
| 62155 | sqlite3RollbackAll(db, SQLITE_OK); |
| 62156 | } |
| @@ -63536,11 +63586,13 @@ | |
| 63586 | */ |
| 63587 | if( db->nVdbeActive==0 ){ |
| 63588 | db->u1.isInterrupted = 0; |
| 63589 | } |
| 63590 | |
| 63591 | assert( db->nVdbeWrite>0 || db->autoCommit==0 |
| 63592 | || (db->nDeferredCons==0 && db->nDeferredImmCons==0) |
| 63593 | ); |
| 63594 | |
| 63595 | #ifndef SQLITE_OMIT_TRACE |
| 63596 | if( db->xProfile && !db->init.busy ){ |
| 63597 | sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime); |
| 63598 | } |
| @@ -65384,16 +65436,15 @@ | |
| 65436 | Op *pOp; /* Current operation */ |
| 65437 | int rc = SQLITE_OK; /* Value to return */ |
| 65438 | sqlite3 *db = p->db; /* The database */ |
| 65439 | u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ |
| 65440 | u8 encoding = ENC(db); /* The database encoding */ |
| 65441 | int iCompare = 0; /* Result of last OP_Compare operation */ |
| 65442 | unsigned nVmStep = 0; /* Number of virtual machine steps */ |
| 65443 | #ifndef SQLITE_OMIT_PROGRESS_CALLBACK |
| 65444 | unsigned nProgressOps = 0; /* nVmStep at last progress callback. */ |
| 65445 | #endif |
| 65446 | Mem *aMem = p->aMem; /* Copy of p->aMem */ |
| 65447 | Mem *pIn1 = 0; /* 1st input operand */ |
| 65448 | Mem *pIn2 = 0; /* 2nd input operand */ |
| 65449 | Mem *pIn3 = 0; /* 3rd input operand */ |
| 65450 | Mem *pOut = 0; /* Output operand */ |
| @@ -65847,13 +65898,10 @@ | |
| 65898 | assert( p->explain==0 ); |
| 65899 | p->pResultSet = 0; |
| 65900 | db->busyHandler.nBusy = 0; |
| 65901 | CHECK_FOR_INTERRUPT; |
| 65902 | sqlite3VdbeIOTraceSql(p); |
| 65903 | #ifdef SQLITE_DEBUG |
| 65904 | sqlite3BeginBenignMalloc(); |
| 65905 | if( p->pc==0 && (p->db->flags & SQLITE_VdbeListing)!=0 ){ |
| 65906 | int i; |
| 65907 | printf("VDBE Program Listing:\n"); |
| @@ -65895,31 +65943,10 @@ | |
| 65943 | sqlite3_interrupt_count--; |
| 65944 | if( sqlite3_interrupt_count==0 ){ |
| 65945 | sqlite3_interrupt(db); |
| 65946 | } |
| 65947 | } |
| 65948 | #endif |
| 65949 | |
| 65950 | /* On any opcode with the "out2-prerelease" tag, free any |
| 65951 | ** external allocations out of mem[p2] and set mem[p2] to be |
| 65952 | ** an undefined integer. Opcodes will either fill in the integer |
| @@ -66010,12 +66037,42 @@ | |
| 66037 | ** The next instruction executed will be |
| 66038 | ** the one at index P2 from the beginning of |
| 66039 | ** the program. |
| 66040 | */ |
| 66041 | case OP_Goto: { /* jump */ |
| 66042 | pc = pOp->p2 - 1; |
| 66043 | |
| 66044 | /* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev, |
| 66045 | ** OP_VNext, OP_RowSetNext, or OP_SorterNext) all jump here upon |
| 66046 | ** completion. Check to see if sqlite3_interrupt() has been called |
| 66047 | ** or if the progress callback needs to be invoked. |
| 66048 | ** |
| 66049 | ** This code uses unstructured "goto" statements and does not look clean. |
| 66050 | ** But that is not due to sloppy coding habits. The code is written this |
| 66051 | ** way for performance, to avoid having to run the interrupt and progress |
| 66052 | ** checks on every opcode. This helps sqlite3_step() to run about 1.5% |
| 66053 | ** faster according to "valgrind --tool=cachegrind" */ |
| 66054 | check_for_interrupt: |
| 66055 | CHECK_FOR_INTERRUPT; |
| 66056 | #ifndef SQLITE_OMIT_PROGRESS_CALLBACK |
| 66057 | /* Call the progress callback if it is configured and the required number |
| 66058 | ** of VDBE ops have been executed (either since this invocation of |
| 66059 | ** sqlite3VdbeExec() or since last time the progress callback was called). |
| 66060 | ** If the progress callback returns non-zero, exit the virtual machine with |
| 66061 | ** a return code SQLITE_ABORT. |
| 66062 | */ |
| 66063 | if( db->xProgress!=0 && (nVmStep - nProgressOps)>=db->nProgressOps ){ |
| 66064 | int prc; |
| 66065 | prc = db->xProgress(db->pProgressArg); |
| 66066 | if( prc!=0 ){ |
| 66067 | rc = SQLITE_INTERRUPT; |
| 66068 | goto vdbe_error_halt; |
| 66069 | } |
| 66070 | nProgressOps = nVmStep; |
| 66071 | } |
| 66072 | #endif |
| 66073 | |
| 66074 | break; |
| 66075 | } |
| 66076 | |
| 66077 | /* Opcode: Gosub P1 P2 * * * |
| 66078 | ** |
| @@ -66132,11 +66189,11 @@ | |
| 66189 | assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR ); |
| 66190 | if( rc==SQLITE_BUSY ){ |
| 66191 | p->rc = rc = SQLITE_BUSY; |
| 66192 | }else{ |
| 66193 | assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ); |
| 66194 | assert( rc==SQLITE_OK || db->nDeferredCons>0 || db->nDeferredImmCons>0 ); |
| 66195 | rc = p->rc ? SQLITE_ERROR : SQLITE_DONE; |
| 66196 | } |
| 66197 | goto vdbe_return; |
| 66198 | } |
| 66199 | |
| @@ -68028,10 +68085,11 @@ | |
| 68085 | |
| 68086 | /* Link the new savepoint into the database handle's list. */ |
| 68087 | u.as.pNew->pNext = db->pSavepoint; |
| 68088 | db->pSavepoint = u.as.pNew; |
| 68089 | u.as.pNew->nDeferredCons = db->nDeferredCons; |
| 68090 | u.as.pNew->nDeferredImmCons = db->nDeferredImmCons; |
| 68091 | } |
| 68092 | } |
| 68093 | }else{ |
| 68094 | u.as.iSavepoint = 0; |
| 68095 | |
| @@ -68115,10 +68173,11 @@ | |
| 68173 | if( !isTransaction ){ |
| 68174 | db->nSavepoint--; |
| 68175 | } |
| 68176 | }else{ |
| 68177 | db->nDeferredCons = u.as.pSavepoint->nDeferredCons; |
| 68178 | db->nDeferredImmCons = u.as.pSavepoint->nDeferredImmCons; |
| 68179 | } |
| 68180 | |
| 68181 | if( !isTransaction ){ |
| 68182 | rc = sqlite3VtabSavepoint(db, u.as.p1, u.as.iSavepoint); |
| 68183 | if( rc!=SQLITE_OK ) goto abort_due_to_error; |
| @@ -68244,10 +68303,14 @@ | |
| 68303 | |
| 68304 | assert( p->bIsReader ); |
| 68305 | assert( p->readOnly==0 || pOp->p2==0 ); |
| 68306 | assert( pOp->p1>=0 && pOp->p1<db->nDb ); |
| 68307 | assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 ); |
| 68308 | if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){ |
| 68309 | rc = SQLITE_READONLY; |
| 68310 | goto abort_due_to_error; |
| 68311 | } |
| 68312 | u.au.pBt = db->aDb[pOp->p1].pBt; |
| 68313 | |
| 68314 | if( u.au.pBt ){ |
| 68315 | rc = sqlite3BtreeBeginTrans(u.au.pBt, pOp->p2); |
| 68316 | if( rc==SQLITE_BUSY ){ |
| @@ -68276,10 +68339,11 @@ | |
| 68339 | |
| 68340 | /* Store the current value of the database handles deferred constraint |
| 68341 | ** counter. If the statement transaction needs to be rolled back, |
| 68342 | ** the value of this counter needs to be restored too. */ |
| 68343 | p->nStmtDefCons = db->nDeferredCons; |
| 68344 | p->nStmtDefImmCons = db->nDeferredImmCons; |
| 68345 | } |
| 68346 | } |
| 68347 | break; |
| 68348 | } |
| 68349 | |
| @@ -69851,11 +69915,10 @@ | |
| 69915 | #if 0 /* local variables moved into u.br */ |
| 69916 | VdbeCursor *pC; |
| 69917 | int res; |
| 69918 | #endif /* local variables moved into u.br */ |
| 69919 | |
| 69920 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); |
| 69921 | assert( pOp->p5<=ArraySize(p->aCounter) ); |
| 69922 | u.br.pC = p->apCsr[pOp->p1]; |
| 69923 | if( u.br.pC==0 ){ |
| 69924 | break; /* See ticket #2273 */ |
| @@ -69880,11 +69943,11 @@ | |
| 69943 | #ifdef SQLITE_TEST |
| 69944 | sqlite3_search_count++; |
| 69945 | #endif |
| 69946 | } |
| 69947 | u.br.pC->rowidIsValid = 0; |
| 69948 | goto check_for_interrupt; |
| 69949 | } |
| 69950 | |
| 69951 | /* Opcode: IdxInsert P1 P2 P3 * P5 |
| 69952 | ** |
| 69953 | ** Register P2 holds an SQL index key made using the |
| @@ -70426,11 +70489,11 @@ | |
| 70489 | */ |
| 70490 | case OP_RowSetRead: { /* jump, in1, out3 */ |
| 70491 | #if 0 /* local variables moved into u.cb */ |
| 70492 | i64 val; |
| 70493 | #endif /* local variables moved into u.cb */ |
| 70494 | |
| 70495 | pIn1 = &aMem[pOp->p1]; |
| 70496 | if( (pIn1->flags & MEM_RowSet)==0 |
| 70497 | || sqlite3RowSetNext(pIn1->u.pRowSet, &u.cb.val)==0 |
| 70498 | ){ |
| 70499 | /* The boolean index is empty */ |
| @@ -70438,11 +70501,11 @@ | |
| 70501 | pc = pOp->p2 - 1; |
| 70502 | }else{ |
| 70503 | /* A value was pulled from the index */ |
| 70504 | sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.cb.val); |
| 70505 | } |
| 70506 | goto check_for_interrupt; |
| 70507 | } |
| 70508 | |
| 70509 | /* Opcode: RowSetTest P1 P2 P3 P4 |
| 70510 | ** |
| 70511 | ** Register P3 is assumed to hold a 64-bit integer value. If register P1 |
| @@ -70658,11 +70721,13 @@ | |
| 70721 | ** If P1 is non-zero, the database constraint counter is incremented |
| 70722 | ** (deferred foreign key constraints). Otherwise, if P1 is zero, the |
| 70723 | ** statement counter is incremented (immediate foreign key constraints). |
| 70724 | */ |
| 70725 | case OP_FkCounter: { |
| 70726 | if( db->flags & SQLITE_DeferFKs ){ |
| 70727 | db->nDeferredImmCons += pOp->p2; |
| 70728 | }else if( pOp->p1 ){ |
| 70729 | db->nDeferredCons += pOp->p2; |
| 70730 | }else{ |
| 70731 | p->nFkConstraint += pOp->p2; |
| 70732 | } |
| 70733 | break; |
| @@ -70679,13 +70744,13 @@ | |
| 70744 | ** zero, the jump is taken if the statement constraint-counter is zero |
| 70745 | ** (immediate foreign key constraint violations). |
| 70746 | */ |
| 70747 | case OP_FkIfZero: { /* jump */ |
| 70748 | if( pOp->p1 ){ |
| 70749 | if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1; |
| 70750 | }else{ |
| 70751 | if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1; |
| 70752 | } |
| 70753 | break; |
| 70754 | } |
| 70755 | #endif /* #ifndef SQLITE_OMIT_FOREIGN_KEY */ |
| 70756 | |
| @@ -71367,11 +71432,11 @@ | |
| 71432 | |
| 71433 | if( !u.cp.res ){ |
| 71434 | /* If there is data, jump to P2 */ |
| 71435 | pc = pOp->p2 - 1; |
| 71436 | } |
| 71437 | goto check_for_interrupt; |
| 71438 | } |
| 71439 | #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
| 71440 | |
| 71441 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 71442 | /* Opcode: VRename P1 * * P4 * |
| @@ -89262,11 +89327,14 @@ | |
| 89327 | sqlite3ReleaseTempReg(pParse, regRec); |
| 89328 | sqlite3ReleaseTempRange(pParse, regTemp, nCol); |
| 89329 | } |
| 89330 | } |
| 89331 | |
| 89332 | if( !pFKey->isDeferred && !(pParse->db->flags & SQLITE_DeferFKs) |
| 89333 | && !pParse->pToplevel |
| 89334 | && !pParse->isMultiWrite |
| 89335 | ){ |
| 89336 | /* Special case: If this is an INSERT statement that will insert exactly |
| 89337 | ** one row into the table, raise a constraint immediately instead of |
| 89338 | ** incrementing a counter. This is necessary as the VM code is being |
| 89339 | ** generated for will not open a statement transaction. */ |
| 89340 | assert( nIncr==1 ); |
| @@ -89653,11 +89721,13 @@ | |
| 89721 | for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){ |
| 89722 | Index *pIdx = 0; /* Foreign key index for pFKey */ |
| 89723 | SrcList *pSrc; |
| 89724 | int *aiCol = 0; |
| 89725 | |
| 89726 | if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs) |
| 89727 | && !pParse->pToplevel && !pParse->isMultiWrite |
| 89728 | ){ |
| 89729 | assert( regOld==0 && regNew!=0 ); |
| 89730 | /* Inserting a single row into a parent table cannot cause an immediate |
| 89731 | ** foreign key violation. So do nothing in this case. */ |
| 89732 | continue; |
| 89733 | } |
| @@ -92615,15 +92685,18 @@ | |
| 92685 | #ifndef SQLITE_CORE |
| 92686 | /* This case when the file really is being compiled as a loadable |
| 92687 | ** extension */ |
| 92688 | # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; |
| 92689 | # define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; |
| 92690 | # define SQLITE_EXTENSION_INIT3 \ |
| 92691 | extern const sqlite3_api_routines *sqlite3_api; |
| 92692 | #else |
| 92693 | /* This case when the file is being statically linked into the |
| 92694 | ** application */ |
| 92695 | # define SQLITE_EXTENSION_INIT1 /*no-op*/ |
| 92696 | # define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */ |
| 92697 | # define SQLITE_EXTENSION_INIT3 /*no-op*/ |
| 92698 | #endif |
| 92699 | |
| 92700 | #endif /* _SQLITE3EXT_H_ */ |
| 92701 | |
| 92702 | /************** End of sqlite3ext.h ******************************************/ |
| @@ -93275,10 +93348,39 @@ | |
| 93348 | sqlite3_mutex_leave(mutex); |
| 93349 | assert( (rc&0xff)==rc ); |
| 93350 | return rc; |
| 93351 | } |
| 93352 | } |
| 93353 | |
| 93354 | /* |
| 93355 | ** Cancel a prior call to sqlite3_auto_extension. Remove xInit from the |
| 93356 | ** set of routines that is invoked for each new database connection, if it |
| 93357 | ** is currently on the list. If xInit is not on the list, then this |
| 93358 | ** routine is a no-op. |
| 93359 | ** |
| 93360 | ** Return 1 if xInit was found on the list and removed. Return 0 if xInit |
| 93361 | ** was not on the list. |
| 93362 | */ |
| 93363 | SQLITE_API int sqlite3_cancel_auto_extension(void (*xInit)(void)){ |
| 93364 | #if SQLITE_THREADSAFE |
| 93365 | sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); |
| 93366 | #endif |
| 93367 | int i; |
| 93368 | int n = 0; |
| 93369 | wsdAutoextInit; |
| 93370 | sqlite3_mutex_enter(mutex); |
| 93371 | for(i=wsdAutoext.nExt-1; i>=0; i--){ |
| 93372 | if( wsdAutoext.aExt[i]==xInit ){ |
| 93373 | wsdAutoext.nExt--; |
| 93374 | wsdAutoext.aExt[i] = wsdAutoext.aExt[wsdAutoext.nExt]; |
| 93375 | n++; |
| 93376 | break; |
| 93377 | } |
| 93378 | } |
| 93379 | sqlite3_mutex_leave(mutex); |
| 93380 | return n; |
| 93381 | } |
| 93382 | |
| 93383 | /* |
| 93384 | ** Reset the automatic extension loading mechanism. |
| 93385 | */ |
| 93386 | SQLITE_API void sqlite3_reset_auto_extension(void){ |
| @@ -93516,10 +93618,11 @@ | |
| 93618 | { "empty_result_callbacks", SQLITE_NullCallback }, |
| 93619 | { "legacy_file_format", SQLITE_LegacyFileFmt }, |
| 93620 | { "fullfsync", SQLITE_FullFSync }, |
| 93621 | { "checkpoint_fullfsync", SQLITE_CkptFullFSync }, |
| 93622 | { "reverse_unordered_selects", SQLITE_ReverseOrder }, |
| 93623 | { "query_only", SQLITE_QueryOnly }, |
| 93624 | #ifndef SQLITE_OMIT_AUTOMATIC_INDEX |
| 93625 | { "automatic_index", SQLITE_AutoIndex }, |
| 93626 | #endif |
| 93627 | #ifdef SQLITE_DEBUG |
| 93628 | { "sql_trace", SQLITE_SqlTrace }, |
| @@ -93536,16 +93639,17 @@ | |
| 93639 | { "writable_schema", SQLITE_WriteSchema|SQLITE_RecoveryMode }, |
| 93640 | |
| 93641 | /* TODO: Maybe it shouldn't be possible to change the ReadUncommitted |
| 93642 | ** flag if there are any active statements. */ |
| 93643 | { "read_uncommitted", SQLITE_ReadUncommitted }, |
| 93644 | { "recursive_triggers", SQLITE_RecTriggers }, |
| 93645 | |
| 93646 | /* This flag may only be set if both foreign-key and trigger support |
| 93647 | ** are present in the build. */ |
| 93648 | #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) |
| 93649 | { "foreign_keys", SQLITE_ForeignKeys }, |
| 93650 | { "defer_foreign_keys", SQLITE_DeferFKs }, |
| 93651 | #endif |
| 93652 | }; |
| 93653 | int i; |
| 93654 | const struct sPragmaType *p; |
| 93655 | for(i=0, p=aPragma; i<ArraySize(aPragma); i++, p++){ |
| @@ -93567,10 +93671,11 @@ | |
| 93671 | |
| 93672 | if( sqlite3GetBoolean(zRight, 0) ){ |
| 93673 | db->flags |= mask; |
| 93674 | }else{ |
| 93675 | db->flags &= ~mask; |
| 93676 | if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0; |
| 93677 | } |
| 93678 | |
| 93679 | /* Many of the flag-pragmas modify the code generated by the SQL |
| 93680 | ** compiler (eg. count_changes). So add an opcode to expire all |
| 93681 | ** compiled SQL statements after modifying a pragma value. |
| @@ -95979,10 +96084,16 @@ | |
| 96084 | |
| 96085 | assert( ppStmt ); |
| 96086 | *ppStmt = 0; |
| 96087 | if( !sqlite3SafetyCheckOk(db) ){ |
| 96088 | return SQLITE_MISUSE_BKPT; |
| 96089 | } |
| 96090 | if( nBytes>=0 ){ |
| 96091 | int sz; |
| 96092 | const char *z = (const char*)zSql; |
| 96093 | for(sz=0; sz<nBytes && (z[sz]!=0 || z[sz+1]!=0); sz += 2){} |
| 96094 | nBytes = sz; |
| 96095 | } |
| 96096 | sqlite3_mutex_enter(db->mutex); |
| 96097 | zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE); |
| 96098 | if( zSql8 ){ |
| 96099 | rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, 0, ppStmt, &zTail8); |
| @@ -104070,12 +104181,12 @@ | |
| 104181 | int (*x)(sqlite3_vtab *); |
| 104182 | sqlite3_vtab *pVtab = aVTrans[i]->pVtab; |
| 104183 | if( pVtab && (x = pVtab->pModule->xSync)!=0 ){ |
| 104184 | rc = x(pVtab); |
| 104185 | sqlite3DbFree(db, *pzErrmsg); |
| 104186 | *pzErrmsg = pVtab->zErrMsg; |
| 104187 | pVtab->zErrMsg = 0; |
| 104188 | } |
| 104189 | } |
| 104190 | db->aVTrans = aVTrans; |
| 104191 | return rc; |
| 104192 | } |
| @@ -104391,10 +104502,12 @@ | |
| 104502 | typedef struct WhereLoop WhereLoop; |
| 104503 | typedef struct WherePath WherePath; |
| 104504 | typedef struct WhereTerm WhereTerm; |
| 104505 | typedef struct WhereLoopBuilder WhereLoopBuilder; |
| 104506 | typedef struct WhereScan WhereScan; |
| 104507 | typedef struct WhereOrCost WhereOrCost; |
| 104508 | typedef struct WhereOrSet WhereOrSet; |
| 104509 | |
| 104510 | /* |
| 104511 | ** Cost X is tracked as 10*log2(X) stored in a 16-bit integer. The |
| 104512 | ** maximum cost for ordinary tables is 64*(2**63) which becomes 6900. |
| 104513 | ** (Virtual tables can return a larger cost, but let's assume they do not.) |
| @@ -104497,10 +104610,31 @@ | |
| 104610 | u16 nLSlot; /* Number of slots allocated for aLTerm[] */ |
| 104611 | WhereTerm **aLTerm; /* WhereTerms used */ |
| 104612 | WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */ |
| 104613 | WhereTerm *aLTermSpace[4]; /* Initial aLTerm[] space */ |
| 104614 | }; |
| 104615 | |
| 104616 | /* This object holds the prerequisites and the cost of running a |
| 104617 | ** subquery on one operand of an OR operator in the WHERE clause. |
| 104618 | ** See WhereOrSet for additional information |
| 104619 | */ |
| 104620 | struct WhereOrCost { |
| 104621 | Bitmask prereq; /* Prerequisites */ |
| 104622 | WhereCost rRun; /* Cost of running this subquery */ |
| 104623 | WhereCost nOut; /* Number of outputs for this subquery */ |
| 104624 | }; |
| 104625 | |
| 104626 | /* The WhereOrSet object holds a set of possible WhereOrCosts that |
| 104627 | ** correspond to the subquery(s) of OR-clause processing. At most |
| 104628 | ** favorable N_OR_COST elements are retained. |
| 104629 | */ |
| 104630 | #define N_OR_COST 3 |
| 104631 | struct WhereOrSet { |
| 104632 | u16 n; /* Number of valid a[] entries */ |
| 104633 | WhereOrCost a[N_OR_COST]; /* Set of best costs */ |
| 104634 | }; |
| 104635 | |
| 104636 | |
| 104637 | /* Forward declaration of methods */ |
| 104638 | static int whereLoopResize(sqlite3*, WhereLoop*, int); |
| 104639 | |
| 104640 | /* |
| @@ -104712,11 +104846,11 @@ | |
| 104846 | struct WhereLoopBuilder { |
| 104847 | WhereInfo *pWInfo; /* Information about this WHERE */ |
| 104848 | WhereClause *pWC; /* WHERE clause terms */ |
| 104849 | ExprList *pOrderBy; /* ORDER BY clause */ |
| 104850 | WhereLoop *pNew; /* Template WhereLoop */ |
| 104851 | WhereOrSet *pOrSet; /* Record best loops here, if not NULL */ |
| 104852 | }; |
| 104853 | |
| 104854 | /* |
| 104855 | ** The WHERE clause processing routine has two halves. The |
| 104856 | ** first part does the start of the WHERE loop and the second |
| @@ -104854,10 +104988,58 @@ | |
| 104988 | ** UPDATE or DELETE might change subsequent WHERE clause results. |
| 104989 | */ |
| 104990 | SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo *pWInfo){ |
| 104991 | return pWInfo->okOnePass; |
| 104992 | } |
| 104993 | |
| 104994 | /* |
| 104995 | ** Move the content of pSrc into pDest |
| 104996 | */ |
| 104997 | static void whereOrMove(WhereOrSet *pDest, WhereOrSet *pSrc){ |
| 104998 | pDest->n = pSrc->n; |
| 104999 | memcpy(pDest->a, pSrc->a, pDest->n*sizeof(pDest->a[0])); |
| 105000 | } |
| 105001 | |
| 105002 | /* |
| 105003 | ** Try to insert a new prerequisite/cost entry into the WhereOrSet pSet. |
| 105004 | ** |
| 105005 | ** The new entry might overwrite an existing entry, or it might be |
| 105006 | ** appended, or it might be discarded. Do whatever is the right thing |
| 105007 | ** so that pSet keeps the N_OR_COST best entries seen so far. |
| 105008 | */ |
| 105009 | static int whereOrInsert( |
| 105010 | WhereOrSet *pSet, /* The WhereOrSet to be updated */ |
| 105011 | Bitmask prereq, /* Prerequisites of the new entry */ |
| 105012 | WhereCost rRun, /* Run-cost of the new entry */ |
| 105013 | WhereCost nOut /* Number of outputs for the new entry */ |
| 105014 | ){ |
| 105015 | u16 i; |
| 105016 | WhereOrCost *p; |
| 105017 | for(i=pSet->n, p=pSet->a; i>0; i--, p++){ |
| 105018 | if( rRun<=p->rRun && (prereq & p->prereq)==prereq ){ |
| 105019 | goto whereOrInsert_done; |
| 105020 | } |
| 105021 | if( p->rRun<=rRun && (p->prereq & prereq)==p->prereq ){ |
| 105022 | return 0; |
| 105023 | } |
| 105024 | } |
| 105025 | if( pSet->n<N_OR_COST ){ |
| 105026 | p = &pSet->a[pSet->n++]; |
| 105027 | p->nOut = nOut; |
| 105028 | }else{ |
| 105029 | p = pSet->a; |
| 105030 | for(i=1; i<pSet->n; i++){ |
| 105031 | if( p->rRun>pSet->a[i].rRun ) p = pSet->a + i; |
| 105032 | } |
| 105033 | if( p->rRun<=rRun ) return 0; |
| 105034 | } |
| 105035 | whereOrInsert_done: |
| 105036 | p->prereq = prereq; |
| 105037 | p->rRun = rRun; |
| 105038 | if( p->nOut>nOut ) p->nOut = nOut; |
| 105039 | return 1; |
| 105040 | } |
| 105041 | |
| 105042 | /* |
| 105043 | ** Initialize a preallocated WhereClause structure. |
| 105044 | */ |
| 105045 | static void whereClauseInit( |
| @@ -108089,12 +108271,13 @@ | |
| 108271 | */ |
| 108272 | if( pWC->nTerm>1 ){ |
| 108273 | int iTerm; |
| 108274 | for(iTerm=0; iTerm<pWC->nTerm; iTerm++){ |
| 108275 | Expr *pExpr = pWC->a[iTerm].pExpr; |
| 108276 | if( &pWC->a[iTerm] == pTerm ) continue; |
| 108277 | if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; |
| 108278 | if( pWC->a[iTerm].wtFlags & (TERM_ORINFO) ) continue; |
| 108279 | if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; |
| 108280 | pExpr = sqlite3ExprDup(pParse->db, pExpr, 0); |
| 108281 | pAndExpr = sqlite3ExprAnd(pParse->db, pAndExpr, pExpr); |
| 108282 | } |
| 108283 | if( pAndExpr ){ |
| @@ -108418,16 +108601,16 @@ | |
| 108601 | ** is better and has fewer dependencies. Or the template will be ignored |
| 108602 | ** and no insert will occur if an existing WhereLoop is faster and has |
| 108603 | ** fewer dependencies than the template. Otherwise a new WhereLoop is |
| 108604 | ** added based on the template. |
| 108605 | ** |
| 108606 | ** If pBuilder->pOrSet is not NULL then we only care about only the |
| 108607 | ** prerequisites and rRun and nOut costs of the N best loops. That |
| 108608 | ** information is gathered in the pBuilder->pOrSet object. This special |
| 108609 | ** processing mode is used only for OR clause processing. |
| 108610 | ** |
| 108611 | ** When accumulating multiple loops (when pBuilder->pOrSet is NULL) we |
| 108612 | ** still might overwrite similar loops with the new template if the |
| 108613 | ** template is better. Loops may be overwritten if the following |
| 108614 | ** conditions are met: |
| 108615 | ** |
| 108616 | ** (1) They have the same iTab. |
| @@ -108440,34 +108623,26 @@ | |
| 108623 | static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ |
| 108624 | WhereLoop **ppPrev, *p, *pNext = 0; |
| 108625 | WhereInfo *pWInfo = pBuilder->pWInfo; |
| 108626 | sqlite3 *db = pWInfo->pParse->db; |
| 108627 | |
| 108628 | /* If pBuilder->pOrSet is defined, then only keep track of the costs |
| 108629 | ** and prereqs. |
| 108630 | */ |
| 108631 | if( pBuilder->pOrSet!=0 ){ |
| 108632 | #if WHERETRACE_ENABLED |
| 108633 | u16 n = pBuilder->pOrSet->n; |
| 108634 | int x = |
| 108635 | #endif |
| 108636 | whereOrInsert(pBuilder->pOrSet, pTemplate->prereq, pTemplate->rRun, |
| 108637 | pTemplate->nOut); |
| 108638 | #if WHERETRACE_ENABLED |
| 108639 | if( sqlite3WhereTrace & 0x8 ){ |
| 108640 | sqlite3DebugPrintf(x?" or-%d: ":" or-X: ", n); |
| 108641 | whereLoopPrint(pTemplate, pWInfo->pTabList); |
| 108642 | } |
| 108643 | #endif |
| 108644 | return SQLITE_OK; |
| 108645 | } |
| 108646 | |
| 108647 | /* Search for an existing WhereLoop to overwrite, or which takes |
| 108648 | ** priority over pTemplate. |
| @@ -108557,11 +108732,11 @@ | |
| 108732 | |
| 108733 | /* Jump here if the insert is a no-op */ |
| 108734 | whereLoopInsert_noop: |
| 108735 | #if WHERETRACE_ENABLED |
| 108736 | if( sqlite3WhereTrace & 0x8 ){ |
| 108737 | sqlite3DebugPrintf("ins-noop: "); |
| 108738 | whereLoopPrint(pTemplate, pWInfo->pTabList); |
| 108739 | } |
| 108740 | #endif |
| 108741 | return SQLITE_OK; |
| 108742 | } |
| @@ -108839,11 +109014,11 @@ | |
| 109014 | } |
| 109015 | rSize = whereCost(pSrc->pTab->nRowEst); |
| 109016 | rLogSize = estLog(rSize); |
| 109017 | |
| 109018 | /* Automatic indexes */ |
| 109019 | if( !pBuilder->pOrSet |
| 109020 | && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0 |
| 109021 | && pSrc->pIndex==0 |
| 109022 | && !pSrc->viaCoroutine |
| 109023 | && !pSrc->notIndexed |
| 109024 | && !pSrc->isCorrelated |
| @@ -109125,11 +109300,11 @@ | |
| 109300 | WhereTerm *pTerm, *pWCEnd; |
| 109301 | int rc = SQLITE_OK; |
| 109302 | int iCur; |
| 109303 | WhereClause tempWC; |
| 109304 | WhereLoopBuilder sSubBuild; |
| 109305 | WhereOrSet sSum, sCur, sPrev; |
| 109306 | struct SrcList_item *pItem; |
| 109307 | |
| 109308 | pWC = pBuilder->pWC; |
| 109309 | if( pWInfo->wctrlFlags & WHERE_AND_ONLY ) return SQLITE_OK; |
| 109310 | pWCEnd = pWC->a + pWC->nTerm; |
| @@ -109140,20 +109315,18 @@ | |
| 109315 | && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0 |
| 109316 | ){ |
| 109317 | WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc; |
| 109318 | WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm]; |
| 109319 | WhereTerm *pOrTerm; |
| 109320 | int once = 1; |
| 109321 | int i, j; |
| 109322 | |
| 109323 | pItem = pWInfo->pTabList->a + pNew->iTab; |
| 109324 | iCur = pItem->iCursor; |
| 109325 | sSubBuild = *pBuilder; |
| 109326 | sSubBuild.pOrderBy = 0; |
| 109327 | sSubBuild.pOrSet = &sCur; |
| 109328 | |
| 109329 | for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){ |
| 109330 | if( (pOrTerm->eOperator & WO_AND)!=0 ){ |
| 109331 | sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc; |
| 109332 | }else if( pOrTerm->leftCursor==iCur ){ |
| @@ -109164,43 +109337,52 @@ | |
| 109337 | tempWC.a = pOrTerm; |
| 109338 | sSubBuild.pWC = &tempWC; |
| 109339 | }else{ |
| 109340 | continue; |
| 109341 | } |
| 109342 | sCur.n = 0; |
| 109343 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 109344 | if( IsVirtual(pItem->pTab) ){ |
| 109345 | rc = whereLoopAddVirtual(&sSubBuild); |
| 109346 | for(i=0; i<sCur.n; i++) sCur.a[i].prereq |= mExtra; |
| 109347 | }else |
| 109348 | #endif |
| 109349 | { |
| 109350 | rc = whereLoopAddBtree(&sSubBuild, mExtra); |
| 109351 | } |
| 109352 | assert( rc==SQLITE_OK || sCur.n==0 ); |
| 109353 | if( sCur.n==0 ){ |
| 109354 | sSum.n = 0; |
| 109355 | break; |
| 109356 | }else if( once ){ |
| 109357 | whereOrMove(&sSum, &sCur); |
| 109358 | once = 0; |
| 109359 | }else{ |
| 109360 | whereOrMove(&sPrev, &sSum); |
| 109361 | sSum.n = 0; |
| 109362 | for(i=0; i<sPrev.n; i++){ |
| 109363 | for(j=0; j<sCur.n; j++){ |
| 109364 | whereOrInsert(&sSum, sPrev.a[i].prereq | sCur.a[j].prereq, |
| 109365 | whereCostAdd(sPrev.a[i].rRun, sCur.a[j].rRun), |
| 109366 | whereCostAdd(sPrev.a[i].nOut, sCur.a[j].nOut)); |
| 109367 | } |
| 109368 | } |
| 109369 | } |
| 109370 | } |
| 109371 | pNew->nLTerm = 1; |
| 109372 | pNew->aLTerm[0] = pTerm; |
| 109373 | pNew->wsFlags = WHERE_MULTI_OR; |
| 109374 | pNew->rSetup = 0; |
| 109375 | pNew->iSortIdx = 0; |
| 109376 | memset(&pNew->u, 0, sizeof(pNew->u)); |
| 109377 | for(i=0; rc==SQLITE_OK && i<sSum.n; i++){ |
| 109378 | /* TUNING: Multiple by 3.5 for the secondary table lookup */ |
| 109379 | pNew->rRun = sSum.a[i].rRun + 18; |
| 109380 | pNew->nOut = sSum.a[i].nOut; |
| 109381 | pNew->prereq = sSum.a[i].prereq; |
| 109382 | rc = whereLoopInsert(pBuilder, pNew); |
| 109383 | } |
| 109384 | } |
| 109385 | } |
| 109386 | return rc; |
| 109387 | } |
| 109388 | |
| @@ -110003,11 +110185,12 @@ | |
| 110185 | pWInfo->wctrlFlags = wctrlFlags; |
| 110186 | pWInfo->savedNQueryLoop = pParse->nQueryLoop; |
| 110187 | pMaskSet = &pWInfo->sMaskSet; |
| 110188 | sWLB.pWInfo = pWInfo; |
| 110189 | sWLB.pWC = &pWInfo->sWC; |
| 110190 | sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo); |
| 110191 | assert( EIGHT_BYTE_ALIGNMENT(sWLB.pNew) ); |
| 110192 | whereLoopInit(sWLB.pNew); |
| 110193 | #ifdef SQLITE_DEBUG |
| 110194 | sWLB.pNew->cId = '*'; |
| 110195 | #endif |
| 110196 | |
| @@ -116127,10 +116310,12 @@ | |
| 116310 | } |
| 116311 | sqlite3BtreeLeaveAll(db); |
| 116312 | |
| 116313 | /* Any deferred constraint violations have now been resolved. */ |
| 116314 | db->nDeferredCons = 0; |
| 116315 | db->nDeferredImmCons = 0; |
| 116316 | db->flags &= ~SQLITE_DeferFKs; |
| 116317 | |
| 116318 | /* If one has been configured, invoke the rollback-hook callback */ |
| 116319 | if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){ |
| 116320 | db->xRollbackCallback(db->pRollbackArg); |
| 116321 | } |
| @@ -116388,11 +116573,11 @@ | |
| 116573 | void *pArg |
| 116574 | ){ |
| 116575 | sqlite3_mutex_enter(db->mutex); |
| 116576 | if( nOps>0 ){ |
| 116577 | db->xProgress = xProgress; |
| 116578 | db->nProgressOps = (unsigned)nOps; |
| 116579 | db->pProgressArg = pArg; |
| 116580 | }else{ |
| 116581 | db->xProgress = 0; |
| 116582 | db->nProgressOps = 0; |
| 116583 | db->pProgressArg = 0; |
| @@ -119087,11 +119272,11 @@ | |
| 119272 | |
| 119273 | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) |
| 119274 | |
| 119275 | /* If not building as part of the core, include sqlite3ext.h. */ |
| 119276 | #ifndef SQLITE_CORE |
| 119277 | SQLITE_EXTENSION_INIT3 |
| 119278 | #endif |
| 119279 | |
| 119280 | /************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/ |
| 119281 | /************** Begin file fts3_tokenizer.h **********************************/ |
| 119282 | /* |
| @@ -124995,11 +125180,14 @@ | |
| 125180 | |
| 125181 | #if !SQLITE_CORE |
| 125182 | /* |
| 125183 | ** Initialize API pointer table, if required. |
| 125184 | */ |
| 125185 | #ifdef _WIN32 |
| 125186 | __declspec(dllexport) |
| 125187 | #endif |
| 125188 | SQLITE_API int sqlite3_fts3_init( |
| 125189 | sqlite3 *db, |
| 125190 | char **pzErrMsg, |
| 125191 | const sqlite3_api_routines *pApi |
| 125192 | ){ |
| 125193 | SQLITE_EXTENSION_INIT2(pApi) |
| @@ -140042,11 +140230,14 @@ | |
| 140230 | (void *)pGeomCtx, geomCallback, 0, 0, doSqlite3Free |
| 140231 | ); |
| 140232 | } |
| 140233 | |
| 140234 | #if !SQLITE_CORE |
| 140235 | #ifdef _WIN32 |
| 140236 | __declspec(dllexport) |
| 140237 | #endif |
| 140238 | SQLITE_API int sqlite3_rtree_init( |
| 140239 | sqlite3 *db, |
| 140240 | char **pzErrMsg, |
| 140241 | const sqlite3_api_routines *pApi |
| 140242 | ){ |
| 140243 | SQLITE_EXTENSION_INIT2(pApi) |
| @@ -140544,11 +140735,14 @@ | |
| 140735 | |
| 140736 | return rc; |
| 140737 | } |
| 140738 | |
| 140739 | #if !SQLITE_CORE |
| 140740 | #ifdef _WIN32 |
| 140741 | __declspec(dllexport) |
| 140742 | #endif |
| 140743 | SQLITE_API int sqlite3_icu_init( |
| 140744 | sqlite3 *db, |
| 140745 | char **pzErrMsg, |
| 140746 | const sqlite3_api_routines *pApi |
| 140747 | ){ |
| 140748 | SQLITE_EXTENSION_INIT2(pApi) |
| 140749 |
+47
-18
| --- src/sqlite3.h | ||
| +++ src/sqlite3.h | ||
| @@ -107,11 +107,11 @@ | ||
| 107 | 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | 109 | */ |
| 110 | 110 | #define SQLITE_VERSION "3.8.0" |
| 111 | 111 | #define SQLITE_VERSION_NUMBER 3008000 |
| 112 | -#define SQLITE_SOURCE_ID "2013-07-09 03:04:32 52a49cbc1621094b2fe2b021209b768d29e0426b" | |
| 112 | +#define SQLITE_SOURCE_ID "2013-07-18 14:50:56 5dcffa671f592ae9355628afa439ae9a2d26f0cd" | |
| 113 | 113 | |
| 114 | 114 | /* |
| 115 | 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | 117 | ** |
| @@ -2557,11 +2557,11 @@ | ||
| 2557 | 2557 | ** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for |
| 2558 | 2558 | ** database connection D. An example use for this |
| 2559 | 2559 | ** interface is to keep a GUI updated during a large query. |
| 2560 | 2560 | ** |
| 2561 | 2561 | ** ^The parameter P is passed through as the only parameter to the |
| 2562 | -** callback function X. ^The parameter N is the number of | |
| 2562 | +** callback function X. ^The parameter N is the approximate number of | |
| 2563 | 2563 | ** [virtual machine instructions] that are evaluated between successive |
| 2564 | 2564 | ** invocations of the callback X. |
| 2565 | 2565 | ** |
| 2566 | 2566 | ** ^Only a single progress handler may be defined at one time per |
| 2567 | 2567 | ** [database connection]; setting a new progress handler cancels the |
| @@ -4182,12 +4182,12 @@ | ||
| 4182 | 4182 | ** CAPI3REF: Function Auxiliary Data |
| 4183 | 4183 | ** |
| 4184 | 4184 | ** The following two functions may be used by scalar SQL functions to |
| 4185 | 4185 | ** associate metadata with argument values. If the same value is passed to |
| 4186 | 4186 | ** multiple invocations of the same SQL function during query execution, under |
| 4187 | -** some circumstances the associated metadata may be preserved. This may | |
| 4188 | -** be used, for example, to add a regular-expression matching scalar | |
| 4187 | +** some circumstances the associated metadata may be preserved. This might | |
| 4188 | +** be used, for example, in a regular-expression matching | |
| 4189 | 4189 | ** function. The compiled version of the regular expression is stored as |
| 4190 | 4190 | ** metadata associated with the SQL value passed as the regular expression |
| 4191 | 4191 | ** pattern. The compiled regular expression can be reused on multiple |
| 4192 | 4192 | ** invocations of the same function so that the original pattern string |
| 4193 | 4193 | ** does not need to be recompiled on each invocation. |
| @@ -4197,27 +4197,36 @@ | ||
| 4197 | 4197 | ** value to the application-defined function. ^If no metadata has been ever |
| 4198 | 4198 | ** been set for the Nth argument of the function, or if the corresponding |
| 4199 | 4199 | ** function parameter has changed since the meta-data was set, |
| 4200 | 4200 | ** then sqlite3_get_auxdata() returns a NULL pointer. |
| 4201 | 4201 | ** |
| 4202 | -** ^The sqlite3_set_auxdata() interface saves the metadata | |
| 4203 | -** pointed to by its 3rd parameter as the metadata for the N-th | |
| 4204 | -** argument of the application-defined function. Subsequent | |
| 4205 | -** calls to sqlite3_get_auxdata() might return this data, if it has | |
| 4206 | -** not been destroyed. | |
| 4207 | -** ^If it is not NULL, SQLite will invoke the destructor | |
| 4208 | -** function given by the 4th parameter to sqlite3_set_auxdata() on | |
| 4209 | -** the metadata when the corresponding function parameter changes | |
| 4210 | -** or when the SQL statement completes, whichever comes first. | |
| 4202 | +** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th | |
| 4203 | +** argument of the application-defined function. ^Subsequent | |
| 4204 | +** calls to sqlite3_get_auxdata(C,N) return P from the most recent | |
| 4205 | +** sqlite3_set_auxdata(C,N,P,X) call if the data has not been dropped, or | |
| 4206 | +** NULL if the data has been dropped. | |
| 4207 | +** ^(If it is not NULL, SQLite will invoke the destructor | |
| 4208 | +** function X passed to sqlite3_set_auxdata(C,N,P,X) when <ul> | |
| 4209 | +** <li> the corresponding function parameter changes, | |
| 4210 | +** <li> [sqlite3_reset()] or [sqlite3_finalize()] is called for the | |
| 4211 | +** SQL statement, | |
| 4212 | +** <li> sqlite3_set_auxdata() is invoked again on the same parameter, or | |
| 4213 | +** <li> a memory allocation error occurs. </ul>)^ | |
| 4211 | 4214 | ** |
| 4212 | 4215 | ** SQLite is free to call the destructor and drop metadata on any |
| 4213 | 4216 | ** parameter of any function at any time. ^The only guarantee is that |
| 4214 | -** the destructor will be called before the metadata is dropped. | |
| 4217 | +** the destructor will be called when the [prepared statement] is destroyed. | |
| 4218 | +** Note in particular that the destructor X in the call to | |
| 4219 | +** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before | |
| 4220 | +** the sqlite3_set_auxdata() call even returns. Hence sqlite3_set_auxdata() | |
| 4221 | +** should be called near the end of the function implementation and the | |
| 4222 | +** implementation should not make any use of P after sqlite3_set_auxdata() | |
| 4223 | +** has been called. | |
| 4215 | 4224 | ** |
| 4216 | 4225 | ** ^(In practice, metadata is preserved between function calls for |
| 4217 | -** expressions that are constant at compile time. This includes literal | |
| 4218 | -** values and [parameters].)^ | |
| 4226 | +** function parameters that are compile-time constants, including literal | |
| 4227 | +** values and [parameters] and expressions composed from the same.)^ | |
| 4219 | 4228 | ** |
| 4220 | 4229 | ** These routines must be called from the same thread in which |
| 4221 | 4230 | ** the SQL function is running. |
| 4222 | 4231 | */ |
| 4223 | 4232 | SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); |
| @@ -5126,14 +5135,27 @@ | ||
| 5126 | 5135 | ** |
| 5127 | 5136 | ** ^Calling sqlite3_auto_extension(X) with an entry point X that is already |
| 5128 | 5137 | ** on the list of automatic extensions is a harmless no-op. ^No entry point |
| 5129 | 5138 | ** will be called more than once for each database connection that is opened. |
| 5130 | 5139 | ** |
| 5131 | -** See also: [sqlite3_reset_auto_extension()]. | |
| 5140 | +** See also: [sqlite3_reset_auto_extension()] | |
| 5141 | +** and [sqlite3_cancel_auto_extension()] | |
| 5132 | 5142 | */ |
| 5133 | 5143 | SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void)); |
| 5134 | 5144 | |
| 5145 | +/* | |
| 5146 | +** CAPI3REF: Cancel Automatic Extension Loading | |
| 5147 | +** | |
| 5148 | +** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the | |
| 5149 | +** initialization routine X that was registered using a prior call to | |
| 5150 | +** [sqlite3_auto_extension(X)]. ^The [sqlite3_cancel_auto_extension(X)] | |
| 5151 | +** routine returns 1 if initialization routine X was successfully | |
| 5152 | +** unregistered and it returns 0 if X was not on the list of initialization | |
| 5153 | +** routines. | |
| 5154 | +*/ | |
| 5155 | +SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void)); | |
| 5156 | + | |
| 5135 | 5157 | /* |
| 5136 | 5158 | ** CAPI3REF: Reset Automatic Extension Loading |
| 5137 | 5159 | ** |
| 5138 | 5160 | ** ^This interface disables all automatic extensions previously |
| 5139 | 5161 | ** registered using [sqlite3_auto_extension()]. |
| @@ -6242,10 +6264,16 @@ | ||
| 6242 | 6264 | ** transaction rollback or database recovery operations are not included. |
| 6243 | 6265 | ** If an IO or other error occurs while writing a page to disk, the effect |
| 6244 | 6266 | ** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The |
| 6245 | 6267 | ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. |
| 6246 | 6268 | ** </dd> |
| 6269 | +** | |
| 6270 | +** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt> | |
| 6271 | +** <dd>This parameter returns the zero for the current value if and only if | |
| 6272 | +** there all foreign key constraints (deferred or immediate) have been | |
| 6273 | +** resolved. The highwater mark is always 0. | |
| 6274 | +** </dd> | |
| 6247 | 6275 | ** </dl> |
| 6248 | 6276 | */ |
| 6249 | 6277 | #define SQLITE_DBSTATUS_LOOKASIDE_USED 0 |
| 6250 | 6278 | #define SQLITE_DBSTATUS_CACHE_USED 1 |
| 6251 | 6279 | #define SQLITE_DBSTATUS_SCHEMA_USED 2 |
| @@ -6254,11 +6282,12 @@ | ||
| 6254 | 6282 | #define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5 |
| 6255 | 6283 | #define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 |
| 6256 | 6284 | #define SQLITE_DBSTATUS_CACHE_HIT 7 |
| 6257 | 6285 | #define SQLITE_DBSTATUS_CACHE_MISS 8 |
| 6258 | 6286 | #define SQLITE_DBSTATUS_CACHE_WRITE 9 |
| 6259 | -#define SQLITE_DBSTATUS_MAX 9 /* Largest defined DBSTATUS */ | |
| 6287 | +#define SQLITE_DBSTATUS_DEFERRED_FKS 10 | |
| 6288 | +#define SQLITE_DBSTATUS_MAX 10 /* Largest defined DBSTATUS */ | |
| 6260 | 6289 | |
| 6261 | 6290 | |
| 6262 | 6291 | /* |
| 6263 | 6292 | ** CAPI3REF: Prepared Statement Status |
| 6264 | 6293 | ** |
| 6265 | 6294 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -107,11 +107,11 @@ | |
| 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | */ |
| 110 | #define SQLITE_VERSION "3.8.0" |
| 111 | #define SQLITE_VERSION_NUMBER 3008000 |
| 112 | #define SQLITE_SOURCE_ID "2013-07-09 03:04:32 52a49cbc1621094b2fe2b021209b768d29e0426b" |
| 113 | |
| 114 | /* |
| 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | ** |
| @@ -2557,11 +2557,11 @@ | |
| 2557 | ** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for |
| 2558 | ** database connection D. An example use for this |
| 2559 | ** interface is to keep a GUI updated during a large query. |
| 2560 | ** |
| 2561 | ** ^The parameter P is passed through as the only parameter to the |
| 2562 | ** callback function X. ^The parameter N is the number of |
| 2563 | ** [virtual machine instructions] that are evaluated between successive |
| 2564 | ** invocations of the callback X. |
| 2565 | ** |
| 2566 | ** ^Only a single progress handler may be defined at one time per |
| 2567 | ** [database connection]; setting a new progress handler cancels the |
| @@ -4182,12 +4182,12 @@ | |
| 4182 | ** CAPI3REF: Function Auxiliary Data |
| 4183 | ** |
| 4184 | ** The following two functions may be used by scalar SQL functions to |
| 4185 | ** associate metadata with argument values. If the same value is passed to |
| 4186 | ** multiple invocations of the same SQL function during query execution, under |
| 4187 | ** some circumstances the associated metadata may be preserved. This may |
| 4188 | ** be used, for example, to add a regular-expression matching scalar |
| 4189 | ** function. The compiled version of the regular expression is stored as |
| 4190 | ** metadata associated with the SQL value passed as the regular expression |
| 4191 | ** pattern. The compiled regular expression can be reused on multiple |
| 4192 | ** invocations of the same function so that the original pattern string |
| 4193 | ** does not need to be recompiled on each invocation. |
| @@ -4197,27 +4197,36 @@ | |
| 4197 | ** value to the application-defined function. ^If no metadata has been ever |
| 4198 | ** been set for the Nth argument of the function, or if the corresponding |
| 4199 | ** function parameter has changed since the meta-data was set, |
| 4200 | ** then sqlite3_get_auxdata() returns a NULL pointer. |
| 4201 | ** |
| 4202 | ** ^The sqlite3_set_auxdata() interface saves the metadata |
| 4203 | ** pointed to by its 3rd parameter as the metadata for the N-th |
| 4204 | ** argument of the application-defined function. Subsequent |
| 4205 | ** calls to sqlite3_get_auxdata() might return this data, if it has |
| 4206 | ** not been destroyed. |
| 4207 | ** ^If it is not NULL, SQLite will invoke the destructor |
| 4208 | ** function given by the 4th parameter to sqlite3_set_auxdata() on |
| 4209 | ** the metadata when the corresponding function parameter changes |
| 4210 | ** or when the SQL statement completes, whichever comes first. |
| 4211 | ** |
| 4212 | ** SQLite is free to call the destructor and drop metadata on any |
| 4213 | ** parameter of any function at any time. ^The only guarantee is that |
| 4214 | ** the destructor will be called before the metadata is dropped. |
| 4215 | ** |
| 4216 | ** ^(In practice, metadata is preserved between function calls for |
| 4217 | ** expressions that are constant at compile time. This includes literal |
| 4218 | ** values and [parameters].)^ |
| 4219 | ** |
| 4220 | ** These routines must be called from the same thread in which |
| 4221 | ** the SQL function is running. |
| 4222 | */ |
| 4223 | SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); |
| @@ -5126,14 +5135,27 @@ | |
| 5126 | ** |
| 5127 | ** ^Calling sqlite3_auto_extension(X) with an entry point X that is already |
| 5128 | ** on the list of automatic extensions is a harmless no-op. ^No entry point |
| 5129 | ** will be called more than once for each database connection that is opened. |
| 5130 | ** |
| 5131 | ** See also: [sqlite3_reset_auto_extension()]. |
| 5132 | */ |
| 5133 | SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void)); |
| 5134 | |
| 5135 | /* |
| 5136 | ** CAPI3REF: Reset Automatic Extension Loading |
| 5137 | ** |
| 5138 | ** ^This interface disables all automatic extensions previously |
| 5139 | ** registered using [sqlite3_auto_extension()]. |
| @@ -6242,10 +6264,16 @@ | |
| 6242 | ** transaction rollback or database recovery operations are not included. |
| 6243 | ** If an IO or other error occurs while writing a page to disk, the effect |
| 6244 | ** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The |
| 6245 | ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. |
| 6246 | ** </dd> |
| 6247 | ** </dl> |
| 6248 | */ |
| 6249 | #define SQLITE_DBSTATUS_LOOKASIDE_USED 0 |
| 6250 | #define SQLITE_DBSTATUS_CACHE_USED 1 |
| 6251 | #define SQLITE_DBSTATUS_SCHEMA_USED 2 |
| @@ -6254,11 +6282,12 @@ | |
| 6254 | #define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5 |
| 6255 | #define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 |
| 6256 | #define SQLITE_DBSTATUS_CACHE_HIT 7 |
| 6257 | #define SQLITE_DBSTATUS_CACHE_MISS 8 |
| 6258 | #define SQLITE_DBSTATUS_CACHE_WRITE 9 |
| 6259 | #define SQLITE_DBSTATUS_MAX 9 /* Largest defined DBSTATUS */ |
| 6260 | |
| 6261 | |
| 6262 | /* |
| 6263 | ** CAPI3REF: Prepared Statement Status |
| 6264 | ** |
| 6265 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -107,11 +107,11 @@ | |
| 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | */ |
| 110 | #define SQLITE_VERSION "3.8.0" |
| 111 | #define SQLITE_VERSION_NUMBER 3008000 |
| 112 | #define SQLITE_SOURCE_ID "2013-07-18 14:50:56 5dcffa671f592ae9355628afa439ae9a2d26f0cd" |
| 113 | |
| 114 | /* |
| 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | ** |
| @@ -2557,11 +2557,11 @@ | |
| 2557 | ** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for |
| 2558 | ** database connection D. An example use for this |
| 2559 | ** interface is to keep a GUI updated during a large query. |
| 2560 | ** |
| 2561 | ** ^The parameter P is passed through as the only parameter to the |
| 2562 | ** callback function X. ^The parameter N is the approximate number of |
| 2563 | ** [virtual machine instructions] that are evaluated between successive |
| 2564 | ** invocations of the callback X. |
| 2565 | ** |
| 2566 | ** ^Only a single progress handler may be defined at one time per |
| 2567 | ** [database connection]; setting a new progress handler cancels the |
| @@ -4182,12 +4182,12 @@ | |
| 4182 | ** CAPI3REF: Function Auxiliary Data |
| 4183 | ** |
| 4184 | ** The following two functions may be used by scalar SQL functions to |
| 4185 | ** associate metadata with argument values. If the same value is passed to |
| 4186 | ** multiple invocations of the same SQL function during query execution, under |
| 4187 | ** some circumstances the associated metadata may be preserved. This might |
| 4188 | ** be used, for example, in a regular-expression matching |
| 4189 | ** function. The compiled version of the regular expression is stored as |
| 4190 | ** metadata associated with the SQL value passed as the regular expression |
| 4191 | ** pattern. The compiled regular expression can be reused on multiple |
| 4192 | ** invocations of the same function so that the original pattern string |
| 4193 | ** does not need to be recompiled on each invocation. |
| @@ -4197,27 +4197,36 @@ | |
| 4197 | ** value to the application-defined function. ^If no metadata has been ever |
| 4198 | ** been set for the Nth argument of the function, or if the corresponding |
| 4199 | ** function parameter has changed since the meta-data was set, |
| 4200 | ** then sqlite3_get_auxdata() returns a NULL pointer. |
| 4201 | ** |
| 4202 | ** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th |
| 4203 | ** argument of the application-defined function. ^Subsequent |
| 4204 | ** calls to sqlite3_get_auxdata(C,N) return P from the most recent |
| 4205 | ** sqlite3_set_auxdata(C,N,P,X) call if the data has not been dropped, or |
| 4206 | ** NULL if the data has been dropped. |
| 4207 | ** ^(If it is not NULL, SQLite will invoke the destructor |
| 4208 | ** function X passed to sqlite3_set_auxdata(C,N,P,X) when <ul> |
| 4209 | ** <li> the corresponding function parameter changes, |
| 4210 | ** <li> [sqlite3_reset()] or [sqlite3_finalize()] is called for the |
| 4211 | ** SQL statement, |
| 4212 | ** <li> sqlite3_set_auxdata() is invoked again on the same parameter, or |
| 4213 | ** <li> a memory allocation error occurs. </ul>)^ |
| 4214 | ** |
| 4215 | ** SQLite is free to call the destructor and drop metadata on any |
| 4216 | ** parameter of any function at any time. ^The only guarantee is that |
| 4217 | ** the destructor will be called when the [prepared statement] is destroyed. |
| 4218 | ** Note in particular that the destructor X in the call to |
| 4219 | ** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before |
| 4220 | ** the sqlite3_set_auxdata() call even returns. Hence sqlite3_set_auxdata() |
| 4221 | ** should be called near the end of the function implementation and the |
| 4222 | ** implementation should not make any use of P after sqlite3_set_auxdata() |
| 4223 | ** has been called. |
| 4224 | ** |
| 4225 | ** ^(In practice, metadata is preserved between function calls for |
| 4226 | ** function parameters that are compile-time constants, including literal |
| 4227 | ** values and [parameters] and expressions composed from the same.)^ |
| 4228 | ** |
| 4229 | ** These routines must be called from the same thread in which |
| 4230 | ** the SQL function is running. |
| 4231 | */ |
| 4232 | SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); |
| @@ -5126,14 +5135,27 @@ | |
| 5135 | ** |
| 5136 | ** ^Calling sqlite3_auto_extension(X) with an entry point X that is already |
| 5137 | ** on the list of automatic extensions is a harmless no-op. ^No entry point |
| 5138 | ** will be called more than once for each database connection that is opened. |
| 5139 | ** |
| 5140 | ** See also: [sqlite3_reset_auto_extension()] |
| 5141 | ** and [sqlite3_cancel_auto_extension()] |
| 5142 | */ |
| 5143 | SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void)); |
| 5144 | |
| 5145 | /* |
| 5146 | ** CAPI3REF: Cancel Automatic Extension Loading |
| 5147 | ** |
| 5148 | ** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the |
| 5149 | ** initialization routine X that was registered using a prior call to |
| 5150 | ** [sqlite3_auto_extension(X)]. ^The [sqlite3_cancel_auto_extension(X)] |
| 5151 | ** routine returns 1 if initialization routine X was successfully |
| 5152 | ** unregistered and it returns 0 if X was not on the list of initialization |
| 5153 | ** routines. |
| 5154 | */ |
| 5155 | SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void)); |
| 5156 | |
| 5157 | /* |
| 5158 | ** CAPI3REF: Reset Automatic Extension Loading |
| 5159 | ** |
| 5160 | ** ^This interface disables all automatic extensions previously |
| 5161 | ** registered using [sqlite3_auto_extension()]. |
| @@ -6242,10 +6264,16 @@ | |
| 6264 | ** transaction rollback or database recovery operations are not included. |
| 6265 | ** If an IO or other error occurs while writing a page to disk, the effect |
| 6266 | ** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The |
| 6267 | ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. |
| 6268 | ** </dd> |
| 6269 | ** |
| 6270 | ** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt> |
| 6271 | ** <dd>This parameter returns the zero for the current value if and only if |
| 6272 | ** there all foreign key constraints (deferred or immediate) have been |
| 6273 | ** resolved. The highwater mark is always 0. |
| 6274 | ** </dd> |
| 6275 | ** </dl> |
| 6276 | */ |
| 6277 | #define SQLITE_DBSTATUS_LOOKASIDE_USED 0 |
| 6278 | #define SQLITE_DBSTATUS_CACHE_USED 1 |
| 6279 | #define SQLITE_DBSTATUS_SCHEMA_USED 2 |
| @@ -6254,11 +6282,12 @@ | |
| 6282 | #define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5 |
| 6283 | #define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 |
| 6284 | #define SQLITE_DBSTATUS_CACHE_HIT 7 |
| 6285 | #define SQLITE_DBSTATUS_CACHE_MISS 8 |
| 6286 | #define SQLITE_DBSTATUS_CACHE_WRITE 9 |
| 6287 | #define SQLITE_DBSTATUS_DEFERRED_FKS 10 |
| 6288 | #define SQLITE_DBSTATUS_MAX 10 /* Largest defined DBSTATUS */ |
| 6289 | |
| 6290 | |
| 6291 | /* |
| 6292 | ** CAPI3REF: Prepared Statement Status |
| 6293 | ** |
| 6294 |
+47
-9
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -462,11 +462,11 @@ | ||
| 462 | 462 | ; |
| 463 | 463 | |
| 464 | 464 | /* |
| 465 | 465 | ** The default Cascading Style Sheet. |
| 466 | 466 | ** It's assembled by different strings for each class. |
| 467 | -** The default css conatains all definitions. | |
| 467 | +** The default css contains all definitions. | |
| 468 | 468 | ** The style sheet, send to the client only contains the ones, |
| 469 | 469 | ** not defined in the user defined css. |
| 470 | 470 | */ |
| 471 | 471 | const char zDefaultCSS[] = |
| 472 | 472 | @ /* General settings for the entire page */ |
| @@ -965,20 +965,43 @@ | ||
| 965 | 965 | { "ul.filelist", |
| 966 | 966 | "List of files in a timeline", |
| 967 | 967 | @ margin-top: 3px; |
| 968 | 968 | @ line-height: 100%; |
| 969 | 969 | }, |
| 970 | - { "div.sbsdiff", | |
| 971 | - "side-by-side diff display", | |
| 972 | - @ font-family: monospace; | |
| 970 | + { "table.sbsdiffcols", | |
| 971 | + "side-by-side diff display (column-based)", | |
| 972 | + @ border-spacing: 0; | |
| 973 | 973 | @ font-size: xx-small; |
| 974 | - @ white-space: pre; | |
| 974 | + }, | |
| 975 | + { "table.sbsdiffcols td", | |
| 976 | + "sbs diff table cell", | |
| 977 | + @ padding: 0; | |
| 978 | + @ vertical-align: top; | |
| 979 | + }, | |
| 980 | + { "table.sbsdiffcols pre", | |
| 981 | + "sbs diff pre block", | |
| 982 | + @ margin: 0; | |
| 983 | + @ padding: 0; | |
| 984 | + @ border: 0; | |
| 985 | + @ font-size: inherit; | |
| 986 | + @ background: inherit; | |
| 987 | + @ color: inherit; | |
| 988 | + }, | |
| 989 | + { "div.difflncol", | |
| 990 | + "diff line number column", | |
| 991 | + @ padding-right: 1em; | |
| 992 | + @ text-align: right; | |
| 993 | + @ color: #a0a0a0; | |
| 994 | + }, | |
| 995 | + { "div.difftxtcol", | |
| 996 | + "diff text column", | |
| 997 | + @ width: 45em; | |
| 998 | + @ overflow-x: auto; | |
| 975 | 999 | }, |
| 976 | - { "div.udiff", | |
| 977 | - "context diff display", | |
| 978 | - @ font-family: monospace; | |
| 979 | - @ white-space: pre; | |
| 1000 | + { "div.diffmkrcol", | |
| 1001 | + "diff marker column", | |
| 1002 | + @ padding: 0 1em; | |
| 980 | 1003 | }, |
| 981 | 1004 | { "span.diffchng", |
| 982 | 1005 | "changes in a diff", |
| 983 | 1006 | @ background-color: #c0c0ff; |
| 984 | 1007 | }, |
| @@ -990,10 +1013,12 @@ | ||
| 990 | 1013 | "deleted in a diff", |
| 991 | 1014 | @ background-color: #ffc8c8; |
| 992 | 1015 | }, |
| 993 | 1016 | { "span.diffhr", |
| 994 | 1017 | "suppressed lines in a diff", |
| 1018 | + @ display: inline-block; | |
| 1019 | + @ margin: .5em 0 1em; | |
| 995 | 1020 | @ color: #0000ff; |
| 996 | 1021 | }, |
| 997 | 1022 | { "span.diffln", |
| 998 | 1023 | "line numbers in a diff", |
| 999 | 1024 | @ color: #a0a0a0; |
| @@ -1033,10 +1058,23 @@ | ||
| 1033 | 1058 | @ padding: 0.1em 1em 0.1em 1em; |
| 1034 | 1059 | }, |
| 1035 | 1060 | { ".statistics-report-row-year", |
| 1036 | 1061 | "", |
| 1037 | 1062 | @ text-align: left; |
| 1063 | + }, | |
| 1064 | + { ".statistics-report-graph-line", | |
| 1065 | + "for the /stats_report views", | |
| 1066 | + @ background-color: #446979; | |
| 1067 | + }, | |
| 1068 | + { ".statistics-report-week-number-label", | |
| 1069 | + "for the /stats_report views", | |
| 1070 | + @ text-align: right; | |
| 1071 | + @ font-size: 0.8em; | |
| 1072 | + }, | |
| 1073 | + { ".statistics-report-week-of-year-list", | |
| 1074 | + "for the /stats_report views", | |
| 1075 | + @ font-size: 0.8em; | |
| 1038 | 1076 | }, |
| 1039 | 1077 | { "tr.row0", |
| 1040 | 1078 | "even table row color", |
| 1041 | 1079 | @ /* use default */ |
| 1042 | 1080 | }, |
| 1043 | 1081 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -462,11 +462,11 @@ | |
| 462 | ; |
| 463 | |
| 464 | /* |
| 465 | ** The default Cascading Style Sheet. |
| 466 | ** It's assembled by different strings for each class. |
| 467 | ** The default css conatains all definitions. |
| 468 | ** The style sheet, send to the client only contains the ones, |
| 469 | ** not defined in the user defined css. |
| 470 | */ |
| 471 | const char zDefaultCSS[] = |
| 472 | @ /* General settings for the entire page */ |
| @@ -965,20 +965,43 @@ | |
| 965 | { "ul.filelist", |
| 966 | "List of files in a timeline", |
| 967 | @ margin-top: 3px; |
| 968 | @ line-height: 100%; |
| 969 | }, |
| 970 | { "div.sbsdiff", |
| 971 | "side-by-side diff display", |
| 972 | @ font-family: monospace; |
| 973 | @ font-size: xx-small; |
| 974 | @ white-space: pre; |
| 975 | }, |
| 976 | { "div.udiff", |
| 977 | "context diff display", |
| 978 | @ font-family: monospace; |
| 979 | @ white-space: pre; |
| 980 | }, |
| 981 | { "span.diffchng", |
| 982 | "changes in a diff", |
| 983 | @ background-color: #c0c0ff; |
| 984 | }, |
| @@ -990,10 +1013,12 @@ | |
| 990 | "deleted in a diff", |
| 991 | @ background-color: #ffc8c8; |
| 992 | }, |
| 993 | { "span.diffhr", |
| 994 | "suppressed lines in a diff", |
| 995 | @ color: #0000ff; |
| 996 | }, |
| 997 | { "span.diffln", |
| 998 | "line numbers in a diff", |
| 999 | @ color: #a0a0a0; |
| @@ -1033,10 +1058,23 @@ | |
| 1033 | @ padding: 0.1em 1em 0.1em 1em; |
| 1034 | }, |
| 1035 | { ".statistics-report-row-year", |
| 1036 | "", |
| 1037 | @ text-align: left; |
| 1038 | }, |
| 1039 | { "tr.row0", |
| 1040 | "even table row color", |
| 1041 | @ /* use default */ |
| 1042 | }, |
| 1043 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -462,11 +462,11 @@ | |
| 462 | ; |
| 463 | |
| 464 | /* |
| 465 | ** The default Cascading Style Sheet. |
| 466 | ** It's assembled by different strings for each class. |
| 467 | ** The default css contains all definitions. |
| 468 | ** The style sheet, send to the client only contains the ones, |
| 469 | ** not defined in the user defined css. |
| 470 | */ |
| 471 | const char zDefaultCSS[] = |
| 472 | @ /* General settings for the entire page */ |
| @@ -965,20 +965,43 @@ | |
| 965 | { "ul.filelist", |
| 966 | "List of files in a timeline", |
| 967 | @ margin-top: 3px; |
| 968 | @ line-height: 100%; |
| 969 | }, |
| 970 | { "table.sbsdiffcols", |
| 971 | "side-by-side diff display (column-based)", |
| 972 | @ border-spacing: 0; |
| 973 | @ font-size: xx-small; |
| 974 | }, |
| 975 | { "table.sbsdiffcols td", |
| 976 | "sbs diff table cell", |
| 977 | @ padding: 0; |
| 978 | @ vertical-align: top; |
| 979 | }, |
| 980 | { "table.sbsdiffcols pre", |
| 981 | "sbs diff pre block", |
| 982 | @ margin: 0; |
| 983 | @ padding: 0; |
| 984 | @ border: 0; |
| 985 | @ font-size: inherit; |
| 986 | @ background: inherit; |
| 987 | @ color: inherit; |
| 988 | }, |
| 989 | { "div.difflncol", |
| 990 | "diff line number column", |
| 991 | @ padding-right: 1em; |
| 992 | @ text-align: right; |
| 993 | @ color: #a0a0a0; |
| 994 | }, |
| 995 | { "div.difftxtcol", |
| 996 | "diff text column", |
| 997 | @ width: 45em; |
| 998 | @ overflow-x: auto; |
| 999 | }, |
| 1000 | { "div.diffmkrcol", |
| 1001 | "diff marker column", |
| 1002 | @ padding: 0 1em; |
| 1003 | }, |
| 1004 | { "span.diffchng", |
| 1005 | "changes in a diff", |
| 1006 | @ background-color: #c0c0ff; |
| 1007 | }, |
| @@ -990,10 +1013,12 @@ | |
| 1013 | "deleted in a diff", |
| 1014 | @ background-color: #ffc8c8; |
| 1015 | }, |
| 1016 | { "span.diffhr", |
| 1017 | "suppressed lines in a diff", |
| 1018 | @ display: inline-block; |
| 1019 | @ margin: .5em 0 1em; |
| 1020 | @ color: #0000ff; |
| 1021 | }, |
| 1022 | { "span.diffln", |
| 1023 | "line numbers in a diff", |
| 1024 | @ color: #a0a0a0; |
| @@ -1033,10 +1058,23 @@ | |
| 1058 | @ padding: 0.1em 1em 0.1em 1em; |
| 1059 | }, |
| 1060 | { ".statistics-report-row-year", |
| 1061 | "", |
| 1062 | @ text-align: left; |
| 1063 | }, |
| 1064 | { ".statistics-report-graph-line", |
| 1065 | "for the /stats_report views", |
| 1066 | @ background-color: #446979; |
| 1067 | }, |
| 1068 | { ".statistics-report-week-number-label", |
| 1069 | "for the /stats_report views", |
| 1070 | @ text-align: right; |
| 1071 | @ font-size: 0.8em; |
| 1072 | }, |
| 1073 | { ".statistics-report-week-of-year-list", |
| 1074 | "for the /stats_report views", |
| 1075 | @ font-size: 0.8em; |
| 1076 | }, |
| 1077 | { "tr.row0", |
| 1078 | "even table row color", |
| 1079 | @ /* use default */ |
| 1080 | }, |
| 1081 |
+228
-39
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -1032,10 +1032,11 @@ | ||
| 1032 | 1032 | const char *zTagName = P("t"); /* Show events with this tag */ |
| 1033 | 1033 | const char *zBrName = P("r"); /* Show events related to this tag */ |
| 1034 | 1034 | const char *zSearch = P("s"); /* Search string */ |
| 1035 | 1035 | const char *zUses = P("uf"); /* Only show checkins hold this file */ |
| 1036 | 1036 | const char *zYearMonth = P("ym"); /* Show checkins for the given YYYY-MM */ |
| 1037 | + const char *zYearWeek = P("yw"); /* Show checkins for the given YYYY-WW (weak-of-year) */ | |
| 1037 | 1038 | int useDividers = P("nd")==0; /* Show dividers if "nd" is missing */ |
| 1038 | 1039 | int renameOnly = P("namechng")!=0; /* Show only checkins that rename files */ |
| 1039 | 1040 | int tagid; /* Tag ID */ |
| 1040 | 1041 | int tmFlags; /* Timeline flags */ |
| 1041 | 1042 | const char *zThisTag = 0; /* Suppress links to this tag */ |
| @@ -1218,10 +1219,14 @@ | ||
| 1218 | 1219 | } |
| 1219 | 1220 | if( zYearMonth ){ |
| 1220 | 1221 | blob_appendf(&sql, " AND %Q=strftime('%%Y-%%m',event.mtime) ", |
| 1221 | 1222 | zYearMonth); |
| 1222 | 1223 | } |
| 1224 | + else if( zYearWeek ){ | |
| 1225 | + blob_appendf(&sql, " AND %Q=strftime('%%Y-%%W',event.mtime) ", | |
| 1226 | + zYearWeek); | |
| 1227 | + } | |
| 1223 | 1228 | if( tagid>0 ){ |
| 1224 | 1229 | blob_appendf(&sql, |
| 1225 | 1230 | "AND (EXISTS(SELECT 1 FROM tagxref" |
| 1226 | 1231 | " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)", tagid); |
| 1227 | 1232 | |
| @@ -1350,10 +1355,12 @@ | ||
| 1350 | 1355 | db_multi_exec("%s", blob_str(&sql)); |
| 1351 | 1356 | |
| 1352 | 1357 | n = db_int(0, "SELECT count(*) FROM timeline WHERE etype!='div' /*scan*/"); |
| 1353 | 1358 | if( zYearMonth ){ |
| 1354 | 1359 | blob_appendf(&desc, "%s events for %h", zEType, zYearMonth); |
| 1360 | + }else if( zYearWeek ){ | |
| 1361 | + blob_appendf(&desc, "%s events for year/week %h", zEType, zYearWeek); | |
| 1355 | 1362 | }else if( zAfter==0 && zBefore==0 && zCirca==0 ){ |
| 1356 | 1363 | blob_appendf(&desc, "%d most recent %ss", n, zEType); |
| 1357 | 1364 | }else{ |
| 1358 | 1365 | blob_appendf(&desc, "%d %ss", n, zEType); |
| 1359 | 1366 | } |
| @@ -1829,36 +1836,64 @@ | ||
| 1829 | 1836 | } |
| 1830 | 1837 | db_finalize(&q); |
| 1831 | 1838 | style_footer(); |
| 1832 | 1839 | } |
| 1833 | 1840 | |
| 1834 | - | |
| 1841 | +/* | |
| 1842 | +** Helper for stats_report_by_month_year(), which generates a list of | |
| 1843 | +** week numbers. zTimeframe should be either a timeframe in the form YYYY | |
| 1844 | +** or YYYY-MM. | |
| 1845 | +*/ | |
| 1846 | +static void stats_report_output_week_links(const char * zTimeframe){ | |
| 1847 | + Stmt stWeek = empty_Stmt; | |
| 1848 | + char yearPart[5] = {0,0,0,0,0}; | |
| 1849 | + memcpy(yearPart, zTimeframe, 4); | |
| 1850 | + db_prepare(&stWeek, | |
| 1851 | + "SELECT DISTINCT strftime('%%W',mtime) AS wk, " | |
| 1852 | + "count(*) AS n, " | |
| 1853 | + "substr(date(mtime),1,%d) AS ym " | |
| 1854 | + "FROM event " | |
| 1855 | + "WHERE ym=%Q AND mtime < current_timestamp " | |
| 1856 | + "GROUP BY wk ORDER BY wk", | |
| 1857 | + strlen(zTimeframe), | |
| 1858 | + zTimeframe); | |
| 1859 | + while( SQLITE_ROW == db_step(&stWeek) ){ | |
| 1860 | + const char * zWeek = db_column_text(&stWeek,0); | |
| 1861 | + const int nCount = db_column_int(&stWeek,1); | |
| 1862 | + cgi_printf("<a href='%s/timeline?" | |
| 1863 | + "yw=%t-%t&n=%d'>%s</a>", | |
| 1864 | + g.zTop, yearPart, zWeek, | |
| 1865 | + nCount, zWeek); | |
| 1866 | + } | |
| 1867 | + db_finalize(&stWeek); | |
| 1868 | +} | |
| 1835 | 1869 | |
| 1836 | 1870 | /* |
| 1837 | 1871 | ** Implements the "byyear" and "bymonth" reports for /stats_report. |
| 1838 | 1872 | ** If includeMonth is true then it generates the "bymonth" report, |
| 1839 | 1873 | ** else the "byyear" report. If zUserName is not NULL and not empty |
| 1840 | 1874 | ** then the report is restricted to events created by the named user |
| 1841 | 1875 | ** account. |
| 1842 | 1876 | */ |
| 1843 | 1877 | static void stats_report_by_month_year(char includeMonth, |
| 1844 | - char const * zUserName){ | |
| 1878 | + char includeWeeks, | |
| 1879 | + const char * zUserName){ | |
| 1845 | 1880 | Stmt query = empty_Stmt; |
| 1846 | - int const nPixelsPerEvent = 1; /* for sizing the "graph" part */ | |
| 1847 | 1881 | int nRowNumber = 0; /* current TR number */ |
| 1848 | 1882 | int nEventTotal = 0; /* Total event count */ |
| 1849 | 1883 | int rowClass = 0; /* counter for alternating |
| 1850 | 1884 | row colors */ |
| 1851 | 1885 | Blob sql = empty_blob; /* SQL */ |
| 1852 | - char const * zTimeLabel = includeMonth ? "Year/Month" : "Year"; | |
| 1886 | + const char * zTimeLabel = includeMonth ? "Year/Month" : "Year"; | |
| 1853 | 1887 | char zPrevYear[5] = {0}; /* For keeping track of when |
| 1854 | 1888 | we change years while looping */ |
| 1855 | - int nEventsPerYear = 0; /* Total even count for the | |
| 1889 | + int nEventsPerYear = 0; /* Total event count for the | |
| 1856 | 1890 | current year */ |
| 1857 | 1891 | char showYearTotal = 0; /* Flag telling us when to show |
| 1858 | 1892 | the per-year event totals */ |
| 1859 | 1893 | Blob header = empty_blob; /* Page header text */ |
| 1894 | + int nMaxEvents = 1; /* for calculating length of graph bars. */ | |
| 1860 | 1895 | |
| 1861 | 1896 | blob_appendf(&header, "Timeline Events by year%s", |
| 1862 | 1897 | (includeMonth ? "/month" : "")); |
| 1863 | 1898 | blob_appendf(&sql, |
| 1864 | 1899 | "SELECT substr(date(mtime),1,%d) AS timeframe, " |
| @@ -1879,18 +1914,31 @@ | ||
| 1879 | 1914 | @ <table class='statistics-report-table-events' border='0' cellpadding='2' |
| 1880 | 1915 | @ cellspacing='0' id='statsTable'> |
| 1881 | 1916 | @ <thead> |
| 1882 | 1917 | @ <th>%s(zTimeLabel)</th> |
| 1883 | 1918 | @ <th>Events</th> |
| 1884 | - @ <th><!-- relative commits graph --></th> | |
| 1919 | + @ <th width='90%%'><!-- relative commits graph --></th> | |
| 1885 | 1920 | @ </thead><tbody> |
| 1886 | 1921 | blob_reset(&header); |
| 1922 | + /* | |
| 1923 | + Run the query twice. The first time we calculate the maximum | |
| 1924 | + number of events for a given row. Maybe someone with better SQL | |
| 1925 | + Fu can re-implement this with a single query. | |
| 1926 | + */ | |
| 1927 | + while( SQLITE_ROW == db_step(&query) ){ | |
| 1928 | + const int nCount = db_column_int(&query, 1); | |
| 1929 | + if(nCount>nMaxEvents){ | |
| 1930 | + nMaxEvents = nCount; | |
| 1931 | + } | |
| 1932 | + } | |
| 1933 | + db_reset(&query); | |
| 1887 | 1934 | while( SQLITE_ROW == db_step(&query) ){ |
| 1888 | - char const * zTimeframe = db_column_text(&query, 0); | |
| 1889 | - int const nCount = db_column_int(&query, 1); | |
| 1890 | - int const nSize = 1 + ((nPixelsPerEvent * nCount) | |
| 1891 | - / (includeMonth ? 1 : 10)); | |
| 1935 | + const char * zTimeframe = db_column_text(&query, 0); | |
| 1936 | + const int nCount = db_column_int(&query, 1); | |
| 1937 | + const int nSize = nCount | |
| 1938 | + ? (int)(100 * nCount / nMaxEvents) | |
| 1939 | + : 1; | |
| 1892 | 1940 | showYearTotal = 0; |
| 1893 | 1941 | if(includeMonth){ |
| 1894 | 1942 | /* For Month/year view, add a separator for each distinct year. */ |
| 1895 | 1943 | if(!*zPrevYear || |
| 1896 | 1944 | (0!=fossil_strncmp(zPrevYear,zTimeframe,4))){ |
| @@ -1906,17 +1954,17 @@ | ||
| 1906 | 1954 | memcpy(zPrevYear,zTimeframe,4); |
| 1907 | 1955 | rowClass = ++nRowNumber % 2; |
| 1908 | 1956 | @ <tr class='row%d(rowClass)'> |
| 1909 | 1957 | @ <th colspan='3' class='statistics-report-row-year'>%s(zPrevYear)</th> |
| 1910 | 1958 | @ </tr> |
| 1911 | - } | |
| 1912 | - } | |
| 1913 | - rowClass = ++nRowNumber % 2; | |
| 1914 | - nEventTotal += nCount; | |
| 1915 | - nEventsPerYear += nCount; | |
| 1916 | - @<tr class='row%d(rowClass)'> | |
| 1917 | - @ <td> | |
| 1959 | + } | |
| 1960 | + } | |
| 1961 | + rowClass = ++nRowNumber % 2; | |
| 1962 | + nEventTotal += nCount; | |
| 1963 | + nEventsPerYear += nCount; | |
| 1964 | + @<tr class='row%d(rowClass)'> | |
| 1965 | + @ <td> | |
| 1918 | 1966 | if(includeMonth){ |
| 1919 | 1967 | cgi_printf("<a href='%s/timeline?" |
| 1920 | 1968 | "ym=%t&n=%d", |
| 1921 | 1969 | g.zTop, zTimeframe, nCount ); |
| 1922 | 1970 | /* Reminder: n=nCount is not actually correct for bymonth unless |
| @@ -1925,41 +1973,51 @@ | ||
| 1925 | 1973 | if( zUserName && *zUserName ){ |
| 1926 | 1974 | cgi_printf("&u=%t", zUserName); |
| 1927 | 1975 | } |
| 1928 | 1976 | cgi_printf("' target='_new'>%s</a>",zTimeframe); |
| 1929 | 1977 | }else { |
| 1930 | - @ %s(zTimeframe) | |
| 1978 | + cgi_printf("<a href='?view=byweek&y=%s", zTimeframe); | |
| 1979 | + if(zUserName && *zUserName){ | |
| 1980 | + cgi_printf("&u=%t", zUserName); | |
| 1981 | + } | |
| 1982 | + cgi_printf("'>%s</a>", zTimeframe); | |
| 1931 | 1983 | } |
| 1932 | 1984 | @ </td><td>%d(nCount)</td> |
| 1933 | 1985 | @ <td> |
| 1934 | 1986 | @ <div class='statistics-report-graph-line' |
| 1935 | - @ style='height:16px;width:%d(nSize)px;'> | |
| 1987 | + @ style='height:16px;width:%d(nSize)%%;'> | |
| 1936 | 1988 | @ </div></td> |
| 1937 | 1989 | @</tr> |
| 1990 | + if(includeWeeks){ | |
| 1991 | + /* This part works fine for months but it terribly slow (4.5s on my PC), | |
| 1992 | + so it's only shown for by-year for now. Suggestions/patches for | |
| 1993 | + a better/faster layout are welcomed. */ | |
| 1994 | + @ <tr class='row%d(rowClass)'> | |
| 1995 | + @ <td colspan='2' class='statistics-report-week-number-label'>Week #:</td> | |
| 1996 | + @ <td class='statistics-report-week-of-year-list'> | |
| 1997 | + stats_report_output_week_links(zTimeframe); | |
| 1998 | + @ </td></tr> | |
| 1999 | + } | |
| 1938 | 2000 | |
| 1939 | 2001 | /* |
| 1940 | 2002 | Potential improvement: calculate the min/max event counts and |
| 1941 | 2003 | use percent-based graph bars. |
| 1942 | 2004 | */ |
| 1943 | 2005 | } |
| 1944 | - | |
| 2006 | + db_finalize(&query); | |
| 1945 | 2007 | if(includeMonth && !showYearTotal && *zPrevYear){ |
| 1946 | 2008 | /* Add final year total separator. */ |
| 1947 | 2009 | rowClass = ++nRowNumber % 2; |
| 1948 | 2010 | @ <tr class='row%d(rowClass)'> |
| 1949 | 2011 | @ <td></td> |
| 1950 | 2012 | @ <td colspan='2'>Yearly total: %d(nEventsPerYear)</td> |
| 1951 | 2013 | @</tr> |
| 1952 | 2014 | } |
| 1953 | -#if 0 | |
| 1954 | - rowClass = ++nRowNumber % 2; | |
| 1955 | - @ <tr class='row%d(rowClass)'> | |
| 1956 | - @ <td colspan='3'>Total events: %d(nEventTotal)</td> | |
| 1957 | - @ </tr> | |
| 1958 | -#endif | |
| 1959 | 2015 | @ </tbody></table> |
| 1960 | - db_finalize(&query); | |
| 2016 | + if(nEventTotal){ | |
| 2017 | + @ <br><div>Total events: %d(nEventTotal)</div> | |
| 2018 | + } | |
| 1961 | 2019 | if( !includeMonth ){ |
| 1962 | 2020 | output_table_sorting_javascript("statsTable","tnx"); |
| 1963 | 2021 | } |
| 1964 | 2022 | } |
| 1965 | 2023 | |
| @@ -1966,16 +2024,17 @@ | ||
| 1966 | 2024 | /* |
| 1967 | 2025 | ** Implements the "byuser" view for /stats_report. |
| 1968 | 2026 | */ |
| 1969 | 2027 | static void stats_report_by_user(){ |
| 1970 | 2028 | Stmt query = empty_Stmt; |
| 1971 | - int const nPixelsPerEvent = 1; /* for sizing the "graph" part */ | |
| 1972 | 2029 | int nRowNumber = 0; /* current TR number */ |
| 1973 | 2030 | int nEventTotal = 0; /* Total event count */ |
| 1974 | 2031 | int rowClass = 0; /* counter for alternating |
| 1975 | 2032 | row colors */ |
| 1976 | 2033 | Blob sql = empty_blob; /* SQL */ |
| 2034 | + int nMaxEvents = 1; /* max number of events for | |
| 2035 | + all rows. */ | |
| 1977 | 2036 | blob_append(&sql, |
| 1978 | 2037 | "SELECT user, " |
| 1979 | 2038 | "COUNT(*) AS eventCount " |
| 1980 | 2039 | "FROM event " |
| 1981 | 2040 | "GROUP BY user ORDER BY eventCount DESC", |
| @@ -1986,26 +2045,35 @@ | ||
| 1986 | 2045 | @ <table class='statistics-report-table-events' border='0' |
| 1987 | 2046 | @ cellpadding='2' cellspacing='0' id='statsTable'> |
| 1988 | 2047 | @ <thead><tr> |
| 1989 | 2048 | @ <th>User</th> |
| 1990 | 2049 | @ <th>Events</th> |
| 1991 | - @ <th><!-- relative commits graph --></th> | |
| 2050 | + @ <th width='90%%'><!-- relative commits graph --></th> | |
| 1992 | 2051 | @ </tr></thead><tbody> |
| 1993 | 2052 | while( SQLITE_ROW == db_step(&query) ){ |
| 1994 | - char const * zUser = db_column_text(&query, 0); | |
| 1995 | - int const nCount = db_column_int(&query, 1); | |
| 1996 | - int const nSize = 1+((nPixelsPerEvent * nCount) / 10); | |
| 1997 | - if(!nCount) continue /* arguable! */; | |
| 2053 | + const int nCount = db_column_int(&query, 1); | |
| 2054 | + if(nCount>nMaxEvents){ | |
| 2055 | + nMaxEvents = nCount; | |
| 2056 | + } | |
| 2057 | + } | |
| 2058 | + db_reset(&query); | |
| 2059 | + while( SQLITE_ROW == db_step(&query) ){ | |
| 2060 | + const char * zUser = db_column_text(&query, 0); | |
| 2061 | + const int nCount = db_column_int(&query, 1); | |
| 2062 | + const int nSize = nCount | |
| 2063 | + ? (int)(100 * nCount / nMaxEvents) | |
| 2064 | + : 0; | |
| 2065 | + if(!nCount) continue /* arguable! Possible? */; | |
| 1998 | 2066 | rowClass = ++nRowNumber % 2; |
| 1999 | 2067 | nEventTotal += nCount; |
| 2000 | 2068 | @<tr class='row%d(rowClass)'> |
| 2001 | 2069 | @ <td> |
| 2002 | 2070 | @ <a href="?view=bymonth&user=%h(zUser)" target="_new">%h(zUser)</a> |
| 2003 | 2071 | @ </td><td>%d(nCount)</td> |
| 2004 | 2072 | @ <td> |
| 2005 | 2073 | @ <div class='statistics-report-graph-line' |
| 2006 | - @ style='height:16px;width:%d(nSize)px;'> | |
| 2074 | + @ style='height:16px;width:%d(nSize)%%;'> | |
| 2007 | 2075 | @ </div></td> |
| 2008 | 2076 | @</tr> |
| 2009 | 2077 | /* |
| 2010 | 2078 | Potential improvement: calculate the min/max event counts and |
| 2011 | 2079 | use percent-based graph bars. |
| @@ -2014,10 +2082,128 @@ | ||
| 2014 | 2082 | @ </tbody></table> |
| 2015 | 2083 | db_finalize(&query); |
| 2016 | 2084 | output_table_sorting_javascript("statsTable","tnx"); |
| 2017 | 2085 | } |
| 2018 | 2086 | |
| 2087 | + | |
| 2088 | +/* | |
| 2089 | +** Helper for stats_report_by_month_year(), which generates a list of | |
| 2090 | +** week numbers. zTimeframe should be either a timeframe in the form YYYY | |
| 2091 | +** or YYYY-MM. | |
| 2092 | +*/ | |
| 2093 | +static void stats_report_year_weeks(const char * zUserName){ | |
| 2094 | + const char * zYear = P("y"); | |
| 2095 | + int nYear = zYear ? strlen(zYear) : 0; | |
| 2096 | + int i = 0; | |
| 2097 | + Stmt qYears = empty_Stmt; | |
| 2098 | + char * zDefaultYear = NULL; | |
| 2099 | + Blob sql = empty_blob; | |
| 2100 | + int nMaxEvents = 1; /* max number of events for | |
| 2101 | + all rows. */ | |
| 2102 | + | |
| 2103 | + cgi_printf("Select year: "); | |
| 2104 | + blob_append(&sql, | |
| 2105 | + "SELECT DISTINCT substr(date(mtime),1,4) AS y " | |
| 2106 | + "FROM event WHERE 1 ", -1); | |
| 2107 | + if(zUserName&&*zUserName){ | |
| 2108 | + blob_appendf(&sql,"AND user=%Q ", zUserName); | |
| 2109 | + } | |
| 2110 | + blob_append(&sql,"GROUP BY y ORDER BY y", -1); | |
| 2111 | + db_prepare(&qYears, blob_str(&sql)); | |
| 2112 | + blob_reset(&sql); | |
| 2113 | + while( SQLITE_ROW == db_step(&qYears) ){ | |
| 2114 | + const char * zT = db_column_text(&qYears, 0); | |
| 2115 | + if( i++ ){ | |
| 2116 | + cgi_printf(" "); | |
| 2117 | + } | |
| 2118 | + cgi_printf("<a href='?view=byweek&y=%s", zT); | |
| 2119 | + if(zUserName && *zUserName){ | |
| 2120 | + cgi_printf("&user=%t",zUserName); | |
| 2121 | + } | |
| 2122 | + cgi_printf("'>%s</a>",zT); | |
| 2123 | + } | |
| 2124 | + db_finalize(&qYears); | |
| 2125 | + cgi_printf("<br/>"); | |
| 2126 | + if(!zYear || !*zYear){ | |
| 2127 | + zDefaultYear = db_text("????", "SELECT strftime('%%Y')"); | |
| 2128 | + zYear = zDefaultYear; | |
| 2129 | + nYear = 4; | |
| 2130 | + } | |
| 2131 | + if(4 == nYear){ | |
| 2132 | + Stmt stWeek = empty_Stmt; | |
| 2133 | + int rowCount = 0; | |
| 2134 | + int total = 0; | |
| 2135 | + Blob header = empty_blob; | |
| 2136 | + blob_appendf(&header, "Timeline events for the calendar weeks " | |
| 2137 | + "of %h", zYear); | |
| 2138 | + blob_appendf(&sql, | |
| 2139 | + "SELECT DISTINCT strftime('%%%%W',mtime) AS wk, " | |
| 2140 | + "count(*) AS n " | |
| 2141 | + "FROM event " | |
| 2142 | + "WHERE %Q=substr(date(mtime),1,4) " | |
| 2143 | + "AND mtime < current_timestamp ", | |
| 2144 | + zYear); | |
| 2145 | + if(zUserName&&*zUserName){ | |
| 2146 | + blob_appendf(&sql, " AND user=%Q ", zUserName); | |
| 2147 | + blob_appendf(&header," for user %h", zUserName); | |
| 2148 | + } | |
| 2149 | + blob_appendf(&sql, "GROUP BY wk ORDER BY wk DESC"); | |
| 2150 | + cgi_printf("<h1>%h</h1>", blob_str(&header)); | |
| 2151 | + blob_reset(&header); | |
| 2152 | + cgi_printf("<table class='statistics-report-table-events' " | |
| 2153 | + "border='0' cellpadding='2' width='100%%' " | |
| 2154 | + "cellspacing='0' id='statsTable'>"); | |
| 2155 | + cgi_printf("<thead><tr>" | |
| 2156 | + "<th>Week</th>" | |
| 2157 | + "<th>Events</th>" | |
| 2158 | + "<th width='90%%'><!-- relative commits graph --></th>" | |
| 2159 | + "</tr></thead>" | |
| 2160 | + "<tbody>"); | |
| 2161 | + db_prepare(&stWeek, blob_str(&sql)); | |
| 2162 | + blob_reset(&sql); | |
| 2163 | + while( SQLITE_ROW == db_step(&stWeek) ){ | |
| 2164 | + const int nCount = db_column_int(&stWeek, 1); | |
| 2165 | + if(nCount>nMaxEvents){ | |
| 2166 | + nMaxEvents = nCount; | |
| 2167 | + } | |
| 2168 | + } | |
| 2169 | + db_reset(&stWeek); | |
| 2170 | + while( SQLITE_ROW == db_step(&stWeek) ){ | |
| 2171 | + const char * zWeek = db_column_text(&stWeek,0); | |
| 2172 | + const int nCount = db_column_int(&stWeek,1); | |
| 2173 | + const int nSize = nCount | |
| 2174 | + ? (int)(100 * nCount / nMaxEvents) | |
| 2175 | + : 0; | |
| 2176 | + total += nCount; | |
| 2177 | + cgi_printf("<tr class='row%d'>", ++rowCount % 2 ); | |
| 2178 | + cgi_printf("<td><a href='%s/timeline?yw=%t-%s&n=%d", | |
| 2179 | + g.zTop, zYear, zWeek, nCount); | |
| 2180 | + if(zUserName && *zUserName){ | |
| 2181 | + cgi_printf("&u=%t",zUserName); | |
| 2182 | + } | |
| 2183 | + cgi_printf("'>%s</a></td>",zWeek); | |
| 2184 | + | |
| 2185 | + cgi_printf("<td>%d</td>",nCount); | |
| 2186 | + cgi_printf("<td>"); | |
| 2187 | + if(nCount){ | |
| 2188 | + cgi_printf("<div class='statistics-report-graph-line'" | |
| 2189 | + "style='height:16px;width:%d%%;'></div>", | |
| 2190 | + nSize); | |
| 2191 | + } | |
| 2192 | + cgi_printf("</td></tr>"); | |
| 2193 | + } | |
| 2194 | + db_finalize(&stWeek); | |
| 2195 | + free(zDefaultYear); | |
| 2196 | + cgi_printf("</tbody></table>"); | |
| 2197 | + if(total){ | |
| 2198 | + cgi_printf("<br><div>Total events: %d</div>", | |
| 2199 | + total); | |
| 2200 | + } | |
| 2201 | + output_table_sorting_javascript("statsTable","tnx"); | |
| 2202 | + } | |
| 2203 | +} | |
| 2204 | + | |
| 2019 | 2205 | /* |
| 2020 | 2206 | ** WEBPAGE: stats_report |
| 2021 | 2207 | ** |
| 2022 | 2208 | ** Shows activity reports for the repository. |
| 2023 | 2209 | ** |
| @@ -2026,37 +2212,40 @@ | ||
| 2026 | 2212 | ** view=REPORT_NAME Valid values: bymonth, byyear, byuser |
| 2027 | 2213 | ** user=NAME Restricts statistics to the given user |
| 2028 | 2214 | */ |
| 2029 | 2215 | void stats_report_page(){ |
| 2030 | 2216 | HQuery url; /* URL for various branch links */ |
| 2031 | - char const * zView = P("view"); /* Which view/report to show. */ | |
| 2032 | - char const *zUserName = P("user"); | |
| 2217 | + const char * zView = P("view"); /* Which view/report to show. */ | |
| 2218 | + const char *zUserName = P("user"); | |
| 2219 | + if(!zUserName) zUserName = P("u"); | |
| 2033 | 2220 | url_initialize(&url, "stats_report"); |
| 2034 | 2221 | |
| 2035 | 2222 | if(zUserName && *zUserName){ |
| 2036 | 2223 | url_add_parameter(&url,"user", zUserName); |
| 2037 | 2224 | timeline_submenu(&url, "(Remove User Flag)", "view", zView, "user"); |
| 2038 | 2225 | } |
| 2039 | 2226 | timeline_submenu(&url, "By Year", "view", "byyear", 0); |
| 2040 | 2227 | timeline_submenu(&url, "By Month", "view", "bymonth", 0); |
| 2228 | + timeline_submenu(&url, "By Week", "view", "byweek", 0); | |
| 2041 | 2229 | timeline_submenu(&url, "By User", "view", "byuser", "user"); |
| 2042 | 2230 | url_reset(&url); |
| 2043 | 2231 | style_header("Activity Reports"); |
| 2044 | 2232 | if(0==fossil_strcmp(zView,"byyear")){ |
| 2045 | - stats_report_by_month_year(0, zUserName); | |
| 2233 | + stats_report_by_month_year(0, 0, zUserName); | |
| 2046 | 2234 | }else if(0==fossil_strcmp(zView,"bymonth")){ |
| 2047 | - stats_report_by_month_year(1, zUserName); | |
| 2235 | + stats_report_by_month_year(1, 0, zUserName); | |
| 2048 | 2236 | }else if(0==fossil_strcmp(zView,"byweek")){ |
| 2049 | - @ TODO: by-week report. | |
| 2237 | + stats_report_year_weeks(zUserName); | |
| 2050 | 2238 | }else if(0==fossil_strcmp(zView,"byuser")){ |
| 2051 | 2239 | stats_report_by_user(); |
| 2052 | 2240 | }else{ |
| 2053 | 2241 | @ <h1>Select a report to show:</h1> |
| 2054 | 2242 | @ <ul> |
| 2055 | 2243 | @ <li><a href='?view=byyear'>Events by year</a></li> |
| 2056 | 2244 | @ <li><a href='?view=bymonth'>Events by month</a></li> |
| 2245 | + @ <li><a href='?view=byweek'>Events by calendar week</a></li> | |
| 2057 | 2246 | @ <li><a href='?view=byuser'>Events by user</a></li> |
| 2058 | 2247 | @ </ul> |
| 2059 | 2248 | } |
| 2060 | 2249 | |
| 2061 | 2250 | style_footer(); |
| 2062 | 2251 | } |
| 2063 | 2252 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -1032,10 +1032,11 @@ | |
| 1032 | const char *zTagName = P("t"); /* Show events with this tag */ |
| 1033 | const char *zBrName = P("r"); /* Show events related to this tag */ |
| 1034 | const char *zSearch = P("s"); /* Search string */ |
| 1035 | const char *zUses = P("uf"); /* Only show checkins hold this file */ |
| 1036 | const char *zYearMonth = P("ym"); /* Show checkins for the given YYYY-MM */ |
| 1037 | int useDividers = P("nd")==0; /* Show dividers if "nd" is missing */ |
| 1038 | int renameOnly = P("namechng")!=0; /* Show only checkins that rename files */ |
| 1039 | int tagid; /* Tag ID */ |
| 1040 | int tmFlags; /* Timeline flags */ |
| 1041 | const char *zThisTag = 0; /* Suppress links to this tag */ |
| @@ -1218,10 +1219,14 @@ | |
| 1218 | } |
| 1219 | if( zYearMonth ){ |
| 1220 | blob_appendf(&sql, " AND %Q=strftime('%%Y-%%m',event.mtime) ", |
| 1221 | zYearMonth); |
| 1222 | } |
| 1223 | if( tagid>0 ){ |
| 1224 | blob_appendf(&sql, |
| 1225 | "AND (EXISTS(SELECT 1 FROM tagxref" |
| 1226 | " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)", tagid); |
| 1227 | |
| @@ -1350,10 +1355,12 @@ | |
| 1350 | db_multi_exec("%s", blob_str(&sql)); |
| 1351 | |
| 1352 | n = db_int(0, "SELECT count(*) FROM timeline WHERE etype!='div' /*scan*/"); |
| 1353 | if( zYearMonth ){ |
| 1354 | blob_appendf(&desc, "%s events for %h", zEType, zYearMonth); |
| 1355 | }else if( zAfter==0 && zBefore==0 && zCirca==0 ){ |
| 1356 | blob_appendf(&desc, "%d most recent %ss", n, zEType); |
| 1357 | }else{ |
| 1358 | blob_appendf(&desc, "%d %ss", n, zEType); |
| 1359 | } |
| @@ -1829,36 +1836,64 @@ | |
| 1829 | } |
| 1830 | db_finalize(&q); |
| 1831 | style_footer(); |
| 1832 | } |
| 1833 | |
| 1834 | |
| 1835 | |
| 1836 | /* |
| 1837 | ** Implements the "byyear" and "bymonth" reports for /stats_report. |
| 1838 | ** If includeMonth is true then it generates the "bymonth" report, |
| 1839 | ** else the "byyear" report. If zUserName is not NULL and not empty |
| 1840 | ** then the report is restricted to events created by the named user |
| 1841 | ** account. |
| 1842 | */ |
| 1843 | static void stats_report_by_month_year(char includeMonth, |
| 1844 | char const * zUserName){ |
| 1845 | Stmt query = empty_Stmt; |
| 1846 | int const nPixelsPerEvent = 1; /* for sizing the "graph" part */ |
| 1847 | int nRowNumber = 0; /* current TR number */ |
| 1848 | int nEventTotal = 0; /* Total event count */ |
| 1849 | int rowClass = 0; /* counter for alternating |
| 1850 | row colors */ |
| 1851 | Blob sql = empty_blob; /* SQL */ |
| 1852 | char const * zTimeLabel = includeMonth ? "Year/Month" : "Year"; |
| 1853 | char zPrevYear[5] = {0}; /* For keeping track of when |
| 1854 | we change years while looping */ |
| 1855 | int nEventsPerYear = 0; /* Total even count for the |
| 1856 | current year */ |
| 1857 | char showYearTotal = 0; /* Flag telling us when to show |
| 1858 | the per-year event totals */ |
| 1859 | Blob header = empty_blob; /* Page header text */ |
| 1860 | |
| 1861 | blob_appendf(&header, "Timeline Events by year%s", |
| 1862 | (includeMonth ? "/month" : "")); |
| 1863 | blob_appendf(&sql, |
| 1864 | "SELECT substr(date(mtime),1,%d) AS timeframe, " |
| @@ -1879,18 +1914,31 @@ | |
| 1879 | @ <table class='statistics-report-table-events' border='0' cellpadding='2' |
| 1880 | @ cellspacing='0' id='statsTable'> |
| 1881 | @ <thead> |
| 1882 | @ <th>%s(zTimeLabel)</th> |
| 1883 | @ <th>Events</th> |
| 1884 | @ <th><!-- relative commits graph --></th> |
| 1885 | @ </thead><tbody> |
| 1886 | blob_reset(&header); |
| 1887 | while( SQLITE_ROW == db_step(&query) ){ |
| 1888 | char const * zTimeframe = db_column_text(&query, 0); |
| 1889 | int const nCount = db_column_int(&query, 1); |
| 1890 | int const nSize = 1 + ((nPixelsPerEvent * nCount) |
| 1891 | / (includeMonth ? 1 : 10)); |
| 1892 | showYearTotal = 0; |
| 1893 | if(includeMonth){ |
| 1894 | /* For Month/year view, add a separator for each distinct year. */ |
| 1895 | if(!*zPrevYear || |
| 1896 | (0!=fossil_strncmp(zPrevYear,zTimeframe,4))){ |
| @@ -1906,17 +1954,17 @@ | |
| 1906 | memcpy(zPrevYear,zTimeframe,4); |
| 1907 | rowClass = ++nRowNumber % 2; |
| 1908 | @ <tr class='row%d(rowClass)'> |
| 1909 | @ <th colspan='3' class='statistics-report-row-year'>%s(zPrevYear)</th> |
| 1910 | @ </tr> |
| 1911 | } |
| 1912 | } |
| 1913 | rowClass = ++nRowNumber % 2; |
| 1914 | nEventTotal += nCount; |
| 1915 | nEventsPerYear += nCount; |
| 1916 | @<tr class='row%d(rowClass)'> |
| 1917 | @ <td> |
| 1918 | if(includeMonth){ |
| 1919 | cgi_printf("<a href='%s/timeline?" |
| 1920 | "ym=%t&n=%d", |
| 1921 | g.zTop, zTimeframe, nCount ); |
| 1922 | /* Reminder: n=nCount is not actually correct for bymonth unless |
| @@ -1925,41 +1973,51 @@ | |
| 1925 | if( zUserName && *zUserName ){ |
| 1926 | cgi_printf("&u=%t", zUserName); |
| 1927 | } |
| 1928 | cgi_printf("' target='_new'>%s</a>",zTimeframe); |
| 1929 | }else { |
| 1930 | @ %s(zTimeframe) |
| 1931 | } |
| 1932 | @ </td><td>%d(nCount)</td> |
| 1933 | @ <td> |
| 1934 | @ <div class='statistics-report-graph-line' |
| 1935 | @ style='height:16px;width:%d(nSize)px;'> |
| 1936 | @ </div></td> |
| 1937 | @</tr> |
| 1938 | |
| 1939 | /* |
| 1940 | Potential improvement: calculate the min/max event counts and |
| 1941 | use percent-based graph bars. |
| 1942 | */ |
| 1943 | } |
| 1944 | |
| 1945 | if(includeMonth && !showYearTotal && *zPrevYear){ |
| 1946 | /* Add final year total separator. */ |
| 1947 | rowClass = ++nRowNumber % 2; |
| 1948 | @ <tr class='row%d(rowClass)'> |
| 1949 | @ <td></td> |
| 1950 | @ <td colspan='2'>Yearly total: %d(nEventsPerYear)</td> |
| 1951 | @</tr> |
| 1952 | } |
| 1953 | #if 0 |
| 1954 | rowClass = ++nRowNumber % 2; |
| 1955 | @ <tr class='row%d(rowClass)'> |
| 1956 | @ <td colspan='3'>Total events: %d(nEventTotal)</td> |
| 1957 | @ </tr> |
| 1958 | #endif |
| 1959 | @ </tbody></table> |
| 1960 | db_finalize(&query); |
| 1961 | if( !includeMonth ){ |
| 1962 | output_table_sorting_javascript("statsTable","tnx"); |
| 1963 | } |
| 1964 | } |
| 1965 | |
| @@ -1966,16 +2024,17 @@ | |
| 1966 | /* |
| 1967 | ** Implements the "byuser" view for /stats_report. |
| 1968 | */ |
| 1969 | static void stats_report_by_user(){ |
| 1970 | Stmt query = empty_Stmt; |
| 1971 | int const nPixelsPerEvent = 1; /* for sizing the "graph" part */ |
| 1972 | int nRowNumber = 0; /* current TR number */ |
| 1973 | int nEventTotal = 0; /* Total event count */ |
| 1974 | int rowClass = 0; /* counter for alternating |
| 1975 | row colors */ |
| 1976 | Blob sql = empty_blob; /* SQL */ |
| 1977 | blob_append(&sql, |
| 1978 | "SELECT user, " |
| 1979 | "COUNT(*) AS eventCount " |
| 1980 | "FROM event " |
| 1981 | "GROUP BY user ORDER BY eventCount DESC", |
| @@ -1986,26 +2045,35 @@ | |
| 1986 | @ <table class='statistics-report-table-events' border='0' |
| 1987 | @ cellpadding='2' cellspacing='0' id='statsTable'> |
| 1988 | @ <thead><tr> |
| 1989 | @ <th>User</th> |
| 1990 | @ <th>Events</th> |
| 1991 | @ <th><!-- relative commits graph --></th> |
| 1992 | @ </tr></thead><tbody> |
| 1993 | while( SQLITE_ROW == db_step(&query) ){ |
| 1994 | char const * zUser = db_column_text(&query, 0); |
| 1995 | int const nCount = db_column_int(&query, 1); |
| 1996 | int const nSize = 1+((nPixelsPerEvent * nCount) / 10); |
| 1997 | if(!nCount) continue /* arguable! */; |
| 1998 | rowClass = ++nRowNumber % 2; |
| 1999 | nEventTotal += nCount; |
| 2000 | @<tr class='row%d(rowClass)'> |
| 2001 | @ <td> |
| 2002 | @ <a href="?view=bymonth&user=%h(zUser)" target="_new">%h(zUser)</a> |
| 2003 | @ </td><td>%d(nCount)</td> |
| 2004 | @ <td> |
| 2005 | @ <div class='statistics-report-graph-line' |
| 2006 | @ style='height:16px;width:%d(nSize)px;'> |
| 2007 | @ </div></td> |
| 2008 | @</tr> |
| 2009 | /* |
| 2010 | Potential improvement: calculate the min/max event counts and |
| 2011 | use percent-based graph bars. |
| @@ -2014,10 +2082,128 @@ | |
| 2014 | @ </tbody></table> |
| 2015 | db_finalize(&query); |
| 2016 | output_table_sorting_javascript("statsTable","tnx"); |
| 2017 | } |
| 2018 | |
| 2019 | /* |
| 2020 | ** WEBPAGE: stats_report |
| 2021 | ** |
| 2022 | ** Shows activity reports for the repository. |
| 2023 | ** |
| @@ -2026,37 +2212,40 @@ | |
| 2026 | ** view=REPORT_NAME Valid values: bymonth, byyear, byuser |
| 2027 | ** user=NAME Restricts statistics to the given user |
| 2028 | */ |
| 2029 | void stats_report_page(){ |
| 2030 | HQuery url; /* URL for various branch links */ |
| 2031 | char const * zView = P("view"); /* Which view/report to show. */ |
| 2032 | char const *zUserName = P("user"); |
| 2033 | url_initialize(&url, "stats_report"); |
| 2034 | |
| 2035 | if(zUserName && *zUserName){ |
| 2036 | url_add_parameter(&url,"user", zUserName); |
| 2037 | timeline_submenu(&url, "(Remove User Flag)", "view", zView, "user"); |
| 2038 | } |
| 2039 | timeline_submenu(&url, "By Year", "view", "byyear", 0); |
| 2040 | timeline_submenu(&url, "By Month", "view", "bymonth", 0); |
| 2041 | timeline_submenu(&url, "By User", "view", "byuser", "user"); |
| 2042 | url_reset(&url); |
| 2043 | style_header("Activity Reports"); |
| 2044 | if(0==fossil_strcmp(zView,"byyear")){ |
| 2045 | stats_report_by_month_year(0, zUserName); |
| 2046 | }else if(0==fossil_strcmp(zView,"bymonth")){ |
| 2047 | stats_report_by_month_year(1, zUserName); |
| 2048 | }else if(0==fossil_strcmp(zView,"byweek")){ |
| 2049 | @ TODO: by-week report. |
| 2050 | }else if(0==fossil_strcmp(zView,"byuser")){ |
| 2051 | stats_report_by_user(); |
| 2052 | }else{ |
| 2053 | @ <h1>Select a report to show:</h1> |
| 2054 | @ <ul> |
| 2055 | @ <li><a href='?view=byyear'>Events by year</a></li> |
| 2056 | @ <li><a href='?view=bymonth'>Events by month</a></li> |
| 2057 | @ <li><a href='?view=byuser'>Events by user</a></li> |
| 2058 | @ </ul> |
| 2059 | } |
| 2060 | |
| 2061 | style_footer(); |
| 2062 | } |
| 2063 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -1032,10 +1032,11 @@ | |
| 1032 | const char *zTagName = P("t"); /* Show events with this tag */ |
| 1033 | const char *zBrName = P("r"); /* Show events related to this tag */ |
| 1034 | const char *zSearch = P("s"); /* Search string */ |
| 1035 | const char *zUses = P("uf"); /* Only show checkins hold this file */ |
| 1036 | const char *zYearMonth = P("ym"); /* Show checkins for the given YYYY-MM */ |
| 1037 | const char *zYearWeek = P("yw"); /* Show checkins for the given YYYY-WW (weak-of-year) */ |
| 1038 | int useDividers = P("nd")==0; /* Show dividers if "nd" is missing */ |
| 1039 | int renameOnly = P("namechng")!=0; /* Show only checkins that rename files */ |
| 1040 | int tagid; /* Tag ID */ |
| 1041 | int tmFlags; /* Timeline flags */ |
| 1042 | const char *zThisTag = 0; /* Suppress links to this tag */ |
| @@ -1218,10 +1219,14 @@ | |
| 1219 | } |
| 1220 | if( zYearMonth ){ |
| 1221 | blob_appendf(&sql, " AND %Q=strftime('%%Y-%%m',event.mtime) ", |
| 1222 | zYearMonth); |
| 1223 | } |
| 1224 | else if( zYearWeek ){ |
| 1225 | blob_appendf(&sql, " AND %Q=strftime('%%Y-%%W',event.mtime) ", |
| 1226 | zYearWeek); |
| 1227 | } |
| 1228 | if( tagid>0 ){ |
| 1229 | blob_appendf(&sql, |
| 1230 | "AND (EXISTS(SELECT 1 FROM tagxref" |
| 1231 | " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)", tagid); |
| 1232 | |
| @@ -1350,10 +1355,12 @@ | |
| 1355 | db_multi_exec("%s", blob_str(&sql)); |
| 1356 | |
| 1357 | n = db_int(0, "SELECT count(*) FROM timeline WHERE etype!='div' /*scan*/"); |
| 1358 | if( zYearMonth ){ |
| 1359 | blob_appendf(&desc, "%s events for %h", zEType, zYearMonth); |
| 1360 | }else if( zYearWeek ){ |
| 1361 | blob_appendf(&desc, "%s events for year/week %h", zEType, zYearWeek); |
| 1362 | }else if( zAfter==0 && zBefore==0 && zCirca==0 ){ |
| 1363 | blob_appendf(&desc, "%d most recent %ss", n, zEType); |
| 1364 | }else{ |
| 1365 | blob_appendf(&desc, "%d %ss", n, zEType); |
| 1366 | } |
| @@ -1829,36 +1836,64 @@ | |
| 1836 | } |
| 1837 | db_finalize(&q); |
| 1838 | style_footer(); |
| 1839 | } |
| 1840 | |
| 1841 | /* |
| 1842 | ** Helper for stats_report_by_month_year(), which generates a list of |
| 1843 | ** week numbers. zTimeframe should be either a timeframe in the form YYYY |
| 1844 | ** or YYYY-MM. |
| 1845 | */ |
| 1846 | static void stats_report_output_week_links(const char * zTimeframe){ |
| 1847 | Stmt stWeek = empty_Stmt; |
| 1848 | char yearPart[5] = {0,0,0,0,0}; |
| 1849 | memcpy(yearPart, zTimeframe, 4); |
| 1850 | db_prepare(&stWeek, |
| 1851 | "SELECT DISTINCT strftime('%%W',mtime) AS wk, " |
| 1852 | "count(*) AS n, " |
| 1853 | "substr(date(mtime),1,%d) AS ym " |
| 1854 | "FROM event " |
| 1855 | "WHERE ym=%Q AND mtime < current_timestamp " |
| 1856 | "GROUP BY wk ORDER BY wk", |
| 1857 | strlen(zTimeframe), |
| 1858 | zTimeframe); |
| 1859 | while( SQLITE_ROW == db_step(&stWeek) ){ |
| 1860 | const char * zWeek = db_column_text(&stWeek,0); |
| 1861 | const int nCount = db_column_int(&stWeek,1); |
| 1862 | cgi_printf("<a href='%s/timeline?" |
| 1863 | "yw=%t-%t&n=%d'>%s</a>", |
| 1864 | g.zTop, yearPart, zWeek, |
| 1865 | nCount, zWeek); |
| 1866 | } |
| 1867 | db_finalize(&stWeek); |
| 1868 | } |
| 1869 | |
| 1870 | /* |
| 1871 | ** Implements the "byyear" and "bymonth" reports for /stats_report. |
| 1872 | ** If includeMonth is true then it generates the "bymonth" report, |
| 1873 | ** else the "byyear" report. If zUserName is not NULL and not empty |
| 1874 | ** then the report is restricted to events created by the named user |
| 1875 | ** account. |
| 1876 | */ |
| 1877 | static void stats_report_by_month_year(char includeMonth, |
| 1878 | char includeWeeks, |
| 1879 | const char * zUserName){ |
| 1880 | Stmt query = empty_Stmt; |
| 1881 | int nRowNumber = 0; /* current TR number */ |
| 1882 | int nEventTotal = 0; /* Total event count */ |
| 1883 | int rowClass = 0; /* counter for alternating |
| 1884 | row colors */ |
| 1885 | Blob sql = empty_blob; /* SQL */ |
| 1886 | const char * zTimeLabel = includeMonth ? "Year/Month" : "Year"; |
| 1887 | char zPrevYear[5] = {0}; /* For keeping track of when |
| 1888 | we change years while looping */ |
| 1889 | int nEventsPerYear = 0; /* Total event count for the |
| 1890 | current year */ |
| 1891 | char showYearTotal = 0; /* Flag telling us when to show |
| 1892 | the per-year event totals */ |
| 1893 | Blob header = empty_blob; /* Page header text */ |
| 1894 | int nMaxEvents = 1; /* for calculating length of graph bars. */ |
| 1895 | |
| 1896 | blob_appendf(&header, "Timeline Events by year%s", |
| 1897 | (includeMonth ? "/month" : "")); |
| 1898 | blob_appendf(&sql, |
| 1899 | "SELECT substr(date(mtime),1,%d) AS timeframe, " |
| @@ -1879,18 +1914,31 @@ | |
| 1914 | @ <table class='statistics-report-table-events' border='0' cellpadding='2' |
| 1915 | @ cellspacing='0' id='statsTable'> |
| 1916 | @ <thead> |
| 1917 | @ <th>%s(zTimeLabel)</th> |
| 1918 | @ <th>Events</th> |
| 1919 | @ <th width='90%%'><!-- relative commits graph --></th> |
| 1920 | @ </thead><tbody> |
| 1921 | blob_reset(&header); |
| 1922 | /* |
| 1923 | Run the query twice. The first time we calculate the maximum |
| 1924 | number of events for a given row. Maybe someone with better SQL |
| 1925 | Fu can re-implement this with a single query. |
| 1926 | */ |
| 1927 | while( SQLITE_ROW == db_step(&query) ){ |
| 1928 | const int nCount = db_column_int(&query, 1); |
| 1929 | if(nCount>nMaxEvents){ |
| 1930 | nMaxEvents = nCount; |
| 1931 | } |
| 1932 | } |
| 1933 | db_reset(&query); |
| 1934 | while( SQLITE_ROW == db_step(&query) ){ |
| 1935 | const char * zTimeframe = db_column_text(&query, 0); |
| 1936 | const int nCount = db_column_int(&query, 1); |
| 1937 | const int nSize = nCount |
| 1938 | ? (int)(100 * nCount / nMaxEvents) |
| 1939 | : 1; |
| 1940 | showYearTotal = 0; |
| 1941 | if(includeMonth){ |
| 1942 | /* For Month/year view, add a separator for each distinct year. */ |
| 1943 | if(!*zPrevYear || |
| 1944 | (0!=fossil_strncmp(zPrevYear,zTimeframe,4))){ |
| @@ -1906,17 +1954,17 @@ | |
| 1954 | memcpy(zPrevYear,zTimeframe,4); |
| 1955 | rowClass = ++nRowNumber % 2; |
| 1956 | @ <tr class='row%d(rowClass)'> |
| 1957 | @ <th colspan='3' class='statistics-report-row-year'>%s(zPrevYear)</th> |
| 1958 | @ </tr> |
| 1959 | } |
| 1960 | } |
| 1961 | rowClass = ++nRowNumber % 2; |
| 1962 | nEventTotal += nCount; |
| 1963 | nEventsPerYear += nCount; |
| 1964 | @<tr class='row%d(rowClass)'> |
| 1965 | @ <td> |
| 1966 | if(includeMonth){ |
| 1967 | cgi_printf("<a href='%s/timeline?" |
| 1968 | "ym=%t&n=%d", |
| 1969 | g.zTop, zTimeframe, nCount ); |
| 1970 | /* Reminder: n=nCount is not actually correct for bymonth unless |
| @@ -1925,41 +1973,51 @@ | |
| 1973 | if( zUserName && *zUserName ){ |
| 1974 | cgi_printf("&u=%t", zUserName); |
| 1975 | } |
| 1976 | cgi_printf("' target='_new'>%s</a>",zTimeframe); |
| 1977 | }else { |
| 1978 | cgi_printf("<a href='?view=byweek&y=%s", zTimeframe); |
| 1979 | if(zUserName && *zUserName){ |
| 1980 | cgi_printf("&u=%t", zUserName); |
| 1981 | } |
| 1982 | cgi_printf("'>%s</a>", zTimeframe); |
| 1983 | } |
| 1984 | @ </td><td>%d(nCount)</td> |
| 1985 | @ <td> |
| 1986 | @ <div class='statistics-report-graph-line' |
| 1987 | @ style='height:16px;width:%d(nSize)%%;'> |
| 1988 | @ </div></td> |
| 1989 | @</tr> |
| 1990 | if(includeWeeks){ |
| 1991 | /* This part works fine for months but it terribly slow (4.5s on my PC), |
| 1992 | so it's only shown for by-year for now. Suggestions/patches for |
| 1993 | a better/faster layout are welcomed. */ |
| 1994 | @ <tr class='row%d(rowClass)'> |
| 1995 | @ <td colspan='2' class='statistics-report-week-number-label'>Week #:</td> |
| 1996 | @ <td class='statistics-report-week-of-year-list'> |
| 1997 | stats_report_output_week_links(zTimeframe); |
| 1998 | @ </td></tr> |
| 1999 | } |
| 2000 | |
| 2001 | /* |
| 2002 | Potential improvement: calculate the min/max event counts and |
| 2003 | use percent-based graph bars. |
| 2004 | */ |
| 2005 | } |
| 2006 | db_finalize(&query); |
| 2007 | if(includeMonth && !showYearTotal && *zPrevYear){ |
| 2008 | /* Add final year total separator. */ |
| 2009 | rowClass = ++nRowNumber % 2; |
| 2010 | @ <tr class='row%d(rowClass)'> |
| 2011 | @ <td></td> |
| 2012 | @ <td colspan='2'>Yearly total: %d(nEventsPerYear)</td> |
| 2013 | @</tr> |
| 2014 | } |
| 2015 | @ </tbody></table> |
| 2016 | if(nEventTotal){ |
| 2017 | @ <br><div>Total events: %d(nEventTotal)</div> |
| 2018 | } |
| 2019 | if( !includeMonth ){ |
| 2020 | output_table_sorting_javascript("statsTable","tnx"); |
| 2021 | } |
| 2022 | } |
| 2023 | |
| @@ -1966,16 +2024,17 @@ | |
| 2024 | /* |
| 2025 | ** Implements the "byuser" view for /stats_report. |
| 2026 | */ |
| 2027 | static void stats_report_by_user(){ |
| 2028 | Stmt query = empty_Stmt; |
| 2029 | int nRowNumber = 0; /* current TR number */ |
| 2030 | int nEventTotal = 0; /* Total event count */ |
| 2031 | int rowClass = 0; /* counter for alternating |
| 2032 | row colors */ |
| 2033 | Blob sql = empty_blob; /* SQL */ |
| 2034 | int nMaxEvents = 1; /* max number of events for |
| 2035 | all rows. */ |
| 2036 | blob_append(&sql, |
| 2037 | "SELECT user, " |
| 2038 | "COUNT(*) AS eventCount " |
| 2039 | "FROM event " |
| 2040 | "GROUP BY user ORDER BY eventCount DESC", |
| @@ -1986,26 +2045,35 @@ | |
| 2045 | @ <table class='statistics-report-table-events' border='0' |
| 2046 | @ cellpadding='2' cellspacing='0' id='statsTable'> |
| 2047 | @ <thead><tr> |
| 2048 | @ <th>User</th> |
| 2049 | @ <th>Events</th> |
| 2050 | @ <th width='90%%'><!-- relative commits graph --></th> |
| 2051 | @ </tr></thead><tbody> |
| 2052 | while( SQLITE_ROW == db_step(&query) ){ |
| 2053 | const int nCount = db_column_int(&query, 1); |
| 2054 | if(nCount>nMaxEvents){ |
| 2055 | nMaxEvents = nCount; |
| 2056 | } |
| 2057 | } |
| 2058 | db_reset(&query); |
| 2059 | while( SQLITE_ROW == db_step(&query) ){ |
| 2060 | const char * zUser = db_column_text(&query, 0); |
| 2061 | const int nCount = db_column_int(&query, 1); |
| 2062 | const int nSize = nCount |
| 2063 | ? (int)(100 * nCount / nMaxEvents) |
| 2064 | : 0; |
| 2065 | if(!nCount) continue /* arguable! Possible? */; |
| 2066 | rowClass = ++nRowNumber % 2; |
| 2067 | nEventTotal += nCount; |
| 2068 | @<tr class='row%d(rowClass)'> |
| 2069 | @ <td> |
| 2070 | @ <a href="?view=bymonth&user=%h(zUser)" target="_new">%h(zUser)</a> |
| 2071 | @ </td><td>%d(nCount)</td> |
| 2072 | @ <td> |
| 2073 | @ <div class='statistics-report-graph-line' |
| 2074 | @ style='height:16px;width:%d(nSize)%%;'> |
| 2075 | @ </div></td> |
| 2076 | @</tr> |
| 2077 | /* |
| 2078 | Potential improvement: calculate the min/max event counts and |
| 2079 | use percent-based graph bars. |
| @@ -2014,10 +2082,128 @@ | |
| 2082 | @ </tbody></table> |
| 2083 | db_finalize(&query); |
| 2084 | output_table_sorting_javascript("statsTable","tnx"); |
| 2085 | } |
| 2086 | |
| 2087 | |
| 2088 | /* |
| 2089 | ** Helper for stats_report_by_month_year(), which generates a list of |
| 2090 | ** week numbers. zTimeframe should be either a timeframe in the form YYYY |
| 2091 | ** or YYYY-MM. |
| 2092 | */ |
| 2093 | static void stats_report_year_weeks(const char * zUserName){ |
| 2094 | const char * zYear = P("y"); |
| 2095 | int nYear = zYear ? strlen(zYear) : 0; |
| 2096 | int i = 0; |
| 2097 | Stmt qYears = empty_Stmt; |
| 2098 | char * zDefaultYear = NULL; |
| 2099 | Blob sql = empty_blob; |
| 2100 | int nMaxEvents = 1; /* max number of events for |
| 2101 | all rows. */ |
| 2102 | |
| 2103 | cgi_printf("Select year: "); |
| 2104 | blob_append(&sql, |
| 2105 | "SELECT DISTINCT substr(date(mtime),1,4) AS y " |
| 2106 | "FROM event WHERE 1 ", -1); |
| 2107 | if(zUserName&&*zUserName){ |
| 2108 | blob_appendf(&sql,"AND user=%Q ", zUserName); |
| 2109 | } |
| 2110 | blob_append(&sql,"GROUP BY y ORDER BY y", -1); |
| 2111 | db_prepare(&qYears, blob_str(&sql)); |
| 2112 | blob_reset(&sql); |
| 2113 | while( SQLITE_ROW == db_step(&qYears) ){ |
| 2114 | const char * zT = db_column_text(&qYears, 0); |
| 2115 | if( i++ ){ |
| 2116 | cgi_printf(" "); |
| 2117 | } |
| 2118 | cgi_printf("<a href='?view=byweek&y=%s", zT); |
| 2119 | if(zUserName && *zUserName){ |
| 2120 | cgi_printf("&user=%t",zUserName); |
| 2121 | } |
| 2122 | cgi_printf("'>%s</a>",zT); |
| 2123 | } |
| 2124 | db_finalize(&qYears); |
| 2125 | cgi_printf("<br/>"); |
| 2126 | if(!zYear || !*zYear){ |
| 2127 | zDefaultYear = db_text("????", "SELECT strftime('%%Y')"); |
| 2128 | zYear = zDefaultYear; |
| 2129 | nYear = 4; |
| 2130 | } |
| 2131 | if(4 == nYear){ |
| 2132 | Stmt stWeek = empty_Stmt; |
| 2133 | int rowCount = 0; |
| 2134 | int total = 0; |
| 2135 | Blob header = empty_blob; |
| 2136 | blob_appendf(&header, "Timeline events for the calendar weeks " |
| 2137 | "of %h", zYear); |
| 2138 | blob_appendf(&sql, |
| 2139 | "SELECT DISTINCT strftime('%%%%W',mtime) AS wk, " |
| 2140 | "count(*) AS n " |
| 2141 | "FROM event " |
| 2142 | "WHERE %Q=substr(date(mtime),1,4) " |
| 2143 | "AND mtime < current_timestamp ", |
| 2144 | zYear); |
| 2145 | if(zUserName&&*zUserName){ |
| 2146 | blob_appendf(&sql, " AND user=%Q ", zUserName); |
| 2147 | blob_appendf(&header," for user %h", zUserName); |
| 2148 | } |
| 2149 | blob_appendf(&sql, "GROUP BY wk ORDER BY wk DESC"); |
| 2150 | cgi_printf("<h1>%h</h1>", blob_str(&header)); |
| 2151 | blob_reset(&header); |
| 2152 | cgi_printf("<table class='statistics-report-table-events' " |
| 2153 | "border='0' cellpadding='2' width='100%%' " |
| 2154 | "cellspacing='0' id='statsTable'>"); |
| 2155 | cgi_printf("<thead><tr>" |
| 2156 | "<th>Week</th>" |
| 2157 | "<th>Events</th>" |
| 2158 | "<th width='90%%'><!-- relative commits graph --></th>" |
| 2159 | "</tr></thead>" |
| 2160 | "<tbody>"); |
| 2161 | db_prepare(&stWeek, blob_str(&sql)); |
| 2162 | blob_reset(&sql); |
| 2163 | while( SQLITE_ROW == db_step(&stWeek) ){ |
| 2164 | const int nCount = db_column_int(&stWeek, 1); |
| 2165 | if(nCount>nMaxEvents){ |
| 2166 | nMaxEvents = nCount; |
| 2167 | } |
| 2168 | } |
| 2169 | db_reset(&stWeek); |
| 2170 | while( SQLITE_ROW == db_step(&stWeek) ){ |
| 2171 | const char * zWeek = db_column_text(&stWeek,0); |
| 2172 | const int nCount = db_column_int(&stWeek,1); |
| 2173 | const int nSize = nCount |
| 2174 | ? (int)(100 * nCount / nMaxEvents) |
| 2175 | : 0; |
| 2176 | total += nCount; |
| 2177 | cgi_printf("<tr class='row%d'>", ++rowCount % 2 ); |
| 2178 | cgi_printf("<td><a href='%s/timeline?yw=%t-%s&n=%d", |
| 2179 | g.zTop, zYear, zWeek, nCount); |
| 2180 | if(zUserName && *zUserName){ |
| 2181 | cgi_printf("&u=%t",zUserName); |
| 2182 | } |
| 2183 | cgi_printf("'>%s</a></td>",zWeek); |
| 2184 | |
| 2185 | cgi_printf("<td>%d</td>",nCount); |
| 2186 | cgi_printf("<td>"); |
| 2187 | if(nCount){ |
| 2188 | cgi_printf("<div class='statistics-report-graph-line'" |
| 2189 | "style='height:16px;width:%d%%;'></div>", |
| 2190 | nSize); |
| 2191 | } |
| 2192 | cgi_printf("</td></tr>"); |
| 2193 | } |
| 2194 | db_finalize(&stWeek); |
| 2195 | free(zDefaultYear); |
| 2196 | cgi_printf("</tbody></table>"); |
| 2197 | if(total){ |
| 2198 | cgi_printf("<br><div>Total events: %d</div>", |
| 2199 | total); |
| 2200 | } |
| 2201 | output_table_sorting_javascript("statsTable","tnx"); |
| 2202 | } |
| 2203 | } |
| 2204 | |
| 2205 | /* |
| 2206 | ** WEBPAGE: stats_report |
| 2207 | ** |
| 2208 | ** Shows activity reports for the repository. |
| 2209 | ** |
| @@ -2026,37 +2212,40 @@ | |
| 2212 | ** view=REPORT_NAME Valid values: bymonth, byyear, byuser |
| 2213 | ** user=NAME Restricts statistics to the given user |
| 2214 | */ |
| 2215 | void stats_report_page(){ |
| 2216 | HQuery url; /* URL for various branch links */ |
| 2217 | const char * zView = P("view"); /* Which view/report to show. */ |
| 2218 | const char *zUserName = P("user"); |
| 2219 | if(!zUserName) zUserName = P("u"); |
| 2220 | url_initialize(&url, "stats_report"); |
| 2221 | |
| 2222 | if(zUserName && *zUserName){ |
| 2223 | url_add_parameter(&url,"user", zUserName); |
| 2224 | timeline_submenu(&url, "(Remove User Flag)", "view", zView, "user"); |
| 2225 | } |
| 2226 | timeline_submenu(&url, "By Year", "view", "byyear", 0); |
| 2227 | timeline_submenu(&url, "By Month", "view", "bymonth", 0); |
| 2228 | timeline_submenu(&url, "By Week", "view", "byweek", 0); |
| 2229 | timeline_submenu(&url, "By User", "view", "byuser", "user"); |
| 2230 | url_reset(&url); |
| 2231 | style_header("Activity Reports"); |
| 2232 | if(0==fossil_strcmp(zView,"byyear")){ |
| 2233 | stats_report_by_month_year(0, 0, zUserName); |
| 2234 | }else if(0==fossil_strcmp(zView,"bymonth")){ |
| 2235 | stats_report_by_month_year(1, 0, zUserName); |
| 2236 | }else if(0==fossil_strcmp(zView,"byweek")){ |
| 2237 | stats_report_year_weeks(zUserName); |
| 2238 | }else if(0==fossil_strcmp(zView,"byuser")){ |
| 2239 | stats_report_by_user(); |
| 2240 | }else{ |
| 2241 | @ <h1>Select a report to show:</h1> |
| 2242 | @ <ul> |
| 2243 | @ <li><a href='?view=byyear'>Events by year</a></li> |
| 2244 | @ <li><a href='?view=bymonth'>Events by month</a></li> |
| 2245 | @ <li><a href='?view=byweek'>Events by calendar week</a></li> |
| 2246 | @ <li><a href='?view=byuser'>Events by user</a></li> |
| 2247 | @ </ul> |
| 2248 | } |
| 2249 | |
| 2250 | style_footer(); |
| 2251 | } |
| 2252 |
+15
| --- src/translate.c | ||
| +++ src/translate.c | ||
| @@ -30,10 +30,25 @@ | ||
| 30 | 30 | ** |
| 31 | 31 | ** This tool allows us to put raw HTML, without the special codes, in |
| 32 | 32 | ** the middle of a C program. This program then translates the text |
| 33 | 33 | ** into standard C by inserting all necessary backslashes and other |
| 34 | 34 | ** punctuation. |
| 35 | +** | |
| 36 | +** Enhancement #1: | |
| 37 | +** | |
| 38 | +** If the last non-whitespace character prior to the first "@" of a | |
| 39 | +** @-block is "=" or "," then the @-block is a string literal initializer | |
| 40 | +** rather than text that is to be output via cgi_printf(). Render it | |
| 41 | +** as such. | |
| 42 | +** | |
| 43 | +** Enhancement #2: | |
| 44 | +** | |
| 45 | +** Comments of the form: "/* @-comment: CC" cause CC to become a | |
| 46 | +** comment character for the @-substitution. Typical values for CC are | |
| 47 | +** "--" (for SQL text) or "#" (for TCL script) or "//" (for C++ code). | |
| 48 | +** Lines of subsequent @-blocks that begin with CC are omitted from the | |
| 49 | +** output. | |
| 35 | 50 | ** |
| 36 | 51 | */ |
| 37 | 52 | #include <stdio.h> |
| 38 | 53 | #include <ctype.h> |
| 39 | 54 | #include <stdlib.h> |
| 40 | 55 |
| --- src/translate.c | |
| +++ src/translate.c | |
| @@ -30,10 +30,25 @@ | |
| 30 | ** |
| 31 | ** This tool allows us to put raw HTML, without the special codes, in |
| 32 | ** the middle of a C program. This program then translates the text |
| 33 | ** into standard C by inserting all necessary backslashes and other |
| 34 | ** punctuation. |
| 35 | ** |
| 36 | */ |
| 37 | #include <stdio.h> |
| 38 | #include <ctype.h> |
| 39 | #include <stdlib.h> |
| 40 |
| --- src/translate.c | |
| +++ src/translate.c | |
| @@ -30,10 +30,25 @@ | |
| 30 | ** |
| 31 | ** This tool allows us to put raw HTML, without the special codes, in |
| 32 | ** the middle of a C program. This program then translates the text |
| 33 | ** into standard C by inserting all necessary backslashes and other |
| 34 | ** punctuation. |
| 35 | ** |
| 36 | ** Enhancement #1: |
| 37 | ** |
| 38 | ** If the last non-whitespace character prior to the first "@" of a |
| 39 | ** @-block is "=" or "," then the @-block is a string literal initializer |
| 40 | ** rather than text that is to be output via cgi_printf(). Render it |
| 41 | ** as such. |
| 42 | ** |
| 43 | ** Enhancement #2: |
| 44 | ** |
| 45 | ** Comments of the form: "/* @-comment: CC" cause CC to become a |
| 46 | ** comment character for the @-substitution. Typical values for CC are |
| 47 | ** "--" (for SQL text) or "#" (for TCL script) or "//" (for C++ code). |
| 48 | ** Lines of subsequent @-blocks that begin with CC are omitted from the |
| 49 | ** output. |
| 50 | ** |
| 51 | */ |
| 52 | #include <stdio.h> |
| 53 | #include <ctype.h> |
| 54 | #include <stdlib.h> |
| 55 |
+2
-2
| --- src/wiki.c | ||
| +++ src/wiki.c | ||
| @@ -786,13 +786,13 @@ | ||
| 786 | 786 | blob_init(&w2, pW2->zWiki, -1); |
| 787 | 787 | } |
| 788 | 788 | blob_zero(&d); |
| 789 | 789 | diffFlags = construct_diff_flags(1,0); |
| 790 | 790 | text_diff(&w2, &w1, &d, 0, diffFlags | DIFF_HTML | DIFF_LINENO); |
| 791 | - @ <div class="udiff"> | |
| 791 | + @ <pre class="udiff"> | |
| 792 | 792 | @ %s(blob_str(&d)) |
| 793 | - @ </div> | |
| 793 | + @ <pre> | |
| 794 | 794 | manifest_destroy(pW1); |
| 795 | 795 | manifest_destroy(pW2); |
| 796 | 796 | style_footer(); |
| 797 | 797 | } |
| 798 | 798 | |
| 799 | 799 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -786,13 +786,13 @@ | |
| 786 | blob_init(&w2, pW2->zWiki, -1); |
| 787 | } |
| 788 | blob_zero(&d); |
| 789 | diffFlags = construct_diff_flags(1,0); |
| 790 | text_diff(&w2, &w1, &d, 0, diffFlags | DIFF_HTML | DIFF_LINENO); |
| 791 | @ <div class="udiff"> |
| 792 | @ %s(blob_str(&d)) |
| 793 | @ </div> |
| 794 | manifest_destroy(pW1); |
| 795 | manifest_destroy(pW2); |
| 796 | style_footer(); |
| 797 | } |
| 798 | |
| 799 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -786,13 +786,13 @@ | |
| 786 | blob_init(&w2, pW2->zWiki, -1); |
| 787 | } |
| 788 | blob_zero(&d); |
| 789 | diffFlags = construct_diff_flags(1,0); |
| 790 | text_diff(&w2, &w1, &d, 0, diffFlags | DIFF_HTML | DIFF_LINENO); |
| 791 | @ <pre class="udiff"> |
| 792 | @ %s(blob_str(&d)) |
| 793 | @ <pre> |
| 794 | manifest_destroy(pW1); |
| 795 | manifest_destroy(pW2); |
| 796 | style_footer(); |
| 797 | } |
| 798 | |
| 799 |
+3
-3
| --- test/diff-test-1.wiki | ||
| +++ test/diff-test-1.wiki | ||
| @@ -2,11 +2,11 @@ | ||
| 2 | 2 | |
| 3 | 3 | This page contains list of URLs of interesting diffs. |
| 4 | 4 | Click on all URLs, one by one, to verify |
| 5 | 5 | the correct operation of the diff logic. |
| 6 | 6 | |
| 7 | - * <a href="../../../info/030035345c#chunk59" target="testwindow"> | |
| 7 | + * <a href="../../../info/030035345c#chunk73" target="testwindow"> | |
| 8 | 8 | Multiple edits on a single line.</a> This is an SQLite version |
| 9 | 9 | update diff. It is a large diff and contains many other interesting |
| 10 | 10 | features. Scan the whole diff. |
| 11 | 11 | * <a href="../../../fdiff?v1=6da016415dc52d61&v2=af6df3466e3c4a88" |
| 12 | 12 | target="testwindow">Tricky alignment and multiple edits per line</a>. |
| @@ -15,12 +15,12 @@ | ||
| 15 | 15 | * <a href="../../../fdiff?v1=d1c60722e0b9d775&v2=58d1a8991bacb113" |
| 16 | 16 | target="testwindow">Column alignment with multibyte characters.</a> |
| 17 | 17 | The edit of a line with multibyte characters is the first chunk. |
| 18 | 18 | * <a href="../../../fdiff?v1=57b0d8183cab0e3d&v2=37b3ef49d73cdfe6" |
| 19 | 19 | target="testwindow">Large diff of sqlite3.c</a>. This diff was very |
| 20 | - slow prior to the preformance enhancement change [9e15437e97]. | |
| 21 | - * <a href="../../../info/bda00cbada#chunk42" target="testwindow"> | |
| 20 | + slow prior to the performance enhancement change [9e15437e97]. | |
| 21 | + * <a href="../../../info/bda00cbada#chunk49" target="testwindow"> | |
| 22 | 22 | A difficult indentation change. |
| 23 | 23 | * <a href="../../../fdiff?v1=955cc67ace8fb622&v2=e2e1c87b86664b45#chunk13" |
| 24 | 24 | target="testwindow">Another tricky indentation.</a> Notice especially |
| 25 | 25 | lines 59398 and 59407 on the left. |
| 26 | 26 | * <a href="../../../fdiff?v2=955cc67ace8fb622&v1=e2e1c87b86664b45#chunk13" |
| 27 | 27 |
| --- test/diff-test-1.wiki | |
| +++ test/diff-test-1.wiki | |
| @@ -2,11 +2,11 @@ | |
| 2 | |
| 3 | This page contains list of URLs of interesting diffs. |
| 4 | Click on all URLs, one by one, to verify |
| 5 | the correct operation of the diff logic. |
| 6 | |
| 7 | * <a href="../../../info/030035345c#chunk59" target="testwindow"> |
| 8 | Multiple edits on a single line.</a> This is an SQLite version |
| 9 | update diff. It is a large diff and contains many other interesting |
| 10 | features. Scan the whole diff. |
| 11 | * <a href="../../../fdiff?v1=6da016415dc52d61&v2=af6df3466e3c4a88" |
| 12 | target="testwindow">Tricky alignment and multiple edits per line</a>. |
| @@ -15,12 +15,12 @@ | |
| 15 | * <a href="../../../fdiff?v1=d1c60722e0b9d775&v2=58d1a8991bacb113" |
| 16 | target="testwindow">Column alignment with multibyte characters.</a> |
| 17 | The edit of a line with multibyte characters is the first chunk. |
| 18 | * <a href="../../../fdiff?v1=57b0d8183cab0e3d&v2=37b3ef49d73cdfe6" |
| 19 | target="testwindow">Large diff of sqlite3.c</a>. This diff was very |
| 20 | slow prior to the preformance enhancement change [9e15437e97]. |
| 21 | * <a href="../../../info/bda00cbada#chunk42" target="testwindow"> |
| 22 | A difficult indentation change. |
| 23 | * <a href="../../../fdiff?v1=955cc67ace8fb622&v2=e2e1c87b86664b45#chunk13" |
| 24 | target="testwindow">Another tricky indentation.</a> Notice especially |
| 25 | lines 59398 and 59407 on the left. |
| 26 | * <a href="../../../fdiff?v2=955cc67ace8fb622&v1=e2e1c87b86664b45#chunk13" |
| 27 |
| --- test/diff-test-1.wiki | |
| +++ test/diff-test-1.wiki | |
| @@ -2,11 +2,11 @@ | |
| 2 | |
| 3 | This page contains list of URLs of interesting diffs. |
| 4 | Click on all URLs, one by one, to verify |
| 5 | the correct operation of the diff logic. |
| 6 | |
| 7 | * <a href="../../../info/030035345c#chunk73" target="testwindow"> |
| 8 | Multiple edits on a single line.</a> This is an SQLite version |
| 9 | update diff. It is a large diff and contains many other interesting |
| 10 | features. Scan the whole diff. |
| 11 | * <a href="../../../fdiff?v1=6da016415dc52d61&v2=af6df3466e3c4a88" |
| 12 | target="testwindow">Tricky alignment and multiple edits per line</a>. |
| @@ -15,12 +15,12 @@ | |
| 15 | * <a href="../../../fdiff?v1=d1c60722e0b9d775&v2=58d1a8991bacb113" |
| 16 | target="testwindow">Column alignment with multibyte characters.</a> |
| 17 | The edit of a line with multibyte characters is the first chunk. |
| 18 | * <a href="../../../fdiff?v1=57b0d8183cab0e3d&v2=37b3ef49d73cdfe6" |
| 19 | target="testwindow">Large diff of sqlite3.c</a>. This diff was very |
| 20 | slow prior to the performance enhancement change [9e15437e97]. |
| 21 | * <a href="../../../info/bda00cbada#chunk49" target="testwindow"> |
| 22 | A difficult indentation change. |
| 23 | * <a href="../../../fdiff?v1=955cc67ace8fb622&v2=e2e1c87b86664b45#chunk13" |
| 24 | target="testwindow">Another tricky indentation.</a> Notice especially |
| 25 | lines 59398 and 59407 on the left. |
| 26 | * <a href="../../../fdiff?v2=955cc67ace8fb622&v1=e2e1c87b86664b45#chunk13" |
| 27 |
+14
-14
| --- test/merge1.test | ||
| +++ test/merge1.test | ||
| @@ -44,13 +44,13 @@ | ||
| 44 | 44 | 222 - The second line program line in code - 2222 |
| 45 | 45 | 333 - This is a test OF THE merging algohm - 3333 |
| 46 | 46 | 444 - If all goes well, we will be pleased - 4444 |
| 47 | 47 | 555 - we think it well and other stuff too - 5555 |
| 48 | 48 | } |
| 49 | -fossil test-3 t1 t3 t2 a32 | |
| 49 | +fossil 3-way-merge t1 t3 t2 a32 | |
| 50 | 50 | test merge1-1.1 {[same_file t23 a32]} |
| 51 | -fossil test-3 t1 t2 t3 a23 | |
| 51 | +fossil 3-way-merge t1 t2 t3 a23 | |
| 52 | 52 | test merge1-1.2 {[same_file t23 a23]} |
| 53 | 53 | |
| 54 | 54 | write_file_indented t1 { |
| 55 | 55 | 111 - This is line one of the demo program - 1111 |
| 56 | 56 | 222 - The second line program line in code - 2222 |
| @@ -96,13 +96,13 @@ | ||
| 96 | 96 | 222 - The second line program line in code - 2222 |
| 97 | 97 | 333 - This is a test of the merging algohm - 3333 |
| 98 | 98 | 444 - If all goes well, we will be pleased - 4444 |
| 99 | 99 | 555 - we think it well and other stuff too - 5555 |
| 100 | 100 | } |
| 101 | -fossil test-3 t1 t3 t2 a32 | |
| 101 | +fossil 3-way-merge t1 t3 t2 a32 | |
| 102 | 102 | test merge1-2.1 {[same_file t32 a32]} |
| 103 | -fossil test-3 t1 t2 t3 a23 | |
| 103 | +fossil 3-way-merge t1 t2 t3 a23 | |
| 104 | 104 | test merge1-2.2 {[same_file t23 a23]} |
| 105 | 105 | |
| 106 | 106 | write_file_indented t1 { |
| 107 | 107 | 111 - This is line one of the demo program - 1111 |
| 108 | 108 | 222 - The second line program line in code - 2222 |
| @@ -129,13 +129,13 @@ | ||
| 129 | 129 | 222 - The second line program line in code - 2222 |
| 130 | 130 | 333 - This is a test of the merging algohm - 3333 |
| 131 | 131 | 444 - If all goes well, we will be pleased - 4444 |
| 132 | 132 | 555 - we think it well and other stuff too - 5555 |
| 133 | 133 | } |
| 134 | -fossil test-3 t1 t3 t2 a32 | |
| 134 | +fossil 3-way-merge t1 t3 t2 a32 | |
| 135 | 135 | test merge1-3.1 {[same_file t23 a32]} |
| 136 | -fossil test-3 t1 t2 t3 a23 | |
| 136 | +fossil 3-way-merge t1 t2 t3 a23 | |
| 137 | 137 | test merge1-3.2 {[same_file t23 a23]} |
| 138 | 138 | |
| 139 | 139 | write_file_indented t1 { |
| 140 | 140 | 111 - This is line one of the demo program - 1111 |
| 141 | 141 | 222 - The second line program line in code - 2222 |
| @@ -181,13 +181,13 @@ | ||
| 181 | 181 | 222 - The second line program line in code - 2222 |
| 182 | 182 | 333 - This is a test of the merging algohm - 3333 |
| 183 | 183 | 444 - If all goes well, we will be pleased - 4444 |
| 184 | 184 | 555 - we think it well and other stuff too - 5555 |
| 185 | 185 | } |
| 186 | -fossil test-3 t1 t3 t2 a32 | |
| 186 | +fossil 3-way-merge t1 t3 t2 a32 | |
| 187 | 187 | test merge1-4.1 {[same_file t32 a32]} |
| 188 | -fossil test-3 t1 t2 t3 a23 | |
| 188 | +fossil 3-way-merge t1 t2 t3 a23 | |
| 189 | 189 | test merge1-4.2 {[same_file t23 a23]} |
| 190 | 190 | |
| 191 | 191 | write_file_indented t1 { |
| 192 | 192 | 111 - This is line one of the demo program - 1111 |
| 193 | 193 | 222 - The second line program line in code - 2222 |
| @@ -214,13 +214,13 @@ | ||
| 214 | 214 | 333 - This is a test of the merging algohm - 3333 |
| 215 | 215 | 444 - If all goes well, we will be pleased - 4444 |
| 216 | 216 | 555 - we think it well and other stuff too - 5555 |
| 217 | 217 | 666 - Extra line at the end of the file wi - 6666 |
| 218 | 218 | } |
| 219 | -fossil test-3 t1 t3 t2 a32 | |
| 219 | +fossil 3-way-merge t1 t3 t2 a32 | |
| 220 | 220 | test merge1-5.1 {[same_file t32 a32]} |
| 221 | -fossil test-3 t1 t2 t3 a23 | |
| 221 | +fossil 3-way-merge t1 t2 t3 a23 | |
| 222 | 222 | test merge1-5.2 {[same_file t32 a23]} |
| 223 | 223 | |
| 224 | 224 | write_file_indented t1 { |
| 225 | 225 | 111 - This is line one of the demo program - 1111 |
| 226 | 226 | 222 - The second line program line in code - 2222 |
| @@ -243,13 +243,13 @@ | ||
| 243 | 243 | write_file_indented t32 { |
| 244 | 244 | 111 - This is line one of the demo program - 1111 |
| 245 | 245 | 333 - This is a test of the merging algohm - 3333 |
| 246 | 246 | 555 - we think it well and other stuff too - 5555 |
| 247 | 247 | } |
| 248 | -fossil test-3 t1 t3 t2 a32 | |
| 248 | +fossil 3-way-merge t1 t3 t2 a32 | |
| 249 | 249 | test merge1-6.1 {[same_file t32 a32]} |
| 250 | -fossil test-3 t1 t2 t3 a23 | |
| 250 | +fossil 3-way-merge t1 t2 t3 a23 | |
| 251 | 251 | test merge1-6.2 {[same_file t32 a23]} |
| 252 | 252 | |
| 253 | 253 | write_file_indented t1 { |
| 254 | 254 | abcd |
| 255 | 255 | efgh |
| @@ -328,11 +328,11 @@ | ||
| 328 | 328 | KLMN |
| 329 | 329 | OPQR |
| 330 | 330 | STUV |
| 331 | 331 | XYZ. |
| 332 | 332 | } |
| 333 | -fossil test-3 t1 t2 t3 a23 | |
| 333 | +fossil 3-way-merge t1 t2 t3 a23 | |
| 334 | 334 | test merge1-7.1 {[same_file t23 a23]} |
| 335 | 335 | |
| 336 | 336 | write_file_indented t2 { |
| 337 | 337 | abcd |
| 338 | 338 | efgh 2 |
| @@ -396,7 +396,7 @@ | ||
| 396 | 396 | KLMN |
| 397 | 397 | OPQR |
| 398 | 398 | STUV |
| 399 | 399 | XYZ. |
| 400 | 400 | } |
| 401 | -fossil test-3 t1 t2 t3 a23 | |
| 401 | +fossil 3-way-merge t1 t2 t3 a23 | |
| 402 | 402 | test merge1-7.2 {[same_file t23 a23]} |
| 403 | 403 |
| --- test/merge1.test | |
| +++ test/merge1.test | |
| @@ -44,13 +44,13 @@ | |
| 44 | 222 - The second line program line in code - 2222 |
| 45 | 333 - This is a test OF THE merging algohm - 3333 |
| 46 | 444 - If all goes well, we will be pleased - 4444 |
| 47 | 555 - we think it well and other stuff too - 5555 |
| 48 | } |
| 49 | fossil test-3 t1 t3 t2 a32 |
| 50 | test merge1-1.1 {[same_file t23 a32]} |
| 51 | fossil test-3 t1 t2 t3 a23 |
| 52 | test merge1-1.2 {[same_file t23 a23]} |
| 53 | |
| 54 | write_file_indented t1 { |
| 55 | 111 - This is line one of the demo program - 1111 |
| 56 | 222 - The second line program line in code - 2222 |
| @@ -96,13 +96,13 @@ | |
| 96 | 222 - The second line program line in code - 2222 |
| 97 | 333 - This is a test of the merging algohm - 3333 |
| 98 | 444 - If all goes well, we will be pleased - 4444 |
| 99 | 555 - we think it well and other stuff too - 5555 |
| 100 | } |
| 101 | fossil test-3 t1 t3 t2 a32 |
| 102 | test merge1-2.1 {[same_file t32 a32]} |
| 103 | fossil test-3 t1 t2 t3 a23 |
| 104 | test merge1-2.2 {[same_file t23 a23]} |
| 105 | |
| 106 | write_file_indented t1 { |
| 107 | 111 - This is line one of the demo program - 1111 |
| 108 | 222 - The second line program line in code - 2222 |
| @@ -129,13 +129,13 @@ | |
| 129 | 222 - The second line program line in code - 2222 |
| 130 | 333 - This is a test of the merging algohm - 3333 |
| 131 | 444 - If all goes well, we will be pleased - 4444 |
| 132 | 555 - we think it well and other stuff too - 5555 |
| 133 | } |
| 134 | fossil test-3 t1 t3 t2 a32 |
| 135 | test merge1-3.1 {[same_file t23 a32]} |
| 136 | fossil test-3 t1 t2 t3 a23 |
| 137 | test merge1-3.2 {[same_file t23 a23]} |
| 138 | |
| 139 | write_file_indented t1 { |
| 140 | 111 - This is line one of the demo program - 1111 |
| 141 | 222 - The second line program line in code - 2222 |
| @@ -181,13 +181,13 @@ | |
| 181 | 222 - The second line program line in code - 2222 |
| 182 | 333 - This is a test of the merging algohm - 3333 |
| 183 | 444 - If all goes well, we will be pleased - 4444 |
| 184 | 555 - we think it well and other stuff too - 5555 |
| 185 | } |
| 186 | fossil test-3 t1 t3 t2 a32 |
| 187 | test merge1-4.1 {[same_file t32 a32]} |
| 188 | fossil test-3 t1 t2 t3 a23 |
| 189 | test merge1-4.2 {[same_file t23 a23]} |
| 190 | |
| 191 | write_file_indented t1 { |
| 192 | 111 - This is line one of the demo program - 1111 |
| 193 | 222 - The second line program line in code - 2222 |
| @@ -214,13 +214,13 @@ | |
| 214 | 333 - This is a test of the merging algohm - 3333 |
| 215 | 444 - If all goes well, we will be pleased - 4444 |
| 216 | 555 - we think it well and other stuff too - 5555 |
| 217 | 666 - Extra line at the end of the file wi - 6666 |
| 218 | } |
| 219 | fossil test-3 t1 t3 t2 a32 |
| 220 | test merge1-5.1 {[same_file t32 a32]} |
| 221 | fossil test-3 t1 t2 t3 a23 |
| 222 | test merge1-5.2 {[same_file t32 a23]} |
| 223 | |
| 224 | write_file_indented t1 { |
| 225 | 111 - This is line one of the demo program - 1111 |
| 226 | 222 - The second line program line in code - 2222 |
| @@ -243,13 +243,13 @@ | |
| 243 | write_file_indented t32 { |
| 244 | 111 - This is line one of the demo program - 1111 |
| 245 | 333 - This is a test of the merging algohm - 3333 |
| 246 | 555 - we think it well and other stuff too - 5555 |
| 247 | } |
| 248 | fossil test-3 t1 t3 t2 a32 |
| 249 | test merge1-6.1 {[same_file t32 a32]} |
| 250 | fossil test-3 t1 t2 t3 a23 |
| 251 | test merge1-6.2 {[same_file t32 a23]} |
| 252 | |
| 253 | write_file_indented t1 { |
| 254 | abcd |
| 255 | efgh |
| @@ -328,11 +328,11 @@ | |
| 328 | KLMN |
| 329 | OPQR |
| 330 | STUV |
| 331 | XYZ. |
| 332 | } |
| 333 | fossil test-3 t1 t2 t3 a23 |
| 334 | test merge1-7.1 {[same_file t23 a23]} |
| 335 | |
| 336 | write_file_indented t2 { |
| 337 | abcd |
| 338 | efgh 2 |
| @@ -396,7 +396,7 @@ | |
| 396 | KLMN |
| 397 | OPQR |
| 398 | STUV |
| 399 | XYZ. |
| 400 | } |
| 401 | fossil test-3 t1 t2 t3 a23 |
| 402 | test merge1-7.2 {[same_file t23 a23]} |
| 403 |
| --- test/merge1.test | |
| +++ test/merge1.test | |
| @@ -44,13 +44,13 @@ | |
| 44 | 222 - The second line program line in code - 2222 |
| 45 | 333 - This is a test OF THE merging algohm - 3333 |
| 46 | 444 - If all goes well, we will be pleased - 4444 |
| 47 | 555 - we think it well and other stuff too - 5555 |
| 48 | } |
| 49 | fossil 3-way-merge t1 t3 t2 a32 |
| 50 | test merge1-1.1 {[same_file t23 a32]} |
| 51 | fossil 3-way-merge t1 t2 t3 a23 |
| 52 | test merge1-1.2 {[same_file t23 a23]} |
| 53 | |
| 54 | write_file_indented t1 { |
| 55 | 111 - This is line one of the demo program - 1111 |
| 56 | 222 - The second line program line in code - 2222 |
| @@ -96,13 +96,13 @@ | |
| 96 | 222 - The second line program line in code - 2222 |
| 97 | 333 - This is a test of the merging algohm - 3333 |
| 98 | 444 - If all goes well, we will be pleased - 4444 |
| 99 | 555 - we think it well and other stuff too - 5555 |
| 100 | } |
| 101 | fossil 3-way-merge t1 t3 t2 a32 |
| 102 | test merge1-2.1 {[same_file t32 a32]} |
| 103 | fossil 3-way-merge t1 t2 t3 a23 |
| 104 | test merge1-2.2 {[same_file t23 a23]} |
| 105 | |
| 106 | write_file_indented t1 { |
| 107 | 111 - This is line one of the demo program - 1111 |
| 108 | 222 - The second line program line in code - 2222 |
| @@ -129,13 +129,13 @@ | |
| 129 | 222 - The second line program line in code - 2222 |
| 130 | 333 - This is a test of the merging algohm - 3333 |
| 131 | 444 - If all goes well, we will be pleased - 4444 |
| 132 | 555 - we think it well and other stuff too - 5555 |
| 133 | } |
| 134 | fossil 3-way-merge t1 t3 t2 a32 |
| 135 | test merge1-3.1 {[same_file t23 a32]} |
| 136 | fossil 3-way-merge t1 t2 t3 a23 |
| 137 | test merge1-3.2 {[same_file t23 a23]} |
| 138 | |
| 139 | write_file_indented t1 { |
| 140 | 111 - This is line one of the demo program - 1111 |
| 141 | 222 - The second line program line in code - 2222 |
| @@ -181,13 +181,13 @@ | |
| 181 | 222 - The second line program line in code - 2222 |
| 182 | 333 - This is a test of the merging algohm - 3333 |
| 183 | 444 - If all goes well, we will be pleased - 4444 |
| 184 | 555 - we think it well and other stuff too - 5555 |
| 185 | } |
| 186 | fossil 3-way-merge t1 t3 t2 a32 |
| 187 | test merge1-4.1 {[same_file t32 a32]} |
| 188 | fossil 3-way-merge t1 t2 t3 a23 |
| 189 | test merge1-4.2 {[same_file t23 a23]} |
| 190 | |
| 191 | write_file_indented t1 { |
| 192 | 111 - This is line one of the demo program - 1111 |
| 193 | 222 - The second line program line in code - 2222 |
| @@ -214,13 +214,13 @@ | |
| 214 | 333 - This is a test of the merging algohm - 3333 |
| 215 | 444 - If all goes well, we will be pleased - 4444 |
| 216 | 555 - we think it well and other stuff too - 5555 |
| 217 | 666 - Extra line at the end of the file wi - 6666 |
| 218 | } |
| 219 | fossil 3-way-merge t1 t3 t2 a32 |
| 220 | test merge1-5.1 {[same_file t32 a32]} |
| 221 | fossil 3-way-merge t1 t2 t3 a23 |
| 222 | test merge1-5.2 {[same_file t32 a23]} |
| 223 | |
| 224 | write_file_indented t1 { |
| 225 | 111 - This is line one of the demo program - 1111 |
| 226 | 222 - The second line program line in code - 2222 |
| @@ -243,13 +243,13 @@ | |
| 243 | write_file_indented t32 { |
| 244 | 111 - This is line one of the demo program - 1111 |
| 245 | 333 - This is a test of the merging algohm - 3333 |
| 246 | 555 - we think it well and other stuff too - 5555 |
| 247 | } |
| 248 | fossil 3-way-merge t1 t3 t2 a32 |
| 249 | test merge1-6.1 {[same_file t32 a32]} |
| 250 | fossil 3-way-merge t1 t2 t3 a23 |
| 251 | test merge1-6.2 {[same_file t32 a23]} |
| 252 | |
| 253 | write_file_indented t1 { |
| 254 | abcd |
| 255 | efgh |
| @@ -328,11 +328,11 @@ | |
| 328 | KLMN |
| 329 | OPQR |
| 330 | STUV |
| 331 | XYZ. |
| 332 | } |
| 333 | fossil 3-way-merge t1 t2 t3 a23 |
| 334 | test merge1-7.1 {[same_file t23 a23]} |
| 335 | |
| 336 | write_file_indented t2 { |
| 337 | abcd |
| 338 | efgh 2 |
| @@ -396,7 +396,7 @@ | |
| 396 | KLMN |
| 397 | OPQR |
| 398 | STUV |
| 399 | XYZ. |
| 400 | } |
| 401 | fossil 3-way-merge t1 t2 t3 a23 |
| 402 | test merge1-7.2 {[same_file t23 a23]} |
| 403 |
+2
-2
| --- test/merge2.test | ||
| +++ test/merge2.test | ||
| @@ -31,11 +31,11 @@ | ||
| 31 | 31 | write_file t3 [set f3 [random_changes $f1 2 4 2 0.1]] |
| 32 | 32 | expr {srand($i*2+1)} |
| 33 | 33 | write_file t23 [random_changes $f2 2 4 2 0.1] |
| 34 | 34 | expr {srand($i*2)} |
| 35 | 35 | write_file t32 [random_changes $f3 2 4 0 0.1] |
| 36 | - fossil test-3-way-merge t1 t2 t3 a23 | |
| 36 | + fossil 3-way-merge t1 t2 t3 a23 | |
| 37 | 37 | test merge-$base-$i-23 {[same_file a23 t23]} |
| 38 | - fossil test-3-way-merge t1 t3 t2 a32 | |
| 38 | + fossil 3-way-merge t1 t3 t2 a32 | |
| 39 | 39 | test merge-$base-$i-32 {[same_file a32 t32]} |
| 40 | 40 | } |
| 41 | 41 | } |
| 42 | 42 |
| --- test/merge2.test | |
| +++ test/merge2.test | |
| @@ -31,11 +31,11 @@ | |
| 31 | write_file t3 [set f3 [random_changes $f1 2 4 2 0.1]] |
| 32 | expr {srand($i*2+1)} |
| 33 | write_file t23 [random_changes $f2 2 4 2 0.1] |
| 34 | expr {srand($i*2)} |
| 35 | write_file t32 [random_changes $f3 2 4 0 0.1] |
| 36 | fossil test-3-way-merge t1 t2 t3 a23 |
| 37 | test merge-$base-$i-23 {[same_file a23 t23]} |
| 38 | fossil test-3-way-merge t1 t3 t2 a32 |
| 39 | test merge-$base-$i-32 {[same_file a32 t32]} |
| 40 | } |
| 41 | } |
| 42 |
| --- test/merge2.test | |
| +++ test/merge2.test | |
| @@ -31,11 +31,11 @@ | |
| 31 | write_file t3 [set f3 [random_changes $f1 2 4 2 0.1]] |
| 32 | expr {srand($i*2+1)} |
| 33 | write_file t23 [random_changes $f2 2 4 2 0.1] |
| 34 | expr {srand($i*2)} |
| 35 | write_file t32 [random_changes $f3 2 4 0 0.1] |
| 36 | fossil 3-way-merge t1 t2 t3 a23 |
| 37 | test merge-$base-$i-23 {[same_file a23 t23]} |
| 38 | fossil 3-way-merge t1 t3 t2 a32 |
| 39 | test merge-$base-$i-32 {[same_file a32 t32]} |
| 40 | } |
| 41 | } |
| 42 |
+1
-1
| --- test/merge3.test | ||
| +++ test/merge3.test | ||
| @@ -20,11 +20,11 @@ | ||
| 20 | 20 | |
| 21 | 21 | proc merge-test {testid basis v1 v2 result} { |
| 22 | 22 | write_file t1 [join [string trim $basis] \n]\n |
| 23 | 23 | write_file t2 [join [string trim $v1] \n]\n |
| 24 | 24 | write_file t3 [join [string trim $v2] \n]\n |
| 25 | - fossil test-3-way-merge t1 t2 t3 t4 | |
| 25 | + fossil 3-way-merge t1 t2 t3 t4 | |
| 26 | 26 | set x [read_file t4] |
| 27 | 27 | regsub -all {<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <+} $x \ |
| 28 | 28 | {MINE:} x |
| 29 | 29 | regsub -all {======= COMMON ANCESTOR content follows =+} $x {COM:} x |
| 30 | 30 | regsub -all {======= MERGED IN content follows =+} $x {YOURS:} x |
| 31 | 31 |
| --- test/merge3.test | |
| +++ test/merge3.test | |
| @@ -20,11 +20,11 @@ | |
| 20 | |
| 21 | proc merge-test {testid basis v1 v2 result} { |
| 22 | write_file t1 [join [string trim $basis] \n]\n |
| 23 | write_file t2 [join [string trim $v1] \n]\n |
| 24 | write_file t3 [join [string trim $v2] \n]\n |
| 25 | fossil test-3-way-merge t1 t2 t3 t4 |
| 26 | set x [read_file t4] |
| 27 | regsub -all {<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <+} $x \ |
| 28 | {MINE:} x |
| 29 | regsub -all {======= COMMON ANCESTOR content follows =+} $x {COM:} x |
| 30 | regsub -all {======= MERGED IN content follows =+} $x {YOURS:} x |
| 31 |
| --- test/merge3.test | |
| +++ test/merge3.test | |
| @@ -20,11 +20,11 @@ | |
| 20 | |
| 21 | proc merge-test {testid basis v1 v2 result} { |
| 22 | write_file t1 [join [string trim $basis] \n]\n |
| 23 | write_file t2 [join [string trim $v1] \n]\n |
| 24 | write_file t3 [join [string trim $v2] \n]\n |
| 25 | fossil 3-way-merge t1 t2 t3 t4 |
| 26 | set x [read_file t4] |
| 27 | regsub -all {<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <+} $x \ |
| 28 | {MINE:} x |
| 29 | regsub -all {======= COMMON ANCESTOR content follows =+} $x {COM:} x |
| 30 | regsub -all {======= MERGED IN content follows =+} $x {YOURS:} x |
| 31 |
+2
-2
| --- test/merge4.test | ||
| +++ test/merge4.test | ||
| @@ -20,12 +20,12 @@ | ||
| 20 | 20 | |
| 21 | 21 | proc merge-test {testid basis v1 v2 result1 result2} { |
| 22 | 22 | write_file t1 [join [string trim $basis] \n]\n |
| 23 | 23 | write_file t2 [join [string trim $v1] \n]\n |
| 24 | 24 | write_file t3 [join [string trim $v2] \n]\n |
| 25 | - fossil test-3-way-merge t1 t2 t3 t4 | |
| 26 | - fossil test-3-way-merge t1 t3 t2 t5 | |
| 25 | + fossil 3-way-merge t1 t2 t3 t4 | |
| 26 | + fossil 3-way-merge t1 t3 t2 t5 | |
| 27 | 27 | set x [read_file t4] |
| 28 | 28 | regsub -all {<<<<<<< BEGIN MERGE CONFLICT.*<<} $x {>} x |
| 29 | 29 | regsub -all {=======.*=======} $x {=} x |
| 30 | 30 | regsub -all {>>>>>>> END MERGE CONFLICT.*>>>>} $x {<} x |
| 31 | 31 | set x [split [string trim $x] \n] |
| 32 | 32 |
| --- test/merge4.test | |
| +++ test/merge4.test | |
| @@ -20,12 +20,12 @@ | |
| 20 | |
| 21 | proc merge-test {testid basis v1 v2 result1 result2} { |
| 22 | write_file t1 [join [string trim $basis] \n]\n |
| 23 | write_file t2 [join [string trim $v1] \n]\n |
| 24 | write_file t3 [join [string trim $v2] \n]\n |
| 25 | fossil test-3-way-merge t1 t2 t3 t4 |
| 26 | fossil test-3-way-merge t1 t3 t2 t5 |
| 27 | set x [read_file t4] |
| 28 | regsub -all {<<<<<<< BEGIN MERGE CONFLICT.*<<} $x {>} x |
| 29 | regsub -all {=======.*=======} $x {=} x |
| 30 | regsub -all {>>>>>>> END MERGE CONFLICT.*>>>>} $x {<} x |
| 31 | set x [split [string trim $x] \n] |
| 32 |
| --- test/merge4.test | |
| +++ test/merge4.test | |
| @@ -20,12 +20,12 @@ | |
| 20 | |
| 21 | proc merge-test {testid basis v1 v2 result1 result2} { |
| 22 | write_file t1 [join [string trim $basis] \n]\n |
| 23 | write_file t2 [join [string trim $v1] \n]\n |
| 24 | write_file t3 [join [string trim $v2] \n]\n |
| 25 | fossil 3-way-merge t1 t2 t3 t4 |
| 26 | fossil 3-way-merge t1 t3 t2 t5 |
| 27 | set x [read_file t4] |
| 28 | regsub -all {<<<<<<< BEGIN MERGE CONFLICT.*<<} $x {>} x |
| 29 | regsub -all {=======.*=======} $x {=} x |
| 30 | regsub -all {>>>>>>> END MERGE CONFLICT.*>>>>} $x {<} x |
| 31 | set x [split [string trim $x] \n] |
| 32 |
+10
-4
| --- win/Makefile.dmc | ||
| +++ win/Makefile.dmc | ||
| @@ -26,13 +26,13 @@ | ||
| 26 | 26 | TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) |
| 27 | 27 | LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 |
| 28 | 28 | |
| 29 | 29 | 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 |
| 30 | 30 | |
| 31 | -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 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 | |
| 31 | +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 | |
| 32 | 32 | |
| 33 | -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)\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 | |
| 33 | +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 | |
| 34 | 34 | |
| 35 | 35 | |
| 36 | 36 | RC=$(DMDIR)\bin\rcc |
| 37 | 37 | RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ |
| 38 | 38 | |
| @@ -46,11 +46,11 @@ | ||
| 46 | 46 | |
| 47 | 47 | $(OBJDIR)\fossil.res: $B\win\fossil.rc |
| 48 | 48 | $(RC) $(RCFLAGS) -o$@ $** |
| 49 | 49 | |
| 50 | 50 | $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res |
| 51 | - +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 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 > $@ | |
| 51 | + +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 > $@ | |
| 52 | 52 | +echo fossil >> $@ |
| 53 | 53 | +echo fossil >> $@ |
| 54 | 54 | +echo $(LIBS) >> $@ |
| 55 | 55 | +echo. >> $@ |
| 56 | 56 | +echo fossil >> $@ |
| @@ -440,10 +440,16 @@ | ||
| 440 | 440 | $(OBJDIR)\login$O : login_.c login.h |
| 441 | 441 | $(TCC) -o$@ -c login_.c |
| 442 | 442 | |
| 443 | 443 | login_.c : $(SRCDIR)\login.c |
| 444 | 444 | +translate$E $** > $@ |
| 445 | + | |
| 446 | +$(OBJDIR)\lookslike$O : lookslike_.c lookslike.h | |
| 447 | + $(TCC) -o$@ -c lookslike_.c | |
| 448 | + | |
| 449 | +lookslike_.c : $(SRCDIR)\lookslike.c | |
| 450 | + +translate$E $** > $@ | |
| 445 | 451 | |
| 446 | 452 | $(OBJDIR)\main$O : main_.c main.h |
| 447 | 453 | $(TCC) -o$@ -c main_.c |
| 448 | 454 | |
| 449 | 455 | main_.c : $(SRCDIR)\main.c |
| @@ -748,7 +754,7 @@ | ||
| 748 | 754 | |
| 749 | 755 | zip_.c : $(SRCDIR)\zip.c |
| 750 | 756 | +translate$E $** > $@ |
| 751 | 757 | |
| 752 | 758 | headers: makeheaders$E page_index.h VERSION.h |
| 753 | - +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 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 | |
| 759 | + +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 | |
| 754 | 760 | @copy /Y nul: headers |
| 755 | 761 |
| --- win/Makefile.dmc | |
| +++ win/Makefile.dmc | |
| @@ -26,13 +26,13 @@ | |
| 26 | TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) |
| 27 | LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 |
| 28 | |
| 29 | 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 |
| 30 | |
| 31 | 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 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 |
| 32 | |
| 33 | 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)\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 |
| 34 | |
| 35 | |
| 36 | RC=$(DMDIR)\bin\rcc |
| 37 | RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ |
| 38 | |
| @@ -46,11 +46,11 @@ | |
| 46 | |
| 47 | $(OBJDIR)\fossil.res: $B\win\fossil.rc |
| 48 | $(RC) $(RCFLAGS) -o$@ $** |
| 49 | |
| 50 | $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res |
| 51 | +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 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 > $@ |
| 52 | +echo fossil >> $@ |
| 53 | +echo fossil >> $@ |
| 54 | +echo $(LIBS) >> $@ |
| 55 | +echo. >> $@ |
| 56 | +echo fossil >> $@ |
| @@ -440,10 +440,16 @@ | |
| 440 | $(OBJDIR)\login$O : login_.c login.h |
| 441 | $(TCC) -o$@ -c login_.c |
| 442 | |
| 443 | login_.c : $(SRCDIR)\login.c |
| 444 | +translate$E $** > $@ |
| 445 | |
| 446 | $(OBJDIR)\main$O : main_.c main.h |
| 447 | $(TCC) -o$@ -c main_.c |
| 448 | |
| 449 | main_.c : $(SRCDIR)\main.c |
| @@ -748,7 +754,7 @@ | |
| 748 | |
| 749 | zip_.c : $(SRCDIR)\zip.c |
| 750 | +translate$E $** > $@ |
| 751 | |
| 752 | headers: makeheaders$E page_index.h VERSION.h |
| 753 | +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 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 |
| 754 | @copy /Y nul: headers |
| 755 |
| --- win/Makefile.dmc | |
| +++ win/Makefile.dmc | |
| @@ -26,13 +26,13 @@ | |
| 26 | TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) |
| 27 | LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 |
| 28 | |
| 29 | 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 |
| 30 | |
| 31 | 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 |
| 32 | |
| 33 | 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 |
| 34 | |
| 35 | |
| 36 | RC=$(DMDIR)\bin\rcc |
| 37 | RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ |
| 38 | |
| @@ -46,11 +46,11 @@ | |
| 46 | |
| 47 | $(OBJDIR)\fossil.res: $B\win\fossil.rc |
| 48 | $(RC) $(RCFLAGS) -o$@ $** |
| 49 | |
| 50 | $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res |
| 51 | +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 > $@ |
| 52 | +echo fossil >> $@ |
| 53 | +echo fossil >> $@ |
| 54 | +echo $(LIBS) >> $@ |
| 55 | +echo. >> $@ |
| 56 | +echo fossil >> $@ |
| @@ -440,10 +440,16 @@ | |
| 440 | $(OBJDIR)\login$O : login_.c login.h |
| 441 | $(TCC) -o$@ -c login_.c |
| 442 | |
| 443 | login_.c : $(SRCDIR)\login.c |
| 444 | +translate$E $** > $@ |
| 445 | |
| 446 | $(OBJDIR)\lookslike$O : lookslike_.c lookslike.h |
| 447 | $(TCC) -o$@ -c lookslike_.c |
| 448 | |
| 449 | lookslike_.c : $(SRCDIR)\lookslike.c |
| 450 | +translate$E $** > $@ |
| 451 | |
| 452 | $(OBJDIR)\main$O : main_.c main.h |
| 453 | $(TCC) -o$@ -c main_.c |
| 454 | |
| 455 | main_.c : $(SRCDIR)\main.c |
| @@ -748,7 +754,7 @@ | |
| 754 | |
| 755 | zip_.c : $(SRCDIR)\zip.c |
| 756 | +translate$E $** > $@ |
| 757 | |
| 758 | headers: makeheaders$E page_index.h VERSION.h |
| 759 | +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 |
| 760 | @copy /Y nul: headers |
| 761 |
+12
| --- win/Makefile.mingw | ||
| +++ win/Makefile.mingw | ||
| @@ -298,10 +298,11 @@ | ||
| 298 | 298 | $(SRCDIR)/json_timeline.c \ |
| 299 | 299 | $(SRCDIR)/json_user.c \ |
| 300 | 300 | $(SRCDIR)/json_wiki.c \ |
| 301 | 301 | $(SRCDIR)/leaf.c \ |
| 302 | 302 | $(SRCDIR)/login.c \ |
| 303 | + $(SRCDIR)/lookslike.c \ | |
| 303 | 304 | $(SRCDIR)/main.c \ |
| 304 | 305 | $(SRCDIR)/manifest.c \ |
| 305 | 306 | $(SRCDIR)/markdown.c \ |
| 306 | 307 | $(SRCDIR)/markdown_html.c \ |
| 307 | 308 | $(SRCDIR)/md5.c \ |
| @@ -406,10 +407,11 @@ | ||
| 406 | 407 | $(OBJDIR)/json_timeline_.c \ |
| 407 | 408 | $(OBJDIR)/json_user_.c \ |
| 408 | 409 | $(OBJDIR)/json_wiki_.c \ |
| 409 | 410 | $(OBJDIR)/leaf_.c \ |
| 410 | 411 | $(OBJDIR)/login_.c \ |
| 412 | + $(OBJDIR)/lookslike_.c \ | |
| 411 | 413 | $(OBJDIR)/main_.c \ |
| 412 | 414 | $(OBJDIR)/manifest_.c \ |
| 413 | 415 | $(OBJDIR)/markdown_.c \ |
| 414 | 416 | $(OBJDIR)/markdown_html_.c \ |
| 415 | 417 | $(OBJDIR)/md5_.c \ |
| @@ -514,10 +516,11 @@ | ||
| 514 | 516 | $(OBJDIR)/json_timeline.o \ |
| 515 | 517 | $(OBJDIR)/json_user.o \ |
| 516 | 518 | $(OBJDIR)/json_wiki.o \ |
| 517 | 519 | $(OBJDIR)/leaf.o \ |
| 518 | 520 | $(OBJDIR)/login.o \ |
| 521 | + $(OBJDIR)/lookslike.o \ | |
| 519 | 522 | $(OBJDIR)/main.o \ |
| 520 | 523 | $(OBJDIR)/manifest.o \ |
| 521 | 524 | $(OBJDIR)/markdown.o \ |
| 522 | 525 | $(OBJDIR)/markdown_html.o \ |
| 523 | 526 | $(OBJDIR)/md5.o \ |
| @@ -735,10 +738,11 @@ | ||
| 735 | 738 | $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h \ |
| 736 | 739 | $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h \ |
| 737 | 740 | $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h \ |
| 738 | 741 | $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h \ |
| 739 | 742 | $(OBJDIR)/login_.c:$(OBJDIR)/login.h \ |
| 743 | + $(OBJDIR)/lookslike_.c:$(OBJDIR)/lookslike.h \ | |
| 740 | 744 | $(OBJDIR)/main_.c:$(OBJDIR)/main.h \ |
| 741 | 745 | $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h \ |
| 742 | 746 | $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h \ |
| 743 | 747 | $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h \ |
| 744 | 748 | $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \ |
| @@ -1234,10 +1238,18 @@ | ||
| 1234 | 1238 | |
| 1235 | 1239 | $(OBJDIR)/login.o: $(OBJDIR)/login_.c $(OBJDIR)/login.h $(SRCDIR)/config.h |
| 1236 | 1240 | $(XTCC) -o $(OBJDIR)/login.o -c $(OBJDIR)/login_.c |
| 1237 | 1241 | |
| 1238 | 1242 | $(OBJDIR)/login.h: $(OBJDIR)/headers |
| 1243 | + | |
| 1244 | +$(OBJDIR)/lookslike_.c: $(SRCDIR)/lookslike.c $(OBJDIR)/translate | |
| 1245 | + $(TRANSLATE) $(SRCDIR)/lookslike.c >$(OBJDIR)/lookslike_.c | |
| 1246 | + | |
| 1247 | +$(OBJDIR)/lookslike.o: $(OBJDIR)/lookslike_.c $(OBJDIR)/lookslike.h $(SRCDIR)/config.h | |
| 1248 | + $(XTCC) -o $(OBJDIR)/lookslike.o -c $(OBJDIR)/lookslike_.c | |
| 1249 | + | |
| 1250 | +$(OBJDIR)/lookslike.h: $(OBJDIR)/headers | |
| 1239 | 1251 | |
| 1240 | 1252 | $(OBJDIR)/main_.c: $(SRCDIR)/main.c $(OBJDIR)/translate |
| 1241 | 1253 | $(TRANSLATE) $(SRCDIR)/main.c >$(OBJDIR)/main_.c |
| 1242 | 1254 | |
| 1243 | 1255 | $(OBJDIR)/main.o: $(OBJDIR)/main_.c $(OBJDIR)/main.h $(OBJDIR)/page_index.h $(SRCDIR)/config.h |
| 1244 | 1256 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -298,10 +298,11 @@ | |
| 298 | $(SRCDIR)/json_timeline.c \ |
| 299 | $(SRCDIR)/json_user.c \ |
| 300 | $(SRCDIR)/json_wiki.c \ |
| 301 | $(SRCDIR)/leaf.c \ |
| 302 | $(SRCDIR)/login.c \ |
| 303 | $(SRCDIR)/main.c \ |
| 304 | $(SRCDIR)/manifest.c \ |
| 305 | $(SRCDIR)/markdown.c \ |
| 306 | $(SRCDIR)/markdown_html.c \ |
| 307 | $(SRCDIR)/md5.c \ |
| @@ -406,10 +407,11 @@ | |
| 406 | $(OBJDIR)/json_timeline_.c \ |
| 407 | $(OBJDIR)/json_user_.c \ |
| 408 | $(OBJDIR)/json_wiki_.c \ |
| 409 | $(OBJDIR)/leaf_.c \ |
| 410 | $(OBJDIR)/login_.c \ |
| 411 | $(OBJDIR)/main_.c \ |
| 412 | $(OBJDIR)/manifest_.c \ |
| 413 | $(OBJDIR)/markdown_.c \ |
| 414 | $(OBJDIR)/markdown_html_.c \ |
| 415 | $(OBJDIR)/md5_.c \ |
| @@ -514,10 +516,11 @@ | |
| 514 | $(OBJDIR)/json_timeline.o \ |
| 515 | $(OBJDIR)/json_user.o \ |
| 516 | $(OBJDIR)/json_wiki.o \ |
| 517 | $(OBJDIR)/leaf.o \ |
| 518 | $(OBJDIR)/login.o \ |
| 519 | $(OBJDIR)/main.o \ |
| 520 | $(OBJDIR)/manifest.o \ |
| 521 | $(OBJDIR)/markdown.o \ |
| 522 | $(OBJDIR)/markdown_html.o \ |
| 523 | $(OBJDIR)/md5.o \ |
| @@ -735,10 +738,11 @@ | |
| 735 | $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h \ |
| 736 | $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h \ |
| 737 | $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h \ |
| 738 | $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h \ |
| 739 | $(OBJDIR)/login_.c:$(OBJDIR)/login.h \ |
| 740 | $(OBJDIR)/main_.c:$(OBJDIR)/main.h \ |
| 741 | $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h \ |
| 742 | $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h \ |
| 743 | $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h \ |
| 744 | $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \ |
| @@ -1234,10 +1238,18 @@ | |
| 1234 | |
| 1235 | $(OBJDIR)/login.o: $(OBJDIR)/login_.c $(OBJDIR)/login.h $(SRCDIR)/config.h |
| 1236 | $(XTCC) -o $(OBJDIR)/login.o -c $(OBJDIR)/login_.c |
| 1237 | |
| 1238 | $(OBJDIR)/login.h: $(OBJDIR)/headers |
| 1239 | |
| 1240 | $(OBJDIR)/main_.c: $(SRCDIR)/main.c $(OBJDIR)/translate |
| 1241 | $(TRANSLATE) $(SRCDIR)/main.c >$(OBJDIR)/main_.c |
| 1242 | |
| 1243 | $(OBJDIR)/main.o: $(OBJDIR)/main_.c $(OBJDIR)/main.h $(OBJDIR)/page_index.h $(SRCDIR)/config.h |
| 1244 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -298,10 +298,11 @@ | |
| 298 | $(SRCDIR)/json_timeline.c \ |
| 299 | $(SRCDIR)/json_user.c \ |
| 300 | $(SRCDIR)/json_wiki.c \ |
| 301 | $(SRCDIR)/leaf.c \ |
| 302 | $(SRCDIR)/login.c \ |
| 303 | $(SRCDIR)/lookslike.c \ |
| 304 | $(SRCDIR)/main.c \ |
| 305 | $(SRCDIR)/manifest.c \ |
| 306 | $(SRCDIR)/markdown.c \ |
| 307 | $(SRCDIR)/markdown_html.c \ |
| 308 | $(SRCDIR)/md5.c \ |
| @@ -406,10 +407,11 @@ | |
| 407 | $(OBJDIR)/json_timeline_.c \ |
| 408 | $(OBJDIR)/json_user_.c \ |
| 409 | $(OBJDIR)/json_wiki_.c \ |
| 410 | $(OBJDIR)/leaf_.c \ |
| 411 | $(OBJDIR)/login_.c \ |
| 412 | $(OBJDIR)/lookslike_.c \ |
| 413 | $(OBJDIR)/main_.c \ |
| 414 | $(OBJDIR)/manifest_.c \ |
| 415 | $(OBJDIR)/markdown_.c \ |
| 416 | $(OBJDIR)/markdown_html_.c \ |
| 417 | $(OBJDIR)/md5_.c \ |
| @@ -514,10 +516,11 @@ | |
| 516 | $(OBJDIR)/json_timeline.o \ |
| 517 | $(OBJDIR)/json_user.o \ |
| 518 | $(OBJDIR)/json_wiki.o \ |
| 519 | $(OBJDIR)/leaf.o \ |
| 520 | $(OBJDIR)/login.o \ |
| 521 | $(OBJDIR)/lookslike.o \ |
| 522 | $(OBJDIR)/main.o \ |
| 523 | $(OBJDIR)/manifest.o \ |
| 524 | $(OBJDIR)/markdown.o \ |
| 525 | $(OBJDIR)/markdown_html.o \ |
| 526 | $(OBJDIR)/md5.o \ |
| @@ -735,10 +738,11 @@ | |
| 738 | $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h \ |
| 739 | $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h \ |
| 740 | $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h \ |
| 741 | $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h \ |
| 742 | $(OBJDIR)/login_.c:$(OBJDIR)/login.h \ |
| 743 | $(OBJDIR)/lookslike_.c:$(OBJDIR)/lookslike.h \ |
| 744 | $(OBJDIR)/main_.c:$(OBJDIR)/main.h \ |
| 745 | $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h \ |
| 746 | $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h \ |
| 747 | $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h \ |
| 748 | $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \ |
| @@ -1234,10 +1238,18 @@ | |
| 1238 | |
| 1239 | $(OBJDIR)/login.o: $(OBJDIR)/login_.c $(OBJDIR)/login.h $(SRCDIR)/config.h |
| 1240 | $(XTCC) -o $(OBJDIR)/login.o -c $(OBJDIR)/login_.c |
| 1241 | |
| 1242 | $(OBJDIR)/login.h: $(OBJDIR)/headers |
| 1243 | |
| 1244 | $(OBJDIR)/lookslike_.c: $(SRCDIR)/lookslike.c $(OBJDIR)/translate |
| 1245 | $(TRANSLATE) $(SRCDIR)/lookslike.c >$(OBJDIR)/lookslike_.c |
| 1246 | |
| 1247 | $(OBJDIR)/lookslike.o: $(OBJDIR)/lookslike_.c $(OBJDIR)/lookslike.h $(SRCDIR)/config.h |
| 1248 | $(XTCC) -o $(OBJDIR)/lookslike.o -c $(OBJDIR)/lookslike_.c |
| 1249 | |
| 1250 | $(OBJDIR)/lookslike.h: $(OBJDIR)/headers |
| 1251 | |
| 1252 | $(OBJDIR)/main_.c: $(SRCDIR)/main.c $(OBJDIR)/translate |
| 1253 | $(TRANSLATE) $(SRCDIR)/main.c >$(OBJDIR)/main_.c |
| 1254 | |
| 1255 | $(OBJDIR)/main.o: $(OBJDIR)/main_.c $(OBJDIR)/main.h $(OBJDIR)/page_index.h $(SRCDIR)/config.h |
| 1256 |
| --- win/Makefile.mingw.mistachkin | ||
| +++ win/Makefile.mingw.mistachkin | ||
| @@ -298,10 +298,11 @@ | ||
| 298 | 298 | $(SRCDIR)/json_timeline.c \ |
| 299 | 299 | $(SRCDIR)/json_user.c \ |
| 300 | 300 | $(SRCDIR)/json_wiki.c \ |
| 301 | 301 | $(SRCDIR)/leaf.c \ |
| 302 | 302 | $(SRCDIR)/login.c \ |
| 303 | + $(SRCDIR)/lookslike.c \ | |
| 303 | 304 | $(SRCDIR)/main.c \ |
| 304 | 305 | $(SRCDIR)/manifest.c \ |
| 305 | 306 | $(SRCDIR)/markdown.c \ |
| 306 | 307 | $(SRCDIR)/markdown_html.c \ |
| 307 | 308 | $(SRCDIR)/md5.c \ |
| @@ -406,10 +407,11 @@ | ||
| 406 | 407 | $(OBJDIR)/json_timeline_.c \ |
| 407 | 408 | $(OBJDIR)/json_user_.c \ |
| 408 | 409 | $(OBJDIR)/json_wiki_.c \ |
| 409 | 410 | $(OBJDIR)/leaf_.c \ |
| 410 | 411 | $(OBJDIR)/login_.c \ |
| 412 | + $(OBJDIR)/lookslike_.c \ | |
| 411 | 413 | $(OBJDIR)/main_.c \ |
| 412 | 414 | $(OBJDIR)/manifest_.c \ |
| 413 | 415 | $(OBJDIR)/markdown_.c \ |
| 414 | 416 | $(OBJDIR)/markdown_html_.c \ |
| 415 | 417 | $(OBJDIR)/md5_.c \ |
| @@ -514,10 +516,11 @@ | ||
| 514 | 516 | $(OBJDIR)/json_timeline.o \ |
| 515 | 517 | $(OBJDIR)/json_user.o \ |
| 516 | 518 | $(OBJDIR)/json_wiki.o \ |
| 517 | 519 | $(OBJDIR)/leaf.o \ |
| 518 | 520 | $(OBJDIR)/login.o \ |
| 521 | + $(OBJDIR)/lookslike.o \ | |
| 519 | 522 | $(OBJDIR)/main.o \ |
| 520 | 523 | $(OBJDIR)/manifest.o \ |
| 521 | 524 | $(OBJDIR)/markdown.o \ |
| 522 | 525 | $(OBJDIR)/markdown_html.o \ |
| 523 | 526 | $(OBJDIR)/md5.o \ |
| @@ -735,10 +738,11 @@ | ||
| 735 | 738 | $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h \ |
| 736 | 739 | $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h \ |
| 737 | 740 | $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h \ |
| 738 | 741 | $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h \ |
| 739 | 742 | $(OBJDIR)/login_.c:$(OBJDIR)/login.h \ |
| 743 | + $(OBJDIR)/lookslike_.c:$(OBJDIR)/lookslike.h \ | |
| 740 | 744 | $(OBJDIR)/main_.c:$(OBJDIR)/main.h \ |
| 741 | 745 | $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h \ |
| 742 | 746 | $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h \ |
| 743 | 747 | $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h \ |
| 744 | 748 | $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \ |
| @@ -1234,10 +1238,18 @@ | ||
| 1234 | 1238 | |
| 1235 | 1239 | $(OBJDIR)/login.o: $(OBJDIR)/login_.c $(OBJDIR)/login.h $(SRCDIR)/config.h |
| 1236 | 1240 | $(XTCC) -o $(OBJDIR)/login.o -c $(OBJDIR)/login_.c |
| 1237 | 1241 | |
| 1238 | 1242 | $(OBJDIR)/login.h: $(OBJDIR)/headers |
| 1243 | + | |
| 1244 | +$(OBJDIR)/lookslike_.c: $(SRCDIR)/lookslike.c $(OBJDIR)/translate | |
| 1245 | + $(TRANSLATE) $(SRCDIR)/lookslike.c >$(OBJDIR)/lookslike_.c | |
| 1246 | + | |
| 1247 | +$(OBJDIR)/lookslike.o: $(OBJDIR)/lookslike_.c $(OBJDIR)/lookslike.h $(SRCDIR)/config.h | |
| 1248 | + $(XTCC) -o $(OBJDIR)/lookslike.o -c $(OBJDIR)/lookslike_.c | |
| 1249 | + | |
| 1250 | +$(OBJDIR)/lookslike.h: $(OBJDIR)/headers | |
| 1239 | 1251 | |
| 1240 | 1252 | $(OBJDIR)/main_.c: $(SRCDIR)/main.c $(OBJDIR)/translate |
| 1241 | 1253 | $(TRANSLATE) $(SRCDIR)/main.c >$(OBJDIR)/main_.c |
| 1242 | 1254 | |
| 1243 | 1255 | $(OBJDIR)/main.o: $(OBJDIR)/main_.c $(OBJDIR)/main.h $(OBJDIR)/page_index.h $(SRCDIR)/config.h |
| 1244 | 1256 |
| --- win/Makefile.mingw.mistachkin | |
| +++ win/Makefile.mingw.mistachkin | |
| @@ -298,10 +298,11 @@ | |
| 298 | $(SRCDIR)/json_timeline.c \ |
| 299 | $(SRCDIR)/json_user.c \ |
| 300 | $(SRCDIR)/json_wiki.c \ |
| 301 | $(SRCDIR)/leaf.c \ |
| 302 | $(SRCDIR)/login.c \ |
| 303 | $(SRCDIR)/main.c \ |
| 304 | $(SRCDIR)/manifest.c \ |
| 305 | $(SRCDIR)/markdown.c \ |
| 306 | $(SRCDIR)/markdown_html.c \ |
| 307 | $(SRCDIR)/md5.c \ |
| @@ -406,10 +407,11 @@ | |
| 406 | $(OBJDIR)/json_timeline_.c \ |
| 407 | $(OBJDIR)/json_user_.c \ |
| 408 | $(OBJDIR)/json_wiki_.c \ |
| 409 | $(OBJDIR)/leaf_.c \ |
| 410 | $(OBJDIR)/login_.c \ |
| 411 | $(OBJDIR)/main_.c \ |
| 412 | $(OBJDIR)/manifest_.c \ |
| 413 | $(OBJDIR)/markdown_.c \ |
| 414 | $(OBJDIR)/markdown_html_.c \ |
| 415 | $(OBJDIR)/md5_.c \ |
| @@ -514,10 +516,11 @@ | |
| 514 | $(OBJDIR)/json_timeline.o \ |
| 515 | $(OBJDIR)/json_user.o \ |
| 516 | $(OBJDIR)/json_wiki.o \ |
| 517 | $(OBJDIR)/leaf.o \ |
| 518 | $(OBJDIR)/login.o \ |
| 519 | $(OBJDIR)/main.o \ |
| 520 | $(OBJDIR)/manifest.o \ |
| 521 | $(OBJDIR)/markdown.o \ |
| 522 | $(OBJDIR)/markdown_html.o \ |
| 523 | $(OBJDIR)/md5.o \ |
| @@ -735,10 +738,11 @@ | |
| 735 | $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h \ |
| 736 | $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h \ |
| 737 | $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h \ |
| 738 | $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h \ |
| 739 | $(OBJDIR)/login_.c:$(OBJDIR)/login.h \ |
| 740 | $(OBJDIR)/main_.c:$(OBJDIR)/main.h \ |
| 741 | $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h \ |
| 742 | $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h \ |
| 743 | $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h \ |
| 744 | $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \ |
| @@ -1234,10 +1238,18 @@ | |
| 1234 | |
| 1235 | $(OBJDIR)/login.o: $(OBJDIR)/login_.c $(OBJDIR)/login.h $(SRCDIR)/config.h |
| 1236 | $(XTCC) -o $(OBJDIR)/login.o -c $(OBJDIR)/login_.c |
| 1237 | |
| 1238 | $(OBJDIR)/login.h: $(OBJDIR)/headers |
| 1239 | |
| 1240 | $(OBJDIR)/main_.c: $(SRCDIR)/main.c $(OBJDIR)/translate |
| 1241 | $(TRANSLATE) $(SRCDIR)/main.c >$(OBJDIR)/main_.c |
| 1242 | |
| 1243 | $(OBJDIR)/main.o: $(OBJDIR)/main_.c $(OBJDIR)/main.h $(OBJDIR)/page_index.h $(SRCDIR)/config.h |
| 1244 |
| --- win/Makefile.mingw.mistachkin | |
| +++ win/Makefile.mingw.mistachkin | |
| @@ -298,10 +298,11 @@ | |
| 298 | $(SRCDIR)/json_timeline.c \ |
| 299 | $(SRCDIR)/json_user.c \ |
| 300 | $(SRCDIR)/json_wiki.c \ |
| 301 | $(SRCDIR)/leaf.c \ |
| 302 | $(SRCDIR)/login.c \ |
| 303 | $(SRCDIR)/lookslike.c \ |
| 304 | $(SRCDIR)/main.c \ |
| 305 | $(SRCDIR)/manifest.c \ |
| 306 | $(SRCDIR)/markdown.c \ |
| 307 | $(SRCDIR)/markdown_html.c \ |
| 308 | $(SRCDIR)/md5.c \ |
| @@ -406,10 +407,11 @@ | |
| 407 | $(OBJDIR)/json_timeline_.c \ |
| 408 | $(OBJDIR)/json_user_.c \ |
| 409 | $(OBJDIR)/json_wiki_.c \ |
| 410 | $(OBJDIR)/leaf_.c \ |
| 411 | $(OBJDIR)/login_.c \ |
| 412 | $(OBJDIR)/lookslike_.c \ |
| 413 | $(OBJDIR)/main_.c \ |
| 414 | $(OBJDIR)/manifest_.c \ |
| 415 | $(OBJDIR)/markdown_.c \ |
| 416 | $(OBJDIR)/markdown_html_.c \ |
| 417 | $(OBJDIR)/md5_.c \ |
| @@ -514,10 +516,11 @@ | |
| 516 | $(OBJDIR)/json_timeline.o \ |
| 517 | $(OBJDIR)/json_user.o \ |
| 518 | $(OBJDIR)/json_wiki.o \ |
| 519 | $(OBJDIR)/leaf.o \ |
| 520 | $(OBJDIR)/login.o \ |
| 521 | $(OBJDIR)/lookslike.o \ |
| 522 | $(OBJDIR)/main.o \ |
| 523 | $(OBJDIR)/manifest.o \ |
| 524 | $(OBJDIR)/markdown.o \ |
| 525 | $(OBJDIR)/markdown_html.o \ |
| 526 | $(OBJDIR)/md5.o \ |
| @@ -735,10 +738,11 @@ | |
| 738 | $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h \ |
| 739 | $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h \ |
| 740 | $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h \ |
| 741 | $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h \ |
| 742 | $(OBJDIR)/login_.c:$(OBJDIR)/login.h \ |
| 743 | $(OBJDIR)/lookslike_.c:$(OBJDIR)/lookslike.h \ |
| 744 | $(OBJDIR)/main_.c:$(OBJDIR)/main.h \ |
| 745 | $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h \ |
| 746 | $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h \ |
| 747 | $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h \ |
| 748 | $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \ |
| @@ -1234,10 +1238,18 @@ | |
| 1238 | |
| 1239 | $(OBJDIR)/login.o: $(OBJDIR)/login_.c $(OBJDIR)/login.h $(SRCDIR)/config.h |
| 1240 | $(XTCC) -o $(OBJDIR)/login.o -c $(OBJDIR)/login_.c |
| 1241 | |
| 1242 | $(OBJDIR)/login.h: $(OBJDIR)/headers |
| 1243 | |
| 1244 | $(OBJDIR)/lookslike_.c: $(SRCDIR)/lookslike.c $(OBJDIR)/translate |
| 1245 | $(TRANSLATE) $(SRCDIR)/lookslike.c >$(OBJDIR)/lookslike_.c |
| 1246 | |
| 1247 | $(OBJDIR)/lookslike.o: $(OBJDIR)/lookslike_.c $(OBJDIR)/lookslike.h $(SRCDIR)/config.h |
| 1248 | $(XTCC) -o $(OBJDIR)/lookslike.o -c $(OBJDIR)/lookslike_.c |
| 1249 | |
| 1250 | $(OBJDIR)/lookslike.h: $(OBJDIR)/headers |
| 1251 | |
| 1252 | $(OBJDIR)/main_.c: $(SRCDIR)/main.c $(OBJDIR)/translate |
| 1253 | $(TRANSLATE) $(SRCDIR)/main.c >$(OBJDIR)/main_.c |
| 1254 | |
| 1255 | $(OBJDIR)/main.o: $(OBJDIR)/main_.c $(OBJDIR)/main.h $(OBJDIR)/page_index.h $(SRCDIR)/config.h |
| 1256 |
+10
| --- win/Makefile.msc | ||
| +++ win/Makefile.msc | ||
| @@ -116,10 +116,11 @@ | ||
| 116 | 116 | json_timeline_.c \ |
| 117 | 117 | json_user_.c \ |
| 118 | 118 | json_wiki_.c \ |
| 119 | 119 | leaf_.c \ |
| 120 | 120 | login_.c \ |
| 121 | + lookslike_.c \ | |
| 121 | 122 | main_.c \ |
| 122 | 123 | manifest_.c \ |
| 123 | 124 | markdown_.c \ |
| 124 | 125 | markdown_html_.c \ |
| 125 | 126 | md5_.c \ |
| @@ -224,10 +225,11 @@ | ||
| 224 | 225 | $(OX)\json_timeline$O \ |
| 225 | 226 | $(OX)\json_user$O \ |
| 226 | 227 | $(OX)\json_wiki$O \ |
| 227 | 228 | $(OX)\leaf$O \ |
| 228 | 229 | $(OX)\login$O \ |
| 230 | + $(OX)\lookslike$O \ | |
| 229 | 231 | $(OX)\main$O \ |
| 230 | 232 | $(OX)\manifest$O \ |
| 231 | 233 | $(OX)\markdown$O \ |
| 232 | 234 | $(OX)\markdown_html$O \ |
| 233 | 235 | $(OX)\md5$O \ |
| @@ -350,10 +352,11 @@ | ||
| 350 | 352 | echo $(OX)\json_timeline.obj >> $@ |
| 351 | 353 | echo $(OX)\json_user.obj >> $@ |
| 352 | 354 | echo $(OX)\json_wiki.obj >> $@ |
| 353 | 355 | echo $(OX)\leaf.obj >> $@ |
| 354 | 356 | echo $(OX)\login.obj >> $@ |
| 357 | + echo $(OX)\lookslike.obj >> $@ | |
| 355 | 358 | echo $(OX)\main.obj >> $@ |
| 356 | 359 | echo $(OX)\manifest.obj >> $@ |
| 357 | 360 | echo $(OX)\markdown.obj >> $@ |
| 358 | 361 | echo $(OX)\markdown_html.obj >> $@ |
| 359 | 362 | echo $(OX)\md5.obj >> $@ |
| @@ -809,10 +812,16 @@ | ||
| 809 | 812 | $(OX)\login$O : login_.c login.h |
| 810 | 813 | $(TCC) /Fo$@ -c login_.c |
| 811 | 814 | |
| 812 | 815 | login_.c : $(SRCDIR)\login.c |
| 813 | 816 | translate$E $** > $@ |
| 817 | + | |
| 818 | +$(OX)\lookslike$O : lookslike_.c lookslike.h | |
| 819 | + $(TCC) /Fo$@ -c lookslike_.c | |
| 820 | + | |
| 821 | +lookslike_.c : $(SRCDIR)\lookslike.c | |
| 822 | + translate$E $** > $@ | |
| 814 | 823 | |
| 815 | 824 | $(OX)\main$O : main_.c main.h |
| 816 | 825 | $(TCC) /Fo$@ -c main_.c |
| 817 | 826 | |
| 818 | 827 | main_.c : $(SRCDIR)\main.c |
| @@ -1174,10 +1183,11 @@ | ||
| 1174 | 1183 | json_timeline_.c:json_timeline.h \ |
| 1175 | 1184 | json_user_.c:json_user.h \ |
| 1176 | 1185 | json_wiki_.c:json_wiki.h \ |
| 1177 | 1186 | leaf_.c:leaf.h \ |
| 1178 | 1187 | login_.c:login.h \ |
| 1188 | + lookslike_.c:lookslike.h \ | |
| 1179 | 1189 | main_.c:main.h \ |
| 1180 | 1190 | manifest_.c:manifest.h \ |
| 1181 | 1191 | markdown_.c:markdown.h \ |
| 1182 | 1192 | markdown_html_.c:markdown_html.h \ |
| 1183 | 1193 | md5_.c:md5.h \ |
| 1184 | 1194 | |
| 1185 | 1195 | ADDED www/adding_code.wiki |
| --- win/Makefile.msc | |
| +++ win/Makefile.msc | |
| @@ -116,10 +116,11 @@ | |
| 116 | json_timeline_.c \ |
| 117 | json_user_.c \ |
| 118 | json_wiki_.c \ |
| 119 | leaf_.c \ |
| 120 | login_.c \ |
| 121 | main_.c \ |
| 122 | manifest_.c \ |
| 123 | markdown_.c \ |
| 124 | markdown_html_.c \ |
| 125 | md5_.c \ |
| @@ -224,10 +225,11 @@ | |
| 224 | $(OX)\json_timeline$O \ |
| 225 | $(OX)\json_user$O \ |
| 226 | $(OX)\json_wiki$O \ |
| 227 | $(OX)\leaf$O \ |
| 228 | $(OX)\login$O \ |
| 229 | $(OX)\main$O \ |
| 230 | $(OX)\manifest$O \ |
| 231 | $(OX)\markdown$O \ |
| 232 | $(OX)\markdown_html$O \ |
| 233 | $(OX)\md5$O \ |
| @@ -350,10 +352,11 @@ | |
| 350 | echo $(OX)\json_timeline.obj >> $@ |
| 351 | echo $(OX)\json_user.obj >> $@ |
| 352 | echo $(OX)\json_wiki.obj >> $@ |
| 353 | echo $(OX)\leaf.obj >> $@ |
| 354 | echo $(OX)\login.obj >> $@ |
| 355 | echo $(OX)\main.obj >> $@ |
| 356 | echo $(OX)\manifest.obj >> $@ |
| 357 | echo $(OX)\markdown.obj >> $@ |
| 358 | echo $(OX)\markdown_html.obj >> $@ |
| 359 | echo $(OX)\md5.obj >> $@ |
| @@ -809,10 +812,16 @@ | |
| 809 | $(OX)\login$O : login_.c login.h |
| 810 | $(TCC) /Fo$@ -c login_.c |
| 811 | |
| 812 | login_.c : $(SRCDIR)\login.c |
| 813 | translate$E $** > $@ |
| 814 | |
| 815 | $(OX)\main$O : main_.c main.h |
| 816 | $(TCC) /Fo$@ -c main_.c |
| 817 | |
| 818 | main_.c : $(SRCDIR)\main.c |
| @@ -1174,10 +1183,11 @@ | |
| 1174 | json_timeline_.c:json_timeline.h \ |
| 1175 | json_user_.c:json_user.h \ |
| 1176 | json_wiki_.c:json_wiki.h \ |
| 1177 | leaf_.c:leaf.h \ |
| 1178 | login_.c:login.h \ |
| 1179 | main_.c:main.h \ |
| 1180 | manifest_.c:manifest.h \ |
| 1181 | markdown_.c:markdown.h \ |
| 1182 | markdown_html_.c:markdown_html.h \ |
| 1183 | md5_.c:md5.h \ |
| 1184 | |
| 1185 | DDED www/adding_code.wiki |
| --- win/Makefile.msc | |
| +++ win/Makefile.msc | |
| @@ -116,10 +116,11 @@ | |
| 116 | json_timeline_.c \ |
| 117 | json_user_.c \ |
| 118 | json_wiki_.c \ |
| 119 | leaf_.c \ |
| 120 | login_.c \ |
| 121 | lookslike_.c \ |
| 122 | main_.c \ |
| 123 | manifest_.c \ |
| 124 | markdown_.c \ |
| 125 | markdown_html_.c \ |
| 126 | md5_.c \ |
| @@ -224,10 +225,11 @@ | |
| 225 | $(OX)\json_timeline$O \ |
| 226 | $(OX)\json_user$O \ |
| 227 | $(OX)\json_wiki$O \ |
| 228 | $(OX)\leaf$O \ |
| 229 | $(OX)\login$O \ |
| 230 | $(OX)\lookslike$O \ |
| 231 | $(OX)\main$O \ |
| 232 | $(OX)\manifest$O \ |
| 233 | $(OX)\markdown$O \ |
| 234 | $(OX)\markdown_html$O \ |
| 235 | $(OX)\md5$O \ |
| @@ -350,10 +352,11 @@ | |
| 352 | echo $(OX)\json_timeline.obj >> $@ |
| 353 | echo $(OX)\json_user.obj >> $@ |
| 354 | echo $(OX)\json_wiki.obj >> $@ |
| 355 | echo $(OX)\leaf.obj >> $@ |
| 356 | echo $(OX)\login.obj >> $@ |
| 357 | echo $(OX)\lookslike.obj >> $@ |
| 358 | echo $(OX)\main.obj >> $@ |
| 359 | echo $(OX)\manifest.obj >> $@ |
| 360 | echo $(OX)\markdown.obj >> $@ |
| 361 | echo $(OX)\markdown_html.obj >> $@ |
| 362 | echo $(OX)\md5.obj >> $@ |
| @@ -809,10 +812,16 @@ | |
| 812 | $(OX)\login$O : login_.c login.h |
| 813 | $(TCC) /Fo$@ -c login_.c |
| 814 | |
| 815 | login_.c : $(SRCDIR)\login.c |
| 816 | translate$E $** > $@ |
| 817 | |
| 818 | $(OX)\lookslike$O : lookslike_.c lookslike.h |
| 819 | $(TCC) /Fo$@ -c lookslike_.c |
| 820 | |
| 821 | lookslike_.c : $(SRCDIR)\lookslike.c |
| 822 | translate$E $** > $@ |
| 823 | |
| 824 | $(OX)\main$O : main_.c main.h |
| 825 | $(TCC) /Fo$@ -c main_.c |
| 826 | |
| 827 | main_.c : $(SRCDIR)\main.c |
| @@ -1174,10 +1183,11 @@ | |
| 1183 | json_timeline_.c:json_timeline.h \ |
| 1184 | json_user_.c:json_user.h \ |
| 1185 | json_wiki_.c:json_wiki.h \ |
| 1186 | leaf_.c:leaf.h \ |
| 1187 | login_.c:login.h \ |
| 1188 | lookslike_.c:lookslike.h \ |
| 1189 | main_.c:main.h \ |
| 1190 | manifest_.c:manifest.h \ |
| 1191 | markdown_.c:markdown.h \ |
| 1192 | markdown_html_.c:markdown_html.h \ |
| 1193 | md5_.c:md5.h \ |
| 1194 | |
| 1195 | DDED www/adding_code.wiki |
+1
| --- a/www/adding_code.wiki | ||
| +++ b/www/adding_code.wiki | ||
| @@ -0,0 +1 @@ | ||
| 1 | +agt the the |
| --- a/www/adding_code.wiki | |
| +++ b/www/adding_code.wiki | |
| @@ -0,0 +1 @@ | |
| --- a/www/adding_code.wiki | |
| +++ b/www/adding_code.wiki | |
| @@ -0,0 +1 @@ | |
| 1 | agt the the |
+7
| --- www/build.wiki | ||
| +++ www/build.wiki | ||
| @@ -122,10 +122,17 @@ | ||
| 122 | 122 | you, or for some other reason you want to know how to build |
| 123 | 123 | Fossil manually, then refer to the |
| 124 | 124 | [./makefile.wiki | Fossil Build Process] document which describes |
| 125 | 125 | in detail what the makefiles do behind the scenes. |
| 126 | 126 | |
| 127 | +<li><p> | |
| 128 | + The fossil executable is self-contained and stand-alone and usually | |
| 129 | + requires no special libraries or other software to be installed. However, | |
| 130 | + the "--tk" option to the [/help/diff|diff command] requires that Tcl/Tk | |
| 131 | + be installed on the local machine. You can get Tcl/Tk from | |
| 132 | + [http://www.activestate.com/activetcl|ActiveState]. | |
| 133 | + | |
| 127 | 134 | <li><p> |
| 128 | 135 | To build on older Macs (circa 2002, MacOS 10.2) edit the Makefile |
| 129 | 136 | generated by configure to add the following lines: |
| 130 | 137 | <blockquote><pre> |
| 131 | 138 | TCC += -DSQLITE_WITHOUT_ZONEMALLOC |
| 132 | 139 |
| --- www/build.wiki | |
| +++ www/build.wiki | |
| @@ -122,10 +122,17 @@ | |
| 122 | you, or for some other reason you want to know how to build |
| 123 | Fossil manually, then refer to the |
| 124 | [./makefile.wiki | Fossil Build Process] document which describes |
| 125 | in detail what the makefiles do behind the scenes. |
| 126 | |
| 127 | <li><p> |
| 128 | To build on older Macs (circa 2002, MacOS 10.2) edit the Makefile |
| 129 | generated by configure to add the following lines: |
| 130 | <blockquote><pre> |
| 131 | TCC += -DSQLITE_WITHOUT_ZONEMALLOC |
| 132 |
| --- www/build.wiki | |
| +++ www/build.wiki | |
| @@ -122,10 +122,17 @@ | |
| 122 | you, or for some other reason you want to know how to build |
| 123 | Fossil manually, then refer to the |
| 124 | [./makefile.wiki | Fossil Build Process] document which describes |
| 125 | in detail what the makefiles do behind the scenes. |
| 126 | |
| 127 | <li><p> |
| 128 | The fossil executable is self-contained and stand-alone and usually |
| 129 | requires no special libraries or other software to be installed. However, |
| 130 | the "--tk" option to the [/help/diff|diff command] requires that Tcl/Tk |
| 131 | be installed on the local machine. You can get Tcl/Tk from |
| 132 | [http://www.activestate.com/activetcl|ActiveState]. |
| 133 | |
| 134 | <li><p> |
| 135 | To build on older Macs (circa 2002, MacOS 10.2) edit the Makefile |
| 136 | generated by configure to add the following lines: |
| 137 | <blockquote><pre> |
| 138 | TCC += -DSQLITE_WITHOUT_ZONEMALLOC |
| 139 |
+1
| --- www/contribute.wiki | ||
| +++ www/contribute.wiki | ||
| @@ -78,5 +78,6 @@ | ||
| 78 | 78 | <h2>5.0 See Also</h2> |
| 79 | 79 | |
| 80 | 80 | * [./build.wiki | How To Compile And Install Fossil] |
| 81 | 81 | * [./makefile.wiki | The Fossil Build Process] |
| 82 | 82 | * [./tech_overview.wiki | A Technical Overview of Fossil] |
| 83 | + * [./adding_code.wiki | Adding Features To Fossil] | |
| 83 | 84 |
| --- www/contribute.wiki | |
| +++ www/contribute.wiki | |
| @@ -78,5 +78,6 @@ | |
| 78 | <h2>5.0 See Also</h2> |
| 79 | |
| 80 | * [./build.wiki | How To Compile And Install Fossil] |
| 81 | * [./makefile.wiki | The Fossil Build Process] |
| 82 | * [./tech_overview.wiki | A Technical Overview of Fossil] |
| 83 |
| --- www/contribute.wiki | |
| +++ www/contribute.wiki | |
| @@ -78,5 +78,6 @@ | |
| 78 | <h2>5.0 See Also</h2> |
| 79 | |
| 80 | * [./build.wiki | How To Compile And Install Fossil] |
| 81 | * [./makefile.wiki | The Fossil Build Process] |
| 82 | * [./tech_overview.wiki | A Technical Overview of Fossil] |
| 83 | * [./adding_code.wiki | Adding Features To Fossil] |
| 84 |
+4
-4
| --- www/faq.tcl | ||
| +++ www/faq.tcl | ||
| @@ -37,13 +37,11 @@ | ||
| 37 | 37 | } { |
| 38 | 38 | There are lots of ways: |
| 39 | 39 | |
| 40 | 40 | When you are checking in a new change using the <b>[/help/commit|commit]</b> |
| 41 | 41 | command, you can add the option "--branch <i>BRANCH-NAME</i>" to |
| 42 | - make the new check-in be the first check-in for a new branch. You can | |
| 43 | - also add the "--bgcolor <i>COLOR</i>" option to give the branch a | |
| 44 | - specific background color on timelines. | |
| 42 | + make the new check-in be the first check-in for a new branch. | |
| 45 | 43 | |
| 46 | 44 | If you want to create a new branch whose initial content is the |
| 47 | 45 | same as an existing check-in, use this command: |
| 48 | 46 | |
| 49 | 47 | <blockquote> |
| @@ -70,11 +68,13 @@ | ||
| 70 | 68 | } { |
| 71 | 69 | There are several ways: |
| 72 | 70 | |
| 73 | 71 | When you are checking in a new change using the <b>[/help/commit|commit]</b> |
| 74 | 72 | command, you can add a tag to that check-in using the |
| 75 | - "--tag <i>TAGNAME</i>" command-line option. | |
| 73 | + "--tag <i>TAGNAME</i>" command-line option. You can repeat the --tag | |
| 74 | + option to give a check-in multiple tags. Tags need not be unique. So, | |
| 75 | + for example, it is common to give every released version a "release" tag. | |
| 76 | 76 | |
| 77 | 77 | If you want add a tag to an existing check-in, you can use the |
| 78 | 78 | <b>[/help/tag|tag]</b> command. For example: |
| 79 | 79 | |
| 80 | 80 | <blockquote> |
| 81 | 81 |
| --- www/faq.tcl | |
| +++ www/faq.tcl | |
| @@ -37,13 +37,11 @@ | |
| 37 | } { |
| 38 | There are lots of ways: |
| 39 | |
| 40 | When you are checking in a new change using the <b>[/help/commit|commit]</b> |
| 41 | command, you can add the option "--branch <i>BRANCH-NAME</i>" to |
| 42 | make the new check-in be the first check-in for a new branch. You can |
| 43 | also add the "--bgcolor <i>COLOR</i>" option to give the branch a |
| 44 | specific background color on timelines. |
| 45 | |
| 46 | If you want to create a new branch whose initial content is the |
| 47 | same as an existing check-in, use this command: |
| 48 | |
| 49 | <blockquote> |
| @@ -70,11 +68,13 @@ | |
| 70 | } { |
| 71 | There are several ways: |
| 72 | |
| 73 | When you are checking in a new change using the <b>[/help/commit|commit]</b> |
| 74 | command, you can add a tag to that check-in using the |
| 75 | "--tag <i>TAGNAME</i>" command-line option. |
| 76 | |
| 77 | If you want add a tag to an existing check-in, you can use the |
| 78 | <b>[/help/tag|tag]</b> command. For example: |
| 79 | |
| 80 | <blockquote> |
| 81 |
| --- www/faq.tcl | |
| +++ www/faq.tcl | |
| @@ -37,13 +37,11 @@ | |
| 37 | } { |
| 38 | There are lots of ways: |
| 39 | |
| 40 | When you are checking in a new change using the <b>[/help/commit|commit]</b> |
| 41 | command, you can add the option "--branch <i>BRANCH-NAME</i>" to |
| 42 | make the new check-in be the first check-in for a new branch. |
| 43 | |
| 44 | If you want to create a new branch whose initial content is the |
| 45 | same as an existing check-in, use this command: |
| 46 | |
| 47 | <blockquote> |
| @@ -70,11 +68,13 @@ | |
| 68 | } { |
| 69 | There are several ways: |
| 70 | |
| 71 | When you are checking in a new change using the <b>[/help/commit|commit]</b> |
| 72 | command, you can add a tag to that check-in using the |
| 73 | "--tag <i>TAGNAME</i>" command-line option. You can repeat the --tag |
| 74 | option to give a check-in multiple tags. Tags need not be unique. So, |
| 75 | for example, it is common to give every released version a "release" tag. |
| 76 | |
| 77 | If you want add a tag to an existing check-in, you can use the |
| 78 | <b>[/help/tag|tag]</b> command. For example: |
| 79 | |
| 80 | <blockquote> |
| 81 |
+4
-4
| --- www/faq.wiki | ||
| +++ www/faq.wiki | ||
| @@ -41,13 +41,11 @@ | ||
| 41 | 41 | |
| 42 | 42 | <blockquote>There are lots of ways: |
| 43 | 43 | |
| 44 | 44 | When you are checking in a new change using the <b>[/help/commit|commit]</b> |
| 45 | 45 | command, you can add the option "--branch <i>BRANCH-NAME</i>" to |
| 46 | -make the new check-in be the first check-in for a new branch. You can | |
| 47 | -also add the "--bgcolor <i>COLOR</i>" option to give the branch a | |
| 48 | -specific background color on timelines. | |
| 46 | +make the new check-in be the first check-in for a new branch. | |
| 49 | 47 | |
| 50 | 48 | If you want to create a new branch whose initial content is the |
| 51 | 49 | same as an existing check-in, use this command: |
| 52 | 50 | |
| 53 | 51 | <blockquote> |
| @@ -73,11 +71,13 @@ | ||
| 73 | 71 | |
| 74 | 72 | <blockquote>There are several ways: |
| 75 | 73 | |
| 76 | 74 | When you are checking in a new change using the <b>[/help/commit|commit]</b> |
| 77 | 75 | command, you can add a tag to that check-in using the |
| 78 | -"--tag <i>TAGNAME</i>" command-line option. | |
| 76 | +"--tag <i>TAGNAME</i>" command-line option. You can repeat the --tag | |
| 77 | +option to give a check-in multiple tags. Tags need not be unique. So, | |
| 78 | +for example, it is common to give every released version a "release" tag. | |
| 79 | 79 | |
| 80 | 80 | If you want add a tag to an existing check-in, you can use the |
| 81 | 81 | <b>[/help/tag|tag]</b> command. For example: |
| 82 | 82 | |
| 83 | 83 | <blockquote> |
| 84 | 84 |
| --- www/faq.wiki | |
| +++ www/faq.wiki | |
| @@ -41,13 +41,11 @@ | |
| 41 | |
| 42 | <blockquote>There are lots of ways: |
| 43 | |
| 44 | When you are checking in a new change using the <b>[/help/commit|commit]</b> |
| 45 | command, you can add the option "--branch <i>BRANCH-NAME</i>" to |
| 46 | make the new check-in be the first check-in for a new branch. You can |
| 47 | also add the "--bgcolor <i>COLOR</i>" option to give the branch a |
| 48 | specific background color on timelines. |
| 49 | |
| 50 | If you want to create a new branch whose initial content is the |
| 51 | same as an existing check-in, use this command: |
| 52 | |
| 53 | <blockquote> |
| @@ -73,11 +71,13 @@ | |
| 73 | |
| 74 | <blockquote>There are several ways: |
| 75 | |
| 76 | When you are checking in a new change using the <b>[/help/commit|commit]</b> |
| 77 | command, you can add a tag to that check-in using the |
| 78 | "--tag <i>TAGNAME</i>" command-line option. |
| 79 | |
| 80 | If you want add a tag to an existing check-in, you can use the |
| 81 | <b>[/help/tag|tag]</b> command. For example: |
| 82 | |
| 83 | <blockquote> |
| 84 |
| --- www/faq.wiki | |
| +++ www/faq.wiki | |
| @@ -41,13 +41,11 @@ | |
| 41 | |
| 42 | <blockquote>There are lots of ways: |
| 43 | |
| 44 | When you are checking in a new change using the <b>[/help/commit|commit]</b> |
| 45 | command, you can add the option "--branch <i>BRANCH-NAME</i>" to |
| 46 | make the new check-in be the first check-in for a new branch. |
| 47 | |
| 48 | If you want to create a new branch whose initial content is the |
| 49 | same as an existing check-in, use this command: |
| 50 | |
| 51 | <blockquote> |
| @@ -73,11 +71,13 @@ | |
| 71 | |
| 72 | <blockquote>There are several ways: |
| 73 | |
| 74 | When you are checking in a new change using the <b>[/help/commit|commit]</b> |
| 75 | command, you can add a tag to that check-in using the |
| 76 | "--tag <i>TAGNAME</i>" command-line option. You can repeat the --tag |
| 77 | option to give a check-in multiple tags. Tags need not be unique. So, |
| 78 | for example, it is common to give every released version a "release" tag. |
| 79 | |
| 80 | If you want add a tag to an existing check-in, you can use the |
| 81 | <b>[/help/tag|tag]</b> command. For example: |
| 82 | |
| 83 | <blockquote> |
| 84 |
+31
-18
| --- www/fossil-v-git.wiki | ||
| +++ www/fossil-v-git.wiki | ||
| @@ -35,11 +35,11 @@ | ||
| 35 | 35 | <h3>3.1 Feature Set</h3> |
| 36 | 36 | |
| 37 | 37 | Git provides file versioning services only, whereas Fossil adds an |
| 38 | 38 | integrated [./wikitheory.wiki | wiki], |
| 39 | 39 | [./bugtheory.wiki | ticketing & bug tracking], |
| 40 | -[./embedddeddoc.wiki | embedded documentation], and | |
| 40 | +[./embeddeddoc.wiki | embedded documentation], and | |
| 41 | 41 | [./event.wiki | News/Blog features]. |
| 42 | 42 | These additional capabilities are available for Git as 3rd-party |
| 43 | 43 | user-installed add-ons, but with Fossil they are integrated into |
| 44 | 44 | the design. One way to describe Fossil is that it is |
| 45 | 45 | "[https://github.com/ | github]-in-a-box". |
| @@ -74,11 +74,11 @@ | ||
| 74 | 74 | until they reach the master branch. |
| 75 | 75 | |
| 76 | 76 | Fossil is designed for smaller and non-hierarchical teams where all |
| 77 | 77 | developers are operating directly on the master branch, or at most |
| 78 | 78 | a small number of well defined branches. |
| 79 | -The [concepts.wiki#workflow | autosync] mode of Fossil makes it easy | |
| 79 | +The [./concepts.wiki#workflow | autosync] mode of Fossil makes it easy | |
| 80 | 80 | for multiple developers to work on a single branch and maintain |
| 81 | 81 | linear development on that branch and avoid needless forking |
| 82 | 82 | and merging. |
| 83 | 83 | |
| 84 | 84 | <h3>3.3 Branches</h3> |
| @@ -115,13 +115,18 @@ | ||
| 115 | 115 | The Git approach scales much better for large projects like the Linux |
| 116 | 116 | kernel with thousands of contributors who in many cases don't even know |
| 117 | 117 | each others names. The integrators serve a gatekeeper role to help keep |
| 118 | 118 | undesirable code out of the official Linux source tree. On the other hand, |
| 119 | 119 | not many projects are as big or as loosely organized as the Linux kernel. |
| 120 | -Most project, have a small team of developers who all know each other | |
| 120 | +Most projects have a small team of developers who all know each other | |
| 121 | 121 | well and trust each other, and who enjoy working together collaboratively |
| 122 | 122 | without the overhead and hierarchy of integrators. |
| 123 | + | |
| 124 | +One consequence of the "everybody-sees-everything" focus of Fossil is that | |
| 125 | +branch names are global and are part of the distributed and synchronized | |
| 126 | +content of a Fossil repository, rather than being private and user-specific | |
| 127 | +as they are in Git. | |
| 123 | 128 | |
| 124 | 129 | <h3>3.4 Complexity</h3> |
| 125 | 130 | |
| 126 | 131 | Git is a complex system. It can be tricky to use and requires a fair |
| 127 | 132 | amount of knowledge and experience to master. Fossil strives to be |
| @@ -139,19 +144,20 @@ | ||
| 139 | 144 | Git requires the developer to maintain a more complex mental model than |
| 140 | 145 | most other DVCSes. Git takes longer to learn. And you have to spend |
| 141 | 146 | more time thinking about what you are doing with Git. |
| 142 | 147 | |
| 143 | 148 | Fossil strives for simplicity. Fossil wants to be easy to learn and to |
| 144 | -require little thinking about how to operating it. Reports from the | |
| 145 | -field indicate that Fossil is mostly successful at this effort. | |
| 149 | +require little thinking about how to operating it. | |
| 150 | +[./quotes.wiki | Reports from the field] | |
| 151 | +indicate that Fossil is mostly successful at this effort. | |
| 146 | 152 | |
| 147 | 153 | <h3>3.5 Web Interface</h3> |
| 148 | 154 | |
| 149 | 155 | Git has a web interface, but it requires a fair amount of setup and an |
| 150 | 156 | external web server. Fossil comes with a fully functional |
| 151 | 157 | [./webui.wiki | built-in web-server] |
| 152 | -and a really simple mechanism (the "<tt>fossil ui</tt>" command) to | |
| 158 | +and a really simple mechanism (the "[/help/ui|fossil ui]" command) to | |
| 153 | 159 | automatically start the web server and bring up a web browser to navigate |
| 154 | 160 | it. The web interface for Fossil is not only easier to set up, it is also |
| 155 | 161 | more powerful and easier to use. The web interface to Fossil is a practical |
| 156 | 162 | replacement to the 3rd-party "GUI Tools" that users often employ to operate |
| 157 | 163 | Git. |
| @@ -188,22 +194,29 @@ | ||
| 188 | 194 | <h3>3.8 Audit Trail</h3> |
| 189 | 195 | |
| 190 | 196 | Git features the "rebase" command which can be used to change the |
| 191 | 197 | sequence of check-ins in the repository. Rebase can be used to "clean up" |
| 192 | 198 | a complex sequence of check-ins to make their intent easier for others |
| 193 | -to understand. From another point of view, rebase can be used to | |
| 194 | -"rewrite history" - to do what | |
| 195 | -[http://en.wikipedia.org/wiki/Winston_Smith | Winston Smith] did for | |
| 196 | -a living in Orwell's novel | |
| 197 | -[http://en.wikipedia.org/wiki/Nineteen_Eighty-Four | 1984]. | |
| 198 | - | |
| 199 | -Fossil deliberately avoids rewriting history. Fossil strives to follow | |
| 200 | -the accountants philosophy of never erasing anything. Mistakes are fixed | |
| 201 | -by entering a correction, with an explanation of why the correction is | |
| 202 | -needed. This can make the history of a project messy, but it also | |
| 203 | -makes it more honest. The lack of a "rebase" function is considered | |
| 204 | -a feature of Fossil, not a bug. | |
| 199 | +to understand. This is important if you view the history of a project | |
| 200 | +as part of the documentation for the project. | |
| 201 | + | |
| 202 | +Fossil takes an opposing view. Fossil views history as sacrosanct and | |
| 203 | +stubornly refuses to change it. | |
| 204 | +Fossil allows mistakes to be corrected (for example, check-in comments | |
| 205 | +can be revised, and check-ins can be moved onto new branches even after | |
| 206 | +the check-in has occurred) but the correction is an addition to the respository | |
| 207 | +and the original actions are preserved and displayed alongside | |
| 208 | +the corrections, thus preserving an historically accurate audit trail. | |
| 209 | +This is analogous to an accountant marking through an incorrect | |
| 210 | +entry in a ledger and writing in a correction beside it, rather than | |
| 211 | +erasing and incorrect entry. | |
| 212 | + | |
| 213 | +To put it another way, Git remembers what you should have done whereas | |
| 214 | +Fossil remembers what you actually did. | |
| 215 | + | |
| 216 | +The lack of a "rebase" command and the inability to rewrite history | |
| 217 | +is considered a feature of Fossil, not an omission or bug. | |
| 205 | 218 | |
| 206 | 219 | <h3>3.9 License</h3> |
| 207 | 220 | |
| 208 | 221 | Both Git and Fossil are open-source. Git is under |
| 209 | 222 | [http://www.gnu.org/licenses/gpl.html | GPL] whereas Fossil is |
| 210 | 223 |
| --- www/fossil-v-git.wiki | |
| +++ www/fossil-v-git.wiki | |
| @@ -35,11 +35,11 @@ | |
| 35 | <h3>3.1 Feature Set</h3> |
| 36 | |
| 37 | Git provides file versioning services only, whereas Fossil adds an |
| 38 | integrated [./wikitheory.wiki | wiki], |
| 39 | [./bugtheory.wiki | ticketing & bug tracking], |
| 40 | [./embedddeddoc.wiki | embedded documentation], and |
| 41 | [./event.wiki | News/Blog features]. |
| 42 | These additional capabilities are available for Git as 3rd-party |
| 43 | user-installed add-ons, but with Fossil they are integrated into |
| 44 | the design. One way to describe Fossil is that it is |
| 45 | "[https://github.com/ | github]-in-a-box". |
| @@ -74,11 +74,11 @@ | |
| 74 | until they reach the master branch. |
| 75 | |
| 76 | Fossil is designed for smaller and non-hierarchical teams where all |
| 77 | developers are operating directly on the master branch, or at most |
| 78 | a small number of well defined branches. |
| 79 | The [concepts.wiki#workflow | autosync] mode of Fossil makes it easy |
| 80 | for multiple developers to work on a single branch and maintain |
| 81 | linear development on that branch and avoid needless forking |
| 82 | and merging. |
| 83 | |
| 84 | <h3>3.3 Branches</h3> |
| @@ -115,13 +115,18 @@ | |
| 115 | The Git approach scales much better for large projects like the Linux |
| 116 | kernel with thousands of contributors who in many cases don't even know |
| 117 | each others names. The integrators serve a gatekeeper role to help keep |
| 118 | undesirable code out of the official Linux source tree. On the other hand, |
| 119 | not many projects are as big or as loosely organized as the Linux kernel. |
| 120 | Most project, have a small team of developers who all know each other |
| 121 | well and trust each other, and who enjoy working together collaboratively |
| 122 | without the overhead and hierarchy of integrators. |
| 123 | |
| 124 | <h3>3.4 Complexity</h3> |
| 125 | |
| 126 | Git is a complex system. It can be tricky to use and requires a fair |
| 127 | amount of knowledge and experience to master. Fossil strives to be |
| @@ -139,19 +144,20 @@ | |
| 139 | Git requires the developer to maintain a more complex mental model than |
| 140 | most other DVCSes. Git takes longer to learn. And you have to spend |
| 141 | more time thinking about what you are doing with Git. |
| 142 | |
| 143 | Fossil strives for simplicity. Fossil wants to be easy to learn and to |
| 144 | require little thinking about how to operating it. Reports from the |
| 145 | field indicate that Fossil is mostly successful at this effort. |
| 146 | |
| 147 | <h3>3.5 Web Interface</h3> |
| 148 | |
| 149 | Git has a web interface, but it requires a fair amount of setup and an |
| 150 | external web server. Fossil comes with a fully functional |
| 151 | [./webui.wiki | built-in web-server] |
| 152 | and a really simple mechanism (the "<tt>fossil ui</tt>" command) to |
| 153 | automatically start the web server and bring up a web browser to navigate |
| 154 | it. The web interface for Fossil is not only easier to set up, it is also |
| 155 | more powerful and easier to use. The web interface to Fossil is a practical |
| 156 | replacement to the 3rd-party "GUI Tools" that users often employ to operate |
| 157 | Git. |
| @@ -188,22 +194,29 @@ | |
| 188 | <h3>3.8 Audit Trail</h3> |
| 189 | |
| 190 | Git features the "rebase" command which can be used to change the |
| 191 | sequence of check-ins in the repository. Rebase can be used to "clean up" |
| 192 | a complex sequence of check-ins to make their intent easier for others |
| 193 | to understand. From another point of view, rebase can be used to |
| 194 | "rewrite history" - to do what |
| 195 | [http://en.wikipedia.org/wiki/Winston_Smith | Winston Smith] did for |
| 196 | a living in Orwell's novel |
| 197 | [http://en.wikipedia.org/wiki/Nineteen_Eighty-Four | 1984]. |
| 198 | |
| 199 | Fossil deliberately avoids rewriting history. Fossil strives to follow |
| 200 | the accountants philosophy of never erasing anything. Mistakes are fixed |
| 201 | by entering a correction, with an explanation of why the correction is |
| 202 | needed. This can make the history of a project messy, but it also |
| 203 | makes it more honest. The lack of a "rebase" function is considered |
| 204 | a feature of Fossil, not a bug. |
| 205 | |
| 206 | <h3>3.9 License</h3> |
| 207 | |
| 208 | Both Git and Fossil are open-source. Git is under |
| 209 | [http://www.gnu.org/licenses/gpl.html | GPL] whereas Fossil is |
| 210 |
| --- www/fossil-v-git.wiki | |
| +++ www/fossil-v-git.wiki | |
| @@ -35,11 +35,11 @@ | |
| 35 | <h3>3.1 Feature Set</h3> |
| 36 | |
| 37 | Git provides file versioning services only, whereas Fossil adds an |
| 38 | integrated [./wikitheory.wiki | wiki], |
| 39 | [./bugtheory.wiki | ticketing & bug tracking], |
| 40 | [./embeddeddoc.wiki | embedded documentation], and |
| 41 | [./event.wiki | News/Blog features]. |
| 42 | These additional capabilities are available for Git as 3rd-party |
| 43 | user-installed add-ons, but with Fossil they are integrated into |
| 44 | the design. One way to describe Fossil is that it is |
| 45 | "[https://github.com/ | github]-in-a-box". |
| @@ -74,11 +74,11 @@ | |
| 74 | until they reach the master branch. |
| 75 | |
| 76 | Fossil is designed for smaller and non-hierarchical teams where all |
| 77 | developers are operating directly on the master branch, or at most |
| 78 | a small number of well defined branches. |
| 79 | The [./concepts.wiki#workflow | autosync] mode of Fossil makes it easy |
| 80 | for multiple developers to work on a single branch and maintain |
| 81 | linear development on that branch and avoid needless forking |
| 82 | and merging. |
| 83 | |
| 84 | <h3>3.3 Branches</h3> |
| @@ -115,13 +115,18 @@ | |
| 115 | The Git approach scales much better for large projects like the Linux |
| 116 | kernel with thousands of contributors who in many cases don't even know |
| 117 | each others names. The integrators serve a gatekeeper role to help keep |
| 118 | undesirable code out of the official Linux source tree. On the other hand, |
| 119 | not many projects are as big or as loosely organized as the Linux kernel. |
| 120 | Most projects have a small team of developers who all know each other |
| 121 | well and trust each other, and who enjoy working together collaboratively |
| 122 | without the overhead and hierarchy of integrators. |
| 123 | |
| 124 | One consequence of the "everybody-sees-everything" focus of Fossil is that |
| 125 | branch names are global and are part of the distributed and synchronized |
| 126 | content of a Fossil repository, rather than being private and user-specific |
| 127 | as they are in Git. |
| 128 | |
| 129 | <h3>3.4 Complexity</h3> |
| 130 | |
| 131 | Git is a complex system. It can be tricky to use and requires a fair |
| 132 | amount of knowledge and experience to master. Fossil strives to be |
| @@ -139,19 +144,20 @@ | |
| 144 | Git requires the developer to maintain a more complex mental model than |
| 145 | most other DVCSes. Git takes longer to learn. And you have to spend |
| 146 | more time thinking about what you are doing with Git. |
| 147 | |
| 148 | Fossil strives for simplicity. Fossil wants to be easy to learn and to |
| 149 | require little thinking about how to operating it. |
| 150 | [./quotes.wiki | Reports from the field] |
| 151 | indicate that Fossil is mostly successful at this effort. |
| 152 | |
| 153 | <h3>3.5 Web Interface</h3> |
| 154 | |
| 155 | Git has a web interface, but it requires a fair amount of setup and an |
| 156 | external web server. Fossil comes with a fully functional |
| 157 | [./webui.wiki | built-in web-server] |
| 158 | and a really simple mechanism (the "[/help/ui|fossil ui]" command) to |
| 159 | automatically start the web server and bring up a web browser to navigate |
| 160 | it. The web interface for Fossil is not only easier to set up, it is also |
| 161 | more powerful and easier to use. The web interface to Fossil is a practical |
| 162 | replacement to the 3rd-party "GUI Tools" that users often employ to operate |
| 163 | Git. |
| @@ -188,22 +194,29 @@ | |
| 194 | <h3>3.8 Audit Trail</h3> |
| 195 | |
| 196 | Git features the "rebase" command which can be used to change the |
| 197 | sequence of check-ins in the repository. Rebase can be used to "clean up" |
| 198 | a complex sequence of check-ins to make their intent easier for others |
| 199 | to understand. This is important if you view the history of a project |
| 200 | as part of the documentation for the project. |
| 201 | |
| 202 | Fossil takes an opposing view. Fossil views history as sacrosanct and |
| 203 | stubornly refuses to change it. |
| 204 | Fossil allows mistakes to be corrected (for example, check-in comments |
| 205 | can be revised, and check-ins can be moved onto new branches even after |
| 206 | the check-in has occurred) but the correction is an addition to the respository |
| 207 | and the original actions are preserved and displayed alongside |
| 208 | the corrections, thus preserving an historically accurate audit trail. |
| 209 | This is analogous to an accountant marking through an incorrect |
| 210 | entry in a ledger and writing in a correction beside it, rather than |
| 211 | erasing and incorrect entry. |
| 212 | |
| 213 | To put it another way, Git remembers what you should have done whereas |
| 214 | Fossil remembers what you actually did. |
| 215 | |
| 216 | The lack of a "rebase" command and the inability to rewrite history |
| 217 | is considered a feature of Fossil, not an omission or bug. |
| 218 | |
| 219 | <h3>3.9 License</h3> |
| 220 | |
| 221 | Both Git and Fossil are open-source. Git is under |
| 222 | [http://www.gnu.org/licenses/gpl.html | GPL] whereas Fossil is |
| 223 |
+5
-3
| --- www/hints.wiki | ||
| +++ www/hints.wiki | ||
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | <title>Fossil Tips And Usage Hints</title> |
| 2 | 2 | |
| 3 | - 1. Click on nodes of any timeline graph to see diffs between two | |
| 3 | + 1. Click on nodes of any timeline graph to see diffs between the two | |
| 4 | 4 | selected versions. |
| 5 | 5 | |
| 6 | 6 | 2. Add the "--tk" option to "[/help?cmd=diff | fossil diff]" commands |
| 7 | 7 | to get a pop-up |
| 8 | 8 | window containing a complete side-by-side diff. (NB: The pop-up |
| @@ -14,13 +14,15 @@ | ||
| 14 | 14 | 3. The "[/help?cmd=clean | fossil clean -f]" command makes a great |
| 15 | 15 | alternative to "make clean". |
| 16 | 16 | |
| 17 | 17 | 4. Use "[/help?cmd=all | fossil all changes]" to look for any uncommitted |
| 18 | 18 | edits in any of your Fossil projects. Use |
| 19 | - "[/help?cmd=all | fossil all sync]" on your laptop | |
| 19 | + "[/help?cmd=all | fossil all pull]" on your laptop | |
| 20 | 20 | prior to going off network (for example, on a long plane ride) |
| 21 | - to make sure you have all of content local. | |
| 21 | + to make sure you have all the latest content locally. Then run | |
| 22 | + "[/help/all|fossil all push]" when you get back online to upload | |
| 23 | + your changes. | |
| 22 | 24 | |
| 23 | 25 | 5. Sub-menu options on Timelines lets you select either 20 or 200 |
| 24 | 26 | records. But you can manual edit the "n=" query parameter in the |
| 25 | 27 | URL to get any number of records you desire. To see a complete |
| 26 | 28 | timeline graph, set n to some ridiculously large value like 10000000. |
| 27 | 29 |
| --- www/hints.wiki | |
| +++ www/hints.wiki | |
| @@ -1,8 +1,8 @@ | |
| 1 | <title>Fossil Tips And Usage Hints</title> |
| 2 | |
| 3 | 1. Click on nodes of any timeline graph to see diffs between two |
| 4 | selected versions. |
| 5 | |
| 6 | 2. Add the "--tk" option to "[/help?cmd=diff | fossil diff]" commands |
| 7 | to get a pop-up |
| 8 | window containing a complete side-by-side diff. (NB: The pop-up |
| @@ -14,13 +14,15 @@ | |
| 14 | 3. The "[/help?cmd=clean | fossil clean -f]" command makes a great |
| 15 | alternative to "make clean". |
| 16 | |
| 17 | 4. Use "[/help?cmd=all | fossil all changes]" to look for any uncommitted |
| 18 | edits in any of your Fossil projects. Use |
| 19 | "[/help?cmd=all | fossil all sync]" on your laptop |
| 20 | prior to going off network (for example, on a long plane ride) |
| 21 | to make sure you have all of content local. |
| 22 | |
| 23 | 5. Sub-menu options on Timelines lets you select either 20 or 200 |
| 24 | records. But you can manual edit the "n=" query parameter in the |
| 25 | URL to get any number of records you desire. To see a complete |
| 26 | timeline graph, set n to some ridiculously large value like 10000000. |
| 27 |
| --- www/hints.wiki | |
| +++ www/hints.wiki | |
| @@ -1,8 +1,8 @@ | |
| 1 | <title>Fossil Tips And Usage Hints</title> |
| 2 | |
| 3 | 1. Click on nodes of any timeline graph to see diffs between the two |
| 4 | selected versions. |
| 5 | |
| 6 | 2. Add the "--tk" option to "[/help?cmd=diff | fossil diff]" commands |
| 7 | to get a pop-up |
| 8 | window containing a complete side-by-side diff. (NB: The pop-up |
| @@ -14,13 +14,15 @@ | |
| 14 | 3. The "[/help?cmd=clean | fossil clean -f]" command makes a great |
| 15 | alternative to "make clean". |
| 16 | |
| 17 | 4. Use "[/help?cmd=all | fossil all changes]" to look for any uncommitted |
| 18 | edits in any of your Fossil projects. Use |
| 19 | "[/help?cmd=all | fossil all pull]" on your laptop |
| 20 | prior to going off network (for example, on a long plane ride) |
| 21 | to make sure you have all the latest content locally. Then run |
| 22 | "[/help/all|fossil all push]" when you get back online to upload |
| 23 | your changes. |
| 24 | |
| 25 | 5. Sub-menu options on Timelines lets you select either 20 or 200 |
| 26 | records. But you can manual edit the "n=" query parameter in the |
| 27 | URL to get any number of records you desire. To see a complete |
| 28 | timeline graph, set n to some ridiculously large value like 10000000. |
| 29 |
+7
| --- www/makefile.wiki | ||
| +++ www/makefile.wiki | ||
| @@ -12,10 +12,11 @@ | ||
| 12 | 12 | So must people do not need to be concerned with the |
| 13 | 13 | build complexities of Fossil. But hard-core developers who desire |
| 14 | 14 | a deep understanding of how Fossil is put together can benefit |
| 15 | 15 | from reviewing this article. |
| 16 | 16 | |
| 17 | +<a name="srctour"></a> | |
| 17 | 18 | <h1>2.0 Source Code Tour</h1> |
| 18 | 19 | |
| 19 | 20 | The source code for Fossil is found in the |
| 20 | 21 | [/dir?ci=trunk&name=src | src/] subdirectory of the |
| 21 | 22 | source tree. The src/ subdirectory contains all code, including |
| @@ -117,10 +118,11 @@ | ||
| 117 | 118 | directories right. The point is that the manifest.uuid, manifest, and |
| 118 | 119 | VERSION files |
| 119 | 120 | in the root of the source tree are the three arguments and |
| 120 | 121 | the generated VERSION.h file appears on standard output. |
| 121 | 122 | |
| 123 | +<a name="preprocessing"></a> | |
| 122 | 124 | <h1>4.0 Preprocessing</h1> |
| 123 | 125 | |
| 124 | 126 | There are three preprocessors for the Fossil sources. The mkindex |
| 125 | 127 | and translate preprocessors can be run in any order. The makeheaders |
| 126 | 128 | preprocessor must be run after translate. |
| @@ -236,5 +238,10 @@ | ||
| 236 | 238 | Fossil needs to be linked against [http://www.zlib.net | zlib]. If |
| 237 | 239 | the HTTPS option is enabled, then it will also need to link against |
| 238 | 240 | the appropriate SSL implementation. And, of course, Fossil needs to |
| 239 | 241 | link against the standard C library. No other libraries or external |
| 240 | 242 | dependences are used. |
| 243 | + | |
| 244 | +<h1>7.0 See Also</h1> | |
| 245 | + | |
| 246 | + * [./tech_overview.wiki | A Technical Overview Of Fossil] | |
| 247 | + * [./adding_code.wiki | How To Add Features To Fossil] | |
| 241 | 248 |
| --- www/makefile.wiki | |
| +++ www/makefile.wiki | |
| @@ -12,10 +12,11 @@ | |
| 12 | So must people do not need to be concerned with the |
| 13 | build complexities of Fossil. But hard-core developers who desire |
| 14 | a deep understanding of how Fossil is put together can benefit |
| 15 | from reviewing this article. |
| 16 | |
| 17 | <h1>2.0 Source Code Tour</h1> |
| 18 | |
| 19 | The source code for Fossil is found in the |
| 20 | [/dir?ci=trunk&name=src | src/] subdirectory of the |
| 21 | source tree. The src/ subdirectory contains all code, including |
| @@ -117,10 +118,11 @@ | |
| 117 | directories right. The point is that the manifest.uuid, manifest, and |
| 118 | VERSION files |
| 119 | in the root of the source tree are the three arguments and |
| 120 | the generated VERSION.h file appears on standard output. |
| 121 | |
| 122 | <h1>4.0 Preprocessing</h1> |
| 123 | |
| 124 | There are three preprocessors for the Fossil sources. The mkindex |
| 125 | and translate preprocessors can be run in any order. The makeheaders |
| 126 | preprocessor must be run after translate. |
| @@ -236,5 +238,10 @@ | |
| 236 | Fossil needs to be linked against [http://www.zlib.net | zlib]. If |
| 237 | the HTTPS option is enabled, then it will also need to link against |
| 238 | the appropriate SSL implementation. And, of course, Fossil needs to |
| 239 | link against the standard C library. No other libraries or external |
| 240 | dependences are used. |
| 241 |
| --- www/makefile.wiki | |
| +++ www/makefile.wiki | |
| @@ -12,10 +12,11 @@ | |
| 12 | So must people do not need to be concerned with the |
| 13 | build complexities of Fossil. But hard-core developers who desire |
| 14 | a deep understanding of how Fossil is put together can benefit |
| 15 | from reviewing this article. |
| 16 | |
| 17 | <a name="srctour"></a> |
| 18 | <h1>2.0 Source Code Tour</h1> |
| 19 | |
| 20 | The source code for Fossil is found in the |
| 21 | [/dir?ci=trunk&name=src | src/] subdirectory of the |
| 22 | source tree. The src/ subdirectory contains all code, including |
| @@ -117,10 +118,11 @@ | |
| 118 | directories right. The point is that the manifest.uuid, manifest, and |
| 119 | VERSION files |
| 120 | in the root of the source tree are the three arguments and |
| 121 | the generated VERSION.h file appears on standard output. |
| 122 | |
| 123 | <a name="preprocessing"></a> |
| 124 | <h1>4.0 Preprocessing</h1> |
| 125 | |
| 126 | There are three preprocessors for the Fossil sources. The mkindex |
| 127 | and translate preprocessors can be run in any order. The makeheaders |
| 128 | preprocessor must be run after translate. |
| @@ -236,5 +238,10 @@ | |
| 238 | Fossil needs to be linked against [http://www.zlib.net | zlib]. If |
| 239 | the HTTPS option is enabled, then it will also need to link against |
| 240 | the appropriate SSL implementation. And, of course, Fossil needs to |
| 241 | link against the standard C library. No other libraries or external |
| 242 | dependences are used. |
| 243 | |
| 244 | <h1>7.0 See Also</h1> |
| 245 | |
| 246 | * [./tech_overview.wiki | A Technical Overview Of Fossil] |
| 247 | * [./adding_code.wiki | How To Add Features To Fossil] |
| 248 |
+2
| --- www/mkindex.tcl | ||
| +++ www/mkindex.tcl | ||
| @@ -5,10 +5,12 @@ | ||
| 5 | 5 | # |
| 6 | 6 | # tclsh mkindex.tcl >permutedindex.wiki |
| 7 | 7 | # |
| 8 | 8 | |
| 9 | 9 | set doclist { |
| 10 | + adding_code.wiki {Adding New Features To Fossil} | |
| 11 | + adding_code.wiki {Hacking Fossil} | |
| 10 | 12 | antibot.wiki {Defense against Spiders and Bots} |
| 11 | 13 | bugtheory.wiki {Bug Tracking In Fossil} |
| 12 | 14 | branching.wiki {Branching, Forking, Merging, and Tagging} |
| 13 | 15 | build.wiki {Compiling and Installing Fossil} |
| 14 | 16 | checkin_names.wiki {Checkin And Version Names} |
| 15 | 17 |
| --- www/mkindex.tcl | |
| +++ www/mkindex.tcl | |
| @@ -5,10 +5,12 @@ | |
| 5 | # |
| 6 | # tclsh mkindex.tcl >permutedindex.wiki |
| 7 | # |
| 8 | |
| 9 | set doclist { |
| 10 | antibot.wiki {Defense against Spiders and Bots} |
| 11 | bugtheory.wiki {Bug Tracking In Fossil} |
| 12 | branching.wiki {Branching, Forking, Merging, and Tagging} |
| 13 | build.wiki {Compiling and Installing Fossil} |
| 14 | checkin_names.wiki {Checkin And Version Names} |
| 15 |
| --- www/mkindex.tcl | |
| +++ www/mkindex.tcl | |
| @@ -5,10 +5,12 @@ | |
| 5 | # |
| 6 | # tclsh mkindex.tcl >permutedindex.wiki |
| 7 | # |
| 8 | |
| 9 | set doclist { |
| 10 | adding_code.wiki {Adding New Features To Fossil} |
| 11 | adding_code.wiki {Hacking Fossil} |
| 12 | antibot.wiki {Defense against Spiders and Bots} |
| 13 | bugtheory.wiki {Bug Tracking In Fossil} |
| 14 | branching.wiki {Branching, Forking, Merging, and Tagging} |
| 15 | build.wiki {Compiling and Installing Fossil} |
| 16 | checkin_names.wiki {Checkin And Version Names} |
| 17 |
| --- www/permutedindex.wiki | ||
| +++ www/permutedindex.wiki | ||
| @@ -13,10 +13,11 @@ | ||
| 13 | 13 | <h2>Permuted Index:</h2> |
| 14 | 14 | <ul> |
| 15 | 15 | <li><a href="fiveminutes.wiki">5 Minutes as a Single User — Update and Running in</a></li> |
| 16 | 16 | <li><a href="fossil-from-msvc.wiki">2010 IDE — Integrating Fossil in the Microsoft Express</a></li> |
| 17 | 17 | <li><a href="tech_overview.wiki">A Technical Overview Of The Design And Implementation Of Fossil</a></li> |
| 18 | +<li><a href="adding_code.wiki">Adding New Features To Fossil</a></li> | |
| 18 | 19 | <li><a href="antibot.wiki">against Spiders and Bots — Defense</a></li> |
| 19 | 20 | <li><a href="copyright-release.html">Agreement — Contributor License</a></li> |
| 20 | 21 | <li><a href="delta_encoder_algorithm.wiki">Algorithm — Fossil Delta Encoding</a></li> |
| 21 | 22 | <li><a href="fiveminutes.wiki">as a Single User — Update and Running in 5 Minutes</a></li> |
| 22 | 23 | <li><a href="faq.wiki">Asked Questions — Frequently</a></li> |
| @@ -61,10 +62,11 @@ | ||
| 61 | 62 | <li><a href="embeddeddoc.wiki">Embedded Project Documentation</a></li> |
| 62 | 63 | <li><a href="delta_encoder_algorithm.wiki">Encoding Algorithm — Fossil Delta</a></li> |
| 63 | 64 | <li><a href="event.wiki">Events</a></li> |
| 64 | 65 | <li><a href="inout.wiki">Export To And From Git — Import And</a></li> |
| 65 | 66 | <li><a href="fossil-from-msvc.wiki">Express 2010 IDE — Integrating Fossil in the Microsoft</a></li> |
| 67 | +<li><a href="adding_code.wiki">Features To Fossil — Adding New</a></li> | |
| 66 | 68 | <li><a href="fileformat.wiki">File Format — Fossil</a></li> |
| 67 | 69 | <li><a href="branching.wiki">Forking, Merging, and Tagging — Branching,</a></li> |
| 68 | 70 | <li><a href="delta_format.wiki">Format — Fossil Delta</a></li> |
| 69 | 71 | <li><a href="fileformat.wiki">Format — Fossil File</a></li> |
| 70 | 72 | <li><a href="changes.wiki">Fossil Changelog</a></li> |
| @@ -86,10 +88,11 @@ | ||
| 86 | 88 | <li><a href="fossil-v-git.wiki">Git — Fossil Versus</a></li> |
| 87 | 89 | <li><a href="inout.wiki">Git — Import And Export To And From</a></li> |
| 88 | 90 | <li><a href="quotes.wiki">Git, and DVCSes in General — Quotes: What People Are Saying About Fossil,</a></li> |
| 89 | 91 | <li><a href="quickstart.wiki">Guide — Fossil Quick Start</a></li> |
| 90 | 92 | <li><a href="style.wiki">Guidelines — Source Code Style</a></li> |
| 93 | +<li><a href="adding_code.wiki">Hacking Fossil</a></li> | |
| 91 | 94 | <li><a href="hints.wiki">Hints — Fossil Tips And Usage</a></li> |
| 92 | 95 | <li><a href="index.wiki">Home Page</a></li> |
| 93 | 96 | <li><a href="selfhost.wiki">Hosting Repositories — Fossil Self</a></li> |
| 94 | 97 | <li><a href="server.wiki">How To Configure A Fossil Server</a></li> |
| 95 | 98 | <li><a href="newrepo.wiki">How To Create A New Fossil Repository</a></li> |
| @@ -104,10 +107,11 @@ | ||
| 104 | 107 | <li><a href="password.wiki">Management And Authentication — Password</a></li> |
| 105 | 108 | <li><a href="branching.wiki">Merging, and Tagging — Branching, Forking,</a></li> |
| 106 | 109 | <li><a href="fossil-from-msvc.wiki">Microsoft Express 2010 IDE — Integrating Fossil in the</a></li> |
| 107 | 110 | <li><a href="fiveminutes.wiki">Minutes as a Single User — Update and Running in 5</a></li> |
| 108 | 111 | <li><a href="checkin_names.wiki">Names — Checkin And Version</a></li> |
| 112 | +<li><a href="adding_code.wiki">New Features To Fossil — Adding</a></li> | |
| 109 | 113 | <li><a href="newrepo.wiki">New Fossil Repository — How To Create A</a></li> |
| 110 | 114 | <li><a href="foss-cklist.wiki">Open-Source Projects — Checklist For Successful</a></li> |
| 111 | 115 | <li><a href="pop.wiki">Operations — Principles Of</a></li> |
| 112 | 116 | <li><a href="tech_overview.wiki">Overview Of The Design And Implementation Of Fossil — A Technical</a></li> |
| 113 | 117 | <li><a href="index.wiki">Page — Home</a></li> |
| 114 | 118 |
| --- www/permutedindex.wiki | |
| +++ www/permutedindex.wiki | |
| @@ -13,10 +13,11 @@ | |
| 13 | <h2>Permuted Index:</h2> |
| 14 | <ul> |
| 15 | <li><a href="fiveminutes.wiki">5 Minutes as a Single User — Update and Running in</a></li> |
| 16 | <li><a href="fossil-from-msvc.wiki">2010 IDE — Integrating Fossil in the Microsoft Express</a></li> |
| 17 | <li><a href="tech_overview.wiki">A Technical Overview Of The Design And Implementation Of Fossil</a></li> |
| 18 | <li><a href="antibot.wiki">against Spiders and Bots — Defense</a></li> |
| 19 | <li><a href="copyright-release.html">Agreement — Contributor License</a></li> |
| 20 | <li><a href="delta_encoder_algorithm.wiki">Algorithm — Fossil Delta Encoding</a></li> |
| 21 | <li><a href="fiveminutes.wiki">as a Single User — Update and Running in 5 Minutes</a></li> |
| 22 | <li><a href="faq.wiki">Asked Questions — Frequently</a></li> |
| @@ -61,10 +62,11 @@ | |
| 61 | <li><a href="embeddeddoc.wiki">Embedded Project Documentation</a></li> |
| 62 | <li><a href="delta_encoder_algorithm.wiki">Encoding Algorithm — Fossil Delta</a></li> |
| 63 | <li><a href="event.wiki">Events</a></li> |
| 64 | <li><a href="inout.wiki">Export To And From Git — Import And</a></li> |
| 65 | <li><a href="fossil-from-msvc.wiki">Express 2010 IDE — Integrating Fossil in the Microsoft</a></li> |
| 66 | <li><a href="fileformat.wiki">File Format — Fossil</a></li> |
| 67 | <li><a href="branching.wiki">Forking, Merging, and Tagging — Branching,</a></li> |
| 68 | <li><a href="delta_format.wiki">Format — Fossil Delta</a></li> |
| 69 | <li><a href="fileformat.wiki">Format — Fossil File</a></li> |
| 70 | <li><a href="changes.wiki">Fossil Changelog</a></li> |
| @@ -86,10 +88,11 @@ | |
| 86 | <li><a href="fossil-v-git.wiki">Git — Fossil Versus</a></li> |
| 87 | <li><a href="inout.wiki">Git — Import And Export To And From</a></li> |
| 88 | <li><a href="quotes.wiki">Git, and DVCSes in General — Quotes: What People Are Saying About Fossil,</a></li> |
| 89 | <li><a href="quickstart.wiki">Guide — Fossil Quick Start</a></li> |
| 90 | <li><a href="style.wiki">Guidelines — Source Code Style</a></li> |
| 91 | <li><a href="hints.wiki">Hints — Fossil Tips And Usage</a></li> |
| 92 | <li><a href="index.wiki">Home Page</a></li> |
| 93 | <li><a href="selfhost.wiki">Hosting Repositories — Fossil Self</a></li> |
| 94 | <li><a href="server.wiki">How To Configure A Fossil Server</a></li> |
| 95 | <li><a href="newrepo.wiki">How To Create A New Fossil Repository</a></li> |
| @@ -104,10 +107,11 @@ | |
| 104 | <li><a href="password.wiki">Management And Authentication — Password</a></li> |
| 105 | <li><a href="branching.wiki">Merging, and Tagging — Branching, Forking,</a></li> |
| 106 | <li><a href="fossil-from-msvc.wiki">Microsoft Express 2010 IDE — Integrating Fossil in the</a></li> |
| 107 | <li><a href="fiveminutes.wiki">Minutes as a Single User — Update and Running in 5</a></li> |
| 108 | <li><a href="checkin_names.wiki">Names — Checkin And Version</a></li> |
| 109 | <li><a href="newrepo.wiki">New Fossil Repository — How To Create A</a></li> |
| 110 | <li><a href="foss-cklist.wiki">Open-Source Projects — Checklist For Successful</a></li> |
| 111 | <li><a href="pop.wiki">Operations — Principles Of</a></li> |
| 112 | <li><a href="tech_overview.wiki">Overview Of The Design And Implementation Of Fossil — A Technical</a></li> |
| 113 | <li><a href="index.wiki">Page — Home</a></li> |
| 114 |
| --- www/permutedindex.wiki | |
| +++ www/permutedindex.wiki | |
| @@ -13,10 +13,11 @@ | |
| 13 | <h2>Permuted Index:</h2> |
| 14 | <ul> |
| 15 | <li><a href="fiveminutes.wiki">5 Minutes as a Single User — Update and Running in</a></li> |
| 16 | <li><a href="fossil-from-msvc.wiki">2010 IDE — Integrating Fossil in the Microsoft Express</a></li> |
| 17 | <li><a href="tech_overview.wiki">A Technical Overview Of The Design And Implementation Of Fossil</a></li> |
| 18 | <li><a href="adding_code.wiki">Adding New Features To Fossil</a></li> |
| 19 | <li><a href="antibot.wiki">against Spiders and Bots — Defense</a></li> |
| 20 | <li><a href="copyright-release.html">Agreement — Contributor License</a></li> |
| 21 | <li><a href="delta_encoder_algorithm.wiki">Algorithm — Fossil Delta Encoding</a></li> |
| 22 | <li><a href="fiveminutes.wiki">as a Single User — Update and Running in 5 Minutes</a></li> |
| 23 | <li><a href="faq.wiki">Asked Questions — Frequently</a></li> |
| @@ -61,10 +62,11 @@ | |
| 62 | <li><a href="embeddeddoc.wiki">Embedded Project Documentation</a></li> |
| 63 | <li><a href="delta_encoder_algorithm.wiki">Encoding Algorithm — Fossil Delta</a></li> |
| 64 | <li><a href="event.wiki">Events</a></li> |
| 65 | <li><a href="inout.wiki">Export To And From Git — Import And</a></li> |
| 66 | <li><a href="fossil-from-msvc.wiki">Express 2010 IDE — Integrating Fossil in the Microsoft</a></li> |
| 67 | <li><a href="adding_code.wiki">Features To Fossil — Adding New</a></li> |
| 68 | <li><a href="fileformat.wiki">File Format — Fossil</a></li> |
| 69 | <li><a href="branching.wiki">Forking, Merging, and Tagging — Branching,</a></li> |
| 70 | <li><a href="delta_format.wiki">Format — Fossil Delta</a></li> |
| 71 | <li><a href="fileformat.wiki">Format — Fossil File</a></li> |
| 72 | <li><a href="changes.wiki">Fossil Changelog</a></li> |
| @@ -86,10 +88,11 @@ | |
| 88 | <li><a href="fossil-v-git.wiki">Git — Fossil Versus</a></li> |
| 89 | <li><a href="inout.wiki">Git — Import And Export To And From</a></li> |
| 90 | <li><a href="quotes.wiki">Git, and DVCSes in General — Quotes: What People Are Saying About Fossil,</a></li> |
| 91 | <li><a href="quickstart.wiki">Guide — Fossil Quick Start</a></li> |
| 92 | <li><a href="style.wiki">Guidelines — Source Code Style</a></li> |
| 93 | <li><a href="adding_code.wiki">Hacking Fossil</a></li> |
| 94 | <li><a href="hints.wiki">Hints — Fossil Tips And Usage</a></li> |
| 95 | <li><a href="index.wiki">Home Page</a></li> |
| 96 | <li><a href="selfhost.wiki">Hosting Repositories — Fossil Self</a></li> |
| 97 | <li><a href="server.wiki">How To Configure A Fossil Server</a></li> |
| 98 | <li><a href="newrepo.wiki">How To Create A New Fossil Repository</a></li> |
| @@ -104,10 +107,11 @@ | |
| 107 | <li><a href="password.wiki">Management And Authentication — Password</a></li> |
| 108 | <li><a href="branching.wiki">Merging, and Tagging — Branching, Forking,</a></li> |
| 109 | <li><a href="fossil-from-msvc.wiki">Microsoft Express 2010 IDE — Integrating Fossil in the</a></li> |
| 110 | <li><a href="fiveminutes.wiki">Minutes as a Single User — Update and Running in 5</a></li> |
| 111 | <li><a href="checkin_names.wiki">Names — Checkin And Version</a></li> |
| 112 | <li><a href="adding_code.wiki">New Features To Fossil — Adding</a></li> |
| 113 | <li><a href="newrepo.wiki">New Fossil Repository — How To Create A</a></li> |
| 114 | <li><a href="foss-cklist.wiki">Open-Source Projects — Checklist For Successful</a></li> |
| 115 | <li><a href="pop.wiki">Operations — Principles Of</a></li> |
| 116 | <li><a href="tech_overview.wiki">Overview Of The Design And Implementation Of Fossil — A Technical</a></li> |
| 117 | <li><a href="index.wiki">Page — Home</a></li> |
| 118 |
+51
-26
| --- www/quickstart.wiki | ||
| +++ www/quickstart.wiki | ||
| @@ -173,13 +173,21 @@ | ||
| 173 | 173 | </blockquote> |
| 174 | 174 | |
| 175 | 175 | <p>You will be prompted for check-in comments using whatever editor |
| 176 | 176 | is specified by your VISUAL or EDITOR environment variable.</p> |
| 177 | 177 | |
| 178 | + In the default configuration, the [/help/commit|commit] | |
| 179 | + command will also automatically [/help/push|push] your changes, but that | |
| 180 | + feature can be disabled. (More information about | |
| 181 | + [./concepts.wiki#workflow|autosync] and how to disable it.) | |
| 182 | + Remember that your coworkers can not see your changes until you | |
| 183 | + commit and push them.</p> | |
| 184 | + | |
| 178 | 185 | <h2>Sharing Changes</h2> |
| 179 | 186 | |
| 180 | - <p>The changes you [/help/commit | commit] are only | |
| 187 | + <p>When [./concepts.wiki#workflow|autosync] is turned off, | |
| 188 | + the changes you [/help/commit | commit] are only | |
| 181 | 189 | on your local repository. |
| 182 | 190 | To share those changes with other repositories, do:</p> |
| 183 | 191 | |
| 184 | 192 | <blockquote> |
| 185 | 193 | <b>[/help/push | fossil push]</b> <i>URL</i> |
| @@ -212,10 +220,17 @@ | ||
| 212 | 220 | date/time stamp. ([./checkin_names.wiki | more info]) |
| 213 | 221 | If you omit |
| 214 | 222 | the <i>VERSION</i>, then fossil moves you to the |
| 215 | 223 | latest version of the branch your are currently on.</p> |
| 216 | 224 | |
| 225 | + <p>The default behaviors is for [./concepts.wiki#workflow|autosync] to | |
| 226 | + be turned on. That means that a [/help/pull|pull] automatically occurs | |
| 227 | + when you run [/help/update|update] and a [/help/push|push] happens | |
| 228 | + automatically after you [/help/commit|commit]. So in normal practice, | |
| 229 | + the push, pull, and sync commands are rarely used. But it is important | |
| 230 | + to know about them, all the same.</p> | |
| 231 | + | |
| 217 | 232 | <h2>Branching And Merging</h2> |
| 218 | 233 | |
| 219 | 234 | <p>Use the --branch option to the [/help/commit | commit] command |
| 220 | 235 | to start a new branch. Note that in Fossil, branches are normally |
| 221 | 236 | created when you commit, not before you start editing. You can |
| @@ -222,36 +237,43 @@ | ||
| 222 | 237 | use the [/help/branch | branch new] command to create a new branch |
| 223 | 238 | before you start editing, if you want, but most people just wait |
| 224 | 239 | until they are ready to commit. |
| 225 | 240 | |
| 226 | 241 | To merge two branches back together, first |
| 227 | - [/help/update | update] to the leaf of one branch. Then do a | |
| 228 | - [/help/merge | merge] of the leaf of the other branch:</p> | |
| 242 | + [/help/update | update] to the branch you want to merge into. | |
| 243 | + Then do a [/help/merge|merge] another branch that you want to incorporate | |
| 244 | + the changes from. For example, to merge "featureX" changes into "trunk" | |
| 245 | + do this:</p> | |
| 229 | 246 | |
| 230 | 247 | <blockquote> |
| 231 | - <b>[/help/merge | fossil merge]</b> <i>VERSION</i> | |
| 248 | + <b>fossil [/help/update|update] trunk</b><br> | |
| 249 | + <b>fossil [/help/merge|merge] featureX</b><br> | |
| 250 | + <i># make sure the merge didn't break anything...</i><br> | |
| 251 | + <b>fossil [/help/commit|commit] | |
| 232 | 252 | </blockquote> |
| 233 | 253 | |
| 234 | - <p>The <i>VERSION</i> can be any of the forms allowed for | |
| 235 | - [/help/update | update]. | |
| 236 | - After performing the merge, you will normally want to test it to | |
| 237 | - make sure it does not break anything, then | |
| 238 | - [/help/commit | commit] your changes. | |
| 239 | - In the default configuration, the [/help/commit|commit] | |
| 240 | - command will also automatically [/help/push|push] your changes, but that | |
| 241 | - feature can be disabled. (More information about | |
| 242 | - [./concepts.wiki#workflow|autosync] and how to disable it.) | |
| 243 | - Remember that your coworkers can not see your changes until you | |
| 244 | - commit and push them.</p> | |
| 245 | - | |
| 246 | - <p>The merge command has options to cherrypick individual | |
| 247 | - changes, or to back out individual changes.</p> | |
| 248 | - | |
| 249 | - <p>Note that the merge command changes only your local check-out. | |
| 250 | - The merge command does <em>not</em> modify the repository in any way. | |
| 251 | - You must do a separate [/help/commit | commit] after the merge in order | |
| 252 | - to put the merged code back into the repository.</p> | |
| 254 | + <p>The argument to the [/help/merge|merge] command can be any of the | |
| 255 | + version identifier forms that work for [/help/update|update]. | |
| 256 | + ([./checkin_names.wiki|more info].) | |
| 257 | + The merge command has options to cherrypick individual | |
| 258 | + changes, or to back out individual changes, if you don't want to | |
| 259 | + do a full merge.</p> | |
| 260 | + | |
| 261 | + The merge command puts all changes in your working check-out. | |
| 262 | + No changes are made to the repository. | |
| 263 | + You must run [/help/commit|commit] separately | |
| 264 | + to add the merge changes into your repository to make them persistent | |
| 265 | + and so that your coworkers can see them. | |
| 266 | + But before you do that, you will normally want to run a few tests | |
| 267 | + to verify that the merge didn't cause logic breaks in your code. | |
| 268 | + | |
| 269 | + The same branch can be merged multiple times without trouble. Fossil | |
| 270 | + automatically keeps up with things and avoids conflicts when doing | |
| 271 | + multiple merges. So even if you have merged the featureX branch | |
| 272 | + into trunk previously, you can do so again and Fossil will automatically | |
| 273 | + know to pull in only those changes that have occurred since the previous | |
| 274 | + merge. | |
| 253 | 275 | |
| 254 | 276 | <p>If a merge or update doesn't work out (perhaps something breaks or |
| 255 | 277 | there are many merge conflicts) then you back up using:</p> |
| 256 | 278 | |
| 257 | 279 | <blockquote> |
| @@ -280,11 +302,11 @@ | ||
| 280 | 302 | <b>[/help/ui | fossil ui]</b> <i>repository-filename</i> |
| 281 | 303 | </blockquote> |
| 282 | 304 | |
| 283 | 305 | <p>The <b>ui</b> command is intended for accessing the web interface |
| 284 | 306 | from a local desktop. The <b>ui</b> command binds to the loopback IP |
| 285 | - address only (and is thus makes the web interface visible only on the | |
| 307 | + address only (and thus makes the web interface visible only on the | |
| 286 | 308 | local machine) and it automatically start your web browser pointing at the |
| 287 | 309 | server. For cross-machine collaboration, use the <b>server</b> command, |
| 288 | 310 | which binds on all IP addresses and does not try to start a web browser. |
| 289 | 311 | You can omit the <i>repository-filename</i> if you are within |
| 290 | 312 | a checked-out local tree. The <b>server</b> uses port 8080 by default |
| @@ -321,11 +343,11 @@ | ||
| 321 | 343 | <p>Adjust the paths to suit your installation, of course. Notice that |
| 322 | 344 | fossil runs as root. This is not required - you can run it as an |
| 323 | 345 | unprivileged user. But it is more secure to run fossil as root. |
| 324 | 346 | When you do run fossil as root, it automatically puts itself in a |
| 325 | 347 | chroot jail in the same directory as the repository, then drops |
| 326 | - root privileges prior to reading any information from the request.</p> | |
| 348 | + root privileges prior to reading any information from the socket.</p> | |
| 327 | 349 | |
| 328 | 350 | <a name="proxy"></a> |
| 329 | 351 | <h2>HTTP Proxies</h2> |
| 330 | 352 | |
| 331 | 353 | <p>If you are behind a restrictive firewall that requires you to use |
| @@ -369,8 +391,11 @@ | ||
| 369 | 391 | <b>fossil sync http://192.168.1.36:8080/ --proxy off</b> |
| 370 | 392 | </blockquote> |
| 371 | 393 | |
| 372 | 394 | <h2>More Hints</h2> |
| 373 | 395 | |
| 374 | - <p>A [/help | complete list of commands] is available. | |
| 396 | + <p>A [/help | complete list of commands] is available, as is the | |
| 397 | + [./hints.wiki|helpful hints] document. See the | |
| 398 | + [./permutedindex.wiki#pindex|permuted index] for additional | |
| 399 | + documentation. | |
| 375 | 400 | |
| 376 | 401 | <p>Explore and have fun!</p> |
| 377 | 402 |
| --- www/quickstart.wiki | |
| +++ www/quickstart.wiki | |
| @@ -173,13 +173,21 @@ | |
| 173 | </blockquote> |
| 174 | |
| 175 | <p>You will be prompted for check-in comments using whatever editor |
| 176 | is specified by your VISUAL or EDITOR environment variable.</p> |
| 177 | |
| 178 | <h2>Sharing Changes</h2> |
| 179 | |
| 180 | <p>The changes you [/help/commit | commit] are only |
| 181 | on your local repository. |
| 182 | To share those changes with other repositories, do:</p> |
| 183 | |
| 184 | <blockquote> |
| 185 | <b>[/help/push | fossil push]</b> <i>URL</i> |
| @@ -212,10 +220,17 @@ | |
| 212 | date/time stamp. ([./checkin_names.wiki | more info]) |
| 213 | If you omit |
| 214 | the <i>VERSION</i>, then fossil moves you to the |
| 215 | latest version of the branch your are currently on.</p> |
| 216 | |
| 217 | <h2>Branching And Merging</h2> |
| 218 | |
| 219 | <p>Use the --branch option to the [/help/commit | commit] command |
| 220 | to start a new branch. Note that in Fossil, branches are normally |
| 221 | created when you commit, not before you start editing. You can |
| @@ -222,36 +237,43 @@ | |
| 222 | use the [/help/branch | branch new] command to create a new branch |
| 223 | before you start editing, if you want, but most people just wait |
| 224 | until they are ready to commit. |
| 225 | |
| 226 | To merge two branches back together, first |
| 227 | [/help/update | update] to the leaf of one branch. Then do a |
| 228 | [/help/merge | merge] of the leaf of the other branch:</p> |
| 229 | |
| 230 | <blockquote> |
| 231 | <b>[/help/merge | fossil merge]</b> <i>VERSION</i> |
| 232 | </blockquote> |
| 233 | |
| 234 | <p>The <i>VERSION</i> can be any of the forms allowed for |
| 235 | [/help/update | update]. |
| 236 | After performing the merge, you will normally want to test it to |
| 237 | make sure it does not break anything, then |
| 238 | [/help/commit | commit] your changes. |
| 239 | In the default configuration, the [/help/commit|commit] |
| 240 | command will also automatically [/help/push|push] your changes, but that |
| 241 | feature can be disabled. (More information about |
| 242 | [./concepts.wiki#workflow|autosync] and how to disable it.) |
| 243 | Remember that your coworkers can not see your changes until you |
| 244 | commit and push them.</p> |
| 245 | |
| 246 | <p>The merge command has options to cherrypick individual |
| 247 | changes, or to back out individual changes.</p> |
| 248 | |
| 249 | <p>Note that the merge command changes only your local check-out. |
| 250 | The merge command does <em>not</em> modify the repository in any way. |
| 251 | You must do a separate [/help/commit | commit] after the merge in order |
| 252 | to put the merged code back into the repository.</p> |
| 253 | |
| 254 | <p>If a merge or update doesn't work out (perhaps something breaks or |
| 255 | there are many merge conflicts) then you back up using:</p> |
| 256 | |
| 257 | <blockquote> |
| @@ -280,11 +302,11 @@ | |
| 280 | <b>[/help/ui | fossil ui]</b> <i>repository-filename</i> |
| 281 | </blockquote> |
| 282 | |
| 283 | <p>The <b>ui</b> command is intended for accessing the web interface |
| 284 | from a local desktop. The <b>ui</b> command binds to the loopback IP |
| 285 | address only (and is thus makes the web interface visible only on the |
| 286 | local machine) and it automatically start your web browser pointing at the |
| 287 | server. For cross-machine collaboration, use the <b>server</b> command, |
| 288 | which binds on all IP addresses and does not try to start a web browser. |
| 289 | You can omit the <i>repository-filename</i> if you are within |
| 290 | a checked-out local tree. The <b>server</b> uses port 8080 by default |
| @@ -321,11 +343,11 @@ | |
| 321 | <p>Adjust the paths to suit your installation, of course. Notice that |
| 322 | fossil runs as root. This is not required - you can run it as an |
| 323 | unprivileged user. But it is more secure to run fossil as root. |
| 324 | When you do run fossil as root, it automatically puts itself in a |
| 325 | chroot jail in the same directory as the repository, then drops |
| 326 | root privileges prior to reading any information from the request.</p> |
| 327 | |
| 328 | <a name="proxy"></a> |
| 329 | <h2>HTTP Proxies</h2> |
| 330 | |
| 331 | <p>If you are behind a restrictive firewall that requires you to use |
| @@ -369,8 +391,11 @@ | |
| 369 | <b>fossil sync http://192.168.1.36:8080/ --proxy off</b> |
| 370 | </blockquote> |
| 371 | |
| 372 | <h2>More Hints</h2> |
| 373 | |
| 374 | <p>A [/help | complete list of commands] is available. |
| 375 | |
| 376 | <p>Explore and have fun!</p> |
| 377 |
| --- www/quickstart.wiki | |
| +++ www/quickstart.wiki | |
| @@ -173,13 +173,21 @@ | |
| 173 | </blockquote> |
| 174 | |
| 175 | <p>You will be prompted for check-in comments using whatever editor |
| 176 | is specified by your VISUAL or EDITOR environment variable.</p> |
| 177 | |
| 178 | In the default configuration, the [/help/commit|commit] |
| 179 | command will also automatically [/help/push|push] your changes, but that |
| 180 | feature can be disabled. (More information about |
| 181 | [./concepts.wiki#workflow|autosync] and how to disable it.) |
| 182 | Remember that your coworkers can not see your changes until you |
| 183 | commit and push them.</p> |
| 184 | |
| 185 | <h2>Sharing Changes</h2> |
| 186 | |
| 187 | <p>When [./concepts.wiki#workflow|autosync] is turned off, |
| 188 | the changes you [/help/commit | commit] are only |
| 189 | on your local repository. |
| 190 | To share those changes with other repositories, do:</p> |
| 191 | |
| 192 | <blockquote> |
| 193 | <b>[/help/push | fossil push]</b> <i>URL</i> |
| @@ -212,10 +220,17 @@ | |
| 220 | date/time stamp. ([./checkin_names.wiki | more info]) |
| 221 | If you omit |
| 222 | the <i>VERSION</i>, then fossil moves you to the |
| 223 | latest version of the branch your are currently on.</p> |
| 224 | |
| 225 | <p>The default behaviors is for [./concepts.wiki#workflow|autosync] to |
| 226 | be turned on. That means that a [/help/pull|pull] automatically occurs |
| 227 | when you run [/help/update|update] and a [/help/push|push] happens |
| 228 | automatically after you [/help/commit|commit]. So in normal practice, |
| 229 | the push, pull, and sync commands are rarely used. But it is important |
| 230 | to know about them, all the same.</p> |
| 231 | |
| 232 | <h2>Branching And Merging</h2> |
| 233 | |
| 234 | <p>Use the --branch option to the [/help/commit | commit] command |
| 235 | to start a new branch. Note that in Fossil, branches are normally |
| 236 | created when you commit, not before you start editing. You can |
| @@ -222,36 +237,43 @@ | |
| 237 | use the [/help/branch | branch new] command to create a new branch |
| 238 | before you start editing, if you want, but most people just wait |
| 239 | until they are ready to commit. |
| 240 | |
| 241 | To merge two branches back together, first |
| 242 | [/help/update | update] to the branch you want to merge into. |
| 243 | Then do a [/help/merge|merge] another branch that you want to incorporate |
| 244 | the changes from. For example, to merge "featureX" changes into "trunk" |
| 245 | do this:</p> |
| 246 | |
| 247 | <blockquote> |
| 248 | <b>fossil [/help/update|update] trunk</b><br> |
| 249 | <b>fossil [/help/merge|merge] featureX</b><br> |
| 250 | <i># make sure the merge didn't break anything...</i><br> |
| 251 | <b>fossil [/help/commit|commit] |
| 252 | </blockquote> |
| 253 | |
| 254 | <p>The argument to the [/help/merge|merge] command can be any of the |
| 255 | version identifier forms that work for [/help/update|update]. |
| 256 | ([./checkin_names.wiki|more info].) |
| 257 | The merge command has options to cherrypick individual |
| 258 | changes, or to back out individual changes, if you don't want to |
| 259 | do a full merge.</p> |
| 260 | |
| 261 | The merge command puts all changes in your working check-out. |
| 262 | No changes are made to the repository. |
| 263 | You must run [/help/commit|commit] separately |
| 264 | to add the merge changes into your repository to make them persistent |
| 265 | and so that your coworkers can see them. |
| 266 | But before you do that, you will normally want to run a few tests |
| 267 | to verify that the merge didn't cause logic breaks in your code. |
| 268 | |
| 269 | The same branch can be merged multiple times without trouble. Fossil |
| 270 | automatically keeps up with things and avoids conflicts when doing |
| 271 | multiple merges. So even if you have merged the featureX branch |
| 272 | into trunk previously, you can do so again and Fossil will automatically |
| 273 | know to pull in only those changes that have occurred since the previous |
| 274 | merge. |
| 275 | |
| 276 | <p>If a merge or update doesn't work out (perhaps something breaks or |
| 277 | there are many merge conflicts) then you back up using:</p> |
| 278 | |
| 279 | <blockquote> |
| @@ -280,11 +302,11 @@ | |
| 302 | <b>[/help/ui | fossil ui]</b> <i>repository-filename</i> |
| 303 | </blockquote> |
| 304 | |
| 305 | <p>The <b>ui</b> command is intended for accessing the web interface |
| 306 | from a local desktop. The <b>ui</b> command binds to the loopback IP |
| 307 | address only (and thus makes the web interface visible only on the |
| 308 | local machine) and it automatically start your web browser pointing at the |
| 309 | server. For cross-machine collaboration, use the <b>server</b> command, |
| 310 | which binds on all IP addresses and does not try to start a web browser. |
| 311 | You can omit the <i>repository-filename</i> if you are within |
| 312 | a checked-out local tree. The <b>server</b> uses port 8080 by default |
| @@ -321,11 +343,11 @@ | |
| 343 | <p>Adjust the paths to suit your installation, of course. Notice that |
| 344 | fossil runs as root. This is not required - you can run it as an |
| 345 | unprivileged user. But it is more secure to run fossil as root. |
| 346 | When you do run fossil as root, it automatically puts itself in a |
| 347 | chroot jail in the same directory as the repository, then drops |
| 348 | root privileges prior to reading any information from the socket.</p> |
| 349 | |
| 350 | <a name="proxy"></a> |
| 351 | <h2>HTTP Proxies</h2> |
| 352 | |
| 353 | <p>If you are behind a restrictive firewall that requires you to use |
| @@ -369,8 +391,11 @@ | |
| 391 | <b>fossil sync http://192.168.1.36:8080/ --proxy off</b> |
| 392 | </blockquote> |
| 393 | |
| 394 | <h2>More Hints</h2> |
| 395 | |
| 396 | <p>A [/help | complete list of commands] is available, as is the |
| 397 | [./hints.wiki|helpful hints] document. See the |
| 398 | [./permutedindex.wiki#pindex|permuted index] for additional |
| 399 | documentation. |
| 400 | |
| 401 | <p>Explore and have fun!</p> |
| 402 |
+2
-1
| --- www/server.wiki | ||
| +++ www/server.wiki | ||
| @@ -107,11 +107,12 @@ | ||
| 107 | 107 | <h2>Various security concerns with hosted repositories</h2><blockquote> |
| 108 | 108 | <p> |
| 109 | 109 | There are two main concerns relating to usage of Fossil for sharing sensitive information (source or any other data): |
| 110 | 110 | <ul> |
| 111 | 111 | <li>Interception of the Fossil synchronization stream, thereby capturing data, and |
| 112 | -</ul>Direct access to the Fossil repository on the server | |
| 112 | +<li>Direct access to the Fossil repository on the server | |
| 113 | +</ul> | |
| 113 | 114 | </p> |
| 114 | 115 | <p> |
| 115 | 116 | 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). |
| 116 | 117 | </p> |
| 117 | 118 | <p> |
| 118 | 119 |
| --- www/server.wiki | |
| +++ www/server.wiki | |
| @@ -107,11 +107,12 @@ | |
| 107 | <h2>Various security concerns with hosted repositories</h2><blockquote> |
| 108 | <p> |
| 109 | There are two main concerns relating to usage of Fossil for sharing sensitive information (source or any other data): |
| 110 | <ul> |
| 111 | <li>Interception of the Fossil synchronization stream, thereby capturing data, and |
| 112 | </ul>Direct access to the Fossil repository on the server |
| 113 | </p> |
| 114 | <p> |
| 115 | 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). |
| 116 | </p> |
| 117 | <p> |
| 118 |
| --- www/server.wiki | |
| +++ www/server.wiki | |
| @@ -107,11 +107,12 @@ | |
| 107 | <h2>Various security concerns with hosted repositories</h2><blockquote> |
| 108 | <p> |
| 109 | There are two main concerns relating to usage of Fossil for sharing sensitive information (source or any other data): |
| 110 | <ul> |
| 111 | <li>Interception of the Fossil synchronization stream, thereby capturing data, and |
| 112 | <li>Direct access to the Fossil repository on the server |
| 113 | </ul> |
| 114 | </p> |
| 115 | <p> |
| 116 | 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). |
| 117 | </p> |
| 118 | <p> |
| 119 |
| --- www/tech_overview.wiki | ||
| +++ www/tech_overview.wiki | ||
| @@ -332,5 +332,11 @@ | ||
| 332 | 332 | |
| 333 | 333 | Note that the stash, the undo stack, and the state of the bisect command |
| 334 | 334 | are all contained within the checkout database. That means that the |
| 335 | 335 | fossil close command will delete all stash content, the undo stack, and |
| 336 | 336 | the bisect state. The close command is not undoable. Use it with care. |
| 337 | + | |
| 338 | +<h2>3.0 See Also</h2> | |
| 339 | + | |
| 340 | + * [./makefile.wiki | The Fossil Build Process] | |
| 341 | + * [./contribute.wiki | How To Contribute Code To Fossil] | |
| 342 | + * [./adding_code.wiki | Adding New Features To Fossil] | |
| 337 | 343 |
| --- www/tech_overview.wiki | |
| +++ www/tech_overview.wiki | |
| @@ -332,5 +332,11 @@ | |
| 332 | |
| 333 | Note that the stash, the undo stack, and the state of the bisect command |
| 334 | are all contained within the checkout database. That means that the |
| 335 | fossil close command will delete all stash content, the undo stack, and |
| 336 | the bisect state. The close command is not undoable. Use it with care. |
| 337 |
| --- www/tech_overview.wiki | |
| +++ www/tech_overview.wiki | |
| @@ -332,5 +332,11 @@ | |
| 332 | |
| 333 | Note that the stash, the undo stack, and the state of the bisect command |
| 334 | are all contained within the checkout database. That means that the |
| 335 | fossil close command will delete all stash content, the undo stack, and |
| 336 | the bisect state. The close command is not undoable. Use it with care. |
| 337 | |
| 338 | <h2>3.0 See Also</h2> |
| 339 | |
| 340 | * [./makefile.wiki | The Fossil Build Process] |
| 341 | * [./contribute.wiki | How To Contribute Code To Fossil] |
| 342 | * [./adding_code.wiki | Adding New Features To Fossil] |
| 343 |