Fossil SCM

merge trunk

jan.nijtmans 2012-11-12 13:19 improve_commit_warning merge
Commit aaa1cb04dd7139d389e0d252a2320e3a6481fbc5
+36 -4
--- src/add.c
+++ src/add.c
@@ -60,22 +60,39 @@
6060
static const char *const azManifest[] = {
6161
"manifest",
6262
"manifest.uuid",
6363
};
6464
65
+ /*
66
+ ** Names of repository files, if they exist in the checkout.
67
+ */
68
+ static const char *azRepo[4] = { 0, 0, 0, 0 };
69
+
6570
/* Cached setting "manifest" */
6671
static int cachedManifest = -1;
6772
6873
if( cachedManifest == -1 ){
74
+ Blob repo;
6975
cachedManifest = db_get_boolean("manifest",0);
76
+ blob_zero(&repo);
77
+ if( file_tree_name(g.zRepositoryName, &repo, 0) ){
78
+ const char *zRepo = blob_str(&repo);
79
+ azRepo[0] = zRepo;
80
+ azRepo[1] = mprintf("%s-journal", zRepo);
81
+ azRepo[2] = mprintf("%s-wal", zRepo);
82
+ azRepo[3] = mprintf("%s-shm", zRepo);
83
+ }
7084
}
7185
72
- if( N>=0 && N<count(azName) ) return azName[N];
73
- if( N>=count(azName) && N<count(azName)+count(azManifest)
74
- && cachedManifest ){
75
- return azManifest[N-count(azName)];
86
+ if( N<0 ) return 0;
87
+ if( N<count(azName) ) return azName[N];
88
+ N -= count(azName);
89
+ if( cachedManifest ){
90
+ if( N<count(azManifest) ) return azManifest[N];
91
+ N -= count(azManifest);
7692
}
93
+ if( N<count(azRepo) ) return azRepo[N];
7794
return 0;
7895
}
7996
8097
/*
8198
** Return a list of all reserved filenames as an SQL list.
@@ -93,10 +110,25 @@
93110
}
94111
zAll = blob_str(&x);
95112
}
96113
return zAll;
97114
}
115
+
116
+/*
117
+** COMMAND: test-reserved-names
118
+**
119
+** Show all reserved filenames for the current check-out.
120
+*/
121
+void test_reserved_names(void){
122
+ int i;
123
+ const char *z;
124
+ db_must_be_within_tree();
125
+ for(i=0; (z = fossil_reserved_name(i))!=0; i++){
126
+ fossil_print("%3d: %s\n", i, z);
127
+ }
128
+ fossil_print("ALL: (%s)\n", fossil_all_reserved_names());
129
+}
98130
99131
/*
100132
** Add a single file named zName to the VFILE table with vid.
101133
**
102134
** Omit any file whose name is pOmit.
103135
--- src/add.c
+++ src/add.c
@@ -60,22 +60,39 @@
60 static const char *const azManifest[] = {
61 "manifest",
62 "manifest.uuid",
63 };
64
 
 
 
 
 
65 /* Cached setting "manifest" */
66 static int cachedManifest = -1;
67
68 if( cachedManifest == -1 ){
 
69 cachedManifest = db_get_boolean("manifest",0);
 
 
 
 
 
 
 
 
70 }
71
72 if( N>=0 && N<count(azName) ) return azName[N];
73 if( N>=count(azName) && N<count(azName)+count(azManifest)
74 && cachedManifest ){
75 return azManifest[N-count(azName)];
 
 
76 }
 
77 return 0;
78 }
79
80 /*
81 ** Return a list of all reserved filenames as an SQL list.
@@ -93,10 +110,25 @@
93 }
94 zAll = blob_str(&x);
95 }
96 return zAll;
97 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
99 /*
100 ** Add a single file named zName to the VFILE table with vid.
101 **
102 ** Omit any file whose name is pOmit.
103
--- src/add.c
+++ src/add.c
@@ -60,22 +60,39 @@
60 static const char *const azManifest[] = {
61 "manifest",
62 "manifest.uuid",
63 };
64
65 /*
66 ** Names of repository files, if they exist in the checkout.
67 */
68 static const char *azRepo[4] = { 0, 0, 0, 0 };
69
70 /* Cached setting "manifest" */
71 static int cachedManifest = -1;
72
73 if( cachedManifest == -1 ){
74 Blob repo;
75 cachedManifest = db_get_boolean("manifest",0);
76 blob_zero(&repo);
77 if( file_tree_name(g.zRepositoryName, &repo, 0) ){
78 const char *zRepo = blob_str(&repo);
79 azRepo[0] = zRepo;
80 azRepo[1] = mprintf("%s-journal", zRepo);
81 azRepo[2] = mprintf("%s-wal", zRepo);
82 azRepo[3] = mprintf("%s-shm", zRepo);
83 }
84 }
85
86 if( N<0 ) return 0;
87 if( N<count(azName) ) return azName[N];
88 N -= count(azName);
89 if( cachedManifest ){
90 if( N<count(azManifest) ) return azManifest[N];
91 N -= count(azManifest);
92 }
93 if( N<count(azRepo) ) return azRepo[N];
94 return 0;
95 }
96
97 /*
98 ** Return a list of all reserved filenames as an SQL list.
@@ -93,10 +110,25 @@
110 }
111 zAll = blob_str(&x);
112 }
113 return zAll;
114 }
115
116 /*
117 ** COMMAND: test-reserved-names
118 **
119 ** Show all reserved filenames for the current check-out.
120 */
121 void test_reserved_names(void){
122 int i;
123 const char *z;
124 db_must_be_within_tree();
125 for(i=0; (z = fossil_reserved_name(i))!=0; i++){
126 fossil_print("%3d: %s\n", i, z);
127 }
128 fossil_print("ALL: (%s)\n", fossil_all_reserved_names());
129 }
130
131 /*
132 ** Add a single file named zName to the VFILE table with vid.
133 **
134 ** Omit any file whose name is pOmit.
135
+1 -1
--- src/attach.c
+++ src/attach.c
@@ -525,11 +525,11 @@
525525
@ </pre>
526526
}
527527
}else if( strncmp(zMime, "image/", 6)==0 ){
528528
@ <img src="%R/raw?name=%s(zSrc)&m=%s(zMime)"></img>
529529
}else{
530
- int sz = db_int(0, "SELECT sz FROM blob WHERE rid=%d", ridSrc);
530
+ int sz = db_int(0, "SELECT size FROM blob WHERE rid=%d", ridSrc);
531531
@ <i>(file is %d(sz) bytes of binary data)</i>
532532
}
533533
@ </blockquote>
534534
manifest_destroy(pAttach);
535535
blob_reset(&attach);
536536
--- src/attach.c
+++ src/attach.c
@@ -525,11 +525,11 @@
525 @ </pre>
526 }
527 }else if( strncmp(zMime, "image/", 6)==0 ){
528 @ <img src="%R/raw?name=%s(zSrc)&m=%s(zMime)"></img>
529 }else{
530 int sz = db_int(0, "SELECT sz FROM blob WHERE rid=%d", ridSrc);
531 @ <i>(file is %d(sz) bytes of binary data)</i>
532 }
533 @ </blockquote>
534 manifest_destroy(pAttach);
535 blob_reset(&attach);
536
--- src/attach.c
+++ src/attach.c
@@ -525,11 +525,11 @@
525 @ </pre>
526 }
527 }else if( strncmp(zMime, "image/", 6)==0 ){
528 @ <img src="%R/raw?name=%s(zSrc)&m=%s(zMime)"></img>
529 }else{
530 int sz = db_int(0, "SELECT size FROM blob WHERE rid=%d", ridSrc);
531 @ <i>(file is %d(sz) bytes of binary data)</i>
532 }
533 @ </blockquote>
534 manifest_destroy(pAttach);
535 blob_reset(&attach);
536
+4 -5
--- src/checkin.c
+++ src/checkin.c
@@ -324,11 +324,10 @@
324324
**
325325
** See also: changes, clean, status
326326
*/
327327
void extra_cmd(void){
328328
Blob path;
329
- Blob repo;
330329
Stmt q;
331330
int n;
332331
const char *zIgnoreFlag = find_option("ignore",0,1);
333332
unsigned scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0;
334333
int cwdRelative = 0;
@@ -353,13 +352,10 @@
353352
"SELECT x FROM sfile"
354353
" WHERE x NOT IN (%s)"
355354
" ORDER BY 1",
356355
fossil_all_reserved_names()
357356
);
358
- if( file_tree_name(g.zRepositoryName, &repo, 0) ){
359
- db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
360
- }
361357
db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)");
362358
blob_zero(&rewrittenPathname);
363359
while( db_step(&q)==SQLITE_ROW ){
364360
zDisplayName = zPathname = db_column_text(&q, 0);
365361
if( cwdRelative ) {
@@ -1031,10 +1027,11 @@
10311027
** --message-file|-M FILE read the commit comment from given file
10321028
** --nosign do not attempt to sign this commit with gpg
10331029
** --private do not sync changes and their descendants
10341030
** --tag TAG-NAME assign given tag TAG-NAME to the checkin
10351031
** --conflict allow unresolved merge conflicts
1032
+** --binary-ok do not warn about committing binary files
10361033
**
10371034
** See also: branch, changes, checkout, extra, sync
10381035
*/
10391036
void commit_cmd(void){
10401037
int hasChanges; /* True if unsaved changes exist */
@@ -1049,10 +1046,11 @@
10491046
int isAMerge = 0; /* True if checking in a merge */
10501047
int forceFlag = 0; /* Force a fork */
10511048
int forceDelta = 0; /* Force a delta-manifest */
10521049
int forceBaseline = 0; /* Force a baseline-manifest */
10531050
int allowConflict = 0; /* Allow unresolve merge conflicts */
1051
+ int binaryOk = 0; /* The --binary-ok flag */
10541052
char *zManifestFile; /* Name of the manifest file */
10551053
int useCksum; /* True if checksums should be computed and verified */
10561054
int outputManifest; /* True to output "manifest" and "manifest.uuid" */
10571055
int testRun; /* True for a test run. Debugging only */
10581056
const char *zBranch; /* Create a new branch with this name */
@@ -1085,10 +1083,11 @@
10851083
zComment = find_option("comment","m",1);
10861084
forceFlag = find_option("force", "f", 0)!=0;
10871085
zBranch = find_option("branch","b",1);
10881086
zColor = find_option("bgcolor",0,1);
10891087
zBrClr = find_option("branchcolor",0,1);
1088
+ binaryOk = find_option("binary-ok",0,0)!=0;
10901089
while( (zTag = find_option("tag",0,1))!=0 ){
10911090
if( zTag[0]==0 ) continue;
10921091
azTag = fossil_realloc((void *)azTag, sizeof(char*)*(nTag+2));
10931092
azTag[nTag++] = zTag;
10941093
azTag[nTag] = 0;
@@ -1294,11 +1293,11 @@
12941293
id = db_column_int(&q, 0);
12951294
zFullname = db_column_text(&q, 1);
12961295
rid = db_column_int(&q, 2);
12971296
crnlOk = db_column_int(&q, 3);
12981297
chnged = db_column_int(&q, 4);
1299
- binOk = db_column_int(&q, 5);
1298
+ binOk = binaryOk || db_column_int(&q, 5);
13001299
13011300
blob_zero(&content);
13021301
if( file_wd_islink(zFullname) ){
13031302
/* Instead of file content, put link destination path */
13041303
blob_read_link(&content, zFullname);
13051304
--- src/checkin.c
+++ src/checkin.c
@@ -324,11 +324,10 @@
324 **
325 ** See also: changes, clean, status
326 */
327 void extra_cmd(void){
328 Blob path;
329 Blob repo;
330 Stmt q;
331 int n;
332 const char *zIgnoreFlag = find_option("ignore",0,1);
333 unsigned scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0;
334 int cwdRelative = 0;
@@ -353,13 +352,10 @@
353 "SELECT x FROM sfile"
354 " WHERE x NOT IN (%s)"
355 " ORDER BY 1",
356 fossil_all_reserved_names()
357 );
358 if( file_tree_name(g.zRepositoryName, &repo, 0) ){
359 db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
360 }
361 db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)");
362 blob_zero(&rewrittenPathname);
363 while( db_step(&q)==SQLITE_ROW ){
364 zDisplayName = zPathname = db_column_text(&q, 0);
365 if( cwdRelative ) {
@@ -1031,10 +1027,11 @@
1031 ** --message-file|-M FILE read the commit comment from given file
1032 ** --nosign do not attempt to sign this commit with gpg
1033 ** --private do not sync changes and their descendants
1034 ** --tag TAG-NAME assign given tag TAG-NAME to the checkin
1035 ** --conflict allow unresolved merge conflicts
 
1036 **
1037 ** See also: branch, changes, checkout, extra, sync
1038 */
1039 void commit_cmd(void){
1040 int hasChanges; /* True if unsaved changes exist */
@@ -1049,10 +1046,11 @@
1049 int isAMerge = 0; /* True if checking in a merge */
1050 int forceFlag = 0; /* Force a fork */
1051 int forceDelta = 0; /* Force a delta-manifest */
1052 int forceBaseline = 0; /* Force a baseline-manifest */
1053 int allowConflict = 0; /* Allow unresolve merge conflicts */
 
1054 char *zManifestFile; /* Name of the manifest file */
1055 int useCksum; /* True if checksums should be computed and verified */
1056 int outputManifest; /* True to output "manifest" and "manifest.uuid" */
1057 int testRun; /* True for a test run. Debugging only */
1058 const char *zBranch; /* Create a new branch with this name */
@@ -1085,10 +1083,11 @@
1085 zComment = find_option("comment","m",1);
1086 forceFlag = find_option("force", "f", 0)!=0;
1087 zBranch = find_option("branch","b",1);
1088 zColor = find_option("bgcolor",0,1);
1089 zBrClr = find_option("branchcolor",0,1);
 
1090 while( (zTag = find_option("tag",0,1))!=0 ){
1091 if( zTag[0]==0 ) continue;
1092 azTag = fossil_realloc((void *)azTag, sizeof(char*)*(nTag+2));
1093 azTag[nTag++] = zTag;
1094 azTag[nTag] = 0;
@@ -1294,11 +1293,11 @@
1294 id = db_column_int(&q, 0);
1295 zFullname = db_column_text(&q, 1);
1296 rid = db_column_int(&q, 2);
1297 crnlOk = db_column_int(&q, 3);
1298 chnged = db_column_int(&q, 4);
1299 binOk = db_column_int(&q, 5);
1300
1301 blob_zero(&content);
1302 if( file_wd_islink(zFullname) ){
1303 /* Instead of file content, put link destination path */
1304 blob_read_link(&content, zFullname);
1305
--- src/checkin.c
+++ src/checkin.c
@@ -324,11 +324,10 @@
324 **
325 ** See also: changes, clean, status
326 */
327 void extra_cmd(void){
328 Blob path;
 
329 Stmt q;
330 int n;
331 const char *zIgnoreFlag = find_option("ignore",0,1);
332 unsigned scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0;
333 int cwdRelative = 0;
@@ -353,13 +352,10 @@
352 "SELECT x FROM sfile"
353 " WHERE x NOT IN (%s)"
354 " ORDER BY 1",
355 fossil_all_reserved_names()
356 );
 
 
 
357 db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)");
358 blob_zero(&rewrittenPathname);
359 while( db_step(&q)==SQLITE_ROW ){
360 zDisplayName = zPathname = db_column_text(&q, 0);
361 if( cwdRelative ) {
@@ -1031,10 +1027,11 @@
1027 ** --message-file|-M FILE read the commit comment from given file
1028 ** --nosign do not attempt to sign this commit with gpg
1029 ** --private do not sync changes and their descendants
1030 ** --tag TAG-NAME assign given tag TAG-NAME to the checkin
1031 ** --conflict allow unresolved merge conflicts
1032 ** --binary-ok do not warn about committing binary files
1033 **
1034 ** See also: branch, changes, checkout, extra, sync
1035 */
1036 void commit_cmd(void){
1037 int hasChanges; /* True if unsaved changes exist */
@@ -1049,10 +1046,11 @@
1046 int isAMerge = 0; /* True if checking in a merge */
1047 int forceFlag = 0; /* Force a fork */
1048 int forceDelta = 0; /* Force a delta-manifest */
1049 int forceBaseline = 0; /* Force a baseline-manifest */
1050 int allowConflict = 0; /* Allow unresolve merge conflicts */
1051 int binaryOk = 0; /* The --binary-ok flag */
1052 char *zManifestFile; /* Name of the manifest file */
1053 int useCksum; /* True if checksums should be computed and verified */
1054 int outputManifest; /* True to output "manifest" and "manifest.uuid" */
1055 int testRun; /* True for a test run. Debugging only */
1056 const char *zBranch; /* Create a new branch with this name */
@@ -1085,10 +1083,11 @@
1083 zComment = find_option("comment","m",1);
1084 forceFlag = find_option("force", "f", 0)!=0;
1085 zBranch = find_option("branch","b",1);
1086 zColor = find_option("bgcolor",0,1);
1087 zBrClr = find_option("branchcolor",0,1);
1088 binaryOk = find_option("binary-ok",0,0)!=0;
1089 while( (zTag = find_option("tag",0,1))!=0 ){
1090 if( zTag[0]==0 ) continue;
1091 azTag = fossil_realloc((void *)azTag, sizeof(char*)*(nTag+2));
1092 azTag[nTag++] = zTag;
1093 azTag[nTag] = 0;
@@ -1294,11 +1293,11 @@
1293 id = db_column_int(&q, 0);
1294 zFullname = db_column_text(&q, 1);
1295 rid = db_column_int(&q, 2);
1296 crnlOk = db_column_int(&q, 3);
1297 chnged = db_column_int(&q, 4);
1298 binOk = binaryOk || db_column_int(&q, 5);
1299
1300 blob_zero(&content);
1301 if( file_wd_islink(zFullname) ){
1302 /* Instead of file content, put link destination path */
1303 blob_read_link(&content, zFullname);
1304
+4 -5
--- src/checkin.c
+++ src/checkin.c
@@ -324,11 +324,10 @@
324324
**
325325
** See also: changes, clean, status
326326
*/
327327
void extra_cmd(void){
328328
Blob path;
329
- Blob repo;
330329
Stmt q;
331330
int n;
332331
const char *zIgnoreFlag = find_option("ignore",0,1);
333332
unsigned scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0;
334333
int cwdRelative = 0;
@@ -353,13 +352,10 @@
353352
"SELECT x FROM sfile"
354353
" WHERE x NOT IN (%s)"
355354
" ORDER BY 1",
356355
fossil_all_reserved_names()
357356
);
358
- if( file_tree_name(g.zRepositoryName, &repo, 0) ){
359
- db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
360
- }
361357
db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)");
362358
blob_zero(&rewrittenPathname);
363359
while( db_step(&q)==SQLITE_ROW ){
364360
zDisplayName = zPathname = db_column_text(&q, 0);
365361
if( cwdRelative ) {
@@ -1031,10 +1027,11 @@
10311027
** --message-file|-M FILE read the commit comment from given file
10321028
** --nosign do not attempt to sign this commit with gpg
10331029
** --private do not sync changes and their descendants
10341030
** --tag TAG-NAME assign given tag TAG-NAME to the checkin
10351031
** --conflict allow unresolved merge conflicts
1032
+** --binary-ok do not warn about committing binary files
10361033
**
10371034
** See also: branch, changes, checkout, extra, sync
10381035
*/
10391036
void commit_cmd(void){
10401037
int hasChanges; /* True if unsaved changes exist */
@@ -1049,10 +1046,11 @@
10491046
int isAMerge = 0; /* True if checking in a merge */
10501047
int forceFlag = 0; /* Force a fork */
10511048
int forceDelta = 0; /* Force a delta-manifest */
10521049
int forceBaseline = 0; /* Force a baseline-manifest */
10531050
int allowConflict = 0; /* Allow unresolve merge conflicts */
1051
+ int binaryOk = 0; /* The --binary-ok flag */
10541052
char *zManifestFile; /* Name of the manifest file */
10551053
int useCksum; /* True if checksums should be computed and verified */
10561054
int outputManifest; /* True to output "manifest" and "manifest.uuid" */
10571055
int testRun; /* True for a test run. Debugging only */
10581056
const char *zBranch; /* Create a new branch with this name */
@@ -1085,10 +1083,11 @@
10851083
zComment = find_option("comment","m",1);
10861084
forceFlag = find_option("force", "f", 0)!=0;
10871085
zBranch = find_option("branch","b",1);
10881086
zColor = find_option("bgcolor",0,1);
10891087
zBrClr = find_option("branchcolor",0,1);
1088
+ binaryOk = find_option("binary-ok",0,0)!=0;
10901089
while( (zTag = find_option("tag",0,1))!=0 ){
10911090
if( zTag[0]==0 ) continue;
10921091
azTag = fossil_realloc((void *)azTag, sizeof(char*)*(nTag+2));
10931092
azTag[nTag++] = zTag;
10941093
azTag[nTag] = 0;
@@ -1294,11 +1293,11 @@
12941293
id = db_column_int(&q, 0);
12951294
zFullname = db_column_text(&q, 1);
12961295
rid = db_column_int(&q, 2);
12971296
crnlOk = db_column_int(&q, 3);
12981297
chnged = db_column_int(&q, 4);
1299
- binOk = db_column_int(&q, 5);
1298
+ binOk = binaryOk || db_column_int(&q, 5);
13001299
13011300
blob_zero(&content);
13021301
if( file_wd_islink(zFullname) ){
13031302
/* Instead of file content, put link destination path */
13041303
blob_read_link(&content, zFullname);
13051304
--- src/checkin.c
+++ src/checkin.c
@@ -324,11 +324,10 @@
324 **
325 ** See also: changes, clean, status
326 */
327 void extra_cmd(void){
328 Blob path;
329 Blob repo;
330 Stmt q;
331 int n;
332 const char *zIgnoreFlag = find_option("ignore",0,1);
333 unsigned scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0;
334 int cwdRelative = 0;
@@ -353,13 +352,10 @@
353 "SELECT x FROM sfile"
354 " WHERE x NOT IN (%s)"
355 " ORDER BY 1",
356 fossil_all_reserved_names()
357 );
358 if( file_tree_name(g.zRepositoryName, &repo, 0) ){
359 db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
360 }
361 db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)");
362 blob_zero(&rewrittenPathname);
363 while( db_step(&q)==SQLITE_ROW ){
364 zDisplayName = zPathname = db_column_text(&q, 0);
365 if( cwdRelative ) {
@@ -1031,10 +1027,11 @@
1031 ** --message-file|-M FILE read the commit comment from given file
1032 ** --nosign do not attempt to sign this commit with gpg
1033 ** --private do not sync changes and their descendants
1034 ** --tag TAG-NAME assign given tag TAG-NAME to the checkin
1035 ** --conflict allow unresolved merge conflicts
 
1036 **
1037 ** See also: branch, changes, checkout, extra, sync
1038 */
1039 void commit_cmd(void){
1040 int hasChanges; /* True if unsaved changes exist */
@@ -1049,10 +1046,11 @@
1049 int isAMerge = 0; /* True if checking in a merge */
1050 int forceFlag = 0; /* Force a fork */
1051 int forceDelta = 0; /* Force a delta-manifest */
1052 int forceBaseline = 0; /* Force a baseline-manifest */
1053 int allowConflict = 0; /* Allow unresolve merge conflicts */
 
1054 char *zManifestFile; /* Name of the manifest file */
1055 int useCksum; /* True if checksums should be computed and verified */
1056 int outputManifest; /* True to output "manifest" and "manifest.uuid" */
1057 int testRun; /* True for a test run. Debugging only */
1058 const char *zBranch; /* Create a new branch with this name */
@@ -1085,10 +1083,11 @@
1085 zComment = find_option("comment","m",1);
1086 forceFlag = find_option("force", "f", 0)!=0;
1087 zBranch = find_option("branch","b",1);
1088 zColor = find_option("bgcolor",0,1);
1089 zBrClr = find_option("branchcolor",0,1);
 
1090 while( (zTag = find_option("tag",0,1))!=0 ){
1091 if( zTag[0]==0 ) continue;
1092 azTag = fossil_realloc((void *)azTag, sizeof(char*)*(nTag+2));
1093 azTag[nTag++] = zTag;
1094 azTag[nTag] = 0;
@@ -1294,11 +1293,11 @@
1294 id = db_column_int(&q, 0);
1295 zFullname = db_column_text(&q, 1);
1296 rid = db_column_int(&q, 2);
1297 crnlOk = db_column_int(&q, 3);
1298 chnged = db_column_int(&q, 4);
1299 binOk = db_column_int(&q, 5);
1300
1301 blob_zero(&content);
1302 if( file_wd_islink(zFullname) ){
1303 /* Instead of file content, put link destination path */
1304 blob_read_link(&content, zFullname);
1305
--- src/checkin.c
+++ src/checkin.c
@@ -324,11 +324,10 @@
324 **
325 ** See also: changes, clean, status
326 */
327 void extra_cmd(void){
328 Blob path;
 
329 Stmt q;
330 int n;
331 const char *zIgnoreFlag = find_option("ignore",0,1);
332 unsigned scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0;
333 int cwdRelative = 0;
@@ -353,13 +352,10 @@
352 "SELECT x FROM sfile"
353 " WHERE x NOT IN (%s)"
354 " ORDER BY 1",
355 fossil_all_reserved_names()
356 );
 
 
 
357 db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)");
358 blob_zero(&rewrittenPathname);
359 while( db_step(&q)==SQLITE_ROW ){
360 zDisplayName = zPathname = db_column_text(&q, 0);
361 if( cwdRelative ) {
@@ -1031,10 +1027,11 @@
1027 ** --message-file|-M FILE read the commit comment from given file
1028 ** --nosign do not attempt to sign this commit with gpg
1029 ** --private do not sync changes and their descendants
1030 ** --tag TAG-NAME assign given tag TAG-NAME to the checkin
1031 ** --conflict allow unresolved merge conflicts
1032 ** --binary-ok do not warn about committing binary files
1033 **
1034 ** See also: branch, changes, checkout, extra, sync
1035 */
1036 void commit_cmd(void){
1037 int hasChanges; /* True if unsaved changes exist */
@@ -1049,10 +1046,11 @@
1046 int isAMerge = 0; /* True if checking in a merge */
1047 int forceFlag = 0; /* Force a fork */
1048 int forceDelta = 0; /* Force a delta-manifest */
1049 int forceBaseline = 0; /* Force a baseline-manifest */
1050 int allowConflict = 0; /* Allow unresolve merge conflicts */
1051 int binaryOk = 0; /* The --binary-ok flag */
1052 char *zManifestFile; /* Name of the manifest file */
1053 int useCksum; /* True if checksums should be computed and verified */
1054 int outputManifest; /* True to output "manifest" and "manifest.uuid" */
1055 int testRun; /* True for a test run. Debugging only */
1056 const char *zBranch; /* Create a new branch with this name */
@@ -1085,10 +1083,11 @@
1083 zComment = find_option("comment","m",1);
1084 forceFlag = find_option("force", "f", 0)!=0;
1085 zBranch = find_option("branch","b",1);
1086 zColor = find_option("bgcolor",0,1);
1087 zBrClr = find_option("branchcolor",0,1);
1088 binaryOk = find_option("binary-ok",0,0)!=0;
1089 while( (zTag = find_option("tag",0,1))!=0 ){
1090 if( zTag[0]==0 ) continue;
1091 azTag = fossil_realloc((void *)azTag, sizeof(char*)*(nTag+2));
1092 azTag[nTag++] = zTag;
1093 azTag[nTag] = 0;
@@ -1294,11 +1293,11 @@
1293 id = db_column_int(&q, 0);
1294 zFullname = db_column_text(&q, 1);
1295 rid = db_column_int(&q, 2);
1296 crnlOk = db_column_int(&q, 3);
1297 chnged = db_column_int(&q, 4);
1298 binOk = binaryOk || db_column_int(&q, 5);
1299
1300 blob_zero(&content);
1301 if( file_wd_islink(zFullname) ){
1302 /* Instead of file content, put link destination path */
1303 blob_read_link(&content, zFullname);
1304
+9
--- src/diff.c
+++ src/diff.c
@@ -1027,10 +1027,19 @@
10271027
}
10281028
if( nRight==0 ){
10291029
memset(aM, 1, nLeft);
10301030
return aM;
10311031
}
1032
+
1033
+ /* This algorithm is O(N**2). So if N is too big, bail out with a
1034
+ ** simple (but stupid and ugly) result that doesn't take too long. */
1035
+ if( nLeft*nRight>100000 ){
1036
+ memset(aM, 3, nRight);
1037
+ memset(aM+nRight, 1, nLeft);
1038
+ return aM;
1039
+ }
1040
+
10321041
if( nRight < (sizeof(aBuf)/sizeof(aBuf[0]))-1 ){
10331042
pToFree = 0;
10341043
a = aBuf;
10351044
}else{
10361045
a = pToFree = fossil_malloc( sizeof(a[0])*(nRight+1) );
10371046
--- src/diff.c
+++ src/diff.c
@@ -1027,10 +1027,19 @@
1027 }
1028 if( nRight==0 ){
1029 memset(aM, 1, nLeft);
1030 return aM;
1031 }
 
 
 
 
 
 
 
 
 
1032 if( nRight < (sizeof(aBuf)/sizeof(aBuf[0]))-1 ){
1033 pToFree = 0;
1034 a = aBuf;
1035 }else{
1036 a = pToFree = fossil_malloc( sizeof(a[0])*(nRight+1) );
1037
--- src/diff.c
+++ src/diff.c
@@ -1027,10 +1027,19 @@
1027 }
1028 if( nRight==0 ){
1029 memset(aM, 1, nLeft);
1030 return aM;
1031 }
1032
1033 /* This algorithm is O(N**2). So if N is too big, bail out with a
1034 ** simple (but stupid and ugly) result that doesn't take too long. */
1035 if( nLeft*nRight>100000 ){
1036 memset(aM, 3, nRight);
1037 memset(aM+nRight, 1, nLeft);
1038 return aM;
1039 }
1040
1041 if( nRight < (sizeof(aBuf)/sizeof(aBuf[0]))-1 ){
1042 pToFree = 0;
1043 a = aBuf;
1044 }else{
1045 a = pToFree = fossil_malloc( sizeof(a[0])*(nRight+1) );
1046
+9
--- src/diff.c
+++ src/diff.c
@@ -1027,10 +1027,19 @@
10271027
}
10281028
if( nRight==0 ){
10291029
memset(aM, 1, nLeft);
10301030
return aM;
10311031
}
1032
+
1033
+ /* This algorithm is O(N**2). So if N is too big, bail out with a
1034
+ ** simple (but stupid and ugly) result that doesn't take too long. */
1035
+ if( nLeft*nRight>100000 ){
1036
+ memset(aM, 3, nRight);
1037
+ memset(aM+nRight, 1, nLeft);
1038
+ return aM;
1039
+ }
1040
+
10321041
if( nRight < (sizeof(aBuf)/sizeof(aBuf[0]))-1 ){
10331042
pToFree = 0;
10341043
a = aBuf;
10351044
}else{
10361045
a = pToFree = fossil_malloc( sizeof(a[0])*(nRight+1) );
10371046
--- src/diff.c
+++ src/diff.c
@@ -1027,10 +1027,19 @@
1027 }
1028 if( nRight==0 ){
1029 memset(aM, 1, nLeft);
1030 return aM;
1031 }
 
 
 
 
 
 
 
 
 
1032 if( nRight < (sizeof(aBuf)/sizeof(aBuf[0]))-1 ){
1033 pToFree = 0;
1034 a = aBuf;
1035 }else{
1036 a = pToFree = fossil_malloc( sizeof(a[0])*(nRight+1) );
1037
--- src/diff.c
+++ src/diff.c
@@ -1027,10 +1027,19 @@
1027 }
1028 if( nRight==0 ){
1029 memset(aM, 1, nLeft);
1030 return aM;
1031 }
1032
1033 /* This algorithm is O(N**2). So if N is too big, bail out with a
1034 ** simple (but stupid and ugly) result that doesn't take too long. */
1035 if( nLeft*nRight>100000 ){
1036 memset(aM, 3, nRight);
1037 memset(aM+nRight, 1, nLeft);
1038 return aM;
1039 }
1040
1041 if( nRight < (sizeof(aBuf)/sizeof(aBuf[0]))-1 ){
1042 pToFree = 0;
1043 a = aBuf;
1044 }else{
1045 a = pToFree = fossil_malloc( sizeof(a[0])*(nRight+1) );
1046
+3 -3
--- src/finfo.c
+++ src/finfo.c
@@ -331,11 +331,11 @@
331331
gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr, 0);
332332
if( memcmp(zDate, zPrevDate, 10) ){
333333
sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
334334
@ <tr><td>
335335
@ <div class="divider">%s(zPrevDate)</div>
336
- @ </td></tr>
336
+ @ </td><td></td><td></td></tr>
337337
}
338338
memcpy(zTime, &zDate[11], 5);
339339
zTime[5] = 0;
340340
@ <tr><td class="timelineTime">
341341
@ %z(href("%R/timeline?c=%t",zDate))%s(zTime)</a></td>
@@ -357,11 +357,11 @@
357357
hyperlink_to_user(zUser, zDate, "");
358358
@ branch: %h(zBr))
359359
if( g.perm.Hyperlink && zUuid ){
360360
const char *z = zFilename;
361361
if( fpid ){
362
- @ %z(href("%R/fdiff?v1=%s&v2=%s",zPUuid,zUuid))[diff]</a>
362
+ @ %z(href("%R/fdiff?v1=%S&v2=%S",zPUuid,zUuid))[diff]</a>
363363
}
364364
@ %z(href("%R/annotate?checkin=%S&filename=%h",zCkin,z))
365365
@ [annotate]</a>
366366
}
367367
@ </td></tr>
@@ -373,12 +373,12 @@
373373
graph_free(pGraph);
374374
pGraph = 0;
375375
}else{
376376
@ <tr><td></td><td>
377377
@ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div>
378
- @ </td></tr>
378
+ @ </td><td></td></tr>
379379
}
380380
}
381381
@ </table>
382382
timeline_output_graph_javascript(pGraph, 0);
383383
style_footer();
384384
}
385385
--- src/finfo.c
+++ src/finfo.c
@@ -331,11 +331,11 @@
331 gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr, 0);
332 if( memcmp(zDate, zPrevDate, 10) ){
333 sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
334 @ <tr><td>
335 @ <div class="divider">%s(zPrevDate)</div>
336 @ </td></tr>
337 }
338 memcpy(zTime, &zDate[11], 5);
339 zTime[5] = 0;
340 @ <tr><td class="timelineTime">
341 @ %z(href("%R/timeline?c=%t",zDate))%s(zTime)</a></td>
@@ -357,11 +357,11 @@
357 hyperlink_to_user(zUser, zDate, "");
358 @ branch: %h(zBr))
359 if( g.perm.Hyperlink && zUuid ){
360 const char *z = zFilename;
361 if( fpid ){
362 @ %z(href("%R/fdiff?v1=%s&v2=%s",zPUuid,zUuid))[diff]</a>
363 }
364 @ %z(href("%R/annotate?checkin=%S&filename=%h",zCkin,z))
365 @ [annotate]</a>
366 }
367 @ </td></tr>
@@ -373,12 +373,12 @@
373 graph_free(pGraph);
374 pGraph = 0;
375 }else{
376 @ <tr><td></td><td>
377 @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div>
378 @ </td></tr>
379 }
380 }
381 @ </table>
382 timeline_output_graph_javascript(pGraph, 0);
383 style_footer();
384 }
385
--- src/finfo.c
+++ src/finfo.c
@@ -331,11 +331,11 @@
331 gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr, 0);
332 if( memcmp(zDate, zPrevDate, 10) ){
333 sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
334 @ <tr><td>
335 @ <div class="divider">%s(zPrevDate)</div>
336 @ </td><td></td><td></td></tr>
337 }
338 memcpy(zTime, &zDate[11], 5);
339 zTime[5] = 0;
340 @ <tr><td class="timelineTime">
341 @ %z(href("%R/timeline?c=%t",zDate))%s(zTime)</a></td>
@@ -357,11 +357,11 @@
357 hyperlink_to_user(zUser, zDate, "");
358 @ branch: %h(zBr))
359 if( g.perm.Hyperlink && zUuid ){
360 const char *z = zFilename;
361 if( fpid ){
362 @ %z(href("%R/fdiff?v1=%S&v2=%S",zPUuid,zUuid))[diff]</a>
363 }
364 @ %z(href("%R/annotate?checkin=%S&filename=%h",zCkin,z))
365 @ [annotate]</a>
366 }
367 @ </td></tr>
@@ -373,12 +373,12 @@
373 graph_free(pGraph);
374 pGraph = 0;
375 }else{
376 @ <tr><td></td><td>
377 @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div>
378 @ </td><td></td></tr>
379 }
380 }
381 @ </table>
382 timeline_output_graph_javascript(pGraph, 0);
383 style_footer();
384 }
385
--- src/http_transport.c
+++ src/http_transport.c
@@ -110,10 +110,12 @@
110110
*/
111111
const char *zSsh; /* The base SSH command */
112112
Blob zCmd; /* The SSH command */
113113
char *zHost; /* The host name to contact */
114114
char *zIn; /* An input line received back from remote */
115
+ unsigned iRandom;
116
+ char zProbe[30];
115117
116118
zSsh = db_get("ssh-command", zDefaultSshCmd);
117119
blob_init(&zCmd, zSsh, -1);
118120
if( g.urlPort!=g.urlDfltPort ){
119121
#ifdef __MINGW32__
@@ -155,18 +157,23 @@
155157
if( sshPid==0 ){
156158
fossil_fatal("cannot start ssh tunnel using [%b]", &zCmd);
157159
}
158160
blob_reset(&zCmd);
159161
160
- /* Send an "echo" command to the other side to make sure that the
162
+ /* Send a couple of "echo" command to the other side to make sure that the
161163
** connection is up and working.
162164
*/
163
- fprintf(sshOut, "echo test\n");
165
+ fprintf(sshOut, "echo test1\n");
166
+ fflush(sshOut);
167
+ zIn = fossil_malloc(50000);
168
+ sshin_read(zIn, 50000);
169
+ sqlite3_randomness(sizeof(iRandom), &iRandom);
170
+ sqlite3_snprintf(sizeof(zProbe), zProbe, "probe-%08x", iRandom);
171
+ fprintf(sshOut, "echo %s\n", zProbe);
164172
fflush(sshOut);
165
- zIn = fossil_malloc(16000);
166
- sshin_read(zIn, 16000);
167
- if( memcmp(zIn, "test", 4)!=0 ){
173
+ sshin_read(zIn, 500);
174
+ if( memcmp(zIn, zProbe, 14)!=0 ){
168175
pclose2(sshIn, sshOut, sshPid);
169176
fossil_fatal("ssh connection failed: [%s]", zIn);
170177
}
171178
fossil_free(zIn);
172179
}
173180
--- src/http_transport.c
+++ src/http_transport.c
@@ -110,10 +110,12 @@
110 */
111 const char *zSsh; /* The base SSH command */
112 Blob zCmd; /* The SSH command */
113 char *zHost; /* The host name to contact */
114 char *zIn; /* An input line received back from remote */
 
 
115
116 zSsh = db_get("ssh-command", zDefaultSshCmd);
117 blob_init(&zCmd, zSsh, -1);
118 if( g.urlPort!=g.urlDfltPort ){
119 #ifdef __MINGW32__
@@ -155,18 +157,23 @@
155 if( sshPid==0 ){
156 fossil_fatal("cannot start ssh tunnel using [%b]", &zCmd);
157 }
158 blob_reset(&zCmd);
159
160 /* Send an "echo" command to the other side to make sure that the
161 ** connection is up and working.
162 */
163 fprintf(sshOut, "echo test\n");
 
 
 
 
 
 
164 fflush(sshOut);
165 zIn = fossil_malloc(16000);
166 sshin_read(zIn, 16000);
167 if( memcmp(zIn, "test", 4)!=0 ){
168 pclose2(sshIn, sshOut, sshPid);
169 fossil_fatal("ssh connection failed: [%s]", zIn);
170 }
171 fossil_free(zIn);
172 }
173
--- src/http_transport.c
+++ src/http_transport.c
@@ -110,10 +110,12 @@
110 */
111 const char *zSsh; /* The base SSH command */
112 Blob zCmd; /* The SSH command */
113 char *zHost; /* The host name to contact */
114 char *zIn; /* An input line received back from remote */
115 unsigned iRandom;
116 char zProbe[30];
117
118 zSsh = db_get("ssh-command", zDefaultSshCmd);
119 blob_init(&zCmd, zSsh, -1);
120 if( g.urlPort!=g.urlDfltPort ){
121 #ifdef __MINGW32__
@@ -155,18 +157,23 @@
157 if( sshPid==0 ){
158 fossil_fatal("cannot start ssh tunnel using [%b]", &zCmd);
159 }
160 blob_reset(&zCmd);
161
162 /* Send a couple of "echo" command to the other side to make sure that the
163 ** connection is up and working.
164 */
165 fprintf(sshOut, "echo test1\n");
166 fflush(sshOut);
167 zIn = fossil_malloc(50000);
168 sshin_read(zIn, 50000);
169 sqlite3_randomness(sizeof(iRandom), &iRandom);
170 sqlite3_snprintf(sizeof(zProbe), zProbe, "probe-%08x", iRandom);
171 fprintf(sshOut, "echo %s\n", zProbe);
172 fflush(sshOut);
173 sshin_read(zIn, 500);
174 if( memcmp(zIn, zProbe, 14)!=0 ){
 
175 pclose2(sshIn, sshOut, sshPid);
176 fossil_fatal("ssh connection failed: [%s]", zIn);
177 }
178 fossil_free(zIn);
179 }
180
+4 -4
--- src/info.c
+++ src/info.c
@@ -617,16 +617,16 @@
617617
@ </td></tr>
618618
}
619619
620620
/* The Download: line */
621621
if( g.perm.Zip ){
622
- char *zUrl = mprintf("%R/tarball/%s-%S.tar.gz?uuid=%s",
622
+ char *zUrl = mprintf("%R/tarball/%t-%S.tar.gz?uuid=%s",
623623
zProjName, zUuid, zUuid);
624624
@ </td></tr>
625625
@ <tr><th>Downloads:</th><td>
626626
@ %z(href("%s",zUrl))Tarball</a>
627
- @ | %z(href("%R/zip/%s-%S.zip?uuid=%s",zProjName,zUuid,zUuid))
627
+ @ | %z(href("%R/zip/%t-%S.zip?uuid=%s",zProjName,zUuid,zUuid))
628628
@ ZIP archive</a>
629629
fossil_free(zUrl);
630630
}
631631
@ </td></tr>
632632
@ <tr><th>Other&nbsp;Links:</th>
@@ -885,11 +885,11 @@
885885
blob_zero(&links);
886886
while( z && z[0] ){
887887
for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){}
888888
blob_appendf(&links,
889889
"%z%#h</a>%.2s",
890
- href("%R/timeline?r=%#t&nd&c=%s",i,z,zDate), i,z, &z[i]
890
+ href("%R/timeline?r=%#t&nd&c=%t",i,z,zDate), i,z, &z[i]
891891
);
892892
if( z[i]==0 ) break;
893893
z += i+2;
894894
}
895895
@ tags: %s(blob_str(&links)),
@@ -1723,14 +1723,14 @@
17231723
}
17241724
@ <tr><th>Ticket:</th>
17251725
@ <td>%z(href("%R/tktview/%s",zTktName))%s(zTktName)</a></td></tr>
17261726
@ <tr><th>Date:</th><td>
17271727
hyperlink_to_date(zDate, "</td></tr>");
1728
- free(zDate);
17291728
@ <tr><th>User:</th><td>
17301729
hyperlink_to_user(pTktChng->zUser, zDate, "</td></tr>");
17311730
@ </table>
1731
+ free(zDate);
17321732
17331733
if( g.perm.ModTkt && modPending ){
17341734
@ <div class="section">Moderation</div>
17351735
@ <blockquote>
17361736
@ <form method="POST" action="%R/tinfo/%s(zUuid)">
17371737
--- src/info.c
+++ src/info.c
@@ -617,16 +617,16 @@
617 @ </td></tr>
618 }
619
620 /* The Download: line */
621 if( g.perm.Zip ){
622 char *zUrl = mprintf("%R/tarball/%s-%S.tar.gz?uuid=%s",
623 zProjName, zUuid, zUuid);
624 @ </td></tr>
625 @ <tr><th>Downloads:</th><td>
626 @ %z(href("%s",zUrl))Tarball</a>
627 @ | %z(href("%R/zip/%s-%S.zip?uuid=%s",zProjName,zUuid,zUuid))
628 @ ZIP archive</a>
629 fossil_free(zUrl);
630 }
631 @ </td></tr>
632 @ <tr><th>Other&nbsp;Links:</th>
@@ -885,11 +885,11 @@
885 blob_zero(&links);
886 while( z && z[0] ){
887 for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){}
888 blob_appendf(&links,
889 "%z%#h</a>%.2s",
890 href("%R/timeline?r=%#t&nd&c=%s",i,z,zDate), i,z, &z[i]
891 );
892 if( z[i]==0 ) break;
893 z += i+2;
894 }
895 @ tags: %s(blob_str(&links)),
@@ -1723,14 +1723,14 @@
1723 }
1724 @ <tr><th>Ticket:</th>
1725 @ <td>%z(href("%R/tktview/%s",zTktName))%s(zTktName)</a></td></tr>
1726 @ <tr><th>Date:</th><td>
1727 hyperlink_to_date(zDate, "</td></tr>");
1728 free(zDate);
1729 @ <tr><th>User:</th><td>
1730 hyperlink_to_user(pTktChng->zUser, zDate, "</td></tr>");
1731 @ </table>
 
1732
1733 if( g.perm.ModTkt && modPending ){
1734 @ <div class="section">Moderation</div>
1735 @ <blockquote>
1736 @ <form method="POST" action="%R/tinfo/%s(zUuid)">
1737
--- src/info.c
+++ src/info.c
@@ -617,16 +617,16 @@
617 @ </td></tr>
618 }
619
620 /* The Download: line */
621 if( g.perm.Zip ){
622 char *zUrl = mprintf("%R/tarball/%t-%S.tar.gz?uuid=%s",
623 zProjName, zUuid, zUuid);
624 @ </td></tr>
625 @ <tr><th>Downloads:</th><td>
626 @ %z(href("%s",zUrl))Tarball</a>
627 @ | %z(href("%R/zip/%t-%S.zip?uuid=%s",zProjName,zUuid,zUuid))
628 @ ZIP archive</a>
629 fossil_free(zUrl);
630 }
631 @ </td></tr>
632 @ <tr><th>Other&nbsp;Links:</th>
@@ -885,11 +885,11 @@
885 blob_zero(&links);
886 while( z && z[0] ){
887 for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){}
888 blob_appendf(&links,
889 "%z%#h</a>%.2s",
890 href("%R/timeline?r=%#t&nd&c=%t",i,z,zDate), i,z, &z[i]
891 );
892 if( z[i]==0 ) break;
893 z += i+2;
894 }
895 @ tags: %s(blob_str(&links)),
@@ -1723,14 +1723,14 @@
1723 }
1724 @ <tr><th>Ticket:</th>
1725 @ <td>%z(href("%R/tktview/%s",zTktName))%s(zTktName)</a></td></tr>
1726 @ <tr><th>Date:</th><td>
1727 hyperlink_to_date(zDate, "</td></tr>");
 
1728 @ <tr><th>User:</th><td>
1729 hyperlink_to_user(pTktChng->zUser, zDate, "</td></tr>");
1730 @ </table>
1731 free(zDate);
1732
1733 if( g.perm.ModTkt && modPending ){
1734 @ <div class="section">Moderation</div>
1735 @ <blockquote>
1736 @ <form method="POST" action="%R/tinfo/%s(zUuid)">
1737
+1 -1
--- src/login.c
+++ src/login.c
@@ -1145,11 +1145,11 @@
11451145
db_exists("SELECT 1 FROM user"
11461146
" WHERE login='anonymous'"
11471147
" AND cap LIKE '%%h%%'") ){
11481148
const char *zUrl = PD("REQUEST_URI", "index");
11491149
@ <p>Many <span class="disabled">hyperlinks are disabled.</span><br />
1150
- @ Use <a href="%s(g.zTop)/login?anon=1&g=%T(zUrl)">anonymous login</a>
1150
+ @ Use <a href="%s(g.zTop)/login?anon=1&amp;g=%T(zUrl)">anonymous login</a>
11511151
@ to enable hyperlinks.</p>
11521152
}
11531153
}
11541154
11551155
/*
11561156
--- src/login.c
+++ src/login.c
@@ -1145,11 +1145,11 @@
1145 db_exists("SELECT 1 FROM user"
1146 " WHERE login='anonymous'"
1147 " AND cap LIKE '%%h%%'") ){
1148 const char *zUrl = PD("REQUEST_URI", "index");
1149 @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br />
1150 @ Use <a href="%s(g.zTop)/login?anon=1&g=%T(zUrl)">anonymous login</a>
1151 @ to enable hyperlinks.</p>
1152 }
1153 }
1154
1155 /*
1156
--- src/login.c
+++ src/login.c
@@ -1145,11 +1145,11 @@
1145 db_exists("SELECT 1 FROM user"
1146 " WHERE login='anonymous'"
1147 " AND cap LIKE '%%h%%'") ){
1148 const char *zUrl = PD("REQUEST_URI", "index");
1149 @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br />
1150 @ Use <a href="%s(g.zTop)/login?anon=1&amp;g=%T(zUrl)">anonymous login</a>
1151 @ to enable hyperlinks.</p>
1152 }
1153 }
1154
1155 /*
1156
+1 -1
--- src/report.c
+++ src/report.c
@@ -60,11 +60,11 @@
6060
} else {
6161
blob_appendf(&ril, "%z%h</a>", href("%R/rptview?rn=%d", rn), zTitle);
6262
}
6363
blob_appendf(&ril, "&nbsp;&nbsp;&nbsp;");
6464
if( g.perm.Write && zOwner && zOwner[0] ){
65
- blob_appendf(&ril, "(by <i>%h</i></i>) ", zOwner);
65
+ blob_appendf(&ril, "(by <i>%h</i>) ", zOwner);
6666
}
6767
if( g.perm.TktFmt ){
6868
blob_appendf(&ril, "[%zcopy</a>] ",
6969
href("%R/rptedit?rn=%d&copy=1", rn));
7070
}
7171
--- src/report.c
+++ src/report.c
@@ -60,11 +60,11 @@
60 } else {
61 blob_appendf(&ril, "%z%h</a>", href("%R/rptview?rn=%d", rn), zTitle);
62 }
63 blob_appendf(&ril, "&nbsp;&nbsp;&nbsp;");
64 if( g.perm.Write && zOwner && zOwner[0] ){
65 blob_appendf(&ril, "(by <i>%h</i></i>) ", zOwner);
66 }
67 if( g.perm.TktFmt ){
68 blob_appendf(&ril, "[%zcopy</a>] ",
69 href("%R/rptedit?rn=%d&copy=1", rn));
70 }
71
--- src/report.c
+++ src/report.c
@@ -60,11 +60,11 @@
60 } else {
61 blob_appendf(&ril, "%z%h</a>", href("%R/rptview?rn=%d", rn), zTitle);
62 }
63 blob_appendf(&ril, "&nbsp;&nbsp;&nbsp;");
64 if( g.perm.Write && zOwner && zOwner[0] ){
65 blob_appendf(&ril, "(by <i>%h</i>) ", zOwner);
66 }
67 if( g.perm.TktFmt ){
68 blob_appendf(&ril, "[%zcopy</a>] ",
69 href("%R/rptedit?rn=%d&copy=1", rn));
70 }
71
+2 -2
--- src/setup.c
+++ src/setup.c
@@ -62,11 +62,11 @@
6262
6363
/* Make sure the header contains <base href="...">. Issue a warning
6464
** if it does not. */
6565
if( !cgi_header_contains("<base href=") ){
6666
@ <p class="generalError"><b>Configuration Error:</b> Please add
67
- @ <tt>&lt;base href="$baseurl/$current_page"&gt</tt> after
67
+ @ <tt>&lt;base href="$baseurl/$current_page"&gt;</tt> after
6868
@ <tt>&lt;head&gt;</tt> in the <a href="setup_header">HTML header</a>!</p>
6969
}
7070
7171
@ <table border="0" cellspacing="7">
7272
setup_menu_entry("Users", "setup_ulist",
@@ -1352,11 +1352,11 @@
13521352
13531353
/* Make sure the header contains <base href="...">. Issue a warning
13541354
** if it does not. */
13551355
if( !cgi_header_contains("<base href=") ){
13561356
@ <p class="generalError">Please add
1357
- @ <tt>&lt;base href="$baseurl/$current_page"&gt</tt> after
1357
+ @ <tt>&lt;base href="$baseurl/$current_page"&gt;</tt> after
13581358
@ <tt>&lt;head&gt;</tt> in the header!
13591359
@ <input type="submit" name="fixbase" value="Add &lt;base&gt; Now"></p>
13601360
}
13611361
13621362
login_insert_csrf_secret();
13631363
--- src/setup.c
+++ src/setup.c
@@ -62,11 +62,11 @@
62
63 /* Make sure the header contains <base href="...">. Issue a warning
64 ** if it does not. */
65 if( !cgi_header_contains("<base href=") ){
66 @ <p class="generalError"><b>Configuration Error:</b> Please add
67 @ <tt>&lt;base href="$baseurl/$current_page"&gt</tt> after
68 @ <tt>&lt;head&gt;</tt> in the <a href="setup_header">HTML header</a>!</p>
69 }
70
71 @ <table border="0" cellspacing="7">
72 setup_menu_entry("Users", "setup_ulist",
@@ -1352,11 +1352,11 @@
1352
1353 /* Make sure the header contains <base href="...">. Issue a warning
1354 ** if it does not. */
1355 if( !cgi_header_contains("<base href=") ){
1356 @ <p class="generalError">Please add
1357 @ <tt>&lt;base href="$baseurl/$current_page"&gt</tt> after
1358 @ <tt>&lt;head&gt;</tt> in the header!
1359 @ <input type="submit" name="fixbase" value="Add &lt;base&gt; Now"></p>
1360 }
1361
1362 login_insert_csrf_secret();
1363
--- src/setup.c
+++ src/setup.c
@@ -62,11 +62,11 @@
62
63 /* Make sure the header contains <base href="...">. Issue a warning
64 ** if it does not. */
65 if( !cgi_header_contains("<base href=") ){
66 @ <p class="generalError"><b>Configuration Error:</b> Please add
67 @ <tt>&lt;base href="$baseurl/$current_page"&gt;</tt> after
68 @ <tt>&lt;head&gt;</tt> in the <a href="setup_header">HTML header</a>!</p>
69 }
70
71 @ <table border="0" cellspacing="7">
72 setup_menu_entry("Users", "setup_ulist",
@@ -1352,11 +1352,11 @@
1352
1353 /* Make sure the header contains <base href="...">. Issue a warning
1354 ** if it does not. */
1355 if( !cgi_header_contains("<base href=") ){
1356 @ <p class="generalError">Please add
1357 @ <tt>&lt;base href="$baseurl/$current_page"&gt;</tt> after
1358 @ <tt>&lt;head&gt;</tt> in the header!
1359 @ <input type="submit" name="fixbase" value="Add &lt;base&gt; Now"></p>
1360 }
1361
1362 login_insert_csrf_secret();
1363
+1 -1
--- src/skins.c
+++ src/skins.c
@@ -1218,11 +1218,11 @@
12181218
@ set fossilUrl http://www.fossil-scm.org
12191219
@ </th1>
12201220
@ <a href="$fossilUrl/">Fossil</a>
12211221
@ version $release_version $tclVersion
12221222
@ <a href="$fossilUrl/index.html/info/$version">$manifest_version</a>
1223
-@ <a href="$fossilUrl/fossil/timeline?c=$manifest_date&y=ci">$manifest_date</a>
1223
+@ <a href="$fossilUrl/fossil/timeline?c=$manifest_date&amp;y=ci">$manifest_date</a>
12241224
@ </div>
12251225
@ </body></html>
12261226
@ ');
12271227
;
12281228
12291229
--- src/skins.c
+++ src/skins.c
@@ -1218,11 +1218,11 @@
1218 @ set fossilUrl http://www.fossil-scm.org
1219 @ </th1>
1220 @ <a href="$fossilUrl/">Fossil</a>
1221 @ version $release_version $tclVersion
1222 @ <a href="$fossilUrl/index.html/info/$version">$manifest_version</a>
1223 @ <a href="$fossilUrl/fossil/timeline?c=$manifest_date&y=ci">$manifest_date</a>
1224 @ </div>
1225 @ </body></html>
1226 @ ');
1227 ;
1228
1229
--- src/skins.c
+++ src/skins.c
@@ -1218,11 +1218,11 @@
1218 @ set fossilUrl http://www.fossil-scm.org
1219 @ </th1>
1220 @ <a href="$fossilUrl/">Fossil</a>
1221 @ version $release_version $tclVersion
1222 @ <a href="$fossilUrl/index.html/info/$version">$manifest_version</a>
1223 @ <a href="$fossilUrl/fossil/timeline?c=$manifest_date&amp;y=ci">$manifest_date</a>
1224 @ </div>
1225 @ </body></html>
1226 @ ');
1227 ;
1228
1229
+84 -12
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -673,11 +673,11 @@
673673
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
674674
** [sqlite_version()] and [sqlite_source_id()].
675675
*/
676676
#define SQLITE_VERSION "3.7.15"
677677
#define SQLITE_VERSION_NUMBER 3007015
678
-#define SQLITE_SOURCE_ID "2012-10-30 18:09:46 9dca18f5fea84afbecb314ee1cdfb98430656af3"
678
+#define SQLITE_SOURCE_ID "2012-11-09 21:40:02 5a3b07f0f5dfae7eea870303f52f37d6a17f1da2"
679679
680680
/*
681681
** CAPI3REF: Run-Time Library Version Numbers
682682
** KEYWORDS: sqlite3_version, sqlite3_sourceid
683683
**
@@ -1038,10 +1038,11 @@
10381038
#define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8))
10391039
#define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8))
10401040
#define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8))
10411041
#define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8))
10421042
#define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8))
1043
+#define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8))
10431044
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
10441045
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
10451046
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
10461047
#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
10471048
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
@@ -11008,10 +11009,11 @@
1100811009
int addrInTop; /* Top of the IN loop */
1100911010
} *aInLoop; /* Information about each nested IN operator */
1101011011
} in; /* Used when plan.wsFlags&WHERE_IN_ABLE */
1101111012
Index *pCovidx; /* Possible covering index for WHERE_MULTI_OR */
1101211013
} u;
11014
+ double rOptCost; /* "Optimal" cost for this level */
1101311015
1101411016
/* The following field is really not part of the current level. But
1101511017
** we need a place to cache virtual table index information for each
1101611018
** virtual table in the FROM clause and the WhereLevel structure is
1101711019
** a convenient place since there is one WhereLevel for each FROM clause
@@ -13716,10 +13718,11 @@
1371613718
int nByte = 0; /* Used to accumulate return value */
1371713719
1371813720
db->pnBytesFreed = &nByte;
1371913721
for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
1372013722
sqlite3VdbeClearObject(db, pVdbe);
13723
+ sqlite3DbFree(db, pVdbe);
1372113724
}
1372213725
db->pnBytesFreed = 0;
1372313726
1372413727
*pHighwater = 0;
1372513728
*pCurrent = nByte;
@@ -28219,12 +28222,17 @@
2821928222
int dirSync /* If true, fsync() directory after deleting file */
2822028223
){
2822128224
int rc = SQLITE_OK;
2822228225
UNUSED_PARAMETER(NotUsed);
2822328226
SimulateIOError(return SQLITE_IOERR_DELETE);
28224
- if( osUnlink(zPath)==(-1) && errno!=ENOENT ){
28225
- return unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
28227
+ if( osUnlink(zPath)==(-1) ){
28228
+ if( errno==ENOENT ){
28229
+ rc = SQLITE_IOERR_DELETE_NOENT;
28230
+ }else{
28231
+ rc = unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
28232
+ }
28233
+ return rc;
2822628234
}
2822728235
#ifndef SQLITE_DISABLE_DIRSYNC
2822828236
if( (dirSync & 1)!=0 ){
2822928237
int fd;
2823028238
rc = osOpenDirectory(zPath, &fd);
@@ -40388,10 +40396,11 @@
4038840396
4038940397
rc = pagerPagecount(pPager, &nPage);
4039040398
if( rc ) return rc;
4039140399
if( nPage==0 ){
4039240400
rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
40401
+ if( rc==SQLITE_IOERR_DELETE_NOENT ) rc = SQLITE_OK;
4039340402
isWal = 0;
4039440403
}else{
4039540404
rc = sqlite3OsAccess(
4039640405
pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal
4039740406
);
@@ -77655,12 +77664,14 @@
7765577664
*/
7765677665
assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
7765777666
ExprSetIrreducible(pExpr);
7765877667
pExpr->iAgg = (i16)i;
7765977668
pExpr->pAggInfo = pAggInfo;
77669
+ return WRC_Prune;
77670
+ }else{
77671
+ return WRC_Continue;
7766077672
}
77661
- return WRC_Prune;
7766277673
}
7766377674
}
7766477675
return WRC_Continue;
7766577676
}
7766677677
static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
@@ -77668,13 +77679,14 @@
7766877679
UNUSED_PARAMETER(pSelect);
7766977680
return WRC_Continue;
7767077681
}
7767177682
7767277683
/*
77673
-** Analyze the given expression looking for aggregate functions and
77674
-** for variables that need to be added to the pParse->aAgg[] array.
77675
-** Make additional entries to the pParse->aAgg[] array as necessary.
77684
+** Analyze the pExpr expression looking for aggregate functions and
77685
+** for variables that need to be added to AggInfo object that pNC->pAggInfo
77686
+** points to. Additional entries are made on the AggInfo object as
77687
+** necessary.
7767677688
**
7767777689
** This routine should only be called after the expression has been
7767877690
** analyzed by sqlite3ResolveExprNames().
7767977691
*/
7768077692
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
@@ -85700,10 +85712,59 @@
8570085712
sqlite3_result_double(context, rVal);
8570185713
break;
8570285714
}
8570385715
}
8570485716
}
85717
+
85718
+/*
85719
+** Implementation of the instr() function.
85720
+**
85721
+** instr(haystack,needle) finds the first occurrence of needle
85722
+** in haystack and returns the number of previous characters plus 1,
85723
+** or 0 if needle does not occur within haystack.
85724
+**
85725
+** If both haystack and needle are BLOBs, then the result is one more than
85726
+** the number of bytes in haystack prior to the first occurrence of needle,
85727
+** or 0 if needle never occurs in haystack.
85728
+*/
85729
+static void instrFunc(
85730
+ sqlite3_context *context,
85731
+ int argc,
85732
+ sqlite3_value **argv
85733
+){
85734
+ const unsigned char *zHaystack;
85735
+ const unsigned char *zNeedle;
85736
+ int nHaystack;
85737
+ int nNeedle;
85738
+ int typeHaystack, typeNeedle;
85739
+ int N = 1;
85740
+ int isText;
85741
+
85742
+ typeHaystack = sqlite3_value_type(argv[0]);
85743
+ typeNeedle = sqlite3_value_type(argv[1]);
85744
+ if( typeHaystack==SQLITE_NULL || typeNeedle==SQLITE_NULL ) return;
85745
+ nHaystack = sqlite3_value_bytes(argv[0]);
85746
+ nNeedle = sqlite3_value_bytes(argv[1]);
85747
+ if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){
85748
+ zHaystack = sqlite3_value_blob(argv[0]);
85749
+ zNeedle = sqlite3_value_blob(argv[1]);
85750
+ isText = 0;
85751
+ }else{
85752
+ zHaystack = sqlite3_value_text(argv[0]);
85753
+ zNeedle = sqlite3_value_text(argv[1]);
85754
+ isText = 1;
85755
+ }
85756
+ while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){
85757
+ N++;
85758
+ do{
85759
+ nHaystack--;
85760
+ zHaystack++;
85761
+ }while( isText && (zHaystack[0]&0xc0)==0x80 );
85762
+ }
85763
+ if( nNeedle>nHaystack ) N = 0;
85764
+ sqlite3_result_int(context, N);
85765
+}
8570585766
8570685767
/*
8570785768
** Implementation of the substr() function.
8570885769
**
8570985770
** substr(x,p1,p2) returns p2 characters of x[] beginning with p1.
@@ -87069,10 +87130,11 @@
8706987130
FUNCTION(max, -1, 1, 1, minmaxFunc ),
8707087131
FUNCTION(max, 0, 1, 1, 0 ),
8707187132
AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ),
8707287133
FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
8707387134
FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
87135
+ FUNCTION(instr, 2, 0, 0, instrFunc ),
8707487136
FUNCTION(substr, 2, 0, 0, substrFunc ),
8707587137
FUNCTION(substr, 3, 0, 0, substrFunc ),
8707687138
FUNCTION(abs, 1, 0, 0, absFunc ),
8707787139
#ifndef SQLITE_OMIT_FLOATING_POINT
8707887140
FUNCTION(round, 1, 0, 0, roundFunc ),
@@ -107298,19 +107360,32 @@
107298107360
|| sWBI.cost.plan.u.pIdx==sWBI.pSrc->pIndex );
107299107361
107300107362
if( isOptimal && (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
107301107363
notIndexed |= m;
107302107364
}
107365
+ if( isOptimal ){
107366
+ pWInfo->a[j].rOptCost = sWBI.cost.rCost;
107367
+ }else if( iFrom<nTabList-1 ){
107368
+ /* If two or more tables have nearly the same outer loop cost,
107369
+ ** very different inner loop (optimal) cost, we want to choose
107370
+ ** for the outer loop that table which benefits the least from
107371
+ ** being in the inner loop. The following code scales the
107372
+ ** outer loop cost estimate to accomplish that. */
107373
+ WHERETRACE((" scaling cost from %.1f to %.1f\n",
107374
+ sWBI.cost.rCost,
107375
+ sWBI.cost.rCost/pWInfo->a[j].rOptCost));
107376
+ sWBI.cost.rCost /= pWInfo->a[j].rOptCost;
107377
+ }
107303107378
107304107379
/* Conditions under which this table becomes the best so far:
107305107380
**
107306107381
** (1) The table must not depend on other tables that have not
107307107382
** yet run. (In other words, it must not depend on tables
107308107383
** in inner loops.)
107309107384
**
107310
- ** (2) A full-table-scan plan cannot supercede indexed plan unless
107311
- ** the full-table-scan is an "optimal" plan as defined above.
107385
+ ** (2) (This rule was removed on 2012-11-09. The scaling of the
107386
+ ** cost using the optimal scan cost made this rule obsolete.)
107312107387
**
107313107388
** (3) All tables have an INDEXED BY clause or this table lacks an
107314107389
** INDEXED BY clause or this table uses the specific
107315107390
** index specified by its INDEXED BY clause. This rule ensures
107316107391
** that a best-so-far is always selected even if an impossible
@@ -107321,13 +107396,10 @@
107321107396
**
107322107397
** (4) The plan cost must be lower than prior plans, where "cost"
107323107398
** is defined by the compareCost() function above.
107324107399
*/
107325107400
if( (sWBI.cost.used&sWBI.notValid)==0 /* (1) */
107326
- && (bestJ<0 || (notIndexed&m)!=0 /* (2) */
107327
- || (bestPlan.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
107328
- || (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0)
107329107401
&& (nUnconstrained==0 || sWBI.pSrc->pIndex==0 /* (3) */
107330107402
|| NEVER((sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0))
107331107403
&& (bestJ<0 || compareCost(&sWBI.cost, &bestPlan)) /* (4) */
107332107404
){
107333107405
WHERETRACE((" === table %d (%s) is best so far\n"
107334107406
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -673,11 +673,11 @@
673 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
674 ** [sqlite_version()] and [sqlite_source_id()].
675 */
676 #define SQLITE_VERSION "3.7.15"
677 #define SQLITE_VERSION_NUMBER 3007015
678 #define SQLITE_SOURCE_ID "2012-10-30 18:09:46 9dca18f5fea84afbecb314ee1cdfb98430656af3"
679
680 /*
681 ** CAPI3REF: Run-Time Library Version Numbers
682 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
683 **
@@ -1038,10 +1038,11 @@
1038 #define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8))
1039 #define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8))
1040 #define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8))
1041 #define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8))
1042 #define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8))
 
1043 #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
1044 #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
1045 #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
1046 #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
1047 #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
@@ -11008,10 +11009,11 @@
11008 int addrInTop; /* Top of the IN loop */
11009 } *aInLoop; /* Information about each nested IN operator */
11010 } in; /* Used when plan.wsFlags&WHERE_IN_ABLE */
11011 Index *pCovidx; /* Possible covering index for WHERE_MULTI_OR */
11012 } u;
 
11013
11014 /* The following field is really not part of the current level. But
11015 ** we need a place to cache virtual table index information for each
11016 ** virtual table in the FROM clause and the WhereLevel structure is
11017 ** a convenient place since there is one WhereLevel for each FROM clause
@@ -13716,10 +13718,11 @@
13716 int nByte = 0; /* Used to accumulate return value */
13717
13718 db->pnBytesFreed = &nByte;
13719 for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
13720 sqlite3VdbeClearObject(db, pVdbe);
 
13721 }
13722 db->pnBytesFreed = 0;
13723
13724 *pHighwater = 0;
13725 *pCurrent = nByte;
@@ -28219,12 +28222,17 @@
28219 int dirSync /* If true, fsync() directory after deleting file */
28220 ){
28221 int rc = SQLITE_OK;
28222 UNUSED_PARAMETER(NotUsed);
28223 SimulateIOError(return SQLITE_IOERR_DELETE);
28224 if( osUnlink(zPath)==(-1) && errno!=ENOENT ){
28225 return unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
 
 
 
 
 
28226 }
28227 #ifndef SQLITE_DISABLE_DIRSYNC
28228 if( (dirSync & 1)!=0 ){
28229 int fd;
28230 rc = osOpenDirectory(zPath, &fd);
@@ -40388,10 +40396,11 @@
40388
40389 rc = pagerPagecount(pPager, &nPage);
40390 if( rc ) return rc;
40391 if( nPage==0 ){
40392 rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
 
40393 isWal = 0;
40394 }else{
40395 rc = sqlite3OsAccess(
40396 pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal
40397 );
@@ -77655,12 +77664,14 @@
77655 */
77656 assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
77657 ExprSetIrreducible(pExpr);
77658 pExpr->iAgg = (i16)i;
77659 pExpr->pAggInfo = pAggInfo;
 
 
 
77660 }
77661 return WRC_Prune;
77662 }
77663 }
77664 return WRC_Continue;
77665 }
77666 static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
@@ -77668,13 +77679,14 @@
77668 UNUSED_PARAMETER(pSelect);
77669 return WRC_Continue;
77670 }
77671
77672 /*
77673 ** Analyze the given expression looking for aggregate functions and
77674 ** for variables that need to be added to the pParse->aAgg[] array.
77675 ** Make additional entries to the pParse->aAgg[] array as necessary.
 
77676 **
77677 ** This routine should only be called after the expression has been
77678 ** analyzed by sqlite3ResolveExprNames().
77679 */
77680 SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
@@ -85700,10 +85712,59 @@
85700 sqlite3_result_double(context, rVal);
85701 break;
85702 }
85703 }
85704 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85705
85706 /*
85707 ** Implementation of the substr() function.
85708 **
85709 ** substr(x,p1,p2) returns p2 characters of x[] beginning with p1.
@@ -87069,10 +87130,11 @@
87069 FUNCTION(max, -1, 1, 1, minmaxFunc ),
87070 FUNCTION(max, 0, 1, 1, 0 ),
87071 AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ),
87072 FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
87073 FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
 
87074 FUNCTION(substr, 2, 0, 0, substrFunc ),
87075 FUNCTION(substr, 3, 0, 0, substrFunc ),
87076 FUNCTION(abs, 1, 0, 0, absFunc ),
87077 #ifndef SQLITE_OMIT_FLOATING_POINT
87078 FUNCTION(round, 1, 0, 0, roundFunc ),
@@ -107298,19 +107360,32 @@
107298 || sWBI.cost.plan.u.pIdx==sWBI.pSrc->pIndex );
107299
107300 if( isOptimal && (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
107301 notIndexed |= m;
107302 }
 
 
 
 
 
 
 
 
 
 
 
 
 
107303
107304 /* Conditions under which this table becomes the best so far:
107305 **
107306 ** (1) The table must not depend on other tables that have not
107307 ** yet run. (In other words, it must not depend on tables
107308 ** in inner loops.)
107309 **
107310 ** (2) A full-table-scan plan cannot supercede indexed plan unless
107311 ** the full-table-scan is an "optimal" plan as defined above.
107312 **
107313 ** (3) All tables have an INDEXED BY clause or this table lacks an
107314 ** INDEXED BY clause or this table uses the specific
107315 ** index specified by its INDEXED BY clause. This rule ensures
107316 ** that a best-so-far is always selected even if an impossible
@@ -107321,13 +107396,10 @@
107321 **
107322 ** (4) The plan cost must be lower than prior plans, where "cost"
107323 ** is defined by the compareCost() function above.
107324 */
107325 if( (sWBI.cost.used&sWBI.notValid)==0 /* (1) */
107326 && (bestJ<0 || (notIndexed&m)!=0 /* (2) */
107327 || (bestPlan.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
107328 || (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0)
107329 && (nUnconstrained==0 || sWBI.pSrc->pIndex==0 /* (3) */
107330 || NEVER((sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0))
107331 && (bestJ<0 || compareCost(&sWBI.cost, &bestPlan)) /* (4) */
107332 ){
107333 WHERETRACE((" === table %d (%s) is best so far\n"
107334
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -673,11 +673,11 @@
673 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
674 ** [sqlite_version()] and [sqlite_source_id()].
675 */
676 #define SQLITE_VERSION "3.7.15"
677 #define SQLITE_VERSION_NUMBER 3007015
678 #define SQLITE_SOURCE_ID "2012-11-09 21:40:02 5a3b07f0f5dfae7eea870303f52f37d6a17f1da2"
679
680 /*
681 ** CAPI3REF: Run-Time Library Version Numbers
682 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
683 **
@@ -1038,10 +1038,11 @@
1038 #define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8))
1039 #define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8))
1040 #define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8))
1041 #define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8))
1042 #define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8))
1043 #define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8))
1044 #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
1045 #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
1046 #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
1047 #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
1048 #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
@@ -11008,10 +11009,11 @@
11009 int addrInTop; /* Top of the IN loop */
11010 } *aInLoop; /* Information about each nested IN operator */
11011 } in; /* Used when plan.wsFlags&WHERE_IN_ABLE */
11012 Index *pCovidx; /* Possible covering index for WHERE_MULTI_OR */
11013 } u;
11014 double rOptCost; /* "Optimal" cost for this level */
11015
11016 /* The following field is really not part of the current level. But
11017 ** we need a place to cache virtual table index information for each
11018 ** virtual table in the FROM clause and the WhereLevel structure is
11019 ** a convenient place since there is one WhereLevel for each FROM clause
@@ -13716,10 +13718,11 @@
13718 int nByte = 0; /* Used to accumulate return value */
13719
13720 db->pnBytesFreed = &nByte;
13721 for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
13722 sqlite3VdbeClearObject(db, pVdbe);
13723 sqlite3DbFree(db, pVdbe);
13724 }
13725 db->pnBytesFreed = 0;
13726
13727 *pHighwater = 0;
13728 *pCurrent = nByte;
@@ -28219,12 +28222,17 @@
28222 int dirSync /* If true, fsync() directory after deleting file */
28223 ){
28224 int rc = SQLITE_OK;
28225 UNUSED_PARAMETER(NotUsed);
28226 SimulateIOError(return SQLITE_IOERR_DELETE);
28227 if( osUnlink(zPath)==(-1) ){
28228 if( errno==ENOENT ){
28229 rc = SQLITE_IOERR_DELETE_NOENT;
28230 }else{
28231 rc = unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
28232 }
28233 return rc;
28234 }
28235 #ifndef SQLITE_DISABLE_DIRSYNC
28236 if( (dirSync & 1)!=0 ){
28237 int fd;
28238 rc = osOpenDirectory(zPath, &fd);
@@ -40388,10 +40396,11 @@
40396
40397 rc = pagerPagecount(pPager, &nPage);
40398 if( rc ) return rc;
40399 if( nPage==0 ){
40400 rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
40401 if( rc==SQLITE_IOERR_DELETE_NOENT ) rc = SQLITE_OK;
40402 isWal = 0;
40403 }else{
40404 rc = sqlite3OsAccess(
40405 pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal
40406 );
@@ -77655,12 +77664,14 @@
77664 */
77665 assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
77666 ExprSetIrreducible(pExpr);
77667 pExpr->iAgg = (i16)i;
77668 pExpr->pAggInfo = pAggInfo;
77669 return WRC_Prune;
77670 }else{
77671 return WRC_Continue;
77672 }
 
77673 }
77674 }
77675 return WRC_Continue;
77676 }
77677 static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
@@ -77668,13 +77679,14 @@
77679 UNUSED_PARAMETER(pSelect);
77680 return WRC_Continue;
77681 }
77682
77683 /*
77684 ** Analyze the pExpr expression looking for aggregate functions and
77685 ** for variables that need to be added to AggInfo object that pNC->pAggInfo
77686 ** points to. Additional entries are made on the AggInfo object as
77687 ** necessary.
77688 **
77689 ** This routine should only be called after the expression has been
77690 ** analyzed by sqlite3ResolveExprNames().
77691 */
77692 SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
@@ -85700,10 +85712,59 @@
85712 sqlite3_result_double(context, rVal);
85713 break;
85714 }
85715 }
85716 }
85717
85718 /*
85719 ** Implementation of the instr() function.
85720 **
85721 ** instr(haystack,needle) finds the first occurrence of needle
85722 ** in haystack and returns the number of previous characters plus 1,
85723 ** or 0 if needle does not occur within haystack.
85724 **
85725 ** If both haystack and needle are BLOBs, then the result is one more than
85726 ** the number of bytes in haystack prior to the first occurrence of needle,
85727 ** or 0 if needle never occurs in haystack.
85728 */
85729 static void instrFunc(
85730 sqlite3_context *context,
85731 int argc,
85732 sqlite3_value **argv
85733 ){
85734 const unsigned char *zHaystack;
85735 const unsigned char *zNeedle;
85736 int nHaystack;
85737 int nNeedle;
85738 int typeHaystack, typeNeedle;
85739 int N = 1;
85740 int isText;
85741
85742 typeHaystack = sqlite3_value_type(argv[0]);
85743 typeNeedle = sqlite3_value_type(argv[1]);
85744 if( typeHaystack==SQLITE_NULL || typeNeedle==SQLITE_NULL ) return;
85745 nHaystack = sqlite3_value_bytes(argv[0]);
85746 nNeedle = sqlite3_value_bytes(argv[1]);
85747 if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){
85748 zHaystack = sqlite3_value_blob(argv[0]);
85749 zNeedle = sqlite3_value_blob(argv[1]);
85750 isText = 0;
85751 }else{
85752 zHaystack = sqlite3_value_text(argv[0]);
85753 zNeedle = sqlite3_value_text(argv[1]);
85754 isText = 1;
85755 }
85756 while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){
85757 N++;
85758 do{
85759 nHaystack--;
85760 zHaystack++;
85761 }while( isText && (zHaystack[0]&0xc0)==0x80 );
85762 }
85763 if( nNeedle>nHaystack ) N = 0;
85764 sqlite3_result_int(context, N);
85765 }
85766
85767 /*
85768 ** Implementation of the substr() function.
85769 **
85770 ** substr(x,p1,p2) returns p2 characters of x[] beginning with p1.
@@ -87069,10 +87130,11 @@
87130 FUNCTION(max, -1, 1, 1, minmaxFunc ),
87131 FUNCTION(max, 0, 1, 1, 0 ),
87132 AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ),
87133 FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
87134 FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
87135 FUNCTION(instr, 2, 0, 0, instrFunc ),
87136 FUNCTION(substr, 2, 0, 0, substrFunc ),
87137 FUNCTION(substr, 3, 0, 0, substrFunc ),
87138 FUNCTION(abs, 1, 0, 0, absFunc ),
87139 #ifndef SQLITE_OMIT_FLOATING_POINT
87140 FUNCTION(round, 1, 0, 0, roundFunc ),
@@ -107298,19 +107360,32 @@
107360 || sWBI.cost.plan.u.pIdx==sWBI.pSrc->pIndex );
107361
107362 if( isOptimal && (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
107363 notIndexed |= m;
107364 }
107365 if( isOptimal ){
107366 pWInfo->a[j].rOptCost = sWBI.cost.rCost;
107367 }else if( iFrom<nTabList-1 ){
107368 /* If two or more tables have nearly the same outer loop cost,
107369 ** very different inner loop (optimal) cost, we want to choose
107370 ** for the outer loop that table which benefits the least from
107371 ** being in the inner loop. The following code scales the
107372 ** outer loop cost estimate to accomplish that. */
107373 WHERETRACE((" scaling cost from %.1f to %.1f\n",
107374 sWBI.cost.rCost,
107375 sWBI.cost.rCost/pWInfo->a[j].rOptCost));
107376 sWBI.cost.rCost /= pWInfo->a[j].rOptCost;
107377 }
107378
107379 /* Conditions under which this table becomes the best so far:
107380 **
107381 ** (1) The table must not depend on other tables that have not
107382 ** yet run. (In other words, it must not depend on tables
107383 ** in inner loops.)
107384 **
107385 ** (2) (This rule was removed on 2012-11-09. The scaling of the
107386 ** cost using the optimal scan cost made this rule obsolete.)
107387 **
107388 ** (3) All tables have an INDEXED BY clause or this table lacks an
107389 ** INDEXED BY clause or this table uses the specific
107390 ** index specified by its INDEXED BY clause. This rule ensures
107391 ** that a best-so-far is always selected even if an impossible
@@ -107321,13 +107396,10 @@
107396 **
107397 ** (4) The plan cost must be lower than prior plans, where "cost"
107398 ** is defined by the compareCost() function above.
107399 */
107400 if( (sWBI.cost.used&sWBI.notValid)==0 /* (1) */
 
 
 
107401 && (nUnconstrained==0 || sWBI.pSrc->pIndex==0 /* (3) */
107402 || NEVER((sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0))
107403 && (bestJ<0 || compareCost(&sWBI.cost, &bestPlan)) /* (4) */
107404 ){
107405 WHERETRACE((" === table %d (%s) is best so far\n"
107406
+2 -1
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -107,11 +107,11 @@
107107
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108108
** [sqlite_version()] and [sqlite_source_id()].
109109
*/
110110
#define SQLITE_VERSION "3.7.15"
111111
#define SQLITE_VERSION_NUMBER 3007015
112
-#define SQLITE_SOURCE_ID "2012-10-30 18:09:46 9dca18f5fea84afbecb314ee1cdfb98430656af3"
112
+#define SQLITE_SOURCE_ID "2012-11-09 21:40:02 5a3b07f0f5dfae7eea870303f52f37d6a17f1da2"
113113
114114
/*
115115
** CAPI3REF: Run-Time Library Version Numbers
116116
** KEYWORDS: sqlite3_version, sqlite3_sourceid
117117
**
@@ -472,10 +472,11 @@
472472
#define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8))
473473
#define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8))
474474
#define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8))
475475
#define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8))
476476
#define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8))
477
+#define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8))
477478
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
478479
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
479480
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
480481
#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
481482
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
482483
--- 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.7.15"
111 #define SQLITE_VERSION_NUMBER 3007015
112 #define SQLITE_SOURCE_ID "2012-10-30 18:09:46 9dca18f5fea84afbecb314ee1cdfb98430656af3"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
@@ -472,10 +472,11 @@
472 #define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8))
473 #define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8))
474 #define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8))
475 #define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8))
476 #define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8))
 
477 #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
478 #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
479 #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
480 #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
481 #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
482
--- 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.7.15"
111 #define SQLITE_VERSION_NUMBER 3007015
112 #define SQLITE_SOURCE_ID "2012-11-09 21:40:02 5a3b07f0f5dfae7eea870303f52f37d6a17f1da2"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
@@ -472,10 +472,11 @@
472 #define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8))
473 #define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8))
474 #define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8))
475 #define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8))
476 #define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8))
477 #define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8))
478 #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
479 #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
480 #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
481 #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
482 #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
483
+7 -3
--- src/style.c
+++ src/style.c
@@ -90,11 +90,13 @@
9090
va_list ap;
9191
va_start(ap, zFormat);
9292
zUrl = vmprintf(zFormat, ap);
9393
va_end(ap);
9494
if( g.perm.Hyperlink && !g.javascriptHyperlink ){
95
- return mprintf("<a %s href=\"%z\">", zExtra, zUrl);
95
+ char *zHUrl = mprintf("<a %s href=\"%h\">", zExtra, zUrl);
96
+ fossil_free(zUrl);
97
+ return zHUrl;
9698
}
9799
if( nHref>=nHrefAlloc ){
98100
nHrefAlloc = nHrefAlloc*2 + 10;
99101
aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0]));
100102
}
@@ -106,11 +108,13 @@
106108
va_list ap;
107109
va_start(ap, zFormat);
108110
zUrl = vmprintf(zFormat, ap);
109111
va_end(ap);
110112
if( g.perm.Hyperlink && !g.javascriptHyperlink ){
111
- return mprintf("<a href=\"%z\">", zUrl);
113
+ char *zHUrl = mprintf("<a href=\"%h\">", zUrl);
114
+ fossil_free(zUrl);
115
+ return zHUrl;
112116
}
113117
if( nHref>=nHrefAlloc ){
114118
nHrefAlloc = nHrefAlloc*2 + 10;
115119
aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0]));
116120
}
@@ -278,11 +282,11 @@
278282
for(i=0; i<nSubmenu; i++){
279283
struct Submenu *p = &aSubmenu[i];
280284
if( p->zLink==0 ){
281285
@ <span class="label">%h(p->zLabel)</span>
282286
}else{
283
- @ <a class="label" href="%s(p->zLink)">%h(p->zLabel)</a>
287
+ @ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a>
284288
}
285289
}
286290
@ </div>
287291
}
288292
style_ad_unit();
289293
--- src/style.c
+++ src/style.c
@@ -90,11 +90,13 @@
90 va_list ap;
91 va_start(ap, zFormat);
92 zUrl = vmprintf(zFormat, ap);
93 va_end(ap);
94 if( g.perm.Hyperlink && !g.javascriptHyperlink ){
95 return mprintf("<a %s href=\"%z\">", zExtra, zUrl);
 
 
96 }
97 if( nHref>=nHrefAlloc ){
98 nHrefAlloc = nHrefAlloc*2 + 10;
99 aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0]));
100 }
@@ -106,11 +108,13 @@
106 va_list ap;
107 va_start(ap, zFormat);
108 zUrl = vmprintf(zFormat, ap);
109 va_end(ap);
110 if( g.perm.Hyperlink && !g.javascriptHyperlink ){
111 return mprintf("<a href=\"%z\">", zUrl);
 
 
112 }
113 if( nHref>=nHrefAlloc ){
114 nHrefAlloc = nHrefAlloc*2 + 10;
115 aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0]));
116 }
@@ -278,11 +282,11 @@
278 for(i=0; i<nSubmenu; i++){
279 struct Submenu *p = &aSubmenu[i];
280 if( p->zLink==0 ){
281 @ <span class="label">%h(p->zLabel)</span>
282 }else{
283 @ <a class="label" href="%s(p->zLink)">%h(p->zLabel)</a>
284 }
285 }
286 @ </div>
287 }
288 style_ad_unit();
289
--- src/style.c
+++ src/style.c
@@ -90,11 +90,13 @@
90 va_list ap;
91 va_start(ap, zFormat);
92 zUrl = vmprintf(zFormat, ap);
93 va_end(ap);
94 if( g.perm.Hyperlink && !g.javascriptHyperlink ){
95 char *zHUrl = mprintf("<a %s href=\"%h\">", zExtra, zUrl);
96 fossil_free(zUrl);
97 return zHUrl;
98 }
99 if( nHref>=nHrefAlloc ){
100 nHrefAlloc = nHrefAlloc*2 + 10;
101 aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0]));
102 }
@@ -106,11 +108,13 @@
108 va_list ap;
109 va_start(ap, zFormat);
110 zUrl = vmprintf(zFormat, ap);
111 va_end(ap);
112 if( g.perm.Hyperlink && !g.javascriptHyperlink ){
113 char *zHUrl = mprintf("<a href=\"%h\">", zUrl);
114 fossil_free(zUrl);
115 return zHUrl;
116 }
117 if( nHref>=nHrefAlloc ){
118 nHrefAlloc = nHrefAlloc*2 + 10;
119 aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0]));
120 }
@@ -278,11 +282,11 @@
282 for(i=0; i<nSubmenu; i++){
283 struct Submenu *p = &aSubmenu[i];
284 if( p->zLink==0 ){
285 @ <span class="label">%h(p->zLabel)</span>
286 }else{
287 @ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a>
288 }
289 }
290 @ </div>
291 }
292 style_ad_unit();
293
+5 -5
--- src/timeline.c
+++ src/timeline.c
@@ -276,11 +276,11 @@
276276
prevWasDivider = 0;
277277
if( memcmp(zDate, zPrevDate, 10) ){
278278
sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
279279
@ <tr><td>
280280
@ <div class="divider">%s(zPrevDate)</div>
281
- @ </td></tr>
281
+ @ </td><td></td><td></td></tr>
282282
}
283283
memcpy(zTime, &zDate[11], 5);
284284
zTime[5] = 0;
285285
@ <tr>
286286
@ <td class="timelineTime">%s(zTime)</td>
@@ -373,11 +373,11 @@
373373
/* Generate the "user: USERNAME" at the end of the comment, together
374374
** with a hyperlink to another timeline for that user.
375375
*/
376376
if( zTagList && zTagList[0]==0 ) zTagList = 0;
377377
if( g.perm.Hyperlink && fossil_strcmp(zUser, zThisUser)!=0 ){
378
- char *zLink = mprintf("%R/timeline?u=%h&amp;c=%t&amp;nd", zUser, zDate);
378
+ char *zLink = mprintf("%R/timeline?u=%h&c=%t&amp;nd", zUser, zDate);
379379
@ (user: %z(href("%z",zLink))%h(zUser)</a>%s(zTagList?",":"\051")
380380
}else{
381381
@ (user: %h(zUser)%s(zTagList?",":"\051")
382382
}
383383
@@ -398,11 +398,11 @@
398398
while( z && z[0] ){
399399
for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){}
400400
if( zThisTag==0 || memcmp(z, zThisTag, i)!=0 || zThisTag[i]!=0 ){
401401
blob_appendf(&links,
402402
"%z%#h</a>%.2s",
403
- href("%R/timeline?r=%#t&amp;nd&amp;c=%t",i,z,zDate), i,z, &z[i]
403
+ href("%R/timeline?r=%#t&nd&c=%t",i,z,zDate), i,z, &z[i]
404404
);
405405
}else{
406406
blob_appendf(&links, "%#h", i+2, z);
407407
}
408408
if( z[i]==0 ) break;
@@ -494,11 +494,11 @@
494494
/* style is not moved to css, because this is
495495
** a technical div for the timeline graph
496496
*/
497497
@ <tr><td></td><td>
498498
@ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div>
499
- @ </td></tr>
499
+ @ </td><td></td></tr>
500500
}
501501
}
502502
@ </table>
503503
if( fchngQueryInit ) db_finalize(&fchngQuery);
504504
timeline_output_graph_javascript(pGraph, (tmFlags & TIMELINE_DISJOINT)!=0);
@@ -1662,10 +1662,10 @@
16621662
" AND blob.rid=c.cid"
16631663
);
16641664
while( db_step(&q)==SQLITE_ROW ){
16651665
const char *zUuid = db_column_text(&q, 0);
16661666
@ <li>
1667
- @ <a href="%s(g.zTop)/timeline?p=%S(zUuid)&d=%S(zUuid)">%S(zUuid)</a>
1667
+ @ <a href="%s(g.zTop)/timeline?p=%S(zUuid)&amp;d=%S(zUuid)">%S(zUuid)</a>
16681668
}
16691669
db_finalize(&q);
16701670
style_footer();
16711671
}
16721672
--- src/timeline.c
+++ src/timeline.c
@@ -276,11 +276,11 @@
276 prevWasDivider = 0;
277 if( memcmp(zDate, zPrevDate, 10) ){
278 sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
279 @ <tr><td>
280 @ <div class="divider">%s(zPrevDate)</div>
281 @ </td></tr>
282 }
283 memcpy(zTime, &zDate[11], 5);
284 zTime[5] = 0;
285 @ <tr>
286 @ <td class="timelineTime">%s(zTime)</td>
@@ -373,11 +373,11 @@
373 /* Generate the "user: USERNAME" at the end of the comment, together
374 ** with a hyperlink to another timeline for that user.
375 */
376 if( zTagList && zTagList[0]==0 ) zTagList = 0;
377 if( g.perm.Hyperlink && fossil_strcmp(zUser, zThisUser)!=0 ){
378 char *zLink = mprintf("%R/timeline?u=%h&amp;c=%t&amp;nd", zUser, zDate);
379 @ (user: %z(href("%z",zLink))%h(zUser)</a>%s(zTagList?",":"\051")
380 }else{
381 @ (user: %h(zUser)%s(zTagList?",":"\051")
382 }
383
@@ -398,11 +398,11 @@
398 while( z && z[0] ){
399 for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){}
400 if( zThisTag==0 || memcmp(z, zThisTag, i)!=0 || zThisTag[i]!=0 ){
401 blob_appendf(&links,
402 "%z%#h</a>%.2s",
403 href("%R/timeline?r=%#t&amp;nd&amp;c=%t",i,z,zDate), i,z, &z[i]
404 );
405 }else{
406 blob_appendf(&links, "%#h", i+2, z);
407 }
408 if( z[i]==0 ) break;
@@ -494,11 +494,11 @@
494 /* style is not moved to css, because this is
495 ** a technical div for the timeline graph
496 */
497 @ <tr><td></td><td>
498 @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div>
499 @ </td></tr>
500 }
501 }
502 @ </table>
503 if( fchngQueryInit ) db_finalize(&fchngQuery);
504 timeline_output_graph_javascript(pGraph, (tmFlags & TIMELINE_DISJOINT)!=0);
@@ -1662,10 +1662,10 @@
1662 " AND blob.rid=c.cid"
1663 );
1664 while( db_step(&q)==SQLITE_ROW ){
1665 const char *zUuid = db_column_text(&q, 0);
1666 @ <li>
1667 @ <a href="%s(g.zTop)/timeline?p=%S(zUuid)&d=%S(zUuid)">%S(zUuid)</a>
1668 }
1669 db_finalize(&q);
1670 style_footer();
1671 }
1672
--- src/timeline.c
+++ src/timeline.c
@@ -276,11 +276,11 @@
276 prevWasDivider = 0;
277 if( memcmp(zDate, zPrevDate, 10) ){
278 sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
279 @ <tr><td>
280 @ <div class="divider">%s(zPrevDate)</div>
281 @ </td><td></td><td></td></tr>
282 }
283 memcpy(zTime, &zDate[11], 5);
284 zTime[5] = 0;
285 @ <tr>
286 @ <td class="timelineTime">%s(zTime)</td>
@@ -373,11 +373,11 @@
373 /* Generate the "user: USERNAME" at the end of the comment, together
374 ** with a hyperlink to another timeline for that user.
375 */
376 if( zTagList && zTagList[0]==0 ) zTagList = 0;
377 if( g.perm.Hyperlink && fossil_strcmp(zUser, zThisUser)!=0 ){
378 char *zLink = mprintf("%R/timeline?u=%h&c=%t&amp;nd", zUser, zDate);
379 @ (user: %z(href("%z",zLink))%h(zUser)</a>%s(zTagList?",":"\051")
380 }else{
381 @ (user: %h(zUser)%s(zTagList?",":"\051")
382 }
383
@@ -398,11 +398,11 @@
398 while( z && z[0] ){
399 for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){}
400 if( zThisTag==0 || memcmp(z, zThisTag, i)!=0 || zThisTag[i]!=0 ){
401 blob_appendf(&links,
402 "%z%#h</a>%.2s",
403 href("%R/timeline?r=%#t&nd&c=%t",i,z,zDate), i,z, &z[i]
404 );
405 }else{
406 blob_appendf(&links, "%#h", i+2, z);
407 }
408 if( z[i]==0 ) break;
@@ -494,11 +494,11 @@
494 /* style is not moved to css, because this is
495 ** a technical div for the timeline graph
496 */
497 @ <tr><td></td><td>
498 @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div>
499 @ </td><td></td></tr>
500 }
501 }
502 @ </table>
503 if( fchngQueryInit ) db_finalize(&fchngQuery);
504 timeline_output_graph_javascript(pGraph, (tmFlags & TIMELINE_DISJOINT)!=0);
@@ -1662,10 +1662,10 @@
1662 " AND blob.rid=c.cid"
1663 );
1664 while( db_step(&q)==SQLITE_ROW ){
1665 const char *zUuid = db_column_text(&q, 0);
1666 @ <li>
1667 @ <a href="%s(g.zTop)/timeline?p=%S(zUuid)&amp;d=%S(zUuid)">%S(zUuid)</a>
1668 }
1669 db_finalize(&q);
1670 style_footer();
1671 }
1672
+1 -1
--- src/url.c
+++ src/url.c
@@ -352,11 +352,11 @@
352352
z = zValue2;
353353
if( z==0 ) continue;
354354
}
355355
blob_appendf(&p->url, "%s%s", zSep, p->azName[i]);
356356
if( z && z[0] ) blob_appendf(&p->url, "=%T", z);
357
- zSep = "&amp;";
357
+ zSep = "&";
358358
}
359359
if( zName1 && zValue1 ){
360360
blob_appendf(&p->url, "%s%s", zSep, zName1);
361361
if( zValue1[0] ) blob_appendf(&p->url, "=%T", zValue1);
362362
}
363363
--- src/url.c
+++ src/url.c
@@ -352,11 +352,11 @@
352 z = zValue2;
353 if( z==0 ) continue;
354 }
355 blob_appendf(&p->url, "%s%s", zSep, p->azName[i]);
356 if( z && z[0] ) blob_appendf(&p->url, "=%T", z);
357 zSep = "&amp;";
358 }
359 if( zName1 && zValue1 ){
360 blob_appendf(&p->url, "%s%s", zSep, zName1);
361 if( zValue1[0] ) blob_appendf(&p->url, "=%T", zValue1);
362 }
363
--- src/url.c
+++ src/url.c
@@ -352,11 +352,11 @@
352 z = zValue2;
353 if( z==0 ) continue;
354 }
355 blob_appendf(&p->url, "%s%s", zSep, p->azName[i]);
356 if( z && z[0] ) blob_appendf(&p->url, "=%T", z);
357 zSep = "&";
358 }
359 if( zName1 && zValue1 ){
360 blob_appendf(&p->url, "%s%s", zSep, zName1);
361 if( zValue1[0] ) blob_appendf(&p->url, "=%T", zValue1);
362 }
363
+2 -2
--- src/wysiwyg.c
+++ src/wysiwyg.c
@@ -173,17 +173,17 @@
173173
@ R9qmKBt1iGzHmOrm6Sz4OXw3Odz4Cl2ZSnw6KxyqO306K63bG70bTB0rDI3bvI4P/////////
174174
@ //////////////////////////yH5BAEKAB8ALAAAAAAWABYAAAVP4CeOZGmeaKqubEs2Cekk
175175
@ ErvEI1zZuOgYFlakECEZFi0GgTGKEBATFmJAVXweVOoKEQgABB9IQDCmrLpjETrQQlhHjINrT
176176
@ q/b7/i8fp8PAQA7" />
177177
178
- @ <img class="intLink" title="Add indentation"
178
+ @ <img class="intLink" title="Delete indentation"
179179
@ onclick="formatDoc('outdent');"
180180
@ src="data:image/gif;base64,R0lGODlhFgAWAMIHAAAAADljwliE35GjuaezxtDV3NHa7P
181181
@ ///yH5BAEAAAcALAAAAAAWABYAAAM2eLrc/jDKCQG9F2i7u8agQgyK1z2EIBil+TWqEMxhMcz
182182
@ sYVJ3e4ahk+sFnAgtxSQDqWw6n5cEADs=" />
183183
184
- @ <img class="intLink" title="Delete indentation"
184
+ @ <img class="intLink" title="Add indentation"
185185
@ onclick="formatDoc('indent');"
186186
@ src="data:image/gif;base64,R0lGODlhFgAWAOMIAAAAADljwl9vj1iE35GjuaezxtDV3N
187187
@ Ha7P///////////////////////////////yH5BAEAAAgALAAAAAAWABYAAAQ7EMlJq704650
188188
@ B/x8gemMpgugwHJNZXodKsO5oqUOgo5KhBwWESyMQsCRDHu9VOyk5TM9zSpFSr9gsJwIAOw==">
189189
190190
191191
ADDED test/many-www.tcl
192192
ADDED test/valgrind-www.tcl
--- src/wysiwyg.c
+++ src/wysiwyg.c
@@ -173,17 +173,17 @@
173 @ R9qmKBt1iGzHmOrm6Sz4OXw3Odz4Cl2ZSnw6KxyqO306K63bG70bTB0rDI3bvI4P/////////
174 @ //////////////////////////yH5BAEKAB8ALAAAAAAWABYAAAVP4CeOZGmeaKqubEs2Cekk
175 @ ErvEI1zZuOgYFlakECEZFi0GgTGKEBATFmJAVXweVOoKEQgABB9IQDCmrLpjETrQQlhHjINrT
176 @ q/b7/i8fp8PAQA7" />
177
178 @ <img class="intLink" title="Add indentation"
179 @ onclick="formatDoc('outdent');"
180 @ src="data:image/gif;base64,R0lGODlhFgAWAMIHAAAAADljwliE35GjuaezxtDV3NHa7P
181 @ ///yH5BAEAAAcALAAAAAAWABYAAAM2eLrc/jDKCQG9F2i7u8agQgyK1z2EIBil+TWqEMxhMcz
182 @ sYVJ3e4ahk+sFnAgtxSQDqWw6n5cEADs=" />
183
184 @ <img class="intLink" title="Delete indentation"
185 @ onclick="formatDoc('indent');"
186 @ src="data:image/gif;base64,R0lGODlhFgAWAOMIAAAAADljwl9vj1iE35GjuaezxtDV3N
187 @ Ha7P///////////////////////////////yH5BAEAAAgALAAAAAAWABYAAAQ7EMlJq704650
188 @ B/x8gemMpgugwHJNZXodKsO5oqUOgo5KhBwWESyMQsCRDHu9VOyk5TM9zSpFSr9gsJwIAOw==">
189
190
191 DDED test/many-www.tcl
192 DDED test/valgrind-www.tcl
--- src/wysiwyg.c
+++ src/wysiwyg.c
@@ -173,17 +173,17 @@
173 @ R9qmKBt1iGzHmOrm6Sz4OXw3Odz4Cl2ZSnw6KxyqO306K63bG70bTB0rDI3bvI4P/////////
174 @ //////////////////////////yH5BAEKAB8ALAAAAAAWABYAAAVP4CeOZGmeaKqubEs2Cekk
175 @ ErvEI1zZuOgYFlakECEZFi0GgTGKEBATFmJAVXweVOoKEQgABB9IQDCmrLpjETrQQlhHjINrT
176 @ q/b7/i8fp8PAQA7" />
177
178 @ <img class="intLink" title="Delete indentation"
179 @ onclick="formatDoc('outdent');"
180 @ src="data:image/gif;base64,R0lGODlhFgAWAMIHAAAAADljwliE35GjuaezxtDV3NHa7P
181 @ ///yH5BAEAAAcALAAAAAAWABYAAAM2eLrc/jDKCQG9F2i7u8agQgyK1z2EIBil+TWqEMxhMcz
182 @ sYVJ3e4ahk+sFnAgtxSQDqWw6n5cEADs=" />
183
184 @ <img class="intLink" title="Add indentation"
185 @ onclick="formatDoc('indent');"
186 @ src="data:image/gif;base64,R0lGODlhFgAWAOMIAAAAADljwl9vj1iE35GjuaezxtDV3N
187 @ Ha7P///////////////////////////////yH5BAEAAAgALAAAAAAWABYAAAQ7EMlJq704650
188 @ B/x8gemMpgugwHJNZXodKsO5oqUOgo5KhBwWESyMQsCRDHu9VOyk5TM9zSpFSr9gsJwIAOw==">
189
190
191 DDED test/many-www.tcl
192 DDED test/valgrind-www.tcl
--- a/test/many-www.tcl
+++ b/test/many-www.tcl
@@ -0,0 +1,78 @@
1
+#!/usr/bin/tclsh
2
+#
3
+# Run this script from within any open Fossil checkout. Example:
4
+#
5
+# tclsh many-www.tcl | tee out.txt
6
+#
7
+# About 10,000 different web page requests will be made. Each is timed
8
+# and the time shown on output. Use this script to search for segfault problems
9
+# or to look for pages that need optimization.
10
+#
11
+proc run_query {url} {
12
+ set fd [open q.txt w]
13
+ puts $fd "GET $url HTTP/1.0\r\n\r"
14
+ close $fd
15
+ return [exec fossil test-http <q.txt]
16
+}
17
+set todo {}
18
+foreach url {
19
+ /home
20
+ /timeline
21
+ /brlist
22
+ /taglist
23
+ /reportlist
24
+ /setup
25
+ /dir
26
+ /wcontent
27
+ /attachlist
28
+ /taglist
29
+ /test_env
30
+ /stat
31
+ /rcvfromlist
32
+ /urllist
33
+ /modreq
34
+ /info/d5c4
35
+ /test-all-help
36
+ /leaves
37
+ /timeline?a=1970-01-01
38
+} {
39
+ set seen($url) 1
40
+ set pending($url) 1
41
+}
42
+set round 1
43
+set limit 25000
44
+set npending [llength [array names pending]]
45
+proc get_pending {} {
46
+ global pending npending round next
47
+ if {$npending==0} {
48
+ incr round
49
+ array set pending [array get next]
50
+ set npending [llength [array names pending]]
51
+ unset -nocomplain next
52
+ }
53
+ set res [lindex [array names pending] [expr {int(rand()*$npending)}]]
54
+ unset pending($res)
55
+ incr npending -1
56
+ return $res
57
+}
58
+for {set i 0} {$i<$limit} {incr i} {
59
+ set url [get_pending]
60
+ puts -nonewline "($round/[expr {$i+1}]) $url "
61
+ flush stdout
62
+ set tm [time {set x [run_query $url]}]
63
+ set ms [lindex $tm 0]
64
+ puts [format {%.3fs} [expr {$ms/1000000.0}]]
65
+ flush stdout
66
+ if {[string length $x]>1000000} {
67
+ set x [string range $x 0 1000000]
68
+ }
69
+ set k 0
70
+ while {[regexp {<[aA] .*?href="(/[a-z].*?)".*?>(.*)$} $x all url tail]} {
71
+ # if {$npending>2*($limit - $i)} break
72
+ incr k
73
+ if {$k>100} break
74
+ set u2 [string map {&lt; < &gt; > &quot; \" &amp; &} $url]
75
+ if {![info exists seen($u2)]} {
76
+ set next($u2) 1
77
+ set seen($u2) 1
78
+
--- a/test/many-www.tcl
+++ b/test/many-www.tcl
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/test/many-www.tcl
+++ b/test/many-www.tcl
@@ -0,0 +1,78 @@
1 #!/usr/bin/tclsh
2 #
3 # Run this script from within any open Fossil checkout. Example:
4 #
5 # tclsh many-www.tcl | tee out.txt
6 #
7 # About 10,000 different web page requests will be made. Each is timed
8 # and the time shown on output. Use this script to search for segfault problems
9 # or to look for pages that need optimization.
10 #
11 proc run_query {url} {
12 set fd [open q.txt w]
13 puts $fd "GET $url HTTP/1.0\r\n\r"
14 close $fd
15 return [exec fossil test-http <q.txt]
16 }
17 set todo {}
18 foreach url {
19 /home
20 /timeline
21 /brlist
22 /taglist
23 /reportlist
24 /setup
25 /dir
26 /wcontent
27 /attachlist
28 /taglist
29 /test_env
30 /stat
31 /rcvfromlist
32 /urllist
33 /modreq
34 /info/d5c4
35 /test-all-help
36 /leaves
37 /timeline?a=1970-01-01
38 } {
39 set seen($url) 1
40 set pending($url) 1
41 }
42 set round 1
43 set limit 25000
44 set npending [llength [array names pending]]
45 proc get_pending {} {
46 global pending npending round next
47 if {$npending==0} {
48 incr round
49 array set pending [array get next]
50 set npending [llength [array names pending]]
51 unset -nocomplain next
52 }
53 set res [lindex [array names pending] [expr {int(rand()*$npending)}]]
54 unset pending($res)
55 incr npending -1
56 return $res
57 }
58 for {set i 0} {$i<$limit} {incr i} {
59 set url [get_pending]
60 puts -nonewline "($round/[expr {$i+1}]) $url "
61 flush stdout
62 set tm [time {set x [run_query $url]}]
63 set ms [lindex $tm 0]
64 puts [format {%.3fs} [expr {$ms/1000000.0}]]
65 flush stdout
66 if {[string length $x]>1000000} {
67 set x [string range $x 0 1000000]
68 }
69 set k 0
70 while {[regexp {<[aA] .*?href="(/[a-z].*?)".*?>(.*)$} $x all url tail]} {
71 # if {$npending>2*($limit - $i)} break
72 incr k
73 if {$k>100} break
74 set u2 [string map {&lt; < &gt; > &quot; \" &amp; &} $url]
75 if {![info exists seen($u2)]} {
76 set next($u2) 1
77 set seen($u2) 1
78
--- a/test/valgrind-www.tcl
+++ b/test/valgrind-www.tcl
@@ -0,0 +1,49 @@
1
+#!/usr/bin/tclsh
2
+#
3
+# Run this script in an open Fossil checkout at the top-level with a
4
+# fresh build of Fossil itself. This script will run fossil on hundreds
5
+# of different web-pages looking for memory allocation problems using y allocation problems using
6
+# valgrind. Valgrind output appears on stderr. Suggested test scenario:
7
+#
8
+# make
9
+# tclsh valgrind-www.tcl 2>&1 | tee valgrind-out.txt
10
+#
11
+# Then examine the valgrind-out.txt file for issues.
12
+#
13
+proc run_query {url} {
14
+ set fd [open q.txt w]
15
+ puts $fd "GET $url HTTreturn [url HTTP/1.0\r\n\r"
16
+ c]/fossil test-http <q.txt 2>@ stderr} msg
17
+ return $msg
18
+}
19
+set todo {}
20
+foreach url {
21
+ /home
22
+ /timeline
23
+ /brlist
24
+ /taglist
25
+ /reportlist
26
+ /setup
27
+ /dir
28
+ /wcontent
29
+} {
30
+ set seen($url) 1
31
+ set pending($url) 1
32
+}
33
+set limit 1000
34
+set npending [llength [array names pending]]
35
+proc get_pending {} {
36
+ global pending npending
37
+ set res [lindex [array names pending] [expr {int(rand()*$npending)}]]
38
+ unset pending($res)
39
+ incr npending -1
40
+ return $res
41
+}
42
+for {set i 0} {$npending>0 && $i<$limit} {incr i} {
43
+ set url [get_pending]
44
+ puts "====== ([expr {$i+1}]) $url ======"
45
+ set x [run_query $url]
46
+ while {[regexp {<[aA] .*?href="(/[a-z].*?)".*?>(.*)$} $x all url tail]} {
47
+ set u2 [string map {&lt; < &gt; > &quot; \" &amp; &} $url]
48
+ if {![info exists seen($u2)]} {
49
+ set pend
--- a/test/valgrind-www.tcl
+++ b/test/valgrind-www.tcl
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/test/valgrind-www.tcl
+++ b/test/valgrind-www.tcl
@@ -0,0 +1,49 @@
1 #!/usr/bin/tclsh
2 #
3 # Run this script in an open Fossil checkout at the top-level with a
4 # fresh build of Fossil itself. This script will run fossil on hundreds
5 # of different web-pages looking for memory allocation problems using y allocation problems using
6 # valgrind. Valgrind output appears on stderr. Suggested test scenario:
7 #
8 # make
9 # tclsh valgrind-www.tcl 2>&1 | tee valgrind-out.txt
10 #
11 # Then examine the valgrind-out.txt file for issues.
12 #
13 proc run_query {url} {
14 set fd [open q.txt w]
15 puts $fd "GET $url HTTreturn [url HTTP/1.0\r\n\r"
16 c]/fossil test-http <q.txt 2>@ stderr} msg
17 return $msg
18 }
19 set todo {}
20 foreach url {
21 /home
22 /timeline
23 /brlist
24 /taglist
25 /reportlist
26 /setup
27 /dir
28 /wcontent
29 } {
30 set seen($url) 1
31 set pending($url) 1
32 }
33 set limit 1000
34 set npending [llength [array names pending]]
35 proc get_pending {} {
36 global pending npending
37 set res [lindex [array names pending] [expr {int(rand()*$npending)}]]
38 unset pending($res)
39 incr npending -1
40 return $res
41 }
42 for {set i 0} {$npending>0 && $i<$limit} {incr i} {
43 set url [get_pending]
44 puts "====== ([expr {$i+1}]) $url ======"
45 set x [run_query $url]
46 while {[regexp {<[aA] .*?href="(/[a-z].*?)".*?>(.*)$} $x all url tail]} {
47 set u2 [string map {&lt; < &gt; > &quot; \" &amp; &} $url]
48 if {![info exists seen($u2)]} {
49 set pend

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button